summaryrefslogtreecommitdiffstats
path: root/contrib/gdb
diff options
context:
space:
mode:
authorpst <pst@FreeBSD.org>1996-11-03 17:03:03 +0000
committerpst <pst@FreeBSD.org>1996-11-03 17:03:03 +0000
commitd3bb4185d06450111ecae1c72f0d3af1b46cc4e1 (patch)
treef411e0f5e1dc1102690bca9349ce094176769e2c /contrib/gdb
downloadFreeBSD-src-d3bb4185d06450111ecae1c72f0d3af1b46cc4e1.zip
FreeBSD-src-d3bb4185d06450111ecae1c72f0d3af1b46cc4e1.tar.gz
Import GDB in its full glory (all 25mb). We'll put it on a diet once it's
fully registered. (This is the second try, the first import ignored .info files but not .info-* files, for some reason. I'm going to make this consistent.) Reviewed by: core Approved for: 2.2
Diffstat (limited to 'contrib/gdb')
-rw-r--r--contrib/gdb/COPYING339
-rw-r--r--contrib/gdb/COPYING.LIB481
-rw-r--r--contrib/gdb/Makefile.in1366
-rw-r--r--contrib/gdb/README50
-rw-r--r--contrib/gdb/bfd/COPYING339
-rw-r--r--contrib/gdb/bfd/Makefile.in1090
-rw-r--r--contrib/gdb/bfd/PORTING83
-rw-r--r--contrib/gdb/bfd/TODO25
-rw-r--r--contrib/gdb/bfd/VERSION1
-rw-r--r--contrib/gdb/bfd/acconfig.h19
-rw-r--r--contrib/gdb/bfd/aclocal.m443
-rw-r--r--contrib/gdb/bfd/aix386-core.c285
-rw-r--r--contrib/gdb/bfd/aout-adobe.c528
-rw-r--r--contrib/gdb/bfd/aout-arm.c548
-rw-r--r--contrib/gdb/bfd/aout-encap.c236
-rw-r--r--contrib/gdb/bfd/aout-ns32k.c399
-rw-r--r--contrib/gdb/bfd/aout-target.h607
-rw-r--r--contrib/gdb/bfd/aout0.c32
-rw-r--r--contrib/gdb/bfd/aout32.c23
-rw-r--r--contrib/gdb/bfd/aout64.c31
-rw-r--r--contrib/gdb/bfd/aoutf1.h788
-rw-r--r--contrib/gdb/bfd/aoutx.h5525
-rw-r--r--contrib/gdb/bfd/archive.c2094
-rw-r--r--contrib/gdb/bfd/archures.c720
-rw-r--r--contrib/gdb/bfd/bfd-in.h668
-rw-r--r--contrib/gdb/bfd/bfd-in2.h2479
-rw-r--r--contrib/gdb/bfd/bfd.c1144
-rw-r--r--contrib/gdb/bfd/binary.c348
-rw-r--r--contrib/gdb/bfd/bout.c1471
-rw-r--r--contrib/gdb/bfd/cache.c347
-rw-r--r--contrib/gdb/bfd/cf-i386lynx.c31
-rw-r--r--contrib/gdb/bfd/cf-m68klynx.c223
-rw-r--r--contrib/gdb/bfd/cf-sparclynx.c28
-rw-r--r--contrib/gdb/bfd/cisco-core.c313
-rw-r--r--contrib/gdb/bfd/coff-a29k.c641
-rw-r--r--contrib/gdb/bfd/coff-alpha.c2390
-rw-r--r--contrib/gdb/bfd/coff-apollo.c162
-rw-r--r--contrib/gdb/bfd/coff-arm.c537
-rw-r--r--contrib/gdb/bfd/coff-aux.c332
-rw-r--r--contrib/gdb/bfd/coff-go32.c25
-rw-r--r--contrib/gdb/bfd/coff-h8300.c650
-rw-r--r--contrib/gdb/bfd/coff-h8500.c355
-rw-r--r--contrib/gdb/bfd/coff-i386.c493
-rw-r--r--contrib/gdb/bfd/coff-i860.c423
-rw-r--r--contrib/gdb/bfd/coff-i960.c683
-rw-r--r--contrib/gdb/bfd/coff-m68k.c203
-rw-r--r--contrib/gdb/bfd/coff-m88k.c311
-rw-r--r--contrib/gdb/bfd/coff-mips.c2596
-rw-r--r--contrib/gdb/bfd/coff-pmac.c27
-rw-r--r--contrib/gdb/bfd/coff-ppc.c3255
-rw-r--r--contrib/gdb/bfd/coff-rs6000.c1403
-rw-r--r--contrib/gdb/bfd/coff-sh.c1525
-rw-r--r--contrib/gdb/bfd/coff-sparc.c278
-rw-r--r--contrib/gdb/bfd/coff-u68k.c35
-rw-r--r--contrib/gdb/bfd/coff-w65.c446
-rw-r--r--contrib/gdb/bfd/coff-we32k.c110
-rw-r--r--contrib/gdb/bfd/coff-z8k.c281
-rw-r--r--contrib/gdb/bfd/coffcode.h3612
-rw-r--r--contrib/gdb/bfd/coffgen.c2121
-rw-r--r--contrib/gdb/bfd/cofflink.c2327
-rw-r--r--contrib/gdb/bfd/coffswap.h807
-rw-r--r--contrib/gdb/bfd/config.bfd491
-rw-r--r--contrib/gdb/bfd/config.in67
-rw-r--r--contrib/gdb/bfd/configure2439
-rw-r--r--contrib/gdb/bfd/configure.bat18
-rw-r--r--contrib/gdb/bfd/configure.host128
-rw-r--r--contrib/gdb/bfd/configure.in577
-rw-r--r--contrib/gdb/bfd/corefile.c106
-rw-r--r--contrib/gdb/bfd/cpu-a29k.c39
-rw-r--r--contrib/gdb/bfd/cpu-alpha.c38
-rw-r--r--contrib/gdb/bfd/cpu-arm.c39
-rw-r--r--contrib/gdb/bfd/cpu-h8300.c246
-rw-r--r--contrib/gdb/bfd/cpu-h8500.c199
-rw-r--r--contrib/gdb/bfd/cpu-hppa.c54
-rw-r--r--contrib/gdb/bfd/cpu-i386.c38
-rw-r--r--contrib/gdb/bfd/cpu-i860.c40
-rw-r--r--contrib/gdb/bfd/cpu-i960.c162
-rw-r--r--contrib/gdb/bfd/cpu-m68k.c42
-rw-r--r--contrib/gdb/bfd/cpu-m88k.c42
-rw-r--r--contrib/gdb/bfd/cpu-mips.c85
-rw-r--r--contrib/gdb/bfd/cpu-ns32k.c868
-rw-r--r--contrib/gdb/bfd/cpu-powerpc.c124
-rw-r--r--contrib/gdb/bfd/cpu-rs6000.c70
-rw-r--r--contrib/gdb/bfd/cpu-sh.c68
-rw-r--r--contrib/gdb/bfd/cpu-sparc.c111
-rw-r--r--contrib/gdb/bfd/cpu-vax.c39
-rw-r--r--contrib/gdb/bfd/cpu-w65.c54
-rw-r--r--contrib/gdb/bfd/cpu-we32k.c39
-rw-r--r--contrib/gdb/bfd/cpu-z8k.c198
-rw-r--r--contrib/gdb/bfd/demo64.c24
-rw-r--r--contrib/gdb/bfd/dep-in.sed24
-rw-r--r--contrib/gdb/bfd/doc/ChangeLog268
-rw-r--r--contrib/gdb/bfd/doc/Makefile.in311
-rw-r--r--contrib/gdb/bfd/doc/bfd.texinfo348
-rw-r--r--contrib/gdb/bfd/doc/bfdsumm.texi148
-rw-r--r--contrib/gdb/bfd/doc/chew.c1551
-rw-r--r--contrib/gdb/bfd/doc/doc.str158
-rw-r--r--contrib/gdb/bfd/doc/proto.str135
-rw-r--r--contrib/gdb/bfd/ecoff.c4740
-rw-r--r--contrib/gdb/bfd/ecofflink.c2452
-rw-r--r--contrib/gdb/bfd/ecoffswap.h853
-rw-r--r--contrib/gdb/bfd/elf-bfd.h858
-rw-r--r--contrib/gdb/bfd/elf.c3318
-rw-r--r--contrib/gdb/bfd/elf32-gen.c37
-rw-r--r--contrib/gdb/bfd/elf32-hppa.c2984
-rw-r--r--contrib/gdb/bfd/elf32-hppa.h152
-rw-r--r--contrib/gdb/bfd/elf32-i386.c1546
-rw-r--r--contrib/gdb/bfd/elf32-i860.c33
-rw-r--r--contrib/gdb/bfd/elf32-m68k.c1600
-rw-r--r--contrib/gdb/bfd/elf32-m88k.c35
-rw-r--r--contrib/gdb/bfd/elf32-mips.c5867
-rw-r--r--contrib/gdb/bfd/elf32-ppc.c2554
-rw-r--r--contrib/gdb/bfd/elf32-sparc.c1795
-rw-r--r--contrib/gdb/bfd/elf32.c23
-rw-r--r--contrib/gdb/bfd/elf64-gen.c37
-rw-r--r--contrib/gdb/bfd/elf64-sparc.c421
-rw-r--r--contrib/gdb/bfd/elf64.c22
-rw-r--r--contrib/gdb/bfd/elfcode.h1406
-rw-r--r--contrib/gdb/bfd/elfcore.h475
-rw-r--r--contrib/gdb/bfd/elflink.c372
-rw-r--r--contrib/gdb/bfd/elflink.h3424
-rw-r--r--contrib/gdb/bfd/elfxx-target.h450
-rw-r--r--contrib/gdb/bfd/filemode.c193
-rw-r--r--contrib/gdb/bfd/format.c319
-rw-r--r--contrib/gdb/bfd/freebsd.h109
-rw-r--r--contrib/gdb/bfd/gen-aout.c101
-rw-r--r--contrib/gdb/bfd/genlink.h106
-rw-r--r--contrib/gdb/bfd/hash.c734
-rw-r--r--contrib/gdb/bfd/host-aout.c83
-rw-r--r--contrib/gdb/bfd/hosts/alphalinux.h6
-rw-r--r--contrib/gdb/bfd/hosts/decstation.h17
-rw-r--r--contrib/gdb/bfd/hosts/delta68.h18
-rw-r--r--contrib/gdb/bfd/hosts/dpx2.h8
-rw-r--r--contrib/gdb/bfd/hosts/hp300bsd.h13
-rw-r--r--contrib/gdb/bfd/hosts/i386bsd.h25
-rw-r--r--contrib/gdb/bfd/hosts/i386linux.h8
-rw-r--r--contrib/gdb/bfd/hosts/i386mach3.h25
-rw-r--r--contrib/gdb/bfd/hosts/i386sco.h19
-rw-r--r--contrib/gdb/bfd/hosts/i860mach3.h27
-rw-r--r--contrib/gdb/bfd/hosts/m68kaux.h16
-rw-r--r--contrib/gdb/bfd/hosts/m68klinux.h6
-rw-r--r--contrib/gdb/bfd/hosts/m88kmach3.h11
-rw-r--r--contrib/gdb/bfd/hosts/mipsbsd.h12
-rw-r--r--contrib/gdb/bfd/hosts/mipsmach3.h10
-rw-r--r--contrib/gdb/bfd/hosts/news-mips.h12
-rw-r--r--contrib/gdb/bfd/hosts/news.h9
-rw-r--r--contrib/gdb/bfd/hosts/pc532mach.h24
-rw-r--r--contrib/gdb/bfd/hosts/riscos.h10
-rw-r--r--contrib/gdb/bfd/hosts/symmetry.h20
-rw-r--r--contrib/gdb/bfd/hosts/tahoe.h12
-rw-r--r--contrib/gdb/bfd/hosts/vaxbsd.h19
-rw-r--r--contrib/gdb/bfd/hosts/vaxult.h8
-rw-r--r--contrib/gdb/bfd/hosts/vaxult2.h8
-rw-r--r--contrib/gdb/bfd/hp300bsd.c38
-rw-r--r--contrib/gdb/bfd/hp300hpux.c865
-rw-r--r--contrib/gdb/bfd/hppa_stubs.h23
-rw-r--r--contrib/gdb/bfd/hppabsd-core.c305
-rw-r--r--contrib/gdb/bfd/hpux-core.c270
-rw-r--r--contrib/gdb/bfd/i386aout.c68
-rw-r--r--contrib/gdb/bfd/i386bsd.c46
-rw-r--r--contrib/gdb/bfd/i386dynix.c80
-rw-r--r--contrib/gdb/bfd/i386freebsd.c33
-rw-r--r--contrib/gdb/bfd/i386linux.c762
-rw-r--r--contrib/gdb/bfd/i386lynx.c563
-rw-r--r--contrib/gdb/bfd/i386mach3.c65
-rw-r--r--contrib/gdb/bfd/i386msdos.c243
-rw-r--r--contrib/gdb/bfd/i386netbsd.c33
-rw-r--r--contrib/gdb/bfd/i386os9k.c370
-rw-r--r--contrib/gdb/bfd/ieee.c3738
-rw-r--r--contrib/gdb/bfd/ihex.c1005
-rw-r--r--contrib/gdb/bfd/init.c50
-rw-r--r--contrib/gdb/bfd/irix-core.c263
-rw-r--r--contrib/gdb/bfd/libaout.h608
-rw-r--r--contrib/gdb/bfd/libbfd-in.h503
-rw-r--r--contrib/gdb/bfd/libbfd.c1197
-rw-r--r--contrib/gdb/bfd/libbfd.h735
-rw-r--r--contrib/gdb/bfd/libcoff-in.h482
-rw-r--r--contrib/gdb/bfd/libcoff.h823
-rw-r--r--contrib/gdb/bfd/libecoff.h352
-rw-r--r--contrib/gdb/bfd/libhppa.h549
-rw-r--r--contrib/gdb/bfd/libieee.h135
-rw-r--r--contrib/gdb/bfd/libnlm.h264
-rw-r--r--contrib/gdb/bfd/liboasys.h83
-rw-r--r--contrib/gdb/bfd/linker.c2781
-rw-r--r--contrib/gdb/bfd/lynx-core.c233
-rw-r--r--contrib/gdb/bfd/m68k4knetbsd.c35
-rw-r--r--contrib/gdb/bfd/m68klinux.c767
-rw-r--r--contrib/gdb/bfd/m68klynx.c54
-rw-r--r--contrib/gdb/bfd/m68knetbsd.c35
-rw-r--r--contrib/gdb/bfd/m88kmach3.c38
-rw-r--r--contrib/gdb/bfd/makefile.dos49
-rw-r--r--contrib/gdb/bfd/mipsbsd.c467
-rw-r--r--contrib/gdb/bfd/mpw-config.in73
-rw-r--r--contrib/gdb/bfd/mpw-make.sed70
-rw-r--r--contrib/gdb/bfd/netbsd-core.c310
-rw-r--r--contrib/gdb/bfd/netbsd.h108
-rw-r--r--contrib/gdb/bfd/newsos3.c40
-rw-r--r--contrib/gdb/bfd/nlm-target.h228
-rw-r--r--contrib/gdb/bfd/nlm.c55
-rw-r--r--contrib/gdb/bfd/nlm32-alpha.c892
-rw-r--r--contrib/gdb/bfd/nlm32-i386.c451
-rw-r--r--contrib/gdb/bfd/nlm32-ppc.c1045
-rw-r--r--contrib/gdb/bfd/nlm32-sparc.c440
-rw-r--r--contrib/gdb/bfd/nlm32.c21
-rw-r--r--contrib/gdb/bfd/nlm64.c21
-rw-r--r--contrib/gdb/bfd/nlmcode.h2057
-rw-r--r--contrib/gdb/bfd/nlmswap.h157
-rw-r--r--contrib/gdb/bfd/ns32knetbsd.c53
-rw-r--r--contrib/gdb/bfd/oasys.c1533
-rw-r--r--contrib/gdb/bfd/opncls.c604
-rw-r--r--contrib/gdb/bfd/osf-core.c256
-rw-r--r--contrib/gdb/bfd/pc532-mach.c121
-rw-r--r--contrib/gdb/bfd/pe-arm.c32
-rw-r--r--contrib/gdb/bfd/pe-i386.c30
-rw-r--r--contrib/gdb/bfd/pe-ppc.c39
-rw-r--r--contrib/gdb/bfd/pei-arm.c33
-rw-r--r--contrib/gdb/bfd/pei-i386.c33
-rw-r--r--contrib/gdb/bfd/pei-ppc.c44
-rw-r--r--contrib/gdb/bfd/peicode.h1861
-rw-r--r--contrib/gdb/bfd/ptrace-core.c233
-rw-r--r--contrib/gdb/bfd/reloc.c2391
-rw-r--r--contrib/gdb/bfd/reloc16.c289
-rw-r--r--contrib/gdb/bfd/riscix.c644
-rw-r--r--contrib/gdb/bfd/rs6000-core.c396
-rw-r--r--contrib/gdb/bfd/section.c976
-rw-r--r--contrib/gdb/bfd/som.c5999
-rw-r--r--contrib/gdb/bfd/som.h224
-rw-r--r--contrib/gdb/bfd/sparclynx.c265
-rw-r--r--contrib/gdb/bfd/sparcnetbsd.c33
-rw-r--r--contrib/gdb/bfd/srec.c1324
-rw-r--r--contrib/gdb/bfd/stab-syms.c57
-rw-r--r--contrib/gdb/bfd/sunos.c2767
-rw-r--r--contrib/gdb/bfd/syms.c1084
-rw-r--r--contrib/gdb/bfd/sysdep.h114
-rw-r--r--contrib/gdb/bfd/targets.c886
-rw-r--r--contrib/gdb/bfd/tekhex.c1031
-rw-r--r--contrib/gdb/bfd/trad-core.c316
-rw-r--r--contrib/gdb/bfd/versados.c906
-rw-r--r--contrib/gdb/bfd/xcofflink.c5798
-rw-r--r--contrib/gdb/gdb/.gdbinit16
-rw-r--r--contrib/gdb/gdb/COPYING339
-rw-r--r--contrib/gdb/gdb/ChangeLog1415
-rw-r--r--contrib/gdb/gdb/ChangeLog-937597
-rw-r--r--contrib/gdb/gdb/ChangeLog-945705
-rw-r--r--contrib/gdb/gdb/ChangeLog-954882
-rw-r--r--contrib/gdb/gdb/Makefile.in1534
-rw-r--r--contrib/gdb/gdb/NEWS1338
-rw-r--r--contrib/gdb/gdb/README583
-rw-r--r--contrib/gdb/gdb/TODO468
-rw-r--r--contrib/gdb/gdb/acconfig.h9
-rw-r--r--contrib/gdb/gdb/aclocal.m4605
-rw-r--r--contrib/gdb/gdb/alpha-nat.c243
-rw-r--r--contrib/gdb/gdb/alpha-tdep.c1274
-rw-r--r--contrib/gdb/gdb/annotate.c540
-rw-r--r--contrib/gdb/gdb/annotate.h95
-rw-r--r--contrib/gdb/gdb/arm-convert.s16
-rw-r--r--contrib/gdb/gdb/arm-tdep.c826
-rw-r--r--contrib/gdb/gdb/arm-xdep.c276
-rw-r--r--contrib/gdb/gdb/bcache.c189
-rw-r--r--contrib/gdb/gdb/bcache.h72
-rw-r--r--contrib/gdb/gdb/blockframe.c854
-rw-r--r--contrib/gdb/gdb/breakpoint.c4117
-rw-r--r--contrib/gdb/gdb/breakpoint.h424
-rw-r--r--contrib/gdb/gdb/buildsym.c1039
-rw-r--r--contrib/gdb/gdb/buildsym.h259
-rw-r--r--contrib/gdb/gdb/c-exp.tab.c2705
-rw-r--r--contrib/gdb/gdb/c-exp.y1641
-rw-r--r--contrib/gdb/gdb/c-lang.c478
-rw-r--r--contrib/gdb/gdb/c-lang.h84
-rw-r--r--contrib/gdb/gdb/c-typeprint.c831
-rw-r--r--contrib/gdb/gdb/c-valprint.c469
-rw-r--r--contrib/gdb/gdb/call-cmds.h28
-rw-r--r--contrib/gdb/gdb/callback.c349
-rw-r--r--contrib/gdb/gdb/callback.h41
-rw-r--r--contrib/gdb/gdb/ch-exp.c2090
-rw-r--r--contrib/gdb/gdb/ch-lang.c653
-rw-r--r--contrib/gdb/gdb/ch-lang.h39
-rw-r--r--contrib/gdb/gdb/ch-typeprint.c346
-rw-r--r--contrib/gdb/gdb/ch-valprint.c664
-rw-r--r--contrib/gdb/gdb/coff-solib.c131
-rw-r--r--contrib/gdb/gdb/coff-solib.h60
-rw-r--r--contrib/gdb/gdb/coffread.c2164
-rw-r--r--contrib/gdb/gdb/command.c1466
-rw-r--r--contrib/gdb/gdb/command.h259
-rw-r--r--contrib/gdb/gdb/complaints.c171
-rw-r--r--contrib/gdb/gdb/complaints.h46
-rw-r--r--contrib/gdb/gdb/config.in90
-rw-r--r--contrib/gdb/gdb/config/i386/cygwin32.mh6
-rw-r--r--contrib/gdb/gdb/config/i386/cygwin32.mt6
-rw-r--r--contrib/gdb/gdb/config/i386/fbsd.mh5
-rw-r--r--contrib/gdb/gdb/config/i386/fbsd.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/gdbserve.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/go32.mh9
-rw-r--r--contrib/gdb/gdb/config/i386/i386aix.mh12
-rw-r--r--contrib/gdb/gdb/config/i386/i386aix.mt7
-rw-r--r--contrib/gdb/gdb/config/i386/i386aout.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386bsd.mh7
-rw-r--r--contrib/gdb/gdb/config/i386/i386bsd.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386dgux.mh14
-rw-r--r--contrib/gdb/gdb/config/i386/i386gnu.mh36
-rw-r--r--contrib/gdb/gdb/config/i386/i386gnu.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386lynx.mh11
-rw-r--r--contrib/gdb/gdb/config/i386/i386lynx.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386m3.mh11
-rw-r--r--contrib/gdb/gdb/config/i386/i386m3.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386mach.mh10
-rw-r--r--contrib/gdb/gdb/config/i386/i386mk.mh8
-rw-r--r--contrib/gdb/gdb/config/i386/i386mk.mt6
-rw-r--r--contrib/gdb/gdb/config/i386/i386nw.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386os9k.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386sco.mh13
-rw-r--r--contrib/gdb/gdb/config/i386/i386sco4.mh12
-rw-r--r--contrib/gdb/gdb/config/i386/i386sco5.mh17
-rw-r--r--contrib/gdb/gdb/config/i386/i386sol2.mh12
-rw-r--r--contrib/gdb/gdb/config/i386/i386sol2.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386v.mh8
-rw-r--r--contrib/gdb/gdb/config/i386/i386v.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/i386v32.mh9
-rw-r--r--contrib/gdb/gdb/config/i386/i386v4.mh14
-rw-r--r--contrib/gdb/gdb/config/i386/i386v4.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/linux.mh13
-rw-r--r--contrib/gdb/gdb/config/i386/linux.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/nbsd.mh5
-rw-r--r--contrib/gdb/gdb/config/i386/nbsd.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/ncr3000.mh21
-rw-r--r--contrib/gdb/gdb/config/i386/ncr3000.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/nm-fbsd.h101
-rw-r--r--contrib/gdb/gdb/config/i386/nm-gnu.h22
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386aix.h42
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386bsd.h39
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386lynx.h25
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386mach.h26
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386sco.h47
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386sco4.h32
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386sco5.h41
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386v.h38
-rw-r--r--contrib/gdb/gdb/config/i386/nm-i386v4.h21
-rw-r--r--contrib/gdb/gdb/config/i386/nm-linux.h82
-rw-r--r--contrib/gdb/gdb/config/i386/nm-m3.h22
-rw-r--r--contrib/gdb/gdb/config/i386/nm-nbsd.h34
-rw-r--r--contrib/gdb/gdb/config/i386/nm-ptx4.h62
-rw-r--r--contrib/gdb/gdb/config/i386/nm-sun386.h27
-rw-r--r--contrib/gdb/gdb/config/i386/nm-symmetry.h47
-rw-r--r--contrib/gdb/gdb/config/i386/ptx.mh7
-rw-r--r--contrib/gdb/gdb/config/i386/ptx.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/ptx4.mh7
-rw-r--r--contrib/gdb/gdb/config/i386/ptx4.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/sun386.mh5
-rw-r--r--contrib/gdb/gdb/config/i386/sun386.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/symmetry.mh5
-rw-r--r--contrib/gdb/gdb/config/i386/symmetry.mt3
-rw-r--r--contrib/gdb/gdb/config/i386/tm-cygwin32.h125
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386.h309
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386aix.h67
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386bsd.h43
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386gnu.h48
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386lynx.h33
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386m3.h60
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386mk.h25
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386nw.h49
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386os9k.h63
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386v.h161
-rw-r--r--contrib/gdb/gdb/config/i386/tm-i386v4.h78
-rw-r--r--contrib/gdb/gdb/config/i386/tm-linux.h35
-rw-r--r--contrib/gdb/gdb/config/i386/tm-nbsd.h42
-rw-r--r--contrib/gdb/gdb/config/i386/tm-ptx.h232
-rw-r--r--contrib/gdb/gdb/config/i386/tm-ptx4.h24
-rw-r--r--contrib/gdb/gdb/config/i386/tm-sun386.h205
-rw-r--r--contrib/gdb/gdb/config/i386/tm-symmetry.h321
-rw-r--r--contrib/gdb/gdb/config/i386/xm-cygwin32.h41
-rw-r--r--contrib/gdb/gdb/config/i386/xm-go32.h31
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386aix.h33
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386bsd.h23
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386gnu.h23
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386lynx.h24
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386m3.h38
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386mach.h35
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386mk.h25
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386sco.h42
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386v.h45
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386v32.h24
-rw-r--r--contrib/gdb/gdb/config/i386/xm-i386v4.h37
-rw-r--r--contrib/gdb/gdb/config/i386/xm-linux.h46
-rw-r--r--contrib/gdb/gdb/config/i386/xm-nbsd.h21
-rw-r--r--contrib/gdb/gdb/config/i386/xm-ptx.h41
-rw-r--r--contrib/gdb/gdb/config/i386/xm-ptx4.h25
-rw-r--r--contrib/gdb/gdb/config/i386/xm-sun386.h20
-rw-r--r--contrib/gdb/gdb/config/i386/xm-symmetry.h28
-rw-r--r--contrib/gdb/gdb/config/nm-empty.h2
-rw-r--r--contrib/gdb/gdb/config/nm-gnu.h46
-rw-r--r--contrib/gdb/gdb/config/nm-lynx.h83
-rw-r--r--contrib/gdb/gdb/config/nm-m3.h123
-rw-r--r--contrib/gdb/gdb/config/nm-nbsd.h86
-rw-r--r--contrib/gdb/gdb/config/nm-sysv4.h34
-rw-r--r--contrib/gdb/gdb/config/tm-lynx.h34
-rw-r--r--contrib/gdb/gdb/config/tm-nbsd.h19
-rw-r--r--contrib/gdb/gdb/config/tm-sunos.h31
-rw-r--r--contrib/gdb/gdb/config/tm-sysv4.h45
-rw-r--r--contrib/gdb/gdb/config/xm-aix4.h96
-rw-r--r--contrib/gdb/gdb/config/xm-lynx.h22
-rw-r--r--contrib/gdb/gdb/config/xm-mpw.h81
-rw-r--r--contrib/gdb/gdb/config/xm-nbsd.h37
-rw-r--r--contrib/gdb/gdb/config/xm-sysv4.h36
-rw-r--r--contrib/gdb/gdb/configure2745
-rw-r--r--contrib/gdb/gdb/configure.in615
-rw-r--r--contrib/gdb/gdb/copying.awk77
-rw-r--r--contrib/gdb/gdb/copying.c327
-rw-r--r--contrib/gdb/gdb/core-aout.c143
-rw-r--r--contrib/gdb/gdb/core-regset.c130
-rw-r--r--contrib/gdb/gdb/core-sol2.c133
-rw-r--r--contrib/gdb/gdb/corefile.c339
-rw-r--r--contrib/gdb/gdb/corelow.c419
-rw-r--r--contrib/gdb/gdb/cp-valprint.c600
-rw-r--r--contrib/gdb/gdb/cpu32bug-rom.c171
-rw-r--r--contrib/gdb/gdb/cxux-nat.c523
-rw-r--r--contrib/gdb/gdb/dbxread.c2556
-rw-r--r--contrib/gdb/gdb/dcache.c564
-rw-r--r--contrib/gdb/gdb/dcache.h50
-rw-r--r--contrib/gdb/gdb/defs.h973
-rw-r--r--contrib/gdb/gdb/demangle.c206
-rw-r--r--contrib/gdb/gdb/doc/ChangeLog1206
-rw-r--r--contrib/gdb/gdb/doc/GDBvn.texi1
-rw-r--r--contrib/gdb/gdb/doc/Makefile.in331
-rw-r--r--contrib/gdb/gdb/doc/a4rc.sed11
-rw-r--r--contrib/gdb/gdb/doc/all-cfg.texi120
-rw-r--r--contrib/gdb/gdb/doc/annotate.texi717
-rw-r--r--contrib/gdb/gdb/doc/configure.in7
-rw-r--r--contrib/gdb/gdb/doc/gdb.texinfo9282
-rw-r--r--contrib/gdb/gdb/doc/gdbint.texinfo2543
-rw-r--r--contrib/gdb/gdb/doc/h8-cfg.texi47
-rw-r--r--contrib/gdb/gdb/doc/libgdb.texinfo878
-rw-r--r--contrib/gdb/gdb/doc/lpsrc.sed13
-rw-r--r--contrib/gdb/gdb/doc/psrc.sed13
-rw-r--r--contrib/gdb/gdb/doc/refcard.dvibin0 -> 21732 bytes
-rw-r--r--contrib/gdb/gdb/doc/refcard.tex645
-rw-r--r--contrib/gdb/gdb/doc/remote.texi1531
-rw-r--r--contrib/gdb/gdb/doc/stabs.texinfo4004
-rw-r--r--contrib/gdb/gdb/dwarfread.c3883
-rw-r--r--contrib/gdb/gdb/elfread.c826
-rw-r--r--contrib/gdb/gdb/environ.c194
-rw-r--r--contrib/gdb/gdb/environ.h58
-rw-r--r--contrib/gdb/gdb/eval.c1780
-rw-r--r--contrib/gdb/gdb/exc_request.defs51
-rw-r--r--contrib/gdb/gdb/exec.c677
-rw-r--r--contrib/gdb/gdb/expprint.c634
-rw-r--r--contrib/gdb/gdb/expression.h386
-rw-r--r--contrib/gdb/gdb/f-exp.tab.c2089
-rw-r--r--contrib/gdb/gdb/f-exp.y1170
-rw-r--r--contrib/gdb/gdb/f-lang.c944
-rw-r--r--contrib/gdb/gdb/f-lang.h94
-rw-r--r--contrib/gdb/gdb/f-typeprint.c454
-rw-r--r--contrib/gdb/gdb/f-valprint.c748
-rw-r--r--contrib/gdb/gdb/findvar.c1444
-rw-r--r--contrib/gdb/gdb/fork-child.c309
-rw-r--r--contrib/gdb/gdb/frame.h196
-rw-r--r--contrib/gdb/gdb/gdb-stabs.h78
-rw-r--r--contrib/gdb/gdb/gdb.1371
-rw-r--r--contrib/gdb/gdb/gdb.gdb35
-rw-r--r--contrib/gdb/gdb/gdb_stat.h68
-rw-r--r--contrib/gdb/gdb/gdb_string.h48
-rw-r--r--contrib/gdb/gdb/gdba.el2607
-rw-r--r--contrib/gdb/gdb/gdbcmd.h106
-rw-r--r--contrib/gdb/gdb/gdbcore.h155
-rw-r--r--contrib/gdb/gdb/gdbserver/Makefile.in245
-rw-r--r--contrib/gdb/gdb/gdbserver/README127
-rw-r--r--contrib/gdb/gdb/gdbserver/configure.in335
-rw-r--r--contrib/gdb/gdb/gdbserver/gdbreplay.c319
-rw-r--r--contrib/gdb/gdb/gdbserver/gdbserver.1103
-rw-r--r--contrib/gdb/gdb/gdbserver/low-hppabsd.c379
-rw-r--r--contrib/gdb/gdb/gdbserver/low-linux.c420
-rw-r--r--contrib/gdb/gdb/gdbserver/low-lynx.c746
-rw-r--r--contrib/gdb/gdb/gdbserver/low-sparc.c334
-rw-r--r--contrib/gdb/gdb/gdbserver/low-sun3.c313
-rw-r--r--contrib/gdb/gdb/gdbserver/remote-utils.c479
-rw-r--r--contrib/gdb/gdb/gdbserver/server.c249
-rw-r--r--contrib/gdb/gdb/gdbserver/server.h50
-rw-r--r--contrib/gdb/gdb/gdbserver/utils.c113
-rw-r--r--contrib/gdb/gdb/gdbtypes.c1683
-rw-r--r--contrib/gdb/gdb/gdbtypes.h789
-rw-r--r--contrib/gdb/gdb/gnu-nat.c2814
-rw-r--r--contrib/gdb/gdb/gnu-nat.h91
-rw-r--r--contrib/gdb/gdb/gnu-regex.c1759
-rw-r--r--contrib/gdb/gdb/gnu-regex.h181
-rw-r--r--contrib/gdb/gdb/go32-xdep.c35
-rw-r--r--contrib/gdb/gdb/i386-stub.c915
-rw-r--r--contrib/gdb/gdb/i386-tdep.c688
-rw-r--r--contrib/gdb/gdb/i386aix-nat.c360
-rw-r--r--contrib/gdb/gdb/i386b-nat.c284
-rw-r--r--contrib/gdb/gdb/i386gnu-nat.c348
-rw-r--r--contrib/gdb/gdb/i386ly-tdep.c42
-rw-r--r--contrib/gdb/gdb/i386m3-nat.c421
-rw-r--r--contrib/gdb/gdb/i386mach-nat.c163
-rw-r--r--contrib/gdb/gdb/i386v-nat.c371
-rw-r--r--contrib/gdb/gdb/i386v4-nat.c163
-rw-r--r--contrib/gdb/gdb/i387-tdep.c107
-rw-r--r--contrib/gdb/gdb/infcmd.c1375
-rw-r--r--contrib/gdb/gdb/inferior.h382
-rw-r--r--contrib/gdb/gdb/inflow.c718
-rw-r--r--contrib/gdb/gdb/infptrace.c534
-rw-r--r--contrib/gdb/gdb/infrun.c2224
-rw-r--r--contrib/gdb/gdb/inftarg.c390
-rw-r--r--contrib/gdb/gdb/irix4-nat.c192
-rw-r--r--contrib/gdb/gdb/irix5-nat.c1067
-rw-r--r--contrib/gdb/gdb/isi-xdep.c20
-rw-r--r--contrib/gdb/gdb/kdb-start.c35
-rw-r--r--contrib/gdb/gdb/language.c1400
-rw-r--r--contrib/gdb/gdb/language.h431
-rw-r--r--contrib/gdb/gdb/lynx-nat.c838
-rw-r--r--contrib/gdb/gdb/m2-exp.tab.c2095
-rw-r--r--contrib/gdb/gdb/m2-exp.y1094
-rw-r--r--contrib/gdb/gdb/m2-lang.c465
-rw-r--r--contrib/gdb/gdb/m2-lang.h31
-rw-r--r--contrib/gdb/gdb/m2-typeprint.c49
-rw-r--r--contrib/gdb/gdb/m2-valprint.c45
-rw-r--r--contrib/gdb/gdb/m3-nat.c4640
-rw-r--r--contrib/gdb/gdb/m68k-stub.c1014
-rw-r--r--contrib/gdb/gdb/m68k-tdep.c514
-rw-r--r--contrib/gdb/gdb/m68knbsd-nat.c86
-rw-r--r--contrib/gdb/gdb/m88k-nat.c285
-rw-r--r--contrib/gdb/gdb/m88k-tdep.c616
-rw-r--r--contrib/gdb/gdb/main.c627
-rw-r--r--contrib/gdb/gdb/maint.c370
-rw-r--r--contrib/gdb/gdb/mdebugread.c4368
-rw-r--r--contrib/gdb/gdb/mem-break.c121
-rw-r--r--contrib/gdb/gdb/minimon.h562
-rw-r--r--contrib/gdb/gdb/minsyms.c855
-rw-r--r--contrib/gdb/gdb/mipsread.c477
-rw-r--r--contrib/gdb/gdb/mon960-rom.c270
-rw-r--r--contrib/gdb/gdb/monitor.c1541
-rw-r--r--contrib/gdb/gdb/monitor.h177
-rw-r--r--contrib/gdb/gdb/mpw-config.in82
-rw-r--r--contrib/gdb/gdb/mpw-make.sed167
-rw-r--r--contrib/gdb/gdb/msg.defs1
-rw-r--r--contrib/gdb/gdb/msg_reply.defs1
-rw-r--r--contrib/gdb/gdb/news-xdep.c65
-rw-r--r--contrib/gdb/gdb/nindy-tdep.c73
-rw-r--r--contrib/gdb/gdb/nlm/Makefile.in173
-rw-r--r--contrib/gdb/gdb/nlm/configure864
-rw-r--r--contrib/gdb/gdb/nlm/configure.in55
-rw-r--r--contrib/gdb/gdb/nlm/gdbserve.c1056
-rw-r--r--contrib/gdb/gdb/nlm/gdbserve.def42
-rw-r--r--contrib/gdb/gdb/nlm/i386.c108
-rw-r--r--contrib/gdb/gdb/nlm/i386.h13
-rw-r--r--contrib/gdb/gdb/nlm/ppc.c257
-rw-r--r--contrib/gdb/gdb/nlm/ppc.h165
-rw-r--r--contrib/gdb/gdb/nlm/prelude.c67
-rw-r--r--contrib/gdb/gdb/nlmread.c308
-rw-r--r--contrib/gdb/gdb/notify.defs1
-rw-r--r--contrib/gdb/gdb/ns32k-tdep.c27
-rw-r--r--contrib/gdb/gdb/ns32km3-nat.c181
-rw-r--r--contrib/gdb/gdb/objfiles.c911
-rw-r--r--contrib/gdb/gdb/objfiles.h502
-rw-r--r--contrib/gdb/gdb/op50-rom.c146
-rw-r--r--contrib/gdb/gdb/os9kread.c1659
-rw-r--r--contrib/gdb/gdb/osfsolib.c955
-rw-r--r--contrib/gdb/gdb/parse.c1013
-rw-r--r--contrib/gdb/gdb/parser-defs.h191
-rw-r--r--contrib/gdb/gdb/partial-stab.h774
-rw-r--r--contrib/gdb/gdb/ppcbug-rom.c233
-rw-r--r--contrib/gdb/gdb/printcmd.c2248
-rw-r--r--contrib/gdb/gdb/process_reply.defs1
-rw-r--r--contrib/gdb/gdb/procfs.c3815
-rw-r--r--contrib/gdb/gdb/ptx4-nat.c209
-rw-r--r--contrib/gdb/gdb/pyr-tdep.c452
-rw-r--r--contrib/gdb/gdb/pyr-xdep.c370
-rw-r--r--contrib/gdb/gdb/remote-adapt.c1359
-rw-r--r--contrib/gdb/gdb/remote-array.c1465
-rw-r--r--contrib/gdb/gdb/remote-bug.c1053
-rw-r--r--contrib/gdb/gdb/remote-e7000.c2066
-rw-r--r--contrib/gdb/gdb/remote-eb.c1009
-rw-r--r--contrib/gdb/gdb/remote-es.c2152
-rw-r--r--contrib/gdb/gdb/remote-est.c174
-rw-r--r--contrib/gdb/gdb/remote-hms.c1463
-rw-r--r--contrib/gdb/gdb/remote-mips.c2997
-rw-r--r--contrib/gdb/gdb/remote-mm.c1627
-rw-r--r--contrib/gdb/gdb/remote-nindy.c820
-rw-r--r--contrib/gdb/gdb/remote-nrom.c332
-rw-r--r--contrib/gdb/gdb/remote-os9k.c1230
-rw-r--r--contrib/gdb/gdb/remote-pa.c1540
-rw-r--r--contrib/gdb/gdb/remote-rdp.c1247
-rw-r--r--contrib/gdb/gdb/remote-sim.c468
-rw-r--r--contrib/gdb/gdb/remote-sim.h142
-rw-r--r--contrib/gdb/gdb/remote-st.c847
-rw-r--r--contrib/gdb/gdb/remote-udi.c1689
-rw-r--r--contrib/gdb/gdb/remote-utils.c646
-rw-r--r--contrib/gdb/gdb/remote-utils.h142
-rw-r--r--contrib/gdb/gdb/remote-vx.c1488
-rw-r--r--contrib/gdb/gdb/remote-vx29k.c188
-rw-r--r--contrib/gdb/gdb/remote-vx68.c158
-rw-r--r--contrib/gdb/gdb/remote-vx960.c163
-rw-r--r--contrib/gdb/gdb/remote-vxmips.c201
-rw-r--r--contrib/gdb/gdb/remote-vxsparc.c196
-rw-r--r--contrib/gdb/gdb/remote.c1839
-rw-r--r--contrib/gdb/gdb/reply_mig_hack.awk123
-rw-r--r--contrib/gdb/gdb/saber.suppress451
-rw-r--r--contrib/gdb/gdb/scm-exp.c414
-rw-r--r--contrib/gdb/gdb/scm-lang.c268
-rw-r--r--contrib/gdb/gdb/scm-lang.h50
-rw-r--r--contrib/gdb/gdb/scm-tags.h385
-rw-r--r--contrib/gdb/gdb/scm-valprint.c404
-rw-r--r--contrib/gdb/gdb/ser-e7kpc.c420
-rw-r--r--contrib/gdb/gdb/ser-go32.c957
-rw-r--r--contrib/gdb/gdb/ser-mac.c361
-rw-r--r--contrib/gdb/gdb/ser-tcp.c343
-rw-r--r--contrib/gdb/gdb/ser-unix.c730
-rw-r--r--contrib/gdb/gdb/serial.c484
-rw-r--r--contrib/gdb/gdb/serial.h182
-rw-r--r--contrib/gdb/gdb/signals.h27
-rw-r--r--contrib/gdb/gdb/solib.c1714
-rw-r--r--contrib/gdb/gdb/solib.h60
-rw-r--r--contrib/gdb/gdb/somread.c470
-rw-r--r--contrib/gdb/gdb/somsolib.c820
-rw-r--r--contrib/gdb/gdb/somsolib.h51
-rw-r--r--contrib/gdb/gdb/source.c1506
-rw-r--r--contrib/gdb/gdb/srec.h35
-rw-r--r--contrib/gdb/gdb/stabsread.c4017
-rw-r--r--contrib/gdb/gdb/stabsread.h225
-rw-r--r--contrib/gdb/gdb/stack.c1502
-rw-r--r--contrib/gdb/gdb/standalone.c593
-rw-r--r--contrib/gdb/gdb/stop-gdb.c110
-rw-r--r--contrib/gdb/gdb/stuff.c174
-rw-r--r--contrib/gdb/gdb/symfile.c1774
-rw-r--r--contrib/gdb/gdb/symfile.h211
-rw-r--r--contrib/gdb/gdb/symm-nat.c846
-rw-r--r--contrib/gdb/gdb/symm-tdep.c93
-rw-r--r--contrib/gdb/gdb/symmisc.c1053
-rw-r--r--contrib/gdb/gdb/symtab.c3346
-rw-r--r--contrib/gdb/gdb/symtab.h1222
-rw-r--r--contrib/gdb/gdb/target.c1858
-rw-r--r--contrib/gdb/gdb/target.h765
-rw-r--r--contrib/gdb/gdb/terminal.h89
-rw-r--r--contrib/gdb/gdb/thread.c476
-rw-r--r--contrib/gdb/gdb/thread.h46
-rw-r--r--contrib/gdb/gdb/top.c3557
-rw-r--r--contrib/gdb/gdb/top.h48
-rw-r--r--contrib/gdb/gdb/typeprint.c302
-rw-r--r--contrib/gdb/gdb/typeprint.h21
-rw-r--r--contrib/gdb/gdb/umax-xdep.c133
-rw-r--r--contrib/gdb/gdb/utils.c1948
-rw-r--r--contrib/gdb/gdb/valarith.c1213
-rw-r--r--contrib/gdb/gdb/valops.c2346
-rw-r--r--contrib/gdb/gdb/valprint.c1015
-rw-r--r--contrib/gdb/gdb/valprint.h44
-rw-r--r--contrib/gdb/gdb/value.h491
-rw-r--r--contrib/gdb/gdb/values.c1418
-rw-r--r--contrib/gdb/gdb/xcoffread.c2767
-rw-r--r--contrib/gdb/gdb/xcoffsolib.c211
-rw-r--r--contrib/gdb/gdb/xcoffsolib.h56
-rw-r--r--contrib/gdb/gdb/xmodem.c284
-rw-r--r--contrib/gdb/gdb/xmodem.h29
-rw-r--r--contrib/gdb/include/COPYING339
-rw-r--r--contrib/gdb/include/ChangeLog973
-rw-r--r--contrib/gdb/include/ansidecl.h141
-rw-r--r--contrib/gdb/include/aout/ChangeLog174
-rw-r--r--contrib/gdb/include/aout/adobe.h297
-rw-r--r--contrib/gdb/include/aout/aout64.h475
-rw-r--r--contrib/gdb/include/aout/ar.h36
-rw-r--r--contrib/gdb/include/aout/dynix3.h71
-rw-r--r--contrib/gdb/include/aout/encap.h135
-rw-r--r--contrib/gdb/include/aout/host.h22
-rw-r--r--contrib/gdb/include/aout/hp.h82
-rw-r--r--contrib/gdb/include/aout/hp300hpux.h119
-rw-r--r--contrib/gdb/include/aout/hppa.h7
-rw-r--r--contrib/gdb/include/aout/ranlib.h62
-rw-r--r--contrib/gdb/include/aout/reloc.h66
-rw-r--r--contrib/gdb/include/aout/stab.def264
-rw-r--r--contrib/gdb/include/aout/stab_gnu.h37
-rw-r--r--contrib/gdb/include/aout/sun4.h219
-rw-r--r--contrib/gdb/include/bfdlink.h452
-rw-r--r--contrib/gdb/include/bout.h182
-rw-r--r--contrib/gdb/include/coff/ChangeLog622
-rw-r--r--contrib/gdb/include/coff/a29k.h305
-rw-r--r--contrib/gdb/include/coff/alpha.h342
-rw-r--r--contrib/gdb/include/coff/apollo.h248
-rw-r--r--contrib/gdb/include/coff/arm.h215
-rw-r--r--contrib/gdb/include/coff/aux-coff.h31
-rw-r--r--contrib/gdb/include/coff/ecoff.h408
-rw-r--r--contrib/gdb/include/coff/h8300.h203
-rw-r--r--contrib/gdb/include/coff/h8500.h201
-rw-r--r--contrib/gdb/include/coff/i386.h224
-rw-r--r--contrib/gdb/include/coff/i860.h204
-rw-r--r--contrib/gdb/include/coff/i960.h251
-rw-r--r--contrib/gdb/include/coff/internal.h648
-rw-r--r--contrib/gdb/include/coff/m68k.h221
-rw-r--r--contrib/gdb/include/coff/m88k.h218
-rw-r--r--contrib/gdb/include/coff/mips.h368
-rw-r--r--contrib/gdb/include/coff/pe.h161
-rw-r--r--contrib/gdb/include/coff/powerpc.h196
-rw-r--r--contrib/gdb/include/coff/rs6000.h242
-rw-r--r--contrib/gdb/include/coff/sh.h253
-rw-r--r--contrib/gdb/include/coff/sparc.h209
-rw-r--r--contrib/gdb/include/coff/sym.h484
-rw-r--r--contrib/gdb/include/coff/symconst.h177
-rw-r--r--contrib/gdb/include/coff/w65.h201
-rw-r--r--contrib/gdb/include/coff/we32k.h206
-rw-r--r--contrib/gdb/include/coff/z8k.h201
-rw-r--r--contrib/gdb/include/demangle.h108
-rw-r--r--contrib/gdb/include/dis-asm.h175
-rw-r--r--contrib/gdb/include/elf/ChangeLog195
-rw-r--r--contrib/gdb/include/elf/common.h239
-rw-r--r--contrib/gdb/include/elf/dwarf.h319
-rw-r--r--contrib/gdb/include/elf/external.h195
-rw-r--r--contrib/gdb/include/elf/hppa.h94
-rw-r--r--contrib/gdb/include/elf/internal.h207
-rw-r--r--contrib/gdb/include/elf/mips.h298
-rw-r--r--contrib/gdb/include/elf/ppc.h54
-rw-r--r--contrib/gdb/include/elf/sparc.h73
-rw-r--r--contrib/gdb/include/floatformat.h88
-rw-r--r--contrib/gdb/include/fopen-bin.h27
-rw-r--r--contrib/gdb/include/fopen-same.h27
-rw-r--r--contrib/gdb/include/gdbm.h91
-rw-r--r--contrib/gdb/include/getopt.h129
-rw-r--r--contrib/gdb/include/hp-symtab.h983
-rw-r--r--contrib/gdb/include/ieee.h139
-rw-r--r--contrib/gdb/include/libiberty.h133
-rw-r--r--contrib/gdb/include/mpw/ChangeLog61
-rw-r--r--contrib/gdb/include/mpw/README1
-rw-r--r--contrib/gdb/include/mpw/dir.h23
-rw-r--r--contrib/gdb/include/mpw/dirent.h31
-rw-r--r--contrib/gdb/include/mpw/fcntl.h124
-rw-r--r--contrib/gdb/include/mpw/grp.h10
-rw-r--r--contrib/gdb/include/mpw/mpw.h130
-rw-r--r--contrib/gdb/include/mpw/pwd.h15
-rw-r--r--contrib/gdb/include/mpw/spin.h64
-rw-r--r--contrib/gdb/include/mpw/stat.h75
-rw-r--r--contrib/gdb/include/mpw/sys/file.h1
-rw-r--r--contrib/gdb/include/mpw/sys/param.h1
-rw-r--r--contrib/gdb/include/mpw/sys/resource.h9
-rw-r--r--contrib/gdb/include/mpw/sys/stat.h44
-rw-r--r--contrib/gdb/include/mpw/sys/time.h13
-rw-r--r--contrib/gdb/include/mpw/sys/types.h15
-rw-r--r--contrib/gdb/include/mpw/utime.h7
-rw-r--r--contrib/gdb/include/mpw/varargs.h9
-rw-r--r--contrib/gdb/include/nlm/ChangeLog83
-rw-r--r--contrib/gdb/include/nlm/alpha-ext.h166
-rw-r--r--contrib/gdb/include/nlm/common.h124
-rw-r--r--contrib/gdb/include/nlm/external.h174
-rw-r--r--contrib/gdb/include/nlm/i386-ext.h116
-rw-r--r--contrib/gdb/include/nlm/internal.h309
-rw-r--r--contrib/gdb/include/nlm/ppc-ext.h163
-rw-r--r--contrib/gdb/include/nlm/sparc32-ext.h120
-rw-r--r--contrib/gdb/include/oasys.h152
-rw-r--r--contrib/gdb/include/obstack.h518
-rw-r--r--contrib/gdb/include/opcode/ChangeLog812
-rw-r--r--contrib/gdb/include/opcode/a29k.h285
-rw-r--r--contrib/gdb/include/opcode/arm.h294
-rw-r--r--contrib/gdb/include/opcode/convex.h1711
-rw-r--r--contrib/gdb/include/opcode/h8300.h550
-rw-r--r--contrib/gdb/include/opcode/hppa.h471
-rw-r--r--contrib/gdb/include/opcode/i386.h898
-rw-r--r--contrib/gdb/include/opcode/i860.h491
-rw-r--r--contrib/gdb/include/opcode/i960.h509
-rw-r--r--contrib/gdb/include/opcode/m68k.h297
-rw-r--r--contrib/gdb/include/opcode/m88k.h923
-rw-r--r--contrib/gdb/include/opcode/mips.h481
-rw-r--r--contrib/gdb/include/opcode/np1.h422
-rw-r--r--contrib/gdb/include/opcode/ns32k.h491
-rw-r--r--contrib/gdb/include/opcode/pn.h282
-rw-r--r--contrib/gdb/include/opcode/ppc.h248
-rw-r--r--contrib/gdb/include/opcode/pyr.h287
-rw-r--r--contrib/gdb/include/opcode/rs6k.h254
-rw-r--r--contrib/gdb/include/opcode/sparc.h220
-rw-r--r--contrib/gdb/include/opcode/tahoe.h213
-rw-r--r--contrib/gdb/include/opcode/vax.h382
-rw-r--r--contrib/gdb/include/os9k.h169
-rw-r--r--contrib/gdb/include/progress.h37
-rw-r--r--contrib/gdb/include/wait.h63
-rw-r--r--contrib/gdb/libiberty/COPYING.LIB481
-rw-r--r--contrib/gdb/libiberty/ChangeLog1815
-rw-r--r--contrib/gdb/libiberty/Makefile.in321
-rw-r--r--contrib/gdb/libiberty/README129
-rw-r--r--contrib/gdb/libiberty/alloca-botch.h5
-rw-r--r--contrib/gdb/libiberty/alloca-norm.h16
-rw-r--r--contrib/gdb/libiberty/alloca.c475
-rw-r--r--contrib/gdb/libiberty/argv.c328
-rw-r--r--contrib/gdb/libiberty/atexit.c14
-rw-r--r--contrib/gdb/libiberty/basename.c43
-rw-r--r--contrib/gdb/libiberty/bcmp.c49
-rw-r--r--contrib/gdb/libiberty/bcopy.c35
-rw-r--r--contrib/gdb/libiberty/bzero.c31
-rw-r--r--contrib/gdb/libiberty/clock.c73
-rw-r--r--contrib/gdb/libiberty/concat.c167
-rw-r--r--contrib/gdb/libiberty/config.table63
-rw-r--r--contrib/gdb/libiberty/config/mh-a68bsd2
-rw-r--r--contrib/gdb/libiberty/config/mh-aix10
-rw-r--r--contrib/gdb/libiberty/config/mh-apollo682
-rw-r--r--contrib/gdb/libiberty/config/mh-cxux73
-rw-r--r--contrib/gdb/libiberty/config/mh-go324
-rw-r--r--contrib/gdb/libiberty/config/mh-hpbsd2
-rw-r--r--contrib/gdb/libiberty/config/mh-irix44
-rw-r--r--contrib/gdb/libiberty/config/mh-lynxos1
-rw-r--r--contrib/gdb/libiberty/config/mh-ncr300019
-rw-r--r--contrib/gdb/libiberty/config/mh-riscix6
-rw-r--r--contrib/gdb/libiberty/config/mh-sysv1
-rw-r--r--contrib/gdb/libiberty/config/mh-sysv43
-rw-r--r--contrib/gdb/libiberty/config/mt-sunos42
-rw-r--r--contrib/gdb/libiberty/config/mt-vxworks527
-rw-r--r--contrib/gdb/libiberty/configure.bat15
-rw-r--r--contrib/gdb/libiberty/configure.in77
-rw-r--r--contrib/gdb/libiberty/copysign.c140
-rw-r--r--contrib/gdb/libiberty/cplus-dem.c3019
-rw-r--r--contrib/gdb/libiberty/dummy.c49
-rw-r--r--contrib/gdb/libiberty/fdmatch.c73
-rw-r--r--contrib/gdb/libiberty/floatformat.c385
-rw-r--r--contrib/gdb/libiberty/functions.def67
-rw-r--r--contrib/gdb/libiberty/getcwd.c52
-rw-r--r--contrib/gdb/libiberty/getopt.c757
-rw-r--r--contrib/gdb/libiberty/getopt1.c190
-rw-r--r--contrib/gdb/libiberty/getpagesize.c89
-rw-r--r--contrib/gdb/libiberty/getruntime.c82
-rw-r--r--contrib/gdb/libiberty/hex.c33
-rw-r--r--contrib/gdb/libiberty/index.c11
-rw-r--r--contrib/gdb/libiberty/insque.c50
-rw-r--r--contrib/gdb/libiberty/makefile.dos29
-rw-r--r--contrib/gdb/libiberty/memchr.c60
-rw-r--r--contrib/gdb/libiberty/memcmp.c38
-rw-r--r--contrib/gdb/libiberty/memcpy.c28
-rw-r--r--contrib/gdb/libiberty/memmove.c18
-rw-r--r--contrib/gdb/libiberty/memset.c19
-rw-r--r--contrib/gdb/libiberty/mpw-config.in9
-rw-r--r--contrib/gdb/libiberty/mpw-make.sed49
-rw-r--r--contrib/gdb/libiberty/mpw.c1010
-rw-r--r--contrib/gdb/libiberty/msdos.c15
-rw-r--r--contrib/gdb/libiberty/obstack.c507
-rw-r--r--contrib/gdb/libiberty/random.c373
-rw-r--r--contrib/gdb/libiberty/rename.c22
-rw-r--r--contrib/gdb/libiberty/rindex.c11
-rw-r--r--contrib/gdb/libiberty/sigsetmask.c30
-rw-r--r--contrib/gdb/libiberty/spaces.c71
-rw-r--r--contrib/gdb/libiberty/strcasecmp.c81
-rw-r--r--contrib/gdb/libiberty/strchr.c34
-rw-r--r--contrib/gdb/libiberty/strdup.c10
-rw-r--r--contrib/gdb/libiberty/strerror.c829
-rw-r--r--contrib/gdb/libiberty/strncasecmp.c82
-rw-r--r--contrib/gdb/libiberty/strrchr.c34
-rw-r--r--contrib/gdb/libiberty/strsignal.c627
-rw-r--r--contrib/gdb/libiberty/strstr.c51
-rw-r--r--contrib/gdb/libiberty/strtod.c122
-rw-r--r--contrib/gdb/libiberty/strtol.c143
-rw-r--r--contrib/gdb/libiberty/strtoul.c110
-rw-r--r--contrib/gdb/libiberty/tmpnam.c39
-rw-r--r--contrib/gdb/libiberty/vasprintf.c165
-rw-r--r--contrib/gdb/libiberty/vfork.c8
-rw-r--r--contrib/gdb/libiberty/vfprintf.c13
-rw-r--r--contrib/gdb/libiberty/vmsbuild.com142
-rw-r--r--contrib/gdb/libiberty/vprintf.c11
-rw-r--r--contrib/gdb/libiberty/vsprintf.c55
-rw-r--r--contrib/gdb/libiberty/waitpid.c11
-rw-r--r--contrib/gdb/libiberty/xatexit.c82
-rw-r--r--contrib/gdb/libiberty/xexit.c36
-rw-r--r--contrib/gdb/libiberty/xmalloc.c106
-rw-r--r--contrib/gdb/libiberty/xstrdup.c17
-rw-r--r--contrib/gdb/libiberty/xstrerror.c54
-rw-r--r--contrib/gdb/opcodes/ChangeLog1772
-rw-r--r--contrib/gdb/opcodes/Makefile.in305
-rw-r--r--contrib/gdb/opcodes/dis-buf.c70
-rw-r--r--contrib/gdb/opcodes/disassemble.c166
-rw-r--r--contrib/gdb/opcodes/i386-dis.c2031
-rw-r--r--contrib/gdb/opcodes/sysdep.h38
-rw-r--r--contrib/gdb/readline/doc/ChangeLog12
-rw-r--r--contrib/gdb/readline/doc/Makefile.in94
-rw-r--r--contrib/gdb/readline/doc/configure.in8
-rw-r--r--contrib/gdb/readline/doc/hist.texinfo106
-rw-r--r--contrib/gdb/readline/doc/hstech.texinfo311
-rw-r--r--contrib/gdb/readline/doc/hsuser.texinfo153
-rw-r--r--contrib/gdb/readline/doc/inc-hist.texi159
-rw-r--r--contrib/gdb/readline/doc/rlman.texinfo103
-rw-r--r--contrib/gdb/readline/doc/rltech.texinfo1012
-rw-r--r--contrib/gdb/readline/doc/rluser.texinfo566
869 files changed, 441264 insertions, 0 deletions
diff --git a/contrib/gdb/COPYING b/contrib/gdb/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/contrib/gdb/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/contrib/gdb/COPYING.LIB b/contrib/gdb/COPYING.LIB
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/contrib/gdb/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library 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 Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/contrib/gdb/Makefile.in b/contrib/gdb/Makefile.in
new file mode 100644
index 0000000..60a8025
--- /dev/null
+++ b/contrib/gdb/Makefile.in
@@ -0,0 +1,1366 @@
+#
+# Makefile for directory with subdirs to build.
+# Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+srcdir = .
+
+prefix = /usr/local
+
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+tooldir = $(exec_prefix)/$(target)
+
+program_transform_name =
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+docdir = $(datadir)/doc
+GDB_NLM_DEPS =
+
+SHELL = /bin/sh
+
+INSTALL = $${srcroot}/install.sh -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL) -m 644
+INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
+
+INSTALL_DOSREL = install-dosrel-fake
+
+AS = as
+AR = ar
+AR_FLAGS = rc
+CC = cc
+
+# Special variables passed down in EXTRA_GCC_FLAGS. They are defined
+# here so that they can be overridden by Makefile fragments.
+HOST_CC = $(CC_FOR_BUILD)
+HOST_PREFIX =
+HOST_PREFIX_1 = loser-
+
+# We don't specify -g -O because many compilers don't support -g -O,
+# and/or -O is broken in and of itself.
+CFLAGS = -g
+LIBCFLAGS = $(CFLAGS)
+CFLAGS_FOR_TARGET = $(CFLAGS)
+LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARGET)
+PICFLAG =
+PICFLAG_FOR_TARGET =
+
+CXX = gcc
+
+# Use -O2 to stress test the compiler.
+CXXFLAGS = -g -O2
+LIBCXXFLAGS = $(CXXFLAGS) -fno-implicit-templates
+CXXFLAGS_FOR_TARGET = $(CXXFLAGS)
+LIBCXXFLAGS_FOR_TARGET = $(CXXFLAGS_FOR_TARGET) -fno-implicit-templates
+
+RANLIB = ranlib
+
+DLLTOOL = dlltool
+
+NM = nm
+# Not plain GZIP, since gzip looks there for extra command-line options.
+GZIPPROG = gzip
+
+# These values are substituted by configure.
+DEFAULT_YACC = yacc
+DEFAULT_LEX = lex
+
+BISON = bison -y
+LEX = `if [ -f $$r/flex/flex ] ; \
+ then echo $$r/flex/flex ; \
+ else echo ${DEFAULT_LEX} ; fi`
+
+M4 = `if [ -f $$r/m4/m4 ] ; \
+ then echo $$r/m4/m4 ; \
+ else echo m4 ; fi`
+
+MAKEINFO = `if [ -f $$r/texinfo/makeinfo/makeinfo ] ; \
+ then echo $$r/texinfo/makeinfo/makeinfo ; \
+ else echo makeinfo ; fi`
+
+# This just becomes part of the MAKEINFO definition passed down to
+# sub-makes. It lets flags be given on the command line while still
+# using the makeinfo from the object tree.
+MAKEINFOFLAGS =
+
+EXPECT = `if [ -f $$r/expect/expect ] ; \
+ then echo $$r/expect/expect ; \
+ else echo expect ; fi`
+
+RUNTEST = `if [ -f $${srcroot}/dejagnu/runtest ] ; \
+ then echo $${srcroot}/dejagnu/runtest ; \
+ else echo runtest ; fi`
+
+
+# compilers to use to create programs which must be run in the build
+# environment.
+CC_FOR_BUILD = $(CC)
+CXX_FOR_BUILD = $(CXX)
+
+SUBDIRS = "this is set via configure, don't edit this"
+OTHERS =
+
+# This is set by the configure script to the list of directories which
+# should be built using the target tools.
+TARGET_CONFIGDIRS = libiberty libgloss newlib libio librx libstdc++ libg++ winsup
+
+# Target libraries are put under this directory:
+TARGET_SUBDIR = . # Changed by configure to $(target_alias) if cross.
+
+# This is set by the configure script to the arguments passed to configure.
+CONFIG_ARGUMENTS =
+
+# This is set by configure to REALLY_SET_LIB_PATH if --enable-shared
+# was used.
+SET_LIB_PATH =
+
+# This is the name of the environment variable used for the path to
+# the libraries. This may be changed by configure.in.
+RPATH_ENVVAR = LD_LIBRARY_PATH
+
+# configure.in sets SET_LIB_PATH to this if --enable-shared was used.
+REALLY_SET_LIB_PATH = \
+ $(RPATH_ENVVAR)=$$r/bfd:$$r/opcodes:$$$(RPATH_ENVVAR); \
+ export $(RPATH_ENVVAR);
+
+ALL = all.normal
+INSTALL_TARGET = install-dirs \
+ $(INSTALL_MODULES) \
+ $(INSTALL_TARGET_MODULES) \
+ $(INSTALL_X11_MODULES) \
+ install-gcc \
+ $(INSTALL_DOSREL)
+
+
+CC_FOR_TARGET = ` \
+ if [ -f $$r/gcc/Makefile ] ; then \
+ if [ -f $$r/$(TARGET_SUBDIR)/newlib/Makefile ] ; then \
+ echo $$r/gcc/xgcc -B$$r/gcc/ -idirafter $$r/$(TARGET_SUBDIR)/newlib/targ-include -idirafter $${srcroot}/newlib/libc/include -nostdinc; \
+ else \
+ echo $$r/gcc/xgcc -B$$r/gcc/; \
+ fi; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CC); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e 's/x/x/' $$t; \
+ fi; \
+ fi`
+
+
+CXX_FOR_TARGET = ` \
+ if [ -f $$r/gcc/Makefile ] ; then \
+ if [ -f $$r/$(TARGET_SUBDIR)/newlib/Makefile ] ; then \
+ echo $$r/gcc/xgcc -B$$r/gcc/ -idirafter $$r/$(TARGET_SUBDIR)/newlib/targ-include -idirafter $${srcroot}/newlib/libc/include -nostdinc; \
+ else \
+ echo $$r/gcc/xgcc -B$$r/gcc/; \
+ fi; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CXX); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e 's/x/x/' $$t; \
+ fi; \
+ fi`
+
+AS_FOR_TARGET = ` \
+ if [ -f $$r/gas/as.new ] ; then \
+ echo $$r/gas/as.new ; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(AS); \
+ else \
+ t='$(program_transform_name)'; echo as | sed -e 's/x/x/' $$t ; \
+ fi; \
+ fi`
+
+LD_FOR_TARGET = ` \
+ if [ -f $$r/ld/ld.new ] ; then \
+ echo $$r/ld/ld.new ; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(LD); \
+ else \
+ t='$(program_transform_name)'; echo ld | sed -e 's/x/x/' $$t ; \
+ fi; \
+ fi`
+
+DLLTOOL_FOR_TARGET = ` \
+ if [ -f $$r/binutils/dlltool ] ; then \
+ echo $$r/binutils/dlltool ; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(DLLTOOL); \
+ else \
+ t='$(program_transform_name)'; echo dlltool | sed -e 's/x/x/' $$t ; \
+ fi; \
+ fi`
+
+AR_FOR_TARGET = ` \
+ if [ -f $$r/binutils/ar ] ; then \
+ echo $$r/binutils/ar ; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(AR); \
+ else \
+ t='$(program_transform_name)'; echo ar | sed -e 's/x/x/' $$t ; \
+ fi; \
+ fi`
+
+RANLIB_FOR_TARGET = ` \
+ if [ -f $$r/binutils/ranlib ] ; then \
+ echo $$r/binutils/ranlib ; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(RANLIB); \
+ else \
+ t='$(program_transform_name)'; echo ranlib | sed -e 's/x/x/' $$t ; \
+ fi; \
+ fi`
+
+NM_FOR_TARGET = ` \
+ if [ -f $$r/binutils/nm.new ] ; then \
+ echo $$r/binutils/nm.new ; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(NM); \
+ else \
+ t='$(program_transform_name)'; echo nm | sed -e 's/x/x/' $$t ; \
+ fi; \
+ fi`
+
+#### host and target specific makefile fragments come in here.
+###
+
+# Flags to pass down to all sub-makes.
+# Please keep these in alphabetical order.
+BASE_FLAGS_TO_PASS = \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "AR_FOR_TARGET=$(AR_FOR_TARGET)" \
+ "AS_FOR_TARGET=$(AS_FOR_TARGET)" \
+ "BISON=$(BISON)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CC_FOR_TARGET=$(CC_FOR_TARGET)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CFLAGS_FOR_TARGET=$(CFLAGS_FOR_TARGET)" \
+ "CXX_FOR_BUILD=$(CXX_FOR_BUILD)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "CXXFLAGS_FOR_TARGET=$(CXXFLAGS_FOR_TARGET)" \
+ "CXX_FOR_TARGET=$(CXX_FOR_TARGET)" \
+ "DLLTOOL_FOR_TARGET=$(DLLTOOL_FOR_TARGET)" \
+ "GCC_FOR_TARGET=$(CC_FOR_TARGET)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_XFORM=$(INSTALL_XFORM)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LEX=$(LEX)" \
+ "LD_FOR_TARGET=$(LD_FOR_TARGET)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "LIBCFLAGS_FOR_TARGET=$(LIBCFLAGS_FOR_TARGET)" \
+ "LIBCXXFLAGS=$(LIBCXXFLAGS)" \
+ "LIBCXXFLAGS_FOR_TARGET=$(LIBCXXFLAGS_FOR_TARGET)" \
+ "M4=$(M4)" \
+ "MAKEINFO=$(MAKEINFO) $(MAKEINFOFLAGS)" \
+ "NM_FOR_TARGET=$(NM_FOR_TARGET)" \
+ "PICFLAG=$(PICFLAG)" \
+ "PICFLAG_FOR_TARGET=$(PICFLAG_FOR_TARGET)" \
+ "RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET)" \
+ "SHELL=$(SHELL)" \
+ "EXPECT=$(EXPECT)" \
+ "RUNTEST=$(RUNTEST)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)" \
+ "YACC=$(BISON)" \
+ "exec_prefix=$(exec_prefix)" \
+ "prefix=$(prefix)" \
+ "tooldir=$(tooldir)"
+
+# Flags to pass down to most sub-makes, in which we're building with
+# the host environment.
+# If any variables are added here, they must be added to do-*, below.
+EXTRA_HOST_FLAGS = \
+ 'AR=$(AR)' \
+ 'AS=$(AS)' \
+ 'CC=$(CC)' \
+ 'CXX=$(CXX)' \
+ 'DLLTOOL=$(DLLTOOL)' \
+ 'NM=$(NM)' \
+ 'RANLIB=$(RANLIB)'
+
+
+FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_HOST_FLAGS)
+
+# Flags that are concerned with the location of the X11 include files
+# and library files
+#
+# NOTE: until the top-level is getting the values via autoconf, it only
+# causes problems to have this top-level Makefile overriding the autoconf-set
+# values in child directories. Only variables that don't conflict with
+# autoconf'ed ones should be passed by X11_FLAGS_TO_PASS for now.
+#
+X11_FLAGS_TO_PASS = \
+ 'X11_EXTRA_CFLAGS=$(X11_EXTRA_CFLAGS)' \
+ 'X11_EXTRA_LIBS=$(X11_EXTRA_LIBS)'
+
+# Flags to pass down to makes which are built with the target environment.
+# The double $ decreases the length of the command line; the variables
+# are set in BASE_FLAGS_TO_PASS, and the sub-make will expand them.
+# If any variables are added here, they must be added to do-*, below.
+EXTRA_TARGET_FLAGS = \
+ 'AR=$$(AR_FOR_TARGET)' \
+ 'AS=$$(AS_FOR_TARGET)' \
+ 'CC=$$(CC_FOR_TARGET)' \
+ 'CFLAGS=$$(CFLAGS_FOR_TARGET)' \
+ 'CXX=$$(CXX_FOR_TARGET)' \
+ 'CXXFLAGS=$$(CXXFLAGS_FOR_TARGET)' \
+ 'DLLTOOL=$$(DLLTOOL_FOR_TARGET)' \
+ 'LD=$$(LD_FOR_TARGET)' \
+ 'LIBCFLAGS=$$(LIBCFLAGS_FOR_TARGET)' \
+ 'LIBCXXFLAGS=$$(LIBCXXFLAGS_FOR_TARGET)' \
+ 'NM=$$(NM_FOR_TARGET)' \
+ 'PICFLAG=$$(PICFLAG_FOR_TARGET)' \
+ 'RANLIB=$$(RANLIB_FOR_TARGET)'
+
+TARGET_FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS)
+
+# Flags to pass down to gcc. gcc builds a library, libgcc.a, so it
+# unfortunately needs the native compiler and the target ar and
+# ranlib.
+# If any variables are added here, they must be added to do-*, below.
+# The HOST_* variables are a special case, which are used for the gcc
+# cross-building scheme.
+EXTRA_GCC_FLAGS = \
+ 'AR=$$(AR_FOR_TARGET)' \
+ 'AS=$(AS)' \
+ 'CC=$(CC)' \
+ 'CXX=$(CXX)' \
+ 'DLLTOOL=$$(DLLTOOL_FOR_TARGET)' \
+ 'HOST_CC=$(CC_FOR_BUILD)' \
+ 'HOST_PREFIX=$(HOST_PREFIX)' \
+ 'HOST_PREFIX_1=$(HOST_PREFIX_1)' \
+ 'NM=$(NM)' \
+ 'RANLIB=$$(RANLIB_FOR_TARGET)' \
+ `if test x"$(LANGUAGES)" != x; then echo "LANGUAGES=$(LANGUAGES)"; fi` \
+ `if test x"$(STMP_FIXPROTO)" != x; then echo "STMP_FIXPROTO=$(STMP_FIXPROTO)"; fi` \
+ `if test x"$(LIMITS_H_TEST)" != x; then echo "LIMITS_H_TEST=$(LIMITS_H_TEST)"; fi` \
+ `if test x"$(LIBGCC1_TEST)" != x; then echo "LIBGCC1_TEST=$(LIBGCC1_TEST)"; fi` \
+ `if test x"$(LIBGCC2_CFLAGS)" != x; then echo "LIBGCC2_CFLAGS=$(LIBGCC2_CFLAGS)"; fi` \
+ `if test x"$(LIBGCC2_INCLUDES)" != x; then echo "LIBGCC2_INCLUDES=$(LIBGCC2_INCLUDES)"; fi` \
+ `if test x"$(ENQUIRE)" != x; then echo "ENQUIRE=$(ENQUIRE)"; fi` \
+ `if test x"$(BOOT_CFLAGS)" != x; then echo "BOOT_CFLAGS=$(BOOT_CFLAGS)"; fi`
+
+GCC_FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_GCC_FLAGS)
+
+# This is a list of the targets for all of the modules which are compiled
+# using $(FLAGS_TO_PASS).
+ALL_MODULES = \
+ all-autoconf \
+ all-bfd \
+ all-binutils \
+ all-byacc \
+ all-cvs \
+ all-dejagnu \
+ all-diff \
+ all-dosutils \
+ all-etc \
+ all-fileutils \
+ all-find \
+ all-flex \
+ all-gas \
+ all-gawk \
+ all-gprof \
+ all-grep \
+ all-grez \
+ all-gzip \
+ all-hello \
+ all-indent \
+ all-ispell \
+ all-ld \
+ all-libiberty \
+ all-m4 \
+ all-make \
+ all-mmalloc \
+ all-opcodes \
+ all-patch \
+ all-prms \
+ all-rcs \
+ all-readline \
+ all-release \
+ all-recode \
+ all-sed \
+ all-send-pr \
+ all-shellutils \
+ all-sim \
+ all-tar \
+ all-tcl \
+ all-texinfo \
+ all-textutils \
+ all-tgas \
+ all-time \
+ all-uudecode \
+ all-wdiff
+
+# This is a list of the check targets for all of the modules which are
+# compiled using $(FLAGS_TO_PASS).
+# This is a list of the check targets for all of the modules which are
+# compiled using $(FLAGS_TO_PASS).
+#
+# The list is in two parts. The first lists those tools which
+# are tested as part of the host's native tool-chain, and not
+# tested in a cross configuration.
+NATIVE_CHECK_MODULES = \
+ check-byacc \
+ check-flex
+
+CROSS_CHECK_MODULES = \
+ check-autoconf \
+ check-bfd \
+ check-binutils \
+ check-cvs \
+ check-dejagnu \
+ check-diff \
+ check-etc \
+ check-fileutils \
+ check-find \
+ check-gas \
+ check-gawk \
+ check-gprof \
+ check-grep \
+ check-gzip \
+ check-hello \
+ check-indent \
+ check-ispell \
+ check-ld \
+ check-libiberty \
+ check-m4 \
+ check-make \
+ check-mmcheckoc \
+ check-opcodes \
+ check-patch \
+ check-prms \
+ check-rcs \
+ check-readline \
+ check-recode \
+ check-sed \
+ check-send-pr \
+ check-shellutils \
+ check-sim \
+ check-tar \
+ check-tcl \
+ check-texinfo \
+ check-textutils \
+ check-tgas \
+ check-time \
+ check-uudecode \
+ check-wdiff
+
+CHECK_MODULES=$(NATIVE_CHECK_MODULES) $(CROSS_CHECK_MODULES)
+
+# This is a list of the install targets for all of the modules which are
+# compiled using $(FLAGS_TO_PASS).
+INSTALL_MODULES = \
+ install-autoconf \
+ install-bfd \
+ install-binutils \
+ install-byacc \
+ install-cvs \
+ install-dejagnu \
+ install-diff \
+ install-dosutils \
+ install-etc \
+ install-fileutils \
+ install-find \
+ install-flex \
+ install-gas \
+ install-gawk \
+ install-gprof \
+ install-grep \
+ install-grez \
+ install-gzip \
+ install-hello \
+ install-indent \
+ install-ispell \
+ install-ld \
+ install-libiberty \
+ install-m4 \
+ install-make \
+ install-mmalloc \
+ install-opcodes \
+ install-patch \
+ install-prms \
+ install-rcs \
+ install-readline \
+ install-recode \
+ install-sed \
+ install-send-pr \
+ install-shellutils \
+ install-sim \
+ install-tar \
+ install-tcl \
+ install-textutils \
+ install-tgas \
+ install-time \
+ install-uudecode \
+ install-wdiff
+
+# This is a list of the targets for all of the modules which are compiled
+# using $(X11_FLAGS_TO_PASS).
+ALL_X11_MODULES = \
+ all-emacs \
+ all-emacs19 \
+ all-gdb \
+ all-expect \
+ all-gash \
+ all-tclX \
+ all-tk
+
+# This is a list of the check targets for all of the modules which are
+# compiled using $(X11_FLAGS_TO_PASS).
+CHECK_X11_MODULES = \
+ check-emacs \
+ check-gdb \
+ check-expect \
+ check-gash \
+ check-tclX \
+ check-tk
+
+# This is a list of the install targets for all the modules which are
+# compiled using $(X11_FLAGS_TO_PASS).
+INSTALL_X11_MODULES = \
+ install-emacs \
+ install-emacs19 \
+ install-gdb \
+ install-expect \
+ install-gash \
+ install-tclX \
+ install-tk
+
+# This is a list of the targets for all of the modules which are compiled
+# using $(TARGET_FLAGS_TO_PASS).
+ALL_TARGET_MODULES = \
+ all-target-libio \
+ all-target-libstdc++ \
+ all-target-librx \
+ all-target-libg++ \
+ all-target-newlib \
+ all-target-winsup \
+ all-target-libgloss \
+ all-target-libiberty \
+ all-target-examples
+
+# This is a list of the configure targets for all of the modules which
+# are compiled using the target tools.
+CONFIGURE_TARGET_MODULES = \
+ configure-target-libio \
+ configure-target-libstdc++ \
+ configure-target-librx \
+ configure-target-libg++ \
+ configure-target-newlib \
+ configure-target-winsup \
+ configure-target-libgloss \
+ configure-target-libiberty \
+ configure-target-examples
+
+# This is a list of the check targets for all of the modules which are
+# compiled using $(TARGET_FLAGS_TO_PASS).
+CHECK_TARGET_MODULES = \
+ check-target-libio \
+ check-target-libstdc++ \
+ check-target-libg++ \
+ check-target-newlib \
+ check-target-winsup \
+ check-target-libiberty
+
+# This is a list of the install targets for all of the modules which are
+# compiled using $(TARGET_FLAGS_TO_PASS).
+INSTALL_TARGET_MODULES = \
+ install-target-libio \
+ install-target-libstdc++ \
+ install-target-libg++ \
+ install-target-newlib \
+ install-target-winsup \
+ install-target-libgloss \
+ install-target-libiberty
+
+# The first rule in the file had better be this one. Don't put any above it.
+all: all.normal
+.PHONY: all
+
+# The target built for a native build.
+.PHONY: all.normal
+all.normal: \
+ $(ALL_MODULES) \
+ $(ALL_TARGET_MODULES) \
+ $(ALL_X11_MODULES) \
+ all-gcc
+
+# Do a target for all the subdirectories. A ``make do-X'' will do a
+# ``make X'' in all subdirectories (because, in general, there is a
+# dependency (below) of X upon do-X, a ``make X'' will also do this,
+# but it may do additional work as well).
+# This target ensures that $(BASE_FLAGS_TO_PASS) appears only once,
+# because it is so large that it can easily overflow the command line
+# length limit on some systems.
+DO_X = \
+ do-clean \
+ do-distclean \
+ do-dvi \
+ do-info \
+ do-install-info \
+ do-installcheck \
+ do-mostlyclean \
+ do-maintainer-clean \
+ do-TAGS
+.PHONY: $(DO_X)
+$(DO_X):
+ @target=`echo $@ | sed -e 's/^do-//'`; \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ for i in $(SUBDIRS) -dummy-; do \
+ if [ -f ./$$i/Makefile ]; then \
+ case $$i in \
+ gcc) \
+ for flag in $(EXTRA_GCC_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'|"`; \
+ done; \
+ ;; \
+ *) \
+ for flag in $(EXTRA_HOST_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'|"`; \
+ done; \
+ ;; \
+ esac ; \
+ export AR AS CC CXX NM RANLIB DLLTOOL; \
+ if (cd ./$$i; \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" \
+ $${target}); \
+ then true; else exit 1; fi; \
+ else true; fi; \
+ done
+ @target=`echo $@ | sed -e 's/^do-//'`; \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ for i in $(TARGET_CONFIGDIRS) -dummy-; do \
+ if [ -f $(TARGET_SUBDIR)/$$i/Makefile ]; then \
+ for flag in $(EXTRA_TARGET_FLAGS); do \
+ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'|"`; \
+ done; \
+ export AR AS CC CXX NM RANLIB DLLTOOL; \
+ if (cd $(TARGET_SUBDIR)/$$i; \
+ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \
+ "CC=$${CC}" "CXX=$${CXX}" "NM=$${NM}" \
+ "RANLIB=$${RANLIB}" \
+ "DLLTOOL=$${DLLTOOL}" \
+ $${target}); \
+ then true; else exit 1; fi; \
+ else true; fi; \
+ done
+
+# Here are the targets which correspond to the do-X targets.
+
+.PHONY: info installcheck dvi install-info
+.PHONY: clean distclean mostlyclean maintainer-clean realclean
+.PHONY: local-clean local-distclean local-maintainer-clean
+info: do-info
+installcheck: do-installcheck
+dvi: do-dvi
+
+install-info: do-install-info dir.info
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ if [ -f dir.info ] ; then \
+ $(INSTALL_DATA) dir.info $(infodir)/dir.info ; \
+ else true ; fi
+
+local-clean:
+ -rm -f *.a TEMP errs core *.o *~ \#* TAGS *.E
+
+local-distclean:
+ -rm -f Makefile config.status
+ -if [ "$(TARGET_SUBDIR)" != "." ]; then \
+ rm -rf $(TARGET_SUBDIR); \
+ else true; fi
+
+local-maintainer-clean:
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+clean: do-clean local-clean
+mostlyclean: do-mostlyclean local-clean
+distclean: do-distclean local-clean local-distclean
+maintainer-clean: local-maintainer-clean do-maintainer-clean local-clean
+maintainer-clean: local-distclean
+realclean: maintainer-clean
+
+# Check target.
+
+.PHONY: check
+check: $(CHECK_MODULES) \
+ $(CHECK_TARGET_MODULES) \
+ $(CHECK_X11_MODULES) \
+ check-gcc
+
+# Installation targets.
+
+.PHONY: install uninstall source-vault binary-vault vault-install
+install: $(INSTALL_TARGET)
+
+uninstall:
+ @echo "the uninstall target is not supported in this tree"
+
+source-vault:
+ $(MAKE) -f ./release/Build-A-Release \
+ host=$(host_alias) source-vault
+
+binary-vault:
+ $(MAKE) -f ./release/Build-A-Release \
+ host=$(host_alias) target=$(target_alias)
+
+vault-install:
+ @if [ -f ./release/vault-install ] ; then \
+ ./release/vault-install $(host_alias) $(target_alias) ; \
+ else \
+ true ; \
+ fi
+
+.PHONY: install.all
+install.all: install-no-fixedincludes
+ @if [ -f ./gcc/Makefile ] ; then \
+ r=`pwd` ; export r ; \
+ $(SET_LIB_PATH) \
+ (cd ./gcc; \
+ $(MAKE) $(FLAGS_TO_PASS) install-headers) ; \
+ else \
+ true ; \
+ fi
+
+# install-no-fixedincludes is used because Cygnus can not distribute
+# the fixed header files.
+.PHONY: install-no-fixedincludes
+install-no-fixedincludes: \
+ install-dirs \
+ $(INSTALL_MODULES) \
+ $(INSTALL_TARGET_MODULES) \
+ $(INSTALL_X11_MODULES) \
+ gcc-no-fixedincludes
+
+# Install the gcc headers files, but not the fixed include files,
+# which Cygnus is not allowed to distribute. This rule is very
+# dependent on the workings of the gcc Makefile.in.
+.PHONY: gcc-no-fixedincludes
+gcc-no-fixedincludes:
+ @if [ -f ./gcc/Makefile ]; then \
+ rm -rf gcc/tmp-include; \
+ mv gcc/include gcc/tmp-include 2>/dev/null; \
+ mkdir gcc/include; \
+ cp $(srcdir)/gcc/gsyslimits.h gcc/include/syslimits.h; \
+ touch gcc/stmp-fixinc gcc/include/fixed; \
+ rm -f gcc/stmp-headers gcc/stmp-int-hdrs; \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd` ; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd ./gcc; \
+ $(MAKE) $(GCC_FLAGS_TO_PASS) install); \
+ rm -rf gcc/include; \
+ mv gcc/tmp-include gcc/include 2>/dev/null; \
+ else true; fi
+
+# This rule is used to build the modules which use FLAGS_TO_PASS. To
+# build a target all-X means to cd to X and make all.
+#
+# all-gui, and all-libproc are handled specially because
+# they are still experimental, and if they fail to build, that
+# shouldn't stop "make all".
+.PHONY: $(ALL_MODULES) all-gui all-libproc
+$(ALL_MODULES) all-gui all-libproc:
+ @dir=`echo $@ | sed -e 's/all-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) all); \
+ else \
+ true; \
+ fi
+
+# These rules are used to check the modules which use FLAGS_TO_PASS.
+# To build a target check-X means to cd to X and make check. Some
+# modules are only tested in a native toolchain.
+
+.PHONY: $(CHECK_MODULES) $(NATIVE_CHECK_MODULES) $(CROSS_CHECK_MODULES)
+$(NATIVE_CHECK_MODULES):
+ @if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ dir=`echo $@ | sed -e 's/check-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) check); \
+ else \
+ true; \
+ fi; \
+ fi
+
+$(CROSS_CHECK_MODULES):
+ @dir=`echo $@ | sed -e 's/check-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) check); \
+ else \
+ true; \
+ fi
+
+# This rule is used to install the modules which use FLAGS_TO_PASS.
+# To build a target install-X means to cd to X and make install.
+.PHONY: $(INSTALL_MODULES)
+$(INSTALL_MODULES): install-dirs
+ @dir=`echo $@ | sed -e 's/install-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) install); \
+ else \
+ true; \
+ fi
+
+# This rule is used to configure the modules which are built with the
+# target tools.
+.PHONY: $(CONFIGURE_TARGET_MODULES)
+$(CONFIGURE_TARGET_MODULES):
+ @dir=`echo $@ | sed -e 's/configure-target-//'`; \
+ if [ -f $(TARGET_SUBDIR)/$${dir}/Makefile ] ; then \
+ true; \
+ elif echo " $(TARGET_CONFIGDIRS) " | grep " $${dir} " >/dev/null 2>&1; then \
+ if [ -d $(srcdir)/$${dir} ]; then \
+ [ -d $(TARGET_SUBDIR)/$${dir} ] || mkdir $(TARGET_SUBDIR)/$${dir};\
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ AR="$(AR_FOR_TARGET)"; export AR; \
+ AS="$(AS_FOR_TARGET)"; export AS; \
+ CC="$(CC_FOR_TARGET)"; export CC; \
+ CFLAGS="$(CFLAGS_FOR_TARGET)"; export CFLAGS; \
+ CXX="$(CXX_FOR_TARGET)"; export CXX; \
+ CXXFLAGS="$(CXXFLAGS_FOR_TARGET)"; export CXXFLAGS; \
+ DLLTOOL="$(DLLTOOL_FOR_TARGET)"; export DLLTOOL; \
+ LD="$(LD_FOR_TARGET)"; export LD; \
+ NM="$(NM_FOR_TARGET)"; export NM; \
+ RANLIB="$(RANLIB_FOR_TARGET)"; export RANLIB; \
+ echo Configuring in $(TARGET_SUBDIR)/$${dir}; \
+ cd $(TARGET_SUBDIR)/$${dir}; \
+ case $(srcdir) in \
+ /*) \
+ topdir=$(srcdir) ;; \
+ *) \
+ case "$(TARGET_SUBDIR)" in \
+ .) topdir="../$(srcdir)" ;; \
+ *) topdir="../../$(srcdir)" ;; \
+ esac ;; \
+ esac; \
+ if [ "$(srcdir)" = "." ] ; then \
+ if [ "$(TARGET_SUBDIR)" != "." ] ; then \
+ if $(SHELL) $${srcroot}/symlink-tree $${topdir}/$${dir} "no-such-file" ; then \
+ if [ -f Makefile ]; then \
+ if $(MAKE) distclean; then \
+ true; \
+ else \
+ exit 1; \
+ fi; \
+ else \
+ true; \
+ fi; \
+ else \
+ exit 1; \
+ fi; \
+ else \
+ true; \
+ fi; \
+ srcdiroption="--srcdir=."; \
+ libsrcdir="."; \
+ else \
+ srcdiroption="--srcdir=$${topdir}/$${dir}"; \
+ libsrcdir="$${srcroot}/$${dir}"; \
+ fi; \
+ if [ -f $${libsrcdir}/configure ] ; then \
+ $(SHELL) $${libsrcdir}/configure \
+ $(CONFIG_ARGUMENTS) $${srcdiroption} \
+ --with-target-subdir="$(TARGET_SUBDIR)"; \
+ else \
+ $(SHELL) $${srcroot}/configure \
+ $(CONFIG_ARGUMENTS) $${srcdiroption} \
+ --with-target-subdir="$(TARGET_SUBDIR)"; \
+ fi; \
+ else \
+ true; \
+ fi; \
+ else \
+ true; \
+ fi
+
+# This rule is used to build the modules which use TARGET_FLAGS_TO_PASS.
+# To build a target all-X means to cd to X and make all.
+.PHONY: $(ALL_TARGET_MODULES)
+$(ALL_TARGET_MODULES):
+ @dir=`echo $@ | sed -e 's/all-target-//'`; \
+ if [ -f $(TARGET_SUBDIR)/$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $(TARGET_SUBDIR)/$${dir}; $(MAKE) $(TARGET_FLAGS_TO_PASS) all); \
+ else \
+ true; \
+ fi
+
+# This rule is used to check the modules which use TARGET_FLAGS_TO_PASS.
+# To build a target install-X means to cd to X and make install.
+.PHONY: $(CHECK_TARGET_MODULES)
+$(CHECK_TARGET_MODULES):
+ @dir=`echo $@ | sed -e 's/check-target-//'`; \
+ if [ -f $(TARGET_SUBDIR)/$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $(TARGET_SUBDIR)/$${dir};$(MAKE) $(TARGET_FLAGS_TO_PASS) check);\
+ else \
+ true; \
+ fi
+
+# This rule is used to install the modules which use
+# TARGET_FLAGS_TO_PASS. To build a target install-X means to cd to X
+# and make install.
+.PHONY: $(INSTALL_TARGET_MODULES)
+$(INSTALL_TARGET_MODULES): install-dirs
+ @dir=`echo $@ | sed -e 's/install-target-//'`; \
+ if [ -f $(TARGET_SUBDIR)/$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $(TARGET_SUBDIR)/$${dir}; \
+ $(MAKE) $(TARGET_FLAGS_TO_PASS) install); \
+ else \
+ true; \
+ fi
+
+# This rule is used to build the modules which use X11_FLAGS_TO_PASS.
+# To build a target all-X means to cd to X and make all.
+.PHONY: $(ALL_X11_MODULES)
+$(ALL_X11_MODULES):
+ @dir=`echo $@ | sed -e 's/all-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; \
+ $(MAKE) $(FLAGS_TO_PASS) $(X11_FLAGS_TO_PASS) all); \
+ else \
+ true; \
+ fi
+
+# This rule is used to check the modules which use X11_FLAGS_TO_PASS.
+# To build a target check-X means to cd to X and make all.
+.PHONY: $(CHECK_X11_MODULES)
+$(CHECK_X11_MODULES):
+ @dir=`echo $@ | sed -e 's/check-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; \
+ $(MAKE) $(FLAGS_TO_PASS) $(X11_FLAGS_TO_PASS) check); \
+ else \
+ true; \
+ fi
+
+# This rule is used to install the modules which use X11_FLAGS_TO_PASS.
+# To build a target install-X means to cd to X and make install.
+.PHONY: $(INSTALL_X11_MODULES)
+$(INSTALL_X11_MODULES):
+ @dir=`echo $@ | sed -e 's/install-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; \
+ $(MAKE) $(FLAGS_TO_PASS) $(X11_FLAGS_TO_PASS) install); \
+ else \
+ true; \
+ fi
+
+# gcc is the only module which uses GCC_FLAGS_TO_PASS.
+.PHONY: all-gcc
+all-gcc:
+ @if [ -f ./gcc/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd gcc; $(MAKE) $(GCC_FLAGS_TO_PASS) all); \
+ else \
+ true; \
+ fi
+
+.PHONY: all-bootstrap
+all-bootstrap:
+ @if [ -f ./gcc/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd gcc; $(MAKE) $(GCC_FLAGS_TO_PASS) bootstrap); \
+ else \
+ true; \
+ fi
+
+.PHONY: check-gcc
+check-gcc:
+ @if [ -f ./gcc/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd gcc; $(MAKE) $(GCC_FLAGS_TO_PASS) check); \
+ else \
+ true; \
+ fi
+
+.PHONY: install-gcc
+install-gcc:
+ @if [ -f ./gcc/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd gcc; $(MAKE) $(GCC_FLAGS_TO_PASS) install); \
+ else \
+ true; \
+ fi
+
+
+# EXPERIMENTAL STUFF
+# This rule is used to install the modules which use FLAGS_TO_PASS.
+# To build a target install-X means to cd to X and make install.
+.PHONY: install-dosrel
+install-dosrel: install-dirs info
+ @dir=`echo $@ | sed -e 's/install-//'`; \
+ if [ -f ./$${dir}/Makefile ] ; then \
+ r=`pwd`; export r; \
+ srcroot=`cd $(srcdir); pwd`; export srcroot; \
+ $(SET_LIB_PATH) \
+ (cd $${dir}; $(MAKE) $(FLAGS_TO_PASS) install); \
+ else \
+ true; \
+ fi
+
+install-dosrel-fake:
+
+
+# This is a list of inter-dependencies among modules.
+all-autoconf: all-m4
+all-bfd:
+all-binutils: all-libiberty all-opcodes all-bfd all-flex all-byacc
+all-byacc:
+all-cvs:
+all-dejagnu: all-tcl all-expect all-tk
+all-diff: all-libiberty
+all-emacs:
+all-emacs19: all-byacc
+all-etc:
+configure-target-examples: $(ALL_GCC)
+all-target-examples: configure-target-examples
+all-expect: all-tcl all-tk
+all-fileutils: all-libiberty
+all-find:
+all-flex: all-libiberty all-byacc
+all-gas: all-libiberty all-opcodes all-bfd
+all-gash: all-tcl
+all-gawk:
+ALL_GCC = all-gcc
+all-gcc: all-libiberty all-byacc all-binutils all-gas all-ld
+all-bootstrap: all-libiberty all-byacc all-binutils all-gas all-ld
+GDB_TK = all-tk all-tcl
+all-gdb: all-libiberty all-opcodes all-bfd all-mmalloc all-readline all-byacc all-sim $(gdbnlmrequirements) $(GDB_TK)
+all-gprof: all-libiberty all-bfd all-opcodes
+all-grep: all-libiberty
+all-grez: all-libiberty all-bfd all-opcodes
+all-gui: all-gdb all-libproc all-target-librx
+all-gzip: all-libiberty
+all-hello: all-libiberty
+all-indent:
+all-ispell: all-emacs19
+all-ld: all-libiberty all-bfd all-opcodes all-byacc all-flex
+configure-target-libg++: $(ALL_GCC) configure-target-librx
+all-target-libg++: configure-target-libg++ all-gas all-ld all-gcc all-target-libiberty all-target-newlib all-target-libio all-target-librx all-target-libstdc++
+configure-target-libgloss: $(ALL_GCC)
+all-target-libgloss: configure-target-libgloss configure-target-newlib
+configure-target-libio: $(ALL_GCC)
+all-target-libio: configure-target-libio all-gas all-ld all-gcc all-target-libiberty all-target-newlib
+all-libiberty:
+configure-target-librx: $(ALL_GCC) configure-target-newlib
+all-target-librx: configure-target-librx
+configure-target-libstdc++: $(ALL_GCC)
+all-target-libstdc++: configure-target-libstdc++ all-gas all-ld all-gcc all-target-libiberty all-target-newlib all-target-libio
+all-m4: all-libiberty
+all-make: all-libiberty
+all-mmalloc:
+configure-target-newlib: $(ALL_GCC)
+all-target-newlib: configure-target-newlib all-binutils all-gas all-gcc
+all-opcodes: all-bfd all-libiberty
+all-patch: all-libiberty
+all-prms: all-libiberty
+all-rcs:
+all-readline:
+all-recode: all-libiberty
+all-sed: all-libiberty
+all-send-pr: all-prms
+all-shellutils:
+all-sim: all-libiberty all-bfd all-opcodes
+all-tar: all-libiberty
+all-tcl:
+all-tclX: all-tcl all-tk
+all-tk: all-tcl
+all-texinfo: all-libiberty
+all-textutils:
+all-tgas: all-libiberty all-bfd all-opcodes
+all-time:
+all-wdiff:
+all-target-winsup: all-target-newlib all-target-libiberty configure-target-winsup
+configure-target-winsup: configure-target-newlib
+all-uudecode: all-libiberty
+configure-target-libiberty: $(ALL_GCC)
+all-target-libiberty: configure-target-libiberty all-gcc all-ld all-target-newlib
+
+### other supporting targets
+
+MAKEDIRS= \
+ $(prefix) \
+ $(exec_prefix) \
+ $(tooldir)
+
+.PHONY: install-dirs
+install-dirs:
+ @for i in $(MAKEDIRS) ; do \
+ echo Making $$i... ; \
+ parent=`echo $$i | sed -e 's@/[^/]*$$@@' | sed -e 's@^$$@/@'`; \
+ if [ -d $$parent ] ; then true ; else mkdir $$parent ; fi ; \
+ if [ ! -d $$i ] ; then \
+ if mkdir $$i ; then \
+ true ; \
+ else \
+ exit 1 ; \
+ fi ; \
+ else \
+ true ; \
+ fi ; \
+ done
+
+
+dir.info: do-install-info
+ if [ -f $(srcdir)/texinfo/gen-info-dir ] ; then \
+ $(srcdir)/texinfo/gen-info-dir $(infodir) $(srcdir)/texinfo/dir.info-template > dir.info.new ; \
+ mv -f dir.info.new dir.info ; \
+ else true ; \
+ fi
+
+dist:
+ @echo "Building a full distribution of this tree isn't done"
+ @echo "via 'make dist'. Check out the etc/ subdirectory"
+
+etags tags: TAGS
+
+# Right now this just builds TAGS in each subdirectory. emacs19 has the
+# ability to use several tags files at once, so there is probably no need
+# to combine them into one big TAGS file (like CVS 1.3 does). We could
+# (if we felt like it) have this Makefile write a piece of elisp which
+# the user could load to tell emacs19 where all the TAGS files we just
+# built are.
+TAGS: do-TAGS
+
+# with the gnu make, this is done automatically.
+
+Makefile: Makefile.in configure.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
+
+#
+# Support for building net releases
+
+# Files in devo used in any net release.
+# ChangeLog omitted because it may refer to files which are not in this
+# distribution (perhaps it would be better to include it anyway).
+DEVO_SUPPORT= README Makefile.in configure configure.in \
+ config.guess config.sub config move-if-change \
+ mpw-README mpw-build.in mpw-config.in mpw-configure \
+ COPYING COPYING.LIB install.sh config-ml.in symlink-tree
+
+# Files in devo/etc used in any net release.
+# ChangeLog omitted because it may refer to files which are not in this
+# distribution (perhaps it would be better to include it anyway).
+ETC_SUPPORT= Makefile.in cfg-paper.texi configure.in configure.man \
+ configure.texi standards.texi make-stds.texi \
+ configure.info* standards.info* cfg-paper.info*
+
+# When you use `make setup-dirs' or `make taz' you should always redefine
+# this macro.
+SUPPORT_FILES = list-of-support-files-for-tool-in-question
+# Files where "byacc" (Cygnus version) should be changed to "bison -y" (FSF).
+DISTBISONFILES= binutils/Makefile.in gas/Makefile.in gdb/Makefile.in
+
+.PHONY: taz
+
+taz: $(DEVO_SUPPORT) $(SUPPORT_FILES) \
+ texinfo/texinfo.tex texinfo/gpl.texinfo texinfo/lgpl.texinfo
+ # Make sure "diststuff" files get built properly.
+ for f in $(DISTBISONFILES) ; do \
+ if [ -r $$f ]; then \
+ sed '/^BISON *=.*$$/s/.*/BISON = bison -y/' <$$f >tmp ; \
+ mv -f tmp $$f ; \
+ else true; fi ; \
+ done
+ # Take out texinfo from a few places; make simple BISON=bison line.
+ sed -e '/^all\.normal: /s/\all-texinfo //' \
+ -e '/^ install-texinfo /d' \
+ -e '/^BISON = /,/^$$/d' \
+ -e '/^# BISON:/s/.*/BISON = bison -y/' \
+ <Makefile.in >tmp
+ mv -f tmp Makefile.in
+ #
+ ./configure sun4
+ [ -z "$(CONFIGURE_TARGET_MODULES)" ] \
+ || $(MAKE) $(CONFIGURE_TARGET_MODULES) ALL_GCC="" \
+ CC_FOR_TARGET="$(CC)" CXX_FOR_TARGET="$(CXX)"
+ # Make links, and run "make diststuff" or "make info" when needed.
+ rm -rf proto-toplev ; mkdir proto-toplev
+ set -e ; dirs="$(TOOL) $(DEVO_SUPPORT) $(SUPPORT_FILES)" ; \
+ for d in $$dirs ; do \
+ if [ -d $$d ]; then \
+ if [ ! -f $$d/Makefile ] ; then true ; \
+ elif grep '^diststuff:' $$d/Makefile >/dev/null ; then \
+ (cd $$d ; $(MAKE) diststuff ) || exit 1 ; \
+ elif grep '^info:' $$d/Makefile >/dev/null ; then \
+ (cd $$d ; $(MAKE) info ) || exit 1 ; \
+ fi ; \
+ if [ -d $$d/proto-$$d.dir ]; then \
+ ln -s ../$$d/proto-$$d.dir proto-toplev/$$d ; \
+ else \
+ ln -s ../$$d proto-toplev/$$d ; \
+ fi ; \
+ else ln -s ../$$d proto-toplev/$$d ; fi ; \
+ done
+ cd etc ; $(MAKE) info
+ $(MAKE) distclean
+ #
+ mkdir proto-toplev/etc
+ (cd proto-toplev/etc; \
+ for i in $(ETC_SUPPORT); do \
+ ln -s ../../etc/$$i . ; \
+ done)
+ #
+ # Take out texinfo from configurable dirs
+ rm proto-toplev/configure.in
+ sed -e '/^host_tools=/s/texinfo //' \
+ <configure.in >proto-toplev/configure.in
+ #
+ mkdir proto-toplev/texinfo
+ ln -s ../../texinfo/texinfo.tex proto-toplev/texinfo/
+ ln -s ../../texinfo/gpl.texinfo proto-toplev/texinfo/
+ ln -s ../../texinfo/lgpl.texinfo proto-toplev/texinfo/
+ ln -s ../../texinfo/tex3patch proto-toplev/texinfo/
+ chmod og=u `find . -print`
+ (VER=`sed <$(TOOL)/Makefile.in -n 's/^VERSION *= *//p'`; \
+ echo "==> Making $(TOOL)-$$VER.tar.gz"; \
+ rm -f $(TOOL)-$$VER; ln -s proto-toplev $(TOOL)-$$VER; \
+ tar cfh - $(TOOL)-$$VER \
+ | $(GZIPPROG) -v -9 >$(TOOL)-$$VER.tar.gz )
+
+TEXINFO_SUPPORT= texinfo/texinfo.tex texinfo/gpl.texinfo texinfo/lgpl.texinfo
+DIST_SUPPORT= $(DEVO_SUPPORT) $(TEXINFO_SUPPORT)
+
+.PHONY: gas.tar.gz
+GAS_SUPPORT_DIRS= bfd include libiberty opcodes
+gas.tar.gz: $(DIST_SUPPORT) $(GAS_SUPPORT_DIRS) gas
+ $(MAKE) -f Makefile.in taz TOOL=gas \
+ SUPPORT_FILES="$(GAS_SUPPORT_DIRS)"
+
+# The FSF "binutils" release includes gprof and ld.
+.PHONY: binutils.tar.gz
+BINUTILS_SUPPORT_DIRS= bfd gas include libiberty opcodes ld gprof
+binutils.tar.gz: $(DIST_SUPPORT) $(BINUTILS_SUPPORT_DIRS) binutils
+ $(MAKE) -f Makefile.in taz TOOL=binutils \
+ SUPPORT_FILES="$(BINUTILS_SUPPORT_DIRS) makeall.bat configure.bat"
+
+.PHONY: gas+binutils.tar.gz
+GASB_SUPPORT_DIRS= $(GAS_SUPPORT_DIRS) binutils ld gprof
+gas+binutils.tar.gz: $(DIST_SUPPORT) $(GASB_SUPPORT_DIRS) gas
+ $(MAKE) -f Makefile.in taz TOOL=gas \
+ SUPPORT_FILES="$(GASB_SUPPORT_DIRS) makeall.bat configure.bat"
+
+.PHONY: libg++.tar.gz
+LIBGXX_SUPPORT_DIRS=include libstdc++ libio librx libiberty
+libg++.tar.gz: $(DIST_SUPPORT) libg++
+ $(MAKE) -f Makefile.in taz TOOL=libg++ \
+ SUPPORT_FILES="$(LIBGXX_SUPPORT_DIRS)"
+
+GNATS_SUPPORT_DIRS=include libiberty send-pr
+gnats.tar.gz: $(DIST_SUPPORT) $(GNATS_SUPPORT_DIRS) gnats
+ $(MAKE) -f Makefile.in taz TOOL=gnats \
+ SUPPORT_FILES="$(GNATS_SUPPORT_DIRS)"
+
+.PHONY: gdb.tar.gz
+GDB_SUPPORT_DIRS= bfd include libiberty mmalloc opcodes readline sim utils
+gdb.tar.gz: $(DIST_SUPPORT) $(GDB_SUPPORT_DIRS) gdb
+ $(MAKE) -f Makefile.in taz TOOL=gdb \
+ SUPPORT_FILES="$(GDB_SUPPORT_DIRS)"
+
+.PHONY: newlib.tar.gz
+NEWLIB_SUPPORT_DIRS=libgloss
+# taz configures for the sun4 target which won't configure newlib.
+# We need newlib configured so that the .info files are made.
+# Unfortunately, it is not enough to just configure newlib separately:
+# taz will build the .info files but since SUBDIRS won't contain newlib,
+# distclean won't be run (leaving Makefile, config.status, and the tmp files
+# used in building the .info files, eg: *.def, *.ref).
+# The problem isn't solvable however without a lot of extra work because
+# target libraries are built in subdir $(target_alias) which gets nuked during
+# the make distclean. For now punt on the issue of shipping newlib info files
+# with newlib net releases and wait for a day when some native target (sun4?)
+# supports newlib (if only minimally).
+newlib.tar.gz: $(DIST_SUPPORT) $(NEWLIB_SUPPORT_DIRS) newlib
+ $(MAKE) -f Makefile.in taz TOOL=newlib \
+ SUPPORT_FILES="$(NEWLIB_SUPPORT_DIRS)" \
+ DEVO_SUPPORT="$(DEVO_SUPPORT) COPYING.NEWLIB" newlib
+
+.NOEXPORT:
+MAKEOVERRIDES=
+
+
+# end of Makefile.in
diff --git a/contrib/gdb/README b/contrib/gdb/README
new file mode 100644
index 0000000..7ec34b1
--- /dev/null
+++ b/contrib/gdb/README
@@ -0,0 +1,50 @@
+ README for GNU development tools
+
+This directory contains various GNU compilers, assemblers, linkers,
+debuggers, etc., plus their support routines, definitions, and documentation.
+
+If you are receiving this as part of a GDB release, see the file gdb/README.
+If with a gas release, see gas/README; if with a libg++ release,
+see libg++/README, etc. That'll give you info about this
+package -- supported targets, how to use it, how to report bugs, etc.
+
+It is now possible to automatically configure and build a variety of
+tools with one command. To build all of the tools contained herein,
+run the ``configure'' script here, e.g.:
+
+ ./configure
+ make
+
+To install them (by default in /usr/local/bin, /usr/local/lib, etc),
+then do:
+ make install
+
+If the configure script can't determine your type of computer, give it
+the name as an argument, for instance ``./configure sun4''. You can
+use the script ``config.sub'' to test whether a name is recognized; if
+it is, config.sub translates it to a triplet specifying CPU, vendor,
+and OS.)
+
+If you have more than one compiler on your system, it is often best to
+explicitly set CC in the environment before running configure, and to
+also set CC when running make. For example (assuming sh/bash/ksh):
+
+ CC=gcc ./configure
+ make CC=gcc
+
+A similar example using csh:
+
+ setenv CC gcc
+ ./configure
+ make CC=gcc
+
+See etc/cfg-paper.texi, etc/configure.texi, and/or the README files in
+various subdirectories, for more details.
+
+Much of the code and documentation enclosed is copyright by
+the Free Software Foundation, Inc. See the file COPYING or
+COPYING.LIB in the various directories, for a description of the
+GNU General Public License terms under which you can copy the files.
+
+REPORTING BUGS: Again, see gdb/README, gas/README, etc., for info on where and
+how to report problems.
diff --git a/contrib/gdb/bfd/COPYING b/contrib/gdb/bfd/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/contrib/gdb/bfd/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/contrib/gdb/bfd/Makefile.in b/contrib/gdb/bfd/Makefile.in
new file mode 100644
index 0000000..e531cf8
--- /dev/null
+++ b/contrib/gdb/bfd/Makefile.in
@@ -0,0 +1,1090 @@
+# Makefile template for Configure for the BFD library.
+# Copyright (C) 1990, 91, 92, 93, 94, 95, 1996
+# Free Software Foundation, Inc.
+# Written by 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
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+prefix = @prefix@
+
+program_transform_name = @program_transform_name@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+oldincludedir =
+docdir = doc
+
+SHELL = /bin/sh
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+AR = @AR@
+AR_FLAGS = rc
+CC = @CC@
+CFLAGS = @CFLAGS@
+MAKEINFO = makeinfo
+RANLIB = @RANLIB@
+
+ALLLIBS = @ALLLIBS@
+
+PICFLAG = @PICFLAG@
+SHLIB = @SHLIB@
+SHLIB_CC = @SHLIB_CC@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+COMMON_SHLIB = @COMMON_SHLIB@
+SHLINK = @SHLINK@
+
+SONAME = lib`echo $(SHLIB) | sed -e 's/^lib//' | sed '$(program_transform_name)'`
+
+CC_FOR_BUILD = @CC_FOR_BUILD@
+
+INCDIR = $(srcdir)/../include
+CSEARCH = -I. -I$(srcdir) -I$(INCDIR)
+DEP = mkdep
+
+SUBDIRS = doc
+
+TARGETLIB = libbfd.a
+
+# bfd.h goes here, for now
+BFD_H = bfd.h
+
+# Some of these files should be in BFD*_BACKENDS below, but some programs
+# won't link without them. So, in order for some of the minimal-bfd
+# hacks to work, they're also included here for now.
+# gdb: elf.o
+# objdump: elf.o
+#
+# Also, Jim Kingdon notes:
+# Writing S-records should be included in all (or at least most)
+# *-*-coff, *-*-aout, etc., configurations, because people will want to
+# be able to use objcopy to create S-records. (S-records are not useful
+# for the debugger, so if you are downloading things as S-records you
+# need two copies of the executable, one to download and one for the
+# debugger).
+BFD_LIBS = \
+ archive.o archures.o bfd.o cache.o coffgen.o corefile.o \
+ format.o init.o libbfd.o opncls.o reloc.o \
+ section.o syms.o targets.o hash.o linker.o \
+ elf.o srec.o binary.o tekhex.o ihex.o stab-syms.o
+
+BFD_LIBS_CFILES = \
+ archive.c archures.c bfd.c cache.c coffgen.c corefile.c \
+ format.c init.c libbfd.c opncls.c reloc.c \
+ section.c syms.c targets.c hash.c linker.c \
+ elf.c srec.c binary.c tekhex.c ihex.c stab-syms.c
+
+# This list is alphabetized to make it easier to keep in sync
+# with the decls and initializer in archures.c.
+ALL_MACHINES = \
+ cpu-a29k.o \
+ cpu-alpha.o \
+ cpu-arm.o \
+ cpu-h8300.o \
+ cpu-h8500.o \
+ cpu-hppa.o \
+ cpu-i386.o \
+ cpu-i860.o \
+ cpu-i960.o \
+ cpu-m68k.o \
+ cpu-m88k.o \
+ cpu-mips.o \
+ cpu-ns32k.o \
+ cpu-powerpc.o \
+ cpu-rs6000.o \
+ cpu-sh.o \
+ cpu-sparc.o \
+ cpu-vax.o \
+ cpu-we32k.o \
+ cpu-w65.o \
+ cpu-z8k.o
+
+ALL_MACHINES_CFILES = \
+ cpu-a29k.c \
+ cpu-alpha.c \
+ cpu-arm.c \
+ cpu-h8300.c \
+ cpu-h8500.c \
+ cpu-hppa.c \
+ cpu-i386.c \
+ cpu-i860.c \
+ cpu-i960.c \
+ cpu-m68k.c \
+ cpu-m88k.c \
+ cpu-mips.c \
+ cpu-ns32k.c \
+ cpu-powerpc.c \
+ cpu-rs6000.c \
+ cpu-sh.c \
+ cpu-sparc.c \
+ cpu-vax.c \
+ cpu-we32k.c \
+ cpu-w65.c \
+ cpu-z8k.c
+
+# The .o files needed by all of the 32 bit vectors that are configured into
+# target_vector in targets.c if configured with --enable-targets=all.
+BFD32_BACKENDS = \
+ aout-adobe.o \
+ aout-ns32k.o \
+ aout0.o \
+ aout32.o \
+ bout.o \
+ cf-i386lynx.o \
+ cf-m68klynx.o \
+ cf-sparclynx.o \
+ coff-a29k.o \
+ coff-apollo.o \
+ coff-arm.o \
+ coff-aux.o \
+ coff-h8300.o \
+ coff-h8500.o \
+ coff-i386.o \
+ coff-go32.o \
+ coff-i860.o \
+ coff-i960.o \
+ coff-m68k.o \
+ coff-m88k.o \
+ coff-mips.o \
+ coff-pmac.o \
+ coff-rs6000.o \
+ coff-sh.o \
+ coff-sparc.o \
+ coff-u68k.o \
+ coff-we32k.o \
+ coff-w65.o \
+ coff-z8k.o \
+ cofflink.o \
+ ecoff.o \
+ ecofflink.o \
+ elf32-gen.o \
+ elf32-hppa.o \
+ elf32-i386.o \
+ elf32-i860.o \
+ elf32-m68k.o \
+ elf32-m88k.o \
+ elf32-mips.o \
+ elf32-ppc.o \
+ elf32-sparc.o \
+ elf32.o \
+ elflink.o \
+ hp300hpux.o \
+ som.o \
+ i386aout.o \
+ i386bsd.o \
+ i386freebsd.o \
+ i386linux.o \
+ i386lynx.o \
+ i386msdos.o \
+ i386netbsd.o \
+ i386mach3.o \
+ i386os9k.o \
+ ieee.o \
+ m68klinux.o \
+ m68klynx.o \
+ m68knetbsd.o \
+ m88kmach3.o \
+ mipsbsd.o \
+ newsos3.o \
+ nlm.o \
+ nlm32-i386.o \
+ nlm32-sparc.o \
+ nlm32-ppc.o \
+ nlm32.o \
+ ns32knetbsd.o \
+ oasys.o \
+ pc532-mach.o \
+ pe-arm.o \
+ pei-arm.o \
+ pe-i386.o \
+ pei-i386.o \
+ pe-ppc.o \
+ pei-ppc.o \
+ reloc16.o \
+ sparclynx.o \
+ sparcnetbsd.o \
+ sunos.o \
+ tekhex.o \
+ versados.o \
+ xcofflink.o
+
+BFD32_BACKENDS_CFILES = \
+ aout-adobe.c \
+ aout-ns32k.c \
+ aout0.c \
+ aout32.c \
+ bout.c \
+ cf-i386lynx.c \
+ cf-m68klynx.c \
+ cf-sparclynx.c \
+ coff-a29k.c \
+ coff-apollo.c \
+ coff-arm.c \
+ coff-aux.c \
+ coff-h8300.c \
+ coff-h8500.c \
+ coff-i386.c \
+ coff-i860.c \
+ coff-go32.c \
+ coff-i960.c \
+ coff-m68k.c \
+ coff-m88k.c \
+ coff-mips.c \
+ coff-pmac.c \
+ coff-rs6000.c \
+ coff-sh.c \
+ coff-sparc.c \
+ coff-u68k.c \
+ coff-we32k.c \
+ coff-w65.c \
+ coff-z8k.c \
+ cofflink.c \
+ ecoff.c \
+ ecofflink.c \
+ elf32-gen.c \
+ elf32-hppa.c \
+ elf32-i386.c \
+ elf32-i860.c \
+ elf32-m68k.c \
+ elf32-m88k.c \
+ elf32-mips.c \
+ elf32-ppc.c \
+ elf32-sparc.c \
+ elf32.c \
+ elflink.c \
+ hp300hpux.c \
+ som.c \
+ i386aout.c \
+ i386bsd.c \
+ i386freebsd.c \
+ i386linux.c \
+ i386lynx.c \
+ i386msdos.c \
+ i386netbsd.c \
+ i386mach3.c \
+ i386os9k.c \
+ ieee.c \
+ m68klinux.c \
+ m68klynx.c \
+ m68knetbsd.c \
+ m88kmach3.c \
+ mipsbsd.c \
+ newsos3.c \
+ nlm.c \
+ nlm32-i386.c \
+ nlm32-sparc.c \
+ nlm32-ppc.c \
+ nlm32.c \
+ ns32knetbsd.c \
+ oasys.c \
+ pc532-mach.c \
+ pe-arm.c \
+ pei-arm.c \
+ pe-i386.c \
+ pei-i386.c \
+ pe-ppc.c \
+ pei-ppc.c \
+ reloc16.c \
+ sparclynx.c \
+ sparcnetbsd.c \
+ sunos.c \
+ tekhex.c \
+ versados.c \
+ xcofflink.c
+
+# The .o files needed by all of the 64 bit vectors that are configured into
+# target_vector in targets.c if configured with --enable-targets=all
+# and --enable-64-bit-bfd.
+BFD64_BACKENDS = \
+ aout64.o \
+ coff-alpha.o \
+ demo64.o \
+ elf64-gen.o \
+ elf64-sparc.o \
+ elf64.o \
+ nlm32-alpha.o \
+ nlm64.o
+
+BFD64_BACKENDS_CFILES = \
+ aout64.c \
+ coff-alpha.c \
+ demo64.c \
+ elf64-gen.c \
+ elf64-sparc.c \
+ elf64.c \
+ nlm32-alpha.c \
+ nlm64.c
+
+OPTIONAL_BACKENDS = \
+ aix386-core.o \
+ hpux-core.o \
+ irix-core.o \
+ lynx-core.o \
+ osf-core.o \
+ trad-core.o \
+ cisco-core.o
+
+OPTIONAL_BACKENDS_CFILES = \
+ aix386-core.c \
+ hpux-core.c \
+ irix-core.c \
+ lynx-core.c \
+ osf-core.c \
+ trad-core.c \
+ cisco-core.c
+
+# These are defined by configure.in:
+WORDSIZE = @wordsize@
+ALL_BACKENDS = @all_backends@
+BFD_BACKENDS = @bfd_backends@
+BFD_MACHINES = @bfd_machines@
+TDEFAULTS = @tdefaults@
+
+all:
+
+FLAGS_TO_PASS = \
+ "prefix=$(prefix)" \
+ "exec_prefix=$(exec_prefix)" \
+ "against=$(against)" \
+ "AR=$(AR)" \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC=$(CC)" \
+ "CC_FOR_BUILD=$(CC_FOR_BUILD)" \
+ "CFLAGS=$(CFLAGS)" \
+ "RANLIB=$(RANLIB)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)"
+
+ALL_CFLAGS=@HDEFINES@ @COREFLAG@ @TDEFINES@ $(CSEARCH) $(CSWITCHES) $(CFLAGS)
+.c.o:
+ if [ -n "$(PICFLAG)" ]; then \
+ $(CC) -c $(PICFLAG) $(ALL_CFLAGS) $< -o pic/$@; \
+ else true; fi
+ $(CC) -c $(ALL_CFLAGS) $<
+
+bfd_libs_here =
+all_machines_here =
+bfd32_backends_here =
+core_files_here =
+configs_not_included_in_all_targets_option_here =
+
+# C source files that correspond to .o's.
+CFILES = \
+ $(BFD_LIBS_CFILES) \
+ $(ALL_MACHINES_CFILES) \
+ $(BFD32_BACKENDS_CFILES) \
+ $(BFD64_BACKENDS_CFILES) \
+ $(OPTIONAL_BACKENDS_CFILES) \
+ i386dynix.c hp300bsd.c
+
+HFILES = aout-target.h aoutf1.h aoutx.h coffcode.h \
+ coffswap.h ecoffswap.h elf32-hppa.h elf32-target.h elf64-target.h \
+ elfcode.h hppa_stubs.h libaout.h libbfd.h \
+ libcoff.h libecoff.h elf-bfd.h libhppa.h libieee.h libnlm.h \
+ liboasys.h nlm-target.h nlmcode.h som.h genlink.h netbsd.h
+
+all: Makefile $(ALLLIBS) @PICLIST@
+ @$(MAKE) subdir_do DO=all "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+
+.NOEXPORT:
+MAKEOVERRIDES=
+
+.PHONY: check installcheck
+check:
+ @echo No testsuites exist for the BFD library. Nothing to check.
+
+installcheck:
+ @echo No testsuites exist for the BFD library. Nothing to check.
+
+info dvi : force
+ @$(MAKE) subdir_do DO=$@ "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+
+clean-info:
+ @$(MAKE) subdir_do DO=clean-info "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+
+install-info: force
+ @$(MAKE) subdir_do DO=install-info "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+
+diststuff: info
+
+# Various kinds of .o files to put in libbfd.a:
+# BFD_LIBS Generic routines, always needed.
+# BFD_BACKENDS Routines the configured targets need.
+# BFD_MACHINES Architecture-specific routines the configured targets need.
+# COREFILE Core file routines for a native configuration
+OFILES = $(BFD_LIBS) $(BFD_BACKENDS) $(BFD_MACHINES) @COREFILE@
+
+stamp-ofiles: Makefile
+ rm -f tofiles
+ f=""; \
+ for i in $(OFILES) ; do \
+ case " $$f " in \
+ *" $$i "*) ;; \
+ *) f="$$f $$i" ;; \
+ esac ; \
+ done ; \
+ echo $$f > tofiles
+ $(srcdir)/../move-if-change tofiles ofiles
+ touch stamp-ofiles
+
+ofiles: stamp-ofiles ; @true
+
+$(TARGETLIB): $(OFILES) ofiles
+ rm -f $(TARGETLIB)
+ @echo ofiles = `cat ofiles`
+ $(AR) $(AR_FLAGS) $(TARGETLIB) `cat ofiles`
+ $(RANLIB) $(TARGETLIB)
+
+stamp-piclist: ofiles
+ rm -f tpiclist
+ if [ -n "$(PICFLAG)" ]; then \
+ sed -e 's,\([^ ][^ ]*\),pic/\1,g' ofiles > tpiclist; \
+ else \
+ cp ofiles tpiclist; \
+ fi
+ $(srcdir)/../move-if-change tpiclist piclist
+ touch stamp-piclist
+
+piclist: stamp-piclist ; @true
+
+$(SHLIB): stamp-picdir $(OFILES) piclist
+ rm -f $(SHLIB)
+ $(SHLIB_CC) $(SHLIB_CFLAGS) -o $(SHLIB) `cat piclist`
+
+# We make a link from libbfd.so to libbfd.so.VERSION for linking, and
+# also a link from libTARGET-bfd.so.VERSION for running.
+$(SHLINK): $(SHLIB)
+ ts=lib`echo $(SHLIB) | sed -e 's/^lib//' | sed -e '$(program_transform_name)'`; \
+ if [ "$$ts" != "$(SHLIB)" ]; then \
+ rm -f $$ts; \
+ ln -sf $(SHLIB) $$ts; \
+ else true; fi
+ rm -f $(SHLINK)
+ ln -sf $(SHLIB) $(SHLINK)
+
+# This target creates libTARGET-bfd.so.VERSION as a symlink to
+# libbfd.so.VERSION. It is used on SunOS, which does not have SONAME.
+stamp-tshlink: $(SHLIB)
+ tf=lib`echo $(SHLIB) | sed -e 's/^lib//' | sed '$(program_transform_name)'`; \
+ if [ "$$tf" != "$(SHLIB)" ]; then \
+ rm -f $$tf; \
+ ln -sf $(SHLIB) $$tf; \
+ else true; fi
+ touch stamp-tshlink
+
+# When compiling archures.c and targets.c, supply the default target
+# info from configure.
+
+targets.o: targets.c Makefile
+ if [ -n "$(PICFLAG)" ]; then \
+ $(CC) -c $(PICFLAG) $(TDEFAULTS) $(ALL_CFLAGS) $(srcdir)/targets.c -o pic/targets.o; \
+ else true; fi
+ $(CC) -c $(TDEFAULTS) $(ALL_CFLAGS) $(srcdir)/targets.c
+
+archures.o: archures.c Makefile
+ if [ -n "$(PICFLAG)" ]; then \
+ $(CC) -c $(PICFLAG) $(TDEFAULTS) $(ALL_CFLAGS) $(srcdir)/archures.c -o pic/archures.o; \
+ else true; fi
+ $(CC) -c $(TDEFAULTS) $(ALL_CFLAGS) $(srcdir)/archures.c
+
+elf32-target.h : elfxx-target.h
+ rm -f elf32-target.h
+ sed -e s/NN/32/g < $(srcdir)/elfxx-target.h > elf32-target.new
+ mv -f elf32-target.new elf32-target.h
+
+elf64-target.h : elfxx-target.h
+ rm -f elf64-target.h
+ sed -e s/NN/64/g < $(srcdir)/elfxx-target.h > elf64-target.new
+ mv -f elf64-target.new elf64-target.h
+
+subdir_do: force
+ @for i in $(DODIRS); do \
+ if [ -d ./$$i ] ; then \
+ if (cd ./$$i; \
+ $(MAKE) $(FLAGS_TO_PASS) $(DO)) ; then true ; \
+ else exit 1 ; fi ; \
+ else true ; fi ; \
+ done
+
+tags etags: TAGS
+
+TAGS: force
+ etags $(INCDIR)/*.h $(srcdir)/*.h $(srcdir)/*.c
+
+do_mostlyclean:
+ rm -f *.o *~ core *.E *.p *.ip aout-params.h gen-aout config.log \
+ pic/*.o
+do_clean: do_mostlyclean
+ rm -f libbfd.a TAGS bfd.h stmp-bfd.h ofiles stamp-ofiles \
+ elf32-target.h elf64-target.h $(SHLIB) $(SHLINK) \
+ piclist stamp-piclist
+do_distclean: do_clean
+ rm -f Makefile config.status config.cache config.h stamp-h
+ rm -rf pic stamp-picdir
+do_maintainer_clean: do_distclean
+ rm -f $(srcdir)/bfd-in2.h $(srcdir)/libbfd.h $(srcdir)/libcoff.h
+
+mostlyclean: do_mostlyclean
+ $(MAKE) subdir_do DO=mostlyclean "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+clean: do_clean
+ $(MAKE) subdir_do DO=clean "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+distclean:
+ $(MAKE) subdir_do DO=distclean "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+ $(MAKE) do_distclean
+clobber maintainer-clean realclean:
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ $(MAKE) subdir_do DO=maintainer-clean "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS)
+ $(MAKE) do_maintainer_clean
+
+BFD_H_DEPS= $(INCDIR)/ansidecl.h $(INCDIR)/obstack.h
+LOCAL_H_DEPS= libbfd.h sysdep.h config.h
+$(BFD_LIBS): $(BFD_H) $(BFD_H_DEPS) $(LOCAL_H_DEPS)
+$(BFD_MACHINES): $(BFD_H) $(BFD_H_DEPS) $(LOCAL_H_DEPS)
+$(BFD_BACKENDS): $(BFD_H) $(BFD_H_DEPS) $(LOCAL_H_DEPS)
+$(OPTIONAL_BACKENDS): $(BFD_H) $(BFD_H_DEPS) $(LOCAL_H_DEPS)
+
+# Get around a Sun Make bug in SunOS 4.1.1 with VPATH
+cpu-i386.o:cpu-i386.c
+cpu-z8k.o: cpu-z8k.c
+cpu-h8500.o: cpu-h8500.c
+cpu-we32k.o: cpu-we32k.c
+
+saber:
+ #suppress 65 on bfd_map_over_sections
+ #suppress 66 on bfd_map_over_sections
+ #suppress 67 on bfd_map_over_sections
+ #suppress 68 on bfd_map_over_sections
+ #suppress 69 on bfd_map_over_sections
+ #suppress 70 on bfd_map_over_sections
+ #suppress 110 in bfd_map_over_sections
+ #suppress 112 in bfd_map_over_sections
+ #suppress 530
+ #suppress 590 in swap_exec_header
+ #suppress 590 in _bfd_dummy_core_file_matches_executable_p
+ #suppress 590 in bfd_dont_truncate_arname
+ #suppress 590 on ignore
+ #suppress 590 on abfd
+ #setopt load_flags $(CFLAGS)
+ #load $(CFILES)
+
+
+#-----------------------------------------------------------------------------
+# 'STANDARD' GNU/960 TARGETS BELOW THIS POINT
+#
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#-----------------------------------------------------------------------------
+
+ver960.c: FORCE
+ rm -f ver960.c
+ echo "char ${TARG}_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+ @V=`cat VERSION` ; \
+ MAJ=`sed 's/\..*//' VERSION` ; \
+ MIN=`sed 's/.*\.//' VERSION` ; \
+ V=$$MAJ.`expr $$MIN + 1` ; \
+ rm -f VERSION ; \
+ echo $$V >VERSION ; \
+ echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+force:
+
+install: $(ALLLIBS)
+ for f in $(ALLLIBS); do \
+ if [ "$$f" = "stamp-tshlink" ]; then \
+ continue; \
+ fi; \
+ tf=lib`echo $$f | sed -e 's/^lib//' | sed '$(program_transform_name)'`; \
+ rm -f $(libdir)/$$tf; \
+ if [ "$$f" = "$(SHLINK)" ]; then \
+ ts=lib`echo $(SHLIB) | sed -e 's/^lib//' | sed '$(program_transform_name)'`; \
+ ln -sf $$ts $(libdir)/$$tf; \
+ elif [ "$$f" = "$(SHLIB)" ]; then \
+ $(INSTALL_PROGRAM) $$f $(libdir)/$$tf; \
+ else \
+ $(INSTALL_DATA) $$f $(libdir)/$$tf; \
+ $(RANLIB) $(libdir)/$$tf; \
+ chmod a-x $(libdir)/$$tf; \
+ fi; \
+ done
+# Install BFD include file, and others that it needs. Install them
+# both in GCC's include directory, and in the system include dir
+# if configured as $(oldincludedir) -- which it usually isnt.
+ $(INSTALL_DATA) $(BFD_H) $(includedir)/bfd.h
+ $(INSTALL_DATA) $(INCDIR)/ansidecl.h $(includedir)/ansidecl.h
+ $(INSTALL_DATA) $(INCDIR)/bfdlink.h $(includedir)/bfdlink.h
+ $(INSTALL_DATA) $(INCDIR)/obstack.h $(includedir)/obstack.h
+ -if test -z "$(oldincludedir)"; then true; else \
+ test -d $(oldincludedir) || mkdir $(oldincludedir); \
+ $(INSTALL_DATA) $(BFD_H) $(oldincludedir)/bfd.h; \
+ $(INSTALL_DATA) $(INCDIR)/ansidecl.h $(oldincludedir)/ansidecl.h; \
+ $(INSTALL_DATA) $(INCDIR)/bfdlink.h $(oldincludedir)/bfdlink.h; \
+ $(INSTALL_DATA) $(INCDIR)/obstack.h $(oldincludedir)/obstack.h; \
+ $(MAKE) subdir_do DO=install "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS); \
+ fi
+
+Makefile: Makefile.in config.status
+ CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+config.h: stamp-h ; @true
+stamp-h: config.in config.status
+ CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status
+
+config.status: configure configure.host config.bfd
+ $(SHELL) config.status --recheck
+
+# Have to get rid of .dep1 here so that "$?" later includes all of $(CFILES).
+.dep: dep.sed $(CFILES) $(HFILES) bfd.h
+ rm -f .dep1
+ $(MAKE) DEP=$(DEP) .dep1
+ sed -f dep.sed <.dep1 >.dep
+
+# This rule really wants a mkdep that runs "gcc -MM".
+# The NetBSD mkdep overwrites any existing file contents, and doesn't insert
+# the "DO NOT DELETE" line.
+# Other mkdep versions require a file that already exists, and do insert it.
+# Hence the weirdness....
+.dep1: $(CFILES)
+ rm -f .dep2 .dep2a
+ echo '# DO NOT DELETE THIS LINE -- mkdep uses it.' > .dep2
+ echo > .dep2a
+ $(DEP) -f .dep2a $(ALL_CFLAGS) $?
+ sed -e '/DO NOT DELETE/d' -e '/^$$/d' < .dep2a >> .dep2
+ rm -f .dep2a
+ $(srcdir)/../move-if-change .dep2 .dep1
+
+dep.sed: dep-in.sed config.status
+ sed <$(srcdir)/dep-in.sed >dep.sed \
+ -e 's!@BFD_H@!$(BFD_H)!' \
+ -e 's!@INCDIR@!$(INCDIR)!' \
+ -e 's!@SRCDIR@!$(srcdir)!'
+
+dep: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < Makefile > tmp-Makefile
+ cat .dep >> tmp-Makefile
+ $(srcdir)/../move-if-change tmp-Makefile Makefile
+
+dep-in: .dep
+ sed -e '/^..DO NOT DELETE THIS LINE/,$$d' < $(srcdir)/Makefile.in > tmp-Makefile.in
+ cat .dep >> tmp-Makefile.in
+ $(srcdir)/../move-if-change tmp-Makefile.in $(srcdir)/Makefile.in
+
+host-aout.o: Makefile
+
+# The following program can be used to generate a simple config file
+# which can be folded into an h-XXX file for a new host, with some editing.
+aout-params.h: gen-aout
+ ./gen-aout host > aout-params.h
+gen-aout: $(srcdir)/gen-aout.c Makefile
+ $(CC) -o gen-aout $(CFLAGS) $(LFLAGS) $(srcdir)/gen-aout.c
+
+BFDIN_H= $(srcdir)/bfd-in2.h
+
+$(BFD_H): stmp-bfd.h ; @true
+
+stmp-bfd.h : $(srcdir)/bfd-in2.h Makefile
+ rm -f bfd.h-new
+ sed -e 's/@WORDSIZE@/$(WORDSIZE)/' \
+ -e "s/@VERSION@/`cat $(srcdir)/VERSION`/" \
+ -e 's/@BFD_HOST_64BIT_LONG@/@HOST_64BIT_LONG@/' \
+ < $(srcdir)/bfd-in2.h \
+ > bfd.h-new
+ $(srcdir)/../move-if-change bfd.h-new $(BFD_H)
+ touch stmp-bfd.h
+
+# Could really use a "copy-if-change"...
+headers:
+ (cd $(docdir); $(MAKE) protos $(FLAGS_TO_PASS))
+ cp $(docdir)/bfd.h bfd-in2.h-new
+ $(srcdir)/../move-if-change bfd-in2.h-new $(srcdir)/bfd-in2.h
+ cp $(docdir)/libbfd.h libbfd.h-new
+ $(srcdir)/../move-if-change libbfd.h-new $(srcdir)/libbfd.h
+ cp $(docdir)/libcoff.h libcoff.h-new
+ $(srcdir)/../move-if-change libcoff.h-new $(srcdir)/libcoff.h
+
+# The rules for the generated header files are here so that people can
+# type `make bfd-in2.h' if they remove it. They are not run by default.
+$(srcdir)/bfd-in2.h:
+ (cd $(docdir); $(MAKE) bfd.h $(FLAGS_TO_PASS))
+ cp $(docdir)/bfd.h bfd-in2.h-new
+ $(srcdir)/../move-if-change bfd-in2.h-new $(srcdir)/bfd-in2.h
+$(srcdir)/libbfd.h:
+ (cd $(docdir); $(MAKE) libbfd.h $(FLAGS_TO_PASS))
+ cp $(docdir)/libbfd.h libbfd.h-new
+ $(srcdir)/../move-if-change libbfd.h-new $(srcdir)/libbfd.h
+$(srcdir)/libcoff.h:
+ (cd $(docdir); $(MAKE) libcoff.h $(FLAGS_TO_PASS))
+ cp $(docdir)/libcoff.h libcoff.h-new
+ $(srcdir)/../move-if-change libcoff.h-new $(srcdir)/libcoff.h
+
+bfd.info:
+ (cd $(docdir); $(MAKE) bfd.info $(FLAGS_TO_PASS))
+
+bfd.dvi:
+ (cd $(docdir); $(MAKE) bfd.dvi $(FLAGS_TO_PASS))
+
+bfd.ps:
+ (cd $(docdir); $(MAKE) bfd.ps $(FLAGS_TO_PASS))
+
+
+$(OFILES): stamp-picdir
+
+stamp-picdir:
+ if [ -n "$(PICFLAG)" ] && [ ! -d pic ]; then \
+ mkdir pic; \
+ else true; fi
+ touch stamp-picdir
+
+# What appears below is generated by a hacked mkdep using gcc -MM.
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+archive.o: archive.c $(INCDIR)/aout/ar.h $(INCDIR)/aout/ranlib.h
+archures.o: archures.c
+bfd.o: bfd.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/sym.h libcoff.h libecoff.h $(INCDIR)/coff/ecoff.h \
+ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+ $(INCDIR)/elf/external.h
+cache.o: cache.c
+coffgen.o: coffgen.c $(INCDIR)/coff/internal.h libcoff.h \
+ $(INCDIR)/bfdlink.h
+corefile.o: corefile.c
+format.o: format.c
+init.o: init.c
+libbfd.o: libbfd.c
+opncls.o: opncls.c
+reloc.o: reloc.c $(INCDIR)/bfdlink.h
+section.o: section.c
+syms.o: syms.c $(INCDIR)/bfdlink.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def
+targets.o: targets.c
+hash.o: hash.c
+linker.o: linker.c $(INCDIR)/bfdlink.h genlink.h
+elf.o: elf.c $(INCDIR)/bfdlink.h elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h
+srec.o: srec.c $(INCDIR)/libiberty.h
+binary.o: binary.c
+tekhex.o: tekhex.c $(INCDIR)/libiberty.h
+ihex.o: ihex.c $(INCDIR)/libiberty.h
+stab-syms.o: stab-syms.c libaout.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab.def
+cpu-a29k.o: cpu-a29k.c
+cpu-alpha.o: cpu-alpha.c
+cpu-arm.o: cpu-arm.c
+cpu-h8300.o: cpu-h8300.c
+cpu-h8500.o: cpu-h8500.c
+cpu-hppa.o: cpu-hppa.c
+cpu-i386.o: cpu-i386.c
+cpu-i860.o: cpu-i860.c
+cpu-i960.o: cpu-i960.c
+cpu-m68k.o: cpu-m68k.c
+cpu-m88k.o: cpu-m88k.c
+cpu-mips.o: cpu-mips.c
+cpu-ns32k.o: cpu-ns32k.c
+cpu-powerpc.o: cpu-powerpc.c
+cpu-rs6000.o: cpu-rs6000.c
+cpu-sh.o: cpu-sh.c
+cpu-sparc.o: cpu-sparc.c
+cpu-vax.o: cpu-vax.c
+cpu-we32k.o: cpu-we32k.c
+cpu-w65.o: cpu-w65.c
+cpu-z8k.o: cpu-z8k.c
+aout-adobe.o: aout-adobe.c $(INCDIR)/aout/adobe.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def libaout.h $(INCDIR)/bfdlink.h
+aout-ns32k.o: aout-ns32k.c $(INCDIR)/aout/aout64.h \
+ libaout.h $(INCDIR)/bfdlink.h
+aout0.o: aout0.c aoutf1.h $(INCDIR)/aout/sun4.h libaout.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h aout-target.h
+aout32.o: aout32.c aoutx.h $(INCDIR)/bfdlink.h libaout.h \
+ $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def \
+ $(INCDIR)/aout/ar.h
+bout.o: bout.c $(INCDIR)/bfdlink.h genlink.h $(INCDIR)/bout.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def libaout.h
+cf-i386lynx.o: cf-i386lynx.c coff-i386.c $(INCDIR)/coff/i386.h \
+ $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+cf-m68klynx.o: cf-m68klynx.c coff-m68k.c $(INCDIR)/coff/m68k.h \
+ $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+cf-sparclynx.o: cf-sparclynx.c coff-sparc.c $(INCDIR)/coff/sparc.h \
+ $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+coff-a29k.o: coff-a29k.c $(INCDIR)/coff/a29k.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-apollo.o: coff-apollo.c $(INCDIR)/coff/apollo.h \
+ $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+coff-arm.o: coff-arm.c $(INCDIR)/coff/arm.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-aux.o: coff-aux.c $(INCDIR)/coff/aux-coff.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/m68k.h coff-m68k.c libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+coff-h8300.o: coff-h8300.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/h8300.h \
+ $(INCDIR)/coff/internal.h libcoff.h coffcode.h coffswap.h
+coff-h8500.o: coff-h8500.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/h8500.h \
+ $(INCDIR)/coff/internal.h libcoff.h coffcode.h coffswap.h
+coff-i386.o: coff-i386.c $(INCDIR)/coff/i386.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-i860.o: coff-i860.c $(INCDIR)/coff/i860.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-go32.o: coff-go32.c coff-i386.c $(INCDIR)/coff/i386.h \
+ $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+coff-i960.o: coff-i960.c $(INCDIR)/coff/i960.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-m68k.o: coff-m68k.c $(INCDIR)/coff/m68k.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-m88k.o: coff-m88k.c $(INCDIR)/coff/m88k.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-mips.o: coff-mips.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/coff/mips.h libcoff.h libecoff.h coffswap.h \
+ ecoffswap.h
+coff-pmac.o: coff-pmac.c coff-rs6000.c $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/rs6000.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+coff-rs6000.o: coff-rs6000.c $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/rs6000.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+coff-sh.o: coff-sh.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/sh.h \
+ $(INCDIR)/coff/internal.h libcoff.h coffcode.h coffswap.h
+coff-sparc.o: coff-sparc.c $(INCDIR)/coff/sparc.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-u68k.o: coff-u68k.c coff-m68k.c $(INCDIR)/coff/m68k.h \
+ $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h \
+ coffcode.h coffswap.h
+coff-we32k.o: coff-we32k.c $(INCDIR)/coff/we32k.h $(INCDIR)/coff/internal.h \
+ libcoff.h $(INCDIR)/bfdlink.h coffcode.h coffswap.h
+coff-w65.o: coff-w65.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/w65.h \
+ $(INCDIR)/coff/internal.h libcoff.h coffcode.h coffswap.h
+coff-z8k.o: coff-z8k.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/z8k.h \
+ $(INCDIR)/coff/internal.h libcoff.h coffcode.h coffswap.h
+cofflink.o: cofflink.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h \
+ libcoff.h
+ecoff.o: ecoff.c $(INCDIR)/bfdlink.h $(INCDIR)/aout/ar.h \
+ $(INCDIR)/aout/ranlib.h $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def \
+ libaout.h $(INCDIR)/aout/aout64.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \
+ libcoff.h libecoff.h
+ecofflink.o: ecofflink.c $(INCDIR)/bfdlink.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/coff/internal.h $(INCDIR)/coff/sym.h \
+ $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h
+elf32-gen.o: elf32-gen.c elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ elf32-target.h
+elf32-hppa.o: elf32-hppa.c $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ elf32-hppa.h libhppa.h $(INCDIR)/elf/hppa.h hppa_stubs.h \
+ elf32-target.h
+elf32-i386.o: elf32-i386.c $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ elf32-target.h
+elf32-i860.o: elf32-i860.c elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ elf32-target.h
+elf32-m68k.o: elf32-m68k.c $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ elf32-target.h
+elf32-m88k.o: elf32-m88k.c elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ elf32-target.h
+elf32-mips.o: elf32-mips.c $(INCDIR)/bfdlink.h genlink.h \
+ elf-bfd.h $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h \
+ $(INCDIR)/elf/external.h $(INCDIR)/elf/mips.h $(INCDIR)/coff/sym.h \
+ $(INCDIR)/coff/symconst.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/ecoff.h $(INCDIR)/coff/mips.h ecoffswap.h \
+ elf32-target.h
+elf32-ppc.o: elf32-ppc.c $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/elf/ppc.h elf32-target.h
+elf32-sparc.o: elf32-sparc.c $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ $(INCDIR)/elf/sparc.h elf32-target.h
+elf32.o: elf32.c elfcode.h $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ elfcore.h elflink.h
+elflink.o: elflink.c $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h
+hp300hpux.o: hp300hpux.c $(INCDIR)/aout/hp300hpux.h \
+ aoutx.h $(INCDIR)/bfdlink.h libaout.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h \
+ aout-target.h
+som.o: som.c
+i386aout.o: i386aout.c libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+i386bsd.o: i386bsd.c libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+i386freebsd.o: i386freebsd.c freebsd.h libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+i386linux.o: i386linux.c $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h libaout.h \
+ $(INCDIR)/bfdlink.h aout-target.h
+i386lynx.o: i386lynx.c libaout.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/aout/aout64.h aout-target.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+i386msdos.o: i386msdos.c libaout.h $(INCDIR)/bfdlink.h
+i386netbsd.o: i386netbsd.c netbsd.h libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+i386mach3.o: i386mach3.c $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h libaout.h \
+ $(INCDIR)/bfdlink.h aout-target.h
+i386os9k.o: i386os9k.c $(INCDIR)/bfdlink.h libaout.h \
+ $(INCDIR)/os9k.h
+ieee.o: ieee.c $(INCDIR)/ieee.h libieee.h
+m68klinux.o: m68klinux.c $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h libaout.h \
+ $(INCDIR)/bfdlink.h aout-target.h
+m68klynx.o: m68klynx.c libaout.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/aout/aout64.h aout-target.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+m68knetbsd.o: m68knetbsd.c netbsd.h libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+m88kmach3.o: m88kmach3.c libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+mipsbsd.o: mipsbsd.c libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+newsos3.o: newsos3.c $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h libaout.h \
+ $(INCDIR)/bfdlink.h aout-target.h
+nlm.o: nlm.c libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+ $(INCDIR)/nlm/external.h
+nlm32-i386.o: nlm32-i386.c $(INCDIR)/nlm/i386-ext.h \
+ libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+ $(INCDIR)/nlm/external.h nlmswap.h nlm-target.h
+nlm32-sparc.o: nlm32-sparc.c $(INCDIR)/nlm/sparc32-ext.h \
+ libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+ $(INCDIR)/nlm/external.h nlmswap.h nlm-target.h
+nlm32-ppc.o: nlm32-ppc.c $(INCDIR)/nlm/ppc-ext.h libnlm.h \
+ $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h $(INCDIR)/nlm/external.h \
+ nlmswap.h nlm-target.h
+nlm32.o: nlm32.c nlmcode.h libnlm.h $(INCDIR)/nlm/common.h \
+ $(INCDIR)/nlm/internal.h $(INCDIR)/nlm/external.h
+ns32knetbsd.o: ns32knetbsd.c netbsd.h libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+oasys.o: oasys.c $(INCDIR)/oasys.h liboasys.h
+pc532-mach.o: pc532-mach.c libaout.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/aout/aout64.h aout-target.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+pe-arm.o: pe-arm.c coff-arm.c $(INCDIR)/coff/arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \
+ $(INCDIR)/bfdlink.h coffcode.h peicode.h
+pei-arm.o: pei-arm.c coff-arm.c $(INCDIR)/coff/arm.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \
+ $(INCDIR)/bfdlink.h coffcode.h peicode.h
+pe-i386.o: pe-i386.c coff-i386.c $(INCDIR)/coff/i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \
+ $(INCDIR)/bfdlink.h coffcode.h peicode.h
+pei-i386.o: pei-i386.c coff-i386.c $(INCDIR)/coff/i386.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \
+ $(INCDIR)/bfdlink.h coffcode.h peicode.h
+pe-ppc.o: pe-ppc.c coff-ppc.c $(INCDIR)/coff/powerpc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \
+ $(INCDIR)/bfdlink.h coffcode.h peicode.h
+pei-ppc.o: pei-ppc.c coff-ppc.c $(INCDIR)/coff/powerpc.h \
+ $(INCDIR)/coff/internal.h $(INCDIR)/coff/pe.h libcoff.h \
+ $(INCDIR)/bfdlink.h coffcode.h peicode.h
+reloc16.o: reloc16.c $(INCDIR)/bfdlink.h genlink.h \
+ $(INCDIR)/coff/internal.h libcoff.h
+sparclynx.o: sparclynx.c $(INCDIR)/aout/sun4.h libaout.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h aout-target.h
+sparcnetbsd.o: sparcnetbsd.c netbsd.h libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+sunos.o: sunos.c $(INCDIR)/bfdlink.h libaout.h aoutf1.h \
+ $(INCDIR)/aout/sun4.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h aout-target.h
+versados.o: versados.c $(INCDIR)/libiberty.h
+xcofflink.o: xcofflink.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h \
+ libcoff.h
+aout64.o: aout64.c aoutx.h $(INCDIR)/bfdlink.h libaout.h \
+ $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def \
+ $(INCDIR)/aout/ar.h
+coff-alpha.o: coff-alpha.c $(INCDIR)/bfdlink.h $(INCDIR)/coff/internal.h \
+ $(INCDIR)/coff/sym.h $(INCDIR)/coff/symconst.h $(INCDIR)/coff/ecoff.h \
+ $(INCDIR)/coff/alpha.h $(INCDIR)/aout/ar.h libcoff.h \
+ libecoff.h coffswap.h ecoffswap.h
+demo64.o: demo64.c aoutf1.h $(INCDIR)/aout/sun4.h libaout.h \
+ $(INCDIR)/bfdlink.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h aout-target.h
+elf64-gen.o: elf64-gen.c elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ elf64-target.h
+elf64-sparc.o: elf64-sparc.c elf-bfd.h $(INCDIR)/elf/common.h \
+ $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h $(INCDIR)/bfdlink.h \
+ $(INCDIR)/elf/sparc.h elf64-target.h
+elf64.o: elf64.c elfcode.h $(INCDIR)/bfdlink.h elf-bfd.h \
+ $(INCDIR)/elf/common.h $(INCDIR)/elf/internal.h $(INCDIR)/elf/external.h \
+ elfcore.h elflink.h
+nlm32-alpha.o: nlm32-alpha.c $(INCDIR)/nlm/alpha-ext.h \
+ libnlm.h $(INCDIR)/nlm/common.h $(INCDIR)/nlm/internal.h \
+ $(INCDIR)/nlm/external.h nlmswap.h nlm-target.h
+nlm64.o: nlm64.c nlmcode.h libnlm.h $(INCDIR)/nlm/common.h \
+ $(INCDIR)/nlm/internal.h $(INCDIR)/nlm/external.h
+aix386-core.o: aix386-core.c $(INCDIR)/coff/i386.h \
+ $(INCDIR)/coff/internal.h libcoff.h $(INCDIR)/bfdlink.h
+hpux-core.o: hpux-core.c
+irix-core.o: irix-core.c
+lynx-core.o: lynx-core.c
+osf-core.o: osf-core.c
+trad-core.o: trad-core.c libaout.h $(INCDIR)/bfdlink.h
+cisco-core.o: cisco-core.c
+i386dynix.o: i386dynix.c $(INCDIR)/aout/dynix3.h aoutx.h \
+ $(INCDIR)/bfdlink.h libaout.h $(INCDIR)/aout/aout64.h \
+ $(INCDIR)/aout/stab_gnu.h $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h \
+ aout-target.h
+hp300bsd.o: hp300bsd.c libaout.h $(INCDIR)/bfdlink.h \
+ aout-target.h $(INCDIR)/aout/aout64.h $(INCDIR)/aout/stab_gnu.h \
+ $(INCDIR)/aout/stab.def $(INCDIR)/aout/ar.h
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/contrib/gdb/bfd/PORTING b/contrib/gdb/bfd/PORTING
new file mode 100644
index 0000000..c8bfd77
--- /dev/null
+++ b/contrib/gdb/bfd/PORTING
@@ -0,0 +1,83 @@
+ Preliminary Notes on Porting BFD
+ --------------------------------
+
+The 'host' is the system a tool runs *on*.
+The 'target' is the system a tool runs *for*, i.e.
+a tool can read/write the binaries of the target.
+
+Porting to a new host
+---------------------
+Pick a name for your host. Call that <host>.
+(<host> might be sun4, ...)
+Create a file hosts/<host>.mh.
+
+Porting to a new target
+-----------------------
+Pick a name for your target. Call that <target>.
+Call the name for your CPU architecture <cpu>.
+You need to create <target>.c and config/<target>.mt,
+and add a case for it to a case statements in bfd/configure.host and
+bfd/config.bfd, which associates each canonical host type with a BFD
+host type (used as the base of the makefile fragment names), and to the
+table in bfd/configure.in which associates each target vector with
+the .o files it uses.
+
+config/<target>.mt is a Makefile fragment.
+The following is usually enough:
+DEFAULT_VECTOR=<target>_vec
+SELECT_ARCHITECTURES=bfd_<cpu>_arch
+
+See the list of cpu types in archures.c, or "ls cpu-*.c".
+If your architecture is new, you need to add it to the tables
+in bfd/archures.c, opcodes/configure.in, and binutils/objdump.c.
+
+For more information about .mt and .mh files, see config/README.
+
+The file <target>.c is the hard part. It implements the
+bfd_target <target>_vec, which includes pointers to
+functions that do the actual <target>-specific methods.
+
+Porting to a <target> that uses the a.out binary format
+-------------------------------------------------------
+
+In this case, the include file aout-target.h probaby does most
+of what you need. The program gen-aout generates <target>.c for
+you automatically for many a.out systems. Do:
+ make gen-aout
+ ./gen-aout <target> > <target>.c
+(This only works if you are building on the target ("native").
+If you must make a cross-port from scratch, copy the most
+similar existing file that includes aout-target.h, and fix what is wrong.)
+
+Check the parameters in <target>.c, and fix anything that is wrong.
+(Also let us know about it; perhaps we can improve gen-aout.c.)
+
+TARGET_IS_BIG_ENDIAN_P
+ Should be defined if <target> is big-endian.
+
+N_HEADER_IN_TEXT(x)
+ See discussion in ../include/aout/aout64.h.
+
+BYTES_IN_WORD
+ Number of bytes per word. (Usually 4 but can be 8.)
+
+ARCH
+ Number of bits per word. (Usually 32, but can be 64.)
+
+ENTRY_CAN_BE_ZERO
+ Define if the extry point (start address of an
+ executable program) can be 0x0.
+
+TEXT_START_ADDR
+ The address of the start of the text segemnt in
+ virtual memory. Normally, the same as the entry point.
+
+TARGET_PAGE_SIZE
+
+SEGMENT_SIZE
+ Usually, the same as the TARGET_PAGE_SIZE.
+ Alignment needed for the data segment.
+
+TARGETNAME
+ The name of the target, for run-time lookups.
+ Usually "a.out-<target>"
diff --git a/contrib/gdb/bfd/TODO b/contrib/gdb/bfd/TODO
new file mode 100644
index 0000000..08a3641
--- /dev/null
+++ b/contrib/gdb/bfd/TODO
@@ -0,0 +1,25 @@
+Things that still need to be done: -*- Text -*-
+
+ o - A source of space lossage is that all the target-dependent code
+ is in a single bfd_target structure. Hence all the code for
+ *writing* object files is still pulled into all the applications
+ that only care about *reading* (gdb, nm, objdump), while gas has
+ to carry along all the unneded baggage for reading objects. And
+ so on. This would be a substantial change, and the payoff would
+ not all that great (essentially none if bfd is used as a shared
+ library).
+
+ o - The storage needed by BFD data structures is also larger than strictly
+ needed. This may be difficult to do much about.
+
+ o - implement bfd_abort, which should close the bfd but not alter the
+ filesystem.
+
+ o - update the bfd doc; write a how-to-write-a-backend doc, take out
+ the stupid quips and fill in all the blanks.
+
+ o - upgrade the reloc handling as per Steve's suggestion.
+
+
+
+
diff --git a/contrib/gdb/bfd/VERSION b/contrib/gdb/bfd/VERSION
new file mode 100644
index 0000000..9ddf6b5
--- /dev/null
+++ b/contrib/gdb/bfd/VERSION
@@ -0,0 +1 @@
+cygnus-2.6
diff --git a/contrib/gdb/bfd/acconfig.h b/contrib/gdb/bfd/acconfig.h
new file mode 100644
index 0000000..647798c
--- /dev/null
+++ b/contrib/gdb/bfd/acconfig.h
@@ -0,0 +1,19 @@
+
+/* Whether malloc must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Whether free must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_FREE
+@TOP@
+
+/* Do we need to use the b modifier when opening binary files? */
+#undef USE_BINARY_FOPEN
+
+/* Name of host specific header file to include in trad-core.c. */
+#undef TRAD_HEADER
+
+/* Define only if <sys/procfs.h> is available *and* it defines prstatus_t. */
+#undef HAVE_SYS_PROCFS_H
+
+/* Do we really want to use mmap if it's available? */
+#undef USE_MMAP
diff --git a/contrib/gdb/bfd/aclocal.m4 b/contrib/gdb/bfd/aclocal.m4
new file mode 100644
index 0000000..1f5027e
--- /dev/null
+++ b/contrib/gdb/bfd/aclocal.m4
@@ -0,0 +1,43 @@
+dnl See whether we need to use fopen-bin.h rather than fopen-same.h.
+AC_DEFUN(BFD_BINARY_FOPEN,
+[AC_REQUIRE([AC_CANONICAL_SYSTEM])
+case "${host}" in
+changequote(,)dnl
+i[345]86-*-msdos* | i[345]86-*-go32* | *-*-cygwin32)
+changequote([,])dnl
+ AC_DEFINE(USE_BINARY_FOPEN) ;;
+esac])dnl
+
+dnl Get a default for CC_FOR_BUILD to put into Makefile.
+AC_DEFUN(BFD_CC_FOR_BUILD,
+[# Put a plausible default for CC_FOR_BUILD in Makefile.
+AC_REQUIRE([AC_C_CROSS])dnl
+if test -z "$CC_FOR_BUILD"; then
+ if test "x$cross_compiling" = "xno"; then
+ CC_FOR_BUILD='$(CC)'
+ else
+ CC_FOR_BUILD=gcc
+ fi
+fi
+AC_SUBST(CC_FOR_BUILD)])dnl
+
+dnl See whether we need a declaration for a function.
+AC_DEFUN(BFD_NEED_DECLARATION,
+[AC_MSG_CHECKING([whether $1 must be declared])
+AC_CACHE_VAL(bfd_cv_decl_needed_$1,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif],
+[char *(*pfn) = (char *(*)) $1],
+bfd_cv_decl_needed_$1=no, bfd_cv_decl_needed_$1=yes)])
+AC_MSG_RESULT($bfd_cv_decl_needed_$1)
+if test $bfd_cv_decl_needed_$1 = yes; then
+ bfd_tr_decl=NEED_DECLARATION_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ AC_DEFINE_UNQUOTED($bfd_tr_decl)
+fi
+])dnl
diff --git a/contrib/gdb/bfd/aix386-core.c b/contrib/gdb/bfd/aix386-core.c
new file mode 100644
index 0000000..21ec9a6
--- /dev/null
+++ b/contrib/gdb/bfd/aix386-core.c
@@ -0,0 +1,285 @@
+/* BFD back-end for AIX on PS/2 core files.
+ This was based on trad-core.c, which was written by John Gilmore of
+ Cygnus Support.
+ Copyright 1988, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Written by Minh Tran-Le <TRANLE@INTELLICORP.COM>.
+ Converted to back end form by Ian Lance Taylor <ian@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/i386.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#include <stdio.h>
+#include <stddef.h>
+#include <signal.h>
+
+#include <errno.h>
+
+#if defined (_AIX) && defined (_I386)
+#define NOCHECKS /* this is for coredump.h */
+#define _h_USER /* avoid including user.h from coredump.h */
+#include <uinfo.h>
+#include <sys/i386/coredump.h>
+#endif /* _AIX && _I386 */
+
+/* maybe this could work on some other i386 but I have not tried it
+ * mtranle@paris - Tue Sep 24 12:49:35 1991
+ */
+
+#ifndef COR_MAGIC
+# define COR_MAGIC "core"
+#endif
+
+/* need this cast because ptr is really void * */
+#define core_hdr(bfd) \
+ (((bfd->tdata.trad_core_data))->hdr)
+#define core_section(bfd,n) \
+ (((bfd)->tdata.trad_core_data)->sections[n])
+#define core_regsec(bfd) \
+ (((bfd)->tdata.trad_core_data)->reg_section)
+#define core_reg2sec(bfd) \
+ (((bfd)->tdata.trad_core_data)->reg2_section)
+
+/* These are stored in the bfd's tdata */
+struct trad_core_struct {
+ struct corehdr *hdr; /* core file header */
+ asection *reg_section;
+ asection *reg2_section;
+ asection *sections[MAX_CORE_SEGS];
+};
+
+static const bfd_target *
+aix386_core_file_p (abfd)
+ bfd *abfd;
+{
+ int i,n;
+ unsigned char longbuf[4]; /* Raw bytes of various header fields */
+ int core_size = sizeof (struct corehdr);
+ struct corehdr *core;
+ struct mergem {
+ struct trad_core_struct coredata;
+ struct corehdr internal_core;
+ } *mergem;
+
+ if (bfd_read ((PTR)longbuf, 1, sizeof (longbuf), abfd) != sizeof (longbuf))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (strncmp(longbuf,COR_MAGIC,4)) return 0;
+
+ if (bfd_seek (abfd, 0L, false) < 0) return 0;
+
+ mergem = (struct mergem *)bfd_zalloc (abfd, sizeof (struct mergem));
+ if (mergem == NULL)
+ return 0;
+
+ core = &mergem->internal_core;
+
+ if ((bfd_read ((PTR) core, 1, core_size, abfd)) != core_size)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ bfd_release (abfd, (char *)mergem);
+ return 0;
+ }
+
+ set_tdata (abfd, &mergem->coredata);
+ core_hdr (abfd) = core;
+
+ /* create the sections. This is raunchy, but bfd_close wants to reclaim
+ them */
+ core_regsec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_regsec (abfd) == NULL)
+ {
+ loser:
+ bfd_release (abfd, (char *)mergem);
+ return 0;
+ }
+ core_reg2sec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_reg2sec (abfd) == NULL)
+ {
+ loser1:
+ bfd_release (abfd, core_regsec (abfd));
+ goto loser;
+ }
+
+ for (i=0, n=0 ; (i < MAX_CORE_SEGS) && (core->cd_segs[i].cs_type) ; i++)
+ {
+ if (core->cd_segs[i].cs_offset == 0)
+ continue;
+ core_section (abfd,n) =
+ (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_section (abfd,n) == NULL)
+ {
+ int j;
+ if (n > 0)
+ {
+ for (j=0; j < n; j++)
+ bfd_release (abfd, core_section(abfd, j));
+ }
+ bfd_release (abfd, (char *)mergem);
+ goto loser1;
+ }
+
+ switch (core->cd_segs[i].cs_type)
+ {
+ case COR_TYPE_DATA:
+ core_section (abfd, n)->name = ".data";
+ core_section (abfd, n)->flags = (SEC_ALLOC + SEC_LOAD +
+ SEC_HAS_CONTENTS);
+ break;
+ case COR_TYPE_STACK:
+ core_section (abfd, n)->name = ".stack";
+ core_section (abfd, n)->flags = (SEC_ALLOC + SEC_LOAD +
+ SEC_HAS_CONTENTS);
+ break;
+ case COR_TYPE_LIBDATA:
+ core_section (abfd, n)->name = ".libdata";
+ core_section (abfd, n)->flags = (SEC_ALLOC + SEC_HAS_CONTENTS);
+ break;
+ case COR_TYPE_WRITE:
+ core_section (abfd, n)->name = ".writeable";
+ core_section (abfd, n)->flags = (SEC_ALLOC + SEC_HAS_CONTENTS);
+ break;
+ case COR_TYPE_MSC:
+ core_section (abfd, n)->name = ".misc";
+ core_section (abfd, n)->flags = (SEC_ALLOC + SEC_HAS_CONTENTS);
+ break;
+ default:
+ core_section (abfd, n)->name = ".unknown";
+ core_section (abfd, n)->flags = (SEC_ALLOC + SEC_HAS_CONTENTS);
+ break;
+ }
+ core_section (abfd, n)->_raw_size = core->cd_segs[i].cs_len;
+ core_section (abfd, n)->vma = core->cd_segs[i].cs_address;
+ core_section (abfd, n)->filepos = core->cd_segs[i].cs_offset;
+ core_section (abfd, n)->alignment_power = 2;
+ core_section (abfd, n)->next = NULL;
+ if (n > 0)
+ core_section (abfd, (n-1))->next = core_section (abfd, n);
+
+ abfd->section_count = ++n;
+ }
+
+ core_regsec (abfd)->name = ".reg";
+ core_reg2sec (abfd)->name = ".reg2";
+
+ core_regsec (abfd)->flags = SEC_HAS_CONTENTS;
+ core_reg2sec (abfd)->flags = SEC_HAS_CONTENTS;
+
+ core_regsec (abfd)->_raw_size = sizeof(core->cd_regs);
+ core_reg2sec (abfd)->_raw_size = sizeof(core->cd_fpregs);
+
+ core_regsec (abfd)->vma = -1;
+ core_reg2sec (abfd)->vma = -1;
+
+ /* We'll access the regs afresh in the core file, like any section: */
+ core_regsec (abfd)->filepos = (file_ptr)offsetof(struct corehdr,cd_regs[0]);
+ core_reg2sec (abfd)->filepos = (file_ptr)offsetof(struct corehdr,
+ cd_fpregs);
+
+ /* add the 2 reg fake sections to abfd */
+ abfd->section_count += 2;
+ abfd->sections = core_regsec (abfd);
+ core_regsec (abfd)->next = core_reg2sec (abfd);
+ core_reg2sec (abfd)->next = core_section (abfd, 0);
+
+ return abfd->xvec;
+}
+
+static char *
+aix386_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return core_hdr (abfd)->cd_comm;
+}
+
+static int
+aix386_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_hdr (abfd)->cd_cursig;
+}
+
+static boolean
+aix386_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd;
+ bfd *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this
+ point */
+}
+
+/* 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 ((PROTO(bfd_vma, (*), ( const bfd_byte *))) swap_abort )
+#define NO_GETS ((PROTO(bfd_signed_vma, (*), (const bfd_byte *))) swap_abort )
+#define NO_PUT ((PROTO(void, (*), (bfd_vma, bfd_byte *))) swap_abort )
+
+const bfd_target aix386_core_vec =
+ {
+ "aix386-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIANG_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_GETS, NO_PUT,
+ NO_GET, NO_GETS, NO_PUT,
+ NO_GET, NO_GETS, NO_PUT, /* data */
+ NO_GET, NO_GETS, NO_PUT,
+ NO_GET, NO_GETS, NO_PUT,
+ NO_GET, NO_GETS, NO_PUT, /* hdrs */
+
+ {_bfd_dummy_target, _bfd_dummy_target,
+ _bfd_dummy_target, aix386_core_file_p},
+ {bfd_false, bfd_false, /* bfd_create_object */
+ bfd_false, bfd_false},
+ {bfd_false, bfd_false, /* bfd_write_contents */
+ bfd_false, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (aix386),
+ 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
+};
diff --git a/contrib/gdb/bfd/aout-adobe.c b/contrib/gdb/bfd/aout-adobe.c
new file mode 100644
index 0000000..36d230d
--- /dev/null
+++ b/contrib/gdb/bfd/aout-adobe.c
@@ -0,0 +1,528 @@
+/* BFD back-end for a.out.adobe binaries.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Written by Cygnus Support. Based on bout.c.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "aout/adobe.h"
+
+#include "aout/stab_gnu.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+extern const bfd_target a_out_adobe_vec; /* Forward decl */
+
+static const bfd_target *aout_adobe_callback PARAMS ((bfd *));
+
+extern boolean aout_32_slurp_symbol_table PARAMS ((bfd *abfd));
+extern boolean aout_32_write_syms PARAMS ((bfd *));
+static void aout_adobe_write_section PARAMS ((bfd *abfd, sec_ptr sect));
+
+/* Swaps the information in an executable header taken from a raw byte
+ stream memory image, into the internal exec_header structure. */
+
+void aout_adobe_swap_exec_header_in
+ PARAMS ((bfd *abfd, struct external_exec *raw_bytes,
+ struct internal_exec *execp));
+
+void
+aout_adobe_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;
+
+ /* 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);
+ execp->a_data = GET_WORD (abfd, bytes->e_data);
+ execp->a_bss = GET_WORD (abfd, bytes->e_bss);
+ execp->a_syms = GET_WORD (abfd, bytes->e_syms);
+ execp->a_entry = GET_WORD (abfd, bytes->e_entry);
+ execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
+ execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
+}
+
+/* Swaps the information in an internal exec header structure into the
+ supplied buffer ready for writing to disk. */
+
+PROTO(void, aout_adobe_swap_exec_header_out,
+ (bfd *abfd,
+ struct internal_exec *execp,
+ struct external_exec *raw_bytes));
+void
+aout_adobe_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;
+
+ /* Now fill in fields in the raw data, from the fields in the exec struct. */
+ bfd_h_put_32 (abfd, execp->a_info , bytes->e_info);
+ PUT_WORD (abfd, execp->a_text , bytes->e_text);
+ PUT_WORD (abfd, execp->a_data , bytes->e_data);
+ PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
+ PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
+ PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
+ PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
+ PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
+}
+
+
+static const bfd_target *
+aout_adobe_object_p (abfd)
+ bfd *abfd;
+{
+ struct internal_exec anexec;
+ struct external_exec exec_bytes;
+ char *targ;
+
+ if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ anexec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info);
+
+ /* Normally we just compare for the magic number.
+ However, a bunch of Adobe tools aren't fixed up yet; they generate
+ files using ZMAGIC(!).
+ If the environment variable GNUTARGET is set to "a.out.adobe", we will
+ take just about any a.out file as an Adobe a.out file. FIXME! */
+
+ if (N_BADMAG (anexec)) {
+ extern char *getenv ();
+
+ targ = getenv ("GNUTARGET");
+ if (targ && !strcmp (targ, a_out_adobe_vec.name))
+ ; /* Just continue anyway, if specifically set to this format */
+ else
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+ }
+
+ aout_adobe_swap_exec_header_in (abfd, &exec_bytes, &anexec);
+ return aout_32_some_aout_object_p (abfd, &anexec, aout_adobe_callback);
+}
+
+
+/* Finish up the opening of a b.out file for reading. Fill in all the
+ fields that are not handled by common code. */
+
+static const bfd_target *
+aout_adobe_callback (abfd)
+ bfd *abfd;
+{
+ struct internal_exec *execp = exec_hdr (abfd);
+ asection *sect;
+ struct external_segdesc ext[1];
+ char *section_name;
+ char try_again[30]; /* name and number */
+ char *newname;
+ int trynum;
+ flagword flags;
+
+ /* Architecture and machine type -- unknown in this format. */
+ bfd_set_arch_mach(abfd, bfd_arch_unknown, 0);
+
+ /* The positions of the string table and symbol table. */
+ obj_str_filepos (abfd) = N_STROFF (*execp);
+ obj_sym_filepos (abfd) = N_SYMOFF (*execp);
+
+ /* Suck up the section information from the file, one section at a time. */
+
+ for (;;) {
+ if (bfd_read ((PTR) ext, 1, sizeof (*ext), abfd) != sizeof (*ext)) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+ switch (ext->e_type[0]) {
+ case N_TEXT:
+ section_name = ".text";
+ flags = SEC_CODE | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
+ break;
+
+ case N_DATA:
+ section_name = ".data";
+ flags = SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_HAS_CONTENTS;
+ break;
+
+ case N_BSS:
+ section_name = ".bss";
+ flags = SEC_DATA | SEC_HAS_CONTENTS;
+ break;
+
+ case 0:
+ goto no_more_sections;
+
+ default:
+ (*_bfd_error_handler)
+ ("%s: Unknown section type in a.out.adobe file: %x\n",
+ bfd_get_filename (abfd), ext->e_type[0]);
+ goto no_more_sections;
+ }
+
+ /* First one is called ".text" or whatever; subsequent ones are
+ ".text1", ".text2", ... */
+
+ bfd_set_error (bfd_error_no_error);
+ sect = bfd_make_section (abfd, section_name);
+ trynum = 0;
+ while (!sect) {
+ if (bfd_get_error () != bfd_error_no_error)
+ return 0; /* Some other error -- slide into the sunset */
+ sprintf (try_again, "%s%d", section_name, ++trynum);
+ sect = bfd_make_section (abfd, try_again);
+ }
+
+ /* Fix the name, if it is a sprintf'd name. */
+ if (sect->name == try_again) {
+ newname = (char *) bfd_zalloc(abfd, strlen (sect->name));
+ if (newname == NULL)
+ return 0;
+ strcpy (newname, sect->name);
+ sect->name = newname;
+ }
+
+ /* Now set the section's attributes. */
+ bfd_set_section_flags (abfd, sect, flags);
+ sect->_raw_size = ((ext->e_size[0] << 8) /* Assumed big-endian */
+ | ext->e_size[1] << 8)
+ | ext->e_size[2];
+ sect->_cooked_size = sect->_raw_size;
+ sect->vma = bfd_h_get_32 (abfd, ext->e_virtbase);
+ sect->filepos = bfd_h_get_32 (abfd, ext->e_filebase);
+ /* FIXME XXX alignment? */
+
+ /* Set relocation information for first section of each type. */
+ if (trynum == 0) switch (ext->e_type[0]) {
+ case N_TEXT:
+ sect->rel_filepos = N_TRELOFF (*execp);
+ sect->reloc_count = execp->a_trsize;
+ break;
+
+ case N_DATA:
+ sect->rel_filepos = N_DRELOFF (*execp);
+ sect->reloc_count = execp->a_drsize;
+ break;
+ }
+ }
+no_more_sections:
+
+ adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
+ adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
+ adata(abfd).page_size = 1; /* Not applicable. */
+ adata(abfd).segment_size = 1; /* Not applicable. */
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+
+ return abfd->xvec;
+}
+
+struct bout_data_struct {
+ struct aoutdata a;
+ struct internal_exec e;
+};
+
+static boolean
+aout_adobe_mkobject (abfd)
+ bfd *abfd;
+{
+ struct bout_data_struct *rawptr;
+
+ rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, sizeof (struct bout_data_struct));
+ if (rawptr == NULL)
+ return false;
+
+ abfd->tdata.bout_data = rawptr;
+ exec_hdr (abfd) = &rawptr->e;
+
+ adata(abfd).reloc_entry_size = sizeof (struct reloc_std_external);
+ adata(abfd).symbol_entry_size = sizeof (struct external_nlist);
+ adata(abfd).page_size = 1; /* Not applicable. */
+ adata(abfd).segment_size = 1; /* Not applicable. */
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+
+ return true;
+}
+
+
+static boolean
+aout_adobe_write_object_contents (abfd)
+ bfd *abfd;
+{
+ struct external_exec swapped_hdr;
+ static struct external_segdesc sentinel[1]; /* Initialized to zero */
+ asection *sect;
+
+ exec_hdr (abfd)->a_info = ZMAGIC;
+
+ /* Calculate text size as total of text sections, etc. */
+
+ exec_hdr (abfd)->a_text = 0;
+ exec_hdr (abfd)->a_data = 0;
+ exec_hdr (abfd)->a_bss = 0;
+ exec_hdr (abfd)->a_trsize = 0;
+ exec_hdr (abfd)->a_drsize = 0;
+
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_CODE) {
+ exec_hdr (abfd)->a_text += sect->_raw_size;
+ exec_hdr (abfd)->a_trsize += sect->reloc_count *
+ sizeof (struct reloc_std_external);
+ } else if (sect->flags & SEC_DATA) {
+ exec_hdr (abfd)->a_data += sect->_raw_size;
+ exec_hdr (abfd)->a_drsize += sect->reloc_count *
+ sizeof (struct reloc_std_external);
+ } else if (sect->flags & SEC_ALLOC && !(sect->flags & SEC_LOAD)) {
+ exec_hdr (abfd)->a_bss += sect->_raw_size;
+ }
+ }
+
+ exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd)
+ * sizeof (struct external_nlist);
+ exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
+
+ aout_adobe_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || (bfd_write ((PTR) &swapped_hdr, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE))
+ return false;
+
+ /* Now write out the section information. Text first, data next, rest
+ afterward. */
+
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_CODE) {
+ aout_adobe_write_section (abfd, sect);
+ }
+ }
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_DATA) {
+ aout_adobe_write_section (abfd, sect);
+ }
+ }
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (!(sect->flags & (SEC_CODE|SEC_DATA))) {
+ aout_adobe_write_section (abfd, sect);
+ }
+ }
+
+ /* Write final `sentinel` section header (with type of 0). */
+ if (bfd_write ((PTR) sentinel, 1, sizeof (*sentinel), abfd)
+ != sizeof (*sentinel))
+ return false;
+
+ /* Now write out reloc info, followed by syms and strings */
+ if (bfd_get_symcount (abfd) != 0)
+ {
+ if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*exec_hdr(abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ if (! aout_32_write_syms (abfd))
+ return false;
+
+ if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*exec_hdr(abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_CODE) {
+ if (!aout_32_squirt_out_relocs (abfd, sect))
+ return false;
+ }
+ }
+
+ if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*exec_hdr(abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_DATA) {
+ if (!aout_32_squirt_out_relocs (abfd, sect))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+static void
+aout_adobe_write_section (abfd, sect)
+ bfd *abfd;
+ sec_ptr sect;
+{
+ /* FIXME XXX */
+}
+
+static boolean
+aout_adobe_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ file_ptr section_start;
+ sec_ptr sect;
+
+ if (abfd->output_has_begun == false) { /* set by bfd.c handler */
+
+ /* Assign file offsets to sections. Text sections are first, and
+ are contiguous. Then data sections. Everything else at the end. */
+
+ section_start = N_TXTOFF (ignore<-->me);
+
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_CODE) {
+ sect->filepos = section_start;
+ /* FIXME: Round to alignment */
+ section_start += sect->_raw_size;
+ }
+ }
+
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_DATA) {
+ sect->filepos = section_start;
+ /* FIXME: Round to alignment */
+ section_start += sect->_raw_size;
+ }
+ }
+
+ for (sect = abfd->sections; sect; sect = sect->next) {
+ if (sect->flags & SEC_HAS_CONTENTS &&
+ !(sect->flags & (SEC_CODE|SEC_DATA))) {
+ sect->filepos = section_start;
+ /* FIXME: Round to alignment */
+ section_start += sect->_raw_size;
+ }
+ }
+ }
+
+ /* regardless, once we know what we're doing, we might as well get going */
+ if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
+ return false;
+
+ if (count != 0) {
+ return (bfd_write ((PTR)location, 1, count, abfd) == count) ?true:false;
+ }
+ return true;
+}
+
+static boolean
+aout_adobe_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
+ || arch == bfd_arch_m68k)
+ return true;
+
+ return false;
+}
+
+static int
+aout_adobe_sizeof_headers (ignore_abfd, ignore)
+ bfd *ignore_abfd;
+ boolean ignore;
+{
+ return sizeof(struct internal_exec);
+}
+
+
+
+
+/* Build the transfer vector for Adobe A.Out files. */
+
+#define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
+
+#define aout_32_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+#define aout_32_bfd_reloc_type_lookup \
+ ((reloc_howto_type *(*) \
+ PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
+
+#define aout_32_set_arch_mach aout_adobe_set_arch_mach
+#define aout_32_set_section_contents aout_adobe_set_section_contents
+
+#define aout_32_sizeof_headers aout_adobe_sizeof_headers
+#define aout_32_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define aout_32_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
+#define aout_32_bfd_relax_section bfd_generic_relax_section
+#define aout_32_bfd_link_hash_table_create \
+ _bfd_generic_link_hash_table_create
+#define aout_32_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define aout_32_bfd_final_link _bfd_generic_final_link
+#define aout_32_bfd_link_split_section _bfd_generic_link_split_section
+
+const bfd_target a_out_adobe_vec =
+{
+ "a.out.adobe", /* name */
+ bfd_target_aout_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is unknown (big assumed) */
+ BFD_ENDIAN_BIG, /* hdr byte order is big */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT ),
+ /* section flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_DATA | SEC_RELOC),
+ '_', /* symbol leading char */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+
+ 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, aout_adobe_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, aout_adobe_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, aout_adobe_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (aout_32),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
+ BFD_JUMP_TABLE_SYMBOLS (aout_32),
+ BFD_JUMP_TABLE_RELOCS (aout_32),
+ BFD_JUMP_TABLE_WRITE (aout_32),
+ BFD_JUMP_TABLE_LINK (aout_32),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/aout-arm.c b/contrib/gdb/bfd/aout-arm.c
new file mode 100644
index 0000000..978664a
--- /dev/null
+++ b/contrib/gdb/bfd/aout-arm.c
@@ -0,0 +1,548 @@
+/* BFD back-end for raw ARM a.out binaries.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#define N_TXTADDR(x) \
+ ((N_MAGIC(x) == NMAGIC) ? 0x8000 : \
+ (N_MAGIC(x) != ZMAGIC) ? 0 : \
+ (N_SHARED_LIB(x)) ? ((x).a_entry & ~(TARGET_PAGE_SIZE - 1)) : \
+ TEXT_START_ADDR)
+
+#define TEXT_START_ADDR 0x8000
+#define TARGET_PAGE_SIZE 0x8000
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_arm
+
+#define MY(OP) CAT(aoutarm_,OP)
+#define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) && \
+ (((x).a_info & ~006000) != OMAGIC) && \
+ ((x).a_info != NMAGIC))
+#define N_MAGIC(x) ((x).a_info & ~07200)
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "assert.h"
+
+#define MYARM(OP) CAT(aoutarm_,OP)
+reloc_howto_type *MYARM(bfd_reloc_type_lookup)
+ PARAMS((bfd *, bfd_reloc_code_real_type));
+static boolean MYARM(write_object_contents) PARAMS((bfd *));
+
+/* Avoid multiple defininitions from aoutx if supporting standarad a.out
+ as well as our own. */
+#define NAME(x,y) CAT3(aoutarm,_32_,y)
+
+#define MY_bfd_reloc_type_lookup aoutarm_bfd_reloc_type_lookup
+
+#include "libaout.h"
+#include "aout/aout64.h"
+
+static bfd_reloc_status_type
+MY(fix_pcrel_26_done) PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+static bfd_reloc_status_type
+MY(fix_pcrel_26) PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+static void MY(swap_std_reloc_in) PARAMS ((bfd *, struct reloc_std_external *,
+ arelent *, asymbol **,
+ bfd_size_type));
+void MY(swap_std_reloc_out) PARAMS ((bfd *, arelent *,
+ struct reloc_std_external *));
+
+reloc_howto_type MY(howto_table)[] =
+{
+ /* 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),
+ HOWTO (3, 2, 2, 26, true, 0, complain_overflow_signed, MY(fix_pcrel_26),
+ "ARM26", true, 0x00ffffff, 0x00ffffff, true),
+ HOWTO (4, 0, 0, 8, true, 0, complain_overflow_signed, 0, "DISP8", true,
+ 0x000000ff, 0x000000ff, true),
+ HOWTO (5, 0, 1, 16, true, 0, complain_overflow_signed, 0, "DISP16", true,
+ 0x0000ffff, 0x0000ffff, true),
+ HOWTO (6, 0, 2, 32, true, 0, complain_overflow_signed, 0, "DISP32", true,
+ 0xffffffff, 0xffffffff, true),
+ HOWTO (7, 2, 2, 26, false, 0, complain_overflow_signed,
+ MY(fix_pcrel_26_done), "ARM26D", true, 0x0, 0x0,
+ false),
+ {-1},
+ HOWTO (9, 0, -1, 16, false, 0, complain_overflow_bitfield, 0, "NEG16", true,
+ 0x0000ffff, 0x0000ffff, false),
+ HOWTO (10, 0, -2, 32, false, 0, complain_overflow_bitfield, 0, "NEG32", true,
+ 0xffffffff, 0xffffffff, false)
+};
+
+#define RELOC_ARM_BITS_NEG_BIG ((unsigned int) 0x08)
+#define RELOC_ARM_BITS_NEG_LITTLE ((unsigned int) 0x10)
+
+reloc_howto_type *
+MY(reloc_howto)(abfd, rel, r_index, r_extern, r_pcrel)
+ bfd *abfd;
+ struct reloc_std_external *rel;
+ int *r_index;
+ int *r_extern;
+ int *r_pcrel;
+{
+ unsigned int r_length;
+ unsigned int r_pcrel_done;
+ unsigned int r_neg;
+ int index;
+
+ *r_pcrel = 0;
+ if (bfd_header_big_endian (abfd))
+ {
+ *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_done = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
+ r_neg = (0 != (rel->r_type[0] & RELOC_ARM_BITS_NEG_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_done = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
+ r_neg = (0 != (rel->r_type[0] & RELOC_ARM_BITS_NEG_LITTLE));
+ r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
+ >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
+ }
+ index = r_length + 4 * r_pcrel_done + 8 * r_neg;
+ if (index == 3)
+ *r_pcrel = 1;
+
+ return MY(howto_table) + index;
+}
+
+#define MY_reloc_howto(BFD, REL, IN, EX, PC) \
+ MY(reloc_howto) (BFD, REL, &IN, &EX, &PC)
+
+void
+MY(put_reloc)(abfd, r_extern, r_index, value, howto, reloc)
+ bfd *abfd;
+ int r_extern;
+ int r_index;
+ long value;
+ reloc_howto_type *howto;
+ struct reloc_std_external *reloc;
+{
+ unsigned int r_length;
+ int r_pcrel;
+ int r_neg;
+
+ PUT_WORD (abfd, value, reloc->r_address);
+ r_length = howto->size ; /* Size as a power of two */
+
+ /* Special case for branch relocations. */
+ if (howto->type == 3 || howto->type == 7)
+ r_length = 3;
+
+ r_pcrel = howto->type & 4; /* PC Relative done? */
+ r_neg = howto->type & 8; /* Negative relocation */
+ if (bfd_header_big_endian (abfd))
+ {
+ reloc->r_index[0] = r_index >> 16;
+ reloc->r_index[1] = r_index >> 8;
+ reloc->r_index[2] = r_index;
+ reloc->r_type[0] =
+ ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
+ | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
+ | (r_neg ? RELOC_ARM_BITS_NEG_BIG : 0)
+ | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
+ }
+ else
+ {
+ reloc->r_index[2] = r_index >> 16;
+ reloc->r_index[1] = r_index >> 8;
+ reloc->r_index[0] = r_index;
+ reloc->r_type[0] =
+ ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
+ | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
+ | (r_neg ? RELOC_ARM_BITS_NEG_LITTLE : 0)
+ | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
+ }
+}
+
+#define MY_put_reloc(BFD, EXT, IDX, VAL, HOWTO, RELOC) \
+ MY(put_reloc)(BFD, EXT, IDX, VAL, HOWTO, RELOC)
+
+void
+MY(relocatable_reloc)(howto, abfd, reloc, amount, r_addr)
+ reloc_howto_type *howto;
+ bfd *abfd;
+ struct reloc_std_external *reloc;
+ bfd_vma *amount;
+ bfd_vma r_addr;
+{
+ if (howto->type == 3)
+ {
+ if (reloc->r_type[0]
+ & (bfd_header_big_endian (abfd)
+ ? RELOC_STD_BITS_EXTERN_BIG : RELOC_STD_BITS_EXTERN_LITTLE))
+ {
+ /* The reloc is still external, so don't modify anything. */
+ *amount = 0;
+ }
+ else
+ {
+ *amount -= r_addr;
+ /* Change the r_pcrel value -- on the ARM, this bit is set once the
+ relocation is done. */
+ if (bfd_header_big_endian (abfd))
+ reloc->r_type[0] |= RELOC_STD_BITS_PCREL_BIG;
+ else
+ reloc->r_type[0] |= RELOC_STD_BITS_PCREL_LITTLE;
+ }
+ }
+ else if (howto->type == 7)
+ *amount = 0;
+}
+
+#define MY_relocatable_reloc(HOW, BFD, REL, AMOUNT, ADDR) \
+ MY(relocatable_reloc)(HOW, BFD, REL, &(AMOUNT), ADDR)
+
+static bfd_reloc_status_type
+MY(fix_pcrel_26_done) (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* This is dead simple at present. */
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+MY(fix_pcrel_26) (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_vma relocation;
+ bfd_size_type addr = reloc_entry->address;
+ long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+ bfd_reloc_status_type flag = bfd_reloc_ok;
+
+ /* If this is an undefined symbol, return error */
+ if (symbol->section == &bfd_und_section
+ && (symbol->flags & BSF_WEAK) == 0)
+ return output_bfd ? bfd_reloc_ok : bfd_reloc_undefined;
+
+ /* If the sections are different, and we are doing a partial relocation,
+ just ignore it for now. */
+ if (symbol->section->name != input_section->name
+ && output_bfd != (bfd *)NULL)
+ return bfd_reloc_ok;
+
+ relocation = (target & 0x00ffffff) << 2;
+ relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */
+ relocation += symbol->value;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+ relocation -= input_section->output_section->vma;
+ relocation -= input_section->output_offset;
+ relocation -= addr;
+ if (relocation & 3)
+ return bfd_reloc_overflow;
+
+ /* Check for overflow */
+ if (relocation & 0x02000000)
+ {
+ if ((relocation & ~0x03ffffff) != ~0x03ffffff)
+ flag = bfd_reloc_overflow;
+ }
+ else if (relocation & ~0x03ffffff)
+ flag = bfd_reloc_overflow;
+
+ target &= ~0x00ffffff;
+ target |= (relocation >> 2) & 0x00ffffff;
+ bfd_put_32 (abfd, target, (bfd_byte *) data + addr);
+
+ /* Now the ARM magic... Change the reloc type so that it is marked as done.
+ Strictly this is only necessary if we are doing a partial relocation. */
+ reloc_entry->howto = &MY(howto_table)[7];
+
+ return flag;
+}
+
+reloc_howto_type *
+MY(bfd_reloc_type_lookup)(abfd,code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+#define ASTD(i,j) case i: return &MY(howto_table)[j]
+ if (code == BFD_RELOC_CTOR)
+ switch (bfd_get_arch_info (abfd)->bits_per_address)
+ {
+ case 32:
+ code = BFD_RELOC_32;
+ break;
+ default: return (CONST struct reloc_howto_struct *) 0;
+ }
+
+ switch (code)
+ {
+ ASTD (BFD_RELOC_16, 1);
+ ASTD (BFD_RELOC_32, 2);
+ ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
+ ASTD (BFD_RELOC_8_PCREL, 4);
+ ASTD (BFD_RELOC_16_PCREL, 5);
+ ASTD (BFD_RELOC_32_PCREL, 6);
+ default: return (CONST struct reloc_howto_struct *) 0;
+ }
+}
+
+#define MY_swap_std_reloc_in MY(swap_std_reloc_in)
+#define MY_swap_std_reloc_out MY(swap_std_reloc_out)
+#define MY_get_section_contents _bfd_generic_get_section_contents
+/* #define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create */
+/* #define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols */
+/* #define MY_bfd_final_link _bfd_generic_final_link */
+
+#include "aoutx.h"
+
+static void
+MY_swap_std_reloc_in (abfd, bytes, cache_ptr, symbols, symcount)
+ bfd *abfd;
+ struct reloc_std_external *bytes;
+ arelent *cache_ptr;
+ asymbol **symbols;
+ bfd_size_type symcount;
+{
+ int r_index;
+ int r_extern;
+ unsigned int r_length;
+ int r_pcrel;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+
+ cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
+
+ cache_ptr->howto = MY_reloc_howto (abfd, bytes, r_index, r_extern, r_pcrel);
+
+ MOVE_ADDRESS (0);
+}
+
+void
+MY_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);
+ int r_extern;
+ int r_length;
+ int r_pcrel;
+ int r_neg = 0; /* Negative relocs use the BASEREL bit. */
+ asection *output_section = sym->section->output_section;
+
+ PUT_WORD(abfd, g->address, natptr->r_address);
+
+ r_length = g->howto->size ; /* Size as a power of two */
+ if (r_length < 0)
+ {
+ r_length = -r_length;
+ r_neg = 1;
+ }
+
+ r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
+
+ /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the
+ relocation has been done already (Only for the 26-bit one I think)???!!!
+ */
+
+ if (g->howto->type == 3)
+ {
+ r_length = 3;
+ r_pcrel = 0;
+ }
+ else if (g->howto->type == 7)
+ {
+ r_length = 3;
+ r_pcrel = 1;
+ }
+
+
+#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 */
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here
+ */
+
+ if (bfd_is_com_section (output_section)
+ || output_section == &bfd_abs_section
+ || output_section == &bfd_und_section)
+ {
+ if (bfd_abs_section.symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+ r_extern = 1;
+ r_index = (*(g->sym_ptr_ptr))->KEEPIT;
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd))
+ {
+ natptr->r_index[0] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[2] = r_index;
+ natptr->r_type[0] =
+ ( (r_extern ? RELOC_STD_BITS_EXTERN_BIG: 0)
+ | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG: 0)
+ | (r_neg ? RELOC_ARM_BITS_NEG_BIG: 0)
+ | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
+ }
+ else
+ {
+ natptr->r_index[2] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[0] = r_index;
+ natptr->r_type[0] =
+ ( (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE: 0)
+ | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE: 0)
+ | (r_neg ? RELOC_ARM_BITS_NEG_LITTLE: 0)
+ | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
+ }
+}
+
+#define MY_BFD_TARGET
+
+#include "aout-target.h"
+
+const bfd_target aout_arm_little_vec =
+{
+ "a.out-arm-little", /* name */
+ bfd_target_aout_flavour,
+ BFD_ENDIAN_LITTLE, /* target byte order (little) */
+ BFD_ENDIAN_LITTLE, /* target headers byte order (little) */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ MY_symbol_leading_char,
+ AR_PAD_CHAR, /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+ {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, MY_core_file_p},
+ {bfd_false, MY_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, MY_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ 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,
+};
+
+const bfd_target aout_arm_big_vec =
+{
+ "a.out-arm-big", /* name */
+ bfd_target_aout_flavour,
+ BFD_ENDIAN_BIG, /* target byte order (big) */
+ BFD_ENDIAN_BIG, /* target headers byte order (big) */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ MY_symbol_leading_char,
+ AR_PAD_CHAR, /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, MY_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, MY_core_file_p},
+ {bfd_false, MY_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, MY_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ 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,
+};
diff --git a/contrib/gdb/bfd/aout-encap.c b/contrib/gdb/bfd/aout-encap.c
new file mode 100644
index 0000000..c25f903
--- /dev/null
+++ b/contrib/gdb/bfd/aout-encap.c
@@ -0,0 +1,236 @@
+/* BFD back-end for a.out files encapsulated with COFF headers.
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* THIS MODULE IS NOT FINISHED. IT PROBABLY DOESN'T EVEN COMPILE. */
+
+#if 0
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define TEXT_START_ADDR 0
+#define BYTES_IN_WORD 4
+#endif
+
+#include "bfd.h"
+#include <sysdep.h>
+#include "libbfd.h"
+#include <aout/aout64.h>
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+const bfd_target *encap_real_callback ();
+
+const bfd_target *
+encap_object_p (abfd)
+ bfd *abfd;
+{
+ unsigned char magicbuf[4]; /* Raw bytes of magic number from file */
+ unsigned long magic; /* Swapped magic number */
+ short coff_magic;
+ struct external_exec exec_bytes;
+ struct internal_exec exec;
+
+ if (bfd_read ((PTR)magicbuf, 1, sizeof (magicbuf), abfd) !=
+ sizeof (magicbuf))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ coff_magic = bfd_h_get_16 (abfd, magicbuf);
+ if (coff_magic != COFF_MAGIC)
+ return 0; /* Not an encap coff file */
+
+ __header_offset_temp==COFF_MAGIC ? sizeof(struct coffheader) : 0)
+ (fseek ((f), HEADER_OFFSET((f)), 1))
+
+ magic = bfd_h_get_32 (abfd, magicbuf);
+
+ if (N_BADMAG (*((struct internal_exec *) &magic))) return 0;
+
+ struct external_exec exec_bytes;
+ if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+ NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, &exec);
+
+ return aout_32_some_aout_object_p (abfd, &exec, encap_realcallback);
+}
+
+/* Finish up the reading of a encapsulated-coff a.out file header */
+const bfd_target *
+encap_real_callback (abfd)
+ bfd *abfd;
+{
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ MY(callback)(abfd, execp);
+
+ /* If we have a coff header, it can give us better values for
+ text_start and exec_data_start. This is particularly useful
+ for remote debugging of embedded systems. */
+ if (N_FLAGS(exec_aouthdr) & N_FLAGS_COFF_ENCAPSULATE)
+ {
+ struct coffheader ch;
+ int val;
+ val = lseek (execchan, -(sizeof (AOUTHDR) + sizeof (ch)), 1);
+ if (val == -1)
+ perror_with_name (filename);
+ val = myread (execchan, &ch, sizeof (ch));
+ if (val < 0)
+ perror_with_name (filename);
+ text_start = ch.text_start;
+ exec_data_start = ch.data_start;
+ } else
+ {
+ text_start =
+ IS_OBJECT_FILE (exec_aouthdr) ? 0 : N_TXTADDR (exec_aouthdr);
+ exec_data_start = IS_OBJECT_FILE (exec_aouthdr)
+ ? exec_aouthdr.a_text : N_DATADDR (exec_aouthdr);
+ }
+
+ /* Determine the architecture and machine type of the object file. */
+ bfd_default_set_arch_mach(abfd, bfd_arch_m68k, 0); /* FIXME */
+
+ return abfd->xvec;
+}
+
+/* Write an object file in Encapsulated COFF format.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+boolean
+encap_write_object_contents (abfd)
+ bfd *abfd;
+{
+ bfd_size_type data_pad = 0;
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+/****** FIXME: Fragments from the old GNU LD program for dealing with
+ encap coff. */
+struct coffheader coffheader;
+int need_coff_header;
+
+ /* Determine whether to count the header as part of
+ the text size, and initialize the text size accordingly.
+ This depends on the kind of system and on the output format selected. */
+
+ N_SET_MAGIC (outheader, magic);
+#ifdef INITIALIZE_HEADER
+ INITIALIZE_HEADER;
+#endif
+
+ text_size = sizeof (struct exec);
+#ifdef COFF_ENCAPSULATE
+ if (relocatable_output == 0 && file_table[0].just_syms_flag == 0)
+ {
+ need_coff_header = 1;
+ /* set this flag now, since it will change the values of N_TXTOFF, etc */
+ N_SET_FLAGS (outheader, aout_backend_info (abfd)->exec_hdr_flags);
+ text_size += sizeof (struct coffheader);
+ }
+#endif
+
+#ifdef COFF_ENCAPSULATE
+ if (need_coff_header)
+ {
+ /* We are encapsulating BSD format within COFF format. */
+ struct coffscn *tp, *dp, *bp;
+
+ tp = &coffheader.scns[0];
+ dp = &coffheader.scns[1];
+ bp = &coffheader.scns[2];
+
+ strcpy (tp->s_name, ".text");
+ tp->s_paddr = text_start;
+ tp->s_vaddr = text_start;
+ tp->s_size = text_size;
+ tp->s_scnptr = sizeof (struct coffheader) + sizeof (struct exec);
+ tp->s_relptr = 0;
+ tp->s_lnnoptr = 0;
+ tp->s_nreloc = 0;
+ tp->s_nlnno = 0;
+ tp->s_flags = 0x20;
+ strcpy (dp->s_name, ".data");
+ dp->s_paddr = data_start;
+ dp->s_vaddr = data_start;
+ dp->s_size = data_size;
+ dp->s_scnptr = tp->s_scnptr + tp->s_size;
+ dp->s_relptr = 0;
+ dp->s_lnnoptr = 0;
+ dp->s_nreloc = 0;
+ dp->s_nlnno = 0;
+ dp->s_flags = 0x40;
+ strcpy (bp->s_name, ".bss");
+ bp->s_paddr = dp->s_vaddr + dp->s_size;
+ bp->s_vaddr = bp->s_paddr;
+ bp->s_size = bss_size;
+ bp->s_scnptr = 0;
+ bp->s_relptr = 0;
+ bp->s_lnnoptr = 0;
+ bp->s_nreloc = 0;
+ bp->s_nlnno = 0;
+ bp->s_flags = 0x80;
+
+ coffheader.f_magic = COFF_MAGIC;
+ coffheader.f_nscns = 3;
+ /* store an unlikely time so programs can
+ * tell that there is a bsd header
+ */
+ coffheader.f_timdat = 1;
+ coffheader.f_symptr = 0;
+ coffheader.f_nsyms = 0;
+ coffheader.f_opthdr = 28;
+ coffheader.f_flags = 0x103;
+ /* aouthdr */
+ coffheader.magic = ZMAGIC;
+ coffheader.vstamp = 0;
+ coffheader.tsize = tp->s_size;
+ coffheader.dsize = dp->s_size;
+ coffheader.bsize = bp->s_size;
+ coffheader.entry = outheader.a_entry;
+ coffheader.text_start = tp->s_vaddr;
+ coffheader.data_start = dp->s_vaddr;
+ }
+#endif
+
+#ifdef COFF_ENCAPSULATE
+ if (need_coff_header)
+ mywrite (&coffheader, sizeof coffheader, 1, outdesc);
+#endif
+
+#ifndef COFF_ENCAPSULATE
+ padfile (N_TXTOFF (outheader) - sizeof outheader, outdesc);
+#endif
+
+ text_size -= N_TXTOFF (outheader);
+ WRITE_HEADERS(abfd, execp);
+ return true;
+}
+
+#define MY_write_object_content encap_write_object_contents
+#define MY_object_p encap_object_p
+#define MY_exec_hdr_flags N_FLAGS_COFF_ENCAPSULATE
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/aout-ns32k.c b/contrib/gdb/bfd/aout-ns32k.c
new file mode 100644
index 0000000..269e053
--- /dev/null
+++ b/contrib/gdb/bfd/aout-ns32k.c
@@ -0,0 +1,399 @@
+/* BFD back-end for ns32k a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Ian Dall (idall@eleceng.adelaide.edu.au).
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+
+#include "bfd.h"
+#include "aout/aout64.h"
+
+#define MYNS(OP) CAT(ns32kaout_,OP)
+reloc_howto_type *
+MYNS(bfd_reloc_type_lookup)
+ PARAMS((bfd *abfd AND
+ bfd_reloc_code_real_type code));
+
+boolean
+MYNS(write_object_contents)
+ PARAMS((bfd *abfd));
+
+/* Avoid multiple definitions from aoutx if supporting standard a.out format(s)
+ * as well as this one
+ */
+#define NAME(x,y) CAT3(ns32kaout,_32_,y)
+
+void bfd_ns32k_arch PARAMS ((void));
+long ns32k_get_displacement PARAMS ((bfd_byte *buffer, long offset, long size));
+int ns32k_put_displacement PARAMS ((long value, bfd_byte *buffer, long offset, long size));
+long ns32k_get_immediate PARAMS ((bfd_byte *buffer, long offset, long size));
+int ns32k_put_immediate PARAMS ((long value, bfd_byte *buffer, long offset, long size));
+bfd_reloc_status_type
+ ns32k_reloc_disp PARAMS ((bfd *abfd, arelent *reloc_entry,
+ struct symbol_cache_entry *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+bfd_reloc_status_type
+ ns32k_reloc_imm PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ struct symbol_cache_entry *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+bfd_reloc_status_type
+ ns32k_final_link_relocate PARAMS ((reloc_howto_type *howto,
+ bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ bfd_vma address,
+ bfd_vma value,
+ bfd_vma addend ));
+bfd_reloc_status_type
+ ns32k_relocate_contents PARAMS ((reloc_howto_type *howto,
+ bfd *input_bfd,
+ bfd_vma relocation,
+ bfd_byte *location));
+
+#include "libaout.h"
+
+#define MY(OP) MYNS(OP)
+
+#define MY_swap_std_reloc_in MY(swap_std_reloc_in)
+#define MY_swap_std_reloc_out MY(swap_std_reloc_out)
+
+static void
+MY_swap_std_reloc_in PARAMS ((bfd *abfd, struct reloc_std_external *bytes,
+ arelent *cache_ptr, asymbol **symbols,
+ bfd_size_type symcount));
+
+static void
+MY_swap_std_reloc_out PARAMS ((bfd *abfd, arelent *g,
+ struct reloc_std_external *natptr));
+
+/* The ns32k series is ah, unusual, when it comes to relocation.
+ * There are three storage methods for relocateable objects. There
+ * are displacements, immediate operands and ordinary twos complement
+ * data. Of these, only the last fits into the standard relocation
+ * scheme. Immediate operands are stored huffman encoded and
+ * immediate operands are stored big endian (where as the natural byte
+ * order is little endian for this achitecture).
+
+ * Note that the ns32k displacement storage method is orthogonal to
+ * whether the relocation is pc relative or not. The "displacement"
+ * storage scheme is used for essentially all address constants. The
+ * displacement can be relative to zero (absolute displacement),
+ * relative to the pc (pc relative), the stack pointer, the frame
+ * pointer, the static base register and general purpose register etc.
+
+ * For example:
+ *
+ * sym1: .long . # pc relative 2's complement
+ * sym1: .long foo # 2's complement not pc relative
+ *
+ * self: movd @self, r0 # pc relative displacement
+ * movd foo, r0 # non pc relative displacement
+ *
+ * self: movd self, r0 # pc relative immediate
+ * movd foo, r0 # non pc relative immediate
+ *
+ * In addition, for historical reasons the encoding of the relocation types
+ * in the a.out format relocation entries is such that even the relocation
+ * methods which are standard are not encoded the standard way.
+ *
+ */
+
+reloc_howto_type MY(howto_table)[] =
+{
+/* ns32k immediate operands */
+HOWTO(BFD_RELOC_NS32K_IMM_8, 0, 0, 8, false, 0, true,
+ ns32k_reloc_imm, "NS32K_IMM_8",
+ true, 0x000000ff,0x000000ff, false),
+HOWTO(BFD_RELOC_NS32K_IMM_16, 0, 1, 16, false, 0, true,
+ ns32k_reloc_imm, "NS32K_IMM_16",
+ true, 0x0000ffff,0x0000ffff, false),
+HOWTO(BFD_RELOC_NS32K_IMM_32, 0, 2, 32, false, 0, true,
+ ns32k_reloc_imm, "NS32K_IMM_32",
+ true, 0xffffffff,0xffffffff, false),
+HOWTO(BFD_RELOC_NS32K_IMM_8_PCREL, 0, 0, 8, true, 0, false,
+ ns32k_reloc_imm, "PCREL_NS32K_IMM_8",
+ true, 0x000000ff, 0x000000ff, false),
+HOWTO(BFD_RELOC_NS32K_IMM_16_PCREL, 0, 1, 16, true, 0, false,
+ ns32k_reloc_imm, "PCREL_NS32K_IMM_16",
+ true, 0x0000ffff,0x0000ffff, false),
+HOWTO(BFD_RELOC_NS32K_IMM_32_PCREL, 0, 2, 32, true, 0, false,
+ ns32k_reloc_imm, "PCREL_NS32K_IMM_32",
+ true, 0xffffffff,0xffffffff, false),
+
+/* ns32k displacements */
+HOWTO(BFD_RELOC_NS32K_DISP_8, 0, 0, 8, false, 0, true,
+ ns32k_reloc_disp, "NS32K_DISP_8",
+ true, 0x000000ff,0x000000ff, false),
+HOWTO(BFD_RELOC_NS32K_DISP_16, 0, 1, 16, false, 0, true,
+ ns32k_reloc_disp, "NS32K_DISP_16",
+ true, 0x0000ffff, 0x0000ffff, false),
+HOWTO(BFD_RELOC_NS32K_DISP_32, 0, 2, 32, false, 0, true,
+ ns32k_reloc_disp, "NS32K_DISP_32",
+ true, 0xffffffff, 0xffffffff, false),
+HOWTO(BFD_RELOC_NS32K_DISP_8_PCREL, 0, 0, 8, true, 0, false,
+ ns32k_reloc_disp, "PCREL_NS32K_DISP_8",
+ true, 0x000000ff,0x000000ff, false),
+HOWTO(BFD_RELOC_NS32K_DISP_16_PCREL, 0, 1, 16, true, 0, false,
+ ns32k_reloc_disp, "PCREL_NS32K_DISP_16",
+ true, 0x0000ffff,0x0000ffff, false),
+HOWTO(BFD_RELOC_NS32K_DISP_32_PCREL, 0, 2, 32, true, 0, false,
+ ns32k_reloc_disp, "PCREL_NS32K_DISP_32",
+ true, 0xffffffff,0xffffffff, false),
+
+/* Normal 2's complement */
+HOWTO(BFD_RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield,0,
+ "8", true, 0x000000ff,0x000000ff, false),
+HOWTO(BFD_RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield,0,
+ "16", true, 0x0000ffff,0x0000ffff, false),
+HOWTO(BFD_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,
+ "32", true, 0xffffffff,0xffffffff, false),
+HOWTO(BFD_RELOC_8_PCREL, 0, 0, 8, true, 0, complain_overflow_signed, 0,
+ "PCREL_8", true, 0x000000ff,0x000000ff, false),
+HOWTO(BFD_RELOC_16_PCREL, 0, 1, 16, true, 0, complain_overflow_signed, 0,
+ "PCREL_16", true, 0x0000ffff,0x0000ffff, false),
+HOWTO(BFD_RELOC_32_PCREL, 0, 2, 32, true, 0, complain_overflow_signed, 0,
+ "PCREL_32", true, 0xffffffff,0xffffffff, false),
+};
+
+
+#define CTOR_TABLE_RELOC_HOWTO(BFD) (MY(howto_table) + 14)
+
+#define RELOC_STD_BITS_NS32K_TYPE_BIG 0x06
+#define RELOC_STD_BITS_NS32K_TYPE_LITTLE 0x60
+#define RELOC_STD_BITS_NS32K_TYPE_SH_BIG 1
+#define RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE 5
+
+reloc_howto_type *
+MY(reloc_howto)(abfd, rel, r_index, r_extern, r_pcrel)
+ bfd *abfd;
+ struct reloc_std_external *rel;
+ int *r_index;
+ int *r_extern;
+ int *r_pcrel;
+{
+ unsigned int r_length;
+ int r_ns32k_type;
+/* BFD_ASSERT(bfd_header_little_endian (abfd)); */
+ *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_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
+ >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
+ r_ns32k_type = ((rel->r_type[0] & RELOC_STD_BITS_NS32K_TYPE_LITTLE)
+ >> RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
+ return (MY(howto_table) + r_length + 3 * (*r_pcrel) + 6 * r_ns32k_type);
+}
+
+#define MY_reloc_howto(BFD,REL,IN,EX,PC) MY(reloc_howto)(BFD, REL, &IN, &EX, &PC)
+
+void
+MY(put_reloc)(abfd, r_extern, r_index, value, howto, reloc)
+ bfd *abfd;
+ int r_extern;
+ int r_index;
+ long value;
+ reloc_howto_type *howto;
+ struct reloc_std_external *reloc;
+{
+ unsigned int r_length;
+ int r_pcrel;
+ int r_ns32k_type;
+ PUT_WORD (abfd, value, reloc->r_address);
+ r_length = howto->size ; /* Size as a power of two */
+ r_pcrel = (int) howto->pc_relative; /* Relative to PC? */
+ r_ns32k_type = (howto - MY(howto_table) )/6;
+/* BFD_ASSERT (bfd_header_little_endian (abfd)); */
+ reloc->r_index[2] = r_index >> 16;
+ reloc->r_index[1] = r_index >> 8;
+ reloc->r_index[0] = r_index;
+ reloc->r_type[0] =
+ (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0)
+ | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0)
+ | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)
+ | (r_ns32k_type << RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
+}
+
+#define MY_put_reloc(BFD, EXT, IDX, VAL, HOWTO, RELOC) \
+ MY(put_reloc)(BFD, EXT, IDX, VAL, HOWTO, RELOC)
+
+#define STAT_FOR_EXEC
+
+#define MY_final_link_relocate ns32k_final_link_relocate
+#define MY_relocate_contents ns32k_relocate_contents
+
+#include <aoutx.h>
+
+reloc_howto_type *
+ MY(bfd_reloc_type_lookup)(abfd,code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+
+#define ENTRY(i,j) case i: return &MY(howto_table)[j]
+
+ int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
+
+ BFD_ASSERT(ext == 0);
+ if (code == BFD_RELOC_CTOR)
+ switch (bfd_get_arch_info (abfd)->bits_per_address)
+ {
+ case 32:
+ code = BFD_RELOC_32;
+ break;
+ }
+ switch (code)
+ {
+ ENTRY(BFD_RELOC_NS32K_IMM_8, 0);
+ ENTRY(BFD_RELOC_NS32K_IMM_16, 1);
+ ENTRY(BFD_RELOC_NS32K_IMM_32, 2);
+ ENTRY(BFD_RELOC_NS32K_IMM_8_PCREL, 3);
+ ENTRY(BFD_RELOC_NS32K_IMM_16_PCREL, 4);
+ ENTRY(BFD_RELOC_NS32K_IMM_32_PCREL, 5);
+ ENTRY(BFD_RELOC_NS32K_DISP_8, 6);
+ ENTRY(BFD_RELOC_NS32K_DISP_16, 7);
+ ENTRY(BFD_RELOC_NS32K_DISP_32, 8);
+ ENTRY(BFD_RELOC_NS32K_DISP_8_PCREL, 9);
+ ENTRY(BFD_RELOC_NS32K_DISP_16_PCREL, 10);
+ ENTRY(BFD_RELOC_NS32K_DISP_32_PCREL, 11);
+ ENTRY(BFD_RELOC_8, 12);
+ ENTRY(BFD_RELOC_16, 13);
+ ENTRY(BFD_RELOC_32, 14);
+ ENTRY(BFD_RELOC_8_PCREL, 15);
+ ENTRY(BFD_RELOC_16_PCREL, 16);
+ ENTRY(BFD_RELOC_32_PCREL, 17);
+ default: return (reloc_howto_type *) NULL;
+ }
+#undef ENTRY
+}
+
+
+static void
+MY_swap_std_reloc_in (abfd, bytes, cache_ptr, symbols, symcount)
+ bfd *abfd;
+ struct reloc_std_external *bytes;
+ arelent *cache_ptr;
+ asymbol **symbols;
+ bfd_size_type symcount;
+{
+ int r_index;
+ int r_extern;
+ int r_pcrel;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+
+ cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
+
+ /* now the fun stuff */
+
+ cache_ptr->howto = MY_reloc_howto(abfd, bytes, r_index, r_extern, r_pcrel);
+
+ MOVE_ADDRESS(0);
+}
+
+static void
+MY_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);
+ int r_extern;
+ unsigned int r_addend;
+ asection *output_section = sym->section->output_section;
+
+ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
+
+ /* name was clobbered by aout_write_syms to be symbol index */
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ Check for that here. */
+
+ if (bfd_is_com_section (output_section)
+ || output_section == &bfd_abs_section
+ || output_section == &bfd_und_section)
+ {
+ if (bfd_abs_section.symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+ r_extern = 1;
+#undef KEEPIT
+#define KEEPIT udata.i
+ r_index = (*(g->sym_ptr_ptr))->KEEPIT;
+#undef KEEPIT
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ MY_put_reloc (abfd, r_extern, r_index, g->address, g->howto, natptr);
+}
+
+bfd_reloc_status_type
+ns32k_relocate_contents (howto, input_bfd, relocation, location)
+ reloc_howto_type *howto;
+ bfd *input_bfd;
+ bfd_vma relocation;
+ bfd_byte *location;
+{
+ int r_ns32k_type = (howto - MY(howto_table)) / 6;
+ long (*get_data)();
+ int (*put_data)();
+
+ switch (r_ns32k_type)
+ {
+ case 0:
+ get_data = ns32k_get_immediate;
+ put_data = ns32k_put_immediate;
+ break;
+ case 1:
+ get_data = ns32k_get_displacement;
+ put_data = ns32k_put_displacement;
+ break;
+ case 2:
+ return _bfd_relocate_contents (howto, input_bfd, relocation,
+ location);
+ /* NOT REACHED */
+ break;
+ }
+ return do_ns32k_reloc_contents (howto, input_bfd, relocation,
+ location, get_data, put_data);
+}
diff --git a/contrib/gdb/bfd/aout-target.h b/contrib/gdb/bfd/aout-target.h
new file mode 100644
index 0000000..6711a71
--- /dev/null
+++ b/contrib/gdb/bfd/aout-target.h
@@ -0,0 +1,607 @@
+/* Define a target vector and some small routines for a variant of a.out.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+/*#include "libaout.h"*/
+
+extern reloc_howto_type * 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 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);
+
+ /* The virtual memory addresses of the sections */
+ obj_textsec (abfd)->vma = N_TXTADDR(*execp);
+ obj_datasec (abfd)->vma = N_DATADDR(*execp);
+ obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
+
+ obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
+ obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
+ obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;
+
+ /* The file offsets of the sections */
+ obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
+ obj_datasec (abfd)->filepos = N_DATOFF (*execp);
+
+ /* The file offsets of the relocation info */
+ obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
+ obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
+
+ /* The file offsets of the string table and symbol table. */
+ obj_sym_filepos (abfd) = N_SYMOFF (*execp);
+ obj_str_filepos (abfd) = N_STROFF (*execp);
+
+ /* Determine the architecture and machine type of the object file. */
+#ifdef SET_ARCH_MACH
+ SET_ARCH_MACH(abfd, *execp);
+#else
+ 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
+ adata(abfd).page_size = TARGET_PAGE_SIZE;
+#ifdef SEGMENT_SIZE
+ adata(abfd).segment_size = SEGMENT_SIZE;
+#else
+ adata(abfd).segment_size = TARGET_PAGE_SIZE;
+#endif
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+#endif
+
+ return abfd->xvec;
+}
+#endif
+
+#ifndef MY_object_p
+/* Finish up the reading of an a.out file header */
+
+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 */
+ const bfd_target *target;
+
+ if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+#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 /* SWAP_MAGIC */
+
+ if (N_BADMAG (exec)) return 0;
+#ifdef MACHTYPE_OK
+ if (!(MACHTYPE_OK (N_MACHTYPE (exec)))) return 0;
+#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
+ /* The NEWSOS3 entry-point is/was 0, which (amongst other lossage)
+ * means that it isn't obvious if EXEC_P should be set.
+ * All of the following must be true for an executable:
+ * There must be no relocations, the bfd can be neither an
+ * archive nor an archive element, and the file must be executable. */
+
+ if (exec.a_trsize + exec.a_drsize == 0
+ && bfd_get_format(abfd) == bfd_object && abfd->my_archive == NULL)
+ {
+ struct stat buf;
+#ifndef S_IXUSR
+#define S_IXUSR 0100 /* Execute by owner. */
+#endif
+ if (stat(abfd->filename, &buf) == 0 && (buf.st_mode & S_IXUSR))
+ abfd->flags |= EXEC_P;
+ }
+#endif /* ENTRY_CAN_BE_ZERO */
+
+ return target;
+}
+#define MY_object_p MY(object_p)
+#endif
+
+
+#ifndef MY_mkobject
+static boolean
+MY(mkobject) (abfd)
+ bfd *abfd;
+{
+ if (NAME(aout,mkobject)(abfd) == false)
+ return false;
+#if 0 /* Sizes get set in set_sizes callback, later, after we know
+ the architecture and machine. */
+ adata(abfd).page_size = TARGET_PAGE_SIZE;
+#ifdef SEGMENT_SIZE
+ adata(abfd).segment_size = SEGMENT_SIZE;
+#else
+ adata(abfd).segment_size = TARGET_PAGE_SIZE;
+#endif
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+#endif
+ return true;
+}
+#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;
+{
+ if (bfd_get_flavour (obfd) == bfd_target_aout_flavour)
+ 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
+MY(write_object_contents) (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+#if CHOOSE_RELOC_SIZE
+ CHOOSE_RELOC_SIZE(abfd);
+#else
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+#endif
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
+#define MY_write_object_contents MY(write_object_contents)
+#endif
+
+#ifndef MY_set_sizes
+static boolean
+MY(set_sizes) (abfd)
+ bfd *abfd;
+{
+ adata(abfd).page_size = TARGET_PAGE_SIZE;
+
+#ifdef SEGMENT_SIZE
+ adata(abfd).segment_size = SEGMENT_SIZE;
+#else
+ adata(abfd).segment_size = TARGET_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 = TARGET_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_zmagic_contiguous
+#define MY_zmagic_contiguous 0
+#endif
+#ifndef MY_text_includes_header
+#define MY_text_includes_header 0
+#endif
+#ifndef MY_exec_header_not_counted
+#define MY_exec_header_not_counted 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) = {
+ MY_zmagic_contiguous,
+ MY_text_includes_header,
+ MY_exec_hdr_flags,
+ 0, /* text vma? */
+ MY_set_sizes,
+ MY_exec_header_not_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
+#endif
+#ifndef MY_get_elt_at_index
+#define MY_get_elt_at_index _bfd_generic_get_elt_at_index
+#endif
+#ifndef MY_generic_stat_arch_elt
+#define MY_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#endif
+#ifndef MY_slurp_armap
+#define MY_slurp_armap bfd_slurp_bsd_armap
+#endif
+#ifndef MY_slurp_extended_name_table
+#define MY_slurp_extended_name_table _bfd_slurp_extended_name_table
+#endif
+#ifndef MY_construct_extended_name_table
+#define MY_construct_extended_name_table \
+ _bfd_archive_bsd_construct_extended_name_table
+#endif
+#ifndef MY_write_armap
+#define MY_write_armap bsd_write_armap
+#endif
+#ifndef MY_read_ar_hdr
+#define MY_read_ar_hdr _bfd_generic_read_ar_hdr
+#endif
+#ifndef MY_truncate_arname
+#define MY_truncate_arname bfd_bsd_truncate_arname
+#endif
+#ifndef MY_update_armap_timestamp
+#define MY_update_armap_timestamp _bfd_archive_bsd_update_armap_timestamp
+#endif
+
+/* No core file defined here -- configure in trad-core.c separately. */
+#ifndef MY_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_nocore_core_file_failing_signal
+#endif
+#ifndef MY_core_file_matches_executable_p
+#define MY_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
+#endif
+
+#ifndef MY_bfd_debug_info_start
+#define MY_bfd_debug_info_start bfd_void
+#endif
+#ifndef MY_bfd_debug_info_end
+#define MY_bfd_debug_info_end bfd_void
+#endif
+#ifndef MY_bfd_debug_info_accumulate
+#define MY_bfd_debug_info_accumulate \
+ (void (*) PARAMS ((bfd*, struct sec *))) bfd_void
+#endif
+
+#ifndef MY_core_file_failing_command
+#define MY_core_file_failing_command NAME(aout,core_file_failing_command)
+#endif
+#ifndef MY_core_file_failing_signal
+#define MY_core_file_failing_signal NAME(aout,core_file_failing_signal)
+#endif
+#ifndef MY_core_file_matches_executable_p
+#define MY_core_file_matches_executable_p NAME(aout,core_file_matches_executable_p)
+#endif
+#ifndef MY_set_section_contents
+#define MY_set_section_contents NAME(aout,set_section_contents)
+#endif
+#ifndef MY_get_section_contents
+#define MY_get_section_contents NAME(aout,get_section_contents)
+#endif
+#ifndef MY_get_section_contents_in_window
+#define MY_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
+#endif
+#ifndef MY_new_section_hook
+#define MY_new_section_hook NAME(aout,new_section_hook)
+#endif
+#ifndef MY_get_symtab_upper_bound
+#define MY_get_symtab_upper_bound NAME(aout,get_symtab_upper_bound)
+#endif
+#ifndef MY_get_symtab
+#define MY_get_symtab NAME(aout,get_symtab)
+#endif
+#ifndef MY_get_reloc_upper_bound
+#define MY_get_reloc_upper_bound NAME(aout,get_reloc_upper_bound)
+#endif
+#ifndef MY_canonicalize_reloc
+#define MY_canonicalize_reloc NAME(aout,canonicalize_reloc)
+#endif
+#ifndef MY_make_empty_symbol
+#define MY_make_empty_symbol NAME(aout,make_empty_symbol)
+#endif
+#ifndef MY_print_symbol
+#define MY_print_symbol NAME(aout,print_symbol)
+#endif
+#ifndef MY_get_symbol_info
+#define MY_get_symbol_info NAME(aout,get_symbol_info)
+#endif
+#ifndef MY_get_lineno
+#define MY_get_lineno NAME(aout,get_lineno)
+#endif
+#ifndef MY_set_arch_mach
+#define MY_set_arch_mach NAME(aout,set_arch_mach)
+#endif
+#ifndef MY_find_nearest_line
+#define MY_find_nearest_line NAME(aout,find_nearest_line)
+#endif
+#ifndef MY_sizeof_headers
+#define MY_sizeof_headers NAME(aout,sizeof_headers)
+#endif
+#ifndef MY_bfd_get_relocated_section_contents
+#define MY_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#endif
+#ifndef MY_bfd_relax_section
+#define MY_bfd_relax_section bfd_generic_relax_section
+#endif
+#ifndef MY_bfd_reloc_type_lookup
+#define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup)
+#endif
+#ifndef MY_bfd_make_debug_symbol
+#define MY_bfd_make_debug_symbol 0
+#endif
+#ifndef MY_read_minisymbols
+#define MY_read_minisymbols NAME(aout,read_minisymbols)
+#endif
+#ifndef MY_minisymbol_to_symbol
+#define MY_minisymbol_to_symbol NAME(aout,minisymbol_to_symbol)
+#endif
+#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_link_split_section
+#define MY_bfd_link_split_section _bfd_generic_link_split_section
+#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_merge_private_bfd_data
+#define MY_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#endif
+
+#ifndef MY_bfd_copy_private_symbol_data
+#define MY_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
+#endif
+
+#ifndef MY_bfd_print_private_bfd_data
+#define MY_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
+#endif
+
+#ifndef MY_bfd_set_private_flags
+#define MY_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+#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 */
+#ifndef MY_symbol_leading_char
+#define MY_symbol_leading_char '_'
+#endif
+
+/* Aout archives normally use spaces for padding */
+#ifndef AR_PAD_CHAR
+#define AR_PAD_CHAR ' '
+#endif
+
+#ifndef MY_BFD_TARGET
+const bfd_target MY(vec) =
+{
+ TARGETNAME, /* name */
+ bfd_target_aout_flavour,
+#ifdef TARGET_IS_BIG_ENDIAN_P
+ BFD_ENDIAN_BIG, /* target byte order (big) */
+ BFD_ENDIAN_BIG, /* target headers byte order (big) */
+#else
+ BFD_ENDIAN_LITTLE, /* target byte order (little) */
+ BFD_ENDIAN_LITTLE, /* target headers byte order (little) */
+#endif
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ MY_symbol_leading_char,
+ AR_PAD_CHAR, /* ar_pad_char */
+ 15, /* ar_max_namelen */
+#ifdef TARGET_IS_BIG_ENDIAN_P
+ 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 */
+#else
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+#endif
+ {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, MY_core_file_p},
+ {bfd_false, MY_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, MY_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ 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/contrib/gdb/bfd/aout0.c b/contrib/gdb/bfd/aout0.c
new file mode 100644
index 0000000..5bc7ae0
--- /dev/null
+++ b/contrib/gdb/bfd/aout0.c
@@ -0,0 +1,32 @@
+/* BFD backend for SunOS style a.out with flags set to 0
+ Copyright (C) 1990, 91, 92, 93, 1994 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGETNAME "a.out-zero-big"
+#define MY(OP) CAT(aout0_big_,OP)
+
+#include "bfd.h"
+
+#define MY_exec_hdr_flags 0
+
+#define MACHTYPE_OK(mtype) \
+ ((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020)
+
+/* Include the usual a.out support. */
+#include "aoutf1.h"
diff --git a/contrib/gdb/bfd/aout32.c b/contrib/gdb/bfd/aout32.c
new file mode 100644
index 0000000..bfc40b4
--- /dev/null
+++ b/contrib/gdb/bfd/aout32.c
@@ -0,0 +1,23 @@
+/* BFD back-end for 32-bit a.out files.
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define ARCH_SIZE 32
+
+#include "aoutx.h"
diff --git a/contrib/gdb/bfd/aout64.c b/contrib/gdb/bfd/aout64.c
new file mode 100644
index 0000000..84036c8
--- /dev/null
+++ b/contrib/gdb/bfd/aout64.c
@@ -0,0 +1,31 @@
+/* BFD back-end for 64-bit a.out files.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define ARCH_SIZE 64
+
+/* aoutx.h requires definitions for BMAGIC and QMAGIC. */
+#ifndef BMAGIC
+#define BMAGIC 0
+#endif
+#ifndef QMAGIC
+#define QMAGIC 0
+#endif
+
+#include "aoutx.h"
diff --git a/contrib/gdb/bfd/aoutf1.h b/contrib/gdb/bfd/aoutf1.h
new file mode 100644
index 0000000..690d528
--- /dev/null
+++ b/contrib/gdb/bfd/aoutf1.h
@@ -0,0 +1,788 @@
+/* A.out "format 1" file handling code for BFD.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "aout/sun4.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+
+/* This is needed to reject a NewsOS file, e.g. in
+ gdb/testsuite/gdb.t10/crossload.exp. <kingdon@cygnus.com>
+ I needed to add M_UNKNOWN to recognize a 68000 object, so this will
+ probably no longer reject a NewsOS object. <ian@cygnus.com>. */
+#ifndef MACHTYPE_OK
+#define MACHTYPE_OK(mtype) \
+ (((mtype) == M_SPARC && bfd_lookup_arch (bfd_arch_sparc, 0) != NULL) \
+ || (((mtype) == M_UNKNOWN || (mtype) == M_68010 || (mtype) == M_68020) \
+ && bfd_lookup_arch (bfd_arch_m68k, 0) != NULL))
+#endif
+
+/*
+The file @code{aoutf1.h} contains the code for BFD's
+a.out back end. Control over the generated back end is given by these
+two preprocessor names:
+@table @code
+@item ARCH_SIZE
+This value should be either 32 or 64, depending upon the size of an
+int in the target format. It changes the sizes of the structs which
+perform the memory/disk mapping of structures.
+
+The 64 bit backend may only be used if the host compiler supports 64
+ints (eg long long with gcc), by defining the name @code{BFD_HOST_64_BIT} in @code{bfd.h}.
+With this name defined, @emph{all} bfd operations are performed with 64bit
+arithmetic, not just those to a 64bit target.
+
+@item TARGETNAME
+The name put into the target vector.
+@item
+@end table
+
+*/
+
+/*SUPPRESS558*/
+/*SUPPRESS529*/
+
+static void
+#if ARCH_SIZE == 64
+sunos_64_set_arch_mach
+#else
+sunos_32_set_arch_mach
+#endif
+ (abfd, machtype)
+ bfd *abfd;
+ int machtype;
+{
+ /* Determine the architecture and machine type of the object file. */
+ enum bfd_architecture arch;
+ long machine;
+ switch (machtype)
+ {
+
+ case M_UNKNOWN:
+ /* Some Sun3s make magic numbers without cpu types in them, so
+ we'll default to the 68000. */
+ arch = bfd_arch_m68k;
+ machine = 68000;
+ break;
+
+ case M_68010:
+ case M_HP200:
+ arch = bfd_arch_m68k;
+ machine = 68010;
+ break;
+
+ case M_68020:
+ case M_HP300:
+ arch = bfd_arch_m68k;
+ machine = 68020;
+ break;
+
+ case M_SPARC:
+ arch = bfd_arch_sparc;
+ machine = 0;
+ break;
+
+ case M_386:
+ case M_386_DYNIX:
+ arch = bfd_arch_i386;
+ machine = 0;
+ break;
+
+ case M_29K:
+ arch = bfd_arch_a29k;
+ machine = 0;
+ break;
+
+ case M_HPUX:
+ arch = bfd_arch_m68k;
+ machine = 0;
+ break;
+
+ default:
+ arch = bfd_arch_obscure;
+ machine = 0;
+ break;
+ }
+ bfd_set_arch_mach (abfd, arch, machine);
+}
+
+#define SET_ARCH_MACH(ABFD, EXEC) \
+ NAME(sunos,set_arch_mach)(ABFD, N_MACHTYPE (EXEC)); \
+ choose_reloc_size(ABFD);
+
+/* Determine the size of a relocation entry, based on the architecture */
+static void
+choose_reloc_size (abfd)
+ bfd *abfd;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_sparc:
+ case bfd_arch_a29k:
+ obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
+ break;
+ default:
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+ break;
+ }
+}
+
+/* Write an object file in SunOS format.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+static boolean
+#if ARCH_SIZE == 64
+aout_64_sunos4_write_object_contents
+#else
+aout_32_sunos4_write_object_contents
+#endif
+ (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ /* Magic number, maestro, please! */
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_m68k:
+ switch (bfd_get_mach (abfd))
+ {
+ case 68000:
+ N_SET_MACHTYPE (*execp, M_UNKNOWN);
+ break;
+ case 68010:
+ N_SET_MACHTYPE (*execp, M_68010);
+ break;
+ default:
+ case 68020:
+ N_SET_MACHTYPE (*execp, M_68020);
+ break;
+ }
+ break;
+ case bfd_arch_sparc:
+ N_SET_MACHTYPE (*execp, M_SPARC);
+ break;
+ case bfd_arch_i386:
+ N_SET_MACHTYPE (*execp, M_386);
+ break;
+ case bfd_arch_a29k:
+ N_SET_MACHTYPE (*execp, M_29K);
+ break;
+ default:
+ N_SET_MACHTYPE (*execp, M_UNKNOWN);
+ }
+
+ choose_reloc_size (abfd);
+
+ N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);
+
+ N_SET_DYNAMIC (*execp, bfd_get_file_flags (abfd) & DYNAMIC);
+
+ WRITE_HEADERS (abfd, execp);
+
+ return true;
+}
+
+/* core files */
+
+#define CORE_MAGIC 0x080456
+#define CORE_NAMELEN 16
+
+/* The core structure is taken from the Sun documentation.
+ Unfortunately, they don't document the FPA structure, or at least I
+ can't find it easily. Fortunately the core header contains its own
+ length. So this shouldn't cause problems, except for c_ucode, which
+ so far we don't use but is easy to find with a little arithmetic. */
+
+/* But the reg structure can be gotten from the SPARC processor handbook.
+ This really should be in a GNU include file though so that gdb can use
+ the same info. */
+struct regs
+{
+ int r_psr;
+ int r_pc;
+ int r_npc;
+ int r_y;
+ int r_g1;
+ int r_g2;
+ int r_g3;
+ int r_g4;
+ int r_g5;
+ int r_g6;
+ int r_g7;
+ int r_o0;
+ int r_o1;
+ int r_o2;
+ int r_o3;
+ int r_o4;
+ int r_o5;
+ int r_o6;
+ int r_o7;
+};
+
+/* Taken from Sun documentation: */
+
+/* FIXME: It's worse than we expect. This struct contains TWO substructs
+ neither of whose size we know, WITH STUFF IN BETWEEN THEM! We can't
+ even portably access the stuff in between! */
+
+struct external_sparc_core
+ {
+ int c_magic; /* Corefile magic number */
+ int c_len; /* Sizeof (struct core) */
+#define SPARC_CORE_LEN 432
+ int c_regs[19]; /* General purpose registers -- MACHDEP SIZE */
+ struct external_exec c_aouthdr; /* A.out header */
+ int c_signo; /* Killing signal, if any */
+ int c_tsize; /* Text size (bytes) */
+ int c_dsize; /* Data size (bytes) */
+ int c_ssize; /* Stack size (bytes) */
+ char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+ double fp_stuff[1]; /* external FPU state (size unknown by us) */
+ /* The type "double" is critical here, for alignment.
+ SunOS declares a struct here, but the struct's alignment
+ is double since it contains doubles. */
+ int c_ucode; /* Exception no. from u_code */
+ /* (this member is not accessible by name since we don't
+ portably know the size of fp_stuff.) */
+ };
+
+/* Core files generated by the BCP (the part of Solaris which allows
+ it to run SunOS4 a.out files). */
+struct external_solaris_bcp_core
+ {
+ int c_magic; /* Corefile magic number */
+ int c_len; /* Sizeof (struct core) */
+#define SOLARIS_BCP_CORE_LEN 456
+ int c_regs[19]; /* General purpose registers -- MACHDEP SIZE */
+ int c_exdata_vp; /* exdata structure */
+ int c_exdata_tsize;
+ int c_exdata_dsize;
+ int c_exdata_bsize;
+ int c_exdata_lsize;
+ int c_exdata_nshlibs;
+ short c_exdata_mach;
+ short c_exdata_mag;
+ int c_exdata_toffset;
+ int c_exdata_doffset;
+ int c_exdata_loffset;
+ int c_exdata_txtorg;
+ int c_exdata_datorg;
+ int c_exdata_entloc;
+ int c_signo; /* Killing signal, if any */
+ int c_tsize; /* Text size (bytes) */
+ int c_dsize; /* Data size (bytes) */
+ int c_ssize; /* Stack size (bytes) */
+ char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+ double fp_stuff[1]; /* external FPU state (size unknown by us) */
+ /* The type "double" is critical here, for alignment.
+ SunOS declares a struct here, but the struct's alignment
+ is double since it contains doubles. */
+ int c_ucode; /* Exception no. from u_code */
+ /* (this member is not accessible by name since we don't
+ portably know the size of fp_stuff.) */
+ };
+
+struct external_sun3_core
+ {
+ int c_magic; /* Corefile magic number */
+ int c_len; /* Sizeof (struct core) */
+#define SUN3_CORE_LEN 826 /* As of SunOS 4.1.1 */
+ int c_regs[18]; /* General purpose registers -- MACHDEP SIZE */
+ struct external_exec c_aouthdr; /* A.out header */
+ int c_signo; /* Killing signal, if any */
+ int c_tsize; /* Text size (bytes) */
+ int c_dsize; /* Data size (bytes) */
+ int c_ssize; /* Stack size (bytes) */
+ char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+ double fp_stuff[1]; /* external FPU state (size unknown by us) */
+ /* The type "double" is critical here, for alignment.
+ SunOS declares a struct here, but the struct's alignment
+ is double since it contains doubles. */
+ int c_ucode; /* Exception no. from u_code */
+ /* (this member is not accessible by name since we don't
+ portably know the size of fp_stuff.) */
+ };
+
+struct internal_sunos_core
+ {
+ int c_magic; /* Corefile magic number */
+ int c_len; /* Sizeof (struct core) */
+ long c_regs_pos; /* file offset of General purpose registers */
+ int c_regs_size; /* size of General purpose registers */
+ struct internal_exec c_aouthdr; /* A.out header */
+ int c_signo; /* Killing signal, if any */
+ int c_tsize; /* Text size (bytes) */
+ int c_dsize; /* Data size (bytes) */
+ bfd_vma c_data_addr; /* Data start (address) */
+ int c_ssize; /* Stack size (bytes) */
+ bfd_vma c_stacktop; /* Stack top (address) */
+ char c_cmdname[CORE_NAMELEN + 1]; /* Command name */
+ long fp_stuff_pos; /* file offset of external FPU state (regs) */
+ int fp_stuff_size; /* Size of it */
+ int c_ucode; /* Exception no. from u_code */
+ };
+
+/* byte-swap in the Sun-3 core structure */
+static void
+swapcore_sun3 (abfd, ext, intcore)
+ bfd *abfd;
+ char *ext;
+ struct internal_sunos_core *intcore;
+{
+ struct external_sun3_core *extcore = (struct external_sun3_core *) ext;
+
+ intcore->c_magic = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_magic);
+ intcore->c_len = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_len);
+ intcore->c_regs_pos = (long) (((struct external_sun3_core *) 0)->c_regs);
+ intcore->c_regs_size = sizeof (extcore->c_regs);
+#if ARCH_SIZE == 64
+ aout_64_swap_exec_header_in
+#else
+ aout_32_swap_exec_header_in
+#endif
+ (abfd, &extcore->c_aouthdr, &intcore->c_aouthdr);
+ intcore->c_signo = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_signo);
+ intcore->c_tsize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_tsize);
+ intcore->c_dsize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_dsize);
+ intcore->c_data_addr = N_DATADDR (intcore->c_aouthdr);
+ intcore->c_ssize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_ssize);
+ memcpy (intcore->c_cmdname, extcore->c_cmdname, sizeof (intcore->c_cmdname));
+ intcore->fp_stuff_pos = (long) (((struct external_sun3_core *) 0)->fp_stuff);
+ /* FP stuff takes up whole rest of struct, except c_ucode. */
+ intcore->fp_stuff_size = intcore->c_len - (sizeof extcore->c_ucode) -
+ (file_ptr) (((struct external_sun3_core *) 0)->fp_stuff);
+ /* Ucode is the last thing in the struct -- just before the end */
+ intcore->c_ucode =
+ bfd_h_get_32 (abfd,
+ intcore->c_len - sizeof (extcore->c_ucode) + (unsigned char *) extcore);
+ intcore->c_stacktop = 0x0E000000; /* By experimentation */
+}
+
+
+/* byte-swap in the Sparc core structure */
+static void
+swapcore_sparc (abfd, ext, intcore)
+ bfd *abfd;
+ char *ext;
+ struct internal_sunos_core *intcore;
+{
+ struct external_sparc_core *extcore = (struct external_sparc_core *) ext;
+
+ intcore->c_magic = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_magic);
+ intcore->c_len = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_len);
+ intcore->c_regs_pos = (long) (((struct external_sparc_core *) 0)->c_regs);
+ intcore->c_regs_size = sizeof (extcore->c_regs);
+#if ARCH_SIZE == 64
+ aout_64_swap_exec_header_in
+#else
+ aout_32_swap_exec_header_in
+#endif
+ (abfd, &extcore->c_aouthdr, &intcore->c_aouthdr);
+ intcore->c_signo = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_signo);
+ intcore->c_tsize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_tsize);
+ intcore->c_dsize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_dsize);
+ intcore->c_data_addr = N_DATADDR (intcore->c_aouthdr);
+ intcore->c_ssize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_ssize);
+ memcpy (intcore->c_cmdname, extcore->c_cmdname, sizeof (intcore->c_cmdname));
+ intcore->fp_stuff_pos = (long) (((struct external_sparc_core *) 0)->fp_stuff);
+ /* FP stuff takes up whole rest of struct, except c_ucode. */
+ intcore->fp_stuff_size = intcore->c_len - (sizeof extcore->c_ucode) -
+ (file_ptr) (((struct external_sparc_core *) 0)->fp_stuff);
+ /* Ucode is the last thing in the struct -- just before the end */
+ intcore->c_ucode =
+ bfd_h_get_32 (abfd,
+ intcore->c_len - sizeof (extcore->c_ucode) + (unsigned char *) extcore);
+
+ /* Supposedly the user stack grows downward from the bottom of kernel memory.
+ Presuming that this remains true, this definition will work. */
+ /* Now sun has provided us with another challenge. The value is different
+ for sparc2 and sparc10 (both running SunOS 4.1.3). We pick one or
+ the other based on the current value of the stack pointer. This
+ loses (a) if the stack pointer has been clobbered, or (b) if the stack
+ is larger than 128 megabytes.
+
+ It's times like these you're glad they're switching to ELF.
+
+ Note that using include files or nlist on /vmunix would be wrong,
+ because we want the value for this core file, no matter what kind of
+ machine we were compiled on or are running on. */
+#define SPARC_USRSTACK_SPARC2 ((bfd_vma)0xf8000000)
+#define SPARC_USRSTACK_SPARC10 ((bfd_vma)0xf0000000)
+ {
+ bfd_vma sp = bfd_h_get_32
+ (abfd, (unsigned char *) &((struct regs *) &extcore->c_regs[0])->r_o6);
+ if (sp < SPARC_USRSTACK_SPARC10)
+ intcore->c_stacktop = SPARC_USRSTACK_SPARC10;
+ else
+ intcore->c_stacktop = SPARC_USRSTACK_SPARC2;
+ }
+}
+
+/* byte-swap in the Solaris BCP core structure */
+static void
+swapcore_solaris_bcp (abfd, ext, intcore)
+ bfd *abfd;
+ char *ext;
+ struct internal_sunos_core *intcore;
+{
+ struct external_solaris_bcp_core *extcore =
+ (struct external_solaris_bcp_core *) ext;
+
+ intcore->c_magic = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_magic);
+ intcore->c_len = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_len);
+ intcore->c_regs_pos = (long) (((struct external_solaris_bcp_core *) 0)->c_regs);
+ intcore->c_regs_size = sizeof (extcore->c_regs);
+
+ /* The Solaris BCP exdata structure does not contain an a_syms field,
+ so we are unable to synthesize an internal exec header.
+ Luckily we are able to figure out the start address of the data section,
+ which is the only thing needed from the internal exec header,
+ from the exdata structure.
+
+ As of Solaris 2.3, BCP core files for statically linked executables
+ are buggy. The exdata structure is not properly filled in, and
+ the data section is written from address zero instead of the data
+ start address. */
+ memset ((PTR) &intcore->c_aouthdr, 0, sizeof (struct internal_exec));
+ intcore->c_data_addr =
+ bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_exdata_datorg);
+ intcore->c_signo = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_signo);
+ intcore->c_tsize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_tsize);
+ intcore->c_dsize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_dsize);
+ intcore->c_ssize = bfd_h_get_32 (abfd, (unsigned char *) &extcore->c_ssize);
+ memcpy (intcore->c_cmdname, extcore->c_cmdname, sizeof (intcore->c_cmdname));
+ intcore->fp_stuff_pos =
+ (long) (((struct external_solaris_bcp_core *) 0)->fp_stuff);
+ /* FP stuff takes up whole rest of struct, except c_ucode. */
+ intcore->fp_stuff_size = intcore->c_len - (sizeof extcore->c_ucode) -
+ (file_ptr) (((struct external_solaris_bcp_core *) 0)->fp_stuff);
+ /* Ucode is the last thing in the struct -- just before the end */
+ intcore->c_ucode =
+ bfd_h_get_32 (abfd,
+ intcore->c_len - sizeof (extcore->c_ucode) + (unsigned char *) extcore);
+
+ /* Supposedly the user stack grows downward from the bottom of kernel memory.
+ Presuming that this remains true, this definition will work. */
+ /* Now sun has provided us with another challenge. The value is different
+ for sparc2 and sparc10 (both running SunOS 4.1.3). We pick one or
+ the other based on the current value of the stack pointer. This
+ loses (a) if the stack pointer has been clobbered, or (b) if the stack
+ is larger than 128 megabytes.
+
+ It's times like these you're glad they're switching to ELF.
+
+ Note that using include files or nlist on /vmunix would be wrong,
+ because we want the value for this core file, no matter what kind of
+ machine we were compiled on or are running on. */
+#define SPARC_USRSTACK_SPARC2 ((bfd_vma)0xf8000000)
+#define SPARC_USRSTACK_SPARC10 ((bfd_vma)0xf0000000)
+ {
+ bfd_vma sp = bfd_h_get_32
+ (abfd, (unsigned char *) &((struct regs *) &extcore->c_regs[0])->r_o6);
+ if (sp < SPARC_USRSTACK_SPARC10)
+ intcore->c_stacktop = SPARC_USRSTACK_SPARC10;
+ else
+ intcore->c_stacktop = SPARC_USRSTACK_SPARC2;
+ }
+}
+
+/* need this cast because ptr is really void * */
+#define core_hdr(bfd) ((bfd)->tdata.sun_core_data)
+#define core_datasec(bfd) (core_hdr(bfd)->data_section)
+#define core_stacksec(bfd) (core_hdr(bfd)->stack_section)
+#define core_regsec(bfd) (core_hdr(bfd)->reg_section)
+#define core_reg2sec(bfd) (core_hdr(bfd)->reg2_section)
+
+/* These are stored in the bfd's tdata */
+struct sun_core_struct
+{
+ struct internal_sunos_core *hdr; /* core file header */
+ asection *data_section;
+ asection *stack_section;
+ asection *reg_section;
+ asection *reg2_section;
+};
+
+static const bfd_target *
+sunos4_core_file_p (abfd)
+ bfd *abfd;
+{
+ unsigned char longbuf[4]; /* Raw bytes of various header fields */
+ bfd_size_type core_size;
+ unsigned long core_mag;
+ struct internal_sunos_core *core;
+ char *extcore;
+ struct mergem
+ {
+ struct sun_core_struct suncoredata;
+ struct internal_sunos_core internal_sunos_core;
+ char external_core[1];
+ }
+ *mergem;
+
+ if (bfd_read ((PTR) longbuf, 1, sizeof (longbuf), abfd) !=
+ sizeof (longbuf))
+ return 0;
+ core_mag = bfd_h_get_32 (abfd, longbuf);
+
+ if (core_mag != CORE_MAGIC)
+ return 0;
+
+ /* SunOS core headers can vary in length; second word is size; */
+ if (bfd_read ((PTR) longbuf, 1, sizeof (longbuf), abfd) !=
+ sizeof (longbuf))
+ return 0;
+ core_size = bfd_h_get_32 (abfd, longbuf);
+ /* Sanity check */
+ if (core_size > 20000)
+ return 0;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) < 0)
+ return 0;
+
+ mergem = (struct mergem *) bfd_zalloc (abfd, core_size + sizeof (struct mergem));
+ if (mergem == NULL)
+ return 0;
+
+ extcore = mergem->external_core;
+
+ if ((bfd_read ((PTR) extcore, 1, core_size, abfd)) != core_size)
+ {
+ bfd_release (abfd, (char *) mergem);
+ return 0;
+ }
+
+ /* Validate that it's a core file we know how to handle, due to sun
+ botching the positioning of registers and other fields in a machine
+ dependent way. */
+ core = &mergem->internal_sunos_core;
+ switch (core_size)
+ {
+ case SPARC_CORE_LEN:
+ swapcore_sparc (abfd, extcore, core);
+ break;
+ case SUN3_CORE_LEN:
+ swapcore_sun3 (abfd, extcore, core);
+ break;
+ case SOLARIS_BCP_CORE_LEN:
+ swapcore_solaris_bcp (abfd, extcore, core);
+ break;
+ default:
+ bfd_set_error (bfd_error_system_call); /* FIXME */
+ bfd_release (abfd, (char *) mergem);
+ return 0;
+ }
+
+ abfd->tdata.sun_core_data = &mergem->suncoredata;
+ abfd->tdata.sun_core_data->hdr = core;
+
+ /* create the sections. This is raunchy, but bfd_close wants to reclaim
+ them */
+ core_stacksec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_stacksec (abfd) == NULL)
+ {
+ loser:
+ bfd_release (abfd, (char *) mergem);
+ return 0;
+ }
+ core_datasec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_datasec (abfd) == NULL)
+ {
+ loser1:
+ bfd_release (abfd, core_stacksec (abfd));
+ goto loser;
+ }
+ core_regsec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_regsec (abfd) == NULL)
+ {
+ loser2:
+ bfd_release (abfd, core_datasec (abfd));
+ goto loser1;
+ }
+ core_reg2sec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_reg2sec (abfd) == NULL)
+ {
+ bfd_release (abfd, core_regsec (abfd));
+ goto loser2;
+ }
+
+ core_stacksec (abfd)->name = ".stack";
+ core_datasec (abfd)->name = ".data";
+ core_regsec (abfd)->name = ".reg";
+ core_reg2sec (abfd)->name = ".reg2";
+
+ 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_HAS_CONTENTS;
+ core_reg2sec (abfd)->flags = SEC_HAS_CONTENTS;
+
+ core_stacksec (abfd)->_raw_size = core->c_ssize;
+ core_datasec (abfd)->_raw_size = core->c_dsize;
+ core_regsec (abfd)->_raw_size = core->c_regs_size;
+ core_reg2sec (abfd)->_raw_size = core->fp_stuff_size;
+
+ core_stacksec (abfd)->vma = (core->c_stacktop - core->c_ssize);
+ core_datasec (abfd)->vma = core->c_data_addr;
+ core_regsec (abfd)->vma = 0;
+ core_reg2sec (abfd)->vma = 0;
+
+ core_stacksec (abfd)->filepos = core->c_len + core->c_dsize;
+ core_datasec (abfd)->filepos = core->c_len;
+ /* We'll access the regs afresh in the core file, like any section: */
+ core_regsec (abfd)->filepos = (file_ptr) core->c_regs_pos;
+ core_reg2sec (abfd)->filepos = (file_ptr) core->fp_stuff_pos;
+
+ /* Align to word at least */
+ core_stacksec (abfd)->alignment_power = 2;
+ core_datasec (abfd)->alignment_power = 2;
+ core_regsec (abfd)->alignment_power = 2;
+ core_reg2sec (abfd)->alignment_power = 2;
+
+ abfd->sections = core_stacksec (abfd);
+ core_stacksec (abfd)->next = core_datasec (abfd);
+ core_datasec (abfd)->next = core_regsec (abfd);
+ core_regsec (abfd)->next = core_reg2sec (abfd);
+
+ abfd->section_count = 4;
+
+ return abfd->xvec;
+}
+
+static char *
+sunos4_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return core_hdr (abfd)->hdr->c_cmdname;
+}
+
+static int
+sunos4_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_hdr (abfd)->hdr->c_signo;
+}
+
+static boolean
+sunos4_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd;
+ bfd *exec_bfd;
+{
+ if (core_bfd->xvec != exec_bfd->xvec)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return false;
+ }
+
+ /* Solaris core files do not include an aouthdr. */
+ if ((core_hdr (core_bfd)->hdr)->c_len == SOLARIS_BCP_CORE_LEN)
+ return true;
+
+ return (memcmp ((char *) &((core_hdr (core_bfd)->hdr)->c_aouthdr),
+ (char *) exec_hdr (exec_bfd),
+ sizeof (struct internal_exec)) == 0) ? true : false;
+}
+
+#define MY_set_sizes sunos4_set_sizes
+static boolean
+sunos4_set_sizes (abfd)
+ bfd *abfd;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ default:
+ return false;
+ case bfd_arch_sparc:
+ adata (abfd).page_size = 0x2000;
+ adata (abfd).segment_size = 0x2000;
+ adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+ return true;
+ case bfd_arch_m68k:
+ adata (abfd).page_size = 0x2000;
+ adata (abfd).segment_size = 0x20000;
+ adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+ return true;
+ }
+}
+
+/* We default to setting the toolversion field to 1, as is required by
+ SunOS. */
+#ifndef MY_exec_hdr_flags
+#define MY_exec_hdr_flags 1
+#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 sunos4_aout_backend =
+{
+ 0, /* zmagic files are not contiguous */
+ 1, /* text includes header */
+ MY_exec_hdr_flags,
+ 0, /* default text vma */
+ sunos4_set_sizes,
+ 0, /* header is counted in zmagic text */
+ 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_core_file_failing_command sunos4_core_file_failing_command
+#define MY_core_file_failing_signal sunos4_core_file_failing_signal
+#define MY_core_file_matches_executable_p sunos4_core_file_matches_executable_p
+
+#define MY_bfd_debug_info_start bfd_void
+#define MY_bfd_debug_info_end bfd_void
+#define MY_bfd_debug_info_accumulate \
+ (void (*) PARAMS ((bfd *, struct sec *))) bfd_void
+#define MY_core_file_p sunos4_core_file_p
+#define MY_write_object_contents NAME(aout,sunos4_write_object_contents)
+#define MY_backend_data &sunos4_aout_backend
+
+#define TARGET_IS_BIG_ENDIAN_P
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/aoutx.h b/contrib/gdb/bfd/aoutx.h
new file mode 100644
index 0000000..4b04943
--- /dev/null
+++ b/contrib/gdb/bfd/aoutx.h
@@ -0,0 +1,5525 @@
+/* BFD semi-generic back-end for a.out binaries.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ a.out backends
+
+
+DESCRIPTION
+
+ BFD supports a number of different flavours of a.out format,
+ though the major differences are only the sizes of the
+ structures on disk, and the shape of the relocation
+ information.
+
+ 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 @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 @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 @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
+ @file{aout32.c} and @file{aout64.c} to form the names
+ <<aout_32_swap_exec_header_in>>, <<aout_64_swap_exec_header_in>>, etc.
+
+ As an example, this is what goes on to make the back end for a
+ sun4, from @file{aout32.c}:
+
+| #define ARCH_SIZE 32
+| #include "aoutx.h"
+
+ Which exports names:
+
+| ...
+| aout_32_canonicalize_reloc
+| aout_32_find_nearest_line
+| aout_32_get_lineno
+| aout_32_get_reloc_upper_bound
+| ...
+
+ from @file{sunos.c}:
+
+| #define TARGET_NAME "a.out-sunos-big"
+| #define VECNAME sunos_big_vec
+| #include "aoutf1.h"
+
+ requires all the names from @file{aout32.c}, and produces the jump vector
+
+| sunos_big_vec
+
+ 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
+ file offsets and addresses of the text, data, and BSS
+ sections, the machine architecture and machine type, and the
+ entry point address, in a host-dependent manner. Once these
+ values have been determined, generic code is used to handle
+ the object file.
+
+ When porting it to run on a new system, you must supply:
+
+| HOST_PAGE_SIZE
+| HOST_SEGMENT_SIZE
+| HOST_MACHINE_ARCH (optional)
+| HOST_MACHINE_MACHINE (optional)
+| HOST_TEXT_START_ADDR
+| HOST_STACK_END_ADDR
+
+ 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 @file{host-aout.c}, specify:
+
+| TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec
+| TDEPFILES= host-aout.o trad-core.o
+
+ in the @file{config/@var{XXX}.mt} file, and modify @file{configure.in}
+ to use the
+ @file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your
+ configuration is selected.
+
+*/
+
+/* Some assumptions:
+ * Any BFD with D_PAGED set is ZMAGIC, and vice versa.
+ Doesn't matter what the setting of WP_TEXT is on output, but it'll
+ get set on input.
+ * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC.
+ * Any BFD with both flags clear is OMAGIC.
+ (Just want to make these explicit, so the conditions tested in this
+ file make sense if you're more familiar with a.out than with BFD.) */
+
+#define KEEPIT udata.i
+
+#include <string.h> /* For strchr and friends */
+#include <ctype.h>
+#include "bfd.h"
+#include <sysdep.h>
+#include "bfdlink.h"
+
+#include "libaout.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+
+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
+
+DESCRIPTION
+ The file @file{aoutx.h} provides for both the @emph{standard}
+ and @emph{extended} forms of a.out relocation 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
+
+#ifndef MY_final_link_relocate
+#define MY_final_link_relocate _bfd_final_link_relocate
+#endif
+
+#ifndef MY_relocate_contents
+#define MY_relocate_contents _bfd_relocate_contents
+#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 */
+ 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),
+ HOWTO(RELOC_DISP8, 0, 0, 8, true, 0, complain_overflow_signed,0,"DISP8", false, 0,0x000000ff, false),
+ HOWTO(RELOC_DISP16, 0, 1, 16, true, 0, complain_overflow_signed,0,"DISP16", false, 0,0x0000ffff, false),
+ HOWTO(RELOC_DISP32, 0, 2, 32, true, 0, complain_overflow_signed,0,"DISP32", false, 0,0xffffffff, false),
+ HOWTO(RELOC_WDISP30,2, 2, 30, true, 0, complain_overflow_signed,0,"WDISP30", false, 0,0x3fffffff, false),
+ HOWTO(RELOC_WDISP22,2, 2, 22, true, 0, complain_overflow_signed,0,"WDISP22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_HI22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"HI22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_22, 0, 2, 22, false, 0, complain_overflow_bitfield,0,"22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"13", false, 0,0x00001fff, false),
+ HOWTO(RELOC_LO10, 0, 2, 10, false, 0, complain_overflow_dont,0,"LO10", false, 0,0x000003ff, false),
+ HOWTO(RELOC_SFA_BASE,0, 2, 32, false, 0, complain_overflow_bitfield,0,"SFA_BASE", false, 0,0xffffffff, false),
+ HOWTO(RELOC_SFA_OFF13,0,2, 32, false, 0, complain_overflow_bitfield,0,"SFA_OFF13",false, 0,0xffffffff, false),
+ HOWTO(RELOC_BASE10, 0, 2, 10, false, 0, complain_overflow_dont,0,"BASE10", false, 0,0x000003ff, false),
+ HOWTO(RELOC_BASE13, 0, 2, 13, false, 0, complain_overflow_bitfield,0,"BASE13", false, 0,0x00001fff, false),
+ HOWTO(RELOC_BASE22, 10, 2, 22, false, 0, complain_overflow_bitfield,0,"BASE22", false, 0,0x003fffff, false),
+ HOWTO(RELOC_PC10, 0, 2, 10, true, 0, complain_overflow_dont,0,"PC10", false, 0,0x000003ff, true),
+ HOWTO(RELOC_PC22, 10, 2, 22, true, 0, complain_overflow_signed,0,"PC22", false, 0,0x003fffff, true),
+ HOWTO(RELOC_JMP_TBL,2, 2, 30, true, 0, complain_overflow_signed,0,"JMP_TBL", false, 0,0x3fffffff, false),
+ HOWTO(RELOC_SEGOFF16,0, 2, 0, false, 0, complain_overflow_bitfield,0,"SEGOFF16", false, 0,0x00000000, false),
+ HOWTO(RELOC_GLOB_DAT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"GLOB_DAT", false, 0,0x00000000, false),
+ HOWTO(RELOC_JMP_SLOT,0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_SLOT", false, 0,0x00000000, false),
+ HOWTO(RELOC_RELATIVE,0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false),
+};
+
+/* 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 */
+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),
+HOWTO( 3, 0, 4, 64, false, 0, complain_overflow_bitfield,0,"64", true, 0xdeaddead,0xdeaddead, false),
+HOWTO( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", true, 0x000000ff,0x000000ff, false),
+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),
+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]))
+
+reloc_howto_type *
+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]
+ int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
+ if (code == BFD_RELOC_CTOR)
+ switch (bfd_get_arch_info (abfd)->bits_per_address)
+ {
+ case 32:
+ code = BFD_RELOC_32;
+ break;
+ case 64:
+ code = BFD_RELOC_64;
+ break;
+ }
+ if (ext)
+ switch (code)
+ {
+ EXT (BFD_RELOC_32, 2);
+ 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_GOT10, 14);
+ EXT (BFD_RELOC_SPARC_BASE13, 15);
+ EXT (BFD_RELOC_SPARC_GOT13, 15);
+ EXT (BFD_RELOC_SPARC_GOT22, 16);
+ EXT (BFD_RELOC_SPARC_PC10, 17);
+ EXT (BFD_RELOC_SPARC_PC22, 18);
+ EXT (BFD_RELOC_SPARC_WPLT30, 19);
+ default: return (reloc_howto_type *) NULL;
+ }
+ else
+ /* std relocs */
+ switch (code)
+ {
+ STD (BFD_RELOC_16, 1);
+ STD (BFD_RELOC_32, 2);
+ STD (BFD_RELOC_8_PCREL, 4);
+ STD (BFD_RELOC_16_PCREL, 5);
+ STD (BFD_RELOC_32_PCREL, 6);
+ STD (BFD_RELOC_16_BASEREL, 9);
+ STD (BFD_RELOC_32_BASEREL, 10);
+ default: return (reloc_howto_type *) NULL;
+ }
+}
+
+/*
+SUBSECTION
+ Internal entry points
+
+DESCRIPTION
+ @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).
+
+*/
+
+/*
+FUNCTION
+ aout_@var{size}_swap_exec_header_in
+
+SYNOPSIS
+ 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
+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;
+
+ /* The internal_exec structure has some fields that are unused in this
+ 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 ((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);
+ execp->a_data = GET_WORD (abfd, bytes->e_data);
+ execp->a_bss = GET_WORD (abfd, bytes->e_bss);
+ execp->a_syms = GET_WORD (abfd, bytes->e_syms);
+ execp->a_entry = GET_WORD (abfd, bytes->e_entry);
+ execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
+ execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
+}
+#define NAME_swap_exec_header_in NAME(aout,swap_exec_header_in)
+#endif
+
+/*
+FUNCTION
+ aout_@var{size}_swap_exec_header_out
+
+SYNOPSIS
+ 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
+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;
+
+ /* Now fill in fields in the raw data, from the fields in the exec struct. */
+ bfd_h_put_32 (abfd, execp->a_info , bytes->e_info);
+ PUT_WORD (abfd, execp->a_text , bytes->e_text);
+ PUT_WORD (abfd, execp->a_data , bytes->e_data);
+ PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
+ PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
+ PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
+ PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
+ 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_@var{size}_some_aout_object_p
+
+SYNOPSIS
+ const bfd_target *aout_@var{size}_some_aout_object_p
+ (bfd *abfd,
+ 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.
+*/
+
+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;
+ const bfd_target *result;
+
+ rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, sizeof (struct aout_data_struct ));
+ if (rawptr == NULL)
+ return 0;
+
+ oldrawptr = abfd->tdata.aout_data;
+ abfd->tdata.aout_data = rawptr;
+
+ /* Copy the contents of the old tdata struct.
+ In particular, we want the subformat, since for hpux it was set in
+ hp300hpux.c:swap_exec_header_in and will be used in
+ hp300hpux.c:callback. */
+ if (oldrawptr != NULL)
+ *abfd->tdata.aout_data = *oldrawptr;
+
+ abfd->tdata.aout_data->a.hdr = &rawptr->e;
+ *(abfd->tdata.aout_data->a.hdr) = *execp; /* Copy in the internal_exec struct */
+ execp = abfd->tdata.aout_data->a.hdr;
+
+ /* Set the file flags */
+ abfd->flags = NO_FLAGS;
+ if (execp->a_drsize || execp->a_trsize)
+ abfd->flags |= HAS_RELOC;
+ /* 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;
+ }
+ 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;
+ }
+ else if (N_MAGIC (*execp) == OMAGIC
+ || N_MAGIC (*execp) == BMAGIC)
+ adata (abfd).magic = o_magic;
+ else
+ {
+ /* Should have been checked with N_BADMAG before this routine
+ was called. */
+ abort ();
+ }
+
+ bfd_get_start_address (abfd) = execp->a_entry;
+
+ obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+ bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
+
+ /* The default relocation entry size is that of traditional V7 Unix. */
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+
+ /* The default symbol entry size is that of traditional Unix. */
+ obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
+
+#ifdef USE_MMAP
+ bfd_init_window (&obj_aout_sym_window (abfd));
+ bfd_init_window (&obj_aout_string_window (abfd));
+#endif
+ obj_aout_external_syms (abfd) = NULL;
+ obj_aout_external_strings (abfd) = NULL;
+ obj_aout_sym_hashes (abfd) = NULL;
+
+ 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_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 addresses between segments, or the starting file
+ position of the text segment -- all of which varies among different
+ versions of a.out. */
+
+ /* Call back to the format-dependent code to fill in the rest of the
+ fields and do any further cleanup. Things that should be filled
+ in by the callback: */
+
+ struct exec *execp = exec_hdr (abfd);
+
+ obj_textsec (abfd)->size = N_TXTSIZE(*execp);
+ obj_textsec (abfd)->raw_size = N_TXTSIZE(*execp);
+ /* data and bss are already filled in since they're so standard */
+
+ /* The virtual memory addresses of the sections */
+ obj_textsec (abfd)->vma = N_TXTADDR(*execp);
+ obj_datasec (abfd)->vma = N_DATADDR(*execp);
+ obj_bsssec (abfd)->vma = N_BSSADDR(*execp);
+
+ /* The file offsets of the sections */
+ obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
+ obj_datasec (abfd)->filepos = N_DATOFF(*execp);
+
+ /* The file offsets of the relocation info */
+ obj_textsec (abfd)->rel_filepos = N_TRELOFF(*execp);
+ obj_datasec (abfd)->rel_filepos = N_DRELOFF(*execp);
+
+ /* The file offsets of the string table and symbol table. */
+ obj_str_filepos (abfd) = N_STROFF (*execp);
+ obj_sym_filepos (abfd) = N_SYMOFF (*execp);
+
+ /* Determine the architecture and machine type of the object file. */
+ switch (N_MACHTYPE (*exec_hdr (abfd))) {
+ default:
+ abfd->obj_arch = bfd_arch_obscure;
+ break;
+ }
+
+ adata(abfd)->page_size = TARGET_PAGE_SIZE;
+ adata(abfd)->segment_size = SEGMENT_SIZE;
+ adata(abfd)->exec_bytes_size = EXEC_BYTES_SIZE;
+
+ return abfd->xvec;
+
+ /* The architecture is encoded in various ways in various a.out variants,
+ or is not encoded at all in some of them. The relocation size depends
+ on the architecture and the a.out variant. Finally, the return value
+ is the bfd_target vector in use. If an error occurs, return zero and
+ set bfd_error to the appropriate error code.
+
+ Formats such as b.out, which have additional fields in the a.out
+ header, should cope with them in this callback as well. */
+#endif /* DOCUMENTATION */
+
+ result = (*callback_to_real_object_p)(abfd);
+
+ /* 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
+ executable even if their entry point address is 0, as long as
+ their text starts at zero.). */
+ if ((execp->a_entry >= obj_textsec(abfd)->vma) &&
+ (execp->a_entry < obj_textsec(abfd)->vma + obj_textsec(abfd)->_raw_size))
+ abfd->flags |= EXEC_P;
+#ifdef STAT_FOR_EXEC
+ else
+ {
+ struct stat stat_buf;
+
+ /* 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. */
+ if (abfd->iostream != NULL
+ && (abfd->flags & BFD_IN_MEMORY) == 0
+ && (fstat(fileno((FILE *) (abfd->iostream)), &stat_buf) == 0)
+ && ((stat_buf.st_mode & 0111) != 0))
+ abfd->flags |= EXEC_P;
+ }
+#endif /* STAT_FOR_EXEC */
+
+ if (result)
+ {
+#if 0 /* These should be set correctly anyways. */
+ abfd->sections = obj_textsec (abfd);
+ obj_textsec (abfd)->next = obj_datasec (abfd);
+ obj_datasec (abfd)->next = obj_bsssec (abfd);
+#endif
+ }
+ else
+ {
+ free (rawptr);
+ abfd->tdata.aout_data = oldrawptr;
+ }
+ return result;
+}
+
+/*
+FUNCTION
+ aout_@var{size}_mkobject
+
+SYNOPSIS
+ boolean aout_@var{size}_mkobject, (bfd *abfd);
+
+DESCRIPTION
+ Initialize BFD @var{abfd} for use with a.out files.
+*/
+
+boolean
+NAME(aout,mkobject) (abfd)
+ bfd *abfd;
+{
+ struct aout_data_struct *rawptr;
+
+ 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)
+ return false;
+
+ abfd->tdata.aout_data = rawptr;
+ exec_hdr (abfd) = &(rawptr->e);
+
+ obj_textsec (abfd) = (asection *)NULL;
+ obj_datasec (abfd) = (asection *)NULL;
+ obj_bsssec (abfd) = (asection *)NULL;
+
+ return true;
+}
+
+
+/*
+FUNCTION
+ 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
+ architecture and machine, or <<M_UNKNOWN>> if that exact architecture
+ and machine can't be represented in a.out format.
+
+ If the architecture is understood, machine type 0 (default)
+ is always understood.
+*/
+
+enum machine_type
+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:
+ if (machine == 0
+ || machine == bfd_mach_sparc
+ || machine == bfd_mach_sparc_v9)
+ arch_flags = M_SPARC;
+ break;
+
+ case bfd_arch_m68k:
+ switch (machine) {
+ case 0: arch_flags = M_68010; 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;
+ }
+ break;
+
+ case bfd_arch_i386:
+ if (machine == 0) arch_flags = M_386;
+ break;
+
+ case bfd_arch_a29k:
+ if (machine == 0) arch_flags = M_29K;
+ break;
+
+ case bfd_arch_arm:
+ if (machine == 0) arch_flags = M_ARM;
+ break;
+
+ case bfd_arch_mips:
+ switch (machine) {
+ case 0:
+ case 2000:
+ case 3000: arch_flags = M_MIPS1; break;
+ case 4000: /* mips3 */
+ case 4400:
+ case 8000: /* mips4 */
+ /* real mips2: */
+ case 6000: arch_flags = M_MIPS2; break;
+ default: arch_flags = M_UNKNOWN; break;
+ }
+ 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;
+
+ case bfd_arch_vax:
+ *unknown = false;
+ break;
+
+
+ default:
+ arch_flags = M_UNKNOWN;
+ }
+
+ if (arch_flags != M_UNKNOWN)
+ *unknown = false;
+
+ return arch_flags;
+}
+
+
+/*
+FUNCTION
+ aout_@var{size}_set_arch_mach
+
+SYNOPSIS
+ boolean aout_@var{size}_set_arch_mach,
+ (bfd *,
+ 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
+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)
+ {
+ boolean unknown;
+
+ NAME(aout,machine_type) (arch, machine, &unknown);
+ if (unknown)
+ return false;
+ }
+
+ /* Determine the size of a relocation entry */
+ switch (arch) {
+ case bfd_arch_sparc:
+ case bfd_arch_a29k:
+ case bfd_arch_mips:
+ obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
+ break;
+ default:
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+ break;
+ }
+
+ 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;
+ 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. */
+ 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;
+ }
+ else
+ vma = obj_datasec(abfd)->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;
+ }
+ else
+ {
+ /* The VMA of the .bss section is set by the the VMA of the
+ .data section plus the size of the .data section. We may
+ need to add padding bytes to make this true. */
+ pad = obj_bsssec (abfd)->vma - vma;
+ if (pad > 0)
+ {
+ obj_datasec (abfd)->_raw_size += pad;
+ pos += pad;
+ }
+ }
+ 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));
+ text_pad = 0;
+ }
+ else
+ {
+ /* The .text section is being loaded at an unusual address. We
+ may need to pad it such that the .data section starts at a page
+ boundary. */
+ if (ztih)
+ text_pad = ((obj_textsec (abfd)->filepos - obj_textsec (abfd)->vma)
+ & (adata (abfd).page_size - 1));
+ else
+ text_pad = ((- obj_textsec (abfd)->vma)
+ & (adata (abfd).page_size - 1));
+ }
+
+ /* 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
+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 (! 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
+ (TARGET_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
+ right from BFD flags to alignment/positioning characteristics. But the
+ old code was sloppy enough about handling the flags, and had enough
+ 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 (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
+ fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n",
+ ({ char *str;
+ switch (adata(abfd).magic) {
+ case n_magic: str = "NMAGIC"; break;
+ case o_magic: str = "OMAGIC"; break;
+ case z_magic: str = "ZMAGIC"; break;
+ default: abort ();
+ }
+ 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);
+#endif
+#endif
+
+ switch (adata(abfd).magic)
+ {
+ case o_magic:
+ adjust_o_magic (abfd, execp);
+ break;
+ case z_magic:
+ adjust_z_magic (abfd, execp);
+ break;
+ case n_magic:
+ 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_bsssec(abfd)->vma, obj_bsssec(abfd)->_raw_size);
+#endif
+
+ return true;
+}
+
+/*
+FUNCTION
+ 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.
+*/
+boolean
+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;
+
+
+ if (bfd_get_format (abfd) == bfd_object)
+ {
+ if (obj_textsec(abfd) == NULL && !strcmp(newsect->name, ".text")) {
+ obj_textsec(abfd)= newsect;
+ 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;
+ return true;
+ }
+
+ if (obj_bsssec(abfd) == NULL && !strcmp(newsect->name, ".bss")) {
+ obj_bsssec(abfd) = newsect;
+ newsect->target_index = N_BSS;
+ return true;
+ }
+
+ }
+
+ /* We allow more than three sections internally */
+ return true;
+}
+
+boolean
+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;
+
+ if (! abfd->output_has_begun)
+ {
+ if (! NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end))
+ return false;
+ }
+
+ if (section == obj_bsssec (abfd))
+ {
+ bfd_set_error (bfd_error_no_contents);
+ return false;
+ }
+
+ if (section != obj_textsec (abfd)
+ && section != obj_datasec (abfd))
+ {
+ (*_bfd_error_handler)
+ ("%s: can not represent section `%s' in a.out object file format",
+ bfd_get_filename (abfd), bfd_get_section_name (abfd, section));
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+
+ if (count != 0)
+ {
+ if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
+ || bfd_write (location, 1, count, abfd) != count)
+ return false;
+ }
+
+ return true;
+}
+
+/* Read the external symbols from an a.out file. */
+
+static boolean
+aout_get_external_symbols (abfd)
+ bfd *abfd;
+{
+ if (obj_aout_external_syms (abfd) == (struct external_nlist *) NULL)
+ {
+ bfd_size_type count;
+ struct external_nlist *syms;
+
+ count = exec_hdr (abfd)->a_syms / EXTERNAL_NLIST_SIZE;
+
+#ifdef USE_MMAP
+ if (bfd_get_file_window (abfd,
+ obj_sym_filepos (abfd), exec_hdr (abfd)->a_syms,
+ &obj_aout_sym_window (abfd), true) == false)
+ return false;
+ syms = (struct external_nlist *) obj_aout_sym_window (abfd).data;
+#else
+ /* 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 *)
+ bfd_malloc ((size_t) count * EXTERNAL_NLIST_SIZE));
+ if (syms == (struct external_nlist *) NULL && count != 0)
+ 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;
+ }
+#endif
+
+ 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);
+
+#ifdef USE_MMAP
+ if (bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize,
+ &obj_aout_string_window (abfd), true) == false)
+ return false;
+ strings = (char *) obj_aout_string_window (abfd).data;
+#else
+ strings = (char *) bfd_malloc ((size_t) stringsize + 1);
+ if (strings == NULL)
+ 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;
+ }
+#endif
+
+ /* Ensure that a zero index yields an empty string. */
+ strings[0] = '\0';
+
+ strings[stringsize - 1] = 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:
+ {
+ asection *section;
+ arelent_chain *reloc;
+ asection *into_section;
+
+ /* 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.
+
+ This action is actually obsolete; it used to make the
+ linker do the right thing, but the linker no longer uses
+ this function. */
+
+ 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)
+ 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)
+ return false;
+
+ /* Build a relocation entry for the constructor. */
+ switch (cache_ptr->type & N_TYPE)
+ {
+ case N_SETA:
+ into_section = bfd_abs_section_ptr;
+ cache_ptr->type = N_ABS;
+ break;
+ case N_SETT:
+ into_section = obj_textsec (abfd);
+ cache_ptr->type = N_TEXT;
+ break;
+ case N_SETD:
+ into_section = obj_datasec (abfd);
+ cache_ptr->type = N_DATA;
+ break;
+ case N_SETB:
+ into_section = obj_bsssec (abfd);
+ cache_ptr->type = N_BSS;
+ break;
+ }
+
+ /* 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;
+ 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, 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;
+
+ reloc->next = section->constructor_chain;
+ section->constructor_chain = reloc;
+ reloc->relent.address = section->_raw_size;
+ section->_raw_size += BYTES_IN_WORD;
+
+ reloc->relent.howto = CTOR_TABLE_RELOC_HOWTO(abfd);
+
+ cache_ptr->symbol.flags |= BSF_CONSTRUCTOR;
+ }
+ break;
+
+ 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;
+ cache_ptr->symbol.section = bfd_abs_section_ptr;
+ break;
+
+ 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_ind_section_ptr;
+ break;
+
+ case N_WEAKU:
+ cache_ptr->symbol.section = bfd_und_section_ptr;
+ cache_ptr->symbol.flags = BSF_WEAK;
+ break;
+
+ case N_WEAKA:
+ cache_ptr->symbol.section = bfd_abs_section_ptr;
+ cache_ptr->symbol.flags = BSF_WEAK;
+ break;
+
+ 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;
+
+ 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;
+ }
+
+ return true;
+}
+
+/* Set the fields of SYM_POINTER according to CACHE_PTR. */
+
+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;
+ asection *sec;
+ bfd_vma off;
+
+ /* Mask out any existing type bits in case copying from one section
+ to another. */
+ sym_pointer->e_type[0] &= ~N_TYPE;
+
+ sec = bfd_get_section (cache_ptr);
+ off = 0;
+
+ if (sec == NULL)
+ {
+ /* This case occurs, e.g., for the *DEBUG* section of a COFF
+ file. */
+ (*_bfd_error_handler)
+ ("%s: can not represent section `%s' in a.out object file format",
+ bfd_get_filename (abfd), bfd_get_section_name (abfd, sec));
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+
+ if (sec->output_section != NULL)
+ {
+ off = sec->output_offset;
+ sec = sec->output_section;
+ }
+
+ if (bfd_is_abs_section (sec))
+ sym_pointer->e_type[0] |= N_ABS;
+ else if (sec == obj_textsec (abfd))
+ sym_pointer->e_type[0] |= N_TEXT;
+ else if (sec == obj_datasec (abfd))
+ sym_pointer->e_type[0] |= N_DATA;
+ else if (sec == obj_bsssec (abfd))
+ sym_pointer->e_type[0] |= N_BSS;
+ else if (bfd_is_und_section (sec))
+ sym_pointer->e_type[0] = N_UNDF | N_EXT;
+ else if (bfd_is_ind_section (sec))
+ sym_pointer->e_type[0] = N_INDR;
+ else if (bfd_is_com_section (sec))
+ sym_pointer->e_type[0] = N_UNDF | N_EXT;
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: can not represent section `%s' in a.out object file format",
+ bfd_get_filename (abfd), bfd_get_section_name (abfd, sec));
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+
+ /* Turn the symbol from section relative to absolute again */
+ value += sec->vma + off;
+
+ if ((cache_ptr->flags & BSF_WARNING) != 0)
+ sym_pointer->e_type[0] = N_WARNING;
+
+ 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) != 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. */
+
+asymbol *
+NAME(aout,make_empty_symbol) (abfd)
+ bfd *abfd;
+{
+ aout_symbol_type *new =
+ (aout_symbol_type *)bfd_zalloc (abfd, sizeof (aout_symbol_type));
+ if (!new)
+ return NULL;
+ new->symbol.the_bfd = abfd;
+
+ return &new->symbol;
+}
+
+/* Translate a set of internal symbols into external symbols. */
+
+boolean
+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;
+{
+ struct external_nlist *ext_end;
+
+ ext_end = ext + count;
+ for (; ext < ext_end; ext++, in++)
+ {
+ 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.p = NULL;
+
+ if (! translate_from_native_sym_flags (abfd, in))
+ return false;
+
+ if (dynamic)
+ in->symbol.flags |= BSF_DYNAMIC;
+ }
+
+ 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;
+
+ cached_size = (obj_aout_external_sym_count (abfd)
+ * sizeof (aout_symbol_type));
+ cached = (aout_symbol_type *) bfd_malloc (cached_size);
+ if (cached == NULL && cached_size != 0)
+ return false;
+ if (cached_size != 0)
+ 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)
+ {
+#ifdef USE_MMAP
+ bfd_free_window (&obj_aout_sym_window (abfd));
+#else
+ free (obj_aout_external_syms (abfd));
+#endif
+ obj_aout_external_syms (abfd) = NULL;
+ }
+
+ return true;
+}
+
+/* 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.
+
+ This hash table code breaks dbx on SunOS 4.1.3, so we don't do it
+ if BFD_TRADITIONAL_FORMAT is set. */
+
+static bfd_size_type add_to_stringtab
+ PARAMS ((bfd *, struct bfd_strtab_hash *, const char *, boolean));
+static boolean emit_stringtab PARAMS ((bfd *, struct bfd_strtab_hash *));
+
+/* Get the index of a string in a strtab, adding it if it is not
+ already present. */
+
+static INLINE bfd_size_type
+add_to_stringtab (abfd, tab, str, copy)
+ bfd *abfd;
+ struct bfd_strtab_hash *tab;
+ const char *str;
+ boolean copy;
+{
+ boolean hash;
+ bfd_size_type index;
+
+ /* An index of 0 always means the empty string. */
+ if (str == 0 || *str == '\0')
+ return 0;
+
+ /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx
+ doesn't understand a hashed string table. */
+ hash = true;
+ if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+
+ index = _bfd_stringtab_add (tab, str, hash, copy);
+
+ if (index != (bfd_size_type) -1)
+ {
+ /* Add BYTES_IN_WORD to the return value to account for the
+ space taken up by the string table size. */
+ index += BYTES_IN_WORD;
+ }
+
+ return index;
+}
+
+/* Write out a strtab. ABFD is already at the right location in the
+ file. */
+
+static boolean
+emit_stringtab (abfd, tab)
+ register bfd *abfd;
+ struct bfd_strtab_hash *tab;
+{
+ bfd_byte buffer[BYTES_IN_WORD];
+
+ /* The string table starts with the size. */
+ PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer);
+ if (bfd_write ((PTR) buffer, 1, BYTES_IN_WORD, abfd) != BYTES_IN_WORD)
+ return false;
+
+ return _bfd_stringtab_emit (abfd, tab);
+}
+
+boolean
+NAME(aout,write_syms) (abfd)
+ bfd *abfd;
+{
+ unsigned int count ;
+ asymbol **generic = bfd_get_outsymbols (abfd);
+ struct bfd_strtab_hash *strtab;
+
+ strtab = _bfd_stringtab_init ();
+ if (strtab == NULL)
+ return false;
+
+ for (count = 0; count < bfd_get_symcount (abfd); count++)
+ {
+ asymbol *g = generic[count];
+ bfd_size_type indx;
+ struct external_nlist nsp;
+
+ 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)
+ {
+ bfd_h_put_16(abfd, aout_symbol(g)->desc, nsp.e_desc);
+ bfd_h_put_8(abfd, aout_symbol(g)->other, nsp.e_other);
+ bfd_h_put_8(abfd, aout_symbol(g)->type, nsp.e_type);
+ }
+ else
+ {
+ bfd_h_put_16(abfd,0, nsp.e_desc);
+ bfd_h_put_8(abfd, 0, nsp.e_other);
+ bfd_h_put_8(abfd, 0, nsp.e_type);
+ }
+
+ if (! translate_to_native_sym_flags (abfd, g, &nsp))
+ goto error_return;
+
+ if (bfd_write((PTR)&nsp,1,EXTERNAL_NLIST_SIZE, abfd)
+ != EXTERNAL_NLIST_SIZE)
+ goto error_return;
+
+ /* NB: `KEEPIT' currently overlays `udata.p', so set this only
+ here, at the end. */
+ g->KEEPIT = count;
+ }
+
+ if (! emit_stringtab (abfd, strtab))
+ goto error_return;
+
+ _bfd_stringtab_free (strtab);
+
+ return true;
+
+error_return:
+ _bfd_stringtab_free (strtab);
+ return false;
+}
+
+
+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 -1;
+
+ for (symbase = obj_aout_symbols(abfd); counter++ < bfd_get_symcount (abfd);)
+ *(location++) = (asymbol *)( symbase++);
+ *location++ =0;
+ return bfd_get_symcount (abfd);
+}
+
+
+/* Standard reloc stuff */
+/* Output standard relocation information to a file in target byte order. */
+
+void
+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);
+ int r_extern;
+ unsigned int r_length;
+ int r_pcrel;
+ int r_baserel, r_jmptable, r_relative;
+ asection *output_section = sym->section->output_section;
+
+ PUT_WORD(abfd, g->address, natptr->r_address);
+
+ r_length = g->howto->size ; /* Size as a power of two */
+ 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 = (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 */
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here
+ */
+
+
+ if (bfd_is_com_section (output_section)
+ || bfd_is_abs_section (output_section)
+ || bfd_is_und_section (output_section))
+ {
+ if (bfd_abs_section_ptr->symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+ r_extern = 1;
+ r_index = (*(g->sym_ptr_ptr))->KEEPIT;
+
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd)) {
+ natptr->r_index[0] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[2] = r_index;
+ natptr->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 {
+ natptr->r_index[2] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[0] = r_index;
+ natptr->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);
+ }
+}
+
+
+/* Extended stuff */
+/* Output extended relocation information to a file in target byte order. */
+
+void
+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;
+ unsigned int r_type;
+ unsigned int r_addend;
+ asymbol *sym = *(g->sym_ptr_ptr);
+ asection *output_section = sym->section->output_section;
+
+ PUT_WORD (abfd, g->address, natptr->r_address);
+
+ r_type = (unsigned int) g->howto->type;
+
+ r_addend = g->addend;
+ if ((sym->flags & BSF_SECTION_SYM) != 0)
+ r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma;
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here. */
+
+ if (bfd_is_abs_section (bfd_get_section (sym)))
+ {
+ r_extern = 0;
+ r_index = 0;
+ }
+ else if ((sym->flags & BSF_SECTION_SYM) == 0)
+ {
+ if (bfd_is_und_section (bfd_get_section (sym))
+ || (sym->flags & BSF_GLOBAL) != 0)
+ r_extern = 1;
+ else
+ r_extern = 0;
+ r_index = (*(g->sym_ptr_ptr))->KEEPIT;
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd)) {
+ natptr->r_index[0] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[2] = r_index;
+ natptr->r_type[0] =
+ ((r_extern? RELOC_EXT_BITS_EXTERN_BIG: 0)
+ | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG));
+ } else {
+ natptr->r_index[2] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[0] = r_index;
+ natptr->r_type[0] =
+ (r_extern? RELOC_EXT_BITS_EXTERN_LITTLE: 0)
+ | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
+ }
+
+ PUT_WORD (abfd, r_addend, natptr->r_addend);
+}
+
+/* BFD deals internally with all things based from the section they're
+ in. so, something in 10 bytes into a text section with a base of
+ 50 would have a symbol (.text+10) and know .text vma was 50.
+
+ Aout keeps all it's symbols based from zero, so the symbol would
+ contain 60. This macro subs the base of each section from the value
+ to give the true offset from the section */
+
+
+#define MOVE_ADDRESS(ad) \
+ if (r_extern) { \
+ /* undefined symbol */ \
+ cache_ptr->sym_ptr_ptr = symbols + r_index; \
+ cache_ptr->addend = ad; \
+ } else { \
+ /* defined, section relative. replace symbol with pointer to \
+ symbol which points to section */ \
+ switch (r_index) { \
+ case N_TEXT: \
+ case N_TEXT | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->textsec->vma; \
+ break; \
+ case N_DATA: \
+ case N_DATA | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->datasec->vma; \
+ break; \
+ case N_BSS: \
+ case N_BSS | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->bsssec->vma; \
+ break; \
+ default: \
+ case N_ABS: \
+ case N_ABS | N_EXT: \
+ cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
+ cache_ptr->addend = ad; \
+ break; \
+ } \
+ } \
+
+void
+NAME(aout,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
+ bfd *abfd;
+ struct reloc_ext_external *bytes;
+ arelent *cache_ptr;
+ asymbol **symbols;
+ bfd_size_type symcount;
+{
+ unsigned int r_index;
+ int r_extern;
+ unsigned int r_type;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+
+ cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd)) {
+ r_index = (bytes->r_index[0] << 16)
+ | (bytes->r_index[1] << 8)
+ | bytes->r_index[2];
+ r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
+ r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
+ >> RELOC_EXT_BITS_TYPE_SH_BIG;
+ } else {
+ r_index = (bytes->r_index[2] << 16)
+ | (bytes->r_index[1] << 8)
+ | bytes->r_index[0];
+ r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
+ r_type = (bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
+ >> RELOC_EXT_BITS_TYPE_SH_LITTLE;
+ }
+
+ cache_ptr->howto = howto_table_ext + r_type;
+
+ /* Base relative relocs are always against the symbol table,
+ regardless of the setting of r_extern. r_extern just reflects
+ whether the symbol the reloc is against is local or global. */
+ if (r_type == RELOC_BASE10
+ || r_type == RELOC_BASE13
+ || r_type == RELOC_BASE22)
+ r_extern = 1;
+
+ if (r_extern && r_index > symcount)
+ {
+ /* We could arrange to return an error, but it might be useful
+ to see the file even if it is bad. */
+ r_extern = 0;
+ r_index = N_ABS;
+ }
+
+ MOVE_ADDRESS(GET_SWORD(abfd, bytes->r_addend));
+}
+
+void
+NAME(aout,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
+ bfd *abfd;
+ struct reloc_std_external *bytes;
+ arelent *cache_ptr;
+ asymbol **symbols;
+ bfd_size_type symcount;
+{
+ unsigned int r_index;
+ int r_extern;
+ unsigned int r_length;
+ int r_pcrel;
+ int r_baserel, r_jmptable, r_relative;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+ unsigned int howto_idx;
+
+ cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd)) {
+ r_index = (bytes->r_index[0] << 16)
+ | (bytes->r_index[1] << 8)
+ | bytes->r_index[2];
+ r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
+ r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
+ r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
+ r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+ r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
+ r_length = (bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
+ >> RELOC_STD_BITS_LENGTH_SH_BIG;
+ } else {
+ r_index = (bytes->r_index[2] << 16)
+ | (bytes->r_index[1] << 8)
+ | bytes->r_index[0];
+ r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
+ r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
+ r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
+ r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
+ r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
+ r_length = (bytes->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));
+ cache_ptr->howto = howto_table_std + howto_idx;
+ BFD_ASSERT (cache_ptr->howto->type != (unsigned int) -1);
+
+ /* Base relative relocs are always against the symbol table,
+ regardless of the setting of r_extern. r_extern just reflects
+ whether the symbol the reloc is against is local or global. */
+ if (r_baserel)
+ r_extern = 1;
+
+ if (r_extern && r_index > symcount)
+ {
+ /* We could arrange to return an error, but it might be useful
+ to see the file even if it is bad. */
+ r_extern = 0;
+ r_index = N_ABS;
+ }
+
+ MOVE_ADDRESS(0);
+}
+
+/* Read and swap the relocs for a section. */
+
+boolean
+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->flags & SEC_CONSTRUCTOR)
+ return true;
+
+ if (asect == obj_datasec (abfd))
+ reloc_size = exec_hdr(abfd)->a_drsize;
+ else if (asect == obj_textsec (abfd))
+ reloc_size = exec_hdr(abfd)->a_trsize;
+ else if (asect == obj_bsssec (abfd))
+ reloc_size = 0;
+ else
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
+ return false;
+
+ each_size = obj_reloc_entry_size (abfd);
+
+ count = reloc_size / each_size;
+
+ reloc_cache = (arelent *) bfd_malloc ((size_t) (count * sizeof (arelent)));
+ if (reloc_cache == NULL && count != 0)
+ return false;
+ memset (reloc_cache, 0, count * sizeof (arelent));
+
+ relocs = bfd_malloc ((size_t) reloc_size);
+ if (relocs == NULL && reloc_size != 0)
+ {
+ free (reloc_cache);
+ 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,
+ bfd_get_symcount (abfd));
+ }
+ 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,
+ bfd_get_symcount (abfd));
+ }
+
+ free (relocs);
+
+ asect->relocation = reloc_cache;
+ asect->reloc_count = cache_ptr - reloc_cache;
+
+ return true;
+}
+
+/* Write out a relocation section into an object file. */
+
+boolean
+NAME(aout,squirt_out_relocs) (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ arelent **generic;
+ unsigned char *native, *natptr;
+ size_t each_size;
+
+ unsigned int count = section->reloc_count;
+ size_t natsize;
+
+ if (count == 0) return true;
+
+ each_size = obj_reloc_entry_size (abfd);
+ natsize = each_size * count;
+ native = (unsigned char *) bfd_zalloc (abfd, natsize);
+ if (!native)
+ return false;
+
+ generic = section->orelocation;
+
+ if (each_size == RELOC_EXT_SIZE)
+ {
+ for (natptr = native;
+ count != 0;
+ --count, natptr += each_size, ++generic)
+ NAME(aout,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *)natptr);
+ }
+ else
+ {
+ for (natptr = native;
+ count != 0;
+ --count, natptr += each_size, ++generic)
+ MY_swap_std_reloc_out(abfd, *generic, (struct reloc_std_external *)natptr);
+ }
+
+ if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
+ bfd_release(abfd, native);
+ return false;
+ }
+ bfd_release (abfd, native);
+
+ return true;
+}
+
+/* This is stupid. This function should be a boolean predicate */
+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 -1;
+
+ if (section->flags & SEC_CONSTRUCTOR) {
+ arelent_chain *chain = section->constructor_chain;
+ for (count = 0; count < section->reloc_count; count ++) {
+ *relptr ++ = &chain->relent;
+ chain = chain->next;
+ }
+ }
+ else {
+ tblptr = section->relocation;
+
+ for (count = 0; count++ < section->reloc_count;)
+ {
+ *relptr++ = tblptr++;
+ }
+ }
+ *relptr = 0;
+
+ return section->reloc_count;
+}
+
+long
+NAME(aout,get_reloc_upper_bound) (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ if (bfd_get_format (abfd) != bfd_object) {
+ 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));
+
+ if (asect == obj_textsec (abfd))
+ return (sizeof (arelent *)
+ * ((exec_hdr(abfd)->a_trsize / obj_reloc_entry_size (abfd))
+ + 1));
+
+ if (asect == obj_bsssec (abfd))
+ return sizeof (arelent *);
+
+ if (asect == obj_bsssec (abfd))
+ return 0;
+
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+}
+
+
+long
+NAME(aout,get_symtab_upper_bound) (abfd)
+ bfd *abfd;
+{
+ if (!NAME(aout,slurp_symbol_table)(abfd))
+ return -1;
+
+ return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
+}
+
+/*ARGSUSED*/
+ alent *
+NAME(aout,get_lineno) (ignore_abfd, ignore_symbol)
+ bfd *ignore_abfd;
+ asymbol *ignore_symbol;
+{
+return (alent *)NULL;
+}
+
+/*ARGSUSED*/
+void
+NAME(aout,get_symbol_info) (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+
+ if (ret->type == '?')
+ {
+ int type_code = aout_symbol(symbol)->type & 0xff;
+ const char *stab_name = bfd_get_stab_name (type_code);
+ static char buf[10];
+
+ if (stab_name == NULL)
+ {
+ sprintf(buf, "(%d)", type_code);
+ stab_name = buf;
+ }
+ ret->type = '-';
+ ret->stab_type = type_code;
+ ret->stab_other = (unsigned)(aout_symbol(symbol)->other & 0xff);
+ ret->stab_desc = (unsigned)(aout_symbol(symbol)->desc & 0xffff);
+ ret->stab_name = stab_name;
+ }
+}
+
+/*ARGSUSED*/
+void
+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;
+
+ switch (how) {
+ case bfd_print_symbol_name:
+ if (symbol->name)
+ fprintf(file,"%s", symbol->name);
+ break;
+ case bfd_print_symbol_more:
+ fprintf(file,"%4x %2x %2x",(unsigned)(aout_symbol(symbol)->desc & 0xffff),
+ (unsigned)(aout_symbol(symbol)->other & 0xff),
+ (unsigned)(aout_symbol(symbol)->type));
+ break;
+ case bfd_print_symbol_all:
+ {
+ CONST char *section_name = symbol->section->name;
+
+
+ bfd_print_symbol_vandf((PTR)file,symbol);
+
+ fprintf(file," %-5s %04x %02x %02x",
+ section_name,
+ (unsigned)(aout_symbol(symbol)->desc & 0xffff),
+ (unsigned)(aout_symbol(symbol)->other & 0xff),
+ (unsigned)(aout_symbol(symbol)->type & 0xff));
+ if (symbol->name)
+ fprintf(file," %s", symbol->name);
+ }
+ break;
+ }
+}
+
+/* If we don't have to allocate more than 1MB to hold the generic
+ symbols, we use the generic minisymbol methord: it's faster, since
+ it only translates the symbols once, not multiple times. */
+#define MINISYM_THRESHOLD (1000000 / sizeof (asymbol))
+
+/* Read minisymbols. For minisymbols, we use the unmodified a.out
+ symbols. The minisymbol_to_symbol function translates these into
+ BFD asymbol structures. */
+
+long
+NAME(aout,read_minisymbols) (abfd, dynamic, minisymsp, sizep)
+ bfd *abfd;
+ boolean dynamic;
+ PTR *minisymsp;
+ unsigned int *sizep;
+{
+ if (dynamic)
+ {
+ /* We could handle the dynamic symbols here as well, but it's
+ easier to hand them off. */
+ return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
+ }
+
+ if (! aout_get_external_symbols (abfd))
+ return -1;
+
+ if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
+ return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
+
+ *minisymsp = (PTR) obj_aout_external_syms (abfd);
+
+ /* By passing the external symbols back from this routine, we are
+ giving up control over the memory block. Clear
+ obj_aout_external_syms, so that we do not try to free it
+ ourselves. */
+ obj_aout_external_syms (abfd) = NULL;
+
+ *sizep = EXTERNAL_NLIST_SIZE;
+ return obj_aout_external_sym_count (abfd);
+}
+
+/* Convert a minisymbol to a BFD asymbol. A minisymbol is just an
+ unmodified a.out symbol. The SYM argument is a structure returned
+ by bfd_make_empty_symbol, which we fill in here. */
+
+asymbol *
+NAME(aout,minisymbol_to_symbol) (abfd, dynamic, minisym, sym)
+ bfd *abfd;
+ boolean dynamic;
+ const PTR minisym;
+ asymbol *sym;
+{
+ if (dynamic
+ || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
+ return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym);
+
+ memset (sym, 0, sizeof (aout_symbol_type));
+
+ /* We call translate_symbol_table to translate a single symbol. */
+ if (! (NAME(aout,translate_symbol_table)
+ (abfd,
+ (aout_symbol_type *) sym,
+ (struct external_nlist *) minisym,
+ (bfd_size_type) 1,
+ obj_aout_external_strings (abfd),
+ obj_aout_external_string_size (abfd),
+ false)))
+ return NULL;
+
+ return sym;
+}
+
+/*
+ provided a BFD, a section and an offset into the section, calculate
+ and return the name of the source file and the line nearest to the
+ wanted location.
+*/
+
+boolean
+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;
+ CONST char *directory_name = NULL;
+ CONST char *main_file_name = NULL;
+ CONST char *current_file_name = NULL;
+ CONST char *line_file_name = NULL; /* Value of current_file_name at line number. */
+ bfd_vma low_line_vma = 0;
+ bfd_vma low_func_vma = 0;
+ asymbol *func = 0;
+ size_t filelen, funclen;
+ char *buf;
+
+ *filename_ptr = abfd->filename;
+ *functionname_ptr = 0;
+ *line_ptr = 0;
+ if (symbols != (asymbol **)NULL) {
+ for (p = symbols; *p; p++) {
+ aout_symbol_type *q = (aout_symbol_type *)(*p);
+ next:
+ switch (q->type){
+ case N_SO:
+ main_file_name = current_file_name = q->symbol.name;
+ /* Look ahead to next symbol to check if that too is an N_SO. */
+ p++;
+ if (*p == NULL)
+ break;
+ q = (aout_symbol_type *)(*p);
+ if (q->type != (int)N_SO)
+ goto next;
+
+ /* Found a second N_SO First is directory; second is filename. */
+ directory_name = current_file_name;
+ main_file_name = current_file_name = q->symbol.name;
+ if (obj_textsec(abfd) != section)
+ goto done;
+ break;
+ case N_SOL:
+ current_file_name = q->symbol.name;
+ break;
+
+ case N_SLINE:
+
+ case N_DSLINE:
+ case N_BSLINE:
+ /* We'll keep this if it resolves nearer than the one we have
+ already. */
+ if (q->symbol.value >= low_line_vma
+ && q->symbol.value <= offset)
+ {
+ *line_ptr = q->desc;
+ low_line_vma = q->symbol.value;
+ line_file_name = current_file_name;
+ }
+ break;
+ case N_FUN:
+ {
+ /* We'll keep this if it is nearer than the one we have already */
+ if (q->symbol.value >= low_func_vma &&
+ q->symbol.value <= offset) {
+ low_func_vma = q->symbol.value;
+ func = (asymbol *)q;
+ }
+ else if (q->symbol.value > offset)
+ goto done;
+ }
+ break;
+ }
+ }
+ }
+
+ done:
+ if (*line_ptr != 0)
+ main_file_name = line_file_name;
+
+ if (main_file_name == NULL
+ || main_file_name[0] == '/'
+ || directory_name == NULL)
+ filelen = 0;
+ else
+ filelen = strlen (directory_name) + strlen (main_file_name);
+ if (func == NULL)
+ funclen = 0;
+ else
+ funclen = strlen (bfd_asymbol_name (func));
+
+ if (adata (abfd).line_buf != NULL)
+ free (adata (abfd).line_buf);
+ if (filelen + funclen == 0)
+ adata (abfd).line_buf = buf = NULL;
+ else
+ {
+ buf = (char *) bfd_malloc (filelen + funclen + 2);
+ adata (abfd).line_buf = buf;
+ if (buf == NULL)
+ return false;
+ }
+
+ if (main_file_name != NULL)
+ {
+ if (main_file_name[0] == '/' || directory_name == NULL)
+ *filename_ptr = main_file_name;
+ else
+ {
+ sprintf (buf, "%s%s", directory_name, main_file_name);
+ *filename_ptr = buf;
+ buf += filelen + 1;
+ }
+ }
+
+ if (func)
+ {
+ const char *function = func->name;
+ char *p;
+
+ /* 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')
+ strcpy (buf, function);
+ else
+ {
+ buf[0] = bfd_get_symbol_leading_char (abfd);
+ strcpy (buf + 1, function);
+ }
+ /* Have to remove : stuff */
+ p = strchr (buf, ':');
+ if (p != NULL)
+ *p = '\0';
+ *functionname_ptr = buf;
+ }
+
+ return true;
+}
+
+/*ARGSUSED*/
+int
+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));
+#ifdef USE_MMAP
+ obj_aout_external_syms (abfd) = 0;
+ bfd_free_window (&obj_aout_sym_window (abfd));
+ bfd_free_window (&obj_aout_string_window (abfd));
+ obj_aout_external_strings (abfd) = 0;
+#else
+ BFCI_FREE (obj_aout_external_syms (abfd));
+ BFCI_FREE (obj_aout_external_strings (abfd));
+#endif
+ 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)
+ 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 *)
+ bfd_alloc (abfd, sizeof (struct aout_link_hash_table)));
+ if (ret == NULL)
+ 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;
+ }
+
+ if (! info->keep_memory || ! *pneeded)
+ {
+ 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)
+ {
+#ifdef USE_MMAP
+ bfd_free_window (&obj_aout_sym_window (abfd));
+#else
+ free ((PTR) obj_aout_external_syms (abfd));
+#endif
+ obj_aout_external_syms (abfd) = (struct external_nlist *) NULL;
+ }
+ if (obj_aout_external_strings (abfd) != (char *) NULL)
+ {
+#ifdef USE_MMAP
+ bfd_free_window (&obj_aout_string_window (abfd));
+#else
+ free ((PTR) obj_aout_external_strings (abfd));
+#endif
+ 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;
+ unsigned int power;
+
+ 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.p = ((struct bfd_link_hash_common_entry *)
+ bfd_hash_allocate (&info->hash->table,
+ sizeof (struct bfd_link_hash_common_entry)));
+ if (h->u.c.p == NULL)
+ return false;
+
+ h->u.c.size = value;
+
+ /* FIXME: This isn't quite right. The maximum
+ alignment of a common symbol should be set by the
+ architecture of the output file, not of the input
+ file. */
+ power = bfd_log2 (value);
+ if (power > bfd_get_arch_info (abfd)->section_align_power)
+ power = bfd_get_arch_info (abfd)->section_align_power;
+ h->u.c.p->alignment_power = power;
+
+ h->u.c.p->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 **));
+ struct external_nlist *syms;
+ 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;
+
+ syms = obj_aout_external_syms (abfd);
+ sym_count = obj_aout_external_sym_count (abfd);
+ strings = obj_aout_external_strings (abfd);
+ if (info->keep_memory)
+ copy = false;
+ else
+ copy = true;
+
+ if ((abfd->flags & DYNAMIC) != 0
+ && aout_backend_info (abfd)->add_dynamic_symbols != NULL)
+ {
+ if (! ((*aout_backend_info (abfd)->add_dynamic_symbols)
+ (abfd, info, &syms, &sym_count, &strings)))
+ return false;
+ }
+
+ /* 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)
+ return false;
+ obj_aout_sym_hashes (abfd) = sym_hash;
+
+ 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 = syms;
+ 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;
+
+ /* Restrict the maximum alignment of a common symbol based on
+ the architecture, since a.out has no way to represent
+ alignment requirements of a section in a .o file. FIXME:
+ This isn't quite right: it should use the architecture of the
+ output file, not the input files. */
+ if ((*sym_hash)->root.type == bfd_link_hash_common
+ && ((*sym_hash)->root.u.c.p->alignment_power >
+ bfd_get_arch_info (abfd)->section_align_power))
+ (*sym_hash)->root.u.c.p->alignment_power =
+ bfd_get_arch_info (abfd)->section_align_power;
+
+ /* If this is a set symbol, and we are not building sets, then
+ it is possible for the hash entry to not have been set. In
+ such a case, treat the symbol as not globally defined. */
+ if ((*sym_hash)->root.type == bfd_link_hash_new)
+ {
+ BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0);
+ *sym_hash = NULL;
+ }
+
+ if (type == (N_INDR | N_EXT) || type == N_WARNING)
+ ++sym_hash;
+ }
+
+ return true;
+}
+
+/* A hash table used for header files with N_BINCL entries. */
+
+struct aout_link_includes_table
+{
+ struct bfd_hash_table root;
+};
+
+/* A linked list of totals that we have found for a particular header
+ file. */
+
+struct aout_link_includes_totals
+{
+ struct aout_link_includes_totals *next;
+ bfd_vma total;
+};
+
+/* An entry in the header file hash table. */
+
+struct aout_link_includes_entry
+{
+ struct bfd_hash_entry root;
+ /* List of totals we have found for this file. */
+ struct aout_link_includes_totals *totals;
+};
+
+/* Look up an entry in an the header file hash table. */
+
+#define aout_link_includes_lookup(table, string, create, copy) \
+ ((struct aout_link_includes_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* 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 bfd_strtab_hash *strtab;
+ /* Header file hash table. */
+ struct aout_link_includes_table includes;
+ /* A buffer large enough to hold the contents of any section. */
+ bfd_byte *contents;
+ /* A buffer large enough to hold the relocs of any section. */
+ PTR relocs;
+ /* A buffer large enough to hold the symbol map of any input BFD. */
+ int *symbol_map;
+ /* A buffer large enough to hold output symbols of any input BFD. */
+ struct external_nlist *output_syms;
+};
+
+static struct bfd_hash_entry *aout_link_includes_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+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));
+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));
+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));
+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));
+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 *));
+
+/* The function to create a new entry in the header file hash table. */
+
+static struct bfd_hash_entry *
+aout_link_includes_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct aout_link_includes_entry *ret =
+ (struct aout_link_includes_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct aout_link_includes_entry *) NULL)
+ ret = ((struct aout_link_includes_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct aout_link_includes_entry)));
+ if (ret == (struct aout_link_includes_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct aout_link_includes_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->totals = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* 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;
+ boolean includes_hash_initialized = false;
+ register bfd *sub;
+ bfd_size_type trsize, drsize;
+ size_t max_contents_size;
+ size_t max_relocs_size;
+ size_t max_sym_count;
+ bfd_size_type text_size;
+ file_ptr text_end;
+ register struct bfd_link_order *p;
+ asection *o;
+ boolean have_link_order_relocs;
+
+ if (info->shared)
+ abfd->flags |= DYNAMIC;
+
+ aout_info.info = info;
+ aout_info.output_bfd = abfd;
+ aout_info.contents = NULL;
+ aout_info.relocs = NULL;
+ aout_info.symbol_map = NULL;
+ aout_info.output_syms = NULL;
+
+ if (! bfd_hash_table_init_n (&aout_info.includes.root,
+ aout_link_includes_newfunc,
+ 251))
+ goto error_return;
+ includes_hash_initialized = true;
+
+ /* Figure out the largest section size. Also, if generating
+ relocateable output, count the relocs. */
+ trsize = 0;
+ drsize = 0;
+ max_contents_size = 0;
+ max_relocs_size = 0;
+ max_sym_count = 0;
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ size_t sz;
+
+ if (info->relocateable)
+ {
+ 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. */
+ (*_bfd_error_handler)
+ ("%s: relocateable link from %s to %s not supported",
+ bfd_get_filename (abfd),
+ sub->xvec->name, abfd->xvec->name);
+ bfd_set_error (bfd_error_invalid_operation);
+ goto error_return;
+ }
+ }
+
+ if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
+ {
+ sz = bfd_section_size (sub, obj_textsec (sub));
+ if (sz > max_contents_size)
+ max_contents_size = sz;
+ sz = bfd_section_size (sub, obj_datasec (sub));
+ if (sz > max_contents_size)
+ max_contents_size = sz;
+
+ sz = exec_hdr (sub)->a_trsize;
+ if (sz > max_relocs_size)
+ max_relocs_size = sz;
+ sz = exec_hdr (sub)->a_drsize;
+ if (sz > max_relocs_size)
+ max_relocs_size = sz;
+
+ sz = obj_aout_external_sym_count (sub);
+ if (sz > max_sym_count)
+ max_sym_count = sz;
+ }
+ }
+
+ if (info->relocateable)
+ {
+ if (obj_textsec (abfd) != (asection *) NULL)
+ trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
+ ->link_order_head)
+ * obj_reloc_entry_size (abfd));
+ 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_trsize = trsize;
+ 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))
+ goto error_return;
+
+ /* 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. */
+ aout_info.strtab = _bfd_stringtab_init ();
+ if (aout_info.strtab == NULL)
+ goto error_return;
+
+ /* Allocate buffers to hold section contents and relocs. */
+ aout_info.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+ aout_info.relocs = (PTR) bfd_malloc (max_relocs_size);
+ aout_info.symbol_map = (int *) bfd_malloc (max_sym_count * sizeof (int *));
+ aout_info.output_syms = ((struct external_nlist *)
+ bfd_malloc ((max_sym_count + 1)
+ * sizeof (struct external_nlist)));
+ if ((aout_info.contents == NULL && max_contents_size != 0)
+ || (aout_info.relocs == NULL && max_relocs_size != 0)
+ || (aout_info.symbol_map == NULL && max_sym_count != 0)
+ || aout_info.output_syms == NULL)
+ goto error_return;
+
+ /* If we have a symbol named __DYNAMIC, force it out now. This is
+ required by SunOS. Doing this here rather than in sunos.c is a
+ hack, but it's easier than exporting everything which would be
+ needed. */
+ {
+ struct aout_link_hash_entry *h;
+
+ h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC",
+ false, false, false);
+ if (h != NULL)
+ aout_link_write_other_symbol (h, &aout_info);
+ }
+
+ /* 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))
+ goto error_return;
+ 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))
+ goto error_return;
+ }
+ }
+ }
+
+ /* 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))
+ goto error_return;
+ }
+ }
+ }
+ }
+
+ if (aout_info.contents != NULL)
+ {
+ free (aout_info.contents);
+ aout_info.contents = NULL;
+ }
+ if (aout_info.relocs != NULL)
+ {
+ free (aout_info.relocs);
+ aout_info.relocs = NULL;
+ }
+ if (aout_info.symbol_map != NULL)
+ {
+ free (aout_info.symbol_map);
+ aout_info.symbol_map = NULL;
+ }
+ if (aout_info.output_syms != NULL)
+ {
+ free (aout_info.output_syms);
+ aout_info.output_syms = NULL;
+ }
+ if (includes_hash_initialized)
+ {
+ bfd_hash_table_free (&aout_info.includes.root);
+ includes_hash_initialized = 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))
+ goto error_return;
+ }
+
+ /* 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)
+ goto error_return;
+ return emit_stringtab (abfd, aout_info.strtab);
+
+ error_return:
+ if (aout_info.contents != NULL)
+ free (aout_info.contents);
+ if (aout_info.relocs != NULL)
+ free (aout_info.relocs);
+ if (aout_info.symbol_map != NULL)
+ free (aout_info.symbol_map);
+ if (aout_info.output_syms != NULL)
+ free (aout_info.output_syms);
+ if (includes_hash_initialized)
+ bfd_hash_table_free (&aout_info.includes.root);
+ return false;
+}
+
+/* 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;
+
+ 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);
+
+ /* Write out the symbols and get a map of the new indices. The map
+ is placed into finfo->symbol_map. */
+ if (! aout_link_write_symbols (finfo, input_bfd))
+ return false;
+
+ /* Relocate and write out the sections. These functions use the
+ symbol map created by aout_link_write_symbols. */
+ if (! aout_link_input_section (finfo, input_bfd,
+ obj_textsec (input_bfd),
+ &finfo->treloff,
+ exec_hdr (input_bfd)->a_trsize)
+ || ! aout_link_input_section (finfo, input_bfd,
+ obj_datasec (input_bfd),
+ &finfo->dreloff,
+ exec_hdr (input_bfd)->a_drsize))
+ return false;
+
+ /* 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))
+ return false;
+ }
+
+ return true;
+}
+
+/* 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)
+ struct aout_final_link_info *finfo;
+ bfd *input_bfd;
+{
+ bfd *output_bfd;
+ bfd_size_type sym_count;
+ char *strings;
+ enum bfd_link_strip strip;
+ enum bfd_link_discard discard;
+ 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;
+ int *symbol_map;
+ boolean pass;
+ boolean skip_next;
+
+ 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;
+ outsym = finfo->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)
+ return false;
+ 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_next = false;
+ sym = obj_aout_external_syms (input_bfd);
+ sym_end = sym + sym_count;
+ sym_hash = obj_aout_sym_hashes (input_bfd);
+ symbol_map = finfo->symbol_map;
+ memset (symbol_map, 0, sym_count * sizeof *symbol_map);
+ 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;
+
+ /* We set *symbol_map to 0 above for all symbols. If it has
+ already been set to -1 for this symbol, it means that we are
+ discarding it because it appears in a duplicate header file.
+ See the N_BINCL code below. */
+ if (*symbol_map == -1)
+ continue;
+
+ /* Initialize *symbol_map to -1, which means that the symbol was
+ not copied into the output file. We will change it later if
+ we do copy the symbol over. */
+ *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_next)
+ {
+ /* Skip this symbol, which is the target of an indirect
+ symbol that we have changed to no longer be an indirect
+ symbol. */
+ skip_next = 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;
+
+ /* Use the name from the hash table, in case the symbol was
+ wrapped. */
+ if (h != NULL)
+ name = h->root.root.string;
+
+ /* 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
+ || type == N_WARNING)
+ skip_next = 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_defweak
+ && 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_next = true;
+
+ symsec = NULL;
+
+ /* 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)
+ {
+ switch (type & N_TYPE)
+ {
+ case N_SETT:
+ symsec = obj_textsec (input_bfd);
+ break;
+ case N_SETD:
+ symsec = obj_datasec (input_bfd);
+ break;
+ case N_SETB:
+ symsec = obj_bsssec (input_bfd);
+ break;
+ case N_SETA:
+ symsec = bfd_abs_section_ptr;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ }
+ else if (hresolve->root.type == bfd_link_hash_defined
+ || hresolve->root.type == bfd_link_hash_defweak)
+ {
+ asection *input_section;
+ asection *output_section;
+
+ /* This case usually 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 |= (hresolve->root.type == bfd_link_hash_defined
+ ? N_TEXT
+ : N_WEAKT);
+ else if (output_section == obj_datasec (output_bfd))
+ type |= (hresolve->root.type == bfd_link_hash_defined
+ ? N_DATA
+ : N_WEAKD);
+ else if (output_section == obj_bsssec (output_bfd))
+ type |= (hresolve->root.type == bfd_link_hash_defined
+ ? N_BSS
+ : N_WEAKB);
+ else
+ type |= (hresolve->root.type == bfd_link_hash_defined
+ ? N_ABS
+ : N_WEAKA);
+ }
+ else if (hresolve->root.type == bfd_link_hash_common)
+ val = hresolve->root.u.c.size;
+ else if (hresolve->root.type == bfd_link_hash_undefweak)
+ {
+ val = 0;
+ type = N_WEAKU;
+ }
+ else
+ val = 0;
+ }
+ 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 if ((type & N_TYPE) != N_SETT
+ && (type & N_TYPE) != N_SETD
+ && (type & N_TYPE) != N_SETB
+ && (type & N_TYPE) != N_SETA)
+ {
+ 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;
+ }
+ }
+
+ /* An N_BINCL symbol indicates the start of the stabs
+ entries for a header file. We need to scan ahead to the
+ next N_EINCL symbol, ignoring nesting, adding up all the
+ characters in the symbol names, not including the file
+ numbers in types (the first number after an open
+ parenthesis). */
+ if (type == N_BINCL)
+ {
+ struct external_nlist *incl_sym;
+ int nest;
+ struct aout_link_includes_entry *incl_entry;
+ struct aout_link_includes_totals *t;
+
+ val = 0;
+ nest = 0;
+ for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
+ {
+ int incl_type;
+
+ incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
+ if (incl_type == N_EINCL)
+ {
+ if (nest == 0)
+ break;
+ --nest;
+ }
+ else if (incl_type == N_BINCL)
+ ++nest;
+ else if (nest == 0)
+ {
+ const char *s;
+
+ s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
+ for (; *s != '\0'; s++)
+ {
+ val += *s;
+ if (*s == '(')
+ {
+ /* Skip the file number. */
+ ++s;
+ while (isdigit ((unsigned char) *s))
+ ++s;
+ --s;
+ }
+ }
+ }
+ }
+
+ /* If we have already included a header file with the
+ same value, then replace this one with an N_EXCL
+ symbol. */
+ copy = ! finfo->info->keep_memory;
+ incl_entry = aout_link_includes_lookup (&finfo->includes,
+ name, true, copy);
+ if (incl_entry == NULL)
+ return false;
+ for (t = incl_entry->totals; t != NULL; t = t->next)
+ if (t->total == val)
+ break;
+ if (t == NULL)
+ {
+ /* This is the first time we have seen this header
+ file with this set of stabs strings. */
+ t = ((struct aout_link_includes_totals *)
+ bfd_hash_allocate (&finfo->includes.root,
+ sizeof *t));
+ if (t == NULL)
+ return false;
+ t->total = val;
+ t->next = incl_entry->totals;
+ incl_entry->totals = t;
+ }
+ else
+ {
+ int *incl_map;
+
+ /* This is a duplicate header file. We must change
+ it to be an N_EXCL entry, and mark all the
+ included symbols to prevent outputting them. */
+ type = N_EXCL;
+
+ nest = 0;
+ for (incl_sym = sym + 1, incl_map = symbol_map + 1;
+ incl_sym < sym_end;
+ incl_sym++, incl_map++)
+ {
+ int incl_type;
+
+ incl_type = bfd_h_get_8 (input_bfd, incl_sym->e_type);
+ if (incl_type == N_EINCL)
+ {
+ if (nest == 0)
+ {
+ *incl_map = -1;
+ break;
+ }
+ --nest;
+ }
+ else if (incl_type == N_BINCL)
+ ++nest;
+ else if (nest == 0)
+ *incl_map = -1;
+ }
+ }
+ }
+ }
+
+ /* 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 = h->root.root.string;
+ else
+ copy = true;
+ }
+ strtab_index = add_to_stringtab (output_bfd, finfo->strtab,
+ name, copy);
+ if (strtab_index == (bfd_size_type) -1)
+ return false;
+ 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 > finfo->output_syms)
+ {
+ bfd_size_type outsym_count;
+
+ if (bfd_seek (output_bfd, finfo->symoff, SEEK_SET) != 0)
+ return false;
+ outsym_count = outsym - finfo->output_syms;
+ if (bfd_write ((PTR) finfo->output_syms,
+ (bfd_size_type) EXTERNAL_NLIST_SIZE,
+ (bfd_size_type) outsym_count, output_bfd)
+ != outsym_count * EXTERNAL_NLIST_SIZE)
+ return false;
+ finfo->symoff += outsym_count * EXTERNAL_NLIST_SIZE;
+ }
+
+ return true;
+}
+
+/* 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;
+
+ /* An indx of -2 means the symbol must be written. */
+ if (h->indx != -2
+ && (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:
+ abort ();
+ /* Avoid variable not initialized warnings. */
+ return true;
+ case bfd_link_hash_new:
+ /* This can happen for set symbols when sets are not being
+ built. */
+ return true;
+ case bfd_link_hash_undefined:
+ type = N_UNDF | N_EXT;
+ val = 0;
+ break;
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ {
+ 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 = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
+ else if (sec == obj_datasec (output_bfd))
+ type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
+ else if (sec == obj_bsssec (output_bfd))
+ type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
+ else
+ type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
+ type |= 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_undefweak:
+ 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)
+ struct aout_final_link_info *finfo;
+ bfd *input_bfd;
+ asection *input_section;
+ file_ptr *reloff_ptr;
+ bfd_size_type rel_size;
+{
+ bfd_size_type input_size;
+ PTR relocs;
+
+ /* Get the section contents. */
+ input_size = bfd_section_size (input_bfd, input_section);
+ if (! bfd_get_section_contents (input_bfd, input_section,
+ (PTR) finfo->contents,
+ (file_ptr) 0, input_size))
+ return false;
+
+ /* 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 = finfo->relocs;
+ if (rel_size > 0)
+ {
+ if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
+ || bfd_read (relocs, 1, rel_size, input_bfd) != rel_size)
+ return false;
+ }
+ }
+
+ /* 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, finfo->contents))
+ return false;
+ }
+ else
+ {
+ if (! aout_link_input_section_ext (finfo, input_bfd, input_section,
+ (struct reloc_ext_external *) relocs,
+ rel_size, finfo->contents))
+ return false;
+ }
+
+ /* Write out the section contents. */
+ if (! bfd_set_section_contents (finfo->output_bfd,
+ input_section->output_section,
+ (PTR) finfo->contents,
+ input_section->output_offset,
+ input_size))
+ return false;
+
+ /* If we are producing relocateable output, the relocs were
+ modified, and we now write them out. */
+ if (finfo->info->relocateable && rel_size > 0)
+ {
+ if (bfd_seek (finfo->output_bfd, *reloff_ptr, SEEK_SET) != 0)
+ return false;
+ if (bfd_write (relocs, (bfd_size_type) 1, rel_size, finfo->output_bfd)
+ != rel_size)
+ return false;
+ *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)));
+ }
+
+ return true;
+}
+
+/* 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)
+ 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;
+{
+ boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
+ bfd *, asection *,
+ struct aout_link_hash_entry *,
+ PTR, bfd_byte *, boolean *,
+ bfd_vma *));
+ bfd *output_bfd;
+ boolean relocateable;
+ struct external_nlist *syms;
+ char *strings;
+ struct aout_link_hash_entry **sym_hashes;
+ int *symbol_map;
+ 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
+ == output_bfd->xvec->header_byteorder);
+
+ 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);
+ symbol_map = finfo->symbol_map;
+
+ 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 = 0;
+ reloc_howto_type *howto;
+ struct aout_link_hash_entry *h = NULL;
+ 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
+ {
+ int r_jmptable;
+ int r_relative;
+ int r_length;
+ unsigned int howto_idx;
+
+ if (bfd_header_big_endian (input_bfd))
+ {
+ 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)
+ {
+ /* 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
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ asection *output_section;
+
+ /* Change the r_extern value. */
+ if (bfd_header_big_endian (output_bfd))
+ 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)
+ {
+ if (h != NULL)
+ {
+ /* We decided to strip this symbol, but it
+ turns out that we can't. Note that we
+ lose the other and desc information here.
+ I don't think that will ever matter for a
+ global symbol. */
+ if (h->indx < 0)
+ {
+ h->indx = -2;
+ h->written = false;
+ if (! aout_link_write_other_symbol (h,
+ (PTR) finfo))
+ return false;
+ }
+ r_index = h->indx;
+ }
+ else
+ {
+ 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 (bfd_header_big_endian (output_bfd))
+ {
+ 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);
+
+#ifdef MY_relocatable_reloc
+ MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr);
+#endif
+
+ if (relocation == 0)
+ r = bfd_reloc_ok;
+ else
+ r = MY_relocate_contents (howto,
+ input_bfd, relocation,
+ contents + r_addr);
+ }
+ else
+ {
+ boolean hundef;
+
+ /* We are generating an executable, and must do a full
+ relocation. */
+ hundef = false;
+ if (r_extern)
+ {
+ h = sym_hashes[r_index];
+
+ if (h != (struct aout_link_hash_entry *) NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ 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_undefweak)
+ relocation = 0;
+ else
+ {
+ hundef = true;
+ 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;
+ }
+
+ if (check_dynamic_reloc != NULL)
+ {
+ boolean skip;
+
+ if (! ((*check_dynamic_reloc)
+ (finfo->info, input_bfd, input_section, h,
+ (PTR) rel, contents, &skip, &relocation)))
+ return false;
+ if (skip)
+ continue;
+ }
+
+ /* Now warn if a global symbol is undefined. We could not
+ do this earlier, because check_dynamic_reloc might want
+ to skip this reloc. */
+ if (hundef && ! finfo->info->shared && ! r_baserel)
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ 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;
+ }
+
+ r = MY_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)
+ 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;
+{
+ boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *,
+ bfd *, asection *,
+ struct aout_link_hash_entry *,
+ PTR, bfd_byte *, boolean *,
+ bfd_vma *));
+ bfd *output_bfd;
+ boolean relocateable;
+ struct external_nlist *syms;
+ char *strings;
+ struct aout_link_hash_entry **sym_hashes;
+ int *symbol_map;
+ 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
+ == output_bfd->xvec->header_byteorder);
+
+ 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);
+ symbol_map = finfo->symbol_map;
+
+ 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;
+ unsigned int r_type;
+ bfd_vma r_addend;
+ struct aout_link_hash_entry *h = NULL;
+ asection *r_section = NULL;
+ bfd_vma relocation;
+
+ r_addr = GET_SWORD (input_bfd, rel->r_address);
+
+ if (bfd_header_big_endian (input_bfd))
+ {
+ 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 < TABLE_SIZE (howto_table_ext));
+
+ if (relocateable)
+ {
+ /* We are generating a relocateable output file, and must
+ modify the reloc accordingly. */
+ if (r_extern)
+ {
+ /* 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
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ asection *output_section;
+
+ /* Change the r_extern value. */
+ if (bfd_header_big_endian (output_bfd))
+ 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)
+ {
+ if (h != NULL)
+ {
+ /* We decided to strip this symbol, but it
+ turns out that we can't. Note that we
+ lose the other and desc information here.
+ I don't think that will ever matter for a
+ global symbol. */
+ if (h->indx < 0)
+ {
+ h->indx = -2;
+ h->written = false;
+ if (! aout_link_write_other_symbol (h,
+ (PTR) finfo))
+ return false;
+ }
+ r_index = h->indx;
+ }
+ else
+ {
+ 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 (bfd_header_big_endian (output_bfd))
+ {
+ 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
+ {
+ /* This is a relocation against a section. We must
+ adjust by the amount that the section moved. */
+ r_section = aout_reloc_index_to_section (input_bfd, r_index);
+ relocation = (r_section->output_section->vma
+ + r_section->output_offset
+ - r_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
+ {
+ boolean hundef;
+ bfd_reloc_status_type r;
+
+ /* We are generating an executable, and must do a full
+ relocation. */
+ hundef = false;
+ if (r_extern)
+ {
+ h = sym_hashes[r_index];
+
+ if (h != (struct aout_link_hash_entry *) NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ 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_undefweak)
+ relocation = 0;
+ else
+ {
+ hundef = true;
+ relocation = 0;
+ }
+ }
+ else if (r_type == RELOC_BASE10
+ || r_type == RELOC_BASE13
+ || r_type == RELOC_BASE22)
+ {
+ struct external_nlist *sym;
+ int type;
+
+ /* For base relative relocs, r_index is always an index
+ into the symbol table, even if r_extern is 0. */
+ sym = syms + r_index;
+ type = bfd_h_get_8 (input_bfd, sym->e_type);
+ if ((type & N_TYPE) == N_TEXT
+ || type == N_WEAKT)
+ r_section = obj_textsec (input_bfd);
+ else if ((type & N_TYPE) == N_DATA
+ || type == N_WEAKD)
+ r_section = obj_datasec (input_bfd);
+ else if ((type & N_TYPE) == N_BSS
+ || type == N_WEAKB)
+ r_section = obj_bsssec (input_bfd);
+ else if ((type & N_TYPE) == N_ABS
+ || type == N_WEAKA)
+ r_section = bfd_abs_section_ptr;
+ else
+ abort ();
+ relocation = (r_section->output_section->vma
+ + r_section->output_offset
+ + (GET_WORD (input_bfd, sym->e_value)
+ - r_section->vma));
+ }
+ else
+ {
+ r_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 = (r_section->output_section->vma
+ + r_section->output_offset
+ - r_section->vma);
+ if (howto_table_ext[r_type].pc_relative)
+ relocation += input_section->vma;
+ }
+
+ if (check_dynamic_reloc != NULL)
+ {
+ boolean skip;
+
+ if (! ((*check_dynamic_reloc)
+ (finfo->info, input_bfd, input_section, h,
+ (PTR) rel, contents, &skip, &relocation)))
+ return false;
+ if (skip)
+ continue;
+ }
+
+ /* Now warn if a global symbol is undefined. We could not
+ do this earlier, because check_dynamic_reloc might want
+ to skip this reloc. */
+ if (hundef
+ && ! finfo->info->shared
+ && r_type != RELOC_BASE10
+ && r_type != RELOC_BASE13
+ && r_type != RELOC_BASE22)
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ 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;
+ }
+
+ r = MY_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
+ || r_type == RELOC_BASE10
+ || r_type == RELOC_BASE13
+ || r_type == RELOC_BASE22)
+ 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;
+ 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 = ((struct aout_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (finfo->output_bfd, finfo->info,
+ pr->u.name, false, false, true));
+ if (h != (struct aout_link_hash_entry *) NULL
+ && h->indx >= 0)
+ r_index = h->indx;
+ else if (h != NULL)
+ {
+ /* We decided to strip this symbol, but it turns out that we
+ can't. Note that we lose the other and desc information
+ here. I don't think that will ever matter for a global
+ symbol. */
+ h->indx = -2;
+ h->written = false;
+ if (! aout_link_write_other_symbol (h, (PTR) finfo))
+ return false;
+ 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 == 0)
+ {
+ 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)
+ {
+#ifdef MY_put_reloc
+ MY_put_reloc(finfo->output_bfd, r_extern, r_index, p->offset, howto,
+ &srel);
+#else
+ {
+ int r_pcrel;
+ int r_baserel;
+ int r_jmptable;
+ int r_relative;
+ int r_length;
+
+ 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 (bfd_header_big_endian (finfo->output_bfd))
+ {
+ 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)
+ return false;
+ r = MY_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 (bfd_header_big_endian (finfo->output_bfd))
+ {
+ 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/contrib/gdb/bfd/archive.c b/contrib/gdb/bfd/archive.c
new file mode 100644
index 0000000..248b918
--- /dev/null
+++ b/contrib/gdb/bfd/archive.c
@@ -0,0 +1,2094 @@
+/* BFD back-end for archive files (libraries).
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+@setfilename archive-info
+SECTION
+ Archives
+
+DESCRIPTION
+ 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 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; they will be handled correctly when the archive is closed.
+
+ Use <<bfd_openr_next_archived_file>> 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
+ <<next>> pointer in a BFD. The first one is findable through
+ the <<archive_head>> slot of the archive. Set it with
+ <<bfd_set_archive_head>> (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
+ archive code of any given environment. BFD archives may
+ contain files of different formats (e.g., a.out and coff) and
+ even different architectures. You may even place archives
+ recursively into archives!
+
+ This can cause unexpected confusion, since some archive
+ formats are more expressive than others. For instance, Intel
+ 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
+ conventions as to how they truncate filenames, whether they
+ preserve directory names in filenames, etc. When
+ interoperating with native tools, be sure your files are
+ homogeneous.
+
+ 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 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 <<archive.c>>.
+
+*/
+
+/* Assumes:
+ o - all archive elements start on an even boundary, newline padded;
+ o - all arch headers are char *;
+ o - all arch headers are the same size (across architectures).
+*/
+
+/* 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
+ 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
+ utilities can't handle that anyway.
+
+ This scheme unfortunately requires that you stand on your head in
+ order to write an archive since you need to put a magic file at the
+ front, and need to touch every entry to do so. C'est la vie.
+
+ We support two variants of this idea:
+ The SVR4 format (extended name table is named "//"),
+ and an extended pseudo-BSD variant (extended name table is named
+ "ARFILENAMES/"). The origin of the latter format is uncertain.
+
+ BSD 4.4 uses a third scheme: It writes a long filename
+ directly after the header. This allows 'ar q' to work.
+ We currently can read BSD 4.4 archives, but not write them.
+*/
+
+/* Summary of archive member names:
+
+ Symbol table (must be first):
+ "__.SYMDEF " - Symbol table, Berkeley style, produced by ranlib.
+ "/ " - Symbol table, system 5 style.
+
+ Long name table (must be before regular file members):
+ "// " - Long name table, System 5 R4 style.
+ "ARFILENAMES/ " - Long name table, non-standard extended BSD (not BSD 4.4).
+
+ Regular file members with short names:
+ "filename.o/ " - Regular file, System 5 style (embedded spaces ok).
+ "filename.o " - Regular file, Berkeley style (no embedded spaces).
+
+ Regular files with long names (or embedded spaces, for BSD variants):
+ "/18 " - SVR4 style, name at offset 18 in name table.
+ "#1/23 " - Long name (or embedded paces) 23 characters long,
+ BSD 4.4 style, full name follows header.
+ Implemented for reading, not writing.
+ " 18 " - Long name 18 characters long, extended pseudo-BSD.
+ */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/ar.h"
+#include "aout/ranlib.h"
+#include <errno.h>
+#include <string.h> /* For memchr, strrchr and friends */
+#include <ctype.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef GNU960
+#define BFD_GNU960_ARMAG(abfd) (BFD_COFF_FILE_P((abfd)) ? ARMAG : ARMAGB)
+#endif
+
+/* 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 */
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* We keep a cache of archive filepointers to archive elements to
+ speed up searching the archive by filepos. We only add an entry to
+ the cache when we actually read one. We also don't sort the cache;
+ it's generally short enough to search linearly.
+ Note that the pointers here point to the front of the ar_hdr, not
+ to the front of the contents!
+*/
+struct ar_cache
+{
+ file_ptr ptr;
+ bfd *arelt;
+ struct ar_cache *next;
+};
+
+#define ar_padchar(abfd) ((abfd)->xvec->ar_pad_char)
+#define ar_maxnamelen(abfd) ((abfd)->xvec->ar_max_namelen)
+
+#define arch_eltdata(bfd) ((struct areltdata *)((bfd)->arelt_data))
+#define arch_hdr(bfd) ((struct ar_hdr *)arch_eltdata(bfd)->arch_header)
+
+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 ((bfd *, const char *file));
+static struct areltdata *bfd_ar_hdr_from_filesystem PARAMS ((bfd *abfd,
+ const char *));
+
+boolean
+_bfd_generic_mkarchive (abfd)
+ bfd *abfd;
+{
+ abfd->tdata.aout_ar_data = ((struct artdata *)
+ bfd_zalloc (abfd, sizeof (struct artdata)));
+
+ if (bfd_ardata (abfd) == NULL)
+ return false;
+
+ 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;
+}
+
+/*
+FUNCTION
+ bfd_get_next_mapent
+
+SYNOPSIS
+ symindex bfd_get_next_mapent(bfd *abfd, symindex previous, carsym **sym);
+
+DESCRIPTION
+ 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 @var{previous} entry to get
+ the first one; returns <<BFD_NO_MORE_SYMBOLS>> when you've already
+ got the last one.
+
+ A <<carsym>> is a canonical archive symbol. The only
+ user-visible element is its name, a null-terminated string.
+*/
+
+symindex
+bfd_get_next_mapent (abfd, prev, entry)
+ bfd *abfd;
+ symindex prev;
+ carsym **entry;
+{
+ 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
+ ++prev;
+ if (prev >= bfd_ardata (abfd)->symdef_count)
+ return BFD_NO_MORE_SYMBOLS;
+
+ *entry = (bfd_ardata (abfd)->symdefs + prev);
+ return prev;
+}
+
+/* To be called by backends only */
+
+bfd *
+_bfd_create_empty_archive_element_shell (obfd)
+ bfd *obfd;
+{
+ return _bfd_new_bfd_contained_in (obfd);
+}
+
+/*
+FUNCTION
+ bfd_set_archive_head
+
+SYNOPSIS
+ boolean bfd_set_archive_head(bfd *output, bfd *new_head);
+
+DESCRIPTION
+ Set the head of the chain of
+ BFDs contained in the archive @var{output} to @var{new_head}.
+*/
+
+boolean
+bfd_set_archive_head (output_archive, new_head)
+ bfd *output_archive;
+ bfd *new_head;
+{
+
+ output_archive->archive_head = new_head;
+ return true;
+}
+
+bfd *
+_bfd_look_for_bfd_in_cache (arch_bfd, filepos)
+ bfd *arch_bfd;
+ file_ptr filepos;
+{
+ struct ar_cache *current;
+
+ for (current = bfd_ardata (arch_bfd)->cache; current != NULL;
+ current = current->next)
+ 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
+_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)));
+
+ if (new_cache == NULL)
+ return false;
+
+ new_cache->ptr = filepos;
+ new_cache->arelt = new_elt;
+ 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;
+
+ while (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. */
+
+static char *
+get_extended_arelt_filename (arch, name)
+ bfd *arch;
+ const char *name;
+{
+ unsigned long index = 0;
+
+ /* Should extract string so that I can guarantee not to overflow into
+ 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_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.
+
+ Presumes the file pointer is already in the right place (ie pointing
+ to the ar_hdr in the file). Moves the file pointer; on success it
+ should be pointing to the front of the file contents; on failure it
+ could have been moved arbitrarily.
+*/
+
+PTR
+_bfd_generic_read_ar_hdr (abfd)
+ bfd *abfd;
+{
+ return _bfd_generic_read_ar_hdr_mag (abfd, (const char *) NULL);
+}
+
+/* Alpha ECOFF uses an optional different ARFMAG value, so we have a
+ variant of _bfd_generic_read_ar_hdr which accepts a magic string. */
+
+PTR
+_bfd_generic_read_ar_hdr_mag (abfd, mag)
+ bfd *abfd;
+ const char *mag;
+{
+ 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))
+ {
+ 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) != 0
+ && (mag == NULL
+ || strncmp (hdr.ar_fmag, mag, 2) != 0))
+ {
+ bfd_set_error (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_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;
+
+ allocptr = bfd_zalloc (abfd, allocsize);
+ if (allocptr == NULL)
+ 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++;
+ break;
+ }
+ }
+
+ allocsize += namelen + 1;
+ }
+
+ if (!allocptr)
+ {
+ allocptr = bfd_zalloc (abfd, allocsize);
+ if (allocptr == NULL)
+ return NULL;
+ }
+
+ 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 (PTR) 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. */
+
+bfd *
+_bfd_get_elt_at_filepos (archive, filepos)
+ bfd *archive;
+ file_ptr filepos;
+{
+ struct areltdata *new_areldata;
+ bfd *n_nfd;
+
+ n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
+ if (n_nfd)
+ return n_nfd;
+
+ if (0 > bfd_seek (archive, filepos, SEEK_SET))
+ return NULL;
+
+ if ((new_areldata = (struct areltdata *) _bfd_read_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);
+ return NULL;
+ }
+
+ n_nfd->origin = bfd_tell (archive);
+ n_nfd->arelt_data = (PTR) new_areldata;
+ n_nfd->filename = new_areldata->filename;
+
+ 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);
+ return NULL;
+}
+
+/* Return the BFD which is referenced by the symbol in ABFD indexed by
+ INDEX. INDEX should have been returned by bfd_get_next_mapent. */
+
+bfd *
+_bfd_generic_get_elt_at_index (abfd, index)
+ bfd *abfd;
+ symindex index;
+{
+ carsym *entry;
+
+ entry = bfd_ardata (abfd)->symdefs + index;
+ return _bfd_get_elt_at_filepos (abfd, entry->file_offset);
+}
+
+/*
+FUNCTION
+ bfd_openr_next_archived_file
+
+SYNOPSIS
+ bfd *bfd_openr_next_archived_file(bfd *archive, bfd *previous);
+
+DESCRIPTION
+ 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.
+
+*/
+
+bfd *
+bfd_openr_next_archived_file (archive, last_file)
+ bfd *archive;
+ bfd *last_file;
+{
+ if ((bfd_get_format (archive) != bfd_archive) ||
+ (archive->direction == write_direction))
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
+ return BFD_SEND (archive,
+ openr_next_archived_file,
+ (archive,
+ last_file));
+}
+
+bfd *
+bfd_generic_openr_next_archived_file (archive, last_file)
+ bfd *archive;
+ bfd *last_file;
+{
+ file_ptr filestart;
+
+ 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;
+ }
+
+ return _bfd_get_elt_at_filepos (archive, filestart);
+}
+
+
+const bfd_target *
+bfd_generic_archive_p (abfd)
+ bfd *abfd;
+{
+ struct artdata *tdata_hold;
+ char armag[SARMAG + 1];
+
+ tdata_hold = abfd->tdata.aout_ar_data;
+
+ 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) != 0)
+ return 0;
+#else
+ 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)));
+
+ if (bfd_ardata (abfd) == NULL)
+ return 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 (!BFD_SEND (abfd, _bfd_slurp_armap, (abfd)))
+ {
+ bfd_release (abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = tdata_hold;
+ return NULL;
+ }
+
+ if (!BFD_SEND (abfd, _bfd_slurp_extended_name_table, (abfd)))
+ {
+ bfd_release (abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = tdata_hold;
+ return NULL;
+ }
+
+ if (bfd_has_map (abfd))
+ {
+ bfd *first;
+
+ /* This archive has a map, so we may presume that the contents
+ are object files. Make sure that if the first file in the
+ archive can be recognized as an object file, it is for this
+ target. If not, assume that this is the wrong format. If
+ the first file is not an object file, somebody is doing
+ something weird, and we permit it so that ar -t will work.
+
+ This is done because any normal format will recognize any
+ normal archive, regardless of the format of the object files.
+ We do accept an empty archive. */
+
+ first = bfd_openr_next_archived_file (abfd, (bfd *) NULL);
+ if (first != NULL)
+ {
+ boolean fail;
+
+ first->target_defaulted = false;
+ fail = false;
+ if (bfd_check_format (first, bfd_object)
+ && first->xvec != abfd->xvec)
+ {
+ (void) bfd_close (first);
+ bfd_release (abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = tdata_hold;
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* We ought to close first here, but we can't, because we
+ have no way to remove it from the archive cache. FIXME. */
+ }
+ }
+
+ 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
+do_slurp_bsd_armap (abfd)
+ bfd *abfd;
+{
+ struct areltdata *mapdata;
+ unsigned int counter;
+ bfd_byte *raw_armap, *rbase;
+ struct artdata *ardata = bfd_ardata (abfd);
+ char *stringbase;
+ unsigned int parsed_size;
+ carsym *set;
+
+ mapdata = (struct areltdata *) _bfd_read_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 = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
+ if (raw_armap == (bfd_byte *) NULL)
+ return false;
+
+ 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);
+ return false;
+ }
+
+ 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_set_error (bfd_error_wrong_format);
+ goto byebye;
+ }
+
+ ardata->cache = 0;
+ 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)
+ 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;
+ /* 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... */
+ bfd_has_map (abfd) = true;
+ return true;
+}
+
+/* Returns false on error, true otherwise */
+static boolean
+do_slurp_coff_armap (abfd)
+ bfd *abfd;
+{
+ struct areltdata *mapdata;
+ int *raw_armap, *rawptr;
+ struct artdata *ardata = bfd_ardata (abfd);
+ char *stringbase;
+ unsigned int stringsize;
+ unsigned int parsed_size;
+ carsym *carsyms;
+ 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 = (struct areltdata *) _bfd_read_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);
+ stringsize = parsed_size - (4 * nsymz) - 4;
+
+#if 1
+ /* ... except that some archive formats are broken, and it may be our
+ 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)
+ {
+ /* This looks dangerous, let's do it the other way around */
+ 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. */
+
+ carsym_size = (nsymz * sizeof (carsym));
+ ptrsize = (4 * nsymz);
+
+ ardata->symdefs = (carsym *) bfd_zalloc (abfd, carsym_size + stringsize + 1);
+ if (ardata->symdefs == NULL)
+ 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)
+ goto release_symdefs;
+ 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++)
+ {
+ rawptr = raw_armap + i;
+ carsyms->file_offset = swap ((PTR) rawptr);
+ carsyms->name = 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;
+
+
+ bfd_has_map (abfd) = true;
+ bfd_release (abfd, (PTR) raw_armap);
+
+
+ /* Check for a second archive header (as used by PE) */
+ {
+ struct areltdata *tmp;
+
+ bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET);
+ tmp = (struct areltdata *) _bfd_read_ar_hdr (abfd);
+ if (tmp != NULL)
+ {
+ if (tmp->arch_header[0] == '/'
+ && tmp->arch_header[1] == ' ')
+ {
+ ardata->first_file_filepos +=
+ (tmp->parsed_size + sizeof(struct ar_hdr) + 1) & ~1;
+ }
+ bfd_release (abfd, tmp);
+ }
+ }
+
+ return true;
+
+release_raw_armap:
+ bfd_release (abfd, (PTR) raw_armap);
+release_symdefs:
+ bfd_release (abfd, (PTR) (ardata)->symdefs);
+ return false;
+}
+
+/* This routine can handle either coff-style or bsd-style armaps.
+ Returns false on error, true otherwise */
+
+boolean
+bfd_slurp_armap (abfd)
+ bfd *abfd;
+{
+ char nextname[17];
+ int i = bfd_read ((PTR) nextname, 1, 16, abfd);
+
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
+ return false;
+
+ 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);
+
+ bfd_has_map (abfd) = false;
+ return true;
+}
+
+/* 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 '/'.
+ This flavour is used by hp300hpux. */
+
+#define HPUX_SYMDEF_COUNT_SIZE 2
+
+boolean
+bfd_slurp_bsd_armap_f2 (abfd)
+ bfd *abfd;
+{
+ struct areltdata *mapdata;
+ char nextname[17];
+ unsigned int counter;
+ bfd_byte *raw_armap, *rbase;
+ struct artdata *ardata = bfd_ardata (abfd);
+ char *stringbase;
+ unsigned int stringsize;
+ carsym *set;
+ int i = bfd_read ((PTR) nextname, 1, 16, abfd);
+
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ /* The archive has at least 16 bytes in it */
+ if (bfd_seek (abfd, -16L, SEEK_CUR) != 0)
+ return false;
+
+ if (!strncmp (nextname, "__.SYMDEF ", 16)
+ || !strncmp (nextname, "__.SYMDEF/ ", 16)) /* old Linux archives */
+ return do_slurp_bsd_armap (abfd);
+
+ if (strncmp (nextname, "/ ", 16))
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
+ if (mapdata == NULL)
+ return false;
+
+ raw_armap = (bfd_byte *) bfd_zalloc (abfd, mapdata->parsed_size);
+ if (raw_armap == NULL)
+ {
+ byebye:
+ bfd_release (abfd, (PTR) mapdata);
+ return false;
+ }
+
+ if (bfd_read ((PTR) raw_armap, 1, mapdata->parsed_size, abfd) !=
+ mapdata->parsed_size)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_malformed_archive);
+ byebyebye:
+ bfd_release (abfd, (PTR) raw_armap);
+ goto byebye;
+ }
+
+ ardata->symdef_count = bfd_h_get_16 (abfd, (PTR) 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_set_error (bfd_error_wrong_format);
+ goto byebyebye;
+ }
+
+ ardata->cache = 0;
+
+ stringsize = bfd_h_get_32 (abfd, raw_armap + HPUX_SYMDEF_COUNT_SIZE);
+ /* skip sym count and string sz */
+ 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)
+ 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;
+ /* 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... */
+ bfd_has_map (abfd) = true;
+ return true;
+}
+
+/** Extended name table.
+
+ Normally archives support only 14-character filenames.
+
+ Intel has extended the format: longer names are stored in a special
+ element (the first in the archive, or second if there is an armap);
+ the name in the ar_hdr is replaced by <space><index into filename
+ element>. Index is the P.R. of an int (decimal). Data General have
+ extended the format by using the prefix // for the special element */
+
+/* Returns false on error, true otherwise */
+boolean
+_bfd_slurp_extended_name_table (abfd)
+ bfd *abfd;
+{
+ char nextname[17];
+ struct areltdata *namedata;
+
+ /* FIXME: Formatting sucks here, and in case of failure of BFD_READ,
+ we probably don't want to return true. */
+ bfd_seek (abfd, bfd_ardata (abfd)->first_file_filepos, SEEK_SET);
+ if (bfd_read ((PTR) nextname, 1, 16, abfd) == 16)
+ {
+ if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) != 0)
+ return false;
+
+ if (strncmp (nextname, "ARFILENAMES/ ", 16) != 0 &&
+ strncmp (nextname, "// ", 16) != 0)
+ {
+ bfd_ardata (abfd)->extended_names = NULL;
+ return true;
+ }
+
+ namedata = (struct areltdata *) _bfd_read_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)
+ {
+ byebye:
+ bfd_release (abfd, (PTR) namedata);
+ return false;
+ }
+
+ 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 '/'. DOS/NT created archive often have \ in them
+ We'll fix all problems here.. */
+ {
+ char *temp = bfd_ardata (abfd)->extended_names;
+ char *limit = temp + namedata->parsed_size;
+ for (; temp < limit; ++temp) {
+ if (*temp == '\012')
+ temp[temp[-1] == '/' ? -1 : 0] = '\0';
+ if (*temp == '\\')
+ *temp = '/';
+ }
+ }
+
+ /* 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;
+}
+
+#ifdef VMS
+
+/* Return a copy of the stuff in the filename between any :]> and a
+ semicolon */
+static const char *
+normalize (abfd, file)
+ bfd *abfd;
+ const char *file;
+{
+ CONST char *first;
+ CONST char *last;
+ char *copy;
+
+ first = file + strlen (file) - 1;
+ last = first + 1;
+
+ while (first != file)
+ {
+ if (*first == ';')
+ last = first;
+ if (*first == ':' || *first == ']' || *first == '>')
+ {
+ first++;
+ break;
+ }
+ first--;
+ }
+
+ copy = (char *) bfd_alloc (abfd, last - first + 1);
+ if (copy == NULL)
+ return NULL;
+
+ memcpy (copy, first, last - first);
+ copy[last - first] = 0;
+
+ return copy;
+}
+
+#else
+static const char *
+normalize (abfd, file)
+ bfd *abfd;
+ const char *file;
+{
+ const char *filename = strrchr (file, '/');
+
+ if (filename != (char *) NULL)
+ filename++;
+ else
+ filename = file;
+ return filename;
+}
+#endif
+
+/* Build a BFD style extended name table. */
+
+boolean
+_bfd_archive_bsd_construct_extended_name_table (abfd, tabloc, tablen, name)
+ bfd *abfd;
+ char **tabloc;
+ bfd_size_type *tablen;
+ const char **name;
+{
+ *name = "ARFILENAMES/";
+ return _bfd_construct_extended_name_table (abfd, false, tabloc, tablen);
+}
+
+/* Build an SVR4 style extended name table. */
+
+boolean
+_bfd_archive_coff_construct_extended_name_table (abfd, tabloc, tablen, name)
+ bfd *abfd;
+ char **tabloc;
+ bfd_size_type *tablen;
+ const char **name;
+{
+ *name = "//";
+ return _bfd_construct_extended_name_table (abfd, true, tabloc, 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! */
+
+boolean
+_bfd_construct_extended_name_table (abfd, trailing_slash, tabloc, tablen)
+ bfd *abfd;
+ boolean trailing_slash;
+ char **tabloc;
+ bfd_size_type *tablen;
+{
+ unsigned int maxname = abfd->xvec->ar_max_namelen;
+ unsigned int total_namelen = 0;
+ bfd *current;
+ char *strptr;
+
+ *tablen = 0;
+
+ /* Figure out how long the table should be */
+ for (current = abfd->archive_head; current != NULL; current = current->next)
+ {
+ const char *normal;
+ unsigned int thislen;
+
+ normal = normalize (current, current->filename);
+ if (normal == NULL)
+ return false;
+
+ thislen = strlen (normal);
+
+ if (thislen > maxname
+ && (bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
+ thislen = maxname;
+
+ if (thislen > maxname)
+ {
+ /* Add one to leave room for \n. */
+ total_namelen += thislen + 1;
+ if (trailing_slash)
+ {
+ /* Leave room for trailing slash. */
+ ++total_namelen;
+ }
+ }
+ else
+ {
+ struct ar_hdr *hdr = arch_hdr (current);
+ if (strncmp (normal, hdr->ar_name, thislen) != 0
+ || (thislen < sizeof hdr->ar_name
+ && hdr->ar_name[thislen] != ar_padchar (current)))
+ {
+ /* Must have been using extended format even though it
+ didn't need to. Fix it to use normal format. */
+ memcpy (hdr->ar_name, normal, thislen);
+ if (thislen < maxname
+ || (thislen == maxname && thislen < sizeof hdr->ar_name))
+ hdr->ar_name[thislen] = ar_padchar (current);
+ }
+ }
+ }
+
+ if (total_namelen == 0)
+ return true;
+
+ *tabloc = bfd_zalloc (abfd, total_namelen);
+ if (*tabloc == NULL)
+ return false;
+
+ *tablen = total_namelen;
+ strptr = *tabloc;
+
+ for (current = abfd->archive_head; current != NULL; current =
+ current->next)
+ {
+ const char *normal;
+ unsigned int thislen;
+
+ normal = normalize (current, current->filename);
+ if (normal == NULL)
+ 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);
+ if (! trailing_slash)
+ strptr[thislen] = '\012';
+ else
+ {
+ strptr[thislen] = '/';
+ strptr[thislen + 1] = '\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;
+ if (trailing_slash)
+ ++strptr;
+ }
+ }
+
+ 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 */
+
+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;
+ }
+
+ ared = (struct areltdata *) bfd_zalloc (abfd, sizeof (struct ar_hdr) +
+ sizeof (struct areltdata));
+ if (ared == NULL)
+ return NULL;
+ hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
+
+ /* ar headers are space padded, not null padded! */
+ 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", (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 = ' ';
+ }
+ strncpy (hdr->ar_fmag, ARFMAG, 2);
+ ared->parsed_size = status.st_size;
+ ared->arch_header = (char *) hdr;
+
+ return ared;
+}
+
+/* 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! */
+
+struct ar_hdr *
+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 (struct ar_hdr *) ar_elt->arch_header;
+}
+
+
+/* Analogous to stat call */
+int
+bfd_generic_stat_arch_elt (abfd, buf)
+ bfd *abfd;
+ struct stat *buf;
+{
+ struct ar_hdr *hdr;
+ char *aloser;
+
+ 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);
+ foo (ar_mode, st_mode, 8);
+
+ buf->st_size = arch_eltdata (abfd)->parsed_size;
+
+ return 0;
+}
+
+void
+bfd_dont_truncate_arname (abfd, pathname, arhdr)
+ bfd *abfd;
+ CONST char *pathname;
+ char *arhdr;
+{
+ /* FIXME: This interacts unpleasantly with ar's quick-append option.
+ 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;
+ size_t length;
+ const char *filename;
+ size_t maxlen = ar_maxnamelen (abfd);
+
+ if ((bfd_get_file_flags (abfd) & BFD_TRADITIONAL_FORMAT) != 0)
+ {
+ bfd_bsd_truncate_arname (abfd, pathname, arhdr);
+ return;
+ }
+
+ filename = normalize (abfd, pathname);
+ if (filename == NULL)
+ {
+ /* FIXME */
+ abort ();
+ }
+
+ length = strlen (filename);
+
+ if (length <= maxlen)
+ memcpy (hdr->ar_name, filename, length);
+
+ /* Add the padding character if there is room for it. */
+ if (length < maxlen
+ || (length == maxlen && length < sizeof hdr->ar_name))
+ (hdr->ar_name)[length] = ar_padchar (abfd);
+}
+
+void
+bfd_bsd_truncate_arname (abfd, pathname, arhdr)
+ bfd *abfd;
+ CONST char *pathname;
+ char *arhdr;
+{
+ struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+ int length;
+ CONST char *filename = strrchr (pathname, '/');
+ int maxlen = ar_maxnamelen (abfd);
+
+ if (filename == NULL)
+ filename = pathname;
+ else
+ ++filename;
+
+ length = strlen (filename);
+
+ if (length <= maxlen)
+ memcpy (hdr->ar_name, filename, length);
+ else
+ {
+ /* pathname: meet procrustes */
+ memcpy (hdr->ar_name, filename, maxlen);
+ length = maxlen;
+ }
+
+ 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. */
+
+/* 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;
+ CONST char *pathname;
+ char *arhdr;
+{
+ struct ar_hdr *hdr = (struct ar_hdr *) arhdr;
+ int length;
+ CONST char *filename = strrchr (pathname, '/');
+ int maxlen = ar_maxnamelen (abfd);
+
+ if (filename == NULL)
+ filename = pathname;
+ else
+ ++filename;
+
+ length = strlen (filename);
+
+ 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';
+ }
+ length = maxlen;
+ }
+
+ 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;
+{
+ bfd *current;
+ char *etable = NULL;
+ bfd_size_type elength = 0;
+ const char *ename = NULL;
+ 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_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)));
+ }
+
+ 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))
+#endif
+ )
+ hasobjects = true;
+ }
+ }
+
+ if (!BFD_SEND (arch, _bfd_construct_extended_name_table,
+ (arch, &etable, &elength, &ename)))
+ return false;
+
+ if (bfd_seek (arch, (file_ptr) 0, SEEK_SET) != 0)
+ return false;
+#ifdef GNU960
+ wrote = bfd_write (BFD_GNU960_ARMAG (arch), 1, SARMAG, arch);
+#else
+ wrote = bfd_write (ARMAG, 1, SARMAG, arch);
+#endif
+ if (wrote != SARMAG)
+ return false;
+
+ if (makemap && hasobjects)
+ {
+ if (_bfd_compute_and_write_armap (arch, elength) != true)
+ return false;
+ }
+
+ if (elength != 0)
+ {
+ struct ar_hdr hdr;
+
+ memset ((char *) (&hdr), 0, sizeof (struct ar_hdr));
+ strcpy (hdr.ar_name, ename);
+ /* Round size up to even number in archive header. */
+ sprintf (&(hdr.ar_size[0]), "%-10d",
+ (int) ((elength + 1) & ~1));
+ 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)
+ amt = remaining;
+ errno = 0;
+ 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)
+ return false;
+ remaining -= amt;
+ }
+ if ((arelt_size (current) % 2) == 1)
+ {
+ if (bfd_write ("\012", 1, 1, arch) != 1)
+ return false;
+ }
+ }
+
+ if (makemap && hasobjects)
+ {
+ /* 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
+ {
+ if (bfd_update_armap_timestamp (arch))
+ break;
+ (*_bfd_error_handler)
+ ("Warning: writing archive was slow: rewriting timestamp\n");
+ }
+ while (++tries < 6);
+ }
+
+ return true;
+}
+
+/* Note that the namidx for the first symbol is 0 */
+
+boolean
+_bfd_compute_and_write_armap (arch, elength)
+ bfd *arch;
+ unsigned int elength;
+{
+ 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;
+
+ map = (struct orl *) bfd_malloc (orl_max * sizeof (struct orl));
+ if (map == NULL)
+ goto error_return;
+
+ /* 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 error_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++)
+ {
+ if ((bfd_check_format (current, bfd_object) == true)
+ && ((bfd_get_file_flags (current) & HAS_SYMS)))
+ {
+ long storage;
+ long symcount;
+ long src_count;
+
+ storage = bfd_get_symtab_upper_bound (current);
+ if (storage < 0)
+ goto error_return;
+
+ if (storage != 0)
+ {
+ if (storage > syms_max)
+ {
+ if (syms_max > 0)
+ free (syms);
+ syms_max = storage;
+ syms = (asymbol **) bfd_malloc ((size_t) syms_max);
+ if (syms == NULL)
+ goto error_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;
+
+ 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;
+ new_map =
+ ((struct orl *)
+ bfd_realloc (map, orl_max * sizeof (struct orl)));
+ if (new_map == (struct orl *) NULL)
+ goto error_return;
+
+ map = new_map;
+ }
+
+ namelen = strlen (syms[src_count]->name);
+ map[orl_count].name = ((char **)
+ bfd_alloc (arch,
+ sizeof (char *)));
+ if (map[orl_count].name == NULL)
+ goto error_return;
+ *(map[orl_count].name) = bfd_alloc (arch, namelen + 1);
+ if (*(map[orl_count].name) == NULL)
+ goto error_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;
+ }
+ }
+ }
+
+ /* 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));
+
+ if (syms_max > 0)
+ free (syms);
+ if (map != NULL)
+ free (map);
+ if (first_name != NULL)
+ bfd_release (arch, first_name);
+
+ return ret;
+
+ 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
+bsd_write_armap (arch, elength, map, orl_count, stridx)
+ bfd *arch;
+ unsigned int elength;
+ struct orl *map;
+ unsigned int orl_count;
+ int stridx;
+{
+ int padit = stridx & 1;
+ unsigned int ranlibsize = orl_count * BSD_SYMDEF_SIZE;
+ unsigned int stringsize = stridx + padit;
+ /* Include 8 bytes to store ranlibsize and stringsize in output. */
+ unsigned int mapsize = ranlibsize + stringsize + 8;
+ file_ptr firstreal;
+ bfd *current = arch->archive_head;
+ bfd *last_elt = current; /* last element arch seen */
+ bfd_byte temp[4];
+ unsigned int count;
+ struct ar_hdr hdr;
+ struct stat statbuf;
+ unsigned int i;
+
+ firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
+
+ stat (arch->filename, &statbuf);
+ 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, "%ld", (long) getuid ());
+ sprintf (hdr.ar_gid, "%ld", (long) getgid ());
+ sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+ 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))
+ return false;
+ bfd_h_put_32 (arch, (bfd_vma) ranlibsize, temp);
+ if (bfd_write (temp, 1, sizeof (temp), arch) != sizeof (temp))
+ return false;
+
+ for (count = 0; count < orl_count; count++)
+ {
+ bfd_byte buf[BSD_SYMDEF_SIZE];
+
+ 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, buf);
+ bfd_h_put_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
+ if (bfd_write (buf, BSD_SYMDEF_SIZE, 1, arch) != BSD_SYMDEF_SIZE)
+ return false;
+ }
+
+ /* now write the strings themselves */
+ bfd_h_put_32 (arch, stringsize, temp);
+ if (bfd_write (temp, 1, sizeof (temp), arch) != sizeof (temp))
+ return false;
+ for (count = 0; count < orl_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 sun's ar we use a null. */
+ if (padit)
+ {
+ 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.
+
+ Return true if the timestamp was OK, or an unusual problem happened.
+ Return false if we updated the timestamp. */
+
+boolean
+_bfd_archive_bsd_update_armap_timestamp (arch)
+ bfd *arch;
+{
+ struct stat archstat;
+ struct ar_hdr hdr;
+ unsigned int i;
+
+ /* 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)
+ return true; /* OK by the linker's rules */
+
+ /* Update the timestamp. */
+ 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);
+ for (i = 0; i < sizeof (hdr.ar_date); i++)
+ if (hdr.ar_date[i] == '\0')
+ (hdr.ar_date)[i] = ' ';
+
+ /* Write it into the file. */
+ bfd_ardata (arch)->armap_datepos = (SARMAG
+ + offsetof (struct ar_hdr, ar_date[0]));
+ 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
+
+ offset of file for symbol n-1
+ symbol name 0
+ symbol name 1
+
+ symbol name n-1
+*/
+
+boolean
+coff_write_armap (arch, elength, map, symbol_count, stridx)
+ bfd *arch;
+ unsigned int elength;
+ struct orl *map;
+ 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 */
+ 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;
+ unsigned int count;
+ struct ar_hdr hdr;
+ unsigned int i;
+ int padit = mapsize & 1;
+
+ 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);
+
+ 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]) = ' ';
+
+ /* Write the ar header for this item and the number of symbols */
+
+ 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);
+
+ /* 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. */
+
+ 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++)
+ {
+ 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/contrib/gdb/bfd/archures.c b/contrib/gdb/bfd/archures.c
new file mode 100644
index 0000000..1db8bc2
--- /dev/null
+++ b/contrib/gdb/bfd/archures.c
@@ -0,0 +1,720 @@
+/* BFD library support routines for architectures.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include <ctype.h>
+
+/*
+
+SECTION
+ Architectures
+
+ BFD keeps one atom in a BFD describing the
+ architecture of the data attached to the BFD: a pointer to a
+ <<bfd_arch_info_type>>.
+
+ 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.
+
+ The architecture information is provided by each architecture package.
+ The set of default architectures is selected by the macro
+ <<SELECT_ARCHITECTURES>>. This is normally set up in the
+ @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
+ initialize method. It is up to the architecture back end to
+ 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}.
+*/
+
+/*
+
+SUBSECTION
+ bfd_architecture
+
+DESCRIPTION
+ This enum gives the object file's CPU architecture, in a
+ 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
+ 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
+.{
+. bfd_arch_unknown, {* File arch not known *}
+. bfd_arch_obscure, {* Arch known, not one of these *}
+. bfd_arch_m68k, {* Motorola 68xxx *}
+. bfd_arch_vax, {* DEC Vax *}
+. bfd_arch_i960, {* Intel 960 *}
+. {* The order of the following is important.
+. lower number indicates a machine type that
+. only accepts a subset of the instructions
+. available to machines with higher numbers.
+. The exception is the "ca", which is
+. incompatible with all other machines except
+. "core". *}
+.
+.#define bfd_mach_i960_core 1
+.#define bfd_mach_i960_ka_sa 2
+.#define bfd_mach_i960_kb_sb 3
+.#define bfd_mach_i960_mc 4
+.#define bfd_mach_i960_xa 5
+.#define bfd_mach_i960_ca 6
+.#define bfd_mach_i960_jx 7
+.#define bfd_mach_i960_hx 8
+.
+. bfd_arch_a29k, {* AMD 29000 *}
+. bfd_arch_sparc, {* SPARC *}
+.#define bfd_mach_sparc 1
+.{* The difference between v8plus and v9 is that v9 is a true 64 bit env. *}
+.#define bfd_mach_sparc_v8plus 2
+.#define bfd_mach_sparc_v8plusa 3 {* with ultrasparc add'ns *}
+.#define bfd_mach_sparc_v9 4
+.#define bfd_mach_sparc_v9a 5 {* with ultrasparc add'ns *}
+.{* Nonzero if MACH has the v9 instruction set. *}
+.#define bfd_mach_sparc_v9_p(mach) ((mach) != bfd_mach_sparc)
+. bfd_arch_mips, {* MIPS Rxxxx *}
+. bfd_arch_i386, {* Intel 386 *}
+. bfd_arch_we32k, {* AT&T WE32xxx *}
+. bfd_arch_tahoe, {* CCI/Harris Tahoe *}
+. bfd_arch_i860, {* Intel 860 *}
+. bfd_arch_romp, {* IBM ROMP PC/RT *}
+. bfd_arch_alliant, {* Alliant *}
+. bfd_arch_convex, {* Convex *}
+. bfd_arch_m88k, {* Motorola 88xxx *}
+. bfd_arch_pyramid, {* Pyramid Technology *}
+. 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 *}
+.#define bfd_mach_z8001 1
+.#define bfd_mach_z8002 2
+. bfd_arch_h8500, {* Hitachi H8/500 *}
+. bfd_arch_sh, {* Hitachi SH *}
+. bfd_arch_alpha, {* Dec Alpha *}
+. bfd_arch_arm, {* Advanced Risc Machines ARM *}
+. bfd_arch_ns32k, {* National Semiconductors ns32000 *}
+. bfd_arch_w65, {* WDC 65816 *}
+. bfd_arch_last
+. };
+
+
+*/
+
+/*
+
+SUBSECTION
+ bfd_arch_info
+
+DESCRIPTION
+ This structure contains information on architectures for use
+ within BFD.
+
+.
+.typedef struct bfd_arch_info
+.{
+. int bits_per_word;
+. int bits_per_address;
+. int bits_per_byte;
+. enum bfd_architecture arch;
+. unsigned long mach;
+. const char *arch_name;
+. const char *printable_name;
+. unsigned int section_align_power;
+. {* true if this is the default machine for the architecture *}
+. boolean the_default;
+. const struct bfd_arch_info * (*compatible)
+. PARAMS ((const struct bfd_arch_info *a,
+. const struct bfd_arch_info *b));
+.
+. boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+.
+. const struct bfd_arch_info *next;
+.} bfd_arch_info_type;
+*/
+
+extern const bfd_arch_info_type bfd_a29k_arch;
+extern const bfd_arch_info_type bfd_alpha_arch;
+extern const bfd_arch_info_type bfd_arm_arch;
+extern const bfd_arch_info_type bfd_h8300_arch;
+extern const bfd_arch_info_type bfd_h8500_arch;
+extern const bfd_arch_info_type bfd_hppa_arch;
+extern const bfd_arch_info_type bfd_i386_arch;
+extern const bfd_arch_info_type bfd_i860_arch;
+extern const bfd_arch_info_type bfd_i960_arch;
+extern const bfd_arch_info_type bfd_m68k_arch;
+extern const bfd_arch_info_type bfd_m88k_arch;
+extern const bfd_arch_info_type bfd_mips_arch;
+extern const bfd_arch_info_type bfd_powerpc_arch;
+extern const bfd_arch_info_type bfd_rs6000_arch;
+extern const bfd_arch_info_type bfd_sh_arch;
+extern const bfd_arch_info_type bfd_sparc_arch;
+extern const bfd_arch_info_type bfd_vax_arch;
+extern const bfd_arch_info_type bfd_we32k_arch;
+extern const bfd_arch_info_type bfd_z8k_arch;
+extern const bfd_arch_info_type bfd_ns32k_arch;
+extern const bfd_arch_info_type bfd_w65_arch;
+
+static const bfd_arch_info_type * const bfd_archures_list[] =
+{
+#ifdef SELECT_ARCHITECTURES
+ SELECT_ARCHITECTURES,
+#else
+ &bfd_a29k_arch,
+ &bfd_alpha_arch,
+ &bfd_arm_arch,
+ &bfd_h8300_arch,
+ &bfd_h8500_arch,
+ &bfd_hppa_arch,
+ &bfd_i386_arch,
+ &bfd_i860_arch,
+ &bfd_i960_arch,
+ &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,
+ &bfd_w65_arch,
+#endif
+ 0
+};
+
+/*
+FUNCTION
+ bfd_printable_name
+
+SYNOPSIS
+ const char *bfd_printable_name(bfd *abfd);
+
+DESCRIPTION
+ Return a printable string representing the architecture and machine
+ from the pointer to the architecture info structure.
+
+*/
+
+const char *
+bfd_printable_name (abfd)
+ bfd *abfd;
+{
+ return abfd->arch_info->printable_name;
+}
+
+
+
+/*
+FUNCTION
+ bfd_scan_arch
+
+SYNOPSIS
+ const bfd_arch_info_type *bfd_scan_arch(const char *string);
+
+DESCRIPTION
+ Figure out if BFD supports any cpu which could be described with
+ the name @var{string}. Return a pointer to an <<arch_info>>
+ structure if a machine is found, otherwise NULL.
+
+*/
+
+const bfd_arch_info_type *
+bfd_scan_arch (string)
+ const char *string;
+{
+ const bfd_arch_info_type * const *app, *ap;
+
+ /* Look through all the installed architectures */
+ for (app = bfd_archures_list; *app != NULL; app++)
+ {
+ for (ap = *app; ap != NULL; ap = ap->next)
+ {
+ if (ap->scan (ap, string))
+ return ap;
+ }
+ }
+
+ return NULL;
+}
+
+
+
+/*
+FUNCTION
+ bfd_arch_get_compatible
+
+SYNOPSIS
+ const bfd_arch_info_type *bfd_arch_get_compatible(
+ const bfd *abfd,
+ const bfd *bbfd);
+
+DESCRIPTION
+ 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.
+*/
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible (abfd, bbfd)
+ const bfd *abfd;
+ const bfd *bbfd;
+{
+ /* If either architecture is unknown, then all we can do is assume
+ the user knows what he's doing. */
+ if (abfd->arch_info->arch == bfd_arch_unknown)
+ return bbfd->arch_info;
+ if (bbfd->arch_info->arch == bfd_arch_unknown)
+ return abfd->arch_info;
+
+ /* Otherwise architecture-specific code has to decide. */
+ return abfd->arch_info->compatible (abfd->arch_info, bbfd->arch_info);
+}
+
+
+/*
+INTERNAL_DEFINITION
+ bfd_default_arch_struct
+
+DESCRIPTION
+ The <<bfd_default_arch_struct>> is an item of
+ <<bfd_arch_info_type>> which has been initialized to a fairly
+ generic state. A BFD starts life by pointing to this
+ structure, until the correct back end has determined the real
+ architecture of the file.
+
+.extern const bfd_arch_info_type bfd_default_arch_struct;
+
+*/
+
+const bfd_arch_info_type bfd_default_arch_struct =
+{
+ 32,32,8,bfd_arch_unknown,0,"unknown","unknown",2,true,
+ bfd_default_compatible,
+ bfd_default_scan,
+ 0,
+};
+
+/*
+FUNCTION
+ bfd_set_arch_info
+
+SYNOPSIS
+ void bfd_set_arch_info(bfd *abfd, const bfd_arch_info_type *arg);
+
+DESCRIPTION
+ Set the architecture info of @var{abfd} to @var{arg}.
+*/
+
+void
+bfd_set_arch_info (abfd, arg)
+ bfd *abfd;
+ const bfd_arch_info_type *arg;
+{
+ abfd->arch_info = arg;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_set_arch_mach
+
+SYNOPSIS
+ boolean bfd_default_set_arch_mach(bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long mach);
+
+DESCRIPTION
+ 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 <<arch_info>>
+ pointer.
+*/
+
+boolean
+bfd_default_set_arch_mach (abfd, arch, mach)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long mach;
+{
+ const bfd_arch_info_type * const *app, *ap;
+
+ for (app = bfd_archures_list; *app != NULL; app++)
+ {
+ for (ap = *app; ap != NULL; ap = ap->next)
+ {
+ if (ap->arch == arch
+ && (ap->mach == mach
+ || (mach == 0 && ap->the_default)))
+ {
+ abfd->arch_info = ap;
+ return true;
+ }
+ }
+ }
+
+ abfd->arch_info = &bfd_default_arch_struct;
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+}
+
+
+/*
+FUNCTION
+ bfd_get_arch
+
+SYNOPSIS
+ enum bfd_architecture bfd_get_arch(bfd *abfd);
+
+DESCRIPTION
+ Return the enumerated type which describes the BFD @var{abfd}'s
+ architecture.
+
+*/
+
+enum bfd_architecture
+bfd_get_arch (abfd)
+ bfd *abfd;
+{
+ return abfd->arch_info->arch;
+}
+
+/*
+FUNCTION
+ bfd_get_mach
+
+SYNOPSIS
+ unsigned long bfd_get_mach(bfd *abfd);
+
+DESCRIPTION
+ Return the long type which describes the BFD @var{abfd}'s
+ machine.
+*/
+
+unsigned long
+bfd_get_mach (abfd)
+ bfd *abfd;
+{
+ return abfd->arch_info->mach;
+}
+
+/*
+FUNCTION
+ bfd_arch_bits_per_byte
+
+SYNOPSIS
+ unsigned int bfd_arch_bits_per_byte(bfd *abfd);
+
+DESCRIPTION
+ Return the number of bits in one of the BFD @var{abfd}'s
+ architecture's bytes.
+
+*/
+
+unsigned int
+bfd_arch_bits_per_byte (abfd)
+ bfd *abfd;
+{
+ return abfd->arch_info->bits_per_byte;
+}
+
+/*
+FUNCTION
+ bfd_arch_bits_per_address
+
+SYNOPSIS
+ unsigned int bfd_arch_bits_per_address(bfd *abfd);
+
+DESCRIPTION
+ Return the number of bits in one of the BFD @var{abfd}'s
+ architecture's addresses.
+*/
+
+unsigned int
+bfd_arch_bits_per_address (abfd)
+ bfd *abfd;
+{
+ return abfd->arch_info->bits_per_address;
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_compatible
+
+SYNOPSIS
+ const bfd_arch_info_type *bfd_default_compatible
+ (const bfd_arch_info_type *a,
+ const bfd_arch_info_type *b);
+
+DESCRIPTION
+ The default function for testing for compatibility.
+*/
+
+const bfd_arch_info_type *
+bfd_default_compatible (a,b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+ if (a->arch != b->arch)
+ return NULL;
+
+ if (a->mach > b->mach)
+ return a;
+
+ if (b->mach > a->mach)
+ return b;
+
+ return a;
+}
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_scan
+
+SYNOPSIS
+ boolean bfd_default_scan(const struct bfd_arch_info *info, const char *string);
+
+DESCRIPTION
+ The default function for working out whether this is an
+ architecture hit and a machine hit.
+*/
+
+boolean
+bfd_default_scan (info, string)
+ const struct bfd_arch_info *info;
+ const char *string;
+{
+ const char *ptr_src;
+ const char *ptr_tst;
+ unsigned long number;
+ enum bfd_architecture arch;
+
+ /* First test for an exact match */
+ if (strcmp (string, info->printable_name) == 0)
+ return true;
+
+ /* See how much of the supplied string matches with the
+ architecture, eg the string m68k:68020 would match the 68k entry
+ up to the :, then we get left with the machine number */
+
+ for (ptr_src = string, ptr_tst = info->arch_name;
+ *ptr_src && *ptr_tst;
+ ptr_src++, ptr_tst++)
+ {
+ if (*ptr_src != *ptr_tst) break;
+ }
+
+ /* Chewed up as much of the architecture as will match, skip any
+ colons */
+ if (*ptr_src == ':')
+ ptr_src++;
+
+ if (*ptr_src == 0)
+ {
+ /* nothing more, then only keep this one if it is the default
+ machine for this architecture */
+ return info->the_default;
+ }
+
+ number = 0;
+ while (isdigit(*ptr_src))
+ {
+ number = number * 10 + *ptr_src - '0';
+ ptr_src++;
+ }
+
+ switch (number)
+ {
+ case 65:
+ arch = bfd_arch_w65;
+ break;
+
+ case 300:
+ arch = bfd_arch_h8300;
+ break;
+
+ case 500:
+ arch = bfd_arch_h8500;
+ break;
+
+ case 68010:
+ case 68020:
+ case 68030:
+ case 68040:
+ case 68332:
+ case 68050:
+ case 68000:
+ arch = bfd_arch_m68k;
+ break;
+
+ case 386:
+ case 80386:
+ case 486:
+ case 80486:
+ arch = bfd_arch_i386;
+ break;
+
+ case 29000:
+ arch = bfd_arch_a29k;
+ break;
+
+ case 8000:
+ arch = bfd_arch_z8k;
+ break;
+
+ case 32000:
+ arch = bfd_arch_we32k;
+ break;
+
+ case 860:
+ case 80860:
+ arch = bfd_arch_i860;
+ break;
+ case 960:
+ case 80960:
+ arch = bfd_arch_i960;
+ break;
+
+ case 2000:
+ case 3000:
+ case 4000:
+ case 4400:
+ arch = bfd_arch_mips;
+ break;
+
+ case 6000:
+ arch = bfd_arch_rs6000;
+ break;
+
+ default:
+ return false;
+ }
+
+ if (arch != info->arch)
+ return false;
+
+ if (number != info->mach)
+ return false;
+
+ return true;
+}
+
+
+/*
+FUNCTION
+ bfd_get_arch_info
+
+SYNOPSIS
+ const bfd_arch_info_type * bfd_get_arch_info(bfd *abfd);
+
+DESCRIPTION
+ Return the architecture info struct in @var{abfd}.
+*/
+
+const bfd_arch_info_type *
+bfd_get_arch_info (abfd)
+ bfd *abfd;
+{
+ return abfd->arch_info;
+}
+
+
+/*
+FUNCTION
+ bfd_lookup_arch
+
+SYNOPSIS
+ const bfd_arch_info_type *bfd_lookup_arch
+ (enum bfd_architecture
+ arch,
+ unsigned long machine);
+
+DESCRIPTION
+ 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.
+*/
+
+const bfd_arch_info_type *
+bfd_lookup_arch (arch, machine)
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ const bfd_arch_info_type * const *app, *ap;
+
+ for (app = bfd_archures_list; *app != NULL; app++)
+ {
+ for (ap = *app; ap != NULL; ap = ap->next)
+ {
+ if (ap->arch == arch
+ && (ap->mach == machine
+ || (machine == 0 && ap->the_default)))
+ return ap;
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+FUNCTION
+ bfd_printable_arch_mach
+
+SYNOPSIS
+ const char *bfd_printable_arch_mach
+ (enum bfd_architecture arch, unsigned long machine);
+
+DESCRIPTION
+ Return a printable string representing the architecture and
+ machine type.
+
+ This routine is depreciated.
+*/
+
+const char *
+bfd_printable_arch_mach (arch, machine)
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ const bfd_arch_info_type *ap = bfd_lookup_arch (arch, machine);
+
+ if (ap)
+ return ap->printable_name;
+ return "UNKNOWN!";
+}
diff --git a/contrib/gdb/bfd/bfd-in.h b/contrib/gdb/bfd/bfd-in.h
new file mode 100644
index 0000000..d291239
--- /dev/null
+++ b/contrib/gdb/bfd/bfd-in.h
@@ -0,0 +1,668 @@
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+** NOTE: bfd.h and bfd-in2.h are GENERATED files. Don't change them;
+** instead, change bfd-in.h or the other BFD source files processed to
+** generate these files.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* bfd.h -- The only header file required by users of the bfd library
+
+The bfd.h file is generated from bfd-in.h and various .c files; if you
+change it, your changes will probably be lost.
+
+All the prototypes and definitions following the comment "THE FOLLOWING
+IS EXTRACTED FROM THE SOURCE" are extracted from the source files for
+BFD. If you change it, someone oneday will extract it from the source
+again, and your changes will be lost. To save yourself from this bind,
+change the definitions in the source in the bfd directory. Type "make
+docs" and then "make headers" in that directory, and magically this file
+will change to reflect your changes.
+
+If you don't have the tools to perform the extraction, then you are
+safe from someone on your system trampling over your header files.
+You should still maintain the equivalence between the source and this
+file though; every change you make to the .c file should be reflected
+here. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+#include "obstack.h"
+
+/* These two lines get substitutions done by commands in Makefile.in. */
+#define BFD_VERSION "@VERSION@"
+#define BFD_ARCH_SIZE @WORDSIZE@
+#define BFD_HOST_64BIT_LONG @BFD_HOST_64BIT_LONG@
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* forward declaration */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+#if defined (__GNUG__) && (__GNUC_MINOR__ > 5)
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef long int file_ptr;
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, the compilation will fail
+ if 64-bit targets are requested. */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+#if BFD_HOST_64BIT_LONG
+#define BFD_HOST_64_BIT long
+#else
+#ifdef __GNUC__
+#define BFD_HOST_64_BIT long long
+#endif /* defined (__GNUC__) */
+#endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+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
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf(s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf(s, "%08lx", x)
+#endif /* not BFD64 */
+#define printf_vma(x) fprintf_vma(stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/** File formats */
+
+typedef enum bfd_format {
+ bfd_unknown = 0, /* file format is unknown */
+ bfd_object, /* linker/assember/compiler output */
+ bfd_archive, /* object archive file */
+ bfd_core, /* core dump */
+ bfd_type_end} /* marks the end; don't use it! */
+ bfd_format;
+
+/* 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) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#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
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* symbols and relocation */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* 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)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#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;
+ file_ptr file_offset; /* look here to find the file */
+} carsym; /* to make these you call a carsymogen */
+
+
+/* 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 */
+ int namidx; /* index into string table */
+};
+
+
+/* Linenumber stuff */
+typedef struct lineno_cache_entry {
+ unsigned int line_number; /* Linenumber from start of function*/
+ union {
+ struct symbol_cache_entry *sym; /* Function name */
+ unsigned long offset; /* Offset into section */
+ } u;
+} alent;
+
+/* object and core file sections */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ CONST char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ CONST char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* 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));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* 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
+ want extra underscores (e.g., "nlm_32_"). The XCAT2 macro will cause the
+ inner CAT macros to be evaluated first, producing still-valid pp-tokens.
+ Then the final concatenation can be done. (Sigh.) */
+#ifndef CAT
+#ifdef SABER
+#define CAT(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define CAT4(a,b,c,d) a##b##c##d
+#else
+#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)
+#define CAT4(a,b,c,d) XCAT2(CAT(a,b),CAT(c,d))
+#else
+#define CAT(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#define CAT4(a,b,c,d) a/**/b/**/c/**/d
+#endif
+#endif
+#endif
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_read
+ PARAMS ((PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern bfd_size_type bfd_write
+ PARAMS ((const PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern int bfd_seek PARAMS ((bfd *abfd, file_ptr fp, int direction));
+extern long bfd_tell PARAMS ((bfd *abfd));
+extern int bfd_flush PARAMS ((bfd *abfd));
+extern int bfd_stat PARAMS ((bfd *abfd, struct stat *));
+
+
+/* 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_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#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)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean)(bool)), true)
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+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;
+struct bfd_link_hash_entry;
+#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));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, boolean,
+ struct bfd_link_info *, struct sec **));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, boolean,
+ struct bfd_link_info *, struct sec **));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+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_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window {
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+} bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ boolean));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+
+/* And more from the source. */
diff --git a/contrib/gdb/bfd/bfd-in2.h b/contrib/gdb/bfd/bfd-in2.h
new file mode 100644
index 0000000..d238d5a
--- /dev/null
+++ b/contrib/gdb/bfd/bfd-in2.h
@@ -0,0 +1,2479 @@
+/* Main header file for the bfd library -- portable access to object files.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+** NOTE: bfd.h and bfd-in2.h are GENERATED files. Don't change them;
+** instead, change bfd-in.h or the other BFD source files processed to
+** generate these files.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* bfd.h -- The only header file required by users of the bfd library
+
+The bfd.h file is generated from bfd-in.h and various .c files; if you
+change it, your changes will probably be lost.
+
+All the prototypes and definitions following the comment "THE FOLLOWING
+IS EXTRACTED FROM THE SOURCE" are extracted from the source files for
+BFD. If you change it, someone oneday will extract it from the source
+again, and your changes will be lost. To save yourself from this bind,
+change the definitions in the source in the bfd directory. Type "make
+docs" and then "make headers" in that directory, and magically this file
+will change to reflect your changes.
+
+If you don't have the tools to perform the extraction, then you are
+safe from someone on your system trampling over your header files.
+You should still maintain the equivalence between the source and this
+file though; every change you make to the .c file should be reflected
+here. */
+
+#ifndef __BFD_H_SEEN__
+#define __BFD_H_SEEN__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ansidecl.h"
+#include "obstack.h"
+
+/* These two lines get substitutions done by commands in Makefile.in. */
+#define BFD_VERSION "@VERSION@"
+#define BFD_ARCH_SIZE @WORDSIZE@
+#define BFD_HOST_64BIT_LONG @BFD_HOST_64BIT_LONG@
+
+#if BFD_ARCH_SIZE >= 64
+#define BFD64
+#endif
+
+#ifndef INLINE
+#if __GNUC__ >= 2
+#define INLINE __inline__
+#else
+#define INLINE
+#endif
+#endif
+
+/* forward declaration */
+typedef struct _bfd bfd;
+
+/* To squelch erroneous compiler warnings ("illegal pointer
+ combination") from the SVR3 compiler, we would like to typedef
+ boolean to int (it doesn't like functions which return boolean.
+ Making sure they are never implicitly declared to return int
+ doesn't seem to help). But this file is not configured based on
+ the host. */
+/* General rules: functions which are boolean return true on success
+ and false on failure (unless they're a predicate). -- bfd.doc */
+/* I'm sure this is going to break something and someone is going to
+ force me to change it. */
+/* typedef enum boolean {false, true} boolean; */
+/* Yup, SVR4 has a "typedef enum boolean" in <sys/types.h> -fnf */
+/* It gets worse if the host also defines a true/false enum... -sts */
+/* And even worse if your compiler has built-in boolean types... -law */
+#if defined (__GNUG__) && (__GNUC_MINOR__ > 5)
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif
+#ifdef MPW
+/* Pre-emptive strike - get the file with the enum. */
+#include <Types.h>
+#define TRUE_FALSE_ALREADY_DEFINED
+#endif /* MPW */
+#ifndef TRUE_FALSE_ALREADY_DEFINED
+typedef enum bfd_boolean {false, true} boolean;
+#define BFD_TRUE_FALSE
+#else
+/* Use enum names that will appear nowhere else. */
+typedef enum bfd_boolean {bfd_fffalse, bfd_tttrue} boolean;
+#endif
+
+/* A pointer to a position in a file. */
+/* FIXME: This should be using off_t from <sys/types.h>.
+ For now, try to avoid breaking stuff by not including <sys/types.h> here.
+ This will break on systems with 64-bit file offsets (e.g. 4.4BSD).
+ Probably the best long-term answer is to avoid using file_ptr AND off_t
+ in this header file, and to handle this in the BFD implementation
+ rather than in its interface. */
+/* typedef off_t file_ptr; */
+typedef long int file_ptr;
+
+/* Support for different sizes of target format ints and addresses.
+ If the type `long' is at least 64 bits, BFD_HOST_64BIT_LONG will be
+ set to 1 above. Otherwise, if gcc is being used, this code will
+ use gcc's "long long" type. Otherwise, the compilation will fail
+ if 64-bit targets are requested. */
+
+#ifdef BFD64
+
+#ifndef BFD_HOST_64_BIT
+#if BFD_HOST_64BIT_LONG
+#define BFD_HOST_64_BIT long
+#else
+#ifdef __GNUC__
+#define BFD_HOST_64_BIT long long
+#endif /* defined (__GNUC__) */
+#endif /* ! BFD_HOST_64BIT_LONG */
+#endif /* ! defined (BFD_HOST_64_BIT) */
+
+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
+#if BFD_HOST_64BIT_LONG
+#define sprintf_vma(s,x) sprintf (s, "%016lx", x)
+#define fprintf_vma(f,x) fprintf (f, "%016lx", x)
+#else
+#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff)))
+#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff))
+#define fprintf_vma(s,x) \
+ fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#define sprintf_vma(s,x) \
+ sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x))
+#endif
+#endif
+
+#else /* not BFD64 */
+
+/* Represent a target address. Also used as a generic unsigned type
+ which is guaranteed to be big enough to hold any arithmetic types
+ we need to deal with. */
+typedef unsigned long bfd_vma;
+
+/* A generic signed type which is guaranteed to be big enough to hold any
+ arithmetic types we need to deal with. Can be assumed to be compatible
+ with bfd_vma in the same way that signed and unsigned ints are compatible
+ (as parameters, in assignment, etc). */
+typedef long bfd_signed_vma;
+
+typedef unsigned long symvalue;
+typedef unsigned long bfd_size_type;
+
+/* Print a bfd_vma x on stream s. */
+#define fprintf_vma(s,x) fprintf(s, "%08lx", x)
+#define sprintf_vma(s,x) sprintf(s, "%08lx", x)
+#endif /* not BFD64 */
+#define printf_vma(x) fprintf_vma(stdout,x)
+
+typedef unsigned int flagword; /* 32 bits of flags */
+typedef unsigned char bfd_byte;
+
+/** File formats */
+
+typedef enum bfd_format {
+ bfd_unknown = 0, /* file format is unknown */
+ bfd_object, /* linker/assember/compiler output */
+ bfd_archive, /* object archive file */
+ bfd_core, /* core dump */
+ bfd_type_end} /* marks the end; don't use it! */
+ bfd_format;
+
+/* 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) (sometimes bfd_relax_section can do something even if
+ this is not set). */
+#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
+
+/* This flag indicates that the BFD contents are actually cached in
+ memory. If this is set, iostream points to a bfd_in_memory struct. */
+#define BFD_IN_MEMORY 0x800
+
+/* symbols and relocation */
+
+/* A count of carsyms (canonical archive symbols). */
+typedef unsigned long symindex;
+
+/* How to perform a relocation. */
+typedef const struct reloc_howto_struct reloc_howto_type;
+
+#define BFD_NO_MORE_SYMBOLS ((symindex) ~0)
+
+/* 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)
+#define bfd_set_section(x,y) ((x)->section) = (y)
+#define bfd_asymbol_base(x) ((x)->section->vma)
+#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value)
+#define bfd_asymbol_name(x) ((x)->name)
+/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/
+#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;
+ file_ptr file_offset; /* look here to find the file */
+} carsym; /* to make these you call a carsymogen */
+
+
+/* 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 */
+ int namidx; /* index into string table */
+};
+
+
+/* Linenumber stuff */
+typedef struct lineno_cache_entry {
+ unsigned int line_number; /* Linenumber from start of function*/
+ union {
+ struct symbol_cache_entry *sym; /* Function name */
+ unsigned long offset; /* Offset into section */
+ } u;
+} alent;
+
+/* object and core file sections */
+
+#define align_power(addr, align) \
+ ( ((addr) + ((1<<(align))-1)) & (-1 << (align)))
+
+typedef struct sec *sec_ptr;
+
+#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0)
+#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0)
+#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0)
+#define bfd_section_name(bfd, ptr) ((ptr)->name)
+#define bfd_section_size(bfd, ptr) (bfd_get_section_size_before_reloc(ptr))
+#define bfd_section_vma(bfd, ptr) ((ptr)->vma)
+#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power)
+#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0)
+#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata)
+
+#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0)
+
+#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma= (val)), ((ptr)->user_set_vma = (boolean)true), true)
+#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),true)
+#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),true)
+
+typedef struct stat stat_type;
+
+typedef enum bfd_print_symbol
+{
+ bfd_print_symbol_name,
+ bfd_print_symbol_more,
+ bfd_print_symbol_all
+} bfd_print_symbol_type;
+
+/* Information about a symbol that nm needs. */
+
+typedef struct _symbol_info
+{
+ symvalue value;
+ char type;
+ CONST char *name; /* Symbol name. */
+ unsigned char stab_type; /* Stab type. */
+ char stab_other; /* Stab other. */
+ short stab_desc; /* Stab desc. */
+ CONST char *stab_name; /* String for stab type. */
+} symbol_info;
+
+/* Get the name of a stabs type code. */
+
+extern const char *bfd_get_stab_name PARAMS ((int));
+
+/* 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));
+
+/* Replace an entry in a hash table. */
+extern void bfd_hash_replace
+ PARAMS ((struct bfd_hash_table *, struct bfd_hash_entry *old,
+ struct bfd_hash_entry *nw));
+
+/* 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
+ want extra underscores (e.g., "nlm_32_"). The XCAT2 macro will cause the
+ inner CAT macros to be evaluated first, producing still-valid pp-tokens.
+ Then the final concatenation can be done. (Sigh.) */
+#ifndef CAT
+#ifdef SABER
+#define CAT(a,b) a##b
+#define CAT3(a,b,c) a##b##c
+#define CAT4(a,b,c,d) a##b##c##d
+#else
+#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)
+#define CAT4(a,b,c,d) XCAT2(CAT(a,b),CAT(c,d))
+#else
+#define CAT(a,b) a/**/b
+#define CAT3(a,b,c) a/**/b/**/c
+#define CAT4(a,b,c,d) a/**/b/**/c/**/d
+#endif
+#endif
+#endif
+
+#define COFF_SWAP_TABLE (PTR) &bfd_coff_std_swap_table
+
+/* User program access to BFD facilities */
+
+/* Direct I/O routines, for programs which know more about the object
+ file than BFD does. Use higher level routines if possible. */
+
+extern bfd_size_type bfd_read
+ PARAMS ((PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern bfd_size_type bfd_write
+ PARAMS ((const PTR, bfd_size_type size, bfd_size_type nitems, bfd *abfd));
+extern int bfd_seek PARAMS ((bfd *abfd, file_ptr fp, int direction));
+extern long bfd_tell PARAMS ((bfd *abfd));
+extern int bfd_flush PARAMS ((bfd *abfd));
+extern int bfd_stat PARAMS ((bfd *abfd, struct stat *));
+
+
+/* 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_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG)
+#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE)
+#define bfd_header_big_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG)
+#define bfd_header_little_endian(abfd) \
+ ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE)
+#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)
+#define bfd_my_archive(abfd) ((abfd)->my_archive)
+#define bfd_has_map(abfd) ((abfd)->has_armap)
+
+#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types)
+#define bfd_usrdata(abfd) ((abfd)->usrdata)
+
+#define bfd_get_start_address(abfd) ((abfd)->start_address)
+#define bfd_get_symcount(abfd) ((abfd)->symcount)
+#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols)
+#define bfd_count_sections(abfd) ((abfd)->section_count)
+
+#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char)
+
+#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = (boolean)(bool)), true)
+
+extern boolean bfd_record_phdr
+ PARAMS ((bfd *, unsigned long, boolean, flagword, boolean, bfd_vma,
+ boolean, boolean, unsigned int, struct sec **));
+
+/* Byte swapping routines. */
+
+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;
+struct bfd_link_hash_entry;
+#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));
+extern boolean bfd_mips_ecoff_create_embedded_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, struct sec *, struct sec *,
+ char **));
+
+/* Externally visible ELF routines. */
+
+struct bfd_link_needed_list
+{
+ struct bfd_link_needed_list *next;
+ bfd *by;
+ const char *name;
+};
+
+extern boolean bfd_elf32_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern boolean bfd_elf64_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean));
+extern struct bfd_link_needed_list *bfd_elf_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_elf32_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, boolean,
+ struct bfd_link_info *, struct sec **));
+extern boolean bfd_elf64_size_dynamic_sections
+ PARAMS ((bfd *, const char *, const char *, boolean,
+ struct bfd_link_info *, struct sec **));
+extern void bfd_elf_set_dt_needed_name PARAMS ((bfd *, const char *));
+extern const char *bfd_elf_get_dt_soname PARAMS ((bfd *));
+
+/* SunOS shared library support routines for the linker. */
+
+extern struct bfd_link_needed_list *bfd_sunos_get_needed_list
+ PARAMS ((bfd *, struct bfd_link_info *));
+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_i386linux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean bfd_m68klinux_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* mmap hacks */
+
+struct _bfd_window_internal;
+typedef struct _bfd_window_internal bfd_window_internal;
+
+typedef struct _bfd_window {
+ /* What the user asked for. */
+ PTR data;
+ bfd_size_type size;
+ /* The actual window used by BFD. Small user-requested read-only
+ regions sharing a page may share a single window into the object
+ file. Read-write versions shouldn't until I've fixed things to
+ keep track of which portions have been claimed by the
+ application; don't want to give the same region back when the
+ application wants two writable copies! */
+ struct _bfd_window_internal *i;
+} bfd_window;
+
+extern void bfd_init_window PARAMS ((bfd_window *));
+extern void bfd_free_window PARAMS ((bfd_window *));
+extern boolean bfd_get_file_window
+ PARAMS ((bfd *, file_ptr, bfd_size_type, bfd_window *, boolean));
+
+/* XCOFF support routines for the linker. */
+
+extern boolean bfd_xcoff_link_record_set
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_size_type));
+extern boolean bfd_xcoff_import_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ bfd_vma, const char *, const char *, const char *));
+extern boolean bfd_xcoff_export_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *,
+ boolean));
+extern boolean bfd_xcoff_link_count_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_record_link_assignment
+ PARAMS ((bfd *, struct bfd_link_info *, const char *));
+extern boolean bfd_xcoff_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, const char *,
+ unsigned long, unsigned long, unsigned long, boolean,
+ int, boolean, boolean, struct sec **));
+
+/* And more from the source. */
+void
+bfd_init PARAMS ((void));
+
+bfd *
+bfd_openr PARAMS ((CONST char *filename, CONST char *target));
+
+bfd *
+bfd_fdopenr PARAMS ((CONST char *filename, CONST char *target, int fd));
+
+bfd *
+bfd_openstreamr PARAMS (());
+
+bfd *
+bfd_openw PARAMS ((CONST char *filename, CONST char *target));
+
+boolean
+bfd_close PARAMS ((bfd *abfd));
+
+boolean
+bfd_close_all_done PARAMS ((bfd *));
+
+bfd_size_type
+bfd_alloc_size PARAMS ((bfd *abfd));
+
+bfd *
+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))
+#define bfd_put_signed_8 \
+ bfd_put_8
+#define bfd_get_8(abfd, ptr) \
+ (*(unsigned char *)(ptr))
+#define bfd_get_signed_8(abfd, ptr) \
+ ((*(unsigned char *)(ptr) ^ 0x80) - 0x80)
+
+#define bfd_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+#define bfd_put_signed_16 \
+ bfd_put_16
+#define bfd_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx16, (ptr))
+#define bfd_get_signed_16(abfd, ptr) \
+ BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+
+#define bfd_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+#define bfd_put_signed_32 \
+ bfd_put_32
+#define bfd_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx32, (ptr))
+#define bfd_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+
+#define bfd_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+#define bfd_put_signed_64 \
+ bfd_put_64
+#define bfd_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx64, (ptr))
+#define bfd_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+
+
+ /* Byte swapping macros for file header data. */
+
+#define bfd_h_put_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_put_signed_8(abfd, val, ptr) \
+ bfd_put_8 (abfd, val, ptr)
+#define bfd_h_get_8(abfd, ptr) \
+ bfd_get_8 (abfd, ptr)
+#define bfd_h_get_signed_8(abfd, ptr) \
+ bfd_get_signed_8 (abfd, ptr)
+
+#define bfd_h_put_16(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
+#define bfd_h_put_signed_16 \
+ bfd_h_put_16
+#define bfd_h_get_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx16,(ptr))
+#define bfd_h_get_signed_16(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))
+
+#define bfd_h_put_32(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
+#define bfd_h_put_signed_32 \
+ bfd_h_put_32
+#define bfd_h_get_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx32,(ptr))
+#define bfd_h_get_signed_32(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))
+
+#define bfd_h_put_64(abfd, val, ptr) \
+ BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
+#define bfd_h_put_signed_64 \
+ bfd_h_put_64
+#define bfd_h_get_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx64,(ptr))
+#define bfd_h_get_signed_64(abfd, ptr) \
+ BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr))
+
+typedef struct sec
+{
+ /* 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. */
+
+ 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
+ flags are read in from the object file, and some are
+ synthesized from other information. */
+
+ flagword flags;
+
+#define SEC_NO_FLAGS 0x000
+
+ /* 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 is clear for a .bss section. */
+#define SEC_LOAD 0x002
+
+ /* The section contains data still to be relocated, so there is
+ some relocation information too. */
+#define SEC_RELOC 0x004
+
+#if 0 /* Obsolete ? */
+#define SEC_BALIGN 0x008
+#endif
+
+ /* A signal to the OS that the section contains read only
+ data. */
+#define SEC_READONLY 0x010
+
+ /* The section contains code only. */
+#define SEC_CODE 0x020
+
+ /* The section contains data only. */
+#define SEC_DATA 0x040
+
+ /* The section will reside in ROM. */
+#define SEC_ROM 0x080
+
+ /* The section contains constructor information. This section
+ type is used by the linker to create lists of constructors and
+ destructors used by <<g++>>. 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 (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 relocate the data
+ contained within - exactly the operations it would peform on
+ standard data. */
+#define SEC_CONSTRUCTOR 0x100
+
+ /* The section is a constuctor, and should be placed at the
+ end of the text, data, or bss section(?). */
+#define SEC_CONSTRUCTOR_TEXT 0x1100
+#define SEC_CONSTRUCTOR_DATA 0x2100
+#define SEC_CONSTRUCTOR_BSS 0x3100
+
+ /* The section has contents - a data section could be
+ <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+ <<SEC_HAS_CONTENTS>> */
+#define SEC_HAS_CONTENTS 0x200
+
+ /* 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 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_ptr), but ECOFF has two. */
+#define SEC_IS_COMMON 0x8000
+
+ /* The section contains only debugging information. For
+ example, this is set for ELF .debug and .stab sections.
+ strip tests this flag to see if a section can be
+ 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
+
+ /* The contents of this section are to be excluded by the
+ linker for executable and shared objects unless those
+ objects are to be further relocated. */
+#define SEC_EXCLUDE 0x40000
+
+ /* The contents of this section are to be sorted by the
+ based on the address specified in the associated symbol
+ table. */
+#define SEC_SORT_ENTRIES 0x80000
+
+ /* End of section flags. */
+
+ /* The virtual memory address of the section - where it will be
+ at run time. The symbols are relocated against this. The
+ user_set_vma flag is maintained by bfd; if it's not set, the
+ backend can assign addresses (for example, in <<a.out>>, where
+ the default address for <<.data>> is dependent on the specific
+ target and various flags). */
+
+ bfd_vma vma;
+ 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
+ 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 (e.g., the
+ size of <<.bss>>). This will be filled in after relocation */
+
+ bfd_size_type _cooked_size;
+
+ /* 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;
+
+ /* 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. 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;
+
+ /* The output section through which to map on output. */
+
+ struct sec *output_section;
+
+ /* The alignment requirement of the section, as an exponent of 2 -
+ e.g., 3 aligns to 2^3 (or 8). */
+
+ unsigned int alignment_power;
+
+ /* If an input section, a pointer to a vector of relocation
+ records for the data in this section. */
+
+ struct reloc_cache_entry *relocation;
+
+ /* If an output section, a pointer to a vector of pointers to
+ relocation records for the data in this section. */
+
+ struct reloc_cache_entry **orelocation;
+
+ /* The number of relocation records in one of the above */
+
+ unsigned reloc_count;
+
+ /* Information below is back end specific - and not always used
+ or updated. */
+
+ /* File position of section data */
+
+ file_ptr filepos;
+
+ /* File position of relocation info */
+
+ file_ptr rel_filepos;
+
+ /* File position of line data */
+
+ file_ptr line_filepos;
+
+ /* Pointer to data for applications */
+
+ PTR userdata;
+
+ /* 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;
+
+ /* When a section is being output, this value changes as more
+ linenumbers are written out */
+
+ file_ptr moving_line_filepos;
+
+ /* What the section number is in the target world */
+
+ int target_index;
+
+ PTR used_by_bfd;
+
+ /* If this is a constructor section then here is a list of the
+ relocations created to relocate items within it. */
+
+ struct relent_chain *constructor_chain;
+
+ /* The BFD which owns the section. */
+
+ bfd *owner;
+
+ boolean reloc_done;
+ /* A symbol which points at this section only */
+ struct symbol_cache_entry *symbol;
+ struct symbol_cache_entry **symbol_ptr_ptr;
+
+ 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. 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 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 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 const asection bfd_com_section;
+#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+ /* Pointer to the indirect 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 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) \
+ ((section->reloc_done) ? (section)->_cooked_size: (abort(),1))
+asection *
+bfd_get_section_by_name PARAMS ((bfd *abfd, CONST char *name));
+
+asection *
+bfd_make_section_old_way PARAMS ((bfd *abfd, CONST char *name));
+
+asection *
+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 *abfd, asection *sec, flagword flags));
+
+void
+bfd_map_over_sections PARAMS ((bfd *abfd,
+ void (*func)(bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj));
+
+boolean
+bfd_set_section_size PARAMS ((bfd *abfd, asection *sec, bfd_size_type val));
+
+boolean
+bfd_set_section_contents
+ PARAMS ((bfd *abfd,
+ asection *section,
+ PTR data,
+ file_ptr offset,
+ bfd_size_type count));
+
+boolean
+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 */
+ bfd_arch_obscure, /* Arch known, not one of these */
+ bfd_arch_m68k, /* Motorola 68xxx */
+ bfd_arch_vax, /* DEC Vax */
+ bfd_arch_i960, /* Intel 960 */
+ /* The order of the following is important.
+ lower number indicates a machine type that
+ only accepts a subset of the instructions
+ available to machines with higher numbers.
+ The exception is the "ca", which is
+ incompatible with all other machines except
+ "core". */
+
+#define bfd_mach_i960_core 1
+#define bfd_mach_i960_ka_sa 2
+#define bfd_mach_i960_kb_sb 3
+#define bfd_mach_i960_mc 4
+#define bfd_mach_i960_xa 5
+#define bfd_mach_i960_ca 6
+#define bfd_mach_i960_jx 7
+#define bfd_mach_i960_hx 8
+
+ bfd_arch_a29k, /* AMD 29000 */
+ bfd_arch_sparc, /* SPARC */
+#define bfd_mach_sparc 1
+ /* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
+#define bfd_mach_sparc_v8plus 2
+#define bfd_mach_sparc_v8plusa 3 /* with ultrasparc add'ns */
+#define bfd_mach_sparc_v9 4
+#define bfd_mach_sparc_v9a 5 /* with ultrasparc add'ns */
+ /* Nonzero if MACH has the v9 instruction set. */
+#define bfd_mach_sparc_v9_p(mach) ((mach) != bfd_mach_sparc)
+ bfd_arch_mips, /* MIPS Rxxxx */
+ bfd_arch_i386, /* Intel 386 */
+ bfd_arch_we32k, /* AT&T WE32xxx */
+ bfd_arch_tahoe, /* CCI/Harris Tahoe */
+ bfd_arch_i860, /* Intel 860 */
+ bfd_arch_romp, /* IBM ROMP PC/RT */
+ bfd_arch_alliant, /* Alliant */
+ bfd_arch_convex, /* Convex */
+ bfd_arch_m88k, /* Motorola 88xxx */
+ bfd_arch_pyramid, /* Pyramid Technology */
+ 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 */
+#define bfd_mach_z8001 1
+#define bfd_mach_z8002 2
+ bfd_arch_h8500, /* Hitachi H8/500 */
+ bfd_arch_sh, /* Hitachi SH */
+ bfd_arch_alpha, /* Dec Alpha */
+ bfd_arch_arm, /* Advanced Risc Machines ARM */
+ bfd_arch_ns32k, /* National Semiconductors ns32000 */
+ bfd_arch_w65, /* WDC 65816 */
+ bfd_arch_last
+ };
+
+typedef struct bfd_arch_info
+{
+ int bits_per_word;
+ int bits_per_address;
+ int bits_per_byte;
+ enum bfd_architecture arch;
+ unsigned long mach;
+ const char *arch_name;
+ const char *printable_name;
+ unsigned int section_align_power;
+ /* true if this is the default machine for the architecture */
+ boolean the_default;
+ const struct bfd_arch_info * (*compatible)
+ PARAMS ((const struct bfd_arch_info *a,
+ const struct bfd_arch_info *b));
+
+ boolean (*scan) PARAMS ((const struct bfd_arch_info *, const char *));
+
+ const struct bfd_arch_info *next;
+} bfd_arch_info_type;
+const char *
+bfd_printable_name PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_scan_arch PARAMS ((const char *string));
+
+const bfd_arch_info_type *
+bfd_arch_get_compatible PARAMS ((
+ const bfd *abfd,
+ const bfd *bbfd));
+
+void
+bfd_set_arch_info PARAMS ((bfd *abfd, const bfd_arch_info_type *arg));
+
+enum bfd_architecture
+bfd_get_arch PARAMS ((bfd *abfd));
+
+unsigned long
+bfd_get_mach PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_byte PARAMS ((bfd *abfd));
+
+unsigned int
+bfd_arch_bits_per_address PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_get_arch_info PARAMS ((bfd *abfd));
+
+const bfd_arch_info_type *
+bfd_lookup_arch
+ PARAMS ((enum bfd_architecture
+ arch,
+ unsigned long machine));
+
+const char *
+bfd_printable_arch_mach
+ PARAMS ((enum bfd_architecture arch, unsigned long machine));
+
+typedef enum bfd_reloc_status
+{
+ /* No errors detected */
+ bfd_reloc_ok,
+
+ /* The relocation was performed, but there was an overflow. */
+ bfd_reloc_overflow,
+
+ /* The address to relocate was not within the section supplied. */
+ bfd_reloc_outofrange,
+
+ /* Used by special functions */
+ bfd_reloc_continue,
+
+ /* Unsupported relocation size requested. */
+ bfd_reloc_notsupported,
+
+ /* Unused */
+ bfd_reloc_other,
+
+ /* The symbol to relocate against was undefined. */
+ bfd_reloc_undefined,
+
+ /* The relocation was performed, but may not be ok - presently
+ generated only when linking i960 coff files with i960 b.out
+ 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
+{
+ /* A pointer into the canonical table of pointers */
+ struct symbol_cache_entry **sym_ptr_ptr;
+
+ /* offset in section */
+ bfd_size_type address;
+
+ /* addend for relocation value */
+ bfd_vma addend;
+
+ /* Pointer to how to perform the required relocation */
+ reloc_howto_type *howto;
+
+} arelent;
+enum complain_overflow
+{
+ /* Do not complain on overflow. */
+ complain_overflow_dont,
+
+ /* Complain if the bitfield overflows, whether it is considered
+ as signed or unsigned. */
+ complain_overflow_bitfield,
+
+ /* Complain if the value overflows when considered as signed
+ number. */
+ complain_overflow_signed,
+
+ /* Complain if the value overflows when considered as an
+ unsigned number. */
+ complain_overflow_unsigned
+};
+
+struct reloc_howto_struct
+{
+ /* The type field has mainly a documetary use - the back end can
+ 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;
+
+ /* The value the final relocation is shifted right by. This drops
+ unwanted data from the relocation. */
+ unsigned int rightshift;
+
+ /* The size of the item to be relocated. This is *not* a
+ 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
+ when doing overflow checking. */
+ unsigned int bitsize;
+
+ /* Notes that the relocation is relative to the location in the
+ data section of the addend. The relocation function will
+ subtract from the relocation value the address of the location
+ being relocated. */
+ boolean pc_relative;
+
+ /* The bit position of the reloc value in the destination.
+ The relocated value is left shifted by this amount. */
+ unsigned int bitpos;
+
+ /* What type of overflow error should be checked for when
+ relocating. */
+ enum complain_overflow complain_on_overflow;
+
+ /* If this field is non null, then the supplied function is
+ 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)
+ PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ struct symbol_cache_entry *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+ /* The textual name of the relocation type. */
+ char *name;
+
+ /* When performing a partial link, some formats must modify the
+ relocations rather than the data - this flag signals this.*/
+ boolean partial_inplace;
+
+ /* 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
+ sun4 extended relocs, the value in the offset part of a
+ relocating field is garbage so we never use it. In this case
+ the mask would be 0x00000000. */
+ bfd_vma src_mask;
+
+ /* 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;
+
+ /* 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.*/
+ boolean pcrel_offset;
+
+};
+#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)
+
+#define HOWTO_PREPARE(relocation, symbol) \
+ { \
+ if (symbol != (asymbol *)NULL) { \
+ if (bfd_is_com_section (symbol->section)) { \
+ relocation = 0; \
+ } \
+ else { \
+ relocation = symbol->value; \
+ } \
+ } \
+}
+int
+bfd_get_reloc_size PARAMS ((reloc_howto_type *));
+
+typedef struct relent_chain {
+ arelent relent;
+ struct relent_chain *next;
+} arelent_chain;
+bfd_reloc_status_type
+
+bfd_perform_relocation
+ PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+
+bfd_reloc_status_type
+
+bfd_install_relocation
+ PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message));
+
+enum bfd_reloc_code_real {
+ _dummy_first_bfd_reloc_code_real,
+
+
+/* Basic absolute relocations of N bits. */
+ BFD_RELOC_64,
+ BFD_RELOC_32,
+ BFD_RELOC_26,
+ BFD_RELOC_16,
+ BFD_RELOC_14,
+ BFD_RELOC_8,
+
+/* PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations. */
+ BFD_RELOC_64_PCREL,
+ BFD_RELOC_32_PCREL,
+ BFD_RELOC_24_PCREL,
+ BFD_RELOC_16_PCREL,
+ BFD_RELOC_12_PCREL,
+ BFD_RELOC_8_PCREL,
+
+/* For ELF. */
+ BFD_RELOC_32_GOT_PCREL,
+ BFD_RELOC_16_GOT_PCREL,
+ BFD_RELOC_8_GOT_PCREL,
+ BFD_RELOC_32_GOTOFF,
+ BFD_RELOC_16_GOTOFF,
+ BFD_RELOC_LO16_GOTOFF,
+ BFD_RELOC_HI16_GOTOFF,
+ BFD_RELOC_HI16_S_GOTOFF,
+ BFD_RELOC_8_GOTOFF,
+ BFD_RELOC_32_PLT_PCREL,
+ BFD_RELOC_24_PLT_PCREL,
+ BFD_RELOC_16_PLT_PCREL,
+ BFD_RELOC_8_PLT_PCREL,
+ BFD_RELOC_32_PLTOFF,
+ BFD_RELOC_16_PLTOFF,
+ BFD_RELOC_LO16_PLTOFF,
+ BFD_RELOC_HI16_PLTOFF,
+ BFD_RELOC_HI16_S_PLTOFF,
+ BFD_RELOC_8_PLTOFF,
+
+/* Relocations used by 68K ELF. */
+ BFD_RELOC_68K_GLOB_DAT,
+ BFD_RELOC_68K_JMP_SLOT,
+ BFD_RELOC_68K_RELATIVE,
+
+/* Linkage-table relative. */
+ BFD_RELOC_32_BASEREL,
+ BFD_RELOC_16_BASEREL,
+ BFD_RELOC_LO16_BASEREL,
+ BFD_RELOC_HI16_BASEREL,
+ BFD_RELOC_HI16_S_BASEREL,
+ BFD_RELOC_8_BASEREL,
+ BFD_RELOC_RVA,
+
+/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */
+ BFD_RELOC_8_FFnn,
+
+/* These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha. */
+ BFD_RELOC_32_PCREL_S2,
+ BFD_RELOC_16_PCREL_S2,
+ BFD_RELOC_23_PCREL_S2,
+
+/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC. */
+ BFD_RELOC_HI22,
+ 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,
+
+/* SPARC ELF relocations. There is probably some overlap with other
+relocation types already defined. */
+ BFD_RELOC_NONE,
+ BFD_RELOC_SPARC_WDISP22,
+ BFD_RELOC_SPARC22,
+ BFD_RELOC_SPARC13,
+ BFD_RELOC_SPARC_GOT10,
+ BFD_RELOC_SPARC_GOT13,
+ BFD_RELOC_SPARC_GOT22,
+ BFD_RELOC_SPARC_PC10,
+ BFD_RELOC_SPARC_PC22,
+ BFD_RELOC_SPARC_WPLT30,
+ BFD_RELOC_SPARC_COPY,
+ BFD_RELOC_SPARC_GLOB_DAT,
+ BFD_RELOC_SPARC_JMP_SLOT,
+ BFD_RELOC_SPARC_RELATIVE,
+ BFD_RELOC_SPARC_UA32,
+
+/* I think these are specific to SPARC a.out (e.g., Sun 4). */
+ BFD_RELOC_SPARC_BASE13,
+ BFD_RELOC_SPARC_BASE22,
+
+/* Some relocations we're using for SPARC V9 -- subject to change. */
+#define BFD_RELOC_SPARC_64 BFD_RELOC_64
+ BFD_RELOC_SPARC_10,
+ BFD_RELOC_SPARC_11,
+ 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_7,
+ BFD_RELOC_SPARC_6,
+ BFD_RELOC_SPARC_5,
+
+/* 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,
+
+/* 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
+extended and added to form the final result. If the low 16
+bits form a negative number, we need to add one to the high value
+to compensate for the borrow when the low bits are added. */
+ 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,
+
+/* Relocation relative to the global pointer. */
+#define BFD_RELOC_MIPS_GPREL BFD_RELOC_GPREL16
+
+/* Relocation against a MIPS literal section. */
+ BFD_RELOC_MIPS_LITERAL,
+
+/* MIPS ELF relocations. */
+ BFD_RELOC_MIPS_GOT16,
+ BFD_RELOC_MIPS_CALL16,
+#define BFD_RELOC_MIPS_GPREL32 BFD_RELOC_GPREL32
+ BFD_RELOC_MIPS_GOT_HI16,
+ BFD_RELOC_MIPS_GOT_LO16,
+ BFD_RELOC_MIPS_CALL_HI16,
+ BFD_RELOC_MIPS_CALL_LO16,
+
+/* i386/elf relocations */
+ BFD_RELOC_386_GOT32,
+ BFD_RELOC_386_PLT32,
+ BFD_RELOC_386_COPY,
+ BFD_RELOC_386_GLOB_DAT,
+ BFD_RELOC_386_JUMP_SLOT,
+ BFD_RELOC_386_RELATIVE,
+ 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,
+
+/* Power(rs6000) and PowerPC relocations. */
+ BFD_RELOC_PPC_B26,
+ BFD_RELOC_PPC_BA26,
+ BFD_RELOC_PPC_TOC16,
+ BFD_RELOC_PPC_B16,
+ BFD_RELOC_PPC_B16_BRTAKEN,
+ BFD_RELOC_PPC_B16_BRNTAKEN,
+ BFD_RELOC_PPC_BA16,
+ BFD_RELOC_PPC_BA16_BRTAKEN,
+ BFD_RELOC_PPC_BA16_BRNTAKEN,
+ BFD_RELOC_PPC_COPY,
+ BFD_RELOC_PPC_GLOB_DAT,
+ BFD_RELOC_PPC_JMP_SLOT,
+ BFD_RELOC_PPC_RELATIVE,
+ BFD_RELOC_PPC_LOCAL24PC,
+ BFD_RELOC_PPC_EMB_NADDR32,
+ BFD_RELOC_PPC_EMB_NADDR16,
+ BFD_RELOC_PPC_EMB_NADDR16_LO,
+ BFD_RELOC_PPC_EMB_NADDR16_HI,
+ BFD_RELOC_PPC_EMB_NADDR16_HA,
+ BFD_RELOC_PPC_EMB_SDAI16,
+ BFD_RELOC_PPC_EMB_SDA2I16,
+ BFD_RELOC_PPC_EMB_SDA2REL,
+ BFD_RELOC_PPC_EMB_SDA21,
+ BFD_RELOC_PPC_EMB_MRKREF,
+ BFD_RELOC_PPC_EMB_RELSEC16,
+ BFD_RELOC_PPC_EMB_RELST_LO,
+ BFD_RELOC_PPC_EMB_RELST_HI,
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
+
+/* The type of reloc used to build a contructor table - at the moment
+probably a 32 bit wide absolute relocation, but the target can choose.
+It generally does map to one of the other relocation types. */
+ BFD_RELOC_CTOR,
+
+/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+not stored in the instruction. */
+ BFD_RELOC_ARM_PCREL_BRANCH,
+
+/* These relocs are only used within the ARM assembler. They are not
+(at present) written to any object files. */
+ BFD_RELOC_ARM_IMMEDIATE,
+ BFD_RELOC_ARM_OFFSET_IMM,
+ BFD_RELOC_ARM_SHIFT_IMM,
+ BFD_RELOC_ARM_SWI,
+ BFD_RELOC_ARM_MULTI,
+ BFD_RELOC_ARM_CP_OFF_IMM,
+ BFD_RELOC_ARM_ADR_IMM,
+ BFD_RELOC_ARM_LDR_IMM,
+ BFD_RELOC_ARM_LITERAL,
+ BFD_RELOC_ARM_IN_POOL,
+ BFD_RELOC_UNUSED };
+typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+reloc_howto_type *
+
+bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+const char *
+bfd_get_reloc_code_name PARAMS ((bfd_reloc_code_real_type code));
+
+
+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
+ information (invisible to the application writer) is carried
+ with the symbol.
+
+ This field is *almost* redundant, since you can use section->owner
+ instead, except that some symbols point to the global sections
+ bfd_{abs,com,und}_section. This could be fixed by making
+ these globals be per-bfd (or per-target-flavor). FIXME. */
+
+ 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
+ application may not alter it. */
+ CONST char *name;
+
+ /* The value of the symbol. This really should be a union of a
+ numeric value with a pointer, since some flags indicate that
+ a pointer to another symbol is stored here. */
+ symvalue value;
+
+ /* Attributes of a symbol: */
+
+#define BSF_NO_FLAGS 0x00
+
+ /* The symbol has local scope; <<static>> in <<C>>. The value
+ is the offset into the section of the data. */
+#define BSF_LOCAL 0x01
+
+ /* The symbol has global scope; initialized data in <<C>>. The
+ 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 offset into the section of the data. */
+#define BSF_EXPORT BSF_GLOBAL /* no real difference */
+
+ /* A normal C symbol would be one of:
+ <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+ <<BSF_GLOBAL>> */
+
+ /* The symbol is a debugging record. The value has an arbitary
+ meaning. */
+#define BSF_DEBUGGING 0x08
+
+ /* The symbol denotes a function entry point. Used in ELF,
+ perhaps others someday. */
+#define BSF_FUNCTION 0x10
+
+ /* Used by the linker. */
+#define BSF_KEEP 0x20
+#define BSF_KEEP_G 0x40
+
+ /* A weak global symbol, overridable without warnings by
+ a regular global symbol of the same name. */
+#define BSF_WEAK 0x80
+
+ /* This symbol was created to point to a section, e.g. ELF's
+ STT_SECTION symbols. */
+#define BSF_SECTION_SYM 0x100
+
+ /* The symbol used to be a common symbol, but now it is
+ allocated. */
+#define BSF_OLD_COMMON 0x200
+
+ /* The default value for common data. */
+#define BFD_FORT_COMM_DEFAULT_VALUE 0
+
+ /* In some files the type of a symbol sometimes alters its
+ location in an output file - ie in coff a <<ISFCN>> symbol
+ which is also <<C_EXT>> symbol appears where it was
+ declared and not at the end of a section. This bit is set
+ by the target BFD part to convey this information. */
+
+#define BSF_NOT_AT_END 0x400
+
+ /* Signal that the symbol is the label of constructor section. */
+#define BSF_CONSTRUCTOR 0x800
+
+ /* Signal that the symbol is a warning symbol. The name is a
+ warning. The name of the next symbol is the one to warn about;
+ if a reference is made to a symbol with the same name as the next
+ symbol, a warning is issued by the linker. */
+#define BSF_WARNING 0x1000
+
+ /* Signal that the symbol is indirect. This symbol is an indirect
+ pointer to the symbol with the same name as the next symbol. */
+#define BSF_INDIRECT 0x2000
+
+ /* BSF_FILE marks symbols that contain a file name. This is used
+ for ELF STT_FILE symbols. */
+#define BSF_FILE 0x4000
+
+ /* Symbol is from dynamic linking information. */
+#define BSF_DYNAMIC 0x8000
+
+ /* The symbol denotes a data object. Used in ELF, and perhaps
+ others someday. */
+#define BSF_OBJECT 0x10000
+
+ flagword flags;
+
+ /* 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;
+
+ /* Back end special data. */
+ union
+ {
+ PTR p;
+ bfd_vma i;
+ } udata;
+
+} asymbol;
+#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 *abfd, asymbol **location, unsigned int count));
+
+void
+bfd_print_symbol_vandf PARAMS ((PTR file, asymbol *symbol));
+
+#define bfd_make_empty_symbol(abfd) \
+ BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+#define bfd_make_debug_symbol(abfd,ptr,size) \
+ BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+int
+bfd_decode_symclass PARAMS ((asymbol *symbol));
+
+void
+bfd_symbol_info PARAMS ((asymbol *symbol, symbol_info *ret));
+
+boolean
+bfd_copy_private_symbol_data PARAMS ((bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym));
+
+#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+ BFD_SEND (ibfd, _bfd_copy_private_symbol_data, \
+ (ibfd, isymbol, obfd, osymbol))
+struct _bfd
+{
+ /* The filename the application opened the BFD with. */
+ CONST char *filename;
+
+ /* A pointer to the target jump table. */
+ const struct bfd_target *xvec;
+
+ /* To avoid dragging too many header files into every file that
+ includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+ *", and MTIME as a "long". Their correct types, to which they
+ are cast when used, are "FILE *" and "time_t". The iostream
+ is the result of an fopen on the filename. However, if the
+ BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+ to a bfd_in_memory struct. */
+ PTR iostream;
+
+ /* 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 which matching algorithm
+ to use to choose the back end. */
+
+ boolean target_defaulted;
+
+ /* The caching routines use these to maintain a
+ least-recently-used list of BFDs */
+
+ struct _bfd *lru_prev, *lru_next;
+
+ /* When a file is closed by the caching routines, BFD retains
+ state information on the file here: */
+
+ file_ptr where;
+
+ /* and here: (``once'' means at least once) */
+
+ boolean opened_once;
+
+ /* Set if we have a locally maintained mtime value, rather than
+ getting it from the file each time: */
+
+ boolean mtime_set;
+
+ /* File modified time, if mtime_set is true: */
+
+ long mtime;
+
+ /* Reserved for an unimplemented file locking extension.*/
+
+ int ifd;
+
+ /* The format which belongs to the BFD. (object, core, etc.) */
+
+ bfd_format format;
+
+ /* The direction the BFD was opened with*/
+
+ enum bfd_direction {no_direction = 0,
+ read_direction = 1,
+ write_direction = 2,
+ both_direction = 3} direction;
+
+ /* Format_specific flags*/
+
+ flagword flags;
+
+ /* Currently my_archive is tested before adding origin to
+ anything. I believe that this can become always an add of
+ origin, with origin set to 0 for non archive files. */
+
+ file_ptr origin;
+
+ /* Remember when output has begun, to stop strange things
+ from happening. */
+ boolean output_has_begun;
+
+ /* Pointer to linked list of sections*/
+ struct sec *sections;
+
+ /* The number of sections */
+ unsigned int section_count;
+
+ /* Stuff only useful for object files:
+ The start address. */
+ bfd_vma start_address;
+
+ /* Used for input and output*/
+ unsigned int symcount;
+
+ /* Symbol table for output BFD (with symcount entries) */
+ struct symbol_cache_entry **outsymbols;
+
+ /* Pointer to structure which contains architecture information*/
+ const struct bfd_arch_info *arch_info;
+
+ /* Stuff only useful for archives:*/
+ PTR arelt_data;
+ 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
+ {
+ struct aout_data_struct *aout_data;
+ struct artdata *aout_ar_data;
+ struct _oasys_data *oasys_obj_data;
+ struct _oasys_ar_data *oasys_ar_data;
+ struct coff_tdata *coff_obj_data;
+ struct pe_tdata *pe_obj_data;
+ struct xcoff_tdata *xcoff_obj_data;
+ struct ecoff_tdata *ecoff_obj_data;
+ struct ieee_data_struct *ieee_data;
+ struct ieee_ar_data_struct *ieee_ar_data;
+ struct srec_data_struct *srec_data;
+ struct ihex_data_struct *ihex_data;
+ struct tekhex_data_struct *tekhex_data;
+ struct elf_obj_tdata *elf_obj_data;
+ struct nlm_obj_tdata *nlm_obj_data;
+ struct bout_data_struct *bout_data;
+ struct sun_core_struct *sun_core_data;
+ struct trad_core_struct *trad_core_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;
+ struct versados_data_struct *versados_data;
+ struct netbsd_core_struct *netbsd_core_data;
+ PTR any;
+ } tdata;
+
+ /* Used by the application to hold private data*/
+ PTR usrdata;
+
+ /* Where all the allocated stuff under this BFD goes */
+ struct obstack memory;
+};
+
+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_armap,
+ 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_file_too_big,
+ 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));
+
+typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+
+bfd_error_handler_type
+bfd_set_error_handler PARAMS ((bfd_error_handler_type));
+
+void
+bfd_set_error_program_name PARAMS ((const char *));
+
+long
+bfd_get_reloc_upper_bound PARAMS ((bfd *abfd, asection *sect));
+
+long
+bfd_canonicalize_reloc
+ PARAMS ((bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms));
+
+void
+bfd_set_reloc
+ PARAMS ((bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+
+ );
+
+boolean
+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 *abfd));
+
+long
+bfd_get_size PARAMS ((bfd *abfd));
+
+int
+bfd_get_gp_size PARAMS ((bfd *abfd));
+
+void
+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))
+boolean
+bfd_merge_private_bfd_data PARAMS ((bfd *ibfd, bfd *obfd));
+
+#define bfd_merge_private_bfd_data(ibfd, obfd) \
+ BFD_SEND (ibfd, _bfd_merge_private_bfd_data, \
+ (ibfd, obfd))
+boolean
+bfd_set_private_flags PARAMS ((bfd *abfd, flagword flags));
+
+#define bfd_set_private_flags(abfd, flags) \
+ BFD_SEND (abfd, _bfd_set_private_flags, \
+ (abfd, flags))
+#define bfd_sizeof_headers(abfd, reloc) \
+ BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+
+#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+ BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+
+ /* Do these three do anything useful at all, for any back end? */
+#define bfd_debug_info_start(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+
+#define bfd_debug_info_end(abfd) \
+ BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+
+#define bfd_debug_info_accumulate(abfd, section) \
+ BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+
+
+#define bfd_stat_arch_elt(abfd, stat) \
+ BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+
+#define bfd_update_armap_timestamp(abfd) \
+ BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+
+#define bfd_set_arch_mach(abfd, arch, mach)\
+ BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+
+#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_print_private_bfd_data(abfd, file)\
+ BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+
+#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))
+
+extern bfd_byte *bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *,
+ boolean, asymbol **));
+
+symindex
+bfd_get_next_mapent PARAMS ((bfd *abfd, symindex previous, carsym **sym));
+
+boolean
+bfd_set_archive_head PARAMS ((bfd *output, bfd *new_head));
+
+bfd *
+bfd_openr_next_archived_file PARAMS ((bfd *archive, bfd *previous));
+
+CONST char *
+bfd_core_file_failing_command PARAMS ((bfd *abfd));
+
+int
+bfd_core_file_failing_signal PARAMS ((bfd *abfd));
+
+boolean
+core_file_matches_executable_p
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+#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_ihex_flavour,
+ bfd_target_som_flavour,
+ bfd_target_os9k_flavour,
+ bfd_target_versados_flavour,
+ bfd_target_msdos_flavour
+};
+
+enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+
+ /* Forward declaration. */
+typedef struct bfd_link_info _bfd_link_info;
+
+typedef struct bfd_target
+{
+ char *name;
+ enum bfd_flavour flavour;
+ enum bfd_endian byteorder;
+ enum bfd_endian header_byteorder;
+ flagword object_flags;
+ flagword section_flags;
+ char symbol_leading_char;
+ char ar_pad_char;
+ unsigned short ar_max_namelen;
+ 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 ((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 ((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 ((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 ((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 ((const bfd_byte *));
+ bfd_signed_vma (*bfd_h_getx_signed_16) PARAMS ((const bfd_byte *));
+ void (*bfd_h_putx16) PARAMS ((bfd_vma, bfd_byte *));
+ 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),\
+CAT(NAME,_get_section_contents_in_window)
+
+ /* 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));
+ boolean (*_bfd_get_section_contents_in_window)
+ PARAMS ((bfd *, sec_ptr, bfd_window *,
+ 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_merge_private_bfd_data),\
+CAT(NAME,_bfd_copy_private_section_data),\
+CAT(NAME,_bfd_copy_private_symbol_data),\
+CAT(NAME,_bfd_set_private_flags),\
+CAT(NAME,_bfd_print_private_bfd_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 merge BFD general private data from one object file
+ to a common output file when linking. */
+ boolean (*_bfd_merge_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));
+ /* Called to copy BFD private symbol data from one symbol
+ to another. */
+ boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+ /* Called to set private backend flags */
+ boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+
+ /* Called to print private BFD data */
+ boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, 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,_construct_extended_name_table),\
+CAT(NAME,_truncate_arname),\
+CAT(NAME,_write_armap),\
+CAT(NAME,_read_ar_hdr),\
+CAT(NAME,_openr_next_archived_file),\
+CAT(NAME,_get_elt_at_index),\
+CAT(NAME,_generic_stat_arch_elt),\
+CAT(NAME,_update_armap_timestamp)
+ boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+ boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+ boolean (*_bfd_construct_extended_name_table)
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+ void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *));
+ boolean (*write_armap) PARAMS ((bfd *arch,
+ unsigned int elength,
+ struct orl *map,
+ unsigned int orl_count,
+ int stridx));
+ PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+ bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
+#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+ bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+ int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+ boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+
+ /* 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),\
+CAT(NAME,_read_minisymbols),\
+CAT(NAME,_minisymbol_to_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,
+ struct symbol_cache_entry *,
+ bfd_print_symbol_type));
+#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+ void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+ 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_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));
+ /* 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. */
+ asymbol * (*_bfd_make_debug_symbol) PARAMS ((
+ bfd *abfd,
+ void *ptr,
+ unsigned long size));
+#define bfd_read_minisymbols(b, d, m, s) \
+ BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+ long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+ unsigned int *));
+#define bfd_minisymbol_to_symbol(b, d, m, f) \
+ BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+ asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+ /* 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. */
+ reloc_howto_type *
+ (*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),\
+CAT(NAME,_bfd_link_split_section)
+ 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 *));
+
+ /* Should this section be split up into smaller pieces during linking. */
+ boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+
+ /* 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;
+const bfd_target *
+bfd_find_target PARAMS ((CONST char *target_name, bfd *abfd));
+
+const char **
+bfd_target_list PARAMS ((void));
+
+boolean
+bfd_check_format PARAMS ((bfd *abfd, bfd_format format));
+
+boolean
+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 format));
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/contrib/gdb/bfd/bfd.c b/contrib/gdb/bfd/bfd.c
new file mode 100644
index 0000000..10ec67e
--- /dev/null
+++ b/contrib/gdb/bfd/bfd.c
@@ -0,0 +1,1144 @@
+/* Generic BFD library interface and support routines.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ <<typedef bfd>>
+
+ A BFD has type <<bfd>>; 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 structure that defines the type <<bfd>>. It
+ contains the major data about the file and pointers
+ to the rest of the data.
+
+CODE_FRAGMENT
+.
+.struct _bfd
+.{
+. {* The filename the application opened the BFD with. *}
+. CONST char *filename;
+.
+. {* A pointer to the target jump table. *}
+. const struct bfd_target *xvec;
+.
+. {* To avoid dragging too many header files into every file that
+. includes `<<bfd.h>>', IOSTREAM has been declared as a "char
+. *", and MTIME as a "long". Their correct types, to which they
+. are cast when used, are "FILE *" and "time_t". The iostream
+. is the result of an fopen on the filename. However, if the
+. BFD_IN_MEMORY flag is set, then iostream is actually a pointer
+. to a bfd_in_memory struct. *}
+. PTR iostream;
+.
+. {* 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 which matching algorithm
+. to use to choose the back end. *}
+.
+. boolean target_defaulted;
+.
+. {* The caching routines use these to maintain a
+. least-recently-used list of BFDs *}
+.
+. struct _bfd *lru_prev, *lru_next;
+.
+. {* When a file is closed by the caching routines, BFD retains
+. state information on the file here: *}
+.
+. file_ptr where;
+.
+. {* and here: (``once'' means at least once) *}
+.
+. boolean opened_once;
+.
+. {* Set if we have a locally maintained mtime value, rather than
+. getting it from the file each time: *}
+.
+. boolean mtime_set;
+.
+. {* File modified time, if mtime_set is true: *}
+.
+. long mtime;
+.
+. {* Reserved for an unimplemented file locking extension.*}
+.
+. int ifd;
+.
+. {* The format which belongs to the BFD. (object, core, etc.) *}
+.
+. bfd_format format;
+.
+. {* The direction the BFD was opened with*}
+.
+. enum bfd_direction {no_direction = 0,
+. read_direction = 1,
+. write_direction = 2,
+. both_direction = 3} direction;
+.
+. {* Format_specific flags*}
+.
+. flagword flags;
+.
+. {* Currently my_archive is tested before adding origin to
+. anything. I believe that this can become always an add of
+. origin, with origin set to 0 for non archive files. *}
+.
+. file_ptr origin;
+.
+. {* Remember when output has begun, to stop strange things
+. from happening. *}
+. boolean output_has_begun;
+.
+. {* Pointer to linked list of sections*}
+. struct sec *sections;
+.
+. {* The number of sections *}
+. unsigned int section_count;
+.
+. {* Stuff only useful for object files:
+. The start address. *}
+. bfd_vma start_address;
+.
+. {* Used for input and output*}
+. unsigned int symcount;
+.
+. {* Symbol table for output BFD (with symcount entries) *}
+. struct symbol_cache_entry **outsymbols;
+.
+. {* Pointer to structure which contains architecture information*}
+. const struct bfd_arch_info *arch_info;
+.
+. {* Stuff only useful for archives:*}
+. PTR arelt_data;
+. 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
+. {
+. struct aout_data_struct *aout_data;
+. struct artdata *aout_ar_data;
+. struct _oasys_data *oasys_obj_data;
+. struct _oasys_ar_data *oasys_ar_data;
+. struct coff_tdata *coff_obj_data;
+. struct pe_tdata *pe_obj_data;
+. struct xcoff_tdata *xcoff_obj_data;
+. struct ecoff_tdata *ecoff_obj_data;
+. struct ieee_data_struct *ieee_data;
+. struct ieee_ar_data_struct *ieee_ar_data;
+. struct srec_data_struct *srec_data;
+. struct ihex_data_struct *ihex_data;
+. struct tekhex_data_struct *tekhex_data;
+. struct elf_obj_tdata *elf_obj_data;
+. struct nlm_obj_tdata *nlm_obj_data;
+. struct bout_data_struct *bout_data;
+. struct sun_core_struct *sun_core_data;
+. struct trad_core_struct *trad_core_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;
+. struct versados_data_struct *versados_data;
+. struct netbsd_core_struct *netbsd_core_data;
+. PTR any;
+. } tdata;
+.
+. {* Used by the application to hold private data*}
+. PTR usrdata;
+.
+. {* Where all the allocated stuff under this BFD goes *}
+. struct obstack memory;
+.};
+.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "libcoff.h"
+#include "libecoff.h"
+#undef obj_symbols
+#include "elf-bfd.h"
+
+#include <ctype.h>
+
+/* provide storage for subsystem, stack and heap data which may have been
+ passed in on the command line. Ld puts this data into a bfd_link_info
+ struct which ultimately gets passed in to the bfd. When it arrives, copy
+ it to the following struct so that the data will be available in coffcode.h
+ where it is needed. The typedef's used are defined in bfd.h */
+
+
+
+/*
+SECTION
+ Error reporting
+
+ Most BFD functions return nonzero on success (check their
+ individual documentation for precise semantics). On an error,
+ they call <<bfd_set_error>> to set an error condition that callers
+ can check by calling <<bfd_get_error>>.
+ If that returns <<bfd_error_system_call>>, then check
+ <<errno>>.
+
+ The easiest way to report a BFD error to the user is to
+ use <<bfd_perror>>.
+
+SUBSECTION
+ Type <<bfd_error_type>>
+
+ The values returned by <<bfd_get_error>> are defined by the
+ enumerated type <<bfd_error_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_armap,
+. 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_file_too_big,
+. bfd_error_invalid_error_code
+.} bfd_error_type;
+.
+*/
+
+#undef strerror
+extern char *strerror();
+
+static bfd_error_type bfd_error = bfd_error_no_error;
+
+CONST char *CONST bfd_errmsgs[] = {
+ "No error",
+ "System call error",
+ "Invalid bfd target",
+ "File in wrong format",
+ "Invalid operation",
+ "Memory exhausted",
+ "No symbols",
+ "Archive has no index; run ranlib to add one",
+ "No more archived files",
+ "Malformed archive",
+ "File format not recognized",
+ "File format is ambiguous",
+ "Section has no contents",
+ "Nonrepresentable section on output",
+ "Symbol needs debug section which does not exist",
+ "Bad value",
+ "File truncated",
+ "File too big",
+ "#<Invalid error code>"
+ };
+
+/*
+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 ()
+{
+ return bfd_error;
+}
+
+/*
+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;
+{
+ bfd_error = error_tag;
+}
+
+/*
+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 <<bfd_error_system_call>>.
+*/
+
+CONST char *
+bfd_errmsg (error_tag)
+ bfd_error_type error_tag;
+{
+#ifndef errno
+ extern int errno;
+#endif
+ if (error_tag == bfd_error_system_call)
+ {
+ const char *errmsg;
+
+ errmsg = strerror (errno);
+ if (errmsg == NULL)
+ {
+ static char buf[32];
+
+ sprintf (buf, "Error %d", errno);
+ errmsg = buf;
+ }
+ return errmsg;
+ }
+
+ 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];
+}
+
+/*
+FUNCTION
+ bfd_perror
+
+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
+bfd_perror (message)
+ CONST char *message;
+{
+ 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_get_error ()));
+ else
+ fprintf (stderr, "%s: %s\n", message, bfd_errmsg (bfd_get_error ()));
+ }
+}
+
+/*
+SUBSECTION
+ BFD error handler
+
+ Some BFD functions want to print messages describing the
+ problem. They call a BFD error handler function. This
+ function may be overriden by the program.
+
+ The BFD error handler acts like printf.
+
+CODE_FRAGMENT
+.
+.typedef void (*bfd_error_handler_type) PARAMS ((const char *, ...));
+.
+*/
+
+/* The program name used when printing BFD error messages. */
+
+static const char *_bfd_error_program_name;
+
+/* This is the default routine to handle BFD error messages. */
+
+#ifdef ANSI_PROTOTYPES
+
+static void _bfd_default_error_handler PARAMS ((const char *s, ...));
+
+static void
+_bfd_default_error_handler (const char *s, ...)
+{
+ va_list p;
+
+ if (_bfd_error_program_name != NULL)
+ fprintf (stderr, "%s: ", _bfd_error_program_name);
+
+ va_start (p, s);
+
+ vfprintf (stderr, s, p);
+
+ va_end (p);
+
+ fprintf (stderr, "\n");
+}
+
+#else /* ! defined (ANSI_PROTOTYPES) */
+
+static void _bfd_default_error_handler ();
+
+static void
+_bfd_default_error_handler (va_alist)
+ va_dcl
+{
+ va_list p;
+ const char *s;
+
+ if (_bfd_error_program_name != NULL)
+ fprintf (stderr, "%s: ", _bfd_error_program_name);
+
+ va_start (p);
+
+ s = va_arg (p, const char *);
+ vfprintf (stderr, s, p);
+
+ va_end (p);
+
+ fprintf (stderr, "\n");
+}
+
+#endif /* ! defined (ANSI_PROTOTYPES) */
+
+/* This is a function pointer to the routine which should handle BFD
+ error messages. It is called when a BFD routine encounters an
+ error for which it wants to print a message. Going through a
+ function pointer permits a program linked against BFD to intercept
+ the messages and deal with them itself. */
+
+bfd_error_handler_type _bfd_error_handler = _bfd_default_error_handler;
+
+/*
+FUNCTION
+ bfd_set_error_handler
+
+SYNOPSIS
+ bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type);
+
+DESCRIPTION
+ Set the BFD error handler function. Returns the previous
+ function.
+*/
+
+bfd_error_handler_type
+bfd_set_error_handler (pnew)
+ bfd_error_handler_type pnew;
+{
+ bfd_error_handler_type pold;
+
+ pold = _bfd_error_handler;
+ _bfd_error_handler = pnew;
+ return pold;
+}
+
+/*
+FUNCTION
+ bfd_set_error_program_name
+
+SYNOPSIS
+ void bfd_set_error_program_name (const char *);
+
+DESCRIPTION
+ Set the program name to use when printing a BFD error. This
+ is printed before the error message followed by a colon and
+ space. The string must not be changed after it is passed to
+ this function.
+*/
+
+void
+bfd_set_error_program_name (name)
+ const char *name;
+{
+ _bfd_error_program_name = name;
+}
+
+/*
+SECTION
+ Symbols
+*/
+
+/*
+FUNCTION
+ bfd_get_reloc_upper_bound
+
+SYNOPSIS
+ long bfd_get_reloc_upper_bound(bfd *abfd, asection *sect);
+
+DESCRIPTION
+ 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.
+
+*/
+
+
+long
+bfd_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ if (abfd->format != bfd_object) {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+
+ return BFD_SEND (abfd, _get_reloc_upper_bound, (abfd, asect));
+}
+
+/*
+FUNCTION
+ bfd_canonicalize_reloc
+
+SYNOPSIS
+ long bfd_canonicalize_reloc
+ (bfd *abfd,
+ asection *sec,
+ arelent **loc,
+ asymbol **syms);
+
+DESCRIPTION
+ 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
+ <<bfd_get_reloc_upper_bound>>. Returns the number of relocs, or
+ -1 on error.
+
+ The @var{syms} table is also needed for horrible internal magic
+ reasons.
+
+
+*/
+long
+bfd_canonicalize_reloc (abfd, asect, location, symbols)
+ bfd *abfd;
+ sec_ptr asect;
+ arelent **location;
+ asymbol **symbols;
+{
+ if (abfd->format != bfd_object) {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+ return BFD_SEND (abfd, _bfd_canonicalize_reloc,
+ (abfd, asect, location, symbols));
+}
+
+/*
+FUNCTION
+ bfd_set_reloc
+
+SYNOPSIS
+ void bfd_set_reloc
+ (bfd *abfd, asection *sec, arelent **rel, unsigned int count)
+
+DESCRIPTION
+ 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*/
+void
+bfd_set_reloc (ignore_abfd, asect, location, count)
+ bfd *ignore_abfd;
+ sec_ptr asect;
+ arelent **location;
+ unsigned int count;
+{
+ asect->orelocation = location;
+ 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 <<bfd_error_wrong_format>> - The target bfd was not of object format.
+ o <<bfd_error_invalid_operation>> - The target bfd was open for reading.
+ o <<bfd_error_invalid_operation>> -
+ The flag word contained a bit which was not applicable to the
+ type of file. E.g., 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)
+ 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)
+ const char *file;
+ int line;
+{
+ (*_bfd_error_handler) ("bfd assertion fail %s:%d", file, line);
+}
+
+
+/*
+FUNCTION
+ bfd_set_start_address
+
+SYNOPSIS
+ boolean bfd_set_start_address(bfd *abfd, bfd_vma vma);
+
+DESCRIPTION
+ Make @var{vma} the entry point of output BFD @var{abfd}.
+
+RETURNS
+ Returns <<true>> on success, <<false>> otherwise.
+*/
+
+boolean
+bfd_set_start_address(abfd, vma)
+bfd *abfd;
+bfd_vma vma;
+{
+ abfd->start_address = vma;
+ return true;
+}
+
+
+/*
+FUNCTION
+ bfd_get_mtime
+
+SYNOPSIS
+ long bfd_get_mtime(bfd *abfd);
+
+DESCRIPTION
+ Return the file modification time (as read from the file system, or
+ from the archive header for archive members).
+
+*/
+
+long
+bfd_get_mtime (abfd)
+ bfd *abfd;
+{
+ FILE *fp;
+ struct stat buf;
+
+ if (abfd->mtime_set)
+ return abfd->mtime;
+
+ fp = bfd_cache_lookup (abfd);
+ if (0 != fstat (fileno (fp), &buf))
+ return 0;
+
+ abfd->mtime = buf.st_mtime; /* Save value in case anyone wants it */
+ return buf.st_mtime;
+}
+
+/*
+FUNCTION
+ bfd_get_size
+
+SYNOPSIS
+ long bfd_get_size(bfd *abfd);
+
+DESCRIPTION
+ Return the file size (as read from file system) for the file
+ associated with BFD @var{abfd}.
+
+ 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 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.
+ 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
+ error when it tries to read the table, or a "virtual memory
+ 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?".
+*/
+
+long
+bfd_get_size (abfd)
+ bfd *abfd;
+{
+ FILE *fp;
+ struct stat buf;
+
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ return ((struct bfd_in_memory *) abfd->iostream)->size;
+
+ fp = bfd_cache_lookup (abfd);
+ if (0 != fstat (fileno (fp), &buf))
+ return 0;
+
+ return buf.st_size;
+}
+
+/*
+FUNCTION
+ bfd_get_gp_size
+
+SYNOPSIS
+ int bfd_get_gp_size(bfd *abfd);
+
+DESCRIPTION
+ 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.
+*/
+
+int
+bfd_get_gp_size (abfd)
+ bfd *abfd;
+{
+ 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
+ bfd_set_gp_size
+
+SYNOPSIS
+ 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.
+*/
+
+void
+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)
+ elf_gp_size (abfd) = i;
+}
+
+/* Get the GP value. This is an internal function used by some of the
+ relocation special_function routines on targets which support a GP
+ register. */
+
+bfd_vma
+_bfd_get_gp_value (abfd)
+ bfd *abfd;
+{
+ if (abfd->format == bfd_object)
+ {
+ if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+ return ecoff_data (abfd)->gp;
+ else if (abfd->xvec->flavour == bfd_target_elf_flavour)
+ return elf_gp (abfd);
+ }
+ return 0;
+}
+
+/* Set the GP value. */
+
+void
+_bfd_set_gp_value (abfd, v)
+ bfd *abfd;
+ bfd_vma v;
+{
+ if (abfd->format != bfd_object)
+ return;
+ if (abfd->xvec->flavour == bfd_target_ecoff_flavour)
+ ecoff_data (abfd)->gp = v;
+ else if (abfd->xvec->flavour == bfd_target_elf_flavour)
+ elf_gp (abfd) = v;
+}
+
+/*
+FUNCTION
+ bfd_scan_vma
+
+SYNOPSIS
+ bfd_vma bfd_scan_vma(CONST char *string, CONST char **end, int base);
+
+DESCRIPTION
+ Convert, like <<strtoul>>, a numerical expression
+ @var{string} into a <<bfd_vma>> integer, and return that integer.
+ (Though without as many bells and whistles as <<strtoul>>.)
+ 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.
+*/
+
+bfd_vma
+bfd_scan_vma (string, end, base)
+ CONST char *string;
+ CONST char **end;
+ int base;
+{
+ bfd_vma value;
+ int digit;
+
+ /* Let the host do it if possible. */
+ if (sizeof(bfd_vma) <= sizeof(unsigned long))
+ return (bfd_vma) strtoul (string, (char **) end, base);
+
+ /* A negative base makes no sense, and we only need to go as high as hex. */
+ if ((base < 0) || (base > 16))
+ return (bfd_vma) 0;
+
+ if (base == 0)
+ {
+ if (string[0] == '0')
+ {
+ if ((string[1] == 'x') || (string[1] == 'X'))
+ base = 16;
+ /* XXX should we also allow "0b" or "0B" to set base to 2? */
+ else
+ base = 8;
+ }
+ else
+ base = 10;
+ }
+ if ((base == 16) &&
+ (string[0] == '0') && ((string[1] == 'x') || (string[1] == 'X')))
+ string += 2;
+ /* XXX should we also skip over "0b" or "0B" if base is 2? */
+
+/* Speed could be improved with a table like hex_value[] in gas. */
+#define HEX_VALUE(c) \
+ (isxdigit(c) ? \
+ (isdigit(c) ? \
+ (c - '0') : \
+ (10 + c - (islower(c) ? 'a' : 'A'))) : \
+ 42)
+
+ for (value = 0; (digit = HEX_VALUE(*string)) < base; string++)
+ {
+ value = value * base + digit;
+ }
+
+ if (end)
+ *end = string;
+
+ 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 <<true>> on success, <<false>> on error.
+ Possible error returns are:
+
+ o <<bfd_error_no_memory>> -
+ 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
+ bfd_merge_private_bfd_data
+
+SYNOPSIS
+ boolean bfd_merge_private_bfd_data(bfd *ibfd, bfd *obfd);
+
+DESCRIPTION
+ Merge private BFD information from the BFD @var{ibfd} to the
+ the output file BFD @var{obfd} when linking. Return <<true>>
+ on success, <<false>> on error. Possible error returns are:
+
+ o <<bfd_error_no_memory>> -
+ Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_merge_private_bfd_data(ibfd, obfd) \
+. BFD_SEND (ibfd, _bfd_merge_private_bfd_data, \
+. (ibfd, obfd))
+
+*/
+
+/*
+FUNCTION
+ bfd_set_private_flags
+
+SYNOPSIS
+ boolean bfd_set_private_flags(bfd *abfd, flagword flags);
+
+DESCRIPTION
+ Set private BFD flag information in the BFD @var{abfd}.
+ Return <<true>> on success, <<false>> on error. Possible error
+ returns are:
+
+ o <<bfd_error_no_memory>> -
+ Not enough memory exists to create private data for @var{obfd}.
+
+.#define bfd_set_private_flags(abfd, flags) \
+. BFD_SEND (abfd, _bfd_set_private_flags, \
+. (abfd, flags))
+
+*/
+
+/*
+FUNCTION
+ stuff
+
+DESCRIPTION
+ Stuff which should be documented:
+
+.#define bfd_sizeof_headers(abfd, reloc) \
+. BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, reloc))
+.
+.#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \
+. BFD_SEND (abfd, _bfd_find_nearest_line, (abfd, sec, syms, off, file, func, line))
+.
+. {* Do these three do anything useful at all, for any back end? *}
+.#define bfd_debug_info_start(abfd) \
+. BFD_SEND (abfd, _bfd_debug_info_start, (abfd))
+.
+.#define bfd_debug_info_end(abfd) \
+. BFD_SEND (abfd, _bfd_debug_info_end, (abfd))
+.
+.#define bfd_debug_info_accumulate(abfd, section) \
+. BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section))
+.
+.
+.#define bfd_stat_arch_elt(abfd, stat) \
+. BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat))
+.
+.#define bfd_update_armap_timestamp(abfd) \
+. BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd))
+.
+.#define bfd_set_arch_mach(abfd, arch, mach)\
+. BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach))
+.
+.#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_print_private_bfd_data(abfd, file)\
+. BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file))
+.
+.#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))
+.
+.extern bfd_byte *bfd_get_relocated_section_contents
+. PARAMS ((bfd *, struct bfd_link_info *,
+. struct bfd_link_order *, bfd_byte *,
+. boolean, asymbol **));
+.
+
+*/
+
+bfd_byte *
+bfd_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;
+{
+ bfd *abfd2;
+ bfd_byte *(*fn) PARAMS ((bfd *, struct bfd_link_info *,
+ struct bfd_link_order *, bfd_byte *, boolean,
+ asymbol **));
+
+ if (link_order->type == bfd_indirect_link_order)
+ {
+ abfd2 = link_order->u.indirect.section->owner;
+ if (abfd2 == 0)
+ abfd2 = abfd;
+ }
+ else
+ abfd2 = abfd;
+ fn = abfd2->xvec->_bfd_get_relocated_section_contents;
+
+ return (*fn) (abfd, link_info, link_order, data, relocateable, symbols);
+}
+
+/* Record information about an ELF program header. */
+
+boolean
+bfd_record_phdr (abfd, type, flags_valid, flags, at_valid, at,
+ includes_filehdr, includes_phdrs, count, secs)
+ bfd *abfd;
+ unsigned long type;
+ boolean flags_valid;
+ flagword flags;
+ boolean at_valid;
+ bfd_vma at;
+ boolean includes_filehdr;
+ boolean includes_phdrs;
+ unsigned int count;
+ asection **secs;
+{
+ struct elf_segment_map *m, **pm;
+
+ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
+ return true;
+
+ m = ((struct elf_segment_map *)
+ bfd_alloc (abfd,
+ (sizeof (struct elf_segment_map)
+ + (count - 1) * sizeof (asection *))));
+ if (m == NULL)
+ return false;
+
+ m->next = NULL;
+ m->p_type = type;
+ m->p_flags = flags;
+ m->p_paddr = at;
+ m->p_flags_valid = flags_valid;
+ m->p_paddr_valid = at_valid;
+ m->includes_filehdr = includes_filehdr;
+ m->includes_phdrs = includes_phdrs;
+ m->count = count;
+ if (count > 0)
+ memcpy (m->sections, secs, count * sizeof (asection *));
+
+ for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next)
+ ;
+ *pm = m;
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/binary.c b/contrib/gdb/bfd/binary.c
new file mode 100644
index 0000000..a480e46
--- /dev/null
+++ b/contrib/gdb/bfd/binary.c
@@ -0,0 +1,348 @@
+/* BFD back-end for binary objects.
+ Copyright 1994 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is a BFD backend which may be used to write binary objects.
+ It may only be used for output, not input. The intention is that
+ this may be used as an output format for objcopy in order to
+ generate raw binary data.
+
+ This is very simple. The only complication is that the real data
+ will start at some address X, and in some cases we will not want to
+ include X zeroes just to get to that point. Since the start
+ address is not meaningful for this object file format, we use it
+ instead to indicate the number of zeroes to skip at the start of
+ the file. objcopy cooperates by specially setting the start
+ address to zero by default. */
+
+#include <ctype.h>
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* Any bfd we create by reading a binary file has three symbols:
+ a start symbol, an end symbol, and an absolute length symbol. */
+#define BIN_SYMS 3
+
+static boolean binary_mkobject PARAMS ((bfd *));
+static const bfd_target *binary_object_p PARAMS ((bfd *));
+static boolean binary_get_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static long binary_get_symtab_upper_bound PARAMS ((bfd *));
+static char *mangle_name PARAMS ((bfd *, char *));
+static long binary_get_symtab PARAMS ((bfd *, asymbol **));
+static asymbol *binary_make_empty_symbol PARAMS ((bfd *));
+static void binary_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
+static boolean binary_set_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static int binary_sizeof_headers PARAMS ((bfd *, boolean));
+
+/* Create a binary object. Invoked via bfd_set_format. */
+
+static boolean
+binary_mkobject (abfd)
+ bfd *abfd;
+{
+ return true;
+}
+
+/* Any file may be considered to be a binary file, provided the target
+ was not defaulted. That is, it must be explicitly specified as
+ being binary. */
+
+static const bfd_target *
+binary_object_p (abfd)
+ bfd *abfd;
+{
+ struct stat statbuf;
+ asection *sec;
+
+ if (abfd->target_defaulted)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ abfd->symcount = BIN_SYMS;
+
+ /* Find the file size. */
+ if (bfd_stat (abfd, &statbuf) < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return NULL;
+ }
+
+ /* One data section. */
+ sec = bfd_make_section (abfd, ".data");
+ if (sec == NULL)
+ return NULL;
+ sec->flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS;
+ sec->vma = 0;
+ sec->_raw_size = statbuf.st_size;
+ sec->filepos = 0;
+
+ abfd->tdata.any = (PTR) sec;
+
+ return abfd->xvec;
+}
+
+#define binary_close_and_cleanup _bfd_generic_close_and_cleanup
+#define binary_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define binary_new_section_hook _bfd_generic_new_section_hook
+
+/* Get contents of the only section. */
+
+static boolean
+binary_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (bfd_seek (abfd, offset, SEEK_SET) != 0
+ || bfd_read (location, 1, count, abfd) != count)
+ return false;
+ return true;
+}
+
+/* Return the amount of memory needed to read the symbol table. */
+
+static long
+binary_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ return (BIN_SYMS + 1) * sizeof (asymbol *);
+}
+
+/* Create a symbol name based on the bfd's filename. */
+
+static char *
+mangle_name (abfd, suffix)
+ bfd *abfd;
+ char *suffix;
+{
+ int size;
+ char *buf;
+ char *p;
+
+ size = (strlen (bfd_get_filename (abfd))
+ + strlen (suffix)
+ + sizeof "_binary__");
+
+ buf = (char *) bfd_alloc (abfd, size);
+ if (buf == NULL)
+ return "";
+
+ sprintf (buf, "_binary_%s_%s", bfd_get_filename (abfd), suffix);
+
+ /* Change any non-alphanumeric characters to underscores. */
+ for (p = buf; *p; p++)
+ if (! isalnum (*p))
+ *p = '_';
+
+ return buf;
+}
+
+/* Return the symbol table. */
+
+static long
+binary_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ asection *sec = (asection *) abfd->tdata.any;
+ asymbol *syms;
+ unsigned int i;
+
+ syms = (asymbol *) bfd_alloc (abfd, BIN_SYMS * sizeof (asymbol));
+ if (syms == NULL)
+ return false;
+
+ /* Start symbol. */
+ syms[0].the_bfd = abfd;
+ syms[0].name = mangle_name (abfd, "start");
+ syms[0].value = 0;
+ syms[0].flags = BSF_GLOBAL;
+ syms[0].section = sec;
+ syms[0].udata.p = NULL;
+
+ /* End symbol. */
+ syms[1].the_bfd = abfd;
+ syms[1].name = mangle_name (abfd, "end");
+ syms[1].value = sec->_raw_size;
+ syms[1].flags = BSF_GLOBAL;
+ syms[1].section = sec;
+ syms[1].udata.p = NULL;
+
+ /* Size symbol. */
+ syms[2].the_bfd = abfd;
+ syms[2].name = mangle_name (abfd, "size");
+ syms[2].value = sec->_raw_size;
+ syms[2].flags = BSF_GLOBAL;
+ syms[2].section = bfd_abs_section_ptr;
+ syms[2].udata.p = NULL;
+
+ for (i = 0; i < BIN_SYMS; i++)
+ *alocation++ = syms++;
+ *alocation = NULL;
+
+ return BIN_SYMS;
+}
+
+/* Make an empty symbol. */
+
+static asymbol *
+binary_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ return (asymbol *) bfd_alloc (abfd, sizeof (asymbol));
+}
+
+#define binary_print_symbol _bfd_nosymbols_print_symbol
+
+/* Get information about a symbol. */
+
+static void
+binary_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+#define binary_bfd_is_local_label bfd_generic_is_local_label
+#define binary_get_lineno _bfd_nosymbols_get_lineno
+#define binary_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define binary_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define binary_read_minisymbols _bfd_generic_read_minisymbols
+#define binary_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define binary_get_reloc_upper_bound \
+ ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
+#define binary_canonicalize_reloc \
+ ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
+#define binary_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+/* Set the architecture of a binary file. */
+#define binary_set_arch_mach _bfd_generic_set_arch_mach
+
+/* Write section contents of a binary file. */
+
+static boolean
+binary_set_section_contents (abfd, sec, data, offset, size)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+ file_ptr offset;
+ bfd_size_type size;
+{
+ if (! abfd->output_has_begun)
+ {
+ bfd_vma low;
+ asection *s;
+
+ /* The lowest section VMA sets the virtual address of the start
+ of the file. We use the set the file position of all the
+ sections. */
+ low = abfd->sections->vma;
+ for (s = abfd->sections->next; s != NULL; s = s->next)
+ if (s->vma < low)
+ low = s->vma;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ s->filepos = s->vma - low;
+
+ abfd->output_has_begun = true;
+ }
+
+ return _bfd_generic_set_section_contents (abfd, sec, data, offset, size);
+}
+
+/* No space is required for header information. */
+
+static int
+binary_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return 0;
+}
+
+#define binary_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define binary_bfd_relax_section bfd_generic_relax_section
+#define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define binary_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define binary_bfd_final_link _bfd_generic_final_link
+#define binary_bfd_link_split_section _bfd_generic_link_split_section
+#define binary_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+const bfd_target binary_vec =
+{
+ "binary", /* name */
+ bfd_target_unknown_flavour, /* flavour */
+ BFD_ENDIAN_UNKNOWN, /* byteorder */
+ BFD_ENDIAN_UNKNOWN, /* header_byteorder */
+ EXEC_P, /* object_flags */
+ (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
+ | SEC_ROM | SEC_HAS_CONTENTS), /* section_flags */
+ 0, /* symbol_leading_char */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 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_check_format */
+ _bfd_dummy_target,
+ binary_object_p, /* bfd_check_format */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ { /* bfd_set_format */
+ bfd_false,
+ binary_mkobject,
+ bfd_false,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ bfd_true,
+ bfd_false,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (binary),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (binary),
+ BFD_JUMP_TABLE_RELOCS (binary),
+ BFD_JUMP_TABLE_WRITE (binary),
+ BFD_JUMP_TABLE_LINK (binary),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ NULL
+};
diff --git a/contrib/gdb/bfd/bout.c b/contrib/gdb/bfd/bout.c
new file mode 100644
index 0000000..9da4b82
--- /dev/null
+++ b/contrib/gdb/bfd/bout.c
@@ -0,0 +1,1471 @@
+/* BFD back-end for Intel 960 b.out binaries.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "genlink.h"
+#include "bout.h"
+
+#include "aout/stab_gnu.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+
+static int aligncode PARAMS ((bfd *abfd, asection *input_section,
+ arelent *r, unsigned int shrink));
+static void perform_slip PARAMS ((bfd *abfd, unsigned int slip,
+ asection *input_section, bfd_vma value));
+static boolean b_out_squirt_out_relocs PARAMS ((bfd *abfd, asection *section));
+static const bfd_target *b_out_callback PARAMS ((bfd *));
+static bfd_reloc_status_type calljx_callback
+ PARAMS ((bfd *, struct bfd_link_info *, arelent *, PTR src, PTR dst,
+ asection *));
+static bfd_reloc_status_type callj_callback
+ PARAMS ((bfd *, struct bfd_link_info *, arelent *, PTR data,
+ unsigned int srcidx, unsigned int dstidx, asection *, boolean));
+static bfd_vma get_value PARAMS ((arelent *, struct bfd_link_info *,
+ asection *));
+static int abs32code PARAMS ((bfd *, asection *, arelent *,
+ unsigned int, struct bfd_link_info *));
+static boolean b_out_bfd_relax_section PARAMS ((bfd *, asection *,
+ struct bfd_link_info *,
+ boolean *));
+static bfd_byte *b_out_bfd_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, asymbol **));
+
+/* Swaps the information in an executable header taken from a raw byte
+ stream memory image, into the internal exec_header structure. */
+
+void
+bout_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;
+
+ /* 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);
+ execp->a_data = GET_WORD (abfd, bytes->e_data);
+ execp->a_bss = GET_WORD (abfd, bytes->e_bss);
+ execp->a_syms = GET_WORD (abfd, bytes->e_syms);
+ execp->a_entry = GET_WORD (abfd, bytes->e_entry);
+ execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
+ execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
+ execp->a_tload = GET_WORD (abfd, bytes->e_tload);
+ execp->a_dload = GET_WORD (abfd, bytes->e_dload);
+ execp->a_talign = bytes->e_talign[0];
+ execp->a_dalign = bytes->e_dalign[0];
+ execp->a_balign = bytes->e_balign[0];
+ execp->a_relaxable = bytes->e_relaxable[0];
+}
+
+/* Swaps the information in an internal exec header structure into the
+ supplied buffer ready for writing to disk. */
+
+PROTO(void, bout_swap_exec_header_out,
+ (bfd *abfd,
+ struct internal_exec *execp,
+ struct external_exec *raw_bytes));
+void
+bout_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;
+
+ /* Now fill in fields in the raw data, from the fields in the exec struct. */
+ bfd_h_put_32 (abfd, execp->a_info , bytes->e_info);
+ PUT_WORD (abfd, execp->a_text , bytes->e_text);
+ PUT_WORD (abfd, execp->a_data , bytes->e_data);
+ PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
+ PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
+ PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
+ PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
+ PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
+ PUT_WORD (abfd, execp->a_tload , bytes->e_tload);
+ PUT_WORD (abfd, execp->a_dload , bytes->e_dload);
+ bytes->e_talign[0] = execp->a_talign;
+ bytes->e_dalign[0] = execp->a_dalign;
+ bytes->e_balign[0] = execp->a_balign;
+ bytes->e_relaxable[0] = execp->a_relaxable;
+}
+
+
+static const bfd_target *
+b_out_object_p (abfd)
+ bfd *abfd;
+{
+ struct internal_exec anexec;
+ struct external_exec exec_bytes;
+
+ if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ anexec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info);
+
+ if (N_BADMAG (anexec)) {
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ bout_swap_exec_header_in (abfd, &exec_bytes, &anexec);
+ return aout_32_some_aout_object_p (abfd, &anexec, b_out_callback);
+}
+
+
+/* Finish up the opening of a b.out file for reading. Fill in all the
+ fields that are not handled by common code. */
+
+static const bfd_target *
+b_out_callback (abfd)
+ bfd *abfd;
+{
+ struct internal_exec *execp = exec_hdr (abfd);
+ unsigned long bss_start;
+
+ /* Architecture and machine type */
+ bfd_set_arch_mach(abfd,
+ bfd_arch_i960, /* B.out only used on i960 */
+ bfd_mach_i960_core /* Default */
+ );
+
+ /* The positions of the string table and symbol table. */
+ obj_str_filepos (abfd) = N_STROFF (*execp);
+ obj_sym_filepos (abfd) = N_SYMOFF (*execp);
+
+ /* The alignments of the sections */
+ obj_textsec (abfd)->alignment_power = execp->a_talign;
+ obj_datasec (abfd)->alignment_power = execp->a_dalign;
+ obj_bsssec (abfd)->alignment_power = execp->a_balign;
+
+ /* The starting addresses of the sections. */
+ obj_textsec (abfd)->vma = execp->a_tload;
+ obj_datasec (abfd)->vma = execp->a_dload;
+
+ /* And reload the sizes, since the aout module zaps them */
+ obj_textsec (abfd)->_raw_size = execp->a_text;
+
+ bss_start = execp->a_dload + execp->a_data; /* BSS = end of data section */
+ obj_bsssec (abfd)->vma = align_power (bss_start, execp->a_balign);
+
+ /* The file positions of the sections */
+ obj_textsec (abfd)->filepos = N_TXTOFF(*execp);
+ obj_datasec (abfd)->filepos = N_DATOFF(*execp);
+
+ /* The file positions of the relocation info */
+ obj_textsec (abfd)->rel_filepos = N_TROFF(*execp);
+ obj_datasec (abfd)->rel_filepos = N_DROFF(*execp);
+
+ adata(abfd).page_size = 1; /* Not applicable. */
+ adata(abfd).segment_size = 1; /* Not applicable. */
+ adata(abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+
+ if (execp->a_relaxable)
+ abfd->flags |= BFD_IS_RELAXABLE;
+ return abfd->xvec;
+}
+
+struct bout_data_struct {
+ struct aoutdata a;
+ struct internal_exec e;
+};
+
+static boolean
+b_out_mkobject (abfd)
+ bfd *abfd;
+{
+ struct bout_data_struct *rawptr;
+
+ rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, sizeof (struct bout_data_struct));
+ if (rawptr == NULL)
+ return false;
+
+ abfd->tdata.bout_data = rawptr;
+ exec_hdr (abfd) = &rawptr->e;
+
+ obj_textsec (abfd) = (asection *)NULL;
+ obj_datasec (abfd) = (asection *)NULL;
+ obj_bsssec (abfd) = (asection *)NULL;
+
+ return true;
+}
+
+static boolean
+b_out_write_object_contents (abfd)
+ bfd *abfd;
+{
+ struct external_exec swapped_hdr;
+
+ if (! aout_32_make_sections (abfd))
+ return false;
+
+ exec_hdr (abfd)->a_info = BMAGIC;
+
+ exec_hdr (abfd)->a_text = obj_textsec (abfd)->_raw_size;
+ exec_hdr (abfd)->a_data = obj_datasec (abfd)->_raw_size;
+ exec_hdr (abfd)->a_bss = obj_bsssec (abfd)->_raw_size;
+ exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
+ exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
+ exec_hdr (abfd)->a_trsize = ((obj_textsec (abfd)->reloc_count) *
+ sizeof (struct relocation_info));
+ exec_hdr (abfd)->a_drsize = ((obj_datasec (abfd)->reloc_count) *
+ sizeof (struct relocation_info));
+
+ exec_hdr (abfd)->a_talign = obj_textsec (abfd)->alignment_power;
+ exec_hdr (abfd)->a_dalign = obj_datasec (abfd)->alignment_power;
+ exec_hdr (abfd)->a_balign = obj_bsssec (abfd)->alignment_power;
+
+ exec_hdr (abfd)->a_tload = obj_textsec (abfd)->vma;
+ exec_hdr (abfd)->a_dload = obj_datasec (abfd)->vma;
+
+ bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || (bfd_write ((PTR) &swapped_hdr, 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_seek (abfd, (file_ptr)(N_SYMOFF(*exec_hdr(abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ if (! aout_32_write_syms (abfd))
+ return false;
+
+ if (bfd_seek (abfd, (file_ptr)(N_TROFF(*exec_hdr(abfd))), SEEK_SET) != 0)
+ return false;
+
+ if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd))) return false;
+ if (bfd_seek (abfd, (file_ptr)(N_DROFF(*exec_hdr(abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd))) return false;
+ }
+ return true;
+}
+
+/** Some reloc hackery */
+
+#define CALLS 0x66003800 /* Template for 'calls' instruction */
+#define BAL 0x0b000000 /* Template for 'bal' instruction */
+#define BALX 0x85000000 /* Template for 'balx' instruction */
+#define BAL_MASK 0x00ffffff
+#define CALL 0x09000000
+#define PCREL13_MASK 0x1fff
+
+
+#define output_addr(sec) ((sec)->output_offset+(sec)->output_section->vma)
+
+/* Magic to turn callx into calljx */
+static bfd_reloc_status_type
+calljx_callback (abfd, link_info, reloc_entry, src, dst, input_section)
+ bfd *abfd;
+ struct bfd_link_info *link_info;
+ arelent *reloc_entry;
+ PTR src;
+ PTR dst;
+ asection *input_section;
+{
+ int word = bfd_get_32 (abfd, src);
+ asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
+ aout_symbol_type *symbol = aout_symbol (symbol_in);
+ bfd_vma value;
+
+ value = get_value (reloc_entry, link_info, input_section);
+
+ if (IS_CALLNAME (symbol->other))
+ {
+ aout_symbol_type *balsym = symbol+1;
+ int inst = bfd_get_32 (abfd, (bfd_byte *) src-4);
+ /* The next symbol should be an N_BALNAME */
+ BFD_ASSERT (IS_BALNAME (balsym->other));
+ inst &= BAL_MASK;
+ inst |= BALX;
+ bfd_put_32 (abfd, inst, (bfd_byte *) dst-4);
+ symbol = balsym;
+ value = (symbol->symbol.value
+ + output_addr (symbol->symbol.section));
+ }
+
+ word += value + reloc_entry->addend;
+
+ bfd_put_32(abfd, word, dst);
+ return bfd_reloc_ok;
+}
+
+
+/* Magic to turn call into callj */
+static bfd_reloc_status_type
+callj_callback (abfd, link_info, reloc_entry, data, srcidx, dstidx,
+ input_section, shrinking)
+ bfd *abfd;
+ struct bfd_link_info *link_info;
+ arelent *reloc_entry;
+ PTR data;
+ unsigned int srcidx;
+ unsigned int dstidx;
+ asection *input_section;
+ boolean shrinking;
+{
+ int word = bfd_get_32 (abfd, (bfd_byte *) data + srcidx);
+ asymbol *symbol_in = *(reloc_entry->sym_ptr_ptr);
+ aout_symbol_type *symbol = aout_symbol (symbol_in);
+ bfd_vma value;
+
+ value = get_value (reloc_entry, link_info, input_section);
+
+ if (IS_OTHER(symbol->other))
+ {
+ /* Call to a system procedure - replace code with system
+ procedure number. */
+ word = CALLS | (symbol->other - 1);
+ }
+ else if (IS_CALLNAME(symbol->other))
+ {
+ aout_symbol_type *balsym = symbol+1;
+
+ /* The next symbol should be an N_BALNAME. */
+ BFD_ASSERT(IS_BALNAME(balsym->other));
+
+ /* We are calling a leaf, so replace the call instruction with a
+ bal. */
+ word = BAL | ((word
+ + output_addr (balsym->symbol.section)
+ + balsym->symbol.value + reloc_entry->addend
+ - dstidx
+ - output_addr (input_section))
+ & BAL_MASK);
+ }
+ else if ((symbol->symbol.flags & BSF_SECTION_SYM) != 0)
+ {
+ /* A callj against a symbol in the same section is a fully
+ resolved relative call. We don't need to do anything here.
+ If the symbol is not in the same section, I'm not sure what
+ to do; fortunately, this case will probably never arise. */
+ BFD_ASSERT (! shrinking);
+ BFD_ASSERT (symbol->symbol.section == input_section);
+ }
+ else
+ {
+ word = CALL | (((word & BAL_MASK)
+ + value
+ + reloc_entry->addend
+ - (shrinking ? dstidx : 0)
+ - output_addr (input_section))
+ & BAL_MASK);
+ }
+ bfd_put_32(abfd, word, (bfd_byte *) data + dstidx);
+ return bfd_reloc_ok;
+}
+
+/* type rshift size bitsize pcrel bitpos absolute overflow check*/
+
+#define ABS32CODE 0
+#define ABS32CODE_SHRUNK 1
+#define PCREL24 2
+#define CALLJ 3
+#define ABS32 4
+#define PCREL13 5
+#define ABS32_MAYBE_RELAXABLE 1
+#define ABS32_WAS_RELAXABLE 2
+
+#define ALIGNER 10
+#define ALIGNDONE 11
+static reloc_howto_type howto_reloc_callj =
+HOWTO(CALLJ, 0, 2, 24, true, 0, complain_overflow_signed, 0,"callj", true, 0x00ffffff, 0x00ffffff,false);
+static reloc_howto_type howto_reloc_abs32 =
+HOWTO(ABS32, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"abs32", true, 0xffffffff,0xffffffff,false);
+static reloc_howto_type howto_reloc_pcrel24 =
+HOWTO(PCREL24, 0, 2, 24, true, 0, complain_overflow_signed,0,"pcrel24", true, 0x00ffffff,0x00ffffff,false);
+
+static reloc_howto_type howto_reloc_pcrel13 =
+HOWTO(PCREL13, 0, 2, 13, true, 0, complain_overflow_signed,0,"pcrel13", true, 0x00001fff,0x00001fff,false);
+
+
+static reloc_howto_type howto_reloc_abs32codeshrunk =
+HOWTO(ABS32CODE_SHRUNK, 0, 2, 24, true, 0, complain_overflow_signed, 0,"callx->callj", true, 0x00ffffff, 0x00ffffff,false);
+
+static reloc_howto_type howto_reloc_abs32code =
+HOWTO(ABS32CODE, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"callx", true, 0xffffffff,0xffffffff,false);
+
+static reloc_howto_type howto_align_table[] = {
+ HOWTO (ALIGNER, 0, 0x1, 0, false, 0, complain_overflow_dont, 0, "align16", false, 0, 0, false),
+ HOWTO (ALIGNER, 0, 0x3, 0, false, 0, complain_overflow_dont, 0, "align32", false, 0, 0, false),
+ HOWTO (ALIGNER, 0, 0x7, 0, false, 0, complain_overflow_dont, 0, "align64", false, 0, 0, false),
+ HOWTO (ALIGNER, 0, 0xf, 0, false, 0, complain_overflow_dont, 0, "align128", false, 0, 0, false),
+};
+
+static reloc_howto_type howto_done_align_table[] = {
+ HOWTO (ALIGNDONE, 0x1, 0x1, 0, false, 0, complain_overflow_dont, 0, "donealign16", false, 0, 0, false),
+ HOWTO (ALIGNDONE, 0x3, 0x3, 0, false, 0, complain_overflow_dont, 0, "donealign32", false, 0, 0, false),
+ HOWTO (ALIGNDONE, 0x7, 0x7, 0, false, 0, complain_overflow_dont, 0, "donealign64", false, 0, 0, false),
+ HOWTO (ALIGNDONE, 0xf, 0xf, 0, false, 0, complain_overflow_dont, 0, "donealign128", false, 0, 0, false),
+};
+
+static reloc_howto_type *
+b_out_bfd_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ default:
+ return 0;
+ case BFD_RELOC_I960_CALLJ:
+ return &howto_reloc_callj;
+ case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
+ return &howto_reloc_abs32;
+ case BFD_RELOC_24_PCREL:
+ return &howto_reloc_pcrel24;
+ }
+}
+
+/* Allocate enough room for all the reloc entries, plus pointers to them all */
+
+static boolean
+b_out_slurp_reloc_table (abfd, asect, symbols)
+ bfd *abfd;
+ sec_ptr asect;
+ asymbol **symbols;
+{
+ register struct relocation_info *rptr;
+ unsigned int counter ;
+ arelent *cache_ptr ;
+ int extern_mask, pcrel_mask, callj_mask, length_shift;
+ int incode_mask;
+ int size_mask;
+ bfd_vma prev_addr = 0;
+ unsigned int count;
+ size_t reloc_size;
+ struct relocation_info *relocs;
+ arelent *reloc_cache;
+
+ if (asect->relocation)
+ return true;
+ if (!aout_32_slurp_symbol_table (abfd))
+ return false;
+
+ if (asect == obj_datasec (abfd)) {
+ reloc_size = exec_hdr(abfd)->a_drsize;
+ goto doit;
+ }
+
+ if (asect == obj_textsec (abfd)) {
+ reloc_size = exec_hdr(abfd)->a_trsize;
+ goto doit;
+ }
+
+ if (asect == obj_bsssec (abfd)) {
+ reloc_size = 0;
+ goto doit;
+ }
+
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+
+ doit:
+ if (bfd_seek (abfd, (file_ptr)(asect->rel_filepos), SEEK_SET) != 0)
+ return false;
+ count = reloc_size / sizeof (struct relocation_info);
+
+ relocs = (struct relocation_info *) bfd_malloc (reloc_size);
+ if (!relocs && reloc_size != 0)
+ return false;
+ reloc_cache = (arelent *) bfd_malloc ((count+1) * sizeof (arelent));
+ if (!reloc_cache) {
+ if (relocs != NULL)
+ free ((char*)relocs);
+ return false;
+ }
+
+ if (bfd_read ((PTR) relocs, 1, reloc_size, abfd) != reloc_size) {
+ free (reloc_cache);
+ if (relocs != NULL)
+ free (relocs);
+ return false;
+ }
+
+
+
+ if (bfd_header_big_endian (abfd)) {
+ /* big-endian bit field allocation order */
+ pcrel_mask = 0x80;
+ extern_mask = 0x10;
+ incode_mask = 0x08;
+ callj_mask = 0x02;
+ size_mask = 0x20;
+ length_shift = 5;
+ } else {
+ /* little-endian bit field allocation order */
+ pcrel_mask = 0x01;
+ extern_mask = 0x08;
+ incode_mask = 0x10;
+ callj_mask = 0x40;
+ size_mask = 0x02;
+ length_shift = 1;
+ }
+
+ for (rptr = relocs, cache_ptr = reloc_cache, counter = 0;
+ counter < count;
+ counter++, rptr++, cache_ptr++)
+ {
+ unsigned char *raw = (unsigned char *)rptr;
+ unsigned int symnum;
+ cache_ptr->address = bfd_h_get_32 (abfd, raw + 0);
+ cache_ptr->howto = 0;
+ if (bfd_header_big_endian (abfd))
+ {
+ symnum = (raw[4] << 16) | (raw[5] << 8) | raw[6];
+ }
+ else
+ {
+ symnum = (raw[6] << 16) | (raw[5] << 8) | raw[4];
+ }
+
+ if (raw[7] & extern_mask)
+ {
+ /* if this is set then the r_index is a index into the symbol table;
+ * if the bit is not set then r_index contains a section map.
+ * we either fill in the sym entry with a pointer to the symbol,
+ * or point to the correct section
+ */
+ cache_ptr->sym_ptr_ptr = symbols + symnum;
+ cache_ptr->addend = 0;
+ } else
+ {
+ /* in a.out symbols are relative to the beginning of the
+ * file rather than sections ?
+ * (look in translate_from_native_sym_flags)
+ * the reloc entry addend has added to it the offset into the
+ * file of the data, so subtract the base to make the reloc
+ * section relative */
+ int s;
+ {
+ /* sign-extend symnum from 24 bits to whatever host uses */
+ s = symnum;
+ if (s & (1 << 23))
+ s |= (~0) << 24;
+ }
+ cache_ptr->sym_ptr_ptr = (asymbol **)NULL;
+ switch (s)
+ {
+ case N_TEXT:
+ case N_TEXT | N_EXT:
+ cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr;
+ cache_ptr->addend = - obj_textsec(abfd)->vma;
+ break;
+ case N_DATA:
+ case N_DATA | N_EXT:
+ cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr;
+ cache_ptr->addend = - obj_datasec(abfd)->vma;
+ break;
+ case N_BSS:
+ case N_BSS | N_EXT:
+ cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr;
+ cache_ptr->addend = - obj_bsssec(abfd)->vma;
+ break;
+ case N_ABS:
+ case N_ABS | N_EXT:
+ cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr;
+ cache_ptr->addend = 0;
+ break;
+ case -2: /* .align */
+ if (raw[7] & pcrel_mask)
+ {
+ cache_ptr->howto = &howto_align_table[(raw[7] >> length_shift) & 3];
+ cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ }
+ else
+ {
+ /* .org? */
+ abort ();
+ }
+ cache_ptr->addend = 0;
+ break;
+ default:
+ BFD_ASSERT(0);
+ break;
+ }
+
+ }
+
+ /* the i960 only has a few relocation types:
+ abs 32-bit and pcrel 24bit. except for callj's! */
+ if (cache_ptr->howto != 0)
+ ;
+ else if (raw[7] & callj_mask)
+ {
+ cache_ptr->howto = &howto_reloc_callj;
+ }
+ else if ( raw[7] & pcrel_mask)
+ {
+ if (raw[7] & size_mask)
+ cache_ptr->howto = &howto_reloc_pcrel13;
+ else
+ cache_ptr->howto = &howto_reloc_pcrel24;
+ }
+ else
+ {
+ if (raw[7] & incode_mask)
+ {
+ cache_ptr->howto = &howto_reloc_abs32code;
+ }
+ else
+ {
+ cache_ptr->howto = &howto_reloc_abs32;
+ }
+ }
+ if (cache_ptr->address < prev_addr)
+ {
+ /* Ouch! this reloc is out of order, insert into the right place
+ */
+ arelent tmp;
+ arelent *cursor = cache_ptr-1;
+ bfd_vma stop = cache_ptr->address;
+ tmp = *cache_ptr;
+ while (cursor->address > stop && cursor >= reloc_cache)
+ {
+ cursor[1] = cursor[0];
+ cursor--;
+ }
+ cursor[1] = tmp;
+ }
+ else
+ {
+ prev_addr = cache_ptr->address;
+ }
+ }
+
+
+ if (relocs != NULL)
+ free (relocs);
+ asect->relocation = reloc_cache;
+ asect->reloc_count = count;
+
+
+ return true;
+}
+
+
+static boolean
+b_out_squirt_out_relocs (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ arelent **generic;
+ int r_extern = 0;
+ int r_idx;
+ int incode_mask;
+ int len_1;
+ unsigned int count = section->reloc_count;
+ struct relocation_info *native, *natptr;
+ size_t natsize = count * sizeof (struct relocation_info);
+ int extern_mask, pcrel_mask, len_2, callj_mask;
+ if (count == 0) return true;
+ generic = section->orelocation;
+ native = ((struct relocation_info *) bfd_malloc (natsize));
+ if (!native && natsize != 0)
+ return false;
+
+ if (bfd_header_big_endian (abfd))
+ {
+ /* Big-endian bit field allocation order */
+ pcrel_mask = 0x80;
+ extern_mask = 0x10;
+ len_2 = 0x40;
+ len_1 = 0x20;
+ callj_mask = 0x02;
+ incode_mask = 0x08;
+ }
+ else
+ {
+ /* Little-endian bit field allocation order */
+ pcrel_mask = 0x01;
+ extern_mask = 0x08;
+ len_2 = 0x04;
+ len_1 = 0x02;
+ callj_mask = 0x40;
+ incode_mask = 0x10;
+ }
+
+ for (natptr = native; count > 0; --count, ++natptr, ++generic)
+ {
+ arelent *g = *generic;
+ unsigned char *raw = (unsigned char *)natptr;
+ asymbol *sym = *(g->sym_ptr_ptr);
+
+ asection *output_section = sym->section->output_section;
+
+ bfd_h_put_32(abfd, g->address, raw);
+ /* Find a type in the output format which matches the input howto -
+ * at the moment we assume input format == output format FIXME!!
+ */
+ r_idx = 0;
+ /* FIXME: Need callj stuff here, and to check the howto entries to
+ be sure they are real for this architecture. */
+ if (g->howto== &howto_reloc_callj)
+ {
+ raw[7] = callj_mask + pcrel_mask + len_2;
+ }
+ else if (g->howto == &howto_reloc_pcrel24)
+ {
+ raw[7] = pcrel_mask + len_2;
+ }
+ else if (g->howto == &howto_reloc_pcrel13)
+ {
+ raw[7] = pcrel_mask + len_1;
+ }
+ else if (g->howto == &howto_reloc_abs32code)
+ {
+ raw[7] = len_2 + incode_mask;
+ }
+ else if (g->howto >= howto_align_table
+ && g->howto <= (howto_align_table
+ + sizeof (howto_align_table) / sizeof (howto_align_table[0])
+ - 1))
+ {
+ /* symnum == -2; extern_mask not set, pcrel_mask set */
+ r_idx = -2;
+ r_extern = 0;
+ raw[7] = (pcrel_mask
+ | ((g->howto - howto_align_table) << 1));
+ }
+ else {
+ raw[7] = len_2;
+ }
+
+ if (r_idx != 0)
+ /* already mucked with r_extern, r_idx */;
+ else if (bfd_is_com_section (output_section)
+ || bfd_is_abs_section (output_section)
+ || bfd_is_und_section (output_section))
+ {
+
+ if (bfd_abs_section_ptr->symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_idx = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+
+ r_extern = 1;
+ r_idx = (*g->sym_ptr_ptr)->udata.i;
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_idx = output_section->target_index;
+ }
+
+ if (bfd_header_big_endian (abfd)) {
+ raw[4] = (unsigned char) (r_idx >> 16);
+ raw[5] = (unsigned char) (r_idx >> 8);
+ raw[6] = (unsigned char) (r_idx );
+ } else {
+ raw[6] = (unsigned char) (r_idx >> 16);
+ raw[5] = (unsigned char) (r_idx>> 8);
+ raw[4] = (unsigned char) (r_idx );
+ }
+ if (r_extern)
+ raw[7] |= extern_mask;
+ }
+
+ if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize) {
+ free((PTR)native);
+ return false;
+ }
+ free ((PTR)native);
+
+ return true;
+}
+
+/* This is stupid. This function should be a boolean predicate */
+static long
+b_out_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *tblptr;
+ unsigned int count;
+
+ if ((section->flags & SEC_CONSTRUCTOR) != 0)
+ {
+ arelent_chain *chain = section->constructor_chain;
+ for (count = 0; count < section->reloc_count; count++)
+ {
+ *relptr++ = &chain->relent;
+ chain = chain->next;
+ }
+ }
+ else
+ {
+ if (section->relocation == NULL
+ && ! b_out_slurp_reloc_table (abfd, section, symbols))
+ return -1;
+
+ tblptr = section->relocation;
+ for (count = 0; count++ < section->reloc_count;)
+ *relptr++ = tblptr++;
+ }
+
+ *relptr = NULL;
+
+ return section->reloc_count;
+}
+
+static long
+b_out_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ if (bfd_get_format (abfd) != bfd_object) {
+ 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 / sizeof (struct relocation_info))
+ +1));
+
+ if (asect == obj_textsec (abfd))
+ return (sizeof (arelent *) *
+ ((exec_hdr(abfd)->a_trsize / sizeof (struct relocation_info))
+ +1));
+
+ if (asect == obj_bsssec (abfd))
+ return 0;
+
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+}
+
+static boolean
+b_out_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) { /* set by bfd.c handler */
+ if (! aout_32_make_sections (abfd))
+ return false;
+
+ obj_textsec (abfd)->filepos = sizeof(struct internal_exec);
+ obj_datasec(abfd)->filepos = obj_textsec(abfd)->filepos
+ + obj_textsec (abfd)->_raw_size;
+
+ }
+ /* regardless, once we know what we're doing, we might as well get going */
+ if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
+ return false;
+
+ if (count != 0) {
+ return (bfd_write ((PTR)location, 1, count, abfd) == count) ?true:false;
+ }
+ return true;
+}
+
+static boolean
+b_out_set_arch_mach (abfd, arch, machine)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ bfd_default_set_arch_mach(abfd, arch, machine);
+
+ if (arch == bfd_arch_unknown) /* Unknown machine arch is OK */
+ return true;
+ if (arch == bfd_arch_i960) /* i960 default is OK */
+ switch (machine) {
+ case bfd_mach_i960_core:
+ case bfd_mach_i960_kb_sb:
+ case bfd_mach_i960_mc:
+ case bfd_mach_i960_xa:
+ case bfd_mach_i960_ca:
+ case bfd_mach_i960_ka_sa:
+ case bfd_mach_i960_jx:
+ case bfd_mach_i960_hx:
+ case 0:
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
+static int
+b_out_sizeof_headers (ignore_abfd, ignore)
+ bfd *ignore_abfd;
+ boolean ignore;
+{
+ return sizeof(struct internal_exec);
+}
+
+
+
+/************************************************************************/
+static bfd_vma
+get_value (reloc, link_info, input_section)
+ arelent *reloc;
+ struct bfd_link_info *link_info;
+ asection *input_section;
+{
+ bfd_vma value;
+ asymbol *symbol = *(reloc->sym_ptr_ptr);
+
+ /* A symbol holds a pointer to a section, and an offset from the
+ base of the section. To relocate, we find where the section will
+ live in the output and add that in */
+
+ if (bfd_is_und_section (symbol->section))
+ {
+ struct bfd_link_hash_entry *h;
+
+ /* The symbol is undefined in this BFD. Look it up in the
+ global linker hash table. FIXME: This should be changed when
+ we convert b.out to use a specific final_link function and
+ change the interface to bfd_relax_section to not require the
+ generic symbols. */
+ h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
+ bfd_asymbol_name (symbol),
+ false, false, true);
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak))
+ value = h->u.def.value + output_addr (h->u.def.section);
+ else if (h != (struct bfd_link_hash_entry *) NULL
+ && h->type == bfd_link_hash_common)
+ value = h->u.c.size;
+ else
+ {
+ if (! ((*link_info->callbacks->undefined_symbol)
+ (link_info, bfd_asymbol_name (symbol),
+ input_section->owner, input_section, reloc->address)))
+ abort ();
+ value = 0;
+ }
+ }
+ else
+ {
+ value = symbol->value + output_addr (symbol->section);
+ }
+
+ /* Add the value contained in the relocation */
+ value += reloc->addend;
+
+ return value;
+}
+
+static void
+perform_slip (abfd, slip, input_section, value)
+ bfd *abfd;
+ unsigned int slip;
+ asection *input_section;
+ bfd_vma value;
+{
+ asymbol **s;
+
+ s = _bfd_generic_link_get_symbols (abfd);
+ BFD_ASSERT (s != (asymbol **) NULL);
+
+ /* Find all symbols past this point, and make them know
+ what's happened */
+ while (*s)
+ {
+ asymbol *p = *s;
+ if (p->section == input_section)
+ {
+ /* This was pointing into this section, so mangle it */
+ if (p->value > value)
+ {
+ p->value -=slip;
+ if (p->udata.p != NULL)
+ {
+ struct generic_link_hash_entry *h;
+
+ h = (struct generic_link_hash_entry *) p->udata.p;
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined);
+ h->root.u.def.value -= slip;
+ BFD_ASSERT (h->root.u.def.value == p->value);
+ }
+ }
+ }
+ s++;
+
+ }
+}
+
+/* This routine works out if the thing we want to get to can be
+ reached with a 24bit offset instead of a 32 bit one.
+ If it can, then it changes the amode */
+
+static int
+abs32code (abfd, input_section, r, shrink, link_info)
+ bfd *abfd;
+ asection *input_section;
+ arelent *r;
+ unsigned int shrink;
+ struct bfd_link_info *link_info;
+{
+ bfd_vma value = get_value (r, link_info, input_section);
+ bfd_vma dot = output_addr (input_section) + r->address;
+ bfd_vma gap;
+
+ /* See if the address we're looking at within 2^23 bytes of where
+ we are, if so then we can use a small branch rather than the
+ jump we were going to */
+
+ gap = value - (dot - shrink);
+
+
+ if (-1<<23 < (long)gap && (long)gap < 1<<23 )
+ {
+ /* Change the reloc type from 32bitcode possible 24, to 24bit
+ possible 32 */
+
+ r->howto = &howto_reloc_abs32codeshrunk;
+ /* The place to relc moves back by four bytes */
+ r->address -=4;
+
+ /* This will be four bytes smaller in the long run */
+ shrink += 4 ;
+ perform_slip (abfd, 4, input_section, r->address-shrink + 4);
+ }
+ return shrink;
+}
+
+static int
+aligncode (abfd, input_section, r, shrink)
+ bfd *abfd;
+ asection *input_section;
+ arelent *r;
+ unsigned int shrink;
+{
+ bfd_vma dot = output_addr (input_section) + r->address;
+ bfd_vma gap;
+ bfd_vma old_end;
+ bfd_vma new_end;
+ int shrink_delta;
+ int size = r->howto->size;
+
+ /* Reduce the size of the alignment so that it's still aligned but
+ smaller - the current size is already the same size as or bigger
+ than the alignment required. */
+
+ /* calculate the first byte following the padding before we optimize */
+ old_end = ((dot + size ) & ~size) + size+1;
+ /* work out where the new end will be - remember that we're smaller
+ than we used to be */
+ new_end = ((dot - shrink + size) & ~size);
+
+ /* This is the new end */
+ gap = old_end - ((dot + size) & ~size);
+
+ shrink_delta = (old_end - new_end) - shrink;
+
+ if (shrink_delta)
+ {
+ /* Change the reloc so that it knows how far to align to */
+ r->howto = howto_done_align_table + (r->howto - howto_align_table);
+
+ /* Encode the stuff into the addend - for future use we need to
+ know how big the reloc used to be */
+ r->addend = old_end - dot + r->address;
+
+ /* This will be N bytes smaller in the long run, adjust all the symbols */
+ perform_slip (abfd, shrink_delta, input_section, r->address - shrink);
+ shrink += shrink_delta;
+ }
+ return shrink;
+}
+
+static boolean
+b_out_bfd_relax_section (abfd, i, link_info, again)
+ bfd *abfd;
+ asection *i;
+ struct bfd_link_info *link_info;
+ boolean *again;
+{
+ /* Get enough memory to hold the stuff */
+ bfd *input_bfd = i->owner;
+ asection *input_section = i;
+ int shrink = 0 ;
+ arelent **reloc_vector = NULL;
+ long reloc_size = bfd_get_reloc_upper_bound(input_bfd,
+ input_section);
+
+ if (reloc_size < 0)
+ return false;
+
+ /* We only run this relaxation once. It might work to run it
+ multiple times, but it hasn't been tested. */
+ *again = false;
+
+ if (reloc_size)
+ {
+ long reloc_count;
+
+ reloc_vector = (arelent **) bfd_malloc (reloc_size);
+ if (reloc_vector == NULL && reloc_size != 0)
+ goto error_return;
+
+ /* Get the relocs and think about them */
+ reloc_count =
+ bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
+ _bfd_generic_link_get_symbols (input_bfd));
+ if (reloc_count < 0)
+ goto error_return;
+ if (reloc_count > 0)
+ {
+ arelent **parent;
+ for (parent = reloc_vector; *parent; parent++)
+ {
+ arelent *r = *parent;
+ switch (r->howto->type)
+ {
+ case ALIGNER:
+ /* An alignment reloc */
+ shrink = aligncode (abfd, input_section, r, shrink);
+ break;
+ case ABS32CODE:
+ /* A 32bit reloc in an addressing mode */
+ shrink = abs32code (input_bfd, input_section, r, shrink,
+ link_info);
+ break;
+ case ABS32CODE_SHRUNK:
+ shrink+=4;
+ break;
+ }
+ }
+ }
+ }
+ input_section->_cooked_size = input_section->_raw_size - shrink;
+
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return true;
+ error_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return false;
+}
+
+static bfd_byte *
+b_out_bfd_get_relocated_section_contents (in_abfd, link_info, link_order,
+ data, relocateable, symbols)
+ bfd *in_abfd;
+ struct bfd_link_info *link_info;
+ struct bfd_link_order *link_order;
+ bfd_byte *data;
+ boolean relocateable;
+ asymbol **symbols;
+{
+ /* Get enough memory to hold the stuff */
+ 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;
+
+ /* If producing relocateable output, don't bother to relax. */
+ if (relocateable)
+ return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
+ link_order,
+ data, relocateable,
+ symbols);
+
+ reloc_vector = (arelent **) bfd_malloc (reloc_size);
+ if (reloc_vector == NULL && reloc_size != 0)
+ goto error_return;
+
+ input_section->reloc_done = 1;
+
+ /* read in the section */
+ BFD_ASSERT (true == bfd_get_section_contents(input_bfd,
+ input_section,
+ data,
+ 0,
+ input_section->_raw_size));
+
+ 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 = reloc_vector;
+ arelent *reloc ;
+
+ unsigned int dst_address = 0;
+ unsigned int src_address = 0;
+ unsigned int run;
+ unsigned int idx;
+
+ /* Find how long a run we can do */
+ while (dst_address < link_order->size)
+ {
+ reloc = *parent;
+ if (reloc)
+ {
+ /* Note that the relaxing didn't tie up the addresses in the
+ relocation, so we use the original address to work out the
+ run of non-relocated data */
+ BFD_ASSERT (reloc->address >= src_address);
+ run = reloc->address - src_address;
+ parent++;
+ }
+ else
+ {
+ run = link_order->size - dst_address;
+ }
+ /* Copy the bytes */
+ for (idx = 0; idx < run; idx++)
+ {
+ data[dst_address++] = data[src_address++];
+ }
+
+ /* Now do the relocation */
+
+ if (reloc)
+ {
+ switch (reloc->howto->type)
+ {
+ case ABS32CODE:
+ calljx_callback (in_abfd, link_info, reloc,
+ src_address + data, dst_address + data,
+ input_section);
+ src_address+=4;
+ dst_address+=4;
+ break;
+ case ABS32:
+ bfd_put_32(in_abfd,
+ (bfd_get_32 (in_abfd, data+src_address)
+ + get_value (reloc, link_info, input_section)),
+ data+dst_address);
+ src_address+=4;
+ dst_address+=4;
+ break;
+ case CALLJ:
+ callj_callback (in_abfd, link_info, reloc, data, src_address,
+ dst_address, input_section, false);
+ src_address+=4;
+ dst_address+=4;
+ break;
+ case ALIGNDONE:
+ BFD_ASSERT (reloc->addend >= src_address);
+ BFD_ASSERT (reloc->addend <= input_section->_raw_size);
+ src_address = reloc->addend;
+ dst_address = ((dst_address + reloc->howto->size)
+ & ~reloc->howto->size);
+ break;
+ case ABS32CODE_SHRUNK:
+ /* This used to be a callx, but we've found out that a
+ callj will reach, so do the right thing. */
+ callj_callback (in_abfd, link_info, reloc, data,
+ src_address + 4, dst_address, input_section,
+ true);
+ dst_address+=4;
+ src_address+=8;
+ break;
+ case PCREL24:
+ {
+ long int word = bfd_get_32(in_abfd, data+src_address);
+ bfd_vma value;
+
+ value = get_value (reloc, link_info, input_section);
+ word = ((word & ~BAL_MASK)
+ | (((word & BAL_MASK)
+ + value
+ - output_addr (input_section)
+ + reloc->addend)
+ & BAL_MASK));
+
+ bfd_put_32(in_abfd,word, data+dst_address);
+ dst_address+=4;
+ src_address+=4;
+
+ }
+ break;
+
+ case PCREL13:
+ {
+ long int word = bfd_get_32(in_abfd, data+src_address);
+ bfd_vma value;
+
+ value = get_value (reloc, link_info, input_section);
+ word = ((word & ~PCREL13_MASK)
+ | (((word & PCREL13_MASK)
+ + value
+ + reloc->addend
+ - output_addr (input_section))
+ & PCREL13_MASK));
+
+ bfd_put_32(in_abfd,word, data+dst_address);
+ dst_address+=4;
+ src_address+=4;
+
+ }
+ break;
+
+ default:
+ abort();
+ }
+ }
+ }
+ }
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return data;
+ error_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return NULL;
+}
+/***********************************************************************/
+
+/* Build the transfer vectors for Big and Little-Endian B.OUT files. */
+
+#define aout_32_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
+
+#define b_out_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define b_out_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define b_out_bfd_final_link _bfd_generic_final_link
+#define b_out_bfd_link_split_section _bfd_generic_link_split_section
+
+#define aout_32_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+const bfd_target b_out_vec_big_host =
+{
+ "b.out.big", /* name */
+ bfd_target_aout_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_BIG, /* hdr byte order is big */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* symbol leading char */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* 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, b_out_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, b_out_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, b_out_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (aout_32),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
+ BFD_JUMP_TABLE_SYMBOLS (aout_32),
+ BFD_JUMP_TABLE_RELOCS (b_out),
+ BFD_JUMP_TABLE_WRITE (b_out),
+ BFD_JUMP_TABLE_LINK (b_out),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0,
+};
+
+
+const bfd_target b_out_vec_little_host =
+{
+ "b.out.little", /* name */
+ bfd_target_aout_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* symbol leading char */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, b_out_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, b_out_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, b_out_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (aout_32),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
+ BFD_JUMP_TABLE_SYMBOLS (aout_32),
+ BFD_JUMP_TABLE_RELOCS (b_out),
+ BFD_JUMP_TABLE_WRITE (b_out),
+ BFD_JUMP_TABLE_LINK (b_out),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/cache.c b/contrib/gdb/bfd/cache.c
new file mode 100644
index 0000000..ef15877
--- /dev/null
+++ b/contrib/gdb/bfd/cache.c
@@ -0,0 +1,347 @@
+/* BFD library -- caching of file descriptors.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ File caching
+
+ The file caching mechanism is embedded within BFD and allows
+ the application to open as many BFDs as it wants without
+ regard to the underlying operating system's file descriptor
+ limit (often as low as 20 open files). The module in
+ <<cache.c>> maintains a least recently used list of
+ <<BFD_CACHE_MAX_OPEN>> files, and exports the name
+ <<bfd_cache_lookup>>, 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.
+
+*/
+
+#include "bfd.h"
+#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
+
+DESCRIPTION
+ The maximum number of files which the cache will keep open at
+ one time.
+
+.#define BFD_CACHE_MAX_OPEN 10
+
+*/
+
+/* The number of BFD files we have open. */
+
+static int open_files;
+
+/*
+INTERNAL_FUNCTION
+ bfd_last_cache
+
+SYNOPSIS
+ extern bfd *bfd_last_cache;
+
+DESCRIPTION
+ Zero, or a pointer to the topmost BFD on the chain. This is
+ used by the <<bfd_cache_lookup>> macro in @file{libbfd.h} to
+ determine when it can avoid a function call.
+*/
+
+bfd *bfd_last_cache;
+
+/*
+ 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))
+
+
+ */
+
+/* Insert a BFD into the cache. */
+
+static INLINE void
+insert (abfd)
+ bfd *abfd;
+{
+ if (bfd_last_cache == NULL)
+ {
+ abfd->lru_next = abfd;
+ abfd->lru_prev = abfd;
+ }
+ 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;
+}
+
+/* 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 (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
+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)
+ ret = true;
+ else
+ {
+ ret = false;
+ bfd_set_error (bfd_error_system_call);
+ }
+
+ snip (abfd);
+
+ abfd->iostream = NULL;
+ --open_files;
+
+ return ret;
+}
+
+/*
+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)
+ {
+ if (! close_one ())
+ return false;
+ }
+ insert (abfd);
+ ++open_files;
+ return true;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_cache_close
+
+SYNOPSIS
+ 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
+ <<false>> is returned if closing the file fails, <<true>> is
+ returned if all is well.
+*/
+
+boolean
+bfd_cache_close (abfd)
+ bfd *abfd;
+{
+ if (abfd->iostream == NULL
+ || (abfd->flags & BFD_IN_MEMORY) != 0)
+ return true;
+
+ return bfd_cache_delete (abfd);
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_open_file
+
+SYNOPSIS
+ FILE* bfd_open_file(bfd *abfd);
+
+DESCRIPTION
+ Call the OS to open a file for @var{abfd}. Return the <<FILE *>>
+ (possibly <<NULL>>) that results from this operation. Set up the
+ BFD so that future accesses know the file is open. If the <<FILE *>>
+ returned is <<NULL>>, then it won't have been put in the
+ cache, so it won't have to be removed from it.
+*/
+
+FILE *
+bfd_open_file (abfd)
+ bfd *abfd;
+{
+ abfd->cacheable = true; /* Allow it to be closed later. */
+
+ if (open_files >= BFD_CACHE_MAX_OPEN)
+ {
+ if (! close_one ())
+ return NULL;
+ }
+
+ switch (abfd->direction)
+ {
+ case read_direction:
+ case no_direction:
+ abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RB);
+ break;
+ case both_direction:
+ case write_direction:
+ if (abfd->opened_once == true)
+ {
+ abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_RUB);
+ if (abfd->iostream == NULL)
+ abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WUB);
+ }
+ else
+ {
+ /*open for creat */
+ abfd->iostream = (PTR) fopen (abfd->filename, FOPEN_WB);
+ abfd->opened_once = true;
+ }
+ break;
+ }
+
+ 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 <<bfd_cache_lookup>> fails to find a
+ quick answer. Find a file descriptor for @var{abfd}. If
+ necessary, it open it. If there are already more than
+ <<BFD_CACHE_MAX_OPEN>> files open, it tries to close one first, to
+ avoid running out of file descriptors.
+*/
+
+FILE *
+bfd_cache_lookup_worker (abfd)
+ bfd *abfd;
+{
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ abort ();
+
+ if (abfd->my_archive)
+ abfd = abfd->my_archive;
+
+ if (abfd->iostream != NULL)
+ {
+ /* Move the file to the start of the cache. */
+ if (abfd != bfd_last_cache)
+ {
+ snip (abfd);
+ insert (abfd);
+ }
+ }
+ else
+ {
+ if (bfd_open_file (abfd) == NULL)
+ return NULL;
+ if (fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0)
+ return NULL;
+ }
+
+ return (FILE *) abfd->iostream;
+}
diff --git a/contrib/gdb/bfd/cf-i386lynx.c b/contrib/gdb/bfd/cf-i386lynx.c
new file mode 100644
index 0000000..2a14bde
--- /dev/null
+++ b/contrib/gdb/bfd/cf-i386lynx.c
@@ -0,0 +1,31 @@
+/* BFD back-end for Intel 386 COFF LynxOS files.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM i386lynx_coff_vec
+#define TARGET_NAME "coff-i386-lynx"
+
+#define LYNXOS
+
+#define COFF_LONG_FILENAMES
+
+#include "coff-i386.c"
diff --git a/contrib/gdb/bfd/cf-m68klynx.c b/contrib/gdb/bfd/cf-m68klynx.c
new file mode 100644
index 0000000..8149dc6
--- /dev/null
+++ b/contrib/gdb/bfd/cf-m68klynx.c
@@ -0,0 +1,223 @@
+/* BFD back-end for Motorola M68K COFF LynxOS files.
+ Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_SYM m68klynx_coff_vec
+#define TARGET_NAME "coff-m68k-lynx"
+
+#define LYNXOS
+
+#define COFF_LONG_FILENAMES
+
+#define _bfd_m68kcoff_howto_table _bfd_m68klynx_howto_table
+#define _bfd_m68kcoff_rtype2howto _bfd_m68klynx_rtype2howto
+#define _bfd_m68kcoff_howto2rtype _bfd_m68klynx_howto2rtype
+#define _bfd_m68kcoff_reloc_type_lookup _bfd_m68klynx_reloc_type_lookup
+
+#define LYNX_SPECIAL_FN _bfd_m68klynx_special_fn
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#ifdef ANSI_PROTOTYPES
+struct internal_reloc;
+struct coff_link_hash_entry;
+struct internal_syment;
+#endif
+
+static bfd_reloc_status_type _bfd_m68klynx_special_fn
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static reloc_howto_type *coff_m68k_lynx_rtype_to_howto
+ PARAMS ((bfd *, asection *, struct internal_reloc *,
+ struct coff_link_hash_entry *, struct internal_syment *,
+ bfd_vma *));
+
+/* For some reason when using m68k COFF the value stored in the .text
+ section for a reference to a common symbol is the value itself plus
+ any desired offset. (taken from work done by Ian Taylor, Cygnus Support,
+ for I386 COFF). */
+
+/* If we are producing relocateable output, we need to do some
+ adjustments to the object file that are not done by the
+ bfd_perform_relocation function. This function is called by every
+ reloc type to make any required adjustments. */
+
+static bfd_reloc_status_type
+_bfd_m68klynx_special_fn (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ symvalue diff;
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ /* We are relocating a common symbol. The current value in the
+ object file is ORIG + OFFSET, where ORIG is the value of the
+ common symbol as seen by the object file when it was compiled
+ (this may be zero if the symbol was undefined) and OFFSET is
+ the offset into the common symbol (normally zero, but may be
+ non-zero when referring to a field in a common structure).
+ ORIG is the negative of reloc_entry->addend, which is set by
+ the CALC_ADDEND macro below. We want to replace the value in
+ the object file with NEW + OFFSET, where NEW is the value of
+ the common symbol which we are going to put in the final
+ object file. NEW is symbol->value. */
+ diff = symbol->value + reloc_entry->addend;
+ }
+ else
+ {
+ /* For some reason bfd_perform_relocation always effectively
+ ignores the addend for a COFF target when producing
+ relocateable output. This seems to be always wrong for 386
+ COFF, so we handle the addend here instead. */
+ diff = reloc_entry->addend;
+ }
+
+#define DOIT(x) \
+ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
+
+ if (diff != 0)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+ unsigned char *addr = (unsigned char *) data + reloc_entry->address;
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, addr);
+ DOIT (x);
+ bfd_put_8 (abfd, x, addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_get_16 (abfd, addr);
+ DOIT (x);
+ bfd_put_16 (abfd, x, addr);
+ }
+ break;
+
+ case 2:
+ {
+ long x = bfd_get_32 (abfd, addr);
+ DOIT (x);
+ bfd_put_32 (abfd, x, addr);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ /* Now let bfd_perform_relocation finish everything up. */
+ return bfd_reloc_continue;
+}
+/* Compute the addend of a reloc. If the reloc is to a common symbol,
+ the object file contains the value of the common symbol. By the
+ time this is called, the linker may be using a different symbol
+ from a different object file with a different value. Therefore, we
+ hack wildly to locate the original symbol from this file so that we
+ can make the correct adjustment. This macro sets coffsym to the
+ symbol from the original file, and uses it to set the addend value
+ correctly. If this is not a common symbol, the usual addend
+ calculation is done, except that an additional tweak is needed for
+ PC relative relocs.
+ FIXME: This macro refers to symbols and asect; these are from the
+ calling function, not the macro arguments. */
+
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = - coffsym->native->u.syment.n_value; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ if (ptr && (reloc.r_type == R_PCRBYTE \
+ || reloc.r_type == R_PCRWORD \
+ || reloc.r_type == R_PCRLONG)) \
+ cache_ptr->addend += asect->vma; \
+ }
+
+#define coff_rtype_to_howto coff_m68k_lynx_rtype_to_howto
+
+#include "coff-m68k.c"
+
+/* coff-m68k.c uses the special COFF backend linker. We need to
+ adjust common symbols.
+
+ We can't define this function until after we have included
+ coff-m68k.c, because it uses RTYPE2HOWTO. */
+
+/*ARGSUSED*/
+static reloc_howto_type *
+coff_m68k_lynx_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+ arelent relent;
+ reloc_howto_type *howto;
+
+ RTYPE2HOWTO (&relent, rel);
+
+ howto = relent.howto;
+
+ if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
+ {
+ /* This is a common symbol. The section contents include the
+ size (sym->n_value) as an addend. The relocate_section
+ function will be adding in the final value of the symbol. We
+ need to subtract out the current size in order to get the
+ correct result. */
+ BFD_ASSERT (h != NULL);
+ *addendp -= sym->n_value;
+ }
+
+ /* If the output symbol is common (in which case this must be a
+ relocateable link), we need to add in the final size of the
+ common symbol. */
+ if (h != NULL && h->root.type == bfd_link_hash_common)
+ *addendp += h->root.u.c.size;
+
+ return howto;
+}
diff --git a/contrib/gdb/bfd/cf-sparclynx.c b/contrib/gdb/bfd/cf-sparclynx.c
new file mode 100644
index 0000000..774a099
--- /dev/null
+++ b/contrib/gdb/bfd/cf-sparclynx.c
@@ -0,0 +1,28 @@
+/* BFD back-end for Sparc COFF LynxOS files.
+ Copyright 1993 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_SYM sparclynx_coff_vec
+#define TARGET_NAME "coff-sparc-lynx"
+
+#define LYNXOS
+
+#define COFF_LONG_FILENAMES
+
+#include "coff-sparc.c"
diff --git a/contrib/gdb/bfd/cisco-core.c b/contrib/gdb/bfd/cisco-core.c
new file mode 100644
index 0000000..a25115c
--- /dev/null
+++ b/contrib/gdb/bfd/cisco-core.c
@@ -0,0 +1,313 @@
+/* BFD back-end for CISCO crash dumps.
+
+Copyright 1994 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+/* core_file_failing_signal returns a host signal (this probably should
+ be fixed). */
+#include <signal.h>
+
+#define CRASH_INFO (0xffc)
+#define CRASH_MAGIC 0xdead1234
+
+typedef enum {
+ CRASH_REASON_NOTCRASHED = 0,
+ CRASH_REASON_EXCEPTION = 1,
+ CRASH_REASON_CORRUPT = 2,
+ } crashreason;
+
+struct crashinfo_external
+{
+ char magic[4]; /* Magic number */
+ char version[4]; /* Version number */
+ char reason[4]; /* Crash reason */
+ char cpu_vector[4]; /* CPU vector for exceptions */
+ char registers[4]; /* Pointer to saved registers */
+ char rambase[4]; /* Base of RAM (not in V1 crash info) */
+};
+
+struct cisco_core_struct
+{
+ int sig;
+};
+
+static const bfd_target *
+cisco_core_file_p (abfd)
+ bfd *abfd;
+{
+ char buf[4];
+ unsigned int crashinfo_offset;
+ struct crashinfo_external crashinfo;
+ int nread;
+ unsigned int rambase;
+ sec_ptr asect;
+ struct stat statbuf;
+
+ if (bfd_seek (abfd, CRASH_INFO, SEEK_SET) != 0)
+ return NULL;
+
+ nread = bfd_read (buf, 1, 4, abfd);
+ if (nread != 4)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ crashinfo_offset = bfd_get_32 (abfd, buf);
+
+ if (bfd_seek (abfd, crashinfo_offset, SEEK_SET) != 0)
+ return NULL;
+
+ nread = bfd_read (&crashinfo, 1, sizeof (crashinfo), abfd);
+ if (nread != sizeof (crashinfo))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (bfd_stat (abfd, &statbuf) < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return NULL;
+ }
+
+ if (bfd_get_32 (abfd, crashinfo.magic) != CRASH_MAGIC)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ switch (bfd_get_32 (abfd, crashinfo.version))
+ {
+ case 0:
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ case 1:
+ rambase = 0;
+ break;
+ default:
+ case 2:
+ rambase = bfd_get_32 (abfd, crashinfo.rambase);
+ break;
+ }
+
+ /* OK, we believe you. You're a core file. */
+
+ abfd->tdata.cisco_core_data =
+ ((struct cisco_core_struct *)
+ bfd_zmalloc (sizeof (struct cisco_core_struct)));
+ if (abfd->tdata.cisco_core_data == NULL)
+ return NULL;
+
+ switch ((crashreason) bfd_get_32 (abfd, crashinfo.reason))
+ {
+ case CRASH_REASON_NOTCRASHED:
+ /* Crash file probably came from write core. */
+ abfd->tdata.cisco_core_data->sig = 0;
+ break;
+ case CRASH_REASON_CORRUPT:
+ /* The crash context area was corrupt -- proceed with caution.
+ We have no way of passing this information back to the caller. */
+ abfd->tdata.cisco_core_data->sig = 0;
+ break;
+ case CRASH_REASON_EXCEPTION:
+ /* Crash occured due to CPU exception. */
+
+ /* This is 68k-specific; for MIPS we'll need to interpret
+ cpu_vector differently based on the target configuration
+ (since CISCO core files don't seem to have the processor
+ encoded in them). */
+
+ switch (bfd_get_32 (abfd, crashinfo.cpu_vector))
+ {
+ /* bus error */
+ case 2 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
+ /* address error */
+ case 3 : abfd->tdata.cisco_core_data->sig = SIGBUS; break;
+ /* illegal instruction */
+ case 4 : abfd->tdata.cisco_core_data->sig = SIGILL; break;
+ /* zero divide */
+ case 5 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* chk instruction */
+ case 6 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* trapv instruction */
+ case 7 : abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* privilege violation */
+ case 8 : abfd->tdata.cisco_core_data->sig = SIGSEGV; break;
+ /* trace trap */
+ case 9 : abfd->tdata.cisco_core_data->sig = SIGTRAP; break;
+ /* line 1010 emulator */
+ case 10: abfd->tdata.cisco_core_data->sig = SIGILL; break;
+ /* line 1111 emulator */
+ case 11: abfd->tdata.cisco_core_data->sig = SIGILL; break;
+
+ /* Coprocessor protocol violation. Using a standard MMU or FPU
+ this cannot be triggered by software. Call it a SIGBUS. */
+ case 13: abfd->tdata.cisco_core_data->sig = SIGBUS; break;
+
+ /* interrupt */
+ case 31: abfd->tdata.cisco_core_data->sig = SIGINT; break;
+ /* breakpoint */
+ case 33: abfd->tdata.cisco_core_data->sig = SIGTRAP; break;
+
+ /* floating point err */
+ case 48: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* floating point err */
+ case 49: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* zero divide */
+ case 50: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* underflow */
+ case 51: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* operand error */
+ case 52: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* overflow */
+ case 53: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ /* NAN */
+ case 54: abfd->tdata.cisco_core_data->sig = SIGFPE; break;
+ default:
+ /* "software generated"*/
+ abfd->tdata.cisco_core_data->sig = SIGEMT;
+ }
+ break;
+ default:
+ /* Unknown crash reason. */
+ abfd->tdata.cisco_core_data->sig = 0;
+ break;
+ }
+
+ abfd->sections = NULL;
+ abfd->section_count = 0;
+
+ asect = (asection *) bfd_zmalloc (sizeof (asection));
+ if (asect == NULL)
+ goto error_return;
+ asect->name = ".reg";
+ asect->flags = SEC_HAS_CONTENTS;
+ /* This can be bigger than the real size. Set it to the size of the whole
+ core file. */
+ asect->_raw_size = statbuf.st_size;
+ asect->vma = 0;
+ asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase;
+ asect->next = abfd->sections;
+ abfd->sections = asect;
+ ++abfd->section_count;
+
+ /* There is only one section containing data from the target system's RAM.
+ We call it .data. */
+ asect = (asection *) bfd_zmalloc (sizeof (asection));
+ if (asect == NULL)
+ goto error_return;
+ asect->name = ".data";
+ asect->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
+ /* The size of memory is the size of the core file itself. */
+ asect->_raw_size = statbuf.st_size;
+ asect->vma = rambase;
+ asect->filepos = 0;
+ asect->next = abfd->sections;
+ abfd->sections = asect;
+ ++abfd->section_count;
+
+ return abfd->xvec;
+
+ error_return:
+ {
+ sec_ptr nextsect;
+ for (asect = abfd->sections; asect != NULL;)
+ {
+ nextsect = asect->next;
+ free (asect);
+ asect = nextsect;
+ }
+ free (abfd->tdata.cisco_core_data);
+ return NULL;
+ }
+}
+
+char *
+cisco_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return NULL;
+}
+
+int
+cisco_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return abfd->tdata.cisco_core_data->sig;
+}
+
+boolean
+cisco_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd;
+ bfd *exec_bfd;
+{
+ return true;
+}
+
+const bfd_target cisco_core_vec =
+ {
+ "trad-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ 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 */
+ 16, /* ar_max_namelen */
+ 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_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ cisco_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (cisco),
+ 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/contrib/gdb/bfd/coff-a29k.c b/contrib/gdb/bfd/coff-a29k.c
new file mode 100644
index 0000000..3ceabfb
--- /dev/null
+++ b/contrib/gdb/bfd/coff-a29k.c
@@ -0,0 +1,641 @@
+/* BFD back-end for AMD 29000 COFF binaries.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by David Wood at New York University 7/8/91.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define A29K 1
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/a29k.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+static long get_symbol_value PARAMS ((asymbol *));
+static bfd_reloc_status_type a29k_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static boolean coff_a29k_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
+static boolean coff_a29k_adjust_symndx
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
+ struct internal_reloc *, boolean *));
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
+
+#define INSERT_HWORD(WORD,HWORD) \
+ (((WORD) & 0xff00ff00) | (((HWORD) & 0xff00) << 8) | ((HWORD)& 0xff))
+#define EXTRACT_HWORD(WORD) \
+ ((((WORD) & 0x00ff0000) >> 8) | ((WORD)& 0xff))
+#define SIGN_EXTEND_HWORD(HWORD) \
+ ((HWORD) & 0x8000 ? (HWORD)|(~0xffffL) : (HWORD))
+
+/* Provided the symbol, returns the value reffed */
+static long
+get_symbol_value (symbol)
+ asymbol *symbol;
+{
+ long relocation = 0;
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ relocation = 0;
+ }
+ else
+ {
+ relocation = symbol->value +
+ symbol->section->output_section->vma +
+ symbol->section->output_offset;
+ }
+
+ return(relocation);
+}
+
+/* this function is in charge of performing all the 29k relocations */
+
+static bfd_reloc_status_type
+a29k_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol_in;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* the consth relocation comes in two parts, we have to remember
+ the state between calls, in these variables */
+ static boolean part1_consth_active = false;
+ static unsigned long part1_consth_value;
+
+ unsigned long insn;
+ unsigned long sym_value;
+ unsigned long unsigned_value;
+ unsigned short r_type;
+ long signed_value;
+
+ unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
+ bfd_byte *hit_data =addr + (bfd_byte *)(data);
+
+ r_type = reloc_entry->howto->type;
+
+ if (output_bfd) {
+ /* Partial linking - do nothing */
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+
+ }
+
+ if (symbol_in != NULL
+ && bfd_is_und_section (symbol_in->section))
+ {
+ /* Keep the state machine happy in case we're called again */
+ if (r_type == R_IHIHALF)
+ {
+ part1_consth_active = true;
+ part1_consth_value = 0;
+ }
+ return(bfd_reloc_undefined);
+ }
+
+ if ((part1_consth_active) && (r_type != R_IHCONST))
+ {
+ part1_consth_active = false;
+ *error_message = (char *) "Missing IHCONST";
+ return(bfd_reloc_dangerous);
+ }
+
+
+ sym_value = get_symbol_value(symbol_in);
+
+ switch (r_type)
+ {
+ case R_IREL:
+ insn = bfd_get_32(abfd, hit_data);
+ /* Take the value in the field and sign extend it */
+ signed_value = EXTRACT_HWORD(insn);
+ signed_value = SIGN_EXTEND_HWORD(signed_value);
+ signed_value <<= 2;
+
+ /* See the note on the R_IREL reloc in coff_a29k_relocate_section. */
+ if (signed_value == - (long) reloc_entry->address)
+ signed_value = 0;
+
+ signed_value += sym_value + reloc_entry->addend;
+ if ((signed_value & ~0x3ffff) == 0)
+ { /* Absolute jmp/call */
+ insn |= (1<<24); /* Make it absolute */
+ /* FIXME: Should we change r_type to R_IABS */
+ }
+ else
+ {
+ /* Relative jmp/call, so subtract from the value the
+ address of the place we're coming from */
+ signed_value -= (reloc_entry->address
+ + input_section->output_section->vma
+ + input_section->output_offset);
+ if (signed_value>0x1ffff || signed_value<-0x20000)
+ return(bfd_reloc_overflow);
+ }
+ signed_value >>= 2;
+ insn = INSERT_HWORD(insn, signed_value);
+ bfd_put_32(abfd, insn ,hit_data);
+ break;
+ case R_ILOHALF:
+ insn = bfd_get_32(abfd, hit_data);
+ unsigned_value = EXTRACT_HWORD(insn);
+ unsigned_value += sym_value + reloc_entry->addend;
+ insn = INSERT_HWORD(insn, unsigned_value);
+ bfd_put_32(abfd, insn, hit_data);
+ break;
+ case R_IHIHALF:
+ insn = bfd_get_32(abfd, hit_data);
+ /* consth, part 1
+ Just get the symbol value that is referenced */
+ part1_consth_active = true;
+ part1_consth_value = sym_value + reloc_entry->addend;
+ /* Don't modify insn until R_IHCONST */
+ break;
+ case R_IHCONST:
+ insn = bfd_get_32(abfd, hit_data);
+ /* consth, part 2
+ Now relocate the reference */
+ if (part1_consth_active == false) {
+ *error_message = (char *) "Missing IHIHALF";
+ return(bfd_reloc_dangerous);
+ }
+ /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */
+ unsigned_value = 0; /*EXTRACT_HWORD(insn) << 16;*/
+ unsigned_value += reloc_entry->addend; /* r_symndx */
+ unsigned_value += part1_consth_value;
+ unsigned_value = unsigned_value >> 16;
+ insn = INSERT_HWORD(insn, unsigned_value);
+ part1_consth_active = false;
+ bfd_put_32(abfd, insn, hit_data);
+ break;
+ case R_BYTE:
+ insn = bfd_get_8(abfd, hit_data);
+ unsigned_value = insn + sym_value + reloc_entry->addend;
+ if (unsigned_value & 0xffffff00)
+ return(bfd_reloc_overflow);
+ bfd_put_8(abfd, unsigned_value, hit_data);
+ break;
+ case R_HWORD:
+ insn = bfd_get_16(abfd, hit_data);
+ unsigned_value = insn + sym_value + reloc_entry->addend;
+ if (unsigned_value & 0xffff0000)
+ return(bfd_reloc_overflow);
+ bfd_put_16(abfd, insn, hit_data);
+ break;
+ case R_WORD:
+ insn = bfd_get_32(abfd, hit_data);
+ insn += sym_value + reloc_entry->addend;
+ bfd_put_32(abfd, insn, hit_data);
+ break;
+ default:
+ *error_message = "Unrecognized reloc";
+ return (bfd_reloc_dangerous);
+ }
+
+
+ return(bfd_reloc_ok);
+}
+
+/* type rightshift
+ size
+ bitsize
+ pc-relative
+ bitpos
+ absolute
+ complain_on_overflow
+ special_function
+ relocation name
+ partial_inplace
+ src_mask
+*/
+
+/*FIXME: I'm not real sure about this table */
+static reloc_howto_type howto_table[] =
+{
+ {R_ABS, 0, 3, 32, false, 0, complain_overflow_bitfield,a29k_reloc,"ABS", true, 0xffffffff,0xffffffff, false},
+ {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10},
+ {11}, {12}, {13}, {14}, {15}, {16}, {17}, {18}, {19}, {20},
+ {21}, {22}, {23},
+ {R_IREL, 0, 3, 32, true, 0, complain_overflow_signed,a29k_reloc,"IREL", true, 0xffffffff,0xffffffff, false},
+ {R_IABS, 0, 3, 32, false, 0, complain_overflow_bitfield, a29k_reloc,"IABS", true, 0xffffffff,0xffffffff, false},
+ {R_ILOHALF, 0, 3, 16, true, 0, complain_overflow_signed, a29k_reloc,"ILOHALF", true, 0x0000ffff,0x0000ffff, false},
+ {R_IHIHALF, 0, 3, 16, true, 16, complain_overflow_signed, a29k_reloc,"IHIHALF", true, 0xffff0000,0xffff0000, false},
+ {R_IHCONST, 0, 3, 16, true, 0, complain_overflow_signed, a29k_reloc,"IHCONST", true, 0xffff0000,0xffff0000, false},
+ {R_BYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, a29k_reloc,"BYTE", true, 0x000000ff,0x000000ff, false},
+ {R_HWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, a29k_reloc,"HWORD", true, 0x0000ffff,0x0000ffff, false},
+ {R_WORD, 0, 2, 32, false, 0, complain_overflow_bitfield, a29k_reloc,"WORD", true, 0xffffffff,0xffffffff, false},
+};
+
+#define BADMAG(x) A29KBADMAG(x)
+
+#define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
+ reloc_processing(relent, reloc, symbols, abfd, section)
+
+static void
+reloc_processing (relent,reloc, symbols, abfd, section)
+ arelent *relent;
+ struct internal_reloc *reloc;
+ asymbol **symbols;
+ bfd *abfd;
+ asection *section;
+{
+ static bfd_vma ihihalf_vaddr = (bfd_vma) -1;
+
+ relent->address = reloc->r_vaddr;
+ relent->howto = howto_table + reloc->r_type;
+ if (reloc->r_type == R_IHCONST)
+ {
+ /* The address of an R_IHCONST should always be the address of
+ the immediately preceding R_IHIHALF. relocs generated by gas
+ are correct, but relocs generated by High C are different (I
+ can't figure out what the address means for High C). We can
+ handle both gas and High C by ignoring the address here, and
+ simply reusing the address saved for R_IHIHALF. */
+ if (ihihalf_vaddr == (bfd_vma) -1)
+ abort ();
+ relent->address = ihihalf_vaddr;
+ ihihalf_vaddr = (bfd_vma) -1;
+ relent->addend = reloc->r_symndx;
+ relent->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
+ }
+ else
+ {
+ asymbol *ptr;
+ relent->sym_ptr_ptr = symbols + obj_convert(abfd)[reloc->r_symndx];
+
+ ptr = *(relent->sym_ptr_ptr);
+
+ if (ptr
+ && bfd_asymbol_bfd(ptr) == abfd
+
+ && ((ptr->flags & BSF_OLD_COMMON)== 0))
+ {
+ relent->addend = 0;
+ }
+ else
+ {
+ relent->addend = 0;
+ }
+ relent->address-= section->vma;
+ if (reloc->r_type == R_IHIHALF)
+ ihihalf_vaddr = relent->address;
+ else if (ihihalf_vaddr != (bfd_vma) -1)
+ abort ();
+ }
+}
+
+/* The reloc processing routine for the optimized COFF linker. */
+
+static boolean
+coff_a29k_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, syms, sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+ boolean hihalf;
+ bfd_vma hihalf_val;
+
+ /* If we are performing a relocateable link, we don't need to do a
+ thing. The caller will take care of adjusting the reloc
+ addresses and symbol indices. */
+ if (info->relocateable)
+ return true;
+
+ hihalf = false;
+ hihalf_val = 0;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ bfd_byte *loc;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ asection *sec;
+ bfd_vma val;
+ boolean overflow;
+ unsigned long insn;
+ long signed_value;
+ unsigned long unsigned_value;
+ bfd_reloc_status_type rstat;
+
+ symndx = rel->r_symndx;
+ loc = contents + rel->r_vaddr - input_section->vma;
+
+ if (symndx == -1)
+ h = NULL;
+ else
+ h = obj_coff_sym_hashes (input_bfd)[symndx];
+
+ sym = NULL;
+ sec = NULL;
+ val = 0;
+
+ /* An R_IHCONST reloc does not have a symbol. Instead, the
+ symbol index is an addend. R_IHCONST is always used in
+ conjunction with R_IHHALF. */
+ if (rel->r_type != R_IHCONST)
+ {
+ if (h == NULL)
+ {
+ if (symndx == -1)
+ sec = bfd_abs_section_ptr;
+ else
+ {
+ sym = syms + symndx;
+ sec = sections[symndx];
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+ }
+ else
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ val = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ if (hihalf)
+ {
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info, "missing IHCONST reloc", input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ hihalf = false;
+ }
+ }
+
+ overflow = false;
+
+ switch (rel->r_type)
+ {
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+
+ case R_IREL:
+ insn = bfd_get_32 (input_bfd, loc);
+
+ /* Extract the addend. */
+ signed_value = EXTRACT_HWORD (insn);
+ signed_value = SIGN_EXTEND_HWORD (signed_value);
+ signed_value <<= 2;
+
+ /* Unfortunately, there are two different versions of COFF
+ a29k. In the original AMD version, the value stored in
+ the field for the R_IREL reloc is a simple addend. In
+ the GNU version, the value is the negative of the address
+ of the reloc within section. We try to cope here by
+ assuming the AMD version, unless the addend is exactly
+ the negative of the address; in the latter case we assume
+ the GNU version. This means that something like
+ .text
+ nop
+ jmp i-4
+ will fail, because the addend of -4 will happen to equal
+ the negative of the address within the section. The
+ compiler will never generate code like this.
+
+ At some point in the future we may want to take out this
+ check. */
+
+ if (signed_value == - (long) (rel->r_vaddr - input_section->vma))
+ signed_value = 0;
+
+ /* Determine the destination of the jump. */
+ signed_value += val;
+
+ if ((signed_value & ~0x3ffff) == 0)
+ {
+ /* We can use an absolute jump. */
+ insn |= (1 << 24);
+ }
+ else
+ {
+ /* Make the destination PC relative. */
+ signed_value -= (input_section->output_section->vma
+ + input_section->output_offset
+ + (rel->r_vaddr - input_section->vma));
+ if (signed_value > 0x1ffff || signed_value < - 0x20000)
+ {
+ overflow = true;
+ signed_value = 0;
+ }
+ }
+
+ /* Put the adjusted value back into the instruction. */
+ signed_value >>= 2;
+ insn = INSERT_HWORD (insn, signed_value);
+
+ bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
+
+ break;
+
+ case R_ILOHALF:
+ insn = bfd_get_32 (input_bfd, loc);
+ unsigned_value = EXTRACT_HWORD (insn);
+ unsigned_value += val;
+ insn = INSERT_HWORD (insn, unsigned_value);
+ bfd_put_32 (input_bfd, insn, loc);
+ break;
+
+ case R_IHIHALF:
+ /* Save the value for the R_IHCONST reloc. */
+ hihalf = true;
+ hihalf_val = val;
+ break;
+
+ case R_IHCONST:
+ if (! hihalf)
+ {
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info, "missing IHIHALF reloc", input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ hihalf_val = 0;
+ }
+
+ insn = bfd_get_32 (input_bfd, loc);
+ unsigned_value = rel->r_symndx + hihalf_val;
+ unsigned_value >>= 16;
+ insn = INSERT_HWORD (insn, unsigned_value);
+ bfd_put_32 (input_bfd, (bfd_vma) insn, loc);
+
+ hihalf = false;
+
+ break;
+
+ case R_BYTE:
+ case R_HWORD:
+ case R_WORD:
+ rstat = _bfd_relocate_contents (howto_table + rel->r_type,
+ input_bfd, val, loc);
+ if (rstat == bfd_reloc_overflow)
+ overflow = true;
+ else if (rstat != bfd_reloc_ok)
+ abort ();
+ break;
+ }
+
+ if (overflow)
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.string;
+ else if (sym == NULL)
+ name = "*unknown*";
+ else if (sym->_n._n_n._n_zeroes == 0
+ && sym->_n._n_n._n_offset != 0)
+ name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
+ else
+ {
+ strncpy (buf, sym->_n._n_name, SYMNMLEN);
+ buf[SYMNMLEN] = '\0';
+ name = buf;
+ }
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto_table[rel->r_type].name, (bfd_vma) 0,
+ input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#define coff_relocate_section coff_a29k_relocate_section
+
+/* We don't want to change the symndx of a R_IHCONST reloc, since it
+ is actually an addend, not a symbol index at all. */
+
+/*ARGSUSED*/
+static boolean
+coff_a29k_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
+ bfd *obfd;
+ struct bfd_link_info *info;
+ bfd *ibfd;
+ asection *sec;
+ struct internal_reloc *irel;
+ boolean *adjustedp;
+{
+ if (irel->r_type == R_IHCONST)
+ *adjustedp = true;
+ else
+ *adjustedp = false;
+ return true;
+}
+
+#define coff_adjust_symndx coff_a29k_adjust_symndx
+
+#include "coffcode.h"
+
+const bfd_target a29kcoff_big_vec =
+{
+ "coff-a29k-big", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC /* section flags */
+ | SEC_LOAD | SEC_RELOC
+ | SEC_READONLY ),
+ '_', /* leading underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ /* 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_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+
+ {
+
+ _bfd_dummy_target,
+ coff_object_p,
+ bfd_generic_archive_p,
+ _bfd_dummy_target
+ },
+ {
+ bfd_false,
+ coff_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+ {
+ bfd_false,
+ coff_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE
+ };
diff --git a/contrib/gdb/bfd/coff-alpha.c b/contrib/gdb/bfd/coff-alpha.c
new file mode 100644
index 0000000..b14f3ef
--- /dev/null
+++ b/contrib/gdb/bfd/coff-alpha.c
@@ -0,0 +1,2390 @@
+/* BFD back-end for ALPHA Extended-Coff files.
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Modified from coff-mips.c by Steve Chamberlain <sac@cygnus.com> and
+ Ian Lance Taylor <ian@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "coff/symconst.h"
+#include "coff/ecoff.h"
+#include "coff/alpha.h"
+#include "aout/ar.h"
+#include "libcoff.h"
+#include "libecoff.h"
+
+/* Prototypes for static functions. */
+
+static const bfd_target *alpha_ecoff_object_p PARAMS ((bfd *));
+static boolean alpha_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
+static PTR alpha_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr));
+static void alpha_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
+ struct internal_reloc *));
+static void alpha_ecoff_swap_reloc_out PARAMS ((bfd *,
+ const struct internal_reloc *,
+ PTR));
+static void alpha_adjust_reloc_in PARAMS ((bfd *,
+ const struct internal_reloc *,
+ arelent *));
+static void alpha_adjust_reloc_out PARAMS ((bfd *, const arelent *,
+ struct internal_reloc *));
+static bfd_byte *alpha_ecoff_get_relocated_section_contents
+ PARAMS ((bfd *abfd, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *data, boolean relocateable, asymbol **symbols));
+static bfd_vma alpha_convert_external_reloc
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, struct external_reloc *,
+ struct ecoff_link_hash_entry *));
+static boolean alpha_relocate_section PARAMS ((bfd *, struct bfd_link_info *,
+ bfd *, asection *,
+ bfd_byte *, PTR));
+static boolean alpha_adjust_headers
+ PARAMS ((bfd *, struct internal_filehdr *, struct internal_aouthdr *));
+static PTR alpha_ecoff_read_ar_hdr PARAMS ((bfd *));
+static bfd *alpha_ecoff_get_elt_at_filepos PARAMS ((bfd *, file_ptr));
+static bfd *alpha_ecoff_openr_next_archived_file PARAMS ((bfd *, bfd *));
+static bfd *alpha_ecoff_get_elt_at_index PARAMS ((bfd *, symindex));
+
+/* ECOFF has COFF sections, but the debugging information is stored in
+ a completely different format. ECOFF targets use some of the
+ swapping routines from coffswap.h, and some of the generic COFF
+ routines in coffgen.c, but, unlike the real COFF targets, do not
+ use coffcode.h itself.
+
+ Get the generic COFF swapping routines, except for the reloc,
+ symbol, and lineno ones. Give them ecoff names. Define some
+ accessor macros for the large sizes used for Alpha ECOFF. */
+
+#define GET_FILEHDR_SYMPTR bfd_h_get_64
+#define PUT_FILEHDR_SYMPTR bfd_h_put_64
+#define GET_AOUTHDR_TSIZE bfd_h_get_64
+#define PUT_AOUTHDR_TSIZE bfd_h_put_64
+#define GET_AOUTHDR_DSIZE bfd_h_get_64
+#define PUT_AOUTHDR_DSIZE bfd_h_put_64
+#define GET_AOUTHDR_BSIZE bfd_h_get_64
+#define PUT_AOUTHDR_BSIZE bfd_h_put_64
+#define GET_AOUTHDR_ENTRY bfd_h_get_64
+#define PUT_AOUTHDR_ENTRY bfd_h_put_64
+#define GET_AOUTHDR_TEXT_START bfd_h_get_64
+#define PUT_AOUTHDR_TEXT_START bfd_h_put_64
+#define GET_AOUTHDR_DATA_START bfd_h_get_64
+#define PUT_AOUTHDR_DATA_START bfd_h_put_64
+#define GET_SCNHDR_PADDR bfd_h_get_64
+#define PUT_SCNHDR_PADDR bfd_h_put_64
+#define GET_SCNHDR_VADDR bfd_h_get_64
+#define PUT_SCNHDR_VADDR bfd_h_put_64
+#define GET_SCNHDR_SIZE bfd_h_get_64
+#define PUT_SCNHDR_SIZE bfd_h_put_64
+#define GET_SCNHDR_SCNPTR bfd_h_get_64
+#define PUT_SCNHDR_SCNPTR bfd_h_put_64
+#define GET_SCNHDR_RELPTR bfd_h_get_64
+#define PUT_SCNHDR_RELPTR bfd_h_put_64
+#define GET_SCNHDR_LNNOPTR bfd_h_get_64
+#define PUT_SCNHDR_LNNOPTR bfd_h_put_64
+
+#define ALPHAECOFF
+
+#define NO_COFF_RELOCS
+#define NO_COFF_SYMBOLS
+#define NO_COFF_LINENOS
+#define coff_swap_filehdr_in alpha_ecoff_swap_filehdr_in
+#define coff_swap_filehdr_out alpha_ecoff_swap_filehdr_out
+#define coff_swap_aouthdr_in alpha_ecoff_swap_aouthdr_in
+#define coff_swap_aouthdr_out alpha_ecoff_swap_aouthdr_out
+#define coff_swap_scnhdr_in alpha_ecoff_swap_scnhdr_in
+#define coff_swap_scnhdr_out alpha_ecoff_swap_scnhdr_out
+#include "coffswap.h"
+
+/* Get the ECOFF swapping routines. */
+#define ECOFF_64
+#include "ecoffswap.h"
+
+/* How to process the various reloc types. */
+
+static bfd_reloc_status_type
+reloc_nil PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+static bfd_reloc_status_type
+reloc_nil (abfd, reloc, sym, data, sec, output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc;
+ asymbol *sym;
+ PTR data;
+ asection *sec;
+ bfd *output_bfd;
+ char **error_message;
+{
+ return bfd_reloc_ok;
+}
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+ from smaller values. Start with zero, widen, *then* decrement. */
+#define MINUS_ONE (((bfd_vma)0) - 1)
+
+static reloc_howto_type alpha_howto_table[] =
+{
+ /* Reloc type 0 is ignored by itself. However, it appears after a
+ GPDISP reloc to identify the location where the low order 16 bits
+ of the gp register are loaded. */
+ HOWTO (ALPHA_R_IGNORE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ reloc_nil, /* special_function */
+ "IGNORE", /* name */
+ true, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A 32 bit reference to a symbol. */
+ HOWTO (ALPHA_R_REFLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "REFLONG", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 64 bit reference to a symbol. */
+ HOWTO (ALPHA_R_REFQUAD, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "REFQUAD", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 32 bit GP relative offset. This is just like REFLONG except
+ that when the value is used the value of the gp register will be
+ added in. */
+ HOWTO (ALPHA_R_GPREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "GPREL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Used for an instruction that refers to memory off the GP
+ register. The offset is 16 bits of the 32 bit instruction. This
+ reloc always seems to be against the .lita section. */
+ HOWTO (ALPHA_R_LITERAL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "LITERAL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* This reloc only appears immediately following a LITERAL reloc.
+ It identifies a use of the literal. It seems that the linker can
+ use this to eliminate a portion of the .lita section. The symbol
+ index is special: 1 means the literal address is in the base
+ register of a memory format instruction; 2 means the literal
+ address is in the byte offset register of a byte-manipulation
+ instruction; 3 means the literal address is in the target
+ register of a jsr instruction. This does not actually do any
+ relocation. */
+ HOWTO (ALPHA_R_LITUSE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ reloc_nil, /* special_function */
+ "LITUSE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Load the gp register. This is always used for a ldah instruction
+ which loads the upper 16 bits of the gp register. The next reloc
+ will be an IGNORE reloc which identifies the location of the lda
+ instruction which loads the lower 16 bits. The symbol index of
+ the GPDISP instruction appears to actually be the number of bytes
+ between the ldah and lda instructions. This gives two different
+ ways to determine where the lda instruction is; I don't know why
+ both are used. The value to use for the relocation is the
+ difference between the GP value and the current location; the
+ load will always be done against a register holding the current
+ address. */
+ HOWTO (ALPHA_R_GPDISP, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ reloc_nil, /* special_function */
+ "GPDISP", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A 21 bit branch. The native assembler generates these for
+ branches within the text segment, and also fills in the PC
+ relative offset in the instruction. */
+ HOWTO (ALPHA_R_BRADDR, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "BRADDR", /* name */
+ true, /* partial_inplace */
+ 0x1fffff, /* src_mask */
+ 0x1fffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A hint for a jump to a register. */
+ HOWTO (ALPHA_R_HINT, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 14, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "HINT", /* name */
+ true, /* partial_inplace */
+ 0x3fff, /* src_mask */
+ 0x3fff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SREL16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SREL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 64 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SREL64", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Push a value on the reloc evaluation stack. */
+ HOWTO (ALPHA_R_OP_PUSH, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_PUSH", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Store the value from the stack at the given address. Store it in
+ a bitfield of size r_size starting at bit position r_offset. */
+ HOWTO (ALPHA_R_OP_STORE, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_STORE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Subtract the reloc address from the value on the top of the
+ relocation stack. */
+ HOWTO (ALPHA_R_OP_PSUB, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_PSUB", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Shift the value on the top of the relocation stack right by the
+ given value. */
+ HOWTO (ALPHA_R_OP_PRSHIFT, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_PRSHIFT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Adjust the GP value for a new range in the object file. */
+ HOWTO (ALPHA_R_GPVALUE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "GPVALUE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+/* Recognize an Alpha ECOFF file. */
+
+static const bfd_target *
+alpha_ecoff_object_p (abfd)
+ bfd *abfd;
+{
+ static const bfd_target *ret;
+
+ ret = coff_object_p (abfd);
+
+ if (ret != NULL)
+ {
+ asection *sec;
+
+ /* Alpha ECOFF has a .pdata section. The lnnoptr field of the
+ .pdata section is the number of entries it contains. Each
+ entry takes up 8 bytes. The number of entries is required
+ since the section is aligned to a 16 byte boundary. When we
+ link .pdata sections together, we do not want to include the
+ alignment bytes. We handle this on input by faking the size
+ of the .pdata section to remove the unwanted alignment bytes.
+ On output we will set the lnnoptr field and force the
+ alignment. */
+ sec = bfd_get_section_by_name (abfd, _PDATA);
+ if (sec != (asection *) NULL)
+ {
+ bfd_size_type size;
+
+ size = sec->line_filepos * 8;
+ BFD_ASSERT (size == bfd_section_size (abfd, sec)
+ || size + 8 == bfd_section_size (abfd, sec));
+ if (! bfd_set_section_size (abfd, sec, size))
+ return NULL;
+ }
+ }
+
+ return ret;
+}
+
+/* See whether the magic number matches. */
+
+static boolean
+alpha_ecoff_bad_format_hook (abfd, filehdr)
+ bfd *abfd;
+ PTR filehdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+
+ if (ALPHA_ECOFF_BADMAG (*internal_f))
+ return false;
+
+ return true;
+}
+
+/* This is a hook called by coff_real_object_p to create any backend
+ specific information. */
+
+static PTR
+alpha_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
+ bfd *abfd;
+ PTR filehdr;
+ PTR aouthdr;
+{
+ PTR ecoff;
+
+ ecoff = _bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr);
+
+ if (ecoff != NULL)
+ {
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+
+ /* Set additional BFD flags according to the object type from the
+ machine specific file header flags. */
+ switch (internal_f->f_flags & F_ALPHA_OBJECT_TYPE_MASK)
+ {
+ case F_ALPHA_SHARABLE:
+ abfd->flags |= DYNAMIC;
+ break;
+ case F_ALPHA_CALL_SHARED:
+ /* Always executable if using shared libraries as the run time
+ loader might resolve undefined references. */
+ abfd->flags |= (DYNAMIC | EXEC_P);
+ break;
+ }
+ }
+ return ecoff;
+}
+
+/* Reloc handling. */
+
+/* Swap a reloc in. */
+
+static void
+alpha_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
+ bfd *abfd;
+ PTR ext_ptr;
+ struct internal_reloc *intern;
+{
+ const RELOC *ext = (RELOC *) ext_ptr;
+
+ intern->r_vaddr = bfd_h_get_64 (abfd, (bfd_byte *) ext->r_vaddr);
+ intern->r_symndx = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_symndx);
+
+ BFD_ASSERT (bfd_header_little_endian (abfd));
+
+ intern->r_type = ((ext->r_bits[0] & RELOC_BITS0_TYPE_LITTLE)
+ >> RELOC_BITS0_TYPE_SH_LITTLE);
+ intern->r_extern = (ext->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0;
+ intern->r_offset = ((ext->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE)
+ >> RELOC_BITS1_OFFSET_SH_LITTLE);
+ /* Ignored the reserved bits. */
+ intern->r_size = ((ext->r_bits[3] & RELOC_BITS3_SIZE_LITTLE)
+ >> RELOC_BITS3_SIZE_SH_LITTLE);
+
+ if (intern->r_type == ALPHA_R_LITUSE
+ || intern->r_type == ALPHA_R_GPDISP)
+ {
+ /* Handle the LITUSE and GPDISP relocs specially. Its symndx
+ value is not actually a symbol index, but is instead a
+ special code. We put the code in the r_size field, and
+ clobber the symndx. */
+ if (intern->r_size != 0)
+ abort ();
+ intern->r_size = intern->r_symndx;
+ intern->r_symndx = RELOC_SECTION_NONE;
+ }
+ else if (intern->r_type == ALPHA_R_IGNORE)
+ {
+ /* The IGNORE reloc generally follows a GPDISP reloc, and is
+ against the .lita section. The section is irrelevant. */
+ if (! intern->r_extern &&
+ intern->r_symndx == RELOC_SECTION_ABS)
+ abort ();
+ if (! intern->r_extern && intern->r_symndx == RELOC_SECTION_LITA)
+ intern->r_symndx = RELOC_SECTION_ABS;
+ }
+}
+
+/* Swap a reloc out. */
+
+static void
+alpha_ecoff_swap_reloc_out (abfd, intern, dst)
+ bfd *abfd;
+ const struct internal_reloc *intern;
+ PTR dst;
+{
+ RELOC *ext = (RELOC *) dst;
+ long symndx;
+ unsigned char size;
+
+ /* Undo the hackery done in swap_reloc_in. */
+ if (intern->r_type == ALPHA_R_LITUSE
+ || intern->r_type == ALPHA_R_GPDISP)
+ {
+ symndx = intern->r_size;
+ size = 0;
+ }
+ else if (intern->r_type == ALPHA_R_IGNORE
+ && ! intern->r_extern
+ && intern->r_symndx == RELOC_SECTION_ABS)
+ {
+ symndx = RELOC_SECTION_LITA;
+ size = intern->r_size;
+ }
+ else
+ {
+ symndx = intern->r_symndx;
+ size = intern->r_size;
+ }
+
+ BFD_ASSERT (intern->r_extern
+ || (intern->r_symndx >= 0 && intern->r_symndx <= 14));
+
+ bfd_h_put_64 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
+ bfd_h_put_32 (abfd, symndx, (bfd_byte *) ext->r_symndx);
+
+ BFD_ASSERT (bfd_header_little_endian (abfd));
+
+ ext->r_bits[0] = ((intern->r_type << RELOC_BITS0_TYPE_SH_LITTLE)
+ & RELOC_BITS0_TYPE_LITTLE);
+ ext->r_bits[1] = ((intern->r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0)
+ | ((intern->r_offset << RELOC_BITS1_OFFSET_SH_LITTLE)
+ & RELOC_BITS1_OFFSET_LITTLE));
+ ext->r_bits[2] = 0;
+ ext->r_bits[3] = ((size << RELOC_BITS3_SIZE_SH_LITTLE)
+ & RELOC_BITS3_SIZE_LITTLE);
+}
+
+/* Finish canonicalizing a reloc. Part of this is generic to all
+ ECOFF targets, and that part is in ecoff.c. The rest is done in
+ this backend routine. It must fill in the howto field. */
+
+static void
+alpha_adjust_reloc_in (abfd, intern, rptr)
+ bfd *abfd;
+ const struct internal_reloc *intern;
+ arelent *rptr;
+{
+ if (intern->r_type > ALPHA_R_GPVALUE)
+ abort ();
+
+ switch (intern->r_type)
+ {
+ case ALPHA_R_BRADDR:
+ case ALPHA_R_SREL16:
+ case ALPHA_R_SREL32:
+ case ALPHA_R_SREL64:
+ /* The PC relative relocs do not seem to use the section VMA as
+ a negative addend. */
+ rptr->addend = 0;
+ break;
+
+ case ALPHA_R_GPREL32:
+ case ALPHA_R_LITERAL:
+ /* Copy the gp value for this object file into the addend, to
+ ensure that we are not confused by the linker. */
+ if (! intern->r_extern)
+ rptr->addend += ecoff_data (abfd)->gp;
+ break;
+
+ case ALPHA_R_LITUSE:
+ case ALPHA_R_GPDISP:
+ /* The LITUSE and GPDISP relocs do not use a symbol, or an
+ addend, but they do use a special code. Put this code in the
+ addend field. */
+ rptr->addend = intern->r_size;
+ break;
+
+ case ALPHA_R_OP_STORE:
+ /* The STORE reloc needs the size and offset fields. We store
+ them in the addend. */
+ BFD_ASSERT (intern->r_offset <= 256 && intern->r_size <= 256);
+ rptr->addend = (intern->r_offset << 8) + intern->r_size;
+ break;
+
+ case ALPHA_R_OP_PUSH:
+ case ALPHA_R_OP_PSUB:
+ case ALPHA_R_OP_PRSHIFT:
+ /* The PUSH, PSUB and PRSHIFT relocs do not actually use an
+ address. I believe that the address supplied is really an
+ addend. */
+ rptr->addend = intern->r_vaddr;
+ break;
+
+ case ALPHA_R_GPVALUE:
+ /* Set the addend field to the new GP value. */
+ rptr->addend = intern->r_symndx + ecoff_data (abfd)->gp;
+ break;
+
+ case ALPHA_R_IGNORE:
+ /* If the type is ALPHA_R_IGNORE, make sure this is a reference
+ to the absolute section so that the reloc is ignored. For
+ some reason the address of this reloc type is not adjusted by
+ the section vma. We record the gp value for this object file
+ here, for convenience when doing the GPDISP relocation. */
+ rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ rptr->address = intern->r_vaddr;
+ rptr->addend = ecoff_data (abfd)->gp;
+ break;
+
+ default:
+ break;
+ }
+
+ rptr->howto = &alpha_howto_table[intern->r_type];
+}
+
+/* When writing out a reloc we need to pull some values back out of
+ the addend field into the reloc. This is roughly the reverse of
+ alpha_adjust_reloc_in, except that there are several changes we do
+ not need to undo. */
+
+static void
+alpha_adjust_reloc_out (abfd, rel, intern)
+ bfd *abfd;
+ const arelent *rel;
+ struct internal_reloc *intern;
+{
+ switch (intern->r_type)
+ {
+ case ALPHA_R_LITUSE:
+ case ALPHA_R_GPDISP:
+ intern->r_size = rel->addend;
+ break;
+
+ case ALPHA_R_OP_STORE:
+ intern->r_size = rel->addend & 0xff;
+ intern->r_offset = (rel->addend >> 8) & 0xff;
+ break;
+
+ case ALPHA_R_OP_PUSH:
+ case ALPHA_R_OP_PSUB:
+ case ALPHA_R_OP_PRSHIFT:
+ intern->r_vaddr = rel->addend;
+ break;
+
+ case ALPHA_R_IGNORE:
+ intern->r_vaddr = rel->address;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* The size of the stack for the relocation evaluator. */
+#define RELOC_STACKSIZE (10)
+
+/* Alpha ECOFF relocs have a built in expression evaluator as well as
+ other interdependencies. Rather than use a bunch of special
+ functions and global variables, we use a single routine to do all
+ the relocation for a section. I haven't yet worked out how the
+ assembler is going to handle this. */
+
+static bfd_byte *
+alpha_ecoff_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;
+{
+ 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;
+ bfd *output_bfd = relocateable ? abfd : (bfd *) NULL;
+ bfd_vma gp;
+ boolean gp_undefined;
+ bfd_vma stack[RELOC_STACKSIZE];
+ int tos = 0;
+
+ if (reloc_size < 0)
+ goto error_return;
+ reloc_vector = (arelent **) bfd_malloc (reloc_size);
+ if (reloc_vector == NULL && reloc_size != 0)
+ goto error_return;
+
+ if (! bfd_get_section_contents (input_bfd, input_section, data,
+ (file_ptr) 0, input_section->_raw_size))
+ goto error_return;
+
+ /* The section size is not going to change. */
+ input_section->_cooked_size = input_section->_raw_size;
+ input_section->reloc_done = true;
+
+ reloc_count = bfd_canonicalize_reloc (input_bfd, input_section,
+ reloc_vector, symbols);
+ if (reloc_count < 0)
+ goto error_return;
+ if (reloc_count == 0)
+ goto successful_return;
+
+ /* Get the GP value for the output BFD. */
+ gp_undefined = false;
+ gp = _bfd_get_gp_value (abfd);
+ if (gp == 0)
+ {
+ if (relocateable != false)
+ {
+ asection *sec;
+ bfd_vma lo;
+
+ /* Make up a value. */
+ lo = (bfd_vma) -1;
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ if (sec->vma < lo
+ && (strcmp (sec->name, ".sbss") == 0
+ || strcmp (sec->name, ".sdata") == 0
+ || strcmp (sec->name, ".lit4") == 0
+ || strcmp (sec->name, ".lit8") == 0
+ || strcmp (sec->name, ".lita") == 0))
+ lo = sec->vma;
+ }
+ gp = lo + 0x8000;
+ _bfd_set_gp_value (abfd, gp);
+ }
+ else
+ {
+ struct bfd_link_hash_entry *h;
+
+ h = bfd_link_hash_lookup (link_info->hash, "_gp", false, false,
+ true);
+ if (h == (struct bfd_link_hash_entry *) NULL
+ || h->type != bfd_link_hash_defined)
+ gp_undefined = true;
+ else
+ {
+ gp = (h->u.def.value
+ + h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset);
+ _bfd_set_gp_value (abfd, gp);
+ }
+ }
+ }
+
+ for (; *reloc_vector != (arelent *) NULL; reloc_vector++)
+ {
+ arelent *rel;
+ bfd_reloc_status_type r;
+ char *err;
+
+ rel = *reloc_vector;
+ r = bfd_reloc_ok;
+ switch (rel->howto->type)
+ {
+ case ALPHA_R_IGNORE:
+ rel->address += input_section->output_offset;
+ break;
+
+ case ALPHA_R_REFLONG:
+ case ALPHA_R_REFQUAD:
+ case ALPHA_R_BRADDR:
+ case ALPHA_R_HINT:
+ case ALPHA_R_SREL16:
+ case ALPHA_R_SREL32:
+ case ALPHA_R_SREL64:
+ if (relocateable
+ && ((*rel->sym_ptr_ptr)->flags & BSF_SECTION_SYM) == 0)
+ {
+ rel->address += input_section->output_offset;
+ break;
+ }
+ r = bfd_perform_relocation (input_bfd, rel, data, input_section,
+ output_bfd, &err);
+ break;
+
+ case ALPHA_R_GPREL32:
+ /* This relocation is used in a switch table. It is a 32
+ bit offset from the current GP value. We must adjust it
+ by the different between the original GP value and the
+ current GP value. The original GP value is stored in the
+ addend. We adjust the addend and let
+ bfd_perform_relocation finish the job. */
+ rel->addend -= gp;
+ r = bfd_perform_relocation (input_bfd, rel, data, input_section,
+ output_bfd, &err);
+ if (r == bfd_reloc_ok && gp_undefined)
+ {
+ r = bfd_reloc_dangerous;
+ err = (char *) "GP relative relocation used when GP not defined";
+ }
+ break;
+
+ case ALPHA_R_LITERAL:
+ /* This is a reference to a literal value, generally
+ (always?) in the .lita section. This is a 16 bit GP
+ relative relocation. Sometimes the subsequent reloc is a
+ LITUSE reloc, which indicates how this reloc is used.
+ This sometimes permits rewriting the two instructions
+ referred to by the LITERAL and the LITUSE into different
+ instructions which do not refer to .lita. This can save
+ a memory reference, and permits removing a value from
+ .lita thus saving GP relative space.
+
+ We do not these optimizations. To do them we would need
+ to arrange to link the .lita section first, so that by
+ the time we got here we would know the final values to
+ use. This would not be particularly difficult, but it is
+ not currently implemented. */
+
+ {
+ unsigned long insn;
+
+ /* I believe that the LITERAL reloc will only apply to a
+ ldq or ldl instruction, so check my assumption. */
+ insn = bfd_get_32 (input_bfd, data + rel->address);
+ BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29
+ || ((insn >> 26) & 0x3f) == 0x28);
+
+ rel->addend -= gp;
+ r = bfd_perform_relocation (input_bfd, rel, data, input_section,
+ output_bfd, &err);
+ if (r == bfd_reloc_ok && gp_undefined)
+ {
+ r = bfd_reloc_dangerous;
+ err =
+ (char *) "GP relative relocation used when GP not defined";
+ }
+ }
+ break;
+
+ case ALPHA_R_LITUSE:
+ /* See ALPHA_R_LITERAL above for the uses of this reloc. It
+ does not cause anything to happen, itself. */
+ rel->address += input_section->output_offset;
+ break;
+
+ case ALPHA_R_GPDISP:
+ /* This marks the ldah of an ldah/lda pair which loads the
+ gp register with the difference of the gp value and the
+ current location. The second of the pair is r_size bytes
+ ahead; it used to be marked with an ALPHA_R_IGNORE reloc,
+ but that no longer happens in OSF/1 3.2. */
+ {
+ unsigned long insn1, insn2;
+ bfd_vma addend;
+
+ /* Get the two instructions. */
+ insn1 = bfd_get_32 (input_bfd, data + rel->address);
+ insn2 = bfd_get_32 (input_bfd, data + rel->address + rel->addend);
+
+ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */
+ BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */
+
+ /* Get the existing addend. We must account for the sign
+ extension done by lda and ldah. */
+ addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff);
+ if (insn1 & 0x8000)
+ {
+ addend -= 0x80000000;
+ addend -= 0x80000000;
+ }
+ if (insn2 & 0x8000)
+ addend -= 0x10000;
+
+ /* The existing addend includes the different between the
+ gp of the input BFD and the address in the input BFD.
+ Subtract this out. */
+ addend -= (ecoff_data (input_bfd)->gp
+ - (input_section->vma + rel->address));
+
+ /* Now add in the final gp value, and subtract out the
+ final address. */
+ addend += (gp
+ - (input_section->output_section->vma
+ + input_section->output_offset
+ + rel->address));
+
+ /* Change the instructions, accounting for the sign
+ extension, and write them out. */
+ if (addend & 0x8000)
+ addend += 0x10000;
+ insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);
+ insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
+
+ bfd_put_32 (input_bfd, (bfd_vma) insn1, data + rel->address);
+ bfd_put_32 (input_bfd, (bfd_vma) insn2,
+ data + rel->address + rel->addend);
+
+ rel->address += input_section->output_offset;
+ }
+ break;
+
+ case ALPHA_R_OP_PUSH:
+ /* Push a value on the reloc evaluation stack. */
+ {
+ asymbol *symbol;
+ bfd_vma relocation;
+
+ if (relocateable)
+ {
+ rel->address += input_section->output_offset;
+ break;
+ }
+
+ /* Figure out the relocation of this symbol. */
+ symbol = *rel->sym_ptr_ptr;
+
+ if (bfd_is_und_section (symbol->section))
+ r = bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += rel->addend;
+
+ if (tos >= RELOC_STACKSIZE)
+ abort ();
+
+ stack[tos++] = relocation;
+ }
+ break;
+
+ case ALPHA_R_OP_STORE:
+ /* Store a value from the reloc stack into a bitfield. */
+ {
+ bfd_vma val;
+ int offset, size;
+
+ if (relocateable)
+ {
+ rel->address += input_section->output_offset;
+ break;
+ }
+
+ if (tos == 0)
+ abort ();
+
+ /* The offset and size for this reloc are encoded into the
+ addend field by alpha_adjust_reloc_in. */
+ offset = (rel->addend >> 8) & 0xff;
+ size = rel->addend & 0xff;
+
+ val = bfd_get_64 (abfd, data + rel->address);
+ val &=~ (((1 << size) - 1) << offset);
+ val |= (stack[--tos] & ((1 << size) - 1)) << offset;
+ bfd_put_64 (abfd, val, data + rel->address);
+ }
+ break;
+
+ case ALPHA_R_OP_PSUB:
+ /* Subtract a value from the top of the stack. */
+ {
+ asymbol *symbol;
+ bfd_vma relocation;
+
+ if (relocateable)
+ {
+ rel->address += input_section->output_offset;
+ break;
+ }
+
+ /* Figure out the relocation of this symbol. */
+ symbol = *rel->sym_ptr_ptr;
+
+ if (bfd_is_und_section (symbol->section))
+ r = bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += rel->addend;
+
+ if (tos == 0)
+ abort ();
+
+ stack[tos - 1] -= relocation;
+ }
+ break;
+
+ case ALPHA_R_OP_PRSHIFT:
+ /* Shift the value on the top of the stack. */
+ {
+ asymbol *symbol;
+ bfd_vma relocation;
+
+ if (relocateable)
+ {
+ rel->address += input_section->output_offset;
+ break;
+ }
+
+ /* Figure out the relocation of this symbol. */
+ symbol = *rel->sym_ptr_ptr;
+
+ if (bfd_is_und_section (symbol->section))
+ r = bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += rel->addend;
+
+ if (tos == 0)
+ abort ();
+
+ stack[tos - 1] >>= relocation;
+ }
+ break;
+
+ case ALPHA_R_GPVALUE:
+ /* I really don't know if this does the right thing. */
+ gp = rel->addend;
+ gp_undefined = false;
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (relocateable)
+ {
+ asection *os = input_section->output_section;
+
+ /* A partial link, so keep the relocs. */
+ os->orelocation[os->reloc_count] = rel;
+ 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 (*rel->sym_ptr_ptr),
+ input_bfd, input_section, rel->address)))
+ goto error_return;
+ break;
+ case bfd_reloc_dangerous:
+ if (! ((*link_info->callbacks->reloc_dangerous)
+ (link_info, err, input_bfd, input_section,
+ rel->address)))
+ goto error_return;
+ break;
+ case bfd_reloc_overflow:
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*rel->sym_ptr_ptr),
+ rel->howto->name, rel->addend, input_bfd,
+ input_section, rel->address)))
+ goto error_return;
+ break;
+ case bfd_reloc_outofrange:
+ default:
+ abort ();
+ break;
+ }
+ }
+ }
+
+ if (tos != 0)
+ abort ();
+
+ successful_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return data;
+
+ error_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return NULL;
+}
+
+/* Get the howto structure for a generic reloc type. */
+
+static reloc_howto_type *
+alpha_bfd_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ int alpha_type;
+
+ switch (code)
+ {
+ case BFD_RELOC_32:
+ alpha_type = ALPHA_R_REFLONG;
+ break;
+ case BFD_RELOC_64:
+ case BFD_RELOC_CTOR:
+ alpha_type = ALPHA_R_REFQUAD;
+ break;
+ case BFD_RELOC_GPREL32:
+ alpha_type = ALPHA_R_GPREL32;
+ break;
+ case BFD_RELOC_ALPHA_LITERAL:
+ alpha_type = ALPHA_R_LITERAL;
+ break;
+ case BFD_RELOC_ALPHA_LITUSE:
+ alpha_type = ALPHA_R_LITUSE;
+ break;
+ case BFD_RELOC_ALPHA_GPDISP_HI16:
+ alpha_type = ALPHA_R_GPDISP;
+ break;
+ case BFD_RELOC_ALPHA_GPDISP_LO16:
+ alpha_type = ALPHA_R_IGNORE;
+ break;
+ case BFD_RELOC_23_PCREL_S2:
+ alpha_type = ALPHA_R_BRADDR;
+ break;
+ case BFD_RELOC_ALPHA_HINT:
+ alpha_type = ALPHA_R_HINT;
+ break;
+ case BFD_RELOC_16_PCREL:
+ alpha_type = ALPHA_R_SREL16;
+ break;
+ case BFD_RELOC_32_PCREL:
+ alpha_type = ALPHA_R_SREL32;
+ break;
+ case BFD_RELOC_64_PCREL:
+ alpha_type = ALPHA_R_SREL64;
+ break;
+#if 0
+ case ???:
+ alpha_type = ALPHA_R_OP_PUSH;
+ break;
+ case ???:
+ alpha_type = ALPHA_R_OP_STORE;
+ break;
+ case ???:
+ alpha_type = ALPHA_R_OP_PSUB;
+ break;
+ case ???:
+ alpha_type = ALPHA_R_OP_PRSHIFT;
+ break;
+ case ???:
+ alpha_type = ALPHA_R_GPVALUE;
+ break;
+#endif
+ default:
+ return (reloc_howto_type *) NULL;
+ }
+
+ return &alpha_howto_table[alpha_type];
+}
+
+/* A helper routine for alpha_relocate_section which converts an
+ external reloc when generating relocateable output. Returns the
+ relocation amount. */
+
+static bfd_vma
+alpha_convert_external_reloc (output_bfd, info, input_bfd, ext_rel, h)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ struct external_reloc *ext_rel;
+ struct ecoff_link_hash_entry *h;
+{
+ unsigned long r_symndx;
+ bfd_vma relocation;
+
+ BFD_ASSERT (info->relocateable);
+
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *hsec;
+ const char *name;
+
+ /* This symbol is defined in the output. Convert the reloc from
+ being against the symbol to being against the section. */
+
+ /* Clear the r_extern bit. */
+ ext_rel->r_bits[1] &=~ RELOC_BITS1_EXTERN_LITTLE;
+
+ /* Compute a new r_symndx value. */
+ hsec = h->root.u.def.section;
+ name = bfd_get_section_name (output_bfd, hsec->output_section);
+
+ r_symndx = -1;
+ switch (name[1])
+ {
+ case 'A':
+ if (strcmp (name, "*ABS*") == 0)
+ r_symndx = RELOC_SECTION_ABS;
+ break;
+ case 'b':
+ if (strcmp (name, ".bss") == 0)
+ r_symndx = RELOC_SECTION_BSS;
+ break;
+ case 'd':
+ if (strcmp (name, ".data") == 0)
+ r_symndx = RELOC_SECTION_DATA;
+ break;
+ case 'f':
+ if (strcmp (name, ".fini") == 0)
+ r_symndx = RELOC_SECTION_FINI;
+ break;
+ case 'i':
+ if (strcmp (name, ".init") == 0)
+ r_symndx = RELOC_SECTION_INIT;
+ break;
+ case 'l':
+ if (strcmp (name, ".lita") == 0)
+ r_symndx = RELOC_SECTION_LITA;
+ else if (strcmp (name, ".lit8") == 0)
+ r_symndx = RELOC_SECTION_LIT8;
+ else if (strcmp (name, ".lit4") == 0)
+ r_symndx = RELOC_SECTION_LIT4;
+ break;
+ case 'p':
+ if (strcmp (name, ".pdata") == 0)
+ r_symndx = RELOC_SECTION_PDATA;
+ break;
+ case 'r':
+ if (strcmp (name, ".rdata") == 0)
+ r_symndx = RELOC_SECTION_RDATA;
+ else if (strcmp (name, ".rconst") == 0)
+ r_symndx = RELOC_SECTION_RCONST;
+ break;
+ case 's':
+ if (strcmp (name, ".sdata") == 0)
+ r_symndx = RELOC_SECTION_SDATA;
+ else if (strcmp (name, ".sbss") == 0)
+ r_symndx = RELOC_SECTION_SBSS;
+ break;
+ case 't':
+ if (strcmp (name, ".text") == 0)
+ r_symndx = RELOC_SECTION_TEXT;
+ break;
+ case 'x':
+ if (strcmp (name, ".xdata") == 0)
+ r_symndx = RELOC_SECTION_XDATA;
+ break;
+ }
+
+ if (r_symndx == -1)
+ abort ();
+
+ /* Add the section VMA and the symbol value. */
+ relocation = (h->root.u.def.value
+ + hsec->output_section->vma
+ + hsec->output_offset);
+ }
+ else
+ {
+ /* Change the symndx value to the right one for
+ the output BFD. */
+ r_symndx = h->indx;
+ if (r_symndx == -1)
+ {
+ /* Caller must give an error. */
+ r_symndx = 0;
+ }
+ relocation = 0;
+ }
+
+ /* Write out the new r_symndx value. */
+ bfd_h_put_32 (input_bfd, (bfd_vma) r_symndx,
+ (bfd_byte *) ext_rel->r_symndx);
+
+ return relocation;
+}
+
+/* Relocate a section while linking an Alpha ECOFF file. This is
+ quite similar to get_relocated_section_contents. Perhaps they
+ could be combined somehow. */
+
+static boolean
+alpha_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, external_relocs)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ PTR external_relocs;
+{
+ asection **symndx_to_section, *lita_sec;
+ struct ecoff_link_hash_entry **sym_hashes;
+ bfd_vma gp;
+ boolean gp_undefined;
+ bfd_vma stack[RELOC_STACKSIZE];
+ int tos = 0;
+ struct external_reloc *ext_rel;
+ struct external_reloc *ext_rel_end;
+
+ /* We keep a table mapping the symndx found in an internal reloc to
+ the appropriate section. This is faster than looking up the
+ section by name each time. */
+ symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
+ if (symndx_to_section == (asection **) NULL)
+ {
+ symndx_to_section = ((asection **)
+ bfd_alloc (input_bfd,
+ (NUM_RELOC_SECTIONS
+ * sizeof (asection *))));
+ if (!symndx_to_section)
+ return false;
+
+ symndx_to_section[RELOC_SECTION_NONE] = NULL;
+ symndx_to_section[RELOC_SECTION_TEXT] =
+ bfd_get_section_by_name (input_bfd, ".text");
+ symndx_to_section[RELOC_SECTION_RDATA] =
+ bfd_get_section_by_name (input_bfd, ".rdata");
+ symndx_to_section[RELOC_SECTION_DATA] =
+ bfd_get_section_by_name (input_bfd, ".data");
+ symndx_to_section[RELOC_SECTION_SDATA] =
+ bfd_get_section_by_name (input_bfd, ".sdata");
+ symndx_to_section[RELOC_SECTION_SBSS] =
+ bfd_get_section_by_name (input_bfd, ".sbss");
+ symndx_to_section[RELOC_SECTION_BSS] =
+ bfd_get_section_by_name (input_bfd, ".bss");
+ symndx_to_section[RELOC_SECTION_INIT] =
+ bfd_get_section_by_name (input_bfd, ".init");
+ symndx_to_section[RELOC_SECTION_LIT8] =
+ bfd_get_section_by_name (input_bfd, ".lit8");
+ symndx_to_section[RELOC_SECTION_LIT4] =
+ bfd_get_section_by_name (input_bfd, ".lit4");
+ symndx_to_section[RELOC_SECTION_XDATA] =
+ bfd_get_section_by_name (input_bfd, ".xdata");
+ symndx_to_section[RELOC_SECTION_PDATA] =
+ bfd_get_section_by_name (input_bfd, ".pdata");
+ symndx_to_section[RELOC_SECTION_FINI] =
+ bfd_get_section_by_name (input_bfd, ".fini");
+ symndx_to_section[RELOC_SECTION_LITA] =
+ bfd_get_section_by_name (input_bfd, ".lita");
+ symndx_to_section[RELOC_SECTION_ABS] = bfd_abs_section_ptr;
+ symndx_to_section[RELOC_SECTION_RCONST] =
+ bfd_get_section_by_name (input_bfd, ".rconst");
+
+ ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
+ }
+
+ sym_hashes = ecoff_data (input_bfd)->sym_hashes;
+
+ /* On the Alpha, the .lita section must be addressable by the global
+ pointer. To support large programs, we need to allow multiple
+ global pointers. This works as long as each input .lita section
+ is <64KB big. This implies that when producing relocatable
+ output, the .lita section is limited to 64KB. . */
+
+ lita_sec = symndx_to_section[RELOC_SECTION_LITA];
+ gp = _bfd_get_gp_value (output_bfd);
+ if (! info->relocateable && lita_sec != NULL)
+ {
+ struct ecoff_section_tdata *lita_sec_data;
+
+ /* Make sure we have a section data structure to which we can
+ hang on to the gp value we pick for the section. */
+ lita_sec_data = ecoff_section_data (input_bfd, lita_sec);
+ if (lita_sec_data == NULL)
+ {
+ lita_sec_data = ((struct ecoff_section_tdata *)
+ bfd_zalloc (input_bfd,
+ sizeof (struct ecoff_section_tdata)));
+ ecoff_section_data (input_bfd, lita_sec) = lita_sec_data;
+ }
+
+ if (lita_sec_data->gp != 0)
+ {
+ /* If we already assigned a gp to this section, we better
+ stick with that value. */
+ gp = lita_sec_data->gp;
+ }
+ else
+ {
+ bfd_vma lita_vma;
+ bfd_size_type lita_size;
+
+ lita_vma = lita_sec->output_offset + lita_sec->output_section->vma;
+ lita_size = lita_sec->_cooked_size;
+ if (lita_size == 0)
+ lita_size = lita_sec->_raw_size;
+
+ if (gp == 0
+ || lita_vma < gp - 0x8000
+ || lita_vma + lita_size >= gp + 0x8000)
+ {
+ /* Either gp hasn't been set at all or the current gp
+ cannot address this .lita section. In both cases we
+ reset the gp to point into the "middle" of the
+ current input .lita section. */
+ if (gp && !ecoff_data (output_bfd)->issued_multiple_gp_warning)
+ {
+ (*info->callbacks->warning) (info,
+ "using multiple gp values",
+ (char *) NULL, output_bfd,
+ (asection *) NULL, (bfd_vma) 0);
+ ecoff_data (output_bfd)->issued_multiple_gp_warning = true;
+ }
+ if (lita_vma < gp - 0x8000)
+ gp = lita_vma + lita_size - 0x8000;
+ else
+ gp = lita_vma + 0x8000;
+
+ }
+
+ lita_sec_data->gp = gp;
+ }
+
+ _bfd_set_gp_value (output_bfd, gp);
+ }
+
+ gp_undefined = (gp == 0);
+
+ BFD_ASSERT (bfd_header_little_endian (output_bfd));
+ BFD_ASSERT (bfd_header_little_endian (input_bfd));
+
+ ext_rel = (struct external_reloc *) external_relocs;
+ ext_rel_end = ext_rel + input_section->reloc_count;
+ for (; ext_rel < ext_rel_end; ext_rel++)
+ {
+ bfd_vma r_vaddr;
+ unsigned long r_symndx;
+ int r_type;
+ int r_extern;
+ int r_offset;
+ int r_size;
+ boolean relocatep;
+ boolean adjust_addrp;
+ boolean gp_usedp;
+ bfd_vma addend;
+
+ r_vaddr = bfd_h_get_64 (input_bfd, (bfd_byte *) ext_rel->r_vaddr);
+ r_symndx = bfd_h_get_32 (input_bfd, (bfd_byte *) ext_rel->r_symndx);
+
+ r_type = ((ext_rel->r_bits[0] & RELOC_BITS0_TYPE_LITTLE)
+ >> RELOC_BITS0_TYPE_SH_LITTLE);
+ r_extern = (ext_rel->r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0;
+ r_offset = ((ext_rel->r_bits[1] & RELOC_BITS1_OFFSET_LITTLE)
+ >> RELOC_BITS1_OFFSET_SH_LITTLE);
+ /* Ignored the reserved bits. */
+ r_size = ((ext_rel->r_bits[3] & RELOC_BITS3_SIZE_LITTLE)
+ >> RELOC_BITS3_SIZE_SH_LITTLE);
+
+ relocatep = false;
+ adjust_addrp = true;
+ gp_usedp = false;
+ addend = 0;
+
+ switch (r_type)
+ {
+ default:
+ abort ();
+
+ case ALPHA_R_IGNORE:
+ /* This reloc appears after a GPDISP reloc. On earlier
+ versions of OSF/1, It marked the position of the second
+ instruction to be altered by the GPDISP reloc, but it is
+ not otherwise used for anything. For some reason, the
+ address of the relocation does not appear to include the
+ section VMA, unlike the other relocation types. */
+ if (info->relocateable)
+ bfd_h_put_64 (input_bfd,
+ input_section->output_offset + r_vaddr,
+ (bfd_byte *) ext_rel->r_vaddr);
+ adjust_addrp = false;
+ break;
+
+ case ALPHA_R_REFLONG:
+ case ALPHA_R_REFQUAD:
+ case ALPHA_R_BRADDR:
+ case ALPHA_R_HINT:
+ case ALPHA_R_SREL16:
+ case ALPHA_R_SREL32:
+ case ALPHA_R_SREL64:
+ relocatep = true;
+ break;
+
+ case ALPHA_R_GPREL32:
+ /* This relocation is used in a switch table. It is a 32
+ bit offset from the current GP value. We must adjust it
+ by the different between the original GP value and the
+ current GP value. */
+ relocatep = true;
+ addend = ecoff_data (input_bfd)->gp - gp;
+ gp_usedp = true;
+ break;
+
+ case ALPHA_R_LITERAL:
+ /* This is a reference to a literal value, generally
+ (always?) in the .lita section. This is a 16 bit GP
+ relative relocation. Sometimes the subsequent reloc is a
+ LITUSE reloc, which indicates how this reloc is used.
+ This sometimes permits rewriting the two instructions
+ referred to by the LITERAL and the LITUSE into different
+ instructions which do not refer to .lita. This can save
+ a memory reference, and permits removing a value from
+ .lita thus saving GP relative space.
+
+ We do not these optimizations. To do them we would need
+ to arrange to link the .lita section first, so that by
+ the time we got here we would know the final values to
+ use. This would not be particularly difficult, but it is
+ not currently implemented. */
+
+ /* I believe that the LITERAL reloc will only apply to a ldq
+ or ldl instruction, so check my assumption. */
+ {
+ unsigned long insn;
+
+ insn = bfd_get_32 (input_bfd,
+ contents + r_vaddr - input_section->vma);
+ BFD_ASSERT (((insn >> 26) & 0x3f) == 0x29
+ || ((insn >> 26) & 0x3f) == 0x28);
+ }
+
+ relocatep = true;
+ addend = ecoff_data (input_bfd)->gp - gp;
+ gp_usedp = true;
+ break;
+
+ case ALPHA_R_LITUSE:
+ /* See ALPHA_R_LITERAL above for the uses of this reloc. It
+ does not cause anything to happen, itself. */
+ break;
+
+ case ALPHA_R_GPDISP:
+ /* This marks the ldah of an ldah/lda pair which loads the
+ gp register with the difference of the gp value and the
+ current location. The second of the pair is r_symndx
+ bytes ahead. It used to be marked with an ALPHA_R_IGNORE
+ reloc, but OSF/1 3.2 no longer does that. */
+ {
+ unsigned long insn1, insn2;
+
+ /* Get the two instructions. */
+ insn1 = bfd_get_32 (input_bfd,
+ contents + r_vaddr - input_section->vma);
+ insn2 = bfd_get_32 (input_bfd,
+ (contents
+ + r_vaddr
+ - input_section->vma
+ + r_symndx));
+
+ BFD_ASSERT (((insn1 >> 26) & 0x3f) == 0x09); /* ldah */
+ BFD_ASSERT (((insn2 >> 26) & 0x3f) == 0x08); /* lda */
+
+ /* Get the existing addend. We must account for the sign
+ extension done by lda and ldah. */
+ addend = ((insn1 & 0xffff) << 16) + (insn2 & 0xffff);
+ if (insn1 & 0x8000)
+ {
+ /* This is addend -= 0x100000000 without causing an
+ integer overflow on a 32 bit host. */
+ addend -= 0x80000000;
+ addend -= 0x80000000;
+ }
+ if (insn2 & 0x8000)
+ addend -= 0x10000;
+
+ /* The existing addend includes the difference between the
+ gp of the input BFD and the address in the input BFD.
+ We want to change this to the difference between the
+ final GP and the final address. */
+ addend += (gp
+ - ecoff_data (input_bfd)->gp
+ + input_section->vma
+ - (input_section->output_section->vma
+ + input_section->output_offset));
+
+ /* Change the instructions, accounting for the sign
+ extension, and write them out. */
+ if (addend & 0x8000)
+ addend += 0x10000;
+ insn1 = (insn1 & 0xffff0000) | ((addend >> 16) & 0xffff);
+ insn2 = (insn2 & 0xffff0000) | (addend & 0xffff);
+
+ bfd_put_32 (input_bfd, (bfd_vma) insn1,
+ contents + r_vaddr - input_section->vma);
+ bfd_put_32 (input_bfd, (bfd_vma) insn2,
+ contents + r_vaddr - input_section->vma + r_symndx);
+
+ gp_usedp = true;
+ }
+ break;
+
+ case ALPHA_R_OP_PUSH:
+ case ALPHA_R_OP_PSUB:
+ case ALPHA_R_OP_PRSHIFT:
+ /* Manipulate values on the reloc evaluation stack. The
+ r_vaddr field is not an address in input_section, it is
+ the current value (including any addend) of the object
+ being used. */
+ if (! r_extern)
+ {
+ asection *s;
+
+ s = symndx_to_section[r_symndx];
+ if (s == (asection *) NULL)
+ abort ();
+ addend = s->output_section->vma + s->output_offset - s->vma;
+ }
+ else
+ {
+ struct ecoff_link_hash_entry *h;
+
+ h = sym_hashes[r_symndx];
+ if (h == (struct ecoff_link_hash_entry *) NULL)
+ abort ();
+
+ if (! info->relocateable)
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ addend = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ else
+ {
+ /* Note that we pass the address as 0, since we
+ do not have a meaningful number for the
+ location within the section that is being
+ relocated. */
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, (bfd_vma) 0)))
+ return false;
+ addend = 0;
+ }
+ }
+ else
+ {
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak
+ && h->indx == -1)
+ {
+ /* This symbol is not being written out. Pass
+ the address as 0, as with undefined_symbol,
+ above. */
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, h->root.root.string, input_bfd,
+ input_section, (bfd_vma) 0)))
+ return false;
+ }
+
+ addend = alpha_convert_external_reloc (output_bfd, info,
+ input_bfd,
+ ext_rel, h);
+ }
+ }
+
+ addend += r_vaddr;
+
+ if (info->relocateable)
+ {
+ /* Adjust r_vaddr by the addend. */
+ bfd_h_put_64 (input_bfd, addend,
+ (bfd_byte *) ext_rel->r_vaddr);
+ }
+ else
+ {
+ switch (r_type)
+ {
+ case ALPHA_R_OP_PUSH:
+ if (tos >= RELOC_STACKSIZE)
+ abort ();
+ stack[tos++] = addend;
+ break;
+
+ case ALPHA_R_OP_PSUB:
+ if (tos == 0)
+ abort ();
+ stack[tos - 1] -= addend;
+ break;
+
+ case ALPHA_R_OP_PRSHIFT:
+ if (tos == 0)
+ abort ();
+ stack[tos - 1] >>= addend;
+ break;
+ }
+ }
+
+ adjust_addrp = false;
+ break;
+
+ case ALPHA_R_OP_STORE:
+ /* Store a value from the reloc stack into a bitfield. If
+ we are generating relocateable output, all we do is
+ adjust the address of the reloc. */
+ if (! info->relocateable)
+ {
+ bfd_vma mask;
+ bfd_vma val;
+
+ if (tos == 0)
+ abort ();
+
+ /* Get the relocation mask. The separate steps and the
+ casts to bfd_vma are attempts to avoid a bug in the
+ Alpha OSF 1.3 C compiler. See reloc.c for more
+ details. */
+ mask = 1;
+ mask <<= (bfd_vma) r_size;
+ mask -= 1;
+
+ /* FIXME: I don't know what kind of overflow checking,
+ if any, should be done here. */
+ val = bfd_get_64 (input_bfd,
+ contents + r_vaddr - input_section->vma);
+ val &=~ mask << (bfd_vma) r_offset;
+ val |= (stack[--tos] & mask) << (bfd_vma) r_offset;
+ bfd_put_64 (input_bfd, val,
+ contents + r_vaddr - input_section->vma);
+ }
+ break;
+
+ case ALPHA_R_GPVALUE:
+ /* I really don't know if this does the right thing. */
+ gp = ecoff_data (input_bfd)->gp + r_symndx;
+ gp_undefined = false;
+ break;
+ }
+
+ if (relocatep)
+ {
+ reloc_howto_type *howto;
+ struct ecoff_link_hash_entry *h = NULL;
+ asection *s = NULL;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+
+ /* Perform a relocation. */
+
+ howto = &alpha_howto_table[r_type];
+
+ if (r_extern)
+ {
+ h = sym_hashes[r_symndx];
+ /* If h is NULL, that means that there is a reloc
+ against an external symbol which we thought was just
+ a debugging symbol. This should not happen. */
+ if (h == (struct ecoff_link_hash_entry *) NULL)
+ abort ();
+ }
+ else
+ {
+ if (r_symndx >= NUM_RELOC_SECTIONS)
+ s = NULL;
+ else
+ s = symndx_to_section[r_symndx];
+
+ if (s == (asection *) NULL)
+ abort ();
+ }
+
+ if (info->relocateable)
+ {
+ /* We are generating relocateable output, and must
+ convert the existing reloc. */
+ if (r_extern)
+ {
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak
+ && h->indx == -1)
+ {
+ /* This symbol is not being written out. */
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, h->root.root.string, input_bfd,
+ input_section, r_vaddr - input_section->vma)))
+ return false;
+ }
+
+ relocation = alpha_convert_external_reloc (output_bfd,
+ info,
+ input_bfd,
+ ext_rel,
+ h);
+ }
+ else
+ {
+ /* This is a relocation against a section. Adjust
+ the value by the amount the section moved. */
+ relocation = (s->output_section->vma
+ + s->output_offset
+ - s->vma);
+ }
+
+ /* If this is PC relative, the existing object file
+ appears to already have the reloc worked out. We
+ must subtract out the old value and add in the new
+ one. */
+ if (howto->pc_relative)
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ - input_section->vma);
+
+ /* Put in any addend. */
+ relocation += addend;
+
+ /* Adjust the contents. */
+ r = _bfd_relocate_contents (howto, input_bfd, relocation,
+ (contents
+ + r_vaddr
+ - input_section->vma));
+ }
+ else
+ {
+ /* We are producing a final executable. */
+ if (r_extern)
+ {
+ /* This is a reloc against a symbol. */
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *hsec;
+
+ hsec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + hsec->output_section->vma
+ + hsec->output_offset);
+ }
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section,
+ r_vaddr - input_section->vma)))
+ return false;
+ relocation = 0;
+ }
+ }
+ else
+ {
+ /* This is a reloc against a section. */
+ relocation = (s->output_section->vma
+ + s->output_offset
+ - s->vma);
+
+ /* Adjust a PC relative relocation by removing the
+ reference to the original source section. */
+ if (howto->pc_relative)
+ relocation += input_section->vma;
+ }
+
+ r = _bfd_final_link_relocate (howto,
+ input_bfd,
+ input_section,
+ contents,
+ r_vaddr - input_section->vma,
+ relocation,
+ 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 = sym_hashes[r_symndx]->root.root.string;
+ else
+ name = bfd_section_name (input_bfd,
+ symndx_to_section[r_symndx]);
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, alpha_howto_table[r_type].name,
+ (bfd_vma) 0, input_bfd, input_section,
+ r_vaddr - input_section->vma)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ if (info->relocateable && adjust_addrp)
+ {
+ /* Change the address of the relocation. */
+ bfd_h_put_64 (input_bfd,
+ (input_section->output_section->vma
+ + input_section->output_offset
+ - input_section->vma
+ + r_vaddr),
+ (bfd_byte *) ext_rel->r_vaddr);
+ }
+
+ if (gp_usedp && gp_undefined)
+ {
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info, "GP relative relocation when GP not defined",
+ input_bfd, input_section, r_vaddr - input_section->vma)))
+ return false;
+ /* Only give the error once per link. */
+ gp = 4;
+ _bfd_set_gp_value (output_bfd, gp);
+ gp_undefined = false;
+ }
+ }
+
+ if (tos != 0)
+ abort ();
+
+ return true;
+}
+
+/* Do final adjustments to the filehdr and the aouthdr. This routine
+ sets the dynamic bits in the file header. */
+
+/*ARGSUSED*/
+static boolean
+alpha_adjust_headers (abfd, fhdr, ahdr)
+ bfd *abfd;
+ struct internal_filehdr *fhdr;
+ struct internal_aouthdr *ahdr;
+{
+ if ((abfd->flags & (DYNAMIC | EXEC_P)) == (DYNAMIC | EXEC_P))
+ fhdr->f_flags |= F_ALPHA_CALL_SHARED;
+ else if ((abfd->flags & DYNAMIC) != 0)
+ fhdr->f_flags |= F_ALPHA_SHARABLE;
+ return true;
+}
+
+/* Archive handling. In OSF/1 (or Digital Unix) v3.2, Digital
+ introduced archive packing, in which the elements in an archive are
+ optionally compressed using a simple dictionary scheme. We know
+ how to read such archives, but we don't write them. */
+
+#define alpha_ecoff_slurp_armap _bfd_ecoff_slurp_armap
+#define alpha_ecoff_slurp_extended_name_table \
+ _bfd_ecoff_slurp_extended_name_table
+#define alpha_ecoff_construct_extended_name_table \
+ _bfd_ecoff_construct_extended_name_table
+#define alpha_ecoff_truncate_arname _bfd_ecoff_truncate_arname
+#define alpha_ecoff_write_armap _bfd_ecoff_write_armap
+#define alpha_ecoff_generic_stat_arch_elt _bfd_ecoff_generic_stat_arch_elt
+#define alpha_ecoff_update_armap_timestamp _bfd_ecoff_update_armap_timestamp
+
+/* A compressed file uses this instead of ARFMAG. */
+
+#define ARFZMAG "Z\012"
+
+/* Read an archive header. This is like the standard routine, but it
+ also accepts ARFZMAG. */
+
+static PTR
+alpha_ecoff_read_ar_hdr (abfd)
+ bfd *abfd;
+{
+ struct areltdata *ret;
+ struct ar_hdr *h;
+
+ ret = (struct areltdata *) _bfd_generic_read_ar_hdr_mag (abfd, ARFZMAG);
+ if (ret == NULL)
+ return NULL;
+
+ h = (struct ar_hdr *) ret->arch_header;
+ if (strncmp (h->ar_fmag, ARFZMAG, 2) == 0)
+ {
+ bfd_byte ab[8];
+
+ /* This is a compressed file. We must set the size correctly.
+ The size is the eight bytes after the dummy file header. */
+ if (bfd_seek (abfd, FILHSZ, SEEK_CUR) != 0
+ || bfd_read (ab, 1, 8, abfd) != 8
+ || bfd_seek (abfd, - (FILHSZ + 8), SEEK_CUR) != 0)
+ return NULL;
+
+ ret->parsed_size = bfd_h_get_64 (abfd, ab);
+ }
+
+ return (PTR) ret;
+}
+
+/* Get an archive element at a specified file position. This is where
+ we uncompress the archive element if necessary. */
+
+static bfd *
+alpha_ecoff_get_elt_at_filepos (archive, filepos)
+ bfd *archive;
+ file_ptr filepos;
+{
+ bfd *nbfd = NULL;
+ struct areltdata *tdata;
+ struct ar_hdr *hdr;
+ bfd_byte ab[8];
+ bfd_size_type size;
+ bfd_byte *buf, *p;
+ struct bfd_in_memory *bim;
+
+ nbfd = _bfd_get_elt_at_filepos (archive, filepos);
+ if (nbfd == NULL)
+ goto error_return;
+
+ if ((nbfd->flags & BFD_IN_MEMORY) != 0)
+ {
+ /* We have already expanded this BFD. */
+ return nbfd;
+ }
+
+ tdata = (struct areltdata *) nbfd->arelt_data;
+ hdr = (struct ar_hdr *) tdata->arch_header;
+ if (strncmp (hdr->ar_fmag, ARFZMAG, 2) != 0)
+ return nbfd;
+
+ /* We must uncompress this element. We do this by copying it into a
+ memory buffer, and making bfd_read and bfd_seek use that buffer.
+ This can use a lot of memory, but it's simpler than getting a
+ temporary file, making that work with the file descriptor caching
+ code, and making sure that it is deleted at all appropriate
+ times. It can be changed if it ever becomes important. */
+
+ /* The compressed file starts with a dummy ECOFF file header. */
+ if (bfd_seek (nbfd, FILHSZ, SEEK_SET) != 0)
+ goto error_return;
+
+ /* The next eight bytes are the real file size. */
+ if (bfd_read (ab, 1, 8, nbfd) != 8)
+ goto error_return;
+ size = bfd_h_get_64 (nbfd, ab);
+
+ if (size == 0)
+ buf = NULL;
+ else
+ {
+ bfd_size_type left;
+ bfd_byte dict[4096];
+ unsigned int h;
+ bfd_byte b;
+
+ buf = (bfd_byte *) bfd_alloc (nbfd, size);
+ if (buf == NULL)
+ goto error_return;
+ p = buf;
+
+ left = size;
+
+ /* I don't know what the next eight bytes are for. */
+ if (bfd_read (ab, 1, 8, nbfd) != 8)
+ goto error_return;
+
+ /* This is the uncompression algorithm. It's a simple
+ dictionary based scheme in which each character is predicted
+ by a hash of the previous three characters. A control byte
+ indicates whether the character is predicted or whether it
+ appears in the input stream; each control byte manages the
+ next eight bytes in the output stream. */
+ memset (dict, 0, sizeof dict);
+ h = 0;
+ while (bfd_read (&b, 1, 1, nbfd) == 1)
+ {
+ unsigned int i;
+
+ for (i = 0; i < 8; i++, b >>= 1)
+ {
+ bfd_byte n;
+
+ if ((b & 1) == 0)
+ n = dict[h];
+ else
+ {
+ if (! bfd_read (&n, 1, 1, nbfd))
+ goto error_return;
+ dict[h] = n;
+ }
+
+ *p++ = n;
+
+ --left;
+ if (left == 0)
+ break;
+
+ h <<= 4;
+ h ^= n;
+ h &= sizeof dict - 1;
+ }
+
+ if (left == 0)
+ break;
+ }
+ }
+
+ /* Now the uncompressed file contents are in buf. */
+ bim = ((struct bfd_in_memory *)
+ bfd_alloc (nbfd, sizeof (struct bfd_in_memory)));
+ if (bim == NULL)
+ goto error_return;
+ bim->size = size;
+ bim->buffer = buf;
+
+ nbfd->mtime_set = true;
+ nbfd->mtime = strtol (hdr->ar_date, (char **) NULL, 10);
+
+ nbfd->flags |= BFD_IN_MEMORY;
+ nbfd->iostream = (PTR) bim;
+ BFD_ASSERT (! nbfd->cacheable);
+
+ return nbfd;
+
+ error_return:
+ if (nbfd != NULL)
+ bfd_close (nbfd);
+ return NULL;
+}
+
+/* Open the next archived file. */
+
+static bfd *
+alpha_ecoff_openr_next_archived_file (archive, last_file)
+ bfd *archive;
+ bfd *last_file;
+{
+ file_ptr filestart;
+
+ if (last_file == NULL)
+ filestart = bfd_ardata (archive)->first_file_filepos;
+ else
+ {
+ struct areltdata *t;
+ struct ar_hdr *h;
+ bfd_size_type size;
+
+ /* We can't use arelt_size here, because that uses parsed_size,
+ which is the uncompressed size. We need the compressed size. */
+ t = (struct areltdata *) last_file->arelt_data;
+ h = (struct ar_hdr *) t->arch_header;
+ size = strtol (h->ar_size, (char **) NULL, 10);
+
+ /* 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 alpha_ecoff_get_elt_at_filepos (archive, filestart);
+}
+
+/* Open the archive file given an index into the armap. */
+
+static bfd *
+alpha_ecoff_get_elt_at_index (abfd, index)
+ bfd *abfd;
+ symindex index;
+{
+ carsym *entry;
+
+ entry = bfd_ardata (abfd)->symdefs + index;
+ return alpha_ecoff_get_elt_at_filepos (abfd, entry->file_offset);
+}
+
+/* This is the ECOFF backend structure. The backend field of the
+ target vector points to this. */
+
+static const struct ecoff_backend_data alpha_ecoff_backend_data =
+{
+ /* COFF backend structure. */
+ {
+ (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
+ (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
+ (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
+ (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
+ alpha_ecoff_swap_filehdr_out, alpha_ecoff_swap_aouthdr_out,
+ alpha_ecoff_swap_scnhdr_out,
+ FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, true,
+ alpha_ecoff_swap_filehdr_in, alpha_ecoff_swap_aouthdr_in,
+ alpha_ecoff_swap_scnhdr_in, NULL,
+ alpha_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
+ alpha_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
+ _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ },
+ /* Supported architecture. */
+ bfd_arch_alpha,
+ /* Initial portion of armap string. */
+ "________64",
+ /* The page boundary used to align sections in a demand-paged
+ executable file. E.g., 0x1000. */
+ 0x2000,
+ /* 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. */
+ true,
+ /* Bitsize of constructor entries. */
+ 64,
+ /* Reloc to use for constructor entries. */
+ &alpha_howto_table[ALPHA_R_REFQUAD],
+ {
+ /* Symbol table magic number. */
+ magicSym2,
+ /* Alignment of debugging information. E.g., 4. */
+ 8,
+ /* Sizes of external symbolic information. */
+ sizeof (struct hdr_ext),
+ sizeof (struct dnr_ext),
+ sizeof (struct pdr_ext),
+ sizeof (struct sym_ext),
+ sizeof (struct opt_ext),
+ sizeof (struct fdr_ext),
+ sizeof (struct rfd_ext),
+ sizeof (struct ext_ext),
+ /* Functions to swap in external symbolic data. */
+ ecoff_swap_hdr_in,
+ ecoff_swap_dnr_in,
+ ecoff_swap_pdr_in,
+ ecoff_swap_sym_in,
+ ecoff_swap_opt_in,
+ ecoff_swap_fdr_in,
+ ecoff_swap_rfd_in,
+ ecoff_swap_ext_in,
+ _bfd_ecoff_swap_tir_in,
+ _bfd_ecoff_swap_rndx_in,
+ /* Functions to swap out external symbolic data. */
+ ecoff_swap_hdr_out,
+ ecoff_swap_dnr_out,
+ ecoff_swap_pdr_out,
+ ecoff_swap_sym_out,
+ ecoff_swap_opt_out,
+ ecoff_swap_fdr_out,
+ ecoff_swap_rfd_out,
+ ecoff_swap_ext_out,
+ _bfd_ecoff_swap_tir_out,
+ _bfd_ecoff_swap_rndx_out,
+ /* Function to read in symbolic data. */
+ _bfd_ecoff_slurp_symbolic_info
+ },
+ /* External reloc size. */
+ RELSZ,
+ /* Reloc swapping functions. */
+ alpha_ecoff_swap_reloc_in,
+ alpha_ecoff_swap_reloc_out,
+ /* Backend reloc tweaking. */
+ alpha_adjust_reloc_in,
+ alpha_adjust_reloc_out,
+ /* Relocate section contents while linking. */
+ alpha_relocate_section,
+ /* Do final adjustments to filehdr and aouthdr. */
+ alpha_adjust_headers,
+ /* Read an element from an archive at a given file position. */
+ alpha_ecoff_get_elt_at_filepos
+};
+
+/* Looking up a reloc type is Alpha specific. */
+#define _bfd_ecoff_bfd_reloc_type_lookup alpha_bfd_reloc_type_lookup
+
+/* So is getting relocated section contents. */
+#define _bfd_ecoff_bfd_get_relocated_section_contents \
+ alpha_ecoff_get_relocated_section_contents
+
+/* Handling file windows is generic. */
+#define _bfd_ecoff_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+/* Relaxing sections is generic. */
+#define _bfd_ecoff_bfd_relax_section bfd_generic_relax_section
+
+const bfd_target ecoffalpha_little_vec =
+{
+ "ecoff-littlealpha", /* name */
+ bfd_target_ecoff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, alpha_ecoff_object_p, /* bfd_check_format */
+ _bfd_ecoff_archive_p, _bfd_dummy_target},
+ {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
+ BFD_JUMP_TABLE_COPY (_bfd_ecoff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (alpha_ecoff),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
+ BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
+ BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
+ BFD_JUMP_TABLE_LINK (_bfd_ecoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) &alpha_ecoff_backend_data
+};
diff --git a/contrib/gdb/bfd/coff-apollo.c b/contrib/gdb/bfd/coff-apollo.c
new file mode 100644
index 0000000..561b1c7
--- /dev/null
+++ b/contrib/gdb/bfd/coff-apollo.c
@@ -0,0 +1,162 @@
+/* BFD back-end for Apollo 68000 COFF binaries.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ By Troy Rollo (troy@cbme.unsw.edu.au)
+ Based on m68k standard COFF version Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/apollo.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+#ifdef ONLY_DECLARE_RELOCS
+extern reloc_howto_type apollocoff_howto_table[];
+#else
+reloc_howto_type apollocoff_howto_table[] =
+{
+ HOWTO(R_RELBYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, "8", true, 0x000000ff,0x000000ff, false),
+ HOWTO(R_RELWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, 0, "16", true, 0x0000ffff,0x0000ffff, false),
+ HOWTO(R_RELLONG, 0, 2, 32, false, 0, complain_overflow_bitfield, 0, "32", true, 0xffffffff,0xffffffff, false),
+ HOWTO(R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, 0, "DISP8", true, 0x000000ff,0x000000ff, false),
+ HOWTO(R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, 0, "DISP16", true, 0x0000ffff,0x0000ffff, false),
+ HOWTO(R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, 0, "DISP32", true, 0xffffffff,0xffffffff, false),
+ HOWTO(R_RELLONG_NEG, 0, -2, 32, false, 0, complain_overflow_bitfield, 0, "-32", true, 0xffffffff,0xffffffff, false),
+};
+#endif /* not ONLY_DECLARE_RELOCS */
+
+#ifndef BADMAG
+#define BADMAG(x) M68KBADMAG(x)
+#endif
+#define APOLLO_M68 1 /* Customize coffcode.h */
+
+/* Turn a howto into a reloc number */
+
+#ifdef ONLY_DECLARE_RELOCS
+extern void apollo_rtype2howto PARAMS ((arelent *internal, int relocentry));
+extern int apollo_howto2rtype PARAMS ((reloc_howto_type *));
+#else
+void
+apollo_rtype2howto(internal, relocentry)
+ arelent *internal;
+ int relocentry;
+{
+ switch (relocentry)
+ {
+ case R_RELBYTE: internal->howto = apollocoff_howto_table + 0; break;
+ case R_RELWORD: internal->howto = apollocoff_howto_table + 1; break;
+ case R_RELLONG: internal->howto = apollocoff_howto_table + 2; break;
+ case R_PCRBYTE: internal->howto = apollocoff_howto_table + 3; break;
+ case R_PCRWORD: internal->howto = apollocoff_howto_table + 4; break;
+ case R_PCRLONG: internal->howto = apollocoff_howto_table + 5; break;
+ case R_RELLONG_NEG: internal->howto = apollocoff_howto_table + 6; break;
+ }
+}
+
+int
+apollo_howto2rtype (internal)
+ reloc_howto_type *internal;
+{
+ if (internal->pc_relative)
+ {
+ switch (internal->bitsize)
+ {
+ case 32: return R_PCRLONG;
+ case 16: return R_PCRWORD;
+ case 8: return R_PCRBYTE;
+ }
+ }
+ else
+ {
+ switch (internal->bitsize)
+ {
+ case 32: return R_RELLONG;
+ case 16: return R_RELWORD;
+ case 8: return R_RELBYTE;
+ }
+ }
+ return R_RELLONG;
+}
+#endif /* not ONLY_DECLARE_RELOCS */
+
+#define RTYPE2HOWTO(internal, relocentry) \
+ apollo_rtype2howto(internal, (relocentry)->r_type)
+
+#define SELECT_RELOC(external, internal) \
+ external.r_type = apollo_howto2rtype(internal);
+
+#include "coffcode.h"
+
+const bfd_target
+#ifdef TARGET_SYM
+ TARGET_SYM =
+#else
+ apollocoff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+ TARGET_NAME,
+#else
+ "apollo-m68k", /* name */
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+#ifdef NAMES_HAVE_UNDERSCORE
+ '_',
+#else
+ 0, /* leading underscore */
+#endif
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE
+ };
diff --git a/contrib/gdb/bfd/coff-arm.c b/contrib/gdb/bfd/coff-arm.c
new file mode 100644
index 0000000..bb16b04
--- /dev/null
+++ b/contrib/gdb/bfd/coff-arm.c
@@ -0,0 +1,537 @@
+/* BFD back-end for ARM COFF files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+
+#include "coff/arm.h"
+
+#include "coff/internal.h"
+
+#ifdef COFF_WITH_PE
+#include "coff/pe.h"
+#endif
+
+#include "libcoff.h"
+
+static bfd_reloc_status_type
+aoutarm_fix_pcrel_26_done PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+static bfd_reloc_status_type
+aoutarm_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+
+static bfd_reloc_status_type coff_arm_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+
+
+/* Used by the assembler. */
+static bfd_reloc_status_type
+coff_arm_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ symvalue diff;
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ diff = reloc_entry->addend;
+
+#define DOIT(x) \
+ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
+
+ if (diff != 0)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+ unsigned char *addr = (unsigned char *) data + reloc_entry->address;
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, addr);
+ DOIT (x);
+ bfd_put_8 (abfd, x, addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_get_16 (abfd, addr);
+ DOIT (x);
+ bfd_put_16 (abfd, x, addr);
+ }
+ break;
+
+ case 2:
+ {
+ long x = bfd_get_32 (abfd, addr);
+ DOIT (x);
+ bfd_put_32 (abfd, x, addr);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ /* Now let bfd_perform_relocation finish everything up. */
+ return bfd_reloc_continue;
+}
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET true
+#endif
+
+static reloc_howto_type aoutarm_std_reloc_howto[] =
+{
+ /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */
+ HOWTO(0, /* type */
+ 0, /* rs */
+ 0, /* size */
+ 8, /* bsz */
+ false, /* pcrel */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* ovf */
+ coff_arm_reloc, /* sf */
+ "8", /*name */
+ true, /* partial */
+ 0x000000ff, /*read mask */
+ 0x000000ff, /* setmask */
+ PCRELOFFSET /* pcdone */),
+ HOWTO(1,
+ 0,
+ 1,
+ 16,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ coff_arm_reloc,
+ "16",
+ true,
+ 0x0000ffff,
+ 0x0000ffff,
+ PCRELOFFSET),
+ HOWTO( 2,
+ 0,
+ 2,
+ 32,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ coff_arm_reloc,
+ "32",
+ true,
+ 0xffffffff,
+ 0xffffffff,
+ PCRELOFFSET),
+ HOWTO( 3,
+ 2,
+ 2,
+ 26,
+ true,
+ 0,
+ complain_overflow_signed,
+ aoutarm_fix_pcrel_26 ,
+ "ARM26",
+ false,
+ 0x00ffffff,
+ 0x00ffffff,
+ PCRELOFFSET),
+ HOWTO( 4,
+ 0,
+ 0,
+ 8,
+ true,
+ 0,
+ complain_overflow_signed,
+ coff_arm_reloc,
+ "DISP8",
+ true,
+ 0x000000ff,
+ 0x000000ff,
+ true),
+ HOWTO( 5,
+ 0,
+ 1,
+ 16,
+ true,
+ 0,
+ complain_overflow_signed,
+ coff_arm_reloc,
+ "DISP16",
+ true,
+ 0x0000ffff,
+ 0x0000ffff,
+ true),
+ HOWTO( 6,
+ 0,
+ 2,
+ 32,
+ true,
+ 0,
+ complain_overflow_signed,
+ coff_arm_reloc,
+ "DISP32",
+ true,
+ 0xffffffff,
+ 0xffffffff,
+ true),
+ HOWTO( 7,
+ 2,
+ 2,
+ 26,
+ false,
+ 0,
+ complain_overflow_signed,
+ aoutarm_fix_pcrel_26_done,
+ "ARM26D",
+ true,
+ 0x00ffffff,
+ 0x00ffffff,
+ false),
+ {-1},
+ HOWTO( 9,
+ 0,
+ -1,
+ 16,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ coff_arm_reloc,
+ "NEG16",
+ true,
+ 0x0000ffff,
+ 0x0000ffff,
+ false),
+ HOWTO( 10,
+ 0,
+ -2,
+ 32,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ coff_arm_reloc,
+ "NEG32",
+ true,
+ 0xffffffff,
+ 0xffffffff,
+ false),
+ HOWTO( 11,
+ 0,
+ 2,
+ 32,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ coff_arm_reloc,
+ "rva32",
+ true,
+ 0xffffffff,
+ 0xffffffff,
+ PCRELOFFSET),
+};
+#ifdef COFF_WITH_PE
+/* Return true if this relocation should
+ appear in the output .reloc section. */
+
+static boolean in_reloc_p (abfd, howto)
+ bfd * abfd;
+ reloc_howto_type *howto;
+{
+ return !howto->pc_relative && howto->type != 11;
+}
+#endif
+
+
+#define RTYPE2HOWTO(cache_ptr, dst) \
+ (cache_ptr)->howto = aoutarm_std_reloc_howto + (dst)->r_type;
+
+#define coff_rtype_to_howto coff_arm_rtype_to_howto
+
+static reloc_howto_type *
+coff_arm_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+ reloc_howto_type *howto;
+
+ howto = aoutarm_std_reloc_howto + rel->r_type;
+
+ if (rel->r_type == 11)
+ {
+ *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+ }
+ return howto;
+
+}
+/* Used by the assembler. */
+
+static bfd_reloc_status_type
+aoutarm_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* This is dead simple at present. */
+ return bfd_reloc_ok;
+}
+
+/* Used by the assembler. */
+
+static bfd_reloc_status_type
+aoutarm_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_vma relocation;
+ bfd_size_type addr = reloc_entry->address;
+ long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+ bfd_reloc_status_type flag = bfd_reloc_ok;
+
+ /* If this is an undefined symbol, return error */
+ if (symbol->section == &bfd_und_section
+ && (symbol->flags & BSF_WEAK) == 0)
+ return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
+
+ /* If the sections are different, and we are doing a partial relocation,
+ just ignore it for now. */
+ if (symbol->section->name != input_section->name
+ && output_bfd != (bfd *)NULL)
+ return bfd_reloc_continue;
+
+ relocation = (target & 0x00ffffff) << 2;
+ relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */
+ relocation += symbol->value;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+ relocation -= input_section->output_section->vma;
+ relocation -= input_section->output_offset;
+ relocation -= addr;
+ if (relocation & 3)
+ return bfd_reloc_overflow;
+
+ /* Check for overflow */
+ if (relocation & 0x02000000)
+ {
+ if ((relocation & ~0x03ffffff) != ~0x03ffffff)
+ flag = bfd_reloc_overflow;
+ }
+ else if (relocation & ~0x03ffffff)
+ flag = bfd_reloc_overflow;
+
+ target &= ~0x00ffffff;
+ target |= (relocation >> 2) & 0x00ffffff;
+ bfd_put_32 (abfd, target, (bfd_byte *) data + addr);
+
+ /* Now the ARM magic... Change the reloc type so that it is marked as done.
+ Strictly this is only necessary if we are doing a partial relocation. */
+ reloc_entry->howto = &aoutarm_std_reloc_howto[7];
+
+ return flag;
+}
+
+
+static CONST struct reloc_howto_struct *
+arm_reloc_type_lookup(abfd,code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+#define ASTD(i,j) case i: return &aoutarm_std_reloc_howto[j]
+ if (code == BFD_RELOC_CTOR)
+ switch (bfd_get_arch_info (abfd)->bits_per_address)
+ {
+ case 32:
+ code = BFD_RELOC_32;
+ break;
+ default: return (CONST struct reloc_howto_struct *) 0;
+ }
+
+ switch (code)
+ {
+ ASTD (BFD_RELOC_16, 1);
+ ASTD (BFD_RELOC_32, 2);
+ ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
+ ASTD (BFD_RELOC_8_PCREL, 4);
+ ASTD (BFD_RELOC_16_PCREL, 5);
+ ASTD (BFD_RELOC_32_PCREL, 6);
+ ASTD (BFD_RELOC_RVA, 11);
+ default: return (CONST struct reloc_howto_struct *) 0;
+ }
+}
+
+
+#define coff_bfd_reloc_type_lookup arm_reloc_type_lookup
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
+#define COFF_PAGE_SIZE 0x1000
+/* Turn a howto into a reloc nunmber */
+
+#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
+#define BADMAG(x) ARMBADMAG(x)
+#define ARM 1 /* Customize coffcode.h */
+
+
+/* We use the special COFF backend linker. */
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+
+#include "coffcode.h"
+
+const bfd_target
+#ifdef TARGET_LITTLE_SYM
+TARGET_LITTLE_SYM =
+#else
+armcoff_little_vec =
+#endif
+{
+#ifdef TARGET_LITTLE_NAME
+ TARGET_LITTLE_NAME,
+#else
+ "coff-arm-little",
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+#ifdef TARGET_UNDERSCORE
+ TARGET_UNDERSCORE, /* leading underscore */
+#else
+ 0, /* leading underscore */
+#endif
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+/* Note that we allow an object file to be treated as a core file as well. */
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, coff_object_p},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
+
+const bfd_target
+#ifdef TARGET_BIG_SYM
+TARGET_BIG_SYM =
+#else
+armcoff_big_vec =
+#endif
+{
+#ifdef TARGET_BIG_NAME
+ TARGET_BIG_NAME,
+#else
+ "coff-arm-big",
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+#ifdef TARGET_UNDERSCORE
+ TARGET_UNDERSCORE, /* leading underscore */
+#else
+ 0, /* leading underscore */
+#endif
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+ 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 */
+
+/* Note that we allow an object file to be treated as a core file as well. */
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, coff_object_p},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-aux.c b/contrib/gdb/bfd/coff-aux.c
new file mode 100644
index 0000000..1dba9d5
--- /dev/null
+++ b/contrib/gdb/bfd/coff-aux.c
@@ -0,0 +1,332 @@
+/* BFD back-end for Apple M68K COFF A/UX 3.x files.
+ Copyright 1996 Free Software Foundation, Inc.
+ Portions written by Richard Henderson <rth@tamu.edu>,
+ COMMON symbol munging cribbed from cf-m68klynx.c which was
+ written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_SYM m68kaux_coff_vec
+#define TARGET_NAME "coff-m68k-aux"
+
+#ifndef TARG_AUX
+#define TARG_AUX
+#endif
+
+#define COFF_LONG_FILENAMES
+
+/* 4k pages */
+#define COFF_PAGE_SIZE 0x1000
+
+/* On AUX, a STYP_NOLOAD|STYP_BSS section is part of a shared library. */
+#define BSS_NOLOAD_IS_SHARED_LIBRARY
+
+#define _bfd_m68kcoff_howto_table _bfd_m68kaux_howto_table
+#define _bfd_m68kcoff_rtype2howto _bfd_m68kaux_rtype2howto
+#define _bfd_m68kcoff_howto2rtype _bfd_m68kaux_howto2rtype
+#define _bfd_m68kcoff_reloc_type_lookup _bfd_m68kaux_reloc_type_lookup
+
+/* Rather than change names lots of places, reuse the same hack */
+#define LYNX_SPECIAL_FN _bfd_m68kaux_special_fn
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#ifdef ANSI_PROTOTYPES
+struct internal_reloc;
+struct coff_link_hash_entry;
+struct internal_syment;
+#endif
+
+
+static bfd_reloc_status_type _bfd_m68kaux_special_fn
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static reloc_howto_type *coff_m68k_aux_rtype_to_howto
+ PARAMS ((bfd *, asection *, struct internal_reloc *,
+ struct coff_link_hash_entry *, struct internal_syment *,
+ bfd_vma *));
+static boolean coff_m68k_aux_link_add_one_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword,
+ asection *, bfd_vma, const char *, boolean, boolean,
+ struct bfd_link_hash_entry **));
+
+
+#define coff_rtype_to_howto coff_m68k_aux_rtype_to_howto
+#define coff_link_add_one_symbol coff_m68k_aux_link_add_one_symbol
+
+
+/* Compute the addend of a reloc. If the reloc is to a common symbol,
+ the object file contains the value of the common symbol. By the
+ time this is called, the linker may be using a different symbol
+ from a different object file with a different value. Therefore, we
+ hack wildly to locate the original symbol from this file so that we
+ can make the correct adjustment. This macro sets coffsym to the
+ symbol from the original file, and uses it to set the addend value
+ correctly. If this is not a common symbol, the usual addend
+ calculation is done, except that an additional tweak is needed for
+ PC relative relocs.
+ FIXME: This macro refers to symbols and asect; these are from the
+ calling function, not the macro arguments. */
+
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = - coffsym->native->u.syment.n_value; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ if (ptr && (reloc.r_type == R_PCRBYTE \
+ || reloc.r_type == R_PCRWORD \
+ || reloc.r_type == R_PCRLONG)) \
+ cache_ptr->addend += asect->vma; \
+ }
+
+
+
+#include "coff/aux-coff.h" /* override coff/internal.h and coff/m68k.h */
+#include "coff-m68k.c"
+
+
+
+/* For some reason when using m68k COFF the value stored in the .text
+ section for a reference to a common symbol is the value itself plus
+ any desired offset. (taken from work done by Ian Taylor, Cygnus Support,
+ for I386 COFF). */
+
+/* If we are producing relocateable output, we need to do some
+ adjustments to the object file that are not done by the
+ bfd_perform_relocation function. This function is called by every
+ reloc type to make any required adjustments. */
+
+static bfd_reloc_status_type
+_bfd_m68kaux_special_fn (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ symvalue diff;
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ /* We are relocating a common symbol. The current value in the
+ object file is ORIG + OFFSET, where ORIG is the value of the
+ common symbol as seen by the object file when it was compiled
+ (this may be zero if the symbol was undefined) and OFFSET is
+ the offset into the common symbol (normally zero, but may be
+ non-zero when referring to a field in a common structure).
+ ORIG is the negative of reloc_entry->addend, which is set by
+ the CALC_ADDEND macro below. We want to replace the value in
+ the object file with NEW + OFFSET, where NEW is the value of
+ the common symbol which we are going to put in the final
+ object file. NEW is symbol->value. */
+ diff = symbol->value + reloc_entry->addend;
+ }
+ else
+ {
+ /* For some reason bfd_perform_relocation always effectively
+ ignores the addend for a COFF target when producing
+ relocateable output. This seems to be always wrong for 386
+ COFF, so we handle the addend here instead. */
+ diff = reloc_entry->addend;
+ }
+
+#define DOIT(x) \
+ x = ((x & ~howto->dst_mask) | \
+ (((x & howto->src_mask) + diff) & howto->dst_mask))
+
+ if (diff != 0)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+ unsigned char *addr = (unsigned char *) data + reloc_entry->address;
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, addr);
+ DOIT (x);
+ bfd_put_8 (abfd, x, addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_get_16 (abfd, addr);
+ DOIT (x);
+ bfd_put_16 (abfd, x, addr);
+ }
+ break;
+
+ case 2:
+ {
+ long x = bfd_get_32 (abfd, addr);
+ DOIT (x);
+ bfd_put_32 (abfd, x, addr);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ /* Now let bfd_perform_relocation finish everything up. */
+ return bfd_reloc_continue;
+}
+
+
+/* coff-m68k.c uses the special COFF backend linker. We need to
+ adjust common symbols. */
+
+/*ARGSUSED*/
+static reloc_howto_type *
+coff_m68k_aux_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+ arelent relent;
+ reloc_howto_type *howto;
+
+ RTYPE2HOWTO (&relent, rel);
+
+ howto = relent.howto;
+
+ if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
+ {
+ /* This is a common symbol. The section contents include the
+ size (sym->n_value) as an addend. The relocate_section
+ function will be adding in the final value of the symbol. We
+ need to subtract out the current size in order to get the
+ correct result. */
+ BFD_ASSERT (h != NULL);
+ *addendp -= sym->n_value;
+ }
+
+ /* If the output symbol is common (in which case this must be a
+ relocateable link), we need to add in the final size of the
+ common symbol. */
+ if (h != NULL && h->root.type == bfd_link_hash_common)
+ *addendp += h->root.u.c.size;
+
+ return howto;
+}
+
+
+/* We need non-absolute symbols to override absolute symbols. This
+ mirrors Apple's "solution" to let a static library symbol override
+ a shared library symbol. On the whole not a good thing, given how
+ shared libraries work here, but can work if you are careful with
+ what you include in the shared object. */
+
+boolean
+coff_m68k_aux_link_add_one_symbol (info, abfd, name, flags, section, value,
+ string, copy, collect, hashp)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ const char *name;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ const char *string;
+ boolean copy;
+ boolean collect;
+ struct bfd_link_hash_entry **hashp;
+{
+ struct bfd_link_hash_entry *h;
+
+ if ((flags & (BSF_WARNING | BSF_CONSTRUCTOR | BSF_WEAK)) == 0 &&
+ !bfd_is_und_section (section) &&
+ !bfd_is_com_section (section))
+ {
+ /* The new symbol is a definition or an indirect definition */
+
+ /* This bit copied from linker.c */
+ if (hashp != NULL && *hashp != NULL)
+ {
+ h = *hashp;
+ BFD_ASSERT (strcmp (h->root.string, name) == 0);
+ }
+ else
+ {
+ h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
+ if (h == NULL)
+ {
+ if (hashp != NULL)
+ *hashp = NULL;
+ return false;
+ }
+ }
+
+ if (info->notice_hash != (struct bfd_hash_table *) NULL
+ && (bfd_hash_lookup (info->notice_hash, name, false, false)
+ != (struct bfd_hash_entry *) NULL))
+ {
+ if (! (*info->callbacks->notice) (info, name, abfd, section, value))
+ return false;
+ }
+
+ if (hashp != (struct bfd_link_hash_entry **) NULL)
+ *hashp = h;
+ /* end duplication from linker.c */
+
+ if (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_indirect)
+ {
+ asection *msec;
+
+ if (h->type == bfd_link_hash_defined)
+ msec = h->u.def.section;
+ else
+ msec = bfd_ind_section_ptr;
+
+ if (bfd_is_abs_section (msec) && !bfd_is_abs_section (section))
+ {
+ h->u.def.section = section;
+ h->u.def.value = value;
+ return true;
+ }
+ else if (bfd_is_abs_section (section) && !bfd_is_abs_section (msec))
+ return true;
+ }
+ }
+
+ /* If we didn't exit early, finish processing in the generic routine */
+ return _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
+ value, string, copy, collect,
+ hashp);
+}
diff --git a/contrib/gdb/bfd/coff-go32.c b/contrib/gdb/bfd/coff-go32.c
new file mode 100644
index 0000000..be4adb2
--- /dev/null
+++ b/contrib/gdb/bfd/coff-go32.c
@@ -0,0 +1,25 @@
+/* BFD back-end for Intel 386 COFF files (go32 variant).
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Written by DJ Delorie.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_SYM go32coff_vec
+#define TARGET_NAME "coff-go32"
+#define TARGET_UNDERSCORE '_'
+
+#include "coff-i386.c"
diff --git a/contrib/gdb/bfd/coff-h8300.c b/contrib/gdb/bfd/coff-h8300.c
new file mode 100644
index 0000000..48d0d5a
--- /dev/null
+++ b/contrib/gdb/bfd/coff-h8300.c
@@ -0,0 +1,650 @@
+/* BFD back-end for Hitachi H8/300 COFF binaries.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by Steve Chamberlain, <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "obstack.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "genlink.h"
+#include "coff/h8300.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
+
+
+/* special handling for H8/300 relocs.
+ We only come here for pcrel stuff and return normally if not an -r link.
+ When doing -r, we can't do any arithmetic for the pcrel stuff, because
+ the code in reloc.c assumes that we can manipulate the targets of
+ the pcrel branches. This isn't so, since the H8/300 can do relaxing,
+ which means that the gap after the instruction may not be enough to
+ contain the offset required for the branch, so we have to use the only
+ the addend until the final link */
+
+static bfd_reloc_status_type
+special (abfd, reloc_entry, symbol, data, input_section, 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)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+static reloc_howto_type howto_table[] =
+{
+ HOWTO (R_RELBYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "8", false, 0x000000ff, 0x000000ff, false),
+ HOWTO (R_RELWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16", false, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_RELLONG, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "32", false, 0xffffffff, 0xffffffff, false),
+ HOWTO (R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, special, "DISP8", false, 0x000000ff, 0x000000ff, true),
+ HOWTO (R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, special, "DISP16", false, 0x0000ffff, 0x0000ffff, true),
+ HOWTO (R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, special, "DISP32", false, 0xffffffff, 0xffffffff, true),
+ HOWTO (R_MOVB1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/8", false, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_MOVB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/16", false, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_JMP1, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "16/pcrel", false, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_JMP2, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pcrecl/16", false, 0x000000ff, 0x000000ff, false),
+
+
+ HOWTO (R_JMPL1, 0, 2, 32, false, 0, complain_overflow_bitfield, special, "24/pcrell", false, 0x00ffffff, 0x00ffffff, false),
+ HOWTO (R_JMPL_B8, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "pc8/24", false, 0x000000ff, 0x000000ff, false),
+
+ HOWTO (R_MOVLB1, 0, 1, 16, false, 0, complain_overflow_bitfield,special, "24/8", false, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_MOVLB2, 0, 1, 16, false, 0, complain_overflow_bitfield, special, "8/24", false, 0x0000ffff, 0x0000ffff, false),
+
+ /* An indirect reference to a function. This causes the function's address
+ to be added to the function vector in lo-mem and puts the address of
+ the function vector's entry in the jsr instruction. */
+ HOWTO (R_MEM_INDIRECT, 0, 0, 8, false, 0, complain_overflow_bitfield, special, "8/indirect", false, 0x000000ff, 0x000000ff, false),
+
+};
+
+
+/* Turn a howto into a reloc number */
+
+#define SELECT_RELOC(x,howto) \
+ { x.r_type = select_reloc(howto); }
+
+#define BADMAG(x) (H8300BADMAG(x)&& H8300HBADMAG(x))
+#define H8300 1 /* Customize coffcode.h */
+#define __A_MAGIC_SET__
+
+
+
+/* Code to swap in the reloc */
+#define SWAP_IN_RELOC_OFFSET bfd_h_get_32
+#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
+#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
+ dst->r_stuff[0] = 'S'; \
+ dst->r_stuff[1] = 'C';
+
+
+static int
+select_reloc (howto)
+ reloc_howto_type *howto;
+{
+ return howto->type;
+}
+
+/* Code to turn a r_type into a howto ptr, uses the above howto table
+ */
+
+static void
+rtype2howto (internal, dst)
+ arelent *internal;
+ struct internal_reloc *dst;
+{
+ switch (dst->r_type)
+ {
+ case R_RELBYTE:
+ internal->howto = howto_table + 0;
+ break;
+ case R_RELWORD:
+ internal->howto = howto_table + 1;
+ break;
+ case R_RELLONG:
+ internal->howto = howto_table + 2;
+ break;
+ case R_PCRBYTE:
+ internal->howto = howto_table + 3;
+ break;
+ case R_PCRWORD:
+ internal->howto = howto_table + 4;
+ break;
+ case R_PCRLONG:
+ internal->howto = howto_table + 5;
+ break;
+ case R_MOVB1:
+ internal->howto = howto_table + 6;
+ break;
+ case R_MOVB2:
+ internal->howto = howto_table + 7;
+ break;
+ case R_JMP1:
+ internal->howto = howto_table + 8;
+ break;
+ case R_JMP2:
+ internal->howto = howto_table + 9;
+ break;
+ case R_JMPL1:
+ internal->howto = howto_table + 10;
+ break;
+ case R_JMPL_B8:
+ internal->howto = howto_table + 11;
+ break;
+ case R_MOVLB1:
+ internal->howto = howto_table + 12;
+ break;
+ case R_MOVLB2:
+ internal->howto = howto_table + 13;
+ break;
+ case R_MEM_INDIRECT:
+ internal->howto = howto_table + 14;
+ break;
+ default:
+ abort ();
+ break;
+ }
+}
+
+#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
+
+
+/* Perform any necessaru magic to the addend in a reloc entry */
+
+
+#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
+ cache_ptr->addend = ext_reloc.r_offset;
+
+
+#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
+ reloc_processing(relent, reloc, symbols, abfd, section)
+
+static void
+reloc_processing (relent, reloc, symbols, abfd, section)
+ arelent * relent;
+ struct internal_reloc *reloc;
+ asymbol ** symbols;
+ bfd * abfd;
+ asection * section;
+{
+ relent->address = reloc->r_vaddr;
+ rtype2howto (relent, reloc);
+
+ if (((int) reloc->r_symndx) > 0)
+ {
+ relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
+ }
+ else
+ {
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ }
+
+
+
+ relent->addend = reloc->r_offset;
+
+ relent->address -= section->vma;
+ /* relent->section = 0;*/
+}
+
+
+static int
+h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
+ bfd *abfd;
+ asection *input_section;
+ arelent *reloc;
+ unsigned int shrink;
+ struct bfd_link_info *link_info;
+{
+ bfd_vma value;
+ bfd_vma dot;
+ bfd_vma gap;
+
+ /* The address of the thing to be relocated will have moved back by
+ the size of the shrink - but we don't change reloc->address here,
+ since we need it to know where the relocation lives in the source
+ uncooked section */
+
+ /* reloc->address -= shrink; conceptual */
+
+ bfd_vma address = reloc->address - shrink;
+
+
+ switch (reloc->howto->type)
+ {
+ case R_MOVB2:
+ case R_JMP2:
+ shrink+=2;
+ break;
+
+ /* Thing is a move one byte */
+ case R_MOVB1:
+ value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+
+ if (value >= 0xff00)
+ {
+
+ /* Change the reloc type from 16bit, possible 8 to 8bit
+ possible 16 */
+ reloc->howto = reloc->howto + 1;
+ /* The place to relc moves back by one */
+ /* This will be two bytes smaller in the long run */
+ shrink +=2 ;
+ bfd_perform_slip(abfd, 2, input_section, address);
+ }
+
+ break;
+ /* This is the 24 bit branch which could become an 8 bitter,
+ the relocation points to the first byte of the insn, not the
+ actual data */
+
+ case R_JMPL1:
+ value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+
+ dot = input_section->output_section->vma +
+ input_section->output_offset + address;
+
+ /* See if the address we're looking at within 127 bytes of where
+ we are, if so then we can use a small branch rather than the
+ jump we were going to */
+
+ gap = value - dot ;
+
+ if (-120 < (long)gap && (long)gap < 120 )
+ {
+
+ /* Change the reloc type from 24bit, possible 8 to 8bit
+ possible 32 */
+ reloc->howto = reloc->howto + 1;
+ /* This will be two bytes smaller in the long run */
+ shrink +=2 ;
+ bfd_perform_slip(abfd, 2, input_section, address);
+ }
+ break;
+
+ case R_JMP1:
+
+ value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+
+ dot = input_section->output_section->vma +
+ input_section->output_offset + address;
+
+ /* See if the address we're looking at within 127 bytes of where
+ we are, if so then we can use a small branch rather than the
+ jump we were going to */
+
+ gap = value - (dot - shrink);
+
+
+ if (-120 < (long)gap && (long)gap < 120 )
+ {
+
+ /* Change the reloc type from 16bit, possible 8 to 8bit
+ possible 16 */
+ reloc->howto = reloc->howto + 1;
+ /* The place to relc moves back by one */
+
+ /* This will be two bytes smaller in the long run */
+ shrink +=2 ;
+ bfd_perform_slip(abfd, 2, input_section, address);
+ }
+ break;
+ }
+
+
+ return shrink;
+}
+
+
+/* First phase of a relaxing link */
+
+/* Reloc types
+ large small
+ R_MOVB1 R_MOVB2 mov.b with 16bit or 8 bit address
+ R_JMP1 R_JMP2 jmp or pcrel branch
+ R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
+ R_MOVLB1 R_MOVLB2 24 or 8 bit reloc for mov.b
+
+*/
+
+static void
+h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
+ dst_ptr)
+ bfd *abfd;
+ 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;
+{
+ unsigned int src_address = *src_ptr;
+ unsigned int dst_address = *dst_ptr;
+ asection *input_section = link_order->u.indirect.section;
+
+ switch (reloc->howto->type)
+ {
+ /* A 24 bit branch which could be a 8 bit pcrel, really pointing to
+ the byte before the 24bit hole, so we can treat it as a 32bit pointer */
+ case R_PCRBYTE:
+ {
+ bfd_vma dot = link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma;
+ int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
+ - dot);
+ if (gap > 127 || gap < -128)
+ {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort ();
+ }
+ gap &= ~1;
+ bfd_put_8 (abfd, gap, data + dst_address);
+ dst_address++;
+ src_address++;
+
+ break;
+ }
+ case R_PCRWORD:
+ {
+ bfd_vma dot = link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma;
+ int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
+ - dot) - 1;
+ if (gap > 32767 || gap < -32768)
+ {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort ();
+ }
+
+ bfd_put_16 (abfd, gap, data + dst_address);
+ dst_address+=2;
+ src_address+=2;
+
+ break;
+ }
+
+ case R_MEM_INDIRECT: /* Temporary */
+ case R_RELBYTE:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ if (gap < 0xff
+ || (gap >= 0x0000ff00
+ && gap <= 0x0000ffff)
+ || ( gap >= 0x00ffff00
+ && gap <= 0x00ffffff)
+ || ( gap >= 0xffffff00
+ && gap <= 0xffffffff))
+ {
+ bfd_put_8 (abfd, gap, data + dst_address);
+ dst_address += 1;
+ src_address += 1;
+ }
+ else
+ {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort ();
+ }
+ }
+ break;
+ case R_JMP1:
+ /* A relword which would have like to have been a pcrel */
+ case R_MOVB1:
+ /* A relword which would like to have been modified but
+ didn't make it */
+ case R_RELWORD:
+ bfd_put_16 (abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ data + dst_address);
+ dst_address += 2;
+ src_address += 2;
+ break;
+ case R_RELLONG:
+ bfd_put_32 (abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ data + dst_address);
+ dst_address += 4;
+ src_address += 4;
+ break;
+
+ case R_MOVB2:
+ /* Special relaxed type, there will be a gap between where we
+ get stuff from and where we put stuff to now
+
+ for a mov.b @aa:16 -> mov.b @aa:8
+ opcode 0x6a 0x0y offset
+ -> 0x2y off
+ */
+ if (data[dst_address - 1] != 0x6a)
+ abort ();
+ switch (data[src_address] & 0xf0)
+ {
+ case 0x00:
+ /* Src is memory */
+ data[dst_address - 1] = (data[src_address] & 0xf) | 0x20;
+ break;
+ case 0x80:
+ /* Src is reg */
+ data[dst_address - 1] = (data[src_address] & 0xf) | 0x30;
+ break;
+ default:
+ abort ();
+ }
+
+ /* the offset must fit ! after all, what was all the relaxing
+ about ? */
+
+ bfd_put_8 (abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ data + dst_address);
+
+ /* Note the magic - src goes up by two bytes, but dst by only
+ one */
+ dst_address += 1;
+ src_address += 3;
+
+ break;
+
+ case R_JMP2:
+
+ /* Speciial relaxed type */
+ {
+ bfd_vma dot = link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma;
+
+ int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
+ - dot - 1);
+
+ if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
+ abort ();
+
+ bfd_put_8 (abfd, gap, data + dst_address);
+
+ switch (data[dst_address - 1])
+ {
+ case 0x5e:
+ /* jsr -> bsr */
+ bfd_put_8 (abfd, 0x55, data + dst_address - 1);
+ break;
+ case 0x5a:
+ /* jmp ->bra */
+ bfd_put_8 (abfd, 0x40, data + dst_address - 1);
+ break;
+
+ default:
+ abort ();
+ }
+ dst_address++;
+ src_address += 3;
+
+ break;
+ }
+ break;
+
+ case R_JMPL_B8: /* 24 bit branch which is now 8 bits */
+
+ /* Speciial relaxed type */
+ {
+ bfd_vma dot = link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma;
+
+ int gap = (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
+ - dot - 2);
+
+ if ((gap & ~0xff) != 0 && ((gap & 0xff00) != 0xff00))
+ abort ();
+
+ switch (data[src_address])
+ {
+ case 0x5e:
+ /* jsr -> bsr */
+ bfd_put_8 (abfd, 0x55, data + dst_address);
+ break;
+ case 0x5a:
+ /* jmp ->bra */
+ bfd_put_8 (abfd, 0x40, data + dst_address);
+ break;
+
+ default:
+ bfd_put_8 (abfd, 0xde, data + dst_address);
+ break;
+ }
+
+ bfd_put_8 (abfd, gap, data + dst_address + 1);
+ dst_address += 2;
+ src_address += 4;
+
+ break;
+ }
+
+ case R_JMPL1:
+ {
+ int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ int o = bfd_get_32 (abfd, data + src_address);
+ v = (v & 0x00ffffff) | (o & 0xff000000);
+ bfd_put_32 (abfd, v, data + dst_address);
+ dst_address += 4;
+ src_address += 4;
+ }
+
+ break;
+
+
+ /* A 24 bit mov which could be an 8 bit move, really pointing to
+ the byte before the 24bit hole, so we can treat it as a 32bit pointer */
+ case R_MOVLB1:
+ {
+ int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
+ int o = bfd_get_32 (abfd, data + dst_address);
+ v = (v & 0x00ffffff) | (o & 0xff000000);
+ bfd_put_32 (abfd, v, data + dst_address);
+ dst_address += 4;
+ src_address += 4;
+ }
+
+ break;
+ default:
+
+ abort ();
+ break;
+
+ }
+ *src_ptr = src_address;
+ *dst_ptr = dst_address;
+
+}
+
+#define coff_reloc16_extra_cases h8300_reloc16_extra_cases
+#define coff_reloc16_estimate h8300_reloc16_estimate
+
+#define COFF_LONG_FILENAMES
+#include "coffcode.h"
+
+
+#undef coff_bfd_get_relocated_section_contents
+#undef coff_bfd_relax_section
+#define coff_bfd_get_relocated_section_contents \
+ bfd_coff_reloc16_get_relocated_section_contents
+#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
+
+
+
+const bfd_target h8300coff_vec =
+{
+ "coff-h8300", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-h8500.c b/contrib/gdb/bfd/coff-h8500.c
new file mode 100644
index 0000000..f416f8f
--- /dev/null
+++ b/contrib/gdb/bfd/coff-h8500.c
@@ -0,0 +1,355 @@
+/* BFD back-end for Hitachi H8/500 COFF binaries.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ Written by Steve Chamberlain, <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "obstack.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "coff/h8500.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
+
+static reloc_howto_type r_imm8 =
+HOWTO (R_H8500_IMM8, 0, 1, 8, false, 0,
+ complain_overflow_bitfield, 0, "r_imm8", true, 0x000000ff, 0x000000ff, false);
+
+static reloc_howto_type r_imm16 =
+HOWTO (R_H8500_IMM16, 0, 1, 16, false, 0,
+ complain_overflow_bitfield, 0, "r_imm16", true, 0x0000ffff, 0x0000ffff, false);
+
+static reloc_howto_type r_imm24 =
+HOWTO (R_H8500_IMM24, 0, 1, 24, false, 0,
+ complain_overflow_bitfield, 0, "r_imm24", true, 0x00ffffff, 0x00ffffff, false);
+
+static reloc_howto_type r_imm32 =
+HOWTO (R_H8500_IMM32, 0, 1, 32, false, 0,
+ complain_overflow_bitfield, 0, "r_imm32", true, 0xffffffff, 0xffffffff, false);
+
+
+static reloc_howto_type r_high8 =
+HOWTO (R_H8500_HIGH8, 0, 1, 8, false, 0,
+ complain_overflow_dont, 0, "r_high8", true, 0x000000ff, 0x000000ff, false);
+
+static reloc_howto_type r_low16 =
+HOWTO (R_H8500_LOW16, 0, 1, 16, false, 0,
+ complain_overflow_dont, 0, "r_low16", true, 0x0000ffff, 0x0000ffff, false);
+
+static reloc_howto_type r_pcrel8 =
+HOWTO (R_H8500_PCREL8, 0, 1, 8, true, 0, complain_overflow_signed, 0, "r_pcrel8", true, 0, 0, true);
+
+
+static reloc_howto_type r_pcrel16 =
+HOWTO (R_H8500_PCREL16, 0, 1, 16, true, 0, complain_overflow_signed, 0, "r_pcrel16", true, 0, 0, true);
+
+static reloc_howto_type r_high16 =
+HOWTO (R_H8500_HIGH16, 0, 1, 8, false, 0,
+ complain_overflow_dont, 0, "r_high16", true, 0x000ffff, 0x0000ffff, false);
+
+
+/* Turn a howto into a reloc number */
+
+static int
+coff_h8500_select_reloc (howto)
+ reloc_howto_type *howto;
+{
+ return howto->type;
+}
+
+#define SELECT_RELOC(x,howto) x.r_type = coff_h8500_select_reloc(howto)
+
+
+#define BADMAG(x) H8500BADMAG(x)
+#define H8500 1 /* Customize coffcode.h */
+
+#define __A_MAGIC_SET__
+
+/* Code to swap in the reloc */
+#define SWAP_IN_RELOC_OFFSET bfd_h_get_32
+#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
+#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
+ dst->r_stuff[0] = 'S'; \
+ dst->r_stuff[1] = 'C';
+
+/* Code to turn a r_type into a howto ptr, uses the above howto table
+ */
+
+static void
+rtype2howto(internal, dst)
+ arelent * internal;
+ struct internal_reloc *dst;
+{
+ switch (dst->r_type)
+ {
+ default:
+ abort ();
+ break;
+ case R_H8500_IMM8:
+ internal->howto = &r_imm8;
+ break;
+ case R_H8500_IMM16:
+ internal->howto = &r_imm16;
+ break;
+ case R_H8500_IMM24:
+ internal->howto = &r_imm24;
+ break;
+ case R_H8500_IMM32:
+ internal->howto = &r_imm32;
+ break;
+ case R_H8500_PCREL8:
+ internal->howto = &r_pcrel8;
+ break;
+ case R_H8500_PCREL16:
+ internal->howto = &r_pcrel16;
+ break;
+ case R_H8500_HIGH8:
+ internal->howto = &r_high8;
+ break;
+ case R_H8500_HIGH16:
+ internal->howto = &r_high16;
+ break;
+ case R_H8500_LOW16:
+ internal->howto = &r_low16;
+ break;
+ }
+}
+
+#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
+
+
+/* Perform any necessaru magic to the addend in a reloc entry */
+
+
+#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
+ cache_ptr->addend = ext_reloc.r_offset;
+
+
+#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
+ reloc_processing(relent, reloc, symbols, abfd, section)
+
+static void reloc_processing (relent, reloc, symbols, abfd, section)
+ arelent * relent;
+ struct internal_reloc *reloc;
+ asymbol ** symbols;
+ bfd * abfd;
+ asection * section;
+{
+ relent->address = reloc->r_vaddr;
+ rtype2howto (relent, reloc);
+
+ if (reloc->r_symndx > 0)
+ {
+ relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
+ }
+ else
+ {
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ }
+
+
+ relent->addend = reloc->r_offset;
+ relent->address -= section->vma;
+}
+
+static void
+extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
+ bfd *in_abfd;
+ 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;
+{
+ bfd_byte *d = data+*dst_ptr;
+ asection *input_section = link_order->u.indirect.section;
+ switch (reloc->howto->type)
+ {
+ case R_H8500_IMM8:
+ bfd_put_8 (in_abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ d);
+ (*dst_ptr) += 1;
+ (*src_ptr) += 1;
+ break;
+
+ case R_H8500_HIGH8:
+ bfd_put_8 (in_abfd,
+ (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
+ >> 16),
+ d );
+ (*dst_ptr) += 1;
+ (*src_ptr) += 1;
+ break;
+
+ case R_H8500_IMM16:
+ bfd_put_16 (in_abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ d );
+ (*dst_ptr) += 2;
+ (*src_ptr) += 2;
+ break;
+
+ case R_H8500_LOW16:
+ bfd_put_16 (in_abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ d);
+
+ (*dst_ptr) += 2;
+ (*src_ptr) += 2;
+ break;
+
+ case R_H8500_HIGH16:
+ bfd_put_16 (in_abfd,
+ (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
+ >>16),
+ d);
+
+ (*dst_ptr) += 2;
+ (*src_ptr) += 2;
+ break;
+
+ case R_H8500_IMM24:
+ {
+ int v = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+ int o = bfd_get_32(in_abfd, data+ *dst_ptr -1);
+ v = (v & 0x00ffffff) | (o & 0xff00000);
+ bfd_put_32 (in_abfd, v, data + *dst_ptr -1);
+ (*dst_ptr) +=3;
+ (*src_ptr)+=3;;
+ }
+ break;
+ case R_H8500_IMM32:
+ {
+ int v = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+ bfd_put_32 (in_abfd, v, data + *dst_ptr);
+ (*dst_ptr) +=4;
+ (*src_ptr)+=4;;
+ }
+ break;
+
+
+ case R_H8500_PCREL8:
+ {
+ bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ bfd_vma dot = link_order->offset
+ + *dst_ptr
+ + link_order->u.indirect.section->output_section->vma;
+ int gap = dst - dot - 1; /* -1 since were in the odd byte of the
+ word and the pc's been incremented */
+
+ if (gap > 128 || gap < -128)
+ {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort ();
+ }
+ bfd_put_8 (in_abfd, gap, data + *dst_ptr);
+ (*dst_ptr)++;
+ (*src_ptr)++;
+ break;
+ }
+ case R_H8500_PCREL16:
+ {
+ bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ bfd_vma dot = link_order->offset
+ + *dst_ptr
+ + link_order->u.indirect.section->output_section->vma;
+ int gap = dst - dot - 1; /* -1 since were in the odd byte of the
+ word and the pc's been incremented */
+
+ if (gap > 32767 || gap < -32768)
+ {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort ();
+ }
+ bfd_put_16 (in_abfd, gap, data + *dst_ptr);
+ (*dst_ptr)+=2;
+ (*src_ptr)+=2;
+ break;
+ }
+
+ default:
+ abort ();
+ }
+}
+
+#define coff_reloc16_extra_cases extra_case
+
+#include "coffcode.h"
+
+
+#undef coff_bfd_get_relocated_section_contents
+#undef coff_bfd_relax_section
+#define coff_bfd_get_relocated_section_contents \
+ bfd_coff_reloc16_get_relocated_section_contents
+#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
+
+const bfd_target h8500coff_vec =
+{
+ "coff-h8500", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading symbol underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-i386.c b/contrib/gdb/bfd/coff-i386.c
new file mode 100644
index 0000000..d905b53
--- /dev/null
+++ b/contrib/gdb/bfd/coff-i386.c
@@ -0,0 +1,493 @@
+/* BFD back-end for Intel 386 COFF files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+
+#include "coff/i386.h"
+
+#include "coff/internal.h"
+
+#ifdef COFF_WITH_PE
+#include "coff/pe.h"
+#endif
+
+#include "libcoff.h"
+
+static bfd_reloc_status_type coff_i386_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static reloc_howto_type *coff_i386_rtype_to_howto
+ PARAMS ((bfd *, asection *, struct internal_reloc *,
+ struct coff_link_hash_entry *, struct internal_syment *,
+
+ bfd_vma *));
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
+/* The page size is a guess based on ELF. */
+
+#define COFF_PAGE_SIZE 0x1000
+
+/* For some reason when using i386 COFF the value stored in the .text
+ section for a reference to a common symbol is the value itself plus
+ any desired offset. Ian Taylor, Cygnus Support. */
+
+/* If we are producing relocateable output, we need to do some
+ adjustments to the object file that are not done by the
+ bfd_perform_relocation function. This function is called by every
+ reloc type to make any required adjustments. */
+
+static bfd_reloc_status_type
+coff_i386_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ symvalue diff;
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ /* We are relocating a common symbol. The current value in the
+ object file is ORIG + OFFSET, where ORIG is the value of the
+ common symbol as seen by the object file when it was compiled
+ (this may be zero if the symbol was undefined) and OFFSET is
+ the offset into the common symbol (normally zero, but may be
+ non-zero when referring to a field in a common structure).
+ ORIG is the negative of reloc_entry->addend, which is set by
+ the CALC_ADDEND macro below. We want to replace the value in
+ the object file with NEW + OFFSET, where NEW is the value of
+ the common symbol which we are going to put in the final
+ object file. NEW is symbol->value. */
+ diff = symbol->value + reloc_entry->addend;
+ }
+ else
+ {
+ /* For some reason bfd_perform_relocation always effectively
+ ignores the addend for a COFF target when producing
+ relocateable output. This seems to be always wrong for 386
+ COFF, so we handle the addend here instead. */
+ diff = reloc_entry->addend;
+ }
+
+
+#ifdef COFF_WITH_PE
+ if (reloc_entry->howto->type == 7)
+ {
+/* diff -= coff_data(output_bfd)->link_info->pe_info.image_base.value;*/
+ exit(1);
+ }
+#endif
+
+#define DOIT(x) \
+ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
+
+ if (diff != 0)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+ unsigned char *addr = (unsigned char *) data + reloc_entry->address;
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, addr);
+ DOIT (x);
+ bfd_put_8 (abfd, x, addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_get_16 (abfd, addr);
+ DOIT (x);
+ bfd_put_16 (abfd, x, addr);
+ }
+ break;
+
+ case 2:
+ {
+ long x = bfd_get_32 (abfd, addr);
+ DOIT (x);
+ bfd_put_32 (abfd, x, addr);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ /* Now let bfd_perform_relocation finish everything up. */
+ return bfd_reloc_continue;
+}
+
+#ifdef COFF_WITH_PE
+/* Return true if this relocation should
+ appear in the output .reloc section. */
+
+static boolean in_reloc_p(abfd, howto)
+ bfd * abfd;
+ reloc_howto_type *howto;
+{
+ return ! howto->pc_relative && howto->type != R_IMAGEBASE;
+}
+#endif
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET false
+#endif
+
+static reloc_howto_type howto_table[] =
+{
+ {0},
+ {1},
+ {2},
+ {3},
+ {4},
+ {5},
+ HOWTO (R_DIR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "dir32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+ /* {7}, */
+ HOWTO (R_IMAGEBASE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "rva32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+ {010},
+ {011},
+ {012},
+ {013},
+ {014},
+ {015},
+ {016},
+ HOWTO (R_RELBYTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "8", /* name */
+ true, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_RELWORD, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_RELLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_PCRBYTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "DISP8", /* name */
+ true, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_PCRWORD, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "DISP16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_PCRLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i386_reloc, /* special_function */
+ "DISP32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ PCRELOFFSET) /* pcrel_offset */
+};
+
+/* Turn a howto into a reloc nunmber */
+
+#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
+#define BADMAG(x) I386BADMAG(x)
+#define I386 1 /* Customize coffcode.h */
+
+#define RTYPE2HOWTO(cache_ptr, dst) \
+ (cache_ptr)->howto = howto_table + (dst)->r_type;
+
+/* For 386 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
+ library. On some other COFF targets STYP_BSS is normally
+ STYP_NOLOAD. */
+#define BSS_NOLOAD_IS_SHARED_LIBRARY
+
+/* Compute the addend of a reloc. If the reloc is to a common symbol,
+ the object file contains the value of the common symbol. By the
+ time this is called, the linker may be using a different symbol
+ from a different object file with a different value. Therefore, we
+ hack wildly to locate the original symbol from this file so that we
+ can make the correct adjustment. This macro sets coffsym to the
+ symbol from the original file, and uses it to set the addend value
+ correctly. If this is not a common symbol, the usual addend
+ calculation is done, except that an additional tweak is needed for
+ PC relative relocs.
+ FIXME: This macro refers to symbols and asect; these are from the
+ calling function, not the macro arguments. */
+
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = - coffsym->native->u.syment.n_value; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ if (ptr && howto_table[reloc.r_type].pc_relative) \
+ cache_ptr->addend += asect->vma; \
+ }
+
+/* We use the special COFF backend linker. */
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+static reloc_howto_type *
+coff_i386_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+
+ reloc_howto_type *howto;
+
+ howto = howto_table + rel->r_type;
+
+#ifdef COFF_WITH_PE
+ *addendp = 0;
+#endif
+
+ if (howto->pc_relative)
+ *addendp += sec->vma;
+
+ if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
+ {
+ /* This is a common symbol. The section contents include the
+ size (sym->n_value) as an addend. The relocate_section
+ function will be adding in the final value of the symbol. We
+ need to subtract out the current size in order to get the
+ correct result. */
+
+ BFD_ASSERT (h != NULL);
+
+
+#ifndef COFF_WITH_PE
+ /* I think we *do* want to bypass this. If we don't, I have seen some data
+ parameters get the wrong relcation address. If I link two versions
+ with and without this section bypassed and then do a binary comparison,
+ the addresses which are different can be looked up in the map. The
+ case in which this section has been bypassed has addresses which correspond
+ to values I can find in the map */
+ *addendp -= sym->n_value;
+#endif
+ }
+
+ /* If the output symbol is common (in which case this must be a
+ relocateable link), we need to add in the final size of the
+ common symbol. */
+ if (h != NULL && h->root.type == bfd_link_hash_common)
+ *addendp += h->root.u.c.size;
+
+
+#ifdef COFF_WITH_PE
+ if (howto->pc_relative)
+ *addendp -= 4;
+
+ if (rel->r_type == R_IMAGEBASE)
+ {
+ *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+ }
+#endif
+
+ return howto;
+}
+
+
+#define coff_bfd_reloc_type_lookup coff_i386_reloc_type_lookup
+
+
+static reloc_howto_type *
+coff_i386_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ case BFD_RELOC_RVA:
+ return howto_table +R_IMAGEBASE;
+ case BFD_RELOC_32:
+ return howto_table + R_DIR32;
+ case BFD_RELOC_32_PCREL:
+ return howto_table + R_PCRLONG;
+ default:
+ BFD_FAIL ();
+ return 0;
+ }
+}
+
+
+
+#define coff_rtype_to_howto coff_i386_rtype_to_howto
+
+#include "coffcode.h"
+
+static const bfd_target *
+i3coff_object_p(a)
+ bfd *a;
+{
+ return coff_object_p(a);
+}
+
+const bfd_target
+#ifdef TARGET_SYM
+ TARGET_SYM =
+#else
+ i386coff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+ TARGET_NAME,
+#else
+ "coff-i386", /* name */
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+#ifdef TARGET_UNDERSCORE
+ TARGET_UNDERSCORE, /* leading underscore */
+#else
+ 0, /* leading underscore */
+#endif
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+/* Note that we allow an object file to be treated as a core file as well. */
+ {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, i3coff_object_p},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-i860.c b/contrib/gdb/bfd/coff-i860.c
new file mode 100644
index 0000000..9605cdf
--- /dev/null
+++ b/contrib/gdb/bfd/coff-i860.c
@@ -0,0 +1,423 @@
+/* BFD back-end for Intel 860 COFF files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Created mostly by substituting "860" for "386" in coff-i386.c
+ Harry Dolan <dolan@ssd.intel.com>, October 1995
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+
+#include "coff/i860.h"
+
+#include "coff/internal.h"
+
+#include "libcoff.h"
+
+static bfd_reloc_status_type coff_i860_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static reloc_howto_type *coff_i860_rtype_to_howto
+ PARAMS ((bfd *, asection *, struct internal_reloc *,
+ struct coff_link_hash_entry *, struct internal_syment *,
+ bfd_vma *));
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
+/* The page size is a guess based on ELF. */
+
+#define COFF_PAGE_SIZE 0x1000
+
+/* For some reason when using i860 COFF the value stored in the .text
+ section for a reference to a common symbol is the value itself plus
+ any desired offset. Ian Taylor, Cygnus Support. */
+
+/* If we are producing relocateable output, we need to do some
+ adjustments to the object file that are not done by the
+ bfd_perform_relocation function. This function is called by every
+ reloc type to make any required adjustments. */
+
+static bfd_reloc_status_type
+coff_i860_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ symvalue diff;
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ /* We are relocating a common symbol. The current value in the
+ object file is ORIG + OFFSET, where ORIG is the value of the
+ common symbol as seen by the object file when it was compiled
+ (this may be zero if the symbol was undefined) and OFFSET is
+ the offset into the common symbol (normally zero, but may be
+ non-zero when referring to a field in a common structure).
+ ORIG is the negative of reloc_entry->addend, which is set by
+ the CALC_ADDEND macro below. We want to replace the value in
+ the object file with NEW + OFFSET, where NEW is the value of
+ the common symbol which we are going to put in the final
+ object file. NEW is symbol->value. */
+ diff = symbol->value + reloc_entry->addend;
+ }
+ else
+ {
+ /* For some reason bfd_perform_relocation always effectively
+ ignores the addend for a COFF target when producing
+ relocateable output. This seems to be always wrong for 860
+ COFF, so we handle the addend here instead. */
+ diff = reloc_entry->addend;
+ }
+
+
+#define DOIT(x) \
+ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
+
+ if (diff != 0)
+ {
+ reloc_howto_type *howto = reloc_entry->howto;
+ unsigned char *addr = (unsigned char *) data + reloc_entry->address;
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, addr);
+ DOIT (x);
+ bfd_put_8 (abfd, x, addr);
+ }
+ break;
+
+ case 1:
+ {
+ short x = bfd_get_16 (abfd, addr);
+ DOIT (x);
+ bfd_put_16 (abfd, x, addr);
+ }
+ break;
+
+ case 2:
+ {
+ long x = bfd_get_32 (abfd, addr);
+ DOIT (x);
+ bfd_put_32 (abfd, x, addr);
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ /* Now let bfd_perform_relocation finish everything up. */
+ return bfd_reloc_continue;
+}
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET false
+#endif
+
+static reloc_howto_type howto_table[] =
+{
+ {0},
+ {1},
+ {2},
+ {3},
+ {4},
+ {5},
+ HOWTO (R_DIR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "dir32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+ /* {7}, */
+ HOWTO (R_IMAGEBASE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "rva32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+ {010},
+ {011},
+ {012},
+ {013},
+ {014},
+ {015},
+ {016},
+ HOWTO (R_RELBYTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "8", /* name */
+ true, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_RELWORD, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_RELLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_PCRBYTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "DISP8", /* name */
+ true, /* partial_inplace */
+ 0x000000ff, /* src_mask */
+ 0x000000ff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_PCRWORD, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "DISP16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ PCRELOFFSET), /* pcrel_offset */
+ HOWTO (R_PCRLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ coff_i860_reloc, /* special_function */
+ "DISP32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ PCRELOFFSET) /* pcrel_offset */
+};
+
+/* Turn a howto into a reloc nunmber */
+
+#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
+#define BADMAG(x) I860BADMAG(x)
+#define I860 1 /* Customize coffcode.h */
+
+#define RTYPE2HOWTO(cache_ptr, dst) \
+ (cache_ptr)->howto = howto_table + (dst)->r_type;
+
+/* For 860 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
+ library. On some other COFF targets STYP_BSS is normally
+ STYP_NOLOAD. */
+#define BSS_NOLOAD_IS_SHARED_LIBRARY
+
+/* Compute the addend of a reloc. If the reloc is to a common symbol,
+ the object file contains the value of the common symbol. By the
+ time this is called, the linker may be using a different symbol
+ from a different object file with a different value. Therefore, we
+ hack wildly to locate the original symbol from this file so that we
+ can make the correct adjustment. This macro sets coffsym to the
+ symbol from the original file, and uses it to set the addend value
+ correctly. If this is not a common symbol, the usual addend
+ calculation is done, except that an additional tweak is needed for
+ PC relative relocs.
+ FIXME: This macro refers to symbols and asect; these are from the
+ calling function, not the macro arguments. */
+
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = - coffsym->native->u.syment.n_value; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ if (ptr && howto_table[reloc.r_type].pc_relative) \
+ cache_ptr->addend += asect->vma; \
+ }
+
+/* We use the special COFF backend linker. */
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+static reloc_howto_type *
+coff_i860_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+
+ reloc_howto_type *howto;
+
+ howto = howto_table + rel->r_type;
+
+ if (howto->pc_relative)
+ *addendp += sec->vma;
+
+ if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
+ {
+ /* This is a common symbol. The section contents include the
+ size (sym->n_value) as an addend. The relocate_section
+ function will be adding in the final value of the symbol. We
+ need to subtract out the current size in order to get the
+ correct result. */
+
+ BFD_ASSERT (h != NULL);
+
+
+ /* I think we *do* want to bypass this. If we don't, I have seen some data
+ parameters get the wrong relcation address. If I link two versions
+ with and without this section bypassed and then do a binary comparison,
+ the addresses which are different can be looked up in the map. The
+ case in which this section has been bypassed has addresses which correspond
+ to values I can find in the map */
+ *addendp -= sym->n_value;
+ }
+
+ /* If the output symbol is common (in which case this must be a
+ relocateable link), we need to add in the final size of the
+ common symbol. */
+ if (h != NULL && h->root.type == bfd_link_hash_common)
+ *addendp += h->root.u.c.size;
+
+ return howto;
+}
+
+#define coff_rtype_to_howto coff_i860_rtype_to_howto
+
+#include "coffcode.h"
+
+static const bfd_target *
+i3coff_object_p(a)
+ bfd *a;
+{
+ return coff_object_p(a);
+}
+
+const bfd_target
+#ifdef TARGET_SYM
+ TARGET_SYM =
+#else
+ i860coff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+ TARGET_NAME,
+#else
+ "coff-i860", /* name */
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+/* Note that we allow an object file to be treated as a core file as well. */
+ {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, i3coff_object_p},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-i960.c b/contrib/gdb/bfd/coff-i960.c
new file mode 100644
index 0000000..ed30125
--- /dev/null
+++ b/contrib/gdb/bfd/coff-i960.c
@@ -0,0 +1,683 @@
+/* BFD back-end for Intel 960 COFF files.
+ Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define I960 1
+#define BADMAG(x) I960BADMAG(x)
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/i960.h"
+#include "coff/internal.h"
+#include "libcoff.h" /* to allow easier abstraction-breaking */
+
+static bfd_reloc_status_type optcall_callback
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type coff_i960_relocate
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static reloc_howto_type *coff_i960_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static boolean coff_i960_start_final_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean coff_i960_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
+static boolean coff_i960_adjust_symndx
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
+ struct internal_reloc *, boolean *));
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+/* The i960 does not support an MMU, so COFF_PAGE_SIZE can be
+ arbitrarily small. */
+#define COFF_PAGE_SIZE 1
+
+#define COFF_LONG_FILENAMES
+
+/* This is just like the usual CALC_ADDEND, but it includes the
+ section VMA for PC relative relocs. */
+#ifndef CALC_ADDEND
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = 0; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ if (ptr && (reloc.r_type == 25 || reloc.r_type == 27)) \
+ cache_ptr->addend += asect->vma; \
+ }
+#endif
+
+#define CALLS 0x66003800 /* Template for 'calls' instruction */
+#define BAL 0x0b000000 /* Template for 'bal' instruction */
+#define BAL_MASK 0x00ffffff
+
+static bfd_reloc_status_type
+optcall_callback (abfd, reloc_entry, symbol_in, data,
+ input_section, ignore_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol_in;
+ PTR data;
+ asection *input_section;
+ bfd *ignore_bfd;
+ char **error_message;
+{
+ /* This item has already been relocated correctly, but we may be
+ * able to patch in yet better code - done by digging out the
+ * correct info on this symbol */
+ bfd_reloc_status_type result;
+ coff_symbol_type *cs = coffsymbol(symbol_in);
+
+ /* Don't do anything with symbols which aren't tied up yet,
+ except move the reloc. */
+ if (bfd_is_und_section (cs->symbol.section)) {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* So the target symbol has to be of coff type, and the symbol
+ has to have the correct native information within it */
+ if ((bfd_asymbol_flavour(&cs->symbol) != bfd_target_coff_flavour)
+ || (cs->native == (combined_entry_type *)NULL))
+ {
+ /* This is interesting, consider the case where we're outputting coff
+ from a mix n match input, linking from coff to a symbol defined in a
+ bout file will cause this match to be true. Should I complain? This
+ will only work if the bout symbol is non leaf. */
+ *error_message =
+ (char *) "uncertain calling convention for non-COFF symbol";
+ result = bfd_reloc_dangerous;
+ }
+ else
+ {
+ switch (cs->native->u.syment.n_sclass)
+ {
+ case C_LEAFSTAT:
+ case C_LEAFEXT:
+ /* This is a call to a leaf procedure, replace instruction with a bal
+ to the correct location. */
+ {
+ union internal_auxent *aux = &((cs->native+2)->u.auxent);
+ int word = bfd_get_32(abfd, (bfd_byte *)data + reloc_entry->address);
+ int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value);
+ BFD_ASSERT(cs->native->u.syment.n_numaux==2);
+
+ /* We replace the original call instruction with a bal to
+ the bal entry point - the offset of which is described in
+ the 2nd auxent of the original symbol. We keep the native
+ sym and auxents untouched, so the delta between the two
+ is the offset of the bal entry point. */
+ word = ((word + olf) & BAL_MASK) | BAL;
+ bfd_put_32(abfd, word, (bfd_byte *) data + reloc_entry->address);
+ }
+ result = bfd_reloc_ok;
+ break;
+ case C_SCALL:
+ /* This is a call to a system call, replace with a calls to # */
+ BFD_ASSERT(0);
+ result = bfd_reloc_ok;
+ break;
+ default:
+ result = bfd_reloc_ok;
+ break;
+ }
+ }
+ return result;
+}
+
+/* i960 COFF is used by VxWorks 5.1. However, VxWorks 5.1 does not
+ appear to correctly handle a reloc against a symbol defined in the
+ same object file. It appears to simply discard such relocs, rather
+ than adding their values into the object file. We handle this here
+ by converting all relocs against defined symbols into relocs
+ against the section symbol, when generating a relocateable output
+ file.
+
+ Note that this function is only called if we are not using the COFF
+ specific backend linker. It only does something when doing a
+ relocateable link, which will almost certainly fail when not
+ generating COFF i960 output, so this function is actually no longer
+ useful. It was used before this target was converted to use the
+ COFF specific backend linker. */
+
+static bfd_reloc_status_type
+coff_i960_relocate (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ asection *osec;
+
+ if (output_bfd == NULL)
+ {
+ /* Not generating relocateable output file. */
+ return bfd_reloc_continue;
+ }
+
+ if (bfd_is_und_section (bfd_get_section (symbol)))
+ {
+ /* Symbol is not defined, so no need to worry about it. */
+ return bfd_reloc_continue;
+ }
+
+ if (bfd_is_com_section (bfd_get_section (symbol)))
+ {
+ /* I don't really know what the right action is for a common
+ symbol. */
+ return bfd_reloc_continue;
+ }
+
+ /* Convert the reloc to use the section symbol. FIXME: This method
+ is ridiculous. */
+ osec = bfd_get_section (symbol)->output_section;
+ if (coff_section_data (output_bfd, osec) != NULL
+ && coff_section_data (output_bfd, osec)->tdata != NULL)
+ reloc_entry->sym_ptr_ptr =
+ (asymbol **) coff_section_data (output_bfd, osec)->tdata;
+ else
+ {
+ const char *sec_name;
+ asymbol **syms, **sym_end;
+
+ sec_name = bfd_get_section_name (output_bfd, osec);
+ syms = bfd_get_outsymbols (output_bfd);
+ sym_end = syms + bfd_get_symcount (output_bfd);
+ for (; syms < sym_end; syms++)
+ {
+ if (bfd_asymbol_name (*syms) != NULL
+ && (*syms)->value == 0
+ && strcmp ((*syms)->section->output_section->name,
+ sec_name) == 0)
+ break;
+ }
+
+ if (syms >= sym_end)
+ abort ();
+
+ reloc_entry->sym_ptr_ptr = syms;
+
+ if (coff_section_data (output_bfd, osec) == NULL)
+ {
+ osec->used_by_bfd =
+ ((PTR) bfd_zalloc (abfd,
+ sizeof (struct coff_section_tdata)));
+ if (osec->used_by_bfd == NULL)
+ return bfd_reloc_overflow;
+ }
+ coff_section_data (output_bfd, osec)->tdata = (PTR) syms;
+ }
+
+ /* Let bfd_perform_relocation do its thing, which will include
+ stuffing the symbol addend into the object file. */
+ return bfd_reloc_continue;
+}
+
+static reloc_howto_type howto_rellong =
+ HOWTO ((unsigned int) R_RELLONG, 0, 2, 32,false, 0,
+ complain_overflow_bitfield, coff_i960_relocate,"rellong", true,
+ 0xffffffff, 0xffffffff, 0);
+static reloc_howto_type howto_iprmed =
+ HOWTO (R_IPRMED, 0, 2, 24,true,0, complain_overflow_signed,
+ coff_i960_relocate, "iprmed ", true, 0x00ffffff, 0x00ffffff, 0);
+static reloc_howto_type howto_optcall =
+ HOWTO (R_OPTCALL, 0,2,24,true,0, complain_overflow_signed,
+ optcall_callback, "optcall", true, 0x00ffffff, 0x00ffffff, 0);
+
+static reloc_howto_type *
+coff_i960_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ default:
+ return 0;
+ case BFD_RELOC_I960_CALLJ:
+ return &howto_optcall;
+ case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
+ return &howto_rellong;
+ case BFD_RELOC_24_PCREL:
+ return &howto_iprmed;
+ }
+}
+
+/* The real code is in coffcode.h */
+
+#define RTYPE2HOWTO(cache_ptr, dst) \
+{ \
+ reloc_howto_type *howto_ptr; \
+ switch ((dst)->r_type) { \
+ case 17: howto_ptr = &howto_rellong; break; \
+ case 25: howto_ptr = &howto_iprmed; break; \
+ case 27: howto_ptr = &howto_optcall; break; \
+ default: howto_ptr = 0; break; \
+ } \
+ (cache_ptr)->howto = howto_ptr; \
+ }
+
+/* i960 COFF is used by VxWorks 5.1. However, VxWorks 5.1 does not
+ appear to correctly handle a reloc against a symbol defined in the
+ same object file. It appears to simply discard such relocs, rather
+ than adding their values into the object file. We handle this by
+ converting all relocs against global symbols into relocs against
+ internal symbols at the start of the section. This routine is
+ called at the start of the linking process, and it creates the
+ necessary symbols. */
+
+static boolean
+coff_i960_start_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ bfd_size_type symesz = bfd_coff_symesz (abfd);
+ asection *o;
+ bfd_byte *esym;
+
+ if (! info->relocateable)
+ return true;
+
+ esym = (bfd_byte *) bfd_malloc (symesz);
+ if (esym == NULL)
+ return false;
+
+ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
+ return false;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct internal_syment isym;
+
+ strncpy (isym._n._n_name, o->name, SYMNMLEN);
+ isym.n_value = 0;
+ isym.n_scnum = o->target_index;
+ isym.n_type = T_NULL;
+ isym.n_sclass = C_STAT;
+ isym.n_numaux = 0;
+
+ bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
+
+ if (bfd_write (esym, symesz, 1, abfd) != symesz)
+ {
+ free (esym);
+ return false;
+ }
+
+ obj_raw_syment_count (abfd) += 1;
+ }
+
+ free (esym);
+
+ return true;
+}
+
+/* The reloc processing routine for the optimized COFF linker. */
+
+static boolean
+coff_i960_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, syms, sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma addend;
+ bfd_vma val;
+ reloc_howto_type *howto;
+ bfd_reloc_status_type rstat = bfd_reloc_ok;
+ boolean done;
+
+ symndx = rel->r_symndx;
+
+ if (symndx == -1)
+ {
+ h = NULL;
+ sym = NULL;
+ }
+ else
+ {
+ h = obj_coff_sym_hashes (input_bfd)[symndx];
+ sym = syms + symndx;
+ }
+
+ if (sym != NULL && sym->n_scnum != 0)
+ addend = - sym->n_value;
+ else
+ addend = 0;
+
+ switch (rel->r_type)
+ {
+ case 17: howto = &howto_rellong; break;
+ case 25: howto = &howto_iprmed; break;
+ case 27: howto = &howto_optcall; break;
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ val = 0;
+
+ if (h == NULL)
+ {
+ asection *sec;
+
+ if (symndx == -1)
+ {
+ sec = bfd_abs_section_ptr;
+ val = 0;
+ }
+ else
+ {
+ sec = sections[symndx];
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+ }
+ else
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ val = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (! info->relocateable)
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ done = false;
+
+ if (howto->type == R_OPTCALL && ! info->relocateable && symndx != -1)
+ {
+ int class;
+
+ if (h != NULL)
+ class = h->class;
+ else
+ class = sym->n_sclass;
+
+ switch (class)
+ {
+ case C_NULL:
+ /* This symbol is apparently not from a COFF input file.
+ We warn, and then assume that it is not a leaf
+ function. */
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info,
+ "uncertain calling convention for non-COFF symbol",
+ input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ break;
+ case C_LEAFSTAT:
+ case C_LEAFEXT:
+ /* This is a call to a leaf procedure; use the bal
+ instruction. */
+ {
+ long olf;
+ unsigned long word;
+
+ if (h != NULL)
+ {
+ BFD_ASSERT (h->numaux == 2);
+ olf = h->aux[1].x_bal.x_balntry;
+ }
+ else
+ {
+ bfd_byte *esyms;
+ union internal_auxent aux;
+
+ BFD_ASSERT (sym->n_numaux == 2);
+ esyms = (bfd_byte *) obj_coff_external_syms (input_bfd);
+ esyms += (symndx + 2) * bfd_coff_symesz (input_bfd);
+ bfd_coff_swap_aux_in (input_bfd, (PTR) esyms, sym->n_type,
+ sym->n_sclass, 1, sym->n_numaux,
+ (PTR) &aux);
+ olf = aux.x_bal.x_balntry;
+ }
+
+ word = bfd_get_32 (input_bfd,
+ (contents
+ + (rel->r_vaddr - input_section->vma)));
+ word = ((word + olf - val) & BAL_MASK) | BAL;
+ bfd_put_32 (input_bfd,
+ word,
+ (contents
+ + (rel->r_vaddr - input_section->vma)));
+ done = true;
+ }
+ break;
+ case C_SCALL:
+ BFD_ASSERT (0);
+ break;
+ }
+ }
+
+ if (! done)
+ {
+ if (howto->pc_relative)
+ addend += input_section->vma;
+ rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents,
+ rel->r_vaddr - input_section->vma,
+ val, addend);
+ }
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+ if (name == NULL)
+ return false;
+ }
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Adjust the symbol index of any reloc against a global symbol to
+ instead be a reloc against the internal symbol we created specially
+ for the section. */
+
+/*ARGSUSED*/
+static boolean
+coff_i960_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp)
+ bfd *obfd;
+ struct bfd_link_info *info;
+ bfd *ibfd;
+ asection *sec;
+ struct internal_reloc *irel;
+ boolean *adjustedp;
+{
+ struct coff_link_hash_entry *h;
+
+ *adjustedp = false;
+
+ h = obj_coff_sym_hashes (ibfd)[irel->r_symndx];
+ if (h == NULL
+ || (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak))
+ return true;
+
+ irel->r_symndx = h->root.u.def.section->output_section->target_index - 1;
+ *adjustedp = true;
+
+ return true;
+}
+
+#define coff_start_final_link coff_i960_start_final_link
+
+#define coff_relocate_section coff_i960_relocate_section
+
+#define coff_adjust_symndx coff_i960_adjust_symndx
+
+#define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup
+
+#include "coffcode.h"
+
+const bfd_target icoff_little_vec =
+{
+ "coff-Intel-little", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
+
+
+const bfd_target icoff_big_vec =
+{
+ "coff-Intel-big", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-m68k.c b/contrib/gdb/bfd/coff-m68k.c
new file mode 100644
index 0000000..77fb45b
--- /dev/null
+++ b/contrib/gdb/bfd/coff-m68k.c
@@ -0,0 +1,203 @@
+/* BFD back-end for Motorola 68000 COFF binaries.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/m68k.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#ifndef LYNX_SPECIAL_FN
+#define LYNX_SPECIAL_FN 0
+#endif
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
+
+#ifndef COFF_PAGE_SIZE
+/* The page size is a guess based on ELF. */
+#define COFF_PAGE_SIZE 0x2000
+#endif
+
+/* Clean up namespace. */
+#define m68kcoff_howto_table _bfd_m68kcoff_howto_table
+#define m68k_rtype2howto _bfd_m68kcoff_rtype2howto
+#define m68k_howto2rtype _bfd_m68kcoff_howto2rtype
+#define m68k_reloc_type_lookup _bfd_m68kcoff_reloc_type_lookup
+
+#ifdef ONLY_DECLARE_RELOCS
+extern reloc_howto_type m68kcoff_howto_table[];
+#else
+reloc_howto_type m68kcoff_howto_table[] =
+{
+ HOWTO(R_RELBYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, LYNX_SPECIAL_FN, "8", true, 0x000000ff,0x000000ff, false),
+ HOWTO(R_RELWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, LYNX_SPECIAL_FN, "16", true, 0x0000ffff,0x0000ffff, false),
+ HOWTO(R_RELLONG, 0, 2, 32, false, 0, complain_overflow_bitfield, LYNX_SPECIAL_FN, "32", true, 0xffffffff,0xffffffff, false),
+ HOWTO(R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, LYNX_SPECIAL_FN, "DISP8", true, 0x000000ff,0x000000ff, false),
+ HOWTO(R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, LYNX_SPECIAL_FN, "DISP16", true, 0x0000ffff,0x0000ffff, false),
+ HOWTO(R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, LYNX_SPECIAL_FN, "DISP32", true, 0xffffffff,0xffffffff, false),
+ HOWTO(R_RELLONG_NEG, 0, -2, 32, false, 0, complain_overflow_bitfield, LYNX_SPECIAL_FN, "-32", true, 0xffffffff,0xffffffff, false),
+};
+#endif /* not ONLY_DECLARE_RELOCS */
+
+#ifndef BADMAG
+#define BADMAG(x) M68KBADMAG(x)
+#endif
+#define M68 1 /* Customize coffcode.h */
+
+/* Turn a howto into a reloc number */
+
+#ifdef ONLY_DECLARE_RELOCS
+extern void m68k_rtype2howto PARAMS ((arelent *internal, int relocentry));
+extern int m68k_howto2rtype PARAMS ((reloc_howto_type *));
+extern reloc_howto_type *m68k_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+#else
+void
+m68k_rtype2howto(internal, relocentry)
+ arelent *internal;
+ int relocentry;
+{
+ switch (relocentry)
+ {
+ case R_RELBYTE: internal->howto = m68kcoff_howto_table + 0; break;
+ case R_RELWORD: internal->howto = m68kcoff_howto_table + 1; break;
+ case R_RELLONG: internal->howto = m68kcoff_howto_table + 2; break;
+ case R_PCRBYTE: internal->howto = m68kcoff_howto_table + 3; break;
+ case R_PCRWORD: internal->howto = m68kcoff_howto_table + 4; break;
+ case R_PCRLONG: internal->howto = m68kcoff_howto_table + 5; break;
+ case R_RELLONG_NEG: internal->howto = m68kcoff_howto_table + 6; break;
+ }
+}
+
+int
+m68k_howto2rtype (internal)
+ reloc_howto_type *internal;
+{
+ if (internal->pc_relative)
+ {
+ switch (internal->bitsize)
+ {
+ case 32: return R_PCRLONG;
+ case 16: return R_PCRWORD;
+ case 8: return R_PCRBYTE;
+ }
+ }
+ else
+ {
+ switch (internal->bitsize)
+ {
+ case 32: return R_RELLONG;
+ case 16: return R_RELWORD;
+ case 8: return R_RELBYTE;
+ }
+ }
+ return R_RELLONG;
+}
+
+reloc_howto_type *
+m68k_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ default: return NULL;
+ case BFD_RELOC_8: return m68kcoff_howto_table + 0;
+ case BFD_RELOC_16: return m68kcoff_howto_table + 1;
+ case BFD_RELOC_CTOR:
+ case BFD_RELOC_32: return m68kcoff_howto_table + 2;
+ case BFD_RELOC_8_PCREL: return m68kcoff_howto_table + 3;
+ case BFD_RELOC_16_PCREL: return m68kcoff_howto_table + 4;
+ case BFD_RELOC_32_PCREL: return m68kcoff_howto_table + 5;
+ /* FIXME: There doesn't seem to be a code for R_RELLONG_NEG. */
+ }
+ /*NOTREACHED*/
+}
+
+#endif /* not ONLY_DECLARE_RELOCS */
+
+#define RTYPE2HOWTO(internal, relocentry) \
+ m68k_rtype2howto(internal, (relocentry)->r_type)
+
+#define SELECT_RELOC(external, internal) \
+ external.r_type = m68k_howto2rtype(internal);
+
+#define coff_bfd_reloc_type_lookup m68k_reloc_type_lookup
+
+#define coff_relocate_section _bfd_coff_generic_relocate_section
+
+#include "coffcode.h"
+
+const bfd_target
+#ifdef TARGET_SYM
+ TARGET_SYM =
+#else
+ m68kcoff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+ TARGET_NAME,
+#else
+ "coff-m68k", /* name */
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+#ifdef NAMES_HAVE_UNDERSCORE
+ '_',
+#else
+ 0, /* leading underscore */
+#endif
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE
+ };
diff --git a/contrib/gdb/bfd/coff-m88k.c b/contrib/gdb/bfd/coff-m88k.c
new file mode 100644
index 0000000..414106d
--- /dev/null
+++ b/contrib/gdb/bfd/coff-m88k.c
@@ -0,0 +1,311 @@
+/* BFD back-end for Motorola 88000 COFF "Binary Compatability Standard" files.
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define M88 1 /* Customize various include files */
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/m88k.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+static bfd_reloc_status_type m88k_special_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
+static void reloc_processing
+ PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+static bfd_reloc_status_type
+m88k_special_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ reloc_howto_type *howto = reloc_entry->howto;
+
+ switch (howto->type)
+ {
+ case R_HVRT16:
+ case R_LVRT16:
+ if (output_bfd != (bfd *) NULL)
+ {
+ /* 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->address += input_section->output_offset;
+ }
+ else
+ {
+ bfd_vma output_base = 0;
+ bfd_vma addr = reloc_entry->address;
+ bfd_vma x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
+ asection *reloc_target_output_section;
+ long relocation = 0;
+
+ /* Work out which section the relocation is targetted at and the
+ initial relocation command value. */
+
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ reloc_target_output_section = symbol->section->output_section;
+
+ /* Convert input-section-relative symbol value to absolute. */
+ if (output_bfd)
+ output_base = 0;
+ else
+ output_base = reloc_target_output_section->vma;
+
+ relocation += output_base + symbol->section->output_offset;
+
+ /* Add in supplied addend. */
+ relocation += ((reloc_entry->addend << howto->bitsize) + x);
+
+ reloc_entry->addend = 0;
+
+ relocation >>= (bfd_vma) howto->rightshift;
+
+ /* Shift everything up to where it's going to be used */
+
+ relocation <<= (bfd_vma) howto->bitpos;
+
+ if (relocation)
+ bfd_put_16 (abfd, relocation, (unsigned char *) data + addr);
+ }
+
+ return bfd_reloc_ok;
+ break;
+
+ default:
+ if (output_bfd != (bfd *) NULL)
+ {
+ /* 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->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+ break;
+ }
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+static reloc_howto_type howto_table[] =
+{
+ HOWTO (R_PCR16L, /* type */
+ 02, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ m88k_special_reloc, /* special_function */
+ "PCR16L", /* name */
+ false, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_PCR26L, /* type */
+ 02, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ m88k_special_reloc, /* special_function */
+ "PCR26L", /* name */
+ false, /* partial_inplace */
+ 0x03ffffff, /* src_mask */
+ 0x03ffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_VRT16, /* type */
+ 00, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ m88k_special_reloc, /* special_function */
+ "VRT16", /* name */
+ false, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_HVRT16, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ m88k_special_reloc, /* special_function */
+ "HVRT16", /* name */
+ false, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_LVRT16, /* type */
+ 00, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ m88k_special_reloc, /* special_function */
+ "LVRT16", /* name */
+ false, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_VRT32, /* type */
+ 00, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ m88k_special_reloc, /* special_function */
+ "VRT32", /* name */
+ false, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+};
+
+/* Code to turn an external r_type into a pointer to an entry in the
+ above howto table. */
+static void
+rtype2howto (cache_ptr, dst)
+ arelent *cache_ptr;
+ struct internal_reloc *dst;
+{
+ if (dst->r_type >= R_PCR16L && dst->r_type <= R_VRT32)
+ {
+ cache_ptr->howto = howto_table + dst->r_type - R_PCR16L;
+ }
+ else
+ {
+ BFD_ASSERT (0);
+ }
+}
+
+#define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst)
+
+
+/* Code to swap in the reloc offset */
+#define SWAP_IN_RELOC_OFFSET bfd_h_get_16
+#define SWAP_OUT_RELOC_OFFSET bfd_h_put_16
+
+
+#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
+ reloc_processing(relent, reloc, symbols, abfd, section)
+
+static void
+reloc_processing (relent, reloc, symbols, abfd, section)
+ arelent *relent;
+ struct internal_reloc *reloc;
+ asymbol **symbols;
+ bfd *abfd;
+ asection *section;
+{
+ relent->address = reloc->r_vaddr;
+ rtype2howto (relent, reloc);
+
+ if (((int) reloc->r_symndx) > 0)
+ {
+ relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
+ }
+ else
+ {
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ }
+
+ relent->addend = reloc->r_offset;
+ relent->address -= section->vma;
+}
+
+#define BADMAG(x) MC88BADMAG(x)
+#include "coffcode.h"
+
+#undef coff_write_armap
+
+const bfd_target m88kbcs_vec =
+{
+ "coff-m88kbcs", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-mips.c b/contrib/gdb/bfd/coff-mips.c
new file mode 100644
index 0000000..c860f9a
--- /dev/null
+++ b/contrib/gdb/bfd/coff-mips.c
@@ -0,0 +1,2596 @@
+/* BFD back-end for MIPS Extended-Coff files.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Original version by Per Bothner.
+ Full support added by Ian Lance Taylor, ian@cygnus.com.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "coff/symconst.h"
+#include "coff/ecoff.h"
+#include "coff/mips.h"
+#include "libcoff.h"
+#include "libecoff.h"
+
+/* Prototypes for static functions. */
+
+static boolean mips_ecoff_bad_format_hook PARAMS ((bfd *abfd, PTR filehdr));
+static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
+ struct internal_reloc *));
+static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
+ const struct internal_reloc *,
+ PTR));
+static void mips_adjust_reloc_in PARAMS ((bfd *,
+ const struct internal_reloc *,
+ arelent *));
+static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
+ struct internal_reloc *));
+static bfd_reloc_status_type mips_generic_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_refhi_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_reflo_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_gprel_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_relhi_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_rello_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_switch_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static void mips_relocate_hi PARAMS ((struct internal_reloc *refhi,
+ struct internal_reloc *reflo,
+ bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ size_t adjust,
+ bfd_vma relocation,
+ boolean pcrel));
+static boolean mips_relocate_section PARAMS ((bfd *, struct bfd_link_info *,
+ bfd *, asection *,
+ bfd_byte *, PTR));
+static boolean mips_read_relocs PARAMS ((bfd *, asection *));
+static boolean mips_relax_section PARAMS ((bfd *, asection *,
+ struct bfd_link_info *,
+ boolean *));
+static boolean mips_relax_pcrel16 PARAMS ((struct bfd_link_info *, bfd *,
+ asection *,
+ struct ecoff_link_hash_entry *,
+ bfd_byte *, bfd_vma));
+
+/* ECOFF has COFF sections, but the debugging information is stored in
+ a completely different format. ECOFF targets use some of the
+ swapping routines from coffswap.h, and some of the generic COFF
+ routines in coffgen.c, but, unlike the real COFF targets, do not
+ use coffcode.h itself.
+
+ Get the generic COFF swapping routines, except for the reloc,
+ symbol, and lineno ones. Give them ECOFF names. */
+#define MIPSECOFF
+#define NO_COFF_RELOCS
+#define NO_COFF_SYMBOLS
+#define NO_COFF_LINENOS
+#define coff_swap_filehdr_in mips_ecoff_swap_filehdr_in
+#define coff_swap_filehdr_out mips_ecoff_swap_filehdr_out
+#define coff_swap_aouthdr_in mips_ecoff_swap_aouthdr_in
+#define coff_swap_aouthdr_out mips_ecoff_swap_aouthdr_out
+#define coff_swap_scnhdr_in mips_ecoff_swap_scnhdr_in
+#define coff_swap_scnhdr_out mips_ecoff_swap_scnhdr_out
+#include "coffswap.h"
+
+/* Get the ECOFF swapping routines. */
+#define ECOFF_32
+#include "ecoffswap.h"
+
+/* How to process the various relocs types. */
+
+static reloc_howto_type mips_howto_table[] =
+{
+ /* Reloc type 0 is ignored. The reloc reading code ensures that
+ this is a reference to the .abs section, which will cause
+ bfd_perform_relocation to do nothing. */
+ HOWTO (MIPS_R_IGNORE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "IGNORE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 16 bit reference to a symbol, normally from a data section. */
+ HOWTO (MIPS_R_REFHALF, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_generic_reloc, /* special_function */
+ "REFHALF", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 32 bit reference to a symbol, normally from a data section. */
+ HOWTO (MIPS_R_REFWORD, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_generic_reloc, /* special_function */
+ "REFWORD", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 26 bit absolute jump address. */
+ HOWTO (MIPS_R_JMPADDR, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ /* This needs complex overflow
+ detection, because the upper four
+ bits must match the PC. */
+ mips_generic_reloc, /* special_function */
+ "JMPADDR", /* name */
+ true, /* partial_inplace */
+ 0x3ffffff, /* src_mask */
+ 0x3ffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The high 16 bits of a symbol value. Handled by the function
+ mips_refhi_reloc. */
+ HOWTO (MIPS_R_REFHI, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_refhi_reloc, /* special_function */
+ "REFHI", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The low 16 bits of a symbol value. */
+ HOWTO (MIPS_R_REFLO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ mips_reflo_reloc, /* special_function */
+ "REFLO", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A reference to an offset from the gp register. Handled by the
+ function mips_gprel_reloc. */
+ HOWTO (MIPS_R_GPREL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_gprel_reloc, /* special_function */
+ "GPREL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A reference to a literal using an offset from the gp register.
+ Handled by the function mips_gprel_reloc. */
+ HOWTO (MIPS_R_LITERAL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_gprel_reloc, /* special_function */
+ "LITERAL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 8 },
+ { 9 },
+ { 10 },
+ { 11 },
+
+ /* This reloc is a Cygnus extension used when generating position
+ independent code for embedded systems. It represents a 16 bit PC
+ relative reloc rightshifted twice as used in the MIPS branch
+ instructions. */
+ HOWTO (MIPS_R_PCREL16, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_generic_reloc, /* special_function */
+ "PCREL16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* This reloc is a Cygnus extension used when generating position
+ independent code for embedded systems. It represents the high 16
+ bits of a PC relative reloc. The next reloc must be
+ MIPS_R_RELLO, and the addend is formed from the addends of the
+ two instructions, just as in MIPS_R_REFHI and MIPS_R_REFLO. The
+ final value is actually PC relative to the location of the
+ MIPS_R_RELLO reloc, not the MIPS_R_RELHI reloc. */
+ HOWTO (MIPS_R_RELHI, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_relhi_reloc, /* special_function */
+ "RELHI", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* This reloc is a Cygnus extension used when generating position
+ independent code for embedded systems. It represents the low 16
+ bits of a PC relative reloc. */
+ HOWTO (MIPS_R_RELLO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ mips_rello_reloc, /* special_function */
+ "RELLO", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ { 15 },
+ { 16 },
+ { 17 },
+ { 18 },
+ { 19 },
+ { 20 },
+ { 21 },
+
+ /* This reloc is a Cygnus extension used when generating position
+ independent code for embedded systems. It represents an entry in
+ a switch table, which is the difference between two symbols in
+ the .text section. The symndx is actually the offset from the
+ reloc address to the subtrahend. See include/coff/mips.h for
+ more details. */
+ HOWTO (MIPS_R_SWITCH, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ mips_switch_reloc, /* special_function */
+ "SWITCH", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true) /* pcrel_offset */
+};
+
+#define MIPS_HOWTO_COUNT \
+ (sizeof mips_howto_table / sizeof mips_howto_table[0])
+
+/* When the linker is doing relaxing, it may change a external PCREL16
+ reloc. This typically represents an instruction like
+ bal foo
+ We change it to
+ .set noreorder
+ bal $L1
+ lui $at,%hi(foo - $L1)
+ $L1:
+ addiu $at,%lo(foo - $L1)
+ addu $at,$at,$31
+ jalr $at
+ PCREL16_EXPANSION_ADJUSTMENT is the number of bytes this changes the
+ instruction by. */
+
+#define PCREL16_EXPANSION_ADJUSTMENT (4 * 4)
+
+/* See whether the magic number matches. */
+
+static boolean
+mips_ecoff_bad_format_hook (abfd, filehdr)
+ bfd *abfd;
+ PTR filehdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+
+ switch (internal_f->f_magic)
+ {
+ case MIPS_MAGIC_1:
+ /* I don't know what endianness this implies. */
+ return true;
+
+ case MIPS_MAGIC_BIG:
+ case MIPS_MAGIC_BIG2:
+ case MIPS_MAGIC_BIG3:
+ return bfd_big_endian (abfd);
+
+ case MIPS_MAGIC_LITTLE:
+ case MIPS_MAGIC_LITTLE2:
+ case MIPS_MAGIC_LITTLE3:
+ return bfd_little_endian (abfd);
+
+ default:
+ return false;
+ }
+}
+
+/* Reloc handling. MIPS ECOFF relocs are packed into 8 bytes in
+ external form. They use a bit which indicates whether the symbol
+ is external. */
+
+/* Swap a reloc in. */
+
+static void
+mips_ecoff_swap_reloc_in (abfd, ext_ptr, intern)
+ bfd *abfd;
+ PTR ext_ptr;
+ struct internal_reloc *intern;
+{
+ const RELOC *ext = (RELOC *) ext_ptr;
+
+ intern->r_vaddr = bfd_h_get_32 (abfd, (bfd_byte *) ext->r_vaddr);
+ if (bfd_header_big_endian (abfd))
+ {
+ intern->r_symndx = (((int) ext->r_bits[0]
+ << RELOC_BITS0_SYMNDX_SH_LEFT_BIG)
+ | ((int) ext->r_bits[1]
+ << RELOC_BITS1_SYMNDX_SH_LEFT_BIG)
+ | ((int) ext->r_bits[2]
+ << RELOC_BITS2_SYMNDX_SH_LEFT_BIG));
+ intern->r_type = ((ext->r_bits[3] & RELOC_BITS3_TYPE_BIG)
+ >> RELOC_BITS3_TYPE_SH_BIG);
+ intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_BIG) != 0;
+ }
+ else
+ {
+ intern->r_symndx = (((int) ext->r_bits[0]
+ << RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE)
+ | ((int) ext->r_bits[1]
+ << RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE)
+ | ((int) ext->r_bits[2]
+ << RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE));
+ intern->r_type = (((ext->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
+ >> RELOC_BITS3_TYPE_SH_LITTLE)
+ | ((ext->r_bits[3] & RELOC_BITS3_TYPEHI_LITTLE)
+ << RELOC_BITS3_TYPEHI_SH_LITTLE));
+ intern->r_extern = (ext->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) != 0;
+ }
+
+ /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
+ MIPS_R_RELLO reloc, r_symndx is actually the offset from the
+ reloc address to the base of the difference (see
+ include/coff/mips.h for more details). We copy symndx into the
+ r_offset field so as not to confuse ecoff_slurp_reloc_table in
+ ecoff.c. In adjust_reloc_in we then copy r_offset into the reloc
+ addend. */
+ if (intern->r_type == MIPS_R_SWITCH
+ || (! intern->r_extern
+ && (intern->r_type == MIPS_R_RELLO
+ || intern->r_type == MIPS_R_RELHI)))
+ {
+ BFD_ASSERT (! intern->r_extern);
+ intern->r_offset = intern->r_symndx;
+ if (intern->r_offset & 0x800000)
+ intern->r_offset -= 0x1000000;
+ intern->r_symndx = RELOC_SECTION_TEXT;
+ }
+}
+
+/* Swap a reloc out. */
+
+static void
+mips_ecoff_swap_reloc_out (abfd, intern, dst)
+ bfd *abfd;
+ const struct internal_reloc *intern;
+ PTR dst;
+{
+ RELOC *ext = (RELOC *) dst;
+ long r_symndx;
+
+ BFD_ASSERT (intern->r_extern
+ || (intern->r_symndx >= 0 && intern->r_symndx <= 12));
+
+ /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELLO or
+ MIPS_R_RELHI reloc, we actually want to write the contents of
+ r_offset out as the symbol index. This undoes the change made by
+ mips_ecoff_swap_reloc_in. */
+ if (intern->r_type != MIPS_R_SWITCH
+ && (intern->r_extern
+ || (intern->r_type != MIPS_R_RELHI
+ && intern->r_type != MIPS_R_RELLO)))
+ r_symndx = intern->r_symndx;
+ else
+ {
+ BFD_ASSERT (intern->r_symndx == RELOC_SECTION_TEXT);
+ r_symndx = intern->r_offset & 0xffffff;
+ }
+
+ bfd_h_put_32 (abfd, intern->r_vaddr, (bfd_byte *) ext->r_vaddr);
+ if (bfd_header_big_endian (abfd))
+ {
+ ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_BIG;
+ ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_BIG;
+ ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_BIG;
+ ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_BIG)
+ & RELOC_BITS3_TYPE_BIG)
+ | (intern->r_extern ? RELOC_BITS3_EXTERN_BIG : 0));
+ }
+ else
+ {
+ ext->r_bits[0] = r_symndx >> RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE;
+ ext->r_bits[1] = r_symndx >> RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE;
+ ext->r_bits[2] = r_symndx >> RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE;
+ ext->r_bits[3] = (((intern->r_type << RELOC_BITS3_TYPE_SH_LITTLE)
+ & RELOC_BITS3_TYPE_LITTLE)
+ | ((intern->r_type >> RELOC_BITS3_TYPEHI_SH_LITTLE
+ & RELOC_BITS3_TYPEHI_LITTLE))
+ | (intern->r_extern ? RELOC_BITS3_EXTERN_LITTLE : 0));
+ }
+}
+
+/* Finish canonicalizing a reloc. Part of this is generic to all
+ ECOFF targets, and that part is in ecoff.c. The rest is done in
+ this backend routine. It must fill in the howto field. */
+
+static void
+mips_adjust_reloc_in (abfd, intern, rptr)
+ bfd *abfd;
+ const struct internal_reloc *intern;
+ arelent *rptr;
+{
+ if (intern->r_type > MIPS_R_SWITCH)
+ abort ();
+
+ if (! intern->r_extern
+ && (intern->r_type == MIPS_R_GPREL
+ || intern->r_type == MIPS_R_LITERAL))
+ rptr->addend += ecoff_data (abfd)->gp;
+
+ /* If the type is MIPS_R_IGNORE, make sure this is a reference to
+ the absolute section so that the reloc is ignored. */
+ if (intern->r_type == MIPS_R_IGNORE)
+ rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+
+ /* If this is a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
+ MIPS_R_RELLO reloc, we want the addend field of the BFD relocto
+ hold the value which was originally in the symndx field of the
+ internal MIPS ECOFF reloc. This value was copied into
+ intern->r_offset by mips_swap_reloc_in, and here we copy it into
+ the addend field. */
+ if (intern->r_type == MIPS_R_SWITCH
+ || (! intern->r_extern
+ && (intern->r_type == MIPS_R_RELHI
+ || intern->r_type == MIPS_R_RELLO)))
+ rptr->addend = intern->r_offset;
+
+ rptr->howto = &mips_howto_table[intern->r_type];
+}
+
+/* Make any adjustments needed to a reloc before writing it out. None
+ are needed for MIPS. */
+
+static void
+mips_adjust_reloc_out (abfd, rel, intern)
+ bfd *abfd;
+ const arelent *rel;
+ struct internal_reloc *intern;
+{
+ /* For a MIPS_R_SWITCH reloc, or an internal MIPS_R_RELHI or
+ MIPS_R_RELLO reloc, we must copy rel->addend into
+ intern->r_offset. This will then be written out as the symbol
+ index by mips_ecoff_swap_reloc_out. This operation parallels the
+ action of mips_adjust_reloc_in. */
+ if (intern->r_type == MIPS_R_SWITCH
+ || (! intern->r_extern
+ && (intern->r_type == MIPS_R_RELHI
+ || intern->r_type == MIPS_R_RELLO)))
+ intern->r_offset = rel->addend;
+}
+
+/* ECOFF relocs are either against external symbols, or against
+ sections. If we are producing relocateable output, and the reloc
+ is against an external symbol, and nothing has given us any
+ additional addend, the resulting reloc will also be against the
+ same symbol. In such a case, we don't want to change anything
+ about the way the reloc is handled, since it will all be done at
+ final link time. Rather than put special case code into
+ bfd_perform_relocation, all the reloc types use this howto
+ function. It just short circuits the reloc if producing
+ relocateable output against an external symbol. */
+
+static bfd_reloc_status_type
+mips_generic_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ 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->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ return bfd_reloc_continue;
+}
+
+/* Do a REFHI relocation. This has to be done in combination with a
+ REFLO reloc, because there is a carry from the REFLO to the REFHI.
+ Here we just save the information we need; we do the actual
+ relocation when we see the REFLO. MIPS ECOFF requires that the
+ REFLO immediately follow the REFHI, so this ought to work. */
+
+static bfd_byte *mips_refhi_addr;
+static bfd_vma mips_refhi_addend;
+
+static bfd_reloc_status_type
+mips_refhi_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_reloc_status_type ret;
+ bfd_vma relocation;
+
+ /* If we're relocating, and this an external symbol, we don't want
+ to change anything. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ ret = bfd_reloc_ok;
+ if (bfd_is_und_section (symbol->section)
+ && output_bfd == (bfd *) NULL)
+ ret = bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Save the information, and let REFLO do the actual relocation. */
+ mips_refhi_addr = (bfd_byte *) data + reloc_entry->address;
+ mips_refhi_addend = relocation;
+
+ if (output_bfd != (bfd *) NULL)
+ reloc_entry->address += input_section->output_offset;
+
+ return ret;
+}
+
+/* Do a REFLO relocation. This is a straightforward 16 bit inplace
+ relocation; this function exists in order to do the REFHI
+ relocation described above. */
+
+static bfd_reloc_status_type
+mips_reflo_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ if (mips_refhi_addr != (bfd_byte *) NULL)
+ {
+ unsigned long insn;
+ unsigned long val;
+ unsigned long vallo;
+
+ /* Do the REFHI relocation. Note that we actually don't need to
+ know anything about the REFLO itself, except where to find
+ the low 16 bits of the addend needed by the REFHI. */
+ insn = bfd_get_32 (abfd, mips_refhi_addr);
+ vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
+ & 0xffff);
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += mips_refhi_addend;
+
+ /* The low order 16 bits are always treated as a signed value.
+ Therefore, a negative value in the low order bits requires an
+ adjustment in the high order bits. We need to make this
+ adjustment in two ways: once for the bits we took from the
+ data, and once for the bits we are putting back in to the
+ data. */
+ if ((vallo & 0x8000) != 0)
+ val -= 0x10000;
+ if ((val & 0x8000) != 0)
+ val += 0x10000;
+
+ insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
+ bfd_put_32 (abfd, insn, mips_refhi_addr);
+
+ mips_refhi_addr = (bfd_byte *) NULL;
+ }
+
+ /* Now do the REFLO reloc in the usual way. */
+ return mips_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+}
+
+/* Do a GPREL relocation. This is a 16 bit value which must become
+ the offset from the gp register. */
+
+static bfd_reloc_status_type
+mips_gprel_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ boolean relocateable;
+ bfd_vma gp;
+ bfd_vma relocation;
+ unsigned long val;
+ unsigned long insn;
+
+ /* If we're relocating, and this is an external symbol with no
+ addend, we don't want to change anything. We will only have an
+ addend if this is a newly created reloc, not read from an ECOFF
+ file. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (output_bfd != (bfd *) NULL)
+ relocateable = true;
+ else
+ {
+ relocateable = false;
+ output_bfd = symbol->section->output_section->owner;
+ }
+
+ if (bfd_is_und_section (symbol->section)
+ && relocateable == false)
+ return bfd_reloc_undefined;
+
+ /* We have to figure out the gp value, so that we can adjust the
+ symbol value correctly. We look up the symbol _gp in the output
+ BFD. If we can't find it, we're stuck. We cache it in the ECOFF
+ target data. We don't need to adjust the symbol value for an
+ external symbol if we are producing relocateable output. */
+ gp = _bfd_get_gp_value (output_bfd);
+ if (gp == 0
+ && (relocateable == false
+ || (symbol->flags & BSF_SECTION_SYM) != 0))
+ {
+ if (relocateable != false)
+ {
+ /* Make up a value. */
+ gp = symbol->section->output_section->vma + 0x4000;
+ _bfd_set_gp_value (output_bfd, gp);
+ }
+ else
+ {
+ unsigned int count;
+ asymbol **sym;
+ unsigned int i;
+
+ count = bfd_get_symcount (output_bfd);
+ sym = bfd_get_outsymbols (output_bfd);
+
+ if (sym == (asymbol **) NULL)
+ i = count;
+ else
+ {
+ for (i = 0; i < count; i++, sym++)
+ {
+ register CONST char *name;
+
+ name = bfd_asymbol_name (*sym);
+ if (*name == '_' && strcmp (name, "_gp") == 0)
+ {
+ gp = bfd_asymbol_value (*sym);
+ _bfd_set_gp_value (output_bfd, gp);
+ break;
+ }
+ }
+ }
+
+ if (i >= count)
+ {
+ /* Only get the error once. */
+ gp = 4;
+ _bfd_set_gp_value (output_bfd, gp);
+ *error_message =
+ (char *) "GP relative relocation when _gp not defined";
+ return bfd_reloc_dangerous;
+ }
+ }
+ }
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+
+ /* Set val to the offset into the section or symbol. */
+ val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
+ if (val & 0x8000)
+ val -= 0x10000;
+
+ /* Adjust val for the final section location and GP value. If we
+ are producing relocateable output, we don't want to do this for
+ an external symbol. */
+ if (relocateable == false
+ || (symbol->flags & BSF_SECTION_SYM) != 0)
+ val += relocation - gp;
+
+ insn = (insn &~ 0xffff) | (val & 0xffff);
+ bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+
+ if (relocateable != false)
+ reloc_entry->address += input_section->output_offset;
+
+ /* Make sure it fit in 16 bits. */
+ if (val >= 0x8000 && val < 0xffff8000)
+ return bfd_reloc_overflow;
+
+ return bfd_reloc_ok;
+}
+
+/* Do a RELHI relocation. We do this in conjunction with a RELLO
+ reloc, just as REFHI and REFLO are done together. RELHI and RELLO
+ are Cygnus extensions used when generating position independent
+ code for embedded systems. */
+
+static bfd_byte *mips_relhi_addr;
+static bfd_vma mips_relhi_addend;
+
+static bfd_reloc_status_type
+mips_relhi_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_reloc_status_type ret;
+ bfd_vma relocation;
+
+ /* If this is a reloc against a section symbol, then it is correct
+ in the object file. The only time we want to change this case is
+ when we are relaxing, and that is handled entirely by
+ mips_relocate_section and never calls this function. */
+ if ((symbol->flags & BSF_SECTION_SYM) != 0)
+ {
+ if (output_bfd != (bfd *) NULL)
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* This is an external symbol. If we're relocating, we don't want
+ to change anything. */
+ if (output_bfd != (bfd *) NULL)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ ret = bfd_reloc_ok;
+ if (bfd_is_und_section (symbol->section)
+ && output_bfd == (bfd *) NULL)
+ ret = bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Save the information, and let RELLO do the actual relocation. */
+ mips_relhi_addr = (bfd_byte *) data + reloc_entry->address;
+ mips_relhi_addend = relocation;
+
+ if (output_bfd != (bfd *) NULL)
+ reloc_entry->address += input_section->output_offset;
+
+ return ret;
+}
+
+/* Do a RELLO relocation. This is a straightforward 16 bit PC
+ relative relocation; this function exists in order to do the RELHI
+ relocation described above. */
+
+static bfd_reloc_status_type
+mips_rello_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ if (mips_relhi_addr != (bfd_byte *) NULL)
+ {
+ unsigned long insn;
+ unsigned long val;
+ unsigned long vallo;
+
+ /* Do the RELHI relocation. Note that we actually don't need to
+ know anything about the RELLO itself, except where to find
+ the low 16 bits of the addend needed by the RELHI. */
+ insn = bfd_get_32 (abfd, mips_relhi_addr);
+ vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
+ & 0xffff);
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += mips_relhi_addend;
+
+ /* If the symbol is defined, make val PC relative. If the
+ symbol is not defined we don't want to do this, because we
+ don't want the value in the object file to incorporate the
+ address of the reloc. */
+ if (! bfd_is_und_section (bfd_get_section (symbol))
+ && ! bfd_is_com_section (bfd_get_section (symbol)))
+ val -= (input_section->output_section->vma
+ + input_section->output_offset
+ + reloc_entry->address);
+
+ /* The low order 16 bits are always treated as a signed value.
+ Therefore, a negative value in the low order bits requires an
+ adjustment in the high order bits. We need to make this
+ adjustment in two ways: once for the bits we took from the
+ data, and once for the bits we are putting back in to the
+ data. */
+ if ((vallo & 0x8000) != 0)
+ val -= 0x10000;
+ if ((val & 0x8000) != 0)
+ val += 0x10000;
+
+ insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
+ bfd_put_32 (abfd, insn, mips_relhi_addr);
+
+ mips_relhi_addr = (bfd_byte *) NULL;
+ }
+
+ /* If this is a reloc against a section symbol, then it is correct
+ in the object file. The only time we want to change this case is
+ when we are relaxing, and that is handled entirely by
+ mips_relocate_section and never calls this function. */
+ if ((symbol->flags & BSF_SECTION_SYM) != 0)
+ {
+ if (output_bfd != (bfd *) NULL)
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* bfd_perform_relocation does not handle pcrel_offset relocations
+ correctly when generating a relocateable file, so handle them
+ directly here. */
+ if (output_bfd != (bfd *) NULL)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* Now do the RELLO reloc in the usual way. */
+ return mips_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+}
+
+/* This is the special function for the MIPS_R_SWITCH reloc. This
+ special reloc is normally correct in the object file, and only
+ requires special handling when relaxing. We don't want
+ bfd_perform_relocation to tamper with it at all. */
+
+/*ARGSUSED*/
+static bfd_reloc_status_type
+mips_switch_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ return bfd_reloc_ok;
+}
+
+/* Get the howto structure for a generic reloc type. */
+
+static reloc_howto_type *
+mips_bfd_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ int mips_type;
+
+ switch (code)
+ {
+ case BFD_RELOC_16:
+ mips_type = MIPS_R_REFHALF;
+ break;
+ case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
+ mips_type = MIPS_R_REFWORD;
+ break;
+ case BFD_RELOC_MIPS_JMP:
+ mips_type = MIPS_R_JMPADDR;
+ break;
+ case BFD_RELOC_HI16_S:
+ mips_type = MIPS_R_REFHI;
+ break;
+ case BFD_RELOC_LO16:
+ mips_type = MIPS_R_REFLO;
+ break;
+ case BFD_RELOC_MIPS_GPREL:
+ mips_type = MIPS_R_GPREL;
+ break;
+ case BFD_RELOC_MIPS_LITERAL:
+ mips_type = MIPS_R_LITERAL;
+ break;
+ case BFD_RELOC_16_PCREL_S2:
+ mips_type = MIPS_R_PCREL16;
+ break;
+ case BFD_RELOC_PCREL_HI16_S:
+ mips_type = MIPS_R_RELHI;
+ break;
+ case BFD_RELOC_PCREL_LO16:
+ mips_type = MIPS_R_RELLO;
+ break;
+ case BFD_RELOC_GPREL32:
+ mips_type = MIPS_R_SWITCH;
+ break;
+ default:
+ return (reloc_howto_type *) NULL;
+ }
+
+ return &mips_howto_table[mips_type];
+}
+
+/* A helper routine for mips_relocate_section which handles the REFHI
+ and RELHI relocations. The REFHI relocation must be followed by a
+ REFLO relocation (and RELHI by a RELLO), and the addend used is
+ formed from the addends of both instructions. */
+
+static void
+mips_relocate_hi (refhi, reflo, input_bfd, input_section, contents, adjust,
+ relocation, pcrel)
+ struct internal_reloc *refhi;
+ struct internal_reloc *reflo;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ size_t adjust;
+ bfd_vma relocation;
+ boolean pcrel;
+{
+ unsigned long insn;
+ unsigned long val;
+ unsigned long vallo;
+
+ insn = bfd_get_32 (input_bfd,
+ contents + adjust + refhi->r_vaddr - input_section->vma);
+ vallo = (bfd_get_32 (input_bfd,
+ contents + adjust + reflo->r_vaddr - input_section->vma)
+ & 0xffff);
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += relocation;
+
+ /* The low order 16 bits are always treated as a signed value.
+ Therefore, a negative value in the low order bits requires an
+ adjustment in the high order bits. We need to make this
+ adjustment in two ways: once for the bits we took from the data,
+ and once for the bits we are putting back in to the data. */
+ if ((vallo & 0x8000) != 0)
+ val -= 0x10000;
+
+ if (pcrel)
+ val -= (input_section->output_section->vma
+ + input_section->output_offset
+ + (reflo->r_vaddr - input_section->vma + adjust));
+
+ if ((val & 0x8000) != 0)
+ val += 0x10000;
+
+ insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
+ bfd_put_32 (input_bfd, (bfd_vma) insn,
+ contents + adjust + refhi->r_vaddr - input_section->vma);
+}
+
+/* Relocate a section while linking a MIPS ECOFF file. */
+
+static boolean
+mips_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, external_relocs)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ PTR external_relocs;
+{
+ asection **symndx_to_section;
+ struct ecoff_link_hash_entry **sym_hashes;
+ bfd_vma gp;
+ boolean gp_undefined;
+ size_t adjust;
+ long *offsets;
+ struct external_reloc *ext_rel;
+ struct external_reloc *ext_rel_end;
+ unsigned int i;
+ boolean got_lo;
+ struct internal_reloc lo_int_rel;
+
+ BFD_ASSERT (input_bfd->xvec->header_byteorder
+ == output_bfd->xvec->header_byteorder);
+
+ /* We keep a table mapping the symndx found in an internal reloc to
+ the appropriate section. This is faster than looking up the
+ section by name each time. */
+ symndx_to_section = ecoff_data (input_bfd)->symndx_to_section;
+ if (symndx_to_section == (asection **) NULL)
+ {
+ symndx_to_section = ((asection **)
+ bfd_alloc (input_bfd,
+ (NUM_RELOC_SECTIONS
+ * sizeof (asection *))));
+ if (!symndx_to_section)
+ return false;
+
+ symndx_to_section[RELOC_SECTION_NONE] = NULL;
+ symndx_to_section[RELOC_SECTION_TEXT] =
+ bfd_get_section_by_name (input_bfd, ".text");
+ symndx_to_section[RELOC_SECTION_RDATA] =
+ bfd_get_section_by_name (input_bfd, ".rdata");
+ symndx_to_section[RELOC_SECTION_DATA] =
+ bfd_get_section_by_name (input_bfd, ".data");
+ symndx_to_section[RELOC_SECTION_SDATA] =
+ bfd_get_section_by_name (input_bfd, ".sdata");
+ symndx_to_section[RELOC_SECTION_SBSS] =
+ bfd_get_section_by_name (input_bfd, ".sbss");
+ symndx_to_section[RELOC_SECTION_BSS] =
+ bfd_get_section_by_name (input_bfd, ".bss");
+ symndx_to_section[RELOC_SECTION_INIT] =
+ bfd_get_section_by_name (input_bfd, ".init");
+ symndx_to_section[RELOC_SECTION_LIT8] =
+ bfd_get_section_by_name (input_bfd, ".lit8");
+ symndx_to_section[RELOC_SECTION_LIT4] =
+ bfd_get_section_by_name (input_bfd, ".lit4");
+ symndx_to_section[RELOC_SECTION_XDATA] = NULL;
+ symndx_to_section[RELOC_SECTION_PDATA] = NULL;
+ symndx_to_section[RELOC_SECTION_FINI] =
+ bfd_get_section_by_name (input_bfd, ".fini");
+ symndx_to_section[RELOC_SECTION_LITA] = NULL;
+ symndx_to_section[RELOC_SECTION_ABS] = NULL;
+
+ ecoff_data (input_bfd)->symndx_to_section = symndx_to_section;
+ }
+
+ sym_hashes = ecoff_data (input_bfd)->sym_hashes;
+
+ gp = _bfd_get_gp_value (output_bfd);
+ if (gp == 0)
+ gp_undefined = true;
+ else
+ gp_undefined = false;
+
+ got_lo = false;
+
+ adjust = 0;
+
+ if (ecoff_section_data (input_bfd, input_section) == NULL)
+ offsets = NULL;
+ else
+ offsets = ecoff_section_data (input_bfd, input_section)->offsets;
+
+ ext_rel = (struct external_reloc *) external_relocs;
+ ext_rel_end = ext_rel + input_section->reloc_count;
+ for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
+ {
+ struct internal_reloc int_rel;
+ bfd_vma addend;
+ reloc_howto_type *howto;
+ struct ecoff_link_hash_entry *h = NULL;
+ asection *s = NULL;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+
+ if (! got_lo)
+ mips_ecoff_swap_reloc_in (input_bfd, (PTR) ext_rel, &int_rel);
+ else
+ {
+ int_rel = lo_int_rel;
+ got_lo = false;
+ }
+
+ BFD_ASSERT (int_rel.r_type
+ < sizeof mips_howto_table / sizeof mips_howto_table[0]);
+
+ /* The REFHI and RELHI relocs requires special handling. they
+ must be followed by a REFLO or RELLO reloc, respectively, and
+ the addend is formed from both relocs. */
+ if (int_rel.r_type == MIPS_R_REFHI
+ || int_rel.r_type == MIPS_R_RELHI)
+ {
+ BFD_ASSERT ((ext_rel + 1) < ext_rel_end);
+ mips_ecoff_swap_reloc_in (input_bfd, (PTR) (ext_rel + 1),
+ &lo_int_rel);
+ BFD_ASSERT ((lo_int_rel.r_type
+ == (int_rel.r_type == MIPS_R_REFHI
+ ? MIPS_R_REFLO
+ : MIPS_R_RELLO))
+ && int_rel.r_extern == lo_int_rel.r_extern
+ && int_rel.r_symndx == lo_int_rel.r_symndx);
+ got_lo = true;
+ }
+
+ howto = &mips_howto_table[int_rel.r_type];
+
+ /* The SWITCH reloc must be handled specially. This reloc is
+ marks the location of a difference between two portions of an
+ object file. The symbol index does not reference a symbol,
+ but is actually the offset from the reloc to the subtrahend
+ of the difference. This reloc is correct in the object file,
+ and needs no further adjustment, unless we are relaxing. If
+ we are relaxing, we may have to add in an offset. Since no
+ symbols are involved in this reloc, we handle it completely
+ here. */
+ if (int_rel.r_type == MIPS_R_SWITCH)
+ {
+ if (offsets != NULL
+ && offsets[i] != 0)
+ {
+ r = _bfd_relocate_contents (howto, input_bfd,
+ (bfd_vma) offsets[i],
+ (contents
+ + adjust
+ + int_rel.r_vaddr
+ - input_section->vma));
+ BFD_ASSERT (r == bfd_reloc_ok);
+ }
+
+ continue;
+ }
+
+ if (int_rel.r_extern)
+ {
+ h = sym_hashes[int_rel.r_symndx];
+ /* If h is NULL, that means that there is a reloc against an
+ external symbol which we thought was just a debugging
+ symbol. This should not happen. */
+ if (h == (struct ecoff_link_hash_entry *) NULL)
+ abort ();
+ }
+ else
+ {
+ if (int_rel.r_symndx < 0 || int_rel.r_symndx >= NUM_RELOC_SECTIONS)
+ s = NULL;
+ else
+ s = symndx_to_section[int_rel.r_symndx];
+
+ if (s == (asection *) NULL)
+ abort ();
+ }
+
+ /* The GPREL reloc uses an addend: the difference in the GP
+ values. */
+ if (int_rel.r_type != MIPS_R_GPREL
+ && int_rel.r_type != MIPS_R_LITERAL)
+ addend = 0;
+ else
+ {
+ if (gp_undefined)
+ {
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info, "GP relative relocation when GP not defined",
+ input_bfd, input_section,
+ int_rel.r_vaddr - input_section->vma)))
+ return false;
+ /* Only give the error once per link. */
+ gp = 4;
+ _bfd_set_gp_value (output_bfd, gp);
+ gp_undefined = false;
+ }
+ if (! int_rel.r_extern)
+ {
+ /* This is a relocation against a section. The current
+ addend in the instruction is the difference between
+ INPUT_SECTION->vma and the GP value of INPUT_BFD. We
+ must change this to be the difference between the
+ final definition (which will end up in RELOCATION)
+ and the GP value of OUTPUT_BFD (which is in GP). */
+ addend = ecoff_data (input_bfd)->gp - gp;
+ }
+ else if (! info->relocateable
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ /* This is a relocation against a defined symbol. The
+ current addend in the instruction is simply the
+ desired offset into the symbol (normally zero). We
+ are going to change this into a relocation against a
+ defined symbol, so we want the instruction to hold
+ the difference between the final definition of the
+ symbol (which will end up in RELOCATION) and the GP
+ value of OUTPUT_BFD (which is in GP). */
+ addend = - gp;
+ }
+ else
+ {
+ /* This is a relocation against an undefined or common
+ symbol. The current addend in the instruction is
+ simply the desired offset into the symbol (normally
+ zero). We are generating relocateable output, and we
+ aren't going to define this symbol, so we just leave
+ the instruction alone. */
+ addend = 0;
+ }
+ }
+
+ /* If we are relaxing, mips_relax_section may have set
+ offsets[i] to some value. A value of 1 means we must expand
+ a PC relative branch into a multi-instruction of sequence,
+ and any other value is an addend. */
+ if (offsets != NULL
+ && offsets[i] != 0)
+ {
+ BFD_ASSERT (! info->relocateable);
+ BFD_ASSERT (int_rel.r_type == MIPS_R_PCREL16
+ || int_rel.r_type == MIPS_R_RELHI
+ || int_rel.r_type == MIPS_R_RELLO);
+ if (offsets[i] != 1)
+ addend += offsets[i];
+ else
+ {
+ bfd_byte *here;
+
+ BFD_ASSERT (int_rel.r_extern
+ && int_rel.r_type == MIPS_R_PCREL16);
+
+ /* Move the rest of the instructions up. */
+ here = (contents
+ + adjust
+ + int_rel.r_vaddr
+ - input_section->vma);
+ memmove (here + PCREL16_EXPANSION_ADJUSTMENT, here,
+ (size_t) (input_section->_raw_size
+ - (int_rel.r_vaddr - input_section->vma)));
+
+ /* Generate the new instructions. */
+ if (! mips_relax_pcrel16 (info, input_bfd, input_section,
+ h, here,
+ (input_section->output_section->vma
+ + input_section->output_offset
+ + (int_rel.r_vaddr
+ - input_section->vma)
+ + adjust)))
+ return false;
+
+ /* We must adjust everything else up a notch. */
+ adjust += PCREL16_EXPANSION_ADJUSTMENT;
+
+ /* mips_relax_pcrel16 handles all the details of this
+ relocation. */
+ continue;
+ }
+ }
+
+ /* If we are relaxing, and this is a reloc against the .text
+ segment, we may need to adjust it if some branches have been
+ expanded. The reloc types which are likely to occur in the
+ .text section are handled efficiently by mips_relax_section,
+ and thus do not need to be handled here. */
+ if (ecoff_data (input_bfd)->debug_info.adjust != NULL
+ && ! int_rel.r_extern
+ && int_rel.r_symndx == RELOC_SECTION_TEXT
+ && (strcmp (bfd_get_section_name (input_bfd, input_section),
+ ".text") != 0
+ || (int_rel.r_type != MIPS_R_PCREL16
+ && int_rel.r_type != MIPS_R_SWITCH
+ && int_rel.r_type != MIPS_R_RELHI
+ && int_rel.r_type != MIPS_R_RELLO)))
+ {
+ bfd_vma adr;
+ struct ecoff_value_adjust *a;
+
+ /* We need to get the addend so that we know whether we need
+ to adjust the address. */
+ BFD_ASSERT (int_rel.r_type == MIPS_R_REFWORD);
+
+ adr = bfd_get_32 (input_bfd,
+ (contents
+ + adjust
+ + int_rel.r_vaddr
+ - input_section->vma));
+
+ for (a = ecoff_data (input_bfd)->debug_info.adjust;
+ a != (struct ecoff_value_adjust *) NULL;
+ a = a->next)
+ {
+ if (adr >= a->start && adr < a->end)
+ addend += a->adjust;
+ }
+ }
+
+ if (info->relocateable)
+ {
+ /* We are generating relocateable output, and must convert
+ the existing reloc. */
+ if (int_rel.r_extern)
+ {
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && ! bfd_is_abs_section (h->root.u.def.section))
+ {
+ const char *name;
+
+ /* This symbol is defined in the output. Convert
+ the reloc from being against the symbol to being
+ against the section. */
+
+ /* Clear the r_extern bit. */
+ int_rel.r_extern = 0;
+
+ /* Compute a new r_symndx value. */
+ s = h->root.u.def.section;
+ name = bfd_get_section_name (output_bfd,
+ s->output_section);
+
+ int_rel.r_symndx = -1;
+ switch (name[1])
+ {
+ case 'b':
+ if (strcmp (name, ".bss") == 0)
+ int_rel.r_symndx = RELOC_SECTION_BSS;
+ break;
+ case 'd':
+ if (strcmp (name, ".data") == 0)
+ int_rel.r_symndx = RELOC_SECTION_DATA;
+ break;
+ case 'f':
+ if (strcmp (name, ".fini") == 0)
+ int_rel.r_symndx = RELOC_SECTION_FINI;
+ break;
+ case 'i':
+ if (strcmp (name, ".init") == 0)
+ int_rel.r_symndx = RELOC_SECTION_INIT;
+ break;
+ case 'l':
+ if (strcmp (name, ".lit8") == 0)
+ int_rel.r_symndx = RELOC_SECTION_LIT8;
+ else if (strcmp (name, ".lit4") == 0)
+ int_rel.r_symndx = RELOC_SECTION_LIT4;
+ break;
+ case 'r':
+ if (strcmp (name, ".rdata") == 0)
+ int_rel.r_symndx = RELOC_SECTION_RDATA;
+ break;
+ case 's':
+ if (strcmp (name, ".sdata") == 0)
+ int_rel.r_symndx = RELOC_SECTION_SDATA;
+ else if (strcmp (name, ".sbss") == 0)
+ int_rel.r_symndx = RELOC_SECTION_SBSS;
+ break;
+ case 't':
+ if (strcmp (name, ".text") == 0)
+ int_rel.r_symndx = RELOC_SECTION_TEXT;
+ break;
+ }
+
+ if (int_rel.r_symndx == -1)
+ abort ();
+
+ /* Add the section VMA and the symbol value. */
+ relocation = (h->root.u.def.value
+ + s->output_section->vma
+ + s->output_offset);
+
+ /* For a PC relative relocation, the object file
+ currently holds just the addend. We must adjust
+ by the address to get the right value. */
+ if (howto->pc_relative)
+ {
+ relocation -= int_rel.r_vaddr - input_section->vma;
+
+ /* If we are converting a RELHI or RELLO reloc
+ from being against an external symbol to
+ being against a section, we must put a
+ special value into the r_offset field. This
+ value is the old addend. The r_offset for
+ both the RELOHI and RELLO relocs are the
+ same, and we set both when we see RELHI. */
+ if (int_rel.r_type == MIPS_R_RELHI)
+ {
+ long addhi, addlo;
+
+ addhi = bfd_get_32 (input_bfd,
+ (contents
+ + adjust
+ + int_rel.r_vaddr
+ - input_section->vma));
+ addhi &= 0xffff;
+ if (addhi & 0x8000)
+ addhi -= 0x10000;
+ addhi <<= 16;
+
+ addlo = bfd_get_32 (input_bfd,
+ (contents
+ + adjust
+ + lo_int_rel.r_vaddr
+ - input_section->vma));
+ addlo &= 0xffff;
+ if (addlo & 0x8000)
+ addlo -= 0x10000;
+
+ int_rel.r_offset = addhi + addlo;
+ lo_int_rel.r_offset = int_rel.r_offset;
+ }
+ }
+
+ h = NULL;
+ }
+ else
+ {
+ /* Change the symndx value to the right one for the
+ output BFD. */
+ int_rel.r_symndx = h->indx;
+ if (int_rel.r_symndx == -1)
+ {
+ /* This symbol is not being written out. */
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, h->root.root.string, input_bfd,
+ input_section,
+ int_rel.r_vaddr - input_section->vma)))
+ return false;
+ int_rel.r_symndx = 0;
+ }
+ relocation = 0;
+ }
+ }
+ else
+ {
+ /* This is a relocation against a section. Adjust the
+ value by the amount the section moved. */
+ relocation = (s->output_section->vma
+ + s->output_offset
+ - s->vma);
+ }
+
+ relocation += addend;
+ addend = 0;
+
+ /* Adjust a PC relative relocation by removing the reference
+ to the original address in the section and including the
+ reference to the new address. However, external RELHI
+ and RELLO relocs are PC relative, but don't include any
+ reference to the address. The addend is merely an
+ addend. */
+ if (howto->pc_relative
+ && (! int_rel.r_extern
+ || (int_rel.r_type != MIPS_R_RELHI
+ && int_rel.r_type != MIPS_R_RELLO)))
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset
+ - input_section->vma);
+
+ /* Adjust the contents. */
+ if (relocation == 0)
+ r = bfd_reloc_ok;
+ else
+ {
+ if (int_rel.r_type != MIPS_R_REFHI
+ && int_rel.r_type != MIPS_R_RELHI)
+ r = _bfd_relocate_contents (howto, input_bfd, relocation,
+ (contents
+ + adjust
+ + int_rel.r_vaddr
+ - input_section->vma));
+ else
+ {
+ mips_relocate_hi (&int_rel, &lo_int_rel,
+ input_bfd, input_section, contents,
+ adjust, relocation,
+ int_rel.r_type == MIPS_R_RELHI);
+ r = bfd_reloc_ok;
+ }
+ }
+
+ /* Adjust the reloc address. */
+ int_rel.r_vaddr += (input_section->output_section->vma
+ + input_section->output_offset
+ - input_section->vma);
+
+ /* Save the changed reloc information. */
+ mips_ecoff_swap_reloc_out (input_bfd, &int_rel, (PTR) ext_rel);
+ }
+ else
+ {
+ /* We are producing a final executable. */
+ if (int_rel.r_extern)
+ {
+ /* This is a reloc against a symbol. */
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *hsec;
+
+ hsec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + hsec->output_section->vma
+ + hsec->output_offset);
+ }
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section,
+ int_rel.r_vaddr - input_section->vma)))
+ return false;
+ relocation = 0;
+ }
+ }
+ else
+ {
+ /* This is a reloc against a section. */
+ relocation = (s->output_section->vma
+ + s->output_offset
+ - s->vma);
+
+ /* A PC relative reloc is already correct in the object
+ file. Make it look like a pcrel_offset relocation by
+ adding in the start address. */
+ if (howto->pc_relative)
+ {
+ if (int_rel.r_type != MIPS_R_RELHI)
+ relocation += int_rel.r_vaddr + adjust;
+ else
+ relocation += lo_int_rel.r_vaddr + adjust;
+ }
+ }
+
+ if (int_rel.r_type != MIPS_R_REFHI
+ && int_rel.r_type != MIPS_R_RELHI)
+ r = _bfd_final_link_relocate (howto,
+ input_bfd,
+ input_section,
+ contents,
+ (int_rel.r_vaddr
+ - input_section->vma
+ + adjust),
+ relocation,
+ addend);
+ else
+ {
+ mips_relocate_hi (&int_rel, &lo_int_rel, input_bfd,
+ input_section, contents, adjust,
+ relocation,
+ int_rel.r_type == MIPS_R_RELHI);
+ r = bfd_reloc_ok;
+ }
+ }
+
+ /* MIPS_R_JMPADDR requires peculiar overflow detection. The
+ instruction provides a 28 bit address (the two lower bits are
+ implicit zeroes) which is combined with the upper four bits
+ of the instruction address. */
+ if (r == bfd_reloc_ok
+ && int_rel.r_type == MIPS_R_JMPADDR
+ && (((relocation
+ + addend
+ + (int_rel.r_extern ? 0 : s->vma))
+ & 0xf0000000)
+ != ((input_section->output_section->vma
+ + input_section->output_offset
+ + (int_rel.r_vaddr - input_section->vma)
+ + adjust)
+ & 0xf0000000)))
+ r = bfd_reloc_overflow;
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+
+ if (int_rel.r_extern)
+ name = h->root.root.string;
+ else
+ name = bfd_section_name (input_bfd, s);
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0,
+ input_bfd, input_section,
+ int_rel.r_vaddr - input_section->vma)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Read in the relocs for a section. */
+
+static boolean
+mips_read_relocs (abfd, sec)
+ bfd *abfd;
+ asection *sec;
+{
+ struct ecoff_section_tdata *section_tdata;
+
+ section_tdata = ecoff_section_data (abfd, sec);
+ if (section_tdata == (struct ecoff_section_tdata *) NULL)
+ {
+ sec->used_by_bfd =
+ (PTR) bfd_alloc_by_size_t (abfd, sizeof (struct ecoff_section_tdata));
+ if (sec->used_by_bfd == NULL)
+ return false;
+
+ section_tdata = ecoff_section_data (abfd, sec);
+ section_tdata->external_relocs = NULL;
+ section_tdata->contents = NULL;
+ section_tdata->offsets = NULL;
+ }
+
+ if (section_tdata->external_relocs == NULL)
+ {
+ bfd_size_type external_relocs_size;
+
+ external_relocs_size = (ecoff_backend (abfd)->external_reloc_size
+ * sec->reloc_count);
+
+ section_tdata->external_relocs =
+ (PTR) bfd_alloc (abfd, external_relocs_size);
+ if (section_tdata->external_relocs == NULL && external_relocs_size != 0)
+ return false;
+
+ if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
+ || (bfd_read (section_tdata->external_relocs, 1,
+ external_relocs_size, abfd)
+ != external_relocs_size))
+ return false;
+ }
+
+ return true;
+}
+
+/* Relax a section when linking a MIPS ECOFF file. This is used for
+ embedded PIC code, which always uses PC relative branches which
+ only have an 18 bit range on MIPS. If a branch is not in range, we
+ generate a long instruction sequence to compensate. Each time we
+ find a branch to expand, we have to check all the others again to
+ make sure they are still in range. This is slow, but it only has
+ to be done when -relax is passed to the linker.
+
+ This routine figures out which branches need to expand; the actual
+ expansion is done in mips_relocate_section when the section
+ contents are relocated. The information is stored in the offsets
+ field of the ecoff_section_tdata structure. An offset of 1 means
+ that the branch must be expanded into a multi-instruction PC
+ relative branch (such an offset will only occur for a PC relative
+ branch to an external symbol). Any other offset must be a multiple
+ of four, and is the amount to change the branch by (such an offset
+ will only occur for a PC relative branch within the same section).
+
+ We do not modify the section relocs or contents themselves so that
+ if memory usage becomes an issue we can discard them and read them
+ again. The only information we must save in memory between this
+ routine and the mips_relocate_section routine is the table of
+ offsets. */
+
+static boolean
+mips_relax_section (abfd, sec, info, again)
+ bfd *abfd;
+ asection *sec;
+ struct bfd_link_info *info;
+ boolean *again;
+{
+ struct ecoff_section_tdata *section_tdata;
+ bfd_byte *contents = NULL;
+ long *offsets;
+ struct external_reloc *ext_rel;
+ struct external_reloc *ext_rel_end;
+ unsigned int i;
+
+ /* Assume we are not going to need another pass. */
+ *again = false;
+
+ /* If we are not generating an ECOFF file, this is much too
+ confusing to deal with. */
+ if (info->hash->creator->flavour != bfd_get_flavour (abfd))
+ return true;
+
+ /* If there are no relocs, there is nothing to do. */
+ if (sec->reloc_count == 0)
+ return true;
+
+ /* We are only interested in PC relative relocs, and why would there
+ ever be one from anything but the .text section? */
+ if (strcmp (bfd_get_section_name (abfd, sec), ".text") != 0)
+ return true;
+
+ /* Read in the relocs, if we haven't already got them. */
+ section_tdata = ecoff_section_data (abfd, sec);
+ if (section_tdata == (struct ecoff_section_tdata *) NULL
+ || section_tdata->external_relocs == NULL)
+ {
+ if (! mips_read_relocs (abfd, sec))
+ goto error_return;
+ section_tdata = ecoff_section_data (abfd, sec);
+ }
+
+ if (sec->_cooked_size == 0)
+ {
+ /* We must initialize _cooked_size only the first time we are
+ called. */
+ sec->_cooked_size = sec->_raw_size;
+ }
+
+ contents = section_tdata->contents;
+ offsets = section_tdata->offsets;
+
+ /* Look for any external PC relative relocs. Internal PC relative
+ relocs are already correct in the object file, so they certainly
+ can not overflow. */
+ ext_rel = (struct external_reloc *) section_tdata->external_relocs;
+ ext_rel_end = ext_rel + sec->reloc_count;
+ for (i = 0; ext_rel < ext_rel_end; ext_rel++, i++)
+ {
+ struct internal_reloc int_rel;
+ struct ecoff_link_hash_entry *h;
+ asection *hsec;
+ bfd_signed_vma relocation;
+ struct external_reloc *adj_ext_rel;
+ unsigned int adj_i;
+ unsigned long ext_count;
+ struct ecoff_link_hash_entry **adj_h_ptr;
+ struct ecoff_link_hash_entry **adj_h_ptr_end;
+ struct ecoff_value_adjust *adjust;
+
+ /* If we have already expanded this reloc, we certainly don't
+ need to do it again. */
+ if (offsets != (long *) NULL && offsets[i] == 1)
+ continue;
+
+ /* Quickly check that this reloc is external PCREL16. */
+ if (bfd_header_big_endian (abfd))
+ {
+ if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_BIG) == 0
+ || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_BIG)
+ >> RELOC_BITS3_TYPE_SH_BIG)
+ != MIPS_R_PCREL16))
+ continue;
+ }
+ else
+ {
+ if ((ext_rel->r_bits[3] & RELOC_BITS3_EXTERN_LITTLE) == 0
+ || (((ext_rel->r_bits[3] & RELOC_BITS3_TYPE_LITTLE)
+ >> RELOC_BITS3_TYPE_SH_LITTLE)
+ != MIPS_R_PCREL16))
+ continue;
+ }
+
+ mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
+
+ h = ecoff_data (abfd)->sym_hashes[int_rel.r_symndx];
+ if (h == (struct ecoff_link_hash_entry *) NULL)
+ abort ();
+
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ {
+ /* Just ignore undefined symbols. These will presumably
+ generate an error later in the link. */
+ continue;
+ }
+
+ /* Get the value of the symbol. */
+ hsec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + hsec->output_section->vma
+ + hsec->output_offset);
+
+ /* Subtract out the current address. */
+ relocation -= (sec->output_section->vma
+ + sec->output_offset
+ + (int_rel.r_vaddr - sec->vma));
+
+ /* The addend is stored in the object file. In the normal case
+ of ``bal symbol'', the addend will be -4. It will only be
+ different in the case of ``bal symbol+constant''. To avoid
+ always reading in the section contents, we don't check the
+ addend in the object file (we could easily check the contents
+ if we happen to have already read them in, but I fear that
+ this could be confusing). This means we will screw up if
+ there is a branch to a symbol that is in range, but added to
+ a constant which puts it out of range; in such a case the
+ link will fail with a reloc overflow error. Since the
+ compiler will never generate such code, it should be easy
+ enough to work around it by changing the assembly code in the
+ source file. */
+ relocation -= 4;
+
+ /* Now RELOCATION is the number we want to put in the object
+ file. See whether it fits. */
+ if (relocation >= -0x20000 && relocation < 0x20000)
+ continue;
+
+ /* Now that we know this reloc needs work, which will rarely
+ happen, go ahead and grab the section contents. */
+ if (contents == (bfd_byte *) NULL)
+ {
+ if (info->keep_memory)
+ contents = (bfd_byte *) bfd_alloc (abfd, sec->_raw_size);
+ else
+ contents = (bfd_byte *) bfd_malloc ((size_t) sec->_raw_size);
+ if (contents == (bfd_byte *) NULL)
+ goto error_return;
+ if (! bfd_get_section_contents (abfd, sec, (PTR) contents,
+ (file_ptr) 0, sec->_raw_size))
+ goto error_return;
+ if (info->keep_memory)
+ section_tdata->contents = contents;
+ }
+
+ /* We only support changing the bal instruction. It would be
+ possible to handle other PC relative branches, but some of
+ them (the conditional branches) would require a different
+ length instruction sequence which would complicate both this
+ routine and mips_relax_pcrel16. It could be written if
+ somebody felt it were important. Ignoring this reloc will
+ presumably cause a reloc overflow error later on. */
+ if (bfd_get_32 (abfd, contents + int_rel.r_vaddr - sec->vma)
+ != 0x0411ffff) /* bgezal $0,. == bal . */
+ continue;
+
+ /* Bother. We need to expand this reloc, and we will need to
+ make another relaxation pass since this change may put other
+ relocs out of range. We need to examine the local branches
+ and we need to allocate memory to hold the offsets we must
+ add to them. We also need to adjust the values of all
+ symbols in the object file following this location. */
+
+ sec->_cooked_size += PCREL16_EXPANSION_ADJUSTMENT;
+ *again = true;
+
+ if (offsets == (long *) NULL)
+ {
+ size_t size;
+
+ size = sec->reloc_count * sizeof (long);
+ offsets = (long *) bfd_alloc_by_size_t (abfd, size);
+ if (offsets == (long *) NULL)
+ goto error_return;
+ memset (offsets, 0, size);
+ section_tdata->offsets = offsets;
+ }
+
+ offsets[i] = 1;
+
+ /* Now look for all PC relative references that cross this reloc
+ and adjust their offsets. */
+ adj_ext_rel = (struct external_reloc *) section_tdata->external_relocs;
+ for (adj_i = 0; adj_ext_rel < ext_rel_end; adj_ext_rel++, adj_i++)
+ {
+ struct internal_reloc adj_int_rel;
+ bfd_vma start, stop;
+ int change;
+
+ mips_ecoff_swap_reloc_in (abfd, (PTR) adj_ext_rel, &adj_int_rel);
+
+ if (adj_int_rel.r_type == MIPS_R_PCREL16)
+ {
+ unsigned long insn;
+
+ /* We only care about local references. External ones
+ will be relocated correctly anyhow. */
+ if (adj_int_rel.r_extern)
+ continue;
+
+ /* We are only interested in a PC relative reloc within
+ this section. FIXME: Cross section PC relative
+ relocs may not be handled correctly; does anybody
+ care? */
+ if (adj_int_rel.r_symndx != RELOC_SECTION_TEXT)
+ continue;
+
+ start = adj_int_rel.r_vaddr;
+
+ insn = bfd_get_32 (abfd,
+ contents + adj_int_rel.r_vaddr - sec->vma);
+
+ stop = (insn & 0xffff) << 2;
+ if ((stop & 0x20000) != 0)
+ stop -= 0x40000;
+ stop += adj_int_rel.r_vaddr + 4;
+ }
+ else if (adj_int_rel.r_type == MIPS_R_RELHI)
+ {
+ struct internal_reloc rello;
+ long addhi, addlo;
+
+ /* The next reloc must be MIPS_R_RELLO, and we handle
+ them together. */
+ BFD_ASSERT (adj_ext_rel + 1 < ext_rel_end);
+
+ mips_ecoff_swap_reloc_in (abfd, (PTR) (adj_ext_rel + 1), &rello);
+
+ BFD_ASSERT (rello.r_type == MIPS_R_RELLO);
+
+ addhi = bfd_get_32 (abfd,
+ contents + adj_int_rel.r_vaddr - sec->vma);
+ addhi &= 0xffff;
+ if (addhi & 0x8000)
+ addhi -= 0x10000;
+ addhi <<= 16;
+
+ addlo = bfd_get_32 (abfd, contents + rello.r_vaddr - sec->vma);
+ addlo &= 0xffff;
+ if (addlo & 0x8000)
+ addlo -= 0x10000;
+
+ if (adj_int_rel.r_extern)
+ {
+ /* The value we want here is
+ sym - RELLOaddr + addend
+ which we can express as
+ sym - (RELLOaddr - addend)
+ Therefore if we are expanding the area between
+ RELLOaddr and RELLOaddr - addend we must adjust
+ the addend. This is admittedly ambiguous, since
+ we might mean (sym + addend) - RELLOaddr, but in
+ practice we don't, and there is no way to handle
+ that case correctly since at this point we have
+ no idea whether any reloc is being expanded
+ between sym and sym + addend. */
+ start = rello.r_vaddr - (addhi + addlo);
+ stop = rello.r_vaddr;
+ }
+ else
+ {
+ /* An internal RELHI/RELLO pair represents the
+ difference between two addresses, $LC0 - foo.
+ The symndx value is actually the difference
+ between the reloc address and $LC0. This lets us
+ compute $LC0, and, by considering the addend,
+ foo. If the reloc we are expanding falls between
+ those two relocs, we must adjust the addend. At
+ this point, the symndx value is actually in the
+ r_offset field, where it was put by
+ mips_ecoff_swap_reloc_in. */
+ start = rello.r_vaddr - adj_int_rel.r_offset;
+ stop = start + addhi + addlo;
+ }
+ }
+ else if (adj_int_rel.r_type == MIPS_R_SWITCH)
+ {
+ /* A MIPS_R_SWITCH reloc represents a word of the form
+ .word $L3-$LS12
+ The value in the object file is correct, assuming the
+ original value of $L3. The symndx value is actually
+ the difference between the reloc address and $LS12.
+ This lets us compute the original value of $LS12 as
+ vaddr - symndx
+ and the original value of $L3 as
+ vaddr - symndx + addend
+ where addend is the value from the object file. At
+ this point, the symndx value is actually found in the
+ r_offset field, since it was moved by
+ mips_ecoff_swap_reloc_in. */
+ start = adj_int_rel.r_vaddr - adj_int_rel.r_offset;
+ stop = start + bfd_get_32 (abfd,
+ (contents
+ + adj_int_rel.r_vaddr
+ - sec->vma));
+ }
+ else
+ continue;
+
+ /* If the range expressed by this reloc, which is the
+ distance between START and STOP crosses the reloc we are
+ expanding, we must adjust the offset. The sign of the
+ adjustment depends upon the direction in which the range
+ crosses the reloc being expanded. */
+ if (start <= int_rel.r_vaddr && stop > int_rel.r_vaddr)
+ change = PCREL16_EXPANSION_ADJUSTMENT;
+ else if (start > int_rel.r_vaddr && stop <= int_rel.r_vaddr)
+ change = - PCREL16_EXPANSION_ADJUSTMENT;
+ else
+ change = 0;
+
+ offsets[adj_i] += change;
+
+ if (adj_int_rel.r_type == MIPS_R_RELHI)
+ {
+ adj_ext_rel++;
+ adj_i++;
+ offsets[adj_i] += change;
+ }
+ }
+
+ /* Find all symbols in this section defined by this object file
+ and adjust their values. Note that we decide whether to
+ adjust the value based on the value stored in the ECOFF EXTR
+ structure, because the value stored in the hash table may
+ have been changed by an earlier expanded reloc and thus may
+ no longer correctly indicate whether the symbol is before or
+ after the expanded reloc. */
+ ext_count = ecoff_data (abfd)->debug_info.symbolic_header.iextMax;
+ adj_h_ptr = ecoff_data (abfd)->sym_hashes;
+ adj_h_ptr_end = adj_h_ptr + ext_count;
+ for (; adj_h_ptr < adj_h_ptr_end; adj_h_ptr++)
+ {
+ struct ecoff_link_hash_entry *adj_h;
+
+ adj_h = *adj_h_ptr;
+ if (adj_h != (struct ecoff_link_hash_entry *) NULL
+ && (adj_h->root.type == bfd_link_hash_defined
+ || adj_h->root.type == bfd_link_hash_defweak)
+ && adj_h->root.u.def.section == sec
+ && adj_h->esym.asym.value > int_rel.r_vaddr)
+ adj_h->root.u.def.value += PCREL16_EXPANSION_ADJUSTMENT;
+ }
+
+ /* Add an entry to the symbol value adjust list. This is used
+ by bfd_ecoff_debug_accumulate to adjust the values of
+ internal symbols and FDR's. */
+ adjust = ((struct ecoff_value_adjust *)
+ bfd_alloc (abfd, sizeof (struct ecoff_value_adjust)));
+ if (adjust == (struct ecoff_value_adjust *) NULL)
+ goto error_return;
+
+ adjust->start = int_rel.r_vaddr;
+ adjust->end = sec->vma + sec->_raw_size;
+ adjust->adjust = PCREL16_EXPANSION_ADJUSTMENT;
+
+ adjust->next = ecoff_data (abfd)->debug_info.adjust;
+ ecoff_data (abfd)->debug_info.adjust = adjust;
+ }
+
+ if (contents != (bfd_byte *) NULL && ! info->keep_memory)
+ free (contents);
+
+ return true;
+
+ error_return:
+ if (contents != (bfd_byte *) NULL && ! info->keep_memory)
+ free (contents);
+ return false;
+}
+
+/* This routine is called from mips_relocate_section when a PC
+ relative reloc must be expanded into the five instruction sequence.
+ It handles all the details of the expansion, including resolving
+ the reloc. */
+
+static boolean
+mips_relax_pcrel16 (info, input_bfd, input_section, h, location, address)
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ struct ecoff_link_hash_entry *h;
+ bfd_byte *location;
+ bfd_vma address;
+{
+ bfd_vma relocation;
+
+ /* 0x0411ffff is bgezal $0,. == bal . */
+ BFD_ASSERT (bfd_get_32 (input_bfd, location) == 0x0411ffff);
+
+ /* We need to compute the distance between the symbol and the
+ current address plus eight. */
+ relocation = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ relocation -= address + 8;
+
+ /* If the lower half is negative, increment the upper 16 half. */
+ if ((relocation & 0x8000) != 0)
+ relocation += 0x10000;
+
+ bfd_put_32 (input_bfd, 0x04110001, location); /* bal .+8 */
+ bfd_put_32 (input_bfd,
+ 0x3c010000 | ((relocation >> 16) & 0xffff), /* lui $at,XX */
+ location + 4);
+ bfd_put_32 (input_bfd,
+ 0x24210000 | (relocation & 0xffff), /* addiu $at,$at,XX */
+ location + 8);
+ bfd_put_32 (input_bfd, 0x003f0821, location + 12); /* addu $at,$at,$ra */
+ bfd_put_32 (input_bfd, 0x0020f809, location + 16); /* jalr $at */
+
+ return true;
+}
+
+/* Given a .sdata section and a .rel.sdata in-memory section, store
+ relocation information into the .rel.sdata section which can be
+ used at runtime to relocate the section. This is called by the
+ linker when the --embedded-relocs switch is used. This is called
+ after the add_symbols entry point has been called for all the
+ objects, and before the final_link entry point is called. This
+ function presumes that the object was compiled using
+ -membedded-pic. */
+
+boolean
+bfd_mips_ecoff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *datasec;
+ asection *relsec;
+ char **errmsg;
+{
+ struct ecoff_link_hash_entry **sym_hashes;
+ struct ecoff_section_tdata *section_tdata;
+ struct external_reloc *ext_rel;
+ struct external_reloc *ext_rel_end;
+ bfd_byte *p;
+
+ BFD_ASSERT (! info->relocateable);
+
+ *errmsg = NULL;
+
+ if (datasec->reloc_count == 0)
+ return true;
+
+ sym_hashes = ecoff_data (abfd)->sym_hashes;
+
+ if (! mips_read_relocs (abfd, datasec))
+ return false;
+
+ relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 4);
+ if (relsec->contents == NULL)
+ return false;
+
+ p = relsec->contents;
+
+ section_tdata = ecoff_section_data (abfd, datasec);
+ ext_rel = (struct external_reloc *) section_tdata->external_relocs;
+ ext_rel_end = ext_rel + datasec->reloc_count;
+ for (; ext_rel < ext_rel_end; ext_rel++, p += 4)
+ {
+ struct internal_reloc int_rel;
+ boolean text_relative;
+
+ mips_ecoff_swap_reloc_in (abfd, (PTR) ext_rel, &int_rel);
+
+ /* We are going to write a four byte word into the runtime reloc
+ section. The word will be the address in the data section
+ which must be relocated. This must be on a word boundary,
+ which means the lower two bits must be zero. We use the
+ least significant bit to indicate how the value in the data
+ section must be relocated. A 0 means that the value is
+ relative to the text section, while a 1 indicates that the
+ value is relative to the data section. Given that we are
+ assuming the code was compiled using -membedded-pic, there
+ should not be any other possibilities. */
+
+ /* We can only relocate REFWORD relocs at run time. */
+ if (int_rel.r_type != MIPS_R_REFWORD)
+ {
+ *errmsg = "unsupported reloc type";
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (int_rel.r_extern)
+ {
+ struct ecoff_link_hash_entry *h;
+
+ h = sym_hashes[int_rel.r_symndx];
+ /* If h is NULL, that means that there is a reloc against an
+ external symbol which we thought was just a debugging
+ symbol. This should not happen. */
+ if (h == (struct ecoff_link_hash_entry *) NULL)
+ abort ();
+ if ((h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->root.u.def.section->flags & SEC_CODE) != 0)
+ text_relative = true;
+ else
+ text_relative = false;
+ }
+ else
+ {
+ switch (int_rel.r_symndx)
+ {
+ case RELOC_SECTION_TEXT:
+ text_relative = true;
+ break;
+ case RELOC_SECTION_SDATA:
+ case RELOC_SECTION_SBSS:
+ case RELOC_SECTION_LIT8:
+ text_relative = false;
+ break;
+ default:
+ /* No other sections should appear in -membedded-pic
+ code. */
+ *errmsg = "reloc against unsupported section";
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ }
+
+ if ((int_rel.r_offset & 3) != 0)
+ {
+ *errmsg = "reloc not properly aligned";
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ bfd_put_32 (abfd,
+ (int_rel.r_vaddr - datasec->vma + datasec->output_offset
+ + (text_relative ? 0 : 1)),
+ p);
+ }
+
+ return true;
+}
+
+/* This is the ECOFF backend structure. The backend field of the
+ target vector points to this. */
+
+static const struct ecoff_backend_data mips_ecoff_backend_data =
+{
+ /* COFF backend structure. */
+ {
+ (void (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR))) bfd_void, /* aux_in */
+ (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_in */
+ (void (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_in */
+ (unsigned (*) PARAMS ((bfd *,PTR,int,int,int,int,PTR)))bfd_void,/*aux_out*/
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* sym_out */
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* lineno_out */
+ (unsigned (*) PARAMS ((bfd *,PTR,PTR))) bfd_void, /* reloc_out */
+ mips_ecoff_swap_filehdr_out, mips_ecoff_swap_aouthdr_out,
+ mips_ecoff_swap_scnhdr_out,
+ FILHSZ, AOUTSZ, SCNHSZ, 0, 0, 0, 0, true,
+ mips_ecoff_swap_filehdr_in, mips_ecoff_swap_aouthdr_in,
+ mips_ecoff_swap_scnhdr_in, NULL,
+ mips_ecoff_bad_format_hook, _bfd_ecoff_set_arch_mach_hook,
+ _bfd_ecoff_mkobject_hook, _bfd_ecoff_styp_to_sec_flags,
+ _bfd_ecoff_set_alignment_hook, _bfd_ecoff_slurp_symbol_table,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+ },
+ /* Supported architecture. */
+ bfd_arch_mips,
+ /* Initial portion of armap string. */
+ "__________",
+ /* The page boundary used to align sections in a demand-paged
+ executable file. E.g., 0x1000. */
+ 0x1000,
+ /* 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. */
+ false,
+ /* Bitsize of constructor entries. */
+ 32,
+ /* Reloc to use for constructor entries. */
+ &mips_howto_table[MIPS_R_REFWORD],
+ {
+ /* Symbol table magic number. */
+ magicSym,
+ /* Alignment of debugging information. E.g., 4. */
+ 4,
+ /* Sizes of external symbolic information. */
+ sizeof (struct hdr_ext),
+ sizeof (struct dnr_ext),
+ sizeof (struct pdr_ext),
+ sizeof (struct sym_ext),
+ sizeof (struct opt_ext),
+ sizeof (struct fdr_ext),
+ sizeof (struct rfd_ext),
+ sizeof (struct ext_ext),
+ /* Functions to swap in external symbolic data. */
+ ecoff_swap_hdr_in,
+ ecoff_swap_dnr_in,
+ ecoff_swap_pdr_in,
+ ecoff_swap_sym_in,
+ ecoff_swap_opt_in,
+ ecoff_swap_fdr_in,
+ ecoff_swap_rfd_in,
+ ecoff_swap_ext_in,
+ _bfd_ecoff_swap_tir_in,
+ _bfd_ecoff_swap_rndx_in,
+ /* Functions to swap out external symbolic data. */
+ ecoff_swap_hdr_out,
+ ecoff_swap_dnr_out,
+ ecoff_swap_pdr_out,
+ ecoff_swap_sym_out,
+ ecoff_swap_opt_out,
+ ecoff_swap_fdr_out,
+ ecoff_swap_rfd_out,
+ ecoff_swap_ext_out,
+ _bfd_ecoff_swap_tir_out,
+ _bfd_ecoff_swap_rndx_out,
+ /* Function to read in symbolic data. */
+ _bfd_ecoff_slurp_symbolic_info
+ },
+ /* External reloc size. */
+ RELSZ,
+ /* Reloc swapping functions. */
+ mips_ecoff_swap_reloc_in,
+ mips_ecoff_swap_reloc_out,
+ /* Backend reloc tweaking. */
+ mips_adjust_reloc_in,
+ mips_adjust_reloc_out,
+ /* Relocate section contents while linking. */
+ mips_relocate_section,
+ /* Do final adjustments to filehdr and aouthdr. */
+ NULL,
+ /* Read an element from an archive at a given file position. */
+ _bfd_get_elt_at_filepos
+};
+
+/* Looking up a reloc type is MIPS specific. */
+#define _bfd_ecoff_bfd_reloc_type_lookup mips_bfd_reloc_type_lookup
+
+/* Getting relocated section contents is generic. */
+#define _bfd_ecoff_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+
+/* Handling file windows is generic. */
+#define _bfd_ecoff_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+/* Relaxing sections is MIPS specific. */
+#define _bfd_ecoff_bfd_relax_section mips_relax_section
+
+const bfd_target ecoff_little_vec =
+{
+ "ecoff-littlemips", /* name */
+ bfd_target_ecoff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ _bfd_ecoff_archive_p, _bfd_dummy_target},
+ {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
+ BFD_JUMP_TABLE_COPY (_bfd_ecoff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
+ BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
+ BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
+ BFD_JUMP_TABLE_LINK (_bfd_ecoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) &mips_ecoff_backend_data
+};
+
+const bfd_target ecoff_big_vec =
+{
+ "ecoff-bigmips", /* name */
+ bfd_target_ecoff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ _bfd_ecoff_archive_p, _bfd_dummy_target},
+ {bfd_false, _bfd_ecoff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, _bfd_ecoff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_ecoff),
+ BFD_JUMP_TABLE_COPY (_bfd_ecoff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_ecoff),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_ecoff),
+ BFD_JUMP_TABLE_RELOCS (_bfd_ecoff),
+ BFD_JUMP_TABLE_WRITE (_bfd_ecoff),
+ BFD_JUMP_TABLE_LINK (_bfd_ecoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) &mips_ecoff_backend_data
+};
diff --git a/contrib/gdb/bfd/coff-pmac.c b/contrib/gdb/bfd/coff-pmac.c
new file mode 100644
index 0000000..f3332d9
--- /dev/null
+++ b/contrib/gdb/bfd/coff-pmac.c
@@ -0,0 +1,27 @@
+/* BFD back-end for Apple et al PowerPC Mac "XCOFF" files.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_SYM pmac_xcoff_vec
+#define TARGET_NAME "xcoff-powermac"
+
+/* Tweak coffcode.h based on this being a PowerMac instead of RS/6000. */
+
+#define POWERMAC
+
+#include "coff-rs6000.c"
diff --git a/contrib/gdb/bfd/coff-ppc.c b/contrib/gdb/bfd/coff-ppc.c
new file mode 100644
index 0000000..4caf3d8
--- /dev/null
+++ b/contrib/gdb/bfd/coff-ppc.c
@@ -0,0 +1,3255 @@
+/* BFD back-end for PowerPC Microsoft Portable Executable files.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+ Original version pieced together by Kim Knuttila (krk@cygnus.com)
+
+ There is nothing new under the sun. This file draws a lot on other
+ coff files, in particular, those for the rs/6000, alpha, mips, and
+ intel backends, and the PE work for the arm.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+/* Current State:
+ - objdump works
+ - relocs generated by gas
+ - ld will link files, but they do not run.
+ - dlltool will not produce correct output in some .reloc cases, and will
+ not produce the right glue code for dll function calls.
+*/
+
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#include "libbfd.h"
+#include "obstack.h"
+
+#include "coff/powerpc.h"
+#include "coff/internal.h"
+
+#include "coff/pe.h"
+
+#ifdef BADMAG
+#undef BADMAG
+#endif
+
+#define BADMAG(x) PPCBADMAG(x)
+
+#include "libcoff.h"
+
+/* The toc is a set of bfd_vma fields. We use the fact that valid */
+/* addresses are even (i.e. the bit representing "1" is off) to allow */
+/* us to encode a little extra information in the field */
+/* - Unallocated addresses are intialized to 1. */
+/* - Allocated addresses are even numbers. */
+/* The first time we actually write a reference to the toc in the bfd, */
+/* we want to record that fact in a fixup file (if it is asked for), so */
+/* we keep track of whether or not an address has been written by marking */
+/* the low order bit with a "1" upon writing */
+
+#define SET_UNALLOCATED(x) ((x) = 1)
+#define IS_UNALLOCATED(x) ((x) == 1)
+
+#define IS_WRITTEN(x) ((x) & 1)
+#define MARK_AS_WRITTEN(x) ((x) |= 1)
+#define MAKE_ADDR_AGAIN(x) ((x) &= ~1)
+
+/* In order not to add an int to every hash table item for every coff
+ linker, we define our own hash table, derived from the coff one */
+
+/* PE linker hash table entries. */
+
+struct ppc_coff_link_hash_entry
+{
+ struct coff_link_hash_entry root; /* First entry, as required */
+
+ /* As we wonder around the relocs, we'll keep the assigned toc_offset
+ here */
+ bfd_vma toc_offset; /* Our addition, as required */
+ int symbol_is_glue;
+ unsigned long int glue_insn;
+ char eye_catcher[8];
+};
+
+/* Need a 7 char string for an eye catcher */
+#define EYE "krkjunk"
+
+#define CHECK_EYE(addr) \
+ if (strcmp(addr, EYE) != 0) \
+ { \
+ fprintf(stderr,\
+ "File %s, line %d, Hash check failure, bad eye %8s\n", \
+ __FILE__, __LINE__, addr); \
+ abort(); \
+ }
+
+/* PE linker hash table. */
+
+struct ppc_coff_link_hash_table
+{
+ struct coff_link_hash_table root; /* First entry, as required */
+};
+
+static struct bfd_hash_entry *ppc_coff_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+
+/* Routine to create an entry in the link hash table. */
+
+static struct bfd_hash_entry *
+ppc_coff_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct ppc_coff_link_hash_entry *ret =
+ (struct ppc_coff_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct ppc_coff_link_hash_entry *) NULL)
+ ret = (struct ppc_coff_link_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct ppc_coff_link_hash_entry));
+
+ if (ret == (struct ppc_coff_link_hash_entry *) NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct ppc_coff_link_hash_entry *)
+ _bfd_coff_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ SET_UNALLOCATED(ret->toc_offset);
+ ret->symbol_is_glue = 0;
+ ret->glue_insn = 0;
+ strcpy(ret->eye_catcher, EYE);
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize a PE linker hash table. */
+
+static boolean
+ppc_coff_link_hash_table_init (table, abfd, newfunc)
+ struct ppc_coff_link_hash_table *table;
+ bfd *abfd;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+{
+ return _bfd_coff_link_hash_table_init (&table->root, abfd, newfunc);
+}
+
+/* Create a PE linker hash table. */
+
+static struct bfd_link_hash_table *
+ppc_coff_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct ppc_coff_link_hash_table *ret;
+
+ ret = ((struct ppc_coff_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct ppc_coff_link_hash_table)));
+ if (ret == NULL)
+ return NULL;
+ if (! ppc_coff_link_hash_table_init (ret, abfd,
+ ppc_coff_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+ return &ret->root.root;
+}
+
+/* Now, tailor coffcode.h to use our hash stuff */
+
+#define coff_bfd_link_hash_table_create ppc_coff_link_hash_table_create
+
+
+/* The nt loader points the toc register to &toc + 32768, in order to */
+/* use the complete range of a 16-bit displacement (I guess). We have */
+/* to adjust for this when we fix up loads displaced off the toc reg. */
+#define TOC_LOAD_ADJUSTMENT (-32768)
+#define TOC_SECTION_NAME ".private.toc"
+
+/* The main body of code is in coffcode.h. */
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+/* In case we're on a 32-bit machine, construct a 64-bit "-1" value
+ from smaller values. Start with zero, widen, *then* decrement. */
+#define MINUS_ONE (((bfd_vma)0) - 1)
+
+/* these should definitely go in a header file somewhere... */
+
+/* NOP */
+#define IMAGE_REL_PPC_ABSOLUTE 0x0000
+
+/* 64-bit address */
+#define IMAGE_REL_PPC_ADDR64 0x0001
+
+/* 32-bit address */
+#define IMAGE_REL_PPC_ADDR32 0x0002
+
+/* 26-bit address, shifted left 2 (branch absolute) */
+#define IMAGE_REL_PPC_ADDR24 0x0003
+
+/* 16-bit address */
+#define IMAGE_REL_PPC_ADDR16 0x0004
+
+/* 16-bit address, shifted left 2 (load doubleword) */
+#define IMAGE_REL_PPC_ADDR14 0x0005
+
+/* 26-bit PC-relative offset, shifted left 2 (branch relative) */
+#define IMAGE_REL_PPC_REL24 0x0006
+
+/* 16-bit PC-relative offset, shifted left 2 (br cond relative) */
+#define IMAGE_REL_PPC_REL14 0x0007
+
+/* 16-bit offset from TOC base */
+#define IMAGE_REL_PPC_TOCREL16 0x0008
+
+/* 16-bit offset from TOC base, shifted left 2 (load doubleword) */
+#define IMAGE_REL_PPC_TOCREL14 0x0009
+
+/* 32-bit addr w/o image base */
+#define IMAGE_REL_PPC_ADDR32NB 0x000A
+
+/* va of containing section (as in an image sectionhdr) */
+#define IMAGE_REL_PPC_SECREL 0x000B
+
+/* sectionheader number */
+#define IMAGE_REL_PPC_SECTION 0x000C
+
+/* substitute TOC restore instruction iff symbol is glue code */
+#define IMAGE_REL_PPC_IFGLUE 0x000D
+
+/* symbol is glue code; virtual address is TOC restore instruction */
+#define IMAGE_REL_PPC_IMGLUE 0x000E
+
+/* va of containing section (limited to 16 bits) */
+#define IMAGE_REL_PPC_SECREL16 0x000F
+
+/* stuff to handle immediate data when the number of bits in the */
+/* data is greater than the number of bits in the immediate field */
+/* We need to do (usually) 32 bit arithmetic on 16 bit chunks */
+#define IMAGE_REL_PPC_REFHI 0x0010
+#define IMAGE_REL_PPC_REFLO 0x0011
+#define IMAGE_REL_PPC_PAIR 0x0012
+
+/* This is essentially the same as tocrel16, with TOCDEFN assumed */
+#define IMAGE_REL_PPC_TOCREL16_DEFN 0x0013
+
+/* Flag bits in IMAGE_RELOCATION.TYPE */
+
+/* subtract reloc value rather than adding it */
+#define IMAGE_REL_PPC_NEG 0x0100
+
+/* fix branch prediction bit to predict branch taken */
+#define IMAGE_REL_PPC_BRTAKEN 0x0200
+
+/* fix branch prediction bit to predict branch not taken */
+#define IMAGE_REL_PPC_BRNTAKEN 0x0400
+
+/* toc slot defined in file (or, data in toc) */
+#define IMAGE_REL_PPC_TOCDEFN 0x0800
+
+/* masks to isolate above values in IMAGE_RELOCATION.Type */
+#define IMAGE_REL_PPC_TYPEMASK 0x00FF
+#define IMAGE_REL_PPC_FLAGMASK 0x0F00
+
+#define EXTRACT_TYPE(x) ((x) & IMAGE_REL_PPC_TYPEMASK)
+#define EXTRACT_FLAGS(x) ((x) & IMAGE_REL_PPC_FLAGMASK)
+#define EXTRACT_JUNK(x) \
+ ((x) & ~(IMAGE_REL_PPC_TYPEMASK | IMAGE_REL_PPC_FLAGMASK))
+
+
+/* static helper functions to make relocation work */
+/* (Work In Progress) */
+
+static bfd_reloc_status_type ppc_refhi_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type ppc_reflo_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type ppc_pair_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+
+static bfd_reloc_status_type ppc_toc16_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_addr32nb_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_section_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_secrel_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+static bfd_reloc_status_type ppc_imglue_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+
+
+
+static boolean in_reloc_p PARAMS((bfd *abfd, reloc_howto_type *howto));
+
+
+/* FIXME: It'll take a while to get through all of these. I only need a few to
+ get us started, so those I'll make sure work. Those marked FIXME are either
+ completely unverified or have a specific unknown marked in the comment */
+
+/*---------------------------------------------------------------------------*/
+/* */
+/* Relocation entries for Windows/NT on PowerPC. */
+/* */
+/* From the document "" we find the following listed as used relocs: */
+/* */
+/* ABSOLUTE : The noop */
+/* ADDR[64|32|16] : fields that hold addresses in data fields or the */
+/* 16 bit displacement field on a load/store. */
+/* ADDR[24|14] : fields that hold addresses in branch and cond */
+/* branches. These represent [26|16] bit addresses. */
+/* The low order 2 bits are preserved. */
+/* REL[24|14] : branches relative to the Instruction Address */
+/* register. These represent [26|16] bit addresses, */
+/* as before. The instruction field will be zero, and */
+/* the address of the SYM will be inserted at link time. */
+/* TOCREL16 : 16 bit displacement field referring to a slot in */
+/* toc. */
+/* TOCREL14 : 16 bit displacement field, similar to REL14 or ADDR14. */
+/* ADDR32NB : 32 bit address relative to the virtual origin. */
+/* (On the alpha, this is always a linker generated thunk)*/
+/* (i.e. 32bit addr relative to the image base) */
+/* SECREL : The value is relative to the start of the section */
+/* containing the symbol. */
+/* SECTION : access to the header containing the item. Supports the */
+/* codeview debugger. */
+/* */
+/* In particular, note that the document does not indicate that the */
+/* relocations listed in the header file are used. */
+/* */
+/* */
+/* */
+/*---------------------------------------------------------------------------*/
+
+static reloc_howto_type ppc_coff_howto_table[] =
+{
+ /* IMAGE_REL_PPC_ABSOLUTE 0x0000 NOP */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ABSOLUTE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* dont complain_on_overflow */
+ 0, /* special_function */
+ "ABSOLUTE", /* name */
+ false, /* partial_inplace */
+ 0x00, /* src_mask */
+ 0x00, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR64 0x0001 64-bit address */
+ /* Unused: */
+ HOWTO(IMAGE_REL_PPC_ADDR64, /* type */
+ 0, /* rightshift */
+ 3, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR64", /* name */
+ true, /* partial_inplace */
+ MINUS_ONE, /* src_mask */
+ MINUS_ONE, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR32 0x0002 32-bit address */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_ADDR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR24 0x0003 26-bit address, shifted left 2 (branch absolute) */
+ /* the LI field is in bit 6 through bit 29 is 24 bits, + 2 for the shift */
+ /* Of course, That's the IBM approved bit numbering, which is not what */
+ /* anyone else uses.... The li field is in bit 2 thru 25 */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_ADDR24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR24", /* name */
+ true, /* partial_inplace */
+ 0x07fffffc, /* src_mask */
+ 0x07fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR16 0x0004 16-bit address */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_ADDR16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR14 0x0005 */
+ /* 16-bit address, shifted left 2 (load doubleword) */
+ /* FIXME: the mask is likely wrong, and the bit position may be as well */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ADDR14, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REL24 0x0006 */
+ /* 26-bit PC-relative offset, shifted left 2 (branch relative) */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_REL24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "REL24", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REL14 0x0007 */
+ /* 16-bit PC-relative offset, shifted left 2 (br cond relative) */
+ /* FIXME: the mask is likely wrong, and the bit position may be as well */
+ /* FIXME: how does it know how far to shift? */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ADDR14, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_TOCREL16 0x0008 */
+ /* 16-bit offset from TOC base */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_TOCREL16,/* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_toc16_reloc, /* special_function */
+ "TOCREL16", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_TOCREL14 0x0009 */
+ /* 16-bit offset from TOC base, shifted left 2 (load doubleword) */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_TOCREL14,/* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "TOCREL14", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_ADDR32NB 0x000A */
+ /* 32-bit addr w/ image base */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_ADDR32NB,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "ADDR32NB", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_SECREL 0x000B */
+ /* va of containing section (as in an image sectionhdr) */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_SECREL,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_secrel_reloc, /* special_function */
+ "SECREL", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_SECTION 0x000C */
+ /* sectionheader number */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_SECTION,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_section_reloc, /* special_function */
+ "SECTION", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_IFGLUE 0x000D */
+ /* substitute TOC restore instruction iff symbol is glue code */
+ /* Used: */
+ HOWTO (IMAGE_REL_PPC_IFGLUE,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "IFGLUE", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_IMGLUE 0x000E */
+ /* symbol is glue code; virtual address is TOC restore instruction */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_IMGLUE,/* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ ppc_imglue_reloc, /* special_function */
+ "IMGLUE", /* name */
+ false, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_SECREL16 0x000F */
+ /* va of containing section (limited to 16 bits) */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_SECREL16,/* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SECREL16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REFHI 0x0010 */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_REFHI, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_refhi_reloc, /* special_function */
+ "REFHI", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_REFLO 0x0011 */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_REFLO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_refhi_reloc, /* special_function */
+ "REFLO", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_PAIR 0x0012 */
+ /* Unused: */
+ HOWTO (IMAGE_REL_PPC_PAIR, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ ppc_pair_reloc, /* special_function */
+ "PAIR", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* IMAGE_REL_PPC_TOCREL16_DEFN 0x0013 */
+ /* 16-bit offset from TOC base, without causing a definition */
+ /* Used: */
+ HOWTO ( (IMAGE_REL_PPC_TOCREL16 | IMAGE_REL_PPC_TOCDEFN), /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "TOCREL16, TOCDEFN", /* name */
+ false, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+};
+
+
+
+
+/* Some really cheezy macros that can be turned on to test stderr :-) */
+
+#ifdef DEBUG_RELOC
+#define UN_IMPL(x) \
+{ \
+ static int i; \
+ if (i == 0) \
+ { \
+ i = 1; \
+ fprintf(stderr,"Unimplemented Relocation -- %s\n",x); \
+ } \
+}
+
+#define DUMP_RELOC(n,r) \
+{ \
+ fprintf(stderr,"%s sym %d, addr %d, addend %d\n", \
+ n, (*(r->sym_ptr_ptr))->name, \
+ r->address, r->addend); \
+}
+
+/* Given a reloc name, n, and a pointer to an internal_reloc,
+ dump out interesting information on the contents
+
+#define n_name _n._n_name
+#define n_zeroes _n._n_n._n_zeroes
+#define n_offset _n._n_n._n_offset
+
+*/
+
+#define DUMP_RELOC2(n,r) \
+{ \
+ fprintf(stderr,"%s sym %d, r_vaddr %d %s\n", \
+ n, r->r_symndx, r->r_vaddr,\
+ (((r->r_type) & IMAGE_REL_PPC_TOCDEFN) == 0) \
+ ?" ":" TOCDEFN" ); \
+}
+
+#else
+#define UN_IMPL(x)
+#define DUMP_RELOC(n,r)
+#define DUMP_RELOC2(n,r)
+#endif
+
+
+
+/* toc construction and management routines */
+extern bfd* bfd_of_toc_owner;
+extern long int global_toc_size;
+
+extern long int import_table_size;
+extern long int first_thunk_address;
+extern long int thunk_size;
+
+enum toc_type
+{
+ default_toc,
+ toc_32,
+ toc_64
+};
+
+enum ref_category
+{
+ priv,
+ pub,
+ data
+};
+
+struct list_ele
+{
+ struct list_ele *next;
+ bfd_vma addr;
+ enum ref_category cat;
+ int offset;
+ const char *name;
+};
+
+extern struct list_ele *head;
+extern struct list_ele *tail;
+
+static void
+record_toc(toc_section, our_toc_offset, cat, name)
+ asection *toc_section;
+ int our_toc_offset;
+ enum ref_category cat;
+ const char *name;
+{
+ /* add this entry to our toc addr-offset-name list */
+ struct list_ele *t;
+ t = bfd_malloc (sizeof (struct list_ele));
+ if (t == NULL)
+ abort ();
+ t->next = 0;
+ t->offset = our_toc_offset;
+ t->name = name;
+ t->cat = cat;
+ t->addr = toc_section->output_offset + our_toc_offset;
+
+ if (head == 0)
+ {
+ head = t;
+ tail = t;
+ }
+ else
+ {
+ tail->next = t;
+ tail = t;
+ }
+}
+
+/* record a toc offset against a symbol */
+static int
+ppc_record_toc_entry(abfd, info, sec, sym, toc_kind)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ int sym;
+ enum toc_type toc_kind;
+{
+ bfd_byte *t;
+ bfd_byte *old_contents;
+ asection *s;
+ int element_size;
+ int data;
+ int offset;
+ struct ppc_coff_link_hash_entry *h;
+ struct coff_symbol_struct *target;
+ int ret_val;
+ const char *name;
+
+ int *local_syms;
+
+ h = 0;
+
+ h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
+ if (h != 0)
+ {
+ CHECK_EYE(h->eye_catcher);
+ }
+
+ if (h == 0)
+ {
+ local_syms = obj_coff_local_toc_table(abfd);
+ if (local_syms == 0)
+ {
+ int i;
+ /* allocate a table */
+ local_syms =
+ (int *) bfd_zalloc (abfd,
+ obj_raw_syment_count(abfd) * sizeof(int));
+ if (local_syms == 0)
+ return false;
+ obj_coff_local_toc_table(abfd) = local_syms;
+ for (i = 0; i < obj_raw_syment_count(abfd); ++i)
+ {
+ SET_UNALLOCATED(local_syms[i]);
+ }
+ }
+
+ if (IS_UNALLOCATED(local_syms[sym]))
+ {
+ local_syms[sym] = global_toc_size;
+ ret_val = global_toc_size;
+ global_toc_size += 4;
+
+ /* The size must fit in a 16bit displacment */
+ if (global_toc_size >= 65535)
+ {
+ fprintf(stderr,
+ "Exceeded toc size of 65535\n");
+ abort();
+ }
+
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Setting toc_offset for local sym %d to %d\n",
+ sym, ret_val);
+#endif
+ }
+ else
+ {
+ ret_val = local_syms[sym];
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "toc_offset already set for local sym %d to %d\n",
+ sym, ret_val);
+#endif
+ }
+ }
+ else
+ {
+ name = h->root.root.root.string;
+
+ /* check to see if there's a toc slot allocated. If not, do it
+ here. It will be used in relocate_section */
+ if (IS_UNALLOCATED(h->toc_offset))
+ {
+ h->toc_offset = global_toc_size;
+ ret_val = global_toc_size;
+ global_toc_size += 4;
+
+ /* The size must fit in a 16bit displacment */
+ if (global_toc_size >= 65535)
+ {
+ fprintf(stderr,
+ "Exceeded toc size of 65535\n");
+ abort();
+ }
+
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Setting toc_offset for sym %d (%s) [h=%p] to %d\n",
+ sym, name, h, ret_val);
+#endif
+ }
+ else
+ {
+ ret_val = h->toc_offset;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "toc_offset already set for sym %d (%s) [h=%p] to %d\n",
+ sym, name, h, ret_val);
+#endif
+ }
+ }
+
+ return ret_val;
+}
+/* FIXME: record a toc offset against a data-in-toc symbol */
+/* Now, there is currenly some confusion on what this means. In some
+ compilers one sees the moral equivalent of:
+ .tocd
+ define some data
+ .text
+ refer to the data with a [tocv] qualifier
+ In general, one sees something to indicate that a tocd has been
+ seen, and that would trigger the allocation of data in toc. The IBM
+ docs seem to suggest that anything with the TOCDEFN qualifier should
+ never trigger storage allocation. However, in the kernel32.lib that
+ we've been using for our test bed, there are a couple of variables
+ referenced that fail that test.
+
+ So it can't work that way.
+*/
+static int
+ppc_record_data_in_toc_entry(abfd, info, sec, sym, toc_kind)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ int sym;
+ enum toc_type toc_kind;
+{
+ bfd_byte *t;
+ bfd_byte *old_contents;
+ asection *s;
+ int element_size;
+ int data;
+ int offset;
+ struct ppc_coff_link_hash_entry *h = 0;
+ struct coff_symbol_struct *target;
+ int ret_val;
+ const char *name;
+
+ int *local_syms;
+
+ h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
+
+ if (h == 0)
+ {
+ local_syms = obj_coff_local_toc_table(abfd);
+ if (local_syms == 0)
+ {
+ int i;
+ /* allocate a table */
+ local_syms =
+ (int *) bfd_zalloc (abfd,
+ obj_raw_syment_count(abfd) * sizeof(int));
+ if (local_syms == 0)
+ return false;
+ obj_coff_local_toc_table(abfd) = local_syms;
+ for (i = 0; i < obj_raw_syment_count(abfd); ++i)
+ {
+ SET_UNALLOCATED(local_syms[i]);
+ }
+ }
+
+ if (IS_UNALLOCATED(local_syms[sym]))
+ {
+ local_syms[sym] = global_toc_size;
+ ret_val = global_toc_size;
+ global_toc_size += 4;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Setting data_in_toc_offset for local sym %d to %d\n",
+ sym, ret_val);
+#endif
+ }
+ else
+ {
+ ret_val = local_syms[sym];
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "data_in_toc_offset already set for local sym %d to %d\n",
+ sym, ret_val);
+#endif
+ }
+ }
+ else
+ {
+ CHECK_EYE(h->eye_catcher);
+
+ name = h->root.root.root.string;
+
+ /* check to see if there's a toc slot allocated. If not, do it
+ here. It will be used in relocate_section */
+ if (IS_UNALLOCATED(h->toc_offset))
+ {
+#if 0
+ h->toc_offset = global_toc_size;
+#endif
+ ret_val = global_toc_size;
+ /* We're allocating a chunk of the toc, as opposed to a slot */
+ /* FIXME: alignment? */
+
+ global_toc_size += 4;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Setting data_in_toc_offset for sym %d (%s) [h=%p] to %d\n",
+ sym, name, h, ret_val);
+#endif
+ }
+ else
+ {
+ ret_val = h->toc_offset;
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "data_in_toc_offset already set for sym %d (%s) [h=%p] to %d\n",
+ sym, name, h, ret_val);
+#endif
+ }
+ }
+
+ return ret_val;
+}
+
+/* record a toc offset against a symbol */
+static void
+ppc_mark_symbol_as_glue(abfd, sym, rel)
+ bfd *abfd;
+ int sym;
+ struct internal_reloc *rel;
+{
+ struct ppc_coff_link_hash_entry *h;
+
+ h = (struct ppc_coff_link_hash_entry *) (obj_coff_sym_hashes (abfd)[sym]);
+
+ CHECK_EYE(h->eye_catcher);
+
+ h->symbol_is_glue = 1;
+ h->glue_insn = bfd_get_32 (abfd, (bfd_byte *) &rel->r_vaddr);
+
+ return;
+}
+
+
+/* Provided the symbol, returns the value reffed */
+static long get_symbol_value PARAMS ((asymbol *));
+
+static long
+get_symbol_value (symbol)
+ asymbol *symbol;
+{
+ long relocation = 0;
+
+ if (bfd_is_com_section (symbol->section))
+ {
+ relocation = 0;
+ }
+ else
+ {
+ relocation = symbol->value +
+ symbol->section->output_section->vma +
+ symbol->section->output_offset;
+ }
+
+ return(relocation);
+}
+
+/* Return true if this relocation should
+ appear in the output .reloc section. */
+
+static boolean in_reloc_p(abfd, howto)
+ bfd * abfd;
+ reloc_howto_type *howto;
+{
+ return
+ (! howto->pc_relative)
+ && (howto->type != IMAGE_REL_PPC_ADDR32NB)
+ && (howto->type != IMAGE_REL_PPC_TOCREL16)
+ && (howto->type != IMAGE_REL_PPC_IMGLUE)
+ && (howto->type != IMAGE_REL_PPC_IFGLUE)
+ && (howto->type != IMAGE_REL_PPC_SECREL)
+ && (howto->type != IMAGE_REL_PPC_SECTION)
+ && (howto->type != IMAGE_REL_PPC_SECREL16)
+ && (howto->type != IMAGE_REL_PPC_REFHI)
+ && (howto->type != IMAGE_REL_PPC_REFLO)
+ && (howto->type != IMAGE_REL_PPC_PAIR)
+ && (howto->type != IMAGE_REL_PPC_TOCREL16_DEFN) ;
+}
+
+/* this function is in charge of performing all the ppc PE relocations */
+/* Don't yet know if we want to do this this particular way ... (krk) */
+/* FIXME: (it is not yet enabled) */
+
+static bfd_reloc_status_type
+pe_ppc_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol_in;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* the consth relocation comes in two parts, we have to remember
+ the state between calls, in these variables */
+ static boolean part1_consth_active = false;
+ static unsigned long part1_consth_value;
+
+ unsigned long insn;
+ unsigned long sym_value;
+ unsigned long unsigned_value;
+ unsigned short r_type;
+ long signed_value;
+
+ unsigned long addr = reloc_entry->address ; /*+ input_section->vma*/
+ bfd_byte *hit_data =addr + (bfd_byte *)(data);
+
+ fprintf(stderr, "pe_ppc_reloc (%s)\n", TARGET_LITTLE_NAME);
+
+ r_type = reloc_entry->howto->type;
+
+ if (output_bfd)
+ {
+ /* Partial linking - do nothing */
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (symbol_in != NULL
+ && bfd_is_und_section (symbol_in->section))
+ {
+ /* Keep the state machine happy in case we're called again */
+ if (r_type == IMAGE_REL_PPC_REFHI)
+ {
+ part1_consth_active = true;
+ part1_consth_value = 0;
+ }
+ return(bfd_reloc_undefined);
+ }
+
+ if ((part1_consth_active) && (r_type != IMAGE_REL_PPC_PAIR))
+ {
+ part1_consth_active = false;
+ *error_message = (char *) "Missing PAIR";
+ return(bfd_reloc_dangerous);
+ }
+
+
+ sym_value = get_symbol_value(symbol_in);
+
+ return(bfd_reloc_ok);
+}
+
+/* The reloc processing routine for the optimized COFF linker. */
+
+static boolean
+coff_ppc_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, syms, sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+ boolean hihalf;
+ bfd_vma hihalf_val;
+ asection *toc_section = 0;
+ bfd_vma relocation;
+ reloc_howto_type *howto = 0;
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ "pe_ppc_relocate_section (%s) for %s in bfd %s\n",
+ TARGET_LITTLE_NAME,
+ input_section->name,
+ input_bfd->filename);
+
+#endif
+
+ /* If we are performing a relocateable link, we don't need to do a
+ thing. The caller will take care of adjusting the reloc
+ addresses and symbol indices. */
+ if (info->relocateable)
+ return true;
+
+ hihalf = false;
+ hihalf_val = 0;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct ppc_coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma val;
+
+ asection *sec;
+ bfd_reloc_status_type rstat;
+ bfd_byte *loc;
+
+ unsigned short r_type = EXTRACT_TYPE (rel->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
+ unsigned short junk = EXTRACT_JUNK (rel->r_type);
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ symndx = rel->r_symndx;
+ loc = contents + rel->r_vaddr - input_section->vma;
+
+ /* FIXME: check bounds on r_type */
+ howto = ppc_coff_howto_table + r_type;
+
+ if (symndx == -1)
+ {
+ h = NULL;
+ sym = NULL;
+ }
+ else
+ {
+ h = (struct ppc_coff_link_hash_entry *)
+ (obj_coff_sym_hashes (input_bfd)[symndx]);
+ if (h != 0)
+ {
+ CHECK_EYE(h->eye_catcher);
+ }
+
+ sym = syms + symndx;
+ }
+
+ sec = NULL;
+ val = 0;
+
+ /* FIXME: PAIR unsupported in the following code */
+ if (h == NULL)
+ {
+ if (symndx == -1)
+ sec = bfd_abs_section_ptr;
+ else
+ {
+ sec = sections[symndx];
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+ }
+ else
+ {
+ CHECK_EYE(h->eye_catcher);
+
+ if (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.root.u.def.section;
+ val = (h->root.root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else
+ {
+fprintf(stderr,
+ "missing %s\n",h->root.root.root.string);
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ rstat = bfd_reloc_ok;
+
+ /* Each case must do its own relocation, setting rstat appropriately */
+ switch (r_type)
+ {
+ default:
+ fprintf( stderr,
+ "ERROR: during reloc processing -- unsupported reloc %s\n",
+ howto->name);
+ bfd_set_error (bfd_error_bad_value);
+ abort();
+ return false;
+ case IMAGE_REL_PPC_TOCREL16:
+ {
+ bfd_vma our_toc_offset;
+ int fixit;
+
+ DUMP_RELOC2(howto->name, rel);
+
+ if (toc_section == 0)
+ {
+ toc_section = bfd_get_section_by_name (bfd_of_toc_owner,
+ TOC_SECTION_NAME);
+#ifdef TOC_DEBUG
+
+ fprintf(stderr,
+ "BFD of toc owner %p (%s), section addr of %s %p\n",
+ bfd_of_toc_owner, bfd_of_toc_owner->filename,
+ TOC_SECTION_NAME, toc_section);
+#endif
+
+ if ( toc_section == NULL )
+ {
+ fprintf(stderr, "No Toc section!\n");
+ abort();
+ }
+ }
+
+ /*
+ * Amazing bit tricks present. As we may have seen earlier, we
+ * use the 1 bit to tell us whether or not a toc offset has been
+ * allocated. Now that they've all been allocated, we will use
+ * the 1 bit to tell us if we've written this particular toc
+ * entry out.
+ */
+ fixit = false;
+ if (h == 0)
+ { /* it is a file local symbol */
+ int *local_toc_table;
+ const char *name;
+
+ sym = syms + symndx;
+ name = sym->_n._n_name;
+
+ local_toc_table = obj_coff_local_toc_table(input_bfd);
+ our_toc_offset = local_toc_table[symndx];
+
+ if (IS_WRITTEN(our_toc_offset))
+ {
+ /* if it has been written out, it is marked with the
+ 1 bit. Fix up our offset, but do not write it out
+ again.
+ */
+ MAKE_ADDR_AGAIN(our_toc_offset);
+#ifdef TOC_DEBUG
+
+ fprintf(stderr,
+ "Not writing out toc_offset of %d for %s\n",
+ our_toc_offset, name);
+#endif
+ }
+ else
+ {
+ /* write out the toc entry */
+ record_toc(toc_section, our_toc_offset, priv, strdup(name));
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Writing out toc_offset "
+ "toc_section (%p,%p)+%d val %d for %s\n",
+ toc_section,
+ toc_section->contents,
+ our_toc_offset,
+ val,
+ name);
+#endif
+
+ bfd_put_32(output_bfd,
+ val,
+ toc_section->contents + our_toc_offset);
+
+ MARK_AS_WRITTEN(local_toc_table[symndx]);
+ fixit = true;
+ }
+ }
+ else
+ {
+ const char *name = h->root.root.root.string;
+ our_toc_offset = h->toc_offset;
+
+ if ((r_flags & IMAGE_REL_PPC_TOCDEFN)
+ == IMAGE_REL_PPC_TOCDEFN )
+#if 0
+ /* This is wrong. If tocdefn is on, we must unconditionally
+ assume the following path */
+ && IS_UNALLOCATED(our_toc_offset))
+#endif
+ {
+ /* This is unbelievable cheese. Some knowledgable asm
+ hacker has decided to use r2 as a base for loading
+ a value. He/She does this by setting the tocdefn bit,
+ and not supplying a toc definition. The behaviour is
+ then to use the difference between the value of the
+ symbol and the actual location of the toc as the toc
+ index.
+
+ In fact, what is usually happening is, because the
+ Import Address Table is mapped immediately following
+ the toc, some trippy library code trying for speed on
+ dll linkage, takes advantage of that and considers
+ the IAT to be part of the toc, thus saving a load.
+ */
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ "TOCDEFN is on, (%s) (%p) our_toc_offset = %x\n",
+ name, h, our_toc_offset);
+#endif
+
+ our_toc_offset = val -
+ (toc_section->output_section->vma +
+ toc_section->output_offset);
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ " our_toc_offset set to %x\n", our_toc_offset);
+#endif
+
+ /* The size must still fit in a 16bit displacment */
+ if (our_toc_offset >= 65535)
+ {
+ fprintf(stderr,
+ "TOCDEFN Relocation exceeded "
+ "displacment of 65535\n");
+ abort();
+ }
+
+ record_toc(toc_section, our_toc_offset, pub, strdup(name));
+ }
+ else if (IS_WRITTEN(our_toc_offset))
+ {
+ /* if it has been written out, it is marked with the
+ 1 bit. Fix up our offset, but do not write it out
+ again.
+ */
+ MAKE_ADDR_AGAIN(our_toc_offset);
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "Not writing out toc_offset of %d for %s\n",
+ our_toc_offset, name);
+#endif
+ }
+ else
+ {
+ record_toc(toc_section, our_toc_offset, pub, strdup(name));
+
+#ifdef TOC_DEBUG
+ /* write out the toc entry */
+ fprintf(stderr,
+ "Writing out toc_offset "
+ "toc_section (%p,%p)+%d val %d for %s\n",
+ toc_section,
+ toc_section->contents,
+ our_toc_offset,
+ val,
+ name);
+#endif
+
+ /* write out the toc entry */
+ bfd_put_32(output_bfd,
+ val,
+ toc_section->contents + our_toc_offset);
+
+ MARK_AS_WRITTEN(h->toc_offset);
+ /* The tricky part is that this is the address that */
+ /* needs a .reloc entry for it */
+ fixit = true;
+ }
+ }
+
+ if (fixit && info->base_file)
+ {
+ /* So if this is non pcrelative, and is referenced
+ to a section or a common symbol, then it needs a reloc */
+
+ /* relocation to a symbol in a section which
+ isn't absolute - we output the address here
+ to a file */
+
+ bfd_vma addr = toc_section->output_section->vma
+ + toc_section->output_offset + our_toc_offset;
+
+ if (coff_data(output_bfd)->pe)
+ addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ " Toc Section .reloc candidate addr = %x\n", addr);
+#endif
+ fwrite (&addr, 1,4, (FILE *) info->base_file);
+ }
+
+
+ /* FIXME: this test is conservative */
+ if ( (r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN &&
+ our_toc_offset > toc_section->_raw_size)
+ {
+ fprintf(stderr,
+ "reloc offset is bigger than the toc size!\n");
+ abort();
+ }
+
+ /* Now we know the relocation for this toc reference */
+ relocation = our_toc_offset + TOC_LOAD_ADJUSTMENT;
+ rstat = _bfd_relocate_contents (howto,
+ input_bfd,
+ relocation,
+ loc);
+ }
+ break;
+ case IMAGE_REL_PPC_IFGLUE:
+ {
+ /* To solve this, we need to know whether or not the symbol */
+ /* appearing on the call instruction is a glue function or not. */
+ /* A glue function must announce itself via a IMGLUE reloc, and */
+ /* the reloc contains the required toc restore instruction */
+
+ bfd_vma x;
+ const char *my_name;
+ DUMP_RELOC2(howto->name, rel);
+
+ if (h != 0)
+ {
+ my_name = h->root.root.root.string;
+ if (h->symbol_is_glue == 1)
+ {
+ x = bfd_get_32(input_bfd, loc);
+ bfd_put_32(input_bfd, h->glue_insn, loc);
+ }
+ }
+ }
+ break;
+ case IMAGE_REL_PPC_SECREL:
+ /* Unimplemented: codeview debugging information */
+ /* For fast access to the header of the section
+ containing the item. */
+ break;
+ case IMAGE_REL_PPC_SECTION:
+ /* Unimplemented: codeview debugging information */
+ /* Is used to indicate that the value should be relative
+ to the beginning of the section that contains the
+ symbol */
+ break;
+ case IMAGE_REL_PPC_ABSOLUTE:
+ {
+ const char *my_name;
+ if (h == 0)
+ my_name = (syms+symndx)->_n._n_name;
+ else
+ {
+ my_name = h->root.root.root.string;
+ }
+
+ fprintf(stderr,
+ "Warning: unsupported reloc %s <file %s, section %s>\n",
+ howto->name,
+ bfd_get_filename(input_bfd),
+ input_section->name);
+
+ fprintf(stderr,"sym %d (%s), r_vaddr %d (%x)\n",
+ rel->r_symndx, my_name, rel->r_vaddr, rel->r_vaddr);
+ }
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ {
+ /* There is nothing to do now. This reloc was noted in the first
+ pass over the relocs, and the glue instruction extracted */
+ const char *my_name;
+ if (h->symbol_is_glue == 1)
+ break;
+ my_name = h->root.root.root.string;
+ fprintf(stderr,
+ "Warning: previously missed IMGLUE reloc %s <file %s, section %s>\n",
+ howto->name,
+ bfd_get_filename(input_bfd),
+ input_section->name);
+ break;
+
+ }
+ break;
+
+ case IMAGE_REL_PPC_ADDR32NB:
+ {
+ struct coff_link_hash_entry *myh = 0;
+ const char *name = 0;
+ DUMP_RELOC2(howto->name, rel);
+
+ if (strncmp(".idata$2",input_section->name,8) == 0 && first_thunk_address == 0)
+ {
+ /* set magic values */
+ int idata5offset;
+ struct coff_link_hash_entry *myh = 0;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata5_magic__",
+ false, false, true);
+ first_thunk_address = myh->root.u.def.value +
+ sec->output_section->vma +
+ sec->output_offset -
+ pe_data(output_bfd)->pe_opthdr.ImageBase;
+
+ idata5offset = myh->root.u.def.value;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata6_magic__",
+ false, false, true);
+
+ thunk_size = myh->root.u.def.value - idata5offset;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata4_magic__",
+ false, false, true);
+ import_table_size = myh->root.u.def.value;
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ "first computation triggered fta %x, ts %d(%x), its %d(%x)\n",
+ first_thunk_address, thunk_size, thunk_size, import_table_size,
+ import_table_size);
+#endif
+ }
+
+ if (h == 0)
+ { /* it is a file local symbol */
+ sym = syms + symndx;
+ name = sym->_n._n_name;
+ }
+ else
+ {
+ char *target = 0;
+
+ name = h->root.root.root.string;
+ if (strcmp(".idata$2", name) == 0)
+ target = "__idata2_magic__";
+ else if (strcmp(".idata$4", name) == 0)
+ target = "__idata4_magic__";
+ else if (strcmp(".idata$5", name) == 0)
+ target = "__idata5_magic__";
+
+ if (target != 0)
+ {
+ myh = 0;
+
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ target,
+ false, false, true);
+ if (myh == 0)
+ {
+ fprintf(stderr, "Missing idata magic cookies, "
+ "this cannot work anyway...\n");
+ abort();
+ }
+
+ val = myh->root.u.def.value +
+ sec->output_section->vma + sec->output_offset;
+ if (first_thunk_address == 0)
+ {
+ int idata5offset;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata5_magic__",
+ false, false, true);
+ first_thunk_address = myh->root.u.def.value +
+ sec->output_section->vma +
+ sec->output_offset -
+ pe_data(output_bfd)->pe_opthdr.ImageBase;
+
+ idata5offset = myh->root.u.def.value;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata6_magic__",
+ false, false, true);
+
+ thunk_size = myh->root.u.def.value - idata5offset;
+ myh = coff_link_hash_lookup (coff_hash_table (info),
+ "__idata4_magic__",
+ false, false, true);
+ import_table_size = myh->root.u.def.value;
+#ifdef DEBUG_RELOC
+
+ fprintf(stderr,
+ "second computation triggered fta %x, ts %d(%x), its %d(%x)\n",
+ first_thunk_address, thunk_size, thunk_size, import_table_size,
+ import_table_size);
+#endif
+ }
+ }
+ }
+
+ rstat = _bfd_relocate_contents (howto,
+ input_bfd,
+ val -
+ pe_data(output_bfd)->pe_opthdr.ImageBase,
+ loc);
+ }
+ break;
+
+ case IMAGE_REL_PPC_REL24:
+ DUMP_RELOC2(howto->name, rel);
+ val -= (input_section->output_section->vma
+ + input_section->output_offset);
+
+ rstat = _bfd_relocate_contents (howto,
+ input_bfd,
+ val,
+ loc);
+ break;
+ case IMAGE_REL_PPC_ADDR16:
+ case IMAGE_REL_PPC_ADDR24:
+ case IMAGE_REL_PPC_ADDR32:
+ DUMP_RELOC2(howto->name, rel);
+ rstat = _bfd_relocate_contents (howto,
+ input_bfd,
+ val,
+ loc);
+ break;
+ }
+
+ if ( info->base_file )
+ {
+ /* So if this is non pcrelative, and is referenced
+ to a section or a common symbol, then it needs a reloc */
+ if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
+ {
+ /* relocation to a symbol in a section which
+ isn't absolute - we output the address here
+ to a file */
+ bfd_vma addr = rel->r_vaddr
+ - input_section->vma
+ + input_section->output_offset
+ + input_section->output_section->vma;
+
+ if (coff_data(output_bfd)->pe)
+ {
+ bfd_vma before_addr = addr;
+ addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ " adjusted down from %x to %x", before_addr, addr);
+#endif
+ }
+#ifdef DEBUG_RELOC
+ fprintf(stderr, "\n");
+#endif
+
+ fwrite (&addr, 1,4, (FILE *) info->base_file);
+ }
+ }
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.root.string;
+ else if (sym == NULL)
+ name = "*unknown*";
+ else if (sym->_n._n_n._n_zeroes == 0
+ && sym->_n._n_n._n_offset != 0)
+ name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
+ else
+ {
+ strncpy (buf, sym->_n._n_name, SYMNMLEN);
+ buf[SYMNMLEN] = '\0';
+ name = buf;
+ }
+#if 0
+ else
+ {
+ name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+ if (name == NULL)
+ return false;
+ }
+#endif
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name,
+ (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ {
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ "pe_ppc_relocate_section (%s) for %s in bfd %s RETURNING TRUE\n",
+ TARGET_LITTLE_NAME,
+ input_section->name,
+ input_bfd->filename);
+
+#endif
+ return false;
+ }
+ }
+ }
+
+ }
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ "pe_ppc_relocate_section (%s) for %s in bfd %s RETURNING TRUE\n",
+ TARGET_LITTLE_NAME,
+ input_section->name,
+ input_bfd->filename);
+
+#endif
+
+ return true;
+}
+
+
+#ifdef COFF_IMAGE_WITH_PE
+
+long int global_toc_size = 4;
+
+bfd* bfd_of_toc_owner = 0;
+
+long int import_table_size;
+long int first_thunk_address;
+long int thunk_size;
+
+struct list_ele *head;
+struct list_ele *tail;
+
+static char *
+h1 = "\n\t\t\tTOC MAPPING\n\n";
+static char *
+h2 = " TOC disassembly Comments Name\n";
+static char *
+h3 = " Offset spelling (if present)\n";
+
+void
+dump_toc(vfile)
+ void *vfile;
+{
+ FILE *file = vfile;
+ struct list_ele *t;
+
+ fprintf(file, h1);
+ fprintf(file, h2);
+ fprintf(file, h3);
+
+ for(t = head; t != 0; t=t->next)
+ {
+ char *cat;
+
+ if (t->cat == priv)
+ cat = "private ";
+ else if (t->cat == pub)
+ cat = "public ";
+ else if (t->cat == data)
+ cat = "data-in-toc ";
+
+ if (t->offset > global_toc_size)
+ {
+ if (t->offset <= global_toc_size + thunk_size)
+ cat = "IAT reference ";
+ else
+ {
+ fprintf(file,
+ "**** global_toc_size %d(%x), thunk_size %d(%x)\n",
+ global_toc_size, global_toc_size, thunk_size, thunk_size);
+ cat = "Out of bounds!";
+ }
+ }
+
+ fprintf(file,
+ " %04lx (%d)", t->offset, t->offset - 32768);
+ fprintf(file,
+ " %s %s\n",
+ cat, t->name);
+
+ }
+
+ fprintf(file, "\n");
+}
+
+boolean
+ppc_allocate_toc_section (info)
+ struct bfd_link_info *info;
+{
+ asection *s;
+ bfd_byte *foo;
+ static char test_char = '1';
+
+ if ( global_toc_size == 0 ) /* FIXME: does this get me in trouble? */
+ return true;
+
+ if (bfd_of_toc_owner == 0)
+ {
+ fprintf(stderr,
+ "There is no bfd that owns the toc section!\n");
+ abort();
+ }
+
+ s = bfd_get_section_by_name ( bfd_of_toc_owner , TOC_SECTION_NAME);
+ if (s == NULL)
+ {
+ fprintf(stderr, "No Toc section!\n");
+ abort();
+ }
+
+ foo = bfd_alloc(bfd_of_toc_owner, global_toc_size);
+ memset(foo, test_char, global_toc_size);
+
+ s->_raw_size = s->_cooked_size = global_toc_size;
+ s->contents = foo;
+
+ return true;
+}
+
+boolean
+ppc_process_before_allocation (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ asection *sec;
+ struct internal_reloc *i, *rel;
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ "ppc_process_before_allocation: BFD %s\n",
+ bfd_get_filename(abfd));
+#endif
+
+ /* here we have a bfd that is to be included on the link. We have a hook
+ to do reloc rummaging, before section sizes are nailed down. */
+
+ _bfd_coff_get_external_symbols(abfd);
+
+ /* rummage around all the relocs and map the toc */
+ sec = abfd->sections;
+
+ if (sec == 0)
+ {
+ return true;
+ }
+
+ for (; sec != 0; sec = sec->next)
+ {
+ int toc_offset;
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr,
+ " section %s reloc count %d\n",
+ sec->name,
+ sec->reloc_count);
+#endif
+
+ if (sec->reloc_count == 0)
+ continue;
+
+ /* load the relocs */
+ /* FIXME: there may be a storage leak here */
+ i=_bfd_coff_read_internal_relocs(abfd,sec,1,0,0,0);
+
+ if (i == 0)
+ abort();
+
+ for (rel=i;rel<i+sec->reloc_count;++rel)
+ {
+ unsigned short r_type = EXTRACT_TYPE (rel->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
+ unsigned short junk = EXTRACT_JUNK (rel->r_type);
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+
+ switch(r_type)
+ {
+ case IMAGE_REL_PPC_TOCREL16:
+#if 0
+ /* FIXME:
+ This remains unimplemented for now, as it currently adds
+ un-necessary elements to the toc. All we need to do today
+ is not do anything if TOCDEFN is on.
+ */
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ toc_offset = ppc_record_data_in_toc_entry(abfd, info, sec,
+ rel->r_symndx,
+ default_toc);
+ else
+ toc_offset = ppc_record_toc_entry(abfd, info, sec,
+ rel->r_symndx, default_toc);
+#endif
+ if ( (r_flags & IMAGE_REL_PPC_TOCDEFN) != IMAGE_REL_PPC_TOCDEFN )
+ toc_offset = ppc_record_toc_entry(abfd, info, sec,
+ rel->r_symndx, default_toc);
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ ppc_mark_symbol_as_glue(abfd, rel->r_symndx, rel);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+#endif
+
+
+static bfd_reloc_status_type
+ppc_refhi_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("REFHI");
+ DUMP_RELOC("REFHI",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_undefined;
+}
+
+static bfd_reloc_status_type
+ppc_reflo_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("REFLO");
+ DUMP_RELOC("REFLO",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_undefined;
+}
+
+static bfd_reloc_status_type
+ppc_pair_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("PAIR");
+ DUMP_RELOC("PAIR",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_undefined;
+}
+
+
+static bfd_reloc_status_type
+ppc_toc16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("TOCREL16");
+ DUMP_RELOC("TOCREL16",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ {
+ return bfd_reloc_continue;
+ }
+
+ return bfd_reloc_ok;
+}
+
+/* ADDR32NB : 32 bit address relative to the virtual origin. */
+/* (On the alpha, this is always a linker generated thunk)*/
+/* (i.e. 32bit addr relative to the image base) */
+/* */
+/* */
+
+static bfd_reloc_status_type
+ppc_addr32nb_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("ADDR32NB");
+ DUMP_RELOC("ADDR32NB",reloc_entry);
+
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+ppc_secrel_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("SECREL");
+ DUMP_RELOC("SECREL",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+ppc_section_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("SECTION");
+ DUMP_RELOC("SECTION",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+ppc_imglue_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ UN_IMPL("IMGLUE");
+ DUMP_RELOC("IMGLUE",reloc_entry);
+
+ if (output_bfd == (bfd *) NULL)
+ return bfd_reloc_continue;
+
+ return bfd_reloc_ok;
+}
+
+
+
+#define MAX_RELOC_INDEX \
+ (sizeof(ppc_coff_howto_table) / sizeof(ppc_coff_howto_table[0]) - 1)
+
+
+/* FIXME: There is a possiblity that when we read in a reloc from a file,
+ that there are some bits encoded in the upper portion of the
+ type field. Not yet implemented.
+*/
+static void ppc_coff_rtype2howto PARAMS ((arelent *relent,
+ struct internal_reloc *internal));
+
+static void
+ppc_coff_rtype2howto (relent, internal)
+ arelent *relent;
+ struct internal_reloc *internal;
+{
+
+ /* We can encode one of three things in the type field, aside from the
+ type:
+ 1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
+ value, rather than an addition value
+ 2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
+ the branch is expected to be taken or not.
+ 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
+ For now, we just strip this stuff to find the type, and ignore it other
+ than that.
+ */
+ reloc_howto_type *howto;
+ unsigned short r_type = EXTRACT_TYPE (internal->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(internal->r_type);
+ unsigned short junk = EXTRACT_JUNK (internal->r_type);
+
+ /* the masking process only slices off the bottom byte for r_type. */
+ if ( r_type > MAX_RELOC_INDEX )
+ {
+ fprintf(stderr,
+ "ppc_coff_rtype2howto: reloc index %d out of range [%d, %d]\n",
+ internal->r_type, 0, MAX_RELOC_INDEX);
+ abort();
+ }
+
+ /* check for absolute crap */
+ if ( junk != 0 )
+ {
+ fprintf(stderr,
+ "ppc_coff_rtype2howto: reloc index %d contains junk %d\n",
+ internal->r_type, junk);
+ abort();
+ }
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ switch(r_type)
+ {
+ case IMAGE_REL_PPC_ADDR16:
+ case IMAGE_REL_PPC_REL24:
+ case IMAGE_REL_PPC_ADDR24:
+ case IMAGE_REL_PPC_ADDR32:
+ case IMAGE_REL_PPC_IFGLUE:
+ case IMAGE_REL_PPC_ADDR32NB:
+ case IMAGE_REL_PPC_SECTION:
+ case IMAGE_REL_PPC_SECREL:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+ howto = ppc_coff_howto_table + r_type;
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+ howto = ppc_coff_howto_table + r_type;
+ break;
+ case IMAGE_REL_PPC_TOCREL16:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, internal);
+ if (r_flags & IMAGE_REL_PPC_TOCDEFN)
+ howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
+ else
+ howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
+ break;
+ default:
+ fprintf(stderr,
+ "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
+ ppc_coff_howto_table[r_type].name,
+ r_type);
+ howto = ppc_coff_howto_table + r_type;
+ break;
+ }
+
+ relent->howto = howto;
+
+}
+
+static reloc_howto_type *
+coff_ppc_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+ reloc_howto_type *howto;
+
+ /* We can encode one of three things in the type field, aside from the
+ type:
+ 1. IMAGE_REL_PPC_NEG - indicates the value field is a subtraction
+ value, rather than an addition value
+ 2. IMAGE_REL_PPC_BRTAKEN, IMAGE_REL_PPC_BRNTAKEN - indicates that
+ the branch is expected to be taken or not.
+ 3. IMAGE_REL_PPC_TOCDEFN - toc slot definition in the file
+ For now, we just strip this stuff to find the type, and ignore it other
+ than that.
+ */
+
+ unsigned short r_type = EXTRACT_TYPE (rel->r_type);
+ unsigned short r_flags = EXTRACT_FLAGS(rel->r_type);
+ unsigned short junk = EXTRACT_JUNK (rel->r_type);
+
+ /* the masking process only slices off the bottom byte for r_type. */
+ if ( r_type > MAX_RELOC_INDEX )
+ {
+ fprintf(stderr,
+ "coff_ppc_rtype_to_howto: index %d out of range [%d, %d]\n",
+ r_type, 0, MAX_RELOC_INDEX);
+ abort();
+ }
+
+ /* check for absolute crap */
+ if ( junk != 0 )
+ {
+ fprintf(stderr,
+ "coff_ppc_rtype_to_howto: reloc index %d contains junk %d\n",
+ rel->r_type, junk);
+ abort();
+ }
+
+#ifdef DEBUG_RELOC
+ /* now examine flags */
+ if (r_flags != 0)
+ {
+ fprintf (stderr, "Reloc with flags found!");
+ if ( r_flags & IMAGE_REL_PPC_NEG )
+ fprintf (stderr, " NEG");
+ if ( r_flags & IMAGE_REL_PPC_BRTAKEN )
+ fprintf (stderr, " BRTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_BRNTAKEN )
+ fprintf (stderr, " BRNTAKEN");
+ if ( r_flags & IMAGE_REL_PPC_TOCDEFN )
+ fprintf (stderr, " TOCDEFN");
+ fprintf(stderr, "\n");
+ }
+#endif
+
+ switch(r_type)
+ {
+ case IMAGE_REL_PPC_ADDR32NB:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+ *addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
+ howto = ppc_coff_howto_table + r_type;
+ break;
+ case IMAGE_REL_PPC_TOCREL16:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+ if (r_flags & IMAGE_REL_PPC_TOCDEFN)
+ howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16_DEFN;
+ else
+ howto = ppc_coff_howto_table + IMAGE_REL_PPC_TOCREL16;
+ break;
+ case IMAGE_REL_PPC_ADDR16:
+ case IMAGE_REL_PPC_REL24:
+ case IMAGE_REL_PPC_ADDR24:
+ case IMAGE_REL_PPC_ADDR32:
+ case IMAGE_REL_PPC_IFGLUE:
+ case IMAGE_REL_PPC_SECTION:
+ case IMAGE_REL_PPC_SECREL:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+ howto = ppc_coff_howto_table + r_type;
+ break;
+ case IMAGE_REL_PPC_IMGLUE:
+ DUMP_RELOC2(ppc_coff_howto_table[r_type].name, rel);
+ howto = ppc_coff_howto_table + r_type;
+ break;
+ default:
+ fprintf(stderr,
+ "Warning: Unsupported reloc %s [%d] used -- it may not work.\n",
+ ppc_coff_howto_table[r_type].name,
+ r_type);
+ howto = ppc_coff_howto_table + r_type;
+ break;
+ }
+
+ return howto;
+}
+
+
+/* a cheesy little macro to make the code a little more readable */
+#define HOW2MAP(bfd_rtype,ppc_rtype) \
+ case bfd_rtype: return &ppc_coff_howto_table[ppc_rtype]
+
+static reloc_howto_type *ppc_coff_reloc_type_lookup
+PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+static reloc_howto_type *
+ppc_coff_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+
+#ifdef DEBUG_RELOC
+ fprintf(stderr, "ppc_coff_reloc_type_lookup for %s\n",
+ bfd_get_reloc_code_name(code));
+#endif
+
+ switch (code)
+ {
+ HOW2MAP(BFD_RELOC_32_GOTOFF, IMAGE_REL_PPC_IMGLUE);
+ HOW2MAP(BFD_RELOC_16_GOT_PCREL, IMAGE_REL_PPC_IFGLUE);
+ HOW2MAP(BFD_RELOC_16, IMAGE_REL_PPC_ADDR16);
+ HOW2MAP(BFD_RELOC_PPC_B26, IMAGE_REL_PPC_REL24);
+ HOW2MAP(BFD_RELOC_PPC_BA26, IMAGE_REL_PPC_ADDR24);
+ HOW2MAP(BFD_RELOC_PPC_TOC16, IMAGE_REL_PPC_TOCREL16);
+ HOW2MAP(BFD_RELOC_16_GOTOFF, IMAGE_REL_PPC_TOCREL16_DEFN);
+ HOW2MAP(BFD_RELOC_32, IMAGE_REL_PPC_ADDR32);
+ HOW2MAP(BFD_RELOC_RVA, IMAGE_REL_PPC_ADDR32NB);
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#undef HOW2MAP
+
+
+/* Tailor coffcode.h -- macro heaven. */
+
+#define RTYPE2HOWTO(cache_ptr, dst) ppc_coff_rtype2howto (cache_ptr, dst)
+
+#ifndef COFF_IMAGE_WITH_PE
+static void
+ppc_coff_swap_sym_in_hook ();
+#endif
+
+/* We use the special COFF backend linker, with our own special touch. */
+
+#define coff_bfd_reloc_type_lookup ppc_coff_reloc_type_lookup
+#define coff_rtype_to_howto coff_ppc_rtype_to_howto
+#define coff_relocate_section coff_ppc_relocate_section
+#define coff_bfd_final_link ppc_bfd_coff_final_link
+
+#ifndef COFF_IMAGE_WITH_PE
+#define coff_swap_sym_in_hook ppc_coff_swap_sym_in_hook
+#endif
+
+#define SELECT_RELOC(internal, howto) {internal.r_type=howto->type;}
+
+#define COFF_PAGE_SIZE 0x1000
+
+#define POWERPC_LE_PE
+
+#include "coffcode.h"
+
+
+
+#ifndef COFF_IMAGE_WITH_PE
+/* FIXME:
+ What we're trying to do here is allocate a toc section (early), and attach
+ it to the last bfd to be processed. This avoids the problem of having a toc
+ written out before all files have been processed. This code allocates
+ a toc section for every file, and records the last one seen. There are
+ at least two problems with this approach:
+ 1. We allocate whole bunches of toc sections that are ignored, but at
+ at least we will not allocate a toc if no .toc is present.
+ 2. It's not clear to me that being the last bfd read necessarily means
+ that you are the last bfd closed.
+ 3. Doing it on a "swap in" hook depends on when the "swap in" is called,
+ and how often, etc. It's not clear to me that there isn't a hole here.
+*/
+
+static void
+ppc_coff_swap_sym_in_hook (abfd, ext1, in1)
+ bfd *abfd;
+ PTR ext1;
+ PTR in1;
+{
+ SYMENT *ext = (SYMENT *)ext1;
+ struct internal_syment *in = (struct internal_syment *)in1;
+
+ if (bfd_of_toc_owner != 0) /* we already have a toc, so go home */
+ return;
+
+ if (strcmp(in->_n._n_name, ".toc") == 0)
+ {
+ flagword flags;
+ register asection *s;
+ char *foo;
+
+ s = bfd_get_section_by_name ( abfd , TOC_SECTION_NAME);
+ if (s != NULL)
+ {
+ return;
+ }
+
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY ;
+
+#ifdef TOC_DEBUG
+ fprintf(stderr,
+ "ppc_coff_swap_sym_in_hook: about to create the %s section\n",
+ TOC_SECTION_NAME);
+#endif
+
+ s = bfd_make_section (abfd, TOC_SECTION_NAME);
+
+ if (s == NULL
+ || !bfd_set_section_flags (abfd, s, flags)
+ || !bfd_set_section_alignment (abfd, s, 2))
+ {
+ fprintf(stderr,
+ "toc section allocation failed!\n");
+ abort();
+ }
+
+ /* save the bfd for later allocation */
+ bfd_of_toc_owner = abfd;
+ }
+
+ return;
+}
+#endif
+
+boolean
+ppc_bfd_coff_final_link ();
+
+#ifndef COFF_IMAGE_WITH_PE
+
+static boolean
+ppc_do_last(abfd)
+ bfd *abfd;
+{
+ if (abfd == bfd_of_toc_owner)
+ return true;
+ else
+ return false;
+}
+
+static bfd *
+ppc_get_last()
+{
+ return bfd_of_toc_owner;
+}
+
+/* this piece of machinery exists only to guarantee that the bfd that holds
+ the toc section is written last.
+
+ This does depend on bfd_make_section attaching a new section to the
+ end of the section list for the bfd.
+
+ This is otherwise intended to be functionally the same as
+ cofflink.c:_bfd_coff_final_link(). It is specifically different only
+ where the POWERPC_LE_PE macro modifies the code. It is left in as a
+ precise form of comment. krk@cygnus.com
+*/
+#define POWERPC_LE_PE
+
+
+/* Do the final link step. */
+
+boolean
+ppc_bfd_coff_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ bfd_size_type symesz;
+ struct coff_final_link_info finfo;
+ boolean debug_merge_allocated;
+ asection *o;
+ struct bfd_link_order *p;
+ size_t max_sym_count;
+ size_t max_lineno_count;
+ size_t max_reloc_count;
+ size_t max_output_reloc_count;
+ size_t max_contents_size;
+ file_ptr rel_filepos;
+ unsigned int relsz;
+ file_ptr line_filepos;
+ unsigned int linesz;
+ bfd *sub;
+ bfd_byte *external_relocs = NULL;
+ char strbuf[STRING_SIZE_SIZE];
+
+ symesz = bfd_coff_symesz (abfd);
+
+ finfo.info = info;
+ finfo.output_bfd = abfd;
+ finfo.strtab = NULL;
+ finfo.section_info = NULL;
+ finfo.last_file_index = -1;
+ finfo.internal_syms = NULL;
+ finfo.sec_ptrs = NULL;
+ finfo.sym_indices = NULL;
+ finfo.outsyms = NULL;
+ finfo.linenos = NULL;
+ finfo.contents = NULL;
+ finfo.external_relocs = NULL;
+ finfo.internal_relocs = NULL;
+ debug_merge_allocated = false;
+
+ coff_data (abfd)->link_info = info;
+
+ finfo.strtab = _bfd_stringtab_init ();
+ if (finfo.strtab == NULL)
+ goto error_return;
+
+ if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
+ goto error_return;
+ debug_merge_allocated = true;
+
+ /* Compute the file positions for all the sections. */
+ if (! abfd->output_has_begun)
+ bfd_coff_compute_section_file_positions (abfd);
+
+ /* Count the line numbers and relocation entries required for the
+ output file. Set the file positions for the relocs. */
+ rel_filepos = obj_relocbase (abfd);
+ relsz = bfd_coff_relsz (abfd);
+ max_contents_size = 0;
+ max_lineno_count = 0;
+ max_reloc_count = 0;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+
+ if (p->type == bfd_indirect_link_order)
+ {
+ asection *sec;
+
+ sec = p->u.indirect.section;
+
+ if (info->strip == strip_none
+ || info->strip == strip_some)
+ o->lineno_count += sec->lineno_count;
+
+ if (info->relocateable)
+ o->reloc_count += sec->reloc_count;
+
+ if (sec->_raw_size > max_contents_size)
+ max_contents_size = sec->_raw_size;
+ if (sec->lineno_count > max_lineno_count)
+ max_lineno_count = sec->lineno_count;
+ if (sec->reloc_count > max_reloc_count)
+ max_reloc_count = sec->reloc_count;
+ }
+ else if (info->relocateable
+ && (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order))
+ ++o->reloc_count;
+ }
+ if (o->reloc_count == 0)
+ o->rel_filepos = 0;
+ else
+ {
+ o->flags |= SEC_RELOC;
+ o->rel_filepos = rel_filepos;
+ rel_filepos += o->reloc_count * relsz;
+ }
+ }
+
+ /* If doing a relocateable link, allocate space for the pointers we
+ need to keep. */
+ if (info->relocateable)
+ {
+ unsigned int i;
+
+ /* We use section_count + 1, rather than section_count, because
+ the target_index fields are 1 based. */
+ finfo.section_info =
+ ((struct coff_link_section_info *)
+ bfd_malloc ((abfd->section_count + 1)
+ * sizeof (struct coff_link_section_info)));
+ if (finfo.section_info == NULL)
+ goto error_return;
+ for (i = 0; i <= abfd->section_count; i++)
+ {
+ finfo.section_info[i].relocs = NULL;
+ finfo.section_info[i].rel_hashes = NULL;
+ }
+ }
+
+ /* We now know the size of the relocs, so we can determine the file
+ positions of the line numbers. */
+ line_filepos = rel_filepos;
+ linesz = bfd_coff_linesz (abfd);
+ max_output_reloc_count = 0;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (o->lineno_count == 0)
+ o->line_filepos = 0;
+ else
+ {
+ o->line_filepos = line_filepos;
+ line_filepos += o->lineno_count * linesz;
+ }
+
+ if (o->reloc_count != 0)
+ {
+ /* We don't know the indices of global symbols until we have
+ written out all the local symbols. For each section in
+ the output file, we keep an array of pointers to hash
+ table entries. Each entry in the array corresponds to a
+ reloc. When we find a reloc against a global symbol, we
+ set the corresponding entry in this array so that we can
+ fix up the symbol index after we have written out all the
+ local symbols.
+
+ Because of this problem, we also keep the relocs in
+ memory until the end of the link. This wastes memory,
+ but only when doing a relocateable link, which is not the
+ common case. */
+ BFD_ASSERT (info->relocateable);
+ finfo.section_info[o->target_index].relocs =
+ ((struct internal_reloc *)
+ bfd_malloc (o->reloc_count * sizeof (struct internal_reloc)));
+ finfo.section_info[o->target_index].rel_hashes =
+ ((struct coff_link_hash_entry **)
+ bfd_malloc (o->reloc_count
+ * sizeof (struct coff_link_hash_entry *)));
+ if (finfo.section_info[o->target_index].relocs == NULL
+ || finfo.section_info[o->target_index].rel_hashes == NULL)
+ goto error_return;
+
+ if (o->reloc_count > max_output_reloc_count)
+ max_output_reloc_count = o->reloc_count;
+ }
+
+ /* Reset the reloc and lineno counts, so that we can use them to
+ count the number of entries we have output so far. */
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ }
+
+ obj_sym_filepos (abfd) = line_filepos;
+
+ /* Figure out the largest number of symbols in an input BFD. Take
+ the opportunity to clear the output_has_begun fields of all the
+ input BFD's. */
+ max_sym_count = 0;
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ size_t sz;
+
+ sub->output_has_begun = false;
+ sz = obj_raw_syment_count (sub);
+ if (sz > max_sym_count)
+ max_sym_count = sz;
+ }
+
+ /* Allocate some buffers used while linking. */
+ finfo.internal_syms = ((struct internal_syment *)
+ bfd_malloc (max_sym_count
+ * sizeof (struct internal_syment)));
+ finfo.sec_ptrs = (asection **) bfd_malloc (max_sym_count
+ * sizeof (asection *));
+ finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
+ finfo.outsyms = ((bfd_byte *)
+ bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
+ finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count
+ * bfd_coff_linesz (abfd));
+ finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+ finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
+ if (! info->relocateable)
+ finfo.internal_relocs = ((struct internal_reloc *)
+ bfd_malloc (max_reloc_count
+ * sizeof (struct internal_reloc)));
+ if ((finfo.internal_syms == NULL && max_sym_count > 0)
+ || (finfo.sec_ptrs == NULL && max_sym_count > 0)
+ || (finfo.sym_indices == NULL && max_sym_count > 0)
+ || finfo.outsyms == NULL
+ || (finfo.linenos == NULL && max_lineno_count > 0)
+ || (finfo.contents == NULL && max_contents_size > 0)
+ || (finfo.external_relocs == NULL && max_reloc_count > 0)
+ || (! info->relocateable
+ && finfo.internal_relocs == NULL
+ && max_reloc_count > 0))
+ goto error_return;
+
+ /* We now know the position of everything in the file, except that
+ we don't know the size of the symbol table and therefore we don't
+ know where the string table starts. We just build the string
+ table in memory as we go along. We process all the relocations
+ for a single input file at once. */
+ obj_raw_syment_count (abfd) = 0;
+
+ if (coff_backend_info (abfd)->_bfd_coff_start_final_link)
+ {
+ if (! bfd_coff_start_final_link (abfd, info))
+ goto error_return;
+ }
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour (p->u.indirect.section->owner)
+ == bfd_target_coff_flavour))
+ {
+ sub = p->u.indirect.section->owner;
+#ifdef POWERPC_LE_PE
+ if (! sub->output_has_begun && !ppc_do_last(sub))
+#else
+ if (! sub->output_has_begun)
+#endif
+ {
+ if (! _bfd_coff_link_input_bfd (&finfo, sub))
+ goto error_return;
+ sub->output_has_begun = true;
+ }
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
+ goto error_return;
+ }
+ else
+ {
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ }
+ }
+
+#ifdef POWERPC_LE_PE
+ {
+ extern bfd* ppc_get_last();
+ bfd* last_one = ppc_get_last();
+ if (last_one)
+ {
+ if (! _bfd_coff_link_input_bfd (&finfo, last_one))
+ goto error_return;
+ }
+ last_one->output_has_begun = true;
+ }
+#endif
+
+ /* Free up the buffers used by _bfd_coff_link_input_bfd. */
+
+ coff_debug_merge_hash_table_free (&finfo.debug_merge);
+ debug_merge_allocated = false;
+
+ if (finfo.internal_syms != NULL)
+ {
+ free (finfo.internal_syms);
+ finfo.internal_syms = NULL;
+ }
+ if (finfo.sec_ptrs != NULL)
+ {
+ free (finfo.sec_ptrs);
+ finfo.sec_ptrs = NULL;
+ }
+ if (finfo.sym_indices != NULL)
+ {
+ free (finfo.sym_indices);
+ finfo.sym_indices = NULL;
+ }
+ if (finfo.linenos != NULL)
+ {
+ free (finfo.linenos);
+ finfo.linenos = NULL;
+ }
+ if (finfo.contents != NULL)
+ {
+ free (finfo.contents);
+ finfo.contents = NULL;
+ }
+ if (finfo.external_relocs != NULL)
+ {
+ free (finfo.external_relocs);
+ finfo.external_relocs = NULL;
+ }
+ if (finfo.internal_relocs != NULL)
+ {
+ free (finfo.internal_relocs);
+ finfo.internal_relocs = NULL;
+ }
+
+ /* The value of the last C_FILE symbol is supposed to be the symbol
+ index of the first external symbol. Write it out again if
+ necessary. */
+ if (finfo.last_file_index != -1
+ && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
+ {
+ finfo.last_file.n_value = obj_raw_syment_count (abfd);
+ bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
+ (PTR) finfo.outsyms);
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + finfo.last_file_index * symesz),
+ SEEK_SET) != 0
+ || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
+ return false;
+ }
+
+ /* Write out the global symbols. */
+ finfo.failed = false;
+ coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_global_sym,
+ (PTR) &finfo);
+ if (finfo.failed)
+ goto error_return;
+
+ /* The outsyms buffer is used by _bfd_coff_write_global_sym. */
+ if (finfo.outsyms != NULL)
+ {
+ free (finfo.outsyms);
+ finfo.outsyms = NULL;
+ }
+
+ if (info->relocateable)
+ {
+ /* Now that we have written out all the global symbols, we know
+ the symbol indices to use for relocs against them, and we can
+ finally write out the relocs. */
+ external_relocs = ((bfd_byte *)
+ bfd_malloc (max_output_reloc_count * relsz));
+ if (external_relocs == NULL)
+ goto error_return;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct internal_reloc *irel;
+ struct internal_reloc *irelend;
+ struct coff_link_hash_entry **rel_hash;
+ bfd_byte *erel;
+
+ if (o->reloc_count == 0)
+ continue;
+
+ irel = finfo.section_info[o->target_index].relocs;
+ irelend = irel + o->reloc_count;
+ rel_hash = finfo.section_info[o->target_index].rel_hashes;
+ erel = external_relocs;
+ for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+ {
+ if (*rel_hash != NULL)
+ {
+ BFD_ASSERT ((*rel_hash)->indx >= 0);
+ irel->r_symndx = (*rel_hash)->indx;
+ }
+ bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+ }
+
+ if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
+ || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
+ abfd) != relsz * o->reloc_count)
+ goto error_return;
+ }
+
+ free (external_relocs);
+ external_relocs = NULL;
+ }
+
+ /* Free up the section information. */
+ if (finfo.section_info != NULL)
+ {
+ unsigned int i;
+
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
+ }
+ free (finfo.section_info);
+ finfo.section_info = NULL;
+ }
+
+ /* Write out the string table. */
+ if (obj_raw_syment_count (abfd) != 0)
+ {
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + obj_raw_syment_count (abfd) * symesz),
+ SEEK_SET) != 0)
+ return false;
+
+#if STRING_SIZE_SIZE == 4
+ bfd_h_put_32 (abfd,
+ _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
+ (bfd_byte *) strbuf);
+#else
+ #error Change bfd_h_put_32
+#endif
+
+ if (bfd_write (strbuf, 1, STRING_SIZE_SIZE, abfd) != STRING_SIZE_SIZE)
+ return false;
+
+ if (! _bfd_stringtab_emit (abfd, finfo.strtab))
+ return false;
+ }
+
+ _bfd_stringtab_free (finfo.strtab);
+
+ /* Setting bfd_get_symcount to 0 will cause write_object_contents to
+ not try to write out the symbols. */
+ bfd_get_symcount (abfd) = 0;
+
+ return true;
+
+ error_return:
+ if (debug_merge_allocated)
+ coff_debug_merge_hash_table_free (&finfo.debug_merge);
+ if (finfo.strtab != NULL)
+ _bfd_stringtab_free (finfo.strtab);
+ if (finfo.section_info != NULL)
+ {
+ unsigned int i;
+
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
+ }
+ free (finfo.section_info);
+ }
+ if (finfo.internal_syms != NULL)
+ free (finfo.internal_syms);
+ if (finfo.sec_ptrs != NULL)
+ free (finfo.sec_ptrs);
+ if (finfo.sym_indices != NULL)
+ free (finfo.sym_indices);
+ if (finfo.outsyms != NULL)
+ free (finfo.outsyms);
+ if (finfo.linenos != NULL)
+ free (finfo.linenos);
+ if (finfo.contents != NULL)
+ free (finfo.contents);
+ if (finfo.external_relocs != NULL)
+ free (finfo.external_relocs);
+ if (finfo.internal_relocs != NULL)
+ free (finfo.internal_relocs);
+ if (external_relocs != NULL)
+ free (external_relocs);
+ return false;
+}
+#endif
+
+
+/* The transfer vectors that lead the outside world to all of the above. */
+
+#ifdef TARGET_LITTLE_SYM
+const bfd_target
+TARGET_LITTLE_SYM =
+{
+ TARGET_LITTLE_NAME, /* name or coff-arm-little */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* FIXME: object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
+#endif
+
+#ifdef TARGET_BIG_SYM
+const bfd_target
+TARGET_BIG_SYM =
+{
+ TARGET_BIG_NAME,
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* FIXME: object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, /* _bfd_dummy_target */ coff_object_p },
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
+
+#endif
diff --git a/contrib/gdb/bfd/coff-rs6000.c b/contrib/gdb/bfd/coff-rs6000.c
new file mode 100644
index 0000000..c065bd4
--- /dev/null
+++ b/contrib/gdb/bfd/coff-rs6000.c
@@ -0,0 +1,1403 @@
+/* BFD back-end for IBM RS/6000 "XCOFF" files.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ FIXME: Can someone provide a transliteration of this name into ASCII?
+ Using the following chars caused a compiler warning on HIUX (so I replaced
+ them with octal escapes), and isn't useful without an understanding of what
+ character set it is.
+ Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
+ and John Gilmore.
+ Archive support from Damon A. Permezel.
+ Contributed by IBM Corporation and 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Internalcoff.h and coffcode.h modify themselves based on this flag. */
+#define RS6000COFF_C 1
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/internal.h"
+#include "coff/rs6000.h"
+#include "libcoff.h"
+
+/* The main body of code is in coffcode.h. */
+
+static boolean xcoff_mkobject PARAMS ((bfd *));
+static boolean xcoff_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static void xcoff_rtype2howto
+ PARAMS ((arelent *, struct internal_reloc *));
+static reloc_howto_type *xcoff_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static boolean xcoff_slurp_armap PARAMS ((bfd *));
+static const bfd_target *xcoff_archive_p PARAMS ((bfd *));
+static PTR xcoff_read_ar_hdr PARAMS ((bfd *));
+static bfd *xcoff_openr_next_archived_file PARAMS ((bfd *, bfd *));
+static int xcoff_generic_stat_arch_elt PARAMS ((bfd *, struct stat *));
+static const char *normalize_filename PARAMS ((bfd *));
+static boolean xcoff_write_armap
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int));
+static boolean xcoff_write_archive_contents PARAMS ((bfd *));
+
+/* We use our own tdata type. Its first field is the COFF tdata type,
+ so the COFF routines are compatible. */
+
+static boolean
+xcoff_mkobject (abfd)
+ bfd *abfd;
+{
+ coff_data_type *coff;
+
+ abfd->tdata.xcoff_obj_data =
+ ((struct xcoff_tdata *)
+ bfd_zalloc (abfd, sizeof (struct xcoff_tdata)));
+ if (abfd->tdata.xcoff_obj_data == NULL)
+ return false;
+ coff = coff_data (abfd);
+ coff->symbols = (coff_symbol_type *) NULL;
+ coff->conversion_table = (unsigned int *) NULL;
+ coff->raw_syments = (struct coff_ptr_struct *) NULL;
+ coff->relocbase = 0;
+
+ xcoff_data (abfd)->modtype = ('1' << 8) | 'L';
+
+ /* We set cputype to -1 to indicate that it has not been
+ initialized. */
+ xcoff_data (abfd)->cputype = -1;
+
+ xcoff_data (abfd)->csects = NULL;
+ xcoff_data (abfd)->debug_indices = NULL;
+
+ return true;
+}
+
+/* Copy XCOFF data from one BFD to another. */
+
+static boolean
+xcoff_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ struct xcoff_tdata *ix, *ox;
+ asection *sec;
+
+ if (ibfd->xvec != obfd->xvec)
+ return true;
+ ix = xcoff_data (ibfd);
+ ox = xcoff_data (obfd);
+ ox->full_aouthdr = ix->full_aouthdr;
+ ox->toc = ix->toc;
+ if (ix->sntoc == 0)
+ ox->sntoc = 0;
+ else
+ {
+ sec = coff_section_from_bfd_index (ibfd, ix->sntoc);
+ if (sec == NULL)
+ ox->sntoc = 0;
+ else
+ ox->sntoc = sec->output_section->target_index;
+ }
+ if (ix->snentry == 0)
+ ox->snentry = 0;
+ else
+ {
+ sec = coff_section_from_bfd_index (ibfd, ix->snentry);
+ if (sec == NULL)
+ ox->snentry = 0;
+ else
+ ox->snentry = sec->output_section->target_index;
+ }
+ ox->text_align_power = ix->text_align_power;
+ ox->data_align_power = ix->data_align_power;
+ ox->modtype = ix->modtype;
+ ox->cputype = ix->cputype;
+ ox->maxdata = ix->maxdata;
+ ox->maxstack = ix->maxstack;
+ return true;
+}
+
+/* The XCOFF reloc table. Actually, XCOFF relocations specify the
+ bitsize and whether they are signed or not, along with a
+ conventional type. This table is for the types, which are used for
+ different algorithms for putting in the reloc. Many of these
+ relocs need special_function entries, which I have not written. */
+
+static reloc_howto_type xcoff_howto_table[] =
+{
+ /* Standard 32 bit relocation. */
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_POS", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit relocation, but store negative value. */
+ HOWTO (1, /* type */
+ 0, /* rightshift */
+ -2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_NEG", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit PC relative relocation. */
+ HOWTO (2, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REL", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit TOC relative relocation. */
+ HOWTO (3, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TOC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* I don't really know what this is. */
+ HOWTO (4, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RTB", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* External TOC relative symbol. */
+ HOWTO (5, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_GL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Local TOC relative symbol. */
+ HOWTO (6, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TCL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 7 },
+
+ /* Non modifiable absolute branch. */
+ HOWTO (8, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_BA", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 9 },
+
+ /* Non modifiable relative branch. */
+ HOWTO (0xa, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_BR", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 0xb },
+
+ /* Indirect load. */
+ HOWTO (0xc, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Load address. */
+ HOWTO (0xd, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RLA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 0xe },
+
+ /* Non-relocating reference. */
+ HOWTO (0xf, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REF", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 0x10 },
+ { 0x11 },
+
+ /* TOC relative indirect load. */
+ HOWTO (0x12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TRL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TOC relative load address. */
+ HOWTO (0x13, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TRLA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable relative branch. */
+ HOWTO (0x14, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RRTBI", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable absolute branch. */
+ HOWTO (0x15, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RRTBA", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable call absolute indirect. */
+ HOWTO (0x16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_CAI", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable call relative. */
+ HOWTO (0x17, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_CREL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x18, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x19, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBAC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch relative. */
+ HOWTO (0x1a, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBR", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x1b, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBRC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+static void
+xcoff_rtype2howto (relent, internal)
+ arelent *relent;
+ struct internal_reloc *internal;
+{
+ relent->howto = xcoff_howto_table + internal->r_type;
+
+ /* The r_size field of an XCOFF reloc encodes the bitsize of the
+ relocation, as well as indicating whether it is signed or not.
+ Doublecheck that the relocation information gathered from the
+ type matches this information. */
+ if (relent->howto->bitsize != ((unsigned int) internal->r_size & 0x1f) + 1)
+ abort ();
+#if 0
+ if ((internal->r_size & 0x80) != 0
+ ? (relent->howto->complain_on_overflow != complain_overflow_signed)
+ : (relent->howto->complain_on_overflow != complain_overflow_bitfield))
+ abort ();
+#endif
+}
+
+static reloc_howto_type *
+xcoff_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ case BFD_RELOC_PPC_B26:
+ return &xcoff_howto_table[0xa];
+ case BFD_RELOC_PPC_BA26:
+ return &xcoff_howto_table[8];
+ case BFD_RELOC_PPC_TOC16:
+ return &xcoff_howto_table[3];
+ case BFD_RELOC_32:
+ case BFD_RELOC_CTOR:
+ return &xcoff_howto_table[0];
+ default:
+ return NULL;
+ }
+}
+
+#define SELECT_RELOC(internal, howto) \
+ { \
+ internal.r_type = howto->type; \
+ internal.r_size = \
+ ((howto->complain_on_overflow == complain_overflow_signed \
+ ? 0x80 \
+ : 0) \
+ | (howto->bitsize - 1)); \
+ }
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+#define COFF_LONG_FILENAMES
+
+#define RTYPE2HOWTO(cache_ptr, dst) xcoff_rtype2howto (cache_ptr, dst)
+
+#define coff_mkobject xcoff_mkobject
+#define coff_bfd_copy_private_bfd_data xcoff_copy_private_bfd_data
+#define coff_bfd_reloc_type_lookup xcoff_reloc_type_lookup
+#define coff_relocate_section _bfd_ppc_xcoff_relocate_section
+
+#include "coffcode.h"
+
+/* XCOFF archive support. The original version of this code was by
+ Damon A. Permezel. It was enhanced to permit cross support, and
+ writing archive files, by Ian Lance Taylor, Cygnus Support.
+
+ XCOFF uses its own archive format. Everything is hooked together
+ with file offset links, so it is possible to rapidly update an
+ archive in place. Of course, we don't do that. An XCOFF archive
+ has a real file header, not just an ARMAG string. The structure of
+ the file header and of each archive header appear below.
+
+ An XCOFF archive also has a member table, which is a list of
+ elements in the archive (you can get that by looking through the
+ linked list, but you have to read a lot more of the file). The
+ member table has a normal archive header with an empty name. It is
+ normally (and perhaps must be) the second to last entry in the
+ archive. The member table data is almost printable ASCII. It
+ starts with a 12 character decimal string which is the number of
+ entries in the table. For each entry it has a 12 character decimal
+ string which is the offset in the archive of that member. These
+ entries are followed by a series of null terminated strings which
+ are the member names for each entry.
+
+ Finally, an XCOFF archive has a global symbol table, which is what
+ we call the armap. The global symbol table has a normal archive
+ header with an empty name. It is normally (and perhaps must be)
+ the last entry in the archive. The contents start with a four byte
+ binary number which is the number of entries. This is followed by
+ a that many four byte binary numbers; each is the file offset of an
+ entry in the archive. These numbers are followed by a series of
+ null terminated strings, which are symbol names. */
+
+/* XCOFF archives use this as a magic string. */
+
+#define XCOFFARMAG "<aiaff>\012"
+#define SXCOFFARMAG 8
+
+/* This terminates an XCOFF archive member name. */
+
+#define XCOFFARFMAG "`\012"
+#define SXCOFFARFMAG 2
+
+/* XCOFF archives start with this (printable) structure. */
+
+struct xcoff_ar_file_hdr
+{
+ /* Magic string. */
+ char magic[SXCOFFARMAG];
+
+ /* Offset of the member table (decimal ASCII string). */
+ char memoff[12];
+
+ /* Offset of the global symbol table (decimal ASCII string). */
+ char symoff[12];
+
+ /* Offset of the first member in the archive (decimal ASCII string). */
+ char firstmemoff[12];
+
+ /* Offset of the last member in the archive (decimal ASCII string). */
+ char lastmemoff[12];
+
+ /* Offset of the first member on the free list (decimal ASCII
+ string). */
+ char freeoff[12];
+};
+
+#define SIZEOF_AR_FILE_HDR (5 * 12 + SXCOFFARMAG)
+
+/* Each XCOFF archive member starts with this (printable) structure. */
+
+struct xcoff_ar_hdr
+{
+ /* File size not including the header (decimal ASCII string). */
+ char size[12];
+
+ /* File offset of next archive member (decimal ASCII string). */
+ char nextoff[12];
+
+ /* File offset of previous archive member (decimal ASCII string). */
+ char prevoff[12];
+
+ /* File mtime (decimal ASCII string). */
+ char date[12];
+
+ /* File UID (decimal ASCII string). */
+ char uid[12];
+
+ /* File GID (decimal ASCII string). */
+ char gid[12];
+
+ /* File mode (octal ASCII string). */
+ char mode[12];
+
+ /* Length of file name (decimal ASCII string). */
+ char namlen[4];
+
+ /* This structure is followed by the file name. The length of the
+ name is given in the namlen field. If the length of the name is
+ odd, the name is followed by a null byte. The name and optional
+ null byte are followed by XCOFFARFMAG, which is not included in
+ namlen. The contents of the archive member follow; the number of
+ bytes is given in the size field. */
+};
+
+#define SIZEOF_AR_HDR (7 * 12 + 4)
+
+/* We store a copy of the xcoff_ar_file_hdr in the tdata field of the
+ artdata structure. */
+#define xcoff_ardata(abfd) \
+ ((struct xcoff_ar_file_hdr *) bfd_ardata (abfd)->tdata)
+
+/* We store a copy of the xcoff_ar_hdr in the arelt_data field of an
+ archive element. */
+#define arch_eltdata(bfd) ((struct areltdata *) ((bfd)->arelt_data))
+#define arch_xhdr(bfd) \
+ ((struct xcoff_ar_hdr *) arch_eltdata (bfd)->arch_header)
+
+/* XCOFF archives do not have anything which corresponds to an
+ extended name table. */
+
+#define xcoff_slurp_extended_name_table bfd_false
+#define xcoff_construct_extended_name_table \
+ ((boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
+ bfd_false)
+#define xcoff_truncate_arname bfd_dont_truncate_arname
+
+/* We can use the standard get_elt_at_index routine. */
+
+#define xcoff_get_elt_at_index _bfd_generic_get_elt_at_index
+
+/* XCOFF archives do not have a timestamp. */
+
+#define xcoff_update_armap_timestamp bfd_true
+
+/* Read in the armap of an XCOFF archive. */
+
+static boolean
+xcoff_slurp_armap (abfd)
+ bfd *abfd;
+{
+ file_ptr off;
+ struct xcoff_ar_hdr hdr;
+ size_t namlen;
+ bfd_size_type sz;
+ bfd_byte *contents, *cend;
+ unsigned int c, i;
+ carsym *arsym;
+ bfd_byte *p;
+
+ if (xcoff_ardata (abfd) == NULL)
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ off = strtol (xcoff_ardata (abfd)->symoff, (char **) NULL, 10);
+ if (off == 0)
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ if (bfd_seek (abfd, off, SEEK_SET) != 0)
+ return false;
+
+ /* The symbol table starts with a normal archive header. */
+ if (bfd_read ((PTR) &hdr, SIZEOF_AR_HDR, 1, abfd) != SIZEOF_AR_HDR)
+ return false;
+
+ /* Skip the name (normally empty). */
+ namlen = strtol (hdr.namlen, (char **) NULL, 10);
+ if (bfd_seek (abfd, ((namlen + 1) & ~1) + SXCOFFARFMAG, SEEK_CUR) != 0)
+ return false;
+
+ /* Read in the entire symbol table. */
+ sz = strtol (hdr.size, (char **) NULL, 10);
+ contents = (bfd_byte *) bfd_alloc (abfd, sz);
+ if (contents == NULL)
+ return false;
+ if (bfd_read ((PTR) contents, 1, sz, abfd) != sz)
+ return false;
+
+ /* The symbol table starts with a four byte count. */
+ c = bfd_h_get_32 (abfd, contents);
+
+ if (c * 4 >= sz)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ bfd_ardata (abfd)->symdefs = ((carsym *)
+ bfd_alloc (abfd, c * sizeof (carsym)));
+ if (bfd_ardata (abfd)->symdefs == NULL)
+ return false;
+
+ /* After the count comes a list of four byte file offsets. */
+ for (i = 0, arsym = bfd_ardata (abfd)->symdefs, p = contents + 4;
+ i < c;
+ ++i, ++arsym, p += 4)
+ arsym->file_offset = bfd_h_get_32 (abfd, p);
+
+ /* After the file offsets come null terminated symbol names. */
+ cend = contents + sz;
+ for (i = 0, arsym = bfd_ardata (abfd)->symdefs;
+ i < c;
+ ++i, ++arsym, p += strlen ((char *) p) + 1)
+ {
+ if (p >= cend)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ arsym->name = (char *) p;
+ }
+
+ bfd_ardata (abfd)->symdef_count = c;
+ bfd_has_map (abfd) = true;
+
+ return true;
+}
+
+/* See if this is an XCOFF archive. */
+
+static const bfd_target *
+xcoff_archive_p (abfd)
+ bfd *abfd;
+{
+ struct xcoff_ar_file_hdr hdr;
+
+ if (bfd_read ((PTR) &hdr, SIZEOF_AR_FILE_HDR, 1, abfd)
+ != SIZEOF_AR_FILE_HDR)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (strncmp (hdr.magic, XCOFFARMAG, SXCOFFARMAG) != 0)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* 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));
+
+ if (bfd_ardata (abfd) == (struct artdata *) NULL)
+ return NULL;
+
+ bfd_ardata (abfd)->first_file_filepos = strtol (hdr.firstmemoff,
+ (char **) NULL, 10);
+ 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 = bfd_zalloc (abfd, SIZEOF_AR_FILE_HDR);
+ if (bfd_ardata (abfd)->tdata == NULL)
+ return NULL;
+
+ memcpy (bfd_ardata (abfd)->tdata, &hdr, SIZEOF_AR_FILE_HDR);
+
+ if (! xcoff_slurp_armap (abfd))
+ {
+ bfd_release (abfd, bfd_ardata (abfd));
+ abfd->tdata.aout_ar_data = (struct artdata *) NULL;
+ return NULL;
+ }
+
+ return abfd->xvec;
+}
+
+/* Read the archive header in an XCOFF archive. */
+
+static PTR
+xcoff_read_ar_hdr (abfd)
+ bfd *abfd;
+{
+ struct xcoff_ar_hdr hdr;
+ size_t namlen;
+ struct xcoff_ar_hdr *hdrp;
+ struct areltdata *ret;
+
+ if (bfd_read ((PTR) &hdr, SIZEOF_AR_HDR, 1, abfd) != SIZEOF_AR_HDR)
+ return NULL;
+
+ namlen = strtol (hdr.namlen, (char **) NULL, 10);
+ hdrp = bfd_alloc (abfd, SIZEOF_AR_HDR + namlen + 1);
+ if (hdrp == NULL)
+ return NULL;
+ memcpy (hdrp, &hdr, SIZEOF_AR_HDR);
+ if (bfd_read ((char *) hdrp + SIZEOF_AR_HDR, 1, namlen, abfd) != namlen)
+ return NULL;
+ ((char *) hdrp)[SIZEOF_AR_HDR + namlen] = '\0';
+
+ ret = (struct areltdata *) bfd_alloc (abfd, sizeof (struct areltdata));
+ if (ret == NULL)
+ return NULL;
+ ret->arch_header = (char *) hdrp;
+ ret->parsed_size = strtol (hdr.size, (char **) NULL, 10);
+ ret->filename = (char *) hdrp + SIZEOF_AR_HDR;
+
+ /* Skip over the XCOFFARFMAG at the end of the file name. */
+ if (bfd_seek (abfd, (namlen & 1) + SXCOFFARFMAG, SEEK_CUR) != 0)
+ return NULL;
+
+ return (PTR) ret;
+}
+
+/* Open the next element in an XCOFF archive. */
+
+static bfd *
+xcoff_openr_next_archived_file (archive, last_file)
+ bfd *archive;
+ bfd *last_file;
+{
+ file_ptr filestart;
+
+ if (xcoff_ardata (archive) == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
+ if (last_file == NULL)
+ filestart = bfd_ardata (archive)->first_file_filepos;
+ else
+ filestart = strtol (arch_xhdr (last_file)->nextoff, (char **) NULL, 10);
+
+ if (filestart == 0
+ || filestart == strtol (xcoff_ardata (archive)->memoff,
+ (char **) NULL, 10)
+ || filestart == strtol (xcoff_ardata (archive)->symoff,
+ (char **) NULL, 10))
+ {
+ bfd_set_error (bfd_error_no_more_archived_files);
+ return NULL;
+ }
+
+ return _bfd_get_elt_at_filepos (archive, filestart);
+}
+
+/* Stat an element in an XCOFF archive. */
+
+static int
+xcoff_generic_stat_arch_elt (abfd, s)
+ bfd *abfd;
+ struct stat *s;
+{
+ struct xcoff_ar_hdr *hdrp;
+
+ if (abfd->arelt_data == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+
+ hdrp = arch_xhdr (abfd);
+
+ s->st_mtime = strtol (hdrp->date, (char **) NULL, 10);
+ s->st_uid = strtol (hdrp->uid, (char **) NULL, 10);
+ s->st_gid = strtol (hdrp->gid, (char **) NULL, 10);
+ s->st_mode = strtol (hdrp->mode, (char **) NULL, 8);
+ s->st_size = arch_eltdata (abfd)->parsed_size;
+
+ return 0;
+}
+
+/* Normalize a file name for inclusion in an archive. */
+
+static const char *
+normalize_filename (abfd)
+ bfd *abfd;
+{
+ const char *file;
+ const char *filename;
+
+ file = bfd_get_filename (abfd);
+ filename = strrchr (file, '/');
+ if (filename != NULL)
+ filename++;
+ else
+ filename = file;
+ return filename;
+}
+
+/* Write out an XCOFF armap. */
+
+/*ARGSUSED*/
+static boolean
+xcoff_write_armap (abfd, elength, map, orl_count, stridx)
+ bfd *abfd;
+ unsigned int elength;
+ struct orl *map;
+ unsigned int orl_count;
+ int stridx;
+{
+ struct xcoff_ar_hdr hdr;
+ char *p;
+ unsigned char buf[4];
+ bfd *sub;
+ file_ptr fileoff;
+ unsigned int i;
+
+ memset (&hdr, 0, sizeof hdr);
+ sprintf (hdr.size, "%ld", (long) (4 + orl_count * 4 + stridx));
+ sprintf (hdr.nextoff, "%d", 0);
+ memcpy (hdr.prevoff, xcoff_ardata (abfd)->memoff, 12);
+ sprintf (hdr.date, "%d", 0);
+ sprintf (hdr.uid, "%d", 0);
+ sprintf (hdr.gid, "%d", 0);
+ sprintf (hdr.mode, "%d", 0);
+ sprintf (hdr.namlen, "%d", 0);
+
+ /* We need spaces, not null bytes, in the header. */
+ for (p = (char *) &hdr; p < (char *) &hdr + SIZEOF_AR_HDR; p++)
+ if (*p == '\0')
+ *p = ' ';
+
+ if (bfd_write ((PTR) &hdr, SIZEOF_AR_HDR, 1, abfd) != SIZEOF_AR_HDR
+ || bfd_write (XCOFFARFMAG, 1, SXCOFFARFMAG, abfd) != SXCOFFARFMAG)
+ return false;
+
+ bfd_h_put_32 (abfd, orl_count, buf);
+ if (bfd_write (buf, 1, 4, abfd) != 4)
+ return false;
+
+ sub = abfd->archive_head;
+ fileoff = SIZEOF_AR_FILE_HDR;
+ i = 0;
+ while (sub != NULL && i < orl_count)
+ {
+ size_t namlen;
+
+ while (((bfd *) (map[i]).pos) == sub)
+ {
+ bfd_h_put_32 (abfd, fileoff, buf);
+ if (bfd_write (buf, 1, 4, abfd) != 4)
+ return false;
+ ++i;
+ }
+ namlen = strlen (normalize_filename (sub));
+ namlen = (namlen + 1) &~ 1;
+ fileoff += (SIZEOF_AR_HDR
+ + namlen
+ + SXCOFFARFMAG
+ + arelt_size (sub));
+ fileoff = (fileoff + 1) &~ 1;
+ sub = sub->next;
+ }
+
+ for (i = 0; i < orl_count; i++)
+ {
+ const char *name;
+ size_t namlen;
+
+ name = *map[i].name;
+ namlen = strlen (name);
+ if (bfd_write (name, 1, namlen + 1, abfd) != namlen + 1)
+ return false;
+ }
+
+ if ((stridx & 1) != 0)
+ {
+ char b;
+
+ b = '\0';
+ if (bfd_write (&b, 1, 1, abfd) != 1)
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out an XCOFF archive. We always write an entire archive,
+ rather than fussing with the freelist and so forth. */
+
+static boolean
+xcoff_write_archive_contents (abfd)
+ bfd *abfd;
+{
+ struct xcoff_ar_file_hdr fhdr;
+ size_t count;
+ size_t total_namlen;
+ file_ptr *offsets;
+ boolean makemap;
+ boolean hasobjects;
+ file_ptr prevoff, nextoff;
+ bfd *sub;
+ unsigned int i;
+ struct xcoff_ar_hdr ahdr;
+ bfd_size_type size;
+ char *p;
+ char decbuf[13];
+
+ memset (&fhdr, 0, sizeof fhdr);
+ strncpy (fhdr.magic, XCOFFARMAG, SXCOFFARMAG);
+ sprintf (fhdr.firstmemoff, "%d", SIZEOF_AR_FILE_HDR);
+ sprintf (fhdr.freeoff, "%d", 0);
+
+ count = 0;
+ total_namlen = 0;
+ for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
+ {
+ ++count;
+ total_namlen += strlen (normalize_filename (sub)) + 1;
+ }
+ offsets = (file_ptr *) bfd_alloc (abfd, count * sizeof (file_ptr));
+ if (offsets == NULL)
+ return false;
+
+ if (bfd_seek (abfd, SIZEOF_AR_FILE_HDR, SEEK_SET) != 0)
+ return false;
+
+ makemap = bfd_has_map (abfd);
+ hasobjects = false;
+ prevoff = 0;
+ nextoff = SIZEOF_AR_FILE_HDR;
+ for (sub = abfd->archive_head, i = 0; sub != NULL; sub = sub->next, i++)
+ {
+ const char *name;
+ size_t namlen;
+ struct xcoff_ar_hdr *ahdrp;
+ bfd_size_type remaining;
+
+ if (makemap && ! hasobjects)
+ {
+ if (bfd_check_format (sub, bfd_object))
+ hasobjects = true;
+ }
+
+ name = normalize_filename (sub);
+ namlen = strlen (name);
+
+ if (sub->arelt_data != NULL)
+ ahdrp = arch_xhdr (sub);
+ else
+ ahdrp = NULL;
+
+ if (ahdrp == NULL)
+ {
+ struct stat s;
+
+ memset (&ahdr, 0, sizeof ahdr);
+ ahdrp = &ahdr;
+ if (stat (bfd_get_filename (sub), &s) != 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return false;
+ }
+
+ sprintf (ahdrp->size, "%ld", (long) s.st_size);
+ sprintf (ahdrp->date, "%ld", (long) s.st_mtime);
+ sprintf (ahdrp->uid, "%ld", (long) s.st_uid);
+ sprintf (ahdrp->gid, "%ld", (long) s.st_gid);
+ sprintf (ahdrp->mode, "%o", (unsigned int) s.st_mode);
+
+ if (sub->arelt_data == NULL)
+ {
+ sub->arelt_data = ((struct areltdata *)
+ bfd_alloc (sub, sizeof (struct areltdata)));
+ if (sub->arelt_data == NULL)
+ return false;
+ }
+
+ arch_eltdata (sub)->parsed_size = s.st_size;
+ }
+
+ sprintf (ahdrp->prevoff, "%ld", (long) prevoff);
+ sprintf (ahdrp->namlen, "%ld", (long) namlen);
+
+ /* If the length of the name is odd, we write out the null byte
+ after the name as well. */
+ namlen = (namlen + 1) &~ 1;
+
+ remaining = arelt_size (sub);
+ size = (SIZEOF_AR_HDR
+ + namlen
+ + SXCOFFARFMAG
+ + remaining);
+
+ BFD_ASSERT (nextoff == bfd_tell (abfd));
+
+ offsets[i] = nextoff;
+
+ prevoff = nextoff;
+ nextoff += size + (size & 1);
+
+ sprintf (ahdrp->nextoff, "%ld", (long) nextoff);
+
+ /* We need spaces, not null bytes, in the header. */
+ for (p = (char *) ahdrp; p < (char *) ahdrp + SIZEOF_AR_HDR; p++)
+ if (*p == '\0')
+ *p = ' ';
+
+ if (bfd_write ((PTR) ahdrp, 1, SIZEOF_AR_HDR, abfd) != SIZEOF_AR_HDR
+ || bfd_write ((PTR) name, 1, namlen, abfd) != namlen
+ || (bfd_write ((PTR) XCOFFARFMAG, 1, SXCOFFARFMAG, abfd)
+ != SXCOFFARFMAG))
+ return false;
+
+ if (bfd_seek (sub, (file_ptr) 0, SEEK_SET) != 0)
+ return false;
+ while (remaining != 0)
+ {
+ bfd_size_type amt;
+ bfd_byte buffer[DEFAULT_BUFFERSIZE];
+
+ amt = sizeof buffer;
+ if (amt > remaining)
+ amt = remaining;
+ if (bfd_read (buffer, 1, amt, sub) != amt
+ || bfd_write (buffer, 1, amt, abfd) != amt)
+ return false;
+ remaining -= amt;
+ }
+
+ if ((size & 1) != 0)
+ {
+ bfd_byte b;
+
+ b = '\0';
+ if (bfd_write (&b, 1, 1, abfd) != 1)
+ return false;
+ }
+ }
+
+ sprintf (fhdr.lastmemoff, "%ld", (long) prevoff);
+
+ /* Write out the member table. */
+
+ BFD_ASSERT (nextoff == bfd_tell (abfd));
+ sprintf (fhdr.memoff, "%ld", (long) nextoff);
+
+ memset (&ahdr, 0, sizeof ahdr);
+ sprintf (ahdr.size, "%ld", (long) (12 + count * 12 + total_namlen));
+ sprintf (ahdr.prevoff, "%ld", (long) prevoff);
+ sprintf (ahdr.date, "%d", 0);
+ sprintf (ahdr.uid, "%d", 0);
+ sprintf (ahdr.gid, "%d", 0);
+ sprintf (ahdr.mode, "%d", 0);
+ sprintf (ahdr.namlen, "%d", 0);
+
+ size = (SIZEOF_AR_HDR
+ + 12
+ + count * 12
+ + total_namlen
+ + SXCOFFARFMAG);
+
+ prevoff = nextoff;
+ nextoff += size + (size & 1);
+
+ if (makemap && hasobjects)
+ sprintf (ahdr.nextoff, "%ld", (long) nextoff);
+ else
+ sprintf (ahdr.nextoff, "%d", 0);
+
+ /* We need spaces, not null bytes, in the header. */
+ for (p = (char *) &ahdr; p < (char *) &ahdr + SIZEOF_AR_HDR; p++)
+ if (*p == '\0')
+ *p = ' ';
+
+ if (bfd_write ((PTR) &ahdr, 1, SIZEOF_AR_HDR, abfd) != SIZEOF_AR_HDR
+ || (bfd_write ((PTR) XCOFFARFMAG, 1, SXCOFFARFMAG, abfd)
+ != SXCOFFARFMAG))
+ return false;
+
+ sprintf (decbuf, "%-12ld", (long) count);
+ if (bfd_write ((PTR) decbuf, 1, 12, abfd) != 12)
+ return false;
+ for (i = 0; i < count; i++)
+ {
+ sprintf (decbuf, "%-12ld", (long) offsets[i]);
+ if (bfd_write ((PTR) decbuf, 1, 12, abfd) != 12)
+ return false;
+ }
+ for (sub = abfd->archive_head; sub != NULL; sub = sub->next)
+ {
+ const char *name;
+ size_t namlen;
+
+ name = normalize_filename (sub);
+ namlen = strlen (name);
+ if (bfd_write ((PTR) name, 1, namlen + 1, abfd) != namlen + 1)
+ return false;
+ }
+ if ((size & 1) != 0)
+ {
+ bfd_byte b;
+
+ b = '\0';
+ if (bfd_write ((PTR) &b, 1, 1, abfd) != 1)
+ return false;
+ }
+
+ /* Write out the armap, if appropriate. */
+
+ if (! makemap || ! hasobjects)
+ sprintf (fhdr.symoff, "%d", 0);
+ else
+ {
+ BFD_ASSERT (nextoff == bfd_tell (abfd));
+ sprintf (fhdr.symoff, "%ld", (long) nextoff);
+ bfd_ardata (abfd)->tdata = (PTR) &fhdr;
+ if (! _bfd_compute_and_write_armap (abfd, 0))
+ return false;
+ }
+
+ /* Write out the archive file header. */
+
+ /* We need spaces, not null bytes, in the header. */
+ for (p = (char *) &fhdr; p < (char *) &fhdr + SIZEOF_AR_FILE_HDR; p++)
+ if (*p == '\0')
+ *p = ' ';
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || (bfd_write ((PTR) &fhdr, SIZEOF_AR_FILE_HDR, 1, abfd) !=
+ SIZEOF_AR_FILE_HDR))
+ return false;
+
+ return true;
+}
+
+/* We can't use the usual coff_sizeof_headers routine, because AIX
+ always uses an a.out header. */
+
+/*ARGSUSED*/
+static int
+_bfd_xcoff_sizeof_headers (abfd, reloc)
+ bfd *abfd;
+ boolean reloc;
+{
+ int size;
+
+ size = FILHSZ;
+ if (xcoff_data (abfd)->full_aouthdr)
+ size += AOUTSZ;
+ else
+ size += SMALL_AOUTSZ;
+ size += abfd->section_count * SCNHSZ;
+ return size;
+}
+
+#define CORE_FILE_P _bfd_dummy_target
+
+#define coff_core_file_failing_command _bfd_nocore_core_file_failing_command
+#define coff_core_file_failing_signal _bfd_nocore_core_file_failing_signal
+#define coff_core_file_matches_executable_p \
+ _bfd_nocore_core_file_matches_executable_p
+
+#ifdef AIX_CORE
+#undef CORE_FILE_P
+#define CORE_FILE_P rs6000coff_core_p
+extern const bfd_target * rs6000coff_core_p ();
+extern boolean rs6000coff_get_section_contents ();
+extern boolean rs6000coff_core_file_matches_executable_p ();
+
+#undef coff_core_file_matches_executable_p
+#define coff_core_file_matches_executable_p \
+ rs6000coff_core_file_matches_executable_p
+
+extern char *rs6000coff_core_file_failing_command PARAMS ((bfd *abfd));
+#undef coff_core_file_failing_command
+#define coff_core_file_failing_command rs6000coff_core_file_failing_command
+
+extern int rs6000coff_core_file_failing_signal PARAMS ((bfd *abfd));
+#undef coff_core_file_failing_signal
+#define coff_core_file_failing_signal rs6000coff_core_file_failing_signal
+
+#undef coff_get_section_contents
+#define coff_get_section_contents rs6000coff_get_section_contents
+#endif /* AIX_CORE */
+
+#ifdef LYNX_CORE
+
+#undef CORE_FILE_P
+#define CORE_FILE_P lynx_core_file_p
+extern const bfd_target *lynx_core_file_p PARAMS ((bfd *abfd));
+
+extern boolean lynx_core_file_matches_executable_p PARAMS ((bfd *core_bfd,
+ bfd *exec_bfd));
+#undef coff_core_file_matches_executable_p
+#define coff_core_file_matches_executable_p lynx_core_file_matches_executable_p
+
+extern char *lynx_core_file_failing_command PARAMS ((bfd *abfd));
+#undef coff_core_file_failing_command
+#define coff_core_file_failing_command lynx_core_file_failing_command
+
+extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd));
+#undef coff_core_file_failing_signal
+#define coff_core_file_failing_signal lynx_core_file_failing_signal
+
+#endif /* LYNX_CORE */
+
+#define _bfd_xcoff_bfd_get_relocated_section_contents \
+ coff_bfd_get_relocated_section_contents
+#define _bfd_xcoff_bfd_relax_section coff_bfd_relax_section
+#define _bfd_xcoff_bfd_link_split_section coff_bfd_link_split_section
+
+/* The transfer vector that leads the outside world to all of the above. */
+
+const bfd_target
+#ifdef TARGET_SYM
+ TARGET_SYM =
+#else
+ rs6000coff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+ TARGET_NAME,
+#else
+ "aixcoff-rs6000", /* name */
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG | DYNAMIC |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen??? FIXMEmgo */
+
+ 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, coff_object_p, /* bfd_check_format */
+ xcoff_archive_p, CORE_FILE_P},
+ {bfd_false, coff_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ xcoff_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (coff),
+ BFD_JUMP_TABLE_ARCHIVE (xcoff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (_bfd_xcoff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-sh.c b/contrib/gdb/bfd/coff-sh.c
new file mode 100644
index 0000000..17bb4b1
--- /dev/null
+++ b/contrib/gdb/bfd/coff-sh.c
@@ -0,0 +1,1525 @@
+/* BFD back-end for Hitachi Super-H COFF binaries.
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ Written by Steve Chamberlain, <sac@cygnus.com>.
+ Relaxing code written by Ian Lance Taylor, <ian@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "obstack.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "coff/sh.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+/* Internal functions. */
+static bfd_reloc_status_type sh_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static long get_symbol_value PARAMS ((asymbol *));
+static boolean sh_relax_section
+ PARAMS ((bfd *, asection *, struct bfd_link_info *, boolean *));
+static boolean sh_relax_delete_bytes
+ PARAMS ((bfd *, asection *, bfd_vma, int));
+static boolean sh_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
+static bfd_byte *sh_coff_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, asymbol **));
+
+/* Default section alignment to 2**2. */
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
+
+/* Generate long file names. */
+#define COFF_LONG_FILENAMES
+
+/* The supported relocations. There are a lot of relocations defined
+ in coff/internal.h which we do not expect to ever see. */
+static reloc_howto_type sh_coff_howtos[] =
+{
+ { 0 },
+ { 1 },
+ { 2 },
+ { 3 }, /* R_SH_PCREL8 */
+ { 4 }, /* R_SH_PCREL16 */
+ { 5 }, /* R_SH_HIGH8 */
+ { 6 }, /* R_SH_IMM24 */
+ { 7 }, /* R_SH_LOW16 */
+ { 8 },
+ { 9 }, /* R_SH_PCDISP8BY4 */
+
+ HOWTO (R_SH_PCDISP8BY2, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_pcdisp8by2", /* name */
+ true, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ { 11 }, /* R_SH_PCDISP8 */
+
+ HOWTO (R_SH_PCDISP, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_pcdisp12by2", /* name */
+ true, /* partial_inplace */
+ 0xfff, /* src_mask */
+ 0xfff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ { 13 },
+
+ HOWTO (R_SH_IMM32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_imm32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 15 },
+ { 16 }, /* R_SH_IMM8 */
+ { 17 }, /* R_SH_IMM8BY2 */
+ { 18 }, /* R_SH_IMM8BY4 */
+ { 19 }, /* R_SH_IMM4 */
+ { 20 }, /* R_SH_IMM4BY2 */
+ { 21 }, /* R_SH_IMM4BY4 */
+
+ HOWTO (R_SH_PCRELIMM8BY2, /* type */
+ 1, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_pcrelimm8by2", /* name */
+ true, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_SH_PCRELIMM8BY4, /* type */
+ 2, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_pcrelimm8by4", /* name */
+ true, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ HOWTO (R_SH_IMM16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_imm16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_SH_SWITCH16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_switch16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_SH_SWITCH32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_switch32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_SH_USES, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_uses", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_SH_COUNT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_count", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ HOWTO (R_SH_ALIGN, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ sh_reloc, /* special_function */
+ "r_align", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+#define SH_COFF_HOWTO_COUNT (sizeof sh_coff_howtos / sizeof sh_coff_howtos[0])
+
+/* Check for a bad magic number. */
+#define BADMAG(x) SHBADMAG(x)
+
+/* Customize coffcode.h (this is not currently used). */
+#define SH 1
+
+/* FIXME: This should not be set here. */
+#define __A_MAGIC_SET__
+
+/* Swap the r_offset field in and out. */
+#define SWAP_IN_RELOC_OFFSET bfd_h_get_32
+#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
+
+/* Swap out extra information in the reloc structure. */
+#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
+ do \
+ { \
+ dst->r_stuff[0] = 'S'; \
+ dst->r_stuff[1] = 'C'; \
+ } \
+ while (0)
+
+/* Get the value of a symbol, when performing a relocation. */
+
+static long
+get_symbol_value (symbol)
+ asymbol *symbol;
+{
+ bfd_vma relocation;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = (symbol->value +
+ symbol->section->output_section->vma +
+ symbol->section->output_offset);
+
+ return relocation;
+}
+
+/* This macro is used in coffcode.h to get the howto corresponding to
+ an internal reloc. */
+
+#define RTYPE2HOWTO(relent, internal) \
+ ((relent)->howto = \
+ ((internal)->r_type < SH_COFF_HOWTO_COUNT \
+ ? &sh_coff_howtos[(internal)->r_type] \
+ : (reloc_howto_type *) NULL))
+
+/* This is the same as the macro in coffcode.h, except that it copies
+ r_offset into reloc_entry->addend for some relocs. */
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = 0; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ if ((reloc).r_type == R_SH_SWITCH16 \
+ || (reloc).r_type == R_SH_SWITCH32 \
+ || (reloc).r_type == R_SH_USES \
+ || (reloc).r_type == R_SH_COUNT \
+ || (reloc).r_type == R_SH_ALIGN) \
+ cache_ptr->addend = (reloc).r_offset; \
+ }
+
+/* This is the howto function for the SH relocations. */
+
+static bfd_reloc_status_type
+sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol_in;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ unsigned long insn;
+ bfd_vma sym_value;
+ unsigned short r_type;
+ bfd_vma addr = reloc_entry->address;
+ bfd_byte *hit_data = addr + (bfd_byte *) data;
+
+ r_type = reloc_entry->howto->type;
+
+ if (output_bfd != NULL)
+ {
+ /* Partial linking--do nothing. */
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* Almost all relocs have to do with relaxing. If any work must be
+ done for them, it has been done in sh_relax_section. */
+ if (r_type != R_SH_IMM32
+ && (r_type != R_SH_PCDISP
+ || (symbol_in->flags & BSF_LOCAL) != 0))
+ return bfd_reloc_ok;
+
+ if (symbol_in != NULL
+ && bfd_is_und_section (symbol_in->section))
+ return bfd_reloc_undefined;
+
+ sym_value = get_symbol_value (symbol_in);
+
+ switch (r_type)
+ {
+ case R_SH_IMM32:
+ insn = bfd_get_32 (abfd, hit_data);
+ insn += sym_value + reloc_entry->addend;
+ bfd_put_32 (abfd, insn, hit_data);
+ break;
+ case R_SH_PCDISP:
+ insn = bfd_get_16 (abfd, hit_data);
+ sym_value += reloc_entry->addend;
+ sym_value -= (input_section->output_section->vma
+ + input_section->output_offset
+ + addr
+ + 4);
+ sym_value += (insn & 0xfff) << 1;
+ if (insn & 0x800)
+ sym_value -= 0x1000;
+ insn = (insn & 0xf000) | (sym_value & 0xfff);
+ bfd_put_16 (abfd, insn, hit_data);
+ if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000)
+ return bfd_reloc_overflow;
+ break;
+ default:
+ abort ();
+ break;
+ }
+
+ return bfd_reloc_ok;
+}
+
+/* We can do relaxing. */
+#define coff_bfd_relax_section sh_relax_section
+
+/* We use the special COFF backend linker. */
+#define coff_relocate_section sh_relocate_section
+
+/* When relaxing, we need to use special code to get the relocated
+ section contents. */
+#define coff_bfd_get_relocated_section_contents \
+ sh_coff_get_relocated_section_contents
+
+#include "coffcode.h"
+
+/* This function handles relaxing on the SH.
+
+ Function calls on the SH look like this:
+
+ movl L1,r0
+ ...
+ jsr @r0
+ ...
+ L1:
+ .long function
+
+ The compiler and assembler will cooperate to create R_SH_USES
+ relocs on the jsr instructions. The r_offset field of the
+ R_SH_USES reloc is the PC relative offset to the instruction which
+ loads the register (the r_offset field is computed as though it
+ were a jump instruction, so the offset value is actually from four
+ bytes past the instruction). The linker can use this reloc to
+ determine just which function is being called, and thus decide
+ whether it is possible to replace the jsr with a bsr.
+
+ If multiple function calls are all based on a single register load
+ (i.e., the same function is called multiple times), the compiler
+ guarantees that each function call will have an R_SH_USES reloc.
+ Therefore, if the linker is able to convert each R_SH_USES reloc
+ which refers to that address, it can safely eliminate the register
+ load.
+
+ When the assembler creates an R_SH_USES reloc, it examines it to
+ determine which address is being loaded (L1 in the above example).
+ It then counts the number of references to that address, and
+ creates an R_SH_COUNT reloc at that address. The r_offset field of
+ the R_SH_COUNT reloc will be the number of references. If the
+ linker is able to eliminate a register load, it can use the
+ R_SH_COUNT reloc to see whether it can also eliminate the function
+ address. */
+
+static boolean
+sh_relax_section (abfd, sec, link_info, again)
+ bfd *abfd;
+ asection *sec;
+ struct bfd_link_info *link_info;
+ boolean *again;
+{
+ struct internal_reloc *internal_relocs;
+ struct internal_reloc *free_relocs = NULL;
+ struct internal_reloc *irel, *irelend;
+ bfd_byte *contents = NULL;
+ bfd_byte *free_contents = NULL;
+
+ *again = false;
+
+ if (link_info->relocateable
+ || (sec->flags & SEC_RELOC) == 0
+ || sec->reloc_count == 0)
+ return true;
+
+ /* If this is the first time we have been called for this section,
+ initialize the cooked size. */
+ if (sec->_cooked_size == 0)
+ sec->_cooked_size = sec->_raw_size;
+
+ internal_relocs = (_bfd_coff_read_internal_relocs
+ (abfd, sec, link_info->keep_memory,
+ (bfd_byte *) NULL, false,
+ (struct internal_reloc *) NULL));
+ if (internal_relocs == NULL)
+ goto error_return;
+ if (! link_info->keep_memory)
+ free_relocs = internal_relocs;
+
+ irelend = internal_relocs + sec->reloc_count;
+ for (irel = internal_relocs; irel < irelend; irel++)
+ {
+ bfd_vma laddr, paddr, symval;
+ unsigned short insn;
+ struct internal_reloc *irelfn, *irelscan, *irelcount;
+ struct internal_syment sym;
+ bfd_signed_vma foff;
+
+ if (irel->r_type != R_SH_USES)
+ continue;
+
+ /* Get the section contents. */
+ if (contents == NULL)
+ {
+ if (coff_section_data (abfd, sec) != NULL
+ && coff_section_data (abfd, sec)->contents != NULL)
+ contents = coff_section_data (abfd, sec)->contents;
+ else
+ {
+ contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
+ if (contents == NULL)
+ goto error_return;
+ free_contents = contents;
+
+ if (! bfd_get_section_contents (abfd, sec, contents,
+ (file_ptr) 0, sec->_raw_size))
+ goto error_return;
+ }
+ }
+
+ /* The r_offset field of the R_SH_USES reloc will point us to
+ the register load. The 4 is because the r_offset field is
+ computed as though it were a jump offset, which are based
+ from 4 bytes after the jump instruction. */
+ laddr = irel->r_vaddr - sec->vma + 4 + irel->r_offset;
+ if (laddr >= sec->_raw_size)
+ {
+ (*_bfd_error_handler) ("%s: 0x%lx: warning: bad R_SH_USES offset",
+ bfd_get_filename (abfd),
+ (unsigned long) irel->r_vaddr);
+ continue;
+ }
+ insn = bfd_get_16 (abfd, contents + laddr);
+
+ /* If the instruction is not mov.l NN,rN, we don't know what to
+ do. */
+ if ((insn & 0xf000) != 0xd000)
+ {
+ ((*_bfd_error_handler)
+ ("%s: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x",
+ bfd_get_filename (abfd), (unsigned long) irel->r_vaddr, insn));
+ continue;
+ }
+
+ /* Get the address from which the register is being loaded. The
+ displacement in the mov.l instruction is quadrupled. It is a
+ displacement from four bytes after the movl instruction, but,
+ before adding in the PC address, two least significant bits
+ of the PC are cleared. We assume that the section is aligned
+ on a four byte boundary. */
+ paddr = insn & 0xff;
+ paddr *= 4;
+ paddr += (laddr + 4) &~ 3;
+ if (paddr >= sec->_raw_size)
+ {
+ ((*_bfd_error_handler)
+ ("%s: 0x%lx: warning: bad R_SH_USES load offset",
+ bfd_get_filename (abfd), (unsigned long) irel->r_vaddr));
+ continue;
+ }
+
+ /* Get the reloc for the address from which the register is
+ being loaded. This reloc will tell us which function is
+ actually being called. */
+ paddr += sec->vma;
+ for (irelfn = internal_relocs; irelfn < irelend; irelfn++)
+ if (irelfn->r_vaddr == paddr
+ && irelfn->r_type == R_SH_IMM32)
+ break;
+ if (irelfn >= irelend)
+ {
+ ((*_bfd_error_handler)
+ ("%s: 0x%lx: warning: could not find expected reloc",
+ bfd_get_filename (abfd), (unsigned long) paddr));
+ continue;
+ }
+
+ /* Get the value of the symbol referred to by the reloc. */
+ if (! _bfd_coff_get_external_symbols (abfd))
+ goto error_return;
+ bfd_coff_swap_sym_in (abfd,
+ ((bfd_byte *) obj_coff_external_syms (abfd)
+ + (irelfn->r_symndx
+ * bfd_coff_symesz (abfd))),
+ &sym);
+ if (sym.n_scnum != 0 && sym.n_scnum != sec->target_index)
+ {
+ ((*_bfd_error_handler)
+ ("%s: 0x%lx: warning: symbol in unexpected section",
+ bfd_get_filename (abfd), (unsigned long) paddr));
+ continue;
+ }
+
+ if (sym.n_sclass != C_EXT)
+ {
+ symval = (sym.n_value
+ - sec->vma
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else
+ {
+ struct coff_link_hash_entry *h;
+
+ h = obj_coff_sym_hashes (abfd)[irelfn->r_symndx];
+ BFD_ASSERT (h != NULL);
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ {
+ /* This appears to be a reference to an undefined
+ symbol. Just ignore it--it will be caught by the
+ regular reloc processing. */
+ continue;
+ }
+
+ symval = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ }
+
+ symval += bfd_get_32 (abfd, contents + paddr - sec->vma);
+
+ /* See if this function call can be shortened. */
+ foff = (symval
+ - (irel->r_vaddr
+ - sec->vma
+ + sec->output_section->vma
+ + sec->output_offset
+ + 4));
+ if (foff < -0x1000 || foff >= 0x1000)
+ {
+ /* After all that work, we can't shorten this function call. */
+ continue;
+ }
+
+ /* Shorten the function call. */
+
+ /* For simplicity of coding, we are going to modify the section
+ contents, the section relocs, and the BFD symbol table. We
+ must tell the rest of the code not to free up this
+ information. It would be possible to instead create a table
+ of changes which have to be made, as is done in coff-mips.c;
+ that would be more work, but would require less memory when
+ the linker is run. */
+
+ if (coff_section_data (abfd, sec) == NULL)
+ {
+ sec->used_by_bfd =
+ ((PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+ if (sec->used_by_bfd == NULL)
+ goto error_return;
+ }
+
+ coff_section_data (abfd, sec)->relocs = internal_relocs;
+ coff_section_data (abfd, sec)->keep_relocs = true;
+ free_relocs = NULL;
+
+ coff_section_data (abfd, sec)->contents = contents;
+ coff_section_data (abfd, sec)->keep_contents = true;
+ free_contents = NULL;
+
+ obj_coff_keep_syms (abfd) = true;
+
+ /* Replace the jsr with a bsr. */
+
+ /* Change the R_SH_USES reloc into an R_SH_PCDISP reloc, and
+ replace the jsr with a bsr. */
+ irel->r_type = R_SH_PCDISP;
+ irel->r_symndx = irelfn->r_symndx;
+ if (sym.n_sclass != C_EXT)
+ {
+ /* If this needs to be changed because of future relaxing,
+ it will be handled here like other internal PCDISP
+ relocs. */
+ bfd_put_16 (abfd,
+ 0xb000 | ((foff >> 1) & 0xfff),
+ contents + irel->r_vaddr - sec->vma);
+ }
+ else
+ {
+ /* We can't fully resolve this yet, because the external
+ symbol value may be changed by future relaxing. We let
+ the final link phase handle it. */
+ bfd_put_16 (abfd, 0xb000, contents + irel->r_vaddr - sec->vma);
+ }
+
+ /* See if there is another R_SH_USES reloc referring to the same
+ register load. */
+ for (irelscan = internal_relocs; irelscan < irelend; irelscan++)
+ if (irelscan->r_type == R_SH_USES
+ && laddr == irelscan->r_vaddr - sec->vma + 4 + irelscan->r_offset)
+ break;
+ if (irelscan < irelend)
+ {
+ /* Some other function call depends upon this register load,
+ and we have not yet converted that function call.
+ Indeed, we may never be able to convert it. There is
+ nothing else we can do at this point. */
+ continue;
+ }
+
+ /* Look for a R_SH_COUNT reloc on the location where the
+ function address is stored. Do this before deleting any
+ bytes, to avoid confusion about the address. */
+ for (irelcount = internal_relocs; irelcount < irelend; irelcount++)
+ if (irelcount->r_vaddr == paddr
+ && irelcount->r_type == R_SH_COUNT)
+ break;
+
+ /* Delete the register load. */
+ if (! sh_relax_delete_bytes (abfd, sec, laddr, 2))
+ goto error_return;
+
+ /* That will change things, so, just in case it permits some
+ other function call to come within range, we should relax
+ again. Note that this is not required, and it may be slow. */
+ *again = true;
+
+ /* Now check whether we got a COUNT reloc. */
+ if (irelcount >= irelend)
+ {
+ ((*_bfd_error_handler)
+ ("%s: 0x%lx: warning: could not find expected COUNT reloc",
+ bfd_get_filename (abfd), (unsigned long) paddr));
+ continue;
+ }
+
+ /* The number of uses is stored in the r_offset field. We've
+ just deleted one. */
+ if (irelcount->r_offset == 0)
+ {
+ ((*_bfd_error_handler) ("%s: 0x%lx: warning: bad count",
+ bfd_get_filename (abfd),
+ (unsigned long) paddr));
+ continue;
+ }
+
+ --irelcount->r_offset;
+
+ /* If there are no more uses, we can delete the address. Reload
+ the address from irelfn, in case it was changed by the
+ previous call to sh_relax_delete_bytes. */
+ if (irelcount->r_offset == 0)
+ {
+ if (! sh_relax_delete_bytes (abfd, sec,
+ irelfn->r_vaddr - sec->vma, 4))
+ goto error_return;
+ }
+
+ /* We've done all we can with that function call. */
+ }
+
+ if (free_relocs != NULL)
+ {
+ free (free_relocs);
+ free_relocs = NULL;
+ }
+
+ if (free_contents != NULL)
+ {
+ if (! link_info->keep_memory)
+ free (free_contents);
+ else
+ {
+ /* Cache the section contents for coff_link_input_bfd. */
+ if (coff_section_data (abfd, sec) == NULL)
+ {
+ sec->used_by_bfd =
+ ((PTR) bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+ if (sec->used_by_bfd == NULL)
+ goto error_return;
+ coff_section_data (abfd, sec)->relocs = NULL;
+ }
+ coff_section_data (abfd, sec)->contents = contents;
+ }
+ }
+
+ return true;
+
+ error_return:
+ if (free_relocs != NULL)
+ free (free_relocs);
+ if (free_contents != NULL)
+ free (free_contents);
+ return false;
+}
+
+/* Delete some bytes from a section while relaxing. */
+
+static boolean
+sh_relax_delete_bytes (abfd, sec, addr, count)
+ bfd *abfd;
+ asection *sec;
+ bfd_vma addr;
+ int count;
+{
+ bfd_byte *contents;
+ struct internal_reloc *irel, *irelend;
+ struct internal_reloc *irelalign;
+ bfd_vma toaddr;
+ bfd_byte *esym, *esymend;
+ bfd_size_type symesz;
+ struct coff_link_hash_entry **sym_hash;
+ asection *o;
+
+ contents = coff_section_data (abfd, sec)->contents;
+
+ /* The deletion must stop at the next ALIGN reloc for an aligment
+ power larger than the number of bytes we are deleting. */
+
+ irelalign = NULL;
+ toaddr = sec->_cooked_size;
+
+ irel = coff_section_data (abfd, sec)->relocs;
+ irelend = irel + sec->reloc_count;
+ for (; irel < irelend; irel++)
+ {
+ if (irel->r_type == R_SH_ALIGN
+ && irel->r_vaddr - sec->vma > addr
+ && count < (1 << irel->r_offset))
+ {
+ irelalign = irel;
+ toaddr = irel->r_vaddr - sec->vma;
+ break;
+ }
+ }
+
+ /* Actually delete the bytes. */
+ memmove (contents + addr, contents + addr + count, toaddr - addr - count);
+ if (irelalign == NULL)
+ sec->_cooked_size -= count;
+ else
+ memset (contents + toaddr - count, 0, count);
+
+ /* Adjust all the relocs. */
+ for (irel = coff_section_data (abfd, sec)->relocs; irel < irelend; irel++)
+ {
+ bfd_vma nraddr, start, stop;
+ int insn = 0;
+ struct internal_syment sym;
+ int off, adjust, oinsn;
+ bfd_signed_vma voff;
+ boolean overflow;
+
+ /* Get the new reloc address. */
+ nraddr = irel->r_vaddr - sec->vma;
+ if ((irel->r_vaddr - sec->vma > addr
+ && irel->r_vaddr - sec->vma < toaddr)
+ || (irel->r_type == R_SH_ALIGN
+ && irel->r_vaddr - sec->vma == toaddr))
+ nraddr -= count;
+
+ /* See if this reloc was for the bytes we have deleted, in which
+ case we no longer care about it. */
+ if (irel->r_vaddr - sec->vma >= addr
+ && irel->r_vaddr - sec->vma < addr + count
+ && irel->r_type != R_SH_ALIGN)
+ irel->r_type = R_SH_UNUSED;
+
+ /* If this is a PC relative reloc, see if the range it covers
+ includes the bytes we have deleted. */
+ switch (irel->r_type)
+ {
+ default:
+ break;
+
+ case R_SH_PCDISP8BY2:
+ case R_SH_PCDISP:
+ case R_SH_PCRELIMM8BY2:
+ case R_SH_PCRELIMM8BY4:
+ start = irel->r_vaddr - sec->vma;
+ insn = bfd_get_16 (abfd, contents + nraddr);
+ break;
+ }
+
+ switch (irel->r_type)
+ {
+ default:
+ start = stop = addr;
+ break;
+
+ case R_SH_IMM32:
+ /* If this reloc is against a symbol defined in this
+ section, and the symbol will not be adjusted below, we
+ must check the addend to see it will put the value in
+ range to be adjusted, and hence must be changed. */
+ bfd_coff_swap_sym_in (abfd,
+ ((bfd_byte *) obj_coff_external_syms (abfd)
+ + (irel->r_symndx
+ * bfd_coff_symesz (abfd))),
+ &sym);
+ if (sym.n_sclass != C_EXT
+ && sym.n_scnum == sec->target_index
+ && ((bfd_vma) sym.n_value <= addr
+ || (bfd_vma) sym.n_value >= toaddr))
+ {
+ bfd_vma val;
+
+ val = bfd_get_32 (abfd, contents + nraddr);
+ val += sym.n_value;
+ if (val >= addr && val < toaddr)
+ bfd_put_32 (abfd, val - count, contents + nraddr);
+ }
+ start = stop = addr;
+ break;
+
+ case R_SH_PCDISP8BY2:
+ off = insn & 0xff;
+ if (off & 0x80)
+ off -= 0x100;
+ stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
+ break;
+
+ case R_SH_PCDISP:
+ bfd_coff_swap_sym_in (abfd,
+ ((bfd_byte *) obj_coff_external_syms (abfd)
+ + (irel->r_symndx
+ * bfd_coff_symesz (abfd))),
+ &sym);
+ if (sym.n_sclass == C_EXT)
+ start = stop = addr;
+ else
+ {
+ off = insn & 0xfff;
+ if (off & 0x800)
+ off -= 0x1000;
+ stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
+ }
+ break;
+
+ case R_SH_PCRELIMM8BY2:
+ off = insn & 0xff;
+ stop = start + 4 + off * 2;
+ break;
+
+ case R_SH_PCRELIMM8BY4:
+ off = insn & 0xff;
+ stop = (start &~ (bfd_vma) 3) + 4 + off * 4;
+ break;
+
+ case R_SH_SWITCH16:
+ case R_SH_SWITCH32:
+ /* These relocs types represent
+ .word L2-L1
+ The r_offset field holds the difference between the reloc
+ address and L1. That is the start of the reloc, and
+ adding in the contents gives us the top. We must adjust
+ both the r_offset field and the section contents. */
+
+ start = irel->r_vaddr - sec->vma;
+ stop = (bfd_vma) ((bfd_signed_vma) start - (long) irel->r_offset);
+
+ if (start > addr
+ && start < toaddr
+ && (stop <= addr || stop >= toaddr))
+ irel->r_offset += count;
+ else if (stop > addr
+ && stop < toaddr
+ && (start <= addr || start >= toaddr))
+ irel->r_offset -= count;
+
+ start = stop;
+
+ if (irel->r_type == R_SH_SWITCH16)
+ voff = bfd_get_signed_16 (abfd, contents + nraddr);
+ else
+ voff = bfd_get_signed_32 (abfd, contents + nraddr);
+ stop = (bfd_vma) ((bfd_signed_vma) start + voff);
+
+ break;
+
+ case R_SH_USES:
+ start = irel->r_vaddr - sec->vma;
+ stop = (bfd_vma) ((bfd_signed_vma) start
+ + (long) irel->r_offset
+ + 4);
+ break;
+ }
+
+ if (start > addr
+ && start < toaddr
+ && (stop <= addr || stop >= toaddr))
+ adjust = count;
+ else if (stop > addr
+ && stop < toaddr
+ && (start <= addr || start >= toaddr))
+ adjust = - count;
+ else
+ adjust = 0;
+
+ if (adjust != 0)
+ {
+ oinsn = insn;
+ overflow = false;
+ switch (irel->r_type)
+ {
+ default:
+ abort ();
+ break;
+
+ case R_SH_PCDISP8BY2:
+ case R_SH_PCRELIMM8BY2:
+ insn += adjust / 2;
+ if ((oinsn & 0xff00) != (insn & 0xff00))
+ overflow = true;
+ bfd_put_16 (abfd, insn, contents + nraddr);
+ break;
+
+ case R_SH_PCDISP:
+ insn += adjust / 2;
+ if ((oinsn & 0xf000) != (insn & 0xf000))
+ overflow = true;
+ bfd_put_16 (abfd, insn, contents + nraddr);
+ break;
+
+ case R_SH_PCRELIMM8BY4:
+ BFD_ASSERT (adjust == count || count >= 4);
+ if (count >= 4)
+ insn += adjust / 4;
+ else
+ {
+ if ((irel->r_vaddr & 3) == 0)
+ ++insn;
+ }
+ if ((oinsn & 0xff00) != (insn & 0xff00))
+ overflow = true;
+ bfd_put_16 (abfd, insn, contents + nraddr);
+ break;
+
+ case R_SH_SWITCH16:
+ voff += adjust;
+ if (voff < - 0x8000 || voff >= 0x8000)
+ overflow = true;
+ bfd_put_signed_16 (abfd, voff, contents + nraddr);
+ break;
+
+ case R_SH_SWITCH32:
+ voff += adjust;
+ bfd_put_signed_32 (abfd, voff, contents + nraddr);
+ break;
+
+ case R_SH_USES:
+ irel->r_offset += adjust;
+ break;
+ }
+
+ if (overflow)
+ {
+ ((*_bfd_error_handler)
+ ("%s: 0x%lx: fatal: reloc overflow while relaxing",
+ bfd_get_filename (abfd), (unsigned long) irel->r_vaddr));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ }
+
+ irel->r_vaddr = nraddr + sec->vma;
+ }
+
+ /* Look through all the other sections. If there contain any IMM32
+ relocs against internal symbols which we are not going to adjust
+ below, we may need to adjust the addends. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct internal_reloc *internal_relocs;
+ struct internal_reloc *irelscan, *irelscanend;
+ bfd_byte *ocontents;
+
+ if (o == sec
+ || (o->flags & SEC_RELOC) == 0
+ || o->reloc_count == 0)
+ continue;
+
+ /* We always cache the relocs. Perhaps, if info->keep_memory is
+ false, we should free them, if we are permitted to, when we
+ leave sh_coff_relax_section. */
+ internal_relocs = (_bfd_coff_read_internal_relocs
+ (abfd, o, true, (bfd_byte *) NULL, false,
+ (struct internal_reloc *) NULL));
+ if (internal_relocs == NULL)
+ return false;
+
+ ocontents = NULL;
+ irelscanend = internal_relocs + o->reloc_count;
+ for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
+ {
+ struct internal_syment sym;
+
+ if (irelscan->r_type != R_SH_IMM32)
+ continue;
+
+ bfd_coff_swap_sym_in (abfd,
+ ((bfd_byte *) obj_coff_external_syms (abfd)
+ + (irelscan->r_symndx
+ * bfd_coff_symesz (abfd))),
+ &sym);
+ if (sym.n_sclass != C_EXT
+ && sym.n_scnum == sec->target_index
+ && ((bfd_vma) sym.n_value <= addr
+ || (bfd_vma) sym.n_value >= toaddr))
+ {
+ bfd_vma val;
+
+ if (ocontents == NULL)
+ {
+ if (coff_section_data (abfd, o)->contents != NULL)
+ ocontents = coff_section_data (abfd, o)->contents;
+ else
+ {
+ /* We always cache the section contents.
+ Perhaps, if info->keep_memory is false, we
+ should free them, if we are permitted to,
+ when we leave sh_coff_relax_section. */
+ ocontents = (bfd_byte *) bfd_malloc (o->_raw_size);
+ if (ocontents == NULL)
+ return false;
+ if (! bfd_get_section_contents (abfd, o, ocontents,
+ (file_ptr) 0,
+ o->_raw_size))
+ return false;
+ coff_section_data (abfd, o)->contents = ocontents;
+ }
+ }
+
+ val = bfd_get_32 (abfd, ocontents + irelscan->r_vaddr - o->vma);
+ val += sym.n_value;
+ if (val >= addr && val < toaddr)
+ bfd_put_32 (abfd, val - count,
+ ocontents + irelscan->r_vaddr - o->vma);
+
+ coff_section_data (abfd, o)->keep_contents = true;
+ }
+ }
+ }
+
+ /* Adjusting the internal symbols will not work if something has
+ already retrieved the generic symbols. It would be possible to
+ make this work by adjusting the generic symbols at the same time.
+ However, this case should not arise in normal usage. */
+ if (obj_symbols (abfd) != NULL
+ || obj_raw_syments (abfd) != NULL)
+ {
+ ((*_bfd_error_handler)
+ ("%s: fatal: generic symbols retrieved before relaxing",
+ bfd_get_filename (abfd)));
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ /* Adjust all the symbols. */
+ sym_hash = obj_coff_sym_hashes (abfd);
+ symesz = bfd_coff_symesz (abfd);
+ esym = (bfd_byte *) obj_coff_external_syms (abfd);
+ esymend = esym + obj_raw_syment_count (abfd) * symesz;
+ while (esym < esymend)
+ {
+ struct internal_syment isym;
+
+ bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &isym);
+
+ if (isym.n_scnum == sec->target_index
+ && (bfd_vma) isym.n_value > addr
+ && (bfd_vma) isym.n_value < toaddr)
+ {
+ isym.n_value -= count;
+
+ bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
+
+ if (*sym_hash != NULL)
+ {
+ BFD_ASSERT ((*sym_hash)->root.type == bfd_link_hash_defined
+ || (*sym_hash)->root.type == bfd_link_hash_defweak);
+ BFD_ASSERT ((*sym_hash)->root.u.def.value >= addr
+ && (*sym_hash)->root.u.def.value < toaddr);
+ (*sym_hash)->root.u.def.value -= count;
+ }
+ }
+
+ esym += (isym.n_numaux + 1) * symesz;
+ sym_hash += isym.n_numaux + 1;
+ }
+
+ /* See if we can move the ALIGN reloc forward. We have adjusted
+ r_vaddr for it already. */
+ if (irelalign != NULL)
+ {
+ bfd_vma alignaddr;
+
+ alignaddr = BFD_ALIGN (irelalign->r_vaddr - sec->vma,
+ 1 << irelalign->r_offset);
+ if (alignaddr != toaddr)
+ {
+ /* Tail recursion. */
+ return sh_relax_delete_bytes (abfd, sec,
+ irelalign->r_vaddr - sec->vma,
+ 1 << irelalign->r_offset);
+ }
+ }
+
+ return true;
+}
+
+/* This is a modification of _bfd_coff_generic_relocate_section, which
+ will handle SH relaxing. */
+
+static boolean
+sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
+ relocs, syms, sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma addend;
+ bfd_vma val;
+ reloc_howto_type *howto;
+ bfd_reloc_status_type rstat;
+
+ /* Almost all relocs have to do with relaxing. If any work must
+ be done for them, it has been done in sh_relax_section. */
+ if (rel->r_type != R_SH_IMM32
+ && rel->r_type != R_SH_PCDISP)
+ continue;
+
+ symndx = rel->r_symndx;
+
+ if (symndx == -1)
+ {
+ h = NULL;
+ sym = NULL;
+ }
+ else
+ {
+ h = obj_coff_sym_hashes (input_bfd)[symndx];
+ sym = syms + symndx;
+ }
+
+ if (sym != NULL && sym->n_scnum != 0)
+ addend = - sym->n_value;
+ else
+ addend = 0;
+
+ if (rel->r_type == R_SH_PCDISP)
+ addend -= 4;
+
+ if (rel->r_type >= SH_COFF_HOWTO_COUNT)
+ howto = NULL;
+ else
+ howto = &sh_coff_howtos[rel->r_type];
+
+ if (howto == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ val = 0;
+
+ if (h == NULL)
+ {
+ asection *sec;
+
+ /* There is nothing to do for an internal PCDISP reloc. */
+ if (rel->r_type == R_SH_PCDISP)
+ continue;
+
+ if (symndx == -1)
+ {
+ sec = bfd_abs_section_ptr;
+ val = 0;
+ }
+ else
+ {
+ sec = sections[symndx];
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+ }
+ else
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ val = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (! info->relocateable)
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents,
+ rel->r_vaddr - input_section->vma,
+ val, addend);
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.string;
+ else if (sym->_n._n_n._n_zeroes == 0
+ && sym->_n._n_n._n_offset != 0)
+ name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
+ else
+ {
+ strncpy (buf, sym->_n._n_name, SYMNMLEN);
+ buf[SYMNMLEN] = '\0';
+ name = buf;
+ }
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* This is a version of bfd_generic_get_relocated_section_contents
+ which uses sh_relocate_section. */
+
+static bfd_byte *
+sh_coff_get_relocated_section_contents (output_bfd, link_info, link_order,
+ data, relocateable, symbols)
+ bfd *output_bfd;
+ struct bfd_link_info *link_info;
+ struct bfd_link_order *link_order;
+ bfd_byte *data;
+ boolean relocateable;
+ asymbol **symbols;
+{
+ asection *input_section = link_order->u.indirect.section;
+ bfd *input_bfd = input_section->owner;
+ asection **sections = NULL;
+ struct internal_reloc *internal_relocs = NULL;
+ struct internal_syment *internal_syms = NULL;
+
+ /* We only need to handle the case of relaxing, or of having a
+ particular set of section contents, specially. */
+ if (relocateable
+ || coff_section_data (input_bfd, input_section) == NULL
+ || coff_section_data (input_bfd, input_section)->contents == NULL)
+ return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
+ link_order, data,
+ relocateable,
+ symbols);
+
+ memcpy (data, coff_section_data (input_bfd, input_section)->contents,
+ input_section->_raw_size);
+
+ if ((input_section->flags & SEC_RELOC) != 0
+ && input_section->reloc_count > 0)
+ {
+ bfd_size_type symesz = bfd_coff_symesz (input_bfd);
+ bfd_byte *esym, *esymend;
+ struct internal_syment *isymp;
+ asection **secpp;
+
+ if (! _bfd_coff_get_external_symbols (input_bfd))
+ goto error_return;
+
+ internal_relocs = (_bfd_coff_read_internal_relocs
+ (input_bfd, input_section, false, (bfd_byte *) NULL,
+ false, (struct internal_reloc *) NULL));
+ if (internal_relocs == NULL)
+ goto error_return;
+
+ internal_syms = ((struct internal_syment *)
+ bfd_malloc (obj_raw_syment_count (input_bfd)
+ * sizeof (struct internal_syment)));
+ if (internal_syms == NULL)
+ goto error_return;
+
+ sections = (asection **) bfd_malloc (obj_raw_syment_count (input_bfd)
+ * sizeof (asection *));
+ if (sections == NULL)
+ goto error_return;
+
+ isymp = internal_syms;
+ secpp = sections;
+ esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
+ esymend = esym + obj_raw_syment_count (input_bfd) * symesz;
+ while (esym < esymend)
+ {
+ bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
+
+ if (isymp->n_scnum != 0)
+ *secpp = coff_section_from_bfd_index (input_bfd, isymp->n_scnum);
+ else
+ {
+ if (isymp->n_value == 0)
+ *secpp = bfd_und_section_ptr;
+ else
+ *secpp = bfd_com_section_ptr;
+ }
+
+ esym += (isymp->n_numaux + 1) * symesz;
+ secpp += isymp->n_numaux + 1;
+ isymp += isymp->n_numaux + 1;
+ }
+
+ if (! sh_relocate_section (output_bfd, link_info, input_bfd,
+ input_section, data, internal_relocs,
+ internal_syms, sections))
+ goto error_return;
+
+ free (sections);
+ sections = NULL;
+ free (internal_syms);
+ internal_syms = NULL;
+ free (internal_relocs);
+ internal_relocs = NULL;
+ }
+
+ return data;
+
+ error_return:
+ if (internal_relocs != NULL)
+ free (internal_relocs);
+ if (internal_syms != NULL)
+ free (internal_syms);
+ if (sections != NULL)
+ free (sections);
+ return NULL;
+}
+
+/* The target vectors. */
+
+const bfd_target shcoff_vec =
+{
+ "coff-sh", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
+ '_', /* leading symbol underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
+
+const bfd_target shlcoff_vec =
+{
+ "coff-shl", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little endian too*/
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
+ '_', /* leading symbol underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-sparc.c b/contrib/gdb/bfd/coff-sparc.c
new file mode 100644
index 0000000..b9bc595
--- /dev/null
+++ b/contrib/gdb/bfd/coff-sparc.c
@@ -0,0 +1,278 @@
+/* BFD back-end for Sparc COFF files.
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/sparc.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+#define BADMAG(x) ((x).f_magic != SPARCMAGIC && (x).f_magic != LYNXCOFFMAGIC)
+
+/* The page size is a guess based on ELF. */
+#define COFF_PAGE_SIZE 0x10000
+
+enum reloc_type
+ {
+ R_SPARC_NONE = 0,
+ R_SPARC_8, R_SPARC_16, R_SPARC_32,
+ R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
+ R_SPARC_WDISP30, R_SPARC_WDISP22,
+ R_SPARC_HI22, R_SPARC_22,
+ R_SPARC_13, R_SPARC_LO10,
+ R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
+ R_SPARC_PC10, R_SPARC_PC22,
+ R_SPARC_WPLT30,
+ R_SPARC_COPY,
+ R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
+ R_SPARC_RELATIVE,
+ R_SPARC_UA32,
+ R_SPARC_max
+ };
+
+#if 0
+static CONST char *CONST reloc_type_names[] =
+{
+ "R_SPARC_NONE",
+ "R_SPARC_8", "R_SPARC_16", "R_SPARC_32",
+ "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32",
+ "R_SPARC_WDISP30", "R_SPARC_WDISP22",
+ "R_SPARC_HI22", "R_SPARC_22",
+ "R_SPARC_13", "R_SPARC_LO10",
+ "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22",
+ "R_SPARC_PC10", "R_SPARC_PC22",
+ "R_SPARC_WPLT30",
+ "R_SPARC_COPY",
+ "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
+ "R_SPARC_RELATIVE",
+ "R_SPARC_UA32",
+};
+#endif
+
+/* This is stolen pretty directly from elf.c. */
+static bfd_reloc_status_type
+bfd_coff_generic_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+static bfd_reloc_status_type
+bfd_coff_generic_reloc (abfd, reloc_entry, symbol, data, input_section,
+ 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->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ return bfd_reloc_continue;
+}
+
+static reloc_howto_type coff_sparc_howto_table[] =
+{
+ HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_NONE", false,0,0x00000000,true),
+ HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_32", false,0,0xffffffff,true),
+ HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_DISP8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_DISP16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_DISP32", false,0,0x00ffffff,true),
+ HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_WDISP30", false,0,0x3fffffff,true),
+ HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_coff_generic_reloc,"R_SPARC_WDISP22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_HI22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_LO10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_GOT22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC10, 0,2,10,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_PC10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_PC22, 0,2,22,false,0,complain_overflow_bitfield,bfd_coff_generic_reloc,"R_SPARC_PC22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_WPLT30", false,0,0x00000000,true),
+ HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_COPY", false,0,0x00000000,true),
+ HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_RELATIVE",false,0,0x00000000,true),
+ HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, bfd_coff_generic_reloc,"R_SPARC_UA32", false,0,0x00000000,true),
+};
+
+struct coff_reloc_map {
+ unsigned char bfd_reloc_val;
+ unsigned char coff_reloc_val;
+};
+
+static CONST struct coff_reloc_map sparc_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_SPARC_NONE, },
+ { BFD_RELOC_16, R_SPARC_16, },
+ { BFD_RELOC_8, R_SPARC_8 },
+ { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
+ { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */
+ { BFD_RELOC_32, R_SPARC_32 },
+ { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
+ { BFD_RELOC_HI22, R_SPARC_HI22 },
+ { BFD_RELOC_LO10, R_SPARC_LO10, },
+ { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+ { BFD_RELOC_SPARC22, R_SPARC_22 },
+ { BFD_RELOC_SPARC13, R_SPARC_13 },
+ { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
+ { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 },
+ { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 },
+ { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 },
+ { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 },
+ { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 },
+ { BFD_RELOC_SPARC_COPY, R_SPARC_COPY },
+ { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT },
+ { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
+ { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
+ { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
+ /* { BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
+};
+
+static reloc_howto_type *
+coff_sparc_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+ for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct coff_reloc_map); i++)
+ {
+ if (sparc_reloc_map[i].bfd_reloc_val == code)
+ return &coff_sparc_howto_table[(int) sparc_reloc_map[i].coff_reloc_val];
+ }
+ return 0;
+}
+#define coff_bfd_reloc_type_lookup coff_sparc_reloc_type_lookup
+
+static void
+rtype2howto (cache_ptr, dst)
+ arelent *cache_ptr;
+ struct internal_reloc *dst;
+{
+ BFD_ASSERT (dst->r_type < (unsigned int) R_SPARC_max);
+ cache_ptr->howto = &coff_sparc_howto_table[dst->r_type];
+}
+
+#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
+
+#define SWAP_IN_RELOC_OFFSET bfd_h_get_32
+#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
+/* This is just like the standard one, except that we don't set up an
+ addend for relocs against global symbols (otherwise linking objects
+ created by -r fails), and we add in the reloc offset at the end. */
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = 0; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL \
+ && (ptr->flags & BSF_GLOBAL) == 0) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ cache_ptr->addend += reloc.r_offset; \
+ }
+
+/* Clear the r_spare field in relocs. */
+#define SWAP_OUT_RELOC_EXTRA(abfd,src,dst) \
+ do { \
+ dst->r_spare[0] = 0; \
+ dst->r_spare[1] = 0; \
+ } while (0)
+
+#define __A_MAGIC_SET__
+
+/* Enable Sparc-specific hacks in coffcode.h. */
+
+#define COFF_SPARC
+
+#include "coffcode.h"
+
+const bfd_target
+#ifdef TARGET_SYM
+ TARGET_SYM =
+#else
+ sparccoff_vec =
+#endif
+{
+#ifdef TARGET_NAME
+ TARGET_NAME,
+#else
+ "coff-sparc", /* name */
+#endif
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+ 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 */
+
+/* Note that we allow an object file to be treated as a core file as well. */
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, coff_object_p},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-u68k.c b/contrib/gdb/bfd/coff-u68k.c
new file mode 100644
index 0000000..97ea73f
--- /dev/null
+++ b/contrib/gdb/bfd/coff-u68k.c
@@ -0,0 +1,35 @@
+/* BFD back-end for Motorola 68000 COFF binaries having underscore with name.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_SYM m68kcoffun_vec
+#define TARGET_NAME "coff-m68k-un"
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* define this to not have multiple copy of m68k_rtype2howto
+ in the executable file */
+#define ONLY_DECLARE_RELOCS
+
+/* This magic number indicates that the names have underscores.
+ Other 68k magic numbers indicate that the names do not have
+ underscores. */
+#define BADMAG(x) ((x).f_magic != MC68KBCSMAGIC)
+
+#include "coff-m68k.c"
diff --git a/contrib/gdb/bfd/coff-w65.c b/contrib/gdb/bfd/coff-w65.c
new file mode 100644
index 0000000..a02243f
--- /dev/null
+++ b/contrib/gdb/bfd/coff-w65.c
@@ -0,0 +1,446 @@
+/* BFD back-end for WDC 65816 COFF binaries.
+ Copyright 1995 Free Software Foundation, Inc.
+ Written by Steve Chamberlain, <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "obstack.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "coff/w65.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
+static reloc_howto_type howto_table[] =
+{
+ HOWTO (R_W65_ABS8, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, "abs8", true, 0x000000ff, 0x000000ff, false),
+ HOWTO (R_W65_ABS16, 1, 0, 16, false, 0, complain_overflow_bitfield, 0, "abs16", true, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_W65_ABS24, 0, 2, 32, false, 0, complain_overflow_bitfield, 0, "abs24", true, 0x00ffffff, 0x00ffffff, false),
+ HOWTO (R_W65_ABS8S8, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, ">abs8", true, 0x000000ff, 0x000000ff, false),
+ HOWTO (R_W65_ABS8S16, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, "^abs8", true, 0x000000ff, 0x000000ff, false),
+ HOWTO (R_W65_ABS16S8, 1, 0, 16, false, 0, complain_overflow_bitfield, 0, ">abs16", true, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_W65_ABS16S16,1, 0, 16, false, 0, complain_overflow_bitfield, 0, "^abs16", true, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_W65_PCR8, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, "pcrel8", true, 0x000000ff, 0x000000ff, true),
+ HOWTO (R_W65_PCR16, 1, 0, 16, false, 0, complain_overflow_bitfield, 0, "pcrel16", true, 0x0000ffff, 0x0000ffff, true),
+ HOWTO (R_W65_DP, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, "dp", true, 0x000000ff, 0x000000ff, false),
+
+};
+
+
+/* Turn a howto into a reloc number */
+
+#define SELECT_RELOC(x,howto) \
+ { x.r_type = select_reloc(howto); }
+
+#define BADMAG(x) (W65BADMAG(x))
+#define W65 1 /* Customize coffcode.h */
+#define __A_MAGIC_SET__
+
+
+/* Code to swap in the reloc */
+#define SWAP_IN_RELOC_OFFSET bfd_h_get_32
+#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
+#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
+ dst->r_stuff[0] = 'S'; \
+ dst->r_stuff[1] = 'C';
+
+
+static int
+select_reloc (howto)
+ reloc_howto_type *howto;
+{
+ return howto->type ;
+}
+
+/* Code to turn a r_type into a howto ptr, uses the above howto table
+ */
+
+static void
+rtype2howto (internal, dst)
+ arelent *internal;
+ struct internal_reloc *dst;
+{
+ internal->howto = howto_table + dst->r_type - 1;
+}
+
+#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
+
+
+/* Perform any necessaru magic to the addend in a reloc entry */
+
+
+#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
+ cache_ptr->addend = ext_reloc.r_offset;
+
+
+#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
+ reloc_processing(relent, reloc, symbols, abfd, section)
+
+static void
+reloc_processing (relent, reloc, symbols, abfd, section)
+ arelent * relent;
+ struct internal_reloc *reloc;
+ asymbol ** symbols;
+ bfd * abfd;
+ asection * section;
+{
+ relent->address = reloc->r_vaddr;
+ rtype2howto (relent, reloc);
+
+ if (((int) reloc->r_symndx) > 0)
+ {
+ relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
+ }
+ else
+ {
+ relent->sym_ptr_ptr = (asymbol **)&(bfd_abs_symbol);
+ }
+
+
+
+ relent->addend = reloc->r_offset;
+
+ relent->address -= section->vma;
+ /* relent->section = 0;*/
+}
+
+
+static int
+h8300_reloc16_estimate(abfd, input_section, reloc, shrink, link_info)
+ bfd *abfd;
+ asection *input_section;
+ arelent *reloc;
+ unsigned int shrink;
+ struct bfd_link_info *link_info;
+{
+ bfd_vma value;
+ bfd_vma dot;
+ bfd_vma gap;
+
+ /* The address of the thing to be relocated will have moved back by
+ the size of the shrink - but we don't change reloc->address here,
+ since we need it to know where the relocation lives in the source
+ uncooked section */
+
+ /* reloc->address -= shrink; conceptual */
+
+ bfd_vma address = reloc->address - shrink;
+
+
+ switch (reloc->howto->type)
+ {
+ case R_MOVB2:
+ case R_JMP2:
+ shrink+=2;
+ break;
+
+ /* Thing is a move one byte */
+ case R_MOVB1:
+ value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+
+ if (value >= 0xff00)
+ {
+
+ /* Change the reloc type from 16bit, possible 8 to 8bit
+ possible 16 */
+ reloc->howto = reloc->howto + 1;
+ /* The place to relc moves back by one */
+ /* This will be two bytes smaller in the long run */
+ shrink +=2 ;
+ bfd_perform_slip(abfd, 2, input_section, address);
+ }
+
+ break;
+ /* This is the 24 bit branch which could become an 8 bitter,
+ the relocation points to the first byte of the insn, not the
+ actual data */
+
+ case R_JMPL1:
+ value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+
+ dot = input_section->output_section->vma +
+ input_section->output_offset + address;
+
+ /* See if the address we're looking at within 127 bytes of where
+ we are, if so then we can use a small branch rather than the
+ jump we were going to */
+
+ gap = value - dot ;
+
+ if (-120 < (long)gap && (long)gap < 120 )
+ {
+
+ /* Change the reloc type from 24bit, possible 8 to 8bit
+ possible 32 */
+ reloc->howto = reloc->howto + 1;
+ /* This will be two bytes smaller in the long run */
+ shrink +=2 ;
+ bfd_perform_slip(abfd, 2, input_section, address);
+ }
+ break;
+
+ case R_JMP1:
+
+ value = bfd_coff_reloc16_get_value(reloc, link_info, input_section);
+
+ dot = input_section->output_section->vma +
+ input_section->output_offset + address;
+
+ /* See if the address we're looking at within 127 bytes of where
+ we are, if so then we can use a small branch rather than the
+ jump we were going to */
+
+ gap = value - (dot - shrink);
+
+
+ if (-120 < (long)gap && (long)gap < 120 )
+ {
+
+ /* Change the reloc type from 16bit, possible 8 to 8bit
+ possible 16 */
+ reloc->howto = reloc->howto + 1;
+ /* The place to relc moves back by one */
+
+ /* This will be two bytes smaller in the long run */
+ shrink +=2 ;
+ bfd_perform_slip(abfd, 2, input_section, address);
+ }
+ break;
+ }
+
+
+ return shrink;
+}
+
+
+/* First phase of a relaxing link */
+
+/* Reloc types
+ large small
+ R_MOVB1 R_MOVB2 mov.b with 16bit or 8 bit address
+ R_JMP1 R_JMP2 jmp or pcrel branch
+ R_JMPL1 R_JMPL_B8 24jmp or pcrel branch
+ R_MOVLB1 R_MOVLB2 24 or 8 bit reloc for mov.b
+
+*/
+
+static void
+h8300_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
+ dst_ptr)
+ bfd *abfd;
+ 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;
+{
+ unsigned int src_address = *src_ptr;
+ unsigned int dst_address = *dst_ptr;
+ asection *input_section = link_order->u.indirect.section;
+
+ switch (reloc->howto->type)
+ {
+ case R_W65_ABS8:
+ case R_W65_DP:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ bfd_put_8 (abfd, gap, data + dst_address);
+ dst_address += 1;
+ src_address += 1;
+ }
+ break;
+
+ case R_W65_ABS8S8:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ gap >>= 8;
+ bfd_put_8 (abfd, gap, data + dst_address);
+ dst_address += 1;
+ src_address += 1;
+ }
+ break;
+
+ case R_W65_ABS8S16:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ gap >>=16;
+ bfd_put_8 (abfd, gap, data + dst_address);
+ dst_address += 1;
+ src_address += 1;
+ }
+ break;
+
+ case R_W65_ABS16:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+
+ bfd_put_16 (abfd, gap, data + dst_address);
+ dst_address += 2;
+ src_address += 2;
+ }
+ break;
+ case R_W65_ABS16S8:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ gap >>= 8;
+ bfd_put_16 (abfd, gap, data + dst_address);
+ dst_address += 2;
+ src_address += 2;
+ }
+ break;
+ case R_W65_ABS16S16:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ gap >>= 16;
+ bfd_put_16 (abfd, gap, data + dst_address);
+ dst_address += 2;
+ src_address += 2;
+ }
+ break;
+
+ case R_W65_ABS24:
+ {
+ unsigned int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ bfd_put_16 (abfd, gap, data + dst_address);
+ bfd_put_8 (abfd, gap>>16, data+dst_address+2);
+ dst_address += 3;
+ src_address += 3;
+ }
+ break;
+
+ case R_W65_PCR8:
+ {
+ int gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ bfd_vma dot = link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma;
+
+ gap -= dot + 1;
+ if (gap < -128 || gap > 127) {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort();
+ }
+ bfd_put_8 (abfd, gap, data + dst_address);
+ dst_address += 1;
+ src_address += 1;
+ }
+ break;
+
+ case R_W65_PCR16:
+ {
+ bfd_vma gap = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ bfd_vma dot = link_order->offset
+ + dst_address
+ + link_order->u.indirect.section->output_section->vma;
+
+
+ /* This wraps within the page, so ignore the relativeness, look at the
+ high part */
+ if ((gap & 0xf0000) != (dot & 0xf0000)) {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort();
+ }
+
+ gap -= dot + 2;
+ bfd_put_16 (abfd, gap, data + dst_address);
+ dst_address += 2;
+ src_address += 2;
+ }
+ break;
+ default:
+ printf("ignoring reloc %s\n", reloc->howto->name);
+ break;
+
+ }
+ *src_ptr = src_address;
+ *dst_ptr = dst_address;
+
+}
+
+#define coff_reloc16_extra_cases h8300_reloc16_extra_cases
+#define coff_reloc16_estimate h8300_reloc16_estimate
+
+#include "coffcode.h"
+
+
+#undef coff_bfd_get_relocated_section_contents
+#undef coff_bfd_relax_section
+#define coff_bfd_get_relocated_section_contents \
+ bfd_coff_reloc16_get_relocated_section_contents
+#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
+
+
+
+bfd_target w65_vec =
+{
+ "coff-w65", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* header byte order is little */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE ),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading char */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-we32k.c b/contrib/gdb/bfd/coff-we32k.c
new file mode 100644
index 0000000..36f1fa1
--- /dev/null
+++ b/contrib/gdb/bfd/coff-we32k.c
@@ -0,0 +1,110 @@
+/* BFD back-end for we32k COFF files.
+ Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Brendan Kehoe (brendan@cs.widener.edu).
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "coff/we32k.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
+
+static reloc_howto_type howto_table[] =
+{
+ {0},
+ {1},
+ {2},
+ {3},
+ {4},
+ {5},
+ HOWTO(R_DIR32, 0, 2, 32, false, 0,complain_overflow_bitfield, 0, "dir32", true, 0xffffffff,0xffffffff, false),
+ {7},
+ {010},
+ {011},
+ {012},
+ {013},
+ {014},
+ {015},
+ {016},
+ HOWTO(R_RELBYTE, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, "8", true, 0x000000ff,0x000000ff, false),
+ HOWTO(R_RELWORD, 0, 1, 16, false, 0, complain_overflow_bitfield, 0, "16", true, 0x0000ffff,0x0000ffff, false),
+ HOWTO(R_RELLONG, 0, 2, 32, false, 0, complain_overflow_bitfield, 0, "32", true, 0xffffffff,0xffffffff, false),
+ HOWTO(R_PCRBYTE, 0, 0, 8, true, 0, complain_overflow_signed, 0, "DISP8", true, 0x000000ff,0x000000ff, false),
+ HOWTO(R_PCRWORD, 0, 1, 16, true, 0, complain_overflow_signed, 0, "DISP16", true, 0x0000ffff,0x0000ffff, false),
+ HOWTO(R_PCRLONG, 0, 2, 32, true, 0, complain_overflow_signed, 0, "DISP32", true, 0xffffffff,0xffffffff, false),
+};
+
+/* Turn a howto into a reloc nunmber */
+
+#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
+#define BADMAG(x) WE32KBADMAG(x)
+#define WE32K 1
+
+#define RTYPE2HOWTO(cache_ptr, dst) \
+ (cache_ptr)->howto = howto_table + (dst)->r_type;
+
+#include "coffcode.h"
+
+#define coff_write_armap bsd_write_armap
+
+const bfd_target we32kcoff_vec =
+{
+ "coff-we32k", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* leading underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coff-z8k.c b/contrib/gdb/bfd/coff-z8k.c
new file mode 100644
index 0000000..5609d35
--- /dev/null
+++ b/contrib/gdb/bfd/coff-z8k.c
@@ -0,0 +1,281 @@
+/* BFD back-end for Zilog Z800n COFF binaries.
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ Written by Steve Chamberlain, <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "obstack.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "coff/z8k.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
+
+static reloc_howto_type r_imm32 =
+HOWTO (R_IMM32, 0, 1, 32, false, 0,
+ complain_overflow_bitfield, 0, "r_imm32", true, 0xffffffff,
+ 0xffffffff, false);
+
+static reloc_howto_type r_imm4l =
+HOWTO (R_IMM4L, 0, 1, 4, false, 0,
+ complain_overflow_bitfield, 0, "r_imm4l", true, 0xf, 0xf, false);
+
+static reloc_howto_type r_da =
+HOWTO (R_IMM16, 0, 1, 16, false, 0,
+ complain_overflow_bitfield, 0, "r_da", true, 0x0000ffff, 0x0000ffff,
+ false);
+
+static reloc_howto_type r_imm8 =
+HOWTO (R_IMM8, 0, 1, 8, false, 0,
+ complain_overflow_bitfield, 0, "r_imm8", true, 0x000000ff, 0x000000ff,
+ false);
+
+static reloc_howto_type r_jr =
+HOWTO (R_JR, 0, 1, 8, true, 0, complain_overflow_signed, 0,
+ "r_jr", true, 0, 0, true);
+
+/* Turn a howto into a reloc number */
+
+static int
+coff_z8k_select_reloc (howto)
+ reloc_howto_type *howto;
+{
+ return howto->type;
+}
+
+#define SELECT_RELOC(x,howto) x.r_type = coff_z8k_select_reloc(howto)
+
+
+#define BADMAG(x) Z8KBADMAG(x)
+#define Z8K 1 /* Customize coffcode.h */
+#define __A_MAGIC_SET__
+
+
+
+/* Code to swap in the reloc */
+#define SWAP_IN_RELOC_OFFSET bfd_h_get_32
+#define SWAP_OUT_RELOC_OFFSET bfd_h_put_32
+#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
+ dst->r_stuff[0] = 'S'; \
+ dst->r_stuff[1] = 'C';
+
+/* Code to turn a r_type into a howto ptr, uses the above howto table
+ */
+
+static void
+rtype2howto (internal, dst)
+ arelent * internal;
+ struct internal_reloc *dst;
+{
+ switch (dst->r_type)
+ {
+ default:
+ abort ();
+ break;
+ case R_IMM8:
+ internal->howto = &r_imm8;
+ break;
+ case R_IMM16:
+ internal->howto = &r_da;
+ break;
+ case R_JR:
+ internal->howto = &r_jr;
+ break;
+ case R_IMM32:
+ internal->howto = &r_imm32;
+ break;
+ case R_IMM4L:
+ internal->howto = &r_imm4l;
+ break;
+ }
+}
+
+#define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
+
+
+/* Perform any necessaru magic to the addend in a reloc entry */
+
+
+#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
+ cache_ptr->addend = ext_reloc.r_offset;
+
+
+#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
+ reloc_processing(relent, reloc, symbols, abfd, section)
+
+static void
+reloc_processing (relent, reloc, symbols, abfd, section)
+ arelent * relent;
+ struct internal_reloc *reloc;
+ asymbol ** symbols;
+ bfd * abfd;
+ asection * section;
+{
+ relent->address = reloc->r_vaddr;
+ rtype2howto (relent, reloc);
+
+ if (reloc->r_symndx > 0)
+ {
+ relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
+ }
+ else
+ {
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ }
+
+
+ relent->addend = reloc->r_offset;
+ relent->address -= section->vma;
+}
+
+static void
+extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
+ bfd *in_abfd;
+ 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;
+{
+ asection *input_section = link_order->u.indirect.section;
+
+ switch (reloc->howto->type)
+ {
+ case R_IMM8:
+ bfd_put_8 (in_abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ data + *dst_ptr);
+ (*dst_ptr) += 1;
+ (*src_ptr) += 1;
+ break;
+
+ case R_IMM32:
+ bfd_put_32 (in_abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ data + *dst_ptr);
+ (*dst_ptr) += 4;
+ (*src_ptr) += 4;
+ break;
+
+ case R_IMM4L:
+ bfd_put_8 (in_abfd,
+ ((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
+ | (0x0f
+ & bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section))),
+ data + *dst_ptr);
+ (*dst_ptr) += 1;
+ (*src_ptr) += 1;
+ break;
+
+ case R_IMM16:
+ bfd_put_16 (in_abfd,
+ bfd_coff_reloc16_get_value (reloc, link_info, input_section),
+ data + *dst_ptr);
+ (*dst_ptr) += 2;
+ (*src_ptr) += 2;
+ break;
+
+ case R_JR:
+ {
+ bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
+ input_section);
+ bfd_vma dot = (link_order->offset
+ + *dst_ptr
+ + input_section->output_section->vma);
+ int gap = dst - dot - 1;/* -1 since were in the odd byte of the
+ word and the pc's been incremented */
+
+ if (gap & 1)
+ abort ();
+ gap /= 2;
+ if (gap > 128 || gap < -128)
+ {
+ if (! ((*link_info->callbacks->reloc_overflow)
+ (link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
+ reloc->howto->name, reloc->addend, input_section->owner,
+ input_section, reloc->address)))
+ abort ();
+ }
+ bfd_put_8 (in_abfd, gap, data + *dst_ptr);
+ (*dst_ptr)++;
+ (*src_ptr)++;
+ break;
+ }
+ default:
+ abort ();
+ }
+}
+
+#define coff_reloc16_extra_cases extra_case
+
+#include "coffcode.h"
+
+
+#undef coff_bfd_get_relocated_section_contents
+#undef coff_bfd_relax_section
+#define coff_bfd_get_relocated_section_contents \
+ bfd_coff_reloc16_get_relocated_section_contents
+#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
+
+const bfd_target z8kcoff_vec =
+{
+ "coff-z8k", /* name */
+ bfd_target_coff_flavour,
+ BFD_ENDIAN_BIG, /* data byte order is big */
+ BFD_ENDIAN_BIG, /* header byte order is big */
+
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT),
+
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ '_', /* leading symbol underscore */
+ '/', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, coff_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
+ bfd_false},
+ {bfd_false, coff_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (coff),
+ BFD_JUMP_TABLE_COPY (coff),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (coff),
+ BFD_JUMP_TABLE_RELOCS (coff),
+ BFD_JUMP_TABLE_WRITE (coff),
+ BFD_JUMP_TABLE_LINK (coff),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ COFF_SWAP_TABLE,
+};
diff --git a/contrib/gdb/bfd/coffcode.h b/contrib/gdb/bfd/coffcode.h
new file mode 100644
index 0000000..22babd0
--- /dev/null
+++ b/contrib/gdb/bfd/coffcode.h
@@ -0,0 +1,3612 @@
+/* Support for the generic parts of most COFF variants, for BFD.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+Most of this hacked by Steve Chamberlain,
+ sac@cygnus.com
+*/
+/*
+
+SECTION
+ coff backends
+
+ BFD supports a number of different flavours of coff format.
+ The major differences between formats are the sizes and
+ alignments of fields in structures on disk, and the occasional
+ extra field.
+
+ Coff in all its varieties is implemented with a few common
+ files and a number of implementation specific files. For
+ example, The 88k bcs coff format is implemented in the file
+ @file{coff-m88k.c}. This file @code{#include}s
+ @file{coff/m88k.h} which defines the external structure of the
+ coff format for the 88k, and @file{coff/internal.h} which
+ defines the internal structure. @file{coff-m88k.c} also
+ defines the relocations used by the 88k format
+ @xref{Relocations}.
+
+ The Intel i960 processor version of coff is implemented in
+ @file{coff-i960.c}. This file has the same structure as
+ @file{coff-m88k.c}, except that it includes @file{coff/i960.h}
+ rather than @file{coff-m88k.h}.
+
+SUBSECTION
+ Porting to a new version of coff
+
+ The recommended method is to select from the existing
+ implementations the version of coff which is most like the one
+ you want to use. For example, we'll say that i386 coff is
+ the one you select, and that your coff flavour is called foo.
+ Copy @file{i386coff.c} to @file{foocoff.c}, copy
+ @file{../include/coff/i386.h} to @file{../include/coff/foo.h},
+ and add the lines to @file{targets.c} and @file{Makefile.in}
+ so that your new back end is used. Alter the shapes of the
+ structures in @file{../include/coff/foo.h} so that they match
+ what you need. You will probably also have to add
+ @code{#ifdef}s to the code in @file{coff/internal.h} and
+ @file{coffcode.h} if your version of coff is too wild.
+
+ You can verify that your new BFD backend works quite simply by
+ building @file{objdump} from the @file{binutils} directory,
+ and making sure that its version of what's going on and your
+ host system's idea (assuming it has the pretty standard coff
+ dump utility, usually called @code{att-dump} or just
+ @code{dump}) are the same. Then clean up your code, and send
+ what you've done to Cygnus. Then your stuff will be in the
+ next release, and you won't have to keep integrating it.
+
+SUBSECTION
+ How the coff backend works
+
+SUBSUBSECTION
+ File layout
+
+ The Coff backend is split into generic routines that are
+ applicable to any Coff target and routines that are specific
+ to a particular target. The target-specific routines are
+ further split into ones which are basically the same for all
+ Coff targets except that they use the external symbol format
+ or use different values for certain constants.
+
+ The generic routines are in @file{coffgen.c}. These routines
+ work for any Coff target. They use some hooks into the target
+ specific code; the hooks are in a @code{bfd_coff_backend_data}
+ structure, one of which exists for each target.
+
+ The essentially similar target-specific routines are in
+ @file{coffcode.h}. This header file includes executable C code.
+ The various Coff targets first include the appropriate Coff
+ header file, make any special defines that are needed, and
+ then include @file{coffcode.h}.
+
+ Some of the Coff targets then also have additional routines in
+ the target source file itself.
+
+ For example, @file{coff-i960.c} includes
+ @file{coff/internal.h} and @file{coff/i960.h}. It then
+ defines a few constants, such as @code{I960}, and includes
+ @file{coffcode.h}. Since the i960 has complex relocation
+ types, @file{coff-i960.c} also includes some code to
+ manipulate the i960 relocs. This code is not in
+ @file{coffcode.h} because it would not be used by any other
+ target.
+
+SUBSUBSECTION
+ Bit twiddling
+
+ Each flavour of coff supported in BFD has its own header file
+ describing the external layout of the structures. There is also
+ an internal description of the coff layout, in
+ @file{coff/internal.h}. A major function of the
+ coff backend is swapping the bytes and twiddling the bits to
+ translate the external form of the structures into the normal
+ internal form. This is all performed in the
+ @code{bfd_swap}_@i{thing}_@i{direction} routines. Some
+ elements are different sizes between different versions of
+ coff; it is the duty of the coff version specific include file
+ to override the definitions of various packing routines in
+ @file{coffcode.h}. E.g., the size of line number entry in coff is
+ sometimes 16 bits, and sometimes 32 bits. @code{#define}ing
+ @code{PUT_LNSZ_LNNO} and @code{GET_LNSZ_LNNO} will select the
+ correct one. No doubt, some day someone will find a version of
+ coff which has a varying field size not catered to at the
+ moment. To port BFD, that person will have to add more @code{#defines}.
+ Three of the bit twiddling routines are exported to
+ @code{gdb}; @code{coff_swap_aux_in}, @code{coff_swap_sym_in}
+ and @code{coff_swap_linno_in}. @code{GDB} reads the symbol
+ table on its own, but uses BFD to fix things up. More of the
+ bit twiddlers are exported for @code{gas};
+ @code{coff_swap_aux_out}, @code{coff_swap_sym_out},
+ @code{coff_swap_lineno_out}, @code{coff_swap_reloc_out},
+ @code{coff_swap_filehdr_out}, @code{coff_swap_aouthdr_out},
+ @code{coff_swap_scnhdr_out}. @code{Gas} currently keeps track
+ of all the symbol table and reloc drudgery itself, thereby
+ saving the internal BFD overhead, but uses BFD to swap things
+ on the way out, making cross ports much safer. Doing so also
+ allows BFD (and thus the linker) to use the same header files
+ as @code{gas}, which makes one avenue to disaster disappear.
+
+SUBSUBSECTION
+ Symbol reading
+
+ The simple canonical form for symbols used by BFD is not rich
+ enough to keep all the information available in a coff symbol
+ table. The back end gets around this problem by keeping the original
+ symbol table around, "behind the scenes".
+
+ When a symbol table is requested (through a call to
+ @code{bfd_canonicalize_symtab}), a request gets through to
+ @code{coff_get_normalized_symtab}. This reads the symbol table from
+ the coff file and swaps all the structures inside into the
+ internal form. It also fixes up all the pointers in the table
+ (represented in the file by offsets from the first symbol in
+ the table) into physical pointers to elements in the new
+ internal table. This involves some work since the meanings of
+ fields change depending upon context: a field that is a
+ pointer to another structure in the symbol table at one moment
+ may be the size in bytes of a structure at the next. Another
+ pass is made over the table. All symbols which mark file names
+ (<<C_FILE>> symbols) are modified so that the internal
+ string points to the value in the auxent (the real filename)
+ rather than the normal text associated with the symbol
+ (@code{".file"}).
+
+ At this time the symbol names are moved around. Coff stores
+ all symbols less than nine characters long physically
+ within the symbol table; longer strings are kept at the end of
+ the file in the string table. This pass moves all strings
+ into memory and replaces them with pointers to the strings.
+
+
+ The symbol table is massaged once again, this time to create
+ the canonical table used by the BFD application. Each symbol
+ is inspected in turn, and a decision made (using the
+ @code{sclass} field) about the various flags to set in the
+ @code{asymbol}. @xref{Symbols}. The generated canonical table
+ shares strings with the hidden internal symbol table.
+
+ Any linenumbers are read from the coff file too, and attached
+ to the symbols which own the functions the linenumbers belong to.
+
+SUBSUBSECTION
+ Symbol writing
+
+ Writing a symbol to a coff file which didn't come from a coff
+ file will lose any debugging information. The @code{asymbol}
+ structure remembers the BFD from which the symbol was taken, and on
+ output the back end makes sure that the same destination target as
+ source target is present.
+
+ When the symbols have come from a coff file then all the
+ debugging information is preserved.
+
+ Symbol tables are provided for writing to the back end in a
+ vector of pointers to pointers. This allows applications like
+ the linker to accumulate and output large symbol tables
+ without having to do too much byte copying.
+
+ This function runs through the provided symbol table and
+ patches each symbol marked as a file place holder
+ (@code{C_FILE}) to point to the next file place holder in the
+ list. It also marks each @code{offset} field in the list with
+ the offset from the first symbol of the current symbol.
+
+ Another function of this procedure is to turn the canonical
+ value form of BFD into the form used by coff. Internally, BFD
+ expects symbol values to be offsets from a section base; so a
+ symbol physically at 0x120, but in a section starting at
+ 0x100, would have the value 0x20. Coff expects symbols to
+ contain their final value, so symbols have their values
+ changed at this point to reflect their sum with their owning
+ section. This transformation uses the
+ <<output_section>> field of the @code{asymbol}'s
+ @code{asection} @xref{Sections}.
+
+ o <<coff_mangle_symbols>>
+
+ This routine runs though the provided symbol table and uses
+ the offsets generated by the previous pass and the pointers
+ generated when the symbol table was read in to create the
+ structured hierachy required by coff. It changes each pointer
+ to a symbol into the index into the symbol table of the asymbol.
+
+ o <<coff_write_symbols>>
+
+ This routine runs through the symbol table and patches up the
+ symbols from their internal form into the coff way, calls the
+ bit twiddlers, and writes out the table to the file.
+
+*/
+
+/*
+INTERNAL_DEFINITION
+ coff_symbol_type
+
+DESCRIPTION
+ The hidden information for an <<asymbol>> is described in a
+ <<combined_entry_type>>:
+
+CODE_FRAGMENT
+.
+.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. *}
+.unsigned int fix_tag : 1;
+.
+. {* Should the endidx field of this symbol be renumbered.
+. Created by coff_pointerize_aux. *}
+.unsigned int fix_end : 1;
+.
+. {* Should the x_csect.x_scnlen field be renumbered.
+. Created by coff_pointerize_aux. *}
+.unsigned int fix_scnlen : 1;
+.
+. {* Fix up an XCOFF C_BINCL/C_EINCL symbol. The value is the
+. index into the line number entries. Set by
+. coff_slurp_symbol_table. *}
+.unsigned int fix_line : 1;
+.
+. {* The container for the symbol structure as read and translated
+. from the file. *}
+.
+.union {
+. union internal_auxent auxent;
+. struct internal_syment syment;
+. } u;
+.} combined_entry_type;
+.
+.
+.{* Each canonical asymbol really looks like this: *}
+.
+.typedef struct coff_symbol_struct
+.{
+. {* The actual symbol which the rest of BFD works with *}
+.asymbol symbol;
+.
+. {* A pointer to the hidden information for this symbol *}
+.combined_entry_type *native;
+.
+. {* A pointer to the linenumber information for this symbol *}
+.struct lineno_cache_entry *lineno;
+.
+. {* Have the line numbers been relocated yet ? *}
+.boolean done_lineno;
+.} coff_symbol_type;
+
+
+*/
+
+#ifdef COFF_WITH_PE
+#include "peicode.h"
+#else
+#include "coffswap.h"
+#endif
+
+
+/* void warning(); */
+
+/*
+ * Return a word with STYP_* (scnhdr.s_flags) flags set to represent the
+ * incoming SEC_* flags. The inverse of this function is styp_to_sec_flags().
+ * NOTE: If you add to/change this routine, you should mirror the changes
+ * in styp_to_sec_flags().
+ */
+static long
+sec_to_styp_flags (sec_name, sec_flags)
+ CONST char *sec_name;
+ flagword sec_flags;
+{
+ long styp_flags = 0;
+
+ if (!strcmp (sec_name, _TEXT))
+ {
+ styp_flags = STYP_TEXT;
+ }
+ else if (!strcmp (sec_name, _DATA))
+ {
+ styp_flags = STYP_DATA;
+ }
+ else if (!strcmp (sec_name, _BSS))
+ {
+ styp_flags = STYP_BSS;
+#ifdef _COMMENT
+ }
+ else if (!strcmp (sec_name, _COMMENT))
+ {
+ styp_flags = STYP_INFO;
+#endif /* _COMMENT */
+#ifdef _LIB
+ }
+ else if (!strcmp (sec_name, _LIB))
+ {
+ styp_flags = STYP_LIB;
+#endif /* _LIB */
+#ifdef _LIT
+ }
+ else if (!strcmp (sec_name, _LIT))
+ {
+ styp_flags = STYP_LIT;
+#endif /* _LIT */
+ }
+ else if (!strcmp (sec_name, ".debug"))
+ {
+#ifdef STYP_DEBUG
+ styp_flags = STYP_DEBUG;
+#else
+ styp_flags = STYP_INFO;
+#endif
+ }
+ else if (!strncmp (sec_name, ".stab", 5))
+ {
+ styp_flags = STYP_INFO;
+ }
+#ifdef COFF_WITH_PE
+ else if (!strcmp (sec_name, ".edata"))
+ {
+ styp_flags = STYP_DATA;
+ }
+#endif
+#ifdef RS6000COFF_C
+ else if (!strcmp (sec_name, _PAD))
+ {
+ styp_flags = STYP_PAD;
+ }
+ else if (!strcmp (sec_name, _LOADER))
+ {
+ styp_flags = STYP_LOADER;
+ }
+#endif
+ /* Try and figure out what it should be */
+ else if (sec_flags & SEC_CODE)
+ {
+ styp_flags = STYP_TEXT;
+ }
+ else if (sec_flags & SEC_DATA)
+ {
+ styp_flags = STYP_DATA;
+ }
+ else if (sec_flags & SEC_READONLY)
+ {
+#ifdef STYP_LIT /* 29k readonly text/data section */
+ styp_flags = STYP_LIT;
+#else
+ styp_flags = STYP_TEXT;
+#endif /* STYP_LIT */
+ }
+ else if (sec_flags & SEC_LOAD)
+ {
+ styp_flags = STYP_TEXT;
+ }
+ else if (sec_flags & SEC_ALLOC)
+ {
+ styp_flags = STYP_BSS;
+ }
+
+#ifdef STYP_NOLOAD
+ if ((sec_flags & (SEC_NEVER_LOAD | SEC_COFF_SHARED_LIBRARY)) != 0)
+ styp_flags |= STYP_NOLOAD;
+#endif
+
+ return (styp_flags);
+}
+/*
+ * Return a word with SEC_* flags set to represent the incoming
+ * STYP_* flags (from scnhdr.s_flags). The inverse of this
+ * function is sec_to_styp_flags().
+ * NOTE: If you add to/change this routine, you should mirror the changes
+ * in sec_to_styp_flags().
+ */
+static flagword
+styp_to_sec_flags (abfd, hdr, name)
+ bfd *abfd;
+ PTR hdr;
+ const char *name;
+{
+ struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
+ long styp_flags = internal_s->s_flags;
+ flagword sec_flags = 0;
+
+#ifdef STYP_NOLOAD
+ if (styp_flags & STYP_NOLOAD)
+ {
+ sec_flags |= SEC_NEVER_LOAD;
+ }
+#endif /* STYP_NOLOAD */
+
+ /* For 386 COFF, at least, an unloadable text or data section is
+ actually a shared library section. */
+ if (styp_flags & STYP_TEXT)
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY;
+ else
+ sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
+ }
+ else if (styp_flags & STYP_DATA)
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
+ else
+ sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
+ }
+ else if (styp_flags & STYP_BSS)
+ {
+#ifdef BSS_NOLOAD_IS_SHARED_LIBRARY
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_ALLOC | SEC_COFF_SHARED_LIBRARY;
+ else
+#endif
+ sec_flags |= SEC_ALLOC;
+ }
+ else if (styp_flags & STYP_INFO)
+ {
+ /* We mark these as SEC_DEBUGGING, but only if COFF_PAGE_SIZE is
+ defined. coff_compute_section_file_positions uses
+ COFF_PAGE_SIZE to ensure that the low order bits of the
+ section VMA and the file offset match. If we don't know
+ COFF_PAGE_SIZE, we can't ensure the correct correspondence,
+ and demand page loading of the file will fail. */
+#ifdef COFF_PAGE_SIZE
+ sec_flags |= SEC_DEBUGGING;
+#endif
+ }
+ else if (styp_flags & STYP_PAD)
+ {
+ sec_flags = 0;
+ }
+ else if (strcmp (name, _TEXT) == 0)
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_CODE | SEC_COFF_SHARED_LIBRARY;
+ else
+ sec_flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
+ }
+ else if (strcmp (name, _DATA) == 0)
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
+ else
+ sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
+ }
+ else if (strcmp (name, _BSS) == 0)
+ {
+#ifdef BSS_NOLOAD_IS_SHARED_LIBRARY
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_ALLOC | SEC_COFF_SHARED_LIBRARY;
+ else
+#endif
+ sec_flags |= SEC_ALLOC;
+ }
+ else if (strcmp (name, ".debug") == 0
+#ifdef _COMMENT
+ || strcmp (name, _COMMENT) == 0
+#endif
+ || strncmp (name, ".stab", 5) == 0)
+ {
+#ifdef COFF_PAGE_SIZE
+ sec_flags |= SEC_DEBUGGING;
+#endif
+ }
+#ifdef _LIB
+ else if (strcmp (name, _LIB) == 0)
+ ;
+#endif
+#ifdef _LIT
+ else if (strcmp (name, _LIT) == 0)
+ {
+ sec_flags = SEC_LOAD | SEC_ALLOC | SEC_READONLY;
+ }
+#endif
+ else
+ {
+ sec_flags |= SEC_ALLOC | SEC_LOAD;
+ }
+
+#ifdef STYP_LIT /* A29k readonly text/data section type */
+ if ((styp_flags & STYP_LIT) == STYP_LIT)
+ {
+ sec_flags = (SEC_LOAD | SEC_ALLOC | SEC_READONLY);
+ }
+#endif /* STYP_LIT */
+#ifdef STYP_OTHER_LOAD /* Other loaded sections */
+ if (styp_flags & STYP_OTHER_LOAD)
+ {
+ sec_flags = (SEC_LOAD | SEC_ALLOC);
+ }
+#endif /* STYP_SDATA */
+
+ return (sec_flags);
+}
+
+#define get_index(symbol) ((symbol)->udata.i)
+
+/*
+INTERNAL_DEFINITION
+ bfd_coff_backend_data
+
+CODE_FRAGMENT
+
+Special entry points for gdb to swap in coff symbol table parts:
+.typedef struct
+.{
+. void (*_bfd_coff_swap_aux_in) PARAMS ((
+. bfd *abfd,
+. PTR ext,
+. int type,
+. int class,
+. int indaux,
+. int numaux,
+. PTR in));
+.
+. void (*_bfd_coff_swap_sym_in) PARAMS ((
+. bfd *abfd ,
+. PTR ext,
+. PTR in));
+.
+. void (*_bfd_coff_swap_lineno_in) PARAMS ((
+. bfd *abfd,
+. PTR ext,
+. PTR in));
+.
+
+Special entry points for gas to swap out coff parts:
+
+. unsigned int (*_bfd_coff_swap_aux_out) PARAMS ((
+. bfd *abfd,
+. PTR in,
+. int type,
+. int class,
+. int indaux,
+. int numaux,
+. PTR ext));
+.
+. unsigned int (*_bfd_coff_swap_sym_out) PARAMS ((
+. bfd *abfd,
+. PTR in,
+. PTR ext));
+.
+. unsigned int (*_bfd_coff_swap_lineno_out) PARAMS ((
+. bfd *abfd,
+. PTR in,
+. PTR ext));
+.
+. unsigned int (*_bfd_coff_swap_reloc_out) PARAMS ((
+. bfd *abfd,
+. PTR src,
+. PTR dst));
+.
+. unsigned int (*_bfd_coff_swap_filehdr_out) PARAMS ((
+. bfd *abfd,
+. PTR in,
+. PTR out));
+.
+. unsigned int (*_bfd_coff_swap_aouthdr_out) PARAMS ((
+. bfd *abfd,
+. PTR in,
+. PTR out));
+.
+. unsigned int (*_bfd_coff_swap_scnhdr_out) PARAMS ((
+. bfd *abfd,
+. PTR in,
+. PTR out));
+.
+
+Special entry points for generic COFF routines to call target
+dependent COFF routines:
+
+. unsigned int _bfd_filhsz;
+. unsigned int _bfd_aoutsz;
+. unsigned int _bfd_scnhsz;
+. unsigned int _bfd_symesz;
+. unsigned int _bfd_auxesz;
+. unsigned int _bfd_relsz;
+. unsigned int _bfd_linesz;
+. boolean _bfd_coff_long_filenames;
+. void (*_bfd_coff_swap_filehdr_in) PARAMS ((
+. bfd *abfd,
+. PTR ext,
+. PTR in));
+. void (*_bfd_coff_swap_aouthdr_in) PARAMS ((
+. bfd *abfd,
+. PTR ext,
+. PTR in));
+. void (*_bfd_coff_swap_scnhdr_in) PARAMS ((
+. bfd *abfd,
+. PTR ext,
+. PTR in));
+. void (*_bfd_coff_swap_reloc_in) PARAMS ((
+. bfd *abfd,
+. PTR ext,
+. PTR in));
+. boolean (*_bfd_coff_bad_format_hook) PARAMS ((
+. bfd *abfd,
+. PTR internal_filehdr));
+. boolean (*_bfd_coff_set_arch_mach_hook) PARAMS ((
+. bfd *abfd,
+. PTR internal_filehdr));
+. PTR (*_bfd_coff_mkobject_hook) PARAMS ((
+. bfd *abfd,
+. PTR internal_filehdr,
+. PTR internal_aouthdr));
+. flagword (*_bfd_styp_to_sec_flags_hook) PARAMS ((
+. bfd *abfd,
+. PTR internal_scnhdr,
+. const char *name));
+. void (*_bfd_set_alignment_hook) PARAMS ((
+. bfd *abfd,
+. asection *sec,
+. PTR internal_scnhdr));
+. boolean (*_bfd_coff_slurp_symbol_table) PARAMS ((
+. bfd *abfd));
+. boolean (*_bfd_coff_symname_in_debug) PARAMS ((
+. bfd *abfd,
+. struct internal_syment *sym));
+. boolean (*_bfd_coff_pointerize_aux_hook) PARAMS ((
+. bfd *abfd,
+. combined_entry_type *table_base,
+. combined_entry_type *symbol,
+. unsigned int indaux,
+. combined_entry_type *aux));
+. boolean (*_bfd_coff_print_aux) PARAMS ((
+. bfd *abfd,
+. FILE *file,
+. combined_entry_type *table_base,
+. combined_entry_type *symbol,
+. combined_entry_type *aux,
+. unsigned int indaux));
+. void (*_bfd_coff_reloc16_extra_cases) PARAMS ((
+. bfd *abfd,
+. 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,
+. arelent *r,
+. unsigned int shrink,
+. struct bfd_link_info *link_info));
+. boolean (*_bfd_coff_sym_is_global) PARAMS ((
+. bfd *abfd,
+. struct internal_syment *));
+. void (*_bfd_coff_compute_section_file_positions) PARAMS ((
+. bfd *abfd));
+. boolean (*_bfd_coff_start_final_link) PARAMS ((
+. bfd *output_bfd,
+. struct bfd_link_info *info));
+. boolean (*_bfd_coff_relocate_section) PARAMS ((
+. bfd *output_bfd,
+. struct bfd_link_info *info,
+. bfd *input_bfd,
+. asection *input_section,
+. bfd_byte *contents,
+. struct internal_reloc *relocs,
+. struct internal_syment *syms,
+. asection **sections));
+. reloc_howto_type *(*_bfd_coff_rtype_to_howto) PARAMS ((
+. bfd *abfd,
+. asection *sec,
+. struct internal_reloc *rel,
+. struct coff_link_hash_entry *h,
+. struct internal_syment *sym,
+. bfd_vma *addendp));
+. boolean (*_bfd_coff_adjust_symndx) PARAMS ((
+. bfd *obfd,
+. struct bfd_link_info *info,
+. bfd *ibfd,
+. asection *sec,
+. struct internal_reloc *reloc,
+. boolean *adjustedp));
+. boolean (*_bfd_coff_link_add_one_symbol) PARAMS ((
+. struct bfd_link_info *info,
+. bfd *abfd,
+. const char *name,
+. flagword flags,
+. asection *section,
+. bfd_vma value,
+. const char *string,
+. boolean copy,
+. boolean collect,
+. struct bfd_link_hash_entry **hashp));
+.
+.} 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,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))
+.
+.#define bfd_coff_swap_lineno_in(a,e,i) \
+. ((coff_backend_info ( a)->_bfd_coff_swap_lineno_in) (a,e,i))
+.
+.#define bfd_coff_swap_reloc_out(abfd, i, o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_out) (abfd, i, o))
+.
+.#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(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))
+.
+.#define bfd_coff_swap_scnhdr_out(abfd, i,o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_out) (abfd, i, o))
+.
+.#define bfd_coff_swap_filehdr_out(abfd, i,o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_out) (abfd, i, o))
+.
+.#define bfd_coff_swap_aouthdr_out(abfd, i,o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_out) (abfd, i, o))
+.
+.#define bfd_coff_filhsz(abfd) (coff_backend_info (abfd)->_bfd_filhsz)
+.#define bfd_coff_aoutsz(abfd) (coff_backend_info (abfd)->_bfd_aoutsz)
+.#define bfd_coff_scnhsz(abfd) (coff_backend_info (abfd)->_bfd_scnhsz)
+.#define bfd_coff_symesz(abfd) (coff_backend_info (abfd)->_bfd_symesz)
+.#define bfd_coff_auxesz(abfd) (coff_backend_info (abfd)->_bfd_auxesz)
+.#define bfd_coff_relsz(abfd) (coff_backend_info (abfd)->_bfd_relsz)
+.#define bfd_coff_linesz(abfd) (coff_backend_info (abfd)->_bfd_linesz)
+.#define bfd_coff_long_filenames(abfd) (coff_backend_info (abfd)->_bfd_coff_long_filenames)
+.#define bfd_coff_swap_filehdr_in(abfd, i,o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o))
+.
+.#define bfd_coff_swap_aouthdr_in(abfd, i,o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_in) (abfd, i, o))
+.
+.#define bfd_coff_swap_scnhdr_in(abfd, i,o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_in) (abfd, i, o))
+.
+.#define bfd_coff_swap_reloc_in(abfd, i, o) \
+. ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_in) (abfd, i, o))
+.
+.#define bfd_coff_bad_format_hook(abfd, filehdr) \
+. ((coff_backend_info (abfd)->_bfd_coff_bad_format_hook) (abfd, filehdr))
+.
+.#define bfd_coff_set_arch_mach_hook(abfd, filehdr)\
+. ((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr))
+.#define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\
+. ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook) (abfd, filehdr, aouthdr))
+.
+.#define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr, name)\
+. ((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook) (abfd, scnhdr, name))
+.
+.#define bfd_coff_set_alignment_hook(abfd, sec, scnhdr)\
+. ((coff_backend_info (abfd)->_bfd_set_alignment_hook) (abfd, sec, scnhdr))
+.
+.#define bfd_coff_slurp_symbol_table(abfd)\
+. ((coff_backend_info (abfd)->_bfd_coff_slurp_symbol_table) (abfd))
+.
+.#define bfd_coff_symname_in_debug(abfd, sym)\
+. ((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym))
+.
+.#define bfd_coff_print_aux(abfd, file, base, symbol, aux, indaux)\
+. ((coff_backend_info (abfd)->_bfd_coff_print_aux)\
+. (abfd, file, base, symbol, aux, indaux))
+.
+.#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, link_info, link_order, reloc, data, src_ptr, dst_ptr))
+.
+.#define bfd_coff_reloc16_estimate(abfd, section, reloc, shrink, link_info)\
+. ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\
+. (abfd, section, reloc, shrink, link_info))
+.
+.#define bfd_coff_sym_is_global(abfd, sym)\
+. ((coff_backend_info (abfd)->_bfd_coff_sym_is_global)\
+. (abfd, sym))
+.
+.#define bfd_coff_compute_section_file_positions(abfd)\
+. ((coff_backend_info (abfd)->_bfd_coff_compute_section_file_positions)\
+. (abfd))
+.
+.#define bfd_coff_start_final_link(obfd, info)\
+. ((coff_backend_info (obfd)->_bfd_coff_start_final_link)\
+. (obfd, info))
+.#define bfd_coff_relocate_section(obfd,info,ibfd,o,con,rel,isyms,secs)\
+. ((coff_backend_info (ibfd)->_bfd_coff_relocate_section)\
+. (obfd, info, ibfd, o, con, rel, isyms, secs))
+.#define bfd_coff_rtype_to_howto(abfd, sec, rel, h, sym, addendp)\
+. ((coff_backend_info (abfd)->_bfd_coff_rtype_to_howto)\
+. (abfd, sec, rel, h, sym, addendp))
+.#define bfd_coff_adjust_symndx(obfd, info, ibfd, sec, rel, adjustedp)\
+. ((coff_backend_info (abfd)->_bfd_coff_adjust_symndx)\
+. (obfd, info, ibfd, sec, rel, adjustedp))
+.#define bfd_coff_link_add_one_symbol(info,abfd,name,flags,section,value,string,cp,coll,hashp)\
+. ((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\
+. (info, abfd, name, flags, section, value, string, cp, coll, hashp))
+.
+*/
+
+/* See whether the magic number matches. */
+
+static boolean
+coff_bad_format_hook (abfd, filehdr)
+ bfd * abfd;
+ PTR filehdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+
+ if (BADMAG (*internal_f))
+ return false;
+
+ /* if the optional header is NULL or not the correct size then
+ quit; the only difference I can see between m88k dgux headers (MC88DMAGIC)
+ and Intel 960 readwrite headers (I960WRMAGIC) is that the
+ optional header is of a different size.
+
+ But the mips keeps extra stuff in it's opthdr, so dont check
+ when doing that
+ */
+
+#if defined(M88) || defined(I960)
+ if (internal_f->f_opthdr != 0 && AOUTSZ != internal_f->f_opthdr)
+ return false;
+#endif
+
+ return true;
+}
+
+/*
+ initialize a section structure with information peculiar to this
+ particular implementation of coff
+*/
+
+static boolean
+coff_new_section_hook (abfd, section)
+ bfd * abfd;
+ asection * section;
+{
+ section->alignment_power = COFF_DEFAULT_SECTION_ALIGNMENT_POWER;
+
+#ifdef RS6000COFF_C
+ if (xcoff_data (abfd)->text_align_power != 0
+ && strcmp (bfd_get_section_name (abfd, section), ".text") == 0)
+ section->alignment_power = xcoff_data (abfd)->text_align_power;
+ if (xcoff_data (abfd)->data_align_power != 0
+ && strcmp (bfd_get_section_name (abfd, section), ".data") == 0)
+ section->alignment_power = xcoff_data (abfd)->data_align_power;
+#endif
+
+ /* Allocate aux records for section symbols, to store size and
+ related info.
+
+ @@ Shouldn't use constant multiplier here! */
+ coffsymbol (section->symbol)->native =
+ (combined_entry_type *) bfd_zalloc (abfd,
+ sizeof (combined_entry_type) * 10);
+
+ /* The .stab section must be aligned to 2**2 at most, because
+ otherwise there may be gaps in the section which gdb will not
+ know how to interpret. Examining the section name is a hack, but
+ that is also how gdb locates the section.
+ We need to handle the .ctors and .dtors sections similarly, to
+ avoid introducing null words in the tables. */
+ if (COFF_DEFAULT_SECTION_ALIGNMENT_POWER > 2
+ && (strncmp (section->name, ".stab", 5) == 0
+ || strcmp (section->name, ".ctors") == 0
+ || strcmp (section->name, ".dtors") == 0))
+ section->alignment_power = 2;
+
+ /* Similarly, the .stabstr section must be aligned to 2**0 at most. */
+ if (COFF_DEFAULT_SECTION_ALIGNMENT_POWER > 0
+ && strncmp (section->name, ".stabstr", 8) == 0)
+ section->alignment_power = 0;
+
+ return true;
+}
+
+#ifdef I960
+
+/* Set the alignment of a BFD section. */
+
+static void
+coff_set_alignment_hook (abfd, section, scnhdr)
+ bfd * abfd;
+ asection * section;
+ PTR scnhdr;
+{
+ struct internal_scnhdr *hdr = (struct internal_scnhdr *) scnhdr;
+ unsigned int i;
+
+ for (i = 0; i < 32; i++)
+ if ((1 << i) >= hdr->s_align)
+ break;
+ section->alignment_power = i;
+}
+
+#else /* ! I960 */
+#ifdef COFF_WITH_PE
+
+/* a couple of macros to help setting the alignment power field */
+#define ALIGN_SET(field,x,y) \
+ if (((field) & IMAGE_SCN_ALIGN_64BYTES) == x )\
+ {\
+ section->alignment_power = y;\
+ }
+
+#define ELIFALIGN_SET(field,x,y) \
+ else if (( (field) & IMAGE_SCN_ALIGN_64BYTES) == x ) \
+ {\
+ section->alignment_power = y;\
+ }
+
+static void
+coff_set_alignment_hook (abfd, section, scnhdr)
+ bfd * abfd;
+ asection * section;
+ PTR scnhdr;
+{
+ struct internal_scnhdr *hdr = (struct internal_scnhdr *) scnhdr;
+
+ ALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_64BYTES, 6)
+ ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_32BYTES, 5)
+ ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_16BYTES, 4)
+ ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_8BYTES, 3)
+ ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_4BYTES, 2)
+ ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_2BYTES, 1)
+ ELIFALIGN_SET (hdr->s_flags, IMAGE_SCN_ALIGN_1BYTES, 0)
+
+#ifdef POWERPC_LE_PE
+ if (strcmp (section->name, ".idata$2") == 0)
+ {
+ section->alignment_power = 0;
+ }
+ else if (strcmp (section->name, ".idata$3") == 0)
+ {
+ section->alignment_power = 0;
+ }
+ else if (strcmp (section->name, ".idata$4") == 0)
+ {
+ section->alignment_power = 2;
+ }
+ else if (strcmp (section->name, ".idata$5") == 0)
+ {
+ section->alignment_power = 2;
+ }
+ else if (strcmp (section->name, ".idata$6") == 0)
+ {
+ section->alignment_power = 1;
+ }
+ else if (strcmp (section->name, ".reloc") == 0)
+ {
+ section->alignment_power = 1;
+ }
+ else if (strncmp (section->name, ".stab", 5) == 0)
+ {
+ section->alignment_power = 2;
+ }
+#endif
+}
+#undef ALIGN_SET
+#undef ELIFALIGN_SET
+
+#else /* ! COFF_WITH_PE */
+#ifdef RS6000COFF_C
+
+/* We grossly abuse this function to handle XCOFF overflow headers.
+ When we see one, we correct the reloc and line number counts in the
+ real header, and remove the section we just created. */
+
+static void
+coff_set_alignment_hook (abfd, section, scnhdr)
+ bfd *abfd;
+ asection *section;
+ PTR scnhdr;
+{
+ struct internal_scnhdr *hdr = (struct internal_scnhdr *) scnhdr;
+ asection *real_sec;
+ asection **ps;
+
+ if ((hdr->s_flags & STYP_OVRFLO) == 0)
+ return;
+
+ real_sec = coff_section_from_bfd_index (abfd, hdr->s_nreloc);
+ if (real_sec == NULL)
+ return;
+
+ real_sec->reloc_count = hdr->s_paddr;
+ real_sec->lineno_count = hdr->s_vaddr;
+
+ for (ps = &abfd->sections; *ps != NULL; ps = &(*ps)->next)
+ {
+ if (*ps == section)
+ {
+ *ps = (*ps)->next;
+ --abfd->section_count;
+ break;
+ }
+ }
+}
+
+#else /* ! RS6000COFF_C */
+
+#define coff_set_alignment_hook \
+ ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void)
+
+#endif /* ! RS6000COFF_C */
+#endif /* ! COFF_WITH_PE */
+#endif /* ! I960 */
+
+#ifndef coff_mkobject
+static boolean
+coff_mkobject (abfd)
+ bfd * abfd;
+{
+ coff_data_type *coff;
+
+ abfd->tdata.coff_obj_data = (struct coff_tdata *) bfd_zalloc (abfd, sizeof (coff_data_type));
+ if (abfd->tdata.coff_obj_data == 0)
+ return false;
+ coff = coff_data (abfd);
+ coff->symbols = (coff_symbol_type *) NULL;
+ coff->conversion_table = (unsigned int *) NULL;
+ coff->raw_syments = (struct coff_ptr_struct *) NULL;
+ coff->relocbase = 0;
+ coff->local_toc_sym_map = 0;
+
+/* make_abs_section(abfd);*/
+
+ return true;
+}
+#endif
+
+/* Create the COFF backend specific information. */
+#ifndef coff_mkobject_hook
+static PTR
+coff_mkobject_hook (abfd, filehdr, aouthdr)
+ bfd * abfd;
+ PTR filehdr;
+ PTR aouthdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ coff_data_type *coff;
+
+ if (coff_mkobject (abfd) == false)
+ return NULL;
+
+ coff = coff_data (abfd);
+
+ coff->sym_filepos = internal_f->f_symptr;
+
+ /* These members communicate important constants about the symbol
+ table to GDB's symbol-reading code. These `constants'
+ unfortunately vary among coff implementations... */
+ coff->local_n_btmask = N_BTMASK;
+ coff->local_n_btshft = N_BTSHFT;
+ coff->local_n_tmask = N_TMASK;
+ coff->local_n_tshift = N_TSHIFT;
+ coff->local_symesz = SYMESZ;
+ coff->local_auxesz = AUXESZ;
+ coff->local_linesz = LINESZ;
+
+ obj_raw_syment_count (abfd) =
+ obj_conv_table_size (abfd) =
+ internal_f->f_nsyms;
+
+#ifdef RS6000COFF_C
+ if ((internal_f->f_flags & F_SHROBJ) != 0)
+ abfd->flags |= DYNAMIC;
+ if (aouthdr != NULL && internal_f->f_opthdr >= AOUTSZ)
+ {
+ struct internal_aouthdr *internal_a =
+ (struct internal_aouthdr *) aouthdr;
+ struct xcoff_tdata *xcoff;
+
+ xcoff = xcoff_data (abfd);
+ xcoff->full_aouthdr = true;
+ xcoff->toc = internal_a->o_toc;
+ xcoff->sntoc = internal_a->o_sntoc;
+ xcoff->snentry = internal_a->o_snentry;
+ xcoff->text_align_power = internal_a->o_algntext;
+ xcoff->data_align_power = internal_a->o_algndata;
+ xcoff->modtype = internal_a->o_modtype;
+ xcoff->cputype = internal_a->o_cputype;
+ xcoff->maxdata = internal_a->o_maxdata;
+ xcoff->maxstack = internal_a->o_maxstack;
+ }
+#endif
+
+ return (PTR) coff;
+}
+#endif
+
+/* Determine the machine architecture and type. FIXME: This is target
+ dependent because the magic numbers are defined in the target
+ dependent header files. But there is no particular need for this.
+ If the magic numbers were moved to a separate file, this function
+ would be target independent and would also be much more successful
+ at linking together COFF files for different architectures. */
+
+static boolean
+coff_set_arch_mach_hook (abfd, filehdr)
+ bfd *abfd;
+ PTR filehdr;
+{
+ long machine;
+ enum bfd_architecture arch;
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+
+ machine = 0;
+ switch (internal_f->f_magic)
+ {
+#ifdef PPCMAGIC
+ case PPCMAGIC:
+ arch = bfd_arch_powerpc;
+ machine = 0; /* what does this mean? (krk) */
+ break;
+#endif
+#ifdef I386MAGIC
+ case I386MAGIC:
+ case I386PTXMAGIC:
+ case I386AIXMAGIC: /* Danbury PS/2 AIX C Compiler */
+ case LYNXCOFFMAGIC: /* shadows the m68k Lynx number below, sigh */
+ arch = bfd_arch_i386;
+ machine = 0;
+ break;
+#endif
+#ifdef A29K_MAGIC_BIG
+ case A29K_MAGIC_BIG:
+ case A29K_MAGIC_LITTLE:
+ arch = bfd_arch_a29k;
+ machine = 0;
+ break;
+#endif
+#ifdef ARMMAGIC
+ case ARMMAGIC:
+ arch = bfd_arch_arm;
+ machine =0;
+ break;
+#endif
+#ifdef MC68MAGIC
+ case MC68MAGIC:
+ case M68MAGIC:
+#ifdef MC68KBCSMAGIC
+ case MC68KBCSMAGIC:
+#endif
+#ifdef APOLLOM68KMAGIC
+ case APOLLOM68KMAGIC:
+#endif
+#ifdef LYNXCOFFMAGIC
+ case LYNXCOFFMAGIC:
+#endif
+ arch = bfd_arch_m68k;
+ machine = 68020;
+ break;
+#endif
+#ifdef MC88MAGIC
+ case MC88MAGIC:
+ case MC88DMAGIC:
+ case MC88OMAGIC:
+ arch = bfd_arch_m88k;
+ machine = 88100;
+ break;
+#endif
+#ifdef Z8KMAGIC
+ case Z8KMAGIC:
+ arch = bfd_arch_z8k;
+ switch (internal_f->f_flags & F_MACHMASK)
+ {
+ case F_Z8001:
+ machine = bfd_mach_z8001;
+ break;
+ case F_Z8002:
+ machine = bfd_mach_z8002;
+ break;
+ default:
+ return false;
+ }
+ break;
+#endif
+#ifdef I860
+ case I860MAGIC:
+ arch = bfd_arch_i860;
+ break;
+#endif
+#ifdef I960
+#ifdef I960ROMAGIC
+ case I960ROMAGIC:
+ case I960RWMAGIC:
+ arch = bfd_arch_i960;
+ switch (F_I960TYPE & internal_f->f_flags)
+ {
+ default:
+ case F_I960CORE:
+ machine = bfd_mach_i960_core;
+ break;
+ case F_I960KB:
+ machine = bfd_mach_i960_kb_sb;
+ break;
+ case F_I960MC:
+ machine = bfd_mach_i960_mc;
+ break;
+ case F_I960XA:
+ machine = bfd_mach_i960_xa;
+ break;
+ case F_I960CA:
+ machine = bfd_mach_i960_ca;
+ break;
+ case F_I960KA:
+ machine = bfd_mach_i960_ka_sa;
+ break;
+ case F_I960JX:
+ machine = bfd_mach_i960_jx;
+ break;
+ case F_I960HX:
+ machine = bfd_mach_i960_hx;
+ break;
+ }
+ break;
+#endif
+#endif
+
+#ifdef RS6000COFF_C
+ case U802ROMAGIC:
+ case U802WRMAGIC:
+ case U802TOCMAGIC:
+ {
+ int cputype;
+
+ if (xcoff_data (abfd)->cputype != -1)
+ cputype = xcoff_data (abfd)->cputype & 0xff;
+ else
+ {
+ /* We did not get a value from the a.out header. If the
+ file has not been stripped, we may be able to get the
+ architecture information from the first symbol, if it
+ is a .file symbol. */
+ if (obj_raw_syment_count (abfd) == 0)
+ cputype = 0;
+ else
+ {
+ bfd_byte buf[SYMESZ];
+ struct internal_syment sym;
+
+ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
+ || bfd_read (buf, 1, SYMESZ, abfd) != SYMESZ)
+ return false;
+ coff_swap_sym_in (abfd, (PTR) buf, (PTR) &sym);
+ if (sym.n_sclass == C_FILE)
+ cputype = sym.n_type & 0xff;
+ else
+ cputype = 0;
+ }
+ }
+
+ /* FIXME: We don't handle all cases here. */
+ switch (cputype)
+ {
+ default:
+ case 0:
+#ifdef POWERMAC
+ /* PowerPC Macs use the same magic numbers as RS/6000
+ (because that's how they were bootstrapped originally),
+ but they are always PowerPC architecture. */
+ arch = bfd_arch_powerpc;
+ machine = 0;
+#else
+ arch = bfd_arch_rs6000;
+ machine = 6000;
+#endif /* POWERMAC */
+ break;
+
+ case 1:
+ arch = bfd_arch_powerpc;
+ machine = 601;
+ break;
+ case 2: /* 64 bit PowerPC */
+ arch = bfd_arch_powerpc;
+ machine = 620;
+ break;
+ case 3:
+ arch = bfd_arch_powerpc;
+ machine = 0;
+ break;
+ case 4:
+ arch = bfd_arch_rs6000;
+ machine = 6000;
+ break;
+ }
+ }
+ break;
+#endif
+
+#ifdef WE32KMAGIC
+ case WE32KMAGIC:
+ arch = bfd_arch_we32k;
+ machine = 0;
+ break;
+#endif
+
+#ifdef H8300MAGIC
+ case H8300MAGIC:
+ arch = bfd_arch_h8300;
+ machine = bfd_mach_h8300;
+ /* !! FIXME this probably isn't the right place for this */
+ abfd->flags |= BFD_IS_RELAXABLE;
+ break;
+#endif
+
+#ifdef H8300HMAGIC
+ case H8300HMAGIC:
+ arch = bfd_arch_h8300;
+ machine = bfd_mach_h8300h;
+ /* !! FIXME this probably isn't the right place for this */
+ abfd->flags |= BFD_IS_RELAXABLE;
+ break;
+#endif
+
+#ifdef SH_ARCH_MAGIC_BIG
+ case SH_ARCH_MAGIC_BIG:
+ case SH_ARCH_MAGIC_LITTLE:
+ arch = bfd_arch_sh;
+ machine = 0;
+ break;
+#endif
+
+#ifdef H8500MAGIC
+ case H8500MAGIC:
+ arch = bfd_arch_h8500;
+ machine = 0;
+ break;
+#endif
+
+#ifdef SPARCMAGIC
+ case SPARCMAGIC:
+#ifdef LYNXCOFFMAGIC
+ case LYNXCOFFMAGIC:
+#endif
+ arch = bfd_arch_sparc;
+ machine = 0;
+ break;
+#endif
+
+ default: /* Unreadable input file type */
+ arch = bfd_arch_obscure;
+ break;
+ }
+
+ bfd_default_set_arch_mach (abfd, arch, machine);
+ return true;
+}
+
+#ifdef SYMNAME_IN_DEBUG
+
+static boolean
+symname_in_debug_hook (abfd, sym)
+ bfd * abfd;
+ struct internal_syment *sym;
+{
+ return SYMNAME_IN_DEBUG (sym) ? true : false;
+}
+
+#else
+
+#define symname_in_debug_hook \
+ (boolean (*) PARAMS ((bfd *, struct internal_syment *))) bfd_false
+
+#endif
+
+#ifdef RS6000COFF_C
+
+/* Handle the csect auxent of a C_EXT or C_HIDEXT symbol. */
+
+static boolean coff_pointerize_aux_hook
+ PARAMS ((bfd *, combined_entry_type *, combined_entry_type *,
+ unsigned int, combined_entry_type *));
+
+/*ARGSUSED*/
+static boolean
+coff_pointerize_aux_hook (abfd, table_base, symbol, indaux, aux)
+ bfd *abfd;
+ combined_entry_type *table_base;
+ combined_entry_type *symbol;
+ unsigned int indaux;
+ combined_entry_type *aux;
+{
+ int class = symbol->u.syment.n_sclass;
+
+ if ((class == C_EXT || class == C_HIDEXT)
+ && indaux + 1 == symbol->u.syment.n_numaux)
+ {
+ if (SMTYP_SMTYP (aux->u.auxent.x_csect.x_smtyp) == XTY_LD)
+ {
+ aux->u.auxent.x_csect.x_scnlen.p =
+ table_base + aux->u.auxent.x_csect.x_scnlen.l;
+ aux->fix_scnlen = 1;
+ }
+
+ /* Return true to indicate that the caller should not do any
+ further work on this auxent. */
+ return true;
+ }
+
+ /* Return false to indicate that this auxent should be handled by
+ the caller. */
+ return false;
+}
+
+#else
+#ifdef I960
+
+/* We don't want to pointerize bal entries. */
+
+static boolean coff_pointerize_aux_hook
+ PARAMS ((bfd *, combined_entry_type *, combined_entry_type *,
+ unsigned int, combined_entry_type *));
+
+/*ARGSUSED*/
+static boolean
+coff_pointerize_aux_hook (abfd, table_base, symbol, indaux, aux)
+ bfd *abfd;
+ combined_entry_type *table_base;
+ combined_entry_type *symbol;
+ unsigned int indaux;
+ combined_entry_type *aux;
+{
+ /* Return true if we don't want to pointerize this aux entry, which
+ is the case for the lastfirst aux entry for a C_LEAFPROC symbol. */
+ return (indaux == 1
+ && (symbol->u.syment.n_sclass == C_LEAFPROC
+ || symbol->u.syment.n_sclass == C_LEAFSTAT
+ || symbol->u.syment.n_sclass == C_LEAFEXT));
+}
+
+#else /* ! I960 */
+
+#define coff_pointerize_aux_hook 0
+
+#endif /* ! I960 */
+#endif /* ! RS6000COFF_C */
+
+/* Print an aux entry. This returns true if it has printed it. */
+
+static boolean coff_print_aux
+ PARAMS ((bfd *, FILE *, combined_entry_type *, combined_entry_type *,
+ combined_entry_type *, unsigned int));
+
+static boolean
+coff_print_aux (abfd, file, table_base, symbol, aux, indaux)
+ bfd *abfd;
+ FILE *file;
+ combined_entry_type *table_base;
+ combined_entry_type *symbol;
+ combined_entry_type *aux;
+ unsigned int indaux;
+{
+#ifdef RS6000COFF_C
+ if ((symbol->u.syment.n_sclass == C_EXT
+ || symbol->u.syment.n_sclass == C_HIDEXT)
+ && indaux + 1 == symbol->u.syment.n_numaux)
+ {
+ /* This is a csect entry. */
+ fprintf (file, "AUX ");
+ if (SMTYP_SMTYP (aux->u.auxent.x_csect.x_smtyp) != XTY_LD)
+ {
+ BFD_ASSERT (! aux->fix_scnlen);
+ fprintf (file, "val %5ld", aux->u.auxent.x_csect.x_scnlen.l);
+ }
+ else
+ {
+ fprintf (file, "indx ");
+ if (! aux->fix_scnlen)
+ fprintf (file, "%4ld", aux->u.auxent.x_csect.x_scnlen.l);
+ else
+ fprintf (file, "%4ld",
+ (long) (aux->u.auxent.x_csect.x_scnlen.p - table_base));
+ }
+ fprintf (file,
+ " prmhsh %ld snhsh %u typ %d algn %d clss %u stb %ld snstb %u",
+ aux->u.auxent.x_csect.x_parmhash,
+ (unsigned int) aux->u.auxent.x_csect.x_snhash,
+ SMTYP_SMTYP (aux->u.auxent.x_csect.x_smtyp),
+ SMTYP_ALIGN (aux->u.auxent.x_csect.x_smtyp),
+ (unsigned int) aux->u.auxent.x_csect.x_smclas,
+ aux->u.auxent.x_csect.x_stab,
+ (unsigned int) aux->u.auxent.x_csect.x_snstab);
+ return true;
+ }
+#endif
+
+ /* Return false to indicate that no special action was taken. */
+ return false;
+}
+
+/*
+SUBSUBSECTION
+ Writing relocations
+
+ To write relocations, the back end steps though the
+ canonical relocation table and create an
+ @code{internal_reloc}. The symbol index to use is removed from
+ the @code{offset} field in the symbol table supplied. The
+ address comes directly from the sum of the section base
+ address and the relocation offset; the type is dug directly
+ from the howto field. Then the @code{internal_reloc} is
+ swapped into the shape of an @code{external_reloc} and written
+ out to disk.
+
+*/
+
+#ifdef TARG_AUX
+
+static int compare_arelent_ptr PARAMS ((const PTR, const PTR));
+
+/* AUX's ld wants relocations to be sorted */
+static int
+compare_arelent_ptr (x, y)
+ const PTR x;
+ const PTR y;
+{
+ const arelent **a = (const arelent **) x;
+ const arelent **b = (const arelent **) y;
+ bfd_size_type aadr = (*a)->address;
+ bfd_size_type badr = (*b)->address;
+
+ return (aadr < badr ? -1 : badr < aadr ? 1 : 0);
+}
+
+#endif /* TARG_AUX */
+
+static boolean
+coff_write_relocs (abfd, first_undef)
+ bfd * abfd;
+ int first_undef;
+{
+ asection *s;
+
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ unsigned int i;
+ struct external_reloc dst;
+ arelent **p;
+
+#ifndef TARG_AUX
+ p = s->orelocation;
+#else
+ /* sort relocations before we write them out */
+ p = (arelent **) bfd_malloc (s->reloc_count * sizeof (arelent *));
+ if (p == NULL && s->reloc_count > 0)
+ return false;
+ memcpy (p, s->orelocation, s->reloc_count * sizeof (arelent *));
+ qsort (p, s->reloc_count, sizeof (arelent *), compare_arelent_ptr);
+#endif
+
+ if (bfd_seek (abfd, s->rel_filepos, SEEK_SET) != 0)
+ return false;
+ for (i = 0; i < s->reloc_count; i++)
+ {
+ struct internal_reloc n;
+ arelent *q = p[i];
+ memset ((PTR) & n, 0, sizeof (n));
+
+ /* Now we've renumbered the symbols we know where the
+ undefined symbols live in the table. Check the reloc
+ entries for symbols who's output bfd isn't the right one.
+ This is because the symbol was undefined (which means
+ that all the pointers are never made to point to the same
+ place). This is a bad thing,'cause the symbols attached
+ to the output bfd are indexed, so that the relocation
+ entries know which symbol index they point to. So we
+ have to look up the output symbol here. */
+
+ if (q->sym_ptr_ptr[0]->the_bfd != abfd)
+ {
+ int i;
+ const char *sname = q->sym_ptr_ptr[0]->name;
+ asymbol **outsyms = abfd->outsymbols;
+ for (i = first_undef; outsyms[i]; i++)
+ {
+ const char *intable = outsyms[i]->name;
+ if (strcmp (intable, sname) == 0) {
+ /* got a hit, so repoint the reloc */
+ q->sym_ptr_ptr = outsyms + i;
+ break;
+ }
+ }
+ }
+
+ n.r_vaddr = q->address + s->vma;
+
+#ifdef R_IHCONST
+ /* The 29k const/consth reloc pair is a real kludge. The consth
+ part doesn't have a symbol; it has an offset. So rebuilt
+ that here. */
+ if (q->howto->type == R_IHCONST)
+ n.r_symndx = q->addend;
+ else
+#endif
+ if (q->sym_ptr_ptr)
+ {
+ if (q->sym_ptr_ptr == bfd_abs_section_ptr->symbol_ptr_ptr)
+ /* This is a relocation relative to the absolute symbol. */
+ n.r_symndx = -1;
+ else
+ {
+ n.r_symndx = get_index ((*(q->sym_ptr_ptr)));
+ /* Take notice if the symbol reloc points to a symbol
+ we don't have in our symbol table. What should we
+ do for this?? */
+ if (n.r_symndx > obj_conv_table_size (abfd))
+ abort ();
+ }
+ }
+
+#ifdef SWAP_OUT_RELOC_OFFSET
+ n.r_offset = q->addend;
+#endif
+
+#ifdef SELECT_RELOC
+ /* Work out reloc type from what is required */
+ SELECT_RELOC (n, q->howto);
+#else
+ n.r_type = q->howto->type;
+#endif
+ coff_swap_reloc_out (abfd, &n, &dst);
+ if (bfd_write ((PTR) & dst, 1, RELSZ, abfd) != RELSZ)
+ return false;
+ }
+
+#ifdef TARG_AUX
+ if (p != NULL)
+ free (p);
+#endif
+ }
+
+ return true;
+}
+
+/* Set flags and magic number of a coff file from architecture and machine
+ type. Result is true if we can represent the arch&type, false if not. */
+
+static boolean
+coff_set_flags (abfd, magicp, flagsp)
+ bfd * abfd;
+ unsigned *magicp;
+ unsigned short *flagsp;
+{
+ switch (bfd_get_arch (abfd))
+ {
+#ifdef Z8KMAGIC
+ case bfd_arch_z8k:
+ *magicp = Z8KMAGIC;
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_z8001:
+ *flagsp = F_Z8001;
+ break;
+ case bfd_mach_z8002:
+ *flagsp = F_Z8002;
+ break;
+ default:
+ return false;
+ }
+ return true;
+#endif
+#ifdef I960ROMAGIC
+
+ case bfd_arch_i960:
+
+ {
+ unsigned flags;
+ *magicp = I960ROMAGIC;
+ /*
+ ((bfd_get_file_flags(abfd) & WP_TEXT) ? I960ROMAGIC :
+ I960RWMAGIC); FIXME???
+ */
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_i960_core:
+ flags = F_I960CORE;
+ break;
+ case bfd_mach_i960_kb_sb:
+ flags = F_I960KB;
+ break;
+ case bfd_mach_i960_mc:
+ flags = F_I960MC;
+ break;
+ case bfd_mach_i960_xa:
+ flags = F_I960XA;
+ break;
+ case bfd_mach_i960_ca:
+ flags = F_I960CA;
+ break;
+ case bfd_mach_i960_ka_sa:
+ flags = F_I960KA;
+ break;
+ case bfd_mach_i960_jx:
+ flags = F_I960JX;
+ break;
+ case bfd_mach_i960_hx:
+ flags = F_I960HX;
+ break;
+ default:
+ return false;
+ }
+ *flagsp = flags;
+ return true;
+ }
+ break;
+#endif
+#ifdef ARMMAGIC
+ case bfd_arch_arm:
+ *magicp = ARMMAGIC;
+ return true;
+#endif
+#ifdef PPCMAGIC
+ case bfd_arch_powerpc:
+ *magicp = PPCMAGIC;
+ return true;
+ break;
+#endif
+#ifdef I386MAGIC
+ case bfd_arch_i386:
+ *magicp = I386MAGIC;
+#ifdef LYNXOS
+ /* Just overwrite the usual value if we're doing Lynx. */
+ *magicp = LYNXCOFFMAGIC;
+#endif
+ return true;
+ break;
+#endif
+#ifdef I860MAGIC
+ case bfd_arch_i860:
+ *magicp = I860MAGIC;
+ return true;
+ break;
+#endif
+#ifdef MC68MAGIC
+ case bfd_arch_m68k:
+#ifdef APOLLOM68KMAGIC
+ *magicp = APOLLO_COFF_VERSION_NUMBER;
+#else
+ *magicp = MC68MAGIC;
+#endif
+#ifdef LYNXOS
+ /* Just overwrite the usual value if we're doing Lynx. */
+ *magicp = LYNXCOFFMAGIC;
+#endif
+ return true;
+ break;
+#endif
+
+#ifdef MC88MAGIC
+ case bfd_arch_m88k:
+ *magicp = MC88OMAGIC;
+ return true;
+ break;
+#endif
+#ifdef H8300MAGIC
+ case bfd_arch_h8300:
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_h8300:
+ *magicp = H8300MAGIC;
+ return true;
+ case bfd_mach_h8300h:
+ *magicp = H8300HMAGIC;
+ return true;
+ }
+ break;
+#endif
+
+#ifdef SH_ARCH_MAGIC_BIG
+ case bfd_arch_sh:
+ if (bfd_big_endian (abfd))
+ *magicp = SH_ARCH_MAGIC_BIG;
+ else
+ *magicp = SH_ARCH_MAGIC_LITTLE;
+ return true;
+ break;
+#endif
+
+#ifdef SPARCMAGIC
+ case bfd_arch_sparc:
+ *magicp = SPARCMAGIC;
+#ifdef LYNXOS
+ /* Just overwrite the usual value if we're doing Lynx. */
+ *magicp = LYNXCOFFMAGIC;
+#endif
+ return true;
+ break;
+#endif
+
+#ifdef H8500MAGIC
+ case bfd_arch_h8500:
+ *magicp = H8500MAGIC;
+ return true;
+ break;
+#endif
+#ifdef A29K_MAGIC_BIG
+ case bfd_arch_a29k:
+ if (bfd_big_endian (abfd))
+ *magicp = A29K_MAGIC_BIG;
+ else
+ *magicp = A29K_MAGIC_LITTLE;
+ return true;
+ break;
+#endif
+
+#ifdef WE32KMAGIC
+ case bfd_arch_we32k:
+ *magicp = WE32KMAGIC;
+ return true;
+ break;
+#endif
+
+#ifdef U802TOCMAGIC
+ case bfd_arch_rs6000:
+#ifndef PPCMAGIC
+ case bfd_arch_powerpc:
+#endif
+ *magicp = U802TOCMAGIC;
+ return true;
+ break;
+#endif
+
+ default: /* Unknown architecture */
+ /* return false; -- fall through to "return false" below, to avoid
+ "statement never reached" errors on the one below. */
+ break;
+ }
+
+ return false;
+}
+
+
+static boolean
+coff_set_arch_mach (abfd, arch, machine)
+ bfd * abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ unsigned dummy1;
+ unsigned short dummy2;
+
+ if (! bfd_default_set_arch_mach (abfd, arch, machine))
+ return false;
+
+ if (arch != bfd_arch_unknown &&
+ coff_set_flags (abfd, &dummy1, &dummy2) != true)
+ return false; /* We can't represent this type */
+
+ return true; /* We're easy ... */
+}
+
+
+/* Calculate the file position for each section. */
+
+static void
+coff_compute_section_file_positions (abfd)
+ bfd * abfd;
+{
+ asection *current;
+ asection *previous = (asection *) NULL;
+ file_ptr sofar = FILHSZ;
+
+#ifndef I960
+ file_ptr old_sofar;
+#endif
+ unsigned int count;
+
+#ifdef RS6000COFF_C
+ /* On XCOFF, if we have symbols, set up the .debug section. */
+ if (bfd_get_symcount (abfd) > 0)
+ {
+ bfd_size_type sz;
+ bfd_size_type i, symcount;
+ asymbol **symp;
+
+ sz = 0;
+ symcount = bfd_get_symcount (abfd);
+ for (symp = abfd->outsymbols, i = 0; i < symcount; symp++, i++)
+ {
+ coff_symbol_type *cf;
+
+ cf = coff_symbol_from (abfd, *symp);
+ if (cf != NULL
+ && cf->native != NULL
+ && SYMNAME_IN_DEBUG (&cf->native->u.syment))
+ {
+ size_t len;
+
+ len = strlen (bfd_asymbol_name (*symp));
+ if (len > SYMNMLEN)
+ sz += len + 3;
+ }
+ }
+ if (sz > 0)
+ {
+ asection *dsec;
+
+ dsec = bfd_make_section_old_way (abfd, ".debug");
+ if (dsec == NULL)
+ abort ();
+ dsec->_raw_size = sz;
+ dsec->flags |= SEC_HAS_CONTENTS;
+ }
+ }
+#endif
+
+#ifdef COFF_IMAGE_WITH_PE
+ int page_size;
+ if (coff_data (abfd)->link_info)
+ {
+ page_size = pe_data (abfd)->pe_opthdr.FileAlignment;
+ }
+ else
+ page_size = PE_DEF_FILE_ALIGNMENT;
+#else
+#ifdef COFF_PAGE_SIZE
+ int page_size = COFF_PAGE_SIZE;
+#endif
+#endif
+
+ if (bfd_get_start_address (abfd))
+ {
+ /* A start address may have been added to the original file. In this
+ case it will need an optional header to record it. */
+ abfd->flags |= EXEC_P;
+ }
+
+ if (abfd->flags & EXEC_P)
+ sofar += AOUTSZ;
+#ifdef RS6000COFF_C
+ else if (xcoff_data (abfd)->full_aouthdr)
+ sofar += AOUTSZ;
+ else
+ sofar += SMALL_AOUTSZ;
+#endif
+
+ sofar += abfd->section_count * SCNHSZ;
+
+#ifdef RS6000COFF_C
+ /* XCOFF handles overflows in the reloc and line number count fields
+ by allocating a new section header to hold the correct counts. */
+ for (current = abfd->sections; current != NULL; current = current->next)
+ if (current->reloc_count >= 0xffff || current->lineno_count >= 0xffff)
+ sofar += SCNHSZ;
+#endif
+
+ for (current = abfd->sections, count = 1;
+ current != (asection *) NULL;
+ current = current->next, ++count)
+ {
+ current->target_index = count;
+
+ /* Only deal with sections which have contents */
+ if (!(current->flags & SEC_HAS_CONTENTS))
+ continue;
+
+#ifdef COFF_WITH_PE
+ /* Do not include the .junk section. This is where we collect section
+ data which we don't need. This is mainly the MS .debug$ data which
+ stores codeview debug data. */
+ if (strcmp (current->name, ".junk") == 0)
+ {
+ continue;
+ }
+#endif
+
+ /* Align the sections in the file to the same boundary on
+ which they are aligned in virtual memory. I960 doesn't
+ do this (FIXME) so we can stay in sync with Intel. 960
+ doesn't yet page from files... */
+#ifndef I960
+ if ((abfd->flags & EXEC_P) != 0)
+ {
+ /* make sure this section is aligned on the right boundary - by
+ padding the previous section up if necessary */
+
+ old_sofar = sofar;
+ sofar = BFD_ALIGN (sofar, 1 << current->alignment_power);
+ if (previous != (asection *) NULL)
+ {
+ previous->_raw_size += sofar - old_sofar;
+ }
+ }
+
+#endif
+
+ /* In demand paged files the low order bits of the file offset
+ must match the low order bits of the virtual address. */
+#ifdef COFF_PAGE_SIZE
+ if ((abfd->flags & D_PAGED) != 0
+ && (current->flags & SEC_ALLOC) != 0)
+ sofar += (current->vma - sofar) % page_size;
+#endif
+ current->filepos = sofar;
+
+#ifdef COFF_IMAGE_WITH_PE
+ /* With PE we have to pad each section to be a multiple of its page size
+ too, and remember both sizes. Cooked_size becomes very useful. */
+ current->_cooked_size = current->_raw_size;
+ current->_raw_size = (current->_raw_size + page_size -1) & -page_size;
+#endif
+
+ sofar += current->_raw_size;
+
+#ifndef I960
+ /* make sure that this section is of the right size too */
+ old_sofar = sofar;
+ sofar = BFD_ALIGN (sofar, 1 << current->alignment_power);
+ current->_raw_size += sofar - old_sofar;
+#endif
+
+#ifdef _LIB
+ /* Force .lib sections to start at zero. The vma is then
+ incremented in coff_set_section_contents. This is right for
+ SVR3.2. */
+ if (strcmp (current->name, _LIB) == 0)
+ bfd_set_section_vma (abfd, current, 0);
+#endif
+
+ previous = current;
+ }
+
+ obj_relocbase (abfd) = sofar;
+ abfd->output_has_begun = true;
+
+}
+
+#if 0
+
+/* This can never work, because it is called too late--after the
+ section positions have been set. I can't figure out what it is
+ for, so I am going to disable it--Ian Taylor 20 March 1996. */
+
+/* If .file, .text, .data, .bss symbols are missing, add them. */
+/* @@ Should we only be adding missing symbols, or overriding the aux
+ values for existing section symbols? */
+static boolean
+coff_add_missing_symbols (abfd)
+ bfd *abfd;
+{
+ unsigned int nsyms = bfd_get_symcount (abfd);
+ asymbol **sympp = abfd->outsymbols;
+ asymbol **sympp2;
+ unsigned int i;
+ int need_text = 1, need_data = 1, need_bss = 1, need_file = 1;
+
+ for (i = 0; i < nsyms; i++)
+ {
+ coff_symbol_type *csym = coff_symbol_from (abfd, sympp[i]);
+ CONST char *name;
+ if (csym)
+ {
+ /* only do this if there is a coff representation of the input
+ symbol */
+ if (csym->native && csym->native->u.syment.n_sclass == C_FILE)
+ {
+ need_file = 0;
+ continue;
+ }
+ name = csym->symbol.name;
+ if (!name)
+ continue;
+ if (!strcmp (name, _TEXT))
+ need_text = 0;
+#ifdef APOLLO_M68
+ else if (!strcmp (name, ".wtext"))
+ need_text = 0;
+#endif
+ else if (!strcmp (name, _DATA))
+ need_data = 0;
+ else if (!strcmp (name, _BSS))
+ need_bss = 0;
+ }
+ }
+ /* Now i == bfd_get_symcount (abfd). */
+ /* @@ For now, don't deal with .file symbol. */
+ need_file = 0;
+
+ if (!need_text && !need_data && !need_bss && !need_file)
+ return true;
+ nsyms += need_text + need_data + need_bss + need_file;
+ sympp2 = (asymbol **) bfd_alloc_by_size_t (abfd, nsyms * sizeof (asymbol *));
+ if (!sympp2)
+ return false;
+ memcpy (sympp2, sympp, i * sizeof (asymbol *));
+ if (need_file)
+ {
+ /* @@ Generate fake .file symbol, in sympp2[i], and increment i. */
+ abort ();
+ }
+ if (need_text)
+ sympp2[i++] = coff_section_symbol (abfd, _TEXT);
+ if (need_data)
+ sympp2[i++] = coff_section_symbol (abfd, _DATA);
+ if (need_bss)
+ sympp2[i++] = coff_section_symbol (abfd, _BSS);
+ BFD_ASSERT (i == nsyms);
+ bfd_set_symtab (abfd, sympp2, nsyms);
+ return true;
+}
+
+#endif /* 0 */
+
+/* SUPPRESS 558 */
+/* SUPPRESS 529 */
+static boolean
+coff_write_object_contents (abfd)
+ bfd * abfd;
+{
+ asection *current;
+ boolean hasrelocs = false;
+ boolean haslinno = false;
+ file_ptr scn_base;
+ file_ptr reloc_base;
+ file_ptr lineno_base;
+ file_ptr sym_base;
+ unsigned long reloc_size = 0;
+ unsigned long lnno_size = 0;
+ asection *text_sec = NULL;
+ asection *data_sec = NULL;
+ asection *bss_sec = NULL;
+
+ struct internal_filehdr internal_f;
+ struct internal_aouthdr internal_a;
+
+ bfd_set_error (bfd_error_system_call);
+
+ /* Make a pass through the symbol table to count line number entries and
+ put them into the correct asections */
+
+ lnno_size = coff_count_linenumbers (abfd) * LINESZ;
+
+ if (abfd->output_has_begun == false)
+ coff_compute_section_file_positions (abfd);
+
+ reloc_base = obj_relocbase (abfd);
+
+ /* Work out the size of the reloc and linno areas */
+
+ for (current = abfd->sections; current != NULL; current =
+ current->next)
+ reloc_size += current->reloc_count * RELSZ;
+
+ lineno_base = reloc_base + reloc_size;
+ sym_base = lineno_base + lnno_size;
+
+ /* Indicate in each section->line_filepos its actual file address */
+ for (current = abfd->sections; current != NULL; current =
+ current->next)
+ {
+ if (current->lineno_count)
+ {
+ current->line_filepos = lineno_base;
+ current->moving_line_filepos = lineno_base;
+ lineno_base += current->lineno_count * LINESZ;
+ }
+ else
+ {
+ current->line_filepos = 0;
+ }
+ if (current->reloc_count)
+ {
+ current->rel_filepos = reloc_base;
+ reloc_base += current->reloc_count * RELSZ;
+ }
+ else
+ {
+ current->rel_filepos = 0;
+ }
+ }
+
+ /* Write section headers to the file. */
+ internal_f.f_nscns = 0;
+
+ if ((abfd->flags & EXEC_P) != 0)
+ scn_base = FILHSZ + AOUTSZ;
+ else
+ {
+ scn_base = FILHSZ;
+#ifdef RS6000COFF_C
+ if (xcoff_data (abfd)->full_aouthdr)
+ scn_base += AOUTSZ;
+ else
+ scn_base += SMALL_AOUTSZ;
+#endif
+ }
+
+ if (bfd_seek (abfd, scn_base, SEEK_SET) != 0)
+ return false;
+
+ for (current = abfd->sections;
+ current != NULL;
+ current = current->next)
+ {
+ struct internal_scnhdr section;
+
+#ifdef COFF_WITH_PE
+ /* Do not include the .junk section. This is where we collect section
+ data which we don't need. This is mainly the MS .debug$ data which
+ stores codeview debug data. */
+ if (strcmp (current->name, ".junk") == 0)
+ {
+ continue;
+ }
+
+ /* If we've got a .reloc section, remember. */
+
+#ifdef COFF_IMAGE_WITH_PE
+ if (strcmp (current->name, ".reloc") == 0)
+ {
+ pe_data (abfd)->has_reloc_section = 1;
+ }
+#endif
+
+#endif
+ internal_f.f_nscns++;
+ strncpy (&(section.s_name[0]), current->name, 8);
+#ifdef _LIB
+ /* Always set s_vaddr of .lib to 0. This is right for SVR3.2
+ Ian Taylor <ian@cygnus.com>. */
+ if (strcmp (current->name, _LIB) == 0)
+ section.s_vaddr = 0;
+ else
+#endif
+ section.s_vaddr = current->vma;
+ section.s_paddr = current->lma;
+ section.s_size = current->_raw_size;
+
+#ifdef COFF_WITH_PE
+ section.s_paddr = current->_cooked_size;
+#endif
+
+ /*
+ If this section has no size or is unloadable then the scnptr
+ will be 0 too
+ */
+ if (current->_raw_size == 0 ||
+ (current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ {
+ section.s_scnptr = 0;
+ }
+ else
+ {
+ section.s_scnptr = current->filepos;
+ }
+ section.s_relptr = current->rel_filepos;
+ section.s_lnnoptr = current->line_filepos;
+ section.s_nreloc = current->reloc_count;
+ section.s_nlnno = current->lineno_count;
+ if (current->reloc_count != 0)
+ hasrelocs = true;
+ if (current->lineno_count != 0)
+ haslinno = true;
+
+#ifdef RS6000COFF_C
+ /* Indicate the use of an XCOFF overflow section header. */
+ if (current->reloc_count >= 0xffff || current->lineno_count >= 0xffff)
+ {
+ section.s_nreloc = 0xffff;
+ section.s_nlnno = 0xffff;
+ }
+#endif
+
+ section.s_flags = sec_to_styp_flags (current->name, current->flags);
+
+ if (!strcmp (current->name, _TEXT))
+ {
+ text_sec = current;
+ }
+ else if (!strcmp (current->name, _DATA))
+ {
+ data_sec = current;
+ }
+ else if (!strcmp (current->name, _BSS))
+ {
+ bss_sec = current;
+ }
+
+#ifdef I960
+ section.s_align = (current->alignment_power
+ ? 1 << current->alignment_power
+ : 0);
+
+#endif
+
+#ifdef COFF_IMAGE_WITH_PE
+ /* suppress output of the sections if they are null. ld includes
+ the bss and data sections even if there is no size assigned
+ to them. NT loader doesn't like it if these section headers are
+ included if the sections themselves are not needed */
+ if (section.s_size == 0)
+ internal_f.f_nscns--;
+ else
+#endif
+ {
+ SCNHDR buff;
+ if (coff_swap_scnhdr_out (abfd, &section, &buff) == 0
+ || bfd_write ((PTR) (&buff), 1, SCNHSZ, abfd) != SCNHSZ)
+ return false;
+ }
+ }
+
+#ifdef RS6000COFF_C
+ /* XCOFF handles overflows in the reloc and line number count fields
+ by creating a new section header to hold the correct values. */
+ for (current = abfd->sections; current != NULL; current = current->next)
+ {
+ if (current->reloc_count >= 0xffff || current->lineno_count >= 0xffff)
+ {
+ struct internal_scnhdr scnhdr;
+ SCNHDR buff;
+
+ internal_f.f_nscns++;
+ strncpy (&(scnhdr.s_name[0]), current->name, 8);
+ scnhdr.s_paddr = current->reloc_count;
+ scnhdr.s_vaddr = current->lineno_count;
+ scnhdr.s_size = 0;
+ scnhdr.s_scnptr = 0;
+ scnhdr.s_relptr = current->rel_filepos;
+ scnhdr.s_lnnoptr = current->line_filepos;
+ scnhdr.s_nreloc = current->target_index;
+ scnhdr.s_nlnno = current->target_index;
+ scnhdr.s_flags = STYP_OVRFLO;
+ if (coff_swap_scnhdr_out (abfd, &scnhdr, &buff) == 0
+ || bfd_write ((PTR) &buff, 1, SCNHSZ, abfd) != SCNHSZ)
+ return false;
+ }
+ }
+#endif
+
+ /* OK, now set up the filehdr... */
+
+ /* Don't include the internal abs section in the section count */
+
+ /*
+ We will NOT put a fucking timestamp in the header here. Every time you
+ put it back, I will come in and take it out again. I'm sorry. This
+ field does not belong here. We fill it with a 0 so it compares the
+ same but is not a reasonable time. -- gnu@cygnus.com
+ */
+ internal_f.f_timdat = 0;
+
+ internal_f.f_flags = 0;
+
+ if (abfd->flags & EXEC_P)
+ internal_f.f_opthdr = AOUTSZ;
+ else
+ {
+ internal_f.f_opthdr = 0;
+#ifdef RS6000COFF_C
+ if (xcoff_data (abfd)->full_aouthdr)
+ internal_f.f_opthdr = AOUTSZ;
+ else
+ internal_f.f_opthdr = SMALL_AOUTSZ;
+#endif
+ }
+
+ if (!hasrelocs)
+ internal_f.f_flags |= F_RELFLG;
+ if (!haslinno)
+ internal_f.f_flags |= F_LNNO;
+ if (abfd->flags & EXEC_P)
+ internal_f.f_flags |= F_EXEC;
+
+ /* FIXME: this is wrong for PPC_PE! */
+ if (bfd_little_endian (abfd))
+ internal_f.f_flags |= F_AR32WR;
+ else
+ internal_f.f_flags |= F_AR32W;
+
+ /*
+ FIXME, should do something about the other byte orders and
+ architectures.
+ */
+
+#ifdef RS6000COFF_C
+ if ((abfd->flags & DYNAMIC) != 0)
+ internal_f.f_flags |= F_SHROBJ;
+ if (bfd_get_section_by_name (abfd, _LOADER) != NULL)
+ internal_f.f_flags |= F_DYNLOAD;
+#endif
+
+ memset (&internal_a, 0, sizeof internal_a);
+
+ /* Set up architecture-dependent stuff */
+
+ {
+ unsigned int magic = 0;
+ unsigned short flags = 0;
+ coff_set_flags (abfd, &magic, &flags);
+ internal_f.f_magic = magic;
+ internal_f.f_flags |= flags;
+ /* ...and the "opt"hdr... */
+
+#ifdef A29K
+#ifdef ULTRA3 /* NYU's machine */
+ /* FIXME: This is a bogus check. I really want to see if there
+ * is a .shbss or a .shdata section, if so then set the magic
+ * number to indicate a shared data executable.
+ */
+ if (internal_f.f_nscns >= 7)
+ internal_a.magic = SHMAGIC; /* Shared magic */
+ else
+#endif /* ULTRA3 */
+ internal_a.magic = NMAGIC; /* Assume separate i/d */
+#define __A_MAGIC_SET__
+#endif /* A29K */
+#ifdef I860
+ /* FIXME: What are the a.out magic numbers for the i860? */
+ internal_a.magic = 0;
+#define __A_MAGIC_SET__
+#endif /* I860 */
+#ifdef I960
+ internal_a.magic = (magic == I960ROMAGIC ? NMAGIC : OMAGIC);
+#define __A_MAGIC_SET__
+#endif /* I960 */
+#if M88
+#define __A_MAGIC_SET__
+ internal_a.magic = PAGEMAGICBCS;
+#endif /* M88 */
+
+#if APOLLO_M68
+#define __A_MAGIC_SET__
+ internal_a.magic = APOLLO_COFF_VERSION_NUMBER;
+#endif
+
+#if defined(M68) || defined(WE32K) || defined(M68K)
+#define __A_MAGIC_SET__
+#if defined(LYNXOS)
+ internal_a.magic = LYNXCOFFMAGIC;
+#else
+#if defined(TARG_AUX)
+ internal_a.magic = (abfd->flags & D_PAGED ? PAGEMAGICPEXECPAGED :
+ abfd->flags & WP_TEXT ? PAGEMAGICPEXECSWAPPED :
+ PAGEMAGICEXECSWAPPED);
+#else
+#if defined (PAGEMAGICPEXECPAGED)
+ internal_a.magic = PAGEMAGICPEXECPAGED;
+#endif
+#endif /* TARG_AUX */
+#endif /* LYNXOS */
+#endif /* M68 || WE32K || M68K */
+
+#if defined(ARM)
+#define __A_MAGIC_SET__
+ internal_a.magic = ZMAGIC;
+#endif
+#if defined(PPC)
+#define __A_MAGIC_SET__
+ internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+#endif
+#if defined(I386)
+#define __A_MAGIC_SET__
+#if defined(LYNXOS)
+ internal_a.magic = LYNXCOFFMAGIC;
+#else /* LYNXOS */
+ internal_a.magic = ZMAGIC;
+#endif /* LYNXOS */
+#endif /* I386 */
+
+#if defined(SPARC)
+#define __A_MAGIC_SET__
+#if defined(LYNXOS)
+ internal_a.magic = LYNXCOFFMAGIC;
+#endif /* LYNXOS */
+#endif /* SPARC */
+
+#if RS6000COFF_C
+#define __A_MAGIC_SET__
+ internal_a.magic = (abfd->flags & D_PAGED) ? RS6K_AOUTHDR_ZMAGIC :
+ (abfd->flags & WP_TEXT) ? RS6K_AOUTHDR_NMAGIC :
+ RS6K_AOUTHDR_OMAGIC;
+#endif
+
+#ifndef __A_MAGIC_SET__
+#include "Your aouthdr magic number is not being set!"
+#else
+#undef __A_MAGIC_SET__
+#endif
+ }
+
+ /* FIXME: Does anybody ever set this to another value? */
+ internal_a.vstamp = 0;
+
+ /* Now should write relocs, strings, syms */
+ obj_sym_filepos (abfd) = sym_base;
+
+ if (bfd_get_symcount (abfd) != 0)
+ {
+ int firstundef;
+#if 0
+ if (!coff_add_missing_symbols (abfd))
+ return false;
+#endif
+ if (!coff_renumber_symbols (abfd, &firstundef))
+ return false;
+ coff_mangle_symbols (abfd);
+ if (! coff_write_symbols (abfd))
+ return false;
+ if (! coff_write_linenumbers (abfd))
+ return false;
+ if (! coff_write_relocs (abfd, firstundef))
+ return false;
+ }
+#ifdef COFF_IMAGE_WITH_PE
+#ifdef PPC
+ else if ((abfd->flags & EXEC_P) != 0)
+ {
+ bfd_byte b;
+
+ /* PowerPC PE appears to require that all executable files be
+ rounded up to the page size. */
+ b = 0;
+ if (bfd_seek (abfd,
+ BFD_ALIGN (sym_base, COFF_PAGE_SIZE) - 1,
+ SEEK_SET) != 0
+ || bfd_write (&b, 1, 1, abfd) != 1)
+ return false;
+ }
+#endif
+#endif
+
+ /* If bfd_get_symcount (abfd) != 0, then we are not using the COFF
+ backend linker, and obj_raw_syment_count is not valid until after
+ coff_write_symbols is called. */
+ if (obj_raw_syment_count (abfd) != 0)
+ {
+ internal_f.f_symptr = sym_base;
+#ifdef RS6000COFF_C
+ /* AIX appears to require that F_RELFLG not be set if there are
+ local symbols but no relocations. */
+ internal_f.f_flags &=~ F_RELFLG;
+#endif
+ }
+ else
+ {
+ internal_f.f_symptr = 0;
+ internal_f.f_flags |= F_LSYMS;
+ }
+
+ if (text_sec)
+ {
+ internal_a.tsize = bfd_get_section_size_before_reloc (text_sec);
+ internal_a.text_start = internal_a.tsize ? text_sec->vma : 0;
+ }
+ if (data_sec)
+ {
+ internal_a.dsize = bfd_get_section_size_before_reloc (data_sec);
+ internal_a.data_start = internal_a.dsize ? data_sec->vma : 0;
+ }
+ if (bss_sec)
+ {
+ internal_a.bsize = bfd_get_section_size_before_reloc (bss_sec);
+ if (internal_a.bsize && bss_sec->vma < internal_a.data_start)
+ internal_a.data_start = bss_sec->vma;
+ }
+
+ internal_a.entry = bfd_get_start_address (abfd);
+ internal_f.f_nsyms = obj_raw_syment_count (abfd);
+
+#ifdef RS6000COFF_C
+ if (xcoff_data (abfd)->full_aouthdr)
+ {
+ bfd_vma toc;
+ asection *loader_sec;
+
+ internal_a.vstamp = 1;
+
+ internal_a.o_snentry = xcoff_data (abfd)->snentry;
+ if (internal_a.o_snentry == 0)
+ internal_a.entry = (bfd_vma) -1;
+
+ if (text_sec != NULL)
+ {
+ internal_a.o_sntext = text_sec->target_index;
+ internal_a.o_algntext = bfd_get_section_alignment (abfd, text_sec);
+ }
+ else
+ {
+ internal_a.o_sntext = 0;
+ internal_a.o_algntext = 0;
+ }
+ if (data_sec != NULL)
+ {
+ internal_a.o_sndata = data_sec->target_index;
+ internal_a.o_algndata = bfd_get_section_alignment (abfd, data_sec);
+ }
+ else
+ {
+ internal_a.o_sndata = 0;
+ internal_a.o_algndata = 0;
+ }
+ loader_sec = bfd_get_section_by_name (abfd, ".loader");
+ if (loader_sec != NULL)
+ internal_a.o_snloader = loader_sec->target_index;
+ else
+ internal_a.o_snloader = 0;
+ if (bss_sec != NULL)
+ internal_a.o_snbss = bss_sec->target_index;
+ else
+ internal_a.o_snbss = 0;
+
+ toc = xcoff_data (abfd)->toc;
+ internal_a.o_toc = toc;
+ internal_a.o_sntoc = xcoff_data (abfd)->sntoc;
+
+ internal_a.o_modtype = xcoff_data (abfd)->modtype;
+ if (xcoff_data (abfd)->cputype != -1)
+ internal_a.o_cputype = xcoff_data (abfd)->cputype;
+ else
+ {
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_rs6000:
+ internal_a.o_cputype = 4;
+ break;
+ case bfd_arch_powerpc:
+ if (bfd_get_mach (abfd) == 0)
+ internal_a.o_cputype = 3;
+ else
+ internal_a.o_cputype = 1;
+ break;
+ default:
+ abort ();
+ }
+ }
+ internal_a.o_maxstack = xcoff_data (abfd)->maxstack;
+ internal_a.o_maxdata = xcoff_data (abfd)->maxdata;
+ }
+#endif
+
+ /* now write them */
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ return false;
+ {
+ FILHDR buff;
+ coff_swap_filehdr_out (abfd, (PTR) & internal_f, (PTR) & buff);
+ if (bfd_write ((PTR) & buff, 1, FILHSZ, abfd) != FILHSZ)
+ return false;
+ }
+ if (abfd->flags & EXEC_P)
+ {
+ AOUTHDR buff;
+ coff_swap_aouthdr_out (abfd, (PTR) & internal_a, (PTR) & buff);
+ if (bfd_write ((PTR) & buff, 1, AOUTSZ, abfd) != AOUTSZ)
+ return false;
+ }
+#ifdef RS6000COFF_C
+ else
+ {
+ AOUTHDR buff;
+ size_t size;
+
+ /* XCOFF seems to always write at least a small a.out header. */
+ coff_swap_aouthdr_out (abfd, (PTR) &internal_a, (PTR) &buff);
+ if (xcoff_data (abfd)->full_aouthdr)
+ size = AOUTSZ;
+ else
+ size = SMALL_AOUTSZ;
+ if (bfd_write ((PTR) &buff, 1, size, abfd) != size)
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+static boolean
+coff_set_section_contents (abfd, section, location, offset, count)
+ bfd * abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (abfd->output_has_begun == false) /* set by bfd.c handler */
+ coff_compute_section_file_positions (abfd);
+
+#ifdef _LIB
+
+ /* The physical address field of a .lib section is used to hold the
+ number of shared libraries in the section. This code counts the
+ number of sections being written, and increments the lma field
+ with the number.
+
+ I have found no documentation on the contents of this section.
+ Experimentation indicates that the section contains zero or more
+ records, each of which has the following structure:
+
+ - a (four byte) word holding the length of this record, in words,
+ - a word that always seems to be set to "2",
+ - the path to a shared library, null-terminated and then padded
+ to a whole word boundary.
+
+ bfd_assert calls have been added to alert if an attempt is made
+ to write a section which doesn't follow these assumptions. The
+ code has been tested on ISC 4.1 by me, and on SCO by Robert Lipe
+ <robertl@arnet.com> (Thanks!).
+
+ Gvran Uddeborg <gvran@uddeborg.pp.se> */
+
+ if (strcmp (section->name, _LIB) == 0)
+ {
+ bfd_byte *rec, *recend;
+
+ rec = (bfd_byte *) location;
+ recend = rec + count;
+ while (rec < recend)
+ {
+ ++section->lma;
+ rec += bfd_get_32 (abfd, rec) * 4;
+ }
+
+ BFD_ASSERT (rec == recend);
+ }
+
+#endif
+
+ /* Don't write out bss sections - one way to do this is to
+ see if the filepos has not been set. */
+ if (section->filepos == 0)
+ return true;
+
+ if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0)
+ return false;
+
+ if (count != 0)
+ {
+ return (bfd_write (location, 1, count, abfd) == count) ? true : false;
+ }
+ return true;
+}
+#if 0
+static boolean
+coff_close_and_cleanup (abfd)
+ bfd *abfd;
+{
+ if (!bfd_read_p (abfd))
+ switch (abfd->format)
+ {
+ case bfd_archive:
+ if (!_bfd_write_archive_contents (abfd))
+ return false;
+ break;
+ case bfd_object:
+ if (!coff_write_object_contents (abfd))
+ return false;
+ break;
+ default:
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ /* We depend on bfd_close to free all the memory on the obstack. */
+ /* FIXME if bfd_release is not using obstacks! */
+ return true;
+}
+
+#endif
+
+static PTR
+buy_and_read (abfd, where, seek_direction, size)
+ bfd *abfd;
+ file_ptr where;
+ int seek_direction;
+ size_t size;
+{
+ PTR area = (PTR) bfd_alloc (abfd, size);
+ if (!area)
+ return (NULL);
+ if (bfd_seek (abfd, where, seek_direction) != 0
+ || bfd_read (area, 1, size, abfd) != size)
+ return (NULL);
+ return (area);
+} /* buy_and_read() */
+
+/*
+SUBSUBSECTION
+ Reading linenumbers
+
+ Creating the linenumber table is done by reading in the entire
+ coff linenumber table, and creating another table for internal use.
+
+ A coff linenumber table is structured so that each function
+ is marked as having a line number of 0. Each line within the
+ function is an offset from the first line in the function. The
+ base of the line number information for the table is stored in
+ the symbol associated with the function.
+
+ The information is copied from the external to the internal
+ table, and each symbol which marks a function is marked by
+ pointing its...
+
+ How does this work ?
+
+*/
+
+static boolean
+coff_slurp_line_table (abfd, asect)
+ bfd *abfd;
+ asection *asect;
+{
+ LINENO *native_lineno;
+ alent *lineno_cache;
+
+ BFD_ASSERT (asect->lineno == (alent *) NULL);
+
+ native_lineno = (LINENO *) buy_and_read (abfd,
+ asect->line_filepos,
+ SEEK_SET,
+ (size_t) (LINESZ *
+ asect->lineno_count));
+ lineno_cache =
+ (alent *) bfd_alloc (abfd, (size_t) ((asect->lineno_count + 1) * sizeof (alent)));
+ if (lineno_cache == NULL)
+ return false;
+ else
+ {
+ unsigned int counter = 0;
+ alent *cache_ptr = lineno_cache;
+ LINENO *src = native_lineno;
+
+ while (counter < asect->lineno_count)
+ {
+ struct internal_lineno dst;
+ coff_swap_lineno_in (abfd, src, &dst);
+ cache_ptr->line_number = dst.l_lnno;
+
+ if (cache_ptr->line_number == 0)
+ {
+ coff_symbol_type *sym =
+ (coff_symbol_type *) (dst.l_addr.l_symndx
+ + obj_raw_syments (abfd))->u.syment._n._n_n._n_zeroes;
+ cache_ptr->u.sym = (asymbol *) sym;
+ if (sym->lineno != NULL)
+ {
+ (*_bfd_error_handler)
+ ("%s: warning: duplicate line number information for `%s'",
+ bfd_get_filename (abfd),
+ bfd_asymbol_name (&sym->symbol));
+ }
+ sym->lineno = cache_ptr;
+ }
+ else
+ {
+ cache_ptr->u.offset = dst.l_addr.l_paddr
+ - bfd_section_vma (abfd, asect);
+ } /* If no linenumber expect a symbol index */
+
+ cache_ptr++;
+ src++;
+ counter++;
+ }
+ cache_ptr->line_number = 0;
+
+ }
+ asect->lineno = lineno_cache;
+ /* FIXME, free native_lineno here, or use alloca or something. */
+ return true;
+}
+
+static boolean
+coff_slurp_symbol_table (abfd)
+ bfd * abfd;
+{
+ combined_entry_type *native_symbols;
+ coff_symbol_type *cached_area;
+ unsigned int *table_ptr;
+
+ unsigned int number_of_symbols = 0;
+
+ if (obj_symbols (abfd))
+ return true;
+
+ /* Read in the symbol table */
+ if ((native_symbols = coff_get_normalized_symtab (abfd)) == NULL)
+ {
+ return (false);
+ } /* on error */
+
+ /* Allocate enough room for all the symbols in cached form */
+ cached_area = ((coff_symbol_type *)
+ bfd_alloc (abfd,
+ (obj_raw_syment_count (abfd)
+ * sizeof (coff_symbol_type))));
+
+ if (cached_area == NULL)
+ return false;
+ table_ptr = ((unsigned int *)
+ bfd_alloc (abfd,
+ (obj_raw_syment_count (abfd)
+ * sizeof (unsigned int))));
+
+ if (table_ptr == NULL)
+ return false;
+ else
+ {
+ coff_symbol_type *dst = cached_area;
+ unsigned int last_native_index = obj_raw_syment_count (abfd);
+ unsigned int this_index = 0;
+ while (this_index < last_native_index)
+ {
+ combined_entry_type *src = native_symbols + this_index;
+ table_ptr[this_index] = number_of_symbols;
+ dst->symbol.the_bfd = abfd;
+
+ dst->symbol.name = (char *) (src->u.syment._n._n_n._n_offset);
+ /* We use the native name field to point to the cached field. */
+ src->u.syment._n._n_n._n_zeroes = (long) dst;
+ dst->symbol.section = coff_section_from_bfd_index (abfd,
+ src->u.syment.n_scnum);
+ dst->symbol.flags = 0;
+ dst->done_lineno = false;
+
+ switch (src->u.syment.n_sclass)
+ {
+#ifdef I960
+ case C_LEAFEXT:
+#if 0
+ dst->symbol.value = src->u.syment.n_value - dst->symbol.section->vma;
+ dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
+ dst->symbol.flags |= BSF_NOT_AT_END | BSF_FUNCTION;
+#endif
+ /* Fall through to next case */
+
+#endif
+
+ case C_EXT:
+#ifdef RS6000COFF_C
+ case C_HIDEXT:
+#endif
+#ifdef COFF_WITH_PE
+ /* PE uses storage class 0x68 to denote a section symbol */
+ case C_SECTION:
+ /* PE uses storage class 0x67 for a weak external symbol. */
+ case C_NT_WEAK:
+#endif
+ if ((src->u.syment.n_scnum) == 0)
+ {
+ if ((src->u.syment.n_value) == 0)
+ {
+ dst->symbol.section = bfd_und_section_ptr;
+ dst->symbol.value = 0;
+ }
+ else
+ {
+ dst->symbol.section = bfd_com_section_ptr;
+ dst->symbol.value = (src->u.syment.n_value);
+ }
+ }
+ else
+ {
+ /* Base the value as an index from the base of the
+ section */
+
+ dst->symbol.flags = BSF_EXPORT | BSF_GLOBAL;
+ dst->symbol.value = (src->u.syment.n_value
+ - dst->symbol.section->vma);
+
+ if (ISFCN ((src->u.syment.n_type)))
+ {
+ /* A function ext does not go at the end of a
+ file. */
+ dst->symbol.flags |= BSF_NOT_AT_END | BSF_FUNCTION;
+ }
+ }
+
+#ifdef RS6000COFF_C
+ /* A C_HIDEXT symbol is not global. */
+ if (src->u.syment.n_sclass == C_HIDEXT)
+ dst->symbol.flags = BSF_LOCAL;
+ /* A symbol with a csect entry should not go at the end. */
+ if (src->u.syment.n_numaux > 0)
+ dst->symbol.flags |= BSF_NOT_AT_END;
+#endif
+
+#ifdef COFF_WITH_PE
+ if (src->u.syment.n_sclass == C_NT_WEAK)
+ dst->symbol.flags = BSF_WEAK;
+#endif
+
+ break;
+
+ case C_STAT: /* static */
+#ifdef I960
+ case C_LEAFSTAT: /* static leaf procedure */
+#endif
+ case C_LABEL: /* label */
+ if (src->u.syment.n_scnum == -2)
+ dst->symbol.flags = BSF_DEBUGGING;
+ else
+ dst->symbol.flags = BSF_LOCAL;
+ /*
+ Base the value as an index from the base of the section, if
+ there is one
+ */
+ if (dst->symbol.section)
+ dst->symbol.value = (src->u.syment.n_value) -
+ dst->symbol.section->vma;
+ else
+ dst->symbol.value = (src->u.syment.n_value);
+ break;
+
+ case C_MOS: /* member of structure */
+ case C_EOS: /* end of structure */
+#ifdef NOTDEF /* C_AUTOARG has the same value */
+#ifdef C_GLBLREG
+ case C_GLBLREG: /* A29k-specific storage class */
+#endif
+#endif
+ case C_REGPARM: /* register parameter */
+ case C_REG: /* register variable */
+#ifdef C_AUTOARG
+ case C_AUTOARG: /* 960-specific storage class */
+#endif
+ case C_TPDEF: /* type definition */
+ case C_ARG:
+ case C_AUTO: /* automatic variable */
+ case C_FIELD: /* bit field */
+ case C_ENTAG: /* enumeration tag */
+ case C_MOE: /* member of enumeration */
+ case C_MOU: /* member of union */
+ case C_UNTAG: /* union tag */
+ dst->symbol.flags = BSF_DEBUGGING;
+ dst->symbol.value = (src->u.syment.n_value);
+ break;
+
+ case C_FILE: /* file name */
+ case C_STRTAG: /* structure tag */
+#ifdef RS6000COFF_C
+ case C_GSYM:
+ case C_LSYM:
+ case C_PSYM:
+ case C_RSYM:
+ case C_RPSYM:
+ case C_STSYM:
+ case C_BCOMM:
+ case C_ECOMM:
+ case C_DECL:
+ case C_ENTRY:
+ case C_FUN:
+ case C_ESTAT:
+#endif
+ dst->symbol.flags = BSF_DEBUGGING;
+ dst->symbol.value = (src->u.syment.n_value);
+ break;
+
+#ifdef RS6000COFF_C
+ case C_BINCL: /* beginning of include file */
+ case C_EINCL: /* ending of include file */
+ /* The value is actually a pointer into the line numbers
+ of the file. We locate the line number entry, and
+ set the section to the section which contains it, and
+ the value to the index in that section. */
+ {
+ asection *sec;
+
+ dst->symbol.flags = BSF_DEBUGGING;
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ if (sec->line_filepos <= (file_ptr) src->u.syment.n_value
+ && ((file_ptr) (sec->line_filepos
+ + sec->lineno_count * LINESZ)
+ > (file_ptr) src->u.syment.n_value))
+ break;
+ if (sec == NULL)
+ dst->symbol.value = 0;
+ else
+ {
+ dst->symbol.section = sec;
+ dst->symbol.value = ((src->u.syment.n_value
+ - sec->line_filepos)
+ / LINESZ);
+ src->fix_line = 1;
+ }
+ }
+ break;
+
+ case C_BSTAT:
+ dst->symbol.flags = BSF_DEBUGGING;
+
+ /* The value is actually a symbol index. Save a pointer
+ to the symbol instead of the index. FIXME: This
+ should use a union. */
+ src->u.syment.n_value =
+ (long) (native_symbols + src->u.syment.n_value);
+ dst->symbol.value = src->u.syment.n_value;
+ src->fix_value = 1;
+ break;
+#endif
+
+ case C_BLOCK: /* ".bb" or ".eb" */
+ case C_FCN: /* ".bf" or ".ef" */
+ case C_EFCN: /* physical end of function */
+ dst->symbol.flags = BSF_LOCAL;
+ /*
+ Base the value as an index from the base of the section
+ */
+ dst->symbol.value = (src->u.syment.n_value) - dst->symbol.section->vma;
+ break;
+
+ case C_NULL:
+ case C_EXTDEF: /* external definition */
+ case C_ULABEL: /* undefined label */
+ case C_USTATIC: /* undefined static */
+#ifndef COFF_WITH_PE
+ /* C_LINE in regular coff is 0x68. NT has taken over this storage
+ class to represent a section symbol */
+ case C_LINE: /* line # reformatted as symbol table entry */
+ /* NT uses 0x67 for a weak symbol, not C_ALIAS. */
+ case C_ALIAS: /* duplicate tag */
+#endif
+ case C_HIDDEN: /* ext symbol in dmert public lib */
+ default:
+ (*_bfd_error_handler)
+ ("%s: Unrecognized storage class %d for %s symbol `%s'",
+ bfd_get_filename (abfd), src->u.syment.n_sclass,
+ dst->symbol.section->name, dst->symbol.name);
+ dst->symbol.flags = BSF_DEBUGGING;
+ dst->symbol.value = (src->u.syment.n_value);
+ break;
+ }
+
+/* BFD_ASSERT(dst->symbol.flags != 0);*/
+
+ dst->native = src;
+
+ dst->symbol.udata.i = 0;
+ dst->lineno = (alent *) NULL;
+ this_index += (src->u.syment.n_numaux) + 1;
+ dst++;
+ number_of_symbols++;
+ } /* walk the native symtab */
+ } /* bfdize the native symtab */
+
+ obj_symbols (abfd) = cached_area;
+ obj_raw_syments (abfd) = native_symbols;
+
+ bfd_get_symcount (abfd) = number_of_symbols;
+ obj_convert (abfd) = table_ptr;
+ /* Slurp the line tables for each section too */
+ {
+ asection *p;
+ p = abfd->sections;
+ while (p)
+ {
+ coff_slurp_line_table (abfd, p);
+ p = p->next;
+ }
+ }
+ return true;
+} /* coff_slurp_symbol_table() */
+
+/* Check whether a symbol is globally visible. This is used by the
+ COFF backend linker code in cofflink.c, since a couple of targets
+ have globally visible symbols which are not class C_EXT. This
+ function need not handle the case of n_class == C_EXT. */
+
+#undef OTHER_GLOBAL_CLASS
+
+#ifdef I960
+#define OTHER_GLOBAL_CLASS C_LEAFEXT
+#endif
+
+#ifdef COFF_WITH_PE
+#define OTHER_GLOBAL_CLASS C_SECTION
+#endif
+
+#ifdef OTHER_GLOBAL_CLASS
+
+static boolean
+coff_sym_is_global (abfd, syment)
+ bfd *abfd;
+ struct internal_syment *syment;
+{
+ if (syment->n_sclass == OTHER_GLOBAL_CLASS)
+ return true;
+ return false;
+}
+
+#undef OTHER_GLOBAL_CLASS
+
+#else /* ! defined (OTHER_GLOBAL_CLASS) */
+
+/* sym_is_global should not be defined if it has nothing to do. */
+
+#define coff_sym_is_global 0
+
+#endif /* ! defined (OTHER_GLOBAL_CLASS) */
+
+/*
+SUBSUBSECTION
+ Reading relocations
+
+ Coff relocations are easily transformed into the internal BFD form
+ (@code{arelent}).
+
+ Reading a coff relocation table is done in the following stages:
+
+ o Read the entire coff relocation table into memory.
+
+ o Process each relocation in turn; first swap it from the
+ external to the internal form.
+
+ o Turn the symbol referenced in the relocation's symbol index
+ into a pointer into the canonical symbol table.
+ This table is the same as the one returned by a call to
+ @code{bfd_canonicalize_symtab}. The back end will call that
+ routine and save the result if a canonicalization hasn't been done.
+
+ o The reloc index is turned into a pointer to a howto
+ structure, in a back end specific way. For instance, the 386
+ and 960 use the @code{r_type} to directly produce an index
+ into a howto table vector; the 88k subtracts a number from the
+ @code{r_type} field and creates an addend field.
+
+
+*/
+
+#ifndef CALC_ADDEND
+#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
+ { \
+ coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
+ if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
+ coffsym = (obj_symbols (abfd) \
+ + (cache_ptr->sym_ptr_ptr - symbols)); \
+ else if (ptr) \
+ coffsym = coff_symbol_from (abfd, ptr); \
+ if (coffsym != (coff_symbol_type *) NULL \
+ && coffsym->native->u.syment.n_scnum == 0) \
+ cache_ptr->addend = 0; \
+ else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
+ && ptr->section != (asection *) NULL) \
+ cache_ptr->addend = - (ptr->section->vma + ptr->value); \
+ else \
+ cache_ptr->addend = 0; \
+ }
+#endif
+
+static boolean
+coff_slurp_reloc_table (abfd, asect, symbols)
+ bfd * abfd;
+ sec_ptr asect;
+ asymbol ** symbols;
+{
+ RELOC *native_relocs;
+ arelent *reloc_cache;
+ arelent *cache_ptr;
+
+ unsigned int idx;
+
+ if (asect->relocation)
+ return true;
+ if (asect->reloc_count == 0)
+ return true;
+ if (asect->flags & SEC_CONSTRUCTOR)
+ return true;
+ if (!coff_slurp_symbol_table (abfd))
+ return false;
+ native_relocs =
+ (RELOC *) buy_and_read (abfd,
+ asect->rel_filepos,
+ SEEK_SET,
+ (size_t) (RELSZ *
+ asect->reloc_count));
+ reloc_cache = (arelent *)
+ bfd_alloc (abfd, (size_t) (asect->reloc_count * sizeof (arelent)));
+
+ if (reloc_cache == NULL)
+ return false;
+
+
+ for (idx = 0; idx < asect->reloc_count; idx++)
+ {
+#ifdef RELOC_PROCESSING
+ struct internal_reloc dst;
+ struct external_reloc *src;
+
+ cache_ptr = reloc_cache + idx;
+ src = native_relocs + idx;
+ coff_swap_reloc_in (abfd, src, &dst);
+
+ RELOC_PROCESSING (cache_ptr, &dst, symbols, abfd, asect);
+#else
+ struct internal_reloc dst;
+ asymbol *ptr;
+ struct external_reloc *src;
+
+ cache_ptr = reloc_cache + idx;
+ src = native_relocs + idx;
+
+ coff_swap_reloc_in (abfd, src, &dst);
+
+
+ cache_ptr->address = dst.r_vaddr;
+
+ if (dst.r_symndx != -1)
+ {
+ /* @@ Should never be greater than count of symbols! */
+ if (dst.r_symndx >= obj_conv_table_size (abfd))
+ abort ();
+ cache_ptr->sym_ptr_ptr = symbols + obj_convert (abfd)[dst.r_symndx];
+ ptr = *(cache_ptr->sym_ptr_ptr);
+ }
+ else
+ {
+ cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ ptr = 0;
+ }
+
+ /* The symbols definitions that we have read in have been
+ relocated as if their sections started at 0. But the offsets
+ refering to the symbols in the raw data have not been
+ modified, so we have to have a negative addend to compensate.
+
+ Note that symbols which used to be common must be left alone */
+
+ /* Calculate any reloc addend by looking at the symbol */
+ CALC_ADDEND (abfd, ptr, dst, cache_ptr);
+
+ cache_ptr->address -= asect->vma;
+/* !! cache_ptr->section = (asection *) NULL;*/
+
+ /* Fill in the cache_ptr->howto field from dst.r_type */
+ RTYPE2HOWTO (cache_ptr, &dst);
+#endif
+
+ }
+
+ asect->relocation = reloc_cache;
+ return true;
+}
+
+#ifndef coff_rtype_to_howto
+#ifdef RTYPE2HOWTO
+
+/* Get the howto structure for a reloc. This is only used if the file
+ including this one defines coff_relocate_section to be
+ _bfd_coff_generic_relocate_section, so it is OK if it does not
+ always work. It is the responsibility of the including file to
+ make sure it is reasonable if it is needed. */
+
+static reloc_howto_type *coff_rtype_to_howto
+ PARAMS ((bfd *, asection *, struct internal_reloc *,
+ struct coff_link_hash_entry *, struct internal_syment *,
+ bfd_vma *));
+
+/*ARGSUSED*/
+static reloc_howto_type *
+coff_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
+ bfd *abfd;
+ asection *sec;
+ struct internal_reloc *rel;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma *addendp;
+{
+ arelent genrel;
+
+ RTYPE2HOWTO (&genrel, rel);
+ return genrel.howto;
+}
+
+#else /* ! defined (RTYPE2HOWTO) */
+
+#define coff_rtype_to_howto NULL
+
+#endif /* ! defined (RTYPE2HOWTO) */
+#endif /* ! defined (coff_rtype_to_howto) */
+
+/* This is stupid. This function should be a boolean predicate. */
+static long
+coff_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd * abfd;
+ sec_ptr section;
+ arelent ** relptr;
+ asymbol ** symbols;
+{
+ arelent *tblptr = section->relocation;
+ unsigned int count = 0;
+
+
+ if (section->flags & SEC_CONSTRUCTOR)
+ {
+ /* this section has relocs made up by us, they are not in the
+ file, so take them out of their chain and place them into
+ the data area provided */
+ arelent_chain *chain = section->constructor_chain;
+ for (count = 0; count < section->reloc_count; count++)
+ {
+ *relptr++ = &chain->relent;
+ chain = chain->next;
+ }
+
+ }
+ else
+ {
+ if (! coff_slurp_reloc_table (abfd, section, symbols))
+ return -1;
+
+ tblptr = section->relocation;
+
+ for (; count++ < section->reloc_count;)
+ *relptr++ = tblptr++;
+
+
+ }
+ *relptr = 0;
+ return section->reloc_count;
+}
+
+#ifdef GNU960
+file_ptr
+coff_sym_filepos (abfd)
+ bfd *abfd;
+{
+ return obj_sym_filepos (abfd);
+}
+#endif
+
+#ifndef coff_reloc16_estimate
+#define coff_reloc16_estimate dummy_reloc16_estimate
+
+static int
+dummy_reloc16_estimate (abfd, input_section, reloc, shrink, link_info)
+ bfd *abfd;
+ asection *input_section;
+ arelent *reloc;
+ unsigned int shrink;
+ struct bfd_link_info *link_info;
+{
+ abort ();
+}
+
+#endif
+
+#ifndef coff_reloc16_extra_cases
+#define coff_reloc16_extra_cases dummy_reloc16_extra_cases
+/* This works even if abort is not declared in any header file. */
+static void
+dummy_reloc16_extra_cases (abfd, link_info, link_order, reloc, data, src_ptr,
+ dst_ptr)
+ bfd *abfd;
+ 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;
+{
+ abort ();
+}
+#endif
+
+/* If coff_relocate_section is defined, we can use the optimized COFF
+ backend linker. Otherwise we must continue to use the old linker. */
+#ifdef coff_relocate_section
+#ifndef coff_bfd_link_hash_table_create
+#define coff_bfd_link_hash_table_create _bfd_coff_link_hash_table_create
+#endif
+#ifndef coff_bfd_link_add_symbols
+#define coff_bfd_link_add_symbols _bfd_coff_link_add_symbols
+#endif
+#ifndef coff_bfd_final_link
+#define coff_bfd_final_link _bfd_coff_final_link
+#endif
+#else /* ! defined (coff_relocate_section) */
+#define coff_relocate_section NULL
+#define coff_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#ifndef coff_bfd_link_add_symbols
+#define coff_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#endif
+#define coff_bfd_final_link _bfd_generic_final_link
+#endif /* ! defined (coff_relocate_section) */
+#define coff_bfd_link_split_section _bfd_generic_link_split_section
+
+#ifndef coff_start_final_link
+#define coff_start_final_link NULL
+#endif
+
+#ifndef coff_adjust_symndx
+#define coff_adjust_symndx NULL
+#endif
+
+#ifndef coff_link_add_one_symbol
+#define coff_link_add_one_symbol _bfd_generic_link_add_one_symbol
+#endif
+
+static CONST bfd_coff_backend_data bfd_coff_std_swap_table =
+{
+ coff_swap_aux_in, coff_swap_sym_in, coff_swap_lineno_in,
+ coff_swap_aux_out, coff_swap_sym_out,
+ coff_swap_lineno_out, coff_swap_reloc_out,
+ coff_swap_filehdr_out, coff_swap_aouthdr_out,
+ coff_swap_scnhdr_out,
+ FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ,
+#ifdef COFF_LONG_FILENAMES
+ true,
+#else
+ false,
+#endif
+ coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
+ coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
+ coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
+ coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
+ coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
+ coff_sym_is_global, coff_compute_section_file_positions,
+ coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
+ coff_adjust_symndx, coff_link_add_one_symbol
+};
+
+#define coff_close_and_cleanup _bfd_generic_close_and_cleanup
+#define coff_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define coff_get_section_contents _bfd_generic_get_section_contents
+
+#ifndef coff_bfd_copy_private_symbol_data
+#define coff_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
+#endif
+
+#ifndef coff_bfd_copy_private_section_data
+#define coff_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
+#endif
+
+#ifndef coff_bfd_copy_private_bfd_data
+#define coff_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
+#endif
+
+#define coff_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#define coff_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+
+#ifndef coff_bfd_print_private_bfd_data
+#define coff_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
+#endif
+
+#ifndef coff_bfd_is_local_label
+#define coff_bfd_is_local_label bfd_generic_is_local_label
+#endif
+#ifndef coff_read_minisymbols
+#define coff_read_minisymbols _bfd_generic_read_minisymbols
+#endif
+#ifndef coff_minisymbol_to_symbol
+#define coff_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+#endif
+
+/* The reloc lookup routine must be supplied by each individual COFF
+ backend. */
+#ifndef coff_bfd_reloc_type_lookup
+#define coff_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+#endif
+
+#ifndef coff_bfd_get_relocated_section_contents
+#define coff_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#endif
+#ifndef coff_bfd_relax_section
+#define coff_bfd_relax_section bfd_generic_relax_section
+#endif
diff --git a/contrib/gdb/bfd/coffgen.c b/contrib/gdb/bfd/coffgen.c
new file mode 100644
index 0000000..285fe61
--- /dev/null
+++ b/contrib/gdb/bfd/coffgen.c
@@ -0,0 +1,2121 @@
+/* Support for the generic parts of COFF, for BFD.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Most of this hacked by Steve Chamberlain, sac@cygnus.com.
+ Split out of coffcode.h by Ian Taylor, ian@cygnus.com. */
+
+/* This file contains COFF code that is not dependent on any
+ particular COFF target. There is only one version of this file in
+ libbfd.a, so no target specific code may be put in here. Or, to
+ put it another way,
+
+ ********** DO NOT PUT TARGET SPECIFIC CODE IN THIS FILE **********
+
+ If you need to add some target specific behaviour, add a new hook
+ function to bfd_coff_backend_data.
+
+ Some of these functions are also called by the ECOFF routines.
+ Those functions may not use any COFF specific information, such as
+ coff_data (abfd). */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+static void coff_fix_symbol_name
+ PARAMS ((bfd *, asymbol *, combined_entry_type *, bfd_size_type *,
+ asection **, bfd_size_type *));
+static boolean coff_write_symbol
+ PARAMS ((bfd *, asymbol *, combined_entry_type *, unsigned int *,
+ bfd_size_type *, asection **, bfd_size_type *));
+static boolean coff_write_alien_symbol
+ PARAMS ((bfd *, asymbol *, unsigned int *, bfd_size_type *,
+ asection **, bfd_size_type *));
+static boolean coff_write_native_symbol
+ PARAMS ((bfd *, coff_symbol_type *, unsigned int *, bfd_size_type *,
+ asection **, bfd_size_type *));
+static void coff_pointerize_aux
+ PARAMS ((bfd *, combined_entry_type *, combined_entry_type *,
+ unsigned int, combined_entry_type *));
+
+#define STRING_SIZE_SIZE (4)
+
+/* 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
+make_a_section_from_file (abfd, hdr, target_index)
+ bfd *abfd;
+ struct internal_scnhdr *hdr;
+ unsigned int target_index;
+{
+ asection *return_section;
+ char *name;
+
+ /* Assorted wastage to null-terminate the name, thanks AT&T! */
+ name = bfd_alloc (abfd, sizeof (hdr->s_name) + 1);
+ if (name == NULL)
+ return false;
+ strncpy (name, (char *) &hdr->s_name[0], sizeof (hdr->s_name));
+ name[sizeof (hdr->s_name)] = 0;
+
+ return_section = bfd_make_section_anyway (abfd, name);
+ if (return_section == NULL)
+ return false;
+
+ return_section->vma = hdr->s_vaddr;
+ return_section->lma = hdr->s_paddr;
+ return_section->_raw_size = hdr->s_size;
+ return_section->filepos = hdr->s_scnptr;
+ return_section->rel_filepos = hdr->s_relptr;
+ return_section->reloc_count = hdr->s_nreloc;
+
+ bfd_coff_set_alignment_hook (abfd, return_section, hdr);
+
+ return_section->line_filepos = hdr->s_lnnoptr;
+
+ return_section->lineno_count = hdr->s_nlnno;
+ return_section->userdata = NULL;
+ return_section->next = (asection *) NULL;
+ return_section->flags = bfd_coff_styp_to_sec_flags_hook (abfd, hdr, name);
+
+ return_section->target_index = target_index;
+
+ /* At least on i386-coff, the line number count for a shared library
+ section must be ignored. */
+ if ((return_section->flags & SEC_COFF_SHARED_LIBRARY) != 0)
+ return_section->lineno_count = 0;
+
+ if (hdr->s_nreloc != 0)
+ return_section->flags |= SEC_RELOC;
+ /* FIXME: should this check 'hdr->s_size > 0' */
+ if (hdr->s_scnptr != 0)
+ return_section->flags |= SEC_HAS_CONTENTS;
+ return true;
+}
+
+/* Read in a COFF object and make it into a BFD. This is used by
+ ECOFF as well. */
+
+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;
+{
+ flagword oflags = abfd->flags;
+ bfd_vma ostart = bfd_get_start_address (abfd);
+ PTR tdata;
+ size_t readsize; /* length of file_info */
+ unsigned int scnhsz;
+ char *external_sections;
+
+ if (!(internal_f->f_flags & F_RELFLG))
+ abfd->flags |= HAS_RELOC;
+ if ((internal_f->f_flags & F_EXEC))
+ abfd->flags |= EXEC_P;
+ if (!(internal_f->f_flags & F_LNNO))
+ abfd->flags |= HAS_LINENO;
+ 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)
+ abfd->flags |= HAS_SYMS;
+
+ if (internal_a != (struct internal_aouthdr *) NULL)
+ bfd_get_start_address (abfd) = internal_a->entry;
+ else
+ bfd_get_start_address (abfd) = 0;
+
+ /* Set up the tdata area. ECOFF uses its own routine, and overrides
+ abfd->flags. */
+ tdata = bfd_coff_mkobject_hook (abfd, (PTR) internal_f, (PTR) internal_a);
+ if (tdata == NULL)
+ return 0;
+
+ scnhsz = bfd_coff_scnhsz (abfd);
+ readsize = nscns * scnhsz;
+ external_sections = (char *) bfd_alloc (abfd, readsize);
+ if (!external_sections)
+ goto fail;
+
+ if (bfd_read ((PTR) external_sections, 1, readsize, abfd) != readsize)
+ goto fail;
+
+ /* Now copy data as required; construct all asections etc */
+ if (nscns != 0)
+ {
+ unsigned int i;
+ for (i = 0; i < nscns; i++)
+ {
+ struct internal_scnhdr tmp;
+ bfd_coff_swap_scnhdr_in (abfd,
+ (PTR) (external_sections + i * scnhsz),
+ (PTR) & tmp);
+ make_a_section_from_file (abfd, &tmp, i + 1);
+ }
+ }
+
+ /* make_abs_section (abfd); */
+
+ if (bfd_coff_set_arch_mach_hook (abfd, (PTR) internal_f) == false)
+ goto fail;
+
+ return abfd->xvec;
+
+ fail:
+ bfd_release (abfd, tdata);
+ abfd->flags = oflags;
+ bfd_get_start_address (abfd) = ostart;
+ return (const bfd_target *) NULL;
+}
+
+/* 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. */
+
+const bfd_target *
+coff_object_p (abfd)
+ bfd *abfd;
+{
+ unsigned int filhsz;
+ unsigned int aoutsz;
+ int nscns;
+ PTR filehdr;
+ struct internal_filehdr internal_f;
+ struct internal_aouthdr internal_a;
+
+ /* figure out how much to read */
+ filhsz = bfd_coff_filhsz (abfd);
+ aoutsz = bfd_coff_aoutsz (abfd);
+
+ filehdr = bfd_alloc (abfd, filhsz);
+ if (filehdr == NULL)
+ return 0;
+ if (bfd_read (filehdr, 1, filhsz, abfd) != filhsz)
+ {
+ 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_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+ nscns = internal_f.f_nscns;
+
+ if (internal_f.f_opthdr)
+ {
+ PTR opthdr;
+
+ opthdr = bfd_alloc (abfd, aoutsz);
+ if (opthdr == NULL)
+ return 0;;
+ if (bfd_read (opthdr, 1, aoutsz, abfd) != aoutsz)
+ {
+ return 0;
+ }
+ bfd_coff_swap_aouthdr_in (abfd, opthdr, (PTR) & internal_a);
+ }
+
+ /* Seek past the opt hdr stuff */
+ 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
+ ? &internal_a
+ : (struct internal_aouthdr *) NULL));
+}
+
+/* Get the BFD section from a COFF symbol section number. */
+
+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_ptr;
+ if (index == N_UNDEF)
+ return bfd_und_section_ptr;
+ if (index == N_DEBUG)
+ return bfd_abs_section_ptr;
+
+ while (answer)
+ {
+ if (answer->target_index == index)
+ return answer;
+ answer = answer->next;
+ }
+
+ /* 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. */
+
+long
+coff_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ if (!bfd_coff_slurp_symbol_table (abfd))
+ return -1;
+
+ return (bfd_get_symcount (abfd) + 1) * (sizeof (coff_symbol_type *));
+}
+
+
+/* Canonicalize a COFF symbol table. */
+
+long
+coff_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ unsigned int counter;
+ coff_symbol_type *symbase;
+ coff_symbol_type **location = (coff_symbol_type **) alocation;
+
+ if (!bfd_coff_slurp_symbol_table (abfd))
+ return -1;
+
+ symbase = obj_symbols (abfd);
+ counter = bfd_get_symcount (abfd);
+ while (counter-- > 0)
+ *location++ = symbase++;
+
+ *location = NULL;
+
+ return bfd_get_symcount (abfd);
+}
+
+/* Get the name of a symbol. The caller must pass in a buffer of size
+ >= SYMNMLEN + 1. */
+
+const char *
+_bfd_coff_internal_syment_name (abfd, sym, buf)
+ bfd *abfd;
+ const struct internal_syment *sym;
+ char *buf;
+{
+ /* FIXME: It's not clear this will work correctly if sizeof
+ (_n_zeroes) != 4. */
+ if (sym->_n._n_n._n_zeroes != 0
+ || sym->_n._n_n._n_offset == 0)
+ {
+ memcpy (buf, sym->_n._n_name, SYMNMLEN);
+ buf[SYMNMLEN] = '\0';
+ return buf;
+ }
+ else
+ {
+ const char *strings;
+
+ BFD_ASSERT (sym->_n._n_n._n_offset >= STRING_SIZE_SIZE);
+ strings = obj_coff_strings (abfd);
+ if (strings == NULL)
+ {
+ strings = _bfd_coff_read_string_table (abfd);
+ if (strings == NULL)
+ return NULL;
+ }
+ return strings + sym->_n._n_n._n_offset;
+ }
+}
+
+/* Read in and swap the relocs. This returns a buffer holding the
+ relocs for section SEC in file ABFD. If CACHE is true and
+ INTERNAL_RELOCS is NULL, the relocs read in will be saved in case
+ the function is called again. If EXTERNAL_RELOCS is not NULL, it
+ is a buffer large enough to hold the unswapped relocs. If
+ INTERNAL_RELOCS is not NULL, it is a buffer large enough to hold
+ the swapped relocs. If REQUIRE_INTERNAL is true, then the return
+ value must be INTERNAL_RELOCS. The function returns NULL on error. */
+
+struct internal_reloc *
+_bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs,
+ require_internal, internal_relocs)
+ bfd *abfd;
+ asection *sec;
+ boolean cache;
+ bfd_byte *external_relocs;
+ boolean require_internal;
+ struct internal_reloc *internal_relocs;
+{
+ bfd_size_type relsz;
+ bfd_byte *free_external = NULL;
+ struct internal_reloc *free_internal = NULL;
+ bfd_byte *erel;
+ bfd_byte *erel_end;
+ struct internal_reloc *irel;
+
+ if (coff_section_data (abfd, sec) != NULL
+ && coff_section_data (abfd, sec)->relocs != NULL)
+ {
+ if (! require_internal)
+ return coff_section_data (abfd, sec)->relocs;
+ memcpy (internal_relocs, coff_section_data (abfd, sec)->relocs,
+ sec->reloc_count * sizeof (struct internal_reloc));
+ return internal_relocs;
+ }
+
+ relsz = bfd_coff_relsz (abfd);
+
+ if (external_relocs == NULL)
+ {
+ free_external = (bfd_byte *) bfd_malloc (sec->reloc_count * relsz);
+ if (free_external == NULL && sec->reloc_count > 0)
+ goto error_return;
+ external_relocs = free_external;
+ }
+
+ if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
+ || (bfd_read (external_relocs, relsz, sec->reloc_count, abfd)
+ != relsz * sec->reloc_count))
+ goto error_return;
+
+ if (internal_relocs == NULL)
+ {
+ free_internal = ((struct internal_reloc *)
+ bfd_malloc (sec->reloc_count
+ * sizeof (struct internal_reloc)));
+ if (free_internal == NULL && sec->reloc_count > 0)
+ goto error_return;
+ internal_relocs = free_internal;
+ }
+
+ /* Swap in the relocs. */
+ erel = external_relocs;
+ erel_end = erel + relsz * sec->reloc_count;
+ irel = internal_relocs;
+ for (; erel < erel_end; erel += relsz, irel++)
+ bfd_coff_swap_reloc_in (abfd, (PTR) erel, (PTR) irel);
+
+ if (free_external != NULL)
+ {
+ free (free_external);
+ free_external = NULL;
+ }
+
+ if (cache && free_internal != NULL)
+ {
+ if (coff_section_data (abfd, sec) == NULL)
+ {
+ sec->used_by_bfd =
+ (PTR) bfd_zalloc (abfd,
+ sizeof (struct coff_section_tdata));
+ if (sec->used_by_bfd == NULL)
+ goto error_return;
+ coff_section_data (abfd, sec)->contents = NULL;
+ }
+ coff_section_data (abfd, sec)->relocs = free_internal;
+ }
+
+ return internal_relocs;
+
+ error_return:
+ if (free_external != NULL)
+ free (free_external);
+ if (free_internal != NULL)
+ free (free_internal);
+ return NULL;
+}
+
+/* Set lineno_count for the output sections of a COFF file. */
+
+int
+coff_count_linenumbers (abfd)
+ bfd *abfd;
+{
+ unsigned int limit = bfd_get_symcount (abfd);
+ unsigned int i;
+ int total = 0;
+ asymbol **p;
+ asection *s;
+
+ if (limit == 0)
+ {
+ /* This may be from the backend linker, in which case the
+ lineno_count in the sections is correct. */
+ for (s = abfd->sections; s != NULL; s = s->next)
+ total += s->lineno_count;
+ return total;
+ }
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ BFD_ASSERT (s->lineno_count == 0);
+
+ for (p = abfd->outsymbols, i = 0; i < limit; i++, p++)
+ {
+ asymbol *q_maybe = *p;
+
+ if (bfd_asymbol_flavour (q_maybe) == bfd_target_coff_flavour)
+ {
+ coff_symbol_type *q = coffsymbol (q_maybe);
+
+ /* The AIX 4.1 compiler can sometimes generate line numbers
+ attached to debugging symbols. We try to simply ignore
+ those here. */
+ if (q->lineno != NULL
+ && q->symbol.section->owner != NULL)
+ {
+ /* This symbol has line numbers. Increment the owning
+ section's linenumber count. */
+ alent *l = q->lineno;
+
+ ++q->symbol.section->output_section->lineno_count;
+ ++total;
+ ++l;
+ while (l->line_number != 0)
+ {
+ ++total;
+ ++q->symbol.section->output_section->lineno_count;
+ ++l;
+ }
+ }
+ }
+ }
+
+ return total;
+}
+
+/* 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 *
+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;
+
+ if (bfd_asymbol_bfd (symbol)->tdata.coff_obj_data == (coff_data_type *) NULL)
+ return (coff_symbol_type *) NULL;
+
+ return (coff_symbol_type *) symbol;
+}
+
+static void
+fixup_symbol_value (coff_symbol_ptr, syment)
+ coff_symbol_type *coff_symbol_ptr;
+ struct internal_syment *syment;
+{
+
+ /* Normalize the symbol flags */
+ if (bfd_is_com_section (coff_symbol_ptr->symbol.section))
+ {
+ /* a common symbol is undefined with a value */
+ syment->n_scnum = N_UNDEF;
+ syment->n_value = coff_symbol_ptr->symbol.value;
+ }
+ else if (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING)
+ {
+ syment->n_value = coff_symbol_ptr->symbol.value;
+ }
+ else if (bfd_is_und_section (coff_symbol_ptr->symbol.section))
+ {
+ syment->n_scnum = N_UNDEF;
+ syment->n_value = 0;
+ }
+ else
+ {
+ if (coff_symbol_ptr->symbol.section)
+ {
+ syment->n_scnum =
+ coff_symbol_ptr->symbol.section->output_section->target_index;
+
+ syment->n_value =
+ coff_symbol_ptr->symbol.value +
+ coff_symbol_ptr->symbol.section->output_offset +
+ coff_symbol_ptr->symbol.section->output_section->vma;
+ }
+ else
+ {
+ BFD_ASSERT (0);
+ /* This can happen, but I don't know why yet (steve@cygnus.com) */
+ syment->n_scnum = N_ABS;
+ syment->n_value = coff_symbol_ptr->symbol.value;
+ }
+ }
+}
+
+/* Run through all the symbols in the symbol table and work out what
+ their indexes into the symbol table will be when output.
+
+ Coff requires that each C_FILE symbol points to the next one in the
+ chain, and that the last one points to the first external symbol. We
+ do that here too. */
+
+boolean
+coff_renumber_symbols (bfd_ptr, first_undef)
+ bfd *bfd_ptr;
+ int *first_undef;
+{
+ unsigned int symbol_count = bfd_get_symcount (bfd_ptr);
+ asymbol **symbol_ptr_ptr = bfd_ptr->outsymbols;
+ unsigned int native_index = 0;
+ struct internal_syment *last_file = (struct internal_syment *) NULL;
+ unsigned int symbol_index;
+
+ /* COFF demands that undefined symbols come after all other symbols.
+ Since we don't need to impose this extra knowledge on all our
+ client programs, deal with that here. Sort the symbol table;
+ just move the undefined symbols to the end, leaving the rest
+ alone. The O'Reilly book says that defined global symbols come
+ at the end before the undefined symbols, so we do that here as
+ well. */
+ /* @@ Do we have some condition we could test for, so we don't always
+ have to do this? I don't think relocatability is quite right, but
+ I'm not certain. [raeburn:19920508.1711EST] */
+ {
+ asymbol **newsyms;
+ unsigned int i;
+
+ newsyms = (asymbol **) bfd_alloc_by_size_t (bfd_ptr,
+ sizeof (asymbol *)
+ * (symbol_count + 1));
+ if (!newsyms)
+ return false;
+ bfd_ptr->outsymbols = newsyms;
+ for (i = 0; i < symbol_count; i++)
+ if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) != 0
+ || (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
+ && !bfd_is_com_section (symbol_ptr_ptr[i]->section)
+ && ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL | BSF_FUNCTION))
+ != BSF_GLOBAL)))
+ *newsyms++ = symbol_ptr_ptr[i];
+
+ for (i = 0; i < symbol_count; i++)
+ if (!bfd_is_und_section (symbol_ptr_ptr[i]->section)
+ && (bfd_is_com_section (symbol_ptr_ptr[i]->section)
+ || ((symbol_ptr_ptr[i]->flags & (BSF_GLOBAL
+ | BSF_NOT_AT_END
+ | BSF_FUNCTION))
+ == BSF_GLOBAL)))
+ *newsyms++ = symbol_ptr_ptr[i];
+
+ *first_undef = newsyms - bfd_ptr->outsymbols;
+
+ for (i = 0; i < symbol_count; i++)
+ if ((symbol_ptr_ptr[i]->flags & BSF_NOT_AT_END) == 0
+ && bfd_is_und_section (symbol_ptr_ptr[i]->section))
+ *newsyms++ = symbol_ptr_ptr[i];
+ *newsyms = (asymbol *) NULL;
+ symbol_ptr_ptr = bfd_ptr->outsymbols;
+ }
+
+ 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]);
+ symbol_ptr_ptr[symbol_index]->udata.i = symbol_index;
+ if (coff_symbol_ptr && coff_symbol_ptr->native)
+ {
+ combined_entry_type *s = coff_symbol_ptr->native;
+ int i;
+
+ if (s->u.syment.n_sclass == C_FILE)
+ {
+ if (last_file != (struct internal_syment *) NULL)
+ last_file->n_value = native_index;
+ last_file = &(s->u.syment);
+ }
+ else
+ {
+
+ /* Modify the symbol values according to their section and
+ type */
+
+ fixup_symbol_value (coff_symbol_ptr, &(s->u.syment));
+ }
+ for (i = 0; i < s->u.syment.n_numaux + 1; i++)
+ s[i].offset = native_index++;
+ }
+ else
+ {
+ native_index++;
+ }
+ }
+ obj_conv_table_size (bfd_ptr) = native_index;
+
+ return true;
+}
+
+/* Run thorough the symbol table again, and fix it so that all
+ pointers to entries are changed to the entries' index in the output
+ symbol table. */
+
+void
+coff_mangle_symbols (bfd_ptr)
+ bfd *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]);
+
+ if (coff_symbol_ptr && coff_symbol_ptr->native)
+ {
+ int i;
+ combined_entry_type *s = coff_symbol_ptr->native;
+
+ 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 (s->fix_line)
+ {
+ /* The value is the offset into the line number entries
+ for the symbol's section. On output, the symbol's
+ section should be N_DEBUG. */
+ s->u.syment.n_value =
+ (coff_symbol_ptr->symbol.section->output_section->line_filepos
+ + s->u.syment.n_value * bfd_coff_linesz (bfd_ptr));
+ coff_symbol_ptr->symbol.section =
+ coff_section_from_bfd_index (bfd_ptr, N_DEBUG);
+ BFD_ASSERT (coff_symbol_ptr->symbol.flags & BSF_DEBUGGING);
+ }
+ 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 void
+coff_fix_symbol_name (abfd, symbol, native, string_size_p,
+ debug_string_section_p, debug_string_size_p)
+ bfd *abfd;
+ asymbol *symbol;
+ combined_entry_type *native;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
+{
+ unsigned int name_length;
+ union internal_auxent *auxent;
+ char *name = (char *) (symbol->name);
+
+ if (name == (char *) NULL)
+ {
+ /* coff symbols always have names, so we'll make one up */
+ symbol->name = "strange";
+ name = (char *) symbol->name;
+ }
+ name_length = strlen (name);
+
+ if (native->u.syment.n_sclass == C_FILE
+ && native->u.syment.n_numaux > 0)
+ {
+ strncpy (native->u.syment._n._n_name, ".file", SYMNMLEN);
+ auxent = &(native + 1)->u.auxent;
+
+ if (bfd_coff_long_filenames (abfd))
+ {
+ if (name_length <= FILNMLEN)
+ {
+ strncpy (auxent->x_file.x_fname, name, FILNMLEN);
+ }
+ else
+ {
+ auxent->x_file.x_n.x_offset = *string_size_p + STRING_SIZE_SIZE;
+ auxent->x_file.x_n.x_zeroes = 0;
+ *string_size_p += name_length + 1;
+ }
+ }
+ else
+ {
+ strncpy (auxent->x_file.x_fname, name, FILNMLEN);
+ if (name_length > FILNMLEN)
+ {
+ name[FILNMLEN] = '\0';
+ }
+ }
+ }
+ else
+ {
+ if (name_length <= SYMNMLEN)
+ {
+ /* This name will fit into the symbol neatly */
+ strncpy (native->u.syment._n._n_name, symbol->name, SYMNMLEN);
+ }
+ else if (!bfd_coff_symname_in_debug (abfd, &native->u.syment))
+ {
+ native->u.syment._n._n_n._n_offset = (*string_size_p
+ + STRING_SIZE_SIZE);
+ native->u.syment._n._n_n._n_zeroes = 0;
+ *string_size_p += 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_p == (asection *) NULL)
+ *debug_string_section_p = 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_p,
+ (PTR) buf,
+ (file_ptr) *debug_string_size_p,
+ (bfd_size_type) 2)
+ || !bfd_set_section_contents (abfd,
+ *debug_string_section_p,
+ (PTR) symbol->name,
+ ((file_ptr) *debug_string_size_p
+ + 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_p + 2;
+ native->u.syment._n._n_n._n_zeroes = 0;
+ *debug_string_size_p += name_length + 3;
+ }
+ }
+}
+
+/* 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. */
+
+#define set_index(symbol, idx) ((symbol)->udata.i = (idx))
+
+/* Write a symbol out to a COFF file. */
+
+static boolean
+coff_write_symbol (abfd, symbol, native, written, string_size_p,
+ debug_string_section_p, debug_string_size_p)
+ bfd *abfd;
+ asymbol *symbol;
+ combined_entry_type *native;
+ unsigned int *written;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
+{
+ 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;
+
+ if (native->u.syment.n_sclass == C_FILE)
+ symbol->flags |= BSF_DEBUGGING;
+
+ if (symbol->flags & BSF_DEBUGGING
+ && bfd_is_abs_section (symbol->section))
+ {
+ native->u.syment.n_scnum = N_DEBUG;
+ }
+ else if (bfd_is_abs_section (symbol->section))
+ {
+ native->u.syment.n_scnum = N_ABS;
+ }
+ 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;
+ }
+
+ coff_fix_symbol_name (abfd, symbol, native, string_size_p,
+ debug_string_section_p, debug_string_size_p);
+
+ symesz = bfd_coff_symesz (abfd);
+ buf = bfd_alloc (abfd, symesz);
+ if (!buf)
+ 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)
+ {
+ bfd_size_type auxesz;
+ unsigned int j;
+
+ auxesz = bfd_coff_auxesz (abfd);
+ buf = bfd_alloc (abfd, auxesz);
+ if (!buf)
+ 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,
+ j,
+ native->u.syment.n_numaux,
+ buf);
+ if (bfd_write (buf, 1, auxesz, abfd) != auxesz)
+ return false;
+ }
+ bfd_release (abfd, buf);
+ }
+
+ /* 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 boolean
+coff_write_alien_symbol (abfd, symbol, written, string_size_p,
+ debug_string_section_p, debug_string_size_p)
+ bfd *abfd;
+ asymbol *symbol;
+ unsigned int *written;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
+{
+ combined_entry_type *native;
+ combined_entry_type dummy;
+
+ native = &dummy;
+ native->u.syment.n_type = T_NULL;
+ native->u.syment.n_flags = 0;
+ 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)
+ {
+ /* There isn't much point to writing out a debugging symbol
+ unless we are prepared to convert it into COFF debugging
+ format. So, we just ignore them. We must clobber the symbol
+ name to keep it from being put in the string table. */
+ symbol->name = "";
+ return true;
+ }
+ 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 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, string_size_p,
+ debug_string_section_p, debug_string_size_p);
+}
+
+/* Write a native symbol to a COFF file. */
+
+static boolean
+coff_write_native_symbol (abfd, symbol, written, string_size_p,
+ debug_string_section_p, debug_string_size_p)
+ bfd *abfd;
+ coff_symbol_type *symbol;
+ unsigned int *written;
+ bfd_size_type *string_size_p;
+ asection **debug_string_section_p;
+ bfd_size_type *debug_string_size_p;
+{
+ combined_entry_type *native = symbol->native;
+ 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 && symbol->symbol.section->owner != NULL)
+ {
+ 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;
+ }
+
+ /* Count and relocate all other linenumbers. */
+ count++;
+ 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,
+ string_size_p, debug_string_section_p,
+ debug_string_size_p);
+}
+
+/* Write out the COFF symbols. */
+
+boolean
+coff_write_symbols (abfd)
+ bfd *abfd;
+{
+ bfd_size_type string_size;
+ asection *debug_string_section;
+ bfd_size_type debug_string_size;
+ unsigned int i;
+ unsigned int limit = bfd_get_symcount (abfd);
+ unsigned int written = 0;
+ asymbol **p;
+
+ string_size = 0;
+ debug_string_section = NULL;
+ debug_string_size = 0;
+
+ /* Seek to the right place */
+ 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);
+
+ if (c_symbol == (coff_symbol_type *) NULL
+ || c_symbol->native == (combined_entry_type *) NULL)
+ {
+ if (!coff_write_alien_symbol (abfd, symbol, &written, &string_size,
+ &debug_string_section,
+ &debug_string_size))
+ return false;
+ }
+ else
+ {
+ if (!coff_write_native_symbol (abfd, c_symbol, &written,
+ &string_size, &debug_string_section,
+ &debug_string_size))
+ return false;
+ }
+ }
+
+ obj_raw_syment_count (abfd) = written;
+
+ /* Now write out strings */
+
+ if (string_size != 0)
+ {
+ unsigned int size = string_size + STRING_SIZE_SIZE;
+ bfd_byte buffer[STRING_SIZE_SIZE];
+
+#if STRING_SIZE_SIZE == 4
+ bfd_h_put_32 (abfd, size, buffer);
+#else
+ #error Change bfd_h_put_32
+#endif
+ 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);
+ coff_symbol_type *c_symbol = coff_symbol_from (abfd, q);
+ size_t maxlen;
+
+ /* 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 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
+ && c_symbol->native->u.syment.n_numaux > 0)
+ maxlen = FILNMLEN;
+ else
+ maxlen = SYMNMLEN;
+
+ 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 = STRING_SIZE_SIZE;
+ bfd_byte buffer[STRING_SIZE_SIZE];
+
+#if STRING_SIZE_SIZE == 4
+ bfd_h_put_32 (abfd, size, buffer);
+#else
+ #error Change bfd_h_put_32
+#endif
+ if (bfd_write ((PTR) buffer, 1, STRING_SIZE_SIZE, abfd)
+ != STRING_SIZE_SIZE)
+ 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;
+}
+
+boolean
+coff_write_linenumbers (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ bfd_size_type linesz;
+ PTR buff;
+
+ linesz = bfd_coff_linesz (abfd);
+ buff = bfd_alloc (abfd, linesz);
+ if (!buff)
+ return false;
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ if (s->lineno_count)
+ {
+ asymbol **q = abfd->outsymbols;
+ if (bfd_seek (abfd, s->line_filepos, SEEK_SET) != 0)
+ return false;
+ /* Find all the linenumbers in this section */
+ while (*q)
+ {
+ asymbol *p = *q;
+ if (p->section->output_section == s)
+ {
+ alent *l =
+ BFD_SEND (bfd_asymbol_bfd (p), _get_lineno,
+ (bfd_asymbol_bfd (p), p));
+ if (l)
+ {
+ /* Found a linenumber entry, output */
+ struct internal_lineno out;
+ memset ((PTR) & out, 0, sizeof (out));
+ out.l_lnno = 0;
+ out.l_addr.l_symndx = l->u.offset;
+ bfd_coff_swap_lineno_out (abfd, &out, buff);
+ 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);
+ if (bfd_write (buff, 1, linesz, abfd) != linesz)
+ return false;
+ l++;
+ }
+ }
+ }
+ q++;
+ }
+ }
+ }
+ bfd_release (abfd, buff);
+ return true;
+}
+
+/*ARGSUSED */
+alent *
+coff_get_lineno (ignore_abfd, symbol)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+{
+ return coffsymbol (symbol)->lineno;
+}
+
+#if 0
+
+/* This is only called from coff_add_missing_symbols, which has been
+ disabled. */
+
+asymbol *
+coff_section_symbol (abfd, name)
+ bfd *abfd;
+ char *name;
+{
+ asection *sec = bfd_make_section_old_way (abfd, name);
+ asymbol *sym;
+ combined_entry_type *csym;
+
+ sym = sec->symbol;
+ csym = coff_symbol_from (abfd, sym)->native;
+ /* Make sure back-end COFF stuff is there. */
+ if (csym == 0)
+ {
+ struct foo
+ {
+ coff_symbol_type sym;
+ /* @@FIXME This shouldn't use a fixed size!! */
+ combined_entry_type e[10];
+ };
+ 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;
+ }
+ csym[0].u.syment.n_sclass = C_STAT;
+ csym[0].u.syment.n_numaux = 1;
+/* SF_SET_STATICS (sym); @@ ??? */
+ csym[1].u.auxent.x_scn.x_scnlen = sec->_raw_size;
+ csym[1].u.auxent.x_scn.x_nreloc = sec->reloc_count;
+ csym[1].u.auxent.x_scn.x_nlinno = sec->lineno_count;
+
+ if (sec->output_section == NULL)
+ {
+ sec->output_section = sec;
+ sec->output_offset = 0;
+ }
+
+ return sym;
+}
+
+#endif /* 0 */
+
+/* This function transforms the offsets into the symbol table into
+ pointers to syments. */
+
+static void
+coff_pointerize_aux (abfd, table_base, symbol, indaux, auxent)
+ bfd *abfd;
+ combined_entry_type *table_base;
+ combined_entry_type *symbol;
+ unsigned int indaux;
+ combined_entry_type *auxent;
+{
+ int type = symbol->u.syment.n_type;
+ int class = symbol->u.syment.n_sclass;
+
+ if (coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
+ {
+ if ((*coff_backend_info (abfd)->_bfd_coff_pointerize_aux_hook)
+ (abfd, table_base, symbol, indaux, auxent))
+ return;
+ }
+
+ /* Don't bother if this is a file or a section */
+ if (class == C_STAT && type == T_NULL)
+ return;
+ if (class == C_FILE)
+ return;
+
+ /* Otherwise patch up */
+#define N_TMASK coff_data (abfd)->local_n_tmask
+#define N_BTSHFT coff_data (abfd)->local_n_btshft
+ if ((ISFCN (type) || ISTAG (class) || class == C_BLOCK)
+ && auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l > 0)
+ {
+ auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p =
+ table_base + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l;
+ auxent->fix_end = 1;
+ }
+ /* A negative tagndx is meaningless, but the SCO 3.2v4 cc can
+ generate one, so we must be careful to ignore it. */
+ if (auxent->u.auxent.x_sym.x_tagndx.l > 0)
+ {
+ auxent->u.auxent.x_sym.x_tagndx.p =
+ table_base + auxent->u.auxent.x_sym.x_tagndx.l;
+ auxent->fix_tag = 1;
+ }
+}
+
+/* Allocate space for the ".debug" section, and read it.
+ We did not read the debug section until now, because
+ we didn't want to go to the trouble until someone needed it. */
+
+static char *
+build_debug_section (abfd)
+ bfd *abfd;
+{
+ char *debug_section;
+ long position;
+
+ asection *sect = bfd_get_section_by_name (abfd, ".debug");
+
+ if (!sect)
+ {
+ 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)
+ return NULL;
+
+ /* Seek to the beginning of the `.debug' section and read it.
+ Save the current position first; it is needed by our caller.
+ Then read debug section and reset the file pointer. */
+
+ position = bfd_tell (abfd);
+ 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;
+ return debug_section;
+}
+
+
+/* Return a pointer to a malloc'd copy of 'name'. 'name' may not be
+ \0-terminated, but will not exceed 'maxlen' characters. The copy *will*
+ be \0-terminated. */
+static char *
+copy_name (abfd, name, maxlen)
+ bfd *abfd;
+ char *name;
+ int maxlen;
+{
+ int len;
+ char *newname;
+
+ for (len = 0; len < maxlen; ++len)
+ {
+ if (name[len] == '\0')
+ {
+ break;
+ }
+ }
+
+ if ((newname = (PTR) bfd_alloc (abfd, len + 1)) == NULL)
+ return (NULL);
+ strncpy (newname, name, len);
+ newname[len] = '\0';
+ return newname;
+}
+
+/* Read in the external symbols. */
+
+boolean
+_bfd_coff_get_external_symbols (abfd)
+ bfd *abfd;
+{
+ bfd_size_type symesz;
+ size_t size;
+ PTR syms;
+
+ if (obj_coff_external_syms (abfd) != NULL)
+ return true;
+
+ symesz = bfd_coff_symesz (abfd);
+
+ size = obj_raw_syment_count (abfd) * symesz;
+
+ syms = (PTR) bfd_malloc (size);
+ if (syms == NULL && size != 0)
+ return false;
+
+ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
+ || bfd_read (syms, size, 1, abfd) != size)
+ {
+ if (syms != NULL)
+ free (syms);
+ return false;
+ }
+
+ obj_coff_external_syms (abfd) = syms;
+
+ return true;
+}
+
+/* Read in the external strings. The strings are not loaded until
+ they are needed. This is because we have no simple way of
+ detecting a missing string table in an archive. */
+
+const char *
+_bfd_coff_read_string_table (abfd)
+ bfd *abfd;
+{
+ char extstrsize[STRING_SIZE_SIZE];
+ size_t strsize;
+ char *strings;
+
+ if (obj_coff_strings (abfd) != NULL)
+ return obj_coff_strings (abfd);
+
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd)),
+ SEEK_SET) != 0)
+ return NULL;
+
+ if (bfd_read (extstrsize, sizeof extstrsize, 1, abfd) != sizeof extstrsize)
+ {
+ if (bfd_get_error () != bfd_error_file_truncated)
+ return NULL;
+
+ /* There is no string table. */
+ strsize = STRING_SIZE_SIZE;
+ }
+ else
+ {
+#if STRING_SIZE_SIZE == 4
+ strsize = bfd_h_get_32 (abfd, (bfd_byte *) extstrsize);
+#else
+ #error Change bfd_h_get_32
+#endif
+ }
+
+ if (strsize < STRING_SIZE_SIZE)
+ {
+ (*_bfd_error_handler)
+ ("%s: bad string table size %lu", bfd_get_filename (abfd),
+ (unsigned long) strsize);
+ bfd_set_error (bfd_error_bad_value);
+ return NULL;
+ }
+
+ strings = (char *) bfd_malloc (strsize);
+ if (strings == NULL)
+ return NULL;
+
+ if (bfd_read (strings + STRING_SIZE_SIZE,
+ strsize - STRING_SIZE_SIZE, 1, abfd)
+ != strsize - STRING_SIZE_SIZE)
+ {
+ free (strings);
+ return NULL;
+ }
+
+ obj_coff_strings (abfd) = strings;
+
+ return strings;
+}
+
+/* Free up the external symbols and strings read from a COFF file. */
+
+boolean
+_bfd_coff_free_symbols (abfd)
+ bfd *abfd;
+{
+ if (obj_coff_external_syms (abfd) != NULL
+ && ! obj_coff_keep_syms (abfd))
+ {
+ free (obj_coff_external_syms (abfd));
+ obj_coff_external_syms (abfd) = NULL;
+ }
+ if (obj_coff_strings (abfd) != NULL
+ && ! obj_coff_keep_strings (abfd))
+ {
+ free (obj_coff_strings (abfd));
+ obj_coff_strings (abfd) = NULL;
+ }
+ return true;
+}
+
+/* Read a symbol table into freshly bfd_allocated memory, swap it, and
+ knit the symbol names into a normalized form. By normalized here I
+ mean that all symbols have an n_offset pointer that points to a null-
+ terminated string. */
+
+combined_entry_type *
+coff_get_normalized_symtab (abfd)
+ bfd *abfd;
+{
+ combined_entry_type *internal;
+ combined_entry_type *internal_ptr;
+ combined_entry_type *symbol_ptr;
+ combined_entry_type *internal_end;
+ bfd_size_type symesz;
+ char *raw_src;
+ char *raw_end;
+ const char *string_table = NULL;
+ char *debug_section = NULL;
+ unsigned long size;
+
+ if (obj_raw_syments (abfd) != NULL)
+ return obj_raw_syments (abfd);
+
+ size = obj_raw_syment_count (abfd) * sizeof (combined_entry_type);
+ internal = (combined_entry_type *) bfd_zalloc (abfd, size);
+ if (internal == NULL && size != 0)
+ return NULL;
+ internal_end = internal + obj_raw_syment_count (abfd);
+
+ if (! _bfd_coff_get_external_symbols (abfd))
+ return NULL;
+
+ raw_src = (char *) obj_coff_external_syms (abfd);
+
+ /* mark the end of the symbols */
+ symesz = bfd_coff_symesz (abfd);
+ raw_end = (char *) raw_src + obj_raw_syment_count (abfd) * symesz;
+
+ /* FIXME SOMEDAY. A string table size of zero is very weird, but
+ probably possible. If one shows up, it will probably kill us. */
+
+ /* Swap all the raw entries */
+ for (internal_ptr = internal;
+ raw_src < raw_end;
+ raw_src += symesz, internal_ptr++)
+ {
+
+ unsigned int i;
+ bfd_coff_swap_sym_in (abfd, (PTR) raw_src,
+ (PTR) & internal_ptr->u.syment);
+ symbol_ptr = internal_ptr;
+
+ for (i = 0;
+ i < symbol_ptr->u.syment.n_numaux;
+ i++)
+ {
+ internal_ptr++;
+ raw_src += symesz;
+ 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));
+ coff_pointerize_aux (abfd, internal, symbol_ptr, i,
+ internal_ptr);
+ }
+ }
+
+ /* Free the raw symbols, but not the strings (if we have them). */
+ obj_coff_keep_strings (abfd) = true;
+ if (! _bfd_coff_free_symbols (abfd))
+ return NULL;
+
+ for (internal_ptr = internal; internal_ptr < internal_end;
+ internal_ptr++)
+ {
+ if (internal_ptr->u.syment.n_sclass == C_FILE
+ && internal_ptr->u.syment.n_numaux > 0)
+ {
+ /* make a file symbol point to the name in the auxent, since
+ the text ".file" is redundant */
+ if ((internal_ptr + 1)->u.auxent.x_file.x_n.x_zeroes == 0)
+ {
+ /* the filename is a long one, point into the string table */
+ if (string_table == NULL)
+ {
+ string_table = _bfd_coff_read_string_table (abfd);
+ if (string_table == NULL)
+ return NULL;
+ }
+
+ internal_ptr->u.syment._n._n_n._n_offset =
+ ((long)
+ (string_table
+ + (internal_ptr + 1)->u.auxent.x_file.x_n.x_offset));
+ }
+ else
+ {
+ /* ordinary short filename, put into memory anyway */
+ internal_ptr->u.syment._n._n_n._n_offset = (long)
+ copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname,
+ FILNMLEN);
+ }
+ }
+ else
+ {
+ if (internal_ptr->u.syment._n._n_n._n_zeroes != 0)
+ {
+ /* This is a "short" name. Make it long. */
+ unsigned long i = 0;
+ char *newstring = NULL;
+
+ /* find the length of this string without walking into memory
+ that isn't ours. */
+ for (i = 0; i < 8; ++i)
+ {
+ if (internal_ptr->u.syment._n._n_name[i] == '\0')
+ {
+ break;
+ } /* if end of string */
+ } /* possible lengths of this string. */
+
+ if ((newstring = (PTR) bfd_alloc (abfd, ++i)) == NULL)
+ return (NULL);
+ memset (newstring, 0, i);
+ strncpy (newstring, internal_ptr->u.syment._n._n_name, i - 1);
+ 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)
+ {
+ string_table = _bfd_coff_read_string_table (abfd);
+ if (string_table == NULL)
+ return NULL;
+ }
+ internal_ptr->u.syment._n._n_n._n_offset =
+ ((long int)
+ (string_table
+ + internal_ptr->u.syment._n._n_n._n_offset));
+ }
+ else
+ {
+ /* Long name in debug section. Very similar. */
+ if (debug_section == NULL)
+ debug_section = build_debug_section (abfd);
+ internal_ptr->u.syment._n._n_n._n_offset = (long int)
+ (debug_section + internal_ptr->u.syment._n._n_n._n_offset);
+ }
+ }
+ internal_ptr += internal_ptr->u.syment.n_numaux;
+ }
+
+ obj_raw_syments (abfd) = internal;
+ BFD_ASSERT (obj_raw_syment_count (abfd)
+ == (unsigned int) (internal_ptr - internal));
+
+ return (internal);
+} /* coff_get_normalized_symtab() */
+
+long
+coff_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ if (bfd_get_format (abfd) != bfd_object)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+ return (asect->reloc_count + 1) * sizeof (arelent *);
+}
+
+asymbol *
+coff_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
+ if (new == NULL)
+ return (NULL);
+ memset (new, 0, sizeof *new);
+ new->symbol.section = 0;
+ new->native = 0;
+ new->lineno = (alent *) NULL;
+ new->done_lineno = false;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+/* Make a debugging symbol. */
+
+asymbol *
+coff_bfd_make_debug_symbol (abfd, ptr, sz)
+ bfd *abfd;
+ PTR ptr;
+ unsigned long sz;
+{
+ coff_symbol_type *new = (coff_symbol_type *) bfd_alloc (abfd, sizeof (coff_symbol_type));
+ if (new == NULL)
+ return (NULL);
+ /* @@ This shouldn't be using a constant multiplier. */
+ new->native = (combined_entry_type *) bfd_zalloc (abfd, sizeof (combined_entry_type) * 10);
+ if (!new->native)
+ return (NULL);
+ new->symbol.section = bfd_abs_section_ptr;
+ new->symbol.flags = BSF_DEBUGGING;
+ new->lineno = (alent *) NULL;
+ new->done_lineno = false;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+/*ARGSUSED */
+void
+coff_get_symbol_info (abfd, symbol, ret)
+ bfd *abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+ if (coffsymbol (symbol)->native != NULL
+ && coffsymbol (symbol)->native->fix_value)
+ {
+ combined_entry_type *psym;
+
+ psym = ((combined_entry_type *)
+ coffsymbol (symbol)->native->u.syment.n_value);
+ ret->value = (bfd_vma) (psym - obj_raw_syments (abfd));
+ }
+}
+
+/* Print out information about COFF symbol. */
+
+void
+coff_print_symbol (abfd, filep, symbol, how)
+ bfd *abfd;
+ PTR filep;
+ asymbol *symbol;
+ bfd_print_symbol_type how;
+{
+ FILE *file = (FILE *) filep;
+
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ fprintf (file, "%s", symbol->name);
+ break;
+
+ case bfd_print_symbol_more:
+ fprintf (file, "coff %s %s",
+ coffsymbol (symbol)->native ? "n" : "g",
+ coffsymbol (symbol)->lineno ? "l" : " ");
+ break;
+
+ case bfd_print_symbol_all:
+ if (coffsymbol (symbol)->native)
+ {
+ unsigned long val;
+ unsigned int aux;
+ combined_entry_type *combined = coffsymbol (symbol)->native;
+ combined_entry_type *root = obj_raw_syments (abfd);
+ struct lineno_cache_entry *l = coffsymbol (symbol)->lineno;
+
+ fprintf (file, "[%3ld]", (long) (combined - root));
+
+ if (! combined->fix_value)
+ val = (unsigned long) combined->u.syment.n_value;
+ else
+ val = ((unsigned long)
+ ((combined_entry_type *) combined->u.syment.n_value
+ - root));
+
+ fprintf (file,
+ "(sec %2d)(fl 0x%02x)(ty %3x)(scl %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,
+ val,
+ symbol->name);
+
+ for (aux = 0; aux < combined->u.syment.n_numaux; aux++)
+ {
+ combined_entry_type *auxp = combined + aux + 1;
+ long tagndx;
+
+ if (auxp->fix_tag)
+ tagndx = auxp->u.auxent.x_sym.x_tagndx.p - root;
+ else
+ tagndx = auxp->u.auxent.x_sym.x_tagndx.l;
+
+ fprintf (file, "\n");
+
+ if (bfd_coff_print_aux (abfd, file, root, combined, auxp, aux))
+ continue;
+
+ switch (combined->u.syment.n_sclass)
+ {
+ case C_FILE:
+ fprintf (file, "File ");
+ break;
+
+ case C_STAT:
+ if (combined->u.syment.n_type == T_NULL)
+ /* probably a section symbol? */
+ {
+ fprintf (file, "AUX scnlen 0x%lx nreloc %d nlnno %d",
+ (long) auxp->u.auxent.x_scn.x_scnlen,
+ auxp->u.auxent.x_scn.x_nreloc,
+ auxp->u.auxent.x_scn.x_nlinno);
+ break;
+ }
+ /* else fall through */
+
+ default:
+ 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);
+ if (auxp->fix_end)
+ fprintf (file, " endndx %ld",
+ ((long)
+ (auxp->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p
+ - root)));
+ break;
+ }
+ }
+
+ if (l)
+ {
+ fprintf (file, "\n%s :", l->u.sym->name);
+ l++;
+ while (l->line_number)
+ {
+ fprintf (file, "\n%4d : 0x%lx",
+ l->line_number,
+ ((unsigned long)
+ (l->u.offset + symbol->section->vma)));
+ l++;
+ }
+ }
+ }
+ else
+ {
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+ fprintf (file, " %-5s %s %s %s",
+ symbol->section->name,
+ coffsymbol (symbol)->native ? "n" : "g",
+ coffsymbol (symbol)->lineno ? "l" : " ",
+ symbol->name);
+ }
+ }
+}
+
+/* Provided a BFD, a section and an offset into the section, calculate
+ and return the name of the source file and the line nearest to the
+ wanted location. */
+
+/*ARGSUSED*/
+boolean
+coff_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;
+{
+ boolean found;
+ unsigned int i;
+ unsigned int line_base;
+ coff_data_type *cof = coff_data (abfd);
+ /* Run through the raw syments if available */
+ combined_entry_type *p;
+ combined_entry_type *pend;
+ alent *l;
+ struct coff_section_tdata *sec_data;
+
+ /* Before looking through the symbol table, try to use a .stab
+ section to find the information. */
+ if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
+ &found, filename_ptr,
+ functionname_ptr, line_ptr,
+ &coff_data (abfd)->line_info))
+ return false;
+ if (found)
+ return true;
+
+ *filename_ptr = 0;
+ *functionname_ptr = 0;
+ *line_ptr = 0;
+
+ /* Don't try and find line numbers in a non coff file */
+ if (abfd->xvec->flavour != bfd_target_coff_flavour)
+ return false;
+
+ if (cof == NULL)
+ return false;
+
+ /* Find the first C_FILE symbol. */
+ p = cof->raw_syments;
+ pend = p + cof->raw_syment_count;
+ while (p < pend)
+ {
+ if (p->u.syment.n_sclass == C_FILE)
+ break;
+ p += 1 + p->u.syment.n_numaux;
+ }
+
+ if (p < pend)
+ {
+ bfd_vma maxdiff;
+
+ /* Look through the C_FILE symbols to find the best one. */
+ *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
+ maxdiff = (bfd_vma) 0 - (bfd_vma) 1;
+ while (1)
+ {
+ combined_entry_type *p2;
+
+ for (p2 = p + 1 + p->u.syment.n_numaux;
+ p2 < pend;
+ p2 += 1 + p2->u.syment.n_numaux)
+ {
+ if (p2->u.syment.n_scnum > 0
+ && (section
+ == coff_section_from_bfd_index (abfd,
+ p2->u.syment.n_scnum)))
+ break;
+ if (p2->u.syment.n_sclass == C_FILE)
+ {
+ p2 = pend;
+ break;
+ }
+ }
+
+ if (p2 < pend
+ && offset >= (bfd_vma) p2->u.syment.n_value
+ && offset - (bfd_vma) p2->u.syment.n_value < maxdiff)
+ {
+ *filename_ptr = (char *) p->u.syment._n._n_n._n_offset;
+ maxdiff = offset - p2->u.syment.n_value;
+ }
+
+ /* Avoid endless loops on erroneous files by ensuring that
+ we always move forward in the file. */
+ if (p - cof->raw_syments >= p->u.syment.n_value)
+ break;
+
+ p = cof->raw_syments + p->u.syment.n_value;
+ if (p > pend || p->u.syment.n_sclass != C_FILE)
+ break;
+ }
+ }
+
+ /* Now wander though the raw linenumbers of the section */
+ /* If we have been called on this section before, and the offset we
+ want is further down then we can prime the lookup loop. */
+ sec_data = coff_section_data (abfd, section);
+ if (sec_data != NULL
+ && sec_data->i > 0
+ && offset >= sec_data->offset)
+ {
+ i = sec_data->i;
+ *functionname_ptr = sec_data->function;
+ line_base = sec_data->line_base;
+ }
+ else
+ {
+ i = 0;
+ line_base = 0;
+ }
+
+ if (section->lineno != NULL)
+ {
+ l = &section->lineno[i];
+
+ for (; i < section->lineno_count; i++)
+ {
+ if (l->line_number == 0)
+ {
+ /* Get the symbol this line number points at */
+ coff_symbol_type *coff = (coff_symbol_type *) (l->u.sym);
+ if (coff->symbol.value > offset)
+ break;
+ *functionname_ptr = coff->symbol.name;
+ if (coff->native)
+ {
+ combined_entry_type *s = coff->native;
+ s = s + 1 + s->u.syment.n_numaux;
+
+ /* In XCOFF a debugging symbol can follow the
+ function symbol. */
+ if (s->u.syment.n_scnum == N_DEBUG)
+ s = s + 1 + s->u.syment.n_numaux;
+
+ /* S should now point to the .bf of the function. */
+ if (s->u.syment.n_numaux)
+ {
+ /* The linenumber is stored in the auxent. */
+ union internal_auxent *a = &((s + 1)->u.auxent);
+ line_base = a->x_sym.x_misc.x_lnsz.x_lnno;
+ *line_ptr = line_base;
+ }
+ }
+ }
+ else
+ {
+ if (l->u.offset + bfd_get_section_vma (abfd, section) > offset)
+ break;
+ *line_ptr = l->line_number + line_base - 1;
+ }
+ l++;
+ }
+ }
+
+ /* Cache the results for the next call. */
+ if (sec_data == NULL && section->owner == abfd)
+ {
+ section->used_by_bfd =
+ ((PTR) bfd_zalloc (abfd,
+ sizeof (struct coff_section_tdata)));
+ sec_data = (struct coff_section_tdata *) section->used_by_bfd;
+ }
+ if (sec_data != NULL)
+ {
+ sec_data->offset = offset;
+ sec_data->i = i;
+ sec_data->function = *functionname_ptr;
+ sec_data->line_base = line_base;
+ }
+
+ return true;
+}
+
+int
+coff_sizeof_headers (abfd, reloc)
+ bfd *abfd;
+ boolean reloc;
+{
+ size_t size;
+
+ if (reloc == false)
+ {
+ size = bfd_coff_filhsz (abfd) + bfd_coff_aoutsz (abfd);
+ }
+ else
+ {
+ size = bfd_coff_filhsz (abfd);
+ }
+
+ size += abfd->section_count * bfd_coff_scnhsz (abfd);
+ return size;
+}
diff --git a/contrib/gdb/bfd/cofflink.c b/contrib/gdb/bfd/cofflink.c
new file mode 100644
index 0000000..c4a42a0
--- /dev/null
+++ b/contrib/gdb/bfd/cofflink.c
@@ -0,0 +1,2327 @@
+/* COFF specific linker code.
+ Copyright 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file contains the COFF backend linker code. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+static boolean coff_link_add_object_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean coff_link_check_archive_element
+ PARAMS ((bfd *, struct bfd_link_info *, boolean *));
+static boolean coff_link_check_ar_symbols
+ PARAMS ((bfd *, struct bfd_link_info *, boolean *));
+static boolean coff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Create an entry in a COFF linker hash table. */
+
+struct bfd_hash_entry *
+_bfd_coff_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct coff_link_hash_entry *ret = (struct coff_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct coff_link_hash_entry *) NULL)
+ ret = ((struct coff_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct coff_link_hash_entry)));
+ if (ret == (struct coff_link_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct coff_link_hash_entry *)
+ _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != (struct coff_link_hash_entry *) NULL)
+ {
+ /* Set local fields. */
+ ret->indx = -1;
+ ret->type = T_NULL;
+ ret->class = C_NULL;
+ ret->numaux = 0;
+ ret->auxbfd = NULL;
+ ret->aux = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize a COFF linker hash table. */
+
+boolean
+_bfd_coff_link_hash_table_init (table, abfd, newfunc)
+ struct coff_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 a COFF linker hash table. */
+
+struct bfd_link_hash_table *
+_bfd_coff_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct coff_link_hash_table *ret;
+
+ ret = ((struct coff_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct coff_link_hash_table)));
+ if (ret == NULL)
+ return NULL;
+ if (! _bfd_coff_link_hash_table_init (ret, abfd,
+ _bfd_coff_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+ return &ret->root;
+}
+
+/* Create an entry in a COFF debug merge hash table. */
+
+struct bfd_hash_entry *
+_bfd_coff_debug_merge_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct coff_debug_merge_hash_entry *ret =
+ (struct coff_debug_merge_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct coff_debug_merge_hash_entry *) NULL)
+ ret = ((struct coff_debug_merge_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct coff_debug_merge_hash_entry)));
+ if (ret == (struct coff_debug_merge_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct coff_debug_merge_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ if (ret != (struct coff_debug_merge_hash_entry *) NULL)
+ {
+ /* Set local fields. */
+ ret->types = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Given a COFF BFD, add symbols to the global hash table as
+ appropriate. */
+
+boolean
+_bfd_coff_link_add_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ switch (bfd_get_format (abfd))
+ {
+ case bfd_object:
+ return coff_link_add_object_symbols (abfd, info);
+ case bfd_archive:
+ return (_bfd_generic_link_add_archive_symbols
+ (abfd, info, coff_link_check_archive_element));
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+}
+
+/* Add symbols from a COFF object file. */
+
+static boolean
+coff_link_add_object_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ if (! _bfd_coff_get_external_symbols (abfd))
+ return false;
+ if (! coff_link_add_symbols (abfd, info))
+ return false;
+
+ if (! info->keep_memory)
+ {
+ if (! _bfd_coff_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 via
+ _bfd_generic_link_add_archive_symbols. */
+
+static boolean
+coff_link_check_archive_element (abfd, info, pneeded)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean *pneeded;
+{
+ if (! _bfd_coff_get_external_symbols (abfd))
+ return false;
+
+ if (! coff_link_check_ar_symbols (abfd, info, pneeded))
+ return false;
+
+ if (*pneeded)
+ {
+ if (! coff_link_add_symbols (abfd, info))
+ return false;
+ }
+
+ if (! info->keep_memory || ! *pneeded)
+ {
+ if (! _bfd_coff_free_symbols (abfd))
+ return false;
+ }
+
+ return true;
+}
+
+/* Look through the symbols to see if this object file should be
+ included in the link. */
+
+static boolean
+coff_link_check_ar_symbols (abfd, info, pneeded)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean *pneeded;
+{
+ boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *));
+ bfd_size_type symesz;
+ bfd_byte *esym;
+ bfd_byte *esym_end;
+
+ *pneeded = false;
+
+ sym_is_global = coff_backend_info (abfd)->_bfd_coff_sym_is_global;
+
+ symesz = bfd_coff_symesz (abfd);
+ esym = (bfd_byte *) obj_coff_external_syms (abfd);
+ esym_end = esym + obj_raw_syment_count (abfd) * symesz;
+ while (esym < esym_end)
+ {
+ struct internal_syment sym;
+
+ bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+
+ if ((sym.n_sclass == C_EXT
+ || (sym_is_global && (*sym_is_global) (abfd, &sym)))
+ && (sym.n_scnum != 0 || sym.n_value != 0))
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ struct bfd_link_hash_entry *h;
+
+ /* This symbol is externally visible, and is defined by this
+ object file. */
+
+ name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
+ if (name == NULL)
+ return false;
+ h = bfd_link_hash_lookup (info->hash, name, false, false, true);
+
+ /* We are only interested in symbols that are currently
+ undefined. If a symbol is currently known to be common,
+ COFF linkers do not bring in an object file which defines
+ it. */
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && h->type == bfd_link_hash_undefined)
+ {
+ if (! (*info->callbacks->add_archive_element) (info, abfd, name))
+ return false;
+ *pneeded = true;
+ return true;
+ }
+ }
+
+ esym += (sym.n_numaux + 1) * symesz;
+ }
+
+ /* We do not need this object file. */
+ return true;
+}
+
+/* Add all the symbols from an object file to the hash table. */
+
+static boolean
+coff_link_add_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *));
+ boolean default_copy;
+ bfd_size_type symcount;
+ struct coff_link_hash_entry **sym_hash;
+ bfd_size_type symesz;
+ bfd_byte *esym;
+ bfd_byte *esym_end;
+
+ sym_is_global = coff_backend_info (abfd)->_bfd_coff_sym_is_global;
+
+ if (info->keep_memory)
+ default_copy = false;
+ else
+ default_copy = true;
+
+ symcount = obj_raw_syment_count (abfd);
+
+ /* We keep a list of the linker hash table entries that correspond
+ to particular symbols. */
+ sym_hash = ((struct coff_link_hash_entry **)
+ bfd_alloc (abfd,
+ ((size_t) symcount
+ * sizeof (struct coff_link_hash_entry *))));
+ if (sym_hash == NULL && symcount != 0)
+ return false;
+ obj_coff_sym_hashes (abfd) = sym_hash;
+ memset (sym_hash, 0,
+ (size_t) symcount * sizeof (struct coff_link_hash_entry *));
+
+ symesz = bfd_coff_symesz (abfd);
+ BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
+ esym = (bfd_byte *) obj_coff_external_syms (abfd);
+ esym_end = esym + symcount * symesz;
+ while (esym < esym_end)
+ {
+ struct internal_syment sym;
+ boolean copy;
+
+ bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+
+ if (sym.n_sclass == C_EXT
+ || (sym_is_global && (*sym_is_global) (abfd, &sym)))
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+
+ /* This symbol is externally visible. */
+
+ name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
+ if (name == NULL)
+ return false;
+
+ /* We must copy the name into memory if we got it from the
+ syment itself, rather than the string table. */
+ copy = default_copy;
+ if (sym._n._n_n._n_zeroes != 0
+ || sym._n._n_n._n_offset == 0)
+ copy = true;
+
+ value = sym.n_value;
+
+ if (sym.n_scnum == 0)
+ {
+ if (value == 0)
+ {
+ flags = 0;
+ section = bfd_und_section_ptr;
+ }
+ else
+ {
+ flags = BSF_GLOBAL;
+ section = bfd_com_section_ptr;
+ }
+ }
+ else
+ {
+ flags = BSF_EXPORT | BSF_GLOBAL;
+ section = coff_section_from_bfd_index (abfd, sym.n_scnum);
+ value -= section->vma;
+ }
+
+ if (! (bfd_coff_link_add_one_symbol
+ (info, abfd, name, flags, section, value,
+ (const char *) NULL, copy, false,
+ (struct bfd_link_hash_entry **) sym_hash)))
+ return false;
+
+ if (info->hash->creator->flavour == bfd_get_flavour (abfd))
+ {
+ if (((*sym_hash)->class == C_NULL
+ && (*sym_hash)->type == T_NULL)
+ || sym.n_scnum != 0
+ || (sym.n_value != 0
+ && (*sym_hash)->root.type != bfd_link_hash_defined))
+ {
+ (*sym_hash)->class = sym.n_sclass;
+ (*sym_hash)->type = sym.n_type;
+ (*sym_hash)->numaux = sym.n_numaux;
+ (*sym_hash)->auxbfd = abfd;
+ if (sym.n_numaux != 0)
+ {
+ union internal_auxent *alloc;
+ unsigned int i;
+ bfd_byte *eaux;
+ union internal_auxent *iaux;
+
+ alloc = ((union internal_auxent *)
+ bfd_hash_allocate (&info->hash->table,
+ (sym.n_numaux
+ * sizeof (*alloc))));
+ if (alloc == NULL)
+ return false;
+ for (i = 0, eaux = esym + symesz, iaux = alloc;
+ i < sym.n_numaux;
+ i++, eaux += symesz, iaux++)
+ bfd_coff_swap_aux_in (abfd, (PTR) eaux, sym.n_type,
+ sym.n_sclass, i, sym.n_numaux,
+ (PTR) iaux);
+ (*sym_hash)->aux = alloc;
+ }
+ }
+ }
+ }
+
+ esym += (sym.n_numaux + 1) * symesz;
+ sym_hash += sym.n_numaux + 1;
+ }
+
+ return true;
+}
+
+/* Do the final link step. */
+
+boolean
+_bfd_coff_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ bfd_size_type symesz;
+ struct coff_final_link_info finfo;
+ boolean debug_merge_allocated;
+ asection *o;
+ struct bfd_link_order *p;
+ size_t max_sym_count;
+ size_t max_lineno_count;
+ size_t max_reloc_count;
+ size_t max_output_reloc_count;
+ size_t max_contents_size;
+ file_ptr rel_filepos;
+ unsigned int relsz;
+ file_ptr line_filepos;
+ unsigned int linesz;
+ bfd *sub;
+ bfd_byte *external_relocs = NULL;
+ char strbuf[STRING_SIZE_SIZE];
+
+ symesz = bfd_coff_symesz (abfd);
+
+ finfo.info = info;
+ finfo.output_bfd = abfd;
+ finfo.strtab = NULL;
+ finfo.section_info = NULL;
+ finfo.last_file_index = -1;
+ finfo.internal_syms = NULL;
+ finfo.sec_ptrs = NULL;
+ finfo.sym_indices = NULL;
+ finfo.outsyms = NULL;
+ finfo.linenos = NULL;
+ finfo.contents = NULL;
+ finfo.external_relocs = NULL;
+ finfo.internal_relocs = NULL;
+ debug_merge_allocated = false;
+
+ coff_data (abfd)->link_info = info;
+
+ finfo.strtab = _bfd_stringtab_init ();
+ if (finfo.strtab == NULL)
+ goto error_return;
+
+ if (! coff_debug_merge_hash_table_init (&finfo.debug_merge))
+ goto error_return;
+ debug_merge_allocated = true;
+
+ /* Compute the file positions for all the sections. */
+ if (! abfd->output_has_begun)
+ bfd_coff_compute_section_file_positions (abfd);
+
+ /* Count the line numbers and relocation entries required for the
+ output file. Set the file positions for the relocs. */
+ rel_filepos = obj_relocbase (abfd);
+ relsz = bfd_coff_relsz (abfd);
+ max_contents_size = 0;
+ max_lineno_count = 0;
+ max_reloc_count = 0;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+
+ if (p->type == bfd_indirect_link_order)
+ {
+ asection *sec;
+
+ sec = p->u.indirect.section;
+
+ if (info->strip == strip_none
+ || info->strip == strip_some)
+ o->lineno_count += sec->lineno_count;
+
+ if (info->relocateable)
+ o->reloc_count += sec->reloc_count;
+
+ if (sec->_raw_size > max_contents_size)
+ max_contents_size = sec->_raw_size;
+ if (sec->lineno_count > max_lineno_count)
+ max_lineno_count = sec->lineno_count;
+ if (sec->reloc_count > max_reloc_count)
+ max_reloc_count = sec->reloc_count;
+ }
+ else if (info->relocateable
+ && (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order))
+ ++o->reloc_count;
+ }
+ if (o->reloc_count == 0)
+ o->rel_filepos = 0;
+ else
+ {
+ o->flags |= SEC_RELOC;
+ o->rel_filepos = rel_filepos;
+ rel_filepos += o->reloc_count * relsz;
+ }
+ }
+
+ /* If doing a relocateable link, allocate space for the pointers we
+ need to keep. */
+ if (info->relocateable)
+ {
+ unsigned int i;
+
+ /* We use section_count + 1, rather than section_count, because
+ the target_index fields are 1 based. */
+ finfo.section_info =
+ ((struct coff_link_section_info *)
+ bfd_malloc ((abfd->section_count + 1)
+ * sizeof (struct coff_link_section_info)));
+ if (finfo.section_info == NULL)
+ goto error_return;
+ for (i = 0; i <= abfd->section_count; i++)
+ {
+ finfo.section_info[i].relocs = NULL;
+ finfo.section_info[i].rel_hashes = NULL;
+ }
+ }
+
+ /* We now know the size of the relocs, so we can determine the file
+ positions of the line numbers. */
+ line_filepos = rel_filepos;
+ linesz = bfd_coff_linesz (abfd);
+ max_output_reloc_count = 0;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (o->lineno_count == 0)
+ o->line_filepos = 0;
+ else
+ {
+ o->line_filepos = line_filepos;
+ line_filepos += o->lineno_count * linesz;
+ }
+
+ if (o->reloc_count != 0)
+ {
+ /* We don't know the indices of global symbols until we have
+ written out all the local symbols. For each section in
+ the output file, we keep an array of pointers to hash
+ table entries. Each entry in the array corresponds to a
+ reloc. When we find a reloc against a global symbol, we
+ set the corresponding entry in this array so that we can
+ fix up the symbol index after we have written out all the
+ local symbols.
+
+ Because of this problem, we also keep the relocs in
+ memory until the end of the link. This wastes memory,
+ but only when doing a relocateable link, which is not the
+ common case. */
+ BFD_ASSERT (info->relocateable);
+ finfo.section_info[o->target_index].relocs =
+ ((struct internal_reloc *)
+ bfd_malloc (o->reloc_count * sizeof (struct internal_reloc)));
+ finfo.section_info[o->target_index].rel_hashes =
+ ((struct coff_link_hash_entry **)
+ bfd_malloc (o->reloc_count
+ * sizeof (struct coff_link_hash_entry *)));
+ if (finfo.section_info[o->target_index].relocs == NULL
+ || finfo.section_info[o->target_index].rel_hashes == NULL)
+ goto error_return;
+
+ if (o->reloc_count > max_output_reloc_count)
+ max_output_reloc_count = o->reloc_count;
+ }
+
+ /* Reset the reloc and lineno counts, so that we can use them to
+ count the number of entries we have output so far. */
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ }
+
+ obj_sym_filepos (abfd) = line_filepos;
+
+ /* Figure out the largest number of symbols in an input BFD. Take
+ the opportunity to clear the output_has_begun fields of all the
+ input BFD's. */
+ max_sym_count = 0;
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ size_t sz;
+
+ sub->output_has_begun = false;
+ sz = obj_raw_syment_count (sub);
+ if (sz > max_sym_count)
+ max_sym_count = sz;
+ }
+
+ /* Allocate some buffers used while linking. */
+ finfo.internal_syms = ((struct internal_syment *)
+ bfd_malloc (max_sym_count
+ * sizeof (struct internal_syment)));
+ finfo.sec_ptrs = (asection **) bfd_malloc (max_sym_count
+ * sizeof (asection *));
+ finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
+ finfo.outsyms = ((bfd_byte *)
+ bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
+ finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count
+ * bfd_coff_linesz (abfd));
+ finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+ finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
+ if (! info->relocateable)
+ finfo.internal_relocs = ((struct internal_reloc *)
+ bfd_malloc (max_reloc_count
+ * sizeof (struct internal_reloc)));
+ if ((finfo.internal_syms == NULL && max_sym_count > 0)
+ || (finfo.sec_ptrs == NULL && max_sym_count > 0)
+ || (finfo.sym_indices == NULL && max_sym_count > 0)
+ || finfo.outsyms == NULL
+ || (finfo.linenos == NULL && max_lineno_count > 0)
+ || (finfo.contents == NULL && max_contents_size > 0)
+ || (finfo.external_relocs == NULL && max_reloc_count > 0)
+ || (! info->relocateable
+ && finfo.internal_relocs == NULL
+ && max_reloc_count > 0))
+ goto error_return;
+
+ /* We now know the position of everything in the file, except that
+ we don't know the size of the symbol table and therefore we don't
+ know where the string table starts. We just build the string
+ table in memory as we go along. We process all the relocations
+ for a single input file at once. */
+ obj_raw_syment_count (abfd) = 0;
+
+ if (coff_backend_info (abfd)->_bfd_coff_start_final_link)
+ {
+ if (! bfd_coff_start_final_link (abfd, info))
+ goto error_return;
+ }
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour (p->u.indirect.section->owner)
+ == bfd_target_coff_flavour))
+ {
+ sub = p->u.indirect.section->owner;
+ if (! sub->output_has_begun)
+ {
+ if (! _bfd_coff_link_input_bfd (&finfo, sub))
+ goto error_return;
+ sub->output_has_begun = true;
+ }
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! _bfd_coff_reloc_link_order (abfd, &finfo, o, p))
+ goto error_return;
+ }
+ else
+ {
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ }
+ }
+
+ /* Free up the buffers used by _bfd_coff_link_input_bfd. */
+
+ coff_debug_merge_hash_table_free (&finfo.debug_merge);
+ debug_merge_allocated = false;
+
+ if (finfo.internal_syms != NULL)
+ {
+ free (finfo.internal_syms);
+ finfo.internal_syms = NULL;
+ }
+ if (finfo.sec_ptrs != NULL)
+ {
+ free (finfo.sec_ptrs);
+ finfo.sec_ptrs = NULL;
+ }
+ if (finfo.sym_indices != NULL)
+ {
+ free (finfo.sym_indices);
+ finfo.sym_indices = NULL;
+ }
+ if (finfo.linenos != NULL)
+ {
+ free (finfo.linenos);
+ finfo.linenos = NULL;
+ }
+ if (finfo.contents != NULL)
+ {
+ free (finfo.contents);
+ finfo.contents = NULL;
+ }
+ if (finfo.external_relocs != NULL)
+ {
+ free (finfo.external_relocs);
+ finfo.external_relocs = NULL;
+ }
+ if (finfo.internal_relocs != NULL)
+ {
+ free (finfo.internal_relocs);
+ finfo.internal_relocs = NULL;
+ }
+
+ /* The value of the last C_FILE symbol is supposed to be the symbol
+ index of the first external symbol. Write it out again if
+ necessary. */
+ if (finfo.last_file_index != -1
+ && (unsigned int) finfo.last_file.n_value != obj_raw_syment_count (abfd))
+ {
+ finfo.last_file.n_value = obj_raw_syment_count (abfd);
+ bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
+ (PTR) finfo.outsyms);
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + finfo.last_file_index * symesz),
+ SEEK_SET) != 0
+ || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
+ return false;
+ }
+
+ /* Write out the global symbols. */
+ finfo.failed = false;
+ coff_link_hash_traverse (coff_hash_table (info), _bfd_coff_write_global_sym,
+ (PTR) &finfo);
+ if (finfo.failed)
+ goto error_return;
+
+ /* The outsyms buffer is used by _bfd_coff_write_global_sym. */
+ if (finfo.outsyms != NULL)
+ {
+ free (finfo.outsyms);
+ finfo.outsyms = NULL;
+ }
+
+ if (info->relocateable)
+ {
+ /* Now that we have written out all the global symbols, we know
+ the symbol indices to use for relocs against them, and we can
+ finally write out the relocs. */
+ external_relocs = ((bfd_byte *)
+ bfd_malloc (max_output_reloc_count * relsz));
+ if (external_relocs == NULL)
+ goto error_return;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct internal_reloc *irel;
+ struct internal_reloc *irelend;
+ struct coff_link_hash_entry **rel_hash;
+ bfd_byte *erel;
+
+ if (o->reloc_count == 0)
+ continue;
+
+ irel = finfo.section_info[o->target_index].relocs;
+ irelend = irel + o->reloc_count;
+ rel_hash = finfo.section_info[o->target_index].rel_hashes;
+ erel = external_relocs;
+ for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+ {
+ if (*rel_hash != NULL)
+ {
+ BFD_ASSERT ((*rel_hash)->indx >= 0);
+ irel->r_symndx = (*rel_hash)->indx;
+ }
+ bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+ }
+
+ if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
+ || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
+ abfd) != relsz * o->reloc_count)
+ goto error_return;
+ }
+
+ free (external_relocs);
+ external_relocs = NULL;
+ }
+
+ /* Free up the section information. */
+ if (finfo.section_info != NULL)
+ {
+ unsigned int i;
+
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
+ }
+ free (finfo.section_info);
+ finfo.section_info = NULL;
+ }
+
+ /* Write out the string table. */
+ if (obj_raw_syment_count (abfd) != 0)
+ {
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + obj_raw_syment_count (abfd) * symesz),
+ SEEK_SET) != 0)
+ return false;
+
+#if STRING_SIZE_SIZE == 4
+ bfd_h_put_32 (abfd,
+ _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
+ (bfd_byte *) strbuf);
+#else
+ #error Change bfd_h_put_32
+#endif
+
+ if (bfd_write (strbuf, 1, STRING_SIZE_SIZE, abfd) != STRING_SIZE_SIZE)
+ return false;
+
+ if (! _bfd_stringtab_emit (abfd, finfo.strtab))
+ return false;
+ }
+
+ _bfd_stringtab_free (finfo.strtab);
+
+ /* Setting bfd_get_symcount to 0 will cause write_object_contents to
+ not try to write out the symbols. */
+ bfd_get_symcount (abfd) = 0;
+
+ return true;
+
+ error_return:
+ if (debug_merge_allocated)
+ coff_debug_merge_hash_table_free (&finfo.debug_merge);
+ if (finfo.strtab != NULL)
+ _bfd_stringtab_free (finfo.strtab);
+ if (finfo.section_info != NULL)
+ {
+ unsigned int i;
+
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
+ }
+ free (finfo.section_info);
+ }
+ if (finfo.internal_syms != NULL)
+ free (finfo.internal_syms);
+ if (finfo.sec_ptrs != NULL)
+ free (finfo.sec_ptrs);
+ if (finfo.sym_indices != NULL)
+ free (finfo.sym_indices);
+ if (finfo.outsyms != NULL)
+ free (finfo.outsyms);
+ if (finfo.linenos != NULL)
+ free (finfo.linenos);
+ if (finfo.contents != NULL)
+ free (finfo.contents);
+ if (finfo.external_relocs != NULL)
+ free (finfo.external_relocs);
+ if (finfo.internal_relocs != NULL)
+ free (finfo.internal_relocs);
+ if (external_relocs != NULL)
+ free (external_relocs);
+ return false;
+}
+
+/* parse out a -heap <reserved>,<commit> line */
+
+static char *
+dores_com (ptr, output_bfd, heap)
+ char *ptr;
+ bfd *output_bfd;
+ int heap;
+{
+ if (coff_data(output_bfd)->pe)
+ {
+ int val = strtoul (ptr, &ptr, 0);
+ if (heap)
+ pe_data(output_bfd)->pe_opthdr.SizeOfHeapReserve =val;
+ else
+ pe_data(output_bfd)->pe_opthdr.SizeOfStackReserve =val;
+
+ if (ptr[0] == ',')
+ {
+ int val = strtoul (ptr+1, &ptr, 0);
+ if (heap)
+ pe_data(output_bfd)->pe_opthdr.SizeOfHeapCommit =val;
+ else
+ pe_data(output_bfd)->pe_opthdr.SizeOfStackCommit =val;
+ }
+ }
+ return ptr;
+}
+
+static char *get_name(ptr, dst)
+char *ptr;
+char **dst;
+{
+ while (*ptr == ' ')
+ ptr++;
+ *dst = ptr;
+ while (*ptr && *ptr != ' ')
+ ptr++;
+ *ptr = 0;
+ return ptr+1;
+}
+
+/* Process any magic embedded commands in a section called .drectve */
+
+static int
+process_embedded_commands (output_bfd, info, abfd)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *abfd;
+{
+ asection *sec = bfd_get_section_by_name (abfd, ".drectve");
+ char *s;
+ char *e;
+ char *copy;
+ if (!sec)
+ return 1;
+
+ copy = bfd_malloc ((size_t) sec->_raw_size);
+ if (!copy)
+ return 0;
+ if (! bfd_get_section_contents(abfd, sec, copy, 0, sec->_raw_size))
+ {
+ free (copy);
+ return 0;
+ }
+ e = copy + sec->_raw_size;
+ for (s = copy; s < e ; )
+ {
+ if (s[0]!= '-') {
+ s++;
+ continue;
+ }
+ if (strncmp (s,"-attr", 5) == 0)
+ {
+ char *name;
+ char *attribs;
+ asection *asec;
+
+ int loop = 1;
+ int had_write = 0;
+ int had_read = 0;
+ int had_exec= 0;
+ int had_shared= 0;
+ s += 5;
+ s = get_name(s, &name);
+ s = get_name(s, &attribs);
+ while (loop) {
+ switch (*attribs++)
+ {
+ case 'W':
+ had_write = 1;
+ break;
+ case 'R':
+ had_read = 1;
+ break;
+ case 'S':
+ had_shared = 1;
+ break;
+ case 'X':
+ had_exec = 1;
+ break;
+ default:
+ loop = 0;
+ }
+ }
+ asec = bfd_get_section_by_name (abfd, name);
+ if (asec) {
+ if (had_exec)
+ asec->flags |= SEC_CODE;
+ if (!had_write)
+ asec->flags |= SEC_READONLY;
+ }
+ }
+ else if (strncmp (s,"-heap", 5) == 0)
+ {
+ s = dores_com (s+5, output_bfd, 1);
+ }
+ else if (strncmp (s,"-stack", 6) == 0)
+ {
+ s = dores_com (s+6, output_bfd, 0);
+ }
+ else
+ s++;
+ }
+ free (copy);
+ return 1;
+}
+
+/* Link an input file into the linker output file. This function
+ handles all the sections and relocations of the input file at once. */
+
+boolean
+_bfd_coff_link_input_bfd (finfo, input_bfd)
+ struct coff_final_link_info *finfo;
+ bfd *input_bfd;
+{
+ boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *));
+ boolean (*adjust_symndx) PARAMS ((bfd *, struct bfd_link_info *, bfd *,
+ asection *, struct internal_reloc *,
+ boolean *));
+ bfd *output_bfd;
+ const char *strings;
+ bfd_size_type syment_base;
+ unsigned int n_tmask;
+ unsigned int n_btshft;
+ boolean copy, hash;
+ bfd_size_type isymesz;
+ bfd_size_type osymesz;
+ bfd_size_type linesz;
+ bfd_byte *esym;
+ bfd_byte *esym_end;
+ struct internal_syment *isymp;
+ asection **secpp;
+ long *indexp;
+ unsigned long output_index;
+ bfd_byte *outsym;
+ struct coff_link_hash_entry **sym_hash;
+ asection *o;
+
+ /* Move all the symbols to the output file. */
+
+ output_bfd = finfo->output_bfd;
+ sym_is_global = coff_backend_info (input_bfd)->_bfd_coff_sym_is_global;
+ strings = NULL;
+ syment_base = obj_raw_syment_count (output_bfd);
+ isymesz = bfd_coff_symesz (input_bfd);
+ osymesz = bfd_coff_symesz (output_bfd);
+ linesz = bfd_coff_linesz (input_bfd);
+ BFD_ASSERT (linesz == bfd_coff_linesz (output_bfd));
+
+ n_tmask = coff_data (input_bfd)->local_n_tmask;
+ n_btshft = coff_data (input_bfd)->local_n_btshft;
+
+ /* Define macros so that ISFCN, et. al., macros work correctly. */
+#define N_TMASK n_tmask
+#define N_BTSHFT n_btshft
+
+ copy = false;
+ if (! finfo->info->keep_memory)
+ copy = true;
+ hash = true;
+ if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+
+ if (! _bfd_coff_get_external_symbols (input_bfd))
+ return false;
+
+ esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
+ esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
+ isymp = finfo->internal_syms;
+ secpp = finfo->sec_ptrs;
+ indexp = finfo->sym_indices;
+ output_index = syment_base;
+ outsym = finfo->outsyms;
+
+ if (coff_data(output_bfd)->pe)
+ {
+ if (!process_embedded_commands (output_bfd, finfo->info, input_bfd))
+ return false;
+ }
+
+ while (esym < esym_end)
+ {
+ struct internal_syment isym;
+ boolean skip;
+ boolean global;
+ int add;
+
+ bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
+
+ /* Make a copy of *isymp so that the relocate_section function
+ always sees the original values. This is more reliable than
+ always recomputing the symbol value even if we are stripping
+ the symbol. */
+ isym = *isymp;
+
+ if (isym.n_scnum != 0)
+ *secpp = coff_section_from_bfd_index (input_bfd, isym.n_scnum);
+ else
+ {
+ if (isym.n_value == 0)
+ *secpp = bfd_und_section_ptr;
+ else
+ *secpp = bfd_com_section_ptr;
+ }
+
+ *indexp = -1;
+
+ skip = false;
+ global = false;
+ add = 1 + isym.n_numaux;
+
+ /* If we are stripping all symbols, we want to skip this one. */
+ if (finfo->info->strip == strip_all)
+ skip = true;
+
+ if (! skip)
+ {
+ if (isym.n_sclass == C_EXT
+ || (sym_is_global && (*sym_is_global) (input_bfd, &isym)))
+ {
+ /* This is a global symbol. Global symbols come at the
+ end of the symbol table, so skip them for now.
+ Function symbols, however, are an exception, and are
+ not moved to the end. */
+ global = true;
+ if (! ISFCN (isym.n_type))
+ skip = true;
+ }
+ else
+ {
+ /* This is a local symbol. Skip it if we are discarding
+ local symbols. */
+ if (finfo->info->discard == discard_all)
+ skip = true;
+ }
+ }
+
+ /* If we stripping debugging symbols, and this is a debugging
+ symbol, then skip it. */
+ if (! skip
+ && finfo->info->strip == strip_debugger
+ && isym.n_scnum == N_DEBUG)
+ skip = true;
+
+ /* If some symbols are stripped based on the name, work out the
+ name and decide whether to skip this symbol. */
+ if (! skip
+ && (finfo->info->strip == strip_some
+ || finfo->info->discard == discard_l))
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+ if (name == NULL)
+ return false;
+
+ if ((finfo->info->strip == strip_some
+ && (bfd_hash_lookup (finfo->info->keep_hash, name, false,
+ false) == NULL))
+ || (! global
+ && finfo->info->discard == discard_l
+ && strncmp (name, finfo->info->lprefix,
+ finfo->info->lprefix_len) == 0))
+ skip = true;
+ }
+
+ /* If this is an enum, struct, or union tag, see if we have
+ already output an identical type. */
+ if (! skip
+ && (finfo->output_bfd->flags & BFD_TRADITIONAL_FORMAT) == 0
+ && (isym.n_sclass == C_ENTAG
+ || isym.n_sclass == C_STRTAG
+ || isym.n_sclass == C_UNTAG)
+ && isym.n_numaux == 1)
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ struct coff_debug_merge_hash_entry *mh;
+ struct coff_debug_merge_type *mt;
+ union internal_auxent aux;
+ struct coff_debug_merge_element **epp;
+ bfd_byte *esl, *eslend;
+ struct internal_syment *islp;
+
+ name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+ if (name == NULL)
+ return false;
+
+ /* Ignore fake names invented by compiler; treat them all as
+ the same name. */
+ if (*name == '~' || *name == '.' || *name == '$'
+ || (*name == bfd_get_symbol_leading_char (input_bfd)
+ && (name[1] == '~' || name[1] == '.' || name[1] == '$')))
+ name = "";
+
+ mh = coff_debug_merge_hash_lookup (&finfo->debug_merge, name,
+ true, true);
+ if (mh == NULL)
+ return false;
+
+ /* Allocate memory to hold type information. If this turns
+ out to be a duplicate, we pass this address to
+ bfd_release. */
+ mt = ((struct coff_debug_merge_type *)
+ bfd_alloc (input_bfd,
+ sizeof (struct coff_debug_merge_type)));
+ if (mt == NULL)
+ return false;
+ mt->class = isym.n_sclass;
+
+ /* Pick up the aux entry, which points to the end of the tag
+ entries. */
+ bfd_coff_swap_aux_in (input_bfd, (PTR) (esym + isymesz),
+ isym.n_type, isym.n_sclass, 0, isym.n_numaux,
+ (PTR) &aux);
+
+ /* Gather the elements. */
+ epp = &mt->elements;
+ mt->elements = NULL;
+ islp = isymp + 2;
+ esl = esym + 2 * isymesz;
+ eslend = ((bfd_byte *) obj_coff_external_syms (input_bfd)
+ + aux.x_sym.x_fcnary.x_fcn.x_endndx.l * isymesz);
+ while (esl < eslend)
+ {
+ const char *elename;
+ char elebuf[SYMNMLEN + 1];
+ char *copy;
+
+ bfd_coff_swap_sym_in (input_bfd, (PTR) esl, (PTR) islp);
+
+ *epp = ((struct coff_debug_merge_element *)
+ bfd_alloc (input_bfd,
+ sizeof (struct coff_debug_merge_element)));
+ if (*epp == NULL)
+ return false;
+
+ elename = _bfd_coff_internal_syment_name (input_bfd, islp,
+ elebuf);
+ if (elename == NULL)
+ return false;
+
+ copy = (char *) bfd_alloc (input_bfd, strlen (elename) + 1);
+ if (copy == NULL)
+ return false;
+ strcpy (copy, elename);
+
+ (*epp)->name = copy;
+ (*epp)->type = islp->n_type;
+ (*epp)->tagndx = 0;
+ if (islp->n_numaux >= 1
+ && islp->n_type != T_NULL
+ && islp->n_sclass != C_EOS)
+ {
+ union internal_auxent eleaux;
+ long indx;
+
+ bfd_coff_swap_aux_in (input_bfd, (PTR) (esl + isymesz),
+ islp->n_type, islp->n_sclass, 0,
+ islp->n_numaux, (PTR) &eleaux);
+ indx = eleaux.x_sym.x_tagndx.l;
+
+ /* FIXME: If this tagndx entry refers to a symbol
+ defined later in this file, we just ignore it.
+ Handling this correctly would be tedious, and may
+ not be required. */
+
+ if (indx > 0
+ && (indx
+ < ((esym -
+ (bfd_byte *) obj_coff_external_syms (input_bfd))
+ / (long) isymesz)))
+ {
+ (*epp)->tagndx = finfo->sym_indices[indx];
+ if ((*epp)->tagndx < 0)
+ (*epp)->tagndx = 0;
+ }
+ }
+ epp = &(*epp)->next;
+ *epp = NULL;
+
+ esl += (islp->n_numaux + 1) * isymesz;
+ islp += islp->n_numaux + 1;
+ }
+
+ /* See if we already have a definition which matches this
+ type. We always output the type if it has no elements,
+ for simplicity. */
+ if (mt->elements == NULL)
+ bfd_release (input_bfd, (PTR) mt);
+ else
+ {
+ struct coff_debug_merge_type *mtl;
+
+ for (mtl = mh->types; mtl != NULL; mtl = mtl->next)
+ {
+ struct coff_debug_merge_element *me, *mel;
+
+ if (mtl->class != mt->class)
+ continue;
+
+ for (me = mt->elements, mel = mtl->elements;
+ me != NULL && mel != NULL;
+ me = me->next, mel = mel->next)
+ {
+ if (strcmp (me->name, mel->name) != 0
+ || me->type != mel->type
+ || me->tagndx != mel->tagndx)
+ break;
+ }
+
+ if (me == NULL && mel == NULL)
+ break;
+ }
+
+ if (mtl == NULL || (bfd_size_type) mtl->indx >= syment_base)
+ {
+ /* This is the first definition of this type. */
+ mt->indx = output_index;
+ mt->next = mh->types;
+ mh->types = mt;
+ }
+ else
+ {
+ /* This is a redefinition which can be merged. */
+ bfd_release (input_bfd, (PTR) mt);
+ *indexp = mtl->indx;
+ add = (eslend - esym) / isymesz;
+ skip = true;
+ }
+ }
+ }
+
+ /* We now know whether we are to skip this symbol or not. */
+ if (! skip)
+ {
+ /* Adjust the symbol in order to output it. */
+
+ if (isym._n._n_n._n_zeroes == 0
+ && isym._n._n_n._n_offset != 0)
+ {
+ const char *name;
+ bfd_size_type indx;
+
+ /* This symbol has a long name. Enter it in the string
+ table we are building. Note that we do not check
+ bfd_coff_symname_in_debug. That is only true for
+ XCOFF, and XCOFF requires different linking code
+ anyhow. */
+ name = _bfd_coff_internal_syment_name (input_bfd, &isym,
+ (char *) NULL);
+ if (name == NULL)
+ return false;
+ indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ }
+
+ if (isym.n_scnum > 0)
+ {
+ isym.n_scnum = (*secpp)->output_section->target_index;
+ isym.n_value += ((*secpp)->output_section->vma
+ + (*secpp)->output_offset
+ - (*secpp)->vma);
+ }
+
+ /* The value of a C_FILE symbol is the symbol index of the
+ next C_FILE symbol. The value of the last C_FILE symbol
+ is the symbol index to the first external symbol
+ (actually, coff_renumber_symbols does not get this
+ right--it just sets the value of the last C_FILE symbol
+ to zero--and nobody has ever complained about it). We
+ try to get this right, below, just before we write the
+ symbols out, but in the general case we may have to write
+ the symbol out twice. */
+ if (isym.n_sclass == C_FILE)
+ {
+ if (finfo->last_file_index != -1
+ && finfo->last_file.n_value != (long) output_index)
+ {
+ /* We must correct the value of the last C_FILE entry. */
+ finfo->last_file.n_value = output_index;
+ if ((bfd_size_type) finfo->last_file_index >= syment_base)
+ {
+ /* The last C_FILE symbol is in this input file. */
+ bfd_coff_swap_sym_out (output_bfd,
+ (PTR) &finfo->last_file,
+ (PTR) (finfo->outsyms
+ + ((finfo->last_file_index
+ - syment_base)
+ * osymesz)));
+ }
+ else
+ {
+ /* We have already written out the last C_FILE
+ symbol. We need to write it out again. We
+ borrow *outsym temporarily. */
+ bfd_coff_swap_sym_out (output_bfd,
+ (PTR) &finfo->last_file,
+ (PTR) outsym);
+ if (bfd_seek (output_bfd,
+ (obj_sym_filepos (output_bfd)
+ + finfo->last_file_index * osymesz),
+ SEEK_SET) != 0
+ || (bfd_write (outsym, osymesz, 1, output_bfd)
+ != osymesz))
+ return false;
+ }
+ }
+
+ finfo->last_file_index = output_index;
+ finfo->last_file = isym;
+ }
+
+ /* Output the symbol. */
+
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) outsym);
+
+ *indexp = output_index;
+
+ if (global)
+ {
+ long indx;
+ struct coff_link_hash_entry *h;
+
+ indx = ((esym - (bfd_byte *) obj_coff_external_syms (input_bfd))
+ / isymesz);
+ h = obj_coff_sym_hashes (input_bfd)[indx];
+ BFD_ASSERT (h != NULL);
+ h->indx = output_index;
+ }
+
+ output_index += add;
+ outsym += add * osymesz;
+ }
+
+ esym += add * isymesz;
+ isymp += add;
+ ++secpp;
+ ++indexp;
+ for (--add; add > 0; --add)
+ {
+ *secpp++ = NULL;
+ *indexp++ = -1;
+ }
+ }
+
+ /* Fix up the aux entries. This must be done in a separate pass,
+ because we don't know the correct symbol indices until we have
+ already decided which symbols we are going to keep. */
+
+ esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
+ esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
+ isymp = finfo->internal_syms;
+ indexp = finfo->sym_indices;
+ sym_hash = obj_coff_sym_hashes (input_bfd);
+ outsym = finfo->outsyms;
+ while (esym < esym_end)
+ {
+ int add;
+
+ add = 1 + isymp->n_numaux;
+
+ if ((*indexp < 0
+ || (bfd_size_type) *indexp < syment_base)
+ && (*sym_hash == NULL
+ || (*sym_hash)->auxbfd != input_bfd))
+ esym += add * isymesz;
+ else
+ {
+ struct coff_link_hash_entry *h;
+ int i;
+
+ h = NULL;
+ if (*indexp < 0)
+ {
+ h = *sym_hash;
+ BFD_ASSERT (h->numaux == isymp->n_numaux);
+ }
+
+ esym += isymesz;
+
+ if (h == NULL)
+ outsym += osymesz;
+
+ /* Handle the aux entries. This handling is based on
+ coff_pointerize_aux. I don't know if it always correct. */
+ for (i = 0; i < isymp->n_numaux && esym < esym_end; i++)
+ {
+ union internal_auxent aux;
+ union internal_auxent *auxp;
+
+ if (h != NULL)
+ auxp = h->aux + i;
+ else
+ {
+ bfd_coff_swap_aux_in (input_bfd, (PTR) esym, isymp->n_type,
+ isymp->n_sclass, i, isymp->n_numaux,
+ (PTR) &aux);
+ auxp = &aux;
+ }
+
+ if (isymp->n_sclass == C_FILE)
+ {
+ /* If this is a long filename, we must put it in the
+ string table. */
+ if (auxp->x_file.x_n.x_zeroes == 0
+ && auxp->x_file.x_n.x_offset != 0)
+ {
+ const char *filename;
+ bfd_size_type indx;
+
+ BFD_ASSERT (auxp->x_file.x_n.x_offset
+ >= STRING_SIZE_SIZE);
+ if (strings == NULL)
+ {
+ strings = _bfd_coff_read_string_table (input_bfd);
+ if (strings == NULL)
+ return false;
+ }
+ filename = strings + auxp->x_file.x_n.x_offset;
+ indx = _bfd_stringtab_add (finfo->strtab, filename,
+ hash, copy);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ auxp->x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+ }
+ }
+ else if (isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
+ {
+ unsigned long indx;
+
+ if (ISFCN (isymp->n_type)
+ || ISTAG (isymp->n_sclass)
+ || isymp->n_sclass == C_BLOCK)
+ {
+ indx = auxp->x_sym.x_fcnary.x_fcn.x_endndx.l;
+ if (indx > 0
+ && indx < obj_raw_syment_count (input_bfd))
+ {
+ /* We look forward through the symbol for
+ the index of the next symbol we are going
+ to include. I don't know if this is
+ entirely right. */
+ while ((finfo->sym_indices[indx] < 0
+ || ((bfd_size_type) finfo->sym_indices[indx]
+ < syment_base))
+ && indx < obj_raw_syment_count (input_bfd))
+ ++indx;
+ if (indx >= obj_raw_syment_count (input_bfd))
+ indx = output_index;
+ else
+ indx = finfo->sym_indices[indx];
+ auxp->x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
+ }
+ }
+
+ indx = auxp->x_sym.x_tagndx.l;
+ if (indx > 0 && indx < obj_raw_syment_count (input_bfd))
+ {
+ long symindx;
+
+ symindx = finfo->sym_indices[indx];
+ if (symindx < 0)
+ auxp->x_sym.x_tagndx.l = 0;
+ else
+ auxp->x_sym.x_tagndx.l = symindx;
+ }
+ }
+
+ if (h == NULL)
+ {
+ bfd_coff_swap_aux_out (output_bfd, (PTR) auxp, isymp->n_type,
+ isymp->n_sclass, i, isymp->n_numaux,
+ (PTR) outsym);
+ outsym += osymesz;
+ }
+
+ esym += isymesz;
+ }
+ }
+
+ indexp += add;
+ isymp += add;
+ sym_hash += add;
+ }
+
+ /* Relocate the line numbers, unless we are stripping them. */
+ if (finfo->info->strip == strip_none
+ || finfo->info->strip == strip_some)
+ {
+ for (o = input_bfd->sections; o != NULL; o = o->next)
+ {
+ bfd_vma offset;
+ bfd_byte *eline;
+ bfd_byte *elineend;
+
+ /* FIXME: If SEC_HAS_CONTENTS is not for the section, then
+ build_link_order in ldwrite.c will not have created a
+ link order, which means that we will not have seen this
+ input section in _bfd_coff_final_link, which means that
+ we will not have allocated space for the line numbers of
+ this section. I don't think line numbers can be
+ meaningful for a section which does not have
+ SEC_HAS_CONTENTS set, but, if they do, this must be
+ changed. */
+ if (o->lineno_count == 0
+ || (o->output_section->flags & SEC_HAS_CONTENTS) == 0)
+ continue;
+
+ if (bfd_seek (input_bfd, o->line_filepos, SEEK_SET) != 0
+ || bfd_read (finfo->linenos, linesz, o->lineno_count,
+ input_bfd) != linesz * o->lineno_count)
+ return false;
+
+ offset = o->output_section->vma + o->output_offset - o->vma;
+ eline = finfo->linenos;
+ elineend = eline + linesz * o->lineno_count;
+ for (; eline < elineend; eline += linesz)
+ {
+ struct internal_lineno iline;
+
+ bfd_coff_swap_lineno_in (input_bfd, (PTR) eline, (PTR) &iline);
+
+ if (iline.l_lnno != 0)
+ iline.l_addr.l_paddr += offset;
+ else if (iline.l_addr.l_symndx >= 0
+ && ((unsigned long) iline.l_addr.l_symndx
+ < obj_raw_syment_count (input_bfd)))
+ {
+ long indx;
+
+ indx = finfo->sym_indices[iline.l_addr.l_symndx];
+
+ if (indx < 0)
+ {
+ /* These line numbers are attached to a symbol
+ which we are stripping. We should really
+ just discard the line numbers, but that would
+ be a pain because we have already counted
+ them. */
+ indx = 0;
+ }
+ else
+ {
+ struct internal_syment is;
+ union internal_auxent ia;
+
+ /* Fix up the lnnoptr field in the aux entry of
+ the symbol. It turns out that we can't do
+ this when we modify the symbol aux entries,
+ because gas sometimes screws up the lnnoptr
+ field and makes it an offset from the start
+ of the line numbers rather than an absolute
+ file index. */
+ bfd_coff_swap_sym_in (output_bfd,
+ (PTR) (finfo->outsyms
+ + ((indx - syment_base)
+ * osymesz)),
+ (PTR) &is);
+ if ((ISFCN (is.n_type)
+ || is.n_sclass == C_BLOCK)
+ && is.n_numaux >= 1)
+ {
+ PTR auxptr;
+
+ auxptr = (PTR) (finfo->outsyms
+ + ((indx - syment_base + 1)
+ * osymesz));
+ bfd_coff_swap_aux_in (output_bfd, auxptr,
+ is.n_type, is.n_sclass,
+ 0, is.n_numaux, (PTR) &ia);
+ ia.x_sym.x_fcnary.x_fcn.x_lnnoptr =
+ (o->output_section->line_filepos
+ + o->output_section->lineno_count * linesz
+ + eline - finfo->linenos);
+ bfd_coff_swap_aux_out (output_bfd, (PTR) &ia,
+ is.n_type, is.n_sclass, 0,
+ is.n_numaux, auxptr);
+ }
+ }
+
+ iline.l_addr.l_symndx = indx;
+ }
+
+ bfd_coff_swap_lineno_out (output_bfd, (PTR) &iline, (PTR) eline);
+ }
+
+ if (bfd_seek (output_bfd,
+ (o->output_section->line_filepos
+ + o->output_section->lineno_count * linesz),
+ SEEK_SET) != 0
+ || bfd_write (finfo->linenos, linesz, o->lineno_count,
+ output_bfd) != linesz * o->lineno_count)
+ return false;
+
+ o->output_section->lineno_count += o->lineno_count;
+ }
+ }
+
+ /* If we swapped out a C_FILE symbol, guess that the next C_FILE
+ symbol will be the first symbol in the next input file. In the
+ normal case, this will save us from writing out the C_FILE symbol
+ again. */
+ if (finfo->last_file_index != -1
+ && (bfd_size_type) finfo->last_file_index >= syment_base)
+ {
+ finfo->last_file.n_value = output_index;
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &finfo->last_file,
+ (PTR) (finfo->outsyms
+ + ((finfo->last_file_index - syment_base)
+ * osymesz)));
+ }
+
+ /* Write the modified symbols to the output file. */
+ if (outsym > finfo->outsyms)
+ {
+ if (bfd_seek (output_bfd,
+ obj_sym_filepos (output_bfd) + syment_base * osymesz,
+ SEEK_SET) != 0
+ || (bfd_write (finfo->outsyms, outsym - finfo->outsyms, 1,
+ output_bfd)
+ != (bfd_size_type) (outsym - finfo->outsyms)))
+ return false;
+
+ BFD_ASSERT ((obj_raw_syment_count (output_bfd)
+ + (outsym - finfo->outsyms) / osymesz)
+ == output_index);
+
+ obj_raw_syment_count (output_bfd) = output_index;
+ }
+
+ /* Relocate the contents of each section. */
+ adjust_symndx = coff_backend_info (input_bfd)->_bfd_coff_adjust_symndx;
+ for (o = input_bfd->sections; o != NULL; o = o->next)
+ {
+ bfd_byte *contents;
+
+ if ((o->flags & SEC_HAS_CONTENTS) == 0)
+ {
+ if ((o->flags & SEC_RELOC) != 0
+ && o->reloc_count != 0)
+ {
+ ((*_bfd_error_handler)
+ ("%s: relocs in section `%s', but it has no contents",
+ bfd_get_filename (input_bfd),
+ bfd_get_section_name (input_bfd, o)));
+ bfd_set_error (bfd_error_no_contents);
+ return false;
+ }
+
+ continue;
+ }
+
+ if (coff_section_data (input_bfd, o) != NULL
+ && coff_section_data (input_bfd, o)->contents != NULL)
+ contents = coff_section_data (input_bfd, o)->contents;
+ else
+ {
+ if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
+ (file_ptr) 0, o->_raw_size))
+ return false;
+ contents = finfo->contents;
+ }
+
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ int target_index;
+ struct internal_reloc *internal_relocs;
+ struct internal_reloc *irel;
+
+ /* Read in the relocs. */
+ target_index = o->output_section->target_index;
+ internal_relocs = (_bfd_coff_read_internal_relocs
+ (input_bfd, o, false, finfo->external_relocs,
+ finfo->info->relocateable,
+ (finfo->info->relocateable
+ ? (finfo->section_info[target_index].relocs
+ + o->output_section->reloc_count)
+ : finfo->internal_relocs)));
+ if (internal_relocs == NULL)
+ return false;
+
+ /* Call processor specific code to relocate the section
+ contents. */
+ if (! bfd_coff_relocate_section (output_bfd, finfo->info,
+ input_bfd, o,
+ contents,
+ internal_relocs,
+ finfo->internal_syms,
+ finfo->sec_ptrs))
+ return false;
+
+ if (finfo->info->relocateable)
+ {
+ bfd_vma offset;
+ struct internal_reloc *irelend;
+ struct coff_link_hash_entry **rel_hash;
+
+ offset = o->output_section->vma + o->output_offset - o->vma;
+ irel = internal_relocs;
+ irelend = irel + o->reloc_count;
+ rel_hash = (finfo->section_info[target_index].rel_hashes
+ + o->output_section->reloc_count);
+ for (; irel < irelend; irel++, rel_hash++)
+ {
+ struct coff_link_hash_entry *h;
+ boolean adjusted;
+
+ *rel_hash = NULL;
+
+ /* Adjust the reloc address and symbol index. */
+
+ irel->r_vaddr += offset;
+
+ if (irel->r_symndx == -1)
+ continue;
+
+ if (adjust_symndx)
+ {
+ if (! (*adjust_symndx) (output_bfd, finfo->info,
+ input_bfd, o, irel,
+ &adjusted))
+ return false;
+ if (adjusted)
+ continue;
+ }
+
+ h = obj_coff_sym_hashes (input_bfd)[irel->r_symndx];
+ if (h != NULL)
+ {
+ /* This is a global symbol. */
+ if (h->indx >= 0)
+ irel->r_symndx = h->indx;
+ else
+ {
+ /* This symbol is being written at the end
+ of the file, and we do not yet know the
+ symbol index. We save the pointer to the
+ hash table entry in the rel_hash list.
+ We set the indx field to -2 to indicate
+ that this symbol must not be stripped. */
+ *rel_hash = h;
+ h->indx = -2;
+ }
+ }
+ else
+ {
+ long indx;
+
+ indx = finfo->sym_indices[irel->r_symndx];
+ if (indx != -1)
+ irel->r_symndx = indx;
+ else
+ {
+ struct internal_syment *is;
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ /* This reloc is against a symbol we are
+ stripping. It would be possible to
+ handle this case, but I don't think it's
+ worth it. */
+ is = finfo->internal_syms + irel->r_symndx;
+
+ name = (_bfd_coff_internal_syment_name
+ (input_bfd, is, buf));
+ if (name == NULL)
+ return false;
+
+ if (! ((*finfo->info->callbacks->unattached_reloc)
+ (finfo->info, name, input_bfd, o,
+ irel->r_vaddr)))
+ return false;
+ }
+ }
+ }
+
+ o->output_section->reloc_count += o->reloc_count;
+ }
+ }
+
+ /* Write out the modified section contents. */
+ if (! bfd_set_section_contents (output_bfd, o->output_section,
+ contents, o->output_offset,
+ (o->_cooked_size != 0
+ ? o->_cooked_size
+ : o->_raw_size)))
+ return false;
+ }
+
+ if (! finfo->info->keep_memory)
+ {
+ if (! _bfd_coff_free_symbols (input_bfd))
+ return false;
+ }
+
+ return true;
+}
+
+/* Write out a global symbol. Called via coff_link_hash_traverse. */
+
+boolean
+_bfd_coff_write_global_sym (h, data)
+ struct coff_link_hash_entry *h;
+ PTR data;
+{
+ struct coff_final_link_info *finfo = (struct coff_final_link_info *) data;
+ bfd *output_bfd;
+ struct internal_syment isym;
+ bfd_size_type symesz;
+ unsigned int i;
+
+ output_bfd = finfo->output_bfd;
+
+ if (h->indx >= 0)
+ return true;
+
+ if (h->indx != -2
+ && (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 ();
+ return false;
+
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ isym.n_scnum = N_UNDEF;
+ isym.n_value = 0;
+ break;
+
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ {
+ asection *sec;
+
+ sec = h->root.u.def.section->output_section;
+ if (bfd_is_abs_section (sec))
+ isym.n_scnum = N_ABS;
+ else
+ isym.n_scnum = sec->target_index;
+ isym.n_value = (h->root.u.def.value
+ + sec->vma
+ + h->root.u.def.section->output_offset);
+ }
+ break;
+
+ case bfd_link_hash_common:
+ isym.n_scnum = N_UNDEF;
+ isym.n_value = h->root.u.c.size;
+ break;
+
+ case bfd_link_hash_indirect:
+ case bfd_link_hash_warning:
+ /* Just ignore these. They can't be handled anyhow. */
+ return true;
+ }
+
+ if (strlen (h->root.root.string) <= SYMNMLEN)
+ strncpy (isym._n._n_name, h->root.root.string, SYMNMLEN);
+ else
+ {
+ boolean hash;
+ bfd_size_type indx;
+
+ hash = true;
+ if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+ indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
+ false);
+ if (indx == (bfd_size_type) -1)
+ {
+ finfo->failed = true;
+ return false;
+ }
+ isym._n._n_n._n_zeroes = 0;
+ isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ }
+
+ isym.n_sclass = h->class;
+ isym.n_type = h->type;
+
+ if (isym.n_sclass == C_NULL)
+ isym.n_sclass = C_EXT;
+
+ isym.n_numaux = h->numaux;
+
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) finfo->outsyms);
+
+ symesz = bfd_coff_symesz (output_bfd);
+
+ if (bfd_seek (output_bfd,
+ (obj_sym_filepos (output_bfd)
+ + obj_raw_syment_count (output_bfd) * symesz),
+ SEEK_SET) != 0
+ || bfd_write (finfo->outsyms, symesz, 1, output_bfd) != symesz)
+ {
+ finfo->failed = true;
+ return false;
+ }
+
+ h->indx = obj_raw_syment_count (output_bfd);
+
+ ++obj_raw_syment_count (output_bfd);
+
+ /* Write out any associated aux entries. There normally will be
+ none. If there are any, I have no idea how to modify them. */
+ for (i = 0; i < isym.n_numaux; i++)
+ {
+ bfd_coff_swap_aux_out (output_bfd, (PTR) (h->aux + i), isym.n_type,
+ isym.n_sclass, i, isym.n_numaux,
+ (PTR) finfo->outsyms);
+ if (bfd_write (finfo->outsyms, symesz, 1, output_bfd) != symesz)
+ {
+ finfo->failed = true;
+ return false;
+ }
+ ++obj_raw_syment_count (output_bfd);
+ }
+
+ return true;
+}
+
+/* Handle a link order which is supposed to generate a reloc. */
+
+boolean
+_bfd_coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
+ bfd *output_bfd;
+ struct coff_final_link_info *finfo;
+ asection *output_section;
+ struct bfd_link_order *link_order;
+{
+ reloc_howto_type *howto;
+ struct internal_reloc *irel;
+ struct coff_link_hash_entry **rel_hash_ptr;
+
+ howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
+ if (howto == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (link_order->u.reloc.p->addend != 0)
+ {
+ bfd_size_type size;
+ bfd_byte *buf;
+ bfd_reloc_status_type rstat;
+ boolean ok;
+
+ size = bfd_get_reloc_size (howto);
+ buf = (bfd_byte *) bfd_zmalloc (size);
+ if (buf == NULL)
+ return false;
+
+ rstat = _bfd_relocate_contents (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 (! ((*finfo->info->callbacks->reloc_overflow)
+ (finfo->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),
+ 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;
+ }
+
+ /* Store the reloc information in the right place. It will get
+ swapped and written out at the end of the final_link routine. */
+
+ irel = (finfo->section_info[output_section->target_index].relocs
+ + output_section->reloc_count);
+ rel_hash_ptr = (finfo->section_info[output_section->target_index].rel_hashes
+ + output_section->reloc_count);
+
+ memset (irel, 0, sizeof (struct internal_reloc));
+ *rel_hash_ptr = NULL;
+
+ irel->r_vaddr = output_section->vma + link_order->offset;
+
+ if (link_order->type == bfd_section_reloc_link_order)
+ {
+ /* We need to somehow locate a symbol in the right section. The
+ symbol must either have a value of zero, or we must adjust
+ the addend by the value of the symbol. FIXME: Write this
+ when we need it. The old linker couldn't handle this anyhow. */
+ abort ();
+ *rel_hash_ptr = NULL;
+ irel->r_symndx = 0;
+ }
+ else
+ {
+ struct coff_link_hash_entry *h;
+
+ h = ((struct coff_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, finfo->info,
+ link_order->u.reloc.p->u.name,
+ false, false, true));
+ if (h != NULL)
+ {
+ if (h->indx >= 0)
+ irel->r_symndx = h->indx;
+ else
+ {
+ /* Set the index to -2 to force this symbol to get
+ written out. */
+ h->indx = -2;
+ *rel_hash_ptr = h;
+ irel->r_symndx = 0;
+ }
+ }
+ else
+ {
+ if (! ((*finfo->info->callbacks->unattached_reloc)
+ (finfo->info, link_order->u.reloc.p->u.name, (bfd *) NULL,
+ (asection *) NULL, (bfd_vma) 0)))
+ return false;
+ irel->r_symndx = 0;
+ }
+ }
+
+ /* FIXME: Is this always right? */
+ irel->r_type = howto->type;
+
+ /* r_size is only used on the RS/6000, which needs its own linker
+ routines anyhow. r_extern is only used for ECOFF. */
+
+ /* FIXME: What is the right value for r_offset? Is zero OK? */
+
+ ++output_section->reloc_count;
+
+ return true;
+}
+
+/* A basic reloc handling routine which may be used by processors with
+ simple relocs. */
+
+boolean
+_bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
+ input_section, contents, relocs, syms,
+ sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct coff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma addend;
+ bfd_vma val;
+ reloc_howto_type *howto;
+ bfd_reloc_status_type rstat;
+
+ symndx = rel->r_symndx;
+
+ if (symndx == -1)
+ {
+ h = NULL;
+ sym = NULL;
+ }
+ else
+ {
+ h = obj_coff_sym_hashes (input_bfd)[symndx];
+ sym = syms + symndx;
+ }
+
+ /* COFF treats common symbols in one of two ways. Either the
+ size of the symbol is included in the section contents, or it
+ is not. We assume that the size is not included, and force
+ the rtype_to_howto function to adjust the addend as needed. */
+
+ if (sym != NULL && sym->n_scnum != 0)
+ addend = - sym->n_value;
+ else
+ addend = 0;
+
+
+ howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
+ sym, &addend);
+ if (howto == NULL)
+ return false;
+
+ val = 0;
+
+ if (h == NULL)
+ {
+ asection *sec;
+
+ if (symndx == -1)
+ {
+ sec = bfd_abs_section_ptr;
+ val = 0;
+ }
+ else
+ {
+ sec = sections[symndx];
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+ }
+ else
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ val = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+
+ else if (! info->relocateable)
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ if (info->base_file)
+ {
+ /* Emit a reloc if the backend thinks it needs it. */
+ if (sym && pe_data(output_bfd)->in_reloc_p(output_bfd, howto))
+ {
+ /* relocation to a symbol in a section which
+ isn't absolute - we output the address here
+ to a file */
+ bfd_vma addr = rel->r_vaddr
+ - input_section->vma
+ + input_section->output_offset
+ + input_section->output_section->vma;
+ if (coff_data(output_bfd)->pe)
+ addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
+ fwrite (&addr, 1,4, (FILE *) info->base_file);
+ }
+ }
+
+ rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents,
+ rel->r_vaddr - input_section->vma,
+ val, addend);
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+ if (name == NULL)
+ return false;
+ }
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
diff --git a/contrib/gdb/bfd/coffswap.h b/contrib/gdb/bfd/coffswap.h
new file mode 100644
index 0000000..ef1b6b3
--- /dev/null
+++ b/contrib/gdb/bfd/coffswap.h
@@ -0,0 +1,807 @@
+/* Generic COFF swapping routines, for BFD.
+ Copyright 1990, 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file contains routines used to swap COFF data. It is a header
+ file because the details of swapping depend on the details of the
+ structures used by each COFF implementation. This is included by
+ coffcode.h, as well as by the ECOFF backend.
+
+ Any file which uses this must first include "coff/internal.h" and
+ "coff/CPU.h". The functions will then be correct for that CPU. */
+
+#ifndef IMAGE_BASE
+#define IMAGE_BASE 0
+#endif
+
+#define PUTWORD bfd_h_put_32
+#define PUTHALF bfd_h_put_16
+#define PUTBYTE bfd_h_put_8
+
+#ifndef GET_FCN_LNNOPTR
+#define GET_FCN_LNNOPTR(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#endif
+
+#ifndef GET_FCN_ENDNDX
+#define GET_FCN_ENDNDX(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
+#endif
+
+#ifndef PUT_FCN_LNNOPTR
+#define PUT_FCN_LNNOPTR(abfd, in, ext) PUTWORD(abfd, in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#endif
+#ifndef PUT_FCN_ENDNDX
+#define PUT_FCN_ENDNDX(abfd, in, ext) PUTWORD(abfd, in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
+#endif
+#ifndef GET_LNSZ_LNNO
+#define GET_LNSZ_LNNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_lnno)
+#endif
+#ifndef GET_LNSZ_SIZE
+#define GET_LNSZ_SIZE(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_size)
+#endif
+#ifndef PUT_LNSZ_LNNO
+#define PUT_LNSZ_LNNO(abfd, in, ext) bfd_h_put_16(abfd, in, (bfd_byte *)ext->x_sym.x_misc.x_lnsz.x_lnno)
+#endif
+#ifndef PUT_LNSZ_SIZE
+#define PUT_LNSZ_SIZE(abfd, in, ext) bfd_h_put_16(abfd, in, (bfd_byte*) ext->x_sym.x_misc.x_lnsz.x_size)
+#endif
+#ifndef GET_SCN_SCNLEN
+#define GET_SCN_SCNLEN(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_scn.x_scnlen)
+#endif
+#ifndef GET_SCN_NRELOC
+#define GET_SCN_NRELOC(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *)ext->x_scn.x_nreloc)
+#endif
+#ifndef GET_SCN_NLINNO
+#define GET_SCN_NLINNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *)ext->x_scn.x_nlinno)
+#endif
+#ifndef PUT_SCN_SCNLEN
+#define PUT_SCN_SCNLEN(abfd,in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_scn.x_scnlen)
+#endif
+#ifndef PUT_SCN_NRELOC
+#define PUT_SCN_NRELOC(abfd,in, ext) bfd_h_put_16(abfd, in, (bfd_byte *)ext->x_scn.x_nreloc)
+#endif
+#ifndef PUT_SCN_NLINNO
+#define PUT_SCN_NLINNO(abfd,in, ext) bfd_h_put_16(abfd,in, (bfd_byte *) ext->x_scn.x_nlinno)
+#endif
+#ifndef GET_LINENO_LNNO
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) (ext->l_lnno));
+#endif
+#ifndef PUT_LINENO_LNNO
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_16(abfd,val, (bfd_byte *) (ext->l_lnno));
+#endif
+
+/* The f_symptr field in the filehdr is sometimes 64 bits. */
+#ifndef GET_FILEHDR_SYMPTR
+#define GET_FILEHDR_SYMPTR bfd_h_get_32
+#endif
+#ifndef PUT_FILEHDR_SYMPTR
+#define PUT_FILEHDR_SYMPTR bfd_h_put_32
+#endif
+
+/* Some fields in the aouthdr are sometimes 64 bits. */
+#ifndef GET_AOUTHDR_TSIZE
+#define GET_AOUTHDR_TSIZE bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_TSIZE
+#define PUT_AOUTHDR_TSIZE bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_DSIZE
+#define GET_AOUTHDR_DSIZE bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_DSIZE
+#define PUT_AOUTHDR_DSIZE bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_BSIZE
+#define GET_AOUTHDR_BSIZE bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_BSIZE
+#define PUT_AOUTHDR_BSIZE bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_ENTRY
+#define GET_AOUTHDR_ENTRY bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_ENTRY
+#define PUT_AOUTHDR_ENTRY bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_TEXT_START
+#define GET_AOUTHDR_TEXT_START bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_TEXT_START
+#define PUT_AOUTHDR_TEXT_START bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_DATA_START
+#define GET_AOUTHDR_DATA_START bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_DATA_START
+#define PUT_AOUTHDR_DATA_START bfd_h_put_32
+#endif
+
+/* Some fields in the scnhdr are sometimes 64 bits. */
+#ifndef GET_SCNHDR_PADDR
+#define GET_SCNHDR_PADDR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_PADDR
+#define PUT_SCNHDR_PADDR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_VADDR
+#define GET_SCNHDR_VADDR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_VADDR
+#define PUT_SCNHDR_VADDR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_SIZE
+#define GET_SCNHDR_SIZE bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_SIZE
+#define PUT_SCNHDR_SIZE bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_SCNPTR
+#define GET_SCNHDR_SCNPTR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_SCNPTR
+#define PUT_SCNHDR_SCNPTR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_RELPTR
+#define GET_SCNHDR_RELPTR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_RELPTR
+#define PUT_SCNHDR_RELPTR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_LNNOPTR
+#define GET_SCNHDR_LNNOPTR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_LNNOPTR
+#define PUT_SCNHDR_LNNOPTR bfd_h_put_32
+#endif
+
+#ifndef NO_COFF_RELOCS
+
+static void
+coff_swap_reloc_in (abfd, src, dst)
+ bfd *abfd;
+ PTR src;
+ PTR dst;
+{
+ RELOC *reloc_src = (RELOC *) src;
+ struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
+
+ reloc_dst->r_vaddr = bfd_h_get_32(abfd, (bfd_byte *)reloc_src->r_vaddr);
+ reloc_dst->r_symndx = bfd_h_get_signed_32(abfd, (bfd_byte *) reloc_src->r_symndx);
+
+#ifdef RS6000COFF_C
+ reloc_dst->r_type = bfd_h_get_8(abfd, reloc_src->r_type);
+ reloc_dst->r_size = bfd_h_get_8(abfd, reloc_src->r_size);
+#else
+ reloc_dst->r_type = bfd_h_get_16(abfd, (bfd_byte *) reloc_src->r_type);
+#endif
+
+#ifdef SWAP_IN_RELOC_OFFSET
+ reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET(abfd,
+ (bfd_byte *) reloc_src->r_offset);
+#endif
+}
+
+
+static unsigned int
+coff_swap_reloc_out (abfd, src, dst)
+ bfd *abfd;
+ PTR src;
+ PTR dst;
+{
+ struct internal_reloc *reloc_src = (struct internal_reloc *)src;
+ struct external_reloc *reloc_dst = (struct external_reloc *)dst;
+ bfd_h_put_32(abfd, reloc_src->r_vaddr, (bfd_byte *) reloc_dst->r_vaddr);
+ bfd_h_put_32(abfd, reloc_src->r_symndx, (bfd_byte *) reloc_dst->r_symndx);
+
+#ifdef RS6000COFF_C
+ bfd_h_put_8 (abfd, reloc_src->r_type, (bfd_byte *) reloc_dst->r_type);
+ bfd_h_put_8 (abfd, reloc_src->r_size, (bfd_byte *) reloc_dst->r_size);
+#else
+ bfd_h_put_16(abfd, reloc_src->r_type, (bfd_byte *)
+ reloc_dst->r_type);
+#endif
+
+#ifdef SWAP_OUT_RELOC_OFFSET
+ SWAP_OUT_RELOC_OFFSET(abfd,
+ reloc_src->r_offset,
+ (bfd_byte *) reloc_dst->r_offset);
+#endif
+#ifdef SWAP_OUT_RELOC_EXTRA
+ SWAP_OUT_RELOC_EXTRA(abfd,reloc_src, reloc_dst);
+#endif
+
+ return sizeof(struct external_reloc);
+}
+
+#endif /* NO_COFF_RELOCS */
+
+static void
+coff_swap_filehdr_in (abfd, src, dst)
+ bfd *abfd;
+ PTR src;
+ PTR dst;
+{
+ FILHDR *filehdr_src = (FILHDR *) src;
+ struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
+ filehdr_dst->f_magic = bfd_h_get_16(abfd, (bfd_byte *) filehdr_src->f_magic);
+ filehdr_dst->f_nscns = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_nscns);
+ filehdr_dst->f_timdat = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_timdat);
+ filehdr_dst->f_symptr =
+ GET_FILEHDR_SYMPTR (abfd, (bfd_byte *) filehdr_src->f_symptr);
+ filehdr_dst->f_nsyms = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_nsyms);
+ filehdr_dst->f_opthdr = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_opthdr);
+ filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags);
+}
+
+static unsigned int
+coff_swap_filehdr_out (abfd, in, out)
+ bfd *abfd;
+ PTR in;
+ PTR out;
+{
+ struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in;
+ FILHDR *filehdr_out = (FILHDR *)out;
+
+ bfd_h_put_16(abfd, filehdr_in->f_magic, (bfd_byte *) filehdr_out->f_magic);
+ bfd_h_put_16(abfd, filehdr_in->f_nscns, (bfd_byte *) filehdr_out->f_nscns);
+ bfd_h_put_32(abfd, filehdr_in->f_timdat, (bfd_byte *) filehdr_out->f_timdat);
+ PUT_FILEHDR_SYMPTR (abfd, (bfd_vma) filehdr_in->f_symptr,
+ (bfd_byte *) filehdr_out->f_symptr);
+ bfd_h_put_32(abfd, filehdr_in->f_nsyms, (bfd_byte *) filehdr_out->f_nsyms);
+ bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr);
+ bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags);
+
+ return sizeof(FILHDR);
+}
+
+
+#ifndef NO_COFF_SYMBOLS
+
+static void
+coff_swap_sym_in (abfd, ext1, in1)
+ bfd *abfd;
+ PTR ext1;
+ PTR in1;
+{
+ SYMENT *ext = (SYMENT *)ext1;
+ struct internal_syment *in = (struct internal_syment *)in1;
+
+ if( ext->e.e_name[0] == 0) {
+ in->_n._n_n._n_zeroes = 0;
+ in->_n._n_n._n_offset = bfd_h_get_32(abfd, (bfd_byte *) ext->e.e.e_offset);
+ }
+ else {
+#if SYMNMLEN != E_SYMNMLEN
+ -> Error, we need to cope with truncating or extending SYMNMLEN!;
+#else
+ memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN);
+#endif
+ }
+ in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value);
+ in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum);
+ if (sizeof(ext->e_type) == 2){
+ in->n_type = bfd_h_get_16(abfd, (bfd_byte *) ext->e_type);
+ }
+ else {
+ in->n_type = bfd_h_get_32(abfd, (bfd_byte *) ext->e_type);
+ }
+ in->n_sclass = bfd_h_get_8(abfd, ext->e_sclass);
+ in->n_numaux = bfd_h_get_8(abfd, ext->e_numaux);
+}
+
+static unsigned int
+coff_swap_sym_out (abfd, inp, extp)
+ bfd *abfd;
+ PTR inp;
+ PTR extp;
+{
+ struct internal_syment *in = (struct internal_syment *)inp;
+ SYMENT *ext =(SYMENT *)extp;
+ if(in->_n._n_name[0] == 0) {
+ bfd_h_put_32(abfd, 0, (bfd_byte *) ext->e.e.e_zeroes);
+ bfd_h_put_32(abfd, in->_n._n_n._n_offset, (bfd_byte *) ext->e.e.e_offset);
+ }
+ else {
+#if SYMNMLEN != E_SYMNMLEN
+ -> Error, we need to cope with truncating or extending SYMNMLEN!;
+#else
+ memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN);
+#endif
+ }
+ bfd_h_put_32(abfd, in->n_value , (bfd_byte *) ext->e_value);
+ bfd_h_put_16(abfd, in->n_scnum , (bfd_byte *) ext->e_scnum);
+ if (sizeof(ext->e_type) == 2)
+ {
+ bfd_h_put_16(abfd, in->n_type , (bfd_byte *) ext->e_type);
+ }
+ else
+ {
+ bfd_h_put_32(abfd, in->n_type , (bfd_byte *) ext->e_type);
+ }
+ bfd_h_put_8(abfd, in->n_sclass , ext->e_sclass);
+ bfd_h_put_8(abfd, in->n_numaux , ext->e_numaux);
+ return sizeof(SYMENT);
+}
+
+static void
+coff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
+ bfd *abfd;
+ PTR ext1;
+ int type;
+ int class;
+ int indx;
+ int numaux;
+ PTR in1;
+{
+ AUXENT *ext = (AUXENT *)ext1;
+ union internal_auxent *in = (union internal_auxent *)in1;
+
+ switch (class) {
+ case C_FILE:
+ if (ext->x_file.x_fname[0] == 0) {
+ in->x_file.x_n.x_zeroes = 0;
+ in->x_file.x_n.x_offset =
+ bfd_h_get_32(abfd, (bfd_byte *) ext->x_file.x_n.x_offset);
+ } else {
+#if FILNMLEN != E_FILNMLEN
+ -> Error, we need to cope with truncating or extending FILNMLEN!;
+#else
+ memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+#endif
+ }
+ return;
+
+ /* RS/6000 "csect" auxents */
+#ifdef RS6000COFF_C
+ case C_EXT:
+ case C_HIDEXT:
+ if (indx + 1 == numaux)
+ {
+ in->x_csect.x_scnlen.l = bfd_h_get_32 (abfd, ext->x_csect.x_scnlen);
+ in->x_csect.x_parmhash = bfd_h_get_32 (abfd,
+ ext->x_csect.x_parmhash);
+ in->x_csect.x_snhash = bfd_h_get_16 (abfd, ext->x_csect.x_snhash);
+ /* We don't have to hack bitfields in x_smtyp because it's
+ defined by shifts-and-ands, which are equivalent on all
+ byte orders. */
+ in->x_csect.x_smtyp = bfd_h_get_8 (abfd, ext->x_csect.x_smtyp);
+ in->x_csect.x_smclas = bfd_h_get_8 (abfd, ext->x_csect.x_smclas);
+ in->x_csect.x_stab = bfd_h_get_32 (abfd, ext->x_csect.x_stab);
+ in->x_csect.x_snstab = bfd_h_get_16 (abfd, ext->x_csect.x_snstab);
+ return;
+ }
+ break;
+#endif
+
+ case C_STAT:
+#ifdef C_LEAFSTAT
+ case C_LEAFSTAT:
+#endif
+ case C_HIDDEN:
+ if (type == T_NULL) {
+ in->x_scn.x_scnlen = GET_SCN_SCNLEN(abfd, ext);
+ in->x_scn.x_nreloc = GET_SCN_NRELOC(abfd, ext);
+ in->x_scn.x_nlinno = GET_SCN_NLINNO(abfd, ext);
+ return;
+ }
+ break;
+ }
+
+ in->x_sym.x_tagndx.l = bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_tagndx);
+#ifndef NO_TVNDX
+ in->x_sym.x_tvndx = bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_tvndx);
+#endif
+
+ if (class == C_BLOCK || ISFCN (type) || ISTAG (class))
+ {
+ in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext);
+ in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext);
+ }
+ else
+ {
+#if DIMNUM != E_DIMNUM
+ #error we need to cope with truncating or extending DIMNUM
+#endif
+ in->x_sym.x_fcnary.x_ary.x_dimen[0] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
+ in->x_sym.x_fcnary.x_ary.x_dimen[1] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
+ in->x_sym.x_fcnary.x_ary.x_dimen[2] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
+ in->x_sym.x_fcnary.x_ary.x_dimen[3] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
+ }
+
+ if (ISFCN(type)) {
+ in->x_sym.x_misc.x_fsize = bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_misc.x_fsize);
+ }
+ else {
+ in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO(abfd, ext);
+ in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE(abfd, ext);
+ }
+}
+
+static unsigned int
+coff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
+ bfd *abfd;
+ PTR inp;
+ int type;
+ int class;
+ int indx;
+ int numaux;
+ PTR extp;
+{
+ union internal_auxent *in = (union internal_auxent *)inp;
+ AUXENT *ext = (AUXENT *)extp;
+
+ memset((PTR)ext, 0, AUXESZ);
+ switch (class) {
+ case C_FILE:
+ if (in->x_file.x_fname[0] == 0) {
+ PUTWORD(abfd, 0, (bfd_byte *) ext->x_file.x_n.x_zeroes);
+ PUTWORD(abfd,
+ in->x_file.x_n.x_offset,
+ (bfd_byte *) ext->x_file.x_n.x_offset);
+ }
+ else {
+#if FILNMLEN != E_FILNMLEN
+ -> Error, we need to cope with truncating or extending FILNMLEN!;
+#else
+ memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
+#endif
+ }
+ return sizeof (AUXENT);
+
+#ifdef RS6000COFF_C
+ /* RS/6000 "csect" auxents */
+ case C_EXT:
+ case C_HIDEXT:
+ if (indx + 1 == numaux)
+ {
+ PUTWORD (abfd, in->x_csect.x_scnlen.l, ext->x_csect.x_scnlen);
+ PUTWORD (abfd, in->x_csect.x_parmhash, ext->x_csect.x_parmhash);
+ PUTHALF (abfd, in->x_csect.x_snhash, ext->x_csect.x_snhash);
+ /* We don't have to hack bitfields in x_smtyp because it's
+ defined by shifts-and-ands, which are equivalent on all
+ byte orders. */
+ PUTBYTE (abfd, in->x_csect.x_smtyp, ext->x_csect.x_smtyp);
+ PUTBYTE (abfd, in->x_csect.x_smclas, ext->x_csect.x_smclas);
+ PUTWORD (abfd, in->x_csect.x_stab, ext->x_csect.x_stab);
+ PUTHALF (abfd, in->x_csect.x_snstab, ext->x_csect.x_snstab);
+ return sizeof (AUXENT);
+ }
+ break;
+#endif
+
+ case C_STAT:
+#ifdef C_LEAFSTAT
+ case C_LEAFSTAT:
+#endif
+ case C_HIDDEN:
+ if (type == T_NULL) {
+ PUT_SCN_SCNLEN(abfd, in->x_scn.x_scnlen, ext);
+ PUT_SCN_NRELOC(abfd, in->x_scn.x_nreloc, ext);
+ PUT_SCN_NLINNO(abfd, in->x_scn.x_nlinno, ext);
+ return sizeof (AUXENT);
+ }
+ break;
+ }
+
+ PUTWORD(abfd, in->x_sym.x_tagndx.l, (bfd_byte *) ext->x_sym.x_tagndx);
+#ifndef NO_TVNDX
+ bfd_h_put_16(abfd, in->x_sym.x_tvndx , (bfd_byte *) ext->x_sym.x_tvndx);
+#endif
+
+ if (class == C_BLOCK || ISFCN (type) || ISTAG (class))
+ {
+ PUT_FCN_LNNOPTR(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext);
+ PUT_FCN_ENDNDX(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext);
+ }
+ else
+ {
+#if DIMNUM != E_DIMNUM
+ #error we need to cope with truncating or extending DIMNUM
+#endif
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
+ }
+
+ if (ISFCN (type))
+ PUTWORD (abfd, in->x_sym.x_misc.x_fsize,
+ (bfd_byte *) ext->x_sym.x_misc.x_fsize);
+ else
+ {
+ PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext);
+ PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext);
+ }
+
+ return sizeof(AUXENT);
+}
+
+#endif /* NO_COFF_SYMBOLS */
+
+#ifndef NO_COFF_LINENOS
+
+static void
+coff_swap_lineno_in (abfd, ext1, in1)
+ bfd *abfd;
+ PTR ext1;
+ PTR in1;
+{
+ LINENO *ext = (LINENO *)ext1;
+ struct internal_lineno *in = (struct internal_lineno *)in1;
+
+ in->l_addr.l_symndx = bfd_h_get_32(abfd, (bfd_byte *) ext->l_addr.l_symndx);
+ in->l_lnno = GET_LINENO_LNNO(abfd, ext);
+}
+
+static unsigned int
+coff_swap_lineno_out (abfd, inp, outp)
+ bfd *abfd;
+ PTR inp;
+ PTR outp;
+{
+ struct internal_lineno *in = (struct internal_lineno *)inp;
+ struct external_lineno *ext = (struct external_lineno *)outp;
+ PUTWORD(abfd, in->l_addr.l_symndx, (bfd_byte *)
+ ext->l_addr.l_symndx);
+
+ PUT_LINENO_LNNO (abfd, in->l_lnno, ext);
+ return sizeof(struct external_lineno);
+}
+
+#endif /* NO_COFF_LINENOS */
+
+
+static void
+coff_swap_aouthdr_in (abfd, aouthdr_ext1, aouthdr_int1)
+ bfd *abfd;
+ PTR aouthdr_ext1;
+ PTR aouthdr_int1;
+{
+ AOUTHDR *aouthdr_ext = (AOUTHDR *) aouthdr_ext1;
+ struct internal_aouthdr *aouthdr_int = (struct internal_aouthdr *)aouthdr_int1;
+
+ aouthdr_int->magic = bfd_h_get_16(abfd, (bfd_byte *) aouthdr_ext->magic);
+ aouthdr_int->vstamp = bfd_h_get_16(abfd, (bfd_byte *) aouthdr_ext->vstamp);
+ aouthdr_int->tsize =
+ GET_AOUTHDR_TSIZE (abfd, (bfd_byte *) aouthdr_ext->tsize);
+ aouthdr_int->dsize =
+ GET_AOUTHDR_DSIZE (abfd, (bfd_byte *) aouthdr_ext->dsize);
+ aouthdr_int->bsize =
+ GET_AOUTHDR_BSIZE (abfd, (bfd_byte *) aouthdr_ext->bsize);
+ aouthdr_int->entry =
+ GET_AOUTHDR_ENTRY (abfd, (bfd_byte *) aouthdr_ext->entry);
+ aouthdr_int->text_start =
+ GET_AOUTHDR_TEXT_START (abfd, (bfd_byte *) aouthdr_ext->text_start);
+ aouthdr_int->data_start =
+ GET_AOUTHDR_DATA_START (abfd, (bfd_byte *) aouthdr_ext->data_start);
+
+#ifdef I960
+ aouthdr_int->tagentries = bfd_h_get_32(abfd, (bfd_byte *) aouthdr_ext->tagentries);
+#endif
+
+#ifdef APOLLO_M68
+ bfd_h_put_32(abfd, aouthdr_int->o_inlib, (bfd_byte *) aouthdr_ext->o_inlib);
+ bfd_h_put_32(abfd, aouthdr_int->o_sri, (bfd_byte *) aouthdr_ext->o_sri);
+ bfd_h_put_32(abfd, aouthdr_int->vid[0], (bfd_byte *) aouthdr_ext->vid);
+ bfd_h_put_32(abfd, aouthdr_int->vid[1], (bfd_byte *) aouthdr_ext->vid + 4);
+#endif
+
+
+#ifdef RS6000COFF_C
+ aouthdr_int->o_toc = bfd_h_get_32(abfd, aouthdr_ext->o_toc);
+ aouthdr_int->o_snentry = bfd_h_get_16(abfd, aouthdr_ext->o_snentry);
+ aouthdr_int->o_sntext = bfd_h_get_16(abfd, aouthdr_ext->o_sntext);
+ aouthdr_int->o_sndata = bfd_h_get_16(abfd, aouthdr_ext->o_sndata);
+ aouthdr_int->o_sntoc = bfd_h_get_16(abfd, aouthdr_ext->o_sntoc);
+ aouthdr_int->o_snloader = bfd_h_get_16(abfd, aouthdr_ext->o_snloader);
+ aouthdr_int->o_snbss = bfd_h_get_16(abfd, aouthdr_ext->o_snbss);
+ aouthdr_int->o_algntext = bfd_h_get_16(abfd, aouthdr_ext->o_algntext);
+ aouthdr_int->o_algndata = bfd_h_get_16(abfd, aouthdr_ext->o_algndata);
+ aouthdr_int->o_modtype = bfd_h_get_16(abfd, aouthdr_ext->o_modtype);
+ aouthdr_int->o_cputype = bfd_h_get_16(abfd, aouthdr_ext->o_cputype);
+ aouthdr_int->o_maxstack = bfd_h_get_32(abfd, aouthdr_ext->o_maxstack);
+ aouthdr_int->o_maxdata = bfd_h_get_32(abfd, aouthdr_ext->o_maxdata);
+#endif
+
+#ifdef MIPSECOFF
+ aouthdr_int->bss_start = bfd_h_get_32(abfd, aouthdr_ext->bss_start);
+ aouthdr_int->gp_value = bfd_h_get_32(abfd, aouthdr_ext->gp_value);
+ aouthdr_int->gprmask = bfd_h_get_32(abfd, aouthdr_ext->gprmask);
+ aouthdr_int->cprmask[0] = bfd_h_get_32(abfd, aouthdr_ext->cprmask[0]);
+ aouthdr_int->cprmask[1] = bfd_h_get_32(abfd, aouthdr_ext->cprmask[1]);
+ aouthdr_int->cprmask[2] = bfd_h_get_32(abfd, aouthdr_ext->cprmask[2]);
+ aouthdr_int->cprmask[3] = bfd_h_get_32(abfd, aouthdr_ext->cprmask[3]);
+#endif
+
+#ifdef ALPHAECOFF
+ aouthdr_int->bss_start = bfd_h_get_64(abfd, aouthdr_ext->bss_start);
+ aouthdr_int->gp_value = bfd_h_get_64(abfd, aouthdr_ext->gp_value);
+ aouthdr_int->gprmask = bfd_h_get_32(abfd, aouthdr_ext->gprmask);
+ aouthdr_int->fprmask = bfd_h_get_32(abfd, aouthdr_ext->fprmask);
+#endif
+}
+
+static unsigned int
+coff_swap_aouthdr_out (abfd, in, out)
+ bfd *abfd;
+ PTR in;
+ PTR out;
+{
+ struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *)in;
+ AOUTHDR *aouthdr_out = (AOUTHDR *)out;
+
+ bfd_h_put_16(abfd, aouthdr_in->magic, (bfd_byte *) aouthdr_out->magic);
+ bfd_h_put_16(abfd, aouthdr_in->vstamp, (bfd_byte *) aouthdr_out->vstamp);
+ PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, (bfd_byte *) aouthdr_out->tsize);
+ PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, (bfd_byte *) aouthdr_out->dsize);
+ PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, (bfd_byte *) aouthdr_out->bsize);
+ PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, (bfd_byte *) aouthdr_out->entry);
+ PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
+ (bfd_byte *) aouthdr_out->text_start);
+ PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
+ (bfd_byte *) aouthdr_out->data_start);
+
+#ifdef I960
+ bfd_h_put_32(abfd, aouthdr_in->tagentries, (bfd_byte *) aouthdr_out->tagentries);
+#endif
+
+#ifdef RS6000COFF_C
+ bfd_h_put_32 (abfd, aouthdr_in->o_toc, aouthdr_out->o_toc);
+ bfd_h_put_16 (abfd, aouthdr_in->o_snentry, aouthdr_out->o_snentry);
+ bfd_h_put_16 (abfd, aouthdr_in->o_sntext, aouthdr_out->o_sntext);
+ bfd_h_put_16 (abfd, aouthdr_in->o_sndata, aouthdr_out->o_sndata);
+ bfd_h_put_16 (abfd, aouthdr_in->o_sntoc, aouthdr_out->o_sntoc);
+ bfd_h_put_16 (abfd, aouthdr_in->o_snloader, aouthdr_out->o_snloader);
+ bfd_h_put_16 (abfd, aouthdr_in->o_snbss, aouthdr_out->o_snbss);
+ bfd_h_put_16 (abfd, aouthdr_in->o_algntext, aouthdr_out->o_algntext);
+ bfd_h_put_16 (abfd, aouthdr_in->o_algndata, aouthdr_out->o_algndata);
+ bfd_h_put_16 (abfd, aouthdr_in->o_modtype, aouthdr_out->o_modtype);
+ bfd_h_put_16 (abfd, aouthdr_in->o_cputype, aouthdr_out->o_cputype);
+ bfd_h_put_32 (abfd, aouthdr_in->o_maxstack, aouthdr_out->o_maxstack);
+ bfd_h_put_32 (abfd, aouthdr_in->o_maxdata, aouthdr_out->o_maxdata);
+ memset (aouthdr_out->o_resv2, 0, sizeof aouthdr_out->o_resv2);
+#endif
+
+#ifdef MIPSECOFF
+ bfd_h_put_32(abfd, aouthdr_in->bss_start, (bfd_byte *) aouthdr_out->bss_start);
+ bfd_h_put_32(abfd, aouthdr_in->gp_value, (bfd_byte *) aouthdr_out->gp_value);
+ bfd_h_put_32(abfd, aouthdr_in->gprmask, (bfd_byte *) aouthdr_out->gprmask);
+ bfd_h_put_32(abfd, aouthdr_in->cprmask[0], (bfd_byte *) aouthdr_out->cprmask[0]);
+ bfd_h_put_32(abfd, aouthdr_in->cprmask[1], (bfd_byte *) aouthdr_out->cprmask[1]);
+ bfd_h_put_32(abfd, aouthdr_in->cprmask[2], (bfd_byte *) aouthdr_out->cprmask[2]);
+ bfd_h_put_32(abfd, aouthdr_in->cprmask[3], (bfd_byte *) aouthdr_out->cprmask[3]);
+#endif
+
+#ifdef ALPHAECOFF
+ /* FIXME: What does bldrev mean? */
+ bfd_h_put_16(abfd, (bfd_vma) 2, (bfd_byte *) aouthdr_out->bldrev);
+ bfd_h_put_16(abfd, (bfd_vma) 0, (bfd_byte *) aouthdr_out->padding);
+ bfd_h_put_64(abfd, aouthdr_in->bss_start, (bfd_byte *) aouthdr_out->bss_start);
+ bfd_h_put_64(abfd, aouthdr_in->gp_value, (bfd_byte *) aouthdr_out->gp_value);
+ bfd_h_put_32(abfd, aouthdr_in->gprmask, (bfd_byte *) aouthdr_out->gprmask);
+ bfd_h_put_32(abfd, aouthdr_in->fprmask, (bfd_byte *) aouthdr_out->fprmask);
+#endif
+
+ return sizeof(AOUTHDR);
+}
+
+static void
+coff_swap_scnhdr_in (abfd, ext, in)
+ bfd *abfd;
+ PTR ext;
+ PTR in;
+{
+ SCNHDR *scnhdr_ext = (SCNHDR *) ext;
+ struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
+
+ memcpy(scnhdr_int->s_name, scnhdr_ext->s_name, sizeof(scnhdr_int->s_name));
+ scnhdr_int->s_vaddr =
+ GET_SCNHDR_VADDR (abfd, (bfd_byte *) scnhdr_ext->s_vaddr);
+ scnhdr_int->s_paddr =
+ GET_SCNHDR_PADDR (abfd, (bfd_byte *) scnhdr_ext->s_paddr);
+ scnhdr_int->s_size =
+ GET_SCNHDR_SIZE (abfd, (bfd_byte *) scnhdr_ext->s_size);
+
+ scnhdr_int->s_scnptr =
+ GET_SCNHDR_SCNPTR (abfd, (bfd_byte *) scnhdr_ext->s_scnptr);
+ scnhdr_int->s_relptr =
+ GET_SCNHDR_RELPTR (abfd, (bfd_byte *) scnhdr_ext->s_relptr);
+ scnhdr_int->s_lnnoptr =
+ GET_SCNHDR_LNNOPTR (abfd, (bfd_byte *) scnhdr_ext->s_lnnoptr);
+ scnhdr_int->s_flags = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_flags);
+#if defined(M88)
+ scnhdr_int->s_nreloc = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_nreloc);
+ scnhdr_int->s_nlnno = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_nlnno);
+#else
+ scnhdr_int->s_nreloc = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nreloc);
+ scnhdr_int->s_nlnno = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nlnno);
+#endif
+#ifdef I960
+ scnhdr_int->s_align = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_align);
+#endif
+}
+
+static unsigned int
+coff_swap_scnhdr_out (abfd, in, out)
+ bfd *abfd;
+ PTR in;
+ PTR out;
+{
+ struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *)in;
+ SCNHDR *scnhdr_ext = (SCNHDR *)out;
+ unsigned int ret = sizeof (SCNHDR);
+
+ memcpy(scnhdr_ext->s_name, scnhdr_int->s_name, sizeof(scnhdr_int->s_name));
+
+ PUT_SCNHDR_VADDR (abfd, scnhdr_int->s_vaddr,
+ (bfd_byte *) scnhdr_ext->s_vaddr);
+
+
+ PUT_SCNHDR_PADDR (abfd, scnhdr_int->s_paddr,
+ (bfd_byte *) scnhdr_ext->s_paddr);
+ PUT_SCNHDR_SIZE (abfd, scnhdr_int->s_size,
+ (bfd_byte *) scnhdr_ext->s_size);
+
+ PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr,
+ (bfd_byte *) scnhdr_ext->s_scnptr);
+ PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr,
+ (bfd_byte *) scnhdr_ext->s_relptr);
+ PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr,
+ (bfd_byte *) scnhdr_ext->s_lnnoptr);
+ PUTWORD(abfd, scnhdr_int->s_flags, (bfd_byte *) scnhdr_ext->s_flags);
+#if defined(M88)
+ PUTWORD(abfd, scnhdr_int->s_nlnno, (bfd_byte *) scnhdr_ext->s_nlnno);
+ PUTWORD(abfd, scnhdr_int->s_nreloc, (bfd_byte *) scnhdr_ext->s_nreloc);
+#else
+ if (scnhdr_int->s_nlnno <= 0xffff)
+ PUTHALF(abfd, scnhdr_int->s_nlnno, (bfd_byte *) scnhdr_ext->s_nlnno);
+ else
+ {
+ (*_bfd_error_handler) ("%s: line number overflow: 0x%lx > 0xffff",
+ bfd_get_filename (abfd),
+ scnhdr_int->s_nlnno);
+ bfd_set_error (bfd_error_file_truncated);
+ PUTHALF (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nlnno);
+ ret = 0;
+ }
+ if (scnhdr_int->s_nreloc <= 0xffff)
+ PUTHALF(abfd, scnhdr_int->s_nreloc, (bfd_byte *) scnhdr_ext->s_nreloc);
+ else
+ {
+ (*_bfd_error_handler) ("%s: reloc overflow: 0x%lx > 0xffff",
+ bfd_get_filename (abfd),
+ scnhdr_int->s_nreloc);
+ bfd_set_error (bfd_error_file_truncated);
+ PUTHALF (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nreloc);
+ ret = 0;
+ }
+#endif
+
+#if defined(I960)
+ PUTWORD(abfd, scnhdr_int->s_align, (bfd_byte *) scnhdr_ext->s_align);
+#endif
+ return ret;
+}
diff --git a/contrib/gdb/bfd/config.bfd b/contrib/gdb/bfd/config.bfd
new file mode 100644
index 0000000..7757d5f
--- /dev/null
+++ b/contrib/gdb/bfd/config.bfd
@@ -0,0 +1,491 @@
+# config.bfd
+# Convert a canonical host type into a BFD host type.
+# Set shell variable targ to canonical target name, and run
+# using ``. config.bfd''.
+# Sets the following shell variables:
+# targ_defvec Default vector for this target
+# targ_selvecs Vectors to build for this target
+# targ_archs Architectures for this target
+# targ_cflags $(CFLAGS) for this target (FIXME: pretty bogus)
+# targ_undercore Whether underscores are used: yes or no
+
+# The binutils c++filt program wants to know whether underscores are
+# stripped or not. That is why we set targ_underscore. c++filt uses
+# this information to choose a default. This information is
+# duplicated in the symbol_leading_char field of the BFD target
+# vector, but c++filt does not deal with object files and is not
+# linked against libbfd.a. It is not terribly important that c++filt
+# get this right; it is just convenient.
+
+targ_defvec=
+targ_selvecs=
+targ_cflags=
+targ_underscore=no
+
+targ_cpu=`echo $targ | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+case "${targ_cpu}" in
+arm*) targ_archs=bfd_arm_arch ;;
+hppa*) targ_archs=bfd_hppa_arch ;;
+i[345]86) targ_archs=bfd_i386_arch ;;
+m68*) targ_archs=bfd_m68k_arch ;;
+m88*) targ_archs=bfd_m88k_arch ;;
+mips*) targ_archs=bfd_mips_arch ;;
+powerpc*) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;;
+rs6000) targ_archs="bfd_rs6000_arch bfd_powerpc_arch" ;;
+sparc*) targ_archs=bfd_sparc_arch ;;
+z8k*) targ_archs=bfd_z8k_arch ;;
+*) targ_archs=bfd_${targ_cpu}_arch ;;
+esac
+
+# WHEN ADDING ENTRIES TO THIS MATRIX:
+# Make sure that the left side always has two dashes. Otherwise you
+# can get spurious matches. Even for unambiguous cases, do this as a
+# convention, else the table becomes a real mess to understand and maintain.
+
+case "${targ}" in
+ alpha-*-netware*)
+ targ_defvec=ecoffalpha_little_vec
+ targ_selvecs=nlm32_alpha_vec
+ ;;
+ alpha-*-*)
+ targ_defvec=ecoffalpha_little_vec
+ ;;
+
+
+ arm-*-riscix*)
+ targ_defvec=riscix_vec
+ ;;
+ arm-*-pe*)
+ targ_defvec=armpe_little_vec
+ targ_selvecs="armpe_little_vec armpe_big_vec armpei_little_vec armpei_big_vec"
+ targ_underscore=yes
+ ;;
+ arm-*-aout | armel-*-aout)
+ targ_defvec=aout_arm_little_vec
+ targ_selvecs=aout_arm_big_vec
+ ;;
+ armeb-*-aout)
+ targ_defvec=aout_arm_big_vec
+ targ_selvecs=aout_arm_little_vec
+ ;;
+ arm-*-coff)
+ targ_defvec=armcoff_little_vec
+ targ_selvecs=armcoff_big_vec
+ targ_underscore=yes
+ ;;
+
+ a29k-*-ebmon* | a29k-*-udi* | a29k-*-coff* | a29k-*-sym1* | \
+ a29k-*-vxworks* | a29k-*-sysv*)
+ targ_defvec=a29kcoff_big_vec
+ targ_selvecs=sunos_big_vec
+ targ_underscore=yes
+ ;;
+ a29k-*-aout* | a29k-*-bsd* | a29k-*-vsta*)
+ targ_defvec=sunos_big_vec
+ targ_underscore=yes
+ ;;
+
+ h8300*-*-*)
+ targ_defvec=h8300coff_vec
+ targ_underscore=yes
+ ;;
+
+ h8500-*-*)
+ targ_defvec=h8500coff_vec
+ targ_underscore=yes
+ ;;
+
+ sh-*-*)
+ targ_defvec=shcoff_vec
+ targ_selvecs="shcoff_vec shlcoff_vec"
+ targ_underscore=yes
+ ;;
+
+ hppa*-*-*elf* | hppa*-*-lites* | hppa*-*-sysv4*)
+ targ_defvec=bfd_elf32_hppa_vec
+ ;;
+ hppa*-*-bsd*)
+ targ_defvec=som_vec
+ targ_selvecs=bfd_elf32_hppa_vec
+ ;;
+ hppa*-*-hpux* | hppa*-*-hiux*)
+ targ_defvec=som_vec
+ ;;
+ hppa*-*-osf*)
+ targ_defvec=som_vec
+ targ_selvecs=bfd_elf32_hppa_vec
+ ;;
+
+ i[345]86-*-sysv4* | i[345]86-*-unixware | i[345]86-*-solaris2* | \
+ i[345]86-*-elf | i[345]86-*-sco*elf*)
+ targ_defvec=bfd_elf32_i386_vec
+ targ_selvecs=i386coff_vec
+ ;;
+ i[345]86-*-sysv* | i[345]86-*-isc* | i[345]86-*-sco* | i[345]86-*-coff | \
+ i[345]86-*-aix* | i[345]86-*-go32*)
+ targ_defvec=i386coff_vec
+ ;;
+ i[345]86-sequent-bsd*)
+ targ_defvec=i386dynix_vec
+ targ_underscore=yes
+ ;;
+ i[345]86-*-bsd*)
+ targ_defvec=i386bsd_vec
+ targ_underscore=yes
+ ;;
+ i[345]86-*-freebsd*)
+ targ_defvec=i386freebsd_vec
+ targ_selvecs=i386bsd_vec
+ targ_underscore=yes
+ ;;
+ i[345]86-*-netbsd*)
+ targ_defvec=i386netbsd_vec
+ targ_selvecs=i386bsd_vec
+ targ_underscore=yes
+ ;;
+ i[345]86-*-netware*)
+ targ_defvec=bfd_elf32_i386_vec
+ targ_selvecs="nlm32_i386_vec i386coff_vec i386aout_vec"
+ ;;
+ i[345]86-*-linuxaout*)
+ targ_defvec=i386linux_vec
+ targ_selvecs=bfd_elf32_i386_vec
+ targ_underscore=yes
+ ;;
+ i[345]86-*-linux*)
+ targ_defvec=bfd_elf32_i386_vec
+ targ_selvecs=i386linux_vec
+ targ_underscore=yes
+ ;;
+ i[345]86-*-lynxos*)
+ targ_defvec=i386lynx_coff_vec
+ targ_selvecs=i386lynx_aout_vec
+ ;;
+ i[345]86-*-gnu*)
+ targ_defvec=bfd_elf32_i386_vec
+ targ_selvecs=i386mach3_vec
+ targ_cflags=-DSTAT_FOR_EXEC
+ targ_underscore=yes
+ ;;
+ i[345]86-*-mach* | i[345]86-*-osf1mk*)
+ targ_defvec=i386mach3_vec
+ targ_cflags=-DSTAT_FOR_EXEC
+ targ_underscore=yes
+ ;;
+ i[345]86-*-os9k)
+ targ_defvec=i386os9k_vec
+ ;;
+ i[345]86-*-msdos*)
+ targ_defvec=i386aout_vec
+ targ_selvecs=i386msdos_vec
+ ;;
+ i[345]86-*-moss*)
+ targ_defvec=bfd_elf32_i386_vec
+ targ_selvecs="i386msdos_vec i386aout_vec"
+ ;;
+ i[345]86-*-cygwin32 | i[345]86-*-winnt | i[345]86-*-pe)
+ targ_defvec=i386pe_vec
+ targ_selvecs="i386pe_vec i386pei_vec"
+ ;;
+ i[345]86-none-*)
+ targ_defvec=i386coff_vec
+ ;;
+ i[345]86-*-aout* | i[345]86*-*-vsta*)
+ targ_defvec=i386aout_vec
+ ;;
+
+ i860-*-mach3* | i860-*-osf1* | i860-*-coff*)
+ targ_defvec=i860coff_vec
+ ;;
+ i860-*-sysv4* | i860-*-elf*)
+ targ_defvec=bfd_elf32_i860_vec
+ ;;
+
+ i960-*-vxworks4* | i960-*-vxworks5.0)
+ targ_defvec=b_out_vec_little_host
+ targ_selvecs="b_out_vec_big_host icoff_little_vec icoff_big_vec"
+ targ_underscore=yes
+ ;;
+ i960-*-vxworks5.* | i960-*-coff* | i960-*-sysv*)
+ targ_defvec=icoff_little_vec
+ targ_selvecs="icoff_big_vec b_out_vec_little_host b_out_vec_big_host"
+ targ_underscore=yes
+ ;;
+ i960-*-vxworks* | i960-*-aout* | i960-*-bout* | i960-*-nindy*)
+ targ_defvec=b_out_vec_little_host
+ targ_selvecs="b_out_vec_big_host icoff_little_vec icoff_big_vec"
+ targ_underscore=yes
+ ;;
+
+ m68*-apollo-*)
+ targ_defvec=apollocoff_vec
+ ;;
+ m68*-bull-sysv*)
+ targ_defvec=m68kcoffun_vec
+ targ_underscore=yes
+ ;;
+ m68*-hp-bsd*)
+ targ_defvec=hp300bsd_vec
+ targ_underscore=yes
+ ;;
+ m68*-*-aout*)
+ targ_defvec=aout0_big_vec
+ # We include this here, rather than making a separate cisco
+ # configuration, so that cisco-core.c gets routinely tested at
+ # least for compilation.
+ targ_selvecs=cisco_core_vec
+ targ_underscore=yes
+ ;;
+ m68*-*-elf* | m68*-*-sysv4*)
+ targ_defvec=bfd_elf32_m68k_vec
+ targ_selvecs=m68kcoff_vec
+ ;;
+ m68*-*-coff* | m68*-*-sysv*)
+ targ_defvec=m68kcoff_vec
+ targ_selvecs="m68kcoff_vec versados_vec"
+ ;;
+ m68*-*-hpux*)
+ targ_defvec=hp300hpux_vec
+ targ_underscore=yes
+ ;;
+ m68*-*-linuxaout*)
+ targ_defvec=m68klinux_vec
+ targ_selvecs=bfd_elf32_m68k_vec
+ targ_underscore=yes
+ ;;
+ m68*-*-linux*)
+ targ_defvec=bfd_elf32_m68k_vec
+ targ_selvecs=m68klinux_vec
+ ;;
+ m68*-*-lynxos*)
+ targ_defvec=m68klynx_coff_vec
+ targ_selvecs=m68klynx_aout_vec
+ ;;
+ m68*-hp*-netbsd*)
+ targ_defvec=m68k4knetbsd_vec
+ targ_selvecs="m68knetbsd_vec hp300bsd_vec sunos_big_vec"
+ targ_underscore=yes
+ ;;
+ m68*-*-netbsd*)
+ targ_defvec=m68knetbsd_vec
+ targ_selvecs="m68k4knetbsd_vec hp300bsd_vec sunos_big_vec"
+ targ_underscore=yes
+ ;;
+ m68*-*-sunos* | m68*-*-os68k* | m68*-*-vxworks* | m68*-netx-* | \
+ m68*-*-bsd* | m68*-*-vsta*)
+ targ_defvec=sunos_big_vec
+ targ_underscore=yes
+ ;;
+ m68*-ericsson-*)
+ targ_defvec=sunos_big_vec
+ targ_selvecs="m68kcoff_vec tekhex_vec"
+ targ_underscore=yes
+ ;;
+ m68*-cbm-*)
+ targ_defvec=bfd_elf32_m68k_vec
+ targ_selvecs=m68kcoff_vec
+ ;;
+ m68*-apple-aux*)
+ targ_defvec=m68kaux_coff_vec
+ ;;
+ m68*-*-psos*)
+ targ_defvec=bfd_elf32_m68k_vec
+ targ_selvecs=ieee_vec
+ targ_underscore=yes
+ ;;
+
+ m88*-harris-cxux* | m88*-*-dgux* | m88*-*-sysv4*)
+ targ_defvec=bfd_elf32_m88k_vec
+ targ_selvecs=m88kbcs_vec
+ ;;
+ m88*-*-mach3*)
+ targ_defvec=m88kmach3_vec
+ targ_cflags=-DSTAT_FOR_EXEC
+ ;;
+ m88*-*-*)
+ targ_defvec=m88kbcs_vec
+ targ_underscore=yes
+ ;;
+
+ mips*-big-*)
+ targ_defvec=ecoff_big_vec
+ targ_selvecs=ecoff_little_vec
+ ;;
+ mips-dec-netbsd*)
+ targ_defvec=bfd_elf32_littlemips_vec
+ targ_selvecs=bfd_elf32_bigmips_vec
+ ;;
+ mips*-dec-bsd*)
+ targ_defvec=aout_mips_little_vec
+ targ_underscore=yes
+ ;;
+ mips*-dec-mach3*)
+ targ_defvec=aout_mips_little_vec
+ targ_cflags=-DSTAT_FOR_EXEC
+ ;;
+ mips*-dec-* | mips*el-*-ecoff*)
+ targ_defvec=ecoff_little_vec
+ targ_selvecs=ecoff_big_vec
+ ;;
+ mips*-*-ecoff*)
+ targ_defvec=ecoff_big_vec
+ targ_selvecs=ecoff_little_vec
+ ;;
+ mips*-*-irix5*)
+ targ_defvec=bfd_elf32_bigmips_vec
+ targ_selvecs="bfd_elf32_littlemips_vec ecoff_big_vec ecoff_little_vec"
+ ;;
+ mips*-sgi-* | mips*-*-bsd*)
+ targ_defvec=ecoff_big_vec
+ targ_selvecs=ecoff_little_vec
+ ;;
+ mips*-*-mach3*)
+ targ_defvec=aout_mips_little_vec
+ targ_cflags=-DSTAT_FOR_EXEC
+ ;;
+ mips*-*-sysv4*)
+ targ_defvec=bfd_elf32_bigmips_vec
+ targ_selvecs="bfd_elf32_littlemips_vec ecoff_big_vec ecoff_little_vec"
+ ;;
+ mips*-*-sysv* | mips*-*-riscos*)
+ targ_defvec=ecoff_big_vec
+ targ_selvecs=ecoff_little_vec
+ ;;
+ mips*el-*-elf*)
+ targ_defvec=bfd_elf32_littlemips_vec
+ targ_selvecs=bfd_elf32_bigmips_vec
+ ;;
+ mips*-*-elf*)
+ targ_defvec=bfd_elf32_bigmips_vec
+ targ_selvecs=bfd_elf32_littlemips_vec
+ ;;
+
+ ns32k-pc532-mach* | ns32k-pc532-ux*)
+ targ_defvec=pc532machaout_vec
+ targ_underscore=yes
+ ;;
+ ns32k-*-netbsd* | ns32k-*-lites*)
+ targ_defvec=pc532netbsd_vec
+ targ_underscore=yes
+ ;;
+
+ powerpc-*-aix*)
+ targ_defvec=rs6000coff_vec
+ ;;
+ powerpc-*-elf* | powerpc-*-sysv4* | powerpc-*-eabi* | powerpc-*-solaris2*)
+ targ_defvec=bfd_elf32_powerpc_vec
+ targ_selvecs="rs6000coff_vec bfd_elf32_powerpcle_vec bfd_powerpcle_pei_vec bfd_powerpc_pei_vec bfd_powerpcle_pe_vec bfd_powerpc_pe_vec"
+ ;;
+ powerpc-*-macos* | powerpc-*-mpw*)
+ targ_defvec=pmac_xcoff_vec
+ ;;
+ powerpc-*-netware*)
+ targ_defvec=bfd_elf32_powerpc_vec
+ targ_selvecs="nlm32_powerpc_vec rs6000coff_vec"
+ ;;
+ powerpcle-*-elf* | powerpcle-*-sysv4* | powerpcle-*-eabi* | \
+ powerpcle-*-solaris2*)
+ targ_defvec=bfd_elf32_powerpcle_vec
+ targ_selvecs="rs6000coff_vec bfd_elf32_powerpc_vec bfd_powerpcle_pei_vec bfd_powerpc_pei_vec bfd_powerpcle_pe_vec bfd_powerpc_pe_vec"
+ ;;
+
+ powerpcle-*-pe | powerpcle-*-winnt* | powerpcle-*-cygwin32)
+ targ_defvec=bfd_powerpcle_pe_vec
+ targ_selvecs="bfd_powerpcle_pei_vec bfd_powerpc_pei_vec bfd_powerpcle_pe_vec bfd_powerpc_pe_vec"
+ ;;
+
+ rs6000-*-*)
+ targ_defvec=rs6000coff_vec
+ ;;
+
+ sparc-*-lynxos*)
+ targ_defvec=sparclynx_coff_vec
+ targ_selvecs=sparclynx_aout_vec
+ ;;
+ sparc-*-netbsd*)
+ targ_defvec=sparcnetbsd_vec
+ targ_underscore=yes
+ ;;
+ sparc-*-elf* | sparc-*-sysv4* | sparc-*-solaris2*)
+ targ_defvec=bfd_elf32_sparc_vec
+ targ_selvecs=sunos_big_vec
+ ;;
+ sparc64-*-aout*)
+ targ_defvec=sunos_big_vec
+ targ_underscore=yes
+ ;;
+ sparc64-*-elf*)
+ targ_defvec=bfd_elf64_sparc_vec
+ targ_selvecs=bfd_elf32_sparc_vec
+ ;;
+ sparc64-*-solaris2* | sparc64-*-sysv4*)
+ targ_defvec=bfd_elf32_sparc_vec
+ # Adding 64 bit support by default causes things like objdump to
+ # print addresses as 64 bits.
+ #targ_selvecs=bfd_elf64_sparc_vec
+ ;;
+ sparc-*-netware*)
+ targ_defvec=bfd_elf32_sparc_vec
+ targ_selvecs="nlm32_sparc_vec sunos_big_vec"
+ ;;
+ sparc*-*-coff*)
+ targ_defvec=sparccoff_vec
+ ;;
+ sparc*-*-*)
+ targ_defvec=sunos_big_vec
+ targ_underscore=yes
+ ;;
+
+ tahoe-*-*)
+ targ_defvec=host_aout_vec
+ targ_underscore=yes
+ ;;
+
+ vax-*-vms*)
+ echo 1>&2 "*** BFD does not support target ${targ}."
+ echo 1>&2 "*** Look in bfd/config.bfd for supported targets."
+ exit 1
+ ;;
+ vax-*-*)
+ targ_defvec=host_aout_vec
+ targ_underscore=yes
+ ;;
+
+ we32k-*-*)
+ targ_defvec=we32kcoff_vec
+ ;;
+
+ w65-*-*)
+ targ_defvec=w65_vec
+ ;;
+
+ z8k*-*-*)
+ targ_defvec=z8kcoff_vec
+ targ_underscore=yes
+ ;;
+
+ *-*-ieee*)
+ targ_defvec=ieee_vec
+ ;;
+
+ *-adobe-*)
+ targ_defvec=a_aout_adobe_vec
+ targ_underscore=yes
+ ;;
+
+ *-sony-*)
+ targ_defvec=newsos3_vec
+ targ_underscore=yes
+ ;;
+
+ *-tandem-*)
+ targ_defvec=m68kcoff_vec
+ targ_selvecs=ieee_vec
+ ;;
+
+ *)
+ echo 1>&2 "*** BFD does not support target ${targ}."
+ echo 1>&2 "*** Look in bfd/config.bfd for supported targets."
+ exit 1
+ ;;
+esac
diff --git a/contrib/gdb/bfd/config.in b/contrib/gdb/bfd/config.in
new file mode 100644
index 0000000..dd4f968
--- /dev/null
+++ b/contrib/gdb/bfd/config.in
@@ -0,0 +1,67 @@
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Whether malloc must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_MALLOC
+
+/* Whether free must be declared even if <stdlib.h> is included. */
+#undef NEED_DECLARATION_FREE
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Do we need to use the b modifier when opening binary files? */
+#undef USE_BINARY_FOPEN
+
+/* Name of host specific header file to include in trad-core.c. */
+#undef TRAD_HEADER
+
+/* Define only if <sys/procfs.h> is available *and* it defines prstatus_t. */
+#undef HAVE_SYS_PROCFS_H
+
+/* Do we really want to use mmap if it's available? */
+#undef USE_MMAP
+
+/* Define if you have the fcntl function. */
+#undef HAVE_FCNTL
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the madvise function. */
+#undef HAVE_MADVISE
+
+/* Define if you have the mprotect function. */
+#undef HAVE_MPROTECT
+
+/* Define if you have the valloc function. */
+#undef HAVE_VALLOC
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
diff --git a/contrib/gdb/bfd/configure b/contrib/gdb/bfd/configure
new file mode 100644
index 0000000..5db14db
--- /dev/null
+++ b/contrib/gdb/bfd/configure
@@ -0,0 +1,2439 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.8
+# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-64-bit-bfd 64-bit support (on hosts with narrower word sizes)"
+ac_help="$ac_help
+ --enable-targets alternative target configurations"
+ac_help="$ac_help
+ --enable-shared build shared BFD library"
+ac_help="$ac_help
+ --enable-commonbfdlib build shared BFD/opcodes/libiberty library"
+ac_help="$ac_help
+ --with-mmap try using mmap for BFD input files if available"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.8"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=libbfd.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# Check whether --enable-64-bit-bfd or --disable-64-bit-bfd was given.
+if test "${enable_64_bit_bfd+set}" = set; then
+ enableval="$enable_64_bit_bfd"
+ case "${enableval}" in
+ yes) want64=true ;;
+ no) want64=false ;;
+ *) { echo "configure: error: bad value ${enableval} for 64-bit-bfd option" 1>&2; exit 1; } ;;
+esac
+else
+ want64=false
+fi
+# Check whether --enable-targets or --disable-targets was given.
+if test "${enable_targets+set}" = set; then
+ enableval="$enable_targets"
+ case "${enableval}" in
+ yes | "") { echo "configure: error: enable-targets option must specify target names or 'all'" 1>&2; exit 1; }
+ ;;
+ no) enable_targets= ;;
+ *) enable_targets=$enableval ;;
+esac
+fi
+# Check whether --enable-shared or --disable-shared was given.
+if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ case "${enableval}" in
+ yes) shared=true ;;
+ no) shared=false ;;
+ *) { echo "configure: error: bad value ${enableval} for BFD shared option" 1>&2; exit 1; } ;;
+esac
+fi
+# Check whether --enable-commonbfdlib or --disable-commonbfdlib was given.
+if test "${enable_commonbfdlib+set}" = set; then
+ enableval="$enable_commonbfdlib"
+ case "${enableval}" in
+ yes) commonbfdlib=true ;;
+ no) commonbfdlib=false ;;
+ *) { echo "configure: error: bad value ${enableval} for BFD commonbfdlib option" 1>&2; exit 1; } ;;
+esac
+fi
+# Check whether --with-mmap or --without-mmap was given.
+if test "${with_mmap+set}" = set; then
+ withval="$with_mmap"
+ case "${withval}" in
+ yes) want_mmap=true ;;
+ no) want_mmap=false ;;
+ *) { echo "configure: error: bad value ${withval} for BFD with-mmap option" 1>&2; exit 1; } ;;
+esac
+else
+ want_mmap=false
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir/..;pwd` $srcdir/`cd $srcdir/..;pwd`; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir/..;pwd` $srcdir/`cd $srcdir/..;pwd`" 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`$ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`$ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+if test -z "$target" ; then
+ { echo "configure: error: Unrecognized target system type; please check config.sub." 1>&2; exit 1; }
+fi
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+host64=false
+target64=false
+
+# host stuff:
+
+ALLLIBS='$(TARGETLIB)'
+PICFLAG=
+SHLIB=unused-shlib
+SHLINK=unused-shlink
+if test "${shared}" = "true"; then
+ PICFLAG=-fpic
+ if test "${commonbfdlib}" = "true"; then
+ ALLLIBS='$(TARGETLIB)'
+ else
+ ALLLIBS='$(TARGETLIB) $(SHLIB) $(SHLINK)'
+ SHLIB=libbfd.so.`sed -e 's/[^0-9]*\([0-9.]*\).*/\1/' ${srcdir}/VERSION`
+ SHLINK=libbfd.so
+ fi
+fi
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:814: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ if test "${CFLAGS+set}" != set; then
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_gcc_g=yes
+else
+ ac_cv_prog_gcc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
+ if test $ac_cv_prog_gcc_g = yes; then
+ CFLAGS="-g -O"
+ else
+ CFLAGS="-O"
+ fi
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+
+# Permit host specific settings.
+. ${srcdir}/configure.host
+
+
+if test $host != $build; then
+ ac_tool_prefix=${host_alias}-
+else
+ ac_tool_prefix=
+fi
+
+# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_RANLIB"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ RANLIB=":"
+fi
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+if test "${shared}" = "true"; then
+ if test "${GCC}" != "yes" && test "${shared_non_gcc}" != "yes"; then
+ echo "configure: warning: BFD --enable-shared only supported when using gcc" 1>&2
+ shared=false
+ ALLLIBS='$(TARGETLIB)'
+ PICFLAG=
+ SHLIB=unused-shlib
+ fi
+fi
+
+
+
+
+
+
+if test "${commonbfdlib}" = "true"; then
+ COMMON_SHLIB=yes
+ PICLIST=piclist
+else
+ COMMON_SHLIB=
+ PICLIST=
+fi
+
+
+
+
+HOST_64BIT_LONG=0
+if test "x${HOST_64BIT_TYPE}" = "xlong"; then
+ HOST_64BIT_LONG=1
+fi
+
+
+# If we cannot run a trivial program, we must be cross compiling.
+echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_cross=yes
+else
+cat > conftest.$ac_ext <<EOF
+#line 1056 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+{ (eval echo configure:1060: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_cross=no
+else
+ ac_cv_c_cross=yes
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_cross" 1>&6
+cross_compiling=$ac_cv_c_cross
+
+# Put a plausible default for CC_FOR_BUILD in Makefile.
+if test -z "$CC_FOR_BUILD"; then
+ if test "x$cross_compiling" = "xno"; then
+ CC_FOR_BUILD='$(CC)'
+ else
+ CC_FOR_BUILD=gcc
+ fi
+fi
+
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 1098 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1104: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 1113 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1119: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+for ac_hdr in stddef.h string.h strings.h stdlib.h time.h unistd.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1147 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1152: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in fcntl.h sys/file.h sys/time.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1184 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1189: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1218 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() { return 0; }
+int t() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:1228: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+for ac_func in fcntl getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1254 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+
+case "${host}" in
+i[345]86-*-msdos* | i[345]86-*-go32* | *-*-cygwin32)
+ cat >> confdefs.h <<\EOF
+#define USE_BINARY_FOPEN 1
+EOF
+ ;;
+esac
+
+echo $ac_n "checking whether malloc must be declared""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_malloc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1313 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() { return 0; }
+int t() {
+char *(*pfn) = (char *(*)) malloc
+; return 0; }
+EOF
+if { (eval echo configure:1328: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_decl_needed_malloc=no
+else
+ rm -rf conftest*
+ bfd_cv_decl_needed_malloc=yes
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_malloc" 1>&6
+if test $bfd_cv_decl_needed_malloc = yes; then
+ bfd_tr_decl=NEED_DECLARATION_`echo malloc | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $bfd_tr_decl 1
+EOF
+
+fi
+
+echo $ac_n "checking whether free must be declared""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'bfd_cv_decl_needed_free'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1353 "configure"
+#include "confdefs.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+int main() { return 0; }
+int t() {
+char *(*pfn) = (char *(*)) free
+; return 0; }
+EOF
+if { (eval echo configure:1368: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_decl_needed_free=no
+else
+ rm -rf conftest*
+ bfd_cv_decl_needed_free=yes
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$bfd_cv_decl_needed_free" 1>&6
+if test $bfd_cv_decl_needed_free = yes; then
+ bfd_tr_decl=NEED_DECLARATION_`echo free | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $bfd_tr_decl 1
+EOF
+
+fi
+
+
+# If we are configured native, pick a core file support file.
+COREFILE=
+COREFLAG=
+if test "${target}" = "${host}"; then
+ case "${host}" in
+ alpha*-*-linux*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/alphalinux.h"
+EOF
+
+ ;;
+ alpha*-*-*) COREFILE=osf-core.o ;;
+ arm-*-riscix) COREFILE=trad-core.o ;;
+ hppa*-*-hpux*) COREFILE=hpux-core.o ;;
+ hppa*-*-hiux*) COREFILE=hpux-core.o ;;
+ hppa*-*-bsd*) COREFILE="hpux-core.o hppabsd-core.o"
+ COREFLAG="-DHPUX_CORE -DHPPABSD_CORE" ;;
+ i[345]86-sequent-bsd*)
+ COREFILE=trad-core.o;
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/symmetry.h"
+EOF
+
+ ;;
+ i[345]86-sequent-sysv4*) ;;
+ i[345]86-sequent-sysv*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/symmetry.h"
+EOF
+
+ ;;
+ i[345]86-*-bsd* | i[345]86-*-freebsd*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/i386bsd.h"
+EOF
+
+ ;;
+ i[345]86-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ i[345]86-esix-sysv3*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/esix.h"
+EOF
+
+ ;;
+ i[345]86-*-sco* | i[345]86-*-isc*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/i386sco.h"
+EOF
+
+ ;;
+ i[345]86-*-mach3*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/i386mach3.h"
+EOF
+
+ ;;
+ i[345]86-*-linux*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/i386linux.h"
+EOF
+
+ ;;
+ i[345]86-*-isc*) COREFILE=trad-core.o ;;
+ i[345]86-*-aix*) COREFILE=aix386-core.o ;;
+ i860-*-mach3* | i860-*-osf1*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/i860mach3.h"
+EOF
+
+ ;;
+ mips-dec-bsd*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/mipsbsd.h"
+EOF
+
+ ;;
+ mips-dec-mach3*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/mipsmach3.h"
+EOF
+
+ ;;
+ mips-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ mips-dec-*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/decstation.h"
+EOF
+
+ ;;
+ mips-sgi-irix4*) COREFILE=irix-core.o ;;
+ mips-sgi-irix5*) COREFILE=irix-core.o ;;
+ mips-*-mach3*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/mipsmach3.h"
+EOF
+
+ ;;
+ mips-*-sysv4*) ;;
+ mips-*-sysv* | mips-*-riscos*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/riscos.h"
+EOF
+
+ ;;
+ mips-sony-bsd*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/news-mips.h"
+EOF
+
+ ;;
+ m68*-bull*-sysv*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/dpx2.h"
+EOF
+
+ ;;
+ m68*-hp-hpux*) COREFILE=hpux-core.o ;;
+ m68*-hp-bsd*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/hp300bsd.h"
+EOF
+
+ ;;
+ m68*-*-linux*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/m68klinux.h"
+EOF
+
+ ;;
+ m68*-motorola-sysv*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/delta68.h"
+EOF
+
+ ;;
+ m68*-sony-*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/news.h"
+EOF
+
+ ;;
+ m68*-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ m68*-apple-aux*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/m68kaux.h"
+EOF
+
+ ;;
+ m88*-*-sysv4*) ;;
+ m88*-motorola-sysv*) COREFILE=ptrace-core.o ;;
+ m88*-*-mach3*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/m88kmach3.h"
+EOF
+
+ ;;
+ ns32k-pc532-mach)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/pc532mach.h"
+EOF
+
+ ;;
+ ns32k-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ rs6000-*-lynx*) COREFILE=lynx-core.o ;;
+ rs6000-*-aix4*) COREFILE=rs6000-core.o ;;
+ rs6000-*-*) COREFILE=rs6000-core.o ;;
+ powerpc-*-aix4*) COREFILE=rs6000-core.o ;;
+ powerpc-*-aix*) COREFILE=rs6000-core.o ;;
+ sparc-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ tahoe-*-*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/tahoe.h"
+EOF
+
+ ;;
+ vax-*-ultrix2*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/vaxult2.h"
+EOF
+
+ ;;
+ vax-*-ultrix*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/vaxult2.h"
+EOF
+
+ ;;
+ vax-*-*)
+ COREFILE=trad-core.o
+ cat >> confdefs.h <<\EOF
+#define TRAD_HEADER "hosts/vaxbsd.h"
+EOF
+
+ ;;
+ esac
+
+ case "$COREFILE" in
+ aix386-core.o) COREFLAG=-DAIX386_CORE ;;
+ hppabsd-core.o) COREFLAG=-DHPPABSD_CORE ;;
+ hpux-core.o) COREFLAG=-DHPUX_CORE ;;
+ irix-core.o) COREFLAG=-DIRIX_CORE ;;
+ lynx-core.o) COREFLAG=-DLYNX_CORE ;;
+ osf-core.o) COREFLAG=-DOSF_CORE ;;
+ ptrace-core.o) COREFLAG=-DPTRACE_CORE ;;
+ rs6000-core.o) COREFLAG="$COREFLAG -DAIX_CORE" ;;
+ trad-core.o) COREFLAG="$COREFLAG -DTRAD_CORE" ;;
+ esac
+
+ # The ELF code uses the native <sys/procfs.h> to handle core files.
+ # Define HAVE_SYS_PROCFS_H if the file exists and defines
+ # prstatus_t.
+ echo $ac_n "checking for sys/procfs.h""... $ac_c" 1>&6
+ if eval "test \"`echo '$''{'bfd_cv_header_sys_procfs_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1640 "configure"
+#include "confdefs.h"
+#include <sys/procfs.h>
+int main() { return 0; }
+int t() {
+prstatus_t t;
+; return 0; }
+EOF
+if { (eval echo configure:1648: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ bfd_cv_header_sys_procfs_h=yes
+else
+ rm -rf conftest*
+ bfd_cv_header_sys_procfs_h=no
+fi
+rm -f conftest*
+
+fi
+
+ echo "$ac_t""$bfd_cv_header_sys_procfs_h" 1>&6
+ if test $bfd_cv_header_sys_procfs_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_PROCFS_H 1
+EOF
+
+ fi
+
+fi
+
+
+
+# target stuff:
+
+# Canonicalize the secondary target names.
+if test -n "$enable_targets" ; then
+ for targ in `echo $enable_targets | sed 's/,/ /g'`
+ do
+ result=`$ac_config_sub $targ 2>/dev/null`
+ if test -n "$result" ; then
+ canon_targets="$canon_targets $result"
+ else
+ # Allow targets that config.sub doesn't recognize, like "all".
+ canon_targets="$canon_targets $targ"
+ fi
+ done
+fi
+
+all_targets=false
+defvec=
+selvecs=
+selarchs=
+TDEFINES=
+for targ in $target $canon_targets
+do
+ if test "x$targ" = "xall"; then
+ all_targets=true
+ else
+ . $srcdir/config.bfd
+ if test "x$targ" = "x$target"; then
+ defvec=$targ_defvec
+ fi
+ selvecs="$selvecs $targ_defvec $targ_selvecs"
+ selarchs="$selarchs $targ_archs"
+ TDEFINES="$TDEFINES $targ_cflags"
+ fi
+done
+
+
+# This processing still needs to be done if we're to decide properly whether
+# 64-bit support needs to be compiled in. Currently, it will be included if
+# the default or any other explicitly requested target requires it; it
+# will not be included on a 32-bit host if no 64-bit target is requested, and
+# no "--with-64-bit-bfd" option is given, even if "--with-targets=all" is
+# used.
+
+# uniq the default and selected vectors in all the configured targets.
+f=""
+for i in $selvecs ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+selvecs="$f"
+
+# uniq the architectures in all the configured targets.
+f=""
+for i in $selarchs ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+selarchs="$f"
+
+# Target backend .o files.
+tb=
+
+elf="elf.o elflink.o"
+
+for vec in $selvecs
+do
+ case "$vec" in
+ # This list is alphabetized to make it easy to compare
+ # with the two vector lists in targets.c.
+ a29kcoff_big_vec) tb="$tb coff-a29k.o cofflink.o" ;;
+ a_out_adobe_vec) tb="$tb aout-adobe.o aout32.o" ;;
+ armcoff_little_vec) tb="$tb coff-arm.o cofflink.o " ;;
+ armcoff_big_vec) tb="$tb coff-arm.o cofflink.o " ;;
+ armpe_little_vec) tb="$tb pe-arm.o cofflink.o " ;;
+ armpe_big_vec) tb="$tb pe-arm.o cofflink.o " ;;
+ armpei_little_vec) tb="$tb pei-arm.o cofflink.o " ;;
+ armpei_big_vec) tb="$tb pei-arm.o cofflink.o " ;;
+ aout0_big_vec) tb="$tb aout0.o aout32.o" ;;
+ aout_arm_big_vec) tb="$tb aout-arm.o aout32.o" ;;
+ aout_arm_little_vec) tb="$tb aout-arm.o aout32.o" ;;
+ aout_mips_big_vec) tb="$tb mipsbsd.o aout32.o" ;;
+ aout_mips_little_vec) tb="$tb mipsbsd.o aout32.o" ;;
+ apollocoff_vec) tb="$tb coff-apollo.o" ;;
+ b_out_vec_big_host) tb="$tb bout.o aout32.o" ;;
+ b_out_vec_little_host) tb="$tb bout.o aout32.o" ;;
+ bfd_elf32_big_generic_vec) tb="$tb elf32-gen.o elf32.o $elf" ;;
+ bfd_elf32_bigmips_vec) tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+ bfd_elf32_hppa_vec) tb="$tb elf32-hppa.o elf32.o $elf" ;;
+ bfd_elf32_i386_vec) tb="$tb elf32-i386.o elf32.o $elf" ;;
+ bfd_elf32_i860_vec) tb="$tb elf32-i860.o elf32.o $elf" ;;
+ bfd_elf32_little_generic_vec) tb="$tb elf32-gen.o elf32.o $elf" ;;
+ bfd_elf32_littlemips_vec) tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+ bfd_elf32_m68k_vec) tb="$tb elf32-m68k.o elf32.o $elf" ;;
+ bfd_elf32_m88k_vec) tb="$tb elf32-m88k.o elf32.o $elf" ;;
+ bfd_elf32_powerpc_vec) tb="$tb elf32-ppc.o elf32.o $elf" ;;
+ bfd_elf32_powerpcle_vec) tb="$tb elf32-ppc.o elf32.o $elf" ;;
+ bfd_elf32_sparc_vec) tb="$tb elf32-sparc.o elf32.o $elf" ;;
+ bfd_elf64_big_generic_vec) tb="$tb elf64-gen.o elf64.o $elf"
+ target64=true ;;
+ bfd_elf64_little_generic_vec) tb="$tb elf64-gen.o elf64.o $elf"
+ target64=true ;;
+ bfd_elf64_sparc_vec) tb="$tb elf64-sparc.o elf64.o $elf"
+ target64=true ;;
+ cisco_core_vec) tb="$tb cisco-core.o" ;;
+ demo_64_vec) tb="$tb demo64.o aout64.o"
+ target64=true ;;
+ ecoff_big_vec) tb="$tb coff-mips.o ecoff.o ecofflink.o" ;;
+ ecoff_little_vec) tb="$tb coff-mips.o ecoff.o ecofflink.o" ;;
+ ecoffalpha_little_vec) tb="$tb coff-alpha.o ecoff.o ecofflink.o"
+ target64=true ;;
+ h8300coff_vec) tb="$tb coff-h8300.o reloc16.o" ;;
+ h8500coff_vec) tb="$tb coff-h8500.o reloc16.o" ;;
+ host_aout_vec) tb="$tb host-aout.o aout32.o" ;;
+ hp300bsd_vec) tb="$tb hp300bsd.o aout32.o" ;;
+ hp300hpux_vec) tb="$tb hp300hpux.o aout32.o" ;;
+ i386aout_vec) tb="$tb i386aout.o aout32.o" ;;
+ i386bsd_vec) tb="$tb i386bsd.o aout32.o" ;;
+ i386coff_vec) tb="$tb coff-i386.o cofflink.o" ;;
+ i386dynix_vec) tb="$tb i386dynix.o aout32.o" ;;
+ i386freebsd_vec) tb="$tb i386freebsd.o aout32.o" ;;
+ i386msdos_vec) tb="$tb i386msdos.o" ;;
+ i386pe_vec) tb="$tb pe-i386.o cofflink.o " ;;
+ i386pei_vec) tb="$tb pei-i386.o cofflink.o" ;;
+ i386linux_vec) tb="$tb i386linux.o aout32.o" ;;
+ i386lynx_aout_vec) tb="$tb i386lynx.o lynx-core.o aout32.o" ;;
+ i386lynx_coff_vec) tb="$tb cf-i386lynx.o cofflink.o lynx-core.o" ;;
+ i386mach3_vec) tb="$tb i386mach3.o aout32.o" ;;
+ i386netbsd_vec) tb="$tb i386netbsd.o aout32.o" ;;
+ i386os9k_vec) tb="$tb i386os9k.o aout32.o" ;;
+ i860coff_vec) tb="$tb coff-i860.o cofflink.o" ;;
+ icoff_big_vec) tb="$tb coff-i960.o cofflink.o" ;;
+ icoff_little_vec) tb="$tb coff-i960.o cofflink.o" ;;
+ ieee_vec) tb="$tb ieee.o" ;;
+ m68kcoff_vec) tb="$tb coff-m68k.o cofflink.o" ;;
+ m68kcoffun_vec) tb="$tb coff-u68k.o coff-m68k.o cofflink.o" ;;
+ m68klinux_vec) tb="$tb m68klinux.o aout32.o" ;;
+ m68klynx_aout_vec) tb="$tb m68klynx.o lynx-core.o aout32.o" ;;
+ m68klynx_coff_vec) tb="$tb cf-m68klynx.o coff-m68k.o cofflink.o lynx-core.o" ;;
+ m68knetbsd_vec) tb="$tb m68knetbsd.o aout32.o" ;;
+ m68k4knetbsd_vec) tb="$tb m68k4knetbsd.o aout32.o" ;;
+ m68kaux_coff_vec) tb="$tb coff-aux.o coff-m68k.o cofflink.o" ;;
+ m88kbcs_vec) tb="$tb coff-m88k.o" ;;
+ newsos3_vec) tb="$tb newsos3.o aout32.o" ;;
+ nlm32_i386_vec) tb="$tb nlm32-i386.o nlm32.o nlm.o" ;;
+ nlm32_sparc_vec) tb="$tb nlm32-sparc.o nlm32.o nlm.o" ;;
+ nlm32_alpha_vec) tb="$tb nlm32-alpha.o nlm32.o nlm.o"
+ target64=true ;;
+ riscix_vec) tb="$tb aout32.o riscix.o" ;;
+ nlm32_powerpc_vec) tb="$tb nlm32-ppc.o nlm32.o nlm.o" ;;
+ pc532netbsd_vec) tb="$tb ns32knetbsd.o aout-ns32k.o" ;;
+ pc532machaout_vec) tb="$tb pc532-mach.o aout-ns32k.o" ;;
+ pmac_xcoff_vec) tb="$tb coff-pmac.o xcofflink.o" ;;
+ rs6000coff_vec) tb="$tb coff-rs6000.o xcofflink.o" ;;
+ bfd_powerpc_pe_vec) tb="$tb pe-ppc.o cofflink.o" ;;
+ bfd_powerpcle_pe_vec) tb="$tb pe-ppc.o cofflink.o" ;;
+ bfd_powerpc_pei_vec) tb="$tb pei-ppc.o cofflink.o" ;;
+ bfd_powerpcle_pei_vec) tb="$tb pei-ppc.o cofflink.o" ;;
+ shcoff_vec) tb="$tb coff-sh.o cofflink.o" ;;
+ shlcoff_vec) tb="$tb coff-sh.o cofflink.o" ;;
+ som_vec) tb="$tb som.o" ;;
+ sparclynx_aout_vec) tb="$tb sparclynx.o lynx-core.o aout32.o" ;;
+ sparclynx_coff_vec) tb="$tb cf-sparclynx.o lynx-core.o" ;;
+ sparcnetbsd_vec) tb="$tb sparcnetbsd.o aout32.o" ;;
+ sparccoff_vec) tb="$tb coff-sparc.o" ;;
+ srec_vec) tb="$tb srec.o" ;;
+ sunos_big_vec) tb="$tb sunos.o aout32.o" ;;
+ symbolsrec_vec) tb="$tb srec.o" ;;
+ tekhex_vec) tb="$tb tekhex.o" ;;
+ we32kcoff_vec) tb="$tb coff-we32k.o" ;;
+ z8kcoff_vec) tb="$tb coff-z8k.o reloc16.o" ;;
+ w65_vec) tb="$tb coff-w65.o reloc16.o" ;;
+ versados_vec) tb="$tb versados.o" ;;
+
+ "") ;;
+ *) { echo "configure: error: *** unknown target vector $vec" 1>&2; exit 1; } ;;
+ esac
+done
+
+# Target architecture .o files.
+ta=`echo $selarchs | sed -e s/bfd_/cpu-/g -e s/_arch/.o/g`
+
+# Weed out duplicate .o files.
+f=""
+for i in $tb ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+tb="$f"
+
+f=""
+for i in $ta ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+ta="$f"
+
+bfd_backends="$tb"
+bfd_machines="$ta"
+
+if test x${all_targets} = xtrue ; then
+ bfd_backends="${bfd_backends}"' $(ALL_BACKENDS)'
+ bfd_machines="${bfd_machines}"' $(ALL_MACHINES)'
+ selvecs=
+ selarchs=
+else # all_targets is true
+ # Only set these if they will be nonempty, for the clever echo.
+ test -n "$selvecs" &&
+ selvecs=`echo $selvecs | sed -e 's/^/\&/' -e 's/ \(.\)/,\&\1/g'`
+ test -n "$selarchs" &&
+ selarchs=`echo $selarchs | sed -e 's/^/\&/' -e 's/ \(.\)/,\&\1/g'`
+fi # all_targets is true
+
+case ${host64}-${target64}-${want64} in
+ *true*)
+ wordsize=64
+ all_backends='$(BFD64_BACKENDS) $(BFD32_BACKENDS)'
+ ;;
+ false-false-false)
+ wordsize=32
+ all_backends='$(BFD32_BACKENDS)'
+ ;;
+esac
+
+
+
+
+
+
+tdefaults=""
+test -n "${defvec}" && tdefaults="${tdefaults} -DDEFAULT_VECTOR=${defvec}"
+test -n "${selvecs}" && tdefaults="${tdefaults} -DSELECT_VECS='${selvecs}'"
+test -n "${selarchs}" && tdefaults="${tdefaults} -DSELECT_ARCHITECTURES='${selarchs}'"
+
+
+for ac_func in valloc getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1928 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_mmap'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap=no
+else
+cat > conftest.$ac_ext <<EOF
+#line 1980 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#ifndef HAVE_GETPAGESIZE
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif
+# else
+# ifdef NBPC
+# define getpagesize() NBPC
+# else
+# define getpagesize() PAGESIZE /* SVR4 */
+# endif
+# endif
+# endif
+#endif
+
+#ifndef HAVE_VALLOC
+# define valloc malloc
+#endif
+
+#ifdef __cplusplus
+extern "C" { void *valloc(unsigned), *malloc(unsigned); }
+#else
+char *valloc(), *malloc();
+#endif
+
+int
+main()
+{
+ char *buf1, *buf2, *buf3;
+ int i = getpagesize(), j;
+ int i2 = i * 2;
+ int fd;
+
+ buf1 = (char *)valloc(i2);
+ buf2 = (char *)valloc(i);
+ buf3 = (char *)malloc(i2);
+ for (j = 0; j < i2; ++j)
+ *(buf1 + j) = rand();
+ fd = open("conftestmmap", O_CREAT | O_RDWR, 0666);
+ write(fd, buf1, i2);
+ mmap(buf2, i, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, fd, 0);
+ for (j = 0; j < i; ++j)
+ if (*(buf1 + j) != *(buf2 + j))
+ exit(1);
+ lseek(fd, (long)i, 0);
+ read(fd, buf2, i); /* read into mapped memory -- file should not change */
+ /* (it does in i386 SVR4.0 - Jim Avera, jima@netcom.com) */
+ lseek(fd, (long)0, 0);
+ read(fd, buf3, i2);
+ for (j = 0; j < i2; ++j)
+ if (*(buf1 + j) != *(buf3 + j))
+ exit(1);
+ exit(0);
+}
+
+EOF
+{ (eval echo configure:2049: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_func_mmap=yes
+else
+ ac_cv_func_mmap=no
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_mmap" 1>&6
+if test $ac_cv_func_mmap = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+for ac_func in madvise mprotect
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2074 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2096: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+case ${want_mmap}+${ac_cv_func_mmap} in
+ true+yes ) cat >> confdefs.h <<\EOF
+#define USE_MMAP 1
+EOF
+ ;;
+esac
+
+rm -f doc/config.status
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+ >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.8"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile doc/Makefile config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@CC@%$CC%g
+s%@HDEFINES@%$HDEFINES%g
+s%@AR@%$AR%g
+s%@RANLIB@%$RANLIB%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@ALLLIBS@%$ALLLIBS%g
+s%@PICFLAG@%$PICFLAG%g
+s%@SHLIB@%$SHLIB%g
+s%@SHLIB_CC@%$SHLIB_CC%g
+s%@SHLIB_CFLAGS@%$SHLIB_CFLAGS%g
+s%@COMMON_SHLIB@%$COMMON_SHLIB%g
+s%@PICLIST@%$PICLIST%g
+s%@SHLINK@%$SHLINK%g
+s%@HOST_64BIT_LONG@%$HOST_64BIT_LONG%g
+s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g
+s%@CPP@%$CPP%g
+s%@COREFILE@%$COREFILE%g
+s%@COREFLAG@%$COREFLAG%g
+s%@TDEFINES@%$TDEFINES%g
+s%@wordsize@%$wordsize%g
+s%@all_backends@%$all_backends%g
+s%@bfd_backends@%$bfd_backends%g
+s%@bfd_machines@%$bfd_machines%g
+s%@tdefaults@%$tdefaults%g
+
+CEOF
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile doc/Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust relative srcdir, etc. for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+fi; done
+rm -f conftest.subs
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+CONFIG_HEADERS=${CONFIG_HEADERS-"config.h:config.in"}
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ cp $ac_given_srcdir/$ac_file_in conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+# Maximum number of lines to put in a single here document.
+ac_max_here_lines=12
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+
+case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/contrib/gdb/bfd/configure.bat b/contrib/gdb/bfd/configure.bat
new file mode 100644
index 0000000..78fe79e
--- /dev/null
+++ b/contrib/gdb/bfd/configure.bat
@@ -0,0 +1,18 @@
+@echo off
+if "%1" == "h8/300" goto h8300
+
+echo Configuring bfd for go32
+update hosts\go32.h sysdep.h
+update Makefile.dos Makefile
+echo s/@WORDSIZE@/32/g>config.sed
+sed -e s/^/s\/@VERSION@\// -e s/$/\/g/g version >>config.sed
+sed -f config.sed < bfd-in2.h > bfd.h2
+update bfd.h2 bfd.h
+goto exit
+
+:h8300
+echo Configuring bfd for H8/300
+update hosts\h-go32.h sysdep.h
+update Makefile.dos Makefile
+
+:exit
diff --git a/contrib/gdb/bfd/configure.host b/contrib/gdb/bfd/configure.host
new file mode 100644
index 0000000..484e5bd
--- /dev/null
+++ b/contrib/gdb/bfd/configure.host
@@ -0,0 +1,128 @@
+# This file is a shell script that overrides some of the tools and
+# flags used on a host specific basis.
+
+# Since the "bfd/hosts" directory is shared by the bfd, opcodes, and
+# binutils directories (at least), the index to it is also shared.
+# This is that index. Each configure.in file should source this file
+# in its per-host part.
+
+# This sets the following shell variables:
+# HDEFINES host specific compiler options
+# host64 set to true if this is a 64 bit host
+# HOST_64BIT_TYPE host 64 bit type
+# SHLIB_CC compiler to use when building shared library
+# SHLIB_CFLAGS flags to use when building shared library
+# PICFLAG may be set to flag to use to compile PIC
+# SHLINK may be set to the name to link the shared library to
+# ALLLIBS may be set to libraries to build
+# HLDFLAGS LDFLAGS specific to the host
+# RPATH_ENVVAR environment variable used to find shared libraries
+
+HDEFINES=
+host64=false
+HOST_64BIT_TYPE=
+
+case "${host}" in
+
+alpha-*-*) host64=true; HOST_64BIT_TYPE=long ;;
+
+hppa*-*-hpux*) HDEFINES=-DHOST_HPPAHPUX ;;
+hppa*-*-hiux*) HDEFINES=-DHOST_HPPAHPUX ;;
+hppa*-*-bsd*) HDEFINES=-DHOST_HPPABSD ;;
+hppa*-*-osf*) HDEFINES=-DHOST_HPPAOSF ;;
+
+i[345]86-sequent-bsd*) HDEFINES=-Dshared=genshared ;;
+i[345]86-sequent-sysv4*) ;;
+i[345]86-sequent-sysv*) HDEFINES=-Dshared=genshared ;;
+
+mips-dec-netbsd*) ;;
+mips-dec-*) HDEFINES="-G 4" ;;
+mips-sgi-irix3*) HDEFINES="-G 4" ;;
+mips-sgi-irix4*) HDEFINES="-G 4" ;;
+mips-*-sysv4*) ;;
+mips-*-sysv*) HDEFINES="-G 4" ;;
+mips-*-riscos*) HDEFINES="-G 4" ;;
+
+m68*-hp-hpux*) HDEFINES=-DHOST_HP300HPUX ;;
+
+esac
+
+# If we are configuring with --enable-shared, adjust the shared
+# library support based on the host. This support must work for both
+# the BFD and the opcodes libraries.
+HLDFLAGS=
+RPATH_ENVVAR=LD_LIBRARY_PATH
+SHLIB_CC='$(CC)'
+SHLIB_CFLAGS='-shared'
+if [ "${shared}" = "true" ]; then
+ case "${host}" in
+ hppa*-*-*) picfrag=../config/mh-papic ;;
+ i[3456]86-*-*) picfrag=../config/mh-x86pic ;;
+ *-*-*) picfrag=../config/mh-${host_cpu}pic ;;
+ esac
+ if [ -f "${picfrag}" ]; then
+ pic=`sed -n -e 's/^PICFLAG[ ]*=[ ]*\(.*\)$/\1/p' ${picfrag}`
+ if [ -n "${pic}" ]; then
+ PICFLAG=${pic}
+ fi
+ fi
+
+ case "${host}" in
+ *-dec-osf*)
+ # -fpic is not needed on the Alpha.
+ PICFLAG=
+ ;;
+ *-*-hpux*)
+ # HP/UX uses .sl for shared libraries.
+ SHLINK=`echo ${SHLINK} | sed -e 's/so$/sl/'`
+ SHLIB_CFLAGS='-shared $(PICFLAG)'
+ HLDFLAGS='-Wl,+s,+b,$(libdir)'
+ RPATH_ENVVAR=SHLIB_PATH
+ ;;
+ *-*-irix5*)
+ # -fpic is not needed on Irix 5.
+ PICFLAG=
+ SHLIB_CFLAGS='-shared -Wl,-soname,$(SONAME)'
+ HLDFLAGS='-Wl,-rpath,$(libdir)'
+ ;;
+ *-*-linux*aout*)
+ ;;
+ *-*-linux*)
+ SHLIB_CFLAGS='-shared -Wl,-soname,$(SONAME)'
+ case "$(libdir)" in
+ /lib | /usr/lib) ;;
+ *) HLDFLAGS='-Wl,-rpath,$(libdir)' ;;
+ esac
+ ;;
+ *-*-sysv4* | *-*-solaris*)
+ SHLIB_CFLAGS='-shared -h $(SONAME)'
+ HLDFLAGS='-R $(libdir)'
+ ;;
+ *-*-sunos*)
+ # Build a libTARGET-bfd.so.VERSION symlink in the object directory.
+ ALLLIBS=`echo ${ALLLIBS} | sed -e 's/\$(SHLINK)/stamp-tshlink/'`
+ ;;
+ esac
+fi
+
+# On SunOS, if the linker supports the -rpath option, use it to
+# prevent ../bfd and ../opcodes from being included in the run time
+# search path.
+case "${host}" in
+ *-*-sunos*)
+ echo 'main () { }' > conftest.c
+ ${CC} -o conftest -Wl,-rpath= conftest.c >/dev/null 2>conftest.t
+ if grep 'unrecognized' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'No such file' conftest.t >/dev/null 2>&1; then
+ :
+ elif grep 'do not mix' conftest.t >/dev/null 2>&1; then
+ :
+ elif [ "${shared}" = "true" ]; then
+ HLDFLAGS='-Wl,-rpath=$(libdir)'
+ else
+ HLDFLAGS='-Wl,-rpath='
+ fi
+ rm -f conftest.t conftest.c conftest
+ ;;
+esac
diff --git a/contrib/gdb/bfd/configure.in b/contrib/gdb/bfd/configure.in
new file mode 100644
index 0000000..c8b8de5
--- /dev/null
+++ b/contrib/gdb/bfd/configure.in
@@ -0,0 +1,577 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl
+AC_PREREQ(2.3)
+AC_INIT(libbfd.c)
+
+AC_ARG_ENABLE(64-bit-bfd,
+[ --enable-64-bit-bfd 64-bit support (on hosts with narrower word sizes)],
+[case "${enableval}" in
+ yes) want64=true ;;
+ no) want64=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for 64-bit-bfd option) ;;
+esac],[want64=false])dnl
+AC_ARG_ENABLE(targets,
+[ --enable-targets alternative target configurations],
+[case "${enableval}" in
+ yes | "") AC_ERROR(enable-targets option must specify target names or 'all')
+ ;;
+ no) enable_targets= ;;
+ *) enable_targets=$enableval ;;
+esac])dnl
+AC_ARG_ENABLE(shared,
+[ --enable-shared build shared BFD library],
+[case "${enableval}" in
+ yes) shared=true ;;
+ no) shared=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for BFD shared option]) ;;
+esac])dnl
+AC_ARG_ENABLE(commonbfdlib,
+[ --enable-commonbfdlib build shared BFD/opcodes/libiberty library],
+[case "${enableval}" in
+ yes) commonbfdlib=true ;;
+ no) commonbfdlib=false ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for BFD commonbfdlib option]) ;;
+esac])dnl
+AC_ARG_WITH(mmap,
+[ --with-mmap try using mmap for BFD input files if available],
+[case "${withval}" in
+ yes) want_mmap=true ;;
+ no) want_mmap=false ;;
+ *) AC_MSG_ERROR(bad value ${withval} for BFD with-mmap option) ;;
+esac],[want_mmap=false])dnl
+
+AC_CONFIG_HEADER(config.h:config.in)
+
+AC_CONFIG_AUX_DIR(`cd $srcdir/..;pwd`)
+AC_CANONICAL_SYSTEM
+if test -z "$target" ; then
+ AC_MSG_ERROR(Unrecognized target system type; please check config.sub.)
+fi
+AC_ARG_PROGRAM
+
+host64=false
+target64=false
+
+# host stuff:
+
+ALLLIBS='$(TARGETLIB)'
+PICFLAG=
+SHLIB=unused-shlib
+SHLINK=unused-shlink
+if test "${shared}" = "true"; then
+ PICFLAG=-fpic
+ if test "${commonbfdlib}" = "true"; then
+ ALLLIBS='$(TARGETLIB)'
+ else
+ ALLLIBS='$(TARGETLIB) $(SHLIB) $(SHLINK)'
+changequote(,)dnl
+ SHLIB=libbfd.so.`sed -e 's/[^0-9]*\([0-9.]*\).*/\1/' ${srcdir}/VERSION`
+changequote([,])dnl
+ SHLINK=libbfd.so
+ fi
+fi
+
+AC_PROG_CC
+
+# Permit host specific settings.
+. ${srcdir}/configure.host
+
+AC_SUBST(HDEFINES)
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_PROG_INSTALL
+
+if test "${shared}" = "true"; then
+ if test "${GCC}" != "yes" && test "${shared_non_gcc}" != "yes"; then
+ AC_MSG_WARN([BFD --enable-shared only supported when using gcc])
+ shared=false
+ ALLLIBS='$(TARGETLIB)'
+ PICFLAG=
+ SHLIB=unused-shlib
+ fi
+fi
+
+AC_SUBST(ALLLIBS)
+AC_SUBST(PICFLAG)
+AC_SUBST(SHLIB)
+AC_SUBST(SHLIB_CC)
+AC_SUBST(SHLIB_CFLAGS)
+if test "${commonbfdlib}" = "true"; then
+ COMMON_SHLIB=yes
+ PICLIST=piclist
+else
+ COMMON_SHLIB=
+ PICLIST=
+fi
+AC_SUBST(COMMON_SHLIB)
+AC_SUBST(PICLIST)
+AC_SUBST(SHLINK)
+
+HOST_64BIT_LONG=0
+if test "x${HOST_64BIT_TYPE}" = "xlong"; then
+ HOST_64BIT_LONG=1
+fi
+AC_SUBST(HOST_64BIT_LONG)
+
+BFD_CC_FOR_BUILD
+
+AC_CHECK_HEADERS(stddef.h string.h strings.h stdlib.h time.h unistd.h)
+AC_CHECK_HEADERS(fcntl.h sys/file.h sys/time.h)
+AC_HEADER_TIME
+AC_CHECK_FUNCS(fcntl getpagesize)
+
+BFD_BINARY_FOPEN
+
+BFD_NEED_DECLARATION(malloc)
+BFD_NEED_DECLARATION(free)
+
+# If we are configured native, pick a core file support file.
+COREFILE=
+COREFLAG=
+if test "${target}" = "${host}"; then
+ case "${host}" in
+ alpha*-*-linux*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/alphalinux.h")
+ ;;
+ alpha*-*-*) COREFILE=osf-core.o ;;
+ arm-*-riscix) COREFILE=trad-core.o ;;
+ hppa*-*-hpux*) COREFILE=hpux-core.o ;;
+ hppa*-*-hiux*) COREFILE=hpux-core.o ;;
+ hppa*-*-bsd*) COREFILE="hpux-core.o hppabsd-core.o"
+ COREFLAG="-DHPUX_CORE -DHPPABSD_CORE" ;;
+changequote(,)dnl
+ i[345]86-sequent-bsd*)
+changequote([,])dnl
+ COREFILE=trad-core.o;
+ AC_DEFINE(TRAD_HEADER,"hosts/symmetry.h")
+ ;;
+changequote(,)dnl
+ i[345]86-sequent-sysv4*) ;;
+ i[345]86-sequent-sysv*)
+changequote([,])dnl
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/symmetry.h")
+ ;;
+changequote(,)dnl
+ i[345]86-*-bsd* | i[345]86-*-freebsd*)
+changequote([,])dnl
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/i386bsd.h")
+ ;;
+changequote(,)dnl
+ i[345]86-*-netbsd*)
+changequote([,])dnl
+ COREFILE=netbsd-core.o
+ ;;
+changequote(,)dnl
+ i[345]86-esix-sysv3*)
+changequote([,])dnl
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/esix.h")
+ ;;
+changequote(,)dnl
+ i[345]86-*-sco* | i[345]86-*-isc*)
+changequote([,])dnl
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/i386sco.h")
+ ;;
+changequote(,)dnl
+ i[345]86-*-mach3*)
+changequote([,])dnl
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/i386mach3.h")
+ ;;
+changequote(,)dnl
+ i[345]86-*-linux*)
+changequote([,])dnl
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/i386linux.h")
+ ;;
+changequote(,)dnl
+ i[345]86-*-isc*) COREFILE=trad-core.o ;;
+ i[345]86-*-aix*) COREFILE=aix386-core.o ;;
+changequote([,])dnl
+ i860-*-mach3* | i860-*-osf1*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/i860mach3.h")
+ ;;
+ mips-dec-bsd*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/mipsbsd.h")
+ ;;
+ mips-dec-mach3*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/mipsmach3.h")
+ ;;
+ mips-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ mips-dec-*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/decstation.h")
+ ;;
+ mips-sgi-irix4*) COREFILE=irix-core.o ;;
+ mips-sgi-irix5*) COREFILE=irix-core.o ;;
+ mips-*-mach3*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/mipsmach3.h")
+ ;;
+ mips-*-sysv4*) ;;
+ mips-*-sysv* | mips-*-riscos*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/riscos.h")
+ ;;
+ mips-sony-bsd*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/news-mips.h")
+ ;;
+ m68*-bull*-sysv*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/dpx2.h")
+ ;;
+ m68*-hp-hpux*) COREFILE=hpux-core.o ;;
+ m68*-hp-bsd*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/hp300bsd.h")
+ ;;
+ m68*-*-linux*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/m68klinux.h")
+ ;;
+ m68*-motorola-sysv*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER, "hosts/delta68.h")
+ ;;
+ m68*-sony-*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/news.h")
+ ;;
+ m68*-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ m68*-apple-aux*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/m68kaux.h")
+ ;;
+ m88*-*-sysv4*) ;;
+ m88*-motorola-sysv*) COREFILE=ptrace-core.o ;;
+ m88*-*-mach3*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/m88kmach3.h")
+ ;;
+ ns32k-pc532-mach)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/pc532mach.h")
+ ;;
+ ns32k-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ rs6000-*-lynx*) COREFILE=lynx-core.o ;;
+ rs6000-*-aix4*) COREFILE=rs6000-core.o ;;
+ rs6000-*-*) COREFILE=rs6000-core.o ;;
+ powerpc-*-aix4*) COREFILE=rs6000-core.o ;;
+ powerpc-*-aix*) COREFILE=rs6000-core.o ;;
+ sparc-*-netbsd*)
+ COREFILE=netbsd-core.o
+ ;;
+ tahoe-*-*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/tahoe.h")
+ ;;
+ vax-*-ultrix2*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/vaxult2.h")
+ ;;
+ vax-*-ultrix*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/vaxult2.h")
+ ;;
+ vax-*-*)
+ COREFILE=trad-core.o
+ AC_DEFINE(TRAD_HEADER,"hosts/vaxbsd.h")
+ ;;
+ esac
+
+ case "$COREFILE" in
+ aix386-core.o) COREFLAG=-DAIX386_CORE ;;
+ hppabsd-core.o) COREFLAG=-DHPPABSD_CORE ;;
+ hpux-core.o) COREFLAG=-DHPUX_CORE ;;
+ irix-core.o) COREFLAG=-DIRIX_CORE ;;
+ lynx-core.o) COREFLAG=-DLYNX_CORE ;;
+ osf-core.o) COREFLAG=-DOSF_CORE ;;
+ ptrace-core.o) COREFLAG=-DPTRACE_CORE ;;
+ rs6000-core.o) COREFLAG="$COREFLAG -DAIX_CORE" ;;
+ trad-core.o) COREFLAG="$COREFLAG -DTRAD_CORE" ;;
+ esac
+
+ # The ELF code uses the native <sys/procfs.h> to handle core files.
+ # Define HAVE_SYS_PROCFS_H if the file exists and defines
+ # prstatus_t.
+ AC_MSG_CHECKING([for sys/procfs.h])
+ AC_CACHE_VAL(bfd_cv_header_sys_procfs_h,
+ [AC_TRY_COMPILE([#include <sys/procfs.h>],
+ [prstatus_t t;],
+ bfd_cv_header_sys_procfs_h=yes, bfd_cv_header_sys_procfs_h=no)])
+ AC_MSG_RESULT($bfd_cv_header_sys_procfs_h)
+ if test $bfd_cv_header_sys_procfs_h = yes; then
+ AC_DEFINE(HAVE_SYS_PROCFS_H)
+ fi
+
+fi
+AC_SUBST(COREFILE)
+AC_SUBST(COREFLAG)
+
+# target stuff:
+
+# Canonicalize the secondary target names.
+if test -n "$enable_targets" ; then
+ for targ in `echo $enable_targets | sed 's/,/ /g'`
+ do
+ result=`$ac_config_sub $targ 2>/dev/null`
+ if test -n "$result" ; then
+ canon_targets="$canon_targets $result"
+ else
+ # Allow targets that config.sub doesn't recognize, like "all".
+ canon_targets="$canon_targets $targ"
+ fi
+ done
+fi
+
+all_targets=false
+defvec=
+selvecs=
+selarchs=
+TDEFINES=
+for targ in $target $canon_targets
+do
+ if test "x$targ" = "xall"; then
+ all_targets=true
+ else
+ . $srcdir/config.bfd
+ if test "x$targ" = "x$target"; then
+ defvec=$targ_defvec
+ fi
+ selvecs="$selvecs $targ_defvec $targ_selvecs"
+ selarchs="$selarchs $targ_archs"
+ TDEFINES="$TDEFINES $targ_cflags"
+ fi
+done
+AC_SUBST(TDEFINES)
+
+# This processing still needs to be done if we're to decide properly whether
+# 64-bit support needs to be compiled in. Currently, it will be included if
+# the default or any other explicitly requested target requires it; it
+# will not be included on a 32-bit host if no 64-bit target is requested, and
+# no "--with-64-bit-bfd" option is given, even if "--with-targets=all" is
+# used.
+
+# uniq the default and selected vectors in all the configured targets.
+f=""
+for i in $selvecs ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+selvecs="$f"
+
+# uniq the architectures in all the configured targets.
+f=""
+for i in $selarchs ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+selarchs="$f"
+
+# Target backend .o files.
+tb=
+
+elf="elf.o elflink.o"
+
+for vec in $selvecs
+do
+ case "$vec" in
+ # This list is alphabetized to make it easy to compare
+ # with the two vector lists in targets.c.
+ a29kcoff_big_vec) tb="$tb coff-a29k.o cofflink.o" ;;
+ a_out_adobe_vec) tb="$tb aout-adobe.o aout32.o" ;;
+ armcoff_little_vec) tb="$tb coff-arm.o cofflink.o " ;;
+ armcoff_big_vec) tb="$tb coff-arm.o cofflink.o " ;;
+ armpe_little_vec) tb="$tb pe-arm.o cofflink.o " ;;
+ armpe_big_vec) tb="$tb pe-arm.o cofflink.o " ;;
+ armpei_little_vec) tb="$tb pei-arm.o cofflink.o " ;;
+ armpei_big_vec) tb="$tb pei-arm.o cofflink.o " ;;
+ aout0_big_vec) tb="$tb aout0.o aout32.o" ;;
+ aout_arm_big_vec) tb="$tb aout-arm.o aout32.o" ;;
+ aout_arm_little_vec) tb="$tb aout-arm.o aout32.o" ;;
+ aout_mips_big_vec) tb="$tb mipsbsd.o aout32.o" ;;
+ aout_mips_little_vec) tb="$tb mipsbsd.o aout32.o" ;;
+ apollocoff_vec) tb="$tb coff-apollo.o" ;;
+ b_out_vec_big_host) tb="$tb bout.o aout32.o" ;;
+ b_out_vec_little_host) tb="$tb bout.o aout32.o" ;;
+ bfd_elf32_big_generic_vec) tb="$tb elf32-gen.o elf32.o $elf" ;;
+ bfd_elf32_bigmips_vec) tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+ bfd_elf32_hppa_vec) tb="$tb elf32-hppa.o elf32.o $elf" ;;
+ bfd_elf32_i386_vec) tb="$tb elf32-i386.o elf32.o $elf" ;;
+ bfd_elf32_i860_vec) tb="$tb elf32-i860.o elf32.o $elf" ;;
+ bfd_elf32_little_generic_vec) tb="$tb elf32-gen.o elf32.o $elf" ;;
+ bfd_elf32_littlemips_vec) tb="$tb elf32-mips.o elf32.o $elf ecofflink.o" ;;
+ bfd_elf32_m68k_vec) tb="$tb elf32-m68k.o elf32.o $elf" ;;
+ bfd_elf32_m88k_vec) tb="$tb elf32-m88k.o elf32.o $elf" ;;
+ bfd_elf32_powerpc_vec) tb="$tb elf32-ppc.o elf32.o $elf" ;;
+ bfd_elf32_powerpcle_vec) tb="$tb elf32-ppc.o elf32.o $elf" ;;
+ bfd_elf32_sparc_vec) tb="$tb elf32-sparc.o elf32.o $elf" ;;
+ bfd_elf64_big_generic_vec) tb="$tb elf64-gen.o elf64.o $elf"
+ target64=true ;;
+ bfd_elf64_little_generic_vec) tb="$tb elf64-gen.o elf64.o $elf"
+ target64=true ;;
+ bfd_elf64_sparc_vec) tb="$tb elf64-sparc.o elf64.o $elf"
+ target64=true ;;
+ cisco_core_vec) tb="$tb cisco-core.o" ;;
+ demo_64_vec) tb="$tb demo64.o aout64.o"
+ target64=true ;;
+ ecoff_big_vec) tb="$tb coff-mips.o ecoff.o ecofflink.o" ;;
+ ecoff_little_vec) tb="$tb coff-mips.o ecoff.o ecofflink.o" ;;
+ ecoffalpha_little_vec) tb="$tb coff-alpha.o ecoff.o ecofflink.o"
+ target64=true ;;
+ h8300coff_vec) tb="$tb coff-h8300.o reloc16.o" ;;
+ h8500coff_vec) tb="$tb coff-h8500.o reloc16.o" ;;
+ host_aout_vec) tb="$tb host-aout.o aout32.o" ;;
+ hp300bsd_vec) tb="$tb hp300bsd.o aout32.o" ;;
+ hp300hpux_vec) tb="$tb hp300hpux.o aout32.o" ;;
+ i386aout_vec) tb="$tb i386aout.o aout32.o" ;;
+ i386bsd_vec) tb="$tb i386bsd.o aout32.o" ;;
+ i386coff_vec) tb="$tb coff-i386.o cofflink.o" ;;
+ i386dynix_vec) tb="$tb i386dynix.o aout32.o" ;;
+ i386freebsd_vec) tb="$tb i386freebsd.o aout32.o" ;;
+ i386msdos_vec) tb="$tb i386msdos.o" ;;
+ i386pe_vec) tb="$tb pe-i386.o cofflink.o " ;;
+ i386pei_vec) tb="$tb pei-i386.o cofflink.o" ;;
+ i386linux_vec) tb="$tb i386linux.o aout32.o" ;;
+ i386lynx_aout_vec) tb="$tb i386lynx.o lynx-core.o aout32.o" ;;
+ i386lynx_coff_vec) tb="$tb cf-i386lynx.o cofflink.o lynx-core.o" ;;
+ i386mach3_vec) tb="$tb i386mach3.o aout32.o" ;;
+ i386netbsd_vec) tb="$tb i386netbsd.o aout32.o" ;;
+ i386os9k_vec) tb="$tb i386os9k.o aout32.o" ;;
+ i860coff_vec) tb="$tb coff-i860.o cofflink.o" ;;
+ icoff_big_vec) tb="$tb coff-i960.o cofflink.o" ;;
+ icoff_little_vec) tb="$tb coff-i960.o cofflink.o" ;;
+ ieee_vec) tb="$tb ieee.o" ;;
+ m68kcoff_vec) tb="$tb coff-m68k.o cofflink.o" ;;
+ m68kcoffun_vec) tb="$tb coff-u68k.o coff-m68k.o cofflink.o" ;;
+ m68klinux_vec) tb="$tb m68klinux.o aout32.o" ;;
+ m68klynx_aout_vec) tb="$tb m68klynx.o lynx-core.o aout32.o" ;;
+ m68klynx_coff_vec) tb="$tb cf-m68klynx.o coff-m68k.o cofflink.o lynx-core.o" ;;
+ m68knetbsd_vec) tb="$tb m68knetbsd.o aout32.o" ;;
+ m68k4knetbsd_vec) tb="$tb m68k4knetbsd.o aout32.o" ;;
+ m68kaux_coff_vec) tb="$tb coff-aux.o coff-m68k.o cofflink.o" ;;
+ m88kbcs_vec) tb="$tb coff-m88k.o" ;;
+ newsos3_vec) tb="$tb newsos3.o aout32.o" ;;
+ nlm32_i386_vec) tb="$tb nlm32-i386.o nlm32.o nlm.o" ;;
+ nlm32_sparc_vec) tb="$tb nlm32-sparc.o nlm32.o nlm.o" ;;
+ nlm32_alpha_vec) tb="$tb nlm32-alpha.o nlm32.o nlm.o"
+ target64=true ;;
+ riscix_vec) tb="$tb aout32.o riscix.o" ;;
+ nlm32_powerpc_vec) tb="$tb nlm32-ppc.o nlm32.o nlm.o" ;;
+ pc532netbsd_vec) tb="$tb ns32knetbsd.o aout-ns32k.o" ;;
+ pc532machaout_vec) tb="$tb pc532-mach.o aout-ns32k.o" ;;
+ pmac_xcoff_vec) tb="$tb coff-pmac.o xcofflink.o" ;;
+ rs6000coff_vec) tb="$tb coff-rs6000.o xcofflink.o" ;;
+ bfd_powerpc_pe_vec) tb="$tb pe-ppc.o cofflink.o" ;;
+ bfd_powerpcle_pe_vec) tb="$tb pe-ppc.o cofflink.o" ;;
+ bfd_powerpc_pei_vec) tb="$tb pei-ppc.o cofflink.o" ;;
+ bfd_powerpcle_pei_vec) tb="$tb pei-ppc.o cofflink.o" ;;
+ shcoff_vec) tb="$tb coff-sh.o cofflink.o" ;;
+ shlcoff_vec) tb="$tb coff-sh.o cofflink.o" ;;
+ som_vec) tb="$tb som.o" ;;
+ sparclynx_aout_vec) tb="$tb sparclynx.o lynx-core.o aout32.o" ;;
+ sparclynx_coff_vec) tb="$tb cf-sparclynx.o lynx-core.o" ;;
+ sparcnetbsd_vec) tb="$tb sparcnetbsd.o aout32.o" ;;
+ sparccoff_vec) tb="$tb coff-sparc.o" ;;
+ srec_vec) tb="$tb srec.o" ;;
+ sunos_big_vec) tb="$tb sunos.o aout32.o" ;;
+ symbolsrec_vec) tb="$tb srec.o" ;;
+ tekhex_vec) tb="$tb tekhex.o" ;;
+ we32kcoff_vec) tb="$tb coff-we32k.o" ;;
+ z8kcoff_vec) tb="$tb coff-z8k.o reloc16.o" ;;
+ w65_vec) tb="$tb coff-w65.o reloc16.o" ;;
+ versados_vec) tb="$tb versados.o" ;;
+
+ "") ;;
+ *) AC_MSG_ERROR(*** unknown target vector $vec) ;;
+ esac
+done
+
+# Target architecture .o files.
+ta=`echo $selarchs | sed -e s/bfd_/cpu-/g -e s/_arch/.o/g`
+
+# Weed out duplicate .o files.
+f=""
+for i in $tb ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+tb="$f"
+
+f=""
+for i in $ta ; do
+ case " $f " in
+ *" $i "*) ;;
+ *) f="$f $i" ;;
+ esac
+done
+ta="$f"
+
+bfd_backends="$tb"
+bfd_machines="$ta"
+
+if test x${all_targets} = xtrue ; then
+ bfd_backends="${bfd_backends}"' $(ALL_BACKENDS)'
+ bfd_machines="${bfd_machines}"' $(ALL_MACHINES)'
+ selvecs=
+ selarchs=
+else # all_targets is true
+ # Only set these if they will be nonempty, for the clever echo.
+ test -n "$selvecs" &&
+ selvecs=`echo $selvecs | sed -e 's/^/\&/' -e 's/ \(.\)/,\&\1/g'`
+ test -n "$selarchs" &&
+ selarchs=`echo $selarchs | sed -e 's/^/\&/' -e 's/ \(.\)/,\&\1/g'`
+fi # all_targets is true
+
+case ${host64}-${target64}-${want64} in
+ *true*)
+ wordsize=64
+ all_backends='$(BFD64_BACKENDS) $(BFD32_BACKENDS)'
+ ;;
+ false-false-false)
+ wordsize=32
+ all_backends='$(BFD32_BACKENDS)'
+ ;;
+esac
+
+AC_SUBST(wordsize)
+AC_SUBST(all_backends)
+AC_SUBST(bfd_backends)
+AC_SUBST(bfd_machines)
+
+tdefaults=""
+test -n "${defvec}" && tdefaults="${tdefaults} -DDEFAULT_VECTOR=${defvec}"
+test -n "${selvecs}" && tdefaults="${tdefaults} -DSELECT_VECS='${selvecs}'"
+test -n "${selarchs}" && tdefaults="${tdefaults} -DSELECT_ARCHITECTURES='${selarchs}'"
+AC_SUBST(tdefaults)
+
+dnl AC_CHECK_HEADERS(sys/mman.h)
+AC_FUNC_MMAP
+AC_CHECK_FUNCS(madvise mprotect)
+case ${want_mmap}+${ac_cv_func_mmap} in
+ true+yes ) AC_DEFINE(USE_MMAP) ;;
+esac
+
+rm -f doc/config.status
+AC_OUTPUT(Makefile doc/Makefile,
+[case x$CONFIG_HEADERS in xconfig.h:config.in) echo > stamp-h ;; esac])
diff --git a/contrib/gdb/bfd/corefile.c b/contrib/gdb/bfd/corefile.c
new file mode 100644
index 0000000..212f519
--- /dev/null
+++ b/contrib/gdb/bfd/corefile.c
@@ -0,0 +1,106 @@
+/* Core file generic interface routines for BFD.
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ Core files
+
+DESCRIPTION
+ These are functions pertaining to core files.
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+/*
+FUNCTION
+ bfd_core_file_failing_command
+
+SYNOPSIS
+ CONST char *bfd_core_file_failing_command(bfd *abfd);
+
+DESCRIPTION
+ Return a read-only string explaining which program was running
+ when it failed and produced the core file @var{abfd}.
+
+*/
+
+CONST char *
+bfd_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ if (abfd->format != bfd_core) {
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+ return BFD_SEND (abfd, _core_file_failing_command, (abfd));
+}
+
+/*
+FUNCTION
+ bfd_core_file_failing_signal
+
+SYNOPSIS
+ int bfd_core_file_failing_signal(bfd *abfd);
+
+DESCRIPTION
+ Returns the signal number which caused the core dump which
+ generated the file the BFD @var{abfd} is attached to.
+*/
+
+int
+bfd_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ if (abfd->format != bfd_core) {
+ bfd_set_error (bfd_error_invalid_operation);
+ return 0;
+ }
+ return BFD_SEND (abfd, _core_file_failing_signal, (abfd));
+}
+
+
+/*
+FUNCTION
+ core_file_matches_executable_p
+
+SYNOPSIS
+ boolean core_file_matches_executable_p
+ (bfd *core_bfd, bfd *exec_bfd);
+
+DESCRIPTION
+ Return <<true>> if the core file attached to @var{core_bfd}
+ was generated by a run of the executable file attached to
+ @var{exec_bfd}, <<false>> 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_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
+ return BFD_SEND (core_bfd, _core_file_matches_executable_p,
+ (core_bfd, exec_bfd));
+}
diff --git a/contrib/gdb/bfd/cpu-a29k.c b/contrib/gdb/bfd/cpu-a29k.c
new file mode 100644
index 0000000..5bd25a4
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-a29k.c
@@ -0,0 +1,39 @@
+/* BFD support for the AMD 29000 architecture.
+ Copyright 1992 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_a29k_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_a29k,
+ 0, /* only 1 machine */
+ "a29k",
+ "a29k",
+ 4,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-alpha.c b/contrib/gdb/bfd/cpu-alpha.c
new file mode 100644
index 0000000..0d66a8b
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-alpha.c
@@ -0,0 +1,38 @@
+/* BFD support for the Alpha architecture.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_alpha_arch =
+ {
+ 64, /* 32 bits in a word */
+ 64, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_alpha,
+ 0, /* only 1 machine */
+ "alpha",
+ "alpha",
+ 3,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-arm.c b/contrib/gdb/bfd/cpu-arm.c
new file mode 100644
index 0000000..92103e6
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-arm.c
@@ -0,0 +1,39 @@
+/* BFD support for the ARM processor
+ Copyright 1994 Free Software Foundation, Inc.
+ Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_arm_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_arm,
+ 0, /* only 1 machine */
+ "arm",
+ "arm",
+ 4,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-h8300.c b/contrib/gdb/bfd/cpu-h8300.c
new file mode 100644
index 0000000..380dfb5
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-h8300.c
@@ -0,0 +1,246 @@
+/* BFD library support routines for the Hitachi H8/300 architecture.
+ Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#if 0 /* not used currently */
+/*
+Relocations for the H8
+
+*/
+static bfd_reloc_status_type
+howto16_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd * abfd;
+ arelent * reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection * ignore_input_section;
+ bfd * ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
+
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_16 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+
+static bfd_reloc_status_type
+howto8_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd * abfd;
+ arelent * reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection * ignore_input_section;
+ bfd * ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
+
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+
+static bfd_reloc_status_type
+howto8_FFnn_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd * abfd;
+ arelent * reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection * ignore_input_section;
+ bfd * ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+
+ long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
+ abort ();
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+howto8_pcrel_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd * abfd;
+ arelent * reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection * ignore_input_section;
+ bfd * ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
+ abort ();
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+static reloc_howto_type howto_16
+= NEWHOWTO (howto16_callback, "abs16", 1, false, false);
+static reloc_howto_type howto_8
+= NEWHOWTO (howto8_callback, "abs8", 0, false, false);
+
+static reloc_howto_type howto_8_FFnn
+= NEWHOWTO (howto8_FFnn_callback, "ff00+abs8", 0, false, false);
+
+static reloc_howto_type howto_8_pcrel
+= NEWHOWTO (howto8_pcrel_callback, "pcrel8", 0, false, true);
+
+static reloc_howto_type *
+local_bfd_reloc_type_lookup (arch, code)
+ const struct bfd_arch_info *arch;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ case BFD_RELOC_16:
+ return &howto_16;
+ case BFD_RELOC_8_FFnn:
+ return &howto_8_FFnn;
+ case BFD_RELOC_8:
+ return &howto_8;
+ case BFD_RELOC_8_PCREL:
+ return &howto_8_pcrel;
+ default:
+ return (reloc_howto_type *) NULL;
+ }
+ }
+#endif
+
+int bfd_default_scan_num_mach ();
+
+static boolean
+h8300_scan (info, string)
+ const struct bfd_arch_info *info;
+ const char *string;
+{
+ if (*string != 'h' && *string != 'H')
+ return false;
+
+ string++;
+ if (*string != '8')
+ return false;
+
+ string++;
+ if (*string == '/')
+ string++;
+
+ if (*string != '3')
+ return false;
+ string++;
+ if (*string != '0')
+ return false;
+ string++;
+ if (*string != '0')
+ return false;
+ string++;
+ if (*string == '-')
+ string++;
+ if (*string == 'h' || *string == 'H')
+ {
+ return (info->mach == bfd_mach_h8300h);
+ }
+ else
+ {
+ return info->mach == bfd_mach_h8300;
+ }
+}
+
+
+/* This routine is provided two arch_infos and works out the
+ machine which would be compatible with both and returns a pointer
+ to its info structure */
+
+static const bfd_arch_info_type *
+compatible (in, out)
+ const bfd_arch_info_type * in;
+ const bfd_arch_info_type * out;
+{
+ /* If the output is non-H and the input is -H, that's bad */
+ if (in->mach == bfd_mach_h8300h &&
+ out->mach == bfd_mach_h8300)
+ return 0;
+
+ /* If either is an -H, the answer is -H */
+ if (in->mach == bfd_mach_h8300h)
+ return in;
+ return out;
+}
+
+static const bfd_arch_info_type h8300_info_struct =
+{
+ 16, /* 16 bits in a word */
+ 16, /* 16 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_h8300,
+ bfd_mach_h8300,
+ "h8300", /* arch_name */
+ "h8300", /* printable name */
+ 1,
+ true, /* the default machine */
+ compatible,
+ h8300_scan,
+/* local_bfd_reloc_type_lookup, */
+ 0,
+};
+
+
+const bfd_arch_info_type bfd_h8300_arch =
+{
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_h8300,
+ bfd_mach_h8300h,
+ "h8300h", /* arch_name */
+ "h8300h", /* printable name */
+ 1,
+ false, /* the default machine */
+ compatible,
+ h8300_scan,
+/* local_bfd_reloc_type_lookup, */
+ &h8300_info_struct,
+};
diff --git a/contrib/gdb/bfd/cpu-h8500.c b/contrib/gdb/bfd/cpu-h8500.c
new file mode 100644
index 0000000..e4abfd1
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-h8500.c
@@ -0,0 +1,199 @@
+/* BFD library support routines for the H8/500 architecture.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#if 0
+
+/*
+Relocations for the Z8K
+
+*/
+static bfd_reloc_status_type
+howto16_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_16(abfd, (bfd_byte *)data + addr);
+
+ HOWTO_PREPARE(relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_16(abfd, x, (bfd_byte *)data + addr);
+ return bfd_reloc_ok;
+}
+
+
+static bfd_reloc_status_type
+howto8_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_8(abfd, (bfd_byte *)data + addr);
+
+ HOWTO_PREPARE(relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8(abfd, x, (bfd_byte *)data + addr);
+ return bfd_reloc_ok;
+}
+
+
+static bfd_reloc_status_type
+howto8_FFnn_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+
+ long x = bfd_get_8(abfd, (bfd_byte *)data + addr);
+ abort();
+ HOWTO_PREPARE(relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8(abfd, x, (bfd_byte *)data + addr);
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+howto8_pcrel_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_8(abfd, (bfd_byte *)data + addr);
+ abort();
+ HOWTO_PREPARE(relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8(abfd, x, (bfd_byte *)data + addr);
+ return bfd_reloc_ok;
+}
+
+
+
+static reloc_howto_type howto_16
+ = NEWHOWTO(howto16_callback,"abs16",1,false,false);
+static reloc_howto_type howto_8
+ = NEWHOWTO(howto8_callback,"abs8",0,false,false);
+
+static reloc_howto_type howto_8_FFnn
+ = NEWHOWTO(howto8_FFnn_callback,"ff00+abs8",0,false,false);
+
+static reloc_howto_type howto_8_pcrel
+ = NEWHOWTO(howto8_pcrel_callback,"pcrel8",0,false,true);
+
+
+static reloc_howto_type *
+local_bfd_reloc_type_lookup (arch, code)
+ const struct bfd_arch_info *arch;
+ bfd_reloc_code_real_type code;
+{
+ switch (code) {
+ case BFD_RELOC_16:
+ return &howto_16;
+ case BFD_RELOC_8_FFnn:
+ return &howto_8_FFnn;
+ case BFD_RELOC_8:
+ return &howto_8;
+ case BFD_RELOC_8_PCREL:
+ return &howto_8_pcrel;
+ }
+ return (reloc_howto_type *)NULL;
+}
+#endif
+
+int bfd_default_scan_num_mach();
+
+static boolean
+scan_mach (info, string)
+ const struct bfd_arch_info *info;
+ const char *string;
+{
+ if (strcmp(string,"h8/500") == 0) return true;
+ if (strcmp(string,"H8/500") == 0) return true;
+ if (strcmp(string,"h8500") == 0) return true;
+ if (strcmp(string,"H8500") == 0) return true;
+ return false;
+}
+
+
+#if 0 /* not used currently */
+/* This routine is provided two arch_infos and returns whether
+ they'd be compatible */
+
+static const bfd_arch_info_type *
+compatible (a,b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+ if (a->arch != b->arch || a->mach != b->mach)
+ return NULL;
+ return a;
+}
+#endif
+
+const bfd_arch_info_type bfd_h8500_arch =
+{
+ 16, /* 16 bits in a word */
+ 24, /* 24 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_h8500,
+ 0, /* only 1 machine */
+ "h8500", /* arch_name */
+ "h8500", /* printable name */
+ 1,
+ true, /* the default machine */
+ bfd_default_compatible,
+ scan_mach,
+ 0,
+};
diff --git a/contrib/gdb/bfd/cpu-hppa.c b/contrib/gdb/bfd/cpu-hppa.c
new file mode 100644
index 0000000..5201008
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-hppa.c
@@ -0,0 +1,54 @@
+/* BFD support for the HP Precision Architecture architecture.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+static const bfd_arch_info_type bfd_hppa10_arch =
+{
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_hppa,
+ 10, /* By convention PA1.0 = 10 */
+ "hppa",
+ "hppa1.0",
+ 3,
+ true, /* Unless we use 1.1 specific features */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+};
+
+const bfd_arch_info_type bfd_hppa_arch =
+{
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_hppa,
+ 11, /* By convention PA1.1 = 11 */
+ "hppa",
+ "hppa1.1",
+ 3,
+ false, /* 1.1 specific features used */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ &bfd_hppa10_arch,
+};
diff --git a/contrib/gdb/bfd/cpu-i386.c b/contrib/gdb/bfd/cpu-i386.c
new file mode 100644
index 0000000..4041090
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-i386.c
@@ -0,0 +1,38 @@
+/* BFD support for the Intel 386 architecture.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_i386_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_i386,
+ 0, /* only 1 machine */
+ "i386",
+ "i386",
+ 3,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-i860.c b/contrib/gdb/bfd/cpu-i860.c
new file mode 100644
index 0000000..57c867c
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-i860.c
@@ -0,0 +1,40 @@
+/* BFD support for the Intel 860 architecture.
+ Copyright 1992, 1995 Free Software Foundation, Inc.
+ Created mostly by substituting "860" for "386" in cpu-i386.c
+ Harry Dolan <dolan@ssd.intel.com>, October 1995
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_i860_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_i860,
+ 0, /* only 1 machine */
+ "i860",
+ "i860",
+ 3,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-i960.c b/contrib/gdb/bfd/cpu-i960.c
new file mode 100644
index 0000000..6970f89
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-i960.c
@@ -0,0 +1,162 @@
+/* BFD library support routines for the i960 architecture.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+/* This routine is provided a string, and tries to work out if it
+ could possibly refer to the i960 machine pointed at in the
+ info_struct pointer */
+
+static boolean
+scan_960_mach (ap, string)
+ const bfd_arch_info_type *ap;
+ const char *string;
+{
+ unsigned long machine;
+
+ /* Look for the string i960, or somesuch at the front of the string */
+
+ if (strncmp("i960",string,4) == 0) {
+ string+=4;
+ }
+ else {
+ /* no match, can be us */
+ return false;
+ }
+ if (string[0] == 0) {
+ /* i960 on it's own means core to us*/
+ if (ap->mach == bfd_mach_i960_core) return true;
+ return false;
+ }
+
+ if (string[0] != ':') {
+ return false;
+ }
+ string++;
+ if (string[0] == '\0')
+ return false;
+ if (string[0] == 'c' && string[1] == 'o' && string[2] == 'r' &&
+ string[3] == 'e' && string[4] == '\0')
+ machine = bfd_mach_i960_core;
+ else if (string[1] == '\0' || string[2] != '\0') /* rest are 2-char */
+ return false;
+ else if (string[0] == 'k' && string[1] == 'b')
+ machine = bfd_mach_i960_kb_sb;
+ else if (string[0] == 's' && string[1] == 'b')
+ machine = bfd_mach_i960_kb_sb;
+ else if (string[0] == 'm' && string[1] == 'c')
+ machine = bfd_mach_i960_mc;
+ else if (string[0] == 'x' && string[1] == 'a')
+ machine = bfd_mach_i960_xa;
+ else if (string[0] == 'c' && string[1] == 'a')
+ machine = bfd_mach_i960_ca;
+ else if (string[0] == 'k' && string[1] == 'a')
+ machine = bfd_mach_i960_ka_sa;
+ else if (string[0] == 's' && string[1] == 'a')
+ machine = bfd_mach_i960_ka_sa;
+ else if (string[0] == 'j' && string[1] == 'x')
+ machine = bfd_mach_i960_jx;
+ else if (string[0] == 'h' && string[1] == 'x')
+ machine = bfd_mach_i960_hx;
+ else
+ return false;
+ if (machine == ap->mach) return true;
+ return false;
+}
+
+
+
+/* This routine is provided two arch_infos and works out the i960
+ machine which would be compatible with both and returns a pointer
+ to its info structure */
+
+static const bfd_arch_info_type *
+compatible (a,b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+
+ /* The i960 has distinct subspecies which may not interbreed:
+ CORE CA
+ CORE KA KB MC XA
+ CORE HX JX
+ Any architecture on the same line is compatible, the one on
+ the right is the least restrictive.
+
+ We represent this information in an array, each machine to a side */
+
+#define ERROR 0
+#define CORE bfd_mach_i960_core /*1*/
+#define KA bfd_mach_i960_ka_sa /*2*/
+#define KB bfd_mach_i960_kb_sb /*3*/
+#define MC bfd_mach_i960_mc /*4*/
+#define XA bfd_mach_i960_xa /*5*/
+#define CA bfd_mach_i960_ca /*6*/
+#define JX bfd_mach_i960_jx /*7*/
+#define HX bfd_mach_i960_hx /*8*/
+#define MAX_ARCH ((int)HX)
+
+ static CONST unsigned long matrix[MAX_ARCH+1][MAX_ARCH+1] =
+ {
+ { ERROR, CORE, KA, KB, MC, XA, CA, JX, HX },
+ { CORE, CORE, KA, KB, MC, XA, CA, JX, HX },
+ { KA, KA, KA, KB, MC, XA, ERROR, ERROR, ERROR},
+ { KB, KB, KB, KB, MC, XA, ERROR, ERROR, ERROR},
+ { MC, MC, MC, MC, MC, XA, ERROR, ERROR, ERROR},
+ { XA, XA, XA, XA, XA, XA, ERROR, ERROR, ERROR},
+ { CA, CA, ERROR, ERROR, ERROR, ERROR, CA, ERROR, ERROR},
+ { JX, JX, ERROR, ERROR, ERROR, ERROR, ERROR, JX, HX },
+ { HX, HX, ERROR, ERROR, ERROR, ERROR, ERROR, HX, HX },
+ };
+
+
+ if (a->arch != b->arch || matrix[a->mach][b->mach] == ERROR)
+ {
+ return NULL;
+ }
+ else
+ {
+ return (a->mach == matrix[a->mach][b->mach]) ? a : b;
+ }
+}
+
+
+
+int bfd_default_scan_num_mach();
+#define N(a,b,d,n) \
+{ 32, 32, 8,bfd_arch_i960,a,"i960",b,3,d,compatible,scan_960_mach,n,}
+
+static const bfd_arch_info_type arch_info_struct[] =
+{
+ N(bfd_mach_i960_ka_sa,"i960:ka_sa",false, &arch_info_struct[1]),
+ N(bfd_mach_i960_kb_sb,"i960:kb_sb",false, &arch_info_struct[2]),
+ N(bfd_mach_i960_mc, "i960:mc", false, &arch_info_struct[3]),
+ N(bfd_mach_i960_xa, "i960:xa", false, &arch_info_struct[4]),
+ N(bfd_mach_i960_ca, "i960:ca", false, &arch_info_struct[5]),
+ N(bfd_mach_i960_jx, "i960:jx", false, &arch_info_struct[6]),
+ N(bfd_mach_i960_hx, "i960:hx", false, 0),
+};
+
+const bfd_arch_info_type bfd_i960_arch =
+ N(bfd_mach_i960_core, "i960:core", true, &arch_info_struct[0]);
diff --git a/contrib/gdb/bfd/cpu-m68k.c b/contrib/gdb/bfd/cpu-m68k.c
new file mode 100644
index 0000000..17a3739
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-m68k.c
@@ -0,0 +1,42 @@
+/* BFD library support routines for architectures.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+int bfd_default_scan_num_mach();
+
+
+#define N(name, print,d,next) \
+{ 32, 32, 8, bfd_arch_m68k, name, "m68k",print,2,d,bfd_default_compatible,bfd_default_scan, next, }
+
+static const bfd_arch_info_type arch_info_struct[] =
+{
+ N(68008,"m68k:68008",false, &arch_info_struct[1]),
+ N(68010,"m68k:68010",false, &arch_info_struct[2]),
+ N(68020,"m68k:68020",true, &arch_info_struct[3]),
+ N(68030,"m68k:68030",false, &arch_info_struct[4]),
+ N(68040,"m68k:68040",false, &arch_info_struct[5]),
+ N(68070,"m68k:68070",false, 0),
+};
+
+const bfd_arch_info_type bfd_m68k_arch =
+ N(68000,"m68k:68000",false, &arch_info_struct[0]);
diff --git a/contrib/gdb/bfd/cpu-m88k.c b/contrib/gdb/bfd/cpu-m88k.c
new file mode 100644
index 0000000..c3716c5
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-m88k.c
@@ -0,0 +1,42 @@
+/* bfd back-end for m88k support
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+
+
+const bfd_arch_info_type bfd_m88k_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_m88k,
+ 88100, /* only 1 machine */
+ "m88k",
+ "m88k:88100",
+ 3,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-mips.c b/contrib/gdb/bfd/cpu-mips.c
new file mode 100644
index 0000000..5e19342
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-mips.c
@@ -0,0 +1,85 @@
+/* bfd back-end for mips support
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+static const bfd_arch_info_type arch_info_struct[] =
+{
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_mips,
+ 6000,
+ "mips",
+ "mips:6000",
+ 3,
+ false,
+ bfd_default_compatible,
+ bfd_default_scan,
+ &arch_info_struct[1],
+ },
+ {
+ 64, /* 64 bits in a word */
+ 64, /* 64 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_mips,
+ 4000,
+ "mips",
+ "mips:4000",
+ 3,
+ false,
+ bfd_default_compatible,
+ bfd_default_scan ,
+ &arch_info_struct[2],
+ },
+ {
+ 64, /* 64 bits in a word */
+ 64, /* 64 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_mips,
+ 8000,
+ "mips",
+ "mips:8000",
+ 3,
+ false,
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ }
+};
+
+const bfd_arch_info_type bfd_mips_arch =
+{
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_mips,
+ 3000,
+ "mips",
+ "mips:3000",
+ 3,
+ true,
+ bfd_default_compatible,
+ bfd_default_scan,
+ &arch_info_struct[0],
+};
diff --git a/contrib/gdb/bfd/cpu-ns32k.c b/contrib/gdb/bfd/cpu-ns32k.c
new file mode 100644
index 0000000..e18e3cf
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-ns32k.c
@@ -0,0 +1,868 @@
+/* BFD support for the ns32k architecture.
+ Copyright (C) 1990, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Almost totally rewritten by Ian Dall from initial work
+ by Andrew Cagney.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+long ns32k_get_displacement PARAMS ((bfd_byte *buffer, long offset, long size));
+int ns32k_put_displacement PARAMS ((long value, bfd_byte *buffer, long offset, long size));
+long ns32k_get_immediate PARAMS ((bfd_byte *buffer, long offset, long size));
+int ns32k_put_immediate PARAMS ((long value, bfd_byte *buffer, long offset, long size));
+bfd_reloc_status_type
+ ns32k_reloc_disp PARAMS ((bfd *abfd, arelent *reloc_entry,
+ struct symbol_cache_entry *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+bfd_reloc_status_type
+ ns32k_reloc_imm PARAMS ((bfd *abfd,
+ arelent *reloc_entry,
+ struct symbol_cache_entry *symbol,
+ PTR data,
+ asection *input_section,
+ bfd *output_bfd,
+ char **error_message));
+bfd_reloc_status_type ns32k_final_link_relocate PARAMS ((reloc_howto_type *howto,
+ bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ bfd_vma address,
+ bfd_vma value,
+ bfd_vma addend ));
+bfd_reloc_status_type ns32k_relocate_contents PARAMS ((reloc_howto_type *howto,
+ bfd *input_bfd,
+ bfd_vma relocation,
+ bfd_byte *location));
+
+int bfd_default_scan_num_mach();
+
+#define N(machine, printable, d, next) \
+{ 32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d,bfd_default_compatible,bfd_default_scan, next, }
+
+static const bfd_arch_info_type arch_info_struct[] =
+{
+ N(32532,"ns32k:32532",true, 0), /* the word ns32k will match this too */
+};
+
+const bfd_arch_info_type bfd_ns32k_arch =
+ N(32032,"ns32k:32032",false, &arch_info_struct[0]);
+
+static long
+ns32k_sign_extend(value, bits)
+ int value;
+ int bits;
+{
+ value = value & ((1 << bits) - 1);
+ return (value & (1 << (bits-1))
+ ? value | (~((1 << bits) - 1))
+ : value);
+}
+
+long
+ns32k_get_displacement(buffer, offset, size)
+ bfd_byte *buffer;
+ long offset;
+ long size;
+{
+ long value;
+ buffer += offset;
+ switch (size)
+ {
+ case 1:
+ value = ns32k_sign_extend (*buffer, 7);
+ break;
+ case 2:
+ value = ns32k_sign_extend(*buffer++, 6);
+ value = (value << 8) | (0xff & *buffer);
+ break;
+ case 4:
+ value = ns32k_sign_extend(*buffer++, 6);
+ value = (value << 8) | (0xff & *buffer++);
+ value = (value << 8) | (0xff & *buffer++);
+ value = (value << 8) | (0xff & *buffer);
+ break;
+ }
+ return value;
+}
+
+int
+ns32k_put_displacement(value, buffer, offset, size)
+ long value;
+ bfd_byte *buffer;
+ long offset;
+ long size;
+{
+ buffer += offset;
+ switch (size)
+ {
+ case 1:
+ if (value < -64 || value > 63)
+ return -1;
+ value&=0x7f;
+ *buffer++=value;
+ break;
+ case 2:
+ if (value < -8192 || value > 8191)
+ return -1;
+ value&=0x3fff;
+ value|=0x8000;
+ *buffer++=(value>>8);
+ *buffer++=value;
+ break;
+ case 4:
+ if (value < -0x1f000000 || value >= 0x20000000)
+ return -1;
+ value|=0xc0000000;
+ *buffer++=(value>>24);
+ *buffer++=(value>>16);
+ *buffer++=(value>>8);
+ *buffer++=value;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+long
+ns32k_get_immediate(buffer, offset, size)
+ bfd_byte *buffer;
+ long offset;
+ long size;
+{
+ long value = 0;
+ buffer += offset;
+ switch (size)
+ {
+ case 4:
+ value = (value << 8) | (*buffer++ & 0xff);
+ case 3:
+ value = (value << 8) | (*buffer++ & 0xff);
+ case 2:
+ value = (value << 8) | (*buffer++ & 0xff);
+ case 1:
+ value = (value << 8) | (*buffer++ & 0xff);
+ }
+ return value;
+}
+
+int
+ns32k_put_immediate (value, buffer, offset, size)
+ long value;
+ bfd_byte *buffer;
+ long offset;
+ long size;
+{
+ buffer += offset + size - 1;
+ switch (size)
+ {
+ case 4:
+ *buffer-- = (value & 0xff); value >>= 8;
+ case 3:
+ *buffer-- = (value & 0xff); value >>= 8;
+ case 2:
+ *buffer-- = (value & 0xff); value >>= 8;
+ case 1:
+ *buffer-- = (value & 0xff); value >>= 8;
+ }
+ return 0;
+}
+
+/* This is just like the standard perform_relocation except we
+ * use get_data and put_data which know about the ns32k
+ * storage methods.
+ * This is probably a lot more complicated than it needs to be!
+ */
+static bfd_reloc_status_type
+do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
+ error_message, get_data, put_data)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+ long (*get_data)();
+ int (*put_data)();
+{
+ int overflow = 0;
+ bfd_vma relocation;
+ bfd_reloc_status_type flag = bfd_reloc_ok;
+ bfd_size_type addr = reloc_entry->address;
+ bfd_vma output_base = 0;
+ reloc_howto_type *howto = reloc_entry->howto;
+ asection *reloc_target_output_section;
+
+ if ((symbol->section == &bfd_abs_section)
+ && output_bfd != (bfd *) NULL)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* 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
+ && (symbol->flags & BSF_WEAK) == 0
+ && output_bfd == (bfd *) NULL)
+ flag = bfd_reloc_undefined;
+
+
+ /* Is the address of the relocation really within the section? */
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Work out which section the relocation is targetted at and the
+ initial relocation command value. */
+
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+
+ reloc_target_output_section = symbol->section->output_section;
+
+ /* Convert input-section-relative symbol value to absolute. */
+ if (output_bfd && howto->partial_inplace == false)
+ output_base = 0;
+ else
+ output_base = reloc_target_output_section->vma;
+
+ relocation += output_base + symbol->section->output_offset;
+
+ /* Add in supplied addend. */
+ relocation += reloc_entry->addend;
+
+ /* Here the variable relocation holds the final address of the
+ symbol we are relocating against, plus any addend. */
+
+ if (howto->pc_relative == true)
+ {
+ /* This is a PC relative relocation. We want to set RELOCATION
+ to the distance between the address of the symbol and the
+ location. RELOCATION is already the address of the symbol.
+
+ We start by subtracting the address of the section containing
+ the location.
+
+ If pcrel_offset is set, we must further subtract the position
+ of the location within the section. Some targets arrange for
+ the addend to be the negative of the position of the location
+ within the section; for example, i386-aout does this. For
+ i386-aout, pcrel_offset is false. Some other targets do not
+ include the position of the location; for example, m88kbcs,
+ or ELF. For those targets, pcrel_offset is true.
+
+ If we are producing relocateable output, then we must ensure
+ that this reloc will be correctly computed when the final
+ relocation is done. If pcrel_offset is false we want to wind
+ up with the negative of the location within the section,
+ which means we must adjust the existing addend by the change
+ in the location within the section. If pcrel_offset is true
+ we do not want to adjust the existing addend at all.
+
+ FIXME: This seems logical to me, but for the case of
+ producing relocateable output it is not what the code
+ actually does. I don't want to change it, because it seems
+ far too likely that something will break. */
+
+ 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 (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;
+ return flag;
+ }
+ else
+ {
+ /* This is a partial relocation, but inplace, so modify the
+ 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. */
+
+ reloc_entry->address += input_section->output_offset;
+
+ /* WTF?? */
+ if (abfd->xvec->flavour == bfd_target_coff_flavour
+ && strcmp (abfd->xvec->name, "aixcoff-rs6000") != 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
+ {
+ reloc_entry->addend = relocation;
+ }
+ }
+ }
+ else
+ {
+ reloc_entry->addend = 0;
+ }
+
+ /* FIXME: This overflow checking is incomplete, because the value
+ might have overflowed before we get here. For a correct check we
+ need to compute the value in a size larger than bitsize, but we
+ can't reasonably do that for a reloc the same size as a host
+ machine word.
+ FIXME: We should also do overflow checking on the result after
+ adding in the value contained in the object file. */
+ if (howto->complain_on_overflow != complain_overflow_dont)
+ {
+ bfd_vma check;
+
+ /* Get the value that will be used for the relocation, but
+ starting at bit position zero. */
+ if (howto->rightshift > howto->bitpos)
+ check = relocation >> (howto->rightshift - howto->bitpos);
+ else
+ check = relocation << (howto->bitpos - howto->rightshift);
+ 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;
+
+ /* 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
+ >> (howto->rightshift - howto->bitpos)));
+ if ((bfd_signed_vma) check > reloc_signed_max
+ || (bfd_signed_vma) check < reloc_signed_min)
+ flag = bfd_reloc_overflow;
+ }
+ 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 ((bfd_vma) check > reloc_unsigned_max)
+ flag = bfd_reloc_overflow;
+ }
+ 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 (((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
+ overflow. */
+ if (howto->rightshift > howto->bitpos
+ && (bfd_signed_vma) relocation < 0)
+ {
+ check |= ((bfd_vma) - 1
+ & ~((bfd_vma) - 1
+ >> (howto->rightshift - howto->bitpos)));
+ if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
+ flag = bfd_reloc_overflow;
+ }
+ else
+ flag = bfd_reloc_overflow;
+ }
+ }
+ break;
+ default:
+ 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)
+ */
+
+ /* 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 <<= (bfd_vma) howto->bitpos;
+
+ /* Wait for the day when all have the mask in them */
+
+ /* What we do:
+ i instruction to be left alone
+ o offset within instruction
+ r relocation offset to apply
+ S src mask
+ D dst mask
+ N ~dst mask
+ A part 1
+ B part 2
+ R result
+
+ Do this:
+ i i i i i o o o o o from bfd_get<size>
+ 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
+ And this:
+ ... i i i i i o o o o o from bfd_get<size>
+ 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
+ -----------------------
+ R R R R R R R R R R put into bfd_put<size>
+ */
+
+#define DOIT(x) \
+ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = get_data (data, addr, 1);
+ DOIT (x);
+ overflow = put_data(x, data, addr, 1);
+ }
+ break;
+
+ case 1:
+ if (relocation)
+ {
+ short x = get_data (data, addr, 2);
+ DOIT (x);
+ overflow = put_data(x, (unsigned char *) data, addr, 2);
+ }
+ break;
+ case 2:
+ if (relocation)
+ {
+ long x = get_data (data, addr, 4);
+ DOIT (x);
+ overflow = put_data(x, data, addr, 4);
+ }
+ break;
+ case -2:
+ {
+ long x = get_data(data, addr, 4);
+ relocation = -relocation;
+ DOIT(x);
+ overflow = put_data(x, data , addr, 4);
+ }
+ break;
+
+ case 3:
+ /* Do nothing */
+ break;
+
+ case 4:
+#ifdef BFD64
+ if (relocation)
+ {
+ bfd_vma x = get_data (data, addr, 8);
+ DOIT (x);
+ overflow = put_data(x, data, addr, 8);
+ }
+#else
+ abort ();
+#endif
+ break;
+ default:
+ return bfd_reloc_other;
+ }
+ if ((howto->complain_on_overflow != complain_overflow_dont) && overflow)
+ return bfd_reloc_overflow;
+
+ return flag;
+}
+
+/* Relocate a given location using a given value and howto. */
+
+bfd_reloc_status_type
+do_ns32k_reloc_contents ( howto, input_bfd, relocation, location, get_data,
+ put_data)
+ reloc_howto_type *howto;
+ bfd *input_bfd;
+ bfd_vma relocation;
+ bfd_byte *location;
+ long (*get_data)();
+ int (*put_data)();
+{
+ 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:
+ case 2:
+ case 4:
+#ifdef BFD64
+ case 8:
+#endif
+ x = get_data (location, 0, size);
+ 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:
+ case 2:
+ case 4:
+#ifdef BFD64
+ case 8:
+#endif
+ put_data(x, location, 0, size);
+ break;
+ }
+
+ return overflow ? bfd_reloc_overflow : bfd_reloc_ok;
+}
+
+bfd_reloc_status_type
+ns32k_reloc_disp(abfd, reloc_entry, symbol, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ return do_ns32k_reloc(abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message, ns32k_get_displacement, ns32k_put_displacement);
+}
+
+bfd_reloc_status_type
+ns32k_reloc_imm (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ return do_ns32k_reloc(abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message, ns32k_get_immediate, ns32k_put_immediate);
+}
+
+bfd_reloc_status_type
+ns32k_final_link_relocate (howto, input_bfd, input_section, contents, address, value, addend )
+ 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 ns32k_relocate_contents (howto, input_bfd, relocation,
+ contents + address);
+}
diff --git a/contrib/gdb/bfd/cpu-powerpc.c b/contrib/gdb/bfd/cpu-powerpc.c
new file mode 100644
index 0000000..11f0f80
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-powerpc.c
@@ -0,0 +1,124 @@
+/* BFD PowerPC CPU definition
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* The common PowerPC architecture is compatible with the RS/6000. */
+
+static const bfd_arch_info_type *powerpc_compatible
+ PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
+
+static const bfd_arch_info_type *
+powerpc_compatible (a,b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+ BFD_ASSERT (a->arch == bfd_arch_powerpc);
+ switch (b->arch)
+ {
+ default:
+ return NULL;
+ case bfd_arch_powerpc:
+ return bfd_default_compatible (a, b);
+ case bfd_arch_rs6000:
+ if (a->mach == 0)
+ return a;
+ return NULL;
+ }
+ /*NOTREACHED*/
+}
+
+static const bfd_arch_info_type arch_info_struct[] =
+{
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_powerpc,
+ 603, /* for the mpc603 */
+ "powerpc",
+ "powerpc:603",
+ 3,
+ false, /* not the default */
+ powerpc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[1]
+ },
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_powerpc,
+ 604, /* for the mpc604 */
+ "powerpc",
+ "powerpc:604",
+ 3,
+ false, /* not the default */
+ powerpc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[2]
+ },
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_powerpc,
+ 403, /* for the 403 */
+ "powerpc",
+ "powerpc:403",
+ 3,
+ false, /* not the default */
+ powerpc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[3]
+ },
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_powerpc,
+ 601, /* for the mpc601 */
+ "powerpc",
+ "powerpc:601",
+ 3,
+ false, /* not the default */
+ powerpc_compatible,
+ bfd_default_scan,
+ 0
+ }
+};
+
+const bfd_arch_info_type bfd_powerpc_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_powerpc,
+ 0, /* for the POWER/PowerPC common architecture */
+ "powerpc",
+ "powerpc:common",
+ 3,
+ true, /* the default */
+ powerpc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[0]
+ };
diff --git a/contrib/gdb/bfd/cpu-rs6000.c b/contrib/gdb/bfd/cpu-rs6000.c
new file mode 100644
index 0000000..9852ae9
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-rs6000.c
@@ -0,0 +1,70 @@
+/* BFD back-end for rs6000 support
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ FIXME: Can someone provide a transliteration of this name into ASCII?
+ Using the following chars caused a compiler warning on HIUX (so I replaced
+ them with octal escapes), and isn't useful without an understanding of what
+ character set it is.
+ Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
+ and John Gilmore 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* The RS/6000 architecture is compatible with the PowerPC common
+ architecture. */
+
+static const bfd_arch_info_type *rs6000_compatible
+ PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
+
+static const bfd_arch_info_type *
+rs6000_compatible (a,b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+ BFD_ASSERT (a->arch == bfd_arch_rs6000);
+ switch (b->arch)
+ {
+ default:
+ return NULL;
+ case bfd_arch_rs6000:
+ return bfd_default_compatible (a, b);
+ case bfd_arch_powerpc:
+ if (b->mach == 0)
+ return b;
+ return NULL;
+ }
+ /*NOTREACHED*/
+}
+
+const bfd_arch_info_type bfd_rs6000_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_rs6000,
+ 6000, /* only 1 machine */
+ "rs6000",
+ "rs6000:6000",
+ 3,
+ true, /* the one and only */
+ rs6000_compatible,
+ bfd_default_scan,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-sh.c b/contrib/gdb/bfd/cpu-sh.c
new file mode 100644
index 0000000..7f6dd68
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-sh.c
@@ -0,0 +1,68 @@
+/* BFD library support routines for the Hitachi-SH architecture.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+int bfd_default_scan_num_mach();
+
+static boolean
+scan_mach (info, string)
+ const struct bfd_arch_info *info;
+ const char *string;
+{
+ if (strcmp(string,"sh") == 0) return true;
+ if (strcmp(string,"SH") == 0) return true;
+ return false;
+}
+
+
+#if 0
+/* This routine is provided two arch_infos and returns whether
+ they'd be compatible */
+
+static const bfd_arch_info_type *
+compatible (a,b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+ if (a->arch != b->arch || a->mach != b->mach)
+ return NULL;
+ return a;
+}
+#endif
+
+const bfd_arch_info_type bfd_sh_arch =
+{
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_sh,
+ 0, /* only 1 machine */
+ "sh", /* arch_name */
+ "sh", /* printable name */
+ 1,
+ true, /* the default machine */
+ bfd_default_compatible,
+ scan_mach,
+ 0,
+};
diff --git a/contrib/gdb/bfd/cpu-sparc.c b/contrib/gdb/bfd/cpu-sparc.c
new file mode 100644
index 0000000..e48aa5e
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-sparc.c
@@ -0,0 +1,111 @@
+/* BFD support for the SPARC architecture.
+ Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* Don't mix 32 bit and 64 bit files. */
+
+static const bfd_arch_info_type *
+sparc_compatible (a, b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+ if (a->bits_per_word != b->bits_per_word)
+ return NULL;
+
+ return bfd_default_compatible (a, b);
+}
+
+static const bfd_arch_info_type arch_info_struct[] =
+{
+ {
+ 32, /* bits in a word */
+ 32, /* bits in an address */
+ 8, /* bits in a byte */
+ bfd_arch_sparc,
+ bfd_mach_sparc_v8plus,
+ "sparc",
+ "sparc:v8plus",
+ 3,
+ false,
+ sparc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[1],
+ },
+ {
+ 32, /* bits in a word */
+ 32, /* bits in an address */
+ 8, /* bits in a byte */
+ bfd_arch_sparc,
+ bfd_mach_sparc_v8plusa,
+ "sparc",
+ "sparc:v8plusa",
+ 3,
+ false,
+ sparc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[2],
+ },
+ {
+ 64, /* bits in a word */
+ 64, /* bits in an address */
+ 8, /* bits in a byte */
+ bfd_arch_sparc,
+ bfd_mach_sparc_v9,
+ "sparc",
+ "sparc:v9",
+ 3,
+ false,
+ sparc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[3],
+ },
+ {
+ 64, /* bits in a word */
+ 64, /* bits in an address */
+ 8, /* bits in a byte */
+ bfd_arch_sparc,
+ bfd_mach_sparc_v9a,
+ "sparc",
+ "sparc:v9a",
+ 3,
+ false,
+ sparc_compatible,
+ bfd_default_scan,
+ 0,
+ }
+};
+
+const bfd_arch_info_type bfd_sparc_arch =
+ {
+ 32, /* bits in a word */
+ 32, /* bits in an address */
+ 8, /* bits in a byte */
+ bfd_arch_sparc,
+ bfd_mach_sparc,
+ "sparc",
+ "sparc",
+ 3,
+ true, /* the default */
+ sparc_compatible,
+ bfd_default_scan,
+ &arch_info_struct[0],
+ };
diff --git a/contrib/gdb/bfd/cpu-vax.c b/contrib/gdb/bfd/cpu-vax.c
new file mode 100644
index 0000000..bdc6d39
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-vax.c
@@ -0,0 +1,39 @@
+/* bfd back-end for vax support
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_vax_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_vax,
+ 0, /* only 1 machine */
+ "vax",
+ "vax",
+ 3,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-w65.c b/contrib/gdb/bfd/cpu-w65.c
new file mode 100644
index 0000000..c0bbf04
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-w65.c
@@ -0,0 +1,54 @@
+/* BFD library support routines for the WDC 65816 architecture.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as publiw65ed by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You w65ould have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+int bfd_default_scan_num_mach();
+
+static boolean
+scan_mach (info, string)
+ const struct bfd_arch_info *info;
+ const char *string;
+{
+ if (strcmp(string,"w65") == 0) return true;
+ if (strcmp(string,"w65816") == 0) return true;
+ return false;
+}
+
+
+
+const bfd_arch_info_type bfd_w65_arch =
+{
+ 16, /* 16 bits in a word */
+ 24, /* 24 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_w65,
+ 0, /* only 1 machine */
+ "w65", /* arch_name */
+ "w65", /* printable name */
+ 1,
+ true, /* the default machine */
+ bfd_default_compatible,
+ scan_mach,
+ 0,
+};
diff --git a/contrib/gdb/bfd/cpu-we32k.c b/contrib/gdb/bfd/cpu-we32k.c
new file mode 100644
index 0000000..a38cbc1
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-we32k.c
@@ -0,0 +1,39 @@
+/* bfd back-end for we32k support
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Contributed by Brendan Kehoe (brendan@cs.widener.edu).
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+const bfd_arch_info_type bfd_we32k_arch =
+ {
+ 32, /* 32 bits in a word */
+ 32, /* 32 bits in an address */
+ 8, /* 8 bits in a byte */
+ bfd_arch_we32k,
+ 32000, /* only 1 machine */
+ "we32k",
+ "we32k:32000",
+ 3,
+ true, /* the one and only */
+ bfd_default_compatible,
+ bfd_default_scan ,
+ 0,
+ };
diff --git a/contrib/gdb/bfd/cpu-z8k.c b/contrib/gdb/bfd/cpu-z8k.c
new file mode 100644
index 0000000..5cce8eb
--- /dev/null
+++ b/contrib/gdb/bfd/cpu-z8k.c
@@ -0,0 +1,198 @@
+/* BFD library support routines for the Z800n architecture.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Hacked by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+#if 0 /* not used currently */
+/*
+Relocations for the Z8K
+
+*/
+static bfd_reloc_status_type
+howto16_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
+
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_16 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+
+static bfd_reloc_status_type
+howto8_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
+
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+
+static bfd_reloc_status_type
+howto8_FFnn_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+
+ long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
+ abort ();
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+howto8_pcrel_callback (abfd, reloc_entry, symbol_in, data,
+ ignore_input_section, ignore_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol_in;
+ PTR data;
+ asection *ignore_input_section;
+ bfd *ignore_bfd;
+{
+ long relocation = 0;
+ bfd_vma addr = reloc_entry->address;
+ long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
+ abort ();
+ HOWTO_PREPARE (relocation, symbol_in);
+
+ x = (x + relocation + reloc_entry->addend);
+
+ bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
+ return bfd_reloc_ok;
+}
+
+
+
+static reloc_howto_type howto_16
+= NEWHOWTO (howto16_callback, "abs16", 1, false, false);
+static reloc_howto_type howto_8
+= NEWHOWTO (howto8_callback, "abs8", 0, false, false);
+
+static reloc_howto_type howto_8_FFnn
+= NEWHOWTO (howto8_FFnn_callback, "ff00+abs8", 0, false, false);
+
+static reloc_howto_type howto_8_pcrel
+= NEWHOWTO (howto8_pcrel_callback, "pcrel8", 0, false, true);
+
+
+static reloc_howto_type *
+local_bfd_reloc_type_lookup (arch, code)
+ const struct bfd_arch_info *arch;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ case BFD_RELOC_16:
+ return &howto_16;
+ case BFD_RELOC_8_FFnn:
+ return &howto_8_FFnn;
+ case BFD_RELOC_8:
+ return &howto_8;
+ case BFD_RELOC_8_PCREL:
+ return &howto_8_pcrel;
+ default:
+ return (reloc_howto_type *) NULL;
+ }
+}
+#endif
+
+int bfd_default_scan_num_mach ();
+
+static boolean
+scan_mach (info, string)
+ const struct bfd_arch_info *info;
+ const char *string;
+{
+ if (strcmp (string, "z8001") == 0 || strcmp (string, "z8k") == 0)
+ {
+ return bfd_mach_z8001 == info->mach;
+ }
+ if (strcmp (string, "z8002") == 0)
+ {
+ return bfd_mach_z8002 == info->mach;
+ }
+ return false;
+}
+
+
+/* This routine is provided two arch_infos and returns whether
+ they'd be compatible */
+
+static const bfd_arch_info_type *
+compatible (a, b)
+ const bfd_arch_info_type *a;
+ const bfd_arch_info_type *b;
+{
+ if (a->arch != b->arch || a->mach != b->mach)
+ return NULL;
+ return a;
+}
+
+
+static const bfd_arch_info_type arch_info_struct[] =
+{
+ {32, 32, 8, bfd_arch_z8k, bfd_mach_z8001, "z8k", "z8001", 1, false, compatible, scan_mach, 0,},
+};
+
+const bfd_arch_info_type bfd_z8k_arch =
+{
+ 32, 16, 8, bfd_arch_z8k, bfd_mach_z8002, "z8k", "z8002", 1, true, compatible, scan_mach, &arch_info_struct[0],
+};
diff --git a/contrib/gdb/bfd/demo64.c b/contrib/gdb/bfd/demo64.c
new file mode 100644
index 0000000..c91381d
--- /dev/null
+++ b/contrib/gdb/bfd/demo64.c
@@ -0,0 +1,24 @@
+/* BFD backend for demonstration 64-bit a.out binaries.
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define ARCH_SIZE 64
+#define MY(OP) CAT(demo_64_,OP)
+#define TARGETNAME "demo64"
+#include "aoutf1.h"
diff --git a/contrib/gdb/bfd/dep-in.sed b/contrib/gdb/bfd/dep-in.sed
new file mode 100644
index 0000000..1cbd786
--- /dev/null
+++ b/contrib/gdb/bfd/dep-in.sed
@@ -0,0 +1,24 @@
+:loop
+/\\$/N
+/\\$/b loop
+
+s! @BFD_H@!!g
+s!@INCDIR@!$(INCDIR)!g
+s!@SRCDIR@/!!g
+s!hosts/[^ ]*\.h ! !g
+s/ sysdep.h//g
+s/ libbfd.h//g
+s/ config.h//g
+s! \$(INCDIR)/fopen-[^ ]*\.h!!g
+s! \$(INCDIR)/ansidecl\.h!!g
+s! \$(INCDIR)/obstack\.h!!g
+
+s/\\\n */ /g
+
+s/ *$//
+s/ */ /g
+s/ *:/:/g
+/:$/d
+
+s/\(.\{50\}[^ ]*\) /\1 \\\
+ /g
diff --git a/contrib/gdb/bfd/doc/ChangeLog b/contrib/gdb/bfd/doc/ChangeLog
new file mode 100644
index 0000000..f076e37
--- /dev/null
+++ b/contrib/gdb/bfd/doc/ChangeLog
@@ -0,0 +1,268 @@
+Tue Jan 30 14:10:46 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ From Ronald F. Guilmette <rfg@monkeys.com>:
+ * Makefile.in (libbfd.h): Depend upon proto.str.
+ (libcoff.h, bfd.h): Likewise.
+
+Fri Nov 3 14:46:48 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (SRCDOC, SRCPROT, core.texi, bfd.h): Use corefile.c,
+ renamed from core.c.
+
+Wed Nov 1 14:28:23 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de>
+
+ * chew.c: Include <ctype.h>.
+
+Fri Oct 6 16:23:34 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ Mon Sep 25 22:49:32 1995 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * Makefile.in (Makefile): Only remake this Makefile.
+
+Wed Oct 4 15:51:05 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * chew.c: Include <stdio.h>.
+
+Tue Sep 12 18:14:50 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target.
+
+Thu Aug 31 12:18:43 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (bfd.h): Add additional #endif at end of bfd.h if
+ __cplusplus is defined.
+
+Tue Nov 29 16:13:34 1994 Doug Evans <dje@canuck.cygnus.com>
+
+ * chew.c (write_buffer): New argument `f', all callers changed.
+ (stdout, stderr, print, drop, idrop): New forth words.
+ * proto.str (COMMENT): New command.
+ * doc.str (COMMENT): Likewise.
+
+Mon Sep 12 11:44:17 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * Makefile.in (DOCFILES): Remove ctor.texi.
+ (IPROTOS): Remove ctor.ip.
+ (SRCIPROT): Remove $(srcdir)/../ctor.c.
+ (ctor.texi): Remove target.
+ (libbfd.h): Remove dependency on $(srcdir)/../ctor.c. Remove
+ $(MKDOC) run on $(srcdir)/../ctor.c.
+ * bfd.texinfo (Constructors): Remove section.
+
+Fri Sep 2 13:33:44 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * chew.c: Include assert.h. Added prototypes for most functions.
+ Changed most uses of int to long. Do bounds checking on the
+ stacks. Added comment at the beginning documenting most of the
+ intrinsics. Lots of whitespace changes. Re-ordered some
+ functions.
+ (die, check_range, icheck_range): New functions.
+ (strip_trailing_newlines, print_stack_level): New functions.
+ (translatecomments): Don't insert tab before "/*".
+ (iscommand): Minimum command length is now 4.
+ (nextword): Handle some \-sequences.
+ (push_addr): Deleted.
+ (main): Add new intrinsics strip_trailing_newlines and
+ print_stack_level. Complain at end if stack contains more than
+ one element, or less.
+ (remchar): Make sure the string is not empty before chopping off a
+ character.
+
+ * doc.str, proto.str: Handle new commands SENUM, ENUM, ENUMX,
+ ENUMEQ, ENUMEQX, ENUMDOC.
+
+Wed Jan 12 18:37:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfd.texinfo: Added Linker Functions node.
+ * doc/Makefile.in (DOCFILES): Added linker.texi.
+ (SRCDOC): Added linker.c.
+ (linker.texi): New target.
+
+Tue Jan 4 10:52:56 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * chew.c: Don't rely on a correct declaration of exit.
+ (chew_exit): New function which just calls exit.
+ (main): Use it.
+
+Mon Jan 3 11:40:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfd.texinfo: Added Hash Tables node.
+ * Makefile.in (DOCFILES): Added hash.texi.
+ (SRCDOC): Added hash.c.
+ (hash.texi): New target.
+
+Thu Dec 30 16:57:04 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * Makefile.in: Delete all references to seclet.c, since it's just
+ been deleted. Don't mention hash.c, linker.c, or genlink.h yet,
+ since they don't contain documentation yet (hint, hint!).
+
+Fri Nov 5 10:58:53 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * bfd.texinfo: Small cleanups.
+
+Fri Nov 19 03:46:11 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (archures.texi): Depends on $(MKDOC).
+
+Tue Aug 10 14:22:39 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * bfd.texinfo (BFD back end): Don't include elfcode.texi, since
+ it's empty now and that triggers a makeinfo bug.
+
+Mon Aug 9 16:27:30 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * bfd.texinfo (BFD back end): New section on ELF, includes
+ elf.texi and elfcode.texi.
+ * Makefile.in (DOCFILES): Include elf.texi, elfcode.texi.
+ (SRCDOC): Include elfcode.h, elf.c.
+ (elf.texi, elfcode.texi): New intermediate targets.
+
+Thu Jun 24 13:48:13 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * Makefile.in (.c.o, chew.o): Put CFLAGS last.
+ * bfdsumm.texi: New file, broken out of bfd.texinfo, to share
+ with ld.texinfo.
+
+Mon Jun 14 12:07:07 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com)
+
+ * Makefile.in (install-info): remove parentdir cruft,
+
+Wed Jun 9 16:00:32 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (mostlyclean): Remove chew.o.
+
+Tue May 25 14:46:58 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (libbfd.h): Use elfcode.h, not elf32.c.
+
+Mon May 24 15:50:07 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * chew.c (compile): Add a couple of missing casts.
+
+Wed May 12 14:45:14 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (CC_FOR_BUILD): New variable, define to be $(CC).
+ (chew.o, $(MKDOC)): Build using CC_FOR_BUILD rather than CC, since
+ it must run on the build machine.
+
+Tue Apr 6 22:38:10 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (chew): Don't compile from .c to executable in a
+ single step; it puts a temporary .o filename into the executable,
+ which makes multi-stage comparisons fail. Compile chew.c to
+ chew.o, and link that, which makes identical executables every time.
+
+Wed Mar 24 17:26:29 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: fix typo (bfd.texinfo not bfd.texino)
+
+Fri Mar 19 01:13:00 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * bfd.texinfo: Since BFD version number has been bumped, do same
+ to "version number" on title page, and elsewhere. Should be
+ fixed to extract real version number.
+
+Tue Mar 16 12:15:13 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in: Add *clean rules.
+
+Mon Jan 11 18:43:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (libbfd.h): Removed duplicate init.c and libbfd.c.
+ Added seclet.c.
+ (bfd.h): Added dependency on bfd.c and seclet.c. Added seclet.c
+ to build.
+
+Thu Dec 17 19:35:43 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: added dvi target, define and use $(TEXI2DVI)
+
+Thu Dec 3 17:42:48 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (TEXIDIR): New variable.
+ (bfd.dvi): Look for bfd.texinfo in $(srcdir). Generate index.
+
+ * bfd.texinfo: Minor doc fixes.
+
+Thu Nov 5 03:13:55 1992 John Gilmore (gnu@cygnus.com)
+
+ Cleanup: Replace all uses of EXFUN in the BFD sources, with PARAMS.
+
+ * doc/chew.c (exfunstuff): Eliminate.
+ (paramstuff): Replace exfunstuff with function to generate PARAMS.
+ * doc/proto.str: Use paramstuff rather than exfunstuff.
+
+Mon Aug 17 12:40:32 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * chew.c: various patches provided by Howard Chu.
+
+Fri Jun 19 18:59:54 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in (libbfd.h): Add elf.c as a source of prototypes.
+
+Mon May 11 18:55:59 1992 John Gilmore (gnu at cygnus.com)
+
+ * chew.c: exit() should be declared by config files, not by
+ portable source code. Its type could be int or void function.
+
+Mon May 4 13:45:57 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: another CFLAGS correction.
+
+Tue Apr 28 10:21:32 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: Do the CFLAGS thing.
+
+Fri Apr 10 22:34:52 1992 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (MINUS_G): Add macro and default to -g.
+
+Fri Mar 6 18:53:18 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * chew.c: now has -w switch turn on warnings
+
+Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in: removed traces of namesubdir,
+ -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
+ copyrights to '92, changed some from Cygnus to FSF.
+
+Tue Dec 10 22:11:05 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: build chew into the current directory. Complete
+ the MKDOC macro transition.
+
+Tue Dec 10 08:26:28 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * chew.c: don't core dump when can't open file
+ * Makefile.in: get proto.str from the right place when built in
+ odd directories
+
+Tue Dec 10 04:07:25 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: infodir belongs in datadir.
+
+Sat Dec 7 17:01:23 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * chew.c: Much modified
+ * proto.str, doc.str: New files for extracting to product
+ prototypes and documents respectively.
+
+
+Fri Dec 6 22:57:12 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: added standards.text support, host/site/target
+ inclusion hooks, install using INSTALL_DATA rather than cp,
+ don't echo on install.
+
+Thu Dec 5 22:46:17 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: idestdir and ddestdir go away. Added copyrights
+ and shift gpl to v2. Added ChangeLog if it didn't exist. docdir
+ and mandir now keyed off datadir by default.
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/bfd/doc/Makefile.in b/contrib/gdb/bfd/doc/Makefile.in
new file mode 100644
index 0000000..aa3a76c
--- /dev/null
+++ b/contrib/gdb/bfd/doc/Makefile.in
@@ -0,0 +1,311 @@
+#
+# Makefile
+# Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+prefix = @prefix@
+
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+docdir = $(datadir)/doc
+
+MKDOC=./chew
+SHELL = /bin/sh
+
+INSTALL = `cd $(srcdir)/../..;pwd`/install.sh -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+
+MAKEINFO = makeinfo
+TEXI2DVI = texi2dvi
+CFLAGS = -g
+
+CC_FOR_BUILD = $(CC)
+
+#### Host, target, and site specific Makefile fragments come in here.
+###
+
+.c.o:
+ $(CC) -c -I.. -I$(srcdir)/.. -I$(srcdir)/../../include $(H_CFLAGS) $(CFLAGS) $<
+
+DOCFILES = aoutx.texi archive.texi archures.texi \
+ bfd.texi cache.texi coffcode.texi \
+ core.texi elf.texi elfcode.texi format.texi libbfd.texi \
+ opncls.texi reloc.texi section.texi \
+ syms.texi targets.texi init.texi hash.texi linker.texi
+
+PROTOS = archive.p archures.p bfd.p \
+ core.p format.p \
+ libbfd.p opncls.p reloc.p \
+ section.p syms.p targets.p \
+ format.p core.p init.p
+
+IPROTOS = cache.ip libbfd.ip reloc.ip init.ip archures.ip coffcode.ip
+
+# SRCDOC, SRCPROT, SRCIPROT only used to sidestep Sun Make bug in interaction
+# between VPATH and suffix rules. If you use GNU Make, perhaps other Makes,
+# you don't need these three:
+SRCDOC = $(srcdir)/../aoutx.h $(srcdir)/../archive.c \
+ $(srcdir)/../archures.c $(srcdir)/../bfd.c \
+ $(srcdir)/../cache.c $(srcdir)/../coffcode.h \
+ $(srcdir)/../corefile.c $(srcdir)/../elf.c \
+ $(srcdir)/../elfcode.h $(srcdir)/../format.c \
+ $(srcdir)/../libbfd.c $(srcdir)/../opncls.c \
+ $(srcdir)/../reloc.c $(srcdir)/../section.c \
+ $(srcdir)/../syms.c $(srcdir)/../targets.c \
+ $(srcdir)/../hash.c $(srcdir)/../linker.c
+
+SRCPROT = $(srcdir)/../archive.c $(srcdir)/../archures.c \
+ $(srcdir)/../bfd.c $(srcdir)/../coffcode.h $(srcdir)/../corefile.c \
+ $(srcdir)/../format.c $(srcdir)/../libbfd.c \
+ $(srcdir)/../opncls.c $(srcdir)/../reloc.c \
+ $(srcdir)/../section.c $(srcdir)/../syms.c \
+ $(srcdir)/../targets.c $(srcdir)/../init.c
+
+SRCIPROT = $(srcdir)/../cache.c $(srcdir)/../libbfd.c \
+ $(srcdir)/../reloc.c $(srcdir)/../cpu-h8300.c \
+ $(srcdir)/../cpu-i960.c $(srcdir)/../archures.c \
+ $(srcdir)/../init.c
+
+STAGESTUFF = $(DOCFILES) *.info*
+
+TEXIDIR = $(srcdir)/../../texinfo/fsf
+
+all install:
+
+info: bfd.info
+
+dvi: bfd.dvi
+
+install-info: info
+ for i in *.info* ; do \
+ $(INSTALL_DATA) $$i $(infodir)/$$i ; \
+ done
+
+docs: $(MKDOC) protos bfd.info bfd.dvi bfd.ps
+
+$(MKDOC): chew.o
+ $(CC_FOR_BUILD) -o $(MKDOC) chew.o $(LOADLIBES) $(LDFLAGS)
+
+chew.o: chew.c
+ $(CC_FOR_BUILD) -c -I.. -I$(srcdir)/.. -I$(srcdir)/../../include $(H_CFLAGS) $(CFLAGS) $(srcdir)/chew.c
+
+protos: libbfd.h libcoff.h bfd.h
+
+
+# We can't replace these rules with an implicit rule, because
+# makes without VPATH support couldn't find the .h files in `..'.
+
+aoutx.texi: $(MKDOC) $(srcdir)/../aoutx.h $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../aoutx.h >aoutx.texi
+
+archive.texi: $(MKDOC) $(srcdir)/../archive.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../archive.c >archive.texi
+
+archures.texi: $(MKDOC) $(srcdir)/../archures.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str < $(srcdir)/../archures.c >archures.texi
+
+bfd.texi: $(MKDOC) $(srcdir)/../bfd.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str < $(srcdir)/../bfd.c >bfd.texi
+
+cache.texi: $(MKDOC) $(srcdir)/../cache.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str < $(srcdir)/../cache.c >cache.texi
+
+coffcode.texi: $(MKDOC) $(srcdir)/../coffcode.h $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../coffcode.h >coffcode.texi
+
+core.texi: $(MKDOC) $(srcdir)/../corefile.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../corefile.c >core.texi
+
+elf.texi: $(MKDOC) $(srcdir)/../elf.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../elf.c >elf.texi
+
+elfcode.texi: $(MKDOC) $(srcdir)/../elfcode.h $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../elfcode.h >elfcode.texi
+
+format.texi: $(MKDOC) $(srcdir)/../format.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../format.c >format.texi
+
+libbfd.texi: $(MKDOC) $(srcdir)/../libbfd.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str < $(srcdir)/../libbfd.c >libbfd.texi
+
+opncls.texi: $(MKDOC) $(srcdir)/../opncls.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../opncls.c >opncls.texi
+
+reloc.texi : $(MKDOC) $(srcdir)/../reloc.c
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../reloc.c >reloc.texi
+
+section.texi: $(MKDOC) $(srcdir)/../section.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../section.c >section.texi
+
+syms.texi : $(MKDOC) $(srcdir)/../syms.c
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../syms.c >syms.texi
+
+targets.texi: $(MKDOC) $(srcdir)/../targets.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../targets.c >targets.texi
+
+init.texi: $(MKDOC) $(srcdir)/../init.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../init.c >init.texi
+
+hash.texi: $(MKDOC) $(srcdir)/../hash.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../hash.c >hash.texi
+
+linker.texi: $(MKDOC) $(srcdir)/../linker.c $(srcdir)/doc.str
+ $(MKDOC) -f $(srcdir)/doc.str <$(srcdir)/../linker.c >linker.texi
+
+libbfd.h: $(srcdir)/../libbfd-in.h \
+ $(srcdir)/../init.c \
+ $(srcdir)/../libbfd.c \
+ $(srcdir)/../cache.c \
+ $(srcdir)/../reloc.c \
+ $(srcdir)/../cpu-h8300.c \
+ $(srcdir)/../cpu-i960.c \
+ $(srcdir)/../archures.c \
+ $(srcdir)/../elfcode.h \
+ $(srcdir)/proto.str \
+ $(MKDOC)
+ cat $(srcdir)/../libbfd-in.h >libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../init.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../libbfd.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../cache.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../reloc.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../cpu-h8300.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../cpu-i960.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../archures.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../elf.c >>libbfd.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../elfcode.h >>libbfd.h
+
+libcoff.h: $(srcdir)/../libcoff-in.h \
+ $(srcdir)/../coffcode.h \
+ $(srcdir)/proto.str \
+ $(MKDOC)
+ cat $(srcdir)/../libcoff-in.h >libcoff.h
+ $(MKDOC) -i -f $(srcdir)/proto.str < $(srcdir)/../coffcode.h >>libcoff.h
+
+bfd.h: $(srcdir)/../bfd-in.h \
+ $(srcdir)/../init.c \
+ $(srcdir)/../opncls.c \
+ $(srcdir)/../libbfd.c \
+ $(srcdir)/../section.c \
+ $(srcdir)/../archures.c \
+ $(srcdir)/../reloc.c \
+ $(srcdir)/../syms.c \
+ $(srcdir)/../bfd.c \
+ $(srcdir)/../archive.c \
+ $(srcdir)/../corefile.c \
+ $(srcdir)/../targets.c \
+ $(srcdir)/../format.c \
+ $(srcdir)/proto.str \
+ $(MKDOC)
+ cat $(srcdir)/../bfd-in.h >bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../init.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../opncls.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../libbfd.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../section.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../archures.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../reloc.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../syms.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../bfd.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../archive.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../corefile.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../targets.c >>bfd.h
+ $(MKDOC) -f $(srcdir)/proto.str<$(srcdir)/../format.c >>bfd.h
+ echo "#ifdef __cplusplus" >>bfd.h
+ echo "}" >>bfd.h
+ echo "#endif" >>bfd.h
+ echo "#endif" >>bfd.h
+
+
+clean-info: clean
+
+mostlyclean:
+ rm -rf *.log *.ps *~* *.dvi *# $(MKDOC) *.o
+
+clean: mostlyclean
+ rm -rf $(STAGESTUFF)
+ rm -f *.p *.ip bfd.?? bfd.??? bfd.h libbfd.h libcoff.h texput.log
+
+distclean: clean
+ rm -f Makefile config.status
+
+maintainer-clean realclean: clean
+ rm -f Makefile config.status
+
+bfd.info: $(DOCFILES) bfdsumm.texi bfd.texinfo
+ $(MAKEINFO) -I$(srcdir) -o bfd.info $(srcdir)/bfd.texinfo
+
+bfd.dvi: $(DOCFILES) bfdsumm.texi bfd.texinfo
+ $(TEXI2DVI) $(srcdir)/bfd.texinfo
+
+bfd.ps: bfd.dvi
+ dvips bfd -o
+
+quickdoc: $(DOCFILES) bfdsumm.texi bfd.texinfo
+ TEXINPUTS=${TEXIDIR}:.:$$TEXINPUTS tex bfd.texinfo
+
+stage1: force
+ - mkdir stage1
+ - mv -f $(STAGESTUFF) stage1
+
+stage2: force
+ - mkdir stage2
+ - mv -f $(STAGESTUFF) stage2
+
+stage3: force
+ - mkdir stage3
+ - mv -f $(STAGESTUFF) stage3
+
+against=stage2
+
+comparison: force
+ for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i || exit 1 ; done
+
+de-stage1: force
+ - (cd stage1 ; mv -f $(STAGESTUFF) ..)
+ - rmdir stage1
+
+de-stage2: force
+ - (cd stage2 ; mv -f $(STAGESTUFF) ..)
+ - rmdir stage2
+
+de-stage3: force
+ - (cd stage3 ; mv -f $(STAGESTUFF) ..)
+ - rmdir stage3
+
+force:
+
+Makefile: $(srcdir)/Makefile.in
+ cd .. && CONFIG_FILES=doc/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
diff --git a/contrib/gdb/bfd/doc/bfd.texinfo b/contrib/gdb/bfd/doc/bfd.texinfo
new file mode 100644
index 0000000..af7bc10
--- /dev/null
+++ b/contrib/gdb/bfd/doc/bfd.texinfo
@@ -0,0 +1,348 @@
+\input texinfo.tex
+@setfilename bfd.info
+@c $Id: bfd.texinfo,v 1.28 1995/11/10 20:04:12 victoria Exp $
+@tex
+% NOTE LOCAL KLUGE TO AVOID TOO MUCH WHITESPACE
+\global\long\def\example{%
+\begingroup
+\let\aboveenvbreak=\par
+\let\afterenvbreak=\par
+\parskip=0pt
+\lisp}
+\global\long\def\Eexample{%
+\Elisp
+\endgroup
+\vskip -\parskip% to cancel out effect of following \par
+}
+@end tex
+@synindex fn cp
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Bfd: (bfd). The Binary File Descriptor library.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This file documents the BFD library.
+
+Copyright (C) 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, subject to the terms
+of the GNU General Public License, which includes the provision that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+@iftex
+@c@finalout
+@setchapternewpage on
+@c@setchapternewpage odd
+@settitle LIB BFD, the Binary File Descriptor Library
+@titlepage
+@title{libbfd}
+@subtitle{The Binary File Descriptor Library}
+@sp 1
+@subtitle First Edition---BFD version < 3.0
+@subtitle April 1991
+@author {Steve Chamberlain}
+@author {Cygnus Support}
+@page
+
+@tex
+\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision: 1.28 $} % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill sac\@cygnus.com\par
+\hfill {\it BFD}, \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+\global\parindent=0pt % Steve likes it this way
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, subject to the terms
+of the GNU General Public License, which includes the provision that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+@end iftex
+
+@node Top, Overview, (dir), (dir)
+@ifinfo
+This file documents the binary file descriptor library libbfd.
+@end ifinfo
+
+@menu
+* Overview:: Overview of BFD
+* BFD front end:: BFD front end
+* BFD back ends:: BFD back ends
+* Index:: Index
+@end menu
+
+@node Overview, BFD front end, Top, Top
+@chapter Introduction
+@cindex BFD
+@cindex what is it?
+BFD is a package which allows applications to use the
+same routines to operate on object files whatever the object file
+format. A new object file format can be supported simply by
+creating a new BFD back end and adding it to the library.
+
+BFD is split into two parts: the front end, and the back ends (one for
+each object file format).
+@itemize @bullet
+@item The front end of BFD provides the interface to the user. It manages
+memory and various canonical data structures. The front end also
+decides which back end to use and when to call back end routines.
+@item The back ends provide BFD its view of the real world. Each back
+end provides a set of calls which the BFD front end can use to maintain
+its canonical form. The back ends also may keep around information for
+their own use, for greater efficiency.
+@end itemize
+@menu
+* History:: History
+* How It Works:: How It Works
+* What BFD Version 2 Can Do:: What BFD Version 2 Can Do
+@end menu
+
+@node History, How It Works, Overview, Overview
+@section History
+
+One spur behind BFD was the desire, on the part of the GNU 960 team at
+Intel Oregon, for interoperability of applications on their COFF and
+b.out file formats. Cygnus was providing GNU support for the team, and
+was contracted to provide the required functionality.
+
+The name came from a conversation David Wallace was having with Richard
+Stallman about the library: RMS said that it would be quite hard---David
+said ``BFD''. Stallman was right, but the name stuck.
+
+At the same time, Ready Systems wanted much the same thing, but for
+different object file formats: IEEE-695, Oasys, Srecords, a.out and 68k
+coff.
+
+BFD was first implemented by members of Cygnus Support; Steve
+Chamberlain (@code{sac@@cygnus.com}), John Gilmore
+(@code{gnu@@cygnus.com}), K. Richard Pixley (@code{rich@@cygnus.com})
+and David Henkel-Wallace (@code{gumby@@cygnus.com}).
+
+
+
+@node How It Works, What BFD Version 2 Can Do, History, Overview
+@section How To Use BFD
+
+To use the library, include @file{bfd.h} and link with @file{libbfd.a}.
+
+BFD provides a common interface to the parts of an object file
+for a calling application.
+
+When an application sucessfully opens a target file (object, archive, or
+whatever), a pointer to an internal structure is returned. This pointer
+points to a structure called @code{bfd}, described in
+@file{bfd.h}. Our convention is to call this pointer a BFD, and
+instances of it within code @code{abfd}. All operations on
+the target object file are applied as methods to the BFD. The mapping is
+defined within @code{bfd.h} in a set of macros, all beginning
+with @samp{bfd_} to reduce namespace pollution.
+
+For example, this sequence does what you would probably expect:
+return the number of sections in an object file attached to a BFD
+@code{abfd}.
+
+@lisp
+@c @cartouche
+#include "bfd.h"
+
+unsigned int number_of_sections(abfd)
+bfd *abfd;
+@{
+ return bfd_count_sections(abfd);
+@}
+@c @end cartouche
+@end lisp
+
+The abstraction used within BFD is that an object file has:
+
+@itemize @bullet
+@item
+a header,
+@item
+a number of sections containing raw data (@pxref{Sections}),
+@item
+a set of relocations (@pxref{Relocations}), and
+@item
+some symbol information (@pxref{Symbols}).
+@end itemize
+@noindent
+Also, BFDs opened for archives have the additional attribute of an index
+and contain subordinate BFDs. This approach is fine for a.out and coff,
+but loses efficiency when applied to formats such as S-records and
+IEEE-695.
+
+@node What BFD Version 2 Can Do, , How It Works, Overview
+@section What BFD Version 2 Can Do
+@include bfdsumm.texi
+
+@node BFD front end, BFD back ends, Overview, Top
+@chapter BFD front end
+@include bfd.texi
+
+@menu
+* Memory Usage::
+* Initialization::
+* Sections::
+* Symbols::
+* Archives::
+* Formats::
+* Relocations::
+* Core Files::
+* Targets::
+* Architectures::
+* Opening and Closing::
+* Internal::
+* File Caching::
+* Linker Functions::
+* Hash Tables::
+@end menu
+
+@node Memory Usage, Initialization, BFD front end, BFD front end
+@section Memory usage
+BFD keeps all of its internal structures in obstacks. There is one obstack
+per open BFD file, into which the current state is stored. When a BFD is
+closed, the obstack is deleted, and so everything which has been
+allocated by BFD for the closing file is thrown away.
+
+BFD does not free anything created by an application, but pointers into
+@code{bfd} structures become invalid on a @code{bfd_close}; for example,
+after a @code{bfd_close} the vector passed to
+@code{bfd_canonicalize_symtab} is still around, since it has been
+allocated by the application, but the data that it pointed to are
+lost.
+
+The general rule is to not close a BFD until all operations dependent
+upon data from the BFD have been completed, or all the data from within
+the file has been copied. To help with the management of memory, there
+is a function (@code{bfd_alloc_size}) which returns the number of bytes
+in obstacks associated with the supplied BFD. This could be used to
+select the greediest open BFD, close it to reclaim the memory, perform
+some operation and reopen the BFD again, to get a fresh copy of the data
+structures.
+
+@node Initialization, Sections, Memory Usage, BFD front end
+@include init.texi
+
+@node Sections, Symbols, Initialization, BFD front end
+@include section.texi
+
+@node Symbols, Archives, Sections, BFD front end
+@include syms.texi
+
+@node Archives, Formats, Symbols, BFD front end
+@include archive.texi
+
+@node Formats, Relocations, Archives, BFD front end
+@include format.texi
+
+@node Relocations, Core Files, Formats, BFD front end
+@include reloc.texi
+
+@node Core Files, Targets, Relocations, BFD front end
+@include core.texi
+
+@node Targets, Architectures, Core Files, BFD front end
+@include targets.texi
+
+@node Architectures, Opening and Closing, Targets, BFD front end
+@include archures.texi
+
+@node Opening and Closing, Internal, Architectures, BFD front end
+@include opncls.texi
+
+@node Internal, File Caching, Opening and Closing, BFD front end
+@include libbfd.texi
+
+@node File Caching, Linker Functions, Internal, BFD front end
+@include cache.texi
+
+@node Linker Functions, Hash Tables, File Caching, BFD front end
+@include linker.texi
+
+@node Hash Tables, , Linker Functions, BFD front end
+@include hash.texi
+
+@node BFD back ends, Index, BFD front end, Top
+@chapter BFD back ends
+@menu
+* What to Put Where::
+* aout :: a.out backends
+* coff :: coff backends
+* elf :: elf backends
+@ignore
+* oasys :: oasys backends
+* ieee :: ieee backend
+* srecord :: s-record backend
+@end ignore
+@end menu
+@node What to Put Where, aout, BFD back ends, BFD back ends
+All of BFD lives in one directory.
+
+@node aout, coff, What to Put Where, BFD back ends
+@include aoutx.texi
+
+@node coff, elf, aout, BFD back ends
+@include coffcode.texi
+
+@node elf, , coff, BFD back ends
+@include elf.texi
+@c Leave this out until the file has some actual contents...
+@c @include elfcode.texi
+
+@node Index, , BFD back ends , Top
+@unnumbered Index
+@printindex cp
+
+@tex
+% I think something like @colophon should be in texinfo. In the
+% meantime:
+\long\def\colophon{\hbox to0pt{}\vfill
+\centerline{The body of this manual is set in}
+\centerline{\fontname\tenrm,}
+\centerline{with headings in {\bf\fontname\tenbf}}
+\centerline{and examples in {\tt\fontname\tentt}.}
+\centerline{{\it\fontname\tenit\/} and}
+\centerline{{\sl\fontname\tensl\/}}
+\centerline{are used for emphasis.}\vfill}
+\page\colophon
+% Blame: doc@cygnus.com, 28mar91.
+@end tex
+
+@contents
+@bye
diff --git a/contrib/gdb/bfd/doc/bfdsumm.texi b/contrib/gdb/bfd/doc/bfdsumm.texi
new file mode 100644
index 0000000..844531a
--- /dev/null
+++ b/contrib/gdb/bfd/doc/bfdsumm.texi
@@ -0,0 +1,148 @@
+@c This summary of BFD is shared by the BFD and LD docs.
+When an object file is opened, BFD subroutines automatically determine
+the format of the input object file. They then build a descriptor in
+memory with pointers to routines that will be used to access elements of
+the object file's data structures.
+
+As different information from the the object files is required,
+BFD reads from different sections of the file and processes them.
+For example, a very common operation for the linker is processing symbol
+tables. Each BFD back end provides a routine for converting
+between the object file's representation of symbols and an internal
+canonical format. When the linker asks for the symbol table of an object
+file, it calls through a memory pointer to the routine from the
+relevant BFD back end which reads and converts the table into a canonical
+form. The linker then operates upon the canonical form. When the link is
+finished and the linker writes the output file's symbol table,
+another BFD back end routine is called to take the newly
+created symbol table and convert it into the chosen output format.
+
+@menu
+* BFD information loss:: Information Loss
+* Canonical format:: The BFD canonical object-file format
+@end menu
+
+@node BFD information loss
+@subsection Information Loss
+
+@emph{Information can be lost during output.} The output formats
+supported by BFD do not provide identical facilities, and
+information which can be described in one form has nowhere to go in
+another format. One example of this is alignment information in
+@code{b.out}. There is nowhere in an @code{a.out} format file to store
+alignment information on the contained data, so when a file is linked
+from @code{b.out} and an @code{a.out} image is produced, alignment
+information will not propagate to the output file. (The linker will
+still use the alignment information internally, so the link is performed
+correctly).
+
+Another example is COFF section names. COFF files may contain an
+unlimited number of sections, each one with a textual section name. If
+the target of the link is a format which does not have many sections (e.g.,
+@code{a.out}) or has sections without names (e.g., the Oasys format), the
+link cannot be done simply. You can circumvent this problem by
+describing the desired input-to-output section mapping with the linker command
+language.
+
+@emph{Information can be lost during canonicalization.} The BFD
+internal canonical form of the external formats is not exhaustive; there
+are structures in input formats for which there is no direct
+representation internally. This means that the BFD back ends
+cannot maintain all possible data richness through the transformation
+between external to internal and back to external formats.
+
+This limitation is only a problem when an application reads one
+format and writes another. Each BFD back end is responsible for
+maintaining as much data as possible, and the internal BFD
+canonical form has structures which are opaque to the BFD core,
+and exported only to the back ends. When a file is read in one format,
+the canonical form is generated for BFD and the application. At the
+same time, the back end saves away any information which may otherwise
+be lost. If the data is then written back in the same format, the back
+end routine will be able to use the canonical form provided by the
+BFD core as well as the information it prepared earlier. Since
+there is a great deal of commonality between back ends,
+there is no information lost when
+linking or copying big endian COFF to little endian COFF, or @code{a.out} to
+@code{b.out}. When a mixture of formats is linked, the information is
+only lost from the files whose format differs from the destination.
+
+@node Canonical format
+@subsection The BFD canonical object-file format
+
+The greatest potential for loss of information occurs when there is the least
+overlap between the information provided by the source format, that
+stored by the canonical format, and that needed by the
+destination format. A brief description of the canonical form may help
+you understand which kinds of data you can count on preserving across
+conversions.
+@cindex BFD canonical format
+@cindex internal object-file format
+
+@table @emph
+@item files
+Information stored on a per-file basis includes target machine
+architecture, particular implementation format type, a demand pageable
+bit, and a write protected bit. Information like Unix magic numbers is
+not stored here---only the magic numbers' meaning, so a @code{ZMAGIC}
+file would have both the demand pageable bit and the write protected
+text bit set. The byte order of the target is stored on a per-file
+basis, so that big- and little-endian object files may be used with one
+another.
+
+@item sections
+Each section in the input file contains the name of the section, the
+section's original address in the object file, size and alignment
+information, various flags, and pointers into other BFD data
+structures.
+
+@item symbols
+Each symbol contains a pointer to the information for the object file
+which originally defined it, its name, its value, and various flag
+bits. When a BFD back end reads in a symbol table, it relocates all
+symbols to make them relative to the base of the section where they were
+defined. Doing this ensures that each symbol points to its containing
+section. Each symbol also has a varying amount of hidden private data
+for the BFD back end. Since the symbol points to the original file, the
+private data format for that symbol is accessible. @code{ld} can
+operate on a collection of symbols of wildly different formats without
+problems.
+
+Normal global and simple local symbols are maintained on output, so an
+output file (no matter its format) will retain symbols pointing to
+functions and to global, static, and common variables. Some symbol
+information is not worth retaining; in @code{a.out}, type information is
+stored in the symbol table as long symbol names. This information would
+be useless to most COFF debuggers; the linker has command line switches
+to allow users to throw it away.
+
+There is one word of type information within the symbol, so if the
+format supports symbol type information within symbols (for example, COFF,
+IEEE, Oasys) and the type is simple enough to fit within one word
+(nearly everything but aggregates), the information will be preserved.
+
+@item relocation level
+Each canonical BFD relocation record contains a pointer to the symbol to
+relocate to, the offset of the data to relocate, the section the data
+is in, and a pointer to a relocation type descriptor. Relocation is
+performed by passing messages through the relocation type
+descriptor and the symbol pointer. Therefore, relocations can be performed
+on output data using a relocation method that is only available in one of the
+input formats. For instance, Oasys provides a byte relocation format.
+A relocation record requesting this relocation type would point
+indirectly to a routine to perform this, so the relocation may be
+performed on a byte being written to a 68k COFF file, even though 68k COFF
+has no such relocation type.
+
+@item line numbers
+Object formats can contain, for debugging purposes, some form of mapping
+between symbols, source line numbers, and addresses in the output file.
+These addresses have to be relocated along with the symbol information.
+Each symbol with an associated list of line number records points to the
+first record of the list. The head of a line number list consists of a
+pointer to the symbol, which allows finding out the address of the
+function whose line number is being described. The rest of the list is
+made up of pairs: offsets into the section and line numbers. Any format
+which can simply derive this information can pass it successfully
+between formats (COFF, IEEE and Oasys).
+@end table
diff --git a/contrib/gdb/bfd/doc/chew.c b/contrib/gdb/bfd/doc/chew.c
new file mode 100644
index 0000000..5c04404
--- /dev/null
+++ b/contrib/gdb/bfd/doc/chew.c
@@ -0,0 +1,1551 @@
+/* chew
+ Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Contributed by steve chamberlain @cygnus
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Yet another way of extracting documentation from source.
+ No, I haven't finished it yet, but I hope you people like it better
+ than the old way
+
+ sac
+
+ Basically, this is a sort of string forth, maybe we should call it
+ struth?
+
+ You define new words thus:
+ : <newword> <oldwords> ;
+
+*/
+
+/* Primitives provided by the program:
+
+ Two stacks are provided, a string stack and an integer stack.
+
+ Internal state variables:
+ internal_wanted - indicates whether `-i' was passed
+ internal_mode - user-settable
+
+ Commands:
+ push_text
+ ! - pop top of integer stack for address, pop next for value; store
+ @ - treat value on integer stack as the address of an integer; push
+ that integer on the integer stack after popping the "address"
+ hello - print "hello\n" to stdout
+ stdout - put stdout marker on TOS
+ stderr - put stderr marker on TOS
+ print - print TOS-1 on TOS (eg: "hello\n" stdout print)
+ skip_past_newline
+ catstr - fn icatstr
+ copy_past_newline - append input, up to and including newline into TOS
+ dup - fn other_dup
+ drop - discard TOS
+ idrop - ditto
+ remchar - delete last character from TOS
+ get_stuff_in_command
+ do_fancy_stuff - translate <<foo>> to @code{foo} in TOS
+ bulletize - if "o" lines found, prepend @itemize @bullet to TOS
+ and @item to each "o" line; append @end itemize
+ courierize - put @example around . and | lines, translate {* *} { }
+ exit - fn chew_exit
+ swap
+ outputdots - strip out lines without leading dots
+ paramstuff - convert full declaration into "PARAMS" form if not already
+ maybecatstr - do catstr if internal_mode == internal_wanted, discard
+ value in any case
+ translatecomments - turn {* and *} into comment delimiters
+ kill_bogus_lines - get rid of extra newlines
+ indent
+ internalmode - pop from integer stack, set `internalmode' to that value
+ print_stack_level - print current stack depth to stderr
+ strip_trailing_newlines - go ahead, guess...
+ [quoted string] - push string onto string stack
+ [word starting with digit] - push atol(str) onto integer stack
+
+ A command must be all upper-case, and alone on a line.
+
+ Foo. */
+
+
+#include <ansidecl.h>
+#include "sysdep.h"
+#include <assert.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define DEF_SIZE 5000
+#define STACK 50
+
+int internal_wanted;
+int internal_mode;
+
+int warning;
+
+/* Here is a string type ... */
+
+typedef struct buffer
+{
+ char *ptr;
+ unsigned long write_idx;
+ unsigned long size;
+} string_type;
+
+
+#ifdef __STDC__
+static void init_string_with_size (string_type *, unsigned int);
+static void init_string (string_type *);
+static int find (string_type *, char *);
+static void write_buffer (string_type *, FILE *);
+static void delete_string (string_type *);
+static char *addr (string_type *, unsigned int);
+static char at (string_type *, unsigned int);
+static void catchar (string_type *, int);
+static void overwrite_string (string_type *, string_type *);
+static void catbuf (string_type *, char *, unsigned int);
+static void cattext (string_type *, char *);
+static void catstr (string_type *, string_type *);
+static unsigned int skip_white_and_starts (string_type *, unsigned int);
+#endif
+
+
+static void DEFUN(init_string_with_size,(buffer, size),
+ string_type *buffer AND
+ unsigned int size )
+{
+ buffer->write_idx = 0;
+ buffer->size = size;
+ buffer->ptr = malloc(size);
+}
+
+static void DEFUN(init_string,(buffer),
+ string_type *buffer)
+{
+ init_string_with_size(buffer, DEF_SIZE);
+
+}
+
+static int DEFUN(find, (str, what),
+ string_type *str AND
+ char *what)
+{
+ unsigned int i;
+ char *p;
+ p = what;
+ for (i = 0; i < str->write_idx && *p; i++)
+ {
+ if (*p == str->ptr[i])
+ p++;
+ else
+ p = what;
+ }
+ return (*p == 0);
+
+}
+
+static void DEFUN(write_buffer,(buffer, f),
+ string_type *buffer AND
+ FILE *f)
+{
+ fwrite(buffer->ptr, buffer->write_idx, 1, f);
+}
+
+
+static void DEFUN(delete_string,(buffer),
+ string_type *buffer)
+{
+ free(buffer->ptr);
+}
+
+
+static char *DEFUN(addr, (buffer, idx),
+ string_type *buffer AND
+ unsigned int idx)
+{
+ return buffer->ptr + idx;
+}
+
+static char DEFUN(at,(buffer, pos),
+ string_type *buffer AND
+ unsigned int pos)
+{
+ if (pos >= buffer->write_idx)
+ return 0;
+ return buffer->ptr[pos];
+}
+
+static void DEFUN(catchar,(buffer, ch),
+ string_type *buffer AND
+ int ch)
+{
+ if (buffer->write_idx == buffer->size)
+ {
+ buffer->size *=2;
+ buffer->ptr = realloc(buffer->ptr, buffer->size);
+ }
+
+ buffer->ptr[buffer->write_idx ++ ] = ch;
+}
+
+
+static void DEFUN(overwrite_string,(dst, src),
+ string_type *dst AND
+ string_type *src)
+{
+ free(dst->ptr);
+ dst->size = src->size;
+ dst->write_idx = src->write_idx;
+ dst->ptr = src->ptr;
+}
+
+static void DEFUN(catbuf,(buffer, buf, len),
+ string_type *buffer AND
+ char *buf AND
+ unsigned int len)
+{
+ if (buffer->write_idx + len >= buffer->size)
+ {
+ while (buffer->write_idx + len >= buffer->size)
+ buffer->size *= 2;
+ buffer->ptr = realloc (buffer->ptr, buffer->size);
+ }
+ memcpy (buffer->ptr + buffer->write_idx, buf, len);
+ buffer->write_idx += len;
+}
+
+static void DEFUN(cattext,(buffer, string),
+ string_type *buffer AND
+ char *string)
+{
+ catbuf (buffer, string, (unsigned int) strlen (string));
+}
+
+static void DEFUN(catstr,(dst, src),
+ string_type *dst AND
+ string_type *src)
+{
+ catbuf (dst, src->ptr, src->write_idx);
+}
+
+
+static unsigned int
+DEFUN(skip_white_and_stars,(src, idx),
+ string_type *src AND
+ unsigned int idx)
+{
+ char c;
+ while ((c = at(src,idx)),
+ isspace (c)
+ || (c == '*'
+ /* Don't skip past end-of-comment or star as first
+ character on its line. */
+ && at(src,idx +1) != '/'
+ && at(src,idx -1) != '\n'))
+ idx++;
+ return idx;
+}
+
+/***********************************************************************/
+
+
+string_type stack[STACK];
+string_type *tos;
+
+unsigned int idx = 0; /* Pos in input buffer */
+string_type *ptr; /* and the buffer */
+typedef void (*stinst_type)();
+stinst_type *pc;
+stinst_type sstack[STACK];
+stinst_type *ssp = &sstack[0];
+long istack[STACK];
+long *isp = &istack[0];
+
+typedef int *word_type;
+
+
+
+struct dict_struct
+{
+ char *word;
+ struct dict_struct *next;
+ stinst_type *code;
+ int code_length;
+ int code_end;
+ int var;
+
+};
+typedef struct dict_struct dict_type;
+#define WORD(x) static void x()
+
+static void
+die (msg)
+ char *msg;
+{
+ fprintf (stderr, "%s\n", msg);
+ exit (1);
+}
+
+static void
+check_range ()
+{
+ if (tos < stack)
+ die ("underflow in string stack");
+ if (tos >= stack + STACK)
+ die ("overflow in string stack");
+}
+
+static void
+icheck_range ()
+{
+ if (isp < istack)
+ die ("underflow in integer stack");
+ if (isp >= istack + STACK)
+ die ("overflow in integer stack");
+}
+
+#ifdef __STDC__
+static void exec (dict_type *);
+static void call (void);
+static void remchar (void), strip_trailing_newlines (void), push_number (void);
+static void push_text (void);
+static void remove_noncomments (string_type *, string_type *);
+static void print_stack_level (void);
+static void paramstuff (void), translatecomments (void), manglecomments (void);
+static void outputdots (void), courierize (void), bulletize (void);
+static void do_fancy_stuff (void);
+static int iscommand (string_type *, unsigned int);
+static int copy_past_newline (string_type *, unsigned int, string_type *);
+static void icopy_past_newline (void), kill_bogus_lines (void), indent (void);
+static void get_stuff_in_command (void), swap (void), other_dup (void);
+static void drop (void), idrop (void);
+static void icatstr (void), skip_past_newline (void), internalmode (void);
+static void maybecatstr (void);
+static char *nextword (char *, char **);
+dict_type *lookup_word (char *);
+static void perform (void);
+dict_type *newentry (char *);
+unsigned int add_to_definition (dict_type *, stinst_type);
+void add_intrinsic (char *, void (*)());
+void add_var (char *);
+void compile (char *);
+static void bang (void);
+static void atsign (void);
+static void hello (void);
+static void stdout_ (void);
+static void stderr_ (void);
+static void print (void);
+static void read_in (string_type *, FILE *);
+static void usage (void);
+static void chew_exit (void);
+#endif
+
+static void DEFUN(exec,(word),
+ dict_type *word)
+{
+ pc = word->code;
+ while (*pc)
+ (*pc)();
+}
+WORD(call)
+{
+ stinst_type *oldpc = pc;
+ dict_type *e;
+ e = (dict_type *)(pc [1]);
+ exec(e);
+ pc = oldpc + 2;
+
+}
+
+WORD(remchar)
+{
+ if (tos->write_idx)
+ tos->write_idx--;
+ pc++;
+}
+
+static void
+strip_trailing_newlines ()
+{
+ while ((isspace (at (tos, tos->write_idx - 1))
+ || at (tos, tos->write_idx - 1) == '\n')
+ && tos->write_idx > 0)
+ tos->write_idx--;
+ pc++;
+}
+
+WORD(push_number)
+{
+ isp++;
+ icheck_range ();
+ pc++;
+ *isp = (long)(*pc);
+ pc++;
+}
+
+WORD(push_text)
+{
+ tos++;
+ check_range ();
+ init_string(tos);
+ pc++;
+ cattext(tos,*((char **)pc));
+ pc++;
+
+}
+
+
+/* This function removes everything not inside comments starting on
+ the first char of the line from the string, also when copying
+ comments, removes blank space and leading *'s.
+ Blank lines are turned into one blank line. */
+
+static void
+DEFUN(remove_noncomments,(src,dst),
+ string_type *src AND
+ string_type *dst)
+{
+ unsigned int idx = 0;
+
+ while (at(src,idx))
+ {
+ /* Now see if we have a comment at the start of the line */
+ if (at(src,idx) == '\n'
+ && at(src,idx+1) == '/'
+ && at(src,idx+2) == '*')
+ {
+ idx+=3;
+
+ idx = skip_white_and_stars(src,idx);
+
+ /* Remove leading dot */
+ if (at(src, idx) == '.')
+ idx++;
+
+ /* Copy to the end of the line, or till the end of the
+ comment */
+ while (at(src, idx))
+ {
+ if (at(src, idx) == '\n')
+ {
+ /* end of line, echo and scrape of leading blanks */
+ if (at(src,idx +1) == '\n')
+ catchar(dst,'\n');
+ catchar(dst,'\n');
+ idx++;
+ idx = skip_white_and_stars(src, idx);
+ }
+ else if (at(src, idx) == '*' && at(src,idx+1) == '/')
+ {
+ idx +=2 ;
+ cattext(dst,"\nENDDD\n");
+ break;
+ }
+ else
+ {
+ catchar(dst, at(src, idx));
+ idx++;
+ }
+ }
+ }
+ else idx++;
+ }
+}
+
+static void
+print_stack_level ()
+{
+ fprintf (stderr, "current string stack depth = %d, ", tos - stack);
+ fprintf (stderr, "current integer stack depth = %d\n", isp - istack);
+ pc++;
+}
+
+/* turn:
+ foobar name(stuff);
+ into:
+ foobar
+ name PARAMS ((stuff));
+ and a blank line.
+ */
+
+static void
+DEFUN_VOID(paramstuff)
+{
+ unsigned int openp;
+ unsigned int fname;
+ unsigned int idx;
+ string_type out;
+ init_string(&out);
+
+
+ /* make sure that it's not already param'd or proto'd */
+ if(find(tos,"PARAMS") || find(tos,"PROTO") || !find(tos,"(")) {
+ catstr(&out,tos);
+ }
+ else
+ {
+ /* Find the open paren */
+ for (openp = 0; at(tos, openp) != '(' && at(tos,openp); openp++)
+ ;
+
+ fname = openp;
+ /* Step back to the fname */
+ fname--;
+ while (fname && isspace(at(tos, fname)))
+ fname --;
+ while (fname && !isspace(at(tos,fname)) && at(tos,fname) != '*')
+ fname--;
+
+ fname++;
+
+ for (idx = 0; idx < fname; idx++) /* Output type */
+ {
+ catchar(&out, at(tos,idx));
+ }
+
+ cattext(&out, "\n"); /* Insert a newline between type and fnname */
+
+ for (idx = fname; idx < openp; idx++) /* Output fnname */
+ {
+ catchar(&out, at(tos,idx));
+ }
+
+ cattext(&out," PARAMS (");
+
+ while (at(tos,idx) && at(tos,idx) !=';')
+ {
+ catchar(&out, at(tos, idx));
+ idx++;
+ }
+ cattext(&out,");\n\n");
+ }
+ overwrite_string(tos, &out);
+ pc++;
+
+}
+
+
+
+/* turn {*
+ and *} into comments */
+
+WORD(translatecomments)
+{
+ unsigned int idx = 0;
+ string_type out;
+ init_string(&out);
+
+ while (at(tos, idx))
+ {
+ if (at(tos,idx) == '{' && at(tos,idx+1) =='*')
+ {
+ cattext(&out,"/*");
+ idx+=2;
+ }
+ else if (at(tos,idx) == '*' && at(tos,idx+1) =='}')
+ {
+ cattext(&out,"*/");
+ idx+=2;
+ }
+ else
+ {
+ catchar(&out, at(tos, idx));
+ idx++;
+ }
+ }
+
+
+ overwrite_string(tos, &out);
+
+ pc++;
+
+}
+
+/* turn everything not starting with a . into a comment */
+
+WORD(manglecomments)
+{
+ unsigned int idx = 0;
+ string_type out;
+ init_string(&out);
+
+ while (at(tos, idx))
+ {
+ if (at(tos,idx) == '\n' && at(tos,idx+1) =='*')
+ {
+ cattext(&out," /*");
+ idx+=2;
+ }
+ else if (at(tos,idx) == '*' && at(tos,idx+1) =='}')
+ {
+ cattext(&out,"*/");
+ idx+=2;
+ }
+ else
+ {
+ catchar(&out, at(tos, idx));
+ idx++;
+ }
+ }
+
+
+ overwrite_string(tos, &out);
+
+ pc++;
+
+}
+
+/* Mod tos so that only lines with leading dots remain */
+static void
+DEFUN_VOID(outputdots)
+{
+ unsigned int idx = 0;
+ string_type out;
+ init_string(&out);
+
+ while (at(tos, idx))
+ {
+ if (at(tos, idx) == '\n' && at(tos, idx+1) == '.')
+ {
+ char c, c2;
+ idx += 2;
+
+ while ((c = at(tos, idx)) && c != '\n')
+ {
+ if (c == '{' && at(tos,idx+1) =='*')
+ {
+ cattext(&out," /*");
+ idx+=2;
+ }
+ else if (c == '*' && at(tos,idx+1) =='}')
+ {
+ cattext(&out,"*/");
+ idx+=2;
+ }
+ else
+ {
+ catchar(&out, c);
+ idx++;
+ }
+ }
+ catchar(&out,'\n');
+ }
+ else
+ {
+ idx++;
+ }
+ }
+
+ overwrite_string(tos, &out);
+ pc++;
+
+}
+
+/* Find lines starting with . and | and put example around them on tos */
+WORD(courierize)
+{
+ string_type out;
+ unsigned int idx = 0;
+ int command = 0;
+
+ init_string(&out);
+
+ while (at(tos, idx))
+ {
+ if (at(tos, idx) == '\n'
+ && (at(tos, idx +1 ) == '.'
+ || at(tos,idx+1) == '|'))
+ {
+ cattext(&out,"\n@example\n");
+ do
+ {
+ idx += 2;
+
+ while (at(tos, idx) && at(tos, idx)!='\n')
+ {
+ if (at(tos,idx)=='{' && at(tos,idx+1) =='*')
+ {
+ cattext(&out," /*");
+ idx+=2;
+ }
+ else if (at(tos,idx)=='*' && at(tos,idx+1) =='}')
+ {
+ cattext(&out,"*/");
+ idx+=2;
+ }
+ else if (at(tos,idx) == '{' && !command)
+ {
+ cattext(&out,"@{");
+ idx++;
+ }
+ else if (at(tos,idx) == '}' && !command)
+ {
+ cattext(&out,"@}");
+ idx++;
+ }
+ else
+ {
+ if (at(tos,idx) == '@')
+ command = 1;
+ else if (isspace(at(tos,idx)) || at(tos,idx) == '}')
+ command = 0;
+ catchar(&out, at(tos, idx));
+ idx++;
+ }
+
+ }
+ catchar(&out,'\n');
+ }
+ while (at(tos, idx) == '\n'
+ && (at(tos, idx+1) == '.')
+ || (at(tos,idx+1) == '|'));
+ cattext(&out,"@end example");
+ }
+ else
+ {
+ catchar(&out, at(tos, idx));
+ idx++;
+ }
+ }
+
+ overwrite_string(tos, &out);
+ pc++;
+
+
+}
+
+/* Finds any lines starting with "o ", if there are any, then turns
+ on @itemize @bullet, and @items each of them. Then ends with @end
+ itemize, inplace at TOS*/
+
+
+WORD(bulletize)
+{
+ unsigned int idx = 0;
+ int on = 0;
+ string_type out;
+ init_string(&out);
+
+ while (at(tos, idx)) {
+ if (at(tos, idx) == '@' &&
+ at(tos, idx+1) == '*')
+ {
+ cattext(&out,"*");
+ idx+=2;
+ }
+
+else
+ if (at(tos, idx) == '\n' &&
+ at(tos, idx+1) == 'o' &&
+ isspace(at(tos, idx +2)))
+ {
+ if (!on)
+ {
+ cattext(&out,"\n@itemize @bullet\n");
+ on = 1;
+
+ }
+ cattext(&out,"\n@item\n");
+ idx+=3;
+ }
+ else
+ {
+ catchar(&out, at(tos, idx));
+ if (on && at(tos, idx) == '\n' &&
+ at(tos, idx+1) == '\n' &&
+ at(tos, idx+2) != 'o')
+ {
+ cattext(&out, "@end itemize");
+ on = 0;
+ }
+ idx++;
+
+ }
+ }
+ if (on)
+ {
+ cattext(&out,"@end itemize\n");
+ }
+
+ delete_string(tos);
+ *tos = out;
+ pc++;
+
+}
+
+/* Turn <<foo>> into @code{foo} in place at TOS*/
+
+
+WORD(do_fancy_stuff)
+{
+ unsigned int idx = 0;
+ string_type out;
+ init_string(&out);
+ while (at(tos, idx))
+ {
+ if (at(tos, idx) == '<'
+ && at(tos, idx+1) == '<'
+ && !isspace(at(tos,idx + 2)))
+ {
+ /* This qualifies as a << startup */
+ idx +=2;
+ cattext(&out,"@code{");
+ while(at(tos,idx) &&
+ at(tos,idx) != '>' )
+ {
+ catchar(&out, at(tos, idx));
+ idx++;
+
+ }
+ cattext(&out,"}");
+ idx+=2;
+ }
+ else
+ {
+ catchar(&out, at(tos, idx));
+ idx++;
+ }
+ }
+ delete_string(tos);
+ *tos = out;
+ pc++;
+
+}
+/* A command is all upper case,and alone on a line */
+static int
+DEFUN( iscommand,(ptr, idx),
+ string_type *ptr AND
+ unsigned int idx)
+{
+ unsigned int len = 0;
+ while (at(ptr,idx)) {
+ if (isupper(at(ptr,idx)) || at(ptr,idx) == ' ' ||
+ at(ptr,idx) == '_')
+ {
+ len++;
+ idx++;
+ }
+ else if(at(ptr,idx) == '\n')
+ {
+ if (len > 3) return 1;
+ return 0;
+ }
+ else return 0;
+ }
+ return 0;
+
+}
+
+
+DEFUN(copy_past_newline,(ptr, idx, dst),
+ string_type *ptr AND
+ unsigned int idx AND
+ string_type *dst)
+{
+ while (at(ptr, idx) && at(ptr, idx) != '\n')
+ {
+ catchar(dst, at(ptr, idx));
+ idx++;
+
+ }
+ catchar(dst, at(ptr, idx));
+ idx++;
+ return idx;
+
+}
+
+WORD(icopy_past_newline)
+{
+ tos++;
+ check_range ();
+ init_string(tos);
+ idx = copy_past_newline(ptr, idx, tos);
+ pc++;
+}
+
+/* indent
+ Take the string at the top of the stack, do some prettying */
+
+
+WORD(kill_bogus_lines)
+{
+ int sl ;
+
+ int nl = 0;
+ int idx = 0;
+ int c;
+ int dot = 0 ;
+
+ string_type out;
+ init_string(&out);
+ /* Drop leading nl */
+ while (at(tos,idx) == '\n')
+ {
+ idx++;
+ }
+ c = idx;
+
+ /* Find the last char */
+ while (at(tos,idx))
+ {
+ idx++;
+ }
+
+ /* find the last non white before the nl */
+ idx--;
+
+ while (idx && isspace(at(tos,idx)))
+ idx--;
+ idx++;
+
+ /* Copy buffer upto last char, but blank lines before and after
+ dots don't count */
+ sl = 1;
+
+ while (c < idx)
+ {
+ if (at(tos,c) == '\n'
+ && at(tos,c+1) == '\n'
+ && at(tos,c+2) == '.')
+ {
+ /* Ignore two newlines before a dot*/
+ c++;
+ }
+ else if (at(tos,c) == '.' && sl)
+ {
+ /* remember that this line started with a dot */
+ dot=2;
+ }
+ else if (at(tos,c) == '\n'
+ && at(tos,c+1) == '\n'
+ && dot)
+ {
+ c++;
+ /* Ignore two newlines when last line was dot */
+ }
+
+ catchar(&out, at(tos,c));
+ if (at(tos,c) == '\n')
+ {
+ sl = 1;
+
+ if (dot == 2)dot=1;else dot = 0;
+ }
+
+ c++;
+
+ }
+
+ /* Append nl*/
+ catchar(&out, '\n');
+ pc++;
+ delete_string(tos);
+ *tos = out;
+
+
+}
+
+WORD(indent)
+{
+ string_type out;
+ int tab = 0;
+ int idx = 0;
+ int ol =0;
+ init_string(&out);
+ while (at(tos,idx)) {
+ switch (at(tos,idx))
+ {
+ case '\n':
+ cattext(&out,"\n");
+ idx++;
+ if (tab)
+ {
+ cattext(&out," ");
+ }
+ ol = 0;
+ break;
+ case '(':
+ tab++;
+ if (ol == 0)
+ cattext(&out," ");
+ idx++;
+ cattext(&out,"(");
+ ol = 1;
+ break;
+ case ')':
+ tab--;
+ cattext(&out,")");
+ idx++;
+ ol=1;
+
+ break;
+ default:
+ catchar(&out,at(tos,idx));
+ ol=1;
+
+ idx++;
+ break;
+ }
+ }
+
+ pc++;
+ delete_string(tos);
+ *tos = out;
+
+}
+
+
+WORD(get_stuff_in_command)
+{
+ tos++;
+ check_range ();
+ init_string(tos);
+
+ while (at(ptr, idx)) {
+ if (iscommand(ptr, idx)) break;
+ idx = copy_past_newline(ptr, idx, tos);
+ }
+ pc++;
+}
+
+WORD(swap)
+{
+ string_type t;
+
+ t = tos[0];
+ tos[0] = tos[-1];
+ tos[-1] =t;
+ pc++;
+
+}
+
+WORD(other_dup)
+{
+ tos++;
+ check_range ();
+ init_string(tos);
+ catstr(tos, tos-1);
+ pc++;
+}
+
+WORD(drop)
+{
+ tos--;
+ check_range ();
+ pc++;
+}
+
+WORD(idrop)
+{
+ isp--;
+ icheck_range ();
+ pc++;
+}
+
+WORD(icatstr)
+{
+ tos--;
+ check_range ();
+ catstr(tos, tos+1);
+ delete_string(tos+1);
+ pc++;
+}
+
+WORD(skip_past_newline)
+{
+ while (at(ptr,idx)
+ && at(ptr,idx) != '\n')
+ idx++;
+ idx++;
+ pc++;
+}
+
+
+WORD(internalmode)
+{
+ internal_mode = *(isp);
+ isp--;
+ icheck_range ();
+ pc++;
+}
+
+WORD(maybecatstr)
+{
+ if (internal_wanted == internal_mode)
+ {
+ catstr(tos-1, tos);
+ }
+ delete_string(tos);
+ tos--;
+ check_range ();
+ pc++;
+}
+
+char *
+DEFUN(nextword,(string, word),
+ char *string AND
+ char **word)
+{
+ char *word_start;
+ int idx;
+ char *dst;
+ char *src;
+
+ int length = 0;
+
+ while (isspace(*string) || *string == '-') {
+ if (*string == '-')
+ {
+ while (*string && *string != '\n')
+ string++;
+
+ }
+ else {
+ string++;
+ }
+ }
+ if (!*string) return 0;
+
+ word_start = string;
+ if (*string == '"')
+ {
+ do
+ {
+ string++;
+ length++;
+ if (*string == '\\')
+ {
+ string += 2;
+ length += 2;
+ }
+ }
+ while (*string != '"');
+ }
+ else
+ {
+ while (!isspace(*string))
+ {
+ string++;
+ length++;
+
+ }
+ }
+
+ *word = malloc(length + 1);
+
+ dst = *word;
+ src = word_start;
+
+
+ for (idx= 0; idx < length; idx++)
+ {
+ if (src[idx] == '\\')
+ switch (src[idx+1])
+ {
+ case 'n':
+ *dst++ = '\n';
+ idx++;
+ break;
+ case '"':
+ case '\\':
+ *dst++ = src[idx+1];
+ idx++;
+ break;
+ default:
+ *dst++ = '\\';
+ break;
+ }
+ else
+ *dst++ = src[idx];
+ }
+ *dst++ = 0;
+
+
+
+
+
+ if(*string)
+ return string + 1;
+ else
+ return 0;
+
+}
+dict_type *root;
+dict_type *
+DEFUN(lookup_word,(word),
+ char *word)
+{
+ dict_type *ptr = root;
+ while (ptr) {
+ if (strcmp(ptr->word, word) == 0) return ptr;
+ ptr = ptr->next;
+
+ }
+ if (warning)
+ fprintf(stderr,"Can't find %s\n",word);
+ return 0;
+
+
+}
+
+static void DEFUN_VOID(perform)
+{
+ tos = stack;
+
+ while (at(ptr, idx)) {
+ /* It's worth looking through the command list */
+ if (iscommand(ptr, idx))
+ {
+ unsigned int i;
+ int found = 0;
+
+ char *next;
+ dict_type *word ;
+
+ (void) nextword(addr(ptr, idx), &next);
+
+
+ word = lookup_word(next);
+
+
+
+
+ if (word)
+ {
+ exec(word);
+ }
+ else
+ {
+ if (warning)
+ fprintf(stderr,"warning, %s is not recognised\n", next);
+ skip_past_newline();
+ }
+
+ }
+ else skip_past_newline();
+
+ }
+}
+
+dict_type *
+DEFUN(newentry,(word),
+ char *word)
+{
+ dict_type *new = (dict_type *)malloc(sizeof(dict_type));
+ new->word = word;
+ new->next = root;
+ root = new;
+ new->code = (stinst_type *)malloc(sizeof(stinst_type ));
+ new->code_length = 1;
+ new->code_end = 0;
+ return new;
+
+}
+
+
+unsigned int
+DEFUN(add_to_definition,(entry, word),
+ dict_type *entry AND
+ stinst_type word)
+{
+ if (entry->code_end == entry->code_length)
+ {
+ entry->code_length += 2;
+ entry->code =
+ (stinst_type *) realloc((char *)(entry->code),
+ entry->code_length *sizeof(word_type));
+ }
+ entry->code[entry->code_end] = word;
+
+return entry->code_end++;
+}
+
+
+
+
+
+
+
+void
+DEFUN(add_intrinsic,(name, func),
+ char *name AND
+ void (*func)())
+{
+ dict_type *new = newentry(name);
+ add_to_definition(new, func);
+ add_to_definition(new, 0);
+}
+
+void
+DEFUN(add_var,(name),
+ char *name)
+{
+ dict_type *new = newentry(name);
+ add_to_definition(new, push_number);
+ add_to_definition(new, (stinst_type)(&(new->var)));
+ add_to_definition(new,0);
+}
+
+
+void
+DEFUN(compile, (string),
+ char *string)
+{
+ int jstack[STACK];
+ int *jptr = jstack;
+ /* add words to the dictionary */
+ char *word;
+ string = nextword(string, &word);
+ while (string && *string && word[0])
+ {
+ if (strcmp(word,"var")==0)
+ {
+ string=nextword(string, &word);
+
+ add_var(word);
+ string=nextword(string, &word);
+ }
+else
+
+ if (word[0] == ':')
+ {
+ dict_type *ptr;
+ /* Compile a word and add to dictionary */
+ string = nextword(string, &word);
+
+ ptr = newentry(word);
+ string = nextword(string, &word);
+ while (word[0] != ';' )
+ {
+ switch (word[0])
+ {
+ case '"':
+ /* got a string, embed magic push string
+ function */
+ add_to_definition(ptr, push_text);
+ add_to_definition(ptr, (stinst_type)(word+1));
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* Got a number, embedd the magic push number
+ function */
+ add_to_definition(ptr, push_number);
+ add_to_definition(ptr, (stinst_type)atol(word));
+ break;
+ default:
+ add_to_definition(ptr, call);
+ add_to_definition(ptr, (stinst_type)lookup_word(word));
+ }
+
+ string = nextword(string, &word);
+ }
+ add_to_definition(ptr,0);
+ string = nextword(string, &word);
+ }
+ else
+ {
+ fprintf(stderr,"syntax error at %s\n",string-1);
+ }
+ }
+
+}
+
+
+static void DEFUN_VOID(bang)
+{
+ *(long *)((isp[0])) = isp[-1];
+ isp-=2;
+ icheck_range ();
+ pc++;
+}
+
+WORD(atsign)
+{
+ isp[0] = *(long *)(isp[0]);
+ pc++;
+}
+
+WORD(hello)
+{
+ printf("hello\n");
+ pc++;
+}
+
+WORD(stdout_)
+{
+ isp++;
+ icheck_range ();
+ *isp = 1;
+ pc++;
+}
+
+WORD(stderr_)
+{
+ isp++;
+ icheck_range ();
+ *isp = 2;
+ pc++;
+}
+
+WORD(print)
+{
+ if (*isp == 1)
+ write_buffer (tos, stdout);
+ else if (*isp == 2)
+ write_buffer (tos, stderr);
+ else
+ fprintf (stderr, "print: illegal print destination `%d'\n", *isp);
+ isp--;
+ tos--;
+ icheck_range ();
+ check_range ();
+ pc++;
+}
+
+
+static void DEFUN(read_in, (str, file),
+ string_type *str AND
+ FILE *file)
+{
+ char buff[10000];
+ unsigned int r;
+ do
+ {
+ r = fread(buff, 1, sizeof(buff), file);
+ catbuf(str, buff, r);
+ }
+ while (r);
+ buff[0] = 0;
+
+ catbuf(str, buff,1);
+}
+
+
+static void DEFUN_VOID(usage)
+{
+ fprintf(stderr,"usage: -[d|i|g] <file >file\n");
+ exit(33);
+}
+
+/* There is no reliable way to declare exit. Sometimes it returns
+ int, and sometimes it returns void. Sometimes it changes between
+ OS releases. Trying to get it declared correctly in the hosts file
+ is a pointless waste of time. */
+
+static void
+chew_exit ()
+{
+ exit (0);
+}
+
+int DEFUN(main,(ac,av),
+int ac AND
+char *av[])
+{
+ unsigned int i;
+ string_type buffer;
+ string_type pptr;
+
+ init_string(&buffer);
+ init_string(&pptr);
+ init_string(stack+0);
+ tos=stack+1;
+ ptr = &pptr;
+
+ add_intrinsic("push_text", push_text);
+ add_intrinsic("!", bang);
+ add_intrinsic("@", atsign);
+ add_intrinsic("hello",hello);
+ add_intrinsic("stdout",stdout_);
+ add_intrinsic("stderr",stderr_);
+ add_intrinsic("print",print);
+ add_intrinsic("skip_past_newline", skip_past_newline );
+ add_intrinsic("catstr", icatstr );
+ add_intrinsic("copy_past_newline", icopy_past_newline );
+ add_intrinsic("dup", other_dup );
+ add_intrinsic("drop", drop);
+ add_intrinsic("idrop", idrop);
+ add_intrinsic("remchar", remchar );
+ add_intrinsic("get_stuff_in_command", get_stuff_in_command );
+ add_intrinsic("do_fancy_stuff", do_fancy_stuff );
+ add_intrinsic("bulletize", bulletize );
+ add_intrinsic("courierize", courierize );
+ /* If the following line gives an error, exit() is not declared in the
+ ../hosts/foo.h file for this host. Fix it there, not here! */
+ /* No, don't fix it anywhere; see comment on chew_exit--Ian Taylor. */
+ add_intrinsic("exit", chew_exit );
+ add_intrinsic("swap", swap );
+ add_intrinsic("outputdots", outputdots );
+ add_intrinsic("paramstuff", paramstuff );
+ add_intrinsic("maybecatstr", maybecatstr );
+ add_intrinsic("translatecomments", translatecomments );
+ add_intrinsic("kill_bogus_lines", kill_bogus_lines);
+ add_intrinsic("indent", indent);
+ add_intrinsic("internalmode", internalmode);
+ add_intrinsic("print_stack_level", print_stack_level);
+ add_intrinsic("strip_trailing_newlines", strip_trailing_newlines);
+
+ /* Put a nl at the start */
+ catchar(&buffer,'\n');
+
+ read_in(&buffer, stdin);
+ remove_noncomments(&buffer, ptr);
+ for (i= 1; i < ac; i++)
+ {
+ if (av[i][0] == '-')
+ {
+ if (av[i][1] == 'f')
+ {
+ string_type b;
+ FILE *f;
+ init_string(&b);
+
+ f = fopen(av[i+1],"r");
+ if (!f)
+ {
+ fprintf(stderr,"Can't open the input file %s\n",av[i+1]);
+ return 33;
+ }
+
+ read_in(&b, f);
+ compile(b.ptr);
+ perform();
+ }
+ else if (av[i][1] == 'i')
+ {
+ internal_wanted = 1;
+ }
+ else if (av[i][1] == 'w')
+ {
+ warning = 1;
+ }
+ }
+ }
+ write_buffer(stack+0, stdout);
+ if (tos != stack)
+ {
+ fprintf (stderr, "finishing with current stack level %d\n", tos - stack);
+ return 1;
+ }
+ return 0;
+}
diff --git a/contrib/gdb/bfd/doc/doc.str b/contrib/gdb/bfd/doc/doc.str
new file mode 100644
index 0000000..9368599
--- /dev/null
+++ b/contrib/gdb/bfd/doc/doc.str
@@ -0,0 +1,158 @@
+: DOCDD
+ skip_past_newline
+ get_stuff_in_command kill_bogus_lines catstr
+ ;
+
+: ENDDD
+ skip_past_newline
+ ;
+
+: EXAMPLE
+ skip_past_newline
+ get_stuff_in_command kill_bogus_lines do_fancy_stuff translatecomments
+ courierize catstr
+
+ ;
+
+: INODE
+ "@node " catstr skip_past_newline copy_past_newline catstr
+ ;
+
+: CODE_FRAGMENT
+ EXAMPLE
+ ;
+
+: COMMENT
+ skip_past_newline
+ get_stuff_in_command
+ drop
+ ;
+
+: SYNOPSIS
+ skip_past_newline
+ "@strong{Synopsis}\n" catstr
+ "@example\n" catstr
+ get_stuff_in_command
+ kill_bogus_lines
+ indent
+ catstr
+ "@end example\n" catstr
+
+ ;
+
+: func
+ "@findex " - a
+ skip_past_newline
+ copy_past_newline
+ dup - a x x
+ "@subsubsection @code{" - a x x b
+ swap
+ remchar
+ "}\n" - a x b x c
+ catstr catstr catstr catstr catstr
+ ;
+
+: FUNCTION
+ "@findex " - a
+ skip_past_newline
+ copy_past_newline
+ dup - a x x
+ "@subsubsection @code{" - a x x b
+ swap
+ remchar
+ "}\n" - a x b x c
+ catstr catstr catstr catstr catstr
+ ;
+
+: bodytext
+ get_stuff_in_command
+ bulletize
+ kill_bogus_lines
+ do_fancy_stuff
+ courierize
+ catstr
+ "@*\n" catstr
+ ;
+
+: asection
+ skip_past_newline
+ catstr
+ copy_past_newline
+ do_fancy_stuff catstr
+ bodytext
+ ;
+
+: SECTION
+ "@section " asection ;
+
+: SUBSECTION
+ "@subsection " asection ;
+
+: SUBSUBSECTION
+ "@subsubsection " asection ;
+
+: subhead
+ skip_past_newline
+ bodytext
+ ;
+
+
+
+
+: DESCRIPTION
+ "@strong{Description}@*\n" catstr subhead ;
+
+: RETURNS
+ "@strong{Returns}@*\n" catstr subhead ;
+
+: INTERNAL_FUNCTION
+ func ;
+
+
+: INTERNAL_DEFINITION
+ func ;
+
+
+: INTERNAL
+ func ;
+
+: TYPEDEF
+ FUNCTION ;
+
+: SENUM
+ skip_past_newline
+ "Here are the possible values for @code{enum "
+ copy_past_newline remchar catstr
+ "}:\n\n" catstr catstr
+ ;
+: ENUM
+ skip_past_newline
+ "@deffn {} "
+ copy_past_newline catstr catstr
+ ;
+: ENUMX
+ skip_past_newline
+ "@deffnx {} "
+ copy_past_newline catstr
+ catstr
+ ;
+: ENUMEQ
+ skip_past_newline
+ "@deffn {} "
+ copy_past_newline catstr catstr
+ skip_past_newline
+ ;
+: ENUMEQX
+ skip_past_newline
+ "@deffnx {} "
+ copy_past_newline catstr
+ catstr
+ skip_past_newline
+ ;
+: ENUMDOC
+ skip_past_newline
+ get_stuff_in_command
+ strip_trailing_newlines
+ catstr
+ "\n@end deffn\n" catstr
+ ;
diff --git a/contrib/gdb/bfd/doc/proto.str b/contrib/gdb/bfd/doc/proto.str
new file mode 100644
index 0000000..8431c16
--- /dev/null
+++ b/contrib/gdb/bfd/doc/proto.str
@@ -0,0 +1,135 @@
+
+: SYNOPSIS
+ skip_past_newline
+ get_stuff_in_command
+ paramstuff
+ indent
+ maybecatstr
+;
+
+: ignore
+ skip_past_newline
+ get_stuff_in_command
+ outputdots
+ maybecatstr
+ ;
+
+: CODE_FRAGMENT
+ ignore ;
+
+: external
+ 0 internalmode ignore ;
+
+: internal
+ 1 internalmode ignore ;
+
+- input stack { a b } output b if internal, a if external
+: ifinternal
+ "" swap 1 internalmode maybecatstr
+ swap
+ "" swap 0 internalmode maybecatstr
+ catstr
+ ;
+
+- Put note in output string, regardless of internal mode.
+: COMMENT
+ skip_past_newline
+ get_stuff_in_command
+ translatecomments
+ catstr
+ ;
+
+- SENUM enum-type-name
+- ENUM enum-name
+- ENUMX addl-enum-name
+- ENUMDOC doc for preceding enums
+- ENDSENUM max-enum-name
+
+: make_enum_header
+ dup
+ "enum " swap catstr
+ " {\n" catstr
+ swap " _dummy_first_" swap catstr catstr
+ ",\n" catstr
+ ;
+: make_string_table_header
+ dup
+ "#ifdef _BFD_MAKE_TABLE_" swap catstr swap
+ "\n\nstatic const char *const " swap catstr catstr
+ "_names[] = { \"@@uninitialized@@\",\n" catstr
+ ;
+: SENUM
+ skip_past_newline
+ copy_past_newline
+ remchar
+ dup
+ make_enum_header
+ swap
+ make_string_table_header
+ ifinternal
+ catstr
+ get_stuff_in_command catstr
+ translatecomments ;
+: ENDSENUM
+ skip_past_newline
+ copy_past_newline strip_trailing_newlines
+ dup
+ " " swap catstr " };\n" catstr swap
+ " \"@@overflow: " swap catstr "@@\",\n};\n#endif\n\n" catstr
+ ifinternal
+ catstr
+ ;
+: make_enumerator
+ " " swap catstr
+ ",\n" catstr
+ ;
+: make_enumerator_string
+ " \"" swap catstr
+ "\",\n" catstr
+ ;
+: ENUM
+ skip_past_newline
+ copy_past_newline
+ remchar
+ dup
+ make_enumerator
+ swap
+ make_enumerator_string
+ ifinternal
+ ;
+: ENUMX ENUM catstr ;
+: ENUMEQ
+ skip_past_newline
+ "#define "
+ copy_past_newline remchar
+ catstr
+ " "
+ catstr
+ copy_past_newline
+ catstr
+ "" swap 0 internalmode maybecatstr
+ ;
+: ENUMEQX ENUMEQ catstr ;
+: ENUMDOC
+ skip_past_newline
+ get_stuff_in_command
+ strip_trailing_newlines
+ "\n{* " swap catstr " *}\n" catstr
+ translatecomments
+ - discard it if we're doing internal mode
+ "" swap 0 internalmode maybecatstr
+ swap
+ catstr catstr
+ ;
+: ENDDD external ;
+: SECTION ignore ;
+: SUBSECTION ignore ;
+: SUBSUBSECTION ignore ;
+: INTERNAL_DEFINITION internal ;
+: DESCRIPTION ignore ;
+: FUNCTION external ;
+: RETURNS ignore ;
+: TYPEDEF external ;
+: INTERNAL_FUNCTION internal ;
+: INTERNAL internal ;
+: INODE ignore ;
diff --git a/contrib/gdb/bfd/ecoff.c b/contrib/gdb/bfd/ecoff.c
new file mode 100644
index 0000000..e219ff7
--- /dev/null
+++ b/contrib/gdb/bfd/ecoff.c
@@ -0,0 +1,4740 @@
+/* Generic ECOFF (Extended-COFF) routines.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Original version by Per Bothner.
+ Full support added by Ian Lance Taylor, ian@cygnus.com.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "aout/ar.h"
+#include "aout/ranlib.h"
+#include "aout/stab_gnu.h"
+
+/* FIXME: We need the definitions of N_SET[ADTB], but aout64.h defines
+ some other stuff which we don't want and which conflicts with stuff
+ we do want. */
+#include "libaout.h"
+#include "aout/aout64.h"
+#undef N_ABS
+#undef exec_hdr
+#undef obj_sym_filepos
+
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "coff/symconst.h"
+#include "coff/ecoff.h"
+#include "libcoff.h"
+#include "libecoff.h"
+
+/* Prototypes for static functions. */
+
+static int ecoff_get_magic PARAMS ((bfd *abfd));
+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, int weak));
+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, FDR *fdr,
+ unsigned int indx));
+static boolean ecoff_slurp_reloc_table PARAMS ((bfd *abfd, asection *section,
+ asymbol **symbols));
+static int ecoff_sort_hdrs PARAMS ((const PTR, const PTR));
+static boolean 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,
+ unsigned int hlog));
+
+/* This stuff is somewhat copied from coffcode.h. */
+
+static asection bfd_debug_section = { "*DEBUG*" };
+
+/* Create an ECOFF object. */
+
+boolean
+_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)
+ return false;
+
+ return true;
+}
+
+/* This is a hook called by coff_real_object_p to create any backend
+ specific information. */
+
+PTR
+_bfd_ecoff_mkobject_hook (abfd, filehdr, aouthdr)
+ bfd *abfd;
+ PTR filehdr;
+ PTR aouthdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ struct internal_aouthdr *internal_a = (struct internal_aouthdr *) aouthdr;
+ ecoff_data_type *ecoff;
+
+ if (_bfd_ecoff_mkobject (abfd) == false)
+ return NULL;
+
+ ecoff = ecoff_data (abfd);
+ ecoff->gp_size = 8;
+ ecoff->sym_filepos = internal_f->f_symptr;
+
+ if (internal_a != (struct internal_aouthdr *) NULL)
+ {
+ int i;
+
+ ecoff->text_start = internal_a->text_start;
+ ecoff->text_end = internal_a->text_start + internal_a->tsize;
+ ecoff->gp = internal_a->gp_value;
+ ecoff->gprmask = internal_a->gprmask;
+ for (i = 0; i < 4; i++)
+ ecoff->cprmask[i] = internal_a->cprmask[i];
+ ecoff->fprmask = internal_a->fprmask;
+ if (internal_a->magic == ECOFF_AOUT_ZMAGIC)
+ abfd->flags |= D_PAGED;
+ else
+ abfd->flags &=~ D_PAGED;
+ }
+
+ /* It turns out that no special action is required by the MIPS or
+ Alpha ECOFF backends. They have different information in the
+ a.out header, but we just copy it all (e.g., gprmask, cprmask and
+ fprmask) and let the swapping routines ensure that only relevant
+ information is written out. */
+
+ return (PTR) ecoff;
+}
+
+/* Initialize a new section. */
+
+boolean
+_bfd_ecoff_new_section_hook (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ /* For the .pdata section, which has a special meaning on the Alpha,
+ we set the alignment power to 3. 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. For every other
+ section we use an alignment power of 4; this could be made target
+ dependent by adding a field to ecoff_backend_data, but 4 appears
+ to be correct for both the MIPS and the Alpha. */
+ if (strcmp (section->name, _PDATA) == 0)
+ section->alignment_power = 3;
+ else
+ section->alignment_power = 4;
+
+ if (strcmp (section->name, _TEXT) == 0)
+ section->flags |= SEC_CODE | SEC_LOAD | SEC_ALLOC;
+ else if (strcmp (section->name, _DATA) == 0
+ || strcmp (section->name, _SDATA) == 0)
+ section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
+ else if (strcmp (section->name, _RDATA) == 0
+ || strcmp (section->name, _LIT8) == 0
+ || strcmp (section->name, _LIT4) == 0
+ || strcmp (section->name, _RCONST) == 0)
+ section->flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC | SEC_READONLY;
+ else if (strcmp (section->name, _BSS) == 0
+ || strcmp (section->name, _SBSS) == 0)
+ section->flags |= SEC_ALLOC;
+ else if (strcmp (section->name, _LIB) == 0)
+ {
+ /* An Irix 4 shared libary. */
+ section->flags |= SEC_COFF_SHARED_LIBRARY;
+ }
+
+ /* Probably any other section name is SEC_NEVER_LOAD, but I'm
+ uncertain about .init on some systems and I don't know how shared
+ libraries work. */
+
+ return true;
+}
+
+/* Determine the machine architecture and type. This is called from
+ the generic COFF routines. It is the inverse of ecoff_get_magic,
+ below. This could be an ECOFF backend routine, with one version
+ for each target, but there aren't all that many ECOFF targets. */
+
+boolean
+_bfd_ecoff_set_arch_mach_hook (abfd, filehdr)
+ bfd *abfd;
+ PTR filehdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ enum bfd_architecture arch;
+ unsigned long mach;
+
+ switch (internal_f->f_magic)
+ {
+ case MIPS_MAGIC_1:
+ case MIPS_MAGIC_LITTLE:
+ case MIPS_MAGIC_BIG:
+ arch = bfd_arch_mips;
+ mach = 3000;
+ break;
+
+ case MIPS_MAGIC_LITTLE2:
+ case MIPS_MAGIC_BIG2:
+ /* MIPS ISA level 2: the r6000 */
+ arch = bfd_arch_mips;
+ mach = 6000;
+ break;
+
+ case MIPS_MAGIC_LITTLE3:
+ case MIPS_MAGIC_BIG3:
+ /* MIPS ISA level 3: the r4000 */
+ arch = bfd_arch_mips;
+ mach = 4000;
+ break;
+
+ case ALPHA_MAGIC:
+ arch = bfd_arch_alpha;
+ mach = 0;
+ break;
+
+ default:
+ arch = bfd_arch_obscure;
+ mach = 0;
+ break;
+ }
+
+ return bfd_default_set_arch_mach (abfd, arch, mach);
+}
+
+/* Get the magic number to use based on the architecture and machine.
+ This is the inverse of _bfd_ecoff_set_arch_mach_hook, above. */
+
+static int
+ecoff_get_magic (abfd)
+ bfd *abfd;
+{
+ int big, little;
+
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_mips:
+ switch (bfd_get_mach (abfd))
+ {
+ default:
+ case 0:
+ case 3000:
+ big = MIPS_MAGIC_BIG;
+ little = MIPS_MAGIC_LITTLE;
+ break;
+
+ case 6000:
+ big = MIPS_MAGIC_BIG2;
+ little = MIPS_MAGIC_LITTLE2;
+ break;
+
+ case 4000:
+ big = MIPS_MAGIC_BIG3;
+ little = MIPS_MAGIC_LITTLE3;
+ break;
+ }
+
+ return bfd_big_endian (abfd) ? big : little;
+
+ case bfd_arch_alpha:
+ return ALPHA_MAGIC;
+
+ default:
+ abort ();
+ return 0;
+ }
+}
+
+/* Get the section s_flags to use for a section. */
+
+static long
+ecoff_sec_to_styp_flags (name, flags)
+ const char *name;
+ flagword flags;
+{
+ long styp;
+
+ styp = 0;
+
+ if (strcmp (name, _TEXT) == 0)
+ styp = STYP_TEXT;
+ else if (strcmp (name, _DATA) == 0)
+ styp = STYP_DATA;
+ else if (strcmp (name, _SDATA) == 0)
+ 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)
+ styp = STYP_LIT4;
+ else if (strcmp (name, _BSS) == 0)
+ styp = STYP_BSS;
+ else if (strcmp (name, _SBSS) == 0)
+ styp = STYP_SBSS;
+ else if (strcmp (name, _INIT) == 0)
+ 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 (strcmp (name, _GOT) == 0)
+ styp = STYP_GOT;
+ else if (strcmp (name, _HASH) == 0)
+ styp = STYP_HASH;
+ else if (strcmp (name, _DYNAMIC) == 0)
+ styp = STYP_DYNAMIC;
+ else if (strcmp (name, _LIBLIST) == 0)
+ styp = STYP_LIBLIST;
+ else if (strcmp (name, _RELDYN) == 0)
+ styp = STYP_RELDYN;
+ else if (strcmp (name, _CONFLIC) == 0)
+ styp = STYP_CONFLIC;
+ else if (strcmp (name, _DYNSTR) == 0)
+ styp = STYP_DYNSTR;
+ else if (strcmp (name, _DYNSYM) == 0)
+ styp = STYP_DYNSYM;
+ else if (strcmp (name, _COMMENT) == 0)
+ {
+ styp = STYP_COMMENT;
+ flags &=~ SEC_NEVER_LOAD;
+ }
+ else if (strcmp (name, _RCONST) == 0)
+ styp = STYP_RCONST;
+ else if (flags & SEC_CODE)
+ styp = STYP_TEXT;
+ else if (flags & SEC_DATA)
+ styp = STYP_DATA;
+ else if (flags & SEC_READONLY)
+ styp = STYP_RDATA;
+ else if (flags & SEC_LOAD)
+ styp = STYP_REG;
+ else
+ styp = STYP_BSS;
+
+ if (flags & SEC_NEVER_LOAD)
+ styp |= STYP_NOLOAD;
+
+ return styp;
+}
+
+/* Get the BFD flags to use for a section. */
+
+/*ARGSUSED*/
+flagword
+_bfd_ecoff_styp_to_sec_flags (abfd, hdr, name)
+ bfd *abfd;
+ PTR hdr;
+ const char *name;
+{
+ struct internal_scnhdr *internal_s = (struct internal_scnhdr *) hdr;
+ long styp_flags = internal_s->s_flags;
+ flagword sec_flags=0;
+
+ if (styp_flags & STYP_NOLOAD)
+ sec_flags |= SEC_NEVER_LOAD;
+
+ /* For 386 COFF, at least, an unloadable text or data section is
+ actually a shared library section. */
+ if ((styp_flags & STYP_TEXT)
+ || (styp_flags & STYP_ECOFF_INIT)
+ || (styp_flags & STYP_ECOFF_FINI)
+ || (styp_flags & STYP_DYNAMIC)
+ || (styp_flags & STYP_LIBLIST)
+ || (styp_flags & STYP_RELDYN)
+ || styp_flags == STYP_CONFLIC
+ || (styp_flags & STYP_DYNSTR)
+ || (styp_flags & STYP_DYNSYM)
+ || (styp_flags & STYP_HASH))
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ 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_PDATA
+ || styp_flags == STYP_XDATA
+ || (styp_flags & STYP_GOT)
+ || styp_flags == STYP_RCONST)
+ {
+ if (sec_flags & SEC_NEVER_LOAD)
+ sec_flags |= SEC_DATA | SEC_COFF_SHARED_LIBRARY;
+ else
+ sec_flags |= SEC_DATA | SEC_LOAD | SEC_ALLOC;
+ if ((styp_flags & STYP_RDATA)
+ || styp_flags == STYP_PDATA
+ || styp_flags == STYP_RCONST)
+ sec_flags |= SEC_READONLY;
+ }
+ else if ((styp_flags & STYP_BSS)
+ || (styp_flags & STYP_SBSS))
+ {
+ sec_flags |= SEC_ALLOC;
+ }
+ else if ((styp_flags & STYP_INFO) || styp_flags == STYP_COMMENT)
+ {
+ sec_flags |= SEC_NEVER_LOAD;
+ }
+ 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;
+ }
+
+ return sec_flags;
+}
+
+/* Read in the symbolic header for an ECOFF object file. */
+
+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) bfd_malloc ((size_t) external_hdr_size);
+ if (raw == NULL)
+ 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;
+ PTR raw;
+ bfd_size_type external_fdr_size;
+ char *fraw_src;
+ char *fraw_end;
+ struct fdr *fdr_ptr;
+ 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)
+ return true;
+ if (ecoff_data (abfd)->sym_filepos == 0)
+ {
+ bfd_get_symcount (abfd) = 0;
+ return true;
+ }
+
+ if (! ecoff_slurp_symbolic_header (abfd))
+ return false;
+
+ internal_symhdr = &debug->symbolic_header;
+
+ /* Read all the symbolic information at once. */
+ 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
+ documented section. And the ordering of the sections varies between
+ statically and dynamically linked executables.
+ If bfd supports SEEK_END someday, this code could be simplified. */
+
+ raw_end = 0;
+
+#define UPDATE_RAW_END(start, count, size) \
+ cb_end = internal_symhdr->start + internal_symhdr->count * (size); \
+ if (cb_end > raw_end) \
+ raw_end = cb_end
+
+ UPDATE_RAW_END (cbLineOffset, cbLine, sizeof (unsigned char));
+ 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->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
+
+ raw_size = raw_end - raw_base;
+ if (raw_size == 0)
+ {
+ ecoff_data (abfd)->sym_filepos = 0;
+ return true;
+ }
+ raw = (PTR) bfd_alloc (abfd, raw_size);
+ if (raw == NULL)
+ return false;
+ 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_release (abfd, raw);
+ return false;
+ }
+
+ 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) \
+ debug->off2 = (type) NULL; \
+ else \
+ 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);
+ FIX (cbSymOffset, external_sym, PTR);
+ FIX (cbOptOffset, external_opt, PTR);
+ FIX (cbAuxOffset, external_aux, union aux_ext *);
+ FIX (cbSsOffset, ss, char *);
+ FIX (cbSsExtOffset, ssext, char *);
+ FIX (cbFdOffset, external_fdr, PTR);
+ FIX (cbRfdOffset, external_rfd, PTR);
+ FIX (cbExtOffset, external_ext, PTR);
+#undef FIX
+
+ /* I don't want to always swap all the data, because it will just
+ waste time and most programs will never look at it. The only
+ time the linker needs most of the debugging information swapped
+ is when linking big-endian and little-endian MIPS object files
+ together, which is not a common occurrence.
+
+ We need to look at the fdr to deal with a lot of information in
+ the symbols, so we swap them here. */
+ debug->fdr = (struct fdr *) bfd_alloc (abfd,
+ (internal_symhdr->ifdMax *
+ sizeof (struct fdr)));
+ if (debug->fdr == NULL)
+ return false;
+ 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->debug_swap.swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+
+ return true;
+}
+
+/* ECOFF symbol table routines. The ECOFF symbol table is described
+ in gcc/mips-tfile.c. */
+
+/* ECOFF uses two common sections. One is the usual one, and the
+ other is for small objects. All the small objects are kept
+ together, and then referenced via the gp pointer, which yields
+ faster assembler code. This is what we use for the small common
+ section. */
+static asection ecoff_scom_section;
+static asymbol ecoff_scom_symbol;
+static asymbol *ecoff_scom_symbol_ptr;
+
+/* Create an empty symbol. */
+
+asymbol *
+_bfd_ecoff_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ ecoff_symbol_type *new;
+
+ new = (ecoff_symbol_type *) bfd_alloc (abfd, sizeof (ecoff_symbol_type));
+ if (new == (ecoff_symbol_type *) NULL)
+ return (asymbol *) NULL;
+ memset ((PTR) new, 0, sizeof *new);
+ new->symbol.section = (asection *) NULL;
+ new->fdr = (FDR *) NULL;
+ new->local = false;
+ new->native = NULL;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+/* Set the BFD flags and section for an ECOFF symbol. */
+
+static boolean
+ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext, weak)
+ bfd *abfd;
+ SYMR *ecoff_sym;
+ asymbol *asym;
+ int ext;
+ int weak;
+{
+ asym->the_bfd = abfd;
+ asym->value = ecoff_sym->value;
+ asym->section = &bfd_debug_section;
+ asym->udata.i = 0;
+
+ /* Most symbol types are just for debugging. */
+ switch (ecoff_sym->st)
+ {
+ case stGlobal:
+ case stStatic:
+ case stLabel:
+ case stProc:
+ case stStaticProc:
+ break;
+ case stNil:
+ if (ECOFF_IS_STAB (ecoff_sym))
+ {
+ asym->flags = BSF_DEBUGGING;
+ return true;
+ }
+ break;
+ default:
+ asym->flags = BSF_DEBUGGING;
+ return true;
+ }
+
+ if (weak)
+ asym->flags = BSF_EXPORT | BSF_WEAK;
+ else if (ext)
+ asym->flags = BSF_EXPORT | BSF_GLOBAL;
+ else
+ {
+ asym->flags = BSF_LOCAL;
+ /* Normally, a local stProc symbol will have a corresponding
+ external symbol. We mark the local symbol as a debugging
+ symbol, in order to prevent nm from printing both out.
+ Similarly, we mark stLabel and stabs symbols as debugging
+ symbols. In both cases, we do want to set the value
+ correctly based on the symbol class. */
+ if (ecoff_sym->st == stProc
+ || ecoff_sym->st == stLabel
+ || ECOFF_IS_STAB (ecoff_sym))
+ asym->flags |= BSF_DEBUGGING;
+ }
+ switch (ecoff_sym->sc)
+ {
+ case scNil:
+ /* Used for compiler generated labels. Leave them in the
+ debugging section, and mark them as local. If BSF_DEBUGGING
+ is set, then nm does not display them for some reason. If no
+ flags are set then the linker whines about them. */
+ asym->flags = BSF_LOCAL;
+ break;
+ case scText:
+ asym->section = bfd_make_section_old_way (abfd, ".text");
+ asym->value -= asym->section->vma;
+ break;
+ case scData:
+ asym->section = bfd_make_section_old_way (abfd, ".data");
+ asym->value -= asym->section->vma;
+ break;
+ case scBss:
+ asym->section = bfd_make_section_old_way (abfd, ".bss");
+ asym->value -= asym->section->vma;
+ break;
+ case scRegister:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scAbs:
+ asym->section = bfd_abs_section_ptr;
+ break;
+ case scUndefined:
+ asym->section = bfd_und_section_ptr;
+ asym->flags = 0;
+ asym->value = 0;
+ break;
+ case scCdbLocal:
+ case scBits:
+ case scCdbSystem:
+ case scRegImage:
+ case scInfo:
+ case scUserStruct:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scSData:
+ asym->section = bfd_make_section_old_way (abfd, ".sdata");
+ asym->value -= asym->section->vma;
+ break;
+ case scSBss:
+ asym->section = bfd_make_section_old_way (abfd, ".sbss");
+ asym->value -= asym->section->vma;
+ break;
+ case scRData:
+ asym->section = bfd_make_section_old_way (abfd, ".rdata");
+ asym->value -= asym->section->vma;
+ break;
+ case scVar:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scCommon:
+ if (asym->value > ecoff_data (abfd)->gp_size)
+ {
+ asym->section = bfd_com_section_ptr;
+ asym->flags = 0;
+ 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;
+ }
+ asym->section = &ecoff_scom_section;
+ asym->flags = 0;
+ break;
+ case scVarRegister:
+ case scVariant:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scSUndefined:
+ asym->section = bfd_und_section_ptr;
+ asym->flags = 0;
+ asym->value = 0;
+ break;
+ case scInit:
+ asym->section = bfd_make_section_old_way (abfd, ".init");
+ asym->value -= asym->section->vma;
+ break;
+ case scBasedVar:
+ case scXData:
+ case scPData:
+ asym->flags = BSF_DEBUGGING;
+ break;
+ case scFini:
+ asym->section = bfd_make_section_old_way (abfd, ".fini");
+ asym->value -= asym->section->vma;
+ break;
+ case scRConst:
+ asym->section = bfd_make_section_old_way (abfd, ".rconst");
+ asym->value -= asym->section->vma;
+ break;
+ default:
+ break;
+ }
+
+ /* Look for special constructors symbols and make relocation entries
+ in a special construction section. These are produced by the
+ -fgnu-linker argument to g++. */
+ if (ECOFF_IS_STAB (ecoff_sym))
+ {
+ switch (ECOFF_UNMARK_STAB (ecoff_sym->index))
+ {
+ default:
+ break;
+
+ case N_SETA:
+ case N_SETT:
+ case N_SETD:
+ case N_SETB:
+ {
+ const char *name;
+ asection *section;
+ arelent_chain *reloc_chain;
+ unsigned int bitsize;
+
+ /* Get a section with the same name as the symbol (usually
+ __CTOR_LIST__ or __DTOR_LIST__). FIXME: gcc uses the
+ name ___CTOR_LIST (three underscores). We need
+ __CTOR_LIST (two underscores), since ECOFF doesn't use
+ a leading underscore. This should be handled by gcc,
+ but instead we do it here. Actually, this should all
+ be done differently anyhow. */
+ name = bfd_asymbol_name (asym);
+ if (name[0] == '_' && name[1] == '_' && name[2] == '_')
+ {
+ ++name;
+ asym->name = name;
+ }
+ section = bfd_get_section_by_name (abfd, name);
+ if (section == (asection *) NULL)
+ {
+ char *copy;
+
+ copy = (char *) bfd_alloc (abfd, strlen (name) + 1);
+ if (!copy)
+ return false;
+ strcpy (copy, name);
+ section = bfd_make_section (abfd, copy);
+ }
+
+ /* Build a reloc pointing to this constructor. */
+ reloc_chain =
+ (arelent_chain *) bfd_alloc (abfd, sizeof (arelent_chain));
+ if (!reloc_chain)
+ return false;
+ reloc_chain->relent.sym_ptr_ptr =
+ bfd_get_section (asym)->symbol_ptr_ptr;
+ reloc_chain->relent.address = section->_raw_size;
+ reloc_chain->relent.addend = asym->value;
+ reloc_chain->relent.howto =
+ ecoff_backend (abfd)->constructor_reloc;
+
+ /* Set up the constructor section to hold the reloc. */
+ section->flags = SEC_CONSTRUCTOR;
+ ++section->reloc_count;
+
+ /* Constructor sections must be rounded to a boundary
+ based on the bitsize. These are not real sections--
+ they are handled specially by the linker--so the ECOFF
+ 16 byte alignment restriction does not apply. */
+ bitsize = ecoff_backend (abfd)->constructor_bitsize;
+ section->alignment_power = 1;
+ while ((1 << section->alignment_power) < bitsize / 8)
+ ++section->alignment_power;
+
+ reloc_chain->next = section->constructor_chain;
+ section->constructor_chain = reloc_chain;
+ section->_raw_size += bitsize / 8;
+
+ /* Mark the symbol as a constructor. */
+ asym->flags |= BSF_CONSTRUCTOR;
+ }
+ break;
+ }
+ }
+ return true;
+}
+
+/* Read an ECOFF symbol table. */
+
+boolean
+_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->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->debug_swap.swap_ext_in;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = backend->debug_swap.swap_sym_in;
+ bfd_size_type internal_size;
+ ecoff_symbol_type *internal;
+ ecoff_symbol_type *internal_ptr;
+ char *eraw_src;
+ char *eraw_end;
+ FDR *fdr_ptr;
+ FDR *fdr_end;
+
+ /* If we've already read in the symbol table, do nothing. */
+ if (ecoff_data (abfd)->canonical_symbols != NULL)
+ return true;
+
+ /* Get the symbolic information. */
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL,
+ &ecoff_data (abfd)->debug_info))
+ return false;
+ if (bfd_get_symcount (abfd) == 0)
+ return true;
+
+ internal_size = bfd_get_symcount (abfd) * sizeof (ecoff_symbol_type);
+ internal = (ecoff_symbol_type *) bfd_alloc (abfd, internal_size);
+ if (internal == NULL)
+ return false;
+
+ internal_ptr = internal;
+ eraw_src = (char *) ecoff_data (abfd)->debug_info.external_ext;
+ eraw_end = (eraw_src
+ + (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)->debug_info.ssext
+ + internal_esym.asym.iss);
+ if (!ecoff_set_symbol_info (abfd, &internal_esym.asym,
+ &internal_ptr->symbol, 1,
+ internal_esym.weakext))
+ return false;
+ /* The alpha uses a negative ifd field for section symbols. */
+ if (internal_esym.ifd >= 0)
+ internal_ptr->fdr = (ecoff_data (abfd)->debug_info.fdr
+ + internal_esym.ifd);
+ else
+ internal_ptr->fdr = NULL;
+ internal_ptr->local = false;
+ internal_ptr->native = (PTR) eraw_src;
+ }
+
+ /* 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)->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)->debug_info.external_sym
+ + fdr_ptr->isymBase * external_sym_size);
+ lraw_end = lraw_src + fdr_ptr->csym * external_sym_size;
+ for (;
+ lraw_src < lraw_end;
+ lraw_src += external_sym_size, internal_ptr++)
+ {
+ SYMR internal_sym;
+
+ (*swap_sym_in) (abfd, (PTR) lraw_src, &internal_sym);
+ internal_ptr->symbol.name = (ecoff_data (abfd)->debug_info.ss
+ + fdr_ptr->issBase
+ + internal_sym.iss);
+ if (!ecoff_set_symbol_info (abfd, &internal_sym,
+ &internal_ptr->symbol, 0, 0))
+ return false;
+ internal_ptr->fdr = fdr_ptr;
+ internal_ptr->local = true;
+ internal_ptr->native = (PTR) lraw_src;
+ }
+ }
+
+ ecoff_data (abfd)->canonical_symbols = internal;
+
+ return true;
+}
+
+/* Return the amount of space needed for the canonical symbols. */
+
+long
+_bfd_ecoff_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ 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 canonical symbols. */
+
+long
+_bfd_ecoff_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ unsigned int counter = 0;
+ ecoff_symbol_type *symbase;
+ ecoff_symbol_type **location = (ecoff_symbol_type **) alocation;
+
+ if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
+ return -1;
+ if (bfd_get_symcount (abfd) == 0)
+ return 0;
+
+ symbase = ecoff_data (abfd)->canonical_symbols;
+ while (counter < bfd_get_symcount (abfd))
+ {
+ *(location++) = symbase++;
+ counter++;
+ }
+ *location++ = (ecoff_symbol_type *) NULL;
+ return bfd_get_symcount (abfd);
+}
+
+/* Turn ECOFF type information into a printable string.
+ ecoff_emit_aggregate and ecoff_type_to_string are from
+ gcc/mips-tdump.c, with swapping added and used_ptr removed. */
+
+/* Write aggregate information to a string. */
+
+static void
+ecoff_emit_aggregate (abfd, fdr, string, rndx, isym, which)
+ bfd *abfd;
+ FDR *fdr;
+ char *string;
+ RNDXR *rndx;
+ long isym;
+ const char *which;
+{
+ 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;
+
+ /* 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 = "<undefined>";
+ else if (indx == indexNil)
+ name = "<no name>";
+ else
+ {
+ SYMR sym;
+
+ 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 = %u, index = %lu }",
+ which, name, ifd,
+ ((long) indx
+ + debug_info->symbolic_header.iextMax));
+}
+
+/* Convert the type information to string format. */
+
+static char *
+ecoff_type_to_string (abfd, fdr, indx)
+ bfd *abfd;
+ FDR *fdr;
+ unsigned int indx;
+{
+ union aux_ext *aux_ptr;
+ int bigendian;
+ AUXU u;
+ struct qual {
+ unsigned int type;
+ int low_bound;
+ int high_bound;
+ int stride;
+ } qualifiers[7];
+ unsigned int basic_type;
+ int i;
+ char buffer1[1024];
+ static char buffer2[1024];
+ char *p1 = buffer1;
+ 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;
+ qualifiers[i].high_bound = 0;
+ qualifiers[i].stride = 0;
+ }
+
+ if (AUX_GET_ISYM (bigendian, &aux_ptr[indx]) == (bfd_vma) -1)
+ return "-1 (no type)";
+ _bfd_ecoff_swap_tir_in (bigendian, &aux_ptr[indx++].a_ti, &u.ti);
+
+ basic_type = u.ti.bt;
+ qualifiers[0].type = u.ti.tq0;
+ qualifiers[1].type = u.ti.tq1;
+ qualifiers[2].type = u.ti.tq2;
+ qualifiers[3].type = u.ti.tq3;
+ qualifiers[4].type = u.ti.tq4;
+ qualifiers[5].type = u.ti.tq5;
+ qualifiers[6].type = tqNil;
+
+ /*
+ * Go get the basic type.
+ */
+ switch (basic_type)
+ {
+ case btNil: /* undefined */
+ strcpy (p1, "nil");
+ break;
+
+ case btAdr: /* address - integer same size as pointer */
+ strcpy (p1, "address");
+ break;
+
+ case btChar: /* character */
+ strcpy (p1, "char");
+ break;
+
+ case btUChar: /* unsigned character */
+ strcpy (p1, "unsigned char");
+ break;
+
+ case btShort: /* short */
+ strcpy (p1, "short");
+ break;
+
+ case btUShort: /* unsigned short */
+ strcpy (p1, "unsigned short");
+ break;
+
+ case btInt: /* int */
+ strcpy (p1, "int");
+ break;
+
+ case btUInt: /* unsigned int */
+ strcpy (p1, "unsigned int");
+ break;
+
+ case btLong: /* long */
+ strcpy (p1, "long");
+ break;
+
+ case btULong: /* unsigned long */
+ strcpy (p1, "unsigned long");
+ break;
+
+ case btFloat: /* float (real) */
+ strcpy (p1, "float");
+ break;
+
+ case btDouble: /* Double (real) */
+ strcpy (p1, "double");
+ break;
+
+ /* Structures add 1-2 aux words:
+ 1st word is [ST_RFDESCAPE, offset] pointer to struct def;
+ 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+
+ case btStruct: /* Structure (Record) */
+ _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;
+
+ /* Unions add 1-2 aux words:
+ 1st word is [ST_RFDESCAPE, offset] pointer to union def;
+ 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+
+ case btUnion: /* Union */
+ _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;
+
+ /* Enumerations add 1-2 aux words:
+ 1st word is [ST_RFDESCAPE, offset] pointer to enum def;
+ 2nd word is file index if 1st word rfd is ST_RFDESCAPE. */
+
+ case btEnum: /* Enumeration */
+ _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;
+
+ case btTypedef: /* defined via a typedef, isymRef points */
+ strcpy (p1, "typedef");
+ break;
+
+ case btRange: /* subrange of int */
+ strcpy (p1, "subrange");
+ break;
+
+ case btSet: /* pascal sets */
+ strcpy (p1, "set");
+ break;
+
+ case btComplex: /* fortran complex */
+ strcpy (p1, "complex");
+ break;
+
+ case btDComplex: /* fortran double complex */
+ strcpy (p1, "double complex");
+ break;
+
+ case btIndirect: /* forward or unnamed typedef */
+ strcpy (p1, "forward/unamed typedef");
+ break;
+
+ case btFixedDec: /* Fixed Decimal */
+ strcpy (p1, "fixed decimal");
+ break;
+
+ case btFloatDec: /* Float Decimal */
+ strcpy (p1, "float decimal");
+ break;
+
+ case btString: /* Varying Length Character String */
+ strcpy (p1, "string");
+ break;
+
+ case btBit: /* Aligned Bit String */
+ strcpy (p1, "bit");
+ break;
+
+ case btPicture: /* Picture */
+ strcpy (p1, "picture");
+ break;
+
+ case btVoid: /* Void */
+ strcpy (p1, "void");
+ break;
+
+ default:
+ sprintf (p1, "Unknown basic type %d", (int) basic_type);
+ break;
+ }
+
+ p1 += strlen (buffer1);
+
+ /*
+ * If this is a bitfield, get the bitsize.
+ */
+ if (u.ti.fBitfield)
+ {
+ int bitsize;
+
+ bitsize = AUX_GET_WIDTH (bigendian, &aux_ptr[indx++]);
+ sprintf (p1, " : %d", bitsize);
+ p1 += strlen (buffer1);
+ }
+
+
+ /*
+ * Deal with any qualifiers.
+ */
+ if (qualifiers[0].type != tqNil)
+ {
+ /*
+ * Snarf up any array bounds in the correct order. Arrays
+ * store 5 successive words in the aux. table:
+ * word 0 RNDXR to type of the bounds (ie, int)
+ * word 1 Current file descriptor index
+ * word 2 low bound
+ * word 3 high bound (or -1 if [])
+ * word 4 stride size in bits
+ */
+ for (i = 0; i < 7; i++)
+ {
+ if (qualifiers[i].type == tqArray)
+ {
+ qualifiers[i].low_bound =
+ AUX_GET_DNLOW (bigendian, &aux_ptr[indx+2]);
+ qualifiers[i].high_bound =
+ AUX_GET_DNHIGH (bigendian, &aux_ptr[indx+3]);
+ qualifiers[i].stride =
+ AUX_GET_WIDTH (bigendian, &aux_ptr[indx+4]);
+ indx += 5;
+ }
+ }
+
+ /*
+ * Now print out the qualifiers.
+ */
+ for (i = 0; i < 6; i++)
+ {
+ switch (qualifiers[i].type)
+ {
+ case tqNil:
+ case tqMax:
+ break;
+
+ case tqPtr:
+ strcpy (p2, "ptr to ");
+ p2 += sizeof ("ptr to ")-1;
+ break;
+
+ case tqVol:
+ strcpy (p2, "volatile ");
+ p2 += sizeof ("volatile ")-1;
+ break;
+
+ case tqFar:
+ strcpy (p2, "far ");
+ p2 += sizeof ("far ")-1;
+ break;
+
+ case tqProc:
+ strcpy (p2, "func. ret. ");
+ p2 += sizeof ("func. ret. ");
+ break;
+
+ case tqArray:
+ {
+ int first_array = i;
+ int j;
+
+ /* Print array bounds reversed (ie, in the order the C
+ programmer writes them). C is such a fun language.... */
+
+ while (i < 5 && qualifiers[i+1].type == tqArray)
+ i++;
+
+ for (j = i; j >= first_array; j--)
+ {
+ strcpy (p2, "array [");
+ p2 += sizeof ("array [")-1;
+ if (qualifiers[j].low_bound != 0)
+ sprintf (p2,
+ "%ld:%ld {%ld bits}",
+ (long) qualifiers[j].low_bound,
+ (long) qualifiers[j].high_bound,
+ (long) qualifiers[j].stride);
+
+ else if (qualifiers[j].high_bound != -1)
+ sprintf (p2,
+ "%ld {%ld bits}",
+ (long) (qualifiers[j].high_bound + 1),
+ (long) (qualifiers[j].stride));
+
+ else
+ sprintf (p2, " {%ld bits}", (long) (qualifiers[j].stride));
+
+ p2 += strlen (p2);
+ strcpy (p2, "] of ");
+ p2 += sizeof ("] of ")-1;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ strcpy (p2, buffer1);
+ return buffer2;
+}
+
+/* Return information about ECOFF symbol SYMBOL in RET. */
+
+/*ARGSUSED*/
+void
+_bfd_ecoff_get_symbol_info (abfd, symbol, ret)
+ bfd *abfd; /* Ignored. */
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+/* Return whether this is a local label. */
+
+/*ARGSUSED*/
+boolean
+_bfd_ecoff_bfd_is_local_label (abfd, symbol)
+ bfd *abfd;
+ asymbol *symbol;
+{
+ return symbol->name[0] == '$';
+}
+
+/* Print information about an ECOFF symbol. */
+
+void
+_bfd_ecoff_print_symbol (abfd, filep, symbol, how)
+ bfd *abfd;
+ PTR filep;
+ asymbol *symbol;
+ bfd_print_symbol_type how;
+{
+ const struct ecoff_debug_swap * const debug_swap
+ = &ecoff_backend (abfd)->debug_swap;
+ FILE *file = (FILE *)filep;
+
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ fprintf (file, "%s", symbol->name);
+ break;
+ case bfd_print_symbol_more:
+ if (ecoffsymbol (symbol)->local)
+ {
+ SYMR 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,
+ (unsigned) ecoff_sym.sc);
+ }
+ else
+ {
+ EXTR 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,
+ (unsigned) ecoff_ext.asym.sc);
+ }
+ break;
+ case bfd_print_symbol_all:
+ /* Print out the symbols in a reasonable way */
+ {
+ char type;
+ int pos;
+ EXTR ecoff_ext;
+ char jmptbl;
+ char cobol_main;
+ char weakext;
+
+ if (ecoffsymbol (symbol)->local)
+ {
+ (*debug_swap->swap_sym_in) (abfd, ecoffsymbol (symbol)->native,
+ &ecoff_ext.asym);
+ type = 'l';
+ pos = ((((char *) ecoffsymbol (symbol)->native
+ - (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
+ {
+ (*debug_swap->swap_ext_in) (abfd, ecoffsymbol (symbol)->native,
+ &ecoff_ext);
+ type = 'e';
+ pos = (((char *) ecoffsymbol (symbol)->native
+ - (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' : ' ';
+ }
+
+ fprintf (file, "[%3d] %c ",
+ pos, type);
+ fprintf_vma (file, (bfd_vma) ecoff_ext.asym.value);
+ fprintf (file, " st %x sc %x indx %x %c%c%c %s",
+ (unsigned) ecoff_ext.asym.st,
+ (unsigned) ecoff_ext.asym.sc,
+ (unsigned) ecoff_ext.asym.index,
+ jmptbl, cobol_main, weakext,
+ symbol->name);
+
+ 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 = fdr->isymBase;
+ if (ecoffsymbol (symbol)->local)
+ 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)->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 = fdr->fBigendian;
+
+ /* This switch is basically from gcc/mips-tdump.c */
+ switch (ecoff_ext.asym.st)
+ {
+ case stNil:
+ case stLabel:
+ break;
+
+ case stFile:
+ case stBlock:
+ fprintf (file, "\n End+1 symbol: %ld",
+ (long) (indx + sym_base));
+ break;
+
+ case stEnd:
+ if (ecoff_ext.asym.sc == scText
+ || ecoff_ext.asym.sc == scInfo)
+ fprintf (file, "\n First symbol: %ld",
+ (long) (indx + sym_base));
+ else
+ fprintf (file, "\n First symbol: %ld",
+ ((long)
+ (AUX_GET_ISYM (bigendian,
+ &aux_base[ecoff_ext.asym.index])
+ + sym_base)));
+ break;
+
+ case stProc:
+ case stStaticProc:
+ if (ECOFF_IS_STAB (&ecoff_ext.asym))
+ ;
+ 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, fdr, indx + 1));
+ else
+ 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, fdr, indx));
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+/* Read in the relocs for a section. */
+
+static boolean
+ecoff_slurp_reloc_table (abfd, section, symbols)
+ bfd *abfd;
+ asection *section;
+ asymbol **symbols;
+{
+ const struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ arelent *internal_relocs;
+ bfd_size_type external_reloc_size;
+ bfd_size_type external_relocs_size;
+ char *external_relocs;
+ arelent *rptr;
+ unsigned int i;
+
+ if (section->relocation != (arelent *) NULL
+ || section->reloc_count == 0
+ || (section->flags & SEC_CONSTRUCTOR) != 0)
+ return true;
+
+ if (_bfd_ecoff_slurp_symbol_table (abfd) == false)
+ return false;
+
+ internal_relocs = (arelent *) bfd_alloc (abfd,
+ (sizeof (arelent)
+ * section->reloc_count));
+ external_reloc_size = backend->external_reloc_size;
+ external_relocs_size = external_reloc_size * section->reloc_count;
+ external_relocs = (char *) bfd_alloc (abfd, external_relocs_size);
+ if (internal_relocs == (arelent *) NULL
+ || external_relocs == (char *) NULL)
+ 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)
+ return false;
+
+ for (i = 0, rptr = internal_relocs; i < section->reloc_count; i++, rptr++)
+ {
+ struct internal_reloc intern;
+
+ (*backend->swap_reloc_in) (abfd,
+ external_relocs + i * external_reloc_size,
+ &intern);
+
+ if (intern.r_extern)
+ {
+ /* r_symndx is an index into the external symbols. */
+ BFD_ASSERT (intern.r_symndx >= 0
+ && (intern.r_symndx
+ < (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_ptr->symbol_ptr_ptr;
+ rptr->addend = 0;
+ }
+ else
+ {
+ CONST char *sec_name;
+ asection *sec;
+
+ /* r_symndx is a section key. */
+ switch (intern.r_symndx)
+ {
+ case RELOC_SECTION_TEXT: sec_name = ".text"; break;
+ case RELOC_SECTION_RDATA: sec_name = ".rdata"; break;
+ case RELOC_SECTION_DATA: sec_name = ".data"; break;
+ case RELOC_SECTION_SDATA: sec_name = ".sdata"; break;
+ case RELOC_SECTION_SBSS: sec_name = ".sbss"; break;
+ case RELOC_SECTION_BSS: sec_name = ".bss"; break;
+ case RELOC_SECTION_INIT: sec_name = ".init"; break;
+ case RELOC_SECTION_LIT8: sec_name = ".lit8"; break;
+ 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;
+ case RELOC_SECTION_RCONST: sec_name = ".rconst"; break;
+ default: abort ();
+ }
+
+ sec = bfd_get_section_by_name (abfd, sec_name);
+ if (sec == (asection *) NULL)
+ abort ();
+ rptr->sym_ptr_ptr = sec->symbol_ptr_ptr;
+
+ rptr->addend = - bfd_get_section_vma (abfd, sec);
+ }
+
+ rptr->address = intern.r_vaddr - bfd_get_section_vma (abfd, section);
+
+ /* Let the backend select the howto field and do any other
+ required processing. */
+ (*backend->adjust_reloc_in) (abfd, &intern, rptr);
+ }
+
+ bfd_release (abfd, external_relocs);
+
+ section->relocation = internal_relocs;
+
+ return true;
+}
+
+/* Get a canonical list of relocs. */
+
+long
+_bfd_ecoff_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd *abfd;
+ asection *section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ unsigned int count;
+
+ if (section->flags & SEC_CONSTRUCTOR)
+ {
+ arelent_chain *chain;
+
+ /* This section has relocs made up by us, not the file, so take
+ them out of their chain and place them into the data area
+ provided. */
+ for (count = 0, chain = section->constructor_chain;
+ count < section->reloc_count;
+ count++, chain = chain->next)
+ *relptr++ = &chain->relent;
+ }
+ else
+ {
+ arelent *tblptr;
+
+ if (ecoff_slurp_reloc_table (abfd, section, symbols) == false)
+ return -1;
+
+ tblptr = section->relocation;
+
+ for (count = 0; count < section->reloc_count; count++)
+ *relptr++ = tblptr++;
+ }
+
+ *relptr = (arelent *) NULL;
+
+ return section->reloc_count;
+}
+
+/* Provided a BFD, a section and an offset into the section, calculate
+ and return the name of the source file and the line nearest to the
+ wanted location. */
+
+/*ARGSUSED*/
+boolean
+_bfd_ecoff_find_nearest_line (abfd, section, ignore_symbols, offset,
+ filename_ptr, functionname_ptr, retline_ptr)
+ bfd *abfd;
+ asection *section;
+ asymbol **ignore_symbols;
+ bfd_vma offset;
+ CONST char **filename_ptr;
+ CONST char **functionname_ptr;
+ unsigned int *retline_ptr;
+{
+ 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;
+ struct ecoff_find_line *line_info;
+
+ /* Make sure we have the FDR's. */
+ if (! _bfd_ecoff_slurp_symbolic_info (abfd, (asection *) NULL, debug_info)
+ || bfd_get_symcount (abfd) == 0)
+ return false;
+
+ if (ecoff_data (abfd)->find_line_info == NULL)
+ {
+ ecoff_data (abfd)->find_line_info =
+ ((struct ecoff_find_line *)
+ bfd_alloc (abfd, sizeof (struct ecoff_find_line)));
+ if (ecoff_data (abfd)->find_line_info == NULL)
+ return false;
+ ecoff_data (abfd)->find_line_info->find_buffer = NULL;
+ ecoff_data (abfd)->find_line_info->fdrtab_len = 0;
+ ecoff_data (abfd)->find_line_info->fdrtab = NULL;
+ }
+ line_info = ecoff_data (abfd)->find_line_info;
+
+ return _bfd_ecoff_locate_line (abfd, section, offset, debug_info,
+ debug_swap, line_info, filename_ptr,
+ functionname_ptr, retline_ptr);
+}
+
+/* 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
+_bfd_ecoff_bfd_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ 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;
+ size_t c;
+ boolean local;
+
+ /* 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;
+
+ /* 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];
+
+ /* 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++)
+ {
+ if (ecoffsymbol (*sym_ptr_ptr)->local)
+ {
+ local = true;
+ break;
+ }
+ }
+
+ if (local)
+ {
+ /* 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;
+
+ 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;
+ }
+ else
+ {
+ /* 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++)
+ {
+ EXTR esym;
+
+ (*(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);
+ }
+ }
+
+ return true;
+}
+
+/* Set the architecture. The supported architecture is stored in the
+ backend pointer. We always set the architecture anyhow, since many
+ callers ignore the return value. */
+
+boolean
+_bfd_ecoff_set_arch_mach (abfd, arch, machine)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ bfd_default_set_arch_mach (abfd, arch, machine);
+ return arch == ecoff_backend (abfd)->arch;
+}
+
+/* Get the size of the section headers. */
+
+/*ARGSUSED*/
+int
+_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)
+ ++c;
+
+ 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. */
+
+boolean
+_bfd_ecoff_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ return _bfd_generic_get_section_contents (abfd, section, location,
+ offset, count);
+}
+
+/* Sort sections by VMA, but put SEC_ALLOC sections first. This is
+ called via qsort. */
+
+static int
+ecoff_sort_hdrs (arg1, arg2)
+ const PTR arg1;
+ const PTR arg2;
+{
+ const asection *hdr1 = *(const asection **) arg1;
+ const asection *hdr2 = *(const asection **) arg2;
+
+ if ((hdr1->flags & SEC_ALLOC) != 0)
+ {
+ if ((hdr2->flags & SEC_ALLOC) == 0)
+ return -1;
+ }
+ else
+ {
+ if ((hdr2->flags & SEC_ALLOC) != 0)
+ return 1;
+ }
+ if (hdr1->vma < hdr2->vma)
+ return -1;
+ else if (hdr1->vma > hdr2->vma)
+ return 1;
+ else
+ return 0;
+}
+
+/* Calculate the file position for each section, and set
+ reloc_filepos. */
+
+static boolean
+ecoff_compute_section_file_positions (abfd)
+ bfd *abfd;
+{
+ file_ptr sofar;
+ asection **sorted_hdrs;
+ asection *current;
+ unsigned int i;
+ file_ptr old_sofar;
+ boolean first_data, first_nonalloc;
+ const bfd_vma round = ecoff_backend (abfd)->round;
+
+ sofar = _bfd_ecoff_sizeof_headers (abfd, false);
+
+ /* Sort the sections by VMA. */
+ sorted_hdrs = (asection **) bfd_malloc (abfd->section_count
+ * sizeof (asection *));
+ if (sorted_hdrs == NULL)
+ return false;
+ for (current = abfd->sections, i = 0;
+ current != NULL;
+ current = current->next, i++)
+ sorted_hdrs[i] = current;
+ BFD_ASSERT (i == abfd->section_count);
+
+ qsort (sorted_hdrs, abfd->section_count, sizeof (asection *),
+ ecoff_sort_hdrs);
+
+ first_data = true;
+ first_nonalloc = true;
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ unsigned int alignment_power;
+
+ current = sorted_hdrs[i];
+
+ /* 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? 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
+ && (current->flags & SEC_CODE) == 0
+ && (! ecoff_backend (abfd)->rdata_in_text
+ || strcmp (current->name, _RDATA) != 0)
+ && strcmp (current->name, _PDATA) != 0
+ && strcmp (current->name, _RCONST) != 0)
+ {
+ sofar = (sofar + round - 1) &~ (round - 1);
+ first_data = false;
+ }
+ else if (strcmp (current->name, _LIB) == 0)
+ {
+ /* 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);
+ }
+ else if (first_nonalloc
+ && (current->flags & SEC_ALLOC) == 0
+ && (abfd->flags & D_PAGED) != 0)
+ {
+ /* Skip up to the next page for an unallocated section, such
+ as the .comment section on the Alpha. This leaves room
+ for the .bss section. */
+ first_nonalloc = false;
+ 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 << alignment_power);
+
+ if ((abfd->flags & D_PAGED) != 0
+ && (current->flags & SEC_ALLOC) != 0)
+ sofar += (current->vma - sofar) % round;
+
+ if ((current->flags & (SEC_HAS_CONTENTS | SEC_LOAD)) != 0)
+ current->filepos = sofar;
+
+ sofar += current->_raw_size;
+
+ /* make sure that this section is of the right size too */
+ old_sofar = sofar;
+ sofar = BFD_ALIGN (sofar, 1 << alignment_power);
+ current->_raw_size += sofar - old_sofar;
+ }
+
+ free (sorted_hdrs);
+ sorted_hdrs = NULL;
+
+ ecoff_data (abfd)->reloc_filepos = sofar;
+
+ return true;
+}
+
+/* Determine the location of the relocs for all the sections in the
+ output file, as well as the location of the symbolic debugging
+ information. */
+
+static bfd_size_type
+ecoff_compute_reloc_file_positions (abfd)
+ bfd *abfd;
+{
+ 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;
+
+ if (! abfd->output_has_begun)
+ {
+ if (! ecoff_compute_section_file_positions (abfd))
+ abort ();
+ abfd->output_has_begun = true;
+ }
+
+ reloc_base = ecoff_data (abfd)->reloc_filepos;
+
+ reloc_size = 0;
+ for (current = abfd->sections;
+ current != (asection *)NULL;
+ current = current->next)
+ {
+ if (current->reloc_count == 0)
+ current->rel_filepos = 0;
+ else
+ {
+ bfd_size_type relsize;
+
+ current->rel_filepos = reloc_base;
+ relsize = current->reloc_count * external_reloc_size;
+ reloc_size += relsize;
+ reloc_base += relsize;
+ }
+ }
+
+ 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 + 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)
+ {
+ if (! ecoff_compute_section_file_positions (abfd))
+ return false;
+ }
+
+ /* 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 <ian@cygnus.com>. */
+ 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 = (sym->flags & BSF_WEAK) != 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 = _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. */
+
+ /* 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) bfd_malloc ((size_t) siz);
+ if (buff == NULL)
+ goto error_return;
+ }
+
+ internal_f.f_nscns = 0;
+ if (bfd_seek (abfd, (file_ptr) (filhsz + aoutsz), SEEK_SET) != 0)
+ goto error_return;
+ for (current = abfd->sections;
+ current != (asection *) NULL;
+ current = current->next)
+ {
+ struct internal_scnhdr section;
+ bfd_vma vma;
+
+ ++internal_f.f_nscns;
+
+ strncpy (section.s_name, current->name, sizeof section.s_name);
+
+ /* 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;
+ else
+ section.s_vaddr = vma;
+
+ section.s_paddr = current->lma;
+ section.s_size = bfd_get_section_size_before_reloc (current);
+
+ /* If this section is unloadable then the scnptr will be 0. */
+ if ((current->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+ section.s_scnptr = 0;
+ else
+ section.s_scnptr = current->filepos;
+ section.s_relptr = current->rel_filepos;
+
+ /* FIXME: the lnnoptr of the .sbss or .sdata section of an
+ object file produced by the assembler is supposed to point to
+ information about how much room is required by objects of
+ various different sizes. I think this only matters if we
+ want the linker to compute the best size to use, or
+ something. I don't know what happens if the information is
+ not present. */
+ 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;
+ section.s_flags = ecoff_sec_to_styp_flags (current->name,
+ current->flags);
+
+ if (bfd_coff_swap_scnhdr_out (abfd, (PTR) &section, buff) == 0
+ || bfd_write (buff, 1, scnhsz, abfd) != scnhsz)
+ goto error_return;
+
+ if ((section.s_flags & STYP_TEXT) != 0
+ || ((section.s_flags & STYP_RDATA) != 0
+ && backend->rdata_in_text)
+ || section.s_flags == STYP_PDATA
+ || (section.s_flags & STYP_DYNAMIC) != 0
+ || (section.s_flags & STYP_LIBLIST) != 0
+ || (section.s_flags & STYP_RELDYN) != 0
+ || section.s_flags == STYP_CONFLIC
+ || (section.s_flags & STYP_DYNSTR) != 0
+ || (section.s_flags & STYP_DYNSYM) != 0
+ || (section.s_flags & STYP_HASH) != 0
+ || (section.s_flags & STYP_ECOFF_INIT) != 0
+ || (section.s_flags & STYP_ECOFF_FINI) != 0
+ || section.s_flags == STYP_RCONST)
+ {
+ text_size += bfd_get_section_size_before_reloc (current);
+ 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_XDATA
+ || (section.s_flags & STYP_GOT) != 0)
+ {
+ data_size += bfd_get_section_size_before_reloc (current);
+ 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 == 0
+ || (section.s_flags & STYP_ECOFF_LIB) != 0
+ || section.s_flags == STYP_COMMENT)
+ /* Do nothing */ ;
+ else
+ abort ();
+ }
+
+ /* Set up the file header. */
+
+ internal_f.f_magic = ecoff_get_magic (abfd);
+
+ /* We will NOT put a fucking timestamp in the header here. Every
+ time you put it back, I will come in and take it out again. I'm
+ sorry. This field does not belong here. We fill it with a 0 so
+ it compares the same but is not a reasonable time. --
+ gnu@cygnus.com. */
+ internal_f.f_timdat = 0;
+
+ if (bfd_get_symcount (abfd) != 0)
+ {
+ /* 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 = ecoff_data (abfd)->sym_filepos;
+ }
+ else
+ {
+ internal_f.f_nsyms = 0;
+ internal_f.f_symptr = 0;
+ }
+
+ internal_f.f_opthdr = aoutsz;
+
+ internal_f.f_flags = F_LNNO;
+ if (reloc_size == 0)
+ internal_f.f_flags |= F_RELFLG;
+ if (bfd_get_symcount (abfd) == 0)
+ internal_f.f_flags |= F_LSYMS;
+ if (abfd->flags & EXEC_P)
+ internal_f.f_flags |= F_EXEC;
+
+ if (bfd_little_endian (abfd))
+ internal_f.f_flags |= F_AR32WR;
+ else
+ internal_f.f_flags |= F_AR32W;
+
+ /* Set up the ``optional'' header. */
+ if ((abfd->flags & D_PAGED) != 0)
+ internal_a.magic = ECOFF_AOUT_ZMAGIC;
+ else
+ internal_a.magic = ECOFF_AOUT_OMAGIC;
+
+ /* 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? */
+ if ((abfd->flags & D_PAGED) != 0)
+ {
+ internal_a.tsize = (text_size + round - 1) &~ (round - 1);
+ internal_a.text_start = text_start &~ (round - 1);
+ internal_a.dsize = (data_size + round - 1) &~ (round - 1);
+ internal_a.data_start = data_start &~ (round - 1);
+ }
+ else
+ {
+ internal_a.tsize = text_size;
+ internal_a.text_start = text_start;
+ internal_a.dsize = data_size;
+ internal_a.data_start = data_start;
+ }
+
+ /* On Ultrix, the initial portions of the .sbss and .bss segments
+ are at the end of the data section. The bsize field in the
+ optional header records how many bss bytes are required beyond
+ those in the data section. The value is not rounded to a page
+ boundary. */
+ if (bss_size < internal_a.dsize - data_size)
+ bss_size = 0;
+ else
+ bss_size -= internal_a.dsize - data_size;
+ internal_a.bsize = bss_size;
+ internal_a.bss_start = internal_a.data_start + internal_a.dsize;
+
+ internal_a.entry = bfd_get_start_address (abfd);
+
+ internal_a.gp_value = ecoff_data (abfd)->gp;
+
+ internal_a.gprmask = ecoff_data (abfd)->gprmask;
+ internal_a.fprmask = ecoff_data (abfd)->fprmask;
+ for (i = 0; i < 4; i++)
+ internal_a.cprmask[i] = ecoff_data (abfd)->cprmask[i];
+
+ /* Let the backend adjust the headers if necessary. */
+ if (backend->adjust_headers)
+ {
+ if (! (*backend->adjust_headers) (abfd, &internal_f, &internal_a))
+ goto error_return;
+ }
+
+ /* Write out the file header and the optional header. */
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ goto error_return;
+
+ bfd_coff_swap_filehdr_out (abfd, (PTR) &internal_f, buff);
+ if (bfd_write (buff, 1, filhsz, abfd) != filhsz)
+ goto error_return;
+
+ bfd_coff_swap_aouthdr_out (abfd, (PTR) &internal_a, buff);
+ if (bfd_write (buff, 1, aoutsz, abfd) != aoutsz)
+ goto error_return;
+
+ /* 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)
+ {
+ 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;
+
+ /* Write out the relocs. */
+ for (current = abfd->sections;
+ current != (asection *) NULL;
+ current = current->next)
+ {
+ arelent **reloc_ptr_ptr;
+ arelent **reloc_end;
+ char *out_ptr;
+
+ if (current->reloc_count == 0)
+ continue;
+
+ reloc_buff =
+ bfd_alloc (abfd, current->reloc_count * external_reloc_size);
+ if (reloc_buff == NULL)
+ 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 ((PTR) &in, 0, sizeof in);
+
+ 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;
+
+ 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;
+ 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 if (strcmp (name, ".rconst") == 0)
+ in.r_symndx = RELOC_SECTION_RCONST;
+ else
+ abort ();
+ in.r_extern = 0;
+ }
+
+ (*adjust_reloc_out) (abfd, reloc, &in);
+
+ (*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;
+ }
+
+ /* 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;
+ }
+ }
+
+ /* 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;
+
+ if (bfd_seek (abfd, (file_ptr) ecoff_data (abfd)->sym_filepos - 1,
+ SEEK_SET) != 0)
+ 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)
+ goto error_return;
+ if (bfd_write (&c, 1, 1, abfd) != 1)
+ 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 (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.
+
+ This is followed by the symbol definitions. Each symbol definition
+ occupies 8 bytes. The first four bytes are the offset from the
+ start of the armap strings to the null-terminated string naming
+ this symbol. The second four bytes are the file offset to the
+ archive member which defines this symbol. If the second four bytes
+ are 0, then this is not actually a symbol definition, and it should
+ be ignored.
+
+ The symbols are hashed into the armap with a closed hashing scheme.
+ See the functions below for the details of the algorithm.
+
+ After the symbol definitions comes four bytes holding the size of
+ the string table, followed by the string table itself. */
+
+/* The name of an archive headers looks like this:
+ __________E[BL]E[BL]_ (with a trailing space).
+ The trailing space is changed to an X if the archive is changed to
+ indicate that the armap is out of date.
+
+ The Alpha seems to use ________64E[BL]E[BL]_. */
+
+#define ARMAP_BIG_ENDIAN 'B'
+#define ARMAP_LITTLE_ENDIAN 'L'
+#define ARMAP_MARKER 'E'
+#define ARMAP_START_LENGTH 10
+#define ARMAP_HEADER_MARKER_INDEX 10
+#define ARMAP_HEADER_ENDIAN_INDEX 11
+#define ARMAP_OBJECT_MARKER_INDEX 12
+#define ARMAP_OBJECT_ENDIAN_INDEX 13
+#define ARMAP_END_INDEX 14
+#define ARMAP_END "_ "
+
+/* This is a magic number used in the hashing algorithm. */
+#define ARMAP_HASH_MAGIC 0x9dd68ab5
+
+/* This returns the hash value to use for a string. It also sets
+ *REHASH to the rehash adjustment if the first slot is taken. SIZE
+ is the number of entries in the hash table, and HLOG is the log
+ base 2 of SIZE. */
+
+static unsigned int
+ecoff_armap_hash (s, rehash, size, hlog)
+ CONST char *s;
+ unsigned int *rehash;
+ unsigned int size;
+ unsigned int hlog;
+{
+ unsigned int hash;
+
+ hash = *s++;
+ while (*s != '\0')
+ hash = ((hash >> 27) | (hash << 5)) + *s++;
+ hash *= ARMAP_HASH_MAGIC;
+ *rehash = (hash & (size - 1)) | 1;
+ return hash >> (32 - hlog);
+}
+
+/* Read in the armap. */
+
+boolean
+_bfd_ecoff_slurp_armap (abfd)
+ bfd *abfd;
+{
+ char nextname[17];
+ unsigned int i;
+ struct areltdata *mapdata;
+ bfd_size_type parsed_size;
+ char *raw_armap;
+ struct artdata *ardata;
+ unsigned int count;
+ char *raw_ptr;
+ struct symdef *symdef_ptr;
+ char *stringbase;
+
+ /* Get the name of the first element. */
+ i = bfd_read ((PTR) nextname, 1, 16, abfd);
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ 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
+ bfd_slurp_armap, but that seems inappropriate since no other
+ target uses this format. Instead, we check directly for a COFF
+ armap. */
+ if (strncmp (nextname, "/ ", 16) == 0)
+ return bfd_slurp_armap (abfd);
+
+ /* See if the first element is an armap. */
+ if (strncmp (nextname, ecoff_backend (abfd)->armap_start,
+ ARMAP_START_LENGTH) != 0
+ || nextname[ARMAP_HEADER_MARKER_INDEX] != ARMAP_MARKER
+ || (nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
+ && nextname[ARMAP_HEADER_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
+ || nextname[ARMAP_OBJECT_MARKER_INDEX] != ARMAP_MARKER
+ || (nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_BIG_ENDIAN
+ && nextname[ARMAP_OBJECT_ENDIAN_INDEX] != ARMAP_LITTLE_ENDIAN)
+ || strncmp (nextname + ARMAP_END_INDEX,
+ ARMAP_END, sizeof ARMAP_END - 1) != 0)
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ /* Make sure we have the right byte ordering. */
+ if (((nextname[ARMAP_HEADER_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
+ ^ (bfd_header_big_endian (abfd)))
+ || ((nextname[ARMAP_OBJECT_ENDIAN_INDEX] == ARMAP_BIG_ENDIAN)
+ ^ (bfd_big_endian (abfd))))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
+ /* Read in the armap. */
+ ardata = bfd_ardata (abfd);
+ mapdata = (struct areltdata *) _bfd_read_ar_hdr (abfd);
+ if (mapdata == (struct areltdata *) NULL)
+ return false;
+ parsed_size = mapdata->parsed_size;
+ bfd_release (abfd, (PTR) mapdata);
+
+ raw_armap = (char *) bfd_alloc (abfd, parsed_size);
+ if (raw_armap == (char *) NULL)
+ return false;
+
+ 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);
+ 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;
+ ardata->cache = (struct ar_cache *) NULL;
+
+ /* This code used to overlay the symdefs over the raw archive data,
+ but that doesn't work on a 64 bit host. */
+
+ stringbase = raw_armap + count * 8 + 8;
+
+#ifdef CHECK_ARMAP_HASH
+ {
+ unsigned int hlog;
+
+ /* Double check that I have the hashing algorithm right by making
+ sure that every symbol can be looked up successfully. */
+ hlog = 0;
+ for (i = 1; i < count; i <<= 1)
+ hlog++;
+ BFD_ASSERT (i == count);
+
+ raw_ptr = raw_armap + 4;
+ for (i = 0; i < count; i++, raw_ptr += 8)
+ {
+ unsigned int name_offset, file_offset;
+ unsigned int hash, rehash, srch;
+
+ name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr);
+ file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4));
+ if (file_offset == 0)
+ continue;
+ hash = ecoff_armap_hash (stringbase + name_offset, &rehash, count,
+ hlog);
+ if (hash == i)
+ continue;
+
+ /* See if we can rehash to this location. */
+ for (srch = (hash + rehash) & (count - 1);
+ srch != hash && srch != i;
+ srch = (srch + rehash) & (count - 1))
+ BFD_ASSERT (bfd_h_get_32 (abfd, (PTR) (raw_armap + 8 + srch * 8))
+ != 0);
+ BFD_ASSERT (srch == i);
+ }
+ }
+
+#endif /* CHECK_ARMAP_HASH */
+
+ raw_ptr = raw_armap + 4;
+ for (i = 0; i < count; i++, raw_ptr += 8)
+ if (bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4)) != 0)
+ ++ardata->symdef_count;
+
+ symdef_ptr = ((struct symdef *)
+ bfd_alloc (abfd,
+ ardata->symdef_count * sizeof (struct symdef)));
+ if (!symdef_ptr)
+ return false;
+
+ ardata->symdefs = (carsym *) symdef_ptr;
+
+ raw_ptr = raw_armap + 4;
+ for (i = 0; i < count; i++, raw_ptr += 8)
+ {
+ unsigned int name_offset, file_offset;
+
+ file_offset = bfd_h_get_32 (abfd, (PTR) (raw_ptr + 4));
+ if (file_offset == 0)
+ continue;
+ name_offset = bfd_h_get_32 (abfd, (PTR) raw_ptr);
+ symdef_ptr->s.name = stringbase + name_offset;
+ symdef_ptr->file_offset = file_offset;
+ ++symdef_ptr;
+ }
+
+ ardata->first_file_filepos = bfd_tell (abfd);
+ /* Pad to an even boundary. */
+ ardata->first_file_filepos += ardata->first_file_filepos % 2;
+
+ bfd_has_map (abfd) = true;
+
+ return true;
+}
+
+/* Write out an armap. */
+
+boolean
+_bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx)
+ bfd *abfd;
+ unsigned int elength;
+ struct orl *map;
+ unsigned int orl_count;
+ int stridx;
+{
+ unsigned int hashsize, hashlog;
+ unsigned int symdefsize;
+ int padit;
+ unsigned int stringsize;
+ unsigned int mapsize;
+ file_ptr firstreal;
+ struct ar_hdr hdr;
+ struct stat statbuf;
+ unsigned int i;
+ bfd_byte temp[4];
+ bfd_byte *hashtable;
+ bfd *current;
+ bfd *last_elt;
+
+ /* Ultrix appears to use as a hash table size the least power of two
+ greater than twice the number of entries. */
+ for (hashlog = 0; (1 << hashlog) <= 2 * orl_count; hashlog++)
+ ;
+ hashsize = 1 << hashlog;
+
+ symdefsize = hashsize * 8;
+ padit = stridx % 2;
+ stringsize = stridx + padit;
+
+ /* Include 8 bytes to store symdefsize and stringsize in output. */
+ mapsize = symdefsize + stringsize + 8;
+
+ firstreal = SARMAG + sizeof (struct ar_hdr) + mapsize + elength;
+
+ memset ((PTR) &hdr, 0, sizeof hdr);
+
+ /* Work out the ECOFF armap name. */
+ strcpy (hdr.ar_name, ecoff_backend (abfd)->armap_start);
+ hdr.ar_name[ARMAP_HEADER_MARKER_INDEX] = ARMAP_MARKER;
+ hdr.ar_name[ARMAP_HEADER_ENDIAN_INDEX] =
+ (bfd_header_big_endian (abfd)
+ ? ARMAP_BIG_ENDIAN
+ : ARMAP_LITTLE_ENDIAN);
+ hdr.ar_name[ARMAP_OBJECT_MARKER_INDEX] = ARMAP_MARKER;
+ hdr.ar_name[ARMAP_OBJECT_ENDIAN_INDEX] =
+ bfd_big_endian (abfd) ? ARMAP_BIG_ENDIAN : ARMAP_LITTLE_ENDIAN;
+ memcpy (hdr.ar_name + ARMAP_END_INDEX, ARMAP_END, sizeof ARMAP_END - 1);
+
+ /* Write the timestamp of the archive header to be just a little bit
+ later than the timestamp of the file, otherwise the linker will
+ complain that the index is out of date. Actually, the Ultrix
+ linker just checks the archive name; the GNU linker may check the
+ date. */
+ stat (abfd->filename, &statbuf);
+ sprintf (hdr.ar_date, "%ld", (long) (statbuf.st_mtime + 60));
+
+ /* The DECstation uses zeroes for the uid, gid and mode of the
+ armap. */
+ hdr.ar_uid[0] = '0';
+ hdr.ar_gid[0] = '0';
+ hdr.ar_mode[0] = '0';
+
+ sprintf (hdr.ar_size, "%-10d", (int) mapsize);
+
+ hdr.ar_fmag[0] = '`';
+ hdr.ar_fmag[1] = '\012';
+
+ /* Turn all null bytes in the header into spaces. */
+ for (i = 0; i < sizeof (struct ar_hdr); i++)
+ if (((char *)(&hdr))[i] == '\0')
+ (((char *)(&hdr))[i]) = ' ';
+
+ if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
+ != sizeof (struct ar_hdr))
+ return false;
+
+ 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)
+ return false;
+
+ current = abfd->archive_head;
+ last_elt = current;
+ for (i = 0; i < orl_count; i++)
+ {
+ unsigned int hash, rehash;
+
+ /* Advance firstreal to the file position of this archive
+ element. */
+ if (((bfd *) map[i].pos) != last_elt)
+ {
+ do
+ {
+ firstreal += arelt_size (current) + sizeof (struct ar_hdr);
+ firstreal += firstreal % 2;
+ current = current->next;
+ }
+ while (current != (bfd *) map[i].pos);
+ }
+
+ last_elt = current;
+
+ hash = ecoff_armap_hash (*map[i].name, &rehash, hashsize, hashlog);
+ if (bfd_h_get_32 (abfd, (PTR) (hashtable + (hash * 8) + 4)) != 0)
+ {
+ unsigned int srch;
+
+ /* The desired slot is already taken. */
+ for (srch = (hash + rehash) & (hashsize - 1);
+ srch != hash;
+ srch = (srch + rehash) & (hashsize - 1))
+ if (bfd_h_get_32 (abfd, (PTR) (hashtable + (srch * 8) + 4)) == 0)
+ break;
+
+ BFD_ASSERT (srch != hash);
+
+ hash = srch;
+ }
+
+ 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 ((PTR) hashtable, 1, symdefsize, abfd) != symdefsize)
+ return false;
+
+ bfd_release (abfd, hashtable);
+
+ /* Now write the strings. */
+ 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++)
+ {
+ bfd_size_type len;
+
+ len = strlen (*map[i].name) + 1;
+ if (bfd_write ((PTR) (*map[i].name), 1, len, abfd) != len)
+ return false;
+ }
+
+ /* The spec sez this should be a newline. But in order to be
+ bug-compatible for DECstation ar we use a null. */
+ if (padit)
+ {
+ if (bfd_write ("", 1, 1, abfd) != 1)
+ return false;
+ }
+
+ return true;
+}
+
+/* See whether this BFD is an archive. If it is, read in the armap
+ and the extended name table. */
+
+const bfd_target *
+_bfd_ecoff_archive_p (abfd)
+ bfd *abfd;
+{
+ char armag[SARMAG + 1];
+
+ if (bfd_read ((PTR) armag, 1, SARMAG, abfd) != SARMAG
+ || strncmp (armag, ARMAG, SARMAG) != 0)
+ {
+ 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
+ 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));
+
+ if (bfd_ardata (abfd) == (struct artdata *) NULL)
+ 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 (_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 (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)
+ 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 *)
+ bfd_alloc (abfd, sizeof (struct ecoff_link_hash_table)));
+ if (ret == NULL)
+ 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 struct ecoff_backend_data * const backend = ecoff_backend (abfd);
+ 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))
+ {
+ /* An empty archive is a special case. */
+ if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
+ return true;
+ bfd_set_error (bfd_error_no_armap);
+ 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 = (*backend->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) bfd_malloc (esize);
+ if (external_ext == NULL && esize != 0)
+ 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 *) bfd_malloc (symhdr->issExtMax);
+ if (ssext == NULL && symhdr->issExtMax != 0)
+ goto error_return;
+
+ if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0
+ || (bfd_read (ssext, 1, symhdr->issExtMax, abfd) !=
+ (bfd_size_type) 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:
+ case scRConst:
+ 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) bfd_malloc (esize);
+ if (external_ext == NULL && esize != 0)
+ 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 *) bfd_malloc (symhdr->issExtMax);
+ if (ssext == NULL && symhdr->issExtMax != 0)
+ goto error_return;
+
+ if (bfd_seek (abfd, symhdr->cbSsExtOffset, SEEK_SET) != 0
+ || (bfd_read (ssext, 1, symhdr->issExtMax, abfd)
+ != (bfd_size_type) 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)
+ 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;
+ case scRConst:
+ section = bfd_make_section_old_way (abfd, ".rconst");
+ 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,
+ esym.weakext ? BSF_WEAK : 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->root.type != bfd_link_hash_defweak))))
+ {
+ 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.p->section->name, SCOMMON) != 0)
+ {
+ h->root.u.c.p->section = bfd_make_section_old_way (abfd,
+ SCOMMON);
+ h->root.u.c.p->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 *));
+
+/* Structure used to pass information to ecoff_link_write_external. */
+
+struct extsym_info
+{
+ bfd *abfd;
+ struct bfd_link_info *info;
+};
+
+/* 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;
+ struct extsym_info einfo;
+
+ /* 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. */
+ einfo.abfd = abfd;
+ einfo.info = info;
+ ecoff_link_hash_traverse (ecoff_hash_table (info),
+ ecoff_link_write_external,
+ (PTR) &einfo);
+
+ 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) bfd_malloc ((size_t) (size * symhdr->count)); \
+ if (debug->ptr == NULL) \
+ { \
+ 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;
+{
+ struct extsym_info *einfo = (struct extsym_info *) data;
+ bfd *output_bfd = einfo->abfd;
+ boolean strip;
+
+ /* We need to check if this symbol is being stripped. */
+ if (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ strip = false;
+ else if (einfo->info->strip == strip_all
+ || (einfo->info->strip == strip_some
+ && bfd_hash_lookup (einfo->info->keep_hash,
+ h->root.root.string,
+ false, false) == NULL))
+ strip = true;
+ else
+ strip = false;
+
+ if (strip || 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->root.type != bfd_link_hash_defweak)
+ 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 if (strcmp (name, _RCONST) == 0)
+ h->esym.asym.sc = scRConst;
+ 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_undefweak:
+ if (h->esym.asym.sc != scUndefined
+ && h->esym.asym.sc != scSUndefined)
+ h->esym.asym.sc = scUndefined;
+ break;
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ 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 *) bfd_malloc (raw_size >= cooked_size
+ ? (size_t) raw_size
+ : (size_t) cooked_size);
+ if (contents == NULL && raw_size != 0)
+ 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, (size_t) 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
+ && section_tdata->external_relocs != NULL)
+ external_relocs = section_tdata->external_relocs;
+ else
+ {
+ external_relocs = (PTR) bfd_malloc ((size_t) external_relocs_size);
+ if (external_relocs == NULL && external_relocs_size != 0)
+ 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;
+{
+ enum bfd_link_order_type type;
+ asection *section;
+ bfd_vma addend;
+ arelent rel;
+ struct internal_reloc in;
+ bfd_size_type external_reloc_size;
+ bfd_byte *rbuf;
+ boolean ok;
+
+ type = link_order->type;
+ section = NULL;
+ addend = link_order->u.reloc.p->addend;
+
+ /* 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 == 0)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (type == bfd_section_reloc_link_order)
+ {
+ section = link_order->u.reloc.p->u.section;
+ rel.sym_ptr_ptr = section->symbol_ptr_ptr;
+ }
+ else
+ {
+ struct bfd_link_hash_entry *h;
+
+ /* Treat a reloc against a defined symbol as though it were
+ actually against the section. */
+ h = bfd_wrapped_link_hash_lookup (output_bfd, info,
+ link_order->u.reloc.p->u.name,
+ false, false, false);
+ if (h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak))
+ {
+ type = bfd_section_reloc_link_order;
+ section = h->u.def.section->output_section;
+ /* It seems that we ought to add the symbol value to the
+ addend here, but in practice it has already been added
+ because it was passed to constructor_callback. */
+ addend += section->vma + h->u.def.section->output_offset;
+ }
+ else
+ {
+ /* We can't set up a reloc against a symbol correctly,
+ because we have no asymbol structure. Currently no
+ adjust_reloc_out routine cares. */
+ 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 (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)
+ return false;
+ rstat = _bfd_relocate_contents (rel.howto, output_bfd, 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, section)
+ : link_order->u.reloc.p->u.name),
+ rel.howto->name, 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 (type == bfd_symbol_reloc_link_order)
+ {
+ struct ecoff_link_hash_entry *h;
+
+ h = ((struct ecoff_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, 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, 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 if (strcmp (name, ".rconst") == 0)
+ in.r_symndx = RELOC_SECTION_RCONST;
+ 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 *) bfd_malloc ((size_t) external_reloc_size);
+ if (rbuf == (bfd_byte *) NULL)
+ 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/contrib/gdb/bfd/ecofflink.c b/contrib/gdb/bfd/ecofflink.c
new file mode 100644
index 0000000..03d6e00
--- /dev/null
+++ b/contrib/gdb/bfd/ecofflink.c
@@ -0,0 +1,2452 @@
+/* Routines to link ECOFF debugging information.
+ Copyright 1993 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "aout/stab_gnu.h"
+#include "coff/internal.h"
+#include "coff/sym.h"
+#include "coff/symconst.h"
+#include "coff/ecoff.h"
+
+static boolean ecoff_add_bytes PARAMS ((char **buf, char **bufend,
+ size_t need));
+static struct bfd_hash_entry *string_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+static void ecoff_align_debug PARAMS ((bfd *abfd,
+ struct ecoff_debug_info *debug,
+ const struct ecoff_debug_swap *swap));
+static boolean ecoff_write_symhdr PARAMS ((bfd *, struct ecoff_debug_info *,
+ const struct ecoff_debug_swap *,
+ file_ptr where));
+static int cmp_fdrtab_entry PARAMS ((const PTR, const PTR));
+static boolean mk_fdrtab PARAMS ((bfd *,
+ struct ecoff_debug_info * const,
+ const struct ecoff_debug_swap * const,
+ struct ecoff_find_line *));
+static long fdrtab_lookup PARAMS ((struct ecoff_find_line *, bfd_vma));
+
+/* Obstack allocation and deallocation routines. */
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+/* Routines to swap auxiliary information in and out. I am assuming
+ that the auxiliary information format is always going to be target
+ independent. */
+
+/* Swap in a type information record.
+ BIGEND says whether AUX symbols are big-endian or little-endian; this
+ info comes from the file header record (fh-fBigendian). */
+
+void
+_bfd_ecoff_swap_tir_in (bigend, ext_copy, intern)
+ int bigend;
+ const struct tir_ext *ext_copy;
+ TIR *intern;
+{
+ struct tir_ext ext[1];
+
+ *ext = *ext_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_BIG);
+ intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_BIG);
+ intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_BIG)
+ >> TIR_BITS1_BT_SH_BIG;
+ intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_BIG)
+ >> TIR_BITS_TQ4_SH_BIG;
+ intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_BIG)
+ >> TIR_BITS_TQ5_SH_BIG;
+ intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_BIG)
+ >> TIR_BITS_TQ0_SH_BIG;
+ intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_BIG)
+ >> TIR_BITS_TQ1_SH_BIG;
+ intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_BIG)
+ >> TIR_BITS_TQ2_SH_BIG;
+ intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_BIG)
+ >> TIR_BITS_TQ3_SH_BIG;
+ } else {
+ intern->fBitfield = 0 != (ext->t_bits1[0] & TIR_BITS1_FBITFIELD_LITTLE);
+ intern->continued = 0 != (ext->t_bits1[0] & TIR_BITS1_CONTINUED_LITTLE);
+ intern->bt = (ext->t_bits1[0] & TIR_BITS1_BT_LITTLE)
+ >> TIR_BITS1_BT_SH_LITTLE;
+ intern->tq4 = (ext->t_tq45[0] & TIR_BITS_TQ4_LITTLE)
+ >> TIR_BITS_TQ4_SH_LITTLE;
+ intern->tq5 = (ext->t_tq45[0] & TIR_BITS_TQ5_LITTLE)
+ >> TIR_BITS_TQ5_SH_LITTLE;
+ intern->tq0 = (ext->t_tq01[0] & TIR_BITS_TQ0_LITTLE)
+ >> TIR_BITS_TQ0_SH_LITTLE;
+ intern->tq1 = (ext->t_tq01[0] & TIR_BITS_TQ1_LITTLE)
+ >> TIR_BITS_TQ1_SH_LITTLE;
+ intern->tq2 = (ext->t_tq23[0] & TIR_BITS_TQ2_LITTLE)
+ >> TIR_BITS_TQ2_SH_LITTLE;
+ intern->tq3 = (ext->t_tq23[0] & TIR_BITS_TQ3_LITTLE)
+ >> TIR_BITS_TQ3_SH_LITTLE;
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out a type information record.
+ BIGEND says whether AUX symbols are big-endian or little-endian; this
+ info comes from the file header record (fh-fBigendian). */
+
+void
+_bfd_ecoff_swap_tir_out (bigend, intern_copy, ext)
+ int bigend;
+ const TIR *intern_copy;
+ struct tir_ext *ext;
+{
+ TIR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_BIG : 0)
+ | (intern->continued ? TIR_BITS1_CONTINUED_BIG : 0)
+ | ((intern->bt << TIR_BITS1_BT_SH_BIG)
+ & TIR_BITS1_BT_BIG));
+ ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_BIG)
+ & TIR_BITS_TQ4_BIG)
+ | ((intern->tq5 << TIR_BITS_TQ5_SH_BIG)
+ & TIR_BITS_TQ5_BIG));
+ ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_BIG)
+ & TIR_BITS_TQ0_BIG)
+ | ((intern->tq1 << TIR_BITS_TQ1_SH_BIG)
+ & TIR_BITS_TQ1_BIG));
+ ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_BIG)
+ & TIR_BITS_TQ2_BIG)
+ | ((intern->tq3 << TIR_BITS_TQ3_SH_BIG)
+ & TIR_BITS_TQ3_BIG));
+ } else {
+ ext->t_bits1[0] = ((intern->fBitfield ? TIR_BITS1_FBITFIELD_LITTLE : 0)
+ | (intern->continued ? TIR_BITS1_CONTINUED_LITTLE : 0)
+ | ((intern->bt << TIR_BITS1_BT_SH_LITTLE)
+ & TIR_BITS1_BT_LITTLE));
+ ext->t_tq45[0] = (((intern->tq4 << TIR_BITS_TQ4_SH_LITTLE)
+ & TIR_BITS_TQ4_LITTLE)
+ | ((intern->tq5 << TIR_BITS_TQ5_SH_LITTLE)
+ & TIR_BITS_TQ5_LITTLE));
+ ext->t_tq01[0] = (((intern->tq0 << TIR_BITS_TQ0_SH_LITTLE)
+ & TIR_BITS_TQ0_LITTLE)
+ | ((intern->tq1 << TIR_BITS_TQ1_SH_LITTLE)
+ & TIR_BITS_TQ1_LITTLE));
+ ext->t_tq23[0] = (((intern->tq2 << TIR_BITS_TQ2_SH_LITTLE)
+ & TIR_BITS_TQ2_LITTLE)
+ | ((intern->tq3 << TIR_BITS_TQ3_SH_LITTLE)
+ & TIR_BITS_TQ3_LITTLE));
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap in a relative symbol record. BIGEND says whether it is in
+ big-endian or little-endian format.*/
+
+void
+_bfd_ecoff_swap_rndx_in (bigend, ext_copy, intern)
+ int bigend;
+ const struct rndx_ext *ext_copy;
+ RNDXR *intern;
+{
+ struct rndx_ext ext[1];
+
+ *ext = *ext_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_BIG)
+ | ((ext->r_bits[1] & RNDX_BITS1_RFD_BIG)
+ >> RNDX_BITS1_RFD_SH_BIG);
+ intern->index = ((ext->r_bits[1] & RNDX_BITS1_INDEX_BIG)
+ << RNDX_BITS1_INDEX_SH_LEFT_BIG)
+ | (ext->r_bits[2] << RNDX_BITS2_INDEX_SH_LEFT_BIG)
+ | (ext->r_bits[3] << RNDX_BITS3_INDEX_SH_LEFT_BIG);
+ } else {
+ intern->rfd = (ext->r_bits[0] << RNDX_BITS0_RFD_SH_LEFT_LITTLE)
+ | ((ext->r_bits[1] & RNDX_BITS1_RFD_LITTLE)
+ << RNDX_BITS1_RFD_SH_LEFT_LITTLE);
+ 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)
+ | ((unsigned int) ext->r_bits[3]
+ << RNDX_BITS3_INDEX_SH_LEFT_LITTLE);
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out a relative symbol record. BIGEND says whether it is in
+ big-endian or little-endian format.*/
+
+void
+_bfd_ecoff_swap_rndx_out (bigend, intern_copy, ext)
+ int bigend;
+ const RNDXR *intern_copy;
+ struct rndx_ext *ext;
+{
+ RNDXR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bigend) {
+ ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_BIG;
+ ext->r_bits[1] = (((intern->rfd << RNDX_BITS1_RFD_SH_BIG)
+ & RNDX_BITS1_RFD_BIG)
+ | ((intern->index >> RNDX_BITS1_INDEX_SH_LEFT_BIG)
+ & RNDX_BITS1_INDEX_BIG));
+ ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_BIG;
+ ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_BIG;
+ } else {
+ ext->r_bits[0] = intern->rfd >> RNDX_BITS0_RFD_SH_LEFT_LITTLE;
+ ext->r_bits[1] = (((intern->rfd >> RNDX_BITS1_RFD_SH_LEFT_LITTLE)
+ & RNDX_BITS1_RFD_LITTLE)
+ | ((intern->index << RNDX_BITS1_INDEX_SH_LITTLE)
+ & RNDX_BITS1_INDEX_LITTLE));
+ ext->r_bits[2] = intern->index >> RNDX_BITS2_INDEX_SH_LEFT_LITTLE;
+ ext->r_bits[3] = intern->index >> RNDX_BITS3_INDEX_SH_LEFT_LITTLE;
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* The minimum amount of data to allocate. */
+#define ALLOC_SIZE (4064)
+
+/* Add bytes to a buffer. Return success. */
+
+static boolean
+ecoff_add_bytes (buf, bufend, need)
+ char **buf;
+ char **bufend;
+ size_t need;
+{
+ size_t have;
+ size_t want;
+ char *newbuf;
+
+ have = *bufend - *buf;
+ if (have > need)
+ want = ALLOC_SIZE;
+ else
+ {
+ want = need - have;
+ if (want < ALLOC_SIZE)
+ want = ALLOC_SIZE;
+ }
+ newbuf = (char *) bfd_realloc (*buf, have + want);
+ if (newbuf == NULL)
+ return false;
+ *buf = newbuf;
+ *bufend = *buf + have + want;
+ return true;
+}
+
+/* We keep a hash table which maps strings to numbers. We use it to
+ map FDR names to indices in the output file, and to map local
+ strings when combining stabs debugging information. */
+
+struct string_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* FDR index or string table offset. */
+ long val;
+ /* Next entry in string table. */
+ struct string_hash_entry *next;
+};
+
+struct string_hash_table
+{
+ struct bfd_hash_table table;
+};
+
+/* Routine to create an entry in a string hash table. */
+
+static struct bfd_hash_entry *
+string_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct string_hash_entry *ret = (struct string_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct string_hash_entry *) NULL)
+ ret = ((struct string_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct string_hash_entry)));
+ if (ret == (struct string_hash_entry *) NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct string_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ ret->val = -1;
+ ret->next = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Look up an entry in an string hash table. */
+
+#define string_hash_lookup(t, string, create, copy) \
+ ((struct string_hash_entry *) \
+ bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
+
+/* We can't afford to read in all the debugging information when we do
+ a link. Instead, we build a list of these structures to show how
+ different parts of the input file map to the output file. */
+
+struct shuffle
+{
+ /* The next entry in this linked list. */
+ struct shuffle *next;
+ /* The length of the information. */
+ unsigned long size;
+ /* Whether this information comes from a file or not. */
+ boolean filep;
+ union
+ {
+ struct
+ {
+ /* The BFD the data comes from. */
+ bfd *input_bfd;
+ /* The offset within input_bfd. */
+ file_ptr offset;
+ } file;
+ /* The data to be written out. */
+ PTR memory;
+ } u;
+};
+
+/* This structure holds information across calls to
+ bfd_ecoff_debug_accumulate. */
+
+struct accumulate
+{
+ /* The FDR hash table. */
+ struct string_hash_table fdr_hash;
+ /* The strings hash table. */
+ struct string_hash_table str_hash;
+ /* Linked lists describing how to shuffle the input debug
+ information into the output file. We keep a pointer to both the
+ head and the tail. */
+ struct shuffle *line;
+ struct shuffle *line_end;
+ struct shuffle *pdr;
+ struct shuffle *pdr_end;
+ struct shuffle *sym;
+ struct shuffle *sym_end;
+ struct shuffle *opt;
+ struct shuffle *opt_end;
+ struct shuffle *aux;
+ struct shuffle *aux_end;
+ struct shuffle *ss;
+ struct shuffle *ss_end;
+ struct string_hash_entry *ss_hash;
+ struct string_hash_entry *ss_hash_end;
+ struct shuffle *fdr;
+ struct shuffle *fdr_end;
+ struct shuffle *rfd;
+ struct shuffle *rfd_end;
+ /* The size of the largest file shuffle. */
+ unsigned long largest_file_shuffle;
+ /* An obstack for debugging information. */
+ struct obstack memory;
+};
+
+/* Add a file entry to a shuffle list. */
+
+static boolean add_file_shuffle PARAMS ((struct accumulate *,
+ struct shuffle **,
+ struct shuffle **, bfd *, file_ptr,
+ unsigned long));
+
+static boolean
+add_file_shuffle (ainfo, head, tail, input_bfd, offset, size)
+ struct accumulate *ainfo;
+ struct shuffle **head;
+ struct shuffle **tail;
+ bfd *input_bfd;
+ file_ptr offset;
+ unsigned long size;
+{
+ struct shuffle *n;
+
+ if (*tail != (struct shuffle *) NULL
+ && (*tail)->filep
+ && (*tail)->u.file.input_bfd == input_bfd
+ && (*tail)->u.file.offset + (*tail)->size == (unsigned long) offset)
+ {
+ /* Just merge this entry onto the existing one. */
+ (*tail)->size += size;
+ if ((*tail)->size > ainfo->largest_file_shuffle)
+ ainfo->largest_file_shuffle = (*tail)->size;
+ return true;
+ }
+
+ n = (struct shuffle *) obstack_alloc (&ainfo->memory,
+ sizeof (struct shuffle));
+ if (!n)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ n->next = NULL;
+ n->size = size;
+ n->filep = true;
+ n->u.file.input_bfd = input_bfd;
+ n->u.file.offset = offset;
+ if (*head == (struct shuffle *) NULL)
+ *head = n;
+ if (*tail != (struct shuffle *) NULL)
+ (*tail)->next = n;
+ *tail = n;
+ if (size > ainfo->largest_file_shuffle)
+ ainfo->largest_file_shuffle = size;
+ return true;
+}
+
+/* Add a memory entry to a shuffle list. */
+
+static boolean add_memory_shuffle PARAMS ((struct accumulate *,
+ struct shuffle **head,
+ struct shuffle **tail,
+ bfd_byte *data, unsigned long size));
+
+static boolean
+add_memory_shuffle (ainfo, head, tail, data, size)
+ struct accumulate *ainfo;
+ struct shuffle **head;
+ struct shuffle **tail;
+ bfd_byte *data;
+ unsigned long size;
+{
+ struct shuffle *n;
+
+ n = (struct shuffle *) obstack_alloc (&ainfo->memory,
+ sizeof (struct shuffle));
+ if (!n)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ n->next = NULL;
+ n->size = size;
+ n->filep = false;
+ n->u.memory = (PTR) data;
+ if (*head == (struct shuffle *) NULL)
+ *head = n;
+ if (*tail != (struct shuffle *) NULL)
+ (*tail)->next = n;
+ *tail = n;
+ return true;
+}
+
+/* Initialize the FDR hash table. This returns a handle which is then
+ passed in to bfd_ecoff_debug_accumulate, et. al. */
+
+/*ARGSUSED*/
+PTR
+bfd_ecoff_debug_init (output_bfd, output_debug, output_swap, info)
+ bfd *output_bfd;
+ struct ecoff_debug_info *output_debug;
+ const struct ecoff_debug_swap *output_swap;
+ struct bfd_link_info *info;
+{
+ struct accumulate *ainfo;
+
+ ainfo = (struct accumulate *) bfd_malloc (sizeof (struct accumulate));
+ if (!ainfo)
+ return NULL;
+ if (! bfd_hash_table_init_n (&ainfo->fdr_hash.table, string_hash_newfunc,
+ 1021))
+ return NULL;
+
+ ainfo->line = NULL;
+ ainfo->line_end = NULL;
+ ainfo->pdr = NULL;
+ ainfo->pdr_end = NULL;
+ ainfo->sym = NULL;
+ ainfo->sym_end = NULL;
+ ainfo->opt = NULL;
+ ainfo->opt_end = NULL;
+ ainfo->aux = NULL;
+ ainfo->aux_end = NULL;
+ ainfo->ss = NULL;
+ ainfo->ss_end = NULL;
+ ainfo->ss_hash = NULL;
+ ainfo->ss_hash_end = NULL;
+ ainfo->fdr = NULL;
+ ainfo->fdr_end = NULL;
+ ainfo->rfd = NULL;
+ ainfo->rfd_end = NULL;
+
+ ainfo->largest_file_shuffle = 0;
+
+ if (! info->relocateable)
+ {
+ if (! bfd_hash_table_init (&ainfo->str_hash.table, string_hash_newfunc))
+ return NULL;
+
+ /* The first entry in the string table is the empty string. */
+ output_debug->symbolic_header.issMax = 1;
+ }
+
+ if (!obstack_begin (&ainfo->memory, 4050))
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return NULL;
+ }
+
+ return (PTR) ainfo;
+}
+
+/* Free the accumulated debugging information. */
+
+/*ARGSUSED*/
+void
+bfd_ecoff_debug_free (handle, output_bfd, output_debug, output_swap, info)
+ PTR handle;
+ bfd *output_bfd;
+ struct ecoff_debug_info *output_debug;
+ const struct ecoff_debug_swap *output_swap;
+ struct bfd_link_info *info;
+{
+ struct accumulate *ainfo = (struct accumulate *) handle;
+
+ bfd_hash_table_free (&ainfo->fdr_hash.table);
+
+ if (! info->relocateable)
+ bfd_hash_table_free (&ainfo->str_hash.table);
+
+ obstack_free (&ainfo->memory, (PTR) NULL);
+
+ free (ainfo);
+}
+
+/* Accumulate the debugging information from INPUT_BFD into
+ OUTPUT_BFD. The INPUT_DEBUG argument points to some ECOFF
+ debugging information which we want to link into the information
+ pointed to by the OUTPUT_DEBUG argument. OUTPUT_SWAP and
+ INPUT_SWAP point to the swapping information needed. INFO is the
+ linker information structure. HANDLE is returned by
+ bfd_ecoff_debug_init. */
+
+/*ARGSUSED*/
+boolean
+bfd_ecoff_debug_accumulate (handle, output_bfd, output_debug, output_swap,
+ input_bfd, input_debug, input_swap,
+ info)
+ 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 *info;
+{
+ struct accumulate *ainfo = (struct accumulate *) handle;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = input_swap->swap_sym_in;
+ void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
+ = input_swap->swap_rfd_in;
+ void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
+ = output_swap->swap_sym_out;
+ void (* const swap_fdr_out) PARAMS ((bfd *, const FDR *, PTR))
+ = output_swap->swap_fdr_out;
+ void (* const swap_rfd_out) PARAMS ((bfd *, const RFDT *, PTR))
+ = output_swap->swap_rfd_out;
+ bfd_size_type external_pdr_size = output_swap->external_pdr_size;
+ bfd_size_type external_sym_size = output_swap->external_sym_size;
+ bfd_size_type external_opt_size = output_swap->external_opt_size;
+ bfd_size_type external_fdr_size = output_swap->external_fdr_size;
+ bfd_size_type external_rfd_size = output_swap->external_rfd_size;
+ HDRR * const output_symhdr = &output_debug->symbolic_header;
+ HDRR * const input_symhdr = &input_debug->symbolic_header;
+ bfd_vma section_adjust[scMax];
+ asection *sec;
+ bfd_byte *fdr_start;
+ bfd_byte *fdr_ptr;
+ bfd_byte *fdr_end;
+ bfd_size_type fdr_add;
+ unsigned int copied;
+ RFDT i;
+ unsigned long sz;
+ bfd_byte *rfd_out;
+ bfd_byte *rfd_in;
+ bfd_byte *rfd_end;
+ long newrfdbase = 0;
+ long oldrfdbase = 0;
+ bfd_byte *fdr_out;
+
+ /* Use section_adjust to hold the value to add to a symbol in a
+ particular section. */
+ memset ((PTR) section_adjust, 0, sizeof section_adjust);
+
+#define SET(name, indx) \
+ sec = bfd_get_section_by_name (input_bfd, name); \
+ if (sec != NULL) \
+ section_adjust[indx] = (sec->output_section->vma \
+ + sec->output_offset \
+ - sec->vma);
+
+ SET (".text", scText);
+ SET (".data", scData);
+ SET (".bss", scBss);
+ SET (".sdata", scSData);
+ SET (".sbss", scSBss);
+ /* scRdata section may be either .rdata or .rodata. */
+ SET (".rdata", scRData);
+ SET (".rodata", scRData);
+ SET (".init", scInit);
+ SET (".fini", scFini);
+ SET (".rconst", scRConst);
+
+#undef SET
+
+ /* Find all the debugging information based on the FDR's. We need
+ to handle them whether they are swapped or not. */
+ if (input_debug->fdr != (FDR *) NULL)
+ {
+ fdr_start = (bfd_byte *) input_debug->fdr;
+ fdr_add = sizeof (FDR);
+ }
+ else
+ {
+ fdr_start = (bfd_byte *) input_debug->external_fdr;
+ fdr_add = input_swap->external_fdr_size;
+ }
+ fdr_end = fdr_start + input_symhdr->ifdMax * fdr_add;
+
+ input_debug->ifdmap = (RFDT *) bfd_alloc (input_bfd,
+ (input_symhdr->ifdMax
+ * sizeof (RFDT)));
+
+ sz = (input_symhdr->crfd + input_symhdr->ifdMax) * external_rfd_size;
+ rfd_out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
+ if (!input_debug->ifdmap || !rfd_out)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ if (!add_memory_shuffle (ainfo, &ainfo->rfd, &ainfo->rfd_end, rfd_out, sz))
+ return false;
+
+ copied = 0;
+
+ /* Look through the FDR's to see which ones we are going to include
+ in the final output. We do not want duplicate FDR information
+ for header files, because ECOFF debugging is often very large.
+ When we find an FDR with no line information which can be merged,
+ we look it up in a hash table to ensure that we only include it
+ once. We keep a table mapping FDR numbers to the final number
+ they get with the BFD, so that we can refer to it when we write
+ out the external symbols. */
+ for (fdr_ptr = fdr_start, i = 0;
+ fdr_ptr < fdr_end;
+ fdr_ptr += fdr_add, i++, rfd_out += external_rfd_size)
+ {
+ FDR fdr;
+
+ if (input_debug->fdr != (FDR *) NULL)
+ fdr = *(FDR *) fdr_ptr;
+ else
+ (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
+
+ /* See if this FDR can be merged with an existing one. */
+ if (fdr.cbLine == 0 && fdr.rss != -1 && fdr.fMerge)
+ {
+ const char *name;
+ char *lookup;
+ struct string_hash_entry *fh;
+
+ /* We look up a string formed from the file name and the
+ number of symbols. Sometimes an include file will
+ conditionally define a typedef or something based on the
+ order of include files. Using the number of symbols as a
+ hash reduces the chance that we will merge symbol
+ information that should not be merged. */
+ name = input_debug->ss + fdr.issBase + fdr.rss;
+
+ lookup = (char *) bfd_malloc (strlen (name) + 20);
+ if (lookup == NULL)
+ return false;
+ sprintf (lookup, "%s %lx", name, fdr.csym);
+
+ fh = string_hash_lookup (&ainfo->fdr_hash, lookup, true, true);
+ free (lookup);
+ if (fh == (struct string_hash_entry *) NULL)
+ return false;
+
+ if (fh->val != -1)
+ {
+ input_debug->ifdmap[i] = fh->val;
+ (*swap_rfd_out) (output_bfd, input_debug->ifdmap + i,
+ (PTR) rfd_out);
+
+ /* Don't copy this FDR. */
+ continue;
+ }
+
+ fh->val = output_symhdr->ifdMax + copied;
+ }
+
+ input_debug->ifdmap[i] = output_symhdr->ifdMax + copied;
+ (*swap_rfd_out) (output_bfd, input_debug->ifdmap + i, (PTR) rfd_out);
+ ++copied;
+ }
+
+ newrfdbase = output_symhdr->crfd;
+ output_symhdr->crfd += input_symhdr->ifdMax;
+
+ /* Copy over any existing RFD's. RFD's are only created by the
+ linker, so this will only happen for input files which are the
+ result of a partial link. */
+ rfd_in = (bfd_byte *) input_debug->external_rfd;
+ rfd_end = rfd_in + input_symhdr->crfd * input_swap->external_rfd_size;
+ for (;
+ rfd_in < rfd_end;
+ rfd_in += input_swap->external_rfd_size)
+ {
+ RFDT rfd;
+
+ (*swap_rfd_in) (input_bfd, (PTR) rfd_in, &rfd);
+ BFD_ASSERT (rfd >= 0 && rfd < input_symhdr->ifdMax);
+ rfd = input_debug->ifdmap[rfd];
+ (*swap_rfd_out) (output_bfd, &rfd, (PTR) rfd_out);
+ rfd_out += external_rfd_size;
+ }
+
+ oldrfdbase = output_symhdr->crfd;
+ output_symhdr->crfd += input_symhdr->crfd;
+
+ /* Look through the FDR's and copy over all associated debugging
+ information. */
+ sz = copied * external_fdr_size;
+ fdr_out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
+ if (!fdr_out)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ if (!add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end, fdr_out, sz))
+ return false;
+ for (fdr_ptr = fdr_start, i = 0;
+ fdr_ptr < fdr_end;
+ fdr_ptr += fdr_add, i++)
+ {
+ FDR fdr;
+ bfd_vma fdr_adr;
+ bfd_byte *sym_out;
+ bfd_byte *lraw_src;
+ bfd_byte *lraw_end;
+ boolean fgotfilename;
+
+ if (input_debug->ifdmap[i] < output_symhdr->ifdMax)
+ {
+ /* We are not copying this FDR. */
+ continue;
+ }
+
+ if (input_debug->fdr != (FDR *) NULL)
+ fdr = *(FDR *) fdr_ptr;
+ else
+ (*input_swap->swap_fdr_in) (input_bfd, (PTR) fdr_ptr, &fdr);
+
+ fdr_adr = fdr.adr;
+
+ /* Adjust the FDR address for any changes that may have been
+ made by relaxing. */
+ if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+ {
+ struct ecoff_value_adjust *adjust;
+
+ for (adjust = input_debug->adjust;
+ adjust != (struct ecoff_value_adjust *) NULL;
+ adjust = adjust->next)
+ if (fdr_adr >= adjust->start
+ && fdr_adr < adjust->end)
+ fdr.adr += adjust->adjust;
+ }
+
+ /* FIXME: It is conceivable that this FDR points to the .init or
+ .fini section, in which case this will not do the right
+ thing. */
+ fdr.adr += section_adjust[scText];
+
+ /* Swap in the local symbols, adjust their values, and swap them
+ out again. */
+ fgotfilename = false;
+ sz = fdr.csym * external_sym_size;
+ sym_out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
+ if (!sym_out)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ if (!add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end, sym_out,
+ sz))
+ return false;
+ lraw_src = ((bfd_byte *) input_debug->external_sym
+ + fdr.isymBase * input_swap->external_sym_size);
+ lraw_end = lraw_src + fdr.csym * input_swap->external_sym_size;
+ for (; lraw_src < lraw_end; lraw_src += input_swap->external_sym_size)
+ {
+ SYMR internal_sym;
+
+ (*swap_sym_in) (input_bfd, (PTR) lraw_src, &internal_sym);
+
+ BFD_ASSERT (internal_sym.sc != scCommon
+ && internal_sym.sc != scSCommon);
+
+ /* Adjust the symbol value if appropriate. */
+ switch (internal_sym.st)
+ {
+ case stNil:
+ if (ECOFF_IS_STAB (&internal_sym))
+ break;
+ /* Fall through. */
+ case stGlobal:
+ case stStatic:
+ case stLabel:
+ case stProc:
+ case stStaticProc:
+ if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+ {
+ bfd_vma value;
+ struct ecoff_value_adjust *adjust;
+
+ value = internal_sym.value;
+ for (adjust = input_debug->adjust;
+ adjust != (struct ecoff_value_adjust *) NULL;
+ adjust = adjust->next)
+ if (value >= adjust->start
+ && value < adjust->end)
+ internal_sym.value += adjust->adjust;
+ }
+ internal_sym.value += section_adjust[internal_sym.sc];
+ break;
+
+ default:
+ break;
+ }
+
+ /* If we are doing a final link, we hash all the strings in
+ the local symbol table together. This reduces the amount
+ of space required by debugging information. We don't do
+ this when performing a relocateable link because it would
+ prevent us from easily merging different FDR's. */
+ if (! info->relocateable)
+ {
+ boolean ffilename;
+ const char *name;
+
+ if (! fgotfilename && internal_sym.iss == fdr.rss)
+ ffilename = true;
+ else
+ ffilename = false;
+
+ /* Hash the name into the string table. */
+ name = input_debug->ss + fdr.issBase + internal_sym.iss;
+ if (*name == '\0')
+ internal_sym.iss = 0;
+ else
+ {
+ struct string_hash_entry *sh;
+
+ sh = string_hash_lookup (&ainfo->str_hash, name, true, true);
+ if (sh == (struct string_hash_entry *) NULL)
+ return false;
+ if (sh->val == -1)
+ {
+ sh->val = output_symhdr->issMax;
+ output_symhdr->issMax += strlen (name) + 1;
+ if (ainfo->ss_hash == (struct string_hash_entry *) NULL)
+ ainfo->ss_hash = sh;
+ if (ainfo->ss_hash_end
+ != (struct string_hash_entry *) NULL)
+ ainfo->ss_hash_end->next = sh;
+ ainfo->ss_hash_end = sh;
+ }
+ internal_sym.iss = sh->val;
+ }
+
+ if (ffilename)
+ {
+ fdr.rss = internal_sym.iss;
+ fgotfilename = true;
+ }
+ }
+
+ (*swap_sym_out) (output_bfd, &internal_sym, sym_out);
+ sym_out += external_sym_size;
+ }
+
+ fdr.isymBase = output_symhdr->isymMax;
+ output_symhdr->isymMax += fdr.csym;
+
+ /* Copy the information that does not need swapping. */
+
+ /* FIXME: If we are relaxing, we need to adjust the line
+ numbers. Frankly, forget it. Anybody using stabs debugging
+ information will not use this line number information, and
+ stabs are adjusted correctly. */
+ if (fdr.cbLine > 0)
+ {
+ if (!add_file_shuffle (ainfo, &ainfo->line, &ainfo->line_end,
+ input_bfd,
+ input_symhdr->cbLineOffset + fdr.cbLineOffset,
+ fdr.cbLine))
+ return false;
+ fdr.ilineBase = output_symhdr->ilineMax;
+ fdr.cbLineOffset = output_symhdr->cbLine;
+ output_symhdr->ilineMax += fdr.cline;
+ output_symhdr->cbLine += fdr.cbLine;
+ }
+ if (fdr.caux > 0)
+ {
+ if (!add_file_shuffle (ainfo, &ainfo->aux, &ainfo->aux_end,
+ input_bfd,
+ (input_symhdr->cbAuxOffset
+ + fdr.iauxBase * sizeof (union aux_ext)),
+ fdr.caux * sizeof (union aux_ext)))
+ return false;
+ fdr.iauxBase = output_symhdr->iauxMax;
+ output_symhdr->iauxMax += fdr.caux;
+ }
+ if (! info->relocateable)
+ {
+
+ /* When are are hashing strings, we lie about the number of
+ strings attached to each FDR. We need to set cbSs
+ because some versions of dbx apparently use it to decide
+ how much of the string table to read in. */
+ fdr.issBase = 0;
+ fdr.cbSs = output_symhdr->issMax;
+ }
+ else if (fdr.cbSs > 0)
+ {
+ if (!add_file_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end,
+ input_bfd,
+ input_symhdr->cbSsOffset + fdr.issBase,
+ fdr.cbSs))
+ return false;
+ fdr.issBase = output_symhdr->issMax;
+ output_symhdr->issMax += fdr.cbSs;
+ }
+
+ if ((output_bfd->xvec->header_byteorder
+ == input_bfd->xvec->header_byteorder)
+ && input_debug->adjust == (struct ecoff_value_adjust *) NULL)
+ {
+ /* The two BFD's have the same endianness, and we don't have
+ to adjust the PDR addresses, so simply copying the
+ information will suffice. */
+ BFD_ASSERT (external_pdr_size == input_swap->external_pdr_size);
+ if (fdr.cpd > 0)
+ {
+ if (!add_file_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end,
+ input_bfd,
+ (input_symhdr->cbPdOffset
+ + fdr.ipdFirst * external_pdr_size),
+ fdr.cpd * external_pdr_size))
+ return false;
+ }
+ BFD_ASSERT (external_opt_size == input_swap->external_opt_size);
+ if (fdr.copt > 0)
+ {
+ if (!add_file_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end,
+ input_bfd,
+ (input_symhdr->cbOptOffset
+ + fdr.ioptBase * external_opt_size),
+ fdr.copt * external_opt_size))
+ return false;
+ }
+ }
+ else
+ {
+ bfd_size_type outsz, insz;
+ bfd_byte *in;
+ bfd_byte *end;
+ bfd_byte *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 unnecessarily slow in the normal case. */
+ outsz = external_pdr_size;
+ insz = input_swap->external_pdr_size;
+ in = ((bfd_byte *) input_debug->external_pdr
+ + fdr.ipdFirst * insz);
+ end = in + fdr.cpd * insz;
+ sz = fdr.cpd * outsz;
+ out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
+ if (!out)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ if (!add_memory_shuffle (ainfo, &ainfo->pdr, &ainfo->pdr_end, out,
+ sz))
+ return false;
+ for (; in < end; in += insz, out += outsz)
+ {
+ PDR pdr;
+
+ (*input_swap->swap_pdr_in) (input_bfd, (PTR) in, &pdr);
+
+ /* If we have been relaxing, we may have to adjust the
+ address. */
+ if (input_debug->adjust != (struct ecoff_value_adjust *) NULL)
+ {
+ bfd_vma adr;
+ struct ecoff_value_adjust *adjust;
+
+ adr = fdr_adr + pdr.adr;
+ for (adjust = input_debug->adjust;
+ adjust != (struct ecoff_value_adjust *) NULL;
+ adjust = adjust->next)
+ if (adr >= adjust->start
+ && adr < adjust->end)
+ pdr.adr += adjust->adjust;
+ }
+
+ (*output_swap->swap_pdr_out) (output_bfd, &pdr, (PTR) out);
+ }
+
+ /* Swap over the optimization information. */
+ outsz = external_opt_size;
+ insz = input_swap->external_opt_size;
+ in = ((bfd_byte *) input_debug->external_opt
+ + fdr.ioptBase * insz);
+ end = in + fdr.copt * insz;
+ sz = fdr.copt * outsz;
+ out = (bfd_byte *) obstack_alloc (&ainfo->memory, sz);
+ if (!out)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ if (!add_memory_shuffle (ainfo, &ainfo->opt, &ainfo->opt_end, out,
+ sz))
+ return false;
+ for (; in < end; in += insz, out += outsz)
+ {
+ OPTR opt;
+
+ (*input_swap->swap_opt_in) (input_bfd, (PTR) in, &opt);
+ (*output_swap->swap_opt_out) (output_bfd, &opt, (PTR) out);
+ }
+ }
+
+ fdr.ipdFirst = output_symhdr->ipdMax;
+ output_symhdr->ipdMax += fdr.cpd;
+ fdr.ioptBase = output_symhdr->ioptMax;
+ output_symhdr->ioptMax += fdr.copt;
+
+ if (fdr.crfd <= 0)
+ {
+ /* Point this FDR at the table of RFD's we created. */
+ fdr.rfdBase = newrfdbase;
+ fdr.crfd = input_symhdr->ifdMax;
+ }
+ else
+ {
+ /* Point this FDR at the remapped RFD's. */
+ fdr.rfdBase += oldrfdbase;
+ }
+
+ (*swap_fdr_out) (output_bfd, &fdr, fdr_out);
+ fdr_out += external_fdr_size;
+ ++output_symhdr->ifdMax;
+ }
+
+ return true;
+}
+
+/* Add a string to the debugging information we are accumulating.
+ Return the offset from the fdr string base. */
+
+static long ecoff_add_string PARAMS ((struct accumulate *,
+ struct bfd_link_info *,
+ struct ecoff_debug_info *,
+ FDR *fdr, const char *string));
+
+static long
+ecoff_add_string (ainfo, info, debug, fdr, string)
+ struct accumulate *ainfo;
+ struct bfd_link_info *info;
+ struct ecoff_debug_info *debug;
+ FDR *fdr;
+ const char *string;
+{
+ HDRR *symhdr;
+ size_t len;
+ bfd_size_type ret;
+
+ symhdr = &debug->symbolic_header;
+ len = strlen (string);
+ if (info->relocateable)
+ {
+ if (!add_memory_shuffle (ainfo, &ainfo->ss, &ainfo->ss_end, (PTR) string,
+ len + 1))
+ return -1;
+ ret = symhdr->issMax;
+ symhdr->issMax += len + 1;
+ fdr->cbSs += len + 1;
+ }
+ else
+ {
+ struct string_hash_entry *sh;
+
+ sh = string_hash_lookup (&ainfo->str_hash, string, true, true);
+ if (sh == (struct string_hash_entry *) NULL)
+ return -1;
+ if (sh->val == -1)
+ {
+ sh->val = symhdr->issMax;
+ symhdr->issMax += len + 1;
+ if (ainfo->ss_hash == (struct string_hash_entry *) NULL)
+ ainfo->ss_hash = sh;
+ if (ainfo->ss_hash_end
+ != (struct string_hash_entry *) NULL)
+ ainfo->ss_hash_end->next = sh;
+ ainfo->ss_hash_end = sh;
+ }
+ ret = sh->val;
+ }
+
+ return ret;
+}
+
+/* Add debugging information from a non-ECOFF file. */
+
+boolean
+bfd_ecoff_debug_accumulate_other (handle, output_bfd, output_debug,
+ output_swap, input_bfd, info)
+ 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 *info;
+{
+ struct accumulate *ainfo = (struct accumulate *) handle;
+ void (* const swap_sym_out) PARAMS ((bfd *, const SYMR *, PTR))
+ = output_swap->swap_sym_out;
+ HDRR *output_symhdr = &output_debug->symbolic_header;
+ FDR fdr;
+ asection *sec;
+ asymbol **symbols;
+ asymbol **sym_ptr;
+ asymbol **sym_end;
+ long symsize;
+ long symcount;
+ PTR external_fdr;
+
+ memset ((PTR) &fdr, 0, sizeof fdr);
+
+ sec = bfd_get_section_by_name (input_bfd, ".text");
+ if (sec != NULL)
+ fdr.adr = sec->output_section->vma + sec->output_offset;
+ else
+ {
+ /* FIXME: What about .init or .fini? */
+ fdr.adr = 0;
+ }
+
+ fdr.issBase = output_symhdr->issMax;
+ fdr.cbSs = 0;
+ fdr.rss = ecoff_add_string (ainfo, info, output_debug, &fdr,
+ bfd_get_filename (input_bfd));
+ if (fdr.rss == -1)
+ return false;
+ fdr.isymBase = output_symhdr->isymMax;
+
+ /* Get the local symbols from the input BFD. */
+ symsize = bfd_get_symtab_upper_bound (input_bfd);
+ if (symsize < 0)
+ return false;
+ symbols = (asymbol **) bfd_alloc (output_bfd, symsize);
+ if (symbols == (asymbol **) NULL)
+ return false;
+ symcount = bfd_canonicalize_symtab (input_bfd, symbols);
+ if (symcount < 0)
+ return false;
+ sym_end = symbols + symcount;
+
+ /* 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;
+ PTR external_sym;
+
+ if (((*sym_ptr)->flags & BSF_EXPORT) != 0)
+ continue;
+ memset ((PTR) &internal_sym, 0, sizeof internal_sym);
+ internal_sym.iss = ecoff_add_string (ainfo, info, output_debug, &fdr,
+ (*sym_ptr)->name);
+
+ if (internal_sym.iss == -1)
+ return false;
+ if (bfd_is_com_section ((*sym_ptr)->section)
+ || bfd_is_und_section ((*sym_ptr)->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;
+
+ external_sym = (PTR) obstack_alloc (&ainfo->memory,
+ output_swap->external_sym_size);
+ if (!external_sym)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ (*swap_sym_out) (output_bfd, &internal_sym, external_sym);
+ add_memory_shuffle (ainfo, &ainfo->sym, &ainfo->sym_end,
+ external_sym, output_swap->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. */
+ external_fdr = (PTR) obstack_alloc (&ainfo->memory,
+ output_swap->external_fdr_size);
+ if (!external_fdr)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ (*output_swap->swap_fdr_out) (output_bfd, &fdr, external_fdr);
+ add_memory_shuffle (ainfo, &ainfo->fdr, &ainfo->fdr_end,
+ external_fdr, output_swap->external_fdr_size);
+
+ ++output_symhdr->ifdMax;
+
+ return true;
+}
+
+/* Set up ECOFF debugging information for the external symbols.
+ FIXME: This is done using a memory buffer, but it should be
+ probably be changed to use a shuffle structure. The assembler uses
+ this interface, so that must be changed to do something else. */
+
+boolean
+bfd_ecoff_debug_externals (abfd, debug, swap, relocateable, get_extr,
+ set_index)
+ bfd *abfd;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+ boolean relocateable;
+ boolean (*get_extr) PARAMS ((asymbol *, EXTR *));
+ void (*set_index) PARAMS ((asymbol *, bfd_size_type));
+{
+ HDRR * const symhdr = &debug->symbolic_header;
+ asymbol **sym_ptr_ptr;
+ size_t c;
+
+ sym_ptr_ptr = bfd_get_outsymbols (abfd);
+ if (sym_ptr_ptr == NULL)
+ return true;
+
+ for (c = bfd_get_symcount (abfd); c > 0; c--, sym_ptr_ptr++)
+ {
+ asymbol *sym_ptr;
+ EXTR esym;
+
+ sym_ptr = *sym_ptr_ptr;
+
+ /* Get the external symbol information. */
+ if ((*get_extr) (sym_ptr, &esym) == false)
+ continue;
+
+ /* 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;
+ }
+
+ if (bfd_is_com_section (sym_ptr->section)
+ || bfd_is_und_section (sym_ptr->section)
+ || sym_ptr->section->output_section == (asection *) NULL)
+ {
+ /* FIXME: gas does not keep the value of a small undefined
+ symbol in the symbol itself, because of relocation
+ problems. */
+ if (esym.asym.sc != scSUndefined
+ || esym.asym.value == 0
+ || sym_ptr->value != 0)
+ esym.asym.value = sym_ptr->value;
+ }
+ else
+ esym.asym.value = (sym_ptr->value
+ + sym_ptr->section->output_offset
+ + sym_ptr->section->output_section->vma);
+
+ if (set_index)
+ (*set_index) (sym_ptr, (bfd_size_type) symhdr->iextMax);
+
+ if (! bfd_ecoff_debug_one_external (abfd, debug, swap,
+ sym_ptr->name, &esym))
+ return false;
+ }
+
+ return true;
+}
+
+/* Add a single external symbol to the debugging information. */
+
+boolean
+bfd_ecoff_debug_one_external (abfd, debug, swap, name, esym)
+ bfd *abfd;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+ const char *name;
+ EXTR *esym;
+{
+ const bfd_size_type external_ext_size = swap->external_ext_size;
+ void (* const swap_ext_out) PARAMS ((bfd *, const EXTR *, PTR))
+ = swap->swap_ext_out;
+ HDRR * const symhdr = &debug->symbolic_header;
+ size_t namelen;
+
+ namelen = strlen (name);
+
+ if ((size_t) (debug->ssext_end - debug->ssext)
+ < symhdr->issExtMax + namelen + 1)
+ {
+ if (ecoff_add_bytes ((char **) &debug->ssext,
+ (char **) &debug->ssext_end,
+ symhdr->issExtMax + namelen + 1)
+ == false)
+ return false;
+ }
+ if ((size_t) ((char *) debug->external_ext_end
+ - (char *) debug->external_ext)
+ < (symhdr->iextMax + 1) * external_ext_size)
+ {
+ if (ecoff_add_bytes ((char **) &debug->external_ext,
+ (char **) &debug->external_ext_end,
+ (symhdr->iextMax + 1) * external_ext_size)
+ == false)
+ return false;
+ }
+
+ esym->asym.iss = symhdr->issExtMax;
+
+ (*swap_ext_out) (abfd, esym,
+ ((char *) debug->external_ext
+ + symhdr->iextMax * swap->external_ext_size));
+
+ ++symhdr->iextMax;
+
+ strcpy (debug->ssext + symhdr->issExtMax, name);
+ symhdr->issExtMax += namelen + 1;
+
+ return true;
+}
+
+/* Align the ECOFF debugging information. */
+
+/*ARGSUSED*/
+static void
+ecoff_align_debug (abfd, debug, swap)
+ bfd *abfd;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+{
+ HDRR * const symhdr = &debug->symbolic_header;
+ bfd_size_type debug_align, aux_align, rfd_align;
+ size_t add;
+
+ /* Adjust the counts so that structures are aligned. */
+ debug_align = swap->debug_align;
+ aux_align = debug_align / sizeof (union aux_ext);
+ rfd_align = debug_align / swap->external_rfd_size;
+
+ add = debug_align - (symhdr->cbLine & (debug_align - 1));
+ if (add != debug_align)
+ {
+ if (debug->line != (unsigned char *) NULL)
+ memset ((PTR) (debug->line + symhdr->cbLine), 0, add);
+ symhdr->cbLine += add;
+ }
+
+ add = debug_align - (symhdr->issMax & (debug_align - 1));
+ if (add != debug_align)
+ {
+ if (debug->ss != (char *) NULL)
+ memset ((PTR) (debug->ss + symhdr->issMax), 0, add);
+ symhdr->issMax += add;
+ }
+
+ add = debug_align - (symhdr->issExtMax & (debug_align - 1));
+ if (add != debug_align)
+ {
+ if (debug->ssext != (char *) NULL)
+ memset ((PTR) (debug->ssext + symhdr->issExtMax), 0, add);
+ symhdr->issExtMax += add;
+ }
+
+ add = aux_align - (symhdr->iauxMax & (aux_align - 1));
+ if (add != aux_align)
+ {
+ if (debug->external_aux != (union aux_ext *) NULL)
+ memset ((PTR) (debug->external_aux + symhdr->iauxMax), 0,
+ add * sizeof (union aux_ext));
+ symhdr->iauxMax += add;
+ }
+
+ add = rfd_align - (symhdr->crfd & (rfd_align - 1));
+ if (add != rfd_align)
+ {
+ if (debug->external_rfd != (PTR) NULL)
+ memset ((PTR) ((char *) debug->external_rfd
+ + symhdr->crfd * swap->external_rfd_size),
+ 0, (size_t) (add * swap->external_rfd_size));
+ symhdr->crfd += add;
+ }
+}
+
+/* Return the size required by the ECOFF debugging information. */
+
+bfd_size_type
+bfd_ecoff_debug_size (abfd, debug, swap)
+ bfd *abfd;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+{
+ bfd_size_type tot;
+
+ ecoff_align_debug (abfd, debug, swap);
+ tot = swap->external_hdr_size;
+
+#define ADD(count, size) \
+ tot += debug->symbolic_header.count * size
+
+ ADD (cbLine, sizeof (unsigned char));
+ ADD (idnMax, swap->external_dnr_size);
+ ADD (ipdMax, swap->external_pdr_size);
+ ADD (isymMax, swap->external_sym_size);
+ ADD (ioptMax, swap->external_opt_size);
+ ADD (iauxMax, sizeof (union aux_ext));
+ ADD (issMax, sizeof (char));
+ ADD (issExtMax, sizeof (char));
+ ADD (ifdMax, swap->external_fdr_size);
+ ADD (crfd, swap->external_rfd_size);
+ ADD (iextMax, swap->external_ext_size);
+
+#undef ADD
+
+ return tot;
+}
+
+/* Write out the ECOFF symbolic header, given the file position it is
+ going to be placed at. This assumes that the counts are set
+ correctly. */
+
+static boolean
+ecoff_write_symhdr (abfd, debug, swap, where)
+ bfd *abfd;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+ file_ptr where;
+{
+ HDRR * const symhdr = &debug->symbolic_header;
+ char *buff = NULL;
+
+ ecoff_align_debug (abfd, debug, swap);
+
+ /* Go to the right location in the file. */
+ if (bfd_seek (abfd, where, SEEK_SET) != 0)
+ return false;
+
+ where += swap->external_hdr_size;
+
+ symhdr->magic = swap->sym_magic;
+
+ /* Fill in the file offsets. */
+#define SET(offset, count, size) \
+ if (symhdr->count == 0) \
+ symhdr->offset = 0; \
+ else \
+ { \
+ symhdr->offset = where; \
+ where += symhdr->count * size; \
+ }
+
+ SET (cbLineOffset, cbLine, sizeof (unsigned char));
+ SET (cbDnOffset, idnMax, swap->external_dnr_size);
+ SET (cbPdOffset, ipdMax, swap->external_pdr_size);
+ SET (cbSymOffset, isymMax, swap->external_sym_size);
+ SET (cbOptOffset, ioptMax, swap->external_opt_size);
+ SET (cbAuxOffset, iauxMax, sizeof (union aux_ext));
+ SET (cbSsOffset, issMax, sizeof (char));
+ SET (cbSsExtOffset, issExtMax, sizeof (char));
+ SET (cbFdOffset, ifdMax, swap->external_fdr_size);
+ SET (cbRfdOffset, crfd, swap->external_rfd_size);
+ SET (cbExtOffset, iextMax, swap->external_ext_size);
+#undef SET
+
+ buff = (PTR) bfd_malloc ((size_t) swap->external_hdr_size);
+ if (buff == NULL && swap->external_hdr_size != 0)
+ goto error_return;
+
+ (*swap->swap_hdr_out) (abfd, symhdr, buff);
+ if (bfd_write (buff, 1, swap->external_hdr_size, abfd)
+ != swap->external_hdr_size)
+ goto error_return;
+
+ if (buff != NULL)
+ free (buff);
+ return true;
+ error_return:
+ if (buff != NULL)
+ free (buff);
+ return false;
+}
+
+/* Write out the ECOFF debugging information. This function assumes
+ that the information (the pointers and counts) in *DEBUG have been
+ set correctly. WHERE is the position in the file to write the
+ information to. This function fills in the file offsets in the
+ symbolic header. */
+
+boolean
+bfd_ecoff_write_debug (abfd, debug, swap, where)
+ bfd *abfd;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+ file_ptr where;
+{
+ HDRR * const symhdr = &debug->symbolic_header;
+
+ if (! ecoff_write_symhdr (abfd, debug, swap, where))
+ return false;
+
+#define WRITE(ptr, count, size, offset) \
+ BFD_ASSERT (symhdr->offset == 0 \
+ || (bfd_vma) bfd_tell (abfd) == symhdr->offset); \
+ if (bfd_write ((PTR) debug->ptr, size, symhdr->count, abfd) \
+ != size * symhdr->count) \
+ return false;
+
+ WRITE (line, cbLine, sizeof (unsigned char), cbLineOffset);
+ WRITE (external_dnr, idnMax, swap->external_dnr_size, cbDnOffset);
+ WRITE (external_pdr, ipdMax, swap->external_pdr_size, cbPdOffset);
+ WRITE (external_sym, isymMax, swap->external_sym_size, cbSymOffset);
+ WRITE (external_opt, ioptMax, swap->external_opt_size, cbOptOffset);
+ WRITE (external_aux, iauxMax, sizeof (union aux_ext), cbAuxOffset);
+ WRITE (ss, issMax, sizeof (char), cbSsOffset);
+ WRITE (ssext, issExtMax, sizeof (char), cbSsExtOffset);
+ WRITE (external_fdr, ifdMax, swap->external_fdr_size, cbFdOffset);
+ WRITE (external_rfd, crfd, swap->external_rfd_size, cbRfdOffset);
+ WRITE (external_ext, iextMax, swap->external_ext_size, cbExtOffset);
+#undef WRITE
+
+ return true;
+}
+
+/* Write out a shuffle list. */
+
+static boolean ecoff_write_shuffle PARAMS ((bfd *,
+ const struct ecoff_debug_swap *,
+ struct shuffle *, PTR space));
+
+static boolean
+ecoff_write_shuffle (abfd, swap, shuffle, space)
+ bfd *abfd;
+ const struct ecoff_debug_swap *swap;
+ struct shuffle *shuffle;
+ PTR space;
+{
+ register struct shuffle *l;
+ unsigned long total;
+
+ total = 0;
+ for (l = shuffle; l != (struct shuffle *) NULL; l = l->next)
+ {
+ if (! l->filep)
+ {
+ if (bfd_write (l->u.memory, 1, l->size, abfd) != l->size)
+ return false;
+ }
+ else
+ {
+ if (bfd_seek (l->u.file.input_bfd, l->u.file.offset, SEEK_SET) != 0
+ || bfd_read (space, 1, l->size, l->u.file.input_bfd) != l->size
+ || bfd_write (space, 1, l->size, abfd) != l->size)
+ return false;
+ }
+ total += l->size;
+ }
+
+ if ((total & (swap->debug_align - 1)) != 0)
+ {
+ unsigned int i;
+ bfd_byte *s;
+
+ i = swap->debug_align - (total & (swap->debug_align - 1));
+ s = (bfd_byte *) bfd_malloc (i);
+ if (s == NULL && i != 0)
+ return false;
+
+ memset ((PTR) s, 0, i);
+ if (bfd_write ((PTR) s, 1, i, abfd) != i)
+ {
+ free (s);
+ return false;
+ }
+ free (s);
+ }
+
+ return true;
+}
+
+/* Write out debugging information using accumulated linker
+ information. */
+
+boolean
+bfd_ecoff_write_accumulated_debug (handle, abfd, debug, swap, info, where)
+ PTR handle;
+ bfd *abfd;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+ struct bfd_link_info *info;
+ file_ptr where;
+{
+ struct accumulate *ainfo = (struct accumulate *) handle;
+ PTR space = NULL;
+
+ if (! ecoff_write_symhdr (abfd, debug, swap, where))
+ goto error_return;
+
+ space = (PTR) bfd_malloc (ainfo->largest_file_shuffle);
+ if (space == NULL && ainfo->largest_file_shuffle != 0)
+ goto error_return;
+
+ if (! ecoff_write_shuffle (abfd, swap, ainfo->line, space)
+ || ! ecoff_write_shuffle (abfd, swap, ainfo->pdr, space)
+ || ! ecoff_write_shuffle (abfd, swap, ainfo->sym, space)
+ || ! ecoff_write_shuffle (abfd, swap, ainfo->opt, space)
+ || ! ecoff_write_shuffle (abfd, swap, ainfo->aux, space))
+ goto error_return;
+
+ /* The string table is written out from the hash table if this is a
+ final link. */
+ if (info->relocateable)
+ {
+ BFD_ASSERT (ainfo->ss_hash == (struct string_hash_entry *) NULL);
+ if (! ecoff_write_shuffle (abfd, swap, ainfo->ss, space))
+ goto error_return;
+ }
+ else
+ {
+ unsigned long total;
+ bfd_byte null;
+ struct string_hash_entry *sh;
+
+ BFD_ASSERT (ainfo->ss == (struct shuffle *) NULL);
+ null = 0;
+ if (bfd_write ((PTR) &null, 1, 1, abfd) != 1)
+ goto error_return;
+ total = 1;
+ BFD_ASSERT (ainfo->ss_hash == NULL || ainfo->ss_hash->val == 1);
+ for (sh = ainfo->ss_hash;
+ sh != (struct string_hash_entry *) NULL;
+ sh = sh->next)
+ {
+ size_t len;
+
+ len = strlen (sh->root.string);
+ if (bfd_write ((PTR) sh->root.string, 1, len + 1, abfd) != len + 1)
+ goto error_return;
+ total += len + 1;
+ }
+
+ if ((total & (swap->debug_align - 1)) != 0)
+ {
+ unsigned int i;
+ bfd_byte *s;
+
+ i = swap->debug_align - (total & (swap->debug_align - 1));
+ s = (bfd_byte *) bfd_malloc (i);
+ if (s == NULL && i != 0)
+ goto error_return;
+ memset ((PTR) s, 0, i);
+ if (bfd_write ((PTR) s, 1, i, abfd) != i)
+ {
+ free (s);
+ goto error_return;
+ }
+ free (s);
+ }
+ }
+
+ /* The external strings and symbol are not converted over to using
+ shuffles. FIXME: They probably should be. */
+ if (bfd_write (debug->ssext, 1, debug->symbolic_header.issExtMax, abfd)
+ != (bfd_size_type) debug->symbolic_header.issExtMax)
+ goto error_return;
+ if ((debug->symbolic_header.issExtMax & (swap->debug_align - 1)) != 0)
+ {
+ unsigned int i;
+ bfd_byte *s;
+
+ i = (swap->debug_align
+ - (debug->symbolic_header.issExtMax & (swap->debug_align - 1)));
+ s = (bfd_byte *) bfd_malloc (i);
+ if (s == NULL && i != 0)
+ goto error_return;
+ memset ((PTR) s, 0, i);
+ if (bfd_write ((PTR) s, 1, i, abfd) != i)
+ {
+ free (s);
+ goto error_return;
+ }
+ free (s);
+ }
+
+ if (! ecoff_write_shuffle (abfd, swap, ainfo->fdr, space)
+ || ! ecoff_write_shuffle (abfd, swap, ainfo->rfd, space))
+ goto error_return;
+
+ BFD_ASSERT (debug->symbolic_header.cbExtOffset == 0
+ || (debug->symbolic_header.cbExtOffset
+ == (bfd_vma) bfd_tell (abfd)));
+
+ if (bfd_write (debug->external_ext, swap->external_ext_size,
+ debug->symbolic_header.iextMax, abfd)
+ != debug->symbolic_header.iextMax * swap->external_ext_size)
+ goto error_return;
+
+ if (space != NULL)
+ free (space);
+ return true;
+
+ error_return:
+ if (space != NULL)
+ free (space);
+ return false;
+}
+
+/* Handle the find_nearest_line function for both ECOFF and MIPS ELF
+ files. */
+
+/* Compare FDR entries. This is called via qsort. */
+
+static int
+cmp_fdrtab_entry (leftp, rightp)
+ const PTR leftp;
+ const PTR rightp;
+{
+ const struct ecoff_fdrtab_entry *lp =
+ (const struct ecoff_fdrtab_entry *) leftp;
+ const struct ecoff_fdrtab_entry *rp =
+ (const struct ecoff_fdrtab_entry *) rightp;
+
+ if (lp->base_addr < rp->base_addr)
+ return -1;
+ if (lp->base_addr > rp->base_addr)
+ return 1;
+ return 0;
+}
+
+/* Each file descriptor (FDR) has a memory address, to simplify
+ looking up an FDR by address, we build a table covering all FDRs
+ that have a least one procedure descriptor in them. The final
+ table will be sorted by address so we can look it up via binary
+ search. */
+
+static boolean
+mk_fdrtab (abfd, debug_info, debug_swap, line_info)
+ bfd *abfd;
+ struct ecoff_debug_info * const debug_info;
+ const struct ecoff_debug_swap * const debug_swap;
+ struct ecoff_find_line *line_info;
+{
+ struct ecoff_fdrtab_entry *tab;
+ FDR *fdr_ptr;
+ FDR *fdr_start;
+ FDR *fdr_end;
+ boolean stabs;
+ long len;
+
+ fdr_start = debug_info->fdr;
+ fdr_end = fdr_start + debug_info->symbolic_header.ifdMax;
+
+ /* First, let's see how long the table needs to be: */
+ for (len = 0, fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
+ {
+ if (fdr_ptr->cpd == 0) /* skip FDRs that have no PDRs */
+ continue;
+ ++len;
+ }
+
+ /* Now, create and fill in the table: */
+
+ line_info->fdrtab = ((struct ecoff_fdrtab_entry*)
+ bfd_zalloc (abfd,
+ len * sizeof (struct ecoff_fdrtab_entry)));
+ if (line_info->fdrtab == NULL)
+ return false;
+ line_info->fdrtab_len = len;
+
+ tab = line_info->fdrtab;
+ for (fdr_ptr = fdr_start; fdr_ptr < fdr_end; fdr_ptr++)
+ {
+ if (fdr_ptr->cpd == 0)
+ continue;
+
+ /* Check whether this file has stabs debugging information. In
+ a file with stabs debugging information, the second local
+ symbol is named @stabs. */
+ stabs = false;
+ if (fdr_ptr->csym >= 2)
+ {
+ char *sym_ptr;
+ SYMR sym;
+
+ sym_ptr = ((char *) debug_info->external_sym
+ + (fdr_ptr->isymBase + 1)*debug_swap->external_sym_size);
+ (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
+ if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
+ STABS_SYMBOL) == 0)
+ stabs = true;
+ }
+
+ if (!stabs)
+ {
+ bfd_size_type external_pdr_size;
+ char *pdr_ptr;
+ PDR pdr;
+
+ external_pdr_size = debug_swap->external_pdr_size;
+
+ pdr_ptr = ((char *) debug_info->external_pdr
+ + fdr_ptr->ipdFirst * external_pdr_size);
+ (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+ /* The address of the first PDR is the offset of that
+ procedure relative to the beginning of file FDR. */
+ tab->base_addr = fdr_ptr->adr - pdr.adr;
+ }
+ else
+ {
+ /* XXX I don't know about stabs, so this is a guess
+ (davidm@cs.arizona.edu): */
+ tab->base_addr = fdr_ptr->adr;
+ }
+ tab->fdr = fdr_ptr;
+ ++tab;
+ }
+
+ /* Finally, the table is sorted in increasing memory-address order.
+ The table is mostly sorted already, but there are cases (e.g.,
+ static functions in include files), where this does not hold.
+ Use "odump -PFv" to verify... */
+ qsort ((PTR) line_info->fdrtab, len,
+ sizeof (struct ecoff_fdrtab_entry), cmp_fdrtab_entry);
+
+ return true;
+}
+
+/* Return index of first FDR that covers to OFFSET. */
+
+static long
+fdrtab_lookup (line_info, offset)
+ struct ecoff_find_line *line_info;
+ bfd_vma offset;
+{
+ long low, high, len;
+ long mid = -1;
+ struct ecoff_fdrtab_entry *tab;
+
+ len = line_info->fdrtab_len;
+ if (len == 0)
+ return -1;
+
+ tab = line_info->fdrtab;
+ for (low = 0, high = len - 1 ; low != high ;)
+ {
+ mid = (high + low) / 2;
+ if (offset >= tab[mid].base_addr && offset < tab[mid + 1].base_addr)
+ goto find_min;
+
+ if (tab[mid].base_addr > offset)
+ high = mid;
+ else
+ low = mid + 1;
+ }
+ ++mid;
+
+ /* last entry is catch-all for all higher addresses: */
+ if (offset < tab[mid].base_addr)
+ return -1;
+
+ find_min:
+
+ while (mid > 0 && tab[mid - 1].base_addr == tab[mid].base_addr)
+ --mid;
+
+ return mid;
+}
+
+/* Do the work of find_nearest_line. */
+
+boolean
+_bfd_ecoff_locate_line (abfd, section, offset, debug_info, debug_swap,
+ line_info, filename_ptr, functionname_ptr, retline_ptr)
+ bfd *abfd;
+ asection *section;
+ bfd_vma offset;
+ struct ecoff_debug_info * const debug_info;
+ const struct ecoff_debug_swap * const debug_swap;
+ struct ecoff_find_line *line_info;
+ const char **filename_ptr;
+ const char **functionname_ptr;
+ unsigned int *retline_ptr;
+{
+ struct ecoff_fdrtab_entry *tab;
+ boolean stabs;
+ FDR *fdr_ptr;
+ int i;
+
+ offset += section->vma;
+
+ /* Build FDR table (sorted by object file's base-address) if we
+ don't have it already. */
+ if (line_info->fdrtab == NULL
+ && !mk_fdrtab (abfd, debug_info, debug_swap, line_info))
+ return false;
+
+ tab = line_info->fdrtab;
+
+ /* find first FDR for address OFFSET */
+ i = fdrtab_lookup (line_info, offset);
+ if (i < 0)
+ return false; /* no FDR, no fun... */
+ fdr_ptr = tab[i].fdr;
+
+ /* Check whether this file has stabs debugging information. In a
+ file with stabs debugging information, the second local symbol is
+ named @stabs. */
+ stabs = false;
+ if (fdr_ptr->csym >= 2)
+ {
+ char *sym_ptr;
+ SYMR sym;
+
+ sym_ptr = ((char *) debug_info->external_sym
+ + (fdr_ptr->isymBase + 1) * debug_swap->external_sym_size);
+ (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
+ if (strcmp (debug_info->ss + fdr_ptr->issBase + sym.iss,
+ STABS_SYMBOL) == 0)
+ stabs = true;
+ }
+
+ if (!stabs)
+ {
+ bfd_size_type external_pdr_size;
+ char *pdr_ptr;
+ char *best_pdr = NULL;
+ FDR *best_fdr;
+ bfd_vma best_dist = ~0;
+ PDR pdr;
+ unsigned char *line_ptr;
+ unsigned char *line_end;
+ int lineno;
+ /* This file uses ECOFF debugging information. Each FDR has a
+ list of procedure descriptors (PDR). The address in the FDR
+ is the absolute address of the first procedure. The address
+ in the first PDR gives the offset of that procedure relative
+ to the object file's base-address. The addresses in
+ subsequent PDRs specify each procedure's address relative to
+ the object file's base-address. To make things more juicy,
+ whenever the PROF bit in the PDR is set, the real entry point
+ of the procedure may be 16 bytes below what would normally be
+ the procedure's entry point. Instead, DEC came up with a
+ wicked scheme to create profiled libraries "on the fly":
+ instead of shipping a regular and a profiled version of each
+ library, they insert 16 bytes of unused space in front of
+ each procedure and set the "prof" bit in the PDR to indicate
+ that there is a gap there (this is done automagically by "as"
+ when option "-pg" is specified). Thus, normally, you link
+ against such a library and, except for lots of 16 byte gaps
+ between functions, things will behave as usual. However,
+ when invoking "ld" with option "-pg", it will fill those gaps
+ with code that calls mcount(). It then moves the function's
+ entry point down by 16 bytes, and out pops a binary that has
+ all functions profiled.
+
+ NOTE: Neither FDRs nor PDRs are strictly sorted in memory
+ order. For example, when including header-files that
+ define functions, the FDRs follow behind the including
+ file, even though their code may have been generated at
+ a lower address. File coff-alpha.c from libbfd
+ illustrates this (use "odump -PFv" to look at a file's
+ FDR/PDR). Similarly, PDRs are sometimes out of order
+ as well. An example of this is OSF/1 v3.0 libc's
+ malloc.c. I'm not sure why this happens, but it could
+ be due to optimizations that reorder a function's
+ position within an object-file.
+
+ Strategy:
+
+ On the first call to this function, we build a table of FDRs
+ that is sorted by the base-address of the object-file the FDR
+ is referring to. Notice that each object-file may contain
+ code from multiple source files (e.g., due to code defined in
+ include files). Thus, for any given base-address, there may
+ be multiple FDRs (but this case is, fortunately, uncommon).
+ lookup(addr) guarantees to return the first FDR that applies
+ to address ADDR. Thus, after invoking lookup(), we have a
+ list of FDRs that may contain the PDR for ADDR. Next, we
+ walk through the PDRs of these FDRs and locate the one that
+ is closest to ADDR (i.e., for which the difference between
+ ADDR and the PDR's entry point is positive and minimal).
+ Once, the right FDR and PDR are located, we simply walk
+ through the line-number table to lookup the line-number that
+ best matches ADDR. Obviously, things could be sped up by
+ keeping a sorted list of PDRs instead of a sorted list of
+ FDRs. However, this would increase space requirements
+ considerably, which is undesirable. */
+ external_pdr_size = debug_swap->external_pdr_size;
+
+ /* Make offset relative to object file's start-address: */
+ offset -= tab[i].base_addr;
+ /* Search FDR list starting at tab[i] for the PDR that best matches
+ OFFSET. Normally, the FDR list is only one entry long. */
+ best_fdr = NULL;
+ do
+ {
+ bfd_vma dist, min_dist = 0;
+ char *pdr_hold;
+ char *pdr_end;
+
+ fdr_ptr = tab[i].fdr;
+
+ pdr_ptr = ((char *) debug_info->external_pdr
+ + fdr_ptr->ipdFirst * external_pdr_size);
+ pdr_end = pdr_ptr + fdr_ptr->cpd * external_pdr_size;
+ (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+ /* Find PDR that is closest to OFFSET. If pdr.prof is set,
+ the procedure entry-point *may* be 0x10 below pdr.adr. We
+ simply pretend that pdr.prof *implies* a lower entry-point.
+ This is safe because it just means that may identify 4 NOPs
+ in front of the function as belonging to the function. */
+ for (pdr_hold = NULL;
+ pdr_ptr < pdr_end;
+ (pdr_ptr += external_pdr_size,
+ (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr)))
+ {
+ if (offset >= (pdr.adr - 0x10 * pdr.prof))
+ {
+ dist = offset - (pdr.adr - 0x10 * pdr.prof);
+ if (!pdr_hold || dist < min_dist)
+ {
+ min_dist = dist;
+ pdr_hold = pdr_ptr;
+ }
+ }
+ }
+
+ if (!best_pdr || min_dist < best_dist)
+ {
+ best_dist = min_dist;
+ best_fdr = fdr_ptr;
+ best_pdr = pdr_hold;
+ }
+ /* continue looping until base_addr of next entry is different: */
+ }
+ while (++i < line_info->fdrtab_len
+ && tab[i].base_addr == tab[i - 1].base_addr);
+
+ if (!best_fdr || !best_pdr)
+ return false; /* shouldn't happen... */
+
+ /* phew, finally we got something that we can hold onto: */
+ fdr_ptr = best_fdr;
+ pdr_ptr = best_pdr;
+ (*debug_swap->swap_pdr_in) (abfd, (PTR) pdr_ptr, &pdr);
+ /* Now we can look for the actual line number. The line numbers
+ are stored in a very funky format, which I won't try to
+ describe. The search is bounded by the end of the FDRs line
+ number entries. */
+ line_end = debug_info->line + fdr_ptr->cbLineOffset + fdr_ptr->cbLine;
+
+ /* Make offset relative to procedure entry: */
+ offset -= pdr.adr - 0x10 * pdr.prof;
+ lineno = pdr.lnLow;
+ line_ptr = debug_info->line + fdr_ptr->cbLineOffset + pdr.cbLineOffset;
+ while (line_ptr < line_end)
+ {
+ int delta;
+ unsigned int count;
+
+ delta = *line_ptr >> 4;
+ if (delta >= 0x8)
+ delta -= 0x10;
+ count = (*line_ptr & 0xf) + 1;
+ ++line_ptr;
+ if (delta == -8)
+ {
+ delta = (((line_ptr[0]) & 0xff) << 8) + ((line_ptr[1]) & 0xff);
+ if (delta >= 0x8000)
+ delta -= 0x10000;
+ line_ptr += 2;
+ }
+ lineno += delta;
+ if (offset < count * 4)
+ break;
+ offset -= count * 4;
+ }
+
+ /* If fdr_ptr->rss is -1, then this file does not have full
+ symbols, at least according to gdb/mipsread.c. */
+ if (fdr_ptr->rss == -1)
+ {
+ *filename_ptr = NULL;
+ if (pdr.isym == -1)
+ *functionname_ptr = NULL;
+ else
+ {
+ EXTR proc_ext;
+
+ (*debug_swap->swap_ext_in)
+ (abfd,
+ ((char *) debug_info->external_ext
+ + pdr.isym * debug_swap->external_ext_size),
+ &proc_ext);
+ *functionname_ptr = debug_info->ssext + proc_ext.asym.iss;
+ }
+ }
+ else
+ {
+ SYMR proc_sym;
+
+ *filename_ptr = debug_info->ss + fdr_ptr->issBase + fdr_ptr->rss;
+ (*debug_swap->swap_sym_in)
+ (abfd,
+ ((char *) debug_info->external_sym
+ + (fdr_ptr->isymBase + pdr.isym) * debug_swap->external_sym_size),
+ &proc_sym);
+ *functionname_ptr = debug_info->ss + fdr_ptr->issBase + proc_sym.iss;
+ }
+ if (lineno == ilineNil)
+ lineno = 0;
+ *retline_ptr = lineno;
+ }
+ else
+ {
+ bfd_size_type external_sym_size;
+ const char *directory_name;
+ const char *main_file_name;
+ const char *current_file_name;
+ const char *function_name;
+ const char *line_file_name;
+ bfd_vma low_func_vma;
+ bfd_vma low_line_vma;
+ boolean past_line;
+ boolean past_fn;
+ char *sym_ptr, *sym_ptr_end;
+ size_t len, funclen;
+ char *buffer = NULL;
+
+ /* This file uses stabs debugging information. When gcc is not
+ optimizing, it will put the line number information before
+ the function name stabs entry. When gcc is optimizing, it
+ will put the stabs entry for all the function first, followed
+ by the line number information. (This appears to happen
+ because of the two output files used by the -mgpopt switch,
+ which is implied by -O). This means that we must keep
+ looking through the symbols until we find both a line number
+ and a function name which are beyond the address we want. */
+
+ *filename_ptr = NULL;
+ *functionname_ptr = NULL;
+ *retline_ptr = 0;
+
+ directory_name = NULL;
+ main_file_name = NULL;
+ current_file_name = NULL;
+ function_name = NULL;
+ line_file_name = NULL;
+ low_func_vma = 0;
+ low_line_vma = 0;
+ past_line = false;
+ past_fn = false;
+
+ external_sym_size = debug_swap->external_sym_size;
+
+ sym_ptr = ((char *) debug_info->external_sym
+ + (fdr_ptr->isymBase + 2) * external_sym_size);
+ sym_ptr_end = sym_ptr + (fdr_ptr->csym - 2) * external_sym_size;
+ for (;
+ sym_ptr < sym_ptr_end && (! past_line || ! past_fn);
+ sym_ptr += external_sym_size)
+ {
+ SYMR sym;
+
+ (*debug_swap->swap_sym_in) (abfd, sym_ptr, &sym);
+
+ if (ECOFF_IS_STAB (&sym))
+ {
+ switch (ECOFF_UNMARK_STAB (sym.index))
+ {
+ case N_SO:
+ main_file_name = current_file_name =
+ debug_info->ss + fdr_ptr->issBase + sym.iss;
+
+ /* Check the next symbol to see if it is also an
+ N_SO symbol. */
+ if (sym_ptr + external_sym_size < sym_ptr_end)
+ {
+ SYMR nextsym;
+
+ (*debug_swap->swap_sym_in) (abfd,
+ sym_ptr + external_sym_size,
+ &nextsym);
+ if (ECOFF_IS_STAB (&nextsym)
+ && ECOFF_UNMARK_STAB (nextsym.index) == N_SO)
+ {
+ directory_name = current_file_name;
+ main_file_name = current_file_name =
+ debug_info->ss + fdr_ptr->issBase + nextsym.iss;
+ sym_ptr += external_sym_size;
+ }
+ }
+ break;
+
+ case N_SOL:
+ current_file_name =
+ debug_info->ss + fdr_ptr->issBase + sym.iss;
+ break;
+
+ case N_FUN:
+ if (sym.value > offset)
+ past_fn = true;
+ else if (sym.value >= low_func_vma)
+ {
+ low_func_vma = sym.value;
+ function_name =
+ debug_info->ss + fdr_ptr->issBase + sym.iss;
+ }
+ break;
+ }
+ }
+ else if (sym.st == stLabel && sym.index != indexNil)
+ {
+ if (sym.value > offset)
+ past_line = true;
+ else if (sym.value >= low_line_vma)
+ {
+ low_line_vma = sym.value;
+ line_file_name = current_file_name;
+ *retline_ptr = sym.index;
+ }
+ }
+ }
+
+ if (*retline_ptr != 0)
+ main_file_name = line_file_name;
+
+ /* We need to remove the stuff after the colon in the function
+ name. We also need to put the directory name and the file
+ name together. */
+ if (function_name == NULL)
+ len = funclen = 0;
+ else
+ len = funclen = strlen (function_name) + 1;
+
+ if (main_file_name != NULL
+ && directory_name != NULL
+ && main_file_name[0] != '/')
+ len += strlen (directory_name) + strlen (main_file_name) + 1;
+
+ if (len != 0)
+ {
+ if (line_info->find_buffer != NULL)
+ free (line_info->find_buffer);
+ buffer = (char *) bfd_malloc (len);
+ if (buffer == NULL)
+ return false;
+ line_info->find_buffer = buffer;
+ }
+
+ if (function_name != NULL)
+ {
+ char *colon;
+
+ strcpy (buffer, function_name);
+ colon = strchr (buffer, ':');
+ if (colon != NULL)
+ *colon = '\0';
+ *functionname_ptr = buffer;
+ }
+
+ if (main_file_name != NULL)
+ {
+ if (directory_name == NULL || main_file_name[0] == '/')
+ *filename_ptr = main_file_name;
+ else
+ {
+ sprintf (buffer + funclen, "%s%s", directory_name,
+ main_file_name);
+ *filename_ptr = buffer + funclen;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* These routines copy symbolic information into a memory buffer.
+
+ FIXME: The whole point of the shuffle code is to avoid storing
+ everything in memory, since the linker is such a memory hog. This
+ code makes that effort useless. It is only called by the MIPS ELF
+ code when generating a shared library, so it is not that big a
+ deal, but it should be fixed eventually. */
+
+/* Collect a shuffle into a memory buffer. */
+
+static boolean ecoff_collect_shuffle PARAMS ((struct shuffle *, bfd_byte *));
+
+static boolean
+ecoff_collect_shuffle (l, buff)
+ struct shuffle *l;
+ bfd_byte *buff;
+{
+ unsigned long total;
+
+ total = 0;
+ for (; l != (struct shuffle *) NULL; l = l->next)
+ {
+ if (! l->filep)
+ memcpy (buff, l->u.memory, l->size);
+ else
+ {
+ if (bfd_seek (l->u.file.input_bfd, l->u.file.offset, SEEK_SET) != 0
+ || bfd_read (buff, 1, l->size, l->u.file.input_bfd) != l->size)
+ return false;
+ }
+ total += l->size;
+ buff += l->size;
+ }
+
+ return true;
+}
+
+/* Copy PDR information into a memory buffer. */
+
+boolean
+_bfd_ecoff_get_accumulated_pdr (handle, buff)
+ PTR handle;
+ bfd_byte *buff;
+{
+ struct accumulate *ainfo = (struct accumulate *) handle;
+
+ return ecoff_collect_shuffle (ainfo->pdr, buff);
+}
+
+/* Copy symbol information into a memory buffer. */
+
+boolean
+_bfd_ecoff_get_accumulated_sym (handle, buff)
+ PTR handle;
+ bfd_byte *buff;
+{
+ struct accumulate *ainfo = (struct accumulate *) handle;
+
+ return ecoff_collect_shuffle (ainfo->sym, buff);
+}
+
+/* Copy the string table into a memory buffer. */
+
+boolean
+_bfd_ecoff_get_accumulated_ss (handle, buff)
+ PTR handle;
+ bfd_byte *buff;
+{
+ struct accumulate *ainfo = (struct accumulate *) handle;
+ struct string_hash_entry *sh;
+ unsigned long total;
+
+ /* The string table is written out from the hash table if this is a
+ final link. */
+ BFD_ASSERT (ainfo->ss == (struct shuffle *) NULL);
+ *buff++ = '\0';
+ total = 1;
+ BFD_ASSERT (ainfo->ss_hash == NULL || ainfo->ss_hash->val == 1);
+ for (sh = ainfo->ss_hash;
+ sh != (struct string_hash_entry *) NULL;
+ sh = sh->next)
+ {
+ size_t len;
+
+ len = strlen (sh->root.string);
+ memcpy (buff, (PTR) sh->root.string, len + 1);
+ total += len + 1;
+ buff += len + 1;
+ }
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/ecoffswap.h b/contrib/gdb/bfd/ecoffswap.h
new file mode 100644
index 0000000..0d28d16
--- /dev/null
+++ b/contrib/gdb/bfd/ecoffswap.h
@@ -0,0 +1,853 @@
+/* Generic ECOFF swapping routines, for BFD.
+ Copyright 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* NOTE: This is a header file, but it contains executable routines.
+ This is done this way because these routines are substantially
+ similar, but are not identical, for all ECOFF targets.
+
+ These are routines to swap the ECOFF symbolic information in and
+ out. The routines are defined statically. You can set breakpoints
+ on them in gdb by naming the including source file; e.g.,
+ 'coff-mips.c':ecoff_swap_hdr_in.
+
+ Before including this header file, one of ECOFF_32 or ECOFF_64 must
+ be defined. These are checked when swapping information that
+ depends upon the target size. This code works for 32 bit and 64
+ bit ECOFF, but may need to be generalized in the future.
+
+ Some header file which defines the external forms of these
+ structures must also be included before including this header file.
+ Currently this is either coff/mips.h or coff/alpha.h.
+
+ If the symbol TEST is defined when this file is compiled, a
+ comparison is made to ensure that, in fact, the output is
+ bit-for-bit the same as the input. Of course, this symbol should
+ only be defined when deliberately testing the code on a machine
+ with the proper byte sex and such. */
+
+#ifdef ECOFF_32
+#define ecoff_get_off bfd_h_get_32
+#define ecoff_put_off bfd_h_put_32
+#endif
+#ifdef ECOFF_64
+#define ecoff_get_off bfd_h_get_64
+#define ecoff_put_off bfd_h_put_64
+#endif
+
+/* ECOFF auxiliary information swapping routines. These are the same
+ for all ECOFF targets, so they are defined in ecofflink.c. */
+
+extern void _bfd_ecoff_swap_tir_in
+ PARAMS ((int, const struct tir_ext *, TIR *));
+extern void _bfd_ecoff_swap_tir_out
+ PARAMS ((int, const TIR *, struct tir_ext *));
+extern void _bfd_ecoff_swap_rndx_in
+ PARAMS ((int, const struct rndx_ext *, RNDXR *));
+extern void _bfd_ecoff_swap_rndx_out
+ PARAMS ((int, const RNDXR *, struct rndx_ext *));
+
+/* Prototypes for functions defined in this file. */
+
+static void ecoff_swap_hdr_in PARAMS ((bfd *, PTR, HDRR *));
+static void ecoff_swap_hdr_out PARAMS ((bfd *, const HDRR *, PTR));
+static void ecoff_swap_fdr_in PARAMS ((bfd *, PTR, FDR *));
+static void ecoff_swap_fdr_out PARAMS ((bfd *, const FDR *, PTR));
+static void ecoff_swap_pdr_in PARAMS ((bfd *, PTR, PDR *));
+static void ecoff_swap_pdr_out PARAMS ((bfd *, const PDR *, PTR));
+static void ecoff_swap_sym_in PARAMS ((bfd *, PTR, SYMR *));
+static void ecoff_swap_sym_out PARAMS ((bfd *, const SYMR *, PTR));
+static void ecoff_swap_ext_in PARAMS ((bfd *, PTR, EXTR *));
+static void ecoff_swap_ext_out PARAMS ((bfd *, const EXTR *, PTR));
+static void ecoff_swap_rfd_in PARAMS ((bfd *, PTR, RFDT *));
+static void ecoff_swap_rfd_out PARAMS ((bfd *, const RFDT *, PTR));
+static void ecoff_swap_opt_in PARAMS ((bfd *, PTR, OPTR *));
+static void ecoff_swap_opt_out PARAMS ((bfd *, const OPTR *, PTR));
+static void ecoff_swap_dnr_in PARAMS ((bfd *, PTR, DNR *));
+static void ecoff_swap_dnr_out PARAMS ((bfd *, const DNR *, PTR));
+
+/* Swap in the symbolic header. */
+
+static void
+ecoff_swap_hdr_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ HDRR *intern;
+{
+ struct hdr_ext ext[1];
+
+ *ext = *(struct hdr_ext *) ext_copy;
+
+ intern->magic = bfd_h_get_signed_16 (abfd, (bfd_byte *)ext->h_magic);
+ intern->vstamp = bfd_h_get_signed_16 (abfd, (bfd_byte *)ext->h_vstamp);
+ intern->ilineMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_ilineMax);
+ intern->cbLine = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbLine);
+ intern->cbLineOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbLineOffset);
+ intern->idnMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_idnMax);
+ intern->cbDnOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbDnOffset);
+ intern->ipdMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_ipdMax);
+ intern->cbPdOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbPdOffset);
+ intern->isymMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_isymMax);
+ intern->cbSymOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbSymOffset);
+ intern->ioptMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_ioptMax);
+ intern->cbOptOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbOptOffset);
+ intern->iauxMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_iauxMax);
+ intern->cbAuxOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbAuxOffset);
+ intern->issMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_issMax);
+ intern->cbSsOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbSsOffset);
+ intern->issExtMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_issExtMax);
+ intern->cbSsExtOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbSsExtOffset);
+ intern->ifdMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_ifdMax);
+ intern->cbFdOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbFdOffset);
+ intern->crfd = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_crfd);
+ intern->cbRfdOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbRfdOffset);
+ intern->iextMax = bfd_h_get_32 (abfd, (bfd_byte *)ext->h_iextMax);
+ intern->cbExtOffset = ecoff_get_off (abfd, (bfd_byte *)ext->h_cbExtOffset);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out the symbolic header. */
+
+static void
+ecoff_swap_hdr_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const HDRR *intern_copy;
+ PTR ext_ptr;
+{
+ struct hdr_ext *ext = (struct hdr_ext *) ext_ptr;
+ HDRR intern[1];
+
+ *intern = *intern_copy;
+
+ bfd_h_put_signed_16 (abfd, intern->magic, (bfd_byte *)ext->h_magic);
+ bfd_h_put_signed_16 (abfd, intern->vstamp, (bfd_byte *)ext->h_vstamp);
+ bfd_h_put_32 (abfd, intern->ilineMax, (bfd_byte *)ext->h_ilineMax);
+ ecoff_put_off (abfd, intern->cbLine, (bfd_byte *)ext->h_cbLine);
+ ecoff_put_off (abfd, intern->cbLineOffset, (bfd_byte *)ext->h_cbLineOffset);
+ bfd_h_put_32 (abfd, intern->idnMax, (bfd_byte *)ext->h_idnMax);
+ ecoff_put_off (abfd, intern->cbDnOffset, (bfd_byte *)ext->h_cbDnOffset);
+ bfd_h_put_32 (abfd, intern->ipdMax, (bfd_byte *)ext->h_ipdMax);
+ ecoff_put_off (abfd, intern->cbPdOffset, (bfd_byte *)ext->h_cbPdOffset);
+ bfd_h_put_32 (abfd, intern->isymMax, (bfd_byte *)ext->h_isymMax);
+ ecoff_put_off (abfd, intern->cbSymOffset, (bfd_byte *)ext->h_cbSymOffset);
+ bfd_h_put_32 (abfd, intern->ioptMax, (bfd_byte *)ext->h_ioptMax);
+ ecoff_put_off (abfd, intern->cbOptOffset, (bfd_byte *)ext->h_cbOptOffset);
+ bfd_h_put_32 (abfd, intern->iauxMax, (bfd_byte *)ext->h_iauxMax);
+ ecoff_put_off (abfd, intern->cbAuxOffset, (bfd_byte *)ext->h_cbAuxOffset);
+ bfd_h_put_32 (abfd, intern->issMax, (bfd_byte *)ext->h_issMax);
+ ecoff_put_off (abfd, intern->cbSsOffset, (bfd_byte *)ext->h_cbSsOffset);
+ bfd_h_put_32 (abfd, intern->issExtMax, (bfd_byte *)ext->h_issExtMax);
+ ecoff_put_off (abfd, intern->cbSsExtOffset, (bfd_byte *)ext->h_cbSsExtOffset);
+ bfd_h_put_32 (abfd, intern->ifdMax, (bfd_byte *)ext->h_ifdMax);
+ ecoff_put_off (abfd, intern->cbFdOffset, (bfd_byte *)ext->h_cbFdOffset);
+ bfd_h_put_32 (abfd, intern->crfd, (bfd_byte *)ext->h_crfd);
+ ecoff_put_off (abfd, intern->cbRfdOffset, (bfd_byte *)ext->h_cbRfdOffset);
+ bfd_h_put_32 (abfd, intern->iextMax, (bfd_byte *)ext->h_iextMax);
+ ecoff_put_off (abfd, intern->cbExtOffset, (bfd_byte *)ext->h_cbExtOffset);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap in the file descriptor record. */
+
+static void
+ecoff_swap_fdr_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ FDR *intern;
+{
+ struct fdr_ext ext[1];
+
+ *ext = *(struct fdr_ext *) ext_copy;
+
+ intern->adr = ecoff_get_off (abfd, (bfd_byte *)ext->f_adr);
+ intern->rss = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_rss);
+#ifdef ECOFF_64
+ if (intern->rss == 0xffffffff)
+ intern->rss = -1;
+#endif
+ intern->issBase = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_issBase);
+ intern->cbSs = ecoff_get_off (abfd, (bfd_byte *)ext->f_cbSs);
+ intern->isymBase = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_isymBase);
+ intern->csym = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_csym);
+ intern->ilineBase = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_ilineBase);
+ intern->cline = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_cline);
+ intern->ioptBase = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_ioptBase);
+ intern->copt = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_copt);
+#ifdef ECOFF_32
+ intern->ipdFirst = bfd_h_get_16 (abfd, (bfd_byte *)ext->f_ipdFirst);
+ intern->cpd = bfd_h_get_16 (abfd, (bfd_byte *)ext->f_cpd);
+#endif
+#ifdef ECOFF_64
+ intern->ipdFirst = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_ipdFirst);
+ intern->cpd = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_cpd);
+#endif
+ intern->iauxBase = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_iauxBase);
+ intern->caux = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_caux);
+ intern->rfdBase = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_rfdBase);
+ intern->crfd = bfd_h_get_32 (abfd, (bfd_byte *)ext->f_crfd);
+
+ /* now the fun stuff... */
+ if (bfd_header_big_endian (abfd)) {
+ intern->lang = (ext->f_bits1[0] & FDR_BITS1_LANG_BIG)
+ >> FDR_BITS1_LANG_SH_BIG;
+ intern->fMerge = 0 != (ext->f_bits1[0] & FDR_BITS1_FMERGE_BIG);
+ intern->fReadin = 0 != (ext->f_bits1[0] & FDR_BITS1_FREADIN_BIG);
+ intern->fBigendian = 0 != (ext->f_bits1[0] & FDR_BITS1_FBIGENDIAN_BIG);
+ intern->glevel = (ext->f_bits2[0] & FDR_BITS2_GLEVEL_BIG)
+ >> FDR_BITS2_GLEVEL_SH_BIG;
+ } else {
+ intern->lang = (ext->f_bits1[0] & FDR_BITS1_LANG_LITTLE)
+ >> FDR_BITS1_LANG_SH_LITTLE;
+ intern->fMerge = 0 != (ext->f_bits1[0] & FDR_BITS1_FMERGE_LITTLE);
+ intern->fReadin = 0 != (ext->f_bits1[0] & FDR_BITS1_FREADIN_LITTLE);
+ intern->fBigendian = 0 != (ext->f_bits1[0] & FDR_BITS1_FBIGENDIAN_LITTLE);
+ intern->glevel = (ext->f_bits2[0] & FDR_BITS2_GLEVEL_LITTLE)
+ >> FDR_BITS2_GLEVEL_SH_LITTLE;
+ }
+ intern->reserved = 0;
+
+ intern->cbLineOffset = ecoff_get_off (abfd, (bfd_byte *)ext->f_cbLineOffset);
+ intern->cbLine = ecoff_get_off (abfd, (bfd_byte *)ext->f_cbLine);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out the file descriptor record. */
+
+static void
+ecoff_swap_fdr_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const FDR *intern_copy;
+ PTR ext_ptr;
+{
+ struct fdr_ext *ext = (struct fdr_ext *) ext_ptr;
+ FDR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ ecoff_put_off (abfd, intern->adr, (bfd_byte *)ext->f_adr);
+ bfd_h_put_32 (abfd, intern->rss, (bfd_byte *)ext->f_rss);
+ bfd_h_put_32 (abfd, intern->issBase, (bfd_byte *)ext->f_issBase);
+ ecoff_put_off (abfd, intern->cbSs, (bfd_byte *)ext->f_cbSs);
+ bfd_h_put_32 (abfd, intern->isymBase, (bfd_byte *)ext->f_isymBase);
+ bfd_h_put_32 (abfd, intern->csym, (bfd_byte *)ext->f_csym);
+ bfd_h_put_32 (abfd, intern->ilineBase, (bfd_byte *)ext->f_ilineBase);
+ bfd_h_put_32 (abfd, intern->cline, (bfd_byte *)ext->f_cline);
+ bfd_h_put_32 (abfd, intern->ioptBase, (bfd_byte *)ext->f_ioptBase);
+ bfd_h_put_32 (abfd, intern->copt, (bfd_byte *)ext->f_copt);
+#ifdef ECOFF_32
+ bfd_h_put_16 (abfd, intern->ipdFirst, (bfd_byte *)ext->f_ipdFirst);
+ bfd_h_put_16 (abfd, intern->cpd, (bfd_byte *)ext->f_cpd);
+#endif
+#ifdef ECOFF_64
+ bfd_h_put_32 (abfd, intern->ipdFirst, (bfd_byte *)ext->f_ipdFirst);
+ bfd_h_put_32 (abfd, intern->cpd, (bfd_byte *)ext->f_cpd);
+#endif
+ bfd_h_put_32 (abfd, intern->iauxBase, (bfd_byte *)ext->f_iauxBase);
+ bfd_h_put_32 (abfd, intern->caux, (bfd_byte *)ext->f_caux);
+ bfd_h_put_32 (abfd, intern->rfdBase, (bfd_byte *)ext->f_rfdBase);
+ bfd_h_put_32 (abfd, intern->crfd, (bfd_byte *)ext->f_crfd);
+
+ /* now the fun stuff... */
+ if (bfd_header_big_endian (abfd)) {
+ ext->f_bits1[0] = (((intern->lang << FDR_BITS1_LANG_SH_BIG)
+ & FDR_BITS1_LANG_BIG)
+ | (intern->fMerge ? FDR_BITS1_FMERGE_BIG : 0)
+ | (intern->fReadin ? FDR_BITS1_FREADIN_BIG : 0)
+ | (intern->fBigendian ? FDR_BITS1_FBIGENDIAN_BIG : 0));
+ ext->f_bits2[0] = ((intern->glevel << FDR_BITS2_GLEVEL_SH_BIG)
+ & FDR_BITS2_GLEVEL_BIG);
+ ext->f_bits2[1] = 0;
+ ext->f_bits2[2] = 0;
+ } else {
+ ext->f_bits1[0] = (((intern->lang << FDR_BITS1_LANG_SH_LITTLE)
+ & FDR_BITS1_LANG_LITTLE)
+ | (intern->fMerge ? FDR_BITS1_FMERGE_LITTLE : 0)
+ | (intern->fReadin ? FDR_BITS1_FREADIN_LITTLE : 0)
+ | (intern->fBigendian ? FDR_BITS1_FBIGENDIAN_LITTLE : 0));
+ ext->f_bits2[0] = ((intern->glevel << FDR_BITS2_GLEVEL_SH_LITTLE)
+ & FDR_BITS2_GLEVEL_LITTLE);
+ ext->f_bits2[1] = 0;
+ ext->f_bits2[2] = 0;
+ }
+
+ ecoff_put_off (abfd, intern->cbLineOffset, (bfd_byte *)ext->f_cbLineOffset);
+ ecoff_put_off (abfd, intern->cbLine, (bfd_byte *)ext->f_cbLine);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+#ifndef MPW_C
+
+/* Swap in the procedure descriptor record. */
+
+static void
+ecoff_swap_pdr_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ PDR *intern;
+{
+ struct pdr_ext ext[1];
+
+ *ext = *(struct pdr_ext *) ext_copy;
+
+ memset ((PTR) intern, 0, sizeof (*intern));
+
+ intern->adr = ecoff_get_off (abfd, (bfd_byte *)ext->p_adr);
+ intern->isym = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_isym);
+ intern->iline = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_iline);
+ intern->regmask = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_regmask);
+ intern->regoffset = bfd_h_get_signed_32 (abfd,
+ (bfd_byte *)ext->p_regoffset);
+ intern->iopt = bfd_h_get_signed_32 (abfd, (bfd_byte *)ext->p_iopt);
+ intern->fregmask = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_fregmask);
+ intern->fregoffset = bfd_h_get_signed_32 (abfd,
+ (bfd_byte *)ext->p_fregoffset);
+ intern->frameoffset = bfd_h_get_signed_32 (abfd,
+ (bfd_byte *)ext->p_frameoffset);
+ intern->framereg = bfd_h_get_16 (abfd, (bfd_byte *)ext->p_framereg);
+ intern->pcreg = bfd_h_get_16 (abfd, (bfd_byte *)ext->p_pcreg);
+ intern->lnLow = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_lnLow);
+ intern->lnHigh = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_lnHigh);
+ intern->cbLineOffset = ecoff_get_off (abfd, (bfd_byte *)ext->p_cbLineOffset);
+
+#ifdef ECOFF_64
+ intern->gp_prologue = bfd_h_get_8 (abfd, (bfd_byte *) ext->p_gp_prologue);
+ if (bfd_header_big_endian (abfd))
+ {
+ intern->gp_used = 0 != (ext->p_bits1[0] & PDR_BITS1_GP_USED_BIG);
+ intern->reg_frame = 0 != (ext->p_bits1[0] & PDR_BITS1_REG_FRAME_BIG);
+ intern->prof = 0 != (ext->p_bits1[0] & PDR_BITS1_PROF_BIG);
+ intern->reserved = (((ext->p_bits1[0] & PDR_BITS1_RESERVED_BIG)
+ << PDR_BITS1_RESERVED_SH_LEFT_BIG)
+ | ((ext->p_bits2[0] & PDR_BITS2_RESERVED_BIG)
+ >> PDR_BITS2_RESERVED_SH_BIG));
+ }
+ else
+ {
+ intern->gp_used = 0 != (ext->p_bits1[0] & PDR_BITS1_GP_USED_LITTLE);
+ intern->reg_frame = 0 != (ext->p_bits1[0] & PDR_BITS1_REG_FRAME_LITTLE);
+ intern->prof = 0 != (ext->p_bits1[0] & PDR_BITS1_PROF_LITTLE);
+ intern->reserved = (((ext->p_bits1[0] & PDR_BITS1_RESERVED_LITTLE)
+ >> PDR_BITS1_RESERVED_SH_LITTLE)
+ | ((ext->p_bits2[0] & PDR_BITS2_RESERVED_LITTLE)
+ << PDR_BITS2_RESERVED_SH_LEFT_LITTLE));
+ }
+ intern->localoff = bfd_h_get_8 (abfd, (bfd_byte *) ext->p_localoff);
+#endif
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out the procedure descriptor record. */
+
+static void
+ecoff_swap_pdr_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const PDR *intern_copy;
+ PTR ext_ptr;
+{
+ struct pdr_ext *ext = (struct pdr_ext *) ext_ptr;
+ PDR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ ecoff_put_off (abfd, intern->adr, (bfd_byte *)ext->p_adr);
+ bfd_h_put_32 (abfd, intern->isym, (bfd_byte *)ext->p_isym);
+ bfd_h_put_32 (abfd, intern->iline, (bfd_byte *)ext->p_iline);
+ bfd_h_put_32 (abfd, intern->regmask, (bfd_byte *)ext->p_regmask);
+ bfd_h_put_32 (abfd, intern->regoffset, (bfd_byte *)ext->p_regoffset);
+ bfd_h_put_32 (abfd, intern->iopt, (bfd_byte *)ext->p_iopt);
+ bfd_h_put_32 (abfd, intern->fregmask, (bfd_byte *)ext->p_fregmask);
+ bfd_h_put_32 (abfd, intern->fregoffset, (bfd_byte *)ext->p_fregoffset);
+ bfd_h_put_32 (abfd, intern->frameoffset, (bfd_byte *)ext->p_frameoffset);
+ bfd_h_put_16 (abfd, intern->framereg, (bfd_byte *)ext->p_framereg);
+ bfd_h_put_16 (abfd, intern->pcreg, (bfd_byte *)ext->p_pcreg);
+ bfd_h_put_32 (abfd, intern->lnLow, (bfd_byte *)ext->p_lnLow);
+ bfd_h_put_32 (abfd, intern->lnHigh, (bfd_byte *)ext->p_lnHigh);
+ ecoff_put_off (abfd, intern->cbLineOffset, (bfd_byte *)ext->p_cbLineOffset);
+
+#ifdef ECOFF_64
+ bfd_h_put_8 (abfd, intern->gp_prologue, (bfd_byte *) ext->p_gp_prologue);
+ if (bfd_header_big_endian (abfd))
+ {
+ ext->p_bits1[0] = ((intern->gp_used ? PDR_BITS1_GP_USED_BIG : 0)
+ | (intern->reg_frame ? PDR_BITS1_REG_FRAME_BIG : 0)
+ | (intern->prof ? PDR_BITS1_PROF_BIG : 0)
+ | ((intern->reserved
+ >> PDR_BITS1_RESERVED_SH_LEFT_BIG)
+ & PDR_BITS1_RESERVED_BIG));
+ ext->p_bits2[0] = ((intern->reserved << PDR_BITS2_RESERVED_SH_BIG)
+ & PDR_BITS2_RESERVED_BIG);
+ }
+ else
+ {
+ ext->p_bits1[0] = ((intern->gp_used ? PDR_BITS1_GP_USED_LITTLE : 0)
+ | (intern->reg_frame ? PDR_BITS1_REG_FRAME_LITTLE : 0)
+ | (intern->prof ? PDR_BITS1_PROF_LITTLE : 0)
+ | ((intern->reserved << PDR_BITS1_RESERVED_SH_LITTLE)
+ & PDR_BITS1_RESERVED_LITTLE));
+ ext->p_bits2[0] = ((intern->reserved >>
+ PDR_BITS2_RESERVED_SH_LEFT_LITTLE)
+ & PDR_BITS2_RESERVED_LITTLE);
+ }
+ bfd_h_put_8 (abfd, intern->localoff, (bfd_byte *) ext->p_localoff);
+#endif
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+#else /* MPW_C */
+/* Same routines, but with ECOFF_64 code removed, so ^&%$#&! MPW C doesn't
+ corrupt itself and then freak out. */
+/* Swap in the procedure descriptor record. */
+
+static void
+ecoff_swap_pdr_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ PDR *intern;
+{
+ struct pdr_ext ext[1];
+
+ *ext = *(struct pdr_ext *) ext_copy;
+
+ intern->adr = ecoff_get_off (abfd, (bfd_byte *)ext->p_adr);
+ intern->isym = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_isym);
+ intern->iline = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_iline);
+ intern->regmask = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_regmask);
+ intern->regoffset = bfd_h_get_signed_32 (abfd,
+ (bfd_byte *)ext->p_regoffset);
+ intern->iopt = bfd_h_get_signed_32 (abfd, (bfd_byte *)ext->p_iopt);
+ intern->fregmask = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_fregmask);
+ intern->fregoffset = bfd_h_get_signed_32 (abfd,
+ (bfd_byte *)ext->p_fregoffset);
+ intern->frameoffset = bfd_h_get_signed_32 (abfd,
+ (bfd_byte *)ext->p_frameoffset);
+ intern->framereg = bfd_h_get_16 (abfd, (bfd_byte *)ext->p_framereg);
+ intern->pcreg = bfd_h_get_16 (abfd, (bfd_byte *)ext->p_pcreg);
+ intern->lnLow = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_lnLow);
+ intern->lnHigh = bfd_h_get_32 (abfd, (bfd_byte *)ext->p_lnHigh);
+ intern->cbLineOffset = ecoff_get_off (abfd, (bfd_byte *)ext->p_cbLineOffset);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out the procedure descriptor record. */
+
+static void
+ecoff_swap_pdr_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const PDR *intern_copy;
+ PTR ext_ptr;
+{
+ struct pdr_ext *ext = (struct pdr_ext *) ext_ptr;
+ PDR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ ecoff_put_off (abfd, intern->adr, (bfd_byte *)ext->p_adr);
+ bfd_h_put_32 (abfd, intern->isym, (bfd_byte *)ext->p_isym);
+ bfd_h_put_32 (abfd, intern->iline, (bfd_byte *)ext->p_iline);
+ bfd_h_put_32 (abfd, intern->regmask, (bfd_byte *)ext->p_regmask);
+ bfd_h_put_32 (abfd, intern->regoffset, (bfd_byte *)ext->p_regoffset);
+ bfd_h_put_32 (abfd, intern->iopt, (bfd_byte *)ext->p_iopt);
+ bfd_h_put_32 (abfd, intern->fregmask, (bfd_byte *)ext->p_fregmask);
+ bfd_h_put_32 (abfd, intern->fregoffset, (bfd_byte *)ext->p_fregoffset);
+ bfd_h_put_32 (abfd, intern->frameoffset, (bfd_byte *)ext->p_frameoffset);
+ bfd_h_put_16 (abfd, intern->framereg, (bfd_byte *)ext->p_framereg);
+ bfd_h_put_16 (abfd, intern->pcreg, (bfd_byte *)ext->p_pcreg);
+ bfd_h_put_32 (abfd, intern->lnLow, (bfd_byte *)ext->p_lnLow);
+ bfd_h_put_32 (abfd, intern->lnHigh, (bfd_byte *)ext->p_lnHigh);
+ ecoff_put_off (abfd, intern->cbLineOffset, (bfd_byte *)ext->p_cbLineOffset);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+#endif /* MPW_C */
+
+/* Swap in a symbol record. */
+
+static void
+ecoff_swap_sym_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ SYMR *intern;
+{
+ struct sym_ext ext[1];
+
+ *ext = *(struct sym_ext *) ext_copy;
+
+ intern->iss = bfd_h_get_32 (abfd, (bfd_byte *)ext->s_iss);
+ intern->value = ecoff_get_off (abfd, (bfd_byte *)ext->s_value);
+
+ /* now the fun stuff... */
+ if (bfd_header_big_endian (abfd)) {
+ intern->st = (ext->s_bits1[0] & SYM_BITS1_ST_BIG)
+ >> SYM_BITS1_ST_SH_BIG;
+ intern->sc = ((ext->s_bits1[0] & SYM_BITS1_SC_BIG)
+ << SYM_BITS1_SC_SH_LEFT_BIG)
+ | ((ext->s_bits2[0] & SYM_BITS2_SC_BIG)
+ >> SYM_BITS2_SC_SH_BIG);
+ intern->reserved = 0 != (ext->s_bits2[0] & SYM_BITS2_RESERVED_BIG);
+ intern->index = ((ext->s_bits2[0] & SYM_BITS2_INDEX_BIG)
+ << SYM_BITS2_INDEX_SH_LEFT_BIG)
+ | (ext->s_bits3[0] << SYM_BITS3_INDEX_SH_LEFT_BIG)
+ | (ext->s_bits4[0] << SYM_BITS4_INDEX_SH_LEFT_BIG);
+ } else {
+ intern->st = (ext->s_bits1[0] & SYM_BITS1_ST_LITTLE)
+ >> SYM_BITS1_ST_SH_LITTLE;
+ intern->sc = ((ext->s_bits1[0] & SYM_BITS1_SC_LITTLE)
+ >> SYM_BITS1_SC_SH_LITTLE)
+ | ((ext->s_bits2[0] & SYM_BITS2_SC_LITTLE)
+ << SYM_BITS2_SC_SH_LEFT_LITTLE);
+ intern->reserved = 0 != (ext->s_bits2[0] & SYM_BITS2_RESERVED_LITTLE);
+ intern->index = ((ext->s_bits2[0] & SYM_BITS2_INDEX_LITTLE)
+ >> SYM_BITS2_INDEX_SH_LITTLE)
+ | (ext->s_bits3[0] << SYM_BITS3_INDEX_SH_LEFT_LITTLE)
+ | ((unsigned int) ext->s_bits4[0]
+ << SYM_BITS4_INDEX_SH_LEFT_LITTLE);
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out a symbol record. */
+
+static void
+ecoff_swap_sym_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const SYMR *intern_copy;
+ PTR ext_ptr;
+{
+ struct sym_ext *ext = (struct sym_ext *) ext_ptr;
+ SYMR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ bfd_h_put_32 (abfd, intern->iss, (bfd_byte *)ext->s_iss);
+ ecoff_put_off (abfd, intern->value, (bfd_byte *)ext->s_value);
+
+ /* now the fun stuff... */
+ if (bfd_header_big_endian (abfd)) {
+ ext->s_bits1[0] = (((intern->st << SYM_BITS1_ST_SH_BIG)
+ & SYM_BITS1_ST_BIG)
+ | ((intern->sc >> SYM_BITS1_SC_SH_LEFT_BIG)
+ & SYM_BITS1_SC_BIG));
+ ext->s_bits2[0] = (((intern->sc << SYM_BITS2_SC_SH_BIG)
+ & SYM_BITS2_SC_BIG)
+ | (intern->reserved ? SYM_BITS2_RESERVED_BIG : 0)
+ | ((intern->index >> SYM_BITS2_INDEX_SH_LEFT_BIG)
+ & SYM_BITS2_INDEX_BIG));
+ ext->s_bits3[0] = (intern->index >> SYM_BITS3_INDEX_SH_LEFT_BIG) & 0xff;
+ ext->s_bits4[0] = (intern->index >> SYM_BITS4_INDEX_SH_LEFT_BIG) & 0xff;
+ } else {
+ ext->s_bits1[0] = (((intern->st << SYM_BITS1_ST_SH_LITTLE)
+ & SYM_BITS1_ST_LITTLE)
+ | ((intern->sc << SYM_BITS1_SC_SH_LITTLE)
+ & SYM_BITS1_SC_LITTLE));
+ ext->s_bits2[0] = (((intern->sc >> SYM_BITS2_SC_SH_LEFT_LITTLE)
+ & SYM_BITS2_SC_LITTLE)
+ | (intern->reserved ? SYM_BITS2_RESERVED_LITTLE : 0)
+ | ((intern->index << SYM_BITS2_INDEX_SH_LITTLE)
+ & SYM_BITS2_INDEX_LITTLE));
+ ext->s_bits3[0] = (intern->index >> SYM_BITS3_INDEX_SH_LEFT_LITTLE) & 0xff;
+ ext->s_bits4[0] = (intern->index >> SYM_BITS4_INDEX_SH_LEFT_LITTLE) & 0xff;
+ }
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap in an external symbol record. */
+
+static void
+ecoff_swap_ext_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ EXTR *intern;
+{
+ struct ext_ext ext[1];
+
+ *ext = *(struct ext_ext *) ext_copy;
+
+ /* now the fun stuff... */
+ if (bfd_header_big_endian (abfd)) {
+ intern->jmptbl = 0 != (ext->es_bits1[0] & EXT_BITS1_JMPTBL_BIG);
+ intern->cobol_main = 0 != (ext->es_bits1[0] & EXT_BITS1_COBOL_MAIN_BIG);
+ intern->weakext = 0 != (ext->es_bits1[0] & EXT_BITS1_WEAKEXT_BIG);
+ } else {
+ intern->jmptbl = 0 != (ext->es_bits1[0] & EXT_BITS1_JMPTBL_LITTLE);
+ intern->cobol_main = 0 != (ext->es_bits1[0] & EXT_BITS1_COBOL_MAIN_LITTLE);
+ intern->weakext = 0 != (ext->es_bits1[0] & EXT_BITS1_WEAKEXT_LITTLE);
+ }
+ intern->reserved = 0;
+
+#ifdef ECOFF_32
+ intern->ifd = bfd_h_get_signed_16 (abfd, (bfd_byte *)ext->es_ifd);
+#endif
+#ifdef ECOFF_64
+ intern->ifd = bfd_h_get_signed_32 (abfd, (bfd_byte *)ext->es_ifd);
+#endif
+
+ ecoff_swap_sym_in (abfd, &ext->es_asym, &intern->asym);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out an external symbol record. */
+
+static void
+ecoff_swap_ext_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const EXTR *intern_copy;
+ PTR ext_ptr;
+{
+ struct ext_ext *ext = (struct ext_ext *) ext_ptr;
+ EXTR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ /* now the fun stuff... */
+ if (bfd_header_big_endian (abfd)) {
+ ext->es_bits1[0] = ((intern->jmptbl ? EXT_BITS1_JMPTBL_BIG : 0)
+ | (intern->cobol_main ? EXT_BITS1_COBOL_MAIN_BIG : 0)
+ | (intern->weakext ? EXT_BITS1_WEAKEXT_BIG : 0));
+ ext->es_bits2[0] = 0;
+#ifdef ECOFF_64
+ ext->es_bits2[1] = 0;
+ ext->es_bits2[2] = 0;
+#endif
+ } else {
+ ext->es_bits1[0] = ((intern->jmptbl ? EXT_BITS1_JMPTBL_LITTLE : 0)
+ | (intern->cobol_main ? EXT_BITS1_COBOL_MAIN_LITTLE : 0)
+ | (intern->weakext ? EXT_BITS1_WEAKEXT_LITTLE : 0));
+ ext->es_bits2[0] = 0;
+#ifdef ECOFF_64
+ ext->es_bits2[1] = 0;
+ ext->es_bits2[2] = 0;
+#endif
+ }
+
+#ifdef ECOFF_32
+ bfd_h_put_signed_16 (abfd, intern->ifd, (bfd_byte *)ext->es_ifd);
+#endif
+#ifdef ECOFF_64
+ bfd_h_put_signed_32 (abfd, intern->ifd, (bfd_byte *)ext->es_ifd);
+#endif
+
+ ecoff_swap_sym_out (abfd, &intern->asym, &ext->es_asym);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap in a relative file descriptor. */
+
+static void
+ecoff_swap_rfd_in (abfd, ext_ptr, intern)
+ bfd *abfd;
+ PTR ext_ptr;
+ RFDT *intern;
+{
+ struct rfd_ext *ext = (struct rfd_ext *) ext_ptr;
+
+ *intern = bfd_h_get_32 (abfd, (bfd_byte *)ext->rfd);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out a relative file descriptor. */
+
+static void
+ecoff_swap_rfd_out (abfd, intern, ext_ptr)
+ bfd *abfd;
+ const RFDT *intern;
+ PTR ext_ptr;
+{
+ struct rfd_ext *ext = (struct rfd_ext *) ext_ptr;
+
+ bfd_h_put_32 (abfd, *intern, (bfd_byte *)ext->rfd);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap in an optimization symbol. */
+
+static void
+ecoff_swap_opt_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ OPTR *intern;
+{
+ struct opt_ext ext[1];
+
+ *ext = *(struct opt_ext *) ext_copy;
+
+ if (bfd_header_big_endian (abfd))
+ {
+ intern->ot = ext->o_bits1[0];
+ intern->value = (((unsigned int) ext->o_bits2[0]
+ << OPT_BITS2_VALUE_SH_LEFT_BIG)
+ | ((unsigned int) ext->o_bits3[0]
+ << OPT_BITS2_VALUE_SH_LEFT_BIG)
+ | ((unsigned int) ext->o_bits4[0]
+ << OPT_BITS2_VALUE_SH_LEFT_BIG));
+ }
+ else
+ {
+ intern->ot = ext->o_bits1[0];
+ intern->value = ((ext->o_bits2[0] << OPT_BITS2_VALUE_SH_LEFT_LITTLE)
+ | (ext->o_bits3[0] << OPT_BITS2_VALUE_SH_LEFT_LITTLE)
+ | (ext->o_bits4[0] << OPT_BITS2_VALUE_SH_LEFT_LITTLE));
+ }
+
+ _bfd_ecoff_swap_rndx_in (bfd_header_big_endian (abfd),
+ &ext->o_rndx, &intern->rndx);
+
+ intern->offset = bfd_h_get_32 (abfd, (bfd_byte *) ext->o_offset);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out an optimization symbol. */
+
+static void
+ecoff_swap_opt_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const OPTR *intern_copy;
+ PTR ext_ptr;
+{
+ struct opt_ext *ext = (struct opt_ext *) ext_ptr;
+ OPTR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ if (bfd_header_big_endian (abfd))
+ {
+ ext->o_bits1[0] = intern->ot;
+ ext->o_bits2[0] = intern->value >> OPT_BITS2_VALUE_SH_LEFT_BIG;
+ ext->o_bits3[0] = intern->value >> OPT_BITS3_VALUE_SH_LEFT_BIG;
+ ext->o_bits4[0] = intern->value >> OPT_BITS4_VALUE_SH_LEFT_BIG;
+ }
+ else
+ {
+ ext->o_bits1[0] = intern->ot;
+ ext->o_bits2[0] = intern->value >> OPT_BITS2_VALUE_SH_LEFT_LITTLE;
+ ext->o_bits3[0] = intern->value >> OPT_BITS3_VALUE_SH_LEFT_LITTLE;
+ ext->o_bits4[0] = intern->value >> OPT_BITS4_VALUE_SH_LEFT_LITTLE;
+ }
+
+ _bfd_ecoff_swap_rndx_out (bfd_header_big_endian (abfd),
+ &intern->rndx, &ext->o_rndx);
+
+ bfd_h_put_32 (abfd, intern->value, (bfd_byte *) ext->o_offset);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap in a dense number. */
+
+static void
+ecoff_swap_dnr_in (abfd, ext_copy, intern)
+ bfd *abfd;
+ PTR ext_copy;
+ DNR *intern;
+{
+ struct dnr_ext ext[1];
+
+ *ext = *(struct dnr_ext *) ext_copy;
+
+ intern->rfd = bfd_h_get_32 (abfd, (bfd_byte *) ext->d_rfd);
+ intern->index = bfd_h_get_32 (abfd, (bfd_byte *) ext->d_index);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
+
+/* Swap out a dense number. */
+
+static void
+ecoff_swap_dnr_out (abfd, intern_copy, ext_ptr)
+ bfd *abfd;
+ const DNR *intern_copy;
+ PTR ext_ptr;
+{
+ struct dnr_ext *ext = (struct dnr_ext *) ext_ptr;
+ DNR intern[1];
+
+ *intern = *intern_copy; /* Make it reasonable to do in-place. */
+
+ bfd_h_put_32 (abfd, intern->rfd, (bfd_byte *) ext->d_rfd);
+ bfd_h_put_32 (abfd, intern->index, (bfd_byte *) ext->d_index);
+
+#ifdef TEST
+ if (memcmp ((char *)ext, (char *)intern, sizeof (*intern)) != 0)
+ abort();
+#endif
+}
diff --git a/contrib/gdb/bfd/elf-bfd.h b/contrib/gdb/bfd/elf-bfd.h
new file mode 100644
index 0000000..ee38e5b
--- /dev/null
+++ b/contrib/gdb/bfd/elf-bfd.h
@@ -0,0 +1,858 @@
+/* BFD back-end data structures for ELF files.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _LIBELF_H_
+#define _LIBELF_H_ 1
+
+#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
+#if ARCH_SIZE==64
+#define NAME(x,y) CAT4(x,64,_,y)
+#endif
+#if ARCH_SIZE==32
+#define NAME(x,y) CAT4(x,32,_,y)
+#endif
+#endif
+
+#ifndef NAME
+#define NAME(x,y) CAT4(x,NOSIZE,_,y)
+#endif
+
+#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 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;
+
+ /* If this symbol requires an entry in the global offset table, the
+ processor specific backend uses this field to hold the offset
+ into the .got section. If this field is -1, then the symbol does
+ not require a global offset table entry. */
+ bfd_vma got_offset;
+
+ /* If this symbol requires an entry in the procedure linkage table,
+ the processor specific backend uses these two fields to hold the
+ offset into the procedure linkage section and the offset into the
+ .got section. If plt_offset is -1, then the symbol does not
+ require an entry in the procedure linkage table. */
+ bfd_vma plt_offset;
+
+ /* If this symbol is used in the linker created sections, the processor
+ specific backend uses this field to map the field into the offset
+ from the beginning of the section. */
+ struct elf_linker_section_pointers *linker_section_pointer;
+
+ /* 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
+ /* Dynamic symbol has been adjustd. */
+#define ELF_LINK_HASH_DYNAMIC_ADJUSTED 020
+ /* Symbol needs a copy reloc. */
+#define ELF_LINK_HASH_NEEDS_COPY 040
+ /* Symbol needs a procedure linkage table entry. */
+#define ELF_LINK_HASH_NEEDS_PLT 0100
+ /* Symbol appears in a non-ELF input file. */
+#define ELF_LINK_NON_ELF 0200
+ /* Note: If you add more flags, you must change the type of
+ elf_link_hash_flags. */
+};
+
+/* ELF linker hash table. */
+
+struct elf_link_hash_table
+{
+ struct bfd_link_hash_table root;
+ /* Whether we have created the special dynamic sections required
+ when linking against or generating a shared object. */
+ boolean dynamic_sections_created;
+ /* The BFD used to hold special sections created by the linker.
+ This will be the first BFD found which requires these sections to
+ be created. */
+ bfd *dynobj;
+ /* The number of symbols found in the link which must be put into
+ the .dynsym section. */
+ bfd_size_type dynsymcount;
+ /* The string table of dynamic symbols, which becomes the .dynstr
+ section. */
+ struct bfd_strtab_hash *dynstr;
+ /* The number of buckets in the hash table in the .hash section.
+ This is based on the number of dynamic symbols. */
+ bfd_size_type bucketcount;
+ /* A linked list of DT_NEEDED names found in dynamic objects
+ included in the link. */
+ struct bfd_link_needed_list *needed;
+};
+
+/* 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_size_info {
+ unsigned char sizeof_ehdr, sizeof_phdr, sizeof_shdr;
+ unsigned char sizeof_rel, sizeof_rela, sizeof_sym, sizeof_dyn, sizeof_note;
+
+ unsigned char arch_size, file_align;
+ unsigned char elfclass, ev_current;
+ int (*write_out_phdrs) PARAMS ((bfd *, Elf_Internal_Phdr *, int));
+ boolean (*write_shdrs_and_ehdr) PARAMS ((bfd *));
+ void (*write_relocs) PARAMS ((bfd *, asection *, PTR));
+ void (*swap_symbol_out) PARAMS ((bfd *, Elf_Internal_Sym *, PTR));
+ boolean (*slurp_reloc_table) PARAMS ((bfd *, asection *, asymbol **));
+ long (*slurp_symbol_table) PARAMS ((bfd *, asymbol **, boolean));
+ void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+};
+
+#define elf_symbol_from(ABFD,S) \
+ (((S)->the_bfd->xvec->flavour == bfd_target_elf_flavour \
+ && (S)->the_bfd->tdata.elf_obj_data != 0) \
+ ? (elf_symbol_type *) (S) \
+ : 0)
+
+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;
+
+ /* 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;
+
+ /* This is true if the linker should ignore changes to the type of a
+ symbol. This is true for MIPS ELF because some Irix 5 objects
+ record undefined functions as STT_OBJECT although the definitions
+ are STT_FUNC. */
+ boolean type_change_ok;
+
+ /* 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 *));
+
+ /* 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 *));
+
+ /* 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 *,
+ unsigned 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 CHECK_RELOCS function is called by the add_symbols phase of
+ the ELF backend linker. It is called once for each section with
+ relocs of an object file, just after the symbols for the object
+ file have been added to the global linker hash table. The
+ function must look through the relocs and do any special handling
+ required. This generally means allocating space in the global
+ offset table, and perhaps allocating space for a reloc. The
+ relocs are always passed as Rela structures; if the section
+ actually uses Rel structures, the r_addend field will always be
+ zero. */
+ boolean (*check_relocs)
+ PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *o,
+ const Elf_Internal_Rela *relocs));
+
+ /* 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 ore bfd_link_hash_defweak, 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));
+
+ /* 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. The LINKER argument is true if this BFD
+ was created by the ELF backend linker. */
+ void (*elf_backend_final_write_processing)
+ PARAMS ((bfd *, boolean linker));
+
+ /* This function is called by get_program_header_size. It should
+ return the number of additional program segments which this BFD
+ will need. It should return -1 on error. */
+ int (*elf_backend_additional_program_headers) PARAMS ((bfd *));
+
+ /* This function is called to modify an existing segment map in a
+ backend specific fashion. */
+ boolean (*elf_backend_modify_segment_map) PARAMS ((bfd *));
+
+ /* 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;
+
+ /* Alternate EM_xxxx machine codes for this backend. */
+ int elf_machine_alt1;
+ int elf_machine_alt2;
+
+ const struct elf_size_info *s;
+
+ unsigned want_got_plt : 1;
+ unsigned plt_readonly : 1;
+ unsigned want_plt_sym : 1;
+};
+
+/* 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;
+ /* 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 swapped relocs. If the section uses REL relocs,
+ rather than RELA, all the r_addend fields will be zero. This
+ pointer may be NULL. It is used by the backend linker. */
+ Elf_Internal_Rela *relocs;
+ /* Used by the backend linker when generating a shared library to
+ record the dynamic symbol index for a section symbol
+ corresponding to this section. */
+ long dynindx;
+ /* A pointer available for the processor specific ELF backend. */
+ PTR tdata;
+};
+
+#define elf_section_data(sec) ((struct bfd_elf_section_data*)sec->used_by_bfd)
+
+#define get_elf_backend_data(abfd) \
+ ((struct elf_backend_data *) (abfd)->xvec->backend_data)
+
+/* Enumeration to specify the special section. */
+typedef enum elf_linker_section_enum
+{
+ LINKER_SECTION_UNKNOWN, /* not used */
+ LINKER_SECTION_GOT, /* .got section for global offset pointers */
+ LINKER_SECTION_PLT, /* .plt section for generated procedure stubs */
+ LINKER_SECTION_SDATA, /* .sdata/.sbss section for PowerPC */
+ LINKER_SECTION_SDATA2, /* .sdata2/.sbss2 section for PowerPC */
+ LINKER_SECTION_MAX /* # of linker sections */
+} elf_linker_section_enum_t;
+
+/* Sections created by the linker. */
+
+typedef struct elf_linker_section
+{
+ char *name; /* name of the section */
+ char *rel_name; /* name of the associated .rel{,a}. section */
+ char *bss_name; /* name of a related .bss section */
+ char *sym_name; /* name of symbol to reference this section */
+ asection *section; /* pointer to the section */
+ asection *bss_section; /* pointer to the bss section associated with this */
+ asection *rel_section; /* pointer to the relocations needed for this section */
+ struct elf_link_hash_entry *sym_hash; /* pointer to the created symbol hash value */
+ bfd_vma initial_size; /* initial size before any linker generated allocations */
+ bfd_vma sym_offset; /* offset of symbol from beginning of section */
+ bfd_vma hole_size; /* size of reserved address hole in allocation */
+ bfd_vma hole_offset; /* current offset for the hole */
+ bfd_vma max_hole_offset; /* maximum offset for the hole */
+ elf_linker_section_enum_t which; /* which section this is */
+ boolean hole_written_p; /* whether the hole has been initialized */
+ int alignment; /* alignment for the section */
+ flagword flags; /* flags to use to create the section */
+} elf_linker_section_t;
+
+/* Linked list of allocated pointer entries. This hangs off of the symbol lists, and
+ provides allows us to return different pointers, based on different addend's. */
+
+typedef struct elf_linker_section_pointers
+{
+ struct elf_linker_section_pointers *next; /* next allocated pointer for this symbol */
+ bfd_vma offset; /* offset of pointer from beginning of section */
+ bfd_signed_vma addend; /* addend used */
+ elf_linker_section_enum_t which; /* which linker section this is */
+ boolean written_address_p; /* whether address was written yet */
+} elf_linker_section_pointers_t;
+
+/* Some private data is stashed away for future use using the tdata pointer
+ in the bfd structure. */
+
+struct elf_obj_tdata
+{
+ Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */
+ Elf_Internal_Shdr **elf_sect_ptr;
+ Elf_Internal_Phdr *phdr;
+ struct elf_segment_map *segment_map;
+ struct bfd_strtab_hash *strtab_ptr;
+ int num_locals;
+ int num_globals;
+ asymbol **section_syms; /* STT_SECTION symbols for each section */
+ Elf_Internal_Shdr symtab_hdr;
+ Elf_Internal_Shdr shstrtab_hdr;
+ Elf_Internal_Shdr strtab_hdr;
+ Elf_Internal_Shdr dynsymtab_hdr;
+ Elf_Internal_Shdr dynstrtab_hdr;
+ unsigned int symtab_section, shstrtab_section;
+ unsigned int 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) */
+ unsigned int gp_size; /* The gp size (MIPS only, for now) */
+
+ /* This is set to true if the object was created by the backend
+ linker. */
+ boolean linker;
+
+ /* 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;
+
+ /* A mapping from local symbols to offsets into the global offset
+ table, used when linking. This is indexed by the symbol index. */
+ bfd_vma *local_got_offsets;
+
+ /* A mapping from local symbols to offsets into the various linker
+ sections added. This is index by the symbol index. */
+ elf_linker_section_pointers_t **linker_section_pointers;
+
+ /* 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. The emulation code then
+ sometimes needs to know what name was actually used. Until the
+ file has been added to the linker symbol table, this field holds
+ the name the linker wants. After it has been added, it holds the
+ name actually used, which will be the DT_SONAME entry if there is
+ one. */
+ const char *dt_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;
+
+ /* Records the result of `get_program_header_size'. */
+ bfd_size_type program_header_size;
+
+ /* Used by find_nearest_line entry point. */
+ PTR line_info;
+
+ /* Used by MIPS ELF find_nearest_line entry point. The structure
+ could be included directly in this one, but there's no point to
+ wasting the memory just for the infrequently called
+ find_nearest_line. */
+ struct mips_elf_find_line *find_line_info;
+
+ /* Used to determine if the e_flags field has been initialized */
+ boolean flags_init;
+
+ /* Linker sections that we are interested in. */
+ struct elf_linker_section *linker_section[ (int)LINKER_SECTION_MAX ];
+};
+
+#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data)
+#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header)
+#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_section_syms(bfd) (elf_tdata(bfd) -> section_syms)
+#define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo)
+#define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus)
+#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_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got_offsets)
+#define elf_local_ptr_offsets(bfd) (elf_tdata(bfd) -> linker_section_pointers)
+#define elf_dt_name(bfd) (elf_tdata(bfd) -> dt_name)
+#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab)
+#define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init)
+#define elf_linker_section(bfd,n) (elf_tdata(bfd) -> linker_section[(int)n])
+
+extern int _bfd_elf_section_from_bfd_section PARAMS ((bfd *, asection *));
+extern char *bfd_elf_string_from_elf_section
+ PARAMS ((bfd *, unsigned, unsigned));
+extern char *bfd_elf_get_str_section PARAMS ((bfd *, unsigned));
+
+extern boolean _bfd_elf_print_private_bfd_data PARAMS ((bfd *, PTR));
+extern void bfd_elf_print_symbol PARAMS ((bfd *, PTR, asymbol *,
+ bfd_print_symbol_type));
+#define elf_string_from_elf_strtab(abfd,strindex) \
+ bfd_elf_string_from_elf_section(abfd,elf_elfheader(abfd)->e_shstrndx,strindex)
+
+#define bfd_elf32_print_symbol bfd_elf_print_symbol
+#define bfd_elf64_print_symbol bfd_elf_print_symbol
+#define bfd_elf32_mkobject bfd_elf_mkobject
+#define bfd_elf64_mkobject bfd_elf_mkobject
+#define elf_mkobject bfd_elf_mkobject
+
+extern unsigned long bfd_elf_hash PARAMS ((CONST unsigned char *));
+
+extern bfd_reloc_status_type bfd_elf_generic_reloc PARAMS ((bfd *,
+ arelent *,
+ asymbol *,
+ PTR,
+ asection *,
+ 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_elf_copy_private_symbol_data
+ PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
+extern boolean _bfd_elf_copy_private_section_data
+ PARAMS ((bfd *, asection *, bfd *, asection *));
+extern boolean _bfd_elf_write_object_contents PARAMS ((bfd *));
+extern boolean _bfd_elf_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr,
+ bfd_size_type));
+extern long _bfd_elf_get_symtab_upper_bound PARAMS ((bfd *));
+extern long _bfd_elf_get_symtab PARAMS ((bfd *, asymbol **));
+extern long _bfd_elf_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
+extern long _bfd_elf_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));
+extern long _bfd_elf_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
+extern long _bfd_elf_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
+ arelent **, asymbol **));
+extern asymbol *_bfd_elf_make_empty_symbol PARAMS ((bfd *));
+extern void _bfd_elf_get_symbol_info PARAMS ((bfd *, asymbol *,
+ symbol_info *));
+extern alent *_bfd_elf_get_lineno PARAMS ((bfd *, asymbol *));
+extern boolean _bfd_elf_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+extern boolean _bfd_elf_find_nearest_line PARAMS ((bfd *, asection *,
+ asymbol **,
+ bfd_vma, CONST char **,
+ CONST char **,
+ unsigned int *));
+#define _bfd_elf_read_minisymbols _bfd_generic_read_minisymbols
+#define _bfd_elf_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+extern int _bfd_elf_sizeof_headers PARAMS ((bfd *, boolean));
+extern boolean _bfd_elf_new_section_hook PARAMS ((bfd *, asection *));
+
+/* If the target doesn't have reloc handling written yet: */
+extern void _bfd_elf_no_info_to_howto PARAMS ((bfd *, arelent *,
+ Elf_Internal_Rela *));
+
+asection *bfd_section_from_elf_index PARAMS ((bfd *, unsigned int));
+boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *,
+ struct bfd_link_info *));
+struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
+boolean
+_bfd_elf_link_record_dynamic_symbol PARAMS ((struct bfd_link_info *,
+ struct elf_link_hash_entry *));
+boolean
+_bfd_elf_compute_section_file_positions PARAMS ((bfd *,
+ struct bfd_link_info *));
+void _bfd_elf_assign_file_positions_for_relocs PARAMS ((bfd *));
+file_ptr _bfd_elf_assign_file_position_for_section PARAMS ((Elf_Internal_Shdr *,
+ file_ptr,
+ boolean));
+
+boolean _bfd_elf_create_dynamic_sections PARAMS ((bfd *,
+ struct bfd_link_info *));
+boolean _bfd_elf_create_got_section PARAMS ((bfd *,
+ struct bfd_link_info *));
+
+elf_linker_section_t *_bfd_elf_create_linker_section
+ PARAMS ((bfd *abfd,
+ struct bfd_link_info *info,
+ enum elf_linker_section_enum,
+ elf_linker_section_t *defaults));
+
+elf_linker_section_pointers_t *_bfd_elf_find_pointer_linker_section
+ PARAMS ((elf_linker_section_pointers_t *linker_pointers,
+ bfd_signed_vma addend,
+ elf_linker_section_enum_t which));
+
+boolean bfd_elf32_create_pointer_linker_section
+ PARAMS ((bfd *abfd,
+ struct bfd_link_info *info,
+ elf_linker_section_t *lsect,
+ struct elf_link_hash_entry *h,
+ const Elf32_Internal_Rela *rel));
+
+bfd_vma bfd_elf32_finish_pointer_linker_section
+ PARAMS ((bfd *output_abfd,
+ bfd *input_bfd,
+ struct bfd_link_info *info,
+ elf_linker_section_t *lsect,
+ struct elf_link_hash_entry *h,
+ bfd_vma relocation,
+ const Elf32_Internal_Rela *rel,
+ int relative_reloc));
+
+boolean bfd_elf64_create_pointer_linker_section
+ PARAMS ((bfd *abfd,
+ struct bfd_link_info *info,
+ elf_linker_section_t *lsect,
+ struct elf_link_hash_entry *h,
+ const Elf64_Internal_Rela *rel));
+
+bfd_vma bfd_elf64_finish_pointer_linker_section
+ PARAMS ((bfd *output_abfd,
+ bfd *input_bfd,
+ struct bfd_link_info *info,
+ elf_linker_section_t *lsect,
+ struct elf_link_hash_entry *h,
+ bfd_vma relocation,
+ const Elf64_Internal_Rela *rel,
+ int relative_reloc));
+
+boolean _bfd_elf_make_linker_section_rela
+ PARAMS ((bfd *dynobj,
+ elf_linker_section_t *lsect,
+ int alignment));
+
+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 *,
+ bfd *));
+
+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 *, PTR));
+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_phdr_in
+ PARAMS ((bfd *, Elf32_External_Phdr *, Elf_Internal_Phdr *));
+extern void bfd_elf32_swap_phdr_out
+ PARAMS ((bfd *, Elf_Internal_Phdr *, Elf32_External_Phdr *));
+extern void bfd_elf32_swap_dyn_in
+ PARAMS ((bfd *, const PTR, 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));
+extern boolean bfd_elf32_link_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+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 *,
+ bfd *));
+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 *, PTR));
+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_phdr_in
+ PARAMS ((bfd *, Elf64_External_Phdr *, Elf_Internal_Phdr *));
+extern void bfd_elf64_swap_phdr_out
+ PARAMS ((bfd *, Elf_Internal_Phdr *, Elf64_External_Phdr *));
+extern void bfd_elf64_swap_dyn_in
+ PARAMS ((bfd *, const PTR, 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));
+extern boolean bfd_elf64_link_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+#define bfd_elf32_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
+#define bfd_elf64_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
+
+#endif /* _LIBELF_H_ */
diff --git a/contrib/gdb/bfd/elf.c b/contrib/gdb/bfd/elf.c
new file mode 100644
index 0000000..981d3ee
--- /dev/null
+++ b/contrib/gdb/bfd/elf.c
@@ -0,0 +1,3318 @@
+/* ELF executable support for BFD.
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+
+SECTION
+ ELF backends
+
+ BFD support for ELF formats is being worked on.
+ Currently, the best supported back ends are for sparc and i386
+ (running svr4 or Solaris 2).
+
+ Documentation of the internals of the support code still needs
+ to be written. The code is changing quickly enough that we
+ haven't bothered yet.
+ */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#define ARCH_SIZE 0
+#include "elf-bfd.h"
+
+static INLINE struct elf_segment_map *make_mapping
+ PARAMS ((bfd *, asection **, unsigned int, unsigned int, boolean));
+static int elf_sort_sections PARAMS ((const PTR, const PTR));
+static boolean assign_file_positions_for_segments PARAMS ((bfd *));
+static boolean assign_file_positions_except_relocs PARAMS ((bfd *));
+static boolean prep_headers PARAMS ((bfd *));
+static boolean swap_out_syms PARAMS ((bfd *, struct bfd_strtab_hash **));
+static boolean copy_private_bfd_data PARAMS ((bfd *, bfd *));
+
+/* Standard ELF hash function. Do not change this function; you will
+ cause invalid hash tables to be generated. (Well, you would if this
+ were being used yet.) */
+unsigned long
+bfd_elf_hash (name)
+ CONST unsigned char *name;
+{
+ unsigned long h = 0;
+ unsigned long g;
+ int ch;
+
+ while ((ch = *name++) != '\0')
+ {
+ h = (h << 4) + ch;
+ if ((g = (h & 0xf0000000)) != 0)
+ {
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ }
+ return h;
+}
+
+/* Read a specified number of bytes at a specified offset in an ELF
+ file, into a newly allocated buffer, and return a pointer to the
+ buffer. */
+
+static char *
+elf_read (abfd, offset, size)
+ bfd * abfd;
+ long offset;
+ unsigned int size;
+{
+ char *buf;
+
+ if ((buf = bfd_alloc (abfd, size)) == NULL)
+ return NULL;
+ if (bfd_seek (abfd, offset, SEEK_SET) == -1)
+ return NULL;
+ if (bfd_read ((PTR) buf, size, 1, abfd) != size)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_file_truncated);
+ return NULL;
+ }
+ return buf;
+}
+
+boolean
+elf_mkobject (abfd)
+ bfd * abfd;
+{
+ /* this just does initialization */
+ /* coff_mkobject zalloc's space for tdata.coff_obj_data ... */
+ elf_tdata (abfd) = (struct elf_obj_tdata *)
+ bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
+ if (elf_tdata (abfd) == 0)
+ return false;
+ /* since everything is done at close time, do we need any
+ initialization? */
+
+ return true;
+}
+
+char *
+bfd_elf_get_str_section (abfd, shindex)
+ bfd * abfd;
+ unsigned int shindex;
+{
+ Elf_Internal_Shdr **i_shdrp;
+ char *shstrtab = NULL;
+ unsigned int offset;
+ unsigned int shstrtabsize;
+
+ i_shdrp = elf_elfsections (abfd);
+ if (i_shdrp == 0 || i_shdrp[shindex] == 0)
+ return 0;
+
+ shstrtab = (char *) i_shdrp[shindex]->contents;
+ if (shstrtab == NULL)
+ {
+ /* No cached one, attempt to read, and cache what we read. */
+ offset = i_shdrp[shindex]->sh_offset;
+ shstrtabsize = i_shdrp[shindex]->sh_size;
+ shstrtab = elf_read (abfd, offset, shstrtabsize);
+ i_shdrp[shindex]->contents = (PTR) shstrtab;
+ }
+ return shstrtab;
+}
+
+char *
+bfd_elf_string_from_elf_section (abfd, shindex, strindex)
+ bfd * abfd;
+ unsigned int shindex;
+ unsigned int strindex;
+{
+ Elf_Internal_Shdr *hdr;
+
+ if (strindex == 0)
+ return "";
+
+ hdr = elf_elfsections (abfd)[shindex];
+
+ if (hdr->contents == NULL
+ && bfd_elf_get_str_section (abfd, shindex) == NULL)
+ return NULL;
+
+ return ((char *) hdr->contents) + strindex;
+}
+
+/* Make a BFD section from an ELF section. We store a pointer to the
+ BFD section in the bfd_section 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->bfd_section != NULL)
+ {
+ BFD_ASSERT (strcmp (name,
+ bfd_get_section_name (abfd, hdr->bfd_section)) == 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;
+
+ if ((flags & SEC_ALLOC) != 0)
+ {
+ Elf_Internal_Phdr *phdr;
+ unsigned int i;
+
+ /* Look through the phdrs to see if we need to adjust the lma. */
+ phdr = elf_tdata (abfd)->phdr;
+ for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++)
+ {
+ if (phdr->p_type == PT_LOAD
+ && phdr->p_paddr != 0
+ && phdr->p_vaddr != phdr->p_paddr
+ && phdr->p_vaddr <= hdr->sh_addr
+ && phdr->p_vaddr + phdr->p_memsz >= hdr->sh_addr + hdr->sh_size)
+ {
+ newsect->lma += phdr->p_paddr - phdr->p_vaddr;
+ break;
+ }
+ }
+ }
+
+ hdr->bfd_section = newsect;
+ elf_section_data (newsect)->this_hdr = *hdr;
+
+ return true;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_elf_find_section
+
+SYNOPSIS
+ struct elf_internal_shdr *bfd_elf_find_section (bfd *abfd, char *name);
+
+DESCRIPTION
+ Helper functions for GDB to locate the string tables.
+ Since BFD hides string tables from callers, GDB needs to use an
+ internal hook to find them. Sun's .stabstr, in particular,
+ isn't even pointed to by the .stab section, so ordinary
+ mechanisms wouldn't work to find it, even if we had some.
+*/
+
+struct elf_internal_shdr *
+bfd_elf_find_section (abfd, name)
+ bfd * abfd;
+ char *name;
+{
+ Elf_Internal_Shdr **i_shdrp;
+ char *shstrtab;
+ unsigned int max;
+ unsigned int i;
+
+ i_shdrp = elf_elfsections (abfd);
+ if (i_shdrp != NULL)
+ {
+ shstrtab = bfd_elf_get_str_section (abfd, elf_elfheader (abfd)->e_shstrndx);
+ if (shstrtab != NULL)
+ {
+ max = elf_elfheader (abfd)->e_shnum;
+ for (i = 1; i < max; i++)
+ if (!strcmp (&shstrtab[i_shdrp[i]->sh_name], name))
+ return i_shdrp[i];
+ }
+ }
+ return 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",
+ "SHT_NOBITS", "SHT_REL", "SHT_SHLIB", "SHT_DYNSYM",
+};
+
+/* ELF relocs are against symbols. If we are producing relocateable
+ output, and the reloc is against an external symbol, and nothing
+ has given us any additional addend, the resulting reloc will also
+ be against the same symbol. In such a case, we don't want to
+ change anything about the way the reloc is handled, since it will
+ all be done at final link time. Rather than put special case code
+ into bfd_perform_relocation, all the reloc types use this howto
+ 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,
+ 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->howto->partial_inplace
+ || reloc_entry->addend == 0))
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ return bfd_reloc_continue;
+}
+
+/* Print out the program headers. */
+
+boolean
+_bfd_elf_print_private_bfd_data (abfd, farg)
+ bfd *abfd;
+ PTR farg;
+{
+ FILE *f = (FILE *) farg;
+ Elf_Internal_Phdr *p;
+ asection *s;
+ bfd_byte *dynbuf = NULL;
+
+ p = elf_tdata (abfd)->phdr;
+ if (p != NULL)
+ {
+ unsigned int i, c;
+
+ fprintf (f, "\nProgram Header:\n");
+ c = elf_elfheader (abfd)->e_phnum;
+ for (i = 0; i < c; i++, p++)
+ {
+ const char *s;
+ char buf[20];
+
+ switch (p->p_type)
+ {
+ case PT_NULL: s = "NULL"; break;
+ case PT_LOAD: s = "LOAD"; break;
+ case PT_DYNAMIC: s = "DYNAMIC"; break;
+ case PT_INTERP: s = "INTERP"; break;
+ case PT_NOTE: s = "NOTE"; break;
+ case PT_SHLIB: s = "SHLIB"; break;
+ case PT_PHDR: s = "PHDR"; break;
+ default: sprintf (buf, "0x%lx", p->p_type); s = buf; break;
+ }
+ fprintf (f, "%8s off 0x", s);
+ fprintf_vma (f, p->p_offset);
+ fprintf (f, " vaddr 0x");
+ fprintf_vma (f, p->p_vaddr);
+ fprintf (f, " paddr 0x");
+ fprintf_vma (f, p->p_paddr);
+ fprintf (f, " align 2**%u\n", bfd_log2 (p->p_align));
+ fprintf (f, " filesz 0x");
+ fprintf_vma (f, p->p_filesz);
+ fprintf (f, " memsz 0x");
+ fprintf_vma (f, p->p_memsz);
+ fprintf (f, " flags %c%c%c",
+ (p->p_flags & PF_R) != 0 ? 'r' : '-',
+ (p->p_flags & PF_W) != 0 ? 'w' : '-',
+ (p->p_flags & PF_X) != 0 ? 'x' : '-');
+ if ((p->p_flags &~ (PF_R | PF_W | PF_X)) != 0)
+ fprintf (f, " %lx", p->p_flags &~ (PF_R | PF_W | PF_X));
+ fprintf (f, "\n");
+ }
+ }
+
+ s = bfd_get_section_by_name (abfd, ".dynamic");
+ if (s != NULL)
+ {
+ int elfsec;
+ unsigned long link;
+ bfd_byte *extdyn, *extdynend;
+ size_t extdynsize;
+ void (*swap_dyn_in) PARAMS ((bfd *, const PTR, Elf_Internal_Dyn *));
+
+ fprintf (f, "\nDynamic Section:\n");
+
+ dynbuf = (bfd_byte *) bfd_malloc (s->_raw_size);
+ if (dynbuf == NULL)
+ goto error_return;
+ if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf, (file_ptr) 0,
+ s->_raw_size))
+ goto error_return;
+
+ elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
+ if (elfsec == -1)
+ goto error_return;
+ link = elf_elfsections (abfd)[elfsec]->sh_link;
+
+ extdynsize = get_elf_backend_data (abfd)->s->sizeof_dyn;
+ swap_dyn_in = get_elf_backend_data (abfd)->s->swap_dyn_in;
+
+ extdyn = dynbuf;
+ extdynend = extdyn + s->_raw_size;
+ for (; extdyn < extdynend; extdyn += extdynsize)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ char ab[20];
+ boolean stringp;
+
+ (*swap_dyn_in) (abfd, (PTR) extdyn, &dyn);
+
+ if (dyn.d_tag == DT_NULL)
+ break;
+
+ stringp = false;
+ switch (dyn.d_tag)
+ {
+ default:
+ sprintf (ab, "0x%lx", (unsigned long) dyn.d_tag);
+ name = ab;
+ break;
+
+ case DT_NEEDED: name = "NEEDED"; stringp = true; break;
+ case DT_PLTRELSZ: name = "PLTRELSZ"; break;
+ case DT_PLTGOT: name = "PLTGOT"; break;
+ case DT_HASH: name = "HASH"; break;
+ case DT_STRTAB: name = "STRTAB"; break;
+ case DT_SYMTAB: name = "SYMTAB"; break;
+ case DT_RELA: name = "RELA"; break;
+ case DT_RELASZ: name = "RELASZ"; break;
+ case DT_RELAENT: name = "RELAENT"; break;
+ case DT_STRSZ: name = "STRSZ"; break;
+ case DT_SYMENT: name = "SYMENT"; break;
+ case DT_INIT: name = "INIT"; break;
+ case DT_FINI: name = "FINI"; break;
+ case DT_SONAME: name = "SONAME"; stringp = true; break;
+ case DT_RPATH: name = "RPATH"; stringp = true; break;
+ case DT_SYMBOLIC: name = "SYMBOLIC"; break;
+ case DT_REL: name = "REL"; break;
+ case DT_RELSZ: name = "RELSZ"; break;
+ case DT_RELENT: name = "RELENT"; break;
+ case DT_PLTREL: name = "PLTREL"; break;
+ case DT_DEBUG: name = "DEBUG"; break;
+ case DT_TEXTREL: name = "TEXTREL"; break;
+ case DT_JMPREL: name = "JMPREL"; break;
+ }
+
+ fprintf (f, " %-11s ", name);
+ if (! stringp)
+ fprintf (f, "0x%lx", (unsigned long) dyn.d_un.d_val);
+ else
+ {
+ const char *string;
+
+ string = bfd_elf_string_from_elf_section (abfd, link,
+ dyn.d_un.d_val);
+ if (string == NULL)
+ goto error_return;
+ fprintf (f, "%s", string);
+ }
+ fprintf (f, "\n");
+ }
+
+ free (dynbuf);
+ dynbuf = NULL;
+ }
+
+ return true;
+
+ error_return:
+ if (dynbuf != NULL)
+ free (dynbuf);
+ return false;
+}
+
+/* Display ELF-specific fields of a symbol. */
+void
+bfd_elf_print_symbol (ignore_abfd, filep, symbol, how)
+ bfd *ignore_abfd;
+ PTR filep;
+ asymbol *symbol;
+ bfd_print_symbol_type how;
+{
+ FILE *file = (FILE *) filep;
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ fprintf (file, "%s", symbol->name);
+ break;
+ case bfd_print_symbol_more:
+ fprintf (file, "elf ");
+ fprintf_vma (file, symbol->value);
+ fprintf (file, " %lx", (long) symbol->flags);
+ break;
+ case bfd_print_symbol_all:
+ {
+ CONST char *section_name;
+ section_name = symbol->section ? symbol->section->name : "(*none*)";
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+ fprintf (file, " %s\t", section_name);
+ /* Print the "other" value for a symbol. For common symbols,
+ we've already printed the size; now print the alignment.
+ For other symbols, we have no specified alignment, and
+ we've printed the address; now print the size. */
+ fprintf_vma (file,
+ (bfd_is_com_section (symbol->section)
+ ? ((elf_symbol_type *) symbol)->internal_elf_sym.st_value
+ : ((elf_symbol_type *) symbol)->internal_elf_sym.st_size));
+ fprintf (file, " %s", symbol->name);
+ }
+ break;
+ }
+}
+
+/* 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)
+ 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->dynindx = -1;
+ ret->dynstr_index = 0;
+ ret->weakdef = NULL;
+ ret->got_offset = (bfd_vma) -1;
+ ret->plt_offset = (bfd_vma) -1;
+ ret->linker_section_pointer = (elf_linker_section_pointers_t *)0;
+ ret->type = STT_NOTYPE;
+ /* Assume that we have been called by a non-ELF symbol reader.
+ This flag is then reset by the code which reads an ELF input
+ file. This ensures that a symbol created by a non-ELF symbol
+ reader will have the flag set correctly. */
+ ret->elf_link_hash_flags = ELF_LINK_NON_ELF;
+ }
+
+ 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->dynamic_sections_created = false;
+ table->dynobj = NULL;
+ /* The first dynamic symbol is a dummy. */
+ table->dynsymcount = 1;
+ table->dynstr = NULL;
+ table->bucketcount = 0;
+ table->needed = NULL;
+ 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)
+ 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. The generic linker passes name as an
+ empty string to indicate that no DT_NEEDED entry should be made. */
+
+void
+bfd_elf_set_dt_needed_name (abfd, name)
+ bfd *abfd;
+ const char *name;
+{
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && bfd_get_format (abfd) == bfd_object)
+ elf_dt_name (abfd) = name;
+}
+
+/* Get the list of DT_NEEDED entries for a link. This is a hook for
+ the ELF emulation code. */
+
+struct bfd_link_needed_list *
+bfd_elf_get_needed_list (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ if (info->hash->creator->flavour != bfd_target_elf_flavour)
+ return NULL;
+ return elf_hash_table (info)->needed;
+}
+
+/* Get the name actually used for a dynamic object for a link. This
+ is the SONAME entry if there is one. Otherwise, it is the string
+ passed to bfd_elf_set_dt_needed_name, or it is the filename. */
+
+const char *
+bfd_elf_get_dt_soname (abfd)
+ bfd *abfd;
+{
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && bfd_get_format (abfd) == bfd_object)
+ return elf_dt_name (abfd);
+ return NULL;
+}
+
+/* Allocate an ELF string table--force the first byte to be zero. */
+
+struct bfd_strtab_hash *
+_bfd_elf_stringtab_init ()
+{
+ struct bfd_strtab_hash *ret;
+
+ ret = _bfd_stringtab_init ();
+ if (ret != NULL)
+ {
+ bfd_size_type loc;
+
+ loc = _bfd_stringtab_add (ret, "", true, false);
+ BFD_ASSERT (loc == 0 || loc == (bfd_size_type) -1);
+ if (loc == (bfd_size_type) -1)
+ {
+ _bfd_stringtab_free (ret);
+ ret = NULL;
+ }
+ }
+ return ret;
+}
+
+/* ELF .o/exec file reading */
+
+/* Create a new bfd section from an ELF section header. */
+
+boolean
+bfd_section_from_shdr (abfd, shindex)
+ bfd *abfd;
+ unsigned int shindex;
+{
+ Elf_Internal_Shdr *hdr = elf_elfsections (abfd)[shindex];
+ Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ char *name;
+
+ name = elf_string_from_elf_strtab (abfd, hdr->sh_name);
+
+ switch (hdr->sh_type)
+ {
+ case SHT_NULL:
+ /* Inactive section. Throw it away. */
+ return true;
+
+ case SHT_PROGBITS: /* Normal section with contents. */
+ case SHT_DYNAMIC: /* Dynamic linking information. */
+ case SHT_NOBITS: /* .bss section. */
+ case SHT_HASH: /* .hash section. */
+ case SHT_NOTE: /* .note section. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+
+ case SHT_SYMTAB: /* A symbol table */
+ if (elf_onesymtab (abfd) == shindex)
+ return true;
+
+ BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
+ BFD_ASSERT (elf_onesymtab (abfd) == 0);
+ elf_onesymtab (abfd) = shindex;
+ elf_tdata (abfd)->symtab_hdr = *hdr;
+ elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->symtab_hdr;
+ abfd->flags |= HAS_SYMS;
+
+ /* Sometimes a shared object will map in the symbol table. If
+ SHF_ALLOC is set, and this is a shared object, then we also
+ treat this section as a BFD section. We can not base the
+ decision purely on SHF_ALLOC, because that flag is sometimes
+ set in a relocateable object file, which would confuse the
+ linker. */
+ if ((hdr->sh_flags & SHF_ALLOC) != 0
+ && (abfd->flags & DYNAMIC) != 0
+ && ! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ return false;
+
+ return true;
+
+ case SHT_DYNSYM: /* A dynamic symbol table */
+ if (elf_dynsymtab (abfd) == shindex)
+ return true;
+
+ BFD_ASSERT (hdr->sh_entsize == bed->s->sizeof_sym);
+ BFD_ASSERT (elf_dynsymtab (abfd) == 0);
+ elf_dynsymtab (abfd) = shindex;
+ elf_tdata (abfd)->dynsymtab_hdr = *hdr;
+ elf_elfsections (abfd)[shindex] = hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ abfd->flags |= HAS_SYMS;
+
+ /* Besides being a symbol table, we also treat this as a regular
+ section, so that objcopy can handle it. */
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+
+ case SHT_STRTAB: /* A string table */
+ if (hdr->bfd_section != NULL)
+ return true;
+ if (ehdr->e_shstrndx == shindex)
+ {
+ elf_tdata (abfd)->shstrtab_hdr = *hdr;
+ elf_elfsections (abfd)[shindex] = &elf_tdata (abfd)->shstrtab_hdr;
+ return true;
+ }
+ {
+ unsigned int i;
+
+ for (i = 1; i < ehdr->e_shnum; i++)
+ {
+ Elf_Internal_Shdr *hdr2 = elf_elfsections (abfd)[i];
+ if (hdr2->sh_link == shindex)
+ {
+ if (! bfd_section_from_shdr (abfd, i))
+ return false;
+ if (elf_onesymtab (abfd) == i)
+ {
+ elf_tdata (abfd)->strtab_hdr = *hdr;
+ elf_elfsections (abfd)[shindex] =
+ &elf_tdata (abfd)->strtab_hdr;
+ return true;
+ }
+ if (elf_dynsymtab (abfd) == i)
+ {
+ elf_tdata (abfd)->dynstrtab_hdr = *hdr;
+ elf_elfsections (abfd)[shindex] = hdr =
+ &elf_tdata (abfd)->dynstrtab_hdr;
+ /* We also treat this as a regular section, so
+ that objcopy can handle it. */
+ break;
+ }
+#if 0 /* Not handling other string tables specially right now. */
+ hdr2 = elf_elfsections (abfd)[i]; /* in case it moved */
+ /* We have a strtab for some random other section. */
+ newsect = (asection *) hdr2->bfd_section;
+ if (!newsect)
+ break;
+ hdr->bfd_section = newsect;
+ hdr2 = &elf_section_data (newsect)->str_hdr;
+ *hdr2 = *hdr;
+ elf_elfsections (abfd)[shindex] = hdr2;
+#endif
+ }
+ }
+ }
+
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+
+ case SHT_REL:
+ case SHT_RELA:
+ /* *These* do a lot of work -- but build no sections! */
+ {
+ asection *target_sect;
+ Elf_Internal_Shdr *hdr2;
+ int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+
+ /* For some incomprehensible reason Oracle distributes
+ libraries for Solaris in which some of the objects have
+ bogus sh_link fields. It would be nice if we could just
+ reject them, but, unfortunately, some people need to use
+ them. We scan through the section headers; if we find only
+ one suitable symbol table, we clobber the sh_link to point
+ to it. I hope this doesn't break anything. */
+ if (elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_SYMTAB
+ && elf_elfsections (abfd)[hdr->sh_link]->sh_type != SHT_DYNSYM)
+ {
+ int scan;
+ int found;
+
+ found = 0;
+ for (scan = 1; scan < ehdr->e_shnum; scan++)
+ {
+ if (elf_elfsections (abfd)[scan]->sh_type == SHT_SYMTAB
+ || elf_elfsections (abfd)[scan]->sh_type == SHT_DYNSYM)
+ {
+ if (found != 0)
+ {
+ found = 0;
+ break;
+ }
+ found = scan;
+ }
+ }
+ if (found != 0)
+ hdr->sh_link = found;
+ }
+
+ /* Get the symbol table. */
+ if (elf_elfsections (abfd)[hdr->sh_link]->sh_type == SHT_SYMTAB
+ && ! bfd_section_from_shdr (abfd, hdr->sh_link))
+ return false;
+
+ /* If this reloc section does not use the main symbol table we
+ don't treat it as a reloc section. BFD can't adequately
+ represent such a section, so at least for now, we don't
+ try. We just present it as a normal section. */
+ if (hdr->sh_link != elf_onesymtab (abfd))
+ return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
+
+ /* Don't allow REL relocations on a machine that uses RELA and
+ vice versa. */
+ /* @@ Actually, the generic ABI does suggest that both might be
+ used in one file. But the four ABI Processor Supplements I
+ have access to right now all specify that only one is used on
+ each of those architectures. It's conceivable that, e.g., a
+ bunch of absolute 32-bit relocs might be more compact in REL
+ form even on a RELA machine... */
+ BFD_ASSERT (use_rela_p
+ ? (hdr->sh_type == SHT_RELA
+ && hdr->sh_entsize == bed->s->sizeof_rela)
+ : (hdr->sh_type == SHT_REL
+ && hdr->sh_entsize == bed->s->sizeof_rel));
+
+ if (! bfd_section_from_shdr (abfd, hdr->sh_info))
+ return false;
+ target_sect = bfd_section_from_elf_index (abfd, hdr->sh_info);
+ if (target_sect == NULL)
+ return false;
+
+ hdr2 = &elf_section_data (target_sect)->rel_hdr;
+ *hdr2 = *hdr;
+ elf_elfsections (abfd)[shindex] = hdr2;
+ target_sect->reloc_count = hdr->sh_size / hdr->sh_entsize;
+ target_sect->flags |= SEC_RELOC;
+ target_sect->relocation = NULL;
+ target_sect->rel_filepos = hdr->sh_offset;
+ abfd->flags |= HAS_RELOC;
+ return true;
+ }
+ break;
+
+ case SHT_SHLIB:
+ return true;
+
+ default:
+ /* Check for any processor-specific section types. */
+ {
+ if (bed->elf_backend_section_from_shdr)
+ (*bed->elf_backend_section_from_shdr) (abfd, hdr, name);
+ }
+ break;
+ }
+
+ return true;
+}
+
+/* Given an ELF section number, retrieve the corresponding BFD
+ section. */
+
+asection *
+bfd_section_from_elf_index (abfd, index)
+ bfd *abfd;
+ unsigned int index;
+{
+ BFD_ASSERT (index > 0 && index < SHN_LORESERVE);
+ if (index >= elf_elfheader (abfd)->e_shnum)
+ return NULL;
+ return elf_elfsections (abfd)[index]->bfd_section;
+}
+
+boolean
+_bfd_elf_new_section_hook (abfd, sec)
+ bfd *abfd;
+ asection *sec;
+{
+ struct bfd_elf_section_data *sdata;
+
+ sdata = (struct bfd_elf_section_data *) bfd_alloc (abfd, sizeof (*sdata));
+ if (!sdata)
+ return false;
+ sec->used_by_bfd = (PTR) sdata;
+ memset (sdata, 0, sizeof (*sdata));
+ return true;
+}
+
+/* Create a new bfd section from an ELF program header.
+
+ Since program segments have no names, we generate a synthetic name
+ of the form segment<NUM>, where NUM is generally the index in the
+ program header table. For segments that are split (see below) we
+ generate the names segment<NUM>a and segment<NUM>b.
+
+ Note that some program segments may have a file size that is different than
+ (less than) the memory size. All this means is that at execution the
+ system must allocate the amount of memory specified by the memory size,
+ but only initialize it with the first "file size" bytes read from the
+ file. This would occur for example, with program segments consisting
+ of combined data+bss.
+
+ To handle the above situation, this routine generates TWO bfd sections
+ for the single program segment. The first has the length specified by
+ the file size of the segment, and the second has the length specified
+ by the difference between the two sizes. In effect, the segment is split
+ into it's initialized and uninitialized parts.
+
+ */
+
+boolean
+bfd_section_from_phdr (abfd, hdr, index)
+ bfd *abfd;
+ Elf_Internal_Phdr *hdr;
+ int index;
+{
+ asection *newsect;
+ char *name;
+ char namebuf[64];
+ int split;
+
+ split = ((hdr->p_memsz > 0) &&
+ (hdr->p_filesz > 0) &&
+ (hdr->p_memsz > hdr->p_filesz));
+ sprintf (namebuf, split ? "segment%da" : "segment%d", index);
+ name = bfd_alloc (abfd, strlen (namebuf) + 1);
+ if (!name)
+ return false;
+ strcpy (name, namebuf);
+ newsect = bfd_make_section (abfd, name);
+ if (newsect == NULL)
+ return false;
+ newsect->vma = hdr->p_vaddr;
+ newsect->lma = hdr->p_paddr;
+ newsect->_raw_size = hdr->p_filesz;
+ newsect->filepos = hdr->p_offset;
+ newsect->flags |= SEC_HAS_CONTENTS;
+ if (hdr->p_type == PT_LOAD)
+ {
+ newsect->flags |= SEC_ALLOC;
+ newsect->flags |= SEC_LOAD;
+ if (hdr->p_flags & PF_X)
+ {
+ /* FIXME: all we known is that it has execute PERMISSION,
+ may be data. */
+ newsect->flags |= SEC_CODE;
+ }
+ }
+ if (!(hdr->p_flags & PF_W))
+ {
+ newsect->flags |= SEC_READONLY;
+ }
+
+ if (split)
+ {
+ sprintf (namebuf, "segment%db", index);
+ name = bfd_alloc (abfd, strlen (namebuf) + 1);
+ if (!name)
+ return false;
+ strcpy (name, namebuf);
+ newsect = bfd_make_section (abfd, name);
+ if (newsect == NULL)
+ return false;
+ newsect->vma = hdr->p_vaddr + hdr->p_filesz;
+ newsect->lma = hdr->p_paddr + hdr->p_filesz;
+ newsect->_raw_size = hdr->p_memsz - hdr->p_filesz;
+ if (hdr->p_type == PT_LOAD)
+ {
+ newsect->flags |= SEC_ALLOC;
+ if (hdr->p_flags & PF_X)
+ newsect->flags |= SEC_CODE;
+ }
+ if (!(hdr->p_flags & PF_W))
+ newsect->flags |= SEC_READONLY;
+ }
+
+ return true;
+}
+
+/* Set up an ELF internal section header for a section. */
+
+/*ARGSUSED*/
+static void
+elf_fake_sections (abfd, asect, failedptrarg)
+ bfd *abfd;
+ asection *asect;
+ PTR failedptrarg;
+{
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ boolean *failedptr = (boolean *) failedptrarg;
+ Elf_Internal_Shdr *this_hdr;
+
+ if (*failedptr)
+ {
+ /* We already failed; just get out of the bfd_map_over_sections
+ loop. */
+ return;
+ }
+
+ this_hdr = &elf_section_data (asect)->this_hdr;
+
+ this_hdr->sh_name = (unsigned long) _bfd_stringtab_add (elf_shstrtab (abfd),
+ asect->name,
+ true, false);
+ if (this_hdr->sh_name == (unsigned long) -1)
+ {
+ *failedptr = true;
+ return;
+ }
+
+ this_hdr->sh_flags = 0;
+
+ if ((asect->flags & SEC_ALLOC) != 0)
+ this_hdr->sh_addr = asect->vma;
+ else
+ this_hdr->sh_addr = 0;
+
+ this_hdr->sh_offset = 0;
+ this_hdr->sh_size = asect->_raw_size;
+ this_hdr->sh_link = 0;
+ this_hdr->sh_addralign = 1 << asect->alignment_power;
+ /* The sh_entsize and sh_info fields may have been set already by
+ copy_private_section_data. */
+
+ this_hdr->bfd_section = asect;
+ this_hdr->contents = NULL;
+
+ /* FIXME: This should not be based on section names. */
+ if (strcmp (asect->name, ".dynstr") == 0)
+ this_hdr->sh_type = SHT_STRTAB;
+ else if (strcmp (asect->name, ".hash") == 0)
+ {
+ this_hdr->sh_type = SHT_HASH;
+ this_hdr->sh_entsize = bed->s->arch_size / 8;
+ }
+ else if (strcmp (asect->name, ".dynsym") == 0)
+ {
+ this_hdr->sh_type = SHT_DYNSYM;
+ this_hdr->sh_entsize = bed->s->sizeof_sym;
+ }
+ else if (strcmp (asect->name, ".dynamic") == 0)
+ {
+ this_hdr->sh_type = SHT_DYNAMIC;
+ this_hdr->sh_entsize = bed->s->sizeof_dyn;
+ }
+ else if (strncmp (asect->name, ".rela", 5) == 0
+ && get_elf_backend_data (abfd)->use_rela_p)
+ {
+ this_hdr->sh_type = SHT_RELA;
+ this_hdr->sh_entsize = bed->s->sizeof_rela;
+ }
+ else if (strncmp (asect->name, ".rel", 4) == 0
+ && ! get_elf_backend_data (abfd)->use_rela_p)
+ {
+ this_hdr->sh_type = SHT_REL;
+ this_hdr->sh_entsize = bed->s->sizeof_rel;
+ }
+ else if (strcmp (asect->name, ".note") == 0)
+ this_hdr->sh_type = SHT_NOTE;
+ else if (strncmp (asect->name, ".stab", 5) == 0
+ && strcmp (asect->name + strlen (asect->name) - 3, "str") == 0)
+ this_hdr->sh_type = SHT_STRTAB;
+ else if ((asect->flags & SEC_ALLOC) != 0
+ && (asect->flags & SEC_LOAD) != 0)
+ this_hdr->sh_type = SHT_PROGBITS;
+ else if ((asect->flags & SEC_ALLOC) != 0
+ && ((asect->flags & SEC_LOAD) == 0))
+ this_hdr->sh_type = SHT_NOBITS;
+ else
+ {
+ /* Who knows? */
+ this_hdr->sh_type = SHT_PROGBITS;
+ }
+
+ if ((asect->flags & SEC_ALLOC) != 0)
+ this_hdr->sh_flags |= SHF_ALLOC;
+ if ((asect->flags & SEC_READONLY) == 0)
+ this_hdr->sh_flags |= SHF_WRITE;
+ if ((asect->flags & SEC_CODE) != 0)
+ this_hdr->sh_flags |= SHF_EXECINSTR;
+
+ /* Check for processor-specific section types. */
+ {
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if (bed->elf_backend_fake_sections)
+ (*bed->elf_backend_fake_sections) (abfd, this_hdr, asect);
+ }
+
+ /* If the section has relocs, set up a section header for the
+ SHT_REL[A] section. */
+ if ((asect->flags & SEC_RELOC) != 0)
+ {
+ Elf_Internal_Shdr *rela_hdr;
+ int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+ char *name;
+
+ rela_hdr = &elf_section_data (asect)->rel_hdr;
+ name = bfd_alloc (abfd, sizeof ".rela" + strlen (asect->name));
+ if (name == NULL)
+ {
+ *failedptr = true;
+ return;
+ }
+ sprintf (name, "%s%s", use_rela_p ? ".rela" : ".rel", asect->name);
+ rela_hdr->sh_name =
+ (unsigned int) _bfd_stringtab_add (elf_shstrtab (abfd), name,
+ true, false);
+ if (rela_hdr->sh_name == (unsigned int) -1)
+ {
+ *failedptr = true;
+ return;
+ }
+ rela_hdr->sh_type = use_rela_p ? SHT_RELA : SHT_REL;
+ rela_hdr->sh_entsize = (use_rela_p
+ ? bed->s->sizeof_rela
+ : bed->s->sizeof_rel);
+ rela_hdr->sh_addralign = bed->s->file_align;
+ rela_hdr->sh_flags = 0;
+ rela_hdr->sh_addr = 0;
+ rela_hdr->sh_size = 0;
+ rela_hdr->sh_offset = 0;
+ }
+}
+
+/* Assign all ELF section numbers. The dummy first section is handled here
+ too. The link/info pointers for the standard section types are filled
+ in here too, while we're at it. */
+
+static boolean
+assign_section_numbers (abfd)
+ bfd *abfd;
+{
+ struct elf_obj_tdata *t = elf_tdata (abfd);
+ asection *sec;
+ unsigned int section_number;
+ Elf_Internal_Shdr **i_shdrp;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ section_number = 1;
+
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ struct bfd_elf_section_data *d = elf_section_data (sec);
+
+ d->this_idx = section_number++;
+ if ((sec->flags & SEC_RELOC) == 0)
+ d->rel_idx = 0;
+ else
+ d->rel_idx = section_number++;
+ }
+
+ t->shstrtab_section = section_number++;
+ elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section;
+ t->shstrtab_hdr.sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
+
+ if (abfd->symcount > 0)
+ {
+ t->symtab_section = section_number++;
+ t->strtab_section = section_number++;
+ }
+
+ elf_elfheader (abfd)->e_shnum = section_number;
+
+ /* Set up the list of section header pointers, in agreement with the
+ indices. */
+ i_shdrp = ((Elf_Internal_Shdr **)
+ bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *)));
+ if (i_shdrp == NULL)
+ return false;
+
+ i_shdrp[0] = ((Elf_Internal_Shdr *)
+ bfd_alloc (abfd, sizeof (Elf_Internal_Shdr)));
+ if (i_shdrp[0] == NULL)
+ {
+ bfd_release (abfd, i_shdrp);
+ return false;
+ }
+ memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr));
+
+ elf_elfsections (abfd) = i_shdrp;
+
+ i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr;
+ if (abfd->symcount > 0)
+ {
+ i_shdrp[t->symtab_section] = &t->symtab_hdr;
+ i_shdrp[t->strtab_section] = &t->strtab_hdr;
+ t->symtab_hdr.sh_link = t->strtab_section;
+ }
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ struct bfd_elf_section_data *d = elf_section_data (sec);
+ asection *s;
+ const char *name;
+
+ i_shdrp[d->this_idx] = &d->this_hdr;
+ if (d->rel_idx != 0)
+ i_shdrp[d->rel_idx] = &d->rel_hdr;
+
+ /* Fill in the sh_link and sh_info fields while we're at it. */
+
+ /* sh_link of a reloc section is the section index of the symbol
+ table. sh_info is the section index of the section to which
+ the relocation entries apply. */
+ if (d->rel_idx != 0)
+ {
+ d->rel_hdr.sh_link = t->symtab_section;
+ d->rel_hdr.sh_info = d->this_idx;
+ }
+
+ switch (d->this_hdr.sh_type)
+ {
+ case SHT_REL:
+ case SHT_RELA:
+ /* A reloc section which we are treating as a normal BFD
+ section. sh_link is the section index of the symbol
+ table. sh_info is the section index of the section to
+ which the relocation entries apply. We assume that an
+ allocated reloc section uses the dynamic symbol table.
+ FIXME: How can we be sure? */
+ s = bfd_get_section_by_name (abfd, ".dynsym");
+ if (s != NULL)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+
+ /* We look up the section the relocs apply to by name. */
+ name = sec->name;
+ if (d->this_hdr.sh_type == SHT_REL)
+ name += 4;
+ else
+ name += 5;
+ s = bfd_get_section_by_name (abfd, name);
+ if (s != NULL)
+ d->this_hdr.sh_info = elf_section_data (s)->this_idx;
+ break;
+
+ case SHT_STRTAB:
+ /* We assume that a section named .stab*str is a stabs
+ string section. We look for a section with the same name
+ but without the trailing ``str'', and set its sh_link
+ field to point to this section. */
+ if (strncmp (sec->name, ".stab", sizeof ".stab" - 1) == 0
+ && strcmp (sec->name + strlen (sec->name) - 3, "str") == 0)
+ {
+ size_t len;
+ char *alc;
+
+ len = strlen (sec->name);
+ alc = (char *) bfd_malloc (len - 2);
+ if (alc == NULL)
+ return false;
+ strncpy (alc, sec->name, len - 3);
+ alc[len - 3] = '\0';
+ s = bfd_get_section_by_name (abfd, alc);
+ free (alc);
+ if (s != NULL)
+ {
+ elf_section_data (s)->this_hdr.sh_link = d->this_idx;
+
+ /* This is a .stab section. */
+ elf_section_data (s)->this_hdr.sh_entsize =
+ 4 + 2 * (bed->s->arch_size / 8);
+ }
+ }
+ break;
+
+ case SHT_DYNAMIC:
+ case SHT_DYNSYM:
+ /* sh_link is the section header index of the string table
+ used for the dynamic entries or symbol table. */
+ s = bfd_get_section_by_name (abfd, ".dynstr");
+ if (s != NULL)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ break;
+
+ case SHT_HASH:
+ /* sh_link is the section header index of the symbol table
+ this hash table is for. */
+ s = bfd_get_section_by_name (abfd, ".dynsym");
+ if (s != NULL)
+ d->this_hdr.sh_link = elf_section_data (s)->this_idx;
+ break;
+ }
+ }
+
+ return true;
+}
+
+/* Map symbol from it's internal number to the external number, moving
+ all local symbols to be at the head of the list. */
+
+static INLINE int
+sym_is_global (abfd, sym)
+ bfd *abfd;
+ asymbol *sym;
+{
+ /* If the backend has a special mapping, use it. */
+ if (get_elf_backend_data (abfd)->elf_backend_sym_is_global)
+ return ((*get_elf_backend_data (abfd)->elf_backend_sym_is_global)
+ (abfd, sym));
+
+ return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || bfd_is_und_section (bfd_get_section (sym))
+ || bfd_is_com_section (bfd_get_section (sym)));
+}
+
+static boolean
+elf_map_symbols (abfd)
+ bfd *abfd;
+{
+ int symcount = bfd_get_symcount (abfd);
+ asymbol **syms = bfd_get_outsymbols (abfd);
+ asymbol **sect_syms;
+ int num_locals = 0;
+ int num_globals = 0;
+ int num_locals2 = 0;
+ int num_globals2 = 0;
+ int max_index = 0;
+ int num_sections = 0;
+ int idx;
+ asection *asect;
+ asymbol **new_syms;
+
+#ifdef DEBUG
+ fprintf (stderr, "elf_map_symbols\n");
+ fflush (stderr);
+#endif
+
+ /* Add a section symbol for each BFD section. FIXME: Is this really
+ necessary? */
+ for (asect = abfd->sections; asect; asect = asect->next)
+ {
+ if (max_index < asect->index)
+ max_index = asect->index;
+ }
+
+ max_index++;
+ sect_syms = (asymbol **) bfd_zalloc (abfd, max_index * sizeof (asymbol *));
+ if (sect_syms == NULL)
+ return false;
+ elf_section_syms (abfd) = sect_syms;
+
+ for (idx = 0; idx < symcount; idx++)
+ {
+ if ((syms[idx]->flags & BSF_SECTION_SYM) != 0
+ && (syms[idx]->value + syms[idx]->section->vma) == 0)
+ {
+ asection *sec;
+
+ sec = syms[idx]->section;
+ if (sec->owner != NULL)
+ {
+ if (sec->owner != abfd)
+ {
+ if (sec->output_offset != 0)
+ continue;
+ sec = sec->output_section;
+ BFD_ASSERT (sec->owner == abfd);
+ }
+ sect_syms[sec->index] = syms[idx];
+ }
+ }
+ }
+
+ for (asect = abfd->sections; asect; asect = asect->next)
+ {
+ asymbol *sym;
+
+ if (sect_syms[asect->index] != NULL)
+ continue;
+
+ sym = bfd_make_empty_symbol (abfd);
+ if (sym == NULL)
+ return false;
+ sym->the_bfd = abfd;
+ sym->name = asect->name;
+ sym->value = 0;
+ /* Set the flags to 0 to indicate that this one was newly added. */
+ sym->flags = 0;
+ sym->section = asect;
+ sect_syms[asect->index] = sym;
+ num_sections++;
+#ifdef DEBUG
+ fprintf (stderr,
+ "creating section symbol, name = %s, value = 0x%.8lx, index = %d, section = 0x%.8lx\n",
+ asect->name, (long) asect->vma, asect->index, (long) asect);
+#endif
+ }
+
+ /* Classify all of the symbols. */
+ for (idx = 0; idx < symcount; idx++)
+ {
+ if (!sym_is_global (abfd, syms[idx]))
+ num_locals++;
+ else
+ num_globals++;
+ }
+ for (asect = abfd->sections; asect; asect = asect->next)
+ {
+ if (sect_syms[asect->index] != NULL
+ && sect_syms[asect->index]->flags == 0)
+ {
+ sect_syms[asect->index]->flags = BSF_SECTION_SYM;
+ if (!sym_is_global (abfd, sect_syms[asect->index]))
+ num_locals++;
+ else
+ num_globals++;
+ sect_syms[asect->index]->flags = 0;
+ }
+ }
+
+ /* Now sort the symbols so the local symbols are first. */
+ new_syms = ((asymbol **)
+ bfd_alloc (abfd,
+ (num_locals + num_globals) * sizeof (asymbol *)));
+ if (new_syms == NULL)
+ return false;
+
+ for (idx = 0; idx < symcount; idx++)
+ {
+ asymbol *sym = syms[idx];
+ int i;
+
+ if (!sym_is_global (abfd, sym))
+ i = num_locals2++;
+ else
+ i = num_locals + num_globals2++;
+ new_syms[i] = sym;
+ sym->udata.i = i + 1;
+ }
+ for (asect = abfd->sections; asect; asect = asect->next)
+ {
+ if (sect_syms[asect->index] != NULL
+ && sect_syms[asect->index]->flags == 0)
+ {
+ asymbol *sym = sect_syms[asect->index];
+ int i;
+
+ sym->flags = BSF_SECTION_SYM;
+ if (!sym_is_global (abfd, sym))
+ i = num_locals2++;
+ else
+ i = num_locals + num_globals2++;
+ new_syms[i] = sym;
+ sym->udata.i = i + 1;
+ }
+ }
+
+ bfd_set_symtab (abfd, new_syms, num_locals + num_globals);
+
+ elf_num_locals (abfd) = num_locals;
+ elf_num_globals (abfd) = num_globals;
+ return true;
+}
+
+/* Align to the maximum file alignment that could be required for any
+ ELF data structure. */
+
+static INLINE file_ptr align_file_position PARAMS ((file_ptr, int));
+static INLINE file_ptr
+align_file_position (off, align)
+ file_ptr off;
+ int align;
+{
+ return (off + align - 1) & ~(align - 1);
+}
+
+/* Assign a file position to a section, optionally aligning to the
+ required section alignment. */
+
+INLINE file_ptr
+_bfd_elf_assign_file_position_for_section (i_shdrp, offset, align)
+ Elf_Internal_Shdr *i_shdrp;
+ file_ptr offset;
+ boolean align;
+{
+ if (align)
+ {
+ unsigned int al;
+
+ al = i_shdrp->sh_addralign;
+ if (al > 1)
+ offset = BFD_ALIGN (offset, al);
+ }
+ i_shdrp->sh_offset = offset;
+ if (i_shdrp->bfd_section != NULL)
+ i_shdrp->bfd_section->filepos = offset;
+ if (i_shdrp->sh_type != SHT_NOBITS)
+ offset += i_shdrp->sh_size;
+ return offset;
+}
+
+/* Compute the file positions we are going to put the sections at, and
+ otherwise prepare to begin writing out the ELF file. If LINK_INFO
+ is not NULL, this is being called by the ELF backend linker. */
+
+boolean
+_bfd_elf_compute_section_file_positions (abfd, link_info)
+ bfd *abfd;
+ struct bfd_link_info *link_info;
+{
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ boolean failed;
+ struct bfd_strtab_hash *strtab;
+ Elf_Internal_Shdr *shstrtab_hdr;
+
+ if (abfd->output_has_begun)
+ return true;
+
+ /* Do any elf backend specific processing first. */
+ if (bed->elf_backend_begin_write_processing)
+ (*bed->elf_backend_begin_write_processing) (abfd, link_info);
+
+ if (! prep_headers (abfd))
+ return false;
+
+ failed = false;
+ bfd_map_over_sections (abfd, elf_fake_sections, &failed);
+ if (failed)
+ return false;
+
+ if (!assign_section_numbers (abfd))
+ return false;
+
+ /* The backend linker builds symbol table information itself. */
+ if (link_info == NULL && abfd->symcount > 0)
+ {
+ if (! swap_out_syms (abfd, &strtab))
+ return false;
+ }
+
+ shstrtab_hdr = &elf_tdata (abfd)->shstrtab_hdr;
+ /* sh_name was set in prep_headers. */
+ shstrtab_hdr->sh_type = SHT_STRTAB;
+ shstrtab_hdr->sh_flags = 0;
+ shstrtab_hdr->sh_addr = 0;
+ shstrtab_hdr->sh_size = _bfd_stringtab_size (elf_shstrtab (abfd));
+ shstrtab_hdr->sh_entsize = 0;
+ shstrtab_hdr->sh_link = 0;
+ shstrtab_hdr->sh_info = 0;
+ /* sh_offset is set in assign_file_positions_except_relocs. */
+ shstrtab_hdr->sh_addralign = 1;
+
+ if (!assign_file_positions_except_relocs (abfd))
+ return false;
+
+ if (link_info == NULL && abfd->symcount > 0)
+ {
+ file_ptr off;
+ Elf_Internal_Shdr *hdr;
+
+ off = elf_tdata (abfd)->next_file_pos;
+
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+
+ hdr = &elf_tdata (abfd)->strtab_hdr;
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+
+ elf_tdata (abfd)->next_file_pos = off;
+
+ /* Now that we know where the .strtab section goes, write it
+ out. */
+ if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) != 0
+ || ! _bfd_stringtab_emit (abfd, strtab))
+ return false;
+ _bfd_stringtab_free (strtab);
+ }
+
+ abfd->output_has_begun = true;
+
+ return true;
+}
+
+/* Create a mapping from a set of sections to a program segment. */
+
+static INLINE struct elf_segment_map *
+make_mapping (abfd, sections, from, to, phdr)
+ bfd *abfd;
+ asection **sections;
+ unsigned int from;
+ unsigned int to;
+ boolean phdr;
+{
+ struct elf_segment_map *m;
+ unsigned int i;
+ asection **hdrpp;
+
+ m = ((struct elf_segment_map *)
+ bfd_zalloc (abfd,
+ (sizeof (struct elf_segment_map)
+ + (to - from - 1) * sizeof (asection *))));
+ if (m == NULL)
+ return NULL;
+ m->next = NULL;
+ m->p_type = PT_LOAD;
+ for (i = from, hdrpp = sections + from; i < to; i++, hdrpp++)
+ m->sections[i - from] = *hdrpp;
+ m->count = to - from;
+
+ if (from == 0 && phdr)
+ {
+ /* Include the headers in the first PT_LOAD segment. */
+ m->includes_filehdr = 1;
+ m->includes_phdrs = 1;
+ }
+
+ return m;
+}
+
+/* Set up a mapping from BFD sections to program segments. */
+
+static boolean
+map_sections_to_segments (abfd)
+ bfd *abfd;
+{
+ asection **sections = NULL;
+ asection *s;
+ unsigned int i;
+ unsigned int count;
+ struct elf_segment_map *mfirst;
+ struct elf_segment_map **pm;
+ struct elf_segment_map *m;
+ asection *last_hdr;
+ unsigned int phdr_index;
+ bfd_vma maxpagesize;
+ asection **hdrpp;
+ boolean phdr_in_section = true;
+ boolean writable;
+ asection *dynsec;
+
+ if (elf_tdata (abfd)->segment_map != NULL)
+ return true;
+
+ if (bfd_count_sections (abfd) == 0)
+ return true;
+
+ /* Select the allocated sections, and sort them. */
+
+ sections = (asection **) bfd_malloc (bfd_count_sections (abfd)
+ * sizeof (asection *));
+ if (sections == NULL)
+ goto error_return;
+
+ i = 0;
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_ALLOC) != 0)
+ {
+ sections[i] = s;
+ ++i;
+ }
+ }
+ BFD_ASSERT (i <= bfd_count_sections (abfd));
+ count = i;
+
+ qsort (sections, (size_t) count, sizeof (asection *), elf_sort_sections);
+
+ /* Build the mapping. */
+
+ mfirst = NULL;
+ pm = &mfirst;
+
+ /* If we have a .interp section, then create a PT_PHDR segment for
+ the program headers and a PT_INTERP segment for the .interp
+ section. */
+ s = bfd_get_section_by_name (abfd, ".interp");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ m = ((struct elf_segment_map *)
+ bfd_zalloc (abfd, sizeof (struct elf_segment_map)));
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_PHDR;
+ /* FIXME: UnixWare and Solaris set PF_X, Irix 5 does not. */
+ m->p_flags = PF_R | PF_X;
+ m->p_flags_valid = 1;
+ m->includes_phdrs = 1;
+
+ *pm = m;
+ pm = &m->next;
+
+ m = ((struct elf_segment_map *)
+ bfd_zalloc (abfd, sizeof (struct elf_segment_map)));
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_INTERP;
+ m->count = 1;
+ m->sections[0] = s;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
+ /* Look through the sections. We put sections in the same program
+ segment when the start of the second section can be placed within
+ a few bytes of the end of the first section. */
+ last_hdr = NULL;
+ phdr_index = 0;
+ maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
+ writable = false;
+ dynsec = bfd_get_section_by_name (abfd, ".dynamic");
+ if (dynsec != NULL
+ && (dynsec->flags & SEC_LOAD) == 0)
+ dynsec = NULL;
+
+ /* Deal with -Ttext or something similar such that the
+ first section is not adjacent to the program headers. */
+ if (count
+ && ((sections[0]->lma % maxpagesize) <
+ (elf_tdata (abfd)->program_header_size % maxpagesize)))
+ phdr_in_section = false;
+
+ for (i = 0, hdrpp = sections; i < count; i++, hdrpp++)
+ {
+ asection *hdr;
+
+ hdr = *hdrpp;
+
+ /* See if this section and the last one will fit in the same
+ segment. Don't put a loadable section after a non-loadable
+ section. If we are building a dynamic executable, don't put
+ a writable section in a read only segment (we don't do this
+ for a non-dynamic executable because some people prefer to
+ have only one program segment; anybody can use PHDRS in their
+ linker script to control what happens anyhow). */
+ if (last_hdr == NULL
+ || ((BFD_ALIGN (last_hdr->lma + last_hdr->_raw_size, maxpagesize)
+ >= hdr->lma)
+ && ((last_hdr->flags & SEC_LOAD) != 0
+ || (hdr->flags & SEC_LOAD) == 0)
+ && (dynsec == NULL
+ || writable
+ || (hdr->flags & SEC_READONLY) != 0)))
+ {
+ last_hdr = hdr;
+ continue;
+ }
+
+ /* This section won't fit in the program segment. We must
+ create a new program header holding all the sections from
+ phdr_index until hdr. */
+
+ m = make_mapping (abfd, sections, phdr_index, i, phdr_in_section);
+ if (m == NULL)
+ goto error_return;
+
+ *pm = m;
+ pm = &m->next;
+
+ if ((hdr->flags & SEC_READONLY) == 0)
+ writable = true;
+
+ last_hdr = hdr;
+ phdr_index = i;
+ phdr_in_section = false;
+ }
+
+ /* Create a final PT_LOAD program segment. */
+ if (last_hdr != NULL)
+ {
+ m = make_mapping (abfd, sections, phdr_index, i, phdr_in_section);
+ if (m == NULL)
+ goto error_return;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
+ /* If there is a .dynamic section, throw in a PT_DYNAMIC segment. */
+ if (dynsec != NULL)
+ {
+ m = ((struct elf_segment_map *)
+ bfd_zalloc (abfd, sizeof (struct elf_segment_map)));
+ if (m == NULL)
+ goto error_return;
+ m->next = NULL;
+ m->p_type = PT_DYNAMIC;
+ m->count = 1;
+ m->sections[0] = dynsec;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
+ free (sections);
+ sections = NULL;
+
+ elf_tdata (abfd)->segment_map = mfirst;
+ return true;
+
+ error_return:
+ if (sections != NULL)
+ free (sections);
+ return false;
+}
+
+/* Sort sections by VMA. */
+
+static int
+elf_sort_sections (arg1, arg2)
+ const PTR arg1;
+ const PTR arg2;
+{
+ const asection *sec1 = *(const asection **) arg1;
+ const asection *sec2 = *(const asection **) arg2;
+
+ if (sec1->vma < sec2->vma)
+ return -1;
+ else if (sec1->vma > sec2->vma)
+ return 1;
+
+ /* Put !SEC_LOAD sections after SEC_LOAD ones. */
+
+#define TOEND(x) (((x)->flags & SEC_LOAD) == 0)
+
+ if (TOEND (sec1))
+ if (TOEND (sec2))
+ return sec1->target_index - sec2->target_index;
+ else
+ return 1;
+
+ if (TOEND (sec2))
+ return -1;
+
+#undef TOEND
+
+ /* Sort by size, to put zero sized sections before others at the
+ same address. */
+
+ if (sec1->_raw_size < sec2->_raw_size)
+ return -1;
+ if (sec1->_raw_size > sec2->_raw_size)
+ return 1;
+
+ return sec1->target_index - sec2->target_index;
+}
+
+/* Assign file positions to the sections based on the mapping from
+ sections to segments. This function also sets up some fields in
+ the file header, and writes out the program headers. */
+
+static boolean
+assign_file_positions_for_segments (abfd)
+ bfd *abfd;
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ unsigned int count;
+ struct elf_segment_map *m;
+ unsigned int alloc;
+ Elf_Internal_Phdr *phdrs;
+ file_ptr off;
+ bfd_vma filehdr_vaddr, filehdr_paddr;
+ bfd_vma phdrs_vaddr, phdrs_paddr;
+ Elf_Internal_Phdr *p;
+
+ if (elf_tdata (abfd)->segment_map == NULL)
+ {
+ if (! map_sections_to_segments (abfd))
+ return false;
+ }
+
+ if (bed->elf_backend_modify_segment_map)
+ {
+ if (! (*bed->elf_backend_modify_segment_map) (abfd))
+ return false;
+ }
+
+ count = 0;
+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ ++count;
+
+ elf_elfheader (abfd)->e_phoff = bed->s->sizeof_ehdr;
+ elf_elfheader (abfd)->e_phentsize = bed->s->sizeof_phdr;
+ elf_elfheader (abfd)->e_phnum = count;
+
+ if (count == 0)
+ return true;
+
+ /* If we already counted the number of program segments, make sure
+ that we allocated enough space. This happens when SIZEOF_HEADERS
+ is used in a linker script. */
+ alloc = elf_tdata (abfd)->program_header_size / bed->s->sizeof_phdr;
+ if (alloc != 0 && count > alloc)
+ {
+ ((*_bfd_error_handler)
+ ("%s: Not enough room for program headers (allocated %u, need %u)",
+ bfd_get_filename (abfd), alloc, count));
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ if (alloc == 0)
+ alloc = count;
+
+ phdrs = ((Elf_Internal_Phdr *)
+ bfd_alloc (abfd, alloc * sizeof (Elf_Internal_Phdr)));
+ if (phdrs == NULL)
+ return false;
+
+ off = bed->s->sizeof_ehdr;
+ off += alloc * bed->s->sizeof_phdr;
+
+ filehdr_vaddr = 0;
+ filehdr_paddr = 0;
+ phdrs_vaddr = 0;
+ phdrs_paddr = 0;
+ for (m = elf_tdata (abfd)->segment_map, p = phdrs;
+ m != NULL;
+ m = m->next, p++)
+ {
+ unsigned int i;
+ asection **secpp;
+
+ /* If elf_segment_map is not from map_sections_to_segments, the
+ sections may not be correctly ordered. */
+ if (m->count > 0)
+ qsort (m->sections, (size_t) m->count, sizeof (asection *),
+ elf_sort_sections);
+
+ p->p_type = m->p_type;
+
+ if (m->p_flags_valid)
+ p->p_flags = m->p_flags;
+ else
+ p->p_flags = 0;
+
+ if (p->p_type == PT_LOAD
+ && m->count > 0
+ && (m->sections[0]->flags & SEC_LOAD) != 0)
+ off += (m->sections[0]->vma - off) % bed->maxpagesize;
+
+ if (m->count == 0)
+ p->p_vaddr = 0;
+ else
+ p->p_vaddr = m->sections[0]->vma;
+
+ if (m->p_paddr_valid)
+ p->p_paddr = m->p_paddr;
+ else if (m->count == 0)
+ p->p_paddr = 0;
+ else
+ p->p_paddr = m->sections[0]->lma;
+
+ if (p->p_type == PT_LOAD)
+ p->p_align = bed->maxpagesize;
+ else if (m->count == 0)
+ p->p_align = bed->s->file_align;
+ else
+ p->p_align = 0;
+
+ p->p_offset = 0;
+ p->p_filesz = 0;
+ p->p_memsz = 0;
+
+ if (m->includes_filehdr)
+ {
+ if (! m->p_flags_valid)
+ p->p_flags |= PF_R;
+ p->p_offset = 0;
+ p->p_filesz = bed->s->sizeof_ehdr;
+ p->p_memsz = bed->s->sizeof_ehdr;
+ if (m->count > 0)
+ {
+ BFD_ASSERT (p->p_type == PT_LOAD);
+ p->p_vaddr -= off;
+ if (! m->p_paddr_valid)
+ p->p_paddr -= off;
+ }
+ if (p->p_type == PT_LOAD)
+ {
+ filehdr_vaddr = p->p_vaddr;
+ filehdr_paddr = p->p_paddr;
+ }
+ }
+
+ if (m->includes_phdrs)
+ {
+ if (! m->p_flags_valid)
+ p->p_flags |= PF_R;
+ if (m->includes_filehdr)
+ {
+ if (p->p_type == PT_LOAD)
+ {
+ phdrs_vaddr = p->p_vaddr + bed->s->sizeof_ehdr;
+ phdrs_paddr = p->p_paddr + bed->s->sizeof_ehdr;
+ }
+ }
+ else
+ {
+ p->p_offset = bed->s->sizeof_ehdr;
+ if (m->count > 0)
+ {
+ BFD_ASSERT (p->p_type == PT_LOAD);
+ p->p_vaddr -= off - p->p_offset;
+ if (! m->p_paddr_valid)
+ p->p_paddr -= off - p->p_offset;
+ }
+ if (p->p_type == PT_LOAD)
+ {
+ phdrs_vaddr = p->p_vaddr;
+ phdrs_paddr = p->p_paddr;
+ }
+ }
+ p->p_filesz += alloc * bed->s->sizeof_phdr;
+ p->p_memsz += alloc * bed->s->sizeof_phdr;
+ }
+
+ if (p->p_type == PT_LOAD)
+ {
+ if (! m->includes_filehdr && ! m->includes_phdrs)
+ p->p_offset = off;
+ else
+ {
+ file_ptr adjust;
+
+ adjust = off - (p->p_offset + p->p_filesz);
+ p->p_filesz += adjust;
+ p->p_memsz += adjust;
+ }
+ }
+
+ for (i = 0, secpp = m->sections; i < m->count; i++, secpp++)
+ {
+ asection *sec;
+ flagword flags;
+ bfd_size_type align;
+
+ sec = *secpp;
+ flags = sec->flags;
+
+ if (p->p_type == PT_LOAD)
+ {
+ bfd_vma adjust;
+
+ /* The section VMA must equal the file position modulo
+ the page size. */
+ if ((flags & SEC_ALLOC) != 0)
+ {
+ adjust = (sec->vma - off) % bed->maxpagesize;
+ if (adjust != 0)
+ {
+ if (i == 0)
+ abort ();
+ p->p_memsz += adjust;
+ off += adjust;
+ if ((flags & SEC_LOAD) != 0)
+ p->p_filesz += adjust;
+ }
+ }
+
+ sec->filepos = off;
+
+ if ((flags & SEC_LOAD) != 0)
+ off += sec->_raw_size;
+ }
+
+ p->p_memsz += sec->_raw_size;
+
+ if ((flags & SEC_LOAD) != 0)
+ p->p_filesz += sec->_raw_size;
+
+ align = 1 << bfd_get_section_alignment (abfd, sec);
+ if (align > p->p_align)
+ p->p_align = align;
+
+ if (! m->p_flags_valid)
+ {
+ p->p_flags |= PF_R;
+ if ((flags & SEC_CODE) != 0)
+ p->p_flags |= PF_X;
+ if ((flags & SEC_READONLY) == 0)
+ p->p_flags |= PF_W;
+ }
+ }
+ }
+
+ /* Now that we have set the section file positions, we can set up
+ the file positions for the non PT_LOAD segments. */
+ for (m = elf_tdata (abfd)->segment_map, p = phdrs;
+ m != NULL;
+ m = m->next, p++)
+ {
+ if (p->p_type != PT_LOAD && m->count > 0)
+ {
+ BFD_ASSERT (! m->includes_filehdr && ! m->includes_phdrs);
+ p->p_offset = m->sections[0]->filepos;
+ }
+ if (m->count == 0)
+ {
+ if (m->includes_filehdr)
+ {
+ p->p_vaddr = filehdr_vaddr;
+ if (! m->p_paddr_valid)
+ p->p_paddr = filehdr_paddr;
+ }
+ else if (m->includes_phdrs)
+ {
+ p->p_vaddr = phdrs_vaddr;
+ if (! m->p_paddr_valid)
+ p->p_paddr = phdrs_paddr;
+ }
+ }
+ }
+
+ /* Clear out any program headers we allocated but did not use. */
+ for (; count < alloc; count++, p++)
+ {
+ memset (p, 0, sizeof *p);
+ p->p_type = PT_NULL;
+ }
+
+ elf_tdata (abfd)->phdr = phdrs;
+
+ elf_tdata (abfd)->next_file_pos = off;
+
+ /* Write out the program headers. */
+ if (bfd_seek (abfd, bed->s->sizeof_ehdr, SEEK_SET) != 0
+ || bed->s->write_out_phdrs (abfd, phdrs, alloc) != 0)
+ return false;
+
+ return true;
+}
+
+/* Get the size of the program header.
+
+ If this is called by the linker before any of the section VMA's are set, it
+ can't calculate the correct value for a strange memory layout. This only
+ happens when SIZEOF_HEADERS is used in a linker script. In this case,
+ SORTED_HDRS is NULL and we assume the normal scenario of one text and one
+ data segment (exclusive of .interp and .dynamic).
+
+ ??? User written scripts must either not use SIZEOF_HEADERS, or assume there
+ will be two segments. */
+
+static bfd_size_type
+get_program_header_size (abfd)
+ bfd *abfd;
+{
+ size_t segs;
+ asection *s;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ /* We can't return a different result each time we're called. */
+ if (elf_tdata (abfd)->program_header_size != 0)
+ return elf_tdata (abfd)->program_header_size;
+
+ if (elf_tdata (abfd)->segment_map != NULL)
+ {
+ struct elf_segment_map *m;
+
+ segs = 0;
+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ ++segs;
+ elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr;
+ return elf_tdata (abfd)->program_header_size;
+ }
+
+ /* Assume we will need exactly two PT_LOAD segments: one for text
+ and one for data. */
+ segs = 2;
+
+ s = bfd_get_section_by_name (abfd, ".interp");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ /* If we have a loadable interpreter section, we need a
+ PT_INTERP segment. In this case, assume we also need a
+ PT_PHDR segment, although that may not be true for all
+ targets. */
+ segs += 2;
+ }
+
+ if (bfd_get_section_by_name (abfd, ".dynamic") != NULL)
+ {
+ /* We need a PT_DYNAMIC segment. */
+ ++segs;
+ }
+
+ /* Let the backend count up any program headers it might need. */
+ if (bed->elf_backend_additional_program_headers)
+ {
+ int a;
+
+ a = (*bed->elf_backend_additional_program_headers) (abfd);
+ if (a == -1)
+ abort ();
+ segs += a;
+ }
+
+ elf_tdata (abfd)->program_header_size = segs * bed->s->sizeof_phdr;
+ return elf_tdata (abfd)->program_header_size;
+}
+
+/* Work out the file positions of all the sections. This is called by
+ _bfd_elf_compute_section_file_positions. All the section sizes and
+ VMAs must be known before this is called.
+
+ We do not consider reloc sections at this point, unless they form
+ part of the loadable image. Reloc sections are assigned file
+ positions in assign_file_positions_for_relocs, which is called by
+ write_object_contents and final_link.
+
+ We also don't set the positions of the .symtab and .strtab here. */
+
+static boolean
+assign_file_positions_except_relocs (abfd)
+ bfd *abfd;
+{
+ struct elf_obj_tdata * const tdata = elf_tdata (abfd);
+ Elf_Internal_Ehdr * const i_ehdrp = elf_elfheader (abfd);
+ Elf_Internal_Shdr ** const i_shdrpp = elf_elfsections (abfd);
+ file_ptr off;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ {
+ Elf_Internal_Shdr **hdrpp;
+ unsigned int i;
+
+ /* Start after the ELF header. */
+ off = i_ehdrp->e_ehsize;
+
+ /* We are not creating an executable, which means that we are
+ not creating a program header, and that the actual order of
+ the sections in the file is unimportant. */
+ for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++)
+ {
+ Elf_Internal_Shdr *hdr;
+
+ hdr = *hdrpp;
+ if (hdr->sh_type == SHT_REL || hdr->sh_type == SHT_RELA)
+ {
+ hdr->sh_offset = -1;
+ continue;
+ }
+ if (i == tdata->symtab_section
+ || i == tdata->strtab_section)
+ {
+ hdr->sh_offset = -1;
+ continue;
+ }
+
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ }
+ }
+ else
+ {
+ unsigned int i;
+ Elf_Internal_Shdr **hdrpp;
+
+ /* Assign file positions for the loaded sections based on the
+ assignment of sections to segments. */
+ if (! assign_file_positions_for_segments (abfd))
+ return false;
+
+ /* Assign file positions for the other sections. */
+
+ off = elf_tdata (abfd)->next_file_pos;
+ for (i = 1, hdrpp = i_shdrpp + 1; i < i_ehdrp->e_shnum; i++, hdrpp++)
+ {
+ Elf_Internal_Shdr *hdr;
+
+ hdr = *hdrpp;
+ if (hdr->bfd_section != NULL
+ && hdr->bfd_section->filepos != 0)
+ hdr->sh_offset = hdr->bfd_section->filepos;
+ else if ((hdr->sh_flags & SHF_ALLOC) != 0)
+ {
+ ((*_bfd_error_handler)
+ ("%s: warning: allocated section `%s' not in segment",
+ bfd_get_filename (abfd),
+ (hdr->bfd_section == NULL
+ ? "*unknown*"
+ : hdr->bfd_section->name)));
+ off += (hdr->sh_addr - off) % bed->maxpagesize;
+ off = _bfd_elf_assign_file_position_for_section (hdr, off,
+ false);
+ }
+ else if (hdr->sh_type == SHT_REL
+ || hdr->sh_type == SHT_RELA
+ || hdr == i_shdrpp[tdata->symtab_section]
+ || hdr == i_shdrpp[tdata->strtab_section])
+ hdr->sh_offset = -1;
+ else
+ off = _bfd_elf_assign_file_position_for_section (hdr, off, true);
+ }
+ }
+
+ /* Place the section headers. */
+ off = align_file_position (off, bed->s->file_align);
+ i_ehdrp->e_shoff = off;
+ off += i_ehdrp->e_shnum * i_ehdrp->e_shentsize;
+
+ elf_tdata (abfd)->next_file_pos = off;
+
+ return true;
+}
+
+static boolean
+prep_headers (abfd)
+ bfd *abfd;
+{
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
+ Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
+ Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
+ int count;
+ struct bfd_strtab_hash *shstrtab;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ i_ehdrp = elf_elfheader (abfd);
+ i_shdrp = elf_elfsections (abfd);
+
+ shstrtab = _bfd_elf_stringtab_init ();
+ if (shstrtab == NULL)
+ return false;
+
+ elf_shstrtab (abfd) = shstrtab;
+
+ i_ehdrp->e_ident[EI_MAG0] = ELFMAG0;
+ i_ehdrp->e_ident[EI_MAG1] = ELFMAG1;
+ i_ehdrp->e_ident[EI_MAG2] = ELFMAG2;
+ i_ehdrp->e_ident[EI_MAG3] = ELFMAG3;
+
+ i_ehdrp->e_ident[EI_CLASS] = bed->s->elfclass;
+ i_ehdrp->e_ident[EI_DATA] =
+ bfd_big_endian (abfd) ? ELFDATA2MSB : ELFDATA2LSB;
+ i_ehdrp->e_ident[EI_VERSION] = bed->s->ev_current;
+
+ for (count = EI_PAD; count < EI_NIDENT; count++)
+ i_ehdrp->e_ident[count] = 0;
+
+ if ((abfd->flags & DYNAMIC) != 0)
+ i_ehdrp->e_type = ET_DYN;
+ else if ((abfd->flags & EXEC_P) != 0)
+ i_ehdrp->e_type = ET_EXEC;
+ else
+ i_ehdrp->e_type = ET_REL;
+
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_unknown:
+ i_ehdrp->e_machine = EM_NONE;
+ break;
+ case bfd_arch_sparc:
+ if (bed->s->arch_size == 64)
+ i_ehdrp->e_machine = EM_SPARC64;
+ else
+ i_ehdrp->e_machine = EM_SPARC;
+ break;
+ case bfd_arch_i386:
+ i_ehdrp->e_machine = EM_386;
+ break;
+ case bfd_arch_m68k:
+ i_ehdrp->e_machine = EM_68K;
+ break;
+ case bfd_arch_m88k:
+ i_ehdrp->e_machine = EM_88K;
+ break;
+ case bfd_arch_i860:
+ i_ehdrp->e_machine = EM_860;
+ break;
+ case bfd_arch_mips: /* MIPS Rxxxx */
+ i_ehdrp->e_machine = EM_MIPS; /* only MIPS R3000 */
+ break;
+ case bfd_arch_hppa:
+ i_ehdrp->e_machine = EM_PARISC;
+ break;
+ case bfd_arch_powerpc:
+ i_ehdrp->e_machine = EM_PPC;
+ break;
+ /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
+ default:
+ i_ehdrp->e_machine = EM_NONE;
+ }
+ i_ehdrp->e_version = bed->s->ev_current;
+ i_ehdrp->e_ehsize = bed->s->sizeof_ehdr;
+
+ /* no program header, for now. */
+ i_ehdrp->e_phoff = 0;
+ i_ehdrp->e_phentsize = 0;
+ i_ehdrp->e_phnum = 0;
+
+ /* each bfd section is section header entry */
+ i_ehdrp->e_entry = bfd_get_start_address (abfd);
+ i_ehdrp->e_shentsize = bed->s->sizeof_shdr;
+
+ /* if we're building an executable, we'll need a program header table */
+ if (abfd->flags & EXEC_P)
+ {
+ /* it all happens later */
+#if 0
+ i_ehdrp->e_phentsize = sizeof (Elf_External_Phdr);
+
+ /* elf_build_phdrs() returns a (NULL-terminated) array of
+ Elf_Internal_Phdrs */
+ i_phdrp = elf_build_phdrs (abfd, i_ehdrp, i_shdrp, &i_ehdrp->e_phnum);
+ i_ehdrp->e_phoff = outbase;
+ outbase += i_ehdrp->e_phentsize * i_ehdrp->e_phnum;
+#endif
+ }
+ else
+ {
+ i_ehdrp->e_phentsize = 0;
+ i_phdrp = 0;
+ i_ehdrp->e_phoff = 0;
+ }
+
+ elf_tdata (abfd)->symtab_hdr.sh_name =
+ (unsigned int) _bfd_stringtab_add (shstrtab, ".symtab", true, false);
+ elf_tdata (abfd)->strtab_hdr.sh_name =
+ (unsigned int) _bfd_stringtab_add (shstrtab, ".strtab", true, false);
+ elf_tdata (abfd)->shstrtab_hdr.sh_name =
+ (unsigned int) _bfd_stringtab_add (shstrtab, ".shstrtab", true, false);
+ if (elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
+ || elf_tdata (abfd)->symtab_hdr.sh_name == (unsigned int) -1
+ || elf_tdata (abfd)->shstrtab_hdr.sh_name == (unsigned int) -1)
+ return false;
+
+ return true;
+}
+
+/* Assign file positions for all the reloc sections which are not part
+ of the loadable file image. */
+
+void
+_bfd_elf_assign_file_positions_for_relocs (abfd)
+ bfd *abfd;
+{
+ file_ptr off;
+ unsigned int i;
+ Elf_Internal_Shdr **shdrpp;
+
+ off = elf_tdata (abfd)->next_file_pos;
+
+ for (i = 1, shdrpp = elf_elfsections (abfd) + 1;
+ i < elf_elfheader (abfd)->e_shnum;
+ i++, shdrpp++)
+ {
+ Elf_Internal_Shdr *shdrp;
+
+ shdrp = *shdrpp;
+ if ((shdrp->sh_type == SHT_REL || shdrp->sh_type == SHT_RELA)
+ && shdrp->sh_offset == -1)
+ off = _bfd_elf_assign_file_position_for_section (shdrp, off, true);
+ }
+
+ elf_tdata (abfd)->next_file_pos = off;
+}
+
+boolean
+_bfd_elf_write_object_contents (abfd)
+ bfd *abfd;
+{
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ Elf_Internal_Ehdr *i_ehdrp;
+ Elf_Internal_Shdr **i_shdrp;
+ boolean failed;
+ unsigned int count;
+
+ if (! abfd->output_has_begun
+ && ! _bfd_elf_compute_section_file_positions (abfd,
+ (struct bfd_link_info *) NULL))
+ return false;
+
+ i_shdrp = elf_elfsections (abfd);
+ i_ehdrp = elf_elfheader (abfd);
+
+ failed = false;
+ bfd_map_over_sections (abfd, bed->s->write_relocs, &failed);
+ if (failed)
+ return false;
+ _bfd_elf_assign_file_positions_for_relocs (abfd);
+
+ /* After writing the headers, we need to write the sections too... */
+ for (count = 1; count < i_ehdrp->e_shnum; count++)
+ {
+ if (bed->elf_backend_section_processing)
+ (*bed->elf_backend_section_processing) (abfd, i_shdrp[count]);
+ if (i_shdrp[count]->contents)
+ {
+ if (bfd_seek (abfd, i_shdrp[count]->sh_offset, SEEK_SET) != 0
+ || (bfd_write (i_shdrp[count]->contents, i_shdrp[count]->sh_size,
+ 1, abfd)
+ != i_shdrp[count]->sh_size))
+ return false;
+ }
+ }
+
+ /* Write out the section header names. */
+ if (bfd_seek (abfd, elf_tdata (abfd)->shstrtab_hdr.sh_offset, SEEK_SET) != 0
+ || ! _bfd_stringtab_emit (abfd, elf_shstrtab (abfd)))
+ return false;
+
+ if (bed->elf_backend_final_write_processing)
+ (*bed->elf_backend_final_write_processing) (abfd,
+ elf_tdata (abfd)->linker);
+
+ return bed->s->write_shdrs_and_ehdr (abfd);
+}
+
+/* given a section, search the header to find them... */
+int
+_bfd_elf_section_from_bfd_section (abfd, asect)
+ bfd *abfd;
+ struct sec *asect;
+{
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
+ int index;
+ Elf_Internal_Shdr *hdr;
+ int maxindex = elf_elfheader (abfd)->e_shnum;
+
+ for (index = 0; index < maxindex; index++)
+ {
+ hdr = i_shdrp[index];
+ if (hdr->bfd_section == asect)
+ return index;
+ }
+
+ if (bed->elf_backend_section_from_bfd_section)
+ {
+ for (index = 0; index < maxindex; index++)
+ {
+ int retval;
+
+ hdr = i_shdrp[index];
+ retval = index;
+ if ((*bed->elf_backend_section_from_bfd_section)
+ (abfd, hdr, asect, &retval))
+ return retval;
+ }
+ }
+
+ if (bfd_is_abs_section (asect))
+ return SHN_ABS;
+ if (bfd_is_com_section (asect))
+ return SHN_COMMON;
+ if (bfd_is_und_section (asect))
+ return SHN_UNDEF;
+
+ return -1;
+}
+
+/* Given a BFD symbol, return the index in the ELF symbol table, or -1
+ on error. */
+
+int
+_bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
+ bfd *abfd;
+ struct symbol_cache_entry **asym_ptr_ptr;
+{
+ struct symbol_cache_entry *asym_ptr = *asym_ptr_ptr;
+ int idx;
+ flagword flags = asym_ptr->flags;
+
+ /* When gas creates relocations against local labels, it creates its
+ own symbol for the section, but does put the symbol into the
+ symbol chain, so udata is 0. When the linker is generating
+ relocatable output, this section symbol may be for one of the
+ input sections rather than the output section. */
+ if (asym_ptr->udata.i == 0
+ && (flags & BSF_SECTION_SYM)
+ && asym_ptr->section)
+ {
+ int indx;
+
+ if (asym_ptr->section->output_section != NULL)
+ indx = asym_ptr->section->output_section->index;
+ else
+ indx = asym_ptr->section->index;
+ if (elf_section_syms (abfd)[indx])
+ asym_ptr->udata.i = elf_section_syms (abfd)[indx]->udata.i;
+ }
+
+ idx = asym_ptr->udata.i;
+
+ if (idx == 0)
+ {
+ /* This case can occur when using --strip-symbol on a symbol
+ which is used in a relocation entry. */
+ (*_bfd_error_handler)
+ ("%s: symbol `%s' required but not present",
+ bfd_get_filename (abfd), bfd_asymbol_name (asym_ptr));
+ bfd_set_error (bfd_error_no_symbols);
+ return -1;
+ }
+
+#if DEBUG & 4
+ {
+ fprintf (stderr,
+ "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n",
+ (long) asym_ptr, asym_ptr->name, idx, flags,
+ elf_symbol_flags (flags));
+ fflush (stderr);
+ }
+#endif
+
+ return idx;
+}
+
+/* Copy private BFD data. This copies any program header information. */
+
+static boolean
+copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ Elf_Internal_Ehdr *iehdr;
+ struct elf_segment_map *mfirst;
+ struct elf_segment_map **pm;
+ Elf_Internal_Phdr *p;
+ unsigned int i, c;
+
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ if (elf_tdata (ibfd)->phdr == NULL)
+ return true;
+
+ iehdr = elf_elfheader (ibfd);
+
+ mfirst = NULL;
+ pm = &mfirst;
+
+ c = elf_elfheader (ibfd)->e_phnum;
+ for (i = 0, p = elf_tdata (ibfd)->phdr; i < c; i++, p++)
+ {
+ unsigned int csecs;
+ asection *s;
+ struct elf_segment_map *m;
+ unsigned int isec;
+
+ csecs = 0;
+
+ /* The complicated case when p_vaddr is 0 is to handle the
+ Solaris linker, which generates a PT_INTERP section with
+ p_vaddr and p_memsz set to 0. */
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ if (((s->vma >= p->p_vaddr
+ && (s->vma + s->_raw_size <= p->p_vaddr + p->p_memsz
+ || s->vma + s->_raw_size <= p->p_vaddr + p->p_filesz))
+ || (p->p_vaddr == 0
+ && p->p_filesz > 0
+ && (s->flags & SEC_HAS_CONTENTS) != 0
+ && (bfd_vma) s->filepos >= p->p_offset
+ && ((bfd_vma) s->filepos + s->_raw_size
+ <= p->p_offset + p->p_filesz)))
+ && (s->flags & SEC_ALLOC) != 0
+ && s->output_section != NULL)
+ ++csecs;
+
+ m = ((struct elf_segment_map *)
+ bfd_alloc (obfd,
+ (sizeof (struct elf_segment_map)
+ + (csecs - 1) * sizeof (asection *))));
+ if (m == NULL)
+ return false;
+
+ m->next = NULL;
+ m->p_type = p->p_type;
+ m->p_flags = p->p_flags;
+ m->p_flags_valid = 1;
+ m->p_paddr = p->p_paddr;
+ m->p_paddr_valid = 1;
+
+ m->includes_filehdr = (p->p_offset == 0
+ && p->p_filesz >= iehdr->e_ehsize);
+
+ m->includes_phdrs = (p->p_offset <= (bfd_vma) iehdr->e_phoff
+ && (p->p_offset + p->p_filesz
+ >= ((bfd_vma) iehdr->e_phoff
+ + iehdr->e_phnum * iehdr->e_phentsize)));
+
+ isec = 0;
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ {
+ if (((s->vma >= p->p_vaddr
+ && (s->vma + s->_raw_size <= p->p_vaddr + p->p_memsz
+ || s->vma + s->_raw_size <= p->p_vaddr + p->p_filesz))
+ || (p->p_vaddr == 0
+ && p->p_filesz > 0
+ && (s->flags & SEC_HAS_CONTENTS) != 0
+ && (bfd_vma) s->filepos >= p->p_offset
+ && ((bfd_vma) s->filepos + s->_raw_size
+ <= p->p_offset + p->p_filesz)))
+ && (s->flags & SEC_ALLOC) != 0
+ && s->output_section != NULL)
+ {
+ m->sections[isec] = s->output_section;
+ ++isec;
+ }
+ }
+ BFD_ASSERT (isec == csecs);
+ m->count = csecs;
+
+ *pm = m;
+ pm = &m->next;
+ }
+
+ elf_tdata (obfd)->segment_map = mfirst;
+
+ return true;
+}
+
+/* Copy private section information. This copies over the entsize
+ field, and sometimes the info field. */
+
+boolean
+_bfd_elf_copy_private_section_data (ibfd, isec, obfd, osec)
+ bfd *ibfd;
+ asection *isec;
+ bfd *obfd;
+ asection *osec;
+{
+ Elf_Internal_Shdr *ihdr, *ohdr;
+
+ if (ibfd->xvec->flavour != bfd_target_elf_flavour
+ || obfd->xvec->flavour != bfd_target_elf_flavour)
+ return true;
+
+ /* Copy over private BFD data if it has not already been copied.
+ This must be done here, rather than in the copy_private_bfd_data
+ entry point, because the latter is called after the section
+ contents have been set, which means that the program headers have
+ already been worked out. */
+ if (elf_tdata (obfd)->segment_map == NULL
+ && elf_tdata (ibfd)->phdr != NULL)
+ {
+ asection *s;
+
+ /* Only set up the segments when all the sections have been set
+ up. */
+ for (s = ibfd->sections; s != NULL; s = s->next)
+ if (s->output_section == NULL)
+ break;
+ if (s == NULL)
+ {
+ if (! copy_private_bfd_data (ibfd, obfd))
+ return false;
+ }
+ }
+
+ ihdr = &elf_section_data (isec)->this_hdr;
+ ohdr = &elf_section_data (osec)->this_hdr;
+
+ ohdr->sh_entsize = ihdr->sh_entsize;
+
+ if (ihdr->sh_type == SHT_SYMTAB
+ || ihdr->sh_type == SHT_DYNSYM)
+ ohdr->sh_info = ihdr->sh_info;
+
+ return true;
+}
+
+/* Copy private symbol information. If this symbol is in a section
+ which we did not map into a BFD section, try to map the section
+ index correctly. We use special macro definitions for the mapped
+ section indices; these definitions are interpreted by the
+ swap_out_syms function. */
+
+#define MAP_ONESYMTAB (SHN_LORESERVE - 1)
+#define MAP_DYNSYMTAB (SHN_LORESERVE - 2)
+#define MAP_STRTAB (SHN_LORESERVE - 3)
+#define MAP_SHSTRTAB (SHN_LORESERVE - 4)
+
+boolean
+_bfd_elf_copy_private_symbol_data (ibfd, isymarg, obfd, osymarg)
+ bfd *ibfd;
+ asymbol *isymarg;
+ bfd *obfd;
+ asymbol *osymarg;
+{
+ elf_symbol_type *isym, *osym;
+
+ isym = elf_symbol_from (ibfd, isymarg);
+ osym = elf_symbol_from (obfd, osymarg);
+
+ if (isym != NULL
+ && osym != NULL
+ && bfd_is_abs_section (isym->symbol.section))
+ {
+ unsigned int shndx;
+
+ shndx = isym->internal_elf_sym.st_shndx;
+ if (shndx == elf_onesymtab (ibfd))
+ shndx = MAP_ONESYMTAB;
+ else if (shndx == elf_dynsymtab (ibfd))
+ shndx = MAP_DYNSYMTAB;
+ else if (shndx == elf_tdata (ibfd)->strtab_section)
+ shndx = MAP_STRTAB;
+ else if (shndx == elf_tdata (ibfd)->shstrtab_section)
+ shndx = MAP_SHSTRTAB;
+ osym->internal_elf_sym.st_shndx = shndx;
+ }
+
+ return true;
+}
+
+/* Swap out the symbols. */
+
+static boolean
+swap_out_syms (abfd, sttp)
+ bfd *abfd;
+ struct bfd_strtab_hash **sttp;
+{
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ if (!elf_map_symbols (abfd))
+ return false;
+
+ /* Dump out the symtabs. */
+ {
+ int symcount = bfd_get_symcount (abfd);
+ asymbol **syms = bfd_get_outsymbols (abfd);
+ struct bfd_strtab_hash *stt;
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Shdr *symstrtab_hdr;
+ char *outbound_syms;
+ int idx;
+
+ stt = _bfd_elf_stringtab_init ();
+ if (stt == NULL)
+ return false;
+
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ symtab_hdr->sh_type = SHT_SYMTAB;
+ symtab_hdr->sh_entsize = bed->s->sizeof_sym;
+ symtab_hdr->sh_size = symtab_hdr->sh_entsize * (symcount + 1);
+ symtab_hdr->sh_info = elf_num_locals (abfd) + 1;
+ symtab_hdr->sh_addralign = bed->s->file_align;
+
+ symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
+ symstrtab_hdr->sh_type = SHT_STRTAB;
+
+ outbound_syms = bfd_alloc (abfd,
+ (1 + symcount) * bed->s->sizeof_sym);
+ if (outbound_syms == NULL)
+ return false;
+ symtab_hdr->contents = (PTR) outbound_syms;
+
+ /* now generate the data (for "contents") */
+ {
+ /* Fill in zeroth symbol and swap it out. */
+ Elf_Internal_Sym sym;
+ sym.st_name = 0;
+ sym.st_value = 0;
+ sym.st_size = 0;
+ sym.st_info = 0;
+ sym.st_other = 0;
+ sym.st_shndx = SHN_UNDEF;
+ bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
+ outbound_syms += bed->s->sizeof_sym;
+ }
+ for (idx = 0; idx < symcount; idx++)
+ {
+ Elf_Internal_Sym sym;
+ bfd_vma value = syms[idx]->value;
+ elf_symbol_type *type_ptr;
+ flagword flags = syms[idx]->flags;
+ int type;
+
+ if (flags & BSF_SECTION_SYM)
+ /* Section symbols have no names. */
+ sym.st_name = 0;
+ else
+ {
+ sym.st_name = (unsigned long) _bfd_stringtab_add (stt,
+ syms[idx]->name,
+ true, false);
+ if (sym.st_name == (unsigned long) -1)
+ return false;
+ }
+
+ type_ptr = elf_symbol_from (abfd, syms[idx]);
+
+ if (bfd_is_com_section (syms[idx]->section))
+ {
+ /* ELF common symbols put the alignment into the `value' field,
+ and the size into the `size' field. This is backwards from
+ how BFD handles it, so reverse it here. */
+ sym.st_size = value;
+ if (type_ptr == NULL
+ || type_ptr->internal_elf_sym.st_value == 0)
+ sym.st_value = value >= 16 ? 16 : (1 << bfd_log2 (value));
+ else
+ sym.st_value = type_ptr->internal_elf_sym.st_value;
+ sym.st_shndx = _bfd_elf_section_from_bfd_section (abfd,
+ syms[idx]->section);
+ }
+ else
+ {
+ asection *sec = syms[idx]->section;
+ int shndx;
+
+ if (sec->output_section)
+ {
+ value += sec->output_offset;
+ sec = sec->output_section;
+ }
+ value += sec->vma;
+ sym.st_value = value;
+ sym.st_size = type_ptr ? type_ptr->internal_elf_sym.st_size : 0;
+
+ if (bfd_is_abs_section (sec)
+ && type_ptr != NULL
+ && type_ptr->internal_elf_sym.st_shndx != 0)
+ {
+ /* This symbol is in a real ELF section which we did
+ not create as a BFD section. Undo the mapping done
+ by copy_private_symbol_data. */
+ shndx = type_ptr->internal_elf_sym.st_shndx;
+ switch (shndx)
+ {
+ case MAP_ONESYMTAB:
+ shndx = elf_onesymtab (abfd);
+ break;
+ case MAP_DYNSYMTAB:
+ shndx = elf_dynsymtab (abfd);
+ break;
+ case MAP_STRTAB:
+ shndx = elf_tdata (abfd)->strtab_section;
+ break;
+ case MAP_SHSTRTAB:
+ shndx = elf_tdata (abfd)->shstrtab_section;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+
+ if (shndx == -1)
+ {
+ asection *sec2;
+
+ /* Writing this would be a hell of a lot easier if
+ we had some decent documentation on bfd, and
+ knew what to expect of the library, and what to
+ demand of applications. For example, it
+ appears that `objcopy' might not set the
+ section of a symbol to be a section that is
+ actually in the output file. */
+ sec2 = bfd_get_section_by_name (abfd, sec->name);
+ BFD_ASSERT (sec2 != 0);
+ shndx = _bfd_elf_section_from_bfd_section (abfd, sec2);
+ BFD_ASSERT (shndx != -1);
+ }
+ }
+
+ sym.st_shndx = shndx;
+ }
+
+ if ((flags & BSF_FUNCTION) != 0)
+ type = STT_FUNC;
+ else if ((flags & BSF_OBJECT) != 0)
+ type = STT_OBJECT;
+ else
+ type = STT_NOTYPE;
+
+ if (bfd_is_com_section (syms[idx]->section))
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, type);
+ else if (bfd_is_und_section (syms[idx]->section))
+ sym.st_info = ELF_ST_INFO (((flags & BSF_WEAK)
+ ? STB_WEAK
+ : STB_GLOBAL),
+ type);
+ else if (flags & BSF_SECTION_SYM)
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ else if (flags & BSF_FILE)
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+ else
+ {
+ int bind = STB_LOCAL;
+
+ if (flags & BSF_LOCAL)
+ bind = STB_LOCAL;
+ else if (flags & BSF_WEAK)
+ bind = STB_WEAK;
+ else if (flags & BSF_GLOBAL)
+ bind = STB_GLOBAL;
+
+ sym.st_info = ELF_ST_INFO (bind, type);
+ }
+
+ sym.st_other = 0;
+ bed->s->swap_symbol_out (abfd, &sym, (PTR) outbound_syms);
+ outbound_syms += bed->s->sizeof_sym;
+ }
+
+ *sttp = stt;
+ symstrtab_hdr->sh_size = _bfd_stringtab_size (stt);
+ symstrtab_hdr->sh_type = SHT_STRTAB;
+
+ symstrtab_hdr->sh_flags = 0;
+ symstrtab_hdr->sh_addr = 0;
+ symstrtab_hdr->sh_entsize = 0;
+ symstrtab_hdr->sh_link = 0;
+ symstrtab_hdr->sh_info = 0;
+ symstrtab_hdr->sh_addralign = 1;
+ }
+
+ return true;
+}
+
+/* Return the number of bytes required to hold the symtab vector.
+
+ Note that we base it on the count plus 1, since we will null terminate
+ the vector allocated based on this size. However, the ELF symbol table
+ always has a dummy entry as symbol #0, so it ends up even. */
+
+long
+_bfd_elf_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ long symcount;
+ long symtab_size;
+ Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
+
+ symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+ symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+
+ return symtab_size;
+}
+
+long
+_bfd_elf_get_dynamic_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ long symcount;
+ long symtab_size;
+ Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+
+ if (elf_dynsymtab (abfd) == 0)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+
+ symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
+ symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+
+ return symtab_size;
+}
+
+long
+_bfd_elf_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ return (asect->reloc_count + 1) * sizeof (arelent *);
+}
+
+/* Canonicalize the relocs. */
+
+long
+_bfd_elf_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *tblptr;
+ unsigned int i;
+
+ if (! get_elf_backend_data (abfd)->s->slurp_reloc_table (abfd, section, symbols))
+ return -1;
+
+ tblptr = section->relocation;
+ for (i = 0; i < section->reloc_count; i++)
+ *relptr++ = tblptr++;
+
+ *relptr = NULL;
+
+ return section->reloc_count;
+}
+
+long
+_bfd_elf_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ long symcount = get_elf_backend_data (abfd)->s->slurp_symbol_table (abfd, alocation, false);
+
+ if (symcount >= 0)
+ bfd_get_symcount (abfd) = symcount;
+ return symcount;
+}
+
+long
+_bfd_elf_canonicalize_dynamic_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ return get_elf_backend_data (abfd)->s->slurp_symbol_table (abfd, alocation, true);
+}
+
+asymbol *
+_bfd_elf_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ elf_symbol_type *newsym;
+
+ newsym = (elf_symbol_type *) bfd_zalloc (abfd, sizeof (elf_symbol_type));
+ if (!newsym)
+ return NULL;
+ else
+ {
+ newsym->symbol.the_bfd = abfd;
+ return &newsym->symbol;
+ }
+}
+
+void
+_bfd_elf_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+alent *
+_bfd_elf_get_lineno (ignore_abfd, symbol)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+{
+ abort ();
+ return NULL;
+}
+
+boolean
+_bfd_elf_set_arch_mach (abfd, arch, machine)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ /* If this isn't the right architecture for this backend, and this
+ isn't the generic backend, fail. */
+ if (arch != get_elf_backend_data (abfd)->arch
+ && arch != bfd_arch_unknown
+ && get_elf_backend_data (abfd)->arch != bfd_arch_unknown)
+ return false;
+
+ return bfd_default_set_arch_mach (abfd, arch, machine);
+}
+
+/* Find the nearest line to a particular section and offset, for error
+ reporting. */
+
+boolean
+_bfd_elf_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;
+{
+ boolean found;
+ const char *filename;
+ asymbol *func;
+ bfd_vma low_func;
+ asymbol **p;
+
+ if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
+ &found, filename_ptr,
+ functionname_ptr, line_ptr,
+ &elf_tdata (abfd)->line_info))
+ return false;
+ if (found)
+ return true;
+
+ if (symbols == NULL)
+ return false;
+
+ filename = NULL;
+ func = NULL;
+ low_func = 0;
+
+ for (p = symbols; *p != NULL; p++)
+ {
+ elf_symbol_type *q;
+
+ q = (elf_symbol_type *) *p;
+
+ if (bfd_get_section (&q->symbol) != section)
+ continue;
+
+ switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
+ {
+ default:
+ break;
+ case STT_FILE:
+ filename = bfd_asymbol_name (&q->symbol);
+ break;
+ case STT_FUNC:
+ if (q->symbol.section == section
+ && q->symbol.value >= low_func
+ && q->symbol.value <= offset)
+ {
+ func = (asymbol *) q;
+ low_func = q->symbol.value;
+ }
+ break;
+ }
+ }
+
+ if (func == NULL)
+ return false;
+
+ *filename_ptr = filename;
+ *functionname_ptr = bfd_asymbol_name (func);
+ *line_ptr = 0;
+ return true;
+}
+
+int
+_bfd_elf_sizeof_headers (abfd, reloc)
+ bfd *abfd;
+ boolean reloc;
+{
+ int ret;
+
+ ret = get_elf_backend_data (abfd)->s->sizeof_ehdr;
+ if (! reloc)
+ ret += get_program_header_size (abfd);
+ return ret;
+}
+
+boolean
+_bfd_elf_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ Elf_Internal_Shdr *hdr;
+
+ if (! abfd->output_has_begun
+ && ! _bfd_elf_compute_section_file_positions (abfd,
+ (struct bfd_link_info *) NULL))
+ return false;
+
+ hdr = &elf_section_data (section)->this_hdr;
+
+ if (bfd_seek (abfd, hdr->sh_offset + offset, SEEK_SET) == -1)
+ return false;
+ if (bfd_write (location, 1, count, abfd) != count)
+ return false;
+
+ return true;
+}
+
+void
+_bfd_elf_no_info_to_howto (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf_Internal_Rela *dst;
+{
+ abort ();
+}
+
+#if 0
+void
+_bfd_elf_no_info_to_howto_rel (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf_Internal_Rel *dst;
+{
+ abort ();
+}
+#endif
diff --git a/contrib/gdb/bfd/elf32-gen.c b/contrib/gdb/bfd/elf32-gen.c
new file mode 100644
index 0000000..385fda2
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-gen.c
@@ -0,0 +1,37 @@
+/* Generic support for 32-bit ELF
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+/* This does not include any relocations, but should be good enough
+ for GDB to read the file. */
+
+#define TARGET_LITTLE_SYM bfd_elf32_little_generic_vec
+#define TARGET_LITTLE_NAME "elf32-little"
+#define TARGET_BIG_SYM bfd_elf32_big_generic_vec
+#define TARGET_BIG_NAME "elf32-big"
+#define ELF_ARCH bfd_arch_unknown
+#define ELF_MACHINE_CODE EM_NONE
+#define bfd_elf32_bfd_reloc_type_lookup bfd_default_reloc_type_lookup
+#define elf_info_to_howto _bfd_elf_no_info_to_howto
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-hppa.c b/contrib/gdb/bfd/elf32-hppa.c
new file mode 100644
index 0000000..2386731
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-hppa.c
@@ -0,0 +1,2984 @@
+/* BFD back-end for HP PA-RISC ELF files.
+ Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+
+ Written by
+
+ Center for Software Science
+ Department of Computer Science
+ University of Utah
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "obstack.h"
+#include "elf-bfd.h"
+
+/* The internal type of a symbol table extension entry. */
+typedef unsigned long symext_entryS;
+
+/* The external type of a symbol table extension entry. */
+#define ELF32_PARISC_SX_SIZE (4)
+#define ELF32_PARISC_SX_GET(bfd, addr) bfd_h_get_32 ((bfd), (addr))
+#define ELF32_PARISC_SX_PUT(bfd, val, addr) \
+ bfd_h_put_32 ((bfd), (val), (addr))
+
+/* HPPA symbol table extension entry types */
+enum elf32_hppa_symextn_types
+{
+ PARISC_SXT_NULL,
+ PARISC_SXT_SYMNDX,
+ PARISC_SXT_ARG_RELOC,
+};
+
+/* These macros compose and decompose the value of a symextn entry:
+
+ entry_type = ELF32_PARISC_SX_TYPE(word);
+ entry_value = ELF32_PARISC_SX_VAL(word);
+ word = ELF32_PARISC_SX_WORD(type,val); */
+
+#define ELF32_PARISC_SX_TYPE(p) ((p) >> 24)
+#define ELF32_PARISC_SX_VAL(p) ((p) & 0xFFFFFF)
+#define ELF32_PARISC_SX_WORD(type,val) (((type) << 24) + (val & 0xFFFFFF))
+
+/* The following was added facilitate implementation of the .hppa_symextn
+ section. This section is built after the symbol table is built in the
+ elf_write_object_contents routine (called from bfd_close). It is built
+ so late because it requires information that is not known until
+ the symbol and string table sections have been allocated, and
+ the symbol table has been built. */
+
+#define SYMEXTN_SECTION_NAME ".PARISC.symext"
+
+struct symext_chain
+ {
+ symext_entryS entry;
+ struct symext_chain *next;
+ };
+
+typedef struct symext_chain symext_chainS;
+
+/* We use three different hash tables to hold information for
+ linking PA ELF objects.
+
+ The first is the elf32_hppa_link_hash_table which is derived
+ from the standard ELF linker hash table. We use this as a place to
+ attach other hash tables and static information.
+
+ The second is the stub hash table which is derived from the
+ base BFD hash table. The stub hash table holds the information
+ necessary to build the linker stubs during a link.
+
+ The last hash table keeps track of argument location information needed
+ to build hash tables. Each function with nonzero argument location
+ bits will have an entry in this table. */
+
+/* Hash table for linker stubs. */
+
+struct elf32_hppa_stub_hash_entry
+{
+ /* Base hash table entry structure, we can get the name of the stub
+ (and thus know exactly what actions it performs) from the base
+ hash table entry. */
+ struct bfd_hash_entry root;
+
+ /* Offset of the beginning of this stub. */
+ bfd_vma offset;
+
+ /* Given the symbol's value and its section we can determine its final
+ value when building the stubs (so the stub knows where to jump. */
+ symvalue target_value;
+ asection *target_section;
+};
+
+struct elf32_hppa_stub_hash_table
+{
+ /* The hash table itself. */
+ struct bfd_hash_table root;
+
+ /* The stub BFD. */
+ bfd *stub_bfd;
+
+ /* Where to place the next stub. */
+ bfd_byte *location;
+
+ /* Current offset in the stub section. */
+ unsigned int offset;
+
+};
+
+/* Hash table for argument location information. */
+
+struct elf32_hppa_args_hash_entry
+{
+ /* Base hash table entry structure. */
+ struct bfd_hash_entry root;
+
+ /* The argument location bits for this entry. */
+ int arg_bits;
+};
+
+struct elf32_hppa_args_hash_table
+{
+ /* The hash table itself. */
+ struct bfd_hash_table root;
+};
+
+struct elf32_hppa_link_hash_entry
+{
+ struct elf_link_hash_entry root;
+};
+
+struct elf32_hppa_link_hash_table
+{
+ /* The main hash table. */
+ struct elf_link_hash_table root;
+
+ /* The stub hash table. */
+ struct elf32_hppa_stub_hash_table *stub_hash_table;
+
+ /* The argument relocation bits hash table. */
+ struct elf32_hppa_args_hash_table *args_hash_table;
+
+ /* A count of the number of output symbols. */
+ unsigned int output_symbol_count;
+
+ /* Stuff so we can handle DP relative relocations. */
+ long global_value;
+ int global_sym_defined;
+};
+
+/* FIXME. */
+#define ARGUMENTS 0
+#define RETURN_VALUE 1
+
+/* The various argument relocations that may be performed. */
+typedef enum
+{
+ /* No relocation. */
+ NO,
+ /* Relocate 32 bits from GR to FP register. */
+ GF,
+ /* Relocate 64 bits from a GR pair to FP pair. */
+ GD,
+ /* Relocate 32 bits from FP to GR. */
+ FG,
+ /* Relocate 64 bits from FP pair to GR pair. */
+ DG,
+} arg_reloc_type;
+
+/* What is being relocated (eg which argument or the return value). */
+typedef enum
+{
+ ARG0, ARG1, ARG2, ARG3, RET,
+} arg_reloc_location;
+
+
+/* ELF32/HPPA relocation support
+
+ This file contains ELF32/HPPA relocation support as specified
+ in the Stratus FTX/Golf Object File Format (SED-1762) dated
+ February 1994. */
+
+#include "elf32-hppa.h"
+#include "hppa_stubs.h"
+
+static bfd_reloc_status_type hppa_elf_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+
+static unsigned long hppa_elf_relocate_insn
+ PARAMS ((bfd *, asection *, unsigned long, unsigned long, long,
+ long, unsigned long, unsigned long, unsigned long));
+
+static bfd_reloc_status_type hppa_elf_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd*, char **));
+
+static reloc_howto_type * elf_hppa_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+
+static boolean elf32_hppa_set_section_contents
+ PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));
+
+static void elf_info_to_howto
+ PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
+
+static boolean elf32_hppa_backend_symbol_table_processing
+ PARAMS ((bfd *, elf_symbol_type *, unsigned int));
+
+static void elf32_hppa_backend_begin_write_processing
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+static void elf32_hppa_backend_final_write_processing
+ PARAMS ((bfd *, boolean));
+
+static void add_entry_to_symext_chain
+ PARAMS ((bfd *, unsigned int, unsigned int, symext_chainS **,
+ symext_chainS **));
+
+static void
+elf_hppa_tc_make_sections PARAMS ((bfd *, symext_chainS *));
+
+static boolean hppa_elf_is_local_label PARAMS ((bfd *, asymbol *));
+
+static boolean elf32_hppa_add_symbol_hook
+ PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+ const char **, flagword *, asection **, bfd_vma *));
+
+static bfd_reloc_status_type elf32_hppa_bfd_final_link_relocate
+ PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *,
+ bfd_byte *, bfd_vma, bfd_vma, bfd_vma, struct bfd_link_info *,
+ asection *, const char *, int));
+
+static struct bfd_link_hash_table *elf32_hppa_link_hash_table_create
+ PARAMS ((bfd *));
+
+static struct bfd_hash_entry *
+elf32_hppa_stub_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+
+static struct bfd_hash_entry *
+elf32_hppa_args_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+
+static boolean
+elf32_hppa_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *,
+ bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+
+static boolean
+elf32_hppa_stub_hash_table_init
+ PARAMS ((struct elf32_hppa_stub_hash_table *, bfd *,
+ struct bfd_hash_entry *(*) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *))));
+
+static boolean
+elf32_hppa_build_one_stub PARAMS ((struct bfd_hash_entry *, PTR));
+
+static boolean
+elf32_hppa_read_symext_info
+ PARAMS ((bfd *, Elf_Internal_Shdr *, struct elf32_hppa_args_hash_table *,
+ Elf_Internal_Sym *));
+
+static unsigned int elf32_hppa_size_of_stub
+ PARAMS ((unsigned int, unsigned int, bfd_vma, bfd_vma, const char *));
+
+static boolean elf32_hppa_arg_reloc_needed
+ PARAMS ((unsigned int, unsigned int, arg_reloc_type []));
+
+static void elf32_hppa_name_of_stub
+ PARAMS ((unsigned int, unsigned int, bfd_vma, bfd_vma, char *));
+
+static boolean elf32_hppa_size_symext PARAMS ((struct bfd_hash_entry *, PTR));
+
+static boolean elf32_hppa_link_output_symbol_hook
+ PARAMS ((bfd *, struct bfd_link_info *, const char *,
+ Elf_Internal_Sym *, asection *));
+
+/* ELF/PA relocation howto entries. */
+
+static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] =
+{
+ {R_PARISC_NONE, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_NONE"},
+ {R_PARISC_DIR32, 0, 0, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR32"},
+ {R_PARISC_DIR21L, 0, 0, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR21L"},
+ {R_PARISC_DIR17R, 0, 0, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR17R"},
+ {R_PARISC_DIR17F, 0, 0, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR17F"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DIR14R, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DIR14R"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_PCREL21L, 0, 0, 21, true, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PCREL21L"},
+ {R_PARISC_PCREL17R, 0, 0, 17, true, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PCREL17R"},
+ {R_PARISC_PCREL17F, 0, 0, 17, true, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PCREL17F"},
+ {R_PARISC_PCREL17C, 0, 0, 17, true, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PCREL17C"},
+ {R_PARISC_PCREL14R, 0, 0, 14, true, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PCREL14R"},
+ {R_PARISC_PCREL14F, 0, 0, 14, true, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PCREL14F"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DPREL21L, 0, 0, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DPREL21L"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DPREL14R, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DPREL14R"},
+ {R_PARISC_DPREL14F, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DPREL14F"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DLTREL21L, 0, 0, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DLTREL21L"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DLTREL14R, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DLTREL14R"},
+ {R_PARISC_DLTREL14F, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DLTREL14F"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DLTIND21L, 0, 0, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DLTIND21L"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DLTIND14R, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DLTIND14R"},
+ {R_PARISC_DLTIND14F, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_DLTIND14F"},
+
+ {R_PARISC_SETBASE, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_SETBASE"},
+ {R_PARISC_BASEREL32, 0, 0, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_BASEREL32"},
+ {R_PARISC_BASEREL21L, 0, 0, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_BASEREL21L"},
+ {R_PARISC_BASEREL17R, 0, 0, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_BASEREL17R"},
+ {R_PARISC_BASEREL17F, 0, 0, 17, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_BASEREL17F"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_BASEREL14R, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_BASEREL14R"},
+ {R_PARISC_BASEREL14F, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_BASEREL14F"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_TEXTREL32, 0, 0, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_TEXTREL32"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_DATAREL32, 0, 0, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_PLABEL32, 0, 0, 32, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PLABEL32"},
+ {R_PARISC_PLABEL21L, 0, 0, 21, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PLABEL21L"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_PLABEL14R, 0, 0, 14, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PLABEL14R"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_PLTIND21L, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PLTIND21L"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_UNIMPLEMENTED"},
+ {R_PARISC_PLTIND14R, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PLTIND14R"},
+ {R_PARISC_PLTIND14F, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_PLTIND14F"},
+
+
+ {R_PARISC_COPY, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_COPY"},
+ {R_PARISC_GLOB_DAT, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_GLOB_DAT"},
+ {R_PARISC_JMP_SLOT, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_JMP_SLOT"},
+ {R_PARISC_RELATIVE, 0, 0, 0, false, 0, complain_overflow_bitfield, hppa_elf_reloc, "R_PARISC_RELATIVE"},
+
+ {R_PARISC_UNIMPLEMENTED, 0, 0, 0, false, 0, complain_overflow_dont, NULL, "R_PARISC_UNIMPLEMENTED"},
+};
+
+/* Where (what register type) is an argument comming from? */
+typedef enum
+{
+ AR_NO,
+ AR_GR,
+ AR_FR,
+ AR_FU,
+ AR_FPDBL1,
+ AR_FPDBL2,
+} arg_location;
+
+/* Horizontal represents the callee's argument location information,
+ vertical represents caller's argument location information. Value at a
+ particular X,Y location represents what (if any) argument relocation
+ needs to be performed to make caller and callee agree. */
+
+static CONST arg_reloc_type arg_mismatches[6][6] =
+{
+ {NO, NO, NO, NO, NO, NO},
+ {NO, NO, GF, NO, GD, NO},
+ {NO, FG, NO, NO, NO, NO},
+ {NO, NO, NO, NO, NO, NO},
+ {NO, DG, NO, NO, NO, NO},
+ {NO, DG, NO, NO, NO, NO},
+};
+
+/* Likewise, but reversed for the return value. */
+static CONST arg_reloc_type ret_mismatches[6][6] =
+{
+ {NO, NO, NO, NO, NO, NO},
+ {NO, NO, FG, NO, DG, NO},
+ {NO, GF, NO, NO, NO, NO},
+ {NO, NO, NO, NO, NO, NO},
+ {NO, GD, NO, NO, NO, NO},
+ {NO, GD, NO, NO, NO, NO},
+};
+
+/* Misc static crud for symbol extension records. */
+static symext_chainS *symext_rootP;
+static symext_chainS *symext_lastP;
+static bfd_size_type symext_chain_size;
+
+/* FIXME: We should be able to try this static variable! */
+static bfd_byte *symextn_contents;
+
+
+/* For linker stub hash tables. */
+#define elf32_hppa_stub_hash_lookup(table, string, create, copy) \
+ ((struct elf32_hppa_stub_hash_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+#define elf32_hppa_stub_hash_traverse(table, func, info) \
+ (bfd_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* For linker args hash tables. */
+#define elf32_hppa_args_hash_lookup(table, string, create, copy) \
+ ((struct elf32_hppa_args_hash_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+#define elf32_hppa_args_hash_traverse(table, func, info) \
+ (bfd_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func), \
+ (info)))
+
+#define elf32_hppa_args_hash_table_init(table, newfunc) \
+ (bfd_hash_table_init \
+ (&(table)->root, \
+ (struct bfd_hash_entry *(*) PARAMS ((struct bfd_hash_entry *, \
+ struct bfd_hash_table *, \
+ const char *))) (newfunc)))
+
+/* For HPPA linker hash table. */
+
+#define elf32_hppa_link_hash_lookup(table, string, create, copy, follow)\
+ ((struct elf32_hppa_link_hash_entry *) \
+ elf_link_hash_lookup (&(table)->root, (string), (create), \
+ (copy), (follow)))
+
+#define elf32_hppa_link_hash_traverse(table, func, info) \
+ (elf_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the PA ELF linker hash table from a link_info structure. */
+
+#define elf32_hppa_hash_table(p) \
+ ((struct elf32_hppa_link_hash_table *) ((p)->hash))
+
+
+/* Extract specific argument location bits for WHICH from
+ the full argument location in AR. */
+#define EXTRACT_ARBITS(ar, which) ((ar) >> (8 - ((which) * 2))) & 3
+
+/* Assorted hash table functions. */
+
+/* Initialize an entry in the stub hash table. */
+
+static struct bfd_hash_entry *
+elf32_hppa_stub_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct elf32_hppa_stub_hash_entry *ret;
+
+ ret = (struct elf32_hppa_stub_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == NULL)
+ ret = ((struct elf32_hppa_stub_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct elf32_hppa_stub_hash_entry)));
+ if (ret == NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct elf32_hppa_stub_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ ret->offset = 0;
+ ret->target_value = 0;
+ ret->target_section = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize a stub hash table. */
+
+static boolean
+elf32_hppa_stub_hash_table_init (table, stub_bfd, newfunc)
+ struct elf32_hppa_stub_hash_table *table;
+ bfd *stub_bfd;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+{
+ table->offset = 0;
+ table->location = 0;
+ table->stub_bfd = stub_bfd;
+ return (bfd_hash_table_init (&table->root, newfunc));
+}
+
+/* Initialize an entry in the argument location hash table. */
+
+static struct bfd_hash_entry *
+elf32_hppa_args_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct elf32_hppa_args_hash_entry *ret;
+
+ ret = (struct elf32_hppa_args_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == NULL)
+ ret = ((struct elf32_hppa_args_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct elf32_hppa_args_hash_entry)));
+ if (ret == NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct elf32_hppa_args_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ /* Initialize the local fields. */
+ if (ret)
+ ret->arg_bits = 0;
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create the derived linker hash table. The PA ELF port uses the derived
+ hash table to keep information specific to the PA ELF linker (without
+ using static variables). */
+
+static struct bfd_link_hash_table *
+elf32_hppa_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct elf32_hppa_link_hash_table *ret;
+
+ ret = ((struct elf32_hppa_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct elf32_hppa_link_hash_table)));
+ if (ret == NULL)
+ return NULL;
+ if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
+ _bfd_elf_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return NULL;
+ }
+ ret->stub_hash_table = NULL;
+ ret->args_hash_table = NULL;
+ ret->output_symbol_count = 0;
+ ret->global_value = 0;
+ ret->global_sym_defined = 0;
+
+ return &ret->root.root;
+}
+
+/* Relocate the given INSN given the various input parameters.
+
+ FIXME: endianness and sizeof (long) issues abound here. */
+
+static unsigned long
+hppa_elf_relocate_insn (abfd, input_sect, insn, address, sym_value,
+ r_addend, r_format, r_field, pcrel)
+ bfd *abfd;
+ asection *input_sect;
+ unsigned long insn;
+ unsigned long address;
+ long sym_value;
+ long r_addend;
+ unsigned long r_format;
+ unsigned long r_field;
+ unsigned long pcrel;
+{
+ unsigned char opcode = get_opcode (insn);
+ long constant_value;
+
+ switch (opcode)
+ {
+ case LDO:
+ case LDB:
+ case LDH:
+ case LDW:
+ case LDWM:
+ case STB:
+ case STH:
+ case STW:
+ case STWM:
+ case COMICLR:
+ case SUBI:
+ case ADDIT:
+ case ADDI:
+ case LDIL:
+ case ADDIL:
+ constant_value = HPPA_R_CONSTANT (r_addend);
+
+ if (pcrel)
+ sym_value -= address;
+
+ sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
+ return hppa_rebuild_insn (abfd, insn, sym_value, r_format);
+
+ case BL:
+ case BE:
+ case BLE:
+ /* XXX computing constant_value is not needed??? */
+ constant_value = assemble_17 ((insn & 0x001f0000) >> 16,
+ (insn & 0x00001ffc) >> 2,
+ insn & 1);
+
+ constant_value = (constant_value << 15) >> 15;
+ if (pcrel)
+ {
+ sym_value -=
+ address + input_sect->output_offset
+ + input_sect->output_section->vma;
+ sym_value = hppa_field_adjust (sym_value, -8, r_field);
+ }
+ else
+ sym_value = hppa_field_adjust (sym_value, constant_value, r_field);
+
+ return hppa_rebuild_insn (abfd, insn, sym_value >> 2, r_format);
+
+ default:
+ if (opcode == 0)
+ {
+ constant_value = HPPA_R_CONSTANT (r_addend);
+
+ if (pcrel)
+ sym_value -= address;
+
+ return hppa_field_adjust (sym_value, constant_value, r_field);
+ }
+ else
+ abort ();
+ }
+}
+
+/* Relocate an HPPA ELF section. */
+
+static boolean
+elf32_hppa_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ 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;
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+
+ rel = relocs;
+ relend = relocs + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ int r_type;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sym_sec;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+ const char *sym_name;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ howto = elf_hppa_howto_table + r_type;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (info->relocateable)
+ {
+ /* This is a relocateable link. We don't have to change
+ anything, unless the reloc is against a section symbol,
+ in which case we have to adjust according to where the
+ section symbol winds up in the output section. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ {
+ sym_sec = local_sections[r_symndx];
+ rel->r_addend += sym_sec->output_offset;
+ }
+ }
+
+ continue;
+ }
+
+ /* This is a final link. */
+ h = NULL;
+ sym = NULL;
+ sym_sec = NULL;
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sym_sec = local_sections[r_symndx];
+ relocation = ((ELF_ST_TYPE (sym->st_info) == STT_SECTION
+ ? 0 : sym->st_value)
+ + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+ }
+ else
+ {
+ long indx;
+
+ indx = r_symndx - symtab_hdr->sh_info;
+ h = elf_sym_hashes (input_bfd)[indx];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sym_sec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else
+ {
+ if (!((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ break;
+ }
+ }
+
+ if (h != NULL)
+ sym_name = h->root.root.string;
+ else
+ {
+ sym_name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (sym_name == NULL)
+ return false;
+ if (*sym_name == '\0')
+ sym_name = bfd_section_name (input_bfd, sym_sec);
+ }
+
+ /* If args_hash_table is NULL, then we have encountered some
+ kind of link error (ex. undefined symbols). Do not try to
+ apply any relocations, continue the loop so we can notify
+ the user of several errors in a single attempted link. */
+ if (elf32_hppa_hash_table (info)->args_hash_table == NULL)
+ continue;
+
+ r = elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
+ input_section, contents,
+ rel->r_offset, relocation,
+ rel->r_addend, info, sym_sec,
+ sym_name, h == NULL);
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ /* This can happen for DP relative relocs if $global$ is
+ undefined. This is a panic situation so we don't try
+ to continue. */
+ case bfd_reloc_undefined:
+ case bfd_reloc_notsupported:
+ if (!((*info->callbacks->undefined_symbol)
+ (info, "$global$", input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ return false;
+ case bfd_reloc_dangerous:
+ {
+ /* We use this return value to indicate that we performed
+ a "dangerous" relocation. This doesn't mean we did
+ the wrong thing, it just means there may be some cleanup
+ that needs to be done here.
+
+ In particular we had to swap the last call insn and its
+ delay slot. If the delay slot insn needed a relocation,
+ then we'll need to adjust the next relocation entry's
+ offset to account for the fact that the insn moved.
+
+ This hair wouldn't be necessary if we inserted stubs
+ between procedures and used a "bl" to get to the stub. */
+ if (rel != relend)
+ {
+ Elf_Internal_Rela *next_rel = rel + 1;
+
+ if (rel->r_offset + 4 == next_rel->r_offset)
+ next_rel->r_offset -= 4;
+ }
+ break;
+ }
+ default:
+ case bfd_reloc_outofrange:
+ case bfd_reloc_overflow:
+ {
+ if (!((*info->callbacks->reloc_overflow)
+ (info, sym_name, howto->name, (bfd_vma) 0,
+ input_bfd, input_section, rel->r_offset)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Return one (or more) BFD relocations which implement the base
+ relocation with modifications based on format and field. */
+
+elf32_hppa_reloc_type **
+hppa_elf_gen_reloc_type (abfd, base_type, format, field, ignore)
+ bfd *abfd;
+ elf32_hppa_reloc_type base_type;
+ int format;
+ int field;
+ int ignore;
+{
+ elf32_hppa_reloc_type *finaltype;
+ elf32_hppa_reloc_type **final_types;
+
+ /* Allocate slots for the BFD relocation. */
+ final_types = (elf32_hppa_reloc_type **)
+ bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type *) * 2);
+ if (final_types == NULL)
+ return NULL;
+
+ /* Allocate space for the relocation itself. */
+ finaltype = (elf32_hppa_reloc_type *)
+ bfd_alloc_by_size_t (abfd, sizeof (elf32_hppa_reloc_type));
+ if (finaltype == NULL)
+ return NULL;
+
+ /* Some reasonable defaults. */
+ final_types[0] = finaltype;
+ final_types[1] = NULL;
+
+#define final_type finaltype[0]
+
+ final_type = base_type;
+
+ /* Just a tangle of nested switch statements to deal with the braindamage
+ that a different field selector means a completely different relocation
+ for PA ELF. */
+ switch (base_type)
+ {
+ case R_HPPA:
+ case R_HPPA_ABS_CALL:
+ switch (format)
+ {
+ case 14:
+ switch (field)
+ {
+ case e_rsel:
+ case e_rrsel:
+ final_type = R_PARISC_DIR14R;
+ break;
+ case e_rtsel:
+ final_type = R_PARISC_DLTREL14R;
+ break;
+ case e_tsel:
+ final_type = R_PARISC_DLTREL14F;
+ break;
+ case e_rpsel:
+ final_type = R_PARISC_PLABEL14R;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case 17:
+ switch (field)
+ {
+ case e_fsel:
+ final_type = R_PARISC_DIR17F;
+ break;
+ case e_rsel:
+ case e_rrsel:
+ final_type = R_PARISC_DIR17R;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case 21:
+ switch (field)
+ {
+ case e_lsel:
+ case e_lrsel:
+ final_type = R_PARISC_DIR21L;
+ break;
+ case e_ltsel:
+ final_type = R_PARISC_DLTREL21L;
+ break;
+ case e_lpsel:
+ final_type = R_PARISC_PLABEL21L;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case 32:
+ switch (field)
+ {
+ case e_fsel:
+ final_type = R_PARISC_DIR32;
+ break;
+ case e_psel:
+ final_type = R_PARISC_PLABEL32;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+ break;
+
+
+ case R_HPPA_GOTOFF:
+ switch (format)
+ {
+ case 14:
+ switch (field)
+ {
+ case e_rsel:
+ case e_rrsel:
+ final_type = R_PARISC_DPREL14R;
+ break;
+ case e_fsel:
+ final_type = R_PARISC_DPREL14F;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case 21:
+ switch (field)
+ {
+ case e_lrsel:
+ case e_lsel:
+ final_type = R_PARISC_DPREL21L;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+ break;
+
+
+ case R_HPPA_PCREL_CALL:
+ switch (format)
+ {
+ case 14:
+ switch (field)
+ {
+ case e_rsel:
+ case e_rrsel:
+ final_type = R_PARISC_PCREL14R;
+ break;
+ case e_fsel:
+ final_type = R_PARISC_PCREL14F;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case 17:
+ switch (field)
+ {
+ case e_rsel:
+ case e_rrsel:
+ final_type = R_PARISC_PCREL17R;
+ break;
+ case e_fsel:
+ final_type = R_PARISC_PCREL17F;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case 21:
+ switch (field)
+ {
+ case e_lsel:
+ case e_lrsel:
+ final_type = R_PARISC_PCREL21L;
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+ break;
+
+ default:
+ return NULL;
+ }
+
+ return final_types;
+}
+
+#undef final_type
+
+/* Set the contents of a particular section at a particular location. */
+
+static boolean
+elf32_hppa_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ /* Ignore write requests for the symbol extension section until we've
+ had the chance to rebuild it ourselves. */
+ if (!strcmp (section->name, ".PARISC.symextn") && !symext_chain_size)
+ return true;
+ else
+ return _bfd_elf_set_section_contents (abfd, section, location,
+ offset, count);
+}
+
+/* Translate from an elf into field into a howto relocation pointer. */
+
+static void
+elf_info_to_howto (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf32_Internal_Rela *dst;
+{
+ BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_PARISC_UNIMPLEMENTED);
+ cache_ptr->howto = &elf_hppa_howto_table[ELF32_R_TYPE (dst->r_info)];
+}
+
+
+/* Actually perform a relocation. NOTE this is (mostly) superceeded
+ by elf32_hppa_bfd_final_link_relocate which is called by the new
+ fast linker. */
+
+static bfd_reloc_status_type
+hppa_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol_in;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* It is no longer valid to call hppa_elf_reloc when creating
+ a final executable. */
+ if (output_bfd)
+ {
+ reloc_entry->address += input_section->output_offset;
+
+ /* Work around lossage in generic elf code to write relocations.
+ (maps different section symbols into the same symbol index). */
+ if ((symbol_in->flags & BSF_SECTION_SYM)
+ && symbol_in->section)
+ reloc_entry->addend += symbol_in->section->output_offset;
+ return bfd_reloc_ok;
+ }
+ else
+ {
+ *error_message = (char *) "Unsupported call to hppa_elf_reloc";
+ return bfd_reloc_notsupported;
+ }
+}
+
+/* Actually perform a relocation as part of a final link. This can get
+ rather hairy when linker stubs are needed. */
+
+static bfd_reloc_status_type
+elf32_hppa_bfd_final_link_relocate (howto, input_bfd, output_bfd,
+ input_section, contents, offset, value,
+ addend, info, sym_sec, sym_name, is_local)
+ reloc_howto_type *howto;
+ bfd *input_bfd;
+ bfd *output_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ bfd_vma offset;
+ bfd_vma value;
+ bfd_vma addend;
+ struct bfd_link_info *info;
+ asection *sym_sec;
+ const char *sym_name;
+ int is_local;
+{
+ unsigned long insn;
+ unsigned long r_type = howto->type;
+ unsigned long r_format = howto->bitsize;
+ unsigned long r_field = e_fsel;
+ bfd_byte *hit_data = contents + offset;
+ boolean r_pcrel = howto->pc_relative;
+
+ insn = bfd_get_32 (input_bfd, hit_data);
+
+ /* Make sure we have a value for $global$. FIXME isn't this effectively
+ just like the gp pointer on MIPS? Can we use those routines for this
+ purpose? */
+ if (!elf32_hppa_hash_table (info)->global_sym_defined)
+ {
+ struct elf_link_hash_entry *h;
+ asection *sec;
+
+ h = elf_link_hash_lookup (elf_hash_table (info), "$global$", false,
+ false, false);
+
+ /* If there isn't a $global$, then we're in deep trouble. */
+ if (h == NULL)
+ return bfd_reloc_notsupported;
+
+ /* If $global$ isn't a defined symbol, then we're still in deep
+ trouble. */
+ if (h->root.type != bfd_link_hash_defined)
+ return bfd_reloc_undefined;
+
+ sec = h->root.u.def.section;
+ elf32_hppa_hash_table (info)->global_value = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ elf32_hppa_hash_table (info)->global_sym_defined = 1;
+ }
+
+ switch (r_type)
+ {
+ case R_PARISC_NONE:
+ break;
+
+ case R_PARISC_DIR32:
+ case R_PARISC_DIR17F:
+ case R_PARISC_PCREL17C:
+ r_field = e_fsel;
+ goto do_basic_type_1;
+ case R_PARISC_DIR21L:
+ case R_PARISC_PCREL21L:
+ r_field = e_lrsel;
+ goto do_basic_type_1;
+ case R_PARISC_DIR17R:
+ case R_PARISC_PCREL17R:
+ case R_PARISC_DIR14R:
+ case R_PARISC_PCREL14R:
+ r_field = e_rrsel;
+ goto do_basic_type_1;
+
+ /* For all the DP relative relocations, we need to examine the symbol's
+ section. If it's a code section, then "data pointer relative" makes
+ no sense. In that case we don't adjust the "value", and for 21 bit
+ addil instructions, we change the source addend register from %dp to
+ %r0. */
+ case R_PARISC_DPREL21L:
+ r_field = e_lrsel;
+ if (sym_sec->flags & SEC_CODE)
+ {
+ if ((insn & 0xfc000000) >> 26 == 0xa
+ && (insn & 0x03e00000) >> 21 == 0x1b)
+ insn &= ~0x03e00000;
+ }
+ else
+ value -= elf32_hppa_hash_table (info)->global_value;
+ goto do_basic_type_1;
+ case R_PARISC_DPREL14R:
+ r_field = e_rrsel;
+ if ((sym_sec->flags & SEC_CODE) == 0)
+ value -= elf32_hppa_hash_table (info)->global_value;
+ goto do_basic_type_1;
+ case R_PARISC_DPREL14F:
+ r_field = e_fsel;
+ if ((sym_sec->flags & SEC_CODE) == 0)
+ value -= elf32_hppa_hash_table (info)->global_value;
+ goto do_basic_type_1;
+
+ /* These cases are separate as they may involve a lot more work
+ to deal with linker stubs. */
+ case R_PARISC_PLABEL32:
+ case R_PARISC_PLABEL21L:
+ case R_PARISC_PLABEL14R:
+ case R_PARISC_PCREL17F:
+ {
+ bfd_vma location;
+ unsigned int len, caller_args, callee_args;
+ arg_reloc_type arg_reloc_types[5];
+ struct elf32_hppa_args_hash_table *args_hash_table;
+ struct elf32_hppa_args_hash_entry *args_hash;
+ char *new_name, *stub_name;
+
+ /* Get the field selector right. We'll need it in a minute. */
+ if (r_type == R_PARISC_PCREL17F
+ || r_type == R_PARISC_PLABEL32)
+ r_field = e_fsel;
+ else if (r_type == R_PARISC_PLABEL21L)
+ r_field = e_lrsel;
+ else if (r_type == R_PARISC_PLABEL14R)
+ r_field = e_rrsel;
+
+ /* Find out where we are and where we're going. */
+ location = (offset +
+ input_section->output_offset +
+ input_section->output_section->vma);
+
+ /* Now look for the argument relocation bits associated with the
+ target. */
+ len = strlen (sym_name) + 1;
+ if (is_local)
+ len += 9;
+ new_name = bfd_malloc (len);
+ if (!new_name)
+ return bfd_reloc_notsupported;
+ strcpy (new_name, sym_name);
+
+ /* Local symbols have unique IDs. */
+ if (is_local)
+ sprintf (new_name + len - 10, "_%08x", (int)sym_sec);
+
+ args_hash_table = elf32_hppa_hash_table (info)->args_hash_table;
+
+ args_hash = elf32_hppa_args_hash_lookup (args_hash_table,
+ new_name, false, false);
+ if (args_hash == NULL)
+ callee_args = 0;
+ else
+ callee_args = args_hash->arg_bits;
+
+ /* If this is a CALL relocation, then get the caller's bits
+ from the addend. Else use the magic 0x155 value for PLABELS.
+
+ Also we don't care about the destination (value) for PLABELS. */
+ if (r_type == R_PARISC_PCREL17F)
+ caller_args = HPPA_R_ARG_RELOC (addend);
+ else
+ {
+ caller_args = 0x155;
+ location = value;
+ }
+
+ /* Any kind of linker stub needed? */
+ if (((int)(value - location) > 0x3ffff)
+ || ((int)(value - location) < (int)0xfffc0000)
+ || elf32_hppa_arg_reloc_needed (caller_args, callee_args,
+ arg_reloc_types))
+ {
+ struct elf32_hppa_stub_hash_table *stub_hash_table;
+ struct elf32_hppa_stub_hash_entry *stub_hash;
+ asection *stub_section;
+
+ /* Build a name for the stub. */
+
+ len = strlen (new_name);
+ len += 23;
+ stub_name = bfd_malloc (len);
+ if (!stub_name)
+ return bfd_reloc_notsupported;
+ elf32_hppa_name_of_stub (caller_args, callee_args,
+ location, value, stub_name);
+ strcat (stub_name, new_name);
+ free (new_name);
+
+ stub_hash_table = elf32_hppa_hash_table (info)->stub_hash_table;
+
+ stub_hash
+ = elf32_hppa_stub_hash_lookup (stub_hash_table, stub_name,
+ false, false);
+
+ /* We're done with that name. */
+ free (stub_name);
+
+ /* The stub BFD only has one section. */
+ stub_section = stub_hash_table->stub_bfd->sections;
+
+ if (stub_hash != NULL)
+ {
+
+ if (r_type == R_PARISC_PCREL17F)
+ {
+ unsigned long delay_insn;
+ unsigned int opcode, rtn_reg, ldo_target_reg, ldo_src_reg;
+
+ /* We'll need to peek at the next insn. */
+ delay_insn = bfd_get_32 (input_bfd, hit_data + 4);
+ opcode = get_opcode (delay_insn);
+
+ /* We also need to know the return register for this
+ call. */
+ rtn_reg = (insn & 0x03e00000) >> 21;
+
+ ldo_src_reg = (delay_insn & 0x03e00000) >> 21;
+ ldo_target_reg = (delay_insn & 0x001f0000) >> 16;
+
+ /* Munge up the value and other parameters for
+ hppa_elf_relocate_insn. */
+
+ value = (stub_hash->offset
+ + stub_section->output_offset
+ + stub_section->output_section->vma);
+
+ r_format = 17;
+ r_field = e_fsel;
+ r_pcrel = 0;
+ addend = 0;
+
+ /* We need to peek at the delay insn and determine if
+ we'll need to swap the branch and its delay insn. */
+ if ((insn & 2)
+ || (opcode == LDO
+ && ldo_target_reg == rtn_reg)
+ || (delay_insn == 0x08000240))
+ {
+ /* No need to swap the branch and its delay slot, but
+ we do need to make sure to jump past the return
+ pointer update in the stub. */
+ value += 4;
+
+ /* If the delay insn does a return pointer adjustment,
+ then we have to make sure it stays valid. */
+ if (opcode == LDO
+ && ldo_target_reg == rtn_reg)
+ {
+ delay_insn &= 0xfc00ffff;
+ delay_insn |= ((31 << 21) | (31 << 16));
+ bfd_put_32 (input_bfd, delay_insn, hit_data + 4);
+ }
+ /* Use a BLE to reach the stub. */
+ insn = BLE_SR4_R0;
+ }
+ else
+ {
+ /* Wonderful, we have to swap the call insn and its
+ delay slot. */
+ bfd_put_32 (input_bfd, delay_insn, hit_data);
+ /* Use a BLE,n to reach the stub. */
+ insn = (BLE_SR4_R0 | 0x2);
+ bfd_put_32 (input_bfd, insn, hit_data + 4);
+ insn = hppa_elf_relocate_insn (input_bfd,
+ input_section,
+ insn, offset + 4,
+ value, addend,
+ r_format, r_field,
+ r_pcrel);
+ /* Update the instruction word. */
+ bfd_put_32 (input_bfd, insn, hit_data + 4);
+ return bfd_reloc_dangerous;
+ }
+ }
+ else
+ {
+ /* PLABEL stuff is easy. */
+
+ value = (stub_hash->offset
+ + stub_section->output_offset
+ + stub_section->output_section->vma);
+ /* We don't need the RP adjustment for PLABELs. */
+ value += 4;
+ if (r_type == R_PARISC_PLABEL32)
+ r_format = 32;
+ else if (r_type == R_PARISC_PLABEL21L)
+ r_format = 21;
+ else if (r_type == R_PARISC_PLABEL14R)
+ r_format = 14;
+
+ r_pcrel = 0;
+ addend = 0;
+ }
+ }
+ else
+ return bfd_reloc_notsupported;
+ }
+ goto do_basic_type_1;
+ }
+
+do_basic_type_1:
+ insn = hppa_elf_relocate_insn (input_bfd, input_section, insn,
+ offset, value, addend, r_format,
+ r_field, r_pcrel);
+ break;
+
+ /* Something we don't know how to handle. */
+ default:
+ return bfd_reloc_notsupported;
+ }
+
+ /* Update the instruction word. */
+ bfd_put_32 (input_bfd, insn, hit_data);
+ return (bfd_reloc_ok);
+}
+
+/* Return the address of the howto table entry to perform the CODE
+ relocation for an ARCH machine. */
+
+static reloc_howto_type *
+elf_hppa_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ if ((int) code < (int) R_PARISC_UNIMPLEMENTED)
+ {
+ BFD_ASSERT ((int) elf_hppa_howto_table[(int) code].type == (int) code);
+ return &elf_hppa_howto_table[(int) code];
+ }
+ return NULL;
+}
+
+/* Return true if SYM represents a local label symbol. */
+
+static boolean
+hppa_elf_is_local_label (abfd, sym)
+ bfd *abfd;
+ asymbol *sym;
+{
+ return (sym->name[0] == 'L' && sym->name[1] == '$');
+}
+
+/* Do any backend specific processing when beginning to write an object
+ file. For PA ELF we need to determine the size of the symbol extension
+ section *before* any other output processing happens. */
+
+static void
+elf32_hppa_backend_begin_write_processing (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ unsigned int i;
+ asection *symextn_sec;
+
+ /* Size up the symbol extension section. */
+ if ((abfd->outsymbols == NULL
+ && info == NULL)
+ || symext_chain_size != 0)
+ return;
+
+ if (info == NULL)
+ {
+ /* We were not called from the BFD ELF linker code, so we need
+ to examine the output BFD's outsymbols.
+
+ Note we can not build the symbol extensions now as the symbol
+ map hasn't been set up. */
+ for (i = 0; i < abfd->symcount; i++)
+ {
+ elf_symbol_type *symbol = (elf_symbol_type *)abfd->outsymbols[i];
+
+ /* Only functions ever need an entry in the symbol extension
+ section. */
+ if (!(symbol->symbol.flags & BSF_FUNCTION))
+ continue;
+
+ /* And only if they specify the locations of their arguments. */
+ if (symbol->tc_data.hppa_arg_reloc == 0)
+ continue;
+
+ /* Yup. This function symbol needs an entry. */
+ symext_chain_size += 2 * ELF32_PARISC_SX_SIZE;
+ }
+ }
+ else if (info->relocateable == true)
+ {
+ struct elf32_hppa_args_hash_table *table;
+ table = elf32_hppa_hash_table (info)->args_hash_table;
+
+ /* Determine the size of the symbol extension section. */
+ elf32_hppa_args_hash_traverse (table,
+ elf32_hppa_size_symext,
+ &symext_chain_size);
+ }
+
+ /* Now create the section and set its size. We'll fill in the
+ contents later. */
+ symextn_sec = bfd_get_section_by_name (abfd, SYMEXTN_SECTION_NAME);
+ if (symextn_sec == NULL)
+ symextn_sec = bfd_make_section (abfd, SYMEXTN_SECTION_NAME);
+
+ bfd_set_section_flags (abfd, symextn_sec,
+ SEC_LOAD | SEC_HAS_CONTENTS | SEC_DATA);
+ symextn_sec->output_section = symextn_sec;
+ symextn_sec->output_offset = 0;
+ bfd_set_section_alignment (abfd, symextn_sec, 2);
+ bfd_set_section_size (abfd, symextn_sec, symext_chain_size);
+}
+
+/* Called for each entry in the args location hash table. For each
+ entry we bump the size pointer by 2 records (16 bytes). */
+
+static boolean
+elf32_hppa_size_symext (gen_entry, in_args)
+ struct bfd_hash_entry *gen_entry;
+ PTR in_args;
+{
+ bfd_size_type *sizep = (bfd_size_type *)in_args;
+
+ *sizep += 2 * ELF32_PARISC_SX_SIZE;
+ return true;
+}
+
+/* Backend routine called by the linker for each output symbol.
+
+ For PA ELF we use this opportunity to add an appropriate entry
+ to the symbol extension chain for function symbols. */
+
+static boolean
+elf32_hppa_link_output_symbol_hook (abfd, info, name, sym, section)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ const char *name;
+ Elf_Internal_Sym *sym;
+ asection *section;
+{
+ char *new_name;
+ unsigned int len, index;
+ struct elf32_hppa_args_hash_table *args_hash_table;
+ struct elf32_hppa_args_hash_entry *args_hash;
+
+ /* If the args hash table is NULL, then we've encountered an error
+ of some sorts (for example, an undefined symbol). In that case
+ we've got nothing else to do.
+
+ NOTE: elf_link_output_symbol will abort if we return false here! */
+ if (elf32_hppa_hash_table (info)->args_hash_table == NULL)
+ return true;
+
+ index = elf32_hppa_hash_table (info)->output_symbol_count++;
+
+ /* We need to look up this symbol in the args hash table to see if
+ it has argument relocation bits. */
+ if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+ return true;
+
+ /* We know it's a function symbol of some kind. */
+ len = strlen (name) + 1;
+ if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
+ len += 9;
+
+ new_name = bfd_malloc (len);
+ if (new_name == NULL)
+ return false;
+
+ strcpy (new_name, name);
+ if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
+ sprintf (new_name + len - 10, "_%08x", (int)section);
+
+ /* Now that we have the unique name, we can look it up in the
+ args hash table. */
+ args_hash_table = elf32_hppa_hash_table (info)->args_hash_table;
+ args_hash = elf32_hppa_args_hash_lookup (args_hash_table, new_name,
+ false, false);
+ free (new_name);
+ if (args_hash == NULL)
+ return true;
+
+ /* We know this symbol has arg reloc bits. */
+ add_entry_to_symext_chain (abfd, args_hash->arg_bits,
+ index, &symext_rootP, &symext_lastP);
+ return true;
+}
+
+/* Perform any processing needed late in the object file writing process.
+ For PA ELF we build and set the contents of the symbol extension
+ section. */
+
+static void
+elf32_hppa_backend_final_write_processing (abfd, linker)
+ bfd *abfd;
+ boolean linker;
+{
+ asection *symextn_sec;
+ unsigned int i;
+
+ /* Now build the symbol extension section. */
+ if (symext_chain_size == 0)
+ return;
+
+ if (! linker)
+ {
+ /* We were not called from the backend linker, so we still need
+ to build the symbol extension chain.
+
+ Look at each symbol, adding the appropriate information to the
+ symbol extension section list as necessary. */
+ for (i = 0; i < abfd->symcount; i++)
+ {
+ elf_symbol_type *symbol = (elf_symbol_type *) abfd->outsymbols[i];
+
+ /* Only functions ever need an entry in the symbol extension
+ section. */
+ if (!(symbol->symbol.flags & BSF_FUNCTION))
+ continue;
+
+ /* And only if they specify the locations of their arguments. */
+ if (symbol->tc_data.hppa_arg_reloc == 0)
+ continue;
+
+ /* Add this symbol's information to the chain. */
+ add_entry_to_symext_chain (abfd, symbol->tc_data.hppa_arg_reloc,
+ symbol->symbol.udata.i, &symext_rootP,
+ &symext_lastP);
+ }
+ }
+
+ /* Now fill in the contents of the symbol extension section. */
+ elf_hppa_tc_make_sections (abfd, symext_rootP);
+
+ /* And attach that as the section's contents. */
+ symextn_sec = bfd_get_section_by_name (abfd, SYMEXTN_SECTION_NAME);
+ if (symextn_sec == (asection *) 0)
+ abort();
+
+ symextn_sec->contents = (void *)symextn_contents;
+
+ bfd_set_section_contents (abfd, symextn_sec, symextn_sec->contents,
+ symextn_sec->output_offset, symextn_sec->_raw_size);
+}
+
+/* Update the symbol extention chain to include the symbol pointed to
+ by SYMBOLP if SYMBOLP is a function symbol. Used internally and by GAS. */
+
+static void
+add_entry_to_symext_chain (abfd, arg_reloc, sym_idx, symext_root, symext_last)
+ bfd *abfd;
+ unsigned int arg_reloc;
+ unsigned int sym_idx;
+ symext_chainS **symext_root;
+ symext_chainS **symext_last;
+{
+ symext_chainS *symextP;
+
+ /* Allocate memory and initialize this entry. */
+ symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2);
+ if (!symextP)
+ abort(); /* FIXME */
+
+ symextP[0].entry = ELF32_PARISC_SX_WORD (PARISC_SXT_SYMNDX, sym_idx);
+ symextP[0].next = &symextP[1];
+
+ symextP[1].entry = ELF32_PARISC_SX_WORD (PARISC_SXT_ARG_RELOC, arg_reloc);
+ symextP[1].next = NULL;
+
+ /* Now update the chain itself so it can be walked later to build
+ the symbol extension section. */
+ if (*symext_root == NULL)
+ {
+ *symext_root = &symextP[0];
+ *symext_last = &symextP[1];
+ }
+ else
+ {
+ (*symext_last)->next = &symextP[0];
+ *symext_last = &symextP[1];
+ }
+}
+
+/* Build the symbol extension section. */
+
+static void
+elf_hppa_tc_make_sections (abfd, symext_root)
+ bfd *abfd;
+ symext_chainS *symext_root;
+{
+ symext_chainS *symextP;
+ unsigned int i;
+ asection *symextn_sec;
+
+ symextn_sec = bfd_get_section_by_name (abfd, SYMEXTN_SECTION_NAME);
+
+ /* Grab some memory for the contents of the symbol extension section
+ itself. */
+ symextn_contents = (bfd_byte *) bfd_zalloc (abfd,
+ symextn_sec->_raw_size);
+ if (!symextn_contents)
+ abort(); /* FIXME */
+
+ /* Fill in the contents of the symbol extension chain. */
+ for (i = 0, symextP = symext_root; symextP; symextP = symextP->next, ++i)
+ ELF32_PARISC_SX_PUT (abfd, (bfd_vma) symextP->entry,
+ symextn_contents + i * ELF32_PARISC_SX_SIZE);
+
+ return;
+}
+
+/* Do some PA ELF specific work after reading in the symbol table.
+ In particular attach the argument relocation from the
+ symbol extension section to the appropriate symbols. */
+
+static boolean
+elf32_hppa_backend_symbol_table_processing (abfd, esyms,symcnt)
+ bfd *abfd;
+ elf_symbol_type *esyms;
+ unsigned int symcnt;
+{
+ Elf32_Internal_Shdr *symextn_hdr =
+ bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME);
+ unsigned int i, current_sym_idx = 0;
+
+ /* If no symbol extension existed, then all symbol extension information
+ is assumed to be zero. */
+ if (symextn_hdr == NULL)
+ {
+ for (i = 0; i < symcnt; i++)
+ esyms[i].tc_data.hppa_arg_reloc = 0;
+ return (true);
+ }
+
+ /* FIXME: Why not use bfd_get_section_contents here? Also should give
+ memory back when we're done. */
+ /* Allocate a buffer of the appropriate size for the symextn section. */
+ symextn_hdr->contents = bfd_zalloc(abfd,symextn_hdr->sh_size);
+ if (!symextn_hdr->contents)
+ return false;
+
+ /* Read in the symextn section. */
+ if (bfd_seek (abfd, symextn_hdr->sh_offset, SEEK_SET) == -1)
+ return false;
+ if (bfd_read ((PTR) symextn_hdr->contents, 1, symextn_hdr->sh_size, abfd)
+ != symextn_hdr->sh_size)
+ return false;
+
+ /* Parse entries in the symbol extension section, updating the symtab
+ entries as we go */
+ for (i = 0; i < symextn_hdr->sh_size / ELF32_PARISC_SX_SIZE; i++)
+ {
+ symext_entryS se =
+ ELF32_PARISC_SX_GET (abfd,
+ ((unsigned char *)symextn_hdr->contents
+ + i * ELF32_PARISC_SX_SIZE));
+ unsigned int se_value = ELF32_PARISC_SX_VAL (se);
+ unsigned int se_type = ELF32_PARISC_SX_TYPE (se);
+
+ switch (se_type)
+ {
+ case PARISC_SXT_NULL:
+ break;
+
+ case PARISC_SXT_SYMNDX:
+ if (se_value >= symcnt)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return (false);
+ }
+ current_sym_idx = se_value - 1;
+ break;
+
+ case PARISC_SXT_ARG_RELOC:
+ esyms[current_sym_idx].tc_data.hppa_arg_reloc = se_value;
+ break;
+
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ return (false);
+ }
+ }
+ return (true);
+}
+
+/* Read and attach the symbol extension information for the symbols
+ in INPUT_BFD to the argument location hash table. Handle locals
+ if DO_LOCALS is true; likewise for globals when DO_GLOBALS is true. */
+
+static boolean
+elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table, local_syms)
+ bfd *input_bfd;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf32_hppa_args_hash_table *args_hash_table;
+ Elf_Internal_Sym *local_syms;
+{
+ asection *symextn_sec;
+ bfd_byte *contents;
+ unsigned int i, n_entries, current_index = 0;
+
+ /* Get the symbol extension section for this BFD. If no section exists
+ then there's nothing to do. Likewise if the section exists, but
+ has no contents. */
+ symextn_sec = bfd_get_section_by_name (input_bfd, SYMEXTN_SECTION_NAME);
+ if (symextn_sec == NULL)
+ return true;
+
+ /* Done separately so we can turn off SEC_HAS_CONTENTS (see below). */
+ if (symextn_sec->_raw_size == 0)
+ {
+ symextn_sec->flags &= ~SEC_HAS_CONTENTS;
+ return true;
+ }
+
+ contents = (bfd_byte *) bfd_malloc ((size_t) symextn_sec->_raw_size);
+ if (contents == NULL)
+ return false;
+
+ /* How gross. We turn off SEC_HAS_CONTENTS for the input symbol extension
+ sections to keep the generic ELF/BFD code from trying to do anything
+ with them. We have to undo that hack temporarily so that we can read
+ in the contents with the generic code. */
+ symextn_sec->flags |= SEC_HAS_CONTENTS;
+ if (bfd_get_section_contents (input_bfd, symextn_sec, contents,
+ 0, symextn_sec->_raw_size) == false)
+ {
+ symextn_sec->flags &= ~SEC_HAS_CONTENTS;
+ free (contents);
+ return false;
+ }
+
+ /* Gross. Turn off SEC_HAS_CONTENTS for the input symbol extension
+ sections (see above). */
+ symextn_sec->flags &= ~SEC_HAS_CONTENTS;
+
+ n_entries = symextn_sec->_raw_size / ELF32_PARISC_SX_SIZE;
+ for (i = 0; i < n_entries; i++)
+ {
+ symext_entryS entry =
+ ELF32_PARISC_SX_GET (input_bfd, contents + i * ELF32_PARISC_SX_SIZE);
+ unsigned int value = ELF32_PARISC_SX_VAL (entry);
+ unsigned int type = ELF32_PARISC_SX_TYPE (entry);
+ struct elf32_hppa_args_hash_entry *args_hash;
+
+ switch (type)
+ {
+ case PARISC_SXT_NULL:
+ break;
+
+ case PARISC_SXT_SYMNDX:
+ if (value >= symtab_hdr->sh_size / sizeof (Elf32_External_Sym))
+ {
+ bfd_set_error (bfd_error_bad_value);
+ free (contents);
+ return false;
+ }
+ current_index = value;
+ break;
+
+ case PARISC_SXT_ARG_RELOC:
+ if (current_index < symtab_hdr->sh_info)
+ {
+ Elf_Internal_Shdr *hdr;
+ char *new_name;
+ const char *sym_name;
+ asection *sym_sec;
+ unsigned int len;
+
+ hdr = elf_elfsections (input_bfd)[local_syms[current_index].st_shndx];
+ sym_sec = hdr->bfd_section;
+ sym_name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ local_syms[current_index].st_name);
+ len = strlen (sym_name) + 10;
+ new_name = bfd_malloc (len);
+ if (new_name == NULL)
+ {
+ free (contents);
+ return false;
+ }
+ strcpy (new_name, sym_name);
+ sprintf (new_name + len - 10, "_%08x", (int)sym_sec);
+
+ /* This is a global symbol with argument location info.
+ We need to enter it into the hash table. */
+ args_hash = elf32_hppa_args_hash_lookup (args_hash_table,
+ new_name, true,
+ true);
+ free (new_name);
+ if (args_hash == NULL)
+ {
+ free (contents);
+ return false;
+ }
+ args_hash->arg_bits = value;
+ break;
+ }
+ else if (current_index >= symtab_hdr->sh_info)
+ {
+ struct elf_link_hash_entry *h;
+
+ current_index -= symtab_hdr->sh_info;
+ h = elf_sym_hashes(input_bfd)[current_index];
+ /* This is a global symbol with argument location
+ information. We need to enter it into the hash table. */
+ args_hash = elf32_hppa_args_hash_lookup (args_hash_table,
+ h->root.root.string,
+ true, true);
+ if (args_hash == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ free (contents);
+ return false;
+ }
+ args_hash->arg_bits = value;
+ break;
+ }
+ else
+ break;
+
+ default:
+ bfd_set_error (bfd_error_bad_value);
+ free (contents);
+ return false;
+ }
+ }
+ free (contents);
+ return true;
+}
+
+/* Undo the generic ELF code's subtraction of section->vma from the
+ value of each external symbol. */
+
+static boolean
+elf32_hppa_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ const Elf_Internal_Sym *sym;
+ const char **namep;
+ flagword *flagsp;
+ asection **secp;
+ bfd_vma *valp;
+{
+ *valp += (*secp)->vma;
+ return true;
+}
+
+/* Determine the name of the stub needed to perform a call assuming the
+ argument relocation bits for caller and callee are in CALLER and CALLEE
+ for a call from LOCATION to DESTINATION. Copy the name into STUB_NAME. */
+
+static void
+elf32_hppa_name_of_stub (caller, callee, location, destination, stub_name)
+ unsigned int caller, callee;
+ bfd_vma location, destination;
+ char *stub_name;
+{
+ arg_reloc_type arg_reloc_types[5];
+
+ if (elf32_hppa_arg_reloc_needed (caller, callee, arg_reloc_types))
+ {
+ arg_reloc_location i;
+ /* Fill in the basic template. */
+ strcpy (stub_name, "__XX_XX_XX_XX_XX_stub_");
+
+ /* Now fix the specifics. */
+ for (i = ARG0; i <= RET; i++)
+ switch (arg_reloc_types[i])
+ {
+ case NO:
+ stub_name[3 * i + 2] = 'N';
+ stub_name[3 * i + 3] = 'O';
+ break;
+ case GF:
+ stub_name[3 * i + 2] = 'G';
+ stub_name[3 * i + 3] = 'F';
+ break;
+ case FG:
+ stub_name[3 * i + 2] = 'F';
+ stub_name[3 * i + 3] = 'G';
+ break;
+ case GD:
+ stub_name[3 * i + 2] = 'G';
+ stub_name[3 * i + 3] = 'D';
+ break;
+ case DG:
+ stub_name[3 * i + 2] = 'D';
+ stub_name[3 * i + 3] = 'G';
+ break;
+ }
+ }
+ else
+ strcpy (stub_name, "_____long_branch_stub_");
+}
+
+/* Determine if an argument relocation stub is needed to perform a
+ call assuming the argument relocation bits for caller and callee
+ are in CALLER and CALLEE. Place the type of relocations (if any)
+ into stub_types_p. */
+
+static boolean
+elf32_hppa_arg_reloc_needed (caller, callee, stub_types)
+ unsigned int caller, callee;
+ arg_reloc_type stub_types[5];
+{
+ /* Special case for no relocations. */
+ if (caller == 0 || callee == 0)
+ return 0;
+ else
+ {
+ arg_location caller_loc[5];
+ arg_location callee_loc[5];
+
+ /* Extract the location information for the argument and return
+ value on both the caller and callee sides. */
+ caller_loc[ARG0] = EXTRACT_ARBITS (caller, ARG0);
+ callee_loc[ARG0] = EXTRACT_ARBITS (callee, ARG0);
+ caller_loc[ARG1] = EXTRACT_ARBITS (caller, ARG1);
+ callee_loc[ARG1] = EXTRACT_ARBITS (callee, ARG1);
+ caller_loc[ARG2] = EXTRACT_ARBITS (caller, ARG2);
+ callee_loc[ARG2] = EXTRACT_ARBITS (callee, ARG2);
+ caller_loc[ARG3] = EXTRACT_ARBITS (caller, ARG3);
+ callee_loc[ARG3] = EXTRACT_ARBITS (callee, ARG3);
+ caller_loc[RET] = EXTRACT_ARBITS (caller, RET);
+ callee_loc[RET] = EXTRACT_ARBITS (callee, RET);
+
+ /* Check some special combinations. This is necessary to
+ deal with double precision FP arguments. */
+ if (caller_loc[ARG0] == AR_FU || caller_loc[ARG1] == AR_FU)
+ {
+ caller_loc[ARG0] = AR_FPDBL1;
+ caller_loc[ARG1] = AR_NO;
+ }
+ if (caller_loc[ARG2] == AR_FU || caller_loc[ARG3] == AR_FU)
+ {
+ caller_loc[ARG2] = AR_FPDBL2;
+ caller_loc[ARG3] = AR_NO;
+ }
+ if (callee_loc[ARG0] == AR_FU || callee_loc[ARG1] == AR_FU)
+ {
+ callee_loc[ARG0] = AR_FPDBL1;
+ callee_loc[ARG1] = AR_NO;
+ }
+ if (callee_loc[ARG2] == AR_FU || callee_loc[ARG3] == AR_FU)
+ {
+ callee_loc[ARG2] = AR_FPDBL2;
+ callee_loc[ARG3] = AR_NO;
+ }
+
+ /* Now look up any relocation needed for each argument and the
+ return value. */
+ stub_types[ARG0] = arg_mismatches[caller_loc[ARG0]][callee_loc[ARG0]];
+ stub_types[ARG1] = arg_mismatches[caller_loc[ARG1]][callee_loc[ARG1]];
+ stub_types[ARG2] = arg_mismatches[caller_loc[ARG2]][callee_loc[ARG2]];
+ stub_types[ARG3] = arg_mismatches[caller_loc[ARG3]][callee_loc[ARG3]];
+ stub_types[RET] = ret_mismatches[caller_loc[RET]][callee_loc[RET]];
+
+ return (stub_types[ARG0] != NO
+ || stub_types[ARG1] != NO
+ || stub_types[ARG2] != NO
+ || stub_types[ARG3] != NO
+ || stub_types[RET] != NO);
+ }
+}
+
+/* Compute the size of the stub needed to call from LOCATION to DESTINATION
+ (a function named SYM_NAME), with argument relocation bits CALLER and
+ CALLEE. Return zero if no stub is needed to perform such a call. */
+
+static unsigned int
+elf32_hppa_size_of_stub (callee, caller, location, destination, sym_name)
+ unsigned int callee, caller;
+ bfd_vma location, destination;
+ const char *sym_name;
+{
+ arg_reloc_type arg_reloc_types[5];
+
+ /* Determine if a long branch or argument relocation stub is needed.
+ If an argument relocation stub is needed, the relocation will be
+ stored into arg_reloc_types. */
+ if (!(((int)(location - destination) > 0x3ffff)
+ || ((int)(location - destination) < (int)0xfffc0000)
+ || elf32_hppa_arg_reloc_needed (caller, callee, arg_reloc_types)))
+ return 0;
+
+ /* Some kind of stub is needed. Determine how big it needs to be.
+ First check for argument relocation stubs as they also handle
+ long calls. Then check for long calls to millicode and finally
+ the normal long calls. */
+ if (arg_reloc_types[ARG0] != NO
+ || arg_reloc_types[ARG1] != NO
+ || arg_reloc_types[ARG2] != NO
+ || arg_reloc_types[ARG3] != NO
+ || arg_reloc_types[RET] != NO)
+ {
+ /* Some kind of argument relocation stub is needed. */
+ unsigned int len = 16;
+ arg_reloc_location i;
+
+ /* Each GR or FG relocation takes 2 insns, each GD or DG
+ relocation takes 3 insns. Plus 4 more insns for the
+ RP adjustment, ldil & (be | ble) and copy. */
+ for (i = ARG0; i <= RET; i++)
+ switch (arg_reloc_types[i])
+ {
+ case GF:
+ case FG:
+ len += 8;
+ break;
+
+ case GD:
+ case DG:
+ len += 12;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Extra instructions are needed if we're relocating a return value. */
+ if (arg_reloc_types[RET] != NO)
+ len += 12;
+
+ return len;
+ }
+ else if (!strncmp ("$$", sym_name, 2)
+ && strcmp ("$$dyncall", sym_name))
+ return 12;
+ else
+ return 16;
+}
+
+/* Build one linker stub as defined by the stub hash table entry GEN_ENTRY.
+ IN_ARGS contains the stub BFD and link info pointers. */
+
+static boolean
+elf32_hppa_build_one_stub (gen_entry, in_args)
+ struct bfd_hash_entry *gen_entry;
+ PTR in_args;
+{
+ void **args = (void **)in_args;
+ bfd *stub_bfd = (bfd *)args[0];
+ struct bfd_link_info *info = (struct bfd_link_info *)args[1];
+ struct elf32_hppa_stub_hash_entry *entry;
+ struct elf32_hppa_stub_hash_table *stub_hash_table;
+ bfd_byte *loc;
+ symvalue sym_value;
+ const char *sym_name;
+
+ /* Initialize pointers to the stub hash table, the particular entry we
+ are building a stub for, and where (in memory) we should place the stub
+ instructions. */
+ entry = (struct elf32_hppa_stub_hash_entry *)gen_entry;
+ stub_hash_table = elf32_hppa_hash_table(info)->stub_hash_table;
+ loc = stub_hash_table->location;
+
+ /* Make a note of the offset within the stubs for this entry. */
+ entry->offset = stub_hash_table->offset;
+
+ /* The symbol's name starts at offset 22. */
+ sym_name = entry->root.string + 22;
+
+ sym_value = (entry->target_value
+ + entry->target_section->output_offset
+ + entry->target_section->output_section->vma);
+
+ if (strncmp ("_____long_branch_stub_", entry->root.string, 22))
+ {
+ /* This must be an argument or return value relocation stub. */
+ unsigned long insn;
+ arg_reloc_location i;
+ bfd_byte *begin_loc = loc;
+
+ /* First the return pointer adjustment. Depending on exact calling
+ sequence this instruction may be skipped. */
+ bfd_put_32 (stub_bfd, LDO_M4_R31_R31, loc);
+ loc += 4;
+
+ /* If we are relocating a return value, then we're going to have
+ to return into the stub. So we have to save off the user's
+ return pointer into the stack at RP'. */
+ if (strncmp (entry->root.string + 14, "NO", 2))
+ {
+ bfd_put_32 (stub_bfd, STW_R31_M8R30, loc);
+ loc += 4;
+ }
+
+ /* Iterate over the argument relocations, emitting instructions
+ to move them around as necessary. */
+ for (i = ARG0; i <= ARG3; i++)
+ {
+ if (!strncmp (entry->root.string + 3 * i + 2, "GF", 2))
+ {
+ bfd_put_32 (stub_bfd, STW_ARG_M16R30 | ((26 - i) << 16), loc);
+ bfd_put_32 (stub_bfd, FLDW_M16R30_FARG | (4 + i), loc + 4);
+ loc += 8;
+ }
+ else if (!strncmp (entry->root.string + 3 * i + 2, "FG", 2))
+ {
+ bfd_put_32 (stub_bfd, FSTW_FARG_M16R30 | (4 + i), loc);
+ bfd_put_32 (stub_bfd, LDW_M16R30_ARG | ((26 - i) << 16), loc + 4);
+ loc += 8;
+ }
+ else if (!strncmp (entry->root.string + 3 * i + 2, "GD", 2))
+ {
+ bfd_put_32 (stub_bfd, STW_ARG_M12R30 | ((26 - i) << 16), loc);
+ bfd_put_32 (stub_bfd, STW_ARG_M16R30 | ((25 - i) << 16), loc + 4);
+ bfd_put_32 (stub_bfd, FLDD_M16R30_FARG | (5 + i), loc + 8);
+ loc += 12;
+ }
+ else if (!strncmp (entry->root.string + 3 * i + 2, "DG", 2))
+ {
+ bfd_put_32 (stub_bfd, FSTD_FARG_M16R30 | (5 + i), loc);
+ bfd_put_32 (stub_bfd, LDW_M12R30_ARG | ((26 - i) << 16), loc + 4);
+ bfd_put_32 (stub_bfd, LDW_M16R30_ARG | ((25 - i) << 16), loc + 8);
+ loc += 12;
+ }
+ }
+
+ /* Load the high bits of the target address into %r1. */
+ insn = hppa_rebuild_insn (stub_bfd, LDIL_R1,
+ hppa_field_adjust (sym_value, 0, e_lrsel), 21);
+ bfd_put_32 (stub_bfd, insn, loc);
+ loc += 4;
+
+ /* If we are relocating a return value, then we're going to have
+ to return into the stub, then perform the return value relocation. */
+ if (strncmp (entry->root.string + 14, "NO", 2))
+ {
+ /* To return to the stub we "ble" to the target and copy the return
+ pointer from %r31 into %r2. */
+ insn = hppa_rebuild_insn (stub_bfd,
+ BLE_SR4_R1,
+ hppa_field_adjust (sym_value, 0,
+ e_rrsel) >> 2,
+ 17);
+ bfd_put_32 (stub_bfd, insn, loc);
+ bfd_put_32 (stub_bfd, COPY_R31_R2, loc + 4);
+
+ /* Reload the return pointer for our caller from the stack. */
+ bfd_put_32 (stub_bfd, LDW_M8R30_R31, loc + 8);
+ loc += 12;
+
+ /* Perform the return value relocation. */
+ if (!strncmp (entry->root.string + 14, "GF", 2))
+ {
+ bfd_put_32 (stub_bfd, STW_ARG_M16R30 | (28 << 16), loc);
+ bfd_put_32 (stub_bfd, FLDW_M16R30_FARG | 4, loc + 4);
+ loc += 8;
+ }
+ else if (!strncmp (entry->root.string + 14, "FG", 2))
+ {
+ bfd_put_32 (stub_bfd, FSTW_FARG_M16R30 | 4, loc);
+ bfd_put_32 (stub_bfd, LDW_M16R30_ARG | (28 << 16), loc + 4);
+ loc += 8;
+ }
+ else if (!strncmp (entry->root.string + 2, "GD", 2))
+ {
+ bfd_put_32 (stub_bfd, STW_ARG_M12R30 | (28 << 16), loc);
+ bfd_put_32 (stub_bfd, STW_ARG_M16R30 | (29 << 16), loc + 4);
+ bfd_put_32 (stub_bfd, FLDD_M16R30_FARG | 4, loc + 8);
+ loc += 12;
+ }
+ else if (!strncmp (entry->root.string + 2, "DG", 2))
+ {
+ bfd_put_32 (stub_bfd, FSTD_FARG_M16R30 | 4, loc);
+ bfd_put_32 (stub_bfd, LDW_M12R30_ARG | (28 << 16), loc + 4);
+ bfd_put_32 (stub_bfd, LDW_M16R30_ARG | (29 << 16), loc + 8);
+ loc += 12;
+ }
+ /* Branch back to the user's code now. */
+ bfd_put_32 (stub_bfd, BV_N_0_R31, loc);
+ loc += 4;
+ }
+ else
+ {
+ /* No return value relocation, so we can simply "be" to the
+ target and copy out return pointer into %r2. */
+ insn = hppa_rebuild_insn (stub_bfd, BE_SR4_R1,
+ hppa_field_adjust (sym_value, 0,
+ e_rrsel) >> 2, 17);
+ bfd_put_32 (stub_bfd, insn, loc);
+ bfd_put_32 (stub_bfd, COPY_R31_R2, loc + 4);
+ loc += 8;
+ }
+
+ /* Update the location and offsets. */
+ stub_hash_table->location += (loc - begin_loc);
+ stub_hash_table->offset += (loc - begin_loc);
+ }
+ else
+ {
+ /* Create one of two variant long branch stubs. One for $$dyncall and
+ normal calls, the other for calls to millicode. */
+ unsigned long insn;
+ int millicode_call = 0;
+
+ if (!strncmp ("$$", sym_name, 2) && strcmp ("$$dyncall", sym_name))
+ millicode_call = 1;
+
+ /* First the return pointer adjustment. Depending on exact calling
+ sequence this instruction may be skipped. */
+ bfd_put_32 (stub_bfd, LDO_M4_R31_R31, loc);
+
+ /* The next two instructions are the long branch itself. A long branch
+ is formed with "ldil" loading the upper bits of the target address
+ into a register, then branching with "be" which adds in the lower bits.
+ Long branches to millicode nullify the delay slot of the "be". */
+ insn = hppa_rebuild_insn (stub_bfd, LDIL_R1,
+ hppa_field_adjust (sym_value, 0, e_lrsel), 21);
+ bfd_put_32 (stub_bfd, insn, loc + 4);
+ insn = hppa_rebuild_insn (stub_bfd, BE_SR4_R1 | (millicode_call ? 2 : 0),
+ hppa_field_adjust (sym_value, 0, e_rrsel) >> 2,
+ 17);
+ bfd_put_32 (stub_bfd, insn, loc + 8);
+
+ if (!millicode_call)
+ {
+ /* The sequence to call this stub places the return pointer into %r31,
+ the final target expects the return pointer in %r2, so copy the
+ return pointer into the proper register. */
+ bfd_put_32 (stub_bfd, COPY_R31_R2, loc + 12);
+
+ /* Update the location and offsets. */
+ stub_hash_table->location += 16;
+ stub_hash_table->offset += 16;
+ }
+ else
+ {
+ /* Update the location and offsets. */
+ stub_hash_table->location += 12;
+ stub_hash_table->offset += 12;
+ }
+
+ }
+ return true;
+}
+
+/* External entry points for sizing and building linker stubs. */
+
+/* Build all the stubs associated with the current output file. The
+ stubs are kept in a hash table attached to the main linker hash
+ table. This is called via hppaelf_finish in the linker. */
+
+boolean
+elf32_hppa_build_stubs (stub_bfd, info)
+ bfd *stub_bfd;
+ struct bfd_link_info *info;
+{
+ /* The stub BFD only has one section. */
+ asection *stub_sec = stub_bfd->sections;
+ struct elf32_hppa_stub_hash_table *table;
+ unsigned int size;
+ void *args[2];
+
+ /* So we can pass both the BFD for the stubs and the link info
+ structure to the routine which actually builds stubs. */
+ args[0] = stub_bfd;
+ args[1] = info;
+
+ /* Allocate memory to hold the linker stubs. */
+ size = bfd_section_size (stub_bfd, stub_sec);
+ stub_sec->contents = (unsigned char *) bfd_zalloc (stub_bfd, size);
+ if (stub_sec->contents == NULL)
+ return false;
+ table = elf32_hppa_hash_table(info)->stub_hash_table;
+ table->location = stub_sec->contents;
+
+ /* Build the stubs as directed by the stub hash table. */
+ elf32_hppa_stub_hash_traverse (table, elf32_hppa_build_one_stub, args);
+
+ return true;
+}
+
+/* Determine and set the size of the stub section for a final link.
+
+ The basic idea here is to examine all the relocations looking for
+ PC-relative calls to a target that is unreachable with a "bl"
+ instruction or calls where the caller and callee disagree on the
+ location of their arguments or return value. */
+
+boolean
+elf32_hppa_size_stubs (stub_bfd, output_bfd, link_info)
+ bfd *stub_bfd;
+ bfd *output_bfd;
+ struct bfd_link_info *link_info;
+{
+ bfd *input_bfd;
+ asection *section, *stub_sec = 0;
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Sym *local_syms, *isym, **all_local_syms;
+ Elf32_External_Sym *ext_syms, *esym;
+ unsigned int i, index, bfd_count = 0;
+ struct elf32_hppa_stub_hash_table *stub_hash_table = 0;
+ struct elf32_hppa_args_hash_table *args_hash_table = 0;
+
+ /* Create and initialize the stub hash table. */
+ stub_hash_table = ((struct elf32_hppa_stub_hash_table *)
+ bfd_malloc (sizeof (struct elf32_hppa_stub_hash_table)));
+ if (!stub_hash_table)
+ goto error_return;
+
+ if (!elf32_hppa_stub_hash_table_init (stub_hash_table, stub_bfd,
+ elf32_hppa_stub_hash_newfunc))
+ goto error_return;
+
+ /* Likewise for the argument location hash table. */
+ args_hash_table = ((struct elf32_hppa_args_hash_table *)
+ bfd_malloc (sizeof (struct elf32_hppa_args_hash_table)));
+ if (!args_hash_table)
+ goto error_return;
+
+ if (!elf32_hppa_args_hash_table_init (args_hash_table,
+ elf32_hppa_args_hash_newfunc))
+ goto error_return;
+
+ /* Attach the hash tables to the main hash table. */
+ elf32_hppa_hash_table(link_info)->stub_hash_table = stub_hash_table;
+ elf32_hppa_hash_table(link_info)->args_hash_table = args_hash_table;
+
+ /* Count the number of input BFDs. */
+ for (input_bfd = link_info->input_bfds;
+ input_bfd != NULL;
+ input_bfd = input_bfd->link_next)
+ bfd_count++;
+
+ /* We want to read in symbol extension records only once. To do this
+ we need to read in the local symbols in parallel and save them for
+ later use; so hold pointers to the local symbols in an array. */
+ all_local_syms
+ = (Elf_Internal_Sym **) bfd_malloc (sizeof (Elf_Internal_Sym *)
+ * bfd_count);
+ if (all_local_syms == NULL)
+ goto error_return;
+ memset (all_local_syms, 0, sizeof (Elf_Internal_Sym *) * bfd_count);
+
+ /* Walk over all the input BFDs adding entries to the args hash table
+ for all the external functions. */
+ for (input_bfd = link_info->input_bfds, index = 0;
+ input_bfd != NULL;
+ input_bfd = input_bfd->link_next, index++)
+ {
+ /* We'll need the symbol table in a second. */
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ if (symtab_hdr->sh_info == 0)
+ continue;
+
+ /* We need an array of the local symbols attached to the input bfd.
+ Unfortunately, we're going to have to read & swap them in. */
+ local_syms
+ = (Elf_Internal_Sym *) bfd_malloc (symtab_hdr->sh_info
+ * sizeof (Elf_Internal_Sym));
+ if (local_syms == NULL)
+ {
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+ all_local_syms[index] = local_syms;
+
+ ext_syms
+ = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_info
+ * sizeof (Elf32_External_Sym));
+ if (ext_syms == NULL)
+ {
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+
+ if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+ || bfd_read (ext_syms, 1,
+ (symtab_hdr->sh_info
+ * sizeof (Elf32_External_Sym)), input_bfd)
+ != (symtab_hdr->sh_info * sizeof (Elf32_External_Sym)))
+ {
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ free (ext_syms);
+ goto error_return;
+ }
+
+ /* Swap the local symbols in. */
+ isym = local_syms;
+ esym = ext_syms;
+ for (i = 0; i < symtab_hdr->sh_info; i++, esym++, isym++)
+ bfd_elf32_swap_symbol_in (input_bfd, esym, isym);
+
+ /* Now we can free the external symbols. */
+ free (ext_syms);
+
+ if (elf32_hppa_read_symext_info (input_bfd, symtab_hdr, args_hash_table,
+ local_syms) == false)
+ {
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+ }
+
+ /* Magic as we know the stub bfd only has one section. */
+ stub_sec = stub_bfd->sections;
+
+ /* If generating a relocateable output file, then we don't
+ have to examine the relocs. */
+ if (link_info->relocateable)
+ {
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ return true;
+ }
+
+ /* Now that we have argument location information for all the global
+ functions we can start looking for stubs. */
+ for (input_bfd = link_info->input_bfds, index = 0;
+ input_bfd != NULL;
+ input_bfd = input_bfd->link_next, index++)
+ {
+ /* We'll need the symbol table in a second. */
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ if (symtab_hdr->sh_info == 0)
+ continue;
+
+ local_syms = all_local_syms[index];
+
+ /* Walk over each section attached to the input bfd. */
+ for (section = input_bfd->sections;
+ section != NULL;
+ section = section->next)
+ {
+ Elf_Internal_Shdr *input_rel_hdr;
+ Elf32_External_Rela *external_relocs, *erelaend, *erela;
+ Elf_Internal_Rela *internal_relocs, *irelaend, *irela;
+
+ /* If there aren't any relocs, then there's nothing to do. */
+ if ((section->flags & SEC_RELOC) == 0
+ || section->reloc_count == 0)
+ continue;
+
+ /* Allocate space for the external relocations. */
+ external_relocs
+ = ((Elf32_External_Rela *)
+ bfd_malloc (section->reloc_count
+ * sizeof (Elf32_External_Rela)));
+ if (external_relocs == NULL)
+ {
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+
+ /* Likewise for the internal relocations. */
+ internal_relocs
+ = ((Elf_Internal_Rela *)
+ bfd_malloc (section->reloc_count * sizeof (Elf_Internal_Rela)));
+ if (internal_relocs == NULL)
+ {
+ free (external_relocs);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+
+ /* Read in the external relocs. */
+ input_rel_hdr = &elf_section_data (section)->rel_hdr;
+ if (bfd_seek (input_bfd, input_rel_hdr->sh_offset, SEEK_SET) != 0
+ || bfd_read (external_relocs, 1, input_rel_hdr->sh_size,
+ input_bfd) != input_rel_hdr->sh_size)
+ {
+ free (external_relocs);
+ free (internal_relocs);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+
+ /* Swap in the relocs. */
+ erela = external_relocs;
+ erelaend = erela + section->reloc_count;
+ irela = internal_relocs;
+ for (; erela < erelaend; erela++, irela++)
+ bfd_elf32_swap_reloca_in (input_bfd, erela, irela);
+
+ /* We're done with the external relocs, free them. */
+ free (external_relocs);
+
+ /* Now examine each relocation. */
+ irela = internal_relocs;
+ irelaend = irela + section->reloc_count;
+ for (; irela < irelaend; irela++)
+ {
+ long r_type, callee_args, caller_args, size_of_stub;
+ unsigned long r_index;
+ struct elf_link_hash_entry *hash;
+ struct elf32_hppa_stub_hash_entry *stub_hash;
+ struct elf32_hppa_args_hash_entry *args_hash;
+ Elf_Internal_Sym *sym;
+ asection *sym_sec;
+ const char *sym_name;
+ symvalue sym_value;
+ bfd_vma location, destination;
+ char *new_name = NULL;
+
+ r_type = ELF32_R_TYPE (irela->r_info);
+ r_index = ELF32_R_SYM (irela->r_info);
+
+ if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ free (internal_relocs);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+
+ /* Only look for stubs on call instructions or plabel
+ references. */
+ if (r_type != R_PARISC_PCREL17F
+ && r_type != R_PARISC_PLABEL32
+ && r_type != R_PARISC_PLABEL21L
+ && r_type != R_PARISC_PLABEL14R)
+ continue;
+
+ /* Now determine the call target, its name, value, section
+ and argument relocation bits. */
+ hash = NULL;
+ sym = NULL;
+ sym_sec = NULL;
+ if (r_index < symtab_hdr->sh_info)
+ {
+ /* It's a local symbol. */
+ Elf_Internal_Shdr *hdr;
+
+ sym = local_syms + r_index;
+ hdr = elf_elfsections (input_bfd)[sym->st_shndx];
+ sym_sec = hdr->bfd_section;
+ sym_name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ sym_value = (ELF_ST_TYPE (sym->st_info) == STT_SECTION
+ ? 0 : sym->st_value);
+ destination = (sym_value
+ + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+
+ /* Tack on an ID so we can uniquely identify this local
+ symbol in the stub or arg info hash tables. */
+ new_name = bfd_malloc (strlen (sym_name) + 10);
+ if (new_name == 0)
+ {
+ free (internal_relocs);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+ sprintf (new_name, "%s_%08x", sym_name, (int)sym_sec);
+ sym_name = new_name;
+ }
+ else
+ {
+ /* It's an external symbol. */
+ long index;
+
+ index = r_index - symtab_hdr->sh_info;
+ hash = elf_sym_hashes (input_bfd)[index];
+ if (hash->root.type == bfd_link_hash_defined
+ || hash->root.type == bfd_link_hash_defweak)
+ {
+ sym_sec = hash->root.u.def.section;
+ sym_name = hash->root.root.string;
+ sym_value = hash->root.u.def.value;
+ destination = (sym_value
+ + sym_sec->output_offset
+ + sym_sec->output_section->vma);
+ }
+ else
+ {
+ bfd_set_error (bfd_error_bad_value);
+ free (internal_relocs);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+ }
+
+ args_hash = elf32_hppa_args_hash_lookup (args_hash_table,
+ sym_name, false, false);
+
+ /* Get both caller and callee argument information. */
+ if (args_hash == NULL)
+ callee_args = 0;
+ else
+ callee_args = args_hash->arg_bits;
+
+ /* For calls get the caller's bits from the addend of
+ the call relocation. For PLABELS the caller's bits
+ are assumed to have all args & return values in general
+ registers (0x155). */
+ if (r_type == R_PARISC_PCREL17F)
+ caller_args = HPPA_R_ARG_RELOC (irela->r_addend);
+ else
+ caller_args = 0x155;
+
+ /* Now determine where the call point is. */
+ location = (section->output_offset
+ + section->output_section->vma
+ + irela->r_offset);
+
+ /* We only care about the destination for PCREL function
+ calls (eg. we don't care for PLABELS). */
+ if (r_type != R_PARISC_PCREL17F)
+ location = destination;
+
+ /* Determine what (if any) linker stub is needed and its
+ size (in bytes). */
+ size_of_stub = elf32_hppa_size_of_stub (callee_args,
+ caller_args,
+ location,
+ destination,
+ sym_name);
+ if (size_of_stub != 0)
+ {
+ char *stub_name;
+ unsigned int len;
+
+ /* Get the name of this stub. */
+ len = strlen (sym_name);
+ len += 23;
+
+ stub_name = bfd_malloc (len);
+ if (!stub_name)
+ {
+ /* Because sym_name was mallocd above for local
+ symbols. */
+ if (r_index < symtab_hdr->sh_info)
+ free (new_name);
+
+ free (internal_relocs);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+ elf32_hppa_name_of_stub (caller_args, callee_args,
+ location, destination, stub_name);
+ strcat (stub_name + 22, sym_name);
+
+ /* Because sym_name was malloced above for local symbols. */
+ if (r_index < symtab_hdr->sh_info)
+ free (new_name);
+
+ stub_hash
+ = elf32_hppa_stub_hash_lookup (stub_hash_table, stub_name,
+ false, false);
+ if (stub_hash != NULL)
+ {
+ /* The proper stub has already been created, nothing
+ else to do. */
+ free (stub_name);
+ }
+ else
+ {
+ bfd_set_section_size (stub_bfd, stub_sec,
+ (bfd_section_size (stub_bfd,
+ stub_sec)
+ + size_of_stub));
+
+ /* Enter this entry into the linker stub hash table. */
+ stub_hash
+ = elf32_hppa_stub_hash_lookup (stub_hash_table,
+ stub_name, true, true);
+ if (stub_hash == NULL)
+ {
+ free (stub_name);
+ free (internal_relocs);
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ goto error_return;
+ }
+
+ /* We'll need these to determine the address that the
+ stub will branch to. */
+ stub_hash->target_value = sym_value;
+ stub_hash->target_section = sym_sec;
+ }
+ free (stub_name);
+ }
+ }
+ /* We're done with the internal relocs, free them. */
+ free (internal_relocs);
+ }
+ }
+ /* We're done with the local symbols, free them. */
+ for (i = 0; i < bfd_count; i++)
+ if (all_local_syms[i])
+ free (all_local_syms[i]);
+ free (all_local_syms);
+ return true;
+
+error_return:
+ /* Return gracefully, avoiding dangling references to the hash tables. */
+ if (stub_hash_table)
+ {
+ elf32_hppa_hash_table(link_info)->stub_hash_table = NULL;
+ free (stub_hash_table);
+ }
+ if (args_hash_table)
+ {
+ elf32_hppa_hash_table(link_info)->args_hash_table = NULL;
+ free (args_hash_table);
+ }
+ /* Set the size of the stub section to zero since we're never going
+ to create them. Avoids losing when we try to get its contents
+ too. */
+ bfd_set_section_size (stub_bfd, stub_sec, 0);
+ return false;
+}
+
+/* Misc BFD support code. */
+#define bfd_elf32_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup
+#define bfd_elf32_bfd_is_local_label hppa_elf_is_local_label
+
+/* Symbol extension stuff. */
+#define bfd_elf32_set_section_contents elf32_hppa_set_section_contents
+#define elf_backend_symbol_table_processing \
+ elf32_hppa_backend_symbol_table_processing
+#define elf_backend_begin_write_processing \
+ elf32_hppa_backend_begin_write_processing
+#define elf_backend_final_write_processing \
+ elf32_hppa_backend_final_write_processing
+
+/* Stuff for the BFD linker. */
+#define elf_backend_relocate_section elf32_hppa_relocate_section
+#define elf_backend_add_symbol_hook elf32_hppa_add_symbol_hook
+#define elf_backend_link_output_symbol_hook \
+ elf32_hppa_link_output_symbol_hook
+#define bfd_elf32_bfd_link_hash_table_create \
+ elf32_hppa_link_hash_table_create
+
+#define TARGET_BIG_SYM bfd_elf32_hppa_vec
+#define TARGET_BIG_NAME "elf32-hppa"
+#define ELF_ARCH bfd_arch_hppa
+#define ELF_MACHINE_CODE EM_PARISC
+#define ELF_MAXPAGESIZE 0x1000
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-hppa.h b/contrib/gdb/bfd/elf32-hppa.h
new file mode 100644
index 0000000..63ee522
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-hppa.h
@@ -0,0 +1,152 @@
+/* ELF32/HPPA support
+
+ This file contains ELF32/HPPA relocation support as specified
+ in the Stratus FTX/Golf Object File Format (SED-1762) dated
+ February 1994.
+
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+ Written by:
+
+ Center for Software Science
+ Department of Computer Science
+ University of Utah
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _ELF32_HPPA_H
+#define _ELF32_HPPA_H
+
+#include "elf-bfd.h"
+#include "libhppa.h"
+#include "elf/hppa.h"
+
+/* ELF/HPPA relocation types */
+
+typedef enum
+ {
+ /* Address relocation types
+ These relocation types do simple base + offset relocations. */
+
+ R_PARISC_NONE = 0x00,
+ R_PARISC_DIR32 = 0x01,
+ R_PARISC_DIR21L = 0x02,
+ R_PARISC_DIR17R = 0x03,
+ R_PARISC_DIR17F = 0x04,
+ R_PARISC_DIR14R = 0x06,
+
+ /* PC-relative relocation types
+ Typically used for calls.
+ Note PCREL17C and PCREL17F differ only in overflow handling.
+ PCREL17C never reports a relocation error.
+
+ When supporting argument relocations, function calls must be
+ accompanied by parameter relocation information. This information is
+ carried in the ten high-order bits of the addend field. The remaining
+ 22 bits of of the addend field are sign-extended to form the Addend.
+
+ Note the code to build argument relocations depends on the
+ addend being zero. A consequence of this limitation is GAS
+ can not perform relocation reductions for function symbols. */
+ R_PARISC_PCREL21L = 0x0a,
+ R_PARISC_PCREL17R = 0x0b,
+ R_PARISC_PCREL17F = 0x0c,
+ R_PARISC_PCREL17C = 0x0d,
+ R_PARISC_PCREL14R = 0x0e,
+ R_PARISC_PCREL14F = 0x0f,
+
+ /* DP-relative relocation types. */
+ R_PARISC_DPREL21L = 0x12,
+ R_PARISC_DPREL14R = 0x16,
+ R_PARISC_DPREL14F = 0x17,
+
+ /* Data linkage table (DLT) relocation types
+
+ SOM DLT_REL fixup requests are used to for static data references
+ from position-independent code within shared libraries. They are
+ similar to the GOT relocation types in some SVR4 implementations. */
+
+ R_PARISC_DLTREL21L = 0x1a,
+ R_PARISC_DLTREL14R = 0x1e,
+ R_PARISC_DLTREL14F = 0x1f,
+
+ /* DLT indirect relocation types */
+ R_PARISC_DLTIND21L = 0x22,
+ R_PARISC_DLTIND14R = 0x26,
+ R_PARISC_DLTIND14F = 0x27,
+
+ /* Base relative relocation types. Ugh. These imply lots of state */
+ R_PARISC_SETBASE = 0x28,
+ R_PARISC_BASEREL32 = 0x29,
+ R_PARISC_BASEREL21L = 0x2a,
+ R_PARISC_BASEREL17R = 0x2b,
+ R_PARISC_BASEREL17F = 0x2c,
+ R_PARISC_BASEREL14R = 0x2e,
+ R_PARISC_BASEREL14F = 0x2f,
+
+ /* Segment relative relocation types. */
+ R_PARISC_TEXTREL32 = 0x31,
+ R_PARISC_DATAREL32 = 0x39,
+
+ /* Plabel relocation types. */
+ R_PARISC_PLABEL32 = 0x41,
+ R_PARISC_PLABEL21L = 0x42,
+ R_PARISC_PLABEL14R = 0x46,
+
+ /* PLT relocations. */
+ R_PARISC_PLTIND21L = 0x82,
+ R_PARISC_PLTIND14R = 0x86,
+ R_PARISC_PLTIND14F = 0x87,
+
+ /* Misc relocation types. */
+ R_PARISC_COPY = 0x88,
+ R_PARISC_GLOB_DAT = 0x89,
+ R_PARISC_JMP_SLOT = 0x8a,
+ R_PARISC_RELATIVE = 0x8b,
+ R_PARISC_UNIMPLEMENTED,
+ }
+elf32_hppa_reloc_type;
+
+#define ELF_HOWTO_TABLE_SIZE R_PARISC_UNIMPLEMENTED + 1
+#define N_PARISC_RELOCS R_PARISC_UNIMPLEMENTED + 1
+
+/* Define groups of basic relocations. FIXME: These should
+ be the only basic relocations created by GAS. The rest
+ should be internal to the BFD backend.
+
+ The idea is both SOM and ELF define these basic relocation
+ types so they map into a SOM or ELF specific relocation
+ as appropriate. This allows GAS to share much more code
+ between the two target object formats. */
+
+#define R_HPPA_NONE R_PARISC_NONE
+#define R_HPPA R_PARISC_DIR32
+#define R_HPPA_GOTOFF R_PARISC_DPREL21L
+#define R_HPPA_PCREL_CALL R_PARISC_PCREL21L
+#define R_HPPA_ABS_CALL R_PARISC_DIR17F
+#define R_HPPA_COMPLEX R_PARISC_UNIMPLEMENTED
+
+elf32_hppa_reloc_type **hppa_elf_gen_reloc_type
+ PARAMS ((bfd *, elf32_hppa_reloc_type, int, int, int));
+
+boolean elf32_hppa_size_stubs
+ PARAMS ((bfd *, bfd *, struct bfd_link_info *));
+
+boolean elf32_hppa_build_stubs
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+#endif /* _ELF32_HPPA_H */
diff --git a/contrib/gdb/bfd/elf32-i386.c b/contrib/gdb/bfd/elf32-i386.c
new file mode 100644
index 0000000..3b39aac
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-i386.c
@@ -0,0 +1,1546 @@
+/* Intel 80386/80486-specific support for 32-bit ELF
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+static reloc_howto_type *elf_i386_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static void elf_i386_info_to_howto
+ PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
+static void elf_i386_info_to_howto_rel
+ PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+static boolean elf_i386_check_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
+static boolean elf_i386_adjust_dynamic_symbol
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static boolean elf_i386_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean elf_i386_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean elf_i386_finish_dynamic_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
+static boolean elf_i386_finish_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+#define USE_REL 1 /* 386 uses REL relocations instead of RELA */
+
+enum reloc_type
+ {
+ R_386_NONE = 0,
+ R_386_32,
+ R_386_PC32,
+ R_386_GOT32,
+ R_386_PLT32,
+ R_386_COPY,
+ R_386_GLOB_DAT,
+ R_386_JUMP_SLOT,
+ R_386_RELATIVE,
+ R_386_GOTOFF,
+ R_386_GOTPC,
+ R_386_max
+ };
+
+#if 0
+static CONST char *CONST reloc_type_names[] =
+{
+ "R_386_NONE",
+ "R_386_32",
+ "R_386_PC32",
+ "R_386_GOT32",
+ "R_386_PLT32",
+ "R_386_COPY",
+ "R_386_GLOB_DAT",
+ "R_386_JUMP_SLOT",
+ "R_386_RELATIVE",
+ "R_386_GOTOFF",
+ "R_386_GOTPC",
+};
+#endif
+
+static reloc_howto_type elf_howto_table[]=
+{
+ HOWTO(R_386_NONE, 0,0, 0,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_NONE", true,0x00000000,0x00000000,false),
+ HOWTO(R_386_32, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_32", true,0xffffffff,0xffffffff,false),
+ HOWTO(R_386_PC32, 0,2,32,true, 0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PC32", true,0xffffffff,0xffffffff,true),
+ HOWTO(R_386_GOT32, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOT32", true,0xffffffff,0xffffffff,false),
+ HOWTO(R_386_PLT32, 0,2,32,true,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_PLT32", true,0xffffffff,0xffffffff,true),
+ HOWTO(R_386_COPY, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_COPY", true,0xffffffff,0xffffffff,false),
+ HOWTO(R_386_GLOB_DAT, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GLOB_DAT", true,0xffffffff,0xffffffff,false),
+ HOWTO(R_386_JUMP_SLOT, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_JUMP_SLOT",true,0xffffffff,0xffffffff,false),
+ HOWTO(R_386_RELATIVE, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_RELATIVE", true,0xffffffff,0xffffffff,false),
+ HOWTO(R_386_GOTOFF, 0,2,32,false,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTOFF", true,0xffffffff,0xffffffff,false),
+ HOWTO(R_386_GOTPC, 0,2,32,true,0,complain_overflow_bitfield, bfd_elf_generic_reloc,"R_386_GOTPC", true,0xffffffff,0xffffffff,true),
+};
+
+#ifdef DEBUG_GEN_RELOC
+#define TRACE(str) fprintf (stderr, "i386 bfd reloc lookup %d (%s)\n", code, str)
+#else
+#define TRACE(str)
+#endif
+
+static reloc_howto_type *
+elf_i386_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ switch (code)
+ {
+ case BFD_RELOC_NONE:
+ TRACE ("BFD_RELOC_NONE");
+ return &elf_howto_table[ (int)R_386_NONE ];
+
+ case BFD_RELOC_32:
+ TRACE ("BFD_RELOC_32");
+ return &elf_howto_table[ (int)R_386_32 ];
+
+ case BFD_RELOC_32_PCREL:
+ TRACE ("BFD_RELOC_PC32");
+ return &elf_howto_table[ (int)R_386_PC32 ];
+
+ case BFD_RELOC_386_GOT32:
+ TRACE ("BFD_RELOC_386_GOT32");
+ return &elf_howto_table[ (int)R_386_GOT32 ];
+
+ case BFD_RELOC_386_PLT32:
+ TRACE ("BFD_RELOC_386_PLT32");
+ return &elf_howto_table[ (int)R_386_PLT32 ];
+
+ case BFD_RELOC_386_COPY:
+ TRACE ("BFD_RELOC_386_COPY");
+ return &elf_howto_table[ (int)R_386_COPY ];
+
+ case BFD_RELOC_386_GLOB_DAT:
+ TRACE ("BFD_RELOC_386_GLOB_DAT");
+ return &elf_howto_table[ (int)R_386_GLOB_DAT ];
+
+ case BFD_RELOC_386_JUMP_SLOT:
+ TRACE ("BFD_RELOC_386_JUMP_SLOT");
+ return &elf_howto_table[ (int)R_386_JUMP_SLOT ];
+
+ case BFD_RELOC_386_RELATIVE:
+ TRACE ("BFD_RELOC_386_RELATIVE");
+ return &elf_howto_table[ (int)R_386_RELATIVE ];
+
+ case BFD_RELOC_386_GOTOFF:
+ TRACE ("BFD_RELOC_386_GOTOFF");
+ return &elf_howto_table[ (int)R_386_GOTOFF ];
+
+ case BFD_RELOC_386_GOTPC:
+ TRACE ("BFD_RELOC_386_GOTPC");
+ return &elf_howto_table[ (int)R_386_GOTPC ];
+
+ default:
+ break;
+ }
+
+ TRACE ("Unknown");
+ return 0;
+}
+
+static void
+elf_i386_info_to_howto (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf32_Internal_Rela *dst;
+{
+ BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_386_max);
+
+ cache_ptr->howto = &elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+}
+
+static void
+elf_i386_info_to_howto_rel (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf32_Internal_Rel *dst;
+{
+ BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_386_max);
+
+ cache_ptr->howto = &elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+}
+
+/* Functions for the i386 ELF linker. */
+
+/* The name of the dynamic interpreter. This is put in the .interp
+ section. */
+
+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
+
+/* The size in bytes of an entry in the procedure linkage table. */
+
+#define PLT_ENTRY_SIZE 16
+
+/* The first entry in an absolute procedure linkage table looks like
+ this. See the SVR4 ABI i386 supplement to see how this works. */
+
+static const bfd_byte elf_i386_plt0_entry[PLT_ENTRY_SIZE] =
+{
+ 0xff, 0x35, /* pushl contents of address */
+ 0, 0, 0, 0, /* replaced with address of .got + 4. */
+ 0xff, 0x25, /* jmp indirect */
+ 0, 0, 0, 0, /* replaced with address of .got + 8. */
+ 0, 0, 0, 0 /* pad out to 16 bytes. */
+};
+
+/* Subsequent entries in an absolute procedure linkage table look like
+ this. */
+
+static const bfd_byte elf_i386_plt_entry[PLT_ENTRY_SIZE] =
+{
+ 0xff, 0x25, /* jmp indirect */
+ 0, 0, 0, 0, /* replaced with address of this symbol in .got. */
+ 0x68, /* pushl immediate */
+ 0, 0, 0, 0, /* replaced with offset into relocation table. */
+ 0xe9, /* jmp relative */
+ 0, 0, 0, 0 /* replaced with offset to start of .plt. */
+};
+
+/* The first entry in a PIC procedure linkage table look like this. */
+
+static const bfd_byte elf_i386_pic_plt0_entry[PLT_ENTRY_SIZE] =
+{
+ 0xff, 0xb3, 4, 0, 0, 0, /* pushl 4(%ebx) */
+ 0xff, 0xa3, 8, 0, 0, 0, /* jmp *8(%ebx) */
+ 0, 0, 0, 0 /* pad out to 16 bytes. */
+};
+
+/* Subsequent entries in a PIC procedure linkage table look like this. */
+
+static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
+{
+ 0xff, 0xa3, /* jmp *offset(%ebx) */
+ 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */
+ 0x68, /* pushl immediate */
+ 0, 0, 0, 0, /* replaced with offset into relocation table. */
+ 0xe9, /* jmp relative */
+ 0, 0, 0, 0 /* replaced with offset to start of .plt. */
+};
+
+/* Look through the relocs for a section during the first phase, and
+ allocate space in the global offset table or procedure linkage
+ table. */
+
+static boolean
+elf_i386_check_relocs (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma *local_got_offsets;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+ asection *sgot;
+ asection *srelgot;
+ asection *sreloc;
+
+ if (info->relocateable)
+ return true;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ local_got_offsets = elf_local_got_offsets (abfd);
+
+ sgot = NULL;
+ srelgot = NULL;
+ sreloc = NULL;
+
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ /* Some relocs require a global offset table. */
+ if (dynobj == NULL)
+ {
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_386_GOT32:
+ case R_386_GOTOFF:
+ case R_386_GOTPC:
+ elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (! _bfd_elf_create_got_section (dynobj, info))
+ return false;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_386_GOT32:
+ /* This symbol requires a global offset table entry. */
+
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ if (srelgot == NULL
+ && (h != NULL || info->shared))
+ {
+ srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
+ if (srelgot == NULL)
+ {
+ srelgot = bfd_make_section (dynobj, ".rel.got");
+ if (srelgot == NULL
+ || ! bfd_set_section_flags (dynobj, srelgot,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, srelgot, 2))
+ return false;
+ }
+ }
+
+ if (h != NULL)
+ {
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+ h->got_offset = sgot->_raw_size;
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ srelgot->_raw_size += sizeof (Elf32_External_Rel);
+ }
+ else
+ {
+ /* This is a global offset table entry for a local
+ symbol. */
+ if (local_got_offsets == NULL)
+ {
+ size_t size;
+ register unsigned int i;
+
+ size = symtab_hdr->sh_info * sizeof (bfd_vma);
+ local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
+ if (local_got_offsets == NULL)
+ return false;
+ elf_local_got_offsets (abfd) = local_got_offsets;
+ for (i = 0; i < symtab_hdr->sh_info; i++)
+ local_got_offsets[i] = (bfd_vma) -1;
+ }
+ if (local_got_offsets[r_symndx] != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+ local_got_offsets[r_symndx] = sgot->_raw_size;
+
+ if (info->shared)
+ {
+ /* If we are generating a shared object, we need to
+ output a R_386_RELATIVE reloc so that the dynamic
+ linker can adjust this GOT entry. */
+ srelgot->_raw_size += sizeof (Elf32_External_Rel);
+ }
+ }
+
+ sgot->_raw_size += 4;
+
+ break;
+
+ case R_386_PLT32:
+ /* This symbol requires a procedure linkage table entry. We
+ actually build the entry in adjust_dynamic_symbol,
+ because this might be a case of linking PIC code which is
+ never referenced by a dynamic object, in which case we
+ don't need to generate a procedure linkage table entry
+ after all. */
+
+ /* If this is a local symbol, we resolve it directly without
+ creating a procedure linkage table entry. */
+ if (h == NULL)
+ continue;
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+
+ break;
+
+ case R_386_32:
+ case R_386_PC32:
+ if (info->shared
+ && (sec->flags & SEC_ALLOC) != 0
+ && (ELF32_R_TYPE (rel->r_info) != R_386_PC32 || h != NULL))
+ {
+ /* When creating a shared object, we must copy these
+ reloc types into the output file. We create a reloc
+ section in dynobj and make room for this reloc. */
+ if (sreloc == NULL)
+ {
+ const char *name;
+
+ name = (bfd_elf_string_from_elf_section
+ (abfd,
+ elf_elfheader (abfd)->e_shstrndx,
+ elf_section_data (sec)->rel_hdr.sh_name));
+ if (name == NULL)
+ return false;
+
+ BFD_ASSERT (strncmp (name, ".rel", 4) == 0
+ && strcmp (bfd_get_section_name (abfd, sec),
+ name + 4) == 0);
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ if (sreloc == NULL)
+ {
+ sreloc = bfd_make_section (dynobj, name);
+ if (sreloc == NULL
+ || ! bfd_set_section_flags (dynobj, sreloc,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+ return false;
+ }
+ }
+
+ sreloc->_raw_size += sizeof (Elf32_External_Rel);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. The current definition is in some section of the
+ dynamic object, but we're not including those sections. We have to
+ change the definition to something the rest of the link can
+ understand. */
+
+static boolean
+elf_i386_adjust_dynamic_symbol (info, h)
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+{
+ bfd *dynobj;
+ asection *s;
+ unsigned int power_of_two;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+ || h->weakdef != NULL
+ || ((h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_REGULAR) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+
+ /* If this is a function, put it in the procedure linkage table. We
+ will fill in the contents of the procedure linkage table later,
+ when we know the address of the .got section. */
+ if (h->type == STT_FUNC
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ {
+ if (! info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0)
+ {
+ /* This case can occur if we saw a PLT32 reloc in an input
+ file, but the symbol was never referred to by a dynamic
+ object. In such a case, we don't actually need to build
+ a procedure linkage table, and we can just do a PC32
+ reloc instead. */
+ BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
+ return true;
+ }
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ if (s->_raw_size == 0)
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* If this symbol is not defined in a regular file, and we are
+ not generating a shared library, then set the symbol to this
+ location in the .plt. This is required to make function
+ pointers compare as equal between the normal executable and
+ the shared library. */
+ if (! info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+ }
+
+ h->plt_offset = s->_raw_size;
+
+ /* Make room for this entry. */
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .got.plt section, which
+ will be placed in the .got section by the linker script. */
+
+ s = bfd_get_section_by_name (dynobj, ".got.plt");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size += 4;
+
+ /* We also need to make an entry in the .rel.plt section. */
+
+ s = bfd_get_section_by_name (dynobj, ".rel.plt");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size += sizeof (Elf32_External_Rel);
+
+ return true;
+ }
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->weakdef != NULL)
+ {
+ BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
+ || h->weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->weakdef->root.u.def.section;
+ h->root.u.def.value = h->weakdef->root.u.def.value;
+ return true;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+
+ /* If we are creating a shared library, we must presume that the
+ only references to the symbol are via the global offset table.
+ For such cases we need not do anything here; the relocations will
+ be handled correctly by relocate_section. */
+ if (info->shared)
+ return true;
+
+ /* We must allocate the symbol in our .dynbss section, which will
+ become part of the .bss section of the executable. There will be
+ an entry for this symbol in the .dynsym section. The dynamic
+ object will contain position independent code, so all references
+ from the dynamic object to this symbol will go through the global
+ offset table. The dynamic linker will use the .dynsym entry to
+ determine the address it must put in the global offset table, so
+ both the dynamic object and the regular object will refer to the
+ same memory location for the variable. */
+
+ s = bfd_get_section_by_name (dynobj, ".dynbss");
+ BFD_ASSERT (s != NULL);
+
+ /* If the symbol is currently defined in the .bss section of the
+ dynamic object, then it is OK to simply initialize it to zero.
+ If the symbol is in some other section, we must generate a
+ R_386_COPY reloc to tell the dynamic linker to copy the initial
+ value out of the dynamic object and into the runtime process
+ image. We need to remember the offset into the .rel.bss section
+ we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_LOAD) != 0)
+ {
+ asection *srel;
+
+ srel = bfd_get_section_by_name (dynobj, ".rel.bss");
+ BFD_ASSERT (srel != NULL);
+ srel->_raw_size += sizeof (Elf32_External_Rel);
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+ }
+
+ /* We need to figure out the alignment required for this symbol. I
+ have no idea how ELF linkers handle this. */
+ power_of_two = bfd_log2 (h->size);
+ if (power_of_two > 3)
+ power_of_two = 3;
+
+ /* Apply the required alignment. */
+ s->_raw_size = BFD_ALIGN (s->_raw_size,
+ (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > bfd_get_section_alignment (dynobj, s))
+ {
+ if (! bfd_set_section_alignment (dynobj, s, power_of_two))
+ return false;
+ }
+
+ /* Define the symbol as being at this point in the section. */
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+
+ /* Increment the section size to make room for the symbol. */
+ s->_raw_size += h->size;
+
+ return true;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static boolean
+elf_i386_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *s;
+ boolean plt;
+ boolean relocs;
+ boolean reltext;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (! info->shared)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+ else
+ {
+ /* We may have created entries in the .rel.got section.
+ However, if we are not creating the dynamic sections, we will
+ not actually use these entries. Reset the size of .rel.got,
+ which will cause it to get stripped from the output file
+ below. */
+ s = bfd_get_section_by_name (dynobj, ".rel.got");
+ if (s != NULL)
+ s->_raw_size = 0;
+ }
+
+ /* The check_relocs and adjust_dynamic_symbol entry points have
+ determined the sizes of the various dynamic sections. Allocate
+ memory for them. */
+ plt = false;
+ relocs = false;
+ reltext = false;
+ for (s = dynobj->sections; s != NULL; s = s->next)
+ {
+ const char *name;
+ boolean strip;
+
+ if ((s->flags & SEC_IN_MEMORY) == 0)
+ continue;
+
+ /* It's OK to base decisions on the section name, because none
+ of the dynobj section names depend upon the input files. */
+ name = bfd_get_section_name (dynobj, s);
+
+ strip = false;
+
+ if (strcmp (name, ".plt") == 0)
+ {
+ if (s->_raw_size == 0)
+ {
+ /* Strip this section if we don't need it; see the
+ comment below. */
+ strip = true;
+ }
+ else
+ {
+ /* Remember whether there is a PLT. */
+ plt = true;
+ }
+ }
+ else if (strncmp (name, ".rel", 4) == 0)
+ {
+ if (s->_raw_size == 0)
+ {
+ /* If we don't need this section, strip it from the
+ output file. This is mostly to handle .rel.bss and
+ .rel.plt. We must create both sections in
+ create_dynamic_sections, because they must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ strip = true;
+ }
+ else
+ {
+ asection *target;
+
+ /* Remember whether there are any reloc sections other
+ than .rel.plt. */
+ if (strcmp (name, ".rel.plt") != 0)
+ {
+ relocs = true;
+
+ /* If this relocation section applies to a read only
+ section, then we probably need a DT_TEXTREL
+ entry. The entries in the .rel.plt section
+ really apply to the .got section, which we
+ created ourselves and so know is not readonly. */
+ target = bfd_get_section_by_name (output_bfd, name + 4);
+ if (target != NULL
+ && (target->flags & SEC_READONLY) != 0)
+ reltext = true;
+ }
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ s->reloc_count = 0;
+ }
+ }
+ else if (strncmp (name, ".got", 4) != 0)
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
+
+ if (strip)
+ {
+ asection **spp;
+
+ for (spp = &s->output_section->owner->sections;
+ *spp != s->output_section;
+ spp = &(*spp)->next)
+ ;
+ *spp = s->output_section->next;
+ --s->output_section->owner->section_count;
+
+ continue;
+ }
+
+ /* Allocate memory for the section contents. */
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ return false;
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Add some entries to the .dynamic section. We fill in the
+ values later, in elf_i386_finish_dynamic_sections, but we
+ must add the entries now so that we get the correct size for
+ the .dynamic section. The DT_DEBUG entry is filled in by the
+ dynamic linker and used by the debugger. */
+ if (! info->shared)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ return false;
+ }
+
+ if (plt)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_REL)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+ return false;
+ }
+
+ if (relocs)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_REL, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_RELSZ, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_RELENT,
+ sizeof (Elf32_External_Rel)))
+ return false;
+ }
+
+ if (reltext)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Relocate an i386 ELF section. */
+
+static boolean
+elf_i386_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ 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;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma *local_got_offsets;
+ asection *sgot;
+ asection *splt;
+ asection *sreloc;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (input_bfd);
+ local_got_offsets = elf_local_got_offsets (input_bfd);
+
+ sgot = NULL;
+ splt = NULL;
+ sreloc = NULL;
+
+ rel = relocs;
+ relend = relocs + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ int r_type;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type < 0 || r_type >= (int) R_386_max)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ howto = elf_howto_table + r_type;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (info->relocateable)
+ {
+ /* This is a relocateable link. We don't have to change
+ anything, unless the reloc is against a section symbol,
+ in which case we have to adjust according to where the
+ section symbol winds up in the output section. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ {
+ bfd_vma val;
+
+ sec = local_sections[r_symndx];
+ val = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ val += sec->output_offset + sym->st_value;
+ bfd_put_32 (input_bfd, val, contents + rel->r_offset);
+ }
+ }
+
+ continue;
+ }
+
+ /* This is a final link. */
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ relocation = (sec->output_section->vma
+ + sec->output_offset
+ + sym->st_value);
+ }
+ else
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ if (r_type == R_386_GOTPC
+ || (r_type == R_386_PLT32
+ && h->plt_offset != (bfd_vma) -1)
+ || (r_type == R_386_GOT32
+ && elf_hash_table (info)->dynamic_sections_created
+ && (! info->shared
+ || ! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ || (info->shared
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ && (r_type == R_386_32
+ || r_type == R_386_PC32)
+ && (input_section->flags & SEC_ALLOC) != 0))
+ {
+ /* In these cases, we don't need the relocation
+ value. We check specially because in some
+ obscure cases sec->output_section will be NULL. */
+ relocation = 0;
+ }
+ else
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else if (info->shared && !info->symbolic)
+ relocation = 0;
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ relocation = 0;
+ }
+ }
+
+ switch (r_type)
+ {
+ case R_386_GOT32:
+ /* Relocation is to the entry for this symbol in the global
+ offset table. */
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ if (h != NULL)
+ {
+ bfd_vma off;
+
+ off = h->got_offset;
+ BFD_ASSERT (off != (bfd_vma) -1);
+
+ if (! elf_hash_table (info)->dynamic_sections_created
+ || (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ {
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally. We must initialize this entry in the
+ global offset table. Since the offset must
+ always be a multiple of 4, we use the least
+ significant bit to record whether we have
+ initialized it already.
+
+ When doing a dynamic link, we create a .rel.got
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation,
+ sgot->contents + off);
+ h->got_offset |= 1;
+ }
+ }
+
+ relocation = sgot->output_offset + off;
+ }
+ else
+ {
+ bfd_vma off;
+
+ BFD_ASSERT (local_got_offsets != NULL
+ && local_got_offsets[r_symndx] != (bfd_vma) -1);
+
+ off = local_got_offsets[r_symndx];
+
+ /* The offset must always be a multiple of 4. We use
+ the least significant bit to record whether we have
+ already generated the necessary reloc. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation, sgot->contents + off);
+
+ if (info->shared)
+ {
+ asection *srelgot;
+ Elf_Internal_Rel outrel;
+
+ srelgot = bfd_get_section_by_name (dynobj, ".rel.got");
+ BFD_ASSERT (srelgot != NULL);
+
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + off);
+ outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ bfd_elf32_swap_reloc_out (output_bfd, &outrel,
+ (((Elf32_External_Rel *)
+ srelgot->contents)
+ + srelgot->reloc_count));
+ ++srelgot->reloc_count;
+ }
+
+ local_got_offsets[r_symndx] |= 1;
+ }
+
+ relocation = sgot->output_offset + off;
+ }
+
+ break;
+
+ case R_386_GOTOFF:
+ /* Relocation is relative to the start of the global offset
+ table. */
+
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ /* Note that sgot->output_offset is not involved in this
+ calculation. We always want the start of .got. If we
+ defined _GLOBAL_OFFSET_TABLE in a different way, as is
+ permitted by the ABI, we might have to change this
+ calculation. */
+ relocation -= sgot->output_section->vma;
+
+ break;
+
+ case R_386_GOTPC:
+ /* Use global offset table as symbol value. */
+
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ relocation = sgot->output_section->vma;
+
+ break;
+
+ case R_386_PLT32:
+ /* Relocation is to the entry for this symbol in the
+ procedure linkage table. */
+
+ /* Resolve a PLT32 reloc again a local symbol directly,
+ without using the procedure linkage table. */
+ if (h == NULL)
+ break;
+
+ if (h->plt_offset == (bfd_vma) -1)
+ {
+ /* We didn't make a PLT entry for this symbol. This
+ happens when statically linking PIC code, or when
+ using -Bsymbolic. */
+ break;
+ }
+
+ if (splt == NULL)
+ {
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL);
+ }
+
+ relocation = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset);
+
+ break;
+
+ case R_386_32:
+ case R_386_PC32:
+ if (info->shared
+ && (input_section->flags & SEC_ALLOC) != 0
+ && (r_type != R_386_PC32
+ || (h != NULL
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))))
+ {
+ Elf_Internal_Rel outrel;
+ boolean relocate;
+
+ /* When generating a shared object, these relocations
+ are copied into the output file to be resolved at run
+ time. */
+
+ if (sreloc == NULL)
+ {
+ const char *name;
+
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd,
+ elf_elfheader (input_bfd)->e_shstrndx,
+ elf_section_data (input_section)->rel_hdr.sh_name));
+ if (name == NULL)
+ return false;
+
+ BFD_ASSERT (strncmp (name, ".rel", 4) == 0
+ && strcmp (bfd_get_section_name (input_bfd,
+ input_section),
+ name + 4) == 0);
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ BFD_ASSERT (sreloc != NULL);
+ }
+
+ outrel.r_offset = (rel->r_offset
+ + input_section->output_section->vma
+ + input_section->output_offset);
+ if (r_type == R_386_PC32)
+ {
+ BFD_ASSERT (h != NULL && h->dynindx != -1);
+ relocate = false;
+ outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_PC32);
+ }
+ else
+ {
+ if (h == NULL
+ || (info->symbolic
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) != 0))
+ {
+ relocate = true;
+ outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ }
+ else
+ {
+ BFD_ASSERT (h->dynindx != -1);
+ relocate = false;
+ outrel.r_info = ELF32_R_INFO (h->dynindx, R_386_32);
+ }
+ }
+
+ bfd_elf32_swap_reloc_out (output_bfd, &outrel,
+ (((Elf32_External_Rel *)
+ sreloc->contents)
+ + sreloc->reloc_count));
+ ++sreloc->reloc_count;
+
+ /* If this reloc is against an external symbol, we do
+ not want to fiddle with the addend. Otherwise, we
+ need to include the symbol value so that it becomes
+ an addend for the dynamic reloc. */
+ if (! relocate)
+ continue;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ 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 (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ return false;
+ if (*name == '\0')
+ name = bfd_section_name (input_bfd, sec);
+ }
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0,
+ input_bfd, input_section, rel->r_offset)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Finish up dynamic symbol handling. We set the contents of various
+ dynamic sections here. */
+
+static boolean
+elf_i386_finish_dynamic_symbol (output_bfd, info, h, sym)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+{
+ bfd *dynobj;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ if (h->plt_offset != (bfd_vma) -1)
+ {
+ asection *splt;
+ asection *sgot;
+ asection *srel;
+ bfd_vma plt_index;
+ bfd_vma got_offset;
+ Elf_Internal_Rel rel;
+
+ /* This symbol has an entry in the procedure linkage table. Set
+ it up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+ srel = bfd_get_section_by_name (dynobj, ".rel.plt");
+ BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+
+ /* Get the index in the procedure linkage table which
+ corresponds to this symbol. This is the index of this symbol
+ in all the symbols for which we are making plt entries. The
+ first entry in the procedure linkage table is reserved. */
+ plt_index = h->plt_offset / PLT_ENTRY_SIZE - 1;
+
+ /* Get the offset into the .got table of the entry that
+ corresponds to this function. Each .got entry is 4 bytes.
+ The first three are reserved. */
+ got_offset = (plt_index + 3) * 4;
+
+ /* Fill in the entry in the procedure linkage table. */
+ if (! info->shared)
+ {
+ memcpy (splt->contents + h->plt_offset, elf_i386_plt_entry,
+ PLT_ENTRY_SIZE);
+ bfd_put_32 (output_bfd,
+ (sgot->output_section->vma
+ + sgot->output_offset
+ + got_offset),
+ splt->contents + h->plt_offset + 2);
+ }
+ else
+ {
+ memcpy (splt->contents + h->plt_offset, elf_i386_pic_plt_entry,
+ PLT_ENTRY_SIZE);
+ bfd_put_32 (output_bfd, got_offset,
+ splt->contents + h->plt_offset + 2);
+ }
+
+ bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel),
+ splt->contents + h->plt_offset + 7);
+ bfd_put_32 (output_bfd, - (h->plt_offset + PLT_ENTRY_SIZE),
+ splt->contents + h->plt_offset + 12);
+
+ /* Fill in the entry in the global offset table. */
+ bfd_put_32 (output_bfd,
+ (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset
+ + 6),
+ sgot->contents + got_offset);
+
+ /* Fill in the entry in the .rel.plt section. */
+ rel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + got_offset);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT);
+ bfd_elf32_swap_reloc_out (output_bfd, &rel,
+ ((Elf32_External_Rel *) srel->contents
+ + plt_index));
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ /* Mark the symbol as undefined, rather than as defined in
+ the .plt section. Leave the value alone. */
+ sym->st_shndx = SHN_UNDEF;
+ }
+ }
+
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ asection *sgot;
+ asection *srel;
+ Elf_Internal_Rel rel;
+
+ /* This symbol has an entry in the global offset table. Set it
+ up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ srel = bfd_get_section_by_name (dynobj, ".rel.got");
+ BFD_ASSERT (sgot != NULL && srel != NULL);
+
+ rel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + (h->got_offset &~ 1));
+
+ /* If this is a -Bsymbolic link, and the symbol is defined
+ locally, we just want to emit a RELATIVE reloc. The entry in
+ the global offset table will already have been initialized in
+ the relocate_section function. */
+ if (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+ rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
+ else
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_386_GLOB_DAT);
+ }
+
+ bfd_elf32_swap_reloc_out (output_bfd, &rel,
+ ((Elf32_External_Rel *) srel->contents
+ + srel->reloc_count));
+ ++srel->reloc_count;
+ }
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+ {
+ asection *s;
+ Elf_Internal_Rel rel;
+
+ /* This symbol needs a copy reloc. Set it up. */
+
+ BFD_ASSERT (h->dynindx != -1
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak));
+
+ s = bfd_get_section_by_name (h->root.u.def.section->owner,
+ ".rel.bss");
+ BFD_ASSERT (s != NULL);
+
+ rel.r_offset = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY);
+ bfd_elf32_swap_reloc_out (output_bfd, &rel,
+ ((Elf32_External_Rel *) s->contents
+ + s->reloc_count));
+ ++s->reloc_count;
+ }
+
+ /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
+ if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+ || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ sym->st_shndx = SHN_ABS;
+
+ return true;
+}
+
+/* Finish up the dynamic sections. */
+
+static boolean
+elf_i386_finish_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *sgot;
+ asection *sdyn;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+ BFD_ASSERT (sgot != NULL);
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ asection *splt;
+ Elf32_External_Dyn *dyncon, *dynconend;
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL && sdyn != NULL);
+
+ dyncon = (Elf32_External_Dyn *) sdyn->contents;
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ asection *s;
+
+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ default:
+ break;
+
+ case DT_PLTGOT:
+ name = ".got";
+ goto get_vma;
+ case DT_JMPREL:
+ name = ".rel.plt";
+ get_vma:
+ s = bfd_get_section_by_name (output_bfd, name);
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_ptr = s->vma;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_PLTRELSZ:
+ s = bfd_get_section_by_name (output_bfd, ".rel.plt");
+ BFD_ASSERT (s != NULL);
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val = s->_cooked_size;
+ else
+ dyn.d_un.d_val = s->_raw_size;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_RELSZ:
+ /* My reading of the SVR4 ABI indicates that the
+ procedure linkage table relocs (DT_JMPREL) should be
+ included in the overall relocs (DT_REL). This is
+ what Solaris does. However, UnixWare can not handle
+ that case. Therefore, we override the DT_RELSZ entry
+ here to make it not include the JMPREL relocs. Since
+ the linker script arranges for .rel.plt to follow all
+ other relocation sections, we don't have to worry
+ about changing the DT_REL entry. */
+ s = bfd_get_section_by_name (output_bfd, ".rel.plt");
+ if (s != NULL)
+ {
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val -= s->_cooked_size;
+ else
+ dyn.d_un.d_val -= s->_raw_size;
+ }
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+ }
+ }
+
+ /* Fill in the first entry in the procedure linkage table. */
+ if (splt->_raw_size > 0)
+ {
+ if (info->shared)
+ memcpy (splt->contents, elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
+ else
+ {
+ memcpy (splt->contents, elf_i386_plt0_entry, PLT_ENTRY_SIZE);
+ bfd_put_32 (output_bfd,
+ sgot->output_section->vma + sgot->output_offset + 4,
+ splt->contents + 2);
+ bfd_put_32 (output_bfd,
+ sgot->output_section->vma + sgot->output_offset + 8,
+ splt->contents + 8);
+ }
+ }
+
+ /* UnixWare sets the entsize of .plt to 4, although that doesn't
+ really seem like the right value. */
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
+ }
+
+ /* Fill in the first three entries in the global offset table. */
+ if (sgot->_raw_size > 0)
+ {
+ if (sdyn == NULL)
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
+ else
+ bfd_put_32 (output_bfd,
+ sdyn->output_section->vma + sdyn->output_offset,
+ sgot->contents);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8);
+ }
+
+ elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
+
+ return true;
+}
+
+#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
+#define TARGET_LITTLE_NAME "elf32-i386"
+#define ELF_ARCH bfd_arch_i386
+#define ELF_MACHINE_CODE EM_386
+#define elf_info_to_howto elf_i386_info_to_howto
+#define elf_info_to_howto_rel elf_i386_info_to_howto_rel
+#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
+#define ELF_MAXPAGESIZE 0x1000
+#define elf_backend_create_dynamic_sections \
+ _bfd_elf_create_dynamic_sections
+#define elf_backend_check_relocs elf_i386_check_relocs
+#define elf_backend_adjust_dynamic_symbol \
+ elf_i386_adjust_dynamic_symbol
+#define elf_backend_size_dynamic_sections \
+ elf_i386_size_dynamic_sections
+#define elf_backend_relocate_section elf_i386_relocate_section
+#define elf_backend_finish_dynamic_symbol \
+ elf_i386_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections \
+ elf_i386_finish_dynamic_sections
+#define elf_backend_want_got_plt 1
+#define elf_backend_plt_readonly 1
+#define elf_backend_want_plt_sym 0
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-i860.c b/contrib/gdb/bfd/elf32-i860.c
new file mode 100644
index 0000000..a8537a7
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-i860.c
@@ -0,0 +1,33 @@
+/* Intel 860 specific support for 32-bit ELF
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+#define bfd_elf32_bfd_reloc_type_lookup bfd_default_reloc_type_lookup
+#define elf_info_to_howto _bfd_elf_no_info_to_howto
+
+#define TARGET_BIG_SYM bfd_elf32_i860_vec
+#define TARGET_BIG_NAME "elf32-i860"
+#define ELF_ARCH bfd_arch_i860
+#define ELF_MACHINE_CODE EM_860
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-m68k.c b/contrib/gdb/bfd/elf32-m68k.c
new file mode 100644
index 0000000..752dfae
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-m68k.c
@@ -0,0 +1,1600 @@
+/* Motorola 68k series support for 32-bit ELF
+ Copyright 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+static reloc_howto_type *reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static void rtype_to_howto
+ PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
+static void rtype_to_howto_rel
+ PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+static boolean elf_m68k_check_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
+static boolean elf_m68k_adjust_dynamic_symbol
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static boolean elf_m68k_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean elf_m68k_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean elf_m68k_finish_dynamic_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
+static boolean elf_m68k_finish_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* elf32 m68k code, generated by elf.el */
+enum reloc_type {
+ R_68K_NONE = 0,
+ R_68K_32 = 1,
+ R_68K_16 = 2,
+ R_68K_8 = 3,
+ R_68K_PC32 = 4,
+ R_68K_PC16 = 5,
+ R_68K_PC8 = 6,
+ R_68K_GOT32 = 7,
+ R_68K_GOT16 = 8,
+ R_68K_GOT8 = 9,
+ R_68K_GOT32O = 10,
+ R_68K_GOT16O = 11,
+ R_68K_GOT8O = 12,
+ R_68K_PLT32 = 13,
+ R_68K_PLT16 = 14,
+ R_68K_PLT8 = 15,
+ R_68K_PLT32O = 16,
+ R_68K_PLT16O = 17,
+ R_68K_PLT8O = 18,
+ R_68K_COPY = 19,
+ R_68K_GLOB_DAT = 20,
+ R_68K_JMP_SLOT = 21,
+ R_68K_RELATIVE = 22,
+ R_68K__max
+};
+
+static reloc_howto_type howto_table[] = {
+ HOWTO(R_68K_NONE, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_NONE", false, 0, 0x00000000,false),
+ HOWTO(R_68K_32, 0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32", false, 0, 0xffffffff,false),
+ HOWTO(R_68K_16, 0, 1,16, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_16", false, 0, 0x0000ffff,false),
+ HOWTO(R_68K_8, 0, 0, 8, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_8", false, 0, 0x000000ff,false),
+ HOWTO(R_68K_PC32, 0, 2,32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC32", false, 0, 0xffffffff,true),
+ HOWTO(R_68K_PC16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC16", false, 0, 0x0000ffff,true),
+ HOWTO(R_68K_PC8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PC8", false, 0, 0x000000ff,true),
+ HOWTO(R_68K_GOT32, 0, 2,32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT32", false, 0, 0xffffffff,true),
+ HOWTO(R_68K_GOT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16", false, 0, 0x0000ffff,true),
+ HOWTO(R_68K_GOT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8", false, 0, 0x000000ff,true),
+ HOWTO(R_68K_GOT32O, 0, 2,32, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT32O", false, 0, 0xffffffff,false),
+ HOWTO(R_68K_GOT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT16O", false, 0, 0x0000ffff,false),
+ HOWTO(R_68K_GOT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_GOT8O", false, 0, 0x000000ff,false),
+ HOWTO(R_68K_PLT32, 0, 2,32, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT32", false, 0, 0xffffffff,true),
+ HOWTO(R_68K_PLT16, 0, 1,16, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16", false, 0, 0x0000ffff,true),
+ HOWTO(R_68K_PLT8, 0, 0, 8, true, 0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8", false, 0, 0x000000ff,true),
+ HOWTO(R_68K_PLT32O, 0, 2,32, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT32O", false, 0, 0xffffffff,false),
+ HOWTO(R_68K_PLT16O, 0, 1,16, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT16O", false, 0, 0x0000ffff,false),
+ HOWTO(R_68K_PLT8O, 0, 0, 8, false,0, complain_overflow_signed, bfd_elf_generic_reloc, "R_68K_PLT8O", false, 0, 0x000000ff,false),
+ HOWTO(R_68K_COPY, 0, 0, 0, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_COPY", false, 0, 0xffffffff,false),
+ HOWTO(R_68K_GLOB_DAT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_GLOB_DAT", false, 0, 0xffffffff,false),
+ HOWTO(R_68K_JMP_SLOT, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_JMP_SLOT", false, 0, 0xffffffff,false),
+ HOWTO(R_68K_RELATIVE, 0, 2,32, false,0, complain_overflow_dont, bfd_elf_generic_reloc, "R_68K_RELATIVE", false, 0, 0xffffffff,false),
+};
+
+static void
+rtype_to_howto (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf_Internal_Rela *dst;
+{
+ BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_68K__max);
+ cache_ptr->howto = &howto_table[ELF32_R_TYPE(dst->r_info)];
+}
+
+static void
+rtype_to_howto_rel (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf_Internal_Rel *dst;
+{
+ BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_68K__max);
+ cache_ptr->howto = &howto_table[ELF32_R_TYPE(dst->r_info)];
+}
+
+#define elf_info_to_howto rtype_to_howto
+#define elf_info_to_howto_rel rtype_to_howto_rel
+
+static const struct { unsigned char bfd_val, elf_val; } reloc_map[] = {
+ { BFD_RELOC_NONE, R_68K_NONE },
+ { BFD_RELOC_32, R_68K_32 },
+ { BFD_RELOC_16, R_68K_16 },
+ { BFD_RELOC_8, R_68K_8 },
+ { BFD_RELOC_32_PCREL, R_68K_PC32 },
+ { BFD_RELOC_16_PCREL, R_68K_PC16 },
+ { BFD_RELOC_8_PCREL, R_68K_PC8 },
+ { BFD_RELOC_32_GOT_PCREL, R_68K_GOT32 },
+ { BFD_RELOC_16_GOT_PCREL, R_68K_GOT16 },
+ { BFD_RELOC_8_GOT_PCREL, R_68K_GOT8 },
+ { BFD_RELOC_32_GOTOFF, R_68K_GOT32O },
+ { BFD_RELOC_16_GOTOFF, R_68K_GOT16O },
+ { BFD_RELOC_8_GOTOFF, R_68K_GOT8O },
+ { BFD_RELOC_32_PLT_PCREL, R_68K_PLT32 },
+ { BFD_RELOC_16_PLT_PCREL, R_68K_PLT16 },
+ { BFD_RELOC_8_PLT_PCREL, R_68K_PLT8 },
+ { BFD_RELOC_32_PLTOFF, R_68K_PLT32O },
+ { BFD_RELOC_16_PLTOFF, R_68K_PLT16O },
+ { BFD_RELOC_8_PLTOFF, R_68K_PLT8O },
+ { BFD_RELOC_NONE, R_68K_COPY },
+ { BFD_RELOC_68K_GLOB_DAT, R_68K_GLOB_DAT },
+ { BFD_RELOC_68K_JMP_SLOT, R_68K_JMP_SLOT },
+ { BFD_RELOC_68K_RELATIVE, R_68K_RELATIVE },
+ { BFD_RELOC_CTOR, R_68K_32 },
+};
+
+static reloc_howto_type *
+reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+ for (i = 0; i < sizeof (reloc_map) / sizeof (reloc_map[0]); i++)
+ {
+ if (reloc_map[i].bfd_val == code)
+ return &howto_table[(int) reloc_map[i].elf_val];
+ }
+ return 0;
+}
+
+#define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup
+#define ELF_ARCH bfd_arch_m68k
+/* end code generated by elf.el */
+
+#define USE_RELA
+
+
+/* Functions for the m68k ELF linker. */
+
+/* The name of the dynamic interpreter. This is put in the .interp
+ section. */
+
+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
+
+/* The size in bytes of an entry in the procedure linkage table. */
+
+#define PLT_ENTRY_SIZE 20
+
+/* The first entry in a procedure linkage table looks like this. See
+ the SVR4 ABI m68k supplement to see how this works. */
+
+static const bfd_byte elf_m68k_plt0_entry[PLT_ENTRY_SIZE] =
+{
+ 0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */
+ 0, 0, 0, 0, /* replaced with offset to .got + 4. */
+ 0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,addr]) */
+ 0, 0, 0, 0, /* replaced with offset to .got + 8. */
+ 0, 0, 0, 0 /* pad out to 20 bytes. */
+};
+
+/* Subsequent entries in a procedure linkage table look like this. */
+
+static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] =
+{
+ 0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,symbol@GOTPC]) */
+ 0, 0, 0, 0, /* replaced with offset to symbol's .got entry. */
+ 0x2f, 0x3c, /* move.l #offset,-(%sp) */
+ 0, 0, 0, 0, /* replaced with offset into relocation table. */
+ 0x60, 0xff, /* bra.l .plt */
+ 0, 0, 0, 0 /* replaced with offset to start of .plt. */
+};
+
+/* Look through the relocs for a section during the first phase, and
+ allocate space in the global offset table or procedure linkage
+ table. */
+
+static boolean
+elf_m68k_check_relocs (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma *local_got_offsets;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+ asection *sgot;
+ asection *srelgot;
+ asection *sreloc;
+
+ if (info->relocateable)
+ return true;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ local_got_offsets = elf_local_got_offsets (abfd);
+
+ sgot = NULL;
+ srelgot = NULL;
+ sreloc = NULL;
+
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_68K_GOT8:
+ case R_68K_GOT16:
+ case R_68K_GOT32:
+ if (h != NULL
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ break;
+ /* Fall through. */
+ case R_68K_GOT8O:
+ case R_68K_GOT16O:
+ case R_68K_GOT32O:
+ /* This symbol requires a global offset table entry. */
+
+ if (dynobj == NULL)
+ {
+ /* Create the .got section. */
+ elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (!_bfd_elf_create_got_section (dynobj, info))
+ return false;
+ }
+
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ if (srelgot == NULL
+ && (h != NULL || info->shared))
+ {
+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ if (srelgot == NULL)
+ {
+ srelgot = bfd_make_section (dynobj, ".rela.got");
+ if (srelgot == NULL
+ || !bfd_set_section_flags (dynobj, srelgot,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || !bfd_set_section_alignment (dynobj, srelgot, 2))
+ return false;
+ }
+ }
+
+ if (h != NULL)
+ {
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+ h->got_offset = sgot->_raw_size;
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ srelgot->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ else
+ {
+ /* This is a global offset table entry for a local
+ symbol. */
+ if (local_got_offsets == NULL)
+ {
+ size_t size;
+ register unsigned int i;
+
+ size = symtab_hdr->sh_info * sizeof (bfd_vma);
+ local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
+ if (local_got_offsets == NULL)
+ return false;
+ elf_local_got_offsets (abfd) = local_got_offsets;
+ for (i = 0; i < symtab_hdr->sh_info; i++)
+ local_got_offsets[i] = (bfd_vma) -1;
+ }
+ if (local_got_offsets[r_symndx] != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+ local_got_offsets[r_symndx] = sgot->_raw_size;
+
+ if (info->shared)
+ {
+ /* If we are generating a shared object, we need to
+ output a R_68K_RELATIVE reloc so that the dynamic
+ linker can adjust this GOT entry. */
+ srelgot->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ }
+
+ sgot->_raw_size += 4;
+ break;
+
+ case R_68K_PLT8:
+ case R_68K_PLT16:
+ case R_68K_PLT32:
+ /* This symbol requires a procedure linkage table entry. We
+ actually build the entry in adjust_dynamic_symbol,
+ because this might be a case of linking PIC code which is
+ never referenced by a dynamic object, in which case we
+ don't need to generate a procedure linkage table entry
+ after all. */
+
+ /* If this is a local symbol, we resolve it directly without
+ creating a procedure linkage table entry. */
+ if (h == NULL)
+ continue;
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ break;
+
+ case R_68K_PLT8O:
+ case R_68K_PLT16O:
+ case R_68K_PLT32O:
+ /* This symbol requires a procedure linkage table entry. */
+
+ if (h == NULL)
+ {
+ /* It does not make sense to have this relocation for a
+ local symbol. FIXME: does it? How to handle it if
+ it does make sense? */
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (!bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ break;
+
+ case R_68K_PC8:
+ case R_68K_PC16:
+ case R_68K_PC32:
+ if (h == NULL)
+ break;
+ /* Fall through. */
+ case R_68K_8:
+ case R_68K_16:
+ case R_68K_32:
+ if (info->shared
+ && (sec->flags & SEC_ALLOC) != 0
+ && ((ELF32_R_TYPE (rel->r_info) != R_68K_PC8
+ && ELF32_R_TYPE (rel->r_info) != R_68K_PC16
+ && ELF32_R_TYPE (rel->r_info) != R_68K_PC32)
+ || (!info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+ {
+ /* When creating a shared object, we must copy these
+ reloc types into the output file. We create a reloc
+ section in dynobj and make room for this reloc. */
+ if (sreloc == NULL)
+ {
+ const char *name;
+
+ name = (bfd_elf_string_from_elf_section
+ (abfd,
+ elf_elfheader (abfd)->e_shstrndx,
+ elf_section_data (sec)->rel_hdr.sh_name));
+ if (name == NULL)
+ return false;
+
+ BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+ && strcmp (bfd_get_section_name (abfd, sec),
+ name + 5) == 0);
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ if (sreloc == NULL)
+ {
+ sreloc = bfd_make_section (dynobj, name);
+ if (sreloc == NULL
+ || !bfd_set_section_flags (dynobj, sreloc,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || !bfd_set_section_alignment (dynobj, sreloc, 2))
+ return false;
+ }
+ }
+
+ sreloc->_raw_size += sizeof (Elf32_External_Rela);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. The current definition is in some section of the
+ dynamic object, but we're not including those sections. We have to
+ change the definition to something the rest of the link can
+ understand. */
+
+static boolean
+elf_m68k_adjust_dynamic_symbol (info, h)
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+{
+ bfd *dynobj;
+ asection *s;
+ unsigned int power_of_two;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+ || h->weakdef != NULL
+ || ((h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_REGULAR) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+
+ /* If this is a function, put it in the procedure linkage table. We
+ will fill in the contents of the procedure linkage table later,
+ when we know the address of the .got section. */
+ if (h->type == STT_FUNC
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ {
+ if (! info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0
+ /* We must always create the plt entry if it was referenced
+ by a PLTxxO relocation. In this case we already recorded
+ it as a dynamic symbol. */
+ && h->dynindx == -1)
+ {
+ /* This case can occur if we saw a PLTxx reloc in an input
+ file, but the symbol was never referred to by a dynamic
+ object. In such a case, we don't actually need to build
+ a procedure linkage table, and we can just do a PCxx
+ reloc instead. */
+ BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
+ return true;
+ }
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+
+ /* If this is the first .plt entry, make room for the special
+ first entry. */
+ if (s->_raw_size == 0)
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* If this symbol is not defined in a regular file, and we are
+ not generating a shared library, then set the symbol to this
+ location in the .plt. This is required to make function
+ pointers compare as equal between the normal executable and
+ the shared library. */
+ if (!info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+ }
+
+ h->plt_offset = s->_raw_size;
+
+ /* Make room for this entry. */
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .got.plt section, which
+ will be placed in the .got section by the linker script. */
+
+ s = bfd_get_section_by_name (dynobj, ".got.plt");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size += 4;
+
+ /* We also need to make an entry in the .rela.plt section. */
+
+ s = bfd_get_section_by_name (dynobj, ".rela.plt");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size += sizeof (Elf32_External_Rela);
+
+ return true;
+ }
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->weakdef != NULL)
+ {
+ BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
+ || h->weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->weakdef->root.u.def.section;
+ h->root.u.def.value = h->weakdef->root.u.def.value;
+ return true;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+
+ /* If we are creating a shared library, we must presume that the
+ only references to the symbol are via the global offset table.
+ For such cases we need not do anything here; the relocations will
+ be handled correctly by relocate_section. */
+ if (info->shared)
+ return true;
+
+ /* We must allocate the symbol in our .dynbss section, which will
+ become part of the .bss section of the executable. There will be
+ an entry for this symbol in the .dynsym section. The dynamic
+ object will contain position independent code, so all references
+ from the dynamic object to this symbol will go through the global
+ offset table. The dynamic linker will use the .dynsym entry to
+ determine the address it must put in the global offset table, so
+ both the dynamic object and the regular object will refer to the
+ same memory location for the variable. */
+
+ s = bfd_get_section_by_name (dynobj, ".dynbss");
+ BFD_ASSERT (s != NULL);
+
+ /* If the symbol is currently defined in the .bss section of the
+ dynamic object, then it is OK to simply initialize it to zero.
+ If the symbol is in some other section, we must generate a
+ R_68K_COPY reloc to tell the dynamic linker to copy the initial
+ value out of the dynamic object and into the runtime process
+ image. We need to remember the offset into the .rela.bss section
+ we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_LOAD) != 0)
+ {
+ asection *srel;
+
+ srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+ BFD_ASSERT (srel != NULL);
+ srel->_raw_size += sizeof (Elf32_External_Rela);
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+ }
+
+ /* We need to figure out the alignment required for this symbol. I
+ have no idea how ELF linkers handle this. */
+ power_of_two = bfd_log2 (h->size);
+ if (power_of_two > 3)
+ power_of_two = 3;
+
+ /* Apply the required alignment. */
+ s->_raw_size = BFD_ALIGN (s->_raw_size,
+ (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > bfd_get_section_alignment (dynobj, s))
+ {
+ if (!bfd_set_section_alignment (dynobj, s, power_of_two))
+ return false;
+ }
+
+ /* Define the symbol as being at this point in the section. */
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+
+ /* Increment the section size to make room for the symbol. */
+ s->_raw_size += h->size;
+
+ return true;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static boolean
+elf_m68k_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *s;
+ boolean plt;
+ boolean relocs;
+ boolean reltext;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (!info->shared)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+ else
+ {
+ /* We may have created entries in the .rela.got section.
+ However, if we are not creating the dynamic sections, we will
+ not actually use these entries. Reset the size of .rela.got,
+ which will cause it to get stripped from the output file
+ below. */
+ s = bfd_get_section_by_name (dynobj, ".rela.got");
+ if (s != NULL)
+ s->_raw_size = 0;
+ }
+
+ /* The check_relocs and adjust_dynamic_symbol entry points have
+ determined the sizes of the various dynamic sections. Allocate
+ memory for them. */
+ plt = false;
+ relocs = false;
+ reltext = false;
+ for (s = dynobj->sections; s != NULL; s = s->next)
+ {
+ const char *name;
+ boolean strip;
+
+ if ((s->flags & SEC_IN_MEMORY) == 0)
+ continue;
+
+ /* It's OK to base decisions on the section name, because none
+ of the dynobj section names depend upon the input files. */
+ name = bfd_get_section_name (dynobj, s);
+
+ strip = false;
+
+ if (strcmp (name, ".plt") == 0)
+ {
+ if (s->_raw_size == 0)
+ {
+ /* Strip this section if we don't need it; see the
+ comment below. */
+ strip = true;
+ }
+ else
+ {
+ /* Remember whether there is a PLT. */
+ plt = true;
+ }
+ }
+ else if (strncmp (name, ".rela", 5) == 0)
+ {
+ if (s->_raw_size == 0)
+ {
+ /* If we don't need this section, strip it from the
+ output file. This is mostly to handle .rela.bss and
+ .rela.plt. We must create both sections in
+ create_dynamic_sections, because they must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ strip = true;
+ }
+ else
+ {
+ asection *target;
+
+ /* Remember whether there are any reloc sections other
+ than .rela.plt. */
+ if (strcmp (name, ".rela.plt") != 0)
+ {
+ relocs = true;
+
+ /* If this relocation section applies to a read only
+ section, then we probably need a DT_TEXTREL
+ entry. .rela.plt is actually associated with
+ .got.plt, which is never readonly. */
+ target = bfd_get_section_by_name (output_bfd, name + 5);
+ if (target != NULL
+ && (target->flags & SEC_READONLY) != 0)
+ reltext = true;
+ }
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ s->reloc_count = 0;
+ }
+ }
+ else if (strncmp (name, ".got", 4) != 0)
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
+
+ if (strip)
+ {
+ asection **spp;
+
+ for (spp = &s->output_section->owner->sections;
+ *spp != s->output_section;
+ spp = &(*spp)->next)
+ ;
+ *spp = s->output_section->next;
+ --s->output_section->owner->section_count;
+
+ continue;
+ }
+
+ /* Allocate memory for the section contents. */
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ return false;
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Add some entries to the .dynamic section. We fill in the
+ values later, in elf_m68k_finish_dynamic_sections, but we
+ must add the entries now so that we get the correct size for
+ the .dynamic section. The DT_DEBUG entry is filled in by the
+ dynamic linker and used by the debugger. */
+ if (!info->shared)
+ {
+ if (!bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ return false;
+ }
+
+ if (plt)
+ {
+ if (!bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0)
+ || !bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+ || !bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
+ || !bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+ return false;
+ }
+
+ if (relocs)
+ {
+ if (!bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
+ || !bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
+ || !bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
+ sizeof (Elf32_External_Rela)))
+ return false;
+ }
+
+ if (reltext)
+ {
+ if (!bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Relocate an M68K ELF section. */
+
+static boolean
+elf_m68k_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ 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;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma *local_got_offsets;
+ asection *sgot;
+ asection *splt;
+ asection *sreloc;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (input_bfd);
+ local_got_offsets = elf_local_got_offsets (input_bfd);
+
+ sgot = NULL;
+ splt = NULL;
+ sreloc = NULL;
+
+ rel = relocs;
+ relend = relocs + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ int r_type;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type < 0 || r_type >= (int) R_68K__max)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ howto = howto_table + r_type;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (info->relocateable)
+ {
+ /* This is a relocateable link. We don't have to change
+ anything, unless the reloc is against a section symbol,
+ in which case we have to adjust according to where the
+ section symbol winds up in the output section. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ {
+ sec = local_sections[r_symndx];
+ rel->r_addend += sec->output_offset + sym->st_value;
+ }
+ }
+
+ continue;
+ }
+
+ /* This is a final link. */
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ relocation = (sec->output_section->vma
+ + sec->output_offset
+ + sym->st_value);
+ }
+ else
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ if (((r_type == R_68K_PLT8
+ || r_type == R_68K_PLT16
+ || r_type == R_68K_PLT32
+ || r_type == R_68K_PLT8O
+ || r_type == R_68K_PLT16O
+ || r_type == R_68K_PLT32O)
+ && h->plt_offset != (bfd_vma) -1)
+ || ((r_type == R_68K_GOT8O
+ || r_type == R_68K_GOT16O
+ || r_type == R_68K_GOT32O
+ || ((r_type == R_68K_GOT8
+ || r_type == R_68K_GOT16
+ || r_type == R_68K_GOT32)
+ && strcmp (h->root.root.string,
+ "_GLOBAL_OFFSET_TABLE_") != 0))
+ && elf_hash_table (info)->dynamic_sections_created
+ && (! info->shared
+ || ! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ || (info->shared
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ && (input_section->flags & SEC_ALLOC) != 0
+ && (r_type == R_68K_8
+ || r_type == R_68K_16
+ || r_type == R_68K_32
+ || r_type == R_68K_PC8
+ || r_type == R_68K_PC16
+ || r_type == R_68K_PC32)))
+ {
+ /* In these cases, we don't need the relocation
+ value. We check specially because in some
+ obscure cases sec->output_section will be NULL. */
+ relocation = 0;
+ }
+ else
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else if (info->shared && !info->symbolic)
+ relocation = 0;
+ else
+ {
+ if (!(info->callbacks->undefined_symbol
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ relocation = 0;
+ }
+ }
+
+ switch (r_type)
+ {
+ case R_68K_GOT8:
+ case R_68K_GOT16:
+ case R_68K_GOT32:
+ /* Relocation is to the address of the entry for this symbol
+ in the global offset table. */
+ if (h != NULL
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ break;
+ /* Fall through. */
+ case R_68K_GOT8O:
+ case R_68K_GOT16O:
+ case R_68K_GOT32O:
+ /* Relocation is the offset of the entry for this symbol in
+ the global offset table. */
+
+ {
+ bfd_vma off;
+
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ if (h != NULL)
+ {
+ off = h->got_offset;
+ BFD_ASSERT (off != (bfd_vma) -1);
+
+ if (!elf_hash_table (info)->dynamic_sections_created
+ || (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ {
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally. We must initialize this entry in the
+ global offset table. Since the offset must
+ always be a multiple of 4, we use the least
+ significant bit to record whether we have
+ initialized it already.
+
+ When doing a dynamic link, we create a .rela.got
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation,
+ sgot->contents + off);
+ h->got_offset |= 1;
+ }
+ }
+ }
+ else
+ {
+ BFD_ASSERT (local_got_offsets != NULL
+ && local_got_offsets[r_symndx] != (bfd_vma) -1);
+
+ off = local_got_offsets[r_symndx];
+
+ /* The offset must always be a multiple of 4. We use
+ the least significant bit to record whether we have
+ already generated the necessary reloc. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation, sgot->contents + off);
+
+ if (info->shared)
+ {
+ asection *srelgot;
+ Elf_Internal_Rela outrel;
+
+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ BFD_ASSERT (srelgot != NULL);
+
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + off);
+ outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
+ outrel.r_addend = relocation;
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+ (((Elf32_External_Rela *)
+ srelgot->contents)
+ + srelgot->reloc_count));
+ ++srelgot->reloc_count;
+ }
+
+ local_got_offsets[r_symndx] |= 1;
+ }
+ }
+
+ relocation = sgot->output_offset + off;
+ if (r_type == R_68K_GOT8O
+ || r_type == R_68K_GOT16O
+ || r_type == R_68K_GOT32O)
+ {
+ /* This relocation does not use the addend. */
+ rel->r_addend = 0;
+ }
+ else
+ relocation += sgot->output_section->vma;
+ }
+ break;
+
+ case R_68K_PLT8:
+ case R_68K_PLT16:
+ case R_68K_PLT32:
+ /* Relocation is to the entry for this symbol in the
+ procedure linkage table. */
+
+ /* Resolve a PLTxx reloc against a local symbol directly,
+ without using the procedure linkage table. */
+ if (h == NULL)
+ break;
+
+ if (h->plt_offset == (bfd_vma) -1)
+ {
+ /* We didn't make a PLT entry for this symbol. This
+ happens when statically linking PIC code, or when
+ using -Bsymbolic. */
+ break;
+ }
+
+ if (splt == NULL)
+ {
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL);
+ }
+
+ relocation = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset);
+ break;
+
+ case R_68K_PLT8O:
+ case R_68K_PLT16O:
+ case R_68K_PLT32O:
+ /* Relocation is the offset of the entry for this symbol in
+ the procedure linkage table. */
+ BFD_ASSERT (h != NULL && h->plt_offset == (bfd_vma) -1);
+
+ if (splt == NULL)
+ {
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL);
+ }
+
+ relocation = h->plt_offset;
+
+ /* This relocation does not use the addend. */
+ rel->r_addend = 0;
+
+ break;
+
+ case R_68K_PC8:
+ case R_68K_PC16:
+ case R_68K_PC32:
+ if (h == NULL)
+ break;
+ /* Fall through. */
+ case R_68K_8:
+ case R_68K_16:
+ case R_68K_32:
+ if (info->shared
+ && (input_section->flags & SEC_ALLOC) != 0
+ && ((r_type != R_68K_PC8
+ && r_type != R_68K_PC16
+ && r_type != R_68K_PC32)
+ || (!info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)))
+ {
+ Elf_Internal_Rela outrel;
+ int relocate;
+
+ /* When generating a shared object, these relocations
+ are copied into the output file to be resolved at run
+ time. */
+
+ if (sreloc == NULL)
+ {
+ const char *name;
+
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd,
+ elf_elfheader (input_bfd)->e_shstrndx,
+ elf_section_data (input_section)->rel_hdr.sh_name));
+ if (name == NULL)
+ return false;
+
+ BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+ && strcmp (bfd_get_section_name (input_bfd,
+ input_section),
+ name + 5) == 0);
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ BFD_ASSERT (sreloc != NULL);
+ }
+
+ outrel.r_offset = (rel->r_offset
+ + input_section->output_section->vma
+ + input_section->output_offset);
+ if (h != NULL
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ {
+ BFD_ASSERT (h->dynindx != -1);
+ relocate = false;
+ outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+ outrel.r_addend = relocation + rel->r_addend;
+ }
+ else
+ {
+ if (r_type == R_68K_32)
+ {
+ relocate = true;
+ outrel.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
+ outrel.r_addend = relocation + rel->r_addend;
+ }
+ else
+ {
+ long indx;
+
+ if (h == NULL)
+ sec = local_sections[r_symndx];
+ else
+ {
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || (h->root.type
+ == bfd_link_hash_defweak));
+ sec = h->root.u.def.section;
+ }
+ if (sec != NULL && bfd_is_abs_section (sec))
+ indx = 0;
+ else if (sec == NULL || sec->owner == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ else
+ {
+ asection *osec;
+
+ osec = sec->output_section;
+ indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ abort ();
+ }
+
+ relocate = false;
+ outrel.r_info = ELF32_R_INFO (indx, r_type);
+ outrel.r_addend = relocation + rel->r_addend;
+ }
+ }
+
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+ (((Elf32_External_Rela *)
+ sreloc->contents)
+ + sreloc->reloc_count));
+ ++sreloc->reloc_count;
+
+ /* This reloc will be computed at runtime, so there's no
+ need to do anything now, except for R_68K_32
+ relocations that have been turned into
+ R_68K_RELATIVE. */
+ if (!relocate)
+ continue;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, rel->r_addend);
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ return false;
+ if (*name == '\0')
+ name = bfd_section_name (input_bfd, sec);
+ }
+ if (!(info->callbacks->reloc_overflow
+ (info, name, howto->name, (bfd_vma) 0,
+ input_bfd, input_section, rel->r_offset)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Finish up dynamic symbol handling. We set the contents of various
+ dynamic sections here. */
+
+static boolean
+elf_m68k_finish_dynamic_symbol (output_bfd, info, h, sym)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+{
+ bfd *dynobj;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ if (h->plt_offset != (bfd_vma) -1)
+ {
+ asection *splt;
+ asection *sgot;
+ asection *srela;
+ bfd_vma plt_index;
+ bfd_vma got_offset;
+ Elf_Internal_Rela rela;
+
+ /* This symbol has an entry in the procedure linkage table. Set
+ it up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+ srela = bfd_get_section_by_name (dynobj, ".rela.plt");
+ BFD_ASSERT (splt != NULL && sgot != NULL && srela != NULL);
+
+ /* Get the index in the procedure linkage table which
+ corresponds to this symbol. This is the index of this symbol
+ in all the symbols for which we are making plt entries. The
+ first entry in the procedure linkage table is reserved. */
+ plt_index = h->plt_offset / PLT_ENTRY_SIZE - 1;
+
+ /* Get the offset into the .got table of the entry that
+ corresponds to this function. Each .got entry is 4 bytes.
+ The first three are reserved. */
+ got_offset = (plt_index + 3) * 4;
+
+ /* Fill in the entry in the procedure linkage table. */
+ memcpy (splt->contents + h->plt_offset, elf_m68k_plt_entry,
+ PLT_ENTRY_SIZE);
+ /* The offset is relative to the first extension word. */
+ bfd_put_32 (output_bfd,
+ (sgot->output_section->vma
+ + sgot->output_offset
+ + got_offset
+ - (splt->output_section->vma
+ + h->plt_offset + 2)),
+ splt->contents + h->plt_offset + 4);
+
+ bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
+ splt->contents + h->plt_offset + 10);
+ bfd_put_32 (output_bfd, - (h->plt_offset + 16),
+ splt->contents + h->plt_offset + 16);
+
+ /* Fill in the entry in the global offset table. */
+ bfd_put_32 (output_bfd,
+ (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset
+ + 8),
+ sgot->contents + got_offset);
+
+ /* Fill in the entry in the .rela.plt section. */
+ rela.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + got_offset);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_JMP_SLOT);
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) srela->contents
+ + plt_index));
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ /* Mark the symbol as undefined, rather than as defined in
+ the .plt section. Leave the value alone. */
+ sym->st_shndx = SHN_UNDEF;
+ }
+ }
+
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ asection *sgot;
+ asection *srela;
+ Elf_Internal_Rela rela;
+
+ /* This symbol has an entry in the global offset table. Set it
+ up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ srela = bfd_get_section_by_name (dynobj, ".rela.got");
+ BFD_ASSERT (sgot != NULL && srela != NULL);
+
+ rela.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + (h->got_offset &~ 1));
+
+ /* If this is a -Bsymbolic link, and the symbol is defined
+ locally, we just want to emit a RELATIVE reloc. The entry in
+ the global offset table will already have been initialized in
+ the relocate_section function. */
+ if (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+ {
+ rela.r_info = ELF32_R_INFO (0, R_68K_RELATIVE);
+ rela.r_addend = bfd_get_32 (output_bfd,
+ sgot->contents + (h->got_offset & ~1));
+ }
+ else
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0,
+ sgot->contents + (h->got_offset & ~1));
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_GLOB_DAT);
+ rela.r_addend = 0;
+ }
+
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) srela->contents
+ + srela->reloc_count));
+ ++srela->reloc_count;
+ }
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+ {
+ asection *s;
+ Elf_Internal_Rela rela;
+
+ /* This symbol needs a copy reloc. Set it up. */
+
+ BFD_ASSERT (h->dynindx != -1
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak));
+
+ s = bfd_get_section_by_name (h->root.u.def.section->owner,
+ ".rela.bss");
+ BFD_ASSERT (s != NULL);
+
+ rela.r_offset = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_68K_COPY);
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) s->contents
+ + s->reloc_count));
+ ++s->reloc_count;
+ }
+
+ /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
+ if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+ || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ sym->st_shndx = SHN_ABS;
+
+ return true;
+}
+
+/* Finish up the dynamic sections. */
+
+static boolean
+elf_m68k_finish_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *sgot;
+ asection *sdyn;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ sgot = bfd_get_section_by_name (dynobj, ".got.plt");
+ BFD_ASSERT (sgot != NULL);
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ asection *splt;
+ Elf32_External_Dyn *dyncon, *dynconend;
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL && sdyn != NULL);
+
+ dyncon = (Elf32_External_Dyn *) sdyn->contents;
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ asection *s;
+
+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ default:
+ break;
+
+ case DT_PLTGOT:
+ name = ".got";
+ goto get_vma;
+ case DT_JMPREL:
+ name = ".rela.plt";
+ get_vma:
+ s = bfd_get_section_by_name (output_bfd, name);
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_ptr = s->vma;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_PLTRELSZ:
+ s = bfd_get_section_by_name (output_bfd, ".rela.plt");
+ BFD_ASSERT (s != NULL);
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val = s->_cooked_size;
+ else
+ dyn.d_un.d_val = s->_raw_size;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_RELASZ:
+ /* The procedure linkage table relocs (DT_JMPREL) should
+ not be included in the overall relocs (DT_RELA).
+ Therefore, we override the DT_RELASZ entry here to
+ make it not include the JMPREL relocs. Since the
+ linker script arranges for .rela.plt to follow all
+ other relocation sections, we don't have to worry
+ about changing the DT_RELA entry. */
+ s = bfd_get_section_by_name (output_bfd, ".rela.plt");
+ if (s != NULL)
+ {
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val -= s->_cooked_size;
+ else
+ dyn.d_un.d_val -= s->_raw_size;
+ }
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+ }
+ }
+
+ /* Fill in the first entry in the procedure linkage table. */
+ if (splt->_raw_size > 0)
+ {
+ memcpy (splt->contents, elf_m68k_plt0_entry, PLT_ENTRY_SIZE);
+ bfd_put_32 (output_bfd,
+ (sgot->output_section->vma
+ + sgot->output_offset + 4
+ - (splt->output_section->vma + 2)),
+ splt->contents + 4);
+ bfd_put_32 (output_bfd,
+ (sgot->output_section->vma
+ + sgot->output_offset + 8
+ - (splt->output_section->vma + 10)),
+ splt->contents + 12);
+ }
+
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize
+ = PLT_ENTRY_SIZE;
+ }
+
+ /* Fill in the first three entries in the global offset table. */
+ if (sgot->_raw_size > 0)
+ {
+ if (sdyn == NULL)
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
+ else
+ bfd_put_32 (output_bfd,
+ sdyn->output_section->vma + sdyn->output_offset,
+ sgot->contents);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 4);
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + 8);
+ }
+
+ elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
+
+ return true;
+}
+
+#define TARGET_BIG_SYM bfd_elf32_m68k_vec
+#define TARGET_BIG_NAME "elf32-m68k"
+#define ELF_MACHINE_CODE EM_68K
+#define ELF_MAXPAGESIZE 0x2000
+#define elf_backend_create_dynamic_sections \
+ _bfd_elf_create_dynamic_sections
+#define elf_backend_check_relocs elf_m68k_check_relocs
+#define elf_backend_adjust_dynamic_symbol \
+ elf_m68k_adjust_dynamic_symbol
+#define elf_backend_size_dynamic_sections \
+ elf_m68k_size_dynamic_sections
+#define elf_backend_relocate_section elf_m68k_relocate_section
+#define elf_backend_finish_dynamic_symbol \
+ elf_m68k_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections \
+ elf_m68k_finish_dynamic_sections
+#define elf_backend_want_got_plt 1
+#define elf_backend_plt_readonly 1
+#define elf_backend_want_plt_sym 0
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-m88k.c b/contrib/gdb/bfd/elf32-m88k.c
new file mode 100644
index 0000000..f3c535e
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-m88k.c
@@ -0,0 +1,35 @@
+/* Motorola 88k-specific support for 32-bit ELF
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+/* This does not include any relocations, but should be good enough
+ for GDB. */
+
+#define TARGET_BIG_SYM bfd_elf32_m88k_vec
+#define TARGET_BIG_NAME "elf32-m88k"
+#define ELF_ARCH bfd_arch_m88k
+#define ELF_MACHINE_CODE EM_88K
+#define bfd_elf32_bfd_reloc_type_lookup bfd_default_reloc_type_lookup
+#define elf_info_to_howto _bfd_elf_no_info_to_howto
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-mips.c b/contrib/gdb/bfd/elf32-mips.c
new file mode 100644
index 0000000..ced0000
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-mips.c
@@ -0,0 +1,5867 @@
+/* MIPS-specific support for 32-bit ELF
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+ Most of the information added by Ian Lance Taylor, Cygnus Support,
+ <ian@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file handles MIPS ELF targets. SGI Irix 5 uses a slightly
+ different MIPS ELF from other targets. This matters when linking.
+ This file supports both, switching at runtime. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "genlink.h"
+#include "elf-bfd.h"
+#include "elf/mips.h"
+
+/* Get the ECOFF swapping routines. */
+#include "coff/sym.h"
+#include "coff/symconst.h"
+#include "coff/internal.h"
+#include "coff/ecoff.h"
+#include "coff/mips.h"
+#define ECOFF_32
+#include "ecoffswap.h"
+
+static bfd_reloc_status_type mips_elf_hi16_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_elf_got16_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_elf_lo16_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_elf_gprel16_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static bfd_reloc_status_type mips_elf_gprel32_reloc PARAMS ((bfd *abfd,
+ arelent *reloc,
+ asymbol *symbol,
+ PTR data,
+ asection *section,
+ bfd *output_bfd,
+ char **error));
+static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static void mips_info_to_howto_rel
+ PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
+static void bfd_mips_elf32_swap_gptab_in
+ PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));
+static void bfd_mips_elf32_swap_gptab_out
+ PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));
+static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *));
+static boolean mips_elf_object_p PARAMS ((bfd *));
+static boolean mips_elf_create_procedure_table
+ PARAMS ((PTR, bfd *, struct bfd_link_info *, asection *,
+ struct ecoff_debug_info *));
+static int mips_elf_additional_program_headers PARAMS ((bfd *));
+static boolean mips_elf_modify_segment_map PARAMS ((bfd *));
+static void mips_elf_final_write_processing
+ PARAMS ((bfd *, boolean));
+static boolean mips_elf_set_private_flags PARAMS ((bfd *, flagword));
+static boolean mips_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean mips_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean mips_elf_section_from_shdr
+ PARAMS ((bfd *, Elf32_Internal_Shdr *, char *));
+static boolean mips_elf_fake_sections
+ PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *));
+static boolean mips_elf_section_from_bfd_section
+ PARAMS ((bfd *, Elf32_Internal_Shdr *, asection *, int *));
+static boolean mips_elf_section_processing
+ PARAMS ((bfd *, Elf32_Internal_Shdr *));
+static void mips_elf_symbol_processing PARAMS ((bfd *, asymbol *));
+static boolean mips_elf_read_ecoff_info
+ PARAMS ((bfd *, asection *, struct ecoff_debug_info *));
+static boolean mips_elf_is_local_label
+ PARAMS ((bfd *, asymbol *));
+static boolean mips_elf_find_nearest_line
+ PARAMS ((bfd *, asection *, asymbol **, bfd_vma, const char **,
+ const char **, unsigned int *));
+static struct bfd_hash_entry *mips_elf_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static struct bfd_link_hash_table *mips_elf_link_hash_table_create
+ PARAMS ((bfd *));
+static int gptab_compare PARAMS ((const void *, const void *));
+static boolean mips_elf_final_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+static void mips_elf_relocate_hi16
+ PARAMS ((bfd *, Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_byte *,
+ bfd_vma));
+static void mips_elf_relocate_got_local
+ PARAMS ((bfd *, bfd *, asection *, Elf_Internal_Rela *,
+ Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static void mips_elf_relocate_global_got
+ PARAMS ((bfd *, Elf_Internal_Rela *, bfd_byte *, bfd_vma));
+static boolean mips_elf_adjust_dynindx
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean mips_elf_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean mips_elf_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean mips_elf_create_compact_rel_section
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean mips_elf_create_got_section
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean mips_elf_check_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
+static boolean mips_elf_adjust_dynamic_symbol
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static boolean mips_elf_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean mips_elf_finish_dynamic_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
+static boolean mips_elf_finish_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean mips_elf_add_symbol_hook
+ PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Sym *,
+ const char **, flagword *, asection **, bfd_vma *));
+static bfd_reloc_status_type mips_elf_final_gp
+ PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));
+static bfd_byte *elf32_mips_get_relocated_section_contents
+ PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
+ bfd_byte *, boolean, asymbol **));
+
+/* This is true for Irix 5 executables, false for normal MIPS ELF ABI
+ executables. FIXME: At the moment, we default to always generating
+ Irix 5 executables. */
+
+#define SGI_COMPAT(abfd) (1)
+
+/* This structure is used to hold .got information when linking. It
+ is stored in the tdata field of the bfd_elf_section_data structure. */
+
+struct mips_got_info
+{
+ /* The symbol index of the first global .got symbol. */
+ unsigned long global_gotsym;
+ /* The number of local .got entries. */
+ unsigned int local_gotno;
+};
+
+/* The number of local .got entries we reserve. */
+#define MIPS_RESERVED_GOTNO (2)
+
+/* Instructions which appear in a stub. For some reason the stub is
+ slightly different on an SGI system. */
+#define ELF_MIPS_GP_OFFSET(abfd) (SGI_COMPAT (abfd) ? 0x7ff0 : 0x8000)
+#define STUB_LW(abfd) \
+ (SGI_COMPAT (abfd) \
+ ? 0x8f998010 /* lw t9,0x8010(gp) */ \
+ : 0x8f998000) /* lw t9,0x8000(gp) */
+#define STUB_MOVE 0x03e07825 /* move t7,ra */
+#define STUB_JALR 0x0320f809 /* jal t9 */
+#define STUB_LI16 0x34180000 /* ori t8,zero,0 */
+#define MIPS_FUNCTION_STUB_SIZE (16)
+
+/* Names of sections which appear in the .dynsym section in an Irix 5
+ executable. */
+
+static const char * const mips_elf_dynsym_sec_names[] =
+{
+ ".text",
+ ".init",
+ ".fini",
+ ".data",
+ ".rodata",
+ ".sdata",
+ ".sbss",
+ ".bss",
+ NULL
+};
+
+#define SIZEOF_MIPS_DYNSYM_SECNAMES \
+ (sizeof mips_elf_dynsym_sec_names / sizeof mips_elf_dynsym_sec_names[0])
+
+/* The number of entries in mips_elf_dynsym_sec_names which go in the
+ text segment. */
+
+#define MIPS_TEXT_DYNSYM_SECNO (3)
+
+/* The names of the runtime procedure table symbols used on Irix 5. */
+
+static const char * const mips_elf_dynsym_rtproc_names[] =
+{
+ "_procedure_table",
+ "_procedure_string_table",
+ "_procedure_table_size",
+ NULL
+};
+
+/* These structures are used to generate the .compact_rel section on
+ Irix 5. */
+
+typedef struct
+{
+ unsigned long id1; /* Always one? */
+ unsigned long num; /* Number of compact relocation entries. */
+ unsigned long id2; /* Always two? */
+ unsigned long offset; /* The file offset of the first relocation. */
+ unsigned long reserved0; /* Zero? */
+ unsigned long reserved1; /* Zero? */
+} Elf32_compact_rel;
+
+typedef struct
+{
+ bfd_byte id1[4];
+ bfd_byte num[4];
+ bfd_byte id2[4];
+ bfd_byte offset[4];
+ bfd_byte reserved0[4];
+ bfd_byte reserved1[4];
+} Elf32_External_compact_rel;
+
+typedef struct
+{
+ unsigned int ctype : 1; /* 1: long 0: short format. See below. */
+ unsigned int rtype : 4; /* Relocation types. See below. */
+ unsigned int dist2to : 8;
+ unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */
+ unsigned long konst; /* KONST field. See below. */
+ unsigned long vaddr; /* VADDR to be relocated. */
+} Elf32_crinfo;
+
+typedef struct
+{
+ unsigned int ctype : 1; /* 1: long 0: short format. See below. */
+ unsigned int rtype : 4; /* Relocation types. See below. */
+ unsigned int dist2to : 8;
+ unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */
+ unsigned long konst; /* KONST field. See below. */
+} Elf32_crinfo2;
+
+typedef struct
+{
+ bfd_byte info[4];
+ bfd_byte konst[4];
+ bfd_byte vaddr[4];
+} Elf32_External_crinfo;
+
+typedef struct
+{
+ bfd_byte info[4];
+ bfd_byte konst[4];
+} Elf32_External_crinfo2;
+
+/* These are the constants used to swap the bitfields in a crinfo. */
+
+#define CRINFO_CTYPE (0x1)
+#define CRINFO_CTYPE_SH (31)
+#define CRINFO_RTYPE (0xf)
+#define CRINFO_RTYPE_SH (27)
+#define CRINFO_DIST2TO (0xff)
+#define CRINFO_DIST2TO_SH (19)
+#define CRINFO_RELVADDR (0x7ffff)
+#define CRINFO_RELVADDR_SH (0)
+
+/* A compact relocation info has long (3 words) or short (2 words)
+ formats. A short format doesn't have VADDR field and relvaddr
+ fields contains ((VADDR - vaddr of the previous entry) >> 2). */
+#define CRF_MIPS_LONG 1
+#define CRF_MIPS_SHORT 0
+
+/* There are 4 types of compact relocation at least. The value KONST
+ has different meaning for each type:
+
+ (type) (konst)
+ CT_MIPS_REL32 Address in data
+ CT_MIPS_WORD Address in word (XXX)
+ CT_MIPS_GPHI_LO GP - vaddr
+ CT_MIPS_JMPAD Address to jump
+ */
+
+#define CRT_MIPS_REL32 0xa
+#define CRT_MIPS_WORD 0xb
+#define CRT_MIPS_GPHI_LO 0xc
+#define CRT_MIPS_JMPAD 0xd
+
+#define mips_elf_set_cr_format(x,format) ((x).ctype = (format))
+#define mips_elf_set_cr_type(x,type) ((x).rtype = (type))
+#define mips_elf_set_cr_dist2to(x,v) ((x).dist2to = (v))
+#define mips_elf_set_cr_relvaddr(x,d) ((x).relvaddr = (d)<<2)
+
+static void bfd_elf32_swap_compact_rel_out
+ PARAMS ((bfd *, const Elf32_compact_rel *, Elf32_External_compact_rel *));
+static void bfd_elf32_swap_crinfo_out
+ PARAMS ((bfd *, const Elf32_crinfo *, Elf32_External_crinfo *));
+
+#define USE_REL 1 /* MIPS uses REL relocations instead of RELA */
+
+enum reloc_type
+{
+ R_MIPS_NONE = 0,
+ R_MIPS_16, R_MIPS_32,
+ R_MIPS_REL32, R_MIPS_26,
+ R_MIPS_HI16, R_MIPS_LO16,
+ R_MIPS_GPREL16, R_MIPS_LITERAL,
+ R_MIPS_GOT16, R_MIPS_PC16,
+ R_MIPS_CALL16, R_MIPS_GPREL32,
+ /* The remaining relocs are defined on Irix, although they are not
+ in the MIPS ELF ABI. */
+ R_MIPS_UNUSED1, R_MIPS_UNUSED2,
+ R_MIPS_UNUSED3,
+ R_MIPS_SHIFT5, R_MIPS_SHIFT6,
+ R_MIPS_64, R_MIPS_GOT_DISP,
+ R_MIPS_GOT_PAGE, R_MIPS_GOT_OFST,
+ R_MIPS_GOT_HI16, R_MIPS_GOT_LO16,
+ R_MIPS_SUB, R_MIPS_INSERT_A,
+ R_MIPS_INSERT_B, R_MIPS_DELETE,
+ R_MIPS_HIGHER, R_MIPS_HIGHEST,
+ R_MIPS_CALL_HI16, R_MIPS_CALL_LO16,
+ R_MIPS_max
+};
+
+static reloc_howto_type elf_mips_howto_table[] =
+{
+ /* No relocation. */
+ HOWTO (R_MIPS_NONE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_NONE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit relocation. */
+ HOWTO (R_MIPS_16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit relocation. */
+ HOWTO (R_MIPS_32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit symbol relative relocation. */
+ HOWTO (R_MIPS_REL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_REL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 26 bit branch address. */
+ HOWTO (R_MIPS_26, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ /* This needs complex overflow
+ detection, because the upper four
+ bits must match the PC. */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_26", /* name */
+ true, /* partial_inplace */
+ 0x3ffffff, /* src_mask */
+ 0x3ffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of symbol value. */
+ HOWTO (R_MIPS_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ mips_elf_hi16_reloc, /* special_function */
+ "R_MIPS_HI16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of symbol value. */
+ HOWTO (R_MIPS_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ mips_elf_lo16_reloc, /* special_function */
+ "R_MIPS_LO16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* GP relative reference. */
+ HOWTO (R_MIPS_GPREL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_elf_gprel16_reloc, /* special_function */
+ "R_MIPS_GPREL16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reference to literal section. */
+ HOWTO (R_MIPS_LITERAL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_elf_gprel16_reloc, /* special_function */
+ "R_MIPS_LITERAL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Reference to global offset table. */
+ HOWTO (R_MIPS_GOT16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ mips_elf_got16_reloc, /* special_function */
+ "R_MIPS_GOT16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit PC relative reference. */
+ HOWTO (R_MIPS_PC16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_PC16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit call through global offset table. */
+ /* FIXME: This is not handled correctly. */
+ HOWTO (R_MIPS_CALL16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit GP relative reference. */
+ HOWTO (R_MIPS_GPREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ mips_elf_gprel32_reloc, /* special_function */
+ "R_MIPS_GPREL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The remaining relocs are defined on Irix 5, although they are
+ not defined by the ABI. */
+ { 13 },
+ { 14 },
+ { 15 },
+
+ /* A 5 bit shift field. */
+ HOWTO (R_MIPS_SHIFT5, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 5, /* bitsize */
+ false, /* pc_relative */
+ 6, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SHIFT5", /* name */
+ true, /* partial_inplace */
+ 0x000007c0, /* src_mask */
+ 0x000007c0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 6 bit shift field. */
+ /* FIXME: This is not handled correctly; a special function is
+ needed to put the most significant bit in the right place. */
+ HOWTO (R_MIPS_SHIFT6, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 6, /* bitsize */
+ false, /* pc_relative */
+ 6, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_SHIFT6", /* name */
+ true, /* partial_inplace */
+ 0x000007c4, /* src_mask */
+ 0x000007c4, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 64 bit relocation. Presumably not used in 32 bit ELF. */
+ { R_MIPS_64 },
+
+ /* Displacement in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_DISP, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_DISP", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Displacement to page pointer in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_PAGE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_PAGE", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Offset from page pointer in the global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_OFST, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_OFST", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* High 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_GOT_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_GOT_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 64 bit subtraction. Presumably not used in 32 bit ELF. */
+ { R_MIPS_SUB },
+
+ /* Used to cause the linker to insert and delete instructions? */
+ { R_MIPS_INSERT_A },
+ { R_MIPS_INSERT_B },
+ { R_MIPS_DELETE },
+
+ /* Get the higher values of a 64 bit addend. Presumably not used in
+ 32 bit ELF. */
+ { R_MIPS_HIGHER },
+ { R_MIPS_HIGHEST },
+
+ /* High 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_CALL_HI16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL_HI16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Low 16 bits of displacement in global offset table. */
+ /* FIXME: Not handled correctly. */
+ HOWTO (R_MIPS_CALL_LO16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_MIPS_CALL_LO16", /* name */
+ true, /* partial_inplace */
+ 0x0000ffff, /* src_mask */
+ 0x0000ffff, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+/* Do a R_MIPS_HI16 relocation. This has to be done in combination
+ with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to
+ the HI16. Here we just save the information we need; we do the
+ actual relocation when we see the LO16. MIPS ELF requires that the
+ LO16 immediately follow the HI16, so this ought to work. */
+
+static bfd_byte *mips_hi16_addr;
+static bfd_vma mips_hi16_addend;
+
+static bfd_reloc_status_type
+mips_elf_hi16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_reloc_status_type ret;
+ bfd_vma relocation;
+
+ /* If we're relocating, and this an external symbol, we don't want
+ to change anything. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ ret = bfd_reloc_ok;
+
+ if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
+ {
+ boolean relocateable;
+ bfd_vma gp;
+
+ if (ret == bfd_reloc_undefined)
+ abort ();
+
+ if (output_bfd != NULL)
+ relocateable = true;
+ else
+ {
+ relocateable = false;
+ output_bfd = symbol->section->output_section->owner;
+ }
+
+ ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
+ error_message, &gp);
+ if (ret != bfd_reloc_ok)
+ return ret;
+
+ relocation = gp - reloc_entry->address;
+ }
+ else
+ {
+ if (bfd_is_und_section (symbol->section)
+ && output_bfd == (bfd *) NULL)
+ ret = bfd_reloc_undefined;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+ }
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Save the information, and let LO16 do the actual relocation. */
+ mips_hi16_addr = (bfd_byte *) data + reloc_entry->address;
+ mips_hi16_addend = relocation;
+
+ if (output_bfd != (bfd *) NULL)
+ reloc_entry->address += input_section->output_offset;
+
+ return ret;
+}
+
+/* Do a R_MIPS_LO16 relocation. This is a straightforward 16 bit
+ inplace relocation; this function exists in order to do the
+ R_MIPS_HI16 relocation described above. */
+
+static bfd_reloc_status_type
+mips_elf_lo16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ arelent gp_disp_relent;
+
+ if (mips_hi16_addr != (bfd_byte *) NULL)
+ {
+ unsigned long insn;
+ unsigned long val;
+ unsigned long vallo;
+
+ /* Do the HI16 relocation. Note that we actually don't need to
+ know anything about the LO16 itself, except where to find the
+ low 16 bits of the addend needed by the LO16. */
+ insn = bfd_get_32 (abfd, mips_hi16_addr);
+ vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
+ & 0xffff);
+ val = ((insn & 0xffff) << 16) + vallo;
+ val += mips_hi16_addend;
+
+ /* The low order 16 bits are always treated as a signed value.
+ Therefore, a negative value in the low order bits requires an
+ adjustment in the high order bits. We need to make this
+ adjustment in two ways: once for the bits we took from the
+ data, and once for the bits we are putting back in to the
+ data. */
+ if ((vallo & 0x8000) != 0)
+ val -= 0x10000;
+ if ((val & 0x8000) != 0)
+ val += 0x10000;
+
+ insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
+ bfd_put_32 (abfd, insn, mips_hi16_addr);
+
+ mips_hi16_addr = (bfd_byte *) NULL;
+
+ if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
+ {
+ gp_disp_relent = *reloc_entry;
+ reloc_entry = &gp_disp_relent;
+ reloc_entry->addend = mips_hi16_addend;
+ }
+ }
+ else if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0)
+ {
+ bfd_reloc_status_type ret;
+ bfd_vma gp, relocation;
+
+ /* FIXME: Does this case ever occur? */
+
+ ret = mips_elf_final_gp (output_bfd, symbol, true, error_message, &gp);
+ if (ret != bfd_reloc_ok)
+ return ret;
+
+ relocation = gp - reloc_entry->address;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ gp_disp_relent = *reloc_entry;
+ reloc_entry = &gp_disp_relent;
+ reloc_entry->addend = relocation - 4;
+ }
+
+ /* Now do the LO16 reloc in the usual way. */
+ return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+}
+
+/* Do a R_MIPS_GOT16 reloc. This is a reloc against the global offset
+ table used for PIC code. If the symbol is an external symbol, the
+ instruction is modified to contain the offset of the appropriate
+ entry in the global offset table. If the symbol is a section
+ symbol, the next reloc is a R_MIPS_LO16 reloc. The two 16 bit
+ addends are combined to form the real addend against the section
+ symbol; the GOT16 is modified to contain the offset of an entry in
+ the global offset table, and the LO16 is modified to offset it
+ appropriately. Thus an offset larger than 16 bits requires a
+ modified value in the global offset table.
+
+ This implementation suffices for the assembler, but the linker does
+ not yet know how to create global offset tables. */
+
+static bfd_reloc_status_type
+mips_elf_got16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* If we're relocating, and this an external symbol, we don't want
+ to change anything. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* If we're relocating, and this is a local symbol, we can handle it
+ just like HI16. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) != 0)
+ return mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd, error_message);
+
+ abort ();
+}
+
+/* We have to figure out the gp value, so that we can adjust the
+ symbol value correctly. We look up the symbol _gp in the output
+ BFD. If we can't find it, we're stuck. We cache it in the ELF
+ target data. We don't need to adjust the symbol value for an
+ external symbol if we are producing relocateable output. */
+
+static bfd_reloc_status_type
+mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, pgp)
+ bfd *output_bfd;
+ asymbol *symbol;
+ boolean relocateable;
+ char **error_message;
+ bfd_vma *pgp;
+{
+ if (bfd_is_und_section (symbol->section)
+ && ! relocateable)
+ {
+ *pgp = 0;
+ return bfd_reloc_undefined;
+ }
+
+ *pgp = _bfd_get_gp_value (output_bfd);
+ if (*pgp == 0
+ && (! relocateable
+ || (symbol->flags & BSF_SECTION_SYM) != 0))
+ {
+ if (relocateable)
+ {
+ /* Make up a value. */
+ *pgp = symbol->section->output_section->vma + 0x4000;
+ _bfd_set_gp_value (output_bfd, *pgp);
+ }
+ else
+ {
+ unsigned int count;
+ asymbol **sym;
+ unsigned int i;
+
+ count = bfd_get_symcount (output_bfd);
+ sym = bfd_get_outsymbols (output_bfd);
+
+ if (sym == (asymbol **) NULL)
+ i = count;
+ else
+ {
+ for (i = 0; i < count; i++, sym++)
+ {
+ register CONST char *name;
+
+ name = bfd_asymbol_name (*sym);
+ if (*name == '_' && strcmp (name, "_gp") == 0)
+ {
+ *pgp = bfd_asymbol_value (*sym);
+ _bfd_set_gp_value (output_bfd, *pgp);
+ break;
+ }
+ }
+ }
+
+ if (i >= count)
+ {
+ /* Only get the error once. */
+ *pgp = 4;
+ _bfd_set_gp_value (output_bfd, *pgp);
+ *error_message =
+ (char *) "GP relative relocation when _gp not defined";
+ return bfd_reloc_dangerous;
+ }
+ }
+ }
+
+ return bfd_reloc_ok;
+}
+
+/* Do a R_MIPS_GPREL16 relocation. This is a 16 bit value which must
+ become the offset from the gp register. This function also handles
+ R_MIPS_LITERAL relocations, although those can be handled more
+ cleverly because the entries in the .lit8 and .lit4 sections can be
+ merged. */
+
+static bfd_reloc_status_type gprel16_with_gp PARAMS ((bfd *, asymbol *,
+ arelent *, asection *,
+ boolean, PTR, bfd_vma));
+
+static bfd_reloc_status_type
+mips_elf_gprel16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ boolean relocateable;
+ bfd_reloc_status_type ret;
+ bfd_vma gp;
+
+ /* If we're relocating, and this is an external symbol with no
+ addend, we don't want to change anything. We will only have an
+ addend if this is a newly created reloc, not read from an ELF
+ file. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (output_bfd != (bfd *) NULL)
+ relocateable = true;
+ else
+ {
+ relocateable = false;
+ output_bfd = symbol->section->output_section->owner;
+ }
+
+ ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message,
+ &gp);
+ if (ret != bfd_reloc_ok)
+ return ret;
+
+ return gprel16_with_gp (abfd, symbol, reloc_entry, input_section,
+ relocateable, data, gp);
+}
+
+static bfd_reloc_status_type
+gprel16_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
+ gp)
+ bfd *abfd;
+ asymbol *symbol;
+ arelent *reloc_entry;
+ asection *input_section;
+ boolean relocateable;
+ PTR data;
+ bfd_vma gp;
+{
+ bfd_vma relocation;
+ unsigned long insn;
+ unsigned long val;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+
+ /* Set val to the offset into the section or symbol. */
+ val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
+ if (val & 0x8000)
+ val -= 0x10000;
+
+ /* Adjust val for the final section location and GP value. If we
+ are producing relocateable output, we don't want to do this for
+ an external symbol. */
+ if (! relocateable
+ || (symbol->flags & BSF_SECTION_SYM) != 0)
+ val += relocation - gp;
+
+ insn = (insn &~ 0xffff) | (val & 0xffff);
+ bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
+
+ if (relocateable)
+ reloc_entry->address += input_section->output_offset;
+
+ /* Make sure it fit in 16 bits. */
+ if (val >= 0x8000 && val < 0xffff8000)
+ return bfd_reloc_overflow;
+
+ return bfd_reloc_ok;
+}
+
+/* Do a R_MIPS_GPREL32 relocation. Is this 32 bit value the offset
+ from the gp register? XXX */
+
+static bfd_reloc_status_type gprel32_with_gp PARAMS ((bfd *, asymbol *,
+ arelent *, asection *,
+ boolean, PTR, bfd_vma));
+
+static bfd_reloc_status_type
+mips_elf_gprel32_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ boolean relocateable;
+ bfd_reloc_status_type ret;
+ bfd_vma gp;
+
+ /* If we're relocating, and this is an external symbol with no
+ addend, we don't want to change anything. We will only have an
+ addend if this is a newly created reloc, not read from an ELF
+ file. */
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && reloc_entry->addend == 0)
+ {
+ *error_message = (char *)
+ "32bits gp relative relocation occurs for an external symbol";
+ return bfd_reloc_outofrange;
+ }
+
+ if (output_bfd != (bfd *) NULL)
+ {
+ relocateable = true;
+ gp = _bfd_get_gp_value (output_bfd);
+ }
+ else
+ {
+ relocateable = false;
+ output_bfd = symbol->section->output_section->owner;
+
+ ret = mips_elf_final_gp (output_bfd, symbol, relocateable,
+ error_message, &gp);
+ if (ret != bfd_reloc_ok)
+ return ret;
+ }
+
+ return gprel32_with_gp (abfd, symbol, reloc_entry, input_section,
+ relocateable, data, gp);
+}
+
+static bfd_reloc_status_type
+gprel32_with_gp (abfd, symbol, reloc_entry, input_section, relocateable, data,
+ gp)
+ bfd *abfd;
+ asymbol *symbol;
+ arelent *reloc_entry;
+ asection *input_section;
+ boolean relocateable;
+ PTR data;
+ bfd_vma gp;
+{
+ bfd_vma relocation;
+ unsigned long val;
+
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ val = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
+
+ /* Set val to the offset into the section or symbol. */
+ val += reloc_entry->addend;
+
+ /* Adjust val for the final section location and GP value. If we
+ are producing relocateable output, we don't want to do this for
+ an external symbol. */
+ if (! relocateable
+ || (symbol->flags & BSF_SECTION_SYM) != 0)
+ val += relocation - gp;
+
+ bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address);
+
+ if (relocateable)
+ reloc_entry->address += input_section->output_offset;
+
+ return bfd_reloc_ok;
+}
+
+/* A mapping from BFD reloc types to MIPS ELF reloc types. */
+
+struct elf_reloc_map {
+ bfd_reloc_code_real_type bfd_reloc_val;
+ enum reloc_type elf_reloc_val;
+};
+
+static CONST struct elf_reloc_map mips_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_MIPS_NONE, },
+ { BFD_RELOC_16, R_MIPS_16 },
+ { BFD_RELOC_32, R_MIPS_32 },
+ { BFD_RELOC_CTOR, R_MIPS_32 },
+ { BFD_RELOC_32_PCREL, R_MIPS_REL32 },
+ { BFD_RELOC_MIPS_JMP, R_MIPS_26 },
+ { BFD_RELOC_HI16_S, R_MIPS_HI16 },
+ { BFD_RELOC_LO16, R_MIPS_LO16 },
+ { BFD_RELOC_MIPS_GPREL, R_MIPS_GPREL16 },
+ { BFD_RELOC_MIPS_LITERAL, R_MIPS_LITERAL },
+ { BFD_RELOC_MIPS_GOT16, R_MIPS_GOT16 },
+ { BFD_RELOC_16_PCREL, R_MIPS_PC16 },
+ { BFD_RELOC_MIPS_CALL16, R_MIPS_CALL16 },
+ { BFD_RELOC_MIPS_GPREL32, R_MIPS_GPREL32 },
+ { BFD_RELOC_MIPS_GOT_HI16, R_MIPS_GOT_HI16 },
+ { BFD_RELOC_MIPS_GOT_LO16, R_MIPS_GOT_LO16 },
+ { BFD_RELOC_MIPS_CALL_HI16, R_MIPS_CALL_HI16 },
+ { BFD_RELOC_MIPS_CALL_LO16, R_MIPS_CALL_LO16 }
+};
+
+/* Given a BFD reloc type, return a howto structure. */
+
+static reloc_howto_type *
+bfd_elf32_bfd_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (mips_reloc_map) / sizeof (struct elf_reloc_map); i++)
+ {
+ if (mips_reloc_map[i].bfd_reloc_val == code)
+ return &elf_mips_howto_table[(int) mips_reloc_map[i].elf_reloc_val];
+ }
+ return NULL;
+}
+
+/* Given a MIPS reloc type, fill in an arelent structure. */
+
+static void
+mips_info_to_howto_rel (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf32_Internal_Rel *dst;
+{
+ unsigned int r_type;
+
+ r_type = ELF32_R_TYPE (dst->r_info);
+ BFD_ASSERT (r_type < (unsigned int) R_MIPS_max);
+ cache_ptr->howto = &elf_mips_howto_table[r_type];
+
+ /* The addend for a GPREL16 or LITERAL relocation comes from the GP
+ value for the object file. We get the addend now, rather than
+ when we do the relocation, because the symbol manipulations done
+ by the linker may cause us to lose track of the input BFD. */
+ if (((*cache_ptr->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0
+ && (r_type == (unsigned int) R_MIPS_GPREL16
+ || r_type == (unsigned int) R_MIPS_LITERAL))
+ cache_ptr->addend = elf_gp (abfd);
+}
+
+/* A .reginfo section holds a single Elf32_RegInfo structure. These
+ routines swap this structure in and out. They are used outside of
+ BFD, so they are globally visible. */
+
+void
+bfd_mips_elf32_swap_reginfo_in (abfd, ex, in)
+ bfd *abfd;
+ const Elf32_External_RegInfo *ex;
+ Elf32_RegInfo *in;
+{
+ in->ri_gprmask = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gprmask);
+ in->ri_cprmask[0] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[0]);
+ in->ri_cprmask[1] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[1]);
+ in->ri_cprmask[2] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[2]);
+ in->ri_cprmask[3] = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_cprmask[3]);
+ in->ri_gp_value = bfd_h_get_32 (abfd, (bfd_byte *) ex->ri_gp_value);
+}
+
+void
+bfd_mips_elf32_swap_reginfo_out (abfd, in, ex)
+ bfd *abfd;
+ const Elf32_RegInfo *in;
+ Elf32_External_RegInfo *ex;
+{
+ bfd_h_put_32 (abfd, (bfd_vma) in->ri_gprmask,
+ (bfd_byte *) ex->ri_gprmask);
+ bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[0],
+ (bfd_byte *) ex->ri_cprmask[0]);
+ bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[1],
+ (bfd_byte *) ex->ri_cprmask[1]);
+ bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[2],
+ (bfd_byte *) ex->ri_cprmask[2]);
+ bfd_h_put_32 (abfd, (bfd_vma) in->ri_cprmask[3],
+ (bfd_byte *) ex->ri_cprmask[3]);
+ bfd_h_put_32 (abfd, (bfd_vma) in->ri_gp_value,
+ (bfd_byte *) ex->ri_gp_value);
+}
+
+/* Swap an entry in a .gptab section. Note that these routines rely
+ on the equivalence of the two elements of the union. */
+
+static void
+bfd_mips_elf32_swap_gptab_in (abfd, ex, in)
+ bfd *abfd;
+ const Elf32_External_gptab *ex;
+ Elf32_gptab *in;
+{
+ in->gt_entry.gt_g_value = bfd_h_get_32 (abfd, ex->gt_entry.gt_g_value);
+ in->gt_entry.gt_bytes = bfd_h_get_32 (abfd, ex->gt_entry.gt_bytes);
+}
+
+static void
+bfd_mips_elf32_swap_gptab_out (abfd, in, ex)
+ bfd *abfd;
+ const Elf32_gptab *in;
+ Elf32_External_gptab *ex;
+{
+ bfd_h_put_32 (abfd, (bfd_vma) in->gt_entry.gt_g_value,
+ ex->gt_entry.gt_g_value);
+ bfd_h_put_32 (abfd, (bfd_vma) in->gt_entry.gt_bytes,
+ ex->gt_entry.gt_bytes);
+}
+
+static void
+bfd_elf32_swap_compact_rel_out (abfd, in, ex)
+ bfd *abfd;
+ const Elf32_compact_rel *in;
+ Elf32_External_compact_rel *ex;
+{
+ bfd_h_put_32 (abfd, (bfd_vma) in->id1, ex->id1);
+ bfd_h_put_32 (abfd, (bfd_vma) in->num, ex->num);
+ bfd_h_put_32 (abfd, (bfd_vma) in->id2, ex->id2);
+ bfd_h_put_32 (abfd, (bfd_vma) in->offset, ex->offset);
+ bfd_h_put_32 (abfd, (bfd_vma) in->reserved0, ex->reserved0);
+ bfd_h_put_32 (abfd, (bfd_vma) in->reserved1, ex->reserved1);
+}
+
+static void
+bfd_elf32_swap_crinfo_out (abfd, in, ex)
+ bfd *abfd;
+ const Elf32_crinfo *in;
+ Elf32_External_crinfo *ex;
+{
+ unsigned long l;
+
+ l = (((in->ctype & CRINFO_CTYPE) << CRINFO_CTYPE_SH)
+ | ((in->rtype & CRINFO_RTYPE) << CRINFO_RTYPE_SH)
+ | ((in->dist2to & CRINFO_DIST2TO) << CRINFO_DIST2TO_SH)
+ | ((in->relvaddr & CRINFO_RELVADDR) << CRINFO_RELVADDR_SH));
+ bfd_h_put_32 (abfd, (bfd_vma) l, ex->info);
+ bfd_h_put_32 (abfd, (bfd_vma) in->konst, ex->konst);
+ bfd_h_put_32 (abfd, (bfd_vma) in->vaddr, ex->vaddr);
+}
+
+/* Determine whether a symbol is global for the purposes of splitting
+ the symbol table into global symbols and local symbols. At least
+ on Irix 5, this split must be between section symbols and all other
+ symbols. On most ELF targets the split is between static symbols
+ and externally visible symbols. */
+
+/*ARGSUSED*/
+static boolean
+mips_elf_sym_is_global (abfd, sym)
+ bfd *abfd;
+ asymbol *sym;
+{
+ return (sym->flags & BSF_SECTION_SYM) == 0 ? true : false;
+}
+
+/* Set the right machine number for a MIPS ELF file. */
+
+static boolean
+mips_elf_object_p (abfd)
+ bfd *abfd;
+{
+ switch (elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH)
+ {
+ default:
+ case E_MIPS_ARCH_1:
+ /* Just use the default, which was set in elfcode.h. */
+ break;
+
+ case E_MIPS_ARCH_2:
+ (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 6000);
+ break;
+
+ case E_MIPS_ARCH_3:
+ (void) bfd_default_set_arch_mach (abfd, bfd_arch_mips, 4000);
+ break;
+ }
+
+ /* Irix 5 is broken. Object file symbol tables are not always
+ sorted correctly such that local symbols precede global symbols,
+ and the sh_info field in the symbol table is not always right. */
+ elf_bad_symtab (abfd) = true;
+
+ return true;
+}
+
+/* The final processing done just before writing out a MIPS ELF object
+ file. This gets the MIPS architecture right based on the machine
+ number. */
+
+/*ARGSUSED*/
+static void
+mips_elf_final_write_processing (abfd, linker)
+ bfd *abfd;
+ boolean linker;
+{
+ unsigned long val;
+ unsigned int i;
+ Elf_Internal_Shdr **hdrpp;
+
+ switch (bfd_get_mach (abfd))
+ {
+ case 3000:
+ val = E_MIPS_ARCH_1;
+ break;
+
+ case 6000:
+ val = E_MIPS_ARCH_2;
+ break;
+
+ case 4000:
+ val = E_MIPS_ARCH_3;
+ break;
+
+ default:
+ val = 0;
+ break;
+ }
+
+ elf_elfheader (abfd)->e_flags &=~ EF_MIPS_ARCH;
+ elf_elfheader (abfd)->e_flags |= val;
+
+ /* Set the sh_info field for .gptab sections. */
+ for (i = 1, hdrpp = elf_elfsections (abfd) + 1;
+ i < elf_elfheader (abfd)->e_shnum;
+ i++, hdrpp++)
+ {
+ if ((*hdrpp)->sh_type == SHT_MIPS_GPTAB)
+ {
+ const char *name;
+ asection *sec;
+
+ BFD_ASSERT ((*hdrpp)->bfd_section != NULL);
+ name = bfd_get_section_name (abfd, (*hdrpp)->bfd_section);
+ BFD_ASSERT (name != NULL
+ && strncmp (name, ".gptab.", sizeof ".gptab." - 1) == 0);
+ sec = bfd_get_section_by_name (abfd, name + sizeof ".gptab" - 1);
+ BFD_ASSERT (sec != NULL);
+ (*hdrpp)->sh_info = elf_section_data (sec)->this_idx;
+ }
+ }
+}
+
+/* Function to keep MIPS specific file flags like as EF_MIPS_PIC. */
+
+static boolean
+mips_elf_set_private_flags (abfd, flags)
+ bfd *abfd;
+ flagword flags;
+{
+ BFD_ASSERT (!elf_flags_init (abfd)
+ || elf_elfheader (abfd)->e_flags == flags);
+
+ elf_elfheader (abfd)->e_flags = flags;
+ elf_flags_init (abfd) = true;
+ return true;
+}
+
+/* Copy backend specific data from one object module to another */
+
+static boolean
+mips_elf_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ /* This function is selected based on the input vector. We only
+ want to copy information over if the output BFD also uses Elf
+ format. */
+ if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ BFD_ASSERT (!elf_flags_init (obfd)
+ || (elf_elfheader (obfd)->e_flags
+ == elf_elfheader (ibfd)->e_flags));
+
+ elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+ elf_flags_init (obfd) = true;
+ return true;
+}
+
+/* Merge backend specific data from an object file to the output
+ object file when linking. */
+
+static boolean
+mips_elf_merge_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ flagword old_flags;
+ flagword new_flags;
+
+ /* Check if we have the same endianess */
+ if (ibfd->xvec->byteorder != obfd->xvec->byteorder
+ && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
+ {
+ (*_bfd_error_handler)
+ ("%s: compiled for a %s endian system and target is %s endian",
+ bfd_get_filename (ibfd),
+ bfd_big_endian (ibfd) ? "big" : "little",
+ bfd_big_endian (obfd) ? "big" : "little");
+
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
+ /* This function is selected based on the input vector. We only
+ want to copy information over if the output BFD also uses Elf
+ format. */
+ if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ new_flags = elf_elfheader (ibfd)->e_flags;
+ elf_elfheader (obfd)->e_flags |= new_flags & EF_MIPS_NOREORDER;
+ old_flags = elf_elfheader (obfd)->e_flags;
+
+ if (!elf_flags_init (obfd)) /* First call, no flags set */
+ {
+ elf_flags_init (obfd) = true;
+ elf_elfheader (obfd)->e_flags = new_flags;
+ }
+ else if (((new_flags ^ old_flags) & ~EF_MIPS_NOREORDER)
+ == 0) /* Compatible flags are ok */
+ ;
+ else /* Incompatible flags */
+ {
+ /* Warn about -fPIC mismatch */
+ if ((new_flags & EF_MIPS_PIC) != (old_flags & EF_MIPS_PIC))
+ {
+ new_flags &= ~EF_MIPS_PIC;
+ (*_bfd_error_handler)
+ ("%s: needs all files compiled with -fPIC",
+ bfd_get_filename (ibfd));
+ }
+
+ if ((new_flags & EF_MIPS_CPIC) != (old_flags & EF_MIPS_CPIC))
+ {
+ new_flags &= ~EF_MIPS_CPIC;
+ (*_bfd_error_handler)
+ ("%s: needs all files compiled with -mabicalls",
+ bfd_get_filename (ibfd));
+ }
+
+ /* Warn about any other mismatches */
+ if (new_flags != old_flags)
+ (*_bfd_error_handler)
+ ("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)",
+ bfd_get_filename (ibfd), (unsigned long) new_flags,
+ (unsigned long) old_flags);
+
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ return true;
+}
+
+/* Handle a MIPS specific section when reading an object file. This
+ is called when elfcode.h finds a section with an unknown type.
+ FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure
+ how to. */
+
+static boolean
+mips_elf_section_from_shdr (abfd, hdr, name)
+ bfd *abfd;
+ Elf32_Internal_Shdr *hdr;
+ char *name;
+{
+ asection *newsect;
+
+ /* There ought to be a place to keep ELF backend specific flags, but
+ at the moment there isn't one. We just keep track of the
+ sections by their name, instead. Fortunately, the ABI gives
+ suggested names for all the MIPS specific sections, so we will
+ probably get away with this. */
+ switch (hdr->sh_type)
+ {
+ case SHT_MIPS_LIBLIST:
+ if (strcmp (name, ".liblist") != 0)
+ return false;
+ break;
+ case SHT_MIPS_MSYM:
+ if (strcmp (name, ".msym") != 0)
+ return false;
+ break;
+ case SHT_MIPS_CONFLICT:
+ if (strcmp (name, ".conflict") != 0)
+ return false;
+ break;
+ case SHT_MIPS_GPTAB:
+ if (strncmp (name, ".gptab.", sizeof ".gptab." - 1) != 0)
+ return false;
+ break;
+ case SHT_MIPS_UCODE:
+ if (strcmp (name, ".ucode") != 0)
+ return false;
+ break;
+ case SHT_MIPS_DEBUG:
+ if (strcmp (name, ".mdebug") != 0)
+ return false;
+ break;
+ case SHT_MIPS_REGINFO:
+ if (strcmp (name, ".reginfo") != 0
+ || hdr->sh_size != sizeof (Elf32_External_RegInfo))
+ return false;
+ break;
+ case SHT_MIPS_OPTIONS:
+ if (strcmp (name, ".options") != 0)
+ return false;
+ break;
+ case SHT_MIPS_DWARF:
+ if (strncmp (name, ".debug_", sizeof ".debug_" - 1) != 0)
+ return false;
+ break;
+ case SHT_MIPS_EVENTS:
+ if (strncmp (name, ".MIPS.events.", sizeof ".MIPS.events." - 1) != 0)
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ return false;
+ newsect = hdr->bfd_section;
+
+ if (hdr->sh_type == SHT_MIPS_DEBUG)
+ {
+ if (! bfd_set_section_flags (abfd, newsect,
+ (bfd_get_section_flags (abfd, newsect)
+ | SEC_DEBUGGING)))
+ return false;
+ }
+
+ /* FIXME: We should record sh_info for a .gptab section. */
+
+ /* For a .reginfo section, set the gp value in the tdata information
+ from the contents of this section. We need the gp value while
+ processing relocs, so we just get it now. */
+ if (hdr->sh_type == SHT_MIPS_REGINFO)
+ {
+ Elf32_External_RegInfo ext;
+ Elf32_RegInfo s;
+
+ if (! bfd_get_section_contents (abfd, newsect, (PTR) &ext,
+ (file_ptr) 0, sizeof ext))
+ return false;
+ bfd_mips_elf32_swap_reginfo_in (abfd, &ext, &s);
+ elf_gp (abfd) = s.ri_gp_value;
+ }
+
+ return true;
+}
+
+/* Set the correct type for a MIPS ELF section. We do this by the
+ section name, which is a hack, but ought to work. */
+
+static boolean
+mips_elf_fake_sections (abfd, hdr, sec)
+ bfd *abfd;
+ Elf32_Internal_Shdr *hdr;
+ asection *sec;
+{
+ register const char *name;
+
+ name = bfd_get_section_name (abfd, sec);
+
+ if (strcmp (name, ".liblist") == 0)
+ {
+ hdr->sh_type = SHT_MIPS_LIBLIST;
+ hdr->sh_info = sec->_raw_size / sizeof (Elf32_Lib);
+ /* FIXME: Set the sh_link field. */
+ }
+ else if (strcmp (name, ".msym") == 0)
+ {
+ hdr->sh_type = SHT_MIPS_MSYM;
+ hdr->sh_entsize = 8;
+ /* FIXME: Set the sh_info field. */
+ }
+ else if (strcmp (name, ".conflict") == 0)
+ hdr->sh_type = SHT_MIPS_CONFLICT;
+ else if (strncmp (name, ".gptab.", sizeof ".gptab." - 1) == 0)
+ {
+ hdr->sh_type = SHT_MIPS_GPTAB;
+ hdr->sh_entsize = sizeof (Elf32_External_gptab);
+ /* The sh_info field is set in mips_elf_final_write_processing. */
+ }
+ else if (strcmp (name, ".ucode") == 0)
+ hdr->sh_type = SHT_MIPS_UCODE;
+ else if (strcmp (name, ".mdebug") == 0)
+ {
+ hdr->sh_type = SHT_MIPS_DEBUG;
+ /* In a shared object on Irix 5.3, the .mdebug section has an
+ entsize of 0. FIXME: Does this matter? */
+ if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0)
+ hdr->sh_entsize = 0;
+ else
+ hdr->sh_entsize = 1;
+ }
+ else if (strcmp (name, ".reginfo") == 0)
+ {
+ hdr->sh_type = SHT_MIPS_REGINFO;
+ /* In a shared object on Irix 5.3, the .reginfo section has an
+ entsize of 0x18. FIXME: Does this matter? */
+ if (SGI_COMPAT (abfd) && (abfd->flags & DYNAMIC) != 0)
+ hdr->sh_entsize = sizeof (Elf32_External_RegInfo);
+ else
+ hdr->sh_entsize = 1;
+
+ /* Force the section size to the correct value, even if the
+ linker thinks it is larger. The link routine below will only
+ write out this much data for .reginfo. */
+ hdr->sh_size = sec->_raw_size = sizeof (Elf32_External_RegInfo);
+ }
+ else if (SGI_COMPAT (abfd)
+ && (strcmp (name, ".hash") == 0
+ || strcmp (name, ".dynamic") == 0
+ || strcmp (name, ".dynstr") == 0))
+ {
+ hdr->sh_entsize = 0;
+ hdr->sh_info = SIZEOF_MIPS_DYNSYM_SECNAMES;
+ }
+ else if (strcmp (name, ".got") == 0
+ || strcmp (name, ".sdata") == 0
+ || strcmp (name, ".sbss") == 0
+ || strcmp (name, ".lit4") == 0
+ || strcmp (name, ".lit8") == 0)
+ hdr->sh_flags |= SHF_MIPS_GPREL;
+ else if (strcmp (name, ".options") == 0)
+ {
+ hdr->sh_type = SHT_MIPS_OPTIONS;
+ hdr->sh_entsize = 1;
+ }
+ else if (strncmp (name, ".debug_", sizeof ".debug_" - 1) == 0)
+ hdr->sh_type = SHT_MIPS_DWARF;
+ else if (strncmp (name, ".MIPS.events.", sizeof ".MIPS.events." - 1) == 0)
+ hdr->sh_type = SHT_MIPS_EVENTS;
+
+ return true;
+}
+
+/* Given a BFD section, try to locate the corresponding ELF section
+ index. */
+
+static boolean
+mips_elf_section_from_bfd_section (abfd, hdr, sec, retval)
+ bfd *abfd;
+ Elf32_Internal_Shdr *hdr;
+ asection *sec;
+ int *retval;
+{
+ if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0)
+ {
+ *retval = SHN_MIPS_SCOMMON;
+ return true;
+ }
+ if (strcmp (bfd_get_section_name (abfd, sec), ".acommon") == 0)
+ {
+ *retval = SHN_MIPS_ACOMMON;
+ return true;
+ }
+ return false;
+}
+
+/* Work over a section just before writing it out. We update the GP
+ value in the .reginfo section based on the value we are using.
+ FIXME: We recognize sections that need the SHF_MIPS_GPREL flag by
+ name; there has to be a better way. */
+
+static boolean
+mips_elf_section_processing (abfd, hdr)
+ bfd *abfd;
+ Elf32_Internal_Shdr *hdr;
+{
+ if (hdr->sh_type == SHT_MIPS_REGINFO)
+ {
+ bfd_byte buf[4];
+
+ BFD_ASSERT (hdr->sh_size == sizeof (Elf32_External_RegInfo));
+ BFD_ASSERT (hdr->contents == NULL);
+
+ if (bfd_seek (abfd,
+ hdr->sh_offset + sizeof (Elf32_External_RegInfo) - 4,
+ SEEK_SET) == -1)
+ return false;
+ bfd_h_put_32 (abfd, (bfd_vma) elf_gp (abfd), buf);
+ if (bfd_write (buf, (bfd_size_type) 1, (bfd_size_type) 4, abfd) != 4)
+ return false;
+ }
+
+ if (hdr->bfd_section != NULL)
+ {
+ const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
+
+ if (strcmp (name, ".sdata") == 0)
+ {
+ hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
+ hdr->sh_type = SHT_PROGBITS;
+ }
+ else if (strcmp (name, ".sbss") == 0)
+ {
+ hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
+ hdr->sh_type = SHT_NOBITS;
+ }
+ else if (strcmp (name, ".lit8") == 0
+ || strcmp (name, ".lit4") == 0)
+ {
+ hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL;
+ hdr->sh_type = SHT_PROGBITS;
+ }
+ else if (strcmp (name, ".compact_rel") == 0)
+ {
+ hdr->sh_flags = 0;
+ hdr->sh_type = SHT_PROGBITS;
+ }
+ else if (strcmp (name, ".rtproc") == 0)
+ {
+ if (hdr->sh_addralign != 0 && hdr->sh_entsize == 0)
+ {
+ unsigned int adjust;
+
+ adjust = hdr->sh_size % hdr->sh_addralign;
+ if (adjust != 0)
+ hdr->sh_size += hdr->sh_addralign - adjust;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* MIPS ELF uses two common sections. One is the usual one, and the
+ other is for small objects. All the small objects are kept
+ together, and then referenced via the gp pointer, which yields
+ faster assembler code. This is what we use for the small common
+ section. This approach is copied from ecoff.c. */
+static asection mips_elf_scom_section;
+static asymbol mips_elf_scom_symbol;
+static asymbol *mips_elf_scom_symbol_ptr;
+
+/* MIPS ELF also uses an acommon section, which represents an
+ allocated common symbol which may be overridden by a
+ definition in a shared library. */
+static asection mips_elf_acom_section;
+static asymbol mips_elf_acom_symbol;
+static asymbol *mips_elf_acom_symbol_ptr;
+
+/* The Irix 5 support uses two virtual sections, which represent
+ text/data symbols defined in dynamic objects. */
+static asection mips_elf_text_section;
+static asection *mips_elf_text_section_ptr;
+static asymbol mips_elf_text_symbol;
+static asymbol *mips_elf_text_symbol_ptr;
+
+static asection mips_elf_data_section;
+static asection *mips_elf_data_section_ptr;
+static asymbol mips_elf_data_symbol;
+static asymbol *mips_elf_data_symbol_ptr;
+
+/* Handle the special MIPS section numbers that a symbol may use. */
+
+static void
+mips_elf_symbol_processing (abfd, asym)
+ bfd *abfd;
+ asymbol *asym;
+{
+ elf_symbol_type *elfsym;
+
+ elfsym = (elf_symbol_type *) asym;
+ switch (elfsym->internal_elf_sym.st_shndx)
+ {
+ case SHN_MIPS_ACOMMON:
+ /* This section is used in a dynamically linked executable file.
+ It is an allocated common section. The dynamic linker can
+ either resolve these symbols to something in a shared
+ library, or it can just leave them here. For our purposes,
+ we can consider these symbols to be in a new section. */
+ if (mips_elf_acom_section.name == NULL)
+ {
+ /* Initialize the acommon section. */
+ mips_elf_acom_section.name = ".acommon";
+ mips_elf_acom_section.flags = SEC_ALLOC;
+ mips_elf_acom_section.output_section = &mips_elf_acom_section;
+ mips_elf_acom_section.symbol = &mips_elf_acom_symbol;
+ mips_elf_acom_section.symbol_ptr_ptr = &mips_elf_acom_symbol_ptr;
+ mips_elf_acom_symbol.name = ".acommon";
+ mips_elf_acom_symbol.flags = BSF_SECTION_SYM;
+ mips_elf_acom_symbol.section = &mips_elf_acom_section;
+ mips_elf_acom_symbol_ptr = &mips_elf_acom_symbol;
+ }
+ asym->section = &mips_elf_acom_section;
+ break;
+
+ case SHN_COMMON:
+ /* Common symbols less than the GP size are automatically
+ treated as SHN_MIPS_SCOMMON symbols. */
+ if (asym->value > elf_gp_size (abfd))
+ break;
+ /* Fall through. */
+ case SHN_MIPS_SCOMMON:
+ if (mips_elf_scom_section.name == NULL)
+ {
+ /* Initialize the small common section. */
+ mips_elf_scom_section.name = ".scommon";
+ mips_elf_scom_section.flags = SEC_IS_COMMON;
+ mips_elf_scom_section.output_section = &mips_elf_scom_section;
+ mips_elf_scom_section.symbol = &mips_elf_scom_symbol;
+ mips_elf_scom_section.symbol_ptr_ptr = &mips_elf_scom_symbol_ptr;
+ mips_elf_scom_symbol.name = ".scommon";
+ mips_elf_scom_symbol.flags = BSF_SECTION_SYM;
+ mips_elf_scom_symbol.section = &mips_elf_scom_section;
+ mips_elf_scom_symbol_ptr = &mips_elf_scom_symbol;
+ }
+ asym->section = &mips_elf_scom_section;
+ asym->value = elfsym->internal_elf_sym.st_size;
+ break;
+
+ case SHN_MIPS_SUNDEFINED:
+ asym->section = bfd_und_section_ptr;
+ break;
+
+#if 0 /* for SGI_COMPAT */
+ case SHN_MIPS_TEXT:
+ asym->section = mips_elf_text_section_ptr;
+ break;
+
+ case SHN_MIPS_DATA:
+ asym->section = mips_elf_data_section_ptr;
+ break;
+#endif
+ }
+}
+
+/* When creating an Irix 5 executable, we need REGINFO and RTPROC
+ segments. */
+
+static int
+mips_elf_additional_program_headers (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ int ret;
+
+ ret = 0;
+
+ if (! SGI_COMPAT (abfd))
+ return ret;
+
+ s = bfd_get_section_by_name (abfd, ".reginfo");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ /* We need a PT_MIPS_REGINFO segment. */
+ ++ret;
+ }
+
+ if (bfd_get_section_by_name (abfd, ".dynamic") != NULL
+ && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
+ {
+ /* We need a PT_MIPS_RTPROC segment. */
+ ++ret;
+ }
+
+ return ret;
+}
+
+/* Modify the segment map for an Irix 5 executable. */
+
+static boolean
+mips_elf_modify_segment_map (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ struct elf_segment_map *m, **pm;
+
+ if (! SGI_COMPAT (abfd))
+ return true;
+
+ /* If there is a .reginfo section, we need a PT_MIPS_REGINFO
+ segment. */
+ s = bfd_get_section_by_name (abfd, ".reginfo");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ if (m->p_type == PT_MIPS_REGINFO)
+ break;
+ if (m == NULL)
+ {
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+ if (m == NULL)
+ return false;
+
+ m->p_type = PT_MIPS_REGINFO;
+ m->count = 1;
+ m->sections[0] = s;
+
+ /* We want to put it after the PHDR and INTERP segments. */
+ pm = &elf_tdata (abfd)->segment_map;
+ while (*pm != NULL
+ && ((*pm)->p_type == PT_PHDR
+ || (*pm)->p_type == PT_INTERP))
+ pm = &(*pm)->next;
+
+ m->next = *pm;
+ *pm = m;
+ }
+ }
+
+ /* If there are .dynamic and .mdebug sections, we make a room for
+ the RTPROC header. FIXME: Rewrite without section names. */
+ if (bfd_get_section_by_name (abfd, ".interp") == NULL
+ && bfd_get_section_by_name (abfd, ".dynamic") != NULL
+ && bfd_get_section_by_name (abfd, ".mdebug") != NULL)
+ {
+ for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ if (m->p_type == PT_MIPS_RTPROC)
+ break;
+ if (m == NULL)
+ {
+ m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+ if (m == NULL)
+ return false;
+
+ m->p_type = PT_MIPS_RTPROC;
+
+ s = bfd_get_section_by_name (abfd, ".rtproc");
+ if (s == NULL)
+ {
+ m->count = 0;
+ m->p_flags = 0;
+ m->p_flags_valid = 1;
+ }
+ else
+ {
+ m->count = 1;
+ m->sections[0] = s;
+ }
+
+ /* We want to put it after the DYNAMIC segment. */
+ pm = &elf_tdata (abfd)->segment_map;
+ while (*pm != NULL && (*pm)->p_type != PT_DYNAMIC)
+ pm = &(*pm)->next;
+ if (*pm != NULL)
+ pm = &(*pm)->next;
+
+ m->next = *pm;
+ *pm = m;
+ }
+ }
+
+ /* On Irix 5, the PT_DYNAMIC segment includes the .dynamic, .dynstr,
+ .dynsym, and .hash sections, and everything in between. */
+ for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next)
+ if ((*pm)->p_type == PT_DYNAMIC)
+ break;
+ m = *pm;
+ if (m != NULL
+ && m->count == 1
+ && strcmp (m->sections[0]->name, ".dynamic") == 0)
+ {
+ static const char *sec_names[] =
+ { ".dynamic", ".dynstr", ".dynsym", ".hash" };
+ bfd_vma low, high;
+ unsigned int i, c;
+ struct elf_segment_map *n;
+
+ low = 0xffffffff;
+ high = 0;
+ for (i = 0; i < sizeof sec_names / sizeof sec_names[0]; i++)
+ {
+ s = bfd_get_section_by_name (abfd, sec_names[i]);
+ if (s != NULL && (s->flags & SEC_LOAD) != 0)
+ {
+ bfd_size_type sz;
+
+ if (low > s->vma)
+ low = s->vma;
+ sz = s->_cooked_size;
+ if (sz == 0)
+ sz = s->_raw_size;
+ if (high < s->vma + sz)
+ high = s->vma + sz;
+ }
+ }
+
+ c = 0;
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if ((s->flags & SEC_LOAD) != 0
+ && s->vma >= low
+ && ((s->vma
+ + (s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size))
+ <= high))
+ ++c;
+
+ n = ((struct elf_segment_map *)
+ bfd_zalloc (abfd, sizeof *n + (c - 1) * sizeof (asection *)));
+ if (n == NULL)
+ return false;
+ *n = *m;
+ n->count = c;
+
+ i = 0;
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_LOAD) != 0
+ && s->vma >= low
+ && ((s->vma
+ + (s->_cooked_size != 0 ? s->_cooked_size : s->_raw_size))
+ <= high))
+ {
+ n->sections[i] = s;
+ ++i;
+ }
+ }
+
+ *pm = n;
+ }
+
+ return true;
+}
+
+/* The structure of the runtime procedure descriptor created by the
+ loader for use by the static exception system. */
+
+typedef struct runtime_pdr {
+ 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 */
+ long fregoffset; /* save floating point register offset */
+ long frameoffset; /* frame size */
+ short framereg; /* frame pointer register */
+ short pcreg; /* offset or reg of return pc */
+ long irpss; /* index into the runtime string table */
+ long reserved;
+ struct exception_info *exception_info;/* pointer to exception array */
+} RPDR, *pRPDR;
+#define cbRPDR sizeof(RPDR)
+#define rpdNil ((pRPDR) 0)
+
+/* Swap RPDR (runtime procedure table entry) for output. */
+
+static void ecoff_swap_rpdr_out
+ PARAMS ((bfd *, const RPDR *, struct rpdr_ext *));
+
+static void
+ecoff_swap_rpdr_out (abfd, in, ex)
+ bfd *abfd;
+ const RPDR *in;
+ struct rpdr_ext *ex;
+{
+ /* ecoff_put_off was defined in ecoffswap.h. */
+ ecoff_put_off (abfd, in->adr, (bfd_byte *) ex->p_adr);
+ bfd_h_put_32 (abfd, in->regmask, (bfd_byte *) ex->p_regmask);
+ bfd_h_put_32 (abfd, in->regoffset, (bfd_byte *) ex->p_regoffset);
+ bfd_h_put_32 (abfd, in->fregmask, (bfd_byte *) ex->p_fregmask);
+ bfd_h_put_32 (abfd, in->fregoffset, (bfd_byte *) ex->p_fregoffset);
+ bfd_h_put_32 (abfd, in->frameoffset, (bfd_byte *) ex->p_frameoffset);
+
+ bfd_h_put_16 (abfd, in->framereg, (bfd_byte *) ex->p_framereg);
+ bfd_h_put_16 (abfd, in->pcreg, (bfd_byte *) ex->p_pcreg);
+
+ bfd_h_put_32 (abfd, in->irpss, (bfd_byte *) ex->p_irpss);
+#if 0 /* FIXME */
+ ecoff_put_off (abfd, in->exception_info, (bfd_byte *) ex->p_exception_info);
+#endif
+}
+
+/* Read ECOFF debugging information from a .mdebug section into a
+ ecoff_debug_info structure. */
+
+static boolean
+mips_elf_read_ecoff_info (abfd, section, debug)
+ bfd *abfd;
+ asection *section;
+ struct ecoff_debug_info *debug;
+{
+ HDRR *symhdr;
+ const struct ecoff_debug_swap *swap;
+ char *ext_hdr = NULL;
+
+ swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+
+ ext_hdr = (char *) bfd_malloc ((size_t) swap->external_hdr_size);
+ if (ext_hdr == NULL && swap->external_hdr_size != 0)
+ goto error_return;
+
+ if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
+ swap->external_hdr_size)
+ == false)
+ goto error_return;
+
+ symhdr = &debug->symbolic_header;
+ (*swap->swap_hdr_in) (abfd, ext_hdr, symhdr);
+
+ /* The symbolic header contains absolute file offsets and sizes to
+ read. */
+#define READ(ptr, offset, count, size, type) \
+ if (symhdr->count == 0) \
+ debug->ptr = NULL; \
+ else \
+ { \
+ debug->ptr = (type) bfd_malloc ((size_t) (size * symhdr->count)); \
+ if (debug->ptr == NULL) \
+ goto error_return; \
+ if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
+ || (bfd_read (debug->ptr, size, symhdr->count, \
+ abfd) != size * symhdr->count)) \
+ goto error_return; \
+ }
+
+ 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 (ssext, cbSsExtOffset, issExtMax, sizeof (char), char *);
+ READ (external_fdr, cbFdOffset, ifdMax, swap->external_fdr_size, PTR);
+ READ (external_rfd, cbRfdOffset, crfd, swap->external_rfd_size, PTR);
+ READ (external_ext, cbExtOffset, iextMax, swap->external_ext_size, PTR);
+#undef READ
+
+ debug->fdr = NULL;
+ debug->adjust = NULL;
+
+ return true;
+
+ error_return:
+ if (ext_hdr != NULL)
+ free (ext_hdr);
+ 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->ssext != NULL)
+ free (debug->ssext);
+ if (debug->external_fdr != NULL)
+ free (debug->external_fdr);
+ if (debug->external_rfd != NULL)
+ free (debug->external_rfd);
+ if (debug->external_ext != NULL)
+ free (debug->external_ext);
+ return false;
+}
+
+/* MIPS ELF local labels start with '$', not 'L'. */
+
+/*ARGSUSED*/
+static boolean
+mips_elf_is_local_label (abfd, symbol)
+ bfd *abfd;
+ asymbol *symbol;
+{
+ return symbol->name[0] == '$';
+}
+
+/* MIPS ELF uses a special find_nearest_line routine in order the
+ handle the ECOFF debugging information. */
+
+struct mips_elf_find_line
+{
+ struct ecoff_debug_info d;
+ struct ecoff_find_line i;
+};
+
+static boolean
+mips_elf_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;
+{
+ asection *msec;
+
+ msec = bfd_get_section_by_name (abfd, ".mdebug");
+ if (msec != NULL)
+ {
+ flagword origflags;
+ struct mips_elf_find_line *fi;
+ const struct ecoff_debug_swap * const swap =
+ get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+
+ /* If we are called during a link, mips_elf_final_link may have
+ cleared the SEC_HAS_CONTENTS field. We force it back on here
+ if appropriate (which it normally will be). */
+ origflags = msec->flags;
+ if (elf_section_data (msec)->this_hdr.sh_type != SHT_NOBITS)
+ msec->flags |= SEC_HAS_CONTENTS;
+
+ fi = elf_tdata (abfd)->find_line_info;
+ if (fi == NULL)
+ {
+ bfd_size_type external_fdr_size;
+ char *fraw_src;
+ char *fraw_end;
+ struct fdr *fdr_ptr;
+
+ fi = ((struct mips_elf_find_line *)
+ bfd_alloc (abfd, sizeof (struct mips_elf_find_line)));
+ if (fi == NULL)
+ {
+ msec->flags = origflags;
+ return false;
+ }
+
+ memset (fi, 0, sizeof (struct mips_elf_find_line));
+
+ if (! mips_elf_read_ecoff_info (abfd, msec, &fi->d))
+ {
+ msec->flags = origflags;
+ return false;
+ }
+
+ /* Swap in the FDR information. */
+ fi->d.fdr = ((struct fdr *)
+ bfd_alloc (abfd,
+ (fi->d.symbolic_header.ifdMax *
+ sizeof (struct fdr))));
+ if (fi->d.fdr == NULL)
+ {
+ msec->flags = origflags;
+ return false;
+ }
+ external_fdr_size = swap->external_fdr_size;
+ fdr_ptr = fi->d.fdr;
+ fraw_src = (char *) fi->d.external_fdr;
+ fraw_end = (fraw_src
+ + fi->d.symbolic_header.ifdMax * external_fdr_size);
+ for (; fraw_src < fraw_end; fraw_src += external_fdr_size, fdr_ptr++)
+ (*swap->swap_fdr_in) (abfd, (PTR) fraw_src, fdr_ptr);
+
+ elf_tdata (abfd)->find_line_info = fi;
+
+ /* Note that we don't bother to ever free this information.
+ find_nearest_line is either called all the time, as in
+ objdump -l, so the information should be saved, or it is
+ rarely called, as in ld error messages, so the memory
+ wasted is unimportant. Still, it would probably be a
+ good idea for free_cached_info to throw it away. */
+ }
+
+ if (_bfd_ecoff_locate_line (abfd, section, offset, &fi->d, swap,
+ &fi->i, filename_ptr, functionname_ptr,
+ line_ptr))
+ {
+ msec->flags = origflags;
+ return true;
+ }
+
+ msec->flags = origflags;
+ }
+
+ /* Fall back on the generic ELF find_nearest_line routine. */
+
+ return _bfd_elf_find_nearest_line (abfd, section, symbols, offset,
+ filename_ptr, functionname_ptr,
+ line_ptr);
+}
+
+/* The MIPS ELF linker needs additional information for each symbol in
+ the global hash table. */
+
+struct mips_elf_link_hash_entry
+{
+ struct elf_link_hash_entry root;
+
+ /* External symbol information. */
+ EXTR esym;
+};
+
+/* MIPS ELF linker hash table. */
+
+struct mips_elf_link_hash_table
+{
+ struct elf_link_hash_table root;
+ /* String section indices for the dynamic section symbols. */
+ bfd_size_type dynsym_sec_strindex[SIZEOF_MIPS_DYNSYM_SECNAMES];
+ /* The number of .rtproc entries. */
+ bfd_size_type procedure_count;
+ /* The size of the .compact_rel section (if SGI_COMPAT). */
+ bfd_size_type compact_rel_size;
+};
+
+/* Look up an entry in a MIPS ELF linker hash table. */
+
+#define mips_elf_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct mips_elf_link_hash_entry *) \
+ elf_link_hash_lookup (&(table)->root, (string), (create), \
+ (copy), (follow)))
+
+/* Traverse a MIPS ELF linker hash table. */
+
+#define mips_elf_link_hash_traverse(table, func, info) \
+ (elf_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the MIPS ELF linker hash table from a link_info structure. */
+
+#define mips_elf_hash_table(p) \
+ ((struct mips_elf_link_hash_table *) ((p)->hash))
+
+static boolean mips_elf_output_extsym
+ PARAMS ((struct mips_elf_link_hash_entry *, PTR));
+
+/* Create an entry in a MIPS ELF linker hash table. */
+
+static struct bfd_hash_entry *
+mips_elf_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct mips_elf_link_hash_entry *ret =
+ (struct mips_elf_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct mips_elf_link_hash_entry *) NULL)
+ ret = ((struct mips_elf_link_hash_entry *)
+ bfd_hash_allocate (table,
+ sizeof (struct mips_elf_link_hash_entry)));
+ if (ret == (struct mips_elf_link_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct mips_elf_link_hash_entry *)
+ _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != (struct mips_elf_link_hash_entry *) NULL)
+ {
+ /* Set local fields. */
+ memset (&ret->esym, 0, sizeof (EXTR));
+ /* We use -2 as a marker to indicate that the information has
+ not been set. -1 means there is no associated ifd. */
+ ret->esym.ifd = -2;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create a MIPS ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+mips_elf_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct mips_elf_link_hash_table *ret;
+ unsigned int i;
+
+ ret = ((struct mips_elf_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct mips_elf_link_hash_table)));
+ if (ret == (struct mips_elf_link_hash_table *) NULL)
+ return NULL;
+
+ if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,
+ mips_elf_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return NULL;
+ }
+
+ for (i = 0; i < SIZEOF_MIPS_DYNSYM_SECNAMES; i++)
+ ret->dynsym_sec_strindex[i] = (bfd_size_type) -1;
+ ret->procedure_count = 0;
+ ret->compact_rel_size = 0;
+
+ return &ret->root.root;
+}
+
+/* Hook called by the linker routine which adds symbols from an object
+ file. We must handle the special MIPS section numbers here. */
+
+/*ARGSUSED*/
+static boolean
+mips_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ const Elf_Internal_Sym *sym;
+ const char **namep;
+ flagword *flagsp;
+ asection **secp;
+ bfd_vma *valp;
+{
+ if (SGI_COMPAT (abfd)
+ && (abfd->flags & DYNAMIC) != 0
+ && strcmp (*namep, "_rld_new_interface") == 0)
+ {
+ /* Skip Irix 5 rld entry name. */
+ *namep = NULL;
+ return true;
+ }
+
+ switch (sym->st_shndx)
+ {
+ case SHN_COMMON:
+ /* Common symbols less than the GP size are automatically
+ treated as SHN_MIPS_SCOMMON symbols. */
+ if (sym->st_size > elf_gp_size (abfd))
+ break;
+ /* Fall through. */
+ case SHN_MIPS_SCOMMON:
+ *secp = bfd_make_section_old_way (abfd, ".scommon");
+ (*secp)->flags |= SEC_IS_COMMON;
+ *valp = sym->st_size;
+ break;
+
+ case SHN_MIPS_TEXT:
+ /* This section is used in a shared object. */
+ if (mips_elf_text_section_ptr == NULL)
+ {
+ /* Initialize the section. */
+ mips_elf_text_section.name = ".text";
+ mips_elf_text_section.flags = SEC_NO_FLAGS;
+ mips_elf_text_section.output_section = NULL;
+ mips_elf_text_section.owner = abfd;
+ mips_elf_text_section.symbol = &mips_elf_text_symbol;
+ mips_elf_text_section.symbol_ptr_ptr = &mips_elf_text_symbol_ptr;
+ mips_elf_text_symbol.name = ".text";
+ mips_elf_text_symbol.flags = BSF_SECTION_SYM;
+ mips_elf_text_symbol.section = &mips_elf_text_section;
+ mips_elf_text_symbol_ptr = &mips_elf_text_symbol;
+ mips_elf_text_section_ptr = &mips_elf_text_section;
+ }
+ if (info->shared)
+ *secp = bfd_und_section_ptr;
+ else
+ *secp = mips_elf_text_section_ptr;
+ break;
+
+ case SHN_MIPS_ACOMMON:
+ /* Fall through. XXX Can we treat this as allocated data? */
+ case SHN_MIPS_DATA:
+ /* This section is used in a shared object. */
+ if (mips_elf_data_section_ptr == NULL)
+ {
+ /* Initialize the section. */
+ mips_elf_data_section.name = ".data";
+ mips_elf_data_section.flags = SEC_NO_FLAGS;
+ mips_elf_data_section.output_section = NULL;
+ mips_elf_data_section.owner = abfd;
+ mips_elf_data_section.symbol = &mips_elf_data_symbol;
+ mips_elf_data_section.symbol_ptr_ptr = &mips_elf_data_symbol_ptr;
+ mips_elf_data_symbol.name = ".data";
+ mips_elf_data_symbol.flags = BSF_SECTION_SYM;
+ mips_elf_data_symbol.section = &mips_elf_data_section;
+ mips_elf_data_symbol_ptr = &mips_elf_data_symbol;
+ mips_elf_data_section_ptr = &mips_elf_data_section;
+ }
+ if (info->shared)
+ *secp = bfd_und_section_ptr;
+ else
+ *secp = mips_elf_data_section_ptr;
+ break;
+
+ case SHN_MIPS_SUNDEFINED:
+ *secp = bfd_und_section_ptr;
+ break;
+ }
+
+ return true;
+}
+
+/* Structure used to pass information to mips_elf_output_extsym. */
+
+struct extsym_info
+{
+ bfd *abfd;
+ struct bfd_link_info *info;
+ struct ecoff_debug_info *debug;
+ const struct ecoff_debug_swap *swap;
+ boolean failed;
+};
+
+/* This routine is used to write out ECOFF debugging external symbol
+ information. It is called via mips_elf_link_hash_traverse. The
+ ECOFF external symbol information must match the ELF external
+ symbol information. Unfortunately, at this point we don't know
+ whether a symbol is required by reloc information, so the two
+ tables may wind up being different. We must sort out the external
+ symbol information before we can set the final size of the .mdebug
+ section, and we must set the size of the .mdebug section before we
+ can relocate any sections, and we can't know which symbols are
+ required by relocation until we relocate the sections.
+ Fortunately, it is relatively unlikely that any symbol will be
+ stripped but required by a reloc. In particular, it can not happen
+ when generating a final executable. */
+
+static boolean
+mips_elf_output_extsym (h, data)
+ struct mips_elf_link_hash_entry *h;
+ PTR data;
+{
+ struct extsym_info *einfo = (struct extsym_info *) data;
+ boolean strip;
+ asection *sec, *output_section;
+
+ if (h->root.indx == -2)
+ strip = false;
+ else if (((h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
+ && (h->root.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ && (h->root.elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+ strip = true;
+ else if (einfo->info->strip == strip_all
+ || (einfo->info->strip == strip_some
+ && bfd_hash_lookup (einfo->info->keep_hash,
+ h->root.root.root.string,
+ false, false) == NULL))
+ strip = true;
+ else
+ strip = false;
+
+ if (strip)
+ return true;
+
+ if (h->esym.ifd == -2)
+ {
+ 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 (SGI_COMPAT (einfo->abfd)
+ && (h->root.root.type == bfd_link_hash_undefined
+ || h->root.root.type == bfd_link_hash_undefweak))
+ {
+ const char *name;
+
+ /* Use undefined class. Also, set class and type for some
+ special symbols. */
+ name = h->root.root.root.string;
+ if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
+ || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
+ {
+ h->esym.asym.sc = scData;
+ h->esym.asym.st = stLabel;
+ h->esym.asym.value = 0;
+ }
+ else if (strcmp (name, mips_elf_dynsym_rtproc_names[2]) == 0)
+ {
+ h->esym.asym.sc = scAbs;
+ h->esym.asym.st = stLabel;
+ h->esym.asym.value =
+ mips_elf_hash_table (einfo->info)->procedure_count;
+ }
+ else if (strcmp (name, "_gp_disp") == 0)
+ {
+ h->esym.asym.sc = scAbs;
+ h->esym.asym.st = stLabel;
+ h->esym.asym.value = elf_gp (einfo->abfd);
+ }
+ else
+ h->esym.asym.sc = scUndefined;
+ }
+ else if (h->root.root.type != bfd_link_hash_defined
+ && h->root.root.type != bfd_link_hash_defweak)
+ h->esym.asym.sc = scAbs;
+ else
+ {
+ const char *name;
+
+ sec = h->root.root.u.def.section;
+ output_section = sec->output_section;
+
+ /* When making a shared library and symbol h is the one from
+ the another shared library, OUTPUT_SECTION may be null. */
+ if (output_section == NULL)
+ h->esym.asym.sc = scUndefined;
+ else
+ {
+ 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, ".rodata") == 0
+ || 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
+ h->esym.asym.sc = scAbs;
+ }
+ }
+
+ h->esym.asym.reserved = 0;
+ h->esym.asym.index = indexNil;
+ }
+
+ if (h->root.root.type == bfd_link_hash_common)
+ h->esym.asym.value = h->root.root.u.c.size;
+ else if (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ {
+ if (h->esym.asym.sc == scCommon)
+ h->esym.asym.sc = scBss;
+ else if (h->esym.asym.sc == scSCommon)
+ h->esym.asym.sc = scSBss;
+
+ sec = h->root.root.u.def.section;
+ output_section = sec->output_section;
+ if (output_section != NULL)
+ h->esym.asym.value = (h->root.root.u.def.value
+ + sec->output_offset
+ + output_section->vma);
+ else
+ h->esym.asym.value = 0;
+ }
+ else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ {
+ /* Set type and value for a symbol with a function stub. */
+ h->esym.asym.st = stProc;
+ sec = h->root.root.u.def.section;
+ if (sec == NULL)
+ h->esym.asym.value = 0;
+ else
+ {
+ output_section = sec->output_section;
+ if (output_section != NULL)
+ h->esym.asym.value = (h->root.plt_offset
+ + sec->output_offset
+ + output_section->vma);
+ else
+ h->esym.asym.value = 0;
+ }
+#if 0 /* FIXME? */
+ h->esym.ifd = 0;
+#endif
+ }
+
+ if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap,
+ h->root.root.root.string,
+ &h->esym))
+ {
+ einfo->failed = true;
+ return false;
+ }
+
+ return true;
+}
+
+/* Create a runtime procedure table from the .mdebug section. */
+
+static boolean
+mips_elf_create_procedure_table (handle, abfd, info, s, debug)
+ PTR handle;
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *s;
+ struct ecoff_debug_info *debug;
+{
+ const struct ecoff_debug_swap *swap;
+ HDRR *hdr = &debug->symbolic_header;
+ RPDR *rpdr, *rp;
+ struct rpdr_ext *erp;
+ PTR rtproc;
+ struct pdr_ext *epdr;
+ struct sym_ext *esym;
+ char *ss, **sv;
+ char *str;
+ unsigned long size, count;
+ unsigned long sindex;
+ unsigned long i;
+ PDR pdr;
+ SYMR sym;
+ const char *no_name_func = "static procedure (no name)";
+
+ epdr = NULL;
+ rpdr = NULL;
+ esym = NULL;
+ ss = NULL;
+ sv = NULL;
+
+ swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+
+ sindex = strlen (no_name_func) + 1;
+ count = hdr->ipdMax;
+ if (count > 0)
+ {
+ size = swap->external_pdr_size;
+
+ epdr = (struct pdr_ext *) bfd_malloc (size * count);
+ if (epdr == NULL)
+ goto error_return;
+
+ if (! _bfd_ecoff_get_accumulated_pdr (handle, (PTR) epdr))
+ goto error_return;
+
+ size = sizeof (RPDR);
+ rp = rpdr = (RPDR *) bfd_malloc (size * count);
+ if (rpdr == NULL)
+ goto error_return;
+
+ sv = (char **) bfd_malloc (sizeof (char *) * count);
+ if (sv == NULL)
+ goto error_return;
+
+ count = hdr->isymMax;
+ size = swap->external_sym_size;
+ esym = (struct sym_ext *) bfd_malloc (size * count);
+ if (esym == NULL)
+ goto error_return;
+
+ if (! _bfd_ecoff_get_accumulated_sym (handle, (PTR) esym))
+ goto error_return;
+
+ count = hdr->issMax;
+ ss = (char *) bfd_malloc (count);
+ if (ss == NULL)
+ goto error_return;
+ if (! _bfd_ecoff_get_accumulated_ss (handle, (PTR) ss))
+ goto error_return;
+
+ count = hdr->ipdMax;
+ for (i = 0; i < count; i++, rp++)
+ {
+ (*swap->swap_pdr_in) (abfd, (PTR) (epdr + i), &pdr);
+ (*swap->swap_sym_in) (abfd, (PTR) &esym[pdr.isym], &sym);
+ rp->adr = sym.value;
+ rp->regmask = pdr.regmask;
+ rp->regoffset = pdr.regoffset;
+ rp->fregmask = pdr.fregmask;
+ rp->fregoffset = pdr.fregoffset;
+ rp->frameoffset = pdr.frameoffset;
+ rp->framereg = pdr.framereg;
+ rp->pcreg = pdr.pcreg;
+ rp->irpss = sindex;
+ sv[i] = ss + sym.iss;
+ sindex += strlen (sv[i]) + 1;
+ }
+ }
+
+ size = sizeof (struct rpdr_ext) * (count + 2) + sindex;
+ size = BFD_ALIGN (size, 16);
+ rtproc = (PTR) bfd_alloc (abfd, size);
+ if (rtproc == NULL)
+ {
+ mips_elf_hash_table (info)->procedure_count = 0;
+ goto error_return;
+ }
+
+ mips_elf_hash_table (info)->procedure_count = count + 2;
+
+ erp = (struct rpdr_ext *) rtproc;
+ memset (erp, 0, sizeof (struct rpdr_ext));
+ erp++;
+ str = (char *) rtproc + sizeof (struct rpdr_ext) * (count + 2);
+ strcpy (str, no_name_func);
+ str += strlen (no_name_func) + 1;
+ for (i = 0; i < count; i++)
+ {
+ ecoff_swap_rpdr_out (abfd, rpdr + i, erp + i);
+ strcpy (str, sv[i]);
+ str += strlen (sv[i]) + 1;
+ }
+ ecoff_put_off (abfd, (bfd_vma) -1, (bfd_byte *) (erp + count)->p_adr);
+
+ /* Set the size and contents of .rtproc section. */
+ s->_raw_size = size;
+ s->contents = rtproc;
+
+ /* Skip this section later on (I don't think this currently
+ matters, but someday it might). */
+ s->link_order_head = (struct bfd_link_order *) NULL;
+
+ if (epdr != NULL)
+ free (epdr);
+ if (rpdr != NULL)
+ free (rpdr);
+ if (esym != NULL)
+ free (esym);
+ if (ss != NULL)
+ free (ss);
+ if (sv != NULL)
+ free (sv);
+
+ return true;
+
+ error_return:
+ if (epdr != NULL)
+ free (epdr);
+ if (rpdr != NULL)
+ free (rpdr);
+ if (esym != NULL)
+ free (esym);
+ if (ss != NULL)
+ free (ss);
+ if (sv != NULL)
+ free (sv);
+ return false;
+}
+
+/* A comparison routine used to sort .gptab entries. */
+
+static int
+gptab_compare (p1, p2)
+ const PTR p1;
+ const PTR p2;
+{
+ const Elf32_gptab *a1 = (const Elf32_gptab *) p1;
+ const Elf32_gptab *a2 = (const Elf32_gptab *) p2;
+
+ return a1->gt_entry.gt_g_value - a2->gt_entry.gt_g_value;
+}
+
+/* We need to use a special link routine to handle the .reginfo and
+ the .mdebug sections. We need to merge all instances of these
+ sections together, not write them all out sequentially. */
+
+static boolean
+mips_elf_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ asection **secpp;
+ asection *o;
+ struct bfd_link_order *p;
+ asection *reginfo_sec, *mdebug_sec, *gptab_data_sec, *gptab_bss_sec;
+ asection *rtproc_sec;
+ Elf32_RegInfo reginfo;
+ struct ecoff_debug_info debug;
+ const struct ecoff_debug_swap *swap
+ = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
+ HDRR *symhdr = &debug.symbolic_header;
+ PTR mdebug_handle = NULL;
+
+ /* Drop the .options section, since it has special semantics which I
+ haven't bothered to figure out. */
+ for (secpp = &abfd->sections; *secpp != NULL; secpp = &(*secpp)->next)
+ {
+ if (strcmp ((*secpp)->name, ".options") == 0)
+ {
+ for (p = (*secpp)->link_order_head; p != NULL; p = p->next)
+ if (p->type == bfd_indirect_link_order)
+ p->u.indirect.section->flags &=~ SEC_HAS_CONTENTS;
+ (*secpp)->link_order_head = NULL;
+ *secpp = (*secpp)->next;
+ --abfd->section_count;
+ break;
+ }
+ }
+
+ /* Get a value for the GP register. */
+ if (elf_gp (abfd) == 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)
+ elf_gp (abfd) = (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))
+ lo = o->vma;
+ }
+ elf_gp (abfd) = lo + ELF_MIPS_GP_OFFSET (abfd);
+ }
+ 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. */
+ }
+ }
+
+ /* Go through the sections and collect the .reginfo and .mdebug
+ information. */
+ reginfo_sec = NULL;
+ mdebug_sec = NULL;
+ gptab_data_sec = NULL;
+ gptab_bss_sec = NULL;
+ for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ {
+ if (strcmp (o->name, ".reginfo") == 0)
+ {
+ memset (&reginfo, 0, sizeof reginfo);
+
+ /* We have found the .reginfo section in the output file.
+ Look through all the link_orders comprising it and merge
+ the information together. */
+ for (p = o->link_order_head;
+ p != (struct bfd_link_order *) NULL;
+ p = p->next)
+ {
+ asection *input_section;
+ bfd *input_bfd;
+ Elf32_External_RegInfo ext;
+ Elf32_RegInfo sub;
+
+ if (p->type != bfd_indirect_link_order)
+ {
+ if (p->type == bfd_fill_link_order)
+ continue;
+ abort ();
+ }
+
+ input_section = p->u.indirect.section;
+ input_bfd = input_section->owner;
+
+ /* The linker emulation code has probably clobbered the
+ size to be zero bytes. */
+ if (input_section->_raw_size == 0)
+ input_section->_raw_size = sizeof (Elf32_External_RegInfo);
+
+ if (! bfd_get_section_contents (input_bfd, input_section,
+ (PTR) &ext,
+ (file_ptr) 0,
+ sizeof ext))
+ return false;
+
+ bfd_mips_elf32_swap_reginfo_in (input_bfd, &ext, &sub);
+
+ reginfo.ri_gprmask |= sub.ri_gprmask;
+ reginfo.ri_cprmask[0] |= sub.ri_cprmask[0];
+ reginfo.ri_cprmask[1] |= sub.ri_cprmask[1];
+ reginfo.ri_cprmask[2] |= sub.ri_cprmask[2];
+ reginfo.ri_cprmask[3] |= sub.ri_cprmask[3];
+
+ /* ri_gp_value is set by the function
+ mips_elf_section_processing when the section is
+ finally written out. */
+
+ /* Hack: reset the SEC_HAS_CONTENTS flag so that
+ elf_link_input_bfd ignores this section. */
+ input_section->flags &=~ SEC_HAS_CONTENTS;
+ }
+
+ /* Force the section size to the value we want. */
+ o->_raw_size = sizeof (Elf32_External_RegInfo);
+
+ /* Skip this section later on (I don't think this currently
+ matters, but someday it might). */
+ o->link_order_head = (struct bfd_link_order *) NULL;
+
+ reginfo_sec = o;
+ }
+
+ if (strcmp (o->name, ".mdebug") == 0)
+ {
+ struct extsym_info einfo;
+
+ /* We have found the .mdebug section in the output file.
+ Look through all the link_orders comprising it and merge
+ the information together. */
+ symhdr->magic = swap->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;
+
+ /* 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;
+
+ mdebug_handle = bfd_ecoff_debug_init (abfd, &debug, swap, info);
+ if (mdebug_handle == (PTR) NULL)
+ return false;
+
+ if (SGI_COMPAT (abfd))
+ {
+ asection *s;
+ EXTR esym;
+ bfd_vma last;
+ unsigned int i;
+ static const char * const name[] =
+ { ".text", ".init", ".fini", ".data",
+ ".rodata", ".sdata", ".sbss", ".bss" };
+ static const int sc[] = { scText, scInit, scFini, scData,
+ scRData, scSData, scSBss, scBss };
+
+ esym.jmptbl = 0;
+ esym.cobol_main = 0;
+ esym.weakext = 0;
+ esym.reserved = 0;
+ esym.ifd = ifdNil;
+ esym.asym.iss = issNil;
+ esym.asym.st = stLocal;
+ esym.asym.reserved = 0;
+ esym.asym.index = indexNil;
+ for (i = 0; i < 8; i++)
+ {
+ esym.asym.sc = sc[i];
+ s = bfd_get_section_by_name (abfd, name[i]);
+ if (s != NULL)
+ {
+ esym.asym.value = s->vma;
+ last = s->vma + s->_raw_size;
+ }
+ else
+ esym.asym.value = last;
+
+ if (! bfd_ecoff_debug_one_external (abfd, &debug, swap,
+ name[i], &esym))
+ return false;
+ }
+ }
+
+ for (p = o->link_order_head;
+ p != (struct bfd_link_order *) NULL;
+ p = p->next)
+ {
+ asection *input_section;
+ bfd *input_bfd;
+ const struct ecoff_debug_swap *input_swap;
+ struct ecoff_debug_info input_debug;
+ char *eraw_src;
+ char *eraw_end;
+
+ if (p->type != bfd_indirect_link_order)
+ {
+ if (p->type == bfd_fill_link_order)
+ continue;
+ abort ();
+ }
+
+ input_section = p->u.indirect.section;
+ input_bfd = input_section->owner;
+
+ if (bfd_get_flavour (input_bfd) != bfd_target_elf_flavour
+ || (get_elf_backend_data (input_bfd)
+ ->elf_backend_ecoff_debug_swap) == NULL)
+ {
+ /* I don't know what a non MIPS ELF bfd would be
+ doing with a .mdebug section, but I don't really
+ want to deal with it. */
+ continue;
+ }
+
+ input_swap = (get_elf_backend_data (input_bfd)
+ ->elf_backend_ecoff_debug_swap);
+
+ BFD_ASSERT (p->size == input_section->_raw_size);
+
+ /* The ECOFF linking code expects that we have already
+ read in the debugging information and set up an
+ ecoff_debug_info structure, so we do that now. */
+ if (! mips_elf_read_ecoff_info (input_bfd, input_section,
+ &input_debug))
+ return false;
+
+ if (! (bfd_ecoff_debug_accumulate
+ (mdebug_handle, abfd, &debug, swap, input_bfd,
+ &input_debug, input_swap, info)))
+ return false;
+
+ /* Loop through the external symbols. For each one with
+ interesting information, try to find the symbol in
+ the linker global hash table and save the information
+ for the output external symbols. */
+ eraw_src = input_debug.external_ext;
+ eraw_end = (eraw_src
+ + (input_debug.symbolic_header.iextMax
+ * input_swap->external_ext_size));
+ for (;
+ eraw_src < eraw_end;
+ eraw_src += input_swap->external_ext_size)
+ {
+ EXTR ext;
+ const char *name;
+ struct mips_elf_link_hash_entry *h;
+
+ (*input_swap->swap_ext_in) (input_bfd, (PTR) eraw_src, &ext);
+ if (ext.asym.sc == scNil
+ || ext.asym.sc == scUndefined
+ || ext.asym.sc == scSUndefined)
+ continue;
+
+ name = input_debug.ssext + ext.asym.iss;
+ h = mips_elf_link_hash_lookup (mips_elf_hash_table (info),
+ name, false, false, true);
+ if (h == NULL || h->esym.ifd != -2)
+ continue;
+
+ if (ext.ifd != -1)
+ {
+ BFD_ASSERT (ext.ifd
+ < input_debug.symbolic_header.ifdMax);
+ ext.ifd = input_debug.ifdmap[ext.ifd];
+ }
+
+ h->esym = ext;
+ }
+
+ /* Free up the information we just read. */
+ free (input_debug.line);
+ free (input_debug.external_dnr);
+ free (input_debug.external_pdr);
+ free (input_debug.external_sym);
+ free (input_debug.external_opt);
+ free (input_debug.external_aux);
+ free (input_debug.ss);
+ free (input_debug.ssext);
+ free (input_debug.external_fdr);
+ free (input_debug.external_rfd);
+ free (input_debug.external_ext);
+
+ /* Hack: reset the SEC_HAS_CONTENTS flag so that
+ elf_link_input_bfd ignores this section. */
+ input_section->flags &=~ SEC_HAS_CONTENTS;
+ }
+
+ if (SGI_COMPAT (abfd) && info->shared)
+ {
+ /* Create .rtproc section. */
+ rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
+ if (rtproc_sec == NULL)
+ {
+ flagword flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_READONLY);
+
+ rtproc_sec = bfd_make_section (abfd, ".rtproc");
+ if (rtproc_sec == NULL
+ || ! bfd_set_section_flags (abfd, rtproc_sec, flags)
+ || ! bfd_set_section_alignment (abfd, rtproc_sec, 12))
+ return false;
+ }
+
+ if (! mips_elf_create_procedure_table (mdebug_handle, abfd,
+ info, rtproc_sec, &debug))
+ return false;
+ }
+
+ /* Build the external symbol information. */
+ einfo.abfd = abfd;
+ einfo.info = info;
+ einfo.debug = &debug;
+ einfo.swap = swap;
+ einfo.failed = false;
+ mips_elf_link_hash_traverse (mips_elf_hash_table (info),
+ mips_elf_output_extsym,
+ (PTR) &einfo);
+ if (einfo.failed)
+ return false;
+
+ /* Set the size of the .mdebug section. */
+ o->_raw_size = bfd_ecoff_debug_size (abfd, &debug, swap);
+
+ /* Skip this section later on (I don't think this currently
+ matters, but someday it might). */
+ o->link_order_head = (struct bfd_link_order *) NULL;
+
+ mdebug_sec = o;
+ }
+
+ if (strncmp (o->name, ".gptab.", sizeof ".gptab." - 1) == 0)
+ {
+ const char *subname;
+ unsigned int c;
+ Elf32_gptab *tab;
+ Elf32_External_gptab *ext_tab;
+ unsigned int i;
+
+ /* The .gptab.sdata and .gptab.sbss sections hold
+ information describing how the small data area would
+ change depending upon the -G switch. These sections
+ not used in executables files. */
+ if (! info->relocateable)
+ {
+ asection **secpp;
+
+ for (p = o->link_order_head;
+ p != (struct bfd_link_order *) NULL;
+ p = p->next)
+ {
+ asection *input_section;
+
+ if (p->type != bfd_indirect_link_order)
+ {
+ if (p->type == bfd_fill_link_order)
+ continue;
+ abort ();
+ }
+
+ input_section = p->u.indirect.section;
+
+ /* Hack: reset the SEC_HAS_CONTENTS flag so that
+ elf_link_input_bfd ignores this section. */
+ input_section->flags &=~ SEC_HAS_CONTENTS;
+ }
+
+ /* Skip this section later on (I don't think this
+ currently matters, but someday it might). */
+ o->link_order_head = (struct bfd_link_order *) NULL;
+
+ /* Really remove the section. */
+ for (secpp = &abfd->sections;
+ *secpp != o;
+ secpp = &(*secpp)->next)
+ ;
+ *secpp = (*secpp)->next;
+ --abfd->section_count;
+
+ continue;
+ }
+
+ /* There is one gptab for initialized data, and one for
+ uninitialized data. */
+ if (strcmp (o->name, ".gptab.sdata") == 0)
+ gptab_data_sec = o;
+ else if (strcmp (o->name, ".gptab.sbss") == 0)
+ gptab_bss_sec = o;
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: illegal section name `%s'",
+ bfd_get_filename (abfd), o->name);
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+
+ /* The linker script always combines .gptab.data and
+ .gptab.sdata into .gptab.sdata, and likewise for
+ .gptab.bss and .gptab.sbss. It is possible that there is
+ no .sdata or .sbss section in the output file, in which
+ case we must change the name of the output section. */
+ subname = o->name + sizeof ".gptab" - 1;
+ if (bfd_get_section_by_name (abfd, subname) == NULL)
+ {
+ if (o == gptab_data_sec)
+ o->name = ".gptab.data";
+ else
+ o->name = ".gptab.bss";
+ subname = o->name + sizeof ".gptab" - 1;
+ BFD_ASSERT (bfd_get_section_by_name (abfd, subname) != NULL);
+ }
+
+ /* Set up the first entry. */
+ c = 1;
+ tab = (Elf32_gptab *) bfd_malloc (c * sizeof (Elf32_gptab));
+ if (tab == NULL)
+ return false;
+ tab[0].gt_header.gt_current_g_value = elf_gp_size (abfd);
+ tab[0].gt_header.gt_unused = 0;
+
+ /* Combine the input sections. */
+ for (p = o->link_order_head;
+ p != (struct bfd_link_order *) NULL;
+ p = p->next)
+ {
+ asection *input_section;
+ bfd *input_bfd;
+ bfd_size_type size;
+ unsigned long last;
+ bfd_size_type gpentry;
+
+ if (p->type != bfd_indirect_link_order)
+ {
+ if (p->type == bfd_fill_link_order)
+ continue;
+ abort ();
+ }
+
+ input_section = p->u.indirect.section;
+ input_bfd = input_section->owner;
+
+ /* Combine the gptab entries for this input section one
+ by one. We know that the input gptab entries are
+ sorted by ascending -G value. */
+ size = bfd_section_size (input_bfd, input_section);
+ last = 0;
+ for (gpentry = sizeof (Elf32_External_gptab);
+ gpentry < size;
+ gpentry += sizeof (Elf32_External_gptab))
+ {
+ Elf32_External_gptab ext_gptab;
+ Elf32_gptab int_gptab;
+ unsigned long val;
+ unsigned long add;
+ boolean exact;
+ unsigned int look;
+
+ if (! (bfd_get_section_contents
+ (input_bfd, input_section, (PTR) &ext_gptab,
+ gpentry, sizeof (Elf32_External_gptab))))
+ {
+ free (tab);
+ return false;
+ }
+
+ bfd_mips_elf32_swap_gptab_in (input_bfd, &ext_gptab,
+ &int_gptab);
+ val = int_gptab.gt_entry.gt_g_value;
+ add = int_gptab.gt_entry.gt_bytes - last;
+
+ exact = false;
+ for (look = 1; look < c; look++)
+ {
+ if (tab[look].gt_entry.gt_g_value >= val)
+ tab[look].gt_entry.gt_bytes += add;
+
+ if (tab[look].gt_entry.gt_g_value == val)
+ exact = true;
+ }
+
+ if (! exact)
+ {
+ Elf32_gptab *new_tab;
+ unsigned int max;
+
+ /* We need a new table entry. */
+ new_tab = ((Elf32_gptab *)
+ bfd_realloc ((PTR) tab,
+ (c + 1) * sizeof (Elf32_gptab)));
+ if (new_tab == NULL)
+ {
+ free (tab);
+ return false;
+ }
+ tab = new_tab;
+ tab[c].gt_entry.gt_g_value = val;
+ tab[c].gt_entry.gt_bytes = add;
+
+ /* Merge in the size for the next smallest -G
+ value, since that will be implied by this new
+ value. */
+ max = 0;
+ for (look = 1; look < c; look++)
+ {
+ if (tab[look].gt_entry.gt_g_value < val
+ && (max == 0
+ || (tab[look].gt_entry.gt_g_value
+ > tab[max].gt_entry.gt_g_value)))
+ max = look;
+ }
+ if (max != 0)
+ tab[c].gt_entry.gt_bytes +=
+ tab[max].gt_entry.gt_bytes;
+
+ ++c;
+ }
+
+ last = int_gptab.gt_entry.gt_bytes;
+ }
+
+ /* Hack: reset the SEC_HAS_CONTENTS flag so that
+ elf_link_input_bfd ignores this section. */
+ input_section->flags &=~ SEC_HAS_CONTENTS;
+ }
+
+ /* The table must be sorted by -G value. */
+ if (c > 2)
+ qsort (tab + 1, c - 1, sizeof (tab[0]), gptab_compare);
+
+ /* Swap out the table. */
+ ext_tab = ((Elf32_External_gptab *)
+ bfd_alloc (abfd, c * sizeof (Elf32_External_gptab)));
+ if (ext_tab == NULL)
+ {
+ free (tab);
+ return false;
+ }
+
+ for (i = 0; i < c; i++)
+ bfd_mips_elf32_swap_gptab_out (abfd, tab + i, ext_tab + i);
+ free (tab);
+
+ o->_raw_size = c * sizeof (Elf32_External_gptab);
+ o->contents = (bfd_byte *) ext_tab;
+
+ /* Skip this section later on (I don't think this currently
+ matters, but someday it might). */
+ o->link_order_head = (struct bfd_link_order *) NULL;
+ }
+ }
+
+ /* Invoke the regular ELF backend linker to do all the work. */
+ if (! bfd_elf32_bfd_final_link (abfd, info))
+ return false;
+
+ /* Now write out the computed sections. */
+
+ if (reginfo_sec != (asection *) NULL)
+ {
+ Elf32_External_RegInfo ext;
+
+ bfd_mips_elf32_swap_reginfo_out (abfd, &reginfo, &ext);
+ if (! bfd_set_section_contents (abfd, reginfo_sec, (PTR) &ext,
+ (file_ptr) 0, sizeof ext))
+ return false;
+ }
+
+ if (mdebug_sec != (asection *) NULL)
+ {
+ BFD_ASSERT (abfd->output_has_begun);
+ if (! bfd_ecoff_write_accumulated_debug (mdebug_handle, abfd, &debug,
+ swap, info,
+ mdebug_sec->filepos))
+ return false;
+
+ bfd_ecoff_debug_free (mdebug_handle, abfd, &debug, swap, info);
+ }
+
+ if (gptab_data_sec != (asection *) NULL)
+ {
+ if (! bfd_set_section_contents (abfd, gptab_data_sec,
+ gptab_data_sec->contents,
+ (file_ptr) 0,
+ gptab_data_sec->_raw_size))
+ return false;
+ }
+
+ if (gptab_bss_sec != (asection *) NULL)
+ {
+ if (! bfd_set_section_contents (abfd, gptab_bss_sec,
+ gptab_bss_sec->contents,
+ (file_ptr) 0,
+ gptab_bss_sec->_raw_size))
+ return false;
+ }
+
+ if (SGI_COMPAT (abfd))
+ {
+ rtproc_sec = bfd_get_section_by_name (abfd, ".rtproc");
+ if (rtproc_sec != NULL)
+ {
+ if (! bfd_set_section_contents (abfd, rtproc_sec,
+ rtproc_sec->contents,
+ (file_ptr) 0,
+ rtproc_sec->_raw_size))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Handle a MIPS ELF HI16 reloc. */
+
+static void
+mips_elf_relocate_hi16 (input_bfd, relhi, rello, contents, addend)
+ bfd *input_bfd;
+ Elf_Internal_Rela *relhi;
+ Elf_Internal_Rela *rello;
+ bfd_byte *contents;
+ bfd_vma addend;
+{
+ bfd_vma insn;
+ bfd_vma addlo;
+
+ insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
+
+ addlo = bfd_get_32 (input_bfd, contents + rello->r_offset);
+ addlo &= 0xffff;
+
+ addend += ((insn & 0xffff) << 16) + addlo;
+
+ if ((addlo & 0x8000) != 0)
+ addend -= 0x10000;
+ if ((addend & 0x8000) != 0)
+ addend += 0x10000;
+
+ bfd_put_32 (input_bfd,
+ (insn & 0xffff0000) | ((addend >> 16) & 0xffff),
+ contents + relhi->r_offset);
+}
+
+/* Handle a MIPS ELF local GOT16 reloc. */
+
+static void
+mips_elf_relocate_got_local (output_bfd, input_bfd, sgot, relhi, rello,
+ contents, addend)
+ bfd *output_bfd;
+ bfd *input_bfd;
+ asection *sgot;
+ Elf_Internal_Rela *relhi;
+ Elf_Internal_Rela *rello;
+ bfd_byte *contents;
+ bfd_vma addend;
+{
+ int local_gotno;
+ int i;
+ bfd_vma insn;
+ bfd_vma addlo;
+ bfd_vma address;
+ bfd_vma hipage;
+ bfd_byte *got_contents;
+ struct mips_got_info *g;
+
+ insn = bfd_get_32 (input_bfd, contents + relhi->r_offset);
+
+ addlo = bfd_get_32 (input_bfd, contents + rello->r_offset);
+ addlo &= 0xffff;
+
+ addend += ((insn & 0xffff) << 16) + addlo;
+
+ if ((addlo & 0x8000) != 0)
+ addend -= 0x10000;
+ if ((addend & 0x8000) != 0)
+ addend += 0x10000;
+
+ /* Get a got entry representing requested hipage. */
+ BFD_ASSERT (elf_section_data (sgot) != NULL);
+ g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+ BFD_ASSERT (g != NULL);
+
+ local_gotno = g->local_gotno;
+ got_contents = sgot->contents;
+ hipage = addend & 0xffff0000;
+
+ for (i = MIPS_RESERVED_GOTNO; i < local_gotno; i++)
+ {
+ address = bfd_get_32 (input_bfd, got_contents + i * 4);
+ if (hipage == (address & 0xffff0000))
+ break;
+ if (address == (bfd_vma) 0)
+ {
+ bfd_put_32 (input_bfd, hipage, got_contents + i * 4);
+ break;
+ }
+ }
+
+ BFD_ASSERT (i < local_gotno);
+#if 1
+ if (i == local_gotno)
+ (*_bfd_error_handler)
+ ("ELF MIPS linker: more got entries are needed for hipage: %x",
+ hipage);
+#endif
+
+ i = - ELF_MIPS_GP_OFFSET (output_bfd) + i * 4;
+ bfd_put_32 (input_bfd, (insn & 0xffff0000) | (i & 0xffff),
+ contents + relhi->r_offset);
+}
+
+/* Handle MIPS ELF CALL16 reloc and global GOT16 reloc. */
+
+static void
+mips_elf_relocate_global_got (input_bfd, rel, contents, offset)
+ bfd *input_bfd;
+ Elf_Internal_Rela *rel;
+ bfd_byte *contents;
+ bfd_vma offset;
+{
+ bfd_vma insn;
+
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ bfd_put_32 (input_bfd,
+ (insn & 0xffff0000) | (offset & 0xffff),
+ contents + rel->r_offset);
+}
+
+/* Relocate a MIPS ELF section. */
+
+static boolean
+mips_elf_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ 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;
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ size_t locsymcount;
+ size_t extsymoff;
+ asection *sgot, *sreloc, *scpt;
+ bfd *dynobj;
+ bfd_vma gp;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+ struct mips_got_info *g;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+
+ sgot = NULL;
+ sreloc = NULL;
+ if (dynobj == NULL || ! SGI_COMPAT (output_bfd))
+ scpt = NULL;
+ else
+ scpt = bfd_get_section_by_name (dynobj, ".compact_rel");
+ g = NULL;
+
+ if (elf_bad_symtab (input_bfd))
+ {
+ locsymcount = symtab_hdr->sh_size / sizeof (Elf32_External_Sym);
+ extsymoff = 0;
+ }
+ else
+ {
+ locsymcount = symtab_hdr->sh_info;
+ extsymoff = symtab_hdr->sh_info;
+ }
+
+ gp = _bfd_get_gp_value (output_bfd);
+
+ rel = relocs;
+ relend = relocs + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ int r_type;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ bfd_vma addend;
+ struct elf_link_hash_entry *h;
+ asection *sec;
+ Elf_Internal_Sym *sym;
+ bfd_reloc_status_type r;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type < 0 || r_type >= (int) R_MIPS_max)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ howto = elf_mips_howto_table + r_type;
+
+ if (dynobj != NULL
+ && (r_type == R_MIPS_CALL16
+ || r_type == R_MIPS_GOT16
+ || r_type == R_MIPS_CALL_HI16
+ || r_type == R_MIPS_CALL_LO16
+ || r_type == R_MIPS_GOT_HI16
+ || r_type == R_MIPS_GOT_LO16))
+ {
+ /* We need the .got section. */
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ BFD_ASSERT (elf_section_data (sgot) != NULL);
+ g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+ BFD_ASSERT (g != NULL);
+ }
+ }
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ /* Mix in the change in GP address for a GP relative reloc. */
+ if (r_type != R_MIPS_GPREL16
+ && r_type != R_MIPS_LITERAL
+ && r_type != R_MIPS_GPREL32)
+ addend = 0;
+ else
+ {
+ if (gp == 0)
+ {
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info,
+ "GP relative relocation when GP not defined",
+ input_bfd, input_section,
+ rel->r_offset)))
+ return false;
+ /* Only give the error once per link. */
+ gp = 4;
+ _bfd_set_gp_value (output_bfd, gp);
+ }
+
+ if (r_symndx < extsymoff
+ || (elf_bad_symtab (input_bfd)
+ && local_sections[r_symndx] != NULL))
+ {
+ /* This is a relocation against a section. The current
+ addend in the instruction is the difference between
+ INPUT_SECTION->vma and the GP value of INPUT_BFD. We
+ must change this to be the difference between the
+ final definition (which will end up in RELOCATION)
+ and the GP value of OUTPUT_BFD (which is in GP). */
+ addend = elf_gp (input_bfd) - gp;
+ }
+ else if (! info->relocateable)
+ {
+ /* We are doing a final link. The current addend in the
+ instruction is simply the desired offset into the
+ symbol (normally zero). We want the instruction to
+ hold the difference between the final definition of
+ the symbol (which will end up in RELOCATION) and the
+ GP value of OUTPUT_BFD (which is in GP). */
+ addend = - gp;
+ }
+ else
+ {
+ /* We are generating relocateable output, and we aren't
+ going to define this symbol, so we just leave the
+ instruction alone. */
+ addend = 0;
+ }
+ }
+
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+ if (info->relocateable)
+ {
+ /* This is a relocateable link. We don't have to change
+ anything, unless the reloc is against a section symbol,
+ in which case we have to adjust according to where the
+ section symbol winds up in the output section. */
+ if (r_symndx >= locsymcount
+ || (elf_bad_symtab (input_bfd)
+ && local_sections[r_symndx] == NULL))
+ r = bfd_reloc_ok;
+ else
+ {
+ sym = local_syms + r_symndx;
+ if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
+ r = bfd_reloc_ok;
+ else
+ {
+ sec = local_sections[r_symndx];
+
+ /* It would be logical to add sym->st_value here,
+ but Irix 5 sometimes generates a garbage symbol
+ value. */
+ addend += sec->output_offset;
+
+ /* If this is HI16 or GOT16 with an associated LO16,
+ adjust the addend accordingly. Otherwise, just
+ relocate. */
+ if ((r_type != R_MIPS_HI16 && r_type != R_MIPS_GOT16)
+ || (rel + 1) >= relend
+ || ELF32_R_TYPE ((rel + 1)->r_info) != R_MIPS_LO16)
+ r = _bfd_relocate_contents (howto, input_bfd,
+ addend,
+ contents + rel->r_offset);
+ else
+ {
+ mips_elf_relocate_hi16 (input_bfd, rel, rel + 1,
+ contents, addend);
+ r = bfd_reloc_ok;
+ }
+ }
+ }
+ }
+ else
+ {
+ bfd_vma relocation;
+ boolean local;
+
+ /* This is a final link. */
+ sym = NULL;
+ if (r_symndx < extsymoff
+ || (elf_bad_symtab (input_bfd)
+ && local_sections[r_symndx] != NULL))
+ {
+ local = true;
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ relocation = (sec->output_section->vma
+ + sec->output_offset);
+
+ /* It would be logical to always add sym->st_value here,
+ but Irix 5 sometimes generates a garbage symbol
+ value. */
+ if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
+ relocation += sym->st_value;
+ }
+ else
+ {
+ long indx;
+
+ local = false;
+ indx = r_symndx - extsymoff;
+ h = elf_sym_hashes (input_bfd)[indx];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (strcmp (h->root.root.string, "_gp_disp") == 0)
+ {
+ if (gp == 0)
+ {
+ if (! ((*info->callbacks->reloc_dangerous)
+ (info,
+ "_gp_disp used when GP not defined",
+ input_bfd, input_section,
+ rel->r_offset)))
+ return false;
+ /* Only give the error once per link. */
+ gp = 4;
+ _bfd_set_gp_value (output_bfd, gp);
+ relocation = 0;
+ }
+ else
+ {
+ sec = input_section;
+ if (sec->output_section != NULL)
+ relocation = (gp
+ - (rel->r_offset
+ + sec->output_section->vma
+ + sec->output_offset));
+ else
+ relocation = gp - rel->r_offset;
+ if (r_type == R_MIPS_LO16)
+ relocation += 4;
+ }
+ }
+ else if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ if (sec->output_section == NULL)
+ relocation = 0;
+ else
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else if (info->shared && ! info->symbolic)
+ relocation = 0;
+ else if (strcmp (h->root.root.string, "_DYNAMIC_LINK") == 0)
+ {
+ /* If this is a dynamic link, we should have created
+ a _DYNAMIC_LINK symbol in
+ mips_elf_create_dynamic_sections. Otherwise, we
+ should define the symbol with a value of 0.
+ FIXME: It should probably get into the symbol
+ table somehow as well. */
+ BFD_ASSERT (! info->shared);
+ BFD_ASSERT (bfd_get_section_by_name (output_bfd,
+ ".dynamic") == NULL);
+ relocation = 0;
+ }
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ relocation = 0;
+ }
+ }
+
+ if (r_type == R_MIPS_HI16
+ && (rel + 1) < relend
+ && ELF32_R_TYPE ((rel + 1)->r_info) == R_MIPS_LO16)
+ {
+ mips_elf_relocate_hi16 (input_bfd, rel, rel + 1,
+ contents, relocation + addend);
+ r = bfd_reloc_ok;
+ }
+ else if (r_type == R_MIPS_GOT16 && local)
+ {
+ /* GOT16 must be also with associated LO16 in the local
+ case. In this case, the addend is extracted and the
+ section in which the referenced object is determined.
+ Then the final address of the object is computed and
+ the GOT entry for the hipage (an aligned 64kb chunk)
+ is added to .got section if needed. The offset field
+ of the GOT16-relocated instruction is replaced by the
+ index of this GOT entry for the hipage. */
+ if ((rel + 1) < relend
+ && ELF32_R_TYPE ((rel + 1)->r_info) == R_MIPS_LO16)
+ {
+ mips_elf_relocate_got_local (output_bfd, input_bfd, sgot,
+ rel, rel + 1,
+ contents,
+ relocation + addend);
+ r = bfd_reloc_ok;
+ }
+ else
+ r = bfd_reloc_outofrange;
+ }
+ else if (r_type == R_MIPS_CALL16
+ || r_type == R_MIPS_GOT16
+ || r_type == R_MIPS_CALL_LO16
+ || r_type == R_MIPS_GOT_LO16)
+ {
+ bfd_vma offset;
+
+ /* This symbol must be registered as a global symbol
+ having the corresponding got entry. */
+ BFD_ASSERT (h->got_offset != (bfd_vma) -1);
+
+ offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
+ BFD_ASSERT (g->local_gotno <= offset
+ && offset < sgot->_raw_size);
+ bfd_put_32 (output_bfd, relocation + addend,
+ sgot->contents + offset);
+ offset = (sgot->output_section->vma + sgot->output_offset
+ + offset - gp);
+ mips_elf_relocate_global_got (input_bfd, rel, contents,
+ offset);
+ r = bfd_reloc_ok;
+ }
+ else if (r_type == R_MIPS_CALL_HI16
+ || r_type == R_MIPS_GOT_HI16)
+ {
+ bfd_vma offset;
+
+ /* This must be a global symbol with a got entry. The
+ next reloc must be the corresponding LO16 reloc. */
+ BFD_ASSERT (h != NULL && h->got_offset != (bfd_vma) -1);
+ BFD_ASSERT ((rel + 1) < relend);
+ BFD_ASSERT (ELF32_R_TYPE ((rel + 1)->r_info)
+ == (r_type == R_MIPS_CALL_HI16
+ ? R_MIPS_CALL_LO16
+ : R_MIPS_GOT_LO16));
+
+ offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
+ BFD_ASSERT (g->local_gotno <= offset
+ && offset < sgot->_raw_size);
+ bfd_put_32 (output_bfd, relocation + addend,
+ sgot->contents + offset);
+ offset = (sgot->output_section->vma + sgot->output_offset
+ + offset - gp);
+ mips_elf_relocate_hi16 (input_bfd, rel, rel + 1, contents,
+ offset);
+ r = bfd_reloc_ok;
+ }
+ else if (r_type == R_MIPS_REL32
+ || r_type == R_MIPS_32)
+ {
+ Elf_Internal_Rel outrel;
+ Elf32_crinfo cptrel;
+ bfd_byte *cr;
+
+ if (info->shared
+ && (input_section->flags & SEC_ALLOC) != 0)
+ {
+ /* When generating a shared object, these
+ relocations are copied into the output file to be
+ resolved at run time. */
+ if (sreloc == NULL)
+ {
+ sreloc = bfd_get_section_by_name (dynobj, ".rel.dyn");
+ BFD_ASSERT (sreloc != NULL);
+ }
+
+ outrel.r_offset = (rel->r_offset
+ + input_section->output_section->vma
+ + input_section->output_offset);
+
+ addend = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ if (h != NULL
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ {
+ BFD_ASSERT (h->dynindx != -1);
+ outrel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_REL32);
+ sec = input_section;
+ }
+ else
+ {
+ long indx;
+
+ if (h == NULL)
+ sec = local_sections[r_symndx];
+ else
+ {
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || (h->root.type
+ == bfd_link_hash_defweak));
+ sec = h->root.u.def.section;
+ }
+ if (sec != NULL && bfd_is_abs_section (sec))
+ indx = 0;
+ else if (sec == NULL || sec->owner == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ else
+ {
+ asection *osec;
+
+ osec = sec->output_section;
+ indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ abort ();
+ }
+
+ outrel.r_info = ELF32_R_INFO (indx, R_MIPS_REL32);
+ addend += relocation;
+ }
+
+ bfd_put_32 (output_bfd, addend, contents + rel->r_offset);
+ bfd_elf32_swap_reloc_out (output_bfd, &outrel,
+ (((Elf32_External_Rel *)
+ sreloc->contents)
+ + sreloc->reloc_count));
+ ++sreloc->reloc_count;
+
+ if (SGI_COMPAT (output_bfd))
+ {
+ if (scpt == NULL)
+ continue;
+
+ /* Make an entry of compact relocation info. */
+ mips_elf_set_cr_format (cptrel, CRF_MIPS_LONG);
+ cptrel.vaddr = (rel->r_offset
+ + input_section->output_section->vma
+ + input_section->output_offset);
+ if (r_type == R_MIPS_REL32)
+ mips_elf_set_cr_type (cptrel, CRT_MIPS_REL32);
+ else
+ mips_elf_set_cr_type (cptrel, CRT_MIPS_WORD);
+ mips_elf_set_cr_dist2to (cptrel, 0);
+ cptrel.konst = addend;
+
+ cr = (scpt->contents
+ + sizeof (Elf32_External_compact_rel));
+ bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
+ ((Elf32_External_crinfo *) cr
+ + scpt->reloc_count));
+ ++scpt->reloc_count;
+ }
+
+ /* This reloc will be computed at runtime, so
+ there's no need to do anything now. */
+ continue;
+ }
+ else
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, addend);
+ }
+ else
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, addend);
+
+ if (SGI_COMPAT (abfd)
+ && scpt != NULL
+ && (input_section->flags & SEC_ALLOC) != 0)
+ {
+ Elf32_crinfo cptrel;
+ bfd_byte *cr;
+
+ /* Make an entry of compact relocation info. */
+ mips_elf_set_cr_format (cptrel, CRF_MIPS_LONG);
+ cptrel.vaddr = (rel->r_offset
+ + input_section->output_section->vma
+ + input_section->output_offset);
+
+ switch (r_type)
+ {
+ case R_MIPS_26:
+ mips_elf_set_cr_type (cptrel, CRT_MIPS_JMPAD);
+ /* XXX How should we set dist2to in this case. */
+ mips_elf_set_cr_dist2to (cptrel, 8);
+ cptrel.konst = addend + relocation;
+ cr = scpt->contents + sizeof (Elf32_External_compact_rel);
+ bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
+ ((Elf32_External_crinfo *) cr
+ + scpt->reloc_count));
+ ++scpt->reloc_count;
+ break;
+
+ case R_MIPS_GPREL16:
+ case R_MIPS_LITERAL:
+ case R_MIPS_GPREL32:
+ mips_elf_set_cr_type (cptrel, CRT_MIPS_GPHI_LO);
+ cptrel.konst = gp - cptrel.vaddr;
+ mips_elf_set_cr_dist2to (cptrel, 4);
+ cr = scpt->contents + sizeof (Elf32_External_compact_rel);
+ bfd_elf32_swap_crinfo_out (output_bfd, &cptrel,
+ ((Elf32_External_crinfo *) cr
+ + scpt->reloc_count));
+ ++scpt->reloc_count;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ return false;
+ if (*name == '\0')
+ name = bfd_section_name (input_bfd, sec);
+ }
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0,
+ input_bfd, input_section, rel->r_offset)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Functions for the dynamic linker. */
+
+/* The name of the dynamic interpreter. This is put in the .interp
+ section. */
+
+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"
+
+/* Create dynamic sections when linking against a dynamic object. */
+
+static boolean
+mips_elf_create_dynamic_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ struct elf_link_hash_entry *h;
+ flagword flags;
+ register asection *s;
+ const char * const *namep;
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_READONLY);
+
+ /* Mips ABI requests the .dynamic section to be read only. */
+ s = bfd_get_section_by_name (abfd, ".dynamic");
+ if (s != NULL)
+ {
+ if (! bfd_set_section_flags (abfd, s, flags))
+ return false;
+ }
+
+ /* We need to create .got section. */
+ if (! mips_elf_create_got_section (abfd, info))
+ return false;
+
+ /* Create .stub section. */
+ if (bfd_get_section_by_name (abfd, ".stub") == NULL)
+ {
+ s = bfd_make_section (abfd, ".stub");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ }
+
+ if (SGI_COMPAT (abfd))
+ {
+ for (namep = mips_elf_dynsym_rtproc_names; *namep != NULL; namep++)
+ {
+ h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, *namep, BSF_GLOBAL, bfd_und_section_ptr,
+ (bfd_vma) 0, (const char *) NULL, false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_SECTION;
+
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ /* We need to create a .compact_rel section. */
+ if (! mips_elf_create_compact_rel_section (abfd, info))
+ return false;
+
+ /* Change aligments of some sections. */
+ s = bfd_get_section_by_name (abfd, ".hash");
+ if (s != NULL)
+ bfd_set_section_alignment (abfd, s, 4);
+ s = bfd_get_section_by_name (abfd, ".dynsym");
+ if (s != NULL)
+ bfd_set_section_alignment (abfd, s, 4);
+ s = bfd_get_section_by_name (abfd, ".dynstr");
+ if (s != NULL)
+ bfd_set_section_alignment (abfd, s, 4);
+ s = bfd_get_section_by_name (abfd, ".reginfo");
+ if (s != NULL)
+ bfd_set_section_alignment (abfd, s, 4);
+ s = bfd_get_section_by_name (abfd, ".dynamic");
+ if (s != NULL)
+ bfd_set_section_alignment (abfd, s, 4);
+ }
+
+ if (!info->shared)
+ {
+ h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "_DYNAMIC_LINK", BSF_GLOBAL, bfd_abs_section_ptr,
+ (bfd_vma) 0, (const char *) NULL, false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags ^=~ ELF_LINK_NON_ELF;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_SECTION;
+
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ return true;
+}
+
+/* Create the .compact_rel section. */
+
+static boolean
+mips_elf_create_compact_rel_section (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+
+ if (bfd_get_section_by_name (abfd, ".compact_rel") == NULL)
+ {
+ flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY;
+
+ s = bfd_make_section (abfd, ".compact_rel");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ s->_raw_size = sizeof (Elf32_External_compact_rel);
+ }
+
+ return true;
+}
+
+/* Create the .got section to hold the global offset table. */
+
+static boolean
+mips_elf_create_got_section (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+ struct elf_link_hash_entry *h;
+ struct mips_got_info *g;
+
+ /* This function may be called more than once. */
+ if (bfd_get_section_by_name (abfd, ".got") != NULL)
+ return true;
+
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ s = bfd_make_section (abfd, ".got");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 4))
+ return false;
+
+ /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the
+ linker script because we don't want to define the symbol if we
+ are not creating a global offset table. */
+ h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s,
+ (bfd_vma) 0, (const char *) NULL, false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+ if (info->shared
+ && ! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+
+ /* The first several global offset table entries are reserved. */
+ s->_raw_size = MIPS_RESERVED_GOTNO * 4;
+
+ g = (struct mips_got_info *) bfd_alloc (abfd,
+ sizeof (struct mips_got_info));
+ if (g == NULL)
+ return false;
+ g->global_gotsym = 0;
+ g->local_gotno = MIPS_RESERVED_GOTNO;
+ if (elf_section_data (s) == NULL)
+ {
+ s->used_by_bfd =
+ (PTR) bfd_zalloc (abfd, sizeof (struct bfd_elf_section_data));
+ if (elf_section_data (s) == NULL)
+ return false;
+ }
+ elf_section_data (s)->tdata = (PTR) g;
+
+ return true;
+}
+
+/* Look through the relocs for a section during the first phase, and
+ allocate space in the global offset table. */
+
+static boolean
+mips_elf_check_relocs (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ struct mips_got_info *g;
+ size_t extsymoff;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+ asection *sgot;
+ asection *sreloc;
+
+ if (info->relocateable)
+ return true;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info;
+
+ sgot = NULL;
+ sreloc = NULL;
+
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (r_symndx < extsymoff)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - extsymoff];
+
+ /* Some relocs require a global offset table. */
+ if (dynobj == NULL)
+ {
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_MIPS_GOT16:
+ case R_MIPS_CALL16:
+ case R_MIPS_CALL_HI16:
+ case R_MIPS_CALL_LO16:
+ case R_MIPS_GOT_HI16:
+ case R_MIPS_GOT_LO16:
+ elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (! mips_elf_create_got_section (dynobj, info))
+ return false;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_MIPS_CALL16:
+ case R_MIPS_CALL_HI16:
+ case R_MIPS_CALL_LO16:
+ /* This symbol requires a global offset table entry. */
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ BFD_ASSERT (elf_section_data (sgot) != NULL);
+ g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+ BFD_ASSERT (g != NULL);
+ }
+
+ BFD_ASSERT (h != NULL);
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+
+ /* Note the index of the first global got symbol in .dynsym. */
+ if (g->global_gotsym == 0
+ || g->global_gotsym > (unsigned long) h->dynindx)
+ g->global_gotsym = h->dynindx;
+
+ /* Make this symbol to have the corresponding got entry. */
+ h->got_offset = 0;
+
+ /* We need a stub, not a plt entry for the undefined
+ function. But we record it as if it needs plt. See
+ elf_adjust_dynamic_symbol in elflink.h. */
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ h->type = STT_FUNC;
+
+ break;
+
+ case R_MIPS_GOT16:
+ case R_MIPS_GOT_HI16:
+ case R_MIPS_GOT_LO16:
+ /* This symbol requires a global offset table entry. */
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ BFD_ASSERT (elf_section_data (sgot) != NULL);
+ g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+ BFD_ASSERT (g != NULL);
+ }
+
+ if (h != NULL)
+ {
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+ /* Note the index of the first global got symbol in
+ .dynsym. */
+ if (g->global_gotsym == 0
+ || g->global_gotsym > (unsigned long) h->dynindx)
+ g->global_gotsym = h->dynindx;
+
+ /* Make this symbol to be the global got symbol. */
+ h->got_offset = 0;
+ }
+
+ break;
+
+ case R_MIPS_32:
+ case R_MIPS_REL32:
+ if (info->shared
+ && (sec->flags & SEC_ALLOC) != 0)
+ {
+ /* When creating a shared object, we must copy these
+ reloc types into the output file as R_MIPS_REL32
+ relocs. We create the .rel.dyn reloc section in
+ dynobj and make room for this reloc. */
+ if (sreloc == NULL)
+ {
+ const char *name = ".rel.dyn";
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ if (sreloc == NULL)
+ {
+ sreloc = bfd_make_section (dynobj, name);
+ if (sreloc == NULL
+ || ! bfd_set_section_flags (dynobj, sreloc,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, sreloc, 4))
+ return false;
+
+ /* Add a null element. */
+ sreloc->_raw_size += sizeof (Elf32_External_Rel);
+ ++sreloc->reloc_count;
+ }
+ }
+
+ sreloc->_raw_size += sizeof (Elf32_External_Rel);
+ }
+
+ if (SGI_COMPAT (abfd))
+ mips_elf_hash_table (info)->compact_rel_size +=
+ sizeof (Elf32_External_crinfo);
+
+ break;
+
+ case R_MIPS_26:
+ case R_MIPS_GPREL16:
+ case R_MIPS_LITERAL:
+ case R_MIPS_GPREL32:
+ if (SGI_COMPAT (abfd))
+ mips_elf_hash_table (info)->compact_rel_size +=
+ sizeof (Elf32_External_crinfo);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. The current definition is in some section of the
+ dynamic object, but we're not including those sections. We have to
+ change the definition to something the rest of the link can
+ understand. */
+
+static boolean
+mips_elf_adjust_dynamic_symbol (info, h)
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+{
+ bfd *dynobj;
+ asection *s;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+ || h->weakdef != NULL
+ || ((h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_REGULAR) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+
+ /* For a function, create a stub, if needed. */
+ if (h->type == STT_FUNC
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ {
+ if (! elf_hash_table (info)->dynamic_sections_created)
+ return true;
+
+ /* If this symbol is not defined in a regular file, then set
+ the symbol to the stub location. This is required to make
+ function pointers compare as equal between the normal
+ executable and the shared library. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ /* We need .stub section. */
+ s = bfd_get_section_by_name (dynobj, ".stub");
+ BFD_ASSERT (s != NULL);
+
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+
+ /* XXX Write this stub address somewhere. */
+ h->plt_offset = s->_raw_size;
+
+ /* Make room for this stub code. */
+ s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
+
+ /* The last half word of the stub will be filled with the index
+ of this symbol in .dynsym section. */
+ return true;
+ }
+ }
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->weakdef != NULL)
+ {
+ BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
+ || h->weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->weakdef->root.u.def.section;
+ h->root.u.def.value = h->weakdef->root.u.def.value;
+ return true;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+
+ return true;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static boolean
+mips_elf_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *s;
+ boolean reltext;
+ asection *sgot;
+ struct mips_got_info *g;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (! info->shared)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+
+ /* Recompute the size of .got for local entires (reserved and
+ hipages) if needed. To estimate it, get the upper bound of total
+ size of loadable sections. */
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+
+ if (sgot != NULL)
+ {
+ bfd_size_type loadable_size = 0;
+ bfd_size_type local_gotno;
+ struct _bfd *sub;
+
+ BFD_ASSERT (elf_section_data (sgot) != NULL);
+ g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+ BFD_ASSERT (g != NULL);
+
+ for (sub = info->input_bfds; sub; sub = sub->link_next)
+ for (s = sub->sections; s != NULL; s = s->next)
+ {
+ if ((s->flags & SEC_ALLOC) == 0)
+ continue;
+ loadable_size += (s->_raw_size + 0xf) & ~0xf;
+ }
+
+ loadable_size += MIPS_FUNCTION_STUB_SIZE;
+
+ /* Assume there are two loadable segments consisting of
+ contiguous sections. Is 5 enough? */
+ local_gotno = (loadable_size >> 16) + 5 + MIPS_RESERVED_GOTNO;
+ g->local_gotno = local_gotno;
+ sgot->_raw_size += local_gotno * 4;
+ }
+
+ /* The check_relocs and adjust_dynamic_symbol entry points have
+ determined the sizes of the various dynamic sections. Allocate
+ memory for them. */
+ reltext = false;
+ for (s = dynobj->sections; s != NULL; s = s->next)
+ {
+ const char *name;
+ boolean strip;
+
+ /* It's OK to base decisions on the section name, because none
+ of the dynobj section names depend upon the input files. */
+ name = bfd_get_section_name (dynobj, s);
+
+ if ((s->flags & SEC_IN_MEMORY) == 0)
+ continue;
+
+ strip = false;
+
+ if (strncmp (name, ".rel", 4) == 0)
+ {
+ if (s->_raw_size == 0)
+ strip = true;
+ else
+ {
+ asection *target;
+
+ /* If this relocation section applies to a read only
+ section, then we probably need a DT_TEXTREL entry.
+ If the relocation section is .rel.dyn, we always
+ assert a DT_TEXTREL entry rather than testing whether
+ there exists a relocation to a read only section or
+ not. */
+ target = bfd_get_section_by_name (output_bfd, name + 4);
+ if ((target != NULL && (target->flags & SEC_READONLY) != 0)
+ || strcmp (name, ".rel.dyn") == 0)
+ reltext = true;
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ if (strcmp (name, ".rel.dyn") != 0)
+ s->reloc_count = 0;
+ }
+ }
+ else if (strncmp (name, ".got", 4) == 0)
+ {
+ int i;
+
+ BFD_ASSERT (elf_section_data (s) != NULL);
+ g = (struct mips_got_info *) elf_section_data (s)->tdata;
+ BFD_ASSERT (g != NULL);
+
+ /* Fix the size of .got section for the correspondence of
+ global symbols and got entries. This adds some useless
+ got entries. Is this required by ABI really? */
+ i = elf_hash_table (info)->dynsymcount - g->global_gotsym;
+ s->_raw_size += i * 4;
+ }
+ else if (strncmp (name, ".stub", 5) == 0)
+ {
+ /* Irix rld assumes that the function stub isn't at the end
+ of .text section. So put a dummy. XXX */
+ s->_raw_size += MIPS_FUNCTION_STUB_SIZE;
+ }
+ else if (SGI_COMPAT (output_bfd)
+ && strncmp (name, ".compact_rel", 12) == 0)
+ s->_raw_size += mips_elf_hash_table (info)->compact_rel_size;
+ else if (strncmp (name, ".init", 5) != 0)
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
+
+ if (strip)
+ {
+ asection **spp;
+
+ for (spp = &s->output_section->owner->sections;
+ *spp != s->output_section;
+ spp = &(*spp)->next)
+ ;
+ *spp = s->output_section->next;
+ --s->output_section->owner->section_count;
+
+ continue;
+ }
+
+ /* Allocate memory for the section contents. */
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ memset (s->contents, 0, s->_raw_size);
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Add some entries to the .dynamic section. We fill in the
+ values later, in elf_mips_finish_dynamic_sections, but we
+ must add the entries now so that we get the correct size for
+ the .dynamic section. The DT_DEBUG entry is filled in by the
+ dynamic linker and used by the debugger. */
+ if (! info->shared)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ return false;
+ }
+
+ if (reltext)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+ return false;
+ }
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0))
+ return false;
+
+ if (bfd_get_section_by_name (dynobj, ".rel.dyn"))
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_REL, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_RELSZ, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_RELENT, 0))
+ return false;
+ }
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICTNO, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLISTNO, 0))
+ return false;
+
+ if (bfd_get_section_by_name (dynobj, ".conflict") != NULL)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_CONFLICT, 0))
+ return false;
+
+ s = bfd_get_section_by_name (dynobj, ".liblist");
+ BFD_ASSERT (s != NULL);
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LIBLIST, 0))
+ return false;
+ }
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_RLD_VERSION, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_FLAGS, 0))
+ return false;
+
+#if 0
+ /* Time stamps in executable files are a bad idea. */
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_TIME_STAMP, 0))
+ return false;
+#endif
+
+#if 0 /* FIXME */
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_ICHECKSUM, 0))
+ return false;
+#endif
+
+#if 0 /* FIXME */
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_IVERSION, 0))
+ return false;
+#endif
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_BASE_ADDRESS, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_LOCAL_GOTNO, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_SYMTABNO, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_UNREFEXTNO, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_GOTSYM, 0))
+ return false;
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_MIPS_HIPAGENO, 0))
+ return false;
+
+#if 0 /* (SGI_COMPAT) */
+ if (! bfd_get_section_by_name (dynobj, ".init"))
+ if (! bfd_elf32_add_dynamic_entry (info, DT_INIT, 0))
+ return false;
+
+ if (! bfd_get_section_by_name (dynobj, ".fini"))
+ if (! bfd_elf32_add_dynamic_entry (info, DT_FINI, 0))
+ return false;
+#endif
+ }
+
+ /* If we use dynamic linking, we generate a section symbol for each
+ output section. These are local symbols, which means that they
+ must come first in the dynamic symbol table.
+ That means we must increment the dynamic symbol index of every
+ other dynamic symbol. */
+ {
+ const char * const *namep;
+ unsigned int c, i;
+ bfd_size_type strindex;
+ struct bfd_strtab_hash *dynstr;
+ struct mips_got_info *g;
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ if (SGI_COMPAT (output_bfd))
+ {
+ c = SIZEOF_MIPS_DYNSYM_SECNAMES - 1;
+ elf_link_hash_traverse (elf_hash_table (info),
+ mips_elf_adjust_dynindx,
+ (PTR) &c);
+ elf_hash_table (info)->dynsymcount += c;
+
+ dynstr = elf_hash_table (info)->dynstr;
+ BFD_ASSERT (dynstr != NULL);
+
+ for (i = 1, namep = mips_elf_dynsym_sec_names;
+ *namep != NULL;
+ i++, namep++)
+ {
+ s = bfd_get_section_by_name (output_bfd, *namep);
+ if (s != NULL)
+ elf_section_data (s)->dynindx = i;
+
+ strindex = _bfd_stringtab_add (dynstr, *namep, true, false);
+ if (strindex == (bfd_size_type) -1)
+ return false;
+
+ mips_elf_hash_table (info)->dynsym_sec_strindex[i] = strindex;
+ }
+ }
+ else
+ {
+ c = bfd_count_sections (output_bfd);
+ elf_link_hash_traverse (elf_hash_table (info),
+ mips_elf_adjust_dynindx,
+ (PTR) &c);
+ elf_hash_table (info)->dynsymcount += c;
+
+ for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
+ {
+ elf_section_data (s)->dynindx = i;
+ /* These symbols will have no names, so we don't need to
+ fiddle with dynstr_index. */
+ }
+ }
+ }
+
+ s = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (s != NULL);
+ BFD_ASSERT (elf_section_data (s) != NULL);
+ g = (struct mips_got_info *) elf_section_data (s)->tdata;
+ BFD_ASSERT (g != NULL);
+
+ /* If there are no global got symbols, fake the last symbol so for
+ safety. */
+ if (g->global_gotsym)
+ g->global_gotsym += c;
+ else
+ g->global_gotsym = elf_hash_table (info)->dynsymcount - 1;
+ }
+
+ return true;
+}
+
+/* Increment the index of a dynamic symbol by a given amount. Called
+ via elf_link_hash_traverse. */
+
+static boolean
+mips_elf_adjust_dynindx (h, cparg)
+ struct elf_link_hash_entry *h;
+ PTR cparg;
+{
+ unsigned int *cp = (unsigned int *) cparg;
+
+ if (h->dynindx != -1)
+ h->dynindx += *cp;
+ return true;
+}
+
+/* Finish up dynamic symbol handling. We set the contents of various
+ dynamic sections here. */
+
+static boolean
+mips_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+{
+ bfd *dynobj;
+ bfd_vma gval;
+ asection *sgot;
+ struct mips_got_info *g;
+ const char *name;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ gval = sym->st_value;
+
+ if (h->plt_offset != (bfd_vma) -1)
+ {
+ asection *s;
+ bfd_byte *p;
+ bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
+
+ /* This symbol has a stub. Set it up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ s = bfd_get_section_by_name (dynobj, ".stub");
+ BFD_ASSERT (s != NULL);
+
+ /* Fill the stub. */
+ p = stub;
+ bfd_put_32 (output_bfd, STUB_LW(output_bfd), p);
+ p += 4;
+ bfd_put_32 (output_bfd, STUB_MOVE, p);
+ p += 4;
+
+ /* FIXME: Can h->dynindex be more than 64K? */
+ if (h->dynindx & 0xffff0000)
+ return false;
+
+ bfd_put_32 (output_bfd, STUB_JALR, p);
+ p += 4;
+ bfd_put_32 (output_bfd, STUB_LI16 + h->dynindx, p);
+
+ BFD_ASSERT (h->plt_offset <= s->_raw_size);
+ memcpy (s->contents + h->plt_offset, stub, MIPS_FUNCTION_STUB_SIZE);
+
+ /* Mark the symbol as undefined. plt_offset != -1 occurs
+ only for the referenced symbol. */
+ sym->st_shndx = SHN_UNDEF;
+
+ /* The run-time linker uses the st_value field of the symbol
+ to reset the global offset table entry for this external
+ to its stub address when unlinking a shared object. */
+ gval = s->output_section->vma + s->output_offset + h->plt_offset;
+ sym->st_value = gval;
+ }
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ BFD_ASSERT (elf_section_data (sgot) != NULL);
+ g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+ BFD_ASSERT (g != NULL);
+
+ if ((unsigned long) h->dynindx >= g->global_gotsym)
+ {
+ bfd_size_type offset;
+
+ /* This symbol has an entry in the global offset table. Set its
+ value to the corresponding got entry, if needed. */
+ if (h->got_offset == (bfd_vma) -1)
+ {
+ offset = (h->dynindx - g->global_gotsym + g->local_gotno) * 4;
+ BFD_ASSERT (g->local_gotno * 4 <= offset
+ && offset < sgot->_raw_size);
+ bfd_put_32 (output_bfd, gval, sgot->contents + offset);
+ }
+ }
+
+ /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
+ name = h->root.root.string;
+ if (strcmp (name, "_DYNAMIC") == 0
+ || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+ sym->st_shndx = SHN_ABS;
+ else if (strcmp (name, "_DYNAMIC_LINK") == 0)
+ {
+ sym->st_shndx = SHN_ABS;
+ sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+ sym->st_value = 1;
+ }
+ else if (SGI_COMPAT (output_bfd))
+ {
+ if (strcmp (name, "_gp_disp") == 0)
+ {
+ sym->st_shndx = SHN_ABS;
+ sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+ sym->st_value = elf_gp (output_bfd);
+ }
+ else if (strcmp (name, mips_elf_dynsym_rtproc_names[0]) == 0
+ || strcmp (name, mips_elf_dynsym_rtproc_names[1]) == 0)
+ {
+ sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+ sym->st_other = STO_PROTECTED;
+ sym->st_value = 0;
+ sym->st_shndx = SHN_MIPS_DATA;
+ }
+ else if (strcmp (name, mips_elf_dynsym_rtproc_names[2]) == 0)
+ {
+ sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION);
+ sym->st_other = STO_PROTECTED;
+ sym->st_value = mips_elf_hash_table (info)->procedure_count;
+ sym->st_shndx = SHN_ABS;
+ }
+ else if (sym->st_shndx != SHN_UNDEF)
+ {
+ if (h->type == STT_FUNC)
+ sym->st_shndx = SHN_MIPS_TEXT;
+ else if (h->type == STT_OBJECT)
+ sym->st_shndx = SHN_MIPS_DATA;
+ }
+ }
+
+ return true;
+}
+
+/* Finish up the dynamic sections. */
+
+static boolean
+mips_elf_finish_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *sdyn;
+ asection *sgot;
+ struct mips_got_info *g;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+
+ BFD_ASSERT (elf_section_data (sgot) != NULL);
+ g = (struct mips_got_info *) elf_section_data (sgot)->tdata;
+ BFD_ASSERT (g != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ Elf32_External_Dyn *dyncon, *dynconend;
+
+ BFD_ASSERT (sdyn != NULL);
+
+ dyncon = (Elf32_External_Dyn *) sdyn->contents;
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ size_t elemsize;
+ asection *s;
+
+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ default:
+ break;
+
+ case DT_RELENT:
+ s = bfd_get_section_by_name (dynobj, ".rel.dyn");
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_val = sizeof (Elf32_External_Rel);
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_STRSZ:
+ /* Rewrite DT_STRSZ. */
+ dyn.d_un.d_val =
+ _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_PLTGOT:
+ name = ".got";
+ goto get_vma;
+ case DT_MIPS_CONFLICT:
+ name = ".conflict";
+ goto get_vma;
+ case DT_MIPS_LIBLIST:
+ name = ".liblist";
+ get_vma:
+ s = bfd_get_section_by_name (output_bfd, name);
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_ptr = s->vma;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_RLD_VERSION:
+ dyn.d_un.d_val = 1; /* XXX */
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_FLAGS:
+ dyn.d_un.d_val = RHF_NOTPOT; /* XXX */
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_CONFLICTNO:
+ name = ".conflict";
+ elemsize = sizeof (Elf32_Conflict);
+ goto set_elemno;
+
+ case DT_MIPS_LIBLISTNO:
+ name = ".liblist";
+ elemsize = sizeof (Elf32_Lib);
+ set_elemno:
+ s = bfd_get_section_by_name (output_bfd, name);
+ if (s != NULL)
+ {
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val = s->_cooked_size / elemsize;
+ else
+ dyn.d_un.d_val = s->_raw_size / elemsize;
+ }
+ else
+ dyn.d_un.d_val = 0;
+
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_TIME_STAMP:
+ time ((time_t *) &dyn.d_un.d_val);
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_ICHECKSUM:
+ /* XXX FIXME: */
+ break;
+
+ case DT_MIPS_IVERSION:
+ /* XXX FIXME: */
+ break;
+
+ case DT_MIPS_BASE_ADDRESS:
+ s = output_bfd->sections;
+ BFD_ASSERT (s != NULL);
+ dyn.d_un.d_ptr = s->vma & ~(0xffff);
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_LOCAL_GOTNO:
+ dyn.d_un.d_val = g->local_gotno;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_SYMTABNO:
+ name = ".dynsym";
+ elemsize = sizeof (Elf32_External_Sym);
+ s = bfd_get_section_by_name (output_bfd, name);
+ BFD_ASSERT (s != NULL);
+
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val = s->_cooked_size / elemsize;
+ else
+ dyn.d_un.d_val = s->_raw_size / elemsize;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_UNREFEXTNO:
+ /* XXX FIXME: */
+ dyn.d_un.d_val = SIZEOF_MIPS_DYNSYM_SECNAMES;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_GOTSYM:
+ dyn.d_un.d_val = g->global_gotsym;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ case DT_MIPS_HIPAGENO:
+ dyn.d_un.d_val = g->local_gotno - MIPS_RESERVED_GOTNO;
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ break;
+
+ }
+ }
+ }
+
+ /* The first entry of the global offset table will be filled at
+ runtime. The second entry will be used by some runtime loaders.
+ This isn't the case of Irix rld. */
+ if (sgot->_raw_size > 0)
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
+ bfd_put_32 (output_bfd, (bfd_vma) 0x80000000, sgot->contents + 4);
+ }
+
+ elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
+
+ {
+ asection *sdynsym;
+ asection *s;
+ unsigned int i;
+ bfd_vma last;
+ Elf_Internal_Sym sym;
+ long dindx;
+ const char *name;
+ const char * const * namep = mips_elf_dynsym_sec_names;
+ Elf32_compact_rel cpt;
+
+ /* Set up the section symbols for the output sections. SGI sets
+ the STT_NOTYPE attribute for these symbols. Should we do so? */
+
+ sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
+ if (sdynsym != NULL)
+ {
+ if (SGI_COMPAT (output_bfd))
+ {
+ sym.st_size = 0;
+ sym.st_name = 0;
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
+ sym.st_other = 0;
+
+ i = 0;
+ while ((name = *namep++) != NULL)
+ {
+ s = bfd_get_section_by_name (output_bfd, name);
+ if (s != NULL)
+ {
+ sym.st_value = s->vma;
+ dindx = elf_section_data (s)->dynindx;
+ last = s->vma + s->_raw_size;
+ }
+ else
+ {
+ sym.st_value = last;
+ dindx++;
+ }
+
+ sym.st_shndx = (i < MIPS_TEXT_DYNSYM_SECNO
+ ? SHN_MIPS_TEXT
+ : SHN_MIPS_DATA);
+ ++i;
+ sym.st_name =
+ mips_elf_hash_table (info)->dynsym_sec_strindex[dindx];
+
+ bfd_elf32_swap_symbol_out (output_bfd, &sym,
+ (((Elf32_External_Sym *)
+ sdynsym->contents)
+ + dindx));
+ }
+
+ /* Set the sh_info field of the output .dynsym section to
+ the index of the first global symbol. */
+ elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+ SIZEOF_MIPS_DYNSYM_SECNAMES;
+ }
+ else
+ {
+ sym.st_size = 0;
+ sym.st_name = 0;
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ sym.st_other = 0;
+
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ {
+ int indx;
+
+ sym.st_value = s->vma;
+
+ indx = elf_section_data (s)->this_idx;
+ BFD_ASSERT (indx > 0);
+ sym.st_shndx = indx;
+
+ bfd_elf32_swap_symbol_out (output_bfd, &sym,
+ (((Elf32_External_Sym *)
+ sdynsym->contents)
+ + elf_section_data (s)->dynindx));
+ }
+
+ /* Set the sh_info field of the output .dynsym section to
+ the index of the first global symbol. */
+ elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+ bfd_count_sections (output_bfd) + 1;
+ }
+ }
+
+ if (SGI_COMPAT (output_bfd))
+ {
+ /* Write .compact_rel section out. */
+ s = bfd_get_section_by_name (dynobj, ".compact_rel");
+ if (s != NULL)
+ {
+ cpt.id1 = 1;
+ cpt.num = s->reloc_count;
+ cpt.id2 = 2;
+ cpt.offset = (s->output_section->filepos
+ + sizeof (Elf32_External_compact_rel));
+ cpt.reserved0 = 0;
+ cpt.reserved1 = 0;
+ bfd_elf32_swap_compact_rel_out (output_bfd, &cpt,
+ ((Elf32_External_compact_rel *)
+ s->contents));
+
+ /* Clean up a dummy stub function entry in .text. */
+ s = bfd_get_section_by_name (dynobj, ".stub");
+ if (s != NULL)
+ {
+ file_ptr dummy_offset;
+
+ BFD_ASSERT (s->_raw_size >= MIPS_FUNCTION_STUB_SIZE);
+ dummy_offset = s->_raw_size - MIPS_FUNCTION_STUB_SIZE;
+ memset (s->contents + dummy_offset, 0,
+ MIPS_FUNCTION_STUB_SIZE);
+ }
+ }
+ }
+
+ /* Clean up a first relocation in .rel.dyn. */
+ s = bfd_get_section_by_name (dynobj, ".rel.dyn");
+ if (s != NULL)
+ memset (s->contents, 0, sizeof (Elf32_External_Rel));
+ }
+
+ return true;
+}
+
+/* This is almost identical to bfd_generic_get_... except that some
+ MIPS relocations need to be handled specially. Sigh. */
+
+static bfd_byte *
+elf32_mips_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;
+{
+ /* Get enough memory to hold the stuff */
+ 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 **) bfd_malloc (reloc_size);
+ if (reloc_vector == NULL && reloc_size != 0)
+ goto error_return;
+
+ /* read in the section */
+ 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;
+
+ 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 mips */
+ int gp_found;
+ bfd_vma gp = 0x12345678; /* initialize just to shut gcc up */
+
+ {
+ struct bfd_hash_entry *h;
+ struct bfd_link_hash_entry *lh;
+ /* Skip all this stuff if we aren't mixing formats. */
+ if (abfd && input_bfd
+ && abfd->xvec == input_bfd->xvec)
+ lh = 0;
+ else
+ {
+ h = bfd_hash_lookup (&link_info->hash->table, "_gp", false, false);
+ lh = (struct bfd_link_hash_entry *) h;
+ }
+ lookup:
+ if (lh)
+ {
+ switch (lh->type)
+ {
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ case bfd_link_hash_common:
+ gp_found = 0;
+ break;
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ gp_found = 1;
+ gp = lh->u.def.value;
+ break;
+ case bfd_link_hash_indirect:
+ case bfd_link_hash_warning:
+ lh = lh->u.i.link;
+ /* @@FIXME ignoring warning for now */
+ goto lookup;
+ case bfd_link_hash_new:
+ default:
+ abort ();
+ }
+ }
+ else
+ gp_found = 0;
+ }
+ /* end mips */
+ for (parent = reloc_vector; *parent != (arelent *) NULL;
+ parent++)
+ {
+ char *error_message = (char *) NULL;
+ bfd_reloc_status_type r;
+
+ /* Specific to MIPS: Deal with relocation types that require
+ knowing the gp of the output bfd. */
+ asymbol *sym = *(*parent)->sym_ptr_ptr;
+ if (bfd_is_abs_section (sym->section) && abfd)
+ {
+ /* The special_function wouldn't get called anyways. */
+ }
+ else if (!gp_found)
+ {
+ /* The gp isn't there; let the special function code
+ fall over on its own. */
+ }
+ else if ((*parent)->howto->special_function
+ == mips_elf_gprel16_reloc)
+ {
+ /* bypass special_function call */
+ r = gprel16_with_gp (input_bfd, sym, *parent, input_section,
+ relocateable, (PTR) data, gp);
+ goto skip_bfd_perform_relocation;
+ }
+ /* end mips specific stuff */
+
+ r = bfd_perform_relocation (input_bfd,
+ *parent,
+ (PTR) data,
+ input_section,
+ relocateable ? abfd : (bfd *) NULL,
+ &error_message);
+ skip_bfd_perform_relocation:
+
+ 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 (reloc_vector != NULL)
+ free (reloc_vector);
+ return data;
+
+error_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return NULL;
+}
+#define bfd_elf32_bfd_get_relocated_section_contents \
+ elf32_mips_get_relocated_section_contents
+
+/* ECOFF swapping routines. These are used when dealing with the
+ .mdebug section, which is in the ECOFF debugging format. */
+static const struct ecoff_debug_swap mips_elf_ecoff_debug_swap =
+{
+ /* Symbol table magic number. */
+ magicSym,
+ /* Alignment of debugging information. E.g., 4. */
+ 4,
+ /* Sizes of external symbolic information. */
+ sizeof (struct hdr_ext),
+ sizeof (struct dnr_ext),
+ sizeof (struct pdr_ext),
+ sizeof (struct sym_ext),
+ sizeof (struct opt_ext),
+ sizeof (struct fdr_ext),
+ sizeof (struct rfd_ext),
+ sizeof (struct ext_ext),
+ /* Functions to swap in external symbolic data. */
+ ecoff_swap_hdr_in,
+ ecoff_swap_dnr_in,
+ ecoff_swap_pdr_in,
+ ecoff_swap_sym_in,
+ ecoff_swap_opt_in,
+ ecoff_swap_fdr_in,
+ ecoff_swap_rfd_in,
+ ecoff_swap_ext_in,
+ _bfd_ecoff_swap_tir_in,
+ _bfd_ecoff_swap_rndx_in,
+ /* Functions to swap out external symbolic data. */
+ ecoff_swap_hdr_out,
+ ecoff_swap_dnr_out,
+ ecoff_swap_pdr_out,
+ ecoff_swap_sym_out,
+ ecoff_swap_opt_out,
+ ecoff_swap_fdr_out,
+ ecoff_swap_rfd_out,
+ ecoff_swap_ext_out,
+ _bfd_ecoff_swap_tir_out,
+ _bfd_ecoff_swap_rndx_out,
+ /* Function to read in symbolic data. */
+ mips_elf_read_ecoff_info
+};
+
+#define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec
+#define TARGET_LITTLE_NAME "elf32-littlemips"
+#define TARGET_BIG_SYM bfd_elf32_bigmips_vec
+#define TARGET_BIG_NAME "elf32-bigmips"
+#define ELF_ARCH bfd_arch_mips
+#define ELF_MACHINE_CODE EM_MIPS
+#define ELF_MAXPAGESIZE 0x10000
+#define elf_backend_collect true
+#define elf_backend_type_change_ok true
+#define elf_info_to_howto 0
+#define elf_info_to_howto_rel mips_info_to_howto_rel
+#define elf_backend_sym_is_global mips_elf_sym_is_global
+#define elf_backend_object_p mips_elf_object_p
+#define elf_backend_section_from_shdr mips_elf_section_from_shdr
+#define elf_backend_fake_sections mips_elf_fake_sections
+#define elf_backend_section_from_bfd_section \
+ mips_elf_section_from_bfd_section
+#define elf_backend_section_processing mips_elf_section_processing
+#define elf_backend_symbol_processing mips_elf_symbol_processing
+#define elf_backend_additional_program_headers \
+ mips_elf_additional_program_headers
+#define elf_backend_modify_segment_map mips_elf_modify_segment_map
+#define elf_backend_final_write_processing \
+ mips_elf_final_write_processing
+#define elf_backend_ecoff_debug_swap &mips_elf_ecoff_debug_swap
+
+#define bfd_elf32_bfd_is_local_label mips_elf_is_local_label
+#define bfd_elf32_find_nearest_line mips_elf_find_nearest_line
+
+#define bfd_elf32_bfd_link_hash_table_create \
+ mips_elf_link_hash_table_create
+#define bfd_elf32_bfd_final_link mips_elf_final_link
+#define bfd_elf32_bfd_copy_private_bfd_data \
+ mips_elf_copy_private_bfd_data
+#define bfd_elf32_bfd_merge_private_bfd_data \
+ mips_elf_merge_private_bfd_data
+#define bfd_elf32_bfd_set_private_flags mips_elf_set_private_flags
+#define elf_backend_add_symbol_hook mips_elf_add_symbol_hook
+#define elf_backend_create_dynamic_sections \
+ mips_elf_create_dynamic_sections
+#define elf_backend_check_relocs mips_elf_check_relocs
+#define elf_backend_adjust_dynamic_symbol \
+ mips_elf_adjust_dynamic_symbol
+#define elf_backend_size_dynamic_sections \
+ mips_elf_size_dynamic_sections
+#define elf_backend_relocate_section mips_elf_relocate_section
+#define elf_backend_finish_dynamic_symbol \
+ mips_elf_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections \
+ mips_elf_finish_dynamic_sections
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-ppc.c b/contrib/gdb/bfd/elf32-ppc.c
new file mode 100644
index 0000000..a8e5ad3
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-ppc.c
@@ -0,0 +1,2554 @@
+/* PowerPC-specific support for 32-bit ELF
+ Copyright 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file is based on a preliminary PowerPC ELF ABI. The
+ information may not match the final PowerPC ELF ABI. It includes
+ suggestions from the in-progress Embedded PowerPC ABI, and that
+ information may also not match. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/ppc.h"
+
+#define USE_RELA /* we want RELA relocations, not REL */
+
+/* PowerPC relocations defined by the ABIs */
+enum ppc_reloc_type
+{
+ R_PPC_NONE = 0,
+ R_PPC_ADDR32 = 1,
+ R_PPC_ADDR24 = 2,
+ R_PPC_ADDR16 = 3,
+ R_PPC_ADDR16_LO = 4,
+ R_PPC_ADDR16_HI = 5,
+ R_PPC_ADDR16_HA = 6,
+ R_PPC_ADDR14 = 7,
+ R_PPC_ADDR14_BRTAKEN = 8,
+ R_PPC_ADDR14_BRNTAKEN = 9,
+ R_PPC_REL24 = 10,
+ R_PPC_REL14 = 11,
+ R_PPC_REL14_BRTAKEN = 12,
+ R_PPC_REL14_BRNTAKEN = 13,
+ R_PPC_GOT16 = 14,
+ R_PPC_GOT16_LO = 15,
+ R_PPC_GOT16_HI = 16,
+ R_PPC_GOT16_HA = 17,
+ R_PPC_PLTREL24 = 18,
+ R_PPC_COPY = 19,
+ R_PPC_GLOB_DAT = 20,
+ R_PPC_JMP_SLOT = 21,
+ R_PPC_RELATIVE = 22,
+ R_PPC_LOCAL24PC = 23,
+ R_PPC_UADDR32 = 24,
+ R_PPC_UADDR16 = 25,
+ R_PPC_REL32 = 26,
+ R_PPC_PLT32 = 27,
+ R_PPC_PLTREL32 = 28,
+ R_PPC_PLT16_LO = 29,
+ R_PPC_PLT16_HI = 30,
+ R_PPC_PLT16_HA = 31,
+ R_PPC_SDAREL16 = 32,
+ R_PPC_SECTOFF = 33,
+ R_PPC_SECTOFF_LO = 34,
+ R_PPC_SECTOFF_HI = 35,
+ R_PPC_SECTOFF_HA = 36,
+
+ /* The remaining relocs are from the Embedded ELF ABI, and are not
+ in the SVR4 ELF ABI. */
+ R_PPC_EMB_NADDR32 = 101,
+ R_PPC_EMB_NADDR16 = 102,
+ R_PPC_EMB_NADDR16_LO = 103,
+ R_PPC_EMB_NADDR16_HI = 104,
+ R_PPC_EMB_NADDR16_HA = 105,
+ R_PPC_EMB_SDAI16 = 106,
+ R_PPC_EMB_SDA2I16 = 107,
+ R_PPC_EMB_SDA2REL = 108,
+ R_PPC_EMB_SDA21 = 109,
+ R_PPC_EMB_MRKREF = 110,
+ R_PPC_EMB_RELSEC16 = 111,
+ R_PPC_EMB_RELST_LO = 112,
+ R_PPC_EMB_RELST_HI = 113,
+ R_PPC_EMB_RELST_HA = 114,
+ R_PPC_EMB_BIT_FLD = 115,
+ R_PPC_EMB_RELSDA = 116,
+
+ /* This is a phony reloc to handle any old fashioned TOC16 references
+ that may still be in object files. */
+ R_PPC_TOC16 = 255,
+
+ R_PPC_max
+};
+
+static reloc_howto_type *ppc_elf_reloc_type_lookup
+ PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+static void ppc_elf_info_to_howto
+ PARAMS ((bfd *abfd, arelent *cache_ptr, Elf32_Internal_Rela *dst));
+static void ppc_elf_howto_init PARAMS ((void));
+static boolean ppc_elf_set_private_flags PARAMS ((bfd *, flagword));
+static boolean ppc_elf_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean ppc_elf_merge_private_bfd_data PARAMS ((bfd *, bfd *));
+
+static int ppc_elf_additional_program_headers PARAMS ((bfd *));
+static boolean ppc_elf_modify_segment_map PARAMS ((bfd *));
+
+static boolean ppc_elf_section_from_shdr PARAMS ((bfd *,
+ Elf32_Internal_Shdr *,
+ char *));
+
+static elf_linker_section_t *ppc_elf_create_linker_section
+ PARAMS ((bfd *abfd,
+ struct bfd_link_info *info,
+ enum elf_linker_section_enum));
+
+static boolean ppc_elf_check_relocs PARAMS ((bfd *,
+ struct bfd_link_info *,
+ asection *,
+ const Elf_Internal_Rela *));
+
+static boolean ppc_elf_adjust_dynamic_symbol PARAMS ((struct bfd_link_info *,
+ struct elf_link_hash_entry *));
+
+static boolean ppc_elf_adjust_dynindx PARAMS ((struct elf_link_hash_entry *, PTR));
+
+static boolean ppc_elf_size_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
+
+static boolean ppc_elf_relocate_section PARAMS ((bfd *,
+ struct bfd_link_info *info,
+ bfd *,
+ asection *,
+ bfd_byte *,
+ Elf_Internal_Rela *relocs,
+ Elf_Internal_Sym *local_syms,
+ asection **));
+
+static boolean ppc_elf_add_symbol_hook PARAMS ((bfd *,
+ struct bfd_link_info *,
+ const Elf_Internal_Sym *,
+ const char **,
+ flagword *,
+ asection **,
+ bfd_vma *));
+
+static boolean ppc_elf_finish_dynamic_symbol PARAMS ((bfd *,
+ struct bfd_link_info *,
+ struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
+
+static boolean ppc_elf_finish_dynamic_sections PARAMS ((bfd *, struct bfd_link_info *));
+
+#define BRANCH_PREDICT_BIT 0x200000 /* branch prediction bit for branch taken relocs */
+#define RA_REGISTER_MASK 0x001f0000 /* mask to set RA in memory instructions */
+#define RA_REGISTER_SHIFT 16 /* value to shift register by to insert RA */
+
+/* The name of the dynamic interpreter. This is put in the .interp
+ section. */
+
+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
+
+
+static reloc_howto_type *ppc_elf_howto_table[ (int)R_PPC_max ];
+
+static reloc_howto_type ppc_elf_howto_raw[] =
+{
+ /* This reloc does nothing. */
+ HOWTO (R_PPC_NONE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_NONE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A standard 32 bit relocation. */
+ HOWTO (R_PPC_ADDR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* An absolute 26 bit branch; the lower two bits must be zero.
+ FIXME: we don't check that, we just clear them. */
+ HOWTO (R_PPC_ADDR24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR24", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A standard 16 bit relocation. */
+ HOWTO (R_PPC_ADDR16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 16 bit relocation without overflow. */
+ HOWTO (R_PPC_ADDR16_LO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR16_LO", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The high order 16 bits of an address. */
+ HOWTO (R_PPC_ADDR16_HI, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR16_HI", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The high order 16 bits of an address, plus 1 if the contents of
+ the low 16 bits, treated as a signed number, is negative. */
+ HOWTO (R_PPC_ADDR16_HA, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR16_HA", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* An absolute 16 bit branch; the lower two bits must be zero.
+ FIXME: we don't check that, we just clear them. */
+ HOWTO (R_PPC_ADDR14, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR14", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* An absolute 16 bit branch, for which bit 10 should be set to
+ indicate that the branch is expected to be taken. The lower two
+ bits must be zero. */
+ HOWTO (R_PPC_ADDR14_BRTAKEN, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR14_BRTAKEN",/* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* An absolute 16 bit branch, for which bit 10 should be set to
+ indicate that the branch is not expected to be taken. The lower
+ two bits must be zero. */
+ HOWTO (R_PPC_ADDR14_BRNTAKEN, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_ADDR14_BRNTAKEN",/* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A relative 26 bit branch; the lower two bits must be zero. */
+ HOWTO (R_PPC_REL24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_REL24", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A relative 16 bit branch; the lower two bits must be zero. */
+ HOWTO (R_PPC_REL14, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_REL14", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A relative 16 bit branch. Bit 10 should be set to indicate that
+ the branch is expected to be taken. The lower two bits must be
+ zero. */
+ HOWTO (R_PPC_REL14_BRTAKEN, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_REL14_BRTAKEN", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A relative 16 bit branch. Bit 10 should be set to indicate that
+ the branch is not expected to be taken. The lower two bits must
+ be zero. */
+ HOWTO (R_PPC_REL14_BRNTAKEN, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_REL14_BRNTAKEN",/* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xfffc, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16, but referring to the GOT table entry for the
+ symbol. */
+ HOWTO (R_PPC_GOT16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_GOT16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16_LO, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_PPC_GOT16_LO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_GOT16_LO", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16_HI, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_PPC_GOT16_HI, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_GOT16_HI", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16_HA, but referring to the GOT table entry for
+ the symbol. */
+ HOWTO (R_PPC_GOT16_HA, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_GOT16_HA", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_REL24, but referring to the procedure linkage table
+ entry for the symbol. FIXME: Not supported. */
+ HOWTO (R_PPC_PLTREL24, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLTREL24", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* This is used only by the dynamic linker. The symbol should exist
+ both in the object being run and in some shared library. The
+ dynamic linker copies the data addressed by the symbol from the
+ shared library into the object. I have no idea what the purpose
+ of this is. */
+ HOWTO (R_PPC_COPY, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_COPY", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR32, but used when setting global offset table
+ entries. */
+ HOWTO (R_PPC_GLOB_DAT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_GLOB_DAT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Marks a procedure linkage table entry for a symbol. */
+ HOWTO (R_PPC_JMP_SLOT, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_JMP_SLOT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Used only by the dynamic linker. When the object is run, this
+ longword is set to the load address of the object, plus the
+ addend. */
+ HOWTO (R_PPC_RELATIVE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_RELATIVE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_REL24, but uses the value of the symbol within the
+ object rather than the final value. Normally used for
+ _GLOBAL_OFFSET_TABLE_. FIXME: Not supported. */
+ HOWTO (R_PPC_LOCAL24PC, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_LOCAL24PC", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR32, but may be unaligned. */
+ HOWTO (R_PPC_UADDR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_UADDR32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16, but may be unaligned. */
+ HOWTO (R_PPC_UADDR16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_UADDR16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32-bit PC relative */
+ HOWTO (R_PPC_REL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_REL32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* 32-bit relocation to the symbol's procedure linkage table.
+ FIXEME: not supported. */
+ HOWTO (R_PPC_PLT32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLT32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32-bit PC relative relocation to the symbol's procedure linkage table.
+ FIXEME: not supported. */
+ HOWTO (R_PPC_PLTREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLTREL32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16_LO, but referring to the PLT table entry for
+ the symbol. */
+ HOWTO (R_PPC_PLT16_LO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLT16_LO", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16_HI, but referring to the PLT table entry for
+ the symbol. */
+ HOWTO (R_PPC_PLT16_HI, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLT16_HI", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Like R_PPC_ADDR16_HA, but referring to the PLT table entry for
+ the symbol. FIXME: Not supported. */
+ HOWTO (R_PPC_PLT16_HA, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_PLT16_HA", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A sign-extended 16 bit value relative to _SDA_BASE_, for use with
+ small data items. */
+ HOWTO (R_PPC_SDAREL16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_SDAREL16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32-bit section relative relocation. */
+ HOWTO (R_PPC_SECTOFF, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_SECTOFF", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* 16-bit lower half section relative relocation. */
+ HOWTO (R_PPC_SECTOFF_LO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_SECTOFF_LO", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16-bit upper half section relative relocation. */
+ HOWTO (R_PPC_SECTOFF_HI, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_SECTOFF_HI", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16-bit upper half adjusted section relative relocation. */
+ HOWTO (R_PPC_SECTOFF_HA, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_SECTOFF_HA", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The remaining relocs are from the Embedded ELF ABI, and are not
+ in the SVR4 ELF ABI. */
+
+ /* 32 bit value resulting from the addend minus the symbol */
+ HOWTO (R_PPC_EMB_NADDR32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_NADDR32", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit value resulting from the addend minus the symbol */
+ HOWTO (R_PPC_EMB_NADDR16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_NADDR16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit value resulting from the addend minus the symbol */
+ HOWTO (R_PPC_EMB_NADDR16_LO, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont,/* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_ADDR16_LO", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The high order 16 bits of the addend minus the symbol */
+ HOWTO (R_PPC_EMB_NADDR16_HI, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_NADDR16_HI", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* The high order 16 bits of the result of the addend minus the address,
+ plus 1 if the contents of the low 16 bits, treated as a signed number,
+ is negative. */
+ HOWTO (R_PPC_EMB_NADDR16_HA, /* type */
+ 16, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_NADDR16_HA", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit value resulting from allocating a 4 byte word to hold an
+ address in the .sdata section, and returning the offset from
+ _SDA_BASE_ for that relocation */
+ HOWTO (R_PPC_EMB_SDAI16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_SDAI16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit value resulting from allocating a 4 byte word to hold an
+ address in the .sdata2 section, and returning the offset from
+ _SDA2_BASE_ for that relocation */
+ HOWTO (R_PPC_EMB_SDA2I16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_SDA2I16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A sign-extended 16 bit value relative to _SDA2_BASE_, for use with
+ small data items. */
+ HOWTO (R_PPC_EMB_SDA2REL, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_SDA2REL", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Relocate against either _SDA_BASE_ or _SDA2_BASE_, filling in the 16 bit
+ signed offset from the appropriate base, and filling in the register
+ field with the appropriate register (0, 2, or 13). */
+ HOWTO (R_PPC_EMB_SDA21, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_SDA21", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Relocation not handled: R_PPC_EMB_MRKREF */
+ /* Relocation not handled: R_PPC_EMB_RELSEC16 */
+ /* Relocation not handled: R_PPC_EMB_RELST_LO */
+ /* Relocation not handled: R_PPC_EMB_RELST_HI */
+ /* Relocation not handled: R_PPC_EMB_RELST_HA */
+ /* Relocation not handled: R_PPC_EMB_BIT_FLD */
+
+ /* PC relative relocation against either _SDA_BASE_ or _SDA2_BASE_, filling
+ in the 16 bit signed offset from the appropriate base, and filling in the
+ register field with the appropriate register (0, 2, or 13). */
+ HOWTO (R_PPC_EMB_RELSDA, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_EMB_RELSDA", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Phony reloc to handle AIX style TOC entries */
+ HOWTO (R_PPC_TOC16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_PPC_TOC16", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+};
+
+
+/* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */
+
+static void
+ppc_elf_howto_init ()
+{
+ unsigned int i, type;
+
+ for (i = 0; i < sizeof (ppc_elf_howto_raw) / sizeof (ppc_elf_howto_raw[0]); i++)
+ {
+ type = ppc_elf_howto_raw[i].type;
+ BFD_ASSERT (type < sizeof(ppc_elf_howto_table) / sizeof(ppc_elf_howto_table[0]));
+ ppc_elf_howto_table[type] = &ppc_elf_howto_raw[i];
+ }
+}
+
+
+static reloc_howto_type *
+ppc_elf_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ enum ppc_reloc_type ppc_reloc = R_PPC_NONE;
+
+ if (!ppc_elf_howto_table[ R_PPC_ADDR32 ]) /* Initialize howto table if needed */
+ ppc_elf_howto_init ();
+
+ switch ((int)code)
+ {
+ default:
+ return (reloc_howto_type *)NULL;
+
+ case BFD_RELOC_NONE: ppc_reloc = R_PPC_NONE; break;
+ case BFD_RELOC_32: ppc_reloc = R_PPC_ADDR32; break;
+ case BFD_RELOC_PPC_BA26: ppc_reloc = R_PPC_ADDR24; break;
+ case BFD_RELOC_16: ppc_reloc = R_PPC_ADDR16; break;
+ case BFD_RELOC_LO16: ppc_reloc = R_PPC_ADDR16_LO; break;
+ case BFD_RELOC_HI16: ppc_reloc = R_PPC_ADDR16_HI; break;
+ case BFD_RELOC_HI16_S: ppc_reloc = R_PPC_ADDR16_HA; break;
+ case BFD_RELOC_PPC_BA16: ppc_reloc = R_PPC_ADDR14; break;
+ case BFD_RELOC_PPC_BA16_BRTAKEN: ppc_reloc = R_PPC_ADDR14_BRTAKEN; break;
+ case BFD_RELOC_PPC_BA16_BRNTAKEN: ppc_reloc = R_PPC_ADDR14_BRNTAKEN; break;
+ case BFD_RELOC_PPC_B26: ppc_reloc = R_PPC_REL24; break;
+ case BFD_RELOC_PPC_B16: ppc_reloc = R_PPC_REL14; break;
+ case BFD_RELOC_PPC_B16_BRTAKEN: ppc_reloc = R_PPC_REL14_BRTAKEN; break;
+ case BFD_RELOC_PPC_B16_BRNTAKEN: ppc_reloc = R_PPC_REL14_BRNTAKEN; break;
+ case BFD_RELOC_16_GOTOFF: ppc_reloc = R_PPC_GOT16; break;
+ case BFD_RELOC_LO16_GOTOFF: ppc_reloc = R_PPC_GOT16_LO; break;
+ case BFD_RELOC_HI16_GOTOFF: ppc_reloc = R_PPC_GOT16_HI; break;
+ case BFD_RELOC_HI16_S_GOTOFF: ppc_reloc = R_PPC_GOT16_HA; break;
+ case BFD_RELOC_24_PLT_PCREL: ppc_reloc = R_PPC_PLTREL24; break;
+ case BFD_RELOC_PPC_COPY: ppc_reloc = R_PPC_COPY; break;
+ case BFD_RELOC_PPC_GLOB_DAT: ppc_reloc = R_PPC_GLOB_DAT; break;
+ case BFD_RELOC_PPC_LOCAL24PC: ppc_reloc = R_PPC_LOCAL24PC; break;
+ case BFD_RELOC_32_PCREL: ppc_reloc = R_PPC_REL32; break;
+ case BFD_RELOC_32_PLTOFF: ppc_reloc = R_PPC_PLT32; break;
+ case BFD_RELOC_32_PLT_PCREL: ppc_reloc = R_PPC_PLTREL32; break;
+ case BFD_RELOC_LO16_PLTOFF: ppc_reloc = R_PPC_PLT16_LO; break;
+ case BFD_RELOC_HI16_PLTOFF: ppc_reloc = R_PPC_PLT16_HI; break;
+ case BFD_RELOC_HI16_S_PLTOFF: ppc_reloc = R_PPC_PLT16_HA; break;
+ case BFD_RELOC_GPREL16: ppc_reloc = R_PPC_SDAREL16; break;
+ case BFD_RELOC_32_BASEREL: ppc_reloc = R_PPC_SECTOFF; break;
+ case BFD_RELOC_LO16_BASEREL: ppc_reloc = R_PPC_SECTOFF_LO; break;
+ case BFD_RELOC_HI16_BASEREL: ppc_reloc = R_PPC_SECTOFF_HI; break;
+ case BFD_RELOC_HI16_S_BASEREL: ppc_reloc = R_PPC_SECTOFF_HA; break;
+ case BFD_RELOC_CTOR: ppc_reloc = R_PPC_ADDR32; break;
+ case BFD_RELOC_PPC_TOC16: ppc_reloc = R_PPC_TOC16; break;
+ case BFD_RELOC_PPC_EMB_NADDR32: ppc_reloc = R_PPC_EMB_NADDR32; break;
+ case BFD_RELOC_PPC_EMB_NADDR16: ppc_reloc = R_PPC_EMB_NADDR16; break;
+ case BFD_RELOC_PPC_EMB_NADDR16_LO: ppc_reloc = R_PPC_EMB_NADDR16_LO; break;
+ case BFD_RELOC_PPC_EMB_NADDR16_HI: ppc_reloc = R_PPC_EMB_NADDR16_HI; break;
+ case BFD_RELOC_PPC_EMB_NADDR16_HA: ppc_reloc = R_PPC_EMB_NADDR16_HA; break;
+ case BFD_RELOC_PPC_EMB_SDAI16: ppc_reloc = R_PPC_EMB_SDAI16; break;
+ case BFD_RELOC_PPC_EMB_SDA2I16: ppc_reloc = R_PPC_EMB_SDA2I16; break;
+ case BFD_RELOC_PPC_EMB_SDA2REL: ppc_reloc = R_PPC_EMB_SDA2REL; break;
+ case BFD_RELOC_PPC_EMB_SDA21: ppc_reloc = R_PPC_EMB_SDA21; break;
+ case BFD_RELOC_PPC_EMB_MRKREF: ppc_reloc = R_PPC_EMB_MRKREF; break;
+ case BFD_RELOC_PPC_EMB_RELSEC16: ppc_reloc = R_PPC_EMB_RELSEC16; break;
+ case BFD_RELOC_PPC_EMB_RELST_LO: ppc_reloc = R_PPC_EMB_RELST_LO; break;
+ case BFD_RELOC_PPC_EMB_RELST_HI: ppc_reloc = R_PPC_EMB_RELST_HI; break;
+ case BFD_RELOC_PPC_EMB_RELST_HA: ppc_reloc = R_PPC_EMB_RELST_HA; break;
+ case BFD_RELOC_PPC_EMB_BIT_FLD: ppc_reloc = R_PPC_EMB_BIT_FLD; break;
+ case BFD_RELOC_PPC_EMB_RELSDA: ppc_reloc = R_PPC_EMB_RELSDA; break;
+ }
+
+ return ppc_elf_howto_table[ (int)ppc_reloc ];
+};
+
+/* Set the howto pointer for a PowerPC ELF reloc. */
+
+static void
+ppc_elf_info_to_howto (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf32_Internal_Rela *dst;
+{
+ if (!ppc_elf_howto_table[ R_PPC_ADDR32 ]) /* Initialize howto table if needed */
+ ppc_elf_howto_init ();
+
+ BFD_ASSERT (ELF32_R_TYPE (dst->r_info) < (unsigned int) R_PPC_max);
+ cache_ptr->howto = ppc_elf_howto_table[ELF32_R_TYPE (dst->r_info)];
+}
+
+/* Function to set whether a module needs the -mrelocatable bit set. */
+
+static boolean
+ppc_elf_set_private_flags (abfd, flags)
+ bfd *abfd;
+ flagword flags;
+{
+ BFD_ASSERT (!elf_flags_init (abfd)
+ || elf_elfheader (abfd)->e_flags == flags);
+
+ elf_elfheader (abfd)->e_flags = flags;
+ elf_flags_init (abfd) = true;
+ return true;
+}
+
+/* Copy backend specific data from one object module to another */
+static boolean
+ppc_elf_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ /* This function is selected based on the input vector. We only
+ want to copy information over if the output BFD also uses Elf
+ format. */
+ if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ BFD_ASSERT (!elf_flags_init (obfd)
+ || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags);
+
+ elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
+ elf_flags_init (obfd) = true;
+ return true;
+}
+
+/* Merge backend specific data from an object file to the output
+ object file when linking */
+static boolean
+ppc_elf_merge_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ flagword old_flags;
+ flagword new_flags;
+ boolean error;
+
+ /* Check if we have the same endianess */
+ if (ibfd->xvec->byteorder != obfd->xvec->byteorder
+ && obfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
+ {
+ (*_bfd_error_handler)
+ ("%s: compiled for a %s endian system and target is %s endian",
+ bfd_get_filename (ibfd),
+ bfd_big_endian (ibfd) ? "big" : "little",
+ bfd_big_endian (obfd) ? "big" : "little");
+
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
+ /* This function is selected based on the input vector. We only
+ want to copy information over if the output BFD also uses Elf
+ format. */
+ if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ new_flags = elf_elfheader (ibfd)->e_flags;
+ old_flags = elf_elfheader (obfd)->e_flags;
+ if (!elf_flags_init (obfd)) /* First call, no flags set */
+ {
+ elf_flags_init (obfd) = true;
+ elf_elfheader (obfd)->e_flags = new_flags;
+ }
+
+ else if (new_flags == old_flags) /* Compatible flags are ok */
+ ;
+
+ else /* Incompatible flags */
+ {
+ /* Warn about -mrelocatable mismatch. Allow -mrelocatable-lib to be linked
+ with either. */
+ error = false;
+ if ((new_flags & EF_PPC_RELOCATABLE) != 0
+ && (old_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0)
+ {
+ error = true;
+ (*_bfd_error_handler)
+ ("%s: compiled with -mrelocatable and linked with modules compiled normally",
+ bfd_get_filename (ibfd));
+ }
+ else if ((new_flags & (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB)) == 0
+ && (old_flags & EF_PPC_RELOCATABLE) != 0)
+ {
+ error = true;
+ (*_bfd_error_handler)
+ ("%s: compiled normally and linked with modules compiled with -mrelocatable",
+ bfd_get_filename (ibfd));
+ }
+ else if ((new_flags & EF_PPC_RELOCATABLE_LIB) != 0)
+ elf_elfheader (obfd)->e_flags |= EF_PPC_RELOCATABLE_LIB;
+
+
+ /* Do not warn about eabi vs. V.4 mismatch, just or in the bit if any module uses it */
+ elf_elfheader (obfd)->e_flags |= (new_flags & EF_PPC_EMB);
+
+ new_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
+ old_flags &= ~ (EF_PPC_RELOCATABLE | EF_PPC_RELOCATABLE_LIB | EF_PPC_EMB);
+
+ /* Warn about any other mismatches */
+ if (new_flags != old_flags)
+ {
+ error = true;
+ (*_bfd_error_handler)
+ ("%s: uses different e_flags (0x%lx) fields than previous modules (0x%lx)",
+ bfd_get_filename (ibfd), (long)new_flags, (long)old_flags);
+ }
+
+ if (error)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/* Handle a PowerPC specific section when reading an object file. This
+ is called when elfcode.h finds a section with an unknown type. */
+
+static boolean
+ppc_elf_section_from_shdr (abfd, hdr, name)
+ bfd *abfd;
+ Elf32_Internal_Shdr *hdr;
+ char *name;
+{
+ asection *newsect;
+ flagword flags;
+
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ return false;
+
+ newsect = hdr->bfd_section;
+ flags = bfd_get_section_flags (abfd, newsect);
+ if (hdr->sh_flags & SHF_EXCLUDE)
+ flags |= SEC_EXCLUDE;
+
+ if (hdr->sh_type == SHT_ORDERED)
+ flags |= SEC_SORT_ENTRIES;
+
+ bfd_set_section_flags (abfd, newsect, flags);
+ return true;
+}
+
+
+/* Set up any other section flags and such that may be necessary. */
+
+boolean
+ppc_elf_fake_sections (abfd, shdr, asect)
+ bfd *abfd;
+ Elf32_Internal_Shdr *shdr;
+ asection *asect;
+{
+ if ((asect->flags & SEC_EXCLUDE) != 0)
+ shdr->sh_flags |= SHF_EXCLUDE;
+
+ if ((asect->flags & SEC_SORT_ENTRIES) != 0)
+ shdr->sh_type = SHT_ORDERED;
+}
+
+
+/* Create a special linker section */
+static elf_linker_section_t *
+ppc_elf_create_linker_section (abfd, info, which)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ enum elf_linker_section_enum which;
+{
+ bfd *dynobj = elf_hash_table (info)->dynobj;
+ elf_linker_section_t *lsect;
+
+ /* Record the first bfd section that needs the special section */
+ if (!dynobj)
+ dynobj = elf_hash_table (info)->dynobj = abfd;
+
+ /* If this is the first time, create the section */
+ lsect = elf_linker_section (dynobj, which);
+ if (!lsect)
+ {
+ elf_linker_section_t defaults;
+ static elf_linker_section_t zero_section;
+
+ defaults = zero_section;
+ defaults.which = which;
+ defaults.hole_written_p = false;
+ defaults.alignment = 2;
+ defaults.flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ switch (which)
+ {
+ default:
+ (*_bfd_error_handler) ("%s: Unknown special linker type %d",
+ bfd_get_filename (abfd),
+ (int)which);
+
+ bfd_set_error (bfd_error_bad_value);
+ return (elf_linker_section_t *)0;
+
+ case LINKER_SECTION_GOT: /* .got section */
+ defaults.name = ".got";
+ defaults.rel_name = ".rela.got";
+ defaults.sym_name = "_GLOBAL_OFFSET_TABLE_";
+ defaults.max_hole_offset = 32764;
+ defaults.hole_size = 16;
+ defaults.sym_offset = 4;
+ break;
+
+ case LINKER_SECTION_SDATA: /* .sdata/.sbss section */
+ defaults.name = ".sdata";
+ defaults.rel_name = ".rela.sdata";
+ defaults.bss_name = ".sbss";
+ defaults.sym_name = "_SDA_BASE_";
+ defaults.sym_offset = 32768;
+ break;
+
+ case LINKER_SECTION_SDATA2: /* .sdata2/.sbss2 section */
+ defaults.name = ".sdata2";
+ defaults.rel_name = ".rela.sdata2";
+ defaults.bss_name = ".sbss2";
+ defaults.sym_name = "_SDA2_BASE_";
+ defaults.sym_offset = 32768;
+ defaults.flags |= SEC_READONLY;
+ break;
+ }
+
+ lsect = _bfd_elf_create_linker_section (abfd, info, which, &defaults);
+ }
+
+ return lsect;
+}
+
+
+/* If we have a non-zero sized .sbss2 or .PPC.EMB.sbss0 sections, we need to bump up
+ the number of section headers. */
+
+static int
+ppc_elf_additional_program_headers (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ int ret;
+
+ ret = 0;
+
+ s = bfd_get_section_by_name (abfd, ".sbss2");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
+ ++ret;
+
+ s = bfd_get_section_by_name (abfd, ".PPC.EMB.sbss0");
+ if (s != NULL && (s->flags & SEC_LOAD) != 0 && s->_raw_size > 0)
+ ++ret;
+
+ return ret;
+}
+
+/* Modify the segment map if needed */
+
+static boolean
+ppc_elf_modify_segment_map (abfd)
+ bfd *abfd;
+{
+ return true;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. The current definition is in some section of the
+ dynamic object, but we're not including those sections. We have to
+ change the definition to something the rest of the link can
+ understand. */
+
+static boolean
+ppc_elf_adjust_dynamic_symbol (info, h)
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+{
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_adjust_dynamic_symbol called\n");
+#endif
+ return true;
+}
+
+
+/* Increment the index of a dynamic symbol by a given amount. Called
+ via elf_link_hash_traverse. */
+
+static boolean
+ppc_elf_adjust_dynindx (h, cparg)
+ struct elf_link_hash_entry *h;
+ PTR cparg;
+{
+ int *cp = (int *) cparg;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_adjust_dynindx called, h->dynindx = %d, *cp = %d\n", h->dynindx, *cp);
+#endif
+
+ if (h->dynindx != -1)
+ h->dynindx += *cp;
+
+ return true;
+}
+
+
+/* Set the sizes of the dynamic sections. */
+
+static boolean
+ppc_elf_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *s;
+ boolean reltext;
+ boolean relplt;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
+#endif
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (! info->shared)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }
+
+ /* Make space for the trailing nop in .plt. */
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+ if (s->_raw_size > 0)
+ s->_raw_size += 4;
+ }
+ else
+ {
+ /* We may have created entries in the .rela.got, .rela.sdata, and
+ .rela.sdata2 section2. However, if we are not creating the
+ dynamic sections, we will not actually use these entries. Reset
+ the size of .rela.got, et al, which will cause it to get
+ stripped from the output file below. */
+ static char *rela_sections[] = { ".rela.got", ".rela.sdata", ".rela.sdata", (char *)0 };
+ char **p;
+
+ for (p = rela_sections; *p != (char *)0; p++)
+ {
+ s = bfd_get_section_by_name (dynobj, *p);
+ if (s != NULL)
+ s->_raw_size = 0;
+ }
+ }
+
+ /* The check_relocs and adjust_dynamic_symbol entry points have
+ determined the sizes of the various dynamic sections. Allocate
+ memory for them. */
+ reltext = false;
+ relplt = false;
+ for (s = dynobj->sections; s != NULL; s = s->next)
+ {
+ const char *name;
+ boolean strip;
+
+ if ((s->flags & SEC_IN_MEMORY) == 0)
+ continue;
+
+ /* It's OK to base decisions on the section name, because none
+ of the dynobj section names depend upon the input files. */
+ name = bfd_get_section_name (dynobj, s);
+
+ strip = false;
+
+#if 0
+ if (strncmp (name, ".rela", 5) == 0)
+ {
+ if (s->_raw_size == 0)
+ {
+ /* If we don't need this section, strip it from the
+ output file. This is to handle .rela.bss and
+ .rel.plt. We must create it in
+ create_dynamic_sections, because it must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ strip = true;
+ }
+ else
+ {
+ asection *target;
+
+ /* If this relocation section applies to a read only
+ section, then we probably need a DT_TEXTREL entry. */
+ target = bfd_get_section_by_name (output_bfd, name + 5);
+ if (target != NULL
+ && (target->flags & SEC_READONLY) != 0)
+ reltext = true;
+
+ if (strcmp (name, ".rela.plt") == 0)
+ relplt = true;
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ s->reloc_count = 0;
+ }
+ }
+ else
+#endif
+ if (strcmp (name, ".plt") != 0
+ && strcmp (name, ".got") != 0
+ && strcmp (name, ".sdata") != 0
+ && strcmp (name, ".sdata2") != 0
+ && strcmp (name, ".rela.sdata") != 0
+ && strcmp (name, ".rela.sdata2") != 0)
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
+
+ if (strip)
+ {
+ asection **spp;
+
+ for (spp = &s->output_section->owner->sections;
+ *spp != s->output_section;
+ spp = &(*spp)->next)
+ ;
+ *spp = s->output_section->next;
+ --s->output_section->owner->section_count;
+
+ continue;
+ }
+
+ /* Allocate memory for the section contents. */
+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ return false;
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Add some entries to the .dynamic section. We fill in the
+ values later, in ppc_elf_finish_dynamic_sections, but we
+ must add the entries now so that we get the correct size for
+ the .dynamic section. The DT_DEBUG entry is filled in by the
+ dynamic linker and used by the debugger. */
+ if (! info->shared)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ return false;
+ }
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0))
+ return false;
+
+ if (relplt)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+ return false;
+ }
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
+ sizeof (Elf32_External_Rela)))
+ return false;
+
+ if (reltext)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+ return false;
+ }
+ }
+
+ /* If we are generating a shared library, we generate a section
+ symbol for each output section. These are local symbols, which
+ means that they must come first in the dynamic symbol table.
+ That means we must increment the dynamic symbol index of every
+ other dynamic symbol. */
+ if (info->shared)
+ {
+ int c, i;
+
+ c = bfd_count_sections (output_bfd);
+ elf_link_hash_traverse (elf_hash_table (info),
+ ppc_elf_adjust_dynindx,
+ (PTR) &c);
+ elf_hash_table (info)->dynsymcount += c;
+
+ for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
+ {
+ elf_section_data (s)->dynindx = i;
+ /* These symbols will have no names, so we don't need to
+ fiddle with dynstr_index. */
+ }
+ }
+
+ return true;
+}
+
+
+/* Look through the relocs for a section during the first phase, and
+ allocate space in the global offset table or procedure linkage
+ table. */
+
+static boolean
+ppc_elf_check_relocs (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+ elf_linker_section_t *got;
+ elf_linker_section_t *sdata;
+ elf_linker_section_t *sdata2;
+ asection *sreloc;
+
+ if (info->relocateable)
+ return true;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_check_relocs called for section %s\n",
+ bfd_get_section_name (abfd, sec));
+#endif
+
+ /* Create the linker generated sections all the time so that the special
+ symbols are created. */
+ if ((got = elf_linker_section (abfd, LINKER_SECTION_GOT)) == NULL)
+ {
+ got = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_GOT);
+ if (!got)
+ return false;
+ }
+
+ if ((sdata = elf_linker_section (abfd, LINKER_SECTION_SDATA)) == NULL)
+ {
+ sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
+ if (!sdata)
+ return false;
+ }
+
+
+ if ((sdata2 = elf_linker_section (abfd, LINKER_SECTION_SDATA2)) == NULL)
+ {
+ sdata2 = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA2);
+ if (!sdata2)
+ return false;
+ }
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+
+ sreloc = NULL;
+
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ default:
+ break;
+
+ /* GOT16 relocations */
+ case R_PPC_GOT16:
+ case R_PPC_GOT16_LO:
+ case R_PPC_GOT16_HI:
+ case R_PPC_GOT16_HA:
+ if (got->rel_section == NULL
+ && (h != NULL || info->shared)
+ && !_bfd_elf_make_linker_section_rela (dynobj, got, 2))
+ return false;
+
+ if (!bfd_elf32_create_pointer_linker_section (abfd, info, got, h, rel))
+ return false;
+
+ break;
+
+ /* Indirect .sdata relocation */
+ case R_PPC_EMB_SDAI16:
+ if (got->rel_section == NULL
+ && (h != NULL || info->shared)
+ && !_bfd_elf_make_linker_section_rela (dynobj, got, 2))
+ return false;
+
+ if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata, h, rel))
+ return false;
+
+ break;
+
+ /* Indirect .sdata2 relocation */
+ case R_PPC_EMB_SDA2I16:
+ if (got->rel_section == NULL
+ && (h != NULL || info->shared)
+ && !_bfd_elf_make_linker_section_rela (dynobj, got, 2))
+ return false;
+
+ if (!bfd_elf32_create_pointer_linker_section (abfd, info, sdata2, h, rel))
+ return false;
+
+ break;
+
+#if 0
+ case R_PPC_PLT32:
+ case R_PPC_PLTREL24:
+ case R_PPC_PLT16_LO:
+ case R_PPC_PLT16_HI:
+ case R_PPC_PLT16_HA:
+#ifdef DEBUG
+ fprintf (stderr, "Reloc requires a PLT entry\n");
+#endif
+ /* This symbol requires a procedure linkage table entry. We
+ actually build the entry in adjust_dynamic_symbol,
+ because this might be a case of linking PIC code without
+ linking in any dynamic objects, in which case we don't
+ need to generate a procedure linkage table after all. */
+
+ if (h == NULL)
+ {
+ /* It does not make sense to have a procedure linkage
+ table entry for a local symbol. */
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ break;
+
+ case R_SPARC_PC10:
+ case R_SPARC_PC22:
+ if (h != NULL
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ break;
+ /* Fall through. */
+ case R_SPARC_DISP8:
+ case R_SPARC_DISP16:
+ case R_SPARC_DISP32:
+ case R_SPARC_WDISP30:
+ case R_SPARC_WDISP22:
+ if (h == NULL)
+ break;
+ /* Fall through. */
+ case R_SPARC_8:
+ case R_SPARC_16:
+ case R_SPARC_32:
+ case R_SPARC_HI22:
+ case R_SPARC_22:
+ case R_SPARC_13:
+ case R_SPARC_LO10:
+ case R_SPARC_UA32:
+ if (info->shared
+ && (sec->flags & SEC_ALLOC) != 0)
+ {
+ /* When creating a shared object, we must copy these
+ relocs into the output file. We create a reloc
+ section in dynobj and make room for the reloc. */
+ if (sreloc == NULL)
+ {
+ const char *name;
+
+ name = (bfd_elf_string_from_elf_section
+ (abfd,
+ elf_elfheader (abfd)->e_shstrndx,
+ elf_section_data (sec)->rel_hdr.sh_name));
+ if (name == NULL)
+ return false;
+
+ BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+ && strcmp (bfd_get_section_name (abfd, sec),
+ name + 5) == 0);
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ if (sreloc == NULL)
+ {
+ sreloc = bfd_make_section (dynobj, name);
+ if (sreloc == NULL
+ || ! bfd_set_section_flags (dynobj, sreloc,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+ return false;
+ }
+ }
+
+ sreloc->_raw_size += sizeof (Elf32_External_Rela);
+ }
+
+ break;
+#endif
+ }
+ }
+
+ return true;
+}
+
+
+/* Hook called by the linker routine which adds symbols from an object
+ file. We use it to put .comm items in .sbss, and not .bss. */
+
+/*ARGSUSED*/
+static boolean
+ppc_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ const Elf_Internal_Sym *sym;
+ const char **namep;
+ flagword *flagsp;
+ asection **secp;
+ bfd_vma *valp;
+{
+ if (sym->st_shndx == SHN_COMMON && sym->st_size <= bfd_get_gp_size (abfd))
+ {
+ /* Common symbols less than or equal to -G nn bytes are automatically
+ put into .sdata. */
+ elf_linker_section_t *sdata = ppc_elf_create_linker_section (abfd, info, LINKER_SECTION_SDATA);
+ if (!sdata->bss_section)
+ {
+ sdata->bss_section = bfd_make_section (elf_hash_table (info)->dynobj, sdata->bss_name);
+ sdata->bss_section->flags = (sdata->bss_section->flags & ~SEC_LOAD) | SEC_IS_COMMON;
+ }
+
+ *secp = sdata->bss_section;
+ *valp = sym->st_size;
+ }
+
+ return true;
+}
+
+
+/* Finish up dynamic symbol handling. We set the contents of various
+ dynamic sections here. */
+
+static boolean
+ppc_elf_finish_dynamic_symbol (output_bfd, info, h, sym)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+{
+ bfd *dynobj;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_finish_dynamic_symbol called for %s\n", h->root.root.string);
+#endif
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (h->plt_offset != (bfd_vma) -1)
+ {
+ asection *splt;
+ asection *srela;
+ Elf_Internal_Rela rela;
+
+ /* This symbol has an entry in the procedure linkage table. Set
+ it up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ srela = bfd_get_section_by_name (dynobj, ".rela.plt");
+ BFD_ASSERT (splt != NULL && srela != NULL);
+
+ /* Fill in the entry in the procedure linkage table. */
+#if 0
+ bfd_put_32 (output_bfd,
+ PLT_ENTRY_WORD0 + h->plt_offset,
+ splt->contents + h->plt_offset);
+ bfd_put_32 (output_bfd,
+ (PLT_ENTRY_WORD1
+ + (((- (h->plt_offset + 4)) >> 2) & 0x3fffff)),
+ splt->contents + h->plt_offset + 4);
+ bfd_put_32 (output_bfd, PLT_ENTRY_WORD2,
+ splt->contents + h->plt_offset + 8);
+
+ /* Fill in the entry in the .rela.plt section. */
+ rela.r_offset = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_JMP_SLOT);
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) srela->contents
+ + h->plt_offset / PLT_ENTRY_SIZE - 4));
+#endif
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ /* Mark the symbol as undefined, rather than as defined in
+ the .plt section. Leave the value alone. */
+ sym->st_shndx = SHN_UNDEF;
+ }
+ }
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+ {
+ asection *s;
+ Elf_Internal_Rela rela;
+
+ /* This symbols needs a copy reloc. Set it up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ s = bfd_get_section_by_name (h->root.u.def.section->owner,
+ ".rela.bss");
+ BFD_ASSERT (s != NULL);
+
+ rela.r_offset = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_COPY);
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) s->contents
+ + s->reloc_count));
+ ++s->reloc_count;
+ }
+
+ /* Mark some specially defined symbols as absolute. */
+ if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+ || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
+ || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
+ sym->st_shndx = SHN_ABS;
+
+ return true;
+}
+
+
+/* Finish up the dynamic sections. */
+
+static boolean
+ppc_elf_finish_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ asection *sdyn;
+ bfd *dynobj = elf_hash_table (info)->dynobj;
+ elf_linker_section_t *got = elf_linker_section (dynobj, LINKER_SECTION_GOT);
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_finish_dynamic_sections called\n");
+#endif
+
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ asection *splt;
+ Elf32_External_Dyn *dyncon, *dynconend;
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL && sdyn != NULL);
+
+ dyncon = (Elf32_External_Dyn *) sdyn->contents;
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ boolean size;
+
+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ case DT_PLTGOT: name = ".plt"; size = false; break;
+ case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
+ case DT_JMPREL: name = ".rela.plt"; size = false; break;
+ default: name = NULL; size = false; break;
+ }
+
+ if (name != NULL)
+ {
+ asection *s;
+
+ s = bfd_get_section_by_name (output_bfd, name);
+ if (s == NULL)
+ dyn.d_un.d_val = 0;
+ else
+ {
+ if (! size)
+ dyn.d_un.d_ptr = s->vma;
+ else
+ {
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val = s->_cooked_size;
+ else
+ dyn.d_un.d_val = s->_raw_size;
+ }
+ }
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ }
+ }
+ }
+
+ /* Add a blrl instruction at _GLOBAL_OFFSET_TABLE_-4 so that a function can
+ easily find the address of the _GLOBAL_OFFSET_TABLE_. */
+ if (got)
+ {
+ unsigned char *contents = got->section->contents + got->hole_offset;
+ bfd_put_32 (output_bfd, 0x4e800021 /* blrl */, contents);
+
+ if (sdyn == NULL)
+ bfd_put_32 (output_bfd, (bfd_vma) 0, contents+4);
+ else
+ bfd_put_32 (output_bfd,
+ sdyn->output_section->vma + sdyn->output_offset,
+ contents+4);
+
+ elf_section_data (got->section->output_section)->this_hdr.sh_entsize = 4;
+ }
+
+ if (info->shared)
+ {
+ asection *sdynsym;
+ asection *s;
+ Elf_Internal_Sym sym;
+
+ /* Set up the section symbols for the output sections. */
+
+ sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (sdynsym != NULL);
+
+ sym.st_size = 0;
+ sym.st_name = 0;
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ sym.st_other = 0;
+
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ {
+ int indx;
+
+ sym.st_value = s->vma;
+
+ indx = elf_section_data (s)->this_idx;
+ BFD_ASSERT (indx > 0);
+ sym.st_shndx = indx;
+
+ bfd_elf32_swap_symbol_out (output_bfd, &sym,
+ (PTR) (((Elf32_External_Sym *)
+ sdynsym->contents)
+ + elf_section_data (s)->dynindx));
+ }
+
+ /* Set the sh_info field of the output .dynsym section to the
+ index of the first global symbol. */
+ elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+ bfd_count_sections (output_bfd) + 1;
+ }
+
+ return true;
+}
+
+
+/* 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. */
+
+static boolean
+ppc_elf_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ 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;
+{
+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
+ bfd *dynobj = elf_hash_table (info)->dynobj;
+ elf_linker_section_t *got = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_GOT) : NULL;
+ elf_linker_section_t *sdata = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA) : NULL;
+ elf_linker_section_t *sdata2 = (dynobj) ? elf_linker_section (dynobj, LINKER_SECTION_SDATA2) : NULL;
+ Elf_Internal_Rela *rel = relocs;
+ Elf_Internal_Rela *relend = relocs + input_section->reloc_count;
+ boolean ret = true;
+ long insn;
+
+#ifdef DEBUG
+ fprintf (stderr, "ppc_elf_relocate_section called for %s section %s, %ld relocations%s\n",
+ bfd_get_filename (input_bfd),
+ bfd_section_name(input_bfd, input_section),
+ (long)input_section->reloc_count,
+ (info->relocateable) ? " (relocatable)" : "");
+#endif
+
+ if (!ppc_elf_howto_table[ R_PPC_ADDR32 ]) /* Initialize howto table if needed */
+ ppc_elf_howto_init ();
+
+ for (; rel < relend; rel++)
+ {
+ enum ppc_reloc_type r_type = (enum ppc_reloc_type)ELF32_R_TYPE (rel->r_info);
+ bfd_vma offset = rel->r_offset;
+ bfd_vma addend = rel->r_addend;
+ bfd_reloc_status_type r = bfd_reloc_other;
+ Elf_Internal_Sym *sym = (Elf_Internal_Sym *)0;
+ asection *sec = (asection *)0;
+ struct elf_link_hash_entry *h = (struct elf_link_hash_entry *)0;
+ const char *sym_name = (const char *)0;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ bfd_vma relocation;
+
+ /* Unknown relocation handling */
+ if ((unsigned)r_type >= (unsigned)R_PPC_max || !ppc_elf_howto_table[(int)r_type])
+ {
+ (*_bfd_error_handler) ("%s: unknown relocation type %d",
+ bfd_get_filename (input_bfd),
+ (int)r_type);
+
+ bfd_set_error (bfd_error_bad_value);
+ ret = false;
+ continue;
+ }
+
+ howto = ppc_elf_howto_table[(int)r_type];
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (info->relocateable)
+ {
+ /* This is a relocateable link. We don't have to change
+ anything, unless the reloc is against a section symbol,
+ in which case we have to adjust according to where the
+ section symbol winds up in the output section. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ if ((unsigned)ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ {
+ sec = local_sections[r_symndx];
+ addend = rel->r_addend += sec->output_offset + sym->st_value;
+ }
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "\ttype = %s (%d), symbol index = %ld, offset = %ld, addend = %ld\n",
+ howto->name,
+ (int)r_type,
+ r_symndx,
+ (long)offset,
+ (long)addend);
+#endif
+ continue;
+ }
+
+ /* This is a final link. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ sym_name = "<local symbol>";
+
+ relocation = (sec->output_section->vma
+ + sec->output_offset
+ + sym->st_value);
+ }
+ else
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ sym_name = h->root.root.string;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else if (info->shared)
+ relocation = 0;
+ else
+ {
+ (*info->callbacks->undefined_symbol)(info,
+ h->root.root.string,
+ input_bfd,
+ input_section,
+ rel->r_offset);
+ ret = false;
+ continue;
+ }
+ }
+
+ switch ((int)r_type)
+ {
+ default:
+ (*_bfd_error_handler) ("%s: unknown relocation type %d for symbol %s",
+ bfd_get_filename (input_bfd),
+ (int)r_type, sym_name);
+
+ bfd_set_error (bfd_error_bad_value);
+ ret = false;
+ continue;
+
+ /* relocations that need no special processing */
+ case (int)R_PPC_NONE:
+ case (int)R_PPC_ADDR32:
+ case (int)R_PPC_ADDR24:
+ case (int)R_PPC_ADDR16:
+ case (int)R_PPC_ADDR16_LO:
+ case (int)R_PPC_ADDR16_HI:
+ case (int)R_PPC_ADDR14:
+ case (int)R_PPC_REL24:
+ case (int)R_PPC_REL14:
+ case (int)R_PPC_UADDR32:
+ case (int)R_PPC_UADDR16:
+ case (int)R_PPC_REL32:
+ break;
+
+ /* branch taken prediction relocations */
+ case (int)R_PPC_ADDR14_BRTAKEN:
+ case (int)R_PPC_REL14_BRTAKEN:
+ insn = bfd_get_32 (output_bfd, contents + offset);
+ if ((relocation - offset) & 0x8000)
+ insn &= ~BRANCH_PREDICT_BIT;
+ else
+ insn |= BRANCH_PREDICT_BIT;
+ bfd_put_32 (output_bfd, insn, contents + offset);
+ break;
+
+ /* branch not taken predicition relocations */
+ case (int)R_PPC_ADDR14_BRNTAKEN:
+ case (int)R_PPC_REL14_BRNTAKEN:
+ insn = bfd_get_32 (output_bfd, contents + offset);
+ if ((relocation - offset) & 0x8000)
+ insn |= BRANCH_PREDICT_BIT;
+ else
+ insn &= ~BRANCH_PREDICT_BIT;
+ bfd_put_32 (output_bfd, insn, contents + offset);
+ break;
+
+ /* GOT16 relocations */
+ case (int)R_PPC_GOT16:
+ case (int)R_PPC_GOT16_LO:
+ case (int)R_PPC_GOT16_HI:
+ case (int)R_PPC_GOT16_HA:
+ relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
+ got, h, relocation, rel,
+ R_PPC_RELATIVE);
+ break;
+
+ /* Indirect .sdata relocation */
+ case (int)R_PPC_EMB_SDAI16:
+ BFD_ASSERT (sdata != NULL);
+ relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
+ sdata, h, relocation, rel,
+ R_PPC_RELATIVE);
+ break;
+
+ /* Indirect .sdata2 relocation */
+ case (int)R_PPC_EMB_SDA2I16:
+ BFD_ASSERT (sdata2 != NULL);
+ relocation = bfd_elf32_finish_pointer_linker_section (output_bfd, input_bfd, info,
+ sdata2, h, relocation, rel,
+ R_PPC_RELATIVE);
+ break;
+
+ /* Handle the TOC16 reloc. We want to use the offset within the .got
+ section, not the actual VMA. This is appropriate when generating
+ an embedded ELF object, for which the .got section acts like the
+ AIX .toc section. */
+ case (int)R_PPC_TOC16: /* phony GOT16 relocations */
+ BFD_ASSERT (sec != (asection *)0);
+ BFD_ASSERT (bfd_is_und_section (sec)
+ || strcmp (bfd_get_section_name (abfd, sec), ".got") == 0
+ || strcmp (bfd_get_section_name (abfd, sec), ".cgot") == 0)
+
+ addend -= sec->output_section->vma + sec->output_offset + 0x8000;
+ break;
+
+ /* arithmetic adjust relocations */
+ case (int)R_PPC_ADDR16_HA:
+ BFD_ASSERT (sec != (asection *)0);
+ addend += ((relocation + addend) & 0x8000) << 1;
+ break;
+
+ /* relocate against _SDA_BASE_ */
+ case (int)R_PPC_SDAREL16:
+ BFD_ASSERT (sec != (asection *)0);
+ if (strcmp (bfd_get_section_name (abfd, sec), ".sdata") != 0
+ && strcmp (bfd_get_section_name (abfd, sec), ".sbss") != 0)
+ {
+ (*_bfd_error_handler) ("%s: The target (%s) of a %s relocation is in the wrong section (%s)",
+ bfd_get_filename (input_bfd),
+ sym_name,
+ ppc_elf_howto_table[ (int)r_type ]->name,
+ bfd_get_section_name (abfd, sec));
+
+ bfd_set_error (bfd_error_bad_value);
+ ret = false;
+ continue;
+ }
+ addend -= (sdata->sym_hash->root.u.def.value
+ + sdata->sym_hash->root.u.def.section->output_section->vma
+ + sdata->sym_hash->root.u.def.section->output_offset);
+ break;
+
+
+ /* relocate against _SDA2_BASE_ */
+ case (int)R_PPC_EMB_SDA2REL:
+ BFD_ASSERT (sec != (asection *)0);
+ if (strcmp (bfd_get_section_name (abfd, sec), ".sdata2") != 0
+ && strcmp (bfd_get_section_name (abfd, sec), ".sbss2") != 0)
+ {
+ (*_bfd_error_handler) ("%s: The target (%s) of a %s relocation is in the wrong section (%s)",
+ bfd_get_filename (input_bfd),
+ sym_name,
+ ppc_elf_howto_table[ (int)r_type ]->name,
+ bfd_get_section_name (abfd, sec));
+
+ bfd_set_error (bfd_error_bad_value);
+ ret = false;
+ continue;
+ }
+ addend -= (sdata2->sym_hash->root.u.def.value
+ + sdata2->sym_hash->root.u.def.section->output_section->vma
+ + sdata2->sym_hash->root.u.def.section->output_offset);
+ break;
+
+
+ /* relocate against either _SDA_BASE_, _SDA2_BASE_, or 0 */
+ case (int)R_PPC_EMB_SDA21:
+ case (int)R_PPC_EMB_RELSDA:
+ {
+ const char *name = bfd_get_section_name (abfd, sec);
+ int reg;
+
+ BFD_ASSERT (sec != (asection *)0);
+ if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0)
+ {
+ reg = 13;
+ addend -= (sdata->sym_hash->root.u.def.value
+ + sdata->sym_hash->root.u.def.section->output_section->vma
+ + sdata->sym_hash->root.u.def.section->output_offset);
+ }
+
+ else if (strcmp (name, ".sdata2") == 0 || strcmp (name, ".sbss2") == 0)
+ {
+ reg = 2;
+ addend -= (sdata2->sym_hash->root.u.def.value
+ + sdata2->sym_hash->root.u.def.section->output_section->vma
+ + sdata2->sym_hash->root.u.def.section->output_offset);
+ }
+
+ else if (strcmp (name, ".PPC.EMB.sdata0") == 0 || strcmp (name, ".PPC.EMB.sbss0") == 0)
+ {
+ reg = 0;
+ }
+
+ else
+ {
+ (*_bfd_error_handler) ("%s: The target (%s) of a %s relocation is in the wrong section (%s)",
+ bfd_get_filename (input_bfd),
+ sym_name,
+ ppc_elf_howto_table[ (int)r_type ]->name,
+ bfd_get_section_name (abfd, sec));
+
+ bfd_set_error (bfd_error_bad_value);
+ ret = false;
+ continue;
+ }
+
+ if (r_type == R_PPC_EMB_SDA21)
+ { /* fill in register field */
+ insn = bfd_get_32 (output_bfd, contents + offset);
+ insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
+ bfd_put_32 (output_bfd, insn, contents + offset);
+ }
+ }
+ break;
+
+ /* Relocate against the beginning of the section */
+ case (int)R_PPC_SECTOFF:
+ case (int)R_PPC_SECTOFF_LO:
+ case (int)R_PPC_SECTOFF_HI:
+ BFD_ASSERT (sec != (asection *)0);
+ addend -= sec->output_section->vma;
+ break;
+
+ case (int)R_PPC_SECTOFF_HA:
+ BFD_ASSERT (sec != (asection *)0);
+ addend -= sec->output_section->vma;
+ addend += ((relocation + addend) & 0x8000) << 1;
+ break;
+
+ /* Negative relocations */
+ case (int)R_PPC_EMB_NADDR32:
+ case (int)R_PPC_EMB_NADDR16:
+ case (int)R_PPC_EMB_NADDR16_LO:
+ case (int)R_PPC_EMB_NADDR16_HI:
+ addend -= 2*relocation;
+ break;
+
+ case (int)R_PPC_EMB_NADDR16_HA:
+ addend -= 2*relocation;
+ addend += ((relocation + addend) & 0x8000) << 1;
+ break;
+
+ /* NOP relocation that prevents garbage collecting linkers from omitting a
+ reference. */
+ case (int)R_PPC_EMB_MRKREF:
+ continue;
+
+ case (int)R_PPC_PLTREL24:
+ case (int)R_PPC_COPY:
+ case (int)R_PPC_GLOB_DAT:
+ case (int)R_PPC_JMP_SLOT:
+ case (int)R_PPC_RELATIVE:
+ case (int)R_PPC_LOCAL24PC:
+ case (int)R_PPC_PLT32:
+ case (int)R_PPC_PLTREL32:
+ case (int)R_PPC_PLT16_LO:
+ case (int)R_PPC_PLT16_HI:
+ case (int)R_PPC_PLT16_HA:
+ case (int)R_PPC_EMB_RELSEC16:
+ case (int)R_PPC_EMB_RELST_LO:
+ case (int)R_PPC_EMB_RELST_HI:
+ case (int)R_PPC_EMB_RELST_HA:
+ case (int)R_PPC_EMB_BIT_FLD:
+ (*_bfd_error_handler) ("%s: Relocation %s is not yet supported for symbol %s.",
+ bfd_get_filename (input_bfd),
+ ppc_elf_howto_table[ (int)r_type ]->name,
+ sym_name);
+
+ bfd_set_error (bfd_error_invalid_operation);
+ ret = false;
+ continue;
+ }
+
+
+#ifdef DEBUG
+ fprintf (stderr, "\ttype = %s (%d), name = %s, symbol index = %ld, offset = %ld, addend = %ld\n",
+ howto->name,
+ (int)r_type,
+ sym_name,
+ r_symndx,
+ (long)offset,
+ (long)addend);
+#endif
+
+ r = _bfd_final_link_relocate (howto,
+ input_bfd,
+ input_section,
+ contents,
+ offset,
+ relocation,
+ addend);
+
+ if (r != bfd_reloc_ok)
+ {
+ ret = false;
+ switch (r)
+ {
+ default:
+ break;
+
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ break;
+
+ if (*name == '\0')
+ name = bfd_section_name (input_bfd, sec);
+ }
+
+ (*info->callbacks->reloc_overflow)(info,
+ name,
+ howto->name,
+ (bfd_vma) 0,
+ input_bfd,
+ input_section,
+ offset);
+ }
+ break;
+
+ }
+ }
+ }
+
+
+#ifdef DEBUG
+ fprintf (stderr, "\n");
+#endif
+
+ return ret;
+}
+
+
+#define TARGET_LITTLE_SYM bfd_elf32_powerpcle_vec
+#define TARGET_LITTLE_NAME "elf32-powerpcle"
+#define TARGET_BIG_SYM bfd_elf32_powerpc_vec
+#define TARGET_BIG_NAME "elf32-powerpc"
+#define ELF_ARCH bfd_arch_powerpc
+#define ELF_MACHINE_CODE EM_PPC
+#define ELF_MAXPAGESIZE 0x10000
+#define elf_info_to_howto ppc_elf_info_to_howto
+
+#ifdef EM_CYGNUS_POWERPC
+#define ELF_MACHINE_ALT1 EM_CYGNUS_POWERPC
+#endif
+
+#ifdef EM_PPC_OLD
+#define ELF_MACHINE_ALT2 EM_PPC_OLD
+#endif
+
+#define bfd_elf32_bfd_copy_private_bfd_data ppc_elf_copy_private_bfd_data
+#define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data
+#define bfd_elf32_bfd_set_private_flags ppc_elf_set_private_flags
+#define bfd_elf32_bfd_reloc_type_lookup ppc_elf_reloc_type_lookup
+#define elf_backend_section_from_shdr ppc_elf_section_from_shdr
+#define elf_backend_relocate_section ppc_elf_relocate_section
+#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
+#define elf_backend_check_relocs ppc_elf_check_relocs
+#define elf_backend_adjust_dynamic_symbol ppc_elf_adjust_dynamic_symbol
+#define elf_backend_add_symbol_hook ppc_elf_add_symbol_hook
+#define elf_backend_size_dynamic_sections ppc_elf_size_dynamic_sections
+#define elf_backend_finish_dynamic_symbol ppc_elf_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections ppc_elf_finish_dynamic_sections
+#define elf_backend_fake_sections ppc_elf_fake_sections
+#define elf_backend_additional_program_headers ppc_elf_additional_program_headers
+#define elf_backend_modify_segment_map ppc_elf_modify_segment_map
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32-sparc.c b/contrib/gdb/bfd/elf32-sparc.c
new file mode 100644
index 0000000..918eb00
--- /dev/null
+++ b/contrib/gdb/bfd/elf32-sparc.c
@@ -0,0 +1,1795 @@
+/* SPARC-specific support for 32-bit ELF
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+#include "elf/sparc.h"
+
+static reloc_howto_type *elf32_sparc_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static void elf_info_to_howto
+ PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+static boolean elf32_sparc_check_relocs
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ const Elf_Internal_Rela *));
+static boolean elf32_sparc_adjust_dynamic_symbol
+ PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
+static boolean elf32_sparc_adjust_dynindx
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf32_sparc_size_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean elf32_sparc_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean elf32_sparc_finish_dynamic_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,
+ Elf_Internal_Sym *));
+static boolean elf32_sparc_finish_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean elf32_sparc_merge_private_bfd_data PARAMS ((bfd *, bfd *));
+static boolean elf32_sparc_object_p
+ PARAMS ((bfd *));
+static void elf32_sparc_final_write_processing
+ PARAMS ((bfd *, boolean));
+
+/* The howto table and associated functions.
+ ??? elf64-sparc.c has its own copy for the moment to ease transition
+ since some of the relocation values have changed. At some point we'll
+ want elf64-sparc.c to switch over and use this table.
+ ??? Do we want to recognize (or flag as errors) some of the 64 bit entries
+ if the target is elf32-sparc.
+*/
+
+static bfd_reloc_status_type sparc_elf_notsupported_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+static bfd_reloc_status_type sparc_elf_wdisp16_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+
+reloc_howto_type _bfd_sparc_elf_howto_table[] =
+{
+ HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true),
+ HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true),
+ HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0x00ffffff,true),
+ HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true),
+ HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_GOT13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PC22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false,0,0x3fffffff,true),
+ HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false,0,0x00000000,true),
+ HOWTO(R_SPARC_GLOB_DAT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_JMP_SLOT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true),
+ HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PLT32", false,0,0x00000000,true),
+ HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true),
+ HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PCPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT22", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PCPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT10", false,0,0x00000000,true),
+ HOWTO(R_SPARC_10, 0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_11, 0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_11", false,0,0x000007ff,true),
+ /* ??? If we need to handle R_SPARC_64 then we need (figuratively)
+ --enable-64-bit-bfd. That causes objdump to print address as 64 bits
+ which we really don't want on an elf32-sparc system. There may be other
+ consequences which we may not want (at least not until it's proven they're
+ necessary) so for now these are only enabled ifdef BFD64. */
+#ifdef BFD64
+ HOWTO(R_SPARC_64, 0,4,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_64", false,0,~ (bfd_vma) 0, true),
+ /* ??? These don't make sense except in 64 bit systems so they're disabled
+ ifndef BFD64 too (for now). */
+ HOWTO(R_SPARC_OLO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_OLO10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_HH22, 42,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_HM10, 32,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_LM22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC_HH22, 42,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC_HM10, 32,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_PC_LM22, 10,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true),
+#else
+ HOWTO(R_SPARC_64, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_64", false,0,0x00000000,true),
+ HOWTO(R_SPARC_OLO10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_OLO10", false,0,0x00000000,true),
+ HOWTO(R_SPARC_HH22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HH22", false,0,0x00000000,true),
+ HOWTO(R_SPARC_HM10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HM10", false,0,0x00000000,true),
+ HOWTO(R_SPARC_LM22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LM22", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PC_HH22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_HH22", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PC_HM10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_HM10", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PC_LM22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PC_LM22", false,0,0x00000000,true),
+#endif
+ HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,complain_overflow_signed, sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true),
+ HOWTO(R_SPARC_WDISP19, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false,0,0x0007ffff,true),
+ HOWTO(R_SPARC_GLOB_JMP, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_7, 0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_7", false,0,0x0000007f,true),
+ HOWTO(R_SPARC_5, 0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", false,0,0x0000001f,true),
+ HOWTO(R_SPARC_6, 0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", false,0,0x0000003f,true),
+};
+
+struct elf_reloc_map {
+ unsigned char bfd_reloc_val;
+ unsigned char elf_reloc_val;
+};
+
+static CONST struct elf_reloc_map sparc_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_SPARC_NONE, },
+ { BFD_RELOC_16, R_SPARC_16, },
+ { BFD_RELOC_8, R_SPARC_8 },
+ { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
+ /* ??? This might cause us to need separate functions in elf{32,64}-sparc.c
+ (we could still have just one table), but is this reloc ever used? */
+ { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */
+ { BFD_RELOC_32, R_SPARC_32 },
+ { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
+ { BFD_RELOC_HI22, R_SPARC_HI22 },
+ { BFD_RELOC_LO10, R_SPARC_LO10, },
+ { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+ { BFD_RELOC_SPARC22, R_SPARC_22 },
+ { BFD_RELOC_SPARC13, R_SPARC_13 },
+ { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
+ { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 },
+ { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 },
+ { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 },
+ { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 },
+ { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 },
+ { BFD_RELOC_SPARC_COPY, R_SPARC_COPY },
+ { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT },
+ { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
+ { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
+ { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
+ /* ??? Doesn't dwarf use this? */
+/*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
+ {BFD_RELOC_SPARC_10, R_SPARC_10},
+ {BFD_RELOC_SPARC_11, R_SPARC_11},
+ {BFD_RELOC_SPARC_64, R_SPARC_64},
+ {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10},
+ {BFD_RELOC_SPARC_HH22, R_SPARC_HH22},
+ {BFD_RELOC_SPARC_HM10, R_SPARC_HM10},
+ {BFD_RELOC_SPARC_LM22, R_SPARC_LM22},
+ {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22},
+ {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10},
+ {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22},
+ {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16},
+ {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19},
+ {BFD_RELOC_SPARC_GLOB_JMP, R_SPARC_GLOB_JMP},
+ {BFD_RELOC_SPARC_7, R_SPARC_7},
+ {BFD_RELOC_SPARC_5, R_SPARC_5},
+ {BFD_RELOC_SPARC_6, R_SPARC_6},
+};
+
+static reloc_howto_type *
+elf32_sparc_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+ for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++)
+ {
+ if (sparc_reloc_map[i].bfd_reloc_val == code)
+ return &_bfd_sparc_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val];
+ }
+ return 0;
+}
+
+/* We need to use ELF32_R_TYPE so we have our own copy of this function,
+ and elf64-sparc.c has its own copy. */
+
+static void
+elf_info_to_howto (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf_Internal_Rela *dst;
+{
+ BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_SPARC_max);
+ cache_ptr->howto = &_bfd_sparc_elf_howto_table[ELF32_R_TYPE(dst->r_info)];
+}
+
+/* For unsupported relocs. */
+
+static bfd_reloc_status_type
+sparc_elf_notsupported_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ return bfd_reloc_notsupported;
+}
+
+/* Handle the WDISP16 reloc. */
+
+static bfd_reloc_status_type
+sparc_elf_wdisp16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_vma relocation;
+ bfd_vma x;
+
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && (! reloc_entry->howto->partial_inplace
+ || reloc_entry->addend == 0))
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (output_bfd != NULL)
+ return bfd_reloc_continue;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ relocation = (symbol->value
+ + symbol->section->output_section->vma
+ + symbol->section->output_offset);
+ relocation += reloc_entry->addend;
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset);
+ relocation -= reloc_entry->address;
+
+ x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
+ x |= ((((relocation >> 2) & 0xc000) << 6)
+ | ((relocation >> 2) & 0x3fff));
+ bfd_put_32 (abfd, x, (char *) data + reloc_entry->address);
+
+ if ((bfd_signed_vma) relocation < - 0x40000
+ || (bfd_signed_vma) relocation > 0x3ffff)
+ return bfd_reloc_overflow;
+ else
+ return bfd_reloc_ok;
+}
+
+/* Functions for the SPARC ELF linker. */
+
+/* The name of the dynamic interpreter. This is put in the .interp
+ section. */
+
+#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
+
+/* The nop opcode we use. */
+
+#define SPARC_NOP 0x01000000
+
+/* The size in bytes of an entry in the procedure linkage table. */
+
+#define PLT_ENTRY_SIZE 12
+
+/* The first four entries in a procedure linkage table are reserved,
+ and the initial contents are unimportant (we zero them out).
+ Subsequent entries look like this. See the SVR4 ABI SPARC
+ supplement to see how this works. */
+
+/* sethi %hi(.-.plt0),%g1. We fill in the address later. */
+#define PLT_ENTRY_WORD0 0x03000000
+/* b,a .plt0. We fill in the offset later. */
+#define PLT_ENTRY_WORD1 0x30800000
+/* nop. */
+#define PLT_ENTRY_WORD2 SPARC_NOP
+
+/* Look through the relocs for a section during the first phase, and
+ allocate space in the global offset table or procedure linkage
+ table. */
+
+static boolean
+elf32_sparc_check_relocs (abfd, info, sec, relocs)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ const Elf_Internal_Rela *relocs;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma *local_got_offsets;
+ const Elf_Internal_Rela *rel;
+ const Elf_Internal_Rela *rel_end;
+ asection *sgot;
+ asection *srelgot;
+ asection *sreloc;
+
+ if (info->relocateable)
+ return true;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (abfd);
+ local_got_offsets = elf_local_got_offsets (abfd);
+
+ sgot = NULL;
+ srelgot = NULL;
+ sreloc = NULL;
+
+ rel_end = relocs + sec->reloc_count;
+ for (rel = relocs; rel < rel_end; rel++)
+ {
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+ if (r_symndx < symtab_hdr->sh_info)
+ h = NULL;
+ else
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+
+ switch (ELF32_R_TYPE (rel->r_info))
+ {
+ case R_SPARC_GOT10:
+ case R_SPARC_GOT13:
+ case R_SPARC_GOT22:
+ /* This symbol requires a global offset table entry. */
+
+ if (dynobj == NULL)
+ {
+ /* Create the .got section. */
+ elf_hash_table (info)->dynobj = dynobj = abfd;
+ if (! _bfd_elf_create_got_section (dynobj, info))
+ return false;
+ }
+
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ if (srelgot == NULL
+ && (h != NULL || info->shared))
+ {
+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ if (srelgot == NULL)
+ {
+ srelgot = bfd_make_section (dynobj, ".rela.got");
+ if (srelgot == NULL
+ || ! bfd_set_section_flags (dynobj, srelgot,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, srelgot, 2))
+ return false;
+ }
+ }
+
+ if (h != NULL)
+ {
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+ h->got_offset = sgot->_raw_size;
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ srelgot->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ else
+ {
+ /* This is a global offset table entry for a local
+ symbol. */
+ if (local_got_offsets == NULL)
+ {
+ size_t size;
+ register unsigned int i;
+
+ size = symtab_hdr->sh_info * sizeof (bfd_vma);
+ local_got_offsets = (bfd_vma *) bfd_alloc (abfd, size);
+ if (local_got_offsets == NULL)
+ return false;
+ elf_local_got_offsets (abfd) = local_got_offsets;
+ for (i = 0; i < symtab_hdr->sh_info; i++)
+ local_got_offsets[i] = (bfd_vma) -1;
+ }
+ if (local_got_offsets[r_symndx] != (bfd_vma) -1)
+ {
+ /* We have already allocated space in the .got. */
+ break;
+ }
+ local_got_offsets[r_symndx] = sgot->_raw_size;
+
+ if (info->shared)
+ {
+ /* If we are generating a shared object, we need to
+ output a R_SPARC_RELATIVE reloc so that the
+ dynamic linker can adjust this GOT entry. */
+ srelgot->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ }
+
+ sgot->_raw_size += 4;
+
+ break;
+
+ case R_SPARC_WPLT30:
+ /* This symbol requires a procedure linkage table entry. We
+ actually build the entry in adjust_dynamic_symbol,
+ because this might be a case of linking PIC code without
+ linking in any dynamic objects, in which case we don't
+ need to generate a procedure linkage table after all. */
+
+ if (h == NULL)
+ {
+ /* It does not make sense to have a procedure linkage
+ table entry for a local symbol. */
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! bfd_elf32_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+
+ break;
+
+ case R_SPARC_PC10:
+ case R_SPARC_PC22:
+ if (h != NULL
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ break;
+ /* Fall through. */
+ case R_SPARC_DISP8:
+ case R_SPARC_DISP16:
+ case R_SPARC_DISP32:
+ case R_SPARC_WDISP30:
+ case R_SPARC_WDISP22:
+ case R_SPARC_WDISP19:
+ case R_SPARC_WDISP16:
+ if (h == NULL)
+ break;
+ /* Fall through. */
+ case R_SPARC_8:
+ case R_SPARC_16:
+ case R_SPARC_32:
+ case R_SPARC_HI22:
+ case R_SPARC_22:
+ case R_SPARC_13:
+ case R_SPARC_LO10:
+ case R_SPARC_UA32:
+ if (info->shared
+ && (sec->flags & SEC_ALLOC) != 0)
+ {
+ /* When creating a shared object, we must copy these
+ relocs into the output file. We create a reloc
+ section in dynobj and make room for the reloc. */
+ if (sreloc == NULL)
+ {
+ const char *name;
+
+ name = (bfd_elf_string_from_elf_section
+ (abfd,
+ elf_elfheader (abfd)->e_shstrndx,
+ elf_section_data (sec)->rel_hdr.sh_name));
+ if (name == NULL)
+ return false;
+
+ BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+ && strcmp (bfd_get_section_name (abfd, sec),
+ name + 5) == 0);
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ if (sreloc == NULL)
+ {
+ sreloc = bfd_make_section (dynobj, name);
+ if (sreloc == NULL
+ || ! bfd_set_section_flags (dynobj, sreloc,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, sreloc, 2))
+ return false;
+ }
+ }
+
+ sreloc->_raw_size += sizeof (Elf32_External_Rela);
+ }
+
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return true;
+}
+
+/* Adjust a symbol defined by a dynamic object and referenced by a
+ regular object. The current definition is in some section of the
+ dynamic object, but we're not including those sections. We have to
+ change the definition to something the rest of the link can
+ understand. */
+
+static boolean
+elf32_sparc_adjust_dynamic_symbol (info, h)
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+{
+ bfd *dynobj;
+ asection *s;
+ unsigned int power_of_two;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* Make sure we know what is going on here. */
+ BFD_ASSERT (dynobj != NULL
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT)
+ || h->weakdef != NULL
+ || ((h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_REF_REGULAR) != 0
+ && (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)));
+
+ /* If this is a function, put it in the procedure linkage table. We
+ will fill in the contents of the procedure linkage table later
+ (although we could actually do it here). */
+ if (h->type == STT_FUNC
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0)
+ {
+ if (! elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* This case can occur if we saw a WPLT30 reloc in an input
+ file, but none of the input files were dynamic objects.
+ In such a case, we don't actually need to build a
+ procedure linkage table, and we can just do a WDISP30
+ reloc instead. */
+ BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0);
+ return true;
+ }
+
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+
+ /* The first four entries in .plt are reserved. */
+ if (s->_raw_size == 0)
+ s->_raw_size = 4 * PLT_ENTRY_SIZE;
+
+ /* The procedure linkage table has a maximum size. */
+ if (s->_raw_size >= 0x400000)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ /* If this symbol is not defined in a regular file, and we are
+ not generating a shared library, then set the symbol to this
+ location in the .plt. This is required to make function
+ pointers compare as equal between the normal executable and
+ the shared library. */
+ if (! info->shared
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+ }
+
+ h->plt_offset = s->_raw_size;
+
+ /* Make room for this entry. */
+ s->_raw_size += PLT_ENTRY_SIZE;
+
+ /* We also need to make an entry in the .rela.plt section. */
+
+ s = bfd_get_section_by_name (dynobj, ".rela.plt");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size += sizeof (Elf32_External_Rela);
+
+ return true;
+ }
+
+ /* If this is a weak symbol, and there is a real definition, the
+ processor independent code will have arranged for us to see the
+ real definition first, and we can just use the same value. */
+ if (h->weakdef != NULL)
+ {
+ BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
+ || h->weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->weakdef->root.u.def.section;
+ h->root.u.def.value = h->weakdef->root.u.def.value;
+ return true;
+ }
+
+ /* This is a reference to a symbol defined by a dynamic object which
+ is not a function. */
+
+ /* If we are creating a shared library, we must presume that the
+ only references to the symbol are via the global offset table.
+ For such cases we need not do anything here; the relocations will
+ be handled correctly by relocate_section. */
+ if (info->shared)
+ return true;
+
+ /* We must allocate the symbol in our .dynbss section, which will
+ become part of the .bss section of the executable. There will be
+ an entry for this symbol in the .dynsym section. The dynamic
+ object will contain position independent code, so all references
+ from the dynamic object to this symbol will go through the global
+ offset table. The dynamic linker will use the .dynsym entry to
+ determine the address it must put in the global offset table, so
+ both the dynamic object and the regular object will refer to the
+ same memory location for the variable. */
+
+ s = bfd_get_section_by_name (dynobj, ".dynbss");
+ BFD_ASSERT (s != NULL);
+
+ /* If the symbol is currently defined in the .bss section of the
+ dynamic object, then it is OK to simply initialize it to zero.
+ If the symbol is in some other section, we must generate a
+ R_SPARC_COPY reloc to tell the dynamic linker to copy the initial
+ value out of the dynamic object and into the runtime process
+ image. We need to remember the offset into the .rel.bss section
+ we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_LOAD) != 0)
+ {
+ asection *srel;
+
+ srel = bfd_get_section_by_name (dynobj, ".rela.bss");
+ BFD_ASSERT (srel != NULL);
+ srel->_raw_size += sizeof (Elf32_External_Rela);
+ h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY;
+ }
+
+ /* We need to figure out the alignment required for this symbol. I
+ have no idea how ELF linkers handle this. */
+ power_of_two = bfd_log2 (h->size);
+ if (power_of_two > 3)
+ power_of_two = 3;
+
+ /* Apply the required alignment. */
+ s->_raw_size = BFD_ALIGN (s->_raw_size,
+ (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > bfd_get_section_alignment (dynobj, s))
+ {
+ if (! bfd_set_section_alignment (dynobj, s, power_of_two))
+ return false;
+ }
+
+ /* Define the symbol as being at this point in the section. */
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->_raw_size;
+
+ /* Increment the section size to make room for the symbol. */
+ s->_raw_size += h->size;
+
+ return true;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static boolean
+elf32_sparc_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *s;
+ boolean reltext;
+ boolean relplt;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (! info->shared)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
+ }
+
+ /* Make space for the trailing nop in .plt. */
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+ if (s->_raw_size > 0)
+ s->_raw_size += 4;
+ }
+ else
+ {
+ /* We may have created entries in the .rela.got section.
+ However, if we are not creating the dynamic sections, we will
+ not actually use these entries. Reset the size of .rela.got,
+ which will cause it to get stripped from the output file
+ below. */
+ s = bfd_get_section_by_name (dynobj, ".rela.got");
+ if (s != NULL)
+ s->_raw_size = 0;
+ }
+
+ /* The check_relocs and adjust_dynamic_symbol entry points have
+ determined the sizes of the various dynamic sections. Allocate
+ memory for them. */
+ reltext = false;
+ relplt = false;
+ for (s = dynobj->sections; s != NULL; s = s->next)
+ {
+ const char *name;
+ boolean strip;
+
+ if ((s->flags & SEC_IN_MEMORY) == 0)
+ continue;
+
+ /* It's OK to base decisions on the section name, because none
+ of the dynobj section names depend upon the input files. */
+ name = bfd_get_section_name (dynobj, s);
+
+ strip = false;
+
+ if (strncmp (name, ".rela", 5) == 0)
+ {
+ if (s->_raw_size == 0)
+ {
+ /* If we don't need this section, strip it from the
+ output file. This is to handle .rela.bss and
+ .rel.plt. We must create it in
+ create_dynamic_sections, because it must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ strip = true;
+ }
+ else
+ {
+ asection *target;
+
+ /* If this relocation section applies to a read only
+ section, then we probably need a DT_TEXTREL entry. */
+ target = bfd_get_section_by_name (output_bfd, name + 5);
+ if (target != NULL
+ && (target->flags & SEC_READONLY) != 0)
+ reltext = true;
+
+ if (strcmp (name, ".rela.plt") == 0)
+ relplt = true;
+
+ /* We use the reloc_count field as a counter if we need
+ to copy relocs into the output file. */
+ s->reloc_count = 0;
+ }
+ }
+ else if (strcmp (name, ".plt") != 0
+ && strcmp (name, ".got") != 0)
+ {
+ /* It's not one of our sections, so don't allocate space. */
+ continue;
+ }
+
+ if (strip)
+ {
+ asection **spp;
+
+ for (spp = &s->output_section->owner->sections;
+ *spp != s->output_section;
+ spp = &(*spp)->next)
+ ;
+ *spp = s->output_section->next;
+ --s->output_section->owner->section_count;
+
+ continue;
+ }
+
+ /* Allocate memory for the section contents. */
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ return false;
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Add some entries to the .dynamic section. We fill in the
+ values later, in elf32_sparc_finish_dynamic_sections, but we
+ must add the entries now so that we get the correct size for
+ the .dynamic section. The DT_DEBUG entry is filled in by the
+ dynamic linker and used by the debugger. */
+ if (! info->shared)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_DEBUG, 0))
+ return false;
+ }
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_PLTGOT, 0))
+ return false;
+
+ if (relplt)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_PLTRELSZ, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_JMPREL, 0))
+ return false;
+ }
+
+ if (! bfd_elf32_add_dynamic_entry (info, DT_RELA, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_RELASZ, 0)
+ || ! bfd_elf32_add_dynamic_entry (info, DT_RELAENT,
+ sizeof (Elf32_External_Rela)))
+ return false;
+
+ if (reltext)
+ {
+ if (! bfd_elf32_add_dynamic_entry (info, DT_TEXTREL, 0))
+ return false;
+ }
+ }
+
+ /* If we are generating a shared library, we generate a section
+ symbol for each output section. These are local symbols, which
+ means that they must come first in the dynamic symbol table.
+ That means we must increment the dynamic symbol index of every
+ other dynamic symbol. */
+ if (info->shared)
+ {
+ int c, i;
+
+ c = bfd_count_sections (output_bfd);
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf32_sparc_adjust_dynindx,
+ (PTR) &c);
+ elf_hash_table (info)->dynsymcount += c;
+
+ for (i = 1, s = output_bfd->sections; s != NULL; s = s->next, i++)
+ {
+ elf_section_data (s)->dynindx = i;
+ /* These symbols will have no names, so we don't need to
+ fiddle with dynstr_index. */
+ }
+ }
+
+ return true;
+}
+
+/* Increment the index of a dynamic symbol by a given amount. Called
+ via elf_link_hash_traverse. */
+
+static boolean
+elf32_sparc_adjust_dynindx (h, cparg)
+ struct elf_link_hash_entry *h;
+ PTR cparg;
+{
+ int *cp = (int *) cparg;
+
+ if (h->dynindx != -1)
+ h->dynindx += *cp;
+ return true;
+}
+
+/* Relocate a SPARC ELF section. */
+
+static boolean
+elf32_sparc_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ 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;
+{
+ bfd *dynobj;
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ bfd_vma *local_got_offsets;
+ asection *sgot;
+ asection *splt;
+ asection *sreloc;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (input_bfd);
+ local_got_offsets = elf_local_got_offsets (input_bfd);
+
+ sgot = NULL;
+ splt = NULL;
+ sreloc = NULL;
+
+ rel = relocs;
+ relend = relocs + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ int r_type;
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+
+ r_type = ELF32_R_TYPE (rel->r_info);
+ if (r_type < 0 || r_type >= (int) R_SPARC_max)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ howto = _bfd_sparc_elf_howto_table + r_type;
+
+ r_symndx = ELF32_R_SYM (rel->r_info);
+
+ if (info->relocateable)
+ {
+ /* This is a relocateable link. We don't have to change
+ anything, unless the reloc is against a section symbol,
+ in which case we have to adjust according to where the
+ section symbol winds up in the output section. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ {
+ sec = local_sections[r_symndx];
+ rel->r_addend += sec->output_offset + sym->st_value;
+ }
+ }
+
+ continue;
+ }
+
+ /* This is a final link. */
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ relocation = (sec->output_section->vma
+ + sec->output_offset
+ + sym->st_value);
+ }
+ else
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ if ((r_type == R_SPARC_WPLT30
+ && h->plt_offset != (bfd_vma) -1)
+ || ((r_type == R_SPARC_GOT10
+ || r_type == R_SPARC_GOT13
+ || r_type == R_SPARC_GOT22)
+ && elf_hash_table (info)->dynamic_sections_created
+ && (! info->shared
+ || ! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ || (info->shared
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ && (input_section->flags & SEC_ALLOC) != 0
+ && (r_type == R_SPARC_8
+ || r_type == R_SPARC_16
+ || r_type == R_SPARC_32
+ || r_type == R_SPARC_DISP8
+ || r_type == R_SPARC_DISP16
+ || r_type == R_SPARC_DISP32
+ || r_type == R_SPARC_WDISP30
+ || r_type == R_SPARC_WDISP22
+ || r_type == R_SPARC_WDISP19
+ || r_type == R_SPARC_WDISP16
+ || r_type == R_SPARC_HI22
+ || r_type == R_SPARC_22
+ || r_type == R_SPARC_13
+ || r_type == R_SPARC_LO10
+ || r_type == R_SPARC_UA32
+ || ((r_type == R_SPARC_PC10
+ || r_type == R_SPARC_PC22)
+ && strcmp (h->root.root.string,
+ "_GLOBAL_OFFSET_TABLE_") != 0))))
+ {
+ /* In these cases, we don't need the relocation
+ value. We check specially because in some
+ obscure cases sec->output_section will be NULL. */
+ relocation = 0;
+ }
+ else
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else if (info->shared && !info->symbolic)
+ relocation = 0;
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ relocation = 0;
+ }
+ }
+
+ switch (r_type)
+ {
+ case R_SPARC_GOT10:
+ case R_SPARC_GOT13:
+ case R_SPARC_GOT22:
+ /* Relocation is to the entry for this symbol in the global
+ offset table. */
+ if (sgot == NULL)
+ {
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ }
+
+ if (h != NULL)
+ {
+ bfd_vma off;
+
+ off = h->got_offset;
+ BFD_ASSERT (off != (bfd_vma) -1);
+
+ if (! elf_hash_table (info)->dynamic_sections_created
+ || (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ {
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally. We must initialize this entry in the
+ global offset table. Since the offset must
+ always be a multiple of 4, we use the least
+ significant bit to record whether we have
+ initialized it already.
+
+ When doing a dynamic link, we create a .rela.got
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation,
+ sgot->contents + off);
+ h->got_offset |= 1;
+ }
+ }
+
+ relocation = sgot->output_offset + off;
+ }
+ else
+ {
+ bfd_vma off;
+
+ BFD_ASSERT (local_got_offsets != NULL
+ && local_got_offsets[r_symndx] != (bfd_vma) -1);
+
+ off = local_got_offsets[r_symndx];
+
+ /* The offset must always be a multiple of 4. We use
+ the least significant bit to record whether we have
+ already processed this entry. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd, relocation, sgot->contents + off);
+
+ if (info->shared)
+ {
+ asection *srelgot;
+ Elf_Internal_Rela outrel;
+
+ /* We need to generate a R_SPARC_RELATIVE reloc
+ for the dynamic linker. */
+ srelgot = bfd_get_section_by_name (dynobj, ".rela.got");
+ BFD_ASSERT (srelgot != NULL);
+
+ outrel.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + off);
+ outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
+ outrel.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+ (((Elf32_External_Rela *)
+ srelgot->contents)
+ + srelgot->reloc_count));
+ ++srelgot->reloc_count;
+ }
+
+ local_got_offsets[r_symndx] |= 1;
+ }
+
+ relocation = sgot->output_offset + off;
+ }
+
+ break;
+
+ case R_SPARC_WPLT30:
+ /* Relocation is to the entry for this symbol in the
+ procedure linkage table. */
+ BFD_ASSERT (h != NULL);
+
+ if (h->plt_offset == (bfd_vma) -1)
+ {
+ /* We didn't make a PLT entry for this symbol. This
+ happens when statically linking PIC code, or when
+ using -Bsymbolic. */
+ break;
+ }
+
+ if (splt == NULL)
+ {
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL);
+ }
+
+ relocation = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset);
+ break;
+
+ case R_SPARC_PC10:
+ case R_SPARC_PC22:
+ if (h != NULL
+ && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+ break;
+ /* Fall through. */
+ case R_SPARC_DISP8:
+ case R_SPARC_DISP16:
+ case R_SPARC_DISP32:
+ case R_SPARC_WDISP30:
+ case R_SPARC_WDISP22:
+ case R_SPARC_WDISP19:
+ case R_SPARC_WDISP16:
+ if (h == NULL)
+ break;
+ /* Fall through. */
+ case R_SPARC_8:
+ case R_SPARC_16:
+ case R_SPARC_32:
+ case R_SPARC_HI22:
+ case R_SPARC_22:
+ case R_SPARC_13:
+ case R_SPARC_LO10:
+ case R_SPARC_UA32:
+ if (info->shared
+ && (input_section->flags & SEC_ALLOC) != 0)
+ {
+ Elf_Internal_Rela outrel;
+
+ /* When generating a shared object, these relocations
+ are copied into the output file to be resolved at run
+ time. */
+
+ if (sreloc == NULL)
+ {
+ const char *name;
+
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd,
+ elf_elfheader (input_bfd)->e_shstrndx,
+ elf_section_data (input_section)->rel_hdr.sh_name));
+ if (name == NULL)
+ return false;
+
+ BFD_ASSERT (strncmp (name, ".rela", 5) == 0
+ && strcmp (bfd_get_section_name (input_bfd,
+ input_section),
+ name + 5) == 0);
+
+ sreloc = bfd_get_section_by_name (dynobj, name);
+ BFD_ASSERT (sreloc != NULL);
+ }
+
+ outrel.r_offset = (rel->r_offset
+ + input_section->output_section->vma
+ + input_section->output_offset);
+ if (h != NULL
+ && (! info->symbolic
+ || (h->elf_link_hash_flags
+ & ELF_LINK_HASH_DEF_REGULAR) == 0))
+ {
+ BFD_ASSERT (h->dynindx != -1);
+ outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
+ outrel.r_addend = rel->r_addend;
+ }
+ else
+ {
+ if (r_type == R_SPARC_32)
+ {
+ outrel.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
+ outrel.r_addend = relocation + rel->r_addend;
+ }
+ else
+ {
+ long indx;
+
+ if (h == NULL)
+ sec = local_sections[r_symndx];
+ else
+ {
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || (h->root.type
+ == bfd_link_hash_defweak));
+ sec = h->root.u.def.section;
+ }
+ if (sec != NULL && bfd_is_abs_section (sec))
+ indx = 0;
+ else if (sec == NULL || sec->owner == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ else
+ {
+ asection *osec;
+
+ osec = sec->output_section;
+ indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ abort ();
+ }
+
+ outrel.r_info = ELF32_R_INFO (indx, r_type);
+ outrel.r_addend = relocation + rel->r_addend;
+ }
+ }
+
+ bfd_elf32_swap_reloca_out (output_bfd, &outrel,
+ (((Elf32_External_Rela *)
+ sreloc->contents)
+ + sreloc->reloc_count));
+ ++sreloc->reloc_count;
+
+ /* This reloc will be computed at runtime, so there's no
+ need to do anything now. */
+ continue;
+ }
+
+ default:
+ break;
+ }
+
+ if (r_type != R_SPARC_WDISP16)
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, rel->r_addend);
+ else
+ {
+ bfd_vma x;
+
+ relocation += rel->r_addend;
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset);
+ relocation -= rel->r_offset;
+
+ x = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ x |= ((((relocation >> 2) & 0xc000) << 6)
+ | ((relocation >> 2) & 0x3fff));
+ bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
+ if ((bfd_signed_vma) relocation < - 0x40000
+ || (bfd_signed_vma) relocation > 0x3ffff)
+ r = bfd_reloc_overflow;
+ else
+ r = bfd_reloc_ok;
+ }
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name);
+ if (name == NULL)
+ return false;
+ if (*name == '\0')
+ name = bfd_section_name (input_bfd, sec);
+ }
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0,
+ input_bfd, input_section, rel->r_offset)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Finish up dynamic symbol handling. We set the contents of various
+ dynamic sections here. */
+
+static boolean
+elf32_sparc_finish_dynamic_symbol (output_bfd, info, h, sym)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+{
+ bfd *dynobj;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ if (h->plt_offset != (bfd_vma) -1)
+ {
+ asection *splt;
+ asection *srela;
+ Elf_Internal_Rela rela;
+
+ /* This symbol has an entry in the procedure linkage table. Set
+ it up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ srela = bfd_get_section_by_name (dynobj, ".rela.plt");
+ BFD_ASSERT (splt != NULL && srela != NULL);
+
+ /* Fill in the entry in the procedure linkage table. */
+ bfd_put_32 (output_bfd,
+ PLT_ENTRY_WORD0 + h->plt_offset,
+ splt->contents + h->plt_offset);
+ bfd_put_32 (output_bfd,
+ (PLT_ENTRY_WORD1
+ + (((- (h->plt_offset + 4)) >> 2) & 0x3fffff)),
+ splt->contents + h->plt_offset + 4);
+ bfd_put_32 (output_bfd, PLT_ENTRY_WORD2,
+ splt->contents + h->plt_offset + 8);
+
+ /* Fill in the entry in the .rela.plt section. */
+ rela.r_offset = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_JMP_SLOT);
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) srela->contents
+ + h->plt_offset / PLT_ENTRY_SIZE - 4));
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ {
+ /* Mark the symbol as undefined, rather than as defined in
+ the .plt section. Leave the value alone. */
+ sym->st_shndx = SHN_UNDEF;
+ }
+ }
+
+ if (h->got_offset != (bfd_vma) -1)
+ {
+ asection *sgot;
+ asection *srela;
+ Elf_Internal_Rela rela;
+
+ /* This symbol has an entry in the global offset table. Set it
+ up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ srela = bfd_get_section_by_name (dynobj, ".rela.got");
+ BFD_ASSERT (sgot != NULL && srela != NULL);
+
+ rela.r_offset = (sgot->output_section->vma
+ + sgot->output_offset
+ + (h->got_offset &~ 1));
+
+ /* If this is a -Bsymbolic link, and the symbol is defined
+ locally, we just want to emit a RELATIVE reloc. The entry in
+ the global offset table will already have been initialized in
+ the relocate_section function. */
+ if (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
+ rela.r_info = ELF32_R_INFO (0, R_SPARC_RELATIVE);
+ else
+ {
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + h->got_offset);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_GLOB_DAT);
+ }
+
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) srela->contents
+ + srela->reloc_count));
+ ++srela->reloc_count;
+ }
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0)
+ {
+ asection *s;
+ Elf_Internal_Rela rela;
+
+ /* This symbols needs a copy reloc. Set it up. */
+
+ BFD_ASSERT (h->dynindx != -1);
+
+ s = bfd_get_section_by_name (h->root.u.def.section->owner,
+ ".rela.bss");
+ BFD_ASSERT (s != NULL);
+
+ rela.r_offset = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+ rela.r_info = ELF32_R_INFO (h->dynindx, R_SPARC_COPY);
+ rela.r_addend = 0;
+ bfd_elf32_swap_reloca_out (output_bfd, &rela,
+ ((Elf32_External_Rela *) s->contents
+ + s->reloc_count));
+ ++s->reloc_count;
+ }
+
+ /* Mark some specially defined symbols as absolute. */
+ if (strcmp (h->root.root.string, "_DYNAMIC") == 0
+ || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
+ || strcmp (h->root.root.string, "_PROCEDURE_LINKAGE_TABLE_") == 0)
+ sym->st_shndx = SHN_ABS;
+
+ return true;
+}
+
+/* Finish up the dynamic sections. */
+
+static boolean
+elf32_sparc_finish_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *sdyn;
+ asection *sgot;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ asection *splt;
+ Elf32_External_Dyn *dyncon, *dynconend;
+
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (splt != NULL && sdyn != NULL);
+
+ dyncon = (Elf32_External_Dyn *) sdyn->contents;
+ dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ boolean size;
+
+ bfd_elf32_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ case DT_PLTGOT: name = ".plt"; size = false; break;
+ case DT_PLTRELSZ: name = ".rela.plt"; size = true; break;
+ case DT_JMPREL: name = ".rela.plt"; size = false; break;
+ default: name = NULL; size = false; break;
+ }
+
+ if (name != NULL)
+ {
+ asection *s;
+
+ s = bfd_get_section_by_name (output_bfd, name);
+ if (s == NULL)
+ dyn.d_un.d_val = 0;
+ else
+ {
+ if (! size)
+ dyn.d_un.d_ptr = s->vma;
+ else
+ {
+ if (s->_cooked_size != 0)
+ dyn.d_un.d_val = s->_cooked_size;
+ else
+ dyn.d_un.d_val = s->_raw_size;
+ }
+ }
+ bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
+ }
+ }
+
+ /* Clear the first four entries in the procedure linkage table,
+ and put a nop in the last four bytes. */
+ if (splt->_raw_size > 0)
+ {
+ memset (splt->contents, 0, 4 * PLT_ENTRY_SIZE);
+ bfd_put_32 (output_bfd, SPARC_NOP,
+ splt->contents + splt->_raw_size - 4);
+ }
+
+ elf_section_data (splt->output_section)->this_hdr.sh_entsize =
+ PLT_ENTRY_SIZE;
+ }
+
+ /* Set the first entry in the global offset table to the address of
+ the dynamic section. */
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (sgot != NULL);
+ if (sgot->_raw_size > 0)
+ {
+ if (sdyn == NULL)
+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
+ else
+ bfd_put_32 (output_bfd,
+ sdyn->output_section->vma + sdyn->output_offset,
+ sgot->contents);
+ }
+
+ elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
+
+ if (info->shared)
+ {
+ asection *sdynsym;
+ asection *s;
+ Elf_Internal_Sym sym;
+
+ /* Set up the section symbols for the output sections. */
+
+ sdynsym = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (sdynsym != NULL);
+
+ sym.st_size = 0;
+ sym.st_name = 0;
+ sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ sym.st_other = 0;
+
+ for (s = output_bfd->sections; s != NULL; s = s->next)
+ {
+ int indx;
+
+ sym.st_value = s->vma;
+
+ indx = elf_section_data (s)->this_idx;
+ BFD_ASSERT (indx > 0);
+ sym.st_shndx = indx;
+
+ bfd_elf32_swap_symbol_out (output_bfd, &sym,
+ (PTR) (((Elf32_External_Sym *)
+ sdynsym->contents)
+ + elf_section_data (s)->dynindx));
+ }
+
+ /* Set the sh_info field of the output .dynsym section to the
+ index of the first global symbol. */
+ elf_section_data (sdynsym->output_section)->this_hdr.sh_info =
+ bfd_count_sections (output_bfd) + 1;
+ }
+
+ return true;
+}
+
+/* Functions for dealing with the e_flags field.
+
+ We don't define set_private_flags or copy_private_bfd_data because
+ the only currently defined values are based on the bfd mach number,
+ so we use the latter instead and defer setting e_flags until the
+ file is written out. */
+
+/* Merge backend specific data from an object file to the output
+ object file when linking. */
+
+static boolean
+elf32_sparc_merge_private_bfd_data (ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ boolean error;
+
+ /* This function is selected based on the input vector. We only
+ want to copy information over if the output BFD also uses Elf
+ format. */
+ if (bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return true;
+
+ error = false;
+
+#if 0
+ /* ??? The native linker doesn't do this so we can't (otherwise gcc would
+ have to know which linker is being used). Instead, the native linker
+ bumps up the architecture level when it has to. However, I still think
+ warnings like these are good, so it would be nice to have them turned on
+ by some option. */
+
+ /* If the output machine is normal sparc, we can't allow v9 input files. */
+ if (bfd_get_mach (obfd) == bfd_mach_sparc
+ && (bfd_get_mach (ibfd) == bfd_mach_sparc_v8plus
+ || bfd_get_mach (ibfd) == bfd_mach_sparc_v8plusa))
+ {
+ error = true;
+ (*_bfd_error_handler)
+ ("%s: compiled for a v8plus system and target is v8",
+ bfd_get_filename (ibfd));
+ }
+ /* If the output machine is v9, we can't allow v9+vis input files. */
+ if (bfd_get_mach (obfd) == bfd_mach_sparc_v8plus
+ && bfd_get_mach (ibfd) == bfd_mach_sparc_v8plusa)
+ {
+ error = true;
+ (*_bfd_error_handler)
+ ("%s: compiled for a v8plusa system and target is v8plus",
+ bfd_get_filename (ibfd));
+ }
+#else
+ if (bfd_get_mach (ibfd) >= bfd_mach_sparc_v9)
+ {
+ error = true;
+ (*_bfd_error_handler)
+ ("%s: compiled for a 64 bit system and target is 32 bit",
+ bfd_get_filename (ibfd));
+ }
+ else if (bfd_get_mach (obfd) < bfd_get_mach (ibfd))
+ bfd_set_arch_mach (obfd, bfd_arch_sparc, bfd_get_mach (ibfd));
+#endif
+
+ if (error)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ return true;
+}
+
+/* Set the right machine number. */
+
+static boolean
+elf32_sparc_object_p (abfd)
+ bfd *abfd;
+{
+ if (elf_elfheader (abfd)->e_machine == EM_SPARC32PLUS)
+ {
+ if (elf_elfheader (abfd)->e_flags & EF_SPARC_SUN_US1)
+ return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
+ bfd_mach_sparc_v8plusa);
+ else if (elf_elfheader (abfd)->e_flags & EF_SPARC_32PLUS)
+ return bfd_default_set_arch_mach (abfd, bfd_arch_sparc,
+ bfd_mach_sparc_v8plus);
+ else
+ return false;
+ }
+ else
+ return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc);
+}
+
+/* The final processing done just before writing out the object file.
+ We need to set the e_machine field appropriately. */
+
+static void
+elf32_sparc_final_write_processing (abfd, linker)
+ bfd *abfd;
+ boolean linker;
+{
+ switch (bfd_get_mach (abfd))
+ {
+ case bfd_mach_sparc :
+ break; /* nothing to do */
+ case bfd_mach_sparc_v8plus :
+ elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
+ elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
+ elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS;
+ break;
+ case bfd_mach_sparc_v8plusa :
+ elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS;
+ elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK;
+ elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1;
+ break;
+ default :
+ abort ();
+ }
+}
+
+#define TARGET_BIG_SYM bfd_elf32_sparc_vec
+#define TARGET_BIG_NAME "elf32-sparc"
+#define ELF_ARCH bfd_arch_sparc
+#define ELF_MACHINE_CODE EM_SPARC
+#define ELF_MACHINE_ALT1 EM_SPARC32PLUS
+#define ELF_MAXPAGESIZE 0x10000
+
+#define bfd_elf32_bfd_reloc_type_lookup elf32_sparc_reloc_type_lookup
+#define elf_backend_create_dynamic_sections \
+ _bfd_elf_create_dynamic_sections
+#define elf_backend_check_relocs elf32_sparc_check_relocs
+#define elf_backend_adjust_dynamic_symbol \
+ elf32_sparc_adjust_dynamic_symbol
+#define elf_backend_size_dynamic_sections \
+ elf32_sparc_size_dynamic_sections
+#define elf_backend_relocate_section elf32_sparc_relocate_section
+#define elf_backend_finish_dynamic_symbol \
+ elf32_sparc_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_sections \
+ elf32_sparc_finish_dynamic_sections
+#define bfd_elf32_bfd_merge_private_bfd_data \
+ elf32_sparc_merge_private_bfd_data
+#define elf_backend_object_p elf32_sparc_object_p
+#define elf_backend_final_write_processing \
+ elf32_sparc_final_write_processing
+#define elf_backend_want_got_plt 0
+#define elf_backend_plt_readonly 0
+#define elf_backend_want_plt_sym 1
+
+#include "elf32-target.h"
diff --git a/contrib/gdb/bfd/elf32.c b/contrib/gdb/bfd/elf32.c
new file mode 100644
index 0000000..f222969
--- /dev/null
+++ b/contrib/gdb/bfd/elf32.c
@@ -0,0 +1,23 @@
+/* ELF 32-bit executable support for BFD.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define ARCH_SIZE 32
+
+
+#include "elfcode.h"
diff --git a/contrib/gdb/bfd/elf64-gen.c b/contrib/gdb/bfd/elf64-gen.c
new file mode 100644
index 0000000..5daf4ee
--- /dev/null
+++ b/contrib/gdb/bfd/elf64-gen.c
@@ -0,0 +1,37 @@
+/* Generic support for 64-bit ELF
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+/* This does not include any relocations, but should be good enough
+ for GDB to read the file. */
+
+#define TARGET_LITTLE_SYM bfd_elf64_little_generic_vec
+#define TARGET_LITTLE_NAME "elf64-little"
+#define TARGET_BIG_SYM bfd_elf64_big_generic_vec
+#define TARGET_BIG_NAME "elf64-big"
+#define ELF_ARCH bfd_arch_unknown
+#define ELF_MACHINE_CODE EM_NONE
+#define bfd_elf64_bfd_reloc_type_lookup bfd_default_reloc_type_lookup
+#define elf_info_to_howto _bfd_elf_no_info_to_howto
+
+#include "elf64-target.h"
diff --git a/contrib/gdb/bfd/elf64-sparc.c b/contrib/gdb/bfd/elf64-sparc.c
new file mode 100644
index 0000000..5059b80
--- /dev/null
+++ b/contrib/gdb/bfd/elf64-sparc.c
@@ -0,0 +1,421 @@
+/* SPARC-specific support for 64-bit ELF
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* We need a published ABI spec for this. Until one comes out, don't
+ assume this'll remain unchanged forever. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+#define SPARC64_OLD_RELOCS
+#include "elf/sparc.h"
+
+static reloc_howto_type *sparc64_elf_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static void elf_info_to_howto
+ PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
+
+static boolean sparc64_elf_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
+static boolean sparc64_elf_object_p PARAMS ((bfd *));
+
+/* The howto table and associated functions.
+ ??? Some of the relocation values have changed. Until we're ready
+ to upgrade, we have our own copy. At some point a non upward compatible
+ change will be made at which point this table can be deleted and we'll
+ use the one in elf32-sparc.c. */
+
+static bfd_reloc_status_type sparc_elf_wdisp16_reloc
+ PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
+
+static reloc_howto_type sparc64_elf_howto_table[] =
+{
+ HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_NONE", false,0,0x00000000,true),
+ HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_32", false,0,0xffffffff,true),
+ HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_DISP32", false,0,0x00ffffff,true),
+ HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP30", false,0,0x3fffffff,true),
+ HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HI22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LO10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_GOT13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GOT22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC10, 0,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_PC10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_PC22, 10,2,22,true, 0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_PC22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_WPLT30, 2,2,30,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WPLT30", false,0,0x3fffffff,true),
+ HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_COPY", false,0,0x00000000,true),
+ HOWTO(R_SPARC_GLOB_DAT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_JMP_SLOT, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_JMP_SLOT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_RELATIVE, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_RELATIVE",false,0,0x00000000,true),
+ HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_UA32", false,0,0x00000000,true),
+#if 0 /* not used yet */
+ HOWTO(R_SPARC_PLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PLT32", false,0,0x00000000,true),
+ HOWTO(R_SPARC_HIPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_HIPLT22", false,0,0x00000000,true),
+ HOWTO(R_SPARC_LOPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_LOPLT10", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PCPLT32, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT32", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PCPLT22, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT22", false,0,0x00000000,true),
+ HOWTO(R_SPARC_PCPLT10, 0,0,00,false,0,complain_overflow_dont, sparc_elf_notsupported_reloc, "R_SPARC_PCPLT10", false,0,0x00000000,true),
+#endif
+ HOWTO(R_SPARC_10, 0,2,10,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_11, 0,2,11,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_11", false,0,0x000007ff,true),
+ HOWTO(R_SPARC_64, 0,4,00,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_64", false,0,~ (bfd_vma) 0, true),
+ HOWTO(R_SPARC_OLO10, 0,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_OLO10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_HH22, 42,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_HM10, 32,2,10,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_LM22, 10,2,22,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC_HH22, 42,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HH22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC_HM10, 32,2,10,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_HM10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_PC_LM22, 10,2,22,true, 0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_LM22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_WDISP16, 2,2,16,true, 0,complain_overflow_signed, sparc_elf_wdisp16_reloc,"R_SPARC_WDISP16", false,0,0x00000000,true),
+ HOWTO(R_SPARC_WDISP19, 2,2,22,true, 0,complain_overflow_signed, bfd_elf_generic_reloc, "R_SPARC_WDISP19", false,0,0x0007ffff,true),
+ HOWTO(R_SPARC_GLOB_JMP, 0,0,00,false,0,complain_overflow_dont, bfd_elf_generic_reloc, "R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_7, 0,2, 7,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_7", false,0,0x0000007f,true),
+#if 0 /* not used yet */
+ HOWTO(R_SPARC_5, 0,2, 5,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_5", false,0,0x0000001f,true),
+ HOWTO(R_SPARC_6, 0,2, 6,false,0,complain_overflow_bitfield,bfd_elf_generic_reloc, "R_SPARC_6", false,0,0x0000003f,true),
+#endif
+};
+
+struct elf_reloc_map {
+ unsigned char bfd_reloc_val;
+ unsigned char elf_reloc_val;
+};
+
+static CONST struct elf_reloc_map sparc_reloc_map[] =
+{
+ { BFD_RELOC_NONE, R_SPARC_NONE, },
+ { BFD_RELOC_16, R_SPARC_16, },
+ { BFD_RELOC_8, R_SPARC_8 },
+ { BFD_RELOC_8_PCREL, R_SPARC_DISP8 },
+ /* ??? This might cause us to need separate functions in elf{32,64}-sparc.c
+ (we could still have just one table), but is this reloc ever used? */
+ { BFD_RELOC_CTOR, R_SPARC_32 }, /* @@ Assumes 32 bits. */
+ { BFD_RELOC_32, R_SPARC_32 },
+ { BFD_RELOC_32_PCREL, R_SPARC_DISP32 },
+ { BFD_RELOC_HI22, R_SPARC_HI22 },
+ { BFD_RELOC_LO10, R_SPARC_LO10, },
+ { BFD_RELOC_32_PCREL_S2, R_SPARC_WDISP30 },
+ { BFD_RELOC_SPARC22, R_SPARC_22 },
+ { BFD_RELOC_SPARC13, R_SPARC_13 },
+ { BFD_RELOC_SPARC_GOT10, R_SPARC_GOT10 },
+ { BFD_RELOC_SPARC_GOT13, R_SPARC_GOT13 },
+ { BFD_RELOC_SPARC_GOT22, R_SPARC_GOT22 },
+ { BFD_RELOC_SPARC_PC10, R_SPARC_PC10 },
+ { BFD_RELOC_SPARC_PC22, R_SPARC_PC22 },
+ { BFD_RELOC_SPARC_WPLT30, R_SPARC_WPLT30 },
+ { BFD_RELOC_SPARC_COPY, R_SPARC_COPY },
+ { BFD_RELOC_SPARC_GLOB_DAT, R_SPARC_GLOB_DAT },
+ { BFD_RELOC_SPARC_JMP_SLOT, R_SPARC_JMP_SLOT },
+ { BFD_RELOC_SPARC_RELATIVE, R_SPARC_RELATIVE },
+ { BFD_RELOC_SPARC_WDISP22, R_SPARC_WDISP22 },
+ /* ??? Doesn't dwarf use this? */
+/*{ BFD_RELOC_SPARC_UA32, R_SPARC_UA32 }, not used?? */
+ {BFD_RELOC_SPARC_10, R_SPARC_10},
+ {BFD_RELOC_SPARC_11, R_SPARC_11},
+ {BFD_RELOC_SPARC_64, R_SPARC_64},
+ {BFD_RELOC_SPARC_OLO10, R_SPARC_OLO10},
+ {BFD_RELOC_SPARC_HH22, R_SPARC_HH22},
+ {BFD_RELOC_SPARC_HM10, R_SPARC_HM10},
+ {BFD_RELOC_SPARC_LM22, R_SPARC_LM22},
+ {BFD_RELOC_SPARC_PC_HH22, R_SPARC_PC_HH22},
+ {BFD_RELOC_SPARC_PC_HM10, R_SPARC_PC_HM10},
+ {BFD_RELOC_SPARC_PC_LM22, R_SPARC_PC_LM22},
+ {BFD_RELOC_SPARC_WDISP16, R_SPARC_WDISP16},
+ {BFD_RELOC_SPARC_WDISP19, R_SPARC_WDISP19},
+ {BFD_RELOC_SPARC_GLOB_JMP, R_SPARC_GLOB_JMP},
+ {BFD_RELOC_SPARC_7, R_SPARC_7},
+#if 0 /* unused */
+ {BFD_RELOC_SPARC_5, R_SPARC_5},
+ {BFD_RELOC_SPARC_6, R_SPARC_6},
+#endif
+};
+
+static reloc_howto_type *
+sparc64_elf_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ unsigned int i;
+ for (i = 0; i < sizeof (sparc_reloc_map) / sizeof (struct elf_reloc_map); i++)
+ {
+ if (sparc_reloc_map[i].bfd_reloc_val == code)
+ return &sparc64_elf_howto_table[(int) sparc_reloc_map[i].elf_reloc_val];
+ }
+ return 0;
+}
+
+static void
+elf_info_to_howto (abfd, cache_ptr, dst)
+ bfd *abfd;
+ arelent *cache_ptr;
+ Elf64_Internal_Rela *dst;
+{
+ BFD_ASSERT (ELF64_R_TYPE (dst->r_info) < (unsigned int) R_SPARC_max);
+ cache_ptr->howto = &sparc64_elf_howto_table[ELF64_R_TYPE (dst->r_info)];
+}
+
+/* Handle the WDISP16 reloc. */
+
+static bfd_reloc_status_type
+sparc_elf_wdisp16_reloc (abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd,
+ error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_vma relocation;
+ bfd_vma x;
+
+ if (output_bfd != (bfd *) NULL
+ && (symbol->flags & BSF_SECTION_SYM) == 0
+ && (! reloc_entry->howto->partial_inplace
+ || reloc_entry->addend == 0))
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ if (output_bfd != NULL)
+ return bfd_reloc_continue;
+
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ relocation = (symbol->value
+ + symbol->section->output_section->vma
+ + symbol->section->output_offset);
+ relocation += reloc_entry->addend;
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset);
+ relocation -= reloc_entry->address;
+
+ x = bfd_get_32 (abfd, (char *) data + reloc_entry->address);
+ x |= ((((relocation >> 2) & 0xc000) << 6)
+ | ((relocation >> 2) & 0x3fff));
+ bfd_put_32 (abfd, x, (char *) data + reloc_entry->address);
+
+ if ((bfd_signed_vma) relocation < - 0x40000
+ || (bfd_signed_vma) relocation > 0x3ffff)
+ return bfd_reloc_overflow;
+ else
+ return bfd_reloc_ok;
+}
+
+/* Relocate a SPARC64 ELF section. */
+
+static boolean
+sparc64_elf_relocate_section (output_bfd, info, input_bfd, input_section,
+ contents, relocs, local_syms, local_sections)
+ 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;
+{
+ Elf_Internal_Shdr *symtab_hdr;
+ struct elf_link_hash_entry **sym_hashes;
+ Elf_Internal_Rela *rel;
+ Elf_Internal_Rela *relend;
+
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ sym_hashes = elf_sym_hashes (input_bfd);
+
+ rel = relocs;
+ relend = relocs + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ int r_type;
+ reloc_howto_type *howto;
+ long r_symndx;
+ struct elf_link_hash_entry *h;
+ Elf_Internal_Sym *sym;
+ asection *sec;
+ bfd_vma relocation;
+ bfd_reloc_status_type r;
+
+ r_type = ELF64_R_TYPE (rel->r_info);
+ if (r_type < 0 || r_type >= (int) R_SPARC_max)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ howto = sparc64_elf_howto_table + r_type;
+
+ r_symndx = ELF64_R_SYM (rel->r_info);
+
+ if (info->relocateable)
+ {
+ /* This is a relocateable link. We don't have to change
+ anything, unless the reloc is against a section symbol,
+ in which case we have to adjust according to where the
+ section symbol winds up in the output section. */
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
+ {
+ sec = local_sections[r_symndx];
+ rel->r_addend += sec->output_offset + sym->st_value;
+ }
+ }
+
+ continue;
+ }
+
+ /* This is a final link. */
+ h = NULL;
+ sym = NULL;
+ sec = NULL;
+ if (r_symndx < symtab_hdr->sh_info)
+ {
+ sym = local_syms + r_symndx;
+ sec = local_sections[r_symndx];
+ relocation = (sec->output_section->vma
+ + sec->output_offset
+ + sym->st_value);
+ }
+ else
+ {
+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ sec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_undefweak)
+ relocation = 0;
+ else
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd,
+ input_section, rel->r_offset)))
+ return false;
+ relocation = 0;
+ }
+ }
+
+ if (r_type != R_SPARC_WDISP16)
+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
+ contents, rel->r_offset,
+ relocation, rel->r_addend);
+ else
+ {
+ bfd_vma x;
+
+ relocation += rel->r_addend;
+ relocation -= (input_section->output_section->vma
+ + input_section->output_offset);
+ relocation -= rel->r_offset;
+
+ x = bfd_get_32 (input_bfd, contents + rel->r_offset);
+ x |= ((((relocation >> 2) & 0xc000) << 6)
+ | ((relocation >> 2) & 0x3fff));
+ bfd_put_32 (input_bfd, x, contents + rel->r_offset);
+
+ if ((bfd_signed_vma) relocation < - 0x40000
+ || (bfd_signed_vma) relocation > 0x3ffff)
+ r = bfd_reloc_overflow;
+ else
+ r = bfd_reloc_ok;
+ }
+
+ if (r != bfd_reloc_ok)
+ {
+ switch (r)
+ {
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+
+ if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd,
+ symtab_hdr->sh_link,
+ sym->st_name));
+ if (name == NULL)
+ return false;
+ if (*name == '\0')
+ name = bfd_section_name (input_bfd, sec);
+ }
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto->name, (bfd_vma) 0,
+ input_bfd, input_section, rel->r_offset)))
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Set the right machine number for a SPARC64 ELF file. */
+
+static boolean
+sparc64_elf_object_p (abfd)
+ bfd *abfd;
+{
+ return bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9);
+}
+
+#define TARGET_BIG_SYM bfd_elf64_sparc_vec
+#define TARGET_BIG_NAME "elf64-sparc"
+#define ELF_ARCH bfd_arch_sparc
+#define ELF_MACHINE_CODE EM_SPARC64
+#define ELF_MAXPAGESIZE 0x100000
+
+#define bfd_elf64_bfd_reloc_type_lookup sparc64_elf_reloc_type_lookup
+#define elf_backend_relocate_section sparc64_elf_relocate_section
+#define elf_backend_object_p sparc64_elf_object_p
+
+#include "elf64-target.h"
diff --git a/contrib/gdb/bfd/elf64.c b/contrib/gdb/bfd/elf64.c
new file mode 100644
index 0000000..69fb5b5
--- /dev/null
+++ b/contrib/gdb/bfd/elf64.c
@@ -0,0 +1,22 @@
+/* ELF 64-bit executable support for BFD.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define ARCH_SIZE 64
+
+#include "elfcode.h"
diff --git a/contrib/gdb/bfd/elfcode.h b/contrib/gdb/bfd/elfcode.h
new file mode 100644
index 0000000..a6199f0
--- /dev/null
+++ b/contrib/gdb/bfd/elfcode.h
@@ -0,0 +1,1406 @@
+/* ELF executable support for BFD.
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, from information published
+ in "UNIX System V Release 4, Programmers Guide: ANSI C and
+ Programming Support Tools". Sufficient support for gdb.
+
+ Rewritten by Mark Eichin @ Cygnus Support, from information
+ published in "System V Application Binary Interface", chapters 4
+ and 5, as well as the various "Processor Supplement" documents
+ derived from it. Added support for assembler and other object file
+ utilities. Further work done by Ken Raeburn (Cygnus Support), Michael
+ Meissner (Open Software Foundation), and Peter Hoogenboom (University
+ of Utah) to finish and extend this.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Problems and other issues to resolve.
+
+ (1) BFD expects there to be some fixed number of "sections" in
+ the object file. I.E. there is a "section_count" variable in the
+ bfd structure which contains the number of sections. However, ELF
+ supports multiple "views" of a file. In particular, with current
+ implementations, executable files typically have two tables, a
+ program header table and a section header table, both of which
+ partition the executable.
+
+ In ELF-speak, the "linking view" of the file uses the section header
+ table to access "sections" within the file, and the "execution view"
+ uses the program header table to access "segments" within the file.
+ "Segments" typically may contain all the data from one or more
+ "sections".
+
+ Note that the section header table is optional in ELF executables,
+ but it is this information that is most useful to gdb. If the
+ section header table is missing, then gdb should probably try
+ to make do with the program header table. (FIXME)
+
+ (2) The code in this file is compiled twice, once in 32-bit mode and
+ once in 64-bit mode. More of it should be made size-independent
+ and moved into elf.c.
+
+ (3) ELF section symbols are handled rather sloppily now. This should
+ be cleaned up, and ELF section symbols reconciled with BFD section
+ symbols.
+
+ (4) We need a published spec for 64-bit ELF. We've got some stuff here
+ that we're using for SPARC V9 64-bit chips, but don't assume that
+ it's cast in stone.
+ */
+
+#include <string.h> /* For strrchr and friends */
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "elf-bfd.h"
+
+/* Renaming structures, typedefs, macros and functions to be size-specific. */
+#define Elf_External_Ehdr NAME(Elf,External_Ehdr)
+#define Elf_External_Sym NAME(Elf,External_Sym)
+#define Elf_External_Shdr NAME(Elf,External_Shdr)
+#define Elf_External_Phdr NAME(Elf,External_Phdr)
+#define Elf_External_Rel NAME(Elf,External_Rel)
+#define Elf_External_Rela NAME(Elf,External_Rela)
+#define Elf_External_Dyn NAME(Elf,External_Dyn)
+
+#define elf_core_file_failing_command NAME(bfd_elf,core_file_failing_command)
+#define elf_core_file_failing_signal NAME(bfd_elf,core_file_failing_signal)
+#define elf_core_file_matches_executable_p \
+ NAME(bfd_elf,core_file_matches_executable_p)
+#define elf_object_p NAME(bfd_elf,object_p)
+#define elf_core_file_p NAME(bfd_elf,core_file_p)
+#define elf_get_symtab_upper_bound NAME(bfd_elf,get_symtab_upper_bound)
+#define elf_get_dynamic_symtab_upper_bound \
+ NAME(bfd_elf,get_dynamic_symtab_upper_bound)
+#define elf_swap_reloc_in NAME(bfd_elf,swap_reloc_in)
+#define elf_swap_reloca_in NAME(bfd_elf,swap_reloca_in)
+#define elf_swap_reloc_out NAME(bfd_elf,swap_reloc_out)
+#define elf_swap_reloca_out NAME(bfd_elf,swap_reloca_out)
+#define elf_swap_symbol_in NAME(bfd_elf,swap_symbol_in)
+#define elf_swap_symbol_out NAME(bfd_elf,swap_symbol_out)
+#define elf_swap_phdr_in NAME(bfd_elf,swap_phdr_in)
+#define elf_swap_phdr_out NAME(bfd_elf,swap_phdr_out)
+#define elf_swap_dyn_in NAME(bfd_elf,swap_dyn_in)
+#define elf_swap_dyn_out NAME(bfd_elf,swap_dyn_out)
+#define elf_get_reloc_upper_bound NAME(bfd_elf,get_reloc_upper_bound)
+#define elf_canonicalize_reloc NAME(bfd_elf,canonicalize_reloc)
+#define elf_get_symtab NAME(bfd_elf,get_symtab)
+#define elf_canonicalize_dynamic_symtab \
+ NAME(bfd_elf,canonicalize_dynamic_symtab)
+#define elf_make_empty_symbol NAME(bfd_elf,make_empty_symbol)
+#define elf_get_symbol_info NAME(bfd_elf,get_symbol_info)
+#define elf_get_lineno NAME(bfd_elf,get_lineno)
+#define elf_set_arch_mach NAME(bfd_elf,set_arch_mach)
+#define elf_find_nearest_line NAME(bfd_elf,find_nearest_line)
+#define elf_sizeof_headers NAME(bfd_elf,sizeof_headers)
+#define elf_set_section_contents NAME(bfd_elf,set_section_contents)
+#define elf_no_info_to_howto NAME(bfd_elf,no_info_to_howto)
+#define elf_no_info_to_howto_rel NAME(bfd_elf,no_info_to_howto_rel)
+#define elf_find_section NAME(bfd_elf,find_section)
+#define elf_bfd_link_add_symbols NAME(bfd_elf,bfd_link_add_symbols)
+#define elf_add_dynamic_entry NAME(bfd_elf,add_dynamic_entry)
+#define elf_link_create_dynamic_sections \
+ NAME(bfd_elf,link_create_dynamic_sections)
+#define elf_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
+#define elf_bfd_final_link NAME(bfd_elf,bfd_final_link)
+#define elf_create_pointer_linker_section NAME(bfd_elf,create_pointer_linker_section)
+#define elf_finish_pointer_linker_section NAME(bfd_elf,finish_pointer_linker_section)
+
+#if ARCH_SIZE == 64
+#define ELF_R_INFO(X,Y) ELF64_R_INFO(X,Y)
+#define ELF_R_SYM(X) ELF64_R_SYM(X)
+#define ELF_R_TYPE(X) ELF64_R_TYPE(X)
+#define ELFCLASS ELFCLASS64
+#define FILE_ALIGN 8
+#define LOG_FILE_ALIGN 3
+#endif
+#if ARCH_SIZE == 32
+#define ELF_R_INFO(X,Y) ELF32_R_INFO(X,Y)
+#define ELF_R_SYM(X) ELF32_R_SYM(X)
+#define ELF_R_TYPE(X) ELF32_R_TYPE(X)
+#define ELFCLASS ELFCLASS32
+#define FILE_ALIGN 4
+#define LOG_FILE_ALIGN 2
+#endif
+
+/* Forward declarations of static functions */
+
+#define elf_stringtab_init _bfd_elf_stringtab_init
+
+extern struct bfd_strtab_hash *_bfd_elf_stringtab_init PARAMS ((void));
+#define section_from_elf_index bfd_section_from_elf_index
+extern boolean bfd_section_from_phdr PARAMS ((bfd *, Elf_Internal_Phdr *,
+ int));
+
+static long elf_slurp_symbol_table PARAMS ((bfd *, asymbol **, boolean));
+
+static boolean elf_slurp_reloc_table PARAMS ((bfd *, asection *, asymbol **));
+
+ int _bfd_elf_symbol_from_bfd_symbol PARAMS ((bfd *,
+ struct symbol_cache_entry **));
+
+static boolean validate_reloc PARAMS ((bfd *, arelent *));
+static void write_relocs PARAMS ((bfd *, asection *, PTR));
+
+ boolean bfd_section_from_shdr PARAMS ((bfd *, unsigned int shindex));
+
+#ifdef DEBUG
+static void elf_debug_section PARAMS ((int, Elf_Internal_Shdr *));
+static void elf_debug_file PARAMS ((Elf_Internal_Ehdr *));
+static char *elf_symbol_flags PARAMS ((flagword));
+#endif
+
+/* Structure swapping routines */
+
+/* Should perhaps use put_offset, put_word, etc. For now, the two versions
+ can be handled by explicitly specifying 32 bits or "the long type". */
+#if ARCH_SIZE == 64
+#define put_word bfd_h_put_64
+#define get_word bfd_h_get_64
+#endif
+#if ARCH_SIZE == 32
+#define put_word bfd_h_put_32
+#define get_word bfd_h_get_32
+#endif
+
+/* Translate an ELF symbol in external format into an ELF symbol in internal
+ format. */
+
+void
+elf_swap_symbol_in (abfd, src, dst)
+ bfd *abfd;
+ Elf_External_Sym *src;
+ Elf_Internal_Sym *dst;
+{
+ dst->st_name = bfd_h_get_32 (abfd, (bfd_byte *) src->st_name);
+ dst->st_value = get_word (abfd, (bfd_byte *) src->st_value);
+ dst->st_size = get_word (abfd, (bfd_byte *) src->st_size);
+ dst->st_info = bfd_h_get_8 (abfd, (bfd_byte *) src->st_info);
+ dst->st_other = bfd_h_get_8 (abfd, (bfd_byte *) src->st_other);
+ dst->st_shndx = bfd_h_get_16 (abfd, (bfd_byte *) src->st_shndx);
+}
+
+/* Translate an ELF symbol in internal format into an ELF symbol in external
+ format. */
+
+void
+elf_swap_symbol_out (abfd, src, cdst)
+ bfd *abfd;
+ Elf_Internal_Sym *src;
+ PTR cdst;
+{
+ Elf_External_Sym *dst = (Elf_External_Sym *) cdst;
+ bfd_h_put_32 (abfd, src->st_name, dst->st_name);
+ put_word (abfd, src->st_value, dst->st_value);
+ put_word (abfd, src->st_size, dst->st_size);
+ bfd_h_put_8 (abfd, src->st_info, dst->st_info);
+ bfd_h_put_8 (abfd, src->st_other, dst->st_other);
+ bfd_h_put_16 (abfd, src->st_shndx, dst->st_shndx);
+}
+
+
+/* Translate an ELF file header in external format into an ELF file header in
+ internal format. */
+
+static void
+elf_swap_ehdr_in (abfd, src, dst)
+ bfd *abfd;
+ Elf_External_Ehdr *src;
+ Elf_Internal_Ehdr *dst;
+{
+ memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
+ dst->e_type = bfd_h_get_16 (abfd, (bfd_byte *) src->e_type);
+ dst->e_machine = bfd_h_get_16 (abfd, (bfd_byte *) src->e_machine);
+ dst->e_version = bfd_h_get_32 (abfd, (bfd_byte *) src->e_version);
+ dst->e_entry = get_word (abfd, (bfd_byte *) src->e_entry);
+ dst->e_phoff = get_word (abfd, (bfd_byte *) src->e_phoff);
+ dst->e_shoff = get_word (abfd, (bfd_byte *) src->e_shoff);
+ dst->e_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->e_flags);
+ dst->e_ehsize = bfd_h_get_16 (abfd, (bfd_byte *) src->e_ehsize);
+ dst->e_phentsize = bfd_h_get_16 (abfd, (bfd_byte *) src->e_phentsize);
+ dst->e_phnum = bfd_h_get_16 (abfd, (bfd_byte *) src->e_phnum);
+ dst->e_shentsize = bfd_h_get_16 (abfd, (bfd_byte *) src->e_shentsize);
+ dst->e_shnum = bfd_h_get_16 (abfd, (bfd_byte *) src->e_shnum);
+ dst->e_shstrndx = bfd_h_get_16 (abfd, (bfd_byte *) src->e_shstrndx);
+}
+
+/* Translate an ELF file header in internal format into an ELF file header in
+ external format. */
+
+static void
+elf_swap_ehdr_out (abfd, src, dst)
+ bfd *abfd;
+ Elf_Internal_Ehdr *src;
+ Elf_External_Ehdr *dst;
+{
+ memcpy (dst->e_ident, src->e_ident, EI_NIDENT);
+ /* note that all elements of dst are *arrays of unsigned char* already... */
+ bfd_h_put_16 (abfd, src->e_type, dst->e_type);
+ bfd_h_put_16 (abfd, src->e_machine, dst->e_machine);
+ bfd_h_put_32 (abfd, src->e_version, dst->e_version);
+ put_word (abfd, src->e_entry, dst->e_entry);
+ put_word (abfd, src->e_phoff, dst->e_phoff);
+ put_word (abfd, src->e_shoff, dst->e_shoff);
+ bfd_h_put_32 (abfd, src->e_flags, dst->e_flags);
+ bfd_h_put_16 (abfd, src->e_ehsize, dst->e_ehsize);
+ bfd_h_put_16 (abfd, src->e_phentsize, dst->e_phentsize);
+ bfd_h_put_16 (abfd, src->e_phnum, dst->e_phnum);
+ bfd_h_put_16 (abfd, src->e_shentsize, dst->e_shentsize);
+ bfd_h_put_16 (abfd, src->e_shnum, dst->e_shnum);
+ bfd_h_put_16 (abfd, src->e_shstrndx, dst->e_shstrndx);
+}
+
+
+/* Translate an ELF section header table entry in external format into an
+ ELF section header table entry in internal format. */
+
+static void
+elf_swap_shdr_in (abfd, src, dst)
+ bfd *abfd;
+ Elf_External_Shdr *src;
+ Elf_Internal_Shdr *dst;
+{
+ dst->sh_name = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_name);
+ dst->sh_type = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_type);
+ dst->sh_flags = get_word (abfd, (bfd_byte *) src->sh_flags);
+ dst->sh_addr = get_word (abfd, (bfd_byte *) src->sh_addr);
+ dst->sh_offset = get_word (abfd, (bfd_byte *) src->sh_offset);
+ dst->sh_size = get_word (abfd, (bfd_byte *) src->sh_size);
+ dst->sh_link = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_link);
+ dst->sh_info = bfd_h_get_32 (abfd, (bfd_byte *) src->sh_info);
+ dst->sh_addralign = get_word (abfd, (bfd_byte *) src->sh_addralign);
+ dst->sh_entsize = get_word (abfd, (bfd_byte *) src->sh_entsize);
+ dst->bfd_section = NULL;
+ dst->contents = NULL;
+}
+
+/* Translate an ELF section header table entry in internal format into an
+ ELF section header table entry in external format. */
+
+static void
+elf_swap_shdr_out (abfd, src, dst)
+ bfd *abfd;
+ Elf_Internal_Shdr *src;
+ Elf_External_Shdr *dst;
+{
+ /* note that all elements of dst are *arrays of unsigned char* already... */
+ bfd_h_put_32 (abfd, src->sh_name, dst->sh_name);
+ bfd_h_put_32 (abfd, src->sh_type, dst->sh_type);
+ put_word (abfd, src->sh_flags, dst->sh_flags);
+ put_word (abfd, src->sh_addr, dst->sh_addr);
+ put_word (abfd, src->sh_offset, dst->sh_offset);
+ put_word (abfd, src->sh_size, dst->sh_size);
+ bfd_h_put_32 (abfd, src->sh_link, dst->sh_link);
+ bfd_h_put_32 (abfd, src->sh_info, dst->sh_info);
+ put_word (abfd, src->sh_addralign, dst->sh_addralign);
+ put_word (abfd, src->sh_entsize, dst->sh_entsize);
+}
+
+
+/* Translate an ELF program header table entry in external format into an
+ ELF program header table entry in internal format. */
+
+void
+elf_swap_phdr_in (abfd, src, dst)
+ bfd *abfd;
+ Elf_External_Phdr *src;
+ Elf_Internal_Phdr *dst;
+{
+ dst->p_type = bfd_h_get_32 (abfd, (bfd_byte *) src->p_type);
+ dst->p_flags = bfd_h_get_32 (abfd, (bfd_byte *) src->p_flags);
+ dst->p_offset = get_word (abfd, (bfd_byte *) src->p_offset);
+ dst->p_vaddr = get_word (abfd, (bfd_byte *) src->p_vaddr);
+ dst->p_paddr = get_word (abfd, (bfd_byte *) src->p_paddr);
+ dst->p_filesz = get_word (abfd, (bfd_byte *) src->p_filesz);
+ dst->p_memsz = get_word (abfd, (bfd_byte *) src->p_memsz);
+ dst->p_align = get_word (abfd, (bfd_byte *) src->p_align);
+}
+
+void
+elf_swap_phdr_out (abfd, src, dst)
+ bfd *abfd;
+ Elf_Internal_Phdr *src;
+ Elf_External_Phdr *dst;
+{
+ /* note that all elements of dst are *arrays of unsigned char* already... */
+ bfd_h_put_32 (abfd, src->p_type, dst->p_type);
+ put_word (abfd, src->p_offset, dst->p_offset);
+ put_word (abfd, src->p_vaddr, dst->p_vaddr);
+ put_word (abfd, src->p_paddr, dst->p_paddr);
+ put_word (abfd, src->p_filesz, dst->p_filesz);
+ put_word (abfd, src->p_memsz, dst->p_memsz);
+ bfd_h_put_32 (abfd, src->p_flags, dst->p_flags);
+ put_word (abfd, src->p_align, dst->p_align);
+}
+
+/* Translate an ELF reloc from external format to internal format. */
+INLINE void
+elf_swap_reloc_in (abfd, src, dst)
+ bfd *abfd;
+ Elf_External_Rel *src;
+ Elf_Internal_Rel *dst;
+{
+ dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset);
+ dst->r_info = get_word (abfd, (bfd_byte *) src->r_info);
+}
+
+INLINE void
+elf_swap_reloca_in (abfd, src, dst)
+ bfd *abfd;
+ Elf_External_Rela *src;
+ Elf_Internal_Rela *dst;
+{
+ dst->r_offset = get_word (abfd, (bfd_byte *) src->r_offset);
+ dst->r_info = get_word (abfd, (bfd_byte *) src->r_info);
+ dst->r_addend = get_word (abfd, (bfd_byte *) src->r_addend);
+}
+
+/* Translate an ELF reloc from internal format to external format. */
+INLINE void
+elf_swap_reloc_out (abfd, src, dst)
+ bfd *abfd;
+ Elf_Internal_Rel *src;
+ Elf_External_Rel *dst;
+{
+ put_word (abfd, src->r_offset, dst->r_offset);
+ put_word (abfd, src->r_info, dst->r_info);
+}
+
+INLINE void
+elf_swap_reloca_out (abfd, src, dst)
+ bfd *abfd;
+ Elf_Internal_Rela *src;
+ Elf_External_Rela *dst;
+{
+ put_word (abfd, src->r_offset, dst->r_offset);
+ put_word (abfd, src->r_info, dst->r_info);
+ put_word (abfd, src->r_addend, dst->r_addend);
+}
+
+INLINE void
+elf_swap_dyn_in (abfd, p, dst)
+ bfd *abfd;
+ const PTR p;
+ Elf_Internal_Dyn *dst;
+{
+ const Elf_External_Dyn *src = (const Elf_External_Dyn *) p;
+
+ dst->d_tag = get_word (abfd, src->d_tag);
+ dst->d_un.d_val = get_word (abfd, src->d_un.d_val);
+}
+
+INLINE void
+elf_swap_dyn_out (abfd, src, dst)
+ bfd *abfd;
+ const Elf_Internal_Dyn *src;
+ Elf_External_Dyn *dst;
+{
+ put_word (abfd, src->d_tag, dst->d_tag);
+ put_word (abfd, src->d_un.d_val, dst->d_un.d_val);
+}
+
+/* ELF .o/exec file reading */
+
+
+/* Begin processing a given object.
+
+ First we validate the file by reading in the ELF header and checking
+ the magic number. */
+
+static INLINE boolean
+elf_file_p (x_ehdrp)
+ Elf_External_Ehdr *x_ehdrp;
+{
+ return ((x_ehdrp->e_ident[EI_MAG0] == ELFMAG0)
+ && (x_ehdrp->e_ident[EI_MAG1] == ELFMAG1)
+ && (x_ehdrp->e_ident[EI_MAG2] == ELFMAG2)
+ && (x_ehdrp->e_ident[EI_MAG3] == ELFMAG3));
+}
+
+/* Check to see if the file associated with ABFD matches the target vector
+ that ABFD points to.
+
+ Note that we may be called several times with the same ABFD, but different
+ target vectors, most of which will not match. We have to avoid leaving
+ any side effects in ABFD, or any data it points to (like tdata), if the
+ file does not match the target vector. */
+
+const bfd_target *
+elf_object_p (abfd)
+ bfd *abfd;
+{
+ Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
+ Elf_External_Shdr x_shdr; /* Section header table entry, external form */
+ Elf_Internal_Shdr *i_shdrp = NULL; /* Section header table, internal form */
+ unsigned int shindex;
+ char *shstrtab; /* Internal copy of section header stringtab */
+ struct elf_backend_data *ebd;
+ struct elf_obj_tdata *preserved_tdata = elf_tdata (abfd);
+ struct elf_obj_tdata *new_tdata = NULL;
+
+ /* Read in the ELF header in external format. */
+
+ if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ goto got_wrong_format_error;
+ else
+ goto got_no_match;
+ }
+
+ /* Now check to see if we have a valid ELF file, and one that BFD can
+ make use of. The magic number must match, the address size ('class')
+ and byte-swapping must match our XVEC entry, and it must have a
+ section header table (FIXME: See comments re sections at top of this
+ file). */
+
+ if ((elf_file_p (&x_ehdr) == false) ||
+ (x_ehdr.e_ident[EI_VERSION] != EV_CURRENT) ||
+ (x_ehdr.e_ident[EI_CLASS] != ELFCLASS))
+ goto got_wrong_format_error;
+
+ /* Check that file's byte order matches xvec's */
+ switch (x_ehdr.e_ident[EI_DATA])
+ {
+ case ELFDATA2MSB: /* Big-endian */
+ if (! bfd_header_big_endian (abfd))
+ goto got_wrong_format_error;
+ break;
+ case ELFDATA2LSB: /* Little-endian */
+ if (! bfd_header_little_endian (abfd))
+ goto got_wrong_format_error;
+ break;
+ case ELFDATANONE: /* No data encoding specified */
+ default: /* Unknown data encoding specified */
+ goto got_wrong_format_error;
+ }
+
+ /* Allocate an instance of the elf_obj_tdata structure and hook it up to
+ the tdata pointer in the bfd. */
+
+ new_tdata = ((struct elf_obj_tdata *)
+ bfd_zalloc (abfd, sizeof (struct elf_obj_tdata)));
+ if (new_tdata == NULL)
+ goto got_no_match;
+ elf_tdata (abfd) = new_tdata;
+
+ /* Now that we know the byte order, swap in the rest of the header */
+ i_ehdrp = elf_elfheader (abfd);
+ elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
+#if DEBUG & 1
+ elf_debug_file (i_ehdrp);
+#endif
+
+ /* If there is no section header table, we're hosed. */
+ if (i_ehdrp->e_shoff == 0)
+ goto got_wrong_format_error;
+
+ /* As a simple sanity check, verify that the what BFD thinks is the
+ size of each section header table entry actually matches the size
+ recorded in the file. */
+ if (i_ehdrp->e_shentsize != sizeof (x_shdr))
+ goto got_wrong_format_error;
+
+ ebd = get_elf_backend_data (abfd);
+
+ /* Check that the ELF e_machine field matches what this particular
+ BFD format expects. */
+ if (ebd->elf_machine_code != i_ehdrp->e_machine
+ && (ebd->elf_machine_alt1 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt1)
+ && (ebd->elf_machine_alt2 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt2))
+ {
+ const bfd_target * const *target_ptr;
+
+ if (ebd->elf_machine_code != EM_NONE)
+ goto got_wrong_format_error;
+
+ /* This is the generic ELF target. Let it match any ELF target
+ for which we do not have a specific backend. */
+ for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
+ {
+ struct elf_backend_data *back;
+
+ if ((*target_ptr)->flavour != bfd_target_elf_flavour)
+ continue;
+ back = (struct elf_backend_data *) (*target_ptr)->backend_data;
+ if (back->elf_machine_code == i_ehdrp->e_machine)
+ {
+ /* target_ptr is an ELF backend which matches this
+ object file, so reject the generic ELF target. */
+ goto got_wrong_format_error;
+ }
+ }
+ }
+
+ if (i_ehdrp->e_type == ET_EXEC)
+ abfd->flags |= EXEC_P;
+ else if (i_ehdrp->e_type == ET_DYN)
+ abfd->flags |= DYNAMIC;
+
+ if (i_ehdrp->e_phnum > 0)
+ abfd->flags |= D_PAGED;
+
+ if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0))
+ goto got_no_match;
+
+ /* Remember the entry point specified in the ELF file header. */
+ bfd_get_start_address (abfd) = i_ehdrp->e_entry;
+
+ /* Allocate space for a copy of the section header table in
+ internal form, seek to the section header table in the file,
+ read it in, and convert it to internal form. */
+ i_shdrp = ((Elf_Internal_Shdr *)
+ bfd_alloc (abfd, sizeof (*i_shdrp) * i_ehdrp->e_shnum));
+ elf_elfsections (abfd) = ((Elf_Internal_Shdr **)
+ bfd_alloc (abfd,
+ sizeof (i_shdrp) * i_ehdrp->e_shnum));
+ if (!i_shdrp || !elf_elfsections (abfd))
+ goto got_no_match;
+ if (bfd_seek (abfd, i_ehdrp->e_shoff, SEEK_SET) != 0)
+ goto got_no_match;
+ for (shindex = 0; shindex < i_ehdrp->e_shnum; shindex++)
+ {
+ if (bfd_read ((PTR) & x_shdr, sizeof x_shdr, 1, abfd) != sizeof (x_shdr))
+ goto got_no_match;
+ elf_swap_shdr_in (abfd, &x_shdr, i_shdrp + shindex);
+ elf_elfsections (abfd)[shindex] = i_shdrp + shindex;
+ }
+ if (i_ehdrp->e_shstrndx)
+ {
+ if (! bfd_section_from_shdr (abfd, i_ehdrp->e_shstrndx))
+ goto got_no_match;
+ }
+
+ /* Read in the program headers. */
+ if (i_ehdrp->e_phnum == 0)
+ elf_tdata (abfd)->phdr = NULL;
+ else
+ {
+ Elf_Internal_Phdr *i_phdr;
+ unsigned int i;
+
+ elf_tdata (abfd)->phdr = ((Elf_Internal_Phdr *)
+ bfd_alloc (abfd,
+ (i_ehdrp->e_phnum
+ * sizeof (Elf_Internal_Phdr))));
+ if (elf_tdata (abfd)->phdr == NULL)
+ goto got_no_match;
+ if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) != 0)
+ goto got_no_match;
+ i_phdr = elf_tdata (abfd)->phdr;
+ for (i = 0; i < i_ehdrp->e_phnum; i++, i_phdr++)
+ {
+ Elf_External_Phdr x_phdr;
+
+ if (bfd_read ((PTR) &x_phdr, sizeof x_phdr, 1, abfd)
+ != sizeof x_phdr)
+ goto got_no_match;
+ elf_swap_phdr_in (abfd, &x_phdr, i_phdr);
+ }
+ }
+
+ /* Read in the string table containing the names of the sections. We
+ will need the base pointer to this table later. */
+ /* We read this inline now, so that we don't have to go through
+ bfd_section_from_shdr with it (since this particular strtab is
+ used to find all of the ELF section names.) */
+
+ shstrtab = bfd_elf_get_str_section (abfd, i_ehdrp->e_shstrndx);
+ if (!shstrtab)
+ goto got_no_match;
+
+ /* Once all of the section headers have been read and converted, we
+ can start processing them. Note that the first section header is
+ a dummy placeholder entry, so we ignore it. */
+
+ for (shindex = 1; shindex < i_ehdrp->e_shnum; shindex++)
+ {
+ if (! bfd_section_from_shdr (abfd, shindex))
+ goto got_no_match;
+ }
+
+ /* Let the backend double check the format and override global
+ information. */
+ if (ebd->elf_backend_object_p)
+ {
+ if ((*ebd->elf_backend_object_p) (abfd) == false)
+ goto got_wrong_format_error;
+ }
+
+ return (abfd->xvec);
+
+got_wrong_format_error:
+ bfd_set_error (bfd_error_wrong_format);
+ goto got_no_match;
+got_no_match:
+ if (new_tdata != NULL
+ && new_tdata->elf_sect_ptr != NULL)
+ bfd_release (abfd, new_tdata->elf_sect_ptr);
+ if (i_shdrp != NULL)
+ bfd_release (abfd, i_shdrp);
+ if (new_tdata != NULL)
+ bfd_release (abfd, new_tdata);
+ elf_tdata (abfd) = preserved_tdata;
+ return (NULL);
+}
+
+/* ELF .o/exec file writing */
+
+/* Try to convert a non-ELF reloc into an ELF one. */
+
+static boolean
+validate_reloc (abfd, areloc)
+ bfd *abfd;
+ arelent *areloc;
+{
+ /* Check whether we really have an ELF howto. */
+
+ if ((*areloc->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec)
+ {
+ bfd_reloc_code_real_type code;
+ reloc_howto_type *howto;
+
+ /* Alien reloc: Try to determine its type to replace it with an
+ equivalent ELF reloc. */
+
+ if (areloc->howto->pc_relative)
+ {
+ switch (areloc->howto->bitsize)
+ {
+ case 8:
+ code = BFD_RELOC_8_PCREL;
+ break;
+ case 12:
+ code = BFD_RELOC_12_PCREL;
+ break;
+ case 16:
+ code = BFD_RELOC_16_PCREL;
+ break;
+ case 24:
+ code = BFD_RELOC_24_PCREL;
+ break;
+ case 32:
+ code = BFD_RELOC_32_PCREL;
+ break;
+ case 64:
+ code = BFD_RELOC_64_PCREL;
+ break;
+ default:
+ goto fail;
+ }
+
+ howto = bfd_reloc_type_lookup (abfd, code);
+
+ if (areloc->howto->pcrel_offset != howto->pcrel_offset)
+ {
+ if (howto->pcrel_offset)
+ areloc->addend += areloc->address;
+ else
+ areloc->addend -= areloc->address; /* addend is unsigned!! */
+ }
+ }
+ else
+ {
+ switch (areloc->howto->bitsize)
+ {
+ case 8:
+ code = BFD_RELOC_8;
+ break;
+ case 14:
+ code = BFD_RELOC_14;
+ break;
+ case 16:
+ code = BFD_RELOC_16;
+ break;
+ case 26:
+ code = BFD_RELOC_26;
+ break;
+ case 32:
+ code = BFD_RELOC_32;
+ break;
+ case 64:
+ code = BFD_RELOC_64;
+ break;
+ default:
+ goto fail;
+ }
+
+ howto = bfd_reloc_type_lookup (abfd, code);
+ }
+
+ if (howto)
+ areloc->howto = howto;
+ else
+ goto fail;
+ }
+
+ return true;
+
+ fail:
+ (*_bfd_error_handler)
+ ("%s: unsupported relocation type %s",
+ bfd_get_filename (abfd), areloc->howto->name);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+}
+
+/* Write out the relocs. */
+
+static void
+write_relocs (abfd, sec, data)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+{
+ boolean *failedp = (boolean *) data;
+ Elf_Internal_Shdr *rela_hdr;
+ Elf_External_Rela *outbound_relocas;
+ Elf_External_Rel *outbound_relocs;
+ unsigned int idx;
+ int use_rela_p = get_elf_backend_data (abfd)->use_rela_p;
+ asymbol *last_sym = 0;
+ int last_sym_idx = 0;
+
+ /* If we have already failed, don't do anything. */
+ if (*failedp)
+ return;
+
+ if ((sec->flags & SEC_RELOC) == 0)
+ return;
+
+ /* The linker backend writes the relocs out itself, and sets the
+ reloc_count field to zero to inhibit writing them here. Also,
+ sometimes the SEC_RELOC flag gets set even when there aren't any
+ relocs. */
+ if (sec->reloc_count == 0)
+ return;
+
+ rela_hdr = &elf_section_data (sec)->rel_hdr;
+
+ rela_hdr->sh_size = rela_hdr->sh_entsize * sec->reloc_count;
+ rela_hdr->contents = (PTR) bfd_alloc (abfd, rela_hdr->sh_size);
+ if (rela_hdr->contents == NULL)
+ {
+ *failedp = true;
+ return;
+ }
+
+ /* orelocation has the data, reloc_count has the count... */
+ if (use_rela_p)
+ {
+ outbound_relocas = (Elf_External_Rela *) rela_hdr->contents;
+
+ for (idx = 0; idx < sec->reloc_count; idx++)
+ {
+ Elf_Internal_Rela dst_rela;
+ Elf_External_Rela *src_rela;
+ arelent *ptr;
+ asymbol *sym;
+ int n;
+
+ ptr = sec->orelocation[idx];
+ src_rela = outbound_relocas + idx;
+
+ /* The address of an ELF reloc is section relative for an object
+ file, and absolute for an executable file or shared library.
+ The address of a BFD reloc is always section relative. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ dst_rela.r_offset = ptr->address;
+ else
+ dst_rela.r_offset = ptr->address + sec->vma;
+
+ sym = *ptr->sym_ptr_ptr;
+ if (sym == last_sym)
+ n = last_sym_idx;
+ else
+ {
+ last_sym = sym;
+ n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+ if (n < 0)
+ {
+ *failedp = true;
+ return;
+ }
+ last_sym_idx = n;
+ }
+
+ if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+ && ! validate_reloc (abfd, ptr))
+ {
+ *failedp = true;
+ return;
+ }
+
+ dst_rela.r_info = ELF_R_INFO (n, ptr->howto->type);
+
+ dst_rela.r_addend = ptr->addend;
+ elf_swap_reloca_out (abfd, &dst_rela, src_rela);
+ }
+ }
+ else
+ /* REL relocations */
+ {
+ outbound_relocs = (Elf_External_Rel *) rela_hdr->contents;
+
+ for (idx = 0; idx < sec->reloc_count; idx++)
+ {
+ Elf_Internal_Rel dst_rel;
+ Elf_External_Rel *src_rel;
+ arelent *ptr;
+ int n;
+ asymbol *sym;
+
+ ptr = sec->orelocation[idx];
+ sym = *ptr->sym_ptr_ptr;
+ src_rel = outbound_relocs + idx;
+
+ /* The address of an ELF reloc is section relative for an object
+ file, and absolute for an executable file or shared library.
+ The address of a BFD reloc is always section relative. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ dst_rel.r_offset = ptr->address;
+ else
+ dst_rel.r_offset = ptr->address + sec->vma;
+
+ if (sym == last_sym)
+ n = last_sym_idx;
+ else
+ {
+ last_sym = sym;
+ n = _bfd_elf_symbol_from_bfd_symbol (abfd, &sym);
+ if (n < 0)
+ {
+ *failedp = true;
+ return;
+ }
+ last_sym_idx = n;
+ }
+
+ if ((*ptr->sym_ptr_ptr)->the_bfd->xvec != abfd->xvec
+ && ! validate_reloc (abfd, ptr))
+ {
+ *failedp = true;
+ return;
+ }
+
+ dst_rel.r_info = ELF_R_INFO (n, ptr->howto->type);
+
+ elf_swap_reloc_out (abfd, &dst_rel, src_rel);
+ }
+ }
+}
+
+static int
+write_out_phdrs (abfd, phdr, count)
+ bfd *abfd;
+ Elf_Internal_Phdr *phdr;
+ int count;
+{
+ while (count--)
+ {
+ Elf_External_Phdr extphdr;
+ elf_swap_phdr_out (abfd, phdr, &extphdr);
+ if (bfd_write (&extphdr, sizeof (Elf_External_Phdr), 1, abfd)
+ != sizeof (Elf_External_Phdr))
+ return -1;
+ phdr++;
+ }
+ return 0;
+}
+
+static boolean
+write_shdrs_and_ehdr (abfd)
+ bfd *abfd;
+{
+ Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
+ Elf_External_Shdr *x_shdrp; /* Section header table, external form */
+ Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
+ unsigned int count;
+
+ i_ehdrp = elf_elfheader (abfd);
+ i_shdrp = elf_elfsections (abfd);
+
+ /* swap the header before spitting it out... */
+
+#if DEBUG & 1
+ elf_debug_file (i_ehdrp);
+#endif
+ elf_swap_ehdr_out (abfd, i_ehdrp, &x_ehdr);
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || (bfd_write ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd)
+ != sizeof (x_ehdr)))
+ return false;
+
+ /* at this point we've concocted all the ELF sections... */
+ x_shdrp = (Elf_External_Shdr *)
+ bfd_alloc (abfd, sizeof (*x_shdrp) * (i_ehdrp->e_shnum));
+ if (!x_shdrp)
+ return false;
+
+ for (count = 0; count < i_ehdrp->e_shnum; count++)
+ {
+#if DEBUG & 2
+ elf_debug_section (count, i_shdrp[count]);
+#endif
+ elf_swap_shdr_out (abfd, i_shdrp[count], x_shdrp + count);
+ }
+ if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_shoff, SEEK_SET) != 0
+ || (bfd_write ((PTR) x_shdrp, sizeof (*x_shdrp), i_ehdrp->e_shnum, abfd)
+ != sizeof (*x_shdrp) * i_ehdrp->e_shnum))
+ return false;
+
+ /* need to dump the string table too... */
+
+ return true;
+}
+
+static long
+elf_slurp_symbol_table (abfd, symptrs, dynamic)
+ bfd *abfd;
+ asymbol **symptrs; /* Buffer for generated bfd symbols */
+ boolean dynamic;
+{
+ Elf_Internal_Shdr *hdr;
+ long symcount; /* Number of external ELF symbols */
+ elf_symbol_type *sym; /* Pointer to current bfd symbol */
+ elf_symbol_type *symbase; /* Buffer for generated bfd symbols */
+ Elf_Internal_Sym i_sym;
+ Elf_External_Sym *x_symp = NULL;
+
+ /* Read each raw ELF symbol, converting from external ELF form to
+ internal ELF form, and then using the information to create a
+ canonical bfd symbol table entry.
+
+ Note that we allocate the initial bfd canonical symbol buffer
+ based on a one-to-one mapping of the ELF symbols to canonical
+ symbols. We actually use all the ELF symbols, so there will be no
+ space left over at the end. When we have all the symbols, we
+ build the caller's pointer vector. */
+
+ if (dynamic)
+ hdr = &elf_tdata (abfd)->dynsymtab_hdr;
+ else
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
+ return -1;
+
+ symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+
+ if (symcount == 0)
+ sym = symbase = NULL;
+ else
+ {
+ long i;
+
+ if (bfd_seek (abfd, hdr->sh_offset, SEEK_SET) == -1)
+ return -1;
+
+ symbase = ((elf_symbol_type *)
+ bfd_zalloc (abfd, symcount * sizeof (elf_symbol_type)));
+ if (symbase == (elf_symbol_type *) NULL)
+ return -1;
+ sym = symbase;
+
+ /* Temporarily allocate room for the raw ELF symbols. */
+ x_symp = ((Elf_External_Sym *)
+ bfd_malloc (symcount * sizeof (Elf_External_Sym)));
+ if (x_symp == NULL && symcount != 0)
+ goto error_return;
+
+ if (bfd_read ((PTR) x_symp, sizeof (Elf_External_Sym), symcount, abfd)
+ != symcount * sizeof (Elf_External_Sym))
+ goto error_return;
+ /* Skip first symbol, which is a null dummy. */
+ for (i = 1; i < symcount; i++)
+ {
+ elf_swap_symbol_in (abfd, x_symp + i, &i_sym);
+ memcpy (&sym->internal_elf_sym, &i_sym, sizeof (Elf_Internal_Sym));
+#ifdef ELF_KEEP_EXTSYM
+ memcpy (&sym->native_elf_sym, x_symp + i, sizeof (Elf_External_Sym));
+#endif
+ sym->symbol.the_bfd = abfd;
+
+ sym->symbol.name = bfd_elf_string_from_elf_section (abfd,
+ hdr->sh_link,
+ i_sym.st_name);
+
+ sym->symbol.value = i_sym.st_value;
+
+ if (i_sym.st_shndx > 0 && i_sym.st_shndx < SHN_LORESERVE)
+ {
+ sym->symbol.section = section_from_elf_index (abfd,
+ i_sym.st_shndx);
+ if (sym->symbol.section == NULL)
+ {
+ /* This symbol is in a section for which we did not
+ create a BFD section. Just use bfd_abs_section,
+ although it is wrong. FIXME. */
+ sym->symbol.section = bfd_abs_section_ptr;
+ }
+ }
+ else if (i_sym.st_shndx == SHN_ABS)
+ {
+ sym->symbol.section = bfd_abs_section_ptr;
+ }
+ else if (i_sym.st_shndx == SHN_COMMON)
+ {
+ sym->symbol.section = bfd_com_section_ptr;
+ /* Elf puts the alignment into the `value' field, and
+ the size into the `size' field. BFD wants to see the
+ size in the value field, and doesn't care (at the
+ moment) about the alignment. */
+ sym->symbol.value = i_sym.st_size;
+ }
+ else if (i_sym.st_shndx == SHN_UNDEF)
+ {
+ sym->symbol.section = bfd_und_section_ptr;
+ }
+ else
+ sym->symbol.section = bfd_abs_section_ptr;
+
+ sym->symbol.value -= sym->symbol.section->vma;
+
+ switch (ELF_ST_BIND (i_sym.st_info))
+ {
+ case STB_LOCAL:
+ sym->symbol.flags |= BSF_LOCAL;
+ break;
+ case STB_GLOBAL:
+ if (i_sym.st_shndx != SHN_UNDEF
+ && i_sym.st_shndx != SHN_COMMON)
+ sym->symbol.flags |= BSF_GLOBAL;
+ break;
+ case STB_WEAK:
+ sym->symbol.flags |= BSF_WEAK;
+ break;
+ }
+
+ switch (ELF_ST_TYPE (i_sym.st_info))
+ {
+ case STT_SECTION:
+ sym->symbol.flags |= BSF_SECTION_SYM | BSF_DEBUGGING;
+ break;
+ case STT_FILE:
+ sym->symbol.flags |= BSF_FILE | BSF_DEBUGGING;
+ break;
+ case STT_FUNC:
+ sym->symbol.flags |= BSF_FUNCTION;
+ break;
+ case STT_OBJECT:
+ sym->symbol.flags |= BSF_OBJECT;
+ break;
+ }
+
+ if (dynamic)
+ sym->symbol.flags |= BSF_DYNAMIC;
+
+ /* Do some backend-specific processing on this symbol. */
+ {
+ struct elf_backend_data *ebd = get_elf_backend_data (abfd);
+ if (ebd->elf_backend_symbol_processing)
+ (*ebd->elf_backend_symbol_processing) (abfd, &sym->symbol);
+ }
+
+ sym++;
+ }
+ }
+
+ /* Do some backend-specific processing on this symbol table. */
+ {
+ struct elf_backend_data *ebd = get_elf_backend_data (abfd);
+ if (ebd->elf_backend_symbol_table_processing)
+ (*ebd->elf_backend_symbol_table_processing) (abfd, symbase, symcount);
+ }
+
+ /* We rely on the zalloc to clear out the final symbol entry. */
+
+ symcount = sym - symbase;
+
+ /* Fill in the user's symbol pointer vector if needed. */
+ if (symptrs)
+ {
+ long l = symcount;
+
+ sym = symbase;
+ while (l-- > 0)
+ {
+ *symptrs++ = &sym->symbol;
+ sym++;
+ }
+ *symptrs = 0; /* Final null pointer */
+ }
+
+ if (x_symp != NULL)
+ free (x_symp);
+ return symcount;
+error_return:
+ if (x_symp != NULL)
+ free (x_symp);
+ return -1;
+}
+
+/* Read in and swap the external relocs. */
+
+static boolean
+elf_slurp_reloc_table (abfd, asect, symbols)
+ bfd *abfd;
+ asection *asect;
+ asymbol **symbols;
+{
+ struct elf_backend_data * const ebd = get_elf_backend_data (abfd);
+ struct bfd_elf_section_data * const d = elf_section_data (asect);
+ PTR allocated = NULL;
+ bfd_byte *native_relocs;
+ arelent *relents;
+ arelent *relent;
+ unsigned int i;
+ int entsize;
+
+ if (asect->relocation != NULL
+ || (asect->flags & SEC_RELOC) == 0
+ || asect->reloc_count == 0)
+ return true;
+
+ BFD_ASSERT (asect->rel_filepos == d->rel_hdr.sh_offset
+ && (asect->reloc_count
+ == d->rel_hdr.sh_size / d->rel_hdr.sh_entsize));
+
+ allocated = (PTR) bfd_malloc ((size_t) d->rel_hdr.sh_size);
+ if (allocated == NULL)
+ goto error_return;
+
+ if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0
+ || (bfd_read (allocated, 1, d->rel_hdr.sh_size, abfd)
+ != d->rel_hdr.sh_size))
+ goto error_return;
+
+ native_relocs = (bfd_byte *) allocated;
+
+ relents = ((arelent *)
+ bfd_alloc (abfd, asect->reloc_count * sizeof (arelent)));
+ if (relents == NULL)
+ goto error_return;
+
+ entsize = d->rel_hdr.sh_entsize;
+ BFD_ASSERT (entsize == sizeof (Elf_External_Rel)
+ || entsize == sizeof (Elf_External_Rela));
+
+ for (i = 0, relent = relents;
+ i < asect->reloc_count;
+ i++, relent++, native_relocs += entsize)
+ {
+ Elf_Internal_Rela rela;
+ Elf_Internal_Rel rel;
+
+ if (entsize == sizeof (Elf_External_Rela))
+ elf_swap_reloca_in (abfd, (Elf_External_Rela *) native_relocs, &rela);
+ else
+ {
+ elf_swap_reloc_in (abfd, (Elf_External_Rel *) native_relocs, &rel);
+ rela.r_offset = rel.r_offset;
+ rela.r_info = rel.r_info;
+ rela.r_addend = 0;
+ }
+
+ /* The address of an ELF reloc is section relative for an object
+ file, and absolute for an executable file or shared library.
+ The address of a BFD reloc is always section relative. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
+ relent->address = rela.r_offset;
+ else
+ relent->address = rela.r_offset - asect->vma;
+
+ if (ELF_R_SYM (rela.r_info) == 0)
+ relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ else
+ {
+ asymbol **ps, *s;
+
+ ps = symbols + ELF_R_SYM (rela.r_info) - 1;
+ s = *ps;
+
+ /* Canonicalize ELF section symbols. FIXME: Why? */
+ if ((s->flags & BSF_SECTION_SYM) == 0)
+ relent->sym_ptr_ptr = ps;
+ else
+ relent->sym_ptr_ptr = s->section->symbol_ptr_ptr;
+ }
+
+ relent->addend = rela.r_addend;
+
+ if (entsize == sizeof (Elf_External_Rela))
+ (*ebd->elf_info_to_howto) (abfd, relent, &rela);
+ else
+ (*ebd->elf_info_to_howto_rel) (abfd, relent, &rel);
+ }
+
+ asect->relocation = relents;
+
+ if (allocated != NULL)
+ free (allocated);
+
+ return true;
+
+ error_return:
+ if (allocated != NULL)
+ free (allocated);
+ return false;
+}
+
+#ifdef DEBUG
+static void
+elf_debug_section (num, hdr)
+ int num;
+ Elf_Internal_Shdr *hdr;
+{
+ fprintf (stderr, "\nSection#%d '%s' 0x%.8lx\n", num,
+ hdr->bfd_section != NULL ? hdr->bfd_section->name : "",
+ (long) hdr);
+ fprintf (stderr,
+ "sh_name = %ld\tsh_type = %ld\tsh_flags = %ld\n",
+ (long) hdr->sh_name,
+ (long) hdr->sh_type,
+ (long) hdr->sh_flags);
+ fprintf (stderr,
+ "sh_addr = %ld\tsh_offset = %ld\tsh_size = %ld\n",
+ (long) hdr->sh_addr,
+ (long) hdr->sh_offset,
+ (long) hdr->sh_size);
+ fprintf (stderr,
+ "sh_link = %ld\tsh_info = %ld\tsh_addralign = %ld\n",
+ (long) hdr->sh_link,
+ (long) hdr->sh_info,
+ (long) hdr->sh_addralign);
+ fprintf (stderr, "sh_entsize = %ld\n",
+ (long) hdr->sh_entsize);
+ fflush (stderr);
+}
+
+static void
+elf_debug_file (ehdrp)
+ Elf_Internal_Ehdr *ehdrp;
+{
+ fprintf (stderr, "e_entry = 0x%.8lx\n", (long) ehdrp->e_entry);
+ fprintf (stderr, "e_phoff = %ld\n", (long) ehdrp->e_phoff);
+ fprintf (stderr, "e_phnum = %ld\n", (long) ehdrp->e_phnum);
+ fprintf (stderr, "e_phentsize = %ld\n", (long) ehdrp->e_phentsize);
+ fprintf (stderr, "e_shoff = %ld\n", (long) ehdrp->e_shoff);
+ fprintf (stderr, "e_shnum = %ld\n", (long) ehdrp->e_shnum);
+ fprintf (stderr, "e_shentsize = %ld\n", (long) ehdrp->e_shentsize);
+}
+
+static char *
+elf_symbol_flags (flags)
+ flagword flags;
+{
+ static char buffer[1024];
+
+ buffer[0] = '\0';
+ if (flags & BSF_LOCAL)
+ strcat (buffer, " local");
+
+ if (flags & BSF_GLOBAL)
+ strcat (buffer, " global");
+
+ if (flags & BSF_DEBUGGING)
+ strcat (buffer, " debug");
+
+ if (flags & BSF_FUNCTION)
+ strcat (buffer, " function");
+
+ if (flags & BSF_KEEP)
+ strcat (buffer, " keep");
+
+ if (flags & BSF_KEEP_G)
+ strcat (buffer, " keep_g");
+
+ if (flags & BSF_WEAK)
+ strcat (buffer, " weak");
+
+ if (flags & BSF_SECTION_SYM)
+ strcat (buffer, " section-sym");
+
+ if (flags & BSF_OLD_COMMON)
+ strcat (buffer, " old-common");
+
+ if (flags & BSF_NOT_AT_END)
+ strcat (buffer, " not-at-end");
+
+ if (flags & BSF_CONSTRUCTOR)
+ strcat (buffer, " constructor");
+
+ if (flags & BSF_WARNING)
+ strcat (buffer, " warning");
+
+ if (flags & BSF_INDIRECT)
+ strcat (buffer, " indirect");
+
+ if (flags & BSF_FILE)
+ strcat (buffer, " file");
+
+ if (flags & DYNAMIC)
+ strcat (buffer, " dynamic");
+
+ if (flags & ~(BSF_LOCAL
+ | BSF_GLOBAL
+ | BSF_DEBUGGING
+ | BSF_FUNCTION
+ | BSF_KEEP
+ | BSF_KEEP_G
+ | BSF_WEAK
+ | BSF_SECTION_SYM
+ | BSF_OLD_COMMON
+ | BSF_NOT_AT_END
+ | BSF_CONSTRUCTOR
+ | BSF_WARNING
+ | BSF_INDIRECT
+ | BSF_FILE
+ | BSF_DYNAMIC))
+ strcat (buffer, " unknown-bits");
+
+ return buffer;
+}
+#endif
+
+#include "elfcore.h"
+#include "elflink.h"
+
+/* Size-dependent data and functions. */
+const struct elf_size_info NAME(_bfd_elf,size_info) = {
+ sizeof (Elf_External_Ehdr),
+ sizeof (Elf_External_Phdr),
+ sizeof (Elf_External_Shdr),
+ sizeof (Elf_External_Rel),
+ sizeof (Elf_External_Rela),
+ sizeof (Elf_External_Sym),
+ sizeof (Elf_External_Dyn),
+ sizeof (Elf_External_Note),
+
+ ARCH_SIZE, FILE_ALIGN,
+ ELFCLASS, EV_CURRENT,
+ write_out_phdrs,
+ write_shdrs_and_ehdr,
+ write_relocs,
+ elf_swap_symbol_out,
+ elf_slurp_reloc_table,
+ elf_slurp_symbol_table,
+ elf_swap_dyn_in
+};
diff --git a/contrib/gdb/bfd/elfcore.h b/contrib/gdb/bfd/elfcore.h
new file mode 100644
index 0000000..8100627
--- /dev/null
+++ b/contrib/gdb/bfd/elfcore.h
@@ -0,0 +1,475 @@
+/* ELF core file support for BFD.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+/* Core file support */
+
+#ifdef HAVE_SYS_PROCFS_H /* Some core file support requires host /proc files */
+#include <signal.h>
+#include <sys/procfs.h>
+#else
+#define bfd_prstatus(abfd, descdata, descsz, filepos) true
+#define bfd_fpregset(abfd, descdata, descsz, filepos) true
+#define bfd_prpsinfo(abfd, descdata, descsz, filepos) true
+#endif
+
+#ifdef HAVE_SYS_PROCFS_H
+
+static boolean
+bfd_prstatus (abfd, descdata, descsz, filepos)
+ bfd *abfd;
+ char *descdata;
+ int descsz;
+ long filepos;
+{
+ asection *newsect;
+ prstatus_t *status = (prstatus_t *) 0;
+
+ if (descsz == sizeof (prstatus_t))
+ {
+ newsect = bfd_make_section (abfd, ".reg");
+ if (newsect == NULL)
+ return false;
+ newsect->_raw_size = sizeof (status->pr_reg);
+ newsect->filepos = filepos + (long) &status->pr_reg;
+ newsect->flags = SEC_HAS_CONTENTS;
+ newsect->alignment_power = 2;
+ if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL)
+ {
+ memcpy (core_prstatus (abfd), descdata, descsz);
+ }
+ }
+ return true;
+}
+
+/* Stash a copy of the prpsinfo structure away for future use. */
+
+static boolean
+bfd_prpsinfo (abfd, descdata, descsz, filepos)
+ bfd *abfd;
+ char *descdata;
+ int descsz;
+ long filepos;
+{
+ if (descsz == sizeof (prpsinfo_t))
+ {
+ if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) == NULL)
+ return false;
+ memcpy (core_prpsinfo (abfd), descdata, descsz);
+ }
+ return true;
+}
+
+static boolean
+bfd_fpregset (abfd, descdata, descsz, filepos)
+ bfd *abfd;
+ char *descdata;
+ int descsz;
+ long filepos;
+{
+ asection *newsect;
+
+ newsect = bfd_make_section (abfd, ".reg2");
+ if (newsect == NULL)
+ return false;
+ newsect->_raw_size = descsz;
+ newsect->filepos = filepos;
+ newsect->flags = SEC_HAS_CONTENTS;
+ newsect->alignment_power = 2;
+ return true;
+}
+
+#endif /* HAVE_SYS_PROCFS_H */
+
+/* Return a pointer to the args (including the command name) that were
+ seen by the program that generated the core dump. Note that for
+ some reason, a spurious space is tacked onto the end of the args
+ in some (at least one anyway) implementations, so strip it off if
+ it exists. */
+
+char *
+elf_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+#ifdef HAVE_SYS_PROCFS_H
+ if (core_prpsinfo (abfd))
+ {
+ prpsinfo_t *p = core_prpsinfo (abfd);
+ char *scan = p->pr_psargs;
+ while (*scan++)
+ {;
+ }
+ scan -= 2;
+ if ((scan > p->pr_psargs) && (*scan == ' '))
+ {
+ *scan = '\000';
+ }
+ return p->pr_psargs;
+ }
+#endif
+ return NULL;
+}
+
+/* Return the number of the signal that caused the core dump. Presumably,
+ since we have a core file, we got a signal of some kind, so don't bother
+ checking the other process status fields, just return the signal number.
+ */
+
+int
+elf_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+#ifdef HAVE_SYS_PROCFS_H
+ if (core_prstatus (abfd))
+ {
+ return ((prstatus_t *) (core_prstatus (abfd)))->pr_cursig;
+ }
+#endif
+ return -1;
+}
+
+/* Check to see if the core file could reasonably be expected to have
+ come for the current executable file. Note that by default we return
+ true unless we find something that indicates that there might be a
+ problem.
+ */
+
+boolean
+elf_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd;
+ bfd *exec_bfd;
+{
+#ifdef HAVE_SYS_PROCFS_H
+ char *corename;
+ char *execname;
+#endif
+
+ /* First, xvecs must match since both are ELF files for the same target. */
+
+ if (core_bfd->xvec != exec_bfd->xvec)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return false;
+ }
+
+#ifdef HAVE_SYS_PROCFS_H
+
+ /* If no prpsinfo, just return true. Otherwise, grab the last component
+ of the exec'd pathname from the prpsinfo. */
+
+ if (core_prpsinfo (core_bfd))
+ {
+ corename = (((prpsinfo_t *) core_prpsinfo (core_bfd))->pr_fname);
+ }
+ else
+ {
+ return true;
+ }
+
+ /* Find the last component of the executable pathname. */
+
+ if ((execname = strrchr (exec_bfd->filename, '/')) != NULL)
+ {
+ execname++;
+ }
+ else
+ {
+ execname = (char *) exec_bfd->filename;
+ }
+
+ /* See if they match */
+
+ return strcmp (execname, corename) ? false : true;
+
+#else
+
+ return true;
+
+#endif /* HAVE_SYS_PROCFS_H */
+}
+
+/* ELF core files contain a segment of type PT_NOTE, that holds much of
+ the information that would normally be available from the /proc interface
+ for the process, at the time the process dumped core. Currently this
+ includes copies of the prstatus, prpsinfo, and fpregset structures.
+
+ Since these structures are potentially machine dependent in size and
+ ordering, bfd provides two levels of support for them. The first level,
+ available on all machines since it does not require that the host
+ have /proc support or the relevant include files, is to create a bfd
+ section for each of the prstatus, prpsinfo, and fpregset structures,
+ without any interpretation of their contents. With just this support,
+ the bfd client will have to interpret the structures itself. Even with
+ /proc support, it might want these full structures for it's own reasons.
+
+ In the second level of support, where HAVE_SYS_PROCFS_H is defined,
+ bfd will pick apart the structures to gather some additional
+ information that clients may want, such as the general register
+ set, the name of the exec'ed file and its arguments, the signal (if
+ any) that caused the core dump, etc.
+
+ */
+
+static boolean
+elf_corefile_note (abfd, hdr)
+ bfd *abfd;
+ Elf_Internal_Phdr *hdr;
+{
+ Elf_External_Note *x_note_p; /* Elf note, external form */
+ Elf_Internal_Note i_note; /* Elf note, internal form */
+ char *buf = NULL; /* Entire note segment contents */
+ char *namedata; /* Name portion of the note */
+ char *descdata; /* Descriptor portion of the note */
+ char *sectname; /* Name to use for new section */
+ long filepos; /* File offset to descriptor data */
+ asection *newsect;
+
+ if (hdr->p_filesz > 0
+ && (buf = (char *) bfd_malloc ((size_t) hdr->p_filesz)) != NULL
+ && bfd_seek (abfd, hdr->p_offset, SEEK_SET) != -1
+ && bfd_read ((PTR) buf, hdr->p_filesz, 1, abfd) == hdr->p_filesz)
+ {
+ x_note_p = (Elf_External_Note *) buf;
+ while ((char *) x_note_p < (buf + hdr->p_filesz))
+ {
+ i_note.namesz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->namesz);
+ i_note.descsz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->descsz);
+ i_note.type = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->type);
+ namedata = x_note_p->name;
+ descdata = namedata + BFD_ALIGN (i_note.namesz, 4);
+ filepos = hdr->p_offset + (descdata - buf);
+ switch (i_note.type)
+ {
+ case NT_PRSTATUS:
+ /* process descdata as prstatus info */
+ if (! bfd_prstatus (abfd, descdata, i_note.descsz, filepos))
+ return false;
+ sectname = ".prstatus";
+ break;
+ case NT_FPREGSET:
+ /* process descdata as fpregset info */
+ if (! bfd_fpregset (abfd, descdata, i_note.descsz, filepos))
+ return false;
+ sectname = ".fpregset";
+ break;
+ case NT_PRPSINFO:
+ /* process descdata as prpsinfo */
+ if (! bfd_prpsinfo (abfd, descdata, i_note.descsz, filepos))
+ return false;
+ sectname = ".prpsinfo";
+ break;
+ default:
+ /* Unknown descriptor, just ignore it. */
+ sectname = NULL;
+ break;
+ }
+ if (sectname != NULL)
+ {
+ newsect = bfd_make_section (abfd, sectname);
+ if (newsect == NULL)
+ return false;
+ newsect->_raw_size = i_note.descsz;
+ newsect->filepos = filepos;
+ newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS;
+ newsect->alignment_power = 2;
+ }
+ x_note_p = (Elf_External_Note *)
+ (descdata + BFD_ALIGN (i_note.descsz, 4));
+ }
+ }
+ if (buf != NULL)
+ {
+ free (buf);
+ }
+ else if (hdr->p_filesz > 0)
+ {
+ return false;
+ }
+ return true;
+
+}
+
+/* Core files are simply standard ELF formatted files that partition
+ the file using the execution view of the file (program header table)
+ rather than the linking view. In fact, there is no section header
+ table in a core file.
+
+ The process status information (including the contents of the general
+ register set) and the floating point register set are stored in a
+ segment of type PT_NOTE. We handcraft a couple of extra bfd sections
+ that allow standard bfd access to the general registers (.reg) and the
+ floating point registers (.reg2).
+
+ */
+
+const bfd_target *
+elf_core_file_p (abfd)
+ bfd *abfd;
+{
+ Elf_External_Ehdr x_ehdr; /* Elf file header, external form */
+ Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */
+ Elf_External_Phdr x_phdr; /* Program header table entry, external form */
+ Elf_Internal_Phdr *i_phdrp; /* Program header table, internal form */
+ unsigned int phindex;
+ struct elf_backend_data *ebd;
+
+ /* Read in the ELF header in external format. */
+
+ if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* Now check to see if we have a valid ELF file, and one that BFD can
+ make use of. The magic number must match, the address size ('class')
+ and byte-swapping must match our XVEC entry, and it must have a
+ program header table (FIXME: See comments re segments at top of this
+ file). */
+
+ if (elf_file_p (&x_ehdr) == false)
+ {
+ wrong:
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* FIXME, Check EI_VERSION here ! */
+
+ {
+#if ARCH_SIZE == 32
+ int desired_address_size = ELFCLASS32;
+#endif
+#if ARCH_SIZE == 64
+ int desired_address_size = ELFCLASS64;
+#endif
+
+ if (x_ehdr.e_ident[EI_CLASS] != desired_address_size)
+ goto wrong;
+ }
+
+ /* Switch xvec to match the specified byte order. */
+ switch (x_ehdr.e_ident[EI_DATA])
+ {
+ case ELFDATA2MSB: /* Big-endian */
+ if (! bfd_big_endian (abfd))
+ goto wrong;
+ break;
+ case ELFDATA2LSB: /* Little-endian */
+ if (! bfd_little_endian (abfd))
+ goto wrong;
+ break;
+ case ELFDATANONE: /* No data encoding specified */
+ default: /* Unknown data encoding specified */
+ goto wrong;
+ }
+
+ /* Allocate an instance of the elf_obj_tdata structure and hook it up to
+ the tdata pointer in the bfd. */
+
+ elf_tdata (abfd) =
+ (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
+ if (elf_tdata (abfd) == NULL)
+ return NULL;
+
+ /* FIXME, `wrong' returns from this point onward, leak memory. */
+
+ /* Now that we know the byte order, swap in the rest of the header */
+ i_ehdrp = elf_elfheader (abfd);
+ elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
+#if DEBUG & 1
+ elf_debug_file (i_ehdrp);
+#endif
+
+ ebd = get_elf_backend_data (abfd);
+
+ /* Check that the ELF e_machine field matches what this particular
+ BFD format expects. */
+ if (ebd->elf_machine_code != i_ehdrp->e_machine
+ && (ebd->elf_machine_alt1 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt1)
+ && (ebd->elf_machine_alt2 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt2))
+ {
+ const bfd_target * const *target_ptr;
+
+ if (ebd->elf_machine_code != EM_NONE)
+ goto wrong;
+
+ /* This is the generic ELF target. Let it match any ELF target
+ for which we do not have a specific backend. */
+ for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
+ {
+ struct elf_backend_data *back;
+
+ if ((*target_ptr)->flavour != bfd_target_elf_flavour)
+ continue;
+ back = (struct elf_backend_data *) (*target_ptr)->backend_data;
+ if (back->elf_machine_code == i_ehdrp->e_machine)
+ {
+ /* target_ptr is an ELF backend which matches this
+ object file, so reject the generic ELF target. */
+ goto wrong;
+ }
+ }
+ }
+
+ /* If there is no program header, or the type is not a core file, then
+ we are hosed. */
+ if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE)
+ goto wrong;
+
+ /* Allocate space for a copy of the program header table in
+ internal form, seek to the program header table in the file,
+ read it in, and convert it to internal form. As a simple sanity
+ check, verify that the what BFD thinks is the size of each program
+ header table entry actually matches the size recorded in the file. */
+
+ if (i_ehdrp->e_phentsize != sizeof (x_phdr))
+ goto wrong;
+ i_phdrp = (Elf_Internal_Phdr *)
+ bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdrp->e_phnum);
+ if (!i_phdrp)
+ return NULL;
+ if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1)
+ return NULL;
+ for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
+ {
+ if (bfd_read ((PTR) & x_phdr, sizeof (x_phdr), 1, abfd)
+ != sizeof (x_phdr))
+ return NULL;
+ elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex);
+ }
+
+ /* Once all of the program headers have been read and converted, we
+ can start processing them. */
+
+ for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
+ {
+ bfd_section_from_phdr (abfd, i_phdrp + phindex, phindex);
+ if ((i_phdrp + phindex)->p_type == PT_NOTE)
+ {
+ if (! elf_corefile_note (abfd, i_phdrp + phindex))
+ return NULL;
+ }
+ }
+
+ /* Remember the entry point specified in the ELF file header. */
+
+ bfd_get_start_address (abfd) = i_ehdrp->e_entry;
+
+ return abfd->xvec;
+}
diff --git a/contrib/gdb/bfd/elflink.c b/contrib/gdb/bfd/elflink.c
new file mode 100644
index 0000000..7b204f7
--- /dev/null
+++ b/contrib/gdb/bfd/elflink.c
@@ -0,0 +1,372 @@
+/* ELF linking support for BFD.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#define ARCH_SIZE 0
+#include "elf-bfd.h"
+
+boolean
+_bfd_elf_create_got_section (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+ struct elf_link_hash_entry *h;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ /* This function may be called more than once. */
+ if (bfd_get_section_by_name (abfd, ".got") != NULL)
+ return true;
+
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ s = bfd_make_section (abfd, ".got");
+ if (s == NULL
+ || !bfd_set_section_flags (abfd, s, flags)
+ || !bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ if (bed->want_got_plt)
+ {
+ s = bfd_make_section (abfd, ".got.plt");
+ if (s == NULL
+ || !bfd_set_section_flags (abfd, s, flags)
+ || !bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ }
+
+ /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
+ (or .got.plt) section. We don't do this in the linker script
+ because we don't want to define the symbol if we are not creating
+ a global offset table. */
+ h = NULL;
+ if (!(_bfd_generic_link_add_one_symbol
+ (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, (bfd_vma) 0,
+ (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+ if (info->shared
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
+
+ /* The first three global offset table entries are reserved. */
+ s->_raw_size += 3 * 4;
+
+ return true;
+}
+
+
+/* Create dynamic sections when linking against a dynamic object. */
+
+boolean
+_bfd_elf_create_dynamic_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+ .rel[a].bss sections. */
+
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ s = bfd_make_section (abfd, ".plt");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s,
+ (flags | SEC_CODE
+ | (bed->plt_readonly ? SEC_READONLY : 0)))
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ if (bed->want_plt_sym)
+ {
+ /* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
+ .plt section. */
+ struct elf_link_hash_entry *h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
+ (bfd_vma) 0, (const char *) NULL, false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+ if (info->shared
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ s = bfd_make_section (abfd, bed->use_rela_p ? ".rela.plt" : ".rel.plt");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ if (! _bfd_elf_create_got_section (abfd, info))
+ return false;
+
+ /* The .dynbss section is a place to put symbols which are defined
+ by dynamic objects, are referenced by regular objects, and are
+ not functions. We must allocate space for them in the process
+ image and use a R_*_COPY reloc to tell the dynamic linker to
+ initialize them at run time. The linker script puts the .dynbss
+ section into the .bss section of the final image. */
+ s = bfd_make_section (abfd, ".dynbss");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, SEC_ALLOC))
+ return false;
+
+ /* The .rel[a].bss section holds copy relocs. This section is not
+ normally needed. We need to create it here, though, so that the
+ linker will map it to an output section. We can't just create it
+ only if we need it, because we will not know whether we need it
+ until we have seen all the input files, and the first time the
+ main linker code calls BFD after examining all the input files
+ (size_dynamic_sections) the input sections have already been
+ mapped to the output sections. If the section turns out not to
+ be needed, we can discard it later. We will never need this
+ section when generating a shared object, since they do not use
+ copy relocs. */
+ if (! info->shared)
+ {
+ s = bfd_make_section (abfd, bed->use_rela_p ? ".rela.bss" : ".rel.bss");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Record a new dynamic symbol. We record the dynamic symbols as we
+ read the input files, since we need to have a list of all of them
+ before we can determine the final sizes of the output sections.
+ Note that we may actually call this function even though we are not
+ going to output any dynamic symbols; in some cases we know that a
+ symbol should be in the dynamic symbol table, but only if there is
+ one. */
+
+boolean
+_bfd_elf_link_record_dynamic_symbol (info, h)
+ struct bfd_link_info *info;
+ struct elf_link_hash_entry *h;
+{
+ if (h->dynindx == -1)
+ {
+ struct bfd_strtab_hash *dynstr;
+
+ h->dynindx = elf_hash_table (info)->dynsymcount;
+ ++elf_hash_table (info)->dynsymcount;
+
+ dynstr = elf_hash_table (info)->dynstr;
+ if (dynstr == NULL)
+ {
+ /* Create a strtab to hold the dynamic symbol names. */
+ elf_hash_table (info)->dynstr = dynstr = _bfd_elf_stringtab_init ();
+ if (dynstr == NULL)
+ return false;
+ }
+
+ h->dynstr_index = ((unsigned long)
+ _bfd_stringtab_add (dynstr, h->root.root.string,
+ true, false));
+ if (h->dynstr_index == (unsigned long) -1)
+ return false;
+ }
+
+ return true;
+}
+
+/* Create a special linker section, or return a pointer to a linker section already created */
+
+elf_linker_section_t *
+_bfd_elf_create_linker_section (abfd, info, which, defaults)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ enum elf_linker_section_enum which;
+ elf_linker_section_t *defaults;
+{
+ bfd *dynobj = elf_hash_table (info)->dynobj;
+ elf_linker_section_t *lsect;
+
+ /* Record the first bfd section that needs the special section */
+ if (!dynobj)
+ dynobj = elf_hash_table (info)->dynobj = abfd;
+
+ /* If this is the first time, create the section */
+ lsect = elf_linker_section (dynobj, which);
+ if (!lsect)
+ {
+ asection *s;
+
+ lsect = (elf_linker_section_t *)
+ bfd_alloc (dynobj, sizeof (elf_linker_section_t));
+
+ *lsect = *defaults;
+ elf_linker_section (dynobj, which) = lsect;
+ lsect->which = which;
+ lsect->hole_written_p = false;
+
+ /* See if the sections already exist */
+ lsect->section = s = bfd_get_section_by_name (dynobj, lsect->name);
+ if (!s)
+ {
+ lsect->section = s = bfd_make_section (dynobj, lsect->name);
+
+ if (s == NULL)
+ return (elf_linker_section_t *)0;
+
+ bfd_set_section_flags (dynobj, s, defaults->flags);
+ bfd_set_section_alignment (dynobj, s, lsect->alignment);
+ }
+ else if (bfd_get_section_alignment (dynobj, s) < lsect->alignment)
+ bfd_set_section_alignment (dynobj, s, lsect->alignment);
+
+ s->_raw_size = align_power (s->_raw_size, lsect->alignment);
+
+ /* Is there a hole we have to provide? If so check whether the segment is
+ too big already */
+ if (lsect->hole_size)
+ {
+ lsect->hole_offset = s->_raw_size;
+ s->_raw_size += lsect->hole_size;
+ if (lsect->hole_offset > lsect->max_hole_offset)
+ {
+ (*_bfd_error_handler) ("%s: Section %s is already to large to put hole of %ld bytes in",
+ bfd_get_filename (abfd),
+ lsect->name,
+ (long)lsect->hole_size);
+
+ bfd_set_error (bfd_error_bad_value);
+ return (elf_linker_section_t *)0;
+ }
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "Creating section %s, current size = %ld\n",
+ lsect->name, (long)s->_raw_size);
+#endif
+
+ if (lsect->sym_name)
+ {
+ struct elf_link_hash_entry *h = NULL;
+#ifdef DEBUG
+ fprintf (stderr, "Adding %s to section %s\n",
+ lsect->sym_name,
+ lsect->name);
+#endif
+ h = (struct elf_link_hash_entry *)
+ bfd_link_hash_lookup (info->hash, lsect->sym_name, false, false, false);
+
+ if ((h == NULL || h->root.type == bfd_link_hash_undefined)
+ && !(_bfd_generic_link_add_one_symbol (info,
+ abfd,
+ lsect->sym_name,
+ BSF_GLOBAL,
+ s,
+ ((lsect->hole_size)
+ ? s->_raw_size - lsect->hole_size + lsect->sym_offset
+ : lsect->sym_offset),
+ (const char *) NULL,
+ false,
+ get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return (elf_linker_section_t *)0;
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_DYNAMIC;
+ h->type = STT_OBJECT;
+ lsect->sym_hash = h;
+
+ if (info->shared
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return (elf_linker_section_t *)0;
+ }
+ }
+
+ /* Find the related sections if they have been created */
+ if (lsect->bss_name && !lsect->bss_section)
+ lsect->bss_section = bfd_get_section_by_name (dynobj, lsect->bss_name);
+
+ if (lsect->rel_name && !lsect->rel_section)
+ lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
+
+ return lsect;
+}
+
+
+/* Find a linker generated pointer with a given addend and type. */
+
+elf_linker_section_pointers_t *
+_bfd_elf_find_pointer_linker_section (linker_pointers, addend, which)
+ elf_linker_section_pointers_t *linker_pointers;
+ bfd_signed_vma addend;
+ elf_linker_section_enum_t which;
+{
+ for ( ; linker_pointers != NULL; linker_pointers = linker_pointers->next)
+ {
+ if (which == linker_pointers->which && addend == linker_pointers->addend)
+ return linker_pointers;
+ }
+
+ return (elf_linker_section_pointers_t *)0;
+}
+
+
+/* Make the .rela section corresponding to the generated linker section. */
+
+boolean
+_bfd_elf_make_linker_section_rela (dynobj, lsect, alignment)
+ bfd *dynobj;
+ elf_linker_section_t *lsect;
+ int alignment;
+{
+ if (lsect->rel_section)
+ return true;
+
+ lsect->rel_section = bfd_get_section_by_name (dynobj, lsect->rel_name);
+ if (lsect->rel_section == NULL)
+ {
+ lsect->rel_section = bfd_make_section (dynobj, lsect->rel_name);
+ if (lsect->rel_section == NULL
+ || ! bfd_set_section_flags (dynobj,
+ lsect->rel_section,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, lsect->rel_section, alignment))
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/contrib/gdb/bfd/elflink.h b/contrib/gdb/bfd/elflink.h
new file mode 100644
index 0000000..4ef3c8b
--- /dev/null
+++ b/contrib/gdb/bfd/elflink.h
@@ -0,0 +1,3424 @@
+/* ELF linker support.
+ Copyright 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* ELF linker code. */
+
+static boolean elf_link_add_object_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean elf_link_add_archive_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+static Elf_Internal_Rela *elf_link_read_relocs
+ PARAMS ((bfd *, asection *, PTR, Elf_Internal_Rela *, boolean));
+static boolean elf_export_symbol
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_adjust_dynamic_symbol
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+
+/* This struct is used to pass information to routines called via
+ elf_link_hash_traverse which must return failure. */
+
+struct elf_info_failed
+{
+ boolean failed;
+ struct bfd_link_info *info;
+};
+
+/* Given an ELF BFD, add symbols to the global hash table as
+ appropriate. */
+
+boolean
+elf_bfd_link_add_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ switch (bfd_get_format (abfd))
+ {
+ case bfd_object:
+ return elf_link_add_object_symbols (abfd, info);
+ case bfd_archive:
+ return elf_link_add_archive_symbols (abfd, info);
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+}
+
+
+/* Add symbols from an ELF archive file to the linker hash table. We
+ don't use _bfd_generic_link_add_archive_symbols because of a
+ problem which arises on UnixWare. The UnixWare libc.so is an
+ archive which includes an entry libc.so.1 which defines a bunch of
+ symbols. The libc.so archive also includes a number of other
+ object files, which also define symbols, some of which are the same
+ as those defined in libc.so.1. Correct linking requires that we
+ consider each object file in turn, and include it if it defines any
+ symbols we need. _bfd_generic_link_add_archive_symbols does not do
+ this; it looks through the list of undefined symbols, and includes
+ any object file which defines them. When this algorithm is used on
+ UnixWare, it winds up pulling in libc.so.1 early and defining a
+ bunch of symbols. This means that some of the other objects in the
+ archive are not included in the link, which is incorrect since they
+ precede libc.so.1 in the archive.
+
+ Fortunately, ELF archive handling is simpler than that done by
+ _bfd_generic_link_add_archive_symbols, which has to allow for a.out
+ oddities. In ELF, if we find a symbol in the archive map, and the
+ symbol is currently undefined, we know that we must pull in that
+ object file.
+
+ Unfortunately, we do have to make multiple passes over the symbol
+ table until nothing further is resolved. */
+
+static boolean
+elf_link_add_archive_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ symindex c;
+ boolean *defined = NULL;
+ boolean *included = NULL;
+ carsym *symdefs;
+ boolean loop;
+
+ if (! bfd_has_map (abfd))
+ {
+ /* An empty archive is a special case. */
+ if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
+ return true;
+ bfd_set_error (bfd_error_no_armap);
+ return false;
+ }
+
+ /* Keep track of all symbols we know to be already defined, and all
+ files we know to be already included. This is to speed up the
+ second and subsequent passes. */
+ c = bfd_ardata (abfd)->symdef_count;
+ if (c == 0)
+ return true;
+ defined = (boolean *) bfd_malloc (c * sizeof (boolean));
+ included = (boolean *) bfd_malloc (c * sizeof (boolean));
+ if (defined == (boolean *) NULL || included == (boolean *) NULL)
+ goto error_return;
+ memset (defined, 0, c * sizeof (boolean));
+ memset (included, 0, c * sizeof (boolean));
+
+ symdefs = bfd_ardata (abfd)->symdefs;
+
+ do
+ {
+ file_ptr last;
+ symindex i;
+ carsym *symdef;
+ carsym *symdefend;
+
+ loop = false;
+ last = -1;
+
+ symdef = symdefs;
+ symdefend = symdef + c;
+ for (i = 0; symdef < symdefend; symdef++, i++)
+ {
+ struct elf_link_hash_entry *h;
+ bfd *element;
+ struct bfd_link_hash_entry *undefs_tail;
+ symindex mark;
+
+ if (defined[i] || included[i])
+ continue;
+ if (symdef->file_offset == last)
+ {
+ included[i] = true;
+ continue;
+ }
+
+ h = elf_link_hash_lookup (elf_hash_table (info), symdef->name,
+ false, false, false);
+ if (h == (struct elf_link_hash_entry *) NULL)
+ continue;
+ if (h->root.type != bfd_link_hash_undefined)
+ {
+ if (h->root.type != bfd_link_hash_undefweak)
+ defined[i] = true;
+ continue;
+ }
+
+ /* We need to include this archive member. */
+
+ element = _bfd_get_elt_at_filepos (abfd, symdef->file_offset);
+ if (element == (bfd *) NULL)
+ goto error_return;
+
+ if (! bfd_check_format (element, bfd_object))
+ goto error_return;
+
+ /* Doublecheck that we have not included this object
+ already--it should be impossible, but there may be
+ something wrong with the archive. */
+ if (element->archive_pass != 0)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ element->archive_pass = 1;
+
+ undefs_tail = info->hash->undefs_tail;
+
+ if (! (*info->callbacks->add_archive_element) (info, element,
+ symdef->name))
+ goto error_return;
+ if (! elf_link_add_object_symbols (element, info))
+ goto error_return;
+
+ /* If there are any new undefined symbols, we need to make
+ another pass through the archive in order to see whether
+ they can be defined. FIXME: This isn't perfect, because
+ common symbols wind up on undefs_tail and because an
+ undefined symbol which is defined later on in this pass
+ does not require another pass. This isn't a bug, but it
+ does make the code less efficient than it could be. */
+ if (undefs_tail != info->hash->undefs_tail)
+ loop = true;
+
+ /* Look backward to mark all symbols from this object file
+ which we have already seen in this pass. */
+ mark = i;
+ do
+ {
+ included[mark] = true;
+ if (mark == 0)
+ break;
+ --mark;
+ }
+ while (symdefs[mark].file_offset == symdef->file_offset);
+
+ /* We mark subsequent symbols from this object file as we go
+ on through the loop. */
+ last = symdef->file_offset;
+ }
+ }
+ while (loop);
+
+ free (defined);
+ free (included);
+
+ return true;
+
+ error_return:
+ if (defined != (boolean *) NULL)
+ free (defined);
+ if (included != (boolean *) NULL)
+ free (included);
+ return false;
+}
+
+/* Add symbols from an ELF object file to the linker hash table. */
+
+static boolean
+elf_link_add_object_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ boolean (*add_symbol_hook) PARAMS ((bfd *, struct bfd_link_info *,
+ const Elf_Internal_Sym *,
+ const char **, flagword *,
+ asection **, bfd_vma *));
+ boolean (*check_relocs) PARAMS ((bfd *, struct bfd_link_info *,
+ asection *, const Elf_Internal_Rela *));
+ boolean collect;
+ Elf_Internal_Shdr *hdr;
+ size_t symcount;
+ size_t extsymcount;
+ size_t extsymoff;
+ Elf_External_Sym *buf = NULL;
+ struct elf_link_hash_entry **sym_hash;
+ boolean dynamic;
+ Elf_External_Dyn *dynbuf = NULL;
+ struct elf_link_hash_entry *weaks;
+ Elf_External_Sym *esym;
+ Elf_External_Sym *esymend;
+
+ add_symbol_hook = get_elf_backend_data (abfd)->elf_add_symbol_hook;
+ collect = get_elf_backend_data (abfd)->collect;
+
+ /* As a GNU extension, any input sections which are named
+ .gnu.warning.SYMBOL are treated as warning symbols for the given
+ symbol. This differs from .gnu.warning sections, which generate
+ warnings when they are included in an output file. */
+ if (! info->shared)
+ {
+ asection *s;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ {
+ const char *name;
+
+ name = bfd_get_section_name (abfd, s);
+ if (strncmp (name, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0)
+ {
+ char *msg;
+ bfd_size_type sz;
+
+ sz = bfd_section_size (abfd, s);
+ msg = (char *) bfd_alloc (abfd, sz);
+ if (msg == NULL)
+ goto error_return;
+
+ if (! bfd_get_section_contents (abfd, s, msg, (file_ptr) 0, sz))
+ goto error_return;
+
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd,
+ name + sizeof ".gnu.warning." - 1,
+ BSF_WARNING, s, (bfd_vma) 0, msg, false, collect,
+ (struct bfd_link_hash_entry **) NULL)))
+ goto error_return;
+
+ if (! info->relocateable)
+ {
+ /* Clobber the section size so that the warning does
+ not get copied into the output file. */
+ s->_raw_size = 0;
+ }
+ }
+ }
+ }
+
+ /* A stripped shared library might only have a dynamic symbol table,
+ not a regular symbol table. In that case we can still go ahead
+ and link using the dynamic symbol table. */
+ if (elf_onesymtab (abfd) == 0
+ && elf_dynsymtab (abfd) != 0)
+ {
+ elf_onesymtab (abfd) = elf_dynsymtab (abfd);
+ elf_tdata (abfd)->symtab_hdr = elf_tdata (abfd)->dynsymtab_hdr;
+ }
+
+ hdr = &elf_tdata (abfd)->symtab_hdr;
+ symcount = hdr->sh_size / sizeof (Elf_External_Sym);
+
+ /* The sh_info field of the symtab header tells us where the
+ external symbols start. We don't care about the local symbols at
+ this point. */
+ if (elf_bad_symtab (abfd))
+ {
+ extsymcount = symcount;
+ extsymoff = 0;
+ }
+ else
+ {
+ extsymcount = symcount - hdr->sh_info;
+ extsymoff = hdr->sh_info;
+ }
+
+ buf = ((Elf_External_Sym *)
+ bfd_malloc (extsymcount * sizeof (Elf_External_Sym)));
+ if (buf == NULL && extsymcount != 0)
+ goto error_return;
+
+ /* We store a pointer to the hash table entry for each external
+ symbol. */
+ sym_hash = ((struct elf_link_hash_entry **)
+ bfd_alloc (abfd,
+ extsymcount * sizeof (struct elf_link_hash_entry *)));
+ if (sym_hash == NULL)
+ goto error_return;
+ elf_sym_hashes (abfd) = sym_hash;
+
+ if (elf_elfheader (abfd)->e_type != ET_DYN)
+ {
+ dynamic = false;
+
+ /* If we are creating a shared library, create all the dynamic
+ sections immediately. We need to attach them to something,
+ so we attach them to this BFD, provided it is the right
+ format. FIXME: If there are no input BFD's of the same
+ format as the output, we can't make a shared library. */
+ if (info->shared
+ && ! elf_hash_table (info)->dynamic_sections_created
+ && abfd->xvec == info->hash->creator)
+ {
+ if (! elf_link_create_dynamic_sections (abfd, info))
+ goto error_return;
+ }
+ }
+ else
+ {
+ asection *s;
+ boolean add_needed;
+ const char *name;
+ bfd_size_type oldsize;
+ bfd_size_type strindex;
+
+ dynamic = true;
+
+ /* You can't use -r against a dynamic object. Also, there's no
+ hope of using a dynamic object which does not exactly match
+ the format of the output file. */
+ if (info->relocateable
+ || info->hash->creator != abfd->xvec)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ goto error_return;
+ }
+
+ /* Find the name to use in a DT_NEEDED entry that refers to this
+ object. If the object has a DT_SONAME entry, we use it.
+ Otherwise, if the generic linker stuck something in
+ elf_dt_name, we use that. Otherwise, we just use the file
+ name. If the generic linker put a null string into
+ elf_dt_name, we don't make a DT_NEEDED entry at all, even if
+ there is a DT_SONAME entry. */
+ add_needed = true;
+ name = bfd_get_filename (abfd);
+ if (elf_dt_name (abfd) != NULL)
+ {
+ name = elf_dt_name (abfd);
+ if (*name == '\0')
+ add_needed = false;
+ }
+ s = bfd_get_section_by_name (abfd, ".dynamic");
+ if (s != NULL)
+ {
+ Elf_External_Dyn *extdyn;
+ Elf_External_Dyn *extdynend;
+ int elfsec;
+ unsigned long link;
+
+ dynbuf = (Elf_External_Dyn *) bfd_malloc ((size_t) s->_raw_size);
+ if (dynbuf == NULL)
+ goto error_return;
+
+ if (! bfd_get_section_contents (abfd, s, (PTR) dynbuf,
+ (file_ptr) 0, s->_raw_size))
+ goto error_return;
+
+ elfsec = _bfd_elf_section_from_bfd_section (abfd, s);
+ if (elfsec == -1)
+ goto error_return;
+ link = elf_elfsections (abfd)[elfsec]->sh_link;
+
+ extdyn = dynbuf;
+ extdynend = extdyn + s->_raw_size / sizeof (Elf_External_Dyn);
+ for (; extdyn < extdynend; extdyn++)
+ {
+ Elf_Internal_Dyn dyn;
+
+ elf_swap_dyn_in (abfd, extdyn, &dyn);
+ if (dyn.d_tag == DT_SONAME)
+ {
+ name = bfd_elf_string_from_elf_section (abfd, link,
+ dyn.d_un.d_val);
+ if (name == NULL)
+ goto error_return;
+ }
+ if (dyn.d_tag == DT_NEEDED)
+ {
+ struct bfd_link_needed_list *n, **pn;
+ char *fnm, *anm;
+
+ n = ((struct bfd_link_needed_list *)
+ bfd_alloc (abfd, sizeof (struct bfd_link_needed_list)));
+ fnm = bfd_elf_string_from_elf_section (abfd, link,
+ dyn.d_un.d_val);
+ if (n == NULL || fnm == NULL)
+ goto error_return;
+ anm = bfd_alloc (abfd, strlen (fnm) + 1);
+ if (anm == NULL)
+ goto error_return;
+ strcpy (anm, fnm);
+ n->name = anm;
+ n->by = abfd;
+ n->next = NULL;
+ for (pn = &elf_hash_table (info)->needed;
+ *pn != NULL;
+ pn = &(*pn)->next)
+ ;
+ *pn = n;
+ }
+ }
+
+ free (dynbuf);
+ dynbuf = NULL;
+ }
+
+ /* We do not want to include any of the sections in a dynamic
+ object in the output file. We hack by simply clobbering the
+ list of sections in the BFD. This could be handled more
+ cleanly by, say, a new section flag; the existing
+ SEC_NEVER_LOAD flag is not the one we want, because that one
+ still implies that the section takes up space in the output
+ file. */
+ abfd->sections = NULL;
+ abfd->section_count = 0;
+
+ /* If this is the first dynamic object found in the link, create
+ the special sections required for dynamic linking. */
+ if (! elf_hash_table (info)->dynamic_sections_created)
+ {
+ if (! elf_link_create_dynamic_sections (abfd, info))
+ goto error_return;
+ }
+
+ if (add_needed)
+ {
+ /* Add a DT_NEEDED entry for this dynamic object. */
+ oldsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+ strindex = _bfd_stringtab_add (elf_hash_table (info)->dynstr, name,
+ true, false);
+ if (strindex == (bfd_size_type) -1)
+ goto error_return;
+
+ if (oldsize == _bfd_stringtab_size (elf_hash_table (info)->dynstr))
+ {
+ asection *sdyn;
+ Elf_External_Dyn *dyncon, *dynconend;
+
+ /* The hash table size did not change, which means that
+ the dynamic object name was already entered. If we
+ have already included this dynamic object in the
+ link, just ignore it. There is no reason to include
+ a particular dynamic object more than once. */
+ sdyn = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
+ ".dynamic");
+ BFD_ASSERT (sdyn != NULL);
+
+ dyncon = (Elf_External_Dyn *) sdyn->contents;
+ dynconend = (Elf_External_Dyn *) (sdyn->contents +
+ sdyn->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+
+ elf_swap_dyn_in (elf_hash_table (info)->dynobj, dyncon,
+ &dyn);
+ if (dyn.d_tag == DT_NEEDED
+ && dyn.d_un.d_val == strindex)
+ {
+ if (buf != NULL)
+ free (buf);
+ return true;
+ }
+ }
+ }
+
+ if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+ goto error_return;
+ }
+
+ /* Save the SONAME, if there is one, because sometimes the
+ linker emulation code will need to know it. */
+ if (*name == '\0')
+ name = bfd_get_filename (abfd);
+ elf_dt_name (abfd) = name;
+ }
+
+ if (bfd_seek (abfd,
+ hdr->sh_offset + extsymoff * sizeof (Elf_External_Sym),
+ SEEK_SET) != 0
+ || (bfd_read ((PTR) buf, sizeof (Elf_External_Sym), extsymcount, abfd)
+ != extsymcount * sizeof (Elf_External_Sym)))
+ goto error_return;
+
+ weaks = NULL;
+
+ esymend = buf + extsymcount;
+ for (esym = buf; esym < esymend; esym++, sym_hash++)
+ {
+ Elf_Internal_Sym sym;
+ int bind;
+ bfd_vma value;
+ asection *sec;
+ flagword flags;
+ const char *name;
+ struct elf_link_hash_entry *h;
+ boolean definition;
+ boolean size_change_ok, type_change_ok;
+ boolean new_weakdef;
+
+ elf_swap_symbol_in (abfd, esym, &sym);
+
+ flags = BSF_NO_FLAGS;
+ sec = NULL;
+ value = sym.st_value;
+ *sym_hash = NULL;
+
+ bind = ELF_ST_BIND (sym.st_info);
+ if (bind == STB_LOCAL)
+ {
+ /* This should be impossible, since ELF requires that all
+ global symbols follow all local symbols, and that sh_info
+ point to the first global symbol. Unfortunatealy, Irix 5
+ screws this up. */
+ continue;
+ }
+ else if (bind == STB_GLOBAL)
+ {
+ if (sym.st_shndx != SHN_UNDEF
+ && sym.st_shndx != SHN_COMMON)
+ flags = BSF_GLOBAL;
+ else
+ flags = 0;
+ }
+ else if (bind == STB_WEAK)
+ flags = BSF_WEAK;
+ else
+ {
+ /* Leave it up to the processor backend. */
+ }
+
+ if (sym.st_shndx == SHN_UNDEF)
+ sec = bfd_und_section_ptr;
+ else if (sym.st_shndx > 0 && sym.st_shndx < SHN_LORESERVE)
+ {
+ sec = section_from_elf_index (abfd, sym.st_shndx);
+ if (sec != NULL)
+ value -= sec->vma;
+ else
+ sec = bfd_abs_section_ptr;
+ }
+ else if (sym.st_shndx == SHN_ABS)
+ sec = bfd_abs_section_ptr;
+ else if (sym.st_shndx == SHN_COMMON)
+ {
+ sec = bfd_com_section_ptr;
+ /* What ELF calls the size we call the value. What ELF
+ calls the value we call the alignment. */
+ value = sym.st_size;
+ }
+ else
+ {
+ /* Leave it up to the processor backend. */
+ }
+
+ name = bfd_elf_string_from_elf_section (abfd, hdr->sh_link, sym.st_name);
+ if (name == (const char *) NULL)
+ goto error_return;
+
+ if (add_symbol_hook)
+ {
+ if (! (*add_symbol_hook) (abfd, info, &sym, &name, &flags, &sec,
+ &value))
+ goto error_return;
+
+ /* The hook function sets the name to NULL if this symbol
+ should be skipped for some reason. */
+ if (name == (const char *) NULL)
+ continue;
+ }
+
+ /* Sanity check that all possibilities were handled. */
+ if (sec == (asection *) NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ if (bfd_is_und_section (sec)
+ || bfd_is_com_section (sec))
+ definition = false;
+ else
+ definition = true;
+
+ size_change_ok = false;
+ type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
+ if (info->hash->creator->flavour == bfd_target_elf_flavour)
+ {
+ /* We need to look up the symbol now in order to get some of
+ the dynamic object handling right. We pass the hash
+ table entry in to _bfd_generic_link_add_one_symbol so
+ that it does not have to look it up again. */
+ if (! bfd_is_und_section (sec))
+ h = elf_link_hash_lookup (elf_hash_table (info), name,
+ true, false, false);
+ else
+ h = ((struct elf_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (abfd, info, name, true,
+ false, false));
+ if (h == NULL)
+ goto error_return;
+ *sym_hash = h;
+
+ if (h->root.type == bfd_link_hash_new)
+ h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+ /* It's OK to change the type if it used to be a weak
+ definition. */
+ if (h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_undefweak)
+ type_change_ok = true;
+
+ /* It's OK to change the size if it used to be a weak
+ definition, or if it used to be undefined, or if we will
+ be overriding an old definition. */
+ if (type_change_ok
+ || h->root.type == bfd_link_hash_undefined)
+ size_change_ok = true;
+
+ /* If we are looking at a dynamic object, and this is a
+ definition, we need to see if it has already been defined
+ by some other object. If it has, we want to use the
+ existing definition, and we do not want to report a
+ multiple symbol definition error; we do this by
+ clobbering sec to be bfd_und_section_ptr. */
+ if (dynamic && definition)
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak
+ || (h->root.type == bfd_link_hash_common
+ && bind == STB_WEAK))
+ {
+ sec = bfd_und_section_ptr;
+ definition = false;
+ size_change_ok = true;
+ }
+ }
+
+ /* Similarly, if we are not looking at a dynamic object, and
+ we have a definition, we want to override any definition
+ we may have from a dynamic object. Symbols from regular
+ files always take precedence over symbols from dynamic
+ objects, even if they are defined after the dynamic
+ object in the link. */
+ if (! dynamic
+ && definition
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (bfd_get_flavour (h->root.u.def.section->owner)
+ == bfd_target_elf_flavour)
+ && (elf_elfheader (h->root.u.def.section->owner)->e_type
+ == ET_DYN))
+ {
+ /* Change the hash table entry to undefined, and let
+ _bfd_generic_link_add_one_symbol do the right thing
+ with the new definition. */
+ h->root.type = bfd_link_hash_undefined;
+ h->root.u.undef.abfd = h->root.u.def.section->owner;
+ size_change_ok = true;
+ }
+ }
+
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, name, flags, sec, value, (const char *) NULL,
+ false, collect, (struct bfd_link_hash_entry **) sym_hash)))
+ goto error_return;
+
+ h = *sym_hash;
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ *sym_hash = h;
+
+ new_weakdef = false;
+ if (dynamic
+ && definition
+ && (flags & BSF_WEAK) != 0
+ && ELF_ST_TYPE (sym.st_info) != STT_FUNC
+ && info->hash->creator->flavour == bfd_target_elf_flavour
+ && h->weakdef == NULL)
+ {
+ /* Keep a list of all weak defined non function symbols from
+ a dynamic object, using the weakdef field. Later in this
+ function we will set the weakdef field to the correct
+ value. We only put non-function symbols from dynamic
+ objects on this list, because that happens to be the only
+ time we need to know the normal symbol corresponding to a
+ weak symbol, and the information is time consuming to
+ figure out. If the weakdef field is not already NULL,
+ then this symbol was already defined by some previous
+ dynamic object, and we will be using that previous
+ definition anyhow. */
+
+ h->weakdef = weaks;
+ weaks = h;
+ new_weakdef = true;
+ }
+
+ /* Get the alignment of a common symbol. */
+ if (sym.st_shndx == SHN_COMMON
+ && h->root.type == bfd_link_hash_common)
+ h->root.u.c.p->alignment_power = bfd_log2 (sym.st_value);
+
+ if (info->hash->creator->flavour == bfd_target_elf_flavour)
+ {
+ int old_flags;
+ boolean dynsym;
+ int new_flag;
+
+ /* Remember the symbol size and type. */
+ if (sym.st_size != 0
+ && (definition || h->size == 0))
+ {
+ if (h->size != 0 && h->size != sym.st_size && ! size_change_ok)
+ (*_bfd_error_handler)
+ ("Warning: size of symbol `%s' changed from %lu to %lu in %s",
+ name, (unsigned long) h->size, (unsigned long) sym.st_size,
+ bfd_get_filename (abfd));
+
+ h->size = sym.st_size;
+ }
+ if (ELF_ST_TYPE (sym.st_info) != STT_NOTYPE
+ && (definition || h->type == STT_NOTYPE))
+ {
+ if (h->type != STT_NOTYPE
+ && h->type != ELF_ST_TYPE (sym.st_info)
+ && ! type_change_ok)
+ (*_bfd_error_handler)
+ ("Warning: type of symbol `%s' changed from %d to %d in %s",
+ name, h->type, ELF_ST_TYPE (sym.st_info),
+ bfd_get_filename (abfd));
+
+ h->type = ELF_ST_TYPE (sym.st_info);
+ }
+
+ /* Set a flag in the hash table entry indicating the type of
+ reference or definition we just found. Keep a count of
+ the number of dynamic symbols we find. A dynamic symbol
+ is one which is referenced or defined by both a regular
+ object and a shared object, or one which is referenced or
+ defined by more than one shared object. */
+ old_flags = h->elf_link_hash_flags;
+ dynsym = false;
+ if (! dynamic)
+ {
+ if (! definition)
+ new_flag = ELF_LINK_HASH_REF_REGULAR;
+ else
+ new_flag = ELF_LINK_HASH_DEF_REGULAR;
+ if (info->shared
+ || (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
+ | ELF_LINK_HASH_REF_DYNAMIC)) != 0)
+ dynsym = true;
+ }
+ else
+ {
+ if (! definition)
+ new_flag = ELF_LINK_HASH_REF_DYNAMIC;
+ else
+ new_flag = ELF_LINK_HASH_DEF_DYNAMIC;
+ if ((old_flags & new_flag) != 0
+ || (old_flags & (ELF_LINK_HASH_DEF_REGULAR
+ | ELF_LINK_HASH_REF_REGULAR)) != 0
+ || (h->weakdef != NULL
+ && (old_flags & (ELF_LINK_HASH_DEF_DYNAMIC
+ | ELF_LINK_HASH_REF_DYNAMIC)) != 0))
+ dynsym = true;
+ }
+
+ h->elf_link_hash_flags |= new_flag;
+ if (dynsym && h->dynindx == -1)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ goto error_return;
+ if (h->weakdef != NULL
+ && ! new_weakdef
+ && h->weakdef->dynindx == -1)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (info,
+ h->weakdef))
+ goto error_return;
+ }
+ }
+ }
+ }
+
+ /* Now set the weakdefs field correctly for all the weak defined
+ symbols we found. The only way to do this is to search all the
+ symbols. Since we only need the information for non functions in
+ dynamic objects, that's the only time we actually put anything on
+ the list WEAKS. We need this information so that if a regular
+ object refers to a symbol defined weakly in a dynamic object, the
+ real symbol in the dynamic object is also put in the dynamic
+ symbols; we also must arrange for both symbols to point to the
+ same memory location. We could handle the general case of symbol
+ aliasing, but a general symbol alias can only be generated in
+ assembler code, handling it correctly would be very time
+ consuming, and other ELF linkers don't handle general aliasing
+ either. */
+ while (weaks != NULL)
+ {
+ struct elf_link_hash_entry *hlook;
+ asection *slook;
+ bfd_vma vlook;
+ struct elf_link_hash_entry **hpp;
+ struct elf_link_hash_entry **hppend;
+
+ hlook = weaks;
+ weaks = hlook->weakdef;
+ hlook->weakdef = NULL;
+
+ BFD_ASSERT (hlook->root.type == bfd_link_hash_defined
+ || hlook->root.type == bfd_link_hash_defweak
+ || hlook->root.type == bfd_link_hash_common
+ || hlook->root.type == bfd_link_hash_indirect);
+ slook = hlook->root.u.def.section;
+ vlook = hlook->root.u.def.value;
+
+ hpp = elf_sym_hashes (abfd);
+ hppend = hpp + extsymcount;
+ for (; hpp < hppend; hpp++)
+ {
+ struct elf_link_hash_entry *h;
+
+ h = *hpp;
+ if (h != NULL && h != hlook
+ && h->root.type == bfd_link_hash_defined
+ && h->root.u.def.section == slook
+ && h->root.u.def.value == vlook)
+ {
+ hlook->weakdef = h;
+
+ /* If the weak definition is in the list of dynamic
+ symbols, make sure the real definition is put there
+ as well. */
+ if (hlook->dynindx != -1
+ && h->dynindx == -1)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ goto error_return;
+ }
+
+ break;
+ }
+ }
+ }
+
+ if (buf != NULL)
+ {
+ free (buf);
+ buf = NULL;
+ }
+
+ /* If this object is the same format as the output object, and it is
+ not a shared library, then let the backend look through the
+ relocs.
+
+ This is required to build global offset table entries and to
+ arrange for dynamic relocs. It is not required for the
+ particular common case of linking non PIC code, even when linking
+ against shared libraries, but unfortunately there is no way of
+ knowing whether an object file has been compiled PIC or not.
+ Looking through the relocs is not particularly time consuming.
+ The problem is that we must either (1) keep the relocs in memory,
+ which causes the linker to require additional runtime memory or
+ (2) read the relocs twice from the input file, which wastes time.
+ This would be a good case for using mmap.
+
+ I have no idea how to handle linking PIC code into a file of a
+ different format. It probably can't be done. */
+ check_relocs = get_elf_backend_data (abfd)->check_relocs;
+ if (! dynamic
+ && abfd->xvec == info->hash->creator
+ && check_relocs != NULL)
+ {
+ asection *o;
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ Elf_Internal_Rela *internal_relocs;
+ boolean ok;
+
+ if ((o->flags & SEC_RELOC) == 0
+ || o->reloc_count == 0)
+ continue;
+
+ /* I believe we can ignore the relocs for any section which
+ does not form part of the final process image, such as a
+ debugging section. */
+ if ((o->flags & SEC_ALLOC) == 0)
+ continue;
+
+ internal_relocs = elf_link_read_relocs (abfd, o, (PTR) NULL,
+ (Elf_Internal_Rela *) NULL,
+ info->keep_memory);
+ if (internal_relocs == NULL)
+ goto error_return;
+
+ ok = (*check_relocs) (abfd, info, o, internal_relocs);
+
+ if (! info->keep_memory)
+ free (internal_relocs);
+
+ if (! ok)
+ goto error_return;
+ }
+ }
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ if (dynbuf != NULL)
+ free (dynbuf);
+ return false;
+}
+
+/* Create some sections which will be filled in with dynamic linking
+ information. ABFD is an input file which requires dynamic sections
+ to be created. The dynamic sections take up virtual memory space
+ when the final executable is run, so we need to create them before
+ addresses are assigned to the output sections. We work out the
+ actual contents and size of these sections later. */
+
+boolean
+elf_link_create_dynamic_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+ struct elf_link_hash_entry *h;
+ struct elf_backend_data *bed;
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ return true;
+
+ /* Make sure that all dynamic sections use the same input BFD. */
+ if (elf_hash_table (info)->dynobj == NULL)
+ elf_hash_table (info)->dynobj = abfd;
+ else
+ abfd = elf_hash_table (info)->dynobj;
+
+ /* Note that we set the SEC_IN_MEMORY flag for all of these
+ sections. */
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ /* A dynamically linked executable has a .interp section, but a
+ shared library does not. */
+ if (! info->shared)
+ {
+ s = bfd_make_section (abfd, ".interp");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
+ return false;
+ }
+
+ s = bfd_make_section (abfd, ".dynsym");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
+ return false;
+
+ s = bfd_make_section (abfd, ".dynstr");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY))
+ return false;
+
+ /* Create a strtab to hold the dynamic symbol names. */
+ if (elf_hash_table (info)->dynstr == NULL)
+ {
+ elf_hash_table (info)->dynstr = elf_stringtab_init ();
+ if (elf_hash_table (info)->dynstr == NULL)
+ return false;
+ }
+
+ s = bfd_make_section (abfd, ".dynamic");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
+ return false;
+
+ /* The special symbol _DYNAMIC is always set to the start of the
+ .dynamic section. This call occurs before we have processed the
+ symbols for any dynamic object, so we don't have to worry about
+ overriding a dynamic definition. We could set _DYNAMIC in a
+ linker script, but we only want to define it if we are, in fact,
+ creating a .dynamic section. We don't want to define it if there
+ is no .dynamic section, since on some ELF platforms the start up
+ code examines it to decide how to initialize the process. */
+ h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, "_DYNAMIC", BSF_GLOBAL, s, (bfd_vma) 0,
+ (const char *) NULL, false, get_elf_backend_data (abfd)->collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+ if (info->shared
+ && ! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
+
+ s = bfd_make_section (abfd, ".hash");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, LOG_FILE_ALIGN))
+ return false;
+
+ /* Let the backend create the rest of the sections. This lets the
+ backend set the right flags. The backend will normally create
+ the .got and .plt sections. */
+ bed = get_elf_backend_data (abfd);
+ if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info))
+ return false;
+
+ elf_hash_table (info)->dynamic_sections_created = true;
+
+ return true;
+}
+
+/* Add an entry to the .dynamic table. */
+
+boolean
+elf_add_dynamic_entry (info, tag, val)
+ struct bfd_link_info *info;
+ bfd_vma tag;
+ bfd_vma val;
+{
+ Elf_Internal_Dyn dyn;
+ bfd *dynobj;
+ asection *s;
+ size_t newsize;
+ bfd_byte *newcontents;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ s = bfd_get_section_by_name (dynobj, ".dynamic");
+ BFD_ASSERT (s != NULL);
+
+ newsize = s->_raw_size + sizeof (Elf_External_Dyn);
+ newcontents = (bfd_byte *) bfd_realloc (s->contents, newsize);
+ if (newcontents == NULL)
+ return false;
+
+ dyn.d_tag = tag;
+ dyn.d_un.d_val = val;
+ elf_swap_dyn_out (dynobj, &dyn,
+ (Elf_External_Dyn *) (newcontents + s->_raw_size));
+
+ s->_raw_size = newsize;
+ s->contents = newcontents;
+
+ return true;
+}
+
+
+/* Read and swap the relocs for a section. They may have been cached.
+ If the EXTERNAL_RELOCS and INTERNAL_RELOCS arguments are not NULL,
+ they are used as buffers to read into. They are known to be large
+ enough. If the INTERNAL_RELOCS relocs argument is NULL, the return
+ value is allocated using either malloc or bfd_alloc, according to
+ the KEEP_MEMORY argument. */
+
+static Elf_Internal_Rela *
+elf_link_read_relocs (abfd, o, external_relocs, internal_relocs, keep_memory)
+ bfd *abfd;
+ asection *o;
+ PTR external_relocs;
+ Elf_Internal_Rela *internal_relocs;
+ boolean keep_memory;
+{
+ Elf_Internal_Shdr *rel_hdr;
+ PTR alloc1 = NULL;
+ Elf_Internal_Rela *alloc2 = NULL;
+
+ if (elf_section_data (o)->relocs != NULL)
+ return elf_section_data (o)->relocs;
+
+ if (o->reloc_count == 0)
+ return NULL;
+
+ rel_hdr = &elf_section_data (o)->rel_hdr;
+
+ if (internal_relocs == NULL)
+ {
+ size_t size;
+
+ size = o->reloc_count * sizeof (Elf_Internal_Rela);
+ if (keep_memory)
+ internal_relocs = (Elf_Internal_Rela *) bfd_alloc (abfd, size);
+ else
+ internal_relocs = alloc2 = (Elf_Internal_Rela *) bfd_malloc (size);
+ if (internal_relocs == NULL)
+ goto error_return;
+ }
+
+ if (external_relocs == NULL)
+ {
+ alloc1 = (PTR) bfd_malloc ((size_t) rel_hdr->sh_size);
+ if (alloc1 == NULL)
+ goto error_return;
+ external_relocs = alloc1;
+ }
+
+ if ((bfd_seek (abfd, rel_hdr->sh_offset, SEEK_SET) != 0)
+ || (bfd_read (external_relocs, 1, rel_hdr->sh_size, abfd)
+ != rel_hdr->sh_size))
+ goto error_return;
+
+ /* Swap in the relocs. For convenience, we always produce an
+ Elf_Internal_Rela array; if the relocs are Rel, we set the addend
+ to 0. */
+ if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
+ {
+ Elf_External_Rel *erel;
+ Elf_External_Rel *erelend;
+ Elf_Internal_Rela *irela;
+
+ erel = (Elf_External_Rel *) external_relocs;
+ erelend = erel + o->reloc_count;
+ irela = internal_relocs;
+ for (; erel < erelend; erel++, irela++)
+ {
+ Elf_Internal_Rel irel;
+
+ elf_swap_reloc_in (abfd, erel, &irel);
+ irela->r_offset = irel.r_offset;
+ irela->r_info = irel.r_info;
+ irela->r_addend = 0;
+ }
+ }
+ else
+ {
+ Elf_External_Rela *erela;
+ Elf_External_Rela *erelaend;
+ Elf_Internal_Rela *irela;
+
+ BFD_ASSERT (rel_hdr->sh_entsize == sizeof (Elf_External_Rela));
+
+ erela = (Elf_External_Rela *) external_relocs;
+ erelaend = erela + o->reloc_count;
+ irela = internal_relocs;
+ for (; erela < erelaend; erela++, irela++)
+ elf_swap_reloca_in (abfd, erela, irela);
+ }
+
+ /* Cache the results for next time, if we can. */
+ if (keep_memory)
+ elf_section_data (o)->relocs = internal_relocs;
+
+ if (alloc1 != NULL)
+ free (alloc1);
+
+ /* Don't free alloc2, since if it was allocated we are passing it
+ back (under the name of internal_relocs). */
+
+ return internal_relocs;
+
+ error_return:
+ if (alloc1 != NULL)
+ free (alloc1);
+ if (alloc2 != NULL)
+ free (alloc2);
+ return NULL;
+}
+
+
+/* Record an assignment to a symbol made by a linker script. We need
+ this in case some dynamic object refers to this symbol. */
+
+/*ARGSUSED*/
+boolean
+NAME(bfd_elf,record_link_assignment) (output_bfd, info, name, provide)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ const char *name;
+ boolean provide;
+{
+ struct elf_link_hash_entry *h;
+
+ if (info->hash->creator->flavour != bfd_target_elf_flavour)
+ return true;
+
+ h = elf_link_hash_lookup (elf_hash_table (info), name, true, true, false);
+ if (h == NULL)
+ return false;
+
+ if (h->root.type == bfd_link_hash_new)
+ h->elf_link_hash_flags &=~ ELF_LINK_NON_ELF;
+
+ /* If this symbol is being provided by the linker script, and it is
+ currently defined by a dynamic object, but not by a regular
+ object, then mark it as undefined so that the generic linker will
+ force the correct value. */
+ if (provide
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ h->root.type = bfd_link_hash_undefined;
+
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ h->type = STT_OBJECT;
+
+ if (((h->elf_link_hash_flags & (ELF_LINK_HASH_DEF_DYNAMIC
+ | ELF_LINK_HASH_REF_DYNAMIC)) != 0
+ || info->shared)
+ && h->dynindx == -1)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+ return false;
+
+ /* If this is a weak defined symbol, and we know a corresponding
+ real symbol from the same dynamic object, make sure the real
+ symbol is also made into a dynamic symbol. */
+ if (h->weakdef != NULL
+ && h->weakdef->dynindx == -1)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (info, h->weakdef))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/* Array used to determine the number of hash table buckets to use
+ based on the number of symbols there are. If there are fewer than
+ 3 symbols we use 1 bucket, fewer than 17 symbols we use 3 buckets,
+ fewer than 37 we use 17 buckets, and so forth. We never use more
+ than 521 buckets. */
+
+static const size_t elf_buckets[] =
+{
+ 1, 3, 17, 37, 67, 97, 131, 197, 263, 521, 0
+};
+
+/* Set up the sizes and contents of the ELF dynamic sections. This is
+ called by the ELF linker emulation before_allocation routine. We
+ must set the sizes of the sections before the linker sets the
+ addresses of the various sections. */
+
+boolean
+NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
+ export_dynamic, info, sinterpptr)
+ bfd *output_bfd;
+ const char *soname;
+ const char *rpath;
+ boolean export_dynamic;
+ struct bfd_link_info *info;
+ asection **sinterpptr;
+{
+ bfd *dynobj;
+ struct elf_backend_data *bed;
+
+ *sinterpptr = NULL;
+
+ if (info->hash->creator->flavour != bfd_target_elf_flavour)
+ return true;
+
+ dynobj = elf_hash_table (info)->dynobj;
+
+ /* If there were no dynamic objects in the link, there is nothing to
+ do here. */
+ if (dynobj == NULL)
+ return true;
+
+ /* If we are supposed to export all symbols into the dynamic symbol
+ table (this is not the normal case), then do so. */
+ if (export_dynamic)
+ {
+ struct elf_info_failed eif;
+
+ eif.failed = false;
+ eif.info = info;
+ elf_link_hash_traverse (elf_hash_table (info), elf_export_symbol,
+ (PTR) &eif);
+ if (eif.failed)
+ return false;
+ }
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ struct elf_info_failed eif;
+ struct elf_link_hash_entry *h;
+ bfd_size_type strsize;
+
+ *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (*sinterpptr != NULL || info->shared);
+
+ if (soname != NULL)
+ {
+ bfd_size_type indx;
+
+ indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, soname,
+ true, true);
+ if (indx == (bfd_size_type) -1
+ || ! elf_add_dynamic_entry (info, DT_SONAME, indx))
+ return false;
+ }
+
+ if (info->symbolic)
+ {
+ if (! elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
+ return false;
+ }
+
+ if (rpath != NULL)
+ {
+ bfd_size_type indx;
+
+ indx = _bfd_stringtab_add (elf_hash_table (info)->dynstr, rpath,
+ true, true);
+ if (indx == (bfd_size_type) -1
+ || ! elf_add_dynamic_entry (info, DT_RPATH, indx))
+ return false;
+ }
+
+ /* Find all symbols which were defined in a dynamic object and make
+ the backend pick a reasonable value for them. */
+ eif.failed = false;
+ eif.info = info;
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_adjust_dynamic_symbol,
+ (PTR) &eif);
+ if (eif.failed)
+ return false;
+
+ /* Add some entries to the .dynamic section. We fill in some of the
+ values later, in elf_bfd_final_link, but we must add the entries
+ now so that we know the final size of the .dynamic section. */
+ h = elf_link_hash_lookup (elf_hash_table (info), "_init", false,
+ false, false);
+ if (h != NULL
+ && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
+ | ELF_LINK_HASH_DEF_REGULAR)) != 0)
+ {
+ if (! elf_add_dynamic_entry (info, DT_INIT, 0))
+ return false;
+ }
+ h = elf_link_hash_lookup (elf_hash_table (info), "_fini", false,
+ false, false);
+ if (h != NULL
+ && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
+ | ELF_LINK_HASH_DEF_REGULAR)) != 0)
+ {
+ if (! elf_add_dynamic_entry (info, DT_FINI, 0))
+ return false;
+ }
+ strsize = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+ if (! elf_add_dynamic_entry (info, DT_HASH, 0)
+ || ! elf_add_dynamic_entry (info, DT_STRTAB, 0)
+ || ! elf_add_dynamic_entry (info, DT_SYMTAB, 0)
+ || ! elf_add_dynamic_entry (info, DT_STRSZ, strsize)
+ || ! elf_add_dynamic_entry (info, DT_SYMENT,
+ sizeof (Elf_External_Sym)))
+ return false;
+ }
+
+ /* The backend must work out the sizes of all the other dynamic
+ sections. */
+ bed = get_elf_backend_data (output_bfd);
+ if (! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
+ return false;
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ size_t dynsymcount;
+ asection *s;
+ size_t i;
+ size_t bucketcount = 0;
+ Elf_Internal_Sym isym;
+
+ /* Set the size of the .dynsym and .hash sections. We counted
+ the number of dynamic symbols in elf_link_add_object_symbols.
+ We will build the contents of .dynsym and .hash when we build
+ the final symbol table, because until then we do not know the
+ correct value to give the symbols. We built the .dynstr
+ section as we went along in elf_link_add_object_symbols. */
+ dynsymcount = elf_hash_table (info)->dynsymcount;
+ s = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = dynsymcount * sizeof (Elf_External_Sym);
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ return false;
+
+ /* The first entry in .dynsym is a dummy symbol. */
+ isym.st_value = 0;
+ isym.st_size = 0;
+ isym.st_name = 0;
+ isym.st_info = 0;
+ isym.st_other = 0;
+ isym.st_shndx = 0;
+ elf_swap_symbol_out (output_bfd, &isym,
+ (PTR) (Elf_External_Sym *) s->contents);
+
+ for (i = 0; elf_buckets[i] != 0; i++)
+ {
+ bucketcount = elf_buckets[i];
+ if (dynsymcount < elf_buckets[i + 1])
+ break;
+ }
+
+ s = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = (2 + bucketcount + dynsymcount) * (ARCH_SIZE / 8);
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL)
+ return false;
+ memset (s->contents, 0, (size_t) s->_raw_size);
+
+ put_word (output_bfd, bucketcount, s->contents);
+ put_word (output_bfd, dynsymcount, s->contents + (ARCH_SIZE / 8));
+
+ elf_hash_table (info)->bucketcount = bucketcount;
+
+ s = bfd_get_section_by_name (dynobj, ".dynstr");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = _bfd_stringtab_size (elf_hash_table (info)->dynstr);
+
+ if (! elf_add_dynamic_entry (info, DT_NULL, 0))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* This routine is used to export all defined symbols into the dynamic
+ symbol table. It is called via elf_link_hash_traverse. */
+
+static boolean
+elf_export_symbol (h, data)
+ struct elf_link_hash_entry *h;
+ PTR data;
+{
+ struct elf_info_failed *eif = (struct elf_info_failed *) data;
+
+ if (h->dynindx == -1
+ && (h->elf_link_hash_flags
+ & (ELF_LINK_HASH_DEF_REGULAR | ELF_LINK_HASH_REF_REGULAR)) != 0)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (eif->info, h))
+ {
+ eif->failed = true;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/* Make the backend pick a good value for a dynamic symbol. This is
+ called via elf_link_hash_traverse, and also calls itself
+ recursively. */
+
+static boolean
+elf_adjust_dynamic_symbol (h, data)
+ struct elf_link_hash_entry *h;
+ PTR data;
+{
+ struct elf_info_failed *eif = (struct elf_info_failed *) data;
+ bfd *dynobj;
+ struct elf_backend_data *bed;
+
+ /* If this symbol was mentioned in a non-ELF file, try to set
+ DEF_REGULAR and REF_REGULAR correctly. This is the only way to
+ permit a non-ELF file to correctly refer to a symbol defined in
+ an ELF dynamic object. */
+ if ((h->elf_link_hash_flags & ELF_LINK_NON_ELF) != 0)
+ {
+ if (h->root.type != bfd_link_hash_defined
+ && h->root.type != bfd_link_hash_defweak)
+ h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+ else
+ {
+ if (h->root.u.def.section->owner != NULL
+ && (bfd_get_flavour (h->root.u.def.section->owner)
+ == bfd_target_elf_flavour))
+ h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+ else
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+ }
+
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
+ {
+ if (! _bfd_elf_link_record_dynamic_symbol (eif->info, h))
+ {
+ eif->failed = true;
+ return false;
+ }
+ }
+ }
+
+ /* If -Bsymbolic was used (which means to bind references to global
+ symbols to the definition within the shared object), and this
+ symbol was defined in a regular object, then it actually doesn't
+ need a PLT entry. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0
+ && eif->info->shared
+ && eif->info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+ h->elf_link_hash_flags &=~ ELF_LINK_HASH_NEEDS_PLT;
+
+ /* If this symbol does not require a PLT entry, and it is not
+ defined by a dynamic object, or is not referenced by a regular
+ object, ignore it. We do have to handle a weak defined symbol,
+ even if no regular object refers to it, if we decided to add it
+ to the dynamic symbol table. FIXME: Do we normally need to worry
+ about symbols which are defined by one dynamic object and
+ referenced by another one? */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) == 0
+ && ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0
+ || ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0
+ && (h->weakdef == NULL || h->weakdef->dynindx == -1))))
+ return true;
+
+ /* If we've already adjusted this symbol, don't do it again. This
+ can happen via a recursive call. */
+ if ((h->elf_link_hash_flags & ELF_LINK_HASH_DYNAMIC_ADJUSTED) != 0)
+ return true;
+
+ /* Don't look at this symbol again. Note that we must set this
+ after checking the above conditions, because we may look at a
+ symbol once, decide not to do anything, and then get called
+ recursively later after REF_REGULAR is set below. */
+ h->elf_link_hash_flags |= ELF_LINK_HASH_DYNAMIC_ADJUSTED;
+
+ /* If this is a weak definition, and we know a real definition, and
+ the real symbol is not itself defined by a regular object file,
+ then get a good value for the real definition. We handle the
+ real symbol first, for the convenience of the backend routine.
+
+ Note that there is a confusing case here. If the real definition
+ is defined by a regular object file, we don't get the real symbol
+ from the dynamic object, but we do get the weak symbol. If the
+ processor backend uses a COPY reloc, then if some routine in the
+ dynamic object changes the real symbol, we will not see that
+ change in the corresponding weak symbol. This is the way other
+ ELF linkers work as well, and seems to be a result of the shared
+ library model.
+
+ I will clarify this issue. Most SVR4 shared libraries define the
+ variable _timezone and define timezone as a weak synonym. The
+ tzset call changes _timezone. If you write
+ extern int timezone;
+ int _timezone = 5;
+ int main () { tzset (); printf ("%d %d\n", timezone, _timezone); }
+ you might expect that, since timezone is a synonym for _timezone,
+ the same number will print both times. However, if the processor
+ backend uses a COPY reloc, then actually timezone will be copied
+ into your process image, and, since you define _timezone
+ yourself, _timezone will not. Thus timezone and _timezone will
+ wind up at different memory locations. The tzset call will set
+ _timezone, leaving timezone unchanged. */
+
+ if (h->weakdef != NULL)
+ {
+ struct elf_link_hash_entry *weakdef;
+
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak);
+ weakdef = h->weakdef;
+ BFD_ASSERT (weakdef->root.type == bfd_link_hash_defined
+ || weakdef->root.type == bfd_link_hash_defweak);
+ BFD_ASSERT (weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC);
+ if ((weakdef->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0)
+ {
+ /* This symbol is defined by a regular object file, so we
+ will not do anything special. Clear weakdef for the
+ convenience of the processor backend. */
+ h->weakdef = NULL;
+ }
+ else
+ {
+ /* There is an implicit reference by a regular object file
+ via the weak symbol. */
+ weakdef->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+ if (! elf_adjust_dynamic_symbol (weakdef, (PTR) eif))
+ return false;
+ }
+ }
+
+ dynobj = elf_hash_table (eif->info)->dynobj;
+ bed = get_elf_backend_data (dynobj);
+ if (! (*bed->elf_backend_adjust_dynamic_symbol) (eif->info, h))
+ {
+ eif->failed = true;
+ return false;
+ }
+
+ return true;
+}
+
+/* Final phase of ELF linker. */
+
+/* A structure we use to avoid passing large numbers of arguments. */
+
+struct elf_final_link_info
+{
+ /* General link information. */
+ struct bfd_link_info *info;
+ /* Output BFD. */
+ bfd *output_bfd;
+ /* Symbol string table. */
+ struct bfd_strtab_hash *symstrtab;
+ /* .dynsym section. */
+ asection *dynsym_sec;
+ /* .hash section. */
+ asection *hash_sec;
+ /* Buffer large enough to hold contents of any section. */
+ bfd_byte *contents;
+ /* Buffer large enough to hold external relocs of any section. */
+ PTR external_relocs;
+ /* Buffer large enough to hold internal relocs of any section. */
+ Elf_Internal_Rela *internal_relocs;
+ /* Buffer large enough to hold external local symbols of any input
+ BFD. */
+ Elf_External_Sym *external_syms;
+ /* Buffer large enough to hold internal local symbols of any input
+ BFD. */
+ Elf_Internal_Sym *internal_syms;
+ /* Array large enough to hold a symbol index for each local symbol
+ of any input BFD. */
+ long *indices;
+ /* Array large enough to hold a section pointer for each local
+ symbol of any input BFD. */
+ asection **sections;
+ /* Buffer to hold swapped out symbols. */
+ Elf_External_Sym *symbuf;
+ /* Number of swapped out symbols in buffer. */
+ size_t symbuf_count;
+ /* Number of symbols which fit in symbuf. */
+ size_t symbuf_size;
+};
+
+static boolean elf_link_output_sym
+ PARAMS ((struct elf_final_link_info *, const char *,
+ Elf_Internal_Sym *, asection *));
+static boolean elf_link_flush_output_syms
+ PARAMS ((struct elf_final_link_info *));
+static boolean elf_link_output_extsym
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean elf_link_input_bfd
+ PARAMS ((struct elf_final_link_info *, bfd *));
+static boolean elf_reloc_link_order
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ struct bfd_link_order *));
+
+/* This struct is used to pass information to routines called via
+ elf_link_hash_traverse which must return failure. */
+
+struct elf_finfo_failed
+{
+ boolean failed;
+ struct elf_final_link_info *finfo;
+};
+
+/* Do the final step of an ELF link. */
+
+boolean
+elf_bfd_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ boolean dynamic;
+ bfd *dynobj;
+ struct elf_final_link_info finfo;
+ register asection *o;
+ register struct bfd_link_order *p;
+ register bfd *sub;
+ size_t max_contents_size;
+ size_t max_external_reloc_size;
+ size_t max_internal_reloc_count;
+ size_t max_sym_count;
+ file_ptr off;
+ Elf_Internal_Sym elfsym;
+ unsigned int i;
+ Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Shdr *symstrtab_hdr;
+ struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct elf_finfo_failed eif;
+
+ if (info->shared)
+ abfd->flags |= DYNAMIC;
+
+ dynamic = elf_hash_table (info)->dynamic_sections_created;
+ dynobj = elf_hash_table (info)->dynobj;
+
+ finfo.info = info;
+ finfo.output_bfd = abfd;
+ finfo.symstrtab = elf_stringtab_init ();
+ if (finfo.symstrtab == NULL)
+ return false;
+ if (! dynamic)
+ {
+ finfo.dynsym_sec = NULL;
+ finfo.hash_sec = NULL;
+ }
+ else
+ {
+ finfo.dynsym_sec = bfd_get_section_by_name (dynobj, ".dynsym");
+ finfo.hash_sec = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (finfo.dynsym_sec != NULL && finfo.hash_sec != NULL);
+ }
+ finfo.contents = NULL;
+ finfo.external_relocs = NULL;
+ finfo.internal_relocs = NULL;
+ finfo.external_syms = NULL;
+ finfo.internal_syms = NULL;
+ finfo.indices = NULL;
+ finfo.sections = NULL;
+ finfo.symbuf = NULL;
+ finfo.symbuf_count = 0;
+
+ /* Count up the number of relocations we will output for each output
+ section, so that we know the sizes of the reloc sections. We
+ also figure out some maximum sizes. */
+ max_contents_size = 0;
+ max_external_reloc_size = 0;
+ max_internal_reloc_count = 0;
+ max_sym_count = 0;
+ for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ {
+ o->reloc_count = 0;
+
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ ++o->reloc_count;
+ else if (p->type == bfd_indirect_link_order)
+ {
+ asection *sec;
+
+ sec = p->u.indirect.section;
+
+ if (info->relocateable)
+ o->reloc_count += sec->reloc_count;
+
+ if (sec->_raw_size > max_contents_size)
+ max_contents_size = sec->_raw_size;
+ if (sec->_cooked_size > max_contents_size)
+ max_contents_size = sec->_cooked_size;
+
+ /* We are interested in just local symbols, not all
+ symbols. */
+ if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour)
+ {
+ size_t sym_count;
+
+ if (elf_bad_symtab (sec->owner))
+ sym_count = (elf_tdata (sec->owner)->symtab_hdr.sh_size
+ / sizeof (Elf_External_Sym));
+ else
+ sym_count = elf_tdata (sec->owner)->symtab_hdr.sh_info;
+
+ if (sym_count > max_sym_count)
+ max_sym_count = sym_count;
+
+ if ((sec->flags & SEC_RELOC) != 0)
+ {
+ size_t ext_size;
+
+ ext_size = elf_section_data (sec)->rel_hdr.sh_size;
+ if (ext_size > max_external_reloc_size)
+ max_external_reloc_size = ext_size;
+ if (sec->reloc_count > max_internal_reloc_count)
+ max_internal_reloc_count = sec->reloc_count;
+ }
+ }
+ }
+ }
+
+ if (o->reloc_count > 0)
+ o->flags |= SEC_RELOC;
+ else
+ {
+ /* Explicitly clear the SEC_RELOC flag. The linker tends to
+ set it (this is probably a bug) and if it is set
+ assign_section_numbers will create a reloc section. */
+ o->flags &=~ SEC_RELOC;
+ }
+
+ /* If the SEC_ALLOC flag is not set, force the section VMA to
+ zero. This is done in elf_fake_sections as well, but forcing
+ the VMA to 0 here will ensure that relocs against these
+ sections are handled correctly. */
+ if ((o->flags & SEC_ALLOC) == 0)
+ o->vma = 0;
+ }
+
+ /* Figure out the file positions for everything but the symbol table
+ and the relocs. We set symcount to force assign_section_numbers
+ to create a symbol table. */
+ abfd->symcount = info->strip == strip_all ? 0 : 1;
+ BFD_ASSERT (! abfd->output_has_begun);
+ if (! _bfd_elf_compute_section_file_positions (abfd, info))
+ goto error_return;
+
+ /* That created the reloc sections. Set their sizes, and assign
+ them file positions, and allocate some buffers. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ Elf_Internal_Shdr *rel_hdr;
+ register struct elf_link_hash_entry **p, **pend;
+
+ rel_hdr = &elf_section_data (o)->rel_hdr;
+
+ rel_hdr->sh_size = rel_hdr->sh_entsize * o->reloc_count;
+
+ /* The contents field must last into write_object_contents,
+ so we allocate it with bfd_alloc rather than malloc. */
+ rel_hdr->contents = (PTR) bfd_alloc (abfd, rel_hdr->sh_size);
+ if (rel_hdr->contents == NULL && rel_hdr->sh_size != 0)
+ goto error_return;
+
+ p = ((struct elf_link_hash_entry **)
+ bfd_malloc (o->reloc_count
+ * sizeof (struct elf_link_hash_entry *)));
+ if (p == NULL && o->reloc_count != 0)
+ goto error_return;
+ elf_section_data (o)->rel_hashes = p;
+ pend = p + o->reloc_count;
+ for (; p < pend; p++)
+ *p = NULL;
+
+ /* Use the reloc_count field as an index when outputting the
+ relocs. */
+ o->reloc_count = 0;
+ }
+ }
+
+ _bfd_elf_assign_file_positions_for_relocs (abfd);
+
+ /* We have now assigned file positions for all the sections except
+ .symtab and .strtab. We start the .symtab section at the current
+ file position, and write directly to it. We build the .strtab
+ section in memory. */
+ abfd->symcount = 0;
+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+ /* sh_name is set in prep_headers. */
+ symtab_hdr->sh_type = SHT_SYMTAB;
+ symtab_hdr->sh_flags = 0;
+ symtab_hdr->sh_addr = 0;
+ symtab_hdr->sh_size = 0;
+ symtab_hdr->sh_entsize = sizeof (Elf_External_Sym);
+ /* sh_link is set in assign_section_numbers. */
+ /* sh_info is set below. */
+ /* sh_offset is set just below. */
+ symtab_hdr->sh_addralign = 4; /* FIXME: system dependent? */
+
+ off = elf_tdata (abfd)->next_file_pos;
+ off = _bfd_elf_assign_file_position_for_section (symtab_hdr, off, true);
+
+ /* Note that at this point elf_tdata (abfd)->next_file_pos is
+ incorrect. We do not yet know the size of the .symtab section.
+ We correct next_file_pos below, after we do know the size. */
+
+ /* Allocate a buffer to hold swapped out symbols. This is to avoid
+ continuously seeking to the right position in the file. */
+ if (! info->keep_memory || max_sym_count < 20)
+ finfo.symbuf_size = 20;
+ else
+ finfo.symbuf_size = max_sym_count;
+ finfo.symbuf = ((Elf_External_Sym *)
+ bfd_malloc (finfo.symbuf_size * sizeof (Elf_External_Sym)));
+ if (finfo.symbuf == NULL)
+ goto error_return;
+
+ /* Start writing out the symbol table. The first symbol is always a
+ dummy symbol. */
+ if (info->strip != strip_all || info->relocateable)
+ {
+ elfsym.st_value = 0;
+ elfsym.st_size = 0;
+ elfsym.st_info = 0;
+ elfsym.st_other = 0;
+ elfsym.st_shndx = SHN_UNDEF;
+ if (! elf_link_output_sym (&finfo, (const char *) NULL,
+ &elfsym, bfd_und_section_ptr))
+ goto error_return;
+ }
+
+#if 0
+ /* Some standard ELF linkers do this, but we don't because it causes
+ bootstrap comparison failures. */
+ /* Output a file symbol for the output file as the second symbol.
+ We output this even if we are discarding local symbols, although
+ I'm not sure if this is correct. */
+ elfsym.st_value = 0;
+ elfsym.st_size = 0;
+ elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+ elfsym.st_other = 0;
+ elfsym.st_shndx = SHN_ABS;
+ if (! elf_link_output_sym (&finfo, bfd_get_filename (abfd),
+ &elfsym, bfd_abs_section_ptr))
+ goto error_return;
+#endif
+
+ /* Output a symbol for each section. We output these even if we are
+ discarding local symbols, since they are used for relocs. These
+ symbols have no names. We store the index of each one in the
+ index field of the section, so that we can find it again when
+ outputting relocs. */
+ if (info->strip != strip_all || info->relocateable)
+ {
+ elfsym.st_value = 0;
+ elfsym.st_size = 0;
+ elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
+ elfsym.st_other = 0;
+ for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
+ {
+ o = section_from_elf_index (abfd, i);
+ if (o != NULL)
+ o->target_index = abfd->symcount;
+ elfsym.st_shndx = i;
+ if (! elf_link_output_sym (&finfo, (const char *) NULL,
+ &elfsym, o))
+ goto error_return;
+ }
+ }
+
+ /* Allocate some memory to hold information read in from the input
+ files. */
+ finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+ finfo.external_relocs = (PTR) bfd_malloc (max_external_reloc_size);
+ finfo.internal_relocs = ((Elf_Internal_Rela *)
+ bfd_malloc (max_internal_reloc_count
+ * sizeof (Elf_Internal_Rela)));
+ finfo.external_syms = ((Elf_External_Sym *)
+ bfd_malloc (max_sym_count
+ * sizeof (Elf_External_Sym)));
+ finfo.internal_syms = ((Elf_Internal_Sym *)
+ bfd_malloc (max_sym_count
+ * sizeof (Elf_Internal_Sym)));
+ finfo.indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
+ finfo.sections = ((asection **)
+ bfd_malloc (max_sym_count * sizeof (asection *)));
+ if ((finfo.contents == NULL && max_contents_size != 0)
+ || (finfo.external_relocs == NULL && max_external_reloc_size != 0)
+ || (finfo.internal_relocs == NULL && max_internal_reloc_count != 0)
+ || (finfo.external_syms == NULL && max_sym_count != 0)
+ || (finfo.internal_syms == NULL && max_sym_count != 0)
+ || (finfo.indices == NULL && max_sym_count != 0)
+ || (finfo.sections == NULL && max_sym_count != 0))
+ goto error_return;
+
+ /* Since ELF permits relocations to be against local symbols, we
+ must have the local symbols available when we do the relocations.
+ Since we would rather only read the local symbols once, and we
+ would rather not keep them in memory, we handle all the
+ relocations for a single input file at the same time.
+
+ Unfortunately, there is no way to know the total number of local
+ symbols until we have seen all of them, and the local symbol
+ indices precede the global symbol indices. This means that when
+ we are generating relocateable output, and we see a reloc against
+ a global symbol, we can not know the symbol index until we have
+ finished examining all the local symbols to see which ones we are
+ going to output. To deal with this, we keep the relocations in
+ memory, and don't output them until the end of the link. This is
+ an unfortunate waste of memory, but I don't see a good way around
+ it. Fortunately, it only happens when performing a relocateable
+ link, which is not the common case. FIXME: If keep_memory is set
+ we could write the relocs out and then read them again; I don't
+ know how bad the memory loss will be. */
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->next)
+ sub->output_has_begun = false;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order
+ && (bfd_get_flavour (p->u.indirect.section->owner)
+ == bfd_target_elf_flavour))
+ {
+ sub = p->u.indirect.section->owner;
+ if (! sub->output_has_begun)
+ {
+ if (! elf_link_input_bfd (&finfo, sub))
+ goto error_return;
+ sub->output_has_begun = true;
+ }
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! elf_reloc_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ else
+ {
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ }
+ }
+
+ /* That wrote out all the local symbols. Finish up the symbol table
+ with the global symbols. */
+
+ /* The sh_info field records the index of the first non local
+ symbol. */
+ symtab_hdr->sh_info = abfd->symcount;
+ if (dynamic)
+ elf_section_data (finfo.dynsym_sec->output_section)->this_hdr.sh_info = 1;
+
+ /* We get the global symbols from the hash table. */
+ eif.failed = false;
+ eif.finfo = &finfo;
+ elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym,
+ (PTR) &eif);
+ if (eif.failed)
+ return false;
+
+ /* Flush all symbols to the file. */
+ if (! elf_link_flush_output_syms (&finfo))
+ return false;
+
+ /* Now we know the size of the symtab section. */
+ off += symtab_hdr->sh_size;
+
+ /* Finish up and write out the symbol string table (.strtab)
+ section. */
+ symstrtab_hdr = &elf_tdata (abfd)->strtab_hdr;
+ /* sh_name was set in prep_headers. */
+ symstrtab_hdr->sh_type = SHT_STRTAB;
+ symstrtab_hdr->sh_flags = 0;
+ symstrtab_hdr->sh_addr = 0;
+ symstrtab_hdr->sh_size = _bfd_stringtab_size (finfo.symstrtab);
+ symstrtab_hdr->sh_entsize = 0;
+ symstrtab_hdr->sh_link = 0;
+ symstrtab_hdr->sh_info = 0;
+ /* sh_offset is set just below. */
+ symstrtab_hdr->sh_addralign = 1;
+
+ off = _bfd_elf_assign_file_position_for_section (symstrtab_hdr, off, true);
+ elf_tdata (abfd)->next_file_pos = off;
+
+ if (abfd->symcount > 0)
+ {
+ if (bfd_seek (abfd, symstrtab_hdr->sh_offset, SEEK_SET) != 0
+ || ! _bfd_stringtab_emit (abfd, finfo.symstrtab))
+ return false;
+ }
+
+ /* Adjust the relocs to have the correct symbol indices. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct elf_link_hash_entry **rel_hash;
+ Elf_Internal_Shdr *rel_hdr;
+
+ if ((o->flags & SEC_RELOC) == 0)
+ continue;
+
+ rel_hash = elf_section_data (o)->rel_hashes;
+ rel_hdr = &elf_section_data (o)->rel_hdr;
+ for (i = 0; i < o->reloc_count; i++, rel_hash++)
+ {
+ if (*rel_hash == NULL)
+ continue;
+
+ BFD_ASSERT ((*rel_hash)->indx >= 0);
+
+ if (rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
+ {
+ Elf_External_Rel *erel;
+ Elf_Internal_Rel irel;
+
+ erel = (Elf_External_Rel *) rel_hdr->contents + i;
+ elf_swap_reloc_in (abfd, erel, &irel);
+ irel.r_info = ELF_R_INFO ((*rel_hash)->indx,
+ ELF_R_TYPE (irel.r_info));
+ elf_swap_reloc_out (abfd, &irel, erel);
+ }
+ else
+ {
+ Elf_External_Rela *erela;
+ Elf_Internal_Rela irela;
+
+ BFD_ASSERT (rel_hdr->sh_entsize
+ == sizeof (Elf_External_Rela));
+
+ erela = (Elf_External_Rela *) rel_hdr->contents + i;
+ elf_swap_reloca_in (abfd, erela, &irela);
+ irela.r_info = ELF_R_INFO ((*rel_hash)->indx,
+ ELF_R_TYPE (irela.r_info));
+ elf_swap_reloca_out (abfd, &irela, erela);
+ }
+ }
+
+ /* Set the reloc_count field to 0 to prevent write_relocs from
+ trying to swap the relocs out itself. */
+ o->reloc_count = 0;
+ }
+
+ /* If we are linking against a dynamic object, or generating a
+ shared library, finish up the dynamic linking information. */
+ if (dynamic)
+ {
+ Elf_External_Dyn *dyncon, *dynconend;
+
+ /* Fix up .dynamic entries. */
+ o = bfd_get_section_by_name (dynobj, ".dynamic");
+ BFD_ASSERT (o != NULL);
+
+ dyncon = (Elf_External_Dyn *) o->contents;
+ dynconend = (Elf_External_Dyn *) (o->contents + o->_raw_size);
+ for (; dyncon < dynconend; dyncon++)
+ {
+ Elf_Internal_Dyn dyn;
+ const char *name;
+ unsigned int type;
+
+ elf_swap_dyn_in (dynobj, dyncon, &dyn);
+
+ switch (dyn.d_tag)
+ {
+ default:
+ break;
+
+ /* SVR4 linkers seem to set DT_INIT and DT_FINI based on
+ magic _init and _fini symbols. This is pretty ugly,
+ but we are compatible. */
+ case DT_INIT:
+ name = "_init";
+ goto get_sym;
+ case DT_FINI:
+ name = "_fini";
+ get_sym:
+ {
+ struct elf_link_hash_entry *h;
+
+ h = elf_link_hash_lookup (elf_hash_table (info), name,
+ false, false, true);
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ dyn.d_un.d_val = h->root.u.def.value;
+ o = h->root.u.def.section;
+ if (o->output_section != NULL)
+ dyn.d_un.d_val += (o->output_section->vma
+ + o->output_offset);
+ else
+ {
+ /* The symbol is imported from another shared
+ library and does not apply to this one. */
+ dyn.d_un.d_val = 0;
+ }
+
+ elf_swap_dyn_out (dynobj, &dyn, dyncon);
+ }
+ }
+ break;
+
+ case DT_HASH:
+ name = ".hash";
+ goto get_vma;
+ case DT_STRTAB:
+ name = ".dynstr";
+ goto get_vma;
+ case DT_SYMTAB:
+ name = ".dynsym";
+ get_vma:
+ o = bfd_get_section_by_name (abfd, name);
+ BFD_ASSERT (o != NULL);
+ dyn.d_un.d_ptr = o->vma;
+ elf_swap_dyn_out (dynobj, &dyn, dyncon);
+ break;
+
+ case DT_REL:
+ case DT_RELA:
+ case DT_RELSZ:
+ case DT_RELASZ:
+ if (dyn.d_tag == DT_REL || dyn.d_tag == DT_RELSZ)
+ type = SHT_REL;
+ else
+ type = SHT_RELA;
+ dyn.d_un.d_val = 0;
+ for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
+ {
+ Elf_Internal_Shdr *hdr;
+
+ hdr = elf_elfsections (abfd)[i];
+ if (hdr->sh_type == type
+ && (hdr->sh_flags & SHF_ALLOC) != 0)
+ {
+ if (dyn.d_tag == DT_RELSZ || dyn.d_tag == DT_RELASZ)
+ dyn.d_un.d_val += hdr->sh_size;
+ else
+ {
+ if (dyn.d_un.d_val == 0
+ || hdr->sh_addr < dyn.d_un.d_val)
+ dyn.d_un.d_val = hdr->sh_addr;
+ }
+ }
+ }
+ elf_swap_dyn_out (dynobj, &dyn, dyncon);
+ break;
+ }
+ }
+ }
+
+ /* If we have created any dynamic sections, then output them. */
+ if (dynobj != NULL)
+ {
+ if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
+ goto error_return;
+
+ for (o = dynobj->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_HAS_CONTENTS) == 0
+ || o->_raw_size == 0)
+ continue;
+ if ((o->flags & SEC_IN_MEMORY) == 0)
+ {
+ /* At this point, we are only interested in sections
+ created by elf_link_create_dynamic_sections. FIXME:
+ This test is fragile. */
+ continue;
+ }
+ if ((elf_section_data (o->output_section)->this_hdr.sh_type
+ != SHT_STRTAB)
+ || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)
+ {
+ if (! bfd_set_section_contents (abfd, o->output_section,
+ o->contents, o->output_offset,
+ o->_raw_size))
+ goto error_return;
+ }
+ else
+ {
+ file_ptr off;
+
+ /* The contents of the .dynstr section are actually in a
+ stringtab. */
+ off = elf_section_data (o->output_section)->this_hdr.sh_offset;
+ if (bfd_seek (abfd, off, SEEK_SET) != 0
+ || ! _bfd_stringtab_emit (abfd,
+ elf_hash_table (info)->dynstr))
+ goto error_return;
+ }
+ }
+ }
+
+ if (finfo.symstrtab != NULL)
+ _bfd_stringtab_free (finfo.symstrtab);
+ if (finfo.contents != NULL)
+ free (finfo.contents);
+ if (finfo.external_relocs != NULL)
+ free (finfo.external_relocs);
+ if (finfo.internal_relocs != NULL)
+ free (finfo.internal_relocs);
+ if (finfo.external_syms != NULL)
+ free (finfo.external_syms);
+ if (finfo.internal_syms != NULL)
+ free (finfo.internal_syms);
+ if (finfo.indices != NULL)
+ free (finfo.indices);
+ if (finfo.sections != NULL)
+ free (finfo.sections);
+ if (finfo.symbuf != NULL)
+ free (finfo.symbuf);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_RELOC) != 0
+ && elf_section_data (o)->rel_hashes != NULL)
+ free (elf_section_data (o)->rel_hashes);
+ }
+
+ elf_tdata (abfd)->linker = true;
+
+ return true;
+
+ error_return:
+ if (finfo.symstrtab != NULL)
+ _bfd_stringtab_free (finfo.symstrtab);
+ if (finfo.contents != NULL)
+ free (finfo.contents);
+ if (finfo.external_relocs != NULL)
+ free (finfo.external_relocs);
+ if (finfo.internal_relocs != NULL)
+ free (finfo.internal_relocs);
+ if (finfo.external_syms != NULL)
+ free (finfo.external_syms);
+ if (finfo.internal_syms != NULL)
+ free (finfo.internal_syms);
+ if (finfo.indices != NULL)
+ free (finfo.indices);
+ if (finfo.sections != NULL)
+ free (finfo.sections);
+ if (finfo.symbuf != NULL)
+ free (finfo.symbuf);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_RELOC) != 0
+ && elf_section_data (o)->rel_hashes != NULL)
+ free (elf_section_data (o)->rel_hashes);
+ }
+
+ return false;
+}
+
+/* Add a symbol to the output symbol table. */
+
+static boolean
+elf_link_output_sym (finfo, name, elfsym, input_sec)
+ struct elf_final_link_info *finfo;
+ const char *name;
+ Elf_Internal_Sym *elfsym;
+ asection *input_sec;
+{
+ boolean (*output_symbol_hook) PARAMS ((bfd *,
+ struct bfd_link_info *info,
+ const char *,
+ Elf_Internal_Sym *,
+ asection *));
+
+ output_symbol_hook = get_elf_backend_data (finfo->output_bfd)->
+ elf_backend_link_output_symbol_hook;
+ if (output_symbol_hook != NULL)
+ {
+ if (! ((*output_symbol_hook)
+ (finfo->output_bfd, finfo->info, name, elfsym, input_sec)))
+ return false;
+ }
+
+ if (name == (const char *) NULL || *name == '\0')
+ elfsym->st_name = 0;
+ else
+ {
+ elfsym->st_name = (unsigned long) _bfd_stringtab_add (finfo->symstrtab,
+ name, true,
+ false);
+ if (elfsym->st_name == (unsigned long) -1)
+ return false;
+ }
+
+ if (finfo->symbuf_count >= finfo->symbuf_size)
+ {
+ if (! elf_link_flush_output_syms (finfo))
+ return false;
+ }
+
+ elf_swap_symbol_out (finfo->output_bfd, elfsym,
+ (PTR) (finfo->symbuf + finfo->symbuf_count));
+ ++finfo->symbuf_count;
+
+ ++finfo->output_bfd->symcount;
+
+ return true;
+}
+
+/* Flush the output symbols to the file. */
+
+static boolean
+elf_link_flush_output_syms (finfo)
+ struct elf_final_link_info *finfo;
+{
+ if (finfo->symbuf_count > 0)
+ {
+ Elf_Internal_Shdr *symtab;
+
+ symtab = &elf_tdata (finfo->output_bfd)->symtab_hdr;
+
+ if (bfd_seek (finfo->output_bfd, symtab->sh_offset + symtab->sh_size,
+ SEEK_SET) != 0
+ || (bfd_write ((PTR) finfo->symbuf, finfo->symbuf_count,
+ sizeof (Elf_External_Sym), finfo->output_bfd)
+ != finfo->symbuf_count * sizeof (Elf_External_Sym)))
+ return false;
+
+ symtab->sh_size += finfo->symbuf_count * sizeof (Elf_External_Sym);
+
+ finfo->symbuf_count = 0;
+ }
+
+ return true;
+}
+
+/* Add an external symbol to the symbol table. This is called from
+ the hash table traversal routine. */
+
+static boolean
+elf_link_output_extsym (h, data)
+ struct elf_link_hash_entry *h;
+ PTR data;
+{
+ struct elf_finfo_failed *eif = (struct elf_finfo_failed *) data;
+ struct elf_final_link_info *finfo = eif->finfo;
+ boolean strip;
+ Elf_Internal_Sym sym;
+ asection *input_sec;
+
+ /* If we are not creating a shared library, and this symbol is
+ referenced by a shared library but is not defined anywhere, then
+ warn that it is undefined. If we do not do this, the runtime
+ linker will complain that the symbol is undefined when the
+ program is run. We don't have to worry about symbols that are
+ referenced by regular files, because we will already have issued
+ warnings for them. */
+ if (! finfo->info->relocateable
+ && ! finfo->info->shared
+ && h->root.type == bfd_link_hash_undefined
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+ {
+ if (! ((*finfo->info->callbacks->undefined_symbol)
+ (finfo->info, h->root.root.string, h->root.u.undef.abfd,
+ (asection *) NULL, 0)))
+ {
+ eif->failed = true;
+ return false;
+ }
+ }
+
+ /* We don't want to output symbols that have never been mentioned by
+ a regular file, or that we have been told to strip. However, if
+ h->indx is set to -2, the symbol is used by a reloc and we must
+ output it. */
+ if (h->indx == -2)
+ strip = false;
+ else if (((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0
+ || (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) != 0)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) == 0)
+ strip = true;
+ else 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))
+ strip = true;
+ else
+ strip = false;
+
+ /* If we're stripping it, and it's not a dynamic symbol, there's
+ nothing else to do. */
+ if (strip && h->dynindx == -1)
+ return true;
+
+ sym.st_value = 0;
+ sym.st_size = h->size;
+ sym.st_other = 0;
+ if (h->root.type == bfd_link_hash_undefweak
+ || h->root.type == bfd_link_hash_defweak)
+ sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
+ else
+ sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
+
+ switch (h->root.type)
+ {
+ default:
+ case bfd_link_hash_new:
+ abort ();
+ return false;
+
+ case bfd_link_hash_undefined:
+ input_sec = bfd_und_section_ptr;
+ sym.st_shndx = SHN_UNDEF;
+ break;
+
+ case bfd_link_hash_undefweak:
+ input_sec = bfd_und_section_ptr;
+ sym.st_shndx = SHN_UNDEF;
+ break;
+
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ {
+ input_sec = h->root.u.def.section;
+ if (input_sec->output_section != NULL)
+ {
+ sym.st_shndx =
+ _bfd_elf_section_from_bfd_section (finfo->output_bfd,
+ input_sec->output_section);
+ if (sym.st_shndx == (unsigned short) -1)
+ {
+ eif->failed = true;
+ return false;
+ }
+
+ /* ELF symbols in relocateable files are section relative,
+ but in nonrelocateable files they are virtual
+ addresses. */
+ sym.st_value = h->root.u.def.value + input_sec->output_offset;
+ if (! finfo->info->relocateable)
+ sym.st_value += input_sec->output_section->vma;
+ }
+ else
+ {
+ BFD_ASSERT ((bfd_get_flavour (input_sec->owner)
+ == bfd_target_elf_flavour)
+ && elf_elfheader (input_sec->owner)->e_type == ET_DYN);
+ sym.st_shndx = SHN_UNDEF;
+ input_sec = bfd_und_section_ptr;
+ }
+ }
+ break;
+
+ case bfd_link_hash_common:
+ input_sec = bfd_com_section_ptr;
+ sym.st_shndx = SHN_COMMON;
+ sym.st_value = 1 << h->root.u.c.p->alignment_power;
+ break;
+
+ case bfd_link_hash_indirect:
+ case bfd_link_hash_warning:
+ /* We can't represent these symbols in ELF. A warning symbol
+ may have come from a .gnu.warning.SYMBOL section anyhow. We
+ just put the target symbol in the hash table. If the target
+ symbol does not really exist, don't do anything. */
+ if (h->root.u.i.link->type == bfd_link_hash_new)
+ return true;
+ return (elf_link_output_extsym
+ ((struct elf_link_hash_entry *) h->root.u.i.link, data));
+ }
+
+ /* If this symbol should be put in the .dynsym section, then put it
+ there now. We have already know the symbol index. We also fill
+ in the entry in the .hash section. */
+ if (h->dynindx != -1
+ && elf_hash_table (finfo->info)->dynamic_sections_created)
+ {
+ struct elf_backend_data *bed;
+ size_t bucketcount;
+ size_t bucket;
+ bfd_byte *bucketpos;
+ bfd_vma chain;
+
+ sym.st_name = h->dynstr_index;
+
+ /* Give the processor backend a chance to tweak the symbol
+ value, and also to finish up anything that needs to be done
+ for this symbol. */
+ bed = get_elf_backend_data (finfo->output_bfd);
+ if (! ((*bed->elf_backend_finish_dynamic_symbol)
+ (finfo->output_bfd, finfo->info, h, &sym)))
+ {
+ eif->failed = true;
+ return false;
+ }
+
+ elf_swap_symbol_out (finfo->output_bfd, &sym,
+ (PTR) (((Elf_External_Sym *)
+ finfo->dynsym_sec->contents)
+ + h->dynindx));
+
+ bucketcount = elf_hash_table (finfo->info)->bucketcount;
+ bucket = (bfd_elf_hash ((const unsigned char *) h->root.root.string)
+ % bucketcount);
+ bucketpos = ((bfd_byte *) finfo->hash_sec->contents
+ + (bucket + 2) * (ARCH_SIZE / 8));
+ chain = get_word (finfo->output_bfd, bucketpos);
+ put_word (finfo->output_bfd, h->dynindx, bucketpos);
+ put_word (finfo->output_bfd, chain,
+ ((bfd_byte *) finfo->hash_sec->contents
+ + (bucketcount + 2 + h->dynindx) * (ARCH_SIZE / 8)));
+ }
+
+ /* If we're stripping it, then it was just a dynamic symbol, and
+ there's nothing else to do. */
+ if (strip)
+ return true;
+
+ h->indx = finfo->output_bfd->symcount;
+
+ if (! elf_link_output_sym (finfo, h->root.root.string, &sym, input_sec))
+ {
+ eif->failed = true;
+ return false;
+ }
+
+ return true;
+}
+
+/* Link an input file into the linker output file. This function
+ handles all the sections and relocations of the input file at once.
+ This is so that we only have to read the local symbols once, and
+ don't have to keep them in memory. */
+
+static boolean
+elf_link_input_bfd (finfo, input_bfd)
+ struct elf_final_link_info *finfo;
+ bfd *input_bfd;
+{
+ boolean (*relocate_section) PARAMS ((bfd *, struct bfd_link_info *,
+ bfd *, asection *, bfd_byte *,
+ Elf_Internal_Rela *,
+ Elf_Internal_Sym *, asection **));
+ bfd *output_bfd;
+ Elf_Internal_Shdr *symtab_hdr;
+ size_t locsymcount;
+ size_t extsymoff;
+ Elf_External_Sym *esym;
+ Elf_External_Sym *esymend;
+ Elf_Internal_Sym *isym;
+ long *pindex;
+ asection **ppsection;
+ asection *o;
+
+ output_bfd = finfo->output_bfd;
+ relocate_section =
+ get_elf_backend_data (output_bfd)->elf_backend_relocate_section;
+
+ /* If this is a dynamic object, we don't want to do anything here:
+ we don't want the local symbols, and we don't want the section
+ contents. */
+ if (elf_elfheader (input_bfd)->e_type == ET_DYN)
+ return true;
+
+ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
+ if (elf_bad_symtab (input_bfd))
+ {
+ locsymcount = symtab_hdr->sh_size / sizeof (Elf_External_Sym);
+ extsymoff = 0;
+ }
+ else
+ {
+ locsymcount = symtab_hdr->sh_info;
+ extsymoff = symtab_hdr->sh_info;
+ }
+
+ /* Read the local symbols. */
+ if (locsymcount > 0
+ && (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0
+ || (bfd_read (finfo->external_syms, sizeof (Elf_External_Sym),
+ locsymcount, input_bfd)
+ != locsymcount * sizeof (Elf_External_Sym))))
+ return false;
+
+ /* Swap in the local symbols and write out the ones which we know
+ are going into the output file. */
+ esym = finfo->external_syms;
+ esymend = esym + locsymcount;
+ isym = finfo->internal_syms;
+ pindex = finfo->indices;
+ ppsection = finfo->sections;
+ for (; esym < esymend; esym++, isym++, pindex++, ppsection++)
+ {
+ asection *isec;
+ const char *name;
+ Elf_Internal_Sym osym;
+
+ elf_swap_symbol_in (input_bfd, esym, isym);
+ *pindex = -1;
+
+ if (elf_bad_symtab (input_bfd))
+ {
+ if (ELF_ST_BIND (isym->st_info) != STB_LOCAL)
+ {
+ *ppsection = NULL;
+ continue;
+ }
+ }
+
+ if (isym->st_shndx == SHN_UNDEF)
+ isec = bfd_und_section_ptr;
+ else if (isym->st_shndx > 0 && isym->st_shndx < SHN_LORESERVE)
+ isec = section_from_elf_index (input_bfd, isym->st_shndx);
+ else if (isym->st_shndx == SHN_ABS)
+ isec = bfd_abs_section_ptr;
+ else if (isym->st_shndx == SHN_COMMON)
+ isec = bfd_com_section_ptr;
+ else
+ {
+ /* Who knows? */
+ isec = NULL;
+ }
+
+ *ppsection = isec;
+
+ /* Don't output the first, undefined, symbol. */
+ if (esym == finfo->external_syms)
+ continue;
+
+ /* If we are stripping all symbols, we don't want to output this
+ one. */
+ if (finfo->info->strip == strip_all)
+ continue;
+
+ /* We never output section symbols. Instead, we use the section
+ symbol of the corresponding section in the output file. */
+ if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+ continue;
+
+ /* If we are discarding all local symbols, we don't want to
+ output this one. If we are generating a relocateable output
+ file, then some of the local symbols may be required by
+ relocs; we output them below as we discover that they are
+ needed. */
+ if (finfo->info->discard == discard_all)
+ continue;
+
+ /* Get the name of the symbol. */
+ name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link,
+ isym->st_name);
+ if (name == NULL)
+ return false;
+
+ /* See if we are discarding symbols with this name. */
+ if ((finfo->info->strip == strip_some
+ && (bfd_hash_lookup (finfo->info->keep_hash, name, false, false)
+ == NULL))
+ || (finfo->info->discard == discard_l
+ && strncmp (name, finfo->info->lprefix,
+ finfo->info->lprefix_len) == 0))
+ continue;
+
+ /* If we get here, we are going to output this symbol. */
+
+ osym = *isym;
+
+ /* Adjust the section index for the output file. */
+ osym.st_shndx = _bfd_elf_section_from_bfd_section (output_bfd,
+ isec->output_section);
+ if (osym.st_shndx == (unsigned short) -1)
+ return false;
+
+ *pindex = output_bfd->symcount;
+
+ /* ELF symbols in relocateable files are section relative, but
+ in executable files they are virtual addresses. Note that
+ this code assumes that all ELF sections have an associated
+ BFD section with a reasonable value for output_offset; below
+ we assume that they also have a reasonable value for
+ output_section. Any special sections must be set up to meet
+ these requirements. */
+ osym.st_value += isec->output_offset;
+ if (! finfo->info->relocateable)
+ osym.st_value += isec->output_section->vma;
+
+ if (! elf_link_output_sym (finfo, name, &osym, isec))
+ return false;
+ }
+
+ /* Relocate the contents of each section. */
+ for (o = input_bfd->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_HAS_CONTENTS) == 0)
+ continue;
+
+ if ((o->flags & SEC_IN_MEMORY) != 0
+ && input_bfd == elf_hash_table (finfo->info)->dynobj)
+ {
+ /* Section was created by elf_link_create_dynamic_sections.
+ FIXME: This test is fragile. */
+ continue;
+ }
+
+ /* Read the contents of the section. */
+ if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
+ (file_ptr) 0, o->_raw_size))
+ return false;
+
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ Elf_Internal_Rela *internal_relocs;
+
+ /* Get the swapped relocs. */
+ internal_relocs = elf_link_read_relocs (input_bfd, o,
+ finfo->external_relocs,
+ finfo->internal_relocs,
+ false);
+ if (internal_relocs == NULL
+ && o->reloc_count > 0)
+ return false;
+
+ /* Relocate the section by invoking a back end routine.
+
+ The back end routine is responsible for adjusting the
+ section contents as necessary, and (if using Rela relocs
+ and generating a relocateable output file) adjusting the
+ reloc addend as necessary.
+
+ The back end routine does not have to worry about setting
+ the reloc address or the reloc symbol index.
+
+ The back end routine is given a pointer to the swapped in
+ internal symbols, and can access the hash table entries
+ for the external symbols via elf_sym_hashes (input_bfd).
+
+ When generating relocateable output, the back end routine
+ must handle STB_LOCAL/STT_SECTION symbols specially. The
+ output symbol is going to be a section symbol
+ corresponding to the output section, which will require
+ the addend to be adjusted. */
+
+ if (! (*relocate_section) (output_bfd, finfo->info,
+ input_bfd, o,
+ finfo->contents,
+ internal_relocs,
+ finfo->internal_syms,
+ finfo->sections))
+ return false;
+
+ if (finfo->info->relocateable)
+ {
+ Elf_Internal_Rela *irela;
+ Elf_Internal_Rela *irelaend;
+ struct elf_link_hash_entry **rel_hash;
+ Elf_Internal_Shdr *input_rel_hdr;
+ Elf_Internal_Shdr *output_rel_hdr;
+
+ /* Adjust the reloc addresses and symbol indices. */
+
+ irela = internal_relocs;
+ irelaend = irela + o->reloc_count;
+ rel_hash = (elf_section_data (o->output_section)->rel_hashes
+ + o->output_section->reloc_count);
+ for (; irela < irelaend; irela++, rel_hash++)
+ {
+ unsigned long r_symndx;
+ Elf_Internal_Sym *isym;
+ asection *sec;
+
+ irela->r_offset += o->output_offset;
+
+ r_symndx = ELF_R_SYM (irela->r_info);
+
+ if (r_symndx == 0)
+ continue;
+
+ if (r_symndx >= locsymcount
+ || (elf_bad_symtab (input_bfd)
+ && finfo->sections[r_symndx] == NULL))
+ {
+ long indx;
+
+ /* This is a reloc against a global symbol. We
+ have not yet output all the local symbols, so
+ we do not know the symbol index of any global
+ symbol. We set the rel_hash entry for this
+ reloc to point to the global hash table entry
+ for this symbol. The symbol index is then
+ set at the end of elf_bfd_final_link. */
+ indx = r_symndx - extsymoff;
+ *rel_hash = elf_sym_hashes (input_bfd)[indx];
+
+ /* Setting the index to -2 tells
+ elf_link_output_extsym that this symbol is
+ used by a reloc. */
+ BFD_ASSERT ((*rel_hash)->indx < 0);
+ (*rel_hash)->indx = -2;
+
+ continue;
+ }
+
+ /* This is a reloc against a local symbol. */
+
+ *rel_hash = NULL;
+ isym = finfo->internal_syms + r_symndx;
+ sec = finfo->sections[r_symndx];
+ if (ELF_ST_TYPE (isym->st_info) == STT_SECTION)
+ {
+ /* I suppose the backend ought to fill in the
+ section of any STT_SECTION symbol against a
+ processor specific section. */
+ if (sec != NULL && bfd_is_abs_section (sec))
+ r_symndx = 0;
+ else if (sec == NULL || sec->owner == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ else
+ {
+ r_symndx = sec->output_section->target_index;
+ BFD_ASSERT (r_symndx != 0);
+ }
+ }
+ else
+ {
+ if (finfo->indices[r_symndx] == -1)
+ {
+ unsigned long link;
+ const char *name;
+ asection *osec;
+
+ if (finfo->info->strip == strip_all)
+ {
+ /* You can't do ld -r -s. */
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ /* This symbol was skipped earlier, but
+ since it is needed by a reloc, we
+ must output it now. */
+ link = symtab_hdr->sh_link;
+ name = bfd_elf_string_from_elf_section (input_bfd,
+ link,
+ isym->st_name);
+ if (name == NULL)
+ return false;
+
+ osec = sec->output_section;
+ isym->st_shndx =
+ _bfd_elf_section_from_bfd_section (output_bfd,
+ osec);
+ if (isym->st_shndx == (unsigned short) -1)
+ return false;
+
+ isym->st_value += sec->output_offset;
+ if (! finfo->info->relocateable)
+ isym->st_value += osec->vma;
+
+ finfo->indices[r_symndx] = output_bfd->symcount;
+
+ if (! elf_link_output_sym (finfo, name, isym, sec))
+ return false;
+ }
+
+ r_symndx = finfo->indices[r_symndx];
+ }
+
+ irela->r_info = ELF_R_INFO (r_symndx,
+ ELF_R_TYPE (irela->r_info));
+ }
+
+ /* Swap out the relocs. */
+ input_rel_hdr = &elf_section_data (o)->rel_hdr;
+ output_rel_hdr = &elf_section_data (o->output_section)->rel_hdr;
+ BFD_ASSERT (output_rel_hdr->sh_entsize
+ == input_rel_hdr->sh_entsize);
+ irela = internal_relocs;
+ irelaend = irela + o->reloc_count;
+ if (input_rel_hdr->sh_entsize == sizeof (Elf_External_Rel))
+ {
+ Elf_External_Rel *erel;
+
+ erel = ((Elf_External_Rel *) output_rel_hdr->contents
+ + o->output_section->reloc_count);
+ for (; irela < irelaend; irela++, erel++)
+ {
+ Elf_Internal_Rel irel;
+
+ irel.r_offset = irela->r_offset;
+ irel.r_info = irela->r_info;
+ BFD_ASSERT (irela->r_addend == 0);
+ elf_swap_reloc_out (output_bfd, &irel, erel);
+ }
+ }
+ else
+ {
+ Elf_External_Rela *erela;
+
+ BFD_ASSERT (input_rel_hdr->sh_entsize
+ == sizeof (Elf_External_Rela));
+ erela = ((Elf_External_Rela *) output_rel_hdr->contents
+ + o->output_section->reloc_count);
+ for (; irela < irelaend; irela++, erela++)
+ elf_swap_reloca_out (output_bfd, irela, erela);
+ }
+
+ o->output_section->reloc_count += o->reloc_count;
+ }
+ }
+
+ /* Write out the modified section contents. */
+ if (! bfd_set_section_contents (output_bfd, o->output_section,
+ finfo->contents, o->output_offset,
+ (o->_cooked_size != 0
+ ? o->_cooked_size
+ : o->_raw_size)))
+ return false;
+ }
+
+ return true;
+}
+
+/* Generate a reloc when linking an ELF 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
+elf_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;
+{
+ reloc_howto_type *howto;
+ long indx;
+ bfd_vma offset;
+ bfd_vma addend;
+ struct elf_link_hash_entry **rel_hash_ptr;
+ Elf_Internal_Shdr *rel_hdr;
+
+ howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
+ if (howto == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ addend = link_order->u.reloc.p->addend;
+
+ /* Figure out the symbol index. */
+ rel_hash_ptr = (elf_section_data (output_section)->rel_hashes
+ + output_section->reloc_count);
+ if (link_order->type == bfd_section_reloc_link_order)
+ {
+ indx = link_order->u.reloc.p->u.section->target_index;
+ BFD_ASSERT (indx != 0);
+ *rel_hash_ptr = NULL;
+ }
+ else
+ {
+ struct elf_link_hash_entry *h;
+
+ /* Treat a reloc against a defined symbol as though it were
+ actually against the section. */
+ h = ((struct elf_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, info,
+ link_order->u.reloc.p->u.name,
+ false, false, true));
+ if (h != NULL
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ {
+ asection *section;
+
+ section = h->root.u.def.section;
+ indx = section->output_section->target_index;
+ *rel_hash_ptr = NULL;
+ /* It seems that we ought to add the symbol value to the
+ addend here, but in practice it has already been added
+ because it was passed to constructor_callback. */
+ addend += section->output_section->vma + section->output_offset;
+ }
+ else if (h != NULL)
+ {
+ /* Setting the index to -2 tells elf_link_output_extsym that
+ this symbol is used by a reloc. */
+ h->indx = -2;
+ *rel_hash_ptr = h;
+ indx = 0;
+ }
+ else
+ {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, link_order->u.reloc.p->u.name, (bfd *) NULL,
+ (asection *) NULL, (bfd_vma) 0)))
+ return false;
+ indx = 0;
+ }
+ }
+
+ /* If this is an inplace reloc, we must write the addend into the
+ object file. */
+ if (howto->partial_inplace && addend != 0)
+ {
+ bfd_size_type size;
+ bfd_reloc_status_type rstat;
+ bfd_byte *buf;
+ boolean ok;
+
+ size = bfd_get_reloc_size (howto);
+ buf = (bfd_byte *) bfd_zmalloc (size);
+ if (buf == (bfd_byte *) NULL)
+ return false;
+ rstat = _bfd_relocate_contents (howto, output_bfd, 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),
+ howto->name, 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;
+ }
+
+ /* The address of a reloc is relative to the section in a
+ relocateable file, and is a virtual address in an executable
+ file. */
+ offset = link_order->offset;
+ if (! info->relocateable)
+ offset += output_section->vma;
+
+ rel_hdr = &elf_section_data (output_section)->rel_hdr;
+
+ if (rel_hdr->sh_type == SHT_REL)
+ {
+ Elf_Internal_Rel irel;
+ Elf_External_Rel *erel;
+
+ irel.r_offset = offset;
+ irel.r_info = ELF_R_INFO (indx, howto->type);
+ erel = ((Elf_External_Rel *) rel_hdr->contents
+ + output_section->reloc_count);
+ elf_swap_reloc_out (output_bfd, &irel, erel);
+ }
+ else
+ {
+ Elf_Internal_Rela irela;
+ Elf_External_Rela *erela;
+
+ irela.r_offset = offset;
+ irela.r_info = ELF_R_INFO (indx, howto->type);
+ irela.r_addend = addend;
+ erela = ((Elf_External_Rela *) rel_hdr->contents
+ + output_section->reloc_count);
+ elf_swap_reloca_out (output_bfd, &irela, erela);
+ }
+
+ ++output_section->reloc_count;
+
+ return true;
+}
+
+
+/* Allocate a pointer to live in a linker created section. */
+
+boolean
+elf_create_pointer_linker_section (abfd, info, lsect, h, rel)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ elf_linker_section_t *lsect;
+ struct elf_link_hash_entry *h;
+ const Elf_Internal_Rela *rel;
+{
+ elf_linker_section_pointers_t **ptr_linker_section_ptr = NULL;
+ elf_linker_section_pointers_t *linker_section_ptr;
+ unsigned long r_symndx = ELF_R_SYM (rel->r_info);;
+
+ BFD_ASSERT (lsect != NULL);
+
+ /* Is this a global symbol? */
+ if (h != NULL)
+ {
+ /* Has this symbol already been allocated, if so, our work is done */
+ if (_bfd_elf_find_pointer_linker_section (h->linker_section_pointer,
+ rel->r_addend,
+ lsect->which))
+ return true;
+
+ ptr_linker_section_ptr = &h->linker_section_pointer;
+ /* Make sure this symbol is output as a dynamic symbol. */
+ if (h->dynindx == -1)
+ {
+ if (! elf_link_record_dynamic_symbol (info, h))
+ return false;
+ }
+
+ if (lsect->rel_section)
+ lsect->rel_section->_raw_size += sizeof (Elf_External_Rela);
+ }
+
+ else /* Allocation of a pointer to a local symbol */
+ {
+ elf_linker_section_pointers_t **ptr = elf_local_ptr_offsets (abfd);
+
+ /* Allocate a table to hold the local symbols if first time */
+ if (!ptr)
+ {
+ int num_symbols = elf_tdata (abfd)->symtab_hdr.sh_info;
+ register unsigned int i;
+
+ ptr = (elf_linker_section_pointers_t **)
+ bfd_alloc (abfd, num_symbols * sizeof (elf_linker_section_pointers_t *));
+
+ if (!ptr)
+ return false;
+
+ elf_local_ptr_offsets (abfd) = ptr;
+ for (i = 0; i < num_symbols; i++)
+ ptr[i] = (elf_linker_section_pointers_t *)0;
+ }
+
+ /* Has this symbol already been allocated, if so, our work is done */
+ if (_bfd_elf_find_pointer_linker_section (ptr[r_symndx],
+ rel->r_addend,
+ lsect->which))
+ return true;
+
+ ptr_linker_section_ptr = &ptr[r_symndx];
+
+ if (info->shared)
+ {
+ /* If we are generating a shared object, we need to
+ output a R_<xxx>_RELATIVE reloc so that the
+ dynamic linker can adjust this GOT entry. */
+ BFD_ASSERT (lsect->rel_section != NULL);
+ lsect->rel_section->_raw_size += sizeof (Elf_External_Rela);
+ }
+ }
+
+ /* Allocate space for a pointer in the linker section, and allocate a new pointer record
+ from internal memory. */
+ BFD_ASSERT (ptr_linker_section_ptr != NULL);
+ linker_section_ptr = (elf_linker_section_pointers_t *)
+ bfd_alloc (abfd, sizeof (elf_linker_section_pointers_t));
+
+ if (!linker_section_ptr)
+ return false;
+
+ linker_section_ptr->next = *ptr_linker_section_ptr;
+ linker_section_ptr->addend = rel->r_addend;
+ linker_section_ptr->which = lsect->which;
+ linker_section_ptr->written_address_p = false;
+ *ptr_linker_section_ptr = linker_section_ptr;
+
+ if (lsect->hole_size && lsect->hole_offset < lsect->max_hole_offset)
+ {
+ linker_section_ptr->offset = lsect->section->_raw_size - lsect->hole_size;
+ lsect->hole_offset += ARCH_SIZE / 8;
+ lsect->sym_offset += ARCH_SIZE / 8;
+ if (lsect->sym_hash) /* Bump up symbol value if needed */
+ lsect->sym_hash->root.u.def.value += ARCH_SIZE / 8;
+ }
+ else
+ linker_section_ptr->offset = lsect->section->_raw_size;
+
+ lsect->section->_raw_size += ARCH_SIZE / 8;
+
+#ifdef DEBUG
+ fprintf (stderr, "Create pointer in linker section %s, offset = %ld, section size = %ld\n",
+ lsect->name, (long)linker_section_ptr->offset, (long)lsect->section->_raw_size);
+#endif
+
+ return true;
+}
+
+
+#if ARCH_SIZE==64
+#define bfd_put_ptr(BFD,VAL,ADDR) bfd_put_64 (BFD, VAL, ADDR)
+#endif
+#if ARCH_SIZE==32
+#define bfd_put_ptr(BFD,VAL,ADDR) bfd_put_32 (BFD, VAL, ADDR)
+#endif
+
+/* Fill in the address for a pointer generated in alinker section. */
+
+bfd_vma
+elf_finish_pointer_linker_section (output_bfd, input_bfd, info, lsect, h, relocation, rel, relative_reloc)
+ bfd *output_bfd;
+ bfd *input_bfd;
+ struct bfd_link_info *info;
+ elf_linker_section_t *lsect;
+ struct elf_link_hash_entry *h;
+ bfd_vma relocation;
+ const Elf_Internal_Rela *rel;
+ int relative_reloc;
+{
+ elf_linker_section_pointers_t *linker_section_ptr;
+
+ BFD_ASSERT (lsect != NULL);
+
+ if (h != NULL) /* global symbol */
+ {
+ linker_section_ptr = _bfd_elf_find_pointer_linker_section (h->linker_section_pointer,
+ rel->r_addend,
+ lsect->which);
+
+ BFD_ASSERT (linker_section_ptr != NULL);
+
+ if (! elf_hash_table (info)->dynamic_sections_created
+ || (info->shared
+ && info->symbolic
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ {
+ /* This is actually a static link, or it is a
+ -Bsymbolic link and the symbol is defined
+ locally. We must initialize this entry in the
+ global section.
+
+ When doing a dynamic link, we create a .rela.<xxx>
+ relocation entry to initialize the value. This
+ is done in the finish_dynamic_symbol routine. */
+ if (!linker_section_ptr->written_address_p)
+ {
+ linker_section_ptr->written_address_p = true;
+ bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend,
+ lsect->section->contents + linker_section_ptr->offset);
+ }
+ }
+ }
+ else /* local symbol */
+ {
+ unsigned long r_symndx = ELF_R_SYM (rel->r_info);
+ BFD_ASSERT (elf_local_ptr_offsets (input_bfd) != NULL);
+ BFD_ASSERT (elf_local_ptr_offsets (input_bfd)[r_symndx] != NULL);
+ linker_section_ptr = _bfd_elf_find_pointer_linker_section (elf_local_ptr_offsets (input_bfd)[r_symndx],
+ rel->r_addend,
+ lsect->which);
+
+ BFD_ASSERT (linker_section_ptr != NULL);
+
+ /* Write out pointer if it hasn't been rewritten out before */
+ if (!linker_section_ptr->written_address_p)
+ {
+ linker_section_ptr->written_address_p = true;
+ bfd_put_ptr (output_bfd, relocation + linker_section_ptr->addend,
+ lsect->section->contents + linker_section_ptr->offset);
+
+ if (info->shared)
+ {
+ asection *srel = lsect->rel_section;
+ Elf_Internal_Rela outrel;
+
+ /* We need to generate a relative reloc for the dynamic linker. */
+ if (!srel)
+ lsect->rel_section = srel = bfd_get_section_by_name (elf_hash_table (info)->dynobj,
+ lsect->rel_name);
+
+ BFD_ASSERT (srel != NULL);
+
+ outrel.r_offset = (lsect->section->output_section->vma
+ + lsect->section->output_offset
+ + linker_section_ptr->offset);
+ outrel.r_info = ELF_R_INFO (0, relative_reloc);
+ outrel.r_addend = 0;
+ elf_swap_reloca_out (output_bfd, &outrel,
+ (((Elf_External_Rela *)
+ lsect->section->contents)
+ + lsect->section->reloc_count));
+ ++lsect->section->reloc_count;
+ }
+ }
+ }
+
+ relocation = (lsect->section->output_offset
+ + linker_section_ptr->offset
+ - lsect->hole_offset
+ - lsect->sym_offset);
+
+#ifdef DEBUG
+ fprintf (stderr, "Finish pointer in linker section %s, offset = %ld (0x%lx)\n",
+ lsect->name, (long)relocation, (long)relocation);
+#endif
+
+ /* Subtract out the addend, because it will get added back in by the normal
+ processing. */
+ return relocation - linker_section_ptr->addend;
+}
diff --git a/contrib/gdb/bfd/elfxx-target.h b/contrib/gdb/bfd/elfxx-target.h
new file mode 100644
index 0000000..f2c0c32
--- /dev/null
+++ b/contrib/gdb/bfd/elfxx-target.h
@@ -0,0 +1,450 @@
+/* Target definitions for NN-bit ELF
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* 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. Every BFD points to a target structure
+ with its "xvec" member.
+
+ There are two such structures here: one for big-endian machines and
+ one for little-endian machines. */
+
+#define bfd_elfNN_close_and_cleanup _bfd_generic_close_and_cleanup
+#define bfd_elfNN_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#ifndef bfd_elfNN_get_section_contents
+#define bfd_elfNN_get_section_contents _bfd_generic_get_section_contents
+#endif
+
+#define bfd_elfNN_canonicalize_dynamic_symtab _bfd_elf_canonicalize_dynamic_symtab
+#define bfd_elfNN_canonicalize_reloc _bfd_elf_canonicalize_reloc
+#ifndef bfd_elfNN_find_nearest_line
+#define bfd_elfNN_find_nearest_line _bfd_elf_find_nearest_line
+#endif
+#define bfd_elfNN_read_minisymbols _bfd_elf_read_minisymbols
+#define bfd_elfNN_minisymbol_to_symbol _bfd_elf_minisymbol_to_symbol
+#define bfd_elfNN_get_dynamic_symtab_upper_bound _bfd_elf_get_dynamic_symtab_upper_bound
+#define bfd_elfNN_get_lineno _bfd_elf_get_lineno
+#define bfd_elfNN_get_reloc_upper_bound _bfd_elf_get_reloc_upper_bound
+#define bfd_elfNN_get_symbol_info _bfd_elf_get_symbol_info
+#define bfd_elfNN_get_symtab _bfd_elf_get_symtab
+#define bfd_elfNN_get_symtab_upper_bound _bfd_elf_get_symtab_upper_bound
+#if 0 /* done in elf-bfd.h */
+#define bfd_elfNN_link_record_dynamic_symbol _bfd_elf_link_record_dynamic_symbol
+#endif
+#define bfd_elfNN_make_empty_symbol _bfd_elf_make_empty_symbol
+#define bfd_elfNN_new_section_hook _bfd_elf_new_section_hook
+#define bfd_elfNN_set_arch_mach _bfd_elf_set_arch_mach
+#ifndef bfd_elfNN_set_section_contents
+#define bfd_elfNN_set_section_contents _bfd_elf_set_section_contents
+#endif
+#define bfd_elfNN_sizeof_headers _bfd_elf_sizeof_headers
+#define bfd_elfNN_write_object_contents _bfd_elf_write_object_contents
+
+#define bfd_elfNN_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#ifndef elf_backend_want_got_plt
+#define elf_backend_want_got_plt 0
+#endif
+#ifndef elf_backend_plt_readonly
+#define elf_backend_plt_readonly 0
+#endif
+#ifndef elf_backend_want_plt_sym
+#define elf_backend_want_plt_sym 0
+#endif
+
+#define bfd_elfNN_bfd_debug_info_start bfd_void
+#define bfd_elfNN_bfd_debug_info_end bfd_void
+#define bfd_elfNN_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void
+
+#ifndef bfd_elfNN_bfd_get_relocated_section_contents
+#define bfd_elfNN_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#endif
+
+#define bfd_elfNN_bfd_relax_section bfd_generic_relax_section
+#define bfd_elfNN_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+#ifndef bfd_elfNN_bfd_copy_private_symbol_data
+#define bfd_elfNN_bfd_copy_private_symbol_data \
+ _bfd_elf_copy_private_symbol_data
+#endif
+
+#ifndef bfd_elfNN_bfd_copy_private_section_data
+#define bfd_elfNN_bfd_copy_private_section_data \
+ _bfd_elf_copy_private_section_data
+#endif
+#ifndef bfd_elfNN_bfd_copy_private_bfd_data
+#define bfd_elfNN_bfd_copy_private_bfd_data \
+ ((boolean (*) PARAMS ((bfd *, bfd *))) bfd_true)
+#endif
+#ifndef bfd_elfNN_bfd_print_private_bfd_data
+#define bfd_elfNN_bfd_print_private_bfd_data \
+ _bfd_elf_print_private_bfd_data
+#endif
+#ifndef bfd_elfNN_bfd_merge_private_bfd_data
+#define bfd_elfNN_bfd_merge_private_bfd_data \
+ ((boolean (*) PARAMS ((bfd *, bfd *))) bfd_true)
+#endif
+#ifndef bfd_elfNN_bfd_set_private_flags
+#define bfd_elfNN_bfd_set_private_flags \
+ ((boolean (*) PARAMS ((bfd *, flagword))) bfd_true)
+#endif
+#ifndef bfd_elfNN_bfd_is_local_label
+#define bfd_elfNN_bfd_is_local_label bfd_generic_is_local_label
+#endif
+
+#ifndef bfd_elfNN_get_dynamic_reloc_upper_bound
+#define bfd_elfNN_get_dynamic_reloc_upper_bound \
+ _bfd_nodynamic_get_dynamic_reloc_upper_bound
+#endif
+#ifndef bfd_elfNN_canonicalize_dynamic_reloc
+#define bfd_elfNN_canonicalize_dynamic_reloc \
+ _bfd_nodynamic_canonicalize_dynamic_reloc
+#endif
+
+#ifdef elf_backend_relocate_section
+#ifndef bfd_elfNN_bfd_link_hash_table_create
+#define bfd_elfNN_bfd_link_hash_table_create _bfd_elf_link_hash_table_create
+#endif
+#else /* ! defined (elf_backend_relocate_section) */
+/* If no backend relocate_section routine, use the generic linker. */
+#ifndef bfd_elfNN_bfd_link_hash_table_create
+#define bfd_elfNN_bfd_link_hash_table_create \
+ _bfd_generic_link_hash_table_create
+#endif
+#ifndef bfd_elfNN_bfd_link_add_symbols
+#define bfd_elfNN_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#endif
+#ifndef bfd_elfNN_bfd_final_link
+#define bfd_elfNN_bfd_final_link _bfd_generic_final_link
+#endif
+#endif /* ! defined (elf_backend_relocate_section) */
+#ifndef bfd_elfNN_bfd_link_split_section
+#define bfd_elfNN_bfd_link_split_section _bfd_generic_link_split_section
+#endif
+
+#ifndef elf_symbol_leading_char
+#define elf_symbol_leading_char 0
+#endif
+
+#ifndef elf_info_to_howto_rel
+#define elf_info_to_howto_rel 0
+#endif
+
+#ifndef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE 1
+#endif
+
+#ifndef elf_backend_collect
+#define elf_backend_collect false
+#endif
+#ifndef elf_backend_type_change_ok
+#define elf_backend_type_change_ok false
+#endif
+
+#ifndef elf_backend_sym_is_global
+#define elf_backend_sym_is_global 0
+#endif
+#ifndef elf_backend_object_p
+#define elf_backend_object_p 0
+#endif
+#ifndef elf_backend_symbol_processing
+#define elf_backend_symbol_processing 0
+#endif
+#ifndef elf_backend_symbol_table_processing
+#define elf_backend_symbol_table_processing 0
+#endif
+#ifndef elf_backend_section_processing
+#define elf_backend_section_processing 0
+#endif
+#ifndef elf_backend_section_from_shdr
+#define elf_backend_section_from_shdr 0
+#endif
+#ifndef elf_backend_fake_sections
+#define elf_backend_fake_sections 0
+#endif
+#ifndef elf_backend_section_from_bfd_section
+#define elf_backend_section_from_bfd_section 0
+#endif
+#ifndef elf_backend_add_symbol_hook
+#define elf_backend_add_symbol_hook 0
+#endif
+#ifndef elf_backend_link_output_symbol_hook
+#define elf_backend_link_output_symbol_hook 0
+#endif
+#ifndef elf_backend_create_dynamic_sections
+#define elf_backend_create_dynamic_sections 0
+#endif
+#ifndef elf_backend_check_relocs
+#define elf_backend_check_relocs 0
+#endif
+#ifndef elf_backend_adjust_dynamic_symbol
+#define elf_backend_adjust_dynamic_symbol 0
+#endif
+#ifndef elf_backend_size_dynamic_sections
+#define elf_backend_size_dynamic_sections 0
+#endif
+#ifndef elf_backend_relocate_section
+#define elf_backend_relocate_section 0
+#endif
+#ifndef elf_backend_finish_dynamic_symbol
+#define elf_backend_finish_dynamic_symbol 0
+#endif
+#ifndef elf_backend_finish_dynamic_sections
+#define elf_backend_finish_dynamic_sections 0
+#endif
+#ifndef elf_backend_begin_write_processing
+#define elf_backend_begin_write_processing 0
+#endif
+#ifndef elf_backend_final_write_processing
+#define elf_backend_final_write_processing 0
+#endif
+#ifndef elf_backend_additional_program_headers
+#define elf_backend_additional_program_headers 0
+#endif
+#ifndef elf_backend_modify_segment_map
+#define elf_backend_modify_segment_map 0
+#endif
+#ifndef elf_backend_ecoff_debug_swap
+#define elf_backend_ecoff_debug_swap 0
+#endif
+
+#ifndef ELF_MACHINE_ALT1
+#define ELF_MACHINE_ALT1 0
+#endif
+
+#ifndef ELF_MACHINE_ALT2
+#define ELF_MACHINE_ALT2 0
+#endif
+
+extern const struct elf_size_info _bfd_elfNN_size_info;
+
+static CONST struct elf_backend_data elfNN_bed =
+{
+#ifdef USE_REL
+ 0, /* use_rela_p */
+#else
+ 1, /* use_rela_p */
+#endif
+ ELF_ARCH, /* arch */
+ ELF_MACHINE_CODE, /* elf_machine_code */
+ ELF_MAXPAGESIZE, /* maxpagesize */
+ elf_backend_collect,
+ elf_backend_type_change_ok,
+ elf_info_to_howto,
+ elf_info_to_howto_rel,
+ elf_backend_sym_is_global,
+ elf_backend_object_p,
+ elf_backend_symbol_processing,
+ elf_backend_symbol_table_processing,
+ elf_backend_section_processing,
+ elf_backend_section_from_shdr,
+ elf_backend_fake_sections,
+ elf_backend_section_from_bfd_section,
+ elf_backend_add_symbol_hook,
+ elf_backend_link_output_symbol_hook,
+ elf_backend_create_dynamic_sections,
+ elf_backend_check_relocs,
+ elf_backend_adjust_dynamic_symbol,
+ elf_backend_size_dynamic_sections,
+ elf_backend_relocate_section,
+ elf_backend_finish_dynamic_symbol,
+ elf_backend_finish_dynamic_sections,
+ elf_backend_begin_write_processing,
+ elf_backend_final_write_processing,
+ elf_backend_additional_program_headers,
+ elf_backend_modify_segment_map,
+ elf_backend_ecoff_debug_swap,
+ ELF_MACHINE_ALT1,
+ ELF_MACHINE_ALT2,
+ &_bfd_elfNN_size_info,
+ elf_backend_want_got_plt,
+ elf_backend_plt_readonly,
+ elf_backend_want_plt_sym
+};
+
+#ifdef TARGET_BIG_SYM
+const bfd_target TARGET_BIG_SYM =
+{
+ /* name: identify kind of target */
+ TARGET_BIG_NAME,
+
+ /* flavour: general indication about file */
+ bfd_target_elf_flavour,
+
+ /* byteorder: data is big endian */
+ BFD_ENDIAN_BIG,
+
+ /* header_byteorder: header is also big endian */
+ BFD_ENDIAN_BIG,
+
+ /* object_flags: mask of all file flags */
+ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS |
+ DYNAMIC | WP_TEXT | D_PAGED),
+
+ /* section_flags: mask of all section flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY |
+ SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES),
+
+ /* leading_symbol_char: is the first char of a user symbol
+ predictable, and if so what is it */
+ elf_symbol_leading_char,
+
+ /* ar_pad_char: pad character for filenames within an archive header
+ FIXME: this really has nothing to do with ELF, this is a characteristic
+ of the archiver and/or os and should be independently tunable */
+ '/',
+
+ /* ar_max_namelen: maximum number of characters in an archive header
+ FIXME: this really has nothing to do with ELF, this is a characteristic
+ of the archiver and should be independently tunable. This value is
+ a WAG (wild a** guess) */
+ 14,
+
+ /* Routines to byte-swap various sized integers from the data sections */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+
+ /* Routines to byte-swap various sized integers from the file headers */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+
+ /* bfd_check_format: check the format of a file being read */
+ { _bfd_dummy_target, /* unknown format */
+ bfd_elfNN_object_p, /* assembler/linker output (object file) */
+ bfd_generic_archive_p, /* an archive */
+ bfd_elfNN_core_file_p /* a core file */
+ },
+
+ /* bfd_set_format: set the format of a file being written */
+ { bfd_false,
+ bfd_elf_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+
+ /* bfd_write_contents: write cached information into a file being written */
+ { bfd_false,
+ bfd_elfNN_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (bfd_elfNN),
+ BFD_JUMP_TABLE_COPY (bfd_elfNN),
+ BFD_JUMP_TABLE_CORE (bfd_elfNN),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN),
+ BFD_JUMP_TABLE_RELOCS (bfd_elfNN),
+ BFD_JUMP_TABLE_WRITE (bfd_elfNN),
+ BFD_JUMP_TABLE_LINK (bfd_elfNN),
+ BFD_JUMP_TABLE_DYNAMIC (bfd_elfNN),
+
+ /* backend_data: */
+ (PTR) &elfNN_bed,
+};
+#endif
+
+#ifdef TARGET_LITTLE_SYM
+const bfd_target TARGET_LITTLE_SYM =
+{
+ /* name: identify kind of target */
+ TARGET_LITTLE_NAME,
+
+ /* flavour: general indication about file */
+ bfd_target_elf_flavour,
+
+ /* byteorder: data is little endian */
+ BFD_ENDIAN_LITTLE,
+
+ /* header_byteorder: header is also little endian */
+ BFD_ENDIAN_LITTLE,
+
+ /* object_flags: mask of all file flags */
+ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS |
+ DYNAMIC | WP_TEXT | D_PAGED),
+
+ /* section_flags: mask of all section flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY |
+ SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_EXCLUDE | SEC_SORT_ENTRIES),
+
+ /* leading_symbol_char: is the first char of a user symbol
+ predictable, and if so what is it */
+ elf_symbol_leading_char,
+
+ /* ar_pad_char: pad character for filenames within an archive header
+ FIXME: this really has nothing to do with ELF, this is a characteristic
+ of the archiver and/or os and should be independently tunable */
+ '/',
+
+ /* ar_max_namelen: maximum number of characters in an archive header
+ FIXME: this really has nothing to do with ELF, this is a characteristic
+ of the archiver and should be independently tunable. This value is
+ a WAG (wild a** guess) */
+ 14,
+
+ /* Routines to byte-swap various sized integers from the data sections */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16,
+
+ /* Routines to byte-swap various sized integers from the file headers */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16,
+
+ /* bfd_check_format: check the format of a file being read */
+ { _bfd_dummy_target, /* unknown format */
+ bfd_elfNN_object_p, /* assembler/linker output (object file) */
+ bfd_generic_archive_p, /* an archive */
+ bfd_elfNN_core_file_p /* a core file */
+ },
+
+ /* bfd_set_format: set the format of a file being written */
+ { bfd_false,
+ bfd_elf_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+
+ /* bfd_write_contents: write cached information into a file being written */
+ { bfd_false,
+ bfd_elfNN_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (bfd_elfNN),
+ BFD_JUMP_TABLE_COPY (bfd_elfNN),
+ BFD_JUMP_TABLE_CORE (bfd_elfNN),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+ BFD_JUMP_TABLE_SYMBOLS (bfd_elfNN),
+ BFD_JUMP_TABLE_RELOCS (bfd_elfNN),
+ BFD_JUMP_TABLE_WRITE (bfd_elfNN),
+ BFD_JUMP_TABLE_LINK (bfd_elfNN),
+ BFD_JUMP_TABLE_DYNAMIC (bfd_elfNN),
+
+ /* backend_data: */
+ (PTR) &elfNN_bed,
+};
+#endif
diff --git a/contrib/gdb/bfd/filemode.c b/contrib/gdb/bfd/filemode.c
new file mode 100644
index 0000000..fd790b3
--- /dev/null
+++ b/contrib/gdb/bfd/filemode.c
@@ -0,0 +1,193 @@
+/* filemode.c -- make a string describing file modes
+ Copyright (C) 1985, 1990 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+void mode_string ();
+static char ftypelet ();
+static void rwx ();
+static void setst ();
+
+/* filemodestring - fill in string STR with an ls-style ASCII
+ representation of the st_mode field of file stats block STATP.
+ 10 characters are stored in STR; no terminating null is added.
+ The characters stored in STR are:
+
+ 0 File type. 'd' for directory, 'c' for character
+ special, 'b' for block special, 'm' for multiplex,
+ 'l' for symbolic link, 's' for socket, 'p' for fifo,
+ '-' for any other file type
+
+ 1 'r' if the owner may read, '-' otherwise.
+
+ 2 'w' if the owner may write, '-' otherwise.
+
+ 3 'x' if the owner may execute, 's' if the file is
+ set-user-id, '-' otherwise.
+ 'S' if the file is set-user-id, but the execute
+ bit isn't set.
+
+ 4 'r' if group members may read, '-' otherwise.
+
+ 5 'w' if group members may write, '-' otherwise.
+
+ 6 'x' if group members may execute, 's' if the file is
+ set-group-id, '-' otherwise.
+ 'S' if it is set-group-id but not executable.
+
+ 7 'r' if any user may read, '-' otherwise.
+
+ 8 'w' if any user may write, '-' otherwise.
+
+ 9 'x' if any user may execute, 't' if the file is "sticky"
+ (will be retained in swap space after execution), '-'
+ otherwise.
+ 'T' if the file is sticky but not executable. */
+
+void
+filemodestring (statp, str)
+ struct stat *statp;
+ char *str;
+{
+ mode_string (statp->st_mode, str);
+}
+
+/* Like filemodestring, but only the relevant part of the `struct stat'
+ is given as an argument. */
+
+void
+mode_string (mode, str)
+ unsigned short mode;
+ char *str;
+{
+ str[0] = ftypelet (mode);
+ rwx ((mode & 0700) << 0, &str[1]);
+ rwx ((mode & 0070) << 3, &str[4]);
+ rwx ((mode & 0007) << 6, &str[7]);
+ setst (mode, str);
+}
+
+/* Return a character indicating the type of file described by
+ file mode BITS:
+ 'd' for directories
+ 'b' for block special files
+ 'c' for character special files
+ 'm' for multiplexor files
+ 'l' for symbolic links
+ 's' for sockets
+ 'p' for fifos
+ '-' for any other file type. */
+
+static char
+ftypelet (bits)
+ unsigned short bits;
+{
+ switch (bits & S_IFMT)
+ {
+ default:
+ return '-';
+ case S_IFDIR:
+ return 'd';
+#ifdef S_IFLNK
+ case S_IFLNK:
+ return 'l';
+#endif
+#ifdef S_IFCHR
+ case S_IFCHR:
+ return 'c';
+#endif
+#ifdef S_IFBLK
+ case S_IFBLK:
+ return 'b';
+#endif
+#ifdef S_IFMPC
+ case S_IFMPC:
+ case S_IFMPB:
+ return 'm';
+#endif
+#ifdef S_IFSOCK
+ case S_IFSOCK:
+ return 's';
+#endif
+#ifdef S_IFIFO
+#if S_IFIFO != S_IFSOCK
+ case S_IFIFO:
+ return 'p';
+#endif
+#endif
+#ifdef S_IFNWK /* HP-UX */
+ case S_IFNWK:
+ return 'n';
+#endif
+ }
+}
+
+/* Look at read, write, and execute bits in BITS and set
+ flags in CHARS accordingly. */
+
+static void
+rwx (bits, chars)
+ unsigned short bits;
+ char *chars;
+{
+ chars[0] = (bits & S_IREAD) ? 'r' : '-';
+ chars[1] = (bits & S_IWRITE) ? 'w' : '-';
+ chars[2] = (bits & S_IEXEC) ? 'x' : '-';
+}
+
+/* Set the 's' and 't' flags in file attributes string CHARS,
+ according to the file mode BITS. */
+
+static void
+setst (bits, chars)
+ unsigned short bits;
+ char *chars;
+{
+#ifdef S_ISUID
+ if (bits & S_ISUID)
+ {
+ if (chars[3] != 'x')
+ /* Set-uid, but not executable by owner. */
+ chars[3] = 'S';
+ else
+ chars[3] = 's';
+ }
+#endif
+#ifdef S_ISGID
+ if (bits & S_ISGID)
+ {
+ if (chars[6] != 'x')
+ /* Set-gid, but not executable by group. */
+ chars[6] = 'S';
+ else
+ chars[6] = 's';
+ }
+#endif
+#ifdef S_ISVTX
+ if (bits & S_ISVTX)
+ {
+ if (chars[9] != 'x')
+ /* Sticky, but not executable by others. */
+ chars[9] = 'T';
+ else
+ chars[9] = 't';
+ }
+#endif
+}
+
+
diff --git a/contrib/gdb/bfd/format.c b/contrib/gdb/bfd/format.c
new file mode 100644
index 0000000..7a303424
--- /dev/null
+++ b/contrib/gdb/bfd/format.c
@@ -0,0 +1,319 @@
+/* Generic BFD support for file formats.
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ File formats
+
+ A format is a BFD concept of high level file contents type. The
+ formats supported by BFD are:
+
+ o <<bfd_object>>
+
+ The BFD may contain data, symbols, relocations and debug info.
+
+ o <<bfd_archive>>
+
+ The BFD contains other BFDs and an optional index.
+
+ o <<bfd_core>>
+
+ The BFD contains the result of an executable core dump.
+
+
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* IMPORT from targets.c. */
+extern const size_t _bfd_target_vector_entries;
+
+/*
+FUNCTION
+ bfd_check_format
+
+SYNOPSIS
+ boolean bfd_check_format(bfd *abfd, bfd_format format);
+
+DESCRIPTION
+ Verify if the file attached to the BFD @var{abfd} is compatible
+ with the format @var{format} (i.e., one of <<bfd_object>>,
+ <<bfd_archive>> or <<bfd_core>>).
+
+ 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
+ <<default>>, 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.
+
+ The function returns <<true>> on success, otherwise <<false>>
+ with one of the following error codes:
+
+ o <<bfd_error_invalid_operation>> -
+ if <<format>> is not one of <<bfd_object>>, <<bfd_archive>> or
+ <<bfd_core>>.
+
+ o <<bfd_error_system_call>> -
+ if an error occured during a read - even some file mismatches
+ can cause bfd_error_system_calls.
+
+ o <<file_not_recognised>> -
+ none of the backends recognised the file format.
+
+ o <<bfd_error_file_ambiguously_recognized>> -
+ more than one backend recognised the file format.
+*/
+
+boolean
+bfd_check_format (abfd, format)
+ bfd *abfd;
+ bfd_format format;
+{
+ 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 <<bfd_check_format>>, except when it returns false with
+ <<bfd_errno>> set to <<bfd_error_file_ambiguously_recognized>>. 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 <<malloc>>.
+ 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_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ if (abfd->format != bfd_unknown)
+ return (abfd->format == format)? true: false;
+
+
+ /* Since the target type was defaulted, check them
+ all in the hope that one will be uniquely recognized. */
+
+ save_targ = abfd->xvec;
+ match_count = 0;
+ if (matching)
+ {
+ matching_vector =
+ (char **) bfd_malloc (sizeof (char *) *
+ (_bfd_target_vector_entries + 1));
+ if (!matching_vector)
+ return false;
+ matching_vector[0] = NULL;
+ *matching = matching_vector;
+ }
+ right_targ = 0;
+
+
+ /* presume the answer is yes */
+ abfd->format = format;
+
+ /* If the target type was explicitly specified, just check that target. */
+
+ if (!abfd->target_defaulted) {
+ 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 = bfd_target_vector; *target != NULL; target++) {
+ extern const bfd_target binary_vec;
+ const bfd_target *temp;
+
+ if (*target == &binary_vec)
+ continue;
+
+ abfd->xvec = *target; /* Change BFD's target temporarily */
+ 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_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 == bfd_default_vector[0])
+ {
+ if (matching)
+ {
+ matching_vector[0] = temp->name;
+ matching_vector[1] = NULL;
+ }
+ match_count = 1;
+ break;
+ }
+#ifdef GNU960
+ /* Big- and little-endian b.out archives look the same, but it doesn't
+ * matter: there is no difference in their headers, and member file byte
+ * orders will (I hope) be handled appropriately by bfd. Ditto for big
+ * and little coff archives. And the 4 coff/b.out object formats are
+ * unambiguous. So accept the first match we find.
+ */
+ break;
+#endif
+ } 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 */
+ 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 *abfd, bfd_format format);
+
+DESCRIPTION
+ 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
+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_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ if (abfd->format != bfd_unknown)
+ return (abfd->format == format) ? true:false;
+
+ /* presume the answer is yes */
+ abfd->format = format;
+
+ if (!BFD_SEND_FMT (abfd, _bfd_set_format, (abfd))) {
+ abfd->format = bfd_unknown;
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+FUNCTION
+ bfd_format_string
+
+SYNOPSIS
+ CONST char *bfd_format_string(bfd_format format);
+
+DESCRIPTION
+ Return a pointer to a const string
+ <<invalid>>, <<object>>, <<archive>>, <<core>>, or <<unknown>>,
+ depending upon the value of @var{format}.
+*/
+
+CONST char *
+bfd_format_string (format)
+ bfd_format format;
+{
+ if (((int)format <(int) bfd_unknown)
+ || ((int)format >=(int) bfd_type_end))
+ return "invalid";
+
+ switch (format) {
+ case bfd_object:
+ return "object"; /* linker/assember/compiler output */
+ case bfd_archive:
+ return "archive"; /* object archive file */
+ case bfd_core:
+ return "core"; /* core dump */
+ default:
+ return "unknown";
+ }
+}
diff --git a/contrib/gdb/bfd/freebsd.h b/contrib/gdb/bfd/freebsd.h
new file mode 100644
index 0000000..7e1d69d
--- /dev/null
+++ b/contrib/gdb/bfd/freebsd.h
@@ -0,0 +1,109 @@
+/* BFD back-end definitions used by all FreeBSD targets.
+ Copyright (C) 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* FreeBSD ZMAGIC files never have the header in the text. */
+#define N_HEADER_IN_TEXT(x) 0
+
+/* ZMAGIC files start at offset 0. Does not apply to QMAGIC files. */
+#define TEXT_START_ADDR 0
+
+#define N_GETMAGIC_NET(exec) \
+ (ntohl ((exec).a_info) & 0xffff)
+#define N_GETMID_NET(exec) \
+ ((ntohl ((exec).a_info) >> 16) & 0x3ff)
+#define N_GETFLAG_NET(ex) \
+ ((ntohl ((exec).a_info) >> 26) & 0x3f)
+
+#define N_MACHTYPE(exec) \
+ ((enum machine_type) \
+ ((N_GETMAGIC_NET (exec) == ZMAGIC) ? N_GETMID_NET (exec) : \
+ ((exec).a_info >> 16) & 0x3ff))
+#define N_FLAGS(exec) \
+ ((N_GETMAGIC_NET (exec) == ZMAGIC) ? N_GETFLAG_NET (exec) : \
+ ((exec).a_info >> 26) & 0x3f)
+
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0x3ff) << 16) \
+ | (((flags) & 0x3f) << 26))
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info & 0xfb00ffff) | ((((int)(machtype))&0x3ff) << 16))
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info & 0x03ffffff) | ((flags & 0x03f) << 26))
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+/* On FreeBSD, the magic number is always in correct endian format */
+#define NO_SWAP_MAGIC
+
+
+#define MY_write_object_contents MY(write_object_contents)
+static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
+
+#include "aout-target.h"
+
+/* Write an object file.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+static boolean
+MY(write_object_contents) (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+#if CHOOSE_RELOC_SIZE
+ CHOOSE_RELOC_SIZE(abfd);
+#else
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+#endif
+
+ /* Magic number, maestro, please! */
+ switch (bfd_get_arch(abfd)) {
+ case bfd_arch_m68k:
+ if (strcmp (abfd->xvec->name, "a.out-m68k4k-netbsd") == 0)
+ N_SET_MACHTYPE(*execp, M_68K4K_NETBSD);
+ else
+ N_SET_MACHTYPE(*execp, M_68K_NETBSD);
+ break;
+ case bfd_arch_sparc:
+ N_SET_MACHTYPE(*execp, M_SPARC_NETBSD);
+ break;
+ case bfd_arch_i386:
+ N_SET_MACHTYPE(*execp, M_386_NETBSD);
+ break;
+ case bfd_arch_ns32k:
+ N_SET_MACHTYPE(*execp, M_532_NETBSD);
+ break;
+ default:
+ N_SET_MACHTYPE(*execp, M_UNKNOWN);
+ break;
+ }
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/gen-aout.c b/contrib/gdb/bfd/gen-aout.c
new file mode 100644
index 0000000..d2224f7
--- /dev/null
+++ b/contrib/gdb/bfd/gen-aout.c
@@ -0,0 +1,101 @@
+/* Generate parameters for an a.out system.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "/usr/include/a.out.h"
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc; char** argv;
+{
+ struct exec my_exec;
+ int page_size;
+ char *target = "unknown", *arch = "unknown";
+ FILE *file = fopen("gen-aout", "r");
+
+ if (file == NULL) {
+ fprintf(stderr, "Cannot open gen-aout!\n");
+ return -1;
+ }
+ if (fread(&my_exec, sizeof(struct exec), 1, file) != 1) {
+ fprintf(stderr, "Cannot read gen-aout!\n");
+ return -1;
+ }
+
+ target = argv[1];
+ if (target == NULL) {
+ fprintf(stderr, "Usage: gen-aout target_name\n");
+ exit (1);
+ }
+
+#ifdef N_TXTOFF
+ page_size = N_TXTOFF(my_exec);
+ if (page_size == 0)
+ printf("#define N_HEADER_IN_TEXT(x) 1\n");
+ else
+ printf("#define N_HEADER_IN_TEXT(x) 0\n");
+#endif
+
+ printf("#define BYTES_IN_WORD %d\n", sizeof (int));
+ if (my_exec.a_entry == 0) {
+ printf("#define ENTRY_CAN_BE_ZERO\n");
+ printf("#define N_SHARED_LIB(x) 0 /* Avoids warning */\n");
+ }
+ else {
+ printf("/*#define ENTRY_CAN_BE_ZERO*/\n");
+ printf("/*#define N_SHARED_LIB(x) 0*/\n");
+ }
+
+ printf("#define TEXT_START_ADDR %d\n", my_exec.a_entry);
+
+#ifdef PAGSIZ
+ if (page_size == 0)
+ page_size = PAGSIZ;
+#endif
+ if (page_size != 0)
+ printf("#define TARGET_PAGE_SIZE %d\n", page_size);
+ else
+ printf("/* #define TARGET_PAGE_SIZE ??? */\n");
+ printf("#define SEGMENT_SIZE TARGET_PAGE_SIZE\n");
+
+#ifdef vax
+ arch = "vax";
+#endif
+#ifdef m68k
+ arch = "m68k";
+#endif
+ if (arch[0] == '1')
+ {
+ fprintf (stderr, "warning: preprocessor substituted architecture name inside string;");
+ fprintf (stderr, " fix DEFAULT_ARCH in the output file yourself\n");
+ arch = "unknown";
+ }
+ printf("#define DEFAULT_ARCH bfd_arch_%s\n", arch);
+
+ printf("\n#define MY(OP) CAT(%s_,OP)\n", target);
+ printf("#define TARGETNAME \"a.out-%s\"\n\n", target);
+
+ printf("#include \"bfd.h\"\n");
+ printf("#include \"sysdep.h\"\n");
+ printf("#include \"libbfd.h\"\n");
+ printf("#include \"libaout.h\"\n");
+ printf("\n#include \"aout-target.h\"\n");
+
+ return 0;
+}
diff --git a/contrib/gdb/bfd/genlink.h b/contrib/gdb/bfd/genlink.h
new file mode 100644
index 0000000..5f08094
--- /dev/null
+++ b/contrib/gdb/bfd/genlink.h
@@ -0,0 +1,106 @@
+/* genlink.h -- interface to the BFD generic linker
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef GENLINK_H
+#define GENLINK_H
+
+/* This header file is internal to BFD. It describes the internal
+ structures and functions used by the BFD generic linker, in case
+ any of the more specific linkers want to use or call them. Note
+ that some functions, such as _bfd_generic_link_hash_table_create,
+ are declared in libbfd.h, because they are expected to be widely
+ used. The functions and structures in this file will probably only
+ be used by a few files besides linker.c itself. In fact, this file
+ is not particularly complete; I have only put in the interfaces I
+ actually needed. */
+
+/* The generic linker uses a hash table which is a derived class of
+ the standard linker hash table, just as the other backend specific
+ linkers do. Do not confuse the generic linker hash table with the
+ standard BFD linker hash table it is built upon. */
+
+/* Generic linker hash table entries. */
+
+struct generic_link_hash_entry
+{
+ struct bfd_link_hash_entry root;
+ /* Whether this symbol has been written out. */
+ boolean written;
+ /* Symbol from input BFD. */
+ asymbol *sym;
+};
+
+/* Generic linker hash table. */
+
+struct generic_link_hash_table
+{
+ struct bfd_link_hash_table root;
+};
+
+/* Look up an entry in an generic link hash table. */
+
+#define _bfd_generic_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct generic_link_hash_entry *) \
+ bfd_link_hash_lookup (&(table)->root, (string), (create), (copy), (follow)))
+
+/* Traverse an generic link hash table. */
+
+#define _bfd_generic_link_hash_traverse(table, func, info) \
+ (bfd_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the generic link hash table from the info structure. This is
+ just a cast. */
+
+#define _bfd_generic_hash_table(p) \
+ ((struct generic_link_hash_table *) ((p)->hash))
+
+/* The generic linker reads in the asymbol structures for an input BFD
+ and keeps them in the outsymbol and symcount fields. */
+
+#define _bfd_generic_link_get_symbols(abfd) ((abfd)->outsymbols)
+#define _bfd_generic_link_get_symcount(abfd) ((abfd)->symcount)
+
+/* Add the symbols of input_bfd to the symbols being built for
+ output_bfd. */
+extern boolean _bfd_generic_link_output_symbols
+ PARAMS ((bfd *output_bfd, bfd *input_bfd, struct bfd_link_info *,
+ size_t *psymalloc));
+
+/* This structure is used to pass information to
+ _bfd_generic_link_write_global_symbol, which may be called via
+ _bfd_generic_link_hash_traverse. */
+
+struct generic_write_global_symbol_info
+{
+ struct bfd_link_info *info;
+ bfd *output_bfd;
+ size_t *psymalloc;
+};
+
+/* Write out a single global symbol. This is expected to be called
+ via _bfd_generic_link_hash_traverse. The second argument must
+ actually be a struct generic_write_global_symbol_info *. */
+extern boolean _bfd_generic_link_write_global_symbol
+ PARAMS ((struct generic_link_hash_entry *, PTR));
+
+#endif
diff --git a/contrib/gdb/bfd/hash.c b/contrib/gdb/bfd/hash.c
new file mode 100644
index 0000000..35913fc
--- /dev/null
+++ b/contrib/gdb/bfd/hash.c
@@ -0,0 +1,734 @@
+/* hash.c -- hash table routines for BFD
+ Copyright (C) 1993, 94 Free Software Foundation, Inc.
+ Written by Steve Chamberlain <sac@cygnus.com>
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+
+/*
+SECTION
+ Hash Tables
+
+@cindex Hash tables
+ BFD provides a simple set of hash table functions. Routines
+ are provided to initialize a hash table, to free a hash table,
+ to look up a string in a hash table and optionally create an
+ entry for it, and to traverse a hash table. There is
+ currently no routine to delete an string from a hash table.
+
+ The basic hash table does not permit any data to be stored
+ with a string. However, a hash table is designed to present a
+ base class from which other types of hash tables may be
+ derived. These derived types may store additional information
+ with the string. Hash tables were implemented in this way,
+ rather than simply providing a data pointer in a hash table
+ entry, because they were designed for use by the linker back
+ ends. The linker may create thousands of hash table entries,
+ and the overhead of allocating private data and storing and
+ following pointers becomes noticeable.
+
+ The basic hash table code is in <<hash.c>>.
+
+@menu
+@* Creating and Freeing a Hash Table::
+@* Looking Up or Entering a String::
+@* Traversing a Hash Table::
+@* Deriving a New Hash Table Type::
+@end menu
+
+INODE
+Creating and Freeing a Hash Table, Looking Up or Entering a String, Hash Tables, Hash Tables
+SUBSECTION
+ Creating and freeing a hash table
+
+@findex bfd_hash_table_init
+@findex bfd_hash_table_init_n
+ To create a hash table, create an instance of a <<struct
+ bfd_hash_table>> (defined in <<bfd.h>>) and call
+ <<bfd_hash_table_init>> (if you know approximately how many
+ entries you will need, the function <<bfd_hash_table_init_n>>,
+ which takes a @var{size} argument, may be used).
+ <<bfd_hash_table_init>> returns <<false>> if some sort of
+ error occurs.
+
+@findex bfd_hash_newfunc
+ The function <<bfd_hash_table_init>> take as an argument a
+ function to use to create new entries. For a basic hash
+ table, use the function <<bfd_hash_newfunc>>. @xref{Deriving
+ a New Hash Table Type} for why you would want to use a
+ different value for this argument.
+
+@findex bfd_hash_allocate
+ <<bfd_hash_table_init>> will create an obstack which will be
+ used to allocate new entries. You may allocate memory on this
+ obstack using <<bfd_hash_allocate>>.
+
+@findex bfd_hash_table_free
+ Use <<bfd_hash_table_free>> to free up all the memory that has
+ been allocated for a hash table. This will not free up the
+ <<struct bfd_hash_table>> itself, which you must provide.
+
+INODE
+Looking Up or Entering a String, Traversing a Hash Table, Creating and Freeing a Hash Table, Hash Tables
+SUBSECTION
+ Looking up or entering a string
+
+@findex bfd_hash_lookup
+ The function <<bfd_hash_lookup>> is used both to look up a
+ string in the hash table and to create a new entry.
+
+ If the @var{create} argument is <<false>>, <<bfd_hash_lookup>>
+ will look up a string. If the string is found, it will
+ returns a pointer to a <<struct bfd_hash_entry>>. If the
+ string is not found in the table <<bfd_hash_lookup>> will
+ return <<NULL>>. You should not modify any of the fields in
+ the returns <<struct bfd_hash_entry>>.
+
+ If the @var{create} argument is <<true>>, the string will be
+ entered into the hash table if it is not already there.
+ Either way a pointer to a <<struct bfd_hash_entry>> will be
+ returned, either to the existing structure or to a newly
+ created one. In this case, a <<NULL>> return means that an
+ error occurred.
+
+ If the @var{create} argument is <<true>>, and a new entry is
+ created, the @var{copy} argument is used to decide whether to
+ copy the string onto the hash table obstack or not. If
+ @var{copy} is passed as <<false>>, you must be careful not to
+ deallocate or modify the string as long as the hash table
+ exists.
+
+INODE
+Traversing a Hash Table, Deriving a New Hash Table Type, Looking Up or Entering a String, Hash Tables
+SUBSECTION
+ Traversing a hash table
+
+@findex bfd_hash_traverse
+ The function <<bfd_hash_traverse>> may be used to traverse a
+ hash table, calling a function on each element. The traversal
+ is done in a random order.
+
+ <<bfd_hash_traverse>> takes as arguments a function and a
+ generic <<void *>> pointer. The function is called with a
+ hash table entry (a <<struct bfd_hash_entry *>>) and the
+ generic pointer passed to <<bfd_hash_traverse>>. The function
+ must return a <<boolean>> value, which indicates whether to
+ continue traversing the hash table. If the function returns
+ <<false>>, <<bfd_hash_traverse>> will stop the traversal and
+ return immediately.
+
+INODE
+Deriving a New Hash Table Type, , Traversing a Hash Table, Hash Tables
+SUBSECTION
+ Deriving a new hash table type
+
+ Many uses of hash tables want to store additional information
+ which each entry in the hash table. Some also find it
+ convenient to store additional information with the hash table
+ itself. This may be done using a derived hash table.
+
+ Since C is not an object oriented language, creating a derived
+ hash table requires sticking together some boilerplate
+ routines with a few differences specific to the type of hash
+ table you want to create.
+
+ An example of a derived hash table is the linker hash table.
+ The structures for this are defined in <<bfdlink.h>>. The
+ functions are in <<linker.c>>.
+
+ You may also derive a hash table from an already derived hash
+ table. For example, the a.out linker backend code uses a hash
+ table derived from the linker hash table.
+
+@menu
+@* Define the Derived Structures::
+@* Write the Derived Creation Routine::
+@* Write Other Derived Routines::
+@end menu
+
+INODE
+Define the Derived Structures, Write the Derived Creation Routine, Deriving a New Hash Table Type, Deriving a New Hash Table Type
+SUBSUBSECTION
+ Define the derived structures
+
+ You must define a structure for an entry in the hash table,
+ and a structure for the hash table itself.
+
+ The first field in the structure for an entry in the hash
+ table must be of the type used for an entry in the hash table
+ you are deriving from. If you are deriving from a basic hash
+ table this is <<struct bfd_hash_entry>>, which is defined in
+ <<bfd.h>>. The first field in the structure for the hash
+ table itself must be of the type of the hash table you are
+ deriving from itself. If you are deriving from a basic hash
+ table, this is <<struct bfd_hash_table>>.
+
+ For example, the linker hash table defines <<struct
+ bfd_link_hash_entry>> (in <<bfdlink.h>>). The first field,
+ <<root>>, is of type <<struct bfd_hash_entry>>. Similarly,
+ the first field in <<struct bfd_link_hash_table>>, <<table>>,
+ is of type <<struct bfd_hash_table>>.
+
+INODE
+Write the Derived Creation Routine, Write Other Derived Routines, Define the Derived Structures, Deriving a New Hash Table Type
+SUBSUBSECTION
+ Write the derived creation routine
+
+ You must write a routine which will create and initialize an
+ entry in the hash table. This routine is passed as the
+ function argument to <<bfd_hash_table_init>>.
+
+ In order to permit other hash tables to be derived from the
+ hash table you are creating, this routine must be written in a
+ standard way.
+
+ The first argument to the creation routine is a pointer to a
+ hash table entry. This may be <<NULL>>, in which case the
+ routine should allocate the right amount of space. Otherwise
+ the space has already been allocated by a hash table type
+ derived from this one.
+
+ After allocating space, the creation routine must call the
+ creation routine of the hash table type it is derived from,
+ passing in a pointer to the space it just allocated. This
+ will initialize any fields used by the base hash table.
+
+ Finally the creation routine must initialize any local fields
+ for the new hash table type.
+
+ Here is a boilerplate example of a creation routine.
+ @var{function_name} is the name of the routine.
+ @var{entry_type} is the type of an entry in the hash table you
+ are creating. @var{base_newfunc} is the name of the creation
+ routine of the hash table type your hash table is derived
+ from.
+
+EXAMPLE
+
+.struct bfd_hash_entry *
+.@var{function_name} (entry, table, string)
+. struct bfd_hash_entry *entry;
+. struct bfd_hash_table *table;
+. const char *string;
+.{
+. struct @var{entry_type} *ret = (@var{entry_type} *) entry;
+.
+. {* Allocate the structure if it has not already been allocated by a
+. derived class. *}
+. if (ret == (@var{entry_type} *) NULL)
+. {
+. ret = ((@var{entry_type} *)
+. bfd_hash_allocate (table, sizeof (@var{entry_type})));
+. if (ret == (@var{entry_type} *) NULL)
+. return NULL;
+. }
+.
+. {* Call the allocation method of the base class. *}
+. ret = ((@var{entry_type} *)
+. @var{base_newfunc} ((struct bfd_hash_entry *) ret, table, string));
+.
+. {* Initialize the local fields here. *}
+.
+. return (struct bfd_hash_entry *) ret;
+.}
+
+DESCRIPTION
+ The creation routine for the linker hash table, which is in
+ <<linker.c>>, looks just like this example.
+ @var{function_name} is <<_bfd_link_hash_newfunc>>.
+ @var{entry_type} is <<struct bfd_link_hash_entry>>.
+ @var{base_newfunc} is <<bfd_hash_newfunc>>, the creation
+ routine for a basic hash table.
+
+ <<_bfd_link_hash_newfunc>> also initializes the local fields
+ in a linker hash table entry: <<type>>, <<written>> and
+ <<next>>.
+
+INODE
+Write Other Derived Routines, , Write the Derived Creation Routine, Deriving a New Hash Table Type
+SUBSUBSECTION
+ Write other derived routines
+
+ You will want to write other routines for your new hash table,
+ as well.
+
+ You will want an initialization routine which calls the
+ initialization routine of the hash table you are deriving from
+ and initializes any other local fields. For the linker hash
+ table, this is <<_bfd_link_hash_table_init>> in <<linker.c>>.
+
+ You will want a lookup routine which calls the lookup routine
+ of the hash table you are deriving from and casts the result.
+ The linker hash table uses <<bfd_link_hash_lookup>> in
+ <<linker.c>> (this actually takes an additional argument which
+ it uses to decide how to return the looked up value).
+
+ You may want a traversal routine. This should just call the
+ traversal routine of the hash table you are deriving from with
+ appropriate casts. The linker hash table uses
+ <<bfd_link_hash_traverse>> in <<linker.c>>.
+
+ These routines may simply be defined as macros. For example,
+ the a.out backend linker hash table, which is derived from the
+ linker hash table, uses macros for the lookup and traversal
+ routines. These are <<aout_link_hash_lookup>> and
+ <<aout_link_hash_traverse>> in aoutx.h.
+*/
+
+/* Obstack allocation and deallocation routines. */
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+/* The default number of entries to use when creating a hash table. */
+#define DEFAULT_SIZE (4051)
+
+/* Create a new hash table, given a number of entries. */
+
+boolean
+bfd_hash_table_init_n (table, newfunc, size)
+ struct bfd_hash_table *table;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+ unsigned int size;
+{
+ unsigned int alloc;
+
+ alloc = size * sizeof (struct bfd_hash_entry *);
+ if (!obstack_begin (&table->memory, alloc))
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ table->table = ((struct bfd_hash_entry **)
+ obstack_alloc (&table->memory, alloc));
+ if (!table->table)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ memset ((PTR) table->table, 0, alloc);
+ table->size = size;
+ table->newfunc = newfunc;
+ return true;
+}
+
+/* Create a new hash table with the default number of entries. */
+
+boolean
+bfd_hash_table_init (table, newfunc)
+ struct bfd_hash_table *table;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+{
+ return bfd_hash_table_init_n (table, newfunc, DEFAULT_SIZE);
+}
+
+/* Free a hash table. */
+
+void
+bfd_hash_table_free (table)
+ struct bfd_hash_table *table;
+{
+ obstack_free (&table->memory, (PTR) NULL);
+}
+
+/* Look up a string in a hash table. */
+
+struct bfd_hash_entry *
+bfd_hash_lookup (table, string, create, copy)
+ struct bfd_hash_table *table;
+ const char *string;
+ boolean create;
+ boolean copy;
+{
+ register const unsigned char *s;
+ register unsigned long hash;
+ register unsigned int c;
+ struct bfd_hash_entry *hashp;
+ unsigned int len;
+ unsigned int index;
+
+ hash = 0;
+ len = 0;
+ s = (const unsigned char *) string;
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ ++len;
+ }
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ index = hash % table->size;
+ for (hashp = table->table[index];
+ hashp != (struct bfd_hash_entry *) NULL;
+ hashp = hashp->next)
+ {
+ if (hashp->hash == hash
+ && strcmp (hashp->string, string) == 0)
+ return hashp;
+ }
+
+ if (! create)
+ return (struct bfd_hash_entry *) NULL;
+
+ hashp = (*table->newfunc) ((struct bfd_hash_entry *) NULL, table, string);
+ if (hashp == (struct bfd_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) NULL;
+ if (copy)
+ {
+ char *new;
+
+ new = (char *) obstack_alloc (&table->memory, len + 1);
+ if (!new)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return (struct bfd_hash_entry *) NULL;
+ }
+ strcpy (new, string);
+ string = new;
+ }
+ hashp->string = string;
+ hashp->hash = hash;
+ hashp->next = table->table[index];
+ table->table[index] = hashp;
+
+ return hashp;
+}
+
+/* Replace an entry in a hash table. */
+
+void
+bfd_hash_replace (table, old, nw)
+ struct bfd_hash_table *table;
+ struct bfd_hash_entry *old;
+ struct bfd_hash_entry *nw;
+{
+ unsigned int index;
+ struct bfd_hash_entry **pph;
+
+ index = old->hash % table->size;
+ for (pph = &table->table[index];
+ (*pph) != (struct bfd_hash_entry *) NULL;
+ pph = &(*pph)->next)
+ {
+ if (*pph == old)
+ {
+ *pph = nw;
+ return;
+ }
+ }
+
+ abort ();
+}
+
+/* Base method for creating a new hash table entry. */
+
+/*ARGSUSED*/
+struct bfd_hash_entry *
+bfd_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ if (entry == (struct bfd_hash_entry *) NULL)
+ entry = ((struct bfd_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct bfd_hash_entry)));
+ return entry;
+}
+
+/* Allocate space in a hash table. */
+
+PTR
+bfd_hash_allocate (table, size)
+ struct bfd_hash_table *table;
+ unsigned int size;
+{
+ PTR ret;
+
+ ret = obstack_alloc (&table->memory, size);
+ if (ret == NULL && size != 0)
+ bfd_set_error (bfd_error_no_memory);
+ return ret;
+}
+
+/* Traverse a hash table. */
+
+void
+bfd_hash_traverse (table, func, info)
+ struct bfd_hash_table *table;
+ boolean (*func) PARAMS ((struct bfd_hash_entry *, PTR));
+ PTR info;
+{
+ unsigned int i;
+
+ for (i = 0; i < table->size; i++)
+ {
+ struct bfd_hash_entry *p;
+
+ for (p = table->table[i]; p != NULL; p = p->next)
+ {
+ if (! (*func) (p, info))
+ return;
+ }
+ }
+}
+
+/* A few different object file formats (a.out, COFF, ELF) use a string
+ table. These functions support adding strings to a string table,
+ returning the byte offset, and writing out the table.
+
+ Possible improvements:
+ + look for strings matching trailing substrings of other strings
+ + better data structures? balanced trees?
+ + 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?) */
+
+/* An entry in the strtab hash table. */
+
+struct strtab_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* Index in string table. */
+ bfd_size_type index;
+ /* Next string in strtab. */
+ struct strtab_hash_entry *next;
+};
+
+/* The strtab hash table. */
+
+struct bfd_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;
+ /* Whether to precede strings with a two byte length, as in the
+ XCOFF .debug section. */
+ boolean xcoff;
+};
+
+static struct bfd_hash_entry *strtab_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+
+/* Routine to create an entry in a strtab. */
+
+static struct bfd_hash_entry *
+strtab_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct strtab_hash_entry *ret = (struct strtab_hash_entry *) entry;
+
+ /* 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)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct strtab_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ ret->index = (bfd_size_type) -1;
+ ret->next = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* 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. */
+
+struct bfd_strtab_hash *
+_bfd_stringtab_init ()
+{
+ struct bfd_strtab_hash *table;
+
+ table = ((struct bfd_strtab_hash *)
+ bfd_malloc (sizeof (struct bfd_strtab_hash)));
+ if (table == NULL)
+ return NULL;
+
+ if (! bfd_hash_table_init (&table->table, strtab_hash_newfunc))
+ {
+ free (table);
+ return NULL;
+ }
+
+ table->size = 0;
+ table->first = NULL;
+ table->last = NULL;
+ table->xcoff = false;
+
+ return table;
+}
+
+/* Create a new strtab in which the strings are output in the format
+ used in the XCOFF .debug section: a two byte length precedes each
+ string. */
+
+struct bfd_strtab_hash *
+_bfd_xcoff_stringtab_init ()
+{
+ struct bfd_strtab_hash *ret;
+
+ ret = _bfd_stringtab_init ();
+ if (ret != NULL)
+ ret->xcoff = true;
+ return ret;
+}
+
+/* Free a strtab. */
+
+void
+_bfd_stringtab_free (table)
+ struct bfd_strtab_hash *table;
+{
+ bfd_hash_table_free (&table->table);
+ free (table);
+}
+
+/* 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. */
+
+bfd_size_type
+_bfd_stringtab_add (tab, str, hash, copy)
+ struct bfd_strtab_hash *tab;
+ const char *str;
+ boolean hash;
+ boolean copy;
+{
+ register struct strtab_hash_entry *entry;
+
+ if (hash)
+ {
+ entry = strtab_hash_lookup (tab, str, true, copy);
+ if (entry == NULL)
+ return (bfd_size_type) -1;
+ }
+ else
+ {
+ 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
+ {
+ 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 (entry->index == (bfd_size_type) -1)
+ {
+ entry->index = tab->size;
+ tab->size += strlen (str) + 1;
+ if (tab->xcoff)
+ {
+ entry->index += 2;
+ tab->size += 2;
+ }
+ if (tab->first == NULL)
+ tab->first = entry;
+ else
+ tab->last->next = entry;
+ tab->last = entry;
+ }
+
+ return entry->index;
+}
+
+/* Get the number of bytes in a strtab. */
+
+bfd_size_type
+_bfd_stringtab_size (tab)
+ struct bfd_strtab_hash *tab;
+{
+ return tab->size;
+}
+
+/* Write out a strtab. ABFD must already be at the right location in
+ the file. */
+
+boolean
+_bfd_stringtab_emit (abfd, tab)
+ register bfd *abfd;
+ struct bfd_strtab_hash *tab;
+{
+ register boolean xcoff;
+ register struct strtab_hash_entry *entry;
+
+ xcoff = tab->xcoff;
+
+ for (entry = tab->first; entry != NULL; entry = entry->next)
+ {
+ register const char *str;
+ register size_t len;
+
+ str = entry->root.string;
+ len = strlen (str) + 1;
+
+ if (xcoff)
+ {
+ bfd_byte buf[2];
+
+ /* The output length includes the null byte. */
+ bfd_put_16 (abfd, len, buf);
+ if (bfd_write ((PTR) buf, 1, 2, abfd) != 2)
+ return false;
+ }
+
+ if (bfd_write ((PTR) str, 1, len, abfd) != len)
+ return false;
+ }
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/host-aout.c b/contrib/gdb/bfd/host-aout.c
new file mode 100644
index 0000000..99643dc
--- /dev/null
+++ b/contrib/gdb/bfd/host-aout.c
@@ -0,0 +1,83 @@
+/* BFD backend for local host's a.out binaries
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Written by Cygnus Support. Probably John Gilmore's fault.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#define ARCH_SIZE 32
+
+/* When porting to a new system, you must supply:
+
+ HOST_PAGE_SIZE (optional)
+ HOST_SEGMENT_SIZE (optional -- defaults to page size)
+ HOST_MACHINE_ARCH (optional)
+ HOST_MACHINE_MACHINE (optional)
+ HOST_TEXT_START_ADDR (optional)
+ HOST_STACK_END_ADDR (not used, except by trad-core ???)
+ HOST_BIG_ENDIAN_P (required -- define if big-endian)
+
+ in the ./hosts/h-systemname.h file. */
+
+#ifdef TRAD_HEADER
+#include TRAD_HEADER
+#endif
+
+#ifdef HOST_PAGE_SIZE
+#define TARGET_PAGE_SIZE HOST_PAGE_SIZE
+#endif
+
+#ifdef HOST_SEGMENT_SIZE
+#define SEGMENT_SIZE HOST_SEGMENT_SIZE
+#else
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#endif
+
+#ifdef HOST_TEXT_START_ADDR
+#define TEXT_START_ADDR HOST_TEXT_START_ADDR
+#endif
+
+#ifdef HOST_STACK_END_ADDR
+#define STACK_END_ADDR HOST_STACK_END_ADDR
+#endif
+
+#ifdef HOST_BIG_ENDIAN_P
+#define TARGET_IS_BIG_ENDIAN_P
+#else
+#undef TARGET_IS_BIG_ENDIAN_P
+#endif
+
+#include "libaout.h" /* BFD a.out internal data structures */
+#include "aout/aout64.h"
+
+#ifdef HOST_MACHINE_ARCH
+#ifdef HOST_MACHINE_MACHINE
+#define SET_ARCH_MACH(abfd, execp) \
+ bfd_default_set_arch_mach(abfd, HOST_MACHINE_ARCH, HOST_MACHINE_MACHINE)
+#else
+#define SET_ARCH_MACH(abfd, execp) \
+ bfd_default_set_arch_mach(abfd, HOST_MACHINE_ARCH, 0)
+#endif
+#endif /* HOST_MACHINE_ARCH */
+
+#define MY(OP) CAT(host_aout_,OP)
+#define TARGETNAME "a.out"
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/hosts/alphalinux.h b/contrib/gdb/bfd/hosts/alphalinux.h
new file mode 100644
index 0000000..d9ba1b7
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/alphalinux.h
@@ -0,0 +1,6 @@
+/* Linux dumps "struct task_struct" at the end of the core-file. This
+ structure is currently 920 bytes long, but we allow up to 1024
+ bytes to allow for some future growth. */
+#define TRAD_CORE_EXTRA_SIZE_ALLOWED 1024
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \
+ ((abfd)->tdata.trad_core_data->u.signal)
diff --git a/contrib/gdb/bfd/hosts/decstation.h b/contrib/gdb/bfd/hosts/decstation.h
new file mode 100644
index 0000000..a80c143
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/decstation.h
@@ -0,0 +1,17 @@
+/* Hopefully this should include either machine/param.h (Ultrix) or
+ machine/machparam.h (Mach), whichever is its name on this system. */
+#include <sys/param.h>
+
+#include <machine/vmparam.h>
+
+#define HOST_PAGE_SIZE NBPG
+/* #define HOST_SEGMENT_SIZE NBPG -- we use HOST_DATA_START_ADDR */
+#define HOST_MACHINE_ARCH bfd_arch_mips
+/* #define HOST_MACHINE_MACHINE */
+
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_DATA_START_ADDR USRDATA
+#define HOST_STACK_END_ADDR USRSTACK
+
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(core_bfd) \
+ ((core_bfd)->tdata.trad_core_data->u.u_arg[0])
diff --git a/contrib/gdb/bfd/hosts/delta68.h b/contrib/gdb/bfd/hosts/delta68.h
new file mode 100644
index 0000000..1a6a6e6
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/delta68.h
@@ -0,0 +1,18 @@
+/* Definitions for a Motorola Delta 3300 box running System V R3.0.
+ Contributed by manfred@lts.sel.alcatel.de. */
+
+#include <sys/param.h>
+
+/* Definitions used by trad-core.c. */
+#define NBPG NBPC
+#define HOST_DATA_START_ADDR u.u_exdata.ux_datorg
+#define HOST_TEXT_START_ADDR u.u_exdata.ux_txtorg
+#if 0
+#define HOST_STACK_END_ADDR 0x40000000
+#else
+/* User's stack, copied from sys/param.h */
+#define HOST_STACK_END_ADDR USRSTACK
+#endif
+#define UPAGES USIZE
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \
+ abfd->tdata.trad_core_data->u.u_abort
diff --git a/contrib/gdb/bfd/hosts/dpx2.h b/contrib/gdb/bfd/hosts/dpx2.h
new file mode 100644
index 0000000..ea6395f
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/dpx2.h
@@ -0,0 +1,8 @@
+/* Definitions that are needed for core files. Core section sizes for
+ the DPX2 are in bytes. */
+
+#include <sys/param.h>
+#define NBPG 1
+#define UPAGES (USIZE * NBPP)
+#define HOST_DATA_START_ADDR (u.u_exdata.ux_datorg)
+#define HOST_STACK_END_ADDR (USERSTACK)
diff --git a/contrib/gdb/bfd/hosts/hp300bsd.h b/contrib/gdb/bfd/hosts/hp300bsd.h
new file mode 100644
index 0000000..9828717
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/hp300bsd.h
@@ -0,0 +1,13 @@
+#include <sys/param.h>
+#ifdef BSD4_4
+#define NO_CORE_COMMAND
+#endif
+
+#define HOST_PAGE_SIZE NBPG
+#define HOST_SEGMENT_SIZE NBPG /* Data seg start addr rounds to NBPG */
+#define HOST_MACHINE_ARCH bfd_arch_m68k
+/* #define HOST_MACHINE_MACHINE */
+
+#define HOST_TEXT_START_ADDR 0
+#define HOST_STACK_END_ADDR 0xfff00000
+#define HOST_BIG_ENDIAN_P
diff --git a/contrib/gdb/bfd/hosts/i386bsd.h b/contrib/gdb/bfd/hosts/i386bsd.h
new file mode 100644
index 0000000..ac0d840
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/i386bsd.h
@@ -0,0 +1,25 @@
+/* Intel 386 running any BSD Unix */
+
+#include <machine/param.h>
+#include <machine/vmparam.h>
+
+#define HOST_PAGE_SIZE NBPG
+#define HOST_MACHINE_ARCH bfd_arch_i386
+#define HOST_TEXT_START_ADDR USRTEXT
+
+/* Jolitz suggested defining HOST_STACK_END_ADDR to
+ (u.u_kproc.kp_eproc.e_vm.vm_maxsaddr + MAXSSIZ), which should work on
+ both BSDI and 386BSD, but that is believed not to work for BSD 4.4. */
+
+#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 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/contrib/gdb/bfd/hosts/i386linux.h b/contrib/gdb/bfd/hosts/i386linux.h
new file mode 100644
index 0000000..13a51f1
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/i386linux.h
@@ -0,0 +1,8 @@
+/* Linux writes the task structure at the end of the core file. Currently it
+ is 2912 bytes. It is possible that this should be a pickier check, but
+ we should probably not be too picky (the size of the task structure might
+ vary, and if it's not the length we expect it to be, it doesn't affect
+ our ability to process the core file). So allow 0-4096 extra bytes at
+ the end. */
+
+#define TRAD_CORE_EXTRA_SIZE_ALLOWED 4096
diff --git a/contrib/gdb/bfd/hosts/i386mach3.h b/contrib/gdb/bfd/hosts/i386mach3.h
new file mode 100644
index 0000000..dcc61e3
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/i386mach3.h
@@ -0,0 +1,25 @@
+#include <machine/vmparam.h>
+#include <sys/param.h>
+
+/* This is an ugly way to hack around the incorrect
+ * definition of UPAGES in i386/machparam.h.
+ *
+ * The definition should specify the size reserved
+ * for "struct user" in core files in PAGES,
+ * but instead it gives it in 512-byte core-clicks
+ * for i386 and i860. UPAGES is used only in trad-core.c.
+ */
+#if UPAGES == 16
+#undef UPAGES
+#define UPAGES 2
+#endif
+
+#if UPAGES != 2
+FIXME!! UPAGES is neither 2 nor 16
+#endif
+
+#define HOST_PAGE_SIZE 1
+#define HOST_SEGMENT_SIZE NBPG
+#define HOST_MACHINE_ARCH bfd_arch_i386
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_STACK_END_ADDR USRSTACK
diff --git a/contrib/gdb/bfd/hosts/i386sco.h b/contrib/gdb/bfd/hosts/i386sco.h
new file mode 100644
index 0000000..ec8608c
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/i386sco.h
@@ -0,0 +1,19 @@
+/* Core file stuff. At least some, perhaps all, of the following
+ defines work on many more systems than just SCO. */
+
+#define NBPG NBPC
+#define UPAGES USIZE
+#define HOST_DATA_START_ADDR u.u_exdata.ux_datorg
+#define HOST_STACK_START_ADDR u.u_sub
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \
+ ((core_upage(abfd)->u_sysabort != 0) \
+ ? core_upage(abfd)->u_sysabort \
+ : -1)
+
+/* According to the manpage, a version 2 SCO corefile can contain
+ various additional sections (it is cleverly arranged so the u area,
+ data, and stack are first where we can find them). So without
+ writing lots of code to parse all their headers and stuff, we can't
+ know whether a corefile is bigger than it should be. */
+
+#define TRAD_CORE_ALLOW_ANY_EXTRA_SIZE 1
diff --git a/contrib/gdb/bfd/hosts/i860mach3.h b/contrib/gdb/bfd/hosts/i860mach3.h
new file mode 100644
index 0000000..edd2aa1
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/i860mach3.h
@@ -0,0 +1,27 @@
+/* This file was hacked from i386mach3.h [dolan@ssd.intel.com] */
+
+#include <machine/vmparam.h>
+#include <sys/param.h>
+
+/* This is an ugly way to hack around the incorrect
+ * definition of UPAGES in i386/machparam.h.
+ *
+ * The definition should specify the size reserved
+ * for "struct user" in core files in PAGES,
+ * but instead it gives it in 512-byte core-clicks
+ * for i386 and i860. UPAGES is used only in trad-core.c.
+ */
+#if UPAGES == 16
+#undef UPAGES
+#define UPAGES 2
+#endif
+
+#if UPAGES != 2
+FIXME!! UPAGES is neither 2 nor 16
+#endif
+
+#define HOST_PAGE_SIZE 1
+#define HOST_SEGMENT_SIZE NBPG
+#define HOST_MACHINE_ARCH bfd_arch_i860
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_STACK_END_ADDR USRSTACK
diff --git a/contrib/gdb/bfd/hosts/m68kaux.h b/contrib/gdb/bfd/hosts/m68kaux.h
new file mode 100644
index 0000000..6237755
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/m68kaux.h
@@ -0,0 +1,16 @@
+/* Definitions for an Apple Macintosh running A/UX 3.x. */
+
+#include <sys/param.h>
+#include <sys/page.h>
+
+/* Definitions used by trad-core.c. */
+#define NBPG NBPP
+
+#define HOST_DATA_START_ADDR u.u_exdata.ux_datorg
+#define HOST_TEXT_START_ADDR u.u_exdata.ux_txtorg
+#define HOST_STACK_END_ADDR 0x100000000
+
+#define UPAGES USIZE
+
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \
+ (abfd->tdata.trad_core_data->u.u_arg[0])
diff --git a/contrib/gdb/bfd/hosts/m68klinux.h b/contrib/gdb/bfd/hosts/m68klinux.h
new file mode 100644
index 0000000..0067dfa
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/m68klinux.h
@@ -0,0 +1,6 @@
+/* Linux dumps "struct task_struct" at the end of the core-file. This
+ structure is currently 2512 bytes long, but we allow up to 4096
+ bytes to allow for some future growth. */
+#define TRAD_CORE_EXTRA_SIZE_ALLOWED 4096
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(abfd) \
+ ((abfd)->tdata.trad_core_data->u.signal)
diff --git a/contrib/gdb/bfd/hosts/m88kmach3.h b/contrib/gdb/bfd/hosts/m88kmach3.h
new file mode 100644
index 0000000..4215538
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/m88kmach3.h
@@ -0,0 +1,11 @@
+#include <machine/vmparam.h>
+#include <sys/param.h>
+
+#undef UPAGES
+#define UPAGES 3
+
+#define HOST_PAGE_SIZE NBPG
+#define HOST_SEGMENT_SIZE NBPG
+#define HOST_MACHINE_ARCH bfd_arch_m88k
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_STACK_END_ADDR USRSTACK
diff --git a/contrib/gdb/bfd/hosts/mipsbsd.h b/contrib/gdb/bfd/hosts/mipsbsd.h
new file mode 100644
index 0000000..a2fad21
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/mipsbsd.h
@@ -0,0 +1,12 @@
+#include <machine/param.h>
+#include <machine/vmparam.h>
+#undef ALIGN
+
+#define HOST_PAGE_SIZE NBPG
+/* #define HOST_SEGMENT_SIZE NBPG -- we use HOST_DATA_START_ADDR */
+#define HOST_MACHINE_ARCH bfd_arch_mips
+/* #define HOST_MACHINE_MACHINE */
+
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_STACK_END_ADDR USRSTACK
+#define NO_CORE_COMMAND
diff --git a/contrib/gdb/bfd/hosts/mipsmach3.h b/contrib/gdb/bfd/hosts/mipsmach3.h
new file mode 100644
index 0000000..c5c468d
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/mipsmach3.h
@@ -0,0 +1,10 @@
+#include <machine/vmparam.h>
+#include <machine/machparam.h>
+#include <sys/param.h>
+
+#define HOST_PAGE_SIZE NBPG
+/* #define HOST_SEGMENT_SIZE NBPG */
+#define HOST_MACHINE_ARCH bfd_arch_mips
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_DATA_START_ADDR USRDATA
+#define HOST_STACK_END_ADDR USRSTACK
diff --git a/contrib/gdb/bfd/hosts/news-mips.h b/contrib/gdb/bfd/hosts/news-mips.h
new file mode 100644
index 0000000..9e799be
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/news-mips.h
@@ -0,0 +1,12 @@
+/* Sony News running NewsOS 3.2. */
+
+#include <sys/param.h>
+#include <machine/vmparam.h>
+
+#define HOST_PAGE_SIZE NBPG
+
+#define HOST_MACHINE_ARCH bfd_arch_mips
+
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_DATA_START_ADDR USRDATA
+#define HOST_STACK_END_ADDR USRSTACK
diff --git a/contrib/gdb/bfd/hosts/news.h b/contrib/gdb/bfd/hosts/news.h
new file mode 100644
index 0000000..bf7946c
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/news.h
@@ -0,0 +1,9 @@
+/* Sony News running NewsOS 3.2. */
+
+#include <machine/vmparam.h>
+
+#define HOST_PAGE_SIZE NBPG
+#define HOST_SEGMENT_SIZE NBPG
+#define HOST_MACHINE_ARCH bfd_arch_m68k
+#define HOST_TEXT_START_ADDR 0
+#define HOST_STACK_END_ADDR (KERNBASE - (UPAGES * NBPG))
diff --git a/contrib/gdb/bfd/hosts/pc532mach.h b/contrib/gdb/bfd/hosts/pc532mach.h
new file mode 100644
index 0000000..ab96f59
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/pc532mach.h
@@ -0,0 +1,24 @@
+#include <machine/vmparam.h>
+#include <sys/param.h>
+
+/* This is an ugly way to hack around the incorrect
+ * definition of UPAGES in ns532/machparam.h.
+ *
+ * The definition should specify the size reserved
+ * for "struct user" in core files in PAGES,
+ * but instead it gives it in 512-byte core-clicks
+ * for ns532, i386 and i860. UPAGES is used only in trad-core.c.
+ */
+#if UPAGES == 16
+#undef UPAGES
+#define UPAGES 2
+#endif
+
+#if UPAGES != 2
+#error UPAGES is neither 2 nor 16
+#endif
+
+#define HOST_PAGE_SIZE 1
+#define HOST_SEGMENT_SIZE NBPG
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_STACK_END_ADDR USRSTACK
diff --git a/contrib/gdb/bfd/hosts/riscos.h b/contrib/gdb/bfd/hosts/riscos.h
new file mode 100644
index 0000000..8ffa826
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/riscos.h
@@ -0,0 +1,10 @@
+/* RISC/os 4.52C, and presumably other versions. */
+
+#include <bsd43/machine/machparam.h>
+#include <bsd43/machine/vmparam.h>
+
+#define NBPG BSD43_NBPG
+#define UPAGES BSD43_UPAGES
+#define HOST_TEXT_START_ADDR BSD43_USRTEXT
+#define HOST_DATA_START_ADDR BSD43_USRDATA
+#define HOST_STACK_END_ADDR BSD43_USRSTACK
diff --git a/contrib/gdb/bfd/hosts/symmetry.h b/contrib/gdb/bfd/hosts/symmetry.h
new file mode 100644
index 0000000..75717b3
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/symmetry.h
@@ -0,0 +1,20 @@
+/* Symmetry running either dynix 3.1 (bsd) or ptx (sysv). */
+
+#define NBPG 4096
+#define UPAGES 1
+
+#ifdef _SEQUENT_
+/* ptx */
+#define HOST_TEXT_START_ADDR 0
+#define HOST_STACK_END_ADDR 0x3fffe000
+#define TRAD_CORE_USER_OFFSET ((UPAGES * NBPG) - sizeof (struct user))
+#else
+/* dynix */
+#define HOST_TEXT_START_ADDR 0x1000
+#define HOST_DATA_START_ADDR (NBPG * u.u_tsize)
+#define HOST_STACK_END_ADDR 0x3ffff000
+#define TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(core_bfd) \
+ ((core_bfd)->tdata.trad_core_data->u.u_arg[0])
+#endif
+
+#define TRAD_CORE_DSIZE_INCLUDES_TSIZE
diff --git a/contrib/gdb/bfd/hosts/tahoe.h b/contrib/gdb/bfd/hosts/tahoe.h
new file mode 100644
index 0000000..716cee2
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/tahoe.h
@@ -0,0 +1,12 @@
+#define NO_CORE_COMMAND
+
+#undef ALIGN /* They use it, we use it too */
+#include <machine/param.h>
+#undef ALIGN /* They use it, we use it too */
+
+#define HOST_PAGE_SIZE NBPG
+#define HOST_MACHINE_ARCH bfd_arch_tahoe
+
+#define HOST_TEXT_START_ADDR 0
+#define HOST_STACK_END_ADDR (KERNBASE - (UPAGES * NBPG))
+#define HOST_BIG_ENDIAN_P
diff --git a/contrib/gdb/bfd/hosts/vaxbsd.h b/contrib/gdb/bfd/hosts/vaxbsd.h
new file mode 100644
index 0000000..ceb9cce
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/vaxbsd.h
@@ -0,0 +1,19 @@
+#define NO_CORE_COMMAND /* No command name in core file */
+
+#if 0
+#undef ALIGN /* They use it, we use it too */
+/* Does not exist on BSD 4.3, it uses machine/machparam.h.
+ Whatever it is, it's included by <sys/param.h>, which trad-core.c,
+ the only place that uses this (I think), already includes. */
+#include <machine/param.h>
+#endif
+#undef ALIGN /* They use it, we use it too */
+
+/* Note that HOST_PAGE_SIZE -- the page size as far as executable files
+ are concerned -- is not the same as NBPG, because of page clustering. */
+#define HOST_PAGE_SIZE 1024
+#define HOST_MACHINE_ARCH bfd_arch_vax
+
+#define HOST_TEXT_START_ADDR 0
+#define HOST_STACK_END_ADDR (0x80000000 - (UPAGES * NBPG))
+#undef HOST_BIG_ENDIAN_P
diff --git a/contrib/gdb/bfd/hosts/vaxult.h b/contrib/gdb/bfd/hosts/vaxult.h
new file mode 100644
index 0000000..13731b7
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/vaxult.h
@@ -0,0 +1,8 @@
+#include <machine/param.h>
+#include <machine/vmparam.h>
+#define HOST_PAGE_SIZE (NBPG*CLSIZE)
+#define HOST_MACHINE_ARCH bfd_arch_vax
+
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_STACK_END_ADDR USRSTACK
+#undef HOST_BIG_ENDIAN_P
diff --git a/contrib/gdb/bfd/hosts/vaxult2.h b/contrib/gdb/bfd/hosts/vaxult2.h
new file mode 100644
index 0000000..13731b7
--- /dev/null
+++ b/contrib/gdb/bfd/hosts/vaxult2.h
@@ -0,0 +1,8 @@
+#include <machine/param.h>
+#include <machine/vmparam.h>
+#define HOST_PAGE_SIZE (NBPG*CLSIZE)
+#define HOST_MACHINE_ARCH bfd_arch_vax
+
+#define HOST_TEXT_START_ADDR USRTEXT
+#define HOST_STACK_END_ADDR USRSTACK
+#undef HOST_BIG_ENDIAN_P
diff --git a/contrib/gdb/bfd/hp300bsd.c b/contrib/gdb/bfd/hp300bsd.c
new file mode 100644
index 0000000..5767b18
--- /dev/null
+++ b/contrib/gdb/bfd/hp300bsd.c
@@ -0,0 +1,38 @@
+/* BFD back-end for HP 9000/300 (68000-based) machines running BSD Unix.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_IS_BIG_ENDIAN_P
+#define N_HEADER_IN_TEXT(x) 0
+#define BYTES_IN_WORD 4
+#define ENTRY_CAN_BE_ZERO
+#define N_SHARED_LIB(x) 0 /* Avoids warning */
+#define TEXT_START_ADDR 0
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_m68k
+
+#define MY(OP) CAT(hp300bsd_,OP)
+#define TARGETNAME "a.out-hp300bsd"
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/hp300hpux.c b/contrib/gdb/bfd/hp300hpux.c
new file mode 100644
index 0000000..1d1acab
--- /dev/null
+++ b/contrib/gdb/bfd/hp300hpux.c
@@ -0,0 +1,865 @@
+/* BFD backend for hp-ux 9000/300
+ Copyright (C) 1990, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Written by Glenn Engel.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+
+ hpux native ------------> | |
+ | hp300hpux bfd | ----------> hpux w/gnu ext
+ hpux w/gnu extension ----> | |
+
+
+ Support for the 9000/[34]00 has several limitations.
+ 1. Shared libraries are not supported.
+ 2. The output format from this bfd is not usable by native tools.
+
+ The primary motivation for writing this bfd was to allow use of
+ gdb and gcc for host based debugging and not to mimic the hp-ux tools
+ in every detail. This leads to a significant simplification of the
+ code and a leap in performance. The decision to not output hp native
+ compatible objects was further strengthened by the fact that the richness
+ of the gcc compiled objects could not be represented without loss of
+ information. For example, while the hp format supports the concept of
+ secondary symbols, it does not support indirect symbols. Another
+ reason is to maintain backwards compatibility with older implementations
+ of gcc on hpux which used 'hpxt' to translate .a and .o files into a
+ format which could be readily understood by the gnu linker and gdb.
+ This allows reading hp secondary symbols and converting them into
+ indirect symbols but the reverse it not always possible.
+
+ Another example of differences is that the hp format stores symbol offsets
+ in the object code while the gnu utilities use a field in the
+ relocation record for this. To support the hp native format, the object
+ code would need to be patched with the offsets when producing .o files.
+
+ The basic technique taken in this implementation is to #include the code
+ from aoutx.h and aout-target.h with appropriate #defines to override
+ code where a unique implementation is needed:
+
+ {
+ #define a bunch of stuff
+ #include <aoutx.h>
+
+ implement a bunch of functions
+
+ #include "aout-target.h"
+ }
+
+ The hp symbol table is a bit different than other a.out targets. Instead
+ of having an array of nlist items and an array of strings, hp's format
+ has them mixed together in one structure. In addition, the strings are
+ not null terminated. It looks something like this:
+
+ nlist element 1
+ string1
+ nlist element 2
+ string2
+ ...
+
+ The whole symbol table is read as one chunk and then we march thru it
+ and convert it to canonical form. As we march thru the table, we copy
+ the nlist data into the internal form and we compact the strings and null
+ terminate them, using storage from the already allocated symbol table:
+
+ string1
+ null
+ string2
+ null
+ */
+
+/* @@ Is this really so different from normal a.out that it needs to include
+ aoutx.h? We should go through this file sometime and see what can be made
+ more dependent on aout32.o and what might need to be broken off and accessed
+ through the backend_data field. Or, maybe we really do need such a
+ completely separate implementation. I don't have time to investigate this
+ much further right now. [raeburn:19930428.2124EST] */
+/* @@ Also, note that there wind up being two versions of some routines, with
+ different names, only one of which actually gets used. For example:
+ slurp_symbol_table
+ swap_std_reloc_in
+ slurp_reloc_table
+ get_symtab
+ get_symtab_upper_bound
+ canonicalize_reloc
+ mkobject
+ This should also be fixed. */
+
+#define TARGETNAME "a.out-hp300hpux"
+#define MY(OP) CAT(hp300hpux_,OP)
+
+#define external_exec hp300hpux_exec_bytes
+#define external_nlist hp300hpux_nlist_bytes
+
+#include "aout/hp300hpux.h"
+
+/* define these so we can compile unused routines in aoutx.h */
+#define e_strx e_shlib
+#define e_other e_length
+#define e_desc e_almod
+
+#define AR_PAD_CHAR '/'
+#define TARGET_IS_BIG_ENDIAN_P
+#define DEFAULT_ARCH bfd_arch_m68k
+
+#define MY_get_section_contents aout_32_get_section_contents
+#define MY_slurp_armap bfd_slurp_bsd_armap_f2
+
+/***********************************************/
+/* provide overrides for routines in this file */
+/***********************************************/
+/* these don't use MY because that causes problems within JUMP_TABLE
+ (CAT winds up being expanded recursively, which ANSI C compilers
+ will not do). */
+#define MY_get_symtab hp300hpux_get_symtab
+#define MY_get_symtab_upper_bound hp300hpux_get_symtab_upper_bound
+#define MY_canonicalize_reloc hp300hpux_canonicalize_reloc
+#define MY_write_object_contents hp300hpux_write_object_contents
+
+#define MY_read_minisymbols _bfd_generic_read_minisymbols
+#define MY_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define MY_final_link_callback unused
+#define MY_bfd_final_link _bfd_generic_final_link
+
+/* Until and unless we convert the slurp_reloc and slurp_symtab
+ routines in this file, we can not use the default aout
+ free_cached_info routine which assumes that the relocs and symtabs
+ were allocated using malloc. */
+#define MY_bfd_free_cached_info bfd_true
+
+#define hp300hpux_write_syms aout_32_write_syms
+
+#define MY_callback MY(callback)
+
+#define MY_exec_hdr_flags 0x2
+
+#define NAME_swap_exec_header_in NAME(hp300hpux_32_,swap_exec_header_in)
+
+#define HP_SYMTYPE_UNDEFINED 0x00
+#define HP_SYMTYPE_ABSOLUTE 0x01
+#define HP_SYMTYPE_TEXT 0x02
+#define HP_SYMTYPE_DATA 0x03
+#define HP_SYMTYPE_BSS 0x04
+#define HP_SYMTYPE_COMMON 0x05
+
+#define HP_SYMTYPE_TYPE 0x0F
+#define HP_SYMTYPE_FILENAME 0x1F
+
+#define HP_SYMTYPE_ALIGN 0x10
+#define HP_SYMTYPE_EXTERNAL 0x20
+#define HP_SECONDARY_SYMBOL 0x40
+
+/* RELOCATION DEFINITIONS */
+#define HP_RSEGMENT_TEXT 0x00
+#define HP_RSEGMENT_DATA 0x01
+#define HP_RSEGMENT_BSS 0x02
+#define HP_RSEGMENT_EXTERNAL 0x03
+#define HP_RSEGMENT_PCREL 0x04
+#define HP_RSEGMENT_RDLT 0x05
+#define HP_RSEGMENT_RPLT 0x06
+#define HP_RSEGMENT_NOOP 0x3F
+
+#define HP_RLENGTH_BYTE 0x00
+#define HP_RLENGTH_WORD 0x01
+#define HP_RLENGTH_LONG 0x02
+#define HP_RLENGTH_ALIGN 0x03
+
+#define NAME(x,y) CAT3(hp300hpux,_32_,y)
+#define ARCH_SIZE 32
+
+/* aoutx.h requires definitions for BMAGIC and QMAGIC. */
+#define BMAGIC HPUX_DOT_O_MAGIC
+#define QMAGIC 0314
+
+#include "aoutx.h"
+
+/* Since the hpux symbol table has nlist elements interspersed with
+ strings and we need to insert som strings for secondary symbols, we
+ give ourselves a little extra padding up front to account for
+ this. Note that for each non-secondary symbol we process, we gain
+ 9 bytes of space for the discarded nlist element (one byte used for
+ null). SYM_EXTRA_BYTES is the extra space. */
+#define SYM_EXTRA_BYTES 1024
+
+/* Set parameters about this a.out file that are machine-dependent.
+ This routine is called from some_aout_object_p just before it returns. */
+static const bfd_target *
+MY (callback) (abfd)
+ bfd *abfd;
+{
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ /* Calculate the file positions of the parts of a newly read aout header */
+ obj_textsec (abfd)->_raw_size = N_TXTSIZE (*execp);
+
+ /* The virtual memory addresses of the sections */
+ obj_textsec (abfd)->vma = N_TXTADDR (*execp);
+ obj_datasec (abfd)->vma = N_DATADDR (*execp);
+ obj_bsssec (abfd)->vma = N_BSSADDR (*execp);
+
+ obj_textsec (abfd)->lma = obj_textsec (abfd)->vma;
+ obj_datasec (abfd)->lma = obj_datasec (abfd)->vma;
+ obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma;
+
+ /* The file offsets of the sections */
+ obj_textsec (abfd)->filepos = N_TXTOFF (*execp);
+ obj_datasec (abfd)->filepos = N_DATOFF (*execp);
+
+ /* The file offsets of the relocation info */
+ obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp);
+ obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp);
+
+ /* The file offsets of the string table and symbol table. */
+ obj_sym_filepos (abfd) = N_SYMOFF (*execp);
+ obj_str_filepos (abfd) = N_STROFF (*execp);
+
+ /* Determine the architecture and machine type of the object file. */
+#ifdef SET_ARCH_MACH
+ SET_ARCH_MACH (abfd, *execp);
+#else
+ bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0);
+#endif
+
+
+ if (obj_aout_subformat (abfd) == gnu_encap_format)
+ {
+ /* The file offsets of the relocation info */
+ obj_textsec (abfd)->rel_filepos = N_GNU_TRELOFF (*execp);
+ obj_datasec (abfd)->rel_filepos = N_GNU_DRELOFF (*execp);
+
+ /* The file offsets of the string table and symbol table. */
+ obj_sym_filepos (abfd) = N_GNU_SYMOFF (*execp);
+ obj_str_filepos (abfd) = (obj_sym_filepos (abfd) + execp->a_syms);
+
+ abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+ bfd_get_symcount (abfd) = execp->a_syms / 12;
+ obj_symbol_entry_size (abfd) = 12;
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+ }
+
+ return abfd->xvec;
+}
+
+extern boolean aout_32_write_syms PARAMS ((bfd * abfd));
+
+static boolean
+MY (write_object_contents) (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+ bfd_size_type text_size; /* dummy vars */
+ file_ptr text_end;
+
+ memset (&exec_bytes, 0, sizeof (exec_bytes));
+#if CHOOSE_RELOC_SIZE
+ CHOOSE_RELOC_SIZE (abfd);
+#else
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+#endif
+
+ if (adata (abfd).magic == undecided_magic)
+ NAME (aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);
+ execp->a_syms = 0;
+
+ execp->a_entry = bfd_get_start_address (abfd);
+
+ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *
+ obj_reloc_entry_size (abfd));
+ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *
+ obj_reloc_entry_size (abfd));
+
+ N_SET_MACHTYPE (*execp, 0xc);
+ N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);
+
+ NAME (aout,swap_exec_header_out) (abfd, execp, &exec_bytes);
+
+ /* update fields not covered by default swap_exec_header_out */
+
+ /* this is really the sym table size but we store it in drelocs */
+ bfd_h_put_32 (abfd, bfd_get_symcount (abfd) * 12, exec_bytes.e_drelocs);
+
+ if (bfd_seek (abfd, 0L, false) != 0
+ || (bfd_write ((PTR) & exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE))
+ return false;
+
+ /* Write out the symbols, and then the relocs. We must write out
+ the symbols first so that we know the symbol indices. */
+
+ if (bfd_get_symcount (abfd) != 0)
+ {
+ /* Skip the relocs to where we want to put the symbols. */
+ if (bfd_seek (abfd, (file_ptr) N_DRELOFF (*execp) + execp->a_drsize,
+ SEEK_SET) != 0)
+ return false;
+ }
+
+ if (!MY (write_syms) (abfd))
+ return false;
+
+ if (bfd_get_symcount (abfd) != 0)
+ {
+ if (bfd_seek (abfd, (long) (N_TRELOFF (*execp)), false) != 0)
+ return false;
+ if (!NAME (aout,squirt_out_relocs) (abfd, obj_textsec (abfd)))
+ return false;
+ if (bfd_seek (abfd, (long) (N_DRELOFF (*execp)), false) != 0)
+ return false;
+ if (!NAME (aout,squirt_out_relocs) (abfd, obj_datasec (abfd)))
+ return false;
+ }
+
+ return true;
+}
+
+/* convert the hp symbol type to be the same as aout64.h usage so we */
+/* can piggyback routines in aoutx.h. */
+
+static void
+convert_sym_type (sym_pointer, cache_ptr, abfd)
+ struct external_nlist *sym_pointer;
+ aout_symbol_type *cache_ptr;
+ bfd *abfd;
+{
+ int name_type;
+ int new_type;
+
+ name_type = (cache_ptr->type);
+ new_type = 0;
+
+ if ((name_type & HP_SYMTYPE_ALIGN) != 0)
+ {
+ /* iou_error ("aligned symbol encountered: %s", name);*/
+ name_type = 0;
+ }
+
+ if (name_type == HP_SYMTYPE_FILENAME)
+ new_type = N_FN;
+ else
+ {
+ switch (name_type & HP_SYMTYPE_TYPE)
+ {
+ case HP_SYMTYPE_UNDEFINED:
+ new_type = N_UNDF;
+ break;
+
+ case HP_SYMTYPE_ABSOLUTE:
+ new_type = N_ABS;
+ break;
+
+ case HP_SYMTYPE_TEXT:
+ new_type = N_TEXT;
+ break;
+
+ case HP_SYMTYPE_DATA:
+ new_type = N_DATA;
+ break;
+
+ case HP_SYMTYPE_BSS:
+ new_type = N_BSS;
+ break;
+
+ case HP_SYMTYPE_COMMON:
+ new_type = N_COMM;
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+ if (name_type & HP_SYMTYPE_EXTERNAL)
+ new_type |= N_EXT;
+
+ if (name_type & HP_SECONDARY_SYMBOL)
+ {
+ switch (new_type)
+ {
+ default:
+ abort ();
+ case N_UNDF | N_EXT:
+ new_type = N_WEAKU;
+ break;
+ case N_ABS | N_EXT:
+ new_type = N_WEAKA;
+ break;
+ case N_TEXT | N_EXT:
+ new_type = N_WEAKT;
+ break;
+ case N_DATA | N_EXT:
+ new_type = N_WEAKD;
+ break;
+ case N_BSS | N_EXT:
+ new_type = N_WEAKB;
+ break;
+ }
+ }
+ }
+ cache_ptr->type = new_type;
+
+}
+
+
+/*
+DESCRIPTION
+ Swaps the information in an executable header taken from a raw
+ byte stream memory image, into the internal exec_header
+ structure.
+*/
+
+void
+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;
+
+ /* The internal_exec structure has some fields that are unused in this
+ 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));
+ /* 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);
+ execp->a_data = GET_WORD (abfd, bytes->e_data);
+ execp->a_bss = GET_WORD (abfd, bytes->e_bss);
+ execp->a_syms = GET_WORD (abfd, bytes->e_syms);
+ execp->a_entry = GET_WORD (abfd, bytes->e_entry);
+ execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
+ execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
+
+ /***************************************************************/
+ /* check the header to see if it was generated by a bfd output */
+ /* this is detected rather bizarely by requiring a bunch of */
+ /* header fields to be zero and an old unused field (now used) */
+ /* to be set. */
+ /***************************************************************/
+ do
+ {
+ long syms;
+ struct aout_data_struct *rawptr;
+ if (bfd_h_get_32 (abfd, bytes->e_passize) != 0)
+ break;
+ if (bfd_h_get_32 (abfd, bytes->e_syms) != 0)
+ break;
+ if (bfd_h_get_32 (abfd, bytes->e_supsize) != 0)
+ break;
+
+ syms = bfd_h_get_32 (abfd, bytes->e_drelocs);
+ if (syms == 0)
+ break;
+
+ /* OK, we've passed the test as best as we can determine */
+ execp->a_syms = syms;
+
+ /* allocate storage for where we will store this result */
+ rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, sizeof (*rawptr));
+
+ if (rawptr == NULL)
+ return;
+ abfd->tdata.aout_data = rawptr;
+ obj_aout_subformat (abfd) = gnu_encap_format;
+ }
+ while (0);
+}
+
+
+/* The hp symbol table is a bit different than other a.out targets. Instead
+ of having an array of nlist items and an array of strings, hp's format
+ has them mixed together in one structure. In addition, the strings are
+ not null terminated. It looks something like this:
+
+ nlist element 1
+ string1
+ nlist element 2
+ string2
+ ...
+
+ The whole symbol table is read as one chunk and then we march thru it
+ and convert it to canonical form. As we march thru the table, we copy
+ the nlist data into the internal form and we compact the strings and null
+ terminate them, using storage from the already allocated symbol table:
+
+ string1
+ null
+ string2
+ null
+ ...
+*/
+
+boolean
+MY (slurp_symbol_table) (abfd)
+ bfd *abfd;
+{
+ bfd_size_type symbol_bytes;
+ struct external_nlist *syms;
+ struct external_nlist *sym_pointer;
+ struct external_nlist *sym_end;
+ char *strings;
+ aout_symbol_type *cached;
+ unsigned num_syms = 0;
+
+ /* If there's no work to be done, don't do any */
+ if (obj_aout_symbols (abfd) != (aout_symbol_type *) NULL)
+ return true;
+ symbol_bytes = exec_hdr (abfd)->a_syms;
+
+ strings = (char *) bfd_alloc (abfd,
+ symbol_bytes + SYM_EXTRA_BYTES);
+ if (!strings)
+ return false;
+ syms = (struct external_nlist *) (strings + SYM_EXTRA_BYTES);
+ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0
+ || bfd_read ((PTR) syms, symbol_bytes, 1, abfd) != symbol_bytes)
+ {
+ bfd_release (abfd, syms);
+ return false;
+ }
+
+
+ sym_end = (struct external_nlist *) (((char *) syms) + symbol_bytes);
+
+ /* first, march thru the table and figure out how many symbols there are */
+ for (sym_pointer = syms; sym_pointer < sym_end; sym_pointer++, num_syms++)
+ {
+ /* skip over the embedded symbol. */
+ sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
+ sym_pointer->e_length[0]);
+ }
+
+ /* now that we know the symbol count, update the bfd header */
+ bfd_get_symcount (abfd) = num_syms;
+
+ cached = ((aout_symbol_type *)
+ bfd_zalloc (abfd,
+ bfd_get_symcount (abfd) * sizeof (aout_symbol_type)));
+ if (cached == NULL && bfd_get_symcount (abfd) != 0)
+ return false;
+
+ /* as we march thru the hp symbol table, convert it into a list of
+ null terminated strings to hold the symbol names. Make sure any
+ assignment to the strings pointer is done after we're thru using
+ the nlist so we don't overwrite anything important. */
+
+ /* OK, now walk the new symtable, cacheing symbol properties */
+ {
+ aout_symbol_type *cache_ptr = cached;
+ aout_symbol_type cache_save;
+ /* Run through table and copy values */
+ for (sym_pointer = syms, cache_ptr = cached;
+ sym_pointer < sym_end; sym_pointer++, cache_ptr++)
+ {
+ unsigned int length;
+ cache_ptr->symbol.the_bfd = abfd;
+ cache_ptr->symbol.value = GET_SWORD (abfd, sym_pointer->e_value);
+ cache_ptr->desc = bfd_get_16 (abfd, sym_pointer->e_almod);
+ cache_ptr->type = bfd_get_8 (abfd, sym_pointer->e_type);
+ cache_ptr->symbol.udata.p = NULL;
+ length = bfd_get_8 (abfd, sym_pointer->e_length);
+ cache_ptr->other = length; /* other not used, save length here */
+
+ cache_save = *cache_ptr;
+ convert_sym_type (sym_pointer, cache_ptr, abfd);
+ if (!translate_from_native_sym_flags (abfd, cache_ptr))
+ return false;
+
+ /********************************************************/
+ /* for hpux, the 'lenght' value indicates the length of */
+ /* the symbol name which follows the nlist entry. */
+ /********************************************************/
+ if (length)
+ {
+ /**************************************************************/
+ /* the hp string is not null terminated so we create a new one*/
+ /* by copying the string to overlap the just vacated nlist */
+ /* structure before it in memory. */
+ /**************************************************************/
+ cache_ptr->symbol.name = strings;
+ memcpy (strings, sym_pointer + 1, length);
+ strings[length] = '\0';
+ strings += length + 1;
+ }
+ else
+ cache_ptr->symbol.name = (char *) NULL;
+
+ /* skip over the embedded symbol. */
+ sym_pointer = (struct external_nlist *) (((char *) sym_pointer) +
+ length);
+ }
+ }
+
+ obj_aout_symbols (abfd) = cached;
+
+ return true;
+}
+
+
+
+void
+MY (swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
+ bfd *abfd;
+ struct hp300hpux_reloc *bytes;
+ arelent *cache_ptr;
+ asymbol **symbols;
+ bfd_size_type symcount;
+{
+ int r_index;
+ int r_extern = 0;
+ unsigned int r_length;
+ int r_pcrel = 0;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+
+ cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
+ r_index = bfd_h_get_16 (abfd, bytes->r_index);
+
+ switch (bytes->r_type[0])
+ {
+ case HP_RSEGMENT_TEXT:
+ r_index = N_TEXT;
+ break;
+ case HP_RSEGMENT_DATA:
+ r_index = N_DATA;
+ break;
+ case HP_RSEGMENT_BSS:
+ r_index = N_BSS;
+ break;
+ case HP_RSEGMENT_EXTERNAL:
+ r_extern = 1;
+ break;
+ case HP_RSEGMENT_PCREL:
+ r_extern = 1;
+ r_pcrel = 1;
+ break;
+ case HP_RSEGMENT_RDLT:
+ break;
+ case HP_RSEGMENT_RPLT:
+ break;
+ case HP_RSEGMENT_NOOP:
+ break;
+ default:
+ abort ();
+ break;
+ }
+
+ switch (bytes->r_length[0])
+ {
+ case HP_RLENGTH_BYTE:
+ r_length = 0;
+ break;
+ case HP_RLENGTH_WORD:
+ r_length = 1;
+ break;
+ case HP_RLENGTH_LONG:
+ r_length = 2;
+ break;
+ default:
+ abort ();
+ break;
+ }
+
+ cache_ptr->howto = howto_table_std + r_length + 4 * r_pcrel;
+ /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
+
+ /* This macro uses the r_index value computed above */
+ if (r_pcrel && r_extern)
+ {
+ /* The GNU linker assumes any offset from beginning of section */
+ /* is already incorporated into the image while the HP linker */
+ /* adds this in later. Add it in now... */
+ MOVE_ADDRESS (-cache_ptr->address);
+ }
+ else
+ {
+ MOVE_ADDRESS (0);
+ }
+}
+
+boolean
+MY (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;
+ struct hp300hpux_reloc *rptr;
+ unsigned int counter;
+ arelent *cache_ptr;
+
+ if (asect->relocation)
+ return true;
+
+ if (asect->flags & SEC_CONSTRUCTOR)
+ return true;
+
+ if (asect == obj_datasec (abfd))
+ {
+ reloc_size = exec_hdr (abfd)->a_drsize;
+ goto doit;
+ }
+
+ if (asect == obj_textsec (abfd))
+ {
+ reloc_size = exec_hdr (abfd)->a_trsize;
+ goto doit;
+ }
+
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+
+doit:
+ if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
+ return false;
+ 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 && count != 0)
+ return false;
+
+ relocs = (PTR) bfd_alloc (abfd, reloc_size);
+ if (!relocs && reloc_size != 0)
+ {
+ bfd_release (abfd, reloc_cache);
+ return false;
+ }
+
+ if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
+ {
+ bfd_release (abfd, relocs);
+ bfd_release (abfd, reloc_cache);
+ return false;
+ }
+
+ rptr = (struct hp300hpux_reloc *) relocs;
+ counter = 0;
+ cache_ptr = reloc_cache;
+
+ for (; counter < count; counter++, rptr++, cache_ptr++)
+ {
+ MY (swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
+ bfd_get_symcount (abfd));
+ }
+
+
+ bfd_release (abfd, relocs);
+ asect->relocation = reloc_cache;
+ asect->reloc_count = count;
+ return true;
+}
+
+
+/************************************************************************/
+/* The following functions are identical to functions in aoutx.h except */
+/* they refer to MY(func) rather than NAME(aout,func) and they also */
+/* call aout_32 versions if the input file was generated by gcc */
+/************************************************************************/
+
+long aout_32_get_symtab PARAMS ((bfd * abfd, asymbol ** location));
+long aout_32_get_symtab_upper_bound PARAMS ((bfd * abfd));
+
+long aout_32_canonicalize_reloc PARAMS ((bfd * abfd, sec_ptr section,
+ arelent ** relptr,
+ asymbol ** symbols));
+
+long
+MY (get_symtab) (abfd, location)
+ bfd *abfd;
+ asymbol **location;
+{
+ unsigned int counter = 0;
+ aout_symbol_type *symbase;
+
+ if (obj_aout_subformat (abfd) == gnu_encap_format)
+ return aout_32_get_symtab (abfd, location);
+
+ if (!MY (slurp_symbol_table) (abfd))
+ return -1;
+
+ for (symbase = obj_aout_symbols (abfd); counter++ < bfd_get_symcount (abfd);)
+ *(location++) = (asymbol *) (symbase++);
+ *location++ = 0;
+ return bfd_get_symcount (abfd);
+}
+
+long
+MY (get_symtab_upper_bound) (abfd)
+ bfd *abfd;
+{
+ if (obj_aout_subformat (abfd) == gnu_encap_format)
+ return aout_32_get_symtab_upper_bound (abfd);
+ if (!MY (slurp_symbol_table) (abfd))
+ return -1;
+
+ return (bfd_get_symcount (abfd) + 1) * (sizeof (aout_symbol_type *));
+}
+
+
+
+
+long
+MY (canonicalize_reloc) (abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *tblptr = section->relocation;
+ unsigned int count;
+ if (obj_aout_subformat (abfd) == gnu_encap_format)
+ return aout_32_canonicalize_reloc (abfd, section, relptr, symbols);
+
+ if (!(tblptr || MY (slurp_reloc_table) (abfd, section, symbols)))
+ return -1;
+
+ if (section->flags & SEC_CONSTRUCTOR)
+ {
+ arelent_chain *chain = section->constructor_chain;
+ for (count = 0; count < section->reloc_count; count++)
+ {
+ *relptr++ = &chain->relent;
+ chain = chain->next;
+ }
+ }
+ else
+ {
+ tblptr = section->relocation;
+
+ for (count = 0; count++ < section->reloc_count;)
+ {
+ *relptr++ = tblptr++;
+ }
+ }
+ *relptr = 0;
+
+ return section->reloc_count;
+}
+
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/hppa_stubs.h b/contrib/gdb/bfd/hppa_stubs.h
new file mode 100644
index 0000000..ee893e8
--- /dev/null
+++ b/contrib/gdb/bfd/hppa_stubs.h
@@ -0,0 +1,23 @@
+/* HPPA linker stub instructions */
+
+/* These are the instructions which the linker may insert into the
+ code stream when building final executables to handle out-of-range
+ calls and argument relocations. */
+
+#define LDO_M4_R31_R31 0x37ff3ff9 /* ldo -4(%r31),%r31 */
+#define LDIL_R1 0x20200000 /* ldil XXX,%r1 */
+#define BE_SR4_R1 0xe0202000 /* be XXX(%sr4,%r1) */
+#define COPY_R31_R2 0x081f0242 /* copy %r31,%r2 */
+#define BLE_SR4_R0 0xe4002000 /* ble XXX(%sr4,%r0) */
+#define BLE_SR4_R1 0xe4202000 /* ble XXX(%sr4,%r1) */
+#define BV_N_0_R31 0xebe0c002 /* bv,n 0(%r31) */
+#define STW_R31_M8R30 0x6bdf3ff1 /* stw %r31,-8(%r30) */
+#define LDW_M8R30_R31 0x4bdf3ff1 /* ldw -8(%r30),%r31 */
+#define STW_ARG_M16R30 0x6bc03fe1 /* stw %argX,-16(%r30) */
+#define LDW_M16R30_ARG 0x4bc03fe1 /* ldw -12(%r30),%argX */
+#define STW_ARG_M12R30 0x6bc03fe9 /* stw %argX,-16(%r30) */
+#define LDW_M12R30_ARG 0x4bc03fe9 /* ldw -12(%r30),%argX */
+#define FSTW_FARG_M16R30 0x27c11200 /* fstws %fargX,-16(%r30) */
+#define FLDW_M16R30_FARG 0x27c11000 /* fldws -16(%r30),%fargX */
+#define FSTD_FARG_M16R30 0x2fc11200 /* fstds %fargX,-16(%r30) */
+#define FLDD_M16R30_FARG 0x2fc11000 /* fldds -16(%r30),%fargX */
diff --git a/contrib/gdb/bfd/hppabsd-core.c b/contrib/gdb/bfd/hppabsd-core.c
new file mode 100644
index 0000000..a76ecc5
--- /dev/null
+++ b/contrib/gdb/bfd/hppabsd-core.c
@@ -0,0 +1,305 @@
+/* BFD back-end for HPPA BSD core files.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support.
+
+ The core file structure for the Utah 4.3BSD and OSF1 ports on the
+ PA is a mix between traditional cores and hpux cores -- just
+ different enough that supporting this format would tend to add
+ gross hacks to trad-core.c or hpux-core.c. So instead we keep any
+ gross hacks isolated to this file. */
+
+
+/* This file can only be compiled on systems which use HPPA-BSD style
+ core files.
+
+ I would not expect this to be of use to any other host/target, but
+ you never know. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#if defined (HOST_HPPABSD)
+
+#include "machine/vmparam.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <machine/reg.h>
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <errno.h>
+
+static asection *make_bfd_asection PARAMS ((bfd *, CONST char *,
+ flagword, bfd_size_type,
+ file_ptr, unsigned int));
+static asymbol *hppabsd_core_make_empty_symbol PARAMS ((bfd *));
+static const bfd_target *hppabsd_core_core_file_p PARAMS ((bfd *));
+static char *hppabsd_core_core_file_failing_command PARAMS ((bfd *));
+static int hppabsd_core_core_file_failing_signal PARAMS ((bfd *));
+static boolean hppabsd_core_core_file_matches_executable_p
+ PARAMS ((bfd *, bfd *));
+static void swap_abort PARAMS ((void));
+
+/* These are stored in the bfd's tdata. */
+
+struct hppabsd_core_struct
+ {
+ int sig;
+ char cmd[MAXCOMLEN + 1];
+ asection *data_section;
+ asection *stack_section;
+ asection *reg_section;
+ };
+
+#define core_hdr(bfd) ((bfd)->tdata.hppabsd_core_data)
+#define core_signal(bfd) (core_hdr(bfd)->sig)
+#define core_command(bfd) (core_hdr(bfd)->cmd)
+#define core_datasec(bfd) (core_hdr(bfd)->data_section)
+#define core_stacksec(bfd) (core_hdr(bfd)->stack_section)
+#define core_regsec(bfd) (core_hdr(bfd)->reg_section)
+
+static asection *
+make_bfd_asection (abfd, name, flags, _raw_size, offset, alignment_power)
+ bfd *abfd;
+ CONST char *name;
+ flagword flags;
+ bfd_size_type _raw_size;
+ file_ptr offset;
+ unsigned int alignment_power;
+{
+ asection *asect;
+
+ asect = bfd_make_section (abfd, name);
+ if (!asect)
+ return NULL;
+
+ asect->flags = flags;
+ asect->_raw_size = _raw_size;
+ asect->filepos = offset;
+ asect->alignment_power = alignment_power;
+
+ return asect;
+}
+
+static asymbol *
+hppabsd_core_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new)
+ new->the_bfd = abfd;
+ return new;
+}
+
+static const bfd_target *
+hppabsd_core_core_file_p (abfd)
+ bfd *abfd;
+{
+ int val;
+ struct user u;
+ struct hppabsd_core_struct *coredata;
+ int clicksz;
+
+ /* Try to read in the u-area. We will need information from this
+ to know how to grok the rest of the core structures. */
+ val = bfd_read ((void *) &u, 1, sizeof u, abfd);
+ if (val != sizeof u)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* Get the page size out of the u structure. This will be different
+ for PA 1.0 machines and PA 1.1 machines. Yuk! */
+ clicksz = u.u_pcb.pcb_pgsz;
+
+ /* clicksz must be a power of two >= 2k. */
+ if (clicksz < 0x800
+ || clicksz != (clicksz & -clicksz))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+
+ /* Sanity checks. Make sure the size of the core file matches the
+ the size computed from information within the core itself. */
+ {
+ FILE *stream = bfd_cache_lookup (abfd);
+ struct stat statbuf;
+ if (stream == NULL || fstat (fileno (stream), &statbuf) < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return NULL;
+ }
+ if (NBPG * (UPAGES + u.u_dsize + u.u_ssize) > statbuf.st_size)
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return NULL;
+ }
+ if (clicksz * (UPAGES + u.u_dsize + u.u_ssize) < statbuf.st_size)
+ {
+ /* 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_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+
+ coredata = (struct hppabsd_core_struct *)
+ bfd_zalloc (abfd, sizeof (struct hppabsd_core_struct));
+ if (!coredata)
+ return NULL;
+
+ /* Make the core data and available via the tdata part of the BFD. */
+ abfd->tdata.hppabsd_core_data = coredata;
+
+ /* Create the sections. */
+ core_stacksec (abfd) = make_bfd_asection (abfd, ".stack",
+ SEC_ALLOC + SEC_HAS_CONTENTS,
+ clicksz * u.u_ssize,
+ NBPG * (USIZE + KSTAKSIZE)
+ + clicksz * u.u_dsize, 2);
+ core_stacksec (abfd)->vma = USRSTACK;
+
+ core_datasec (abfd) = make_bfd_asection (abfd, ".data",
+ SEC_ALLOC + SEC_LOAD
+ + SEC_HAS_CONTENTS,
+ clicksz * u.u_dsize,
+ NBPG * (USIZE + KSTAKSIZE), 2);
+ core_datasec (abfd)->vma = UDATASEG;
+
+ core_regsec (abfd) = make_bfd_asection (abfd, ".reg",
+ SEC_HAS_CONTENTS,
+ KSTAKSIZE * NBPG,
+ NBPG * USIZE, 2);
+ core_regsec (abfd)->vma = 0;
+
+ strncpy (core_command (abfd), u.u_comm, MAXCOMLEN + 1);
+ core_signal (abfd) = u.u_code;
+ return abfd->xvec;
+}
+
+static char *
+hppabsd_core_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return core_command (abfd);
+}
+
+/* ARGSUSED */
+static int
+hppabsd_core_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_signal (abfd);
+}
+
+/* ARGSUSED */
+static boolean
+hppabsd_core_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ /* There's no way to know this... */
+ return true;
+}
+
+
+#define hppabsd_core_get_symtab_upper_bound \
+ _bfd_nosymbols_get_symtab_upper_bound
+#define hppabsd_core_get_symtab _bfd_nosymbols_get_symtab
+#define hppabsd_core_print_symbol _bfd_nosymbols_print_symbol
+#define hppabsd_core_get_symbol_info _bfd_nosymbols_get_symbol_info
+#define hppabsd_core_bfd_is_local_label _bfd_nosymbols_bfd_is_local_label
+#define hppabsd_core_get_lineno _bfd_nosymbols_get_lineno
+#define hppabsd_core_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define hppabsd_core_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define hppabsd_core_read_minisymbols _bfd_nosymbols_read_minisymbols
+#define hppabsd_core_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
+
+/* If somebody calls any byte-swapping routines, shoot them. */
+static void
+swap_abort ()
+{
+ /* This way doesn't require any declaration for ANSI to fuck up. */
+ 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 ((const bfd_byte *))) swap_abort )
+
+const bfd_target hppabsd_core_vec =
+ {
+ "hppabsd-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ 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 */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ hppabsd_core_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (hppabsd_core),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (hppabsd_core),
+ 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 */
+};
+#endif
diff --git a/contrib/gdb/bfd/hpux-core.c b/contrib/gdb/bfd/hpux-core.c
new file mode 100644
index 0000000..675a5f8
--- /dev/null
+++ b/contrib/gdb/bfd/hpux-core.c
@@ -0,0 +1,270 @@
+/* BFD back-end for HP/UX core files.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ Written by Stu Grossman, Cygnus Support.
+ Converted to back-end form by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file can only be compiled on systems which use HP/UX style
+ core files. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#if defined (HOST_HPPAHPUX) || defined (HOST_HP300HPUX)
+
+/* FIXME: sys/core.h doesn't exist for HPUX version 7. HPUX version
+ 5, 6, and 7 core files seem to be standard trad-core.c type core
+ files; can we just use trad-core.c in addition to this file? */
+
+#include <sys/core.h>
+#include <sys/utsname.h>
+
+#endif /* HOST_HPPAHPUX */
+
+#ifdef HOST_HPPABSD
+
+/* Not a very swift place to put it, but that's where the BSD port
+ puts them. */
+#include "/hpux/usr/include/sys/core.h"
+
+#endif /* HOST_HPPABSD */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <machine/reg.h>
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include <errno.h>
+
+/* These are stored in the bfd's tdata */
+
+struct hpux_core_struct
+{
+ int sig;
+ char cmd[MAXCOMLEN + 1];
+};
+
+#define core_hdr(bfd) ((bfd)->tdata.hpux_core_data)
+#define core_signal(bfd) (core_hdr(bfd)->sig)
+#define core_command(bfd) (core_hdr(bfd)->cmd)
+
+static asection *
+make_bfd_asection (abfd, name, flags, _raw_size, vma, alignment_power)
+ bfd *abfd;
+ CONST char *name;
+ flagword flags;
+ bfd_size_type _raw_size;
+ bfd_vma vma;
+ unsigned int alignment_power;
+{
+ asection *asect;
+
+ asect = bfd_make_section_anyway (abfd, name);
+ if (!asect)
+ return NULL;
+
+ asect->flags = flags;
+ asect->_raw_size = _raw_size;
+ asect->vma = vma;
+ asect->filepos = bfd_tell (abfd);
+ asect->alignment_power = alignment_power;
+
+ return asect;
+}
+
+static asymbol *
+hpux_core_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new)
+ new->the_bfd = abfd;
+ return new;
+}
+
+static const bfd_target *
+hpux_core_core_file_p (abfd)
+ bfd *abfd;
+{
+ core_hdr (abfd) = (struct hpux_core_struct *)
+ bfd_zalloc (abfd, sizeof (struct hpux_core_struct));
+ if (!core_hdr (abfd))
+ return NULL;
+
+ while (1)
+ {
+ int val;
+ struct corehead core_header;
+
+ val = bfd_read ((void *) &core_header, 1, sizeof core_header, abfd);
+ if (val <= 0)
+ break;
+ switch (core_header.type)
+ {
+ case CORE_KERNEL:
+ case CORE_FORMAT:
+ bfd_seek (abfd, core_header.len, SEEK_CUR); /* Just skip this */
+ break;
+ case CORE_EXEC:
+ {
+ struct proc_exec proc_exec;
+ if (bfd_read ((void *) &proc_exec, 1, core_header.len, abfd)
+ != core_header.len)
+ break;
+ strncpy (core_command (abfd), proc_exec.cmd, MAXCOMLEN + 1);
+ }
+ break;
+ case CORE_PROC:
+ {
+ struct proc_info proc_info;
+ if (!make_bfd_asection (abfd, ".reg",
+ SEC_HAS_CONTENTS,
+ core_header.len,
+ (int) &proc_info - (int) & proc_info.hw_regs,
+ 2))
+ return NULL;
+
+ if (bfd_read (&proc_info, 1, core_header.len, abfd)
+ != core_header.len)
+ break;
+ core_signal (abfd) = proc_info.sig;
+ }
+ break;
+
+ case CORE_DATA:
+ case CORE_STACK:
+ case CORE_TEXT:
+ case CORE_MMF:
+ case CORE_SHM:
+ if (!make_bfd_asection (abfd, ".data",
+ SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
+ core_header.len, core_header.addr, 2))
+ return NULL;
+
+ bfd_seek (abfd, core_header.len, SEEK_CUR);
+ break;
+
+ default:
+ /* Falling into here is an error and should prevent this
+ target from matching. That way systems which use hpux
+ cores along with other formats can still work. */
+ return 0;
+ }
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+
+ return abfd->xvec;
+}
+
+static char *
+hpux_core_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return core_command (abfd);
+}
+
+/* ARGSUSED */
+static int
+hpux_core_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_signal (abfd);
+}
+
+/* ARGSUSED */
+static boolean
+hpux_core_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this point */
+}
+
+#define hpux_core_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
+#define hpux_core_get_symtab _bfd_nosymbols_get_symtab
+#define hpux_core_print_symbol _bfd_nosymbols_print_symbol
+#define hpux_core_get_symbol_info _bfd_nosymbols_get_symbol_info
+#define hpux_core_bfd_is_local_label _bfd_nosymbols_bfd_is_local_label
+#define hpux_core_get_lineno _bfd_nosymbols_get_lineno
+#define hpux_core_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define hpux_core_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define hpux_core_read_minisymbols _bfd_nosymbols_read_minisymbols
+#define hpux_core_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
+
+/* 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 (( const bfd_byte *))) swap_abort )
+#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
+#define NO_SIGNED_GET \
+ ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
+
+const bfd_target hpux_core_vec =
+ {
+ "hpux-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ 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 */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ hpux_core_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (hpux_core),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (hpux_core),
+ 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/contrib/gdb/bfd/i386aout.c b/contrib/gdb/bfd/i386aout.c
new file mode 100644
index 0000000..0801832
--- /dev/null
+++ b/contrib/gdb/bfd/i386aout.c
@@ -0,0 +1,68 @@
+/* BFD back-end for i386 a.out binaries.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* The only 386 aout system we have here is GO32 from DJ.
+ These numbers make BFD work with that. If your aout 386 system
+ doesn't work with these, we'll have to split them into different
+ files. Send me (sac@cygnus.com) the runes to make it work on your
+ system, and I'll stick it in for the next release. */
+
+#define N_HEADER_IN_TEXT(x) 0
+#define BYTES_IN_WORD 4
+
+#define N_TXTOFF(x) 0x20
+#define N_TXTADDR(x) (N_MAGIC(x)==ZMAGIC ? 0x1020 : 0)
+
+#define N_TXTSIZE(x) ((x).a_text)
+#if 0
+#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+(x).a_text) : (SEGMENT_SIZE + ((0x1020+(x).a_text-1) & ~(SEGMENT_SIZE-1))))
+#define NOSUBEXECB
+
+#endif
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE 0x400000
+#define DEFAULT_ARCH bfd_arch_i386
+
+#define MY(OP) CAT(i386aout_,OP)
+#define TARGETNAME "a.out-i386"
+#define NO_WRITE_HEADER_KLUDGE 1
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+static boolean MY(set_sizes)();
+#define MY_backend_data &MY(backend_data)
+static CONST struct aout_backend_data MY(backend_data) = {
+ 0, /* zmagic contiguous */
+ 1, /* text incl header */
+ 0, /* exec_hdr_flags */
+ 0, /* text vma? */
+ MY(set_sizes),
+ 1, /* exec header not counted */
+ 0, /* add_dynamic_symbols */
+ 0, /* add_one_symbol */
+ 0, /* link_dynamic_object */
+ 0, /* write_dynamic_symbol */
+ 0, /* check_dynamic_reloc */
+ 0 /* finish_dynamic_link */
+};
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/i386bsd.c b/contrib/gdb/bfd/i386bsd.c
new file mode 100644
index 0000000..2328fe3
--- /dev/null
+++ b/contrib/gdb/bfd/i386bsd.c
@@ -0,0 +1,46 @@
+/* BFD back-end for i386 a.out binaries under BSD.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This data should be correct for the format used under all the various
+ BSD ports for 386 machines. */
+
+#define BYTES_IN_WORD 4
+
+/* ZMAGIC files never have the header in the text. */
+#define N_HEADER_IN_TEXT(x) 0
+
+/* ZMAGIC files start at address 0. This does not apply to QMAGIC. */
+#define TEXT_START_ADDR 0
+#define N_SHARED_LIB(x) 0
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(i386bsd_,OP)
+#define TARGETNAME "a.out-i386-bsd"
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/i386dynix.c b/contrib/gdb/bfd/i386dynix.c
new file mode 100644
index 0000000..ff50a14
--- /dev/null
+++ b/contrib/gdb/bfd/i386dynix.c
@@ -0,0 +1,80 @@
+/* BFD back-end for i386 a.out binaries under dynix.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This BFD is currently only tested with gdb, writing object files
+ may not work. */
+
+#define BYTES_IN_WORD 4
+
+#define TEXT_START_ADDR 4096
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+
+#include "aout/dynix3.h"
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MACHTYPE_OK(mtype) ((mtype) == M_386 || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(i386dynix_,OP)
+#define TARGETNAME "a.out-i386-dynix"
+#define NAME(x,y) CAT3(i386dynix,_32_,y)
+#define ARCH_SIZE 32
+#define NAME_swap_exec_header_in NAME(i386dynix_32_,swap_exec_header_in)
+#define MY_get_section_contents aout_32_get_section_contents
+
+/* aoutx.h requires definitions for NMAGIC, BMAGIC and QMAGIC. */
+#define NMAGIC 0
+#define BMAGIC OMAGIC
+#define QMAGIC XMAGIC
+
+#include "aoutx.h"
+
+/* (Ab)use some fields in the internal exec header to be able to read
+ executables that contain shared data. */
+
+#define a_shdata a_tload
+#define a_shdrsize a_dload
+
+void
+i386dynix_32_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;
+
+ /* The internal_exec structure has some fields that are unused in this
+ 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 ((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);
+ execp->a_data = GET_WORD (abfd, bytes->e_data);
+ execp->a_bss = GET_WORD (abfd, bytes->e_bss);
+ execp->a_syms = GET_WORD (abfd, bytes->e_syms);
+ execp->a_entry = GET_WORD (abfd, bytes->e_entry);
+ execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
+ execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
+ execp->a_shdata = GET_WORD (abfd, bytes->e_shdata);
+ execp->a_shdrsize = GET_WORD (abfd, bytes->e_shdrsize);
+}
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/i386freebsd.c b/contrib/gdb/bfd/i386freebsd.c
new file mode 100644
index 0000000..7a6371b
--- /dev/null
+++ b/contrib/gdb/bfd/i386freebsd.c
@@ -0,0 +1,33 @@
+/* BFD back-end for FreeBSD/386 a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#undef TARGET_IS_BIG_ENDIAN_P
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MACHTYPE_OK(mtype) ((mtype) == M_386_NETBSD || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(i386freebsd_,OP)
+/* This needs to start with a.out so GDB knows it is an a.out variant. */
+#define TARGETNAME "a.out-i386-freebsd"
+
+#include "freebsd.h"
diff --git a/contrib/gdb/bfd/i386linux.c b/contrib/gdb/bfd/i386linux.c
new file mode 100644
index 0000000..a45f97c
--- /dev/null
+++ b/contrib/gdb/bfd/i386linux.c
@@ -0,0 +1,762 @@
+/* BFD back-end for linux flavored i386 a.out binaries.
+ Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_PAGE_SIZE 4096
+#define ZMAGIC_DISK_BLOCK_SIZE 1024
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define TEXT_START_ADDR 0x0
+#define N_SHARED_LIB(x) 0
+#define BYTES_IN_WORD 4
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MY(OP) CAT(i386linux_,OP)
+#define TARGETNAME "a.out-i386-linux"
+
+extern const bfd_target MY(vec);
+
+/* We always generate QMAGIC files in preference to ZMAGIC files. It
+ would be possible to make this a linker option, if that ever
+ becomes important. */
+
+static void MY_final_link_callback
+ PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
+
+static boolean
+i386linux_bfd_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ obj_aout_subformat (abfd) = q_magic_format;
+ return NAME(aout,final_link) (abfd, info, MY_final_link_callback);
+}
+
+#define MY_bfd_final_link i386linux_bfd_final_link
+
+/* Set the machine type correctly. */
+
+static boolean
+i386linux_write_object_contents (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ N_SET_MACHTYPE (*execp, M_386);
+
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
+
+#define MY_write_object_contents i386linux_write_object_contents
+
+/* Code to link against Linux a.out shared libraries. */
+
+/* See if a symbol name is a reference to the global offset table. */
+
+#ifndef GOT_REF_PREFIX
+#define GOT_REF_PREFIX "__GOT_"
+#endif
+
+#define IS_GOT_SYM(name) \
+ (strncmp (name, GOT_REF_PREFIX, sizeof GOT_REF_PREFIX - 1) == 0)
+
+/* See if a symbol name is a reference to the procedure linkage table. */
+
+#ifndef PLT_REF_PREFIX
+#define PLT_REF_PREFIX "__PLT_"
+#endif
+
+#define IS_PLT_SYM(name) \
+ (strncmp (name, PLT_REF_PREFIX, sizeof PLT_REF_PREFIX - 1) == 0)
+
+/* This string is used to generate specialized error messages. */
+
+#ifndef NEEDS_SHRLIB
+#define NEEDS_SHRLIB "__NEEDS_SHRLIB_"
+#endif
+
+/* This special symbol is a set vector that contains a list of
+ pointers to fixup tables. It will be present in any dynamicly
+ linked file. The linker generated fixup table should also be added
+ to the list, and it should always appear in the second slot (the
+ first one is a dummy with a magic number that is defined in
+ crt0.o). */
+
+#ifndef SHARABLE_CONFLICTS
+#define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__"
+#endif
+
+/* We keep a list of fixups. The terminology is a bit strange, but
+ each fixup contains two 32 bit numbers. A regular fixup contains
+ an address and a pointer, and at runtime we should store the
+ address at the location pointed to by the pointer. A builtin fixup
+ contains two pointers, and we should read the address using one
+ pointer and store it at the location pointed to by the other
+ pointer. Builtin fixups come into play when we have duplicate
+ __GOT__ symbols for the same variable. The builtin fixup will copy
+ the GOT pointer from one over into the other. */
+
+struct fixup
+{
+ struct fixup *next;
+ struct linux_link_hash_entry *h;
+ bfd_vma value;
+
+ /* Nonzero if this is a jump instruction that needs to be fixed,
+ zero if this is just a pointer */
+ char jump;
+
+ char builtin;
+};
+
+/* We don't need a special hash table entry structure, but we do need
+ to keep some information between linker passes, so we use a special
+ hash table. */
+
+struct linux_link_hash_entry
+{
+ struct aout_link_hash_entry root;
+};
+
+struct linux_link_hash_table
+{
+ struct aout_link_hash_table root;
+
+ /* First dynamic object found in link. */
+ bfd *dynobj;
+
+ /* Number of fixups. */
+ size_t fixup_count;
+
+ /* Number of builtin fixups. */
+ size_t local_builtins;
+
+ /* List of fixups. */
+ struct fixup *fixup_list;
+};
+
+static struct bfd_hash_entry *linux_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static struct bfd_link_hash_table *linux_link_hash_table_create
+ PARAMS ((bfd *));
+static struct fixup *new_fixup
+ PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *,
+ bfd_vma, int));
+static boolean linux_link_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean linux_add_one_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
+ bfd_vma, const char *, boolean, boolean,
+ struct bfd_link_hash_entry **));
+static boolean linux_tally_symbols
+ PARAMS ((struct linux_link_hash_entry *, PTR));
+static boolean linux_finish_dynamic_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Routine to create an entry in an Linux link hash table. */
+
+static struct bfd_hash_entry *
+linux_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct linux_link_hash_entry *) NULL)
+ ret = ((struct linux_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry)));
+ if (ret == NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct linux_link_hash_entry *)
+ NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != NULL)
+ {
+ /* Set local fields; there aren't any. */
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create a Linux link hash table. */
+
+static struct bfd_link_hash_table *
+linux_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct linux_link_hash_table *ret;
+
+ ret = ((struct linux_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct linux_link_hash_table)));
+ if (ret == (struct linux_link_hash_table *) NULL)
+ return (struct bfd_link_hash_table *) NULL;
+ if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
+ linux_link_hash_newfunc))
+ {
+ free (ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+
+ ret->dynobj = NULL;
+ ret->fixup_count = 0;
+ ret->local_builtins = 0;
+ ret->fixup_list = NULL;
+
+ return &ret->root.root;
+}
+
+/* Look up an entry in a Linux link hash table. */
+
+#define linux_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct linux_link_hash_entry *) \
+ aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
+ (follow)))
+
+/* Traverse a Linux link hash table. */
+
+#define linux_link_hash_traverse(table, func, info) \
+ (aout_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the Linux link hash table from the info structure. This is
+ just a cast. */
+
+#define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
+
+/* Store the information for a new fixup. */
+
+static struct fixup *
+new_fixup (info, h, value, builtin)
+ struct bfd_link_info *info;
+ struct linux_link_hash_entry *h;
+ bfd_vma value;
+ int builtin;
+{
+ struct fixup *f;
+
+ f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
+ sizeof (struct fixup));
+ if (f == NULL)
+ return f;
+ f->next = linux_hash_table (info)->fixup_list;
+ linux_hash_table (info)->fixup_list = f;
+ f->h = h;
+ f->value = value;
+ f->builtin = builtin;
+ f->jump = 0;
+ ++linux_hash_table (info)->fixup_count;
+ return f;
+}
+
+/* We come here once we realize that we are going to link to a shared
+ library. We need to create a special section that contains the
+ fixup table, and we ultimately need to add a pointer to this into
+ the set vector for SHARABLE_CONFLICTS. At this point we do not
+ know the size of the section, but that's OK - we just need to
+ create it for now. */
+
+static boolean
+linux_link_create_dynamic_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+
+ /* Note that we set the SEC_IN_MEMORY flag. */
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ /* We choose to use the name ".linux-dynamic" for the fixup table.
+ Why not? */
+ s = bfd_make_section (abfd, ".linux-dynamic");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ s->_raw_size = 0;
+ s->contents = 0;
+
+ return true;
+}
+
+/* Function to add a single symbol to the linker hash table. This is
+ a wrapper around _bfd_generic_link_add_one_symbol which handles the
+ tweaking needed for dynamic linking support. */
+
+static boolean
+linux_add_one_symbol (info, abfd, name, flags, section, value, string,
+ copy, collect, hashp)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ const char *name;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ const char *string;
+ boolean copy;
+ boolean collect;
+ struct bfd_link_hash_entry **hashp;
+{
+ struct linux_link_hash_entry *h;
+ boolean insert;
+
+ /* Look up and see if we already have this symbol in the hash table.
+ If we do, and the defining entry is from a shared library, we
+ need to create the dynamic sections.
+
+ FIXME: What if abfd->xvec != info->hash->creator? We may want to
+ be able to link Linux a.out and ELF objects together, but serious
+ confusion is possible. */
+
+ insert = false;
+
+ if (! info->relocateable
+ && linux_hash_table (info)->dynobj == NULL
+ && strcmp (name, SHARABLE_CONFLICTS) == 0
+ && (flags & BSF_CONSTRUCTOR) != 0
+ && abfd->xvec == info->hash->creator)
+ {
+ if (! linux_link_create_dynamic_sections (abfd, info))
+ return false;
+ linux_hash_table (info)->dynobj = abfd;
+ insert = true;
+ }
+
+ if (bfd_is_abs_section (section)
+ && abfd->xvec == info->hash->creator)
+ {
+ h = linux_link_hash_lookup (linux_hash_table (info), name, false,
+ false, false);
+ if (h != NULL
+ && (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak))
+ {
+ struct fixup *f;
+
+ if (hashp != NULL)
+ *hashp = (struct bfd_link_hash_entry *) h;
+
+ f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
+ if (f == NULL)
+ return false;
+ f->jump = IS_PLT_SYM (name);
+
+ return true;
+ }
+ }
+
+ /* Do the usual procedure for adding a symbol. */
+ if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
+ value, string, copy, collect,
+ hashp))
+ return false;
+
+ /* Insert a pointer to our table in the set vector. The dynamic
+ linker requires this information */
+ if (insert)
+ {
+ asection *s;
+
+ /* Here we do our special thing to add the pointer to the
+ dynamic section in the SHARABLE_CONFLICTS set vector. */
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ BFD_ASSERT (s != NULL);
+
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
+ BSF_GLOBAL | BSF_CONSTRUCTOR, s, 0, NULL, false, false, NULL)))
+ return false;
+ }
+
+ return true;
+}
+
+/* We will crawl the hash table and come here for every global symbol.
+ We will examine each entry and see if there are indications that we
+ need to add a fixup. There are two possible cases - one is where
+ you have duplicate definitions of PLT or GOT symbols - these will
+ have already been caught and added as "builtin" fixups. If we find
+ that the corresponding non PLT/GOT symbol is also present, we
+ convert it to a regular fixup instead.
+
+ This function is called via linux_link_hash_traverse. */
+
+static boolean
+linux_tally_symbols (h, data)
+ struct linux_link_hash_entry *h;
+ PTR data;
+{
+ struct bfd_link_info *info = (struct bfd_link_info *) data;
+ struct fixup *f, *f1;
+ int is_plt;
+ struct linux_link_hash_entry *h1, *h2;
+ boolean exists;
+
+ if (h->root.root.type == bfd_link_hash_undefined
+ && strncmp (h->root.root.root.string, NEEDS_SHRLIB,
+ sizeof NEEDS_SHRLIB - 1) == 0)
+ {
+ const char *name;
+ char *p;
+ char *alloc = NULL;
+
+ name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
+ p = strrchr (name, '_');
+ if (p != NULL)
+ alloc = (char *) bfd_malloc (strlen (name) + 1);
+
+ if (p == NULL || alloc == NULL)
+ (*_bfd_error_handler) ("Output file requires shared library `%s'\n",
+ name);
+ else
+ {
+ strcpy (alloc, name);
+ p = strrchr (alloc, '_');
+ *p++ = '\0';
+ (*_bfd_error_handler)
+ ("Output file requires shared library `%s.so.%s'\n",
+ alloc, p);
+ free (alloc);
+ }
+
+ abort ();
+ }
+
+ /* If this symbol is not a PLT/GOT, we do not even need to look at it */
+ is_plt = IS_PLT_SYM (h->root.root.root.string);
+
+ if (is_plt || IS_GOT_SYM (h->root.root.root.string))
+ {
+ /* Look up this symbol twice. Once just as a regular lookup,
+ and then again following all of the indirect links until we
+ reach a real symbol. */
+ h1 = linux_link_hash_lookup (linux_hash_table (info),
+ (h->root.root.root.string
+ + sizeof PLT_REF_PREFIX - 1),
+ false, false, true);
+ /* h2 does not follow indirect symbols. */
+ h2 = linux_link_hash_lookup (linux_hash_table (info),
+ (h->root.root.root.string
+ + sizeof PLT_REF_PREFIX - 1),
+ false, false, false);
+
+ /* The real symbol must exist but if it is also an ABS symbol,
+ there is no need to have a fixup. This is because they both
+ came from the same library. If on the other hand, we had to
+ use an indirect symbol to get to the real symbol, we add the
+ fixup anyway, since there are cases where these symbols come
+ from different shared libraries */
+ if (h1 != NULL
+ && (((h1->root.root.type == bfd_link_hash_defined
+ || h1->root.root.type == bfd_link_hash_defweak)
+ && ! bfd_is_abs_section (h1->root.root.u.def.section))
+ || h2->root.root.type == bfd_link_hash_indirect))
+ {
+ /* See if there is a "builtin" fixup already present
+ involving this symbol. If so, convert it to a regular
+ fixup. In the end, this relaxes some of the requirements
+ about the order of performing fixups. */
+ exists = false;
+ for (f1 = linux_hash_table (info)->fixup_list;
+ f1 != NULL;
+ f1 = f1->next)
+ {
+ if ((f1->h != h && f1->h != h1)
+ || (! f1->builtin && ! f1->jump))
+ continue;
+ if (f1->h == h1)
+ exists = true;
+ if (! exists
+ && bfd_is_abs_section (h->root.root.u.def.section))
+ {
+ f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);
+ f->jump = is_plt;
+ }
+ f1->h = h1;
+ f1->jump = is_plt;
+ f1->builtin = 0;
+ exists = true;
+ }
+ if (! exists
+ && bfd_is_abs_section (h->root.root.u.def.section))
+ {
+ f = new_fixup (info, h1, h->root.root.u.def.value, 0);
+ if (f == NULL)
+ {
+ /* FIXME: No way to return error. */
+ abort ();
+ }
+ f->jump = is_plt;
+ }
+ }
+
+ /* Quick and dirty way of stripping these symbols from the
+ symtab. */
+ if (bfd_is_abs_section (h->root.root.u.def.section))
+ h->root.written = true;
+ }
+
+ return true;
+}
+
+/* This is called to set the size of the .linux-dynamic section is.
+ It is called by the Linux linker emulation before_allocation
+ routine. We have finished reading all of the input files, and now
+ we just scan the hash tables to find out how many additional fixups
+ are required. */
+
+boolean
+bfd_i386linux_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ struct fixup *f;
+ asection *s;
+
+ if (output_bfd->xvec != &MY(vec))
+ return true;
+
+ /* First find the fixups... */
+ linux_link_hash_traverse (linux_hash_table (info),
+ linux_tally_symbols,
+ (PTR) info);
+
+ /* If there are builtin fixups, leave room for a marker. This is
+ used by the dynamic linker so that it knows that all that follow
+ are builtin fixups instead of regular fixups. */
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (f->builtin)
+ {
+ ++linux_hash_table (info)->fixup_count;
+ ++linux_hash_table (info)->local_builtins;
+ break;
+ }
+ }
+
+ if (linux_hash_table (info)->dynobj == NULL)
+ {
+ if (linux_hash_table (info)->fixup_count > 0)
+ abort ();
+ return true;
+ }
+
+ /* Allocate memory for our fixup table. We will fill it in later. */
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ if (s != NULL)
+ {
+ s->_raw_size = 8 + linux_hash_table (info)->fixup_count * 8;
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL)
+ return false;
+ memset (s->contents, 0, (size_t) s->_raw_size);
+ }
+
+ return true;
+}
+
+/* We come here once we are ready to actually write the fixup table to
+ the output file. Scan the fixup tables and so forth and generate
+ the stuff we need. */
+
+static boolean
+linux_finish_dynamic_link (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ asection *s, *os, *is;
+ bfd_byte *fixup_table;
+ struct linux_link_hash_entry *h;
+ struct fixup *f;
+ unsigned int new_addr;
+ int section_offset;
+ unsigned int fixups_written;
+
+ if (linux_hash_table (info)->dynobj == NULL)
+ return true;
+
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ BFD_ASSERT (s != NULL);
+ os = s->output_section;
+ fixups_written = 0;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup table file offset: %x VMA: %x\n",
+ os->filepos + s->output_offset,
+ os->vma + s->output_offset);
+#endif
+
+ fixup_table = s->contents;
+ bfd_put_32 (output_bfd, linux_hash_table (info)->fixup_count, fixup_table);
+ fixup_table += 4;
+
+ /* Fill in fixup table. */
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (f->builtin)
+ continue;
+
+ if (f->h->root.root.type != bfd_link_hash_defined
+ && f->h->root.root.type != bfd_link_hash_defweak)
+ {
+ (*_bfd_error_handler)
+ ("Symbol %s not defined for fixups\n",
+ f->h->root.root.root.string);
+ continue;
+ }
+
+ is = f->h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = f->h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,
+ new_addr, f->value);
+#endif
+
+ if (f->jump)
+ {
+ /* Relative address */
+ new_addr = new_addr - (f->value + 5);
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value + 1, fixup_table);
+ fixup_table += 4;
+ }
+ else
+ {
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value, fixup_table);
+ fixup_table += 4;
+ }
+ ++fixups_written;
+ }
+
+ if (linux_hash_table (info)->local_builtins != 0)
+ {
+ /* Special marker so we know to switch to the other type of fixup */
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (! f->builtin)
+ continue;
+
+ if (f->h->root.root.type != bfd_link_hash_defined
+ && f->h->root.root.type != bfd_link_hash_defweak)
+ {
+ (*_bfd_error_handler)
+ ("Symbol %s not defined for fixups\n",
+ f->h->root.root.root.string);
+ continue;
+ }
+
+ is = f->h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = f->h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,
+ new_addr, f->value);
+#endif
+
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ }
+ }
+
+ if (linux_hash_table (info)->fixup_count != fixups_written)
+ {
+ (*_bfd_error_handler) ("Warning: fixup count mismatch\n");
+ while (linux_hash_table (info)->fixup_count > fixups_written)
+ {
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ }
+ }
+
+ h = linux_link_hash_lookup (linux_hash_table (info),
+ "__BUILTIN_FIXUPS__",
+ false, false, false);
+
+ if (h != NULL
+ && (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak))
+ {
+ is = h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Builtin fixup table at %x\n", new_addr);
+#endif
+
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ }
+ else
+ bfd_put_32 (output_bfd, 0, fixup_table);
+
+ if (bfd_seek (output_bfd, os->filepos + s->output_offset, SEEK_SET) != 0)
+ return false;
+
+ if (bfd_write ((PTR) s->contents, 1, s->_raw_size, output_bfd)
+ != s->_raw_size)
+ return false;
+
+ return true;
+}
+
+#define MY_bfd_link_hash_table_create linux_link_hash_table_create
+#define MY_add_one_symbol linux_add_one_symbol
+#define MY_finish_dynamic_link linux_finish_dynamic_link
+
+#define MY_zmagic_contiguous 1
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/i386lynx.c b/contrib/gdb/bfd/i386lynx.c
new file mode 100644
index 0000000..2381cff
--- /dev/null
+++ b/contrib/gdb/bfd/i386lynx.c
@@ -0,0 +1,563 @@
+/* BFD back-end for i386 a.out binaries under LynxOS.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#define N_SHARED_LIB(x) 0
+
+#define TEXT_START_ADDR 0
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_i386
+
+#define MY(OP) CAT(i386lynx_aout_,OP)
+#define TARGETNAME "a.out-i386-lynx"
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#ifndef WRITE_HEADERS
+#define WRITE_HEADERS(abfd, execp) \
+ { \
+ bfd_size_type text_size; /* dummy vars */ \
+ file_ptr text_end; \
+ if (adata(abfd).magic == undecided_magic) \
+ NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
+ \
+ execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
+ execp->a_entry = bfd_get_start_address (abfd); \
+ \
+ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
+ \
+ 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_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) \
+ != 0) \
+ return false; \
+ \
+ if (! NAME(aout,write_syms)(abfd)) return false; \
+ \
+ if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET) \
+ != 0) \
+ return false; \
+ \
+ if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd))) \
+ return false; \
+ if (bfd_seek (abfd, (file_ptr)(N_DRELOFF(*execp)), SEEK_SET) \
+ != 0) \
+ return 0; \
+ \
+ if (!NAME(lynx,squirt_out_relocs)(abfd, obj_datasec (abfd))) \
+ return false; \
+ } \
+ }
+#endif
+
+#include "libaout.h"
+#include "aout/aout64.h"
+
+#ifdef LYNX_CORE
+
+char *lynx_core_file_failing_command ();
+int lynx_core_file_failing_signal ();
+boolean lynx_core_file_matches_executable_p ();
+const bfd_target *lynx_core_file_p ();
+
+#define MY_core_file_failing_command lynx_core_file_failing_command
+#define MY_core_file_failing_signal lynx_core_file_failing_signal
+#define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
+#define MY_core_file_p lynx_core_file_p
+
+#endif /* LYNX_CORE */
+
+
+#define KEEPIT flags
+
+extern reloc_howto_type aout_32_ext_howto_table[];
+extern reloc_howto_type aout_32_std_howto_table[];
+
+/* Standard reloc stuff */
+/* Output standard relocation information to a file in target byte order. */
+
+void
+NAME(lynx,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);
+ int r_extern;
+ 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);
+
+ r_length = g->howto->size; /* Size as a power of two */
+ r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
+ /* r_baserel, r_jmptable, r_relative??? FIXME-soon */
+ r_baserel = 0;
+ r_jmptable = 0;
+ r_relative = 0;
+
+ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
+
+ /* name was clobbered by aout_write_syms to be symbol index */
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here
+ */
+
+
+ if (bfd_is_com_section (output_section)
+ || bfd_is_abs_section (output_section)
+ || bfd_is_und_section (output_section))
+ {
+ if (bfd_abs_section_ptr->symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+ r_extern = 1;
+ r_index = stoi ((*(g->sym_ptr_ptr))->KEEPIT);
+
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd))
+ {
+ natptr->r_index[0] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[2] = r_index;
+ natptr->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
+ {
+ natptr->r_index[2] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[0] = r_index;
+ natptr->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);
+ }
+}
+
+
+/* Extended stuff */
+/* Output extended relocation information to a file in target byte order. */
+
+void
+NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
+ bfd *abfd;
+ arelent *g;
+ register struct reloc_ext_external *natptr;
+{
+ int r_index;
+ int r_extern;
+ unsigned int r_type;
+ unsigned int r_addend;
+ asymbol *sym = *(g->sym_ptr_ptr);
+ asection *output_section = sym->section->output_section;
+
+ PUT_WORD (abfd, g->address, natptr->r_address);
+
+ r_type = (unsigned int) g->howto->type;
+
+ r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
+
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here
+ */
+
+ if (bfd_is_com_section (output_section)
+ || bfd_is_abs_section (output_section)
+ || bfd_is_und_section (output_section))
+ {
+ if (bfd_abs_section_ptr->symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ r_extern = 1;
+ r_index = stoi ((*(g->sym_ptr_ptr))->KEEPIT);
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd))
+ {
+ natptr->r_index[0] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[2] = r_index;
+ natptr->r_type[0] =
+ (r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
+ | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
+ }
+ else
+ {
+ natptr->r_index[2] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[0] = r_index;
+ natptr->r_type[0] =
+ (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
+ | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
+ }
+
+ PUT_WORD (abfd, r_addend, natptr->r_addend);
+}
+
+/* BFD deals internally with all things based from the section they're
+ in. so, something in 10 bytes into a text section with a base of
+ 50 would have a symbol (.text+10) and know .text vma was 50.
+
+ Aout keeps all it's symbols based from zero, so the symbol would
+ contain 60. This macro subs the base of each section from the value
+ to give the true offset from the section */
+
+
+#define MOVE_ADDRESS(ad) \
+ if (r_extern) { \
+ /* undefined symbol */ \
+ cache_ptr->sym_ptr_ptr = symbols + r_index; \
+ cache_ptr->addend = ad; \
+ } else { \
+ /* defined, section relative. replace symbol with pointer to \
+ symbol which points to section */ \
+ switch (r_index) { \
+ case N_TEXT: \
+ case N_TEXT | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_textsec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->textsec->vma; \
+ break; \
+ case N_DATA: \
+ case N_DATA | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_datasec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->datasec->vma; \
+ break; \
+ case N_BSS: \
+ case N_BSS | N_EXT: \
+ cache_ptr->sym_ptr_ptr = obj_bsssec(abfd)->symbol_ptr_ptr; \
+ cache_ptr->addend = ad - su->bsssec->vma; \
+ break; \
+ default: \
+ case N_ABS: \
+ case N_ABS | N_EXT: \
+ cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
+ cache_ptr->addend = ad; \
+ break; \
+ } \
+ } \
+
+void
+NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
+ bfd *abfd;
+ struct reloc_ext_external *bytes;
+ arelent *cache_ptr;
+ asymbol **symbols;
+ bfd_size_type symcount;
+{
+ int r_index;
+ int r_extern;
+ unsigned int r_type;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+
+ cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
+
+ r_index = bytes->r_index[1];
+ r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
+ r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
+ >> RELOC_EXT_BITS_TYPE_SH_BIG;
+
+ cache_ptr->howto = aout_32_ext_howto_table + r_type;
+ MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
+}
+
+void
+NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
+ bfd *abfd;
+ struct reloc_std_external *bytes;
+ arelent *cache_ptr;
+ asymbol **symbols;
+ bfd_size_type symcount;
+{
+ int r_index;
+ int r_extern;
+ unsigned int r_length;
+ int r_pcrel;
+ int r_baserel, r_jmptable, r_relative;
+ struct aoutdata *su = &(abfd->tdata.aout_data->a);
+
+ cache_ptr->address = bfd_h_get_32 (abfd, bytes->r_address);
+
+ r_index = bytes->r_index[1];
+ r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
+ r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
+ r_baserel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_BASEREL_BIG));
+ r_jmptable = (0 != (bytes->r_index[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+ r_relative = (0 != (bytes->r_index[0] & RELOC_STD_BITS_RELATIVE_BIG));
+ r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
+ >> RELOC_STD_BITS_LENGTH_SH_BIG;
+
+ cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
+ /* FIXME-soon: Roll baserel, jmptable, relative bits into howto setting */
+
+ MOVE_ADDRESS (0);
+}
+
+/* Reloc hackery */
+
+boolean
+NAME(lynx,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;
+
+ if (asect->relocation)
+ return true;
+
+ if (asect->flags & SEC_CONSTRUCTOR)
+ return true;
+
+ if (asect == obj_datasec (abfd))
+ {
+ reloc_size = exec_hdr (abfd)->a_drsize;
+ goto doit;
+ }
+
+ if (asect == obj_textsec (abfd))
+ {
+ reloc_size = exec_hdr (abfd)->a_trsize;
+ goto doit;
+ }
+
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+
+doit:
+ if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
+ return false;
+ each_size = obj_reloc_entry_size (abfd);
+
+ count = reloc_size / each_size;
+
+
+ reloc_cache = (arelent *) bfd_malloc (count * sizeof (arelent));
+ if (!reloc_cache && count != 0)
+ return false;
+ memset (reloc_cache, 0, count * sizeof (arelent));
+
+ relocs = (PTR) bfd_alloc (abfd, reloc_size);
+ if (!relocs && reloc_size != 0)
+ {
+ free (reloc_cache);
+ return false;
+ }
+
+ if (bfd_read (relocs, 1, reloc_size, abfd) != reloc_size)
+ {
+ bfd_release (abfd, relocs);
+ free (reloc_cache);
+ 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(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
+ bfd_get_symcount (abfd));
+ }
+ }
+ else
+ {
+ register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
+ unsigned int counter = 0;
+ arelent *cache_ptr = reloc_cache;
+
+ for (; counter < count; counter++, rptr++, cache_ptr++)
+ {
+ NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
+ bfd_get_symcount (abfd));
+ }
+
+ }
+
+ bfd_release (abfd, relocs);
+ asect->relocation = reloc_cache;
+ asect->reloc_count = count;
+ return true;
+}
+
+
+
+/* Write out a relocation section into an object file. */
+
+boolean
+NAME(lynx,squirt_out_relocs) (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ arelent **generic;
+ unsigned char *native, *natptr;
+ size_t each_size;
+
+ unsigned int count = section->reloc_count;
+ size_t natsize;
+
+ if (count == 0)
+ return true;
+
+ each_size = obj_reloc_entry_size (abfd);
+ natsize = each_size * count;
+ native = (unsigned char *) bfd_zalloc (abfd, natsize);
+ if (!native)
+ return false;
+
+ generic = section->orelocation;
+
+ if (each_size == RELOC_EXT_SIZE)
+ {
+ for (natptr = native;
+ count != 0;
+ --count, natptr += each_size, ++generic)
+ NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
+ }
+ else
+ {
+ for (natptr = native;
+ count != 0;
+ --count, natptr += each_size, ++generic)
+ NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
+ }
+
+ if (bfd_write ((PTR) native, 1, natsize, abfd) != natsize)
+ {
+ bfd_release (abfd, native);
+ return false;
+ }
+ bfd_release (abfd, native);
+
+ return true;
+}
+
+/* This is stupid. This function should be a boolean predicate */
+long
+NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *tblptr = section->relocation;
+ unsigned int count;
+
+ if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
+ return -1;
+
+ if (section->flags & SEC_CONSTRUCTOR)
+ {
+ arelent_chain *chain = section->constructor_chain;
+ for (count = 0; count < section->reloc_count; count++)
+ {
+ *relptr++ = &chain->relent;
+ chain = chain->next;
+ }
+ }
+ else
+ {
+ tblptr = section->relocation;
+
+ for (count = 0; count++ < section->reloc_count;)
+ {
+ *relptr++ = tblptr++;
+ }
+ }
+ *relptr = 0;
+
+ return section->reloc_count;
+}
+
+#define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/i386mach3.c b/contrib/gdb/bfd/i386mach3.c
new file mode 100644
index 0000000..72a28f3
--- /dev/null
+++ b/contrib/gdb/bfd/i386mach3.c
@@ -0,0 +1,65 @@
+/* BFD back-end for i386 a.out binaries.
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is for Mach 3, which uses a.out, not Mach-O. */
+
+/* There is no magic number or anything which lets us distinguish this target
+ from i386aout or i386bsd. So this target is only useful if it is the
+ default target. */
+
+#define TARGET_PAGE_SIZE 1
+#define SEGMENT_SIZE 0x1000
+#define TEXT_START_ADDR 0x10000
+#define ARCH 32
+#define BYTES_IN_WORD 4
+/* This macro is only relevant when N_MAGIC(x) == ZMAGIC. */
+#define N_HEADER_IN_TEXT(x) 1
+
+#define N_TXTSIZE(x) ((x).a_text)
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MY(OP) CAT(i386mach3_,OP)
+#define TARGETNAME "a.out-mach3"
+
+static boolean MY(set_sizes)();
+#define MY_backend_data &MY(backend_data)
+static CONST struct aout_backend_data MY(backend_data) = {
+ 0, /* zmagic contiguous */
+ 1, /* text incl header */
+ 0, /* exec_hdr_flags */
+ 0, /* text vma? */
+ MY(set_sizes),
+ 1, /* exec header not counted */
+ 0, /* add_dynamic_symbols */
+ 0, /* add_one_symbol */
+ 0, /* link_dynamic_object */
+ 0, /* write_dynamic_symbol */
+ 0, /* check_dynamic_reloc */
+ 0 /* finish_dynamic_link */
+};
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/i386msdos.c b/contrib/gdb/bfd/i386msdos.c
new file mode 100644
index 0000000..24a456b
--- /dev/null
+++ b/contrib/gdb/bfd/i386msdos.c
@@ -0,0 +1,243 @@
+/* BFD back-end for MS-DOS executables.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Written by Bryan Ford of the University of Utah.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+#if 0
+struct exe_header
+{
+ unsigned short magic;
+ unsigned short bytes_in_last_page;
+ unsigned short npages; /* number of 512-byte "pages" including this header */
+ unsigned short nrelocs;
+ unsigned short header_paras; /* number of 16-byte paragraphs in header */
+ unsigned short reserved;
+ unsigned short load_switch;
+ unsigned short ss_ofs;
+ unsigned short sp;
+ unsigned short checksum;
+ unsigned short ip;
+ unsigned short cs_ofs;
+ unsigned short reloc_ofs;
+ unsigned short reserved2;
+ unsigned short something1;
+ unsigned short something2;
+ unsigned short something3;
+};
+#endif
+
+#define EXE_MAGIC 0x5a4d
+#define EXE_LOAD_HIGH 0x0000
+#define EXE_LOAD_LOW 0xffff
+#define EXE_PAGE_SIZE 512
+
+
+static int
+msdos_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return 0;
+}
+
+static boolean
+msdos_write_object_contents (abfd)
+ bfd *abfd;
+{
+ static char hdr[EXE_PAGE_SIZE];
+ file_ptr outfile_size = sizeof(hdr);
+ bfd_vma high_vma = 0;
+ asection *sec;
+
+ /* Find the total size of the program on disk and in memory. */
+ for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
+ {
+ if (bfd_get_section_size_before_reloc (sec) == 0)
+ continue;
+ if (bfd_get_section_flags (abfd, sec) & SEC_ALLOC)
+ {
+ bfd_vma sec_vma = bfd_get_section_vma (abfd, sec)
+ + bfd_get_section_size_before_reloc (sec);
+ if (sec_vma > high_vma)
+ high_vma = sec_vma;
+ }
+ if (bfd_get_section_flags (abfd, sec) & SEC_LOAD)
+ {
+ file_ptr sec_end = sizeof(hdr)
+ + bfd_get_section_vma (abfd, sec)
+ + bfd_get_section_size_before_reloc (sec);
+ if (sec_end > outfile_size)
+ outfile_size = sec_end;
+ }
+ }
+
+ /* Make sure the program isn't too big. */
+ if (high_vma > (bfd_vma)0xffff)
+ {
+ bfd_set_error(bfd_error_file_too_big);
+ return false;
+ }
+
+ /* constants */
+ bfd_h_put_16(abfd, EXE_MAGIC, &hdr[0]);
+ bfd_h_put_16(abfd, EXE_PAGE_SIZE / 16, &hdr[8]);
+ bfd_h_put_16(abfd, EXE_LOAD_LOW, &hdr[12]);
+ bfd_h_put_16(abfd, 0x3e, &hdr[24]);
+ bfd_h_put_16(abfd, 0x0001, &hdr[28]); /* XXX??? */
+ bfd_h_put_16(abfd, 0x30fb, &hdr[30]); /* XXX??? */
+ bfd_h_put_16(abfd, 0x726a, &hdr[32]); /* XXX??? */
+
+ /* bytes in last page (0 = full page) */
+ bfd_h_put_16(abfd, outfile_size & (EXE_PAGE_SIZE - 1), &hdr[2]);
+
+ /* number of pages */
+ bfd_h_put_16(abfd, (outfile_size + EXE_PAGE_SIZE - 1) / EXE_PAGE_SIZE,
+ &hdr[4]);
+
+ /* Set the initial stack pointer to the end of the bss.
+ The program's crt0 code must relocate it to a real stack. */
+ bfd_h_put_16(abfd, high_vma, &hdr[16]);
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || bfd_write (hdr, 1, sizeof(hdr), abfd) != sizeof(hdr))
+ return false;
+
+ return true;
+}
+
+static boolean
+msdos_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;
+
+ section->filepos = EXE_PAGE_SIZE + bfd_get_section_vma (abfd, section);
+
+ if (bfd_get_section_flags (abfd, section) & SEC_LOAD)
+ {
+ if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
+ || bfd_write (location, 1, count, abfd) != count)
+ return false;
+ }
+
+ return true;
+}
+
+
+
+#define msdos_mkobject aout_32_mkobject
+#define msdos_make_empty_symbol aout_32_make_empty_symbol
+#define msdos_bfd_reloc_type_lookup aout_32_reloc_type_lookup
+
+#define msdos_close_and_cleanup _bfd_generic_close_and_cleanup
+#define msdos_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define msdos_new_section_hook _bfd_generic_new_section_hook
+#define msdos_get_section_contents _bfd_generic_get_section_contents
+#define msdos_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+#define msdos_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define msdos_bfd_relax_section bfd_generic_relax_section
+#define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define msdos_bfd_final_link _bfd_generic_final_link
+#define msdos_bfd_link_split_section _bfd_generic_link_split_section
+#define msdos_set_arch_mach _bfd_generic_set_arch_mach
+
+#define msdos_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
+#define msdos_get_symtab _bfd_nosymbols_get_symtab
+#define msdos_print_symbol _bfd_nosymbols_print_symbol
+#define msdos_get_symbol_info _bfd_nosymbols_get_symbol_info
+#define msdos_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define msdos_get_lineno _bfd_nosymbols_get_lineno
+#define msdos_bfd_is_local_label _bfd_nosymbols_bfd_is_local_label
+#define msdos_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define msdos_read_minisymbols _bfd_nosymbols_read_minisymbols
+#define msdos_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
+
+#define msdos_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
+#define msdos_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
+#define msdos_32_bfd_link_split_section _bfd_generic_link_split_section
+
+const bfd_target i386msdos_vec =
+{
+ "msdos", /* name */
+ bfd_target_msdos_flavour,
+ BFD_ENDIAN_LITTLE, /* target byte order */
+ BFD_ENDIAN_LITTLE, /* target headers byte order */
+ (EXEC_P), /* object flags */
+ (SEC_CODE | SEC_DATA | SEC_HAS_CONTENTS
+ | SEC_ALLOC | SEC_LOAD), /* section flags */
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ {
+ _bfd_dummy_target,
+ _bfd_dummy_target, /* bfd_check_format */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ {
+ bfd_false,
+ msdos_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ msdos_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (msdos),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (msdos),
+ BFD_JUMP_TABLE_RELOCS (msdos),
+ BFD_JUMP_TABLE_WRITE (msdos),
+ BFD_JUMP_TABLE_LINK (msdos),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
+
+
diff --git a/contrib/gdb/bfd/i386netbsd.c b/contrib/gdb/bfd/i386netbsd.c
new file mode 100644
index 0000000..32feaa7
--- /dev/null
+++ b/contrib/gdb/bfd/i386netbsd.c
@@ -0,0 +1,33 @@
+/* BFD back-end for NetBSD/386 a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#undef TARGET_IS_BIG_ENDIAN_P
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+
+#define DEFAULT_ARCH bfd_arch_i386
+#define MACHTYPE_OK(mtype) ((mtype) == M_386_NETBSD || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(i386netbsd_,OP)
+/* This needs to start with a.out so GDB knows it is an a.out variant. */
+#define TARGETNAME "a.out-i386-netbsd"
+
+#include "netbsd.h"
diff --git a/contrib/gdb/bfd/i386os9k.c b/contrib/gdb/bfd/i386os9k.c
new file mode 100644
index 0000000..fe1a021
--- /dev/null
+++ b/contrib/gdb/bfd/i386os9k.c
@@ -0,0 +1,370 @@
+/* BFD back-end for os9000 i386 binaries.
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+#include "os9k.h"
+
+static const bfd_target *os9k_callback PARAMS ((bfd *));
+
+/* Swaps the information in an executable header taken from a raw byte
+ stream memory image, into the internal exec_header structure. */
+boolean
+os9k_swap_exec_header_in (abfd, raw_bytes, execp)
+ bfd *abfd;
+ mh_com *raw_bytes;
+ struct internal_exec *execp;
+{
+ mh_com *bytes = (mh_com *) raw_bytes;
+ unsigned int dload, dmemsize, dmemstart;
+
+ /* Now fill in fields in the execp, from the bytes in the raw data. */
+ execp->a_info = bfd_h_get_16 (abfd, bytes->m_sync);
+ execp->a_syms = 0;
+ execp->a_entry = bfd_h_get_32 (abfd, bytes->m_exec);
+ execp->a_talign = 2;
+ execp->a_dalign = 2;
+ execp->a_balign = 2;
+
+ dload = bfd_h_get_32 (abfd, bytes->m_idata);
+ execp->a_data = dload + 8;
+
+ if (bfd_seek (abfd, (file_ptr) dload, SEEK_SET) != 0
+ || (bfd_read (&dmemstart, sizeof (dmemstart), 1, abfd)
+ != sizeof (dmemstart))
+ || (bfd_read (&dmemsize, sizeof (dmemsize), 1, abfd)
+ != sizeof (dmemsize)))
+ return false;
+
+ execp->a_tload = 0;
+ execp->a_dload = bfd_h_get_32 (abfd, (unsigned char *) &dmemstart);
+ execp->a_text = dload - execp->a_tload;
+ execp->a_data = bfd_h_get_32 (abfd, (unsigned char *) &dmemsize);
+ execp->a_bss = bfd_h_get_32 (abfd, bytes->m_data) - execp->a_data;
+
+ execp->a_trsize = 0;
+ execp->a_drsize = 0;
+
+ return true;
+}
+
+#if 0
+/* Swaps the information in an internal exec header structure into the
+ supplied buffer ready for writing to disk. */
+
+PROTO (void, os9k_swap_exec_header_out,
+ (bfd * abfd,
+ struct internal_exec * execp,
+ struct mh_com * raw_bytes));
+void
+os9k_swap_exec_header_out (abfd, execp, raw_bytes)
+ bfd *abfd;
+ struct internal_exec *execp;
+ mh_com *raw_bytes;
+{
+ mh_com *bytes = (mh_com *) raw_bytes;
+
+ /* Now fill in fields in the raw data, from the fields in the exec struct. */
+ bfd_h_put_32 (abfd, execp->a_info, bytes->e_info);
+ bfd_h_put_32 (abfd, execp->a_text, bytes->e_text);
+ bfd_h_put_32 (abfd, execp->a_data, bytes->e_data);
+ bfd_h_put_32 (abfd, execp->a_bss, bytes->e_bss);
+ bfd_h_put_32 (abfd, execp->a_syms, bytes->e_syms);
+ bfd_h_put_32 (abfd, execp->a_entry, bytes->e_entry);
+ bfd_h_put_32 (abfd, execp->a_trsize, bytes->e_trsize);
+ bfd_h_put_32 (abfd, execp->a_drsize, bytes->e_drsize);
+ bfd_h_put_32 (abfd, execp->a_tload, bytes->e_tload);
+ bfd_h_put_32 (abfd, execp->a_dload, bytes->e_dload);
+ bytes->e_talign[0] = execp->a_talign;
+ bytes->e_dalign[0] = execp->a_dalign;
+ bytes->e_balign[0] = execp->a_balign;
+ bytes->e_relaxable[0] = execp->a_relaxable;
+}
+
+#endif /* 0 */
+
+static const bfd_target *
+os9k_object_p (abfd)
+ bfd *abfd;
+{
+ struct internal_exec anexec;
+ mh_com exec_bytes;
+
+ if (bfd_read ((PTR) & exec_bytes, MHCOM_BYTES_SIZE, 1, abfd)
+ != MHCOM_BYTES_SIZE)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ anexec.a_info = bfd_h_get_16 (abfd, exec_bytes.m_sync);
+ if (N_BADMAG (anexec))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (! os9k_swap_exec_header_in (abfd, &exec_bytes, &anexec))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ return aout_32_some_aout_object_p (abfd, &anexec, os9k_callback);
+}
+
+
+/* Finish up the opening of a b.out file for reading. Fill in all the
+ fields that are not handled by common code. */
+
+static const bfd_target *
+os9k_callback (abfd)
+ bfd *abfd;
+{
+ struct internal_exec *execp = exec_hdr (abfd);
+ unsigned long bss_start;
+
+ /* Architecture and machine type */
+ bfd_set_arch_mach (abfd, bfd_arch_i386, 0);
+
+ /* The positions of the string table and symbol table. */
+ obj_str_filepos (abfd) = 0;
+ obj_sym_filepos (abfd) = 0;
+
+ /* The alignments of the sections */
+ obj_textsec (abfd)->alignment_power = execp->a_talign;
+ obj_datasec (abfd)->alignment_power = execp->a_dalign;
+ obj_bsssec (abfd)->alignment_power = execp->a_balign;
+
+ /* The starting addresses of the sections. */
+ obj_textsec (abfd)->vma = execp->a_tload;
+ obj_datasec (abfd)->vma = execp->a_dload;
+
+ /* And reload the sizes, since the aout module zaps them */
+ obj_textsec (abfd)->_raw_size = execp->a_text;
+
+ bss_start = execp->a_dload + execp->a_data; /* BSS = end of data section */
+ obj_bsssec (abfd)->vma = align_power (bss_start, execp->a_balign);
+
+ /* The file positions of the sections */
+ obj_textsec (abfd)->filepos = execp->a_entry;
+ obj_datasec (abfd)->filepos = execp->a_dload;
+
+ /* The file positions of the relocation info ***
+ obj_textsec (abfd)->rel_filepos = N_TROFF(*execp);
+ obj_datasec (abfd)->rel_filepos = N_DROFF(*execp);
+ */
+
+ adata (abfd).page_size = 1; /* Not applicable. */
+ adata (abfd).segment_size = 1;/* Not applicable. */
+ adata (abfd).exec_bytes_size = MHCOM_BYTES_SIZE;
+
+ return abfd->xvec;
+}
+
+#if 0
+struct bout_data_struct
+{
+ struct aoutdata a;
+ struct internal_exec e;
+};
+
+static boolean
+os9k_mkobject (abfd)
+ bfd *abfd;
+{
+ struct bout_data_struct *rawptr;
+
+ rawptr = (struct bout_data_struct *) bfd_zalloc (abfd, sizeof (struct bout_data_struct));
+ if (rawptr == NULL)
+ return false;
+
+ abfd->tdata.bout_data = rawptr;
+ exec_hdr (abfd) = &rawptr->e;
+
+ obj_textsec (abfd) = (asection *) NULL;
+ obj_datasec (abfd) = (asection *) NULL;
+ obj_bsssec (abfd) = (asection *) NULL;
+
+ return true;
+}
+
+static boolean
+os9k_write_object_contents (abfd)
+ bfd *abfd;
+{
+ struct external_exec swapped_hdr;
+
+ if (! aout_32_make_sections (abfd))
+ return false;
+
+ exec_hdr (abfd)->a_info = BMAGIC;
+
+ exec_hdr (abfd)->a_text = obj_textsec (abfd)->_raw_size;
+ exec_hdr (abfd)->a_data = obj_datasec (abfd)->_raw_size;
+ exec_hdr (abfd)->a_bss = obj_bsssec (abfd)->_raw_size;
+ exec_hdr (abfd)->a_syms = bfd_get_symcount (abfd) * sizeof (struct nlist);
+ exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
+ exec_hdr (abfd)->a_trsize = ((obj_textsec (abfd)->reloc_count) *
+ sizeof (struct relocation_info));
+ exec_hdr (abfd)->a_drsize = ((obj_datasec (abfd)->reloc_count) *
+ sizeof (struct relocation_info));
+
+ exec_hdr (abfd)->a_talign = obj_textsec (abfd)->alignment_power;
+ exec_hdr (abfd)->a_dalign = obj_datasec (abfd)->alignment_power;
+ exec_hdr (abfd)->a_balign = obj_bsssec (abfd)->alignment_power;
+
+ exec_hdr (abfd)->a_tload = obj_textsec (abfd)->vma;
+ exec_hdr (abfd)->a_dload = obj_datasec (abfd)->vma;
+
+ bout_swap_exec_header_out (abfd, exec_hdr (abfd), &swapped_hdr);
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || (bfd_write ((PTR) & swapped_hdr, 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_seek (abfd, (file_ptr) (N_SYMOFF (*exec_hdr (abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ if (!aout_32_write_syms (abfd))
+ return false;
+
+ if (bfd_seek (abfd, (file_ptr) (N_TROFF (*exec_hdr (abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ if (!b_out_squirt_out_relocs (abfd, obj_textsec (abfd)))
+ return false;
+ if (bfd_seek (abfd, (file_ptr) (N_DROFF (*exec_hdr (abfd))), SEEK_SET)
+ != 0)
+ return false;
+
+ if (!b_out_squirt_out_relocs (abfd, obj_datasec (abfd)))
+ return false;
+ }
+ return true;
+}
+
+static boolean
+os9k_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ unsigned char *location;
+ file_ptr offset;
+ int count;
+{
+
+ if (abfd->output_has_begun == false)
+ { /* set by bfd.c handler */
+ if (! aout_32_make_sections (abfd))
+ return false;
+
+ obj_textsec (abfd)->filepos = sizeof (struct internal_exec);
+ obj_datasec (abfd)->filepos = obj_textsec (abfd)->filepos
+ + obj_textsec (abfd)->_raw_size;
+
+ }
+ /* regardless, once we know what we're doing, we might as well get going */
+ if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0)
+ return false;
+
+ if (count != 0)
+ {
+ return (bfd_write ((PTR) location, 1, count, abfd) == count) ? true : false;
+ }
+ return true;
+}
+#endif /* 0 */
+
+static int
+os9k_sizeof_headers (ignore_abfd, ignore)
+ bfd *ignore_abfd;
+ boolean ignore;
+{
+ return sizeof (struct internal_exec);
+}
+
+
+/***********************************************************************/
+
+#define aout_32_close_and_cleanup aout_32_bfd_free_cached_info
+
+#define aout_32_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+
+#define aout_32_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define aout_32_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#define os9k_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define os9k_bfd_relax_section bfd_generic_relax_section
+#define os9k_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define os9k_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define os9k_bfd_final_link _bfd_generic_final_link
+#define os9k_bfd_link_split_section _bfd_generic_link_split_section
+
+const bfd_target i386os9k_vec =
+{
+ "i386os9k", /* name */
+ bfd_target_os9k_flavour,
+ BFD_ENDIAN_LITTLE, /* data byte order is little */
+ BFD_ENDIAN_LITTLE, /* hdr byte order is little */
+ (HAS_RELOC | EXEC_P | WP_TEXT), /* object flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD), /* section flags */
+ 0, /* symbol leading char */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+ {_bfd_dummy_target, os9k_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, _bfd_dummy_target},
+ {bfd_false, bfd_false, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, bfd_false, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ BFD_JUMP_TABLE_GENERIC (aout_32),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_bsd),
+ BFD_JUMP_TABLE_SYMBOLS (aout_32),
+ BFD_JUMP_TABLE_RELOCS (aout_32),
+ BFD_JUMP_TABLE_WRITE (aout_32),
+ BFD_JUMP_TABLE_LINK (os9k),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0,
+};
diff --git a/contrib/gdb/bfd/ieee.c b/contrib/gdb/bfd/ieee.c
new file mode 100644
index 0000000..201f225
--- /dev/null
+++ b/contrib/gdb/bfd/ieee.c
@@ -0,0 +1,3738 @@
+/* BFD back-end for ieee-695 objects.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define KEEPMINUSPCININST 0
+
+/* IEEE 695 format is a stream of records, which we parse using a simple one-
+ token (which is one byte in this lexicon) lookahead recursive decent
+ parser. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "ieee.h"
+#include "libieee.h"
+
+static boolean ieee_write_byte PARAMS ((bfd *, bfd_byte));
+static boolean ieee_write_2bytes PARAMS ((bfd *, int));
+static boolean ieee_write_int PARAMS ((bfd *, bfd_vma));
+static boolean ieee_write_id PARAMS ((bfd *, const char *));
+static boolean ieee_write_expression
+ PARAMS ((bfd *, bfd_vma, asymbol *, boolean, unsigned int));
+static void ieee_write_int5 PARAMS ((bfd_byte *, bfd_vma));
+static boolean ieee_write_int5_out PARAMS ((bfd *, bfd_vma));
+static boolean ieee_write_section_part PARAMS ((bfd *));
+static boolean do_with_relocs PARAMS ((bfd *, asection *));
+static boolean do_as_repeat PARAMS ((bfd *, asection *));
+static boolean do_without_relocs PARAMS ((bfd *, asection *));
+static boolean ieee_write_external_part PARAMS ((bfd *));
+static boolean ieee_write_data_part PARAMS ((bfd *));
+static boolean ieee_write_debug_part PARAMS ((bfd *));
+static boolean ieee_write_me_part PARAMS ((bfd *));
+static boolean ieee_write_processor PARAMS ((bfd *));
+
+static boolean ieee_slurp_debug PARAMS ((bfd *));
+static boolean ieee_slurp_section_data PARAMS ((bfd *));
+
+/* Functions for writing to ieee files in the strange way that the
+ standard requires. */
+
+static boolean
+ieee_write_byte (abfd, byte)
+ bfd *abfd;
+ bfd_byte byte;
+{
+ if (bfd_write ((PTR) &byte, 1, 1, abfd) != 1)
+ return false;
+ return true;
+}
+
+static boolean
+ieee_write_2bytes (abfd, bytes)
+ bfd *abfd;
+ int bytes;
+{
+ bfd_byte buffer[2];
+
+ buffer[0] = bytes >> 8;
+ buffer[1] = bytes & 0xff;
+ if (bfd_write ((PTR) buffer, 1, 2, abfd) != 2)
+ return false;
+ return true;
+}
+
+static boolean
+ieee_write_int (abfd, value)
+ bfd *abfd;
+ bfd_vma value;
+{
+ if (value <= 127)
+ {
+ if (! ieee_write_byte (abfd, (bfd_byte) value))
+ return false;
+ }
+ else
+ {
+ unsigned int length;
+
+ /* How many significant bytes ? */
+ /* FIXME FOR LONGER INTS */
+ if (value & 0xff000000)
+ length = 4;
+ else if (value & 0x00ff0000)
+ length = 3;
+ else if (value & 0x0000ff00)
+ length = 2;
+ else
+ length = 1;
+
+ if (! ieee_write_byte (abfd,
+ (bfd_byte) ((int) ieee_number_repeat_start_enum
+ + length)))
+ return false;
+ switch (length)
+ {
+ case 4:
+ if (! ieee_write_byte (abfd, (bfd_byte) (value >> 24)))
+ return false;
+ /* Fall through. */
+ case 3:
+ if (! ieee_write_byte (abfd, (bfd_byte) (value >> 16)))
+ return false;
+ /* Fall through. */
+ case 2:
+ if (! ieee_write_byte (abfd, (bfd_byte) (value >> 8)))
+ return false;
+ /* Fall through. */
+ case 1:
+ if (! ieee_write_byte (abfd, (bfd_byte) (value)))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static boolean
+ieee_write_id (abfd, id)
+ bfd *abfd;
+ const char *id;
+{
+ size_t length = strlen (id);
+
+ if (length <= 127)
+ {
+ if (! ieee_write_byte (abfd, (bfd_byte) length))
+ return false;
+ }
+ else if (length < 255)
+ {
+ if (! ieee_write_byte (abfd, ieee_extension_length_1_enum)
+ || ! ieee_write_byte (abfd, (bfd_byte) length))
+ return false;
+ }
+ else if (length < 65535)
+ {
+ if (! ieee_write_byte (abfd, ieee_extension_length_2_enum)
+ || ! ieee_write_2bytes (abfd, (int) length))
+ return false;
+ }
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: string too long (%d chars, max 65535)",
+ bfd_get_filename (abfd), length);
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ if (bfd_write ((PTR) id, 1, length, abfd) != length)
+ return false;
+ return true;
+}
+
+/***************************************************************************
+Functions for reading from ieee files in the strange way that the
+standard requires:
+*/
+
+#define this_byte(ieee) *((ieee)->input_p)
+#define next_byte(ieee) ((ieee)->input_p++)
+#define this_byte_and_next(ieee) (*((ieee)->input_p++))
+
+static unsigned short
+read_2bytes (ieee)
+ common_header_type *ieee;
+{
+ unsigned char c1 = this_byte_and_next (ieee);
+ unsigned char c2 = this_byte_and_next (ieee);
+ return (c1 << 8) | c2;
+}
+
+static void
+bfd_get_string (ieee, string, length)
+ common_header_type *ieee;
+ char *string;
+ size_t length;
+{
+ size_t i;
+ for (i = 0; i < length; i++)
+ {
+ string[i] = this_byte_and_next (ieee);
+ }
+}
+
+static char *
+read_id (ieee)
+ common_header_type *ieee;
+{
+ size_t length;
+ char *string;
+ length = this_byte_and_next (ieee);
+ if (length <= 0x7f)
+ {
+ /* Simple string of length 0 to 127 */
+ }
+ else if (length == 0xde)
+ {
+ /* Length is next byte, allowing 0..255 */
+ length = this_byte_and_next (ieee);
+ }
+ else if (length == 0xdf)
+ {
+ /* Length is next two bytes, allowing 0..65535 */
+ length = this_byte_and_next (ieee);
+ length = (length * 256) + this_byte_and_next (ieee);
+ }
+ /* Buy memory and read string */
+ string = bfd_alloc (ieee->abfd, length + 1);
+ if (!string)
+ return NULL;
+ bfd_get_string (ieee, string, length);
+ string[length] = 0;
+ return string;
+}
+
+static boolean
+ieee_write_expression (abfd, value, symbol, pcrel, index)
+ bfd *abfd;
+ bfd_vma value;
+ asymbol *symbol;
+ boolean pcrel;
+ unsigned int index;
+{
+ unsigned int term_count = 0;
+
+ if (value != 0)
+ {
+ if (! ieee_write_int (abfd, value))
+ return false;
+ term_count++;
+ }
+
+ if (bfd_is_com_section (symbol->section)
+ || bfd_is_und_section (symbol->section))
+ {
+ /* Def of a common symbol */
+ if (! ieee_write_byte (abfd, ieee_variable_X_enum)
+ || ! ieee_write_int (abfd, symbol->value))
+ return false;
+ term_count++;
+ }
+ else if (! bfd_is_abs_section (symbol->section))
+ {
+ /* Ref to defined symbol - */
+
+ if (symbol->flags & BSF_GLOBAL)
+ {
+ if (! ieee_write_byte (abfd, ieee_variable_I_enum)
+ || ! ieee_write_int (abfd, symbol->value))
+ return false;
+ term_count++;
+ }
+ else if (symbol->flags & (BSF_LOCAL | BSF_SECTION_SYM))
+ {
+ /* This is a reference to a defined local symbol. We can
+ easily do a local as a section+offset. */
+ if (! ieee_write_byte (abfd, ieee_variable_R_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (symbol->section->index
+ + IEEE_SECTION_NUMBER_BASE)))
+ return false;
+ term_count++;
+ if (symbol->value != 0)
+ {
+ if (! ieee_write_int (abfd, symbol->value))
+ return false;
+ term_count++;
+ }
+ }
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: unrecognized symbol `%s' flags 0x%x",
+ bfd_get_filename (abfd), bfd_asymbol_name (symbol),
+ symbol->flags);
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+ }
+
+ if (pcrel)
+ {
+ /* subtract the pc from here by asking for PC of this section*/
+ if (! ieee_write_byte (abfd, ieee_variable_P_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (index + IEEE_SECTION_NUMBER_BASE))
+ || ! ieee_write_byte (abfd, ieee_function_minus_enum))
+ return false;
+ }
+
+ /* Handle the degenerate case of a 0 address. */
+ if (term_count == 0)
+ {
+ if (! ieee_write_int (abfd, 0))
+ return false;
+ }
+
+ while (term_count > 1)
+ {
+ if (! ieee_write_byte (abfd, ieee_function_plus_enum))
+ return false;
+ term_count--;
+ }
+
+ return true;
+}
+
+/*****************************************************************************/
+
+/*
+writes any integer into the buffer supplied and always takes 5 bytes
+*/
+static void
+ieee_write_int5 (buffer, value)
+ bfd_byte *buffer;
+ bfd_vma value;
+{
+ buffer[0] = (bfd_byte) ieee_number_repeat_4_enum;
+ buffer[1] = (value >> 24) & 0xff;
+ buffer[2] = (value >> 16) & 0xff;
+ buffer[3] = (value >> 8) & 0xff;
+ buffer[4] = (value >> 0) & 0xff;
+}
+
+static boolean
+ieee_write_int5_out (abfd, value)
+ bfd *abfd;
+ bfd_vma value;
+{
+ bfd_byte b[5];
+
+ ieee_write_int5 (b, value);
+ if (bfd_write ((PTR) b, 1, 5, abfd) != 5)
+ return false;
+ return true;
+}
+
+static boolean
+parse_int (ieee, value_ptr)
+ common_header_type *ieee;
+ bfd_vma *value_ptr;
+{
+ int value = this_byte (ieee);
+ int result;
+ if (value >= 0 && value <= 127)
+ {
+ *value_ptr = value;
+ next_byte (ieee);
+ return true;
+ }
+ else if (value >= 0x80 && value <= 0x88)
+ {
+ unsigned int count = value & 0xf;
+ result = 0;
+ next_byte (ieee);
+ while (count)
+ {
+ result = (result << 8) | this_byte_and_next (ieee);
+ count--;
+ }
+ *value_ptr = result;
+ return true;
+ }
+ return false;
+}
+
+static int
+parse_i (ieee, ok)
+ common_header_type *ieee;
+ boolean *ok;
+{
+ bfd_vma x;
+ *ok = parse_int (ieee, &x);
+ return x;
+}
+
+static bfd_vma
+must_parse_int (ieee)
+ common_header_type *ieee;
+{
+ bfd_vma result;
+ BFD_ASSERT (parse_int (ieee, &result) == true);
+ return result;
+}
+
+typedef struct
+{
+ bfd_vma value;
+ asection *section;
+ ieee_symbol_index_type symbol;
+} ieee_value_type;
+
+
+#ifdef KEEPMINUSPCININST
+
+#define SRC_MASK(arg) arg
+#define PCREL_OFFSET false
+
+#else
+
+#define SRC_MASK(arg) 0
+#define PCREL_OFFSET true
+
+#endif
+
+static reloc_howto_type abs32_howto =
+ HOWTO (1,
+ 0,
+ 2,
+ 32,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ 0,
+ "abs32",
+ true,
+ 0xffffffff,
+ 0xffffffff,
+ false);
+
+static reloc_howto_type abs16_howto =
+ HOWTO (1,
+ 0,
+ 1,
+ 16,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ 0,
+ "abs16",
+ true,
+ 0x0000ffff,
+ 0x0000ffff,
+ false);
+
+static reloc_howto_type abs8_howto =
+ HOWTO (1,
+ 0,
+ 0,
+ 8,
+ false,
+ 0,
+ complain_overflow_bitfield,
+ 0,
+ "abs8",
+ true,
+ 0x000000ff,
+ 0x000000ff,
+ false);
+
+static reloc_howto_type rel32_howto =
+ HOWTO (1,
+ 0,
+ 2,
+ 32,
+ true,
+ 0,
+ complain_overflow_signed,
+ 0,
+ "rel32",
+ true,
+ SRC_MASK (0xffffffff),
+ 0xffffffff,
+ PCREL_OFFSET);
+
+static reloc_howto_type rel16_howto =
+ HOWTO (1,
+ 0,
+ 1,
+ 16,
+ true,
+ 0,
+ complain_overflow_signed,
+ 0,
+ "rel16",
+ true,
+ SRC_MASK (0x0000ffff),
+ 0x0000ffff,
+ PCREL_OFFSET);
+
+static reloc_howto_type rel8_howto =
+ HOWTO (1,
+ 0,
+ 0,
+ 8,
+ true,
+ 0,
+ complain_overflow_signed,
+ 0,
+ "rel8",
+ true,
+ SRC_MASK (0x000000ff),
+ 0x000000ff,
+ PCREL_OFFSET);
+
+static ieee_symbol_index_type NOSYMBOL = {0, 0};
+
+static void
+parse_expression (ieee, value, symbol, pcrel, extra, section)
+ ieee_data_type *ieee;
+ bfd_vma *value;
+ ieee_symbol_index_type *symbol;
+ boolean *pcrel;
+ unsigned int *extra;
+ asection **section;
+
+{
+#define POS sp[1]
+#define TOS sp[0]
+#define NOS sp[-1]
+#define INC sp++;
+#define DEC sp--;
+
+ boolean loop = true;
+ ieee_value_type stack[10];
+
+ /* The stack pointer always points to the next unused location */
+#define PUSH(x,y,z) TOS.symbol=x;TOS.section=y;TOS.value=z;INC;
+#define POP(x,y,z) DEC;x=TOS.symbol;y=TOS.section;z=TOS.value;
+ ieee_value_type *sp = stack;
+
+ while (loop)
+ {
+ switch (this_byte (&(ieee->h)))
+ {
+ case ieee_variable_P_enum:
+ /* P variable, current program counter for section n */
+ {
+ int section_n;
+ next_byte (&(ieee->h));
+ *pcrel = true;
+ section_n = must_parse_int (&(ieee->h));
+ PUSH (NOSYMBOL, bfd_abs_section_ptr, 0);
+ break;
+ }
+ case ieee_variable_L_enum:
+ /* L variable address of section N */
+ next_byte (&(ieee->h));
+ PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0);
+ break;
+ case ieee_variable_R_enum:
+ /* R variable, logical address of section module */
+ /* FIXME, this should be different to L */
+ next_byte (&(ieee->h));
+ PUSH (NOSYMBOL, ieee->section_table[must_parse_int (&(ieee->h))], 0);
+ break;
+ case ieee_variable_S_enum:
+ /* S variable, size in MAUS of section module */
+ next_byte (&(ieee->h));
+ PUSH (NOSYMBOL,
+ 0,
+ ieee->section_table[must_parse_int (&(ieee->h))]->_raw_size);
+ break;
+ case ieee_variable_I_enum:
+ /* Push the address of variable n */
+ {
+ ieee_symbol_index_type sy;
+ next_byte (&(ieee->h));
+ sy.index = (int) must_parse_int (&(ieee->h));
+ sy.letter = 'I';
+
+ PUSH (sy, bfd_abs_section_ptr, 0);
+ }
+ break;
+ case ieee_variable_X_enum:
+ /* Push the address of external variable n */
+ {
+ ieee_symbol_index_type sy;
+ next_byte (&(ieee->h));
+ sy.index = (int) (must_parse_int (&(ieee->h)));
+ sy.letter = 'X';
+
+ PUSH (sy, bfd_und_section_ptr, 0);
+ }
+ break;
+ case ieee_function_minus_enum:
+ {
+ bfd_vma value1, value2;
+ asection *section1, *section_dummy;
+ ieee_symbol_index_type sy;
+ next_byte (&(ieee->h));
+
+ POP (sy, section1, value1);
+ POP (sy, section_dummy, value2);
+ PUSH (sy, section1 ? section1 : section_dummy, value2 - value1);
+ }
+ break;
+ case ieee_function_plus_enum:
+ {
+ bfd_vma value1, value2;
+ asection *section1;
+ asection *section2;
+ ieee_symbol_index_type sy1;
+ ieee_symbol_index_type sy2;
+ next_byte (&(ieee->h));
+
+ POP (sy1, section1, value1);
+ POP (sy2, section2, value2);
+ PUSH (sy1.letter ? sy1 : sy2,
+ bfd_is_abs_section (section1) ? section2 : section1,
+ value1 + value2);
+ }
+ break;
+ default:
+ {
+ bfd_vma va;
+ BFD_ASSERT (this_byte (&(ieee->h)) < (int) ieee_variable_A_enum
+ || this_byte (&(ieee->h)) > (int) ieee_variable_Z_enum);
+ if (parse_int (&(ieee->h), &va))
+ {
+ PUSH (NOSYMBOL, bfd_abs_section_ptr, va);
+ }
+ else
+ {
+ /*
+ Thats all that we can understand. As far as I can see
+ there is a bug in the Microtec IEEE output which I'm
+ using to scan, whereby the comma operator is omitted
+ sometimes in an expression, giving expressions with too
+ many terms. We can tell if that's the case by ensuring
+ that sp == stack here. If not, then we've pushed
+ something too far, so we keep adding. */
+
+ while (sp != stack + 1)
+ {
+ asection *section1;
+ ieee_symbol_index_type sy1;
+ POP (sy1, section1, *extra);
+ }
+ {
+ asection *dummy;
+
+ POP (*symbol, dummy, *value);
+ if (section)
+ *section = dummy;
+ }
+
+ loop = false;
+ }
+ }
+ }
+ }
+}
+
+
+#define ieee_seek(abfd, offset) \
+ IEEE_DATA(abfd)->h.input_p = IEEE_DATA(abfd)->h.first_byte + offset
+
+#define ieee_pos(abfd) \
+ (IEEE_DATA(abfd)->h.input_p - IEEE_DATA(abfd)->h.first_byte)
+
+static unsigned int last_index;
+static char last_type; /* is the index for an X or a D */
+
+static ieee_symbol_type *
+get_symbol (abfd,
+ ieee,
+ last_symbol,
+ symbol_count,
+ pptr,
+ max_index,
+ this_type
+)
+ bfd *abfd;
+ ieee_data_type *ieee;
+ ieee_symbol_type *last_symbol;
+ unsigned int *symbol_count;
+ ieee_symbol_type ***pptr;
+ unsigned int *max_index;
+ char this_type
+ ;
+{
+ /* Need a new symbol */
+ unsigned int new_index = must_parse_int (&(ieee->h));
+ if (new_index != last_index || this_type != last_type)
+ {
+ ieee_symbol_type *new_symbol = (ieee_symbol_type *) bfd_alloc (ieee->h.abfd,
+ sizeof (ieee_symbol_type));
+ if (!new_symbol)
+ return NULL;
+
+ new_symbol->index = new_index;
+ last_index = new_index;
+ (*symbol_count)++;
+ **pptr = new_symbol;
+ *pptr = &new_symbol->next;
+ if (new_index > *max_index)
+ {
+ *max_index = new_index;
+ }
+ last_type = this_type;
+ new_symbol->symbol.section = bfd_abs_section_ptr;
+ return new_symbol;
+ }
+ return last_symbol;
+}
+
+static boolean
+ieee_slurp_external_symbols (abfd)
+ bfd *abfd;
+{
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ file_ptr offset = ieee->w.r.external_part;
+
+ ieee_symbol_type **prev_symbols_ptr = &ieee->external_symbols;
+ ieee_symbol_type **prev_reference_ptr = &ieee->external_reference;
+ ieee_symbol_type *symbol = (ieee_symbol_type *) NULL;
+ unsigned int symbol_count = 0;
+ boolean loop = true;
+ last_index = 0xffffff;
+ ieee->symbol_table_full = true;
+
+ ieee_seek (abfd, offset);
+
+ while (loop)
+ {
+ switch (this_byte (&(ieee->h)))
+ {
+ case ieee_nn_record:
+ next_byte (&(ieee->h));
+
+ symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
+ &prev_symbols_ptr,
+ &ieee->external_symbol_max_index, 'I');
+ if (symbol == NULL)
+ return false;
+
+ symbol->symbol.the_bfd = abfd;
+ symbol->symbol.name = read_id (&(ieee->h));
+ symbol->symbol.udata.p = (PTR) NULL;
+ symbol->symbol.flags = BSF_NO_FLAGS;
+ break;
+ case ieee_external_symbol_enum:
+ next_byte (&(ieee->h));
+
+ symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
+ &prev_symbols_ptr,
+ &ieee->external_symbol_max_index, 'D');
+ if (symbol == NULL)
+ return false;
+
+ BFD_ASSERT (symbol->index >= ieee->external_symbol_min_index);
+
+ symbol->symbol.the_bfd = abfd;
+ symbol->symbol.name = read_id (&(ieee->h));
+ symbol->symbol.udata.p = (PTR) NULL;
+ symbol->symbol.flags = BSF_NO_FLAGS;
+ break;
+ case ieee_attribute_record_enum >> 8:
+ {
+ unsigned int symbol_name_index;
+ unsigned int symbol_type_index;
+ unsigned int symbol_attribute_def;
+ bfd_vma value;
+ switch (read_2bytes (ieee))
+ {
+ case ieee_attribute_record_enum:
+ symbol_name_index = must_parse_int (&(ieee->h));
+ symbol_type_index = must_parse_int (&(ieee->h));
+ symbol_attribute_def = must_parse_int (&(ieee->h));
+ switch (symbol_attribute_def)
+ {
+ case 8:
+ case 19:
+ parse_int (&ieee->h, &value);
+ break;
+ default:
+ (*_bfd_error_handler)
+ ("%s: unimplemented ATI record %u for symbol %u",
+ bfd_get_filename (abfd), symbol_attribute_def,
+ symbol_name_index);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ break;
+ }
+ break;
+ case ieee_external_reference_info_record_enum:
+ /* Skip over ATX record. */
+ parse_int (&(ieee->h), &value);
+ parse_int (&(ieee->h), &value);
+ parse_int (&(ieee->h), &value);
+ parse_int (&(ieee->h), &value);
+ break;
+ }
+ }
+ break;
+ case ieee_value_record_enum >> 8:
+ {
+ unsigned int symbol_name_index;
+ ieee_symbol_index_type symbol_ignore;
+ boolean pcrel_ignore;
+ unsigned int extra;
+ next_byte (&(ieee->h));
+ next_byte (&(ieee->h));
+
+ symbol_name_index = must_parse_int (&(ieee->h));
+ parse_expression (ieee,
+ &symbol->symbol.value,
+ &symbol_ignore,
+ &pcrel_ignore,
+ &extra,
+ &symbol->symbol.section);
+
+ symbol->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+
+ }
+ break;
+ case ieee_weak_external_reference_enum:
+ {
+ bfd_vma size;
+ bfd_vma value;
+ next_byte (&(ieee->h));
+ /* Throw away the external reference index */
+ (void) must_parse_int (&(ieee->h));
+ /* Fetch the default size if not resolved */
+ size = must_parse_int (&(ieee->h));
+ /* Fetch the defautlt value if available */
+ if (parse_int (&(ieee->h), &value) == false)
+ {
+ value = 0;
+ }
+ /* This turns into a common */
+ symbol->symbol.section = bfd_com_section_ptr;
+ symbol->symbol.value = size;
+ }
+ break;
+
+ case ieee_external_reference_enum:
+ next_byte (&(ieee->h));
+
+ symbol = get_symbol (abfd, ieee, symbol, &symbol_count,
+ &prev_reference_ptr,
+ &ieee->external_reference_max_index, 'X');
+ if (symbol == NULL)
+ return false;
+
+ symbol->symbol.the_bfd = abfd;
+ symbol->symbol.name = read_id (&(ieee->h));
+ symbol->symbol.udata.p = (PTR) NULL;
+ symbol->symbol.section = bfd_und_section_ptr;
+ symbol->symbol.value = (bfd_vma) 0;
+ symbol->symbol.flags = 0;
+
+ BFD_ASSERT (symbol->index >= ieee->external_reference_min_index);
+ break;
+
+ default:
+ loop = false;
+ }
+ }
+
+ if (ieee->external_symbol_max_index != 0)
+ {
+ ieee->external_symbol_count =
+ ieee->external_symbol_max_index -
+ ieee->external_symbol_min_index + 1;
+ }
+ else
+ {
+ ieee->external_symbol_count = 0;
+ }
+
+ if (ieee->external_reference_max_index != 0)
+ {
+ ieee->external_reference_count =
+ ieee->external_reference_max_index -
+ ieee->external_reference_min_index + 1;
+ }
+ else
+ {
+ ieee->external_reference_count = 0;
+ }
+
+ abfd->symcount =
+ ieee->external_reference_count + ieee->external_symbol_count;
+
+ if (symbol_count != abfd->symcount)
+ {
+ /* There are gaps in the table -- */
+ ieee->symbol_table_full = false;
+ }
+
+ *prev_symbols_ptr = (ieee_symbol_type *) NULL;
+ *prev_reference_ptr = (ieee_symbol_type *) NULL;
+
+ return true;
+}
+
+static boolean
+ieee_slurp_symbol_table (abfd)
+ bfd *abfd;
+{
+ if (IEEE_DATA (abfd)->read_symbols == false)
+ {
+ if (! ieee_slurp_external_symbols (abfd))
+ return false;
+ IEEE_DATA (abfd)->read_symbols = true;
+ }
+ return true;
+}
+
+long
+ieee_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ if (! ieee_slurp_symbol_table (abfd))
+ return -1;
+
+ return (abfd->symcount != 0) ?
+ (abfd->symcount + 1) * (sizeof (ieee_symbol_type *)) : 0;
+}
+
+/*
+Move from our internal lists to the canon table, and insert in
+symbol index order
+*/
+
+extern const bfd_target ieee_vec;
+
+long
+ieee_get_symtab (abfd, location)
+ bfd *abfd;
+ asymbol **location;
+{
+ ieee_symbol_type *symp;
+ static bfd dummy_bfd;
+ static asymbol empty_symbol =
+ /* the_bfd, name, value, attr, section */
+ {&dummy_bfd, " ieee empty", (symvalue) 0, BSF_DEBUGGING, bfd_abs_section_ptr};
+
+ if (abfd->symcount)
+ {
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ dummy_bfd.xvec = &ieee_vec;
+ if (! ieee_slurp_symbol_table (abfd))
+ return -1;
+
+ if (ieee->symbol_table_full == false)
+ {
+ /* Arrgh - there are gaps in the table, run through and fill them */
+ /* up with pointers to a null place */
+ unsigned int i;
+ for (i = 0; i < abfd->symcount; i++)
+ {
+ location[i] = &empty_symbol;
+ }
+ }
+
+ ieee->external_symbol_base_offset = -ieee->external_symbol_min_index;
+ for (symp = IEEE_DATA (abfd)->external_symbols;
+ symp != (ieee_symbol_type *) NULL;
+ symp = symp->next)
+ {
+ /* Place into table at correct index locations */
+ location[symp->index + ieee->external_symbol_base_offset] = &symp->symbol;
+ }
+
+ /* The external refs are indexed in a bit */
+ ieee->external_reference_base_offset =
+ -ieee->external_reference_min_index + ieee->external_symbol_count;
+
+ for (symp = IEEE_DATA (abfd)->external_reference;
+ symp != (ieee_symbol_type *) NULL;
+ symp = symp->next)
+ {
+ location[symp->index + ieee->external_reference_base_offset] =
+ &symp->symbol;
+
+ }
+ }
+ if (abfd->symcount)
+ {
+ location[abfd->symcount] = (asymbol *) NULL;
+ }
+ return abfd->symcount;
+}
+
+static asection *
+get_section_entry (abfd, ieee, index)
+ bfd *abfd;
+ ieee_data_type *ieee;
+ unsigned int index;
+{
+ if (ieee->section_table[index] == (asection *) NULL)
+ {
+ char *tmp = bfd_alloc (abfd, 11);
+ asection *section;
+
+ if (!tmp)
+ return NULL;
+ sprintf (tmp, " fsec%4d", index);
+ section = bfd_make_section (abfd, tmp);
+ ieee->section_table[index] = section;
+ section->flags = SEC_NO_FLAGS;
+ section->target_index = index;
+ ieee->section_table[index] = section;
+ }
+ return ieee->section_table[index];
+}
+
+static void
+ieee_slurp_sections (abfd)
+ bfd *abfd;
+{
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ file_ptr offset = ieee->w.r.section_part;
+ asection *section = (asection *) NULL;
+ char *name;
+
+ if (offset != 0)
+ {
+ bfd_byte section_type[3];
+ ieee_seek (abfd, offset);
+ while (true)
+ {
+ switch (this_byte (&(ieee->h)))
+ {
+ case ieee_section_type_enum:
+ {
+ unsigned int section_index;
+ next_byte (&(ieee->h));
+ section_index = must_parse_int (&(ieee->h));
+ /* Fixme to be nice about a silly number of sections */
+ BFD_ASSERT (section_index < NSECTIONS);
+
+ section = get_section_entry (abfd, ieee, section_index);
+
+ section_type[0] = this_byte_and_next (&(ieee->h));
+
+ /* Set minimal section attributes. Attributes are
+ extended later, based on section contents. */
+
+ switch (section_type[0])
+ {
+ case 0xC1:
+ /* Normal attributes for absolute sections */
+ section_type[1] = this_byte (&(ieee->h));
+ section->flags = SEC_ALLOC;
+ switch (section_type[1])
+ {
+ case 0xD3: /* AS Absolute section attributes */
+ next_byte (&(ieee->h));
+ section_type[2] = this_byte (&(ieee->h));
+ switch (section_type[2])
+ {
+ case 0xD0:
+ /* Normal code */
+ next_byte (&(ieee->h));
+ section->flags |= SEC_CODE;
+ break;
+ case 0xC4:
+ /* Normal data */
+ next_byte (&(ieee->h));
+ section->flags |= SEC_DATA;
+ break;
+ case 0xD2:
+ next_byte (&(ieee->h));
+ /* Normal rom data */
+ section->flags |= SEC_ROM | SEC_DATA;
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case 0xC3: /* Named relocatable sections (type C) */
+ section_type[1] = this_byte (&(ieee->h));
+ section->flags = SEC_ALLOC;
+ switch (section_type[1])
+ {
+ case 0xD0: /* Normal code (CP) */
+ next_byte (&(ieee->h));
+ section->flags |= SEC_CODE;
+ break;
+ case 0xC4: /* Normal data (CD) */
+ next_byte (&(ieee->h));
+ section->flags |= SEC_DATA;
+ break;
+ case 0xD2: /* Normal rom data (CR) */
+ next_byte (&(ieee->h));
+ section->flags |= SEC_ROM | SEC_DATA;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Read section name, use it if non empty. */
+ name = read_id (&ieee->h);
+ if (name[0])
+ section->name = name;
+
+ /* Skip these fields, which we don't care about */
+ {
+ bfd_vma parent, brother, context;
+ parse_int (&(ieee->h), &parent);
+ parse_int (&(ieee->h), &brother);
+ parse_int (&(ieee->h), &context);
+ }
+ }
+ break;
+ case ieee_section_alignment_enum:
+ {
+ unsigned int section_index;
+ bfd_vma value;
+ asection *section;
+ next_byte (&(ieee->h));
+ section_index = must_parse_int (&ieee->h);
+ section = get_section_entry (abfd, ieee, section_index);
+ if (section_index > ieee->section_count)
+ {
+ ieee->section_count = section_index;
+ }
+ section->alignment_power =
+ bfd_log2 (must_parse_int (&ieee->h));
+ (void) parse_int (&(ieee->h), &value);
+ }
+ break;
+ case ieee_e2_first_byte_enum:
+ {
+ ieee_record_enum_type t = (ieee_record_enum_type) (read_2bytes (&(ieee->h)));
+
+ switch (t)
+ {
+ case ieee_section_size_enum:
+ section = ieee->section_table[must_parse_int (&(ieee->h))];
+ section->_raw_size = must_parse_int (&(ieee->h));
+ break;
+ case ieee_physical_region_size_enum:
+ section = ieee->section_table[must_parse_int (&(ieee->h))];
+ section->_raw_size = must_parse_int (&(ieee->h));
+ break;
+ case ieee_region_base_address_enum:
+ section = ieee->section_table[must_parse_int (&(ieee->h))];
+ section->vma = must_parse_int (&(ieee->h));
+ section->lma = section->vma;
+ break;
+ case ieee_mau_size_enum:
+ must_parse_int (&(ieee->h));
+ must_parse_int (&(ieee->h));
+ break;
+ case ieee_m_value_enum:
+ must_parse_int (&(ieee->h));
+ must_parse_int (&(ieee->h));
+ break;
+ case ieee_section_base_address_enum:
+ section = ieee->section_table[must_parse_int (&(ieee->h))];
+ section->vma = must_parse_int (&(ieee->h));
+ section->lma = section->vma;
+ break;
+ case ieee_section_offset_enum:
+ (void) must_parse_int (&(ieee->h));
+ (void) must_parse_int (&(ieee->h));
+ break;
+ default:
+ return;
+ }
+ }
+ break;
+ default:
+ return;
+ }
+ }
+ }
+}
+
+/* Make a section for the debugging information, if any. We don't try
+ to interpret the debugging information; we just point the section
+ at the area in the file so that program which understand can dig it
+ out. */
+
+static boolean
+ieee_slurp_debug (abfd)
+ bfd *abfd;
+{
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ asection *sec;
+
+ if (ieee->w.r.debug_information_part == 0)
+ return true;
+
+ sec = bfd_make_section (abfd, ".debug");
+ if (sec == NULL)
+ return false;
+ sec->flags |= SEC_DEBUGGING | SEC_HAS_CONTENTS;
+ sec->filepos = ieee->w.r.debug_information_part;
+ sec->_raw_size = ieee->w.r.data_part - ieee->w.r.debug_information_part;
+
+ return true;
+}
+
+/***********************************************************************
+* archive stuff
+*/
+
+const bfd_target *
+ieee_archive_p (abfd)
+ bfd *abfd;
+{
+ char *library;
+ boolean loop;
+ unsigned int i;
+ unsigned char buffer[512];
+ file_ptr buffer_offset = 0;
+ ieee_ar_data_type *save = abfd->tdata.ieee_ar_data;
+ ieee_ar_data_type *ieee;
+ abfd->tdata.ieee_ar_data = (ieee_ar_data_type *) bfd_alloc (abfd, sizeof (ieee_ar_data_type));
+ if (!abfd->tdata.ieee_ar_data)
+ return NULL;
+ ieee = IEEE_AR_DATA (abfd);
+
+ /* FIXME: Check return value. I'm not sure whether it needs to read
+ the entire buffer or not. */
+ bfd_read ((PTR) buffer, 1, sizeof (buffer), abfd);
+
+ ieee->h.first_byte = buffer;
+ ieee->h.input_p = buffer;
+
+ ieee->h.abfd = abfd;
+
+ if (this_byte (&(ieee->h)) != Module_Beginning)
+ {
+ abfd->tdata.ieee_ar_data = save;
+ return (const bfd_target *) NULL;
+ }
+
+ next_byte (&(ieee->h));
+ library = read_id (&(ieee->h));
+ if (strcmp (library, "LIBRARY") != 0)
+ {
+ bfd_release (abfd, ieee);
+ abfd->tdata.ieee_ar_data = save;
+ return (const bfd_target *) NULL;
+ }
+ /* Throw away the filename */
+ read_id (&(ieee->h));
+
+ ieee->element_count = 0;
+ ieee->element_index = 0;
+
+ next_byte (&(ieee->h)); /* Drop the ad part */
+ must_parse_int (&(ieee->h)); /* And the two dummy numbers */
+ must_parse_int (&(ieee->h));
+
+ loop = true;
+ /* Read the index of the BB table */
+ while (loop)
+ {
+ ieee_ar_obstack_type t;
+ int rec = read_2bytes (&(ieee->h));
+ if (rec == (int) ieee_assign_value_to_variable_enum)
+ {
+ must_parse_int (&(ieee->h));
+ t.file_offset = must_parse_int (&(ieee->h));
+ t.abfd = (bfd *) NULL;
+ ieee->element_count++;
+
+ bfd_alloc_grow (abfd, (PTR) &t, sizeof t);
+
+ /* Make sure that we don't go over the end of the buffer */
+
+ if ((size_t) ieee_pos (abfd) > sizeof (buffer) / 2)
+ {
+ /* Past half way, reseek and reprime */
+ buffer_offset += ieee_pos (abfd);
+ if (bfd_seek (abfd, buffer_offset, SEEK_SET) != 0)
+ return NULL;
+ /* FIXME: Check return value. I'm not sure whether it
+ needs to read the entire buffer or not. */
+ bfd_read ((PTR) buffer, 1, sizeof (buffer), abfd);
+ ieee->h.first_byte = buffer;
+ ieee->h.input_p = buffer;
+ }
+ }
+ else
+ loop = false;
+ }
+
+ ieee->elements = (ieee_ar_obstack_type *) bfd_alloc_finish (abfd);
+ if (!ieee->elements)
+ return (const bfd_target *) NULL;
+
+ /* Now scan the area again, and replace BB offsets with file */
+ /* offsets */
+
+ for (i = 2; i < ieee->element_count; i++)
+ {
+ if (bfd_seek (abfd, ieee->elements[i].file_offset, SEEK_SET) != 0)
+ return NULL;
+ /* FIXME: Check return value. I'm not sure whether it needs to
+ read the entire buffer or not. */
+ bfd_read ((PTR) buffer, 1, sizeof (buffer), abfd);
+ ieee->h.first_byte = buffer;
+ ieee->h.input_p = buffer;
+
+ next_byte (&(ieee->h)); /* Drop F8 */
+ next_byte (&(ieee->h)); /* Drop 14 */
+ must_parse_int (&(ieee->h)); /* Drop size of block */
+ if (must_parse_int (&(ieee->h)) != 0)
+ {
+ /* This object has been deleted */
+ ieee->elements[i].file_offset = 0;
+ }
+ else
+ {
+ ieee->elements[i].file_offset = must_parse_int (&(ieee->h));
+ }
+ }
+
+/* abfd->has_armap = ;*/
+ return abfd->xvec;
+}
+
+static boolean
+ieee_mkobject (abfd)
+ bfd *abfd;
+{
+ abfd->tdata.ieee_data = (ieee_data_type *) bfd_zalloc (abfd, sizeof (ieee_data_type));
+ return abfd->tdata.ieee_data ? true : false;
+}
+
+const bfd_target *
+ieee_object_p (abfd)
+ bfd *abfd;
+{
+ char *processor;
+ unsigned int part;
+ ieee_data_type *ieee;
+ unsigned char buffer[300];
+ ieee_data_type *save = IEEE_DATA (abfd);
+
+ abfd->tdata.ieee_data = 0;
+ ieee_mkobject (abfd);
+
+ ieee = IEEE_DATA (abfd);
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ goto fail;
+ /* Read the first few bytes in to see if it makes sense */
+ /* FIXME: Check return value. I'm not sure whether it needs to read
+ the entire buffer or not. */
+ bfd_read ((PTR) buffer, 1, sizeof (buffer), abfd);
+
+ ieee->h.input_p = buffer;
+ if (this_byte_and_next (&(ieee->h)) != Module_Beginning)
+ goto got_wrong_format;
+
+ ieee->read_symbols = false;
+ ieee->read_data = false;
+ ieee->section_count = 0;
+ ieee->external_symbol_max_index = 0;
+ ieee->external_symbol_min_index = IEEE_PUBLIC_BASE;
+ ieee->external_reference_min_index = IEEE_REFERENCE_BASE;
+ ieee->external_reference_max_index = 0;
+ ieee->h.abfd = abfd;
+ memset ((PTR) ieee->section_table, 0, sizeof (ieee->section_table));
+
+ processor = ieee->mb.processor = read_id (&(ieee->h));
+ if (strcmp (processor, "LIBRARY") == 0)
+ goto got_wrong_format;
+ ieee->mb.module_name = read_id (&(ieee->h));
+ if (abfd->filename == (CONST char *) NULL)
+ {
+ abfd->filename = ieee->mb.module_name;
+ }
+ /* Determine the architecture and machine type of the object file.
+ */
+ {
+ const bfd_arch_info_type *arch = bfd_scan_arch (processor);
+ if (arch == 0)
+ goto got_wrong_format;
+ abfd->arch_info = arch;
+ }
+
+ if (this_byte (&(ieee->h)) != (int) ieee_address_descriptor_enum)
+ {
+ goto fail;
+ }
+ next_byte (&(ieee->h));
+
+ if (parse_int (&(ieee->h), &ieee->ad.number_of_bits_mau) == false)
+ {
+ goto fail;
+ }
+ if (parse_int (&(ieee->h), &ieee->ad.number_of_maus_in_address) == false)
+ {
+ goto fail;
+ }
+
+ /* If there is a byte order info, take it */
+ if (this_byte (&(ieee->h)) == (int) ieee_variable_L_enum ||
+ this_byte (&(ieee->h)) == (int) ieee_variable_M_enum)
+ next_byte (&(ieee->h));
+
+ for (part = 0; part < N_W_VARIABLES; part++)
+ {
+ boolean ok;
+ if (read_2bytes (&(ieee->h)) != (int) ieee_assign_value_to_variable_enum)
+ {
+ goto fail;
+ }
+ if (this_byte_and_next (&(ieee->h)) != part)
+ {
+ goto fail;
+ }
+
+ ieee->w.offset[part] = parse_i (&(ieee->h), &ok);
+ if (ok == false)
+ {
+ goto fail;
+ }
+
+ }
+
+ if (ieee->w.r.external_part != 0)
+ abfd->flags = HAS_SYMS;
+
+ /* By now we know that this is a real IEEE file, we're going to read
+ the whole thing into memory so that we can run up and down it
+ quickly. We can work out how big the file is from the trailer
+ record */
+
+ IEEE_DATA (abfd)->h.first_byte =
+ (unsigned char *) bfd_alloc (ieee->h.abfd, ieee->w.r.me_record + 1);
+ if (!IEEE_DATA (abfd)->h.first_byte)
+ goto fail;
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ goto fail;
+ /* FIXME: Check return value. I'm not sure whether it needs to read
+ the entire buffer or not. */
+ bfd_read ((PTR) (IEEE_DATA (abfd)->h.first_byte), 1,
+ ieee->w.r.me_record + 1, abfd);
+
+ ieee_slurp_sections (abfd);
+
+ if (! ieee_slurp_debug (abfd))
+ goto fail;
+
+ /* Parse section data to activate file and section flags implied by
+ section contents. */
+
+ if (! ieee_slurp_section_data (abfd))
+ goto fail;
+
+ return abfd->xvec;
+got_wrong_format:
+ bfd_set_error (bfd_error_wrong_format);
+fail:
+ (void) bfd_release (abfd, ieee);
+ abfd->tdata.ieee_data = save;
+ return (const bfd_target *) NULL;
+}
+
+void
+ieee_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+ if (symbol->name[0] == ' ')
+ ret->name = "* empty table entry ";
+ if (!symbol->section)
+ ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
+}
+
+void
+ieee_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;
+ case bfd_print_symbol_more:
+#if 0
+ fprintf (file, "%4x %2x", aout_symbol (symbol)->desc & 0xffff,
+ aout_symbol (symbol)->other & 0xff);
+#endif
+ BFD_FAIL ();
+ break;
+ case bfd_print_symbol_all:
+ {
+ const char *section_name =
+ (symbol->section == (asection *) NULL
+ ? "*abs"
+ : symbol->section->name);
+ if (symbol->name[0] == ' ')
+ {
+ fprintf (file, "* empty table entry ");
+ }
+ else
+ {
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+
+ fprintf (file, " %-5s %04x %02x %s",
+ section_name,
+ (unsigned) ieee_symbol (symbol)->index,
+ (unsigned) 0,
+ symbol->name);
+ }
+ }
+ break;
+ }
+}
+
+static boolean
+do_one (ieee, current_map, location_ptr, s, iterations)
+ ieee_data_type *ieee;
+ ieee_per_section_type *current_map;
+ unsigned char *location_ptr;
+ asection *s;
+ int iterations;
+{
+ switch (this_byte (&(ieee->h)))
+ {
+ case ieee_load_constant_bytes_enum:
+ {
+ unsigned int number_of_maus;
+ unsigned int i;
+ next_byte (&(ieee->h));
+ number_of_maus = must_parse_int (&(ieee->h));
+
+ for (i = 0; i < number_of_maus; i++)
+ {
+ location_ptr[current_map->pc++] = this_byte (&(ieee->h));
+ next_byte (&(ieee->h));
+ }
+ }
+ break;
+
+ case ieee_load_with_relocation_enum:
+ {
+ boolean loop = true;
+ next_byte (&(ieee->h));
+ while (loop)
+ {
+ switch (this_byte (&(ieee->h)))
+ {
+ case ieee_variable_R_enum:
+
+ case ieee_function_signed_open_b_enum:
+ case ieee_function_unsigned_open_b_enum:
+ case ieee_function_either_open_b_enum:
+ {
+ unsigned int extra = 4;
+ boolean pcrel = false;
+ asection *section;
+ ieee_reloc_type *r =
+ (ieee_reloc_type *) bfd_alloc (ieee->h.abfd,
+ sizeof (ieee_reloc_type));
+ if (!r)
+ return false;
+
+ *(current_map->reloc_tail_ptr) = r;
+ current_map->reloc_tail_ptr = &r->next;
+ r->next = (ieee_reloc_type *) NULL;
+ next_byte (&(ieee->h));
+/* abort();*/
+ r->relent.sym_ptr_ptr = 0;
+ parse_expression (ieee,
+ &r->relent.addend,
+ &r->symbol,
+ &pcrel, &extra, &section);
+ r->relent.address = current_map->pc;
+ s->flags |= SEC_RELOC;
+ s->owner->flags |= HAS_RELOC;
+ s->reloc_count++;
+ if (r->relent.sym_ptr_ptr == 0)
+ {
+ r->relent.sym_ptr_ptr = section->symbol_ptr_ptr;
+ }
+
+ if (this_byte (&(ieee->h)) == (int) ieee_comma)
+ {
+ next_byte (&(ieee->h));
+ /* Fetch number of bytes to pad */
+ extra = must_parse_int (&(ieee->h));
+ };
+
+ switch (this_byte (&(ieee->h)))
+ {
+ case ieee_function_signed_close_b_enum:
+ next_byte (&(ieee->h));
+ break;
+ case ieee_function_unsigned_close_b_enum:
+ next_byte (&(ieee->h));
+ break;
+ case ieee_function_either_close_b_enum:
+ next_byte (&(ieee->h));
+ break;
+ default:
+ break;
+ }
+ /* Build a relocation entry for this type */
+ /* If pc rel then stick -ve pc into instruction
+ and take out of reloc ..
+
+ I've changed this. It's all too complicated. I
+ keep 0 in the instruction now. */
+
+ switch (extra)
+ {
+ case 0:
+ case 4:
+
+ if (pcrel == true)
+ {
+#if KEEPMINUSPCININST
+ bfd_put_32 (ieee->h.abfd, -current_map->pc, location_ptr +
+ current_map->pc);
+ r->relent.howto = &rel32_howto;
+ r->relent.addend -=
+ current_map->pc;
+#else
+ bfd_put_32 (ieee->h.abfd, 0, location_ptr +
+ current_map->pc);
+ r->relent.howto = &rel32_howto;
+#endif
+ }
+ else
+ {
+ bfd_put_32 (ieee->h.abfd, 0, location_ptr +
+ current_map->pc);
+ r->relent.howto = &abs32_howto;
+ }
+ current_map->pc += 4;
+ break;
+ case 2:
+ if (pcrel == true)
+ {
+#if KEEPMINUSPCININST
+ bfd_put_16 (ieee->h.abfd, (int) (-current_map->pc), location_ptr + current_map->pc);
+ r->relent.addend -= current_map->pc;
+ r->relent.howto = &rel16_howto;
+#else
+
+ bfd_put_16 (ieee->h.abfd, 0, location_ptr + current_map->pc);
+ r->relent.howto = &rel16_howto;
+#endif
+ }
+
+ else
+ {
+ bfd_put_16 (ieee->h.abfd, 0, location_ptr + current_map->pc);
+ r->relent.howto = &abs16_howto;
+ }
+ current_map->pc += 2;
+ break;
+ case 1:
+ if (pcrel == true)
+ {
+#if KEEPMINUSPCININST
+ bfd_put_8 (ieee->h.abfd, (int) (-current_map->pc), location_ptr + current_map->pc);
+ r->relent.addend -= current_map->pc;
+ r->relent.howto = &rel8_howto;
+#else
+ bfd_put_8 (ieee->h.abfd, 0, location_ptr + current_map->pc);
+ r->relent.howto = &rel8_howto;
+#endif
+ }
+ else
+ {
+ bfd_put_8 (ieee->h.abfd, 0, location_ptr + current_map->pc);
+ r->relent.howto = &abs8_howto;
+ }
+ current_map->pc += 1;
+ break;
+
+ default:
+ BFD_FAIL ();
+ return false;
+ }
+ }
+ break;
+ default:
+ {
+ bfd_vma this_size;
+ if (parse_int (&(ieee->h), &this_size) == true)
+ {
+ unsigned int i;
+ for (i = 0; i < this_size; i++)
+ {
+ location_ptr[current_map->pc++] = this_byte (&(ieee->h));
+ next_byte (&(ieee->h));
+ }
+ }
+ else
+ {
+ loop = false;
+ }
+ }
+ }
+
+ /* Prevent more than the first load-item of an LR record
+ from being repeated (MRI convention). */
+ if (iterations != 1)
+ loop = false;
+ }
+ }
+ }
+ return true;
+}
+
+/* Read in all the section data and relocation stuff too */
+static boolean
+ieee_slurp_section_data (abfd)
+ bfd *abfd;
+{
+ bfd_byte *location_ptr = (bfd_byte *) NULL;
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ unsigned int section_number;
+
+ ieee_per_section_type *current_map = (ieee_per_section_type *) NULL;
+ asection *s;
+ /* Seek to the start of the data area */
+ if (ieee->read_data == true)
+ return true;
+ ieee->read_data = true;
+ ieee_seek (abfd, ieee->w.r.data_part);
+
+ /* Allocate enough space for all the section contents */
+
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ ieee_per_section_type *per = (ieee_per_section_type *) s->used_by_bfd;
+ if ((s->flags & SEC_DEBUGGING) != 0)
+ continue;
+ per->data = (bfd_byte *) bfd_alloc (ieee->h.abfd, s->_raw_size);
+ if (!per->data)
+ return false;
+ /*SUPPRESS 68*/
+ per->reloc_tail_ptr =
+ (ieee_reloc_type **) & (s->relocation);
+ }
+
+ while (true)
+ {
+ switch (this_byte (&(ieee->h)))
+ {
+ /* IF we see anything strange then quit */
+ default:
+ return true;
+
+ case ieee_set_current_section_enum:
+ next_byte (&(ieee->h));
+ section_number = must_parse_int (&(ieee->h));
+ s = ieee->section_table[section_number];
+ s->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
+ current_map = (ieee_per_section_type *) s->used_by_bfd;
+ location_ptr = current_map->data - s->vma;
+ /* The document I have says that Microtec's compilers reset */
+ /* this after a sec section, even though the standard says not */
+ /* to. SO .. */
+ current_map->pc = s->vma;
+ break;
+
+ case ieee_e2_first_byte_enum:
+ next_byte (&(ieee->h));
+ switch (this_byte (&(ieee->h)))
+ {
+ case ieee_set_current_pc_enum & 0xff:
+ {
+ bfd_vma value;
+ ieee_symbol_index_type symbol;
+ unsigned int extra;
+ boolean pcrel;
+ next_byte (&(ieee->h));
+ must_parse_int (&(ieee->h)); /* Thow away section #*/
+ parse_expression (ieee, &value,
+ &symbol,
+ &pcrel, &extra,
+ 0);
+ current_map->pc = value;
+ BFD_ASSERT ((unsigned) (value - s->vma) <= s->_raw_size);
+ }
+ break;
+
+ case ieee_value_starting_address_enum & 0xff:
+ /* We've got to the end of the data now - */
+ return true;
+ default:
+ BFD_FAIL ();
+ return false;
+ }
+ break;
+ case ieee_repeat_data_enum:
+ {
+ /* Repeat the following LD or LR n times - we do this by
+ remembering the stream pointer before running it and
+ resetting it and running it n times. We special case
+ the repetition of a repeat_data/load_constant
+ */
+
+ unsigned int iterations;
+ unsigned char *start;
+ next_byte (&(ieee->h));
+ iterations = must_parse_int (&(ieee->h));
+ start = ieee->h.input_p;
+ if (start[0] == (int) ieee_load_constant_bytes_enum &&
+ start[1] == 1)
+ {
+ while (iterations != 0)
+ {
+ location_ptr[current_map->pc++] = start[2];
+ iterations--;
+ }
+ next_byte (&(ieee->h));
+ next_byte (&(ieee->h));
+ next_byte (&(ieee->h));
+ }
+ else
+ {
+ while (iterations != 0)
+ {
+ ieee->h.input_p = start;
+ if (!do_one (ieee, current_map, location_ptr, s,
+ iterations))
+ return false;
+ iterations--;
+ }
+ }
+ }
+ break;
+ case ieee_load_constant_bytes_enum:
+ case ieee_load_with_relocation_enum:
+ {
+ if (!do_one (ieee, current_map, location_ptr, s, 1))
+ return false;
+ }
+ }
+ }
+}
+
+boolean
+ieee_new_section_hook (abfd, newsect)
+ bfd *abfd;
+ asection *newsect;
+{
+ newsect->used_by_bfd = (PTR)
+ bfd_alloc (abfd, sizeof (ieee_per_section_type));
+ if (!newsect->used_by_bfd)
+ return false;
+ ieee_per_section (newsect)->data = (bfd_byte *) NULL;
+ ieee_per_section (newsect)->section = newsect;
+ return true;
+}
+
+long
+ieee_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ if ((asect->flags & SEC_DEBUGGING) != 0)
+ return 0;
+ if (! ieee_slurp_section_data (abfd))
+ return -1;
+ return (asect->reloc_count + 1) * sizeof (arelent *);
+}
+
+static boolean
+ieee_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ ieee_per_section_type *p = (ieee_per_section_type *) section->used_by_bfd;
+ if ((section->flags & SEC_DEBUGGING) != 0)
+ return _bfd_generic_get_section_contents (abfd, section, location,
+ offset, count);
+ ieee_slurp_section_data (abfd);
+ (void) memcpy ((PTR) location, (PTR) (p->data + offset), (unsigned) count);
+ return true;
+}
+
+long
+ieee_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+/* ieee_per_section_type *p = (ieee_per_section_type *) section->used_by_bfd;*/
+ ieee_reloc_type *src = (ieee_reloc_type *) (section->relocation);
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+
+ if ((section->flags & SEC_DEBUGGING) != 0)
+ return 0;
+
+ while (src != (ieee_reloc_type *) NULL)
+ {
+ /* Work out which symbol to attach it this reloc to */
+ switch (src->symbol.letter)
+ {
+ case 'I':
+ src->relent.sym_ptr_ptr =
+ symbols + src->symbol.index + ieee->external_symbol_base_offset;
+ break;
+ case 'X':
+ src->relent.sym_ptr_ptr =
+ symbols + src->symbol.index + ieee->external_reference_base_offset;
+ break;
+ case 0:
+ src->relent.sym_ptr_ptr =
+ src->relent.sym_ptr_ptr[0]->section->symbol_ptr_ptr;
+ break;
+ default:
+
+ BFD_FAIL ();
+ }
+ *relptr++ = &src->relent;
+ src = src->next;
+ }
+ *relptr = (arelent *) NULL;
+ return section->reloc_count;
+}
+
+static int
+comp (ap, bp)
+ CONST PTR ap;
+ CONST PTR bp;
+{
+ arelent *a = *((arelent **) ap);
+ arelent *b = *((arelent **) bp);
+ return a->address - b->address;
+}
+
+/* Write the section headers. */
+
+static boolean
+ieee_write_section_part (abfd)
+ bfd *abfd;
+{
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ asection *s;
+ ieee->w.r.section_part = bfd_tell (abfd);
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ if (! bfd_is_abs_section (s)
+ && (s->flags & SEC_DEBUGGING) == 0)
+ {
+ if (! ieee_write_byte (abfd, ieee_section_type_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (s->index
+ + IEEE_SECTION_NUMBER_BASE)))
+ return false;
+
+ if (abfd->flags & EXEC_P)
+ {
+ /* This image is executable, so output absolute sections */
+ if (! ieee_write_byte (abfd, ieee_variable_A_enum)
+ || ! ieee_write_byte (abfd, ieee_variable_S_enum))
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_byte (abfd, ieee_variable_C_enum))
+ return false;
+ }
+
+ switch (s->flags & (SEC_CODE | SEC_DATA | SEC_ROM))
+ {
+ case SEC_CODE | SEC_LOAD:
+ case SEC_CODE:
+ if (! ieee_write_byte (abfd, ieee_variable_P_enum))
+ return false;
+ break;
+ case SEC_DATA:
+ default:
+ if (! ieee_write_byte (abfd, ieee_variable_D_enum))
+ return false;
+ break;
+ case SEC_ROM:
+ case SEC_ROM | SEC_DATA:
+ case SEC_ROM | SEC_LOAD:
+ case SEC_ROM | SEC_DATA | SEC_LOAD:
+ if (! ieee_write_byte (abfd, ieee_variable_R_enum))
+ return false;
+ }
+
+
+ if (! ieee_write_id (abfd, s->name))
+ return false;
+#if 0
+ ieee_write_int (abfd, 0); /* Parent */
+ ieee_write_int (abfd, 0); /* Brother */
+ ieee_write_int (abfd, 0); /* Context */
+#endif
+ /* Alignment */
+ if (! ieee_write_byte (abfd, ieee_section_alignment_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (s->index
+ + IEEE_SECTION_NUMBER_BASE))
+ || ! ieee_write_int (abfd, 1 << s->alignment_power))
+ return false;
+
+ /* Size */
+ if (! ieee_write_2bytes (abfd, ieee_section_size_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (s->index
+ + IEEE_SECTION_NUMBER_BASE))
+ || ! ieee_write_int (abfd, s->_raw_size))
+ return false;
+ if (abfd->flags & EXEC_P)
+ {
+ /* Relocateable sections don't have asl records */
+ /* Vma */
+ if (! ieee_write_2bytes (abfd, ieee_section_base_address_enum)
+ || ! ieee_write_byte (abfd,
+ ((bfd_byte)
+ (s->index
+ + IEEE_SECTION_NUMBER_BASE)))
+ || ! ieee_write_int (abfd, s->vma))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+static boolean
+do_with_relocs (abfd, s)
+ bfd *abfd;
+ asection *s;
+{
+ unsigned int number_of_maus_in_address =
+ bfd_arch_bits_per_address (abfd) / bfd_arch_bits_per_byte (abfd);
+ unsigned int relocs_to_go = s->reloc_count;
+ bfd_byte *stream = ieee_per_section (s)->data;
+ arelent **p = s->orelocation;
+ bfd_size_type current_byte_index = 0;
+
+ qsort (s->orelocation,
+ relocs_to_go,
+ sizeof (arelent **),
+ comp);
+
+ /* Output the section preheader */
+ if (! ieee_write_byte (abfd, ieee_set_current_section_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE))
+ || ! ieee_write_2bytes (abfd, ieee_set_current_pc_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (s->index + IEEE_SECTION_NUMBER_BASE)))
+ return false;
+ if ((abfd->flags & EXEC_P) != 0 && relocs_to_go == 0)
+ {
+ if (! ieee_write_int (abfd, s->vma))
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_expression (abfd, 0, s->symbol, 0, 0))
+ return false;
+ }
+
+ if (relocs_to_go == 0)
+ {
+ /* If there aren't any relocations then output the load constant
+ byte opcode rather than the load with relocation opcode */
+
+ while (current_byte_index < s->_raw_size)
+ {
+ bfd_size_type run;
+ unsigned int MAXRUN = 127;
+ run = MAXRUN;
+ if (run > s->_raw_size - current_byte_index)
+ {
+ run = s->_raw_size - current_byte_index;
+ }
+
+ if (run != 0)
+ {
+ if (! ieee_write_byte (abfd, ieee_load_constant_bytes_enum))
+ return false;
+ /* Output a stream of bytes */
+ if (! ieee_write_int (abfd, run))
+ return false;
+ if (bfd_write ((PTR) (stream + current_byte_index),
+ 1,
+ run,
+ abfd)
+ != run)
+ return false;
+ current_byte_index += run;
+ }
+ }
+ }
+ else
+ {
+ if (! ieee_write_byte (abfd, ieee_load_with_relocation_enum))
+ return false;
+
+ /* Output the data stream as the longest sequence of bytes
+ possible, allowing for the a reasonable packet size and
+ relocation stuffs. */
+
+ if ((PTR) stream == (PTR) NULL)
+ {
+ /* Outputting a section without data, fill it up */
+ stream = (unsigned char *) (bfd_alloc (abfd, s->_raw_size));
+ if (!stream)
+ return false;
+ memset ((PTR) stream, 0, (size_t) s->_raw_size);
+ }
+ while (current_byte_index < s->_raw_size)
+ {
+ bfd_size_type run;
+ unsigned int MAXRUN = 127;
+ if (relocs_to_go)
+ {
+ run = (*p)->address - current_byte_index;
+ if (run > MAXRUN)
+ run = MAXRUN;
+ }
+ else
+ {
+ run = MAXRUN;
+ }
+ if (run > s->_raw_size - current_byte_index)
+ {
+ run = s->_raw_size - current_byte_index;
+ }
+
+ if (run != 0)
+ {
+ /* Output a stream of bytes */
+ if (! ieee_write_int (abfd, run))
+ return false;
+ if (bfd_write ((PTR) (stream + current_byte_index),
+ 1,
+ run,
+ abfd)
+ != run)
+ return false;
+ current_byte_index += run;
+ }
+ /* Output any relocations here */
+ if (relocs_to_go && (*p) && (*p)->address == current_byte_index)
+ {
+ while (relocs_to_go
+ && (*p) && (*p)->address == current_byte_index)
+ {
+ arelent *r = *p;
+ bfd_signed_vma ov;
+
+#if 0
+ if (r->howto->pc_relative)
+ {
+ r->addend += current_byte_index;
+ }
+#endif
+
+ switch (r->howto->size)
+ {
+ case 2:
+
+ ov = bfd_get_signed_32 (abfd,
+ stream + current_byte_index);
+ current_byte_index += 4;
+ break;
+ case 1:
+ ov = bfd_get_signed_16 (abfd,
+ stream + current_byte_index);
+ current_byte_index += 2;
+ break;
+ case 0:
+ ov = bfd_get_signed_8 (abfd,
+ stream + current_byte_index);
+ current_byte_index++;
+ break;
+ default:
+ ov = 0;
+ BFD_FAIL ();
+ return false;
+ }
+
+ ov &= r->howto->src_mask;
+
+ if (r->howto->pc_relative
+ && ! r->howto->pcrel_offset)
+ ov += r->address;
+
+ if (! ieee_write_byte (abfd,
+ ieee_function_either_open_b_enum))
+ return false;
+
+/* abort();*/
+
+ if (r->sym_ptr_ptr != (asymbol **) NULL)
+ {
+ if (! ieee_write_expression (abfd, r->addend + ov,
+ *(r->sym_ptr_ptr),
+ r->howto->pc_relative,
+ s->index))
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_expression (abfd, r->addend + ov,
+ (asymbol *) NULL,
+ r->howto->pc_relative,
+ s->index))
+ return false;
+ }
+
+ if (number_of_maus_in_address
+ != bfd_get_reloc_size (r->howto))
+ {
+ if (! ieee_write_int (abfd,
+ bfd_get_reloc_size (r->howto)))
+ return false;
+ }
+ if (! ieee_write_byte (abfd,
+ ieee_function_either_close_b_enum))
+ return false;
+
+ relocs_to_go--;
+ p++;
+ }
+
+ }
+ }
+ }
+
+ return true;
+}
+
+/* If there are no relocations in the output section then we can be
+ clever about how we write. We block items up into a max of 127
+ bytes. */
+
+static boolean
+do_as_repeat (abfd, s)
+ bfd *abfd;
+ asection *s;
+{
+ if (s->_raw_size)
+ {
+ if (! ieee_write_byte (abfd, ieee_set_current_section_enum)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (s->index
+ + IEEE_SECTION_NUMBER_BASE))
+ || ! ieee_write_byte (abfd, ieee_set_current_pc_enum >> 8)
+ || ! ieee_write_byte (abfd, ieee_set_current_pc_enum & 0xff)
+ || ! ieee_write_byte (abfd,
+ (bfd_byte) (s->index
+ + IEEE_SECTION_NUMBER_BASE))
+ || ! ieee_write_int (abfd, s->vma)
+ || ! ieee_write_byte (abfd, ieee_repeat_data_enum)
+ || ! ieee_write_int (abfd, s->_raw_size)
+ || ! ieee_write_byte (abfd, ieee_load_constant_bytes_enum)
+ || ! ieee_write_byte (abfd, 1)
+ || ! ieee_write_byte (abfd, 0))
+ return false;
+ }
+
+ return true;
+}
+
+static boolean
+do_without_relocs (abfd, s)
+ bfd *abfd;
+ asection *s;
+{
+ bfd_byte *stream = ieee_per_section (s)->data;
+
+ if (stream == 0 || ((s->flags & SEC_LOAD) == 0))
+ {
+ if (! do_as_repeat (abfd, s))
+ return false;
+ }
+ else
+ {
+ unsigned int i;
+ for (i = 0; i < s->_raw_size; i++)
+ {
+ if (stream[i] != 0)
+ {
+ if (! do_with_relocs (abfd, s))
+ return false;
+ return true;
+ }
+ }
+ if (! do_as_repeat (abfd, s))
+ return false;
+ }
+
+ return true;
+}
+
+
+static unsigned char *output_ptr_start;
+static unsigned char *output_ptr;
+static unsigned char *output_ptr_end;
+static unsigned char *input_ptr_start;
+static unsigned char *input_ptr;
+static unsigned char *input_ptr_end;
+static bfd *input_bfd;
+static bfd *output_bfd;
+static int output_buffer;
+
+static void
+fill ()
+{
+ /* FIXME: Check return value. I'm not sure whether it needs to read
+ the entire buffer or not. */
+ bfd_read ((PTR) input_ptr_start, 1, input_ptr_end - input_ptr_start, input_bfd);
+ input_ptr = input_ptr_start;
+}
+static void
+flush ()
+{
+ if (bfd_write ((PTR) (output_ptr_start), 1, output_ptr - output_ptr_start,
+ output_bfd)
+ != (bfd_size_type) (output_ptr - output_ptr_start))
+ abort ();
+ output_ptr = output_ptr_start;
+ output_buffer++;
+}
+
+#define THIS() ( *input_ptr )
+#define NEXT() { input_ptr++; if (input_ptr == input_ptr_end) fill(); }
+#define OUT(x) { *output_ptr++ = (x); if(output_ptr == output_ptr_end) flush(); }
+
+static void
+write_int (value)
+ int value;
+{
+ if (value >= 0 && value <= 127)
+ {
+ OUT (value);
+ }
+ else
+ {
+ unsigned int length;
+ /* How many significant bytes ? */
+ /* FIXME FOR LONGER INTS */
+ if (value & 0xff000000)
+ {
+ length = 4;
+ }
+ else if (value & 0x00ff0000)
+ {
+ length = 3;
+ }
+ else if (value & 0x0000ff00)
+ {
+ length = 2;
+ }
+ else
+ length = 1;
+
+ OUT ((int) ieee_number_repeat_start_enum + length);
+ switch (length)
+ {
+ case 4:
+ OUT (value >> 24);
+ case 3:
+ OUT (value >> 16);
+ case 2:
+ OUT (value >> 8);
+ case 1:
+ OUT (value);
+ }
+
+ }
+}
+
+static void
+copy_id ()
+{
+ int length = THIS ();
+ char ch;
+ OUT (length);
+ NEXT ();
+ while (length--)
+ {
+ ch = THIS ();
+ OUT (ch);
+ NEXT ();
+ }
+}
+
+#define VAR(x) ((x | 0x80))
+static void
+copy_expression ()
+{
+ int stack[10];
+ int *tos = stack;
+ int value = 0;
+ while (1)
+ {
+ switch (THIS ())
+ {
+ case 0x84:
+ NEXT ();
+ value = THIS ();
+ NEXT ();
+ value = (value << 8) | THIS ();
+ NEXT ();
+ value = (value << 8) | THIS ();
+ NEXT ();
+ value = (value << 8) | THIS ();
+ NEXT ();
+ *tos++ = value;
+ break;
+ case 0x83:
+ NEXT ();
+ value = THIS ();
+ NEXT ();
+ value = (value << 8) | THIS ();
+ NEXT ();
+ value = (value << 8) | THIS ();
+ NEXT ();
+ *tos++ = value;
+ break;
+ case 0x82:
+ NEXT ();
+ value = THIS ();
+ NEXT ();
+ value = (value << 8) | THIS ();
+ NEXT ();
+ *tos++ = value;
+ break;
+ case 0x81:
+ NEXT ();
+ value = THIS ();
+ NEXT ();
+ *tos++ = value;
+ break;
+ case 0x80:
+ NEXT ();
+ *tos++ = 0;
+ break;
+ default:
+ if (THIS () > 0x84)
+ {
+ /* Not a number, just bug out with the answer */
+ write_int (*(--tos));
+ return;
+ }
+ *tos++ = THIS ();
+ NEXT ();
+ value = 0;
+ break;
+ case 0xa5:
+ /* PLUS anything */
+ {
+ int value = *(--tos);
+ value += *(--tos);
+ *tos++ = value;
+ NEXT ();
+ }
+ break;
+ case VAR ('R'):
+ {
+ int section_number;
+ ieee_data_type *ieee;
+ asection *s;
+ NEXT ();
+ section_number = THIS ();
+
+ NEXT ();
+ ieee = IEEE_DATA (input_bfd);
+ s = ieee->section_table[section_number];
+ if (s->output_section)
+ {
+ value = s->output_section->vma;
+ }
+ else
+ {
+ value = 0;
+ }
+ value += s->output_offset;
+ *tos++ = value;
+ value = 0;
+ }
+ break;
+ case 0x90:
+ {
+ NEXT ();
+ write_int (*(--tos));
+ OUT (0x90);
+ return;
+
+ }
+ }
+ }
+
+}
+
+/* Drop the int in the buffer, and copy a null into the gap, which we
+ will overwrite later */
+
+struct output_buffer_struct
+{
+ unsigned char *ptrp;
+ int buffer;
+};
+
+static void
+fill_int (buf)
+ struct output_buffer_struct *buf;
+{
+ if (buf->buffer == output_buffer)
+ {
+ /* Still a chance to output the size */
+ int value = output_ptr - buf->ptrp + 3;
+ buf->ptrp[0] = value >> 24;
+ buf->ptrp[1] = value >> 16;
+ buf->ptrp[2] = value >> 8;
+ buf->ptrp[3] = value >> 0;
+ }
+}
+
+static void
+drop_int (buf)
+ struct output_buffer_struct *buf;
+{
+ int type = THIS ();
+ int ch;
+ if (type <= 0x84)
+ {
+ NEXT ();
+ switch (type)
+ {
+ case 0x84:
+ ch = THIS ();
+ NEXT ();
+ case 0x83:
+ ch = THIS ();
+ NEXT ();
+ case 0x82:
+ ch = THIS ();
+ NEXT ();
+ case 0x81:
+ ch = THIS ();
+ NEXT ();
+ case 0x80:
+ break;
+ }
+ }
+ OUT (0x84);
+ buf->ptrp = output_ptr;
+ buf->buffer = output_buffer;
+ OUT (0);
+ OUT (0);
+ OUT (0);
+ OUT (0);
+}
+
+static void
+copy_int ()
+{
+ int type = THIS ();
+ int ch;
+ if (type <= 0x84)
+ {
+ OUT (type);
+ NEXT ();
+ switch (type)
+ {
+ case 0x84:
+ ch = THIS ();
+ NEXT ();
+ OUT (ch);
+ case 0x83:
+ ch = THIS ();
+ NEXT ();
+ OUT (ch);
+ case 0x82:
+ ch = THIS ();
+ NEXT ();
+ OUT (ch);
+ case 0x81:
+ ch = THIS ();
+ NEXT ();
+ OUT (ch);
+ case 0x80:
+ break;
+ }
+ }
+}
+
+#define ID copy_id()
+#define INT copy_int()
+#define EXP copy_expression()
+static void copy_till_end ();
+#define INTn(q) copy_int()
+#define EXPn(q) copy_expression()
+
+static void
+f1_record ()
+{
+ int ch;
+ /* ATN record */
+ NEXT ();
+ ch = THIS ();
+ switch (ch)
+ {
+ default:
+ OUT (0xf1);
+ OUT (ch);
+ break;
+ case 0xc9:
+ NEXT ();
+ OUT (0xf1);
+ OUT (0xc9);
+ INT;
+ INT;
+ ch = THIS ();
+ switch (ch)
+ {
+ case 0x16:
+ NEXT ();
+ break;
+ case 0x01:
+ NEXT ();
+ break;
+ case 0x00:
+ NEXT ();
+ INT;
+ break;
+ case 0x03:
+ NEXT ();
+ INT;
+ break;
+ case 0x13:
+ EXPn (instruction address);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0xd8:
+ /* EXternal ref */
+ NEXT ();
+ OUT (0xf1);
+ OUT (0xd8);
+ EXP;
+ EXP;
+ EXP;
+ EXP;
+ break;
+ case 0xce:
+ NEXT ();
+ OUT (0xf1);
+ OUT (0xce);
+ INT;
+ INT;
+ ch = THIS ();
+ INT;
+ switch (ch)
+ {
+ case 0x01:
+ INT;
+ INT;
+ break;
+ case 0x02:
+ INT;
+ break;
+ case 0x04:
+ EXPn (external function);
+ break;
+ case 0x05:
+ break;
+ case 0x07:
+ INTn (line number);
+ INT;
+ case 0x08:
+ break;
+ case 0x0a:
+ INTn (locked register);
+ INT;
+ break;
+ case 0x3f:
+ copy_till_end ();
+ break;
+ case 0x3e:
+ copy_till_end ();
+ break;
+ case 0x40:
+ copy_till_end ();
+ break;
+ case 0x41:
+ ID;
+ break;
+ }
+ }
+
+}
+
+static void
+f0_record ()
+{
+ /* Attribute record */
+ NEXT ();
+ OUT (0xf0);
+ INTn (Symbol name);
+ ID;
+}
+
+static void
+copy_till_end ()
+{
+ int ch = THIS ();
+ while (1)
+ {
+ while (ch <= 0x80)
+ {
+ OUT (ch);
+ NEXT ();
+ ch = THIS ();
+ }
+ switch (ch)
+ {
+ case 0x84:
+ OUT (THIS ());
+ NEXT ();
+ case 0x83:
+ OUT (THIS ());
+ NEXT ();
+ case 0x82:
+ OUT (THIS ());
+ NEXT ();
+ case 0x81:
+ OUT (THIS ());
+ NEXT ();
+ OUT (THIS ());
+ NEXT ();
+
+ ch = THIS ();
+ break;
+ default:
+ return;
+ }
+ }
+
+}
+
+static void
+f2_record ()
+{
+ NEXT ();
+ OUT (0xf2);
+ INT;
+ NEXT ();
+ OUT (0xce);
+ INT;
+ copy_till_end ();
+}
+
+
+static void block ();
+static void
+f8_record ()
+{
+ int ch;
+ NEXT ();
+ ch = THIS ();
+ switch (ch)
+ {
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ /* Unique typedefs for module */
+ /* GLobal typedefs */
+ /* High level module scope beginning */
+ {
+ struct output_buffer_struct ob;
+ NEXT ();
+ OUT (0xf8);
+ OUT (ch);
+ drop_int (&ob);
+ ID;
+
+ block ();
+
+ NEXT ();
+ fill_int (&ob);
+ OUT (0xf9);
+ }
+ break;
+ case 0x04:
+ /* Global function */
+ {
+ struct output_buffer_struct ob;
+ NEXT ();
+ OUT (0xf8);
+ OUT (0x04);
+ drop_int (&ob);
+ ID;
+ INTn (stack size);
+ INTn (ret val);
+ EXPn (offset);
+
+ block ();
+
+ NEXT ();
+ OUT (0xf9);
+ EXPn (size of block);
+ fill_int (&ob);
+ }
+ break;
+
+ case 0x05:
+ /* File name for source line numbers */
+ {
+ struct output_buffer_struct ob;
+ NEXT ();
+ OUT (0xf8);
+ OUT (0x05);
+ drop_int (&ob);
+ ID;
+ INTn (year);
+ INTn (month);
+ INTn (day);
+ INTn (hour);
+ INTn (monute);
+ INTn (second);
+ block ();
+ NEXT ();
+ OUT (0xf9);
+ fill_int (&ob);
+ }
+ break;
+
+ case 0x06:
+ /* Local function */
+ {
+ struct output_buffer_struct ob;
+ NEXT ();
+ OUT (0xf8);
+ OUT (0x06);
+ drop_int (&ob);
+ ID;
+ INTn (stack size);
+ INTn (type return);
+ EXPn (offset);
+ block ();
+ NEXT ();
+ OUT (0xf9);
+ EXPn (size);
+ fill_int (&ob);
+ }
+ break;
+
+ case 0x0a:
+ /* Assembler module scope beginning -*/
+ {
+ struct output_buffer_struct ob;
+
+ NEXT ();
+ OUT (0xf8);
+ OUT (0x0a);
+ drop_int (&ob);
+ ID;
+ ID;
+ INT;
+ ID;
+ INT;
+ INT;
+ INT;
+ INT;
+ INT;
+ INT;
+
+ block ();
+
+ NEXT ();
+ OUT (0xf9);
+ fill_int (&ob);
+ }
+ break;
+ case 0x0b:
+ {
+ struct output_buffer_struct ob;
+ NEXT ();
+ OUT (0xf8);
+ OUT (0x0b);
+ drop_int (&ob);
+ ID;
+ INT;
+ INTn (section index);
+ EXPn (offset);
+ INTn (stuff);
+
+ block ();
+
+ OUT (0xf9);
+ NEXT ();
+ EXPn (Size in Maus);
+ fill_int (&ob);
+ }
+ break;
+ }
+}
+
+static void
+e2_record ()
+{
+ OUT (0xe2);
+ NEXT ();
+ OUT (0xce);
+ NEXT ();
+ INT;
+ EXP;
+}
+
+static void
+block ()
+{
+ int ch;
+ while (1)
+ {
+ ch = THIS ();
+ switch (ch)
+ {
+ case 0xe1:
+ case 0xe5:
+ return;
+ case 0xf9:
+ return;
+ case 0xf0:
+ f0_record ();
+ break;
+ case 0xf1:
+ f1_record ();
+ break;
+ case 0xf2:
+ f2_record ();
+ break;
+ case 0xf8:
+ f8_record ();
+ break;
+ case 0xe2:
+ e2_record ();
+ break;
+
+ }
+ }
+}
+
+
+
+/* relocate_debug,
+ moves all the debug information from the source bfd to the output
+ bfd, and relocates any expressions it finds
+*/
+
+static void
+relocate_debug (output, input)
+ bfd *output;
+ bfd *input;
+{
+#define IBS 400
+#define OBS 400
+ unsigned char input_buffer[IBS];
+
+ input_ptr_start = input_ptr = input_buffer;
+ input_ptr_end = input_buffer + IBS;
+ input_bfd = input;
+ /* FIXME: Check return value. I'm not sure whether it needs to read
+ the entire buffer or not. */
+ bfd_read ((PTR) input_ptr_start, 1, IBS, input);
+ block ();
+}
+
+/*
+ During linking, we we told about the bfds which made up our
+ contents, we have a list of them. They will still be open, so go to
+ the debug info in each, and copy it out, relocating it as we go.
+*/
+
+static boolean
+ieee_write_debug_part (abfd)
+ bfd *abfd;
+{
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ bfd_chain_type *chain = ieee->chain_root;
+ unsigned char output_buffer[OBS];
+ boolean some_debug = false;
+ file_ptr here = bfd_tell (abfd);
+
+ output_ptr_start = output_ptr = output_buffer;
+ output_ptr_end = output_buffer + OBS;
+ output_ptr = output_buffer;
+ output_bfd = abfd;
+
+ if (chain == (bfd_chain_type *) NULL)
+ {
+ asection *s;
+
+ for (s = abfd->sections; s != NULL; s = s->next)
+ if ((s->flags & SEC_DEBUGGING) != 0)
+ break;
+ if (s == NULL)
+ {
+ ieee->w.r.debug_information_part = 0;
+ return true;
+ }
+
+ ieee->w.r.debug_information_part = here;
+ if (bfd_write (s->contents, 1, s->_raw_size, abfd) != s->_raw_size)
+ return false;
+ }
+ else
+ {
+ while (chain != (bfd_chain_type *) NULL)
+ {
+ bfd *entry = chain->this;
+ ieee_data_type *entry_ieee = IEEE_DATA (entry);
+ if (entry_ieee->w.r.debug_information_part)
+ {
+ if (bfd_seek (entry, entry_ieee->w.r.debug_information_part,
+ SEEK_SET)
+ != 0)
+ return false;
+ relocate_debug (abfd, entry);
+ }
+
+ chain = chain->next;
+ }
+ if (some_debug)
+ {
+ ieee->w.r.debug_information_part = here;
+ }
+ else
+ {
+ ieee->w.r.debug_information_part = 0;
+ }
+
+ flush ();
+ }
+
+ return true;
+}
+
+/* Write the data in an ieee way. */
+
+static boolean
+ieee_write_data_part (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ ieee->w.r.data_part = bfd_tell (abfd);
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ /* Skip sections that have no loadable contents (.bss,
+ debugging, etc.) */
+ if ((s->flags & SEC_LOAD) == 0)
+ continue;
+
+ /* Sort the reloc records so we can insert them in the correct
+ places */
+ if (s->reloc_count != 0)
+ {
+ if (! do_with_relocs (abfd, s))
+ return false;
+ }
+ else
+ {
+ if (! do_without_relocs (abfd, s))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+static boolean
+init_for_output (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ if ((s->flags & SEC_DEBUGGING) != 0)
+ continue;
+ if (s->_raw_size != 0)
+ {
+ ieee_per_section (s)->data = (bfd_byte *) (bfd_alloc (abfd, s->_raw_size));
+ if (!ieee_per_section (s)->data)
+ return false;
+ }
+ }
+ return true;
+}
+
+/** exec and core file sections */
+
+/* set section contents is complicated with IEEE since the format is
+* not a byte image, but a record stream.
+*/
+boolean
+ieee_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if ((section->flags & SEC_DEBUGGING) != 0)
+ {
+ if (section->contents == NULL)
+ {
+ section->contents = bfd_alloc (abfd, section->_raw_size);
+ if (section->contents == NULL)
+ return false;
+ }
+ /* bfd_set_section_contents has already checked that everything
+ is within range. */
+ memcpy (section->contents + offset, location, count);
+ return true;
+ }
+
+ if (ieee_per_section (section)->data == (bfd_byte *) NULL)
+ {
+ if (!init_for_output (abfd))
+ return false;
+ }
+ memcpy ((PTR) (ieee_per_section (section)->data + offset),
+ (PTR) location,
+ (unsigned int) count);
+ return true;
+}
+
+/* Write the external symbols of a file. IEEE considers two sorts of
+ external symbols, public, and referenced. It uses to internal
+ forms to index them as well. When we write them out we turn their
+ symbol values into indexes from the right base. */
+
+static boolean
+ieee_write_external_part (abfd)
+ bfd *abfd;
+{
+ asymbol **q;
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+
+ unsigned int reference_index = IEEE_REFERENCE_BASE;
+ unsigned int public_index = IEEE_PUBLIC_BASE + 2;
+ file_ptr here = bfd_tell (abfd);
+ boolean hadone = false;
+ if (abfd->outsymbols != (asymbol **) NULL)
+ {
+
+ for (q = abfd->outsymbols; *q != (asymbol *) NULL; q++)
+ {
+ asymbol *p = *q;
+ hadone = true;
+ if (bfd_is_und_section (p->section))
+ {
+ /* This must be a symbol reference .. */
+ if (! ieee_write_byte (abfd, ieee_external_reference_enum)
+ || ! ieee_write_int (abfd, reference_index)
+ || ! ieee_write_id (abfd, p->name))
+ return false;
+ p->value = reference_index;
+ reference_index++;
+ }
+ else if (bfd_is_com_section (p->section))
+ {
+ /* This is a weak reference */
+ if (! ieee_write_byte (abfd, ieee_external_reference_enum)
+ || ! ieee_write_int (abfd, reference_index)
+ || ! ieee_write_id (abfd, p->name)
+ || ! ieee_write_byte (abfd,
+ ieee_weak_external_reference_enum)
+ || ! ieee_write_int (abfd, reference_index)
+ || ! ieee_write_int (abfd, p->value))
+ return false;
+ p->value = reference_index;
+ reference_index++;
+ }
+ else if (p->flags & BSF_GLOBAL)
+ {
+ /* This must be a symbol definition */
+
+ if (! ieee_write_byte (abfd, ieee_external_symbol_enum)
+ || ! ieee_write_int (abfd, public_index)
+ || ! ieee_write_id (abfd, p->name)
+ || ! ieee_write_2bytes (abfd, ieee_attribute_record_enum)
+ || ! ieee_write_int (abfd, public_index)
+ || ! ieee_write_byte (abfd, 15) /* instruction address */
+ || ! ieee_write_byte (abfd, 19) /* static symbol */
+ || ! ieee_write_byte (abfd, 1)) /* one of them */
+ return false;
+
+ /* Write out the value */
+ if (! ieee_write_2bytes (abfd, ieee_value_record_enum)
+ || ! ieee_write_int (abfd, public_index))
+ return false;
+ if (! bfd_is_abs_section (p->section))
+ {
+ if (abfd->flags & EXEC_P)
+ {
+ /* If fully linked, then output all symbols
+ relocated */
+ if (! (ieee_write_int
+ (abfd,
+ (p->value
+ + p->section->output_offset
+ + p->section->output_section->vma))))
+ return false;
+ }
+ else
+ {
+ if (! (ieee_write_expression
+ (abfd,
+ p->value + p->section->output_offset,
+ p->section->output_section->symbol,
+ false, 0)))
+ return false;
+ }
+ }
+ else
+ {
+ if (! ieee_write_expression (abfd,
+ p->value,
+ bfd_abs_section_ptr->symbol,
+ false, 0))
+ return false;
+ }
+ p->value = public_index;
+ public_index++;
+ }
+ else
+ {
+ /* This can happen - when there are gaps in the symbols read */
+ /* from an input ieee file */
+ }
+ }
+ }
+ if (hadone)
+ ieee->w.r.external_part = here;
+
+ return true;
+}
+
+
+static CONST unsigned char exten[] =
+{
+ 0xf0, 0x20, 0x00,
+ 0xf1, 0xce, 0x20, 0x00, 37, 3, 3, /* Set version 3 rev 3 */
+ 0xf1, 0xce, 0x20, 0x00, 39, 2,/* keep symbol in original case */
+ 0xf1, 0xce, 0x20, 0x00, 38 /* set object type relocateable to x */
+};
+
+static CONST unsigned char envi[] =
+{
+ 0xf0, 0x21, 0x00,
+
+/* 0xf1, 0xce, 0x21, 00, 50, 0x82, 0x07, 0xc7, 0x09, 0x11, 0x11,
+ 0x19, 0x2c,
+*/
+ 0xf1, 0xce, 0x21, 00, 52, 0x00, /* exec ok */
+
+ 0xf1, 0xce, 0x21, 0, 53, 0x03,/* host unix */
+/* 0xf1, 0xce, 0x21, 0, 54, 2,1,1 tool & version # */
+};
+
+static boolean
+ieee_write_me_part (abfd)
+ bfd *abfd;
+{
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ ieee->w.r.trailer_part = bfd_tell (abfd);
+ if (abfd->start_address)
+ {
+ if (! ieee_write_2bytes (abfd, ieee_value_starting_address_enum)
+ || ! ieee_write_byte (abfd, ieee_function_either_open_b_enum)
+ || ! ieee_write_int (abfd, abfd->start_address)
+ || ! ieee_write_byte (abfd, ieee_function_either_close_b_enum))
+ return false;
+ }
+ ieee->w.r.me_record = bfd_tell (abfd);
+ if (! ieee_write_byte (abfd, ieee_module_end_enum))
+ return false;
+ return true;
+}
+
+/* Write out the IEEE processor ID. */
+
+static boolean
+ieee_write_processor (abfd)
+ bfd *abfd;
+{
+ const bfd_arch_info_type *arch;
+
+ arch = bfd_get_arch_info (abfd);
+ switch (arch->arch)
+ {
+ default:
+ if (! ieee_write_id (abfd, bfd_printable_name (abfd)))
+ return false;
+ break;
+
+ case bfd_arch_a29k:
+ if (! ieee_write_id (abfd, "29000"))
+ return false;
+ break;
+
+ case bfd_arch_h8300:
+ if (! ieee_write_id (abfd, "H8/300"))
+ return false;
+ break;
+
+ case bfd_arch_h8500:
+ if (! ieee_write_id (abfd, "H8/500"))
+ return false;
+ break;
+
+ case bfd_arch_i960:
+ switch (arch->mach)
+ {
+ default:
+ case bfd_mach_i960_core:
+ case bfd_mach_i960_ka_sa:
+ if (! ieee_write_id (abfd, "80960KA"))
+ return false;
+ break;
+
+ case bfd_mach_i960_kb_sb:
+ if (! ieee_write_id (abfd, "80960KB"))
+ return false;
+ break;
+
+ case bfd_mach_i960_ca:
+ if (! ieee_write_id (abfd, "80960CA"))
+ return false;
+ break;
+
+ case bfd_mach_i960_mc:
+ case bfd_mach_i960_xa:
+ if (! ieee_write_id (abfd, "80960MC"))
+ return false;
+ break;
+ }
+ break;
+
+ case bfd_arch_m68k:
+ {
+ char ab[20];
+
+ sprintf (ab, "%lu", arch->mach);
+ if (! ieee_write_id (abfd, ab))
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
+boolean
+ieee_write_object_contents (abfd)
+ bfd *abfd;
+{
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+ unsigned int i;
+ file_ptr old;
+
+ /* Fast forward over the header area */
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ return false;
+
+ if (! ieee_write_byte (abfd, ieee_module_beginning_enum)
+ || ! ieee_write_processor (abfd)
+ || ! ieee_write_id (abfd, abfd->filename))
+ return false;
+
+ /* Fast forward over the variable bits */
+ if (! ieee_write_byte (abfd, ieee_address_descriptor_enum))
+ return false;
+
+ /* Bits per MAU */
+ if (! ieee_write_byte (abfd, (bfd_byte) (bfd_arch_bits_per_byte (abfd))))
+ return false;
+ /* MAU's per address */
+ if (! ieee_write_byte (abfd,
+ (bfd_byte) (bfd_arch_bits_per_address (abfd)
+ / bfd_arch_bits_per_byte (abfd))))
+ return false;
+
+ old = bfd_tell (abfd);
+ if (bfd_seek (abfd, (file_ptr) (8 * N_W_VARIABLES), SEEK_CUR) != 0)
+ return false;
+
+ ieee->w.r.extension_record = bfd_tell (abfd);
+ if (bfd_write ((char *) exten, 1, sizeof (exten), abfd) != sizeof (exten))
+ return false;
+ if (abfd->flags & EXEC_P)
+ {
+ if (! ieee_write_byte (abfd, 0x1)) /* Absolute */
+ return false;
+ }
+ else
+ {
+ if (! ieee_write_byte (abfd, 0x2)) /* Relocateable */
+ return false;
+ }
+
+ ieee->w.r.environmental_record = bfd_tell (abfd);
+ if (bfd_write ((char *) envi, 1, sizeof (envi), abfd) != sizeof (envi))
+ return false;
+ output_bfd = abfd;
+
+ flush ();
+
+ if (! ieee_write_section_part (abfd))
+ return false;
+ /* First write the symbols. This changes their values into table
+ indeces so we cant use it after this point. */
+ if (! ieee_write_external_part (abfd))
+ return false;
+
+ /* ieee_write_byte(abfd, ieee_record_seperator_enum);*/
+
+ /* ieee_write_byte(abfd, ieee_record_seperator_enum);*/
+
+
+ /* Write any debugs we have been told about. */
+ if (! ieee_write_debug_part (abfd))
+ return false;
+
+ /* Can only write the data once the symbols have been written, since
+ the data contains relocation information which points to the
+ symbols. */
+ if (! ieee_write_data_part (abfd))
+ return false;
+
+ /* At the end we put the end! */
+ if (! ieee_write_me_part (abfd))
+ return false;
+
+ /* Generate the header */
+ if (bfd_seek (abfd, old, SEEK_SET) != 0)
+ return false;
+
+ for (i = 0; i < N_W_VARIABLES; i++)
+ {
+ if (! ieee_write_2bytes (abfd, ieee_assign_value_to_variable_enum)
+ || ! ieee_write_byte (abfd, (bfd_byte) i)
+ || ! ieee_write_int5_out (abfd, ieee->w.offset[i]))
+ return false;
+ }
+
+ 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 *
+ieee_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ ieee_symbol_type *new =
+ (ieee_symbol_type *) bfd_zmalloc (sizeof (ieee_symbol_type));
+ if (!new)
+ return NULL;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+static bfd *
+ieee_openr_next_archived_file (arch, prev)
+ bfd *arch;
+ bfd *prev;
+{
+ ieee_ar_data_type *ar = IEEE_AR_DATA (arch);
+ /* take the next one from the arch state, or reset */
+ if (prev == (bfd *) NULL)
+ {
+ /* Reset the index - the first two entries are bogus*/
+ ar->element_index = 2;
+ }
+ while (true)
+ {
+ ieee_ar_obstack_type *p = ar->elements + ar->element_index;
+ ar->element_index++;
+ if (ar->element_index <= ar->element_count)
+ {
+ if (p->file_offset != (file_ptr) 0)
+ {
+ if (p->abfd == (bfd *) NULL)
+ {
+ p->abfd = _bfd_create_empty_archive_element_shell (arch);
+ p->abfd->origin = p->file_offset;
+ }
+ return p->abfd;
+ }
+ }
+ else
+ {
+ bfd_set_error (bfd_error_no_more_archived_files);
+ return (bfd *) NULL;
+ }
+
+ }
+}
+
+static boolean
+ieee_find_nearest_line (abfd,
+ section,
+ symbols,
+ offset,
+ filename_ptr,
+ functionname_ptr,
+ line_ptr)
+ bfd *abfd;
+ asection *section;
+ asymbol **symbols;
+ bfd_vma offset;
+ char **filename_ptr;
+ char **functionname_ptr;
+ int *line_ptr;
+{
+ return false;
+}
+
+static int
+ieee_generic_stat_arch_elt (abfd, buf)
+ bfd *abfd;
+ struct stat *buf;
+{
+ ieee_ar_data_type *ar = abfd->my_archive->tdata.ieee_ar_data;
+ if (ar == (ieee_ar_data_type *) NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+ else if (ieee_object_p (abfd))
+ {
+ ieee_data_type *ieee = IEEE_DATA (abfd);
+
+ buf->st_size = ieee->w.r.me_record + 1;
+ buf->st_mode = 0644;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+static int
+ieee_sizeof_headers (abfd, x)
+ bfd *abfd;
+ boolean x;
+{
+ return 0;
+}
+
+
+/* The debug info routines are never used. */
+#if 0
+
+static void
+ieee_bfd_debug_info_start (abfd)
+ bfd *abfd;
+{
+
+}
+
+static void
+ieee_bfd_debug_info_end (abfd)
+ bfd *abfd;
+{
+
+}
+
+
+/* Add this section to the list of sections we have debug info for, to
+ be ready to output it at close time
+ */
+static void
+ieee_bfd_debug_info_accumulate (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ ieee_data_type *ieee = IEEE_DATA (section->owner);
+ ieee_data_type *output_ieee = IEEE_DATA (abfd);
+ /* can only accumulate data from other ieee bfds */
+ if (section->owner->xvec != abfd->xvec)
+ return;
+ /* Only bother once per bfd */
+ if (ieee->done_debug == true)
+ return;
+ ieee->done_debug = true;
+
+ /* Don't bother if there is no debug info */
+ if (ieee->w.r.debug_information_part == 0)
+ return;
+
+
+ /* Add to chain */
+ {
+ bfd_chain_type *n = (bfd_chain_type *) bfd_alloc (abfd, sizeof (bfd_chain_type));
+ if (!n)
+ abort (); /* FIXME */
+ n->this = section->owner;
+ n->next = (bfd_chain_type *) NULL;
+
+ if (output_ieee->chain_head)
+ {
+ output_ieee->chain_head->next = n;
+ }
+ else
+ {
+ output_ieee->chain_root = n;
+
+ }
+ output_ieee->chain_head = n;
+ }
+}
+
+#endif
+
+#define ieee_close_and_cleanup _bfd_generic_close_and_cleanup
+#define ieee_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+
+#define ieee_slurp_armap bfd_true
+#define ieee_slurp_extended_name_table bfd_true
+#define ieee_construct_extended_name_table \
+ ((boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
+ bfd_true)
+#define ieee_truncate_arname bfd_dont_truncate_arname
+#define ieee_write_armap \
+ ((boolean (*) \
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \
+ bfd_true)
+#define ieee_read_ar_hdr bfd_nullvoidptr
+#define ieee_update_armap_timestamp bfd_true
+#define ieee_get_elt_at_index _bfd_generic_get_elt_at_index
+
+#define ieee_bfd_is_local_label bfd_generic_is_local_label
+#define ieee_get_lineno _bfd_nosymbols_get_lineno
+#define ieee_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define ieee_read_minisymbols _bfd_generic_read_minisymbols
+#define ieee_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define ieee_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define ieee_set_arch_mach _bfd_generic_set_arch_mach
+
+#define ieee_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+#define ieee_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define ieee_bfd_relax_section bfd_generic_relax_section
+#define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define ieee_bfd_final_link _bfd_generic_final_link
+#define ieee_bfd_link_split_section _bfd_generic_link_split_section
+
+/*SUPPRESS 460 */
+const bfd_target ieee_vec =
+{
+ "ieee", /* name */
+ bfd_target_ieee_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* 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 */
+ 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,
+ ieee_object_p, /* bfd_check_format */
+ ieee_archive_p,
+ _bfd_dummy_target,
+ },
+ {
+ bfd_false,
+ ieee_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+ {
+ bfd_false,
+ ieee_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (ieee),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (ieee),
+ BFD_JUMP_TABLE_SYMBOLS (ieee),
+ BFD_JUMP_TABLE_RELOCS (ieee),
+ BFD_JUMP_TABLE_WRITE (ieee),
+ BFD_JUMP_TABLE_LINK (ieee),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/ihex.c b/contrib/gdb/bfd/ihex.c
new file mode 100644
index 0000000..80140da
--- /dev/null
+++ b/contrib/gdb/bfd/ihex.c
@@ -0,0 +1,1005 @@
+/* BFD back-end for Intel Hex objects.
+ Copyright 1995 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor of Cygnus Support <ian@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is what Intel Hex files look like:
+
+1. INTEL FORMATS
+
+A. Intel 1
+
+ 16-bit address-field format, for files 64k bytes in length or less.
+
+ DATA RECORD
+ Byte 1 Header = colon(:)
+ 2..3 The number of data bytes in hex notation
+ 4..5 High byte of the record load address
+ 6..7 Low byte of the record load address
+ 8..9 Record type, must be "00"
+ 10..x Data bytes in hex notation:
+ x = (number of bytes - 1) * 2 + 11
+ x+1..x+2 Checksum in hex notation
+ x+3..x+4 Carriage return, line feed
+
+ END RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "00"
+ 4..7 Transfer-address (usually "0000")
+ the jump-to address, execution start address
+ 8..9 Record type, must be "01"
+ 10..11 Checksum, in hex notation
+ 12..13 Carriage return, line feed
+
+B. INTEL 2
+
+ MCS-86 format, using a 20-bit address for files larger than 64K bytes.
+
+ DATA RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count of this record, hex notation
+ 4..5 High byte of the record load address
+ 6..7 Low byte of the record load address
+ 8..9 Record type, must be "00"
+ 10..x The data bytes in hex notation:
+ x = (number of data bytes - 1) * 2 + 11
+ x+1..x+2 Checksum in hex notation
+ x+3..x+4 Carriage return, line feed
+
+ EXTENDED ADDRESS RECORD
+ Byte 1 Header = colon(:)
+ 2..3 The byte count, must be "02"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "02"
+ 10..11 High byte of the offset address
+ 12..13 Low byte of the offset address
+ 14..15 Checksum in hex notation
+ 16..17 Carriage return, line feed
+
+ The checksums are the two's complement of the 8-bit sum
+ without carry of the byte count, offset address, and the
+ record type.
+
+ START ADDRESS RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "04"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "03"
+ 10..13 8086 CS value
+ 14..17 8086 IP value
+ 18..19 Checksum in hex notation
+ 20..21 Carriage return, line feed
+
+Another document reports these additional types:
+
+ EXTENDED LINEAR ADDRESS RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "02"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "04"
+ 10..13 Upper 16 bits of address of subsequent records
+ 14..15 Checksum in hex notation
+ 16..17 Carriage return, line feed
+
+ START LINEAR ADDRESS RECORD
+ Byte 1 Header = colon (:)
+ 2..3 The byte count, must be "02"
+ 4..7 Load address, must be "0000"
+ 8..9 Record type, must be "05"
+ 10..13 Upper 16 bits of start address
+ 14..15 Checksum in hex notation
+ 16..17 Carriage return, line feed
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libiberty.h"
+
+#include <ctype.h>
+
+static void ihex_init PARAMS ((void));
+static boolean ihex_mkobject PARAMS ((bfd *));
+static INLINE int ihex_get_byte PARAMS ((bfd *, boolean *));
+static void ihex_bad_byte PARAMS ((bfd *, unsigned int, int, boolean));
+static boolean ihex_scan PARAMS ((bfd *));
+static const bfd_target *ihex_object_p PARAMS ((bfd *));
+static boolean ihex_read_section PARAMS ((bfd *, asection *, bfd_byte *));
+static boolean ihex_get_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static boolean ihex_set_section_contents
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+static boolean ihex_write_record
+ PARAMS ((bfd *, bfd_size_type, bfd_vma, unsigned int, bfd_byte *));
+static boolean ihex_write_object_contents PARAMS ((bfd *));
+static asymbol *ihex_make_empty_symbol PARAMS ((bfd *));
+static boolean ihex_set_arch_mach
+ PARAMS ((bfd *, enum bfd_architecture, unsigned long));
+
+/* The number of bytes we put on one line during output. */
+
+#define CHUNK (21)
+
+/* Macros for converting between hex and binary. */
+
+#define NIBBLE(x) (hex_value (x))
+#define HEX2(buffer) ((NIBBLE ((buffer)[0]) << 4) + NIBBLE ((buffer)[1]))
+#define HEX4(buffer) ((HEX2 (buffer) << 8) + HEX2 ((buffer) + 2))
+#define ISHEX(x) (hex_p (x))
+
+/* When we write out an ihex value, the values can not be output as
+ they are seen. Instead, we hold them in memory in this structure. */
+
+struct ihex_data_list
+{
+ struct ihex_data_list *next;
+ bfd_byte *data;
+ bfd_vma where;
+ bfd_size_type size;
+};
+
+/* The ihex tdata information. */
+
+struct ihex_data_struct
+{
+ struct ihex_data_list *head;
+ struct ihex_data_list *tail;
+};
+
+/* Initialize by filling in the hex conversion array. */
+
+static void
+ihex_init ()
+{
+ static boolean inited;
+
+ if (! inited)
+ {
+ inited = true;
+ hex_init ();
+ }
+}
+
+/* Create an ihex object. */
+
+static boolean
+ihex_mkobject (abfd)
+ bfd *abfd;
+{
+ if (abfd->tdata.ihex_data == NULL)
+ {
+ struct ihex_data_struct *tdata;
+
+ tdata = ((struct ihex_data_struct *)
+ bfd_alloc (abfd, sizeof (struct ihex_data_struct)));
+ if (tdata == NULL)
+ return false;
+ abfd->tdata.ihex_data = tdata;
+ tdata->head = NULL;
+ tdata->tail = NULL;
+ }
+
+ return true;
+}
+
+/* Read a byte from a BFD. Set *ERRORPTR if an error occurred.
+ Return EOF on error or end of file. */
+
+static INLINE int
+ihex_get_byte (abfd, errorptr)
+ bfd *abfd;
+ boolean *errorptr;
+{
+ bfd_byte c;
+
+ if (bfd_read (&c, 1, 1, abfd) != 1)
+ {
+ if (bfd_get_error () != bfd_error_file_truncated)
+ *errorptr = true;
+ return EOF;
+ }
+
+ return (int) (c & 0xff);
+}
+
+/* Report a problem in an Intel Hex file. */
+
+static void
+ihex_bad_byte (abfd, lineno, c, error)
+ bfd *abfd;
+ unsigned int lineno;
+ int c;
+ boolean error;
+{
+ if (c == EOF)
+ {
+ if (! error)
+ bfd_set_error (bfd_error_file_truncated);
+ }
+ else
+ {
+ char buf[10];
+
+ if (! isprint (c))
+ sprintf (buf, "\\%03o", (unsigned int) c);
+ else
+ {
+ buf[0] = c;
+ buf[1] = '\0';
+ }
+ (*_bfd_error_handler)
+ ("%s:%d: unexpected character `%s' in Intel Hex file\n",
+ bfd_get_filename (abfd), lineno, buf);
+ bfd_set_error (bfd_error_bad_value);
+ }
+}
+
+/* Read an Intel hex file and turn it into sections. We create a new
+ section for each contiguous set of bytes. */
+
+static boolean
+ihex_scan (abfd)
+ bfd *abfd;
+{
+ bfd_vma segbase;
+ bfd_vma extbase;
+ asection *sec;
+ int lineno;
+ boolean error;
+ bfd_byte *buf;
+ size_t bufsize;
+ int c;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ goto error_return;
+
+ abfd->start_address = 0;
+
+ extbase = 0;
+ segbase = 0;
+ sec = NULL;
+ lineno = 1;
+ error = false;
+ buf = NULL;
+ bufsize = 0;
+ while ((c = ihex_get_byte (abfd, &error)) != EOF)
+ {
+ if (c == '\r')
+ continue;
+ else if (c == '\n')
+ {
+ ++lineno;
+ continue;
+ }
+ else if (c != ':')
+ {
+ ihex_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+ else
+ {
+ file_ptr pos;
+ char hdr[8];
+ unsigned int i;
+ unsigned int len;
+ bfd_vma addr;
+ unsigned int type;
+ unsigned int chars;
+ unsigned int chksum;
+
+ /* This is a data record. */
+
+ pos = bfd_tell (abfd) - 1;
+
+ /* Read the header bytes. */
+
+ if (bfd_read (hdr, 1, 8, abfd) != 8)
+ goto error_return;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (! ISHEX (hdr[i]))
+ {
+ ihex_bad_byte (abfd, lineno, hdr[i], error);
+ goto error_return;
+ }
+ }
+
+ len = HEX2 (hdr);
+ addr = HEX4 (hdr + 2);
+ type = HEX2 (hdr + 6);
+
+ /* Read the data bytes. */
+
+ chars = len * 2 + 2;
+ if (chars >= bufsize)
+ {
+ buf = (bfd_byte *) bfd_realloc (buf, chars);
+ if (buf == NULL)
+ goto error_return;
+ bufsize = chars;
+ }
+
+ if (bfd_read (buf, 1, chars, abfd) != chars)
+ goto error_return;
+
+ for (i = 0; i < chars; i++)
+ {
+ if (! ISHEX (buf[i]))
+ {
+ ihex_bad_byte (abfd, lineno, hdr[i], error);
+ goto error_return;
+ }
+ }
+
+ /* Check the checksum. */
+ chksum = len + addr + (addr >> 8) + type;
+ for (i = 0; i < len; i++)
+ chksum += HEX2 (buf + 2 * i);
+ if (((- chksum) & 0xff) != (unsigned int) HEX2 (buf + 2 * i))
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad checksum in Intel Hex file (expected %u, found %u)",
+ bfd_get_filename (abfd), lineno,
+ (- chksum) & 0xff, (unsigned int) HEX2 (buf + 2 * i));
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ switch (type)
+ {
+ case 0:
+ /* This is a data record. */
+ if (sec != NULL
+ && sec->vma + sec->_raw_size == extbase + segbase + addr)
+ {
+ /* This data goes at the end of the section we are
+ currently building. */
+ sec->_raw_size += len;
+ }
+ else if (len > 0)
+ {
+ char secbuf[20];
+ char *secname;
+
+ sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
+ secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1);
+ if (secname == NULL)
+ goto error_return;
+ strcpy (secname, secbuf);
+ sec = bfd_make_section (abfd, secname);
+ if (sec == NULL)
+ goto error_return;
+ sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
+ sec->vma = extbase + segbase + addr;
+ sec->lma = extbase + segbase + addr;
+ sec->_raw_size = len;
+ sec->filepos = pos;
+ }
+ break;
+
+ case 1:
+ /* An end record. */
+ if (abfd->start_address == 0)
+ abfd->start_address = addr;
+ if (buf != NULL)
+ free (buf);
+ return true;
+
+ case 2:
+ /* An extended address record. */
+ if (len != 2)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended address record length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ segbase = HEX4 (buf) << 4;
+
+ sec = NULL;
+
+ break;
+
+ case 3:
+ /* An extended start address record. */
+ if (len != 4)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended start address length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ abfd->start_address += (HEX4 (buf) << 4) + HEX4 (buf + 4);
+
+ sec = NULL;
+
+ break;
+
+ case 4:
+ /* An extended linear address record. */
+ if (len != 2)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended linear address record length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ segbase = HEX4 (buf) << 16;
+
+ sec = NULL;
+
+ break;
+
+ case 5:
+ /* An extended linear start address record. */
+ if (len != 2)
+ {
+ (*_bfd_error_handler)
+ ("%s:%d: bad extended linear start address length in Intel Hex file",
+ bfd_get_filename (abfd), lineno);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ abfd->start_address += HEX4 (buf) << 16;
+
+ sec = NULL;
+
+ break;
+
+ default:
+ (*_bfd_error_handler)
+ ("%s:%d: unrecognized ihex type %u in Intel Hex file\n",
+ bfd_get_filename (abfd), lineno, type);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ }
+ }
+
+ if (error)
+ goto error_return;
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Try to recognize an Intel Hex file. */
+
+static const bfd_target *
+ihex_object_p (abfd)
+ bfd *abfd;
+{
+ bfd_byte b[9];
+ unsigned int i;
+ unsigned int type;
+
+ ihex_init ();
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ return NULL;
+ if (bfd_read (b, 1, 9, abfd) != 9)
+ {
+ if (bfd_get_error () == bfd_error_file_truncated)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (b[0] != ':')
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ for (i = 1; i < 9; i++)
+ {
+ if (! ISHEX (b[i]))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ }
+
+ type = HEX2 (b + 7);
+ if (type > 5)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* OK, it looks like it really is an Intel Hex file. */
+
+ if (! ihex_mkobject (abfd)
+ || ! ihex_scan (abfd))
+ return NULL;
+
+ return abfd->xvec;
+}
+
+/* Read the contents of a section in an Intel Hex file. */
+
+static boolean
+ihex_read_section (abfd, section, contents)
+ bfd *abfd;
+ asection *section;
+ bfd_byte *contents;
+{
+ int c;
+ bfd_byte *p;
+ bfd_byte *buf;
+ size_t bufsize;
+ boolean error;
+
+ if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
+ goto error_return;
+
+ p = contents;
+ buf = NULL;
+ bufsize = 0;
+ error = false;
+ while ((c = ihex_get_byte (abfd, &error)) != EOF)
+ {
+ char hdr[8];
+ unsigned int len;
+ bfd_vma addr;
+ unsigned int type;
+ unsigned int i;
+
+ if (c == '\r' || c == '\n')
+ continue;
+
+ /* This is called after ihex_scan has succeeded, so we ought to
+ know the exact format. */
+ BFD_ASSERT (c == ':');
+
+ if (bfd_read (hdr, 1, 8, abfd) != 8)
+ goto error_return;
+
+ len = HEX2 (hdr);
+ addr = HEX4 (hdr + 2);
+ type = HEX2 (hdr + 6);
+
+ /* We should only see type 0 records here. */
+ if (type != 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: internal error in ihex_read_section",
+ bfd_get_filename (abfd));
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ if (len * 2 > bufsize)
+ {
+ buf = (bfd_byte *) bfd_realloc (buf, len * 2);
+ if (buf == NULL)
+ goto error_return;
+ bufsize = len * 2;
+ }
+
+ if (bfd_read (buf, 1, len * 2, abfd) != len * 2)
+ goto error_return;
+
+ for (i = 0; i < len; i++)
+ *p++ = HEX2 (buf + 2 * i);
+ if ((bfd_size_type) (p - contents) >= section->_raw_size)
+ {
+ /* We've read everything in the section. */
+ if (buf != NULL)
+ free (buf);
+ return true;
+ }
+
+ /* Skip the checksum. */
+ if (bfd_read (buf, 1, 2, abfd) != 2)
+ goto error_return;
+ }
+
+ if ((bfd_size_type) (p - contents) < section->_raw_size)
+ {
+ (*_bfd_error_handler)
+ ("%s: bad section length in ihex_read_section",
+ bfd_get_filename (abfd));
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Get the contents of a section in an Intel Hex file. */
+
+static boolean
+ihex_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 == NULL)
+ {
+ section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
+ if (section->used_by_bfd == NULL)
+ return false;
+ if (! ihex_read_section (abfd, section, section->used_by_bfd))
+ return false;
+ }
+
+ memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
+ (size_t) count);
+
+ return true;
+}
+
+/* Set the contents of a section in an Intel Hex file. */
+
+static boolean
+ihex_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ struct ihex_data_list *n;
+ bfd_byte *data;
+ struct ihex_data_struct *tdata;
+
+ if (count == 0
+ || (section->flags & SEC_ALLOC) == 0
+ || (section->flags & SEC_LOAD) == 0)
+ return true;
+
+ n = ((struct ihex_data_list *)
+ bfd_alloc (abfd, sizeof (struct ihex_data_list)));
+ if (n == NULL)
+ return false;
+
+ data = (bfd_byte *) bfd_alloc (abfd, count);
+ if (data == NULL)
+ return false;
+ memcpy (data, location, (size_t) count);
+
+ n->data = data;
+ n->where = section->lma + offset;
+ n->size = count;
+
+ /* Sort the records by address. Optimize for the common case of
+ adding a record to the end of the list. */
+ tdata = abfd->tdata.ihex_data;
+ if (tdata->tail != NULL
+ && n->where >= tdata->tail->where)
+ {
+ tdata->tail->next = n;
+ n->next = NULL;
+ tdata->tail = n;
+ }
+ else
+ {
+ register struct ihex_data_list **pp;
+
+ for (pp = &tdata->head;
+ *pp != NULL && (*pp)->where < n->where;
+ pp = &(*pp)->next)
+ ;
+ n->next = *pp;
+ *pp = n;
+ if (n->next == NULL)
+ tdata->tail = n;
+ }
+
+ return true;
+}
+
+/* Write a record out to an Intel Hex file. */
+
+static boolean
+ihex_write_record (abfd, count, addr, type, data)
+ bfd *abfd;
+ bfd_size_type count;
+ bfd_vma addr;
+ unsigned int type;
+ bfd_byte *data;
+{
+ static const char digs[] = "0123456789ABCDEF";
+ char buf[9 + CHUNK * 2 + 4];
+ char *p;
+ unsigned int chksum;
+ unsigned int i;
+
+#define TOHEX(buf, v) \
+ ((buf)[0] = digs[((v) >> 4) & 0xf], (buf)[1] = digs[(v) & 0xf])
+
+ buf[0] = ':';
+ TOHEX (buf + 1, count);
+ TOHEX (buf + 3, (addr >> 8) & 0xff);
+ TOHEX (buf + 5, addr & 0xff);
+ TOHEX (buf + 7, type);
+
+ chksum = count + addr + (addr >> 8) + type;
+
+ for (i = 0, p = buf + 9; i < count; i++, p += 2, data++)
+ {
+ TOHEX (p, *data);
+ chksum += *data;
+ }
+
+ TOHEX (p, (- chksum) & 0xff);
+ p[2] = '\r';
+ p[3] = '\n';
+
+ if (bfd_write (buf, 1, 9 + count * 2 + 4, abfd) != 9 + count * 2 + 4)
+ return false;
+
+ return true;
+}
+
+/* Write out an Intel Hex file. */
+
+static boolean
+ihex_write_object_contents (abfd)
+ bfd *abfd;
+{
+ bfd_vma extbase;
+ bfd_vma segbase;
+ struct ihex_data_list *l;
+
+ extbase = 0;
+ segbase = 0;
+ for (l = abfd->tdata.ihex_data->head; l != NULL; l = l->next)
+ {
+ bfd_vma where;
+ bfd_byte *p;
+ bfd_size_type count;
+
+ where = l->where;
+ p = l->data;
+ count = l->size;
+ while (count > 0)
+ {
+ bfd_size_type now;
+
+ now = count;
+ if (now > CHUNK)
+ now = CHUNK;
+
+ if (where > extbase + segbase + 0xffff)
+ {
+ bfd_byte addr[2];
+
+ /* We need a new base address. */
+ if (where <= 0xfffff)
+ {
+ segbase = where & 0xf0000;
+ addr[0] = (segbase >> 12) & 0xff;
+ addr[1] = (segbase >> 4) & 0xff;
+ if (! ihex_write_record (abfd, 2, 0, 2, addr))
+ return false;
+ }
+ else
+ {
+ extbase = where & 0xffff0000;
+ if (where > extbase + 0xffff)
+ {
+ char buf[20];
+
+ sprintf_vma (buf, where);
+ (*_bfd_error_handler)
+ ("%s: address 0x%s out of range for Intex Hex file",
+ bfd_get_filename (abfd), buf);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ addr[0] = (extbase >> 24) & 0xff;
+ addr[1] = (extbase >> 16) & 0xff;
+ if (! ihex_write_record (abfd, 2, 0, 4, addr))
+ return false;
+ }
+ }
+
+ if (! ihex_write_record (abfd, now, where - (extbase + segbase),
+ 0, p))
+ return false;
+
+ where += now;
+ p += now;
+ count -= now;
+ }
+ }
+
+ if (abfd->start_address != 0)
+ {
+ bfd_vma start;
+ bfd_byte startbuf[4];
+
+ start = abfd->start_address;
+
+ if (start > 0xfffff)
+ {
+ startbuf[0] = (start >> 24) & 0xff;
+ startbuf[1] = (start >> 16) & 0xff;
+ if (! ihex_write_record (abfd, 2, 0, 5, startbuf))
+ return false;
+ start &= 0xffff;
+ }
+
+ startbuf[0] = ((start & 0xf0000) >> 12) & 0xff;
+ startbuf[1] = 0;
+ startbuf[2] = (start >> 8) & 0xff;
+ startbuf[3] = start & 0xff;
+ if (! ihex_write_record (abfd, 4, 0, 3, startbuf))
+ return false;
+ }
+
+ if (! ihex_write_record (abfd, 0, 0, 1, NULL))
+ return false;
+
+ return true;
+}
+
+/* Make an empty symbol. This is required only because
+ bfd_make_section_anyway wants to create a symbol for the section. */
+
+static asymbol *
+ihex_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new;
+
+ new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new != NULL)
+ new->the_bfd = abfd;
+ return new;
+}
+
+/* Set the architecture for the output file. The architecture is
+ irrelevant, so we ignore errors about unknown architectures. */
+
+static boolean
+ihex_set_arch_mach (abfd, arch, mach)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long mach;
+{
+ if (! bfd_default_set_arch_mach (abfd, arch, mach))
+ {
+ if (arch != bfd_arch_unknown)
+ return false;
+ }
+ return true;
+}
+
+/* Get the size of the headers, for the linker. */
+
+/*ARGSUSED*/
+static int
+ihex_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return 0;
+}
+
+/* Some random definitions for the target vector. */
+
+#define ihex_close_and_cleanup _bfd_generic_close_and_cleanup
+#define ihex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define ihex_new_section_hook _bfd_generic_new_section_hook
+#define ihex_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#define ihex_get_symtab_upper_bound bfd_0l
+#define ihex_get_symtab \
+ ((long (*) PARAMS ((bfd *, asymbol **))) bfd_0l)
+#define ihex_print_symbol _bfd_nosymbols_print_symbol
+#define ihex_get_symbol_info _bfd_nosymbols_get_symbol_info
+#define ihex_bfd_is_local_label _bfd_nosymbols_bfd_is_local_label
+#define ihex_get_lineno _bfd_nosymbols_get_lineno
+#define ihex_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define ihex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define ihex_read_minisymbols _bfd_nosymbols_read_minisymbols
+#define ihex_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
+
+#define ihex_get_reloc_upper_bound \
+ ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
+#define ihex_canonicalize_reloc \
+ ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
+#define ihex_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define ihex_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define ihex_bfd_relax_section bfd_generic_relax_section
+#define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define ihex_bfd_final_link _bfd_generic_final_link
+#define ihex_bfd_link_split_section _bfd_generic_link_split_section
+
+/* The Intel Hex target vector. */
+
+const bfd_target ihex_vec =
+{
+ "ihex", /* name */
+ bfd_target_ihex_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* target headers byte order */
+ 0, /* object flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD), /* section flags */
+ 0, /* leading underscore */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 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,
+ ihex_object_p, /* bfd_check_format */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ {
+ bfd_false,
+ ihex_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ ihex_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (ihex),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (ihex),
+ BFD_JUMP_TABLE_RELOCS (ihex),
+ BFD_JUMP_TABLE_WRITE (ihex),
+ BFD_JUMP_TABLE_LINK (ihex),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/init.c b/contrib/gdb/bfd/init.c
new file mode 100644
index 0000000..1fa1d50
--- /dev/null
+++ b/contrib/gdb/bfd/init.c
@@ -0,0 +1,50 @@
+/* bfd initialization stuff
+ Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/*
+SECTION
+ Initialization
+
+ These are the functions that handle initializing a BFD.
+*/
+
+/*
+FUNCTION
+ bfd_init
+
+SYNOPSIS
+ void bfd_init(void);
+
+DESCRIPTION
+ This routine must be called before any other BFD function to
+ initialize magical internal data structures.
+*/
+
+/* Actually, there is currently nothing for this function to do.
+ However, someday it may be needed, so keep it around. */
+
+void
+bfd_init ()
+{
+}
diff --git a/contrib/gdb/bfd/irix-core.c b/contrib/gdb/bfd/irix-core.c
new file mode 100644
index 0000000..3fd3977
--- /dev/null
+++ b/contrib/gdb/bfd/irix-core.c
@@ -0,0 +1,263 @@
+/* BFD back-end for Irix core files.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ Written by Stu Grossman, Cygnus Support.
+ Converted to back-end form by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file can only be compiled on systems which use Irix style core
+ files (namely, Irix 4 and Irix 5, so far). */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#ifdef IRIX_CORE
+
+#include <core.out.h>
+
+struct sgi_core_struct
+{
+ int sig;
+ char cmd[CORE_NAMESIZE];
+};
+
+#define core_hdr(bfd) ((bfd)->tdata.sgi_core_data)
+#define core_signal(bfd) (core_hdr(bfd)->sig)
+#define core_command(bfd) (core_hdr(bfd)->cmd)
+
+static asection *
+make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
+ bfd *abfd;
+ CONST char *name;
+ flagword flags;
+ bfd_size_type _raw_size;
+ bfd_vma vma;
+ file_ptr filepos;
+{
+ asection *asect;
+
+ asect = bfd_make_section_anyway (abfd, name);
+ if (!asect)
+ return NULL;
+
+ asect->flags = flags;
+ asect->_raw_size = _raw_size;
+ asect->vma = vma;
+ asect->filepos = filepos;
+ asect->alignment_power = 4;
+
+ return asect;
+}
+
+static const bfd_target *
+irix_core_core_file_p (abfd)
+ bfd *abfd;
+{
+ int val;
+ int i;
+ char *secname;
+ struct coreout coreout;
+ struct idesc *idg, *idf, *ids;
+
+ val = bfd_read ((PTR)&coreout, 1, sizeof coreout, abfd);
+ if (val != sizeof coreout)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (coreout.c_magic != CORE_MAGIC
+ || coreout.c_version != CORE_VERSION1)
+ return 0;
+
+ core_hdr (abfd) = (struct sgi_core_struct *) bfd_zalloc (abfd, sizeof (struct sgi_core_struct));
+ if (!core_hdr (abfd))
+ return NULL;
+
+ strncpy (core_command (abfd), coreout.c_name, CORE_NAMESIZE);
+ core_signal (abfd) = coreout.c_sigcause;
+
+ if (bfd_seek (abfd, coreout.c_vmapoffset, SEEK_SET) != 0)
+ return NULL;
+
+ for (i = 0; i < coreout.c_nvmap; i++)
+ {
+ struct vmap vmap;
+
+ val = bfd_read ((PTR)&vmap, 1, sizeof vmap, abfd);
+ if (val != sizeof vmap)
+ break;
+
+ switch (vmap.v_type)
+ {
+ case VDATA:
+ secname = ".data";
+ break;
+ case VSTACK:
+ secname = ".stack";
+ break;
+#ifdef VMAPFILE
+ case VMAPFILE:
+ secname = ".mapfile";
+ break;
+#endif
+ default:
+ continue;
+ }
+
+ /* A file offset of zero means that the section is not contained
+ in the corefile. */
+ if (vmap.v_offset == 0)
+ continue;
+
+ if (!make_bfd_asection (abfd, secname,
+ SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS,
+ vmap.v_len,
+ vmap.v_vaddr,
+ vmap.v_offset,
+ 2))
+ return NULL;
+ }
+
+ /* Make sure that the regs are contiguous within the core file. */
+
+ idg = &coreout.c_idesc[I_GPREGS];
+ idf = &coreout.c_idesc[I_FPREGS];
+ ids = &coreout.c_idesc[I_SPECREGS];
+
+ if (idg->i_offset + idg->i_len != idf->i_offset
+ || idf->i_offset + idf->i_len != ids->i_offset)
+ return 0; /* Can't deal with non-contig regs */
+
+ if (bfd_seek (abfd, idg->i_offset, SEEK_SET) != 0)
+ return NULL;
+
+ make_bfd_asection (abfd, ".reg",
+ SEC_HAS_CONTENTS,
+ idg->i_len + idf->i_len + ids->i_len,
+ 0,
+ idg->i_offset);
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+
+ return abfd->xvec;
+}
+
+static char *
+irix_core_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return core_command (abfd);
+}
+
+static int
+irix_core_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_signal (abfd);
+}
+
+static boolean
+irix_core_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* XXX - FIXME */
+}
+
+static asymbol *
+irix_core_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new)
+ new->the_bfd = abfd;
+ return new;
+}
+
+#define irix_core_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
+#define irix_core_get_symtab _bfd_nosymbols_get_symtab
+#define irix_core_print_symbol _bfd_nosymbols_print_symbol
+#define irix_core_get_symbol_info _bfd_nosymbols_get_symbol_info
+#define irix_core_bfd_is_local_label _bfd_nosymbols_bfd_is_local_label
+#define irix_core_get_lineno _bfd_nosymbols_get_lineno
+#define irix_core_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define irix_core_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define irix_core_read_minisymbols _bfd_nosymbols_read_minisymbols
+#define irix_core_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
+
+/* 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 (( const bfd_byte *))) swap_abort )
+#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
+#define NO_SIGNED_GET \
+ ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
+
+const bfd_target irix_core_vec =
+ {
+ "irix-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ 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 */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ irix_core_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (irix_core),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (irix_core),
+ 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 */
+};
+
+#endif /* IRIX_CORE */
diff --git a/contrib/gdb/bfd/libaout.h b/contrib/gdb/bfd/libaout.h
new file mode 100644
index 0000000..76c1dff
--- /dev/null
+++ b/contrib/gdb/bfd/libaout.h
@@ -0,0 +1,608 @@
+/* BFD back-end data structures for a.out (and similar) files.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
+#define GET_WORD bfd_h_get_64
+#define GET_SWORD bfd_h_get_signed_64
+#define PUT_WORD bfd_h_put_64
+#ifndef NAME
+#define NAME(x,y) CAT3(x,_64_,y)
+#endif
+#define JNAME(x) CAT(x,_64)
+#define BYTES_IN_WORD 8
+#else /* ARCH_SIZE == 32 */
+#define GET_WORD bfd_h_get_32
+#define GET_SWORD bfd_h_get_signed_32
+#define PUT_WORD bfd_h_put_32
+#ifndef NAME
+#define NAME(x,y) CAT3(x,_32_,y)
+#endif
+#define JNAME(x) CAT(x,_32)
+#define BYTES_IN_WORD 4
+#endif /* ARCH_SIZE==32 */
+
+/* Declare at file level, since used in parameter lists, which have
+ weird scope. */
+struct external_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
+{
+ /* Are ZMAGIC files mapped contiguously? If so, the text section may
+ need more padding, if the segment size (granularity for memory access
+ control) is larger than the page size. */
+ unsigned char zmagic_mapped_contiguous;
+ /* If this flag is set, ZMAGIC/NMAGIC file headers get mapped in with the
+ text section, which starts immediately after the file header.
+ 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. */
+ /* ?? Perhaps a callback would be a better choice? Will this do anything
+ reasonable for a format that handles multiple CPUs with different
+ load addresses for each? */
+ bfd_vma default_text_vma;
+
+ /* Callback for setting the page and segment sizes, if they can't be
+ trivially determined from the architecture. */
+ boolean (*set_sizes) PARAMS ((bfd *));
+
+ /* zmagic files only. For go32, the length of the exec header contributes
+ 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 *,
+ struct external_nlist **,
+ bfd_size_type *, char **));
+
+ /* 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 *));
+
+ /* If this callback is not NULL, the linker calls it for each reloc.
+ RELOC is a pointer to the unswapped reloc. If *SKIP is set to
+ true, the reloc will be skipped. *RELOCATION may be changed to
+ change the effects of the relocation. */
+ boolean (*check_dynamic_reloc) PARAMS ((struct bfd_link_info *info,
+ bfd *input_bfd,
+ asection *input_section,
+ struct aout_link_hash_entry *h,
+ PTR reloc, bfd_byte *contents,
+ boolean *skip,
+ bfd_vma *relocation));
+
+ /* 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))
+
+/* This is the layout in memory of a "struct exec" while we process it.
+ All 'lengths' are given as a number of bytes.
+ All 'alignments' are for relinkable files only; an alignment of
+ 'n' indicates the corresponding segment must begin at an
+ address that is a multiple of (2**n). */
+
+struct internal_exec
+{
+ long a_info; /* Magic number and flags, packed */
+ bfd_vma a_text; /* length of text, in bytes */
+ bfd_vma a_data; /* length of data, in bytes */
+ bfd_vma a_bss; /* length of uninitialized data area in mem */
+ bfd_vma a_syms; /* length of symbol table data in file */
+ bfd_vma a_entry; /* start address */
+ bfd_vma a_trsize; /* length of text's relocation info, in bytes */
+ bfd_vma a_drsize; /* length of data's relocation info, in bytes */
+ /* Added for i960 */
+ bfd_vma a_tload; /* Text runtime load address */
+ bfd_vma a_dload; /* Data runtime load address */
+ unsigned char a_talign; /* Alignment of text segment */
+ unsigned char a_dalign; /* Alignment of data segment */
+ unsigned char a_balign; /* Alignment of bss segment */
+ char a_relaxable; /* Enough info for linker relax */
+};
+
+/* Magic number is written
+< MSB >
+3130292827262524232221201918171615141312111009080706050403020100
+< FLAGS >< MACHINE TYPE >< MAGIC NUMBER >
+*/
+/* Magic number for NetBSD is
+<MSB >
+3130292827262524232221201918171615141312111009080706050403020100
+< FLAGS >< >< MAGIC NUMBER >
+*/
+
+enum machine_type {
+ M_UNKNOWN = 0,
+ M_68010 = 1,
+ 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_ARM = 103, /* Advanced Risc Machines ARM */
+ M_386_NETBSD = 134, /* NetBSD/i386 binary */
+ M_68K_NETBSD = 135, /* NetBSD/m68k binary */
+ M_68K4K_NETBSD = 136, /* NetBSD/m68k4k binary */
+ M_532_NETBSD = 137, /* NetBSD/ns32k binary */
+ M_SPARC_NETBSD = 138, /* NetBSD/sparc binary */
+ M_MIPS1 = 151, /* MIPS R2000/R3000 binary */
+ M_MIPS2 = 152, /* MIPS R4000/R6000 binary */
+ M_HP200 = 200, /* HP 200 (68010) BSD binary */
+ M_HP300 = (300 % 256), /* HP 300 (68020+68881) BSD binary */
+ M_HPUX = (0x20c % 256)/* HP 200/300 HPUX binary */
+};
+
+#define N_DYNAMIC(exec) ((exec).a_info & 0x80000000)
+
+#ifndef N_MAGIC
+# define N_MAGIC(exec) ((exec).a_info & 0xffff)
+#endif
+
+#ifndef N_MACHTYPE
+# define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
+#endif
+
+#ifndef N_FLAGS
+# define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
+#endif
+
+#ifndef N_SET_INFO
+# define N_SET_INFO(exec, magic, type, flags) \
+((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0xff) << 16) \
+ | (((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)))
+#endif
+
+#ifndef N_SET_MACHTYPE
+# define N_SET_MACHTYPE(exec, machtype) \
+((exec).a_info = \
+ ((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
+#endif
+
+#ifndef N_SET_FLAGS
+# define N_SET_FLAGS(exec, flags) \
+((exec).a_info = \
+ ((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
+#endif
+
+typedef struct aout_symbol {
+ asymbol symbol;
+ short desc;
+ char other;
+ unsigned char type;
+} aout_symbol_type;
+
+/* The `tdata' struct for all a.out-like object file formats.
+ Various things depend on this struct being around any time an a.out
+ file is being handled. An example is dbxread.c in GDB. */
+
+struct aoutdata {
+ struct internal_exec *hdr; /* exec file header */
+ aout_symbol_type *symbols; /* symtab for input bfd */
+
+ /* For ease, we do this */
+ asection *textsec;
+ asection *datasec;
+ asection *bsssec;
+
+ /* We remember these offsets so that after check_file_format, we have
+ no dependencies on the particular format of the exec_hdr. */
+ file_ptr sym_filepos;
+ file_ptr str_filepos;
+
+ /* Size of a relocation entry in external form */
+ unsigned reloc_entry_size;
+
+ /* Size of a symbol table entry in external form */
+ unsigned symbol_entry_size;
+
+ /* Page size - needed for alignment of demand paged files. */
+ unsigned long page_size;
+
+ /* 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,
+ /* 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;
+
+ /* A buffer for find_nearest_line. */
+ char *line_buf;
+
+ /* The external symbol information. */
+ struct external_nlist *external_syms;
+ bfd_size_type external_sym_count;
+ bfd_window sym_window;
+ char *external_strings;
+ bfd_size_type external_string_size;
+ bfd_window string_window;
+ struct aout_link_hash_entry **sym_hashes;
+
+ /* A pointer for shared library information. */
+ PTR dynamic_info;
+
+ /* A mapping from local symbols to offsets into the global offset
+ table, used when linking on SunOS. This is indexed by the symbol
+ index. */
+ bfd_vma *local_got_offsets;
+};
+
+struct aout_data_struct {
+ struct aoutdata a;
+ struct internal_exec e;
+};
+
+#define adata(bfd) ((bfd)->tdata.aout_data->a)
+#define exec_hdr(bfd) (adata(bfd).hdr)
+#define obj_aout_symbols(bfd) (adata(bfd).symbols)
+#define obj_textsec(bfd) (adata(bfd).textsec)
+#define obj_datasec(bfd) (adata(bfd).datasec)
+#define obj_bsssec(bfd) (adata(bfd).bsssec)
+#define obj_sym_filepos(bfd) (adata(bfd).sym_filepos)
+#define obj_str_filepos(bfd) (adata(bfd).str_filepos)
+#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_sym_window(bfd) (adata(bfd).sym_window)
+#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_string_window(bfd) (adata(bfd).string_window)
+#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)
+
+#define set_aout_section_data(s,v) \
+ ((s)->used_by_bfd = (PTR)&(v)->relocs)
+
+/* Prototype declarations for functions defined in aoutx.h */
+
+boolean
+NAME(aout,squirt_out_relocs) PARAMS ((bfd *abfd, asection *section));
+
+boolean
+NAME(aout,make_sections) PARAMS ((bfd *));
+
+const bfd_target *
+NAME(aout,some_aout_object_p) PARAMS ((bfd *abfd,
+ 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,
+ boolean *unknown));
+
+boolean
+NAME(aout,set_arch_mach) PARAMS ((bfd *abfd, enum bfd_architecture arch,
+ unsigned long machine));
+
+boolean
+NAME(aout,new_section_hook) PARAMS ((bfd *abfd, asection *newsect));
+
+boolean
+NAME(aout,set_section_contents) PARAMS ((bfd *abfd, sec_ptr section,
+ PTR location, file_ptr offset, bfd_size_type count));
+
+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));
+
+boolean
+NAME(aout,write_syms) PARAMS ((bfd *abfd));
+
+void
+NAME(aout,reclaim_symbol_table) PARAMS ((bfd *abfd));
+
+long
+NAME(aout,get_symtab_upper_bound) PARAMS ((bfd *abfd));
+
+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 **, bfd_size_type));
+void
+NAME(aout,swap_std_reloc_in) PARAMS ((bfd *, struct reloc_std_external *,
+ arelent *, asymbol **, bfd_size_type));
+
+reloc_howto_type *
+NAME(aout,reloc_type_lookup) PARAMS ((bfd *abfd,
+ bfd_reloc_code_real_type code));
+
+boolean
+NAME(aout,slurp_reloc_table) PARAMS ((bfd *abfd, sec_ptr asect,
+ asymbol **symbols));
+
+long
+NAME(aout,canonicalize_reloc) PARAMS ((bfd *abfd, sec_ptr section,
+ arelent **relptr, asymbol **symbols));
+
+long
+NAME(aout,get_reloc_upper_bound) PARAMS ((bfd *abfd, sec_ptr asect));
+
+void
+NAME(aout,reclaim_reloc) PARAMS ((bfd *ignore_abfd, sec_ptr ignore));
+
+alent *
+NAME(aout,get_lineno) PARAMS ((bfd *ignore_abfd, asymbol *ignore_symbol));
+
+void
+NAME(aout,print_symbol) PARAMS ((bfd *ignore_abfd, PTR file,
+ asymbol *symbol, bfd_print_symbol_type how));
+
+void
+NAME(aout,get_symbol_info) PARAMS ((bfd *ignore_abfd,
+ asymbol *symbol, symbol_info *ret));
+
+boolean
+NAME(aout,find_nearest_line) PARAMS ((bfd *abfd, asection *section,
+ asymbol **symbols, bfd_vma offset, CONST char **filename_ptr,
+ CONST char **functionname_ptr, unsigned int *line_ptr));
+
+long
+NAME(aout,read_minisymbols) PARAMS ((bfd *, boolean, PTR *, unsigned int *));
+
+asymbol *
+NAME(aout,minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+ asymbol *));
+
+int
+NAME(aout,sizeof_headers) PARAMS ((bfd *abfd, boolean exec));
+
+boolean
+NAME(aout,adjust_sizes_and_vmas) PARAMS ((bfd *abfd,
+ bfd_size_type *text_size, file_ptr *text_end));
+
+void
+NAME(aout,swap_exec_header_in) PARAMS ((bfd *abfd,
+ struct external_exec *raw_bytes, struct internal_exec *execp));
+
+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 *));
+
+/* A.out uses the generic versions of these routines... */
+
+#define aout_32_get_section_contents _bfd_generic_get_section_contents
+
+#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) \
+ { \
+ bfd_size_type text_size; /* dummy vars */ \
+ file_ptr text_end; \
+ if (adata(abfd).magic == undecided_magic) \
+ NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
+ \
+ execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
+ execp->a_entry = bfd_get_start_address (abfd); \
+ \
+ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
+ \
+ 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_outsymbols (abfd) != (asymbol **) NULL \
+ && bfd_get_symcount (abfd) != 0) \
+ { \
+ if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) \
+ != 0) \
+ return false; \
+ \
+ if (! NAME(aout,write_syms)(abfd)) return false; \
+ \
+ 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; \
+ 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; \
+ } \
+ }
+#endif
+
+#endif /* ! defined (LIBAOUT_H) */
diff --git a/contrib/gdb/bfd/libbfd-in.h b/contrib/gdb/bfd/libbfd-in.h
new file mode 100644
index 0000000..14935eb
--- /dev/null
+++ b/contrib/gdb/bfd/libbfd-in.h
@@ -0,0 +1,503 @@
+/* libbfd.h -- Declarations used by bfd library *implementation*.
+ (This include file is not for users of the library.)
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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) \
+ ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
+
+/* If you want to read and write large blocks, you might want to do it
+ in quanta of this amount */
+#define DEFAULT_BUFFERSIZE 8192
+
+/* Set a tdata field. Can't use the other macros for this, since they
+ do casts, and casting to the left of assignment isn't portable. */
+#define set_tdata(bfd, v) ((bfd)->tdata.any = (PTR) (v))
+
+/* If BFD_IN_MEMORY is set for a BFD, then the iostream fields points
+ to an instance of this structure. */
+
+struct bfd_in_memory
+{
+ /* Size of buffer. */
+ bfd_size_type size;
+ /* Buffer holding contents of BFD. */
+ bfd_byte *buffer;
+};
+
+/* tdata for an archive. For an input archive, cache
+ needs to be free()'d. For an output archive, symdefs do. */
+
+struct artdata {
+ file_ptr first_file_filepos;
+ /* Speed up searching the armap */
+ struct ar_cache *cache;
+ bfd *archive_head; /* Only interesting in output routines */
+ carsym *symdefs; /* the symdef entries */
+ symindex symdef_count; /* how many there are */
+ char *extended_names; /* clever intel extension */
+ /* 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,
+ just before we finish writing an
+ 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)
+
+/* Goes in bfd's arelt_data slot */
+struct areltdata {
+ char * arch_header; /* it's actually a string */
+ unsigned int parsed_size; /* octets of filesize not including ar_hdr */
+ char *filename; /* null-terminated */
+};
+
+#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
+
+extern PTR bfd_malloc PARAMS ((size_t));
+extern PTR bfd_realloc PARAMS ((PTR, size_t));
+extern PTR bfd_zmalloc PARAMS ((size_t));
+
+extern bfd_error_handler_type _bfd_error_handler;
+
+/* These routines allocate and free things on the BFD's obstack. */
+
+PTR bfd_alloc PARAMS ((bfd *abfd, size_t size));
+PTR bfd_zalloc PARAMS ((bfd *abfd, 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));
+
+#define bfd_release(x,y) (void) obstack_free(&(x->memory),y)
+
+bfd * _bfd_create_empty_archive_element_shell PARAMS ((bfd *obfd));
+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));
+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));
+extern boolean _bfd_construct_extended_name_table
+ PARAMS ((bfd *, boolean, char **, bfd_size_type *));
+boolean _bfd_write_archive_contents PARAMS ((bfd *abfd));
+boolean _bfd_compute_and_write_armap PARAMS ((bfd *, unsigned int elength));
+bfd *_bfd_get_elt_at_filepos PARAMS ((bfd *archive, file_ptr filepos));
+extern bfd *_bfd_generic_get_elt_at_index PARAMS ((bfd *, symindex));
+bfd * _bfd_new_bfd PARAMS ((void));
+
+boolean bfd_false PARAMS ((bfd *ignore));
+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 *_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));
+void bfd_bsd_truncate_arname PARAMS ((bfd *abfd, CONST char *filename,
+ char *hdr));
+void bfd_gnu_truncate_arname PARAMS ((bfd *abfd, CONST char *filename,
+ char *hdr));
+
+boolean bsd_write_armap PARAMS ((bfd *arch, unsigned int elength,
+ struct orl *map, unsigned int orl_count, int stridx));
+
+boolean coff_write_armap PARAMS ((bfd *arch, unsigned int elength,
+ struct orl *map, unsigned int orl_count, int stridx));
+
+extern PTR _bfd_generic_read_ar_hdr PARAMS ((bfd *));
+
+extern PTR _bfd_generic_read_ar_hdr_mag PARAMS ((bfd *, const char *));
+
+bfd * bfd_generic_openr_next_archived_file PARAMS ((bfd *archive,
+ bfd *last_file));
+
+int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *));
+
+#define _bfd_read_ar_hdr(abfd) \
+ BFD_SEND (abfd, _bfd_read_ar_hdr_fn, (abfd))
+
+/* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic). */
+
+#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));
+extern boolean _bfd_generic_get_section_contents_in_window
+ PARAMS ((bfd *, asection *, bfd_window *, file_ptr, bfd_size_type));
+
+/* 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_merge_private_bfd_data \
+ ((boolean (*) PARAMS ((bfd *, bfd *))) bfd_true)
+#define _bfd_generic_bfd_set_private_flags \
+ ((boolean (*) PARAMS ((bfd *, flagword))) bfd_true)
+#define _bfd_generic_bfd_copy_private_section_data \
+ ((boolean (*) PARAMS ((bfd *, asection *, bfd *, asection *))) bfd_true)
+#define _bfd_generic_bfd_copy_private_symbol_data \
+ ((boolean (*) PARAMS ((bfd *, asymbol *, bfd *, asymbol *))) bfd_true)
+#define _bfd_generic_bfd_print_private_bfd_data \
+ ((boolean (*) PARAMS ((bfd *, PTR))) 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_construct_extended_name_table \
+ ((boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
+ 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_read_ar_hdr bfd_nullvoidptr
+#define _bfd_noarchive_openr_next_archived_file \
+ ((bfd *(*) PARAMS ((bfd *, bfd *))) bfd_nullvoidptr)
+#define _bfd_noarchive_get_elt_at_index \
+ ((bfd *(*) PARAMS ((bfd *, symindex))) bfd_nullvoidptr)
+#define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define _bfd_noarchive_update_armap_timestamp bfd_false
+
+/* 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
+extern boolean _bfd_archive_bsd_construct_extended_name_table
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+#define _bfd_archive_bsd_truncate_arname bfd_bsd_truncate_arname
+#define _bfd_archive_bsd_write_armap bsd_write_armap
+#define _bfd_archive_bsd_read_ar_hdr _bfd_generic_read_ar_hdr
+#define _bfd_archive_bsd_openr_next_archived_file \
+ bfd_generic_openr_next_archived_file
+#define _bfd_archive_bsd_get_elt_at_index _bfd_generic_get_elt_at_index
+#define _bfd_archive_bsd_generic_stat_arch_elt \
+ bfd_generic_stat_arch_elt
+extern boolean _bfd_archive_bsd_update_armap_timestamp PARAMS ((bfd *));
+
+/* 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
+extern boolean _bfd_archive_coff_construct_extended_name_table
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+#define _bfd_archive_coff_truncate_arname bfd_dont_truncate_arname
+#define _bfd_archive_coff_write_armap coff_write_armap
+#define _bfd_archive_coff_read_ar_hdr _bfd_generic_read_ar_hdr
+#define _bfd_archive_coff_openr_next_archived_file \
+ bfd_generic_openr_next_archived_file
+#define _bfd_archive_coff_get_elt_at_index _bfd_generic_get_elt_at_index
+#define _bfd_archive_coff_generic_stat_arch_elt \
+ bfd_generic_stat_arch_elt
+#define _bfd_archive_coff_update_armap_timestamp bfd_true
+
+/* 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)
+#define _bfd_nosymbols_read_minisymbols \
+ ((long (*) PARAMS ((bfd *, boolean, PTR *, unsigned int *))) _bfd_n1)
+#define _bfd_nosymbols_minisymbol_to_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, boolean, const PTR, asymbol *))) \
+ 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 \
+ ((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)
+#define _bfd_nolink_bfd_link_split_section \
+ ((boolean (*) PARAMS ((bfd *, struct sec *))) 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 *));
+
+/* Generic minisymbol routines. */
+extern long _bfd_generic_read_minisymbols
+ PARAMS ((bfd *, boolean, PTR *, unsigned int *));
+extern asymbol *_bfd_generic_minisymbol_to_symbol
+ PARAMS ((bfd *, boolean, const PTR, asymbol *));
+
+/* Find the nearest line using .stab/.stabstr sections. */
+extern boolean _bfd_stab_section_find_nearest_line
+ PARAMS ((bfd *, asymbol **, asection *, bfd_vma, boolean *, const char **,
+ const char **, unsigned int *, PTR *));
+
+/* 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 *));
+
+extern boolean _bfd_generic_link_split_section
+ PARAMS ((bfd *, struct sec *));
+
+/* 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 ((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 ((reloc_howto_type *, bfd *, bfd_vma, bfd_byte *));
+
+/* Create a string table. */
+extern struct bfd_strtab_hash *_bfd_stringtab_init PARAMS ((void));
+
+/* Create an XCOFF .debug section style string table. */
+extern struct bfd_strtab_hash *_bfd_xcoff_stringtab_init PARAMS ((void));
+
+/* Free a string table. */
+extern void _bfd_stringtab_free PARAMS ((struct bfd_strtab_hash *));
+
+/* Get the size of a string table. */
+extern bfd_size_type _bfd_stringtab_size PARAMS ((struct bfd_strtab_hash *));
+
+/* Add a string to a string table. */
+extern bfd_size_type _bfd_stringtab_add
+ PARAMS ((struct bfd_strtab_hash *, const char *, boolean hash,
+ boolean copy));
+
+/* Write out a string table. */
+extern boolean _bfd_stringtab_emit PARAMS ((bfd *, struct bfd_strtab_hash *));
+
+/* Macros to tell if bfds are read or write enabled.
+
+ Note that bfds open for read may be scribbled into if the fd passed
+ to bfd_fdopenr is actually open both for read and write
+ simultaneously. However an output bfd will never be open for
+ read. Therefore sometimes you want to check bfd_read_p or
+ !bfd_read_p, and only sometimes bfd_write_p.
+*/
+
+#define bfd_read_p(abfd) ((abfd)->direction == read_direction || (abfd)->direction == both_direction)
+#define bfd_write_p(abfd) ((abfd)->direction == write_direction || (abfd)->direction == both_direction)
+
+void bfd_assert PARAMS ((const char*,int));
+
+#define BFD_ASSERT(x) \
+{ if (!(x)) bfd_assert(__FILE__,__LINE__); }
+
+#define BFD_FAIL() \
+{ bfd_assert(__FILE__,__LINE__); }
+
+FILE * bfd_cache_lookup_worker PARAMS ((bfd *));
+
+extern bfd *bfd_last_cache;
+
+/* Now Steve, what's the story here? */
+#ifdef lint
+#define itos(x) "l"
+#define stoi(x) 1
+#else
+#define itos(x) ((char*)(x))
+#define stoi(x) ((int)(x))
+#endif
+
+/* 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[];
+
+/* Functions shared by the ECOFF and MIPS ELF backends, which have no
+ other common header files. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_find_line;
+#endif
+
+extern boolean _bfd_ecoff_locate_line
+ PARAMS ((bfd *, asection *, bfd_vma, struct ecoff_debug_info * const,
+ const struct ecoff_debug_swap * const, struct ecoff_find_line *,
+ const char **, const char **, unsigned int *));
+extern boolean _bfd_ecoff_get_accumulated_pdr PARAMS ((PTR, bfd_byte *));
+extern boolean _bfd_ecoff_get_accumulated_sym PARAMS ((PTR, bfd_byte *));
+extern boolean _bfd_ecoff_get_accumulated_ss PARAMS ((PTR, bfd_byte *));
+
+extern bfd_vma _bfd_get_gp_value PARAMS ((bfd *));
+extern void _bfd_set_gp_value PARAMS ((bfd *, bfd_vma));
+
+/* And more follows */
+
diff --git a/contrib/gdb/bfd/libbfd.c b/contrib/gdb/bfd/libbfd.c
new file mode 100644
index 0000000..1052a3a1
--- /dev/null
+++ b/contrib/gdb/bfd/libbfd.c
@@ -0,0 +1,1197 @@
+/* Assorted BFD support routines, only used internally.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+static int real_read PARAMS ((PTR, size_t, size_t, FILE *));
+
+/*
+SECTION
+ Internal functions
+
+DESCRIPTION
+ These routines are used within BFD.
+ They are not intended for export, but are documented here for
+ completeness.
+*/
+
+/* A routine which is used in target vectors for unsupported
+ operations. */
+
+/*ARGSUSED*/
+boolean
+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
+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
+bfd_nullvoidptr (ignore)
+ bfd *ignore;
+{
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+}
+
+/*ARGSUSED*/
+int
+bfd_0 (ignore)
+ bfd *ignore;
+{
+ return 0;
+}
+
+/*ARGSUSED*/
+unsigned int
+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
+bfd_void (ignore)
+ bfd *ignore;
+{
+}
+
+/*ARGSUSED*/
+boolean
+_bfd_nocore_core_file_matches_executable_p (ignore_core_bfd, ignore_exec_bfd)
+ bfd *ignore_core_bfd;
+ bfd *ignore_exec_bfd;
+{
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+}
+
+/* Routine to handle core_file_failing_command entry point for targets
+ without core file support. */
+
+/*ARGSUSED*/
+char *
+_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
+_bfd_nocore_core_file_failing_signal (ignore_abfd)
+ bfd *ignore_abfd;
+{
+ bfd_set_error (bfd_error_invalid_operation);
+ return 0;
+}
+
+/*ARGSUSED*/
+const bfd_target *
+_bfd_dummy_target (ignore_abfd)
+ bfd *ignore_abfd;
+{
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+}
+
+/* Allocate memory using malloc. */
+
+PTR
+bfd_malloc (size)
+ size_t size;
+{
+ PTR ptr;
+
+ ptr = (PTR) malloc (size);
+ if (ptr == NULL && size != 0)
+ bfd_set_error (bfd_error_no_memory);
+ return ptr;
+}
+
+/* Reallocate memory using realloc. */
+
+PTR
+bfd_realloc (ptr, size)
+ PTR ptr;
+ size_t size;
+{
+ PTR ret;
+
+ if (ptr == NULL)
+ ret = malloc (size);
+ else
+ ret = realloc (ptr, size);
+
+ if (ret == NULL)
+ bfd_set_error (bfd_error_no_memory);
+
+ return ret;
+}
+
+/* Allocate memory using malloc and clear it. */
+
+PTR
+bfd_zmalloc (size)
+ size_t size;
+{
+ PTR ptr;
+
+ ptr = (PTR) malloc (size);
+
+ if (size != 0)
+ {
+ if (ptr == NULL)
+ bfd_set_error (bfd_error_no_memory);
+ else
+ memset (ptr, 0, size);
+ }
+
+ return ptr;
+}
+
+/* Some IO code */
+
+
+/* Note that archive entries don't have streams; they share their parent's.
+ This allows someone to play with the iostream behind BFD's back.
+
+ Also, note that the origin pointer points to the beginning of a file's
+ contents (0 for non-archive elements). For archive entries this is the
+ first octet in the file, NOT the beginning of the archive header. */
+
+static int
+real_read (where, a,b, file)
+ PTR where;
+ size_t a;
+ size_t 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
+bfd_read (ptr, size, nitems, abfd)
+ PTR ptr;
+ bfd_size_type size;
+ bfd_size_type nitems;
+ bfd *abfd;
+{
+ int nread;
+
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ {
+ struct bfd_in_memory *bim;
+ bfd_size_type get;
+
+ bim = (struct bfd_in_memory *) abfd->iostream;
+ get = size * nitems;
+ if (abfd->where + get > bim->size)
+ {
+ get = bim->size - abfd->where;
+ bfd_set_error (bfd_error_file_truncated);
+ }
+ memcpy (ptr, bim->buffer + abfd->where, get);
+ abfd->where += get;
+ return get;
+ }
+
+ nread = real_read (ptr, 1, (size_t)(size*nitems), bfd_cache_lookup(abfd));
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ 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;
+}
+
+/* The window support stuff should probably be broken out into
+ another file.... */
+/* The idea behind the next and refcount fields is that one mapped
+ region can suffice for multiple read-only windows or multiple
+ non-overlapping read-write windows. It's not implemented yet
+ though. */
+struct _bfd_window_internal {
+ struct _bfd_window_internal *next;
+ PTR data;
+ bfd_size_type size;
+ int refcount : 31; /* should be enough... */
+ unsigned mapped : 1; /* 1 = mmap, 0 = malloc */
+};
+
+void
+bfd_init_window (windowp)
+ bfd_window *windowp;
+{
+ windowp->data = 0;
+ windowp->i = 0;
+ windowp->size = 0;
+}
+
+#undef HAVE_MPROTECT /* code's not tested yet */
+
+#if HAVE_MMAP || HAVE_MPROTECT || HAVE_MADVISE
+#include <sys/types.h>
+#include <sys/mman.h>
+#endif
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+
+static int debug_windows;
+
+/* Currently, if USE_MMAP is undefined, none if the window stuff is
+ used. Okay, so it's mis-named. At least the command-line option
+ "--without-mmap" is more obvious than "--without-windows" or some
+ such. */
+#ifdef USE_MMAP
+
+void
+bfd_free_window (windowp)
+ bfd_window *windowp;
+{
+ bfd_window_internal *i = windowp->i;
+ windowp->i = 0;
+ windowp->data = 0;
+ if (i == 0)
+ return;
+ i->refcount--;
+ if (debug_windows)
+ fprintf (stderr, "freeing window @%p<%p,%lx,%p>\n",
+ windowp, windowp->data, windowp->size, windowp->i);
+ if (i->refcount != 0)
+ return;
+
+ if (i->mapped)
+ {
+#ifdef HAVE_MMAP
+ munmap (i->data, i->size);
+ goto no_free;
+#else
+ abort ();
+#endif
+ }
+#ifdef HAVE_MPROTECT
+ mprotect (i->data, i->size, PROT_READ | PROT_WRITE);
+#endif
+ free (i->data);
+#ifdef HAVE_MMAP
+ no_free:
+#endif
+ i->data = 0;
+ /* There should be no more references to i at this point. */
+ free (i);
+}
+#endif
+
+static int ok_to_map = 1;
+
+boolean
+bfd_get_file_window (abfd, offset, size, windowp, writable)
+ bfd *abfd;
+ file_ptr offset;
+ bfd_size_type size;
+ bfd_window *windowp;
+ boolean writable;
+{
+ static size_t pagesize;
+ bfd_window_internal *i = windowp->i;
+ size_t size_to_alloc = size;
+
+#ifndef USE_MMAP
+ abort ();
+#endif
+
+ if (debug_windows)
+ fprintf (stderr, "bfd_get_file_window (%p, %6ld, %6ld, %p<%p,%lx,%p>, %d)",
+ abfd, (long) offset, (long) size,
+ windowp, windowp->data, windowp->size, windowp->i,
+ writable);
+
+ /* Make sure we know the page size, so we can be friendly to mmap. */
+ if (pagesize == 0)
+ pagesize = getpagesize ();
+ if (pagesize == 0)
+ abort ();
+
+ if (i == 0)
+ {
+ windowp->i = i = (bfd_window_internal *) bfd_zmalloc (sizeof (bfd_window_internal));
+ if (i == 0)
+ return false;
+ i->data = 0;
+ }
+#ifdef HAVE_MMAP
+ if (ok_to_map
+ && (i->data == 0 || i->mapped == 1)
+ && (abfd->flags & BFD_IN_MEMORY) == 0)
+ {
+ file_ptr file_offset, offset2;
+ size_t real_size;
+ int fd;
+ FILE *f;
+
+ /* Find the real file and the real offset into it. */
+ while (abfd->my_archive != NULL)
+ {
+ offset += abfd->origin;
+ abfd = abfd->my_archive;
+ }
+ f = bfd_cache_lookup (abfd);
+ fd = fileno (f);
+
+ /* Compute offsets and size for mmap and for the user's data. */
+ offset2 = offset % pagesize;
+ if (offset2 < 0)
+ abort ();
+ file_offset = offset - offset2;
+ real_size = offset + size - file_offset;
+ real_size = real_size + pagesize - 1;
+ real_size -= real_size % pagesize;
+
+ /* If we're re-using a memory region, make sure it's big enough. */
+ if (i->data && i->size < size)
+ {
+ munmap (i->data, i->size);
+ i->data = 0;
+ }
+ i->data = mmap (i->data, real_size,
+ writable ? PROT_WRITE | PROT_READ : PROT_READ,
+ (writable
+ ? MAP_FILE | MAP_PRIVATE
+ : MAP_FILE | MAP_SHARED),
+ fd, file_offset);
+ if (i->data == (PTR) -1)
+ {
+ /* An error happened. Report it, or try using malloc, or
+ something. */
+ bfd_set_error (bfd_error_system_call);
+ i->data = 0;
+ windowp->data = 0;
+ if (debug_windows)
+ fprintf (stderr, "\t\tmmap failed!\n");
+ return false;
+ }
+ if (debug_windows)
+ fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n",
+ (long) real_size, i->data, (long) offset2);
+ i->size = real_size;
+ windowp->data = (PTR) ((bfd_byte *) i->data + offset2);
+ windowp->size = size;
+ i->mapped = 1;
+ return true;
+ }
+ else if (debug_windows)
+ {
+ if (ok_to_map)
+ fprintf (stderr, "not mapping: data=%lx mapped=%d\n",
+ (unsigned long) i->data, (int) i->mapped);
+ else
+ fprintf (stderr, "not mapping: env var not set\n");
+ }
+#else
+ ok_to_map = 0;
+#endif
+
+#ifdef HAVE_MPROTECT
+ if (!writable)
+ {
+ size_to_alloc += pagesize - 1;
+ size_to_alloc -= size_to_alloc % pagesize;
+ }
+#endif
+ if (debug_windows)
+ fprintf (stderr, "\n\t%s(%6ld)",
+ i->data ? "realloc" : " malloc", (long) size_to_alloc);
+ i->data = (PTR) bfd_realloc (i->data, size_to_alloc);
+ if (debug_windows)
+ fprintf (stderr, "\t-> %p\n", i->data);
+ i->refcount = 1;
+ if (i->data == NULL)
+ {
+ if (size_to_alloc == 0)
+ return true;
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ if (bfd_seek (abfd, offset, SEEK_SET) != 0)
+ return false;
+ i->size = bfd_read (i->data, size, 1, abfd);
+ if (i->size != size)
+ return false;
+ i->mapped = 0;
+#ifdef HAVE_MPROTECT
+ if (!writable)
+ {
+ if (debug_windows)
+ fprintf (stderr, "\tmprotect (%p, %ld, PROT_READ)\n", i->data,
+ (long) i->size);
+ mprotect (i->data, i->size, PROT_READ);
+ }
+#endif
+ windowp->data = i->data;
+ windowp->size = i->size;
+ return true;
+}
+
+bfd_size_type
+bfd_write (ptr, size, nitems, abfd)
+ CONST PTR ptr;
+ bfd_size_type size;
+ bfd_size_type nitems;
+ bfd *abfd;
+{
+ long nwrote;
+
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ abort ();
+
+ nwrote = fwrite (ptr, 1, (size_t) (size * nitems),
+ bfd_cache_lookup (abfd));
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ if (nwrote > 0)
+ abfd->where += nwrote;
+#endif
+ if ((bfd_size_type) nwrote != size * nitems)
+ {
+#ifdef ENOSPC
+ if (nwrote >= 0)
+ errno = ENOSPC;
+#endif
+ bfd_set_error (bfd_error_system_call);
+ }
+ return nwrote;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_write_bigendian_4byte_int
+
+SYNOPSIS
+ void bfd_write_bigendian_4byte_int(bfd *abfd, int i);
+
+DESCRIPTION
+ 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
+bfd_write_bigendian_4byte_int (abfd, i)
+ bfd *abfd;
+ int i;
+{
+ bfd_byte buffer[4];
+ bfd_putb32(i, buffer);
+ if (bfd_write((PTR)buffer, 4, 1, abfd) != 4)
+ abort ();
+}
+
+long
+bfd_tell (abfd)
+ bfd *abfd;
+{
+ file_ptr ptr;
+
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ return abfd->where;
+
+ ptr = ftell (bfd_cache_lookup(abfd));
+
+ if (abfd->my_archive)
+ ptr -= abfd->origin;
+ abfd->where = ptr;
+ return ptr;
+}
+
+int
+bfd_flush (abfd)
+ bfd *abfd;
+{
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ return 0;
+ return fflush (bfd_cache_lookup(abfd));
+}
+
+/* Returns 0 for success, negative value for failure (in which case
+ bfd_get_error can retrieve the error code). */
+int
+bfd_stat (abfd, statbuf)
+ bfd *abfd;
+ struct stat *statbuf;
+{
+ FILE *f;
+ int result;
+
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ abort ();
+
+ f = bfd_cache_lookup (abfd);
+ if (f == NULL)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return -1;
+ }
+ result = fstat (fileno (f), statbuf);
+ if (result < 0)
+ bfd_set_error (bfd_error_system_call);
+ return result;
+}
+
+/* Returns 0 for success, nonzero for failure (in which case bfd_get_error
+ can retrieve the error code). */
+
+int
+bfd_seek (abfd, position, direction)
+ bfd *abfd;
+ file_ptr position;
+ int direction;
+{
+ int result;
+ FILE *f;
+ file_ptr file_position;
+ /* For the time being, a BFD may not seek to it's end. The problem
+ is that we don't easily have a way to recognize the end of an
+ element in an archive. */
+
+ BFD_ASSERT (direction == SEEK_SET || direction == SEEK_CUR);
+
+ if (direction == SEEK_CUR && position == 0)
+ return 0;
+
+ if ((abfd->flags & BFD_IN_MEMORY) != 0)
+ {
+ if (direction == SEEK_SET)
+ abfd->where = position;
+ else
+ abfd->where += position;
+ return 0;
+ }
+
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ if (abfd->format != bfd_archive && abfd->my_archive == 0)
+ {
+#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'
+ that the `where' field is correct. If we can go a while without
+ tripping the abort, we can probably safely disable this code,
+ so that the real optimizations happen. */
+ file_ptr where_am_i_now;
+ where_am_i_now = ftell (bfd_cache_lookup (abfd));
+ if (abfd->my_archive)
+ where_am_i_now -= abfd->origin;
+ if (where_am_i_now != abfd->where)
+ abort ();
+#endif
+ if (direction == SEEK_SET && position == abfd->where)
+ return 0;
+ }
+ else
+ {
+ /* We need something smarter to optimize access to archives.
+ Currently, anything inside an archive is read via the file
+ handle for the archive. Which means that a bfd_seek on one
+ component affects the `current position' in the archive, as
+ well as in any other component.
+
+ It might be sufficient to put a spike through the cache
+ abstraction, and look to the archive for the file position,
+ but I think we should try for something cleaner.
+
+ In the meantime, no optimization for archives. */
+ }
+#endif
+
+ f = bfd_cache_lookup (abfd);
+ file_position = position;
+ if (direction == SEEK_SET && abfd->my_archive != NULL)
+ file_position += abfd->origin;
+
+ result = fseek (f, file_position, direction);
+
+ if (result != 0)
+ {
+ /* Force redetermination of `where' field. */
+ bfd_tell (abfd);
+ bfd_set_error (bfd_error_system_call);
+ }
+ else
+ {
+#ifdef FILE_OFFSET_IS_CHAR_INDEX
+ /* Adjust `where' field. */
+ if (direction == SEEK_SET)
+ abfd->where = position;
+ else
+ abfd->where += position;
+#endif
+ }
+ return result;
+}
+
+/** The do-it-yourself (byte) sex-change kit */
+
+/* The middle letter e.g. get<b>short indicates Big or Little endian
+ target machine. It doesn't matter what the byte order of the host
+ machine is; these routines work for either. */
+
+/* FIXME: Should these take a count argument?
+ Answer (gnu@cygnus.com): No, but perhaps they should be inline
+ functions in swap.h #ifdef __GNUC__.
+ Gprof them later and find out. */
+
+/*
+FUNCTION
+ bfd_put_size
+FUNCTION
+ bfd_get_size
+
+DESCRIPTION
+ These macros as used for reading and writing raw data in
+ sections; each access (except for bytes) is vectored through
+ the target format of the BFD and mangled accordingly. The
+ 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, @file{libaout.h} defines <<GET_WORD>>
+ to either <<bfd_get_32>> or <<bfd_get_64>>.
+
+ In the put routines, @var{val} must be a <<bfd_vma>>. 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.
+
+.
+.{* Byte swapping macros for user section data. *}
+.
+.#define bfd_put_8(abfd, val, ptr) \
+. (*((unsigned char *)(ptr)) = (unsigned char)(val))
+.#define bfd_put_signed_8 \
+. bfd_put_8
+.#define bfd_get_8(abfd, ptr) \
+. (*(unsigned char *)(ptr))
+.#define bfd_get_signed_8(abfd, ptr) \
+. ((*(unsigned char *)(ptr) ^ 0x80) - 0x80)
+.
+.#define bfd_put_16(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_putx16, ((val),(ptr)))
+.#define bfd_put_signed_16 \
+. bfd_put_16
+.#define bfd_get_16(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx16, (ptr))
+.#define bfd_get_signed_16(abfd, ptr) \
+. BFD_SEND (abfd, bfd_getx_signed_16, (ptr))
+.
+.#define bfd_put_32(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_putx32, ((val),(ptr)))
+.#define bfd_put_signed_32 \
+. bfd_put_32
+.#define bfd_get_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx32, (ptr))
+.#define bfd_get_signed_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx_signed_32, (ptr))
+.
+.#define bfd_put_64(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_putx64, ((val), (ptr)))
+.#define bfd_put_signed_64 \
+. bfd_put_64
+.#define bfd_get_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx64, (ptr))
+.#define bfd_get_signed_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_getx_signed_64, (ptr))
+.
+*/
+
+/*
+FUNCTION
+ bfd_h_put_size
+ bfd_h_get_size
+
+DESCRIPTION
+ These macros have the same function as their <<bfd_get_x>>
+ 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.
+.
+.{* Byte swapping macros for file header data. *}
+.
+.#define bfd_h_put_8(abfd, val, ptr) \
+. bfd_put_8 (abfd, val, ptr)
+.#define bfd_h_put_signed_8(abfd, val, ptr) \
+. bfd_put_8 (abfd, val, ptr)
+.#define bfd_h_get_8(abfd, ptr) \
+. bfd_get_8 (abfd, ptr)
+.#define bfd_h_get_signed_8(abfd, ptr) \
+. bfd_get_signed_8 (abfd, ptr)
+.
+.#define bfd_h_put_16(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_h_putx16,(val,ptr))
+.#define bfd_h_put_signed_16 \
+. bfd_h_put_16
+.#define bfd_h_get_16(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx16,(ptr))
+.#define bfd_h_get_signed_16(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx_signed_16, (ptr))
+.
+.#define bfd_h_put_32(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_h_putx32,(val,ptr))
+.#define bfd_h_put_signed_32 \
+. bfd_h_put_32
+.#define bfd_h_get_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx32,(ptr))
+.#define bfd_h_get_signed_32(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx_signed_32, (ptr))
+.
+.#define bfd_h_put_64(abfd, val, ptr) \
+. BFD_SEND(abfd, bfd_h_putx64,(val, ptr))
+.#define bfd_h_put_signed_64 \
+. bfd_h_put_64
+.#define bfd_h_get_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx64,(ptr))
+.#define bfd_h_get_signed_64(abfd, ptr) \
+. BFD_SEND(abfd, bfd_h_getx_signed_64, (ptr))
+.
+*/
+
+/* 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 (((BFD_HOST_64_BIT)0x80000000) << 32)
+#define COERCE64(x) \
+ (((bfd_signed_vma) (x) ^ EIGHT_GAZILLION) - EIGHT_GAZILLION)
+
+bfd_vma
+bfd_getb16 (addr)
+ register const bfd_byte *addr;
+{
+ return (addr[0] << 8) | addr[1];
+}
+
+bfd_vma
+bfd_getl16 (addr)
+ register const bfd_byte *addr;
+{
+ return (addr[1] << 8) | addr[0];
+}
+
+bfd_signed_vma
+bfd_getb_signed_16 (addr)
+ register const bfd_byte *addr;
+{
+ return COERCE16((addr[0] << 8) | addr[1]);
+}
+
+bfd_signed_vma
+bfd_getl_signed_16 (addr)
+ register const bfd_byte *addr;
+{
+ return COERCE16((addr[1] << 8) | addr[0]);
+}
+
+void
+bfd_putb16 (data, addr)
+ bfd_vma data;
+ register bfd_byte *addr;
+{
+ addr[0] = (bfd_byte)(data >> 8);
+ addr[1] = (bfd_byte )data;
+}
+
+void
+bfd_putl16 (data, addr)
+ bfd_vma data;
+ register bfd_byte *addr;
+{
+ addr[0] = (bfd_byte )data;
+ addr[1] = (bfd_byte)(data >> 8);
+}
+
+bfd_vma
+bfd_getb32 (addr)
+ register const bfd_byte *addr;
+{
+ return (((((bfd_vma)addr[0] << 8) | addr[1]) << 8)
+ | addr[2]) << 8 | addr[3];
+}
+
+bfd_vma
+bfd_getl32 (addr)
+ register const bfd_byte *addr;
+{
+ return (((((bfd_vma)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0];
+}
+
+bfd_signed_vma
+bfd_getb_signed_32 (addr)
+ register const bfd_byte *addr;
+{
+ return COERCE32((((((bfd_vma)addr[0] << 8) | addr[1]) << 8)
+ | addr[2]) << 8 | addr[3]);
+}
+
+bfd_signed_vma
+bfd_getl_signed_32 (addr)
+ register const bfd_byte *addr;
+{
+ return COERCE32((((((bfd_vma)addr[3] << 8) | addr[2]) << 8)
+ | addr[1]) << 8 | addr[0]);
+}
+
+bfd_vma
+bfd_getb64 (addr)
+ register const bfd_byte *addr;
+{
+#ifdef BFD64
+ bfd_vma low, high;
+
+ high= ((((((((addr[0]) << 8) |
+ addr[1]) << 8) |
+ addr[2]) << 8) |
+ addr[3]) );
+
+ low = (((((((((bfd_vma)addr[4]) << 8) |
+ addr[5]) << 8) |
+ addr[6]) << 8) |
+ addr[7]));
+
+ return high << 32 | low;
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+}
+
+bfd_vma
+bfd_getl64 (addr)
+ register const bfd_byte *addr;
+{
+#ifdef BFD64
+ bfd_vma low, high;
+ high= (((((((addr[7] << 8) |
+ addr[6]) << 8) |
+ addr[5]) << 8) |
+ addr[4]));
+
+ low = ((((((((bfd_vma)addr[3] << 8) |
+ addr[2]) << 8) |
+ addr[1]) << 8) |
+ addr[0]) );
+
+ return high << 32 | low;
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+
+}
+
+bfd_signed_vma
+bfd_getb_signed_64 (addr)
+ register const bfd_byte *addr;
+{
+#ifdef BFD64
+ bfd_vma low, high;
+
+ high= ((((((((addr[0]) << 8) |
+ addr[1]) << 8) |
+ addr[2]) << 8) |
+ addr[3]) );
+
+ low = (((((((((bfd_vma)addr[4]) << 8) |
+ addr[5]) << 8) |
+ addr[6]) << 8) |
+ addr[7]));
+
+ return COERCE64(high << 32 | low);
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+}
+
+bfd_signed_vma
+bfd_getl_signed_64 (addr)
+ register const bfd_byte *addr;
+{
+#ifdef BFD64
+ bfd_vma low, high;
+ high= (((((((addr[7] << 8) |
+ addr[6]) << 8) |
+ addr[5]) << 8) |
+ addr[4]));
+
+ low = ((((((((bfd_vma)addr[3] << 8) |
+ addr[2]) << 8) |
+ addr[1]) << 8) |
+ addr[0]) );
+
+ return COERCE64(high << 32 | low);
+#else
+ BFD_FAIL();
+ return 0;
+#endif
+}
+
+void
+bfd_putb32 (data, addr)
+ bfd_vma data;
+ register bfd_byte *addr;
+{
+ addr[0] = (bfd_byte)(data >> 24);
+ addr[1] = (bfd_byte)(data >> 16);
+ addr[2] = (bfd_byte)(data >> 8);
+ addr[3] = (bfd_byte)data;
+}
+
+void
+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
+bfd_putb64 (data, addr)
+ bfd_vma data;
+ register bfd_byte *addr;
+{
+#ifdef BFD64
+ addr[0] = (bfd_byte)(data >> (7*8));
+ addr[1] = (bfd_byte)(data >> (6*8));
+ addr[2] = (bfd_byte)(data >> (5*8));
+ addr[3] = (bfd_byte)(data >> (4*8));
+ addr[4] = (bfd_byte)(data >> (3*8));
+ addr[5] = (bfd_byte)(data >> (2*8));
+ addr[6] = (bfd_byte)(data >> (1*8));
+ addr[7] = (bfd_byte)(data >> (0*8));
+#else
+ BFD_FAIL();
+#endif
+}
+
+void
+bfd_putl64 (data, addr)
+ bfd_vma data;
+ register bfd_byte *addr;
+{
+#ifdef BFD64
+ addr[7] = (bfd_byte)(data >> (7*8));
+ addr[6] = (bfd_byte)(data >> (6*8));
+ addr[5] = (bfd_byte)(data >> (5*8));
+ addr[4] = (bfd_byte)(data >> (4*8));
+ addr[3] = (bfd_byte)(data >> (3*8));
+ addr[2] = (bfd_byte)(data >> (2*8));
+ addr[1] = (bfd_byte)(data >> (1*8));
+ addr[0] = (bfd_byte)(data >> (0*8));
+#else
+ BFD_FAIL();
+#endif
+}
+
+/* Default implementation */
+
+boolean
+_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;
+ if ((bfd_size_type)(offset+count) > section->_raw_size
+ || bfd_seek(abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1
+ || bfd_read(location, (bfd_size_type)1, count, abfd) != count)
+ return (false); /* on error */
+ return (true);
+}
+
+boolean
+_bfd_generic_get_section_contents_in_window (abfd, section, w, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ bfd_window *w;
+ file_ptr offset;
+ bfd_size_type count;
+{
+#ifdef USE_MMAP
+ if (count == 0)
+ return true;
+ if (abfd->xvec->_bfd_get_section_contents != _bfd_generic_get_section_contents)
+ {
+ /* We don't know what changes the bfd's get_section_contents
+ method may have to make. So punt trying to map the file
+ window, and let get_section_contents do its thing. */
+ /* @@ FIXME : If the internal window has a refcount of 1 and was
+ allocated with malloc instead of mmap, just reuse it. */
+ bfd_free_window (w);
+ w->i = (bfd_window_internal *) bfd_zmalloc (sizeof (bfd_window_internal));
+ if (w->i == NULL)
+ return false;
+ w->i->data = (PTR) bfd_malloc ((size_t) count);
+ if (w->i->data == NULL)
+ {
+ free (w->i);
+ w->i = NULL;
+ return false;
+ }
+ w->i->mapped = 0;
+ w->i->refcount = 1;
+ w->size = w->i->size = count;
+ w->data = w->i->data;
+ return bfd_get_section_contents (abfd, section, w->data, offset, count);
+ }
+ if ((bfd_size_type) (offset+count) > section->_raw_size
+ || (bfd_get_file_window (abfd, section->filepos + offset, count, w, true)
+ == false))
+ return false;
+ return true;
+#else
+ abort ();
+#endif
+}
+
+/* This generic function can only be used in implementations where creating
+ NEW sections is disallowed. It is useful in patching existing sections
+ in read-write files, though. See other set_section_contents functions
+ to see why it doesn't work for new sections. */
+boolean
+_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_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
+
+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
+bfd_log2(x)
+ bfd_vma x;
+{
+ unsigned result = 0;
+ while ( (bfd_vma)(1<< result) < 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/contrib/gdb/bfd/libbfd.h b/contrib/gdb/bfd/libbfd.h
new file mode 100644
index 0000000..5cf504c
--- /dev/null
+++ b/contrib/gdb/bfd/libbfd.h
@@ -0,0 +1,735 @@
+/* libbfd.h -- Declarations used by bfd library *implementation*.
+ (This include file is not for users of the library.)
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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) \
+ ((( (this) + ((boundary) -1)) & (~((boundary)-1))))
+
+/* If you want to read and write large blocks, you might want to do it
+ in quanta of this amount */
+#define DEFAULT_BUFFERSIZE 8192
+
+/* Set a tdata field. Can't use the other macros for this, since they
+ do casts, and casting to the left of assignment isn't portable. */
+#define set_tdata(bfd, v) ((bfd)->tdata.any = (PTR) (v))
+
+/* If BFD_IN_MEMORY is set for a BFD, then the iostream fields points
+ to an instance of this structure. */
+
+struct bfd_in_memory
+{
+ /* Size of buffer. */
+ bfd_size_type size;
+ /* Buffer holding contents of BFD. */
+ bfd_byte *buffer;
+};
+
+/* tdata for an archive. For an input archive, cache
+ needs to be free()'d. For an output archive, symdefs do. */
+
+struct artdata {
+ file_ptr first_file_filepos;
+ /* Speed up searching the armap */
+ struct ar_cache *cache;
+ bfd *archive_head; /* Only interesting in output routines */
+ carsym *symdefs; /* the symdef entries */
+ symindex symdef_count; /* how many there are */
+ char *extended_names; /* clever intel extension */
+ /* 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,
+ just before we finish writing an
+ 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)
+
+/* Goes in bfd's arelt_data slot */
+struct areltdata {
+ char * arch_header; /* it's actually a string */
+ unsigned int parsed_size; /* octets of filesize not including ar_hdr */
+ char *filename; /* null-terminated */
+};
+
+#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
+
+extern PTR bfd_malloc PARAMS ((size_t));
+extern PTR bfd_realloc PARAMS ((PTR, size_t));
+extern PTR bfd_zmalloc PARAMS ((size_t));
+
+extern bfd_error_handler_type _bfd_error_handler;
+
+/* These routines allocate and free things on the BFD's obstack. */
+
+PTR bfd_alloc PARAMS ((bfd *abfd, size_t size));
+PTR bfd_zalloc PARAMS ((bfd *abfd, 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));
+
+#define bfd_release(x,y) (void) obstack_free(&(x->memory),y)
+
+bfd * _bfd_create_empty_archive_element_shell PARAMS ((bfd *obfd));
+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));
+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));
+extern boolean _bfd_construct_extended_name_table
+ PARAMS ((bfd *, boolean, char **, bfd_size_type *));
+boolean _bfd_write_archive_contents PARAMS ((bfd *abfd));
+boolean _bfd_compute_and_write_armap PARAMS ((bfd *, unsigned int elength));
+bfd *_bfd_get_elt_at_filepos PARAMS ((bfd *archive, file_ptr filepos));
+extern bfd *_bfd_generic_get_elt_at_index PARAMS ((bfd *, symindex));
+bfd * _bfd_new_bfd PARAMS ((void));
+
+boolean bfd_false PARAMS ((bfd *ignore));
+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 *_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));
+void bfd_bsd_truncate_arname PARAMS ((bfd *abfd, CONST char *filename,
+ char *hdr));
+void bfd_gnu_truncate_arname PARAMS ((bfd *abfd, CONST char *filename,
+ char *hdr));
+
+boolean bsd_write_armap PARAMS ((bfd *arch, unsigned int elength,
+ struct orl *map, unsigned int orl_count, int stridx));
+
+boolean coff_write_armap PARAMS ((bfd *arch, unsigned int elength,
+ struct orl *map, unsigned int orl_count, int stridx));
+
+extern PTR _bfd_generic_read_ar_hdr PARAMS ((bfd *));
+
+extern PTR _bfd_generic_read_ar_hdr_mag PARAMS ((bfd *, const char *));
+
+bfd * bfd_generic_openr_next_archived_file PARAMS ((bfd *archive,
+ bfd *last_file));
+
+int bfd_generic_stat_arch_elt PARAMS ((bfd *, struct stat *));
+
+#define _bfd_read_ar_hdr(abfd) \
+ BFD_SEND (abfd, _bfd_read_ar_hdr_fn, (abfd))
+
+/* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic). */
+
+#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));
+extern boolean _bfd_generic_get_section_contents_in_window
+ PARAMS ((bfd *, asection *, bfd_window *, file_ptr, bfd_size_type));
+
+/* 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_merge_private_bfd_data \
+ ((boolean (*) PARAMS ((bfd *, bfd *))) bfd_true)
+#define _bfd_generic_bfd_set_private_flags \
+ ((boolean (*) PARAMS ((bfd *, flagword))) bfd_true)
+#define _bfd_generic_bfd_copy_private_section_data \
+ ((boolean (*) PARAMS ((bfd *, asection *, bfd *, asection *))) bfd_true)
+#define _bfd_generic_bfd_copy_private_symbol_data \
+ ((boolean (*) PARAMS ((bfd *, asymbol *, bfd *, asymbol *))) bfd_true)
+#define _bfd_generic_bfd_print_private_bfd_data \
+ ((boolean (*) PARAMS ((bfd *, PTR))) 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_construct_extended_name_table \
+ ((boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
+ 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_read_ar_hdr bfd_nullvoidptr
+#define _bfd_noarchive_openr_next_archived_file \
+ ((bfd *(*) PARAMS ((bfd *, bfd *))) bfd_nullvoidptr)
+#define _bfd_noarchive_get_elt_at_index \
+ ((bfd *(*) PARAMS ((bfd *, symindex))) bfd_nullvoidptr)
+#define _bfd_noarchive_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define _bfd_noarchive_update_armap_timestamp bfd_false
+
+/* 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
+extern boolean _bfd_archive_bsd_construct_extended_name_table
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+#define _bfd_archive_bsd_truncate_arname bfd_bsd_truncate_arname
+#define _bfd_archive_bsd_write_armap bsd_write_armap
+#define _bfd_archive_bsd_read_ar_hdr _bfd_generic_read_ar_hdr
+#define _bfd_archive_bsd_openr_next_archived_file \
+ bfd_generic_openr_next_archived_file
+#define _bfd_archive_bsd_get_elt_at_index _bfd_generic_get_elt_at_index
+#define _bfd_archive_bsd_generic_stat_arch_elt \
+ bfd_generic_stat_arch_elt
+extern boolean _bfd_archive_bsd_update_armap_timestamp PARAMS ((bfd *));
+
+/* 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
+extern boolean _bfd_archive_coff_construct_extended_name_table
+ PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+#define _bfd_archive_coff_truncate_arname bfd_dont_truncate_arname
+#define _bfd_archive_coff_write_armap coff_write_armap
+#define _bfd_archive_coff_read_ar_hdr _bfd_generic_read_ar_hdr
+#define _bfd_archive_coff_openr_next_archived_file \
+ bfd_generic_openr_next_archived_file
+#define _bfd_archive_coff_get_elt_at_index _bfd_generic_get_elt_at_index
+#define _bfd_archive_coff_generic_stat_arch_elt \
+ bfd_generic_stat_arch_elt
+#define _bfd_archive_coff_update_armap_timestamp bfd_true
+
+/* 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)
+#define _bfd_nosymbols_read_minisymbols \
+ ((long (*) PARAMS ((bfd *, boolean, PTR *, unsigned int *))) _bfd_n1)
+#define _bfd_nosymbols_minisymbol_to_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, boolean, const PTR, asymbol *))) \
+ 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 \
+ ((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)
+#define _bfd_nolink_bfd_link_split_section \
+ ((boolean (*) PARAMS ((bfd *, struct sec *))) 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 *));
+
+/* Generic minisymbol routines. */
+extern long _bfd_generic_read_minisymbols
+ PARAMS ((bfd *, boolean, PTR *, unsigned int *));
+extern asymbol *_bfd_generic_minisymbol_to_symbol
+ PARAMS ((bfd *, boolean, const PTR, asymbol *));
+
+/* Find the nearest line using .stab/.stabstr sections. */
+extern boolean _bfd_stab_section_find_nearest_line
+ PARAMS ((bfd *, asymbol **, asection *, bfd_vma, boolean *, const char **,
+ const char **, unsigned int *, PTR *));
+
+/* 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 *));
+
+extern boolean _bfd_generic_link_split_section
+ PARAMS ((bfd *, struct sec *));
+
+/* 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 ((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 ((reloc_howto_type *, bfd *, bfd_vma, bfd_byte *));
+
+/* Create a string table. */
+extern struct bfd_strtab_hash *_bfd_stringtab_init PARAMS ((void));
+
+/* Create an XCOFF .debug section style string table. */
+extern struct bfd_strtab_hash *_bfd_xcoff_stringtab_init PARAMS ((void));
+
+/* Free a string table. */
+extern void _bfd_stringtab_free PARAMS ((struct bfd_strtab_hash *));
+
+/* Get the size of a string table. */
+extern bfd_size_type _bfd_stringtab_size PARAMS ((struct bfd_strtab_hash *));
+
+/* Add a string to a string table. */
+extern bfd_size_type _bfd_stringtab_add
+ PARAMS ((struct bfd_strtab_hash *, const char *, boolean hash,
+ boolean copy));
+
+/* Write out a string table. */
+extern boolean _bfd_stringtab_emit PARAMS ((bfd *, struct bfd_strtab_hash *));
+
+/* Macros to tell if bfds are read or write enabled.
+
+ Note that bfds open for read may be scribbled into if the fd passed
+ to bfd_fdopenr is actually open both for read and write
+ simultaneously. However an output bfd will never be open for
+ read. Therefore sometimes you want to check bfd_read_p or
+ !bfd_read_p, and only sometimes bfd_write_p.
+*/
+
+#define bfd_read_p(abfd) ((abfd)->direction == read_direction || (abfd)->direction == both_direction)
+#define bfd_write_p(abfd) ((abfd)->direction == write_direction || (abfd)->direction == both_direction)
+
+void bfd_assert PARAMS ((const char*,int));
+
+#define BFD_ASSERT(x) \
+{ if (!(x)) bfd_assert(__FILE__,__LINE__); }
+
+#define BFD_FAIL() \
+{ bfd_assert(__FILE__,__LINE__); }
+
+FILE * bfd_cache_lookup_worker PARAMS ((bfd *));
+
+extern bfd *bfd_last_cache;
+
+/* Now Steve, what's the story here? */
+#ifdef lint
+#define itos(x) "l"
+#define stoi(x) 1
+#else
+#define itos(x) ((char*)(x))
+#define stoi(x) ((int)(x))
+#endif
+
+/* 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[];
+
+/* Functions shared by the ECOFF and MIPS ELF backends, which have no
+ other common header files. */
+
+#if defined(__STDC__) || defined(ALMOST_STDC)
+struct ecoff_find_line;
+#endif
+
+extern boolean _bfd_ecoff_locate_line
+ PARAMS ((bfd *, asection *, bfd_vma, struct ecoff_debug_info * const,
+ const struct ecoff_debug_swap * const, struct ecoff_find_line *,
+ const char **, const char **, unsigned int *));
+extern boolean _bfd_ecoff_get_accumulated_pdr PARAMS ((PTR, bfd_byte *));
+extern boolean _bfd_ecoff_get_accumulated_sym PARAMS ((PTR, bfd_byte *));
+extern boolean _bfd_ecoff_get_accumulated_ss PARAMS ((PTR, bfd_byte *));
+
+extern bfd_vma _bfd_get_gp_value PARAMS ((bfd *));
+extern void _bfd_set_gp_value PARAMS ((bfd *, bfd_vma));
+
+/* And more follows */
+
+void
+bfd_write_bigendian_4byte_int PARAMS ((bfd *abfd, int i));
+
+unsigned int
+bfd_log2 PARAMS ((bfd_vma x));
+
+#define BFD_CACHE_MAX_OPEN 10
+extern bfd *bfd_last_cache;
+
+#define bfd_cache_lookup(x) \
+ ((x)==bfd_last_cache? \
+ (FILE*)(bfd_last_cache->iostream): \
+ bfd_cache_lookup_worker(x))
+boolean
+bfd_cache_init PARAMS ((bfd *abfd));
+
+boolean
+bfd_cache_close PARAMS ((bfd *abfd));
+
+FILE*
+bfd_open_file PARAMS ((bfd *abfd));
+
+FILE *
+bfd_cache_lookup_worker PARAMS ((bfd *abfd));
+
+#ifdef _BFD_MAKE_TABLE_bfd_reloc_code_real
+
+static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
+
+ "BFD_RELOC_64",
+ "BFD_RELOC_32",
+ "BFD_RELOC_26",
+ "BFD_RELOC_16",
+ "BFD_RELOC_14",
+ "BFD_RELOC_8",
+ "BFD_RELOC_64_PCREL",
+ "BFD_RELOC_32_PCREL",
+ "BFD_RELOC_24_PCREL",
+ "BFD_RELOC_16_PCREL",
+ "BFD_RELOC_12_PCREL",
+ "BFD_RELOC_8_PCREL",
+ "BFD_RELOC_32_GOT_PCREL",
+ "BFD_RELOC_16_GOT_PCREL",
+ "BFD_RELOC_8_GOT_PCREL",
+ "BFD_RELOC_32_GOTOFF",
+ "BFD_RELOC_16_GOTOFF",
+ "BFD_RELOC_LO16_GOTOFF",
+ "BFD_RELOC_HI16_GOTOFF",
+ "BFD_RELOC_HI16_S_GOTOFF",
+ "BFD_RELOC_8_GOTOFF",
+ "BFD_RELOC_32_PLT_PCREL",
+ "BFD_RELOC_24_PLT_PCREL",
+ "BFD_RELOC_16_PLT_PCREL",
+ "BFD_RELOC_8_PLT_PCREL",
+ "BFD_RELOC_32_PLTOFF",
+ "BFD_RELOC_16_PLTOFF",
+ "BFD_RELOC_LO16_PLTOFF",
+ "BFD_RELOC_HI16_PLTOFF",
+ "BFD_RELOC_HI16_S_PLTOFF",
+ "BFD_RELOC_8_PLTOFF",
+ "BFD_RELOC_68K_GLOB_DAT",
+ "BFD_RELOC_68K_JMP_SLOT",
+ "BFD_RELOC_68K_RELATIVE",
+ "BFD_RELOC_32_BASEREL",
+ "BFD_RELOC_16_BASEREL",
+ "BFD_RELOC_LO16_BASEREL",
+ "BFD_RELOC_HI16_BASEREL",
+ "BFD_RELOC_HI16_S_BASEREL",
+ "BFD_RELOC_8_BASEREL",
+ "BFD_RELOC_RVA",
+ "BFD_RELOC_8_FFnn",
+ "BFD_RELOC_32_PCREL_S2",
+ "BFD_RELOC_16_PCREL_S2",
+ "BFD_RELOC_23_PCREL_S2",
+ "BFD_RELOC_HI22",
+ "BFD_RELOC_LO10",
+ "BFD_RELOC_GPREL16",
+ "BFD_RELOC_GPREL32",
+ "BFD_RELOC_I960_CALLJ",
+ "BFD_RELOC_NONE",
+ "BFD_RELOC_SPARC_WDISP22",
+ "BFD_RELOC_SPARC22",
+ "BFD_RELOC_SPARC13",
+ "BFD_RELOC_SPARC_GOT10",
+ "BFD_RELOC_SPARC_GOT13",
+ "BFD_RELOC_SPARC_GOT22",
+ "BFD_RELOC_SPARC_PC10",
+ "BFD_RELOC_SPARC_PC22",
+ "BFD_RELOC_SPARC_WPLT30",
+ "BFD_RELOC_SPARC_COPY",
+ "BFD_RELOC_SPARC_GLOB_DAT",
+ "BFD_RELOC_SPARC_JMP_SLOT",
+ "BFD_RELOC_SPARC_RELATIVE",
+ "BFD_RELOC_SPARC_UA32",
+ "BFD_RELOC_SPARC_BASE13",
+ "BFD_RELOC_SPARC_BASE22",
+ "BFD_RELOC_SPARC_10",
+ "BFD_RELOC_SPARC_11",
+ "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_7",
+ "BFD_RELOC_SPARC_6",
+ "BFD_RELOC_SPARC_5",
+ "BFD_RELOC_ALPHA_GPDISP_HI16",
+ "BFD_RELOC_ALPHA_GPDISP_LO16",
+ "BFD_RELOC_ALPHA_LITERAL",
+ "BFD_RELOC_ALPHA_LITUSE",
+ "BFD_RELOC_ALPHA_HINT",
+ "BFD_RELOC_MIPS_JMP",
+ "BFD_RELOC_HI16",
+ "BFD_RELOC_HI16_S",
+ "BFD_RELOC_LO16",
+ "BFD_RELOC_PCREL_HI16_S",
+ "BFD_RELOC_PCREL_LO16",
+ "BFD_RELOC_MIPS_LITERAL",
+ "BFD_RELOC_MIPS_GOT16",
+ "BFD_RELOC_MIPS_CALL16",
+ "BFD_RELOC_MIPS_GOT_HI16",
+ "BFD_RELOC_MIPS_GOT_LO16",
+ "BFD_RELOC_MIPS_CALL_HI16",
+ "BFD_RELOC_MIPS_CALL_LO16",
+ "BFD_RELOC_386_GOT32",
+ "BFD_RELOC_386_PLT32",
+ "BFD_RELOC_386_COPY",
+ "BFD_RELOC_386_GLOB_DAT",
+ "BFD_RELOC_386_JUMP_SLOT",
+ "BFD_RELOC_386_RELATIVE",
+ "BFD_RELOC_386_GOTOFF",
+ "BFD_RELOC_386_GOTPC",
+ "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",
+ "BFD_RELOC_PPC_B26",
+ "BFD_RELOC_PPC_BA26",
+ "BFD_RELOC_PPC_TOC16",
+ "BFD_RELOC_PPC_B16",
+ "BFD_RELOC_PPC_B16_BRTAKEN",
+ "BFD_RELOC_PPC_B16_BRNTAKEN",
+ "BFD_RELOC_PPC_BA16",
+ "BFD_RELOC_PPC_BA16_BRTAKEN",
+ "BFD_RELOC_PPC_BA16_BRNTAKEN",
+ "BFD_RELOC_PPC_COPY",
+ "BFD_RELOC_PPC_GLOB_DAT",
+ "BFD_RELOC_PPC_JMP_SLOT",
+ "BFD_RELOC_PPC_RELATIVE",
+ "BFD_RELOC_PPC_LOCAL24PC",
+ "BFD_RELOC_PPC_EMB_NADDR32",
+ "BFD_RELOC_PPC_EMB_NADDR16",
+ "BFD_RELOC_PPC_EMB_NADDR16_LO",
+ "BFD_RELOC_PPC_EMB_NADDR16_HI",
+ "BFD_RELOC_PPC_EMB_NADDR16_HA",
+ "BFD_RELOC_PPC_EMB_SDAI16",
+ "BFD_RELOC_PPC_EMB_SDA2I16",
+ "BFD_RELOC_PPC_EMB_SDA2REL",
+ "BFD_RELOC_PPC_EMB_SDA21",
+ "BFD_RELOC_PPC_EMB_MRKREF",
+ "BFD_RELOC_PPC_EMB_RELSEC16",
+ "BFD_RELOC_PPC_EMB_RELST_LO",
+ "BFD_RELOC_PPC_EMB_RELST_HI",
+ "BFD_RELOC_PPC_EMB_RELST_HA",
+ "BFD_RELOC_PPC_EMB_BIT_FLD",
+ "BFD_RELOC_PPC_EMB_RELSDA",
+ "BFD_RELOC_CTOR",
+ "BFD_RELOC_ARM_PCREL_BRANCH",
+ "BFD_RELOC_ARM_IMMEDIATE",
+ "BFD_RELOC_ARM_OFFSET_IMM",
+ "BFD_RELOC_ARM_SHIFT_IMM",
+ "BFD_RELOC_ARM_SWI",
+ "BFD_RELOC_ARM_MULTI",
+ "BFD_RELOC_ARM_CP_OFF_IMM",
+ "BFD_RELOC_ARM_ADR_IMM",
+ "BFD_RELOC_ARM_LDR_IMM",
+ "BFD_RELOC_ARM_LITERAL",
+ "BFD_RELOC_ARM_IN_POOL",
+ "@@overflow: BFD_RELOC_UNUSED@@",
+};
+#endif
+
+reloc_howto_type *
+bfd_default_reloc_type_lookup
+ PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
+
+boolean
+bfd_generic_relax_section
+ PARAMS ((bfd *abfd,
+ asection *section,
+ struct bfd_link_info *,
+ boolean *));
+
+bfd_byte *
+
+bfd_generic_get_relocated_section_contents PARAMS ((bfd *abfd,
+ struct bfd_link_info *link_info,
+ struct bfd_link_order *link_order,
+ bfd_byte *data,
+ boolean relocateable,
+ asymbol **symbols));
+
+extern const bfd_arch_info_type bfd_default_arch_struct;
+boolean
+bfd_default_set_arch_mach PARAMS ((bfd *abfd,
+ enum bfd_architecture arch,
+ unsigned long mach));
+
+const bfd_arch_info_type *
+bfd_default_compatible
+ PARAMS ((const bfd_arch_info_type *a,
+ const bfd_arch_info_type *b));
+
+boolean
+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/contrib/gdb/bfd/libcoff-in.h b/contrib/gdb/bfd/libcoff-in.h
new file mode 100644
index 0000000..648ed80
--- /dev/null
+++ b/contrib/gdb/bfd/libcoff-in.h
@@ -0,0 +1,482 @@
+/* BFD COFF object file private structure.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+** NOTE: libcoff.h is a GENERATED file. Don't change it; instead,
+** change libcoff-in.h or coffcode.h.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfdlink.h"
+
+/* Object file tdata; access macros */
+
+#define coff_data(bfd) ((bfd)->tdata.coff_obj_data)
+#define exec_hdr(bfd) (coff_data(bfd)->hdr)
+#define obj_pe(bfd) (coff_data(bfd)->pe)
+#define obj_symbols(bfd) (coff_data(bfd)->symbols)
+#define obj_sym_filepos(bfd) (coff_data(bfd)->sym_filepos)
+
+#define obj_relocbase(bfd) (coff_data(bfd)->relocbase)
+#define obj_raw_syments(bfd) (coff_data(bfd)->raw_syments)
+#define obj_raw_syment_count(bfd) (coff_data(bfd)->raw_syment_count)
+#define obj_convert(bfd) (coff_data(bfd)->conversion_table)
+#define obj_conv_table_size(bfd) (coff_data(bfd)->conv_table_size)
+
+#define obj_coff_external_syms(bfd) (coff_data (bfd)->external_syms)
+#define obj_coff_keep_syms(bfd) (coff_data (bfd)->keep_syms)
+#define obj_coff_strings(bfd) (coff_data (bfd)->strings)
+#define obj_coff_keep_strings(bfd) (coff_data (bfd)->keep_strings)
+#define obj_coff_sym_hashes(bfd) (coff_data (bfd)->sym_hashes)
+
+#define obj_coff_local_toc_table(bfd) (coff_data(bfd)->local_toc_sym_map)
+
+/* `Tdata' information kept for COFF files. */
+
+typedef struct coff_tdata
+{
+ struct coff_symbol_struct *symbols; /* symtab for input bfd */
+ unsigned int *conversion_table;
+ int conv_table_size;
+ file_ptr sym_filepos;
+
+ struct coff_ptr_struct *raw_syments;
+ unsigned int raw_syment_count;
+
+ /* These are only valid once writing has begun */
+ long int relocbase;
+
+ /* These members communicate important constants about the symbol table
+ to GDB's symbol-reading code. These `constants' unfortunately vary
+ from coff implementation to implementation... */
+ unsigned local_n_btmask;
+ unsigned local_n_btshft;
+ unsigned local_n_tmask;
+ unsigned local_n_tshift;
+ unsigned local_symesz;
+ unsigned local_auxesz;
+ unsigned local_linesz;
+
+ /* The unswapped external symbols. May be NULL. Read by
+ _bfd_coff_get_external_symbols. */
+ PTR external_syms;
+ /* If this is true, the external_syms may not be freed. */
+ boolean keep_syms;
+
+ /* The string table. May be NULL. Read by
+ _bfd_coff_read_string_table. */
+ char *strings;
+ /* If this is true, the strings may not be freed. */
+ boolean keep_strings;
+
+ /* is this a PE format coff file */
+ int pe;
+ /* Used by the COFF backend linker. */
+ struct coff_link_hash_entry **sym_hashes;
+
+ /* used by the pe linker for PowerPC */
+ int *local_toc_sym_map;
+
+ struct bfd_link_info *link_info;
+
+ /* Used by coff_find_nearest_line. */
+ PTR line_info;
+} coff_data_type;
+
+/* Tdata for pe image files. */
+typedef struct pe_tdata
+{
+ coff_data_type coff;
+ struct internal_extra_pe_aouthdr pe_opthdr;
+ int dll;
+ int has_reloc_section;
+ boolean (*in_reloc_p) PARAMS((bfd *, reloc_howto_type *));
+ flagword real_flags;
+} pe_data_type;
+
+#define pe_data(bfd) ((bfd)->tdata.pe_obj_data)
+
+/* Tdata for XCOFF files. */
+
+struct xcoff_tdata
+{
+ /* Basic COFF information. */
+ coff_data_type coff;
+
+ /* True if a large a.out header should be generated. */
+ boolean full_aouthdr;
+
+ /* TOC value. */
+ bfd_vma toc;
+
+ /* Index of section holding TOC. */
+ int sntoc;
+
+ /* Index of section holding entry point. */
+ int snentry;
+
+ /* .text alignment from optional header. */
+ int text_align_power;
+
+ /* .data alignment from optional header. */
+ int data_align_power;
+
+ /* modtype from optional header. */
+ short modtype;
+
+ /* cputype from optional header. */
+ short cputype;
+
+ /* maxdata from optional header. */
+ bfd_size_type maxdata;
+
+ /* maxstack from optional header. */
+ bfd_size_type maxstack;
+
+ /* Used by the XCOFF backend linker. */
+ asection **csects;
+ unsigned long *debug_indices;
+ unsigned int import_file_id;
+};
+
+#define xcoff_data(abfd) ((abfd)->tdata.xcoff_obj_data)
+
+/* We take the address of the first element of a asymbol to ensure that the
+ * macro is only ever applied to an asymbol. */
+#define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd)))
+
+/* The used_by_bfd field of a section may be set to a pointer to this
+ structure. */
+
+struct coff_section_tdata
+{
+ /* The relocs, swapped into COFF internal form. This may be NULL. */
+ struct internal_reloc *relocs;
+ /* If this is true, the relocs entry may not be freed. */
+ boolean keep_relocs;
+ /* The section contents. This may be NULL. */
+ bfd_byte *contents;
+ /* If this is true, the contents entry may not be freed. */
+ boolean keep_contents;
+ /* Information cached by coff_find_nearest_line. */
+ bfd_vma offset;
+ unsigned int i;
+ const char *function;
+ int line_base;
+ /* Available for individual backends. */
+ PTR tdata;
+};
+
+/* An accessor macro for the coff_section_tdata structure. */
+#define coff_section_data(abfd, sec) \
+ ((struct coff_section_tdata *) (sec)->used_by_bfd)
+
+/* Tdata for sections in XCOFF files. This is used by the linker. */
+
+struct xcoff_section_tdata
+{
+ /* Used for XCOFF csects created by the linker; points to the real
+ XCOFF section which contains this csect. */
+ asection *enclosing;
+ /* The lineno_count field for the enclosing section, because we are
+ going to clobber it there. */
+ unsigned int lineno_count;
+ /* The first and one past the last symbol indices for symbols used
+ by this csect. */
+ unsigned long first_symndx;
+ unsigned long last_symndx;
+};
+
+/* An accessor macro the xcoff_section_tdata structure. */
+#define xcoff_section_data(abfd, sec) \
+ ((struct xcoff_section_tdata *) coff_section_data ((abfd), (sec))->tdata)
+
+/* COFF linker hash table entries. */
+
+struct coff_link_hash_entry
+{
+ struct bfd_link_hash_entry root;
+
+ /* Symbol index in output file. Set to -1 initially. Set to -2 if
+ there is a reloc against this symbol. */
+ long indx;
+
+ /* Symbol type. */
+ unsigned short type;
+
+ /* Symbol class. */
+ unsigned char class;
+
+ /* Number of auxiliary entries. */
+ char numaux;
+
+ /* BFD to take auxiliary entries from. */
+ bfd *auxbfd;
+
+ /* Pointer to array of auxiliary entries, if any. */
+ union internal_auxent *aux;
+};
+
+/* COFF linker hash table. */
+
+struct coff_link_hash_table
+{
+ struct bfd_link_hash_table root;
+};
+
+/* Look up an entry in a COFF linker hash table. */
+
+#define coff_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct coff_link_hash_entry *) \
+ bfd_link_hash_lookup (&(table)->root, (string), (create), \
+ (copy), (follow)))
+
+/* Traverse a COFF linker hash table. */
+
+#define coff_link_hash_traverse(table, func, info) \
+ (bfd_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the COFF linker hash table from a link_info structure. */
+
+#define coff_hash_table(p) ((struct coff_link_hash_table *) ((p)->hash))
+
+/* Functions in coffgen.c. */
+extern const bfd_target *coff_object_p PARAMS ((bfd *));
+extern struct sec *coff_section_from_bfd_index PARAMS ((bfd *, int));
+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 boolean coff_renumber_symbols PARAMS ((bfd *, int *));
+extern void coff_mangle_symbols 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 boolean _bfd_coff_get_external_symbols PARAMS ((bfd *));
+extern const char *_bfd_coff_read_string_table PARAMS ((bfd *));
+extern boolean _bfd_coff_free_symbols PARAMS ((bfd *));
+extern struct coff_ptr_struct *coff_get_normalized_symtab PARAMS ((bfd *));
+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));
+extern void coff_get_symbol_info PARAMS ((bfd *, asymbol *,
+ symbol_info *ret));
+extern asymbol *coff_bfd_make_debug_symbol PARAMS ((bfd *, PTR,
+ unsigned long));
+extern boolean coff_find_nearest_line PARAMS ((bfd *,
+ asection *,
+ asymbol **,
+ bfd_vma offset,
+ CONST char **filename_ptr,
+ 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 *, struct bfd_link_info *, boolean *));
+extern bfd_byte *bfd_coff_reloc16_get_relocated_section_contents
+ 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_link_info *,
+ asection *));
+extern void bfd_perform_slip PARAMS ((bfd *abfd, unsigned int slip,
+ asection *input_section,
+ bfd_vma val));
+
+/* Functions and types in cofflink.c. */
+
+#define STRING_SIZE_SIZE (4)
+
+/* We use a hash table to merge identical enum, struct, and union
+ definitions in the linker. */
+
+/* Information we keep for a single element (an enum value, a
+ structure or union field) in the debug merge hash table. */
+
+struct coff_debug_merge_element
+{
+ /* Next element. */
+ struct coff_debug_merge_element *next;
+
+ /* Name. */
+ const char *name;
+
+ /* Type. */
+ unsigned int type;
+
+ /* Symbol index for complex type. */
+ long tagndx;
+};
+
+/* A linked list of debug merge entries for a given name. */
+
+struct coff_debug_merge_type
+{
+ /* Next type with the same name. */
+ struct coff_debug_merge_type *next;
+
+ /* Class of type. */
+ int class;
+
+ /* Symbol index where this type is defined. */
+ long indx;
+
+ /* List of elements. */
+ struct coff_debug_merge_element *elements;
+};
+
+/* Information we store in the debug merge hash table. */
+
+struct coff_debug_merge_hash_entry
+{
+ struct bfd_hash_entry root;
+
+ /* A list of types with this name. */
+ struct coff_debug_merge_type *types;
+};
+
+/* The debug merge hash table. */
+
+struct coff_debug_merge_hash_table
+{
+ struct bfd_hash_table root;
+};
+
+/* Initialize a COFF debug merge hash table. */
+
+#define coff_debug_merge_hash_table_init(table) \
+ (bfd_hash_table_init (&(table)->root, _bfd_coff_debug_merge_hash_newfunc))
+
+/* Free a COFF debug merge hash table. */
+
+#define coff_debug_merge_hash_table_free(table) \
+ (bfd_hash_table_free (&(table)->root))
+
+/* Look up an entry in a COFF debug merge hash table. */
+
+#define coff_debug_merge_hash_lookup(table, string, create, copy) \
+ ((struct coff_debug_merge_hash_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* Information we keep for each section in the output file when doing
+ a relocateable link. */
+
+struct coff_link_section_info
+{
+ /* The relocs to be output. */
+ struct internal_reloc *relocs;
+ /* For each reloc against a global symbol whose index was not known
+ when the reloc was handled, the global hash table entry. */
+ struct coff_link_hash_entry **rel_hashes;
+};
+
+/* Information that we pass around while doing the final link step. */
+
+struct coff_final_link_info
+{
+ /* General link information. */
+ struct bfd_link_info *info;
+ /* Output BFD. */
+ bfd *output_bfd;
+ /* Used to indicate failure in traversal routine. */
+ boolean failed;
+ /* Hash table for long symbol names. */
+ struct bfd_strtab_hash *strtab;
+ /* When doing a relocateable link, an array of information kept for
+ each output section, indexed by the target_index field. */
+ struct coff_link_section_info *section_info;
+ /* Symbol index of last C_FILE symbol (-1 if none). */
+ long last_file_index;
+ /* Contents of last C_FILE symbol. */
+ struct internal_syment last_file;
+ /* Hash table used to merge debug information. */
+ struct coff_debug_merge_hash_table debug_merge;
+ /* Buffer large enough to hold swapped symbols of any input file. */
+ struct internal_syment *internal_syms;
+ /* Buffer large enough to hold sections of symbols of any input file. */
+ asection **sec_ptrs;
+ /* Buffer large enough to hold output indices of symbols of any
+ input file. */
+ long *sym_indices;
+ /* Buffer large enough to hold output symbols for any input file. */
+ bfd_byte *outsyms;
+ /* Buffer large enough to hold external line numbers for any input
+ section. */
+ bfd_byte *linenos;
+ /* Buffer large enough to hold any input section. */
+ bfd_byte *contents;
+ /* Buffer large enough to hold external relocs of any input section. */
+ bfd_byte *external_relocs;
+ /* Buffer large enough to hold swapped relocs of any input section. */
+ struct internal_reloc *internal_relocs;
+};
+
+extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+extern boolean _bfd_coff_link_hash_table_init
+ PARAMS ((struct coff_link_hash_table *, bfd *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create
+ PARAMS ((bfd *));
+extern const char *_bfd_coff_internal_syment_name
+ PARAMS ((bfd *, const struct internal_syment *, char *));
+extern boolean _bfd_coff_link_add_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_coff_final_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern struct internal_reloc *_bfd_coff_read_internal_relocs
+ PARAMS ((bfd *, asection *, boolean, bfd_byte *, boolean,
+ struct internal_reloc *));
+extern boolean _bfd_coff_generic_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
+
+extern struct bfd_hash_entry *_bfd_coff_debug_merge_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+extern boolean _bfd_coff_write_global_sym
+ PARAMS ((struct coff_link_hash_entry *, PTR));
+extern boolean _bfd_coff_link_input_bfd
+ PARAMS ((struct coff_final_link_info *, bfd *));
+extern boolean _bfd_coff_reloc_link_order
+ PARAMS ((bfd *, struct coff_final_link_info *, asection *,
+ struct bfd_link_order *));
+
+
+#define coff_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+/* Functions in xcofflink.c. */
+
+extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
+ PARAMS ((bfd *));
+extern boolean _bfd_xcoff_bfd_link_add_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_xcoff_bfd_final_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_ppc_xcoff_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
+
+/* And more taken from the source .. */
+
diff --git a/contrib/gdb/bfd/libcoff.h b/contrib/gdb/bfd/libcoff.h
new file mode 100644
index 0000000..daa39b5
--- /dev/null
+++ b/contrib/gdb/bfd/libcoff.h
@@ -0,0 +1,823 @@
+/* BFD COFF object file private structure.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+** NOTE: libcoff.h is a GENERATED file. Don't change it; instead,
+** change libcoff-in.h or coffcode.h.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfdlink.h"
+
+/* Object file tdata; access macros */
+
+#define coff_data(bfd) ((bfd)->tdata.coff_obj_data)
+#define exec_hdr(bfd) (coff_data(bfd)->hdr)
+#define obj_pe(bfd) (coff_data(bfd)->pe)
+#define obj_symbols(bfd) (coff_data(bfd)->symbols)
+#define obj_sym_filepos(bfd) (coff_data(bfd)->sym_filepos)
+
+#define obj_relocbase(bfd) (coff_data(bfd)->relocbase)
+#define obj_raw_syments(bfd) (coff_data(bfd)->raw_syments)
+#define obj_raw_syment_count(bfd) (coff_data(bfd)->raw_syment_count)
+#define obj_convert(bfd) (coff_data(bfd)->conversion_table)
+#define obj_conv_table_size(bfd) (coff_data(bfd)->conv_table_size)
+
+#define obj_coff_external_syms(bfd) (coff_data (bfd)->external_syms)
+#define obj_coff_keep_syms(bfd) (coff_data (bfd)->keep_syms)
+#define obj_coff_strings(bfd) (coff_data (bfd)->strings)
+#define obj_coff_keep_strings(bfd) (coff_data (bfd)->keep_strings)
+#define obj_coff_sym_hashes(bfd) (coff_data (bfd)->sym_hashes)
+
+#define obj_coff_local_toc_table(bfd) (coff_data(bfd)->local_toc_sym_map)
+
+/* `Tdata' information kept for COFF files. */
+
+typedef struct coff_tdata
+{
+ struct coff_symbol_struct *symbols; /* symtab for input bfd */
+ unsigned int *conversion_table;
+ int conv_table_size;
+ file_ptr sym_filepos;
+
+ struct coff_ptr_struct *raw_syments;
+ unsigned int raw_syment_count;
+
+ /* These are only valid once writing has begun */
+ long int relocbase;
+
+ /* These members communicate important constants about the symbol table
+ to GDB's symbol-reading code. These `constants' unfortunately vary
+ from coff implementation to implementation... */
+ unsigned local_n_btmask;
+ unsigned local_n_btshft;
+ unsigned local_n_tmask;
+ unsigned local_n_tshift;
+ unsigned local_symesz;
+ unsigned local_auxesz;
+ unsigned local_linesz;
+
+ /* The unswapped external symbols. May be NULL. Read by
+ _bfd_coff_get_external_symbols. */
+ PTR external_syms;
+ /* If this is true, the external_syms may not be freed. */
+ boolean keep_syms;
+
+ /* The string table. May be NULL. Read by
+ _bfd_coff_read_string_table. */
+ char *strings;
+ /* If this is true, the strings may not be freed. */
+ boolean keep_strings;
+
+ /* is this a PE format coff file */
+ int pe;
+ /* Used by the COFF backend linker. */
+ struct coff_link_hash_entry **sym_hashes;
+
+ /* used by the pe linker for PowerPC */
+ int *local_toc_sym_map;
+
+ struct bfd_link_info *link_info;
+
+ /* Used by coff_find_nearest_line. */
+ PTR line_info;
+} coff_data_type;
+
+/* Tdata for pe image files. */
+typedef struct pe_tdata
+{
+ coff_data_type coff;
+ struct internal_extra_pe_aouthdr pe_opthdr;
+ int dll;
+ int has_reloc_section;
+ boolean (*in_reloc_p) PARAMS((bfd *, reloc_howto_type *));
+ flagword real_flags;
+} pe_data_type;
+
+#define pe_data(bfd) ((bfd)->tdata.pe_obj_data)
+
+/* Tdata for XCOFF files. */
+
+struct xcoff_tdata
+{
+ /* Basic COFF information. */
+ coff_data_type coff;
+
+ /* True if a large a.out header should be generated. */
+ boolean full_aouthdr;
+
+ /* TOC value. */
+ bfd_vma toc;
+
+ /* Index of section holding TOC. */
+ int sntoc;
+
+ /* Index of section holding entry point. */
+ int snentry;
+
+ /* .text alignment from optional header. */
+ int text_align_power;
+
+ /* .data alignment from optional header. */
+ int data_align_power;
+
+ /* modtype from optional header. */
+ short modtype;
+
+ /* cputype from optional header. */
+ short cputype;
+
+ /* maxdata from optional header. */
+ bfd_size_type maxdata;
+
+ /* maxstack from optional header. */
+ bfd_size_type maxstack;
+
+ /* Used by the XCOFF backend linker. */
+ asection **csects;
+ unsigned long *debug_indices;
+ unsigned int import_file_id;
+};
+
+#define xcoff_data(abfd) ((abfd)->tdata.xcoff_obj_data)
+
+/* We take the address of the first element of a asymbol to ensure that the
+ * macro is only ever applied to an asymbol. */
+#define coffsymbol(asymbol) ((coff_symbol_type *)(&((asymbol)->the_bfd)))
+
+/* The used_by_bfd field of a section may be set to a pointer to this
+ structure. */
+
+struct coff_section_tdata
+{
+ /* The relocs, swapped into COFF internal form. This may be NULL. */
+ struct internal_reloc *relocs;
+ /* If this is true, the relocs entry may not be freed. */
+ boolean keep_relocs;
+ /* The section contents. This may be NULL. */
+ bfd_byte *contents;
+ /* If this is true, the contents entry may not be freed. */
+ boolean keep_contents;
+ /* Information cached by coff_find_nearest_line. */
+ bfd_vma offset;
+ unsigned int i;
+ const char *function;
+ int line_base;
+ /* Available for individual backends. */
+ PTR tdata;
+};
+
+/* An accessor macro for the coff_section_tdata structure. */
+#define coff_section_data(abfd, sec) \
+ ((struct coff_section_tdata *) (sec)->used_by_bfd)
+
+/* Tdata for sections in XCOFF files. This is used by the linker. */
+
+struct xcoff_section_tdata
+{
+ /* Used for XCOFF csects created by the linker; points to the real
+ XCOFF section which contains this csect. */
+ asection *enclosing;
+ /* The lineno_count field for the enclosing section, because we are
+ going to clobber it there. */
+ unsigned int lineno_count;
+ /* The first and one past the last symbol indices for symbols used
+ by this csect. */
+ unsigned long first_symndx;
+ unsigned long last_symndx;
+};
+
+/* An accessor macro the xcoff_section_tdata structure. */
+#define xcoff_section_data(abfd, sec) \
+ ((struct xcoff_section_tdata *) coff_section_data ((abfd), (sec))->tdata)
+
+/* COFF linker hash table entries. */
+
+struct coff_link_hash_entry
+{
+ struct bfd_link_hash_entry root;
+
+ /* Symbol index in output file. Set to -1 initially. Set to -2 if
+ there is a reloc against this symbol. */
+ long indx;
+
+ /* Symbol type. */
+ unsigned short type;
+
+ /* Symbol class. */
+ unsigned char class;
+
+ /* Number of auxiliary entries. */
+ char numaux;
+
+ /* BFD to take auxiliary entries from. */
+ bfd *auxbfd;
+
+ /* Pointer to array of auxiliary entries, if any. */
+ union internal_auxent *aux;
+};
+
+/* COFF linker hash table. */
+
+struct coff_link_hash_table
+{
+ struct bfd_link_hash_table root;
+};
+
+/* Look up an entry in a COFF linker hash table. */
+
+#define coff_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct coff_link_hash_entry *) \
+ bfd_link_hash_lookup (&(table)->root, (string), (create), \
+ (copy), (follow)))
+
+/* Traverse a COFF linker hash table. */
+
+#define coff_link_hash_traverse(table, func, info) \
+ (bfd_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the COFF linker hash table from a link_info structure. */
+
+#define coff_hash_table(p) ((struct coff_link_hash_table *) ((p)->hash))
+
+/* Functions in coffgen.c. */
+extern const bfd_target *coff_object_p PARAMS ((bfd *));
+extern struct sec *coff_section_from_bfd_index PARAMS ((bfd *, int));
+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 boolean coff_renumber_symbols PARAMS ((bfd *, int *));
+extern void coff_mangle_symbols 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 boolean _bfd_coff_get_external_symbols PARAMS ((bfd *));
+extern const char *_bfd_coff_read_string_table PARAMS ((bfd *));
+extern boolean _bfd_coff_free_symbols PARAMS ((bfd *));
+extern struct coff_ptr_struct *coff_get_normalized_symtab PARAMS ((bfd *));
+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));
+extern void coff_get_symbol_info PARAMS ((bfd *, asymbol *,
+ symbol_info *ret));
+extern asymbol *coff_bfd_make_debug_symbol PARAMS ((bfd *, PTR,
+ unsigned long));
+extern boolean coff_find_nearest_line PARAMS ((bfd *,
+ asection *,
+ asymbol **,
+ bfd_vma offset,
+ CONST char **filename_ptr,
+ 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 *, struct bfd_link_info *, boolean *));
+extern bfd_byte *bfd_coff_reloc16_get_relocated_section_contents
+ 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_link_info *,
+ asection *));
+extern void bfd_perform_slip PARAMS ((bfd *abfd, unsigned int slip,
+ asection *input_section,
+ bfd_vma val));
+
+/* Functions and types in cofflink.c. */
+
+#define STRING_SIZE_SIZE (4)
+
+/* We use a hash table to merge identical enum, struct, and union
+ definitions in the linker. */
+
+/* Information we keep for a single element (an enum value, a
+ structure or union field) in the debug merge hash table. */
+
+struct coff_debug_merge_element
+{
+ /* Next element. */
+ struct coff_debug_merge_element *next;
+
+ /* Name. */
+ const char *name;
+
+ /* Type. */
+ unsigned int type;
+
+ /* Symbol index for complex type. */
+ long tagndx;
+};
+
+/* A linked list of debug merge entries for a given name. */
+
+struct coff_debug_merge_type
+{
+ /* Next type with the same name. */
+ struct coff_debug_merge_type *next;
+
+ /* Class of type. */
+ int class;
+
+ /* Symbol index where this type is defined. */
+ long indx;
+
+ /* List of elements. */
+ struct coff_debug_merge_element *elements;
+};
+
+/* Information we store in the debug merge hash table. */
+
+struct coff_debug_merge_hash_entry
+{
+ struct bfd_hash_entry root;
+
+ /* A list of types with this name. */
+ struct coff_debug_merge_type *types;
+};
+
+/* The debug merge hash table. */
+
+struct coff_debug_merge_hash_table
+{
+ struct bfd_hash_table root;
+};
+
+/* Initialize a COFF debug merge hash table. */
+
+#define coff_debug_merge_hash_table_init(table) \
+ (bfd_hash_table_init (&(table)->root, _bfd_coff_debug_merge_hash_newfunc))
+
+/* Free a COFF debug merge hash table. */
+
+#define coff_debug_merge_hash_table_free(table) \
+ (bfd_hash_table_free (&(table)->root))
+
+/* Look up an entry in a COFF debug merge hash table. */
+
+#define coff_debug_merge_hash_lookup(table, string, create, copy) \
+ ((struct coff_debug_merge_hash_entry *) \
+ bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
+
+/* Information we keep for each section in the output file when doing
+ a relocateable link. */
+
+struct coff_link_section_info
+{
+ /* The relocs to be output. */
+ struct internal_reloc *relocs;
+ /* For each reloc against a global symbol whose index was not known
+ when the reloc was handled, the global hash table entry. */
+ struct coff_link_hash_entry **rel_hashes;
+};
+
+/* Information that we pass around while doing the final link step. */
+
+struct coff_final_link_info
+{
+ /* General link information. */
+ struct bfd_link_info *info;
+ /* Output BFD. */
+ bfd *output_bfd;
+ /* Used to indicate failure in traversal routine. */
+ boolean failed;
+ /* Hash table for long symbol names. */
+ struct bfd_strtab_hash *strtab;
+ /* When doing a relocateable link, an array of information kept for
+ each output section, indexed by the target_index field. */
+ struct coff_link_section_info *section_info;
+ /* Symbol index of last C_FILE symbol (-1 if none). */
+ long last_file_index;
+ /* Contents of last C_FILE symbol. */
+ struct internal_syment last_file;
+ /* Hash table used to merge debug information. */
+ struct coff_debug_merge_hash_table debug_merge;
+ /* Buffer large enough to hold swapped symbols of any input file. */
+ struct internal_syment *internal_syms;
+ /* Buffer large enough to hold sections of symbols of any input file. */
+ asection **sec_ptrs;
+ /* Buffer large enough to hold output indices of symbols of any
+ input file. */
+ long *sym_indices;
+ /* Buffer large enough to hold output symbols for any input file. */
+ bfd_byte *outsyms;
+ /* Buffer large enough to hold external line numbers for any input
+ section. */
+ bfd_byte *linenos;
+ /* Buffer large enough to hold any input section. */
+ bfd_byte *contents;
+ /* Buffer large enough to hold external relocs of any input section. */
+ bfd_byte *external_relocs;
+ /* Buffer large enough to hold swapped relocs of any input section. */
+ struct internal_reloc *internal_relocs;
+};
+
+extern struct bfd_hash_entry *_bfd_coff_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+extern boolean _bfd_coff_link_hash_table_init
+ PARAMS ((struct coff_link_hash_table *, bfd *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create
+ PARAMS ((bfd *));
+extern const char *_bfd_coff_internal_syment_name
+ PARAMS ((bfd *, const struct internal_syment *, char *));
+extern boolean _bfd_coff_link_add_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_coff_final_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern struct internal_reloc *_bfd_coff_read_internal_relocs
+ PARAMS ((bfd *, asection *, boolean, bfd_byte *, boolean,
+ struct internal_reloc *));
+extern boolean _bfd_coff_generic_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
+
+extern struct bfd_hash_entry *_bfd_coff_debug_merge_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+extern boolean _bfd_coff_write_global_sym
+ PARAMS ((struct coff_link_hash_entry *, PTR));
+extern boolean _bfd_coff_link_input_bfd
+ PARAMS ((struct coff_final_link_info *, bfd *));
+extern boolean _bfd_coff_reloc_link_order
+ PARAMS ((bfd *, struct coff_final_link_info *, asection *,
+ struct bfd_link_order *));
+
+
+#define coff_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+/* Functions in xcofflink.c. */
+
+extern struct bfd_link_hash_table *_bfd_xcoff_bfd_link_hash_table_create
+ PARAMS ((bfd *));
+extern boolean _bfd_xcoff_bfd_link_add_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_xcoff_bfd_final_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+extern boolean _bfd_ppc_xcoff_relocate_section
+ PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+ struct internal_reloc *, struct internal_syment *, asection **));
+
+/* And more taken from the source .. */
+
+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. */
+unsigned int fix_tag : 1;
+
+ /* Should the endidx field of this symbol be renumbered.
+ Created by coff_pointerize_aux. */
+unsigned int fix_end : 1;
+
+ /* Should the x_csect.x_scnlen field be renumbered.
+ Created by coff_pointerize_aux. */
+unsigned int fix_scnlen : 1;
+
+ /* Fix up an XCOFF C_BINCL/C_EINCL symbol. The value is the
+ index into the line number entries. Set by
+ coff_slurp_symbol_table. */
+unsigned int fix_line : 1;
+
+ /* The container for the symbol structure as read and translated
+ from the file. */
+
+union {
+ union internal_auxent auxent;
+ struct internal_syment syment;
+ } u;
+} combined_entry_type;
+
+
+ /* Each canonical asymbol really looks like this: */
+
+typedef struct coff_symbol_struct
+{
+ /* The actual symbol which the rest of BFD works with */
+asymbol symbol;
+
+ /* A pointer to the hidden information for this symbol */
+combined_entry_type *native;
+
+ /* A pointer to the linenumber information for this symbol */
+struct lineno_cache_entry *lineno;
+
+ /* Have the line numbers been relocated yet ? */
+boolean done_lineno;
+} coff_symbol_type;
+typedef struct
+{
+ void (*_bfd_coff_swap_aux_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ int type,
+ int class,
+ int indaux,
+ int numaux,
+ PTR in));
+
+ void (*_bfd_coff_swap_sym_in) PARAMS ((
+ bfd *abfd ,
+ PTR ext,
+ PTR in));
+
+ void (*_bfd_coff_swap_lineno_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+
+ unsigned int (*_bfd_coff_swap_aux_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ int type,
+ int class,
+ int indaux,
+ int numaux,
+ PTR ext));
+
+ unsigned int (*_bfd_coff_swap_sym_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR ext));
+
+ unsigned int (*_bfd_coff_swap_lineno_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR ext));
+
+ unsigned int (*_bfd_coff_swap_reloc_out) PARAMS ((
+ bfd *abfd,
+ PTR src,
+ PTR dst));
+
+ unsigned int (*_bfd_coff_swap_filehdr_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR out));
+
+ unsigned int (*_bfd_coff_swap_aouthdr_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR out));
+
+ unsigned int (*_bfd_coff_swap_scnhdr_out) PARAMS ((
+ bfd *abfd,
+ PTR in,
+ PTR out));
+
+ unsigned int _bfd_filhsz;
+ unsigned int _bfd_aoutsz;
+ unsigned int _bfd_scnhsz;
+ unsigned int _bfd_symesz;
+ unsigned int _bfd_auxesz;
+ unsigned int _bfd_relsz;
+ unsigned int _bfd_linesz;
+ boolean _bfd_coff_long_filenames;
+ void (*_bfd_coff_swap_filehdr_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+ void (*_bfd_coff_swap_aouthdr_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+ void (*_bfd_coff_swap_scnhdr_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+ void (*_bfd_coff_swap_reloc_in) PARAMS ((
+ bfd *abfd,
+ PTR ext,
+ PTR in));
+ boolean (*_bfd_coff_bad_format_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_filehdr));
+ boolean (*_bfd_coff_set_arch_mach_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_filehdr));
+ PTR (*_bfd_coff_mkobject_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_filehdr,
+ PTR internal_aouthdr));
+ flagword (*_bfd_styp_to_sec_flags_hook) PARAMS ((
+ bfd *abfd,
+ PTR internal_scnhdr,
+ const char *name));
+ void (*_bfd_set_alignment_hook) PARAMS ((
+ bfd *abfd,
+ asection *sec,
+ PTR internal_scnhdr));
+ boolean (*_bfd_coff_slurp_symbol_table) PARAMS ((
+ bfd *abfd));
+ boolean (*_bfd_coff_symname_in_debug) PARAMS ((
+ bfd *abfd,
+ struct internal_syment *sym));
+ boolean (*_bfd_coff_pointerize_aux_hook) PARAMS ((
+ bfd *abfd,
+ combined_entry_type *table_base,
+ combined_entry_type *symbol,
+ unsigned int indaux,
+ combined_entry_type *aux));
+ boolean (*_bfd_coff_print_aux) PARAMS ((
+ bfd *abfd,
+ FILE *file,
+ combined_entry_type *table_base,
+ combined_entry_type *symbol,
+ combined_entry_type *aux,
+ unsigned int indaux));
+ void (*_bfd_coff_reloc16_extra_cases) PARAMS ((
+ bfd *abfd,
+ 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,
+ arelent *r,
+ unsigned int shrink,
+ struct bfd_link_info *link_info));
+ boolean (*_bfd_coff_sym_is_global) PARAMS ((
+ bfd *abfd,
+ struct internal_syment *));
+ void (*_bfd_coff_compute_section_file_positions) PARAMS ((
+ bfd *abfd));
+ boolean (*_bfd_coff_start_final_link) PARAMS ((
+ bfd *output_bfd,
+ struct bfd_link_info *info));
+ boolean (*_bfd_coff_relocate_section) PARAMS ((
+ bfd *output_bfd,
+ struct bfd_link_info *info,
+ bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ struct internal_reloc *relocs,
+ struct internal_syment *syms,
+ asection **sections));
+ reloc_howto_type *(*_bfd_coff_rtype_to_howto) PARAMS ((
+ bfd *abfd,
+ asection *sec,
+ struct internal_reloc *rel,
+ struct coff_link_hash_entry *h,
+ struct internal_syment *sym,
+ bfd_vma *addendp));
+ boolean (*_bfd_coff_adjust_symndx) PARAMS ((
+ bfd *obfd,
+ struct bfd_link_info *info,
+ bfd *ibfd,
+ asection *sec,
+ struct internal_reloc *reloc,
+ boolean *adjustedp));
+ boolean (*_bfd_coff_link_add_one_symbol) PARAMS ((
+ struct bfd_link_info *info,
+ bfd *abfd,
+ const char *name,
+ flagword flags,
+ asection *section,
+ bfd_vma value,
+ const char *string,
+ boolean copy,
+ boolean collect,
+ struct bfd_link_hash_entry **hashp));
+
+} 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,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))
+
+#define bfd_coff_swap_lineno_in(a,e,i) \
+ ((coff_backend_info ( a)->_bfd_coff_swap_lineno_in) (a,e,i))
+
+#define bfd_coff_swap_reloc_out(abfd, i, o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_out) (abfd, i, o))
+
+#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(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))
+
+#define bfd_coff_swap_scnhdr_out(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_out) (abfd, i, o))
+
+#define bfd_coff_swap_filehdr_out(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_out) (abfd, i, o))
+
+#define bfd_coff_swap_aouthdr_out(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_out) (abfd, i, o))
+
+#define bfd_coff_filhsz(abfd) (coff_backend_info (abfd)->_bfd_filhsz)
+#define bfd_coff_aoutsz(abfd) (coff_backend_info (abfd)->_bfd_aoutsz)
+#define bfd_coff_scnhsz(abfd) (coff_backend_info (abfd)->_bfd_scnhsz)
+#define bfd_coff_symesz(abfd) (coff_backend_info (abfd)->_bfd_symesz)
+#define bfd_coff_auxesz(abfd) (coff_backend_info (abfd)->_bfd_auxesz)
+#define bfd_coff_relsz(abfd) (coff_backend_info (abfd)->_bfd_relsz)
+#define bfd_coff_linesz(abfd) (coff_backend_info (abfd)->_bfd_linesz)
+#define bfd_coff_long_filenames(abfd) (coff_backend_info (abfd)->_bfd_coff_long_filenames)
+#define bfd_coff_swap_filehdr_in(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_filehdr_in) (abfd, i, o))
+
+#define bfd_coff_swap_aouthdr_in(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_aouthdr_in) (abfd, i, o))
+
+#define bfd_coff_swap_scnhdr_in(abfd, i,o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_scnhdr_in) (abfd, i, o))
+
+#define bfd_coff_swap_reloc_in(abfd, i, o) \
+ ((coff_backend_info (abfd)->_bfd_coff_swap_reloc_in) (abfd, i, o))
+
+#define bfd_coff_bad_format_hook(abfd, filehdr) \
+ ((coff_backend_info (abfd)->_bfd_coff_bad_format_hook) (abfd, filehdr))
+
+#define bfd_coff_set_arch_mach_hook(abfd, filehdr)\
+ ((coff_backend_info (abfd)->_bfd_coff_set_arch_mach_hook) (abfd, filehdr))
+#define bfd_coff_mkobject_hook(abfd, filehdr, aouthdr)\
+ ((coff_backend_info (abfd)->_bfd_coff_mkobject_hook) (abfd, filehdr, aouthdr))
+
+#define bfd_coff_styp_to_sec_flags_hook(abfd, scnhdr, name)\
+ ((coff_backend_info (abfd)->_bfd_styp_to_sec_flags_hook) (abfd, scnhdr, name))
+
+#define bfd_coff_set_alignment_hook(abfd, sec, scnhdr)\
+ ((coff_backend_info (abfd)->_bfd_set_alignment_hook) (abfd, sec, scnhdr))
+
+#define bfd_coff_slurp_symbol_table(abfd)\
+ ((coff_backend_info (abfd)->_bfd_coff_slurp_symbol_table) (abfd))
+
+#define bfd_coff_symname_in_debug(abfd, sym)\
+ ((coff_backend_info (abfd)->_bfd_coff_symname_in_debug) (abfd, sym))
+
+#define bfd_coff_print_aux(abfd, file, base, symbol, aux, indaux)\
+ ((coff_backend_info (abfd)->_bfd_coff_print_aux)\
+ (abfd, file, base, symbol, aux, indaux))
+
+#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, link_info, link_order, reloc, data, src_ptr, dst_ptr))
+
+#define bfd_coff_reloc16_estimate(abfd, section, reloc, shrink, link_info)\
+ ((coff_backend_info (abfd)->_bfd_coff_reloc16_estimate)\
+ (abfd, section, reloc, shrink, link_info))
+
+#define bfd_coff_sym_is_global(abfd, sym)\
+ ((coff_backend_info (abfd)->_bfd_coff_sym_is_global)\
+ (abfd, sym))
+
+#define bfd_coff_compute_section_file_positions(abfd)\
+ ((coff_backend_info (abfd)->_bfd_coff_compute_section_file_positions)\
+ (abfd))
+
+#define bfd_coff_start_final_link(obfd, info)\
+ ((coff_backend_info (obfd)->_bfd_coff_start_final_link)\
+ (obfd, info))
+#define bfd_coff_relocate_section(obfd,info,ibfd,o,con,rel,isyms,secs)\
+ ((coff_backend_info (ibfd)->_bfd_coff_relocate_section)\
+ (obfd, info, ibfd, o, con, rel, isyms, secs))
+#define bfd_coff_rtype_to_howto(abfd, sec, rel, h, sym, addendp)\
+ ((coff_backend_info (abfd)->_bfd_coff_rtype_to_howto)\
+ (abfd, sec, rel, h, sym, addendp))
+#define bfd_coff_adjust_symndx(obfd, info, ibfd, sec, rel, adjustedp)\
+ ((coff_backend_info (abfd)->_bfd_coff_adjust_symndx)\
+ (obfd, info, ibfd, sec, rel, adjustedp))
+#define bfd_coff_link_add_one_symbol(info,abfd,name,flags,section,value,string,cp,coll,hashp)\
+ ((coff_backend_info (abfd)->_bfd_coff_link_add_one_symbol)\
+ (info, abfd, name, flags, section, value, string, cp, coll, hashp))
+
diff --git a/contrib/gdb/bfd/libecoff.h b/contrib/gdb/bfd/libecoff.h
new file mode 100644
index 0000000..169610d
--- /dev/null
+++ b/contrib/gdb/bfd/libecoff.h
@@ -0,0 +1,352 @@
+/* BFD ECOFF object file private structure.
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
+ the generic COFF code. */
+
+#define ecoff_backend(abfd) \
+ ((struct ecoff_backend_data *) (abfd)->xvec->backend_data)
+
+struct ecoff_backend_data
+{
+ /* COFF backend information. This must be the first field. */
+ bfd_coff_backend_data coff;
+ /* Supported architecture. */
+ enum bfd_architecture arch;
+ /* Initial portion of armap string. */
+ const char *armap_start;
+ /* 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. */
+ reloc_howto_type *constructor_reloc;
+ /* 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 (*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));
+ /* Do final adjustments to filehdr and aouthdr. */
+ boolean (*adjust_headers) PARAMS ((bfd *, struct internal_filehdr *,
+ struct internal_aouthdr *));
+ /* Read an element from an archive at a given file position. This
+ is needed because OSF/1 3.2 uses a weird archive format. */
+ bfd *(*get_elt_at_filepos) PARAMS ((bfd *, file_ptr));
+};
+
+/* This is the target specific information kept for ECOFF files. */
+
+#define ecoff_data(abfd) ((abfd)->tdata.ecoff_obj_data)
+
+typedef struct ecoff_tdata
+{
+ /* The reloc file position, set by
+ ecoff_compute_section_file_positions. */
+ file_ptr reloc_filepos;
+
+ /* 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
+ existing file, not for one we are creating. */
+ unsigned long text_start;
+ unsigned long text_end;
+
+ /* The cached gp value. This is used when relocating. */
+ bfd_vma gp;
+
+ /* The maximum size of objects to optimize using gp. This is
+ typically set by the -G option to the compiler, assembler or
+ linker. */
+ unsigned int gp_size;
+
+ /* The register masks. When linking, all the masks found in the
+ input files are combined into the masks of the output file.
+ These are not all used for all targets, but that's OK, because
+ the relevant ones are the only ones swapped in and out. */
+ unsigned long gprmask;
+ unsigned long fprmask;
+ unsigned long cprmask[4];
+
+ /* The ECOFF symbolic debugging information. */
+ struct ecoff_debug_info debug_info;
+
+ /* The unswapped ECOFF symbolic information. */
+ PTR raw_syments;
+
+ /* 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;
+
+ /* True if a warning that multiple global pointer values are
+ needed in the output binary was issued already. */
+ boolean issued_multiple_gp_warning;
+
+ /* Used by find_nearest_line entry point. The structure could be
+ included directly in this one, but there's no point to wasting
+ the memory just for the infrequently called find_nearest_line. */
+ struct ecoff_find_line *find_line_info;
+
+} ecoff_data_type;
+
+/* Each canonical asymbol really looks like this. */
+
+typedef struct ecoff_symbol_struct
+{
+ /* The actual symbol which the rest of BFD works with */
+ asymbol symbol;
+
+ /* The fdr for this symbol. */
+ FDR *fdr;
+
+ /* true if this is a local symbol rather than an external one. */
+ boolean local;
+
+ /* A pointer to the unswapped hidden information for this symbol.
+ This is either a struct sym_ext or a struct ext_ext, depending on
+ the value of the local field above. */
+ PTR native;
+} ecoff_symbol_type;
+
+/* We take the address of the first element of a asymbol to ensure that the
+ macro is only ever applied to an asymbol. */
+#define ecoffsymbol(asymbol) ((ecoff_symbol_type *) (&((asymbol)->the_bfd)))
+
+/* We need to save the index of an external symbol when we write it
+ out so that can set the symbol index correctly when we write out
+ the relocs. */
+#define ecoff_get_sym_index(symbol) ((symbol)->udata.i)
+#define ecoff_set_sym_index(symbol, idx) ((symbol)->udata.i = (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;
+
+ /* When producing an executable (i.e., final, non-relocatable link)
+ on the Alpha, we may need to use multiple global pointer values
+ to span the entire .lita section. In essence, we allow each
+ input .lita section to have its own gp value. To support this,
+ we need to keep track of the gp values that we picked for each
+ input .lita section . */
+ bfd_vma gp;
+};
+
+/* 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 _bfd_ecoff_mkobject PARAMS ((bfd *));
+
+/* Read in the ECOFF symbolic debugging information. */
+extern boolean _bfd_ecoff_slurp_symbolic_info
+ PARAMS ((bfd *, asection *, struct ecoff_debug_info *));
+
+/* Generic ECOFF BFD backend vectors. */
+
+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));
+
+#define _bfd_ecoff_bfd_link_split_section _bfd_generic_link_split_section
+
+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
+
+#define _bfd_ecoff_bfd_copy_private_symbol_data \
+ _bfd_generic_bfd_copy_private_symbol_data
+
+#define _bfd_ecoff_bfd_print_private_bfd_data \
+ _bfd_generic_bfd_print_private_bfd_data
+
+#define _bfd_ecoff_bfd_merge_private_bfd_data \
+ _bfd_generic_bfd_merge_private_bfd_data
+
+#define _bfd_ecoff_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+extern boolean _bfd_ecoff_slurp_armap PARAMS ((bfd *abfd));
+#define _bfd_ecoff_slurp_extended_name_table _bfd_slurp_extended_name_table
+#define _bfd_ecoff_construct_extended_name_table \
+ _bfd_archive_bsd_construct_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_read_ar_hdr _bfd_generic_read_ar_hdr
+#define _bfd_ecoff_openr_next_archived_file \
+ bfd_generic_openr_next_archived_file
+#define _bfd_ecoff_get_elt_at_index _bfd_generic_get_elt_at_index
+#define _bfd_ecoff_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define _bfd_ecoff_update_armap_timestamp bfd_true
+
+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 *));
+extern boolean _bfd_ecoff_bfd_is_local_label
+ PARAMS ((bfd *, asymbol *));
+#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_read_minisymbols _bfd_generic_read_minisymbols
+#define _bfd_ecoff_minisymbol_to_symbol _bfd_generic_minisymbol_to_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 _bfd_ecoff_mkobject_hook PARAMS ((bfd *, PTR filehdr, PTR aouthdr));
+#define _bfd_ecoff_set_alignment_hook \
+ ((void (*) PARAMS ((bfd *, asection *, PTR))) bfd_void)
+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, const char *name));
+extern boolean _bfd_ecoff_slurp_symbol_table PARAMS ((bfd *abfd));
+
+/* ECOFF auxiliary information swapping routines. These are the same
+ for all ECOFF targets, so they are defined in ecofflink.c. */
+
+extern void _bfd_ecoff_swap_tir_in
+ PARAMS ((int, const struct tir_ext *, TIR *));
+extern void _bfd_ecoff_swap_tir_out
+ PARAMS ((int, const TIR *, struct tir_ext *));
+extern void _bfd_ecoff_swap_rndx_in
+ PARAMS ((int, const struct rndx_ext *, RNDXR *));
+extern void _bfd_ecoff_swap_rndx_out
+ PARAMS ((int, const RNDXR *, struct rndx_ext *));
diff --git a/contrib/gdb/bfd/libhppa.h b/contrib/gdb/bfd/libhppa.h
new file mode 100644
index 0000000..fa97b68
--- /dev/null
+++ b/contrib/gdb/bfd/libhppa.h
@@ -0,0 +1,549 @@
+/* HP PA-RISC SOM object file format: definitions internal to BFD.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _HPPA_H
+#define _HPPA_H
+
+#define BYTES_IN_WORD 4
+#define PA_PAGESIZE 0x1000
+
+#ifndef INLINE
+#ifdef __GNUC__
+#define INLINE inline
+#else
+#define INLINE
+#endif /* GNU C? */
+#endif /* INLINE */
+
+/* The PA instruction set variants. */
+enum pa_arch {pa10 = 10, pa11 = 11, pa20 = 20};
+
+/* HP PA-RISC relocation types */
+
+enum hppa_reloc_field_selector_type
+ {
+ R_HPPA_FSEL = 0x0,
+ R_HPPA_LSSEL = 0x1,
+ R_HPPA_RSSEL = 0x2,
+ R_HPPA_LSEL = 0x3,
+ R_HPPA_RSEL = 0x4,
+ R_HPPA_LDSEL = 0x5,
+ R_HPPA_RDSEL = 0x6,
+ R_HPPA_LRSEL = 0x7,
+ R_HPPA_RRSEL = 0x8,
+ R_HPPA_NSEL = 0x9,
+ R_HPPA_NLSEL = 0xa,
+ R_HPPA_NLRSEL = 0xb,
+ R_HPPA_PSEL = 0xc,
+ R_HPPA_LPSEL = 0xd,
+ R_HPPA_RPSEL = 0xe,
+ R_HPPA_TSEL = 0xf,
+ R_HPPA_LTSEL = 0x10,
+ R_HPPA_RTSEL = 0x11
+ };
+
+/* /usr/include/reloc.h defines these to constants. We want to use
+ them in enums, so #undef them before we start using them. We might
+ be able to fix this another way by simply managing not to include
+ /usr/include/reloc.h, but currently GDB picks up these defines
+ somewhere. */
+#undef e_fsel
+#undef e_lssel
+#undef e_rssel
+#undef e_lsel
+#undef e_rsel
+#undef e_ldsel
+#undef e_rdsel
+#undef e_lrsel
+#undef e_rrsel
+#undef e_nsel
+#undef e_nlsel
+#undef e_nlrsel
+#undef e_psel
+#undef e_lpsel
+#undef e_rpsel
+#undef e_tsel
+#undef e_ltsel
+#undef e_rtsel
+#undef e_one
+#undef e_two
+#undef e_pcrel
+#undef e_con
+#undef e_plabel
+#undef e_abs
+
+/* for compatibility */
+enum hppa_reloc_field_selector_type_alt
+ {
+ e_fsel = R_HPPA_FSEL,
+ e_lssel = R_HPPA_LSSEL,
+ e_rssel = R_HPPA_RSSEL,
+ e_lsel = R_HPPA_LSEL,
+ e_rsel = R_HPPA_RSEL,
+ e_ldsel = R_HPPA_LDSEL,
+ e_rdsel = R_HPPA_RDSEL,
+ e_lrsel = R_HPPA_LRSEL,
+ e_rrsel = R_HPPA_RRSEL,
+ e_nsel = R_HPPA_NSEL,
+ e_nlsel = R_HPPA_NLSEL,
+ e_nlrsel = R_HPPA_NLRSEL,
+ e_psel = R_HPPA_PSEL,
+ e_lpsel = R_HPPA_LPSEL,
+ e_rpsel = R_HPPA_RPSEL,
+ e_tsel = R_HPPA_TSEL,
+ e_ltsel = R_HPPA_LTSEL,
+ e_rtsel = R_HPPA_RTSEL
+ };
+
+enum hppa_reloc_expr_type
+ {
+ R_HPPA_E_ONE = 0,
+ R_HPPA_E_TWO = 1,
+ R_HPPA_E_PCREL = 2,
+ R_HPPA_E_CON = 3,
+ R_HPPA_E_PLABEL = 7,
+ R_HPPA_E_ABS = 18
+ };
+
+/* for compatibility */
+enum hppa_reloc_expr_type_alt
+ {
+ e_one = R_HPPA_E_ONE,
+ e_two = R_HPPA_E_TWO,
+ e_pcrel = R_HPPA_E_PCREL,
+ e_con = R_HPPA_E_CON,
+ e_plabel = R_HPPA_E_PLABEL,
+ e_abs = R_HPPA_E_ABS
+ };
+
+
+/* Relocations for function calls must be accompanied by parameter
+ relocation bits. These bits describe exactly where the caller has
+ placed the function's arguments and where it expects to find a return
+ value.
+
+ Both ELF and SOM encode this information within the addend field
+ of the call relocation. (Note this could break very badly if one
+ was to make a call like bl foo + 0x12345678).
+
+ The high order 10 bits contain parameter relocation information,
+ the low order 22 bits contain the constant offset. */
+
+#define HPPA_R_ARG_RELOC(a) (((a) >> 22) & 0x3FF)
+#define HPPA_R_CONSTANT(a) ((((int)(a)) << 10) >> 10)
+#define HPPA_R_ADDEND(r,c) (((r) << 22) + ((c) & 0x3FFFFF))
+
+/* Some functions to manipulate PA instructions. */
+static INLINE unsigned int
+assemble_3 (x)
+ unsigned int x;
+{
+ return (((x & 1) << 2) | ((x & 6) >> 1)) & 7;
+}
+
+static INLINE void
+dis_assemble_3 (x, r)
+ unsigned int x;
+ unsigned int *r;
+{
+ *r = (((x & 4) >> 2) | ((x & 3) << 1)) & 7;
+}
+
+static INLINE unsigned int
+assemble_12 (x, y)
+ unsigned int x, y;
+{
+ return (((y & 1) << 11) | ((x & 1) << 10) | ((x & 0x7fe) >> 1)) & 0xfff;
+}
+
+static INLINE void
+dis_assemble_12 (as12, x, y)
+ unsigned int as12;
+ unsigned int *x, *y;
+{
+ *y = (as12 & 0x800) >> 11;
+ *x = ((as12 & 0x3ff) << 1) | ((as12 & 0x400) >> 10);
+}
+
+static INLINE unsigned long
+assemble_17 (x, y, z)
+ unsigned int x, y, z;
+{
+ unsigned long temp;
+
+ temp = ((z & 1) << 16) |
+ ((x & 0x1f) << 11) |
+ ((y & 1) << 10) |
+ ((y & 0x7fe) >> 1);
+ return temp & 0x1ffff;
+}
+
+static INLINE void
+dis_assemble_17 (as17, x, y, z)
+ unsigned int as17;
+ unsigned int *x, *y, *z;
+{
+
+ *z = (as17 & 0x10000) >> 16;
+ *x = (as17 & 0x0f800) >> 11;
+ *y = (((as17 & 0x00400) >> 10) | ((as17 & 0x3ff) << 1)) & 0x7ff;
+}
+
+static INLINE unsigned long
+assemble_21 (x)
+ unsigned int x;
+{
+ unsigned long temp;
+
+ temp = ((x & 1) << 20) |
+ ((x & 0xffe) << 8) |
+ ((x & 0xc000) >> 7) |
+ ((x & 0x1f0000) >> 14) |
+ ((x & 0x003000) >> 12);
+ return temp & 0x1fffff;
+}
+
+static INLINE void
+dis_assemble_21 (as21, x)
+ unsigned int as21, *x;
+{
+ unsigned long temp;
+
+
+ temp = (as21 & 0x100000) >> 20;
+ temp |= (as21 & 0x0ffe00) >> 8;
+ temp |= (as21 & 0x000180) << 7;
+ temp |= (as21 & 0x00007c) << 14;
+ temp |= (as21 & 0x000003) << 12;
+ *x = temp;
+}
+
+static INLINE unsigned long
+sign_extend (x, len)
+ unsigned int x, len;
+{
+ return (int)(x >> (len - 1) ? (-1 << len) | x : x);
+}
+
+static INLINE unsigned int
+ones (n)
+ int n;
+{
+ unsigned int len_ones;
+ int i;
+
+ i = 0;
+ len_ones = 0;
+ while (i < n)
+ {
+ len_ones = (len_ones << 1) | 1;
+ i++;
+ }
+
+ return len_ones;
+}
+
+static INLINE void
+sign_unext (x, len, result)
+ unsigned int x, len;
+ unsigned int *result;
+{
+ unsigned int len_ones;
+
+ len_ones = ones (len);
+
+ *result = x & len_ones;
+}
+
+static INLINE unsigned long
+low_sign_extend (x, len)
+ unsigned int x, len;
+{
+ return (int)((x & 0x1 ? (-1 << (len - 1)) : 0) | x >> 1);
+}
+
+static INLINE void
+low_sign_unext (x, len, result)
+ unsigned int x, len;
+ unsigned int *result;
+{
+ unsigned int temp;
+ unsigned int sign;
+ unsigned int rest;
+ unsigned int one_bit_at_len;
+ unsigned int len_ones;
+
+ len_ones = ones (len);
+ one_bit_at_len = 1 << (len - 1);
+
+ sign_unext (x, len, &temp);
+ sign = temp & one_bit_at_len;
+ sign >>= (len - 1);
+
+ rest = temp & (len_ones ^ one_bit_at_len);
+ rest <<= 1;
+
+ *result = rest | sign;
+}
+
+/* Handle field selectors for PA instructions. */
+
+static INLINE unsigned long
+hppa_field_adjust (value, constant_value, r_field)
+ unsigned long value;
+ unsigned long constant_value;
+ unsigned short r_field;
+{
+ switch (r_field)
+ {
+ case e_fsel: /* F : no change */
+ case e_nsel: /* N : no change */
+ value += constant_value;
+ break;
+
+ case e_lssel: /* LS : if (bit 21) then add 0x800
+ arithmetic shift right 11 bits */
+ value += constant_value;
+ if (value & 0x00000400)
+ value += 0x800;
+ value = (value & 0xfffff800) >> 11;
+ break;
+
+ case e_rssel: /* RS : Sign extend from bit 21 */
+ value += constant_value;
+ if (value & 0x00000400)
+ value |= 0xfffff800;
+ else
+ value &= 0x7ff;
+ break;
+
+ case e_lsel: /* L : Arithmetic shift right 11 bits */
+ case e_nlsel: /* NL : Arithmetic shift right 11 bits */
+ value += constant_value;
+ value = (value & 0xfffff800) >> 11;
+ break;
+
+ case e_rsel: /* R : Set bits 0-20 to zero */
+ value += constant_value;
+ value = value & 0x7ff;
+ break;
+
+ case e_ldsel: /* LD : Add 0x800, arithmetic shift
+ right 11 bits */
+ value += constant_value;
+ value += 0x800;
+ value = (value & 0xfffff800) >> 11;
+ break;
+
+ case e_rdsel: /* RD : Set bits 0-20 to one */
+ value += constant_value;
+ value |= 0xfffff800;
+ break;
+
+ case e_lrsel: /* LR : L with "rounded" constant */
+ case e_nlrsel: /* NLR : NL with "rounded" constant */
+ value = value + ((constant_value + 0x1000) & 0xffffe000);
+ value = (value & 0xfffff800) >> 11;
+ break;
+
+ case e_rrsel: /* RR : R with "rounded" constant */
+ value = value + ((constant_value + 0x1000) & 0xffffe000);
+ value = (value & 0x7ff) + constant_value - ((constant_value + 0x1000) & 0xffffe000);
+ break;
+
+ default:
+ abort ();
+ }
+ return value;
+
+}
+
+/* PA-RISC OPCODES */
+#define get_opcode(insn) ((insn) & 0xfc000000) >> 26
+
+/* FIXME: this list is incomplete. It should also be an enumerated
+ type rather than #defines. */
+
+#define LDO 0x0d
+#define LDB 0x10
+#define LDH 0x11
+#define LDW 0x12
+#define LDWM 0x13
+#define STB 0x18
+#define STH 0x19
+#define STW 0x1a
+#define STWM 0x1b
+#define COMICLR 0x24
+#define SUBI 0x25
+#define SUBIO 0x25
+#define ADDIT 0x2c
+#define ADDITO 0x2c
+#define ADDI 0x2d
+#define ADDIO 0x2d
+#define LDIL 0x08
+#define ADDIL 0x0a
+
+#define MOVB 0x32
+#define MOVIB 0x33
+#define COMBT 0x20
+#define COMBF 0x22
+#define COMIBT 0x21
+#define COMIBF 0x23
+#define ADDBT 0x28
+#define ADDBF 0x2a
+#define ADDIBT 0x29
+#define ADDIBF 0x2b
+#define BVB 0x30
+#define BB 0x31
+
+#define BL 0x3a
+#define BLE 0x39
+#define BE 0x38
+
+
+/* Given a machine instruction, return its format.
+
+ FIXME: opcodes which do not map to a known format
+ should return an error of some sort. */
+
+static INLINE char
+bfd_hppa_insn2fmt (insn)
+ unsigned long insn;
+{
+ char fmt = -1;
+ unsigned char op = get_opcode (insn);
+
+ switch (op)
+ {
+ case ADDI:
+ case ADDIT:
+ case SUBI:
+ fmt = 11;
+ break;
+ case MOVB:
+ case MOVIB:
+ case COMBT:
+ case COMBF:
+ case COMIBT:
+ case COMIBF:
+ case ADDBT:
+ case ADDBF:
+ case ADDIBT:
+ case ADDIBF:
+ case BVB:
+ case BB:
+ fmt = 12;
+ break;
+ case LDO:
+ case LDB:
+ case LDH:
+ case LDW:
+ case LDWM:
+ case STB:
+ case STH:
+ case STW:
+ case STWM:
+ fmt = 14;
+ break;
+ case BL:
+ case BE:
+ case BLE:
+ fmt = 17;
+ break;
+ case LDIL:
+ case ADDIL:
+ fmt = 21;
+ break;
+ default:
+ fmt = 32;
+ break;
+ }
+ return fmt;
+}
+
+
+/* Insert VALUE into INSN using R_FORMAT to determine exactly what
+ bits to change. */
+
+static INLINE unsigned long
+hppa_rebuild_insn (abfd, insn, value, r_format)
+ bfd *abfd;
+ unsigned long insn;
+ unsigned long value;
+ unsigned long r_format;
+{
+ unsigned long const_part;
+ unsigned long rebuilt_part;
+
+ switch (r_format)
+ {
+ case 11:
+ {
+ unsigned w1, w;
+
+ const_part = insn & 0xffffe002;
+ dis_assemble_12 (value, &w1, &w);
+ rebuilt_part = (w1 << 2) | w;
+ return const_part | rebuilt_part;
+ }
+
+ case 12:
+ {
+ unsigned w1, w;
+
+ const_part = insn & 0xffffe002;
+ dis_assemble_12 (value, &w1, &w);
+ rebuilt_part = (w1 << 2) | w;
+ return const_part | rebuilt_part;
+ }
+
+ case 14:
+ const_part = insn & 0xffffc000;
+ low_sign_unext (value, 14, &rebuilt_part);
+ return const_part | rebuilt_part;
+
+ case 17:
+ {
+ unsigned w1, w2, w;
+
+ const_part = insn & 0xffe0e002;
+ dis_assemble_17 (value, &w1, &w2, &w);
+ rebuilt_part = (w2 << 2) | (w1 << 16) | w;
+ return const_part | rebuilt_part;
+ }
+
+ case 21:
+ const_part = insn & 0xffe00000;
+ dis_assemble_21 (value, &rebuilt_part);
+ return const_part | rebuilt_part;
+
+ case 32:
+ const_part = 0;
+ return value;
+
+ default:
+ abort ();
+ }
+ return insn;
+}
+
+#endif /* _HPPA_H */
diff --git a/contrib/gdb/bfd/libieee.h b/contrib/gdb/bfd/libieee.h
new file mode 100644
index 0000000..c3729cb
--- /dev/null
+++ b/contrib/gdb/bfd/libieee.h
@@ -0,0 +1,135 @@
+/* IEEE-695 object file formats: definitions internal to BFD.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Written by Cygnus Support. Mostly Steve Chamberlain's fault.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+typedef struct {
+ unsigned int index:24;
+ char letter;
+} ieee_symbol_index_type;
+
+typedef struct ct {
+ bfd *this;
+ struct ct *next;
+} bfd_chain_type;
+
+typedef struct ieee_symbol
+{
+ asymbol symbol;
+ struct ieee_symbol *next;
+
+ unsigned int index;
+} ieee_symbol_type;
+
+
+typedef struct ieee_reloc {
+ arelent relent;
+ struct ieee_reloc *next;
+ ieee_symbol_index_type symbol;
+
+} ieee_reloc_type;
+
+#define ieee_symbol(x) ((ieee_symbol_type *)(x))
+
+typedef struct ieee_per_section
+{
+ asection *section;
+ bfd_byte *data;
+ bfd_vma offset;
+ bfd_vma pc;
+ /* For output */
+ file_ptr current_pos;
+ unsigned int current_byte;
+ boolean initialized;
+ ieee_reloc_type **reloc_tail_ptr;
+} ieee_per_section_type;
+
+#define ieee_per_section(x) ((ieee_per_section_type *)((x)->used_by_bfd))
+/* FIXME! There should be no limit to the number of sections! */
+#define NSECTIONS 20
+
+
+typedef struct {
+ unsigned char *input_p;
+ unsigned char *first_byte;
+ bfd *abfd;
+} common_header_type ;
+
+typedef struct ieee_data_struct
+{
+ common_header_type h;
+ boolean read_symbols;
+ boolean read_data;
+ file_ptr output_cursor;
+ /* Map of section indexes to section ptrs */
+ asection * section_table[NSECTIONS];
+ ieee_address_descriptor_type ad;
+ ieee_module_begin_type mb;
+ ieee_w_variable_type w;
+
+ unsigned int section_count;
+
+ unsigned int map_idx;
+ /* List of GLOBAL EXPORT symbols */
+ ieee_symbol_type *external_symbols;
+ /* List of UNDEFINED symbols */
+ ieee_symbol_type *external_reference;
+
+ /* When the symbols have been canonicalized, they are in a
+ * special order, we remember various bases here.. */
+ unsigned int external_symbol_max_index;
+ unsigned int external_symbol_min_index;
+ unsigned int external_symbol_count;
+ int external_symbol_base_offset;
+
+ unsigned int external_reference_max_index;
+ unsigned int external_reference_min_index;
+ unsigned int external_reference_count;
+ int external_reference_base_offset;
+
+
+ boolean symbol_table_full;
+
+
+boolean done_debug;
+
+
+bfd_chain_type *chain_head;
+bfd_chain_type *chain_root;
+
+} ieee_data_type;
+
+typedef struct {
+ file_ptr file_offset;
+ bfd *abfd;
+} ieee_ar_obstack_type;
+
+typedef struct ieee_ar_data_struct
+{
+ common_header_type h;
+ ieee_ar_obstack_type *elements;
+
+ unsigned int element_index ;
+ unsigned int element_count;
+
+} ieee_ar_data_type;
+
+#define IEEE_DATA(abfd) ((abfd)->tdata.ieee_data)
+#define IEEE_AR_DATA(abfd) ((abfd)->tdata.ieee_ar_data)
+
+#define ptr(abfd) (ieee_data(abfd)->input_p)
diff --git a/contrib/gdb/bfd/libnlm.h b/contrib/gdb/bfd/libnlm.h
new file mode 100644
index 0000000..12d2e4e
--- /dev/null
+++ b/contrib/gdb/bfd/libnlm.h
@@ -0,0 +1,264 @@
+/* BFD back-end data structures for NLM (NetWare Loadable Modules) files.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _LIBNLM_H_
+#define _LIBNLM_H_ 1
+
+#ifdef ARCH_SIZE
+# define NLM_ARCH_SIZE ARCH_SIZE
+#endif
+#include "nlm/common.h"
+#include "nlm/internal.h"
+#include "nlm/external.h"
+
+/* A reloc for an imported NLM symbol. Normal relocs are associated
+ with sections, and include a symbol. These relocs are associated
+ with (undefined) symbols, and include a section. */
+
+struct nlm_relent
+{
+ /* Section of reloc. */
+ asection *section;
+ /* Reloc info (sym_ptr_ptr field set only when canonicalized). */
+ arelent reloc;
+};
+
+/* Information we keep for an NLM symbol. */
+
+typedef struct
+{
+ /* BFD symbol. */
+ asymbol symbol;
+ /* Number of reloc entries for imported symbol. */
+ bfd_size_type rcnt;
+ /* Array of reloc information for imported symbol. */
+ struct nlm_relent *relocs;
+} nlmNAME(symbol_type);
+
+extern boolean nlm_mkobject PARAMS ((bfd *));
+extern boolean nlm_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+
+extern void nlmNAME(get_symbol_info)
+ PARAMS ((bfd *, asymbol *, symbol_info *));
+extern long nlmNAME(get_symtab_upper_bound)
+ PARAMS ((bfd *));
+extern long nlmNAME(get_symtab)
+ PARAMS ((bfd *, asymbol **));
+extern asymbol *nlmNAME(make_empty_symbol)
+ PARAMS ((bfd *));
+extern void nlmNAME(print_symbol)
+ PARAMS ((bfd *, PTR, asymbol *, bfd_print_symbol_type));
+extern long nlmNAME(get_reloc_upper_bound)
+ PARAMS ((bfd *, asection *));
+extern long nlmNAME(canonicalize_reloc)
+ PARAMS ((bfd *, asection *, arelent **, asymbol **));
+extern const bfd_target *nlmNAME(object_p)
+ PARAMS ((bfd *));
+extern boolean nlmNAME(set_arch_mach)
+ PARAMS ((bfd *, enum bfd_architecture, unsigned long));
+extern boolean nlmNAME(set_section_contents)
+ PARAMS ((bfd *, asection *, PTR, file_ptr, bfd_size_type));
+extern boolean nlmNAME(write_object_contents)
+ PARAMS ((bfd *));
+
+/* Some private data is stashed away for future use using the tdata pointer
+ in the bfd structure. */
+
+struct nlm_obj_tdata
+{
+ /* Actual data, but ref like ptr */
+ Nlm_Internal_Fixed_Header nlm_fixed_hdr[1];
+ Nlm_Internal_Variable_Header nlm_variable_hdr[1];
+ Nlm_Internal_Version_Header nlm_version_hdr[1];
+ Nlm_Internal_Copyright_Header nlm_copyright_hdr[1];
+ Nlm_Internal_Extended_Header nlm_extended_hdr[1];
+ Nlm_Internal_Custom_Header nlm_custom_hdr[1];
+ Nlm_Internal_Cygnus_Ext_Header nlm_cygnus_ext_hdr[1];
+ /* BFD NLM symbols. */
+ nlmNAME(symbol_type) *nlm_symbols;
+ /* Lowest text and data VMA values. */
+ bfd_vma nlm_text_low;
+ bfd_vma nlm_data_low;
+ /* Caches for data read from object file. */
+ arelent * nlm_reloc_fixups;
+ asection ** nlm_reloc_fixup_secs;
+ /* Backend specific information. This should probably be a pointer,
+ but that would require yet another entry point to initialize the
+ structure. */
+ union
+ {
+ struct /* Alpha backend information. */
+ {
+ bfd_vma gp; /* GP value. */
+ bfd_vma lita_address; /* .lita section address. */
+ bfd_size_type lita_size; /* .lita section size. */
+ }
+ alpha_backend_data;
+ }
+ backend_data;
+};
+
+#define nlm_tdata(bfd) ((bfd) -> tdata.nlm_obj_data)
+#define nlm_fixed_header(bfd) (nlm_tdata(bfd) -> nlm_fixed_hdr)
+#define nlm_variable_header(bfd) (nlm_tdata(bfd) -> nlm_variable_hdr)
+#define nlm_version_header(bfd) (nlm_tdata(bfd) -> nlm_version_hdr)
+#define nlm_copyright_header(bfd) (nlm_tdata(bfd) -> nlm_copyright_hdr)
+#define nlm_extended_header(bfd) (nlm_tdata(bfd) -> nlm_extended_hdr)
+#define nlm_custom_header(bfd) (nlm_tdata(bfd) -> nlm_custom_hdr)
+#define nlm_cygnus_ext_header(bfd) (nlm_tdata(bfd) -> nlm_cygnus_ext_hdr)
+#define nlm_get_symbols(bfd) (nlm_tdata(bfd) -> nlm_symbols)
+#define nlm_set_symbols(bfd, p) (nlm_tdata(bfd) -> nlm_symbols = (p))
+#define nlm_set_text_low(bfd, i) (nlm_tdata(bfd) -> nlm_text_low = (i))
+#define nlm_get_text_low(bfd) (nlm_tdata(bfd) -> nlm_text_low)
+#define nlm_set_data_low(bfd, i) (nlm_tdata(bfd) -> nlm_data_low = (i))
+#define nlm_get_data_low(bfd) (nlm_tdata(bfd) -> nlm_data_low)
+#define nlm_relocation_fixups(bfd) (nlm_tdata(bfd) -> nlm_reloc_fixups)
+#define nlm_relocation_fixup_secs(bfd) (nlm_tdata(bfd)->nlm_reloc_fixup_secs)
+
+#define nlm_alpha_backend_data(bfd) \
+ (&nlm_tdata (bfd)->backend_data.alpha_backend_data)
+
+/* This is used when writing out the external relocs. */
+
+struct reloc_and_sec
+{
+ arelent *rel;
+ asection *sec;
+};
+
+/* We store some function pointer in the backend structure. This lets
+ different NLM targets share most of the same code, while providing
+ slightly different code where necessary. */
+
+struct nlm_backend_data
+{
+ /* Signature for this backend. */
+ char signature[NLM_SIGNATURE_SIZE];
+ /* Size of the fixed header. */
+ bfd_size_type fixed_header_size;
+ /* Size of optional prefix for this backend. Some backend may
+ require this to be a function, but so far a constant is OK. This
+ is for a prefix which precedes the standard NLM fixed header. */
+ bfd_size_type optional_prefix_size;
+ /* Architecture. */
+ enum bfd_architecture arch;
+ /* Machine. */
+ long mach;
+ /* Some NLM formats do not use the uninitialized data section, so
+ all uninitialized data must be put into the regular data section
+ instead. */
+ boolean no_uninitialized_data;
+ /* Some NLM formats have a prefix on the file. If this function is
+ not NULL, it will be called by nlm_object_p. It should return
+ true if this file could match this format, and it should leave
+ the BFD such that a bfd_read will pick up the fixed header. */
+ boolean (*nlm_backend_object_p) PARAMS ((bfd *));
+ /* Write out the prefix. This function may be NULL. This must
+ write out the same number of bytes as is in the field
+ optional_prefix_size. */
+ boolean (*nlm_write_prefix) PARAMS ((bfd *));
+ /* Read a relocation fixup from abfd. The reloc information is
+ machine specific. The second argument is the symbol if this is
+ an import, or NULL if this is a reloc fixup. This function
+ should set the third argument to the section which the reloc
+ belongs in, and the fourth argument to the reloc itself; it does
+ not need to fill in the sym_ptr_ptr field for a reloc against an
+ import symbol. */
+ boolean (*nlm_read_reloc) PARAMS ((bfd *, nlmNAME(symbol_type) *,
+ asection **, arelent *));
+ /* To make objcopy to an i386 NLM work, the i386 backend needs a
+ chance to work over the relocs. This is a bit icky. */
+ boolean (*nlm_mangle_relocs) PARAMS ((bfd *, asection *, PTR data,
+ bfd_vma offset,
+ bfd_size_type count));
+ /* Read an import record from abfd. It would be nice if this
+ were in a machine-dependent format, but it doesn't seem to be. */
+ boolean (*nlm_read_import) PARAMS ((bfd *, nlmNAME(symbol_type) *));
+ /* Write an import record to abfd. */
+ boolean (*nlm_write_import) PARAMS ((bfd *, asection *, arelent *));
+ /* Set the section for a public symbol. This may be NULL, in which
+ case a default method will be used. */
+ boolean (*nlm_set_public_section) PARAMS ((bfd *, nlmNAME(symbol_type) *));
+ /* Get the offset to write out for a public symbol. This may be
+ NULL, in which case a default method will be used. */
+ bfd_vma (*nlm_get_public_offset) PARAMS ((bfd *, asymbol *));
+ /* Swap the fixed header in and out */
+ void (*nlm_swap_fhdr_in) PARAMS ((bfd *,
+ PTR,
+ Nlm_Internal_Fixed_Header *));
+ void (*nlm_swap_fhdr_out) PARAMS ((bfd *,
+ struct nlm_internal_fixed_header *,
+ PTR));
+ /* Write out an external reference. */
+ boolean (*nlm_write_external) PARAMS ((bfd *, bfd_size_type,
+ asymbol *,
+ struct reloc_and_sec *));
+ boolean (*nlm_write_export) PARAMS ((bfd *, asymbol *, bfd_vma));
+};
+
+#define nlm_backend(bfd) \
+ ((struct nlm_backend_data *)((bfd) -> xvec -> backend_data))
+#define nlm_signature(bfd) \
+ (nlm_backend(bfd) -> signature)
+#define nlm_fixed_header_size(bfd) \
+ (nlm_backend(bfd) -> fixed_header_size)
+#define nlm_optional_prefix_size(bfd) \
+ (nlm_backend(bfd) -> optional_prefix_size)
+#define nlm_architecture(bfd) \
+ (nlm_backend(bfd) -> arch)
+#define nlm_machine(bfd) \
+ (nlm_backend(bfd) -> mach)
+#define nlm_no_uninitialized_data(bfd) \
+ (nlm_backend(bfd) -> no_uninitialized_data)
+#define nlm_backend_object_p_func(bfd) \
+ (nlm_backend(bfd) -> nlm_backend_object_p)
+#define nlm_write_prefix_func(bfd) \
+ (nlm_backend(bfd) -> nlm_write_prefix)
+#define nlm_read_reloc_func(bfd) \
+ (nlm_backend(bfd) -> nlm_read_reloc)
+#define nlm_mangle_relocs_func(bfd) \
+ (nlm_backend(bfd) -> nlm_mangle_relocs)
+#define nlm_read_import_func(bfd) \
+ (nlm_backend(bfd) -> nlm_read_import)
+#define nlm_write_import_func(bfd) \
+ (nlm_backend(bfd) -> nlm_write_import)
+#define nlm_set_public_section_func(bfd) \
+ (nlm_backend(bfd) -> nlm_set_public_section)
+#define nlm_get_public_offset_func(bfd) \
+ (nlm_backend(bfd) -> nlm_get_public_offset)
+#define nlm_swap_fixed_header_in_func(bfd) \
+ (nlm_backend(bfd) -> nlm_swap_fhdr_in)
+#define nlm_swap_fixed_header_out_func(bfd) \
+ (nlm_backend(bfd) -> nlm_swap_fhdr_out)
+#define nlm_write_external_func(bfd) \
+ (nlm_backend(bfd) -> nlm_write_external)
+#define nlm_write_export_func(bfd) \
+ (nlm_backend(bfd) -> nlm_write_export)
+
+/* The NLM code, data, and uninitialized sections have no names defined
+ in the NLM, but bfd wants to give them names, so use the traditional
+ UNIX names. */
+
+#define NLM_CODE_NAME ".text"
+#define NLM_INITIALIZED_DATA_NAME ".data"
+#define NLM_UNINITIALIZED_DATA_NAME ".bss"
+
+#endif /* _LIBNLM_H_ */
diff --git a/contrib/gdb/bfd/liboasys.h b/contrib/gdb/bfd/liboasys.h
new file mode 100644
index 0000000..2d15813
--- /dev/null
+++ b/contrib/gdb/bfd/liboasys.h
@@ -0,0 +1,83 @@
+/* BFD internal declarations for Oasys file format handling.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Scrawled by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+typedef struct _oasys_symbol
+{
+ asymbol symbol;
+} oasys_symbol_type;
+
+typedef struct _oasys_reloc {
+ arelent relent;
+ struct _oasys_reloc *next;
+ unsigned int symbol;
+} oasys_reloc_type;
+
+
+#define oasys_symbol(x) ((oasys_symbol_type *)(x))
+#define oasys_per_section(x) ((oasys_per_section_type *)(x->used_by_bfd))
+
+typedef struct _oasys_per_section
+{
+ asection *section;
+ bfd_byte *data;
+ bfd_vma offset;
+ boolean had_vma;
+ oasys_reloc_type **reloc_tail_ptr;
+ bfd_vma pc;
+
+
+ file_ptr current_pos;
+ unsigned int current_byte;
+ boolean initialized;
+} oasys_per_section_type;
+
+#define NSECTIONS 10
+
+typedef struct _oasys_ar_obstack {
+ file_ptr file_offset;
+ bfd *abfd;
+} oasys_ar_obstack_type;
+
+
+typedef struct _oasys_module_info {
+ file_ptr pos;
+ unsigned int size;
+ bfd *abfd;
+ char *name;
+} oasys_module_info_type;
+
+typedef struct _oasys_ar_data {
+ oasys_module_info_type *module;
+ unsigned int module_count;
+ unsigned int module_index;
+} oasys_ar_data_type;
+
+typedef struct _oasys_data {
+ struct obstack oasys_obstack;
+ char *strings;
+ asymbol *symbols;
+ unsigned int symbol_string_length;
+ asection *sections[OASYS_MAX_SEC_COUNT];
+ file_ptr first_data_record;
+} oasys_data_type;
+
+#define OASYS_DATA(abfd) ((abfd)->tdata.oasys_obj_data)
+#define OASYS_AR_DATA(abfd) ((abfd)->tdata.oasys_ar_data)
+
diff --git a/contrib/gdb/bfd/linker.c b/contrib/gdb/bfd/linker.c
new file mode 100644
index 0000000..4decc88
--- /dev/null
+++ b/contrib/gdb/bfd/linker.c
@@ -0,0 +1,2781 @@
+/* linker.c -- BFD linker routines
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by Steve Chamberlain and Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "genlink.h"
+
+/*
+SECTION
+ Linker Functions
+
+@cindex Linker
+ The linker uses three special entry points in the BFD target
+ vector. It is not necessary to write special routines for
+ these entry points when creating a new BFD back end, since
+ generic versions are provided. However, writing them can
+ speed up linking and make it use significantly less runtime
+ memory.
+
+ The first routine creates a hash table used by the other
+ routines. The second routine adds the symbols from an object
+ file to the hash table. The third routine takes all the
+ object files and links them together to create the output
+ file. These routines are designed so that the linker proper
+ does not need to know anything about the symbols in the object
+ files that it is linking. The linker merely arranges the
+ sections as directed by the linker script and lets BFD handle
+ the details of symbols and relocs.
+
+ The second routine and third routines are passed a pointer to
+ a <<struct bfd_link_info>> structure (defined in
+ <<bfdlink.h>>) which holds information relevant to the link,
+ including the linker hash table (which was created by the
+ first routine) and a set of callback functions to the linker
+ proper.
+
+ The generic linker routines are in <<linker.c>>, and use the
+ header file <<genlink.h>>. As of this writing, the only back
+ ends which have implemented versions of these routines are
+ a.out (in <<aoutx.h>>) and ECOFF (in <<ecoff.c>>). The a.out
+ routines are used as examples throughout this section.
+
+@menu
+@* Creating a Linker Hash Table::
+@* Adding Symbols to the Hash Table::
+@* Performing the Final Link::
+@end menu
+
+INODE
+Creating a Linker Hash Table, Adding Symbols to the Hash Table, Linker Functions, Linker Functions
+SUBSECTION
+ Creating a linker hash table
+
+@cindex _bfd_link_hash_table_create in target vector
+@cindex target vector (_bfd_link_hash_table_create)
+ The linker routines must create a hash table, which must be
+ derived from <<struct bfd_link_hash_table>> described in
+ <<bfdlink.c>>. @xref{Hash Tables} for information on how to
+ create a derived hash table. This entry point is called using
+ the target vector of the linker output file.
+
+ The <<_bfd_link_hash_table_create>> entry point must allocate
+ and initialize an instance of the desired hash table. If the
+ back end does not require any additional information to be
+ stored with the entries in the hash table, the entry point may
+ simply create a <<struct bfd_link_hash_table>>. Most likely,
+ however, some additional information will be needed.
+
+ For example, with each entry in the hash table the a.out
+ linker keeps the index the symbol has in the final output file
+ (this index number is used so that when doing a relocateable
+ link the symbol index used in the output file can be quickly
+ filled in when copying over a reloc). The a.out linker code
+ defines the required structures and functions for a hash table
+ derived from <<struct bfd_link_hash_table>>. The a.out linker
+ hash table is created by the function
+ <<NAME(aout,link_hash_table_create)>>; it simply allocates
+ space for the hash table, initializes it, and returns a
+ pointer to it.
+
+ When writing the linker routines for a new back end, you will
+ generally not know exactly which fields will be required until
+ you have finished. You should simply create a new hash table
+ which defines no additional fields, and then simply add fields
+ as they become necessary.
+
+INODE
+Adding Symbols to the Hash Table, Performing the Final Link, Creating a Linker Hash Table, Linker Functions
+SUBSECTION
+ Adding symbols to the hash table
+
+@cindex _bfd_link_add_symbols in target vector
+@cindex target vector (_bfd_link_add_symbols)
+ The linker proper will call the <<_bfd_link_add_symbols>>
+ entry point for each object file or archive which is to be
+ linked (typically these are the files named on the command
+ line, but some may also come from the linker script). The
+ entry point is responsible for examining the file. For an
+ object file, BFD must add any relevant symbol information to
+ the hash table. For an archive, BFD must determine which
+ elements of the archive should be used and adding them to the
+ link.
+
+ The a.out version of this entry point is
+ <<NAME(aout,link_add_symbols)>>.
+
+@menu
+@* Differing file formats::
+@* Adding symbols from an object file::
+@* Adding symbols from an archive::
+@end menu
+
+INODE
+Differing file formats, Adding symbols from an object file, Adding Symbols to the Hash Table, Adding Symbols to the Hash Table
+SUBSUBSECTION
+ Differing file formats
+
+ Normally all the files involved in a link will be of the same
+ format, but it is also possible to link together different
+ format object files, and the back end must support that. The
+ <<_bfd_link_add_symbols>> entry point is called via the target
+ vector of the file to be added. This has an important
+ consequence: the function may not assume that the hash table
+ is the type created by the corresponding
+ <<_bfd_link_hash_table_create>> vector. All the
+ <<_bfd_link_add_symbols>> function can assume about the hash
+ table is that it is derived from <<struct
+ bfd_link_hash_table>>.
+
+ Sometimes the <<_bfd_link_add_symbols>> function must store
+ some information in the hash table entry to be used by the
+ <<_bfd_final_link>> function. In such a case the <<creator>>
+ field of the hash table must be checked to make sure that the
+ hash table was created by an object file of the same format.
+
+ The <<_bfd_final_link>> routine must be prepared to handle a
+ hash entry without any extra information added by the
+ <<_bfd_link_add_symbols>> function. A hash entry without
+ extra information will also occur when the linker script
+ directs the linker to create a symbol. Note that, regardless
+ of how a hash table entry is added, all the fields will be
+ initialized to some sort of null value by the hash table entry
+ initialization function.
+
+ See <<ecoff_link_add_externals>> for an example of how to
+ check the <<creator>> field before saving information (in this
+ case, the ECOFF external symbol debugging information) in a
+ hash table entry.
+
+INODE
+Adding symbols from an object file, Adding symbols from an archive, Differing file formats, Adding Symbols to the Hash Table
+SUBSUBSECTION
+ Adding symbols from an object file
+
+ When the <<_bfd_link_add_symbols>> routine is passed an object
+ file, it must add all externally visible symbols in that
+ object file to the hash table. The actual work of adding the
+ symbol to the hash table is normally handled by the function
+ <<_bfd_generic_link_add_one_symbol>>. The
+ <<_bfd_link_add_symbols>> routine is responsible for reading
+ all the symbols from the object file and passing the correct
+ information to <<_bfd_generic_link_add_one_symbol>>.
+
+ The <<_bfd_link_add_symbols>> routine should not use
+ <<bfd_canonicalize_symtab>> to read the symbols. The point of
+ providing this routine is to avoid the overhead of converting
+ the symbols into generic <<asymbol>> structures.
+
+@findex _bfd_generic_link_add_one_symbol
+ <<_bfd_generic_link_add_one_symbol>> handles the details of
+ combining common symbols, warning about multiple definitions,
+ and so forth. It takes arguments which describe the symbol to
+ add, notably symbol flags, a section, and an offset. The
+ symbol flags include such things as <<BSF_WEAK>> or
+ <<BSF_INDIRECT>>. The section is a section in the object
+ file, or something like <<bfd_und_section_ptr>> for an undefined
+ symbol or <<bfd_com_section_ptr>> for a common symbol.
+
+ If the <<_bfd_final_link>> routine is also going to need to
+ read the symbol information, the <<_bfd_link_add_symbols>>
+ routine should save it somewhere attached to the object file
+ BFD. However, the information should only be saved if the
+ <<keep_memory>> field of the <<info>> argument is true, so
+ that the <<-no-keep-memory>> linker switch is effective.
+
+ The a.out function which adds symbols from an object file is
+ <<aout_link_add_object_symbols>>, and most of the interesting
+ work is in <<aout_link_add_symbols>>. The latter saves
+ pointers to the hash tables entries created by
+ <<_bfd_generic_link_add_one_symbol>> indexed by symbol number,
+ so that the <<_bfd_final_link>> routine does not have to call
+ the hash table lookup routine to locate the entry.
+
+INODE
+Adding symbols from an archive, , Adding symbols from an object file, Adding Symbols to the Hash Table
+SUBSUBSECTION
+ Adding symbols from an archive
+
+ When the <<_bfd_link_add_symbols>> routine is passed an
+ archive, it must look through the symbols defined by the
+ archive and decide which elements of the archive should be
+ included in the link. For each such element it must call the
+ <<add_archive_element>> linker callback, and it must add the
+ symbols from the object file to the linker hash table.
+
+@findex _bfd_generic_link_add_archive_symbols
+ In most cases the work of looking through the symbols in the
+ archive should be done by the
+ <<_bfd_generic_link_add_archive_symbols>> function. This
+ function builds a hash table from the archive symbol table and
+ looks through the list of undefined symbols to see which
+ elements should be included.
+ <<_bfd_generic_link_add_archive_symbols>> is passed a function
+ to call to make the final decision about adding an archive
+ element to the link and to do the actual work of adding the
+ symbols to the linker hash table.
+
+ The function passed to
+ <<_bfd_generic_link_add_archive_symbols>> must read the
+ symbols of the archive element and decide whether the archive
+ element should be included in the link. If the element is to
+ be included, the <<add_archive_element>> linker callback
+ routine must be called with the element as an argument, and
+ the elements symbols must be added to the linker hash table
+ just as though the element had itself been passed to the
+ <<_bfd_link_add_symbols>> function.
+
+ When the a.out <<_bfd_link_add_symbols>> function receives an
+ archive, it calls <<_bfd_generic_link_add_archive_symbols>>
+ passing <<aout_link_check_archive_element>> as the function
+ argument. <<aout_link_check_archive_element>> calls
+ <<aout_link_check_ar_symbols>>. If the latter decides to add
+ the element (an element is only added if it provides a real,
+ non-common, definition for a previously undefined or common
+ symbol) it calls the <<add_archive_element>> callback and then
+ <<aout_link_check_archive_element>> calls
+ <<aout_link_add_symbols>> to actually add the symbols to the
+ linker hash table.
+
+ The ECOFF back end is unusual in that it does not normally
+ call <<_bfd_generic_link_add_archive_symbols>>, because ECOFF
+ archives already contain a hash table of symbols. The ECOFF
+ back end searches the archive itself to avoid the overhead of
+ creating a new hash table.
+
+INODE
+Performing the Final Link, , Adding Symbols to the Hash Table, Linker Functions
+SUBSECTION
+ Performing the final link
+
+@cindex _bfd_link_final_link in target vector
+@cindex target vector (_bfd_final_link)
+ When all the input files have been processed, the linker calls
+ the <<_bfd_final_link>> entry point of the output BFD. This
+ routine is responsible for producing the final output file,
+ which has several aspects. It must relocate the contents of
+ the input sections and copy the data into the output sections.
+ It must build an output symbol table including any local
+ symbols from the input files and the global symbols from the
+ hash table. When producing relocateable output, it must
+ modify the input relocs and write them into the output file.
+ There may also be object format dependent work to be done.
+
+ The linker will also call the <<write_object_contents>> entry
+ point when the BFD is closed. The two entry points must work
+ together in order to produce the correct output file.
+
+ The details of how this works are inevitably dependent upon
+ the specific object file format. The a.out
+ <<_bfd_final_link>> routine is <<NAME(aout,final_link)>>.
+
+@menu
+@* Information provided by the linker::
+@* Relocating the section contents::
+@* Writing the symbol table::
+@end menu
+
+INODE
+Information provided by the linker, Relocating the section contents, Performing the Final Link, Performing the Final Link
+SUBSUBSECTION
+ Information provided by the linker
+
+ Before the linker calls the <<_bfd_final_link>> entry point,
+ it sets up some data structures for the function to use.
+
+ The <<input_bfds>> field of the <<bfd_link_info>> structure
+ will point to a list of all the input files included in the
+ link. These files are linked through the <<link_next>> field
+ of the <<bfd>> structure.
+
+ Each section in the output file will have a list of
+ <<link_order>> structures attached to the <<link_order_head>>
+ field (the <<link_order>> structure is defined in
+ <<bfdlink.h>>). These structures describe how to create the
+ contents of the output section in terms of the contents of
+ various input sections, fill constants, and, eventually, other
+ types of information. They also describe relocs that must be
+ created by the BFD backend, but do not correspond to any input
+ file; this is used to support -Ur, which builds constructors
+ while generating a relocateable object file.
+
+INODE
+Relocating the section contents, Writing the symbol table, Information provided by the linker, Performing the Final Link
+SUBSUBSECTION
+ Relocating the section contents
+
+ The <<_bfd_final_link>> function should look through the
+ <<link_order>> structures attached to each section of the
+ output file. Each <<link_order>> structure should either be
+ handled specially, or it should be passed to the function
+ <<_bfd_default_link_order>> which will do the right thing
+ (<<_bfd_default_link_order>> is defined in <<linker.c>>).
+
+ For efficiency, a <<link_order>> of type
+ <<bfd_indirect_link_order>> whose associated section belongs
+ to a BFD of the same format as the output BFD must be handled
+ specially. This type of <<link_order>> describes part of an
+ output section in terms of a section belonging to one of the
+ input files. The <<_bfd_final_link>> function should read the
+ contents of the section and any associated relocs, apply the
+ relocs to the section contents, and write out the modified
+ section contents. If performing a relocateable link, the
+ relocs themselves must also be modified and written out.
+
+@findex _bfd_relocate_contents
+@findex _bfd_final_link_relocate
+ The functions <<_bfd_relocate_contents>> and
+ <<_bfd_final_link_relocate>> provide some general support for
+ performing the actual relocations, notably overflow checking.
+ Their arguments include information about the symbol the
+ relocation is against and a <<reloc_howto_type>> argument
+ which describes the relocation to perform. These functions
+ are defined in <<reloc.c>>.
+
+ The a.out function which handles reading, relocating, and
+ writing section contents is <<aout_link_input_section>>. The
+ actual relocation is done in <<aout_link_input_section_std>>
+ and <<aout_link_input_section_ext>>.
+
+INODE
+Writing the symbol table, , Relocating the section contents, Performing the Final Link
+SUBSUBSECTION
+ Writing the symbol table
+
+ The <<_bfd_final_link>> function must gather all the symbols
+ in the input files and write them out. It must also write out
+ all the symbols in the global hash table. This must be
+ controlled by the <<strip>> and <<discard>> fields of the
+ <<bfd_link_info>> structure.
+
+ The local symbols of the input files will not have been
+ entered into the linker hash table. The <<_bfd_final_link>>
+ routine must consider each input file and include the symbols
+ in the output file. It may be convenient to do this when
+ looking through the <<link_order>> structures, or it may be
+ done by stepping through the <<input_bfds>> list.
+
+ The <<_bfd_final_link>> routine must also traverse the global
+ hash table to gather all the externally visible symbols. It
+ is possible that most of the externally visible symbols may be
+ written out when considering the symbols of each input file,
+ but it is still necessary to traverse the hash table since the
+ linker script may have defined some symbols that are not in
+ any of the input files.
+
+ The <<strip>> field of the <<bfd_link_info>> structure
+ controls which symbols are written out. The possible values
+ are listed in <<bfdlink.h>>. If the value is <<strip_some>>,
+ then the <<keep_hash>> field of the <<bfd_link_info>>
+ structure is a hash table of symbols to keep; each symbol
+ should be looked up in this hash table, and only symbols which
+ are present should be included in the output file.
+
+ If the <<strip>> field of the <<bfd_link_info>> structure
+ permits local symbols to be written out, the <<discard>> field
+ is used to further controls which local symbols are included
+ in the output file. If the value is <<discard_l>>, then all
+ local symbols which begin with a certain prefix are discarded;
+ this prefix is described by the <<lprefix>> and
+ <<lprefix_len>> fields of the <<bfd_link_info>> structure.
+
+ The a.out backend handles symbols by calling
+ <<aout_link_write_symbols>> on each input BFD and then
+ traversing the global hash table with the function
+ <<aout_link_write_other_symbol>>. It builds a string table
+ while writing out the symbols, which is written to the output
+ file at the end of <<NAME(aout,final_link)>>.
+*/
+
+static struct bfd_hash_entry *generic_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *,
+ const char *));
+static boolean generic_link_read_symbols
+ PARAMS ((bfd *));
+static boolean generic_link_add_symbols
+ PARAMS ((bfd *, struct bfd_link_info *, boolean collect));
+static boolean generic_link_add_object_symbols
+ PARAMS ((bfd *, struct bfd_link_info *, boolean collect));
+static boolean generic_link_check_archive_element_no_collect
+ PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded));
+static boolean generic_link_check_archive_element_collect
+ PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded));
+static boolean generic_link_check_archive_element
+ PARAMS ((bfd *, struct bfd_link_info *, boolean *pneeded, boolean collect));
+static boolean generic_link_add_symbol_list
+ PARAMS ((bfd *, struct bfd_link_info *, bfd_size_type count, asymbol **,
+ boolean collect));
+static bfd *hash_entry_bfd PARAMS ((struct bfd_link_hash_entry *));
+static void set_symbol_from_hash
+ PARAMS ((asymbol *, struct bfd_link_hash_entry *));
+static boolean generic_add_output_symbol
+ PARAMS ((bfd *, size_t *psymalloc, asymbol *));
+static boolean default_fill_link_order
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ struct bfd_link_order *));
+static boolean default_indirect_link_order
+ PARAMS ((bfd *, struct bfd_link_info *, asection *,
+ struct bfd_link_order *, boolean));
+
+/* The link hash table structure is defined in bfdlink.h. It provides
+ a base hash table which the backend specific hash tables are built
+ upon. */
+
+/* Routine to create an entry in the link hash table. */
+
+struct bfd_hash_entry *
+_bfd_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct bfd_link_hash_entry *ret = (struct bfd_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct bfd_link_hash_entry *) NULL)
+ ret = ((struct bfd_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct bfd_link_hash_entry)));
+ if (ret == (struct bfd_link_hash_entry *) NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct bfd_link_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ ret->type = bfd_link_hash_new;
+ ret->next = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize a link hash table. The BFD argument is the one
+ responsible for creating this table. */
+
+boolean
+_bfd_link_hash_table_init (table, abfd, newfunc)
+ struct bfd_link_hash_table *table;
+ bfd *abfd;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+{
+ table->creator = abfd->xvec;
+ table->undefs = NULL;
+ table->undefs_tail = NULL;
+ return bfd_hash_table_init (&table->table, newfunc);
+}
+
+/* Look up a symbol in a link hash table. If follow is true, we
+ follow bfd_link_hash_indirect and bfd_link_hash_warning links to
+ the real symbol. */
+
+struct bfd_link_hash_entry *
+bfd_link_hash_lookup (table, string, create, copy, follow)
+ struct bfd_link_hash_table *table;
+ const char *string;
+ boolean create;
+ boolean copy;
+ boolean follow;
+{
+ struct bfd_link_hash_entry *ret;
+
+ ret = ((struct bfd_link_hash_entry *)
+ bfd_hash_lookup (&table->table, string, create, copy));
+
+ if (follow && ret != (struct bfd_link_hash_entry *) NULL)
+ {
+ while (ret->type == bfd_link_hash_indirect
+ || ret->type == bfd_link_hash_warning)
+ ret = ret->u.i.link;
+ }
+
+ return ret;
+}
+
+/* Look up a symbol in the main linker hash table if the symbol might
+ be wrapped. This should only be used for references to an
+ undefined symbol, not for definitions of a symbol. */
+
+struct bfd_link_hash_entry *
+bfd_wrapped_link_hash_lookup (abfd, info, string, create, copy, follow)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ const char *string;
+ boolean create;
+ boolean copy;
+ boolean follow;
+{
+ if (info->wrap_hash != NULL)
+ {
+ const char *l;
+
+ l = string;
+ if (*l == bfd_get_symbol_leading_char (abfd))
+ ++l;
+
+#undef WRAP
+#define WRAP "__wrap_"
+
+ if (bfd_hash_lookup (info->wrap_hash, l, false, false) != NULL)
+ {
+ char *n;
+ struct bfd_link_hash_entry *h;
+
+ /* This symbol is being wrapped. We want to replace all
+ references to SYM with references to __wrap_SYM. */
+
+ n = (char *) bfd_malloc (strlen (l) + sizeof WRAP + 1);
+ if (n == NULL)
+ return NULL;
+
+ /* Note that symbol_leading_char may be '\0'. */
+ n[0] = bfd_get_symbol_leading_char (abfd);
+ n[1] = '\0';
+ strcat (n, WRAP);
+ strcat (n, l);
+ h = bfd_link_hash_lookup (info->hash, n, create, true, follow);
+ free (n);
+ return h;
+ }
+
+#undef WRAP
+
+#undef REAL
+#define REAL "__real_"
+
+ if (*l == '_'
+ && strncmp (l, REAL, sizeof REAL - 1) == 0
+ && bfd_hash_lookup (info->wrap_hash, l + sizeof REAL - 1,
+ false, false) != NULL)
+ {
+ char *n;
+ struct bfd_link_hash_entry *h;
+
+ /* This is a reference to __real_SYM, where SYM is being
+ wrapped. We want to replace all references to __real_SYM
+ with references to SYM. */
+
+ n = (char *) bfd_malloc (strlen (l + sizeof REAL - 1) + 2);
+ if (n == NULL)
+ return NULL;
+
+ /* Note that symbol_leading_char may be '\0'. */
+ n[0] = bfd_get_symbol_leading_char (abfd);
+ n[1] = '\0';
+ strcat (n, l + sizeof REAL - 1);
+ h = bfd_link_hash_lookup (info->hash, n, create, true, follow);
+ free (n);
+ return h;
+ }
+
+#undef REAL
+ }
+
+ return bfd_link_hash_lookup (info->hash, string, create, copy, follow);
+}
+
+/* Traverse a generic link hash table. The only reason this is not a
+ macro is to do better type checking. This code presumes that an
+ argument passed as a struct bfd_hash_entry * may be caught as a
+ struct bfd_link_hash_entry * with no explicit cast required on the
+ call. */
+
+void
+bfd_link_hash_traverse (table, func, info)
+ struct bfd_link_hash_table *table;
+ boolean (*func) PARAMS ((struct bfd_link_hash_entry *, PTR));
+ PTR info;
+{
+ bfd_hash_traverse (&table->table,
+ ((boolean (*) PARAMS ((struct bfd_hash_entry *, PTR)))
+ func),
+ info);
+}
+
+/* Add a symbol to the linker hash table undefs list. */
+
+INLINE void
+bfd_link_add_undef (table, h)
+ struct bfd_link_hash_table *table;
+ struct bfd_link_hash_entry *h;
+{
+ BFD_ASSERT (h->next == NULL);
+ if (table->undefs_tail != (struct bfd_link_hash_entry *) NULL)
+ table->undefs_tail->next = h;
+ if (table->undefs == (struct bfd_link_hash_entry *) NULL)
+ table->undefs = h;
+ table->undefs_tail = h;
+}
+
+/* Routine to create an entry in an generic link hash table. */
+
+static struct bfd_hash_entry *
+generic_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct generic_link_hash_entry *ret =
+ (struct generic_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct generic_link_hash_entry *) NULL)
+ ret = ((struct generic_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct generic_link_hash_entry)));
+ if (ret == (struct generic_link_hash_entry *) NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct generic_link_hash_entry *)
+ _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+
+ if (ret)
+ {
+ /* Set local fields. */
+ ret->written = false;
+ ret->sym = NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create an generic link hash table. */
+
+struct bfd_link_hash_table *
+_bfd_generic_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct generic_link_hash_table *ret;
+
+ ret = ((struct generic_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct generic_link_hash_table)));
+ if (ret == NULL)
+ return (struct bfd_link_hash_table *) NULL;
+ if (! _bfd_link_hash_table_init (&ret->root, abfd,
+ generic_link_hash_newfunc))
+ {
+ free (ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+ return &ret->root;
+}
+
+/* Grab the symbols for an object file when doing a generic link. We
+ store the symbols in the outsymbols field. We need to keep them
+ around for the entire link to ensure that we only read them once.
+ If we read them multiple times, we might wind up with relocs and
+ the hash table pointing to different instances of the symbol
+ structure. */
+
+static boolean
+generic_link_read_symbols (abfd)
+ bfd *abfd;
+{
+ if (abfd->outsymbols == (asymbol **) NULL)
+ {
+ long symsize;
+ long symcount;
+
+ symsize = bfd_get_symtab_upper_bound (abfd);
+ if (symsize < 0)
+ return false;
+ abfd->outsymbols = (asymbol **) bfd_alloc (abfd, symsize);
+ if (abfd->outsymbols == NULL && symsize != 0)
+ return false;
+ symcount = bfd_canonicalize_symtab (abfd, abfd->outsymbols);
+ if (symcount < 0)
+ return false;
+ abfd->symcount = symcount;
+ }
+
+ return true;
+}
+
+/* Generic function to add symbols to from an object file to the
+ global hash table. This version does not automatically collect
+ constructors by name. */
+
+boolean
+_bfd_generic_link_add_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ return generic_link_add_symbols (abfd, info, false);
+}
+
+/* Generic function to add symbols from an object file to the global
+ hash table. This version automatically collects constructors by
+ name, as the collect2 program does. It should be used for any
+ target which does not provide some other mechanism for setting up
+ constructors and destructors; these are approximately those targets
+ for which gcc uses collect2 and do not support stabs. */
+
+boolean
+_bfd_generic_link_add_symbols_collect (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ return generic_link_add_symbols (abfd, info, true);
+}
+
+/* Add symbols from an object file to the global hash table. */
+
+static boolean
+generic_link_add_symbols (abfd, info, collect)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean collect;
+{
+ boolean ret;
+
+ switch (bfd_get_format (abfd))
+ {
+ case bfd_object:
+ ret = generic_link_add_object_symbols (abfd, info, collect);
+ break;
+ case bfd_archive:
+ ret = (_bfd_generic_link_add_archive_symbols
+ (abfd, info,
+ (collect
+ ? generic_link_check_archive_element_collect
+ : generic_link_check_archive_element_no_collect)));
+ break;
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ ret = false;
+ }
+
+ return ret;
+}
+
+/* Add symbols from an object file to the global hash table. */
+
+static boolean
+generic_link_add_object_symbols (abfd, info, collect)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean collect;
+{
+ if (! generic_link_read_symbols (abfd))
+ return false;
+ return generic_link_add_symbol_list (abfd, info,
+ _bfd_generic_link_get_symcount (abfd),
+ _bfd_generic_link_get_symbols (abfd),
+ collect);
+}
+
+/* We build a hash table of all symbols defined in an archive. */
+
+/* An archive symbol may be defined by multiple archive elements.
+ This linked list is used to hold the elements. */
+
+struct archive_list
+{
+ struct archive_list *next;
+ int indx;
+};
+
+/* An entry in an archive hash table. */
+
+struct archive_hash_entry
+{
+ struct bfd_hash_entry root;
+ /* Where the symbol is defined. */
+ struct archive_list *defs;
+};
+
+/* An archive hash table itself. */
+
+struct archive_hash_table
+{
+ struct bfd_hash_table table;
+};
+
+static struct bfd_hash_entry *archive_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static boolean archive_hash_table_init
+ PARAMS ((struct archive_hash_table *,
+ struct bfd_hash_entry *(*) (struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *)));
+
+/* Create a new entry for an archive hash table. */
+
+static struct bfd_hash_entry *
+archive_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct archive_hash_entry *ret = (struct archive_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct archive_hash_entry *) NULL)
+ ret = ((struct archive_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct archive_hash_entry)));
+ if (ret == (struct archive_hash_entry *) NULL)
+ return NULL;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct archive_hash_entry *)
+ bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+
+ if (ret)
+ {
+ /* Initialize the local fields. */
+ ret->defs = (struct archive_list *) NULL;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Initialize an archive hash table. */
+
+static boolean
+archive_hash_table_init (table, newfunc)
+ struct archive_hash_table *table;
+ struct bfd_hash_entry *(*newfunc) PARAMS ((struct bfd_hash_entry *,
+ struct bfd_hash_table *,
+ const char *));
+{
+ return bfd_hash_table_init (&table->table, newfunc);
+}
+
+/* Look up an entry in an archive hash table. */
+
+#define archive_hash_lookup(t, string, create, copy) \
+ ((struct archive_hash_entry *) \
+ bfd_hash_lookup (&(t)->table, (string), (create), (copy)))
+
+/* Allocate space in an archive hash table. */
+
+#define archive_hash_allocate(t, size) bfd_hash_allocate (&(t)->table, (size))
+
+/* Free an archive hash table. */
+
+#define archive_hash_table_free(t) bfd_hash_table_free (&(t)->table)
+
+/* Generic function to add symbols from an archive file to the global
+ hash file. This function presumes that the archive symbol table
+ has already been read in (this is normally done by the
+ bfd_check_format entry point). It looks through the undefined and
+ common symbols and searches the archive symbol table for them. If
+ it finds an entry, it includes the associated object file in the
+ link.
+
+ The old linker looked through the archive symbol table for
+ undefined symbols. We do it the other way around, looking through
+ undefined symbols for symbols defined in the archive. The
+ advantage of the newer scheme is that we only have to look through
+ the list of undefined symbols once, whereas the old method had to
+ re-search the symbol table each time a new object file was added.
+
+ The CHECKFN argument is used to see if an object file should be
+ included. CHECKFN should set *PNEEDED to true if the object file
+ should be included, and must also call the bfd_link_info
+ add_archive_element callback function and handle adding the symbols
+ to the global hash table. CHECKFN should only return false if some
+ sort of error occurs.
+
+ For some formats, such as a.out, it is possible to look through an
+ object file but not actually include it in the link. The
+ archive_pass field in a BFD is used to avoid checking the symbols
+ of an object files too many times. When an object is included in
+ the link, archive_pass is set to -1. If an object is scanned but
+ not included, archive_pass is set to the pass number. The pass
+ number is incremented each time a new object file is included. The
+ pass number is used because when a new object file is included it
+ may create new undefined symbols which cause a previously examined
+ object file to be included. */
+
+boolean
+_bfd_generic_link_add_archive_symbols (abfd, info, checkfn)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean (*checkfn) PARAMS ((bfd *, struct bfd_link_info *,
+ boolean *pneeded));
+{
+ carsym *arsyms;
+ carsym *arsym_end;
+ register carsym *arsym;
+ int pass;
+ struct archive_hash_table arsym_hash;
+ int indx;
+ struct bfd_link_hash_entry **pundef;
+
+ if (! bfd_has_map (abfd))
+ {
+ /* An empty archive is a special case. */
+ if (bfd_openr_next_archived_file (abfd, (bfd *) NULL) == NULL)
+ return true;
+ bfd_set_error (bfd_error_no_armap);
+ return false;
+ }
+
+ arsyms = bfd_ardata (abfd)->symdefs;
+ arsym_end = arsyms + bfd_ardata (abfd)->symdef_count;
+
+ /* In order to quickly determine whether an symbol is defined in
+ this archive, we build a hash table of the symbols. */
+ if (! archive_hash_table_init (&arsym_hash, archive_hash_newfunc))
+ return false;
+ for (arsym = arsyms, indx = 0; arsym < arsym_end; arsym++, indx++)
+ {
+ struct archive_hash_entry *arh;
+ struct archive_list *l, **pp;
+
+ arh = archive_hash_lookup (&arsym_hash, arsym->name, true, false);
+ if (arh == (struct archive_hash_entry *) NULL)
+ goto error_return;
+ l = ((struct archive_list *)
+ archive_hash_allocate (&arsym_hash, sizeof (struct archive_list)));
+ if (l == NULL)
+ goto error_return;
+ l->indx = indx;
+ for (pp = &arh->defs;
+ *pp != (struct archive_list *) NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = l;
+ l->next = NULL;
+ }
+
+ /* The archive_pass field in the archive itself is used to
+ initialize PASS, sine we may search the same archive multiple
+ times. */
+ pass = abfd->archive_pass + 1;
+
+ /* New undefined symbols are added to the end of the list, so we
+ only need to look through it once. */
+ pundef = &info->hash->undefs;
+ while (*pundef != (struct bfd_link_hash_entry *) NULL)
+ {
+ struct bfd_link_hash_entry *h;
+ struct archive_hash_entry *arh;
+ struct archive_list *l;
+
+ 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 (it would also cause
+ us to lose track of whether the symbol has been
+ referenced). */
+ if (*pundef != info->hash->undefs_tail)
+ *pundef = (*pundef)->next;
+ else
+ pundef = &(*pundef)->next;
+ continue;
+ }
+
+ /* Look for this symbol in the archive symbol map. */
+ arh = archive_hash_lookup (&arsym_hash, h->root.string, false, false);
+ if (arh == (struct archive_hash_entry *) NULL)
+ {
+ pundef = &(*pundef)->next;
+ continue;
+ }
+
+ /* Look at all the objects which define this symbol. */
+ for (l = arh->defs; l != (struct archive_list *) NULL; l = l->next)
+ {
+ bfd *element;
+ boolean needed;
+
+ /* If the symbol has gotten defined along the way, quit. */
+ if (h->type != bfd_link_hash_undefined
+ && h->type != bfd_link_hash_common)
+ break;
+
+ element = bfd_get_elt_at_index (abfd, l->indx);
+ if (element == (bfd *) NULL)
+ goto error_return;
+
+ /* If we've already included this element, or if we've
+ already checked it on this pass, continue. */
+ if (element->archive_pass == -1
+ || element->archive_pass == pass)
+ continue;
+
+ /* If we can't figure this element out, just ignore it. */
+ if (! bfd_check_format (element, bfd_object))
+ {
+ element->archive_pass = -1;
+ continue;
+ }
+
+ /* CHECKFN will see if this element should be included, and
+ go ahead and include it if appropriate. */
+ if (! (*checkfn) (element, info, &needed))
+ goto error_return;
+
+ if (! needed)
+ element->archive_pass = pass;
+ else
+ {
+ element->archive_pass = -1;
+
+ /* Increment the pass count to show that we may need to
+ recheck object files which were already checked. */
+ ++pass;
+ }
+ }
+
+ pundef = &(*pundef)->next;
+ }
+
+ archive_hash_table_free (&arsym_hash);
+
+ /* Save PASS in case we are called again. */
+ abfd->archive_pass = pass;
+
+ return true;
+
+ error_return:
+ archive_hash_table_free (&arsym_hash);
+ return false;
+}
+
+/* See if we should include an archive element. This version is used
+ when we do not want to automatically collect constructors based on
+ the symbol name, presumably because we have some other mechanism
+ for finding them. */
+
+static boolean
+generic_link_check_archive_element_no_collect (abfd, info, pneeded)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean *pneeded;
+{
+ return generic_link_check_archive_element (abfd, info, pneeded, false);
+}
+
+/* See if we should include an archive element. This version is used
+ when we want to automatically collect constructors based on the
+ symbol name, as collect2 does. */
+
+static boolean
+generic_link_check_archive_element_collect (abfd, info, pneeded)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean *pneeded;
+{
+ return generic_link_check_archive_element (abfd, info, pneeded, true);
+}
+
+/* See if we should include an archive element. Optionally collect
+ constructors. */
+
+static boolean
+generic_link_check_archive_element (abfd, info, pneeded, collect)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean *pneeded;
+ boolean collect;
+{
+ asymbol **pp, **ppend;
+
+ *pneeded = false;
+
+ if (! generic_link_read_symbols (abfd))
+ return false;
+
+ pp = _bfd_generic_link_get_symbols (abfd);
+ ppend = pp + _bfd_generic_link_get_symcount (abfd);
+ for (; pp < ppend; pp++)
+ {
+ asymbol *p;
+ struct bfd_link_hash_entry *h;
+
+ p = *pp;
+
+ /* We are only interested in globally visible symbols. */
+ if (! bfd_is_com_section (p->section)
+ && (p->flags & (BSF_GLOBAL | BSF_INDIRECT | BSF_WEAK)) == 0)
+ continue;
+
+ /* We are only interested if we know something about this
+ symbol, and it is undefined or common. An undefined weak
+ symbol (type bfd_link_hash_undefweak) is not considered to be
+ a reference when pulling files out of an archive. See the
+ SVR4 ABI, p. 4-27. */
+ h = bfd_link_hash_lookup (info->hash, bfd_asymbol_name (p), false,
+ false, true);
+ if (h == (struct bfd_link_hash_entry *) NULL
+ || (h->type != bfd_link_hash_undefined
+ && h->type != bfd_link_hash_common))
+ continue;
+
+ /* P is a symbol we are looking for. */
+
+ if (! bfd_is_com_section (p->section))
+ {
+ bfd_size_type symcount;
+ asymbol **symbols;
+
+ /* This object file defines this symbol, so pull it in. */
+ if (! (*info->callbacks->add_archive_element) (info, abfd,
+ bfd_asymbol_name (p)))
+ return false;
+ symcount = _bfd_generic_link_get_symcount (abfd);
+ symbols = _bfd_generic_link_get_symbols (abfd);
+ if (! generic_link_add_symbol_list (abfd, info, symcount,
+ symbols, collect))
+ return false;
+ *pneeded = true;
+ return true;
+ }
+
+ /* P is a common symbol. */
+
+ if (h->type == bfd_link_hash_undefined)
+ {
+ bfd *symbfd;
+ bfd_vma size;
+ unsigned int power;
+
+ 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 for the -u option in the linker. */
+ if (! (*info->callbacks->add_archive_element)
+ (info, abfd, bfd_asymbol_name (p)))
+ return false;
+ *pneeded = true;
+ return true;
+ }
+
+ /* Turn the symbol into a common symbol but do not link in
+ the object file. This is how a.out works. Object
+ formats that require different semantics must implement
+ this function differently. This symbol is already on the
+ undefs list. We add the section to a common section
+ attached to symbfd to ensure that it is in a BFD which
+ will be linked in. */
+ h->type = bfd_link_hash_common;
+ h->u.c.p =
+ ((struct bfd_link_hash_common_entry *)
+ bfd_hash_allocate (&info->hash->table,
+ sizeof (struct bfd_link_hash_common_entry)));
+ if (h->u.c.p == NULL)
+ return false;
+
+ size = bfd_asymbol_value (p);
+ h->u.c.size = size;
+
+ power = bfd_log2 (size);
+ if (power > 4)
+ power = 4;
+ h->u.c.p->alignment_power = power;
+
+ if (p->section == bfd_com_section_ptr)
+ h->u.c.p->section = bfd_make_section_old_way (symbfd, "COMMON");
+ else
+ h->u.c.p->section = bfd_make_section_old_way (symbfd,
+ p->section->name);
+ h->u.c.p->section->flags = SEC_ALLOC;
+ }
+ else
+ {
+ /* Adjust the size of the common symbol if necessary. This
+ is how a.out works. Object formats that require
+ different semantics must implement this function
+ differently. */
+ if (bfd_asymbol_value (p) > h->u.c.size)
+ h->u.c.size = bfd_asymbol_value (p);
+ }
+ }
+
+ /* This archive element is not needed. */
+ return true;
+}
+
+/* Add the symbols from an object file to the global hash table. ABFD
+ is the object file. INFO is the linker information. SYMBOL_COUNT
+ is the number of symbols. SYMBOLS is the list of symbols. COLLECT
+ is true if constructors should be automatically collected by name
+ as is done by collect2. */
+
+static boolean
+generic_link_add_symbol_list (abfd, info, symbol_count, symbols, collect)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ bfd_size_type symbol_count;
+ asymbol **symbols;
+ boolean collect;
+{
+ asymbol **pp, **ppend;
+
+ pp = symbols;
+ ppend = symbols + symbol_count;
+ for (; pp < ppend; pp++)
+ {
+ asymbol *p;
+
+ p = *pp;
+
+ if ((p->flags & (BSF_INDIRECT
+ | BSF_WARNING
+ | BSF_GLOBAL
+ | BSF_CONSTRUCTOR
+ | BSF_WEAK)) != 0
+ || bfd_is_und_section (bfd_get_section (p))
+ || bfd_is_com_section (bfd_get_section (p))
+ || bfd_is_ind_section (bfd_get_section (p)))
+ {
+ const char *name;
+ const char *string;
+ struct generic_link_hash_entry *h;
+
+ name = bfd_asymbol_name (p);
+ if (((p->flags & BSF_INDIRECT) != 0
+ || bfd_is_ind_section (p->section))
+ && pp + 1 < ppend)
+ {
+ pp++;
+ string = bfd_asymbol_name (*pp);
+ }
+ else if ((p->flags & BSF_WARNING) != 0
+ && pp + 1 < ppend)
+ {
+ /* The name of P is actually the warning string, and the
+ next symbol is the one to warn about. */
+ string = name;
+ pp++;
+ name = bfd_asymbol_name (*pp);
+ }
+ else
+ string = NULL;
+
+ h = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, name, p->flags, bfd_get_section (p),
+ p->value, string, false, collect,
+ (struct bfd_link_hash_entry **) &h)))
+ return false;
+
+ /* If this is a constructor symbol, and the linker didn't do
+ anything with it, then we want to just pass the symbol
+ through to the output file. This will happen when
+ linking with -r. */
+ if ((p->flags & BSF_CONSTRUCTOR) != 0
+ && (h == NULL || h->root.type == bfd_link_hash_new))
+ {
+ p->udata.p = NULL;
+ continue;
+ }
+
+ /* Save the BFD symbol so that we don't lose any backend
+ specific information that may be attached to it. We only
+ want this one if it gives more information than the
+ existing one; we don't want to replace a defined symbol
+ with an undefined one. This routine may be called with a
+ hash table other than the generic hash table, so we only
+ do this if we are certain that the hash table is a
+ generic one. */
+ if (info->hash->creator == abfd->xvec)
+ {
+ if (h->sym == (asymbol *) NULL
+ || (! bfd_is_und_section (bfd_get_section (p))
+ && (! bfd_is_com_section (bfd_get_section (p))
+ || bfd_is_und_section (bfd_get_section (h->sym)))))
+ {
+ h->sym = p;
+ /* BSF_OLD_COMMON is a hack to support COFF reloc
+ reading, and it should go away when the COFF
+ linker is switched to the new version. */
+ if (bfd_is_com_section (bfd_get_section (p)))
+ p->flags |= BSF_OLD_COMMON;
+ }
+
+ /* Store a back pointer from the symbol to the hash
+ table entry for the benefit of relaxation code until
+ it gets rewritten to not use asymbol structures.
+ Setting this is also used to check whether these
+ symbols were set up by the generic linker. */
+ p->udata.p = (PTR) h;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* We use a state table to deal with adding symbols from an object
+ file. The first index into the state table describes the symbol
+ from the object file. The second index into the state table is the
+ type of the symbol in the hash table. */
+
+/* The symbol from the object file is turned into one of these row
+ values. */
+
+enum link_row
+{
+ UNDEF_ROW, /* Undefined. */
+ UNDEFW_ROW, /* Weak undefined. */
+ DEF_ROW, /* Defined. */
+ DEFW_ROW, /* Weak defined. */
+ COMMON_ROW, /* Common. */
+ INDR_ROW, /* Indirect. */
+ WARN_ROW, /* Warning. */
+ SET_ROW /* Member of set. */
+};
+
+/* apparently needed for Hitachi 3050R(HI-UX/WE2)? */
+#undef FAIL
+
+/* The actions to take in the state table. */
+
+enum link_action
+{
+ FAIL, /* Abort. */
+ UND, /* Mark symbol undefined. */
+ WEAK, /* Mark symbol weak undefined. */
+ DEF, /* Mark symbol defined. */
+ DEFW, /* Mark symbol weak defined. */
+ COM, /* Mark symbol common. */
+ REF, /* Mark defined symbol referenced. */
+ CREF, /* Possibly warn about common reference to defined symbol. */
+ CDEF, /* Define existing common symbol. */
+ NOACT, /* No action. */
+ BIG, /* Mark symbol common using largest size. */
+ MDEF, /* Multiple definition error. */
+ MIND, /* Multiple indirect symbols. */
+ IND, /* Make indirect symbol. */
+ CIND, /* Make indirect symbol from existing common symbol. */
+ SET, /* Add value to set. */
+ MWARN, /* Make warning symbol. */
+ WARN, /* Issue warning. */
+ CWARN, /* Warn if referenced, else MWARN. */
+ CYCLE, /* Repeat with symbol pointed to. */
+ REFC, /* Mark indirect symbol referenced and then CYCLE. */
+ WARNC /* Issue warning and then CYCLE. */
+};
+
+/* The state table itself. The first index is a link_row and the
+ second index is a bfd_link_hash_type. */
+
+static const enum link_action link_action[8][8] =
+{
+ /* current\prev new undef undefw def defw com indr warn */
+ /* UNDEF_ROW */ {UND, NOACT, UND, REF, REF, NOACT, REFC, WARNC },
+ /* UNDEFW_ROW */ {WEAK, NOACT, NOACT, REF, REF, NOACT, REFC, WARNC },
+ /* DEF_ROW */ {DEF, DEF, DEF, MDEF, DEF, CDEF, MDEF, CYCLE },
+ /* DEFW_ROW */ {DEFW, DEFW, DEFW, NOACT, NOACT, NOACT, NOACT, CYCLE },
+ /* COMMON_ROW */ {COM, COM, COM, CREF, CREF, BIG, CREF, WARNC },
+ /* INDR_ROW */ {IND, IND, IND, MDEF, IND, CIND, MIND, CYCLE },
+ /* WARN_ROW */ {MWARN, WARN, WARN, CWARN, CWARN, WARN, CWARN, CYCLE },
+ /* SET_ROW */ {SET, SET, SET, SET, SET, SET, CYCLE, CYCLE }
+};
+
+/* Most of the entries in the LINK_ACTION table are straightforward,
+ but a few are somewhat subtle.
+
+ A reference to an indirect symbol (UNDEF_ROW/indr or
+ UNDEFW_ROW/indr) is counted as a reference both to the indirect
+ symbol and to the symbol the indirect symbol points to.
+
+ A reference to a warning symbol (UNDEF_ROW/warn or UNDEFW_ROW/warn)
+ causes the warning to be issued.
+
+ A common definition of an indirect symbol (COMMON_ROW/indr) is
+ treated as a multiple definition error. Likewise for an indirect
+ definition of a common symbol (INDR_ROW/com).
+
+ An indirect definition of a warning (INDR_ROW/warn) does not cause
+ the warning to be issued.
+
+ If a warning is created for an indirect symbol (WARN_ROW/indr) no
+ warning is created for the symbol the indirect symbol points to.
+
+ Adding an entry to a set does not count as a reference to a set,
+ and no warning is issued (SET_ROW/warn). */
+
+/* Return the BFD in which a hash entry has been defined, if known. */
+
+static bfd *
+hash_entry_bfd (h)
+ struct bfd_link_hash_entry *h;
+{
+ while (h->type == bfd_link_hash_warning)
+ h = h->u.i.link;
+ switch (h->type)
+ {
+ default:
+ return NULL;
+ case bfd_link_hash_undefined:
+ case bfd_link_hash_undefweak:
+ return h->u.undef.abfd;
+ case bfd_link_hash_defined:
+ case bfd_link_hash_defweak:
+ return h->u.def.section->owner;
+ case bfd_link_hash_common:
+ return h->u.c.p->section->owner;
+ }
+ /*NOTREACHED*/
+}
+
+/* Add a symbol to the global hash table.
+ ABFD is the BFD the symbol comes from.
+ NAME is the name of the symbol.
+ FLAGS is the BSF_* bits associated with the symbol.
+ SECTION is the section in which the symbol is defined; this may be
+ bfd_und_section_ptr or bfd_com_section_ptr.
+ VALUE is the value of the symbol, relative to the section.
+ STRING is used for either an indirect symbol, in which case it is
+ the name of the symbol to indirect to, or a warning symbol, in
+ which case it is the warning string.
+ COPY is true if NAME or STRING must be copied into locally
+ allocated memory if they need to be saved.
+ COLLECT is true if we should automatically collect gcc constructor
+ or destructor names as collect2 does.
+ HASHP, if not NULL, is a place to store the created hash table
+ entry; if *HASHP is not NULL, the caller has already looked up
+ the hash table entry, and stored it in *HASHP. */
+
+boolean
+_bfd_generic_link_add_one_symbol (info, abfd, name, flags, section, value,
+ string, copy, collect, hashp)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ const char *name;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ const char *string;
+ boolean copy;
+ boolean collect;
+ struct bfd_link_hash_entry **hashp;
+{
+ enum link_row row;
+ struct bfd_link_hash_entry *h;
+ boolean cycle;
+
+ if (bfd_is_ind_section (section)
+ || (flags & BSF_INDIRECT) != 0)
+ row = INDR_ROW;
+ else if ((flags & BSF_WARNING) != 0)
+ row = WARN_ROW;
+ else if ((flags & BSF_CONSTRUCTOR) != 0)
+ row = SET_ROW;
+ else if (bfd_is_und_section (section))
+ {
+ if ((flags & BSF_WEAK) != 0)
+ row = UNDEFW_ROW;
+ else
+ row = UNDEF_ROW;
+ }
+ else if ((flags & BSF_WEAK) != 0)
+ row = DEFW_ROW;
+ else if (bfd_is_com_section (section))
+ row = COMMON_ROW;
+ else
+ row = DEF_ROW;
+
+ if (hashp != NULL && *hashp != NULL)
+ h = *hashp;
+ else
+ {
+ if (row == UNDEF_ROW || row == UNDEFW_ROW)
+ h = bfd_wrapped_link_hash_lookup (abfd, info, name, true, copy, false);
+ else
+ h = bfd_link_hash_lookup (info->hash, name, true, copy, false);
+ if (h == NULL)
+ {
+ if (hashp != NULL)
+ *hashp = NULL;
+ return false;
+ }
+ }
+
+ if (info->notice_hash != (struct bfd_hash_table *) NULL
+ && (bfd_hash_lookup (info->notice_hash, name, false, false)
+ != (struct bfd_hash_entry *) NULL))
+ {
+ if (! (*info->callbacks->notice) (info, name, abfd, section, value))
+ return false;
+ }
+
+ if (hashp != (struct bfd_link_hash_entry **) NULL)
+ *hashp = h;
+
+ do
+ {
+ enum link_action action;
+
+ cycle = false;
+ action = link_action[(int) row][(int) h->type];
+ switch (action)
+ {
+ case FAIL:
+ abort ();
+
+ case NOACT:
+ /* Do nothing. */
+ break;
+
+ case UND:
+ /* Make a new undefined symbol. */
+ h->type = bfd_link_hash_undefined;
+ h->u.undef.abfd = abfd;
+ bfd_link_add_undef (info->hash, h);
+ break;
+
+ case WEAK:
+ /* Make a new weak undefined symbol. */
+ h->type = bfd_link_hash_undefweak;
+ h->u.undef.abfd = abfd;
+ break;
+
+ case CDEF:
+ /* We have found a definition for a symbol which was
+ previously common. */
+ BFD_ASSERT (h->type == bfd_link_hash_common);
+ if (! ((*info->callbacks->multiple_common)
+ (info, name,
+ h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
+ abfd, bfd_link_hash_defined, (bfd_vma) 0)))
+ return false;
+ /* Fall through. */
+ case DEF:
+ case DEFW:
+ {
+ enum bfd_link_hash_type oldtype;
+
+ /* Define a symbol. */
+ oldtype = h->type;
+ if (action == DEFW)
+ h->type = bfd_link_hash_defweak;
+ else
+ h->type = bfd_link_hash_defined;
+ h->u.def.section = section;
+ h->u.def.value = value;
+
+ /* If we have been asked to, we act like collect2 and
+ identify all functions that might be global
+ constructors and destructors and pass them up in a
+ callback. We only do this for certain object file
+ types, since many object file types can handle this
+ automatically. */
+ if (collect && name[0] == '_')
+ {
+ const char *s;
+
+ /* A constructor or destructor name starts like this:
+ _+GLOBAL_[_.$][ID][_.$] where the first [_.$] and
+ the second are the same character (we accept any
+ character there, in case a new object file format
+ comes along with even worse naming restrictions). */
+
+#define CONS_PREFIX "GLOBAL_"
+#define CONS_PREFIX_LEN (sizeof CONS_PREFIX - 1)
+
+ s = name + 1;
+ while (*s == '_')
+ ++s;
+ if (s[0] == 'G'
+ && strncmp (s, CONS_PREFIX, CONS_PREFIX_LEN - 1) == 0)
+ {
+ char c;
+
+ c = s[CONS_PREFIX_LEN + 1];
+ if ((c == 'I' || c == 'D')
+ && s[CONS_PREFIX_LEN] == s[CONS_PREFIX_LEN + 2])
+ {
+ /* If this is a definition of a symbol which
+ was previously weakly defined, we are in
+ trouble. We have already added a
+ constructor entry for the weak defined
+ symbol, and now we are trying to add one
+ for the new symbol. Fortunately, this case
+ should never arise in practice. */
+ if (oldtype == bfd_link_hash_defweak)
+ abort ();
+
+ if (! ((*info->callbacks->constructor)
+ (info,
+ c == 'I' ? true : false,
+ name, abfd, section, value)))
+ return false;
+ }
+ }
+ }
+ }
+
+ break;
+
+ case COM:
+ /* We have found a common definition for a symbol. */
+ if (h->type == bfd_link_hash_new)
+ bfd_link_add_undef (info->hash, h);
+ h->type = bfd_link_hash_common;
+ h->u.c.p =
+ ((struct bfd_link_hash_common_entry *)
+ bfd_hash_allocate (&info->hash->table,
+ sizeof (struct bfd_link_hash_common_entry)));
+ if (h->u.c.p == NULL)
+ return false;
+
+ h->u.c.size = value;
+
+ /* Select a default alignment based on the size. This may
+ be overridden by the caller. */
+ {
+ unsigned int power;
+
+ power = bfd_log2 (value);
+ if (power > 4)
+ power = 4;
+ h->u.c.p->alignment_power = power;
+ }
+
+ /* The section of a common symbol is only used if the common
+ symbol is actually allocated. It basically provides a
+ hook for the linker script to decide which output section
+ the common symbols should be put in. In most cases, the
+ section of a common symbol will be bfd_com_section_ptr,
+ the code here will choose a common symbol section named
+ "COMMON", and the linker script will contain *(COMMON) in
+ the appropriate place. A few targets use separate common
+ sections for small symbols, and they require special
+ handling. */
+ if (section == bfd_com_section_ptr)
+ {
+ h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON");
+ h->u.c.p->section->flags = SEC_ALLOC;
+ }
+ else if (section->owner != abfd)
+ {
+ h->u.c.p->section = bfd_make_section_old_way (abfd,
+ section->name);
+ h->u.c.p->section->flags = SEC_ALLOC;
+ }
+ else
+ h->u.c.p->section = section;
+ break;
+
+ case REF:
+ /* A reference to a defined symbol. */
+ if (h->next == NULL && info->hash->undefs_tail != h)
+ h->next = h;
+ break;
+
+ case BIG:
+ /* We have found a common definition for a symbol which
+ already had a common definition. Use the maximum of the
+ two sizes. */
+ BFD_ASSERT (h->type == bfd_link_hash_common);
+ if (! ((*info->callbacks->multiple_common)
+ (info, name,
+ h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
+ abfd, bfd_link_hash_common, value)))
+ return false;
+ if (value > h->u.c.size)
+ {
+ unsigned int power;
+
+ h->u.c.size = value;
+
+ /* Select a default alignment based on the size. This may
+ be overridden by the caller. */
+ power = bfd_log2 (value);
+ if (power > 4)
+ power = 4;
+ h->u.c.p->alignment_power = power;
+ }
+ break;
+
+ case CREF:
+ {
+ bfd *obfd;
+
+ /* We have found a common definition for a symbol which
+ was already defined. FIXME: It would nice if we could
+ report the BFD which defined an indirect symbol, but we
+ don't have anywhere to store the information. */
+ if (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ obfd = h->u.def.section->owner;
+ else
+ obfd = NULL;
+ if (! ((*info->callbacks->multiple_common)
+ (info, name, obfd, h->type, (bfd_vma) 0,
+ abfd, bfd_link_hash_common, value)))
+ return false;
+ }
+ break;
+
+ case MIND:
+ /* Multiple indirect symbols. This is OK if they both point
+ to the same symbol. */
+ if (strcmp (h->u.i.link->root.string, string) == 0)
+ break;
+ /* Fall through. */
+ case MDEF:
+ /* Handle a multiple definition. */
+ {
+ asection *msec;
+ bfd_vma mval;
+
+ switch (h->type)
+ {
+ case bfd_link_hash_defined:
+ msec = h->u.def.section;
+ mval = h->u.def.value;
+ break;
+ case bfd_link_hash_indirect:
+ msec = bfd_ind_section_ptr;
+ mval = 0;
+ break;
+ default:
+ abort ();
+ }
+
+ /* Ignore a redefinition of an absolute symbol to the same
+ value; it's harmless. */
+ if (h->type == bfd_link_hash_defined
+ && bfd_is_abs_section (msec)
+ && bfd_is_abs_section (section)
+ && value == mval)
+ break;
+
+ if (! ((*info->callbacks->multiple_definition)
+ (info, name, msec->owner, msec, mval, abfd, section,
+ value)))
+ return false;
+ }
+ break;
+
+ case CIND:
+ /* Create an indirect symbol from an existing common symbol. */
+ BFD_ASSERT (h->type == bfd_link_hash_common);
+ if (! ((*info->callbacks->multiple_common)
+ (info, name,
+ h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size,
+ abfd, bfd_link_hash_indirect, (bfd_vma) 0)))
+ return false;
+ /* Fall through. */
+ case IND:
+ /* Create an indirect symbol. */
+ {
+ struct bfd_link_hash_entry *inh;
+
+ /* STRING is the name of the symbol we want to indirect
+ to. */
+ inh = bfd_wrapped_link_hash_lookup (abfd, info, string, true,
+ copy, false);
+ if (inh == (struct bfd_link_hash_entry *) NULL)
+ return false;
+ if (inh->type == bfd_link_hash_new)
+ {
+ inh->type = bfd_link_hash_undefined;
+ inh->u.undef.abfd = abfd;
+ bfd_link_add_undef (info->hash, inh);
+ }
+
+ /* If the indirect symbol has been referenced, we need to
+ push the reference down to the symbol we are
+ referencing. */
+ if (h->type != bfd_link_hash_new)
+ {
+ row = UNDEF_ROW;
+ cycle = true;
+ }
+
+ h->type = bfd_link_hash_indirect;
+ h->u.i.link = inh;
+ }
+ break;
+
+ case SET:
+ /* Add an entry to a set. */
+ if (! (*info->callbacks->add_to_set) (info, h, BFD_RELOC_CTOR,
+ abfd, section, value))
+ return false;
+ break;
+
+ case WARNC:
+ /* Issue a warning and cycle. */
+ if (h->u.i.warning != NULL)
+ {
+ if (! (*info->callbacks->warning) (info, h->u.i.warning, name,
+ abfd, (asection *) NULL,
+ (bfd_vma) 0))
+ return false;
+ /* Only issue a warning once. */
+ h->u.i.warning = NULL;
+ }
+ /* Fall through. */
+ case CYCLE:
+ /* Try again with the referenced symbol. */
+ h = h->u.i.link;
+ cycle = true;
+ break;
+
+ case REFC:
+ /* A reference to an indirect symbol. */
+ if (h->next == NULL && info->hash->undefs_tail != h)
+ h->next = h;
+ h = h->u.i.link;
+ cycle = true;
+ break;
+
+ case WARN:
+ /* Issue a warning. */
+ if (! (*info->callbacks->warning) (info, string, name,
+ hash_entry_bfd (h),
+ (asection *) NULL, (bfd_vma) 0))
+ return false;
+ break;
+
+ case CWARN:
+ /* Warn if this symbol has been referenced already,
+ otherwise add a warning. A symbol has been referenced if
+ the next field is not NULL, or it is the tail of the
+ undefined symbol list. The REF case above helps to
+ ensure this. */
+ if (h->next != NULL || info->hash->undefs_tail == h)
+ {
+ if (! (*info->callbacks->warning) (info, string, name,
+ hash_entry_bfd (h),
+ (asection *) NULL,
+ (bfd_vma) 0))
+ return false;
+ break;
+ }
+ /* Fall through. */
+ case MWARN:
+ /* Make a warning symbol. */
+ {
+ struct bfd_link_hash_entry *sub;
+
+ /* STRING is the warning to give. */
+ sub = ((struct bfd_link_hash_entry *)
+ ((*info->hash->table.newfunc)
+ ((struct bfd_hash_entry *) NULL, &info->hash->table,
+ h->root.string)));
+ if (sub == NULL)
+ return false;
+ *sub = *h;
+ sub->type = bfd_link_hash_warning;
+ sub->u.i.link = h;
+ if (! copy)
+ sub->u.i.warning = string;
+ else
+ {
+ char *w;
+
+ w = bfd_hash_allocate (&info->hash->table,
+ strlen (string) + 1);
+ if (w == NULL)
+ return false;
+ strcpy (w, string);
+ sub->u.i.warning = w;
+ }
+
+ bfd_hash_replace (&info->hash->table,
+ (struct bfd_hash_entry *) h,
+ (struct bfd_hash_entry *) sub);
+ if (hashp != NULL)
+ *hashp = sub;
+ }
+ break;
+ }
+ }
+ while (cycle);
+
+ return true;
+}
+
+/* Generic final link routine. */
+
+boolean
+_bfd_generic_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ bfd *sub;
+ asection *o;
+ struct bfd_link_order *p;
+ size_t outsymalloc;
+ struct generic_write_global_symbol_info wginfo;
+
+ abfd->outsymbols = (asymbol **) NULL;
+ abfd->symcount = 0;
+ outsymalloc = 0;
+
+ /* Build the output symbol table. */
+ for (sub = info->input_bfds; sub != (bfd *) NULL; sub = sub->link_next)
+ if (! _bfd_generic_link_output_symbols (abfd, sub, info, &outsymalloc))
+ return false;
+
+ /* Accumulate the global symbols. */
+ wginfo.info = info;
+ wginfo.output_bfd = abfd;
+ wginfo.psymalloc = &outsymalloc;
+ _bfd_generic_link_hash_traverse (_bfd_generic_hash_table (info),
+ _bfd_generic_link_write_global_symbol,
+ (PTR) &wginfo);
+
+ if (info->relocateable)
+ {
+ /* Allocate space for the output relocs for each section. */
+ 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_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ ++o->reloc_count;
+ else if (p->type == bfd_indirect_link_order)
+ {
+ asection *input_section;
+ bfd *input_bfd;
+ long relsize;
+ arelent **relocs;
+ asymbol **symbols;
+ long reloc_count;
+
+ input_section = p->u.indirect.section;
+ input_bfd = input_section->owner;
+ relsize = bfd_get_reloc_upper_bound (input_bfd,
+ input_section);
+ if (relsize < 0)
+ return false;
+ relocs = (arelent **) bfd_malloc ((size_t) relsize);
+ if (!relocs && relsize != 0)
+ return false;
+ symbols = _bfd_generic_link_get_symbols (input_bfd);
+ reloc_count = bfd_canonicalize_reloc (input_bfd,
+ input_section,
+ relocs,
+ symbols);
+ if (reloc_count < 0)
+ return false;
+ BFD_ASSERT ((unsigned long) reloc_count
+ == input_section->reloc_count);
+ o->reloc_count += reloc_count;
+ free (relocs);
+ }
+ }
+ if (o->reloc_count > 0)
+ {
+ o->orelocation = ((arelent **)
+ bfd_alloc (abfd,
+ (o->reloc_count
+ * sizeof (arelent *))));
+ if (!o->orelocation)
+ return false;
+ o->flags |= SEC_RELOC;
+ /* Reset the count so that it can be used as an index
+ when putting in the output relocs. */
+ o->reloc_count = 0;
+ }
+ }
+ }
+
+ /* Handle all the link order information for the sections. */
+ 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)
+ {
+ switch (p->type)
+ {
+ case bfd_section_reloc_link_order:
+ case bfd_symbol_reloc_link_order:
+ if (! _bfd_generic_reloc_link_order (abfd, info, o, p))
+ return false;
+ break;
+ case bfd_indirect_link_order:
+ if (! default_indirect_link_order (abfd, info, o, p, true))
+ return false;
+ break;
+ default:
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ return false;
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Add an output symbol to the output BFD. */
+
+static boolean
+generic_add_output_symbol (output_bfd, psymalloc, sym)
+ bfd *output_bfd;
+ size_t *psymalloc;
+ asymbol *sym;
+{
+ if (output_bfd->symcount >= *psymalloc)
+ {
+ asymbol **newsyms;
+
+ if (*psymalloc == 0)
+ *psymalloc = 124;
+ else
+ *psymalloc *= 2;
+ newsyms = (asymbol **) bfd_realloc (output_bfd->outsymbols,
+ *psymalloc * sizeof (asymbol *));
+ if (newsyms == (asymbol **) NULL)
+ return false;
+ output_bfd->outsymbols = newsyms;
+ }
+
+ output_bfd->outsymbols[output_bfd->symcount] = sym;
+ ++output_bfd->symcount;
+
+ return true;
+}
+
+/* Handle the symbols for an input BFD. */
+
+boolean
+_bfd_generic_link_output_symbols (output_bfd, input_bfd, info, psymalloc)
+ bfd *output_bfd;
+ bfd *input_bfd;
+ struct bfd_link_info *info;
+ size_t *psymalloc;
+{
+ asymbol **sym_ptr;
+ asymbol **sym_end;
+
+ if (! generic_link_read_symbols (input_bfd))
+ return false;
+
+ /* Create a filename symbol if we are supposed to. */
+ if (info->create_object_symbols_section != (asection *) NULL)
+ {
+ asection *sec;
+
+ for (sec = input_bfd->sections;
+ sec != (asection *) NULL;
+ sec = sec->next)
+ {
+ if (sec->output_section == info->create_object_symbols_section)
+ {
+ asymbol *newsym;
+
+ newsym = bfd_make_empty_symbol (input_bfd);
+ if (!newsym)
+ return false;
+ newsym->name = input_bfd->filename;
+ newsym->value = 0;
+ newsym->flags = BSF_LOCAL | BSF_FILE;
+ newsym->section = sec;
+
+ if (! generic_add_output_symbol (output_bfd, psymalloc,
+ newsym))
+ return false;
+
+ break;
+ }
+ }
+ }
+
+ /* Adjust the values of the globally visible symbols, and write out
+ local symbols. */
+ sym_ptr = _bfd_generic_link_get_symbols (input_bfd);
+ sym_end = sym_ptr + _bfd_generic_link_get_symcount (input_bfd);
+ for (; sym_ptr < sym_end; sym_ptr++)
+ {
+ asymbol *sym;
+ struct generic_link_hash_entry *h;
+ boolean output;
+
+ h = (struct generic_link_hash_entry *) NULL;
+ sym = *sym_ptr;
+ if ((sym->flags & (BSF_INDIRECT
+ | BSF_WARNING
+ | BSF_GLOBAL
+ | BSF_CONSTRUCTOR
+ | BSF_WEAK)) != 0
+ || bfd_is_und_section (bfd_get_section (sym))
+ || bfd_is_com_section (bfd_get_section (sym))
+ || bfd_is_ind_section (bfd_get_section (sym)))
+ {
+ if (sym->udata.p != NULL)
+ h = (struct generic_link_hash_entry *) sym->udata.p;
+ else if ((sym->flags & BSF_CONSTRUCTOR) != 0)
+ {
+ /* This case normally means that the main linker code
+ deliberately ignored this constructor symbol. We
+ should just pass it through. This will screw up if
+ the constructor symbol is from a different,
+ non-generic, object file format, but the case will
+ only arise when linking with -r, which will probably
+ fail anyhow, since there will be no way to represent
+ the relocs in the output format being used. */
+ h = NULL;
+ }
+ else if (bfd_is_und_section (bfd_get_section (sym)))
+ h = ((struct generic_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, info,
+ bfd_asymbol_name (sym),
+ false, false, true));
+ else
+ h = _bfd_generic_link_hash_lookup (_bfd_generic_hash_table (info),
+ bfd_asymbol_name (sym),
+ false, false, true);
+
+ if (h != (struct generic_link_hash_entry *) NULL)
+ {
+ /* Force all references to this symbol to point to
+ the same area in memory. It is possible that
+ this routine will be called with a hash table
+ other than a generic hash table, so we double
+ check that. */
+ if (info->hash->creator == input_bfd->xvec)
+ {
+ if (h->sym != (asymbol *) NULL)
+ *sym_ptr = sym = h->sym;
+ }
+
+ switch (h->root.type)
+ {
+ default:
+ case bfd_link_hash_new:
+ abort ();
+ case bfd_link_hash_undefined:
+ break;
+ case bfd_link_hash_undefweak:
+ sym->flags |= BSF_WEAK;
+ break;
+ case bfd_link_hash_indirect:
+ h = (struct generic_link_hash_entry *) h->root.u.i.link;
+ /* fall through */
+ case bfd_link_hash_defined:
+ sym->flags |= BSF_GLOBAL;
+ sym->flags &=~ BSF_CONSTRUCTOR;
+ sym->value = h->root.u.def.value;
+ sym->section = h->root.u.def.section;
+ break;
+ case bfd_link_hash_defweak:
+ sym->flags |= BSF_WEAK;
+ sym->flags &=~ BSF_CONSTRUCTOR;
+ sym->value = h->root.u.def.value;
+ sym->section = h->root.u.def.section;
+ break;
+ case bfd_link_hash_common:
+ sym->value = h->root.u.c.size;
+ sym->flags |= BSF_GLOBAL;
+ if (! bfd_is_com_section (sym->section))
+ {
+ BFD_ASSERT (bfd_is_und_section (sym->section));
+ sym->section = bfd_com_section_ptr;
+ }
+ /* We do not set the section of the symbol to
+ h->root.u.c.p->section. That value was saved so
+ that we would know where to allocate the symbol
+ if it was defined. In this case the type is
+ still bfd_link_hash_common, so we did not define
+ it, so we do not want to use that section. */
+ break;
+ }
+ }
+ }
+
+ /* This switch is straight from the old code in
+ write_file_locals in ldsym.c. */
+ if (info->strip == strip_some
+ && (bfd_hash_lookup (info->keep_hash, bfd_asymbol_name (sym),
+ false, false)
+ == (struct bfd_hash_entry *) NULL))
+ output = false;
+ else if ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0)
+ {
+ /* If this symbol is marked as occurring now, rather
+ than at the end, output it now. This is used for
+ COFF C_EXT FCN symbols. FIXME: There must be a
+ better way. */
+ if (bfd_asymbol_bfd (sym) == input_bfd
+ && (sym->flags & BSF_NOT_AT_END) != 0)
+ output = true;
+ else
+ output = false;
+ }
+ else if (bfd_is_ind_section (sym->section))
+ output = false;
+ else if ((sym->flags & BSF_DEBUGGING) != 0)
+ {
+ if (info->strip == strip_none)
+ output = true;
+ else
+ output = false;
+ }
+ else if (bfd_is_und_section (sym->section)
+ || bfd_is_com_section (sym->section))
+ output = false;
+ else if ((sym->flags & BSF_LOCAL) != 0)
+ {
+ if ((sym->flags & BSF_WARNING) != 0)
+ output = false;
+ else
+ {
+ switch (info->discard)
+ {
+ default:
+ case discard_all:
+ output = false;
+ break;
+ case discard_l:
+ if (bfd_asymbol_name (sym)[0] == info->lprefix[0]
+ && (info->lprefix_len == 1
+ || strncmp (bfd_asymbol_name (sym), info->lprefix,
+ info->lprefix_len) == 0))
+ output = false;
+ else
+ output = true;
+ break;
+ case discard_none:
+ output = true;
+ break;
+ }
+ }
+ }
+ else if ((sym->flags & BSF_CONSTRUCTOR))
+ {
+ if (info->strip != strip_all)
+ output = true;
+ else
+ output = false;
+ }
+ else
+ abort ();
+
+ if (output)
+ {
+ if (! generic_add_output_symbol (output_bfd, psymalloc, sym))
+ return false;
+ if (h != (struct generic_link_hash_entry *) NULL)
+ h->written = true;
+ }
+ }
+
+ return true;
+}
+
+/* Set the section and value of a generic BFD symbol based on a linker
+ hash table entry. */
+
+static void
+set_symbol_from_hash (sym, h)
+ asymbol *sym;
+ struct bfd_link_hash_entry *h;
+{
+ switch (h->type)
+ {
+ default:
+ abort ();
+ break;
+ case bfd_link_hash_new:
+ /* This can happen when a constructor symbol is seen but we are
+ not building constructors. */
+ if (sym->section != NULL)
+ {
+ BFD_ASSERT ((sym->flags & BSF_CONSTRUCTOR) != 0);
+ }
+ else
+ {
+ sym->flags |= BSF_CONSTRUCTOR;
+ sym->section = bfd_abs_section_ptr;
+ sym->value = 0;
+ }
+ break;
+ case bfd_link_hash_undefined:
+ sym->section = bfd_und_section_ptr;
+ sym->value = 0;
+ break;
+ case bfd_link_hash_undefweak:
+ sym->section = bfd_und_section_ptr;
+ sym->value = 0;
+ sym->flags |= BSF_WEAK;
+ break;
+ case bfd_link_hash_defined:
+ sym->section = h->u.def.section;
+ sym->value = h->u.def.value;
+ break;
+ case bfd_link_hash_defweak:
+ sym->flags |= BSF_WEAK;
+ sym->section = h->u.def.section;
+ sym->value = h->u.def.value;
+ break;
+ case bfd_link_hash_common:
+ sym->value = h->u.c.size;
+ if (sym->section == NULL)
+ sym->section = bfd_com_section_ptr;
+ else if (! bfd_is_com_section (sym->section))
+ {
+ BFD_ASSERT (bfd_is_und_section (sym->section));
+ sym->section = bfd_com_section_ptr;
+ }
+ /* Do not set the section; see _bfd_generic_link_output_symbols. */
+ break;
+ case bfd_link_hash_indirect:
+ case bfd_link_hash_warning:
+ /* FIXME: What should we do here? */
+ break;
+ }
+}
+
+/* Write out a global symbol, if it hasn't already been written out.
+ This is called for each symbol in the hash table. */
+
+boolean
+_bfd_generic_link_write_global_symbol (h, data)
+ struct generic_link_hash_entry *h;
+ PTR data;
+{
+ struct generic_write_global_symbol_info *wginfo =
+ (struct generic_write_global_symbol_info *) data;
+ asymbol *sym;
+
+ if (h->written)
+ return true;
+
+ h->written = true;
+
+ if (wginfo->info->strip == strip_all
+ || (wginfo->info->strip == strip_some
+ && bfd_hash_lookup (wginfo->info->keep_hash, h->root.root.string,
+ false, false) == NULL))
+ return true;
+
+ if (h->sym != (asymbol *) NULL)
+ sym = h->sym;
+ else
+ {
+ sym = bfd_make_empty_symbol (wginfo->output_bfd);
+ if (!sym)
+ return false;
+ sym->name = h->root.root.string;
+ sym->flags = 0;
+ }
+
+ set_symbol_from_hash (sym, &h->root);
+
+ sym->flags |= BSF_GLOBAL;
+
+ if (! generic_add_output_symbol (wginfo->output_bfd, wginfo->psymalloc,
+ sym))
+ {
+ /* FIXME: No way to return failure. */
+ abort ();
+ }
+
+ return true;
+}
+
+/* Create a relocation. */
+
+boolean
+_bfd_generic_reloc_link_order (abfd, info, sec, link_order)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ struct bfd_link_order *link_order;
+{
+ arelent *r;
+
+ if (! info->relocateable)
+ abort ();
+ if (sec->orelocation == (arelent **) NULL)
+ abort ();
+
+ r = (arelent *) bfd_alloc (abfd, sizeof (arelent));
+ if (r == (arelent *) NULL)
+ return false;
+
+ r->address = link_order->offset;
+ r->howto = bfd_reloc_type_lookup (abfd, link_order->u.reloc.p->reloc);
+ if (r->howto == 0)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ /* Get the symbol to use for the relocation. */
+ if (link_order->type == bfd_section_reloc_link_order)
+ r->sym_ptr_ptr = link_order->u.reloc.p->u.section->symbol_ptr_ptr;
+ else
+ {
+ struct generic_link_hash_entry *h;
+
+ h = ((struct generic_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (abfd, info,
+ link_order->u.reloc.p->u.name,
+ false, false, true));
+ if (h == (struct generic_link_hash_entry *) NULL
+ || ! h->written)
+ {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, link_order->u.reloc.p->u.name,
+ (bfd *) NULL, (asection *) NULL, (bfd_vma) 0)))
+ return false;
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ r->sym_ptr_ptr = &h->sym;
+ }
+
+ /* If this is an inplace reloc, write the addend to the object file.
+ Otherwise, store it in the reloc addend. */
+ if (! r->howto->partial_inplace)
+ r->addend = link_order->u.reloc.p->addend;
+ else
+ {
+ bfd_size_type size;
+ bfd_reloc_status_type rstat;
+ bfd_byte *buf;
+ boolean ok;
+
+ size = bfd_get_reloc_size (r->howto);
+ buf = (bfd_byte *) bfd_zmalloc (size);
+ if (buf == (bfd_byte *) NULL)
+ return false;
+ rstat = _bfd_relocate_contents (r->howto, abfd,
+ 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 (abfd, link_order->u.reloc.p->u.section)
+ : link_order->u.reloc.p->u.name),
+ r->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 (abfd, sec, (PTR) buf,
+ (file_ptr) link_order->offset, size);
+ free (buf);
+ if (! ok)
+ return false;
+
+ r->addend = 0;
+ }
+
+ sec->orelocation[sec->reloc_count] = r;
+ ++sec->reloc_count;
+
+ return true;
+}
+
+/* Allocate a new link_order for a section. */
+
+struct bfd_link_order *
+bfd_new_link_order (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ struct bfd_link_order *new;
+
+ new = ((struct bfd_link_order *)
+ bfd_alloc_by_size_t (abfd, sizeof (struct bfd_link_order)));
+ if (!new)
+ return NULL;
+
+ new->type = bfd_undefined_link_order;
+ new->offset = 0;
+ new->size = 0;
+ new->next = (struct bfd_link_order *) NULL;
+
+ if (section->link_order_tail != (struct bfd_link_order *) NULL)
+ section->link_order_tail->next = new;
+ else
+ section->link_order_head = new;
+ section->link_order_tail = new;
+
+ return new;
+}
+
+/* Default link order processing routine. Note that we can not handle
+ the reloc_link_order types here, since they depend upon the details
+ of how the particular backends generates relocs. */
+
+boolean
+_bfd_default_link_order (abfd, info, sec, link_order)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ struct bfd_link_order *link_order;
+{
+ switch (link_order->type)
+ {
+ case bfd_undefined_link_order:
+ case bfd_section_reloc_link_order:
+ case bfd_symbol_reloc_link_order:
+ default:
+ abort ();
+ case bfd_indirect_link_order:
+ return default_indirect_link_order (abfd, info, sec, link_order,
+ false);
+ case bfd_fill_link_order:
+ return default_fill_link_order (abfd, info, sec, link_order);
+ case bfd_data_link_order:
+ return bfd_set_section_contents (abfd, sec,
+ (PTR) link_order->u.data.contents,
+ (file_ptr) link_order->offset,
+ link_order->size);
+ }
+}
+
+/* Default routine to handle a bfd_fill_link_order. */
+
+/*ARGSUSED*/
+static boolean
+default_fill_link_order (abfd, info, sec, link_order)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ asection *sec;
+ struct bfd_link_order *link_order;
+{
+ size_t size;
+ char *space;
+ size_t i;
+ int fill;
+ boolean result;
+
+ BFD_ASSERT ((sec->flags & SEC_HAS_CONTENTS) != 0);
+
+ size = (size_t) link_order->size;
+ space = (char *) bfd_malloc (size);
+ if (space == NULL && size != 0)
+ return false;
+
+ fill = link_order->u.fill.value;
+ for (i = 0; i < size; i += 2)
+ space[i] = fill >> 8;
+ for (i = 1; i < size; i += 2)
+ space[i] = fill;
+ result = bfd_set_section_contents (abfd, sec, space,
+ (file_ptr) link_order->offset,
+ link_order->size);
+ free (space);
+ return result;
+}
+
+/* Default routine to handle a bfd_indirect_link_order. */
+
+static boolean
+default_indirect_link_order (output_bfd, info, output_section, link_order,
+ generic_linker)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ asection *output_section;
+ struct bfd_link_order *link_order;
+ boolean generic_linker;
+{
+ asection *input_section;
+ bfd *input_bfd;
+ bfd_byte *contents = NULL;
+ bfd_byte *new_contents;
+
+ 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;
+
+ BFD_ASSERT (input_section->output_section == output_section);
+ BFD_ASSERT (input_section->output_offset == link_order->offset);
+ BFD_ASSERT (input_section->_cooked_size == link_order->size);
+
+ if (info->relocateable
+ && input_section->reloc_count > 0
+ && output_section->orelocation == (arelent **) NULL)
+ {
+ /* Space has not been allocated for the output relocations.
+ This can happen when we are called by a specific backend
+ because somebody is attempting to link together different
+ types of object files. Handling this case correctly is
+ difficult, and sometimes impossible. */
+ abort ();
+ }
+
+ if (! generic_linker)
+ {
+ asymbol **sympp;
+ asymbol **symppend;
+
+ /* Get the canonical symbols. The generic linker will always
+ have retrieved them by this point, but we are being called by
+ a specific linker, presumably because we are linking
+ different types of object files together. */
+ if (! generic_link_read_symbols (input_bfd))
+ return false;
+
+ /* Since we have been called by a specific linker, rather than
+ the generic linker, the values of the symbols will not be
+ right. They will be the values as seen in the input file,
+ not the values of the final link. We need to fix them up
+ before we can relocate the section. */
+ sympp = _bfd_generic_link_get_symbols (input_bfd);
+ symppend = sympp + _bfd_generic_link_get_symcount (input_bfd);
+ for (; sympp < symppend; sympp++)
+ {
+ asymbol *sym;
+ struct bfd_link_hash_entry *h;
+
+ sym = *sympp;
+
+ if ((sym->flags & (BSF_INDIRECT
+ | BSF_WARNING
+ | BSF_GLOBAL
+ | BSF_CONSTRUCTOR
+ | BSF_WEAK)) != 0
+ || bfd_is_und_section (bfd_get_section (sym))
+ || bfd_is_com_section (bfd_get_section (sym))
+ || bfd_is_ind_section (bfd_get_section (sym)))
+ {
+ /* sym->udata may have been set by
+ generic_link_add_symbol_list. */
+ if (sym->udata.p != NULL)
+ h = (struct bfd_link_hash_entry *) sym->udata.p;
+ else if (bfd_is_und_section (bfd_get_section (sym)))
+ h = bfd_wrapped_link_hash_lookup (output_bfd, info,
+ bfd_asymbol_name (sym),
+ false, false, true);
+ else
+ h = bfd_link_hash_lookup (info->hash,
+ bfd_asymbol_name (sym),
+ false, false, true);
+ if (h != NULL)
+ set_symbol_from_hash (sym, h);
+ }
+ }
+ }
+
+ /* Get and relocate the section contents. */
+ contents = ((bfd_byte *)
+ bfd_malloc (bfd_section_size (input_bfd, input_section)));
+ if (contents == NULL && bfd_section_size (input_bfd, input_section) != 0)
+ goto error_return;
+ new_contents = (bfd_get_relocated_section_contents
+ (output_bfd, info, link_order, contents, info->relocateable,
+ _bfd_generic_link_get_symbols (input_bfd)));
+ if (!new_contents)
+ goto error_return;
+
+ /* Output the section contents. */
+ if (! bfd_set_section_contents (output_bfd, output_section,
+ (PTR) new_contents,
+ link_order->offset, link_order->size))
+ goto error_return;
+
+ if (contents != NULL)
+ free (contents);
+ return true;
+
+ error_return:
+ if (contents != NULL)
+ free (contents);
+ return false;
+}
+
+/* A little routine to count the number of relocs in a link_order
+ list. */
+
+unsigned int
+_bfd_count_link_order_relocs (link_order)
+ struct bfd_link_order *link_order;
+{
+ register unsigned int c;
+ register struct bfd_link_order *l;
+
+ c = 0;
+ for (l = link_order; l != (struct bfd_link_order *) NULL; l = l->next)
+ {
+ if (l->type == bfd_section_reloc_link_order
+ || l->type == bfd_symbol_reloc_link_order)
+ ++c;
+ }
+
+ return c;
+}
+
+/*
+FUNCTION
+ bfd_link_split_section
+
+SYNOPSIS
+ boolean bfd_link_split_section(bfd *abfd, asection *sec);
+
+DESCRIPTION
+ Return nonzero if @var{sec} should be split during a
+ reloceatable or final link.
+
+.#define bfd_link_split_section(abfd, sec) \
+. BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
+.
+
+*/
+
+
+
+boolean
+_bfd_generic_link_split_section (abfd, sec)
+ bfd *abfd;
+ asection *sec;
+{
+ return false;
+}
diff --git a/contrib/gdb/bfd/lynx-core.c b/contrib/gdb/bfd/lynx-core.c
new file mode 100644
index 0000000..2358177
--- /dev/null
+++ b/contrib/gdb/bfd/lynx-core.c
@@ -0,0 +1,233 @@
+/* BFD back end for Lynx core files
+ Copyright 1993 Free Software Foundation, Inc.
+ Written by Stu Grossman 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#ifdef LYNX_CORE
+
+#include <sys/conf.h>
+#include <sys/kernel.h>
+/* sys/kernel.h should define this, but doesn't always, sigh. */
+#ifndef __LYNXOS
+#define __LYNXOS
+#endif
+#include <sys/mem.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/itimer.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+
+/* These are stored in the bfd's tdata */
+
+struct lynx_core_struct
+{
+ int sig;
+ char cmd[PNMLEN + 1];
+};
+
+#define core_hdr(bfd) ((bfd)->tdata.lynx_core_data)
+#define core_signal(bfd) (core_hdr(bfd)->sig)
+#define core_command(bfd) (core_hdr(bfd)->cmd)
+
+/* Handle Lynx core dump file. */
+
+static asection *
+make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
+ bfd *abfd;
+ CONST char *name;
+ flagword flags;
+ bfd_size_type _raw_size;
+ bfd_vma vma;
+ file_ptr filepos;
+{
+ asection *asect;
+ char *newname;
+
+ newname = bfd_alloc (abfd, strlen (name) + 1);
+ if (!newname)
+ return NULL;
+
+ strcpy (newname, name);
+
+ asect = bfd_make_section (abfd, newname);
+ if (!asect)
+ return NULL;
+
+ asect->flags = flags;
+ asect->_raw_size = _raw_size;
+ asect->vma = vma;
+ asect->filepos = filepos;
+ asect->alignment_power = 2;
+
+ return asect;
+}
+
+/* ARGSUSED */
+const bfd_target *
+lynx_core_file_p (abfd)
+ bfd *abfd;
+{
+ int val;
+ int secnum;
+ struct pssentry pss;
+ size_t tcontext_size;
+ core_st_t *threadp;
+ int pagesize;
+ asection *newsect;
+
+ pagesize = getpagesize (); /* Serious cross-target issue here... This
+ really needs to come from a system-specific
+ header file. */
+
+ /* Get the pss entry from the core file */
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+ return NULL;
+
+ val = bfd_read ((void *)&pss, 1, sizeof pss, abfd);
+ if (val != sizeof pss)
+ {
+ /* Too small to be a core file */
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ core_hdr (abfd) = (struct lynx_core_struct *)
+ bfd_zalloc (abfd, sizeof (struct lynx_core_struct));
+
+ if (!core_hdr (abfd))
+ return NULL;
+
+ strncpy (core_command (abfd), pss.pname, PNMLEN + 1);
+
+ /* Compute the size of the thread contexts */
+
+ tcontext_size = pss.threadcnt * sizeof (core_st_t);
+
+ /* Allocate space for the thread contexts */
+
+ threadp = (core_st_t *)bfd_alloc (abfd, tcontext_size);
+ if (!threadp)
+ return NULL;
+
+ /* Save thread contexts */
+
+ if (bfd_seek (abfd, pagesize, SEEK_SET) != 0)
+ return NULL;
+
+ val = bfd_read ((void *)threadp, pss.threadcnt, sizeof (core_st_t), abfd);
+
+ if (val != tcontext_size)
+ {
+ /* Probably too small to be a core file */
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ core_signal (abfd) = threadp->currsig;
+
+ newsect = make_bfd_asection (abfd, ".stack",
+ SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
+ pss.ssize,
+ pss.slimit,
+ pagesize + tcontext_size);
+ if (!newsect)
+ return NULL;
+
+ newsect = make_bfd_asection (abfd, ".data",
+ SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS,
+ pss.data_len + pss.bss_len,
+ pss.data_start,
+ pagesize + tcontext_size + pss.ssize
+#if defined (SPARC) || defined (__SPARC__)
+ /* SPARC Lynx seems to start dumping
+ the .data section at a page
+ boundary. It's OK to check a
+ #define like SPARC here because this
+ file can only be compiled on a Lynx
+ host. */
+ + pss.data_start % pagesize
+#endif
+ );
+ if (!newsect)
+ return NULL;
+
+/* And, now for the .reg/XXX pseudo sections. Each thread has it's own
+ .reg/XXX section, where XXX is the thread id (without leading zeros). The
+ currently running thread (at the time of the core dump) also has an alias
+ called `.reg' (just to keep GDB happy). Note that we use `.reg/XXX' as
+ opposed to `.regXXX' because GDB expects that .reg2 will be the floating-
+ point registers. */
+
+ newsect = make_bfd_asection (abfd, ".reg",
+ SEC_HAS_CONTENTS,
+ sizeof (core_st_t),
+ 0,
+ pagesize);
+ if (!newsect)
+ return NULL;
+
+ for (secnum = 0; secnum < pss.threadcnt; secnum++)
+ {
+ char secname[100];
+
+ sprintf (secname, ".reg/%d", BUILDPID (0, threadp[secnum].tid));
+ newsect = make_bfd_asection (abfd, secname,
+ SEC_HAS_CONTENTS,
+ sizeof (core_st_t),
+ 0,
+ pagesize + secnum * sizeof (core_st_t));
+ if (!newsect)
+ return NULL;
+ }
+
+ return abfd->xvec;
+}
+
+char *
+lynx_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return core_command (abfd);
+}
+
+/* ARGSUSED */
+int
+lynx_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_signal (abfd);
+}
+
+/* ARGSUSED */
+boolean
+lynx_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this point */
+}
+
+#endif /* LYNX_CORE */
diff --git a/contrib/gdb/bfd/m68k4knetbsd.c b/contrib/gdb/bfd/m68k4knetbsd.c
new file mode 100644
index 0000000..c1ecb43
--- /dev/null
+++ b/contrib/gdb/bfd/m68k4knetbsd.c
@@ -0,0 +1,35 @@
+/* BFD back-end for NetBSD/m68k a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#define TARGET_IS_BIG_ENDIAN_P
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE 4096
+
+#define DEFAULT_ARCH bfd_arch_m68k
+#define MACHTYPE_OK(mtype) \
+ ((mtype) == M_68020 || (mtype) == M_68K_NETBSD || (mtype) == M_68K4K_NETBSD \
+ || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(m68k4knetbsd_,OP)
+/* This needs to start with a.out so GDB knows it is an a.out variant. */
+#define TARGETNAME "a.out-m68k4k-netbsd"
+
+#include "netbsd.h"
diff --git a/contrib/gdb/bfd/m68klinux.c b/contrib/gdb/bfd/m68klinux.c
new file mode 100644
index 0000000..062165b
--- /dev/null
+++ b/contrib/gdb/bfd/m68klinux.c
@@ -0,0 +1,767 @@
+/* BFD back-end for linux flavored m68k a.out binaries.
+ Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_PAGE_SIZE 4096
+#define ZMAGIC_DISK_BLOCK_SIZE 1024
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define TEXT_START_ADDR 0x0
+#define N_SHARED_LIB(x) 0
+#define BYTES_IN_WORD 4
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#define TARGET_IS_BIG_ENDIAN_P
+#define DEFAULT_ARCH bfd_arch_m68k
+#define MY(OP) CAT(m68klinux_,OP)
+#define TARGETNAME "a.out-m68k-linux"
+
+extern const bfd_target MY(vec);
+
+/* We always generate QMAGIC files in preference to ZMAGIC files. It
+ would be possible to make this a linker option, if that ever
+ becomes important. */
+
+static void MY_final_link_callback
+ PARAMS ((bfd *, file_ptr *, file_ptr *, file_ptr *));
+
+static boolean
+m68klinux_bfd_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ obj_aout_subformat (abfd) = q_magic_format;
+ return NAME(aout,final_link) (abfd, info, MY_final_link_callback);
+}
+
+#define MY_bfd_final_link m68klinux_bfd_final_link
+
+/* Set the machine type correctly. */
+
+static boolean
+m68klinux_write_object_contents (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ N_SET_MACHTYPE (*execp, M_68020);
+
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
+
+#define MY_write_object_contents m68klinux_write_object_contents
+
+/* Code to link against Linux a.out shared libraries. */
+
+/* See if a symbol name is a reference to the global offset table. */
+
+#ifndef GOT_REF_PREFIX
+#define GOT_REF_PREFIX "__GOT_"
+#endif
+
+#define IS_GOT_SYM(name) \
+ (strncmp (name, GOT_REF_PREFIX, sizeof GOT_REF_PREFIX - 1) == 0)
+
+/* See if a symbol name is a reference to the procedure linkage table. */
+
+#ifndef PLT_REF_PREFIX
+#define PLT_REF_PREFIX "__PLT_"
+#endif
+
+#define IS_PLT_SYM(name) \
+ (strncmp (name, PLT_REF_PREFIX, sizeof PLT_REF_PREFIX - 1) == 0)
+
+/* This string is used to generate specialized error messages. */
+
+#ifndef NEEDS_SHRLIB
+#define NEEDS_SHRLIB "__NEEDS_SHRLIB_"
+#endif
+
+/* This special symbol is a set vector that contains a list of
+ pointers to fixup tables. It will be present in any dynamicly
+ linked file. The linker generated fixup table should also be added
+ to the list, and it should always appear in the second slot (the
+ first one is a dummy with a magic number that is defined in
+ crt0.o). */
+
+#ifndef SHARABLE_CONFLICTS
+#define SHARABLE_CONFLICTS "__SHARABLE_CONFLICTS__"
+#endif
+
+/* We keep a list of fixups. The terminology is a bit strange, but
+ each fixup contains two 32 bit numbers. A regular fixup contains
+ an address and a pointer, and at runtime we should store the
+ address at the location pointed to by the pointer. A builtin fixup
+ contains two pointers, and we should read the address using one
+ pointer and store it at the location pointed to by the other
+ pointer. Builtin fixups come into play when we have duplicate
+ __GOT__ symbols for the same variable. The builtin fixup will copy
+ the GOT pointer from one over into the other. */
+
+struct fixup
+{
+ struct fixup *next;
+ struct linux_link_hash_entry *h;
+ bfd_vma value;
+
+ /* Nonzero if this is a jump instruction that needs to be fixed,
+ zero if this is just a pointer */
+ char jump;
+
+ char builtin;
+};
+
+/* We don't need a special hash table entry structure, but we do need
+ to keep some information between linker passes, so we use a special
+ hash table. */
+
+struct linux_link_hash_entry
+{
+ struct aout_link_hash_entry root;
+};
+
+struct linux_link_hash_table
+{
+ struct aout_link_hash_table root;
+
+ /* First dynamic object found in link. */
+ bfd *dynobj;
+
+ /* Number of fixups. */
+ size_t fixup_count;
+
+ /* Number of builtin fixups. */
+ size_t local_builtins;
+
+ /* List of fixups. */
+ struct fixup *fixup_list;
+};
+
+static struct bfd_hash_entry *linux_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static struct bfd_link_hash_table *linux_link_hash_table_create
+ PARAMS ((bfd *));
+static struct fixup *new_fixup
+ PARAMS ((struct bfd_link_info *, struct linux_link_hash_entry *,
+ bfd_vma, int));
+static boolean linux_link_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean linux_add_one_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
+ bfd_vma, const char *, boolean, boolean,
+ struct bfd_link_hash_entry **));
+static boolean linux_tally_symbols
+ PARAMS ((struct linux_link_hash_entry *, PTR));
+static boolean linux_finish_dynamic_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+/* Routine to create an entry in an Linux link hash table. */
+
+static struct bfd_hash_entry *
+linux_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct linux_link_hash_entry *ret = (struct linux_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct linux_link_hash_entry *) NULL)
+ ret = ((struct linux_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct linux_link_hash_entry)));
+ if (ret == NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct linux_link_hash_entry *)
+ NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != NULL)
+ {
+ /* Set local fields; there aren't any. */
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create a Linux link hash table. */
+
+static struct bfd_link_hash_table *
+linux_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct linux_link_hash_table *ret;
+
+ ret = ((struct linux_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct linux_link_hash_table)));
+ if (ret == (struct linux_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->root, abfd,
+ linux_link_hash_newfunc))
+ {
+ free (ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+
+ ret->dynobj = NULL;
+ ret->fixup_count = 0;
+ ret->local_builtins = 0;
+ ret->fixup_list = NULL;
+
+ return &ret->root.root;
+}
+
+/* Look up an entry in a Linux link hash table. */
+
+#define linux_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct linux_link_hash_entry *) \
+ aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
+ (follow)))
+
+/* Traverse a Linux link hash table. */
+
+#define linux_link_hash_traverse(table, func, info) \
+ (aout_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the Linux link hash table from the info structure. This is
+ just a cast. */
+
+#define linux_hash_table(p) ((struct linux_link_hash_table *) ((p)->hash))
+
+/* Store the information for a new fixup. */
+
+static struct fixup *
+new_fixup (info, h, value, builtin)
+ struct bfd_link_info *info;
+ struct linux_link_hash_entry *h;
+ bfd_vma value;
+ int builtin;
+{
+ struct fixup *f;
+
+ f = (struct fixup *) bfd_hash_allocate (&info->hash->table,
+ sizeof (struct fixup));
+ if (f == NULL)
+ return f;
+ f->next = linux_hash_table (info)->fixup_list;
+ linux_hash_table (info)->fixup_list = f;
+ f->h = h;
+ f->value = value;
+ f->builtin = builtin;
+ f->jump = 0;
+ ++linux_hash_table (info)->fixup_count;
+ return f;
+}
+
+/* We come here once we realize that we are going to link to a shared
+ library. We need to create a special section that contains the
+ fixup table, and we ultimately need to add a pointer to this into
+ the set vector for SHARABLE_CONFLICTS. At this point we do not
+ know the size of the section, but that's OK - we just need to
+ create it for now. */
+
+static boolean
+linux_link_create_dynamic_sections (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ flagword flags;
+ register asection *s;
+
+ /* Note that we set the SEC_IN_MEMORY flag. */
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ /* We choose to use the name ".linux-dynamic" for the fixup table.
+ Why not? */
+ s = bfd_make_section (abfd, ".linux-dynamic");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+ s->_raw_size = 0;
+ s->contents = 0;
+
+ return true;
+}
+
+/* Function to add a single symbol to the linker hash table. This is
+ a wrapper around _bfd_generic_link_add_one_symbol which handles the
+ tweaking needed for dynamic linking support. */
+
+static boolean
+linux_add_one_symbol (info, abfd, name, flags, section, value, string,
+ copy, collect, hashp)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ const char *name;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ const char *string;
+ boolean copy;
+ boolean collect;
+ struct bfd_link_hash_entry **hashp;
+{
+ struct linux_link_hash_entry *h;
+ boolean insert;
+
+ /* Look up and see if we already have this symbol in the hash table.
+ If we do, and the defining entry is from a shared library, we
+ need to create the dynamic sections.
+
+ FIXME: What if abfd->xvec != info->hash->creator? We may want to
+ be able to link Linux a.out and ELF objects together, but serious
+ confusion is possible. */
+
+ insert = false;
+
+ if (! info->relocateable
+ && linux_hash_table (info)->dynobj == NULL
+ && strcmp (name, SHARABLE_CONFLICTS) == 0
+ && (flags & BSF_CONSTRUCTOR) != 0
+ && abfd->xvec == info->hash->creator)
+ {
+ if (! linux_link_create_dynamic_sections (abfd, info))
+ return false;
+ linux_hash_table (info)->dynobj = abfd;
+ insert = true;
+ }
+
+ if (bfd_is_abs_section (section)
+ && abfd->xvec == info->hash->creator)
+ {
+ h = linux_link_hash_lookup (linux_hash_table (info), name, false,
+ false, false);
+ if (h != NULL
+ && (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak))
+ {
+ struct fixup *f;
+
+ if (hashp != NULL)
+ *hashp = (struct bfd_link_hash_entry *) h;
+
+ f = new_fixup (info, h, value, ! IS_PLT_SYM (name));
+ if (f == NULL)
+ return false;
+ f->jump = IS_PLT_SYM (name);
+
+ return true;
+ }
+ }
+
+ /* Do the usual procedure for adding a symbol. */
+ if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
+ value, string, copy, collect,
+ hashp))
+ return false;
+
+ /* Insert a pointer to our table in the set vector. The dynamic
+ linker requires this information */
+ if (insert)
+ {
+ asection *s;
+
+ /* Here we do our special thing to add the pointer to the
+ dynamic section in the SHARABLE_CONFLICTS set vector. */
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ BFD_ASSERT (s != NULL);
+
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, linux_hash_table (info)->dynobj, SHARABLE_CONFLICTS,
+ BSF_GLOBAL | BSF_CONSTRUCTOR, s, 0, NULL, false, false, NULL)))
+ return false;
+ }
+
+ return true;
+}
+
+/* We will crawl the hash table and come here for every global symbol.
+ We will examine each entry and see if there are indications that we
+ need to add a fixup. There are two possible cases - one is where
+ you have duplicate definitions of PLT or GOT symbols - these will
+ have already been caught and added as "builtin" fixups. If we find
+ that the corresponding non PLT/GOT symbol is also present, we
+ convert it to a regular fixup instead.
+
+ This function is called via linux_link_hash_traverse. */
+
+static boolean
+linux_tally_symbols (h, data)
+ struct linux_link_hash_entry *h;
+ PTR data;
+{
+ struct bfd_link_info *info = (struct bfd_link_info *) data;
+ struct fixup *f, *f1;
+ int is_plt;
+ struct linux_link_hash_entry *h1, *h2;
+ boolean exists;
+
+ if (h->root.root.type == bfd_link_hash_undefined
+ && strncmp (h->root.root.root.string, NEEDS_SHRLIB,
+ sizeof NEEDS_SHRLIB - 1) == 0)
+ {
+ const char *name;
+ char *p;
+ char *alloc = NULL;
+
+ name = h->root.root.root.string + sizeof NEEDS_SHRLIB - 1;
+ p = strrchr (name, '_');
+ if (p != NULL)
+ alloc = (char *) bfd_malloc (strlen (name) + 1);
+
+ if (p == NULL || alloc == NULL)
+ (*_bfd_error_handler) ("Output file requires shared library `%s'\n",
+ name);
+ else
+ {
+ strcpy (alloc, name);
+ p = strrchr (alloc, '_');
+ *p++ = '\0';
+ (*_bfd_error_handler)
+ ("Output file requires shared library `%s.so.%s'\n",
+ alloc, p);
+ free (alloc);
+ }
+
+ abort ();
+ }
+
+ /* If this symbol is not a PLT/GOT, we do not even need to look at it */
+ is_plt = IS_PLT_SYM (h->root.root.root.string);
+
+ if (is_plt || IS_GOT_SYM (h->root.root.root.string))
+ {
+ /* Look up this symbol twice. Once just as a regular lookup,
+ and then again following all of the indirect links until we
+ reach a real symbol. */
+ h1 = linux_link_hash_lookup (linux_hash_table (info),
+ (h->root.root.root.string
+ + sizeof PLT_REF_PREFIX - 1),
+ false, false, true);
+ /* h2 does not follow indirect symbols. */
+ h2 = linux_link_hash_lookup (linux_hash_table (info),
+ (h->root.root.root.string
+ + sizeof PLT_REF_PREFIX - 1),
+ false, false, false);
+
+ /* The real symbol must exist but if it is also an ABS symbol,
+ there is no need to have a fixup. This is because they both
+ came from the same library. If on the other hand, we had to
+ use an indirect symbol to get to the real symbol, we add the
+ fixup anyway, since there are cases where these symbols come
+ from different shared libraries */
+ if (h1 != NULL
+ && (((h1->root.root.type == bfd_link_hash_defined
+ || h1->root.root.type == bfd_link_hash_defweak)
+ && ! bfd_is_abs_section (h1->root.root.u.def.section))
+ || h2->root.root.type == bfd_link_hash_indirect))
+ {
+ /* See if there is a "builtin" fixup already present
+ involving this symbol. If so, convert it to a regular
+ fixup. In the end, this relaxes some of the requirements
+ about the order of performing fixups. */
+ exists = false;
+ for (f1 = linux_hash_table (info)->fixup_list;
+ f1 != NULL;
+ f1 = f1->next)
+ {
+ if ((f1->h != h && f1->h != h1)
+ || (! f1->builtin && ! f1->jump))
+ continue;
+ if (f1->h == h1)
+ exists = true;
+ if (! exists
+ && bfd_is_abs_section (h->root.root.u.def.section))
+ {
+ f = new_fixup (info, h1, f1->h->root.root.u.def.value, 0);
+ f->jump = is_plt;
+ }
+ f1->h = h1;
+ f1->jump = is_plt;
+ f1->builtin = 0;
+ exists = true;
+ }
+ if (! exists
+ && bfd_is_abs_section (h->root.root.u.def.section))
+ {
+ f = new_fixup (info, h1, h->root.root.u.def.value, 0);
+ if (f == NULL)
+ {
+ /* FIXME: No way to return error. */
+ abort ();
+ }
+ f->jump = is_plt;
+ }
+ }
+
+ /* Quick and dirty way of stripping these symbols from the
+ symtab. */
+ if (bfd_is_abs_section (h->root.root.u.def.section))
+ h->root.written = true;
+ }
+
+ return true;
+}
+
+/* This is called to set the size of the .linux-dynamic section is.
+ It is called by the Linux linker emulation before_allocation
+ routine. We have finished reading all of the input files, and now
+ we just scan the hash tables to find out how many additional fixups
+ are required. */
+
+boolean
+bfd_m68klinux_size_dynamic_sections (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ struct fixup *f;
+ asection *s;
+
+ if (output_bfd->xvec != &MY(vec))
+ return true;
+
+ /* First find the fixups... */
+ linux_link_hash_traverse (linux_hash_table (info),
+ linux_tally_symbols,
+ (PTR) info);
+
+ /* If there are builtin fixups, leave room for a marker. This is
+ used by the dynamic linker so that it knows that all that follow
+ are builtin fixups instead of regular fixups. */
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (f->builtin)
+ {
+ ++linux_hash_table (info)->fixup_count;
+ ++linux_hash_table (info)->local_builtins;
+ break;
+ }
+ }
+
+ if (linux_hash_table (info)->dynobj == NULL)
+ {
+ if (linux_hash_table (info)->fixup_count > 0)
+ abort ();
+ return true;
+ }
+
+ /* Allocate memory for our fixup table. We will fill it in later. */
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ if (s != NULL)
+ {
+ s->_raw_size = 8 + linux_hash_table (info)->fixup_count * 8;
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return false;
+ }
+ memset (s->contents, 0, (size_t) s->_raw_size);
+ }
+
+ return true;
+}
+
+/* We come here once we are ready to actually write the fixup table to
+ the output file. Scan the fixup tables and so forth and generate
+ the stuff we need. */
+
+static boolean
+linux_finish_dynamic_link (output_bfd, info)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+{
+ asection *s, *os, *is;
+ bfd_byte *fixup_table;
+ struct linux_link_hash_entry *h;
+ struct fixup *f;
+ unsigned int new_addr;
+ int section_offset;
+ unsigned int fixups_written;
+
+ if (linux_hash_table (info)->dynobj == NULL)
+ return true;
+
+ s = bfd_get_section_by_name (linux_hash_table (info)->dynobj,
+ ".linux-dynamic");
+ BFD_ASSERT (s != NULL);
+ os = s->output_section;
+ fixups_written = 0;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup table file offset: %x VMA: %x\n",
+ os->filepos + s->output_offset,
+ os->vma + s->output_offset);
+#endif
+
+ fixup_table = s->contents;
+ bfd_put_32 (output_bfd, linux_hash_table (info)->fixup_count, fixup_table);
+ fixup_table += 4;
+
+ /* Fill in fixup table. */
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (f->builtin)
+ continue;
+
+ if (f->h->root.root.type != bfd_link_hash_defined
+ && f->h->root.root.type != bfd_link_hash_defweak)
+ {
+ (*_bfd_error_handler)
+ ("Symbol %s not defined for fixups\n",
+ f->h->root.root.root.string);
+ continue;
+ }
+
+ is = f->h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = f->h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup(%d) %s: %x %x\n",f->jump, f->h->root.root.string,
+ new_addr, f->value);
+#endif
+
+ if (f->jump)
+ {
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value + 2, fixup_table);
+ fixup_table += 4;
+ }
+ else
+ {
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value, fixup_table);
+ fixup_table += 4;
+ }
+ ++fixups_written;
+ }
+
+ if (linux_hash_table (info)->local_builtins != 0)
+ {
+ /* Special marker so we know to switch to the other type of fixup */
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ for (f = linux_hash_table (info)->fixup_list; f != NULL; f = f->next)
+ {
+ if (! f->builtin)
+ continue;
+
+ if (f->h->root.root.type != bfd_link_hash_defined
+ && f->h->root.root.type != bfd_link_hash_defweak)
+ {
+ (*_bfd_error_handler)
+ ("Symbol %s not defined for fixups\n",
+ f->h->root.root.root.string);
+ continue;
+ }
+
+ is = f->h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = f->h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Fixup(B) %s: %x %x\n", f->h->root.root.string,
+ new_addr, f->value);
+#endif
+
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, f->value, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ }
+ }
+
+ if (linux_hash_table (info)->fixup_count != fixups_written)
+ {
+ (*_bfd_error_handler) ("Warning: fixup count mismatch\n");
+ while (linux_hash_table (info)->fixup_count > fixups_written)
+ {
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ bfd_put_32 (output_bfd, 0, fixup_table);
+ fixup_table += 4;
+ ++fixups_written;
+ }
+ }
+
+ h = linux_link_hash_lookup (linux_hash_table (info),
+ "__BUILTIN_FIXUPS__",
+ false, false, false);
+
+ if (h != NULL
+ && (h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak))
+ {
+ is = h->root.root.u.def.section;
+ section_offset = is->output_section->vma + is->output_offset;
+ new_addr = h->root.root.u.def.value + section_offset;
+
+#ifdef LINUX_LINK_DEBUG
+ printf ("Builtin fixup table at %x\n", new_addr);
+#endif
+
+ bfd_put_32 (output_bfd, new_addr, fixup_table);
+ }
+ else
+ bfd_put_32 (output_bfd, 0, fixup_table);
+
+ if (bfd_seek (output_bfd, os->filepos + s->output_offset, SEEK_SET) != 0)
+ return false;
+
+ if (bfd_write ((PTR) s->contents, 1, s->_raw_size, output_bfd)
+ != s->_raw_size)
+ return false;
+
+ return true;
+}
+
+#define MY_bfd_link_hash_table_create linux_link_hash_table_create
+#define MY_add_one_symbol linux_add_one_symbol
+#define MY_finish_dynamic_link linux_finish_dynamic_link
+
+#define MY_zmagic_contiguous 1
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/m68klynx.c b/contrib/gdb/bfd/m68klynx.c
new file mode 100644
index 0000000..7acdfbc
--- /dev/null
+++ b/contrib/gdb/bfd/m68klynx.c
@@ -0,0 +1,54 @@
+/* BFD back-end for m68k binaries under LynxOS.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#define N_SHARED_LIB(x) 0
+
+#define TEXT_START_ADDR 0
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_m68k
+
+#define MY(OP) CAT(m68klynx_aout_,OP)
+#define TARGETNAME "a.out-m68k-lynx"
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "libaout.h"
+#include "aout/aout64.h"
+
+#define TARGET_IS_BIG_ENDIAN_P
+
+#ifdef LYNX_CORE
+
+char *lynx_core_file_failing_command();
+int lynx_core_file_failing_signal();
+boolean lynx_core_file_matches_executable_p();
+const bfd_target *lynx_core_file_p();
+
+#define MY_core_file_failing_command lynx_core_file_failing_command
+#define MY_core_file_failing_signal lynx_core_file_failing_signal
+#define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
+#define MY_core_file_p lynx_core_file_p
+
+#endif /* LYNX_CORE */
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/m68knetbsd.c b/contrib/gdb/bfd/m68knetbsd.c
new file mode 100644
index 0000000..3bff530
--- /dev/null
+++ b/contrib/gdb/bfd/m68knetbsd.c
@@ -0,0 +1,35 @@
+/* BFD back-end for NetBSD/m68k a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#define TARGET_IS_BIG_ENDIAN_P
+
+#define TARGET_PAGE_SIZE 8192
+#define SEGMENT_SIZE 8192
+
+#define DEFAULT_ARCH bfd_arch_m68k
+#define MACHTYPE_OK(mtype) \
+ ((mtype) == M_68020 || (mtype) == M_68K_NETBSD || (mtype) == M_68K4K_NETBSD \
+ || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(m68knetbsd_,OP)
+/* This needs to start with a.out so GDB knows it is an a.out variant. */
+#define TARGETNAME "a.out-m68k-netbsd"
+
+#include "netbsd.h"
diff --git a/contrib/gdb/bfd/m88kmach3.c b/contrib/gdb/bfd/m88kmach3.c
new file mode 100644
index 0000000..7a56408
--- /dev/null
+++ b/contrib/gdb/bfd/m88kmach3.c
@@ -0,0 +1,38 @@
+/* BFD back-end for Motorola m88k a.out (Mach 3) binaries.
+ Copyright (C) 1990, 1991, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_PAGE_SIZE (4096*2)
+#define SEGMENT_SIZE 0x20000
+#define TEXT_START_ADDR 0
+#define BYTES_IN_WORD 4
+#define N_HEADER_IN_TEXT(x) 1 /* (N_MAGIG(x) == ZMAGIC) */
+#define N_SHARED_LIB(x) 0
+
+#define N_TXTSIZE(x) ((x).a_text)
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+#define DEFAULT_ARCH bfd_arch_m88k
+#define MY(OP) CAT(m88kmach3_,OP)
+#define TARGETNAME "a.out-m88k-mach3"
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/makefile.dos b/contrib/gdb/bfd/makefile.dos
new file mode 100644
index 0000000..8a22c6a
--- /dev/null
+++ b/contrib/gdb/bfd/makefile.dos
@@ -0,0 +1,49 @@
+CFLAGS=-O2
+
+.c.o :
+ gcc $(CFLAGS) -I. -I../include -c $<
+
+all : libbfd.a
+
+targets.o : targets.c
+ gcc $(CFLAGS) -I. -I../include -DSELECT_VECS=&go32coff_vec,&i386aout_vec -DDEFAULT_VECTOR=go32coff_vec -c $*.c
+
+archures.o : archures.c
+ gcc $(CFLAGS) -I. -I../include -DSELECT_ARCHITECTURES=bfd_i386_arch -c $*.c
+
+OBJS = \
+ libbfd.o \
+ opncls.o \
+ bfd.o \
+ archive.o \
+ targets.o \
+ cache.o \
+ archures.o \
+ corefile.o \
+ section.o \
+ format.o \
+ syms.o \
+ reloc.o \
+ init.o \
+ coffgen.o \
+ srec.o \
+ hash.o \
+ linker.o \
+ ecoff.o \
+ ecofflink.o \
+ elf.o \
+ aout32.o \
+ stab-sym.o \
+ i386aout.o \
+ cpu-i386.o \
+ coff-go32.o \
+ cofflink.o \
+ elf32.o \
+ binary.o \
+ tekhex.o \
+ $E
+
+libbfd.a : $(OBJS)
+ -rm libbfd.a
+ ar rvs libbfd.a $(OBJS)
+ ranlib libbfd.a
diff --git a/contrib/gdb/bfd/mipsbsd.c b/contrib/gdb/bfd/mipsbsd.c
new file mode 100644
index 0000000..801f360
--- /dev/null
+++ b/contrib/gdb/bfd/mipsbsd.c
@@ -0,0 +1,467 @@
+/* BFD backend for MIPS BSD (a.out) binaries.
+ Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by Ralph Campbell.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+/* #define ENTRY_CAN_BE_ZERO */
+#define N_HEADER_IN_TEXT(x) 1
+#define N_SHARED_LIB(x) 0
+#define N_TXTADDR(x) \
+ (N_MAGIC(x) != ZMAGIC ? (x).a_entry : /* object file or NMAGIC */\
+ TEXT_START_ADDR + EXEC_BYTES_SIZE /* no padding */\
+ )
+#define N_DATADDR(x) (N_TXTADDR(x)+N_TXTSIZE(x))
+#define TEXT_START_ADDR 4096
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_mips
+#define MACHTYPE_OK(mtype) ((mtype) == M_UNKNOWN \
+ || (mtype) == M_MIPS1 || (mtype) == M_MIPS2)
+#define MY_symbol_leading_char '\0'
+
+#define MY(OP) CAT(mipsbsd_,OP)
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+#define SET_ARCH_MACH(ABFD, EXEC) \
+ MY(set_arch_mach)(ABFD, N_MACHTYPE (EXEC)); \
+ MY(choose_reloc_size)(ABFD);
+void MY(set_arch_mach) PARAMS ((bfd *abfd, int machtype));
+static void MY(choose_reloc_size) PARAMS ((bfd *abfd));
+
+#define MY_write_object_contents MY(write_object_contents)
+static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
+
+/* We can't use MY(x) here because it leads to a recursive call to CAT
+ when expanded inside JUMP_TABLE. */
+#define MY_bfd_reloc_type_lookup mipsbsd_reloc_howto_type_lookup
+#define MY_canonicalize_reloc mipsbsd_canonicalize_reloc
+
+#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define MY_final_link_callback unused
+#define MY_bfd_final_link _bfd_generic_final_link
+
+#define MY_backend_data &MY(backend_data)
+#define MY_BFD_TARGET
+
+#include "aout-target.h"
+
+void
+MY(set_arch_mach) (abfd, machtype)
+ bfd *abfd;
+ int machtype;
+{
+ enum bfd_architecture arch;
+ long machine;
+
+ /* Determine the architecture and machine type of the object file. */
+ switch (machtype) {
+
+ case M_MIPS1:
+ arch = bfd_arch_mips;
+ machine = 3000;
+ break;
+
+ case M_MIPS2:
+ arch = bfd_arch_mips;
+ machine = 4000;
+ break;
+
+ default:
+ arch = bfd_arch_obscure;
+ machine = 0;
+ break;
+ }
+ bfd_set_arch_mach(abfd, arch, machine);
+}
+
+/* Determine the size of a relocation entry, based on the architecture */
+static void
+MY(choose_reloc_size) (abfd)
+ bfd *abfd;
+{
+ switch (bfd_get_arch(abfd)) {
+ case bfd_arch_sparc:
+ case bfd_arch_a29k:
+ case bfd_arch_mips:
+ obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
+ break;
+ default:
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+ break;
+ }
+}
+
+/* Write an object file in BSD a.out format.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+static boolean
+MY(write_object_contents) (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ /* Magic number, maestro, please! */
+ switch (bfd_get_arch(abfd)) {
+ case bfd_arch_m68k:
+ switch (bfd_get_mach(abfd)) {
+ case 68010:
+ N_SET_MACHTYPE(*execp, M_68010);
+ break;
+ default:
+ case 68020:
+ N_SET_MACHTYPE(*execp, M_68020);
+ break;
+ }
+ break;
+ case bfd_arch_sparc:
+ N_SET_MACHTYPE(*execp, M_SPARC);
+ break;
+ case bfd_arch_i386:
+ N_SET_MACHTYPE(*execp, M_386);
+ break;
+ case bfd_arch_a29k:
+ N_SET_MACHTYPE(*execp, M_29K);
+ break;
+ case bfd_arch_mips:
+ switch (bfd_get_mach(abfd)) {
+ case 4000:
+ case 6000:
+ N_SET_MACHTYPE(*execp, M_MIPS2);
+ break;
+ default:
+ N_SET_MACHTYPE(*execp, M_MIPS1);
+ break;
+ }
+ break;
+ default:
+ N_SET_MACHTYPE(*execp, M_UNKNOWN);
+ }
+
+ MY(choose_reloc_size)(abfd);
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
+
+/*
+ * MIPS relocation types.
+ */
+#define MIPS_RELOC_32 0
+#define MIPS_RELOC_JMP 1
+#define MIPS_RELOC_WDISP16 2
+#define MIPS_RELOC_HI16 3
+#define MIPS_RELOC_HI16_S 4
+#define MIPS_RELOC_LO16 5
+
+/*
+ * This is only called when performing a BFD_RELOC_MIPS_JMP relocation.
+ * The jump destination address is formed from the upper 4 bits of the
+ * "current" program counter concatenated with the jump instruction's
+ * 26 bit field and two trailing zeros.
+ * If the destination address is not in the same segment as the "current"
+ * program counter, then we need to signal an error.
+ */
+static bfd_reloc_status_type
+mips_fix_jmp_addr (abfd,reloc_entry,symbol,data,input_section,output_bfd)
+ bfd *abfd;
+ arelent *reloc_entry;
+ struct symbol_cache_entry *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+{
+ bfd_vma relocation, pc;
+
+ /* If this is a partial relocation, just continue. */
+ if (output_bfd != (bfd *)NULL)
+ return bfd_reloc_continue;
+
+ /* If this is an undefined symbol, return error */
+ if (bfd_is_und_section (symbol->section)
+ && (symbol->flags & BSF_WEAK) == 0)
+ return bfd_reloc_undefined;
+
+ /*
+ * Work out which section the relocation is targetted at and the
+ * initial relocation command value.
+ */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+
+ pc = input_section->output_section->vma + input_section->output_offset +
+ reloc_entry->address + 4;
+
+ if ((relocation & 0xF0000000) != (pc & 0xF0000000))
+ return bfd_reloc_overflow;
+
+ return bfd_reloc_continue;
+}
+
+/*
+ * This is only called when performing a BFD_RELOC_HI16_S relocation.
+ * We need to see if bit 15 is set in the result. If it is, we add
+ * 0x10000 and continue normally. This will compensate for the sign extension
+ * when the low bits are added at run time.
+ */
+static bfd_reloc_status_type
+mips_fix_hi16_s PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+static bfd_reloc_status_type
+mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_vma relocation;
+
+ /* If this is a partial relocation, just continue. */
+ if (output_bfd != (bfd *)NULL)
+ return bfd_reloc_continue;
+
+ /* If this is an undefined symbol, return error */
+ if (bfd_is_und_section (symbol->section)
+ && (symbol->flags & BSF_WEAK) == 0)
+ return bfd_reloc_undefined;
+
+ /*
+ * Work out which section the relocation is targetted at and the
+ * initial relocation command value.
+ */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+
+ if (relocation & 0x8000)
+ reloc_entry->addend += 0x10000;
+
+ return bfd_reloc_continue;
+}
+
+static reloc_howto_type mips_howto_table_ext[] = {
+ {MIPS_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield, 0,
+ "32", false, 0, 0xffffffff, false},
+ {MIPS_RELOC_JMP, 2, 2, 26, false, 0, complain_overflow_dont,
+ mips_fix_jmp_addr,
+ "MIPS_JMP", false, 0, 0x03ffffff, false},
+ {MIPS_RELOC_WDISP16, 2, 2, 16, true, 0, complain_overflow_signed, 0,
+ "WDISP16", false, 0, 0x0000ffff, false},
+ {MIPS_RELOC_HI16, 16, 2, 16, false, 0, complain_overflow_bitfield, 0,
+ "HI16", false, 0, 0x0000ffff, false},
+ {MIPS_RELOC_HI16_S, 16, 2, 16, false, 0, complain_overflow_bitfield,
+ mips_fix_hi16_s,
+ "HI16_S", false, 0, 0x0000ffff, false},
+ {MIPS_RELOC_LO16, 0, 2, 16, false, 0, complain_overflow_dont, 0,
+ "LO16", false, 0, 0x0000ffff, false},
+};
+
+static reloc_howto_type *
+MY(reloc_howto_type_lookup) (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+
+ if (bfd_get_arch (abfd) != bfd_arch_mips)
+ return 0;
+
+ switch (code)
+ {
+ case BFD_RELOC_CTOR:
+ case BFD_RELOC_32:
+ return (&mips_howto_table_ext[MIPS_RELOC_32]);
+ case BFD_RELOC_MIPS_JMP:
+ return (&mips_howto_table_ext[MIPS_RELOC_JMP]);
+ case BFD_RELOC_16_PCREL_S2:
+ return (&mips_howto_table_ext[MIPS_RELOC_WDISP16]);
+ case BFD_RELOC_HI16:
+ return (&mips_howto_table_ext[MIPS_RELOC_HI16]);
+ case BFD_RELOC_HI16_S:
+ return (&mips_howto_table_ext[MIPS_RELOC_HI16_S]);
+ case BFD_RELOC_LO16:
+ return (&mips_howto_table_ext[MIPS_RELOC_LO16]);
+ default:
+ return 0;
+ }
+}
+
+/*
+ * This is just like the standard aoutx.h version but we need to do our
+ * own mapping of external reloc type values to howto entries.
+ */
+long
+MY(canonicalize_reloc)(abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *tblptr = section->relocation;
+ unsigned int count, c;
+ extern reloc_howto_type NAME(aout,ext_howto_table)[];
+
+ /* If we have already read in the relocation table, return the values. */
+ if (section->flags & SEC_CONSTRUCTOR) {
+ arelent_chain *chain = section->constructor_chain;
+
+ for (count = 0; count < section->reloc_count; count++) {
+ *relptr++ = &chain->relent;
+ chain = chain->next;
+ }
+ *relptr = 0;
+ return section->reloc_count;
+ }
+ if (tblptr && section->reloc_count) {
+ for (count = 0; count++ < section->reloc_count;)
+ *relptr++ = tblptr++;
+ *relptr = 0;
+ return section->reloc_count;
+ }
+
+ if (!NAME(aout,slurp_reloc_table)(abfd, section, symbols))
+ return -1;
+ tblptr = section->relocation;
+
+ /* fix up howto entries */
+ for (count = 0; count++ < section->reloc_count;)
+ {
+ c = tblptr->howto - NAME(aout,ext_howto_table);
+ tblptr->howto = &mips_howto_table_ext[c];
+
+ *relptr++ = tblptr++;
+ }
+ *relptr = 0;
+ return section->reloc_count;
+}
+
+static CONST struct aout_backend_data MY(backend_data) = {
+ 0, /* zmagic contiguous */
+ 1, /* text incl header */
+ 0, /* exec_hdr_flags */
+ TARGET_PAGE_SIZE, /* text vma */
+ MY_set_sizes,
+ 0, /* text size includes exec header */
+ 0, /* add_dynamic_symbols */
+ 0, /* add_one_symbol */
+ 0, /* link_dynamic_object */
+ 0, /* write_dynamic_symbol */
+ 0, /* check_dynamic_reloc */
+ 0 /* finish_dynamic_link */
+};
+
+const bfd_target aout_mips_little_vec =
+{
+ "a.out-mips-little", /* name */
+ bfd_target_aout_flavour,
+ BFD_ENDIAN_LITTLE, /* target byte order (little) */
+ BFD_ENDIAN_LITTLE, /* target headers byte order (little) */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ MY_symbol_leading_char,
+ ' ', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+ {_bfd_dummy_target, MY_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, MY_core_file_p},
+ {bfd_false, MY_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, MY_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ 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 (_bfd_nodynamic),
+
+ (PTR) MY_backend_data,
+};
+
+const bfd_target aout_mips_big_vec =
+{
+ "a.out-mips-big", /* name */
+ bfd_target_aout_flavour,
+ BFD_ENDIAN_BIG, /* target byte order (big) */
+ BFD_ENDIAN_BIG, /* target headers byte order (big) */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ MY_symbol_leading_char,
+ ' ', /* ar_pad_char */
+ 15, /* ar_max_namelen */
+ 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, MY_object_p, /* bfd_check_format */
+ bfd_generic_archive_p, MY_core_file_p},
+ {bfd_false, MY_mkobject, /* bfd_set_format */
+ _bfd_generic_mkarchive, bfd_false},
+ {bfd_false, MY_write_object_contents, /* bfd_write_contents */
+ _bfd_write_archive_contents, bfd_false},
+
+ 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 (_bfd_nodynamic),
+
+ (PTR) MY_backend_data,
+};
diff --git a/contrib/gdb/bfd/mpw-config.in b/contrib/gdb/bfd/mpw-config.in
new file mode 100644
index 0000000..9195d0e
--- /dev/null
+++ b/contrib/gdb/bfd/mpw-config.in
@@ -0,0 +1,73 @@
+# Configuration fragment for BFD.
+
+# This is almost always correct.
+
+Set selarchs "&bfd_{target_cpu}_arch"
+Set defvec ""
+Set selvecs ""
+
+If "{target_canonical}" =~ /m68k-apple-macos/
+ Set BFD_BACKENDS '"{o}"coff-m68k.c.o "{o}"cofflink.c.o'
+ Set defvec m68kcoff_vec
+ Set selvecs '&m68kcoff_vec'
+
+Else If "{target_canonical}" =~ /powerpc-apple-macos/
+ Set BFD_BACKENDS '"{o}"coff-pmac.c.o "{o}"xcofflink.c.o'
+ Set defvec pmac_xcoff_vec
+ Set selvecs '&pmac_xcoff_vec'
+ Set selarchs "&bfd_powerpc_arch"
+
+Else If "{target_canonical}" =~ /i386-unknown-go32/
+ Set BFD_BACKENDS '"{o}"coff-i386.c.o'
+ Set defvec i386coff_vec
+ Set selvecs '&i386coff_vec'
+
+Else If "{target_canonical}" =~ /mips-\Option-x-\Option-x/
+ Set BFD_BACKENDS '"{o}"coff-mips.c.o "{o}"ecoff.c.o "{o}"ecofflink.c.o'
+ Set defvec ecoff_big_vec
+ Set selvecs '&ecoff_big_vec,&ecoff_little_vec'
+
+Else If "{target_canonical}" =~ /sh-hitachi-hms/
+ Set BFD_BACKENDS '"{o}"coff-sh.c.o "{o}"cofflink.c.o'
+ Set defvec shcoff_vec
+ Set selvecs '&shcoff_vec,&shlcoff_vec'
+End If
+
+Set ta `echo {selarchs} | sed -e 's/&bfd_/{o}cpu-/g' -e 's/_arch/.c.o/g'`
+
+Set tdefaults "-d DEFAULT_VECTOR={defvec} -d SELECT_VECS={selvecs} -d SELECT_ARCHITECTURES={selarchs}"
+
+Echo '# From mpw-config.in' > "{o}"mk.tmp
+Echo 'WORDSIZE = 32' >> "{o}"mk.tmp
+Echo 'BFD_MACHINES = ' {ta} >> "{o}"mk.tmp
+Echo 'BFD_BACKENDS = ' {BFD_BACKENDS} >> "{o}"mk.tmp
+Echo 'TDEFAULTS = ' {tdefaults} >> "{o}"mk.tmp
+Echo 'HDEPFILES = ' >> "{o}"mk.tmp
+Echo 'TDEPFILES = ' >> "{o}"mk.tmp
+Echo '# End from mpw-config.in' >> "{o}"mk.tmp
+
+Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new
+Echo '#include "mpw.h"' >> "{o}"config.new
+
+MoveIfChange "{o}"config.new "{o}"config.h
+
+# We can only handle 32-bit targets right now.
+
+sed -e 's/@WORDSIZE@/32/' \Option-d
+ -e "s/@VERSION@/`Catenate {srcdir}VERSION`/" \Option-d
+ -e 's/@BFD_HOST_64BIT_LONG@/0/' \Option-d
+ "{srcdir}"bfd-in2.h >"{o}"bfd.h-new
+
+MoveIfChange "{o}"bfd.h-new "{o}"bfd.h
+
+# Pre-expand some macros in coffswap.h, so MPW C doesn't choke.
+
+sed -e 's/^ PUT_AOUTHDR_TSIZE (/ bfd_h_put_32 (/' \Option-d
+ -e 's/^ PUT_AOUTHDR_DSIZE (/ bfd_h_put_32 (/' \Option-d
+ -e 's/^ PUT_AOUTHDR_BSIZE (/ bfd_h_put_32 (/' \Option-d
+ -e 's/^ PUT_AOUTHDR_ENTRY (/ bfd_h_put_32 (/' \Option-d
+ -e 's/^ PUT_AOUTHDR_TEXT_START (/ bfd_h_put_32 (/' \Option-d
+ -e 's/^ PUT_AOUTHDR_DATA_START (/ bfd_h_put_32 (/' \Option-d
+ "{srcdir}"coffswap.h >"{o}"coffswap.h-new
+
+MoveIfChange "{o}"coffswap.h-new "{o}"coffswap.h
diff --git a/contrib/gdb/bfd/mpw-make.sed b/contrib/gdb/bfd/mpw-make.sed
new file mode 100644
index 0000000..a989ef0
--- /dev/null
+++ b/contrib/gdb/bfd/mpw-make.sed
@@ -0,0 +1,70 @@
+# Sed commands to finish translating the Unix BFD Makefile into MPW syntax.
+
+# Whack out unused host and target define bits.
+/HDEFINES/s/@HDEFINES@//
+/TDEFINES/s/@TDEFINES@//
+
+/INCDIR=/s/"{srcdir}":/"{topsrcdir}"/
+/^CSEARCH = .*$/s/$/ -i "{INCDIR}":mpw: -i ::extra-include:/
+
+/WORDSIZE/s/^WORDSIZE = /#WORDSIZE = /
+/BFD_MACHINES/s/^BFD_MACHINES = /#BFD_MACHINES = /
+/BFD_BACKENDS/s/^BFD_BACKENDS = /#BFD_BACKENDS = /
+/TDEFAULTS/s/^TDEFAULTS = /#TDEFAULTS = /
+
+# Remove extra, useless, "all".
+/^all \\Option-f _oldest/,/^$/d
+
+# Remove the Makefile rebuild rule.
+/^Makefile /,/--recheck/d
+
+# Don't do any recursive subdir stuff.
+/ subdir_do/s/{MAKE}/null-command/
+
+/BFD_H/s/^{BFD_H}/#{BFD_H}/
+
+# Point at include files that are always in the objdir.
+/bfd/s/"{s}"bfd\.h/"{o}"bfd.h/g
+/config/s/"{s}"config\.h/"{o}"config.h/g
+/elf32-target/s/"{s}"elf32-target\.h/"{o}"elf32-target.h/g
+/elf64-target/s/"{s}"elf64-target\.h/"{o}"elf64-target.h/g
+
+/"{s}"{INCDIR}/s/"{s}"{INCDIR}/"{INCDIR}"/g
+
+/dep/s/\.dep/__dep/g
+
+# Removing duplicates is cool but presently unnecessary,
+# so whack this out.
+/^ofiles \\Option-f/,/^$/d
+/ofiles/s/{OFILES} ofiles/{OFILES}/
+/echo ofiles = /d
+/cat ofiles/s/`cat ofiles`/{OFILES}/
+
+# No corefile support.
+/COREFILE/s/@COREFILE@//
+/COREFLAG/s/@COREFLAG@//
+
+# No PIC foolery in this environment.
+/@ALLLIBS@/s/@ALLLIBS@/{TARGETLIB}/
+/@PICLIST@/s/@PICLIST@//
+/@PICFLAG@/s/@PICFLAG@//
+/^{OFILES} \\Option-f stamp-picdir/,/^$/d
+
+# Remove the pic trickery from the default build rule.
+/^\.c\.o \\Option-f /,/End If/c\
+.c.o \\Option-f .c
+
+# MPW Make doesn't know about $<.
+/"{o}"targets.c.o \\Option-f "{s}"targets.c Makefile/,/^$/c\
+"{o}"targets.c.o \\Option-f "{s}"targets.c Makefile\
+ {CC} {ALL_CFLAGS} {TDEFAULTS} "{s}"targets.c -o "{o}"targets.c.o
+
+/"{o}"archures.c.o \\Option-f "{s}"archures.c Makefile/,/^$/c\
+"{o}"archures.c.o \\Option-f "{s}"archures.c Makefile\
+ {CC} {ALL_CFLAGS} {TDEFAULTS} "{s}"archures.c -o "{o}"archures.c.o
+
+# Remove the .h rebuilding rules, we don't currently have a doc subdir,
+# or a way to build the prototype-hacking tool that's in it.
+/^"{srcdir}"bfd-in2.h \\Option-f /,/^$/d
+/^"{srcdir}"libbfd.h \\Option-f /,/^$/d
+/^"{srcdir}"libcoff.h \\Option-f /,/^$/d
diff --git a/contrib/gdb/bfd/netbsd-core.c b/contrib/gdb/bfd/netbsd-core.c
new file mode 100644
index 0000000..4e82867
--- /dev/null
+++ b/contrib/gdb/bfd/netbsd-core.c
@@ -0,0 +1,310 @@
+/* BFD back end for NetBSD style core files
+ Copyright 1988, 1989, 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
+ Written by Paul Kranenburg, EUR
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/core.h>
+#include <errno.h>
+
+/*
+ * FIXME: On NetBSD/sparc CORE_FPU_OFFSET should be (sizeof(struct trapframe))
+ */
+
+struct netbsd_core_struct {
+ struct core core;
+} *rawptr;
+
+/* forward declarations */
+
+static const bfd_target * netbsd_core_core_file_p PARAMS ((bfd *abfd));
+static char * netbsd_core_core_file_failing_command PARAMS ((bfd *abfd));
+static int netbsd_core_core_file_failing_signal PARAMS ((bfd *abfd));
+static boolean netbsd_core_core_file_matches_executable_p
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+/* Handle NetBSD-style core dump file. */
+
+/* ARGSUSED */
+static const bfd_target *
+netbsd_core_core_file_p (abfd)
+ bfd *abfd;
+
+{
+ int i, val, offset;
+ asection *asect, *asect2;
+ struct core core;
+ struct coreseg coreseg;
+
+ val = bfd_read ((void *)&core, 1, sizeof core, abfd);
+ if (val != sizeof core) {
+ /* Too small to be a core file */
+ bfd_set_error(bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (CORE_GETMAGIC(core) != COREMAGIC) {
+ bfd_set_error(bfd_error_wrong_format);
+ return 0;
+ }
+
+ rawptr = (struct netbsd_core_struct *)
+ bfd_zalloc (abfd, sizeof (struct netbsd_core_struct));
+ if (rawptr == NULL) {
+ bfd_set_error(bfd_error_no_memory);
+ return 0;
+ }
+
+ rawptr->core = core;
+ abfd->tdata.netbsd_core_data = rawptr;
+
+ offset = core.c_hdrsize;
+ for (i = 0; i < core.c_nseg; i++) {
+
+ if (bfd_seek (abfd, offset, SEEK_SET) != 0)
+ goto punt;
+
+ val = bfd_read ((void *)&coreseg, 1, sizeof coreseg, abfd);
+ if (val != sizeof coreseg) {
+ bfd_set_error(bfd_error_file_truncated);
+ goto punt;
+ }
+ if (CORE_GETMAGIC(coreseg) != CORESEGMAGIC) {
+ bfd_set_error(bfd_error_wrong_format);
+ goto punt;
+ }
+
+ offset += core.c_seghdrsize;
+
+ asect = (asection *) bfd_zalloc (abfd, sizeof(asection));
+ if (asect == NULL) {
+ bfd_set_error(bfd_error_no_memory);
+ }
+
+ asect->_raw_size = coreseg.c_size;
+ asect->vma = coreseg.c_addr;
+ asect->filepos = offset;
+ asect->alignment_power = 2;
+ asect->next = abfd->sections;
+ abfd->sections = asect;
+ abfd->section_count++;
+ offset += coreseg.c_size;
+
+ switch (CORE_GETFLAG(coreseg)) {
+ case CORE_CPU:
+ asect->name = ".reg";
+ asect->flags = SEC_ALLOC + SEC_HAS_CONTENTS;
+#ifdef CORE_FPU_OFFSET
+ /* Hackish... */
+ asect->_raw_size = CORE_FPU_OFFSET;
+ asect2 = (asection *)bfd_zalloc (abfd,
+ sizeof (asection));
+ if (asect2 == NULL) {
+ bfd_set_error(bfd_error_no_memory);
+ goto punt;
+ }
+ asect2->_raw_size = coreseg.c_size - CORE_FPU_OFFSET;
+ asect2->vma = 0;
+ asect2->filepos = asect->filepos + CORE_FPU_OFFSET;
+ asect2->alignment_power = 2;
+ asect2->next = abfd->sections;
+ asect2->name = ".reg2";
+ asect2->flags = SEC_ALLOC + SEC_HAS_CONTENTS;
+ abfd->sections = asect2;
+ abfd->section_count++;
+#endif
+
+ break;
+ case CORE_DATA:
+ asect->name = ".data";
+ asect->flags = SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS;
+ break;
+ case CORE_STACK:
+ asect->name = ".stack";
+ asect->flags = SEC_ALLOC+SEC_LOAD+SEC_HAS_CONTENTS;
+ break;
+ }
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+ return abfd->xvec;
+
+punt: {
+ asection *anext;
+ for (asect = abfd->sections; asect; asect = anext) {
+ anext = asect->next;
+ free((void *)asect);
+ }
+ }
+ free ((void *)rawptr);
+ abfd->tdata.netbsd_core_data = NULL;
+ abfd->sections = NULL;
+ abfd->section_count = 0;
+ return 0;
+}
+
+static char*
+netbsd_core_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ /*return core_command (abfd);*/
+ return abfd->tdata.netbsd_core_data->core.c_name;
+}
+
+/* ARGSUSED */
+static int
+netbsd_core_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ /*return core_signal (abfd);*/
+ return abfd->tdata.netbsd_core_data->core.c_signo;
+}
+
+/* ARGSUSED */
+static boolean
+netbsd_core_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this point */
+}
+
+/* No archive file support via this BFD */
+#define netbsd_openr_next_archived_file bfd_generic_openr_next_archived_file
+#define netbsd_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define netbsd_slurp_armap bfd_false
+#define netbsd_slurp_extended_name_table bfd_true
+#define netbsd_write_armap (boolean (*) PARAMS \
+ ((bfd *arch, unsigned int elength, struct orl *map, \
+ unsigned int orl_count, int stridx))) bfd_false
+#define netbsd_truncate_arname bfd_dont_truncate_arname
+#define aout_32_openr_next_archived_file bfd_generic_openr_next_archived_file
+
+#define netbsd_close_and_cleanup bfd_generic_close_and_cleanup
+#define netbsd_set_section_contents (boolean (*) PARAMS \
+ ((bfd *abfd, asection *section, PTR data, file_ptr offset, \
+ bfd_size_type count))) bfd_false
+#define netbsd_get_section_contents bfd_generic_get_section_contents
+#define netbsd_new_section_hook (boolean (*) PARAMS \
+ ((bfd *, sec_ptr))) bfd_true
+#define netbsd_get_symtab_upper_bound bfd_0u
+#define netbsd_get_symtab (unsigned int (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry **))) bfd_0u
+#define netbsd_get_reloc_upper_bound (unsigned int (*) PARAMS \
+ ((bfd *, sec_ptr))) bfd_0u
+#define netbsd_canonicalize_reloc (unsigned int (*) PARAMS \
+ ((bfd *, sec_ptr, arelent **, struct symbol_cache_entry**))) bfd_0u
+#define netbsd_make_empty_symbol (struct symbol_cache_entry * \
+ (*) PARAMS ((bfd *))) bfd_false
+#define netbsd_print_symbol (void (*) PARAMS \
+ ((bfd *, PTR, struct symbol_cache_entry *, \
+ bfd_print_symbol_type))) bfd_false
+#define netbsd_get_symbol_info (void (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry *, \
+ symbol_info *))) bfd_false
+#define netbsd_get_lineno (alent * (*) PARAMS \
+ ((bfd *, struct symbol_cache_entry *))) bfd_nullvoidptr
+#define netbsd_set_arch_mach (boolean (*) PARAMS \
+ ((bfd *, enum bfd_architecture, unsigned long))) bfd_false
+#define netbsd_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 netbsd_sizeof_headers (int (*) PARAMS \
+ ((bfd *, boolean))) bfd_0
+
+#define netbsd_bfd_debug_info_start bfd_void
+#define netbsd_bfd_debug_info_end bfd_void
+#define netbsd_bfd_debug_info_accumulate (void (*) PARAMS \
+ ((bfd *, struct sec *))) bfd_void
+#define netbsd_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
+#define netbsd_bfd_relax_section bfd_generic_relax_section
+#define netbsd_bfd_seclet_link \
+ ((boolean (*) PARAMS ((bfd *, PTR, boolean))) bfd_false)
+#define netbsd_bfd_reloc_type_lookup \
+ ((CONST struct reloc_howto_struct *(*) PARAMS ((bfd *, bfd_reloc_code_real_type))) bfd_nullvoidptr)
+#define netbsd_bfd_make_debug_symbol \
+ ((asymbol *(*) PARAMS ((bfd *, void *, unsigned long))) bfd_nullvoidptr)
+
+/* If somebody calls any byte-swapping routines, shoot them. */
+static void
+swap_abort()
+{
+ abort(); /* This way doesn't require any declaration for ANSI to fuck up */
+}
+#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 (( const bfd_byte *))) swap_abort )
+
+const bfd_target netbsd_core_vec =
+ {
+ "netbsd-core",
+ bfd_target_unknown_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_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* symbol prefix */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 3, /* minimum alignment power */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ netbsd_core_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (netbsd_core),
+ 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/contrib/gdb/bfd/netbsd.h b/contrib/gdb/bfd/netbsd.h
new file mode 100644
index 0000000..dd73d37
--- /dev/null
+++ b/contrib/gdb/bfd/netbsd.h
@@ -0,0 +1,108 @@
+/* BFD back-end definitions used by all NetBSD targets.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+/* NetBSD fits its header into the start of its text segment */
+#define N_HEADER_IN_TEXT(x) 1
+#define TEXT_START_ADDR TARGET_PAGE_SIZE
+
+#define N_MACHTYPE(exec) \
+ ((enum machine_type)(((exec).a_info >> 16) & 0x03ff))
+#define N_FLAGS(exec) \
+ (((exec).a_info >> 26) & 0x3f)
+
+#define N_SET_INFO(exec, magic, type, flags) \
+ ((exec).a_info = ((magic) & 0xffff) \
+ | (((int)(type) & 0x3ff) << 16) \
+ | (((flags) & 0x3f) << 24))
+#define N_SET_MACHTYPE(exec, machtype) \
+ ((exec).a_info = \
+ ((exec).a_info & 0xfb00ffff) | ((((int)(machtype))&0x3ff) << 16))
+#define N_SET_FLAGS(exec, flags) \
+ ((exec).a_info = \
+ ((exec).a_info & 0x03ffffff) | ((flags & 0x03f) << 26))
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h"
+
+/* On NetBSD, the magic number is always in ntohl's "network" (big-endian)
+ format. */
+#define SWAP_MAGIC(ext) bfd_getb32 (ext)
+
+
+#define MY_write_object_contents MY(write_object_contents)
+static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
+#define MY_text_includes_header 1
+
+#include "aout-target.h"
+
+/* Write an object file.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+static boolean
+MY(write_object_contents) (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+#if CHOOSE_RELOC_SIZE
+ CHOOSE_RELOC_SIZE(abfd);
+#else
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+#endif
+
+ /* Magic number, maestro, please! */
+ switch (bfd_get_arch(abfd)) {
+ case bfd_arch_m68k:
+ if (strcmp (abfd->xvec->name, "a.out-m68k4k-netbsd") == 0)
+ N_SET_MACHTYPE(*execp, M_68K4K_NETBSD);
+ else
+ N_SET_MACHTYPE(*execp, M_68K_NETBSD);
+ break;
+ case bfd_arch_sparc:
+ N_SET_MACHTYPE(*execp, M_SPARC_NETBSD);
+ break;
+ case bfd_arch_i386:
+ N_SET_MACHTYPE(*execp, M_386_NETBSD);
+ break;
+ case bfd_arch_ns32k:
+ N_SET_MACHTYPE(*execp, M_532_NETBSD);
+ break;
+ default:
+ N_SET_MACHTYPE(*execp, M_UNKNOWN);
+ break;
+ }
+
+ /* The NetBSD magic number is always big-endian */
+#ifndef TARGET_IS_BIG_ENDIAN_P
+ /* XXX aren't there any macro to change byteorder of a word independent of
+ the host's or target's endianesses? */
+ execp->a_info
+ = (execp->a_info & 0xff) << 24 | (execp->a_info & 0xff00) << 8
+ | (execp->a_info & 0xff0000) >> 8 | (execp->a_info & 0xff000000) >> 24;
+#endif
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/newsos3.c b/contrib/gdb/bfd/newsos3.c
new file mode 100644
index 0000000..7ec7a75
--- /dev/null
+++ b/contrib/gdb/bfd/newsos3.c
@@ -0,0 +1,40 @@
+/* BFD back-end for NewsOS3 (Sony, 68k) binaries.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define TEXT_START_ADDR 0
+#define BYTES_IN_WORD 4
+#define MY(OP) CAT(newsos3_,OP)
+#define TARGETNAME "a.out-newsos3"
+#define ENTRY_CAN_BE_ZERO
+#define N_SHARED_LIB(x) 0 /* Avoids warning when compiled with -Wall. */
+#define DEFAULT_ARCH bfd_arch_m68k
+#define TARGET_IS_BIG_ENDIAN_P
+#define N_HEADER_IN_TEXT(x) 0
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/nlm-target.h b/contrib/gdb/bfd/nlm-target.h
new file mode 100644
index 0000000..cdd3fa8
--- /dev/null
+++ b/contrib/gdb/bfd/nlm-target.h
@@ -0,0 +1,228 @@
+/* Target definitions for 32/64-bit NLM (NetWare Loadable Module)
+ Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define nlm_core_file_p _bfd_dummy_target
+
+#define nlm_get_symtab_upper_bound nlmNAME(get_symtab_upper_bound)
+#define nlm_get_symtab nlmNAME(get_symtab)
+#define nlm_make_empty_symbol nlmNAME(make_empty_symbol)
+#define nlm_print_symbol nlmNAME(print_symbol)
+#define nlm_get_symbol_info nlmNAME(get_symbol_info)
+#define nlm_bfd_is_local_label bfd_generic_is_local_label
+#define nlm_get_lineno _bfd_nosymbols_get_lineno
+#define nlm_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define nlm_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define nlm_read_minisymbols _bfd_generic_read_minisymbols
+#define nlm_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define nlm_get_reloc_upper_bound nlmNAME(get_reloc_upper_bound)
+#define nlm_canonicalize_reloc nlmNAME(canonicalize_reloc)
+#define nlm_bfd_reloc_type_lookup bfd_default_reloc_type_lookup
+
+#define nlm_set_section_contents nlmNAME(set_section_contents)
+
+#define nlm_sizeof_headers _bfd_nolink_sizeof_headers
+#define nlm_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define nlm_bfd_relax_section bfd_generic_relax_section
+#define nlm_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define nlm_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define nlm_bfd_final_link _bfd_generic_final_link
+#define nlm_bfd_link_split_section _bfd_generic_link_split_section
+
+/* 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. Every BFD points to a target structure
+ with its "xvec" member.
+
+ There are two such structures here: one for big-endian machines and
+ one for little-endian machines. */
+
+
+#ifdef TARGET_BIG_SYM
+const bfd_target TARGET_BIG_SYM =
+{
+ /* name: identify kind of target */
+ TARGET_BIG_NAME,
+
+ /* flavour: general indication about file */
+ bfd_target_nlm_flavour,
+
+ /* byteorder: data is big endian */
+ BFD_ENDIAN_BIG,
+
+ /* header_byteorder: header is also big endian */
+ BFD_ENDIAN_BIG,
+
+ /* object_flags: mask of all file flags */
+ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
+ | WP_TEXT),
+
+ /* section_flags: mask of all section flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY |
+ SEC_CODE | SEC_DATA),
+
+ /* leading_symbol_char: is the first char of a user symbol
+ predictable, and if so what is it */
+ 0,
+
+ /* ar_pad_char: pad character for filenames within an archive header
+ FIXME: this really has nothing to do with NLM, this is a characteristic
+ of the archiver and/or os and should be independently tunable */
+ '/',
+
+ /* ar_max_namelen: maximum number of characters in an archive header
+ FIXME: this really has nothing to do with NLM, this is a characteristic
+ of the archiver and should be independently tunable. This value is
+ a WAG (wild a** guess) */
+ 15,
+
+ /* Routines to byte-swap various sized integers from the data sections */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+
+ /* Routines to byte-swap various sized integers from the file headers */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16,
+
+ /* bfd_check_format: check the format of a file being read */
+ { _bfd_dummy_target, /* unknown format */
+ nlmNAME(object_p), /* assembler/linker output (object file) */
+ bfd_generic_archive_p, /* an archive */
+ nlm_core_file_p /* a core file */
+ },
+
+ /* bfd_set_format: set the format of a file being written */
+ { bfd_false,
+ nlm_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+
+ /* bfd_write_contents: write cached information into a file being written */
+ { bfd_false,
+ nlmNAME(write_object_contents),
+ _bfd_write_archive_contents,
+ bfd_false
+ },
+
+ /* Initialize a jump table with the standard macro. All names start with
+ "nlm" */
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (nlm),
+ BFD_JUMP_TABLE_RELOCS (nlm),
+ BFD_JUMP_TABLE_WRITE (nlm),
+ BFD_JUMP_TABLE_LINK (nlm),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ /* backend_data: */
+ (PTR) TARGET_BACKEND_DATA
+};
+#endif
+
+#ifdef TARGET_LITTLE_SYM
+const bfd_target TARGET_LITTLE_SYM =
+{
+ /* name: identify kind of target */
+ TARGET_LITTLE_NAME,
+
+ /* flavour: general indication about file */
+ bfd_target_nlm_flavour,
+
+ /* byteorder: data is little endian */
+ BFD_ENDIAN_LITTLE,
+
+ /* header_byteorder: header is also little endian */
+ BFD_ENDIAN_LITTLE,
+
+ /* object_flags: mask of all file flags */
+ (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
+ | WP_TEXT),
+
+ /* section_flags: mask of all section flags */
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY |
+ SEC_DATA),
+
+ /* leading_symbol_char: is the first char of a user symbol
+ predictable, and if so what is it */
+ 0,
+
+ /* ar_pad_char: pad character for filenames within an archive header
+ FIXME: this really has nothing to do with NLM, this is a characteristic
+ of the archiver and/or os and should be independently tunable */
+ '/',
+
+ /* ar_max_namelen: maximum number of characters in an archive header
+ FIXME: this really has nothing to do with NLM, this is a characteristic
+ of the archiver and should be independently tunable. This value is
+ a WAG (wild a** guess) */
+ 15,
+
+ /* Routines to byte-swap various sized integers from the data sections */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16,
+
+ /* Routines to byte-swap various sized integers from the file headers */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16,
+
+ /* bfd_check_format: check the format of a file being read */
+ { _bfd_dummy_target, /* unknown format */
+ nlmNAME(object_p), /* assembler/linker output (object file) */
+ bfd_generic_archive_p, /* an archive */
+ nlm_core_file_p /* a core file */
+ },
+
+ /* bfd_set_format: set the format of a file being written */
+ { bfd_false,
+ nlm_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+
+ /* bfd_write_contents: write cached information into a file being written */
+ { bfd_false,
+ nlmNAME(write_object_contents),
+ _bfd_write_archive_contents,
+ bfd_false
+ },
+
+ /* Initialize a jump table with the standard macro. All names start with
+ "nlm" */
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (nlm),
+ BFD_JUMP_TABLE_RELOCS (nlm),
+ BFD_JUMP_TABLE_WRITE (nlm),
+ BFD_JUMP_TABLE_LINK (nlm),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ /* backend_data: */
+ (PTR) TARGET_BACKEND_DATA
+};
+#endif
diff --git a/contrib/gdb/bfd/nlm.c b/contrib/gdb/bfd/nlm.c
new file mode 100644
index 0000000..89c6baa
--- /dev/null
+++ b/contrib/gdb/bfd/nlm.c
@@ -0,0 +1,55 @@
+/* NLM (NetWare Loadable Module) executable support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libnlm.h"
+
+/* Make an NLM object. We just need to allocate the backend
+ information. */
+
+boolean
+nlm_mkobject (abfd)
+ bfd * abfd;
+{
+ nlm_tdata (abfd) =
+ (struct nlm_obj_tdata *) bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata));
+ if (nlm_tdata (abfd) == NULL)
+ return (false);
+
+ if (nlm_architecture (abfd) != bfd_arch_unknown)
+ bfd_default_set_arch_mach (abfd, nlm_architecture (abfd),
+ nlm_machine (abfd));
+
+ /* since everything is done at close time, do we need any initialization? */
+ return (true);
+}
+
+/* Set the architecture and machine for an NLM object. */
+
+boolean
+nlm_set_arch_mach (abfd, arch, machine)
+ bfd * abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ bfd_default_set_arch_mach (abfd, arch, machine);
+ return arch == nlm_architecture (abfd);
+}
diff --git a/contrib/gdb/bfd/nlm32-alpha.c b/contrib/gdb/bfd/nlm32-alpha.c
new file mode 100644
index 0000000..24c8e51
--- /dev/null
+++ b/contrib/gdb/bfd/nlm32-alpha.c
@@ -0,0 +1,892 @@
+/* Support for 32-bit Alpha NLM (NetWare Loadable Module)
+ Copyright (C) 1993 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file describes the 32 bit Alpha NLM format. You might think
+ that an Alpha chip would use a 64 bit format, but, for some reason,
+ it doesn't. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#define ARCH_SIZE 32
+
+#include "nlm/alpha-ext.h"
+#define Nlm_External_Fixed_Header Nlm32_alpha_External_Fixed_Header
+
+#include "libnlm.h"
+
+static boolean nlm_alpha_backend_object_p
+ PARAMS ((bfd *));
+static boolean nlm_alpha_write_prefix
+ PARAMS ((bfd *));
+static boolean nlm_alpha_read_reloc
+ PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
+static boolean nlm_alpha_mangle_relocs
+ PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
+static boolean nlm_alpha_read_import
+ PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static boolean nlm_alpha_write_import
+ PARAMS ((bfd *, asection *, arelent *));
+static boolean nlm_alpha_set_public_section
+ PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static bfd_vma nlm_alpha_get_public_offset
+ PARAMS ((bfd *, asymbol *));
+static boolean nlm_alpha_write_external
+ PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
+
+/* Alpha NLM's have a prefix header before the standard NLM. This
+ function reads it in, verifies the version, and seeks the bfd to
+ the location before the regular NLM header. */
+
+static boolean
+nlm_alpha_backend_object_p (abfd)
+ bfd *abfd;
+{
+ struct nlm32_alpha_external_prefix_header s;
+ bfd_size_type size;
+
+ if (bfd_read ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
+ return false;
+
+ if (bfd_h_get_32 (abfd, s.magic) != NLM32_ALPHA_MAGIC)
+ return false;
+
+ /* FIXME: Should we check the format number? */
+
+ /* Skip to the end of the header. */
+ size = bfd_h_get_32 (abfd, s.size);
+ if (bfd_seek (abfd, size, SEEK_SET) != 0)
+ return false;
+
+ return true;
+}
+
+/* Write out the prefix. */
+
+static boolean
+nlm_alpha_write_prefix (abfd)
+ bfd *abfd;
+{
+ struct nlm32_alpha_external_prefix_header s;
+
+ memset (&s, 0, sizeof s);
+ bfd_h_put_32 (abfd, (bfd_vma) NLM32_ALPHA_MAGIC, s.magic);
+ bfd_h_put_32 (abfd, (bfd_vma) 2, s.format);
+ bfd_h_put_32 (abfd, (bfd_vma) sizeof s, s.size);
+ if (bfd_write ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
+ return false;
+ return true;
+}
+
+/* How to process the various reloc types. */
+
+static reloc_howto_type nlm32_alpha_howto_table[] =
+{
+ /* Reloc type 0 is ignored by itself. However, it appears after a
+ GPDISP reloc to identify the location where the low order 16 bits
+ of the gp register are loaded. */
+ HOWTO (ALPHA_R_IGNORE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "IGNORE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 32 bit reference to a symbol. */
+ HOWTO (ALPHA_R_REFLONG, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "REFLONG", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 64 bit reference to a symbol. */
+ HOWTO (ALPHA_R_REFQUAD, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "REFQUAD", /* name */
+ true, /* partial_inplace */
+ 0xffffffffffffffff, /* src_mask */
+ 0xffffffffffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 32 bit GP relative offset. This is just like REFLONG except
+ that when the value is used the value of the gp register will be
+ added in. */
+ HOWTO (ALPHA_R_GPREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "GPREL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Used for an instruction that refers to memory off the GP
+ register. The offset is 16 bits of the 32 bit instruction. This
+ reloc always seems to be against the .lita section. */
+ HOWTO (ALPHA_R_LITERAL, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "LITERAL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* This reloc only appears immediately following a LITERAL reloc.
+ It identifies a use of the literal. It seems that the linker can
+ use this to eliminate a portion of the .lita section. The symbol
+ index is special: 1 means the literal address is in the base
+ register of a memory format instruction; 2 means the literal
+ address is in the byte offset register of a byte-manipulation
+ instruction; 3 means the literal address is in the target
+ register of a jsr instruction. This does not actually do any
+ relocation. */
+ HOWTO (ALPHA_R_LITUSE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "LITUSE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Load the gp register. This is always used for a ldah instruction
+ which loads the upper 16 bits of the gp register. The next reloc
+ will be an IGNORE reloc which identifies the location of the lda
+ instruction which loads the lower 16 bits. The symbol index of
+ the GPDISP instruction appears to actually be the number of bytes
+ between the ldah and lda instructions. This gives two different
+ ways to determine where the lda instruction is; I don't know why
+ both are used. The value to use for the relocation is the
+ difference between the GP value and the current location; the
+ load will always be done against a register holding the current
+ address. */
+ HOWTO (ALPHA_R_GPDISP, /* type */
+ 16, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "GPDISP", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ true), /* pcrel_offset */
+
+ /* A 21 bit branch. The native assembler generates these for
+ branches within the text segment, and also fills in the PC
+ relative offset in the instruction. It seems to me that this
+ reloc, unlike the others, is not partial_inplace. */
+ HOWTO (ALPHA_R_BRADDR, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "BRADDR", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0x1fffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A hint for a jump to a register. */
+ HOWTO (ALPHA_R_HINT, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 14, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "HINT", /* name */
+ true, /* partial_inplace */
+ 0x3fff, /* src_mask */
+ 0x3fff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SREL16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SREL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* A 64 bit PC relative offset. */
+ HOWTO (ALPHA_R_SREL64, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "SREL64", /* name */
+ true, /* partial_inplace */
+ 0xffffffffffffffff, /* src_mask */
+ 0xffffffffffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Push a value on the reloc evaluation stack. */
+ HOWTO (ALPHA_R_OP_PUSH, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_PUSH", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Store the value from the stack at the given address. Store it in
+ a bitfield of size r_size starting at bit position r_offset. */
+ HOWTO (ALPHA_R_OP_STORE, /* type */
+ 0, /* rightshift */
+ 4, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_STORE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0xffffffffffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Subtract the reloc address from the value on the top of the
+ relocation stack. */
+ HOWTO (ALPHA_R_OP_PSUB, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_PSUB", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Shift the value on the top of the relocation stack right by the
+ given value. */
+ HOWTO (ALPHA_R_OP_PRSHIFT, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "OP_PRSHIFT", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Adjust the GP value for a new range in the object file. */
+ HOWTO (ALPHA_R_GPVALUE, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "GPVALUE", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+static reloc_howto_type nlm32_alpha_nw_howto =
+ HOWTO (ALPHA_R_NW_RELOC, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ 0, /* special_function */
+ "NW_RELOC", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* Read an Alpha NLM reloc. This routine keeps some static data which
+ it uses when handling local relocs. This only works correctly
+ because all the local relocs are read at once. */
+
+static boolean
+nlm_alpha_read_reloc (abfd, sym, secp, rel)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+ asection **secp;
+ arelent *rel;
+{
+ static bfd_vma gp_value;
+ static bfd_vma lita_address;
+ struct nlm32_alpha_external_reloc ext;
+ bfd_vma r_vaddr;
+ long r_symndx;
+ int r_type, r_extern, r_offset, r_size;
+ asection *code_sec, *data_sec;
+
+ /* Read the reloc from the file. */
+ if (bfd_read (&ext, sizeof ext, 1, abfd) != sizeof ext)
+ return false;
+
+ /* Swap in the reloc information. */
+ r_vaddr = bfd_h_get_64 (abfd, (bfd_byte *) ext.r_vaddr);
+ r_symndx = bfd_h_get_32 (abfd, (bfd_byte *) ext.r_symndx);
+
+ BFD_ASSERT (bfd_little_endian (abfd));
+
+ r_type = ((ext.r_bits[0] & RELOC_BITS0_TYPE_LITTLE)
+ >> RELOC_BITS0_TYPE_SH_LITTLE);
+ r_extern = (ext.r_bits[1] & RELOC_BITS1_EXTERN_LITTLE) != 0;
+ r_offset = ((ext.r_bits[1] & RELOC_BITS1_OFFSET_LITTLE)
+ >> RELOC_BITS1_OFFSET_SH_LITTLE);
+ /* Ignore the reserved bits. */
+ r_size = ((ext.r_bits[3] & RELOC_BITS3_SIZE_LITTLE)
+ >> RELOC_BITS3_SIZE_SH_LITTLE);
+
+ /* Fill in the BFD arelent structure. */
+ code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ if (r_extern)
+ {
+ /* External relocations are only used for imports. */
+ BFD_ASSERT (sym != NULL);
+ /* We don't need to set sym_ptr_ptr for this case. It is set in
+ nlm_canonicalize_reloc. */
+ rel->sym_ptr_ptr = NULL;
+ rel->addend = 0;
+ }
+ else
+ {
+ /* Internal relocations are only used for local relocation
+ fixups. If they are not NW_RELOC or GPDISP or IGNORE, they
+ must be against .text or .data. */
+ BFD_ASSERT (r_type == ALPHA_R_NW_RELOC || sym == NULL);
+ if (r_type == ALPHA_R_NW_RELOC
+ || r_type == ALPHA_R_GPDISP
+ || r_type == ALPHA_R_IGNORE)
+ {
+ rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ rel->addend = 0;
+ }
+ else if (r_symndx == ALPHA_RELOC_SECTION_TEXT)
+ {
+ rel->sym_ptr_ptr = code_sec->symbol_ptr_ptr;
+ BFD_ASSERT (bfd_get_section_vma (abfd, code_sec) == 0);
+ rel->addend = 0;
+ }
+ else if (r_symndx == ALPHA_RELOC_SECTION_DATA)
+ {
+ rel->sym_ptr_ptr = data_sec->symbol_ptr_ptr;
+ rel->addend = - bfd_get_section_vma (abfd, data_sec);
+ }
+ else
+ {
+ BFD_ASSERT (0);
+ rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ rel->addend = 0;
+ }
+ }
+
+ /* We use the address to determine whether the reloc is in the .text
+ or .data section. R_NW_RELOC relocs don't really have a section,
+ so we put them in .text. */
+ if (r_type == ALPHA_R_NW_RELOC
+ || r_vaddr < bfd_section_size (abfd, code_sec))
+ {
+ *secp = code_sec;
+ rel->address = r_vaddr;
+ }
+ else
+ {
+ *secp = data_sec;
+ rel->address = r_vaddr - bfd_section_size (abfd, code_sec);
+ }
+
+ /* We must adjust the addend based on the type. */
+ BFD_ASSERT ((r_type >= 0 && r_type <= ALPHA_R_GPVALUE)
+ || r_type == ALPHA_R_NW_RELOC);
+
+ switch (r_type)
+ {
+ case ALPHA_R_BRADDR:
+ case ALPHA_R_SREL16:
+ case ALPHA_R_SREL32:
+ case ALPHA_R_SREL64:
+ /* The PC relative relocs do not seem to use the section VMA as
+ a negative addend. */
+ rel->addend = 0;
+ break;
+
+ case ALPHA_R_GPREL32:
+ /* Copy the gp value for this object file into the addend, to
+ ensure that we are not confused by the linker. */
+ if (! r_extern)
+ rel->addend += gp_value;
+ break;
+
+ case ALPHA_R_LITERAL:
+ BFD_ASSERT (! r_extern);
+ rel->addend += lita_address;
+ break;
+
+ case ALPHA_R_LITUSE:
+ case ALPHA_R_GPDISP:
+ /* The LITUSE and GPDISP relocs do not use a symbol, or an
+ addend, but they do use a special code. Put this code in the
+ addend field. */
+ rel->addend = r_symndx;
+ rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ break;
+
+ case ALPHA_R_OP_STORE:
+ /* The STORE reloc needs the size and offset fields. We store
+ them in the addend. */
+ BFD_ASSERT (r_offset < 256 && r_size < 256);
+ rel->addend = (r_offset << 8) + r_size;
+ break;
+
+ case ALPHA_R_OP_PUSH:
+ case ALPHA_R_OP_PSUB:
+ case ALPHA_R_OP_PRSHIFT:
+ /* The PUSH, PSUB and PRSHIFT relocs do not actually use an
+ address. I believe that the address supplied is really an
+ addend. */
+ rel->addend = r_vaddr;
+ break;
+
+ case ALPHA_R_GPVALUE:
+ /* Record the new gp value. */
+ gp_value += r_symndx;
+ rel->addend = gp_value;
+ break;
+
+ case ALPHA_R_IGNORE:
+ /* If the type is ALPHA_R_IGNORE, make sure this is a reference
+ to the absolute section so that the reloc is ignored. For
+ some reason the address of this reloc type is not adjusted by
+ the section vma. We record the gp value for this object file
+ here, for convenience when doing the GPDISP relocation. */
+ rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ rel->address = r_vaddr;
+ rel->addend = gp_value;
+ break;
+
+ case ALPHA_R_NW_RELOC:
+ /* If this is SETGP, we set the addend to 0. Otherwise we set
+ the addend to the size of the .lita section (this is
+ r_symndx) plus 1. We have already set the address of the
+ reloc to r_vaddr. */
+ if (r_size == ALPHA_R_NW_RELOC_SETGP)
+ {
+ gp_value = r_vaddr;
+ rel->addend = 0;
+ }
+ else if (r_size == ALPHA_R_NW_RELOC_LITA)
+ {
+ lita_address = r_vaddr;
+ rel->addend = r_symndx + 1;
+ }
+ else
+ BFD_ASSERT (0);
+ rel->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ break;
+
+ default:
+ break;
+ }
+
+ if (r_type == ALPHA_R_NW_RELOC)
+ rel->howto = &nlm32_alpha_nw_howto;
+ else
+ rel->howto = &nlm32_alpha_howto_table[r_type];
+
+ return true;
+}
+
+/* Mangle Alpha NLM relocs for output. */
+
+static boolean
+nlm_alpha_mangle_relocs (abfd, sec, data, offset, count)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+ bfd_vma offset;
+ bfd_size_type count;
+{
+ return true;
+}
+
+/* Read an ALPHA NLM import record */
+
+static boolean
+nlm_alpha_read_import (abfd, sym)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+{
+ struct nlm_relent *nlm_relocs; /* relocation records for symbol */
+ bfd_size_type rcount; /* number of relocs */
+ bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
+ unsigned char symlength; /* length of symbol name */
+ char *name;
+
+ if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
+ != sizeof (symlength))
+ return false;
+ sym -> symbol.the_bfd = abfd;
+ name = bfd_alloc (abfd, symlength + 1);
+ if (name == NULL)
+ return false;
+ if (bfd_read (name, symlength, 1, abfd) != symlength)
+ return false;
+ name[symlength] = '\0';
+ sym -> symbol.name = name;
+ sym -> symbol.flags = 0;
+ sym -> symbol.value = 0;
+ sym -> symbol.section = bfd_und_section_ptr;
+ if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return false;
+ rcount = bfd_h_get_32 (abfd, temp);
+ nlm_relocs = ((struct nlm_relent *)
+ bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
+ if (!nlm_relocs)
+ return false;
+ sym -> relocs = nlm_relocs;
+ sym -> rcnt = 0;
+ while (sym -> rcnt < rcount)
+ {
+ asection *section;
+
+ if (nlm_alpha_read_reloc (abfd, sym, &section,
+ &nlm_relocs -> reloc)
+ == false)
+ return false;
+ nlm_relocs -> section = section;
+ nlm_relocs++;
+ sym -> rcnt++;
+ }
+
+ return true;
+}
+
+/* Write an Alpha NLM reloc. */
+
+static boolean
+nlm_alpha_write_import (abfd, sec, rel)
+ bfd *abfd;
+ asection *sec;
+ arelent *rel;
+{
+ asymbol *sym;
+ bfd_vma r_vaddr;
+ long r_symndx;
+ int r_type, r_extern, r_offset, r_size;
+ struct nlm32_alpha_external_reloc ext;
+
+ sym = *rel->sym_ptr_ptr;
+
+ /* Get values for the relocation fields. */
+ r_type = rel->howto->type;
+ if (r_type != ALPHA_R_NW_RELOC)
+ {
+ r_vaddr = bfd_get_section_vma (abfd, sec) + rel->address;
+ if ((sec->flags & SEC_CODE) == 0)
+ r_vaddr += bfd_section_size (abfd,
+ bfd_get_section_by_name (abfd,
+ NLM_CODE_NAME));
+ if (bfd_is_und_section (bfd_get_section (sym)))
+ {
+ r_extern = 1;
+ r_symndx = 0;
+ }
+ else
+ {
+ r_extern = 0;
+ if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
+ r_symndx = ALPHA_RELOC_SECTION_TEXT;
+ else
+ r_symndx = ALPHA_RELOC_SECTION_DATA;
+ }
+ r_offset = 0;
+ r_size = 0;
+
+ switch (r_type)
+ {
+ case ALPHA_R_LITUSE:
+ case ALPHA_R_GPDISP:
+ r_symndx = rel->addend;
+ break;
+
+ case ALPHA_R_OP_STORE:
+ r_size = rel->addend & 0xff;
+ r_offset = (rel->addend >> 8) & 0xff;
+ break;
+
+ case ALPHA_R_OP_PUSH:
+ case ALPHA_R_OP_PSUB:
+ case ALPHA_R_OP_PRSHIFT:
+ r_vaddr = rel->addend;
+ break;
+
+ case ALPHA_R_IGNORE:
+ r_vaddr = rel->address;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ /* r_type == ALPHA_R_NW_RELOC */
+ r_vaddr = rel->address;
+ if (rel->addend == 0)
+ {
+ r_symndx = 0;
+ r_size = ALPHA_R_NW_RELOC_SETGP;
+ }
+ else
+ {
+ r_symndx = rel->addend - 1;
+ r_size = ALPHA_R_NW_RELOC_LITA;
+ }
+ r_extern = 0;
+ r_offset = 0;
+ }
+
+ /* Swap out the relocation fields. */
+ bfd_h_put_64 (abfd, r_vaddr, (bfd_byte *) ext.r_vaddr);
+ bfd_h_put_32 (abfd, r_symndx, (bfd_byte *) ext.r_symndx);
+
+ BFD_ASSERT (bfd_little_endian (abfd));
+
+ ext.r_bits[0] = ((r_type << RELOC_BITS0_TYPE_SH_LITTLE)
+ & RELOC_BITS0_TYPE_LITTLE);
+ ext.r_bits[1] = ((r_extern ? RELOC_BITS1_EXTERN_LITTLE : 0)
+ | ((r_offset << RELOC_BITS1_OFFSET_SH_LITTLE)
+ & RELOC_BITS1_OFFSET_LITTLE));
+ ext.r_bits[2] = 0;
+ ext.r_bits[3] = ((r_size << RELOC_BITS3_SIZE_SH_LITTLE)
+ & RELOC_BITS3_SIZE_LITTLE);
+
+ /* Write out the relocation. */
+ if (bfd_write (&ext, sizeof ext, 1, abfd) != sizeof ext)
+ return false;
+
+ return true;
+}
+
+/* Alpha NetWare does not use the high bit to determine whether a
+ public symbol is in the code segment or the data segment. Instead,
+ it just uses the address. The set_public_section and
+ get_public_offset routines override the default code which uses the
+ high bit. */
+
+/* Set the section for a public symbol. */
+
+static boolean
+nlm_alpha_set_public_section (abfd, sym)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+{
+ asection *code_sec, *data_sec;
+
+ code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ if (sym->symbol.value < bfd_section_size (abfd, code_sec))
+ {
+ sym->symbol.section = code_sec;
+ sym->symbol.flags |= BSF_FUNCTION;
+ }
+ else
+ {
+ sym->symbol.section = data_sec;
+ sym->symbol.value -= bfd_section_size (abfd, code_sec);
+ /* The data segment had better be aligned. */
+ BFD_ASSERT ((bfd_section_size (abfd, code_sec) & 0xf) == 0);
+ }
+ return true;
+}
+
+/* Get the offset to write out for a public symbol. */
+
+static bfd_vma
+nlm_alpha_get_public_offset (abfd, sym)
+ bfd *abfd;
+ asymbol *sym;
+{
+ return bfd_asymbol_value (sym);
+}
+
+/* Write an Alpha NLM external symbol. */
+
+static boolean
+nlm_alpha_write_external (abfd, count, sym, relocs)
+ bfd *abfd;
+ bfd_size_type count;
+ asymbol *sym;
+ struct reloc_and_sec *relocs;
+{
+ int i;
+ bfd_byte len;
+ unsigned char temp[NLM_TARGET_LONG_SIZE];
+ arelent r;
+
+ len = strlen (sym->name);
+ if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
+ || bfd_write (sym->name, len, 1, abfd) != len)
+ return false;
+
+ bfd_put_32 (abfd, count + 2, temp);
+ if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ /* The first two relocs for each external symbol are the .lita
+ address and the GP value. */
+ r.sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ r.howto = &nlm32_alpha_nw_howto;
+
+ r.address = nlm_alpha_backend_data (abfd)->lita_address;
+ r.addend = nlm_alpha_backend_data (abfd)->lita_size + 1;
+ if (nlm_alpha_write_import (abfd, (asection *) NULL, &r) == false)
+ return false;
+
+ r.address = nlm_alpha_backend_data (abfd)->gp;
+ r.addend = 0;
+ if (nlm_alpha_write_import (abfd, (asection *) NULL, &r) == false)
+ return false;
+
+ for (i = 0; i < count; i++)
+ {
+ if (nlm_alpha_write_import (abfd, relocs[i].sec,
+ relocs[i].rel) == false)
+ return false;
+ }
+
+ return true;
+}
+
+#include "nlmswap.h"
+
+static const struct nlm_backend_data nlm32_alpha_backend =
+{
+ "NetWare Alpha Module \032",
+ sizeof (Nlm32_alpha_External_Fixed_Header),
+ sizeof (struct nlm32_alpha_external_prefix_header),
+ bfd_arch_alpha,
+ 0,
+ true, /* no uninitialized data permitted by Alpha NetWare. */
+ nlm_alpha_backend_object_p,
+ nlm_alpha_write_prefix,
+ nlm_alpha_read_reloc,
+ nlm_alpha_mangle_relocs,
+ nlm_alpha_read_import,
+ nlm_alpha_write_import,
+ nlm_alpha_set_public_section,
+ nlm_alpha_get_public_offset,
+ nlm_swap_fixed_header_in,
+ nlm_swap_fixed_header_out,
+ nlm_alpha_write_external,
+ 0, /* write_export */
+};
+
+#define TARGET_LITTLE_NAME "nlm32-alpha"
+#define TARGET_LITTLE_SYM nlmNAME(alpha_vec)
+#define TARGET_BACKEND_DATA &nlm32_alpha_backend
+
+#include "nlm-target.h"
diff --git a/contrib/gdb/bfd/nlm32-i386.c b/contrib/gdb/bfd/nlm32-i386.c
new file mode 100644
index 0000000..f16c74d
--- /dev/null
+++ b/contrib/gdb/bfd/nlm32-i386.c
@@ -0,0 +1,451 @@
+/* Support for 32-bit i386 NLM (NetWare Loadable Module)
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#define ARCH_SIZE 32
+
+#include "nlm/i386-ext.h"
+#define Nlm_External_Fixed_Header Nlm32_i386_External_Fixed_Header
+
+#include "libnlm.h"
+
+static boolean nlm_i386_read_reloc
+ PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
+static boolean nlm_i386_write_import
+ PARAMS ((bfd *, asection *, arelent *));
+static boolean nlm_i386_mangle_relocs
+ PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
+static boolean nlm_i386_read_import
+ PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static boolean nlm_i386_write_external
+ PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
+
+/* Adjust the reloc location by an absolute value. */
+
+static reloc_howto_type nlm_i386_abs_howto =
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* Adjust the reloc location by a PC relative displacement. */
+
+static reloc_howto_type nlm_i386_pcrel_howto =
+ HOWTO (1, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "DISP32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true); /* pcrel_offset */
+
+/* Read a NetWare i386 reloc. */
+
+static boolean
+nlm_i386_read_reloc (abfd, sym, secp, rel)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+ asection **secp;
+ arelent *rel;
+{
+ bfd_byte temp[4];
+ bfd_vma val;
+ const char *name;
+
+ if (bfd_read (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ val = bfd_get_32 (abfd, temp);
+
+ /* The value is an offset into either the code or data segment.
+ This is the location which needs to be adjusted.
+
+ If this is a relocation fixup rather than an imported symbol (the
+ sym argument is NULL) then the high bit is 0 if the location
+ needs to be adjusted by the address of the data segment, or 1 if
+ the location needs to be adjusted by the address of the code
+ segment. If this is an imported symbol, then the high bit is 0
+ if the location is 0 if the location should be adjusted by the
+ offset to the symbol, or 1 if the location should adjusted by the
+ absolute value of the symbol.
+
+ The second most significant bit is 0 if the value is an offset
+ into the data segment, or 1 if the value is an offset into the
+ code segment.
+
+ All this translates fairly easily into a BFD reloc. */
+
+ if (sym == NULL)
+ {
+ if ((val & NLM_HIBIT) == 0)
+ name = NLM_INITIALIZED_DATA_NAME;
+ else
+ {
+ name = NLM_CODE_NAME;
+ val &=~ NLM_HIBIT;
+ }
+ rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
+ rel->howto = &nlm_i386_abs_howto;
+ }
+ else
+ {
+ /* In this case we do not need to set the sym_ptr_ptr field. */
+ rel->sym_ptr_ptr = NULL;
+ if ((val & NLM_HIBIT) == 0)
+ rel->howto = &nlm_i386_pcrel_howto;
+ else
+ {
+ rel->howto = &nlm_i386_abs_howto;
+ val &=~ NLM_HIBIT;
+ }
+ }
+
+ if ((val & (NLM_HIBIT >> 1)) == 0)
+ *secp = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ else
+ {
+ *secp = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ val &=~ (NLM_HIBIT >> 1);
+ }
+
+ rel->address = val;
+ rel->addend = 0;
+
+ return true;
+}
+
+/* Write a NetWare i386 reloc. */
+
+static boolean
+nlm_i386_write_import (abfd, sec, rel)
+ bfd *abfd;
+ asection *sec;
+ arelent *rel;
+{
+ asymbol *sym;
+ bfd_vma val;
+ bfd_byte temp[4];
+
+ /* NetWare only supports two kinds of relocs. We should check
+ special_function here, as well, but at the moment coff-i386
+ relocs uses a special_function which does not affect what we do
+ here. */
+ if (rel->addend != 0
+ || rel->howto == NULL
+ || rel->howto->rightshift != 0
+ || rel->howto->size != 2
+ || rel->howto->bitsize != 32
+ || rel->howto->bitpos != 0
+ || rel->howto->src_mask != 0xffffffff
+ || rel->howto->dst_mask != 0xffffffff)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ sym = *rel->sym_ptr_ptr;
+
+ /* The value we write out is the offset into the appropriate
+ segment. This offset is the section vma, adjusted by the vma of
+ the lowest section in that segment, plus the address of the
+ relocation. */
+ val = bfd_get_section_vma (abfd, sec) + rel->address;
+
+ /* The second most significant bit is 0 if the value is an offset
+ into the data segment, or 1 if the value is an offset into the
+ code segment. */
+ if (bfd_get_section_flags (abfd, sec) & SEC_CODE)
+ {
+ val -= nlm_get_text_low (abfd);
+ val |= NLM_HIBIT >> 1;
+ }
+ else
+ val -= nlm_get_data_low (abfd);
+
+ if (! bfd_is_und_section (bfd_get_section (sym)))
+ {
+ /* NetWare only supports absolute internal relocs. */
+ if (rel->howto->pc_relative)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ /* The high bit is 1 if the reloc is against the code section, 0
+ if against the data section. */
+ if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
+ val |= NLM_HIBIT;
+ }
+ else
+ {
+ /* The high bit is 1 if this is an absolute reloc, 0 if it is PC
+ relative. */
+ if (! rel->howto->pc_relative)
+ val |= NLM_HIBIT;
+ else
+ {
+ /* PC relative relocs on NetWare must be pcrel_offset. */
+ if (! rel->howto->pcrel_offset)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+ }
+ }
+
+ bfd_put_32 (abfd, val, temp);
+ if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ return true;
+}
+
+/* I want to be able to use objcopy to turn a i386 a.out or COFF file
+ into a NetWare i386 module. That means that the relocs from the
+ source file have to be mapped into relocs that apply to the target
+ file. This function is called by nlm_set_section_contents to give
+ it a chance to rework the relocs.
+
+ This is actually a fairly general concept. However, this is not a
+ general implementation. */
+
+static boolean
+nlm_i386_mangle_relocs (abfd, sec, data, offset, count)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+ bfd_vma offset;
+ bfd_size_type count;
+{
+ arelent **rel_ptr_ptr, **rel_end;
+
+ rel_ptr_ptr = sec->orelocation;
+ rel_end = rel_ptr_ptr + sec->reloc_count;
+ for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
+ {
+ arelent *rel;
+ asymbol *sym;
+ bfd_vma addend;
+
+ rel = *rel_ptr_ptr;
+ sym = *rel->sym_ptr_ptr;
+
+ /* Note that no serious harm will ensue if we fail to change a
+ reloc. We will wind up failing in nlm_i386_write_import. */
+
+ /* Make sure this reloc is within the data we have. We only 4
+ byte relocs here, so we insist on having 4 bytes. */
+ if (rel->address < offset
+ || rel->address + 4 > offset + count)
+ continue;
+
+ /* NetWare doesn't support reloc addends, so we get rid of them
+ here by simply adding them into the object data. We handle
+ the symbol value, if any, the same way. */
+ addend = rel->addend + sym->value;
+
+ /* The value of a symbol is the offset into the section. If the
+ symbol is in the .bss segment, we need to include the size of
+ the data segment in the offset as well. Fortunately, we know
+ that at this point the size of the data section is in the NLM
+ header. */
+ if (((bfd_get_section_flags (abfd, bfd_get_section (sym))
+ & SEC_LOAD) == 0)
+ && ((bfd_get_section_flags (abfd, bfd_get_section (sym))
+ & SEC_ALLOC) != 0))
+ addend += nlm_fixed_header (abfd)->dataImageSize;
+
+ if (addend != 0
+ && rel->howto != NULL
+ && rel->howto->rightshift == 0
+ && rel->howto->size == 2
+ && rel->howto->bitsize == 32
+ && rel->howto->bitpos == 0
+ && rel->howto->src_mask == 0xffffffff
+ && rel->howto->dst_mask == 0xffffffff)
+ {
+ bfd_vma val;
+
+ val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
+ val += addend;
+ bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
+ rel->addend = 0;
+ }
+
+ /* NetWare uses a reloc with pcrel_offset set. We adjust
+ pc_relative relocs accordingly. We are going to change the
+ howto field, so we can only do this if the current one is
+ compatible. We should check special_function here, but at
+ the moment coff-i386 uses a special_function which does not
+ affect what we are doing here. */
+ if (rel->howto != NULL
+ && rel->howto->pc_relative
+ && ! rel->howto->pcrel_offset
+ && rel->howto->rightshift == 0
+ && rel->howto->size == 2
+ && rel->howto->bitsize == 32
+ && rel->howto->bitpos == 0
+ && rel->howto->src_mask == 0xffffffff
+ && rel->howto->dst_mask == 0xffffffff)
+ {
+ bfd_vma val;
+
+ /* When pcrel_offset is not set, it means that the negative
+ of the address of the memory location is stored in the
+ memory location. We must add it back in. */
+ val = bfd_get_32 (abfd, (bfd_byte *) data + rel->address - offset);
+ val += rel->address;
+ bfd_put_32 (abfd, val, (bfd_byte *) data + rel->address - offset);
+
+ rel->howto = &nlm_i386_pcrel_howto;
+ }
+ }
+
+ return true;
+}
+
+/* Read a NetWare i386 import record */
+static boolean
+nlm_i386_read_import (abfd, sym)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+{
+ struct nlm_relent *nlm_relocs; /* relocation records for symbol */
+ bfd_size_type rcount; /* number of relocs */
+ bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
+ unsigned char symlength; /* length of symbol name */
+ char *name;
+
+ if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
+ != sizeof (symlength))
+ return false;
+ sym -> symbol.the_bfd = abfd;
+ name = bfd_alloc (abfd, symlength + 1);
+ if (name == NULL)
+ return false;
+ if (bfd_read (name, symlength, 1, abfd) != symlength)
+ return false;
+ name[symlength] = '\0';
+ sym -> symbol.name = name;
+ sym -> symbol.flags = 0;
+ sym -> symbol.value = 0;
+ sym -> symbol.section = bfd_und_section_ptr;
+ if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return false;
+ rcount = bfd_h_get_32 (abfd, temp);
+ nlm_relocs = ((struct nlm_relent *)
+ bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
+ if (!nlm_relocs)
+ return false;
+ sym -> relocs = nlm_relocs;
+ sym -> rcnt = 0;
+ while (sym -> rcnt < rcount)
+ {
+ asection *section;
+
+ if (nlm_i386_read_reloc (abfd, sym, &section,
+ &nlm_relocs -> reloc)
+ == false)
+ return false;
+ nlm_relocs -> section = section;
+ nlm_relocs++;
+ sym -> rcnt++;
+ }
+ return true;
+}
+
+/* Write out an external reference. */
+
+static boolean
+nlm_i386_write_external (abfd, count, sym, relocs)
+ bfd *abfd;
+ bfd_size_type count;
+ asymbol *sym;
+ struct reloc_and_sec *relocs;
+{
+ unsigned int i;
+ bfd_byte len;
+ unsigned char temp[NLM_TARGET_LONG_SIZE];
+
+ len = strlen (sym->name);
+ if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
+ || bfd_write (sym->name, len, 1, abfd) != len)
+ return false;
+
+ bfd_put_32 (abfd, count, temp);
+ if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ for (i = 0; i < count; i++)
+ {
+ if (nlm_i386_write_import (abfd, relocs[i].sec,
+ relocs[i].rel) == false)
+ return false;
+ }
+
+ return true;
+}
+
+#include "nlmswap.h"
+
+static const struct nlm_backend_data nlm32_i386_backend =
+{
+ "NetWare Loadable Module\032",
+ sizeof (Nlm32_i386_External_Fixed_Header),
+ 0, /* optional_prefix_size */
+ bfd_arch_i386,
+ 0,
+ false,
+ 0, /* backend_object_p */
+ 0, /* write_prefix_func */
+ nlm_i386_read_reloc,
+ nlm_i386_mangle_relocs,
+ nlm_i386_read_import,
+ nlm_i386_write_import,
+ 0, /* set_public_section */
+ 0, /* get_public_offset */
+ nlm_swap_fixed_header_in,
+ nlm_swap_fixed_header_out,
+ nlm_i386_write_external,
+ 0, /* write_export */
+};
+
+#define TARGET_LITTLE_NAME "nlm32-i386"
+#define TARGET_LITTLE_SYM nlmNAME(i386_vec)
+#define TARGET_BACKEND_DATA &nlm32_i386_backend
+
+#include "nlm-target.h"
diff --git a/contrib/gdb/bfd/nlm32-ppc.c b/contrib/gdb/bfd/nlm32-ppc.c
new file mode 100644
index 0000000..ecf2de8
--- /dev/null
+++ b/contrib/gdb/bfd/nlm32-ppc.c
@@ -0,0 +1,1045 @@
+/* Support for 32-bit PowerPC NLM (NetWare Loadable Module)
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/* The format of a PowerPC NLM changed. Define OLDFORMAT to get the
+ old format. */
+
+#define ARCH_SIZE 32
+
+#include "nlm/ppc-ext.h"
+#define Nlm_External_Fixed_Header Nlm32_powerpc_External_Fixed_Header
+
+#include "libnlm.h"
+
+#ifdef OLDFORMAT
+static boolean nlm_powerpc_backend_object_p
+ PARAMS ((bfd *));
+static boolean nlm_powerpc_write_prefix
+ PARAMS ((bfd *));
+#endif
+
+static boolean nlm_powerpc_read_reloc
+ PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
+static boolean nlm_powerpc_mangle_relocs
+ PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
+static boolean nlm_powerpc_read_import
+ PARAMS ((bfd *, nlmNAME(symbol_type) *));
+
+#ifdef OLDFORMAT
+static boolean nlm_powerpc_write_reloc
+ PARAMS ((bfd *, asection *, arelent *, int));
+#endif
+
+static boolean nlm_powerpc_write_import
+ PARAMS ((bfd *, asection *, arelent *));
+static boolean nlm_powerpc_write_external
+ PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
+
+#ifndef OLDFORMAT
+static boolean nlm_powerpc_set_public_section
+ PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static bfd_vma nlm_powerpc_get_public_offset
+ PARAMS ((bfd *, asymbol *));
+#endif
+
+#ifdef OLDFORMAT
+
+/* The prefix header is only used in the old format. */
+
+/* PowerPC NLM's have a prefix header before the standard NLM. This
+ function reads it in, verifies the version, and seeks the bfd to
+ the location before the regular NLM header. */
+
+static boolean
+nlm_powerpc_backend_object_p (abfd)
+ bfd *abfd;
+{
+ struct nlm32_powerpc_external_prefix_header s;
+
+ if (bfd_read ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
+ return false;
+
+ if (memcmp (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature) != 0
+ || bfd_h_get_32 (abfd, s.headerVersion) != NLM32_POWERPC_HEADER_VERSION)
+ return false;
+
+ return true;
+}
+
+/* Write out the prefix. */
+
+static boolean
+nlm_powerpc_write_prefix (abfd)
+ bfd *abfd;
+{
+ struct nlm32_powerpc_external_prefix_header s;
+
+ memset (&s, 0, sizeof s);
+ memcpy (s.signature, NLM32_POWERPC_SIGNATURE, sizeof s.signature);
+ bfd_h_put_32 (abfd, (bfd_vma) NLM32_POWERPC_HEADER_VERSION, s.headerVersion);
+ bfd_h_put_32 (abfd, (bfd_vma) 0, s.origins);
+
+ /* FIXME: What should we do about the date? */
+
+ if (bfd_write ((PTR) &s, sizeof s, 1, abfd) != sizeof s)
+ return false;
+
+ return true;
+}
+
+#endif /* OLDFORMAT */
+
+#ifndef OLDFORMAT
+
+/* There is only one type of reloc in a PowerPC NLM. */
+
+static reloc_howto_type nlm_powerpc_howto =
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false); /* pcrel_offset */
+
+/* Read a PowerPC NLM reloc. */
+
+static boolean
+nlm_powerpc_read_reloc (abfd, sym, secp, rel)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+ asection **secp;
+ arelent *rel;
+{
+ bfd_byte temp[4];
+ bfd_vma val;
+ const char *name;
+
+ if (bfd_read (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ val = bfd_get_32 (abfd, temp);
+
+ /* The value is a word offset into either the code or data segment.
+ This is the location which needs to be adjusted.
+
+ The high bit is 0 if the value is an offset into the data
+ segment, or 1 if the value is an offset into the text segment.
+
+ If this is a relocation fixup rather than an imported symbol (the
+ sym argument is NULL), then the second most significant bit is 0
+ if the address of the data segment should be added to the
+ location addressed by the value, or 1 if the address of the text
+ segment should be added.
+
+ If this is an imported symbol, the second most significant bit is
+ not used and must be 0. */
+
+ if ((val & NLM_HIBIT) == 0)
+ name = NLM_INITIALIZED_DATA_NAME;
+ else
+ {
+ name = NLM_CODE_NAME;
+ val &=~ NLM_HIBIT;
+ }
+ *secp = bfd_get_section_by_name (abfd, name);
+
+ if (sym == NULL)
+ {
+ if ((val & (NLM_HIBIT >> 1)) == 0)
+ name = NLM_INITIALIZED_DATA_NAME;
+ else
+ {
+ name = NLM_CODE_NAME;
+ val &=~ (NLM_HIBIT >> 1);
+ }
+ rel->sym_ptr_ptr = bfd_get_section_by_name (abfd, name)->symbol_ptr_ptr;
+ }
+
+ rel->howto = &nlm_powerpc_howto;
+
+ rel->address = val << 2;
+ rel->addend = 0;
+
+ return true;
+}
+
+#else /* OLDFORMAT */
+
+/* This reloc handling is only applicable to the old format. */
+
+/* How to process the various reloc types. PowerPC NLMs use XCOFF
+ reloc types, and I have just copied the XCOFF reloc table here. */
+
+static reloc_howto_type nlm_powerpc_howto_table[] =
+{
+ /* Standard 32 bit relocation. */
+ HOWTO (0, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_POS", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit relocation, but store negative value. */
+ HOWTO (1, /* type */
+ 0, /* rightshift */
+ -2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_NEG", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 32 bit PC relative relocation. */
+ HOWTO (2, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REL", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* 16 bit TOC relative relocation. */
+ HOWTO (3, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TOC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* I don't really know what this is. */
+ HOWTO (4, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RTB", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* External TOC relative symbol. */
+ HOWTO (5, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_GL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Local TOC relative symbol. */
+ HOWTO (6, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TCL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 7 },
+
+ /* Non modifiable absolute branch. */
+ HOWTO (8, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_BA", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 9 },
+
+ /* Non modifiable relative branch. */
+ HOWTO (0xa, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_BR", /* name */
+ true, /* partial_inplace */
+ 0x3fffffc, /* src_mask */
+ 0x3fffffc, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 0xb },
+
+ /* Indirect load. */
+ HOWTO (0xc, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Load address. */
+ HOWTO (0xd, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RLA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 0xe },
+
+ /* Non-relocating reference. */
+ HOWTO (0xf, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REF", /* name */
+ false, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ false), /* pcrel_offset */
+
+ { 0x10 },
+ { 0x11 },
+
+ /* TOC relative indirect load. */
+ HOWTO (0x12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TRL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* TOC relative load address. */
+ HOWTO (0x13, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_TRLA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable relative branch. */
+ HOWTO (0x14, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RRTBI", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable absolute branch. */
+ HOWTO (0x15, /* type */
+ 1, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RRTBA", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable call absolute indirect. */
+ HOWTO (0x16, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_CAI", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable call relative. */
+ HOWTO (0x17, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x18, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBA", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x19, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBAC", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch relative. */
+ HOWTO (0x1a, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
+
+ /* Modifiable branch absolute. */
+ HOWTO (0x1b, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_REL", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false) /* pcrel_offset */
+};
+
+#define HOWTO_COUNT (sizeof nlm_powerpc_howto_table \
+ / sizeof nlm_powerpc_howto_table[0])
+
+/* Read a PowerPC NLM reloc. */
+
+static boolean
+nlm_powerpc_read_reloc (abfd, sym, secp, rel)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+ asection **secp;
+ arelent *rel;
+{
+ struct nlm32_powerpc_external_reloc ext;
+ bfd_vma l_vaddr;
+ unsigned long l_symndx;
+ int l_rtype;
+ int l_rsecnm;
+ asection *code_sec, *data_sec, *bss_sec;
+
+ /* Read the reloc from the file. */
+ if (bfd_read (&ext, sizeof ext, 1, abfd) != sizeof ext)
+ return false;
+
+ /* Swap in the fields. */
+ l_vaddr = bfd_h_get_32 (abfd, ext.l_vaddr);
+ l_symndx = bfd_h_get_32 (abfd, ext.l_symndx);
+ l_rtype = bfd_h_get_16 (abfd, ext.l_rtype);
+ l_rsecnm = bfd_h_get_16 (abfd, ext.l_rsecnm);
+
+ /* Get the sections now, for convenience. */
+ code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
+
+ /* Work out the arelent fields. */
+ if (sym != NULL)
+ {
+ /* This is an import. sym_ptr_ptr is filled in by
+ nlm_canonicalize_reloc. */
+ rel->sym_ptr_ptr = NULL;
+ }
+ else
+ {
+ asection *sec;
+
+ if (l_symndx == 0)
+ sec = code_sec;
+ else if (l_symndx == 1)
+ sec = data_sec;
+ else if (l_symndx == 2)
+ sec = bss_sec;
+ else
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ rel->sym_ptr_ptr = sec->symbol_ptr_ptr;
+ }
+
+ rel->addend = 0;
+
+ BFD_ASSERT ((l_rtype & 0xff) < HOWTO_COUNT);
+
+ rel->howto = nlm_powerpc_howto_table + (l_rtype & 0xff);
+
+ BFD_ASSERT (rel->howto->name != NULL
+ && ((l_rtype & 0x8000) != 0
+ ? (rel->howto->complain_on_overflow
+ == complain_overflow_signed)
+ : (rel->howto->complain_on_overflow
+ == complain_overflow_bitfield))
+ && ((l_rtype >> 8) & 0x1f) == rel->howto->bitsize - 1);
+
+ if (l_rsecnm == 0)
+ *secp = code_sec;
+ else if (l_rsecnm == 1)
+ {
+ *secp = data_sec;
+ l_vaddr -= bfd_section_size (abfd, code_sec);
+ }
+ else
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ rel->address = l_vaddr;
+
+ return true;
+}
+
+#endif /* OLDFORMAT */
+
+/* Mangle PowerPC NLM relocs for output. */
+
+static boolean
+nlm_powerpc_mangle_relocs (abfd, sec, data, offset, count)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+ bfd_vma offset;
+ bfd_size_type count;
+{
+ return true;
+}
+
+/* Read a PowerPC NLM import record */
+
+static boolean
+nlm_powerpc_read_import (abfd, sym)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+{
+ struct nlm_relent *nlm_relocs; /* relocation records for symbol */
+ bfd_size_type rcount; /* number of relocs */
+ bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
+ unsigned char symlength; /* length of symbol name */
+ char *name;
+
+ if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
+ != sizeof (symlength))
+ return (false);
+ sym -> symbol.the_bfd = abfd;
+ name = bfd_alloc (abfd, symlength + 1);
+ if (name == NULL)
+ return false;
+ if (bfd_read (name, symlength, 1, abfd) != symlength)
+ return (false);
+ name[symlength] = '\0';
+ sym -> symbol.name = name;
+ sym -> symbol.flags = 0;
+ sym -> symbol.value = 0;
+ sym -> symbol.section = bfd_und_section_ptr;
+ if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return (false);
+ rcount = bfd_h_get_32 (abfd, temp);
+ nlm_relocs = ((struct nlm_relent *)
+ bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
+ if (nlm_relocs == (struct nlm_relent *) NULL)
+ return false;
+ sym -> relocs = nlm_relocs;
+ sym -> rcnt = 0;
+ while (sym -> rcnt < rcount)
+ {
+ asection *section;
+
+ if (nlm_powerpc_read_reloc (abfd, sym, &section,
+ &nlm_relocs -> reloc)
+ == false)
+ return false;
+ nlm_relocs -> section = section;
+ nlm_relocs++;
+ sym -> rcnt++;
+ }
+ return true;
+}
+
+#ifndef OLDFORMAT
+
+/* Write a PowerPC NLM reloc. */
+
+static boolean
+nlm_powerpc_write_import (abfd, sec, rel)
+ bfd *abfd;
+ asection *sec;
+ arelent *rel;
+{
+ asymbol *sym;
+ bfd_vma val;
+ bfd_byte temp[4];
+
+ /* PowerPC NetWare only supports one kind of reloc. */
+ if (rel->addend != 0
+ || rel->howto == NULL
+ || rel->howto->rightshift != 0
+ || rel->howto->size != 2
+ || rel->howto->bitsize != 32
+ || rel->howto->bitpos != 0
+ || rel->howto->pc_relative
+ || (rel->howto->src_mask != 0xffffffff && rel->addend != 0)
+ || rel->howto->dst_mask != 0xffffffff)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ sym = *rel->sym_ptr_ptr;
+
+ /* The value we write out is the offset into the appropriate
+ segment, rightshifted by two. This offset is the section vma,
+ adjusted by the vma of the lowest section in that segment, plus
+ the address of the relocation. */
+ val = bfd_get_section_vma (abfd, sec) + rel->address;
+ if ((val & 3) != 0)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ val >>= 2;
+
+ /* The high bit is 0 if the reloc is in the data section, or 1 if
+ the reloc is in the code section. */
+ if (bfd_get_section_flags (abfd, sec) & SEC_DATA)
+ val -= nlm_get_data_low (abfd);
+ else
+ {
+ val -= nlm_get_text_low (abfd);
+ val |= NLM_HIBIT;
+ }
+
+ if (! bfd_is_und_section (bfd_get_section (sym)))
+ {
+ /* This is an internal relocation fixup. The second most
+ significant bit is 0 if this is a reloc against the data
+ segment, or 1 if it is a reloc against the text segment. */
+ if (bfd_get_section_flags (abfd, bfd_get_section (sym)) & SEC_CODE)
+ val |= NLM_HIBIT >> 1;
+ }
+
+ bfd_put_32 (abfd, val, temp);
+ if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ return true;
+}
+
+#else /* OLDFORMAT */
+
+/* This is used for the reloc handling in the old format. */
+
+/* Write a PowerPC NLM reloc. */
+
+static boolean
+nlm_powerpc_write_reloc (abfd, sec, rel, indx)
+ bfd *abfd;
+ asection *sec;
+ arelent *rel;
+ int indx;
+{
+ struct nlm32_powerpc_external_reloc ext;
+ asection *code_sec, *data_sec, *bss_sec;
+ asymbol *sym;
+ asection *symsec;
+ unsigned long l_symndx;
+ int l_rtype;
+ int l_rsecnm;
+ reloc_howto_type *howto;
+ bfd_size_type address;
+
+ /* Get the sections now, for convenience. */
+ code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
+
+ sym = *rel->sym_ptr_ptr;
+ symsec = bfd_get_section (sym);
+ if (indx != -1)
+ {
+ BFD_ASSERT (bfd_is_und_section (symsec));
+ l_symndx = indx + 3;
+ }
+ else
+ {
+ if (symsec == code_sec)
+ l_symndx = 0;
+ else if (symsec == data_sec)
+ l_symndx = 1;
+ else if (symsec == bss_sec)
+ l_symndx = 2;
+ else
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ }
+
+ bfd_h_put_32 (abfd, (bfd_vma) l_symndx, ext.l_symndx);
+
+ for (howto = nlm_powerpc_howto_table;
+ howto < nlm_powerpc_howto_table + HOWTO_COUNT;
+ howto++)
+ {
+ if (howto->rightshift == rel->howto->rightshift
+ && howto->size == rel->howto->size
+ && howto->bitsize == rel->howto->bitsize
+ && howto->pc_relative == rel->howto->pc_relative
+ && howto->bitpos == rel->howto->bitpos
+ && (howto->partial_inplace == rel->howto->partial_inplace
+ || (! rel->howto->partial_inplace
+ && rel->addend == 0))
+ && (howto->src_mask == rel->howto->src_mask
+ || (rel->howto->src_mask == 0
+ && rel->addend == 0))
+ && howto->dst_mask == rel->howto->dst_mask
+ && howto->pcrel_offset == rel->howto->pcrel_offset)
+ break;
+ }
+ if (howto >= nlm_powerpc_howto_table + HOWTO_COUNT)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ l_rtype = howto->type;
+ if (howto->complain_on_overflow == complain_overflow_signed)
+ l_rtype |= 0x8000;
+ l_rtype |= (howto->bitsize - 1) << 8;
+ bfd_h_put_16 (abfd, (bfd_vma) l_rtype, ext.l_rtype);
+
+ address = rel->address;
+
+ if (sec == code_sec)
+ l_rsecnm = 0;
+ else if (sec == data_sec)
+ {
+ l_rsecnm = 1;
+ address += bfd_section_size (abfd, code_sec);
+ }
+ else
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ bfd_h_put_16 (abfd, (bfd_vma) l_rsecnm, ext.l_rsecnm);
+ bfd_h_put_32 (abfd, (bfd_vma) address, ext.l_vaddr);
+
+ if (bfd_write (&ext, sizeof ext, 1, abfd) != sizeof ext)
+ return false;
+
+ return true;
+}
+
+/* Write a PowerPC NLM import. */
+
+static boolean
+nlm_powerpc_write_import (abfd, sec, rel)
+ bfd *abfd;
+ asection *sec;
+ arelent *rel;
+{
+ return nlm_powerpc_write_reloc (abfd, sec, rel, -1);
+}
+
+#endif /* OLDFORMAT */
+
+/* Write a PowerPC NLM external symbol. This routine keeps a static
+ count of the symbol index. FIXME: I don't know if this is
+ necessary, and the index never gets reset. */
+
+static boolean
+nlm_powerpc_write_external (abfd, count, sym, relocs)
+ bfd *abfd;
+ bfd_size_type count;
+ asymbol *sym;
+ struct reloc_and_sec *relocs;
+{
+ unsigned int i;
+ bfd_byte len;
+ unsigned char temp[NLM_TARGET_LONG_SIZE];
+#ifdef OLDFORMAT
+ static int indx;
+#endif
+
+ len = strlen (sym->name);
+ if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
+ || bfd_write (sym->name, len, 1, abfd) != len)
+ return false;
+
+ bfd_put_32 (abfd, count, temp);
+ if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ for (i = 0; i < count; i++)
+ {
+#ifndef OLDFORMAT
+ if (! nlm_powerpc_write_import (abfd, relocs[i].sec, relocs[i].rel))
+ return false;
+#else
+ if (! nlm_powerpc_write_reloc (abfd, relocs[i].sec,
+ relocs[i].rel, indx))
+ return false;
+#endif
+ }
+
+#ifdef OLDFORMAT
+ ++indx;
+#endif
+
+ return true;
+}
+
+#ifndef OLDFORMAT
+
+/* PowerPC Netware uses a word offset, not a byte offset, for public
+ symbols. */
+
+/* Set the section for a public symbol. */
+
+static boolean
+nlm_powerpc_set_public_section (abfd, sym)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+{
+ if (sym->symbol.value & NLM_HIBIT)
+ {
+ sym->symbol.value &= ~NLM_HIBIT;
+ sym->symbol.flags |= BSF_FUNCTION;
+ sym->symbol.section =
+ bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ }
+ else
+ {
+ sym->symbol.section =
+ bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ }
+
+ sym->symbol.value <<= 2;
+
+ return true;
+}
+
+/* Get the offset to write out for a public symbol. */
+
+static bfd_vma
+nlm_powerpc_get_public_offset (abfd, sym)
+ bfd *abfd;
+ asymbol *sym;
+{
+ bfd_vma offset;
+ asection *sec;
+
+ offset = bfd_asymbol_value (sym);
+ sec = bfd_get_section (sym);
+ if (sec->flags & SEC_CODE)
+ {
+ offset -= nlm_get_text_low (abfd);
+ offset |= NLM_HIBIT;
+ }
+ else if (sec->flags & (SEC_DATA | SEC_ALLOC))
+ {
+ /* SEC_ALLOC is for the .bss section. */
+ offset -= nlm_get_data_low (abfd);
+ }
+ else
+ {
+ /* We can't handle an exported symbol that is not in the code or
+ data segment. */
+ bfd_set_error (bfd_error_invalid_operation);
+ /* FIXME: No way to return error. */
+ abort ();
+ }
+
+ return offset;
+}
+
+#endif /* ! defined (OLDFORMAT) */
+
+#include "nlmswap.h"
+
+static const struct nlm_backend_data nlm32_powerpc_backend =
+{
+ "NetWare PowerPC Module \032",
+ sizeof (Nlm32_powerpc_External_Fixed_Header),
+#ifndef OLDFORMAT
+ 0, /* optional_prefix_size */
+#else
+ sizeof (struct nlm32_powerpc_external_prefix_header),
+#endif
+ bfd_arch_powerpc,
+ 0,
+ false,
+#ifndef OLDFORMAT
+ 0, /* backend_object_p */
+ 0, /* write_prefix */
+#else
+ nlm_powerpc_backend_object_p,
+ nlm_powerpc_write_prefix,
+#endif
+ nlm_powerpc_read_reloc,
+ nlm_powerpc_mangle_relocs,
+ nlm_powerpc_read_import,
+ nlm_powerpc_write_import,
+#ifndef OLDFORMAT
+ nlm_powerpc_set_public_section,
+ nlm_powerpc_get_public_offset,
+#else
+ 0, /* set_public_section */
+ 0, /* get_public_offset */
+#endif
+ nlm_swap_fixed_header_in,
+ nlm_swap_fixed_header_out,
+ nlm_powerpc_write_external,
+ 0, /* write_export */
+};
+
+#define TARGET_BIG_NAME "nlm32-powerpc"
+#define TARGET_BIG_SYM nlmNAME(powerpc_vec)
+#define TARGET_BACKEND_DATA &nlm32_powerpc_backend
+
+#include "nlm-target.h"
diff --git a/contrib/gdb/bfd/nlm32-sparc.c b/contrib/gdb/bfd/nlm32-sparc.c
new file mode 100644
index 0000000..5963adb
--- /dev/null
+++ b/contrib/gdb/bfd/nlm32-sparc.c
@@ -0,0 +1,440 @@
+/* Support for 32-bit SPARC NLM (NetWare Loadable Module)
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#define ARCH_SIZE 32
+
+#include "nlm/sparc32-ext.h"
+#define Nlm_External_Fixed_Header Nlm32_sparc_External_Fixed_Header
+
+#include "libnlm.h"
+
+static boolean nlm_sparc_read_reloc
+ PARAMS ((bfd *, nlmNAME(symbol_type) *, asection **, arelent *));
+static boolean nlm_sparc_write_reloc
+ PARAMS ((bfd *, asection *, arelent *));
+static boolean nlm_sparc_mangle_relocs
+ PARAMS ((bfd *, asection *, PTR, bfd_vma, bfd_size_type));
+static boolean nlm_sparc_read_import
+ PARAMS ((bfd *, nlmNAME(symbol_type) *));
+static boolean nlm_sparc_write_import
+ PARAMS ((bfd *, asection *, arelent *));
+static boolean nlm_sparc_write_external
+ PARAMS ((bfd *, bfd_size_type, asymbol *, struct reloc_and_sec *));
+
+enum reloc_type
+ {
+ R_SPARC_NONE = 0,
+ R_SPARC_8, R_SPARC_16, R_SPARC_32,
+ R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
+ R_SPARC_WDISP30, R_SPARC_WDISP22,
+ R_SPARC_HI22, R_SPARC_22,
+ R_SPARC_13, R_SPARC_LO10,
+ R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
+ R_SPARC_PC10, R_SPARC_PC22,
+ R_SPARC_WPLT30,
+ R_SPARC_COPY,
+ R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
+ R_SPARC_RELATIVE,
+ R_SPARC_UA32,
+ R_SPARC_max
+ };
+
+#if 0
+static CONST char *CONST reloc_type_names[] =
+{
+ "R_SPARC_NONE",
+ "R_SPARC_8", "R_SPARC_16", "R_SPARC_32",
+ "R_SPARC_DISP8", "R_SPARC_DISP16", "R_SPARC_DISP32",
+ "R_SPARC_WDISP30", "R_SPARC_WDISP22",
+ "R_SPARC_HI22", "R_SPARC_22",
+ "R_SPARC_13", "R_SPARC_LO10",
+ "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22",
+ "R_SPARC_PC10", "R_SPARC_PC22",
+ "R_SPARC_WPLT30",
+ "R_SPARC_COPY",
+ "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT",
+ "R_SPARC_RELATIVE",
+ "R_SPARC_UA32",
+};
+#endif
+
+static reloc_howto_type nlm32_sparc_howto_table[] =
+{
+ HOWTO(R_SPARC_NONE, 0,0, 0,false,0,complain_overflow_dont, 0,"R_SPARC_NONE", false,0,0x00000000,true),
+ HOWTO(R_SPARC_8, 0,0, 8,false,0,complain_overflow_bitfield,0,"R_SPARC_8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_16, 0,1,16,false,0,complain_overflow_bitfield,0,"R_SPARC_16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_32, 0,2,32,false,0,complain_overflow_bitfield,0,"R_SPARC_32", false,0,0xffffffff,true),
+ HOWTO(R_SPARC_DISP8, 0,0, 8,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP8", false,0,0x000000ff,true),
+ HOWTO(R_SPARC_DISP16, 0,1,16,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP16", false,0,0x0000ffff,true),
+ HOWTO(R_SPARC_DISP32, 0,2,32,true, 0,complain_overflow_signed, 0,"R_SPARC_DISP32", false,0,0x00ffffff,true),
+ HOWTO(R_SPARC_WDISP30, 2,2,30,true, 0,complain_overflow_signed, 0,"R_SPARC_WDISP30", false,0,0x3fffffff,true),
+ HOWTO(R_SPARC_WDISP22, 2,2,22,true, 0,complain_overflow_signed, 0,"R_SPARC_WDISP22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_HI22, 10,2,22,false,0,complain_overflow_dont, 0,"R_SPARC_HI22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_22, 0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_13, 0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_LO10, 0,2,10,false,0,complain_overflow_dont, 0,"R_SPARC_LO10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT10, 0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_GOT13, 0,2,13,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT13", false,0,0x00001fff,true),
+ HOWTO(R_SPARC_GOT22, 10,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_GOT22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_PC10, 0,2,10,false,0,complain_overflow_bitfield,0,"R_SPARC_PC10", false,0,0x000003ff,true),
+ HOWTO(R_SPARC_PC22, 0,2,22,false,0,complain_overflow_bitfield,0,"R_SPARC_PC22", false,0,0x003fffff,true),
+ HOWTO(R_SPARC_WPLT30, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_WPLT30", false,0,0x00000000,true),
+ HOWTO(R_SPARC_COPY, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_COPY", false,0,0x00000000,true),
+ HOWTO(R_SPARC_GLOB_DAT,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_GLOB_DAT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_JMP_SLOT,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_JMP_SLOT",false,0,0x00000000,true),
+ HOWTO(R_SPARC_RELATIVE,0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_RELATIVE",false,0,0x00000000,true),
+ HOWTO(R_SPARC_UA32, 0,0,00,false,0,complain_overflow_dont, 0,"R_SPARC_UA32", false,0,0x00000000,true),
+};
+
+/* Read a NetWare sparc reloc. */
+
+struct nlm32_sparc_reloc_ext {
+ unsigned char offset[4];
+ unsigned char addend[4];
+ unsigned char type[1];
+ unsigned char pad1[3];
+};
+
+static boolean
+nlm_sparc_read_reloc (abfd, sym, secp, rel)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+ asection **secp;
+ arelent *rel;
+{
+ bfd_vma val, addend;
+ unsigned int index;
+ unsigned int type;
+ struct nlm32_sparc_reloc_ext tmp_reloc;
+ asection *code_sec, *data_sec;
+
+ if (bfd_read (&tmp_reloc, 12, 1, abfd) != 12)
+ return false;
+
+ code_sec = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ data_sec = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+
+ *secp = code_sec;
+
+ val = bfd_get_32 (abfd, tmp_reloc.offset);
+ addend = bfd_get_32 (abfd, tmp_reloc.addend);
+ type = bfd_get_8 (abfd, tmp_reloc.type);
+
+ rel->address = val;
+ rel->addend = addend;
+ rel->howto = NULL;
+
+ for (index = 0;
+ index < sizeof(nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
+ index++)
+ if (nlm32_sparc_howto_table[index].type == type) {
+ rel->howto = &nlm32_sparc_howto_table[index];
+ break;
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "%s: address = %08lx, addend = %08lx, type = %d, howto = %08lx\n",
+ __FUNCTION__, rel->address, rel->addend, type, rel->howto);
+#endif
+ return true;
+
+}
+
+/* Write a NetWare sparc reloc. */
+
+static boolean
+nlm_sparc_write_reloc (abfd, sec, rel)
+ bfd *abfd;
+ asection *sec;
+ arelent *rel;
+{
+ bfd_vma val;
+ struct nlm32_sparc_reloc_ext tmp_reloc;
+ unsigned int index;
+ int type = -1;
+ reloc_howto_type *tmp;
+
+
+ for (index = 0;
+ index < sizeof (nlm32_sparc_howto_table) / sizeof(reloc_howto_type);
+ index++) {
+ tmp = &nlm32_sparc_howto_table[index];
+
+ if (tmp->rightshift == rel->howto->rightshift
+ && tmp->size == rel->howto->size
+ && tmp->bitsize == rel->howto->bitsize
+ && tmp->pc_relative == rel->howto->pc_relative
+ && tmp->bitpos == rel->howto->bitpos
+ && tmp->src_mask == rel->howto->src_mask
+ && tmp->dst_mask == rel->howto->dst_mask) {
+ type = tmp->type;
+ break;
+ }
+ }
+ if (type == -1)
+ abort();
+
+ /*
+ * Netware wants a list of relocs for each address.
+ * Format is:
+ * long offset
+ * long addend
+ * char type
+ * That should be it.
+ */
+
+ /* The value we write out is the offset into the appropriate
+ segment. This offset is the section vma, adjusted by the vma of
+ the lowest section in that segment, plus the address of the
+ relocation. */
+#if 0
+ val = bfd_get_section_vma (abfd, (*rel->sym_ptr_ptr)->section) + rel->address;
+#else
+ val = bfd_get_section_vma (abfd, sec) + rel->address;
+#endif
+
+#ifdef DEBUG
+ fprintf (stderr, "%s: val = %08lx, addend = %08lx, type = %d\n",
+ __FUNCTION__, val, rel->addend, rel->howto->type);
+#endif
+ bfd_put_32 (abfd, val, tmp_reloc.offset);
+ bfd_put_32 (abfd, rel->addend, tmp_reloc.addend);
+ bfd_put_8 (abfd, (short)(rel->howto->type), tmp_reloc.type);
+
+ if (bfd_write (&tmp_reloc, 12, 1, abfd) != 12)
+ return false;
+
+ return true;
+}
+
+/* Mangle relocs for SPARC NetWare. We can just use the standard
+ SPARC relocs. */
+
+static boolean
+nlm_sparc_mangle_relocs (abfd, sec, data, offset, count)
+ bfd *abfd;
+ asection *sec;
+ PTR data;
+ bfd_vma offset;
+ bfd_size_type count;
+{
+ return true;
+}
+
+/* Read a NetWare sparc import record */
+static boolean
+nlm_sparc_read_import (abfd, sym)
+ bfd *abfd;
+ nlmNAME(symbol_type) *sym;
+{
+ struct nlm_relent *nlm_relocs; /* relocation records for symbol */
+ bfd_size_type rcount; /* number of relocs */
+ bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* temporary 32-bit value */
+ unsigned char symlength; /* length of symbol name */
+ char *name;
+
+ /*
+ * First, read in the number of relocation
+ * entries for this symbol
+ */
+ if (bfd_read ((PTR) temp, 4, 1, abfd) != 4)
+ return false;
+
+ rcount = bfd_get_32 (abfd, temp);
+
+ /*
+ * Next, read in the length of the symbol
+ */
+
+ if (bfd_read ((PTR) &symlength, sizeof (symlength), 1, abfd)
+ != sizeof (symlength))
+ return false;
+ sym -> symbol.the_bfd = abfd;
+ name = bfd_alloc (abfd, symlength + 1);
+ if (name == NULL)
+ return false;
+
+ /*
+ * Then read in the symbol
+ */
+
+ if (bfd_read (name, symlength, 1, abfd) != symlength)
+ return false;
+ name[symlength] = '\0';
+ sym -> symbol.name = name;
+ sym -> symbol.flags = 0;
+ sym -> symbol.value = 0;
+ sym -> symbol.section = bfd_und_section_ptr;
+
+ /*
+ * Next, start reading in the relocs.
+ */
+
+ nlm_relocs = ((struct nlm_relent *)
+ bfd_alloc (abfd, rcount * sizeof (struct nlm_relent)));
+ if (!nlm_relocs)
+ return false;
+ sym -> relocs = nlm_relocs;
+ sym -> rcnt = 0;
+ while (sym -> rcnt < rcount)
+ {
+ asection *section;
+
+ if (nlm_sparc_read_reloc (abfd, sym, &section,
+ &nlm_relocs -> reloc)
+ == false)
+ return false;
+ nlm_relocs -> section = section;
+ nlm_relocs++;
+ sym -> rcnt++;
+ }
+ return true;
+}
+
+static boolean
+nlm_sparc_write_import (abfd, sec, rel)
+ bfd *abfd;
+ asection *sec;
+ arelent *rel;
+{
+ char temp[4];
+ asection *code, *data, *bss, *symsec;
+ bfd_vma base;
+
+ code = bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ data = bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ bss = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
+ symsec = (*rel->sym_ptr_ptr)->section;
+
+ if (symsec == code) {
+ base = 0;
+ } else if (symsec == data) {
+ base = bfd_section_size (abfd, code);
+ } else if (symsec == bss) {
+ base = bfd_section_size (abfd, code) + bfd_section_size (abfd, data);
+ } else
+ base = 0;
+
+#ifdef DEBUG
+ fprintf (stderr, "%s: <%x, 1>\n\t",
+ __FUNCTION__, base + (*rel->sym_ptr_ptr)->value);
+#endif
+ bfd_put_32 (abfd, base + (*rel->sym_ptr_ptr)->value, temp);
+ if (bfd_write ((PTR)temp, 4, 1, abfd) != 4)
+ return false;
+ bfd_put_32 (abfd, 1, temp);
+ if (bfd_write ((PTR)temp, 4, 1, abfd) != 4)
+ return false;
+ if (nlm_sparc_write_reloc (abfd, sec, rel) == false)
+ return false;
+ return true;
+}
+
+/* Write out an external reference. */
+
+static boolean
+nlm_sparc_write_external (abfd, count, sym, relocs)
+ bfd *abfd;
+ bfd_size_type count;
+ asymbol *sym;
+ struct reloc_and_sec *relocs;
+{
+ unsigned int i;
+ bfd_byte len;
+ unsigned char temp[NLM_TARGET_LONG_SIZE];
+
+ bfd_put_32 (abfd, count, temp);
+ if (bfd_write (temp, sizeof(temp), 1, abfd) != sizeof (temp))
+ return false;
+
+ len = strlen (sym->name);
+ if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd) != sizeof(bfd_byte))
+ || bfd_write (sym->name, len, 1, abfd) != len)
+ return false;
+
+ for (i = 0; i < count; i++)
+ {
+ if (nlm_sparc_write_reloc (abfd, relocs[i].sec,
+ relocs[i].rel) == false)
+ return false;
+ }
+
+ return true;
+}
+
+static boolean
+nlm_sparc_write_export (abfd, sym, value)
+ bfd *abfd;
+ asymbol *sym;
+ bfd_vma value;
+{
+ bfd_byte len;
+ bfd_byte temp[4];
+
+#ifdef DEBUG
+ fprintf (stderr, "%s: <%x, %d, %s>\n",
+ __FUNCTION__, value, strlen (sym->name), sym->name);
+#endif
+ bfd_put_32 (abfd, value, temp);
+ len = strlen (sym->name);
+
+ if (bfd_write (temp, 4, 1, abfd) != 4
+ || bfd_write (&len, 1, 1, abfd) != 1
+ || bfd_write (sym->name, len, 1, abfd) != len)
+ return false;
+
+ return true;
+}
+
+#undef nlm_swap_fixed_header_in
+#undef nlm_swap_fixed_header_out
+
+#include "nlmswap.h"
+
+static const struct nlm_backend_data nlm32_sparc_backend =
+{
+ "NetWare SPARC Module \032",
+ sizeof (Nlm32_sparc_External_Fixed_Header),
+ 0, /* optional_prefix_size */
+ bfd_arch_sparc,
+ 0,
+ false,
+ 0, /* backend_object_p */
+ 0, /* write_prefix_func */
+ nlm_sparc_read_reloc,
+ nlm_sparc_mangle_relocs,
+ nlm_sparc_read_import,
+ nlm_sparc_write_import,
+ 0, /* set_public_section */
+ 0, /* get_public_offset */
+ nlm_swap_fixed_header_in,
+ nlm_swap_fixed_header_out,
+ nlm_sparc_write_external,
+ nlm_sparc_write_export
+};
+
+#define TARGET_BIG_NAME "nlm32-sparc"
+#define TARGET_BIG_SYM nlmNAME(sparc_vec)
+#define TARGET_BACKEND_DATA &nlm32_sparc_backend
+
+#include "nlm-target.h"
diff --git a/contrib/gdb/bfd/nlm32.c b/contrib/gdb/bfd/nlm32.c
new file mode 100644
index 0000000..4730e4f
--- /dev/null
+++ b/contrib/gdb/bfd/nlm32.c
@@ -0,0 +1,21 @@
+/* NLM (NetWare Loadable Module) 32-bit executable support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define ARCH_SIZE 32
+#include "nlmcode.h"
diff --git a/contrib/gdb/bfd/nlm64.c b/contrib/gdb/bfd/nlm64.c
new file mode 100644
index 0000000..5dcd96a
--- /dev/null
+++ b/contrib/gdb/bfd/nlm64.c
@@ -0,0 +1,21 @@
+/* NLM (NetWare Loadable Module) 64-bit executable support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define ARCH_SIZE 64
+#include "nlmcode.h"
diff --git a/contrib/gdb/bfd/nlmcode.h b/contrib/gdb/bfd/nlmcode.h
new file mode 100644
index 0000000..7f828b4
--- /dev/null
+++ b/contrib/gdb/bfd/nlmcode.h
@@ -0,0 +1,2057 @@
+/* NLM (NetWare Loadable Module) executable support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, using ELF support as the
+ template.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <string.h> /* For strrchr and friends */
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libnlm.h"
+
+/* The functions in this file do not use the names they appear to use.
+ This file is actually compiled multiple times, once for each size
+ of NLM target we are using. At each size we use a different name,
+ constructed by the macro nlmNAME. For example, the function which
+ is named nlm_symbol_type below is actually named nlm32_symbol_type
+ in the final executable. */
+
+#define Nlm_External_Fixed_Header NlmNAME(External_Fixed_Header)
+#define Nlm_External_Version_Header NlmNAME(External_Version_Header)
+#define Nlm_External_Copyright_Header NlmNAME(External_Copyright_Header)
+#define Nlm_External_Extended_Header NlmNAME(External_Extended_Header)
+#define Nlm_External_Custom_Header NlmNAME(External_Custom_Header)
+#define Nlm_External_Cygnus_Ext_Header NlmNAME(External_Cygnus_Ext_Header)
+
+#define nlm_symbol_type nlmNAME(symbol_type)
+#define nlm_get_symtab_upper_bound nlmNAME(get_symtab_upper_bound)
+#define nlm_get_symtab nlmNAME(get_symtab)
+#define nlm_make_empty_symbol nlmNAME(make_empty_symbol)
+#define nlm_print_symbol nlmNAME(print_symbol)
+#define nlm_get_symbol_info nlmNAME(get_symbol_info)
+#define nlm_get_reloc_upper_bound nlmNAME(get_reloc_upper_bound)
+#define nlm_canonicalize_reloc nlmNAME(canonicalize_reloc)
+#define nlm_object_p nlmNAME(object_p)
+#define nlm_set_section_contents nlmNAME(set_section_contents)
+#define nlm_write_object_contents nlmNAME(write_object_contents)
+
+#define nlm_swap_fixed_header_in(abfd,src,dst) \
+ (nlm_swap_fixed_header_in_func(abfd))(abfd,src,dst)
+#define nlm_swap_fixed_header_out(abfd,src,dst) \
+ (nlm_swap_fixed_header_out_func(abfd))(abfd,src,dst)
+
+/* Forward declarations of static functions */
+
+static boolean add_bfd_section
+ PARAMS ((bfd *, char *, file_ptr, bfd_size_type, flagword));
+static boolean nlm_swap_variable_header_in
+ PARAMS ((bfd *));
+static boolean nlm_swap_variable_header_out
+ PARAMS ((bfd *));
+static boolean find_nonzero
+ PARAMS ((PTR, size_t));
+static boolean nlm_swap_auxiliary_headers_in
+ PARAMS ((bfd *));
+static boolean nlm_swap_auxiliary_headers_out
+ PARAMS ((bfd *));
+static boolean nlm_slurp_symbol_table
+ PARAMS ((bfd *));
+static boolean nlm_slurp_reloc_fixups
+ PARAMS ((bfd *));
+static boolean nlm_compute_section_file_positions
+ PARAMS ((bfd *));
+static int nlm_external_reloc_compare
+ PARAMS ((const void *, const void *));
+
+/* Should perhaps use put_offset, put_word, etc. For now, the two versions
+ can be handled by explicitly specifying 32 bits or "the long type". */
+#if ARCH_SIZE == 64
+#define put_word bfd_h_put_64
+#define get_word bfd_h_get_64
+#endif
+#if ARCH_SIZE == 32
+#define put_word bfd_h_put_32
+#define get_word bfd_h_get_32
+#endif
+
+const bfd_target *
+nlm_object_p (abfd)
+ bfd *abfd;
+{
+ struct nlm_obj_tdata *preserved_tdata = nlm_tdata (abfd);
+ boolean (*backend_object_p) PARAMS ((bfd *));
+ PTR x_fxdhdr = NULL;
+ Nlm_Internal_Fixed_Header *i_fxdhdrp;
+ struct nlm_obj_tdata *new_tdata = NULL;
+ const char *signature;
+ enum bfd_architecture arch;
+
+ /* Some NLM formats have a prefix before the standard NLM fixed
+ header. */
+ backend_object_p = nlm_backend_object_p_func (abfd);
+ if (backend_object_p)
+ {
+ if (!(*backend_object_p) (abfd))
+ goto got_wrong_format_error;
+ }
+
+ /* Read in the fixed length portion of the NLM header in external format. */
+
+ x_fxdhdr = (PTR) bfd_malloc ((size_t) nlm_fixed_header_size (abfd));
+ if (x_fxdhdr == NULL)
+ goto got_no_match;
+
+ if (bfd_read ((PTR) x_fxdhdr, nlm_fixed_header_size (abfd), 1, abfd) !=
+ nlm_fixed_header_size (abfd))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ goto got_wrong_format_error;
+ else
+ goto got_no_match;
+ }
+
+ /* Allocate an instance of the nlm_obj_tdata structure and hook it up to
+ the tdata pointer in the bfd. */
+
+ new_tdata = ((struct nlm_obj_tdata *)
+ bfd_zalloc (abfd, sizeof (struct nlm_obj_tdata)));
+ if (new_tdata == NULL)
+ goto got_no_match;
+
+ nlm_tdata (abfd) = new_tdata;
+
+ i_fxdhdrp = nlm_fixed_header (abfd);
+ nlm_swap_fixed_header_in (abfd, x_fxdhdr, i_fxdhdrp);
+ free (x_fxdhdr);
+ x_fxdhdr = NULL;
+
+ /* Check to see if we have an NLM file for this backend by matching
+ the NLM signature. */
+
+ signature = nlm_signature (abfd);
+ if (signature != NULL
+ && *signature != '\0'
+ && strncmp ((char *) i_fxdhdrp->signature, signature,
+ NLM_SIGNATURE_SIZE) != 0)
+ goto got_wrong_format_error;
+
+ /* There's no supported way to discover the endianess of an NLM, so test for
+ a sane version number after doing byte swapping appropriate for this
+ XVEC. (Hack alert!) */
+
+ if (i_fxdhdrp->version > 0xFFFF)
+ goto got_wrong_format_error;
+
+ /* There's no supported way to check for 32 bit versus 64 bit addresses,
+ so ignore this distinction for now. (FIXME) */
+
+ /* Swap in the rest of the required header. */
+ if (!nlm_swap_variable_header_in (abfd))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ goto got_wrong_format_error;
+ else
+ goto got_no_match;
+ }
+
+ /* Add the sections supplied by all NLM's, and then read in the
+ auxiliary headers. Reading the auxiliary headers may create
+ additional sections described in the cygnus_ext header.
+ From this point on we assume that we have an NLM, and do not
+ treat errors as indicating the wrong format. */
+
+ if (!add_bfd_section (abfd, NLM_CODE_NAME,
+ i_fxdhdrp->codeImageOffset,
+ i_fxdhdrp->codeImageSize,
+ (SEC_CODE | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_RELOC))
+ || !add_bfd_section (abfd, NLM_INITIALIZED_DATA_NAME,
+ i_fxdhdrp->dataImageOffset,
+ i_fxdhdrp->dataImageSize,
+ (SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS
+ | SEC_RELOC))
+ || !add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
+ (file_ptr) 0,
+ i_fxdhdrp->uninitializedDataSize,
+ SEC_ALLOC))
+ goto got_no_match;
+
+ if (!nlm_swap_auxiliary_headers_in (abfd))
+ goto got_no_match;
+
+ if (nlm_fixed_header (abfd)->numberOfRelocationFixups != 0
+ || nlm_fixed_header (abfd)->numberOfExternalReferences != 0)
+ abfd->flags |= HAS_RELOC;
+ if (nlm_fixed_header (abfd)->numberOfPublics != 0
+ || nlm_fixed_header (abfd)->numberOfDebugRecords != 0
+ || nlm_fixed_header (abfd)->numberOfExternalReferences != 0)
+ abfd->flags |= HAS_SYMS;
+
+ arch = nlm_architecture (abfd);
+ if (arch != bfd_arch_unknown)
+ bfd_default_set_arch_mach (abfd, arch, (unsigned long) 0);
+
+ abfd->flags |= EXEC_P;
+ bfd_get_start_address (abfd) = nlm_fixed_header (abfd)->codeStartOffset;
+
+ return (abfd->xvec);
+
+got_wrong_format_error:
+ bfd_set_error (bfd_error_wrong_format);
+got_no_match:
+ nlm_tdata (abfd) = preserved_tdata;
+ if (new_tdata != NULL)
+ bfd_release (abfd, new_tdata);
+ if (x_fxdhdr != NULL)
+ free (x_fxdhdr);
+ return (NULL);
+}
+
+/* Add a section to the bfd. */
+
+static boolean
+add_bfd_section (abfd, name, offset, size, flags)
+ bfd *abfd;
+ char *name;
+ file_ptr offset;
+ bfd_size_type size;
+ flagword flags;
+{
+ asection *newsect;
+
+ newsect = bfd_make_section (abfd, name);
+ if (newsect == NULL)
+ {
+ return (false);
+ }
+ newsect->vma = 0; /* NLM's are relocatable. */
+ newsect->_raw_size = size;
+ newsect->filepos = offset;
+ newsect->flags = flags;
+ newsect->alignment_power = bfd_log2 (0); /* FIXME */
+ return (true);
+}
+
+/* Read and swap in the variable length header. All the fields must
+ exist in the NLM, and must exist in the order they are read here. */
+
+static boolean
+nlm_swap_variable_header_in (abfd)
+ bfd *abfd;
+{
+ unsigned char temp[NLM_TARGET_LONG_SIZE];
+
+ /* Read the description length and text members. */
+
+ if (bfd_read ((PTR) & nlm_variable_header (abfd)->descriptionLength,
+ sizeof (nlm_variable_header (abfd)->descriptionLength),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->descriptionLength))
+ return (false);
+ if (bfd_read ((PTR) nlm_variable_header (abfd)->descriptionText,
+ nlm_variable_header (abfd)->descriptionLength + 1,
+ 1, abfd) !=
+ (bfd_size_type) nlm_variable_header (abfd)->descriptionLength + 1)
+ return (false);
+
+ /* Read and convert the stackSize field. */
+
+ if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return (false);
+ nlm_variable_header (abfd)->stackSize = get_word (abfd, (bfd_byte *) temp);
+
+ /* Read and convert the reserved field. */
+
+ if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return (false);
+ nlm_variable_header (abfd)->reserved = get_word (abfd, (bfd_byte *) temp);
+
+ /* Read the oldThreadName field. This field is a fixed length string. */
+
+ if (bfd_read ((PTR) nlm_variable_header (abfd)->oldThreadName,
+ sizeof (nlm_variable_header (abfd)->oldThreadName),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->oldThreadName))
+ return (false);
+
+ /* Read the screen name length and text members. */
+
+ if (bfd_read ((PTR) & nlm_variable_header (abfd)->screenNameLength,
+ sizeof (nlm_variable_header (abfd)->screenNameLength),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->screenNameLength))
+ return (false);
+ if (bfd_read ((PTR) nlm_variable_header (abfd)->screenName,
+ nlm_variable_header (abfd)->screenNameLength + 1,
+ 1, abfd) !=
+ (bfd_size_type) nlm_variable_header (abfd)->screenNameLength + 1)
+ return (false);
+
+ /* Read the thread name length and text members. */
+
+ if (bfd_read ((PTR) & nlm_variable_header (abfd)->threadNameLength,
+ sizeof (nlm_variable_header (abfd)->threadNameLength),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->threadNameLength))
+ return (false);
+ if (bfd_read ((PTR) nlm_variable_header (abfd)->threadName,
+ nlm_variable_header (abfd)->threadNameLength + 1,
+ 1, abfd) !=
+ (bfd_size_type) nlm_variable_header (abfd)->threadNameLength + 1)
+ return (false);
+ return (true);
+}
+
+/* Swap and write out the variable length header. All the fields must
+ exist in the NLM, and must exist in this order. */
+
+static boolean
+nlm_swap_variable_header_out (abfd)
+ bfd *abfd;
+{
+ unsigned char temp[NLM_TARGET_LONG_SIZE];
+
+ /* Write the description length and text members. */
+
+ if (bfd_write ((PTR) & nlm_variable_header (abfd)->descriptionLength,
+ sizeof (nlm_variable_header (abfd)->descriptionLength),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->descriptionLength))
+ return (false);
+ if (bfd_write ((PTR) nlm_variable_header (abfd)->descriptionText,
+ nlm_variable_header (abfd)->descriptionLength + 1,
+ 1, abfd) !=
+ (bfd_size_type) nlm_variable_header (abfd)->descriptionLength + 1)
+ return (false);
+
+ /* Convert and write the stackSize field. */
+
+ put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->stackSize,
+ (bfd_byte *) temp);
+ if (bfd_write ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return (false);
+
+ /* Convert and write the reserved field. */
+
+ put_word (abfd, (bfd_vma) nlm_variable_header (abfd)->reserved,
+ (bfd_byte *) temp);
+ if (bfd_write ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return (false);
+
+ /* Write the oldThreadName field. This field is a fixed length string. */
+
+ if (bfd_write ((PTR) nlm_variable_header (abfd)->oldThreadName,
+ sizeof (nlm_variable_header (abfd)->oldThreadName),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->oldThreadName))
+ return (false);
+
+ /* Write the screen name length and text members. */
+
+ if (bfd_write ((PTR) & nlm_variable_header (abfd)->screenNameLength,
+ sizeof (nlm_variable_header (abfd)->screenNameLength),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->screenNameLength))
+ return (false);
+ if (bfd_write ((PTR) nlm_variable_header (abfd)->screenName,
+ nlm_variable_header (abfd)->screenNameLength + 1,
+ 1, abfd) !=
+ (bfd_size_type) nlm_variable_header (abfd)->screenNameLength + 1)
+ return (false);
+
+ /* Write the thread name length and text members. */
+
+ if (bfd_write ((PTR) & nlm_variable_header (abfd)->threadNameLength,
+ sizeof (nlm_variable_header (abfd)->threadNameLength),
+ 1, abfd) !=
+ sizeof (nlm_variable_header (abfd)->threadNameLength))
+ return (false);
+ if (bfd_write ((PTR) nlm_variable_header (abfd)->threadName,
+ nlm_variable_header (abfd)->threadNameLength + 1,
+ 1, abfd) !=
+ (bfd_size_type) nlm_variable_header (abfd)->threadNameLength + 1)
+ return (false);
+ return (true);
+}
+
+/* Read and swap in the contents of all the auxiliary headers. Because of
+ the braindead design, we have to do strcmps on strings of indeterminate
+ length to figure out what each auxiliary header is. Even worse, we have
+ no way of knowing how many auxiliary headers there are or where the end
+ of the auxiliary headers are, except by finding something that doesn't
+ look like a known auxiliary header. This means that the first new type
+ of auxiliary header added will break all existing tools that don't
+ recognize it. */
+
+static boolean
+nlm_swap_auxiliary_headers_in (abfd)
+ bfd *abfd;
+{
+ char tempstr[16];
+ long position;
+
+ for (;;)
+ {
+ position = bfd_tell (abfd);
+ if (bfd_read ((PTR) tempstr, sizeof (tempstr), 1, abfd) !=
+ sizeof (tempstr))
+ return (false);
+ if (bfd_seek (abfd, position, SEEK_SET) == -1)
+ return (false);
+ if (strncmp (tempstr, "VeRsIoN#", 8) == 0)
+ {
+ Nlm_External_Version_Header thdr;
+ if (bfd_read ((PTR) & thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+ return (false);
+ memcpy (nlm_version_header (abfd)->stamp, thdr.stamp,
+ sizeof (thdr.stamp));
+ nlm_version_header (abfd)->majorVersion =
+ get_word (abfd, (bfd_byte *) thdr.majorVersion);
+ nlm_version_header (abfd)->minorVersion =
+ get_word (abfd, (bfd_byte *) thdr.minorVersion);
+ nlm_version_header (abfd)->revision =
+ get_word (abfd, (bfd_byte *) thdr.revision);
+ nlm_version_header (abfd)->year =
+ get_word (abfd, (bfd_byte *) thdr.year);
+ nlm_version_header (abfd)->month =
+ get_word (abfd, (bfd_byte *) thdr.month);
+ nlm_version_header (abfd)->day =
+ get_word (abfd, (bfd_byte *) thdr.day);
+ }
+ else if (strncmp (tempstr, "MeSsAgEs", 8) == 0)
+ {
+ Nlm_External_Extended_Header thdr;
+ if (bfd_read ((PTR) & thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+ return (false);
+ memcpy (nlm_extended_header (abfd)->stamp, thdr.stamp,
+ sizeof (thdr.stamp));
+ nlm_extended_header (abfd)->languageID =
+ get_word (abfd, (bfd_byte *) thdr.languageID);
+ nlm_extended_header (abfd)->messageFileOffset =
+ get_word (abfd, (bfd_byte *) thdr.messageFileOffset);
+ nlm_extended_header (abfd)->messageFileLength =
+ get_word (abfd, (bfd_byte *) thdr.messageFileLength);
+ nlm_extended_header (abfd)->messageCount =
+ get_word (abfd, (bfd_byte *) thdr.messageCount);
+ nlm_extended_header (abfd)->helpFileOffset =
+ get_word (abfd, (bfd_byte *) thdr.helpFileOffset);
+ nlm_extended_header (abfd)->helpFileLength =
+ get_word (abfd, (bfd_byte *) thdr.helpFileLength);
+ nlm_extended_header (abfd)->RPCDataOffset =
+ get_word (abfd, (bfd_byte *) thdr.RPCDataOffset);
+ nlm_extended_header (abfd)->RPCDataLength =
+ get_word (abfd, (bfd_byte *) thdr.RPCDataLength);
+ nlm_extended_header (abfd)->sharedCodeOffset =
+ get_word (abfd, (bfd_byte *) thdr.sharedCodeOffset);
+ nlm_extended_header (abfd)->sharedCodeLength =
+ get_word (abfd, (bfd_byte *) thdr.sharedCodeLength);
+ nlm_extended_header (abfd)->sharedDataOffset =
+ get_word (abfd, (bfd_byte *) thdr.sharedDataOffset);
+ nlm_extended_header (abfd)->sharedDataLength =
+ get_word (abfd, (bfd_byte *) thdr.sharedDataLength);
+ nlm_extended_header (abfd)->sharedRelocationFixupOffset =
+ get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupOffset);
+ nlm_extended_header (abfd)->sharedRelocationFixupCount =
+ get_word (abfd, (bfd_byte *) thdr.sharedRelocationFixupCount);
+ nlm_extended_header (abfd)->sharedExternalReferenceOffset =
+ get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceOffset);
+ nlm_extended_header (abfd)->sharedExternalReferenceCount =
+ get_word (abfd, (bfd_byte *) thdr.sharedExternalReferenceCount);
+ nlm_extended_header (abfd)->sharedPublicsOffset =
+ get_word (abfd, (bfd_byte *) thdr.sharedPublicsOffset);
+ nlm_extended_header (abfd)->sharedPublicsCount =
+ get_word (abfd, (bfd_byte *) thdr.sharedPublicsCount);
+ nlm_extended_header (abfd)->sharedDebugRecordOffset =
+ get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordOffset);
+ nlm_extended_header (abfd)->sharedDebugRecordCount =
+ get_word (abfd, (bfd_byte *) thdr.sharedDebugRecordCount);
+ nlm_extended_header (abfd)->SharedInitializationOffset =
+ get_word (abfd, (bfd_byte *) thdr.sharedInitializationOffset);
+ nlm_extended_header (abfd)->SharedExitProcedureOffset =
+ get_word (abfd, (bfd_byte *) thdr.SharedExitProcedureOffset);
+ nlm_extended_header (abfd)->productID =
+ get_word (abfd, (bfd_byte *) thdr.productID);
+ nlm_extended_header (abfd)->reserved0 =
+ get_word (abfd, (bfd_byte *) thdr.reserved0);
+ nlm_extended_header (abfd)->reserved1 =
+ get_word (abfd, (bfd_byte *) thdr.reserved1);
+ nlm_extended_header (abfd)->reserved2 =
+ get_word (abfd, (bfd_byte *) thdr.reserved2);
+ nlm_extended_header (abfd)->reserved3 =
+ get_word (abfd, (bfd_byte *) thdr.reserved3);
+ nlm_extended_header (abfd)->reserved4 =
+ get_word (abfd, (bfd_byte *) thdr.reserved4);
+ nlm_extended_header (abfd)->reserved5 =
+ get_word (abfd, (bfd_byte *) thdr.reserved5);
+ }
+ else if (strncmp (tempstr, "CoPyRiGhT=", 10) == 0)
+ {
+ if (bfd_read ((PTR) nlm_copyright_header (abfd)->stamp,
+ sizeof (nlm_copyright_header (abfd)->stamp),
+ 1, abfd)
+ != sizeof (nlm_copyright_header (abfd)->stamp))
+ return (false);
+ if (bfd_read ((PTR) & (nlm_copyright_header (abfd)
+ ->copyrightMessageLength),
+ 1, 1, abfd) != 1)
+ return (false);
+ /* The copyright message is a variable length string. */
+ if (bfd_read ((PTR) nlm_copyright_header (abfd)->copyrightMessage,
+ nlm_copyright_header (abfd)->copyrightMessageLength + 1,
+ 1, abfd) !=
+ ((bfd_size_type)
+ nlm_copyright_header (abfd)->copyrightMessageLength + 1))
+ return (false);
+ }
+ else if (strncmp (tempstr, "CuStHeAd", 8) == 0)
+ {
+ Nlm_External_Custom_Header thdr;
+ bfd_size_type hdrLength;
+ file_ptr dataOffset;
+ bfd_size_type dataLength;
+ char dataStamp[8];
+ PTR hdr;
+
+ /* Read the stamp ("CuStHeAd"). */
+ if (bfd_read ((PTR) thdr.stamp, 1, sizeof (thdr.stamp), abfd)
+ != sizeof (thdr.stamp))
+ return false;
+ /* Read the length of this custom header. */
+ if (bfd_read ((PTR) thdr.length, 1, sizeof (thdr.length), abfd)
+ != sizeof (thdr.length))
+ return false;
+ hdrLength = get_word (abfd, (bfd_byte *) thdr.length);
+ /* Read further fields if we have them. */
+ if (hdrLength < NLM_TARGET_LONG_SIZE)
+ dataOffset = 0;
+ else
+ {
+ if (bfd_read ((PTR) thdr.dataOffset, 1,
+ sizeof (thdr.dataOffset), abfd)
+ != sizeof (thdr.dataOffset))
+ return false;
+ dataOffset = get_word (abfd, (bfd_byte *) thdr.dataOffset);
+ }
+ if (hdrLength < 2 * NLM_TARGET_LONG_SIZE)
+ dataLength = 0;
+ else
+ {
+ if (bfd_read ((PTR) thdr.dataLength, 1,
+ sizeof (thdr.dataLength), abfd)
+ != sizeof (thdr.dataLength))
+ return false;
+ dataLength = get_word (abfd, (bfd_byte *) thdr.dataLength);
+ }
+ if (hdrLength < 2 * NLM_TARGET_LONG_SIZE + 8)
+ memset (dataStamp, 0, sizeof (dataStamp));
+ else
+ {
+ if (bfd_read ((PTR) dataStamp, 1, sizeof (dataStamp), abfd)
+ != sizeof (dataStamp))
+ return false;
+ }
+
+ /* Read the rest of the header, if any. */
+ if (hdrLength <= 2 * NLM_TARGET_LONG_SIZE + 8)
+ {
+ hdr = NULL;
+ hdrLength = 0;
+ }
+ else
+ {
+ hdrLength -= 2 * NLM_TARGET_LONG_SIZE + 8;
+ hdr = bfd_alloc (abfd, hdrLength);
+ if (hdr == NULL)
+ return false;
+ if (bfd_read (hdr, 1, hdrLength, abfd) != hdrLength)
+ return false;
+ }
+
+ /* If we have found a Cygnus header, process it. Otherwise,
+ just save the associated data without trying to interpret
+ it. */
+ if (strncmp (dataStamp, "CyGnUsEx", 8) == 0)
+ {
+ file_ptr pos;
+ bfd_byte *contents;
+ bfd_byte *p, *pend;
+
+ BFD_ASSERT (hdrLength == 0 && hdr == NULL);
+
+ pos = bfd_tell (abfd);
+ if (bfd_seek (abfd, dataOffset, SEEK_SET) != 0)
+ return false;
+ contents = (bfd_byte *) bfd_alloc (abfd, dataLength);
+ if (contents == NULL)
+ return false;
+ if (bfd_read (contents, 1, dataLength, abfd) != dataLength)
+ return false;
+ if (bfd_seek (abfd, pos, SEEK_SET) != 0)
+ return false;
+
+ memcpy (nlm_cygnus_ext_header (abfd), "CyGnUsEx", 8);
+ nlm_cygnus_ext_header (abfd)->offset = dataOffset;
+ nlm_cygnus_ext_header (abfd)->length = dataLength;
+
+ /* This data this header points to provides a list of
+ the sections which were in the original object file
+ which was converted to become an NLM. We locate
+ those sections and add them to the BFD. Note that
+ this is likely to create a second .text, .data and
+ .bss section; retrieving the sections by name will
+ get the actual NLM sections, which is what we want to
+ happen. The sections from the original file, which
+ may be subsets of the NLM section, can only be found
+ using bfd_map_over_sections. */
+ p = contents;
+ pend = p + dataLength;
+ while (p < pend)
+ {
+ char *name;
+ size_t l;
+ file_ptr filepos;
+ bfd_size_type size;
+ asection *newsec;
+
+ /* The format of this information is
+ null terminated section name
+ zeroes to adjust to 4 byte boundary
+ 4 byte section data file pointer
+ 4 byte section size
+ */
+
+ name = (char *) p;
+ l = strlen (name) + 1;
+ l = (l + 3) &~ 3;
+ p += l;
+ filepos = bfd_h_get_32 (abfd, p);
+ p += 4;
+ size = bfd_h_get_32 (abfd, p);
+ p += 4;
+
+ newsec = bfd_make_section_anyway (abfd, name);
+ if (newsec == (asection *) NULL)
+ return false;
+ newsec->_raw_size = size;
+ if (filepos != 0)
+ {
+ newsec->filepos = filepos;
+ newsec->flags |= SEC_HAS_CONTENTS;
+ }
+ }
+ }
+ else
+ {
+ memcpy (nlm_custom_header (abfd)->stamp, thdr.stamp,
+ sizeof (thdr.stamp));
+ nlm_custom_header (abfd)->hdrLength = hdrLength;
+ nlm_custom_header (abfd)->dataOffset = dataOffset;
+ nlm_custom_header (abfd)->dataLength = dataLength;
+ memcpy (nlm_custom_header (abfd)->dataStamp, dataStamp,
+ sizeof (dataStamp));
+ nlm_custom_header (abfd)->hdr = hdr;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+ return (true);
+}
+
+/* Return whether there is a non-zero byte in a memory block. */
+
+static boolean
+find_nonzero (buf, size)
+ PTR buf;
+ size_t size;
+{
+ char *p = (char *) buf;
+
+ while (size-- != 0)
+ if (*p++ != 0)
+ return true;
+ return false;
+}
+
+/* Swap out the contents of the auxiliary headers. We create those
+ auxiliary headers which have been set non-zero. We do not require
+ the caller to set up the stamp fields. */
+
+static boolean
+nlm_swap_auxiliary_headers_out (abfd)
+ bfd *abfd;
+{
+ /* Write out the version header if there is one. */
+ if (find_nonzero ((PTR) nlm_version_header (abfd),
+ sizeof (Nlm_Internal_Version_Header)))
+ {
+ Nlm_External_Version_Header thdr;
+
+ memcpy (thdr.stamp, "VeRsIoN#", 8);
+ put_word (abfd, (bfd_vma) nlm_version_header (abfd)->majorVersion,
+ (bfd_byte *) thdr.majorVersion);
+ put_word (abfd, (bfd_vma) nlm_version_header (abfd)->minorVersion,
+ (bfd_byte *) thdr.minorVersion);
+ put_word (abfd, (bfd_vma) nlm_version_header (abfd)->revision,
+ (bfd_byte *) thdr.revision);
+ put_word (abfd, (bfd_vma) nlm_version_header (abfd)->year,
+ (bfd_byte *) thdr.year);
+ put_word (abfd, (bfd_vma) nlm_version_header (abfd)->month,
+ (bfd_byte *) thdr.month);
+ put_word (abfd, (bfd_vma) nlm_version_header (abfd)->day,
+ (bfd_byte *) thdr.day);
+ if (bfd_write ((PTR) & thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+ return false;
+ }
+
+ /* Write out the extended header if there is one. */
+ if (find_nonzero ((PTR) nlm_extended_header (abfd),
+ sizeof (Nlm_Internal_Extended_Header)))
+ {
+ Nlm_External_Extended_Header thdr;
+
+ memcpy (thdr.stamp, "MeSsAgEs", 8);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->languageID,
+ (bfd_byte *) thdr.languageID);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->messageFileOffset,
+ (bfd_byte *) thdr.messageFileOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->messageFileLength,
+ (bfd_byte *) thdr.messageFileLength);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->messageCount,
+ (bfd_byte *) thdr.messageCount);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->helpFileOffset,
+ (bfd_byte *) thdr.helpFileOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->helpFileLength,
+ (bfd_byte *) thdr.helpFileLength);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->RPCDataOffset,
+ (bfd_byte *) thdr.RPCDataOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->RPCDataLength,
+ (bfd_byte *) thdr.RPCDataLength);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedCodeOffset,
+ (bfd_byte *) thdr.sharedCodeOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedCodeLength,
+ (bfd_byte *) thdr.sharedCodeLength);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedDataOffset,
+ (bfd_byte *) thdr.sharedDataOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedDataLength,
+ (bfd_byte *) thdr.sharedDataLength);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupOffset,
+ (bfd_byte *) thdr.sharedRelocationFixupOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedRelocationFixupCount,
+ (bfd_byte *) thdr.sharedRelocationFixupCount);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceOffset,
+ (bfd_byte *) thdr.sharedExternalReferenceOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedExternalReferenceCount,
+ (bfd_byte *) thdr.sharedExternalReferenceCount);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedPublicsOffset,
+ (bfd_byte *) thdr.sharedPublicsOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedPublicsCount,
+ (bfd_byte *) thdr.sharedPublicsCount);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordOffset,
+ (bfd_byte *) thdr.sharedDebugRecordOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->sharedDebugRecordCount,
+ (bfd_byte *) thdr.sharedDebugRecordCount);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->SharedInitializationOffset,
+ (bfd_byte *) thdr.sharedInitializationOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->SharedExitProcedureOffset,
+ (bfd_byte *) thdr.SharedExitProcedureOffset);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->productID,
+ (bfd_byte *) thdr.productID);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->reserved0,
+ (bfd_byte *) thdr.reserved0);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->reserved1,
+ (bfd_byte *) thdr.reserved1);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->reserved2,
+ (bfd_byte *) thdr.reserved2);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->reserved3,
+ (bfd_byte *) thdr.reserved3);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->reserved4,
+ (bfd_byte *) thdr.reserved4);
+ put_word (abfd,
+ (bfd_vma) nlm_extended_header (abfd)->reserved5,
+ (bfd_byte *) thdr.reserved5);
+ if (bfd_write ((PTR) & thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+ return false;
+ }
+
+
+ /* Write out the copyright header if there is one. */
+ if (find_nonzero ((PTR) nlm_copyright_header (abfd),
+ sizeof (Nlm_Internal_Copyright_Header)))
+ {
+ Nlm_External_Copyright_Header thdr;
+
+ memcpy (thdr.stamp, "CoPyRiGhT=", 10);
+ if (bfd_write ((PTR) thdr.stamp, sizeof (thdr.stamp), 1, abfd)
+ != sizeof (thdr.stamp))
+ return false;
+ thdr.copyrightMessageLength[0] =
+ nlm_copyright_header (abfd)->copyrightMessageLength;
+ if (bfd_write ((PTR) thdr.copyrightMessageLength, 1, 1, abfd) != 1)
+ return false;
+ /* The copyright message is a variable length string. */
+ if (bfd_write ((PTR) nlm_copyright_header (abfd)->copyrightMessage,
+ nlm_copyright_header (abfd)->copyrightMessageLength + 1,
+ 1, abfd) !=
+ ((bfd_size_type)
+ nlm_copyright_header (abfd)->copyrightMessageLength + 1))
+ return false;
+ }
+
+ /* Write out the custom header if there is one. */
+ if (find_nonzero ((PTR) nlm_custom_header (abfd),
+ sizeof (Nlm_Internal_Custom_Header)))
+ {
+ Nlm_External_Custom_Header thdr;
+ boolean ds;
+ bfd_size_type hdrLength;
+
+ ds = find_nonzero ((PTR) nlm_custom_header (abfd)->dataStamp,
+ sizeof (nlm_custom_header (abfd)->dataStamp));
+ memcpy (thdr.stamp, "CuStHeAd", 8);
+ hdrLength = (2 * NLM_TARGET_LONG_SIZE + (ds ? 8 : 0)
+ + nlm_custom_header (abfd)->hdrLength);
+ put_word (abfd, hdrLength, thdr.length);
+ put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataOffset,
+ thdr.dataOffset);
+ put_word (abfd, (bfd_vma) nlm_custom_header (abfd)->dataLength,
+ thdr.dataLength);
+ if (! ds)
+ {
+ BFD_ASSERT (nlm_custom_header (abfd)->hdrLength == 0);
+ if (bfd_write ((PTR) &thdr, 1,
+ sizeof (thdr) - sizeof (thdr.dataStamp), abfd)
+ != sizeof (thdr) - sizeof (thdr.dataStamp))
+ return false;
+ }
+ else
+ {
+ memcpy (thdr.dataStamp, nlm_custom_header (abfd)->dataStamp,
+ sizeof (thdr.dataStamp));
+ if (bfd_write ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+ return false;
+ if (bfd_write (nlm_custom_header (abfd)->hdr, 1,
+ nlm_custom_header (abfd)->hdrLength, abfd)
+ != nlm_custom_header (abfd)->hdrLength)
+ return false;
+ }
+ }
+
+ /* Write out the Cygnus debugging header if there is one. */
+ if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
+ sizeof (Nlm_Internal_Cygnus_Ext_Header)))
+ {
+ Nlm_External_Custom_Header thdr;
+
+ memcpy (thdr.stamp, "CuStHeAd", 8);
+ put_word (abfd, (bfd_vma) 2 * NLM_TARGET_LONG_SIZE + 8,
+ (bfd_byte *) thdr.length);
+ put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->offset,
+ (bfd_byte *) thdr.dataOffset);
+ put_word (abfd, (bfd_vma) nlm_cygnus_ext_header (abfd)->length,
+ (bfd_byte *) thdr.dataLength);
+ memcpy (thdr.dataStamp, "CyGnUsEx", 8);
+ if (bfd_write ((PTR) &thdr, sizeof (thdr), 1, abfd) != sizeof (thdr))
+ return false;
+ }
+
+ return true;
+}
+
+/* We read the NLM's public symbols and use it to generate a bfd symbol
+ table (hey, it's better than nothing) on a one-for-one basis. Thus
+ use the number of public symbols as the number of bfd symbols we will
+ have once we actually get around to reading them in.
+
+ Return the number of bytes required to hold the symtab vector, based on
+ the count plus 1, since we will NULL terminate the vector allocated based
+ on this size. */
+
+long
+nlm_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form */
+ long symcount;
+ long symtab_size = 0;
+
+ i_fxdhdrp = nlm_fixed_header (abfd);
+ symcount = (i_fxdhdrp->numberOfPublics
+ + i_fxdhdrp->numberOfDebugRecords
+ + i_fxdhdrp->numberOfExternalReferences);
+ symtab_size = (symcount + 1) * (sizeof (asymbol));
+ return (symtab_size);
+}
+
+/* Note that bfd_get_symcount is guaranteed to be zero if slurping the
+ symbol table fails. */
+
+long
+nlm_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ nlm_symbol_type *symbase;
+ bfd_size_type counter = 0;
+
+ if (nlm_slurp_symbol_table (abfd) == false)
+ return -1;
+ symbase = nlm_get_symbols (abfd);
+ while (counter < bfd_get_symcount (abfd))
+ {
+ *alocation++ = &symbase->symbol;
+ symbase++;
+ counter++;
+ }
+ *alocation = (asymbol *) NULL;
+ return bfd_get_symcount (abfd);
+}
+
+/* Make an NLM symbol. There is nothing special to do here. */
+
+asymbol *
+nlm_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ nlm_symbol_type *new;
+
+ new = (nlm_symbol_type *) bfd_zalloc (abfd, sizeof (nlm_symbol_type));
+ if (new)
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+/* Get symbol information. */
+
+void
+nlm_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+/* Print symbol information. */
+
+void
+nlm_print_symbol (abfd, afile, symbol, how)
+ bfd *abfd;
+ PTR afile;
+ asymbol *symbol;
+ bfd_print_symbol_type how;
+{
+ FILE *file = (FILE *) afile;
+
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ case bfd_print_symbol_more:
+ if (symbol->name)
+ fprintf (file, "%s", symbol->name);
+ break;
+ case bfd_print_symbol_all:
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+ fprintf (file, " %-5s", symbol->section->name);
+ if (symbol->name)
+ fprintf (file, " %s", symbol->name);
+ break;
+ }
+}
+
+/* Slurp in nlm symbol table.
+
+ In the external (in-file) form, NLM export records are variable length,
+ with the following form:
+
+ 1 byte length of the symbol name (N)
+ N bytes the symbol name
+ 4 bytes the symbol offset from start of it's section
+
+ We also read in the debugging symbols and import records. Import
+ records are treated as undefined symbols. As we read the import
+ records we also read in the associated reloc information, which is
+ attached to the symbol.
+
+ The bfd symbols are copied to SYMPTRS.
+
+ When we return, the bfd symcount is either zero or contains the correct
+ number of symbols.
+*/
+
+static boolean
+nlm_slurp_symbol_table (abfd)
+ bfd *abfd;
+{
+ Nlm_Internal_Fixed_Header *i_fxdhdrp; /* Nlm file header, internal form */
+ bfd_size_type totsymcount; /* Number of NLM symbols */
+ bfd_size_type symcount; /* Counter of NLM symbols */
+ nlm_symbol_type *sym; /* Pointer to current bfd symbol */
+ unsigned char symlength; /* Symbol length read into here */
+ unsigned char symtype; /* Type of debugging symbol */
+ bfd_byte temp[NLM_TARGET_LONG_SIZE]; /* Symbol offsets read into here */
+ boolean (*read_import_func) PARAMS ((bfd *, nlm_symbol_type *));
+ boolean (*set_public_section_func) PARAMS ((bfd *, nlm_symbol_type *));
+
+ if (nlm_get_symbols (abfd) != NULL)
+ return (true);
+
+ /* Read each raw NLM symbol, using the information to create a canonical bfd
+ symbol table entry.
+
+ Note that we allocate the initial bfd canonical symbol buffer based on a
+ one-to-one mapping of the NLM symbols to canonical symbols. We actually
+ use all the NLM symbols, so there will be no space left over at the end.
+ When we have all the symbols, we build the caller's pointer vector. */
+
+ abfd->symcount = 0;
+ i_fxdhdrp = nlm_fixed_header (abfd);
+ totsymcount = (i_fxdhdrp->numberOfPublics
+ + i_fxdhdrp->numberOfDebugRecords
+ + i_fxdhdrp->numberOfExternalReferences);
+ if (totsymcount == 0)
+ {
+ return (true);
+ }
+
+ if (bfd_seek (abfd, i_fxdhdrp->publicsOffset, SEEK_SET) == -1)
+ return (false);
+
+ sym = ((nlm_symbol_type *)
+ bfd_zalloc (abfd, totsymcount * sizeof (nlm_symbol_type)));
+ if (!sym)
+ return false;
+ nlm_set_symbols (abfd, sym);
+
+ /* We use the bfd's symcount directly as the control count, so that early
+ termination of the loop leaves the symcount correct for the symbols that
+ were read. */
+
+ set_public_section_func = nlm_set_public_section_func (abfd);
+ symcount = i_fxdhdrp->numberOfPublics;
+ while (abfd->symcount < symcount)
+ {
+ if (bfd_read ((PTR) & symlength, sizeof (symlength), 1, abfd)
+ != sizeof (symlength))
+ return (false);
+ sym->symbol.the_bfd = abfd;
+ sym->symbol.name = bfd_alloc (abfd, symlength + 1);
+ if (!sym->symbol.name)
+ return false;
+ if (bfd_read ((PTR) sym->symbol.name, symlength, 1, abfd)
+ != symlength)
+ return (false);
+ /* Cast away const. */
+ ((char *) (sym->symbol.name))[symlength] = '\0';
+ if (bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ return (false);
+ sym->symbol.flags = BSF_GLOBAL | BSF_EXPORT;
+ sym->symbol.value = get_word (abfd, temp);
+ if (set_public_section_func)
+ {
+ /* Most backends can use the code below, but unfortunately
+ some use a different scheme. */
+ if ((*set_public_section_func) (abfd, sym) == false)
+ return false;
+ }
+ else
+ {
+ if (sym->symbol.value & NLM_HIBIT)
+ {
+ sym->symbol.value &= ~NLM_HIBIT;
+ sym->symbol.flags |= BSF_FUNCTION;
+ sym->symbol.section =
+ bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ }
+ else
+ {
+ sym->symbol.section =
+ bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ }
+ }
+ sym->rcnt = 0;
+ abfd->symcount++;
+ sym++;
+ }
+
+ /* Read the debugging records. */
+
+ if (i_fxdhdrp->numberOfDebugRecords > 0)
+ {
+ if (bfd_seek (abfd, i_fxdhdrp->debugInfoOffset, SEEK_SET) == -1)
+ return (false);
+
+ symcount += i_fxdhdrp->numberOfDebugRecords;
+ while (abfd->symcount < symcount)
+ {
+ if ((bfd_read ((PTR) & symtype, sizeof (symtype), 1, abfd)
+ != sizeof (symtype))
+ || bfd_read ((PTR) temp, sizeof (temp), 1, abfd) != sizeof (temp)
+ || (bfd_read ((PTR) & symlength, sizeof (symlength), 1, abfd)
+ != sizeof (symlength)))
+ return false;
+ sym->symbol.the_bfd = abfd;
+ sym->symbol.name = bfd_alloc (abfd, symlength + 1);
+ if (!sym->symbol.name)
+ return false;
+ if (bfd_read ((PTR) sym->symbol.name, symlength, 1, abfd)
+ != symlength)
+ return (false);
+ /* Cast away const. */
+ ((char *) (sym->symbol.name))[symlength] = '\0';
+ sym->symbol.flags = BSF_LOCAL;
+ sym->symbol.value = get_word (abfd, temp);
+ if (symtype == 0)
+ {
+ sym->symbol.section =
+ bfd_get_section_by_name (abfd, NLM_INITIALIZED_DATA_NAME);
+ }
+ else if (symtype == 1)
+ {
+ sym->symbol.flags |= BSF_FUNCTION;
+ sym->symbol.section =
+ bfd_get_section_by_name (abfd, NLM_CODE_NAME);
+ }
+ else
+ {
+ sym->symbol.section = bfd_abs_section_ptr;
+ }
+ sym->rcnt = 0;
+ abfd->symcount++;
+ sym++;
+ }
+ }
+
+ /* Read in the import records. We can only do this if we know how
+ to read relocs for this target. */
+
+ read_import_func = nlm_read_import_func (abfd);
+ if (read_import_func != NULL)
+ {
+ if (bfd_seek (abfd, i_fxdhdrp->externalReferencesOffset, SEEK_SET)
+ == -1)
+ return (false);
+
+ symcount += i_fxdhdrp->numberOfExternalReferences;
+ while (abfd->symcount < symcount)
+ {
+ if ((*read_import_func) (abfd, sym) == false)
+ return false;
+ sym++;
+ abfd->symcount++;
+ }
+ }
+
+ return (true);
+}
+
+/* Get the relocs for an NLM file. There are two types of relocs.
+ Imports are relocs against symbols defined in other NLM files. We
+ treat these as relocs against global symbols. Relocation fixups
+ are internal relocs.
+
+ The actual format used to store the relocs is machine specific. */
+
+/* Read in the relocation fixup information. This is stored in
+ nlm_relocation_fixups, an array of arelent structures, and
+ nlm_relocation_fixup_secs, an array of section pointers. The
+ section pointers are needed because the relocs are not sorted by
+ section. */
+
+static boolean
+nlm_slurp_reloc_fixups (abfd)
+ bfd *abfd;
+{
+ boolean (*read_func) PARAMS ((bfd *, nlm_symbol_type *, asection **,
+ arelent *));
+ bfd_size_type count;
+ arelent *rels;
+ asection **secs;
+
+ if (nlm_relocation_fixups (abfd) != NULL)
+ return true;
+ read_func = nlm_read_reloc_func (abfd);
+ if (read_func == NULL)
+ return true;
+
+ if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
+ SEEK_SET) != 0)
+ return false;
+
+ count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
+ rels = (arelent *) bfd_alloc (abfd, count * sizeof (arelent));
+ secs = (asection **) bfd_alloc (abfd, count * sizeof (asection *));
+ if ((rels == NULL || secs == NULL) && count != 0)
+ return false;
+ nlm_relocation_fixups (abfd) = rels;
+ nlm_relocation_fixup_secs (abfd) = secs;
+
+ /* We have to read piece by piece, because we don't know how large
+ the machine specific reloc information is. */
+ while (count-- != 0)
+ {
+ if ((*read_func) (abfd, (nlm_symbol_type *) NULL, secs, rels) == false)
+ {
+ nlm_relocation_fixups (abfd) = NULL;
+ nlm_relocation_fixup_secs (abfd) = NULL;
+ return false;
+ }
+ ++secs;
+ ++rels;
+ }
+
+ return true;
+}
+
+/* Get the number of relocs. This really just returns an upper bound,
+ since it does not attempt to distinguish them based on the section.
+ That will be handled when they are actually read. */
+
+long
+nlm_get_reloc_upper_bound (abfd, sec)
+ bfd *abfd;
+ asection *sec;
+{
+ nlm_symbol_type *syms;
+ bfd_size_type count;
+ unsigned int ret;
+
+ /* If we don't know how to read relocs, just return 0. */
+ if (nlm_read_reloc_func (abfd) == NULL)
+ return -1;
+ /* Make sure we have either the code or the data section. */
+ if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
+ return 0;
+
+ syms = nlm_get_symbols (abfd);
+ if (syms == NULL)
+ {
+ if (nlm_slurp_symbol_table (abfd) == false)
+ return -1;
+ syms = nlm_get_symbols (abfd);
+ }
+
+ ret = nlm_fixed_header (abfd)->numberOfRelocationFixups;
+
+ count = bfd_get_symcount (abfd);
+ while (count-- != 0)
+ {
+ ret += syms->rcnt;
+ ++syms;
+ }
+
+ return (ret + 1) * sizeof (arelent *);
+}
+
+/* Get the relocs themselves. */
+
+long
+nlm_canonicalize_reloc (abfd, sec, relptr, symbols)
+ bfd *abfd;
+ asection *sec;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *rels;
+ asection **secs;
+ bfd_size_type count, i;
+ unsigned int ret;
+
+ /* Get the relocation fixups. */
+ rels = nlm_relocation_fixups (abfd);
+ if (rels == NULL)
+ {
+ if (nlm_slurp_reloc_fixups (abfd) == false)
+ return -1;
+ rels = nlm_relocation_fixups (abfd);
+ }
+ secs = nlm_relocation_fixup_secs (abfd);
+
+ ret = 0;
+ count = nlm_fixed_header (abfd)->numberOfRelocationFixups;
+ for (i = 0; i < count; i++, rels++, secs++)
+ {
+ if (*secs == sec)
+ {
+ *relptr++ = rels;
+ ++ret;
+ }
+ }
+
+ /* Get the import symbols. */
+ count = bfd_get_symcount (abfd);
+ for (i = 0; i < count; i++, symbols++)
+ {
+ asymbol *sym;
+
+ sym = *symbols;
+ if (bfd_asymbol_flavour (sym) == bfd_target_nlm_flavour)
+ {
+ nlm_symbol_type *nlm_sym;
+ bfd_size_type j;
+
+ nlm_sym = (nlm_symbol_type *) sym;
+ for (j = 0; j < nlm_sym->rcnt; j++)
+ {
+ if (nlm_sym->relocs[j].section == sec)
+ {
+ *relptr = &nlm_sym->relocs[j].reloc;
+ (*relptr)->sym_ptr_ptr = symbols;
+ ++relptr;
+ ++ret;
+ }
+ }
+ }
+ }
+
+ *relptr = NULL;
+
+ return ret;
+}
+
+/* Compute the section file positions for an NLM file. All variable
+ length data in the file headers must be set before this function is
+ called. If the variable length data is changed later, the
+ resulting object file will be incorrect. Unfortunately, there is
+ no way to check this.
+
+ This routine also sets the Size and Offset fields in the fixed
+ header.
+
+ It also looks over the symbols and moves any common symbols into
+ the .bss section; NLM has no way to represent a common symbol.
+ This approach means that either the symbols must already have been
+ set at this point, or there must be no common symbols. We need to
+ move the symbols at this point so that mangle_relocs can see the
+ final values. */
+
+static boolean
+nlm_compute_section_file_positions (abfd)
+ bfd *abfd;
+{
+ file_ptr sofar;
+ asection *sec;
+ bfd_vma text, data, bss;
+ bfd_vma text_low, data_low;
+ unsigned int text_align, data_align, other_align;
+ file_ptr text_ptr, data_ptr, other_ptr;
+ asection *bss_sec;
+ asymbol **sym_ptr_ptr;
+
+ if (abfd->output_has_begun == true)
+ return true;
+
+ /* Make sure we have a section to hold uninitialized data. */
+ bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
+ if (bss_sec == NULL)
+ {
+ if (!add_bfd_section (abfd, NLM_UNINITIALIZED_DATA_NAME,
+ (file_ptr) 0, (bfd_size_type) 0,
+ SEC_ALLOC))
+ return false;
+ bss_sec = bfd_get_section_by_name (abfd, NLM_UNINITIALIZED_DATA_NAME);
+ }
+
+ abfd->output_has_begun = true;
+
+ /* The fixed header. */
+ sofar = nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd);
+
+ /* The variable header. */
+ sofar += (sizeof (nlm_variable_header (abfd)->descriptionLength)
+ + nlm_variable_header (abfd)->descriptionLength + 1
+ + NLM_TARGET_LONG_SIZE /* stackSize */
+ + NLM_TARGET_LONG_SIZE /* reserved */
+ + sizeof (nlm_variable_header (abfd)->oldThreadName)
+ + sizeof (nlm_variable_header (abfd)->screenNameLength)
+ + nlm_variable_header (abfd)->screenNameLength + 1
+ + sizeof (nlm_variable_header (abfd)->threadNameLength)
+ + nlm_variable_header (abfd)->threadNameLength + 1);
+
+ /* The auxiliary headers. */
+ if (find_nonzero ((PTR) nlm_version_header (abfd),
+ sizeof (Nlm_Internal_Version_Header)))
+ sofar += sizeof (Nlm_External_Version_Header);
+ if (find_nonzero ((PTR) nlm_extended_header (abfd),
+ sizeof (Nlm_Internal_Extended_Header)))
+ sofar += sizeof (Nlm_External_Extended_Header);
+ if (find_nonzero ((PTR) nlm_copyright_header (abfd),
+ sizeof (Nlm_Internal_Copyright_Header)))
+ sofar += (sizeof (Nlm_External_Copyright_Header)
+ + nlm_copyright_header (abfd)->copyrightMessageLength + 1);
+ if (find_nonzero ((PTR) nlm_custom_header (abfd),
+ sizeof (Nlm_Internal_Custom_Header)))
+ sofar += (sizeof (Nlm_External_Custom_Header)
+ + nlm_custom_header (abfd)->hdrLength);
+ if (find_nonzero ((PTR) nlm_cygnus_ext_header (abfd),
+ sizeof (Nlm_Internal_Cygnus_Ext_Header)))
+ sofar += sizeof (Nlm_External_Custom_Header);
+
+ /* Compute the section file positions in two passes. First get the
+ sizes of the text and data sections, and then set the file
+ positions. This code aligns the sections in the file using the
+ same alignment restrictions that apply to the sections in memory;
+ this may not be necessary. */
+ text = 0;
+ text_low = (bfd_vma) - 1;
+ text_align = 0;
+ data = 0;
+ data_low = (bfd_vma) - 1;
+ data_align = 0;
+ bss = 0;
+ other_align = 0;
+ for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
+ {
+ flagword f;
+
+ sec->_raw_size = BFD_ALIGN (sec->_raw_size, 1 << sec->alignment_power);
+
+ f = bfd_get_section_flags (abfd, sec);
+ if (f & SEC_CODE)
+ {
+ text += sec->_raw_size;
+ if (bfd_get_section_vma (abfd, sec) < text_low)
+ text_low = bfd_get_section_vma (abfd, sec);
+ if (sec->alignment_power > text_align)
+ text_align = sec->alignment_power;
+ }
+ else if (f & SEC_DATA)
+ {
+ data += sec->_raw_size;
+ if (bfd_get_section_vma (abfd, sec) < data_low)
+ data_low = bfd_get_section_vma (abfd, sec);
+ if (sec->alignment_power > data_align)
+ data_align = sec->alignment_power;
+ }
+ else if (f & SEC_HAS_CONTENTS)
+ {
+ if (sec->alignment_power > other_align)
+ other_align = sec->alignment_power;
+ }
+ else if (f & SEC_ALLOC)
+ bss += sec->_raw_size;
+ }
+
+ nlm_set_text_low (abfd, text_low);
+ nlm_set_data_low (abfd, data_low);
+
+ if (nlm_no_uninitialized_data (abfd))
+ {
+ /* This NetWare format does not use uninitialized data. We must
+ increase the size of the data section. We will never wind up
+ writing those file locations, so they will remain zero. */
+ data += bss;
+ bss = 0;
+ }
+
+ text_ptr = BFD_ALIGN (sofar, 1 << text_align);
+ data_ptr = BFD_ALIGN (text_ptr + text, 1 << data_align);
+ other_ptr = BFD_ALIGN (data_ptr + data, 1 << other_align);
+
+ /* Fill in some fields in the header for which we now have the
+ information. */
+ nlm_fixed_header (abfd)->codeImageOffset = text_ptr;
+ nlm_fixed_header (abfd)->codeImageSize = text;
+ nlm_fixed_header (abfd)->dataImageOffset = data_ptr;
+ nlm_fixed_header (abfd)->dataImageSize = data;
+ nlm_fixed_header (abfd)->uninitializedDataSize = bss;
+
+ for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
+ {
+ flagword f;
+
+ f = bfd_get_section_flags (abfd, sec);
+
+ if (f & SEC_CODE)
+ {
+ sec->filepos = text_ptr;
+ text_ptr += sec->_raw_size;
+ }
+ else if (f & SEC_DATA)
+ {
+ sec->filepos = data_ptr;
+ data_ptr += sec->_raw_size;
+ }
+ else if (f & SEC_HAS_CONTENTS)
+ {
+ sec->filepos = other_ptr;
+ other_ptr += sec->_raw_size;
+ }
+ }
+
+ nlm_fixed_header (abfd)->relocationFixupOffset = other_ptr;
+
+ /* Move all common symbols into the .bss section. */
+
+ sym_ptr_ptr = bfd_get_outsymbols (abfd);
+ if (sym_ptr_ptr != NULL)
+ {
+ asymbol **sym_end;
+ bfd_vma add;
+
+ sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
+ add = 0;
+ for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
+ {
+ asymbol *sym;
+ bfd_vma size;
+
+ sym = *sym_ptr_ptr;
+
+ if (!bfd_is_com_section (bfd_get_section (sym)))
+ continue;
+
+ /* Put the common symbol in the .bss section, and increase
+ the size of the .bss section by the size of the common
+ symbol (which is the old value of the symbol). */
+ sym->section = bss_sec;
+ size = sym->value;
+ sym->value = bss_sec->_raw_size + add;
+ add += size;
+ add = BFD_ALIGN (add, 1 << bss_sec->alignment_power);
+ }
+ if (add != 0)
+ {
+ if (nlm_no_uninitialized_data (abfd))
+ {
+ /* We could handle this case, but so far it hasn't been
+ necessary. */
+ abort ();
+ }
+ nlm_fixed_header (abfd)->uninitializedDataSize += add;
+ bss_sec->_raw_size += add;
+ }
+ }
+
+ return true;
+}
+
+/* Set the contents of a section. To do this we need to know where
+ the section is going to be located in the output file. That means
+ that the sizes of all the sections must be set, and all the
+ variable size header information must be known. */
+
+boolean
+nlm_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
+ && nlm_compute_section_file_positions (abfd) == false)
+ return false;
+
+ if (count == 0)
+ return true;
+
+ /* i386 NetWare has a very restricted set of relocs. In order for
+ objcopy to work, the NLM i386 backend needs a chance to rework
+ the section contents so that its set of relocs will work. If all
+ the relocs are already acceptable, this will not do anything. */
+ if (section->reloc_count != 0)
+ {
+ boolean (*mangle_relocs_func) PARAMS ((bfd *, asection *, PTR,
+ bfd_vma, bfd_size_type));
+
+ mangle_relocs_func = nlm_mangle_relocs_func (abfd);
+ if (mangle_relocs_func != NULL)
+ {
+ if (!(*mangle_relocs_func) (abfd, section, location,
+ (bfd_vma) offset, count))
+ return false;
+ }
+ }
+
+ if (bfd_seek (abfd, (file_ptr) (section->filepos + offset), SEEK_SET) != 0
+ || bfd_write (location, 1, count, abfd) != count)
+ return false;
+
+ return true;
+}
+
+/* We need to sort a list of relocs associated with sections when we
+ write out the external relocs. */
+
+static int
+nlm_external_reloc_compare (p1, p2)
+ const void *p1;
+ const void *p2;
+{
+ const struct reloc_and_sec *r1 = (const struct reloc_and_sec *) p1;
+ const struct reloc_and_sec *r2 = (const struct reloc_and_sec *) p2;
+ int cmp;
+
+ cmp = strcmp ((*r1->rel->sym_ptr_ptr)->name,
+ (*r2->rel->sym_ptr_ptr)->name);
+ if (cmp != 0)
+ return cmp;
+
+ /* We sort by address within symbol to make the sort more stable and
+ increase the chances that different hosts will generate bit for
+ bit equivalent results. */
+ return (int) (r1->rel->address - r2->rel->address);
+}
+
+/* Write out an NLM file. We write out the information in this order:
+ fixed header
+ variable header
+ auxiliary headers
+ code sections
+ data sections
+ other sections (custom data, messages, help, shared NLM, RPC,
+ module dependencies)
+ relocation fixups
+ external references (imports)
+ public symbols (exports)
+ debugging records
+ This is similar to the order used by the NetWare tools; the
+ difference is that NetWare puts the sections other than code, data
+ and custom data at the end of the NLM. It is convenient for us to
+ know where the sections are going to be before worrying about the
+ size of the other information.
+
+ By the time this function is called, all the section data should
+ have been output using set_section_contents. Note that custom
+ data, the message file, the help file, the shared NLM file, the RPC
+ data, and the module dependencies are all considered to be
+ sections; the caller is responsible for filling in the offset and
+ length fields in the NLM headers. The relocation fixups and
+ imports are both obtained from the list of relocs attached to each
+ section. The exports and debugging records are obtained from the
+ list of outsymbols. */
+
+boolean
+nlm_write_object_contents (abfd)
+ bfd *abfd;
+{
+ asection *sec;
+ boolean (*write_import_func) PARAMS ((bfd *, asection *, arelent *));
+ bfd_size_type external_reloc_count, internal_reloc_count, i, c;
+ struct reloc_and_sec *external_relocs;
+ asymbol **sym_ptr_ptr;
+ file_ptr last;
+ boolean (*write_prefix_func) PARAMS ((bfd *));
+ unsigned char *fixed_header = NULL;
+
+ fixed_header = ((unsigned char *)
+ bfd_malloc ((size_t) nlm_fixed_header_size (abfd)));
+ if (fixed_header == NULL)
+ goto error_return;
+
+ if (abfd->output_has_begun == false
+ && nlm_compute_section_file_positions (abfd) == false)
+ goto error_return;
+
+ /* Write out the variable length headers. */
+ if (bfd_seek (abfd,
+ nlm_optional_prefix_size (abfd) + nlm_fixed_header_size (abfd),
+ SEEK_SET) != 0)
+ goto error_return;
+ if (nlm_swap_variable_header_out (abfd) == false
+ || nlm_swap_auxiliary_headers_out (abfd) == false)
+ {
+ bfd_set_error (bfd_error_system_call);
+ goto error_return;
+ }
+
+ /* A weak check on whether the section file positions were
+ reasonable. */
+ if (bfd_tell (abfd) > nlm_fixed_header (abfd)->codeImageOffset)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ goto error_return;
+ }
+
+ /* Advance to the relocs. */
+ if (bfd_seek (abfd, nlm_fixed_header (abfd)->relocationFixupOffset,
+ SEEK_SET) != 0)
+ goto error_return;
+
+ /* The format of the relocation entries is dependent upon the
+ particular target. We use an external routine to write the reloc
+ out. */
+ write_import_func = nlm_write_import_func (abfd);
+
+ /* Write out the internal relocation fixups. While we're looping
+ over the relocs, we also count the external relocs, which is
+ needed when they are written out below. */
+ internal_reloc_count = 0;
+ external_reloc_count = 0;
+ for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
+ {
+ arelent **rel_ptr_ptr, **rel_end;
+
+ if (sec->reloc_count == 0)
+ continue;
+
+ /* We can only represent relocs within a code or data
+ section. We ignore them for a debugging section. */
+ if ((bfd_get_section_flags (abfd, sec) & (SEC_CODE | SEC_DATA)) == 0)
+ continue;
+
+ /* We need to know how to write out imports */
+ if (write_import_func == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ goto error_return;
+ }
+
+ rel_ptr_ptr = sec->orelocation;
+ rel_end = rel_ptr_ptr + sec->reloc_count;
+ for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
+ {
+ arelent *rel;
+ asymbol *sym;
+
+ rel = *rel_ptr_ptr;
+ sym = *rel->sym_ptr_ptr;
+
+ if (! bfd_is_und_section (bfd_get_section (sym)))
+ {
+ ++internal_reloc_count;
+ if ((*write_import_func) (abfd, sec, rel) == false)
+ goto error_return;
+ }
+ else
+ ++external_reloc_count;
+ }
+ }
+ nlm_fixed_header (abfd)->numberOfRelocationFixups = internal_reloc_count;
+
+ /* Write out the imports (relocs against external symbols). These
+ are output as a symbol name followed by all the relocs for that
+ symbol, so we must first gather together all the relocs against
+ external symbols and sort them. */
+ external_relocs =
+ (struct reloc_and_sec *) bfd_alloc (abfd,
+ (external_reloc_count
+ * sizeof (struct reloc_and_sec)));
+ if (external_relocs == (struct reloc_and_sec *) NULL)
+ goto error_return;
+ i = 0;
+ for (sec = abfd->sections; sec != (asection *) NULL; sec = sec->next)
+ {
+ arelent **rel_ptr_ptr, **rel_end;
+
+ if (sec->reloc_count == 0)
+ continue;
+
+ rel_ptr_ptr = sec->orelocation;
+ rel_end = rel_ptr_ptr + sec->reloc_count;
+ for (; rel_ptr_ptr < rel_end; rel_ptr_ptr++)
+ {
+ arelent *rel;
+ asymbol *sym;
+
+ rel = *rel_ptr_ptr;
+ sym = *rel->sym_ptr_ptr;
+
+ if (! bfd_is_und_section (bfd_get_section (sym)))
+ continue;
+
+ external_relocs[i].rel = rel;
+ external_relocs[i].sec = sec;
+ ++i;
+ }
+ }
+
+ BFD_ASSERT (i == external_reloc_count);
+
+ /* Sort the external relocs by name. */
+ qsort ((PTR) external_relocs, (size_t) external_reloc_count,
+ sizeof (struct reloc_and_sec), nlm_external_reloc_compare);
+
+ /* Write out the external relocs. */
+ nlm_fixed_header (abfd)->externalReferencesOffset = bfd_tell (abfd);
+ c = 0;
+ i = 0;
+ while (i < external_reloc_count)
+ {
+ arelent *rel;
+ asymbol *sym;
+ bfd_size_type j, cnt;
+
+ ++c;
+
+ rel = external_relocs[i].rel;
+ sym = *rel->sym_ptr_ptr;
+
+ cnt = 0;
+ for (j = i;
+ (j < external_reloc_count
+ && *external_relocs[j].rel->sym_ptr_ptr == sym);
+ j++)
+ ++cnt;
+
+ if ((*nlm_write_external_func (abfd)) (abfd, cnt, sym,
+ &external_relocs[i])
+ == false)
+ goto error_return;
+
+ i += cnt;
+ }
+
+ nlm_fixed_header (abfd)->numberOfExternalReferences = c;
+
+ /* Write out the public symbols (exports). */
+ sym_ptr_ptr = bfd_get_outsymbols (abfd);
+ if (sym_ptr_ptr != (asymbol **) NULL)
+ {
+ bfd_vma (*get_public_offset_func) PARAMS ((bfd *, asymbol *));
+ boolean (*write_export_func) PARAMS ((bfd *, asymbol *, bfd_vma));
+
+ asymbol **sym_end;
+
+ nlm_fixed_header (abfd)->publicsOffset = bfd_tell (abfd);
+ get_public_offset_func = nlm_get_public_offset_func (abfd);
+ write_export_func = nlm_write_export_func (abfd);
+ c = 0;
+ sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
+ for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
+ {
+ asymbol *sym;
+ bfd_byte len;
+ bfd_vma offset;
+ bfd_byte temp[NLM_TARGET_LONG_SIZE];
+
+ sym = *sym_ptr_ptr;
+
+ if ((sym->flags & (BSF_EXPORT | BSF_GLOBAL)) == 0
+ || bfd_is_und_section (bfd_get_section (sym)))
+ continue;
+
+ ++c;
+
+ if (get_public_offset_func)
+ {
+ /* Most backends can use the code below, but
+ unfortunately some use a different scheme. */
+ offset = (*get_public_offset_func) (abfd, sym);
+ }
+ else
+ {
+ offset = bfd_asymbol_value (sym);
+ sec = sym->section;
+ if (sec->flags & SEC_CODE)
+ {
+ offset -= nlm_get_text_low (abfd);
+ offset |= NLM_HIBIT;
+ }
+ else if (sec->flags & (SEC_DATA | SEC_ALLOC))
+ {
+ /* SEC_ALLOC is for the .bss section. */
+ offset -= nlm_get_data_low (abfd);
+ }
+ else
+ {
+ /* We can't handle an exported symbol that is not in
+ the code or data segment. */
+ bfd_set_error (bfd_error_invalid_operation);
+ goto error_return;
+ }
+ }
+
+ if (write_export_func)
+ {
+ if ((*write_export_func) (abfd, sym, offset) == false)
+ goto error_return;
+ }
+ else
+ {
+ len = strlen (sym->name);
+ if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd)
+ != sizeof (bfd_byte))
+ || bfd_write (sym->name, len, 1, abfd) != len)
+ goto error_return;
+
+ put_word (abfd, offset, temp);
+ if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ goto error_return;
+ }
+ }
+ nlm_fixed_header (abfd)->numberOfPublics = c;
+
+ /* Write out the debugging records. The NLM conversion program
+ wants to be able to inhibit this, so as a special hack if
+ debugInfoOffset is set to -1 we don't write any debugging
+ information. This can not be handled by fiddling with the
+ symbol table, because exported symbols appear in both the
+ exported symbol list and the debugging information. */
+ if (nlm_fixed_header (abfd)->debugInfoOffset == (file_ptr) - 1)
+ {
+ nlm_fixed_header (abfd)->debugInfoOffset = 0;
+ nlm_fixed_header (abfd)->numberOfDebugRecords = 0;
+ }
+ else
+ {
+ nlm_fixed_header (abfd)->debugInfoOffset = bfd_tell (abfd);
+ c = 0;
+ sym_ptr_ptr = bfd_get_outsymbols (abfd);
+ sym_end = sym_ptr_ptr + bfd_get_symcount (abfd);
+ for (; sym_ptr_ptr < sym_end; sym_ptr_ptr++)
+ {
+ asymbol *sym;
+ bfd_byte type, len;
+ bfd_vma offset;
+ bfd_byte temp[NLM_TARGET_LONG_SIZE];
+
+ sym = *sym_ptr_ptr;
+
+ /* The NLM notion of a debugging symbol is actually what
+ BFD calls a local or global symbol. What BFD calls a
+ debugging symbol NLM does not understand at all. */
+ if ((sym->flags & (BSF_LOCAL | BSF_GLOBAL | BSF_EXPORT)) == 0
+ || (sym->flags & BSF_DEBUGGING) != 0
+ || bfd_is_und_section (bfd_get_section (sym)))
+ continue;
+
+ ++c;
+
+ offset = bfd_asymbol_value (sym);
+ sec = sym->section;
+ if (sec->flags & SEC_CODE)
+ {
+ offset -= nlm_get_text_low (abfd);
+ type = 1;
+ }
+ else if (sec->flags & (SEC_DATA | SEC_ALLOC))
+ {
+ /* SEC_ALLOC is for the .bss section. */
+ offset -= nlm_get_data_low (abfd);
+ type = 0;
+ }
+ else
+ type = 2;
+
+ /* The type is 0 for data, 1 for code, 2 for absolute. */
+ if (bfd_write (&type, sizeof (bfd_byte), 1, abfd)
+ != sizeof (bfd_byte))
+ goto error_return;
+
+ put_word (abfd, offset, temp);
+ if (bfd_write (temp, sizeof (temp), 1, abfd) != sizeof (temp))
+ goto error_return;
+
+ len = strlen (sym->name);
+ if ((bfd_write (&len, sizeof (bfd_byte), 1, abfd)
+ != sizeof (bfd_byte))
+ || bfd_write (sym->name, len, 1, abfd) != len)
+ goto error_return;
+ }
+ nlm_fixed_header (abfd)->numberOfDebugRecords = c;
+ }
+ }
+
+ /* NLMLINK fills in offset values even if there is no data, so we do
+ the same. */
+ last = bfd_tell (abfd);
+ if (nlm_fixed_header (abfd)->codeImageOffset == 0)
+ nlm_fixed_header (abfd)->codeImageOffset = last;
+ if (nlm_fixed_header (abfd)->dataImageOffset == 0)
+ nlm_fixed_header (abfd)->dataImageOffset = last;
+ if (nlm_fixed_header (abfd)->customDataOffset == 0)
+ nlm_fixed_header (abfd)->customDataOffset = last;
+ if (nlm_fixed_header (abfd)->moduleDependencyOffset == 0)
+ nlm_fixed_header (abfd)->moduleDependencyOffset = last;
+ if (nlm_fixed_header (abfd)->relocationFixupOffset == 0)
+ nlm_fixed_header (abfd)->relocationFixupOffset = last;
+ if (nlm_fixed_header (abfd)->externalReferencesOffset == 0)
+ nlm_fixed_header (abfd)->externalReferencesOffset = last;
+ if (nlm_fixed_header (abfd)->publicsOffset == 0)
+ nlm_fixed_header (abfd)->publicsOffset = last;
+ if (nlm_fixed_header (abfd)->debugInfoOffset == 0)
+ nlm_fixed_header (abfd)->debugInfoOffset = last;
+
+ /* At this point everything has been written out except the fixed
+ header. */
+ memcpy (nlm_fixed_header (abfd)->signature, nlm_signature (abfd),
+ NLM_SIGNATURE_SIZE);
+ nlm_fixed_header (abfd)->version = NLM_HEADER_VERSION;
+ nlm_fixed_header (abfd)->codeStartOffset =
+ (bfd_get_start_address (abfd)
+ - nlm_get_text_low (abfd));
+
+ /* We have no convenient way for the caller to pass in the exit
+ procedure or the check unload procedure, so the caller must set
+ the values in the header to the values of the symbols. */
+ nlm_fixed_header (abfd)->exitProcedureOffset -= nlm_get_text_low (abfd);
+ if (nlm_fixed_header (abfd)->checkUnloadProcedureOffset != 0)
+ nlm_fixed_header (abfd)->checkUnloadProcedureOffset -=
+ nlm_get_text_low (abfd);
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+ goto error_return;
+
+ write_prefix_func = nlm_write_prefix_func (abfd);
+ if (write_prefix_func)
+ {
+ if ((*write_prefix_func) (abfd) == false)
+ goto error_return;
+ }
+
+ BFD_ASSERT ((bfd_size_type) bfd_tell (abfd)
+ == nlm_optional_prefix_size (abfd));
+
+ nlm_swap_fixed_header_out (abfd, nlm_fixed_header (abfd), fixed_header);
+ if (bfd_write (fixed_header, nlm_fixed_header_size (abfd), 1, abfd)
+ != nlm_fixed_header_size (abfd))
+ goto error_return;
+
+ if (fixed_header != NULL)
+ free (fixed_header);
+ return true;
+
+error_return:
+ if (fixed_header != NULL)
+ free (fixed_header);
+ return false;
+}
diff --git a/contrib/gdb/bfd/nlmswap.h b/contrib/gdb/bfd/nlmswap.h
new file mode 100644
index 0000000..5a9ce72
--- /dev/null
+++ b/contrib/gdb/bfd/nlmswap.h
@@ -0,0 +1,157 @@
+/* NLM (NetWare Loadable Module) swapping routines for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, using ELF support as the
+ template.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Although this is a header file, it defines functions. It is
+ included by NLM backends to define swapping functions that vary
+ from one NLM to another. The backend code must arrange for
+ Nlm_External_xxxx to be defined appropriately, and can then include
+ this file to get the swapping routines.
+
+ At the moment this is only needed for one structure, the fixed NLM
+ file header. */
+
+static void nlm_swap_fixed_header_in PARAMS ((bfd *, PTR,
+ Nlm_Internal_Fixed_Header *));
+static void nlm_swap_fixed_header_out PARAMS ((bfd *,
+ Nlm_Internal_Fixed_Header *,
+ PTR));
+
+/* Translate an NLM fixed length file header in external format into an NLM
+ file header in internal format. */
+
+static void
+nlm_swap_fixed_header_in (abfd, realsrc, dst)
+ bfd *abfd;
+ PTR realsrc;
+ Nlm_Internal_Fixed_Header *dst;
+{
+ Nlm_External_Fixed_Header *src = (Nlm_External_Fixed_Header *) realsrc;
+ memcpy (dst->signature, src->signature, NLM_SIGNATURE_SIZE);
+ memcpy (dst->moduleName, src->moduleName, NLM_MODULE_NAME_SIZE);
+ dst->version =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->version);
+ dst->codeImageOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->codeImageOffset);
+ dst->codeImageSize =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->codeImageSize);
+ dst->dataImageOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->dataImageOffset);
+ dst->dataImageSize =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->dataImageSize);
+ dst->uninitializedDataSize =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->uninitializedDataSize);
+ dst->customDataOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->customDataOffset);
+ dst->customDataSize =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->customDataSize);
+ dst->moduleDependencyOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->moduleDependencyOffset);
+ dst->numberOfModuleDependencies =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->numberOfModuleDependencies);
+ dst->relocationFixupOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->relocationFixupOffset);
+ dst->numberOfRelocationFixups =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->numberOfRelocationFixups);
+ dst->externalReferencesOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->externalReferencesOffset);
+ dst->numberOfExternalReferences =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->numberOfExternalReferences);
+ dst->publicsOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->publicsOffset);
+ dst->numberOfPublics =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->numberOfPublics);
+ dst->debugInfoOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->debugInfoOffset);
+ dst->numberOfDebugRecords =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->numberOfDebugRecords);
+ dst->codeStartOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->codeStartOffset);
+ dst->exitProcedureOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->exitProcedureOffset);
+ dst->checkUnloadProcedureOffset =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->checkUnloadProcedureOffset);
+ dst->moduleType =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->moduleType);
+ dst->flags =
+ bfd_h_get_32 (abfd, (bfd_byte *) src->flags);
+}
+
+/* Translate an NLM fixed length file header in internal format into
+ an NLM file header in external format. */
+
+static void
+nlm_swap_fixed_header_out (abfd, src, realdst)
+ bfd *abfd;
+ Nlm_Internal_Fixed_Header *src;
+ PTR realdst;
+{
+ Nlm_External_Fixed_Header *dst = (Nlm_External_Fixed_Header *) realdst;
+ memset (dst, 0, sizeof *dst);
+ memcpy (dst->signature, src->signature, NLM_SIGNATURE_SIZE);
+ memcpy (dst->moduleName, src->moduleName, NLM_MODULE_NAME_SIZE);
+ bfd_h_put_32 (abfd, (bfd_vma) src->version,
+ (bfd_byte *) dst->version);
+ bfd_h_put_32 (abfd, (bfd_vma) src->codeImageOffset,
+ (bfd_byte *) dst->codeImageOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->codeImageSize,
+ (bfd_byte *) dst->codeImageSize);
+ bfd_h_put_32 (abfd, (bfd_vma) src->dataImageOffset,
+ (bfd_byte *) dst->dataImageOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->dataImageSize,
+ (bfd_byte *) dst->dataImageSize);
+ bfd_h_put_32 (abfd, (bfd_vma) src->uninitializedDataSize,
+ (bfd_byte *) dst->uninitializedDataSize);
+ bfd_h_put_32 (abfd, (bfd_vma) src->customDataOffset,
+ (bfd_byte *) dst->customDataOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->customDataSize,
+ (bfd_byte *) dst->customDataSize);
+ bfd_h_put_32 (abfd, (bfd_vma) src->moduleDependencyOffset,
+ (bfd_byte *) dst->moduleDependencyOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->numberOfModuleDependencies,
+ (bfd_byte *) dst->numberOfModuleDependencies);
+ bfd_h_put_32 (abfd, (bfd_vma) src->relocationFixupOffset,
+ (bfd_byte *) dst->relocationFixupOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->numberOfRelocationFixups,
+ (bfd_byte *) dst->numberOfRelocationFixups);
+ bfd_h_put_32 (abfd, (bfd_vma) src->externalReferencesOffset,
+ (bfd_byte *) dst->externalReferencesOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->numberOfExternalReferences,
+ (bfd_byte *) dst->numberOfExternalReferences);
+ bfd_h_put_32 (abfd, (bfd_vma) src->publicsOffset,
+ (bfd_byte *) dst->publicsOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->numberOfPublics,
+ (bfd_byte *) dst->numberOfPublics);
+ bfd_h_put_32 (abfd, (bfd_vma) src->debugInfoOffset,
+ (bfd_byte *) dst->debugInfoOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->numberOfDebugRecords,
+ (bfd_byte *) dst->numberOfDebugRecords);
+ bfd_h_put_32 (abfd, (bfd_vma) src->codeStartOffset,
+ (bfd_byte *) dst->codeStartOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->exitProcedureOffset,
+ (bfd_byte *) dst->exitProcedureOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->checkUnloadProcedureOffset,
+ (bfd_byte *) dst->checkUnloadProcedureOffset);
+ bfd_h_put_32 (abfd, (bfd_vma) src->moduleType,
+ (bfd_byte *) dst->moduleType);
+ bfd_h_put_32 (abfd, (bfd_vma) src->flags,
+ (bfd_byte *) dst->flags);
+}
diff --git a/contrib/gdb/bfd/ns32knetbsd.c b/contrib/gdb/bfd/ns32knetbsd.c
new file mode 100644
index 0000000..3e3f08a
--- /dev/null
+++ b/contrib/gdb/bfd/ns32knetbsd.c
@@ -0,0 +1,53 @@
+/* BFD back-end for NetBSD/ns32k a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#undef TARGET_IS_BIG_ENDIAN_P
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE 4096
+
+#define DEFAULT_ARCH bfd_arch_ns32k
+#define MACHTYPE_OK(mtype) ((mtype) == M_532_NETBSD || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(pc532netbsd_,OP)
+
+#define NAME(x,y) CAT3(ns32kaout,_32_,y)
+
+/* This needs to start with a.out so GDB knows it is an a.out variant. */
+#define TARGETNAME "a.out-ns32k-netbsd"
+
+#define ns32kaout_32_get_section_contents aout_32_get_section_contents
+
+#define MY_text_includes_header 1
+
+/* We can`t use the MYNS macro here for cpp reasons too subtle
+ * for me -- IWD
+ */
+#define MY_bfd_reloc_type_lookup ns32kaout_bfd_reloc_type_lookup
+
+#include "bfd.h" /* To ensure following declaration is OK */
+
+CONST struct reloc_howto_struct *
+MY_bfd_reloc_type_lookup
+ PARAMS((bfd *abfd AND
+ bfd_reloc_code_real_type code));
+
+
+#include "netbsd.h"
diff --git a/contrib/gdb/bfd/oasys.c b/contrib/gdb/bfd/oasys.c
new file mode 100644
index 0000000..c721472
--- /dev/null
+++ b/contrib/gdb/bfd/oasys.c
@@ -0,0 +1,1533 @@
+/* BFD back-end for oasys objects.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by Steve Chamberlain of Cygnus Support, <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define UNDERSCORE_HACK 1
+#include "bfd.h"
+#include "sysdep.h"
+#include <ctype.h>
+#include "libbfd.h"
+#include "oasys.h"
+#include "liboasys.h"
+
+/* XXX - FIXME. offsetof belongs in the system-specific files in
+ ../include/sys. */
+/* Define offsetof for those systems which lack it */
+
+#ifndef offsetof
+#define offsetof(type, identifier) (size_t) &(((type *) 0)->identifier)
+#endif
+
+static boolean oasys_read_record PARAMS ((bfd *,
+ oasys_record_union_type *));
+static boolean oasys_write_sections PARAMS ((bfd *));
+static boolean oasys_write_record PARAMS ((bfd *,
+ oasys_record_enum_type,
+ oasys_record_union_type *,
+ size_t));
+static boolean oasys_write_syms PARAMS ((bfd *));
+static boolean oasys_write_header PARAMS ((bfd *));
+static boolean oasys_write_end PARAMS ((bfd *));
+static boolean oasys_write_data PARAMS ((bfd *));
+
+/* Read in all the section data and relocation stuff too */
+PROTO (static boolean, oasys_slurp_section_data, (bfd * CONST abfd));
+
+static boolean
+oasys_read_record (abfd, record)
+ bfd *abfd;
+ oasys_record_union_type *record;
+{
+ if (bfd_read ((PTR) record, 1, sizeof (record->header), abfd)
+ != sizeof (record->header))
+ return false;
+
+ if ((size_t) record->header.length <= (size_t) sizeof (record->header))
+ return true;
+ if (bfd_read ((PTR) (((char *) record) + sizeof (record->header)),
+ 1, record->header.length - sizeof (record->header),
+ abfd)
+ != record->header.length - sizeof (record->header))
+ return false;
+ return true;
+}
+static size_t
+oasys_string_length (record)
+ oasys_record_union_type *record;
+{
+ return record->header.length
+ - ((char *) record->symbol.name - (char *) record);
+}
+
+/*****************************************************************************/
+
+/*
+
+Slurp the symbol table by reading in all the records at the start file
+till we get to the first section record.
+
+We'll sort the symbolss into two lists, defined and undefined. The
+undefined symbols will be placed into the table according to their
+refno.
+
+We do this by placing all undefined symbols at the front of the table
+moving in, and the defined symbols at the end of the table moving back.
+
+*/
+
+static boolean
+oasys_slurp_symbol_table (abfd)
+ bfd *CONST abfd;
+{
+ oasys_record_union_type record;
+ oasys_data_type *data = OASYS_DATA (abfd);
+ boolean loop = true;
+ asymbol *dest_defined;
+ asymbol *dest;
+ char *string_ptr;
+
+
+ if (data->symbols != (asymbol *) NULL)
+ {
+ return true;
+ }
+ /* Buy enough memory for all the symbols and all the names */
+ data->symbols =
+ (asymbol *) bfd_alloc (abfd, sizeof (asymbol) * abfd->symcount);
+#ifdef UNDERSCORE_HACK
+ /* buy 1 more char for each symbol to keep the underscore in*/
+ data->strings = bfd_alloc (abfd, data->symbol_string_length +
+ abfd->symcount);
+#else
+ data->strings = bfd_alloc (abfd, data->symbol_string_length);
+#endif
+ if (!data->symbols || !data->strings)
+ return false;
+
+ dest_defined = data->symbols + abfd->symcount - 1;
+
+ string_ptr = data->strings;
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ return false;
+ while (loop)
+ {
+
+ if (! oasys_read_record (abfd, &record))
+ return false;
+ switch (record.header.type)
+ {
+ case oasys_record_is_header_enum:
+ break;
+ case oasys_record_is_local_enum:
+ case oasys_record_is_symbol_enum:
+ {
+ int flag = record.header.type == (int) oasys_record_is_local_enum ?
+ (BSF_LOCAL) : (BSF_GLOBAL | BSF_EXPORT);
+
+
+ size_t length = oasys_string_length (&record);
+ switch (record.symbol.relb & RELOCATION_TYPE_BITS)
+ {
+ case RELOCATION_TYPE_ABS:
+ dest = dest_defined--;
+ dest->section = bfd_abs_section_ptr;
+ dest->flags = 0;
+
+ break;
+ case RELOCATION_TYPE_REL:
+ dest = dest_defined--;
+ dest->section =
+ OASYS_DATA (abfd)->sections[record.symbol.relb &
+ RELOCATION_SECT_BITS];
+ if (record.header.type == (int) oasys_record_is_local_enum)
+ {
+ dest->flags = BSF_LOCAL;
+ if (dest->section == (asection *) (~0))
+ {
+ /* It seems that sometimes internal symbols are tied up, but
+ still get output, even though there is no
+ section */
+ dest->section = 0;
+ }
+ }
+ else
+ {
+
+ dest->flags = flag;
+ }
+ break;
+ case RELOCATION_TYPE_UND:
+ dest = data->symbols + bfd_h_get_16 (abfd, record.symbol.refno);
+ dest->section = bfd_und_section_ptr;
+ break;
+ case RELOCATION_TYPE_COM:
+ dest = dest_defined--;
+ dest->name = string_ptr;
+ dest->the_bfd = abfd;
+
+ dest->section = bfd_com_section_ptr;
+
+ break;
+ default:
+ dest = dest_defined--;
+ BFD_ASSERT (0);
+ break;
+ }
+ dest->name = string_ptr;
+ dest->the_bfd = abfd;
+ dest->udata.p = (PTR) NULL;
+ dest->value = bfd_h_get_32 (abfd, record.symbol.value);
+
+#ifdef UNDERSCORE_HACK
+ if (record.symbol.name[0] != '_')
+ {
+ string_ptr[0] = '_';
+ string_ptr++;
+ }
+#endif
+ memcpy (string_ptr, record.symbol.name, length);
+
+
+ string_ptr[length] = 0;
+ string_ptr += length + 1;
+ }
+ break;
+ default:
+ loop = false;
+ }
+ }
+ return true;
+}
+
+static long
+oasys_get_symtab_upper_bound (abfd)
+ bfd *CONST abfd;
+{
+ if (! oasys_slurp_symbol_table (abfd))
+ return -1;
+
+ return (abfd->symcount + 1) * (sizeof (oasys_symbol_type *));
+}
+
+/*
+*/
+
+extern const bfd_target oasys_vec;
+
+long
+oasys_get_symtab (abfd, location)
+ bfd *abfd;
+ asymbol **location;
+{
+ asymbol *symbase;
+ unsigned int counter;
+ if (oasys_slurp_symbol_table (abfd) == false)
+ {
+ return -1;
+ }
+ symbase = OASYS_DATA (abfd)->symbols;
+ for (counter = 0; counter < abfd->symcount; counter++)
+ {
+ *(location++) = symbase++;
+ }
+ *location = 0;
+ return abfd->symcount;
+}
+
+/***********************************************************************
+* archive stuff
+*/
+
+static const bfd_target *
+oasys_archive_p (abfd)
+ bfd *abfd;
+{
+ oasys_archive_header_type header;
+ oasys_extarchive_header_type header_ext;
+ unsigned int i;
+ file_ptr filepos;
+
+ if (bfd_seek (abfd, (file_ptr) 0, false) != 0
+ || (bfd_read ((PTR) & header_ext, 1, sizeof (header_ext), abfd)
+ != sizeof (header_ext)))
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ header.version = bfd_h_get_32 (abfd, header_ext.version);
+ header.mod_count = bfd_h_get_32 (abfd, header_ext.mod_count);
+ header.mod_tbl_offset = bfd_h_get_32 (abfd, header_ext.mod_tbl_offset);
+ header.sym_tbl_size = bfd_h_get_32 (abfd, header_ext.sym_tbl_size);
+ header.sym_count = bfd_h_get_32 (abfd, header_ext.sym_count);
+ header.sym_tbl_offset = bfd_h_get_32 (abfd, header_ext.sym_tbl_offset);
+ header.xref_count = bfd_h_get_32 (abfd, header_ext.xref_count);
+ header.xref_lst_offset = bfd_h_get_32 (abfd, header_ext.xref_lst_offset);
+
+ /*
+ There isn't a magic number in an Oasys archive, so the best we
+ can do to verify reasnableness is to make sure that the values in
+ the header are too weird
+ */
+
+ if (header.version > 10000 ||
+ header.mod_count > 10000 ||
+ header.sym_count > 100000 ||
+ header.xref_count > 100000)
+ return (const bfd_target *) NULL;
+
+ /*
+ That all worked, let's buy the space for the header and read in
+ the headers.
+ */
+ {
+ oasys_ar_data_type *ar =
+ (oasys_ar_data_type *) bfd_alloc (abfd, sizeof (oasys_ar_data_type));
+
+ oasys_module_info_type *module =
+ (oasys_module_info_type *)
+ bfd_alloc (abfd, sizeof (oasys_module_info_type) * header.mod_count);
+ oasys_module_table_type record;
+
+ if (!ar || !module)
+ return NULL;
+
+ abfd->tdata.oasys_ar_data = ar;
+ ar->module = module;
+ ar->module_count = header.mod_count;
+
+ filepos = header.mod_tbl_offset;
+ for (i = 0; i < header.mod_count; i++)
+ {
+ if (bfd_seek (abfd, filepos, SEEK_SET) != 0)
+ return NULL;
+
+ /* There are two ways of specifying the archive header */
+
+ if (0)
+ {
+ oasys_extmodule_table_type_a_type record_ext;
+ if (bfd_read ((PTR) & record_ext, 1, sizeof (record_ext), abfd)
+ != sizeof (record_ext))
+ return NULL;
+
+ record.mod_size = bfd_h_get_32 (abfd, record_ext.mod_size);
+ record.file_offset = bfd_h_get_32 (abfd, record_ext.file_offset);
+
+ record.dep_count = bfd_h_get_32 (abfd, record_ext.dep_count);
+ record.depee_count = bfd_h_get_32 (abfd, record_ext.depee_count);
+ record.sect_count = bfd_h_get_32 (abfd, record_ext.sect_count);
+
+ module[i].name = bfd_alloc (abfd, 33);
+ if (!module[i].name)
+ return NULL;
+
+ memcpy (module[i].name, record_ext.mod_name, 33);
+ filepos +=
+ sizeof (record_ext) +
+ record.dep_count * 4 +
+ record.depee_count * 4 +
+ record.sect_count * 8 + 187;
+ }
+ else
+ {
+ oasys_extmodule_table_type_b_type record_ext;
+ if (bfd_read ((PTR) & record_ext, 1, sizeof (record_ext), abfd)
+ != sizeof (record_ext))
+ return NULL;
+
+ record.mod_size = bfd_h_get_32 (abfd, record_ext.mod_size);
+ record.file_offset = bfd_h_get_32 (abfd, record_ext.file_offset);
+
+ record.dep_count = bfd_h_get_32 (abfd, record_ext.dep_count);
+ record.depee_count = bfd_h_get_32 (abfd, record_ext.depee_count);
+ record.sect_count = bfd_h_get_32 (abfd, record_ext.sect_count);
+ record.module_name_size = bfd_h_get_32 (abfd, record_ext.mod_name_length);
+
+ module[i].name = bfd_alloc (abfd, record.module_name_size + 1);
+ if (!module[i].name)
+ return NULL;
+ if (bfd_read ((PTR) module[i].name, 1, record.module_name_size,
+ abfd)
+ != record.module_name_size)
+ return NULL;
+ module[i].name[record.module_name_size] = 0;
+ filepos +=
+ sizeof (record_ext) +
+ record.dep_count * 4 +
+ record.module_name_size + 1;
+
+ }
+
+
+ module[i].size = record.mod_size;
+ module[i].pos = record.file_offset;
+ module[i].abfd = 0;
+ }
+
+ }
+ return abfd->xvec;
+}
+
+static boolean
+oasys_mkobject (abfd)
+ bfd *abfd;
+{
+
+ abfd->tdata.oasys_obj_data = (oasys_data_type *) bfd_alloc (abfd, sizeof (oasys_data_type));
+ return abfd->tdata.oasys_obj_data ? true : false;
+}
+
+#define MAX_SECS 16
+static const bfd_target *
+oasys_object_p (abfd)
+ bfd *abfd;
+{
+ oasys_data_type *oasys;
+ oasys_data_type *save = OASYS_DATA (abfd);
+ boolean loop = true;
+ boolean had_usefull = false;
+
+ abfd->tdata.oasys_obj_data = 0;
+ oasys_mkobject (abfd);
+ oasys = OASYS_DATA (abfd);
+ memset ((PTR) oasys->sections, 0xff, sizeof (oasys->sections));
+
+ /* Point to the start of the file */
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ goto fail;
+ oasys->symbol_string_length = 0;
+ /* Inspect the records, but only keep the section info -
+ remember the size of the symbols
+ */
+ oasys->first_data_record = 0;
+ while (loop)
+ {
+ oasys_record_union_type record;
+ if (! oasys_read_record (abfd, &record))
+ goto fail;
+ if ((size_t) record.header.length < (size_t) sizeof (record.header))
+ goto fail;
+
+
+ switch ((oasys_record_enum_type) (record.header.type))
+ {
+ case oasys_record_is_header_enum:
+ had_usefull = true;
+ break;
+ case oasys_record_is_symbol_enum:
+ case oasys_record_is_local_enum:
+ /* Count symbols and remember their size for a future malloc */
+ abfd->symcount++;
+ oasys->symbol_string_length += 1 + oasys_string_length (&record);
+ had_usefull = true;
+ break;
+ case oasys_record_is_section_enum:
+ {
+ asection *s;
+ char *buffer;
+ unsigned int section_number;
+ if (record.section.header.length != sizeof (record.section))
+ {
+ goto fail;
+ }
+ buffer = bfd_alloc (abfd, 3);
+ if (!buffer)
+ goto fail;
+ section_number = record.section.relb & RELOCATION_SECT_BITS;
+ sprintf (buffer, "%u", section_number);
+ s = bfd_make_section (abfd, buffer);
+ oasys->sections[section_number] = s;
+ switch (record.section.relb & RELOCATION_TYPE_BITS)
+ {
+ case RELOCATION_TYPE_ABS:
+ case RELOCATION_TYPE_REL:
+ break;
+ case RELOCATION_TYPE_UND:
+ case RELOCATION_TYPE_COM:
+ BFD_FAIL ();
+ }
+
+ s->_raw_size = bfd_h_get_32 (abfd, record.section.value);
+ s->vma = bfd_h_get_32 (abfd, record.section.vma);
+ s->flags = 0;
+ had_usefull = true;
+ }
+ break;
+ case oasys_record_is_data_enum:
+ oasys->first_data_record = bfd_tell (abfd) - record.header.length;
+ case oasys_record_is_debug_enum:
+ case oasys_record_is_module_enum:
+ case oasys_record_is_named_section_enum:
+ case oasys_record_is_end_enum:
+ if (had_usefull == false)
+ goto fail;
+ loop = false;
+ break;
+ default:
+ goto fail;
+ }
+ }
+ oasys->symbols = (asymbol *) NULL;
+ /*
+ Oasys support several architectures, but I can't see a simple way
+ to discover which one is in a particular file - we'll guess
+ */
+ bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
+ if (abfd->symcount != 0)
+ {
+ abfd->flags |= HAS_SYMS;
+ }
+
+ /*
+ We don't know if a section has data until we've read it..
+ */
+
+ oasys_slurp_section_data (abfd);
+
+
+ return abfd->xvec;
+
+fail:
+ (void) bfd_release (abfd, oasys);
+ abfd->tdata.oasys_obj_data = save;
+ return (const bfd_target *) NULL;
+}
+
+
+static void
+oasys_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+ if (!symbol->section)
+ ret->type = (symbol->flags & BSF_LOCAL) ? 'a' : 'A';
+}
+
+static void
+oasys_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:
+ case bfd_print_symbol_more:
+ fprintf (file, "%s", symbol->name);
+ break;
+ case bfd_print_symbol_all:
+ {
+ CONST char *section_name = symbol->section == (asection *) NULL ?
+ (CONST char *) "*abs" : symbol->section->name;
+
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+
+ fprintf (file, " %-5s %s",
+ section_name,
+ symbol->name);
+ }
+ break;
+ }
+}
+/*
+ The howto table is build using the top two bits of a reloc byte to
+ index into it. The bits are PCREL,WORD/LONG
+*/
+static reloc_howto_type howto_table[] =
+{
+
+ HOWTO (0, 0, 1, 16, false, 0, complain_overflow_bitfield, 0, "abs16", true, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (0, 0, 2, 32, false, 0, complain_overflow_bitfield, 0, "abs32", true, 0xffffffff, 0xffffffff, false),
+ HOWTO (0, 0, 1, 16, true, 0, complain_overflow_signed, 0, "pcrel16", true, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (0, 0, 2, 32, true, 0, complain_overflow_signed, 0, "pcrel32", true, 0xffffffff, 0xffffffff, false)
+};
+
+/* Read in all the section data and relocation stuff too */
+static boolean
+oasys_slurp_section_data (abfd)
+ bfd *CONST abfd;
+{
+ oasys_record_union_type record;
+ oasys_data_type *data = OASYS_DATA (abfd);
+ boolean loop = true;
+
+ oasys_per_section_type *per;
+
+ asection *s;
+
+ /* See if the data has been slurped already .. */
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ per = oasys_per_section (s);
+ if (per->initialized == true)
+ return true;
+ }
+
+ if (data->first_data_record == 0)
+ return true;
+
+ if (bfd_seek (abfd, data->first_data_record, SEEK_SET) != 0)
+ return false;
+ while (loop)
+ {
+ if (! oasys_read_record (abfd, &record))
+ return false;
+ switch (record.header.type)
+ {
+ case oasys_record_is_header_enum:
+ break;
+ case oasys_record_is_data_enum:
+ {
+
+ bfd_byte *src = record.data.data;
+ bfd_byte *end_src = ((bfd_byte *) & record) + record.header.length;
+ bfd_byte *dst_ptr;
+ bfd_byte *dst_base_ptr;
+ unsigned int relbit;
+ unsigned int count;
+ asection *section =
+ data->sections[record.data.relb & RELOCATION_SECT_BITS];
+ bfd_vma dst_offset;
+
+ per = oasys_per_section (section);
+
+ if (per->initialized == false)
+ {
+ per->data = (bfd_byte *) bfd_zalloc (abfd, section->_raw_size);
+ if (!per->data)
+ return false;
+ per->reloc_tail_ptr = (oasys_reloc_type **) & (section->relocation);
+ per->had_vma = false;
+ per->initialized = true;
+ section->reloc_count = 0;
+ section->flags = SEC_ALLOC;
+ }
+
+ dst_offset = bfd_h_get_32 (abfd, record.data.addr);
+ if (per->had_vma == false)
+ {
+ /* Take the first vma we see as the base */
+ section->vma = dst_offset;
+ per->had_vma = true;
+ }
+
+ dst_offset -= section->vma;
+
+ dst_base_ptr = oasys_per_section (section)->data;
+ dst_ptr = oasys_per_section (section)->data +
+ dst_offset;
+
+ if (src < end_src)
+ {
+ section->flags |= SEC_LOAD | SEC_HAS_CONTENTS;
+ }
+ while (src < end_src)
+ {
+ unsigned char mod_byte = *src++;
+ size_t gap = end_src - src;
+
+ count = 8;
+ if (mod_byte == 0 && gap >= 8)
+ {
+ dst_ptr[0] = src[0];
+ dst_ptr[1] = src[1];
+ dst_ptr[2] = src[2];
+ dst_ptr[3] = src[3];
+ dst_ptr[4] = src[4];
+ dst_ptr[5] = src[5];
+ dst_ptr[6] = src[6];
+ dst_ptr[7] = src[7];
+ dst_ptr += 8;
+ src += 8;
+ }
+ else
+ {
+ for (relbit = 1; count-- != 0 && src < end_src; relbit <<= 1)
+ {
+ if (relbit & mod_byte)
+ {
+ unsigned char reloc = *src;
+ /* This item needs to be relocated */
+ switch (reloc & RELOCATION_TYPE_BITS)
+ {
+ case RELOCATION_TYPE_ABS:
+
+ break;
+
+ case RELOCATION_TYPE_REL:
+ {
+ /* Relocate the item relative to the section */
+ oasys_reloc_type *r =
+ (oasys_reloc_type *)
+ bfd_alloc (abfd,
+ sizeof (oasys_reloc_type));
+ if (!r)
+ return false;
+ *(per->reloc_tail_ptr) = r;
+ per->reloc_tail_ptr = &r->next;
+ r->next = (oasys_reloc_type *) NULL;
+ /* Reference to undefined symbol */
+ src++;
+ /* There is no symbol */
+ r->symbol = 0;
+ /* Work out the howto */
+ abort ();
+#if 0
+ r->relent.section =
+ data->sections[reloc &
+ RELOCATION_SECT_BITS];
+
+ r->relent.addend = -
+ r->relent.section->vma;
+#endif
+ r->relent.address = dst_ptr - dst_base_ptr;
+ r->relent.howto = &howto_table[reloc >> 6];
+ r->relent.sym_ptr_ptr = (asymbol **) NULL;
+ section->reloc_count++;
+
+ /* Fake up the data to look like it's got the -ve pc in it, this makes
+ it much easier to convert into other formats. This is done by
+ hitting the addend.
+ */
+ if (r->relent.howto->pc_relative == true)
+ {
+ r->relent.addend -= dst_ptr - dst_base_ptr;
+ }
+
+
+ }
+ break;
+
+
+ case RELOCATION_TYPE_UND:
+ {
+ oasys_reloc_type *r =
+ (oasys_reloc_type *)
+ bfd_alloc (abfd,
+ sizeof (oasys_reloc_type));
+ if (!r)
+ return false;
+ *(per->reloc_tail_ptr) = r;
+ per->reloc_tail_ptr = &r->next;
+ r->next = (oasys_reloc_type *) NULL;
+ /* Reference to undefined symbol */
+ src++;
+ /* Get symbol number */
+ r->symbol = (src[0] << 8) | src[1];
+ /* Work out the howto */
+ abort ();
+
+#if 0
+ r->relent.section = (asection
+ *) NULL;
+#endif
+ r->relent.addend = 0;
+ r->relent.address = dst_ptr - dst_base_ptr;
+ r->relent.howto = &howto_table[reloc >> 6];
+ r->relent.sym_ptr_ptr = (asymbol **) NULL;
+ section->reloc_count++;
+
+ src += 2;
+ /* Fake up the data to look like it's got the -ve pc in it, this makes
+ it much easier to convert into other formats. This is done by
+ hitting the addend.
+ */
+ if (r->relent.howto->pc_relative == true)
+ {
+ r->relent.addend -= dst_ptr - dst_base_ptr;
+ }
+
+
+
+ }
+ break;
+ case RELOCATION_TYPE_COM:
+ BFD_FAIL ();
+ }
+ }
+ *dst_ptr++ = *src++;
+ }
+ }
+ }
+ }
+ break;
+ case oasys_record_is_local_enum:
+ case oasys_record_is_symbol_enum:
+ case oasys_record_is_section_enum:
+ break;
+ default:
+ loop = false;
+ }
+ }
+
+ return true;
+
+}
+
+static boolean
+oasys_new_section_hook (abfd, newsect)
+ bfd *abfd;
+ asection *newsect;
+{
+ newsect->used_by_bfd = (PTR)
+ bfd_alloc (abfd, sizeof (oasys_per_section_type));
+ if (!newsect->used_by_bfd)
+ return false;
+ oasys_per_section (newsect)->data = (bfd_byte *) NULL;
+ oasys_per_section (newsect)->section = newsect;
+ oasys_per_section (newsect)->offset = 0;
+ oasys_per_section (newsect)->initialized = false;
+ newsect->alignment_power = 1;
+ /* Turn the section string into an index */
+
+ sscanf (newsect->name, "%u", &newsect->target_index);
+
+ return true;
+}
+
+
+static long
+oasys_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ if (! oasys_slurp_section_data (abfd))
+ return -1;
+ return (asect->reloc_count + 1) * sizeof (arelent *);
+}
+
+static boolean
+oasys_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ oasys_per_section_type *p = (oasys_per_section_type *) section->used_by_bfd;
+ oasys_slurp_section_data (abfd);
+ if (p->initialized == false)
+ {
+ (void) memset (location, 0, (int) count);
+ }
+ else
+ {
+ (void) memcpy (location, (PTR) (p->data + offset), (int) count);
+ }
+ return true;
+}
+
+
+long
+oasys_canonicalize_reloc (ignore_abfd, section, relptr, symbols)
+ bfd *ignore_abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ unsigned int reloc_count = 0;
+ oasys_reloc_type *src = (oasys_reloc_type *) (section->relocation);
+ while (src != (oasys_reloc_type *) NULL)
+ {
+ abort ();
+
+#if 0
+ if (src->relent.section == (asection *) NULL)
+ {
+ src->relent.sym_ptr_ptr = symbols + src->symbol;
+ }
+#endif
+
+ *relptr++ = &src->relent;
+ src = src->next;
+ reloc_count++;
+ }
+ *relptr = (arelent *) NULL;
+ return section->reloc_count = reloc_count;
+}
+
+
+
+
+/* Writing */
+
+
+/* Calculate the checksum and write one record */
+static boolean
+oasys_write_record (abfd, type, record, size)
+ bfd *abfd;
+ oasys_record_enum_type type;
+ oasys_record_union_type *record;
+ size_t size;
+{
+ int checksum;
+ size_t i;
+ unsigned char *ptr;
+
+ record->header.length = size;
+ record->header.type = (int) type;
+ record->header.check_sum = 0;
+ record->header.fill = 0;
+ ptr = (unsigned char *) &record->pad[0];
+ checksum = 0;
+ for (i = 0; i < size; i++)
+ {
+ checksum += *ptr++;
+ }
+ record->header.check_sum = 0xff & (-checksum);
+ if (bfd_write ((PTR) record, 1, size, abfd) != size)
+ return false;
+ return true;
+}
+
+
+/* Write out all the symbols */
+static boolean
+oasys_write_syms (abfd)
+ bfd *abfd;
+{
+ unsigned int count;
+ asymbol **generic = bfd_get_outsymbols (abfd);
+ unsigned int index = 0;
+ for (count = 0; count < bfd_get_symcount (abfd); count++)
+ {
+
+ oasys_symbol_record_type symbol;
+ asymbol *CONST g = generic[count];
+
+ CONST char *src = g->name;
+ char *dst = symbol.name;
+ unsigned int l = 0;
+
+ if (bfd_is_com_section (g->section))
+ {
+ symbol.relb = RELOCATION_TYPE_COM;
+ bfd_h_put_16 (abfd, index, symbol.refno);
+ index++;
+ }
+ else if (bfd_is_abs_section (g->section))
+ {
+ symbol.relb = RELOCATION_TYPE_ABS;
+ bfd_h_put_16 (abfd, 0, symbol.refno);
+
+ }
+ else if (bfd_is_und_section (g->section))
+ {
+ symbol.relb = RELOCATION_TYPE_UND;
+ bfd_h_put_16 (abfd, index, symbol.refno);
+ /* Overload the value field with the output index number */
+ index++;
+ }
+ else if (g->flags & BSF_DEBUGGING)
+ {
+ /* throw it away */
+ continue;
+ }
+ else
+ {
+ if (g->section == (asection *) NULL)
+ {
+ /* Sometime, the oasys tools give out a symbol with illegal
+ bits in it, we'll output it in the same broken way */
+
+ symbol.relb = RELOCATION_TYPE_REL | 0;
+ }
+ else
+ {
+ symbol.relb = RELOCATION_TYPE_REL | g->section->output_section->target_index;
+ }
+ bfd_h_put_16 (abfd, 0, symbol.refno);
+ }
+#ifdef UNDERSCORE_HACK
+ if (src[l] == '_')
+ dst[l++] = '.';
+#endif
+ while (src[l])
+ {
+ dst[l] = src[l];
+ l++;
+ }
+
+ bfd_h_put_32 (abfd, g->value, symbol.value);
+
+
+ if (g->flags & BSF_LOCAL)
+ {
+ if (! oasys_write_record (abfd,
+ oasys_record_is_local_enum,
+ (oasys_record_union_type *) & symbol,
+ offsetof (oasys_symbol_record_type,
+ name[0]) + l))
+ return false;
+ }
+ else
+ {
+ if (! oasys_write_record (abfd,
+ oasys_record_is_symbol_enum,
+ (oasys_record_union_type *) & symbol,
+ offsetof (oasys_symbol_record_type,
+ name[0]) + l))
+ return false;
+ }
+ g->value = index - 1;
+ }
+
+ return true;
+}
+
+
+ /* Write a section header for each section */
+static boolean
+oasys_write_sections (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ static oasys_section_record_type out;
+
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ if (!isdigit (s->name[0]))
+ {
+ (*_bfd_error_handler)
+ ("%s: can not represent section `%s' in oasys",
+ bfd_get_filename (abfd), s->name);
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+ out.relb = RELOCATION_TYPE_REL | s->target_index;
+ bfd_h_put_32 (abfd, s->_cooked_size, out.value);
+ bfd_h_put_32 (abfd, s->vma, out.vma);
+
+ if (! oasys_write_record (abfd,
+ oasys_record_is_section_enum,
+ (oasys_record_union_type *) & out,
+ sizeof (out)))
+ return false;
+ }
+ return true;
+}
+
+static boolean
+oasys_write_header (abfd)
+ bfd *abfd;
+{
+ /* Create and write the header */
+ oasys_header_record_type r;
+ size_t length = strlen (abfd->filename);
+ if (length > (size_t) sizeof (r.module_name))
+ {
+ length = sizeof (r.module_name);
+ }
+
+ (void) memcpy (r.module_name,
+ abfd->filename,
+ length);
+ (void) memset (r.module_name + length,
+ ' ',
+ sizeof (r.module_name) - length);
+
+ r.version_number = OASYS_VERSION_NUMBER;
+ r.rev_number = OASYS_REV_NUMBER;
+ if (! oasys_write_record (abfd,
+ oasys_record_is_header_enum,
+ (oasys_record_union_type *) & r,
+ offsetof (oasys_header_record_type,
+ description[0])))
+ return false;
+
+ return true;
+}
+
+static boolean
+oasys_write_end (abfd)
+ bfd *abfd;
+{
+ oasys_end_record_type end;
+ unsigned char null = 0;
+ end.relb = RELOCATION_TYPE_ABS;
+ bfd_h_put_32 (abfd, abfd->start_address, end.entry);
+ bfd_h_put_16 (abfd, 0, end.fill);
+ end.zero = 0;
+ if (! oasys_write_record (abfd,
+ oasys_record_is_end_enum,
+ (oasys_record_union_type *) & end,
+ sizeof (end)))
+ return false;
+ if (bfd_write ((PTR) & null, 1, 1, abfd) != 1)
+ return false;
+ return true;
+}
+
+static int
+comp (ap, bp)
+ CONST PTR ap;
+ CONST PTR bp;
+{
+ arelent *a = *((arelent **) ap);
+ arelent *b = *((arelent **) bp);
+ return a->address - b->address;
+}
+
+/*
+ Writing data..
+
+*/
+static boolean
+oasys_write_data (abfd)
+ bfd *abfd;
+{
+ asection *s;
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_byte *raw_data = oasys_per_section (s)->data;
+ oasys_data_record_type processed_data;
+ bfd_size_type current_byte_index = 0;
+ unsigned int relocs_to_go = s->reloc_count;
+ arelent **p = s->orelocation;
+ if (s->reloc_count != 0)
+ {
+/* Sort the reloc records so it's easy to insert the relocs into the
+ data */
+
+ qsort (s->orelocation,
+ s->reloc_count,
+ sizeof (arelent **),
+ comp);
+ }
+ current_byte_index = 0;
+ processed_data.relb = s->target_index | RELOCATION_TYPE_REL;
+
+ while (current_byte_index < s->_cooked_size)
+ {
+ /* Scan forwards by eight bytes or however much is left and see if
+ there are any relocations going on */
+ bfd_byte *mod = &processed_data.data[0];
+ bfd_byte *dst = &processed_data.data[1];
+
+ unsigned int i = 0;
+ *mod = 0;
+
+
+ bfd_h_put_32 (abfd, s->vma + current_byte_index,
+ processed_data.addr);
+
+ /* Don't start a relocation unless you're sure you can finish it
+ within the same data record. The worst case relocation is a
+ 4-byte relocatable value which is split across two modification
+ bytes (1 relocation byte + 2 symbol reference bytes + 2 data +
+ 1 modification byte + 2 data = 8 bytes total). That's where
+ the magic number 8 comes from.
+ */
+ while (current_byte_index < s->_raw_size && dst <=
+ &processed_data.data[sizeof (processed_data.data) - 8])
+ {
+
+
+ if (relocs_to_go != 0)
+ {
+ arelent *r = *p;
+ reloc_howto_type *const how = r->howto;
+ /* There is a relocation, is it for this byte ? */
+ if (r->address == current_byte_index)
+ {
+ unsigned char rel_byte;
+
+ p++;
+ relocs_to_go--;
+
+ *mod |= (1 << i);
+ if (how->pc_relative)
+ {
+ rel_byte = RELOCATION_PCREL_BIT;
+
+ /* Also patch the raw data so that it doesn't have
+ the -ve stuff any more */
+ if (how->size != 2)
+ {
+ bfd_put_16 (abfd,
+ bfd_get_16 (abfd, raw_data) +
+ current_byte_index, raw_data);
+ }
+
+ else
+ {
+ bfd_put_32 (abfd,
+ bfd_get_32 (abfd, raw_data) +
+ current_byte_index, raw_data);
+ }
+ }
+ else
+ {
+ rel_byte = 0;
+ }
+ if (how->size == 2)
+ {
+ rel_byte |= RELOCATION_32BIT_BIT;
+ }
+
+ /* Is this a section relative relocation, or a symbol
+ relative relocation ? */
+ abort ();
+
+#if 0
+ if (r->section != (asection *) NULL)
+ {
+ /* The relent has a section attached, so it must be section
+ relative */
+ rel_byte |= RELOCATION_TYPE_REL;
+ rel_byte |= r->section->output_section->target_index;
+ *dst++ = rel_byte;
+ }
+ else
+#endif
+ {
+ asymbol *p = *(r->sym_ptr_ptr);
+
+ /* If this symbol has a section attached, then it
+ has already been resolved. Change from a symbol
+ ref to a section ref */
+ if (p->section != (asection *) NULL)
+ {
+ rel_byte |= RELOCATION_TYPE_REL;
+ rel_byte |=
+ p->section->output_section->target_index;
+ *dst++ = rel_byte;
+ }
+ else
+ {
+ rel_byte |= RELOCATION_TYPE_UND;
+ *dst++ = rel_byte;
+ /* Next two bytes are a symbol index - we can get
+ this from the symbol value which has been zapped
+ into the symbol index in the table when the
+ symbol table was written
+ */
+ *dst++ = p->value >> 8;
+ *dst++ = p->value;
+ }
+ }
+#define ADVANCE { if (++i >= 8) { i = 0; mod = dst++; *mod = 0; } current_byte_index++; }
+ /* relocations never occur from an unloadable section,
+ so we can assume that raw_data is not NULL
+ */
+ *dst++ = *raw_data++;
+ ADVANCE
+ * dst++ = *raw_data++;
+ ADVANCE
+ if (how->size == 2)
+ {
+ *dst++ = *raw_data++;
+ ADVANCE
+ * dst++ = *raw_data++;
+ ADVANCE
+ }
+ continue;
+ }
+ }
+ /* If this is coming from an unloadable section then copy
+ zeros */
+ if (raw_data == NULL)
+ {
+ *dst++ = 0;
+ }
+ else
+ {
+ *dst++ = *raw_data++;
+ }
+ ADVANCE
+ }
+
+ /* Don't write a useless null modification byte */
+ if (dst == mod + 1)
+ {
+ --dst;
+ }
+
+ if (! oasys_write_record (abfd,
+ oasys_record_is_data_enum,
+ ((oasys_record_union_type *)
+ & processed_data),
+ dst - (bfd_byte *) & processed_data))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+static boolean
+oasys_write_object_contents (abfd)
+ bfd *abfd;
+{
+ if (! oasys_write_header (abfd))
+ return false;
+ if (! oasys_write_syms (abfd))
+ return false;
+ if (! oasys_write_sections (abfd))
+ return false;
+ if (! oasys_write_data (abfd))
+ return false;
+ if (! oasys_write_end (abfd))
+ return false;
+ return true;
+}
+
+
+
+
+/** exec and core file sections */
+
+/* set section contents is complicated with OASYS since the format is
+* not a byte image, but a record stream.
+*/
+static boolean
+oasys_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)
+ {
+ if (oasys_per_section (section)->data == (bfd_byte *) NULL)
+ {
+ oasys_per_section (section)->data =
+ (bfd_byte *) (bfd_alloc (abfd, section->_cooked_size));
+ if (!oasys_per_section (section)->data)
+ return false;
+ }
+ (void) memcpy ((PTR) (oasys_per_section (section)->data + offset),
+ location,
+ (size_t) count);
+ }
+ 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. */
+
+static asymbol *
+oasys_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+
+ oasys_symbol_type *new =
+ (oasys_symbol_type *) bfd_zalloc (abfd, sizeof (oasys_symbol_type));
+ if (!new)
+ return NULL;
+ new->symbol.the_bfd = abfd;
+ return &new->symbol;
+}
+
+
+
+
+/* User should have checked the file flags; perhaps we should return
+BFD_NO_MORE_SYMBOLS if there are none? */
+
+static bfd *
+oasys_openr_next_archived_file (arch, prev)
+ bfd *arch;
+ bfd *prev;
+{
+ oasys_ar_data_type *ar = OASYS_AR_DATA (arch);
+ oasys_module_info_type *p;
+ /* take the next one from the arch state, or reset */
+ if (prev == (bfd *) NULL)
+ {
+ /* Reset the index - the first two entries are bogus*/
+ ar->module_index = 0;
+ }
+
+ p = ar->module + ar->module_index;
+ ar->module_index++;
+
+ if (ar->module_index <= ar->module_count)
+ {
+ if (p->abfd == (bfd *) NULL)
+ {
+ p->abfd = _bfd_create_empty_archive_element_shell (arch);
+ p->abfd->origin = p->pos;
+ p->abfd->filename = p->name;
+
+ /* Fixup a pointer to this element for the member */
+ p->abfd->arelt_data = (PTR) p;
+ }
+ return p->abfd;
+ }
+ else
+ {
+ bfd_set_error (bfd_error_no_more_archived_files);
+ return (bfd *) NULL;
+ }
+}
+
+static boolean
+oasys_find_nearest_line (abfd,
+ section,
+ symbols,
+ offset,
+ filename_ptr,
+ functionname_ptr,
+ line_ptr)
+ bfd *abfd;
+ asection *section;
+ asymbol **symbols;
+ bfd_vma offset;
+ char **filename_ptr;
+ char **functionname_ptr;
+ unsigned int *line_ptr;
+{
+ return false;
+
+}
+
+static int
+oasys_generic_stat_arch_elt (abfd, buf)
+ bfd *abfd;
+ struct stat *buf;
+{
+ oasys_module_info_type *mod = (oasys_module_info_type *) abfd->arelt_data;
+ if (mod == (oasys_module_info_type *) NULL)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return -1;
+ }
+ else
+ {
+ buf->st_size = mod->size;
+ buf->st_mode = 0666;
+ return 0;
+ }
+}
+
+static int
+oasys_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return 0;
+}
+
+#define oasys_close_and_cleanup _bfd_generic_close_and_cleanup
+#define oasys_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+
+#define oasys_slurp_armap bfd_true
+#define oasys_slurp_extended_name_table bfd_true
+#define oasys_construct_extended_name_table \
+ ((boolean (*) PARAMS ((bfd *, char **, bfd_size_type *, const char **))) \
+ bfd_true)
+#define oasys_truncate_arname bfd_dont_truncate_arname
+#define oasys_write_armap \
+ ((boolean (*) \
+ PARAMS ((bfd *, unsigned int, struct orl *, unsigned int, int))) \
+ bfd_true)
+#define oasys_read_ar_hdr bfd_nullvoidptr
+#define oasys_get_elt_at_index _bfd_generic_get_elt_at_index
+#define oasys_update_armap_timestamp bfd_true
+
+#define oasys_bfd_is_local_label bfd_generic_is_local_label
+#define oasys_get_lineno _bfd_nosymbols_get_lineno
+#define oasys_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define oasys_read_minisymbols _bfd_generic_read_minisymbols
+#define oasys_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define oasys_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define oasys_set_arch_mach bfd_default_set_arch_mach
+
+#define oasys_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#define oasys_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define oasys_bfd_relax_section bfd_generic_relax_section
+#define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define oasys_bfd_final_link _bfd_generic_final_link
+#define oasys_bfd_link_split_section _bfd_generic_link_split_section
+
+/*SUPPRESS 460 */
+const bfd_target oasys_vec =
+{
+ "oasys", /* name */
+ bfd_target_oasys_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* 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 */
+ 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,
+ oasys_object_p, /* bfd_check_format */
+ oasys_archive_p,
+ _bfd_dummy_target,
+ },
+ { /* bfd_set_format */
+ bfd_false,
+ oasys_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ oasys_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (oasys),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (oasys),
+ BFD_JUMP_TABLE_SYMBOLS (oasys),
+ BFD_JUMP_TABLE_RELOCS (oasys),
+ BFD_JUMP_TABLE_WRITE (oasys),
+ BFD_JUMP_TABLE_LINK (oasys),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/opncls.c b/contrib/gdb/bfd/opncls.c
new file mode 100644
index 0000000..54528db
--- /dev/null
+++ b/contrib/gdb/bfd/opncls.c
@@ -0,0 +1,604 @@
+/* opncls.c -- open and close a BFD.
+ Copyright (C) 1990 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "obstack.h"
+
+#ifndef S_IXUSR
+#define S_IXUSR 0100 /* Execute by owner. */
+#endif
+#ifndef S_IXGRP
+#define S_IXGRP 0010 /* Execute by group. */
+#endif
+#ifndef S_IXOTH
+#define S_IXOTH 0001 /* Execute by others. */
+#endif
+
+/* fdopen is a loser -- we should use stdio exclusively. Unfortunately
+ if we do that we can't use fcntl. */
+
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+#ifndef HAVE_GETPAGESIZE
+#define getpagesize() 2048
+#endif
+
+long _bfd_chunksize = -1;
+
+/* Return a new BFD. All BFD's are allocated through this routine. */
+
+bfd *
+_bfd_new_bfd ()
+{
+ bfd *nbfd;
+
+ nbfd = (bfd *)bfd_zmalloc (sizeof (bfd));
+ if (!nbfd)
+ return 0;
+
+ if (_bfd_chunksize <= 0)
+ {
+ _bfd_chunksize = getpagesize ();
+ if (_bfd_chunksize <= 0)
+ _bfd_chunksize = 2048;
+ /* Leave some slush space, since many malloc implementations
+ prepend a header, and may wind up wasting another page
+ because of it. */
+ _bfd_chunksize -= 32;
+ }
+
+ if (!obstack_begin(&nbfd->memory, _bfd_chunksize))
+ {
+ bfd_set_error (bfd_error_no_memory);
+ return 0;
+ }
+
+ nbfd->arch_info = &bfd_default_arch_struct;
+
+ nbfd->direction = no_direction;
+ nbfd->iostream = NULL;
+ nbfd->where = 0;
+ nbfd->sections = (asection *)NULL;
+ nbfd->format = bfd_unknown;
+ nbfd->my_archive = (bfd *)NULL;
+ nbfd->origin = 0;
+ nbfd->opened_once = false;
+ nbfd->output_has_begun = false;
+ nbfd->section_count = 0;
+ nbfd->usrdata = (PTR)NULL;
+ nbfd->cacheable = false;
+ nbfd->flags = NO_FLAGS;
+ nbfd->mtime_set = false;
+
+ return nbfd;
+}
+
+/* Allocate a new BFD as a member of archive OBFD. */
+
+bfd *
+_bfd_new_bfd_contained_in (obfd)
+ bfd *obfd;
+{
+ bfd *nbfd;
+
+ nbfd = _bfd_new_bfd();
+ nbfd->xvec = obfd->xvec;
+ nbfd->my_archive = obfd;
+ nbfd->direction = read_direction;
+ nbfd->target_defaulted = obfd->target_defaulted;
+ return nbfd;
+}
+
+/*
+SECTION
+ Opening and closing BFDs
+
+*/
+
+/*
+FUNCTION
+ bfd_openr
+
+SYNOPSIS
+ bfd *bfd_openr(CONST char *filename, CONST char *target);
+
+DESCRIPTION
+ Open the file @var{filename} (using <<fopen>>) with the target
+ @var{target}. Return a pointer to the created BFD.
+
+ Calls <<bfd_find_target>>, so @var{target} is interpreted as by
+ that function.
+
+ If <<NULL>> is returned then an error has occured. Possible errors
+ are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error.
+*/
+
+bfd *
+bfd_openr (filename, target)
+ CONST char *filename;
+ CONST char *target;
+{
+ bfd *nbfd;
+ const bfd_target *target_vec;
+
+ nbfd = _bfd_new_bfd();
+ if (nbfd == NULL)
+ return NULL;
+
+ target_vec = bfd_find_target (target, nbfd);
+ if (target_vec == NULL) {
+ bfd_set_error (bfd_error_invalid_target);
+ return NULL;
+ }
+
+ nbfd->filename = filename;
+ nbfd->direction = read_direction;
+
+ if (bfd_open_file (nbfd) == NULL) {
+ bfd_set_error (bfd_error_system_call); /* File didn't exist, or some such */
+ bfd_release(nbfd,0);
+ return NULL;
+ }
+ return nbfd;
+}
+
+
+/* Don't try to `optimize' this function:
+
+ o - We lock using stack space so that interrupting the locking
+ won't cause a storage leak.
+ o - We open the file stream last, since we don't want to have to
+ close it if anything goes wrong. Closing the stream means closing
+ the file descriptor too, even though we didn't open it.
+ */
+/*
+FUNCTION
+ bfd_fdopenr
+
+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>>.
+ It opens a BFD on a file already described by the @var{fd}
+ supplied.
+
+ When the file is later <<bfd_close>>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), 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
+ files.
+
+ Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
+*/
+
+bfd *
+bfd_fdopenr (filename, target, fd)
+ CONST char *filename;
+ CONST char *target;
+ int fd;
+{
+ bfd *nbfd;
+ const bfd_target *target_vec;
+ int fdflags;
+
+ bfd_set_error (bfd_error_system_call);
+#if ! defined(HAVE_FCNTL) || ! defined(F_GETFL)
+ fdflags = O_RDWR; /* Assume full access */
+#else
+ fdflags = fcntl (fd, F_GETFL, NULL);
+#endif
+ if (fdflags == -1) return NULL;
+
+ nbfd = _bfd_new_bfd();
+
+ if (nbfd == NULL)
+ return NULL;
+
+ target_vec = bfd_find_target (target, nbfd);
+ if (target_vec == NULL) {
+ bfd_set_error (bfd_error_invalid_target);
+ return NULL;
+ }
+#if defined(VMS) || defined(__GO32__) || defined (WINGDB)
+ nbfd->iostream = (PTR)fopen(filename, FOPEN_RB);
+#else
+ /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
+ switch (fdflags & (O_ACCMODE)) {
+ case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB); break;
+ case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break;
+ case O_RDWR: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break;
+ default: abort ();
+ }
+#endif
+ if (nbfd->iostream == NULL) {
+ (void) obstack_free (&nbfd->memory, (PTR)0);
+ return NULL;
+ }
+
+ /* OK, put everything where it belongs */
+
+ nbfd->filename = filename;
+
+ /* As a special case we allow a FD open for read/write to
+ be written through, although doing so requires that we end
+ the previous clause with a preposition. */
+ /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
+ switch (fdflags & (O_ACCMODE)) {
+ case O_RDONLY: nbfd->direction = read_direction; break;
+ case O_WRONLY: nbfd->direction = write_direction; break;
+ case O_RDWR: nbfd->direction = both_direction; break;
+ default: abort ();
+ }
+
+ if (! bfd_cache_init (nbfd))
+ return NULL;
+
+ return nbfd;
+}
+
+/*
+FUNCTION
+ bfd_openstreamr
+
+SYNOPSIS
+ bfd *bfd_openstreamr();
+
+DESCRIPTION
+
+ Open a BFD for read access on an existing stdio stream. When
+ the BFD is passed to <<bfd_close>>, the stream will be closed.
+*/
+
+bfd *
+bfd_openstreamr (filename, target, stream)
+ const char *filename;
+ const char *target;
+ FILE *stream;
+{
+ bfd *nbfd;
+ const bfd_target *target_vec;
+
+ nbfd = _bfd_new_bfd ();
+ if (nbfd == NULL)
+ return NULL;
+
+ target_vec = bfd_find_target (target, nbfd);
+ if (target_vec == NULL)
+ {
+ bfd_set_error (bfd_error_invalid_target);
+ return NULL;
+ }
+
+ nbfd->iostream = (PTR) stream;
+ nbfd->filename = filename;
+ nbfd->direction = read_direction;
+
+ if (! bfd_cache_init (nbfd))
+ return NULL;
+
+ return nbfd;
+}
+
+/** bfd_openw -- open for writing.
+ Returns a pointer to a freshly-allocated BFD on success, or NULL.
+
+ See comment by bfd_fdopenr before you try to modify this function. */
+
+/*
+FUNCTION
+ bfd_openw
+
+SYNOPSIS
+ bfd *bfd_openw(CONST char *filename, CONST char *target);
+
+DESCRIPTION
+ Create a BFD, associated with file @var{filename}, using the
+ file format @var{target}, and return a pointer to it.
+
+ Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
+ <<bfd_error_invalid_target>>.
+*/
+
+bfd *
+bfd_openw (filename, target)
+ CONST char *filename;
+ CONST char *target;
+{
+ bfd *nbfd;
+ const bfd_target *target_vec;
+
+ 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 = _bfd_new_bfd();
+ if (nbfd == NULL)
+ return NULL;
+
+ target_vec = bfd_find_target (target, nbfd);
+ if (target_vec == NULL) return NULL;
+
+ nbfd->filename = filename;
+ nbfd->direction = write_direction;
+
+ if (bfd_open_file (nbfd) == NULL) {
+ bfd_set_error (bfd_error_system_call); /* File not writeable, etc */
+ (void) obstack_free (&nbfd->memory, (PTR)0);
+ return NULL;
+ }
+ return nbfd;
+}
+
+/*
+
+FUNCTION
+ bfd_close
+
+SYNOPSIS
+ boolean bfd_close(bfd *abfd);
+
+DESCRIPTION
+
+ 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
+ <<chmod>> is called to mark it as such.
+
+ 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>>).
+
+RETURNS
+ <<true>> is returned if all is ok, otherwise <<false>>.
+*/
+
+
+boolean
+bfd_close (abfd)
+ bfd *abfd;
+{
+ boolean ret;
+
+ if (!bfd_read_p (abfd))
+ {
+ if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
+ return false;
+ }
+
+ if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
+ return false;
+
+ ret = bfd_cache_close (abfd);
+
+ /* If the file was open for writing and is now executable,
+ make it so */
+ if (ret
+ && abfd->direction == write_direction
+ && abfd->flags & EXEC_P)
+ {
+ struct stat buf;
+
+ if (stat (abfd->filename, &buf) == 0)
+ {
+ int mask = umask (0);
+ umask (mask);
+ chmod (abfd->filename,
+ (0777
+ & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
+ }
+ }
+
+ (void) obstack_free (&abfd->memory, (PTR)0);
+ (void) free (abfd);
+
+ return ret;
+}
+
+/*
+FUNCTION
+ bfd_close_all_done
+
+SYNOPSIS
+ boolean bfd_close_all_done(bfd *);
+
+DESCRIPTION
+ Close a BFD. Differs from <<bfd_close>>
+ 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.
+
+ If the created file is executable, then <<chmod>> is called
+ to mark it as such.
+
+ All memory attached to the BFD's obstacks is released.
+
+RETURNS
+ <<true>> is returned if all is ok, otherwise <<false>>.
+
+*/
+
+boolean
+bfd_close_all_done (abfd)
+ bfd *abfd;
+{
+ boolean ret;
+
+ ret = bfd_cache_close (abfd);
+
+ /* If the file was open for writing and is now executable,
+ make it so */
+ if (ret
+ && abfd->direction == write_direction
+ && abfd->flags & EXEC_P)
+ {
+ struct stat buf;
+
+ if (stat (abfd->filename, &buf) == 0)
+ {
+ int mask = umask (0);
+ umask (mask);
+ chmod (abfd->filename,
+ (0x777
+ & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
+ }
+ }
+ (void) obstack_free (&abfd->memory, (PTR)0);
+ (void) free(abfd);
+ return ret;
+}
+
+
+/*
+FUNCTION
+ bfd_alloc_size
+
+SYNOPSIS
+ bfd_size_type bfd_alloc_size(bfd *abfd);
+
+DESCRIPTION
+ Return the number of bytes in the obstacks connected to @var{abfd}.
+
+*/
+
+bfd_size_type
+bfd_alloc_size (abfd)
+ bfd *abfd;
+{
+ struct _obstack_chunk *chunk = abfd->memory.chunk;
+ size_t size = 0;
+ while (chunk) {
+ size += chunk->limit - &(chunk->contents[0]);
+ chunk = chunk->prev;
+ }
+ return size;
+}
+
+
+
+/*
+FUNCTION
+ bfd_create
+
+SYNOPSIS
+ bfd *bfd_create(CONST char *filename, bfd *templ);
+
+DESCRIPTION
+ Create a new BFD in the manner of
+ <<bfd_openw>>, but without opening a file. The new BFD
+ takes the target from the target used by @var{template}. The
+ format is always set to <<bfd_object>>.
+
+*/
+
+bfd *
+bfd_create (filename, templ)
+ CONST char *filename;
+ bfd *templ;
+{
+ bfd *nbfd = _bfd_new_bfd();
+ if (nbfd == (bfd *)NULL)
+ return (bfd *)NULL;
+ nbfd->filename = filename;
+ if(templ) {
+ nbfd->xvec = templ->xvec;
+ }
+ nbfd->direction = no_direction;
+ bfd_set_format(nbfd, bfd_object);
+ return nbfd;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_alloc_by_size_t
+
+SYNOPSIS
+ PTR bfd_alloc_by_size_t(bfd *abfd, size_t wanted);
+
+DESCRIPTION
+ Allocate a block of @var{wanted} bytes of memory in the obstack
+ attatched to <<abfd>> and return a pointer to it.
+*/
+
+
+PTR
+bfd_alloc_by_size_t (abfd, size)
+ bfd *abfd;
+ size_t size;
+{
+ PTR ret;
+
+ ret = obstack_alloc (&(abfd->memory), size);
+ if (ret == NULL)
+ bfd_set_error (bfd_error_no_memory);
+ return ret;
+}
+
+void
+bfd_alloc_grow (abfd, ptr, size)
+ bfd *abfd;
+ PTR ptr;
+ size_t size;
+{
+ (void) obstack_grow(&(abfd->memory), ptr, size);
+}
+
+PTR
+bfd_alloc_finish (abfd)
+ bfd *abfd;
+{
+ PTR ret;
+
+ ret = obstack_finish (&(abfd->memory));
+ if (ret == NULL)
+ bfd_set_error (bfd_error_no_memory);
+ return ret;
+}
+
+PTR
+bfd_alloc (abfd, size)
+ bfd *abfd;
+ size_t size;
+{
+ return bfd_alloc_by_size_t(abfd, (size_t)size);
+}
+
+PTR
+bfd_zalloc (abfd, size)
+ bfd *abfd;
+ size_t size;
+{
+ PTR res;
+ res = bfd_alloc(abfd, size);
+ if (res)
+ memset(res, 0, (size_t)size);
+ return res;
+}
diff --git a/contrib/gdb/bfd/osf-core.c b/contrib/gdb/bfd/osf-core.c
new file mode 100644
index 0000000..6d1df9b
--- /dev/null
+++ b/contrib/gdb/bfd/osf-core.c
@@ -0,0 +1,256 @@
+/* BFD back-end for OSF/1 core files.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file can only be compiled on systems which use OSF/1 style
+ core files. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/user.h>
+#include <sys/core.h>
+
+/* forward declarations */
+
+static asection *
+make_bfd_asection PARAMS ((bfd *, CONST char *, flagword, bfd_size_type,
+ bfd_vma, file_ptr));
+static asymbol *
+osf_core_make_empty_symbol PARAMS ((bfd *));
+static const bfd_target *
+osf_core_core_file_p PARAMS ((bfd *));
+static char *
+osf_core_core_file_failing_command PARAMS ((bfd *));
+static int
+osf_core_core_file_failing_signal PARAMS ((bfd *));
+static boolean
+osf_core_core_file_matches_executable_p PARAMS ((bfd *, bfd *));
+static void
+swap_abort PARAMS ((void));
+
+/* These are stored in the bfd's tdata */
+
+struct osf_core_struct
+{
+ int sig;
+ char cmd[MAXCOMLEN + 1];
+};
+
+#define core_hdr(bfd) ((bfd)->tdata.osf_core_data)
+#define core_signal(bfd) (core_hdr(bfd)->sig)
+#define core_command(bfd) (core_hdr(bfd)->cmd)
+
+static asection *
+make_bfd_asection (abfd, name, flags, _raw_size, vma, filepos)
+ bfd *abfd;
+ CONST char *name;
+ flagword flags;
+ bfd_size_type _raw_size;
+ bfd_vma vma;
+ file_ptr filepos;
+{
+ asection *asect;
+
+ asect = bfd_make_section_anyway (abfd, name);
+ if (!asect)
+ return NULL;
+
+ asect->flags = flags;
+ asect->_raw_size = _raw_size;
+ asect->vma = vma;
+ asect->filepos = filepos;
+ asect->alignment_power = 8;
+
+ return asect;
+}
+
+static asymbol *
+osf_core_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new)
+ new->the_bfd = abfd;
+ return new;
+}
+
+static const bfd_target *
+osf_core_core_file_p (abfd)
+ bfd *abfd;
+{
+ int val;
+ int i;
+ char *secname;
+ struct core_filehdr core_header;
+
+ val = bfd_read ((PTR)&core_header, 1, sizeof core_header, abfd);
+ if (val != sizeof core_header)
+ return NULL;
+
+ if (strncmp (core_header.magic, "Core", 4) != 0)
+ return NULL;
+
+ core_hdr (abfd) = (struct osf_core_struct *)
+ bfd_zalloc (abfd, sizeof (struct osf_core_struct));
+ if (!core_hdr (abfd))
+ return NULL;
+
+ strncpy (core_command (abfd), core_header.name, MAXCOMLEN + 1);
+ core_signal (abfd) = core_header.signo;
+
+ for (i = 0; i < core_header.nscns; i++)
+ {
+ struct core_scnhdr core_scnhdr;
+ flagword flags;
+
+ val = bfd_read ((PTR)&core_scnhdr, 1, sizeof core_scnhdr, abfd);
+ if (val != sizeof core_scnhdr)
+ break;
+
+ /* Skip empty sections. */
+ if (core_scnhdr.size == 0 || core_scnhdr.scnptr == 0)
+ continue;
+
+ switch (core_scnhdr.scntype)
+ {
+ case SCNRGN:
+ secname = ".data";
+ flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
+ break;
+ case SCNSTACK:
+ secname = ".stack";
+ flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
+ break;
+ case SCNREGS:
+ secname = ".reg";
+ flags = SEC_HAS_CONTENTS;
+ break;
+ default:
+ (*_bfd_error_handler) ("Unhandled OSF/1 core file section type %d\n",
+ core_scnhdr.scntype);
+ continue;
+ }
+
+ if (!make_bfd_asection (abfd, secname, flags,
+ (bfd_size_type) core_scnhdr.size,
+ (bfd_vma) core_scnhdr.vaddr,
+ (file_ptr) core_scnhdr.scnptr))
+ return NULL;
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+
+ return abfd->xvec;
+}
+
+static char *
+osf_core_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ return core_command (abfd);
+}
+
+/* ARGSUSED */
+static int
+osf_core_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_signal (abfd);
+}
+
+/* ARGSUSED */
+static boolean
+osf_core_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this point */
+}
+
+#define osf_core_get_symtab_upper_bound _bfd_nosymbols_get_symtab_upper_bound
+#define osf_core_get_symtab _bfd_nosymbols_get_symtab
+#define osf_core_print_symbol _bfd_nosymbols_print_symbol
+#define osf_core_get_symbol_info _bfd_nosymbols_get_symbol_info
+#define osf_core_bfd_is_local_label _bfd_nosymbols_bfd_is_local_label
+#define osf_core_get_lineno _bfd_nosymbols_get_lineno
+#define osf_core_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define osf_core_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define osf_core_read_minisymbols _bfd_nosymbols_read_minisymbols
+#define osf_core_minisymbol_to_symbol _bfd_nosymbols_minisymbol_to_symbol
+
+/* If somebody calls any byte-swapping routines, shoot them. */
+static void
+swap_abort()
+{
+ abort(); /* This way doesn't require any declaration for ANSI to fuck up */
+}
+#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 ((const bfd_byte *))) swap_abort )
+
+const bfd_target osf_core_vec =
+ {
+ "osf-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ 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 */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ osf_core_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (osf_core),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (osf_core),
+ 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/contrib/gdb/bfd/pc532-mach.c b/contrib/gdb/bfd/pc532-mach.c
new file mode 100644
index 0000000..73f4ac4
--- /dev/null
+++ b/contrib/gdb/bfd/pc532-mach.c
@@ -0,0 +1,121 @@
+/* BFD back-end for Mach3/532 a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Ian Dall
+ * 19-Apr-94
+ *
+ * Formerly part of aout-pc532-mach.c. Split out to allow more
+ * flexibility with multiple formats.
+ *
+ */
+/* This architecture has N_TXTOFF and N_TXTADDR defined as if
+ * N_HEADER_IN_TEXT, but the a_text entry (text size) does not include the
+ * space for the header. So we have N_HEADER_IN_TEXT defined to
+ * 1 and specially define our own N_TXTSIZE
+ */
+
+#define N_HEADER_IN_TEXT(x) 1
+#define N_TXTSIZE(x) ((x).a_text)
+
+
+#define TEXT_START_ADDR 0x10000 /* from old ld */
+#define TARGET_PAGE_SIZE 0x1000 /* from old ld, 032 & 532 are really 512/4k */
+
+/* Use a_entry of 0 to distinguish object files from OMAGIC executables */
+#define N_TXTADDR(x) \
+ (N_MAGIC(x) == OMAGIC ? \
+ ((x).a_entry < TEXT_START_ADDR? 0: TEXT_START_ADDR): \
+ (N_MAGIC(x) == NMAGIC? TEXT_START_ADDR: \
+ TEXT_START_ADDR + EXEC_BYTES_SIZE))
+
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+
+#define N_SHARED_LIB(x) 0
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_ns32k
+
+#define MY(OP) CAT(pc532machaout_,OP)
+
+/* Must be the same as aout-ns32k.c */
+#define NAME(x,y) CAT3(ns32kaout,_32_,y)
+
+#define TARGETNAME "a.out-pc532-mach"
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libaout.h"
+#include "libbfd.h"
+#include "aout/aout64.h"
+
+/* We can`t use the MYNS macro here for cpp reasons too subtle for me -- IWD */
+
+#define MY_bfd_reloc_type_lookup ns32kaout_bfd_reloc_type_lookup
+
+/* libaout doesn't use NAME for these ... */
+
+#define MY_get_section_contents aout_32_get_section_contents
+
+#define MY_text_includes_header 1
+
+#define MY_exec_header_not_counted 1
+
+#define MYNSX(OP) CAT(ns32kaout_,OP)
+reloc_howto_type *
+MYNSX(bfd_reloc_type_lookup)
+ PARAMS((bfd *abfd AND
+ bfd_reloc_code_real_type code));
+
+boolean
+MYNSX(write_object_contents)
+ PARAMS((bfd *abfd));
+
+static boolean
+MY(write_object_contents) (abfd)
+bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+#if CHOOSE_RELOC_SIZE
+ CHOOSE_RELOC_SIZE(abfd);
+#else
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+#endif
+
+ BFD_ASSERT (bfd_get_arch (abfd) == bfd_arch_ns32k);
+ switch (bfd_get_mach (abfd))
+ {
+ case 32032:
+ N_SET_MACHTYPE (*execp, M_NS32032);
+ break;
+ case 32532:
+ default:
+ N_SET_MACHTYPE (*execp, M_NS32532);
+ break;
+ }
+ N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);
+
+ WRITE_HEADERS(abfd, execp);
+
+ return true;
+}
+
+#define MY_write_object_contents MY(write_object_contents)
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/pe-arm.c b/contrib/gdb/bfd/pe-arm.c
new file mode 100644
index 0000000..fa97e2e
--- /dev/null
+++ b/contrib/gdb/bfd/pe-arm.c
@@ -0,0 +1,32 @@
+/* BFD back-end for ARM PECOFF files.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_LITTLE_SYM armpe_little_vec
+#define TARGET_LITTLE_NAME "pe-arm-little"
+#define TARGET_BIG_SYM armpe_big_vec
+#define TARGET_BIG_NAME "pe-arm-big"
+
+#define COFF_OBJ_WITH_PE
+#define COFF_WITH_PE
+#define PCRELOFFSET true
+
+#include "coff-arm.c"
diff --git a/contrib/gdb/bfd/pe-i386.c b/contrib/gdb/bfd/pe-i386.c
new file mode 100644
index 0000000..878993e
--- /dev/null
+++ b/contrib/gdb/bfd/pe-i386.c
@@ -0,0 +1,30 @@
+/* BFD back-end for Intel 386 PECOFF files.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+
+#define TARGET_SYM i386pe_vec
+#define TARGET_NAME "pe-i386"
+#define COFF_OBJ_WITH_PE
+#define COFF_WITH_PE
+#define PCRELOFFSET true
+#define TARGET_UNDERSCORE '_'
+#include "coff-i386.c"
diff --git a/contrib/gdb/bfd/pe-ppc.c b/contrib/gdb/bfd/pe-ppc.c
new file mode 100644
index 0000000..67fdda0
--- /dev/null
+++ b/contrib/gdb/bfd/pe-ppc.c
@@ -0,0 +1,39 @@
+/* BFD back-end for Intel 386 PECOFF files.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+
+#define E_FILENMLEN 18
+
+#define PPC
+
+#define TARGET_LITTLE_SYM bfd_powerpcle_pe_vec
+#define TARGET_LITTLE_NAME "pe-powerpcle"
+
+#define TARGET_BIG_SYM bfd_powerpc_pe_vec
+#define TARGET_BIG_NAME "pe-powerpc"
+
+#define COFF_OBJ_WITH_PE
+#define COFF_WITH_PE
+
+/* FIXME: verify PCRELOFFSET is always false */
+
+#include "coff-ppc.c"
diff --git a/contrib/gdb/bfd/pei-arm.c b/contrib/gdb/bfd/pei-arm.c
new file mode 100644
index 0000000..fd9d398
--- /dev/null
+++ b/contrib/gdb/bfd/pei-arm.c
@@ -0,0 +1,33 @@
+/* BFD back-end for arm PE IMAGE COFF files.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_LITTLE_SYM armpei_little_vec
+#define TARGET_LITTLE_NAME "pei-arm-little"
+#define TARGET_BIG_SYM armpei_big_vec
+#define TARGET_BIG_NAME "pei-arm-big"
+
+#define IMAGE_BASE NT_IMAGE_BASE
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define PCRELOFFSET true
+
+#include "coff-arm.c"
diff --git a/contrib/gdb/bfd/pei-i386.c b/contrib/gdb/bfd/pei-i386.c
new file mode 100644
index 0000000..8754e7c
--- /dev/null
+++ b/contrib/gdb/bfd/pei-i386.c
@@ -0,0 +1,33 @@
+/* BFD back-end for Intel 386 PE IMAGE COFF files.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#define TARGET_SYM i386pei_vec
+#define TARGET_NAME "pei-i386"
+#define IMAGE_BASE NT_IMAGE_BASE
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+#define PCRELOFFSET true
+#define TARGET_UNDERSCORE '_'
+#include "coff-i386.c"
+
+
+
diff --git a/contrib/gdb/bfd/pei-ppc.c b/contrib/gdb/bfd/pei-ppc.c
new file mode 100644
index 0000000..fc8f89f
--- /dev/null
+++ b/contrib/gdb/bfd/pei-ppc.c
@@ -0,0 +1,44 @@
+/* BFD back-end for Intel 386 PE IMAGE COFF files.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+/* setting up for a PE environment stolen directly from the i386 structure */
+#define E_FILNMLEN 18 /* # characters in a file name */
+
+#define PPC
+
+#define TARGET_LITTLE_SYM bfd_powerpcle_pei_vec
+#define TARGET_LITTLE_NAME "pei-powerpcle"
+
+#define TARGET_BIG_SYM bfd_powerpc_pei_vec
+#define TARGET_BIG_NAME "pei-powerpc"
+
+#define IMAGE_BASE NT_IMAGE_BASE
+
+#define COFF_IMAGE_WITH_PE
+#define COFF_WITH_PE
+
+/* FIXME: Verify PCRELOFFSET is always false */
+
+#include "coff-ppc.c"
+
+
+
diff --git a/contrib/gdb/bfd/peicode.h b/contrib/gdb/bfd/peicode.h
new file mode 100644
index 0000000..a7a4746
--- /dev/null
+++ b/contrib/gdb/bfd/peicode.h
@@ -0,0 +1,1861 @@
+/* Support for the generic parts of most COFF variants, for BFD.
+ Copyright 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+Most of this hacked by Steve Chamberlain,
+ sac@cygnus.com
+*/
+
+
+
+#define coff_bfd_print_private_bfd_data pe_print_private_bfd_data
+#define coff_mkobject pe_mkobject
+#define coff_mkobject_hook pe_mkobject_hook
+
+#ifndef GET_FCN_LNNOPTR
+#define GET_FCN_LNNOPTR(abfd, ext) \
+ bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#endif
+
+#ifndef GET_FCN_ENDNDX
+#define GET_FCN_ENDNDX(abfd, ext) \
+ bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
+#endif
+
+#ifndef PUT_FCN_LNNOPTR
+#define PUT_FCN_LNNOPTR(abfd, in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#endif
+#ifndef PUT_FCN_ENDNDX
+#define PUT_FCN_ENDNDX(abfd, in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
+#endif
+#ifndef GET_LNSZ_LNNO
+#define GET_LNSZ_LNNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_lnno)
+#endif
+#ifndef GET_LNSZ_SIZE
+#define GET_LNSZ_SIZE(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_size)
+#endif
+#ifndef PUT_LNSZ_LNNO
+#define PUT_LNSZ_LNNO(abfd, in, ext) bfd_h_put_16(abfd, in, (bfd_byte *)ext->x_sym.x_misc.x_lnsz.x_lnno)
+#endif
+#ifndef PUT_LNSZ_SIZE
+#define PUT_LNSZ_SIZE(abfd, in, ext) bfd_h_put_16(abfd, in, (bfd_byte*) ext->x_sym.x_misc.x_lnsz.x_size)
+#endif
+#ifndef GET_SCN_SCNLEN
+#define GET_SCN_SCNLEN(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_scn.x_scnlen)
+#endif
+#ifndef GET_SCN_NRELOC
+#define GET_SCN_NRELOC(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *)ext->x_scn.x_nreloc)
+#endif
+#ifndef GET_SCN_NLINNO
+#define GET_SCN_NLINNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *)ext->x_scn.x_nlinno)
+#endif
+#ifndef PUT_SCN_SCNLEN
+#define PUT_SCN_SCNLEN(abfd,in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_scn.x_scnlen)
+#endif
+#ifndef PUT_SCN_NRELOC
+#define PUT_SCN_NRELOC(abfd,in, ext) bfd_h_put_16(abfd, in, (bfd_byte *)ext->x_scn.x_nreloc)
+#endif
+#ifndef PUT_SCN_NLINNO
+#define PUT_SCN_NLINNO(abfd,in, ext) bfd_h_put_16(abfd,in, (bfd_byte *) ext->x_scn.x_nlinno)
+#endif
+#ifndef GET_LINENO_LNNO
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_16(abfd, (bfd_byte *) (ext->l_lnno));
+#endif
+#ifndef PUT_LINENO_LNNO
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_16(abfd,val, (bfd_byte *) (ext->l_lnno));
+#endif
+
+/* The f_symptr field in the filehdr is sometimes 64 bits. */
+#ifndef GET_FILEHDR_SYMPTR
+#define GET_FILEHDR_SYMPTR bfd_h_get_32
+#endif
+#ifndef PUT_FILEHDR_SYMPTR
+#define PUT_FILEHDR_SYMPTR bfd_h_put_32
+#endif
+
+/* Some fields in the aouthdr are sometimes 64 bits. */
+#ifndef GET_AOUTHDR_TSIZE
+#define GET_AOUTHDR_TSIZE bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_TSIZE
+#define PUT_AOUTHDR_TSIZE bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_DSIZE
+#define GET_AOUTHDR_DSIZE bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_DSIZE
+#define PUT_AOUTHDR_DSIZE bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_BSIZE
+#define GET_AOUTHDR_BSIZE bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_BSIZE
+#define PUT_AOUTHDR_BSIZE bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_ENTRY
+#define GET_AOUTHDR_ENTRY bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_ENTRY
+#define PUT_AOUTHDR_ENTRY bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_TEXT_START
+#define GET_AOUTHDR_TEXT_START bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_TEXT_START
+#define PUT_AOUTHDR_TEXT_START bfd_h_put_32
+#endif
+#ifndef GET_AOUTHDR_DATA_START
+#define GET_AOUTHDR_DATA_START bfd_h_get_32
+#endif
+#ifndef PUT_AOUTHDR_DATA_START
+#define PUT_AOUTHDR_DATA_START bfd_h_put_32
+#endif
+
+/* Some fields in the scnhdr are sometimes 64 bits. */
+#ifndef GET_SCNHDR_PADDR
+#define GET_SCNHDR_PADDR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_PADDR
+#define PUT_SCNHDR_PADDR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_VADDR
+#define GET_SCNHDR_VADDR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_VADDR
+#define PUT_SCNHDR_VADDR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_SIZE
+#define GET_SCNHDR_SIZE bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_SIZE
+#define PUT_SCNHDR_SIZE bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_SCNPTR
+#define GET_SCNHDR_SCNPTR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_SCNPTR
+#define PUT_SCNHDR_SCNPTR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_RELPTR
+#define GET_SCNHDR_RELPTR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_RELPTR
+#define PUT_SCNHDR_RELPTR bfd_h_put_32
+#endif
+#ifndef GET_SCNHDR_LNNOPTR
+#define GET_SCNHDR_LNNOPTR bfd_h_get_32
+#endif
+#ifndef PUT_SCNHDR_LNNOPTR
+#define PUT_SCNHDR_LNNOPTR bfd_h_put_32
+#endif
+
+
+
+/**********************************************************************/
+
+static void
+coff_swap_reloc_in (abfd, src, dst)
+ bfd *abfd;
+ PTR src;
+ PTR dst;
+{
+ RELOC *reloc_src = (RELOC *) src;
+ struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
+
+ reloc_dst->r_vaddr = bfd_h_get_32(abfd, (bfd_byte *)reloc_src->r_vaddr);
+ reloc_dst->r_symndx = bfd_h_get_signed_32(abfd, (bfd_byte *) reloc_src->r_symndx);
+
+ reloc_dst->r_type = bfd_h_get_16(abfd, (bfd_byte *) reloc_src->r_type);
+
+#ifdef SWAP_IN_RELOC_OFFSET
+ reloc_dst->r_offset = SWAP_IN_RELOC_OFFSET(abfd,
+ (bfd_byte *) reloc_src->r_offset);
+#endif
+}
+
+
+static unsigned int
+coff_swap_reloc_out (abfd, src, dst)
+ bfd *abfd;
+ PTR src;
+ PTR dst;
+{
+ struct internal_reloc *reloc_src = (struct internal_reloc *)src;
+ struct external_reloc *reloc_dst = (struct external_reloc *)dst;
+ bfd_h_put_32(abfd, reloc_src->r_vaddr, (bfd_byte *) reloc_dst->r_vaddr);
+ bfd_h_put_32(abfd, reloc_src->r_symndx, (bfd_byte *) reloc_dst->r_symndx);
+
+ bfd_h_put_16(abfd, reloc_src->r_type, (bfd_byte *)
+ reloc_dst->r_type);
+
+#ifdef SWAP_OUT_RELOC_OFFSET
+ SWAP_OUT_RELOC_OFFSET(abfd,
+ reloc_src->r_offset,
+ (bfd_byte *) reloc_dst->r_offset);
+#endif
+#ifdef SWAP_OUT_RELOC_EXTRA
+ SWAP_OUT_RELOC_EXTRA(abfd,reloc_src, reloc_dst);
+#endif
+ return sizeof(struct external_reloc);
+}
+
+
+static void
+coff_swap_filehdr_in (abfd, src, dst)
+ bfd *abfd;
+ PTR src;
+ PTR dst;
+{
+ FILHDR *filehdr_src = (FILHDR *) src;
+ struct internal_filehdr *filehdr_dst = (struct internal_filehdr *) dst;
+ filehdr_dst->f_magic = bfd_h_get_16(abfd, (bfd_byte *) filehdr_src->f_magic);
+ filehdr_dst->f_nscns = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_nscns);
+ filehdr_dst->f_timdat = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_timdat);
+
+ filehdr_dst->f_nsyms = bfd_h_get_32(abfd, (bfd_byte *)filehdr_src-> f_nsyms);
+ filehdr_dst->f_flags = bfd_h_get_16(abfd, (bfd_byte *)filehdr_src-> f_flags);
+ filehdr_dst->f_symptr = bfd_h_get_32 (abfd, (bfd_byte *) filehdr_src->f_symptr);
+
+ /* Other people's tools sometimes generate headers
+ with an nsyms but a zero symptr. */
+ if (filehdr_dst->f_nsyms && filehdr_dst->f_symptr)
+ {
+ filehdr_dst->f_flags |= HAS_SYMS;
+ }
+ else
+ {
+ filehdr_dst->f_symptr = 0;
+ filehdr_dst->f_nsyms = 0;
+ filehdr_dst->f_flags &= ~HAS_SYMS;
+ }
+
+ filehdr_dst->f_opthdr = bfd_h_get_16(abfd,
+ (bfd_byte *)filehdr_src-> f_opthdr);
+}
+
+#ifdef COFF_IMAGE_WITH_PE
+
+static unsigned int
+coff_swap_filehdr_out (abfd, in, out)
+ bfd *abfd;
+ PTR in;
+ PTR out;
+{
+ int idx;
+ struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in;
+ FILHDR *filehdr_out = (FILHDR *)out;
+
+ if (pe_data (abfd)->has_reloc_section)
+ filehdr_in->f_flags &= ~F_RELFLG;
+
+ if (pe_data (abfd)->dll)
+ filehdr_in->f_flags |= F_DLL;
+
+ filehdr_in->pe.e_magic = DOSMAGIC;
+ filehdr_in->pe.e_cblp = 0x90;
+ filehdr_in->pe.e_cp = 0x3;
+ filehdr_in->pe.e_crlc = 0x0;
+ filehdr_in->pe.e_cparhdr = 0x4;
+ filehdr_in->pe.e_minalloc = 0x0;
+ filehdr_in->pe.e_maxalloc = 0xffff;
+ filehdr_in->pe.e_ss = 0x0;
+ filehdr_in->pe.e_sp = 0xb8;
+ filehdr_in->pe.e_csum = 0x0;
+ filehdr_in->pe.e_ip = 0x0;
+ filehdr_in->pe.e_cs = 0x0;
+ filehdr_in->pe.e_lfarlc = 0x40;
+ filehdr_in->pe.e_ovno = 0x0;
+
+ for (idx=0; idx < 4; idx++)
+ filehdr_in->pe.e_res[idx] = 0x0;
+
+ filehdr_in->pe.e_oemid = 0x0;
+ filehdr_in->pe.e_oeminfo = 0x0;
+
+ for (idx=0; idx < 10; idx++)
+ filehdr_in->pe.e_res2[idx] = 0x0;
+
+ filehdr_in->pe.e_lfanew = 0x80;
+
+ /* this next collection of data are mostly just characters. It appears
+ to be constant within the headers put on NT exes */
+ filehdr_in->pe.dos_message[0] = 0x0eba1f0e;
+ filehdr_in->pe.dos_message[1] = 0xcd09b400;
+ filehdr_in->pe.dos_message[2] = 0x4c01b821;
+ filehdr_in->pe.dos_message[3] = 0x685421cd;
+ filehdr_in->pe.dos_message[4] = 0x70207369;
+ filehdr_in->pe.dos_message[5] = 0x72676f72;
+ filehdr_in->pe.dos_message[6] = 0x63206d61;
+ filehdr_in->pe.dos_message[7] = 0x6f6e6e61;
+ filehdr_in->pe.dos_message[8] = 0x65622074;
+ filehdr_in->pe.dos_message[9] = 0x6e757220;
+ filehdr_in->pe.dos_message[10] = 0x206e6920;
+ filehdr_in->pe.dos_message[11] = 0x20534f44;
+ filehdr_in->pe.dos_message[12] = 0x65646f6d;
+ filehdr_in->pe.dos_message[13] = 0x0a0d0d2e;
+ filehdr_in->pe.dos_message[14] = 0x24;
+ filehdr_in->pe.dos_message[15] = 0x0;
+ filehdr_in->pe.nt_signature = NT_SIGNATURE;
+
+
+
+ bfd_h_put_16(abfd, filehdr_in->f_magic, (bfd_byte *) filehdr_out->f_magic);
+ bfd_h_put_16(abfd, filehdr_in->f_nscns, (bfd_byte *) filehdr_out->f_nscns);
+
+ bfd_h_put_32(abfd, time (0), (bfd_byte *) filehdr_out->f_timdat);
+ PUT_FILEHDR_SYMPTR (abfd, (bfd_vma) filehdr_in->f_symptr,
+ (bfd_byte *) filehdr_out->f_symptr);
+ bfd_h_put_32(abfd, filehdr_in->f_nsyms, (bfd_byte *) filehdr_out->f_nsyms);
+ bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr);
+ bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags);
+
+ /* put in extra dos header stuff. This data remains essentially
+ constant, it just has to be tacked on to the beginning of all exes
+ for NT */
+ bfd_h_put_16(abfd, filehdr_in->pe.e_magic, (bfd_byte *) filehdr_out->e_magic);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_cblp, (bfd_byte *) filehdr_out->e_cblp);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_cp, (bfd_byte *) filehdr_out->e_cp);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_crlc, (bfd_byte *) filehdr_out->e_crlc);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_cparhdr,
+ (bfd_byte *) filehdr_out->e_cparhdr);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_minalloc,
+ (bfd_byte *) filehdr_out->e_minalloc);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_maxalloc,
+ (bfd_byte *) filehdr_out->e_maxalloc);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_ss, (bfd_byte *) filehdr_out->e_ss);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_sp, (bfd_byte *) filehdr_out->e_sp);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_csum, (bfd_byte *) filehdr_out->e_csum);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_ip, (bfd_byte *) filehdr_out->e_ip);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_cs, (bfd_byte *) filehdr_out->e_cs);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_lfarlc, (bfd_byte *) filehdr_out->e_lfarlc);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_ovno, (bfd_byte *) filehdr_out->e_ovno);
+ {
+ int idx;
+ for (idx=0; idx < 4; idx++)
+ bfd_h_put_16(abfd, filehdr_in->pe.e_res[idx],
+ (bfd_byte *) filehdr_out->e_res[idx]);
+ }
+ bfd_h_put_16(abfd, filehdr_in->pe.e_oemid, (bfd_byte *) filehdr_out->e_oemid);
+ bfd_h_put_16(abfd, filehdr_in->pe.e_oeminfo,
+ (bfd_byte *) filehdr_out->e_oeminfo);
+ {
+ int idx;
+ for (idx=0; idx < 10; idx++)
+ bfd_h_put_16(abfd, filehdr_in->pe.e_res2[idx],
+ (bfd_byte *) filehdr_out->e_res2[idx]);
+ }
+ bfd_h_put_32(abfd, filehdr_in->pe.e_lfanew, (bfd_byte *) filehdr_out->e_lfanew);
+
+ {
+ int idx;
+ for (idx=0; idx < 16; idx++)
+ bfd_h_put_32(abfd, filehdr_in->pe.dos_message[idx],
+ (bfd_byte *) filehdr_out->dos_message[idx]);
+ }
+
+ /* also put in the NT signature */
+ bfd_h_put_32(abfd, filehdr_in->pe.nt_signature,
+ (bfd_byte *) filehdr_out->nt_signature);
+
+
+
+
+ return sizeof(FILHDR);
+}
+#else
+
+static unsigned int
+coff_swap_filehdr_out (abfd, in, out)
+ bfd *abfd;
+ PTR in;
+ PTR out;
+{
+ struct internal_filehdr *filehdr_in = (struct internal_filehdr *)in;
+ FILHDR *filehdr_out = (FILHDR *)out;
+
+ bfd_h_put_16(abfd, filehdr_in->f_magic, (bfd_byte *) filehdr_out->f_magic);
+ bfd_h_put_16(abfd, filehdr_in->f_nscns, (bfd_byte *) filehdr_out->f_nscns);
+ bfd_h_put_32(abfd, filehdr_in->f_timdat, (bfd_byte *) filehdr_out->f_timdat);
+ PUT_FILEHDR_SYMPTR (abfd, (bfd_vma) filehdr_in->f_symptr,
+ (bfd_byte *) filehdr_out->f_symptr);
+ bfd_h_put_32(abfd, filehdr_in->f_nsyms, (bfd_byte *) filehdr_out->f_nsyms);
+ bfd_h_put_16(abfd, filehdr_in->f_opthdr, (bfd_byte *) filehdr_out->f_opthdr);
+ bfd_h_put_16(abfd, filehdr_in->f_flags, (bfd_byte *) filehdr_out->f_flags);
+
+ return sizeof(FILHDR);
+}
+
+#endif
+
+
+static void
+coff_swap_sym_in (abfd, ext1, in1)
+ bfd *abfd;
+ PTR ext1;
+ PTR in1;
+{
+ SYMENT *ext = (SYMENT *)ext1;
+ struct internal_syment *in = (struct internal_syment *)in1;
+
+ if( ext->e.e_name[0] == 0) {
+ in->_n._n_n._n_zeroes = 0;
+ in->_n._n_n._n_offset = bfd_h_get_32(abfd, (bfd_byte *) ext->e.e.e_offset);
+ }
+ else {
+#if SYMNMLEN != E_SYMNMLEN
+ -> Error, we need to cope with truncating or extending SYMNMLEN!;
+#else
+ memcpy(in->_n._n_name, ext->e.e_name, SYMNMLEN);
+#endif
+ }
+
+ in->n_value = bfd_h_get_32(abfd, (bfd_byte *) ext->e_value);
+ in->n_scnum = bfd_h_get_16(abfd, (bfd_byte *) ext->e_scnum);
+ if (sizeof(ext->e_type) == 2){
+ in->n_type = bfd_h_get_16(abfd, (bfd_byte *) ext->e_type);
+ }
+ else {
+ in->n_type = bfd_h_get_32(abfd, (bfd_byte *) ext->e_type);
+ }
+ in->n_sclass = bfd_h_get_8(abfd, ext->e_sclass);
+ in->n_numaux = bfd_h_get_8(abfd, ext->e_numaux);
+
+ /* The section symbols for the .idata$ sections have class 68, which MS
+ documentation indicates is a section symbol. The problem is that the
+ value field in the symbol is simply a copy of the .idata section's flags
+ rather than something useful. When these symbols are encountered, change
+ the value to 0 and the section number to 1 so that they will be handled
+ somewhat correctly in the bfd code. */
+ if (in->n_sclass == 0x68) {
+ in->n_value = 0x0;
+ in->n_scnum = 1;
+ /* I have tried setting the class to 3 and using the following to set
+ the section number. This will put the address of the pointer to the
+ string kernel32.dll at addresses 0 and 0x10 off start of idata section
+ which is not correct */
+ /* if (strcmp (in->_n._n_name, ".idata$4") == 0) */
+ /* in->n_scnum = 3; */
+ /* else */
+ /* in->n_scnum = 2; */
+ }
+
+#ifdef coff_swap_sym_in_hook
+ coff_swap_sym_in_hook(abfd, ext1, in1);
+#endif
+}
+
+static unsigned int
+coff_swap_sym_out (abfd, inp, extp)
+ bfd *abfd;
+ PTR inp;
+ PTR extp;
+{
+ struct internal_syment *in = (struct internal_syment *)inp;
+ SYMENT *ext =(SYMENT *)extp;
+ if(in->_n._n_name[0] == 0) {
+ bfd_h_put_32(abfd, 0, (bfd_byte *) ext->e.e.e_zeroes);
+ bfd_h_put_32(abfd, in->_n._n_n._n_offset, (bfd_byte *) ext->e.e.e_offset);
+ }
+ else {
+#if SYMNMLEN != E_SYMNMLEN
+ -> Error, we need to cope with truncating or extending SYMNMLEN!;
+#else
+ memcpy(ext->e.e_name, in->_n._n_name, SYMNMLEN);
+#endif
+ }
+
+ bfd_h_put_32(abfd, in->n_value , (bfd_byte *) ext->e_value);
+ bfd_h_put_16(abfd, in->n_scnum , (bfd_byte *) ext->e_scnum);
+ if (sizeof(ext->e_type) == 2)
+ {
+ bfd_h_put_16(abfd, in->n_type , (bfd_byte *) ext->e_type);
+ }
+ else
+ {
+ bfd_h_put_32(abfd, in->n_type , (bfd_byte *) ext->e_type);
+ }
+ bfd_h_put_8(abfd, in->n_sclass , ext->e_sclass);
+ bfd_h_put_8(abfd, in->n_numaux , ext->e_numaux);
+
+ return sizeof(SYMENT);
+}
+
+static void
+coff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1)
+ bfd *abfd;
+ PTR ext1;
+ int type;
+ int class;
+ int indx;
+ int numaux;
+ PTR in1;
+{
+ AUXENT *ext = (AUXENT *)ext1;
+ union internal_auxent *in = (union internal_auxent *)in1;
+
+ switch (class) {
+ case C_FILE:
+ if (ext->x_file.x_fname[0] == 0) {
+ in->x_file.x_n.x_zeroes = 0;
+ in->x_file.x_n.x_offset =
+ bfd_h_get_32(abfd, (bfd_byte *) ext->x_file.x_n.x_offset);
+ } else {
+#if FILNMLEN != E_FILNMLEN
+ -> Error, we need to cope with truncating or extending FILNMLEN!;
+#else
+ memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN);
+#endif
+ }
+ return;
+
+
+ case C_STAT:
+#ifdef C_LEAFSTAT
+ case C_LEAFSTAT:
+#endif
+ case C_HIDDEN:
+ if (type == T_NULL) {
+ in->x_scn.x_scnlen = GET_SCN_SCNLEN(abfd, ext);
+ in->x_scn.x_nreloc = GET_SCN_NRELOC(abfd, ext);
+ in->x_scn.x_nlinno = GET_SCN_NLINNO(abfd, ext);
+ return;
+ }
+ break;
+ }
+
+ in->x_sym.x_tagndx.l = bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_tagndx);
+#ifndef NO_TVNDX
+ in->x_sym.x_tvndx = bfd_h_get_16(abfd, (bfd_byte *) ext->x_sym.x_tvndx);
+#endif
+
+ if (class == C_BLOCK || ISFCN (type) || ISTAG (class))
+ {
+ in->x_sym.x_fcnary.x_fcn.x_lnnoptr = GET_FCN_LNNOPTR (abfd, ext);
+ in->x_sym.x_fcnary.x_fcn.x_endndx.l = GET_FCN_ENDNDX (abfd, ext);
+ }
+ else
+ {
+#if DIMNUM != E_DIMNUM
+ #error we need to cope with truncating or extending DIMNUM
+#endif
+ in->x_sym.x_fcnary.x_ary.x_dimen[0] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
+ in->x_sym.x_fcnary.x_ary.x_dimen[1] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
+ in->x_sym.x_fcnary.x_ary.x_dimen[2] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
+ in->x_sym.x_fcnary.x_ary.x_dimen[3] =
+ bfd_h_get_16 (abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
+ }
+
+ if (ISFCN(type)) {
+ in->x_sym.x_misc.x_fsize = bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_misc.x_fsize);
+ }
+ else {
+ in->x_sym.x_misc.x_lnsz.x_lnno = GET_LNSZ_LNNO(abfd, ext);
+ in->x_sym.x_misc.x_lnsz.x_size = GET_LNSZ_SIZE(abfd, ext);
+ }
+}
+
+static unsigned int
+coff_swap_aux_out (abfd, inp, type, class, indx, numaux, extp)
+ bfd *abfd;
+ PTR inp;
+ int type;
+ int class;
+ int indx;
+ int numaux;
+ PTR extp;
+{
+ union internal_auxent *in = (union internal_auxent *)inp;
+ AUXENT *ext = (AUXENT *)extp;
+
+ memset((PTR)ext, 0, AUXESZ);
+ switch (class) {
+ case C_FILE:
+ if (in->x_file.x_fname[0] == 0) {
+ bfd_h_put_32(abfd, 0, (bfd_byte *) ext->x_file.x_n.x_zeroes);
+ bfd_h_put_32(abfd,
+ in->x_file.x_n.x_offset,
+ (bfd_byte *) ext->x_file.x_n.x_offset);
+ }
+ else {
+#if FILNMLEN != E_FILNMLEN
+ -> Error, we need to cope with truncating or extending FILNMLEN!;
+#else
+ memcpy (ext->x_file.x_fname, in->x_file.x_fname, FILNMLEN);
+#endif
+ }
+ return sizeof (AUXENT);
+
+
+ case C_STAT:
+#ifdef C_LEAFSTAT
+ case C_LEAFSTAT:
+#endif
+ case C_HIDDEN:
+ if (type == T_NULL) {
+ PUT_SCN_SCNLEN(abfd, in->x_scn.x_scnlen, ext);
+ PUT_SCN_NRELOC(abfd, in->x_scn.x_nreloc, ext);
+ PUT_SCN_NLINNO(abfd, in->x_scn.x_nlinno, ext);
+ return sizeof (AUXENT);
+ }
+ break;
+ }
+
+ bfd_h_put_32(abfd, in->x_sym.x_tagndx.l, (bfd_byte *) ext->x_sym.x_tagndx);
+#ifndef NO_TVNDX
+ bfd_h_put_16(abfd, in->x_sym.x_tvndx , (bfd_byte *) ext->x_sym.x_tvndx);
+#endif
+
+ if (class == C_BLOCK || ISFCN (type) || ISTAG (class))
+ {
+ PUT_FCN_LNNOPTR(abfd, in->x_sym.x_fcnary.x_fcn.x_lnnoptr, ext);
+ PUT_FCN_ENDNDX(abfd, in->x_sym.x_fcnary.x_fcn.x_endndx.l, ext);
+ }
+ else
+ {
+#if DIMNUM != E_DIMNUM
+ #error we need to cope with truncating or extending DIMNUM
+#endif
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[0],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[0]);
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[1],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[1]);
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[2],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[2]);
+ bfd_h_put_16 (abfd, in->x_sym.x_fcnary.x_ary.x_dimen[3],
+ (bfd_byte *) ext->x_sym.x_fcnary.x_ary.x_dimen[3]);
+ }
+
+ if (ISFCN (type))
+ bfd_h_put_32 (abfd, in->x_sym.x_misc.x_fsize,
+ (bfd_byte *) ext->x_sym.x_misc.x_fsize);
+ else
+ {
+ PUT_LNSZ_LNNO (abfd, in->x_sym.x_misc.x_lnsz.x_lnno, ext);
+ PUT_LNSZ_SIZE (abfd, in->x_sym.x_misc.x_lnsz.x_size, ext);
+ }
+
+ return sizeof(AUXENT);
+}
+
+
+static void
+coff_swap_lineno_in (abfd, ext1, in1)
+ bfd *abfd;
+ PTR ext1;
+ PTR in1;
+{
+ LINENO *ext = (LINENO *)ext1;
+ struct internal_lineno *in = (struct internal_lineno *)in1;
+
+ in->l_addr.l_symndx = bfd_h_get_32(abfd, (bfd_byte *) ext->l_addr.l_symndx);
+ in->l_lnno = GET_LINENO_LNNO(abfd, ext);
+}
+
+static unsigned int
+coff_swap_lineno_out (abfd, inp, outp)
+ bfd *abfd;
+ PTR inp;
+ PTR outp;
+{
+ struct internal_lineno *in = (struct internal_lineno *)inp;
+ struct external_lineno *ext = (struct external_lineno *)outp;
+ bfd_h_put_32(abfd, in->l_addr.l_symndx, (bfd_byte *)
+ ext->l_addr.l_symndx);
+
+ PUT_LINENO_LNNO (abfd, in->l_lnno, ext);
+ return sizeof(struct external_lineno);
+}
+
+
+
+static void
+coff_swap_aouthdr_in (abfd, aouthdr_ext1, aouthdr_int1)
+ bfd *abfd;
+ PTR aouthdr_ext1;
+ PTR aouthdr_int1;
+{
+ struct internal_extra_pe_aouthdr *a;
+ PEAOUTHDR *src = (PEAOUTHDR *)(aouthdr_ext1);
+ AOUTHDR *aouthdr_ext = (AOUTHDR *) aouthdr_ext1;
+ struct internal_aouthdr *aouthdr_int = (struct internal_aouthdr *)aouthdr_int1;
+
+ aouthdr_int->magic = bfd_h_get_16(abfd, (bfd_byte *) aouthdr_ext->magic);
+ aouthdr_int->vstamp = bfd_h_get_16(abfd, (bfd_byte *) aouthdr_ext->vstamp);
+ aouthdr_int->tsize =
+ GET_AOUTHDR_TSIZE (abfd, (bfd_byte *) aouthdr_ext->tsize);
+ aouthdr_int->dsize =
+ GET_AOUTHDR_DSIZE (abfd, (bfd_byte *) aouthdr_ext->dsize);
+ aouthdr_int->bsize =
+ GET_AOUTHDR_BSIZE (abfd, (bfd_byte *) aouthdr_ext->bsize);
+ aouthdr_int->entry =
+ GET_AOUTHDR_ENTRY (abfd, (bfd_byte *) aouthdr_ext->entry);
+ aouthdr_int->text_start =
+ GET_AOUTHDR_TEXT_START (abfd, (bfd_byte *) aouthdr_ext->text_start);
+ aouthdr_int->data_start =
+ GET_AOUTHDR_DATA_START (abfd, (bfd_byte *) aouthdr_ext->data_start);
+
+ a = &aouthdr_int->pe;
+ a->ImageBase = bfd_h_get_32 (abfd, src->ImageBase);
+ a->SectionAlignment = bfd_h_get_32 (abfd, src->SectionAlignment);
+ a->FileAlignment = bfd_h_get_32 (abfd, src->FileAlignment);
+ a->MajorOperatingSystemVersion =
+ bfd_h_get_16 (abfd, src->MajorOperatingSystemVersion);
+ a->MinorOperatingSystemVersion =
+ bfd_h_get_16 (abfd, src->MinorOperatingSystemVersion);
+ a->MajorImageVersion = bfd_h_get_16 (abfd, src->MajorImageVersion);
+ a->MinorImageVersion = bfd_h_get_16 (abfd, src->MinorImageVersion);
+ a->MajorSubsystemVersion = bfd_h_get_16 (abfd, src->MajorSubsystemVersion);
+ a->MinorSubsystemVersion = bfd_h_get_16 (abfd, src->MinorSubsystemVersion);
+ a->Reserved1 = bfd_h_get_32 (abfd, src->Reserved1);
+ a->SizeOfImage = bfd_h_get_32 (abfd, src->SizeOfImage);
+ a->SizeOfHeaders = bfd_h_get_32 (abfd, src->SizeOfHeaders);
+ a->CheckSum = bfd_h_get_32 (abfd, src->CheckSum);
+ a->Subsystem = bfd_h_get_16 (abfd, src->Subsystem);
+ a->DllCharacteristics = bfd_h_get_16 (abfd, src->DllCharacteristics);
+ a->SizeOfStackReserve = bfd_h_get_32 (abfd, src->SizeOfStackReserve);
+ a->SizeOfStackCommit = bfd_h_get_32 (abfd, src->SizeOfStackCommit);
+ a->SizeOfHeapReserve = bfd_h_get_32 (abfd, src->SizeOfHeapReserve);
+ a->SizeOfHeapCommit = bfd_h_get_32 (abfd, src->SizeOfHeapCommit);
+ a->LoaderFlags = bfd_h_get_32 (abfd, src->LoaderFlags);
+ a->NumberOfRvaAndSizes = bfd_h_get_32 (abfd, src->NumberOfRvaAndSizes);
+
+ {
+ int idx;
+ for (idx=0; idx < 16; idx++)
+ {
+ a->DataDirectory[idx].VirtualAddress =
+ bfd_h_get_32 (abfd, src->DataDirectory[idx][0]);
+ a->DataDirectory[idx].Size =
+ bfd_h_get_32 (abfd, src->DataDirectory[idx][1]);
+ }
+ }
+
+ if (aouthdr_int->entry)
+ aouthdr_int->entry += a->ImageBase;
+ if (aouthdr_int->tsize)
+ aouthdr_int->text_start += a->ImageBase;
+ if (aouthdr_int->dsize)
+ aouthdr_int->data_start += a->ImageBase;
+}
+
+
+static void add_data_entry (abfd, aout, idx, name, base)
+ bfd *abfd;
+ struct internal_extra_pe_aouthdr *aout;
+ int idx;
+ char *name;
+ bfd_vma base;
+{
+ asection *sec = bfd_get_section_by_name (abfd, name);
+
+ /* add import directory information if it exists */
+ if (sec != NULL)
+ {
+ aout->DataDirectory[idx].VirtualAddress = sec->vma - base;
+ aout->DataDirectory[idx].Size = sec->_cooked_size;
+ sec->flags |= SEC_DATA;
+ }
+}
+
+static unsigned int
+coff_swap_aouthdr_out (abfd, in, out)
+ bfd *abfd;
+ PTR in;
+ PTR out;
+{
+ struct internal_aouthdr *aouthdr_in = (struct internal_aouthdr *)in;
+ struct internal_extra_pe_aouthdr *extra = &pe_data (abfd)->pe_opthdr;
+ PEAOUTHDR *aouthdr_out = (PEAOUTHDR *)out;
+
+ bfd_vma sa = extra->SectionAlignment;
+ bfd_vma fa = extra->FileAlignment;
+ bfd_vma ib = extra->ImageBase ;
+
+ if (aouthdr_in->tsize)
+ aouthdr_in->text_start -= ib;
+ if (aouthdr_in->dsize)
+ aouthdr_in->data_start -= ib;
+ if (aouthdr_in->entry)
+ aouthdr_in->entry -= ib;
+
+#define FA(x) (((x) + fa -1 ) & (- fa))
+#define SA(x) (((x) + sa -1 ) & (- sa))
+
+ /* We like to have the sizes aligned */
+
+ aouthdr_in->bsize = FA (aouthdr_in->bsize);
+
+
+ extra->NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+
+ /* first null out all data directory entries .. */
+ memset (extra->DataDirectory, sizeof (extra->DataDirectory), 0);
+
+ add_data_entry (abfd, extra, 0, ".edata", ib);
+ add_data_entry (abfd, extra, 1, ".idata", ib);
+ add_data_entry (abfd, extra, 2, ".rsrc" ,ib);
+
+#ifdef POWERPC_LE_PE
+ /* FIXME: do other PE platforms use this? */
+ add_data_entry (abfd, extra, 3, ".pdata" ,ib);
+#endif
+
+ add_data_entry (abfd, extra, 5, ".reloc", ib);
+
+#ifdef POWERPC_LE_PE
+ /* On the PPC NT system, this field is set up as follows. It is
+ not an "officially" reserved field, so it currently has no title.
+ first_thunk_address is idata$5, and the thunk_size is the size
+ of the idata$5 chunk of the idata section.
+ */
+ extra->DataDirectory[12].VirtualAddress = first_thunk_address;
+ extra->DataDirectory[12].Size = thunk_size;
+
+ /* On the PPC NT system, the size of the directory entry is not the
+ size of the entire section. It's actually offset to the end of
+ the idata$3 component of the idata section. This is the size of
+ the entire import table. (also known as the start of idata$4)
+ */
+ extra->DataDirectory[1].Size = import_table_size;
+#endif
+
+ {
+ asection *sec;
+ bfd_vma dsize= 0;
+ bfd_vma isize = SA(abfd->sections->filepos);
+ bfd_vma tsize= 0;
+
+ for (sec = abfd->sections; sec; sec = sec->next)
+ {
+ int rounded = FA(sec->_raw_size);
+
+ if (strcmp(sec->name,".junk") == 0)
+ {
+ continue;
+ }
+
+ if (sec->flags & SEC_DATA)
+ dsize += rounded;
+ if (sec->flags & SEC_CODE)
+ tsize += rounded;
+ isize += SA(rounded);
+ }
+
+ aouthdr_in->dsize = dsize;
+ aouthdr_in->tsize = tsize;
+ extra->SizeOfImage = isize;
+ }
+
+ extra->SizeOfHeaders = abfd->sections->filepos;
+ bfd_h_put_16(abfd, aouthdr_in->magic, (bfd_byte *) aouthdr_out->standard.magic);
+
+#ifdef POWERPC_LE_PE
+ /* this little piece of magic sets the "linker version" field to 2.60 */
+ bfd_h_put_16(abfd, 2 + 60 * 256, (bfd_byte *) aouthdr_out->standard.vstamp);
+#else
+ /* this little piece of magic sets the "linker version" field to 2.55 */
+ bfd_h_put_16(abfd, 2 + 55 * 256, (bfd_byte *) aouthdr_out->standard.vstamp);
+#endif
+
+ PUT_AOUTHDR_TSIZE (abfd, aouthdr_in->tsize, (bfd_byte *) aouthdr_out->standard.tsize);
+ PUT_AOUTHDR_DSIZE (abfd, aouthdr_in->dsize, (bfd_byte *) aouthdr_out->standard.dsize);
+ PUT_AOUTHDR_BSIZE (abfd, aouthdr_in->bsize, (bfd_byte *) aouthdr_out->standard.bsize);
+ PUT_AOUTHDR_ENTRY (abfd, aouthdr_in->entry, (bfd_byte *) aouthdr_out->standard.entry);
+ PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
+ (bfd_byte *) aouthdr_out->standard.text_start);
+
+ PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
+ (bfd_byte *) aouthdr_out->standard.data_start);
+
+
+ bfd_h_put_32 (abfd, extra->ImageBase,
+ (bfd_byte *) aouthdr_out->ImageBase);
+ bfd_h_put_32 (abfd, extra->SectionAlignment,
+ (bfd_byte *) aouthdr_out->SectionAlignment);
+ bfd_h_put_32 (abfd, extra->FileAlignment,
+ (bfd_byte *) aouthdr_out->FileAlignment);
+ bfd_h_put_16 (abfd, extra->MajorOperatingSystemVersion,
+ (bfd_byte *) aouthdr_out->MajorOperatingSystemVersion);
+ bfd_h_put_16 (abfd, extra->MinorOperatingSystemVersion,
+ (bfd_byte *) aouthdr_out->MinorOperatingSystemVersion);
+ bfd_h_put_16 (abfd, extra->MajorImageVersion,
+ (bfd_byte *) aouthdr_out->MajorImageVersion);
+ bfd_h_put_16 (abfd, extra->MinorImageVersion,
+ (bfd_byte *) aouthdr_out->MinorImageVersion);
+ bfd_h_put_16 (abfd, extra->MajorSubsystemVersion,
+ (bfd_byte *) aouthdr_out->MajorSubsystemVersion);
+ bfd_h_put_16 (abfd, extra->MinorSubsystemVersion,
+ (bfd_byte *) aouthdr_out->MinorSubsystemVersion);
+ bfd_h_put_32 (abfd, extra->Reserved1,
+ (bfd_byte *) aouthdr_out->Reserved1);
+ bfd_h_put_32 (abfd, extra->SizeOfImage,
+ (bfd_byte *) aouthdr_out->SizeOfImage);
+ bfd_h_put_32 (abfd, extra->SizeOfHeaders,
+ (bfd_byte *) aouthdr_out->SizeOfHeaders);
+ bfd_h_put_32 (abfd, extra->CheckSum,
+ (bfd_byte *) aouthdr_out->CheckSum);
+ bfd_h_put_16 (abfd, extra->Subsystem,
+ (bfd_byte *) aouthdr_out->Subsystem);
+ bfd_h_put_16 (abfd, extra->DllCharacteristics,
+ (bfd_byte *) aouthdr_out->DllCharacteristics);
+ bfd_h_put_32 (abfd, extra->SizeOfStackReserve,
+ (bfd_byte *) aouthdr_out->SizeOfStackReserve);
+ bfd_h_put_32 (abfd, extra->SizeOfStackCommit,
+ (bfd_byte *) aouthdr_out->SizeOfStackCommit);
+ bfd_h_put_32 (abfd, extra->SizeOfHeapReserve,
+ (bfd_byte *) aouthdr_out->SizeOfHeapReserve);
+ bfd_h_put_32 (abfd, extra->SizeOfHeapCommit,
+ (bfd_byte *) aouthdr_out->SizeOfHeapCommit);
+ bfd_h_put_32 (abfd, extra->LoaderFlags,
+ (bfd_byte *) aouthdr_out->LoaderFlags);
+ bfd_h_put_32 (abfd, extra->NumberOfRvaAndSizes,
+ (bfd_byte *) aouthdr_out->NumberOfRvaAndSizes);
+ {
+ int idx;
+ for (idx=0; idx < 16; idx++)
+ {
+ bfd_h_put_32 (abfd, extra->DataDirectory[idx].VirtualAddress,
+ (bfd_byte *) aouthdr_out->DataDirectory[idx][0]);
+ bfd_h_put_32 (abfd, extra->DataDirectory[idx].Size,
+ (bfd_byte *) aouthdr_out->DataDirectory[idx][1]);
+ }
+ }
+
+ return sizeof(AOUTHDR);
+}
+
+static void
+ coff_swap_scnhdr_in (abfd, ext, in)
+ bfd *abfd;
+ PTR ext;
+ PTR in;
+{
+ SCNHDR *scnhdr_ext = (SCNHDR *) ext;
+ struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *) in;
+
+ memcpy(scnhdr_int->s_name, scnhdr_ext->s_name, sizeof(scnhdr_int->s_name));
+ scnhdr_int->s_vaddr =
+ GET_SCNHDR_VADDR (abfd, (bfd_byte *) scnhdr_ext->s_vaddr);
+ scnhdr_int->s_paddr =
+ GET_SCNHDR_PADDR (abfd, (bfd_byte *) scnhdr_ext->s_paddr);
+ scnhdr_int->s_size =
+ GET_SCNHDR_SIZE (abfd, (bfd_byte *) scnhdr_ext->s_size);
+ scnhdr_int->s_scnptr =
+ GET_SCNHDR_SCNPTR (abfd, (bfd_byte *) scnhdr_ext->s_scnptr);
+ scnhdr_int->s_relptr =
+ GET_SCNHDR_RELPTR (abfd, (bfd_byte *) scnhdr_ext->s_relptr);
+ scnhdr_int->s_lnnoptr =
+ GET_SCNHDR_LNNOPTR (abfd, (bfd_byte *) scnhdr_ext->s_lnnoptr);
+ scnhdr_int->s_flags = bfd_h_get_32(abfd, (bfd_byte *) scnhdr_ext->s_flags);
+
+ scnhdr_int->s_nreloc = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nreloc);
+ scnhdr_int->s_nlnno = bfd_h_get_16(abfd, (bfd_byte *) scnhdr_ext->s_nlnno);
+
+ if (scnhdr_int->s_vaddr != 0)
+ {
+ scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
+ }
+ if (strcmp (scnhdr_int->s_name, _BSS) == 0)
+ {
+ scnhdr_int->s_size = scnhdr_int->s_paddr;
+ scnhdr_int->s_paddr = 0;
+ }
+}
+
+static unsigned int
+coff_swap_scnhdr_out (abfd, in, out)
+ bfd *abfd;
+ PTR in;
+ PTR out;
+{
+ struct internal_scnhdr *scnhdr_int = (struct internal_scnhdr *)in;
+ SCNHDR *scnhdr_ext = (SCNHDR *)out;
+ unsigned int ret = sizeof (SCNHDR);
+ bfd_vma ps;
+ bfd_vma ss;
+
+ memcpy(scnhdr_ext->s_name, scnhdr_int->s_name, sizeof(scnhdr_int->s_name));
+
+ PUT_SCNHDR_VADDR (abfd,
+ (scnhdr_int->s_vaddr
+ - pe_data(abfd)->pe_opthdr.ImageBase),
+ (bfd_byte *) scnhdr_ext->s_vaddr);
+
+ /* NT wants the size data to be rounded up to the next NT_FILE_ALIGNMENT
+ value except for the BSS section, its s_size should be 0 */
+
+
+ if (strcmp (scnhdr_int->s_name, _BSS) == 0)
+ {
+ ps = scnhdr_int->s_size;
+ ss = 0;
+ }
+ else
+ {
+ ps = scnhdr_int->s_paddr;
+ ss = scnhdr_int->s_size;
+ }
+
+ PUT_SCNHDR_SIZE (abfd, ss,
+ (bfd_byte *) scnhdr_ext->s_size);
+
+
+ PUT_SCNHDR_PADDR (abfd, ps, (bfd_byte *) scnhdr_ext->s_paddr);
+
+ PUT_SCNHDR_SCNPTR (abfd, scnhdr_int->s_scnptr,
+ (bfd_byte *) scnhdr_ext->s_scnptr);
+ PUT_SCNHDR_RELPTR (abfd, scnhdr_int->s_relptr,
+ (bfd_byte *) scnhdr_ext->s_relptr);
+ PUT_SCNHDR_LNNOPTR (abfd, scnhdr_int->s_lnnoptr,
+ (bfd_byte *) scnhdr_ext->s_lnnoptr);
+
+ /* Extra flags must be set when dealing with NT. All sections should also
+ have the IMAGE_SCN_MEM_READ (0x40000000) flag set. In addition, the
+ .text section must have IMAGE_SCN_MEM_EXECUTE (0x20000000) and the data
+ sections (.idata, .data, .bss, .CRT) must have IMAGE_SCN_MEM_WRITE set
+ (this is especially important when dealing with the .idata section since
+ the addresses for routines from .dlls must be overwritten). If .reloc
+ section data is ever generated, we must add IMAGE_SCN_MEM_DISCARDABLE
+ (0x02000000). Also, the resource data should also be read and
+ writable. */
+
+ /* FIXME: alignment is also encoded in this field, at least on ppc (krk) */
+ /* FIXME: even worse, I don't see how to get the original alignment field*/
+ /* back... */
+
+ {
+ int flags = scnhdr_int->s_flags;
+ if (strcmp (scnhdr_int->s_name, ".data") == 0 ||
+ strcmp (scnhdr_int->s_name, ".CRT") == 0 ||
+ strcmp (scnhdr_int->s_name, ".rsrc") == 0 ||
+ strcmp (scnhdr_int->s_name, ".bss") == 0)
+ flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
+ else if (strcmp (scnhdr_int->s_name, ".text") == 0)
+ flags |= IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE;
+ else if (strcmp (scnhdr_int->s_name, ".reloc") == 0)
+ flags = SEC_DATA| IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE;
+ else if (strcmp (scnhdr_int->s_name, ".idata") == 0)
+ flags = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | SEC_DATA;
+ else if (strcmp (scnhdr_int->s_name, ".rdata") == 0
+ || strcmp (scnhdr_int->s_name, ".edata") == 0)
+ flags = IMAGE_SCN_MEM_READ | SEC_DATA;
+ /* ppc-nt additions */
+ else if (strcmp (scnhdr_int->s_name, ".pdata") == 0)
+ flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES |
+ IMAGE_SCN_MEM_READ ;
+ /* Remember this field is a max of 8 chars, so the null is _not_ there
+ for an 8 character name like ".reldata". (yep. Stupid bug) */
+ else if (strncmp (scnhdr_int->s_name, ".reldata", strlen(".reldata")) == 0)
+ flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
+ else if (strcmp (scnhdr_int->s_name, ".ydata") == 0)
+ flags = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_8BYTES |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE ;
+ else if (strcmp (scnhdr_int->s_name, ".drectve") == 0)
+ flags = IMAGE_SCN_LNK_INFO | IMAGE_SCN_LNK_REMOVE ;
+ /* end of ppc-nt additions */
+#ifdef POWERPC_LE_PE
+ else if (strncmp (scnhdr_int->s_name, ".stabstr", strlen(".stabstr")) == 0)
+ {
+ flags = IMAGE_SCN_LNK_INFO;
+ }
+ else if (strcmp (scnhdr_int->s_name, ".stab") == 0)
+ {
+ flags = IMAGE_SCN_LNK_INFO;
+ }
+#endif
+
+ bfd_h_put_32(abfd, flags, (bfd_byte *) scnhdr_ext->s_flags);
+ }
+
+ if (scnhdr_int->s_nlnno <= 0xffff)
+ bfd_h_put_16(abfd, scnhdr_int->s_nlnno, (bfd_byte *) scnhdr_ext->s_nlnno);
+ else
+ {
+ (*_bfd_error_handler) ("%s: line number overflow: 0x%lx > 0xffff",
+ bfd_get_filename (abfd),
+ scnhdr_int->s_nlnno);
+ bfd_set_error (bfd_error_file_truncated);
+ bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nlnno);
+ ret = 0;
+ }
+ if (scnhdr_int->s_nreloc <= 0xffff)
+ bfd_h_put_16(abfd, scnhdr_int->s_nreloc, (bfd_byte *) scnhdr_ext->s_nreloc);
+ else
+ {
+ (*_bfd_error_handler) ("%s: reloc overflow: 0x%lx > 0xffff",
+ bfd_get_filename (abfd),
+ scnhdr_int->s_nreloc);
+ bfd_set_error (bfd_error_file_truncated);
+ bfd_h_put_16 (abfd, 0xffff, (bfd_byte *) scnhdr_ext->s_nreloc);
+ ret = 0;
+ }
+ return ret;
+}
+
+static char * dir_names[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] =
+{
+ "Export Directory [.edata]",
+ "Import Directory [parts of .idata]",
+ "Resource Directory [.rsrc]",
+ "Exception Directory [.pdata]",
+ "Security Directory",
+ "Base Relocation Directory [.reloc]",
+ "Debug Directory",
+ "Description Directory",
+ "Special Directory",
+ "Thread Storage Directory [.tls]",
+ "Load Configuration Directory",
+ "Bound Import Directory",
+ "Import Address Table Directory",
+ "Reserved",
+ "Reserved",
+ "Reserved"
+};
+
+/**********************************************************************/
+static boolean
+pe_print_idata(abfd, vfile)
+ bfd*abfd;
+ void *vfile;
+{
+ FILE *file = vfile;
+ bfd_byte *data = 0;
+ asection *section = bfd_get_section_by_name (abfd, ".idata");
+
+#ifdef POWERPC_LE_PE
+ asection *rel_section = bfd_get_section_by_name (abfd, ".reldata");
+#endif
+
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+ bfd_size_type start, stop;
+ int onaline = 20;
+ bfd_vma addr_value;
+ bfd_vma loadable_toc_address;
+ bfd_vma toc_address;
+ bfd_vma start_address;
+
+ pe_data_type *pe = pe_data (abfd);
+ struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+
+ if (section == 0)
+ return true;
+
+#ifdef POWERPC_LE_PE
+ if (rel_section != 0 && bfd_section_size (abfd, rel_section) != 0)
+ {
+ /* The toc address can be found by taking the starting address,
+ which on the PPC locates a function descriptor. The descriptor
+ consists of the function code starting address followed by the
+ address of the toc. The starting address we get from the bfd,
+ and the descriptor is supposed to be in the .reldata section.
+ */
+
+ bfd_byte *data = 0;
+ int offset;
+ data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd,
+ rel_section));
+ if (data == NULL && bfd_section_size (abfd, rel_section) != 0)
+ return false;
+
+ datasize = bfd_section_size (abfd, rel_section);
+
+ bfd_get_section_contents (abfd,
+ rel_section,
+ (PTR) data, 0,
+ bfd_section_size (abfd, rel_section));
+
+ offset = abfd->start_address - rel_section->vma;
+
+ start_address = bfd_get_32(abfd, data+offset);
+ loadable_toc_address = bfd_get_32(abfd, data+offset+4);
+ toc_address = loadable_toc_address - 32768;
+
+ fprintf(file,
+ "\nFunction descriptor located at the start address: %04lx\n",
+ (unsigned long int) (abfd->start_address));
+ fprintf (file,
+ "\tcode-base %08lx toc (loadable/actual) %08lx/%08lx\n",
+ start_address, loadable_toc_address, toc_address);
+ }
+ else
+ {
+ loadable_toc_address = 0;
+ toc_address = 0;
+ start_address = 0;
+ }
+#endif
+
+ fprintf(file,
+ "\nThe Import Tables (interpreted .idata section contents)\n");
+ fprintf(file,
+ " vma: Hint Time Forward DLL First\n");
+ fprintf(file,
+ " Table Stamp Chain Name Thunk\n");
+
+ if (bfd_section_size (abfd, section) == 0)
+ return true;
+
+ data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
+ datasize = bfd_section_size (abfd, section);
+ if (data == NULL && datasize != 0)
+ return false;
+
+ bfd_get_section_contents (abfd,
+ section,
+ (PTR) data, 0,
+ bfd_section_size (abfd, section));
+
+ start = 0;
+
+ stop = bfd_section_size (abfd, section);
+
+ for (i = start; i < stop; i += onaline)
+ {
+ bfd_vma hint_addr;
+ bfd_vma time_stamp;
+ bfd_vma forward_chain;
+ bfd_vma dll_name;
+ bfd_vma first_thunk;
+ int idx;
+ int j;
+ char *dll;
+ int adj = extra->ImageBase - section->vma;
+
+ fprintf (file,
+ " %04lx\t",
+ (unsigned long int) (i + section->vma));
+
+ if (i+20 > stop)
+ {
+ /* check stuff */
+ ;
+ }
+
+ hint_addr = bfd_get_32(abfd, data+i);
+ time_stamp = bfd_get_32(abfd, data+i+4);
+ forward_chain = bfd_get_32(abfd, data+i+8);
+ dll_name = bfd_get_32(abfd, data+i+12);
+ first_thunk = bfd_get_32(abfd, data+i+16);
+
+ fprintf(file, "%08lx %08lx %08lx %08lx %08lx\n",
+ hint_addr,
+ time_stamp,
+ forward_chain,
+ dll_name,
+ first_thunk);
+
+ if (hint_addr ==0)
+ {
+ break;
+ }
+
+ /* the image base is present in the section->vma */
+ dll = data + dll_name + adj;
+ fprintf(file, "\n\tDLL Name: %s\n", dll);
+ fprintf(file, "\tvma: Ordinal Member-Name\n");
+
+ idx = hint_addr + adj;
+
+ for (j=0;j<stop;j+=4)
+ {
+ int ordinal;
+ char *member_name;
+ bfd_vma member = bfd_get_32(abfd, data + idx + j);
+ if (member == 0)
+ break;
+ ordinal = bfd_get_16(abfd,
+ data + member + adj);
+ member_name = data + member + adj + 2;
+ fprintf(file, "\t%04lx\t %4d %s\n",
+ member, ordinal, member_name);
+ }
+
+ if (hint_addr != first_thunk)
+ {
+ int differ = 0;
+ int idx2;
+
+ idx2 = first_thunk + adj;
+
+ for (j=0;j<stop;j+=4)
+ {
+ int ordinal;
+ char *member_name;
+ bfd_vma hint_member = bfd_get_32(abfd, data + idx + j);
+ bfd_vma iat_member = bfd_get_32(abfd, data + idx2 + j);
+ if (hint_member != iat_member)
+ {
+ if (differ == 0)
+ {
+ fprintf(file,
+ "\tThe Import Address Table (difference found)\n");
+ fprintf(file, "\tvma: Ordinal Member-Name\n");
+ differ = 1;
+ }
+ if (iat_member == 0)
+ {
+ fprintf(file,
+ "\t>>> Ran out of IAT members!\n");
+ }
+ else
+ {
+ ordinal = bfd_get_16(abfd,
+ data + iat_member + adj);
+ member_name = data + iat_member + adj + 2;
+ fprintf(file, "\t%04lx\t %4d %s\n",
+ iat_member, ordinal, member_name);
+ }
+ break;
+ }
+ if (hint_member == 0)
+ break;
+ }
+ if (differ == 0)
+ {
+ fprintf(file,
+ "\tThe Import Address Table is identical\n");
+ }
+ }
+
+ fprintf(file, "\n");
+
+ }
+
+ free (data);
+}
+
+static boolean
+pe_print_edata(abfd, vfile)
+ bfd*abfd;
+ void *vfile;
+{
+ FILE *file = vfile;
+ bfd_byte *data = 0;
+ asection *section = bfd_get_section_by_name (abfd, ".edata");
+
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+
+ int adj;
+ struct EDT_type
+ {
+ long export_flags; /* reserved - should be zero */
+ long time_stamp;
+ short major_ver;
+ short minor_ver;
+ bfd_vma name; /* rva - relative to image base */
+ long base; /* ordinal base */
+ long num_functions; /* Number in the export address table */
+ long num_names; /* Number in the name pointer table */
+ bfd_vma eat_addr; /* rva to the export address table */
+ bfd_vma npt_addr; /* rva to the Export Name Pointer Table */
+ bfd_vma ot_addr; /* rva to the Ordinal Table */
+ } edt;
+
+ pe_data_type *pe = pe_data (abfd);
+ struct internal_extra_pe_aouthdr *extra = &pe->pe_opthdr;
+
+ if (section == 0)
+ return true;
+
+ data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd,
+ section));
+ datasize = bfd_section_size (abfd, section);
+
+ if (data == NULL && datasize != 0)
+ return false;
+
+ bfd_get_section_contents (abfd,
+ section,
+ (PTR) data, 0,
+ bfd_section_size (abfd, section));
+
+ /* Go get Export Directory Table */
+ edt.export_flags = bfd_get_32(abfd, data+0);
+ edt.time_stamp = bfd_get_32(abfd, data+4);
+ edt.major_ver = bfd_get_16(abfd, data+8);
+ edt.minor_ver = bfd_get_16(abfd, data+10);
+ edt.name = bfd_get_32(abfd, data+12);
+ edt.base = bfd_get_32(abfd, data+16);
+ edt.num_functions = bfd_get_32(abfd, data+20);
+ edt.num_names = bfd_get_32(abfd, data+24);
+ edt.eat_addr = bfd_get_32(abfd, data+28);
+ edt.npt_addr = bfd_get_32(abfd, data+32);
+ edt.ot_addr = bfd_get_32(abfd, data+36);
+
+ adj = extra->ImageBase - section->vma;
+
+
+ /* Dump the EDT first first */
+ fprintf(file,
+ "\nThe Export Tables (interpreted .edata section contents)\n\n");
+
+ fprintf(file,
+ "Export Flags \t\t\t%x\n",edt.export_flags);
+
+ fprintf(file,
+ "Time/Date stamp \t\t%x\n",edt.time_stamp);
+
+ fprintf(file,
+ "Major/Minor \t\t\t%d/%d\n", edt.major_ver, edt.minor_ver);
+
+ fprintf(file,
+ "Name \t\t\t\t%x %s\n", edt.name, data + edt.name + adj);
+
+ fprintf(file,
+ "Ordinal Base \t\t\t%d\n", edt.base);
+
+ fprintf(file,
+ "Number in:\n");
+
+ fprintf(file,
+ "\tExport Address Table \t\t%x\n", edt.num_functions);
+
+ fprintf(file,
+ "\t[Name Pointer/Ordinal] Table\t%d\n", edt.num_names);
+
+ fprintf(file,
+ "Table Addresses\n");
+
+ fprintf(file,
+ "\tExport Address Table \t\t%x\n",
+ edt.eat_addr);
+
+ fprintf(file,
+ "\tName Pointer Table \t\t%x\n",
+ edt.npt_addr);
+
+ fprintf(file,
+ "\tOrdinal Table \t\t\t%x\n",
+ edt.ot_addr);
+
+
+ /* The next table to find si the Export Address Table. It's basically
+ a list of pointers that either locate a function in this dll, or
+ forward the call to another dll. Something like:
+ typedef union
+ {
+ long export_rva;
+ long forwarder_rva;
+ } export_address_table_entry;
+ */
+
+ fprintf(file,
+ "\nExport Address Table -- Ordinal Base %d\n",
+ edt.base);
+
+ for (i = 0; i < edt.num_functions; ++i)
+ {
+ bfd_vma eat_member = bfd_get_32(abfd,
+ data + edt.eat_addr + (i*4) + adj);
+ bfd_vma eat_actual = extra->ImageBase + eat_member;
+ bfd_vma edata_start = bfd_get_section_vma(abfd,section);
+ bfd_vma edata_end = edata_start + bfd_section_size (abfd, section);
+
+
+ if (eat_member == 0)
+ continue;
+
+ if (edata_start < eat_actual && eat_actual < edata_end)
+ {
+ /* this rva is to a name (forwarding function) in our section */
+ /* Should locate a function descriptor */
+ fprintf(file,
+ "\t[%4d] +base[%4d] %04lx %s -- %s\n",
+ i, i+edt.base, eat_member, "Forwarder RVA",
+ data + eat_member + adj);
+ }
+ else
+ {
+ /* Should locate a function descriptor in the reldata section */
+ fprintf(file,
+ "\t[%4d] +base[%4d] %04lx %s\n",
+ i, i+edt.base, eat_member, "Export RVA");
+ }
+ }
+
+ /* The Export Name Pointer Table is paired with the Export Ordinal Table */
+ /* Dump them in parallel for clarity */
+ fprintf(file,
+ "\n[Ordinal/Name Pointer] Table\n");
+
+ for (i = 0; i < edt.num_names; ++i)
+ {
+ bfd_vma name_ptr = bfd_get_32(abfd,
+ data +
+ edt.npt_addr
+ + (i*4) + adj);
+
+ char *name = data + name_ptr + adj;
+
+ bfd_vma ord = bfd_get_16(abfd,
+ data +
+ edt.ot_addr
+ + (i*2) + adj);
+ fprintf(file,
+ "\t[%4d] %s\n", ord, name);
+
+ }
+
+ free (data);
+}
+
+static boolean
+pe_print_pdata(abfd, vfile)
+ bfd*abfd;
+ void *vfile;
+{
+ FILE *file = vfile;
+ bfd_byte *data = 0;
+ asection *section = bfd_get_section_by_name (abfd, ".pdata");
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+ bfd_size_type start, stop;
+ int onaline = 20;
+ bfd_vma addr_value;
+
+ if (section == 0)
+ return true;
+
+ fprintf(file,
+ "\nThe Function Table (interpreted .pdata section contents)\n");
+ fprintf(file,
+ " vma:\t\tBegin End EH EH PrologEnd\n");
+ fprintf(file,
+ " \t\tAddress Address Handler Data Address\n");
+
+ if (bfd_section_size (abfd, section) == 0)
+ return true;
+
+ data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
+ datasize = bfd_section_size (abfd, section);
+ if (data == NULL && datasize != 0)
+ return false;
+
+ bfd_get_section_contents (abfd,
+ section,
+ (PTR) data, 0,
+ bfd_section_size (abfd, section));
+
+ start = 0;
+
+ stop = bfd_section_size (abfd, section);
+
+ for (i = start; i < stop; i += onaline)
+ {
+ bfd_vma begin_addr;
+ bfd_vma end_addr;
+ bfd_vma eh_handler;
+ bfd_vma eh_data;
+ bfd_vma prolog_end_addr;
+
+ if (i+20 > stop)
+ break;
+
+ begin_addr = bfd_get_32(abfd, data+i);
+ end_addr = bfd_get_32(abfd, data+i+4);
+ eh_handler = bfd_get_32(abfd, data+i+8);
+ eh_data = bfd_get_32(abfd, data+i+12);
+ prolog_end_addr = bfd_get_32(abfd, data+i+16);
+
+ if (begin_addr == 0 && end_addr == 0 && eh_handler == 0
+ && eh_data == 0 && prolog_end_addr == 0)
+ {
+ /* We are probably into the padding of the
+ section now */
+ break;
+ }
+
+ fprintf (file,
+ " %08lx\t",
+ (unsigned long int) (i + section->vma));
+
+ fprintf(file, "%08lx %08lx %08lx %08lx %08lx",
+ begin_addr,
+ end_addr,
+ eh_handler,
+ eh_data,
+ prolog_end_addr);
+
+#ifdef POWERPC_LE_PE
+ if (eh_handler == 0 && eh_data != 0)
+ {
+ /* Special bits here, although the meaning may */
+ /* be a little mysterious. The only one I know */
+ /* for sure is 0x03. */
+ /* Code Significance */
+ /* 0x00 None */
+ /* 0x01 Register Save Millicode */
+ /* 0x02 Register Restore Millicode */
+ /* 0x03 Glue Code Sequence */
+ switch (eh_data)
+ {
+ case 0x01:
+ fprintf(file, " Register save millicode");
+ break;
+ case 0x02:
+ fprintf(file, " Register restore millicode");
+ break;
+ case 0x03:
+ fprintf(file, " Glue code sequence");
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+ fprintf(file, "\n");
+ }
+
+ free (data);
+}
+
+static const char *tbl[6] =
+{
+"ABSOLUTE",
+"HIGH",
+"LOW",
+"HIGHLOW",
+"HIGHADJ",
+"unknown"
+};
+
+static boolean
+pe_print_reloc(abfd, vfile)
+ bfd*abfd;
+ void *vfile;
+{
+ FILE *file = vfile;
+ bfd_byte *data = 0;
+ asection *section = bfd_get_section_by_name (abfd, ".reloc");
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+ bfd_size_type start, stop;
+ int onaline = 20;
+ bfd_vma addr_value;
+
+ if (section == 0)
+ return true;
+
+ if (bfd_section_size (abfd, section) == 0)
+ return true;
+
+ fprintf(file,
+ "\n\nPE File Base Relocations (interpreted .reloc"
+ " section contents)\n");
+
+ data = (bfd_byte *) bfd_malloc ((size_t) bfd_section_size (abfd, section));
+ datasize = bfd_section_size (abfd, section);
+ if (data == NULL && datasize != 0)
+ return false;
+
+ bfd_get_section_contents (abfd,
+ section,
+ (PTR) data, 0,
+ bfd_section_size (abfd, section));
+
+ start = 0;
+
+ stop = bfd_section_size (abfd, section);
+
+ for (i = start; i < stop;)
+ {
+ int j;
+ bfd_vma virtual_address;
+ long number, size;
+
+ /* The .reloc section is a sequence of blocks, with a header consisting
+ of two 32 bit quantities, followed by a number of 16 bit entries */
+
+ virtual_address = bfd_get_32(abfd, data+i);
+ size = bfd_get_32(abfd, data+i+4);
+ number = (size - 8) / 2;
+
+ if (size == 0)
+ {
+ break;
+ }
+
+ fprintf (file,
+ "\nVirtual Address: %08lx Chunk size %d (0x%x) "
+ "Number of fixups %d\n",
+ virtual_address, size, size, number);
+
+ for (j = 0; j < number; ++j)
+ {
+ unsigned short e = bfd_get_16(abfd, data + i + 8 + j*2);
+ int t = (e & 0xF000) >> 12;
+ int off = e & 0x0FFF;
+
+ if (t > 5)
+ abort();
+
+ fprintf(file,
+ "\treloc %4d offset %4x [%4x] %s\n",
+ j, off, off+virtual_address, tbl[t]);
+
+ }
+ i += size;
+ }
+
+ free (data);
+}
+
+static boolean
+pe_print_private_bfd_data (abfd, vfile)
+ bfd *abfd;
+ PTR vfile;
+{
+ FILE *file = (FILE *) vfile;
+ int j;
+ pe_data_type *pe = pe_data (abfd);
+ struct internal_extra_pe_aouthdr *i = &pe->pe_opthdr;
+
+ fprintf (file,"\nImageBase\t\t");
+ fprintf_vma (file, i->ImageBase);
+ fprintf (file,"\nSectionAlignment\t");
+ fprintf_vma (file, i->SectionAlignment);
+ fprintf (file,"\nFileAlignment\t\t");
+ fprintf_vma (file, i->FileAlignment);
+ fprintf (file,"\nMajorOSystemVersion\t%d\n", i->MajorOperatingSystemVersion);
+ fprintf (file,"MinorOSystemVersion\t%d\n", i->MinorOperatingSystemVersion);
+ fprintf (file,"MajorImageVersion\t%d\n", i->MajorImageVersion);
+ fprintf (file,"MinorImageVersion\t%d\n", i->MinorImageVersion);
+ fprintf (file,"MajorSubsystemVersion\t%d\n", i->MajorSubsystemVersion);
+ fprintf (file,"MinorSubsystemVersion\t%d\n", i->MinorSubsystemVersion);
+ fprintf (file,"Reserved1\t\t%08lx\n", i->Reserved1);
+ fprintf (file,"SizeOfImage\t\t%08lx\n", i->SizeOfImage);
+ fprintf (file,"SizeOfHeaders\t\t%08lx\n", i->SizeOfHeaders);
+ fprintf (file,"CheckSum\t\t%08lx\n", i->CheckSum);
+ fprintf (file,"Subsystem\t\t%08x\n", i->Subsystem);
+ fprintf (file,"DllCharacteristics\t%08x\n", i->DllCharacteristics);
+ fprintf (file,"SizeOfStackReserve\t");
+ fprintf_vma (file, i->SizeOfStackReserve);
+ fprintf (file,"\nSizeOfStackCommit\t");
+ fprintf_vma (file, i->SizeOfStackCommit);
+ fprintf (file,"\nSizeOfHeapReserve\t");
+ fprintf_vma (file, i->SizeOfHeapReserve);
+ fprintf (file,"\nSizeOfHeapCommit\t");
+ fprintf_vma (file, i->SizeOfHeapCommit);
+ fprintf (file,"\nLoaderFlags\t\t%08lx\n", i->LoaderFlags);
+ fprintf (file,"NumberOfRvaAndSizes\t%08lx\n", i->NumberOfRvaAndSizes);
+
+ fprintf (file,"\nThe Data Directory\n");
+ for (j = 0; j < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; j++)
+ {
+ fprintf (file, "Entry %1x ", j);
+ fprintf_vma (file, i->DataDirectory[j].VirtualAddress);
+ fprintf (file, " %08lx ", i->DataDirectory[j].Size);
+ fprintf (file, "%s\n", dir_names[j]);
+ }
+
+ pe_print_idata(abfd, vfile);
+ pe_print_edata(abfd, vfile);
+ pe_print_pdata(abfd, vfile);
+ pe_print_reloc(abfd, vfile);
+
+ return true;
+}
+
+static boolean
+pe_mkobject (abfd)
+ bfd * abfd;
+{
+ pe_data_type *pe;
+ abfd->tdata.pe_obj_data =
+ (struct pe_tdata *) bfd_zalloc (abfd, sizeof (pe_data_type));
+
+ if (abfd->tdata.pe_obj_data == 0)
+ return false;
+
+ pe = pe_data (abfd);
+
+ pe->coff.pe = 1;
+ pe->in_reloc_p = in_reloc_p;
+ return true;
+}
+
+/* Create the COFF backend specific information. */
+static PTR
+pe_mkobject_hook (abfd, filehdr, aouthdr)
+ bfd * abfd;
+ PTR filehdr;
+ PTR aouthdr;
+{
+ struct internal_filehdr *internal_f = (struct internal_filehdr *) filehdr;
+ pe_data_type *pe;
+
+ if (pe_mkobject (abfd) == false)
+ return NULL;
+
+ pe = pe_data (abfd);
+ pe->coff.sym_filepos = internal_f->f_symptr;
+ /* These members communicate important constants about the symbol
+ table to GDB's symbol-reading code. These `constants'
+ unfortunately vary among coff implementations... */
+ pe->coff.local_n_btmask = N_BTMASK;
+ pe->coff.local_n_btshft = N_BTSHFT;
+ pe->coff.local_n_tmask = N_TMASK;
+ pe->coff.local_n_tshift = N_TSHIFT;
+ pe->coff.local_symesz = SYMESZ;
+ pe->coff.local_auxesz = AUXESZ;
+ pe->coff.local_linesz = LINESZ;
+
+ obj_raw_syment_count (abfd) =
+ obj_conv_table_size (abfd) =
+ internal_f->f_nsyms;
+
+ pe->real_flags = internal_f->f_flags;
+
+#ifdef COFF_IMAGE_WITH_PE
+ if (aouthdr)
+ {
+ pe->pe_opthdr = ((struct internal_aouthdr *)aouthdr)->pe;
+ }
+#endif
+
+ return (PTR) pe;
+}
+
+
+
+/* Copy any private info we understand from the input bfd
+ to the output bfd. */
+
+#define coff_bfd_copy_private_bfd_data pe_bfd_copy_private_bfd_data
+
+static boolean
+pe_bfd_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd, *obfd;
+{
+ /* One day we may try to grok other private data. */
+ if (ibfd->xvec->flavour != bfd_target_coff_flavour
+ || obfd->xvec->flavour != bfd_target_coff_flavour)
+ return true;
+
+ pe_data(obfd)->pe_opthdr = pe_data (ibfd)->pe_opthdr;
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/ptrace-core.c b/contrib/gdb/bfd/ptrace-core.c
new file mode 100644
index 0000000..e356457
--- /dev/null
+++ b/contrib/gdb/bfd/ptrace-core.c
@@ -0,0 +1,233 @@
+/* BFD backend for core files which use the ptrace_user structure
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ The structure of this file is based on trad-core.c written by John Gilmore
+ of Cygnus Support.
+ Modified to work with the ptrace_user structure by Kevin A. Buettner.
+ (Longterm it may be better to merge this file with trad-core.c)
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef PTRACE_CORE
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/ptrace.h>
+
+
+struct trad_core_struct
+ {
+ asection *data_section;
+ asection *stack_section;
+ asection *reg_section;
+ struct ptrace_user u;
+ };
+
+#define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u))
+#define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section)
+#define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
+#define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section)
+
+/* forward declarations */
+
+const bfd_target *ptrace_unix_core_file_p PARAMS ((bfd *abfd));
+char * ptrace_unix_core_file_failing_command PARAMS ((bfd *abfd));
+int ptrace_unix_core_file_failing_signal PARAMS ((bfd *abfd));
+boolean ptrace_unix_core_file_matches_executable_p
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+/* ARGSUSED */
+const bfd_target *
+ptrace_unix_core_file_p (abfd)
+ bfd *abfd;
+
+{
+ int val;
+ struct ptrace_user u;
+ struct trad_core_struct *rawptr;
+
+ val = bfd_read ((void *)&u, 1, sizeof u, abfd);
+ if (val != sizeof u || u.pt_magic != _BCS_PTRACE_MAGIC
+ || u.pt_rev != _BCS_PTRACE_REV)
+ {
+ /* Too small to be a core file */
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+
+ /* 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));
+
+ if (rawptr == NULL)
+ return 0;
+
+ abfd->tdata.trad_core_data = rawptr;
+
+ rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
+
+ /* Create the sections. This is raunchy, but bfd_close wants to free
+ them separately. */
+
+ core_stacksec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_stacksec (abfd) == NULL)
+ return NULL;
+ core_datasec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_datasec (abfd) == NULL)
+ return NULL;
+ core_regsec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_regsec (abfd) == NULL)
+ return NULL;
+
+ core_stacksec (abfd)->name = ".stack";
+ core_datasec (abfd)->name = ".data";
+ core_regsec (abfd)->name = ".reg";
+
+ /* FIXME: Need to worry about shared memory, library data, and library
+ text. I don't think that any of these things are supported on the
+ system on which I am developing this for though. */
+
+
+ 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_HAS_CONTENTS;
+
+ core_datasec (abfd)->_raw_size = u.pt_dsize;
+ core_stacksec (abfd)->_raw_size = u.pt_ssize;
+ core_regsec (abfd)->_raw_size = sizeof(u);
+
+ core_datasec (abfd)->vma = u.pt_o_data_start;
+ core_stacksec (abfd)->vma = USRSTACK - u.pt_ssize;
+ core_regsec (abfd)->vma = 0 - sizeof(u); /* see trad-core.c */
+
+ core_datasec (abfd)->filepos = (int) u.pt_dataptr;
+ core_stacksec (abfd)->filepos = (int) (u.pt_dataptr + u.pt_dsize);
+ core_regsec (abfd)->filepos = 0; /* Register segment is ptrace_user */
+
+ /* Align to word at least */
+ core_stacksec (abfd)->alignment_power = 2;
+ core_datasec (abfd)->alignment_power = 2;
+ core_regsec (abfd)->alignment_power = 2;
+
+ abfd->sections = core_stacksec (abfd);
+ core_stacksec (abfd)->next = core_datasec (abfd);
+ core_datasec (abfd)->next = core_regsec (abfd);
+ abfd->section_count = 3;
+
+ return abfd->xvec;
+}
+
+char *
+ptrace_unix_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ char *com = abfd->tdata.trad_core_data->u.pt_comm;
+ if (*com)
+ return com;
+ else
+ return 0;
+}
+
+/* ARGSUSED */
+int
+ptrace_unix_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return abfd->tdata.trad_core_data->u.pt_sigframe.sig_num;
+}
+
+/* ARGSUSED */
+boolean
+ptrace_unix_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ /* FIXME: Use pt_timdat field of the ptrace_user structure to match
+ the date of the executable */
+ return true;
+}
+
+/* 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 (( const bfd_byte *))) swap_abort )
+#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
+#define NO_SIGNED_GET \
+ ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
+
+const bfd_target ptrace_core_vec =
+ {
+ "trad-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ 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 */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ ptrace_unix_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (ptrace_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 */
+};
+
+#endif /* PTRACE_CORE */
diff --git a/contrib/gdb/bfd/reloc.c b/contrib/gdb/bfd/reloc.c
new file mode 100644
index 0000000..46ed5c2
--- /dev/null
+++ b/contrib/gdb/bfd/reloc.c
@@ -0,0 +1,2391 @@
+/* BFD support for handling relocation entries.
+ Copyright (C) 1990, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ Relocations
+
+ 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 <<bfd_perform_relocation>> acts upon the
+ canonical form to do the fixup.
+
+ Relocations are maintained on a per section basis,
+ while symbols are maintained on a per BFD basis.
+
+ All that a back end has to do to fit the BFD interface is to create
+ a <<struct reloc_cache_entry>> for each relocation
+ in a particular section, and fill in the right bits of the structures.
+
+@menu
+@* typedef arelent::
+@* howto manager::
+@end menu
+
+*/
+
+/* DO compile in the reloc_code name table from libbfd.h. */
+#define _BFD_MAKE_TABLE_bfd_reloc_code_real
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+/*
+DOCDD
+INODE
+ typedef arelent, howto manager, Relocations, Relocations
+
+SUBSECTION
+ typedef arelent
+
+ This is the structure of a relocation entry:
+
+CODE_FRAGMENT
+.
+.typedef enum bfd_reloc_status
+.{
+. {* No errors detected *}
+. bfd_reloc_ok,
+.
+. {* The relocation was performed, but there was an overflow. *}
+. bfd_reloc_overflow,
+.
+. {* The address to relocate was not within the section supplied. *}
+. bfd_reloc_outofrange,
+.
+. {* Used by special functions *}
+. bfd_reloc_continue,
+.
+. {* Unsupported relocation size requested. *}
+. bfd_reloc_notsupported,
+.
+. {* Unused *}
+. bfd_reloc_other,
+.
+. {* The symbol to relocate against was undefined. *}
+. bfd_reloc_undefined,
+.
+. {* The relocation was performed, but may not be ok - presently
+. generated only when linking i960 coff files with i960 b.out
+. 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
+.{
+. {* A pointer into the canonical table of pointers *}
+. struct symbol_cache_entry **sym_ptr_ptr;
+.
+. {* offset in section *}
+. bfd_size_type address;
+.
+. {* addend for relocation value *}
+. bfd_vma addend;
+.
+. {* Pointer to how to perform the required relocation *}
+. reloc_howto_type *howto;
+.
+.} arelent;
+
+*/
+
+/*
+DESCRIPTION
+
+ Here is a description of each of the fields within an <<arelent>>:
+
+ o <<sym_ptr_ptr>>
+
+ The symbol table pointer points to a pointer to the symbol
+ associated with the relocation request. It is
+ the pointer into the table returned by the back end's
+ <<get_symtab>> 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
+ uses the base of the section the symbol is attached to and the
+ value of the symbol as the initial relocation offset. If the
+ symbol pointer is zero, then the section provided is looked up.
+
+ o <<address>>
+
+ The <<address>> 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
+ 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>>
+
+ The <<addend>> 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:
+
+
+| char foo[];
+| main()
+| {
+| return foo[0x12345678];
+| }
+
+ Could be compiled into:
+
+| linkw fp,#-4
+| moveb @@#12345678,d0
+| extbl d0
+| unlk fp
+| rts
+
+
+ This could create a reloc pointing to <<foo>>, but leave the
+ offset in the data, something like:
+
+
+|RELOCATION RECORDS FOR [.text]:
+|offset type value
+|00000006 32 _foo
+|
+|00000000 4e56 fffc ; linkw fp,#-4
+|00000004 1039 1234 5678 ; moveb @@#12345678,d0
+|0000000a 49c0 ; extbl d0
+|0000000c 4e5e ; unlk fp
+|0000000e 4e75 ; rts
+
+
+ Using coff and an 88k, some instructions don't have enough
+ space in them to represent the full address range, and
+ pointers have to be loaded in two parts. So you'd get something like:
+
+
+| or.u r13,r0,hi16(_foo+0x12345678)
+| ld.b r2,r13,lo16(_foo+0x12345678)
+| jmp r1
+
+
+ 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
+|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
+ 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 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. Anything in the data should be ignored.
+
+| save %sp,-112,%sp
+| sethi %hi(_foo+0x12345678),%g2
+| ldsb [%g2+%lo(_foo+0x12345678)],%i0
+| ret
+| restore
+
+ Both relocs contain a pointer to <<foo>>, and the offsets
+ contain junk.
+
+
+|RELOCATION RECORDS FOR [.text]:
+|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
+|0000000c 81c7e008 ; ret
+|00000010 81e80000 ; restore
+
+
+ o <<howto>>
+
+ The <<howto>> 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.
+
+*/
+
+/*
+SUBSUBSECTION
+ <<enum complain_overflow>>
+
+ Indicates what sort of overflow checking should be done when
+ performing a relocation.
+
+CODE_FRAGMENT
+.
+.enum complain_overflow
+.{
+. {* Do not complain on overflow. *}
+. complain_overflow_dont,
+.
+. {* Complain if the bitfield overflows, whether it is considered
+. as signed or unsigned. *}
+. complain_overflow_bitfield,
+.
+. {* Complain if the value overflows when considered as signed
+. number. *}
+. complain_overflow_signed,
+.
+. {* Complain if the value overflows when considered as an
+. unsigned number. *}
+. complain_overflow_unsigned
+.};
+
+*/
+
+/*
+SUBSUBSECTION
+ <<reloc_howto_type>>
+
+ The <<reloc_howto_type>> is a structure which contains all the
+ information that libbfd needs to know to tie up a back end's data.
+
+CODE_FRAGMENT
+.struct symbol_cache_entry; {* Forward declaration *}
+.
+.struct reloc_howto_struct
+.{
+. {* The type field has mainly a documetary use - the back end can
+. 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;
+.
+. {* The value the final relocation is shifted right by. This drops
+. unwanted data from the relocation. *}
+. unsigned int rightshift;
+.
+. {* The size of the item to be relocated. This is *not* a
+. 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
+. when doing overflow checking. *}
+. unsigned int bitsize;
+.
+. {* Notes that the relocation is relative to the location in the
+. data section of the addend. The relocation function will
+. subtract from the relocation value the address of the location
+. being relocated. *}
+. boolean pc_relative;
+.
+. {* The bit position of the reloc value in the destination.
+. The relocated value is left shifted by this amount. *}
+. unsigned int bitpos;
+.
+. {* What type of overflow error should be checked for when
+. relocating. *}
+. enum complain_overflow complain_on_overflow;
+.
+. {* If this field is non null, then the supplied function is
+. 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)
+. PARAMS ((bfd *abfd,
+. arelent *reloc_entry,
+. struct symbol_cache_entry *symbol,
+. PTR data,
+. asection *input_section,
+. bfd *output_bfd,
+. char **error_message));
+.
+. {* The textual name of the relocation type. *}
+. char *name;
+.
+. {* When performing a partial link, some formats must modify the
+. relocations rather than the data - this flag signals this.*}
+. boolean partial_inplace;
+.
+. {* 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
+. sun4 extended relocs, the value in the offset part of a
+. relocating field is garbage so we never use it. In this case
+. the mask would be 0x00000000. *}
+. bfd_vma src_mask;
+.
+. {* 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;
+.
+. {* 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.*}
+. boolean pcrel_offset;
+.
+.};
+
+*/
+
+/*
+FUNCTION
+ The HOWTO Macro
+
+DESCRIPTION
+ The HOWTO define is horrible and will go away.
+
+
+.#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}
+
+DESCRIPTION
+ And will be replaced with the totally magic way. But for the
+ 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)
+.
+DESCRIPTION
+ Helper routine to turn a symbol into a relocation value.
+
+.#define HOWTO_PREPARE(relocation, symbol) \
+. { \
+. if (symbol != (asymbol *)NULL) { \
+. if (bfd_is_com_section (symbol->section)) { \
+. relocation = 0; \
+. } \
+. else { \
+. relocation = symbol->value; \
+. } \
+. } \
+.}
+
+*/
+
+/*
+FUNCTION
+ bfd_get_reloc_size
+
+SYNOPSIS
+ int bfd_get_reloc_size (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)
+ 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
+ arelent_chain
+
+DESCRIPTION
+
+ How relocs are tied together in an <<asection>>:
+
+.typedef struct relent_chain {
+. arelent relent;
+. struct relent_chain *next;
+.} arelent_chain;
+
+*/
+
+
+
+/*
+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,
+ char **error_message);
+
+DESCRIPTION
+ 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
+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_vma output_base = 0;
+ reloc_howto_type *howto = reloc_entry->howto;
+ asection *reloc_target_output_section;
+ asymbol *symbol;
+
+ 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;
+ }
+
+ /* 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 (bfd_is_und_section (symbol->section)
+ && (symbol->flags & BSF_WEAK) == 0
+ && output_bfd == (bfd *) NULL)
+ flag = bfd_reloc_undefined;
+
+ /* If there is a function supplied to handle this relocation type,
+ call it. It'll return `bfd_reloc_continue' if further processing
+ can be done. */
+ if (howto->special_function)
+ {
+ bfd_reloc_status_type cont;
+ cont = howto->special_function (abfd, reloc_entry, symbol, data,
+ input_section, output_bfd,
+ error_message);
+ if (cont != bfd_reloc_continue)
+ return cont;
+ }
+
+ /* Is the address of the relocation really within the section? */
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Work out which section the relocation is targetted at and the
+ initial relocation command value. */
+
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+
+ reloc_target_output_section = symbol->section->output_section;
+
+ /* Convert input-section-relative symbol value to absolute. */
+ if (output_bfd && howto->partial_inplace == false)
+ output_base = 0;
+ else
+ output_base = reloc_target_output_section->vma;
+
+ relocation += output_base + symbol->section->output_offset;
+
+ /* Add in supplied addend. */
+ relocation += reloc_entry->addend;
+
+ /* Here the variable relocation holds the final address of the
+ symbol we are relocating against, plus any addend. */
+
+ if (howto->pc_relative == true)
+ {
+ /* This is a PC relative relocation. We want to set RELOCATION
+ to the distance between the address of the symbol and the
+ location. RELOCATION is already the address of the symbol.
+
+ We start by subtracting the address of the section containing
+ the location.
+
+ If pcrel_offset is set, we must further subtract the position
+ of the location within the section. Some targets arrange for
+ the addend to be the negative of the position of the location
+ within the section; for example, i386-aout does this. For
+ i386-aout, pcrel_offset is false. Some other targets do not
+ include the position of the location; for example, m88kbcs,
+ or ELF. For those targets, pcrel_offset is true.
+
+ If we are producing relocateable output, then we must ensure
+ that this reloc will be correctly computed when the final
+ relocation is done. If pcrel_offset is false we want to wind
+ up with the negative of the location within the section,
+ which means we must adjust the existing addend by the change
+ in the location within the section. If pcrel_offset is true
+ we do not want to adjust the existing addend at all.
+
+ FIXME: This seems logical to me, but for the case of
+ producing relocateable output it is not what the code
+ actually does. I don't want to change it, because it seems
+ far too likely that something will break. */
+
+ 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 (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;
+ return flag;
+ }
+ else
+ {
+ /* This is a partial relocation, but inplace, so modify the
+ 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. */
+
+ reloc_entry->address += input_section->output_offset;
+
+ /* WTF?? */
+ 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
+ {
+ reloc_entry->addend = relocation;
+ }
+ }
+ }
+ else
+ {
+ reloc_entry->addend = 0;
+ }
+
+ /* FIXME: This overflow checking is incomplete, because the value
+ might have overflowed before we get here. For a correct check we
+ need to compute the value in a size larger than bitsize, but we
+ can't reasonably do that for a reloc the same size as a host
+ machine word.
+ FIXME: We should also do overflow checking on the result after
+ adding in the value contained in the object file. */
+ if (howto->complain_on_overflow != complain_overflow_dont
+ && flag == bfd_reloc_ok)
+ {
+ bfd_vma check;
+
+ /* Get the value that will be used for the relocation, but
+ starting at bit position zero. */
+ check = relocation >> howto->rightshift;
+ 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;
+
+ /* The above right shift is incorrect for a signed value.
+ Fix it up by forcing on the upper bits. */
+ if (howto->rightshift > 0
+ && (bfd_signed_vma) relocation < 0)
+ check |= ((bfd_vma) - 1
+ & ~((bfd_vma) - 1
+ >> howto->rightshift));
+ if ((bfd_signed_vma) check > reloc_signed_max
+ || (bfd_signed_vma) check < reloc_signed_min)
+ flag = bfd_reloc_overflow;
+ }
+ 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 ((bfd_vma) check > reloc_unsigned_max)
+ flag = bfd_reloc_overflow;
+ }
+ 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 (((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
+ overflow. */
+ if (howto->rightshift > 0
+ && (bfd_signed_vma) relocation < 0)
+ {
+ check |= ((bfd_vma) - 1
+ & ~((bfd_vma) - 1
+ >> howto->rightshift));
+ if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
+ flag = bfd_reloc_overflow;
+ }
+ else
+ flag = bfd_reloc_overflow;
+ }
+ }
+ break;
+ default:
+ 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)
+ */
+
+ /* 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 <<= (bfd_vma) howto->bitpos;
+
+ /* Wait for the day when all have the mask in them */
+
+ /* What we do:
+ i instruction to be left alone
+ o offset within instruction
+ r relocation offset to apply
+ S src mask
+ D dst mask
+ N ~dst mask
+ A part 1
+ B part 2
+ R result
+
+ Do this:
+ i i i i i o o o o o from bfd_get<size>
+ 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
+ And this:
+ ... i i i i i o o o o o from bfd_get<size>
+ 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
+ -----------------------
+ R R R R R R R R R R put into bfd_put<size>
+ */
+
+#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;
+
+ 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:
+ {
+ long x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
+ relocation = -relocation;
+ DOIT (x);
+ bfd_put_16 (abfd, x, (bfd_byte *) data + addr);
+ }
+ break;
+
+ case 3:
+ /* Do nothing */
+ break;
+
+ 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);
+ }
+#else
+ abort ();
+#endif
+ break;
+ default:
+ return bfd_reloc_other;
+ }
+
+ return flag;
+}
+
+/*
+FUNCTION
+ bfd_install_relocation
+
+SYNOPSIS
+ bfd_reloc_status_type
+ bfd_install_relocation
+ (bfd *abfd,
+ arelent *reloc_entry,
+ PTR data, bfd_vma data_start,
+ asection *input_section,
+ char **error_message);
+
+DESCRIPTION
+ This looks remarkably like <<bfd_perform_relocation>>, except it
+ does not expect that the section contents have been filled in.
+ I.e., it's suitable for use when creating, rather than applying
+ a relocation.
+
+ For now, this function should be considered reserved for the
+ assembler.
+
+*/
+
+
+bfd_reloc_status_type
+bfd_install_relocation (abfd, reloc_entry, data_start, data_start_offset,
+ input_section, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ PTR data_start;
+ bfd_vma data_start_offset;
+ asection *input_section;
+ char **error_message;
+{
+ bfd_vma relocation;
+ bfd_reloc_status_type flag = bfd_reloc_ok;
+ bfd_size_type addr = reloc_entry->address;
+ bfd_vma output_base = 0;
+ reloc_howto_type *howto = reloc_entry->howto;
+ asection *reloc_target_output_section;
+ asymbol *symbol;
+ bfd_byte *data;
+
+ symbol = *(reloc_entry->sym_ptr_ptr);
+ if (bfd_is_abs_section (symbol->section))
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+
+ /* If there is a function supplied to handle this relocation type,
+ call it. It'll return `bfd_reloc_continue' if further processing
+ can be done. */
+ if (howto->special_function)
+ {
+ bfd_reloc_status_type cont;
+ /* XXX - The special_function calls haven't been fixed up to deal
+ with creating new relocations and section contents. */
+ cont = howto->special_function (abfd, reloc_entry, symbol,
+ /* XXX - Non-portable! */
+ ((bfd_byte *) data_start
+ - data_start_offset),
+ input_section, abfd, error_message);
+ if (cont != bfd_reloc_continue)
+ return cont;
+ }
+
+ /* Is the address of the relocation really within the section? */
+ if (reloc_entry->address > input_section->_cooked_size)
+ return bfd_reloc_outofrange;
+
+ /* Work out which section the relocation is targetted at and the
+ initial relocation command value. */
+
+ /* Get symbol value. (Common symbols are special.) */
+ if (bfd_is_com_section (symbol->section))
+ relocation = 0;
+ else
+ relocation = symbol->value;
+
+
+ reloc_target_output_section = symbol->section->output_section;
+
+ /* Convert input-section-relative symbol value to absolute. */
+ if (howto->partial_inplace == false)
+ output_base = 0;
+ else
+ output_base = reloc_target_output_section->vma;
+
+ relocation += output_base + symbol->section->output_offset;
+
+ /* Add in supplied addend. */
+ relocation += reloc_entry->addend;
+
+ /* Here the variable relocation holds the final address of the
+ symbol we are relocating against, plus any addend. */
+
+ if (howto->pc_relative == true)
+ {
+ /* This is a PC relative relocation. We want to set RELOCATION
+ to the distance between the address of the symbol and the
+ location. RELOCATION is already the address of the symbol.
+
+ We start by subtracting the address of the section containing
+ the location.
+
+ If pcrel_offset is set, we must further subtract the position
+ of the location within the section. Some targets arrange for
+ the addend to be the negative of the position of the location
+ within the section; for example, i386-aout does this. For
+ i386-aout, pcrel_offset is false. Some other targets do not
+ include the position of the location; for example, m88kbcs,
+ or ELF. For those targets, pcrel_offset is true.
+
+ If we are producing relocateable output, then we must ensure
+ that this reloc will be correctly computed when the final
+ relocation is done. If pcrel_offset is false we want to wind
+ up with the negative of the location within the section,
+ which means we must adjust the existing addend by the change
+ in the location within the section. If pcrel_offset is true
+ we do not want to adjust the existing addend at all.
+
+ FIXME: This seems logical to me, but for the case of
+ producing relocateable output it is not what the code
+ actually does. I don't want to change it, because it seems
+ far too likely that something will break. */
+
+ relocation -=
+ input_section->output_section->vma + input_section->output_offset;
+
+ if (howto->pcrel_offset == true && howto->partial_inplace == true)
+ relocation -= reloc_entry->address;
+ }
+
+ 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;
+ return flag;
+ }
+ else
+ {
+ /* This is a partial relocation, but inplace, so modify the
+ 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. */
+
+ reloc_entry->address += input_section->output_offset;
+
+ /* WTF?? */
+ 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_install_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_install_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
+ {
+ reloc_entry->addend = relocation;
+ }
+ }
+
+ /* FIXME: This overflow checking is incomplete, because the value
+ might have overflowed before we get here. For a correct check we
+ need to compute the value in a size larger than bitsize, but we
+ can't reasonably do that for a reloc the same size as a host
+ machine word.
+
+ FIXME: We should also do overflow checking on the result after
+ adding in the value contained in the object file. */
+ if (howto->complain_on_overflow != complain_overflow_dont)
+ {
+ bfd_vma check;
+
+ /* Get the value that will be used for the relocation, but
+ starting at bit position zero. */
+ check = relocation >> howto->rightshift;
+ 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;
+
+ /* The above right shift is incorrect for a signed value.
+ Fix it up by forcing on the upper bits. */
+ if (howto->rightshift > 0
+ && (bfd_signed_vma) relocation < 0)
+ check |= ((bfd_vma) - 1
+ & ~((bfd_vma) - 1
+ >> howto->rightshift));
+ if ((bfd_signed_vma) check > reloc_signed_max
+ || (bfd_signed_vma) check < reloc_signed_min)
+ flag = bfd_reloc_overflow;
+ }
+ 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 ((bfd_vma) check > reloc_unsigned_max)
+ flag = bfd_reloc_overflow;
+ }
+ 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 (((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
+ overflow. */
+ if (howto->rightshift > 0
+ && (bfd_signed_vma) relocation < 0)
+ {
+ check |= ((bfd_vma) - 1
+ & ~((bfd_vma) - 1
+ >> howto->rightshift));
+ if (((bfd_vma) check & ~reloc_bits) != (-1 & ~reloc_bits))
+ flag = bfd_reloc_overflow;
+ }
+ else
+ flag = bfd_reloc_overflow;
+ }
+ }
+ break;
+ default:
+ 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)
+ */
+
+ /* 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 <<= (bfd_vma) howto->bitpos;
+
+ /* Wait for the day when all have the mask in them */
+
+ /* What we do:
+ i instruction to be left alone
+ o offset within instruction
+ r relocation offset to apply
+ S src mask
+ D dst mask
+ N ~dst mask
+ A part 1
+ B part 2
+ R result
+
+ Do this:
+ i i i i i o o o o o from bfd_get<size>
+ 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
+ And this:
+ ... i i i i i o o o o o from bfd_get<size>
+ 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
+ -----------------------
+ R R R R R R R R R R put into bfd_put<size>
+ */
+
+#define DOIT(x) \
+ x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
+
+ data = (bfd_byte *) data_start + (addr - data_start_offset);
+
+ switch (howto->size)
+ {
+ case 0:
+ {
+ char x = bfd_get_8 (abfd, (char *) data);
+ DOIT (x);
+ bfd_put_8 (abfd, x, (unsigned char *) data);
+ }
+ break;
+
+ case 1:
+ if (relocation)
+ {
+ short x = bfd_get_16 (abfd, (bfd_byte *) data);
+ DOIT (x);
+ bfd_put_16 (abfd, x, (unsigned char *) data);
+ }
+ break;
+ case 2:
+ if (relocation)
+ {
+ long x = bfd_get_32 (abfd, (bfd_byte *) data);
+ DOIT (x);
+ bfd_put_32 (abfd, x, (bfd_byte *) data);
+ }
+ break;
+ case -2:
+ {
+ long x = bfd_get_32 (abfd, (bfd_byte *) data);
+ relocation = -relocation;
+ DOIT (x);
+ bfd_put_32 (abfd, x, (bfd_byte *) data);
+ }
+ break;
+
+ case 3:
+ /* Do nothing */
+ break;
+
+ case 4:
+ if (relocation)
+ {
+ bfd_vma x = bfd_get_64 (abfd, (bfd_byte *) data);
+ DOIT (x);
+ bfd_put_64 (abfd, x, (bfd_byte *) data);
+ }
+ 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)
+ 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)
+ 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
+INODE
+ howto manager, , typedef arelent, Relocations
+
+SECTION
+ 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
+ using this bit of code.
+
+*/
+
+/*
+TYPEDEF
+ bfd_reloc_code_type
+
+DESCRIPTION
+ The insides of a reloc code. The idea is that, eventually, there
+ will be one enumerator for every type of relocation we ever do.
+ Pass one of these values to <<bfd_reloc_type_lookup>>, and it'll
+ return a howto pointer.
+
+ This does mean that the application must determine the correct
+ enumerator value; you can't get a howto pointer from a random set
+ of attributes.
+
+SENUM
+ bfd_reloc_code_real
+
+ENUM
+ BFD_RELOC_64
+ENUMX
+ BFD_RELOC_32
+ENUMX
+ BFD_RELOC_26
+ENUMX
+ BFD_RELOC_16
+ENUMX
+ BFD_RELOC_14
+ENUMX
+ BFD_RELOC_8
+ENUMDOC
+ Basic absolute relocations of N bits.
+
+ENUM
+ BFD_RELOC_64_PCREL
+ENUMX
+ BFD_RELOC_32_PCREL
+ENUMX
+ BFD_RELOC_24_PCREL
+ENUMX
+ BFD_RELOC_16_PCREL
+ENUMX
+ BFD_RELOC_12_PCREL
+ENUMX
+ BFD_RELOC_8_PCREL
+ENUMDOC
+ PC-relative relocations. Sometimes these are relative to the address
+of the relocation itself; sometimes they are relative to the start of
+the section containing the relocation. It depends on the specific target.
+
+The 24-bit relocation is used in some Intel 960 configurations.
+
+ENUM
+ BFD_RELOC_32_GOT_PCREL
+ENUMX
+ BFD_RELOC_16_GOT_PCREL
+ENUMX
+ BFD_RELOC_8_GOT_PCREL
+ENUMX
+ BFD_RELOC_32_GOTOFF
+ENUMX
+ BFD_RELOC_16_GOTOFF
+ENUMX
+ BFD_RELOC_LO16_GOTOFF
+ENUMX
+ BFD_RELOC_HI16_GOTOFF
+ENUMX
+ BFD_RELOC_HI16_S_GOTOFF
+ENUMX
+ BFD_RELOC_8_GOTOFF
+ENUMX
+ BFD_RELOC_32_PLT_PCREL
+ENUMX
+ BFD_RELOC_24_PLT_PCREL
+ENUMX
+ BFD_RELOC_16_PLT_PCREL
+ENUMX
+ BFD_RELOC_8_PLT_PCREL
+ENUMX
+ BFD_RELOC_32_PLTOFF
+ENUMX
+ BFD_RELOC_16_PLTOFF
+ENUMX
+ BFD_RELOC_LO16_PLTOFF
+ENUMX
+ BFD_RELOC_HI16_PLTOFF
+ENUMX
+ BFD_RELOC_HI16_S_PLTOFF
+ENUMX
+ BFD_RELOC_8_PLTOFF
+ENUMDOC
+ For ELF.
+
+ENUM
+ BFD_RELOC_68K_GLOB_DAT
+ENUMX
+ BFD_RELOC_68K_JMP_SLOT
+ENUMX
+ BFD_RELOC_68K_RELATIVE
+ENUMDOC
+ Relocations used by 68K ELF.
+
+ENUM
+ BFD_RELOC_32_BASEREL
+ENUMX
+ BFD_RELOC_16_BASEREL
+ENUMX
+ BFD_RELOC_LO16_BASEREL
+ENUMX
+ BFD_RELOC_HI16_BASEREL
+ENUMX
+ BFD_RELOC_HI16_S_BASEREL
+ENUMX
+ BFD_RELOC_8_BASEREL
+ENUMX
+ BFD_RELOC_RVA
+ENUMDOC
+ Linkage-table relative.
+
+ENUM
+ BFD_RELOC_8_FFnn
+ENUMDOC
+ Absolute 8-bit relocation, but used to form an address like 0xFFnn.
+
+ENUM
+ BFD_RELOC_32_PCREL_S2
+ENUMX
+ BFD_RELOC_16_PCREL_S2
+ENUMX
+ BFD_RELOC_23_PCREL_S2
+ENUMDOC
+ These PC-relative relocations are stored as word displacements --
+i.e., byte displacements shifted right two bits. The 30-bit word
+displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the
+SPARC. (SPARC tools generally refer to this as <<WDISP30>>.) The
+signed 16-bit displacement is used on the MIPS, and the 23-bit
+displacement is used on the Alpha.
+
+ENUM
+ BFD_RELOC_HI22
+ENUMX
+ BFD_RELOC_LO10
+ENUMDOC
+ High 22 bits and low 10 bits of 32-bit value, placed into lower bits of
+the target word. These are used on the SPARC.
+
+ENUM
+ BFD_RELOC_GPREL16
+ENUMX
+ BFD_RELOC_GPREL32
+ENUMDOC
+ 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.
+
+
+ENUM
+ BFD_RELOC_I960_CALLJ
+ENUMDOC
+ Reloc types used for i960/b.out.
+
+ENUM
+ BFD_RELOC_NONE
+ENUMX
+ BFD_RELOC_SPARC_WDISP22
+ENUMX
+ BFD_RELOC_SPARC22
+ENUMX
+ BFD_RELOC_SPARC13
+ENUMX
+ BFD_RELOC_SPARC_GOT10
+ENUMX
+ BFD_RELOC_SPARC_GOT13
+ENUMX
+ BFD_RELOC_SPARC_GOT22
+ENUMX
+ BFD_RELOC_SPARC_PC10
+ENUMX
+ BFD_RELOC_SPARC_PC22
+ENUMX
+ BFD_RELOC_SPARC_WPLT30
+ENUMX
+ BFD_RELOC_SPARC_COPY
+ENUMX
+ BFD_RELOC_SPARC_GLOB_DAT
+ENUMX
+ BFD_RELOC_SPARC_JMP_SLOT
+ENUMX
+ BFD_RELOC_SPARC_RELATIVE
+ENUMX
+ BFD_RELOC_SPARC_UA32
+ENUMDOC
+ SPARC ELF relocations. There is probably some overlap with other
+ relocation types already defined.
+
+ENUM
+ BFD_RELOC_SPARC_BASE13
+ENUMX
+ BFD_RELOC_SPARC_BASE22
+ENUMDOC
+ I think these are specific to SPARC a.out (e.g., Sun 4).
+
+ENUMEQ
+ BFD_RELOC_SPARC_64
+ BFD_RELOC_64
+ENUMX
+ BFD_RELOC_SPARC_10
+ENUMX
+ BFD_RELOC_SPARC_11
+ENUMX
+ BFD_RELOC_SPARC_OLO10
+ENUMX
+ BFD_RELOC_SPARC_HH22
+ENUMX
+ BFD_RELOC_SPARC_HM10
+ENUMX
+ BFD_RELOC_SPARC_LM22
+ENUMX
+ BFD_RELOC_SPARC_PC_HH22
+ENUMX
+ BFD_RELOC_SPARC_PC_HM10
+ENUMX
+ BFD_RELOC_SPARC_PC_LM22
+ENUMX
+ BFD_RELOC_SPARC_WDISP16
+ENUMX
+ BFD_RELOC_SPARC_WDISP19
+ENUMX
+ BFD_RELOC_SPARC_GLOB_JMP
+ENUMX
+ BFD_RELOC_SPARC_7
+ENUMX
+ BFD_RELOC_SPARC_6
+ENUMX
+ BFD_RELOC_SPARC_5
+ENUMDOC
+ Some relocations we're using for SPARC V9 -- subject to change.
+
+ENUM
+ BFD_RELOC_ALPHA_GPDISP_HI16
+ENUMDOC
+ 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).
+ENUM
+ BFD_RELOC_ALPHA_GPDISP_LO16
+ENUMDOC
+ 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.
+
+ENUM
+ BFD_RELOC_ALPHA_LITERAL
+ENUMX
+ BFD_RELOC_ALPHA_LITUSE
+ENUMDOC
+ 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.
+
+ENUM
+ BFD_RELOC_ALPHA_HINT
+ENUMDOC
+ 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.
+
+ENUM
+ BFD_RELOC_MIPS_JMP
+ENUMDOC
+ Bits 27..2 of the relocation address shifted right 2 bits;
+ simple reloc otherwise.
+
+ENUM
+ BFD_RELOC_HI16
+ENUMDOC
+ High 16 bits of 32-bit value; simple reloc.
+ENUM
+ BFD_RELOC_HI16_S
+ENUMDOC
+ High 16 bits of 32-bit value but the low 16 bits will be sign
+ extended and added to form the final result. If the low 16
+ bits form a negative number, we need to add one to the high value
+ to compensate for the borrow when the low bits are added.
+ENUM
+ BFD_RELOC_LO16
+ENUMDOC
+ Low 16 bits.
+ENUM
+ BFD_RELOC_PCREL_HI16_S
+ENUMDOC
+ Like BFD_RELOC_HI16_S, but PC relative.
+ENUM
+ BFD_RELOC_PCREL_LO16
+ENUMDOC
+ Like BFD_RELOC_LO16, but PC relative.
+
+ENUMEQ
+ BFD_RELOC_MIPS_GPREL
+ BFD_RELOC_GPREL16
+ENUMDOC
+ Relocation relative to the global pointer.
+
+ENUM
+ BFD_RELOC_MIPS_LITERAL
+ENUMDOC
+ Relocation against a MIPS literal section.
+
+ENUM
+ BFD_RELOC_MIPS_GOT16
+ENUMX
+ BFD_RELOC_MIPS_CALL16
+ENUMEQX
+ BFD_RELOC_MIPS_GPREL32
+ BFD_RELOC_GPREL32
+ENUMX
+ BFD_RELOC_MIPS_GOT_HI16
+ENUMX
+ BFD_RELOC_MIPS_GOT_LO16
+ENUMX
+ BFD_RELOC_MIPS_CALL_HI16
+ENUMX
+ BFD_RELOC_MIPS_CALL_LO16
+ENUMDOC
+ MIPS ELF relocations.
+
+ENUM
+ BFD_RELOC_386_GOT32
+ENUMX
+ BFD_RELOC_386_PLT32
+ENUMX
+ BFD_RELOC_386_COPY
+ENUMX
+ BFD_RELOC_386_GLOB_DAT
+ENUMX
+ BFD_RELOC_386_JUMP_SLOT
+ENUMX
+ BFD_RELOC_386_RELATIVE
+ENUMX
+ BFD_RELOC_386_GOTOFF
+ENUMX
+ BFD_RELOC_386_GOTPC
+ENUMDOC
+ i386/elf relocations
+
+ENUM
+ BFD_RELOC_NS32K_IMM_8
+ENUMX
+ BFD_RELOC_NS32K_IMM_16
+ENUMX
+ BFD_RELOC_NS32K_IMM_32
+ENUMX
+ BFD_RELOC_NS32K_IMM_8_PCREL
+ENUMX
+ BFD_RELOC_NS32K_IMM_16_PCREL
+ENUMX
+ BFD_RELOC_NS32K_IMM_32_PCREL
+ENUMX
+ BFD_RELOC_NS32K_DISP_8
+ENUMX
+ BFD_RELOC_NS32K_DISP_16
+ENUMX
+ BFD_RELOC_NS32K_DISP_32
+ENUMX
+ BFD_RELOC_NS32K_DISP_8_PCREL
+ENUMX
+ BFD_RELOC_NS32K_DISP_16_PCREL
+ENUMX
+ BFD_RELOC_NS32K_DISP_32_PCREL
+ENUMDOC
+ ns32k relocations
+
+ENUM
+ BFD_RELOC_PPC_B26
+ENUMX
+ BFD_RELOC_PPC_BA26
+ENUMX
+ BFD_RELOC_PPC_TOC16
+ENUMX
+ BFD_RELOC_PPC_B16
+ENUMX
+ BFD_RELOC_PPC_B16_BRTAKEN
+ENUMX
+ BFD_RELOC_PPC_B16_BRNTAKEN
+ENUMX
+ BFD_RELOC_PPC_BA16
+ENUMX
+ BFD_RELOC_PPC_BA16_BRTAKEN
+ENUMX
+ BFD_RELOC_PPC_BA16_BRNTAKEN
+ENUMX
+ BFD_RELOC_PPC_COPY
+ENUMX
+ BFD_RELOC_PPC_GLOB_DAT
+ENUMX
+ BFD_RELOC_PPC_JMP_SLOT
+ENUMX
+ BFD_RELOC_PPC_RELATIVE
+ENUMX
+ BFD_RELOC_PPC_LOCAL24PC
+ENUMX
+ BFD_RELOC_PPC_EMB_NADDR32
+ENUMX
+ BFD_RELOC_PPC_EMB_NADDR16
+ENUMX
+ BFD_RELOC_PPC_EMB_NADDR16_LO
+ENUMX
+ BFD_RELOC_PPC_EMB_NADDR16_HI
+ENUMX
+ BFD_RELOC_PPC_EMB_NADDR16_HA
+ENUMX
+ BFD_RELOC_PPC_EMB_SDAI16
+ENUMX
+ BFD_RELOC_PPC_EMB_SDA2I16
+ENUMX
+ BFD_RELOC_PPC_EMB_SDA2REL
+ENUMX
+ BFD_RELOC_PPC_EMB_SDA21
+ENUMX
+ BFD_RELOC_PPC_EMB_MRKREF
+ENUMX
+ BFD_RELOC_PPC_EMB_RELSEC16
+ENUMX
+ BFD_RELOC_PPC_EMB_RELST_LO
+ENUMX
+ BFD_RELOC_PPC_EMB_RELST_HI
+ENUMX
+ BFD_RELOC_PPC_EMB_RELST_HA
+ENUMX
+ BFD_RELOC_PPC_EMB_BIT_FLD
+ENUMX
+ BFD_RELOC_PPC_EMB_RELSDA
+ENUMDOC
+ Power(rs6000) and PowerPC relocations.
+
+ENUM
+ BFD_RELOC_CTOR
+ENUMDOC
+ The type of reloc used to build a contructor table - at the moment
+ probably a 32 bit wide absolute relocation, but the target can choose.
+ It generally does map to one of the other relocation types.
+
+ENUM
+ BFD_RELOC_ARM_PCREL_BRANCH
+ENUMDOC
+ ARM 26 bit pc-relative branch. The lowest two bits must be zero and are
+ not stored in the instruction.
+ENUM
+ BFD_RELOC_ARM_IMMEDIATE
+ENUMX
+ BFD_RELOC_ARM_OFFSET_IMM
+ENUMX
+ BFD_RELOC_ARM_SHIFT_IMM
+ENUMX
+ BFD_RELOC_ARM_SWI
+ENUMX
+ BFD_RELOC_ARM_MULTI
+ENUMX
+ BFD_RELOC_ARM_CP_OFF_IMM
+ENUMX
+ BFD_RELOC_ARM_ADR_IMM
+ENUMX
+ BFD_RELOC_ARM_LDR_IMM
+ENUMX
+ BFD_RELOC_ARM_LITERAL
+ENUMX
+ BFD_RELOC_ARM_IN_POOL
+ENUMDOC
+ These relocs are only used within the ARM assembler. They are not
+ (at present) written to any object files.
+
+COMMENT
+ENDSENUM
+ BFD_RELOC_UNUSED
+CODE_FRAGMENT
+.
+.typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
+*/
+
+
+/*
+FUNCTION
+ bfd_reloc_type_lookup
+
+SYNOPSIS
+ reloc_howto_type *
+ bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
+
+DESCRIPTION
+ Return a pointer to a howto structure which, when
+ invoked, will perform the relocation @var{code} on data from the
+ architecture noted.
+
+*/
+
+
+reloc_howto_type *
+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);
+
+
+/*
+INTERNAL_FUNCTION
+ bfd_default_reloc_type_lookup
+
+SYNOPSIS
+ reloc_howto_type *bfd_default_reloc_type_lookup
+ (bfd *abfd, bfd_reloc_code_real_type code);
+
+DESCRIPTION
+ Provides a default relocation lookup routine for any architecture.
+
+
+*/
+
+reloc_howto_type *
+bfd_default_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type 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 ();
+ }
+ default:
+ BFD_FAIL ();
+ }
+ return (reloc_howto_type *) NULL;
+}
+
+/*
+FUNCTION
+ bfd_get_reloc_code_name
+
+SYNOPSIS
+ const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code);
+
+DESCRIPTION
+ Provides a printable name for the supplied relocation code.
+ Useful mainly for printing error messages.
+*/
+
+const char *
+bfd_get_reloc_code_name (code)
+ bfd_reloc_code_real_type code;
+{
+ if (code > BFD_RELOC_UNUSED)
+ return 0;
+ return bfd_reloc_code_real_names[(int)code];
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_generic_relax_section
+
+SYNOPSIS
+ boolean bfd_generic_relax_section
+ (bfd *abfd,
+ asection *section,
+ 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
+bfd_generic_relax_section (abfd, section, link_info, again)
+ bfd *abfd;
+ asection *section;
+ struct bfd_link_info *link_info;
+ boolean *again;
+{
+ *again = false;
+ return true;
+}
+
+/*
+INTERNAL_FUNCTION
+ bfd_generic_get_relocated_section_contents
+
+SYNOPSIS
+ bfd_byte *
+ bfd_generic_get_relocated_section_contents (bfd *abfd,
+ struct bfd_link_info *link_info,
+ struct bfd_link_order *link_order,
+ bfd_byte *data,
+ boolean relocateable,
+ asymbol **symbols);
+
+DESCRIPTION
+ Provides default handling of relocation effort for back ends
+ which can't be bothered to do it efficiently.
+
+*/
+
+bfd_byte *
+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;
+{
+ /* Get enough memory to hold the stuff */
+ 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 **) bfd_malloc ((size_t) reloc_size);
+ if (reloc_vector == NULL && reloc_size != 0)
+ goto error_return;
+
+ /* read in the section */
+ 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;
+
+ 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++)
+ {
+ 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);
+
+ 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 (reloc_vector != NULL)
+ free (reloc_vector);
+ return data;
+
+error_return:
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return NULL;
+}
diff --git a/contrib/gdb/bfd/reloc16.c b/contrib/gdb/bfd/reloc16.c
new file mode 100644
index 0000000..e88d50f
--- /dev/null
+++ b/contrib/gdb/bfd/reloc16.c
@@ -0,0 +1,289 @@
+/* 8 and 16 bit COFF relocation functions, for BFD.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+Most of this hacked by Steve Chamberlain,
+ sac@cygnus.com
+*/
+
+/* These routines are used by coff-h8300 and coff-z8k to do
+ relocation.
+
+ FIXME: This code should be rewritten to support the new COFF
+ linker. Basically, they need to deal with COFF relocs rather than
+ BFD generic relocs. They should store the relocs in some location
+ where coff_link_input_bfd can find them (and coff_link_input_bfd
+ should be changed to use this location rather than rereading the
+ file) (unless info->keep_memory is false, in which case they should
+ free up the relocs after dealing with them). */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "obstack.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "genlink.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+bfd_vma
+bfd_coff_reloc16_get_value (reloc, link_info, input_section)
+ arelent *reloc;
+ struct bfd_link_info *link_info;
+ asection *input_section;
+{
+ bfd_vma value;
+ asymbol *symbol = *(reloc->sym_ptr_ptr);
+ /* A symbol holds a pointer to a section, and an offset from the
+ base of the section. To relocate, we find where the section will
+ live in the output and add that in */
+
+ if (bfd_is_und_section (symbol->section))
+ {
+ struct bfd_link_hash_entry *h;
+
+ /* The symbol is undefined in this BFD. Look it up in the
+ global linker hash table. FIXME: This should be changed when
+ we convert this stuff to use a specific final_link function
+ and change the interface to bfd_relax_section to not require
+ the generic symbols. */
+ h = bfd_wrapped_link_hash_lookup (input_section->owner, link_info,
+ bfd_asymbol_name (symbol),
+ false, false, true);
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak))
+ value = (h->u.def.value
+ + h->u.def.section->output_section->vma
+ + h->u.def.section->output_offset);
+ else if (h != (struct bfd_link_hash_entry *) NULL
+ && h->type == bfd_link_hash_common)
+ value = h->u.c.size;
+ else
+ {
+ if (! ((*link_info->callbacks->undefined_symbol)
+ (link_info, bfd_asymbol_name (symbol),
+ input_section->owner, input_section, reloc->address)))
+ abort ();
+ value = 0;
+ }
+ }
+ else
+ {
+ value = symbol->value +
+ symbol->section->output_offset +
+ symbol->section->output_section->vma;
+ }
+
+ /* Add the value contained in the relocation */
+ value += reloc->addend;
+
+ return value;
+}
+
+void
+bfd_perform_slip(abfd, slip, input_section, value)
+ bfd *abfd;
+ unsigned int slip;
+ asection *input_section;
+ bfd_vma value;
+{
+ asymbol **s;
+
+ s = _bfd_generic_link_get_symbols (abfd);
+ BFD_ASSERT (s != (asymbol **) NULL);
+
+ /* Find all symbols past this point, and make them know
+ what's happened */
+ while (*s)
+ {
+ asymbol *p = *s;
+ if (p->section == input_section)
+ {
+ /* This was pointing into this section, so mangle it */
+ if (p->value > value)
+ {
+ p->value -= slip;
+ if (p->udata.p != NULL)
+ {
+ struct generic_link_hash_entry *h;
+
+ h = (struct generic_link_hash_entry *) p->udata.p;
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak);
+ h->root.u.def.value -= slip;
+ BFD_ASSERT (h->root.u.def.value == p->value);
+ }
+ }
+ }
+ s++;
+ }
+}
+
+boolean
+bfd_coff_reloc16_relax_section (abfd, i, link_info, again)
+ bfd *abfd;
+ asection *i;
+ struct bfd_link_info *link_info;
+ boolean *again;
+{
+ /* Get enough memory to hold the stuff */
+ bfd *input_bfd = i->owner;
+ asection *input_section = i;
+ int shrink = 0 ;
+ long reloc_size = bfd_get_reloc_upper_bound (input_bfd, input_section);
+ arelent **reloc_vector = NULL;
+ long reloc_count;
+
+ /* We only run this relaxation once. It might work to run it more
+ often, but it hasn't been tested. */
+ *again = false;
+
+ if (reloc_size < 0)
+ return false;
+
+ reloc_vector = (arelent **) bfd_malloc (reloc_size);
+ if (!reloc_vector && reloc_size > 0)
+ return false;
+
+ /* Get the relocs and think about them */
+ reloc_count =
+ bfd_canonicalize_reloc (input_bfd, input_section, reloc_vector,
+ _bfd_generic_link_get_symbols (input_bfd));
+ if (reloc_count < 0)
+ {
+ free (reloc_vector);
+ return false;
+ }
+
+ if (reloc_count > 0)
+ {
+ arelent **parent;
+ for (parent = reloc_vector; *parent; parent++)
+ {
+ shrink = bfd_coff_reloc16_estimate (abfd, input_section,
+ *parent, shrink, link_info);
+ }
+ }
+
+ input_section->_cooked_size -= shrink;
+ free((char *)reloc_vector);
+ return true;
+}
+
+bfd_byte *
+bfd_coff_reloc16_get_relocated_section_contents(in_abfd,
+ link_info,
+ link_order,
+ data,
+ relocateable,
+ symbols)
+ bfd *in_abfd;
+ struct bfd_link_info *link_info;
+ struct bfd_link_order *link_order;
+ bfd_byte *data;
+ boolean relocateable;
+ asymbol **symbols;
+{
+ /* Get enough memory to hold the stuff */
+ 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;
+ long reloc_count;
+
+ if (reloc_size < 0)
+ return NULL;
+
+ /* If producing relocateable output, don't bother to relax. */
+ if (relocateable)
+ return bfd_generic_get_relocated_section_contents (in_abfd, link_info,
+ link_order,
+ data, relocateable,
+ symbols);
+
+ /* read in the section */
+ if (! bfd_get_section_contents(input_bfd,
+ input_section,
+ data,
+ 0,
+ input_section->_raw_size))
+ return NULL;
+
+
+ reloc_vector = (arelent **) bfd_malloc((size_t) reloc_size);
+ if (!reloc_vector && reloc_size != 0)
+ return NULL;
+
+ reloc_count = bfd_canonicalize_reloc (input_bfd,
+ input_section,
+ reloc_vector,
+ symbols);
+ if (reloc_count < 0)
+ {
+ free (reloc_vector);
+ return NULL;
+ }
+
+ if (reloc_count > 0)
+ {
+ arelent **parent = reloc_vector;
+ arelent *reloc ;
+ unsigned int dst_address = 0;
+ unsigned int src_address = 0;
+ unsigned int run;
+ unsigned int idx;
+
+ /* Find how long a run we can do */
+ while (dst_address < link_order->size)
+ {
+ reloc = *parent;
+ if (reloc)
+ {
+ /* Note that the relaxing didn't tie up the addresses in the
+ relocation, so we use the original address to work out the
+ run of non-relocated data */
+ run = reloc->address - src_address;
+ parent++;
+ }
+ else
+ {
+ run = link_order->size - dst_address;
+ }
+ /* Copy the bytes */
+ for (idx = 0; idx < run; idx++)
+ {
+ data[dst_address++] = data[src_address++];
+ }
+
+ /* Now do the relocation */
+
+ if (reloc)
+ {
+ bfd_coff_reloc16_extra_cases (input_bfd, link_info, link_order,
+ reloc, data, &src_address,
+ &dst_address);
+ }
+ }
+ }
+ free((char *)reloc_vector);
+ return data;
+}
+
diff --git a/contrib/gdb/bfd/riscix.c b/contrib/gdb/bfd/riscix.c
new file mode 100644
index 0000000..21a86d5
--- /dev/null
+++ b/contrib/gdb/bfd/riscix.c
@@ -0,0 +1,644 @@
+/* BFD back-end for RISC iX (Acorn, arm) binaries.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* RISC iX overloads the MAGIC field to indicate more than just the usual
+ [ZNO]MAGIC values. Also included are squeezing information and
+ shared library usage. */
+
+/* The following come from the man page. */
+#define SHLIBLEN 60
+
+#define MF_IMPURE 00200
+#define MF_SQUEEZED 01000
+#define MF_USES_SL 02000
+#define MF_IS_SL 04000
+
+/* Common combinations. */
+#define IMAGIC (MF_IMPURE|ZMAGIC) /* Demand load (impure text) */
+#define SPOMAGIC (MF_USES_SL|OMAGIC) /* OMAGIC with large header */
+ /* -- may contain a ref to a */
+ /* shared lib required by the */
+ /* object. */
+#define SLOMAGIC (MF_IS_SL|OMAGIC) /* A reference to a shared library */
+ /* The text portion of the object */
+ /* contains "overflow text" from */
+ /* the shared library to be linked */
+ /* in with an object */
+#define QMAGIC (MF_SQUEEZED|ZMAGIC) /* Sqeezed demand paged. */
+ /* NOTE: This interpretation of */
+ /* QMAGIC seems to be at variance */
+ /* With that used on other */
+ /* architectures. */
+#define SPZMAGIC (MF_USES_SL|ZMAGIC) /* program which uses sl */
+#define SPQMAGIC (MF_USES_SL|QMAGIC) /* sqeezed ditto */
+#define SLZMAGIC (MF_IS_SL|ZMAGIC) /* shared lib part of prog */
+#define SLPZMAGIC (MF_USES_SL|SLZMAGIC) /* sl which uses another */
+
+#define N_SHARED_LIB(x) ((x).a_info & MF_USES_SL)
+
+/* Only a pure OMAGIC file has the minimal header */
+#define N_TXTOFF(x) \
+ ((x).a_info == OMAGIC ? 32 \
+ : (N_MAGIC(x) == ZMAGIC) ? TARGET_PAGE_SIZE \
+ : 999)
+
+#define N_TXTADDR(x) \
+ (N_MAGIC(x) != ZMAGIC ? 0 /* object file or NMAGIC */ \
+ /* Programs with shared libs are loaded at the first page after all the \
+ text segments of the shared library programs. Without looking this \
+ up we can't know exactly what the address will be. A reasonable guess \
+ is that a_entry will be in the first page of the executable. */ \
+ : N_SHARED_LIB(x) ? ((x).a_entry & ~(TARGET_PAGE_SIZE - 1)) \
+ : TEXT_START_ADDR)
+
+#define N_SYMOFF(x) \
+ (N_TXTOFF (x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize)
+
+#define N_STROFF(x) (N_SYMOFF (x) + (x).a_syms)
+
+#define TEXT_START_ADDR 32768
+#define TARGET_PAGE_SIZE 32768
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_arm
+
+#define MY(OP) CAT(riscix_,OP)
+#define TARGETNAME "a.out-riscix"
+#define N_BADMAG(x) ((((x).a_info & ~007200) != ZMAGIC) && \
+ (((x).a_info & ~006000) != OMAGIC) && \
+ ((x).a_info != NMAGIC))
+#define N_MAGIC(x) ((x).a_info & ~07200)
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "assert.h"
+
+#define WRITE_HEADERS(abfd, execp) \
+ { \
+ bfd_size_type text_size; /* dummy vars */ \
+ file_ptr text_end; \
+ if (adata(abfd).magic == undecided_magic) \
+ NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end); \
+ \
+ execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; \
+ execp->a_entry = bfd_get_start_address (abfd); \
+ \
+ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * \
+ obj_reloc_entry_size (abfd)); \
+ NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes); \
+ \
+ 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_outsymbols (abfd) != (asymbol **) NULL \
+ && bfd_get_symcount (abfd) != 0) \
+ { \
+ if (bfd_seek (abfd, (file_ptr)(N_SYMOFF(*execp)), SEEK_SET) != 0) \
+ return false; \
+ \
+ if (! NAME(aout,write_syms)(abfd)) return false; \
+ \
+ if (bfd_seek (abfd, (file_ptr)(N_TRELOFF(*execp)), SEEK_SET) != 0) \
+ return false; \
+ \
+ if (! riscix_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; \
+ } \
+ }
+
+#include "libaout.h"
+#include "aout/aout64.h"
+
+static bfd_reloc_status_type
+riscix_fix_pcrel_26_done PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+static bfd_reloc_status_type
+riscix_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR,
+ asection *, bfd *, char **));
+
+static reloc_howto_type riscix_std_reloc_howto[] = {
+ /* 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),
+ HOWTO( 3, 2, 3, 26, true, 0, complain_overflow_signed, riscix_fix_pcrel_26 , "ARM26", true, 0x00ffffff,0x00ffffff, false),
+ HOWTO( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", true, 0x000000ff,0x000000ff, true),
+ HOWTO( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, true),
+ HOWTO( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, true),
+ HOWTO( 7, 2, 3, 26, false, 0, complain_overflow_signed, riscix_fix_pcrel_26_done, "ARM26D",true,0x00ffffff,0x00ffffff, false),
+ {-1},
+ HOWTO( 9, 0, -1, 16, false, 0, complain_overflow_bitfield,0,"NEG16", true, 0x0000ffff,0x0000ffff, false),
+ HOWTO( 10, 0, -2, 32, false, 0, complain_overflow_bitfield,0,"NEG32", true, 0xffffffff,0xffffffff, false)
+};
+
+#define RISCIX_TABLE_SIZE \
+ (sizeof (riscix_std_reloc_howto) / sizeof (reloc_howto_type))
+
+
+static bfd_reloc_status_type
+riscix_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ /* This is dead simple at present. */
+ return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+riscix_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section,
+ output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ bfd_vma relocation;
+ bfd_size_type addr = reloc_entry->address;
+ long target = bfd_get_32 (abfd, (bfd_byte *) data + addr);
+ bfd_reloc_status_type flag = bfd_reloc_ok;
+
+ /* If this is an undefined symbol, return error */
+ if (symbol->section == &bfd_und_section
+ && (symbol->flags & BSF_WEAK) == 0)
+ return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined;
+
+ /* If the sections are different, and we are doing a partial relocation,
+ just ignore it for now. */
+ if (symbol->section->name != input_section->name
+ && output_bfd != (bfd *)NULL)
+ return bfd_reloc_continue;
+
+ relocation = (target & 0x00ffffff) << 2;
+ relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */
+ relocation += symbol->value;
+ relocation += symbol->section->output_section->vma;
+ relocation += symbol->section->output_offset;
+ relocation += reloc_entry->addend;
+ relocation -= input_section->output_section->vma;
+ relocation -= input_section->output_offset;
+ relocation -= addr;
+ if (relocation & 3)
+ return bfd_reloc_overflow;
+
+ /* Check for overflow */
+ if (relocation & 0x02000000)
+ {
+ if ((relocation & ~0x03ffffff) != ~0x03ffffff)
+ flag = bfd_reloc_overflow;
+ }
+ else if (relocation & ~0x03ffffff)
+ flag = bfd_reloc_overflow;
+
+ target &= ~0x00ffffff;
+ target |= (relocation >> 2) & 0x00ffffff;
+ bfd_put_32 (abfd, target, (bfd_byte *) data + addr);
+
+ /* Now the ARM magic... Change the reloc type so that it is marked as done.
+ Strictly this is only necessary if we are doing a partial relocation. */
+ reloc_entry->howto = &riscix_std_reloc_howto[7];
+
+ return flag;
+}
+
+reloc_howto_type *
+DEFUN(riscix_reloc_type_lookup,(abfd,code),
+ bfd *abfd AND
+ bfd_reloc_code_real_type code)
+{
+#define ASTD(i,j) case i: return &riscix_std_reloc_howto[j]
+ if (code == BFD_RELOC_CTOR)
+ switch (bfd_get_arch_info (abfd)->bits_per_address)
+ {
+ case 32:
+ code = BFD_RELOC_32;
+ break;
+ default: return (reloc_howto_type *) NULL;
+ }
+
+ switch (code)
+ {
+ ASTD (BFD_RELOC_16, 1);
+ ASTD (BFD_RELOC_32, 2);
+ ASTD (BFD_RELOC_ARM_PCREL_BRANCH, 3);
+ ASTD (BFD_RELOC_8_PCREL, 4);
+ ASTD (BFD_RELOC_16_PCREL, 5);
+ ASTD (BFD_RELOC_32_PCREL, 6);
+ default: return (reloc_howto_type *) NULL;
+ }
+}
+
+#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define MY_bfd_final_link _bfd_generic_final_link
+
+#define MY_bfd_reloc_type_lookup riscix_reloc_type_lookup
+#define MY_canonicalize_reloc riscix_canonicalize_reloc
+#define MY_object_p riscix_object_p
+
+static const bfd_target *riscix_callback PARAMS ((bfd *));
+
+void
+riscix_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);
+ int r_extern;
+ int r_length;
+ int r_pcrel;
+ int r_neg = 0; /* Negative relocs use the BASEREL bit. */
+ asection *output_section = sym->section->output_section;
+
+ PUT_WORD(abfd, g->address, natptr->r_address);
+
+ r_length = g->howto->size ; /* Size as a power of two */
+ if (r_length < 0)
+ {
+ r_length = -r_length;
+ r_neg = 1;
+ }
+
+ r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
+
+ /* For RISC iX, in pc-relative relocs the r_pcrel bit means that the
+ relocation has been done already (Only for the 26-bit one I think)???!!!
+ */
+
+ if (r_length == 3)
+ r_pcrel = r_pcrel ? 0 : 1;
+
+
+#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 */
+
+ /* If this relocation is relative to a symbol then set the
+ r_index to the symbols index, and the r_extern bit.
+
+ Absolute symbols can come in in two ways, either as an offset
+ from the abs section, or as a symbol which has an abs value.
+ check for that here
+ */
+
+ if (bfd_is_com_section (output_section)
+ || output_section == &bfd_abs_section
+ || output_section == &bfd_und_section)
+ {
+ if (bfd_abs_section.symbol == sym)
+ {
+ /* Whoops, looked like an abs symbol, but is really an offset
+ from the abs section */
+ r_index = 0;
+ r_extern = 0;
+ }
+ else
+ {
+ /* Fill in symbol */
+ r_extern = 1;
+ r_index = stoi((*(g->sym_ptr_ptr))->flags);
+ }
+ }
+ else
+ {
+ /* Just an ordinary section */
+ r_extern = 0;
+ r_index = output_section->target_index;
+ }
+
+ /* now the fun stuff */
+ if (bfd_header_big_endian (abfd))
+ {
+ natptr->r_index[0] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[2] = r_index;
+ natptr->r_type[0] =
+ ( (r_extern ? RELOC_STD_BITS_EXTERN_BIG: 0)
+ | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG: 0)
+ | (r_neg ? RELOC_STD_BITS_BASEREL_BIG: 0)
+ | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
+ }
+ else
+ {
+ natptr->r_index[2] = r_index >> 16;
+ natptr->r_index[1] = r_index >> 8;
+ natptr->r_index[0] = r_index;
+ natptr->r_type[0] =
+ ( (r_extern ? RELOC_STD_BITS_EXTERN_LITTLE: 0)
+ | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE: 0)
+ | (r_neg ? RELOC_STD_BITS_BASEREL_LITTLE: 0)
+ | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
+ }
+}
+
+boolean
+riscix_squirt_out_relocs (abfd, section)
+ bfd *abfd;
+ asection *section;
+{
+ arelent **generic;
+ unsigned char *native, *natptr;
+ size_t each_size;
+
+ unsigned int count = section->reloc_count;
+ size_t natsize;
+
+ if (count == 0) return true;
+
+ each_size = obj_reloc_entry_size (abfd);
+ natsize = each_size * count;
+ native = (unsigned char *) bfd_zalloc (abfd, natsize);
+ if (!native)
+ return false;
+
+ generic = section->orelocation;
+
+ for (natptr = native;
+ count != 0;
+ --count, natptr += each_size, ++generic)
+ riscix_swap_std_reloc_out (abfd, *generic,
+ (struct reloc_std_external *) natptr);
+
+ if ( bfd_write ((PTR) native, 1, natsize, abfd) != natsize)
+ {
+ bfd_release(abfd, native);
+ return false;
+ }
+
+ bfd_release (abfd, native);
+ return true;
+}
+
+
+/*
+ * This is just like the standard aoutx.h version but we need to do our
+ * own mapping of external reloc type values to howto entries.
+ */
+long
+MY(canonicalize_reloc)(abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *tblptr = section->relocation;
+ unsigned int count, c;
+ extern reloc_howto_type NAME(aout,std_howto_table)[];
+
+ /* If we have already read in the relocation table, return the values. */
+ if (section->flags & SEC_CONSTRUCTOR) {
+ arelent_chain *chain = section->constructor_chain;
+
+ for (count = 0; count < section->reloc_count; count++) {
+ *relptr++ = &chain->relent;
+ chain = chain->next;
+ }
+ *relptr = 0;
+ return section->reloc_count;
+ }
+ if (tblptr && section->reloc_count) {
+ for (count = 0; count++ < section->reloc_count;)
+ *relptr++ = tblptr++;
+ *relptr = 0;
+ return section->reloc_count;
+ }
+
+ if (!NAME(aout,slurp_reloc_table)(abfd, section, symbols))
+ return -1;
+ tblptr = section->relocation;
+
+ /* fix up howto entries */
+ for (count = 0; count++ < section->reloc_count;)
+ {
+ c = tblptr->howto - NAME(aout,std_howto_table);
+ assert (c < RISCIX_TABLE_SIZE);
+ tblptr->howto = &riscix_std_reloc_howto[c];
+
+ *relptr++ = tblptr++;
+ }
+ *relptr = 0;
+ return section->reloc_count;
+}
+
+/* This is the same as NAME(aout,some_aout_object_p), but has different
+ expansions of the macro definitions. */
+
+const bfd_target *
+riscix_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;
+ const bfd_target *result;
+
+ rawptr = ((struct aout_data_struct *)
+ bfd_zalloc (abfd, sizeof (struct aout_data_struct )));
+
+ if (rawptr == NULL)
+ return 0;
+
+ oldrawptr = abfd->tdata.aout_data;
+ abfd->tdata.aout_data = rawptr;
+
+ /* Copy the contents of the old tdata struct.
+ In particular, we want the subformat, since for hpux it was set in
+ hp300hpux.c:swap_exec_header_in and will be used in
+ hp300hpux.c:callback. */
+ if (oldrawptr != NULL)
+ *abfd->tdata.aout_data = *oldrawptr;
+
+ abfd->tdata.aout_data->a.hdr = &rawptr->e;
+ *(abfd->tdata.aout_data->a.hdr) = *execp; /* Copy in the internal_exec
+ struct */
+ execp = abfd->tdata.aout_data->a.hdr;
+
+ /* Set the file flags */
+ abfd->flags = NO_FLAGS;
+ if (execp->a_drsize || execp->a_trsize)
+ abfd->flags |= HAS_RELOC;
+ /* 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 ((execp->a_info & MF_SQUEEZED) != 0) /* Squeezed files aren't supported
+ (yet)! */
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ else if ((execp->a_info & MF_IS_SL) != 0) /* Nor are shared libraries */
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+ else if (N_MAGIC (*execp) == ZMAGIC)
+ {
+ abfd->flags |= D_PAGED | WP_TEXT;
+ adata (abfd).magic = z_magic;
+ }
+ else if (N_MAGIC (*execp) == NMAGIC)
+ {
+ abfd->flags |= WP_TEXT;
+ adata (abfd).magic = n_magic;
+ }
+ else if (N_MAGIC (*execp) == OMAGIC)
+ adata (abfd).magic = o_magic;
+ else
+ {
+ /* Should have been checked with N_BADMAG before this routine
+ was called. */
+ abort ();
+ }
+
+ bfd_get_start_address (abfd) = execp->a_entry;
+
+ obj_aout_symbols (abfd) = (aout_symbol_type *)NULL;
+ bfd_get_symcount (abfd) = execp->a_syms / sizeof (struct external_nlist);
+
+ /* The default relocation entry size is that of traditional V7 Unix. */
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+
+ /* The default symbol entry size is that of traditional Unix. */
+ obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
+
+ obj_aout_external_syms (abfd) = NULL;
+ obj_aout_external_strings (abfd) = NULL;
+ obj_aout_sym_hashes (abfd) = NULL;
+
+ 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_bsssec (abfd)->flags = SEC_ALLOC;
+
+ 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 != NULL
+ && (abfd->flags & BFD_IN_MEMORY) == 0
+ && (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
+ executable even if their entry point address is 0, as long as
+ their text starts at zero.)
+
+ At some point we should probably break down and stat the file and
+ declare it executable if (one of) its 'x' bits are on... */
+ 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)
+ {
+ }
+ else
+ {
+ free (rawptr);
+ abfd->tdata.aout_data = oldrawptr;
+ }
+ return result;
+}
+
+
+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 */
+ const bfd_target *target;
+
+ if (bfd_read ((PTR) &exec_bytes, 1, EXEC_BYTES_SIZE, abfd)
+ != EXEC_BYTES_SIZE) {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ exec.a_info = bfd_h_get_32 (abfd, exec_bytes.e_info);
+
+ if (N_BADMAG (exec)) return 0;
+#ifdef MACHTYPE_OK
+ if (!(MACHTYPE_OK (N_MACHTYPE (exec)))) return 0;
+#endif
+
+ NAME(aout,swap_exec_header_in)(abfd, &exec_bytes, &exec);
+
+ target = riscix_some_aout_object_p (abfd, &exec, MY(callback));
+
+ return target;
+}
+
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/rs6000-core.c b/contrib/gdb/bfd/rs6000-core.c
new file mode 100644
index 0000000..4889f72
--- /dev/null
+++ b/contrib/gdb/bfd/rs6000-core.c
@@ -0,0 +1,396 @@
+/* IBM RS/6000 "XCOFF" back-end for BFD.
+ Copyright (C) 1990, 1991, 1995 Free Software Foundation, Inc.
+ FIXME: Can someone provide a transliteration of this name into ASCII?
+ Using the following chars caused a compiler warning on HIUX (so I replaced
+ them with octal escapes), and isn't useful without an understanding of what
+ character set it is.
+ Written by Metin G. Ozisik, Mimi Ph\373\364ng-Th\345o V\365,
+ and John Gilmore.
+ Archive support from Damon A. Permezel.
+ Contributed by IBM Corporation and 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This port currently only handles reading object files, except when
+ compiled on an RS/6000 host. -- no archive support, no core files.
+ In all cases, it does not support writing.
+
+ FIXMEmgo comments are left from Metin Ozisik's original port.
+
+ This is in a separate file from coff-rs6000.c, because it includes
+ system include files that conflict with coff/rs6000.h.
+ */
+
+/* Internalcoff.h and coffcode.h modify themselves based on this flag. */
+#define RS6000COFF_C 1
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#ifdef AIX_CORE
+
+/* AOUTHDR is defined by the above. We need another defn of it, from the
+ system include files. Punt the old one and get us a new name for the
+ typedef in the system include files. */
+#ifdef AOUTHDR
+#undef AOUTHDR
+#endif
+#define AOUTHDR second_AOUTHDR
+
+#undef SCNHDR
+
+
+/* ------------------------------------------------------------------------ */
+/* Support for core file stuff.. */
+/* ------------------------------------------------------------------------ */
+
+#include <sys/user.h>
+#include <sys/ldr.h>
+#include <sys/core.h>
+
+
+/* Number of special purpose registers supported by gdb. This value
+ should match `tm.h' in gdb directory. Clean this mess up and use
+ the macros in sys/reg.h. FIXMEmgo. */
+
+#define NUM_OF_SPEC_REGS 7
+
+#define core_hdr(bfd) (((Rs6kCorData*)(bfd->tdata.any))->hdr)
+#define core_datasec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->data_section)
+#define core_stacksec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->stack_section)
+#define core_regsec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->reg_section)
+#define core_reg2sec(bfd) (((Rs6kCorData*)(bfd->tdata.any))->reg2_section)
+
+/* AIX 4.1 Changed the names and locations of a few items in the core file,
+ this seems to be the quickest easiet way to deal with it.
+
+ Note however that encoding magic addresses (STACK_END_ADDR) is going
+ to be _very_ fragile. But I don't see any easy way to get that info
+ right now. */
+#ifdef CORE_VERSION_1
+#define CORE_DATA_SIZE_FIELD c_u.U_dsize
+#define CORE_COMM_FIELD c_u.U_comm
+#define SAVE_FIELD c_mst
+#define STACK_END_ADDR 0x2ff23000
+#else
+#define CORE_DATA_SIZE_FIELD c_u.u_dsize
+#define CORE_COMM_FIELD c_u.u_comm
+#define SAVE_FIELD c_u.u_save
+#define STACK_END_ADDR 0x2ff80000
+#endif
+
+/* These are stored in the bfd's tdata */
+typedef struct {
+ struct core_dump hdr; /* core file header */
+ asection *data_section,
+ *stack_section,
+ *reg_section, /* section for GPRs and special registers. */
+ *reg2_section; /* section for FPRs. */
+
+ /* This tells us where everything is mapped (shared libraries and so on).
+ GDB needs it. */
+ asection *ldinfo_section;
+#define core_ldinfosec(bfd) (((Rs6kCorData *)(bfd->tdata.any))->ldinfo_section)
+} Rs6kCorData;
+
+
+/* Decide if a given bfd represents a `core' file or not. There really is no
+ magic number or anything like, in rs6000coff. */
+
+const bfd_target *
+rs6000coff_core_p (abfd)
+ bfd *abfd;
+{
+ int fd;
+ struct core_dump coredata;
+ struct stat statbuf;
+ char *tmpptr;
+
+ /* Use bfd_xxx routines, rather than O/S primitives to read coredata. FIXMEmgo */
+ fd = open (abfd->filename, O_RDONLY);
+ if (fd < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return NULL;
+ }
+
+ if (fstat (fd, &statbuf) < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ close (fd);
+ return NULL;
+ }
+ if (read (fd, &coredata, sizeof (struct core_dump))
+ != sizeof (struct core_dump))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ close (fd);
+ return NULL;
+ }
+
+ if (close (fd) < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return NULL;
+ }
+
+ /* If the core file ulimit is too small, the system will first
+ omit the data segment, then omit the stack, then decline to
+ dump core altogether (as far as I know UBLOCK_VALID and LE_VALID
+ are always set) (this is based on experimentation on AIX 3.2).
+ Now, the thing is that GDB users will be surprised
+ if segments just silently don't appear (well, maybe they would
+ think to check "info files", I don't know), but we have no way of
+ returning warnings (as opposed to errors).
+
+ For the data segment, we have no choice but to keep going if it's
+ not there, since the default behavior is not to dump it (regardless
+ of the ulimit, it's based on SA_FULLDUMP). But for the stack segment,
+ if it's not there, we refuse to have anything to do with this core
+ file. The usefulness of a core dump without a stack segment is pretty
+ limited anyway. */
+
+ if (!(coredata.c_flag & UBLOCK_VALID)
+ || !(coredata.c_flag & LE_VALID))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if ((coredata.c_flag & CORE_TRUNC)
+ || !(coredata.c_flag & USTACK_VALID))
+ {
+ bfd_set_error (bfd_error_file_truncated);
+ return NULL;
+ }
+
+ /* Don't check the core file size for a full core, AIX 4.1 includes
+ additional shared library sections in a full core. */
+ if (!(coredata.c_flag & FULL_CORE)
+ && ((bfd_vma)coredata.c_stack + coredata.c_size) != statbuf.st_size)
+ {
+ /* If the size is wrong, it means we're misinterpreting something. */
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* Sanity check on the c_tab field. */
+ if ((u_long) coredata.c_tab < sizeof coredata ||
+ (u_long) coredata.c_tab >= statbuf.st_size ||
+ (long) coredata.c_tab >= (long)coredata.c_stack)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* maybe you should alloc space for the whole core chunk over here!! FIXMEmgo */
+ tmpptr = (char*)bfd_zalloc (abfd, sizeof (Rs6kCorData));
+ if (!tmpptr)
+ return NULL;
+
+ set_tdata (abfd, tmpptr);
+
+ /* Copy core file header. */
+ core_hdr (abfd) = coredata;
+
+ /* .stack section. */
+ if ((core_stacksec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
+ == NULL)
+ return NULL;
+ core_stacksec (abfd)->name = ".stack";
+ core_stacksec (abfd)->flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS;
+ core_stacksec (abfd)->_raw_size = coredata.c_size;
+ core_stacksec (abfd)->vma = STACK_END_ADDR - coredata.c_size;
+ core_stacksec (abfd)->filepos = (int)coredata.c_stack; /*???? */
+
+ /* .reg section for GPRs and special registers. */
+ if ((core_regsec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
+ == NULL)
+ return NULL;
+ core_regsec (abfd)->name = ".reg";
+ core_regsec (abfd)->flags = SEC_HAS_CONTENTS;
+ core_regsec (abfd)->_raw_size = (32 + NUM_OF_SPEC_REGS) * 4;
+ core_regsec (abfd)->vma = 0; /* not used?? */
+ core_regsec (abfd)->filepos =
+ (char*)&coredata.SAVE_FIELD - (char*)&coredata;
+
+ /* .reg2 section for FPRs (floating point registers). */
+ if ((core_reg2sec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
+ == NULL)
+ return NULL;
+ core_reg2sec (abfd)->name = ".reg2";
+ core_reg2sec (abfd)->flags = SEC_HAS_CONTENTS;
+ core_reg2sec (abfd)->_raw_size = 8 * 32; /* 32 FPRs. */
+ core_reg2sec (abfd)->vma = 0; /* not used?? */
+ core_reg2sec (abfd)->filepos =
+ (char*)&coredata.SAVE_FIELD.fpr[0] - (char*)&coredata;
+
+ if ((core_ldinfosec (abfd) = (asection*) bfd_zalloc (abfd, sizeof (asection)))
+ == NULL)
+ return NULL;
+ core_ldinfosec (abfd)->name = ".ldinfo";
+ core_ldinfosec (abfd)->flags = SEC_HAS_CONTENTS;
+ /* To actually find out how long this section is in this particular
+ core dump would require going down the whole list of struct ld_info's.
+ See if we can just fake it. */
+ core_ldinfosec (abfd)->_raw_size = 0x7fffffff;
+ /* Not relevant for ldinfo section. */
+ core_ldinfosec (abfd)->vma = 0;
+ core_ldinfosec (abfd)->filepos = (file_ptr) coredata.c_tab;
+
+ /* set up section chain here. */
+ abfd->section_count = 4;
+ abfd->sections = core_stacksec (abfd);
+ core_stacksec (abfd)->next = core_regsec(abfd);
+ core_regsec (abfd)->next = core_reg2sec (abfd);
+ core_reg2sec (abfd)->next = core_ldinfosec (abfd);
+ core_ldinfosec (abfd)->next = NULL;
+
+ if (coredata.c_flag & FULL_CORE)
+ {
+ asection *sec = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (sec == NULL)
+ return NULL;
+ sec->name = ".data";
+ sec->flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
+ sec->_raw_size = coredata.CORE_DATA_SIZE_FIELD;
+ sec->vma = CDATA_ADDR (coredata.CORE_DATA_SIZE_FIELD);
+ sec->filepos = (int)coredata.c_stack + coredata.c_size;
+
+ sec->next = abfd->sections;
+ abfd->sections = sec;
+ ++abfd->section_count;
+ }
+
+ return abfd->xvec; /* this is garbage for now. */
+}
+
+
+
+/* return `true' if given core is from the given executable.. */
+boolean
+rs6000coff_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd;
+ bfd *exec_bfd;
+{
+ FILE *fd;
+ struct core_dump coredata;
+ struct ld_info ldinfo;
+ char pathname [1024];
+ const char *str1, *str2;
+
+ /* Use bfd_xxx routines, rather than O/S primitives, do error checking!!
+ FIXMEmgo */
+ /* Actually should be able to use bfd_get_section_contents now that
+ we have a .ldinfo section. */
+ fd = fopen (core_bfd->filename, FOPEN_RB);
+
+ fread (&coredata, sizeof (struct core_dump), 1, fd);
+ fseek (fd, (long)coredata.c_tab, 0);
+ fread (&ldinfo, (char*)&ldinfo.ldinfo_filename[0] - (char*)&ldinfo.ldinfo_next,
+ 1, fd);
+ fscanf (fd, "%s", pathname);
+
+ str1 = strrchr (pathname, '/');
+ str2 = strrchr (exec_bfd->filename, '/');
+
+ /* step over character '/' */
+ str1 = str1 ? str1+1 : &pathname[0];
+ str2 = str2 ? str2+1 : exec_bfd->filename;
+
+ fclose (fd);
+ return strcmp (str1, str2) == 0;
+}
+
+char *
+rs6000coff_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+ char *com = core_hdr (abfd).CORE_COMM_FIELD;
+ if (*com)
+ return com;
+ else
+ return 0;
+}
+
+int
+rs6000coff_core_file_failing_signal (abfd)
+ bfd *abfd;
+{
+ return core_hdr (abfd).c_signo;
+}
+
+
+boolean
+rs6000coff_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ int count;
+{
+ if (count == 0)
+ return true;
+
+ /* Reading a core file's sections will be slightly different. For the
+ rest of them we can use bfd_generic_get_section_contents () I suppose. */
+ /* Make sure this routine works for any bfd and any section. FIXMEmgo. */
+
+ if (abfd->format == bfd_core && strcmp (section->name, ".reg") == 0) {
+
+ struct mstsave mstatus;
+ int regoffset = (char*)&mstatus.gpr[0] - (char*)&mstatus;
+
+ /* Assert that the only way this code will be executed is reading the
+ whole section. */
+ if (offset || count != (sizeof(mstatus.gpr) + (4 * NUM_OF_SPEC_REGS)))
+ (*_bfd_error_handler)
+ ("ERROR! in rs6000coff_get_section_contents()\n");
+
+ /* for `.reg' section, `filepos' is a pointer to the `mstsave' structure
+ in the core file. */
+
+ /* read GPR's into the location. */
+ if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
+ || bfd_read(location, sizeof (mstatus.gpr), 1, abfd) != sizeof (mstatus.gpr))
+ return (false); /* on error */
+
+ /* increment location to the beginning of special registers in the section,
+ reset register offset value to the beginning of first special register
+ in mstsave structure, and read special registers. */
+
+ location = (PTR) ((char*)location + sizeof (mstatus.gpr));
+ regoffset = (char*)&mstatus.iar - (char*)&mstatus;
+
+ if ( bfd_seek(abfd, section->filepos + regoffset, SEEK_SET) == -1
+ || bfd_read(location, 4 * NUM_OF_SPEC_REGS, 1, abfd) !=
+ 4 * NUM_OF_SPEC_REGS)
+ return (false); /* on error */
+
+ /* increment location address, and read the special registers.. */
+ /* FIXMEmgo */
+ return (true);
+ }
+
+ /* else, use default bfd section content transfer. */
+ else
+ return _bfd_generic_get_section_contents
+ (abfd, section, location, offset, count);
+}
+
+#endif /* AIX_CORE */
diff --git a/contrib/gdb/bfd/section.c b/contrib/gdb/bfd/section.c
new file mode 100644
index 0000000..ac9a449
--- /dev/null
+++ b/contrib/gdb/bfd/section.c
@@ -0,0 +1,976 @@
+/* Object file "section" support for the BFD library.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ Sections
+
+ The raw data contained within a BFD is maintained through the
+ section abstraction. A single BFD may have any number of
+ 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 <<section.c>>.
+
+@menu
+@* Section Input::
+@* Section Output::
+@* typedef asection::
+@* section prototypes::
+@end menu
+
+INODE
+Section Input, Section Output, Sections, Sections
+SUBSECTION
+ 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, <<a.out>> 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>>.
+
+ 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 an extra section
+ <<COMMON>> for each input file's BFD to hold information about
+ common storage.
+
+ The raw data is not necessarily read in when
+ the section descriptor is created. Some targets may leave the
+ data in place until a <<bfd_get_section_contents>> 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
+ 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
+ relocations.
+
+INODE
+Section Output, typedef asection, Section Input, Sections
+
+SUBSECTION
+ 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 <<bfd_set_section_contents>>.
+
+ Any program that creates or combines sections (e.g., the assembler
+ and linker) must use the <<asection>> fields <<output_section>> and
+ <<output_offset>> to indicate the file sections to which each
+ section must be written. (If the section is being created from
+ scratch, <<output_section>> should probably point to the section
+ itself and <<output_offset>> should probably be zero.)
+
+ The data to be written comes from input sections attached
+ (via <<output_section>> pointers) to
+ the output sections. The output section structure can be
+ 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 (i.e., at vma
+ 0x100) and "B" at offset 0x20 (i.e., at vma 0x120) the <<asection>>
+ structures would look like:
+
+| section name "A"
+| output_offset 0x00
+| size 0x20
+| output_section -----------> section name "O"
+| | vma 0x100
+| section name "B" | size 0x123
+| output_offset 0x20 |
+| size 0x103 |
+| output_section --------|
+
+
+SUBSECTION
+ Link orders
+
+ The data within a section is stored in a @dfn{link_order}.
+ These are much like the fixups in <<gas>>. The link_order
+ abstraction allows a section to grow and shrink within itself.
+
+ 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 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 link_order by link_order basis.
+
+*/
+
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+
+/*
+DOCDD
+INODE
+typedef asection, section prototypes, Section Output, Sections
+SUBSECTION
+ typedef asection
+
+ Here is the section structure:
+
+CODE_FRAGMENT
+.
+.typedef struct sec
+.{
+. {* 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. *}
+.
+. 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
+. flags are read in from the object file, and some are
+. synthesized from other information. *}
+.
+. flagword flags;
+.
+.#define SEC_NO_FLAGS 0x000
+.
+. {* 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 is clear for a .bss section. *}
+.#define SEC_LOAD 0x002
+.
+. {* The section contains data still to be relocated, so there is
+. some relocation information too. *}
+.#define SEC_RELOC 0x004
+.
+.#if 0 {* Obsolete ? *}
+.#define SEC_BALIGN 0x008
+.#endif
+.
+. {* A signal to the OS that the section contains read only
+. data. *}
+.#define SEC_READONLY 0x010
+.
+. {* The section contains code only. *}
+.#define SEC_CODE 0x020
+.
+. {* The section contains data only. *}
+.#define SEC_DATA 0x040
+.
+. {* The section will reside in ROM. *}
+.#define SEC_ROM 0x080
+.
+. {* The section contains constructor information. This section
+. type is used by the linker to create lists of constructors and
+. destructors used by <<g++>>. 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 (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 relocate the data
+. contained within - exactly the operations it would peform on
+. standard data. *}
+.#define SEC_CONSTRUCTOR 0x100
+.
+. {* The section is a constuctor, and should be placed at the
+. end of the text, data, or bss section(?). *}
+.#define SEC_CONSTRUCTOR_TEXT 0x1100
+.#define SEC_CONSTRUCTOR_DATA 0x2100
+.#define SEC_CONSTRUCTOR_BSS 0x3100
+.
+. {* The section has contents - a data section could be
+. <<SEC_ALLOC>> | <<SEC_HAS_CONTENTS>>; a debug section could be
+. <<SEC_HAS_CONTENTS>> *}
+.#define SEC_HAS_CONTENTS 0x200
+.
+. {* 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 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_ptr), but ECOFF has two. *}
+.#define SEC_IS_COMMON 0x8000
+.
+. {* The section contains only debugging information. For
+. example, this is set for ELF .debug and .stab sections.
+. strip tests this flag to see if a section can be
+. 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
+.
+. {* The contents of this section are to be excluded by the
+. linker for executable and shared objects unless those
+. objects are to be further relocated. *}
+.#define SEC_EXCLUDE 0x40000
+.
+. {* The contents of this section are to be sorted by the
+. based on the address specified in the associated symbol
+. table. *}
+.#define SEC_SORT_ENTRIES 0x80000
+.
+. {* End of section flags. *}
+.
+. {* The virtual memory address of the section - where it will be
+. at run time. The symbols are relocated against this. The
+. user_set_vma flag is maintained by bfd; if it's not set, the
+. backend can assign addresses (for example, in <<a.out>>, where
+. the default address for <<.data>> is dependent on the specific
+. target and various flags). *}
+.
+. bfd_vma vma;
+. 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
+. 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 (e.g., the
+. size of <<.bss>>). This will be filled in after relocation *}
+.
+. bfd_size_type _cooked_size;
+.
+. {* 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;
+.
+. {* 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. 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;
+.
+. {* The output section through which to map on output. *}
+.
+. struct sec *output_section;
+.
+. {* The alignment requirement of the section, as an exponent of 2 -
+. e.g., 3 aligns to 2^3 (or 8). *}
+.
+. unsigned int alignment_power;
+.
+. {* If an input section, a pointer to a vector of relocation
+. records for the data in this section. *}
+.
+. struct reloc_cache_entry *relocation;
+.
+. {* If an output section, a pointer to a vector of pointers to
+. relocation records for the data in this section. *}
+.
+. struct reloc_cache_entry **orelocation;
+.
+. {* The number of relocation records in one of the above *}
+.
+. unsigned reloc_count;
+.
+. {* Information below is back end specific - and not always used
+. or updated. *}
+.
+. {* File position of section data *}
+.
+. file_ptr filepos;
+.
+. {* File position of relocation info *}
+.
+. file_ptr rel_filepos;
+.
+. {* File position of line data *}
+.
+. file_ptr line_filepos;
+.
+. {* Pointer to data for applications *}
+.
+. PTR userdata;
+.
+. {* 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;
+.
+. {* When a section is being output, this value changes as more
+. linenumbers are written out *}
+.
+. file_ptr moving_line_filepos;
+.
+. {* What the section number is in the target world *}
+.
+. int target_index;
+.
+. PTR used_by_bfd;
+.
+. {* If this is a constructor section then here is a list of the
+. relocations created to relocate items within it. *}
+.
+. struct relent_chain *constructor_chain;
+.
+. {* The BFD which owns the section. *}
+.
+. bfd *owner;
+.
+. boolean reloc_done;
+. {* A symbol which points at this section only *}
+. struct symbol_cache_entry *symbol;
+. struct symbol_cache_entry **symbol_ptr_ptr;
+.
+. 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. 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 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 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 const asection bfd_com_section;
+.#define bfd_com_section_ptr ((asection *) &bfd_com_section)
+. {* Pointer to the indirect 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 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) \
+. ((section->reloc_done) ? (section)->_cooked_size: (abort(),1))
+*/
+
+/* 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, (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) \
+ 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_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);
+#undef STD_SECTION
+
+/*
+DOCDD
+INODE
+section prototypes, , typedef asection, Sections
+SUBSECTION
+ Section prototypes
+
+These are the functions exported by the section handling part of BFD.
+*/
+
+/*
+FUNCTION
+ bfd_get_section_by_name
+
+SYNOPSIS
+ asection *bfd_get_section_by_name(bfd *abfd, CONST char *name);
+
+DESCRIPTION
+ Run through @var{abfd} and return the one of the
+ <<asection>>s whose name matches @var{name}, otherwise <<NULL>>.
+ @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
+ or something else) for each section.
+*/
+
+asection *
+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;
+ return NULL;
+}
+
+
+/*
+FUNCTION
+ bfd_make_section_old_way
+
+SYNOPSIS
+ asection *bfd_make_section_old_way(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 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 it was rewritten....
+
+ Possible errors are:
+ o <<bfd_error_invalid_operation>> -
+ If output has already started for this BFD.
+ o <<bfd_error_no_memory>> -
+ If obstack alloc fails.
+
+*/
+
+
+asection *
+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)
+ {
+ sec = bfd_make_section (abfd, name);
+ }
+ return sec;
+}
+
+/*
+FUNCTION
+ bfd_make_section_anyway
+
+SYNOPSIS
+ 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.
+
+ Return <<NULL>> and set <<bfd_error>> on error; possible errors are:
+ o <<bfd_error_invalid_operation>> - If output has already started for @var{abfd}.
+ o <<bfd_error_no_memory>> - If obstack alloc fails.
+*/
+
+sec_ptr
+bfd_make_section_anyway (abfd, name)
+ bfd *abfd;
+ CONST char *name;
+{
+ asection *newsect;
+ asection **prev = &abfd->sections;
+ asection *sect = abfd->sections;
+
+ if (abfd->output_has_begun)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return NULL;
+ }
+
+ while (sect)
+ {
+ prev = &sect->next;
+ sect = sect->next;
+ }
+
+ newsect = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (newsect == NULL)
+ return NULL;
+
+ newsect->name = name;
+ newsect->index = abfd->section_count++;
+ newsect->flags = SEC_NO_FLAGS;
+
+ newsect->userdata = NULL;
+ newsect->contents = NULL;
+ newsect->next = (asection *) NULL;
+ newsect->relocation = (arelent *) NULL;
+ newsect->reloc_count = 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);
+ if (newsect->symbol == NULL)
+ return NULL;
+ newsect->symbol->name = name;
+ newsect->symbol->value = 0;
+ newsect->symbol->section = newsect;
+ newsect->symbol->flags = BSF_SECTION_SYM;
+
+ newsect->symbol_ptr_ptr = &newsect->symbol;
+
+ if (BFD_SEND (abfd, _new_section_hook, (abfd, newsect)) != true)
+ {
+ free (newsect);
+ return NULL;
+ }
+
+ *prev = newsect;
+ return newsect;
+}
+
+/*
+FUNCTION
+ bfd_make_section
+
+SYNOPSIS
+ asection *bfd_make_section(bfd *, CONST char *name);
+
+DESCRIPTION
+ Like <<bfd_make_section_anyway>>, but return <<NULL>> (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 <<NULL>> and set
+ <<bfd_error>>.
+*/
+
+asection *
+bfd_make_section (abfd, name)
+ bfd *abfd;
+ CONST char *name;
+{
+ asection *sect = abfd->sections;
+
+ 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_ptr;
+ }
+
+ 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);
+}
+
+
+/*
+FUNCTION
+ bfd_set_section_flags
+
+SYNOPSIS
+ boolean bfd_set_section_flags(bfd *abfd, asection *sec, flagword flags);
+
+DESCRIPTION
+ Set the attributes of the section @var{sec} in the BFD
+ @var{abfd} to the value @var{flags}. Return <<true>> on success,
+ <<false>> on error. Possible error returns are:
+
+ o <<bfd_error_invalid_operation>> -
+ The section cannot have one or more of the attributes
+ requested. For example, a .bss section in <<a.out>> may not
+ have the <<SEC_HAS_CONTENTS>> field set.
+
+*/
+
+/*ARGSUSED*/
+boolean
+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
+ has the SEC_CODE flag set) to an output file, this loses big if
+ 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_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+#endif
+
+ section->flags = flags;
+ return true;
+}
+
+
+/*
+FUNCTION
+ bfd_map_over_sections
+
+SYNOPSIS
+ void bfd_map_over_sections(bfd *abfd,
+ void (*func)(bfd *abfd,
+ asection *sect,
+ PTR obj),
+ PTR obj);
+
+DESCRIPTION
+ 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
+
+| func(abfd, the_section, obj);
+
+ This is the prefered method for iterating over sections; an
+ alternative would be to use a loop:
+
+| section *p;
+| for (p = abfd->sections; p != NULL; p = p->next)
+| func(abfd, p, ...)
+
+
+*/
+
+/*VARARGS2*/
+void
+bfd_map_over_sections (abfd, operation, user_storage)
+ bfd *abfd;
+ void (*operation) PARAMS ((bfd * abfd, asection * sect, PTR obj));
+ PTR user_storage;
+{
+ asection *sect;
+ unsigned 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 ();
+}
+
+
+/*
+FUNCTION
+ bfd_set_section_size
+
+SYNOPSIS
+ boolean bfd_set_section_size(bfd *abfd, asection *sec, bfd_size_type val);
+
+DESCRIPTION
+ Set @var{sec} to the size @var{val}. If the operation is
+ ok, then <<true>> is returned, else <<false>>.
+
+ Possible error returns:
+ o <<bfd_error_invalid_operation>> -
+ Writing has started to the BFD, so setting the size is invalid.
+
+*/
+
+boolean
+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_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ ptr->_cooked_size = val;
+ ptr->_raw_size = val;
+
+ return true;
+}
+
+/*
+FUNCTION
+ bfd_set_section_contents
+
+SYNOPSIS
+ boolean bfd_set_section_contents
+ (bfd *abfd,
+ asection *section,
+ PTR data,
+ file_ptr offset,
+ bfd_size_type count);
+
+
+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.
+
+
+
+ Normally <<true>> is returned, else <<false>>. Possible error
+ returns are:
+ o <<bfd_error_no_contents>> -
+ The output section does not have the <<SEC_HAS_CONTENTS>>
+ attribute, so nothing can be written to it.
+ o and some more too
+
+ This routine is front end to the back end function
+ <<_bfd_set_section_contents>>.
+
+
+*/
+
+#define bfd_get_section_size_now(abfd,sec) \
+(sec->reloc_done \
+ ? bfd_get_section_size_after_reloc (sec) \
+ : bfd_get_section_size_before_reloc (sec))
+
+boolean
+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_set_error (bfd_error_no_contents);
+ return (false);
+ }
+
+ if (offset < 0)
+ {
+ bad_val:
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ sz = bfd_get_section_size_now (abfd, section);
+ if ((bfd_size_type) offset > sz
+ || count > sz
+ || offset + count > sz)
+ goto bad_val;
+
+ switch (abfd->direction)
+ {
+ case read_direction:
+ case no_direction:
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+
+ case write_direction:
+ break;
+
+ 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;
+ }
+
+ if (BFD_SEND (abfd, _bfd_set_section_contents,
+ (abfd, section, location, offset, count)))
+ {
+ abfd->output_has_begun = true;
+ return true;
+ }
+
+ return false;
+}
+
+/*
+FUNCTION
+ bfd_get_section_contents
+
+SYNOPSIS
+ boolean bfd_get_section_contents
+ (bfd *abfd, asection *section, PTR location,
+ file_ptr offset, bfd_size_type count);
+
+DESCRIPTION
+ 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 constructor with the <<SEC_CONSTRUCTOR>>
+ flag set are requested or if the section does not have the
+ <<SEC_HAS_CONTENTS>> flag set, then the @var{location} is filled
+ with zeroes. If no errors occur, <<true>> is returned, else
+ <<false>>.
+
+
+
+*/
+boolean
+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)
+ {
+ memset (location, 0, (unsigned) count);
+ return true;
+ }
+
+ if (offset < 0)
+ {
+ bad_val:
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ /* Even if reloc_done is true, this function reads unrelocated
+ contents, so we want the raw size. */
+ sz = section->_raw_size;
+ if ((bfd_size_type) 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, (size_t) 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 <<true>> on success, <<false>> on error. Possible error
+ returns are:
+
+ o <<bfd_error_no_memory>> -
+ 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/contrib/gdb/bfd/som.c b/contrib/gdb/bfd/som.c
new file mode 100644
index 0000000..dd03d99
--- /dev/null
+++ b/contrib/gdb/bfd/som.c
@@ -0,0 +1,5999 @@
+/* bfd back-end for HP PA-RISC SOM objects.
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+
+#if defined (HOST_HPPAHPUX) || defined (HOST_HPPABSD) || defined (HOST_HPPAOSF)
+
+#include "libbfd.h"
+#include "som.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <signal.h>
+#include <machine/reg.h>
+#include <sys/file.h>
+#include <errno.h>
+
+/* Magic not defined in standard HP-UX header files until 8.0 */
+
+#ifndef CPU_PA_RISC1_0
+#define CPU_PA_RISC1_0 0x20B
+#endif /* CPU_PA_RISC1_0 */
+
+#ifndef CPU_PA_RISC1_1
+#define CPU_PA_RISC1_1 0x210
+#endif /* CPU_PA_RISC1_1 */
+
+#ifndef _PA_RISC1_0_ID
+#define _PA_RISC1_0_ID CPU_PA_RISC1_0
+#endif /* _PA_RISC1_0_ID */
+
+#ifndef _PA_RISC1_1_ID
+#define _PA_RISC1_1_ID CPU_PA_RISC1_1
+#endif /* _PA_RISC1_1_ID */
+
+#ifndef _PA_RISC_MAXID
+#define _PA_RISC_MAXID 0x2FF
+#endif /* _PA_RISC_MAXID */
+
+#ifndef _PA_RISC_ID
+#define _PA_RISC_ID(__m_num) \
+ (((__m_num) == _PA_RISC1_0_ID) || \
+ ((__m_num) >= _PA_RISC1_1_ID && (__m_num) <= _PA_RISC_MAXID))
+#endif /* _PA_RISC_ID */
+
+
+/* HIUX in it's infinite stupidity changed the names for several "well
+ known" constants. Work around such braindamage. Try the HPUX version
+ first, then the HIUX version, and finally provide a default. */
+#ifdef HPUX_AUX_ID
+#define EXEC_AUX_ID HPUX_AUX_ID
+#endif
+
+#if !defined (EXEC_AUX_ID) && defined (HIUX_AUX_ID)
+#define EXEC_AUX_ID HIUX_AUX_ID
+#endif
+
+#ifndef EXEC_AUX_ID
+#define EXEC_AUX_ID 0
+#endif
+
+/* Size (in chars) of the temporary buffers used during fixup and string
+ table writes. */
+
+#define SOM_TMP_BUFSIZE 8192
+
+/* Size of the hash table in archives. */
+#define SOM_LST_HASH_SIZE 31
+
+/* Max number of SOMs to be found in an archive. */
+#define SOM_LST_MODULE_LIMIT 1024
+
+/* Generic alignment macro. */
+#define SOM_ALIGN(val, alignment) \
+ (((val) + (alignment) - 1) & ~((alignment) - 1))
+
+/* SOM allows any one of the four previous relocations to be reused
+ with a "R_PREV_FIXUP" relocation entry. Since R_PREV_FIXUP
+ relocations are always a single byte, using a R_PREV_FIXUP instead
+ of some multi-byte relocation makes object files smaller.
+
+ Note one side effect of using a R_PREV_FIXUP is the relocation that
+ is being repeated moves to the front of the queue. */
+struct reloc_queue
+ {
+ unsigned char *reloc;
+ unsigned int size;
+ } reloc_queue[4];
+
+/* This fully describes the symbol types which may be attached to
+ an EXPORT or IMPORT directive. Only SOM uses this formation
+ (ELF has no need for it). */
+typedef enum
+{
+ SYMBOL_TYPE_UNKNOWN,
+ SYMBOL_TYPE_ABSOLUTE,
+ SYMBOL_TYPE_CODE,
+ SYMBOL_TYPE_DATA,
+ SYMBOL_TYPE_ENTRY,
+ SYMBOL_TYPE_MILLICODE,
+ SYMBOL_TYPE_PLABEL,
+ SYMBOL_TYPE_PRI_PROG,
+ SYMBOL_TYPE_SEC_PROG,
+} pa_symbol_type;
+
+struct section_to_type
+{
+ char *section;
+ char type;
+};
+
+/* Assorted symbol information that needs to be derived from the BFD symbol
+ and/or the BFD backend private symbol data. */
+struct som_misc_symbol_info
+{
+ unsigned int symbol_type;
+ unsigned int symbol_scope;
+ unsigned int arg_reloc;
+ unsigned int symbol_info;
+ unsigned int symbol_value;
+};
+
+/* Forward declarations */
+
+static boolean som_mkobject PARAMS ((bfd *));
+static const bfd_target * som_object_setup PARAMS ((bfd *,
+ struct header *,
+ struct som_exec_auxhdr *));
+static boolean setup_sections PARAMS ((bfd *, struct header *));
+static const bfd_target * som_object_p PARAMS ((bfd *));
+static boolean som_write_object_contents PARAMS ((bfd *));
+static boolean som_slurp_string_table PARAMS ((bfd *));
+static unsigned int som_slurp_symbol_table PARAMS ((bfd *));
+static long som_get_symtab_upper_bound PARAMS ((bfd *));
+static long som_canonicalize_reloc PARAMS ((bfd *, sec_ptr,
+ arelent **, asymbol **));
+static long som_get_reloc_upper_bound PARAMS ((bfd *, sec_ptr));
+static unsigned int som_set_reloc_info PARAMS ((unsigned char *, unsigned int,
+ arelent *, asection *,
+ asymbol **, boolean));
+static boolean som_slurp_reloc_table PARAMS ((bfd *, asection *,
+ asymbol **, boolean));
+static long som_get_symtab PARAMS ((bfd *, asymbol **));
+static asymbol * som_make_empty_symbol PARAMS ((bfd *));
+static void som_print_symbol PARAMS ((bfd *, PTR,
+ asymbol *, bfd_print_symbol_type));
+static boolean som_new_section_hook PARAMS ((bfd *, asection *));
+static boolean som_bfd_copy_private_symbol_data PARAMS ((bfd *, asymbol *,
+ bfd *, asymbol *));
+static boolean som_bfd_copy_private_section_data PARAMS ((bfd *, asection *,
+ bfd *, asection *));
+static boolean som_bfd_copy_private_bfd_data PARAMS ((bfd *, bfd *));
+#define som_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
+#define som_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
+static boolean som_bfd_is_local_label PARAMS ((bfd *, asymbol *));
+static boolean som_set_section_contents PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+static boolean som_get_section_contents PARAMS ((bfd *, sec_ptr, PTR,
+ file_ptr, bfd_size_type));
+static boolean som_set_arch_mach PARAMS ((bfd *, enum bfd_architecture,
+ unsigned long));
+static boolean som_find_nearest_line PARAMS ((bfd *, asection *,
+ asymbol **, bfd_vma,
+ CONST char **,
+ CONST char **,
+ unsigned int *));
+static void som_get_symbol_info PARAMS ((bfd *, asymbol *, symbol_info *));
+static asection * bfd_section_from_som_symbol PARAMS ((bfd *,
+ struct symbol_dictionary_record *));
+static int log2 PARAMS ((unsigned int));
+static bfd_reloc_status_type hppa_som_reloc PARAMS ((bfd *, arelent *,
+ asymbol *, PTR,
+ asection *, bfd *,
+ char **));
+static void som_initialize_reloc_queue PARAMS ((struct reloc_queue *));
+static void som_reloc_queue_insert PARAMS ((unsigned char *, unsigned int,
+ struct reloc_queue *));
+static void som_reloc_queue_fix PARAMS ((struct reloc_queue *, unsigned int));
+static int som_reloc_queue_find PARAMS ((unsigned char *, unsigned int,
+ struct reloc_queue *));
+static unsigned char * try_prev_fixup PARAMS ((bfd *, int *, unsigned char *,
+ unsigned int,
+ struct reloc_queue *));
+
+static unsigned char * som_reloc_skip PARAMS ((bfd *, unsigned int,
+ unsigned char *, unsigned int *,
+ struct reloc_queue *));
+static unsigned char * som_reloc_addend PARAMS ((bfd *, int, unsigned char *,
+ unsigned int *,
+ struct reloc_queue *));
+static unsigned char * som_reloc_call PARAMS ((bfd *, unsigned char *,
+ unsigned int *,
+ arelent *, int,
+ struct reloc_queue *));
+static unsigned long som_count_spaces PARAMS ((bfd *));
+static unsigned long som_count_subspaces PARAMS ((bfd *));
+static int compare_syms PARAMS ((const void *, const void *));
+static int compare_subspaces PARAMS ((const void *, const void *));
+static unsigned long som_compute_checksum PARAMS ((bfd *));
+static boolean som_prep_headers PARAMS ((bfd *));
+static int som_sizeof_headers PARAMS ((bfd *, boolean));
+static boolean som_finish_writing PARAMS ((bfd *));
+static boolean som_build_and_write_symbol_table PARAMS ((bfd *));
+static void som_prep_for_fixups PARAMS ((bfd *, asymbol **, unsigned long));
+static boolean som_write_fixups PARAMS ((bfd *, unsigned long, unsigned int *));
+static boolean som_write_space_strings PARAMS ((bfd *, unsigned long,
+ unsigned int *));
+static boolean som_write_symbol_strings PARAMS ((bfd *, unsigned long,
+ asymbol **, unsigned int,
+ unsigned *));
+static boolean som_begin_writing PARAMS ((bfd *));
+static reloc_howto_type * som_bfd_reloc_type_lookup
+ PARAMS ((bfd *, bfd_reloc_code_real_type));
+static char som_section_type PARAMS ((const char *));
+static int som_decode_symclass PARAMS ((asymbol *));
+static boolean som_bfd_count_ar_symbols PARAMS ((bfd *, struct lst_header *,
+ symindex *));
+
+static boolean som_bfd_fill_in_ar_symbols PARAMS ((bfd *, struct lst_header *,
+ carsym **syms));
+static boolean som_slurp_armap PARAMS ((bfd *));
+static boolean som_write_armap PARAMS ((bfd *, unsigned int, struct orl *,
+ unsigned int, int));
+static void som_bfd_derive_misc_symbol_info PARAMS ((bfd *, asymbol *,
+ struct som_misc_symbol_info *));
+static boolean som_bfd_prep_for_ar_write PARAMS ((bfd *, unsigned int *,
+ unsigned int *));
+static unsigned int som_bfd_ar_symbol_hash PARAMS ((asymbol *));
+static boolean som_bfd_ar_write_symbol_stuff PARAMS ((bfd *, unsigned int,
+ unsigned int,
+ struct lst_header));
+static CONST char *normalize PARAMS ((CONST char *file));
+static boolean som_is_space PARAMS ((asection *));
+static boolean som_is_subspace PARAMS ((asection *));
+static boolean som_is_container PARAMS ((asection *, asection *));
+static boolean som_bfd_free_cached_info PARAMS ((bfd *));
+static boolean som_bfd_link_split_section PARAMS ((bfd *, asection *));
+
+/* Map SOM section names to POSIX/BSD single-character symbol types.
+
+ This table includes all the standard subspaces as defined in the
+ current "PRO ABI for PA-RISC Systems", $UNWIND$ which for
+ some reason was left out, and sections specific to embedded stabs. */
+
+static const struct section_to_type stt[] = {
+ {"$TEXT$", 't'},
+ {"$SHLIB_INFO$", 't'},
+ {"$MILLICODE$", 't'},
+ {"$LIT$", 't'},
+ {"$CODE$", 't'},
+ {"$UNWIND_START$", 't'},
+ {"$UNWIND$", 't'},
+ {"$PRIVATE$", 'd'},
+ {"$PLT$", 'd'},
+ {"$SHLIB_DATA$", 'd'},
+ {"$DATA$", 'd'},
+ {"$SHORTDATA$", 'g'},
+ {"$DLT$", 'd'},
+ {"$GLOBAL$", 'g'},
+ {"$SHORTBSS$", 's'},
+ {"$BSS$", 'b'},
+ {"$GDB_STRINGS$", 'N'},
+ {"$GDB_SYMBOLS$", 'N'},
+ {0, 0}
+};
+
+/* About the relocation formatting table...
+
+ There are 256 entries in the table, one for each possible
+ relocation opcode available in SOM. We index the table by
+ the relocation opcode. The names and operations are those
+ defined by a.out_800 (4).
+
+ Right now this table is only used to count and perform minimal
+ processing on relocation streams so that they can be internalized
+ into BFD and symbolically printed by utilities. To make actual use
+ of them would be much more difficult, BFD's concept of relocations
+ is far too simple to handle SOM relocations. The basic assumption
+ that a relocation can be completely processed independent of other
+ relocations before an object file is written is invalid for SOM.
+
+ The SOM relocations are meant to be processed as a stream, they
+ specify copying of data from the input section to the output section
+ while possibly modifying the data in some manner. They also can
+ specify that a variable number of zeros or uninitialized data be
+ inserted on in the output segment at the current offset. Some
+ relocations specify that some previous relocation be re-applied at
+ the current location in the input/output sections. And finally a number
+ of relocations have effects on other sections (R_ENTRY, R_EXIT,
+ R_UNWIND_AUX and a variety of others). There isn't even enough room
+ in the BFD relocation data structure to store enough information to
+ perform all the relocations.
+
+ Each entry in the table has three fields.
+
+ The first entry is an index into this "class" of relocations. This
+ index can then be used as a variable within the relocation itself.
+
+ The second field is a format string which actually controls processing
+ of the relocation. It uses a simple postfix machine to do calculations
+ based on variables/constants found in the string and the relocation
+ stream.
+
+ The third field specifys whether or not this relocation may use
+ a constant (V) from the previous R_DATA_OVERRIDE rather than a constant
+ stored in the instruction.
+
+ Variables:
+
+ L = input space byte count
+ D = index into class of relocations
+ M = output space byte count
+ N = statement number (unused?)
+ O = stack operation
+ R = parameter relocation bits
+ S = symbol index
+ T = first 32 bits of stack unwind information
+ U = second 32 bits of stack unwind information
+ V = a literal constant (usually used in the next relocation)
+ P = a previous relocation
+
+ Lower case letters (starting with 'b') refer to following
+ bytes in the relocation stream. 'b' is the next 1 byte,
+ c is the next 2 bytes, d is the next 3 bytes, etc...
+ This is the variable part of the relocation entries that
+ makes our life a living hell.
+
+ numerical constants are also used in the format string. Note
+ the constants are represented in decimal.
+
+ '+', "*" and "=" represents the obvious postfix operators.
+ '<' represents a left shift.
+
+ Stack Operations:
+
+ Parameter Relocation Bits:
+
+ Unwind Entries:
+
+ Previous Relocations: The index field represents which in the queue
+ of 4 previous fixups should be re-applied.
+
+ Literal Constants: These are generally used to represent addend
+ parts of relocations when these constants are not stored in the
+ fields of the instructions themselves. For example the instruction
+ addil foo-$global$-0x1234 would use an override for "0x1234" rather
+ than storing it into the addil itself. */
+
+struct fixup_format
+{
+ int D;
+ char *format;
+};
+
+static const struct fixup_format som_fixup_formats[256] =
+{
+ /* R_NO_RELOCATION */
+ 0, "LD1+4*=", /* 0x00 */
+ 1, "LD1+4*=", /* 0x01 */
+ 2, "LD1+4*=", /* 0x02 */
+ 3, "LD1+4*=", /* 0x03 */
+ 4, "LD1+4*=", /* 0x04 */
+ 5, "LD1+4*=", /* 0x05 */
+ 6, "LD1+4*=", /* 0x06 */
+ 7, "LD1+4*=", /* 0x07 */
+ 8, "LD1+4*=", /* 0x08 */
+ 9, "LD1+4*=", /* 0x09 */
+ 10, "LD1+4*=", /* 0x0a */
+ 11, "LD1+4*=", /* 0x0b */
+ 12, "LD1+4*=", /* 0x0c */
+ 13, "LD1+4*=", /* 0x0d */
+ 14, "LD1+4*=", /* 0x0e */
+ 15, "LD1+4*=", /* 0x0f */
+ 16, "LD1+4*=", /* 0x10 */
+ 17, "LD1+4*=", /* 0x11 */
+ 18, "LD1+4*=", /* 0x12 */
+ 19, "LD1+4*=", /* 0x13 */
+ 20, "LD1+4*=", /* 0x14 */
+ 21, "LD1+4*=", /* 0x15 */
+ 22, "LD1+4*=", /* 0x16 */
+ 23, "LD1+4*=", /* 0x17 */
+ 0, "LD8<b+1+4*=", /* 0x18 */
+ 1, "LD8<b+1+4*=", /* 0x19 */
+ 2, "LD8<b+1+4*=", /* 0x1a */
+ 3, "LD8<b+1+4*=", /* 0x1b */
+ 0, "LD16<c+1+4*=", /* 0x1c */
+ 1, "LD16<c+1+4*=", /* 0x1d */
+ 2, "LD16<c+1+4*=", /* 0x1e */
+ 0, "Ld1+=", /* 0x1f */
+ /* R_ZEROES */
+ 0, "Lb1+4*=", /* 0x20 */
+ 1, "Ld1+=", /* 0x21 */
+ /* R_UNINIT */
+ 0, "Lb1+4*=", /* 0x22 */
+ 1, "Ld1+=", /* 0x23 */
+ /* R_RELOCATION */
+ 0, "L4=", /* 0x24 */
+ /* R_DATA_ONE_SYMBOL */
+ 0, "L4=Sb=", /* 0x25 */
+ 1, "L4=Sd=", /* 0x26 */
+ /* R_DATA_PLEBEL */
+ 0, "L4=Sb=", /* 0x27 */
+ 1, "L4=Sd=", /* 0x28 */
+ /* R_SPACE_REF */
+ 0, "L4=", /* 0x29 */
+ /* R_REPEATED_INIT */
+ 0, "L4=Mb1+4*=", /* 0x2a */
+ 1, "Lb4*=Mb1+L*=", /* 0x2b */
+ 2, "Lb4*=Md1+4*=", /* 0x2c */
+ 3, "Ld1+=Me1+=", /* 0x2d */
+ /* R_SHORT_PCREL_MODE */
+ 0, "", /* 0x2e */
+ /* R_LONG_PCREL_MODE */
+ 0, "", /* 0x2f */
+ /* R_PCREL_CALL */
+ 0, "L4=RD=Sb=", /* 0x30 */
+ 1, "L4=RD=Sb=", /* 0x31 */
+ 2, "L4=RD=Sb=", /* 0x32 */
+ 3, "L4=RD=Sb=", /* 0x33 */
+ 4, "L4=RD=Sb=", /* 0x34 */
+ 5, "L4=RD=Sb=", /* 0x35 */
+ 6, "L4=RD=Sb=", /* 0x36 */
+ 7, "L4=RD=Sb=", /* 0x37 */
+ 8, "L4=RD=Sb=", /* 0x38 */
+ 9, "L4=RD=Sb=", /* 0x39 */
+ 0, "L4=RD8<b+=Sb=",/* 0x3a */
+ 1, "L4=RD8<b+=Sb=",/* 0x3b */
+ 0, "L4=RD8<b+=Sd=",/* 0x3c */
+ 1, "L4=RD8<b+=Sd=",/* 0x3d */
+ /* R_RESERVED */
+ 0, "", /* 0x3e */
+ 0, "", /* 0x3f */
+ /* R_ABS_CALL */
+ 0, "L4=RD=Sb=", /* 0x40 */
+ 1, "L4=RD=Sb=", /* 0x41 */
+ 2, "L4=RD=Sb=", /* 0x42 */
+ 3, "L4=RD=Sb=", /* 0x43 */
+ 4, "L4=RD=Sb=", /* 0x44 */
+ 5, "L4=RD=Sb=", /* 0x45 */
+ 6, "L4=RD=Sb=", /* 0x46 */
+ 7, "L4=RD=Sb=", /* 0x47 */
+ 8, "L4=RD=Sb=", /* 0x48 */
+ 9, "L4=RD=Sb=", /* 0x49 */
+ 0, "L4=RD8<b+=Sb=",/* 0x4a */
+ 1, "L4=RD8<b+=Sb=",/* 0x4b */
+ 0, "L4=RD8<b+=Sd=",/* 0x4c */
+ 1, "L4=RD8<b+=Sd=",/* 0x4d */
+ /* R_RESERVED */
+ 0, "", /* 0x4e */
+ 0, "", /* 0x4f */
+ /* R_DP_RELATIVE */
+ 0, "L4=SD=", /* 0x50 */
+ 1, "L4=SD=", /* 0x51 */
+ 2, "L4=SD=", /* 0x52 */
+ 3, "L4=SD=", /* 0x53 */
+ 4, "L4=SD=", /* 0x54 */
+ 5, "L4=SD=", /* 0x55 */
+ 6, "L4=SD=", /* 0x56 */
+ 7, "L4=SD=", /* 0x57 */
+ 8, "L4=SD=", /* 0x58 */
+ 9, "L4=SD=", /* 0x59 */
+ 10, "L4=SD=", /* 0x5a */
+ 11, "L4=SD=", /* 0x5b */
+ 12, "L4=SD=", /* 0x5c */
+ 13, "L4=SD=", /* 0x5d */
+ 14, "L4=SD=", /* 0x5e */
+ 15, "L4=SD=", /* 0x5f */
+ 16, "L4=SD=", /* 0x60 */
+ 17, "L4=SD=", /* 0x61 */
+ 18, "L4=SD=", /* 0x62 */
+ 19, "L4=SD=", /* 0x63 */
+ 20, "L4=SD=", /* 0x64 */
+ 21, "L4=SD=", /* 0x65 */
+ 22, "L4=SD=", /* 0x66 */
+ 23, "L4=SD=", /* 0x67 */
+ 24, "L4=SD=", /* 0x68 */
+ 25, "L4=SD=", /* 0x69 */
+ 26, "L4=SD=", /* 0x6a */
+ 27, "L4=SD=", /* 0x6b */
+ 28, "L4=SD=", /* 0x6c */
+ 29, "L4=SD=", /* 0x6d */
+ 30, "L4=SD=", /* 0x6e */
+ 31, "L4=SD=", /* 0x6f */
+ 32, "L4=Sb=", /* 0x70 */
+ 33, "L4=Sd=", /* 0x71 */
+ /* R_RESERVED */
+ 0, "", /* 0x72 */
+ 0, "", /* 0x73 */
+ 0, "", /* 0x74 */
+ 0, "", /* 0x75 */
+ 0, "", /* 0x76 */
+ 0, "", /* 0x77 */
+ /* R_DLT_REL */
+ 0, "L4=Sb=", /* 0x78 */
+ 1, "L4=Sd=", /* 0x79 */
+ /* R_RESERVED */
+ 0, "", /* 0x7a */
+ 0, "", /* 0x7b */
+ 0, "", /* 0x7c */
+ 0, "", /* 0x7d */
+ 0, "", /* 0x7e */
+ 0, "", /* 0x7f */
+ /* R_CODE_ONE_SYMBOL */
+ 0, "L4=SD=", /* 0x80 */
+ 1, "L4=SD=", /* 0x81 */
+ 2, "L4=SD=", /* 0x82 */
+ 3, "L4=SD=", /* 0x83 */
+ 4, "L4=SD=", /* 0x84 */
+ 5, "L4=SD=", /* 0x85 */
+ 6, "L4=SD=", /* 0x86 */
+ 7, "L4=SD=", /* 0x87 */
+ 8, "L4=SD=", /* 0x88 */
+ 9, "L4=SD=", /* 0x89 */
+ 10, "L4=SD=", /* 0x8q */
+ 11, "L4=SD=", /* 0x8b */
+ 12, "L4=SD=", /* 0x8c */
+ 13, "L4=SD=", /* 0x8d */
+ 14, "L4=SD=", /* 0x8e */
+ 15, "L4=SD=", /* 0x8f */
+ 16, "L4=SD=", /* 0x90 */
+ 17, "L4=SD=", /* 0x91 */
+ 18, "L4=SD=", /* 0x92 */
+ 19, "L4=SD=", /* 0x93 */
+ 20, "L4=SD=", /* 0x94 */
+ 21, "L4=SD=", /* 0x95 */
+ 22, "L4=SD=", /* 0x96 */
+ 23, "L4=SD=", /* 0x97 */
+ 24, "L4=SD=", /* 0x98 */
+ 25, "L4=SD=", /* 0x99 */
+ 26, "L4=SD=", /* 0x9a */
+ 27, "L4=SD=", /* 0x9b */
+ 28, "L4=SD=", /* 0x9c */
+ 29, "L4=SD=", /* 0x9d */
+ 30, "L4=SD=", /* 0x9e */
+ 31, "L4=SD=", /* 0x9f */
+ 32, "L4=Sb=", /* 0xa0 */
+ 33, "L4=Sd=", /* 0xa1 */
+ /* R_RESERVED */
+ 0, "", /* 0xa2 */
+ 0, "", /* 0xa3 */
+ 0, "", /* 0xa4 */
+ 0, "", /* 0xa5 */
+ 0, "", /* 0xa6 */
+ 0, "", /* 0xa7 */
+ 0, "", /* 0xa8 */
+ 0, "", /* 0xa9 */
+ 0, "", /* 0xaa */
+ 0, "", /* 0xab */
+ 0, "", /* 0xac */
+ 0, "", /* 0xad */
+ /* R_MILLI_REL */
+ 0, "L4=Sb=", /* 0xae */
+ 1, "L4=Sd=", /* 0xaf */
+ /* R_CODE_PLABEL */
+ 0, "L4=Sb=", /* 0xb0 */
+ 1, "L4=Sd=", /* 0xb1 */
+ /* R_BREAKPOINT */
+ 0, "L4=", /* 0xb2 */
+ /* R_ENTRY */
+ 0, "Te=Ue=", /* 0xb3 */
+ 1, "Uf=", /* 0xb4 */
+ /* R_ALT_ENTRY */
+ 0, "", /* 0xb5 */
+ /* R_EXIT */
+ 0, "", /* 0xb6 */
+ /* R_BEGIN_TRY */
+ 0, "", /* 0xb7 */
+ /* R_END_TRY */
+ 0, "R0=", /* 0xb8 */
+ 1, "Rb4*=", /* 0xb9 */
+ 2, "Rd4*=", /* 0xba */
+ /* R_BEGIN_BRTAB */
+ 0, "", /* 0xbb */
+ /* R_END_BRTAB */
+ 0, "", /* 0xbc */
+ /* R_STATEMENT */
+ 0, "Nb=", /* 0xbd */
+ 1, "Nc=", /* 0xbe */
+ 2, "Nd=", /* 0xbf */
+ /* R_DATA_EXPR */
+ 0, "L4=", /* 0xc0 */
+ /* R_CODE_EXPR */
+ 0, "L4=", /* 0xc1 */
+ /* R_FSEL */
+ 0, "", /* 0xc2 */
+ /* R_LSEL */
+ 0, "", /* 0xc3 */
+ /* R_RSEL */
+ 0, "", /* 0xc4 */
+ /* R_N_MODE */
+ 0, "", /* 0xc5 */
+ /* R_S_MODE */
+ 0, "", /* 0xc6 */
+ /* R_D_MODE */
+ 0, "", /* 0xc7 */
+ /* R_R_MODE */
+ 0, "", /* 0xc8 */
+ /* R_DATA_OVERRIDE */
+ 0, "V0=", /* 0xc9 */
+ 1, "Vb=", /* 0xca */
+ 2, "Vc=", /* 0xcb */
+ 3, "Vd=", /* 0xcc */
+ 4, "Ve=", /* 0xcd */
+ /* R_TRANSLATED */
+ 0, "", /* 0xce */
+ /* R_RESERVED */
+ 0, "", /* 0xcf */
+ /* R_COMP1 */
+ 0, "Ob=", /* 0xd0 */
+ /* R_COMP2 */
+ 0, "Ob=Sd=", /* 0xd1 */
+ /* R_COMP3 */
+ 0, "Ob=Ve=", /* 0xd2 */
+ /* R_PREV_FIXUP */
+ 0, "P", /* 0xd3 */
+ 1, "P", /* 0xd4 */
+ 2, "P", /* 0xd5 */
+ 3, "P", /* 0xd6 */
+ /* R_SEC_STMT */
+ 0, "", /* 0xd7 */
+ /* R_N0SEL */
+ 0, "", /* 0xd8 */
+ /* R_N1SEL */
+ 0, "", /* 0xd9 */
+ /* R_LINETAB */
+ 0, "", /* 0xda */
+ /* R_LINETAB_ESC */
+ 0, "", /* 0xdb */
+ /* R_LTP_OVERRIDE */
+ 0, "", /* 0xdc */
+ /* R_COMMENT */
+ 0, "", /* 0xdd */
+ /* R_RESERVED */
+ 0, "", /* 0xde */
+ 0, "", /* 0xdf */
+ 0, "", /* 0xe0 */
+ 0, "", /* 0xe1 */
+ 0, "", /* 0xe2 */
+ 0, "", /* 0xe3 */
+ 0, "", /* 0xe4 */
+ 0, "", /* 0xe5 */
+ 0, "", /* 0xe6 */
+ 0, "", /* 0xe7 */
+ 0, "", /* 0xe8 */
+ 0, "", /* 0xe9 */
+ 0, "", /* 0xea */
+ 0, "", /* 0xeb */
+ 0, "", /* 0xec */
+ 0, "", /* 0xed */
+ 0, "", /* 0xee */
+ 0, "", /* 0xef */
+ 0, "", /* 0xf0 */
+ 0, "", /* 0xf1 */
+ 0, "", /* 0xf2 */
+ 0, "", /* 0xf3 */
+ 0, "", /* 0xf4 */
+ 0, "", /* 0xf5 */
+ 0, "", /* 0xf6 */
+ 0, "", /* 0xf7 */
+ 0, "", /* 0xf8 */
+ 0, "", /* 0xf9 */
+ 0, "", /* 0xfa */
+ 0, "", /* 0xfb */
+ 0, "", /* 0xfc */
+ 0, "", /* 0xfd */
+ 0, "", /* 0xfe */
+ 0, "", /* 0xff */
+};
+
+static const int comp1_opcodes[] =
+{
+ 0x00,
+ 0x40,
+ 0x41,
+ 0x42,
+ 0x43,
+ 0x44,
+ 0x45,
+ 0x46,
+ 0x47,
+ 0x48,
+ 0x49,
+ 0x4a,
+ 0x4b,
+ 0x60,
+ 0x80,
+ 0xa0,
+ 0xc0,
+ -1
+};
+
+static const int comp2_opcodes[] =
+{
+ 0x00,
+ 0x80,
+ 0x82,
+ 0xc0,
+ -1
+};
+
+static const int comp3_opcodes[] =
+{
+ 0x00,
+ 0x02,
+ -1
+};
+
+/* These apparently are not in older versions of hpux reloc.h (hpux7). */
+#ifndef R_DLT_REL
+#define R_DLT_REL 0x78
+#endif
+
+#ifndef R_AUX_UNWIND
+#define R_AUX_UNWIND 0xcf
+#endif
+
+#ifndef R_SEC_STMT
+#define R_SEC_STMT 0xd7
+#endif
+
+/* And these first appeared in hpux10. */
+#ifndef R_SHORT_PCREL_MODE
+#define R_SHORT_PCREL_MODE 0x3e
+#endif
+
+#ifndef R_LONG_PCREL_MODE
+#define R_LONG_PCREL_MODE 0x3f
+#endif
+
+#ifndef R_N0SEL
+#define R_N0SEL 0xd8
+#endif
+
+#ifndef R_N1SEL
+#define R_N1SEL 0xd9
+#endif
+
+#ifndef R_LINETAB
+#define R_LINETAB 0xda
+#endif
+
+#ifndef R_LINETAB_ESC
+#define R_LINETAB_ESC 0xdb
+#endif
+
+#ifndef R_LTP_OVERRIDE
+#define R_LTP_OVERRIDE 0xdc
+#endif
+
+#ifndef R_COMMENT
+#define R_COMMENT 0xdd
+#endif
+
+static reloc_howto_type som_hppa_howto_table[] =
+{
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_NO_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_NO_RELOCATION"},
+ {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
+ {R_ZEROES, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ZEROES"},
+ {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
+ {R_UNINIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_UNINIT"},
+ {R_RELOCATION, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RELOCATION"},
+ {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
+ {R_DATA_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_ONE_SYMBOL"},
+ {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
+ {R_DATA_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_PLABEL"},
+ {R_SPACE_REF, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SPACE_REF"},
+ {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
+ {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
+ {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
+ {R_REPEATED_INIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "REPEATED_INIT"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_PCREL_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PCREL_CALL"},
+ {R_SHORT_PCREL_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SHORT_PCREL_MODE"},
+ {R_LONG_PCREL_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LONG_PCREL_MODE"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_ABS_CALL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ABS_CALL"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_DP_RELATIVE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DP_RELATIVE"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_DLT_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DLT_REL"},
+ {R_DLT_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DLT_REL"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_CODE_ONE_SYMBOL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_ONE_SYMBOL"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
+ {R_MILLI_REL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_MILLI_REL"},
+ {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
+ {R_CODE_PLABEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_PLABEL"},
+ {R_BREAKPOINT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BREAKPOINT"},
+ {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
+ {R_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ENTRY"},
+ {R_ALT_ENTRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_ALT_ENTRY"},
+ {R_EXIT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_EXIT"},
+ {R_BEGIN_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_TRY"},
+ {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
+ {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
+ {R_END_TRY, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_TRY"},
+ {R_BEGIN_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_BEGIN_BRTAB"},
+ {R_END_BRTAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_END_BRTAB"},
+ {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
+ {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
+ {R_STATEMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_STATEMENT"},
+ {R_DATA_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_EXPR"},
+ {R_CODE_EXPR, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_CODE_EXPR"},
+ {R_FSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_FSEL"},
+ {R_LSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LSEL"},
+ {R_RSEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RSEL"},
+ {R_N_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N_MODE"},
+ {R_S_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_S_MODE"},
+ {R_D_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_D_MODE"},
+ {R_R_MODE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_R_MODE"},
+ {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
+ {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
+ {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
+ {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
+ {R_DATA_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_DATA_OVERRIDE"},
+ {R_TRANSLATED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_TRANSLATED"},
+ {R_AUX_UNWIND, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_AUX_UNWIND"},
+ {R_COMP1, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP1"},
+ {R_COMP2, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP2"},
+ {R_COMP3, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMP3"},
+ {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
+ {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
+ {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
+ {R_PREV_FIXUP, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_PREV_FIXUP"},
+ {R_SEC_STMT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_SEC_STMT"},
+ {R_N0SEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N0SEL"},
+ {R_N1SEL, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_N1SEL"},
+ {R_LINETAB, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LINETAB"},
+ {R_LINETAB_ESC, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LINETAB_ESC"},
+ {R_LTP_OVERRIDE, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_LTP_OVERRIDE"},
+ {R_COMMENT, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_COMMENT"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"},
+ {R_RESERVED, 0, 0, 32, false, 0, 0, hppa_som_reloc, "R_RESERVED"}};
+
+/* Initialize the SOM relocation queue. By definition the queue holds
+ the last four multibyte fixups. */
+
+static void
+som_initialize_reloc_queue (queue)
+ struct reloc_queue *queue;
+{
+ queue[0].reloc = NULL;
+ queue[0].size = 0;
+ queue[1].reloc = NULL;
+ queue[1].size = 0;
+ queue[2].reloc = NULL;
+ queue[2].size = 0;
+ queue[3].reloc = NULL;
+ queue[3].size = 0;
+}
+
+/* Insert a new relocation into the relocation queue. */
+
+static void
+som_reloc_queue_insert (p, size, queue)
+ unsigned char *p;
+ unsigned int size;
+ struct reloc_queue *queue;
+{
+ queue[3].reloc = queue[2].reloc;
+ queue[3].size = queue[2].size;
+ queue[2].reloc = queue[1].reloc;
+ queue[2].size = queue[1].size;
+ queue[1].reloc = queue[0].reloc;
+ queue[1].size = queue[0].size;
+ queue[0].reloc = p;
+ queue[0].size = size;
+}
+
+/* When an entry in the relocation queue is reused, the entry moves
+ to the front of the queue. */
+
+static void
+som_reloc_queue_fix (queue, index)
+ struct reloc_queue *queue;
+ unsigned int index;
+{
+ if (index == 0)
+ return;
+
+ if (index == 1)
+ {
+ unsigned char *tmp1 = queue[0].reloc;
+ unsigned int tmp2 = queue[0].size;
+ queue[0].reloc = queue[1].reloc;
+ queue[0].size = queue[1].size;
+ queue[1].reloc = tmp1;
+ queue[1].size = tmp2;
+ return;
+ }
+
+ if (index == 2)
+ {
+ unsigned char *tmp1 = queue[0].reloc;
+ unsigned int tmp2 = queue[0].size;
+ queue[0].reloc = queue[2].reloc;
+ queue[0].size = queue[2].size;
+ queue[2].reloc = queue[1].reloc;
+ queue[2].size = queue[1].size;
+ queue[1].reloc = tmp1;
+ queue[1].size = tmp2;
+ return;
+ }
+
+ if (index == 3)
+ {
+ unsigned char *tmp1 = queue[0].reloc;
+ unsigned int tmp2 = queue[0].size;
+ queue[0].reloc = queue[3].reloc;
+ queue[0].size = queue[3].size;
+ queue[3].reloc = queue[2].reloc;
+ queue[3].size = queue[2].size;
+ queue[2].reloc = queue[1].reloc;
+ queue[2].size = queue[1].size;
+ queue[1].reloc = tmp1;
+ queue[1].size = tmp2;
+ return;
+ }
+ abort();
+}
+
+/* Search for a particular relocation in the relocation queue. */
+
+static int
+som_reloc_queue_find (p, size, queue)
+ unsigned char *p;
+ unsigned int size;
+ struct reloc_queue *queue;
+{
+ if (queue[0].reloc && !memcmp (p, queue[0].reloc, size)
+ && size == queue[0].size)
+ return 0;
+ if (queue[1].reloc && !memcmp (p, queue[1].reloc, size)
+ && size == queue[1].size)
+ return 1;
+ if (queue[2].reloc && !memcmp (p, queue[2].reloc, size)
+ && size == queue[2].size)
+ return 2;
+ if (queue[3].reloc && !memcmp (p, queue[3].reloc, size)
+ && size == queue[3].size)
+ return 3;
+ return -1;
+}
+
+static unsigned char *
+try_prev_fixup (abfd, subspace_reloc_sizep, p, size, queue)
+ bfd *abfd;
+ int *subspace_reloc_sizep;
+ unsigned char *p;
+ unsigned int size;
+ struct reloc_queue *queue;
+{
+ int queue_index = som_reloc_queue_find (p, size, queue);
+
+ if (queue_index != -1)
+ {
+ /* Found this in a previous fixup. Undo the fixup we
+ just built and use R_PREV_FIXUP instead. We saved
+ a total of size - 1 bytes in the fixup stream. */
+ bfd_put_8 (abfd, R_PREV_FIXUP + queue_index, p);
+ p += 1;
+ *subspace_reloc_sizep += 1;
+ som_reloc_queue_fix (queue, queue_index);
+ }
+ else
+ {
+ som_reloc_queue_insert (p, size, queue);
+ *subspace_reloc_sizep += size;
+ p += size;
+ }
+ return p;
+}
+
+/* Emit the proper R_NO_RELOCATION fixups to map the next SKIP
+ bytes without any relocation. Update the size of the subspace
+ relocation stream via SUBSPACE_RELOC_SIZE_P; also return the
+ current pointer into the relocation stream. */
+
+static unsigned char *
+som_reloc_skip (abfd, skip, p, subspace_reloc_sizep, queue)
+ bfd *abfd;
+ unsigned int skip;
+ unsigned char *p;
+ unsigned int *subspace_reloc_sizep;
+ struct reloc_queue *queue;
+{
+ /* Use a 4 byte R_NO_RELOCATION entry with a maximal value
+ then R_PREV_FIXUPs to get the difference down to a
+ reasonable size. */
+ if (skip >= 0x1000000)
+ {
+ skip -= 0x1000000;
+ bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
+ bfd_put_8 (abfd, 0xff, p + 1);
+ bfd_put_16 (abfd, 0xffff, p + 2);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
+ while (skip >= 0x1000000)
+ {
+ skip -= 0x1000000;
+ bfd_put_8 (abfd, R_PREV_FIXUP, p);
+ p++;
+ *subspace_reloc_sizep += 1;
+ /* No need to adjust queue here since we are repeating the
+ most recent fixup. */
+ }
+ }
+
+ /* The difference must be less than 0x1000000. Use one
+ more R_NO_RELOCATION entry to get to the right difference. */
+ if ((skip & 3) == 0 && skip <= 0xc0000 && skip > 0)
+ {
+ /* Difference can be handled in a simple single-byte
+ R_NO_RELOCATION entry. */
+ if (skip <= 0x60)
+ {
+ bfd_put_8 (abfd, R_NO_RELOCATION + (skip >> 2) - 1, p);
+ *subspace_reloc_sizep += 1;
+ p++;
+ }
+ /* Handle it with a two byte R_NO_RELOCATION entry. */
+ else if (skip <= 0x1000)
+ {
+ bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p);
+ bfd_put_8 (abfd, (skip >> 2) - 1, p + 1);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
+ }
+ /* Handle it with a three byte R_NO_RELOCATION entry. */
+ else
+ {
+ bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p);
+ bfd_put_16 (abfd, (skip >> 2) - 1, p + 1);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
+ }
+ }
+ /* Ugh. Punt and use a 4 byte entry. */
+ else if (skip > 0)
+ {
+ bfd_put_8 (abfd, R_NO_RELOCATION + 31, p);
+ bfd_put_8 (abfd, (skip - 1) >> 16, p + 1);
+ bfd_put_16 (abfd, skip - 1, p + 2);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
+ }
+ return p;
+}
+
+/* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend
+ from a BFD relocation. Update the size of the subspace relocation
+ stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer
+ into the relocation stream. */
+
+static unsigned char *
+som_reloc_addend (abfd, addend, p, subspace_reloc_sizep, queue)
+ bfd *abfd;
+ int addend;
+ unsigned char *p;
+ unsigned int *subspace_reloc_sizep;
+ struct reloc_queue *queue;
+{
+ if ((unsigned)(addend) + 0x80 < 0x100)
+ {
+ bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p);
+ bfd_put_8 (abfd, addend, p + 1);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
+ }
+ else if ((unsigned) (addend) + 0x8000 < 0x10000)
+ {
+ bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p);
+ bfd_put_16 (abfd, addend, p + 1);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
+ }
+ else if ((unsigned) (addend) + 0x800000 < 0x1000000)
+ {
+ bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p);
+ bfd_put_8 (abfd, addend >> 16, p + 1);
+ bfd_put_16 (abfd, addend, p + 2);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue);
+ }
+ else
+ {
+ bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p);
+ bfd_put_32 (abfd, addend, p + 1);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
+ }
+ return p;
+}
+
+/* Handle a single function call relocation. */
+
+static unsigned char *
+som_reloc_call (abfd, p, subspace_reloc_sizep, bfd_reloc, sym_num, queue)
+ bfd *abfd;
+ unsigned char *p;
+ unsigned int *subspace_reloc_sizep;
+ arelent *bfd_reloc;
+ int sym_num;
+ struct reloc_queue *queue;
+{
+ int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend);
+ int rtn_bits = arg_bits & 0x3;
+ int type, done = 0;
+
+ /* You'll never believe all this is necessary to handle relocations
+ for function calls. Having to compute and pack the argument
+ relocation bits is the real nightmare.
+
+ If you're interested in how this works, just forget it. You really
+ do not want to know about this braindamage. */
+
+ /* First see if this can be done with a "simple" relocation. Simple
+ relocations have a symbol number < 0x100 and have simple encodings
+ of argument relocations. */
+
+ if (sym_num < 0x100)
+ {
+ switch (arg_bits)
+ {
+ case 0:
+ case 1:
+ type = 0;
+ break;
+ case 1 << 8:
+ case 1 << 8 | 1:
+ type = 1;
+ break;
+ case 1 << 8 | 1 << 6:
+ case 1 << 8 | 1 << 6 | 1:
+ type = 2;
+ break;
+ case 1 << 8 | 1 << 6 | 1 << 4:
+ case 1 << 8 | 1 << 6 | 1 << 4 | 1:
+ type = 3;
+ break;
+ case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2:
+ case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1:
+ type = 4;
+ break;
+ default:
+ /* Not one of the easy encodings. This will have to be
+ handled by the more complex code below. */
+ type = -1;
+ break;
+ }
+ if (type != -1)
+ {
+ /* Account for the return value too. */
+ if (rtn_bits)
+ type += 5;
+
+ /* Emit a 2 byte relocation. Then see if it can be handled
+ with a relocation which is already in the relocation queue. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type + type, p);
+ bfd_put_8 (abfd, sym_num, p + 1);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue);
+ done = 1;
+ }
+ }
+
+ /* If this could not be handled with a simple relocation, then do a hard
+ one. Hard relocations occur if the symbol number was too high or if
+ the encoding of argument relocation bits is too complex. */
+ if (! done)
+ {
+ /* Don't ask about these magic sequences. I took them straight
+ from gas-1.36 which took them from the a.out man page. */
+ type = rtn_bits;
+ if ((arg_bits >> 6 & 0xf) == 0xe)
+ type += 9 * 40;
+ else
+ type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40;
+ if ((arg_bits >> 2 & 0xf) == 0xe)
+ type += 9 * 4;
+ else
+ type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4;
+
+ /* Output the first two bytes of the relocation. These describe
+ the length of the relocation and encoding style. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type + 10
+ + 2 * (sym_num >= 0x100) + (type >= 0x100),
+ p);
+ bfd_put_8 (abfd, type, p + 1);
+
+ /* Now output the symbol index and see if this bizarre relocation
+ just happened to be in the relocation queue. */
+ if (sym_num < 0x100)
+ {
+ bfd_put_8 (abfd, sym_num, p + 2);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue);
+ }
+ else
+ {
+ bfd_put_8 (abfd, sym_num >> 16, p + 2);
+ bfd_put_16 (abfd, sym_num, p + 3);
+ p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue);
+ }
+ }
+ return p;
+}
+
+
+/* Return the logarithm of X, base 2, considering X unsigned.
+ Abort -1 if X is not a power or two or is zero. */
+
+static int
+log2 (x)
+ unsigned int x;
+{
+ int log = 0;
+
+ /* Test for 0 or a power of 2. */
+ if (x == 0 || x != (x & -x))
+ return -1;
+
+ while ((x >>= 1) != 0)
+ log++;
+ return log;
+}
+
+static bfd_reloc_status_type
+hppa_som_reloc (abfd, reloc_entry, symbol_in, data,
+ input_section, output_bfd, error_message)
+ bfd *abfd;
+ arelent *reloc_entry;
+ asymbol *symbol_in;
+ PTR data;
+ asection *input_section;
+ bfd *output_bfd;
+ char **error_message;
+{
+ if (output_bfd)
+ {
+ reloc_entry->address += input_section->output_offset;
+ return bfd_reloc_ok;
+ }
+ return bfd_reloc_ok;
+}
+
+/* Given a generic HPPA relocation type, the instruction format,
+ and a field selector, return one or more appropriate SOM relocations. */
+
+int **
+hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff)
+ bfd *abfd;
+ int base_type;
+ int format;
+ enum hppa_reloc_field_selector_type_alt field;
+ int sym_diff;
+{
+ int *final_type, **final_types;
+
+ final_types = (int **) bfd_alloc_by_size_t (abfd, sizeof (int *) * 6);
+ final_type = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types || !final_type)
+ return NULL;
+
+ /* The field selector may require additional relocations to be
+ generated. It's impossible to know at this moment if additional
+ relocations will be needed, so we make them. The code to actually
+ write the relocation/fixup stream is responsible for removing
+ any redundant relocations. */
+ switch (field)
+ {
+ case e_fsel:
+ case e_psel:
+ case e_lpsel:
+ case e_rpsel:
+ final_types[0] = final_type;
+ final_types[1] = NULL;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_tsel:
+ case e_ltsel:
+ case e_rtsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ if (field == e_tsel)
+ *final_types[0] = R_FSEL;
+ else if (field == e_ltsel)
+ *final_types[0] = R_LSEL;
+ else
+ *final_types[0] = R_RSEL;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_lssel:
+ case e_rssel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_S_MODE;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_lsel:
+ case e_rsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_N_MODE;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_ldsel:
+ case e_rdsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_D_MODE;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_lrsel:
+ case e_rrsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_R_MODE;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_nsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_N1SEL;
+ final_types[1] = final_type;
+ final_types[2] = NULL;
+ *final_type = base_type;
+ break;
+
+ case e_nlsel:
+ case e_nlrsel:
+ final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0])
+ return NULL;
+ *final_types[0] = R_N0SEL;
+ final_types[1] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[1])
+ return NULL;
+ if (field == e_nlsel)
+ *final_types[1] = R_N_MODE;
+ else
+ *final_types[1] = R_R_MODE;
+ final_types[2] = final_type;
+ final_types[3] = NULL;
+ *final_type = base_type;
+ break;
+ }
+
+ switch (base_type)
+ {
+ case R_HPPA:
+ /* The difference of two symbols needs *very* special handling. */
+ if (sym_diff)
+ {
+ final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0] || !final_types[1] || !final_types[2])
+ return NULL;
+ if (field == e_fsel)
+ *final_types[0] = R_FSEL;
+ else if (field == e_rsel)
+ *final_types[0] = R_RSEL;
+ else if (field == e_lsel)
+ *final_types[0] = R_LSEL;
+ *final_types[1] = R_COMP2;
+ *final_types[2] = R_COMP2;
+ *final_types[3] = R_COMP1;
+ final_types[4] = final_type;
+ *final_types[4] = R_CODE_EXPR;
+ final_types[5] = NULL;
+ break;
+ }
+ /* PLABELs get their own relocation type. */
+ else if (field == e_psel
+ || field == e_lpsel
+ || field == e_rpsel)
+ {
+ /* A PLABEL relocation that has a size of 32 bits must
+ be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */
+ if (format == 32)
+ *final_type = R_DATA_PLABEL;
+ else
+ *final_type = R_CODE_PLABEL;
+ }
+ /* PIC stuff. */
+ else if (field == e_tsel
+ || field == e_ltsel
+ || field == e_rtsel)
+ *final_type = R_DLT_REL;
+ /* A relocation in the data space is always a full 32bits. */
+ else if (format == 32)
+ *final_type = R_DATA_ONE_SYMBOL;
+
+ break;
+
+ case R_HPPA_GOTOFF:
+ /* More PLABEL special cases. */
+ if (field == e_psel
+ || field == e_lpsel
+ || field == e_rpsel)
+ *final_type = R_DATA_PLABEL;
+ break;
+
+ case R_HPPA_COMPLEX:
+ /* The difference of two symbols needs *very* special handling. */
+ if (sym_diff)
+ {
+ final_types[0] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[1] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[2] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ final_types[3] = (int *)bfd_alloc_by_size_t (abfd, sizeof (int));
+ if (!final_types[0] || !final_types[1] || !final_types[2])
+ return NULL;
+ if (field == e_fsel)
+ *final_types[0] = R_FSEL;
+ else if (field == e_rsel)
+ *final_types[0] = R_RSEL;
+ else if (field == e_lsel)
+ *final_types[0] = R_LSEL;
+ *final_types[1] = R_COMP2;
+ *final_types[2] = R_COMP2;
+ *final_types[3] = R_COMP1;
+ final_types[4] = final_type;
+ *final_types[4] = R_CODE_EXPR;
+ final_types[5] = NULL;
+ break;
+ }
+ else
+ break;
+
+ case R_HPPA_NONE:
+ case R_HPPA_ABS_CALL:
+ case R_HPPA_PCREL_CALL:
+ /* Right now we can default all these. */
+ break;
+ }
+ return final_types;
+}
+
+/* Return the address of the correct entry in the PA SOM relocation
+ howto table. */
+
+/*ARGSUSED*/
+static reloc_howto_type *
+som_bfd_reloc_type_lookup (abfd, code)
+ bfd *abfd;
+ bfd_reloc_code_real_type code;
+{
+ if ((int) code < (int) R_NO_RELOCATION + 255)
+ {
+ BFD_ASSERT ((int) som_hppa_howto_table[(int) code].type == (int) code);
+ return &som_hppa_howto_table[(int) code];
+ }
+
+ return (reloc_howto_type *) 0;
+}
+
+/* Perform some initialization for an object. Save results of this
+ initialization in the BFD. */
+
+static const bfd_target *
+som_object_setup (abfd, file_hdrp, aux_hdrp)
+ bfd *abfd;
+ struct header *file_hdrp;
+ struct som_exec_auxhdr *aux_hdrp;
+{
+ asection *section;
+ int found;
+
+ /* som_mkobject will set bfd_error if som_mkobject fails. */
+ if (som_mkobject (abfd) != true)
+ return 0;
+
+ /* Set BFD flags based on what information is available in the SOM. */
+ abfd->flags = NO_FLAGS;
+ if (file_hdrp->symbol_total)
+ abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
+
+ switch (file_hdrp->a_magic)
+ {
+ case DEMAND_MAGIC:
+ abfd->flags |= (D_PAGED | WP_TEXT | EXEC_P);
+ break;
+ case SHARE_MAGIC:
+ abfd->flags |= (WP_TEXT | EXEC_P);
+ break;
+ case EXEC_MAGIC:
+ abfd->flags |= (EXEC_P);
+ break;
+ case RELOC_MAGIC:
+ abfd->flags |= HAS_RELOC;
+ break;
+#ifdef SHL_MAGIC
+ case SHL_MAGIC:
+#endif
+#ifdef DL_MAGIC
+ case DL_MAGIC:
+#endif
+ abfd->flags |= DYNAMIC;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Allocate space to hold the saved exec header information. */
+ obj_som_exec_data (abfd) = (struct som_exec_data *)
+ bfd_zalloc (abfd, sizeof (struct som_exec_data ));
+ if (obj_som_exec_data (abfd) == NULL)
+ return NULL;
+
+ /* The braindamaged OSF1 linker switched exec_flags and exec_entry!
+
+ We used to identify OSF1 binaries based on NEW_VERSION_ID, but
+ apparently the latest HPUX linker is using NEW_VERSION_ID now.
+
+ It's about time, OSF has used the new id since at least 1992;
+ HPUX didn't start till nearly 1995!.
+
+ The new approach examines the entry field. If it's zero or not 4
+ byte aligned then it's not a proper code address and we guess it's
+ really the executable flags. */
+ found = 0;
+ for (section = abfd->sections; section; section = section->next)
+ {
+ if ((section->flags & SEC_CODE) == 0)
+ continue;
+ if (aux_hdrp->exec_entry >= section->vma
+ && aux_hdrp->exec_entry < section->vma + section->_cooked_size)
+ found = 1;
+ }
+ if (aux_hdrp->exec_entry == 0
+ || (aux_hdrp->exec_entry & 0x3) != 0
+ || ! found)
+ {
+ bfd_get_start_address (abfd) = aux_hdrp->exec_flags;
+ obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_entry;
+ }
+ else
+ {
+ bfd_get_start_address (abfd) = aux_hdrp->exec_entry;
+ obj_som_exec_data (abfd)->exec_flags = aux_hdrp->exec_flags;
+ }
+
+ bfd_default_set_arch_mach (abfd, bfd_arch_hppa, pa10);
+ bfd_get_symcount (abfd) = file_hdrp->symbol_total;
+
+ /* Initialize the saved symbol table and string table to NULL.
+ Save important offsets and sizes from the SOM header into
+ the BFD. */
+ obj_som_stringtab (abfd) = (char *) NULL;
+ obj_som_symtab (abfd) = (som_symbol_type *) NULL;
+ obj_som_sorted_syms (abfd) = NULL;
+ obj_som_stringtab_size (abfd) = file_hdrp->symbol_strings_size;
+ obj_som_sym_filepos (abfd) = file_hdrp->symbol_location;
+ obj_som_str_filepos (abfd) = file_hdrp->symbol_strings_location;
+ obj_som_reloc_filepos (abfd) = file_hdrp->fixup_request_location;
+ obj_som_exec_data (abfd)->system_id = file_hdrp->system_id;
+
+ return abfd->xvec;
+}
+
+/* Convert all of the space and subspace info into BFD sections. Each space
+ contains a number of subspaces, which in turn describe the mapping between
+ regions of the exec file, and the address space that the program runs in.
+ BFD sections which correspond to spaces will overlap the sections for the
+ associated subspaces. */
+
+static boolean
+setup_sections (abfd, file_hdr)
+ bfd *abfd;
+ struct header *file_hdr;
+{
+ char *space_strings;
+ unsigned int space_index, i;
+ unsigned int total_subspaces = 0;
+ asection **subspace_sections, *section;
+
+ /* First, read in space names */
+
+ space_strings = bfd_malloc (file_hdr->space_strings_size);
+ if (!space_strings && file_hdr->space_strings_size != 0)
+ goto error_return;
+
+ if (bfd_seek (abfd, file_hdr->space_strings_location, SEEK_SET) < 0)
+ goto error_return;
+ if (bfd_read (space_strings, 1, file_hdr->space_strings_size, abfd)
+ != file_hdr->space_strings_size)
+ goto error_return;
+
+ /* Loop over all of the space dictionaries, building up sections */
+ for (space_index = 0; space_index < file_hdr->space_total; space_index++)
+ {
+ struct space_dictionary_record space;
+ struct subspace_dictionary_record subspace, save_subspace;
+ int subspace_index;
+ asection *space_asect;
+ char *newname;
+
+ /* Read the space dictionary element */
+ if (bfd_seek (abfd, file_hdr->space_location
+ + space_index * sizeof space, SEEK_SET) < 0)
+ goto error_return;
+ if (bfd_read (&space, 1, sizeof space, abfd) != sizeof space)
+ goto error_return;
+
+ /* Setup the space name string */
+ space.name.n_name = space.name.n_strx + space_strings;
+
+ /* Make a section out of it */
+ newname = bfd_alloc (abfd, strlen (space.name.n_name) + 1);
+ if (!newname)
+ goto error_return;
+ strcpy (newname, space.name.n_name);
+
+ space_asect = bfd_make_section_anyway (abfd, newname);
+ if (!space_asect)
+ goto error_return;
+
+ if (space.is_loadable == 0)
+ space_asect->flags |= SEC_DEBUGGING;
+
+ /* Set up all the attributes for the space. */
+ if (bfd_som_set_section_attributes (space_asect, space.is_defined,
+ space.is_private, space.sort_key,
+ space.space_number) == false)
+ goto error_return;
+
+ /* If the space has no subspaces, then we're done. */
+ if (space.subspace_quantity == 0)
+ continue;
+
+ /* Now, read in the first subspace for this space */
+ if (bfd_seek (abfd, file_hdr->subspace_location
+ + space.subspace_index * sizeof subspace,
+ SEEK_SET) < 0)
+ goto error_return;
+ if (bfd_read (&subspace, 1, sizeof subspace, abfd) != sizeof subspace)
+ goto error_return;
+ /* Seek back to the start of the subspaces for loop below */
+ if (bfd_seek (abfd, file_hdr->subspace_location
+ + space.subspace_index * sizeof subspace,
+ SEEK_SET) < 0)
+ goto error_return;
+
+ /* Setup the start address and file loc from the first subspace record */
+ space_asect->vma = subspace.subspace_start;
+ space_asect->filepos = subspace.file_loc_init_value;
+ space_asect->alignment_power = log2 (subspace.alignment);
+ if (space_asect->alignment_power == -1)
+ goto error_return;
+
+ /* Initialize save_subspace so we can reliably determine if this
+ loop placed any useful values into it. */
+ memset (&save_subspace, 0, sizeof (struct subspace_dictionary_record));
+
+ /* Loop over the rest of the subspaces, building up more sections */
+ for (subspace_index = 0; subspace_index < space.subspace_quantity;
+ subspace_index++)
+ {
+ asection *subspace_asect;
+
+ /* Read in the next subspace */
+ if (bfd_read (&subspace, 1, sizeof subspace, abfd)
+ != sizeof subspace)
+ goto error_return;
+
+ /* Setup the subspace name string */
+ subspace.name.n_name = subspace.name.n_strx + space_strings;
+
+ newname = bfd_alloc (abfd, strlen (subspace.name.n_name) + 1);
+ if (!newname)
+ goto error_return;
+ strcpy (newname, subspace.name.n_name);
+
+ /* Make a section out of this subspace */
+ subspace_asect = bfd_make_section_anyway (abfd, newname);
+ if (!subspace_asect)
+ goto error_return;
+
+ /* Store private information about the section. */
+ if (bfd_som_set_subsection_attributes (subspace_asect, space_asect,
+ subspace.access_control_bits,
+ subspace.sort_key,
+ subspace.quadrant) == false)
+ goto error_return;
+
+ /* Keep an easy mapping between subspaces and sections.
+ Note we do not necessarily read the subspaces in the
+ same order in which they appear in the object file.
+
+ So to make the target index come out correctly, we
+ store the location of the subspace header in target
+ index, then sort using the location of the subspace
+ header as the key. Then we can assign correct
+ subspace indices. */
+ total_subspaces++;
+ subspace_asect->target_index = bfd_tell (abfd) - sizeof (subspace);
+
+ /* Set SEC_READONLY and SEC_CODE/SEC_DATA as specified
+ by the access_control_bits in the subspace header. */
+ switch (subspace.access_control_bits >> 4)
+ {
+ /* Readonly data. */
+ case 0x0:
+ subspace_asect->flags |= SEC_DATA | SEC_READONLY;
+ break;
+
+ /* Normal data. */
+ case 0x1:
+ subspace_asect->flags |= SEC_DATA;
+ break;
+
+ /* Readonly code and the gateways.
+ Gateways have other attributes which do not map
+ into anything BFD knows about. */
+ case 0x2:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ subspace_asect->flags |= SEC_CODE | SEC_READONLY;
+ break;
+
+ /* dynamic (writable) code. */
+ case 0x3:
+ subspace_asect->flags |= SEC_CODE;
+ break;
+ }
+
+ if (subspace.dup_common || subspace.is_common)
+ subspace_asect->flags |= SEC_IS_COMMON;
+ else if (subspace.subspace_length > 0)
+ subspace_asect->flags |= SEC_HAS_CONTENTS;
+
+ if (subspace.is_loadable)
+ subspace_asect->flags |= SEC_ALLOC | SEC_LOAD;
+ else
+ subspace_asect->flags |= SEC_DEBUGGING;
+
+ if (subspace.code_only)
+ subspace_asect->flags |= SEC_CODE;
+
+ /* Both file_loc_init_value and initialization_length will
+ be zero for a BSS like subspace. */
+ if (subspace.file_loc_init_value == 0
+ && subspace.initialization_length == 0)
+ subspace_asect->flags &= ~(SEC_DATA | SEC_LOAD | SEC_HAS_CONTENTS);
+
+ /* This subspace has relocations.
+ The fixup_request_quantity is a byte count for the number of
+ entries in the relocation stream; it is not the actual number
+ of relocations in the subspace. */
+ if (subspace.fixup_request_quantity != 0)
+ {
+ subspace_asect->flags |= SEC_RELOC;
+ subspace_asect->rel_filepos = subspace.fixup_request_index;
+ som_section_data (subspace_asect)->reloc_size
+ = subspace.fixup_request_quantity;
+ /* We can not determine this yet. When we read in the
+ relocation table the correct value will be filled in. */
+ subspace_asect->reloc_count = -1;
+ }
+
+ /* Update save_subspace if appropriate. */
+ if (subspace.file_loc_init_value > save_subspace.file_loc_init_value)
+ save_subspace = subspace;
+
+ subspace_asect->vma = subspace.subspace_start;
+ subspace_asect->_cooked_size = subspace.subspace_length;
+ subspace_asect->_raw_size = subspace.subspace_length;
+ subspace_asect->filepos = subspace.file_loc_init_value;
+ subspace_asect->alignment_power = log2 (subspace.alignment);
+ if (subspace_asect->alignment_power == -1)
+ goto error_return;
+ }
+
+ /* Yow! there is no subspace within the space which actually
+ has initialized information in it; this should never happen
+ as far as I know. */
+ if (!save_subspace.file_loc_init_value)
+ goto error_return;
+
+ /* Setup the sizes for the space section based upon the info in the
+ last subspace of the space. */
+ space_asect->_cooked_size = save_subspace.subspace_start
+ - space_asect->vma + save_subspace.subspace_length;
+ space_asect->_raw_size = save_subspace.file_loc_init_value
+ - space_asect->filepos + save_subspace.initialization_length;
+ }
+ /* Now that we've read in all the subspace records, we need to assign
+ a target index to each subspace. */
+ subspace_sections = (asection **) bfd_malloc (total_subspaces
+ * sizeof (asection *));
+ if (subspace_sections == NULL)
+ goto error_return;
+
+ for (i = 0, section = abfd->sections; section; section = section->next)
+ {
+ if (!som_is_subspace (section))
+ continue;
+
+ subspace_sections[i] = section;
+ i++;
+ }
+ qsort (subspace_sections, total_subspaces,
+ sizeof (asection *), compare_subspaces);
+
+ /* subspace_sections is now sorted in the order in which the subspaces
+ appear in the object file. Assign an index to each one now. */
+ for (i = 0; i < total_subspaces; i++)
+ subspace_sections[i]->target_index = i;
+
+ if (space_strings != NULL)
+ free (space_strings);
+
+ if (subspace_sections != NULL)
+ free (subspace_sections);
+
+ return true;
+
+ error_return:
+ if (space_strings != NULL)
+ free (space_strings);
+
+ if (subspace_sections != NULL)
+ free (subspace_sections);
+ return false;
+}
+
+/* Read in a SOM object and make it into a BFD. */
+
+static const bfd_target *
+som_object_p (abfd)
+ bfd *abfd;
+{
+ struct header file_hdr;
+ struct som_exec_auxhdr aux_hdr;
+
+ if (bfd_read ((PTR) & file_hdr, 1, FILE_HDR_SIZE, abfd) != FILE_HDR_SIZE)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (!_PA_RISC_ID (file_hdr.system_id))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ switch (file_hdr.a_magic)
+ {
+ case RELOC_MAGIC:
+ case EXEC_MAGIC:
+ case SHARE_MAGIC:
+ case DEMAND_MAGIC:
+#ifdef DL_MAGIC
+ case DL_MAGIC:
+#endif
+#ifdef SHL_MAGIC
+ case SHL_MAGIC:
+#endif
+#ifdef EXECLIBMAGIC
+ case EXECLIBMAGIC:
+#endif
+#ifdef SHARED_MAGIC_CNX
+ case SHARED_MAGIC_CNX:
+#endif
+ break;
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ if (file_hdr.version_id != VERSION_ID
+ && file_hdr.version_id != NEW_VERSION_ID)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ /* If the aux_header_size field in the file header is zero, then this
+ object is an incomplete executable (a .o file). Do not try to read
+ a non-existant auxiliary header. */
+ memset (&aux_hdr, 0, sizeof (struct som_exec_auxhdr));
+ if (file_hdr.aux_header_size != 0)
+ {
+ if (bfd_read ((PTR) & aux_hdr, 1, AUX_HDR_SIZE, abfd) != AUX_HDR_SIZE)
+ {
+ if (bfd_get_error () != bfd_error_system_call)
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+ }
+
+ if (!setup_sections (abfd, &file_hdr))
+ {
+ /* setup_sections does not bubble up a bfd error code. */
+ bfd_set_error (bfd_error_bad_value);
+ return 0;
+ }
+
+ /* This appears to be a valid SOM object. Do some initialization. */
+ return som_object_setup (abfd, &file_hdr, &aux_hdr);
+}
+
+/* Create a SOM object. */
+
+static boolean
+som_mkobject (abfd)
+ bfd *abfd;
+{
+ /* Allocate memory to hold backend information. */
+ abfd->tdata.som_data = (struct som_data_struct *)
+ bfd_zalloc (abfd, sizeof (struct som_data_struct));
+ if (abfd->tdata.som_data == NULL)
+ return false;
+ return true;
+}
+
+/* Initialize some information in the file header. This routine makes
+ not attempt at doing the right thing for a full executable; it
+ is only meant to handle relocatable objects. */
+
+static boolean
+som_prep_headers (abfd)
+ bfd *abfd;
+{
+ struct header *file_hdr;
+ asection *section;
+
+ /* Make and attach a file header to the BFD. */
+ file_hdr = (struct header *) bfd_zalloc (abfd, sizeof (struct header));
+ if (file_hdr == NULL)
+ return false;
+ obj_som_file_hdr (abfd) = file_hdr;
+
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ {
+
+ /* Make and attach an exec header to the BFD. */
+ obj_som_exec_hdr (abfd) = (struct som_exec_auxhdr *)
+ bfd_zalloc (abfd, sizeof (struct som_exec_auxhdr));
+ if (obj_som_exec_hdr (abfd) == NULL)
+ return false;
+
+ if (abfd->flags & D_PAGED)
+ file_hdr->a_magic = DEMAND_MAGIC;
+ else if (abfd->flags & WP_TEXT)
+ file_hdr->a_magic = SHARE_MAGIC;
+#ifdef SHL_MAGIC
+ else if (abfd->flags & DYNAMIC)
+ file_hdr->a_magic = SHL_MAGIC;
+#endif
+ else
+ file_hdr->a_magic = EXEC_MAGIC;
+ }
+ else
+ file_hdr->a_magic = RELOC_MAGIC;
+
+ /* Only new format SOM is supported. */
+ file_hdr->version_id = NEW_VERSION_ID;
+
+ /* These fields are optional, and embedding timestamps is not always
+ a wise thing to do, it makes comparing objects during a multi-stage
+ bootstrap difficult. */
+ file_hdr->file_time.secs = 0;
+ file_hdr->file_time.nanosecs = 0;
+
+ file_hdr->entry_space = 0;
+ file_hdr->entry_subspace = 0;
+ file_hdr->entry_offset = 0;
+ file_hdr->presumed_dp = 0;
+
+ /* Now iterate over the sections translating information from
+ BFD sections to SOM spaces/subspaces. */
+
+ for (section = abfd->sections; section != NULL; section = section->next)
+ {
+ /* Ignore anything which has not been marked as a space or
+ subspace. */
+ if (!som_is_space (section) && !som_is_subspace (section))
+ continue;
+
+ if (som_is_space (section))
+ {
+ /* Allocate space for the space dictionary. */
+ som_section_data (section)->space_dict
+ = (struct space_dictionary_record *)
+ bfd_zalloc (abfd, sizeof (struct space_dictionary_record));
+ if (som_section_data (section)->space_dict == NULL)
+ return false;
+ /* Set space attributes. Note most attributes of SOM spaces
+ are set based on the subspaces it contains. */
+ som_section_data (section)->space_dict->loader_fix_index = -1;
+ som_section_data (section)->space_dict->init_pointer_index = -1;
+
+ /* Set more attributes that were stuffed away in private data. */
+ som_section_data (section)->space_dict->sort_key =
+ som_section_data (section)->copy_data->sort_key;
+ som_section_data (section)->space_dict->is_defined =
+ som_section_data (section)->copy_data->is_defined;
+ som_section_data (section)->space_dict->is_private =
+ som_section_data (section)->copy_data->is_private;
+ som_section_data (section)->space_dict->space_number =
+ som_section_data (section)->copy_data->space_number;
+ }
+ else
+ {
+ /* Allocate space for the subspace dictionary. */
+ som_section_data (section)->subspace_dict
+ = (struct subspace_dictionary_record *)
+ bfd_zalloc (abfd, sizeof (struct subspace_dictionary_record));
+ if (som_section_data (section)->subspace_dict == NULL)
+ return false;
+
+ /* Set subspace attributes. Basic stuff is done here, additional
+ attributes are filled in later as more information becomes
+ available. */
+ if (section->flags & SEC_IS_COMMON)
+ {
+ som_section_data (section)->subspace_dict->dup_common = 1;
+ som_section_data (section)->subspace_dict->is_common = 1;
+ }
+
+ if (section->flags & SEC_ALLOC)
+ som_section_data (section)->subspace_dict->is_loadable = 1;
+
+ if (section->flags & SEC_CODE)
+ som_section_data (section)->subspace_dict->code_only = 1;
+
+ som_section_data (section)->subspace_dict->subspace_start =
+ section->vma;
+ som_section_data (section)->subspace_dict->subspace_length =
+ bfd_section_size (abfd, section);
+ som_section_data (section)->subspace_dict->initialization_length =
+ bfd_section_size (abfd, section);
+ som_section_data (section)->subspace_dict->alignment =
+ 1 << section->alignment_power;
+
+ /* Set more attributes that were stuffed away in private data. */
+ som_section_data (section)->subspace_dict->sort_key =
+ som_section_data (section)->copy_data->sort_key;
+ som_section_data (section)->subspace_dict->access_control_bits =
+ som_section_data (section)->copy_data->access_control_bits;
+ som_section_data (section)->subspace_dict->quadrant =
+ som_section_data (section)->copy_data->quadrant;
+ }
+ }
+ return true;
+}
+
+/* Return true if the given section is a SOM space, false otherwise. */
+
+static boolean
+som_is_space (section)
+ asection *section;
+{
+ /* If no copy data is available, then it's neither a space nor a
+ subspace. */
+ if (som_section_data (section)->copy_data == NULL)
+ return false;
+
+ /* If the containing space isn't the same as the given section,
+ then this isn't a space. */
+ if (som_section_data (section)->copy_data->container != section
+ && (som_section_data (section)->copy_data->container->output_section
+ != section))
+ return false;
+
+ /* OK. Must be a space. */
+ return true;
+}
+
+/* Return true if the given section is a SOM subspace, false otherwise. */
+
+static boolean
+som_is_subspace (section)
+ asection *section;
+{
+ /* If no copy data is available, then it's neither a space nor a
+ subspace. */
+ if (som_section_data (section)->copy_data == NULL)
+ return false;
+
+ /* If the containing space is the same as the given section,
+ then this isn't a subspace. */
+ if (som_section_data (section)->copy_data->container == section
+ || (som_section_data (section)->copy_data->container->output_section
+ == section))
+ return false;
+
+ /* OK. Must be a subspace. */
+ return true;
+}
+
+/* Return true if the given space containins the given subspace. It
+ is safe to assume space really is a space, and subspace really
+ is a subspace. */
+
+static boolean
+som_is_container (space, subspace)
+ asection *space, *subspace;
+{
+ return (som_section_data (subspace)->copy_data->container == space
+ || (som_section_data (subspace)->copy_data->container->output_section
+ == space));
+}
+
+/* Count and return the number of spaces attached to the given BFD. */
+
+static unsigned long
+som_count_spaces (abfd)
+ bfd *abfd;
+{
+ int count = 0;
+ asection *section;
+
+ for (section = abfd->sections; section != NULL; section = section->next)
+ count += som_is_space (section);
+
+ return count;
+}
+
+/* Count the number of subspaces attached to the given BFD. */
+
+static unsigned long
+som_count_subspaces (abfd)
+ bfd *abfd;
+{
+ int count = 0;
+ asection *section;
+
+ for (section = abfd->sections; section != NULL; section = section->next)
+ count += som_is_subspace (section);
+
+ return count;
+}
+
+/* Return -1, 0, 1 indicating the relative ordering of sym1 and sym2.
+
+ We desire symbols to be ordered starting with the symbol with the
+ highest relocation count down to the symbol with the lowest relocation
+ count. Doing so compacts the relocation stream. */
+
+static int
+compare_syms (arg1, arg2)
+ const PTR arg1;
+ const PTR arg2;
+
+{
+ asymbol **sym1 = (asymbol **) arg1;
+ asymbol **sym2 = (asymbol **) arg2;
+ unsigned int count1, count2;
+
+ /* Get relocation count for each symbol. Note that the count
+ is stored in the udata pointer for section symbols! */
+ if ((*sym1)->flags & BSF_SECTION_SYM)
+ count1 = (*sym1)->udata.i;
+ else
+ count1 = som_symbol_data (*sym1)->reloc_count;
+
+ if ((*sym2)->flags & BSF_SECTION_SYM)
+ count2 = (*sym2)->udata.i;
+ else
+ count2 = som_symbol_data (*sym2)->reloc_count;
+
+ /* Return the appropriate value. */
+ if (count1 < count2)
+ return 1;
+ else if (count1 > count2)
+ return -1;
+ return 0;
+}
+
+/* Return -1, 0, 1 indicating the relative ordering of subspace1
+ and subspace. */
+
+static int
+compare_subspaces (arg1, arg2)
+ const PTR arg1;
+ const PTR arg2;
+
+{
+ asection **subspace1 = (asection **) arg1;
+ asection **subspace2 = (asection **) arg2;
+ unsigned int count1, count2;
+
+ if ((*subspace1)->target_index < (*subspace2)->target_index)
+ return -1;
+ else if ((*subspace2)->target_index < (*subspace1)->target_index)
+ return 1;
+ else
+ return 0;
+}
+
+/* Perform various work in preparation for emitting the fixup stream. */
+
+static void
+som_prep_for_fixups (abfd, syms, num_syms)
+ bfd *abfd;
+ asymbol **syms;
+ unsigned long num_syms;
+{
+ int i;
+ asection *section;
+ asymbol **sorted_syms;
+
+ /* Most SOM relocations involving a symbol have a length which is
+ dependent on the index of the symbol. So symbols which are
+ used often in relocations should have a small index. */
+
+ /* First initialize the counters for each symbol. */
+ for (i = 0; i < num_syms; i++)
+ {
+ /* Handle a section symbol; these have no pointers back to the
+ SOM symbol info. So we just use the udata field to hold the
+ relocation count. */
+ if (som_symbol_data (syms[i]) == NULL
+ || syms[i]->flags & BSF_SECTION_SYM)
+ {
+ syms[i]->flags |= BSF_SECTION_SYM;
+ syms[i]->udata.i = 0;
+ }
+ else
+ som_symbol_data (syms[i])->reloc_count = 0;
+ }
+
+ /* Now that the counters are initialized, make a weighted count
+ of how often a given symbol is used in a relocation. */
+ for (section = abfd->sections; section != NULL; section = section->next)
+ {
+ int i;
+
+ /* Does this section have any relocations? */
+ if (section->reloc_count <= 0)
+ continue;
+
+ /* Walk through each relocation for this section. */
+ for (i = 1; i < section->reloc_count; i++)
+ {
+ arelent *reloc = section->orelocation[i];
+ int scale;
+
+ /* A relocation against a symbol in the *ABS* section really
+ does not have a symbol. Likewise if the symbol isn't associated
+ with any section. */
+ if (reloc->sym_ptr_ptr == NULL
+ || bfd_is_abs_section ((*reloc->sym_ptr_ptr)->section))
+ continue;
+
+ /* Scaling to encourage symbols involved in R_DP_RELATIVE
+ and R_CODE_ONE_SYMBOL relocations to come first. These
+ two relocations have single byte versions if the symbol
+ index is very small. */
+ if (reloc->howto->type == R_DP_RELATIVE
+ || reloc->howto->type == R_CODE_ONE_SYMBOL)
+ scale = 2;
+ else
+ scale = 1;
+
+ /* Handle section symbols by storing the count in the udata
+ field. It will not be used and the count is very important
+ for these symbols. */
+ if ((*reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
+ {
+ (*reloc->sym_ptr_ptr)->udata.i =
+ (*reloc->sym_ptr_ptr)->udata.i + scale;
+ continue;
+ }
+
+ /* A normal symbol. Increment the count. */
+ som_symbol_data (*reloc->sym_ptr_ptr)->reloc_count += scale;
+ }
+ }
+
+ /* Sort a copy of the symbol table, rather than the canonical
+ output symbol table. */
+ sorted_syms = (asymbol **) bfd_zalloc (abfd, num_syms * sizeof (asymbol *));
+ memcpy (sorted_syms, syms, num_syms * sizeof (asymbol *));
+ qsort (sorted_syms, num_syms, sizeof (asymbol *), compare_syms);
+ obj_som_sorted_syms (abfd) = sorted_syms;
+
+ /* Compute the symbol indexes, they will be needed by the relocation
+ code. */
+ for (i = 0; i < num_syms; i++)
+ {
+ /* A section symbol. Again, there is no pointer to backend symbol
+ information, so we reuse the udata field again. */
+ if (sorted_syms[i]->flags & BSF_SECTION_SYM)
+ sorted_syms[i]->udata.i = i;
+ else
+ som_symbol_data (sorted_syms[i])->index = i;
+ }
+}
+
+static boolean
+som_write_fixups (abfd, current_offset, total_reloc_sizep)
+ bfd *abfd;
+ unsigned long current_offset;
+ unsigned int *total_reloc_sizep;
+{
+ unsigned int i, j;
+ /* Chunk of memory that we can use as buffer space, then throw
+ away. */
+ unsigned char tmp_space[SOM_TMP_BUFSIZE];
+ unsigned char *p;
+ unsigned int total_reloc_size = 0;
+ unsigned int subspace_reloc_size = 0;
+ unsigned int num_spaces = obj_som_file_hdr (abfd)->space_total;
+ asection *section = abfd->sections;
+
+ memset (tmp_space, 0, SOM_TMP_BUFSIZE);
+ p = tmp_space;
+
+ /* All the fixups for a particular subspace are emitted in a single
+ stream. All the subspaces for a particular space are emitted
+ as a single stream.
+
+ So, to get all the locations correct one must iterate through all the
+ spaces, for each space iterate through its subspaces and output a
+ fixups stream. */
+ for (i = 0; i < num_spaces; i++)
+ {
+ asection *subsection;
+
+ /* Find a space. */
+ while (!som_is_space (section))
+ section = section->next;
+
+ /* Now iterate through each of its subspaces. */
+ for (subsection = abfd->sections;
+ subsection != NULL;
+ subsection = subsection->next)
+ {
+ int reloc_offset, current_rounding_mode;
+
+ /* Find a subspace of this space. */
+ if (!som_is_subspace (subsection)
+ || !som_is_container (section, subsection))
+ continue;
+
+ /* If this subspace does not have real data, then we are
+ finised with it. */
+ if ((subsection->flags & SEC_HAS_CONTENTS) == 0)
+ {
+ som_section_data (subsection)->subspace_dict->fixup_request_index
+ = -1;
+ continue;
+ }
+
+ /* This subspace has some relocations. Put the relocation stream
+ index into the subspace record. */
+ som_section_data (subsection)->subspace_dict->fixup_request_index
+ = total_reloc_size;
+
+ /* To make life easier start over with a clean slate for
+ each subspace. Seek to the start of the relocation stream
+ for this subspace in preparation for writing out its fixup
+ stream. */
+ if (bfd_seek (abfd, current_offset + total_reloc_size, SEEK_SET) < 0)
+ return false;
+
+ /* Buffer space has already been allocated. Just perform some
+ initialization here. */
+ p = tmp_space;
+ subspace_reloc_size = 0;
+ reloc_offset = 0;
+ som_initialize_reloc_queue (reloc_queue);
+ current_rounding_mode = R_N_MODE;
+
+ /* Translate each BFD relocation into one or more SOM
+ relocations. */
+ for (j = 0; j < subsection->reloc_count; j++)
+ {
+ arelent *bfd_reloc = subsection->orelocation[j];
+ unsigned int skip;
+ int sym_num;
+
+ /* Get the symbol number. Remember it's stored in a
+ special place for section symbols. */
+ if ((*bfd_reloc->sym_ptr_ptr)->flags & BSF_SECTION_SYM)
+ sym_num = (*bfd_reloc->sym_ptr_ptr)->udata.i;
+ else
+ sym_num = som_symbol_data (*bfd_reloc->sym_ptr_ptr)->index;
+
+ /* If there is not enough room for the next couple relocations,
+ then dump the current buffer contents now. Also reinitialize
+ the relocation queue.
+
+ No single BFD relocation could ever translate into more
+ than 100 bytes of SOM relocations (20bytes is probably the
+ upper limit, but leave lots of space for growth). */
+ if (p - tmp_space + 100 > SOM_TMP_BUFSIZE)
+ {
+ if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
+ != p - tmp_space)
+ return false;
+
+ p = tmp_space;
+ som_initialize_reloc_queue (reloc_queue);
+ }
+
+ /* Emit R_NO_RELOCATION fixups to map any bytes which were
+ skipped. */
+ skip = bfd_reloc->address - reloc_offset;
+ p = som_reloc_skip (abfd, skip, p,
+ &subspace_reloc_size, reloc_queue);
+
+ /* Update reloc_offset for the next iteration.
+
+ Many relocations do not consume input bytes. They
+ are markers, or set state necessary to perform some
+ later relocation. */
+ switch (bfd_reloc->howto->type)
+ {
+ /* This only needs to handle relocations that may be
+ made by hppa_som_gen_reloc. */
+ case R_ENTRY:
+ case R_ALT_ENTRY:
+ case R_EXIT:
+ case R_N_MODE:
+ case R_S_MODE:
+ case R_D_MODE:
+ case R_R_MODE:
+ case R_FSEL:
+ case R_LSEL:
+ case R_RSEL:
+ case R_COMP1:
+ case R_COMP2:
+ case R_BEGIN_BRTAB:
+ case R_END_BRTAB:
+ case R_N0SEL:
+ case R_N1SEL:
+ reloc_offset = bfd_reloc->address;
+ break;
+
+ default:
+ reloc_offset = bfd_reloc->address + 4;
+ break;
+ }
+
+ /* Now the actual relocation we care about. */
+ switch (bfd_reloc->howto->type)
+ {
+ case R_PCREL_CALL:
+ case R_ABS_CALL:
+ p = som_reloc_call (abfd, p, &subspace_reloc_size,
+ bfd_reloc, sym_num, reloc_queue);
+ break;
+
+ case R_CODE_ONE_SYMBOL:
+ case R_DP_RELATIVE:
+ /* Account for any addend. */
+ if (bfd_reloc->addend)
+ p = som_reloc_addend (abfd, bfd_reloc->addend, p,
+ &subspace_reloc_size, reloc_queue);
+
+ if (sym_num < 0x20)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type + sym_num, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ }
+ else if (sym_num < 0x100)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type + 32, p);
+ bfd_put_8 (abfd, sym_num, p + 1);
+ p = try_prev_fixup (abfd, &subspace_reloc_size, p,
+ 2, reloc_queue);
+ }
+ else if (sym_num < 0x10000000)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type + 33, p);
+ bfd_put_8 (abfd, sym_num >> 16, p + 1);
+ bfd_put_16 (abfd, sym_num, p + 2);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 4, reloc_queue);
+ }
+ else
+ abort ();
+ break;
+
+ case R_DATA_ONE_SYMBOL:
+ case R_DATA_PLABEL:
+ case R_CODE_PLABEL:
+ case R_DLT_REL:
+ /* Account for any addend using R_DATA_OVERRIDE. */
+ if (bfd_reloc->howto->type != R_DATA_ONE_SYMBOL
+ && bfd_reloc->addend)
+ p = som_reloc_addend (abfd, bfd_reloc->addend, p,
+ &subspace_reloc_size, reloc_queue);
+
+ if (sym_num < 0x100)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ bfd_put_8 (abfd, sym_num, p + 1);
+ p = try_prev_fixup (abfd, &subspace_reloc_size, p,
+ 2, reloc_queue);
+ }
+ else if (sym_num < 0x10000000)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type + 1, p);
+ bfd_put_8 (abfd, sym_num >> 16, p + 1);
+ bfd_put_16 (abfd, sym_num, p + 2);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 4, reloc_queue);
+ }
+ else
+ abort ();
+ break;
+
+ case R_ENTRY:
+ {
+ int tmp;
+ arelent *tmp_reloc = NULL;
+ bfd_put_8 (abfd, R_ENTRY, p);
+
+ /* R_ENTRY relocations have 64 bits of associated
+ data. Unfortunately the addend field of a bfd
+ relocation is only 32 bits. So, we split up
+ the 64bit unwind information and store part in
+ the R_ENTRY relocation, and the rest in the R_EXIT
+ relocation. */
+ bfd_put_32 (abfd, bfd_reloc->addend, p + 1);
+
+ /* Find the next R_EXIT relocation. */
+ for (tmp = j; tmp < subsection->reloc_count; tmp++)
+ {
+ tmp_reloc = subsection->orelocation[tmp];
+ if (tmp_reloc->howto->type == R_EXIT)
+ break;
+ }
+
+ if (tmp == subsection->reloc_count)
+ abort ();
+
+ bfd_put_32 (abfd, tmp_reloc->addend, p + 5);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 9, reloc_queue);
+ break;
+ }
+
+ case R_N_MODE:
+ case R_S_MODE:
+ case R_D_MODE:
+ case R_R_MODE:
+ /* If this relocation requests the current rounding
+ mode, then it is redundant. */
+ if (bfd_reloc->howto->type != current_rounding_mode)
+ {
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ current_rounding_mode = bfd_reloc->howto->type;
+ }
+ break;
+
+ case R_EXIT:
+ case R_ALT_ENTRY:
+ case R_FSEL:
+ case R_LSEL:
+ case R_RSEL:
+ case R_BEGIN_BRTAB:
+ case R_END_BRTAB:
+ case R_N0SEL:
+ case R_N1SEL:
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ break;
+
+ case R_COMP1:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ bfd_put_8 (abfd, 0x44, p + 1);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 2, reloc_queue);
+ break;
+
+ case R_COMP2:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ bfd_put_8 (abfd, 0x80, p + 1);
+ bfd_put_8 (abfd, sym_num >> 16, p + 2);
+ bfd_put_16 (abfd, sym_num, p + 3);
+ p = try_prev_fixup (abfd, &subspace_reloc_size,
+ p, 5, reloc_queue);
+ break;
+
+ case R_CODE_EXPR:
+ /* The only time we generate R_COMP1, R_COMP2 and
+ R_CODE_EXPR relocs is for the difference of two
+ symbols. Hence we can cheat here. */
+ bfd_put_8 (abfd, bfd_reloc->howto->type, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ break;
+
+ /* Put a "R_RESERVED" relocation in the stream if
+ we hit something we do not understand. The linker
+ will complain loudly if this ever happens. */
+ default:
+ bfd_put_8 (abfd, 0xff, p);
+ subspace_reloc_size += 1;
+ p += 1;
+ break;
+ }
+ }
+
+ /* Last BFD relocation for a subspace has been processed.
+ Map the rest of the subspace with R_NO_RELOCATION fixups. */
+ p = som_reloc_skip (abfd, bfd_section_size (abfd, subsection)
+ - reloc_offset,
+ p, &subspace_reloc_size, reloc_queue);
+
+ /* Scribble out the relocations. */
+ if (bfd_write ((PTR) tmp_space, p - tmp_space, 1, abfd)
+ != p - tmp_space)
+ return false;
+ p = tmp_space;
+
+ total_reloc_size += subspace_reloc_size;
+ som_section_data (subsection)->subspace_dict->fixup_request_quantity
+ = subspace_reloc_size;
+ }
+ section = section->next;
+ }
+ *total_reloc_sizep = total_reloc_size;
+ return true;
+}
+
+/* Write out the space/subspace string table. */
+
+static boolean
+som_write_space_strings (abfd, current_offset, string_sizep)
+ bfd *abfd;
+ unsigned long current_offset;
+ unsigned int *string_sizep;
+{
+ /* Chunk of memory that we can use as buffer space, then throw
+ away. */
+ unsigned char tmp_space[SOM_TMP_BUFSIZE];
+ unsigned char *p;
+ unsigned int strings_size = 0;
+ asection *section;
+
+ memset (tmp_space, 0, SOM_TMP_BUFSIZE);
+ p = tmp_space;
+
+ /* Seek to the start of the space strings in preparation for writing
+ them out. */
+ if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
+ return false;
+
+ /* Walk through all the spaces and subspaces (order is not important)
+ building up and writing string table entries for their names. */
+ for (section = abfd->sections; section != NULL; section = section->next)
+ {
+ int length;
+
+ /* Only work with space/subspaces; avoid any other sections
+ which might have been made (.text for example). */
+ if (!som_is_space (section) && !som_is_subspace (section))
+ continue;
+
+ /* Get the length of the space/subspace name. */
+ length = strlen (section->name);
+
+ /* If there is not enough room for the next entry, then dump the
+ current buffer contents now. Each entry will take 4 bytes to
+ hold the string length + the string itself + null terminator. */
+ if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
+ {
+ if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd)
+ != p - tmp_space)
+ return false;
+ /* Reset to beginning of the buffer space. */
+ p = tmp_space;
+ }
+
+ /* First element in a string table entry is the length of the
+ string. Alignment issues are already handled. */
+ bfd_put_32 (abfd, length, p);
+ p += 4;
+ strings_size += 4;
+
+ /* Record the index in the space/subspace records. */
+ if (som_is_space (section))
+ som_section_data (section)->space_dict->name.n_strx = strings_size;
+ else
+ som_section_data (section)->subspace_dict->name.n_strx = strings_size;
+
+ /* Next comes the string itself + a null terminator. */
+ strcpy (p, section->name);
+ p += length + 1;
+ strings_size += length + 1;
+
+ /* Always align up to the next word boundary. */
+ while (strings_size % 4)
+ {
+ bfd_put_8 (abfd, 0, p);
+ p++;
+ strings_size++;
+ }
+ }
+
+ /* Done with the space/subspace strings. Write out any information
+ contained in a partial block. */
+ if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd) != p - tmp_space)
+ return false;
+ *string_sizep = strings_size;
+ return true;
+}
+
+/* Write out the symbol string table. */
+
+static boolean
+som_write_symbol_strings (abfd, current_offset, syms, num_syms, string_sizep)
+ bfd *abfd;
+ unsigned long current_offset;
+ asymbol **syms;
+ unsigned int num_syms;
+ unsigned int *string_sizep;
+{
+ unsigned int i;
+
+ /* Chunk of memory that we can use as buffer space, then throw
+ away. */
+ unsigned char tmp_space[SOM_TMP_BUFSIZE];
+ unsigned char *p;
+ unsigned int strings_size = 0;
+
+ memset (tmp_space, 0, SOM_TMP_BUFSIZE);
+ p = tmp_space;
+
+ /* Seek to the start of the space strings in preparation for writing
+ them out. */
+ if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
+ return false;
+
+ for (i = 0; i < num_syms; i++)
+ {
+ int length = strlen (syms[i]->name);
+
+ /* If there is not enough room for the next entry, then dump the
+ current buffer contents now. */
+ if (p - tmp_space + 5 + length > SOM_TMP_BUFSIZE)
+ {
+ if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd)
+ != p - tmp_space)
+ return false;
+ /* Reset to beginning of the buffer space. */
+ p = tmp_space;
+ }
+
+ /* First element in a string table entry is the length of the
+ string. This must always be 4 byte aligned. This is also
+ an appropriate time to fill in the string index field in the
+ symbol table entry. */
+ bfd_put_32 (abfd, length, p);
+ strings_size += 4;
+ p += 4;
+
+ /* Next comes the string itself + a null terminator. */
+ strcpy (p, syms[i]->name);
+
+ som_symbol_data(syms[i])->stringtab_offset = strings_size;
+ p += length + 1;
+ strings_size += length + 1;
+
+ /* Always align up to the next word boundary. */
+ while (strings_size % 4)
+ {
+ bfd_put_8 (abfd, 0, p);
+ strings_size++;
+ p++;
+ }
+ }
+
+ /* Scribble out any partial block. */
+ if (bfd_write ((PTR) &tmp_space[0], p - tmp_space, 1, abfd) != p - tmp_space)
+ return false;
+
+ *string_sizep = strings_size;
+ return true;
+}
+
+/* Compute variable information to be placed in the SOM headers,
+ space/subspace dictionaries, relocation streams, etc. Begin
+ writing parts of the object file. */
+
+static boolean
+som_begin_writing (abfd)
+ bfd *abfd;
+{
+ unsigned long current_offset = 0;
+ int strings_size = 0;
+ unsigned int total_reloc_size = 0;
+ unsigned long num_spaces, num_subspaces, i;
+ asection *section;
+ unsigned int total_subspaces = 0;
+ struct som_exec_auxhdr *exec_header = NULL;
+
+ /* The file header will always be first in an object file,
+ everything else can be in random locations. To keep things
+ "simple" BFD will lay out the object file in the manner suggested
+ by the PRO ABI for PA-RISC Systems. */
+
+ /* Before any output can really begin offsets for all the major
+ portions of the object file must be computed. So, starting
+ with the initial file header compute (and sometimes write)
+ each portion of the object file. */
+
+ /* Make room for the file header, it's contents are not complete
+ yet, so it can not be written at this time. */
+ current_offset += sizeof (struct header);
+
+ /* Any auxiliary headers will follow the file header. Right now
+ we support only the copyright and version headers. */
+ obj_som_file_hdr (abfd)->aux_header_location = current_offset;
+ obj_som_file_hdr (abfd)->aux_header_size = 0;
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ {
+ /* Parts of the exec header will be filled in later, so
+ delay writing the header itself. Fill in the defaults,
+ and write it later. */
+ current_offset += sizeof (struct som_exec_auxhdr);
+ obj_som_file_hdr (abfd)->aux_header_size
+ += sizeof (struct som_exec_auxhdr);
+ exec_header = obj_som_exec_hdr (abfd);
+ exec_header->som_auxhdr.type = EXEC_AUX_ID;
+ exec_header->som_auxhdr.length = 40;
+ }
+ if (obj_som_version_hdr (abfd) != NULL)
+ {
+ unsigned int len;
+
+ if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
+ return false;
+
+ /* Write the aux_id structure and the string length. */
+ len = sizeof (struct aux_id) + sizeof (unsigned int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_version_hdr (abfd), len, 1, abfd) != len)
+ return false;
+
+ /* Write the version string. */
+ len = obj_som_version_hdr (abfd)->header_id.length - sizeof (int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_version_hdr (abfd)->user_string,
+ len, 1, abfd) != len)
+ return false;
+ }
+
+ if (obj_som_copyright_hdr (abfd) != NULL)
+ {
+ unsigned int len;
+
+ if (bfd_seek (abfd, current_offset, SEEK_SET) < 0)
+ return false;
+
+ /* Write the aux_id structure and the string length. */
+ len = sizeof (struct aux_id) + sizeof (unsigned int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_copyright_hdr (abfd), len, 1, abfd) != len)
+ return false;
+
+ /* Write the copyright string. */
+ len = obj_som_copyright_hdr (abfd)->header_id.length - sizeof (int);
+ obj_som_file_hdr (abfd)->aux_header_size += len;
+ current_offset += len;
+ if (bfd_write ((PTR) obj_som_copyright_hdr (abfd)->copyright,
+ len, 1, abfd) != len)
+ return false;
+ }
+
+ /* Next comes the initialization pointers; we have no initialization
+ pointers, so current offset does not change. */
+ obj_som_file_hdr (abfd)->init_array_location = current_offset;
+ obj_som_file_hdr (abfd)->init_array_total = 0;
+
+ /* Next are the space records. These are fixed length records.
+
+ Count the number of spaces to determine how much room is needed
+ in the object file for the space records.
+
+ The names of the spaces are stored in a separate string table,
+ and the index for each space into the string table is computed
+ below. Therefore, it is not possible to write the space headers
+ at this time. */
+ num_spaces = som_count_spaces (abfd);
+ obj_som_file_hdr (abfd)->space_location = current_offset;
+ obj_som_file_hdr (abfd)->space_total = num_spaces;
+ current_offset += num_spaces * sizeof (struct space_dictionary_record);
+
+ /* Next are the subspace records. These are fixed length records.
+
+ Count the number of subspaes to determine how much room is needed
+ in the object file for the subspace records.
+
+ A variety if fields in the subspace record are still unknown at
+ this time (index into string table, fixup stream location/size, etc). */
+ num_subspaces = som_count_subspaces (abfd);
+ obj_som_file_hdr (abfd)->subspace_location = current_offset;
+ obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
+ current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
+
+ /* Next is the string table for the space/subspace names. We will
+ build and write the string table on the fly. At the same time
+ we will fill in the space/subspace name index fields. */
+
+ /* The string table needs to be aligned on a word boundary. */
+ if (current_offset % 4)
+ current_offset += (4 - (current_offset % 4));
+
+ /* Mark the offset of the space/subspace string table in the
+ file header. */
+ obj_som_file_hdr (abfd)->space_strings_location = current_offset;
+
+ /* Scribble out the space strings. */
+ if (som_write_space_strings (abfd, current_offset, &strings_size) == false)
+ return false;
+
+ /* Record total string table size in the header and update the
+ current offset. */
+ obj_som_file_hdr (abfd)->space_strings_size = strings_size;
+ current_offset += strings_size;
+
+ /* Next is the compiler records. We do not use these. */
+ obj_som_file_hdr (abfd)->compiler_location = current_offset;
+ obj_som_file_hdr (abfd)->compiler_total = 0;
+
+ /* Now compute the file positions for the loadable subspaces, taking
+ care to make sure everything stays properly aligned. */
+
+ section = abfd->sections;
+ for (i = 0; i < num_spaces; i++)
+ {
+ asection *subsection;
+ int first_subspace;
+ unsigned int subspace_offset = 0;
+
+ /* Find a space. */
+ while (!som_is_space (section))
+ section = section->next;
+
+ first_subspace = 1;
+ /* Now look for all its subspaces. */
+ for (subsection = abfd->sections;
+ subsection != NULL;
+ subsection = subsection->next)
+ {
+
+ if (!som_is_subspace (subsection)
+ || !som_is_container (section, subsection)
+ || (subsection->flags & SEC_ALLOC) == 0)
+ continue;
+
+ /* If this is the first subspace in the space, and we are
+ building an executable, then take care to make sure all
+ the alignments are correct and update the exec header. */
+ if (first_subspace
+ && (abfd->flags & (EXEC_P | DYNAMIC)))
+ {
+ /* Demand paged executables have each space aligned to a
+ page boundary. Sharable executables (write-protected
+ text) have just the private (aka data & bss) space aligned
+ to a page boundary. Ugh. Not true for HPUX.
+
+ The HPUX kernel requires the text to always be page aligned
+ within the file regardless of the executable's type. */
+ if (abfd->flags & (D_PAGED | DYNAMIC)
+ || (subsection->flags & SEC_CODE)
+ || ((abfd->flags & WP_TEXT)
+ && (subsection->flags & SEC_DATA)))
+ current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
+
+ /* Update the exec header. */
+ if (subsection->flags & SEC_CODE && exec_header->exec_tfile == 0)
+ {
+ exec_header->exec_tmem = section->vma;
+ exec_header->exec_tfile = current_offset;
+ }
+ if (subsection->flags & SEC_DATA && exec_header->exec_dfile == 0)
+ {
+ exec_header->exec_dmem = section->vma;
+ exec_header->exec_dfile = current_offset;
+ }
+
+ /* Keep track of exactly where we are within a particular
+ space. This is necessary as the braindamaged HPUX
+ loader will create holes between subspaces *and*
+ subspace alignments are *NOT* preserved. What a crock. */
+ subspace_offset = subsection->vma;
+
+ /* Only do this for the first subspace within each space. */
+ first_subspace = 0;
+ }
+ else if (abfd->flags & (EXEC_P | DYNAMIC))
+ {
+ /* The braindamaged HPUX loader may have created a hole
+ between two subspaces. It is *not* sufficient to use
+ the alignment specifications within the subspaces to
+ account for these holes -- I've run into at least one
+ case where the loader left one code subspace unaligned
+ in a final executable.
+
+ To combat this we keep a current offset within each space,
+ and use the subspace vma fields to detect and preserve
+ holes. What a crock!
+
+ ps. This is not necessary for unloadable space/subspaces. */
+ current_offset += subsection->vma - subspace_offset;
+ if (subsection->flags & SEC_CODE)
+ exec_header->exec_tsize += subsection->vma - subspace_offset;
+ else
+ exec_header->exec_dsize += subsection->vma - subspace_offset;
+ subspace_offset += subsection->vma - subspace_offset;
+ }
+
+
+ subsection->target_index = total_subspaces++;
+ /* This is real data to be loaded from the file. */
+ if (subsection->flags & SEC_LOAD)
+ {
+ /* Update the size of the code & data. */
+ if (abfd->flags & (EXEC_P | DYNAMIC)
+ && subsection->flags & SEC_CODE)
+ exec_header->exec_tsize += subsection->_cooked_size;
+ else if (abfd->flags & (EXEC_P | DYNAMIC)
+ && subsection->flags & SEC_DATA)
+ exec_header->exec_dsize += subsection->_cooked_size;
+ som_section_data (subsection)->subspace_dict->file_loc_init_value
+ = current_offset;
+ subsection->filepos = current_offset;
+ current_offset += bfd_section_size (abfd, subsection);
+ subspace_offset += bfd_section_size (abfd, subsection);
+ }
+ /* Looks like uninitialized data. */
+ else
+ {
+ /* Update the size of the bss section. */
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ exec_header->exec_bsize += subsection->_cooked_size;
+
+ som_section_data (subsection)->subspace_dict->file_loc_init_value
+ = 0;
+ som_section_data (subsection)->subspace_dict->
+ initialization_length = 0;
+ }
+ }
+ /* Goto the next section. */
+ section = section->next;
+ }
+
+ /* Finally compute the file positions for unloadable subspaces.
+ If building an executable, start the unloadable stuff on its
+ own page. */
+
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
+
+ obj_som_file_hdr (abfd)->unloadable_sp_location = current_offset;
+ section = abfd->sections;
+ for (i = 0; i < num_spaces; i++)
+ {
+ asection *subsection;
+
+ /* Find a space. */
+ while (!som_is_space (section))
+ section = section->next;
+
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
+
+ /* Now look for all its subspaces. */
+ for (subsection = abfd->sections;
+ subsection != NULL;
+ subsection = subsection->next)
+ {
+
+ if (!som_is_subspace (subsection)
+ || !som_is_container (section, subsection)
+ || (subsection->flags & SEC_ALLOC) != 0)
+ continue;
+
+ subsection->target_index = total_subspaces++;
+ /* This is real data to be loaded from the file. */
+ if ((subsection->flags & SEC_LOAD) == 0)
+ {
+ som_section_data (subsection)->subspace_dict->file_loc_init_value
+ = current_offset;
+ subsection->filepos = current_offset;
+ current_offset += bfd_section_size (abfd, subsection);
+ }
+ /* Looks like uninitialized data. */
+ else
+ {
+ som_section_data (subsection)->subspace_dict->file_loc_init_value
+ = 0;
+ som_section_data (subsection)->subspace_dict->
+ initialization_length = bfd_section_size (abfd, subsection);
+ }
+ }
+ /* Goto the next section. */
+ section = section->next;
+ }
+
+ /* If building an executable, then make sure to seek to and write
+ one byte at the end of the file to make sure any necessary
+ zeros are filled in. Ugh. */
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ current_offset = SOM_ALIGN (current_offset, PA_PAGESIZE);
+ if (bfd_seek (abfd, current_offset - 1, SEEK_SET) < 0)
+ return false;
+ if (bfd_write ((PTR) "", 1, 1, abfd) != 1)
+ return false;
+
+ obj_som_file_hdr (abfd)->unloadable_sp_size
+ = current_offset - obj_som_file_hdr (abfd)->unloadable_sp_location;
+
+ /* Loader fixups are not supported in any way shape or form. */
+ obj_som_file_hdr (abfd)->loader_fixup_location = 0;
+ obj_som_file_hdr (abfd)->loader_fixup_total = 0;
+
+ /* Done. Store the total size of the SOM so far. */
+ obj_som_file_hdr (abfd)->som_length = current_offset;
+
+ return true;
+}
+
+/* Finally, scribble out the various headers to the disk. */
+
+static boolean
+som_finish_writing (abfd)
+ bfd *abfd;
+{
+ int num_spaces = som_count_spaces (abfd);
+ asymbol **syms = bfd_get_outsymbols (abfd);
+ int i, num_syms, strings_size;
+ int subspace_index = 0;
+ file_ptr location;
+ asection *section;
+ unsigned long current_offset;
+ unsigned int total_reloc_size;
+
+ /* Next is the symbol table. These are fixed length records.
+
+ Count the number of symbols to determine how much room is needed
+ in the object file for the symbol table.
+
+ The names of the symbols are stored in a separate string table,
+ and the index for each symbol name into the string table is computed
+ below. Therefore, it is not possible to write the symbol table
+ at this time.
+
+ These used to be output before the subspace contents, but they
+ were moved here to work around a stupid bug in the hpux linker
+ (fixed in hpux10). */
+ current_offset = obj_som_file_hdr (abfd)->som_length;
+
+ /* Make sure we're on a word boundary. */
+ if (current_offset % 4)
+ current_offset += (4 - (current_offset % 4));
+
+ num_syms = bfd_get_symcount (abfd);
+ obj_som_file_hdr (abfd)->symbol_location = current_offset;
+ obj_som_file_hdr (abfd)->symbol_total = num_syms;
+ current_offset += num_syms * sizeof (struct symbol_dictionary_record);
+
+ /* Next are the symbol strings.
+ Align them to a word boundary. */
+ if (current_offset % 4)
+ current_offset += (4 - (current_offset % 4));
+ obj_som_file_hdr (abfd)->symbol_strings_location = current_offset;
+
+ /* Scribble out the symbol strings. */
+ if (som_write_symbol_strings (abfd, current_offset, syms,
+ num_syms, &strings_size)
+ == false)
+ return false;
+
+ /* Record total string table size in header and update the
+ current offset. */
+ obj_som_file_hdr (abfd)->symbol_strings_size = strings_size;
+ current_offset += strings_size;
+
+ /* Do prep work before handling fixups. */
+ som_prep_for_fixups (abfd,
+ bfd_get_outsymbols (abfd),
+ bfd_get_symcount (abfd));
+
+ /* At the end of the file is the fixup stream which starts on a
+ word boundary. */
+ if (current_offset % 4)
+ current_offset += (4 - (current_offset % 4));
+ obj_som_file_hdr (abfd)->fixup_request_location = current_offset;
+
+ /* Write the fixups and update fields in subspace headers which
+ relate to the fixup stream. */
+ if (som_write_fixups (abfd, current_offset, &total_reloc_size) == false)
+ return false;
+
+ /* Record the total size of the fixup stream in the file header. */
+ obj_som_file_hdr (abfd)->fixup_request_total = total_reloc_size;
+
+ /* Done. Store the total size of the SOM. */
+ obj_som_file_hdr (abfd)->som_length = current_offset + total_reloc_size;
+
+ /* Now that the symbol table information is complete, build and
+ write the symbol table. */
+ if (som_build_and_write_symbol_table (abfd) == false)
+ return false;
+
+ /* Subspaces are written first so that we can set up information
+ about them in their containing spaces as the subspace is written. */
+
+ /* Seek to the start of the subspace dictionary records. */
+ location = obj_som_file_hdr (abfd)->subspace_location;
+ if (bfd_seek (abfd, location, SEEK_SET) < 0)
+ return false;
+
+ section = abfd->sections;
+ /* Now for each loadable space write out records for its subspaces. */
+ for (i = 0; i < num_spaces; i++)
+ {
+ asection *subsection;
+
+ /* Find a space. */
+ while (!som_is_space (section))
+ section = section->next;
+
+ /* Now look for all its subspaces. */
+ for (subsection = abfd->sections;
+ subsection != NULL;
+ subsection = subsection->next)
+ {
+
+ /* Skip any section which does not correspond to a space
+ or subspace. Or does not have SEC_ALLOC set (and therefore
+ has no real bits on the disk). */
+ if (!som_is_subspace (subsection)
+ || !som_is_container (section, subsection)
+ || (subsection->flags & SEC_ALLOC) == 0)
+ continue;
+
+ /* If this is the first subspace for this space, then save
+ the index of the subspace in its containing space. Also
+ set "is_loadable" in the containing space. */
+
+ if (som_section_data (section)->space_dict->subspace_quantity == 0)
+ {
+ som_section_data (section)->space_dict->is_loadable = 1;
+ som_section_data (section)->space_dict->subspace_index
+ = subspace_index;
+ }
+
+ /* Increment the number of subspaces seen and the number of
+ subspaces contained within the current space. */
+ subspace_index++;
+ som_section_data (section)->space_dict->subspace_quantity++;
+
+ /* Mark the index of the current space within the subspace's
+ dictionary record. */
+ som_section_data (subsection)->subspace_dict->space_index = i;
+
+ /* Dump the current subspace header. */
+ if (bfd_write ((PTR) som_section_data (subsection)->subspace_dict,
+ sizeof (struct subspace_dictionary_record), 1, abfd)
+ != sizeof (struct subspace_dictionary_record))
+ return false;
+ }
+ /* Goto the next section. */
+ section = section->next;
+ }
+
+ /* Now repeat the process for unloadable subspaces. */
+ section = abfd->sections;
+ /* Now for each space write out records for its subspaces. */
+ for (i = 0; i < num_spaces; i++)
+ {
+ asection *subsection;
+
+ /* Find a space. */
+ while (!som_is_space (section))
+ section = section->next;
+
+ /* Now look for all its subspaces. */
+ for (subsection = abfd->sections;
+ subsection != NULL;
+ subsection = subsection->next)
+ {
+
+ /* Skip any section which does not correspond to a space or
+ subspace, or which SEC_ALLOC set (and therefore handled
+ in the loadable spaces/subspaces code above). */
+
+ if (!som_is_subspace (subsection)
+ || !som_is_container (section, subsection)
+ || (subsection->flags & SEC_ALLOC) != 0)
+ continue;
+
+ /* If this is the first subspace for this space, then save
+ the index of the subspace in its containing space. Clear
+ "is_loadable". */
+
+ if (som_section_data (section)->space_dict->subspace_quantity == 0)
+ {
+ som_section_data (section)->space_dict->is_loadable = 0;
+ som_section_data (section)->space_dict->subspace_index
+ = subspace_index;
+ }
+
+ /* Increment the number of subspaces seen and the number of
+ subspaces contained within the current space. */
+ som_section_data (section)->space_dict->subspace_quantity++;
+ subspace_index++;
+
+ /* Mark the index of the current space within the subspace's
+ dictionary record. */
+ som_section_data (subsection)->subspace_dict->space_index = i;
+
+ /* Dump this subspace header. */
+ if (bfd_write ((PTR) som_section_data (subsection)->subspace_dict,
+ sizeof (struct subspace_dictionary_record), 1, abfd)
+ != sizeof (struct subspace_dictionary_record))
+ return false;
+ }
+ /* Goto the next section. */
+ section = section->next;
+ }
+
+ /* All the subspace dictiondary records are written, and all the
+ fields are set up in the space dictionary records.
+
+ Seek to the right location and start writing the space
+ dictionary records. */
+ location = obj_som_file_hdr (abfd)->space_location;
+ if (bfd_seek (abfd, location, SEEK_SET) < 0)
+ return false;
+
+ section = abfd->sections;
+ for (i = 0; i < num_spaces; i++)
+ {
+
+ /* Find a space. */
+ while (!som_is_space (section))
+ section = section->next;
+
+ /* Dump its header */
+ if (bfd_write ((PTR) som_section_data (section)->space_dict,
+ sizeof (struct space_dictionary_record), 1, abfd)
+ != sizeof (struct space_dictionary_record))
+ return false;
+
+ /* Goto the next section. */
+ section = section->next;
+ }
+
+ /* Setting of the system_id has to happen very late now that copying of
+ BFD private data happens *after* section contents are set. */
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ obj_som_file_hdr(abfd)->system_id = obj_som_exec_data (abfd)->system_id;
+ else if (bfd_get_mach (abfd) == pa11)
+ obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_1;
+ else
+ obj_som_file_hdr(abfd)->system_id = CPU_PA_RISC1_0;
+
+ /* Compute the checksum for the file header just before writing
+ the header to disk. */
+ obj_som_file_hdr (abfd)->checksum = som_compute_checksum (abfd);
+
+ /* Only thing left to do is write out the file header. It is always
+ at location zero. Seek there and write it. */
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) < 0)
+ return false;
+ if (bfd_write ((PTR) obj_som_file_hdr (abfd),
+ sizeof (struct header), 1, abfd)
+ != sizeof (struct header))
+ return false;
+
+ /* Now write the exec header. */
+ if (abfd->flags & (EXEC_P | DYNAMIC))
+ {
+ long tmp;
+ struct som_exec_auxhdr *exec_header;
+
+ exec_header = obj_som_exec_hdr (abfd);
+ exec_header->exec_entry = bfd_get_start_address (abfd);
+ exec_header->exec_flags = obj_som_exec_data (abfd)->exec_flags;
+
+ /* Oh joys. Ram some of the BSS data into the DATA section
+ to be compatable with how the hp linker makes objects
+ (saves memory space). */
+ tmp = exec_header->exec_dsize;
+ tmp = SOM_ALIGN (tmp, PA_PAGESIZE);
+ exec_header->exec_bsize -= (tmp - exec_header->exec_dsize);
+ if (exec_header->exec_bsize < 0)
+ exec_header->exec_bsize = 0;
+ exec_header->exec_dsize = tmp;
+
+ if (bfd_seek (abfd, obj_som_file_hdr (abfd)->aux_header_location,
+ SEEK_SET) < 0)
+ return false;
+
+ if (bfd_write ((PTR) exec_header, AUX_HDR_SIZE, 1, abfd)
+ != AUX_HDR_SIZE)
+ return false;
+ }
+ return true;
+}
+
+/* Compute and return the checksum for a SOM file header. */
+
+static unsigned long
+som_compute_checksum (abfd)
+ bfd *abfd;
+{
+ unsigned long checksum, count, i;
+ unsigned long *buffer = (unsigned long *) obj_som_file_hdr (abfd);
+
+ checksum = 0;
+ count = sizeof (struct header) / sizeof (unsigned long);
+ for (i = 0; i < count; i++)
+ checksum ^= *(buffer + i);
+
+ return checksum;
+}
+
+static void
+som_bfd_derive_misc_symbol_info (abfd, sym, info)
+ bfd *abfd;
+ asymbol *sym;
+ struct som_misc_symbol_info *info;
+{
+ /* Initialize. */
+ memset (info, 0, sizeof (struct som_misc_symbol_info));
+
+ /* The HP SOM linker requires detailed type information about
+ all symbols (including undefined symbols!). Unfortunately,
+ the type specified in an import/export statement does not
+ always match what the linker wants. Severe braindamage. */
+
+ /* Section symbols will not have a SOM symbol type assigned to
+ them yet. Assign all section symbols type ST_DATA. */
+ if (sym->flags & BSF_SECTION_SYM)
+ info->symbol_type = ST_DATA;
+ else
+ {
+ /* Common symbols must have scope SS_UNSAT and type
+ ST_STORAGE or the linker will choke. */
+ if (bfd_is_com_section (sym->section))
+ {
+ info->symbol_scope = SS_UNSAT;
+ info->symbol_type = ST_STORAGE;
+ }
+
+ /* It is possible to have a symbol without an associated
+ type. This happens if the user imported the symbol
+ without a type and the symbol was never defined
+ locally. If BSF_FUNCTION is set for this symbol, then
+ assign it type ST_CODE (the HP linker requires undefined
+ external functions to have type ST_CODE rather than ST_ENTRY). */
+ else if ((som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
+ || som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
+ && bfd_is_und_section (sym->section)
+ && sym->flags & BSF_FUNCTION)
+ info->symbol_type = ST_CODE;
+
+ /* Handle function symbols which were defined in this file.
+ They should have type ST_ENTRY. Also retrieve the argument
+ relocation bits from the SOM backend information. */
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ENTRY
+ || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE
+ && (sym->flags & BSF_FUNCTION))
+ || (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN
+ && (sym->flags & BSF_FUNCTION)))
+ {
+ info->symbol_type = ST_ENTRY;
+ info->arg_reloc = som_symbol_data (sym)->tc_data.hppa_arg_reloc;
+ }
+
+ /* If the type is unknown at this point, it should be ST_DATA or
+ ST_CODE (function/ST_ENTRY symbols were handled as special
+ cases above). */
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
+ {
+ if (sym->section->flags & SEC_CODE)
+ info->symbol_type = ST_CODE;
+ else
+ info->symbol_type = ST_DATA;
+ }
+
+ /* From now on it's a very simple mapping. */
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
+ info->symbol_type = ST_ABSOLUTE;
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_CODE)
+ info->symbol_type = ST_CODE;
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_DATA)
+ info->symbol_type = ST_DATA;
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_MILLICODE)
+ info->symbol_type = ST_MILLICODE;
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PLABEL)
+ info->symbol_type = ST_PLABEL;
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_PRI_PROG)
+ info->symbol_type = ST_PRI_PROG;
+ else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_SEC_PROG)
+ info->symbol_type = ST_SEC_PROG;
+ }
+
+ /* Now handle the symbol's scope. Exported data which is not
+ in the common section has scope SS_UNIVERSAL. Note scope
+ of common symbols was handled earlier! */
+ if (bfd_is_und_section (sym->section))
+ info->symbol_scope = SS_UNSAT;
+ else if (sym->flags & BSF_EXPORT && ! bfd_is_com_section (sym->section))
+ info->symbol_scope = SS_UNIVERSAL;
+ /* Anything else which is not in the common section has scope
+ SS_LOCAL. */
+ else if (! bfd_is_com_section (sym->section))
+ info->symbol_scope = SS_LOCAL;
+
+ /* Now set the symbol_info field. It has no real meaning
+ for undefined or common symbols, but the HP linker will
+ choke if it's not set to some "reasonable" value. We
+ use zero as a reasonable value. */
+ if (bfd_is_com_section (sym->section)
+ || bfd_is_und_section (sym->section)
+ || bfd_is_abs_section (sym->section))
+ info->symbol_info = 0;
+ /* For all other symbols, the symbol_info field contains the
+ subspace index of the space this symbol is contained in. */
+ else
+ info->symbol_info = sym->section->target_index;
+
+ /* Set the symbol's value. */
+ info->symbol_value = sym->value + sym->section->vma;
+}
+
+/* Build and write, in one big chunk, the entire symbol table for
+ this BFD. */
+
+static boolean
+som_build_and_write_symbol_table (abfd)
+ bfd *abfd;
+{
+ unsigned int num_syms = bfd_get_symcount (abfd);
+ file_ptr symtab_location = obj_som_file_hdr (abfd)->symbol_location;
+ asymbol **bfd_syms = obj_som_sorted_syms (abfd);
+ struct symbol_dictionary_record *som_symtab = NULL;
+ int i, symtab_size;
+
+ /* Compute total symbol table size and allocate a chunk of memory
+ to hold the symbol table as we build it. */
+ symtab_size = num_syms * sizeof (struct symbol_dictionary_record);
+ som_symtab = (struct symbol_dictionary_record *) bfd_malloc (symtab_size);
+ if (som_symtab == NULL && symtab_size != 0)
+ goto error_return;
+ memset (som_symtab, 0, symtab_size);
+
+ /* Walk over each symbol. */
+ for (i = 0; i < num_syms; i++)
+ {
+ struct som_misc_symbol_info info;
+
+ /* This is really an index into the symbol strings table.
+ By the time we get here, the index has already been
+ computed and stored into the name field in the BFD symbol. */
+ som_symtab[i].name.n_strx = som_symbol_data(bfd_syms[i])->stringtab_offset;
+
+ /* Derive SOM information from the BFD symbol. */
+ som_bfd_derive_misc_symbol_info (abfd, bfd_syms[i], &info);
+
+ /* Now use it. */
+ som_symtab[i].symbol_type = info.symbol_type;
+ som_symtab[i].symbol_scope = info.symbol_scope;
+ som_symtab[i].arg_reloc = info.arg_reloc;
+ som_symtab[i].symbol_info = info.symbol_info;
+ som_symtab[i].symbol_value = info.symbol_value;
+ }
+
+ /* Everything is ready, seek to the right location and
+ scribble out the symbol table. */
+ if (bfd_seek (abfd, symtab_location, SEEK_SET) != 0)
+ return false;
+
+ if (bfd_write ((PTR) som_symtab, symtab_size, 1, abfd) != symtab_size)
+ goto error_return;
+
+ if (som_symtab != NULL)
+ free (som_symtab);
+ return true;
+ error_return:
+ if (som_symtab != NULL)
+ free (som_symtab);
+ return false;
+}
+
+/* Write an object in SOM format. */
+
+static boolean
+som_write_object_contents (abfd)
+ bfd *abfd;
+{
+ if (abfd->output_has_begun == false)
+ {
+ /* Set up fixed parts of the file, space, and subspace headers.
+ Notify the world that output has begun. */
+ som_prep_headers (abfd);
+ abfd->output_has_begun = true;
+ /* Start writing the object file. This include all the string
+ tables, fixup streams, and other portions of the object file. */
+ som_begin_writing (abfd);
+ }
+
+ return (som_finish_writing (abfd));
+}
+
+
+/* Read and save the string table associated with the given BFD. */
+
+static boolean
+som_slurp_string_table (abfd)
+ bfd *abfd;
+{
+ char *stringtab;
+
+ /* Use the saved version if its available. */
+ if (obj_som_stringtab (abfd) != NULL)
+ return true;
+
+ /* I don't think this can currently happen, and I'm not sure it should
+ really be an error, but it's better than getting unpredictable results
+ from the host's malloc when passed a size of zero. */
+ if (obj_som_stringtab_size (abfd) == 0)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ return false;
+ }
+
+ /* Allocate and read in the string table. */
+ stringtab = bfd_malloc (obj_som_stringtab_size (abfd));
+ if (stringtab == NULL)
+ return false;
+ memset (stringtab, 0, obj_som_stringtab_size (abfd));
+
+ if (bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET) < 0)
+ return false;
+
+ if (bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd)
+ != obj_som_stringtab_size (abfd))
+ return false;
+
+ /* Save our results and return success. */
+ obj_som_stringtab (abfd) = stringtab;
+ return true;
+}
+
+/* Return the amount of data (in bytes) required to hold the symbol
+ table for this object. */
+
+static long
+som_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ if (!som_slurp_symbol_table (abfd))
+ return -1;
+
+ return (bfd_get_symcount (abfd) + 1) * (sizeof (asymbol *));
+}
+
+/* Convert from a SOM subspace index to a BFD section. */
+
+static asection *
+bfd_section_from_som_symbol (abfd, symbol)
+ bfd *abfd;
+ struct symbol_dictionary_record *symbol;
+{
+ asection *section;
+
+ /* The meaning of the symbol_info field changes for functions
+ within executables. So only use the quick symbol_info mapping for
+ incomplete objects and non-function symbols in executables. */
+ if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0
+ || (symbol->symbol_type != ST_ENTRY
+ && symbol->symbol_type != ST_PRI_PROG
+ && symbol->symbol_type != ST_SEC_PROG
+ && symbol->symbol_type != ST_MILLICODE))
+ {
+ unsigned int index = symbol->symbol_info;
+ for (section = abfd->sections; section != NULL; section = section->next)
+ if (section->target_index == index && som_is_subspace (section))
+ return section;
+
+ /* Could be a symbol from an external library (such as an OMOS
+ shared library). Don't abort. */
+ return bfd_abs_section_ptr;
+
+ }
+ else
+ {
+ unsigned int value = symbol->symbol_value;
+
+ /* For executables we will have to use the symbol's address and
+ find out what section would contain that address. Yuk. */
+ for (section = abfd->sections; section; section = section->next)
+ {
+ if (value >= section->vma
+ && value <= section->vma + section->_cooked_size
+ && som_is_subspace (section))
+ return section;
+ }
+
+ /* Could be a symbol from an external library (such as an OMOS
+ shared library). Don't abort. */
+ return bfd_abs_section_ptr;
+
+ }
+}
+
+/* Read and save the symbol table associated with the given BFD. */
+
+static unsigned int
+som_slurp_symbol_table (abfd)
+ bfd *abfd;
+{
+ int symbol_count = bfd_get_symcount (abfd);
+ int symsize = sizeof (struct symbol_dictionary_record);
+ char *stringtab;
+ struct symbol_dictionary_record *buf = NULL, *bufp, *endbufp;
+ som_symbol_type *sym, *symbase;
+
+ /* Return saved value if it exists. */
+ if (obj_som_symtab (abfd) != NULL)
+ goto successful_return;
+
+ /* Special case. This is *not* an error. */
+ if (symbol_count == 0)
+ goto successful_return;
+
+ if (!som_slurp_string_table (abfd))
+ goto error_return;
+
+ stringtab = obj_som_stringtab (abfd);
+
+ symbase = ((som_symbol_type *)
+ bfd_malloc (symbol_count * sizeof (som_symbol_type)));
+ if (symbase == NULL)
+ goto error_return;
+ memset (symbase, 0, symbol_count * sizeof (som_symbol_type));
+
+ /* Read in the external SOM representation. */
+ buf = bfd_malloc (symbol_count * symsize);
+ if (buf == NULL && symbol_count * symsize != 0)
+ goto error_return;
+ if (bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET) < 0)
+ goto error_return;
+ if (bfd_read (buf, symbol_count * symsize, 1, abfd)
+ != symbol_count * symsize)
+ goto error_return;
+
+ /* Iterate over all the symbols and internalize them. */
+ endbufp = buf + symbol_count;
+ for (bufp = buf, sym = symbase; bufp < endbufp; ++bufp)
+ {
+
+ /* I don't think we care about these. */
+ if (bufp->symbol_type == ST_SYM_EXT
+ || bufp->symbol_type == ST_ARG_EXT)
+ continue;
+
+ /* Set some private data we care about. */
+ if (bufp->symbol_type == ST_NULL)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
+ else if (bufp->symbol_type == ST_ABSOLUTE)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_ABSOLUTE;
+ else if (bufp->symbol_type == ST_DATA)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_DATA;
+ else if (bufp->symbol_type == ST_CODE)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_CODE;
+ else if (bufp->symbol_type == ST_PRI_PROG)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_PRI_PROG;
+ else if (bufp->symbol_type == ST_SEC_PROG)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_SEC_PROG;
+ else if (bufp->symbol_type == ST_ENTRY)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_ENTRY;
+ else if (bufp->symbol_type == ST_MILLICODE)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_MILLICODE;
+ else if (bufp->symbol_type == ST_PLABEL)
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_PLABEL;
+ else
+ som_symbol_data (sym)->som_type = SYMBOL_TYPE_UNKNOWN;
+ som_symbol_data (sym)->tc_data.hppa_arg_reloc = bufp->arg_reloc;
+
+ /* Some reasonable defaults. */
+ sym->symbol.the_bfd = abfd;
+ sym->symbol.name = bufp->name.n_strx + stringtab;
+ sym->symbol.value = bufp->symbol_value;
+ sym->symbol.section = 0;
+ sym->symbol.flags = 0;
+
+ switch (bufp->symbol_type)
+ {
+ case ST_ENTRY:
+ case ST_MILLICODE:
+ sym->symbol.flags |= BSF_FUNCTION;
+ sym->symbol.value &= ~0x3;
+ break;
+
+ case ST_STUB:
+ case ST_CODE:
+ case ST_PRI_PROG:
+ case ST_SEC_PROG:
+ sym->symbol.value &= ~0x3;
+ /* If the symbol's scope is ST_UNSAT, then these are
+ undefined function symbols. */
+ if (bufp->symbol_scope == SS_UNSAT)
+ sym->symbol.flags |= BSF_FUNCTION;
+
+
+ default:
+ break;
+ }
+
+ /* Handle scoping and section information. */
+ switch (bufp->symbol_scope)
+ {
+ /* symbol_info field is undefined for SS_EXTERNAL and SS_UNSAT symbols,
+ so the section associated with this symbol can't be known. */
+ case SS_EXTERNAL:
+ if (bufp->symbol_type != ST_STORAGE)
+ sym->symbol.section = bfd_und_section_ptr;
+ else
+ sym->symbol.section = bfd_com_section_ptr;
+ sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
+ break;
+
+ case SS_UNSAT:
+ if (bufp->symbol_type != ST_STORAGE)
+ sym->symbol.section = bfd_und_section_ptr;
+ else
+ sym->symbol.section = bfd_com_section_ptr;
+ break;
+
+ case SS_UNIVERSAL:
+ sym->symbol.flags |= (BSF_EXPORT | BSF_GLOBAL);
+ sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
+ sym->symbol.value -= sym->symbol.section->vma;
+ break;
+
+#if 0
+ /* SS_GLOBAL and SS_LOCAL are two names for the same thing.
+ Sound dumb? It is. */
+ case SS_GLOBAL:
+#endif
+ case SS_LOCAL:
+ sym->symbol.flags |= BSF_LOCAL;
+ sym->symbol.section = bfd_section_from_som_symbol (abfd, bufp);
+ sym->symbol.value -= sym->symbol.section->vma;
+ break;
+ }
+
+ /* Mark section symbols and symbols used by the debugger.
+ Note $START$ is a magic code symbol, NOT a section symbol. */
+ if (sym->symbol.name[0] == '$'
+ && sym->symbol.name[strlen (sym->symbol.name) - 1] == '$'
+ && !strcmp (sym->symbol.name, sym->symbol.section->name))
+ sym->symbol.flags |= BSF_SECTION_SYM;
+ else if (!strncmp (sym->symbol.name, "L$0\002", 4))
+ {
+ sym->symbol.flags |= BSF_SECTION_SYM;
+ sym->symbol.name = sym->symbol.section->name;
+ }
+ else if (!strncmp (sym->symbol.name, "L$0\001", 4))
+ sym->symbol.flags |= BSF_DEBUGGING;
+
+ /* Note increment at bottom of loop, since we skip some symbols
+ we can not include it as part of the for statement. */
+ sym++;
+ }
+
+ /* Save our results and return success. */
+ obj_som_symtab (abfd) = symbase;
+ successful_return:
+ if (buf != NULL)
+ free (buf);
+ return (true);
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Canonicalize a SOM symbol table. Return the number of entries
+ in the symbol table. */
+
+static long
+som_get_symtab (abfd, location)
+ bfd *abfd;
+ asymbol **location;
+{
+ int i;
+ som_symbol_type *symbase;
+
+ if (!som_slurp_symbol_table (abfd))
+ return -1;
+
+ i = bfd_get_symcount (abfd);
+ symbase = obj_som_symtab (abfd);
+
+ for (; i > 0; i--, location++, symbase++)
+ *location = &symbase->symbol;
+
+ /* Final null pointer. */
+ *location = 0;
+ return (bfd_get_symcount (abfd));
+}
+
+/* Make a SOM symbol. There is nothing special to do here. */
+
+static asymbol *
+som_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ som_symbol_type *new =
+ (som_symbol_type *) bfd_zalloc (abfd, sizeof (som_symbol_type));
+ if (new == NULL)
+ return 0;
+ new->symbol.the_bfd = abfd;
+
+ return &new->symbol;
+}
+
+/* Print symbol information. */
+
+static void
+som_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;
+ case bfd_print_symbol_more:
+ fprintf (file, "som ");
+ fprintf_vma (file, symbol->value);
+ fprintf (file, " %lx", (long) symbol->flags);
+ break;
+ case bfd_print_symbol_all:
+ {
+ CONST char *section_name;
+ section_name = symbol->section ? symbol->section->name : "(*none*)";
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+ fprintf (file, " %s\t%s", section_name, symbol->name);
+ break;
+ }
+ }
+}
+
+static boolean
+som_bfd_is_local_label (abfd, sym)
+ bfd *abfd;
+ asymbol *sym;
+{
+ return (sym->name[0] == 'L' && sym->name[1] == '$');
+}
+
+/* Count or process variable-length SOM fixup records.
+
+ To avoid code duplication we use this code both to compute the number
+ of relocations requested by a stream, and to internalize the stream.
+
+ When computing the number of relocations requested by a stream the
+ variables rptr, section, and symbols have no meaning.
+
+ Return the number of relocations requested by the fixup stream. When
+ not just counting
+
+ This needs at least two or three more passes to get it cleaned up. */
+
+static unsigned int
+som_set_reloc_info (fixup, end, internal_relocs, section, symbols, just_count)
+ unsigned char *fixup;
+ unsigned int end;
+ arelent *internal_relocs;
+ asection *section;
+ asymbol **symbols;
+ boolean just_count;
+{
+ unsigned int op, varname, deallocate_contents = 0;
+ unsigned char *end_fixups = &fixup[end];
+ const struct fixup_format *fp;
+ char *cp;
+ unsigned char *save_fixup;
+ int variables[26], stack[20], c, v, count, prev_fixup, *sp, saved_unwind_bits;
+ const int *subop;
+ arelent *rptr= internal_relocs;
+ unsigned int offset = 0;
+
+#define var(c) variables[(c) - 'A']
+#define push(v) (*sp++ = (v))
+#define pop() (*--sp)
+#define emptystack() (sp == stack)
+
+ som_initialize_reloc_queue (reloc_queue);
+ memset (variables, 0, sizeof (variables));
+ memset (stack, 0, sizeof (stack));
+ count = 0;
+ prev_fixup = 0;
+ saved_unwind_bits = 0;
+ sp = stack;
+
+ while (fixup < end_fixups)
+ {
+
+ /* Save pointer to the start of this fixup. We'll use
+ it later to determine if it is necessary to put this fixup
+ on the queue. */
+ save_fixup = fixup;
+
+ /* Get the fixup code and its associated format. */
+ op = *fixup++;
+ fp = &som_fixup_formats[op];
+
+ /* Handle a request for a previous fixup. */
+ if (*fp->format == 'P')
+ {
+ /* Get pointer to the beginning of the prev fixup, move
+ the repeated fixup to the head of the queue. */
+ fixup = reloc_queue[fp->D].reloc;
+ som_reloc_queue_fix (reloc_queue, fp->D);
+ prev_fixup = 1;
+
+ /* Get the fixup code and its associated format. */
+ op = *fixup++;
+ fp = &som_fixup_formats[op];
+ }
+
+ /* If this fixup will be passed to BFD, set some reasonable defaults. */
+ if (! just_count
+ && som_hppa_howto_table[op].type != R_NO_RELOCATION
+ && som_hppa_howto_table[op].type != R_DATA_OVERRIDE)
+ {
+ rptr->address = offset;
+ rptr->howto = &som_hppa_howto_table[op];
+ rptr->addend = 0;
+ rptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
+ }
+
+ /* Set default input length to 0. Get the opcode class index
+ into D. */
+ var ('L') = 0;
+ var ('D') = fp->D;
+ var ('U') = saved_unwind_bits;
+
+ /* Get the opcode format. */
+ cp = fp->format;
+
+ /* Process the format string. Parsing happens in two phases,
+ parse RHS, then assign to LHS. Repeat until no more
+ characters in the format string. */
+ while (*cp)
+ {
+ /* The variable this pass is going to compute a value for. */
+ varname = *cp++;
+
+ /* Start processing RHS. Continue until a NULL or '=' is found. */
+ do
+ {
+ c = *cp++;
+
+ /* If this is a variable, push it on the stack. */
+ if (isupper (c))
+ push (var (c));
+
+ /* If this is a lower case letter, then it represents
+ additional data from the fixup stream to be pushed onto
+ the stack. */
+ else if (islower (c))
+ {
+ int bits = (c - 'a') * 8;
+ for (v = 0; c > 'a'; --c)
+ v = (v << 8) | *fixup++;
+ if (varname == 'V')
+ v = sign_extend (v, bits);
+ push (v);
+ }
+
+ /* A decimal constant. Push it on the stack. */
+ else if (isdigit (c))
+ {
+ v = c - '0';
+ while (isdigit (*cp))
+ v = (v * 10) + (*cp++ - '0');
+ push (v);
+ }
+ else
+
+ /* An operator. Pop two two values from the stack and
+ use them as operands to the given operation. Push
+ the result of the operation back on the stack. */
+ switch (c)
+ {
+ case '+':
+ v = pop ();
+ v += pop ();
+ push (v);
+ break;
+ case '*':
+ v = pop ();
+ v *= pop ();
+ push (v);
+ break;
+ case '<':
+ v = pop ();
+ v = pop () << v;
+ push (v);
+ break;
+ default:
+ abort ();
+ }
+ }
+ while (*cp && *cp != '=');
+
+ /* Move over the equal operator. */
+ cp++;
+
+ /* Pop the RHS off the stack. */
+ c = pop ();
+
+ /* Perform the assignment. */
+ var (varname) = c;
+
+ /* Handle side effects. and special 'O' stack cases. */
+ switch (varname)
+ {
+ /* Consume some bytes from the input space. */
+ case 'L':
+ offset += c;
+ break;
+ /* A symbol to use in the relocation. Make a note
+ of this if we are not just counting. */
+ case 'S':
+ if (! just_count)
+ rptr->sym_ptr_ptr = &symbols[c];
+ break;
+ /* Argument relocation bits for a function call. */
+ case 'R':
+ if (! just_count)
+ {
+ unsigned int tmp = var ('R');
+ rptr->addend = 0;
+
+ if ((som_hppa_howto_table[op].type == R_PCREL_CALL
+ && R_PCREL_CALL + 10 > op)
+ || (som_hppa_howto_table[op].type == R_ABS_CALL
+ && R_ABS_CALL + 10 > op))
+ {
+ /* Simple encoding. */
+ if (tmp > 4)
+ {
+ tmp -= 5;
+ rptr->addend |= 1;
+ }
+ if (tmp == 4)
+ rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2;
+ else if (tmp == 3)
+ rptr->addend |= 1 << 8 | 1 << 6 | 1 << 4;
+ else if (tmp == 2)
+ rptr->addend |= 1 << 8 | 1 << 6;
+ else if (tmp == 1)
+ rptr->addend |= 1 << 8;
+ }
+ else
+ {
+ unsigned int tmp1, tmp2;
+
+ /* First part is easy -- low order two bits are
+ directly copied, then shifted away. */
+ rptr->addend = tmp & 0x3;
+ tmp >>= 2;
+
+ /* Diving the result by 10 gives us the second
+ part. If it is 9, then the first two words
+ are a double precision paramater, else it is
+ 3 * the first arg bits + the 2nd arg bits. */
+ tmp1 = tmp / 10;
+ tmp -= tmp1 * 10;
+ if (tmp1 == 9)
+ rptr->addend += (0xe << 6);
+ else
+ {
+ /* Get the two pieces. */
+ tmp2 = tmp1 / 3;
+ tmp1 -= tmp2 * 3;
+ /* Put them in the addend. */
+ rptr->addend += (tmp2 << 8) + (tmp1 << 6);
+ }
+
+ /* What's left is the third part. It's unpacked
+ just like the second. */
+ if (tmp == 9)
+ rptr->addend += (0xe << 2);
+ else
+ {
+ tmp2 = tmp / 3;
+ tmp -= tmp2 * 3;
+ rptr->addend += (tmp2 << 4) + (tmp << 2);
+ }
+ }
+ rptr->addend = HPPA_R_ADDEND (rptr->addend, 0);
+ }
+ break;
+ /* Handle the linker expression stack. */
+ case 'O':
+ switch (op)
+ {
+ case R_COMP1:
+ subop = comp1_opcodes;
+ break;
+ case R_COMP2:
+ subop = comp2_opcodes;
+ break;
+ case R_COMP3:
+ subop = comp3_opcodes;
+ break;
+ default:
+ abort ();
+ }
+ while (*subop <= (unsigned char) c)
+ ++subop;
+ --subop;
+ break;
+ /* The lower 32unwind bits must be persistent. */
+ case 'U':
+ saved_unwind_bits = var ('U');
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /* If we used a previous fixup, clean up after it. */
+ if (prev_fixup)
+ {
+ fixup = save_fixup + 1;
+ prev_fixup = 0;
+ }
+ /* Queue it. */
+ else if (fixup > save_fixup + 1)
+ som_reloc_queue_insert (save_fixup, fixup - save_fixup, reloc_queue);
+
+ /* We do not pass R_DATA_OVERRIDE or R_NO_RELOCATION
+ fixups to BFD. */
+ if (som_hppa_howto_table[op].type != R_DATA_OVERRIDE
+ && som_hppa_howto_table[op].type != R_NO_RELOCATION)
+ {
+ /* Done with a single reloction. Loop back to the top. */
+ if (! just_count)
+ {
+ if (som_hppa_howto_table[op].type == R_ENTRY)
+ rptr->addend = var ('T');
+ else if (som_hppa_howto_table[op].type == R_EXIT)
+ rptr->addend = var ('U');
+ else if (som_hppa_howto_table[op].type == R_PCREL_CALL
+ || som_hppa_howto_table[op].type == R_ABS_CALL)
+ ;
+ else if (som_hppa_howto_table[op].type == R_DATA_ONE_SYMBOL)
+ {
+ unsigned addend = var ('V');
+
+ /* Try what was specified in R_DATA_OVERRIDE first
+ (if anything). Then the hard way using the
+ section contents. */
+ rptr->addend = var ('V');
+
+ if (rptr->addend == 0 && !section->contents)
+ {
+ /* Got to read the damn contents first. We don't
+ bother saving the contents (yet). Add it one
+ day if the need arises. */
+ section->contents = bfd_malloc (section->_raw_size);
+ if (section->contents == NULL)
+ return -1;
+
+ deallocate_contents = 1;
+ bfd_get_section_contents (section->owner,
+ section,
+ section->contents,
+ 0,
+ section->_raw_size);
+ }
+ else if (rptr->addend == 0)
+ rptr->addend = bfd_get_32 (section->owner,
+ (section->contents
+ + offset - var ('L')));
+
+ }
+ else
+ rptr->addend = var ('V');
+ rptr++;
+ }
+ count++;
+ /* Now that we've handled a "full" relocation, reset
+ some state. */
+ memset (variables, 0, sizeof (variables));
+ memset (stack, 0, sizeof (stack));
+ }
+ }
+ if (deallocate_contents)
+ free (section->contents);
+
+ return count;
+
+#undef var
+#undef push
+#undef pop
+#undef emptystack
+}
+
+/* Read in the relocs (aka fixups in SOM terms) for a section.
+
+ som_get_reloc_upper_bound calls this routine with JUST_COUNT
+ set to true to indicate it only needs a count of the number
+ of actual relocations. */
+
+static boolean
+som_slurp_reloc_table (abfd, section, symbols, just_count)
+ bfd *abfd;
+ asection *section;
+ asymbol **symbols;
+ boolean just_count;
+{
+ char *external_relocs;
+ unsigned int fixup_stream_size;
+ arelent *internal_relocs;
+ unsigned int num_relocs;
+
+ fixup_stream_size = som_section_data (section)->reloc_size;
+ /* If there were no relocations, then there is nothing to do. */
+ if (section->reloc_count == 0)
+ return true;
+
+ /* If reloc_count is -1, then the relocation stream has not been
+ parsed. We must do so now to know how many relocations exist. */
+ if (section->reloc_count == -1)
+ {
+ external_relocs = (char *) bfd_malloc (fixup_stream_size);
+ if (external_relocs == (char *) NULL)
+ return false;
+ /* Read in the external forms. */
+ if (bfd_seek (abfd,
+ obj_som_reloc_filepos (abfd) + section->rel_filepos,
+ SEEK_SET)
+ != 0)
+ return false;
+ if (bfd_read (external_relocs, 1, fixup_stream_size, abfd)
+ != fixup_stream_size)
+ return false;
+
+ /* Let callers know how many relocations found.
+ also save the relocation stream as we will
+ need it again. */
+ section->reloc_count = som_set_reloc_info (external_relocs,
+ fixup_stream_size,
+ NULL, NULL, NULL, true);
+
+ som_section_data (section)->reloc_stream = external_relocs;
+ }
+
+ /* If the caller only wanted a count, then return now. */
+ if (just_count)
+ return true;
+
+ num_relocs = section->reloc_count;
+ external_relocs = som_section_data (section)->reloc_stream;
+ /* Return saved information about the relocations if it is available. */
+ if (section->relocation != (arelent *) NULL)
+ return true;
+
+ internal_relocs = (arelent *)
+ bfd_zalloc (abfd, (num_relocs * sizeof (arelent)));
+ if (internal_relocs == (arelent *) NULL)
+ return false;
+
+ /* Process and internalize the relocations. */
+ som_set_reloc_info (external_relocs, fixup_stream_size,
+ internal_relocs, section, symbols, false);
+
+ /* We're done with the external relocations. Free them. */
+ free (external_relocs);
+
+ /* Save our results and return success. */
+ section->relocation = internal_relocs;
+ return (true);
+}
+
+/* Return the number of bytes required to store the relocation
+ information associated with the given section. */
+
+static long
+som_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ /* If section has relocations, then read in the relocation stream
+ and parse it to determine how many relocations exist. */
+ if (asect->flags & SEC_RELOC)
+ {
+ if (! som_slurp_reloc_table (abfd, asect, NULL, true))
+ return -1;
+ return (asect->reloc_count + 1) * sizeof (arelent *);
+ }
+ /* There are no relocations. */
+ return 0;
+}
+
+/* Convert relocations from SOM (external) form into BFD internal
+ form. Return the number of relocations. */
+
+static long
+som_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ arelent *tblptr;
+ int count;
+
+ if (som_slurp_reloc_table (abfd, section, symbols, false) == false)
+ return -1;
+
+ count = section->reloc_count;
+ tblptr = section->relocation;
+
+ while (count--)
+ *relptr++ = tblptr++;
+
+ *relptr = (arelent *) NULL;
+ return section->reloc_count;
+}
+
+extern const bfd_target som_vec;
+
+/* A hook to set up object file dependent section information. */
+
+static boolean
+som_new_section_hook (abfd, newsect)
+ bfd *abfd;
+ asection *newsect;
+{
+ newsect->used_by_bfd =
+ (PTR) bfd_zalloc (abfd, sizeof (struct som_section_data_struct));
+ if (!newsect->used_by_bfd)
+ return false;
+ newsect->alignment_power = 3;
+
+ /* We allow more than three sections internally */
+ return true;
+}
+
+/* Copy any private info we understand from the input symbol
+ to the output symbol. */
+
+static boolean
+som_bfd_copy_private_symbol_data (ibfd, isymbol, obfd, osymbol)
+ bfd *ibfd;
+ asymbol *isymbol;
+ bfd *obfd;
+ asymbol *osymbol;
+{
+ struct som_symbol *input_symbol = (struct som_symbol *) isymbol;
+ struct som_symbol *output_symbol = (struct som_symbol *) osymbol;
+
+ /* One day we may try to grok other private data. */
+ if (ibfd->xvec->flavour != bfd_target_som_flavour
+ || obfd->xvec->flavour != bfd_target_som_flavour)
+ return false;
+
+ /* The only private information we need to copy is the argument relocation
+ bits. */
+ output_symbol->tc_data.hppa_arg_reloc = input_symbol->tc_data.hppa_arg_reloc;
+
+ return true;
+}
+
+/* Copy any private info we understand from the input section
+ to the output section. */
+static boolean
+som_bfd_copy_private_section_data (ibfd, isection, obfd, osection)
+ bfd *ibfd;
+ asection *isection;
+ bfd *obfd;
+ asection *osection;
+{
+ /* One day we may try to grok other private data. */
+ if (ibfd->xvec->flavour != bfd_target_som_flavour
+ || obfd->xvec->flavour != bfd_target_som_flavour
+ || (!som_is_space (isection) && !som_is_subspace (isection)))
+ return true;
+
+ som_section_data (osection)->copy_data
+ = (struct som_copyable_section_data_struct *)
+ bfd_zalloc (obfd, sizeof (struct som_copyable_section_data_struct));
+ if (som_section_data (osection)->copy_data == NULL)
+ return false;
+
+ memcpy (som_section_data (osection)->copy_data,
+ som_section_data (isection)->copy_data,
+ sizeof (struct som_copyable_section_data_struct));
+
+ /* Reparent if necessary. */
+ if (som_section_data (osection)->copy_data->container)
+ som_section_data (osection)->copy_data->container =
+ som_section_data (osection)->copy_data->container->output_section;
+
+ return true;
+}
+
+/* Copy any private info we understand from the input bfd
+ to the output bfd. */
+
+static boolean
+som_bfd_copy_private_bfd_data (ibfd, obfd)
+ bfd *ibfd, *obfd;
+{
+ /* One day we may try to grok other private data. */
+ if (ibfd->xvec->flavour != bfd_target_som_flavour
+ || obfd->xvec->flavour != bfd_target_som_flavour)
+ return true;
+
+ /* Allocate some memory to hold the data we need. */
+ obj_som_exec_data (obfd) = (struct som_exec_data *)
+ bfd_zalloc (obfd, sizeof (struct som_exec_data));
+ if (obj_som_exec_data (obfd) == NULL)
+ return false;
+
+ /* Now copy the data. */
+ memcpy (obj_som_exec_data (obfd), obj_som_exec_data (ibfd),
+ sizeof (struct som_exec_data));
+
+ return true;
+}
+
+/* Set backend info for sections which can not be described
+ in the BFD data structures. */
+
+boolean
+bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
+ asection *section;
+ int defined;
+ int private;
+ unsigned int sort_key;
+ int spnum;
+{
+ /* Allocate memory to hold the magic information. */
+ if (som_section_data (section)->copy_data == NULL)
+ {
+ som_section_data (section)->copy_data
+ = (struct som_copyable_section_data_struct *)
+ bfd_zalloc (section->owner,
+ sizeof (struct som_copyable_section_data_struct));
+ if (som_section_data (section)->copy_data == NULL)
+ return false;
+ }
+ som_section_data (section)->copy_data->sort_key = sort_key;
+ som_section_data (section)->copy_data->is_defined = defined;
+ som_section_data (section)->copy_data->is_private = private;
+ som_section_data (section)->copy_data->container = section;
+ som_section_data (section)->copy_data->space_number = spnum;
+ return true;
+}
+
+/* Set backend info for subsections which can not be described
+ in the BFD data structures. */
+
+boolean
+bfd_som_set_subsection_attributes (section, container, access,
+ sort_key, quadrant)
+ asection *section;
+ asection *container;
+ int access;
+ unsigned int sort_key;
+ int quadrant;
+{
+ /* Allocate memory to hold the magic information. */
+ if (som_section_data (section)->copy_data == NULL)
+ {
+ som_section_data (section)->copy_data
+ = (struct som_copyable_section_data_struct *)
+ bfd_zalloc (section->owner,
+ sizeof (struct som_copyable_section_data_struct));
+ if (som_section_data (section)->copy_data == NULL)
+ return false;
+ }
+ som_section_data (section)->copy_data->sort_key = sort_key;
+ som_section_data (section)->copy_data->access_control_bits = access;
+ som_section_data (section)->copy_data->quadrant = quadrant;
+ som_section_data (section)->copy_data->container = container;
+ return true;
+}
+
+/* Set the full SOM symbol type. SOM needs far more symbol information
+ than any other object file format I'm aware of. It is mandatory
+ to be able to know if a symbol is an entry point, millicode, data,
+ code, absolute, storage request, or procedure label. If you get
+ the symbol type wrong your program will not link. */
+
+void
+bfd_som_set_symbol_type (symbol, type)
+ asymbol *symbol;
+ unsigned int type;
+{
+ som_symbol_data (symbol)->som_type = type;
+}
+
+/* Attach an auxiliary header to the BFD backend so that it may be
+ written into the object file. */
+boolean
+bfd_som_attach_aux_hdr (abfd, type, string)
+ bfd *abfd;
+ int type;
+ char *string;
+{
+ if (type == VERSION_AUX_ID)
+ {
+ int len = strlen (string);
+ int pad = 0;
+
+ if (len % 4)
+ pad = (4 - (len % 4));
+ obj_som_version_hdr (abfd) = (struct user_string_aux_hdr *)
+ bfd_zalloc (abfd, sizeof (struct aux_id)
+ + sizeof (unsigned int) + len + pad);
+ if (!obj_som_version_hdr (abfd))
+ return false;
+ obj_som_version_hdr (abfd)->header_id.type = VERSION_AUX_ID;
+ obj_som_version_hdr (abfd)->header_id.length = len + pad;
+ obj_som_version_hdr (abfd)->header_id.length += sizeof (int);
+ obj_som_version_hdr (abfd)->string_length = len;
+ strncpy (obj_som_version_hdr (abfd)->user_string, string, len);
+ }
+ else if (type == COPYRIGHT_AUX_ID)
+ {
+ int len = strlen (string);
+ int pad = 0;
+
+ if (len % 4)
+ pad = (4 - (len % 4));
+ obj_som_copyright_hdr (abfd) = (struct copyright_aux_hdr *)
+ bfd_zalloc (abfd, sizeof (struct aux_id)
+ + sizeof (unsigned int) + len + pad);
+ if (!obj_som_copyright_hdr (abfd))
+ return false;
+ obj_som_copyright_hdr (abfd)->header_id.type = COPYRIGHT_AUX_ID;
+ obj_som_copyright_hdr (abfd)->header_id.length = len + pad;
+ obj_som_copyright_hdr (abfd)->header_id.length += sizeof (int);
+ obj_som_copyright_hdr (abfd)->string_length = len;
+ strcpy (obj_som_copyright_hdr (abfd)->copyright, string);
+ }
+ return true;
+}
+
+static boolean
+som_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 || ((section->flags & SEC_HAS_CONTENTS) == 0))
+ return true;
+ if ((bfd_size_type)(offset+count) > section->_raw_size
+ || bfd_seek (abfd, (file_ptr)(section->filepos + offset), SEEK_SET) == -1
+ || bfd_read (location, (bfd_size_type)1, count, abfd) != count)
+ return (false); /* on error */
+ return (true);
+}
+
+static boolean
+som_set_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ sec_ptr section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (abfd->output_has_begun == false)
+ {
+ /* Set up fixed parts of the file, space, and subspace headers.
+ Notify the world that output has begun. */
+ som_prep_headers (abfd);
+ abfd->output_has_begun = true;
+ /* Start writing the object file. This include all the string
+ tables, fixup streams, and other portions of the object file. */
+ som_begin_writing (abfd);
+ }
+
+ /* Only write subspaces which have "real" contents (eg. the contents
+ are not generated at run time by the OS). */
+ if (!som_is_subspace (section)
+ || ((section->flags & SEC_HAS_CONTENTS) == 0))
+ return true;
+
+ /* Seek to the proper offset within the object file and write the
+ data. */
+ offset += som_section_data (section)->subspace_dict->file_loc_init_value;
+ if (bfd_seek (abfd, offset, SEEK_SET) == -1)
+ return false;
+
+ if (bfd_write ((PTR) location, 1, count, abfd) != count)
+ return false;
+ return true;
+}
+
+static boolean
+som_set_arch_mach (abfd, arch, machine)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ /* Allow any architecture to be supported by the SOM backend */
+ return bfd_default_set_arch_mach (abfd, arch, machine);
+}
+
+static boolean
+som_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;
+{
+ return (false);
+}
+
+static int
+som_sizeof_headers (abfd, reloc)
+ bfd *abfd;
+ boolean reloc;
+{
+ (*_bfd_error_handler) ("som_sizeof_headers unimplemented");
+ fflush (stderr);
+ abort ();
+ return (0);
+}
+
+/* Return the single-character symbol type corresponding to
+ SOM section S, or '?' for an unknown SOM section. */
+
+static char
+som_section_type (s)
+ const char *s;
+{
+ const struct section_to_type *t;
+
+ for (t = &stt[0]; t->section; t++)
+ if (!strcmp (s, t->section))
+ return t->type;
+ return '?';
+}
+
+static int
+som_decode_symclass (symbol)
+ asymbol *symbol;
+{
+ char c;
+
+ if (bfd_is_com_section (symbol->section))
+ return 'C';
+ if (bfd_is_und_section (symbol->section))
+ return 'U';
+ if (bfd_is_ind_section (symbol->section))
+ return 'I';
+ if (!(symbol->flags & (BSF_GLOBAL|BSF_LOCAL)))
+ return '?';
+
+ if (bfd_is_abs_section (symbol->section)
+ || (som_symbol_data (symbol) != NULL
+ && som_symbol_data (symbol)->som_type == SYMBOL_TYPE_ABSOLUTE))
+ c = 'a';
+ else if (symbol->section)
+ c = som_section_type (symbol->section->name);
+ else
+ return '?';
+ if (symbol->flags & BSF_GLOBAL)
+ c = toupper (c);
+ return c;
+}
+
+/* Return information about SOM symbol SYMBOL in RET. */
+
+static void
+som_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ ret->type = som_decode_symclass (symbol);
+ if (ret->type != 'U')
+ ret->value = symbol->value+symbol->section->vma;
+ else
+ ret->value = 0;
+ ret->name = symbol->name;
+}
+
+/* Count the number of symbols in the archive symbol table. Necessary
+ so that we can allocate space for all the carsyms at once. */
+
+static boolean
+som_bfd_count_ar_symbols (abfd, lst_header, count)
+ bfd *abfd;
+ struct lst_header *lst_header;
+ symindex *count;
+{
+ unsigned int i;
+ unsigned int *hash_table = NULL;
+ file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+ hash_table =
+ (unsigned int *) bfd_malloc (lst_header->hash_size
+ * sizeof (unsigned int));
+ if (hash_table == NULL && lst_header->hash_size != 0)
+ goto error_return;
+
+ /* Don't forget to initialize the counter! */
+ *count = 0;
+
+ /* Read in the hash table. The has table is an array of 32bit file offsets
+ which point to the hash chains. */
+ if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
+ != lst_header->hash_size * 4)
+ goto error_return;
+
+ /* Walk each chain counting the number of symbols found on that particular
+ chain. */
+ for (i = 0; i < lst_header->hash_size; i++)
+ {
+ struct lst_symbol_record lst_symbol;
+
+ /* An empty chain has zero as it's file offset. */
+ if (hash_table[i] == 0)
+ continue;
+
+ /* Seek to the first symbol in this hash chain. */
+ if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
+ goto error_return;
+
+ /* Read in this symbol and update the counter. */
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ goto error_return;
+
+ (*count)++;
+
+ /* Now iterate through the rest of the symbols on this chain. */
+ while (lst_symbol.next_entry)
+ {
+
+ /* Seek to the next symbol. */
+ if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET)
+ < 0)
+ goto error_return;
+
+ /* Read the symbol in and update the counter. */
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ goto error_return;
+
+ (*count)++;
+ }
+ }
+ if (hash_table != NULL)
+ free (hash_table);
+ return true;
+
+ error_return:
+ if (hash_table != NULL)
+ free (hash_table);
+ return false;
+}
+
+/* Fill in the canonical archive symbols (SYMS) from the archive described
+ by ABFD and LST_HEADER. */
+
+static boolean
+som_bfd_fill_in_ar_symbols (abfd, lst_header, syms)
+ bfd *abfd;
+ struct lst_header *lst_header;
+ carsym **syms;
+{
+ unsigned int i, len;
+ carsym *set = syms[0];
+ unsigned int *hash_table = NULL;
+ struct som_entry *som_dict = NULL;
+ file_ptr lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+ hash_table =
+ (unsigned int *) bfd_malloc (lst_header->hash_size
+ * sizeof (unsigned int));
+ if (hash_table == NULL && lst_header->hash_size != 0)
+ goto error_return;
+
+ som_dict =
+ (struct som_entry *) bfd_malloc (lst_header->module_count
+ * sizeof (struct som_entry));
+ if (som_dict == NULL && lst_header->module_count != 0)
+ goto error_return;
+
+ /* Read in the hash table. The has table is an array of 32bit file offsets
+ which point to the hash chains. */
+ if (bfd_read ((PTR) hash_table, lst_header->hash_size, 4, abfd)
+ != lst_header->hash_size * 4)
+ goto error_return;
+
+ /* Seek to and read in the SOM dictionary. We will need this to fill
+ in the carsym's filepos field. */
+ if (bfd_seek (abfd, lst_filepos + lst_header->dir_loc, SEEK_SET) < 0)
+ goto error_return;
+
+ if (bfd_read ((PTR) som_dict, lst_header->module_count,
+ sizeof (struct som_entry), abfd)
+ != lst_header->module_count * sizeof (struct som_entry))
+ goto error_return;
+
+ /* Walk each chain filling in the carsyms as we go along. */
+ for (i = 0; i < lst_header->hash_size; i++)
+ {
+ struct lst_symbol_record lst_symbol;
+
+ /* An empty chain has zero as it's file offset. */
+ if (hash_table[i] == 0)
+ continue;
+
+ /* Seek to and read the first symbol on the chain. */
+ if (bfd_seek (abfd, lst_filepos + hash_table[i], SEEK_SET) < 0)
+ goto error_return;
+
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ goto error_return;
+
+ /* Get the name of the symbol, first get the length which is stored
+ as a 32bit integer just before the symbol.
+
+ One might ask why we don't just read in the entire string table
+ and index into it. Well, according to the SOM ABI the string
+ index can point *anywhere* in the archive to save space, so just
+ using the string table would not be safe. */
+ if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
+ + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
+ goto error_return;
+
+ if (bfd_read (&len, 1, 4, abfd) != 4)
+ goto error_return;
+
+ /* Allocate space for the name and null terminate it too. */
+ set->name = bfd_zalloc (abfd, len + 1);
+ if (!set->name)
+ goto error_return;
+ if (bfd_read (set->name, 1, len, abfd) != len)
+ goto error_return;
+
+ set->name[len] = 0;
+
+ /* Fill in the file offset. Note that the "location" field points
+ to the SOM itself, not the ar_hdr in front of it. */
+ set->file_offset = som_dict[lst_symbol.som_index].location
+ - sizeof (struct ar_hdr);
+
+ /* Go to the next symbol. */
+ set++;
+
+ /* Iterate through the rest of the chain. */
+ while (lst_symbol.next_entry)
+ {
+ /* Seek to the next symbol and read it in. */
+ if (bfd_seek (abfd, lst_filepos + lst_symbol.next_entry, SEEK_SET) <0)
+ goto error_return;
+
+ if (bfd_read ((PTR) & lst_symbol, 1, sizeof (lst_symbol), abfd)
+ != sizeof (lst_symbol))
+ goto error_return;
+
+ /* Seek to the name length & string and read them in. */
+ if (bfd_seek (abfd, lst_filepos + lst_header->string_loc
+ + lst_symbol.name.n_strx - 4, SEEK_SET) < 0)
+ goto error_return;
+
+ if (bfd_read (&len, 1, 4, abfd) != 4)
+ goto error_return;
+
+ /* Allocate space for the name and null terminate it too. */
+ set->name = bfd_zalloc (abfd, len + 1);
+ if (!set->name)
+ goto error_return;
+
+ if (bfd_read (set->name, 1, len, abfd) != len)
+ goto error_return;
+ set->name[len] = 0;
+
+ /* Fill in the file offset. Note that the "location" field points
+ to the SOM itself, not the ar_hdr in front of it. */
+ set->file_offset = som_dict[lst_symbol.som_index].location
+ - sizeof (struct ar_hdr);
+
+ /* Go on to the next symbol. */
+ set++;
+ }
+ }
+ /* If we haven't died by now, then we successfully read the entire
+ archive symbol table. */
+ if (hash_table != NULL)
+ free (hash_table);
+ if (som_dict != NULL)
+ free (som_dict);
+ return true;
+
+ error_return:
+ if (hash_table != NULL)
+ free (hash_table);
+ if (som_dict != NULL)
+ free (som_dict);
+ return false;
+}
+
+/* Read in the LST from the archive. */
+static boolean
+som_slurp_armap (abfd)
+ bfd *abfd;
+{
+ struct lst_header lst_header;
+ struct ar_hdr ar_header;
+ unsigned int parsed_size;
+ struct artdata *ardata = bfd_ardata (abfd);
+ char nextname[17];
+ int i = bfd_read ((PTR) nextname, 1, 16, abfd);
+
+ /* Special cases. */
+ if (i == 0)
+ return true;
+ if (i != 16)
+ return false;
+
+ if (bfd_seek (abfd, (file_ptr) - 16, SEEK_CUR) < 0)
+ return false;
+
+ /* For archives without .o files there is no symbol table. */
+ if (strncmp (nextname, "/ ", 16))
+ {
+ bfd_has_map (abfd) = false;
+ return true;
+ }
+
+ /* Read in and sanity check the archive header. */
+ if (bfd_read ((PTR) &ar_header, 1, sizeof (struct ar_hdr), abfd)
+ != sizeof (struct ar_hdr))
+ return false;
+
+ if (strncmp (ar_header.ar_fmag, ARFMAG, 2))
+ {
+ bfd_set_error (bfd_error_malformed_archive);
+ return false;
+ }
+
+ /* How big is the archive symbol table entry? */
+ errno = 0;
+ parsed_size = strtol (ar_header.ar_size, NULL, 10);
+ if (errno != 0)
+ {
+ bfd_set_error (bfd_error_malformed_archive);
+ return false;
+ }
+
+ /* Save off the file offset of the first real user data. */
+ ardata->first_file_filepos = bfd_tell (abfd) + parsed_size;
+
+ /* Read in the library symbol table. We'll make heavy use of this
+ in just a minute. */
+ if (bfd_read ((PTR) & lst_header, 1, sizeof (struct lst_header), abfd)
+ != sizeof (struct lst_header))
+ return false;
+
+ /* Sanity check. */
+ if (lst_header.a_magic != LIBMAGIC)
+ {
+ bfd_set_error (bfd_error_malformed_archive);
+ return false;
+ }
+
+ /* Count the number of symbols in the library symbol table. */
+ if (som_bfd_count_ar_symbols (abfd, &lst_header, &ardata->symdef_count)
+ == false)
+ return false;
+
+ /* Get back to the start of the library symbol table. */
+ if (bfd_seek (abfd, ardata->first_file_filepos - parsed_size
+ + sizeof (struct lst_header), SEEK_SET) < 0)
+ return false;
+
+ /* Initializae the cache and allocate space for the library symbols. */
+ ardata->cache = 0;
+ ardata->symdefs = (carsym *) bfd_alloc (abfd,
+ (ardata->symdef_count
+ * sizeof (carsym)));
+ if (!ardata->symdefs)
+ return false;
+
+ /* Now fill in the canonical archive symbols. */
+ if (som_bfd_fill_in_ar_symbols (abfd, &lst_header, &ardata->symdefs)
+ == false)
+ return false;
+
+ /* Seek back to the "first" file in the archive. Note the "first"
+ file may be the extended name table. */
+ if (bfd_seek (abfd, ardata->first_file_filepos, SEEK_SET) < 0)
+ return false;
+
+ /* Notify the generic archive code that we have a symbol map. */
+ bfd_has_map (abfd) = true;
+ return true;
+}
+
+/* Begin preparing to write a SOM library symbol table.
+
+ As part of the prep work we need to determine the number of symbols
+ and the size of the associated string section. */
+
+static boolean
+som_bfd_prep_for_ar_write (abfd, num_syms, stringsize)
+ bfd *abfd;
+ unsigned int *num_syms, *stringsize;
+{
+ bfd *curr_bfd = abfd->archive_head;
+
+ /* Some initialization. */
+ *num_syms = 0;
+ *stringsize = 0;
+
+ /* Iterate over each BFD within this archive. */
+ while (curr_bfd != NULL)
+ {
+ unsigned int curr_count, i;
+ som_symbol_type *sym;
+
+ /* Don't bother for non-SOM objects. */
+ if (curr_bfd->format != bfd_object
+ || curr_bfd->xvec->flavour != bfd_target_som_flavour)
+ {
+ curr_bfd = curr_bfd->next;
+ continue;
+ }
+
+ /* Make sure the symbol table has been read, then snag a pointer
+ to it. It's a little slimey to grab the symbols via obj_som_symtab,
+ but doing so avoids allocating lots of extra memory. */
+ if (som_slurp_symbol_table (curr_bfd) == false)
+ return false;
+
+ sym = obj_som_symtab (curr_bfd);
+ curr_count = bfd_get_symcount (curr_bfd);
+
+ /* Examine each symbol to determine if it belongs in the
+ library symbol table. */
+ for (i = 0; i < curr_count; i++, sym++)
+ {
+ struct som_misc_symbol_info info;
+
+ /* Derive SOM information from the BFD symbol. */
+ som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
+
+ /* Should we include this symbol? */
+ if (info.symbol_type == ST_NULL
+ || info.symbol_type == ST_SYM_EXT
+ || info.symbol_type == ST_ARG_EXT)
+ continue;
+
+ /* Only global symbols and unsatisfied commons. */
+ if (info.symbol_scope != SS_UNIVERSAL
+ && info.symbol_type != ST_STORAGE)
+ continue;
+
+ /* Do no include undefined symbols. */
+ if (bfd_is_und_section (sym->symbol.section))
+ continue;
+
+ /* Bump the various counters, being careful to honor
+ alignment considerations in the string table. */
+ (*num_syms)++;
+ *stringsize = *stringsize + strlen (sym->symbol.name) + 5;
+ while (*stringsize % 4)
+ (*stringsize)++;
+ }
+
+ curr_bfd = curr_bfd->next;
+ }
+ return true;
+}
+
+/* Hash a symbol name based on the hashing algorithm presented in the
+ SOM ABI. */
+static unsigned int
+som_bfd_ar_symbol_hash (symbol)
+ asymbol *symbol;
+{
+ unsigned int len = strlen (symbol->name);
+
+ /* Names with length 1 are special. */
+ if (len == 1)
+ return 0x1000100 | (symbol->name[0] << 16) | symbol->name[0];
+
+ return ((len & 0x7f) << 24) | (symbol->name[1] << 16)
+ | (symbol->name[len-2] << 8) | symbol->name[len-1];
+}
+
+static CONST char *
+normalize (file)
+ CONST char *file;
+{
+ CONST char *filename = strrchr (file, '/');
+
+ if (filename != NULL)
+ filename++;
+ else
+ filename = file;
+ return filename;
+}
+
+/* Do the bulk of the work required to write the SOM library
+ symbol table. */
+
+static boolean
+som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst)
+ bfd *abfd;
+ unsigned int nsyms, string_size;
+ struct lst_header lst;
+{
+ file_ptr lst_filepos;
+ char *strings = NULL, *p;
+ struct lst_symbol_record *lst_syms = NULL, *curr_lst_sym;
+ bfd *curr_bfd;
+ unsigned int *hash_table = NULL;
+ struct som_entry *som_dict = NULL;
+ struct lst_symbol_record **last_hash_entry = NULL;
+ unsigned int curr_som_offset, som_index, extended_name_length = 0;
+ unsigned int maxname = abfd->xvec->ar_max_namelen;
+
+ hash_table =
+ (unsigned int *) bfd_malloc (lst.hash_size * sizeof (unsigned int));
+ if (hash_table == NULL && lst.hash_size != 0)
+ goto error_return;
+ som_dict =
+ (struct som_entry *) bfd_malloc (lst.module_count
+ * sizeof (struct som_entry));
+ if (som_dict == NULL && lst.module_count != 0)
+ goto error_return;
+
+ last_hash_entry =
+ ((struct lst_symbol_record **)
+ bfd_malloc (lst.hash_size * sizeof (struct lst_symbol_record *)));
+ if (last_hash_entry == NULL && lst.hash_size != 0)
+ goto error_return;
+
+ /* Lots of fields are file positions relative to the start
+ of the lst record. So save its location. */
+ lst_filepos = bfd_tell (abfd) - sizeof (struct lst_header);
+
+ /* Some initialization. */
+ memset (hash_table, 0, 4 * lst.hash_size);
+ memset (som_dict, 0, lst.module_count * sizeof (struct som_entry));
+ memset (last_hash_entry, 0,
+ lst.hash_size * sizeof (struct lst_symbol_record *));
+
+ /* Symbols have som_index fields, so we have to keep track of the
+ index of each SOM in the archive.
+
+ The SOM dictionary has (among other things) the absolute file
+ position for the SOM which a particular dictionary entry
+ describes. We have to compute that information as we iterate
+ through the SOMs/symbols. */
+ som_index = 0;
+ curr_som_offset = 8 + 2 * sizeof (struct ar_hdr) + lst.file_end;
+
+ /* Yow! We have to know the size of the extended name table
+ too. */
+ for (curr_bfd = abfd->archive_head;
+ curr_bfd != NULL;
+ curr_bfd = curr_bfd->next)
+ {
+ CONST char *normal = normalize (curr_bfd->filename);
+ unsigned int thislen;
+
+ if (!normal)
+ return false;
+ thislen = strlen (normal);
+ if (thislen > maxname)
+ extended_name_length += thislen + 1;
+ }
+
+ /* Make room for the archive header and the contents of the
+ extended string table. */
+ if (extended_name_length)
+ curr_som_offset += extended_name_length + sizeof (struct ar_hdr);
+
+ /* Make sure we're properly aligned. */
+ curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
+
+ /* FIXME should be done with buffers just like everything else... */
+ lst_syms = bfd_malloc (nsyms * sizeof (struct lst_symbol_record));
+ if (lst_syms == NULL && nsyms != 0)
+ goto error_return;
+ strings = bfd_malloc (string_size);
+ if (strings == NULL && string_size != 0)
+ goto error_return;
+
+ p = strings;
+ curr_lst_sym = lst_syms;
+
+ curr_bfd = abfd->archive_head;
+ while (curr_bfd != NULL)
+ {
+ unsigned int curr_count, i;
+ som_symbol_type *sym;
+
+ /* Don't bother for non-SOM objects. */
+ if (curr_bfd->format != bfd_object
+ || curr_bfd->xvec->flavour != bfd_target_som_flavour)
+ {
+ curr_bfd = curr_bfd->next;
+ continue;
+ }
+
+ /* Make sure the symbol table has been read, then snag a pointer
+ to it. It's a little slimey to grab the symbols via obj_som_symtab,
+ but doing so avoids allocating lots of extra memory. */
+ if (som_slurp_symbol_table (curr_bfd) == false)
+ goto error_return;
+
+ sym = obj_som_symtab (curr_bfd);
+ curr_count = bfd_get_symcount (curr_bfd);
+
+ for (i = 0; i < curr_count; i++, sym++)
+ {
+ struct som_misc_symbol_info info;
+
+ /* Derive SOM information from the BFD symbol. */
+ som_bfd_derive_misc_symbol_info (curr_bfd, &sym->symbol, &info);
+
+ /* Should we include this symbol? */
+ if (info.symbol_type == ST_NULL
+ || info.symbol_type == ST_SYM_EXT
+ || info.symbol_type == ST_ARG_EXT)
+ continue;
+
+ /* Only global symbols and unsatisfied commons. */
+ if (info.symbol_scope != SS_UNIVERSAL
+ && info.symbol_type != ST_STORAGE)
+ continue;
+
+ /* Do no include undefined symbols. */
+ if (bfd_is_und_section (sym->symbol.section))
+ continue;
+
+ /* If this is the first symbol from this SOM, then update
+ the SOM dictionary too. */
+ if (som_dict[som_index].location == 0)
+ {
+ som_dict[som_index].location = curr_som_offset;
+ som_dict[som_index].length = arelt_size (curr_bfd);
+ }
+
+ /* Fill in the lst symbol record. */
+ curr_lst_sym->hidden = 0;
+ curr_lst_sym->secondary_def = 0;
+ curr_lst_sym->symbol_type = info.symbol_type;
+ curr_lst_sym->symbol_scope = info.symbol_scope;
+ curr_lst_sym->check_level = 0;
+ curr_lst_sym->must_qualify = 0;
+ curr_lst_sym->initially_frozen = 0;
+ curr_lst_sym->memory_resident = 0;
+ curr_lst_sym->is_common = bfd_is_com_section (sym->symbol.section);
+ curr_lst_sym->dup_common = 0;
+ curr_lst_sym->xleast = 0;
+ curr_lst_sym->arg_reloc = info.arg_reloc;
+ curr_lst_sym->name.n_strx = p - strings + 4;
+ curr_lst_sym->qualifier_name.n_strx = 0;
+ curr_lst_sym->symbol_info = info.symbol_info;
+ curr_lst_sym->symbol_value = info.symbol_value;
+ curr_lst_sym->symbol_descriptor = 0;
+ curr_lst_sym->reserved = 0;
+ curr_lst_sym->som_index = som_index;
+ curr_lst_sym->symbol_key = som_bfd_ar_symbol_hash (&sym->symbol);
+ curr_lst_sym->next_entry = 0;
+
+ /* Insert into the hash table. */
+ if (hash_table[curr_lst_sym->symbol_key % lst.hash_size])
+ {
+ struct lst_symbol_record *tmp;
+
+ /* There is already something at the head of this hash chain,
+ so tack this symbol onto the end of the chain. */
+ tmp = last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size];
+ tmp->next_entry
+ = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
+ + lst.hash_size * 4
+ + lst.module_count * sizeof (struct som_entry)
+ + sizeof (struct lst_header);
+ }
+ else
+ {
+ /* First entry in this hash chain. */
+ hash_table[curr_lst_sym->symbol_key % lst.hash_size]
+ = (curr_lst_sym - lst_syms) * sizeof (struct lst_symbol_record)
+ + lst.hash_size * 4
+ + lst.module_count * sizeof (struct som_entry)
+ + sizeof (struct lst_header);
+ }
+
+ /* Keep track of the last symbol we added to this chain so we can
+ easily update its next_entry pointer. */
+ last_hash_entry[curr_lst_sym->symbol_key % lst.hash_size]
+ = curr_lst_sym;
+
+
+ /* Update the string table. */
+ bfd_put_32 (abfd, strlen (sym->symbol.name), p);
+ p += 4;
+ strcpy (p, sym->symbol.name);
+ p += strlen (sym->symbol.name) + 1;
+ while ((int)p % 4)
+ {
+ bfd_put_8 (abfd, 0, p);
+ p++;
+ }
+
+ /* Head to the next symbol. */
+ curr_lst_sym++;
+ }
+
+ /* Keep track of where each SOM will finally reside; then look
+ at the next BFD. */
+ curr_som_offset += arelt_size (curr_bfd) + sizeof (struct ar_hdr);
+
+ /* A particular object in the archive may have an odd length; the
+ linker requires objects begin on an even boundary. So round
+ up the current offset as necessary. */
+ curr_som_offset = (curr_som_offset + 0x1) & ~0x1;
+ curr_bfd = curr_bfd->next;
+ som_index++;
+ }
+
+ /* Now scribble out the hash table. */
+ if (bfd_write ((PTR) hash_table, lst.hash_size, 4, abfd)
+ != lst.hash_size * 4)
+ goto error_return;
+
+ /* Then the SOM dictionary. */
+ if (bfd_write ((PTR) som_dict, lst.module_count,
+ sizeof (struct som_entry), abfd)
+ != lst.module_count * sizeof (struct som_entry))
+ goto error_return;
+
+ /* The library symbols. */
+ if (bfd_write ((PTR) lst_syms, nsyms, sizeof (struct lst_symbol_record), abfd)
+ != nsyms * sizeof (struct lst_symbol_record))
+ goto error_return;
+
+ /* And finally the strings. */
+ if (bfd_write ((PTR) strings, string_size, 1, abfd) != string_size)
+ goto error_return;
+
+ if (hash_table != NULL)
+ free (hash_table);
+ if (som_dict != NULL)
+ free (som_dict);
+ if (last_hash_entry != NULL)
+ free (last_hash_entry);
+ if (lst_syms != NULL)
+ free (lst_syms);
+ if (strings != NULL)
+ free (strings);
+ return true;
+
+ error_return:
+ if (hash_table != NULL)
+ free (hash_table);
+ if (som_dict != NULL)
+ free (som_dict);
+ if (last_hash_entry != NULL)
+ free (last_hash_entry);
+ if (lst_syms != NULL)
+ free (lst_syms);
+ if (strings != NULL)
+ free (strings);
+
+ return false;
+}
+
+/* SOM almost uses the SVR4 style extended name support, but not
+ quite. */
+
+static boolean
+som_construct_extended_name_table (abfd, tabloc, tablen, name)
+ bfd *abfd;
+ char **tabloc;
+ bfd_size_type *tablen;
+ const char **name;
+{
+ *name = "//";
+ return _bfd_construct_extended_name_table (abfd, false, tabloc, tablen);
+}
+
+/* Write out the LST for the archive.
+
+ You'll never believe this is really how armaps are handled in SOM... */
+
+/*ARGSUSED*/
+static boolean
+som_write_armap (abfd, elength, map, orl_count, stridx)
+ bfd *abfd;
+ unsigned int elength;
+ struct orl *map;
+ unsigned int orl_count;
+ int stridx;
+{
+ bfd *curr_bfd;
+ struct stat statbuf;
+ unsigned int i, lst_size, nsyms, stringsize;
+ struct ar_hdr hdr;
+ struct lst_header lst;
+ int *p;
+
+ /* We'll use this for the archive's date and mode later. */
+ if (stat (abfd->filename, &statbuf) != 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return false;
+ }
+ /* Fudge factor. */
+ bfd_ardata (abfd)->armap_timestamp = statbuf.st_mtime + 60;
+
+ /* Account for the lst header first. */
+ lst_size = sizeof (struct lst_header);
+
+ /* Start building the LST header. */
+ /* FIXME: Do we need to examine each element to determine the
+ largest id number? */
+ lst.system_id = CPU_PA_RISC1_0;
+ lst.a_magic = LIBMAGIC;
+ lst.version_id = VERSION_ID;
+ lst.file_time.secs = 0;
+ lst.file_time.nanosecs = 0;
+
+ lst.hash_loc = lst_size;
+ lst.hash_size = SOM_LST_HASH_SIZE;
+
+ /* Hash table is a SOM_LST_HASH_SIZE 32bit offsets. */
+ lst_size += 4 * SOM_LST_HASH_SIZE;
+
+ /* We need to count the number of SOMs in this archive. */
+ curr_bfd = abfd->archive_head;
+ lst.module_count = 0;
+ while (curr_bfd != NULL)
+ {
+ /* Only true SOM objects count. */
+ if (curr_bfd->format == bfd_object
+ && curr_bfd->xvec->flavour == bfd_target_som_flavour)
+ lst.module_count++;
+ curr_bfd = curr_bfd->next;
+ }
+ lst.module_limit = lst.module_count;
+ lst.dir_loc = lst_size;
+ lst_size += sizeof (struct som_entry) * lst.module_count;
+
+ /* We don't support import/export tables, auxiliary headers,
+ or free lists yet. Make the linker work a little harder
+ to make our life easier. */
+
+ lst.export_loc = 0;
+ lst.export_count = 0;
+ lst.import_loc = 0;
+ lst.aux_loc = 0;
+ lst.aux_size = 0;
+
+ /* Count how many symbols we will have on the hash chains and the
+ size of the associated string table. */
+ if (som_bfd_prep_for_ar_write (abfd, &nsyms, &stringsize) == false)
+ return false;
+
+ lst_size += sizeof (struct lst_symbol_record) * nsyms;
+
+ /* For the string table. One day we might actually use this info
+ to avoid small seeks/reads when reading archives. */
+ lst.string_loc = lst_size;
+ lst.string_size = stringsize;
+ lst_size += stringsize;
+
+ /* SOM ABI says this must be zero. */
+ lst.free_list = 0;
+ lst.file_end = lst_size;
+
+ /* Compute the checksum. Must happen after the entire lst header
+ has filled in. */
+ p = (int *)&lst;
+ lst.checksum = 0;
+ for (i = 0; i < sizeof (struct lst_header)/sizeof (int) - 1; i++)
+ lst.checksum ^= *p++;
+
+ sprintf (hdr.ar_name, "/ ");
+ sprintf (hdr.ar_date, "%ld", bfd_ardata (abfd)->armap_timestamp);
+ sprintf (hdr.ar_uid, "%ld", (long) getuid ());
+ sprintf (hdr.ar_gid, "%ld", (long) getgid ());
+ sprintf (hdr.ar_mode, "%-8o", (unsigned int) statbuf.st_mode);
+ sprintf (hdr.ar_size, "%-10d", (int) lst_size);
+ hdr.ar_fmag[0] = '`';
+ hdr.ar_fmag[1] = '\012';
+
+ /* Turn any nulls into spaces. */
+ for (i = 0; i < sizeof (struct ar_hdr); i++)
+ if (((char *) (&hdr))[i] == '\0')
+ (((char *) (&hdr))[i]) = ' ';
+
+ /* Scribble out the ar header. */
+ if (bfd_write ((PTR) &hdr, 1, sizeof (struct ar_hdr), abfd)
+ != sizeof (struct ar_hdr))
+ return false;
+
+ /* Now scribble out the lst header. */
+ if (bfd_write ((PTR) &lst, 1, sizeof (struct lst_header), abfd)
+ != sizeof (struct lst_header))
+ return false;
+
+ /* Build and write the armap. */
+ if (som_bfd_ar_write_symbol_stuff (abfd, nsyms, stringsize, lst) == false)
+ return false;
+
+ /* Done. */
+ return true;
+}
+
+/* Free all information we have cached for this BFD. We can always
+ read it again later if we need it. */
+
+static boolean
+som_bfd_free_cached_info (abfd)
+ bfd *abfd;
+{
+ asection *o;
+
+ if (bfd_get_format (abfd) != bfd_object)
+ return true;
+
+#define FREE(x) if (x != NULL) { free (x); x = NULL; }
+ /* Free the native string and symbol tables. */
+ FREE (obj_som_symtab (abfd));
+ FREE (obj_som_stringtab (abfd));
+ for (o = abfd->sections; o != (asection *) NULL; o = o->next)
+ {
+ /* Free the native relocations. */
+ o->reloc_count = -1;
+ FREE (som_section_data (o)->reloc_stream);
+ /* Free the generic relocations. */
+ FREE (o->relocation);
+ }
+#undef FREE
+
+ return true;
+}
+
+/* End of miscellaneous support functions. */
+
+/* Linker support functions. */
+static boolean
+som_bfd_link_split_section (abfd, sec)
+ bfd *abfd;
+ asection *sec;
+{
+ return (som_is_subspace (sec) && sec->_raw_size > 240000);
+}
+
+#define som_close_and_cleanup som_bfd_free_cached_info
+
+#define som_read_ar_hdr _bfd_generic_read_ar_hdr
+#define som_openr_next_archived_file bfd_generic_openr_next_archived_file
+#define som_get_elt_at_index _bfd_generic_get_elt_at_index
+#define som_generic_stat_arch_elt bfd_generic_stat_arch_elt
+#define som_truncate_arname bfd_bsd_truncate_arname
+#define som_slurp_extended_name_table _bfd_slurp_extended_name_table
+#define som_update_armap_timestamp bfd_true
+#define som_bfd_print_private_bfd_data _bfd_generic_bfd_print_private_bfd_data
+
+#define som_get_lineno _bfd_nosymbols_get_lineno
+#define som_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define som_read_minisymbols _bfd_generic_read_minisymbols
+#define som_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+#define som_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#define som_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define som_bfd_relax_section bfd_generic_relax_section
+#define som_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define som_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define som_bfd_final_link _bfd_generic_final_link
+
+
+const bfd_target som_vec =
+{
+ "som", /* name */
+ bfd_target_som_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
+ (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
+ | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+
+/* leading_symbol_char: is the first char of a user symbol
+ predictable, and if so what is it */
+ 0,
+ '/', /* ar_pad_char */
+ 14, /* ar_max_namelen */
+ 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,
+ som_object_p, /* bfd_check_format */
+ bfd_generic_archive_p,
+ _bfd_dummy_target
+ },
+ {
+ bfd_false,
+ som_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false
+ },
+ {
+ bfd_false,
+ som_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+#undef som
+
+ BFD_JUMP_TABLE_GENERIC (som),
+ BFD_JUMP_TABLE_COPY (som),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (som),
+ BFD_JUMP_TABLE_SYMBOLS (som),
+ BFD_JUMP_TABLE_RELOCS (som),
+ BFD_JUMP_TABLE_WRITE (som),
+ BFD_JUMP_TABLE_LINK (som),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
+
+#endif /* HOST_HPPAHPUX || HOST_HPPABSD || HOST_HPPAOSF */
diff --git a/contrib/gdb/bfd/som.h b/contrib/gdb/bfd/som.h
new file mode 100644
index 0000000..6290e88
--- /dev/null
+++ b/contrib/gdb/bfd/som.h
@@ -0,0 +1,224 @@
+/* HP PA-RISC SOM object file format: definitions internal to BFD.
+ Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _SOM_H
+#define _SOM_H
+
+#include "../bfd/sysdep.h"
+#include "libhppa.h"
+
+#include <a.out.h>
+#include <lst.h>
+#include <ar.h>
+
+/* The SOM BFD backend doesn't currently use anything from these
+ two include files, but it's likely to need them in the future. */
+#ifdef R_DLT_REL
+#include <shl.h>
+#include <dl.h>
+#endif
+
+#if defined(HOST_HPPABSD) || defined (HOST_HPPAOSF)
+/* BSD uses a completely different scheme for object file identification.
+ so for now, define _PA_RISC_ID to accept any random value for a model
+ number. */
+#undef _PA_RISC_ID
+#define _PA_RISC_ID(__m_num) 1
+#endif /* HOST_HPPABSD */
+
+#define FILE_HDR_SIZE sizeof(struct header)
+#define AUX_HDR_SIZE sizeof(struct som_exec_auxhdr)
+
+typedef struct som_symbol
+ {
+ asymbol symbol;
+ unsigned int som_type;
+
+ /* Structured like the ELF tc_data union. Allows more code sharing
+ in GAS this way. */
+ union
+ {
+ unsigned int hppa_arg_reloc;
+ PTR any;
+ }
+ tc_data;
+
+ /* Index of this symbol in the symbol table. Only used when
+ building relocation streams for incomplete objects. */
+ int index;
+
+ /* How many times this symbol is used in a relocation. By sorting
+ the symbols from most used to least used we can significantly
+ reduce the size of the relocation stream for incomplete objects. */
+ int reloc_count;
+
+ /* During object file writing, the offset of the name of this symbol
+ in the SOM string table. */
+ int stringtab_offset;
+ }
+som_symbol_type;
+
+/* A structure containing all the magic information stored in a BFD's
+ private data which needs to be copied during an objcopy/strip run. */
+struct som_exec_data
+ {
+ /* Sort-of a magic number. BSD uses it to distinguish between
+ native executables and hpux executables. */
+ short system_id;
+
+ /* Magic exec flags. These control things like whether or not
+ null pointer dereferencing is allowed and the like. */
+ long exec_flags;
+
+ /* Add more stuff here as needed. Good examples of information
+ we might want to pass would be presumed_dp, entry_* and maybe
+ others from the file header. */
+ };
+
+struct somdata
+ {
+ /* All the magic information about an executable which lives
+ in the private BFD structure and needs to be copied from
+ the input bfd to the output bfd during a objcopy/strip. */
+ struct som_exec_data *exec_data;
+
+ /* These three fields are only used when writing files and are
+ generated from scratch. They need not be copied for objcopy
+ or strip to work. */
+ struct header *file_hdr;
+ struct copyright_aux_hdr *copyright_aux_hdr;
+ struct user_string_aux_hdr *version_aux_hdr;
+ struct som_exec_auxhdr *exec_hdr;
+
+ /* Pointers to a saved copy of the symbol and string tables. These
+ need not be copied for objcopy or strip to work. */
+ som_symbol_type *symtab;
+ char *stringtab;
+ asymbol **sorted_syms;
+
+ /* We remember these offsets so that after check_file_format, we have
+ no dependencies on the particular format of the exec_hdr.
+ These offsets need not be copied for objcopy or strip to work. */
+
+ file_ptr sym_filepos;
+ file_ptr str_filepos;
+ file_ptr reloc_filepos;
+ unsigned stringtab_size;
+ };
+
+struct som_data_struct
+ {
+ struct somdata a;
+ };
+
+/* Substructure of som_section_data_struct used to hold information
+ which can't be represented by the generic BFD section structure,
+ but which must be copied during objcopy or strip. */
+struct som_copyable_section_data_struct
+ {
+ /* Various fields in space and subspace headers that we need
+ to pass around. */
+ unsigned int sort_key : 8;
+ unsigned int access_control_bits : 7;
+ unsigned int is_defined : 1;
+ unsigned int is_private : 1;
+ unsigned int quadrant : 2;
+
+ /* For subspaces, this points to the section which represents the
+ space in which the subspace is contained. For spaces it points
+ back to the section for this space. */
+ asection *container;
+
+ /* The user-specified space number. It is wrong to use this as
+ an index since duplicates and holes are allowed. */
+ int space_number;
+
+ /* Add more stuff here as needed. Good examples of information
+ we might want to pass would be initialization pointers,
+ and the many subspace flags we do not represent yet. */
+ };
+
+/* Used to keep extra SOM specific information for a given section.
+
+ reloc_size holds the size of the relocation stream, note this
+ is very different from the number of relocations as SOM relocations
+ are variable length.
+
+ reloc_stream is the actual stream of relocation entries. */
+
+struct som_section_data_struct
+ {
+ struct som_copyable_section_data_struct *copy_data;
+ unsigned int reloc_size;
+ char *reloc_stream;
+ struct space_dictionary_record *space_dict;
+ struct subspace_dictionary_record *subspace_dict;
+ };
+
+#define somdata(bfd) ((bfd)->tdata.som_data->a)
+#define obj_som_exec_data(bfd) (somdata(bfd).exec_data)
+#define obj_som_file_hdr(bfd) (somdata(bfd).file_hdr)
+#define obj_som_exec_hdr(bfd) (somdata(bfd).exec_hdr)
+#define obj_som_copyright_hdr(bfd) (somdata(bfd).copyright_aux_hdr)
+#define obj_som_version_hdr(bfd) (somdata(bfd).version_aux_hdr)
+#define obj_som_symtab(bfd) (somdata(bfd).symtab)
+#define obj_som_stringtab(bfd) (somdata(bfd).stringtab)
+#define obj_som_sym_filepos(bfd) (somdata(bfd).sym_filepos)
+#define obj_som_str_filepos(bfd) (somdata(bfd).str_filepos)
+#define obj_som_stringtab_size(bfd) (somdata(bfd).stringtab_size)
+#define obj_som_reloc_filepos(bfd) (somdata(bfd).reloc_filepos)
+#define obj_som_sorted_syms(bfd) (somdata(bfd).sorted_syms)
+#define som_section_data(sec) \
+ ((struct som_section_data_struct *)sec->used_by_bfd)
+#define som_symbol_data(symbol) ((som_symbol_type *) symbol)
+
+
+/* Defines groups of basic relocations. FIXME: These should
+ be the only basic relocations created by GAS. The rest
+ should be internal to the BFD backend.
+
+ The idea is both SOM and ELF define these basic relocation
+ types so they map into a SOM or ELF specific reloation as
+ appropriate. This allows GAS to share much more code
+ between the two object formats. */
+
+#define R_HPPA_NONE R_NO_RELOCATION
+#define R_HPPA R_CODE_ONE_SYMBOL
+#define R_HPPA_PCREL_CALL R_PCREL_CALL
+#define R_HPPA_ABS_CALL R_ABS_CALL
+#define R_HPPA_GOTOFF R_DP_RELATIVE
+#define R_HPPA_ENTRY R_ENTRY
+#define R_HPPA_EXIT R_EXIT
+#define R_HPPA_COMPLEX R_COMP1
+#define R_HPPA_BEGIN_BRTAB R_BEGIN_BRTAB
+#define R_HPPA_END_BRTAB R_END_BRTAB
+
+/* Exported functions, mostly for use by GAS. */
+boolean bfd_som_set_section_attributes PARAMS ((asection *, int, int,
+ unsigned int, int));
+boolean bfd_som_set_subsection_attributes PARAMS ((asection *, asection *,
+ int, unsigned int, int));
+void bfd_som_set_symbol_type PARAMS ((asymbol *, unsigned int));
+boolean bfd_som_attach_aux_hdr PARAMS ((bfd *, int, char *));
+int ** hppa_som_gen_reloc_type
+ PARAMS ((bfd *, int, int, enum hppa_reloc_field_selector_type_alt, int));
+#endif /* _SOM_H */
diff --git a/contrib/gdb/bfd/sparclynx.c b/contrib/gdb/bfd/sparclynx.c
new file mode 100644
index 0000000..0885620
--- /dev/null
+++ b/contrib/gdb/bfd/sparclynx.c
@@ -0,0 +1,265 @@
+/* BFD support for Sparc binaries under LynxOS.
+ Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if 0
+#define BYTES_IN_WORD 4
+#define N_SHARED_LIB(x) 0
+
+#define TEXT_START_ADDR 0
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#define DEFAULT_ARCH bfd_arch_sparc
+
+#endif
+
+#define MY(OP) CAT(sparclynx_aout_,OP)
+#define TARGETNAME "a.out-sparc-lynx"
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+#include "aout/sun4.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h"
+#include "aout/ar.h"
+
+/* This is needed to reject a NewsOS file, e.g. in
+ gdb/testsuite/gdb.t10/crossload.exp. <kingdon@cygnus.com>
+ I needed to add M_UNKNOWN to recognize a 68000 object, so this will
+ probably no longer reject a NewsOS object. <ian@cygnus.com>. */
+#define MACHTYPE_OK(mtype) ((mtype) == M_UNKNOWN \
+ || (mtype) == M_68010 \
+ || (mtype) == M_68020 \
+ || (mtype) == M_SPARC)
+
+/*
+The file @code{aoutf1.h} contains the code for BFD's
+a.out back end. Control over the generated back end is given by these
+two preprocessor names:
+@table @code
+@item ARCH_SIZE
+This value should be either 32 or 64, depending upon the size of an
+int in the target format. It changes the sizes of the structs which
+perform the memory/disk mapping of structures.
+
+The 64 bit backend may only be used if the host compiler supports 64
+ints (eg long long with gcc), by defining the name @code{BFD_HOST_64_BIT} in @code{bfd.h}.
+With this name defined, @emph{all} bfd operations are performed with 64bit
+arithmetic, not just those to a 64bit target.
+
+@item TARGETNAME
+The name put into the target vector.
+@item
+@end table
+
+*/
+
+/*SUPPRESS558*/
+/*SUPPRESS529*/
+
+void
+NAME(lynx,set_arch_mach) (abfd, machtype)
+ bfd *abfd;
+ int machtype;
+{
+ /* Determine the architecture and machine type of the object file. */
+ enum bfd_architecture arch;
+ long machine;
+ switch (machtype)
+ {
+
+ case M_UNKNOWN:
+ /* Some Sun3s make magic numbers without cpu types in them, so
+ we'll default to the 68000. */
+ arch = bfd_arch_m68k;
+ machine = 68000;
+ break;
+
+ case M_68010:
+ case M_HP200:
+ arch = bfd_arch_m68k;
+ machine = 68010;
+ break;
+
+ case M_68020:
+ case M_HP300:
+ arch = bfd_arch_m68k;
+ machine = 68020;
+ break;
+
+ case M_SPARC:
+ arch = bfd_arch_sparc;
+ machine = 0;
+ break;
+
+ case M_386:
+ case M_386_DYNIX:
+ arch = bfd_arch_i386;
+ machine = 0;
+ break;
+
+ case M_29K:
+ arch = bfd_arch_a29k;
+ machine = 0;
+ break;
+
+ case M_HPUX:
+ arch = bfd_arch_m68k;
+ machine = 0;
+ break;
+
+ default:
+ arch = bfd_arch_obscure;
+ machine = 0;
+ break;
+ }
+ bfd_set_arch_mach (abfd, arch, machine);
+}
+
+#define SET_ARCH_MACH(ABFD, EXEC) \
+ NAME(lynx,set_arch_mach)(ABFD, N_MACHTYPE (EXEC)); \
+ choose_reloc_size(ABFD);
+
+/* Determine the size of a relocation entry, based on the architecture */
+static void
+choose_reloc_size (abfd)
+ bfd *abfd;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_sparc:
+ case bfd_arch_a29k:
+ obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
+ break;
+ default:
+ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
+ break;
+ }
+}
+
+/* Write an object file in LynxOS format.
+ Section contents have already been written. We write the
+ file header, symbols, and relocation. */
+
+static boolean
+NAME(aout,sparclynx_write_object_contents) (abfd)
+ bfd *abfd;
+{
+ struct external_exec exec_bytes;
+ struct internal_exec *execp = exec_hdr (abfd);
+
+ /* Magic number, maestro, please! */
+ switch (bfd_get_arch (abfd))
+ {
+ case bfd_arch_m68k:
+ switch (bfd_get_mach (abfd))
+ {
+ case 68010:
+ N_SET_MACHTYPE (*execp, M_68010);
+ break;
+ default:
+ case 68020:
+ N_SET_MACHTYPE (*execp, M_68020);
+ break;
+ }
+ break;
+ case bfd_arch_sparc:
+ N_SET_MACHTYPE (*execp, M_SPARC);
+ break;
+ case bfd_arch_i386:
+ N_SET_MACHTYPE (*execp, M_386);
+ break;
+ case bfd_arch_a29k:
+ N_SET_MACHTYPE (*execp, M_29K);
+ break;
+ default:
+ N_SET_MACHTYPE (*execp, M_UNKNOWN);
+ }
+
+ choose_reloc_size (abfd);
+
+ N_SET_FLAGS (*execp, aout_backend_info (abfd)->exec_hdr_flags);
+
+ WRITE_HEADERS (abfd, execp);
+
+ return true;
+}
+
+#define MY_set_sizes sparclynx_set_sizes
+static boolean
+sparclynx_set_sizes (abfd)
+ bfd *abfd;
+{
+ switch (bfd_get_arch (abfd))
+ {
+ default:
+ return false;
+ case bfd_arch_sparc:
+ adata (abfd).page_size = 0x2000;
+ adata (abfd).segment_size = 0x2000;
+ adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+ return true;
+ case bfd_arch_m68k:
+ adata (abfd).page_size = 0x2000;
+ adata (abfd).segment_size = 0x20000;
+ adata (abfd).exec_bytes_size = EXEC_BYTES_SIZE;
+ return true;
+ }
+}
+
+static CONST struct aout_backend_data sparclynx_aout_backend =
+{
+ 0, 1, 1, 0, sparclynx_set_sizes, 0,
+ 0, /* add_dynamic_symbols */
+ 0, /* add_one_symbol */
+ 0, /* link_dynamic_object */
+ 0, /* write_dynamic_symbol */
+ 0, /* check_dynamic_reloc */
+ 0 /* finish_dynamic_link */
+};
+
+
+#define MY_bfd_debug_info_start bfd_void
+#define MY_bfd_debug_info_end bfd_void
+#define MY_bfd_debug_info_accumulate \
+ (void (*) PARAMS ((bfd *, struct sec *))) bfd_void
+
+#define MY_write_object_contents NAME(aout,sparclynx_write_object_contents)
+#define MY_backend_data &sparclynx_aout_backend
+
+#define TARGET_IS_BIG_ENDIAN_P
+
+#ifdef LYNX_CORE
+
+char *lynx_core_file_failing_command ();
+int lynx_core_file_failing_signal ();
+boolean lynx_core_file_matches_executable_p ();
+const bfd_target *lynx_core_file_p ();
+
+#define MY_core_file_failing_command lynx_core_file_failing_command
+#define MY_core_file_failing_signal lynx_core_file_failing_signal
+#define MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
+#define MY_core_file_p lynx_core_file_p
+
+#endif /* LYNX_CORE */
+
+#include "aout-target.h"
diff --git a/contrib/gdb/bfd/sparcnetbsd.c b/contrib/gdb/bfd/sparcnetbsd.c
new file mode 100644
index 0000000..69240f5
--- /dev/null
+++ b/contrib/gdb/bfd/sparcnetbsd.c
@@ -0,0 +1,33 @@
+/* BFD back-end for NetBSD/sparc a.out-ish binaries.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define BYTES_IN_WORD 4
+#define TARGET_IS_BIG_ENDIAN_P
+
+#define TARGET_PAGE_SIZE 4096
+#define SEGMENT_SIZE 4096
+
+#define DEFAULT_ARCH bfd_arch_sparc
+#define MACHTYPE_OK(mtype) ((mtype) == M_SPARC_NETBSD || (mtype) == M_UNKNOWN)
+
+#define MY(OP) CAT(sparcnetbsd_,OP)
+/* This needs to start with a.out so GDB knows it is an a.out variant. */
+#define TARGETNAME "a.out-sparc-netbsd"
+
+#include "netbsd.h"
diff --git a/contrib/gdb/bfd/srec.c b/contrib/gdb/bfd/srec.c
new file mode 100644
index 0000000..33d28d5
--- /dev/null
+++ b/contrib/gdb/bfd/srec.c
@@ -0,0 +1,1324 @@
+/* BFD back-end for s-record objects.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SUBSECTION
+ S-Record handling
+
+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".
+
+ When bfd_get_section_contents is called the file is read
+ again, and this time the data is placed into a bfd_alloc'd
+ area.
+
+ Any number of sections may be created for output, we save them
+ up and output them when it's time to close the bfd.
+
+ An s record looks like:
+
+EXAMPLE
+ S<type><length><address><data><checksum>
+
+DESCRIPTION
+ Where
+ o length
+ is the number of bytes following upto the checksum. Note that
+ this is not the number of chars following, since it takes two
+ chars to represent a byte.
+ o type
+ is one of:
+ 0) header record
+ 1) two byte address data record
+ 2) three byte address data record
+ 3) four byte address data record
+ 7) four byte address termination record
+ 8) three byte address termination record
+ 9) two byte address termination record
+
+ o address
+ is the start address of the data following, or in the case of
+ a termination record, the start address of the image
+ o data
+ is the data.
+ o checksum
+ is the sum of all the raw byte data in the record, from the length
+ upwards, modulo 256 and subtracted from 255.
+
+
+SUBSECTION
+ Symbol S-Record handling
+
+DESCRIPTION
+ Some ICE equipment understands an addition to the standard
+ S-Record format; symbols and their addresses can be sent
+ before the data.
+
+ The format of this is:
+ ($$ <modulename>
+ (<space> <symbol> <address>)*)
+ $$
+
+ so a short symbol table could look like:
+
+EXAMPLE
+ $$ flash.x
+ $$ flash.c
+ _port6 $0
+ _delay $4
+ _start $14
+ _etext $8036
+ _edata $8036
+ _end $8036
+ $$
+
+DESCRIPTION
+ We allow symbols to be anywhere in the data stream - the module names
+ are always ignored.
+
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libiberty.h"
+#include <ctype.h>
+
+static void srec_init PARAMS ((void));
+static boolean srec_mkobject PARAMS ((bfd *));
+static int srec_get_byte PARAMS ((bfd *, boolean *));
+static void srec_bad_byte PARAMS ((bfd *, unsigned int, int, boolean));
+static boolean srec_scan PARAMS ((bfd *));
+static const bfd_target *srec_object_p PARAMS ((bfd *));
+static const bfd_target *symbolsrec_object_p PARAMS ((bfd *));
+static boolean srec_read_section PARAMS ((bfd *, asection *, bfd_byte *));
+
+static boolean srec_write_record PARAMS ((bfd *, int, bfd_vma,
+ const bfd_byte *,
+ const bfd_byte *));
+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";
+
+#define NIBBLE(x) hex_value(x)
+#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
+#define TOHEX(d, x, ch) \
+ d[1] = digs[(x) & 0xf]; \
+ d[0] = digs[((x)>>4)&0xf]; \
+ ch += ((x) & 0xff);
+#define ISHEX(x) hex_p(x)
+
+/* Initialize by filling in the hex conversion array. */
+
+static void
+srec_init ()
+{
+ static boolean inited = false;
+
+ if (inited == false)
+ {
+ inited = true;
+ hex_init ();
+ }
+}
+
+/* The maximum number of bytes on a line is FF */
+#define MAXCHUNK 0xff
+/* The number of bytes we fit onto a line on output */
+#define CHUNK 21
+
+/* When writing an S-record file, the S-records can not be output as
+ they are seen. This structure is used to hold them in memory. */
+
+struct srec_data_list_struct
+{
+ struct srec_data_list_struct *next;
+ bfd_byte *data;
+ bfd_vma where;
+ bfd_size_type size;
+};
+
+typedef struct srec_data_list_struct srec_data_list_type;
+
+/* When scanning the S-record file, a linked list of srec_symbol
+ structures is built to represent the symbol table (if there is
+ one). */
+
+struct srec_symbol
+{
+ struct srec_symbol *next;
+ const char *name;
+ bfd_vma val;
+};
+
+/* The S-record tdata information. */
+
+typedef struct srec_data_struct
+ {
+ srec_data_list_type *head;
+ srec_data_list_type *tail;
+ unsigned int type;
+ struct srec_symbol *symbols;
+ struct srec_symbol *symtail;
+ asymbol *csymbols;
+ }
+tdata_type;
+
+static boolean srec_write_section PARAMS ((bfd *, tdata_type *,
+ srec_data_list_type *));
+static boolean srec_write_terminator PARAMS ((bfd *, tdata_type *));
+
+/* Set up the S-record tdata information. */
+
+static boolean
+srec_mkobject (abfd)
+ bfd *abfd;
+{
+ srec_init ();
+
+ if (abfd->tdata.srec_data == NULL)
+ {
+ tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
+ if (tdata == NULL)
+ return false;
+ abfd->tdata.srec_data = tdata;
+ tdata->type = 1;
+ tdata->head = NULL;
+ tdata->tail = NULL;
+ tdata->symbols = NULL;
+ tdata->symtail = NULL;
+ tdata->csymbols = NULL;
+ }
+
+ return true;
+}
+
+/* Read a byte from an S record file. Set *ERRORPTR if an error
+ occurred. Return EOF on error or end of file. */
+
+static int
+srec_get_byte (abfd, errorptr)
+ bfd *abfd;
+ boolean *errorptr;
+{
+ bfd_byte c;
+
+ if (bfd_read (&c, 1, 1, abfd) != 1)
+ {
+ if (bfd_get_error () != bfd_error_file_truncated)
+ *errorptr = true;
+ return EOF;
+ }
+
+ return (int) (c & 0xff);
+}
+
+/* Report a problem in an S record file. FIXME: This probably should
+ not call fprintf, but we really do need some mechanism for printing
+ error messages. */
+
+static void
+srec_bad_byte (abfd, lineno, c, error)
+ bfd *abfd;
+ unsigned int lineno;
+ int c;
+ boolean error;
+{
+ if (c == EOF)
+ {
+ if (! error)
+ bfd_set_error (bfd_error_file_truncated);
+ }
+ else
+ {
+ char buf[10];
+
+ if (! isprint (c))
+ sprintf (buf, "\\%03o", (unsigned int) c);
+ else
+ {
+ buf[0] = c;
+ buf[1] = '\0';
+ }
+ (*_bfd_error_handler)
+ ("%s:%d: Unexpected character `%s' in S-record file\n",
+ bfd_get_filename (abfd), lineno, buf);
+ bfd_set_error (bfd_error_bad_value);
+ }
+}
+
+/* Add a new symbol found in an S-record file. */
+
+static boolean
+srec_new_symbol (abfd, name, val)
+ bfd *abfd;
+ const char *name;
+ bfd_vma val;
+{
+ struct srec_symbol *n;
+
+ n = (struct srec_symbol *) bfd_alloc (abfd, sizeof (struct srec_symbol));
+ if (n == NULL)
+ return false;
+
+ n->name = name;
+ n->val = val;
+
+ if (abfd->tdata.srec_data->symbols == NULL)
+ abfd->tdata.srec_data->symbols = n;
+ else
+ abfd->tdata.srec_data->symtail->next = n;
+ abfd->tdata.srec_data->symtail = n;
+ n->next = NULL;
+
+ ++abfd->symcount;
+
+ return true;
+}
+
+/* Read the S record file and turn it into sections. We create a new
+ section for each contiguous set of bytes. */
+
+static boolean
+srec_scan (abfd)
+ bfd *abfd;
+{
+ int c;
+ unsigned int lineno = 1;
+ boolean error = false;
+ bfd_byte *buf = NULL;
+ size_t bufsize = 0;
+ asection *sec = NULL;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ goto error_return;
+
+ while ((c = srec_get_byte (abfd, &error)) != EOF)
+ {
+ /* We only build sections from contiguous S-records, so if this
+ is not an S-record, then stop building a section. */
+ if (c != 'S' && c != '\r' && c != '\n')
+ sec = NULL;
+
+ switch (c)
+ {
+ default:
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+
+ case '\n':
+ ++lineno;
+ break;
+
+ case '\r':
+ break;
+
+ case '$':
+ /* Starting a module name, which we ignore. */
+ while ((c = srec_get_byte (abfd, &error)) != '\n'
+ && c != EOF)
+ ;
+ if (c == EOF)
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+
+ ++lineno;
+
+ break;
+
+ case ' ':
+ {
+ char *symname;
+ bfd_vma symval;
+
+ /* Starting a symbol definition. */
+ while ((c = srec_get_byte (abfd, &error)) != EOF
+ && (c == ' ' || c == '\t'))
+ ;
+ if (c == EOF)
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+
+ obstack_1grow (&abfd->memory, c);
+ while ((c = srec_get_byte (abfd, &error)) != EOF
+ && ! isspace (c))
+ obstack_1grow (&abfd->memory, c);
+ if (c == EOF)
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+
+ symname = obstack_finish (&abfd->memory);
+ if (symname == NULL)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
+ while ((c = srec_get_byte (abfd, &error)) != EOF
+ && (c == ' ' || c == '\t'))
+ ;
+ if (c == EOF)
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+
+ /* Skip a dollar sign before the hex value. */
+ if (c == '$')
+ {
+ c = srec_get_byte (abfd, &error);
+ if (c == EOF)
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+ }
+
+ symval = 0;
+ while (ISHEX (c))
+ {
+ symval <<= 4;
+ symval += NIBBLE (c);
+ c = srec_get_byte (abfd, &error);
+ }
+
+ if (c == EOF || ! isspace (c))
+ {
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+
+ if (! srec_new_symbol (abfd, symname, symval))
+ goto error_return;
+
+ if (c == '\n')
+ ++lineno;
+
+ }
+ break;
+
+ case 'S':
+ {
+ file_ptr pos;
+ char hdr[3];
+ unsigned int bytes;
+ bfd_vma address;
+ bfd_byte *data;
+
+ /* Starting an S-record. */
+
+ pos = bfd_tell (abfd) - 1;
+
+ if (bfd_read (hdr, 1, 3, abfd) != 3)
+ goto error_return;
+
+ if (! ISHEX (hdr[1]) || ! ISHEX (hdr[2]))
+ {
+ if (! ISHEX (hdr[1]))
+ c = hdr[1];
+ else
+ c = hdr[2];
+ srec_bad_byte (abfd, lineno, c, error);
+ goto error_return;
+ }
+
+ bytes = HEX (hdr + 1);
+ if (bytes * 2 > bufsize)
+ {
+ if (buf != NULL)
+ free (buf);
+ buf = (bfd_byte *) bfd_malloc (bytes * 2);
+ if (buf == NULL)
+ goto error_return;
+ bufsize = bytes * 2;
+ }
+
+ if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
+ goto error_return;
+
+ /* Ignore the checksum byte. */
+ --bytes;
+
+ address = 0;
+ data = buf;
+ switch (hdr[0])
+ {
+ case '0':
+ case '5':
+ /* Prologue--ignore the file name, but stop building a
+ section at this point. */
+ sec = NULL;
+ break;
+
+ case '3':
+ address = HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '2':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '1':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ address = (address << 8) | HEX (data);
+ data += 2;
+ bytes -= 2;
+
+ if (sec != NULL
+ && sec->vma + sec->_raw_size == address)
+ {
+ /* This data goes at the end of the section we are
+ currently building. */
+ sec->_raw_size += bytes;
+ }
+ else
+ {
+ char secbuf[20];
+ char *secname;
+
+ sprintf (secbuf, ".sec%d", bfd_count_sections (abfd) + 1);
+ secname = (char *) bfd_alloc (abfd, strlen (secbuf) + 1);
+ strcpy (secname, secbuf);
+ sec = bfd_make_section (abfd, secname);
+ if (sec == NULL)
+ goto error_return;
+ sec->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
+ sec->vma = address;
+ sec->lma = address;
+ sec->_raw_size = bytes;
+ sec->filepos = pos;
+ }
+
+ break;
+
+ case '7':
+ address = HEX (data);
+ data += 2;
+ /* Fall through. */
+ case '8':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ /* Fall through. */
+ case '9':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ address = (address << 8) | HEX (data);
+ data += 2;
+
+ /* This is a termination record. */
+ abfd->start_address = address;
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+ }
+ }
+ break;
+ }
+ }
+
+ if (error)
+ goto error_return;
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Check whether an existing file is an S-record file. */
+
+static const bfd_target *
+srec_object_p (abfd)
+ bfd *abfd;
+{
+ bfd_byte b[4];
+
+ srec_init ();
+
+ 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]))
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (! srec_mkobject (abfd)
+ || ! srec_scan (abfd))
+ return NULL;
+
+ return abfd->xvec;
+}
+
+/* Check whether an existing file is an S-record file with symbols. */
+
+static const bfd_target *
+symbolsrec_object_p (abfd)
+ bfd *abfd;
+{
+ char b[2];
+
+ srec_init ();
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || bfd_read (b, 1, 2, abfd) != 2)
+ return NULL;
+
+ if (b[0] != '$' || b[1] != '$')
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ if (! srec_mkobject (abfd)
+ || ! srec_scan (abfd))
+ return NULL;
+
+ return abfd->xvec;
+}
+
+/* Read in the contents of a section in an S-record file. */
+
+static boolean
+srec_read_section (abfd, section, contents)
+ bfd *abfd;
+ asection *section;
+ bfd_byte *contents;
+{
+ int c;
+ bfd_size_type sofar = 0;
+ boolean error = false;
+ bfd_byte *buf = NULL;
+ size_t bufsize = 0;
+
+ if (bfd_seek (abfd, section->filepos, SEEK_SET) != 0)
+ goto error_return;
+
+ while ((c = srec_get_byte (abfd, &error)) != EOF)
+ {
+ bfd_byte hdr[3];
+ unsigned int bytes;
+ bfd_vma address;
+ bfd_byte *data;
+
+ if (c == '\r' || c == '\n')
+ continue;
+
+ /* This is called after srec_scan has already been called, so we
+ ought to know the exact format. */
+ BFD_ASSERT (c == 'S');
+
+ if (bfd_read (hdr, 1, 3, abfd) != 3)
+ goto error_return;
+
+ BFD_ASSERT (ISHEX (hdr[1]) && ISHEX (hdr[2]));
+
+ bytes = HEX (hdr + 1);
+
+ if (bytes * 2 > bufsize)
+ {
+ if (buf != NULL)
+ free (buf);
+ buf = (bfd_byte *) bfd_malloc (bytes * 2);
+ if (buf == NULL)
+ goto error_return;
+ bufsize = bytes * 2;
+ }
+
+ if (bfd_read (buf, 1, bytes * 2, abfd) != bytes * 2)
+ goto error_return;
+
+ address = 0;
+ data = buf;
+ switch (hdr[0])
+ {
+ default:
+ BFD_ASSERT (sofar == section->_raw_size);
+ if (buf != NULL)
+ free (buf);
+ return true;
+
+ case '3':
+ address = HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '2':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '1':
+ address = (address << 8) | HEX (data);
+ data += 2;
+ address = (address << 8) | HEX (data);
+ data += 2;
+ bytes -= 2;
+
+ if (address != section->vma + sofar)
+ {
+ /* We've come to the end of this section. */
+ BFD_ASSERT (sofar == section->_raw_size);
+ if (buf != NULL)
+ free (buf);
+ return true;
+ }
+
+ /* Don't consider checksum. */
+ --bytes;
+
+ while (bytes-- != 0)
+ {
+ contents[sofar] = HEX (data);
+ data += 2;
+ ++sofar;
+ }
+
+ break;
+ }
+ }
+
+ if (error)
+ goto error_return;
+
+ BFD_ASSERT (sofar == section->_raw_size);
+
+ if (buf != NULL)
+ free (buf);
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Get the contents of a section in an S-record file. */
+
+static boolean
+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 == NULL)
+ {
+ section->used_by_bfd = bfd_alloc (abfd, section->_raw_size);
+ if (section->used_by_bfd == NULL
+ && section->_raw_size != 0)
+ return false;
+
+ if (! srec_read_section (abfd, section, section->used_by_bfd))
+ return false;
+ }
+
+ memcpy (location, (bfd_byte *) section->used_by_bfd + offset,
+ (size_t) count);
+
+ return true;
+}
+
+/* we have to save up all the Srecords for a splurge before output */
+
+static boolean
+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;
+ register srec_data_list_type *entry;
+
+ entry = ((srec_data_list_type *)
+ bfd_alloc (abfd, sizeof (srec_data_list_type)));
+ if (entry == NULL)
+ return false;
+
+ if (bytes_to_do
+ && (section->flags & SEC_ALLOC)
+ && (section->flags & SEC_LOAD))
+ {
+ bfd_byte *data = (bfd_byte *) bfd_alloc (abfd, bytes_to_do);
+ if (data == NULL)
+ return false;
+ memcpy ((PTR) data, location, (size_t) bytes_to_do);
+
+ if ((section->lma + offset + bytes_to_do - 1) <= 0xffff)
+ {
+
+ }
+ else if ((section->lma + offset + bytes_to_do - 1) <= 0xffffff
+ && tdata->type < 2)
+ {
+ tdata->type = 2;
+ }
+ else
+ {
+ tdata->type = 3;
+ }
+
+ entry->data = data;
+ entry->where = section->lma + offset;
+ entry->size = bytes_to_do;
+
+ /* Sort the records by address. Optimize for the common case of
+ adding a record to the end of the list. */
+ if (tdata->tail != NULL
+ && entry->where >= tdata->tail->where)
+ {
+ tdata->tail->next = entry;
+ entry->next = NULL;
+ tdata->tail = entry;
+ }
+ else
+ {
+ register srec_data_list_type **look;
+
+ for (look = &tdata->head;
+ *look != NULL && (*look)->where < entry->where;
+ look = &(*look)->next)
+ ;
+ entry->next = *look;
+ *look = entry;
+ if (entry->next == NULL)
+ tdata->tail = entry;
+ }
+ }
+ 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 boolean
+srec_write_record (abfd, type, address, data, end)
+ bfd *abfd;
+ int type;
+ bfd_vma address;
+ const bfd_byte *data;
+ const bfd_byte *end;
+{
+ char buffer[MAXCHUNK];
+ unsigned int check_sum = 0;
+ CONST bfd_byte *src = data;
+ char *dst = buffer;
+ char *length;
+ bfd_size_type wrlen;
+
+ *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;
+
+ }
+ for (src = data; src < end; src++)
+ {
+ 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';
+ wrlen = dst - buffer;
+ if (bfd_write ((PTR) buffer, 1, wrlen, abfd) != wrlen)
+ return false;
+ return true;
+}
+
+
+
+static boolean
+srec_write_header (abfd)
+ bfd *abfd;
+{
+ bfd_byte buffer[MAXCHUNK];
+ bfd_byte *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++)
+ {
+ *dst++ = abfd->filename[i];
+ }
+ return srec_write_record (abfd, 0, 0, buffer, dst);
+}
+
+static boolean
+srec_write_section (abfd, tdata, list)
+ bfd *abfd;
+ tdata_type *tdata;
+ srec_data_list_type *list;
+{
+ unsigned int bytes_written = 0;
+ bfd_byte *location = list->data;
+
+ while (bytes_written < list->size)
+ {
+ bfd_vma address;
+
+ unsigned int bytes_this_chunk = list->size - bytes_written;
+
+ if (bytes_this_chunk > CHUNK)
+ {
+ bytes_this_chunk = CHUNK;
+ }
+
+ address = list->where + bytes_written;
+
+ if (! srec_write_record (abfd,
+ tdata->type,
+ address,
+ location,
+ location + bytes_this_chunk))
+ return false;
+
+ bytes_written += bytes_this_chunk;
+ location += bytes_this_chunk;
+ }
+
+ return true;
+}
+
+static boolean
+srec_write_terminator (abfd, tdata)
+ bfd *abfd;
+ tdata_type *tdata;
+{
+ bfd_byte buffer[2];
+
+ return srec_write_record (abfd, 10 - tdata->type,
+ abfd->start_address, buffer, buffer);
+}
+
+
+
+static boolean
+srec_write_symbols (abfd)
+ bfd *abfd;
+{
+ char buffer[MAXCHUNK];
+ /* Dump out the symbols of a bfd */
+ int i;
+ int count = bfd_get_symcount (abfd);
+
+ if (count)
+ {
+ size_t len;
+ asymbol **table = bfd_get_outsymbols (abfd);
+ sprintf (buffer, "$$ %s\r\n", abfd->filename);
+
+ 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);
+ 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 */
+ bfd_size_type l;
+ char buf2[40], *p;
+
+ 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;
+ }
+
+ return true;
+}
+
+static boolean
+internal_srec_write_object_contents (abfd, symbols)
+ bfd *abfd;
+ int symbols;
+{
+ tdata_type *tdata = abfd->tdata.srec_data;
+ srec_data_list_type *list;
+
+ if (symbols)
+ {
+ if (! srec_write_symbols (abfd))
+ return false;
+ }
+
+ 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)
+ bfd *abfd;
+{
+ return internal_srec_write_object_contents (abfd, 0);
+}
+
+static boolean
+symbolsrec_write_object_contents (abfd)
+ bfd *abfd;
+{
+ return internal_srec_write_object_contents (abfd, 1);
+}
+
+/*ARGSUSED*/
+static int
+srec_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return 0;
+}
+
+static asymbol *
+srec_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new)
+ new->the_bfd = abfd;
+ return new;
+}
+
+/* Return the amount of memory needed to read the symbol table. */
+
+static long
+srec_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
+}
+
+/* Return the symbol table. */
+
+static long
+srec_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ unsigned int symcount = bfd_get_symcount (abfd);
+ asymbol *csymbols;
+ unsigned int i;
+
+ csymbols = abfd->tdata.srec_data->csymbols;
+ if (csymbols == NULL)
+ {
+ asymbol *c;
+ struct srec_symbol *s;
+
+ csymbols = (asymbol *) bfd_alloc (abfd, symcount * sizeof (asymbol));
+ if (csymbols == NULL && symcount != 0)
+ return false;
+ abfd->tdata.srec_data->csymbols = csymbols;
+
+ for (s = abfd->tdata.srec_data->symbols, c = csymbols;
+ s != NULL;
+ s = s->next, ++c)
+ {
+ c->the_bfd = abfd;
+ c->name = s->name;
+ c->value = s->val;
+ c->flags = BSF_GLOBAL;
+ c->section = bfd_abs_section_ptr;
+ c->udata.p = NULL;
+ }
+ }
+
+ for (i = 0; i < symcount; i++)
+ *alocation++ = csymbols++;
+ *alocation = NULL;
+
+ return symcount;
+}
+
+/*ARGSUSED*/
+void
+srec_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+/*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);
+
+ }
+}
+
+#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_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_read_minisymbols _bfd_generic_read_minisymbols
+#define srec_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define srec_get_reloc_upper_bound \
+ ((long (*) PARAMS ((bfd *, asection *))) bfd_0l)
+#define srec_canonicalize_reloc \
+ ((long (*) PARAMS ((bfd *, asection *, arelent **, asymbol **))) bfd_0l)
+#define srec_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define srec_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+#define srec_set_arch_mach bfd_default_set_arch_mach
+
+#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_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
+#define srec_bfd_link_split_section _bfd_generic_link_split_section
+
+const bfd_target srec_vec =
+{
+ "srec", /* name */
+ bfd_target_srec_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* 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 */
+ 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 */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ {
+ 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_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 (srec),
+ BFD_JUMP_TABLE_WRITE (srec),
+ BFD_JUMP_TABLE_LINK (srec),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
+
+
+
+const bfd_target symbolsrec_vec =
+{
+ "symbolsrec", /* name */
+ bfd_target_srec_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* 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 */
+ 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 */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ {
+ 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_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 (srec),
+ BFD_JUMP_TABLE_WRITE (srec),
+ BFD_JUMP_TABLE_LINK (srec),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/stab-syms.c b/contrib/gdb/bfd/stab-syms.c
new file mode 100644
index 0000000..f4fe6c8
--- /dev/null
+++ b/contrib/gdb/bfd/stab-syms.c
@@ -0,0 +1,57 @@
+/* Table of stab names for the BFD library.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+
+#define ARCH_SIZE 32 /* Value doesn't matter. */
+#include "libaout.h"
+#include "aout/aout64.h"
+
+/* Ignore duplicate stab codes; just return the string for the first
+ one. */
+#define __define_stab(NAME, CODE, STRING) __define_name(CODE, STRING)
+#define __define_stab_duplicate(NAME, CODE, STRING)
+
+/* 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 EXTRA_SYMBOLS \
+ __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")
+
+const char *
+bfd_get_stab_name (code)
+ int code;
+{
+ switch (code)
+ {
+#define __define_name(val, str) case val: return str;
+#include "aout/stab.def"
+ EXTRA_SYMBOLS
+ }
+
+ return (const char *) 0;
+}
diff --git a/contrib/gdb/bfd/sunos.c b/contrib/gdb/bfd/sunos.c
new file mode 100644
index 0000000..77bf319
--- /dev/null
+++ b/contrib/gdb/bfd/sunos.c
@@ -0,0 +1,2767 @@
+/* BFD backend for SunOS binaries.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define TARGETNAME "a.out-sunos-big"
+#define MY(OP) CAT(sunos_big_,OP)
+
+#include "bfd.h"
+#include "bfdlink.h"
+#include "libaout.h"
+
+/* Static routines defined in this file. */
+
+static boolean sunos_read_dynamic_info PARAMS ((bfd *));
+static long sunos_get_dynamic_symtab_upper_bound PARAMS ((bfd *));
+static boolean sunos_slurp_dynamic_symtab PARAMS ((bfd *));
+static long sunos_canonicalize_dynamic_symtab PARAMS ((bfd *, asymbol **));
+static long sunos_get_dynamic_reloc_upper_bound PARAMS ((bfd *));
+static long sunos_canonicalize_dynamic_reloc
+ PARAMS ((bfd *, arelent **, asymbol **));
+static struct bfd_hash_entry *sunos_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static struct bfd_link_hash_table *sunos_link_hash_table_create
+ PARAMS ((bfd *));
+static boolean sunos_create_dynamic_sections
+ PARAMS ((bfd *, struct bfd_link_info *, boolean));
+static boolean sunos_add_dynamic_symbols
+ PARAMS ((bfd *, struct bfd_link_info *, struct external_nlist **,
+ bfd_size_type *, char **));
+static boolean sunos_add_one_symbol
+ PARAMS ((struct bfd_link_info *, bfd *, const char *, flagword, asection *,
+ bfd_vma, const char *, boolean, boolean,
+ struct bfd_link_hash_entry **));
+static boolean sunos_scan_relocs
+ PARAMS ((struct bfd_link_info *, bfd *, asection *, bfd_size_type));
+static boolean sunos_scan_std_relocs
+ PARAMS ((struct bfd_link_info *, bfd *, asection *,
+ const struct reloc_std_external *, bfd_size_type));
+static boolean sunos_scan_ext_relocs
+ PARAMS ((struct bfd_link_info *, bfd *, asection *,
+ const struct reloc_ext_external *, bfd_size_type));
+static boolean sunos_link_dynamic_object
+ PARAMS ((struct bfd_link_info *, bfd *));
+static boolean sunos_write_dynamic_symbol
+ PARAMS ((bfd *, struct bfd_link_info *, struct aout_link_hash_entry *));
+static boolean sunos_check_dynamic_reloc
+ PARAMS ((struct bfd_link_info *, bfd *, asection *,
+ struct aout_link_hash_entry *, PTR, bfd_byte *, boolean *,
+ bfd_vma *));
+static boolean sunos_finish_dynamic_link
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+#define MY_get_dynamic_symtab_upper_bound sunos_get_dynamic_symtab_upper_bound
+#define MY_canonicalize_dynamic_symtab sunos_canonicalize_dynamic_symtab
+#define MY_get_dynamic_reloc_upper_bound sunos_get_dynamic_reloc_upper_bound
+#define MY_canonicalize_dynamic_reloc sunos_canonicalize_dynamic_reloc
+#define MY_bfd_link_hash_table_create sunos_link_hash_table_create
+#define MY_add_dynamic_symbols sunos_add_dynamic_symbols
+#define MY_add_one_symbol sunos_add_one_symbol
+#define MY_link_dynamic_object sunos_link_dynamic_object
+#define MY_write_dynamic_symbol sunos_write_dynamic_symbol
+#define MY_check_dynamic_reloc sunos_check_dynamic_reloc
+#define MY_finish_dynamic_link sunos_finish_dynamic_link
+
+/* Include the usual a.out support. */
+#include "aoutf1.h"
+
+/* SunOS shared library support. We store a pointer to this structure
+ in obj_aout_dynamic_info (abfd). */
+
+struct sunos_dynamic_info
+{
+ /* Whether we found any dynamic information. */
+ boolean valid;
+ /* Dynamic information. */
+ struct internal_sun4_dynamic_link dyninfo;
+ /* Number of dynamic symbols. */
+ unsigned long dynsym_count;
+ /* Read in nlists for dynamic symbols. */
+ struct external_nlist *dynsym;
+ /* asymbol structures for dynamic symbols. */
+ aout_symbol_type *canonical_dynsym;
+ /* Read in dynamic string table. */
+ char *dynstr;
+ /* Number of dynamic relocs. */
+ unsigned long dynrel_count;
+ /* Read in dynamic relocs. This may be reloc_std_external or
+ reloc_ext_external. */
+ PTR dynrel;
+ /* arelent structures for dynamic relocs. */
+ arelent *canonical_dynrel;
+};
+
+/* The hash table of dynamic symbols is composed of two word entries.
+ See include/aout/sun4.h for details. */
+
+#define HASH_ENTRY_SIZE (2 * BYTES_IN_WORD)
+
+/* Read in the basic dynamic information. This locates the __DYNAMIC
+ structure and uses it to find the dynamic_link structure. It
+ creates and saves a sunos_dynamic_info structure. If it can't find
+ __DYNAMIC, it sets the valid field of the sunos_dynamic_info
+ structure to false to avoid doing this work again. */
+
+static boolean
+sunos_read_dynamic_info (abfd)
+ bfd *abfd;
+{
+ struct sunos_dynamic_info *info;
+ asection *dynsec;
+ bfd_vma dynoff;
+ struct external_sun4_dynamic dyninfo;
+ unsigned long dynver;
+ struct external_sun4_dynamic_link linkinfo;
+
+ if (obj_aout_dynamic_info (abfd) != (PTR) NULL)
+ return true;
+
+ if ((abfd->flags & DYNAMIC) == 0)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ info = ((struct sunos_dynamic_info *)
+ bfd_zalloc (abfd, sizeof (struct sunos_dynamic_info)));
+ if (!info)
+ return false;
+ info->valid = false;
+ info->dynsym = NULL;
+ info->dynstr = NULL;
+ info->canonical_dynsym = NULL;
+ info->dynrel = NULL;
+ info->canonical_dynrel = NULL;
+ obj_aout_dynamic_info (abfd) = (PTR) info;
+
+ /* This code used to look for the __DYNAMIC symbol to locate the dynamic
+ linking information.
+ However this inhibits recovering the dynamic symbols from a
+ stripped object file, so blindly assume that the dynamic linking
+ information is located at the start of the data section.
+ We could verify this assumption later by looking through the dynamic
+ symbols for the __DYNAMIC symbol. */
+ if ((abfd->flags & DYNAMIC) == 0)
+ return true;
+ if (! bfd_get_section_contents (abfd, obj_datasec (abfd), (PTR) &dyninfo,
+ (file_ptr) 0, sizeof dyninfo))
+ return true;
+
+ dynver = GET_WORD (abfd, dyninfo.ld_version);
+ if (dynver != 2 && dynver != 3)
+ return true;
+
+ dynoff = GET_WORD (abfd, dyninfo.ld);
+
+ /* dynoff is a virtual address. It is probably always in the .data
+ section, but this code should work even if it moves. */
+ if (dynoff < bfd_get_section_vma (abfd, obj_datasec (abfd)))
+ dynsec = obj_textsec (abfd);
+ else
+ dynsec = obj_datasec (abfd);
+ dynoff -= bfd_get_section_vma (abfd, dynsec);
+ if (dynoff > bfd_section_size (abfd, dynsec))
+ return true;
+
+ /* This executable appears to be dynamically linked in a way that we
+ can understand. */
+ if (! bfd_get_section_contents (abfd, dynsec, (PTR) &linkinfo, dynoff,
+ (bfd_size_type) sizeof linkinfo))
+ return true;
+
+ /* Swap in the dynamic link information. */
+ info->dyninfo.ld_loaded = GET_WORD (abfd, linkinfo.ld_loaded);
+ info->dyninfo.ld_need = GET_WORD (abfd, linkinfo.ld_need);
+ info->dyninfo.ld_rules = GET_WORD (abfd, linkinfo.ld_rules);
+ info->dyninfo.ld_got = GET_WORD (abfd, linkinfo.ld_got);
+ info->dyninfo.ld_plt = GET_WORD (abfd, linkinfo.ld_plt);
+ info->dyninfo.ld_rel = GET_WORD (abfd, linkinfo.ld_rel);
+ info->dyninfo.ld_hash = GET_WORD (abfd, linkinfo.ld_hash);
+ info->dyninfo.ld_stab = GET_WORD (abfd, linkinfo.ld_stab);
+ info->dyninfo.ld_stab_hash = GET_WORD (abfd, linkinfo.ld_stab_hash);
+ info->dyninfo.ld_buckets = GET_WORD (abfd, linkinfo.ld_buckets);
+ info->dyninfo.ld_symbols = GET_WORD (abfd, linkinfo.ld_symbols);
+ info->dyninfo.ld_symb_size = GET_WORD (abfd, linkinfo.ld_symb_size);
+ info->dyninfo.ld_text = GET_WORD (abfd, linkinfo.ld_text);
+ info->dyninfo.ld_plt_sz = GET_WORD (abfd, linkinfo.ld_plt_sz);
+
+ /* Reportedly the addresses need to be offset by the size of the
+ exec header in an NMAGIC file. */
+ if (adata (abfd).magic == n_magic)
+ {
+ unsigned long exec_bytes_size = adata (abfd).exec_bytes_size;
+
+ info->dyninfo.ld_need += exec_bytes_size;
+ info->dyninfo.ld_rules += exec_bytes_size;
+ info->dyninfo.ld_rel += exec_bytes_size;
+ info->dyninfo.ld_hash += exec_bytes_size;
+ info->dyninfo.ld_stab += exec_bytes_size;
+ info->dyninfo.ld_symbols += exec_bytes_size;
+ }
+
+ /* The only way to get the size of the symbol information appears to
+ be to determine the distance between it and the string table. */
+ info->dynsym_count = ((info->dyninfo.ld_symbols - info->dyninfo.ld_stab)
+ / EXTERNAL_NLIST_SIZE);
+ BFD_ASSERT (info->dynsym_count * EXTERNAL_NLIST_SIZE
+ == (unsigned long) (info->dyninfo.ld_symbols
+ - info->dyninfo.ld_stab));
+
+ /* Similarly, the relocs end at the hash table. */
+ info->dynrel_count = ((info->dyninfo.ld_hash - info->dyninfo.ld_rel)
+ / obj_reloc_entry_size (abfd));
+ BFD_ASSERT (info->dynrel_count * obj_reloc_entry_size (abfd)
+ == (unsigned long) (info->dyninfo.ld_hash
+ - info->dyninfo.ld_rel));
+
+ info->valid = true;
+
+ return true;
+}
+
+/* Return the amount of memory required for the dynamic symbols. */
+
+static long
+sunos_get_dynamic_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ struct sunos_dynamic_info *info;
+
+ if (! sunos_read_dynamic_info (abfd))
+ return -1;
+
+ info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+ if (! info->valid)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ return -1;
+ }
+
+ return (info->dynsym_count + 1) * sizeof (asymbol *);
+}
+
+/* Read the external dynamic symbols. */
+
+static boolean
+sunos_slurp_dynamic_symtab (abfd)
+ bfd *abfd;
+{
+ struct sunos_dynamic_info *info;
+
+ /* Get the general dynamic information. */
+ if (obj_aout_dynamic_info (abfd) == NULL)
+ {
+ if (! sunos_read_dynamic_info (abfd))
+ return false;
+ }
+
+ info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+ if (! info->valid)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ return false;
+ }
+
+ /* Get the dynamic nlist structures. */
+ if (info->dynsym == (struct external_nlist *) NULL)
+ {
+ info->dynsym = ((struct external_nlist *)
+ bfd_alloc (abfd,
+ (info->dynsym_count
+ * EXTERNAL_NLIST_SIZE)));
+ if (info->dynsym == NULL && info->dynsym_count != 0)
+ return false;
+ if (bfd_seek (abfd, info->dyninfo.ld_stab, SEEK_SET) != 0
+ || (bfd_read ((PTR) info->dynsym, info->dynsym_count,
+ EXTERNAL_NLIST_SIZE, abfd)
+ != info->dynsym_count * EXTERNAL_NLIST_SIZE))
+ {
+ if (info->dynsym != NULL)
+ {
+ bfd_release (abfd, info->dynsym);
+ info->dynsym = NULL;
+ }
+ return false;
+ }
+ }
+
+ /* Get the dynamic strings. */
+ if (info->dynstr == (char *) NULL)
+ {
+ info->dynstr = (char *) bfd_alloc (abfd, info->dyninfo.ld_symb_size);
+ if (info->dynstr == NULL && info->dyninfo.ld_symb_size != 0)
+ return false;
+ if (bfd_seek (abfd, info->dyninfo.ld_symbols, SEEK_SET) != 0
+ || (bfd_read ((PTR) info->dynstr, 1, info->dyninfo.ld_symb_size,
+ abfd)
+ != info->dyninfo.ld_symb_size))
+ {
+ if (info->dynstr != NULL)
+ {
+ bfd_release (abfd, info->dynstr);
+ info->dynstr = NULL;
+ }
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/* Read in the dynamic symbols. */
+
+static long
+sunos_canonicalize_dynamic_symtab (abfd, storage)
+ bfd *abfd;
+ asymbol **storage;
+{
+ struct sunos_dynamic_info *info;
+ unsigned long i;
+
+ if (! sunos_slurp_dynamic_symtab (abfd))
+ return -1;
+
+ info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+
+#ifdef CHECK_DYNAMIC_HASH
+ /* Check my understanding of the dynamic hash table by making sure
+ that each symbol can be located in the hash table. */
+ {
+ bfd_size_type table_size;
+ bfd_byte *table;
+ bfd_size_type i;
+
+ if (info->dyninfo.ld_buckets > info->dynsym_count)
+ abort ();
+ table_size = info->dyninfo.ld_stab - info->dyninfo.ld_hash;
+ table = (bfd_byte *) bfd_malloc (table_size);
+ if (table == NULL && table_size != 0)
+ abort ();
+ if (bfd_seek (abfd, info->dyninfo.ld_hash, SEEK_SET) != 0
+ || bfd_read ((PTR) table, 1, table_size, abfd) != table_size)
+ abort ();
+ for (i = 0; i < info->dynsym_count; i++)
+ {
+ unsigned char *name;
+ unsigned long hash;
+
+ name = ((unsigned char *) info->dynstr
+ + GET_WORD (abfd, info->dynsym[i].e_strx));
+ hash = 0;
+ while (*name != '\0')
+ hash = (hash << 1) + *name++;
+ hash &= 0x7fffffff;
+ hash %= info->dyninfo.ld_buckets;
+ while (GET_WORD (abfd, table + hash * HASH_ENTRY_SIZE) != i)
+ {
+ hash = GET_WORD (abfd,
+ table + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD);
+ if (hash == 0 || hash >= table_size / HASH_ENTRY_SIZE)
+ abort ();
+ }
+ }
+ free (table);
+ }
+#endif /* CHECK_DYNAMIC_HASH */
+
+ /* Get the asymbol structures corresponding to the dynamic nlist
+ structures. */
+ if (info->canonical_dynsym == (aout_symbol_type *) NULL)
+ {
+ info->canonical_dynsym = ((aout_symbol_type *)
+ bfd_alloc (abfd,
+ (info->dynsym_count
+ * sizeof (aout_symbol_type))));
+ if (info->canonical_dynsym == NULL && info->dynsym_count != 0)
+ return -1;
+
+ if (! aout_32_translate_symbol_table (abfd, info->canonical_dynsym,
+ info->dynsym, info->dynsym_count,
+ info->dynstr,
+ info->dyninfo.ld_symb_size,
+ true))
+ {
+ if (info->canonical_dynsym != NULL)
+ {
+ bfd_release (abfd, info->canonical_dynsym);
+ info->canonical_dynsym = NULL;
+ }
+ return -1;
+ }
+ }
+
+ /* Return pointers to the dynamic asymbol structures. */
+ for (i = 0; i < info->dynsym_count; i++)
+ *storage++ = (asymbol *) (info->canonical_dynsym + i);
+ *storage = NULL;
+
+ return info->dynsym_count;
+}
+
+/* Return the amount of memory required for the dynamic relocs. */
+
+static long
+sunos_get_dynamic_reloc_upper_bound (abfd)
+ bfd *abfd;
+{
+ struct sunos_dynamic_info *info;
+
+ if (! sunos_read_dynamic_info (abfd))
+ return -1;
+
+ info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+ if (! info->valid)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ return -1;
+ }
+
+ return (info->dynrel_count + 1) * sizeof (arelent *);
+}
+
+/* Read in the dynamic relocs. */
+
+static long
+sunos_canonicalize_dynamic_reloc (abfd, storage, syms)
+ bfd *abfd;
+ arelent **storage;
+ asymbol **syms;
+{
+ struct sunos_dynamic_info *info;
+ unsigned long i;
+
+ /* Get the general dynamic information. */
+ if (obj_aout_dynamic_info (abfd) == (PTR) NULL)
+ {
+ if (! sunos_read_dynamic_info (abfd))
+ return -1;
+ }
+
+ info = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+ if (! info->valid)
+ {
+ bfd_set_error (bfd_error_no_symbols);
+ return -1;
+ }
+
+ /* Get the dynamic reloc information. */
+ if (info->dynrel == NULL)
+ {
+ info->dynrel = (PTR) bfd_alloc (abfd,
+ (info->dynrel_count
+ * obj_reloc_entry_size (abfd)));
+ if (info->dynrel == NULL && info->dynrel_count != 0)
+ return -1;
+ if (bfd_seek (abfd, info->dyninfo.ld_rel, SEEK_SET) != 0
+ || (bfd_read ((PTR) info->dynrel, info->dynrel_count,
+ obj_reloc_entry_size (abfd), abfd)
+ != info->dynrel_count * obj_reloc_entry_size (abfd)))
+ {
+ if (info->dynrel != NULL)
+ {
+ bfd_release (abfd, info->dynrel);
+ info->dynrel = NULL;
+ }
+ return -1;
+ }
+ }
+
+ /* Get the arelent structures corresponding to the dynamic reloc
+ information. */
+ if (info->canonical_dynrel == (arelent *) NULL)
+ {
+ arelent *to;
+
+ info->canonical_dynrel = ((arelent *)
+ bfd_alloc (abfd,
+ (info->dynrel_count
+ * sizeof (arelent))));
+ if (info->canonical_dynrel == NULL && info->dynrel_count != 0)
+ return -1;
+
+ to = info->canonical_dynrel;
+
+ if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
+ {
+ register struct reloc_ext_external *p;
+ struct reloc_ext_external *pend;
+
+ p = (struct reloc_ext_external *) info->dynrel;
+ pend = p + info->dynrel_count;
+ for (; p < pend; p++, to++)
+ NAME(aout,swap_ext_reloc_in) (abfd, p, to, syms,
+ info->dynsym_count);
+ }
+ else
+ {
+ register struct reloc_std_external *p;
+ struct reloc_std_external *pend;
+
+ p = (struct reloc_std_external *) info->dynrel;
+ pend = p + info->dynrel_count;
+ for (; p < pend; p++, to++)
+ NAME(aout,swap_std_reloc_in) (abfd, p, to, syms,
+ info->dynsym_count);
+ }
+ }
+
+ /* Return pointers to the dynamic arelent structures. */
+ for (i = 0; i < info->dynrel_count; i++)
+ *storage++ = info->canonical_dynrel + i;
+ *storage = NULL;
+
+ return info->dynrel_count;
+}
+
+/* Code to handle linking of SunOS shared libraries. */
+
+/* A SPARC procedure linkage table entry is 12 bytes. The first entry
+ in the table is a jump which is filled in by the runtime linker.
+ The remaining entries are branches back to the first entry,
+ followed by an index into the relocation table encoded to look like
+ a sethi of %g0. */
+
+#define SPARC_PLT_ENTRY_SIZE (12)
+
+static const bfd_byte sparc_plt_first_entry[SPARC_PLT_ENTRY_SIZE] =
+{
+ /* sethi %hi(0),%g1; address filled in by runtime linker. */
+ 0x3, 0, 0, 0,
+ /* jmp %g1; offset filled in by runtime linker. */
+ 0x81, 0xc0, 0x60, 0,
+ /* nop */
+ 0x1, 0, 0, 0
+};
+
+/* save %sp, -96, %sp */
+#define SPARC_PLT_ENTRY_WORD0 0x9de3bfa0
+/* call; address filled in later. */
+#define SPARC_PLT_ENTRY_WORD1 0x40000000
+/* sethi; reloc index filled in later. */
+#define SPARC_PLT_ENTRY_WORD2 0x01000000
+
+/* This sequence is used when for the jump table entry to a defined
+ symbol in a complete executable. It is used when linking PIC
+ compiled code which is not being put into a shared library. */
+/* sethi <address to be filled in later>, %g1 */
+#define SPARC_PLT_PIC_WORD0 0x03000000
+/* jmp %g1 + <address to be filled in later> */
+#define SPARC_PLT_PIC_WORD1 0x81c06000
+/* nop */
+#define SPARC_PLT_PIC_WORD2 0x01000000
+
+/* An m68k procedure linkage table entry is 8 bytes. The first entry
+ in the table is a jump which is filled in the by the runtime
+ linker. The remaining entries are branches back to the first
+ entry, followed by a two byte index into the relocation table. */
+
+#define M68K_PLT_ENTRY_SIZE (8)
+
+static const bfd_byte m68k_plt_first_entry[M68K_PLT_ENTRY_SIZE] =
+{
+ /* jmps @# */
+ 0x4e, 0xf9,
+ /* Filled in by runtime linker with a magic address. */
+ 0, 0, 0, 0,
+ /* Not used? */
+ 0, 0
+};
+
+/* bsrl */
+#define M68K_PLT_ENTRY_WORD0 (0x61ff)
+/* Remaining words filled in later. */
+
+/* An entry in the SunOS linker hash table. */
+
+struct sunos_link_hash_entry
+{
+ struct aout_link_hash_entry root;
+
+ /* If this is a dynamic symbol, this is its index into the dynamic
+ symbol table. This is initialized to -1. As the linker looks at
+ the input files, it changes this to -2 if it will be added to the
+ dynamic symbol table. After all the input files have been seen,
+ the linker will know whether to build a dynamic symbol table; if
+ it does build one, this becomes the index into the table. */
+ long dynindx;
+
+ /* If this is a dynamic symbol, this is the index of the name in the
+ dynamic symbol string table. */
+ long dynstr_index;
+
+ /* The offset into the global offset table used for this symbol. If
+ the symbol does not require a GOT entry, this is 0. */
+ bfd_vma got_offset;
+
+ /* The offset into the procedure linkage table used for this symbol.
+ If the symbol does not require a PLT entry, this is 0. */
+ bfd_vma plt_offset;
+
+ /* Some linker flags. */
+ unsigned char flags;
+ /* Symbol is referenced by a regular object. */
+#define SUNOS_REF_REGULAR 01
+ /* Symbol is defined by a regular object. */
+#define SUNOS_DEF_REGULAR 02
+ /* Symbol is referenced by a dynamic object. */
+#define SUNOS_REF_DYNAMIC 04
+ /* Symbol is defined by a dynamic object. */
+#define SUNOS_DEF_DYNAMIC 010
+ /* Symbol is a constructor symbol in a regular object. */
+#define SUNOS_CONSTRUCTOR 020
+};
+
+/* The SunOS linker hash table. */
+
+struct sunos_link_hash_table
+{
+ struct aout_link_hash_table root;
+
+ /* The object which holds the dynamic sections. */
+ bfd *dynobj;
+
+ /* Whether we have created the dynamic sections. */
+ boolean dynamic_sections_created;
+
+ /* Whether we need the dynamic sections. */
+ boolean dynamic_sections_needed;
+
+ /* The number of dynamic symbols. */
+ size_t dynsymcount;
+
+ /* The number of buckets in the hash table. */
+ size_t bucketcount;
+
+ /* The list of dynamic objects needed by dynamic objects included in
+ the link. */
+ struct bfd_link_needed_list *needed;
+};
+
+/* Routine to create an entry in an SunOS link hash table. */
+
+static struct bfd_hash_entry *
+sunos_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct sunos_link_hash_entry *ret = (struct sunos_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct sunos_link_hash_entry *) NULL)
+ ret = ((struct sunos_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct sunos_link_hash_entry)));
+ if (ret == (struct sunos_link_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct sunos_link_hash_entry *)
+ NAME(aout,link_hash_newfunc) ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != NULL)
+ {
+ /* Set local fields. */
+ ret->dynindx = -1;
+ ret->dynstr_index = -1;
+ ret->got_offset = 0;
+ ret->plt_offset = 0;
+ ret->flags = 0;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create a SunOS link hash table. */
+
+static struct bfd_link_hash_table *
+sunos_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct sunos_link_hash_table *ret;
+
+ ret = ((struct sunos_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct sunos_link_hash_table)));
+ if (ret == (struct sunos_link_hash_table *) NULL)
+ return (struct bfd_link_hash_table *) NULL;
+ if (! NAME(aout,link_hash_table_init) (&ret->root, abfd,
+ sunos_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+
+ ret->dynobj = NULL;
+ ret->dynamic_sections_created = false;
+ ret->dynamic_sections_needed = false;
+ ret->dynsymcount = 0;
+ ret->bucketcount = 0;
+ ret->needed = NULL;
+
+ return &ret->root.root;
+}
+
+/* Look up an entry in an SunOS link hash table. */
+
+#define sunos_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct sunos_link_hash_entry *) \
+ aout_link_hash_lookup (&(table)->root, (string), (create), (copy),\
+ (follow)))
+
+/* Traverse a SunOS link hash table. */
+
+#define sunos_link_hash_traverse(table, func, info) \
+ (aout_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct aout_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the SunOS link hash table from the info structure. This is
+ just a cast. */
+
+#define sunos_hash_table(p) ((struct sunos_link_hash_table *) ((p)->hash))
+
+static boolean sunos_scan_dynamic_symbol
+ PARAMS ((struct sunos_link_hash_entry *, PTR));
+
+/* Create the dynamic sections needed if we are linking against a
+ dynamic object, or if we are linking PIC compiled code. ABFD is a
+ bfd we can attach the dynamic sections to. The linker script will
+ look for these special sections names and put them in the right
+ place in the output file. See include/aout/sun4.h for more details
+ of the dynamic linking information. */
+
+static boolean
+sunos_create_dynamic_sections (abfd, info, needed)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean needed;
+{
+ asection *s;
+
+ if (! sunos_hash_table (info)->dynamic_sections_created)
+ {
+ flagword flags;
+
+ sunos_hash_table (info)->dynobj = abfd;
+
+ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+
+ /* The .dynamic section holds the basic dynamic information: the
+ sun4_dynamic structure, the dynamic debugger information, and
+ the sun4_dynamic_link structure. */
+ s = bfd_make_section (abfd, ".dynamic");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ /* The .got section holds the global offset table. The address
+ is put in the ld_got field. */
+ s = bfd_make_section (abfd, ".got");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ /* The .plt section holds the procedure linkage table. The
+ address is put in the ld_plt field. */
+ s = bfd_make_section (abfd, ".plt");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_CODE)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ /* The .dynrel section holds the dynamic relocs. The address is
+ put in the ld_rel field. */
+ s = bfd_make_section (abfd, ".dynrel");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ /* The .hash section holds the dynamic hash table. The address
+ is put in the ld_hash field. */
+ s = bfd_make_section (abfd, ".hash");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ /* The .dynsym section holds the dynamic symbols. The address
+ is put in the ld_stab field. */
+ s = bfd_make_section (abfd, ".dynsym");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ /* The .dynstr section holds the dynamic symbol string table.
+ The address is put in the ld_symbols field. */
+ s = bfd_make_section (abfd, ".dynstr");
+ if (s == NULL
+ || ! bfd_set_section_flags (abfd, s, flags | SEC_READONLY)
+ || ! bfd_set_section_alignment (abfd, s, 2))
+ return false;
+
+ sunos_hash_table (info)->dynamic_sections_created = true;
+ }
+
+ if (needed && ! sunos_hash_table (info)->dynamic_sections_needed)
+ {
+ bfd *dynobj;
+
+ dynobj = sunos_hash_table (info)->dynobj;
+
+ s = bfd_get_section_by_name (dynobj, ".got");
+ s->_raw_size = BYTES_IN_WORD;
+
+ sunos_hash_table (info)->dynamic_sections_needed = true;
+ }
+
+ return true;
+}
+
+/* Add dynamic symbols during a link. This is called by the a.out
+ backend linker when it encounters an object with the DYNAMIC flag
+ set. */
+
+static boolean
+sunos_add_dynamic_symbols (abfd, info, symsp, sym_countp, stringsp)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ struct external_nlist **symsp;
+ bfd_size_type *sym_countp;
+ char **stringsp;
+{
+ asection *s;
+ bfd *dynobj;
+ struct sunos_dynamic_info *dinfo;
+ unsigned long need;
+
+ /* We do not want to include the sections in a dynamic object in the
+ output file. We hack by simply clobbering the list of sections
+ in the BFD. This could be handled more cleanly by, say, a new
+ section flag; the existing SEC_NEVER_LOAD flag is not the one we
+ want, because that one still implies that the section takes up
+ space in the output file. */
+ abfd->sections = NULL;
+
+ /* The native linker seems to just ignore dynamic objects when -r is
+ used. */
+ if (info->relocateable)
+ return true;
+
+ /* There's no hope of using a dynamic object which does not exactly
+ match the format of the output file. */
+ if (info->hash->creator != abfd->xvec)
+ {
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+
+ /* Make sure we have all the required information. */
+ if (! sunos_create_dynamic_sections (abfd, info, true))
+ return false;
+
+ /* Make sure we have a .need and a .rules sections. These are only
+ needed if there really is a dynamic object in the link, so they
+ are not added by sunos_create_dynamic_sections. */
+ dynobj = sunos_hash_table (info)->dynobj;
+ if (bfd_get_section_by_name (dynobj, ".need") == NULL)
+ {
+ /* The .need section holds the list of names of shared objets
+ which must be included at runtime. The address of this
+ section is put in the ld_need field. */
+ s = bfd_make_section (dynobj, ".need");
+ if (s == NULL
+ || ! bfd_set_section_flags (dynobj, s,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, s, 2))
+ return false;
+ }
+
+ if (bfd_get_section_by_name (dynobj, ".rules") == NULL)
+ {
+ /* The .rules section holds the path to search for shared
+ objects. The address of this section is put in the ld_rules
+ field. */
+ s = bfd_make_section (dynobj, ".rules");
+ if (s == NULL
+ || ! bfd_set_section_flags (dynobj, s,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY))
+ || ! bfd_set_section_alignment (dynobj, s, 2))
+ return false;
+ }
+
+ /* Pick up the dynamic symbols and return them to the caller. */
+ if (! sunos_slurp_dynamic_symtab (abfd))
+ return false;
+
+ dinfo = (struct sunos_dynamic_info *) obj_aout_dynamic_info (abfd);
+ *symsp = dinfo->dynsym;
+ *sym_countp = dinfo->dynsym_count;
+ *stringsp = dinfo->dynstr;
+
+ /* Record information about any other objects needed by this one. */
+ need = dinfo->dyninfo.ld_need;
+ while (need != 0)
+ {
+ bfd_byte buf[16];
+ unsigned long name, flags;
+ unsigned short major_vno, minor_vno;
+ struct bfd_link_needed_list *needed, **pp;
+ bfd_byte b;
+
+ if (bfd_seek (abfd, need, SEEK_SET) != 0
+ || bfd_read (buf, 1, 16, abfd) != 16)
+ return false;
+
+ /* For the format of an ld_need entry, see aout/sun4.h. We
+ should probably define structs for this manipulation. */
+
+ name = bfd_get_32 (abfd, buf);
+ flags = bfd_get_32 (abfd, buf + 4);
+ major_vno = bfd_get_16 (abfd, buf + 8);
+ minor_vno = bfd_get_16 (abfd, buf + 10);
+ need = bfd_get_32 (abfd, buf + 12);
+
+ needed = (struct bfd_link_needed_list *) bfd_alloc (abfd, sizeof (struct bfd_link_needed_list));
+ if (needed == NULL)
+ return false;
+ needed->by = abfd;
+
+ /* We return the name as [-l]name[.maj][.min]. */
+
+ if ((flags & 0x80000000) != 0)
+ bfd_alloc_grow (abfd, "-l", 2);
+ if (bfd_seek (abfd, name, SEEK_SET) != 0)
+ return false;
+ do
+ {
+ if (bfd_read (&b, 1, 1, abfd) != 1)
+ return false;
+ bfd_alloc_grow (abfd, &b, 1);
+ }
+ while (b != '\0');
+ if (major_vno != 0)
+ {
+ char verbuf[30];
+
+ sprintf (verbuf, ".%d", major_vno);
+ bfd_alloc_grow (abfd, verbuf, strlen (verbuf));
+ if (minor_vno != 0)
+ {
+ sprintf (verbuf, ".%d", minor_vno);
+ bfd_alloc_grow (abfd, verbuf, strlen (verbuf));
+ }
+ }
+ needed->name = bfd_alloc_finish (abfd);
+ if (needed->name == NULL)
+ return false;
+
+ needed->next = NULL;
+
+ for (pp = &sunos_hash_table (info)->needed;
+ *pp != NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = needed;
+ }
+
+ return true;
+}
+
+/* Function to add a single symbol to the linker hash table. This is
+ a wrapper around _bfd_generic_link_add_one_symbol which handles the
+ tweaking needed for dynamic linking support. */
+
+static boolean
+sunos_add_one_symbol (info, abfd, name, flags, section, value, string,
+ copy, collect, hashp)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ const char *name;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ const char *string;
+ boolean copy;
+ boolean collect;
+ struct bfd_link_hash_entry **hashp;
+{
+ struct sunos_link_hash_entry *h;
+ int new_flag;
+
+ if (! sunos_hash_table (info)->dynamic_sections_created)
+ {
+ /* We must create the dynamic sections while reading the input
+ files, even though at this point we don't know if any of the
+ sections will be needed. This will ensure that the dynamic
+ sections are mapped to the right output section. It does no
+ harm to create these sections if they are not needed. */
+ if (! sunos_create_dynamic_sections (abfd, info, false))
+ return false;
+ }
+
+ if ((flags & (BSF_INDIRECT | BSF_WARNING | BSF_CONSTRUCTOR)) != 0
+ || ! bfd_is_und_section (section))
+ h = sunos_link_hash_lookup (sunos_hash_table (info), name, true, copy,
+ false);
+ else
+ h = ((struct sunos_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (abfd, info, name, true, copy, false));
+ if (h == NULL)
+ return false;
+
+ if (hashp != NULL)
+ *hashp = (struct bfd_link_hash_entry *) h;
+
+ /* Treat a common symbol in a dynamic object as defined in the .bss
+ section of the dynamic object. We don't want to allocate space
+ for it in our process image. */
+ if ((abfd->flags & DYNAMIC) != 0
+ && bfd_is_com_section (section))
+ section = obj_bsssec (abfd);
+
+ if (! bfd_is_und_section (section)
+ && h->root.root.type != bfd_link_hash_new
+ && h->root.root.type != bfd_link_hash_undefined
+ && h->root.root.type != bfd_link_hash_defweak)
+ {
+ /* We are defining the symbol, and it is already defined. This
+ is a potential multiple definition error. */
+ if ((abfd->flags & DYNAMIC) != 0)
+ {
+ /* The definition we are adding is from a dynamic object.
+ We do not want this new definition to override the
+ existing definition, so we pretend it is just a
+ reference. */
+ section = bfd_und_section_ptr;
+ }
+ else if (h->root.root.type == bfd_link_hash_defined
+ && h->root.root.u.def.section->owner != NULL
+ && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
+ {
+ /* The existing definition is from a dynamic object. We
+ want to override it with the definition we just found.
+ Clobber the existing definition. */
+ h->root.root.type = bfd_link_hash_new;
+ }
+ else if (h->root.root.type == bfd_link_hash_common
+ && (h->root.root.u.c.p->section->owner->flags & DYNAMIC) != 0)
+ {
+ /* The existing definition is from a dynamic object. We
+ want to override it with the definition we just found.
+ Clobber the existing definition. We can't set it to new,
+ because it is on the undefined list. */
+ h->root.root.type = bfd_link_hash_undefined;
+ h->root.root.u.undef.abfd = h->root.root.u.c.p->section->owner;
+ }
+ }
+
+ if ((abfd->flags & DYNAMIC) != 0
+ && abfd->xvec == info->hash->creator
+ && (h->flags & SUNOS_CONSTRUCTOR) != 0)
+ {
+ /* The existing symbol is a constructor symbol, and this symbol
+ is from a dynamic object. A constructor symbol is actually a
+ definition, although the type will be bfd_link_hash_undefined
+ at this point. We want to ignore the definition from the
+ dynamic object. */
+ section = bfd_und_section_ptr;
+ }
+ else if ((flags & BSF_CONSTRUCTOR) != 0
+ && (abfd->flags & DYNAMIC) == 0
+ && h->root.root.type == bfd_link_hash_defined
+ && h->root.root.u.def.section->owner != NULL
+ && (h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
+ {
+ /* The existing symbol is defined by a dynamic object, and this
+ is a constructor symbol. As above, we want to force the use
+ of the constructor symbol from the regular object. */
+ h->root.root.type = bfd_link_hash_new;
+ }
+
+ /* Do the usual procedure for adding a symbol. */
+ if (! _bfd_generic_link_add_one_symbol (info, abfd, name, flags, section,
+ value, string, copy, collect,
+ hashp))
+ return false;
+
+ if (abfd->xvec == info->hash->creator)
+ {
+ /* Set a flag in the hash table entry indicating the type of
+ reference or definition we just found. Keep a count of the
+ number of dynamic symbols we find. A dynamic symbol is one
+ which is referenced or defined by both a regular object and a
+ shared object. */
+ if ((abfd->flags & DYNAMIC) == 0)
+ {
+ if (bfd_is_und_section (section))
+ new_flag = SUNOS_REF_REGULAR;
+ else
+ new_flag = SUNOS_DEF_REGULAR;
+ }
+ else
+ {
+ if (bfd_is_und_section (section))
+ new_flag = SUNOS_REF_DYNAMIC;
+ else
+ new_flag = SUNOS_DEF_DYNAMIC;
+ }
+ h->flags |= new_flag;
+
+ if (h->dynindx == -1
+ && (h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0)
+ {
+ ++sunos_hash_table (info)->dynsymcount;
+ h->dynindx = -2;
+ }
+
+ if ((flags & BSF_CONSTRUCTOR) != 0
+ && (abfd->flags & DYNAMIC) == 0)
+ h->flags |= SUNOS_CONSTRUCTOR;
+ }
+
+ return true;
+}
+
+/* Return the list of objects needed by BFD. */
+
+/*ARGSUSED*/
+struct bfd_link_needed_list *
+bfd_sunos_get_needed_list (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ if (info->hash->creator != &MY(vec))
+ return NULL;
+ return sunos_hash_table (info)->needed;
+}
+
+/* Record an assignment made to a symbol by a linker script. We need
+ this in case some dynamic object refers to this symbol. */
+
+boolean
+bfd_sunos_record_link_assignment (output_bfd, info, name)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ const char *name;
+{
+ struct sunos_link_hash_entry *h;
+
+ if (output_bfd->xvec != &MY(vec))
+ return true;
+
+ /* This is called after we have examined all the input objects. If
+ the symbol does not exist, it merely means that no object refers
+ to it, and we can just ignore it at this point. */
+ h = sunos_link_hash_lookup (sunos_hash_table (info), name,
+ false, false, false);
+ if (h == NULL)
+ return true;
+
+ /* In a shared library, the __DYNAMIC symbol does not appear in the
+ dynamic symbol table. */
+ if (! info->shared || strcmp (name, "__DYNAMIC") != 0)
+ {
+ h->flags |= SUNOS_DEF_REGULAR;
+
+ if (h->dynindx == -1)
+ {
+ ++sunos_hash_table (info)->dynsymcount;
+ h->dynindx = -2;
+ }
+ }
+
+ return true;
+}
+
+/* Set up the sizes and contents of the dynamic sections created in
+ sunos_add_dynamic_symbols. This is called by the SunOS linker
+ emulation before_allocation routine. We must set the sizes of the
+ sections before the linker sets the addresses of the various
+ sections. This unfortunately requires reading all the relocs so
+ that we can work out which ones need to become dynamic relocs. If
+ info->keep_memory is true, we keep the relocs in memory; otherwise,
+ we discard them, and will read them again later. */
+
+boolean
+bfd_sunos_size_dynamic_sections (output_bfd, info, sdynptr, sneedptr,
+ srulesptr)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ asection **sdynptr;
+ asection **sneedptr;
+ asection **srulesptr;
+{
+ bfd *dynobj;
+ size_t dynsymcount;
+ struct sunos_link_hash_entry *h;
+ asection *s;
+ size_t bucketcount;
+ size_t hashalloc;
+ size_t i;
+ bfd *sub;
+
+ *sdynptr = NULL;
+ *sneedptr = NULL;
+ *srulesptr = NULL;
+
+ if (output_bfd->xvec != &MY(vec))
+ return true;
+
+ /* Look through all the input BFD's and read their relocs. It would
+ be better if we didn't have to do this, but there is no other way
+ to determine the number of dynamic relocs we need, and, more
+ importantly, there is no other way to know which symbols should
+ get an entry in the procedure linkage table. */
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ if ((sub->flags & DYNAMIC) == 0
+ && sub->xvec == output_bfd->xvec)
+ {
+ if (! sunos_scan_relocs (info, sub, obj_textsec (sub),
+ exec_hdr (sub)->a_trsize)
+ || ! sunos_scan_relocs (info, sub, obj_datasec (sub),
+ exec_hdr (sub)->a_drsize))
+ return false;
+ }
+ }
+
+ dynobj = sunos_hash_table (info)->dynobj;
+ dynsymcount = sunos_hash_table (info)->dynsymcount;
+
+ /* If there were no dynamic objects in the link, and we don't need
+ to build a global offset table, there is nothing to do here. */
+ if (! sunos_hash_table (info)->dynamic_sections_needed)
+ return true;
+
+ /* If __GLOBAL_OFFSET_TABLE_ was mentioned, define it. */
+ h = sunos_link_hash_lookup (sunos_hash_table (info),
+ "__GLOBAL_OFFSET_TABLE_", false, false, false);
+ if (h != NULL && (h->flags & SUNOS_REF_REGULAR) != 0)
+ {
+ h->flags |= SUNOS_DEF_REGULAR;
+ if (h->dynindx == -1)
+ {
+ ++sunos_hash_table (info)->dynsymcount;
+ h->dynindx = -2;
+ }
+ h->root.root.type = bfd_link_hash_defined;
+ h->root.root.u.def.section = bfd_get_section_by_name (dynobj, ".got");
+ h->root.root.u.def.value = 0;
+ }
+
+ /* The .dynamic section is always the same size. */
+ s = bfd_get_section_by_name (dynobj, ".dynamic");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = (sizeof (struct external_sun4_dynamic)
+ + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE
+ + sizeof (struct external_sun4_dynamic_link));
+
+ /* Set the size of the .dynsym and .hash sections. We counted the
+ number of dynamic symbols as we read the input files. We will
+ build the dynamic symbol table (.dynsym) and the hash table
+ (.hash) when we build the final symbol table, because until then
+ we do not know the correct value to give the symbols. We build
+ the dynamic symbol string table (.dynstr) in a traversal of the
+ symbol table using sunos_scan_dynamic_symbol. */
+ s = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ s->_raw_size = dynsymcount * sizeof (struct external_nlist);
+ s->contents = (bfd_byte *) bfd_alloc (output_bfd, s->_raw_size);
+ if (s->contents == NULL && s->_raw_size != 0)
+ return false;
+
+ /* The number of buckets is just the number of symbols divided by
+ four. To compute the final size of the hash table, we must
+ actually compute the hash table. Normally we need exactly as
+ many entries in the hash table as there are dynamic symbols, but
+ if some of the buckets are not used we will need additional
+ entries. In the worst case, every symbol will hash to the same
+ bucket, and we will need BUCKETCOUNT - 1 extra entries. */
+ if (dynsymcount >= 4)
+ bucketcount = dynsymcount / 4;
+ else if (dynsymcount > 0)
+ bucketcount = dynsymcount;
+ else
+ bucketcount = 1;
+ s = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (s != NULL);
+ hashalloc = (dynsymcount + bucketcount - 1) * HASH_ENTRY_SIZE;
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, hashalloc);
+ if (s->contents == NULL && dynsymcount > 0)
+ return false;
+ memset (s->contents, 0, hashalloc);
+ for (i = 0; i < bucketcount; i++)
+ PUT_WORD (output_bfd, (bfd_vma) -1, s->contents + i * HASH_ENTRY_SIZE);
+ s->_raw_size = bucketcount * HASH_ENTRY_SIZE;
+
+ sunos_hash_table (info)->bucketcount = bucketcount;
+
+ /* Scan all the symbols, place them in the dynamic symbol table, and
+ build the dynamic hash table. We reuse dynsymcount as a counter
+ for the number of symbols we have added so far. */
+ sunos_hash_table (info)->dynsymcount = 0;
+ sunos_link_hash_traverse (sunos_hash_table (info),
+ sunos_scan_dynamic_symbol,
+ (PTR) info);
+ BFD_ASSERT (sunos_hash_table (info)->dynsymcount == dynsymcount);
+
+ /* The SunOS native linker seems to align the total size of the
+ symbol strings to a multiple of 8. I don't know if this is
+ important, but it can't hurt much. */
+ s = bfd_get_section_by_name (dynobj, ".dynstr");
+ BFD_ASSERT (s != NULL);
+ if ((s->_raw_size & 7) != 0)
+ {
+ bfd_size_type add;
+ bfd_byte *contents;
+
+ add = 8 - (s->_raw_size & 7);
+ contents = (bfd_byte *) bfd_realloc (s->contents,
+ (size_t) (s->_raw_size + add));
+ if (contents == NULL)
+ return false;
+ memset (contents + s->_raw_size, 0, (size_t) add);
+ s->contents = contents;
+ s->_raw_size += add;
+ }
+
+ /* Now that we have worked out the sizes of the procedure linkage
+ table and the dynamic relocs, allocate storage for them. */
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+ if (s->_raw_size != 0)
+ {
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ if (s->contents == NULL)
+ return false;
+
+ /* Fill in the first entry in the table. */
+ switch (bfd_get_arch (dynobj))
+ {
+ case bfd_arch_sparc:
+ memcpy (s->contents, sparc_plt_first_entry, SPARC_PLT_ENTRY_SIZE);
+ break;
+
+ case bfd_arch_m68k:
+ memcpy (s->contents, m68k_plt_first_entry, M68K_PLT_ENTRY_SIZE);
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ s = bfd_get_section_by_name (dynobj, ".dynrel");
+ if (s->_raw_size != 0)
+ {
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ if (s->contents == NULL)
+ return false;
+ }
+ /* We use the reloc_count field to keep track of how many of the
+ relocs we have output so far. */
+ s->reloc_count = 0;
+
+ /* Make space for the global offset table. */
+ s = bfd_get_section_by_name (dynobj, ".got");
+ s->contents = (bfd_byte *) bfd_alloc (dynobj, s->_raw_size);
+ if (s->contents == NULL)
+ return false;
+
+ *sdynptr = bfd_get_section_by_name (dynobj, ".dynamic");
+ *sneedptr = bfd_get_section_by_name (dynobj, ".need");
+ *srulesptr = bfd_get_section_by_name (dynobj, ".rules");
+
+ return true;
+}
+
+/* Scan the relocs for an input section. */
+
+static boolean
+sunos_scan_relocs (info, abfd, sec, rel_size)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ asection *sec;
+ bfd_size_type rel_size;
+{
+ PTR relocs;
+ PTR free_relocs = NULL;
+
+ if (rel_size == 0)
+ return true;
+
+ if (! info->keep_memory)
+ relocs = free_relocs = bfd_malloc ((size_t) rel_size);
+ else
+ {
+ struct aout_section_data_struct *n;
+
+ n = ((struct aout_section_data_struct *)
+ bfd_alloc (abfd, sizeof (struct aout_section_data_struct)));
+ if (n == NULL)
+ relocs = NULL;
+ else
+ {
+ set_aout_section_data (sec, n);
+ relocs = bfd_malloc ((size_t) rel_size);
+ aout_section_data (sec)->relocs = relocs;
+ }
+ }
+ if (relocs == NULL)
+ return false;
+
+ if (bfd_seek (abfd, sec->rel_filepos, SEEK_SET) != 0
+ || bfd_read (relocs, 1, rel_size, abfd) != rel_size)
+ goto error_return;
+
+ if (obj_reloc_entry_size (abfd) == RELOC_STD_SIZE)
+ {
+ if (! sunos_scan_std_relocs (info, abfd, sec,
+ (struct reloc_std_external *) relocs,
+ rel_size))
+ goto error_return;
+ }
+ else
+ {
+ if (! sunos_scan_ext_relocs (info, abfd, sec,
+ (struct reloc_ext_external *) relocs,
+ rel_size))
+ goto error_return;
+ }
+
+ if (free_relocs != NULL)
+ free (free_relocs);
+
+ return true;
+
+ error_return:
+ if (free_relocs != NULL)
+ free (free_relocs);
+ return false;
+}
+
+/* Scan the relocs for an input section using standard relocs. We
+ need to figure out what to do for each reloc against a dynamic
+ symbol. If the symbol is in the .text section, an entry is made in
+ the procedure linkage table. Note that this will do the wrong
+ thing if the symbol is actually data; I don't think the Sun 3
+ native linker handles this case correctly either. If the symbol is
+ not in the .text section, we must preserve the reloc as a dynamic
+ reloc. FIXME: We should also handle the PIC relocs here by
+ building global offset table entries. */
+
+static boolean
+sunos_scan_std_relocs (info, abfd, sec, relocs, rel_size)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ asection *sec;
+ const struct reloc_std_external *relocs;
+ bfd_size_type rel_size;
+{
+ bfd *dynobj;
+ asection *splt = NULL;
+ asection *srel = NULL;
+ struct sunos_link_hash_entry **sym_hashes;
+ const struct reloc_std_external *rel, *relend;
+
+ /* We only know how to handle m68k plt entries. */
+ if (bfd_get_arch (abfd) != bfd_arch_m68k)
+ {
+ bfd_set_error (bfd_error_invalid_target);
+ return false;
+ }
+
+ dynobj = NULL;
+
+ sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
+
+ relend = relocs + rel_size / RELOC_STD_SIZE;
+ for (rel = relocs; rel < relend; rel++)
+ {
+ int r_index;
+ struct sunos_link_hash_entry *h;
+
+ /* We only want relocs against external symbols. */
+ if (bfd_header_big_endian (abfd))
+ {
+ if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG) == 0)
+ continue;
+ }
+ else
+ {
+ if ((rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE) == 0)
+ continue;
+ }
+
+ /* Get the symbol index. */
+ if (bfd_header_big_endian (abfd))
+ r_index = ((rel->r_index[0] << 16)
+ | (rel->r_index[1] << 8)
+ | rel->r_index[2]);
+ else
+ r_index = ((rel->r_index[2] << 16)
+ | (rel->r_index[1] << 8)
+ | rel->r_index[0]);
+
+ /* Get the hash table entry. */
+ h = sym_hashes[r_index];
+ if (h == NULL)
+ {
+ /* This should not normally happen, but it will in any case
+ be caught in the relocation phase. */
+ continue;
+ }
+
+ /* At this point common symbols have already been allocated, so
+ we don't have to worry about them. We need to consider that
+ we may have already seen this symbol and marked it undefined;
+ if the symbol is really undefined, then SUNOS_DEF_DYNAMIC
+ will be zero. */
+ if (h->root.root.type != bfd_link_hash_defined
+ && h->root.root.type != bfd_link_hash_defweak
+ && h->root.root.type != bfd_link_hash_undefined)
+ continue;
+
+ if ((h->flags & SUNOS_DEF_DYNAMIC) == 0
+ || (h->flags & SUNOS_DEF_REGULAR) != 0)
+ continue;
+
+ if (dynobj == NULL)
+ {
+ if (! sunos_create_dynamic_sections (abfd, info, true))
+ return false;
+ dynobj = sunos_hash_table (info)->dynobj;
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ srel = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (splt != NULL && srel != NULL);
+ }
+
+ BFD_ASSERT ((h->flags & SUNOS_REF_REGULAR) != 0);
+ BFD_ASSERT (h->plt_offset != 0
+ || ((h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ ? (h->root.root.u.def.section->owner->flags
+ & DYNAMIC) != 0
+ : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
+
+ /* This reloc is against a symbol defined only by a dynamic
+ object. */
+
+ if (h->root.root.type == bfd_link_hash_undefined)
+ {
+ /* Presumably this symbol was marked as being undefined by
+ an earlier reloc. */
+ srel->_raw_size += RELOC_STD_SIZE;
+ }
+ else if ((h->root.root.u.def.section->flags & SEC_CODE) == 0)
+ {
+ bfd *sub;
+
+ /* This reloc is not in the .text section. It must be
+ copied into the dynamic relocs. We mark the symbol as
+ being undefined. */
+ srel->_raw_size += RELOC_STD_SIZE;
+ sub = h->root.root.u.def.section->owner;
+ h->root.root.type = bfd_link_hash_undefined;
+ h->root.root.u.undef.abfd = sub;
+ }
+ else
+ {
+ /* This symbol is in the .text section. We must give it an
+ entry in the procedure linkage table, if we have not
+ already done so. We change the definition of the symbol
+ to the .plt section; this will cause relocs against it to
+ be handled correctly. */
+ if (h->plt_offset == 0)
+ {
+ if (splt->_raw_size == 0)
+ splt->_raw_size = M68K_PLT_ENTRY_SIZE;
+ h->plt_offset = splt->_raw_size;
+
+ if ((h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ h->root.root.u.def.section = splt;
+ h->root.root.u.def.value = splt->_raw_size;
+ }
+
+ splt->_raw_size += M68K_PLT_ENTRY_SIZE;
+
+ /* We may also need a dynamic reloc entry. */
+ if ((h->flags & SUNOS_DEF_REGULAR) == 0)
+ srel->_raw_size += RELOC_STD_SIZE;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* Scan the relocs for an input section using extended relocs. We
+ need to figure out what to do for each reloc against a dynamic
+ symbol. If the reloc is a WDISP30, and the symbol is in the .text
+ section, an entry is made in the procedure linkage table.
+ Otherwise, we must preserve the reloc as a dynamic reloc. */
+
+static boolean
+sunos_scan_ext_relocs (info, abfd, sec, relocs, rel_size)
+ struct bfd_link_info *info;
+ bfd *abfd;
+ asection *sec;
+ const struct reloc_ext_external *relocs;
+ bfd_size_type rel_size;
+{
+ bfd *dynobj;
+ struct sunos_link_hash_entry **sym_hashes;
+ const struct reloc_ext_external *rel, *relend;
+ asection *splt = NULL;
+ asection *sgot = NULL;
+ asection *srel = NULL;
+
+ /* We only know how to handle SPARC plt entries. */
+ if (bfd_get_arch (abfd) != bfd_arch_sparc)
+ {
+ bfd_set_error (bfd_error_invalid_target);
+ return false;
+ }
+
+ dynobj = NULL;
+
+ sym_hashes = (struct sunos_link_hash_entry **) obj_aout_sym_hashes (abfd);
+
+ relend = relocs + rel_size / RELOC_EXT_SIZE;
+ for (rel = relocs; rel < relend; rel++)
+ {
+ unsigned int r_index;
+ int r_extern;
+ int r_type;
+ struct sunos_link_hash_entry *h = NULL;
+
+ /* Swap in the reloc information. */
+ if (bfd_header_big_endian (abfd))
+ {
+ 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);
+ }
+
+ if (r_extern)
+ {
+ h = sym_hashes[r_index];
+ if (h == NULL)
+ {
+ /* This should not normally happen, but it will in any
+ case be caught in the relocation phase. */
+ continue;
+ }
+ }
+
+ /* If this is a base relative reloc, we need to make an entry in
+ the .got section. */
+ if (r_type == RELOC_BASE10
+ || r_type == RELOC_BASE13
+ || r_type == RELOC_BASE22)
+ {
+ if (dynobj == NULL)
+ {
+ if (! sunos_create_dynamic_sections (abfd, info, true))
+ return false;
+ dynobj = sunos_hash_table (info)->dynobj;
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ srel = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+ }
+
+ if (r_extern)
+ {
+ if (h->got_offset != 0)
+ continue;
+
+ h->got_offset = sgot->_raw_size;
+ }
+ else
+ {
+ if (r_index >= bfd_get_symcount (abfd))
+ {
+ /* This is abnormal, but should be caught in the
+ relocation phase. */
+ continue;
+ }
+
+ if (adata (abfd).local_got_offsets == NULL)
+ {
+ adata (abfd).local_got_offsets =
+ (bfd_vma *) bfd_zalloc (abfd,
+ (bfd_get_symcount (abfd)
+ * sizeof (bfd_vma)));
+ if (adata (abfd).local_got_offsets == NULL)
+ return false;
+ }
+
+ if (adata (abfd).local_got_offsets[r_index] != 0)
+ continue;
+
+ adata (abfd).local_got_offsets[r_index] = sgot->_raw_size;
+ }
+
+ sgot->_raw_size += BYTES_IN_WORD;
+
+ /* If we are making a shared library, or if the symbol is
+ defined by a dynamic object, we will need a dynamic reloc
+ entry. */
+ if (info->shared
+ || (h != NULL
+ && (h->flags & SUNOS_DEF_DYNAMIC) != 0
+ && (h->flags & SUNOS_DEF_REGULAR) == 0))
+ srel->_raw_size += RELOC_EXT_SIZE;
+
+ continue;
+ }
+
+ /* Otherwise, we are only interested in relocs against symbols
+ defined in dynamic objects but not in regular objects. We
+ only need to consider relocs against external symbols. */
+ if (! r_extern)
+ {
+ /* But, if we are creating a shared library, we need to
+ generate an absolute reloc. */
+ if (info->shared)
+ {
+ if (dynobj == NULL)
+ {
+ if (! sunos_create_dynamic_sections (abfd, info, true))
+ return false;
+ dynobj = sunos_hash_table (info)->dynobj;
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ srel = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+ }
+
+ srel->_raw_size += RELOC_EXT_SIZE;
+ }
+
+ continue;
+ }
+
+ /* At this point common symbols have already been allocated, so
+ we don't have to worry about them. We need to consider that
+ we may have already seen this symbol and marked it undefined;
+ if the symbol is really undefined, then SUNOS_DEF_DYNAMIC
+ will be zero. */
+ if (h->root.root.type != bfd_link_hash_defined
+ && h->root.root.type != bfd_link_hash_defweak
+ && h->root.root.type != bfd_link_hash_undefined)
+ continue;
+
+ if (r_type != RELOC_JMP_TBL
+ && ! info->shared
+ && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
+ || (h->flags & SUNOS_DEF_REGULAR) != 0))
+ continue;
+
+ if (r_type == RELOC_JMP_TBL
+ && ! info->shared
+ && (h->flags & SUNOS_DEF_DYNAMIC) == 0
+ && (h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ /* This symbol is apparently undefined. Don't do anything
+ here; just let the relocation routine report an undefined
+ symbol. */
+ continue;
+ }
+
+ if (strcmp (h->root.root.root.string, "__GLOBAL_OFFSET_TABLE_") == 0)
+ continue;
+
+ if (dynobj == NULL)
+ {
+ if (! sunos_create_dynamic_sections (abfd, info, true))
+ return false;
+ dynobj = sunos_hash_table (info)->dynobj;
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+ srel = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (splt != NULL && sgot != NULL && srel != NULL);
+ }
+
+ BFD_ASSERT (r_type == RELOC_JMP_TBL
+ || info->shared
+ || (h->flags & SUNOS_REF_REGULAR) != 0);
+ BFD_ASSERT (r_type == RELOC_JMP_TBL
+ || info->shared
+ || h->plt_offset != 0
+ || ((h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ ? (h->root.root.u.def.section->owner->flags
+ & DYNAMIC) != 0
+ : (h->root.root.u.undef.abfd->flags & DYNAMIC) != 0));
+
+ /* This reloc is against a symbol defined only by a dynamic
+ object, or it is a jump table reloc from PIC compiled code. */
+
+ if (r_type != RELOC_JMP_TBL
+ && h->root.root.type == bfd_link_hash_undefined)
+ {
+ /* Presumably this symbol was marked as being undefined by
+ an earlier reloc. */
+ srel->_raw_size += RELOC_EXT_SIZE;
+ }
+ else if (r_type != RELOC_JMP_TBL
+ && (h->root.root.u.def.section->flags & SEC_CODE) == 0)
+ {
+ bfd *sub;
+
+ /* This reloc is not in the .text section. It must be
+ copied into the dynamic relocs. We mark the symbol as
+ being undefined. */
+ srel->_raw_size += RELOC_EXT_SIZE;
+ if ((h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ sub = h->root.root.u.def.section->owner;
+ h->root.root.type = bfd_link_hash_undefined;
+ h->root.root.u.undef.abfd = sub;
+ }
+ }
+ else
+ {
+ /* This symbol is in the .text section. We must give it an
+ entry in the procedure linkage table, if we have not
+ already done so. We change the definition of the symbol
+ to the .plt section; this will cause relocs against it to
+ be handled correctly. */
+ if (h->plt_offset == 0)
+ {
+ if (splt->_raw_size == 0)
+ splt->_raw_size = SPARC_PLT_ENTRY_SIZE;
+ h->plt_offset = splt->_raw_size;
+
+ if ((h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ if (h->root.root.type == bfd_link_hash_undefined)
+ h->root.root.type = bfd_link_hash_defined;
+ h->root.root.u.def.section = splt;
+ h->root.root.u.def.value = splt->_raw_size;
+ }
+
+ splt->_raw_size += SPARC_PLT_ENTRY_SIZE;
+
+ /* We will also need a dynamic reloc entry, unless this
+ is a JMP_TBL reloc produced by linking PIC compiled
+ code, and we are not making a shared library. */
+ if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
+ srel->_raw_size += RELOC_EXT_SIZE;
+ }
+
+ /* If we are creating a shared library, we need to copy over
+ any reloc other than a jump table reloc. */
+ if (info->shared && r_type != RELOC_JMP_TBL)
+ srel->_raw_size += RELOC_EXT_SIZE;
+ }
+ }
+
+ return true;
+}
+
+/* Build the hash table of dynamic symbols, and to mark as written all
+ symbols from dynamic objects which we do not plan to write out. */
+
+static boolean
+sunos_scan_dynamic_symbol (h, data)
+ struct sunos_link_hash_entry *h;
+ PTR data;
+{
+ struct bfd_link_info *info = (struct bfd_link_info *) data;
+
+ /* Set the written flag for symbols we do not want to write out as
+ part of the regular symbol table. This is all symbols which are
+ not defined in a regular object file. For some reason symbols
+ which are referenced by a regular object and defined by a dynamic
+ object do not seem to show up in the regular symbol table. It is
+ possible for a symbol to have only SUNOS_REF_REGULAR set here, it
+ is an undefined symbol which was turned into a common symbol
+ because it was found in an archive object which was not included
+ in the link. */
+ if ((h->flags & SUNOS_DEF_REGULAR) == 0
+ && (h->flags & SUNOS_DEF_DYNAMIC) != 0
+ && strcmp (h->root.root.root.string, "__DYNAMIC") != 0)
+ h->root.written = true;
+
+ /* If this symbol is defined by a dynamic object and referenced by a
+ regular object, see whether we gave it a reasonable value while
+ scanning the relocs. */
+
+ if ((h->flags & SUNOS_DEF_REGULAR) == 0
+ && (h->flags & SUNOS_DEF_DYNAMIC) != 0
+ && (h->flags & SUNOS_REF_REGULAR) != 0)
+ {
+ if ((h->root.root.type == bfd_link_hash_defined
+ || h->root.root.type == bfd_link_hash_defweak)
+ && ((h->root.root.u.def.section->owner->flags & DYNAMIC) != 0)
+ && h->root.root.u.def.section->output_section == NULL)
+ {
+ bfd *sub;
+
+ /* This symbol is currently defined in a dynamic section
+ which is not being put into the output file. This
+ implies that there is no reloc against the symbol. I'm
+ not sure why this case would ever occur. In any case, we
+ change the symbol to be undefined. */
+ sub = h->root.root.u.def.section->owner;
+ h->root.root.type = bfd_link_hash_undefined;
+ h->root.root.u.undef.abfd = sub;
+ }
+ }
+
+ /* If this symbol is defined or referenced by a regular file, add it
+ to the dynamic symbols. */
+ if ((h->flags & (SUNOS_DEF_REGULAR | SUNOS_REF_REGULAR)) != 0)
+ {
+ asection *s;
+ size_t len;
+ bfd_byte *contents;
+ unsigned char *name;
+ unsigned long hash;
+ bfd *dynobj;
+
+ BFD_ASSERT (h->dynindx == -2);
+
+ dynobj = sunos_hash_table (info)->dynobj;
+
+ h->dynindx = sunos_hash_table (info)->dynsymcount;
+ ++sunos_hash_table (info)->dynsymcount;
+
+ len = strlen (h->root.root.root.string);
+
+ /* We don't bother to construct a BFD hash table for the strings
+ which are the names of the dynamic symbols. Using a hash
+ table for the regular symbols is beneficial, because the
+ regular symbols includes the debugging symbols, which have
+ long names and are often duplicated in several object files.
+ There are no debugging symbols in the dynamic symbols. */
+ s = bfd_get_section_by_name (dynobj, ".dynstr");
+ BFD_ASSERT (s != NULL);
+ contents = (bfd_byte *) bfd_realloc (s->contents,
+ s->_raw_size + len + 1);
+ if (contents == NULL)
+ return false;
+ s->contents = contents;
+
+ h->dynstr_index = s->_raw_size;
+ strcpy (contents + s->_raw_size, h->root.root.root.string);
+ s->_raw_size += len + 1;
+
+ /* Add it to the dynamic hash table. */
+ name = (unsigned char *) h->root.root.root.string;
+ hash = 0;
+ while (*name != '\0')
+ hash = (hash << 1) + *name++;
+ hash &= 0x7fffffff;
+ hash %= sunos_hash_table (info)->bucketcount;
+
+ s = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (s != NULL);
+
+ if (GET_SWORD (dynobj, s->contents + hash * HASH_ENTRY_SIZE) == -1)
+ PUT_WORD (dynobj, h->dynindx, s->contents + hash * HASH_ENTRY_SIZE);
+ else
+ {
+ bfd_vma next;
+
+ next = GET_WORD (dynobj,
+ (s->contents
+ + hash * HASH_ENTRY_SIZE
+ + BYTES_IN_WORD));
+ PUT_WORD (dynobj, s->_raw_size / HASH_ENTRY_SIZE,
+ s->contents + hash * HASH_ENTRY_SIZE + BYTES_IN_WORD);
+ PUT_WORD (dynobj, h->dynindx, s->contents + s->_raw_size);
+ PUT_WORD (dynobj, next, s->contents + s->_raw_size + BYTES_IN_WORD);
+ s->_raw_size += HASH_ENTRY_SIZE;
+ }
+ }
+
+ return true;
+}
+
+/* Link a dynamic object. We actually don't have anything to do at
+ this point. This entry point exists to prevent the regular linker
+ code from doing anything with the object. */
+
+/*ARGSUSED*/
+static boolean
+sunos_link_dynamic_object (info, abfd)
+ struct bfd_link_info *info;
+ bfd *abfd;
+{
+ return true;
+}
+
+/* Write out a dynamic symbol. This is called by the final traversal
+ over the symbol table. */
+
+static boolean
+sunos_write_dynamic_symbol (output_bfd, info, harg)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct aout_link_hash_entry *harg;
+{
+ struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
+ int type;
+ bfd_vma val;
+ asection *s;
+ struct external_nlist *outsym;
+
+ if (h->dynindx < 0)
+ return true;
+
+ switch (h->root.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:
+ case bfd_link_hash_defweak:
+ {
+ asection *sec;
+ asection *output_section;
+
+ sec = h->root.root.u.def.section;
+ output_section = sec->output_section;
+ BFD_ASSERT (bfd_is_abs_section (output_section)
+ || output_section->owner == output_bfd);
+ if (h->plt_offset != 0
+ && (h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ type = N_UNDF | N_EXT;
+ val = 0;
+ }
+ else
+ {
+ if (output_section == obj_textsec (output_bfd))
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_TEXT
+ : N_WEAKT);
+ else if (output_section == obj_datasec (output_bfd))
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_DATA
+ : N_WEAKD);
+ else if (output_section == obj_bsssec (output_bfd))
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_BSS
+ : N_WEAKB);
+ else
+ type = (h->root.root.type == bfd_link_hash_defined
+ ? N_ABS
+ : N_WEAKA);
+ type |= N_EXT;
+ val = (h->root.root.u.def.value
+ + output_section->vma
+ + sec->output_offset);
+ }
+ }
+ break;
+ case bfd_link_hash_common:
+ type = N_UNDF | N_EXT;
+ val = h->root.root.u.c.size;
+ break;
+ case bfd_link_hash_undefweak:
+ type = N_WEAKU;
+ val = 0;
+ 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;
+ }
+
+ s = bfd_get_section_by_name (sunos_hash_table (info)->dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ outsym = ((struct external_nlist *)
+ (s->contents + h->dynindx * EXTERNAL_NLIST_SIZE));
+
+ bfd_h_put_8 (output_bfd, type, outsym->e_type);
+ bfd_h_put_8 (output_bfd, 0, outsym->e_other);
+
+ /* FIXME: The native linker doesn't use 0 for desc. It seems to use
+ one less than the desc value in the shared library, although that
+ seems unlikely. */
+ bfd_h_put_16 (output_bfd, 0, outsym->e_desc);
+
+ PUT_WORD (output_bfd, h->dynstr_index, outsym->e_strx);
+ PUT_WORD (output_bfd, val, outsym->e_value);
+
+ /* If this symbol is in the procedure linkage table, fill in the
+ table entry. */
+ if (h->plt_offset != 0)
+ {
+ bfd *dynobj;
+ asection *splt;
+ bfd_byte *p;
+ asection *s;
+ bfd_vma r_address;
+
+ dynobj = sunos_hash_table (info)->dynobj;
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ p = splt->contents + h->plt_offset;
+
+ s = bfd_get_section_by_name (dynobj, ".dynrel");
+
+ r_address = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset);
+
+ switch (bfd_get_arch (output_bfd))
+ {
+ case bfd_arch_sparc:
+ if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD0, p);
+ bfd_put_32 (output_bfd,
+ (SPARC_PLT_ENTRY_WORD1
+ + (((- (h->plt_offset + 4) >> 2)
+ & 0x3fffffff))),
+ p + 4);
+ bfd_put_32 (output_bfd, SPARC_PLT_ENTRY_WORD2 + s->reloc_count,
+ p + 8);
+ }
+ else
+ {
+ bfd_vma val;
+
+ val = (h->root.root.u.def.section->output_section->vma
+ + h->root.root.u.def.section->output_offset
+ + h->root.root.u.def.value);
+ bfd_put_32 (output_bfd,
+ SPARC_PLT_PIC_WORD0 + ((val >> 10) & 0x3fffff),
+ p);
+ bfd_put_32 (output_bfd,
+ SPARC_PLT_PIC_WORD1 + (val & 0x3ff),
+ p + 4);
+ bfd_put_32 (output_bfd, SPARC_PLT_PIC_WORD2, p + 8);
+ }
+ break;
+
+ case bfd_arch_m68k:
+ if (! info->shared && (h->flags & SUNOS_DEF_REGULAR) != 0)
+ abort ();
+ bfd_put_16 (output_bfd, M68K_PLT_ENTRY_WORD0, p);
+ bfd_put_32 (output_bfd, (- (h->plt_offset + 2)), p + 2);
+ bfd_put_16 (output_bfd, s->reloc_count, p + 6);
+ r_address += 2;
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* We also need to add a jump table reloc, unless this is the
+ result of a JMP_TBL reloc from PIC compiled code. */
+ if (info->shared || (h->flags & SUNOS_DEF_REGULAR) == 0)
+ {
+ BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
+ < s->_raw_size);
+ p = s->contents + s->reloc_count * obj_reloc_entry_size (output_bfd);
+ if (obj_reloc_entry_size (output_bfd) == RELOC_STD_SIZE)
+ {
+ struct reloc_std_external *srel;
+
+ srel = (struct reloc_std_external *) p;
+ PUT_WORD (output_bfd, r_address, srel->r_address);
+ if (bfd_header_big_endian (output_bfd))
+ {
+ srel->r_index[0] = h->dynindx >> 16;
+ srel->r_index[1] = h->dynindx >> 8;
+ srel->r_index[2] = h->dynindx;
+ srel->r_type[0] = (RELOC_STD_BITS_EXTERN_BIG
+ | RELOC_STD_BITS_JMPTABLE_BIG);
+ }
+ else
+ {
+ srel->r_index[2] = h->dynindx >> 16;
+ srel->r_index[1] = h->dynindx >> 8;
+ srel->r_index[0] = h->dynindx;
+ srel->r_type[0] = (RELOC_STD_BITS_EXTERN_LITTLE
+ | RELOC_STD_BITS_JMPTABLE_LITTLE);
+ }
+ }
+ else
+ {
+ struct reloc_ext_external *erel;
+
+ erel = (struct reloc_ext_external *) p;
+ PUT_WORD (output_bfd, r_address, erel->r_address);
+ if (bfd_header_big_endian (output_bfd))
+ {
+ erel->r_index[0] = h->dynindx >> 16;
+ erel->r_index[1] = h->dynindx >> 8;
+ erel->r_index[2] = h->dynindx;
+ erel->r_type[0] =
+ (RELOC_EXT_BITS_EXTERN_BIG
+ | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_BIG));
+ }
+ else
+ {
+ erel->r_index[2] = h->dynindx >> 16;
+ erel->r_index[1] = h->dynindx >> 8;
+ erel->r_index[0] = h->dynindx;
+ erel->r_type[0] =
+ (RELOC_EXT_BITS_EXTERN_LITTLE
+ | (RELOC_JMP_SLOT << RELOC_EXT_BITS_TYPE_SH_LITTLE));
+ }
+ PUT_WORD (output_bfd, (bfd_vma) 0, erel->r_addend);
+ }
+
+ ++s->reloc_count;
+ }
+ }
+
+ return true;
+}
+
+/* This is called for each reloc against an external symbol. If this
+ is a reloc which are are going to copy as a dynamic reloc, then
+ copy it over, and tell the caller to not bother processing this
+ reloc. */
+
+/*ARGSUSED*/
+static boolean
+sunos_check_dynamic_reloc (info, input_bfd, input_section, harg, reloc,
+ contents, skip, relocationp)
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ struct aout_link_hash_entry *harg;
+ PTR reloc;
+ bfd_byte *contents;
+ boolean *skip;
+ bfd_vma *relocationp;
+{
+ struct sunos_link_hash_entry *h = (struct sunos_link_hash_entry *) harg;
+ bfd *dynobj;
+ boolean baserel;
+ boolean jmptbl;
+ asection *s;
+ bfd_byte *p;
+ long indx;
+
+ *skip = false;
+
+ dynobj = sunos_hash_table (info)->dynobj;
+
+ if (h != NULL && h->plt_offset != 0)
+ {
+ asection *splt;
+
+ /* Redirect the relocation to the PLT entry. */
+ splt = bfd_get_section_by_name (dynobj, ".plt");
+ *relocationp = (splt->output_section->vma
+ + splt->output_offset
+ + h->plt_offset);
+ }
+
+ if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
+ {
+ struct reloc_std_external *srel;
+
+ srel = (struct reloc_std_external *) reloc;
+ if (bfd_header_big_endian (input_bfd))
+ {
+ baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
+ jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
+ }
+ else
+ {
+ baserel = (0 != (srel->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
+ jmptbl = (0 != (srel->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
+ }
+ }
+ else
+ {
+ struct reloc_ext_external *erel;
+ int r_type;
+
+ erel = (struct reloc_ext_external *) reloc;
+ if (bfd_header_big_endian (input_bfd))
+ r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
+ >> RELOC_EXT_BITS_TYPE_SH_BIG);
+ else
+ r_type = ((erel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
+ >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
+ baserel = (r_type == RELOC_BASE10
+ || r_type == RELOC_BASE13
+ || r_type == RELOC_BASE22);
+ jmptbl = r_type == RELOC_JMP_TBL;
+ }
+
+ if (baserel)
+ {
+ bfd_vma *got_offsetp;
+ asection *sgot;
+
+ if (h != NULL)
+ got_offsetp = &h->got_offset;
+ else if (adata (input_bfd).local_got_offsets == NULL)
+ got_offsetp = NULL;
+ else
+ {
+ struct reloc_std_external *srel;
+ int r_index;
+
+ srel = (struct reloc_std_external *) reloc;
+ if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
+ {
+ if (bfd_header_big_endian (input_bfd))
+ r_index = ((srel->r_index[0] << 16)
+ | (srel->r_index[1] << 8)
+ | srel->r_index[2]);
+ else
+ r_index = ((srel->r_index[2] << 16)
+ | (srel->r_index[1] << 8)
+ | srel->r_index[0]);
+ }
+ else
+ {
+ struct reloc_ext_external *erel;
+
+ erel = (struct reloc_ext_external *) reloc;
+ if (bfd_header_big_endian (input_bfd))
+ r_index = ((erel->r_index[0] << 16)
+ | (erel->r_index[1] << 8)
+ | erel->r_index[2]);
+ else
+ r_index = ((erel->r_index[2] << 16)
+ | (erel->r_index[1] << 8)
+ | erel->r_index[0]);
+ }
+
+ got_offsetp = adata (input_bfd).local_got_offsets + r_index;
+ }
+
+ BFD_ASSERT (got_offsetp != NULL && *got_offsetp != 0);
+
+ sgot = bfd_get_section_by_name (dynobj, ".got");
+
+ /* We set the least significant bit to indicate whether we have
+ already initialized the GOT entry. */
+ if ((*got_offsetp & 1) == 0)
+ {
+ if (h == NULL
+ || (! info->shared
+ && ((h->flags & SUNOS_DEF_DYNAMIC) == 0
+ || (h->flags & SUNOS_DEF_REGULAR) != 0)))
+ PUT_WORD (dynobj, *relocationp, sgot->contents + *got_offsetp);
+ else
+ PUT_WORD (dynobj, 0, sgot->contents + *got_offsetp);
+
+ if (info->shared
+ || (h != NULL
+ && (h->flags & SUNOS_DEF_DYNAMIC) != 0
+ && (h->flags & SUNOS_DEF_REGULAR) == 0))
+ {
+ /* We need to create a GLOB_DAT or 32 reloc to tell the
+ dynamic linker to fill in this entry in the table. */
+
+ s = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (s != NULL);
+ BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj)
+ < s->_raw_size);
+
+ p = (s->contents
+ + s->reloc_count * obj_reloc_entry_size (dynobj));
+
+ if (h != NULL)
+ indx = h->dynindx;
+ else
+ indx = 0;
+
+ if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
+ {
+ struct reloc_std_external *srel;
+
+ srel = (struct reloc_std_external *) p;
+ PUT_WORD (dynobj,
+ (*got_offsetp
+ + sgot->output_section->vma
+ + sgot->output_offset),
+ srel->r_address);
+ if (bfd_header_big_endian (dynobj))
+ {
+ srel->r_index[0] = indx >> 16;
+ srel->r_index[1] = indx >> 8;
+ srel->r_index[2] = indx;
+ if (h == NULL)
+ srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_BIG;
+ else
+ srel->r_type[0] =
+ (RELOC_STD_BITS_EXTERN_BIG
+ | RELOC_STD_BITS_BASEREL_BIG
+ | RELOC_STD_BITS_RELATIVE_BIG
+ | (2 << RELOC_STD_BITS_LENGTH_SH_BIG));
+ }
+ else
+ {
+ srel->r_index[2] = indx >> 16;
+ srel->r_index[1] = indx >> 8;
+ srel->r_index[0] = indx;
+ if (h == NULL)
+ srel->r_type[0] = 2 << RELOC_STD_BITS_LENGTH_SH_LITTLE;
+ else
+ srel->r_type[0] =
+ (RELOC_STD_BITS_EXTERN_LITTLE
+ | RELOC_STD_BITS_BASEREL_LITTLE
+ | RELOC_STD_BITS_RELATIVE_LITTLE
+ | (2 << RELOC_STD_BITS_LENGTH_SH_LITTLE));
+ }
+ }
+ else
+ {
+ struct reloc_ext_external *erel;
+
+ erel = (struct reloc_ext_external *) p;
+ PUT_WORD (dynobj,
+ (*got_offsetp
+ + sgot->output_section->vma
+ + sgot->output_offset),
+ erel->r_address);
+ if (bfd_header_big_endian (dynobj))
+ {
+ erel->r_index[0] = indx >> 16;
+ erel->r_index[1] = indx >> 8;
+ erel->r_index[2] = indx;
+ if (h == NULL)
+ erel->r_type[0] =
+ RELOC_32 << RELOC_EXT_BITS_TYPE_SH_BIG;
+ else
+ erel->r_type[0] =
+ (RELOC_EXT_BITS_EXTERN_BIG
+ | (RELOC_GLOB_DAT << RELOC_EXT_BITS_TYPE_SH_BIG));
+ }
+ else
+ {
+ erel->r_index[2] = indx >> 16;
+ erel->r_index[1] = indx >> 8;
+ erel->r_index[0] = indx;
+ if (h == NULL)
+ erel->r_type[0] =
+ RELOC_32 << RELOC_EXT_BITS_TYPE_SH_LITTLE;
+ else
+ erel->r_type[0] =
+ (RELOC_EXT_BITS_EXTERN_LITTLE
+ | (RELOC_GLOB_DAT
+ << RELOC_EXT_BITS_TYPE_SH_LITTLE));
+ }
+ PUT_WORD (dynobj, 0, erel->r_addend);
+ }
+
+ ++s->reloc_count;
+ }
+
+ *got_offsetp |= 1;
+ }
+
+ *relocationp = sgot->vma + (*got_offsetp &~ 1);
+
+ /* There is nothing else to do for a base relative reloc. */
+ return true;
+ }
+
+ if (! sunos_hash_table (info)->dynamic_sections_needed)
+ return true;
+ if (! info->shared)
+ {
+ if (h == NULL
+ || h->dynindx == -1
+ || h->root.root.type != bfd_link_hash_undefined
+ || (h->flags & SUNOS_DEF_REGULAR) != 0
+ || (h->flags & SUNOS_DEF_DYNAMIC) == 0
+ || (h->root.root.u.undef.abfd->flags & DYNAMIC) == 0)
+ return true;
+ }
+ else
+ {
+ if (h != NULL
+ && (h->dynindx == -1
+ || jmptbl
+ || strcmp (h->root.root.root.string,
+ "__GLOBAL_OFFSET_TABLE_") == 0))
+ return true;
+ }
+
+ /* It looks like this is a reloc we are supposed to copy. */
+
+ s = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (s != NULL);
+ BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) < s->_raw_size);
+
+ p = s->contents + s->reloc_count * obj_reloc_entry_size (dynobj);
+
+ /* Copy the reloc over. */
+ memcpy (p, reloc, obj_reloc_entry_size (dynobj));
+
+ if (h != NULL)
+ indx = h->dynindx;
+ else
+ indx = 0;
+
+ /* Adjust the address and symbol index. */
+ if (obj_reloc_entry_size (dynobj) == RELOC_STD_SIZE)
+ {
+ struct reloc_std_external *srel;
+
+ srel = (struct reloc_std_external *) p;
+ PUT_WORD (dynobj,
+ (GET_WORD (dynobj, srel->r_address)
+ + input_section->output_section->vma
+ + input_section->output_offset),
+ srel->r_address);
+ if (bfd_header_big_endian (dynobj))
+ {
+ srel->r_index[0] = indx >> 16;
+ srel->r_index[1] = indx >> 8;
+ srel->r_index[2] = indx;
+ }
+ else
+ {
+ srel->r_index[2] = indx >> 16;
+ srel->r_index[1] = indx >> 8;
+ srel->r_index[0] = indx;
+ }
+ }
+ else
+ {
+ struct reloc_ext_external *erel;
+
+ erel = (struct reloc_ext_external *) p;
+ PUT_WORD (dynobj,
+ (GET_WORD (dynobj, erel->r_address)
+ + input_section->output_section->vma
+ + input_section->output_offset),
+ erel->r_address);
+ if (bfd_header_big_endian (dynobj))
+ {
+ erel->r_index[0] = indx >> 16;
+ erel->r_index[1] = indx >> 8;
+ erel->r_index[2] = indx;
+ }
+ else
+ {
+ erel->r_index[2] = indx >> 16;
+ erel->r_index[1] = indx >> 8;
+ erel->r_index[0] = indx;
+ }
+ }
+
+ ++s->reloc_count;
+
+ if (h != NULL)
+ *skip = true;
+
+ return true;
+}
+
+/* Finish up the dynamic linking information. */
+
+static boolean
+sunos_finish_dynamic_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ bfd *dynobj;
+ asection *o;
+ asection *s;
+ asection *sdyn;
+ struct external_sun4_dynamic esd;
+ struct external_sun4_dynamic_link esdl;
+
+ if (! sunos_hash_table (info)->dynamic_sections_needed)
+ return true;
+
+ dynobj = sunos_hash_table (info)->dynobj;
+
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+ BFD_ASSERT (sdyn != NULL);
+
+ /* Finish up the .need section. The linker emulation code filled it
+ in, but with offsets from the start of the section instead of
+ real addresses. Now that we know the section location, we can
+ fill in the final values. */
+ s = bfd_get_section_by_name (dynobj, ".need");
+ if (s != NULL && s->_raw_size != 0)
+ {
+ file_ptr filepos;
+ bfd_byte *p;
+
+ filepos = s->output_section->filepos + s->output_offset;
+ p = s->contents;
+ while (1)
+ {
+ bfd_vma val;
+
+ PUT_WORD (dynobj, GET_WORD (dynobj, p) + filepos, p);
+ val = GET_WORD (dynobj, p + 12);
+ if (val == 0)
+ break;
+ PUT_WORD (dynobj, val + filepos, p + 12);
+ p += 16;
+ }
+ }
+
+ /* The first entry in the .got section is the address of the
+ dynamic information, unless this is a shared library. */
+ s = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (s != NULL);
+ if (info->shared)
+ PUT_WORD (dynobj, 0, s->contents);
+ else
+ PUT_WORD (dynobj, sdyn->output_section->vma + sdyn->output_offset,
+ s->contents);
+
+ for (o = dynobj->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_HAS_CONTENTS) != 0
+ && o->contents != NULL)
+ {
+ BFD_ASSERT (o->output_section != NULL
+ && o->output_section->owner == abfd);
+ if (! bfd_set_section_contents (abfd, o->output_section,
+ o->contents, o->output_offset,
+ o->_raw_size))
+ return false;
+ }
+ }
+
+ /* Finish up the dynamic link information. */
+ PUT_WORD (dynobj, (bfd_vma) 3, esd.ld_version);
+ PUT_WORD (dynobj,
+ sdyn->output_section->vma + sdyn->output_offset + sizeof esd,
+ esd.ldd);
+ PUT_WORD (dynobj,
+ (sdyn->output_section->vma
+ + sdyn->output_offset
+ + sizeof esd
+ + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE),
+ esd.ld);
+
+ if (! bfd_set_section_contents (abfd, sdyn->output_section, &esd,
+ sdyn->output_offset, sizeof esd))
+ return false;
+
+
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_loaded);
+
+ s = bfd_get_section_by_name (dynobj, ".need");
+ if (s == NULL || s->_raw_size == 0)
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_need);
+ else
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_need);
+
+ s = bfd_get_section_by_name (dynobj, ".rules");
+ if (s == NULL || s->_raw_size == 0)
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_rules);
+ else
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_rules);
+
+ s = bfd_get_section_by_name (dynobj, ".got");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->vma + s->output_offset, esdl.ld_got);
+
+ s = bfd_get_section_by_name (dynobj, ".plt");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->vma + s->output_offset, esdl.ld_plt);
+ PUT_WORD (dynobj, s->_raw_size, esdl.ld_plt_sz);
+
+ s = bfd_get_section_by_name (dynobj, ".dynrel");
+ BFD_ASSERT (s != NULL);
+ BFD_ASSERT (s->reloc_count * obj_reloc_entry_size (dynobj) == s->_raw_size);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_rel);
+
+ s = bfd_get_section_by_name (dynobj, ".hash");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_hash);
+
+ s = bfd_get_section_by_name (dynobj, ".dynsym");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_stab);
+
+ PUT_WORD (dynobj, (bfd_vma) 0, esdl.ld_stab_hash);
+
+ PUT_WORD (dynobj, (bfd_vma) sunos_hash_table (info)->bucketcount,
+ esdl.ld_buckets);
+
+ s = bfd_get_section_by_name (dynobj, ".dynstr");
+ BFD_ASSERT (s != NULL);
+ PUT_WORD (dynobj, s->output_section->filepos + s->output_offset,
+ esdl.ld_symbols);
+ PUT_WORD (dynobj, s->_raw_size, esdl.ld_symb_size);
+
+ /* The size of the text area is the size of the .text section
+ rounded up to a page boundary. FIXME: Should the page size be
+ conditional on something? */
+ PUT_WORD (dynobj,
+ BFD_ALIGN (obj_textsec (abfd)->_raw_size, 0x2000),
+ esdl.ld_text);
+
+ if (! bfd_set_section_contents (abfd, sdyn->output_section, &esdl,
+ (sdyn->output_offset
+ + sizeof esd
+ + EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE),
+ sizeof esdl))
+ return false;
+
+ abfd->flags |= DYNAMIC;
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/syms.c b/contrib/gdb/bfd/syms.c
new file mode 100644
index 0000000..e3007e4
--- /dev/null
+++ b/contrib/gdb/bfd/syms.c
@@ -0,0 +1,1084 @@
+/* Generic symbol-table support for the BFD library.
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SECTION
+ Symbols
+
+ 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 <<asymbol>> 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 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 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
+ made. Then the BFD back end fills in a table provided by the
+ application with pointers to the canonical information. To
+ output symbols, the application provides BFD with a table of
+ pointers to pointers to <<asymbol>>s. This allows applications
+ 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::
+@* Mini Symbols::
+@* typedef asymbol::
+@* symbol handling functions::
+@end menu
+
+INODE
+Reading Symbols, Writing Symbols, Symbols, Symbols
+SUBSECTION
+ Reading symbols
+
+ 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 application which reads the symbol table:
+
+| long storage_needed;
+| asymbol **symbol_table;
+| 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 **) xmalloc (storage_needed);
+| ...
+| 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; it is freed when the BFD is closed.
+
+
+INODE
+Writing Symbols, Mini Symbols, Reading Symbols, Symbols
+SUBSECTION
+ 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 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 <<bfd_make_empty_symbol>>. Here is an
+ example showing the creation of a symbol table with only one element:
+
+| #include "bfd.h"
+| 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);
+| new->name = "dummy_symbol";
+| 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
+| nm foo
+| 00012345 A dummy_symbol
+
+ Many formats cannot represent arbitary symbol information; for
+ instance, the <<a.out>> 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.
+
+INODE
+Mini Symbols, typedef asymbol, Writing Symbols, Symbols
+SUBSECTION
+ Mini Symbols
+
+ Mini symbols provide read-only access to the symbol table.
+ They use less memory space, but require more time to access.
+ They can be useful for tools like nm or objdump, which may
+ have to handle symbol tables of extremely large executables.
+
+ The <<bfd_read_minisymbols>> function will read the symbols
+ into memory in an internal form. It will return a <<void *>>
+ pointer to a block of memory, a symbol count, and the size of
+ each symbol. The pointer is allocated using <<malloc>>, and
+ should be freed by the caller when it is no longer needed.
+
+ The function <<bfd_minisymbol_to_symbol>> will take a pointer
+ to a minisymbol, and a pointer to a structure returned by
+ <<bfd_make_empty_symbol>>, and return a <<asymbol>> structure.
+ The return value may or may not be the same as the value from
+ <<bfd_make_empty_symbol>> which was passed in.
+
+*/
+
+
+
+/*
+DOCDD
+INODE
+typedef asymbol, symbol handling functions, Mini Symbols, Symbols
+
+*/
+/*
+SUBSECTION
+ typedef asymbol
+
+ An <<asymbol>> has the form:
+
+*/
+
+/*
+CODE_FRAGMENT
+
+.
+.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
+. information (invisible to the application writer) is carried
+. with the symbol.
+.
+. This field is *almost* redundant, since you can use section->owner
+. instead, except that some symbols point to the global sections
+. bfd_{abs,com,und}_section. This could be fixed by making
+. these globals be per-bfd (or per-target-flavor). FIXME. *}
+.
+. 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
+. application may not alter it. *}
+. CONST char *name;
+.
+. {* The value of the symbol. This really should be a union of a
+. numeric value with a pointer, since some flags indicate that
+. a pointer to another symbol is stored here. *}
+. symvalue value;
+.
+. {* Attributes of a symbol: *}
+.
+.#define BSF_NO_FLAGS 0x00
+.
+. {* The symbol has local scope; <<static>> in <<C>>. The value
+. is the offset into the section of the data. *}
+.#define BSF_LOCAL 0x01
+.
+. {* The symbol has global scope; initialized data in <<C>>. The
+. 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 offset into the section of the data. *}
+.#define BSF_EXPORT BSF_GLOBAL {* no real difference *}
+.
+. {* A normal C symbol would be one of:
+. <<BSF_LOCAL>>, <<BSF_FORT_COMM>>, <<BSF_UNDEFINED>> or
+. <<BSF_GLOBAL>> *}
+.
+. {* The symbol is a debugging record. The value has an arbitary
+. meaning. *}
+.#define BSF_DEBUGGING 0x08
+.
+. {* The symbol denotes a function entry point. Used in ELF,
+. perhaps others someday. *}
+.#define BSF_FUNCTION 0x10
+.
+. {* Used by the linker. *}
+.#define BSF_KEEP 0x20
+.#define BSF_KEEP_G 0x40
+.
+. {* A weak global symbol, overridable without warnings by
+. a regular global symbol of the same name. *}
+.#define BSF_WEAK 0x80
+.
+. {* This symbol was created to point to a section, e.g. ELF's
+. STT_SECTION symbols. *}
+.#define BSF_SECTION_SYM 0x100
+.
+. {* The symbol used to be a common symbol, but now it is
+. allocated. *}
+.#define BSF_OLD_COMMON 0x200
+.
+. {* The default value for common data. *}
+.#define BFD_FORT_COMM_DEFAULT_VALUE 0
+.
+. {* In some files the type of a symbol sometimes alters its
+. location in an output file - ie in coff a <<ISFCN>> symbol
+. which is also <<C_EXT>> symbol appears where it was
+. declared and not at the end of a section. This bit is set
+. by the target BFD part to convey this information. *}
+.
+.#define BSF_NOT_AT_END 0x400
+.
+. {* Signal that the symbol is the label of constructor section. *}
+.#define BSF_CONSTRUCTOR 0x800
+.
+. {* Signal that the symbol is a warning symbol. The name is a
+. warning. The name of the next symbol is the one to warn about;
+. if a reference is made to a symbol with the same name as the next
+. symbol, a warning is issued by the linker. *}
+.#define BSF_WARNING 0x1000
+.
+. {* Signal that the symbol is indirect. This symbol is an indirect
+. pointer to the symbol with the same name as the next symbol. *}
+.#define BSF_INDIRECT 0x2000
+.
+. {* BSF_FILE marks symbols that contain a file name. This is used
+. for ELF STT_FILE symbols. *}
+.#define BSF_FILE 0x4000
+.
+. {* Symbol is from dynamic linking information. *}
+.#define BSF_DYNAMIC 0x8000
+.
+. {* The symbol denotes a data object. Used in ELF, and perhaps
+. others someday. *}
+.#define BSF_OBJECT 0x10000
+.
+. flagword flags;
+.
+. {* 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;
+.
+. {* Back end special data. *}
+. union
+. {
+. PTR p;
+. bfd_vma i;
+. } udata;
+.
+.} asymbol;
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "bfdlink.h"
+#include "aout/stab_gnu.h"
+
+/*
+DOCDD
+INODE
+symbol handling functions, , typedef asymbol, Symbols
+SUBSECTION
+ Symbol handling functions
+*/
+
+/*
+FUNCTION
+ bfd_get_symtab_upper_bound
+
+DESCRIPTION
+ Return the number of bytes required to store a vector of pointers
+ to <<asymbols>> for all the symbols in the BFD @var{abfd},
+ including a terminal NULL pointer. If there are no symbols in
+ the BFD, then return 0. If an error occurs, return -1.
+
+.#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
+ 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.
+
+
+.#define bfd_canonicalize_symtab(abfd, location) \
+. BFD_SEND (abfd, _bfd_canonicalize_symtab,\
+. (abfd, location))
+
+*/
+
+
+/*
+FUNCTION
+ bfd_set_symtab
+
+SYNOPSIS
+ 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
+bfd_set_symtab (abfd, location, symcount)
+ bfd *abfd;
+ asymbol **location;
+ unsigned int symcount;
+{
+ 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;
+ return true;
+}
+
+/*
+FUNCTION
+ bfd_print_symbol_vandf
+
+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
+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);
+ }
+
+ /* This presumes that a symbol can not be both BSF_DEBUGGING and
+ BSF_DYNAMIC, nor more than one of BSF_FUNCTION, BSF_FILE, and
+ BSF_OBJECT. */
+ fprintf (file, " %c%c%c%c%c%c%c",
+ ((type & BSF_LOCAL)
+ ? (type & BSF_GLOBAL) ? '!' : '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' : ' ',
+ ((type & BSF_FUNCTION)
+ ? 'F'
+ : ((type & BSF_FILE)
+ ? 'f'
+ : ((type & BSF_OBJECT) ? 'O' : ' '))));
+}
+
+
+/*
+FUNCTION
+ bfd_make_empty_symbol
+
+DESCRIPTION
+ Create a new <<asymbol>> structure for the BFD @var{abfd}
+ and return a pointer to it.
+
+ This routine is necessary because each back end has private
+ information surrounding the <<asymbol>>. Building your own
+ <<asymbol>> and pointing to it will not create the private
+ information, and will cause problems later on.
+
+.#define bfd_make_empty_symbol(abfd) \
+. BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd))
+*/
+
+/*
+FUNCTION
+ bfd_make_debug_symbol
+
+DESCRIPTION
+ Create a new <<asymbol>> structure for the BFD @var{abfd},
+ to be used as a debugging symbol. Further details of its use have
+ yet to be worked out.
+
+.#define bfd_make_debug_symbol(abfd,ptr,size) \
+. BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size))
+*/
+
+struct section_to_type
+{
+ CONST char *section;
+ char type;
+};
+
+/* 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[] =
+{
+ {"*DEBUG*", 'N'},
+ {".bss", 'b'},
+ {"zerovars", 'b'}, /* MRI .bss */
+ {".data", 'd'},
+ {"vars", 'd'}, /* MRI .data */
+ {".rdata", 'r'}, /* Read only data. */
+ {".rodata", 'r'}, /* Read only data. */
+ {".sbss", 's'}, /* Small BSS (uninitialized data). */
+ {".scommon", 'c'}, /* Small common. */
+ {".sdata", 'g'}, /* Small initialized data. */
+ {".text", 't'},
+ {"code", 't'}, /* MRI .text */
+ {0, 0}
+};
+
+/* Return the single-character symbol type corresponding to
+ section S, or '?' for an unknown COFF section.
+
+ Check for any leading string which matches, so .text5 returns
+ 't' as well as .text */
+
+static char
+coff_section_type (s)
+ char *s;
+{
+ CONST struct section_to_type *t;
+
+ for (t = &stt[0]; t->section; t++)
+ if (!strncmp (s, t->section, strlen (t->section)))
+ return t->type;
+
+ return '?';
+}
+
+#ifndef islower
+#define islower(c) ((c) >= 'a' && (c) <= 'z')
+#endif
+#ifndef toupper
+#define toupper(c) (islower(c) ? ((c) & ~0x20) : (c))
+#endif
+
+/*
+FUNCTION
+ bfd_decode_symclass
+
+DESCRIPTION
+ Return a character corresponding to the symbol
+ class of @var{symbol}, or '?' for an unknown class.
+
+SYNOPSIS
+ int bfd_decode_symclass(asymbol *symbol);
+*/
+int
+bfd_decode_symclass (symbol)
+ asymbol *symbol;
+{
+ char c;
+
+ if (bfd_is_com_section (symbol->section))
+ return 'C';
+ if (bfd_is_und_section (symbol->section))
+ return 'U';
+ if (bfd_is_ind_section (symbol->section))
+ return 'I';
+ if (symbol->flags & BSF_WEAK)
+ return 'W';
+ if (!(symbol->flags & (BSF_GLOBAL | BSF_LOCAL)))
+ return '?';
+
+ if (bfd_is_abs_section (symbol->section))
+ c = 'a';
+ else if (symbol->section)
+ c = coff_section_type (symbol->section->name);
+ else
+ return '?';
+ if (symbol->flags & BSF_GLOBAL)
+ c = toupper (c);
+ return c;
+
+ /* We don't have to handle these cases just yet, but we will soon:
+ N_SETV: 'v';
+ N_SETA: 'l';
+ N_SETT: 'x';
+ N_SETD: 'z';
+ N_SETB: 's';
+ N_INDR: 'i';
+ */
+}
+
+/*
+FUNCTION
+ bfd_symbol_info
+
+DESCRIPTION
+ Fill in the basic info about symbol that nm needs.
+ Additional info may be added by the back-ends after
+ calling this function.
+
+SYNOPSIS
+ void bfd_symbol_info(asymbol *symbol, symbol_info *ret);
+*/
+
+void
+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;
+ else
+ ret->value = 0;
+ ret->name = symbol->name;
+}
+
+void
+bfd_symbol_is_absolute ()
+{
+ abort ();
+}
+
+/*
+FUNCTION
+ bfd_copy_private_symbol_data
+
+SYNOPSIS
+ boolean bfd_copy_private_symbol_data(bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym);
+
+DESCRIPTION
+ Copy private symbol information from @var{isym} in the BFD
+ @var{ibfd} to the symbol @var{osym} in the BFD @var{obfd}.
+ Return <<true>> on success, <<false>> on error. Possible error
+ returns are:
+
+ o <<bfd_error_no_memory>> -
+ Not enough memory exists to create private data for @var{osec}.
+
+.#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \
+. BFD_SEND (ibfd, _bfd_copy_private_symbol_data, \
+. (ibfd, isymbol, obfd, osymbol))
+
+*/
+
+/* The generic version of the function which returns mini symbols.
+ This is used when the backend does not provide a more efficient
+ version. It just uses BFD asymbol structures as mini symbols. */
+
+long
+_bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep)
+ bfd *abfd;
+ boolean dynamic;
+ PTR *minisymsp;
+ unsigned int *sizep;
+{
+ long storage;
+ asymbol **syms = NULL;
+ long symcount;
+
+ if (dynamic)
+ storage = bfd_get_dynamic_symtab_upper_bound (abfd);
+ else
+ storage = bfd_get_symtab_upper_bound (abfd);
+ if (storage < 0)
+ goto error_return;
+
+ syms = (asymbol **) bfd_malloc ((size_t) storage);
+ if (syms == NULL)
+ goto error_return;
+
+ if (dynamic)
+ symcount = bfd_canonicalize_dynamic_symtab (abfd, syms);
+ else
+ symcount = bfd_canonicalize_symtab (abfd, syms);
+ if (symcount < 0)
+ goto error_return;
+
+ *minisymsp = (PTR) syms;
+ *sizep = sizeof (asymbol *);
+ return symcount;
+
+ error_return:
+ if (syms != NULL)
+ free (syms);
+ return -1;
+}
+
+/* The generic version of the function which converts a minisymbol to
+ an asymbol. We don't worry about the sym argument we are passed;
+ we just return the asymbol the minisymbol points to. */
+
+/*ARGSUSED*/
+asymbol *
+_bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym)
+ bfd *abfd;
+ boolean dynamic;
+ const PTR minisym;
+ asymbol *sym;
+{
+ return *(asymbol **) minisym;
+}
+
+/* Look through stabs debugging information in .stab and .stabstr
+ sections to find the source file and line closest to a desired
+ location. This is used by COFF and ELF targets. It sets *pfound
+ to true if it finds some information. The *pinfo field is used to
+ pass cached information in and out of this routine; this first time
+ the routine is called for a BFD, *pinfo should be NULL. The value
+ placed in *pinfo should be saved with the BFD, and passed back each
+ time this function is called. */
+
+/* A pointer to this structure is stored in *pinfo. */
+
+struct stab_find_info
+{
+ /* The .stab section. */
+ asection *stabsec;
+ /* The .stabstr section. */
+ asection *strsec;
+ /* The contents of the .stab section. */
+ bfd_byte *stabs;
+ /* The contents of the .stabstr section. */
+ bfd_byte *strs;
+ /* An malloc buffer to hold the file name. */
+ char *filename;
+ /* Cached values to restart quickly. */
+ bfd_vma cached_offset;
+ bfd_byte *cached_stab;
+ bfd_byte *cached_str;
+ bfd_size_type cached_stroff;
+};
+
+boolean
+_bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, pfound,
+ pfilename, pfnname, pline, pinfo)
+ bfd *abfd;
+ asymbol **symbols;
+ asection *section;
+ bfd_vma offset;
+ boolean *pfound;
+ const char **pfilename;
+ const char **pfnname;
+ unsigned int *pline;
+ PTR *pinfo;
+{
+ struct stab_find_info *info;
+ bfd_size_type stabsize, strsize;
+ bfd_byte *stab, *stabend, *str;
+ bfd_size_type stroff;
+ bfd_vma fnaddr;
+ char *directory_name, *main_file_name, *current_file_name, *line_file_name;
+ char *fnname;
+ bfd_vma low_func_vma, low_line_vma;
+
+ *pfound = false;
+ *pfilename = bfd_get_filename (abfd);
+ *pfnname = NULL;
+ *pline = 0;
+
+ info = (struct stab_find_info *) *pinfo;
+ if (info != NULL)
+ {
+ if (info->stabsec == NULL || info->strsec == NULL)
+ {
+ /* No stabs debugging information. */
+ return true;
+ }
+
+ stabsize = info->stabsec->_raw_size;
+ strsize = info->strsec->_raw_size;
+ }
+ else
+ {
+ long reloc_size, reloc_count;
+ arelent **reloc_vector;
+
+ info = (struct stab_find_info *) bfd_zalloc (abfd, sizeof *info);
+ if (info == NULL)
+ return false;
+
+ /* FIXME: When using the linker --split-by-file or
+ --split-by-reloc options, it is possible for the .stab and
+ .stabstr sections to be split. We should handle that. */
+
+ info->stabsec = bfd_get_section_by_name (abfd, ".stab");
+ info->strsec = bfd_get_section_by_name (abfd, ".stabstr");
+
+ if (info->stabsec == NULL || info->strsec == NULL)
+ {
+ /* No stabs debugging information. Set *pinfo so that we
+ can return quickly in the info != NULL case above. */
+ *pinfo = (PTR) info;
+ return true;
+ }
+
+ stabsize = info->stabsec->_raw_size;
+ strsize = info->strsec->_raw_size;
+
+ info->stabs = (bfd_byte *) bfd_alloc (abfd, stabsize);
+ info->strs = (bfd_byte *) bfd_alloc (abfd, strsize);
+ if (info->stabs == NULL || info->strs == NULL)
+ return false;
+
+ if (! bfd_get_section_contents (abfd, info->stabsec, info->stabs, 0,
+ stabsize)
+ || ! bfd_get_section_contents (abfd, info->strsec, info->strs, 0,
+ strsize))
+ return false;
+
+ /* If this is a relocateable object file, we have to relocate
+ the entries in .stab. This should always be simple 32 bit
+ relocations against symbols defined in this object file, so
+ this should be no big deal. */
+ reloc_size = bfd_get_reloc_upper_bound (abfd, info->stabsec);
+ if (reloc_size < 0)
+ return false;
+ reloc_vector = (arelent **) bfd_malloc (reloc_size);
+ if (reloc_vector == NULL && reloc_size != 0)
+ return false;
+ reloc_count = bfd_canonicalize_reloc (abfd, info->stabsec, reloc_vector,
+ symbols);
+ if (reloc_count < 0)
+ {
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return false;
+ }
+ if (reloc_count > 0)
+ {
+ arelent **pr;
+
+ for (pr = reloc_vector; *pr != NULL; pr++)
+ {
+ arelent *r;
+ unsigned long val;
+ asymbol *sym;
+
+ r = *pr;
+ if (r->howto->rightshift != 0
+ || r->howto->size != 2
+ || r->howto->bitsize != 32
+ || r->howto->pc_relative
+ || r->howto->bitpos != 0
+ || r->howto->dst_mask != 0xffffffff)
+ {
+ (*_bfd_error_handler)
+ ("Unsupported .stab relocation");
+ bfd_set_error (bfd_error_invalid_operation);
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+ return false;
+ }
+
+ val = bfd_get_32 (abfd, info->stabs + r->address);
+ val &= r->howto->src_mask;
+ sym = *r->sym_ptr_ptr;
+ val += sym->value + sym->section->vma + r->addend;
+ bfd_put_32 (abfd, val, info->stabs + r->address);
+ }
+ }
+
+ if (reloc_vector != NULL)
+ free (reloc_vector);
+
+ *pinfo = (PTR) info;
+ }
+
+ /* We are passed a section relative offset. The offsets in the
+ stabs information are absolute. */
+ offset += bfd_get_section_vma (abfd, section);
+
+ /* Stabs entries use a 12 byte format:
+ 4 byte string table index
+ 1 byte stab type
+ 1 byte stab other field
+ 2 byte stab desc field
+ 4 byte stab value
+ FIXME: This will have to change for a 64 bit object format.
+
+ The stabs symbols are divided into compilation units. For the
+ first entry in each unit, the type of 0, the value is the length
+ of the string table for this unit, and the desc field is the
+ number of stabs symbols for this unit. */
+
+#define STRDXOFF (0)
+#define TYPEOFF (4)
+#define OTHEROFF (5)
+#define DESCOFF (6)
+#define VALOFF (8)
+#define STABSIZE (12)
+
+ /* It would be nice if we could skip ahead to the stabs symbols for
+ the next compilation unit to quickly scan through the compilation
+ units. Unfortunately, since each line number gets a separate
+ stabs entry, it is entirely plausible that a large source file
+ will overflow the 16 bit count of stabs entries. */
+ fnaddr = 0;
+ directory_name = NULL;
+ main_file_name = NULL;
+ current_file_name = NULL;
+ line_file_name = NULL;
+ fnname = NULL;
+ low_func_vma = 0;
+ low_line_vma = 0;
+
+ stabend = info->stabs + stabsize;
+
+ if (info->cached_stab == NULL || offset < info->cached_offset)
+ {
+ stab = info->stabs;
+ str = info->strs;
+ stroff = 0;
+ }
+ else
+ {
+ stab = info->cached_stab;
+ str = info->cached_str;
+ stroff = info->cached_stroff;
+ }
+
+ info->cached_offset = offset;
+
+ for (; stab < stabend; stab += STABSIZE)
+ {
+ boolean done;
+ bfd_vma val;
+ char *name;
+
+ done = false;
+
+ switch (stab[TYPEOFF])
+ {
+ case 0:
+ /* This is the first entry in a compilation unit. */
+ if ((bfd_size_type) ((info->strs + strsize) - str) < stroff)
+ {
+ done = true;
+ break;
+ }
+ str += stroff;
+ stroff = bfd_get_32 (abfd, stab + VALOFF);
+ break;
+
+ case N_SO:
+ /* The main file name. */
+
+ val = bfd_get_32 (abfd, stab + VALOFF);
+ if (val > offset)
+ {
+ done = true;
+ break;
+ }
+
+ name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF);
+
+ /* An empty string indicates the end of the compilation
+ unit. */
+ if (*name == '\0')
+ {
+ /* If there are functions in different sections, they
+ may have addresses larger than val, but we don't want
+ to forget the file name. When there are functions in
+ different cases, there is supposed to be an N_FUN at
+ the end of the function indicating where it ends. */
+ if (low_func_vma < val || fnname == NULL)
+ main_file_name = NULL;
+ break;
+ }
+
+ /* We know that we have to get to at least this point in the
+ stabs entries for this offset. */
+ info->cached_stab = stab;
+ info->cached_str = str;
+ info->cached_stroff = stroff;
+
+ current_file_name = name;
+
+ /* Look ahead to the next symbol. Two consecutive N_SO
+ symbols are a directory and a file name. */
+ if (stab + STABSIZE >= stabend
+ || *(stab + STABSIZE + TYPEOFF) != N_SO)
+ directory_name = NULL;
+ else
+ {
+ stab += STABSIZE;
+ directory_name = current_file_name;
+ current_file_name = ((char *) str
+ + bfd_get_32 (abfd, stab + STRDXOFF));
+ }
+
+ main_file_name = current_file_name;
+
+ break;
+
+ case N_SOL:
+ /* The name of an include file. */
+ current_file_name = ((char *) str
+ + bfd_get_32 (abfd, stab + STRDXOFF));
+ break;
+
+ case N_SLINE:
+ case N_DSLINE:
+ case N_BSLINE:
+ /* A line number. The value is relative to the start of the
+ current function. */
+ val = fnaddr + bfd_get_32 (abfd, stab + VALOFF);
+ if (val >= low_line_vma && val <= offset)
+ {
+ *pline = bfd_get_16 (abfd, stab + DESCOFF);
+ low_line_vma = val;
+ line_file_name = current_file_name;
+ }
+ break;
+
+ case N_FUN:
+ /* A function name. */
+ val = bfd_get_32 (abfd, stab + VALOFF);
+ name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF);
+
+ /* An empty string here indicates the end of a function, and
+ the value is relative to fnaddr. */
+
+ if (*name == '\0')
+ {
+ val += fnaddr;
+ if (val >= low_func_vma && val < offset)
+ fnname = NULL;
+ }
+ else
+ {
+ if (val >= low_func_vma && val <= offset)
+ {
+ fnname = name;
+ low_func_vma = val;
+ }
+
+ fnaddr = val;
+ }
+
+ break;
+ }
+
+ if (done)
+ break;
+ }
+
+ if (main_file_name == NULL)
+ {
+ /* No information found. */
+ return true;
+ }
+
+ *pfound = true;
+
+ if (*pline != 0)
+ main_file_name = line_file_name;
+
+ if (main_file_name != NULL)
+ {
+ if (main_file_name[0] == '/' || directory_name == NULL)
+ *pfilename = main_file_name;
+ else
+ {
+ size_t dirlen;
+
+ dirlen = strlen (directory_name);
+ if (info->filename == NULL
+ || strncmp (info->filename, directory_name, dirlen) != 0
+ || strcmp (info->filename + dirlen, main_file_name) != 0)
+ {
+ if (info->filename != NULL)
+ free (info->filename);
+ info->filename = (char *) bfd_malloc (dirlen +
+ strlen (main_file_name)
+ + 1);
+ if (info->filename == NULL)
+ return false;
+ strcpy (info->filename, directory_name);
+ strcpy (info->filename + dirlen, main_file_name);
+ }
+
+ *pfilename = info->filename;
+ }
+ }
+
+ if (fnname != NULL)
+ {
+ char *s;
+
+ /* This will typically be something like main:F(0,1), so we want
+ to clobber the colon. It's OK to change the name, since the
+ string is in our own local storage anyhow. */
+
+ s = strchr (fnname, ':');
+ if (s != NULL)
+ *s = '\0';
+
+ *pfnname = fnname;
+ }
+
+ return true;
+}
diff --git a/contrib/gdb/bfd/sysdep.h b/contrib/gdb/bfd/sysdep.h
new file mode 100644
index 0000000..dd8146a
--- /dev/null
+++ b/contrib/gdb/bfd/sysdep.h
@@ -0,0 +1,114 @@
+/* sysdep.h -- handle host dependencies for the BFD library
+ Copyright 1995 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef BFD_SYSDEP_H
+#define BFD_SYSDEP_H
+
+#include "ansidecl.h"
+
+#include "config.h"
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#else
+extern char *strchr ();
+extern char *strrchr ();
+extern char *strstr ();
+#endif
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef USE_BINARY_FOPEN
+#include "fopen-bin.h"
+#else
+#include "fopen-same.h"
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#endif
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+#ifndef O_WRONLY
+#define O_WRONLY 1
+#endif
+#ifndef O_RDWR
+#define O_RDWR 2
+#endif
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifdef NEED_DECLARATION_MALLOC
+extern PTR malloc ();
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free ();
+#endif
+
+#endif /* ! defined (BFD_SYSDEP_H) */
diff --git a/contrib/gdb/bfd/targets.c b/contrib/gdb/bfd/targets.c
new file mode 100644
index 0000000..e1e6468
--- /dev/null
+++ b/contrib/gdb/bfd/targets.c
@@ -0,0 +1,886 @@
+/* Generic target-file-type support for the BFD library.
+ Copyright 1990, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Written by 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+
+/*
+SECTION
+ Targets
+
+DESCRIPTION
+ Each port of BFD to a different machine requries the creation
+ of a target back end. All the back end provides to the root
+ part of BFD is a structure containing pointers to functions
+ which perform certain low level operations on files. BFD
+ translates the applications's requests through a pointer into
+ calls to the back end routines.
+
+ When a file is opened with <<bfd_openr>>, its format and
+ target are unknown. BFD uses various mechanisms to determine
+ how to interpret the file. The operations performed are:
+
+ o Create a BFD by calling the internal routine
+ <<_bfd_new_bfd>>, then call <<bfd_find_target>> with the
+ target string supplied to <<bfd_openr>> and the new BFD pointer.
+
+ o If a null target string was provided to <<bfd_find_target>>,
+ look up the environment variable <<GNUTARGET>> and use
+ that as the target string.
+
+ o If the target string is still <<NULL>>, or the target string is
+ <<default>>, then use the first item in the target vector
+ as the target type, and set <<target_defaulted>> in the BFD to
+ cause <<bfd_check_format>> to loop through all the targets.
+ @xref{bfd_target}. @xref{Formats}.
+
+ o Otherwise, inspect the elements in the target vector
+ one by one, until a match on target name is found. When found,
+ use it.
+
+ o Otherwise return the error <<bfd_error_invalid_target>> to
+ <<bfd_openr>>.
+
+ o <<bfd_openr>> attempts to open the file using
+ <<bfd_open_file>>, and returns the BFD.
+
+ Once the BFD has been opened and the target selected, the file
+ format may be determined. This is done by calling
+ <<bfd_check_format>> on the BFD with a suggested format.
+ If <<target_defaulted>> has been set, each possible target
+ type is tried to see if it recognizes the specified format.
+ <<bfd_check_format>> returns <<true>> when the caller guesses right.
+@menu
+@* bfd_target::
+@end menu
+*/
+
+
+/*
+
+INODE
+ bfd_target, , Targets, Targets
+DOCDD
+SUBSECTION
+ bfd_target
+
+DESCRIPTION
+ This structure contains everything that BFD knows about a
+ 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 <<xvec>>
+ member.
+
+ The macros below are used to dispatch to functions through the
+ <<bfd_target>> 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 @var{arglist}
+ argument must be parenthesized; it contains all the arguments
+ to the called function.
+
+ They make the documentation (more) unpleasant to read, so if
+ someone wants to fix this and not break the above, please do.
+
+.#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:
+
+.#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 structure which defines the type of BFD this is. The
+ <<xvec>> member of the struct <<bfd>> itself points here. Each
+ module that implements access to a different target under BFD,
+ defines one of these.
+
+
+ FIXME, these names should be rationalised with the names of
+ 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_ihex_flavour,
+. bfd_target_som_flavour,
+. bfd_target_os9k_flavour,
+. bfd_target_versados_flavour,
+. bfd_target_msdos_flavour
+.};
+.
+.enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
+.
+.{* Forward declaration. *}
+.typedef struct bfd_link_info _bfd_link_info;
+.
+.typedef struct bfd_target
+.{
+
+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 bfd_flavour flavour;
+
+The order of bytes within the data area of a file.
+
+. enum bfd_endian byteorder;
+
+The order of bytes within the header parts of a file.
+
+. enum bfd_endian header_byteorder;
+
+A mask of all the flags which an executable may have set -
+from the set <<NO_FLAGS>>, <<HAS_RELOC>>, ...<<D_PAGED>>.
+
+. flagword object_flags;
+
+A mask of all the flags which a section may have set - from
+the set <<SEC_NO_FLAGS>>, <<SEC_ALLOC>>, ...<<SET_NEVER_LOAD>>.
+
+. flagword section_flags;
+
+The character normally found at the front of a symbol
+(if any), perhaps `_'.
+
+. char symbol_leading_char;
+
+The pad character for file names within an archive header.
+
+. char ar_pad_char;
+
+The maximum number of characters in an archive header.
+
+. unsigned short ar_max_namelen;
+
+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 ((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 ((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 ((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 ((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 ((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 ((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 a <<bfd_target *>> or zero.
+
+. 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>>.
+
+. boolean (*_bfd_write_contents[bfd_type_end]) PARAMS ((bfd *));
+
+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),\
+.CAT(NAME,_get_section_contents_in_window)
+.
+. {* 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));
+. boolean (*_bfd_get_section_contents_in_window)
+. PARAMS ((bfd *, sec_ptr, bfd_window *,
+. 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_merge_private_bfd_data),\
+.CAT(NAME,_bfd_copy_private_section_data),\
+.CAT(NAME,_bfd_copy_private_symbol_data),\
+.CAT(NAME,_bfd_set_private_flags),\
+.CAT(NAME,_bfd_print_private_bfd_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 merge BFD general private data from one object file
+. to a common output file when linking. *}
+. boolean (*_bfd_merge_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));
+. {* Called to copy BFD private symbol data from one symbol
+. to another. *}
+. boolean (*_bfd_copy_private_symbol_data) PARAMS ((bfd *, asymbol *,
+. bfd *, asymbol *));
+. {* Called to set private backend flags *}
+. boolean (*_bfd_set_private_flags) PARAMS ((bfd *, flagword));
+.
+. {* Called to print private BFD data *}
+. boolean (*_bfd_print_private_bfd_data) PARAMS ((bfd *, 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,_construct_extended_name_table),\
+.CAT(NAME,_truncate_arname),\
+.CAT(NAME,_write_armap),\
+.CAT(NAME,_read_ar_hdr),\
+.CAT(NAME,_openr_next_archived_file),\
+.CAT(NAME,_get_elt_at_index),\
+.CAT(NAME,_generic_stat_arch_elt),\
+.CAT(NAME,_update_armap_timestamp)
+. boolean (*_bfd_slurp_armap) PARAMS ((bfd *));
+. boolean (*_bfd_slurp_extended_name_table) PARAMS ((bfd *));
+. boolean (*_bfd_construct_extended_name_table)
+. PARAMS ((bfd *, char **, bfd_size_type *, const char **));
+. void (*_bfd_truncate_arname) PARAMS ((bfd *, CONST char *, char *));
+. boolean (*write_armap) PARAMS ((bfd *arch,
+. unsigned int elength,
+. struct orl *map,
+. unsigned int orl_count,
+. int stridx));
+. PTR (*_bfd_read_ar_hdr_fn) PARAMS ((bfd *));
+. bfd * (*openr_next_archived_file) PARAMS ((bfd *arch, bfd *prev));
+.#define bfd_get_elt_at_index(b,i) BFD_SEND(b, _bfd_get_elt_at_index, (b,i))
+. bfd * (*_bfd_get_elt_at_index) PARAMS ((bfd *, symindex));
+. int (*_bfd_stat_arch_elt) PARAMS ((bfd *, struct stat *));
+. boolean (*_bfd_update_armap_timestamp) PARAMS ((bfd *));
+.
+. {* 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),\
+.CAT(NAME,_read_minisymbols),\
+.CAT(NAME,_minisymbol_to_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,
+. struct symbol_cache_entry *,
+. bfd_print_symbol_type));
+.#define bfd_print_symbol(b,p,s,e) BFD_SEND(b, _bfd_print_symbol, (b,p,s,e))
+. void (*_bfd_get_symbol_info) PARAMS ((bfd *,
+. 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_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));
+. {* 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. *}
+. asymbol * (*_bfd_make_debug_symbol) PARAMS ((
+. bfd *abfd,
+. void *ptr,
+. unsigned long size));
+.#define bfd_read_minisymbols(b, d, m, s) \
+. BFD_SEND (b, _read_minisymbols, (b, d, m, s))
+. long (*_read_minisymbols) PARAMS ((bfd *, boolean, PTR *,
+. unsigned int *));
+.#define bfd_minisymbol_to_symbol(b, d, m, f) \
+. BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f))
+. asymbol *(*_minisymbol_to_symbol) PARAMS ((bfd *, boolean, const PTR,
+. asymbol *));
+.
+. {* 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. *}
+. reloc_howto_type *
+. (*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),\
+.CAT(NAME,_bfd_link_split_section)
+. 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 *));
+.
+. {* Should this section be split up into smaller pieces during linking. *}
+. boolean (*_bfd_link_split_section) PARAMS ((bfd *, struct sec *));
+.
+. {* 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.
+
+. PTR backend_data;
+.} bfd_target;
+
+*/
+
+/* All known xvecs (even those that don't compile on all systems).
+ Alphabetized for easy reference.
+ They are listed a second time below, since
+ we can't intermix extern's and initializers. */
+extern const bfd_target a29kcoff_big_vec;
+extern const bfd_target a_out_adobe_vec;
+extern const bfd_target aout_arm_big_vec;
+extern const bfd_target aout_arm_little_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 armcoff_little_vec;
+extern const bfd_target armcoff_big_vec;
+extern const bfd_target armpe_little_vec;
+extern const bfd_target armpe_big_vec;
+extern const bfd_target armpei_little_vec;
+extern const bfd_target armpei_big_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_powerpcle_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 i386freebsd_vec;
+extern const bfd_target i386os9k_vec;
+extern const bfd_target i386coff_vec;
+extern const bfd_target bfd_powerpc_pe_vec;
+extern const bfd_target bfd_powerpcle_pe_vec;
+extern const bfd_target bfd_powerpc_pei_vec;
+extern const bfd_target bfd_powerpcle_pei_vec;
+extern const bfd_target i386pe_vec;
+extern const bfd_target i386pei_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 i386msdos_vec;
+extern const bfd_target i386netbsd_vec;
+extern const bfd_target i860coff_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 m68kaux_coff_vec;
+extern const bfd_target m68kcoff_vec;
+extern const bfd_target m68kcoffun_vec;
+extern const bfd_target m68klinux_vec;
+extern const bfd_target m68klynx_aout_vec;
+extern const bfd_target m68klynx_coff_vec;
+extern const bfd_target m68knetbsd_vec;
+extern const bfd_target m68k4knetbsd_vec;
+extern const bfd_target m88kbcs_vec;
+extern const bfd_target m88kmach3_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 pc532netbsd_vec;
+extern const bfd_target oasys_vec;
+extern const bfd_target pc532machaout_vec;
+extern const bfd_target riscix_vec;
+extern const bfd_target pmac_xcoff_vec;
+extern const bfd_target rs6000coff_vec;
+extern const bfd_target shcoff_vec;
+extern const bfd_target shlcoff_vec;
+extern const bfd_target sparclynx_aout_vec;
+extern const bfd_target sparclynx_coff_vec;
+extern const bfd_target sparcnetbsd_vec;
+extern const bfd_target sparccoff_vec;
+extern const bfd_target sunos_big_vec;
+extern const bfd_target tekhex_vec;
+extern const bfd_target versados_vec;
+extern const bfd_target we32kcoff_vec;
+extern const bfd_target w65_vec;
+extern const bfd_target z8kcoff_vec;
+
+/* srec is always included. */
+extern const bfd_target srec_vec;
+extern const bfd_target symbolsrec_vec;
+
+/* binary is always included. */
+extern const bfd_target binary_vec;
+
+/* ihex is always included. */
+extern const bfd_target ihex_vec;
+
+/* All of the xvecs for core files. */
+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;
+
+const bfd_target * const bfd_target_vector[] = {
+
+#ifdef SELECT_VECS
+
+ SELECT_VECS,
+
+#else /* not SELECT_VECS */
+
+#ifdef DEFAULT_VECTOR
+ &DEFAULT_VECTOR,
+#endif
+ /* This list is alphabetized to make it easy to compare
+ with other vector lists -- the decls above and
+ the case statement in configure.in.
+ Vectors that don't compile on all systems, or aren't finished,
+ should have an entry here with #if 0 around it, to show that
+ it wasn't omitted by mistake. */
+ &a29kcoff_big_vec,
+ &a_out_adobe_vec,
+#if 0 /* No one seems to use this. */
+ &aout_mips_big_vec,
+#endif
+ &aout_mips_little_vec,
+ &b_out_vec_big_host,
+ &b_out_vec_little_host,
+
+ /* 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,
+ &bfd_elf32_hppa_vec,
+ &bfd_elf32_i386_vec,
+ &bfd_elf32_i860_vec,
+ &bfd_elf32_little_generic_vec,
+ &bfd_elf32_littlemips_vec,
+ &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
+ &ecoff_big_vec,
+ &ecoff_little_vec,
+#if 0
+ &ecoffalpha_little_vec,
+#endif
+ &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) || defined (HOST_HPPAOSF)
+ &som_vec,
+#endif
+ &i386aout_vec,
+ &i386bsd_vec,
+ &i386coff_vec,
+ &i386freebsd_vec,
+ &i860coff_vec,
+ &bfd_powerpc_pe_vec,
+ &bfd_powerpcle_pe_vec,
+ &bfd_powerpc_pei_vec,
+ &bfd_powerpcle_pei_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
+ &i386msdos_vec,
+ &i386netbsd_vec,
+ &i386os9k_vec,
+ &i386pe_vec,
+ &i386pei_vec,
+ &armcoff_little_vec,
+ &armcoff_big_vec,
+ &armpe_little_vec,
+ &armpe_big_vec,
+ &armpei_little_vec,
+ &armpei_big_vec,
+ &icoff_big_vec,
+ &icoff_little_vec,
+ &ieee_vec,
+ &m68kcoff_vec,
+ &m68kcoffun_vec,
+#if 0
+ /* Since a.out files lack decent magic numbers, no way to recognize
+ which kind of a.out file it is. */
+ &m68klinux_vec,
+#endif
+ &m68klynx_aout_vec,
+ &m68klynx_coff_vec,
+ &m68knetbsd_vec,
+ &m88kbcs_vec,
+ &m88kmach3_vec,
+ &newsos3_vec,
+ &nlm32_i386_vec,
+ &nlm32_sparc_vec,
+#ifdef BFD64
+ &nlm32_alpha_vec,
+#endif
+ &pc532netbsd_vec,
+#if 0
+ /* We have no oasys tools anymore, so we can't test any of this
+ anymore. If you want to test the stuff yourself, go ahead...
+ steve@cygnus.com
+ Worse, since there is no magic number for archives, there
+ can be annoying target mis-matches. */
+ &oasys_vec,
+#endif
+ &pc532machaout_vec,
+#if 0
+ /* We have no way of distinguishing these from other a.out variants */
+ &aout_arm_big_vec,
+ &aout_arm_little_vec,
+ &riscix_vec,
+#endif
+#if 0
+ /* This has the same magic number as RS/6000. */
+ &pmac_xcoff_vec,
+#endif
+ &rs6000coff_vec,
+ &shcoff_vec,
+ &shlcoff_vec,
+ &sparclynx_aout_vec,
+ &sparclynx_coff_vec,
+ &sparcnetbsd_vec,
+ &sunos_big_vec,
+ &aout0_big_vec,
+ &tekhex_vec,
+ &we32kcoff_vec,
+ &versados_vec,
+ &z8kcoff_vec,
+
+#endif /* not SELECT_VECS */
+
+/* Always support S-records, for convenience. */
+ &srec_vec,
+ &symbolsrec_vec,
+/* And tekhex */
+ &tekhex_vec,
+/* Likewise for binary output. */
+ &binary_vec,
+/* Likewise for ihex. */
+ &ihex_vec,
+
+/* Add any required traditional-core-file-handler. */
+
+#ifdef AIX386_CORE
+ &aix386_core_vec,
+#endif
+#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 TRAD_CORE
+ &trad_core_vec,
+#endif
+
+#ifdef PTRACE_CORE
+ &ptrace_core_vec,
+#endif
+
+ NULL /* end of list marker */
+};
+
+/* bfd_default_vector[0] contains either the address of the default vector,
+ if there is one, or zero if there isn't. */
+
+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
+ Return a pointer to the transfer vector for the object target
+ named @var{target_name}. If @var{target_name} is <<NULL>>, choose the
+ one in the environment variable <<GNUTARGET>>; 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 <<bfd_check_format>> to loop over all the
+ targets to find the one that matches the file being read.
+*/
+
+const bfd_target *
+bfd_find_target (target_name, abfd)
+ CONST char *target_name;
+ bfd *abfd;
+{
+ const bfd_target * const *target;
+ extern char *getenv ();
+ CONST char *targname = (target_name ? target_name :
+ (CONST char *) getenv ("GNUTARGET"));
+
+ /* This is safe; the vector cannot be null */
+ if (targname == NULL || !strcmp (targname, "default")) {
+ abfd->target_defaulted = true;
+ return abfd->xvec = bfd_target_vector[0];
+ }
+
+ abfd->target_defaulted = false;
+
+ for (target = &bfd_target_vector[0]; *target != NULL; target++) {
+ if (!strcmp (targname, (*target)->name))
+ return abfd->xvec = *target;
+ }
+
+ bfd_set_error (bfd_error_invalid_target);
+ return NULL;
+}
+
+
+/*
+FUNCTION
+ bfd_target_list
+
+SYNOPSIS
+ 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 **
+bfd_target_list ()
+{
+ int vec_length= 0;
+#if defined (HOST_HPPAHPUX) && ! defined (__STDC__)
+ /* The native compiler on the HP9000/700 has a bug which causes it
+ to loop endlessly when compiling this file. This avoids it. */
+ volatile
+#endif
+ const bfd_target * const *target;
+ CONST char **name_list, **name_ptr;
+
+ for (target = &bfd_target_vector[0]; *target != NULL; target++)
+ vec_length++;
+
+ name_ptr = name_list = (CONST char **)
+ bfd_zmalloc ((vec_length + 1) * sizeof (char **));
+
+ if (name_list == NULL)
+ return NULL;
+
+ for (target = &bfd_target_vector[0]; *target != NULL; target++)
+ *(name_ptr++) = (*target)->name;
+
+ return name_list;
+}
diff --git a/contrib/gdb/bfd/tekhex.c b/contrib/gdb/bfd/tekhex.c
new file mode 100644
index 0000000..bf7957e
--- /dev/null
+++ b/contrib/gdb/bfd/tekhex.c
@@ -0,0 +1,1031 @@
+/* BFD backend for Extended Tektronix Hex Format objects.
+ Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+ Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+SUBSECTION
+ Tektronix Hex Format handling
+
+DESCRIPTION
+
+ Tek Hex records can hold symbols and data, but not
+ relocations. Their main application is communication with
+ devices like PROM programmers and ICE equipment.
+
+ It seems that the sections are descibed as being really big,
+ the example I have says that the text section is 0..ffffffff.
+ BFD would barf with this, many apps would try to alloc 4GB to
+ read in the file.
+
+ Tex Hex may contain many sections, but the data which comes in
+ has no tag saying which section it belongs to, so we create
+ one section for each block of data, called "blknnnn" which we
+ stick all the data into.
+
+ TekHex 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 sections we
+ create.
+ We read in the data into pages of CHUNK_MASK+1 size and read
+ them out from that whenever we need to.
+
+ Any number of sections may be created for output, we save them
+ up and output them when it's time to close the bfd.
+
+
+ A TekHex record looks like:
+EXAMPLE
+ %<block length><type><checksum><stuff><cr>
+
+DESCRIPTION
+ Where
+ o length
+ is the number of bytes in the record not including the % sign.
+ o type
+ is one of:
+ 3) symbol record
+ 6) data record
+ 8) termination record
+
+
+The data can come out of order, and may be discontigous. This is a
+serial protocol, so big files are unlikely, so we keep a list of 8k chunks
+*/
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libiberty.h"
+
+typedef struct
+ {
+ bfd_vma low;
+ bfd_vma high;
+ } addr_range_type;
+
+typedef struct tekhex_symbol_struct
+ {
+
+ asymbol symbol;
+ struct tekhex_symbol_struct *prev;
+
+ } tekhex_symbol_type;
+
+static const char digs[] = "0123456789ABCDEF";
+
+static char sum_block[256];
+
+#define NOT_HEX 20
+#define NIBBLE(x) hex_value(x)
+#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
+#define TOHEX(d,x) \
+(d)[1] = digs[(x) & 0xf]; \
+(d)[0] = digs[((x)>>4)&0xf];
+#define ISHEX(x) hex_p(x)
+
+/*
+Here's an example
+%3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
+%1B3709T_SEGMENT1108FFFFFFFF
+%2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
+%373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
+%373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
+%373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
+%373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
+%373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
+%373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
+%373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
+%2734D9T_SEGMENT8Bvoid$t15$151035_main10
+%2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
+%2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
+%07 8 10 10
+
+explanation:
+%3A6C6480004E56FFFC4E717063B0AEFFFC6D0652AEFFFC60F24E5E4E75
+ ^ ^^ ^ ^-data
+ | || +------ 4 char integer 0x8000
+ | |+-------- checksum
+ | +--------- type 6 (data record)
+ +----------- length 3a chars
+ <---------------------- 3a (58 chars) ------------------->
+
+%1B3709T_SEGMENT1108FFFFFFFF
+ ^ ^^ ^- 8 character integer 0xffffffff
+ | |+- 1 character integer 0
+ | +-- type 1 symbol (section definition)
+ +------------ 9 char symbol T_SEGMENT
+
+%2B3AB9T_SEGMENT7Dgcc_compiled$1087hello$c10
+%373829T_SEGMENT80int$t1$r1$$214741080char$t2$r2$0$12710
+%373769T_SEGMENT80long$int$t3$r1$$1080unsigned$int$t4$10
+%373CA9T_SEGMENT80long$unsigned$in1080short$int$t6$r1$10
+%373049T_SEGMENT80long$long$int$t71080short$unsigned$i10
+%373A29T_SEGMENT80long$long$unsign1080signed$char$t10$10
+%373D69T_SEGMENT80unsigned$char$t11080float$t12$r1$4$010
+%373D19T_SEGMENT80double$t13$r1$8$1080long$double$t14$10
+%2734D9T_SEGMENT8Bvoid$t15$151035_main10
+%2F3CA9T_SEGMENT81$1081$1681$1E81$21487main$F110
+%2832F9T_SEGMENT83i$18FFFFFFFC81$1481$214
+%0781010
+
+Turns into
+sac@thepub$ ./objdump -dx -m m68k f
+
+f: file format tekhex
+-----x--- 9/55728 -134219416 Sep 29 15:13 1995 f
+architecture: UNKNOWN!, flags 0x00000010:
+HAS_SYMS
+start address 0x00000000
+SECTION 0 [D00000000] : size 00020000 vma 00000000 align 2**0
+ ALLOC, LOAD
+SECTION 1 [D00008000] : size 00002001 vma 00008000 align 2**0
+
+SECTION 2 [T_SEGMENT] : size ffffffff vma 00000000 align 2**0
+
+SYMBOL TABLE:
+00000000 g T_SEGMENT gcc_compiled$
+00000000 g T_SEGMENT hello$c
+00000000 g T_SEGMENT int$t1$r1$$21474
+00000000 g T_SEGMENT char$t2$r2$0$127
+00000000 g T_SEGMENT long$int$t3$r1$$
+00000000 g T_SEGMENT unsigned$int$t4$
+00000000 g T_SEGMENT long$unsigned$in
+00000000 g T_SEGMENT short$int$t6$r1$
+00000000 g T_SEGMENT long$long$int$t7
+00000000 g T_SEGMENT short$unsigned$i
+00000000 g T_SEGMENT long$long$unsign
+00000000 g T_SEGMENT signed$char$t10$
+00000000 g T_SEGMENT unsigned$char$t1
+00000000 g T_SEGMENT float$t12$r1$4$0
+00000000 g T_SEGMENT double$t13$r1$8$
+00000000 g T_SEGMENT long$double$t14$
+00000000 g T_SEGMENT void$t15$15
+00000000 g T_SEGMENT _main
+00000000 g T_SEGMENT $
+00000000 g T_SEGMENT $
+00000000 g T_SEGMENT $
+00000010 g T_SEGMENT $
+00000000 g T_SEGMENT main$F1
+fcffffff g T_SEGMENT i$1
+00000000 g T_SEGMENT $
+00000010 g T_SEGMENT $
+
+
+RELOCATION RECORDS FOR [D00000000]: (none)
+
+RELOCATION RECORDS FOR [D00008000]: (none)
+
+RELOCATION RECORDS FOR [T_SEGMENT]: (none)
+
+Disassembly of section D00000000:
+...
+00008000 ($+)7ff0 linkw fp,#-4
+00008004 ($+)7ff4 nop
+00008006 ($+)7ff6 movel #99,d0
+00008008 ($+)7ff8 cmpl fp@(-4),d0
+0000800c ($+)7ffc blts 00008014 ($+)8004
+0000800e ($+)7ffe addql #1,fp@(-4)
+00008012 ($+)8002 bras 00008006 ($+)7ff6
+00008014 ($+)8004 unlk fp
+00008016 ($+)8006 rts
+...
+
+*/
+
+static void
+tekhex_init ()
+{
+ unsigned int i;
+ static boolean inited = false;
+ int val;
+
+ if (inited == false)
+ {
+ inited = true;
+ hex_init ();
+ val = 0;
+ for (i = 0; i < 10; i++)
+ {
+ sum_block[i + '0'] = val++;
+ }
+ for (i = 'A'; i <= 'Z'; i++)
+ {
+ sum_block[i] = val++;
+ }
+ sum_block['$'] = val++;
+ sum_block['%'] = val++;
+ sum_block['.'] = val++;
+ sum_block['_'] = val++;
+ for (i = 'a'; i <= 'z'; i++)
+ {
+ sum_block[i] = val++;
+ }
+ }
+}
+
+/* The maximum number of bytes on a line is FF */
+#define MAXCHUNK 0xff
+/* The number of bytes we fit onto a line on output */
+#define CHUNK 21
+
+/* We cannot output our tekhexords as we see them, we have to glue them
+ together, this is done in this structure : */
+
+struct tekhex_data_list_struct
+{
+ unsigned char *data;
+ bfd_vma where;
+ bfd_size_type size;
+ struct tekhex_data_list_struct *next;
+
+};
+typedef struct tekhex_data_list_struct tekhex_data_list_type;
+
+#define CHUNK_MASK 0x1fff
+
+struct data_struct
+ {
+ char chunk_data[CHUNK_MASK + 1];
+ char chunk_init[CHUNK_MASK + 1];
+ bfd_vma vma;
+ struct data_struct *next;
+ };
+
+typedef struct tekhex_data_struct
+{
+ tekhex_data_list_type *head;
+ unsigned int type;
+ struct tekhex_symbol_struct *symbols;
+ struct data_struct *data;
+} tdata_type;
+
+#define enda(x) (x->vma + x->size)
+
+static bfd_vma
+getvalue (srcp)
+ char **srcp;
+{
+ char *src = *srcp;
+ bfd_vma value = 0;
+ unsigned int len = hex_value(*src++);
+
+ if (len == 0)
+ len = 16;
+ while (len--)
+ {
+ value = value << 4 | hex_value(*src++);
+ }
+ *srcp = src;
+ return value;
+}
+
+static unsigned int
+getsym (dstp, srcp)
+ char *dstp;
+ char **srcp;
+{
+ char *src = *srcp;
+ unsigned int i;
+ unsigned int len = hex_value(*src++);
+
+ if (len == 0)
+ len = 16;
+ for (i = 0; i < len; i++)
+ dstp[i] = src[i];
+ dstp[i] = 0;
+ *srcp = src + i;
+ return len;
+}
+
+struct data_struct *
+find_chunk (abfd, vma)
+ bfd *abfd;
+ bfd_vma vma;
+{
+ struct data_struct *d = abfd->tdata.tekhex_data->data;
+
+ vma &= ~CHUNK_MASK;
+ while (d && (d->vma) != vma)
+ {
+ d = d->next;
+ }
+ if (!d)
+ {
+ char *sname = bfd_alloc (abfd, 12);
+
+ /* No chunk for this address, so make one up */
+ d = (struct data_struct *)
+ bfd_alloc (abfd, sizeof (struct data_struct));
+
+ if (!sname || !d)
+ return NULL;
+
+ memset (d->chunk_init, 0, CHUNK_MASK + 1);
+ memset (d->chunk_data, 0, CHUNK_MASK + 1);
+ d->next = abfd->tdata.tekhex_data->data;
+ d->vma = vma;
+ abfd->tdata.tekhex_data->data = d;
+ }
+ return d;
+}
+
+static void
+insert_byte (abfd, value, addr)
+ bfd *abfd;
+ int value;
+ bfd_vma addr;
+{
+ /* Find the chunk that this byte needs and put it in */
+ struct data_struct *d = find_chunk (abfd, addr);
+
+ d->chunk_data[addr & CHUNK_MASK] = value;
+ d->chunk_init[addr & CHUNK_MASK] = 1;
+}
+
+/* The first pass is to find the names of all the sections, and see
+ how big the data is */
+static void
+first_phase (abfd, type, src)
+ bfd *abfd;
+ char type;
+ char *src;
+{
+ asection *section = bfd_abs_section_ptr;
+ int len;
+ char sym[17]; /* A symbol can only be 16chars long */
+
+ switch (type)
+ {
+ case '6':
+ /* Data record - read it and store it */
+ {
+ bfd_vma addr = getvalue (&src);
+
+ while (*src)
+ {
+ insert_byte (abfd, HEX (src), addr);
+ src += 2;
+ addr++;
+ }
+ }
+
+ return;
+ case '3':
+ /* Symbol record, read the segment */
+ len = getsym (sym, &src);
+ section = bfd_get_section_by_name (abfd, sym);
+ if (section == (asection *) NULL)
+ {
+ char *n = bfd_alloc (abfd, len + 1);
+
+ if (!n)
+ abort(); /* FIXME */
+ memcpy (n, sym, len + 1);
+ section = bfd_make_section (abfd, n);
+ }
+ while (*src)
+ {
+ switch (*src)
+ {
+ case '1': /* section range */
+ src++;
+ section->vma = getvalue (&src);
+ section->_raw_size = getvalue (&src) - section->vma;
+ section->flags = SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
+ break;
+ case '0':
+ case '2':
+ case '3':
+ case '4':
+ case '6':
+ case '7':
+ case '8':
+ /* Symbols, add to section */
+ {
+ tekhex_symbol_type *new =
+ (tekhex_symbol_type *) bfd_alloc (abfd,
+ sizeof (tekhex_symbol_type));
+ char type = (*src);
+
+ if (!new)
+ abort(); /* FIXME */
+ new->symbol.the_bfd = abfd;
+ src++;
+ abfd->symcount++;
+ abfd->flags |= HAS_SYMS;
+ new->prev = abfd->tdata.tekhex_data->symbols;
+ abfd->tdata.tekhex_data->symbols = new;
+ len = getsym (sym, &src);
+ new->symbol.name = bfd_alloc (abfd, len + 1);
+ if (!new->symbol.name)
+ abort(); /* FIXME */
+ memcpy ((char *) (new->symbol.name), sym, len + 1);
+ new->symbol.section = section;
+ if (type <= '4')
+ new->symbol.flags = (BSF_GLOBAL | BSF_EXPORT);
+ else
+ new->symbol.flags = BSF_LOCAL;
+ new->symbol.value = getvalue (&src) - section->vma;
+ }
+ }
+ }
+ }
+}
+
+/* Pass over an tekhex, calling one of the above functions on each
+ record. */
+
+static void
+ pass_over (abfd, func)
+ bfd *abfd;
+ void (*func) ();
+{
+ unsigned int chars_on_line;
+ boolean eof = false;
+
+ /* To the front of the file */
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0)
+ abort ();
+ while (eof == false)
+ {
+ char buffer[MAXCHUNK];
+ char *src = buffer;
+ char type;
+
+ /* Find first '%' */
+ eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
+ while (*src != '%' && !eof)
+ {
+ eof = (boolean) (bfd_read (src, 1, 1, abfd) != 1);
+ }
+ if (eof)
+ break;
+ src++;
+
+ /* Fetch the type and the length and the checksum */
+ if (bfd_read (src, 1, 5, abfd) != 5)
+ abort (); /* FIXME */
+
+ type = src[2];
+
+ if (!ISHEX (src[0]) || !ISHEX (src[1]))
+ break;
+
+ chars_on_line = HEX (src) - 5; /* Already read five char */
+
+ if (bfd_read (src, 1, chars_on_line, abfd) != chars_on_line)
+ abort (); /* FIXME */
+ src[chars_on_line] = 0; /* put a null at the end */
+
+ func (abfd, type, src);
+ }
+
+}
+
+long
+tekhex_get_symtab (abfd, table)
+ bfd *abfd;
+ asymbol **table;
+
+{
+ tekhex_symbol_type *p = abfd->tdata.tekhex_data->symbols;
+ unsigned int c = bfd_get_symcount (abfd);
+
+ table[c] = 0;
+ while (p)
+ {
+ table[--c] = &(p->symbol);
+ p = p->prev;
+ }
+
+ return bfd_get_symcount (abfd);
+}
+
+long
+tekhex_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ return (abfd->symcount + 1) * (sizeof (struct tekhex_asymbol_struct *));
+
+}
+
+static boolean
+tekhex_mkobject (abfd)
+ bfd *abfd;
+{
+ tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
+
+ if (!tdata)
+ return false;
+ abfd->tdata.tekhex_data = tdata;
+ tdata->type = 1;
+ tdata->head = (tekhex_data_list_type *) NULL;
+ tdata->symbols = (struct tekhex_symbol_struct *) NULL;
+ tdata->data = (struct data_struct *) NULL;
+ return true;
+}
+
+/*
+ Return true if the file looks like it's in TekHex format. Just look
+ for a percent sign and some hex digits */
+
+static const bfd_target *
+tekhex_object_p (abfd)
+ bfd *abfd;
+{
+ char b[4];
+
+ tekhex_init ();
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0
+ || bfd_read (b, 1, 4, abfd) != 4)
+ return NULL;
+
+ if (b[0] != '%' || !ISHEX (b[1]) || !ISHEX (b[2]) || !ISHEX (b[3]))
+ return (const bfd_target *) NULL;
+
+ tekhex_mkobject (abfd);
+
+ pass_over (abfd, first_phase);
+ return abfd->xvec;
+}
+
+static void
+move_section_contents (abfd, section, locationp, offset, count, get)
+ bfd *abfd;
+ asection *section;
+ PTR locationp;
+ file_ptr offset;
+ bfd_size_type count;
+ boolean get;
+{
+ bfd_vma addr;
+ char *location = (char *) locationp;
+ bfd_vma prev_number = 1; /* Nothing can have this as a high bit*/
+ struct data_struct *d = (struct data_struct *) NULL;
+
+ for (addr = section->vma; count != 0; count--, addr++)
+ {
+
+ bfd_vma chunk_number = addr & ~CHUNK_MASK; /* Get high bits of address */
+ bfd_vma low_bits = addr & CHUNK_MASK;
+
+ if (chunk_number != prev_number)
+ {
+ /* Different chunk, so move pointer */
+ d = find_chunk (abfd, chunk_number);
+ }
+
+ if (get)
+ {
+ if (d->chunk_init[low_bits])
+ {
+ *location = d->chunk_data[low_bits];
+ }
+ else
+ {
+ *location = 0;
+ }
+ }
+ else
+ {
+ d->chunk_data[low_bits] = *location;
+ d->chunk_init[low_bits] = (*location != 0);
+ }
+
+ location++;
+
+ }
+
+}
+static boolean
+tekhex_get_section_contents (abfd, section, locationp, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR locationp;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (section->flags & (SEC_LOAD | SEC_ALLOC))
+ {
+ move_section_contents (abfd, section, locationp, offset, count, true);
+ return true;
+ }
+ else
+ return false;
+}
+
+boolean
+tekhex_set_arch_mach (abfd, arch, machine)
+ bfd *abfd;
+ enum bfd_architecture arch;
+ unsigned long machine;
+{
+ return bfd_default_set_arch_mach (abfd, arch, machine);
+}
+
+/* we have to save up all the Tekhexords for a splurge before output,
+ */
+
+static boolean
+tekhex_set_section_contents (abfd, section, locationp, offset, bytes_to_do)
+ bfd *abfd;
+ sec_ptr section;
+ PTR locationp;
+ file_ptr offset;
+ bfd_size_type bytes_to_do;
+{
+
+ if (abfd->output_has_begun == false)
+ {
+ /* The first time around, allocate enough sections to hold all the chunks */
+ asection *s = abfd->sections;
+ bfd_vma vma;
+
+ for (s = abfd->sections; s; s = s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ for (vma = s->vma & ~CHUNK_MASK;
+ vma < s->vma + s->_raw_size;
+ vma += CHUNK_MASK)
+ find_chunk (abfd, vma);
+ }
+ }
+
+ }
+ if (section->flags & (SEC_LOAD | SEC_ALLOC))
+ {
+ move_section_contents (abfd, section, locationp, offset, bytes_to_do, false);
+ return true;
+ }
+ else
+ return false;
+
+}
+
+static void
+writevalue (dst, value)
+ char **dst;
+ bfd_vma value;
+{
+ char *p = *dst;
+ int len;
+ int shift;
+
+ for (len = 8, shift = 28; shift; shift -= 4, len--)
+ {
+ if ((value >> shift) & 0xf)
+ {
+ *p++ = len + '0';
+ while (len)
+ {
+ *p++ = digs[(value >> shift) & 0xf];
+ shift -= 4;
+ len--;
+ }
+ *dst = p;
+ return;
+
+ }
+ }
+ *p++ = '1';
+ *p++ = '0';
+ *dst = p;
+}
+
+static void
+writesym (dst, sym)
+ char **dst;
+ CONST char *sym;
+{
+ char *p = *dst;
+ int len = (sym ? strlen (sym) : 0);
+
+ if (len >= 16)
+ {
+ *p++ = '0';
+ len = 16;
+ }
+
+ else
+ {
+ if (len == 0)
+ {
+ *p++ = '1';
+ sym = "$";
+ len = 1;
+ }
+ else
+ {
+ *p++ = digs[len];
+ }
+ }
+
+ while (len--)
+ {
+ *p++ = *sym++;
+ }
+ *dst = p;
+}
+
+static void
+out (abfd, type, start, end)
+ bfd *abfd;
+ char type;
+ char *start;
+ char *end;
+{
+ int sum = 0;
+ char *s;
+ char front[6];
+ bfd_size_type wrlen;
+
+ front[0] = '%';
+ TOHEX (front + 1, end - start + 5);
+ front[3] = type;
+
+ for (s = start; s < end; s++)
+ {
+ sum += sum_block[(unsigned char) *s];
+ }
+
+ sum += sum_block[(unsigned char) front[1]]; /* length */
+ sum += sum_block[(unsigned char) front[2]];
+ sum += sum_block[(unsigned char) front[3]]; /* type */
+ TOHEX (front + 4, sum);
+ if (bfd_write (front, 1, 6, abfd) != 6)
+ abort ();
+ end[0] = '\n';
+ wrlen = end - start + 1;
+ if (bfd_write (start, 1, wrlen, abfd) != wrlen)
+ abort ();
+}
+
+static boolean
+tekhex_write_object_contents (abfd)
+ bfd *abfd;
+{
+ int bytes_written;
+ char buffer[100];
+ asymbol **p;
+ asection *s;
+ struct data_struct *d;
+
+ bytes_written = 0;
+
+ /* And the raw data */
+ for (d = abfd->tdata.tekhex_data->data;
+ d != (struct data_struct *) NULL;
+ d = d->next)
+ {
+ int low;
+
+ CONST int span = 32;
+ int addr;
+
+ /* Write it in blocks of 32 bytes */
+
+ for (addr = 0; addr < CHUNK_MASK + 1; addr += span)
+ {
+ int need = 0;
+
+ /* Check to see if necessary */
+ for (low = 0; !need && low < span; low++)
+ {
+ if (d->chunk_init[addr + low])
+ need = 1;
+ }
+ if (need)
+ {
+ char *dst = buffer;
+
+ writevalue (&dst, addr + d->vma);
+ for (low = 0; low < span; low++)
+ {
+ TOHEX (dst, d->chunk_data[addr + low]);
+ dst += 2;
+ }
+ out (abfd, '6', buffer, dst);
+ }
+ }
+ }
+ /* write all the section headers for the sections */
+ for (s = abfd->sections; s != (asection *) NULL; s = s->next)
+ {
+ char *dst = buffer;
+
+ writesym (&dst, s->name);
+ *dst++ = '1';
+ writevalue (&dst, s->vma);
+ writevalue (&dst, s->vma + s->_raw_size);
+ out (abfd, '3', buffer, dst);
+ }
+
+ /* And the symbols */
+ for (p = abfd->outsymbols; *p; p++)
+ {
+ int section_code = bfd_decode_symclass (*p);
+
+ if (section_code != '?')
+ { /* do not include debug symbols */
+ asymbol *s = *p;
+ char *dst = buffer;
+
+ writesym (&dst, s->section->name);
+
+ switch (section_code)
+ {
+ case 'A':
+ *dst++ = '2';
+ break;
+ case 'a':
+ *dst++ = '6';
+ break;
+ case 'D':
+ case 'B':
+ case 'O':
+ *dst++ = '4';
+ break;
+ case 'd':
+ case 'b':
+ case 'o':
+ *dst++ = '8';
+ break;
+ case 'T':
+ *dst++ = '3';
+ break;
+ case 't':
+ *dst++ = '7';
+ break;
+ case 'C':
+ case 'U':
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+
+ writesym (&dst, s->name);
+ writevalue (&dst, s->value + s->section->vma);
+ out (abfd, '3', buffer, dst);
+ }
+ }
+
+ /* And the terminator */
+ if (bfd_write ("%0781010\n", 1, 9, abfd) != 9)
+ abort ();
+ return true;
+}
+
+static int
+ tekhex_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+
+{
+ return 0;
+}
+
+static asymbol *
+tekhex_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ tekhex_symbol_type *new =
+ (tekhex_symbol_type *) bfd_zalloc (abfd, sizeof (struct tekhex_symbol_struct));
+
+ if (!new)
+ return NULL;
+ new->symbol.the_bfd = abfd;
+ new->prev = (struct tekhex_symbol_struct *) NULL;
+ return &(new->symbol);
+}
+
+static void
+tekhex_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+static void
+tekhex_print_symbol (ignore_abfd, filep, symbol, how)
+ bfd *ignore_abfd;
+ PTR filep;
+ asymbol *symbol;
+ bfd_print_symbol_type how;
+{
+ FILE *file = (FILE *) filep;
+
+ switch (how)
+ {
+ case bfd_print_symbol_name:
+ fprintf (file, "%s", symbol->name);
+ break;
+ case bfd_print_symbol_more:
+ break;
+
+ case bfd_print_symbol_all:
+ {
+ CONST char *section_name = symbol->section->name;
+
+ bfd_print_symbol_vandf ((PTR) file, symbol);
+
+ fprintf (file, " %-5s %s",
+ section_name,
+ symbol->name);
+ }
+ }
+}
+
+#define tekhex_close_and_cleanup _bfd_generic_close_and_cleanup
+#define tekhex_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define tekhex_new_section_hook _bfd_generic_new_section_hook
+
+#define tekhex_bfd_is_local_label bfd_generic_is_local_label
+#define tekhex_get_lineno _bfd_nosymbols_get_lineno
+#define tekhex_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define tekhex_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define tekhex_read_minisymbols _bfd_generic_read_minisymbols
+#define tekhex_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define tekhex_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define tekhex_bfd_relax_section bfd_generic_relax_section
+#define tekhex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define tekhex_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define tekhex_bfd_final_link _bfd_generic_final_link
+#define tekhex_bfd_link_split_section _bfd_generic_link_split_section
+
+#define tekhex_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+const bfd_target tekhex_vec =
+{
+ "tekhex", /* name */
+ bfd_target_tekhex_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* target headers byte order */
+ (EXEC_P | /* object flags */
+ HAS_SYMS | HAS_LINENO | HAS_DEBUG | HAS_RELOC | 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 */
+ 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,
+ tekhex_object_p, /* bfd_check_format */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ {
+ bfd_false,
+ tekhex_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ tekhex_write_object_contents,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (tekhex),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (tekhex),
+ BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+ BFD_JUMP_TABLE_WRITE (tekhex),
+ BFD_JUMP_TABLE_LINK (tekhex),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/trad-core.c b/contrib/gdb/bfd/trad-core.c
new file mode 100644
index 0000000..09c74ae
--- /dev/null
+++ b/contrib/gdb/bfd/trad-core.c
@@ -0,0 +1,316 @@
+/* BFD back end for traditional Unix core files (U-area and raw sections)
+ 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libaout.h" /* BFD a.out internal data structures */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+
+#include <sys/user.h> /* After a.out.h */
+
+#ifdef TRAD_HEADER
+#include TRAD_HEADER
+#endif
+
+ struct trad_core_struct
+ {
+ asection *data_section;
+ asection *stack_section;
+ asection *reg_section;
+ struct user u;
+ };
+
+#define core_upage(bfd) (&((bfd)->tdata.trad_core_data->u))
+#define core_datasec(bfd) ((bfd)->tdata.trad_core_data->data_section)
+#define core_stacksec(bfd) ((bfd)->tdata.trad_core_data->stack_section)
+#define core_regsec(bfd) ((bfd)->tdata.trad_core_data->reg_section)
+
+/* forward declarations */
+
+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
+ PARAMS ((bfd *core_bfd, bfd *exec_bfd));
+
+/* Handle 4.2-style (and perhaps also sysV-style) core dump file. */
+
+/* ARGSUSED */
+const bfd_target *
+trad_unix_core_file_p (abfd)
+ bfd *abfd;
+
+{
+ int val;
+ struct user u;
+ struct trad_core_struct *rawptr;
+
+#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)
+ return 0;
+#endif
+
+ val = bfd_read ((void *)&u, 1, sizeof u, abfd);
+ if (val != sizeof u)
+ {
+ /* Too small to be a core file */
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ /* Sanity check perhaps??? */
+ if (u.u_dsize > 0x1000000) /* Remember, it's in pages... */
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+ if (u.u_ssize > 0x1000000)
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+
+ /* Check that the size claimed is no greater than the file size. */
+ {
+ FILE *stream = bfd_cache_lookup (abfd);
+ struct stat statbuf;
+ if (stream == NULL)
+ return 0;
+ if (fstat (fileno (stream), &statbuf) < 0)
+ {
+ bfd_set_error (bfd_error_system_call);
+ return 0;
+ }
+ if (NBPG * (UPAGES + u.u_dsize
+#ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE
+ - u.u_tsize
+#endif
+ + u.u_ssize) > statbuf.st_size)
+ {
+ 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. */
+ + TRAD_CORE_EXTRA_SIZE_ALLOWED
+#endif
+ < statbuf.st_size)
+ {
+ /* 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_set_error (bfd_error_wrong_format);
+ return 0;
+ }
+#endif
+ }
+
+ /* OK, we believe you. You're a core file (sure, sure). */
+
+ /* 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_zmalloc (sizeof (struct trad_core_struct));
+ if (rawptr == NULL)
+ return 0;
+
+ abfd->tdata.trad_core_data = rawptr;
+
+ rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */
+
+ /* Create the sections. This is raunchy, but bfd_close wants to free
+ them separately. */
+
+ core_stacksec(abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_stacksec (abfd) == NULL)
+ return NULL;
+ core_datasec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_datasec (abfd) == NULL)
+ return NULL;
+ core_regsec (abfd) = (asection *) bfd_zalloc (abfd, sizeof (asection));
+ if (core_regsec (abfd) == NULL)
+ return NULL;
+
+ core_stacksec (abfd)->name = ".stack";
+ core_datasec (abfd)->name = ".data";
+ core_regsec (abfd)->name = ".reg";
+
+ 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_HAS_CONTENTS;
+
+ 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 */
+
+ /* What a hack... we'd like to steal it from the exec file,
+ since the upage does not seem to provide it. FIXME. */
+#ifdef HOST_DATA_START_ADDR
+ core_datasec (abfd)->vma = HOST_DATA_START_ADDR;
+#else
+ core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize);
+#endif
+
+#ifdef HOST_STACK_START_ADDR
+ core_stacksec (abfd)->vma = HOST_STACK_START_ADDR;
+#else
+ core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize);
+#endif
+
+ /* This is tricky. As the "register section", we give them the entire
+ upage and stack. u.u_ar0 points to where "register 0" is stored.
+ There are two tricks with this, though. One is that the rest of the
+ registers might be at positive or negative (or both) displacements
+ from *u_ar0. The other is that u_ar0 is sometimes an absolute address
+ in kernel memory, and on other systems it is an offset from the beginning
+ of the `struct user'.
+
+ As a practical matter, we don't know where the registers actually are,
+ so we have to pass the whole area to GDB. We encode the value of u_ar0
+ by setting the .regs section up so that its virtual memory address
+ 0 is at the place pointed to by u_ar0 (by setting the vma of the start
+ of the section to -u_ar0). GDB uses this info to locate the regs,
+ using minor trickery to get around the offset-or-absolute-addr problem. */
+ core_regsec (abfd)->vma = 0 - (bfd_vma) u.u_ar0;
+
+ core_datasec (abfd)->filepos = NBPG * UPAGES;
+ 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 */
+ core_stacksec (abfd)->alignment_power = 2;
+ core_datasec (abfd)->alignment_power = 2;
+ core_regsec (abfd)->alignment_power = 2;
+
+ abfd->sections = core_stacksec (abfd);
+ core_stacksec (abfd)->next = core_datasec (abfd);
+ core_datasec (abfd)->next = core_regsec (abfd);
+ abfd->section_count = 3;
+
+ return abfd->xvec;
+}
+
+char *
+trad_unix_core_file_failing_command (abfd)
+ bfd *abfd;
+{
+#ifndef NO_CORE_COMMAND
+ char *com = abfd->tdata.trad_core_data->u.u_comm;
+ if (*com)
+ return com;
+ else
+#endif
+ return 0;
+}
+
+/* ARGSUSED */
+int
+trad_unix_core_file_failing_signal (ignore_abfd)
+ bfd *ignore_abfd;
+{
+#ifdef TRAD_UNIX_CORE_FILE_FAILING_SIGNAL
+ return TRAD_UNIX_CORE_FILE_FAILING_SIGNAL(ignore_abfd);
+#else
+ return -1; /* FIXME, where is it? */
+#endif
+}
+
+/* ARGSUSED */
+boolean
+trad_unix_core_file_matches_executable_p (core_bfd, exec_bfd)
+ bfd *core_bfd, *exec_bfd;
+{
+ return true; /* FIXME, We have no way of telling at this point */
+}
+
+/* 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 (( const bfd_byte *))) swap_abort )
+#define NO_PUT ((void (*) PARAMS ((bfd_vma, bfd_byte *))) swap_abort )
+#define NO_SIGNED_GET \
+ ((bfd_signed_vma (*) PARAMS ((const bfd_byte *))) swap_abort )
+
+const bfd_target trad_core_vec =
+ {
+ "trad-core",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_UNKNOWN, /* target byte order */
+ BFD_ENDIAN_UNKNOWN, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ 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 */
+ 16, /* ar_max_namelen */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit data */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 64 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 32 bit hdrs */
+ NO_GET, NO_SIGNED_GET, NO_PUT, /* 16 bit hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ trad_unix_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ 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/contrib/gdb/bfd/versados.c b/contrib/gdb/bfd/versados.c
new file mode 100644
index 0000000..84ad114
--- /dev/null
+++ b/contrib/gdb/bfd/versados.c
@@ -0,0 +1,906 @@
+/* BFD back-end for VERSAdos-E objects.
+
+ Versados is a Motorola trademark.
+
+ Copyright 1995 Free Software Foundation, Inc.
+ Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ SUBSECTION
+ VERSAdos-E relocateable object file format
+
+ DESCRIPTION
+
+ This module supports reading of VERSAdos relocateable
+ object files.
+
+ A VERSAdos file looks like contains
+
+ o Indentification Record
+ o External Symbol Definition Record
+ o Object Text Recrod
+ o End Record
+
+
+ */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "libbfd.h"
+#include "libiberty.h"
+
+
+static boolean versados_mkobject PARAMS ((bfd *));
+static boolean versados_scan PARAMS ((bfd *));
+static const bfd_target *versados_object_p PARAMS ((bfd *));
+
+
+#define VHEADER '1'
+#define VESTDEF '2'
+#define VOTR '3'
+#define VEND '4'
+
+
+#define ES_BASE 17 /* first symbol has esdid 17 */
+
+/* Per file target dependent information */
+
+/* one for each section */
+struct esdid
+ {
+ asection *section; /* ptr to bfd version */
+ unsigned char *contents; /* used to build image */
+ int pc;
+ int relocs; /* reloc count, valid end of pass 1 */
+ int donerel; /* have relocs been translated */
+ };
+
+typedef struct versados_data_struct
+ {
+ int es_done; /* count of symbol index, starts at ES_BASE */
+ asymbol *symbols; /* pointer to local symbols */
+ char *strings; /* strings of all the above */
+ int stringlen; /* len of string table (valid end of pass1) */
+ int nsecsyms; /* number of sections */
+
+ int ndefs; /* number of exported symbols (they dont get esdids) */
+ int nrefs; /* number of imported symbols (valid end of pass1) */
+
+ int ref_idx; /* current processed value of the above */
+ int def_idx;
+
+ int pass_2_done;
+
+ struct esdid e[16]; /* per section info */
+ int alert; /* to see if we're trampling */
+ asymbol *rest[256 - 16]; /* per symbol info */
+
+ }
+tdata_type;
+
+#define VDATA(abfd) (abfd->tdata.versados_data)
+#define EDATA(abfd, n) (abfd->tdata.versados_data->e[n])
+#define RDATA(abfd, n) (abfd->tdata.versados_data->rest[n])
+
+struct ext_otr
+ {
+ unsigned char size;
+ char type;
+ unsigned char map[4];
+ unsigned char esdid;
+ unsigned char data[200];
+ };
+
+struct ext_vheader
+ {
+ unsigned char size;
+ char type; /* record type */
+ char name[10]; /* module name */
+ char rev; /* module rev number */
+ char lang;
+ char vol[4];
+ char user[2];
+ char cat[8];
+ char fname[8];
+ char ext[2];
+ char time[3];
+ char date[3];
+ char rest[211];
+ };
+
+struct ext_esd
+ {
+ unsigned char size;
+ char type;
+ unsigned char esd_entries[1];
+ };
+#define ESD_ABS 0
+#define ESD_COMMON 1
+#define ESD_STD_REL_SEC 2
+#define ESD_SHRT_REL_SEC 3
+#define ESD_XDEF_IN_SEC 4
+#define ESD_XREF_SYM 7
+#define ESD_XREF_SEC 6
+#define ESD_XDEF_IN_ABS 5
+union ext_any
+ {
+ unsigned char size;
+ struct ext_vheader header;
+ struct ext_esd esd;
+ struct ext_otr otr;
+ };
+
+/* Initialize by filling in the hex conversion array. */
+
+
+
+
+
+/* Set up the tdata information. */
+
+static boolean
+versados_mkobject (abfd)
+ bfd *abfd;
+{
+ if (abfd->tdata.versados_data == NULL)
+ {
+ tdata_type *tdata = (tdata_type *) bfd_alloc (abfd, sizeof (tdata_type));
+ if (tdata == NULL)
+ return false;
+ abfd->tdata.versados_data = tdata;
+ tdata->symbols = NULL;
+ VDATA (abfd)->alert = 0x12345678;
+ }
+
+ bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0);
+ return true;
+}
+
+
+/* Report a problem in an S record file. FIXME: This probably should
+ not call fprintf, but we really do need some mechanism for printing
+ error messages. */
+
+
+
+static asymbol *
+versados_new_symbol (abfd, snum, name, val, sec)
+ bfd *abfd;
+ int snum;
+ const char *name;
+ bfd_vma val;
+ asection *sec;
+{
+ asymbol *n = VDATA (abfd)->symbols + snum;
+ n->name = name;
+ n->value = val;
+ n->section = sec;
+ n->the_bfd = abfd;
+ n->flags = 0;
+ return n;
+}
+
+
+static int
+get_record (abfd, ptr)
+ bfd *abfd;
+ union ext_any *ptr;
+{
+ bfd_read (&ptr->size, 1, 1, abfd);
+ if (bfd_read ((char *) ptr + 1, 1, ptr->size, abfd) != ptr->size)
+ return 0;
+ return 1;
+}
+
+int
+get_4 (pp)
+ unsigned char **pp;
+{
+ unsigned char *p = *pp;
+ *pp += 4;
+ return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
+}
+
+void
+get_10 (pp, name)
+ unsigned char **pp;
+ char *name;
+{
+ char *p = (char *) *pp;
+ int len = 10;
+ *pp += len;
+ while (*p != ' '
+ && len)
+ {
+ *name++ = *p++;
+ len--;
+ }
+ *name = 0;
+}
+
+static char *
+new_symbol_string (abfd, name)
+ bfd *abfd;
+ char *name;
+{
+ char *n = VDATA (abfd)->strings;
+ strcpy (VDATA (abfd)->strings, name);
+ VDATA (abfd)->strings += strlen (VDATA (abfd)->strings) + 1;
+ return n;
+}
+
+
+static void
+process_esd (abfd, esd, pass)
+ bfd *abfd;
+ struct ext_esd *esd;
+ int pass;
+{
+ /* Read through the ext def for the est entries */
+ int togo = esd->size - 2;
+ bfd_vma size;
+ bfd_vma start;
+ asection *sec;
+ char name[11];
+ unsigned char *ptr = esd->esd_entries;
+ unsigned char *end = ptr + togo;
+ while (ptr < end)
+ {
+ int scn = *ptr & 0xf;
+ int typ = (*ptr >> 4) & 0xf;
+
+ /* Declare this section */
+ sprintf (name, "%d", scn);
+ sec = bfd_make_section_old_way (abfd, strdup (name));
+ sec->target_index = scn;
+ EDATA (abfd, scn).section = sec;
+ ptr++;
+ switch (typ)
+ {
+ default:
+ abort ();
+ case ESD_XREF_SEC:
+ case ESD_XREF_SYM:
+ {
+ int snum = VDATA (abfd)->ref_idx++;
+ get_10 (&ptr, name);
+ if (pass == 1)
+ {
+ VDATA (abfd)->stringlen += strlen (name) + 1;
+ }
+ else
+ {
+ int esidx;
+ asymbol *s;
+ char *n = new_symbol_string (abfd, name);
+ s = versados_new_symbol (abfd, snum, n, 0,
+ &bfd_und_section, scn);
+ esidx = VDATA (abfd)->es_done++;
+ RDATA (abfd, esidx - ES_BASE) = s;
+ }
+ }
+ break;
+
+
+ case ESD_ABS:
+ size = get_4 (&ptr);
+ start = get_4 (&ptr);
+ break;
+ case ESD_STD_REL_SEC:
+ case ESD_SHRT_REL_SEC:
+ {
+ sec->_raw_size = get_4 (&ptr);
+ sec->flags |= SEC_ALLOC;
+ }
+ break;
+ case ESD_XDEF_IN_ABS:
+ sec = (asection *) & bfd_abs_section;
+ case ESD_XDEF_IN_SEC:
+ {
+ int snum = VDATA (abfd)->def_idx++;
+ long val;
+ get_10 (&ptr, name);
+ val = get_4 (&ptr);
+ if (pass == 1)
+ {
+ /* Just remember the symbol */
+ VDATA (abfd)->stringlen += strlen (name) + 1;
+ }
+ else
+ {
+ asymbol *s;
+ char *n = new_symbol_string (abfd, name);
+ s = versados_new_symbol (abfd, snum + VDATA (abfd)->nrefs, n, val, sec, scn);
+ s->flags |= BSF_GLOBAL;
+ }
+ }
+ break;
+ }
+ }
+}
+
+#define R_RELWORD 1
+#define R_RELLONG 2
+#define R_RELWORD_NEG 3
+#define R_RELLONG_NEG 4
+
+reloc_howto_type versados_howto_table[] =
+{
+ HOWTO (R_RELWORD, 0, 1, 16, false,
+ 0, complain_overflow_dont, 0,
+ "+v16", true, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_RELLONG, 0, 2, 32, false,
+ 0, complain_overflow_dont, 0,
+ "+v32", true, 0xffffffff, 0xffffffff, false),
+
+ HOWTO (R_RELWORD_NEG, 0, -1, 16, false,
+ 0, complain_overflow_dont, 0,
+ "-v16", true, 0x0000ffff, 0x0000ffff, false),
+ HOWTO (R_RELLONG_NEG, 0, -2, 32, false,
+ 0, complain_overflow_dont, 0,
+ "-v32", true, 0xffffffff, 0xffffffff, false),
+};
+
+
+static int
+get_offset (len, ptr)
+ int len;
+ unsigned char *ptr;
+{
+ int val = 0;
+ if (len)
+ {
+ int i;
+ val = *ptr++;
+ if (val & 0x80)
+ val |= ~0xff;
+ for (i = 1; i < len; i++)
+ val = (val << 8) | *ptr++;
+ }
+
+ return val;
+}
+
+static void
+process_otr (abfd, otr, pass)
+ bfd *abfd;
+ struct ext_otr *otr;
+ int pass;
+{
+ unsigned long shift;
+ unsigned char *srcp = otr->data;
+ unsigned char *endp = (unsigned char *) otr + otr->size;
+ unsigned int bits = (otr->map[0] << 24)
+ | (otr->map[1] << 16)
+ | (otr->map[2] << 8)
+ | (otr->map[3] << 0);
+
+ struct esdid *esdid = &EDATA (abfd, otr->esdid - 1);
+ unsigned char *contents = esdid->contents;
+ int need_contents = 0;
+ unsigned int dst_idx = esdid->pc;
+
+ for (shift = (1 << 31); shift && srcp < endp; shift >>= 1)
+ {
+ if (bits & shift)
+ {
+ int flag = *srcp++;
+ int esdids = (flag >> 5) & 0x7;
+ int sizeinwords = ((flag >> 3) & 1) ? 2 : 1;
+ int offsetlen = flag & 0x7;
+ int j;
+
+
+ if (esdids == 0)
+ {
+ /* A zero esdid means the new pc is the offset given */
+ dst_idx += get_offset (offsetlen, srcp);
+ srcp += offsetlen;
+ }
+ else
+ {
+ int val = get_offset (offsetlen, srcp + esdids);
+ if (pass == 1)
+ need_contents = 1;
+ else
+ for (j = 0; j < sizeinwords * 2; j++)
+ {
+ contents[dst_idx + (sizeinwords * 2) - j - 1] = val;
+ val >>= 8;
+ }
+
+ for (j = 0; j < esdids; j++)
+ {
+ int esdid = *srcp++;
+
+ if (esdid)
+ {
+ int rn = EDATA (abfd, otr->esdid - 1).relocs++;
+ if (pass == 1)
+ {
+ /* this is the first pass over the data,
+ just remember that we need a reloc */
+ }
+ else
+ {
+ arelent *n =
+ EDATA (abfd, otr->esdid - 1).section->relocation + rn;
+ n->address = dst_idx;
+
+ n->sym_ptr_ptr = (asymbol **) esdid;
+ n->addend = 0;
+ n->howto = versados_howto_table + ((j & 1) * 2) + (sizeinwords - 1);
+ }
+ }
+ }
+ srcp += offsetlen;
+ dst_idx += sizeinwords * 2;
+ }
+ }
+ else
+ {
+ need_contents = 1;
+ if (dst_idx < esdid->section->_raw_size)
+ if (pass == 2)
+ {
+ /* absolute code, comes in 16 bit lumps */
+ contents[dst_idx] = srcp[0];
+ contents[dst_idx + 1] = srcp[1];
+ }
+ dst_idx += 2;
+ srcp += 2;
+ }
+ }
+ EDATA (abfd, otr->esdid - 1).pc = dst_idx;
+
+ if (!contents && need_contents)
+ esdid->contents = (unsigned char *) bfd_alloc (abfd, esdid->section->_raw_size);
+
+
+}
+
+static boolean
+versados_scan (abfd)
+ bfd *abfd;
+{
+ int loop = 1;
+ int i;
+ int j;
+ int nsecs = 0;
+
+ VDATA (abfd)->nrefs = 0;
+ VDATA (abfd)->ndefs = 0;
+ VDATA (abfd)->ref_idx = 0;
+ VDATA (abfd)->def_idx = 0;
+
+ while (loop)
+ {
+ union ext_any any;
+ if (!get_record (abfd, &any))
+ return true;
+ switch (any.header.type)
+ {
+ case VHEADER:
+ break;
+ case VEND:
+ loop = 0;
+ break;
+ case VESTDEF:
+ process_esd (abfd, &any.esd, 1);
+ break;
+ case VOTR:
+ process_otr (abfd, &any.otr, 1);
+ break;
+ }
+ }
+
+ /* Now allocate space for the relocs and sections */
+
+ VDATA (abfd)->nrefs = VDATA (abfd)->ref_idx;
+ VDATA (abfd)->ndefs = VDATA (abfd)->def_idx;
+ VDATA (abfd)->ref_idx = 0;
+ VDATA (abfd)->def_idx = 0;
+
+ abfd->symcount = VDATA (abfd)->nrefs + VDATA (abfd)->ndefs;
+
+ for (i = 0; i < 16; i++)
+ {
+ struct esdid *esdid = &EDATA (abfd, i);
+ if (esdid->section)
+ {
+ esdid->section->relocation
+ = (arelent *) bfd_alloc (abfd, sizeof (arelent) * esdid->relocs);
+
+ esdid->pc = 0;
+
+ if (esdid->contents)
+ esdid->section->flags |= SEC_HAS_CONTENTS | SEC_LOAD;
+
+ esdid->section->reloc_count = esdid->relocs;
+ if (esdid->relocs)
+ esdid->section->flags |= SEC_RELOC;
+
+ esdid->relocs = 0;
+
+ /* Add an entry into the symbol table for it */
+ nsecs++;
+ VDATA (abfd)->stringlen += strlen (esdid->section->name) + 1;
+ }
+ }
+
+ abfd->symcount += nsecs;
+
+ VDATA (abfd)->symbols = (asymbol *) bfd_alloc (abfd,
+ sizeof (asymbol) * (abfd->symcount));
+
+ VDATA (abfd)->strings = bfd_alloc (abfd, VDATA (abfd)->stringlen);
+
+
+ /* Actually fill in the section symbols,
+ we stick them at the end of the table */
+
+ for (j = VDATA (abfd)->nrefs + VDATA (abfd)->ndefs, i = 0; i < 16; i++)
+ {
+ struct esdid *esdid = &EDATA (abfd, i);
+ asection *sec = esdid->section;
+ if (sec)
+ {
+ asymbol *s = VDATA (abfd)->symbols + j;
+ s->name = new_symbol_string (abfd, sec->name);
+ s->section = sec;
+ s->flags = BSF_LOCAL;
+ s->value = 0;
+ s->the_bfd = abfd;
+ j++;
+ }
+ }
+ if (abfd->symcount)
+ abfd->flags |= HAS_SYMS;
+
+ /* Set this to nsecs - since we've already planted the section
+ symbols */
+ VDATA (abfd)->nsecsyms = nsecs;
+
+ VDATA (abfd)->ref_idx = 0;
+
+ return 1;
+}
+
+
+
+/* Check whether an existing file is a versados file. */
+
+static const bfd_target *
+versados_object_p (abfd)
+ bfd *abfd;
+{
+ struct ext_vheader ext;
+ unsigned char len;
+
+ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET))
+ return NULL;
+
+
+ bfd_read (&len, 1, 1, abfd);
+ if (bfd_read (&ext.type, 1, len, abfd) != len
+ || ext.type != '1')
+ {
+ bfd_set_error (bfd_error_wrong_format);
+ return NULL;
+ }
+
+ /* ok, looks like a record, build the tdata and read
+ in.. */
+
+ if (!versados_mkobject (abfd)
+ || !versados_scan (abfd))
+ return NULL;
+
+ return abfd->xvec;
+}
+
+
+static boolean
+versados_pass_2 (abfd)
+ bfd *abfd;
+{
+ union ext_any any;
+
+ if (VDATA (abfd)->pass_2_done)
+ return 1;
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0)
+ return 0;
+
+ VDATA (abfd)->es_done = ES_BASE;
+
+
+ /* read records till we get to where we want to be */
+
+ while (1)
+ {
+ get_record (abfd, &any);
+ switch (any.header.type)
+ {
+ case VEND:
+ VDATA (abfd)->pass_2_done = 1;
+ return 1;
+ case VESTDEF:
+ process_esd (abfd, &any.esd, 2);
+ break;
+ case VOTR:
+ process_otr (abfd, &any.otr, 2);
+ break;
+ }
+ }
+}
+
+static boolean
+versados_get_section_contents (abfd, section, location, offset, count)
+ bfd *abfd;
+ asection *section;
+ PTR location;
+ file_ptr offset;
+ bfd_size_type count;
+{
+ if (!versados_pass_2 (abfd))
+ return false;
+
+ memcpy (location,
+ EDATA (abfd, section->target_index).contents + offset,
+ (size_t) count);
+
+ return true;
+}
+
+#define versados_get_section_contents_in_window \
+ _bfd_generic_get_section_contents_in_window
+
+static boolean
+versados_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;
+{
+ return false;
+}
+
+
+/*ARGSUSED */
+static int
+versados_sizeof_headers (abfd, exec)
+ bfd *abfd;
+ boolean exec;
+{
+ return 0;
+}
+
+static asymbol *
+versados_make_empty_symbol (abfd)
+ bfd *abfd;
+{
+ asymbol *new = (asymbol *) bfd_zalloc (abfd, sizeof (asymbol));
+ if (new)
+ new->the_bfd = abfd;
+ return new;
+}
+
+/* Return the amount of memory needed to read the symbol table. */
+
+static long
+versados_get_symtab_upper_bound (abfd)
+ bfd *abfd;
+{
+ return (bfd_get_symcount (abfd) + 1) * sizeof (asymbol *);
+}
+
+/* Return the symbol table. */
+
+static long
+versados_get_symtab (abfd, alocation)
+ bfd *abfd;
+ asymbol **alocation;
+{
+ unsigned int symcount = bfd_get_symcount (abfd);
+ unsigned int i;
+ asymbol *s;
+
+ versados_pass_2 (abfd);
+
+ for (i = 0, s = VDATA (abfd)->symbols;
+ i < symcount;
+ s++, i++)
+ {
+ *alocation++ = s;
+ }
+
+ *alocation = NULL;
+
+ return symcount;
+}
+
+/*ARGSUSED */
+void
+versados_get_symbol_info (ignore_abfd, symbol, ret)
+ bfd *ignore_abfd;
+ asymbol *symbol;
+ symbol_info *ret;
+{
+ bfd_symbol_info (symbol, ret);
+}
+
+/*ARGSUSED */
+void
+versados_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);
+
+ }
+}
+
+long
+versados_get_reloc_upper_bound (abfd, asect)
+ bfd *abfd;
+ sec_ptr asect;
+{
+ return (asect->reloc_count + 1) * sizeof (arelent *);
+}
+
+
+long
+versados_canonicalize_reloc (abfd, section, relptr, symbols)
+ bfd *abfd;
+ sec_ptr section;
+ arelent **relptr;
+ asymbol **symbols;
+{
+ unsigned int count;
+ arelent *src;
+
+ versados_pass_2 (abfd);
+ src = section->relocation;
+ if (!EDATA (abfd, section->target_index).donerel)
+ {
+ EDATA (abfd, section->target_index).donerel = 1;
+ /* translate from indexes to symptr ptrs */
+ for (count = 0; count < section->reloc_count; count++)
+ {
+ int esdid = (int) src[count].sym_ptr_ptr;
+
+ if (esdid == 0)
+ {
+ src[count].sym_ptr_ptr = bfd_abs_section.symbol_ptr_ptr;
+ }
+ else if (esdid < ES_BASE) /* Section relative thing */
+ {
+ struct esdid *e = &EDATA (abfd, esdid - 1);
+ if (!section)
+ {
+ /** relocation relative to section which was
+ never declared ! */
+ }
+ src[count].sym_ptr_ptr = e->section->symbol_ptr_ptr;
+ }
+ else
+ {
+ src[count].sym_ptr_ptr = symbols + esdid - ES_BASE;
+ }
+
+ }
+ }
+
+ for (count = 0; count < section->reloc_count; count++)
+ {
+ *relptr++ = src++;
+ }
+ *relptr = 0;
+ return section->reloc_count;
+}
+
+#define versados_close_and_cleanup _bfd_generic_close_and_cleanup
+#define versados_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
+#define versados_new_section_hook _bfd_generic_new_section_hook
+
+#define versados_bfd_is_local_label bfd_generic_is_local_label
+#define versados_get_lineno _bfd_nosymbols_get_lineno
+#define versados_find_nearest_line _bfd_nosymbols_find_nearest_line
+#define versados_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
+#define versados_read_minisymbols _bfd_generic_read_minisymbols
+#define versados_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
+
+#define versados_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
+
+#define versados_set_arch_mach bfd_default_set_arch_mach
+
+#define versados_bfd_get_relocated_section_contents \
+ bfd_generic_get_relocated_section_contents
+#define versados_bfd_relax_section bfd_generic_relax_section
+#define versados_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
+#define versados_bfd_link_add_symbols _bfd_generic_link_add_symbols
+#define versados_bfd_final_link _bfd_generic_final_link
+#define versados_bfd_link_split_section _bfd_generic_link_split_section
+
+const bfd_target versados_vec =
+{
+ "versados", /* name */
+ bfd_target_versados_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* 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 */
+ 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,
+ versados_object_p, /* bfd_check_format */
+ _bfd_dummy_target,
+ _bfd_dummy_target,
+ },
+ {
+ bfd_false,
+ versados_mkobject,
+ _bfd_generic_mkarchive,
+ bfd_false,
+ },
+ { /* bfd_write_contents */
+ bfd_false,
+ bfd_false,
+ _bfd_write_archive_contents,
+ bfd_false,
+ },
+
+ BFD_JUMP_TABLE_GENERIC (versados),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (_bfd_nocore),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (versados),
+ BFD_JUMP_TABLE_RELOCS (versados),
+ BFD_JUMP_TABLE_WRITE (versados),
+ BFD_JUMP_TABLE_LINK (versados),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ (PTR) 0
+};
diff --git a/contrib/gdb/bfd/xcofflink.c b/contrib/gdb/bfd/xcofflink.c
new file mode 100644
index 0000000..16a76cc
--- /dev/null
+++ b/contrib/gdb/bfd/xcofflink.c
@@ -0,0 +1,5798 @@
+/* POWER/PowerPC XCOFF linker support.
+ Copyright 1995, 1996 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <ian@cygnus.com>, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+#include "libbfd.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+
+/* This file holds the XCOFF linker code. */
+
+#define STRING_SIZE_SIZE (4)
+
+/* In order to support linking different object file formats into an
+ XCOFF format, we need to be able to determine whether a particular
+ bfd_target is an XCOFF vector. FIXME: We need to rethink this
+ whole approach. */
+#define XCOFF_XVECP(xv) \
+ (strcmp ((xv)->name, "aixcoff-rs6000") == 0 \
+ || strcmp ((xv)->name, "xcoff-powermac") == 0)
+
+/* Get the XCOFF hash table entries for a BFD. */
+#define obj_xcoff_sym_hashes(bfd) \
+ ((struct xcoff_link_hash_entry **) obj_coff_sym_hashes (bfd))
+
+/* XCOFF relocation types. These probably belong in a header file
+ somewhere. The relocations are described in the function
+ _bfd_ppc_xcoff_relocate_section in this file. */
+
+#define R_POS (0x00)
+#define R_NEG (0x01)
+#define R_REL (0x02)
+#define R_TOC (0x03)
+#define R_RTB (0x04)
+#define R_GL (0x05)
+#define R_TCL (0x06)
+#define R_BA (0x08)
+#define R_BR (0x0a)
+#define R_RL (0x0c)
+#define R_RLA (0x0d)
+#define R_REF (0x0f)
+#define R_TRL (0x12)
+#define R_TRLA (0x13)
+#define R_RRTBI (0x14)
+#define R_RRTBA (0x15)
+#define R_CAI (0x16)
+#define R_CREL (0x17)
+#define R_RBA (0x18)
+#define R_RBAC (0x19)
+#define R_RBR (0x1a)
+#define R_RBRC (0x1b)
+
+/* The first word of global linkage code. This must be modified by
+ filling in the correct TOC offset. */
+
+#define XCOFF_GLINK_FIRST (0x81820000) /* lwz r12,0(r2) */
+
+/* The remaining words of global linkage code. */
+
+static unsigned long xcoff_glink_code[] =
+{
+ 0x90410014, /* stw r2,20(r1) */
+ 0x800c0000, /* lwz r0,0(r12) */
+ 0x804c0004, /* lwz r2,4(r12) */
+ 0x7c0903a6, /* mtctr r0 */
+ 0x4e800420, /* bctr */
+ 0x0, /* start of traceback table */
+ 0x000c8000, /* traceback table */
+ 0x0 /* traceback table */
+};
+
+#define XCOFF_GLINK_SIZE \
+ (((sizeof xcoff_glink_code / sizeof xcoff_glink_code[0]) * 4) + 4)
+
+/* We reuse the SEC_ROM flag as a mark flag for garbage collection.
+ This flag will only be used on input sections. */
+
+#define SEC_MARK (SEC_ROM)
+
+/* The ldhdr structure. This appears at the start of the .loader
+ section. */
+
+struct internal_ldhdr
+{
+ /* The version number: currently always 1. */
+ unsigned long l_version;
+ /* The number of symbol table entries. */
+ bfd_size_type l_nsyms;
+ /* The number of relocation table entries. */
+ bfd_size_type l_nreloc;
+ /* The length of the import file string table. */
+ bfd_size_type l_istlen;
+ /* The number of import files. */
+ bfd_size_type l_nimpid;
+ /* The offset from the start of the .loader section to the first
+ entry in the import file table. */
+ bfd_size_type l_impoff;
+ /* The length of the string table. */
+ bfd_size_type l_stlen;
+ /* The offset from the start of the .loader section to the first
+ entry in the string table. */
+ bfd_size_type l_stoff;
+};
+
+struct external_ldhdr
+{
+ bfd_byte l_version[4];
+ bfd_byte l_nsyms[4];
+ bfd_byte l_nreloc[4];
+ bfd_byte l_istlen[4];
+ bfd_byte l_nimpid[4];
+ bfd_byte l_impoff[4];
+ bfd_byte l_stlen[4];
+ bfd_byte l_stoff[4];
+};
+
+#define LDHDRSZ (8 * 4)
+
+/* The ldsym structure. This is used to represent a symbol in the
+ .loader section. */
+
+struct internal_ldsym
+{
+ union
+ {
+ /* The symbol name if <= SYMNMLEN characters. */
+ char _l_name[SYMNMLEN];
+ struct
+ {
+ /* Zero if the symbol name is more than SYMNMLEN characters. */
+ long _l_zeroes;
+ /* The offset in the string table if the symbol name is more
+ than SYMNMLEN characters. */
+ long _l_offset;
+ } _l_l;
+ } _l;
+ /* The symbol value. */
+ bfd_vma l_value;
+ /* The symbol section number. */
+ short l_scnum;
+ /* The symbol type and flags. */
+ char l_smtype;
+ /* The symbol storage class. */
+ char l_smclas;
+ /* The import file ID. */
+ bfd_size_type l_ifile;
+ /* Offset to the parameter type check string. */
+ bfd_size_type l_parm;
+};
+
+struct external_ldsym
+{
+ union
+ {
+ bfd_byte _l_name[SYMNMLEN];
+ struct
+ {
+ bfd_byte _l_zeroes[4];
+ bfd_byte _l_offset[4];
+ } _l_l;
+ } _l;
+ bfd_byte l_value[4];
+ bfd_byte l_scnum[2];
+ bfd_byte l_smtype[1];
+ bfd_byte l_smclas[1];
+ bfd_byte l_ifile[4];
+ bfd_byte l_parm[4];
+};
+
+#define LDSYMSZ (8 + 3 * 4 + 2 + 2)
+
+/* These flags are for the l_smtype field (the lower three bits are an
+ XTY_* value). */
+
+/* Imported symbol. */
+#define L_IMPORT (0x40)
+/* Entry point. */
+#define L_ENTRY (0x20)
+/* Exported symbol. */
+#define L_EXPORT (0x10)
+
+/* The ldrel structure. This is used to represent a reloc in the
+ .loader section. */
+
+struct internal_ldrel
+{
+ /* The reloc address. */
+ bfd_vma l_vaddr;
+ /* The symbol table index in the .loader section symbol table. */
+ bfd_size_type l_symndx;
+ /* The relocation type and size. */
+ short l_rtype;
+ /* The section number this relocation applies to. */
+ short l_rsecnm;
+};
+
+struct external_ldrel
+{
+ bfd_byte l_vaddr[4];
+ bfd_byte l_symndx[4];
+ bfd_byte l_rtype[2];
+ bfd_byte l_rsecnm[2];
+};
+
+#define LDRELSZ (2 * 4 + 2 * 2)
+
+/* The list of import files. */
+
+struct xcoff_import_file
+{
+ /* The next entry in the list. */
+ struct xcoff_import_file *next;
+ /* The path. */
+ const char *path;
+ /* The file name. */
+ const char *file;
+ /* The member name. */
+ const char *member;
+};
+
+/* An entry in the XCOFF linker hash table. */
+
+struct xcoff_link_hash_entry
+{
+ struct bfd_link_hash_entry root;
+
+ /* Symbol index in output file. Set to -1 initially. Set to -2 if
+ there is a reloc against this symbol. */
+ long indx;
+
+ /* If we have created a TOC entry for this symbol, this is the .tc
+ section which holds it. */
+ asection *toc_section;
+
+ union
+ {
+ /* If we have created a TOC entry (the XCOFF_SET_TOC flag is
+ set), this is the offset in toc_section. */
+ bfd_vma toc_offset;
+ /* If the TOC entry comes from an input file, this is set to the
+ symbo lindex of the C_HIDEXT XMC_TC symbol. */
+ long toc_indx;
+ } u;
+
+ /* If this symbol is a function entry point which is called, this
+ field holds a pointer to the function descriptor. If this symbol
+ is a function descriptor, this field holds a pointer to the
+ function entry point. */
+ struct xcoff_link_hash_entry *descriptor;
+
+ /* The .loader symbol table entry, if there is one. */
+ struct internal_ldsym *ldsym;
+
+ /* The .loader symbol table index. */
+ long ldindx;
+
+ /* Some linker flags. */
+ unsigned short flags;
+ /* Symbol is referenced by a regular object. */
+#define XCOFF_REF_REGULAR (01)
+ /* Symbol is defined by a regular object. */
+#define XCOFF_DEF_REGULAR (02)
+ /* Symbol is defined by a dynamic object. */
+#define XCOFF_DEF_DYNAMIC (04)
+ /* Symbol is used in a reloc being copied into the .loader section. */
+#define XCOFF_LDREL (010)
+ /* Symbol is the entry point. */
+#define XCOFF_ENTRY (020)
+ /* Symbol is called; this is, it appears in a R_BR reloc. */
+#define XCOFF_CALLED (040)
+ /* Symbol needs the TOC entry filled in. */
+#define XCOFF_SET_TOC (0100)
+ /* Symbol is explicitly imported. */
+#define XCOFF_IMPORT (0200)
+ /* Symbol is explicitly exported. */
+#define XCOFF_EXPORT (0400)
+ /* Symbol has been processed by xcoff_build_ldsyms. */
+#define XCOFF_BUILT_LDSYM (01000)
+ /* Symbol is mentioned by a section which was not garbage collected. */
+#define XCOFF_MARK (02000)
+ /* Symbol size is recorded in size_list list from hash table. */
+#define XCOFF_HAS_SIZE (04000)
+ /* Symbol is a function descriptor. */
+#define XCOFF_DESCRIPTOR (010000)
+
+ /* The storage mapping class. */
+ unsigned char smclas;
+};
+
+/* The XCOFF linker hash table. */
+
+struct xcoff_link_hash_table
+{
+ struct bfd_link_hash_table root;
+
+ /* The .debug string hash table. We need to compute this while
+ reading the input files, so that we know how large the .debug
+ section will be before we assign section positions. */
+ struct bfd_strtab_hash *debug_strtab;
+
+ /* The .debug section we will use for the final output. */
+ asection *debug_section;
+
+ /* The .loader section we will use for the final output. */
+ asection *loader_section;
+
+ /* A count of non TOC relative relocs which will need to be
+ allocated in the .loader section. */
+ size_t ldrel_count;
+
+ /* The .loader section header. */
+ struct internal_ldhdr ldhdr;
+
+ /* The .gl section we use to hold global linkage code. */
+ asection *linkage_section;
+
+ /* The .tc section we use to hold toc entries we build for global
+ linkage code. */
+ asection *toc_section;
+
+ /* The .ds section we use to hold function descriptors which we
+ create for exported symbols. */
+ asection *descriptor_section;
+
+ /* The list of import files. */
+ struct xcoff_import_file *imports;
+
+ /* Required alignment of sections within the output file. */
+ unsigned long file_align;
+
+ /* Whether the .text section must be read-only. */
+ boolean textro;
+
+ /* Whether garbage collection was done. */
+ boolean gc;
+
+ /* A linked list of symbols for which we have size information. */
+ struct xcoff_link_size_list
+ {
+ struct xcoff_link_size_list *next;
+ struct xcoff_link_hash_entry *h;
+ bfd_size_type size;
+ } *size_list;
+
+ /* Magic sections: _text, _etext, _data, _edata, _end, end. */
+ asection *special_sections[6];
+};
+
+/* Information we keep for each section in the output file during the
+ final link phase. */
+
+struct xcoff_link_section_info
+{
+ /* The relocs to be output. */
+ struct internal_reloc *relocs;
+ /* For each reloc against a global symbol whose index was not known
+ when the reloc was handled, the global hash table entry. */
+ struct xcoff_link_hash_entry **rel_hashes;
+ /* If there is a TOC relative reloc against a global symbol, and the
+ index of the TOC symbol is not known when the reloc was handled,
+ an entry is added to this linked list. This is not an array,
+ like rel_hashes, because this case is quite uncommon. */
+ struct xcoff_toc_rel_hash
+ {
+ struct xcoff_toc_rel_hash *next;
+ struct xcoff_link_hash_entry *h;
+ struct internal_reloc *rel;
+ } *toc_rel_hashes;
+};
+
+/* Information that we pass around while doing the final link step. */
+
+struct xcoff_final_link_info
+{
+ /* General link information. */
+ struct bfd_link_info *info;
+ /* Output BFD. */
+ bfd *output_bfd;
+ /* Hash table for long symbol names. */
+ struct bfd_strtab_hash *strtab;
+ /* Array of information kept for each output section, indexed by the
+ target_index field. */
+ struct xcoff_link_section_info *section_info;
+ /* Symbol index of last C_FILE symbol (-1 if none). */
+ long last_file_index;
+ /* Contents of last C_FILE symbol. */
+ struct internal_syment last_file;
+ /* Symbol index of TOC symbol. */
+ long toc_symindx;
+ /* Start of .loader symbols. */
+ struct external_ldsym *ldsym;
+ /* Next .loader reloc to swap out. */
+ struct external_ldrel *ldrel;
+ /* File position of start of line numbers. */
+ file_ptr line_filepos;
+ /* Buffer large enough to hold swapped symbols of any input file. */
+ struct internal_syment *internal_syms;
+ /* Buffer large enough to hold output indices of symbols of any
+ input file. */
+ long *sym_indices;
+ /* Buffer large enough to hold output symbols for any input file. */
+ bfd_byte *outsyms;
+ /* Buffer large enough to hold external line numbers for any input
+ section. */
+ bfd_byte *linenos;
+ /* Buffer large enough to hold any input section. */
+ bfd_byte *contents;
+ /* Buffer large enough to hold external relocs of any input section. */
+ bfd_byte *external_relocs;
+};
+
+static void xcoff_swap_ldhdr_in
+ PARAMS ((bfd *, const struct external_ldhdr *, struct internal_ldhdr *));
+static void xcoff_swap_ldhdr_out
+ PARAMS ((bfd *, const struct internal_ldhdr *, struct external_ldhdr *));
+static void xcoff_swap_ldsym_in
+ PARAMS ((bfd *, const struct external_ldsym *, struct internal_ldsym *));
+static void xcoff_swap_ldsym_out
+ PARAMS ((bfd *, const struct internal_ldsym *, struct external_ldsym *));
+static void xcoff_swap_ldrel_out
+ PARAMS ((bfd *, const struct internal_ldrel *, struct external_ldrel *));
+static struct bfd_hash_entry *xcoff_link_hash_newfunc
+ PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
+static struct internal_reloc *xcoff_read_internal_relocs
+ PARAMS ((bfd *, asection *, boolean, bfd_byte *, boolean,
+ struct internal_reloc *));
+static boolean xcoff_link_add_object_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean xcoff_link_check_archive_element
+ PARAMS ((bfd *, struct bfd_link_info *, boolean *));
+static boolean xcoff_link_check_ar_symbols
+ PARAMS ((bfd *, struct bfd_link_info *, boolean *));
+static bfd_size_type xcoff_find_reloc
+ PARAMS ((struct internal_reloc *, bfd_size_type, bfd_vma));
+static boolean xcoff_link_add_symbols PARAMS ((bfd *, struct bfd_link_info *));
+static boolean xcoff_link_add_dynamic_symbols
+ PARAMS ((bfd *, struct bfd_link_info *));
+static boolean xcoff_mark PARAMS ((struct bfd_link_info *, asection *));
+static void xcoff_sweep PARAMS ((struct bfd_link_info *));
+static boolean xcoff_build_ldsyms
+ PARAMS ((struct xcoff_link_hash_entry *, PTR));
+static boolean xcoff_link_input_bfd
+ PARAMS ((struct xcoff_final_link_info *, bfd *));
+static boolean xcoff_write_global_symbol
+ PARAMS ((struct xcoff_link_hash_entry *, PTR));
+static boolean xcoff_reloc_link_order
+ PARAMS ((bfd *, struct xcoff_final_link_info *, asection *,
+ struct bfd_link_order *));
+static int xcoff_sort_relocs PARAMS ((const PTR, const PTR));
+
+/* Routines to swap information in the XCOFF .loader section. If we
+ ever need to write an XCOFF loader, this stuff will need to be
+ moved to another file shared by the linker (which XCOFF calls the
+ ``binder'') and the loader. */
+
+/* Swap in the ldhdr structure. */
+
+static void
+xcoff_swap_ldhdr_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldhdr *src;
+ struct internal_ldhdr *dst;
+{
+ dst->l_version = bfd_get_32 (abfd, src->l_version);
+ dst->l_nsyms = bfd_get_32 (abfd, src->l_nsyms);
+ dst->l_nreloc = bfd_get_32 (abfd, src->l_nreloc);
+ dst->l_istlen = bfd_get_32 (abfd, src->l_istlen);
+ dst->l_nimpid = bfd_get_32 (abfd, src->l_nimpid);
+ dst->l_impoff = bfd_get_32 (abfd, src->l_impoff);
+ dst->l_stlen = bfd_get_32 (abfd, src->l_stlen);
+ dst->l_stoff = bfd_get_32 (abfd, src->l_stoff);
+}
+
+/* Swap out the ldhdr structure. */
+
+static void
+xcoff_swap_ldhdr_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldhdr *src;
+ struct external_ldhdr *dst;
+{
+ bfd_put_32 (abfd, src->l_version, dst->l_version);
+ bfd_put_32 (abfd, src->l_nsyms, dst->l_nsyms);
+ bfd_put_32 (abfd, src->l_nreloc, dst->l_nreloc);
+ bfd_put_32 (abfd, src->l_istlen, dst->l_istlen);
+ bfd_put_32 (abfd, src->l_nimpid, dst->l_nimpid);
+ bfd_put_32 (abfd, src->l_impoff, dst->l_impoff);
+ bfd_put_32 (abfd, src->l_stlen, dst->l_stlen);
+ bfd_put_32 (abfd, src->l_stoff, dst->l_stoff);
+}
+
+/* Swap in the ldsym structure. */
+
+static void
+xcoff_swap_ldsym_in (abfd, src, dst)
+ bfd *abfd;
+ const struct external_ldsym *src;
+ struct internal_ldsym *dst;
+{
+ if (bfd_get_32 (abfd, src->_l._l_l._l_zeroes) != 0)
+ memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
+ else
+ {
+ dst->_l._l_l._l_zeroes = 0;
+ dst->_l._l_l._l_offset = bfd_get_32 (abfd, src->_l._l_l._l_offset);
+ }
+ dst->l_value = bfd_get_32 (abfd, src->l_value);
+ dst->l_scnum = bfd_get_16 (abfd, src->l_scnum);
+ dst->l_smtype = bfd_get_8 (abfd, src->l_smtype);
+ dst->l_smclas = bfd_get_8 (abfd, src->l_smclas);
+ dst->l_ifile = bfd_get_32 (abfd, src->l_ifile);
+ dst->l_parm = bfd_get_32 (abfd, src->l_parm);
+}
+
+/* Swap out the ldsym structure. */
+
+static void
+xcoff_swap_ldsym_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldsym *src;
+ struct external_ldsym *dst;
+{
+ if (src->_l._l_l._l_zeroes != 0)
+ memcpy (dst->_l._l_name, src->_l._l_name, SYMNMLEN);
+ else
+ {
+ bfd_put_32 (abfd, 0, dst->_l._l_l._l_zeroes);
+ bfd_put_32 (abfd, src->_l._l_l._l_offset, dst->_l._l_l._l_offset);
+ }
+ bfd_put_32 (abfd, src->l_value, dst->l_value);
+ bfd_put_16 (abfd, src->l_scnum, dst->l_scnum);
+ bfd_put_8 (abfd, src->l_smtype, dst->l_smtype);
+ bfd_put_8 (abfd, src->l_smclas, dst->l_smclas);
+ bfd_put_32 (abfd, src->l_ifile, dst->l_ifile);
+ bfd_put_32 (abfd, src->l_parm, dst->l_parm);
+}
+
+/* As it happens, we never need to swap in the ldrel structure. */
+
+/* Swap out the ldrel structure. */
+
+static void
+xcoff_swap_ldrel_out (abfd, src, dst)
+ bfd *abfd;
+ const struct internal_ldrel *src;
+ struct external_ldrel *dst;
+{
+ bfd_put_32 (abfd, src->l_vaddr, dst->l_vaddr);
+ bfd_put_32 (abfd, src->l_symndx, dst->l_symndx);
+ bfd_put_16 (abfd, src->l_rtype, dst->l_rtype);
+ bfd_put_16 (abfd, src->l_rsecnm, dst->l_rsecnm);
+}
+
+/* Routine to create an entry in an XCOFF link hash table. */
+
+static struct bfd_hash_entry *
+xcoff_link_hash_newfunc (entry, table, string)
+ struct bfd_hash_entry *entry;
+ struct bfd_hash_table *table;
+ const char *string;
+{
+ struct xcoff_link_hash_entry *ret = (struct xcoff_link_hash_entry *) entry;
+
+ /* Allocate the structure if it has not already been allocated by a
+ subclass. */
+ if (ret == (struct xcoff_link_hash_entry *) NULL)
+ ret = ((struct xcoff_link_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct xcoff_link_hash_entry)));
+ if (ret == (struct xcoff_link_hash_entry *) NULL)
+ return (struct bfd_hash_entry *) ret;
+
+ /* Call the allocation method of the superclass. */
+ ret = ((struct xcoff_link_hash_entry *)
+ _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
+ table, string));
+ if (ret != NULL)
+ {
+ /* Set local fields. */
+ ret->indx = -1;
+ ret->toc_section = NULL;
+ ret->u.toc_indx = -1;
+ ret->descriptor = NULL;
+ ret->ldsym = NULL;
+ ret->ldindx = -1;
+ ret->flags = 0;
+ ret->smclas = XMC_UA;
+ }
+
+ return (struct bfd_hash_entry *) ret;
+}
+
+/* Create a XCOFF link hash table. */
+
+struct bfd_link_hash_table *
+_bfd_xcoff_bfd_link_hash_table_create (abfd)
+ bfd *abfd;
+{
+ struct xcoff_link_hash_table *ret;
+
+ ret = ((struct xcoff_link_hash_table *)
+ bfd_alloc (abfd, sizeof (struct xcoff_link_hash_table)));
+ if (ret == (struct xcoff_link_hash_table *) NULL)
+ return (struct bfd_link_hash_table *) NULL;
+ if (! _bfd_link_hash_table_init (&ret->root, abfd, xcoff_link_hash_newfunc))
+ {
+ bfd_release (abfd, ret);
+ return (struct bfd_link_hash_table *) NULL;
+ }
+
+ ret->debug_strtab = _bfd_xcoff_stringtab_init ();
+ ret->debug_section = NULL;
+ ret->loader_section = NULL;
+ ret->ldrel_count = 0;
+ memset (&ret->ldhdr, 0, sizeof (struct internal_ldhdr));
+ ret->linkage_section = NULL;
+ ret->toc_section = NULL;
+ ret->descriptor_section = NULL;
+ ret->imports = NULL;
+ ret->file_align = 0;
+ ret->textro = false;
+ ret->gc = false;
+ memset (ret->special_sections, 0, sizeof ret->special_sections);
+
+ /* The linker will always generate a full a.out header. We need to
+ record that fact now, before the sizeof_headers routine could be
+ called. */
+ xcoff_data (abfd)->full_aouthdr = true;
+
+ return &ret->root;
+}
+
+/* Look up an entry in an XCOFF link hash table. */
+
+#define xcoff_link_hash_lookup(table, string, create, copy, follow) \
+ ((struct xcoff_link_hash_entry *) \
+ bfd_link_hash_lookup (&(table)->root, (string), (create), (copy),\
+ (follow)))
+
+/* Traverse an XCOFF link hash table. */
+
+#define xcoff_link_hash_traverse(table, func, info) \
+ (bfd_link_hash_traverse \
+ (&(table)->root, \
+ (boolean (*) PARAMS ((struct bfd_link_hash_entry *, PTR))) (func), \
+ (info)))
+
+/* Get the XCOFF link hash table from the info structure. This is
+ just a cast. */
+
+#define xcoff_hash_table(p) ((struct xcoff_link_hash_table *) ((p)->hash))
+
+/* Read internal relocs for an XCOFF csect. This is a wrapper around
+ _bfd_coff_read_internal_relocs which tries to take advantage of any
+ relocs which may have been cached for the enclosing section. */
+
+static struct internal_reloc *
+xcoff_read_internal_relocs (abfd, sec, cache, external_relocs,
+ require_internal, internal_relocs)
+ bfd *abfd;
+ asection *sec;
+ boolean cache;
+ bfd_byte *external_relocs;
+ boolean require_internal;
+ struct internal_reloc *internal_relocs;
+{
+ if (coff_section_data (abfd, sec) != NULL
+ && coff_section_data (abfd, sec)->relocs == NULL
+ && xcoff_section_data (abfd, sec) != NULL)
+ {
+ asection *enclosing;
+
+ enclosing = xcoff_section_data (abfd, sec)->enclosing;
+
+ if (enclosing != NULL
+ && (coff_section_data (abfd, enclosing) == NULL
+ || coff_section_data (abfd, enclosing)->relocs == NULL)
+ && cache
+ && enclosing->reloc_count > 0)
+ {
+ if (_bfd_coff_read_internal_relocs (abfd, enclosing, true,
+ external_relocs, false,
+ (struct internal_reloc *) NULL)
+ == NULL)
+ return NULL;
+ }
+
+ if (enclosing != NULL
+ && coff_section_data (abfd, enclosing) != NULL
+ && coff_section_data (abfd, enclosing)->relocs != NULL)
+ {
+ size_t off;
+
+ off = ((sec->rel_filepos - enclosing->rel_filepos)
+ / bfd_coff_relsz (abfd));
+ if (! require_internal)
+ return coff_section_data (abfd, enclosing)->relocs + off;
+ memcpy (internal_relocs,
+ coff_section_data (abfd, enclosing)->relocs + off,
+ sec->reloc_count * sizeof (struct internal_reloc));
+ return internal_relocs;
+ }
+ }
+
+ return _bfd_coff_read_internal_relocs (abfd, sec, cache, external_relocs,
+ require_internal, internal_relocs);
+}
+
+/* Given an XCOFF BFD, add symbols to the global hash table as
+ appropriate. */
+
+boolean
+_bfd_xcoff_bfd_link_add_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ switch (bfd_get_format (abfd))
+ {
+ case bfd_object:
+ return xcoff_link_add_object_symbols (abfd, info);
+ case bfd_archive:
+ return (_bfd_generic_link_add_archive_symbols
+ (abfd, info, xcoff_link_check_archive_element));
+ default:
+ bfd_set_error (bfd_error_wrong_format);
+ return false;
+ }
+}
+
+/* Add symbols from an XCOFF object file. */
+
+static boolean
+xcoff_link_add_object_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ if (! _bfd_coff_get_external_symbols (abfd))
+ return false;
+ if (! xcoff_link_add_symbols (abfd, info))
+ return false;
+ if (! info->keep_memory)
+ {
+ if (! _bfd_coff_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 via
+ _bfd_generic_link_add_archive_symbols. */
+
+static boolean
+xcoff_link_check_archive_element (abfd, info, pneeded)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean *pneeded;
+{
+ if (! _bfd_coff_get_external_symbols (abfd))
+ return false;
+
+ if (! xcoff_link_check_ar_symbols (abfd, info, pneeded))
+ return false;
+
+ if (*pneeded)
+ {
+ if (! xcoff_link_add_symbols (abfd, info))
+ return false;
+ }
+
+ if (! info->keep_memory || ! *pneeded)
+ {
+ if (! _bfd_coff_free_symbols (abfd))
+ return false;
+ }
+
+ return true;
+}
+
+/* Look through the symbols to see if this object file should be
+ included in the link. */
+
+static boolean
+xcoff_link_check_ar_symbols (abfd, info, pneeded)
+ bfd *abfd;
+ struct bfd_link_info *info;
+ boolean *pneeded;
+{
+ bfd_size_type symesz;
+ bfd_byte *esym;
+ bfd_byte *esym_end;
+
+ *pneeded = false;
+
+ symesz = bfd_coff_symesz (abfd);
+ esym = (bfd_byte *) obj_coff_external_syms (abfd);
+ esym_end = esym + obj_raw_syment_count (abfd) * symesz;
+ while (esym < esym_end)
+ {
+ struct internal_syment sym;
+
+ bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+
+ if (sym.n_sclass == C_EXT && sym.n_scnum != N_UNDEF)
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ struct bfd_link_hash_entry *h;
+
+ /* This symbol is externally visible, and is defined by this
+ object file. */
+
+ name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
+ if (name == NULL)
+ return false;
+ h = bfd_link_hash_lookup (info->hash, name, false, false, true);
+
+ /* We are only interested in symbols that are currently
+ undefined. If a symbol is currently known to be common,
+ XCOFF linkers do not bring in an object file which
+ defines it. We also don't bring in symbols to satisfy
+ undefined references in shared objects. */
+ if (h != (struct bfd_link_hash_entry *) NULL
+ && h->type == bfd_link_hash_undefined)
+ {
+ if (! (*info->callbacks->add_archive_element) (info, abfd, name))
+ return false;
+ *pneeded = true;
+ return true;
+ }
+ }
+
+ esym += (sym.n_numaux + 1) * symesz;
+ }
+
+ /* We do not need this object file. */
+ return true;
+}
+
+/* Returns the index of reloc in RELOCS with the least address greater
+ than or equal to ADDRESS. The relocs are sorted by address. */
+
+static bfd_size_type
+xcoff_find_reloc (relocs, count, address)
+ struct internal_reloc *relocs;
+ bfd_size_type count;
+ bfd_vma address;
+{
+ bfd_size_type min, max, this;
+
+ if (count < 2)
+ {
+ if (count == 1 && relocs[0].r_vaddr < address)
+ return 1;
+ else
+ return 0;
+ }
+
+ min = 0;
+ max = count;
+
+ /* Do a binary search over (min,max]. */
+ while (min + 1 < max)
+ {
+ bfd_vma raddr;
+
+ this = (max + min) / 2;
+ raddr = relocs[this].r_vaddr;
+ if (raddr > address)
+ max = this;
+ else if (raddr < address)
+ min = this;
+ else
+ {
+ min = this;
+ break;
+ }
+ }
+
+ if (relocs[min].r_vaddr < address)
+ return min + 1;
+
+ while (min > 0
+ && relocs[min - 1].r_vaddr == address)
+ --min;
+
+ return min;
+}
+
+/* Add all the symbols from an object file to the hash table.
+
+ XCOFF is a weird format. A normal XCOFF .o files will have three
+ COFF sections--.text, .data, and .bss--but each COFF section will
+ contain many csects. These csects are described in the symbol
+ table. From the linker's point of view, each csect must be
+ considered a section in its own right. For example, a TOC entry is
+ handled as a small XMC_TC csect. The linker must be able to merge
+ different TOC entries together, which means that it must be able to
+ extract the XMC_TC csects from the .data section of the input .o
+ file.
+
+ From the point of view of our linker, this is, of course, a hideous
+ nightmare. We cope by actually creating sections for each csect,
+ and discarding the original sections. We then have to handle the
+ relocation entries carefully, since the only way to tell which
+ csect they belong to is to examine the address. */
+
+static boolean
+xcoff_link_add_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ unsigned int n_tmask;
+ unsigned int n_btshft;
+ boolean default_copy;
+ bfd_size_type symcount;
+ struct xcoff_link_hash_entry **sym_hash;
+ asection **csect_cache;
+ bfd_size_type linesz;
+ asection *o;
+ asection *last_real;
+ boolean keep_syms;
+ asection *csect;
+ unsigned int csect_index;
+ asection *first_csect;
+ bfd_size_type symesz;
+ bfd_byte *esym;
+ bfd_byte *esym_end;
+ struct reloc_info_struct
+ {
+ struct internal_reloc *relocs;
+ asection **csects;
+ bfd_byte *linenos;
+ } *reloc_info = NULL;
+
+ if ((abfd->flags & DYNAMIC) != 0
+ && ! info->static_link)
+ {
+ if (! xcoff_link_add_dynamic_symbols (abfd, info))
+ return false;
+ }
+
+ /* We need to build a .loader section, so we do it here. This won't
+ work if we're producing an XCOFF output file with no XCOFF input
+ files. FIXME. */
+ if (xcoff_hash_table (info)->loader_section == NULL)
+ {
+ asection *lsec;
+
+ lsec = bfd_make_section_anyway (abfd, ".loader");
+ if (lsec == NULL)
+ goto error_return;
+ xcoff_hash_table (info)->loader_section = lsec;
+ lsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ }
+ /* Likewise for the linkage section. */
+ if (xcoff_hash_table (info)->linkage_section == NULL)
+ {
+ asection *lsec;
+
+ lsec = bfd_make_section_anyway (abfd, ".gl");
+ if (lsec == NULL)
+ goto error_return;
+ xcoff_hash_table (info)->linkage_section = lsec;
+ lsec->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ lsec->alignment_power = 2;
+ }
+ /* Likewise for the TOC section. */
+ if (xcoff_hash_table (info)->toc_section == NULL)
+ {
+ asection *tsec;
+
+ tsec = bfd_make_section_anyway (abfd, ".tc");
+ if (tsec == NULL)
+ goto error_return;
+ xcoff_hash_table (info)->toc_section = tsec;
+ tsec->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ tsec->alignment_power = 2;
+ }
+ /* Likewise for the descriptor section. */
+ if (xcoff_hash_table (info)->descriptor_section == NULL)
+ {
+ asection *dsec;
+
+ dsec = bfd_make_section_anyway (abfd, ".ds");
+ if (dsec == NULL)
+ goto error_return;
+ xcoff_hash_table (info)->descriptor_section = dsec;
+ dsec->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ dsec->alignment_power = 2;
+ }
+ /* Likewise for the .debug section. */
+ if (xcoff_hash_table (info)->debug_section == NULL)
+ {
+ asection *dsec;
+
+ dsec = bfd_make_section_anyway (abfd, ".debug");
+ if (dsec == NULL)
+ goto error_return;
+ xcoff_hash_table (info)->debug_section = dsec;
+ dsec->flags |= SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ }
+
+ if ((abfd->flags & DYNAMIC) != 0
+ && ! info->static_link)
+ return true;
+
+ n_tmask = coff_data (abfd)->local_n_tmask;
+ n_btshft = coff_data (abfd)->local_n_btshft;
+
+ /* Define macros so that ISFCN, et. al., macros work correctly. */
+#define N_TMASK n_tmask
+#define N_BTSHFT n_btshft
+
+ if (info->keep_memory)
+ default_copy = false;
+ else
+ default_copy = true;
+
+ symcount = obj_raw_syment_count (abfd);
+
+ /* We keep a list of the linker hash table entries that correspond
+ to each external symbol. */
+ sym_hash = ((struct xcoff_link_hash_entry **)
+ bfd_alloc (abfd,
+ (symcount
+ * sizeof (struct xcoff_link_hash_entry *))));
+ if (sym_hash == NULL && symcount != 0)
+ goto error_return;
+ coff_data (abfd)->sym_hashes = (struct coff_link_hash_entry **) sym_hash;
+ memset (sym_hash, 0,
+ (size_t) symcount * sizeof (struct xcoff_link_hash_entry *));
+
+ /* Because of the weird stuff we are doing with XCOFF csects, we can
+ not easily determine which section a symbol is in, so we store
+ the information in the tdata for the input file. */
+ csect_cache = ((asection **)
+ bfd_alloc (abfd, symcount * sizeof (asection *)));
+ if (csect_cache == NULL && symcount != 0)
+ goto error_return;
+ xcoff_data (abfd)->csects = csect_cache;
+ memset (csect_cache, 0, (size_t) symcount * sizeof (asection *));
+
+ /* While splitting sections into csects, we need to assign the
+ relocs correctly. The relocs and the csects must both be in
+ order by VMA within a given section, so we handle this by
+ scanning along the relocs as we process the csects. We index
+ into reloc_info using the section target_index. */
+ reloc_info = ((struct reloc_info_struct *)
+ bfd_malloc ((abfd->section_count + 1)
+ * sizeof (struct reloc_info_struct)));
+ if (reloc_info == NULL)
+ goto error_return;
+ memset ((PTR) reloc_info, 0,
+ (abfd->section_count + 1) * sizeof (struct reloc_info_struct));
+
+ /* Read in the relocs and line numbers for each section. */
+ linesz = bfd_coff_linesz (abfd);
+ last_real = NULL;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ last_real = o;
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ reloc_info[o->target_index].relocs =
+ xcoff_read_internal_relocs (abfd, o, true, (bfd_byte *) NULL,
+ false, (struct internal_reloc *) NULL);
+ reloc_info[o->target_index].csects =
+ (asection **) bfd_malloc (o->reloc_count * sizeof (asection *));
+ if (reloc_info[o->target_index].csects == NULL)
+ goto error_return;
+ memset (reloc_info[o->target_index].csects, 0,
+ o->reloc_count * sizeof (asection *));
+ }
+
+ if ((info->strip == strip_none || info->strip == strip_some)
+ && o->lineno_count > 0)
+ {
+ bfd_byte *linenos;
+
+ linenos = (bfd_byte *) bfd_malloc (o->lineno_count * linesz);
+ if (linenos == NULL)
+ goto error_return;
+ reloc_info[o->target_index].linenos = linenos;
+ if (bfd_seek (abfd, o->line_filepos, SEEK_SET) != 0
+ || (bfd_read (linenos, linesz, o->lineno_count, abfd)
+ != linesz * o->lineno_count))
+ goto error_return;
+ }
+ }
+
+ /* Don't let the linker relocation routines discard the symbols. */
+ keep_syms = obj_coff_keep_syms (abfd);
+ obj_coff_keep_syms (abfd) = true;
+
+ csect = NULL;
+ csect_index = 0;
+ first_csect = NULL;
+
+ symesz = bfd_coff_symesz (abfd);
+ BFD_ASSERT (symesz == bfd_coff_auxesz (abfd));
+ esym = (bfd_byte *) obj_coff_external_syms (abfd);
+ esym_end = esym + symcount * symesz;
+ while (esym < esym_end)
+ {
+ struct internal_syment sym;
+ union internal_auxent aux;
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ int smtyp;
+ flagword flags;
+ asection *section;
+ bfd_vma value;
+ struct xcoff_link_hash_entry *set_toc;
+
+ bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &sym);
+
+ /* In this pass we are only interested in symbols with csect
+ information. */
+ if (sym.n_sclass != C_EXT && sym.n_sclass != C_HIDEXT)
+ {
+ if (sym.n_sclass == C_FILE && csect != NULL)
+ {
+ xcoff_section_data (abfd, csect)->last_symndx =
+ ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz);
+ csect = NULL;
+ }
+
+ if (csect != NULL)
+ *csect_cache = csect;
+ else if (first_csect == NULL || sym.n_sclass == C_FILE)
+ *csect_cache = coff_section_from_bfd_index (abfd, sym.n_scnum);
+ else
+ *csect_cache = NULL;
+ esym += (sym.n_numaux + 1) * symesz;
+ sym_hash += sym.n_numaux + 1;
+ csect_cache += sym.n_numaux + 1;
+ continue;
+ }
+
+ name = _bfd_coff_internal_syment_name (abfd, &sym, buf);
+ if (name == NULL)
+ goto error_return;
+
+ /* If this symbol has line number information attached to it,
+ and we're not stripping it, count the number of entries and
+ add them to the count for this csect. In the final link pass
+ we are going to attach line number information by symbol,
+ rather than by section, in order to more easily handle
+ garbage collection. */
+ if ((info->strip == strip_none || info->strip == strip_some)
+ && sym.n_numaux > 1
+ && csect != NULL
+ && ISFCN (sym.n_type))
+ {
+ union internal_auxent auxlin;
+
+ bfd_coff_swap_aux_in (abfd, (PTR) (esym + symesz),
+ sym.n_type, sym.n_sclass,
+ 0, sym.n_numaux, (PTR) &auxlin);
+ if (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
+ {
+ asection *enclosing;
+ bfd_size_type linoff;
+
+ enclosing = xcoff_section_data (abfd, csect)->enclosing;
+ if (enclosing == NULL)
+ {
+ (*_bfd_error_handler)
+ ("%s: `%s' has line numbers but no enclosing section",
+ bfd_get_filename (abfd), name);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ linoff = (auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr
+ - enclosing->line_filepos);
+ if (linoff < enclosing->lineno_count * linesz)
+ {
+ struct internal_lineno lin;
+ bfd_byte *linpstart;
+
+ linpstart = (reloc_info[enclosing->target_index].linenos
+ + linoff);
+ bfd_coff_swap_lineno_in (abfd, (PTR) linpstart, (PTR) &lin);
+ if (lin.l_lnno == 0
+ && ((bfd_size_type) lin.l_addr.l_symndx
+ == ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz)))
+ {
+ bfd_byte *linpend, *linp;
+
+ linpend = (reloc_info[enclosing->target_index].linenos
+ + enclosing->lineno_count * linesz);
+ for (linp = linpstart + linesz;
+ linp < linpend;
+ linp += linesz)
+ {
+ bfd_coff_swap_lineno_in (abfd, (PTR) linp,
+ (PTR) &lin);
+ if (lin.l_lnno == 0)
+ break;
+ }
+ csect->lineno_count += (linp - linpstart) / linesz;
+ /* The setting of line_filepos will only be
+ useful if all the line number entries for a
+ csect are contiguous; this only matters for
+ error reporting. */
+ if (csect->line_filepos == 0)
+ csect->line_filepos =
+ auxlin.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ }
+ }
+ }
+ }
+
+ /* Pick up the csect auxiliary information. */
+
+ if (sym.n_numaux == 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: class %d symbol `%s' has no aux entries",
+ bfd_get_filename (abfd), sym.n_sclass, name);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ bfd_coff_swap_aux_in (abfd,
+ (PTR) (esym + symesz * sym.n_numaux),
+ sym.n_type, sym.n_sclass,
+ sym.n_numaux - 1, sym.n_numaux,
+ (PTR) &aux);
+
+ smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
+
+ flags = BSF_GLOBAL;
+ section = NULL;
+ value = 0;
+ set_toc = NULL;
+
+ switch (smtyp)
+ {
+ default:
+ (*_bfd_error_handler)
+ ("%s: symbol `%s' has unrecognized csect type %d",
+ bfd_get_filename (abfd), name, smtyp);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+
+ case XTY_ER:
+ /* This is an external reference. */
+ if (sym.n_sclass == C_HIDEXT
+ || sym.n_scnum != N_UNDEF
+ || aux.x_csect.x_scnlen.l != 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: bad XTY_ER symbol `%s': class %d scnum %d scnlen %d",
+ bfd_get_filename (abfd), name, sym.n_sclass, sym.n_scnum,
+ aux.x_csect.x_scnlen.l);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ /* An XMC_XO external reference is actually a reference to
+ an absolute location. */
+ if (aux.x_csect.x_smclas != XMC_XO)
+ section = bfd_und_section_ptr;
+ else
+ {
+ section = bfd_abs_section_ptr;
+ value = sym.n_value;
+ }
+ break;
+
+ case XTY_SD:
+ /* This is a csect definition. */
+
+ if (csect != NULL)
+ {
+ xcoff_section_data (abfd, csect)->last_symndx =
+ ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz);
+ }
+
+ csect = NULL;
+ csect_index = -1;
+
+ /* When we see a TOC anchor, we record the TOC value. */
+ if (aux.x_csect.x_smclas == XMC_TC0)
+ {
+ if (sym.n_sclass != C_HIDEXT
+ || aux.x_csect.x_scnlen.l != 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: XMC_TC0 symbol `%s' is class %d scnlen %d",
+ bfd_get_filename (abfd), name, sym.n_sclass,
+ aux.x_csect.x_scnlen.l);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ xcoff_data (abfd)->toc = sym.n_value;
+ }
+
+ /* We must merge TOC entries for the same symbol. We can
+ merge two TOC entries if they are both C_HIDEXT, they
+ both have the same name, they are both 4 bytes long, and
+ they both have a relocation table entry for an external
+ symbol with the same name. Unfortunately, this means
+ that we must look through the relocations. Ick. */
+ if (aux.x_csect.x_smclas == XMC_TC
+ && sym.n_sclass == C_HIDEXT
+ && aux.x_csect.x_scnlen.l == 4
+ && info->hash->creator == abfd->xvec)
+ {
+ asection *enclosing;
+ struct internal_reloc *relocs;
+ bfd_size_type relindx;
+ struct internal_reloc *rel;
+
+ enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
+ if (enclosing == NULL)
+ goto error_return;
+
+ relocs = reloc_info[enclosing->target_index].relocs;
+ relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
+ sym.n_value);
+ rel = relocs + relindx;
+ if (relindx < enclosing->reloc_count
+ && rel->r_vaddr == (bfd_vma) sym.n_value
+ && rel->r_size == 31
+ && rel->r_type == R_POS)
+ {
+ bfd_byte *erelsym;
+ struct internal_syment relsym;
+
+ erelsym = ((bfd_byte *) obj_coff_external_syms (abfd)
+ + rel->r_symndx * symesz);
+ bfd_coff_swap_sym_in (abfd, (PTR) erelsym, (PTR) &relsym);
+ if (relsym.n_sclass == C_EXT)
+ {
+ const char *relname;
+ char relbuf[SYMNMLEN + 1];
+ boolean copy;
+ struct xcoff_link_hash_entry *h;
+
+ /* At this point we know that the TOC entry is
+ for an externally visible symbol. */
+ relname = _bfd_coff_internal_syment_name (abfd, &relsym,
+ relbuf);
+ if (relname == NULL)
+ goto error_return;
+
+ /* We only merge TOC entries if the TC name is
+ the same as the symbol name. This handles
+ the normal case, but not common cases like
+ SYM.P4 which gcc generates to store SYM + 4
+ in the TOC. FIXME. */
+ if (strcmp (name, relname) == 0)
+ {
+ copy = (! info->keep_memory
+ || relsym._n._n_n._n_zeroes != 0
+ || relsym._n._n_n._n_offset == 0);
+ h = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ relname, true, copy,
+ false);
+ if (h == NULL)
+ goto error_return;
+
+ /* At this point h->root.type could be
+ bfd_link_hash_new. That should be OK,
+ since we know for sure that we will come
+ across this symbol as we step through the
+ file. */
+
+ /* We store h in *sym_hash for the
+ convenience of the relocate_section
+ function. */
+ *sym_hash = h;
+
+ if (h->toc_section != NULL)
+ {
+ asection **rel_csects;
+
+ /* We already have a TOC entry for this
+ symbol, so we can just ignore this
+ one. */
+ rel_csects =
+ reloc_info[enclosing->target_index].csects;
+ rel_csects[relindx] = bfd_und_section_ptr;
+ break;
+ }
+
+ /* We are about to create a TOC entry for
+ this symbol. */
+ set_toc = h;
+ }
+ }
+ }
+ }
+
+ /* We need to create a new section. We get the name from
+ the csect storage mapping class, so that the linker can
+ accumulate similar csects together. */
+ {
+ static const char *csect_name_by_class[] =
+ {
+ ".pr", ".ro", ".db", ".tc", ".ua", ".rw", ".gl", ".xo",
+ ".sv", ".bs", ".ds", ".uc", ".ti", ".tb", NULL, ".tc0",
+ ".td"
+ };
+ const char *csect_name;
+ asection *enclosing;
+
+ if ((aux.x_csect.x_smclas >=
+ sizeof csect_name_by_class / sizeof csect_name_by_class[0])
+ || csect_name_by_class[aux.x_csect.x_smclas] == NULL)
+ {
+ (*_bfd_error_handler)
+ ("%s: symbol `%s' has unrecognized smclas %d",
+ bfd_get_filename (abfd), name, aux.x_csect.x_smclas);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ csect_name = csect_name_by_class[aux.x_csect.x_smclas];
+ csect = bfd_make_section_anyway (abfd, csect_name);
+ if (csect == NULL)
+ goto error_return;
+ enclosing = coff_section_from_bfd_index (abfd, sym.n_scnum);
+ if (enclosing == NULL)
+ goto error_return;
+ if (! bfd_is_abs_section (enclosing)
+ && ((bfd_vma) sym.n_value < enclosing->vma
+ || ((bfd_vma) sym.n_value + aux.x_csect.x_scnlen.l
+ > enclosing->vma + enclosing->_raw_size)))
+ {
+ (*_bfd_error_handler)
+ ("%s: csect `%s' not in enclosing section",
+ bfd_get_filename (abfd), name);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+ csect->vma = sym.n_value;
+ csect->filepos = (enclosing->filepos
+ + sym.n_value
+ - enclosing->vma);
+ csect->_raw_size = aux.x_csect.x_scnlen.l;
+ csect->flags |= SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
+ csect->alignment_power = SMTYP_ALIGN (aux.x_csect.x_smtyp);
+
+ /* Record the enclosing section in the tdata for this new
+ section. */
+ csect->used_by_bfd =
+ ((struct coff_section_tdata *)
+ bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+ if (csect->used_by_bfd == NULL)
+ goto error_return;
+ coff_section_data (abfd, csect)->tdata =
+ bfd_zalloc (abfd, sizeof (struct xcoff_section_tdata));
+ if (coff_section_data (abfd, csect)->tdata == NULL)
+ goto error_return;
+ xcoff_section_data (abfd, csect)->enclosing = enclosing;
+ xcoff_section_data (abfd, csect)->lineno_count =
+ enclosing->lineno_count;
+
+ if (enclosing->owner == abfd)
+ {
+ struct internal_reloc *relocs;
+ bfd_size_type relindx;
+ struct internal_reloc *rel;
+ asection **rel_csect;
+
+ relocs = reloc_info[enclosing->target_index].relocs;
+ relindx = xcoff_find_reloc (relocs, enclosing->reloc_count,
+ csect->vma);
+ rel = relocs + relindx;
+ rel_csect = (reloc_info[enclosing->target_index].csects
+ + relindx);
+ csect->rel_filepos = (enclosing->rel_filepos
+ + relindx * bfd_coff_relsz (abfd));
+ while (relindx < enclosing->reloc_count
+ && *rel_csect == NULL
+ && rel->r_vaddr < csect->vma + csect->_raw_size)
+ {
+ *rel_csect = csect;
+ csect->flags |= SEC_RELOC;
+ ++csect->reloc_count;
+ ++relindx;
+ ++rel;
+ ++rel_csect;
+ }
+ }
+
+ /* There are a number of other fields and section flags
+ which we do not bother to set. */
+
+ csect_index = ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz);
+
+ xcoff_section_data (abfd, csect)->first_symndx = csect_index;
+
+ if (first_csect == NULL)
+ first_csect = csect;
+
+ /* If this symbol is C_EXT, we treat it as starting at the
+ beginning of the newly created section. */
+ if (sym.n_sclass == C_EXT)
+ {
+ section = csect;
+ value = 0;
+ }
+
+ /* If this is a TOC section for a symbol, record it. */
+ if (set_toc != NULL)
+ set_toc->toc_section = csect;
+ }
+ break;
+
+ case XTY_LD:
+ /* This is a label definition. The x_scnlen field is the
+ symbol index of the csect. I believe that this must
+ always follow the appropriate XTY_SD symbol, so I will
+ insist on it. */
+ {
+ boolean bad;
+
+ bad = false;
+ if (aux.x_csect.x_scnlen.l < 0
+ || (aux.x_csect.x_scnlen.l
+ >= esym - (bfd_byte *) obj_coff_external_syms (abfd)))
+ bad = true;
+ if (! bad)
+ {
+ section = xcoff_data (abfd)->csects[aux.x_csect.x_scnlen.l];
+ if (section == NULL
+ || (section->flags & SEC_HAS_CONTENTS) == 0)
+ bad = true;
+ }
+ if (bad)
+ {
+ (*_bfd_error_handler)
+ ("%s: misplaced XTY_LD `%s'",
+ bfd_get_filename (abfd), name);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ value = sym.n_value - csect->vma;
+ }
+ break;
+
+ case XTY_CM:
+ /* This is an unitialized csect. We could base the name on
+ the storage mapping class, but we don't bother. If this
+ csect is externally visible, it is a common symbol. */
+
+ if (csect != NULL)
+ {
+ xcoff_section_data (abfd, csect)->last_symndx =
+ ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz);
+ }
+
+ csect = bfd_make_section_anyway (abfd, ".bss");
+ if (csect == NULL)
+ goto error_return;
+ csect->vma = sym.n_value;
+ csect->_raw_size = aux.x_csect.x_scnlen.l;
+ csect->flags |= SEC_ALLOC;
+ csect->alignment_power = SMTYP_ALIGN (aux.x_csect.x_smtyp);
+ /* There are a number of other fields and section flags
+ which we do not bother to set. */
+
+ csect_index = ((esym
+ - (bfd_byte *) obj_coff_external_syms (abfd))
+ / symesz);
+
+ csect->used_by_bfd =
+ ((struct coff_section_tdata *)
+ bfd_zalloc (abfd, sizeof (struct coff_section_tdata)));
+ if (csect->used_by_bfd == NULL)
+ goto error_return;
+ coff_section_data (abfd, csect)->tdata =
+ bfd_zalloc (abfd, sizeof (struct xcoff_section_tdata));
+ if (coff_section_data (abfd, csect)->tdata == NULL)
+ goto error_return;
+ xcoff_section_data (abfd, csect)->first_symndx = csect_index;
+
+ if (first_csect == NULL)
+ first_csect = csect;
+
+ if (sym.n_sclass == C_EXT)
+ {
+ csect->flags |= SEC_IS_COMMON;
+ csect->_raw_size = 0;
+ section = csect;
+ value = aux.x_csect.x_scnlen.l;
+ }
+
+ break;
+ }
+
+ /* Check for magic symbol names. */
+ if ((smtyp == XTY_SD || smtyp == XTY_CM)
+ && aux.x_csect.x_smclas != XMC_TC)
+ {
+ int i;
+
+ i = -1;
+ if (name[0] == '_')
+ {
+ if (strcmp (name, "_text") == 0)
+ i = 0;
+ else if (strcmp (name, "_etext") == 0)
+ i = 1;
+ else if (strcmp (name, "_data") == 0)
+ i = 2;
+ else if (strcmp (name, "_edata") == 0)
+ i = 3;
+ else if (strcmp (name, "_end") == 0)
+ i = 4;
+ }
+ else if (name[0] == 'e' && strcmp (name, "end") == 0)
+ i = 5;
+
+ if (i != -1)
+ xcoff_hash_table (info)->special_sections[i] = csect;
+ }
+
+ /* Now we have enough information to add the symbol to the
+ linker hash table. */
+
+ if (sym.n_sclass == C_EXT)
+ {
+ boolean copy;
+
+ BFD_ASSERT (section != NULL);
+
+ /* We must copy the name into memory if we got it from the
+ syment itself, rather than the string table. */
+ copy = default_copy;
+ if (sym._n._n_n._n_zeroes != 0
+ || sym._n._n_n._n_offset == 0)
+ copy = true;
+
+ if (info->hash->creator == abfd->xvec)
+ {
+ /* If we are statically linking a shared object, it is
+ OK for symbol redefinitions to occur. I can't figure
+ out just what the XCOFF linker is doing, but
+ something like this is required for -bnso to work. */
+ if (! bfd_is_und_section (section))
+ *sym_hash = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ name, true, copy, false);
+ else
+ *sym_hash = ((struct xcoff_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (abfd, info, name,
+ true, copy, false));
+ if (*sym_hash == NULL)
+ goto error_return;
+ if (((*sym_hash)->root.type == bfd_link_hash_defined
+ || (*sym_hash)->root.type == bfd_link_hash_defweak)
+ && ! bfd_is_und_section (section)
+ && ! bfd_is_com_section (section))
+ {
+ if ((abfd->flags & DYNAMIC) != 0)
+ {
+ section = bfd_und_section_ptr;
+ value = 0;
+ }
+ else if (((*sym_hash)->root.u.def.section->owner->flags
+ & DYNAMIC) != 0)
+ {
+ (*sym_hash)->root.type = bfd_link_hash_undefined;
+ (*sym_hash)->root.u.undef.abfd =
+ (*sym_hash)->root.u.def.section->owner;
+ }
+ }
+ }
+
+ /* _bfd_generic_link_add_one_symbol may call the linker to
+ generate an error message, and the linker may try to read
+ the symbol table to give a good error. Right now, the
+ line numbers are in an inconsistent state, since they are
+ counted both in the real sections and in the new csects.
+ We need to leave the count in the real sections so that
+ the linker can report the line number of the error
+ correctly, so temporarily clobber the link to the csects
+ so that the linker will not try to read the line numbers
+ a second time from the csects. */
+ BFD_ASSERT (last_real->next == first_csect);
+ last_real->next = NULL;
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, name, flags, section, value,
+ (const char *) NULL, copy, true,
+ (struct bfd_link_hash_entry **) sym_hash)))
+ goto error_return;
+ last_real->next = first_csect;
+
+ if (smtyp == XTY_CM)
+ {
+ if ((*sym_hash)->root.type != bfd_link_hash_common
+ || (*sym_hash)->root.u.c.p->section != csect)
+ {
+ /* We don't need the common csect we just created. */
+ csect->_raw_size = 0;
+ }
+ else
+ {
+ (*sym_hash)->root.u.c.p->alignment_power
+ = csect->alignment_power;
+ }
+ }
+
+ if (info->hash->creator == abfd->xvec)
+ {
+ int flag;
+
+ if (smtyp == XTY_ER || smtyp == XTY_CM)
+ flag = XCOFF_REF_REGULAR;
+ else
+ flag = XCOFF_DEF_REGULAR;
+ (*sym_hash)->flags |= flag;
+
+ if ((*sym_hash)->smclas == XMC_UA
+ || flag == XCOFF_DEF_REGULAR)
+ (*sym_hash)->smclas = aux.x_csect.x_smclas;
+ }
+ }
+
+ *csect_cache = csect;
+
+ esym += (sym.n_numaux + 1) * symesz;
+ sym_hash += sym.n_numaux + 1;
+ csect_cache += sym.n_numaux + 1;
+ }
+
+ BFD_ASSERT (last_real == NULL || last_real->next == first_csect);
+
+ /* Make sure that we have seen all the relocs. */
+ for (o = abfd->sections; o != first_csect; o = o->next)
+ {
+ /* Reset the section size and the line numebr count, since the
+ data is now attached to the csects. Don't reset the size of
+ the .debug section, since we need to read it below in
+ bfd_xcoff_size_dynamic_sections. */
+ if (strcmp (bfd_get_section_name (abfd, o), ".debug") != 0)
+ o->_raw_size = 0;
+ o->lineno_count = 0;
+
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ bfd_size_type i;
+ struct internal_reloc *rel;
+ asection **rel_csect;
+
+ rel = reloc_info[o->target_index].relocs;
+ rel_csect = reloc_info[o->target_index].csects;
+ for (i = 0; i < o->reloc_count; i++, rel++, rel_csect++)
+ {
+ if (*rel_csect == NULL)
+ {
+ (*_bfd_error_handler)
+ ("%s: reloc %s:%d not in csect",
+ bfd_get_filename (abfd), o->name, i);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
+ /* We identify all symbols which are called, so that we
+ can create glue code for calls to functions imported
+ from dynamic objects. */
+ if (info->hash->creator == abfd->xvec
+ && *rel_csect != bfd_und_section_ptr
+ && (rel->r_type == R_BR
+ || rel->r_type == R_RBR)
+ && obj_xcoff_sym_hashes (abfd)[rel->r_symndx] != NULL)
+ {
+ struct xcoff_link_hash_entry *h;
+
+ h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx];
+ h->flags |= XCOFF_CALLED;
+ /* If the symbol name starts with a period, it is
+ the code of a function. If the symbol is
+ currently undefined, then add an undefined symbol
+ for the function descriptor. This should do no
+ harm, because any regular object that defines the
+ function should also define the function
+ descriptor. It helps, because it means that we
+ will identify the function descriptor with a
+ dynamic object if a dynamic object defines it. */
+ if (h->root.root.string[0] == '.'
+ && h->descriptor == NULL)
+ {
+ struct xcoff_link_hash_entry *hds;
+
+ hds = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ h->root.root.string + 1,
+ true, false, true);
+ if (hds == NULL)
+ goto error_return;
+ if (hds->root.type == bfd_link_hash_new)
+ {
+ if (! (_bfd_generic_link_add_one_symbol
+ (info, abfd, hds->root.root.string,
+ (flagword) 0, bfd_und_section_ptr,
+ (bfd_vma) 0, (const char *) NULL, false,
+ true,
+ (struct bfd_link_hash_entry **) &hds)))
+ goto error_return;
+ }
+ hds->flags |= XCOFF_DESCRIPTOR;
+ BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0
+ && (h->flags & XCOFF_DESCRIPTOR) == 0);
+ hds->descriptor = h;
+ h->descriptor = hds;
+ }
+ }
+ }
+
+ free (reloc_info[o->target_index].csects);
+ reloc_info[o->target_index].csects = NULL;
+
+ /* Reset SEC_RELOC and the reloc_count, since the reloc
+ information is now attached to the csects. */
+ o->flags &=~ SEC_RELOC;
+ o->reloc_count = 0;
+
+ /* If we are not keeping memory, free the reloc information. */
+ if (! info->keep_memory
+ && coff_section_data (abfd, o) != NULL
+ && coff_section_data (abfd, o)->relocs != NULL
+ && ! coff_section_data (abfd, o)->keep_relocs)
+ {
+ free (coff_section_data (abfd, o)->relocs);
+ coff_section_data (abfd, o)->relocs = NULL;
+ }
+ }
+
+ /* Free up the line numbers. FIXME: We could cache these
+ somewhere for the final link, to avoid reading them again. */
+ if (reloc_info[o->target_index].linenos != NULL)
+ {
+ free (reloc_info[o->target_index].linenos);
+ reloc_info[o->target_index].linenos = NULL;
+ }
+ }
+
+ free (reloc_info);
+
+ obj_coff_keep_syms (abfd) = keep_syms;
+
+ return true;
+
+ error_return:
+ if (reloc_info != NULL)
+ {
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (reloc_info[o->target_index].csects != NULL)
+ free (reloc_info[o->target_index].csects);
+ if (reloc_info[o->target_index].linenos != NULL)
+ free (reloc_info[o->target_index].linenos);
+ }
+ free (reloc_info);
+ }
+ obj_coff_keep_syms (abfd) = keep_syms;
+ return false;
+}
+
+#undef N_TMASK
+#undef N_BTSHFT
+
+/* This function is used to add symbols from a dynamic object to the
+ global symbol table. */
+
+static boolean
+xcoff_link_add_dynamic_symbols (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ asection *lsec;
+ bfd_byte *buf = NULL;
+ struct internal_ldhdr ldhdr;
+ const char *strings;
+ struct external_ldsym *elsym, *elsymend;
+ struct xcoff_import_file *n;
+ const char *bname;
+ const char *mname;
+ const char *s;
+ unsigned int c;
+ struct xcoff_import_file **pp;
+
+ /* We can only handle a dynamic object if we are generating an XCOFF
+ output file. */
+ if (info->hash->creator != abfd->xvec)
+ {
+ (*_bfd_error_handler)
+ ("%s: XCOFF shared object when not producing XCOFF output",
+ bfd_get_filename (abfd));
+ bfd_set_error (bfd_error_invalid_operation);
+ goto error_return;
+ }
+
+ /* The symbols we use from a dynamic object are not the symbols in
+ the normal symbol table, but, rather, the symbols in the export
+ table. If there is a global symbol in a dynamic object which is
+ not in the export table, the loader will not be able to find it,
+ so we don't want to find it either. Also, on AIX 4.1.3, shr.o in
+ libc.a has symbols in the export table which are not in the
+ symbol table. */
+
+ /* Read in the .loader section. FIXME: We should really use the
+ o_snloader field in the a.out header, rather than grabbing the
+ section by name. */
+ lsec = bfd_get_section_by_name (abfd, ".loader");
+ if (lsec == NULL)
+ {
+ (*_bfd_error_handler)
+ ("%s: dynamic object with no .loader section",
+ bfd_get_filename (abfd));
+ bfd_set_error (bfd_error_no_symbols);
+ goto error_return;
+ }
+
+ buf = (bfd_byte *) bfd_malloc (lsec->_raw_size);
+ if (buf == NULL && lsec->_raw_size > 0)
+ goto error_return;
+
+ if (! bfd_get_section_contents (abfd, lsec, (PTR) buf, (file_ptr) 0,
+ lsec->_raw_size))
+ goto error_return;
+
+ /* Remove the sections from this object, so that they do not get
+ included in the link. */
+ abfd->sections = NULL;
+
+ xcoff_swap_ldhdr_in (abfd, (struct external_ldhdr *) buf, &ldhdr);
+
+ strings = (char *) buf + ldhdr.l_stoff;
+
+ elsym = (struct external_ldsym *) (buf + LDHDRSZ);
+ elsymend = elsym + ldhdr.l_nsyms;
+ BFD_ASSERT (sizeof (struct external_ldsym) == LDSYMSZ);
+ for (; elsym < elsymend; elsym++)
+ {
+ struct internal_ldsym ldsym;
+ char nambuf[SYMNMLEN + 1];
+ const char *name;
+ struct xcoff_link_hash_entry *h;
+
+ xcoff_swap_ldsym_in (abfd, elsym, &ldsym);
+
+ /* We are only interested in exported symbols. */
+ if ((ldsym.l_smtype & L_EXPORT) == 0)
+ continue;
+
+ if (ldsym._l._l_l._l_zeroes == 0)
+ name = strings + ldsym._l._l_l._l_offset;
+ else
+ {
+ memcpy (nambuf, ldsym._l._l_name, SYMNMLEN);
+ nambuf[SYMNMLEN] = '\0';
+ name = nambuf;
+ }
+
+ /* Normally we could not call xcoff_link_hash_lookup in an add
+ symbols routine, since we might not be using an XCOFF hash
+ table. However, we verified above that we are using an XCOFF
+ hash table. */
+
+ h = xcoff_link_hash_lookup (xcoff_hash_table (info), name, true,
+ true, true);
+ if (h == NULL)
+ goto error_return;
+
+ h->flags |= XCOFF_DEF_DYNAMIC;
+
+ /* If the symbol is undefined, and the BFD it was found in is
+ not a dynamic object, change the BFD to this dynamic object,
+ so that we can get the correct import file ID. */
+ if ((h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ && (h->root.u.undef.abfd == NULL
+ || (h->root.u.undef.abfd->flags & DYNAMIC) == 0))
+ h->root.u.undef.abfd = abfd;
+
+ if (h->root.type == bfd_link_hash_new)
+ {
+ h->root.type = bfd_link_hash_undefined;
+ h->root.u.undef.abfd = abfd;
+ /* We do not want to add this to the undefined symbol list. */
+ }
+
+ if (h->smclas == XMC_UA
+ || h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ h->smclas = ldsym.l_smclas;
+
+ /* Unless this is an XMC_XO symbol, we don't bother to actually
+ define it, since we don't have a section to put it in anyhow.
+ Instead, the relocation routines handle the DEF_DYNAMIC flag
+ correctly. */
+
+ if (h->smclas == XMC_XO
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak))
+ {
+ /* This symbol has an absolute value. */
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.section = bfd_abs_section_ptr;
+ h->root.u.def.value = ldsym.l_value;
+ }
+ }
+
+ if (buf != NULL)
+ {
+ free (buf);
+ buf = NULL;
+ }
+
+ /* Record this file in the import files. */
+
+ n = ((struct xcoff_import_file *)
+ bfd_alloc (abfd, sizeof (struct xcoff_import_file)));
+ if (n == NULL)
+ goto error_return;
+ n->next = NULL;
+
+ /* For some reason, the path entry in the import file list for a
+ shared object appears to always be empty. The file name is the
+ base name. */
+ n->path = "";
+ if (abfd->my_archive == NULL)
+ {
+ bname = bfd_get_filename (abfd);
+ mname = "";
+ }
+ else
+ {
+ bname = bfd_get_filename (abfd->my_archive);
+ mname = bfd_get_filename (abfd);
+ }
+ s = strrchr (bname, '/');
+ if (s != NULL)
+ bname = s + 1;
+ n->file = bname;
+ n->member = mname;
+
+ /* We start c at 1 because the first import file number is reserved
+ for LIBPATH. */
+ for (pp = &xcoff_hash_table (info)->imports, c = 1;
+ *pp != NULL;
+ pp = &(*pp)->next, ++c)
+ ;
+ *pp = n;
+
+ xcoff_data (abfd)->import_file_id = c;
+
+ return true;
+
+ error_return:
+ if (buf != NULL)
+ free (buf);
+ return false;
+}
+
+/* Routines that are called after all the input files have been
+ handled, but before the sections are laid out in memory. */
+
+/* Mark a symbol as not being garbage, including the section in which
+ it is defined. */
+
+static INLINE boolean
+xcoff_mark_symbol (info, h)
+ struct bfd_link_info *info;
+ struct xcoff_link_hash_entry *h;
+{
+ if ((h->flags & XCOFF_MARK) != 0)
+ return true;
+
+ h->flags |= XCOFF_MARK;
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *hsec;
+
+ hsec = h->root.u.def.section;
+ if ((hsec->flags & SEC_MARK) == 0)
+ {
+ if (! xcoff_mark (info, hsec))
+ return false;
+ }
+ }
+
+ if (h->toc_section != NULL
+ && (h->toc_section->flags & SEC_MARK) == 0)
+ {
+ if (! xcoff_mark (info, h->toc_section))
+ return false;
+ }
+
+ return true;
+}
+
+/* The mark phase of garbage collection. For a given section, mark
+ it, and all the sections which define symbols to which it refers.
+ Because this function needs to look at the relocs, we also count
+ the number of relocs which need to be copied into the .loader
+ section. */
+
+static boolean
+xcoff_mark (info, sec)
+ struct bfd_link_info *info;
+ asection *sec;
+{
+ if ((sec->flags & SEC_MARK) != 0)
+ return true;
+
+ sec->flags |= SEC_MARK;
+
+ if (sec->owner->xvec == info->hash->creator
+ && coff_section_data (sec->owner, sec) != NULL
+ && xcoff_section_data (sec->owner, sec) != NULL)
+ {
+ register struct xcoff_link_hash_entry **hp, **hpend;
+ struct internal_reloc *rel, *relend;
+
+ /* Mark all the symbols in this section. */
+
+ hp = (obj_xcoff_sym_hashes (sec->owner)
+ + xcoff_section_data (sec->owner, sec)->first_symndx);
+ hpend = (obj_xcoff_sym_hashes (sec->owner)
+ + xcoff_section_data (sec->owner, sec)->last_symndx);
+ for (; hp < hpend; hp++)
+ {
+ register struct xcoff_link_hash_entry *h;
+
+ h = *hp;
+ if (h != NULL
+ && (h->flags & XCOFF_MARK) == 0)
+ {
+ if (! xcoff_mark_symbol (info, h))
+ return false;
+ }
+ }
+
+ /* Look through the section relocs. */
+
+ if ((sec->flags & SEC_RELOC) != 0
+ && sec->reloc_count > 0)
+ {
+ rel = xcoff_read_internal_relocs (sec->owner, sec, true,
+ (bfd_byte *) NULL, false,
+ (struct internal_reloc *) NULL);
+ if (rel == NULL)
+ return false;
+ relend = rel + sec->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ asection *rsec;
+ struct xcoff_link_hash_entry *h;
+
+ if ((unsigned int) rel->r_symndx
+ > obj_raw_syment_count (sec->owner))
+ continue;
+
+ h = obj_xcoff_sym_hashes (sec->owner)[rel->r_symndx];
+ if (h != NULL
+ && (h->flags & XCOFF_MARK) == 0)
+ {
+ if (! xcoff_mark_symbol (info, h))
+ return false;
+ }
+
+ rsec = xcoff_data (sec->owner)->csects[rel->r_symndx];
+ if (rsec != NULL
+ && (rsec->flags & SEC_MARK) == 0)
+ {
+ if (! xcoff_mark (info, rsec))
+ return false;
+ }
+
+ /* See if this reloc needs to be copied into the .loader
+ section. */
+ switch (rel->r_type)
+ {
+ default:
+ if (h == NULL
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_common
+ || ((h->flags & XCOFF_CALLED) != 0
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ && h->root.root.string[0] == '.'
+ && h->descriptor != NULL
+ && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
+ || info->shared
+ || ((h->descriptor->flags & XCOFF_IMPORT) != 0
+ && (h->descriptor->flags
+ & XCOFF_DEF_REGULAR) == 0))))
+ break;
+ /* Fall through. */
+ case R_POS:
+ case R_NEG:
+ case R_RL:
+ case R_RLA:
+ ++xcoff_hash_table (info)->ldrel_count;
+ if (h != NULL)
+ h->flags |= XCOFF_LDREL;
+ break;
+ case R_TOC:
+ case R_GL:
+ case R_TCL:
+ case R_TRL:
+ case R_TRLA:
+ /* We should never need a .loader reloc for a TOC
+ relative reloc. */
+ break;
+ }
+ }
+
+ if (! info->keep_memory
+ && coff_section_data (sec->owner, sec) != NULL
+ && coff_section_data (sec->owner, sec)->relocs != NULL
+ && ! coff_section_data (sec->owner, sec)->keep_relocs)
+ {
+ free (coff_section_data (sec->owner, sec)->relocs);
+ coff_section_data (sec->owner, sec)->relocs = NULL;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* The sweep phase of garbage collection. Remove all garbage
+ sections. */
+
+static void
+xcoff_sweep (info)
+ struct bfd_link_info *info;
+{
+ bfd *sub;
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *o;
+
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_MARK) == 0)
+ {
+ /* Keep all sections from non-XCOFF input files. Keep
+ special sections. Keep .debug sections for the
+ moment. */
+ if (sub->xvec != info->hash->creator
+ || o == xcoff_hash_table (info)->debug_section
+ || o == xcoff_hash_table (info)->loader_section
+ || o == xcoff_hash_table (info)->linkage_section
+ || o == xcoff_hash_table (info)->toc_section
+ || o == xcoff_hash_table (info)->descriptor_section
+ || strcmp (o->name, ".debug") == 0)
+ o->flags |= SEC_MARK;
+ else
+ {
+ o->_raw_size = 0;
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ }
+ }
+ }
+ }
+}
+
+/* Record the number of elements in a set. This is used to output the
+ correct csect length. */
+
+boolean
+bfd_xcoff_link_record_set (output_bfd, info, harg, size)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct bfd_link_hash_entry *harg;
+ bfd_size_type size;
+{
+ struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
+ struct xcoff_link_size_list *n;
+
+ if (! XCOFF_XVECP (output_bfd->xvec))
+ return true;
+
+ /* This will hardly ever be called. I don't want to burn four bytes
+ per global symbol, so instead the size is kept on a linked list
+ attached to the hash table. */
+
+ n = ((struct xcoff_link_size_list *)
+ bfd_alloc (output_bfd, sizeof (struct xcoff_link_size_list)));
+ if (n == NULL)
+ return false;
+ n->next = xcoff_hash_table (info)->size_list;
+ n->h = h;
+ n->size = size;
+ xcoff_hash_table (info)->size_list = n;
+
+ h->flags |= XCOFF_HAS_SIZE;
+
+ return true;
+}
+
+/* Import a symbol. */
+
+boolean
+bfd_xcoff_import_symbol (output_bfd, info, harg, val, imppath, impfile,
+ impmember)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct bfd_link_hash_entry *harg;
+ bfd_vma val;
+ const char *imppath;
+ const char *impfile;
+ const char *impmember;
+{
+ struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
+
+ if (! XCOFF_XVECP (output_bfd->xvec))
+ return true;
+
+ h->flags |= XCOFF_IMPORT;
+
+ if (val != (bfd_vma) -1)
+ {
+ if (h->root.type == bfd_link_hash_defined
+ && (! bfd_is_abs_section (h->root.u.def.section)
+ || h->root.u.def.value != val))
+ {
+ if (! ((*info->callbacks->multiple_definition)
+ (info, h->root.root.string, h->root.u.def.section->owner,
+ h->root.u.def.section, h->root.u.def.value,
+ output_bfd, bfd_abs_section_ptr, val)))
+ return false;
+ }
+
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.section = bfd_abs_section_ptr;
+ h->root.u.def.value = val;
+ }
+
+ if (h->ldsym == NULL)
+ {
+ h->ldsym = ((struct internal_ldsym *)
+ bfd_zalloc (output_bfd, sizeof (struct internal_ldsym)));
+ if (h->ldsym == NULL)
+ return false;
+ }
+
+ if (imppath == NULL)
+ h->ldsym->l_ifile = (bfd_size_type) -1;
+ else
+ {
+ unsigned int c;
+ struct xcoff_import_file **pp;
+
+ /* We start c at 1 because the first entry in the import list is
+ reserved for the library search path. */
+ for (pp = &xcoff_hash_table (info)->imports, c = 1;
+ *pp != NULL;
+ pp = &(*pp)->next, ++c)
+ {
+ if (strcmp ((*pp)->path, imppath) == 0
+ && strcmp ((*pp)->file, impfile) == 0
+ && strcmp ((*pp)->member, impmember) == 0)
+ break;
+ }
+
+ if (*pp == NULL)
+ {
+ struct xcoff_import_file *n;
+
+ n = ((struct xcoff_import_file *)
+ bfd_alloc (output_bfd, sizeof (struct xcoff_import_file)));
+ if (n == NULL)
+ return false;
+ n->next = NULL;
+ n->path = imppath;
+ n->file = impfile;
+ n->member = impmember;
+ *pp = n;
+ }
+
+ h->ldsym->l_ifile = c;
+ }
+
+ return true;
+}
+
+/* Export a symbol. */
+
+boolean
+bfd_xcoff_export_symbol (output_bfd, info, harg, syscall)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ struct bfd_link_hash_entry *harg;
+ boolean syscall;
+{
+ struct xcoff_link_hash_entry *h = (struct xcoff_link_hash_entry *) harg;
+
+ if (! XCOFF_XVECP (output_bfd->xvec))
+ return true;
+
+ h->flags |= XCOFF_EXPORT;
+
+ /* FIXME: I'm not at all sure what syscall is supposed to mean, so
+ I'm just going to ignore it until somebody explains it. */
+
+ /* See if this is a function descriptor. It may be one even though
+ it is not so marked. */
+ if ((h->flags & XCOFF_DESCRIPTOR) == 0
+ && h->root.root.string[0] != '.')
+ {
+ char *fnname;
+ struct xcoff_link_hash_entry *hfn;
+
+ fnname = (char *) bfd_malloc (strlen (h->root.root.string) + 2);
+ if (fnname == NULL)
+ return false;
+ fnname[0] = '.';
+ strcpy (fnname + 1, h->root.root.string);
+ hfn = xcoff_link_hash_lookup (xcoff_hash_table (info),
+ fnname, false, false, true);
+ free (fnname);
+ if (hfn != NULL
+ && hfn->smclas == XMC_PR
+ && (hfn->root.type == bfd_link_hash_defined
+ || hfn->root.type == bfd_link_hash_defweak))
+ {
+ h->flags |= XCOFF_DESCRIPTOR;
+ h->descriptor = hfn;
+ hfn->descriptor = h;
+ }
+ }
+
+ /* Make sure we don't garbage collect this symbol. */
+ if (! xcoff_mark_symbol (info, h))
+ return false;
+
+ /* If this is a function descriptor, make sure we don't garbage
+ collect the associated function code. We normally don't have to
+ worry about this, because the descriptor will be attached to a
+ section with relocs, but if we are creating the descriptor
+ ourselves those relocs will not be visible to the mark code. */
+ if ((h->flags & XCOFF_DESCRIPTOR) != 0)
+ {
+ if (! xcoff_mark_symbol (info, h->descriptor))
+ return false;
+ }
+
+ return true;
+}
+
+/* Count a reloc against a symbol. This is called for relocs
+ generated by the linker script, typically for global constructors
+ and destructors. */
+
+boolean
+bfd_xcoff_link_count_reloc (output_bfd, info, name)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ const char *name;
+{
+ struct xcoff_link_hash_entry *h;
+
+ if (! XCOFF_XVECP (output_bfd->xvec))
+ return true;
+
+ h = ((struct xcoff_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, info, name, false, false,
+ false));
+ if (h == NULL)
+ {
+ (*_bfd_error_handler) ("%s: no such symbol", name);
+ bfd_set_error (bfd_error_no_symbols);
+ return false;
+ }
+
+ h->flags |= XCOFF_REF_REGULAR | XCOFF_LDREL;
+ ++xcoff_hash_table (info)->ldrel_count;
+
+ /* Mark the symbol to avoid garbage collection. */
+ if (! xcoff_mark_symbol (info, h))
+ return false;
+
+ return true;
+}
+
+/* This function is called for each symbol to which the linker script
+ assigns a value. */
+
+boolean
+bfd_xcoff_record_link_assignment (output_bfd, info, name)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ const char *name;
+{
+ struct xcoff_link_hash_entry *h;
+
+ if (! XCOFF_XVECP (output_bfd->xvec))
+ return true;
+
+ h = xcoff_link_hash_lookup (xcoff_hash_table (info), name, true, true,
+ false);
+ if (h == NULL)
+ return false;
+
+ h->flags |= XCOFF_DEF_REGULAR;
+
+ return true;
+}
+
+/* This structure is used to pass information through
+ xcoff_link_hash_traverse. */
+
+struct xcoff_loader_info
+{
+ /* Set if a problem occurred. */
+ boolean failed;
+ /* Output BFD. */
+ bfd *output_bfd;
+ /* Link information structure. */
+ struct bfd_link_info *info;
+ /* Whether all defined symbols should be exported. */
+ boolean export_defineds;
+ /* Number of ldsym structures. */
+ size_t ldsym_count;
+ /* Size of string table. */
+ size_t string_size;
+ /* String table. */
+ bfd_byte *strings;
+ /* Allocated size of string table. */
+ size_t string_alc;
+};
+
+/* Build the .loader section. This is called by the XCOFF linker
+ emulation before_allocation routine. We must set the size of the
+ .loader section before the linker lays out the output file.
+ LIBPATH is the library path to search for shared objects; this is
+ normally built from the -L arguments passed to the linker. ENTRY
+ is the name of the entry point symbol (the -e linker option).
+ FILE_ALIGN is the alignment to use for sections within the file
+ (the -H linker option). MAXSTACK is the maximum stack size (the
+ -bmaxstack linker option). MAXDATA is the maximum data size (the
+ -bmaxdata linker option). GC is whether to do garbage collection
+ (the -bgc linker option). MODTYPE is the module type (the
+ -bmodtype linker option). TEXTRO is whether the text section must
+ be read only (the -btextro linker option). EXPORT_DEFINEDS is
+ whether all defined symbols should be exported (the -unix linker
+ option). SPECIAL_SECTIONS is set by this routine to csects with
+ magic names like _end. */
+
+boolean
+bfd_xcoff_size_dynamic_sections (output_bfd, info, libpath, entry,
+ file_align, maxstack, maxdata, gc,
+ modtype, textro, export_defineds,
+ special_sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ const char *libpath;
+ const char *entry;
+ unsigned long file_align;
+ unsigned long maxstack;
+ unsigned long maxdata;
+ boolean gc;
+ int modtype;
+ boolean textro;
+ boolean export_defineds;
+ asection **special_sections;
+{
+ struct xcoff_link_hash_entry *hentry;
+ asection *lsec;
+ struct xcoff_loader_info ldinfo;
+ int i;
+ size_t impsize, impcount;
+ struct xcoff_import_file *fl;
+ struct internal_ldhdr *ldhdr;
+ bfd_size_type stoff;
+ register char *out;
+ asection *sec;
+ bfd *sub;
+ struct bfd_strtab_hash *debug_strtab;
+ bfd_byte *debug_contents = NULL;
+
+ if (! XCOFF_XVECP (output_bfd->xvec))
+ {
+ for (i = 0; i < 6; i++)
+ special_sections[i] = NULL;
+ return true;
+ }
+
+ ldinfo.failed = false;
+ ldinfo.output_bfd = output_bfd;
+ ldinfo.info = info;
+ ldinfo.export_defineds = export_defineds;
+ ldinfo.ldsym_count = 0;
+ ldinfo.string_size = 0;
+ ldinfo.strings = NULL;
+ ldinfo.string_alc = 0;
+
+ xcoff_data (output_bfd)->maxstack = maxstack;
+ xcoff_data (output_bfd)->maxdata = maxdata;
+ xcoff_data (output_bfd)->modtype = modtype;
+
+ xcoff_hash_table (info)->file_align = file_align;
+ xcoff_hash_table (info)->textro = textro;
+
+ hentry = xcoff_link_hash_lookup (xcoff_hash_table (info), entry,
+ false, false, true);
+ if (hentry != NULL)
+ hentry->flags |= XCOFF_ENTRY;
+
+ /* Garbage collect unused sections. */
+ if (info->relocateable
+ || ! gc
+ || hentry == NULL
+ || (hentry->root.type != bfd_link_hash_defined
+ && hentry->root.type != bfd_link_hash_defweak))
+ {
+ gc = false;
+ xcoff_hash_table (info)->gc = false;
+
+ /* We still need to call xcoff_mark, in order to set ldrel_count
+ correctly. */
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *o;
+
+ for (o = sub->sections; o != NULL; o = o->next)
+ {
+ if ((o->flags & SEC_MARK) == 0)
+ {
+ if (! xcoff_mark (info, o))
+ goto error_return;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (! xcoff_mark (info, hentry->root.u.def.section))
+ goto error_return;
+ xcoff_sweep (info);
+ xcoff_hash_table (info)->gc = true;
+ }
+
+ /* Return special sections to the caller. */
+ for (i = 0; i < 6; i++)
+ {
+ asection *sec;
+
+ sec = xcoff_hash_table (info)->special_sections[i];
+ if (sec != NULL
+ && gc
+ && (sec->flags & SEC_MARK) == 0)
+ sec = NULL;
+ special_sections[i] = sec;
+ }
+
+ if (info->input_bfds == NULL)
+ {
+ /* I'm not sure what to do in this bizarre case. */
+ return true;
+ }
+
+ xcoff_link_hash_traverse (xcoff_hash_table (info), xcoff_build_ldsyms,
+ (PTR) &ldinfo);
+ if (ldinfo.failed)
+ goto error_return;
+
+ /* Work out the size of the import file names. Each import file ID
+ consists of three null terminated strings: the path, the file
+ name, and the archive member name. The first entry in the list
+ of names is the path to use to find objects, which the linker has
+ passed in as the libpath argument. For some reason, the path
+ entry in the other import file names appears to always be empty. */
+ impsize = strlen (libpath) + 3;
+ impcount = 1;
+ for (fl = xcoff_hash_table (info)->imports; fl != NULL; fl = fl->next)
+ {
+ ++impcount;
+ impsize += (strlen (fl->path)
+ + strlen (fl->file)
+ + strlen (fl->member)
+ + 3);
+ }
+
+ /* Set up the .loader section header. */
+ ldhdr = &xcoff_hash_table (info)->ldhdr;
+ ldhdr->l_version = 1;
+ ldhdr->l_nsyms = ldinfo.ldsym_count;
+ ldhdr->l_nreloc = xcoff_hash_table (info)->ldrel_count;
+ ldhdr->l_istlen = impsize;
+ ldhdr->l_nimpid = impcount;
+ ldhdr->l_impoff = (LDHDRSZ
+ + ldhdr->l_nsyms * LDSYMSZ
+ + ldhdr->l_nreloc * LDRELSZ);
+ ldhdr->l_stlen = ldinfo.string_size;
+ stoff = ldhdr->l_impoff + impsize;
+ if (ldinfo.string_size == 0)
+ ldhdr->l_stoff = 0;
+ else
+ ldhdr->l_stoff = stoff;
+
+ /* We now know the final size of the .loader section. Allocate
+ space for it. */
+ lsec = xcoff_hash_table (info)->loader_section;
+ lsec->_raw_size = stoff + ldhdr->l_stlen;
+ lsec->contents = (bfd_byte *) bfd_zalloc (output_bfd, lsec->_raw_size);
+ if (lsec->contents == NULL)
+ goto error_return;
+
+ /* Set up the header. */
+ xcoff_swap_ldhdr_out (output_bfd, ldhdr,
+ (struct external_ldhdr *) lsec->contents);
+
+ /* Set up the import file names. */
+ out = (char *) lsec->contents + ldhdr->l_impoff;
+ strcpy (out, libpath);
+ out += strlen (libpath) + 1;
+ *out++ = '\0';
+ *out++ = '\0';
+ for (fl = xcoff_hash_table (info)->imports; fl != NULL; fl = fl->next)
+ {
+ register const char *s;
+
+ s = fl->path;
+ while ((*out++ = *s++) != '\0')
+ ;
+ s = fl->file;
+ while ((*out++ = *s++) != '\0')
+ ;
+ s = fl->member;
+ while ((*out++ = *s++) != '\0')
+ ;
+ }
+
+ BFD_ASSERT ((bfd_size_type) ((bfd_byte *) out - lsec->contents) == stoff);
+
+ /* Set up the symbol string table. */
+ if (ldinfo.string_size > 0)
+ {
+ memcpy (out, ldinfo.strings, ldinfo.string_size);
+ free (ldinfo.strings);
+ ldinfo.strings = NULL;
+ }
+
+ /* We can't set up the symbol table or the relocs yet, because we
+ don't yet know the final position of the various sections. The
+ .loader symbols are written out when the corresponding normal
+ symbols are written out in xcoff_link_input_bfd or
+ xcoff_write_global_symbol. The .loader relocs are written out
+ when the corresponding normal relocs are handled in
+ xcoff_link_input_bfd. */
+
+ /* Allocate space for the magic sections. */
+ sec = xcoff_hash_table (info)->linkage_section;
+ if (sec->_raw_size > 0)
+ {
+ sec->contents = (bfd_byte *) bfd_zalloc (output_bfd, sec->_raw_size);
+ if (sec->contents == NULL)
+ goto error_return;
+ }
+ sec = xcoff_hash_table (info)->toc_section;
+ if (sec->_raw_size > 0)
+ {
+ sec->contents = (bfd_byte *) bfd_zalloc (output_bfd, sec->_raw_size);
+ if (sec->contents == NULL)
+ goto error_return;
+ }
+ sec = xcoff_hash_table (info)->descriptor_section;
+ if (sec->_raw_size > 0)
+ {
+ sec->contents = (bfd_byte *) bfd_zalloc (output_bfd, sec->_raw_size);
+ if (sec->contents == NULL)
+ goto error_return;
+ }
+
+ /* Now that we've done garbage collection, figure out the contents
+ of the .debug section. */
+ debug_strtab = xcoff_hash_table (info)->debug_strtab;
+
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ asection *subdeb;
+ bfd_size_type symcount;
+ unsigned long *debug_index;
+ asection **csectpp;
+ bfd_byte *esym, *esymend;
+ bfd_size_type symesz;
+
+ if (sub->xvec != info->hash->creator)
+ continue;
+ subdeb = bfd_get_section_by_name (sub, ".debug");
+ if (subdeb == NULL || subdeb->_raw_size == 0)
+ continue;
+
+ if (info->strip == strip_all
+ || info->strip == strip_debugger
+ || info->discard == discard_all)
+ {
+ subdeb->_raw_size = 0;
+ continue;
+ }
+
+ if (! _bfd_coff_get_external_symbols (sub))
+ goto error_return;
+
+ symcount = obj_raw_syment_count (sub);
+ debug_index = ((unsigned long *)
+ bfd_zalloc (sub, symcount * sizeof (unsigned long)));
+ if (debug_index == NULL)
+ goto error_return;
+ xcoff_data (sub)->debug_indices = debug_index;
+
+ /* Grab the contents of the .debug section. We use malloc and
+ copy the neams into the debug stringtab, rather than
+ bfd_alloc, because I expect that, when linking many files
+ together, many of the strings will be the same. Storing the
+ strings in the hash table should save space in this case. */
+ debug_contents = (bfd_byte *) bfd_malloc (subdeb->_raw_size);
+ if (debug_contents == NULL)
+ goto error_return;
+ if (! bfd_get_section_contents (sub, subdeb, (PTR) debug_contents,
+ (file_ptr) 0, subdeb->_raw_size))
+ goto error_return;
+
+ csectpp = xcoff_data (sub)->csects;
+
+ symesz = bfd_coff_symesz (sub);
+ esym = (bfd_byte *) obj_coff_external_syms (sub);
+ esymend = esym + symcount * symesz;
+ while (esym < esymend)
+ {
+ struct internal_syment sym;
+
+ bfd_coff_swap_sym_in (sub, (PTR) esym, (PTR) &sym);
+
+ *debug_index = (unsigned long) -1;
+
+ if (sym._n._n_n._n_zeroes == 0
+ && *csectpp != NULL
+ && (! gc
+ || ((*csectpp)->flags & SEC_MARK) != 0
+ || *csectpp == bfd_abs_section_ptr)
+ && bfd_coff_symname_in_debug (sub, &sym))
+ {
+ char *name;
+ bfd_size_type indx;
+
+ name = (char *) debug_contents + sym._n._n_n._n_offset;
+ indx = _bfd_stringtab_add (debug_strtab, name, true, true);
+ if (indx == (bfd_size_type) -1)
+ goto error_return;
+ *debug_index = indx;
+ }
+
+ esym += (sym.n_numaux + 1) * symesz;
+ csectpp += sym.n_numaux + 1;
+ debug_index += sym.n_numaux + 1;
+ }
+
+ free (debug_contents);
+ debug_contents = NULL;
+
+ /* Clear the size of subdeb, so that it is not included directly
+ in the output file. */
+ subdeb->_raw_size = 0;
+
+ if (! info->keep_memory)
+ {
+ if (! _bfd_coff_free_symbols (sub))
+ goto error_return;
+ }
+ }
+
+ xcoff_hash_table (info)->debug_section->_raw_size =
+ _bfd_stringtab_size (debug_strtab);
+
+ return true;
+
+ error_return:
+ if (ldinfo.strings != NULL)
+ free (ldinfo.strings);
+ if (debug_contents != NULL)
+ free (debug_contents);
+ return false;
+}
+
+/* Add a symbol to the .loader symbols, if necessary. */
+
+static boolean
+xcoff_build_ldsyms (h, p)
+ struct xcoff_link_hash_entry *h;
+ PTR p;
+{
+ struct xcoff_loader_info *ldinfo = (struct xcoff_loader_info *) p;
+ size_t len;
+
+ /* If all defined symbols should be exported, mark them now. */
+ if (ldinfo->export_defineds
+ && (h->flags & XCOFF_DEF_REGULAR) != 0)
+ h->flags |= XCOFF_EXPORT;
+
+ /* We don't want to garbage collect symbols which are not defined in
+ XCOFF files. This is a convenient place to mark them. */
+ if (xcoff_hash_table (ldinfo->info)->gc
+ && (h->flags & XCOFF_MARK) == 0
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && (h->root.u.def.section->owner == NULL
+ || (h->root.u.def.section->owner->xvec
+ != ldinfo->info->hash->creator)))
+ h->flags |= XCOFF_MARK;
+
+ /* If this symbol is called and defined in a dynamic object, or not
+ defined at all when building a shared object, or imported, then
+ we need to set up global linkage code for it. (Unless we did
+ garbage collection and we didn't need this symbol.) */
+ if ((h->flags & XCOFF_CALLED) != 0
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ && h->root.root.string[0] == '.'
+ && h->descriptor != NULL
+ && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0
+ || ldinfo->info->shared
+ || ((h->descriptor->flags & XCOFF_IMPORT) != 0
+ && (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0))
+ && (! xcoff_hash_table (ldinfo->info)->gc
+ || (h->flags & XCOFF_MARK) != 0))
+ {
+ asection *sec;
+ struct xcoff_link_hash_entry *hds;
+
+ sec = xcoff_hash_table (ldinfo->info)->linkage_section;
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.section = sec;
+ h->root.u.def.value = sec->_raw_size;
+ h->smclas = XMC_GL;
+ h->flags |= XCOFF_DEF_REGULAR;
+ sec->_raw_size += XCOFF_GLINK_SIZE;
+
+ /* The global linkage code requires a TOC entry for the
+ descriptor. */
+ hds = h->descriptor;
+ BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined
+ || hds->root.type == bfd_link_hash_undefweak)
+ && (hds->flags & XCOFF_DEF_REGULAR) == 0);
+ hds->flags |= XCOFF_MARK;
+ if (hds->toc_section == NULL)
+ {
+ hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section;
+ hds->u.toc_offset = hds->toc_section->_raw_size;
+ hds->toc_section->_raw_size += 4;
+ ++xcoff_hash_table (ldinfo->info)->ldrel_count;
+ ++hds->toc_section->reloc_count;
+ hds->indx = -2;
+ hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL;
+
+ /* We need to call xcoff_build_ldsyms recursively here,
+ because we may already have passed hds on the traversal. */
+ xcoff_build_ldsyms (hds, p);
+ }
+ }
+
+ /* If this symbol is exported, but not defined, we need to try to
+ define it. */
+ if ((h->flags & XCOFF_EXPORT) != 0
+ && (h->flags & XCOFF_IMPORT) == 0
+ && (h->flags & XCOFF_DEF_REGULAR) == 0
+ && (h->flags & XCOFF_DEF_DYNAMIC) == 0
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak))
+ {
+ if ((h->flags & XCOFF_DESCRIPTOR) != 0
+ && (h->descriptor->root.type == bfd_link_hash_defined
+ || h->descriptor->root.type == bfd_link_hash_defweak))
+ {
+ asection *sec;
+
+ /* This is an undefined function descriptor associated with
+ a defined entry point. We can build up a function
+ descriptor ourselves. Believe it or not, the AIX linker
+ actually does this, and there are cases where we need to
+ do it as well. */
+ sec = xcoff_hash_table (ldinfo->info)->descriptor_section;
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.section = sec;
+ h->root.u.def.value = sec->_raw_size;
+ h->smclas = XMC_DS;
+ h->flags |= XCOFF_DEF_REGULAR;
+ sec->_raw_size += 12;
+
+ /* A function descriptor uses two relocs: one for the
+ associated code, and one for the TOC address. */
+ xcoff_hash_table (ldinfo->info)->ldrel_count += 2;
+ sec->reloc_count += 2;
+
+ /* We handle writing out the contents of the descriptor in
+ xcoff_write_global_symbol. */
+ }
+ else
+ {
+ (*_bfd_error_handler)
+ ("attempt to export undefined symbol `%s'",
+ h->root.root.string);
+ ldinfo->failed = true;
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+ }
+
+ /* If this is still a common symbol, and it wasn't garbage
+ collected, we need to actually allocate space for it in the .bss
+ section. */
+ if (h->root.type == bfd_link_hash_common
+ && (! xcoff_hash_table (ldinfo->info)->gc
+ || (h->flags & XCOFF_MARK) != 0)
+ && h->root.u.c.p->section->_raw_size == 0)
+ {
+ BFD_ASSERT (bfd_is_com_section (h->root.u.c.p->section));
+ h->root.u.c.p->section->_raw_size = h->root.u.c.size;
+ }
+
+ /* We need to add a symbol to the .loader section if it is mentioned
+ in a reloc which we are copying to the .loader section and it was
+ not defined or common, or if it is the entry point, or if it is
+ being exported. */
+
+ if (((h->flags & XCOFF_LDREL) == 0
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_common)
+ && (h->flags & XCOFF_ENTRY) == 0
+ && (h->flags & XCOFF_EXPORT) == 0)
+ {
+ h->ldsym = NULL;
+ return true;
+ }
+
+ /* We don't need to add this symbol if we did garbage collection and
+ we did not mark this symbol. */
+ if (xcoff_hash_table (ldinfo->info)->gc
+ && (h->flags & XCOFF_MARK) == 0)
+ {
+ h->ldsym = NULL;
+ return true;
+ }
+
+ /* We may have already processed this symbol due to the recursive
+ call above. */
+ if ((h->flags & XCOFF_BUILT_LDSYM) != 0)
+ return true;
+
+ /* We need to add this symbol to the .loader symbols. */
+
+ /* h->ldsym will already have been allocated for an explicitly
+ imported symbol. */
+ if (h->ldsym == NULL)
+ {
+ h->ldsym = ((struct internal_ldsym *)
+ bfd_zalloc (ldinfo->output_bfd,
+ sizeof (struct internal_ldsym)));
+ if (h->ldsym == NULL)
+ {
+ ldinfo->failed = true;
+ return false;
+ }
+ }
+
+ /* The first 3 symbol table indices are reserved to indicate the
+ sections. */
+ h->ldindx = ldinfo->ldsym_count + 3;
+
+ ++ldinfo->ldsym_count;
+
+ len = strlen (h->root.root.string);
+ if (len <= SYMNMLEN)
+ strncpy (h->ldsym->_l._l_name, h->root.root.string, SYMNMLEN);
+ else
+ {
+ if (ldinfo->string_size + len + 3 > ldinfo->string_alc)
+ {
+ size_t newalc;
+ bfd_byte *newstrings;
+
+ newalc = ldinfo->string_alc * 2;
+ if (newalc == 0)
+ newalc = 32;
+ while (ldinfo->string_size + len + 3 > newalc)
+ newalc *= 2;
+
+ newstrings = ((bfd_byte *)
+ bfd_realloc ((PTR) ldinfo->strings, newalc));
+ if (newstrings == NULL)
+ {
+ ldinfo->failed = true;
+ return false;
+ }
+ ldinfo->string_alc = newalc;
+ ldinfo->strings = newstrings;
+ }
+
+ bfd_put_16 (ldinfo->output_bfd, len + 1,
+ ldinfo->strings + ldinfo->string_size);
+ strcpy (ldinfo->strings + ldinfo->string_size + 2, h->root.root.string);
+ h->ldsym->_l._l_l._l_zeroes = 0;
+ h->ldsym->_l._l_l._l_offset = ldinfo->string_size + 2;
+ ldinfo->string_size += len + 3;
+ }
+
+ h->flags |= XCOFF_BUILT_LDSYM;
+
+ return true;
+}
+
+/* Do the final link step. */
+
+boolean
+_bfd_xcoff_bfd_final_link (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info;
+{
+ bfd_size_type symesz;
+ struct xcoff_final_link_info finfo;
+ asection *o;
+ struct bfd_link_order *p;
+ size_t max_contents_size;
+ size_t max_sym_count;
+ size_t max_lineno_count;
+ size_t max_reloc_count;
+ size_t max_output_reloc_count;
+ file_ptr rel_filepos;
+ unsigned int relsz;
+ file_ptr line_filepos;
+ unsigned int linesz;
+ bfd *sub;
+ bfd_byte *external_relocs = NULL;
+ char strbuf[STRING_SIZE_SIZE];
+
+ if (info->shared)
+ abfd->flags |= DYNAMIC;
+
+ symesz = bfd_coff_symesz (abfd);
+
+ finfo.info = info;
+ finfo.output_bfd = abfd;
+ finfo.strtab = NULL;
+ finfo.section_info = NULL;
+ finfo.last_file_index = -1;
+ finfo.toc_symindx = -1;
+ finfo.internal_syms = NULL;
+ finfo.sym_indices = NULL;
+ finfo.outsyms = NULL;
+ finfo.linenos = NULL;
+ finfo.contents = NULL;
+ finfo.external_relocs = NULL;
+
+ finfo.ldsym = ((struct external_ldsym *)
+ (xcoff_hash_table (info)->loader_section->contents
+ + LDHDRSZ));
+ finfo.ldrel = ((struct external_ldrel *)
+ (xcoff_hash_table (info)->loader_section->contents
+ + LDHDRSZ
+ + xcoff_hash_table (info)->ldhdr.l_nsyms * LDSYMSZ));
+
+ xcoff_data (abfd)->coff.link_info = info;
+
+ finfo.strtab = _bfd_stringtab_init ();
+ if (finfo.strtab == NULL)
+ goto error_return;
+
+ /* Count the line number and relocation entries required for the
+ output file. Determine a few maximum sizes. */
+ max_contents_size = 0;
+ max_lineno_count = 0;
+ max_reloc_count = 0;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order)
+ {
+ asection *sec;
+
+ sec = p->u.indirect.section;
+
+ if (info->strip == strip_none
+ || info->strip == strip_some)
+ o->lineno_count += sec->lineno_count;
+
+ o->reloc_count += sec->reloc_count;
+
+ if (sec->_raw_size > max_contents_size)
+ max_contents_size = sec->_raw_size;
+ if (sec->lineno_count > max_lineno_count)
+ max_lineno_count = sec->lineno_count;
+ if (coff_section_data (sec->owner, sec) != NULL
+ && xcoff_section_data (sec->owner, sec) != NULL
+ && (xcoff_section_data (sec->owner, sec)->lineno_count
+ > max_lineno_count))
+ max_lineno_count =
+ xcoff_section_data (sec->owner, sec)->lineno_count;
+ if (sec->reloc_count > max_reloc_count)
+ max_reloc_count = sec->reloc_count;
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ ++o->reloc_count;
+ }
+ }
+
+ /* Compute the file positions for all the sections. */
+ if (abfd->output_has_begun)
+ {
+ if (xcoff_hash_table (info)->file_align != 0)
+ abort ();
+ }
+ else
+ {
+ bfd_vma file_align;
+
+ file_align = xcoff_hash_table (info)->file_align;
+ if (file_align != 0)
+ {
+ boolean saw_contents;
+ int indx;
+ asection **op;
+ file_ptr sofar;
+
+ /* Insert .pad sections before every section which has
+ contents and is loaded, if it is preceded by some other
+ section which has contents and is loaded. */
+ saw_contents = true;
+ for (op = &abfd->sections; *op != NULL; op = &(*op)->next)
+ {
+ (*op)->target_index = indx;
+ if (strcmp ((*op)->name, ".pad") == 0)
+ saw_contents = false;
+ else if (((*op)->flags & SEC_HAS_CONTENTS) != 0
+ && ((*op)->flags & SEC_LOAD) != 0)
+ {
+ if (! saw_contents)
+ saw_contents = true;
+ else
+ {
+ asection *n, *hold;
+
+ hold = *op;
+ *op = NULL;
+ n = bfd_make_section_anyway (abfd, ".pad");
+ BFD_ASSERT (*op == n);
+ n->next = hold;
+ n->flags = SEC_HAS_CONTENTS;
+ n->alignment_power = 0;
+ saw_contents = false;
+ }
+ }
+ }
+
+ /* Reset the section indices after inserting the new
+ sections. */
+ indx = 0;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ ++indx;
+ o->target_index = indx;
+ }
+ BFD_ASSERT ((unsigned int) indx == abfd->section_count);
+
+ /* Work out appropriate sizes for the .pad sections to force
+ each section to land on a page boundary. This bit of
+ code knows what compute_section_file_positions is going
+ to do. */
+ sofar = bfd_coff_filhsz (abfd);
+ sofar += bfd_coff_aoutsz (abfd);
+ sofar += abfd->section_count * bfd_coff_scnhsz (abfd);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ if (o->reloc_count >= 0xffff || o->lineno_count >= 0xffff)
+ sofar += bfd_coff_scnhsz (abfd);
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (strcmp (o->name, ".pad") == 0)
+ {
+ bfd_vma pageoff;
+
+ BFD_ASSERT (o->_raw_size == 0);
+ pageoff = sofar & (file_align - 1);
+ if (pageoff != 0)
+ {
+ o->_raw_size = file_align - pageoff;
+ sofar += file_align - pageoff;
+ o->flags |= SEC_HAS_CONTENTS;
+ }
+ }
+ else
+ {
+ if ((o->flags & SEC_HAS_CONTENTS) != 0)
+ sofar += BFD_ALIGN (o->_raw_size,
+ 1 << o->alignment_power);
+ }
+ }
+ }
+
+ bfd_coff_compute_section_file_positions (abfd);
+ }
+
+ /* Allocate space for the pointers we need to keep for the relocs. */
+ {
+ unsigned int i;
+
+ /* We use section_count + 1, rather than section_count, because
+ the target_index fields are 1 based. */
+ finfo.section_info =
+ ((struct xcoff_link_section_info *)
+ bfd_malloc ((abfd->section_count + 1)
+ * sizeof (struct xcoff_link_section_info)));
+ if (finfo.section_info == NULL)
+ goto error_return;
+ for (i = 0; i <= abfd->section_count; i++)
+ {
+ finfo.section_info[i].relocs = NULL;
+ finfo.section_info[i].rel_hashes = NULL;
+ finfo.section_info[i].toc_rel_hashes = NULL;
+ }
+ }
+
+ /* Set the file positions for the relocs. */
+ rel_filepos = obj_relocbase (abfd);
+ relsz = bfd_coff_relsz (abfd);
+ max_output_reloc_count = 0;
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (o->reloc_count == 0)
+ o->rel_filepos = 0;
+ else
+ {
+ o->flags |= SEC_RELOC;
+ o->rel_filepos = rel_filepos;
+ rel_filepos += o->reloc_count * relsz;
+
+ /* We don't know the indices of global symbols until we have
+ written out all the local symbols. For each section in
+ the output file, we keep an array of pointers to hash
+ table entries. Each entry in the array corresponds to a
+ reloc. When we find a reloc against a global symbol, we
+ set the corresponding entry in this array so that we can
+ fix up the symbol index after we have written out all the
+ local symbols.
+
+ Because of this problem, we also keep the relocs in
+ memory until the end of the link. This wastes memory.
+ We could backpatch the file later, I suppose, although it
+ would be slow. */
+ finfo.section_info[o->target_index].relocs =
+ ((struct internal_reloc *)
+ bfd_malloc (o->reloc_count * sizeof (struct internal_reloc)));
+ finfo.section_info[o->target_index].rel_hashes =
+ ((struct xcoff_link_hash_entry **)
+ bfd_malloc (o->reloc_count
+ * sizeof (struct xcoff_link_hash_entry *)));
+ if (finfo.section_info[o->target_index].relocs == NULL
+ || finfo.section_info[o->target_index].rel_hashes == NULL)
+ goto error_return;
+
+ if (o->reloc_count > max_output_reloc_count)
+ max_output_reloc_count = o->reloc_count;
+ }
+ }
+
+ /* We now know the size of the relocs, so we can determine the file
+ positions of the line numbers. */
+ line_filepos = rel_filepos;
+ finfo.line_filepos = line_filepos;
+ linesz = bfd_coff_linesz (abfd);
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ if (o->lineno_count == 0)
+ o->line_filepos = 0;
+ else
+ {
+ o->line_filepos = line_filepos;
+ line_filepos += o->lineno_count * linesz;
+ }
+
+ /* Reset the reloc and lineno counts, so that we can use them to
+ count the number of entries we have output so far. */
+ o->reloc_count = 0;
+ o->lineno_count = 0;
+ }
+
+ obj_sym_filepos (abfd) = line_filepos;
+
+ /* Figure out the largest number of symbols in an input BFD. Take
+ the opportunity to clear the output_has_begun fields of all the
+ input BFD's. We want at least 4 symbols, since that is the
+ number which xcoff_write_global_symbol may need. */
+ max_sym_count = 4;
+ for (sub = info->input_bfds; sub != NULL; sub = sub->link_next)
+ {
+ size_t sz;
+
+ sub->output_has_begun = false;
+ sz = obj_raw_syment_count (sub);
+ if (sz > max_sym_count)
+ max_sym_count = sz;
+ }
+
+ /* Allocate some buffers used while linking. */
+ finfo.internal_syms = ((struct internal_syment *)
+ bfd_malloc (max_sym_count
+ * sizeof (struct internal_syment)));
+ finfo.sym_indices = (long *) bfd_malloc (max_sym_count * sizeof (long));
+ finfo.outsyms = ((bfd_byte *)
+ bfd_malloc ((size_t) ((max_sym_count + 1) * symesz)));
+ finfo.linenos = (bfd_byte *) bfd_malloc (max_lineno_count
+ * bfd_coff_linesz (abfd));
+ finfo.contents = (bfd_byte *) bfd_malloc (max_contents_size);
+ finfo.external_relocs = (bfd_byte *) bfd_malloc (max_reloc_count * relsz);
+ if ((finfo.internal_syms == NULL && max_sym_count > 0)
+ || (finfo.sym_indices == NULL && max_sym_count > 0)
+ || finfo.outsyms == NULL
+ || (finfo.linenos == NULL && max_lineno_count > 0)
+ || (finfo.contents == NULL && max_contents_size > 0)
+ || (finfo.external_relocs == NULL && max_reloc_count > 0))
+ goto error_return;
+
+ obj_raw_syment_count (abfd) = 0;
+ xcoff_data (abfd)->toc = (bfd_vma) -1;
+
+ /* We now know the position of everything in the file, except that
+ we don't know the size of the symbol table and therefore we don't
+ know where the string table starts. We just build the string
+ table in memory as we go along. We process all the relocations
+ for a single input file at once. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ for (p = o->link_order_head; p != NULL; p = p->next)
+ {
+ if (p->type == bfd_indirect_link_order
+ && p->u.indirect.section->owner->xvec == abfd->xvec)
+ {
+ sub = p->u.indirect.section->owner;
+ if (! sub->output_has_begun)
+ {
+ if (! xcoff_link_input_bfd (&finfo, sub))
+ goto error_return;
+ sub->output_has_begun = true;
+ }
+ }
+ else if (p->type == bfd_section_reloc_link_order
+ || p->type == bfd_symbol_reloc_link_order)
+ {
+ if (! xcoff_reloc_link_order (abfd, &finfo, o, p))
+ goto error_return;
+ }
+ else
+ {
+ if (! _bfd_default_link_order (abfd, info, o, p))
+ goto error_return;
+ }
+ }
+ }
+
+ /* Free up the buffers used by xcoff_link_input_bfd. */
+
+ if (finfo.internal_syms != NULL)
+ {
+ free (finfo.internal_syms);
+ finfo.internal_syms = NULL;
+ }
+ if (finfo.sym_indices != NULL)
+ {
+ free (finfo.sym_indices);
+ finfo.sym_indices = NULL;
+ }
+ if (finfo.linenos != NULL)
+ {
+ free (finfo.linenos);
+ finfo.linenos = NULL;
+ }
+ if (finfo.contents != NULL)
+ {
+ free (finfo.contents);
+ finfo.contents = NULL;
+ }
+ if (finfo.external_relocs != NULL)
+ {
+ free (finfo.external_relocs);
+ finfo.external_relocs = NULL;
+ }
+
+ /* The value of the last C_FILE symbol is supposed to be -1. Write
+ it out again. */
+ if (finfo.last_file_index != -1)
+ {
+ finfo.last_file.n_value = -1;
+ bfd_coff_swap_sym_out (abfd, (PTR) &finfo.last_file,
+ (PTR) finfo.outsyms);
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + finfo.last_file_index * symesz),
+ SEEK_SET) != 0
+ || bfd_write (finfo.outsyms, symesz, 1, abfd) != symesz)
+ goto error_return;
+ }
+
+ /* Write out all the global symbols which do not come from XCOFF
+ input files. */
+ xcoff_link_hash_traverse (xcoff_hash_table (info),
+ xcoff_write_global_symbol,
+ (PTR) &finfo);
+
+ if (finfo.outsyms != NULL)
+ {
+ free (finfo.outsyms);
+ finfo.outsyms = NULL;
+ }
+
+ /* Now that we have written out all the global symbols, we know the
+ symbol indices to use for relocs against them, and we can finally
+ write out the relocs. */
+ external_relocs = (bfd_byte *) malloc (max_output_reloc_count * relsz);
+ if (external_relocs == NULL && max_output_reloc_count != 0)
+ {
+ bfd_set_error (bfd_error_no_memory);
+ goto error_return;
+ }
+
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct internal_reloc *irel;
+ struct internal_reloc *irelend;
+ struct xcoff_link_hash_entry **rel_hash;
+ struct xcoff_toc_rel_hash *toc_rel_hash;
+ bfd_byte *erel;
+
+ if (o->reloc_count == 0)
+ continue;
+
+ irel = finfo.section_info[o->target_index].relocs;
+ irelend = irel + o->reloc_count;
+ rel_hash = finfo.section_info[o->target_index].rel_hashes;
+ for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+ {
+ if (*rel_hash != NULL)
+ {
+ if ((*rel_hash)->indx < 0)
+ {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, (*rel_hash)->root.root.string,
+ (bfd *) NULL, o, irel->r_vaddr)))
+ goto error_return;
+ (*rel_hash)->indx = 0;
+ }
+ irel->r_symndx = (*rel_hash)->indx;
+ }
+ }
+
+ for (toc_rel_hash = finfo.section_info[o->target_index].toc_rel_hashes;
+ toc_rel_hash != NULL;
+ toc_rel_hash = toc_rel_hash->next)
+ {
+ if (toc_rel_hash->h->u.toc_indx < 0)
+ {
+ if (! ((*info->callbacks->unattached_reloc)
+ (info, toc_rel_hash->h->root.root.string,
+ (bfd *) NULL, o, toc_rel_hash->rel->r_vaddr)))
+ goto error_return;
+ toc_rel_hash->h->u.toc_indx = 0;
+ }
+ toc_rel_hash->rel->r_symndx = toc_rel_hash->h->u.toc_indx;
+ }
+
+ /* XCOFF requires that the relocs be sorted by address. We tend
+ to produce them in the order in which their containing csects
+ appear in the symbol table, which is not necessarily by
+ address. So we sort them here. There may be a better way to
+ do this. */
+ qsort ((PTR) finfo.section_info[o->target_index].relocs,
+ o->reloc_count, sizeof (struct internal_reloc),
+ xcoff_sort_relocs);
+
+ irel = finfo.section_info[o->target_index].relocs;
+ irelend = irel + o->reloc_count;
+ erel = external_relocs;
+ for (; irel < irelend; irel++, rel_hash++, erel += relsz)
+ bfd_coff_swap_reloc_out (abfd, (PTR) irel, (PTR) erel);
+
+ if (bfd_seek (abfd, o->rel_filepos, SEEK_SET) != 0
+ || bfd_write ((PTR) external_relocs, relsz, o->reloc_count,
+ abfd) != relsz * o->reloc_count)
+ goto error_return;
+ }
+
+ if (external_relocs != NULL)
+ {
+ free (external_relocs);
+ external_relocs = NULL;
+ }
+
+ /* Free up the section information. */
+ if (finfo.section_info != NULL)
+ {
+ unsigned int i;
+
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
+ }
+ free (finfo.section_info);
+ finfo.section_info = NULL;
+ }
+
+ /* Write out the loader section contents. */
+ BFD_ASSERT ((bfd_byte *) finfo.ldrel
+ == (xcoff_hash_table (info)->loader_section->contents
+ + xcoff_hash_table (info)->ldhdr.l_impoff));
+ o = xcoff_hash_table (info)->loader_section;
+ if (! bfd_set_section_contents (abfd, o->output_section,
+ o->contents, o->output_offset,
+ o->_raw_size))
+ goto error_return;
+
+ /* Write out the magic sections. */
+ o = xcoff_hash_table (info)->linkage_section;
+ if (o->_raw_size > 0
+ && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
+ o->output_offset, o->_raw_size))
+ goto error_return;
+ o = xcoff_hash_table (info)->toc_section;
+ if (o->_raw_size > 0
+ && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
+ o->output_offset, o->_raw_size))
+ goto error_return;
+ o = xcoff_hash_table (info)->descriptor_section;
+ if (o->_raw_size > 0
+ && ! bfd_set_section_contents (abfd, o->output_section, o->contents,
+ o->output_offset, o->_raw_size))
+ goto error_return;
+
+ /* Write out the string table. */
+ if (bfd_seek (abfd,
+ (obj_sym_filepos (abfd)
+ + obj_raw_syment_count (abfd) * symesz),
+ SEEK_SET) != 0)
+ goto error_return;
+ bfd_h_put_32 (abfd,
+ _bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
+ (bfd_byte *) strbuf);
+ if (bfd_write (strbuf, 1, STRING_SIZE_SIZE, abfd) != STRING_SIZE_SIZE)
+ goto error_return;
+ if (! _bfd_stringtab_emit (abfd, finfo.strtab))
+ goto error_return;
+
+ _bfd_stringtab_free (finfo.strtab);
+
+ /* Write out the debugging string table. */
+ o = xcoff_hash_table (info)->debug_section;
+ if (o != NULL)
+ {
+ struct bfd_strtab_hash *debug_strtab;
+
+ debug_strtab = xcoff_hash_table (info)->debug_strtab;
+ BFD_ASSERT (o->output_section->_raw_size - o->output_offset
+ >= _bfd_stringtab_size (debug_strtab));
+ if (bfd_seek (abfd,
+ o->output_section->filepos + o->output_offset,
+ SEEK_SET) != 0)
+ goto error_return;
+ if (! _bfd_stringtab_emit (abfd, debug_strtab))
+ goto error_return;
+ }
+
+ /* Setting bfd_get_symcount to 0 will cause write_object_contents to
+ not try to write out the symbols. */
+ bfd_get_symcount (abfd) = 0;
+
+ return true;
+
+ error_return:
+ if (finfo.strtab != NULL)
+ _bfd_stringtab_free (finfo.strtab);
+ if (finfo.section_info != NULL)
+ {
+ unsigned int i;
+
+ for (i = 0; i < abfd->section_count; i++)
+ {
+ if (finfo.section_info[i].relocs != NULL)
+ free (finfo.section_info[i].relocs);
+ if (finfo.section_info[i].rel_hashes != NULL)
+ free (finfo.section_info[i].rel_hashes);
+ }
+ free (finfo.section_info);
+ }
+ if (finfo.internal_syms != NULL)
+ free (finfo.internal_syms);
+ if (finfo.sym_indices != NULL)
+ free (finfo.sym_indices);
+ if (finfo.outsyms != NULL)
+ free (finfo.outsyms);
+ if (finfo.linenos != NULL)
+ free (finfo.linenos);
+ if (finfo.contents != NULL)
+ free (finfo.contents);
+ if (finfo.external_relocs != NULL)
+ free (finfo.external_relocs);
+ if (external_relocs != NULL)
+ free (external_relocs);
+ return false;
+}
+
+/* Link an input file into the linker output file. This function
+ handles all the sections and relocations of the input file at once. */
+
+static boolean
+xcoff_link_input_bfd (finfo, input_bfd)
+ struct xcoff_final_link_info *finfo;
+ bfd *input_bfd;
+{
+ bfd *output_bfd;
+ const char *strings;
+ bfd_size_type syment_base;
+ unsigned int n_tmask;
+ unsigned int n_btshft;
+ boolean copy, hash;
+ bfd_size_type isymesz;
+ bfd_size_type osymesz;
+ bfd_size_type linesz;
+ bfd_byte *esym;
+ bfd_byte *esym_end;
+ struct xcoff_link_hash_entry **sym_hash;
+ struct internal_syment *isymp;
+ asection **csectpp;
+ unsigned long *debug_index;
+ long *indexp;
+ unsigned long output_index;
+ bfd_byte *outsym;
+ unsigned int incls;
+ asection *oline;
+ boolean keep_syms;
+ asection *o;
+
+ /* We can just skip DYNAMIC files, unless this is a static link. */
+ if ((input_bfd->flags & DYNAMIC) != 0
+ && ! finfo->info->static_link)
+ return true;
+
+ /* Move all the symbols to the output file. */
+
+ output_bfd = finfo->output_bfd;
+ strings = NULL;
+ syment_base = obj_raw_syment_count (output_bfd);
+ isymesz = bfd_coff_symesz (input_bfd);
+ osymesz = bfd_coff_symesz (output_bfd);
+ linesz = bfd_coff_linesz (input_bfd);
+ BFD_ASSERT (linesz == bfd_coff_linesz (output_bfd));
+
+ n_tmask = coff_data (input_bfd)->local_n_tmask;
+ n_btshft = coff_data (input_bfd)->local_n_btshft;
+
+ /* Define macros so that ISFCN, et. al., macros work correctly. */
+#define N_TMASK n_tmask
+#define N_BTSHFT n_btshft
+
+ copy = false;
+ if (! finfo->info->keep_memory)
+ copy = true;
+ hash = true;
+ if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+
+ if (! _bfd_coff_get_external_symbols (input_bfd))
+ return false;
+
+ esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
+ esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
+ sym_hash = obj_xcoff_sym_hashes (input_bfd);
+ csectpp = xcoff_data (input_bfd)->csects;
+ debug_index = xcoff_data (input_bfd)->debug_indices;
+ isymp = finfo->internal_syms;
+ indexp = finfo->sym_indices;
+ output_index = syment_base;
+ outsym = finfo->outsyms;
+ incls = 0;
+ oline = NULL;
+
+ while (esym < esym_end)
+ {
+ struct internal_syment isym;
+ union internal_auxent aux;
+ int smtyp = 0;
+ boolean skip;
+ boolean require;
+ int add;
+
+ bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
+
+ /* If this is a C_EXT or C_HIDEXT symbol, we need the csect
+ information. */
+ if (isymp->n_sclass == C_EXT || isymp->n_sclass == C_HIDEXT)
+ {
+ BFD_ASSERT (isymp->n_numaux > 0);
+ bfd_coff_swap_aux_in (input_bfd,
+ (PTR) (esym + isymesz * isymp->n_numaux),
+ isymp->n_type, isymp->n_sclass,
+ isymp->n_numaux - 1, isymp->n_numaux,
+ (PTR) &aux);
+ smtyp = SMTYP_SMTYP (aux.x_csect.x_smtyp);
+ }
+
+ /* Make a copy of *isymp so that the relocate_section function
+ always sees the original values. This is more reliable than
+ always recomputing the symbol value even if we are stripping
+ the symbol. */
+ isym = *isymp;
+
+ /* If this symbol is in the .loader section, swap out the
+ .loader symbol information. If this is an external symbol
+ reference to a defined symbol, though, then wait until we get
+ to the definition. */
+ if (isym.n_sclass == C_EXT
+ && *sym_hash != NULL
+ && (*sym_hash)->ldsym != NULL
+ && (smtyp != XTY_ER
+ || (*sym_hash)->root.type == bfd_link_hash_undefined))
+ {
+ struct xcoff_link_hash_entry *h;
+ struct internal_ldsym *ldsym;
+
+ h = *sym_hash;
+ ldsym = h->ldsym;
+ if (isym.n_scnum > 0)
+ {
+ ldsym->l_scnum = (*csectpp)->output_section->target_index;
+ ldsym->l_value = (isym.n_value
+ + (*csectpp)->output_section->vma
+ + (*csectpp)->output_offset
+ - (*csectpp)->vma);
+ }
+ else
+ {
+ ldsym->l_scnum = isym.n_scnum;
+ ldsym->l_value = isym.n_value;
+ }
+
+ ldsym->l_smtype = smtyp;
+ if (((h->flags & XCOFF_DEF_REGULAR) == 0
+ && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
+ || (h->flags & XCOFF_IMPORT) != 0)
+ ldsym->l_smtype |= L_IMPORT;
+ if (((h->flags & XCOFF_DEF_REGULAR) != 0
+ && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
+ || (h->flags & XCOFF_EXPORT) != 0)
+ ldsym->l_smtype |= L_EXPORT;
+ if ((h->flags & XCOFF_ENTRY) != 0)
+ ldsym->l_smtype |= L_ENTRY;
+
+ ldsym->l_smclas = aux.x_csect.x_smclas;
+
+ if (ldsym->l_ifile == (bfd_size_type) -1)
+ ldsym->l_ifile = 0;
+ else if (ldsym->l_ifile == 0)
+ {
+ if ((ldsym->l_smtype & L_IMPORT) == 0)
+ ldsym->l_ifile = 0;
+ else
+ {
+ bfd *impbfd;
+
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ impbfd = h->root.u.def.section->owner;
+ else if (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ impbfd = h->root.u.undef.abfd;
+ else
+ impbfd = NULL;
+
+ if (impbfd == NULL)
+ ldsym->l_ifile = 0;
+ else
+ {
+ BFD_ASSERT (impbfd->xvec == finfo->output_bfd->xvec);
+ ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
+ }
+ }
+ }
+
+ ldsym->l_parm = 0;
+
+ BFD_ASSERT (h->ldindx >= 0);
+ BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
+ xcoff_swap_ldsym_out (finfo->output_bfd, ldsym,
+ finfo->ldsym + h->ldindx - 3);
+ h->ldsym = NULL;
+
+ /* Fill in snentry now that we know the target_index. */
+ if ((h->flags & XCOFF_ENTRY) != 0
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak))
+ xcoff_data (output_bfd)->snentry =
+ h->root.u.def.section->output_section->target_index;
+ }
+
+ *indexp = -1;
+
+ skip = false;
+ require = false;
+ add = 1 + isym.n_numaux;
+
+ /* If we are skipping this csect, we want to skip this symbol. */
+ if (*csectpp == NULL)
+ skip = true;
+
+ /* If we garbage collected this csect, we want to skip this
+ symbol. */
+ if (! skip
+ && xcoff_hash_table (finfo->info)->gc
+ && ((*csectpp)->flags & SEC_MARK) == 0
+ && *csectpp != bfd_abs_section_ptr)
+ skip = true;
+
+ /* An XCOFF linker always skips C_STAT symbols. */
+ if (! skip
+ && isymp->n_sclass == C_STAT)
+ skip = true;
+
+ /* We skip all but the first TOC anchor. */
+ if (! skip
+ && isymp->n_sclass == C_HIDEXT
+ && aux.x_csect.x_smclas == XMC_TC0)
+ {
+ if (finfo->toc_symindx != -1)
+ skip = true;
+ else
+ {
+ bfd_vma tocval, tocend;
+
+ tocval = ((*csectpp)->output_section->vma
+ + (*csectpp)->output_offset
+ + isym.n_value
+ - (*csectpp)->vma);
+ /* We want to find out if tocval is a good value to use
+ as the TOC anchor--that is, whether we can access all
+ of the TOC using a 16 bit offset from tocval. This
+ test assumes that the TOC comes at the end of the
+ output section, as it does in the default linker
+ script. If the TOC anchor is too far into the .toc
+ section, the relocation routine will report
+ overflows. */
+ tocend = ((*csectpp)->output_section->vma
+ + (*csectpp)->output_section->_raw_size);
+ if (tocval + 0x8000 < tocend)
+ {
+ bfd_vma tocadd;
+
+ tocadd = tocend - (tocval + 0x8000);
+ tocval += tocadd;
+ isym.n_value += tocadd;
+ }
+
+ finfo->toc_symindx = output_index;
+ xcoff_data (finfo->output_bfd)->toc = tocval;
+ xcoff_data (finfo->output_bfd)->sntoc =
+ (*csectpp)->output_section->target_index;
+ require = true;
+ }
+ }
+
+ /* If we are stripping all symbols, we want to skip this one. */
+ if (! skip
+ && finfo->info->strip == strip_all)
+ skip = true;
+
+ /* We can skip resolved external references. */
+ if (! skip
+ && isym.n_sclass == C_EXT
+ && smtyp == XTY_ER
+ && (*sym_hash)->root.type != bfd_link_hash_undefined)
+ skip = true;
+
+ /* We can skip common symbols if they got defined somewhere
+ else. */
+ if (! skip
+ && isym.n_sclass == C_EXT
+ && smtyp == XTY_CM
+ && ((*sym_hash)->root.type != bfd_link_hash_common
+ || (*sym_hash)->root.u.c.p->section != *csectpp)
+ && ((*sym_hash)->root.type != bfd_link_hash_defined
+ || (*sym_hash)->root.u.def.section != *csectpp))
+ skip = true;
+
+ /* Skip local symbols if we are discarding them. */
+ if (! skip
+ && finfo->info->discard == discard_all
+ && isym.n_sclass != C_EXT
+ && (isym.n_sclass != C_HIDEXT
+ || smtyp != XTY_SD))
+ skip = true;
+
+ /* If we stripping debugging symbols, and this is a debugging
+ symbol, then skip it. */
+ if (! skip
+ && finfo->info->strip == strip_debugger
+ && isym.n_scnum == N_DEBUG)
+ skip = true;
+
+ /* If some symbols are stripped based on the name, work out the
+ name and decide whether to skip this symbol. We don't handle
+ this correctly for symbols whose names are in the .debug
+ section; to get it right we would need a new bfd_strtab_hash
+ function to return the string given the index. */
+ if (! skip
+ && (finfo->info->strip == strip_some
+ || finfo->info->discard == discard_l)
+ && (debug_index == NULL || *debug_index == (unsigned long) -1))
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ name = _bfd_coff_internal_syment_name (input_bfd, &isym, buf);
+ if (name == NULL)
+ return false;
+
+ if ((finfo->info->strip == strip_some
+ && (bfd_hash_lookup (finfo->info->keep_hash, name, false,
+ false) == NULL))
+ || (finfo->info->discard == discard_l
+ && (isym.n_sclass != C_EXT
+ && (isym.n_sclass != C_HIDEXT
+ || smtyp != XTY_SD))
+ && strncmp (name, finfo->info->lprefix,
+ finfo->info->lprefix_len) == 0))
+ skip = true;
+ }
+
+ /* We can not skip the first TOC anchor. */
+ if (skip
+ && require
+ && finfo->info->strip != strip_all)
+ skip = false;
+
+ /* We now know whether we are to skip this symbol or not. */
+ if (! skip)
+ {
+ /* Adjust the symbol in order to output it. */
+
+ if (isym._n._n_n._n_zeroes == 0
+ && isym._n._n_n._n_offset != 0)
+ {
+ /* This symbol has a long name. Enter it in the string
+ table we are building. If *debug_index != -1, the
+ name has already been entered in the .debug section. */
+ if (debug_index != NULL && *debug_index != (unsigned long) -1)
+ isym._n._n_n._n_offset = *debug_index;
+ else
+ {
+ const char *name;
+ bfd_size_type indx;
+
+ name = _bfd_coff_internal_syment_name (input_bfd, &isym,
+ (char *) NULL);
+ if (name == NULL)
+ return false;
+ indx = _bfd_stringtab_add (finfo->strtab, name, hash, copy);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ }
+ }
+
+ if (isym.n_sclass != C_BSTAT
+ && isym.n_sclass != C_ESTAT
+ && isym.n_sclass != C_DECL
+ && isym.n_scnum > 0)
+ {
+ isym.n_scnum = (*csectpp)->output_section->target_index;
+ isym.n_value += ((*csectpp)->output_section->vma
+ + (*csectpp)->output_offset
+ - (*csectpp)->vma);
+ }
+
+ /* The value of a C_FILE symbol is the symbol index of the
+ next C_FILE symbol. The value of the last C_FILE symbol
+ is -1. We try to get this right, below, just before we
+ write the symbols out, but in the general case we may
+ have to write the symbol out twice. */
+ if (isym.n_sclass == C_FILE)
+ {
+ if (finfo->last_file_index != -1
+ && finfo->last_file.n_value != (long) output_index)
+ {
+ /* We must correct the value of the last C_FILE entry. */
+ finfo->last_file.n_value = output_index;
+ if ((bfd_size_type) finfo->last_file_index >= syment_base)
+ {
+ /* The last C_FILE symbol is in this input file. */
+ bfd_coff_swap_sym_out (output_bfd,
+ (PTR) &finfo->last_file,
+ (PTR) (finfo->outsyms
+ + ((finfo->last_file_index
+ - syment_base)
+ * osymesz)));
+ }
+ else
+ {
+ /* We have already written out the last C_FILE
+ symbol. We need to write it out again. We
+ borrow *outsym temporarily. */
+ bfd_coff_swap_sym_out (output_bfd,
+ (PTR) &finfo->last_file,
+ (PTR) outsym);
+ if (bfd_seek (output_bfd,
+ (obj_sym_filepos (output_bfd)
+ + finfo->last_file_index * osymesz),
+ SEEK_SET) != 0
+ || (bfd_write (outsym, osymesz, 1, output_bfd)
+ != osymesz))
+ return false;
+ }
+ }
+
+ finfo->last_file_index = output_index;
+ finfo->last_file = isym;
+ }
+
+ /* The value of a C_BINCL or C_EINCL symbol is a file offset
+ into the line numbers. We update the symbol values when
+ we handle the line numbers. */
+ if (isym.n_sclass == C_BINCL
+ || isym.n_sclass == C_EINCL)
+ {
+ isym.n_value = finfo->line_filepos;
+ ++incls;
+ }
+
+ /* Output the symbol. */
+
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) outsym);
+
+ *indexp = output_index;
+
+ if (isym.n_sclass == C_EXT)
+ {
+ long indx;
+ struct xcoff_link_hash_entry *h;
+
+ indx = ((esym - (bfd_byte *) obj_coff_external_syms (input_bfd))
+ / isymesz);
+ h = obj_xcoff_sym_hashes (input_bfd)[indx];
+ BFD_ASSERT (h != NULL);
+ h->indx = output_index;
+ }
+
+ /* If this is a symbol in the TOC which we may have merged
+ (class XMC_TC), remember the symbol index of the TOC
+ symbol. */
+ if (isym.n_sclass == C_HIDEXT
+ && aux.x_csect.x_smclas == XMC_TC
+ && *sym_hash != NULL)
+ {
+ BFD_ASSERT (((*sym_hash)->flags & XCOFF_SET_TOC) == 0);
+ BFD_ASSERT ((*sym_hash)->toc_section != NULL);
+ (*sym_hash)->u.toc_indx = output_index;
+ }
+
+ output_index += add;
+ outsym += add * osymesz;
+ }
+
+ esym += add * isymesz;
+ isymp += add;
+ csectpp += add;
+ sym_hash += add;
+ if (debug_index != NULL)
+ debug_index += add;
+ ++indexp;
+ for (--add; add > 0; --add)
+ *indexp++ = -1;
+ }
+
+ /* Fix up the aux entries and the C_BSTAT symbols. This must be
+ done in a separate pass, because we don't know the correct symbol
+ indices until we have already decided which symbols we are going
+ to keep. */
+
+ esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
+ esym_end = esym + obj_raw_syment_count (input_bfd) * isymesz;
+ isymp = finfo->internal_syms;
+ indexp = finfo->sym_indices;
+ csectpp = xcoff_data (input_bfd)->csects;
+ outsym = finfo->outsyms;
+ while (esym < esym_end)
+ {
+ int add;
+
+ add = 1 + isymp->n_numaux;
+
+ if (*indexp < 0)
+ esym += add * isymesz;
+ else
+ {
+ int i;
+
+ if (isymp->n_sclass == C_BSTAT)
+ {
+ struct internal_syment isym;
+ unsigned long indx;
+
+ /* The value of a C_BSTAT symbol is the symbol table
+ index of the containing csect. */
+ bfd_coff_swap_sym_in (output_bfd, (PTR) outsym, (PTR) &isym);
+ indx = isym.n_value;
+ if (indx < obj_raw_syment_count (input_bfd))
+ {
+ long symindx;
+
+ symindx = finfo->sym_indices[indx];
+ if (symindx < 0)
+ isym.n_value = 0;
+ else
+ isym.n_value = symindx;
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &isym,
+ (PTR) outsym);
+ }
+ }
+
+ esym += isymesz;
+ outsym += osymesz;
+
+ for (i = 0; i < isymp->n_numaux && esym < esym_end; i++)
+ {
+ union internal_auxent aux;
+
+ bfd_coff_swap_aux_in (input_bfd, (PTR) esym, isymp->n_type,
+ isymp->n_sclass, i, isymp->n_numaux,
+ (PTR) &aux);
+
+ if (isymp->n_sclass == C_FILE)
+ {
+ /* This is the file name (or some comment put in by
+ the compiler). If it is long, we must put it in
+ the string table. */
+ if (aux.x_file.x_n.x_zeroes == 0
+ && aux.x_file.x_n.x_offset != 0)
+ {
+ const char *filename;
+ bfd_size_type indx;
+
+ BFD_ASSERT (aux.x_file.x_n.x_offset
+ >= STRING_SIZE_SIZE);
+ if (strings == NULL)
+ {
+ strings = _bfd_coff_read_string_table (input_bfd);
+ if (strings == NULL)
+ return false;
+ }
+ filename = strings + aux.x_file.x_n.x_offset;
+ indx = _bfd_stringtab_add (finfo->strtab, filename,
+ hash, copy);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ aux.x_file.x_n.x_offset = STRING_SIZE_SIZE + indx;
+ }
+ }
+ else if ((isymp->n_sclass == C_EXT
+ || isymp->n_sclass == C_HIDEXT)
+ && i + 1 == isymp->n_numaux)
+ {
+ /* We don't support type checking. I don't know if
+ anybody does. */
+ aux.x_csect.x_parmhash = 0;
+ /* I don't think anybody uses these fields, but we'd
+ better clobber them just in case. */
+ aux.x_csect.x_stab = 0;
+ aux.x_csect.x_snstab = 0;
+ if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_LD)
+ {
+ unsigned long indx;
+
+ indx = aux.x_csect.x_scnlen.l;
+ if (indx < obj_raw_syment_count (input_bfd))
+ {
+ long symindx;
+
+ symindx = finfo->sym_indices[indx];
+ if (symindx < 0)
+ aux.x_sym.x_tagndx.l = 0;
+ else
+ aux.x_sym.x_tagndx.l = symindx;
+ }
+ }
+ }
+ else if (isymp->n_sclass != C_STAT || isymp->n_type != T_NULL)
+ {
+ unsigned long indx;
+
+ if (ISFCN (isymp->n_type)
+ || ISTAG (isymp->n_sclass)
+ || isymp->n_sclass == C_BLOCK)
+ {
+ indx = aux.x_sym.x_fcnary.x_fcn.x_endndx.l;
+ if (indx > 0
+ && indx < obj_raw_syment_count (input_bfd))
+ {
+ /* We look forward through the symbol for
+ the index of the next symbol we are going
+ to include. I don't know if this is
+ entirely right. */
+ while (finfo->sym_indices[indx] < 0
+ && indx < obj_raw_syment_count (input_bfd))
+ ++indx;
+ if (indx >= obj_raw_syment_count (input_bfd))
+ indx = output_index;
+ else
+ indx = finfo->sym_indices[indx];
+ aux.x_sym.x_fcnary.x_fcn.x_endndx.l = indx;
+ }
+ }
+
+ indx = aux.x_sym.x_tagndx.l;
+ if (indx > 0 && indx < obj_raw_syment_count (input_bfd))
+ {
+ long symindx;
+
+ symindx = finfo->sym_indices[indx];
+ if (symindx < 0)
+ aux.x_sym.x_tagndx.l = 0;
+ else
+ aux.x_sym.x_tagndx.l = symindx;
+ }
+ }
+
+ /* Copy over the line numbers, unless we are stripping
+ them. We do this on a symbol by symbol basis in
+ order to more easily handle garbage collection. */
+ if ((isymp->n_sclass == C_EXT
+ || isymp->n_sclass == C_HIDEXT)
+ && i == 0
+ && isymp->n_numaux > 1
+ && ISFCN (isymp->n_type)
+ && aux.x_sym.x_fcnary.x_fcn.x_lnnoptr != 0)
+ {
+ if (finfo->info->strip != strip_none
+ && finfo->info->strip != strip_some)
+ aux.x_sym.x_fcnary.x_fcn.x_lnnoptr = 0;
+ else
+ {
+ asection *enclosing;
+ unsigned int enc_count;
+ bfd_size_type linoff;
+ struct internal_lineno lin;
+
+ o = *csectpp;
+ enclosing = xcoff_section_data (abfd, o)->enclosing;
+ enc_count = xcoff_section_data (abfd, o)->lineno_count;
+ if (oline != enclosing)
+ {
+ if (bfd_seek (input_bfd,
+ enclosing->line_filepos,
+ SEEK_SET) != 0
+ || (bfd_read (finfo->linenos, linesz,
+ enc_count, input_bfd)
+ != linesz * enc_count))
+ return false;
+ oline = enclosing;
+ }
+
+ linoff = (aux.x_sym.x_fcnary.x_fcn.x_lnnoptr
+ - enclosing->line_filepos);
+
+ bfd_coff_swap_lineno_in (input_bfd,
+ (PTR) (finfo->linenos + linoff),
+ (PTR) &lin);
+ if (lin.l_lnno != 0
+ || ((bfd_size_type) lin.l_addr.l_symndx
+ != ((esym
+ - isymesz
+ - ((bfd_byte *)
+ obj_coff_external_syms (input_bfd)))
+ / isymesz)))
+ aux.x_sym.x_fcnary.x_fcn.x_lnnoptr = 0;
+ else
+ {
+ bfd_byte *linpend, *linp;
+ bfd_vma offset;
+ bfd_size_type count;
+
+ lin.l_addr.l_symndx = *indexp;
+ bfd_coff_swap_lineno_out (output_bfd, (PTR) &lin,
+ (PTR) (finfo->linenos
+ + linoff));
+
+ linpend = (finfo->linenos
+ + enc_count * linesz);
+ offset = (o->output_section->vma
+ + o->output_offset
+ - o->vma);
+ for (linp = finfo->linenos + linoff + linesz;
+ linp < linpend;
+ linp += linesz)
+ {
+ bfd_coff_swap_lineno_in (input_bfd, (PTR) linp,
+ (PTR) &lin);
+ if (lin.l_lnno == 0)
+ break;
+ lin.l_addr.l_paddr += offset;
+ bfd_coff_swap_lineno_out (output_bfd,
+ (PTR) &lin,
+ (PTR) linp);
+ }
+
+ count = (linp - (finfo->linenos + linoff)) / linesz;
+
+ aux.x_sym.x_fcnary.x_fcn.x_lnnoptr =
+ (o->output_section->line_filepos
+ + o->output_section->lineno_count * linesz);
+
+ if (bfd_seek (output_bfd,
+ aux.x_sym.x_fcnary.x_fcn.x_lnnoptr,
+ SEEK_SET) != 0
+ || (bfd_write (finfo->linenos + linoff,
+ linesz, count, output_bfd)
+ != linesz * count))
+ return false;
+
+ o->output_section->lineno_count += count;
+
+ if (incls > 0)
+ {
+ struct internal_syment *iisp, *iispend;
+ long *iindp;
+ bfd_byte *oos;
+
+ /* Update any C_BINCL or C_EINCL symbols
+ that refer to a line number in the
+ range we just output. */
+ iisp = finfo->internal_syms;
+ iispend = (iisp
+ + obj_raw_syment_count (input_bfd));
+ iindp = finfo->sym_indices;
+ oos = finfo->outsyms;
+ while (iisp < iispend)
+ {
+ if ((iisp->n_sclass == C_BINCL
+ || iisp->n_sclass == C_EINCL)
+ && ((bfd_size_type) iisp->n_value
+ >= enclosing->line_filepos + linoff)
+ && ((bfd_size_type) iisp->n_value
+ < (enclosing->line_filepos
+ + enc_count * linesz)))
+ {
+ struct internal_syment iis;
+
+ bfd_coff_swap_sym_in (output_bfd,
+ (PTR) oos,
+ (PTR) &iis);
+ iis.n_value =
+ (iisp->n_value
+ - enclosing->line_filepos
+ - linoff
+ + aux.x_sym.x_fcnary.x_fcn.x_lnnoptr);
+ bfd_coff_swap_sym_out (output_bfd,
+ (PTR) &iis,
+ (PTR) oos);
+ --incls;
+ }
+
+ iisp += iisp->n_numaux + 1;
+ iindp += iisp->n_numaux + 1;
+ oos += (iisp->n_numaux + 1) * osymesz;
+ }
+ }
+ }
+ }
+ }
+
+ bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, isymp->n_type,
+ isymp->n_sclass, i, isymp->n_numaux,
+ (PTR) outsym);
+ outsym += osymesz;
+ esym += isymesz;
+ }
+ }
+
+ indexp += add;
+ isymp += add;
+ csectpp += add;
+ }
+
+ /* If we swapped out a C_FILE symbol, guess that the next C_FILE
+ symbol will be the first symbol in the next input file. In the
+ normal case, this will save us from writing out the C_FILE symbol
+ again. */
+ if (finfo->last_file_index != -1
+ && (bfd_size_type) finfo->last_file_index >= syment_base)
+ {
+ finfo->last_file.n_value = output_index;
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &finfo->last_file,
+ (PTR) (finfo->outsyms
+ + ((finfo->last_file_index - syment_base)
+ * osymesz)));
+ }
+
+ /* Write the modified symbols to the output file. */
+ if (outsym > finfo->outsyms)
+ {
+ if (bfd_seek (output_bfd,
+ obj_sym_filepos (output_bfd) + syment_base * osymesz,
+ SEEK_SET) != 0
+ || (bfd_write (finfo->outsyms, outsym - finfo->outsyms, 1,
+ output_bfd)
+ != (bfd_size_type) (outsym - finfo->outsyms)))
+ return false;
+
+ BFD_ASSERT ((obj_raw_syment_count (output_bfd)
+ + (outsym - finfo->outsyms) / osymesz)
+ == output_index);
+
+ obj_raw_syment_count (output_bfd) = output_index;
+ }
+
+ /* Don't let the linker relocation routines discard the symbols. */
+ keep_syms = obj_coff_keep_syms (input_bfd);
+ obj_coff_keep_syms (input_bfd) = true;
+
+ /* Relocate the contents of each section. */
+ for (o = input_bfd->sections; o != NULL; o = o->next)
+ {
+ bfd_byte *contents;
+
+ if ((o->flags & SEC_HAS_CONTENTS) == 0
+ || o->_raw_size == 0
+ || (o->flags & SEC_IN_MEMORY) != 0)
+ continue;
+
+ /* We have set filepos correctly for the sections we created to
+ represent csects, so bfd_get_section_contents should work. */
+ if (coff_section_data (input_bfd, o) != NULL
+ && coff_section_data (input_bfd, o)->contents != NULL)
+ contents = coff_section_data (input_bfd, o)->contents;
+ else
+ {
+ if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
+ (file_ptr) 0, o->_raw_size))
+ return false;
+ contents = finfo->contents;
+ }
+
+ if ((o->flags & SEC_RELOC) != 0)
+ {
+ int target_index;
+ struct internal_reloc *internal_relocs;
+ struct internal_reloc *irel;
+ bfd_vma offset;
+ struct internal_reloc *irelend;
+ struct xcoff_link_hash_entry **rel_hash;
+ long r_symndx;
+
+ /* Read in the relocs. */
+ target_index = o->output_section->target_index;
+ internal_relocs = (xcoff_read_internal_relocs
+ (input_bfd, o, false, finfo->external_relocs,
+ true,
+ (finfo->section_info[target_index].relocs
+ + o->output_section->reloc_count)));
+ if (internal_relocs == NULL)
+ return false;
+
+ /* Call processor specific code to relocate the section
+ contents. */
+ if (! bfd_coff_relocate_section (output_bfd, finfo->info,
+ input_bfd, o,
+ contents,
+ internal_relocs,
+ finfo->internal_syms,
+ xcoff_data (input_bfd)->csects))
+ return false;
+
+ offset = o->output_section->vma + o->output_offset - o->vma;
+ irel = internal_relocs;
+ irelend = irel + o->reloc_count;
+ rel_hash = (finfo->section_info[target_index].rel_hashes
+ + o->output_section->reloc_count);
+ for (; irel < irelend; irel++, rel_hash++)
+ {
+ struct xcoff_link_hash_entry *h = NULL;
+ struct internal_ldrel ldrel;
+
+ *rel_hash = NULL;
+
+ /* Adjust the reloc address and symbol index. */
+
+ irel->r_vaddr += offset;
+
+ r_symndx = irel->r_symndx;
+
+ if (r_symndx != -1)
+ {
+ h = obj_xcoff_sym_hashes (input_bfd)[r_symndx];
+ if (h != NULL
+ && (irel->r_type == R_TOC
+ || irel->r_type == R_GL
+ || irel->r_type == R_TCL
+ || irel->r_type == R_TRL
+ || irel->r_type == R_TRLA))
+ {
+ /* This is a TOC relative reloc with a symbol
+ attached. The symbol should be the one which
+ this reloc is for. We want to make this
+ reloc against the TOC address of the symbol,
+ not the symbol itself. */
+ BFD_ASSERT (h->toc_section != NULL);
+ BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+ if (h->u.toc_indx != -1)
+ irel->r_symndx = h->u.toc_indx;
+ else
+ {
+ struct xcoff_toc_rel_hash *n;
+ struct xcoff_link_section_info *si;
+
+ n = ((struct xcoff_toc_rel_hash *)
+ bfd_alloc (finfo->output_bfd,
+ sizeof (struct xcoff_toc_rel_hash)));
+ if (n == NULL)
+ return false;
+ si = finfo->section_info + target_index;
+ n->next = si->toc_rel_hashes;
+ n->h = h;
+ n->rel = irel;
+ si->toc_rel_hashes = n;
+ }
+ }
+ else if (h != NULL)
+ {
+ /* This is a global symbol. */
+ if (h->indx >= 0)
+ irel->r_symndx = h->indx;
+ else
+ {
+ /* This symbol is being written at the end
+ of the file, and we do not yet know the
+ symbol index. We save the pointer to the
+ hash table entry in the rel_hash list.
+ We set the indx field to -2 to indicate
+ that this symbol must not be stripped. */
+ *rel_hash = h;
+ h->indx = -2;
+ }
+ }
+ else
+ {
+ long indx;
+
+ indx = finfo->sym_indices[r_symndx];
+
+ if (indx == -1)
+ {
+ struct internal_syment *is;
+
+ /* Relocations against a TC0 TOC anchor are
+ automatically transformed to be against
+ the TOC anchor in the output file. */
+ is = finfo->internal_syms + r_symndx;
+ if (is->n_sclass == C_HIDEXT
+ && is->n_numaux > 0)
+ {
+ PTR auxptr;
+ union internal_auxent aux;
+
+ auxptr = ((PTR)
+ (((bfd_byte *)
+ obj_coff_external_syms (input_bfd))
+ + ((r_symndx + is->n_numaux)
+ * isymesz)));
+ bfd_coff_swap_aux_in (input_bfd, auxptr,
+ is->n_type, is->n_sclass,
+ is->n_numaux - 1,
+ is->n_numaux,
+ (PTR) &aux);
+ if (SMTYP_SMTYP (aux.x_csect.x_smtyp) == XTY_SD
+ && aux.x_csect.x_smclas == XMC_TC0)
+ indx = finfo->toc_symindx;
+ }
+ }
+
+ if (indx != -1)
+ irel->r_symndx = indx;
+ else
+ {
+ struct internal_syment *is;
+ const char *name;
+ char buf[SYMNMLEN + 1];
+
+ /* This reloc is against a symbol we are
+ stripping. It would be possible to handle
+ this case, but I don't think it's worth it. */
+ is = finfo->internal_syms + r_symndx;
+
+ name = (_bfd_coff_internal_syment_name
+ (input_bfd, is, buf));
+ if (name == NULL)
+ return false;
+
+ if (! ((*finfo->info->callbacks->unattached_reloc)
+ (finfo->info, name, input_bfd, o,
+ irel->r_vaddr)))
+ return false;
+ }
+ }
+ }
+
+ switch (irel->r_type)
+ {
+ default:
+ if (h == NULL
+ || h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_common)
+ break;
+ /* Fall through. */
+ case R_POS:
+ case R_NEG:
+ case R_RL:
+ case R_RLA:
+ /* This reloc needs to be copied into the .loader
+ section. */
+ ldrel.l_vaddr = irel->r_vaddr;
+ if (r_symndx == -1)
+ ldrel.l_symndx = -1;
+ else if (h == NULL
+ || (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak
+ || h->root.type == bfd_link_hash_common))
+ {
+ asection *sec;
+
+ if (h == NULL)
+ sec = xcoff_data (input_bfd)->csects[r_symndx];
+ else if (h->root.type == bfd_link_hash_common)
+ sec = h->root.u.c.p->section;
+ else
+ sec = h->root.u.def.section;
+ sec = sec->output_section;
+
+ if (strcmp (sec->name, ".text") == 0)
+ ldrel.l_symndx = 0;
+ else if (strcmp (sec->name, ".data") == 0)
+ ldrel.l_symndx = 1;
+ else if (strcmp (sec->name, ".bss") == 0)
+ ldrel.l_symndx = 2;
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: loader reloc in unrecognized section `%s'",
+ bfd_get_filename (input_bfd),
+ sec->name);
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+ }
+ else
+ {
+ if (h->ldindx < 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: `%s' in loader reloc but not loader sym",
+ bfd_get_filename (input_bfd),
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ ldrel.l_symndx = h->ldindx;
+ }
+ ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
+ ldrel.l_rsecnm = o->output_section->target_index;
+ if (xcoff_hash_table (finfo->info)->textro
+ && strcmp (o->output_section->name, ".text") == 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: loader reloc in read-only section %s",
+ bfd_get_filename (input_bfd),
+ bfd_get_section_name (finfo->output_bfd,
+ o->output_section));
+ bfd_set_error (bfd_error_invalid_operation);
+ return false;
+ }
+ xcoff_swap_ldrel_out (output_bfd, &ldrel,
+ finfo->ldrel);
+ BFD_ASSERT (sizeof (struct external_ldrel) == LDRELSZ);
+ ++finfo->ldrel;
+ break;
+
+ case R_TOC:
+ case R_GL:
+ case R_TCL:
+ case R_TRL:
+ case R_TRLA:
+ /* We should never need a .loader reloc for a TOC
+ relative reloc. */
+ break;
+ }
+ }
+
+ o->output_section->reloc_count += o->reloc_count;
+ }
+
+ /* Write out the modified section contents. */
+ if (! bfd_set_section_contents (output_bfd, o->output_section,
+ contents, o->output_offset,
+ (o->_cooked_size != 0
+ ? o->_cooked_size
+ : o->_raw_size)))
+ return false;
+ }
+
+ obj_coff_keep_syms (input_bfd) = keep_syms;
+
+ if (! finfo->info->keep_memory)
+ {
+ if (! _bfd_coff_free_symbols (input_bfd))
+ return false;
+ }
+
+ return true;
+}
+
+#undef N_TMASK
+#undef N_BTSHFT
+
+/* Write out a non-XCOFF global symbol. */
+
+static boolean
+xcoff_write_global_symbol (h, p)
+ struct xcoff_link_hash_entry *h;
+ PTR p;
+{
+ struct xcoff_final_link_info *finfo = (struct xcoff_final_link_info *) p;
+ bfd *output_bfd;
+ bfd_byte *outsym;
+ struct internal_syment isym;
+ union internal_auxent aux;
+
+ output_bfd = finfo->output_bfd;
+
+ /* If this symbol was garbage collected, just skip it. */
+ if (xcoff_hash_table (finfo->info)->gc
+ && (h->flags & XCOFF_MARK) == 0)
+ return true;
+
+ /* If we need a .loader section entry, write it out. */
+ if (h->ldsym != NULL)
+ {
+ struct internal_ldsym *ldsym;
+ bfd *impbfd;
+
+ ldsym = h->ldsym;
+
+ if (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ {
+ ldsym->l_value = 0;
+ ldsym->l_scnum = N_UNDEF;
+ ldsym->l_smtype = XTY_ER;
+ impbfd = h->root.u.undef.abfd;
+ }
+ else if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ ldsym->l_value = (sec->output_section->vma
+ + sec->output_offset
+ + h->root.u.def.value);
+ ldsym->l_scnum = sec->output_section->target_index;
+ ldsym->l_smtype = XTY_SD;
+ impbfd = sec->owner;
+ }
+ else
+ abort ();
+
+ if (((h->flags & XCOFF_DEF_REGULAR) == 0
+ && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
+ || (h->flags & XCOFF_IMPORT) != 0)
+ ldsym->l_smtype |= L_IMPORT;
+ if (((h->flags & XCOFF_DEF_REGULAR) != 0
+ && (h->flags & XCOFF_DEF_DYNAMIC) != 0)
+ || (h->flags & XCOFF_EXPORT) != 0)
+ ldsym->l_smtype |= L_EXPORT;
+ if ((h->flags & XCOFF_ENTRY) != 0)
+ ldsym->l_smtype |= L_ENTRY;
+
+ ldsym->l_smclas = h->smclas;
+
+ if (ldsym->l_ifile == (bfd_size_type) -1)
+ ldsym->l_ifile = 0;
+ else if (ldsym->l_ifile == 0)
+ {
+ if ((ldsym->l_smtype & L_IMPORT) == 0)
+ ldsym->l_ifile = 0;
+ else if (impbfd == NULL)
+ ldsym->l_ifile = 0;
+ else
+ {
+ BFD_ASSERT (impbfd->xvec == output_bfd->xvec);
+ ldsym->l_ifile = xcoff_data (impbfd)->import_file_id;
+ }
+ }
+
+ ldsym->l_parm = 0;
+
+ BFD_ASSERT (h->ldindx >= 0);
+ BFD_ASSERT (LDSYMSZ == sizeof (struct external_ldsym));
+ xcoff_swap_ldsym_out (output_bfd, ldsym, finfo->ldsym + h->ldindx - 3);
+ h->ldsym = NULL;
+ }
+
+ /* If this symbol needs global linkage code, write it out. */
+ if (h->root.type == bfd_link_hash_defined
+ && (h->root.u.def.section
+ == xcoff_hash_table (finfo->info)->linkage_section))
+ {
+ bfd_byte *p;
+ bfd_vma tocoff;
+ unsigned int i;
+
+ p = h->root.u.def.section->contents + h->root.u.def.value;
+
+ /* The first instruction in the global linkage code loads a
+ specific TOC element. */
+ tocoff = (h->descriptor->toc_section->output_section->vma
+ + h->descriptor->toc_section->output_offset
+ - xcoff_data (output_bfd)->toc);
+ if ((h->descriptor->flags & XCOFF_SET_TOC) != 0)
+ tocoff += h->descriptor->u.toc_offset;
+ bfd_put_32 (output_bfd, XCOFF_GLINK_FIRST | (tocoff & 0xffff), p);
+ for (i = 0, p += 4;
+ i < sizeof xcoff_glink_code / sizeof xcoff_glink_code[0];
+ i++, p += 4)
+ bfd_put_32 (output_bfd, xcoff_glink_code[i], p);
+ }
+
+ /* If we created a TOC entry for this symbol, write out the required
+ relocs. */
+ if ((h->flags & XCOFF_SET_TOC) != 0)
+ {
+ asection *tocsec;
+ asection *osec;
+ int oindx;
+ struct internal_reloc *irel;
+ struct internal_ldrel ldrel;
+
+ tocsec = h->toc_section;
+ osec = tocsec->output_section;
+ oindx = osec->target_index;
+ irel = finfo->section_info[oindx].relocs + osec->reloc_count;
+ irel->r_vaddr = (osec->vma
+ + tocsec->output_offset
+ + h->u.toc_offset);
+ if (h->indx >= 0)
+ irel->r_symndx = h->indx;
+ else
+ {
+ h->indx = -2;
+ irel->r_symndx = obj_raw_syment_count (output_bfd);
+ }
+ irel->r_type = R_POS;
+ irel->r_size = 31;
+ finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
+ ++osec->reloc_count;
+
+ BFD_ASSERT (h->ldindx >= 0);
+ ldrel.l_vaddr = irel->r_vaddr;
+ ldrel.l_symndx = h->ldindx;
+ ldrel.l_rtype = (31 << 8) | R_POS;
+ ldrel.l_rsecnm = oindx;
+ xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ ++finfo->ldrel;
+ }
+
+ /* If this symbol is a specially defined function descriptor, write
+ it out. The first word is the address of the function code
+ itself, the second word is the address of the TOC, and the third
+ word is zero. */
+ if ((h->flags & XCOFF_DESCRIPTOR) != 0
+ && h->root.type == bfd_link_hash_defined
+ && (h->root.u.def.section
+ == xcoff_hash_table (finfo->info)->descriptor_section))
+ {
+ asection *sec;
+ asection *osec;
+ int oindx;
+ bfd_byte *p;
+ struct xcoff_link_hash_entry *hentry;
+ asection *esec;
+ struct internal_reloc *irel;
+ struct internal_ldrel ldrel;
+ asection *tsec;
+
+ sec = h->root.u.def.section;
+ osec = sec->output_section;
+ oindx = osec->target_index;
+ p = sec->contents + h->root.u.def.value;
+
+ hentry = h->descriptor;
+ BFD_ASSERT (hentry != NULL
+ && (hentry->root.type == bfd_link_hash_defined
+ || hentry->root.type == bfd_link_hash_defweak));
+ esec = hentry->root.u.def.section;
+ bfd_put_32 (output_bfd,
+ (esec->output_section->vma
+ + esec->output_offset
+ + hentry->root.u.def.value),
+ p);
+
+ irel = finfo->section_info[oindx].relocs + osec->reloc_count;
+ irel->r_vaddr = (osec->vma
+ + sec->output_offset
+ + h->root.u.def.value);
+ irel->r_symndx = esec->output_section->target_index;
+ irel->r_type = R_POS;
+ irel->r_size = 31;
+ finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
+ ++osec->reloc_count;
+
+ ldrel.l_vaddr = irel->r_vaddr;
+ if (strcmp (esec->output_section->name, ".text") == 0)
+ ldrel.l_symndx = 0;
+ else if (strcmp (esec->output_section->name, ".data") == 0)
+ ldrel.l_symndx = 1;
+ else if (strcmp (esec->output_section->name, ".bss") == 0)
+ ldrel.l_symndx = 2;
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: loader reloc in unrecognized section `%s'",
+ bfd_get_filename (output_bfd),
+ esec->output_section->name);
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+ ldrel.l_rtype = (31 << 8) | R_POS;
+ ldrel.l_rsecnm = oindx;
+ xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ ++finfo->ldrel;
+
+ bfd_put_32 (output_bfd, xcoff_data (output_bfd)->toc, p + 4);
+
+ tsec = coff_section_from_bfd_index (output_bfd,
+ xcoff_data (output_bfd)->sntoc);
+
+ ++irel;
+ irel->r_vaddr = (osec->vma
+ + sec->output_offset
+ + h->root.u.def.value
+ + 4);
+ irel->r_symndx = tsec->output_section->target_index;
+ irel->r_type = R_POS;
+ irel->r_size = 31;
+ finfo->section_info[oindx].rel_hashes[osec->reloc_count] = NULL;
+ ++osec->reloc_count;
+
+ ldrel.l_vaddr = irel->r_vaddr;
+ if (strcmp (tsec->output_section->name, ".text") == 0)
+ ldrel.l_symndx = 0;
+ else if (strcmp (tsec->output_section->name, ".data") == 0)
+ ldrel.l_symndx = 1;
+ else if (strcmp (tsec->output_section->name, ".bss") == 0)
+ ldrel.l_symndx = 2;
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: loader reloc in unrecognized section `%s'",
+ bfd_get_filename (output_bfd),
+ tsec->output_section->name);
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+ ldrel.l_rtype = (31 << 8) | R_POS;
+ ldrel.l_rsecnm = oindx;
+ xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ ++finfo->ldrel;
+ }
+
+ if (h->indx >= 0)
+ return true;
+
+ if (h->indx != -2
+ && (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;
+
+ if (h->indx != -2
+ && (h->flags & (XCOFF_REF_REGULAR | XCOFF_DEF_REGULAR)) == 0)
+ return true;
+
+ outsym = finfo->outsyms;
+
+ memset (&aux, 0, sizeof aux);
+
+ h->indx = obj_raw_syment_count (output_bfd);
+
+ if (strlen (h->root.root.string) <= SYMNMLEN)
+ strncpy (isym._n._n_name, h->root.root.string, SYMNMLEN);
+ else
+ {
+ boolean hash;
+ bfd_size_type indx;
+
+ hash = true;
+ if ((output_bfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
+ hash = false;
+ indx = _bfd_stringtab_add (finfo->strtab, h->root.root.string, hash,
+ false);
+ if (indx == (bfd_size_type) -1)
+ return false;
+ isym._n._n_n._n_zeroes = 0;
+ isym._n._n_n._n_offset = STRING_SIZE_SIZE + indx;
+ }
+
+ if (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak)
+ {
+ isym.n_value = 0;
+ isym.n_scnum = N_UNDEF;
+ isym.n_sclass = C_EXT;
+ aux.x_csect.x_smtyp = XTY_ER;
+ }
+ else if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ struct xcoff_link_size_list *l;
+
+ isym.n_value = (h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset
+ + h->root.u.def.value);
+ isym.n_scnum = h->root.u.def.section->output_section->target_index;
+ isym.n_sclass = C_HIDEXT;
+ aux.x_csect.x_smtyp = XTY_SD;
+
+ if ((h->flags & XCOFF_HAS_SIZE) != 0)
+ {
+ for (l = xcoff_hash_table (finfo->info)->size_list;
+ l != NULL;
+ l = l->next)
+ {
+ if (l->h == h)
+ {
+ aux.x_csect.x_scnlen.l = l->size;
+ break;
+ }
+ }
+ }
+ }
+ else if (h->root.type == bfd_link_hash_common)
+ {
+ isym.n_value = (h->root.u.c.p->section->output_section->vma
+ + h->root.u.c.p->section->output_offset);
+ isym.n_scnum = h->root.u.c.p->section->output_section->target_index;
+ isym.n_sclass = C_EXT;
+ aux.x_csect.x_smtyp = XTY_CM;
+ aux.x_csect.x_scnlen.l = h->root.u.c.size;
+ }
+ else
+ abort ();
+
+ isym.n_type = T_NULL;
+ isym.n_numaux = 1;
+
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) outsym);
+ outsym += bfd_coff_symesz (output_bfd);
+
+ aux.x_csect.x_smclas = h->smclas;
+
+ bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, isym.n_sclass, 0, 1,
+ (PTR) outsym);
+ outsym += bfd_coff_auxesz (output_bfd);
+
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ /* We just output an SD symbol. Now output an LD symbol. */
+
+ h->indx += 2;
+
+ isym.n_sclass = C_EXT;
+ bfd_coff_swap_sym_out (output_bfd, (PTR) &isym, (PTR) outsym);
+ outsym += bfd_coff_symesz (output_bfd);
+
+ aux.x_csect.x_smtyp = XTY_LD;
+ aux.x_csect.x_scnlen.l = obj_raw_syment_count (output_bfd);
+
+ bfd_coff_swap_aux_out (output_bfd, (PTR) &aux, T_NULL, C_EXT, 0, 1,
+ (PTR) outsym);
+ outsym += bfd_coff_auxesz (output_bfd);
+ }
+
+ if (bfd_seek (output_bfd,
+ (obj_sym_filepos (output_bfd)
+ + (obj_raw_syment_count (output_bfd)
+ * bfd_coff_symesz (output_bfd))),
+ SEEK_SET) != 0
+ || (bfd_write (finfo->outsyms, outsym - finfo->outsyms, 1, output_bfd)
+ != (bfd_size_type) (outsym - finfo->outsyms)))
+ return false;
+ obj_raw_syment_count (output_bfd) +=
+ (outsym - finfo->outsyms) / bfd_coff_symesz (output_bfd);
+
+ return true;
+}
+
+/* Handle a link order which is supposed to generate a reloc. */
+
+static boolean
+xcoff_reloc_link_order (output_bfd, finfo, output_section, link_order)
+ bfd *output_bfd;
+ struct xcoff_final_link_info *finfo;
+ asection *output_section;
+ struct bfd_link_order *link_order;
+{
+ reloc_howto_type *howto;
+ struct xcoff_link_hash_entry *h;
+ asection *hsec;
+ bfd_vma hval;
+ bfd_vma addend;
+ struct internal_reloc *irel;
+ struct xcoff_link_hash_entry **rel_hash_ptr;
+ struct internal_ldrel ldrel;
+
+ if (link_order->type == bfd_section_reloc_link_order)
+ {
+ /* We need to somehow locate a symbol in the right section. The
+ symbol must either have a value of zero, or we must adjust
+ the addend by the value of the symbol. FIXME: Write this
+ when we need it. The old linker couldn't handle this anyhow. */
+ abort ();
+ }
+
+ howto = bfd_reloc_type_lookup (output_bfd, link_order->u.reloc.p->reloc);
+ if (howto == NULL)
+ {
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
+ h = ((struct xcoff_link_hash_entry *)
+ bfd_wrapped_link_hash_lookup (output_bfd, finfo->info,
+ link_order->u.reloc.p->u.name,
+ false, false, true));
+ if (h == NULL)
+ {
+ if (! ((*finfo->info->callbacks->unattached_reloc)
+ (finfo->info, link_order->u.reloc.p->u.name, (bfd *) NULL,
+ (asection *) NULL, (bfd_vma) 0)))
+ return false;
+ return true;
+ }
+
+ if (h->root.type == bfd_link_hash_common)
+ {
+ hsec = h->root.u.c.p->section;
+ hval = 0;
+ }
+ else if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ hsec = h->root.u.def.section;
+ hval = h->root.u.def.value;
+ }
+ else
+ {
+ hsec = NULL;
+ hval = 0;
+ }
+
+ addend = link_order->u.reloc.p->addend;
+ if (hsec != NULL)
+ addend += (hsec->output_section->vma
+ + hsec->output_offset
+ + hval);
+
+ if (addend != 0)
+ {
+ bfd_size_type size;
+ bfd_byte *buf;
+ bfd_reloc_status_type rstat;
+ boolean ok;
+
+ size = bfd_get_reloc_size (howto);
+ buf = (bfd_byte *) bfd_zmalloc (size);
+ if (buf == NULL)
+ return false;
+
+ rstat = _bfd_relocate_contents (howto, output_bfd, addend, buf);
+ switch (rstat)
+ {
+ case bfd_reloc_ok:
+ break;
+ default:
+ case bfd_reloc_outofrange:
+ abort ();
+ case bfd_reloc_overflow:
+ if (! ((*finfo->info->callbacks->reloc_overflow)
+ (finfo->info, link_order->u.reloc.p->u.name,
+ howto->name, 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;
+ }
+
+ /* Store the reloc information in the right place. It will get
+ swapped and written out at the end of the final_link routine. */
+
+ irel = (finfo->section_info[output_section->target_index].relocs
+ + output_section->reloc_count);
+ rel_hash_ptr = (finfo->section_info[output_section->target_index].rel_hashes
+ + output_section->reloc_count);
+
+ memset (irel, 0, sizeof (struct internal_reloc));
+ *rel_hash_ptr = NULL;
+
+ irel->r_vaddr = output_section->vma + link_order->offset;
+
+ if (h->indx >= 0)
+ irel->r_symndx = h->indx;
+ else
+ {
+ /* Set the index to -2 to force this symbol to get written out. */
+ h->indx = -2;
+ *rel_hash_ptr = h;
+ irel->r_symndx = 0;
+ }
+
+ irel->r_type = howto->type;
+ irel->r_size = howto->bitsize - 1;
+ if (howto->complain_on_overflow == complain_overflow_signed)
+ irel->r_size |= 0x80;
+
+ ++output_section->reloc_count;
+
+ /* Now output the reloc to the .loader section. */
+
+ ldrel.l_vaddr = irel->r_vaddr;
+
+ if (hsec != NULL)
+ {
+ const char *secname;
+
+ secname = hsec->output_section->name;
+
+ if (strcmp (secname, ".text") == 0)
+ ldrel.l_symndx = 0;
+ else if (strcmp (secname, ".data") == 0)
+ ldrel.l_symndx = 1;
+ else if (strcmp (secname, ".bss") == 0)
+ ldrel.l_symndx = 2;
+ else
+ {
+ (*_bfd_error_handler)
+ ("%s: loader reloc in unrecognized section `%s'",
+ bfd_get_filename (output_bfd), secname);
+ bfd_set_error (bfd_error_nonrepresentable_section);
+ return false;
+ }
+ }
+ else
+ {
+ if (h->ldindx < 0)
+ {
+ (*_bfd_error_handler)
+ ("%s: `%s' in loader reloc but not loader sym",
+ bfd_get_filename (output_bfd),
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ ldrel.l_symndx = h->ldindx;
+ }
+
+ ldrel.l_rtype = (irel->r_size << 8) | irel->r_type;
+ ldrel.l_rsecnm = output_section->target_index;
+ xcoff_swap_ldrel_out (output_bfd, &ldrel, finfo->ldrel);
+ ++finfo->ldrel;
+
+ return true;
+}
+
+/* Sort relocs by VMA. This is called via qsort. */
+
+static int
+xcoff_sort_relocs (p1, p2)
+ const PTR p1;
+ const PTR p2;
+{
+ const struct internal_reloc *r1 = (const struct internal_reloc *) p1;
+ const struct internal_reloc *r2 = (const struct internal_reloc *) p2;
+
+ if (r1->r_vaddr > r2->r_vaddr)
+ return 1;
+ else if (r1->r_vaddr < r2->r_vaddr)
+ return -1;
+ else
+ return 0;
+}
+
+/* This is the relocation function for the RS/6000/POWER/PowerPC.
+ This is currently the only processor which uses XCOFF; I hope that
+ will never change. */
+
+boolean
+_bfd_ppc_xcoff_relocate_section (output_bfd, info, input_bfd,
+ input_section, contents, relocs, syms,
+ sections)
+ bfd *output_bfd;
+ struct bfd_link_info *info;
+ bfd *input_bfd;
+ asection *input_section;
+ bfd_byte *contents;
+ struct internal_reloc *relocs;
+ struct internal_syment *syms;
+ asection **sections;
+{
+ struct internal_reloc *rel;
+ struct internal_reloc *relend;
+
+ rel = relocs;
+ relend = rel + input_section->reloc_count;
+ for (; rel < relend; rel++)
+ {
+ long symndx;
+ struct xcoff_link_hash_entry *h;
+ struct internal_syment *sym;
+ bfd_vma addend;
+ bfd_vma val;
+ struct reloc_howto_struct howto;
+ bfd_reloc_status_type rstat;
+
+ /* Relocation type R_REF is a special relocation type which is
+ merely used to prevent garbage collection from occurring for
+ the csect including the symbol which it references. */
+ if (rel->r_type == R_REF)
+ continue;
+
+ symndx = rel->r_symndx;
+
+ if (symndx == -1)
+ {
+ h = NULL;
+ sym = NULL;
+ addend = 0;
+ }
+ else
+ {
+ h = obj_xcoff_sym_hashes (input_bfd)[symndx];
+ sym = syms + symndx;
+ addend = - sym->n_value;
+ }
+
+ /* We build the howto information on the fly. */
+
+ howto.type = rel->r_type;
+ howto.rightshift = 0;
+ howto.size = 2;
+ howto.bitsize = (rel->r_size & 0x1f) + 1;
+ howto.pc_relative = false;
+ howto.bitpos = 0;
+ if ((rel->r_size & 0x80) != 0)
+ howto.complain_on_overflow = complain_overflow_signed;
+ else
+ howto.complain_on_overflow = complain_overflow_bitfield;
+ howto.special_function = NULL;
+ howto.name = "internal";
+ howto.partial_inplace = true;
+ if (howto.bitsize == 32)
+ howto.src_mask = howto.dst_mask = 0xffffffff;
+ else
+ {
+ howto.src_mask = howto.dst_mask = (1 << howto.bitsize) - 1;
+ if (howto.bitsize == 16)
+ howto.size = 1;
+ }
+ howto.pcrel_offset = false;
+
+ val = 0;
+
+ if (h == NULL)
+ {
+ asection *sec;
+
+ if (symndx == -1)
+ {
+ sec = bfd_abs_section_ptr;
+ val = 0;
+ }
+ else
+ {
+ sec = sections[symndx];
+ /* Hack to make sure we use the right TOC anchor value
+ if this reloc is against the TOC anchor. */
+ if (sec->name[3] == '0'
+ && strcmp (sec->name, ".tc0") == 0)
+ val = xcoff_data (output_bfd)->toc;
+ else
+ val = (sec->output_section->vma
+ + sec->output_offset
+ + sym->n_value
+ - sec->vma);
+ }
+ }
+ else
+ {
+ if (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ {
+ asection *sec;
+
+ sec = h->root.u.def.section;
+ val = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if (h->root.type == bfd_link_hash_common)
+ {
+ asection *sec;
+
+ sec = h->root.u.c.p->section;
+ val = (sec->output_section->vma
+ + sec->output_offset);
+ }
+ else if ((h->flags & XCOFF_DEF_DYNAMIC) != 0
+ || (h->flags & XCOFF_IMPORT) != 0)
+ {
+ /* Every symbol in a shared object is defined somewhere. */
+ val = 0;
+ }
+ else if (! info->relocateable
+ && ! info->shared)
+ {
+ if (! ((*info->callbacks->undefined_symbol)
+ (info, h->root.root.string, input_bfd, input_section,
+ rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+
+ /* I took the relocation type definitions from two documents:
+ the PowerPC AIX Version 4 Application Binary Interface, First
+ Edition (April 1992), and the PowerOpen ABI, Big-Endian
+ 32-Bit Hardware Implementation (June 30, 1994). Differences
+ between the documents are noted below. */
+
+ switch (rel->r_type)
+ {
+ case R_RTB:
+ case R_RRTBI:
+ case R_RRTBA:
+ /* These relocs are defined by the PowerPC ABI to be
+ relative branches which use half of the difference
+ between the symbol and the program counter. I can't
+ quite figure out when this is useful. These relocs are
+ not defined by the PowerOpen ABI. */
+ default:
+ (*_bfd_error_handler)
+ ("%s: unsupported relocation type 0x%02x",
+ bfd_get_filename (input_bfd), (unsigned int) rel->r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ case R_POS:
+ /* Simple positive relocation. */
+ break;
+ case R_NEG:
+ /* Simple negative relocation. */
+ val = - val;
+ break;
+ case R_REL:
+ /* Simple PC relative relocation. */
+ howto.pc_relative = true;
+ break;
+ case R_TOC:
+ /* TOC relative relocation. The value in the instruction in
+ the input file is the offset from the input file TOC to
+ the desired location. We want the offset from the final
+ TOC to the desired location. We have:
+ isym = iTOC + in
+ iinsn = in + o
+ osym = oTOC + on
+ oinsn = on + o
+ so we must change insn by on - in.
+ */
+ case R_GL:
+ /* Global linkage relocation. The value of this relocation
+ is the address of the entry in the TOC section. */
+ case R_TCL:
+ /* Local object TOC address. I can't figure out the
+ difference between this and case R_GL. */
+ case R_TRL:
+ /* TOC relative relocation. A TOC relative load instruction
+ which may be changed to a load address instruction.
+ FIXME: We don't currently implement this optimization. */
+ case R_TRLA:
+ /* TOC relative relocation. This is a TOC relative load
+ address instruction which may be changed to a load
+ instruction. FIXME: I don't know if this is the correct
+ implementation. */
+ if (h != NULL && h->toc_section == NULL)
+ {
+ (*_bfd_error_handler)
+ ("%s: TOC reloc at 0x%x to symbol `%s' with no TOC entry",
+ bfd_get_filename (input_bfd), rel->r_vaddr,
+ h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ if (h != NULL)
+ {
+ BFD_ASSERT ((h->flags & XCOFF_SET_TOC) == 0);
+ val = (h->toc_section->output_section->vma
+ + h->toc_section->output_offset);
+ }
+ val = ((val - xcoff_data (output_bfd)->toc)
+ - (sym->n_value - xcoff_data (input_bfd)->toc));
+ addend = 0;
+ break;
+ case R_BA:
+ /* Absolute branch. We don't want to mess with the lower
+ two bits of the instruction. */
+ case R_CAI:
+ /* The PowerPC ABI defines this as an absolute call which
+ may be modified to become a relative call. The PowerOpen
+ ABI does not define this relocation type. */
+ case R_RBA:
+ /* Absolute branch which may be modified to become a
+ relative branch. */
+ case R_RBAC:
+ /* The PowerPC ABI defines this as an absolute branch to a
+ fixed address which may be modified to an absolute branch
+ to a symbol. The PowerOpen ABI does not define this
+ relocation type. */
+ case R_RBRC:
+ /* The PowerPC ABI defines this as an absolute branch to a
+ fixed address which may be modified to a relative branch.
+ The PowerOpen ABI does not define this relocation type. */
+ howto.src_mask &= ~3;
+ howto.dst_mask = howto.src_mask;
+ break;
+ case R_BR:
+ /* Relative branch. We don't want to mess with the lower
+ two bits of the instruction. */
+ case R_CREL:
+ /* The PowerPC ABI defines this as a relative call which may
+ be modified to become an absolute call. The PowerOpen
+ ABI does not define this relocation type. */
+ case R_RBR:
+ /* A relative branch which may be modified to become an
+ absolute branch. FIXME: We don't implement this,
+ although we should for symbols of storage mapping class
+ XMC_XO. */
+ howto.pc_relative = true;
+ howto.src_mask &= ~3;
+ howto.dst_mask = howto.src_mask;
+ break;
+ case R_RL:
+ /* The PowerPC AIX ABI describes this as a load which may be
+ changed to a load address. The PowerOpen ABI says this
+ is the same as case R_POS. */
+ break;
+ case R_RLA:
+ /* The PowerPC AIX ABI describes this as a load address
+ which may be changed to a load. The PowerOpen ABI says
+ this is the same as R_POS. */
+ break;
+ }
+
+ /* If we see an R_BR or R_RBR reloc which is jumping to global
+ linkage code, and it is followed by an appropriate cror nop
+ instruction, we replace the cror with lwz r2,20(r1). This
+ restores the TOC after the glink code. Contrariwise, if the
+ call is followed by a lwz r2,20(r1), but the call is not
+ going to global linkage code, we can replace the load with a
+ cror. */
+ if ((rel->r_type == R_BR || rel->r_type == R_RBR)
+ && h != NULL
+ && h->root.type == bfd_link_hash_defined
+ && (rel->r_vaddr - input_section->vma + 8
+ <= input_section->_cooked_size))
+ {
+ bfd_byte *pnext;
+ unsigned long next;
+
+ pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+ next = bfd_get_32 (input_bfd, pnext);
+ if (h->smclas == XMC_GL)
+ {
+ if (next == 0x4def7b82 /* cror 15,15,15 */
+ || next == 0x4ffffb82) /* cror 31,31,31 */
+ bfd_put_32 (input_bfd, 0x80410014, pnext); /* lwz r1,20(r1) */
+ }
+ else
+ {
+ if (next == 0x80410014) /* lwz r1,20(r1) */
+ bfd_put_32 (input_bfd, 0x4ffffb82, pnext); /* cror 31,31,31 */
+ }
+ }
+
+ /* A PC relative reloc includes the section address. */
+ if (howto.pc_relative)
+ addend += input_section->vma;
+
+ rstat = _bfd_final_link_relocate (&howto, input_bfd, input_section,
+ contents,
+ rel->r_vaddr - input_section->vma,
+ val, addend);
+
+ switch (rstat)
+ {
+ default:
+ abort ();
+ case bfd_reloc_ok:
+ break;
+ case bfd_reloc_overflow:
+ {
+ const char *name;
+ char buf[SYMNMLEN + 1];
+ char howto_name[10];
+
+ if (symndx == -1)
+ name = "*ABS*";
+ else if (h != NULL)
+ name = h->root.root.string;
+ else
+ {
+ name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
+ if (name == NULL)
+ return false;
+ }
+ sprintf (howto_name, "0x%02x", rel->r_type);
+
+ if (! ((*info->callbacks->reloc_overflow)
+ (info, name, howto_name, (bfd_vma) 0, input_bfd,
+ input_section, rel->r_vaddr - input_section->vma)))
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/contrib/gdb/gdb/.gdbinit b/contrib/gdb/gdb/.gdbinit
new file mode 100644
index 0000000..f60802e
--- /dev/null
+++ b/contrib/gdb/gdb/.gdbinit
@@ -0,0 +1,16 @@
+echo Setting up the environment for debugging gdb.\n
+
+set complaints 1
+
+b fatal
+
+b info_command
+commands
+ silent
+ return
+end
+
+dir ../mmalloc
+dir ../libiberty
+dir ../bfd
+set prompt (top-gdb)
diff --git a/contrib/gdb/gdb/COPYING b/contrib/gdb/gdb/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/contrib/gdb/gdb/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/contrib/gdb/gdb/ChangeLog b/contrib/gdb/gdb/ChangeLog
new file mode 100644
index 0000000..0ee1d9c
--- /dev/null
+++ b/contrib/gdb/gdb/ChangeLog
@@ -0,0 +1,1415 @@
+Mon Apr 22 20:17:01 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version number to 4.16
+ * NEWS: Update for 4.16 release.
+
+Fri Apr 12 21:39:42 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.86
+ * README: Update for 4.16 release.
+ * configure.in (AC_CHECK_FUNCS): Also check for sbrk.
+ * configure: Regenerate with autoconf.
+ * config.in: Regenerate with autoheader.
+ * main.c (main): Only use sbrk() when HAVE_SBRK is defined.
+ * top.c (command_loop): Ditto.
+
+Thu Apr 11 17:51:58 1996 Fred Fish <fnf@cygnus.com>
+
+ From: Miles Bader <miles@gnu.ai.mit.edu>
+ * configure.in (AC_CHECK_HEADERS): check for endian.h.
+ Use AC_CHECK_TOOL to find AR & RANLIB. Add AC_PROG_AWK.
+ Add host & target cases for i[345]86-*-gnu*.
+ * config.in: Regenerate with autoheader.
+ * configure: Regenerate with autoconf.
+ * Makefile.in (AR, AWK): Set from corresponding autoconf substs.
+ (init.c): Don't scan mig-generated files.
+ * defs.h (endian.h): Include if HAVE_ENDIAN_H defined.
+ * config/nm-m3.h (ATTACH_NO_WAIT): Define.
+ * infcmd.c (attach_command): Use "#ifndef ATTACH_NO_WAIT"
+ rather than "#ifndef MACH".
+
+Mon Apr 8 12:53:56 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (scm-exp.o, scm-lang.o, scm-valprint.o): Add targets and
+ dependencies.
+ * scm-lang.c (gdb_string.h): Include.
+ * objfiles.c (add_to_objfile_sections): Cast second arg of obstack_grow
+ call to correct type (char *).
+ * cp-valprint.c (cp_print_static_field): Ditto.
+ * somsolib.c (som_solib_create_inferior_hook): Add a declaration
+ for external find_unwind_entry function (from hppa-tdep.c).
+ * remote-pa.c (remote_write_bytes, remote_read_bytes): Change
+ type of second arg to "char *" to be type compatible with
+ dcache.
+ (remote_wait): Cast second arg to strtol to correct type.
+ * hppa-tdep.c (compare_unwind_entries): Change argument types to
+ "const void *" to be type compatible with qsort, and then
+ assign to local args prior to use.
+
+Sun Apr 7 22:34:29 1996 Fred Fish <fnf@cygnus.com>
+
+ From: Miles Bader <miles@gnu.ai.mit.edu>
+ * gnu-nat.c, gnu-nat.h, msg.defs, exc_request.defs, i386gnu-nat.c,
+ msg_reply.defs, notify.defs, process_reply.defs, reply_mig_hack.awk,
+ config/nm-gnu.h, config/i386/{i386gnu.mh, i386gnu.mt, nm-gnu.h,
+ m-i386gnu.h, xm-i386gnu.h}: New files for GNU hurd.
+
+Sun Apr 7 13:32:41 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (case host): Add i386sco5 host.
+ * configure: Regenerate.
+
+ From: Robert Lipe <robertl@dgii.com>
+ Add support for SCO OpenServer 5 (a.k.a. 3.2v5*) This
+ target is an SVR3.2 with COFF, ELF, and shared libes, but
+ no /proc.
+ * config/i386/i386sco5.mh: New file.
+ * config/i386/nm-i386sco5.h: New file.
+
+Sat Apr 6 08:55:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * bcache.c (bcache): When size of chunk to cache is exactly equal to
+ BCACHE_MAXLENGTH, stash chunk as unique copy.
+
+Sat Apr 6 00:46:26 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (INLINE_ADD_PSYMBOL): Remove ifdef.
+ (add_psymbol_to_list): Add an arg for passing CORE_ADDR values and
+ use it, rather than calling add_psymbol_addr_to_list.
+ (add_psymbol_addr_to_list): Delete.
+ (add_psymbol_to_list): Make psymbol static to avoid random data in
+ gaps due to alignment of structure members.
+ * symfile.h (INLINE_ADD_PSYMBOL, ADD_PSYMBOL_TO_LIST,
+ ADD_PSYMBOL_ADDR_TO_LIST): Remove. Real world tests show no
+ performance improvements by inlining via complicated macros and
+ they just make gdb larger and harder to maintain.
+ * dwarfread.c (add_enum_psymbol): Replace ADD_PSYMBOL_TO_LIST
+ and/or ADD_PSYMBOL_ADDR_TO_LIST macro(s) with call to
+ add_psymbol_to_list with appropriate long or CORE_ADDR args.
+ (add_partial_symbol): Ditto.
+ * partial-stab.h: Ditto.
+ * os9kread.c (read_os9k_psymtab): Ditto
+ * mdebugread.c (parse_partial_symbols): Ditto.
+ (handle_psymbol_enumerators): Ditto.
+ (demangle.h): Include.
+ * hpread.c (hpread_build_psymtabs): Ditto.
+ (hpread_build_psymtabs): Ditto.
+ (demangle.h): Include
+
+Thu Apr 4 17:59:58 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Check for setpgid function.
+ * config.in: Regenerate with autoheader.
+ * configure: Regenerate with autoconf.
+ * inflow.c (_initialize_inflow): Only try to use _SC_JOB_CONTROL
+ if it is actually defined.
+ (gdb_setpgid): Use HAVE_SETPGID.
+ * ch-exp.c: Change include of <string.h> to "gdb_string.h".
+ * c-exp.y: Ditto.
+ * f-exp.y: Ditto.
+ * m2-exp.y: Ditto.
+ * c-exp.y: Include <ctype.h>.
+ * serial.c: Ditto.
+ * config/m68k/nm-news.h: Add typedef for pid_t which is
+ apparently missing from <sys/types.h>. Enclose entire
+ file in NM_NEWS_H ifndef and define when included.
+ * config/mips/nm-news-mips.h: Ditto.
+ * config/m68k/tm-m68k.h (REGISTER_CONVERT_TO_VIRTUAL,
+ REGISTER_CONVERT_TO_RAW): Change name of temporary variable.
+
+Thu Apr 4 17:17:53 1996 Fred Fish <fnf@cygnus.com>
+
+ * symmisc.c (print_objfile_statistics): Print memory used by
+ psymbol cache obstack.
+
+Mon Apr 1 16:31:00 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Change references to config.h to be in objdir,
+ edit out rules to rebuild config.h.
+
+Mon Apr 1 08:32:23 1996 Fred Fish <fnf@cygnus.com>
+
+ * hppa-tdep.c (hppa_pop_frame): Call clear_proceed_status before
+ proceeding.
+
+Sun Mar 31 16:15:43 1996 Fred Fish <fnf@cygnus.com>
+
+ * hppah-nat.c (store_inferior_registers, store_inferior_registers,
+ fetch_register, child_xfer_memory): Use call_ptrace function supplied
+ by infptrace.c rather than calling ptrace directly.
+
+Sat Mar 30 11:00:22 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Check whether printf family supports printing
+ long doubles or not and define PRINTF_HAS_LONG_DOUBLE if so.
+ * acconfig.h: Provide default undef for PRINTF_HAS_LONG_DOUBLE.
+ * configure: Regenerate.
+ * valprint.c (print_floating): Use PRINTF_HAS_LONG_DOUBLE.
+ * c-exp.y (parse_number): Use PRINTF_HAS_LONG_DOUBLE.
+ * configure.in: Fix have_gregset and have_fpregset autoconf
+ variable names so that they match the pattern required to
+ cache them.
+
+Fri Mar 29 21:53:14 1996 Fred Fish <fnf@cygnus.com>
+
+ * core-aout.c (fetch_core_registers): Cast core_reg_size to int
+ before testing against reg_ptr.
+ * eval.c (evaluate_subexp_standard): Cast type of
+ TYPE_FN_FIELD_VOFFSET to int.
+ * findvar.c (extract_signed_integer, extract_unsigned_integer,
+ extract_long_unsigned_integer): Cast type of sizeof to int.
+ * values.c (unpack_field_as_long, modify_field): Ditto.
+ * valops.c (value_assign, call_function_by_hand): Ditto.
+ * infcmd.c (do_registers_info): Ditto.
+ * ser-tcp.c (tcp_open): Ditto
+ * remote.c (putpkt): Ditto.
+ * dcache.c (dcache_peek): Ditto.
+ * dcache.c (dcache_poke): Ditto.
+ * m2-exp.y (yylex): Ditto.
+ * gnu-regex.c (re_match_2): Ditto.
+ * f-lang.c (ADD_BF_SYMNUM, saved_bf_list_end, tmp_bf_ptr): Ifdef
+ out unused macro definition and variables.
+ * inftarg.c (proc_wait): Move from main.c to here, and make static.
+ * valprint.c (val_print_string): Change bufsize from int to unsigned.
+ * main.c (wait.h): Include
+ * top.c (command_line_input): Remove unused variable "c".
+ * f-typeprint.c (f_type_print_varspec_prefix): Add missing enum
+ value TYPE_CODE_TYPEDEF to switch statement.
+ (f_type_print_varspec_suffix): Add missing enum value
+ TYPE_CODE_TYPEDEF to switch statement.
+ * ch-exp.c (parse_primval): Add remaining enumeration values to
+ switch statement, with no specific action.
+ (ch_lex): Add LOC_UNRESOLVED in switch statement.
+ (pushback_token): Ifdef out, since code using it is ifdef'd out.
+ * stabsread.c (cleanup_undefined_types): Remove unused label
+ "badtype".
+ * objfiles.h (print_symbol_bcache_statistics): Add prototype.
+ * maint.c (objfiles.h): Include.
+ (maintenance_print_statistics): Remove unused variable "temp".
+ * minsyms.c (lookup_minimal_symbol_solib_trampoline): Remove
+ unused variable "found_file_symbol".
+ * m2-exp.y (yylex): Add LOC_UNRESOLVED case to switch.
+ * language.c (lang_bool_type): Use existing function local type
+ variable rather than create block local variables.
+ * solib.c (disable_break): Enclose in ifndef SVR4_SHARED_LIBS.
+ * infptrace.c (wait.h, command.h): Include.
+ * ser-tcp.c (gdb_string.h): Include
+ * i386-tdep.c (codestream_seek): Change "place" to CORE_ADDR.
+ (i386_get_frame_setup): Change "pc" from int to CORE_ADDR.
+ * command.c (complete_on_enum): Make assignment used as truth value
+ explictly check against NULL.
+ (wait.h): Include.
+ * infrun.c (wait_for_inferior): Ifdef out prologue_pc since code
+ that uses it is ifdef'd out.
+ * parser-defs.h: Add prototype for write_dollar_variable.
+ * infrun.c: Add prototype for write_pc_pid.
+ * breakpoint.h: Add prototype for re_enable_breakpoints_in_shlibs.
+ * symmisc.c (bcache.h): Include.
+ * bcache.h: Add prototype for print_bcache_statistics.
+ * symfile.c: Include <time.h>.
+ * printcmd.c (print_scalar_formatted): Change len to unsigned int.
+ * valarith.c (value_equal): Cast result of TYPE_LENGTH to int.
+ * valarith.c (value_binop): Change result_len, promoted_len1,
+ and promoted_len2 to unsigned int.
+ * valarith.c (value_subscripted_rvalue): Change elt_offs and
+ elt_size to unsigned int.
+ * valops.c (value_array): Change typelength to unsigned int.
+ (destructor_name_p): Change len to unsigned int.
+ * scm-lang.h (scm_parse): Add prototype for scm_unpack.
+ * symfile.c (decrement_reading_symtab): Change return type to void.
+ * valarith.c (value_subscript): Remove unused variable "word".
+ (value_subscript): Remove unused variable "tint".
+ * valops.c (auto_abandon): Ifdef out, since code using it is also
+ ifdef'd out.
+ * eval.c (init_array_element): Remove unused variable "val".
+ * Makefile.in (values.o): Depends on scm-lang.h.
+ (command.o): Depends upon wait_h.
+ (ser-tcp.o): Depends upon gdb_string.h.
+ (infptrace.o): Depends upon wait_h and command_h.
+ (maint.o): Depends on objfiles.h and symfile.h.
+ * values.c (allocate_repeat_value): Remove unused variable
+ "element_type".
+ (scm-lang.h): Include.
+ * breakpoint.c (create_longjmp_breakpoint): Enclose in
+ GET_LONGJMP_TARGET define, unused otherwise.
+ * config/i386/nm-linux.h: Add prototypes for i386_insert_watchpoint,
+ i386_remove_watchpoint and i386_stopped_by_watchpoint.
+
+Thu Mar 28 06:51:26 1996 Fred Fish <fnf@cygnus.com>
+
+ * valops.c (value_assign): Make copy of internal variable value
+ before returning it as a new value, since it is owned by the
+ internal variable and will be freed along with it.
+
+Wed Mar 27 12:54:55 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * breakpoint.c (breakpoint_re_set_one): Keep temporary
+ breakpoints bp_until, bp_finish, bp_watchpoint_cope, bp_call_dummy
+ and bp_step_resume in case breakpoint_re_set_one is called due
+ to a step over a dlopen call.
+ * infrun.c (wait_for_inferior): Always remove breakpoints from
+ inferior in BPSTAT_WHAT_CHECK_SHLIBS case.
+
+Tue Mar 26 13:15:32 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.85
+
+ * config/mips/tm-mips.h (COERCE_FLOAT_TO_DOUBLE): Only prefer
+ non-prototyped case over prototyped case for C.
+ * config/pa/tm-hppa.h (COERCE_FLOAT_TO_DOUBLE): Ditto.
+
+Sat Mar 23 15:50:47 1996 Fred Fish <fnf@cygnus.com>
+
+ * os9kread.c (os9k_process_one_symbol): Note nonportable
+ assumption that an int can hold a char *.
+
+ * bcache.h (struct hashlink): Wrap data[] inside union with
+ double to force longest alignment.
+ (BCACHE_DATA): New macro to access data[].
+ (BCACHE_ALIGNMENT): New macro to get offset to data[].
+ * bcache.c (lookup_cache, bcache): Use BCACHE_DATA to get
+ address of cached data. Use BCACHE_ALIGNMENT to compute
+ amount of space to allocate for each hashlink struct.
+
+Sat Mar 23 12:14:02 1996 Fred Fish <fnf@cygnus.com>
+
+ * ch-lang.c (evaluate_subexp_chill): Fix typo.
+
+Thu Mar 21 08:27:19 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.3
+
+Thu Mar 21 10:56:41 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.in: Rename from config.h.in.
+ * configure.in: Call AC_CONFIG_HEADER with config.h:config.in.
+ Change CONFIG_HEADERS test in AC_OUTPUT accordingly.
+ * configure: Rebuild.
+ * Makefile.in (stamp-h): Depend upon config.in, not config.h.in.
+ Set CONFIG_HEADERS to config.h:config.in.
+
+Tue Mar 19 12:47:51 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * partial-stab.h (case N_ENDM): Finish current partial symbol
+ table for Solaris 2 cc.
+
+Tue Mar 19 10:39:15 1996 Jeffrey A Law (law@cygnus.com)
+
+ * rs6000-nat.c (exec_one_dummy_insn): Don't clobber the
+ PC in the registers array. From Peter Schauer.
+
+Mon Mar 18 13:47:09 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (reread_symbols): Reinitialize bcache struct
+ members to zero using memset. Also use memset to reinit
+ global_psymbols and static_psymbols, rather than explicitly
+ resetting each structure member.
+
+Sat Mar 16 19:47:36 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Add fragment to create stamp-h.
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * configure.in (AC_CHECK_HEADERS): Check for link.h.
+ * configure: Regenerate with autoconf.
+ * config.h.in: Regenerate with autoheader.
+ * config/i386/nm-linux.h: Include solib.h only if HAVE_LINK_H
+ is defined.
+ * solib.c: Exclude most of the code if HAVE_LINK_H is not defined.
+ * config/i386/linux.mh: Reinstate XM_CLIBS, it is needed for
+ older a.out based systems.
+
+Sat Mar 16 16:45:43 1996 Fred Fish <fnf@cygnus.com>
+
+ * config.h.in: New file.
+ * acconfig.h: New file, for autoheader.
+ * configure.in (AC_CONFIG_HEADER): Add, generate config.h.
+ * configure: Regenerate.
+ * Makefile.in (defs_h): Add config.h
+ (distclean): Remove config.h and stamp-h during distclean.
+ (config.h, stamp-h): New targets to remake config.h when necessary.
+ * defs.h (config.h): Include before any other includes or defines.
+ * i386-tdep.c (gdb_string.h): Move include after include of defs.h.
+ * i386v4-nat.c (defs.h): Include before testing HAVE_SYS_PROCFS_H.
+
+Sat Mar 16 14:55:27 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * Makefile.in (INSTALLED_LIBS): Make sure that @LIBS@ will not
+ result in an empty line, to work around a bug in native Ultrix 4.4
+ and OSF/1-3.2C make.
+
+Sat Mar 16 13:33:17 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Add gdbserver to configdirs under linux.
+ * configure: Regenerate.
+
+Fri Mar 15 12:06:58 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/i386/nm-nbsd.h (FLOAT_INFO): Comment out.
+ * config/i386/tm-nbsd.h (NUM_REGS): Define.
+
+Thu Mar 14 10:31:18 1996 Jeffrey A Law (law@cygnus.com)
+
+ * solib.c (solib_break_names): Add _r_debug_state for
+ vanilla SVR4 implementations. From Peter Schauer.
+
+Mon Mar 11 14:24:57 1996 Dawn Perchik <dawn@critters.cygnus.com>
+
+ * mon960-rom.c: New file; support mon960 rom monitor on i960.
+ * monitor.c (monitor_debug): Change remotedebug to buffer strings.
+ * monitor.c (monitor_open): Add test for flag MO_NO_ECHO_ON_OPEN before
+ epecting prompt and echo during open.
+ * monitor.c (monitor_stop): Add test for flag MO_SEND_BREAK_ON_OPEN to
+ determine if break should be sent as stop command.
+ * monitor.h: Add flags MO_NO_ECHO_ON_OPEN and MO_SEND_BREAK_ON_OPEN.
+ * i960-tdep.c (mon960_frame_chain_valid): New function for getting
+ stack frame on mon960.
+ * Makefile.in: Add mon960 files.
+ * configure.in: Changed i960-*-coff* and i960-*-elf* to target mon960;
+ added i960-nindy-coff* and i960-nindy-elf* for target nindy.
+ * configure: Regenerated.
+ * config/i960/mon960.mt, config/i960/tm-mon960.h: New files;
+ support mon960 rom monitor on i960.
+
+Mon Mar 11 11:02:47 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ With Michael Snyder:
+ * i386-tdep.c (skip_trampoline_code): Fix strncmp length.
+ * win32-nat.c (CHECK, DEBUG*, debug_*): New.
+ (handle_load_dll): Don't reload symbols.
+ (handle_exception): Use the DEBUG_* names.
+ (child_wait): Add DEBUG_* code.
+ (_initialize_inftarg): Add new commands to set debug_ names.
+
+Mon Mar 11 09:19:58 1996 Jeffrey A Law (law@cygnus.com)
+
+ * From Peter Schauer:
+ * breakpoint.c (insert_breakpoints): Use ALL_BREAKPOINTS_SAFE.
+ (bpstat_stop_status): Likewise.
+ (remove_solib_event_breakpoints): Likewise.
+ (clear_momentary_breakpoints): Likewise.
+ (re_enable_breakpoints_in_shlibs): Don't reenable a breakpoint
+ if we still can't read the memory for that breakpoint.
+ (mention): Add bp_shlib_event case to keep gcc quiet.
+
+Fri Mar 8 12:08:12 1996 Jeffrey A Law (law@cygnus.com)
+
+ * breakpoint.h (enum enable): New enum shlib_disabled for
+ shared library breakpoints that have been temporarily disabled.
+ * breakpoint.c: Handle temporarily disabled shared library
+ breakpoints like disabled breakpoints in most places.
+ (insert_breakpoints): Use shlib_disabled to indicate
+ that an unsettable breakpoint is only temporarily disabled.
+ (re_enable_breakpoints_in_shlibs): New function.
+ * corelow.c (solib_add_stub): After adding shared libraries,
+ try to reenable any temporarily disabled breakpoints.
+ * infcmd.c (attach_command): Likewise.
+ * infrun.c (wait_for_inferior): Likewise.
+
+Fri Mar 8 11:41:25 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * defs.h (extract_long_unsigned_integer): Declare.
+ * findvar.c (extract_long_unsigned_integer): New function.
+ * printcmd.c (print_scalar_formatted): Use it.
+ * valprint.c (val_print_type_code_int): Likewise.
+
+Thu Mar 7 17:40:50 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * infcmd.c (do_registers_info): Ignore anonymous registers.
+ * sh-tdep.c (set processor): New command to set specific
+ processor type.
+ (sh_reg_names, sh3_reg_names): Arrays of register names for
+ SH and SH3 processors.
+ (sh_set_processor_type): New function.
+ * sh3-rom.c (sh3_open): Call it.
+ (sh3_regname): Add names of all the bank registers.
+ (sh3_supply_register): Clean up formatting.
+ * config/sh/tm-sh.h (NUM_REGS, NUM_REALREGS): Increase to include
+ bank registers.
+ (REGISTER_NAMES): Add names of bank registers.
+ (FP15_REGNUM): Define.
+ (REGISTER_VIRTUAL_TYPE): Use it.
+ * monitor.c: Clean up some comments.
+
+Thu Mar 7 12:09:51 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * i386b-nat.c: Revert part of Mar 5 change. FreeBSD collapsed the
+ s* and t* symbols too.
+
+Thu Mar 7 15:18:51 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * symfile.c (generic_load): Avoid division by zero.
+
+Wed Mar 6 17:57:59 1996 Jeffrey A Law (law@cygnus.com)
+
+ * breakpoint.c (bfd_lookup_symbol): Provide for all SVR4 systems,
+ not just those with HANDLE_SVR4_EXEC_EMULATORS.
+
+ From Peter Schauer:
+ * breakpoint.c (internal_breakpoint_number): Move to file scope.
+ (create_solib_event_breakpoint): Use an internal breakpoint number.
+
+Wed Mar 6 00:32:44 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * valarith.c (value_in): Change builtin_type_chill_bool to
+ LA_BOOL_TYPE.
+
+Tue Mar 5 23:48:36 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * ch-exp.c (parse_primval): Handle CARD, MAX, MIN.
+ (match_string_literal): Handle control sequence.
+ (match_character_literal): Deto.
+
+ * ch-lang.c (chill_printchar): Change formating of nonprintable
+ characters from C'xx' to ^(num).
+ (chill_printstr): Deto.
+ (value_chill_card, value_chill_max_min): New functions to process
+ Chill's CARD, MAX, MIN.
+ (evaluate_subexp_chill): Process UNOP_CARD, UNOP_CHMAX, UNOP_CHMIN.
+
+ * expression.h (exp_opcode): Add UNOP_CARD, UNOP_CHMAX, UNOP_CHMIN
+ for Chill's CARD, MAX, MIN.
+
+ * valarith.c (value_in): Add processing of TYPE_CODE_RANGE
+ and change return type from builtin_type_int to
+ builtin_type_chill_bool.
+
+Tue Mar 5 18:54:04 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/nm-nbsd.h (link_object, lo_name, etc): Move to here
+ from config/nm-nbsd.h.
+ * config/sparc/nm-nbsd.h (regs, fp_status, etc): Move to here
+ from config/sparc/tm-nbsd.h.
+
+ * config/m68k/nm-hp300hpux.h (FIVE_ARG_PTRACE): Define here
+ instead of in config/m68k/xm-hp300hpux.h.
+
+Tue Mar 5 12:05:35 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * i386b-nat.c, m68knbsd-nat.c (fetch_core_registers): Provide
+ implementation for NetBSD systems.
+
+Mon Mar 4 23:44:16 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valarith.c (binop_user_defined_p): Return 0 for BINOP_CONCAT.
+ (value_concat): Handle varying strings (add COERCE_VARYING_ARRAY).
+
+ * ch-lang.c (evaluate_subexp_chill case MULTI_SUBSCRIPT): Error
+ if "function" is pointer to non-function.
+
+Mon Mar 4 17:47:03 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (print_gdb_version): Update copyright year.
+
+Mon Mar 4 14:44:54 1996 Jeffrey A Law (law@cygnus.com)
+
+ From Peter Schauer:
+ * infrun.c (wait_for_inferior): Remove breakpoints and
+ switch terminal settings before calling SOLIB_ADD.
+ * solib.c (enable_break, SVR4 variant): Don't map in symbols
+ for the dynamic linker, the namespace pollution causes real
+ problems.
+
+Sun Mar 3 17:18:57 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * remote-mips.c (common_breakpoint): Explicitly terminate the
+ returned buffer.
+
+Wed Feb 28 22:32:18 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Wilfried Moser <wilfried.moser@aut.alcatel.at>:
+ * remote.c (remote_detach): Send a command 'D' to the target
+ when detaching, update the function's comments.
+
+Wed Feb 28 15:50:12 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.2 to establish
+ baseline for gdb 4.16 rerelease testing.
+
+Wed Feb 28 13:32:05 1996 Jeffrey A Law (law@cygnus.com)
+
+ * somsolib.c (som_solib_create_inferior_hook): Before returning
+ call clear_symtab_users.
+
+Tue Feb 27 00:04:46 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote-e7000.c (e7000_open): Delete all breakpoints when
+ connecting to e7000. Change connect message to allow use of
+ monitor.exp in test suite.
+ * (e7000_load): Print transfer rate of download.
+ * symfile.c (generic_load): Print transfer rate of download.
+
+Sun Feb 25 13:58:33 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (mips*-*-vxworks*): New config.
+ * configure: Regenerated.
+
+ * config/mips/vxmips.mt, config/mips/tm-vxmips.h: New files.
+ * remote-vxmips.c (vx_convert_to_virtual, vx_convert_from_virtual):
+ Remove, never used.
+
+Sat Feb 24 12:30:28 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * partial-stab.h (case N_FUN): Function symbols generated
+ by SPARCworks cc have a meaningless zero value, do not update
+ pst->textlow if the function symbol value is zero.
+
+ * stabsread.c (define_symbol): Initialize SYMBOL_TYPE field
+ for function prototype declaration symbols.
+
+Fri Feb 23 22:33:04 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * remote-e7000.c (e7000_load): New routine to download via the
+ network.
+ * (e7000_wait): Don't backup PC when we hit a breakpoint.
+ Apparantly new sh2 pods get this right...
+ * (e7000_ops): Add call to e7000_load.
+
+Thu Feb 22 00:52:42 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/m68k/{nbsd.mh,nbsd.mt,nm-nbsd.h,tm-nbsd.h,xm-nbsd.h},
+ m68knbsd-nat.c: New files, support for NetBSD/m68k.
+
+ * configure.in (m68k-*-netbsd*): New config.
+ * configure: Regenerated.
+
+Wed Feb 21 19:00:21 1996 Fred Fish <fnf@cygnus.com>
+
+ * standalone.c (open, _initialize_standalone): Fix obvious typos
+ reported by Martin Pool <martin@citr.uq.oz.au>.
+
+Wed Feb 21 14:24:04 1996 Jeffrey A Law (law@cygnus.com)
+
+ * solib.c (solib_create_inferior_hook): Fix thinko.
+
+Tue Feb 20 23:59:19 1996 Jeffrey A Law (law@cygnus.com)
+
+ * solib.c (solib_break_names): Define for Solaris and Linux.
+ (enable_break): For SVR4 systems, first try to use the debugger
+ interfaces in the dynamic linker to track shared library events
+ as they happen, then fall back to BKPT_AT_SYMBOL code. Convert
+ BKPT_AT_SYMBOL code to use shared library event breakpoints.
+ (solib_create_inferior_hook): Simplify BKPT_AT_SYMBOL code,
+ it no longer needs to restart/wait on the inferior.
+ * symfile.c (find_lowest_section): No longer static.
+ * symfile.h (find_lowest_section): Corresponding changes.
+
+Tue Feb 20 18:54:08 1996 Fred Fish <fnf@cygnus.com>
+
+ * valops.c (COERCE_FLOAT_TO_DOUBLE): Define default value.
+ (value_arg_coerce): Use COERCE_FLOAT_TO_DOUBLE.
+ * config/alpha/tm-alpha.h (COERCE_FLOAT_TO_DOUBLE): Define to 1.
+ * config/mips/tm-mips.h: Ditto.
+ * config/pa/tm-hppa.h: Ditto.
+ * config/rs6000/tm-rs6000.h: Ditto.
+ * config/sparc/tm-sparc.h: Ditto.
+
+Tue Feb 20 17:32:05 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/{i386,ns32k}/nbsd.mh (NATDEPFILES): Remove core-aout.o.
+
+ * config/nm-nbsd.h (FETCH_INFERIOR_REGISTERS): Defined.
+ * config/xm-nbsd.h (CC_HAS_LONG_LONG, PRINTF_HAS_LONG_LONG):
+ #ifdef'd out definitions --- Causes serious gdb failures on
+ the i386. Need to investigate further before enabling.
+
+ * i386b-nat.c (fetch_inferior_registers, store_inferior_registers,
+ fetch_core_registers): New functions. These functions are defined
+ if FETCH_INFERIOR_REGISTERS is set. Registers are fetched/stored
+ with ptrace PT_GETREGS/PT_SETREGS.
+
+Tue Feb 20 16:55:06 1996 Stu Grossman (grossman@critters.cygnus.com)
+
+ * findvar.c (extract_floating store_floating): Replace `long
+ double' with `DOUBLEST'.
+
+Mon Feb 19 15:25:51 1996 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/xm-nbsd.h (CC_HAS_LONG_LONG, PRINTF_HAS_LONG_LONG):
+ Define.
+
+Mon Feb 19 10:32:05 1996 Jeffrey A Law (law@cygnus.com)
+
+ * symtab.h (looup_minimal_symbol_solib_trampoline): Declare.
+
+ * breakpoint.h (remove_solib_event_breakpoints): Declare.
+ * breakpoint.c (remove_solib_event_breakpoints): New function.
+ * somsolib.c (solib_create_inferior_hook): Remove all solib event
+ breakpoints before inserting any new ones. Use a solib event
+ breakpoint for the breakpoint at "_start".
+ Remove extraneous "\n" from calls to warning.
+
+ * breakpoint.c (breakpoint_1): Add missing "sigtramp" to bptypes
+ name array.
+
+Mon Feb 19 01:09:32 1996 Doug Evans <dje@cygnus.com>
+
+ * dwarfread.c (add_partial_symbol): Use ADD_PSYMBOL_ADDR_TO_LIST
+ for CORE_ADDR values.
+ (new_symbol): Use SYMBOL_VALUE_ADDRESS for CORE_ADDR values.
+ * symfile.h (add_psymbol_{,addr}to_list): Add prototypes.
+
+Sun Feb 18 14:37:13 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (mipscoff_symfile_read): Unconditionally add
+ alpha coff dynamic symbols for all symbol files. Makes skipping
+ over the trampoline code work when stepping from a function in a
+ shared library into a function in a different shared library.
+
+Sun Feb 18 09:27:10 1996 Stu Grossman (grossman@cygnus.com)
+
+ * config/sparc/tm-sparc.h: Define PS_FLAG_CARRY. Define
+ RETURN_VALUE_ON_STACK to return long doubles on the stack.
+
+Sat Feb 17 16:33:11 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (ch-exp.o): Add dependencies.
+ (various): Add gdb_string.h to dependencies that need it.
+
+Sat Feb 17 08:57:50 1996 Fred Fish <fnf@cygnus.com>
+
+ * symmisc.c (print_symbol_bcache_statistics): Update description for
+ printing byte cache statistics.
+
+Thu Feb 16 16:02:03 1996 Stu Grossman (grossman@cygnus.com)
+
+ * Add native support for long double data type.
+ * c-exp.y (%union): Change dval to typed_val_float. Use DOUBLEST
+ to store actual data. Change types of INT and FLOAT tokens to
+ typed_val_int and typed_val_float respectively. Create new token
+ DOUBLE_KEYWORD to specify the string `double'. Make production
+ for FLOAT use type determined by parse_number. Add production for
+ "long double" data type.
+ * (parse_number): Use sscanf to parse numbers as float, double or
+ long double depending upon the type of typed_val_float.dval. Also
+ allow user to specify `f' or `l' suffix to explicitly specify
+ float or long double constants. Change typed_val to
+ typed_val_int.
+ * (yylex): Change typed_val to typed_val_int. Also, scan for
+ "double" keyword.
+ * coffread.c (decode_base_type): Add support for T_LNGDBL basic
+ type.
+ * configure, configure.in: Add check for long double support in
+ the host compiler.
+ * defs.h: Define DOUBLEST appropriatly depending on whether
+ HAVE_LONG_DOUBLE (from autoconf) is defined. Also, fix prototypes
+ for functions that handle this type.
+ * expression.h (union exp_element): doubleconst is now type
+ DOUBLEST.
+ * m2-exp.y f-exp.y (%union): dval becomes type DOUBLEST.
+ * findvar.c (extract_floating): Make return value be DOUBLEST.
+ Also, add support for numbers with size of long double.
+ * (store_floating): Arg `val' is now type DOUBLEST. Handle all
+ floating types.
+ * parser-defs.h parse.c (write_exp_elt_dblcst): Arg expelt is now
+ DOUBLEST.
+ * valarith.c (value_binop): Change temp variables v1, v2 and v to
+ type DOUBLEST. Coerce type of result to long double if either op
+ was of that type.
+ * valops.c (value_arg_coerce): If argument type is bigger than
+ double, coerce to long double.
+ * (call_function_by_hand): If REG_STRUCT_HAS_ADDR is defined, and
+ arg type is float and > 8 bytes, then use pointer-to-object
+ calling conventions.
+ * valprint.c (print_floating): Arg doub is now type DOUBLEST.
+ Use appropriate format and precision to print out floating point
+ values.
+ * value.h: Fixup prototypes for value_as_double,
+ value_from_double, and unpack_double to use DOUBLEST.
+ * values.c (record_latest_value): Remove check for invalid
+ floats. Allow history to store them so that people may examine
+ them in hex if they want.
+ * (value_as_double unpack_double): Change return value to DOUBLEST.
+ * (value_from_double): Arg `num' is now DOUBLEST.
+ * (using_struct_return): Use RETURN_VALUE_ON_STACK macro (target
+ specific) to expect certain types to always be returned on the stack.
+
+Fri Feb 16 14:00:54 1996 Fred Fish <fnf@cygnus.com>
+
+ * bcache.c, bcache.h: New files to implement a byte cache.
+ * Makefile.in (SFILES): Add bcache.c.
+ (symtab_h): Add bcache.h.
+ (HFILES_NO_SRCDIR): add bcache.h
+ (COMMON_OBJS): Add bcache.o
+ (bcache.o): New target.
+ * dbxread.c (start_psymtab): Make global_syms & static_syms
+ type "partial_symbol **".
+ * hpread.c (hpread_start_symtab): Ditto.
+ * os9kread.c (os9k_start_psymtab): Ditto.
+ * stabsread.h (start_psymtab): Ditto.
+ * {symfile.c, symfile.h} (start_psymtab_common): Ditto.
+ * maint.c (maintenance_print_statistics): Call
+ print_symbol_bcache_statistics.
+ * objfiles.c (allocate_objfile): Initialize psymbol bcache malloc
+ and free pointers.
+ * solib.c (allocate_rt_common_objfile): Ditto.
+ * symfile.c (reread_symbols): Ditto.
+ (free_objfile): Free psymbol bcache when objfile is freed.
+ (objfile_relocate): Use new indirect psymbol pointers.
+ * objfiles.h (struct objfile): Add psymbol cache.
+ * symfile.c (compare_psymbols): Now passed pointers to pointers to
+ psymbols.
+ (reread_symbols): Free psymbol bcache when freeing other objfile
+ resources.
+ (add_psymbol_to_list, add_psymbol_addr_to_list): Initialize new
+ psymbol using the psymbol bcache.
+ (init_psymbol_list): Psymbol lists now contain pointers rather than
+ the actual psymbols.
+ * symfile.h (psymbol_allocation_list): Psymbol lists now dynamically
+ grown arrays of pointers.
+ (ADD_PSYMBOL_VT_TO_LIST): Initialize new symbol using the psymbol
+ bcache.
+ * symmisc.c (print_partial_symbols): Now takes pointer to pointer
+ to partial symbol.
+ (print_symbol_bcache_statistics): New function to print per objfile
+ bcache statistics.
+ (print_partial_symbol, print_partial_symbols,
+ maintenance_check_symtabs, extend_psymbol_list):
+ Account for change to pointer to pointer to partial symbol.
+ * symtab.c (find_pc_psymbol, lookup_partial_symbol, decode_line_2,
+ make_symbol_completion_list):
+ Account for change to pointer to pointer to partial symbol.
+ * symtab.h (bcache.h): Include.
+ * xcoffread.c (xcoff_start_psymtab): Make global_syms & static_syms
+ type "partial_symbol **".
+
+Fri Feb 16 10:02:34 1996 Fred Fish <fnf@cygnus.com>
+
+ * dwarfread.c (free_utypes): New function.
+ (read_file_scope): Call free_utypes as cleanup, rather than just
+ freeing the utypes pointer.
+
+Thu Feb 15 21:40:52 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * demangle.c (is_cplus_marker): New function, checks if a
+ character is one of the commonly used C++ marker characters.
+ * defs.h (is_cplus_marker): Add prototype.
+ * c-typeprint.c (c_type_print_base), ch-lang.c (chill_demangle),
+ cp-valprint.c (cp_print_class_method), mdebugread.c (parse_symbol),
+ stabsread.c (define_symbol, read_member_functions, read_struct_fields),
+ symtab.h (OPNAME_PREFIX_P, VTBL_PREFIX_P, DESTRUCTOR_PREFIX_P),
+ values.c (vb_match): Use is_cplus_marker instead of comparison
+ with CPLUS_MARKER.
+
+Thu Feb 15 18:08:13 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.h (INLINE_ADD_PSYMBOL): Default this to 0 and possibly
+ delete entirely someday.
+
+Thu Feb 15 15:25:34 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Edit out makefile rebuild rule.
+ (host_alias, target_alias): Comment out instead of deleting.
+ (@LIBS@): Edit out references.
+
+Tue Feb 13 22:56:46 1996 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ Use n_psyms in OBJSTAT, not psyms.
+
+Mon Feb 12 15:59:31 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * configure.in (sparclet-*-aout*): New config.
+ * configure: Regenerated.
+
+Mon Feb 12 14:17:52 1996 Fred Fish <fnf@cygnus.com>
+
+ * somsolib.c (som_solib_add): Use xmalloc rather than bare
+ unchecked call to malloc.
+ * remote-mips.c (pmon_load_fast): ditto.
+ * remote-mm.c (mm_open): ditto.
+ * hpread.c (hpread_lookup_type): ditto.
+ * remote-adapt.c (adapt_open): ditto.
+
+Mon Feb 12 13:11:32 1996 Fred Fish <fnf@cygnus.com>
+
+ * f-lang.c (allocate_saved_bf_node, allocate_saved_function_node,
+ allocate_saved_f77_common_node, allocate_common_entry_node,
+ add_common_block): Use xmalloc rather than malloc, some of which
+ were unchecked.
+ * gnu-regex.c: At same point as other gdb specific changes
+ #undef malloc and then #define it to xmalloc.
+ * ch-exp.c (growbuf_by_size): Use xmalloc/xrealloc rather than
+ bare unchecked calls to malloc/realloc.
+ * stabsread.c (dbx_lookup_type): Use xmalloc rather than bare
+ unchecked call to malloc.
+
+Wed Feb 7 11:31:26 1996 Stu Grossman (grossman@cygnus.com)
+
+ * symtab.c (gdb_mangle_name): Change opname var to be const to
+ match return val of cplus_mangle_name.
+ * i960-tdep.c: Change arg types of next_insn to match callers.
+
+Wed Feb 7 07:34:24 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/i386/linux.mh (XM_CLIBS, GDBSERVER_LIBS): Remove. These
+ apparently aren't needed in any reasonably recent version of
+ linux.
+
+Tue Feb 6 21:37:03 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (read_range_type): If !self-subrange and language
+ is Chill, assume a true range. If a true_range is a sub_subrange,
+ use builtin_type_int for index_type.
+
+Tue Feb 6 18:38:51 1996 J.T. Conklin <jtc@slave.cygnus.com>
+
+ * nindy-share/nindy.c (say): Use stdarg.h macros when compiling
+ with an ANSI compiler.
+
+Mon Feb 5 18:24:28 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ From Michael_Snyder@NeXT.COM (Michael Snyder):
+ * valops.c (value_arg_coerce): Coerce float to double, unless the
+ function prototype specifies float.
+
+Mon Feb 5 09:51:55 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * language.c (set_language_command): Use languages table when
+ printing available languages.
+
+Sat Feb 3 12:22:05 1996 Fred Fish <fnf@cygnus.com>
+
+ Fix problems reported by Hans Verkuil (hans@wyst.hobby.nl):
+ * command.c (add_cmd): Add missing initialization for enums member.
+ Reorder members to match structure declaration to make it easier to
+ tell when one is missing.
+ * exec.c (exec_file_command): Fix problem where filename in malloc'd
+ memory is referenced after being freed.
+
+Sat Feb 3 03:26:21 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dwarfread.c (read_func_scope): Avoid GDB core dumps if
+ AT_name tag is missing.
+
+ * procfs.c (procfs_stopped_by_watchpoint): Fix logic when
+ FLTWATCH and FLTKWATCH are defined.
+
+ * remote.c (remote_read_bytes): Advance memaddr for transfers,
+ return number of bytes transferred for partial reads.
+
+ * top.c (init_signals): Reset SIGTRAP to SIG_DFL.
+
+Fri Feb 2 13:40:50 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * win32-nat.c (mappings): Add ppc registers.
+ (child_resume): Turn off step for ppc.
+
+Thu Feb 1 10:29:31 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config/powerpc/(cygwin32.mh, cygwin32.mt, tm-cygwin32.h,
+ xm-cygwin32.h): New.
+ * config/i386/(*win32*): Becomes *cygwin32*.
+ * configure.in (i[3456]86-*-win32*): Becomes i[3456]86-*-cygwin32.
+ (powerpcle-*-cygwin32): New.
+ * configure: Regenerate.
+ * win32-nat.c (child_create_inferior): Call CreateProcess
+ with the right program arg.
+
+Thu Feb 1 11:01:10 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/pa/tm-hppa.h (SOFT_FLOAT): Provide a default definition.
+
+Wed Jan 31 19:01:28 1996 Fred Fish <fnf@cygnus.com>
+
+ * serial.c: Change fputc/fputs/fprintf to _unfiltered forms.
+
+Wed Jan 31 18:36:27 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/sparc/xm-sun4os4.h (HAVE_TERMIOS): Remove.
+
+ * config/sparc/xm-sparc.h (HAVE_WAIT_STRUCT): Remove, never used.
+
+ * config/i386/nm-i386mach.h (CHILD_PREPARE_TO_STORE): Move to
+ here from config/i386/xm-i386mach.h, fix name.
+ * config/i386/nm-sun386.h: Ditto, from config/i386/xm-sun386.h.
+ * config/i386/nm-ptx4.h (CHILD_PREPARE_TO_STORE): Move to
+ here from config/i386/xm-ptx4.h.
+ * config/i386/nm-ptx4.h: Ditto, from config/i386/xm-ptx.h.
+ * config/i386/nm-symmetry.h: Ditto, from config/i386/xm-symmetry.h.
+ * config/m68k/nm-sun3.h: Ditto, from config/m68k/xm-sun3.h.
+ * config/sparc/nm-nbsd.h: Ditto, from config/sparc/xm-nbsd.h.
+ * config/sparc/nm-sun4os4: Ditto, from config/sparc/xm-sparc.h.
+
+ * config/sparc/nm-sun4sol2.h: New file, renamed from nm-sysv4.h.
+ (PRSVADDR_BROKEN): Move here from xm-sun4sol2.h.
+ * config/sparc/sun4sol2.mh (NAT_FILE): Update.
+
+Wed Jan 31 17:20:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * config/pa/tm-hppa.h (EXTRACT_RETURN_VALUE): Handle software
+ floating point correctly.
+ (STORE_RETURN_VALUE): Likewise.
+ * config/pa/tm-pro.h (SOFT_FLOAT): define.
+
+Wed Jan 31 13:34:52 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/i386/xm-linux.h (MMAP_BASE_ADDRESS, MMAP_INCREMENT):
+ Define to what should be reasonable values. However, apparently
+ a bug in linux mmap prevents mapped symbol tables from working.
+
+Tue Jan 30 18:26:19 1996 Fred Fish <fnf@cygnus.com>
+
+ * defs.h (errno.h>: Move #include closer to head of file to solve
+ obscure problem with systems that declare perror with const arg, in
+ both errno.h and stdio.h, and const is defined away by intervening
+ local include.
+
+Tue Jan 30 15:41:10 1996 Fred Fish <fnf@cygnus.com>
+
+ From Jon Reeves <reeves@zk3.dec.com>:
+ * i386-stub.c (getpacket): Change fprintf stream from "gdb" to stderr.
+ (mem_fault_routine): Fix misplaced volatile type qualifier in decl.
+
+Mon Jan 29 19:05:58 1996 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (diststuff): Make all-doc; diststuff target does not
+ exist in doc/Makefile.in.
+
+Mon Jan 29 18:44:57 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/m88k/xm-cxux.h (BP_HIT_COUNT): Remove, never used.
+
+Mon Jan 29 00:10:35 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * ch-valprint.c (calculate_array_length): New function to
+ determine the length of an array type.
+ (chill_val_print (case TYPE_CODE_ARRAY)): If the length of an
+ array type is zero, call calculate_array_length.
+
+ * gdbtypes.c (get_discrete_bounds (case TYPE_CODE_ENUM)): The
+ values may not be sorted. Scan all entries and set the real lower
+ and upper bound.
+
+Sun Jan 28 15:50:42 1996 Fred Fish <fnf@cygnus.com>
+
+ * config/xm-linux.h: Move include of solib.h and #define of
+ SVR4_SHARED_LIBS from here ...
+ * config/nm-linux.h: ...to here.
+
+Sat Jan 27 10:34:05 1996 Fred Fish <fnf@cygnus.com>
+
+ * configure.in (AC_CHECK_HEADERS): Check for sys/procfs.h.
+ Also check for gregset_t and fpregset_t types.
+ * configure: Regenerate.
+ * core-regset.c (sys/procfs.h): Only include if HAVE_SYS_PROCFS_H
+ is defined.
+ (fetch_core_registers): Turn into stub unless both HAVE_GREGSET_T
+ and HAVE_FPREGSET_T are defined. These changes allow systems
+ like linux that are migrating to /proc support to use a single
+ configuration for both new and old versions.
+
+ * config/i386/linux.mt: Note that this is now for both a.out and
+ ELF systems.
+ * config/i386/linux.mh (NATDEPFILES): Add solib.o, core-regset.o,
+ i386v4-nat.o
+ * config/i386/tm-linux.h (tm-sysv4.h): Include.
+ * config/i386/xm-linux.h (solib.h): Include
+ (SVR4_SHARED_LIBS): Define.
+ * i386v4-nat.c: Only compile if HAVE_SYS_PROCFS_H is defined.
+ (supply_gregset, fill_gregset): Compile if HAVE_GREGSET_T defined.
+ (supply_fpregset, fill_fpregset): Compile if HAVE_FPREGSET_T
+ defined.
+
+Fri Jan 26 13:48:14 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/sparc/xm-sparc.h (NEW_SUN_CORE): Remove, never used.
+ * config/i386/xm-sun386.h: Ditto.
+ * config/m68k/xm-sun2.h, config/m68k/xm-sun3.h: Ditto.
+
+Thu Jan 25 16:05:53 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * Makefile.in (INSTALLED_LIBS, CLIBS): Include @LIBS@.
+
+Thu Jan 25 09:22:15 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ From Greg McGary <gkm@gnu.ai.mit.edu>:
+ * dcache.c (dcache_peek, dcache_poke): Advance addr for
+ multi-byte I/O.
+
+Thu Jan 25 13:08:51 1996 Doug Evans (dje@cygnus.com)
+
+ * infrun.c (normal_stop): Fix test for shared library event.
+
+Thu Jan 25 03:26:38 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * configure.in (sparc64-*-*): Add default host configuration.
+ (sparc64-*-solaris2*): Add target configuration.
+ * configure: Regenerated.
+ * sparc/sp64sol2.mt: New file.
+
+Wed Jan 24 22:31:37 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * Makefile.in (RUNTEST): srcdir renamed to rootsrc.
+
+Wed Jan 24 15:42:24 1996 Tom Tromey <tromey@creche.cygnus.com>
+
+ * Makefile.in (lint): Close backquotes.
+
+Wed Jan 24 13:19:10 1996 Fred Fish <fnf@cygnus.com>
+
+ * NEWS: Make note of new record and replay feature for
+ remote debug sessions.
+ * serial.c (gdbcmd.h): Include.
+ (serial_logfile, serial_logfp, serial_reading, serial_writing):
+ Define here, for remote debug session logging.
+ (serial_log_command, serial_logchar, serial_write, serial_readchar):
+ New functions for remote debug session logging.
+ (serial_open): Open remote debug session log file when needed.
+ (serial_close): Close remote debug session log file when needed.
+ (_initialize_serial): Add set/show commands for name of remote
+ debug session log file.
+ * serial.h (serial_readchar): Declare
+ (SERIAL_READCHAR): Call serial_readchar().
+ (SERIAL_WRITE): Call serial_write().
+ (serial_close): Declare as extern.
+ (serial_logfile, serial_logfp): Declare.
+ * top.c (execute_command): Declare serial_logfp. Log user command
+ in remote debug session log if log file is open.
+ * remote-array.c (array_wait): #ifdef out echo to gdb_stdout.
+ (array_read_inferior_memory): Rewrite to fix memory overwrite bug.
+ * remote-array.c (SREC_SIZE): Remove, duplicates define in
+ monitor.h.
+ * remote-array.c (hexchars, hex2mem): Remove, unused.
+ * gdbserver/low-linux.c (store_inferior_registers): Remove
+ unnecessary extern declaration of registers[].
+ * gdbserver/Makefile.in (all): Add gdbreplay.
+ * gdbserver/gdbreplay.c: New file.
+ * gdbserver/README: Give example of recording a remote
+ debug session with gdb and then replaying it with gdbreplay.
+
+Tue Jan 23 18:02:35 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (rs6000_builtin_type): Make bool type unsigned.
+ (read_one_struct_field): Support boolean bitfields.
+ * c-valprint.c (c_val_print): Print booleans properly.
+
+Tue Jan 23 18:54:09 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-vxsparc.c (vx_convert_to_virtual, vx_convert_from_virtual):
+ Remove, never used.
+ * config/sparc/vxsparc.mt (TDEPFILES): Add remote-vxsparc.o.
+
+Tue Jan 23 14:36:05 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.c (parse_tuple): Error if invalid mode.
+
+ * value.h (COERCE_ARRAY): Don't coerce enums.
+ (COERCE_ENUM): Don't COERCE_REF.
+ (COERCE_NUMBER): New macro (same as COERCE_ARRAY then COERCE_ENUM).
+ * valops.c (value_assign): Only do COERCE_ARRAY if internalvar (let
+ value_cast handle it otherwise); do *not* COERCE_ENUM either way.
+ * valarith.c: Use COERCE_NUMBER instead od COEREC_ARRAY.
+ Add COERCE_REF before COERCE_ENUM.
+ * values.c (value_as_long): Simplify.
+
+ * valops.c (value_array): Create internalvar if !c_style_arrays.
+
+ * language.c (lang_bool_type): Add Fortran support.
+ * eval.c (OP_BOOL): Use LA_BOOL_TYPE.
+
+Tue Jan 23 13:08:26 1996 Jeffrey A Law (law@cygnus.com)
+
+ * symfile.c (auto_solib_add): Renamed from auto_solib_add_at_startup.
+ All references changed.
+ * breakpoint.c (bpstat_what): Add shlib_event to the class types.
+ Update state table. Reformat so that it's still readable.
+ When we hit the shlib_event breakpoint, set the calss of shlib_event.
+ (breakpoint_1): Add "shlib events" as a breakpoint type.
+ Print the shlib_event breakpoint like other breakpoints.
+ (create_solib_event_breakpoint): New function.
+ (breakpoint_re_set_one): Handle solib_event breakpoints.
+ * breakpoint.h (enum bytype): Add bp_shlib_event breakpoint type.
+ (enum bpstat_what_main_action): Add BPSTAT_WHAT_CHECK_SHLIBS
+ action.
+ (create_solib_event_breakpoint): Declare.
+ * infrun.c (wait_for_inferior): Handle CHECK_SHLIBS bpstat.
+ (normal_stop): Inform the user when the inferior stoped due
+ to a shared library event.
+ (_initialize_infrun): Add new set/show variable "stop-on-solib-events"
+ to control whether or not gdb continues the inferior or stops it when
+ a shared library event occurs.
+ * minsyms.c (lookup_minimal_symbol_solib_trampoline): New function.
+ * somsolib.c (TODO list): Update.
+ (som_solib_create_inferior_hook): Arrange for gdb to be notified
+ when significant shared library events occur.
+ * hppa-tdep.c (find_unwind_entry): No longer static.
+
+Tue Jan 23 09:00:48 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * printcmd.c (print_insn): Pass fprintf_unfiltered to
+ INIT_DISASSEMBLE_INFO.
+
+Mon Jan 22 16:59:40 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (remotebreak): New GDB variable.
+ (remote_break): New global.
+ (remote_interrupt): Send a break instead of ^C if remote_break.
+ * NEWS: Describe the new variable.
+
+Mon Jan 22 16:24:11 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-tdep.c (_initialize_sparc_tdep): Always use print_insn_sparc.
+
+Fri Jan 19 07:19:38 1996 Fred Fish <fnf@cygnus.com>
+
+ * hp300ux-nat.c (getpagesize): Remove unused function
+ fetch_core_registers.
+ (hp300ux_core_fns): Remove, is unused.
+ (_initialize_core_hp300ux): Remove, is unused.
+ (gdbcore.h): Remove #include, no longer needed.
+
+Fri Jan 19 00:59:53 1996 Jeffrey A Law (law@cygnus.com)
+
+ * rs6000-nat.c (exec_one_dummy_insn): Rework to avoid
+ ptrace bug in aix4.1.3 on the rs6000.
+
+Wed Jan 17 13:22:27 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-hms.c (hms_ops): Add value for to_thread_alive.
+ * remote-nindy.c (nindy_ops): Ditto.
+ * remote-udi.c (udi_ops): Ditto.
+
+Tue Jan 16 18:00:35 1996 James G. Smith <jsmith@cygnus.co.uk>
+
+ * remote-mips.c (pmon_opn, pmon_wait, pmon_makeb64, pmon_zeroset,
+ pmon_checkset, pmon_make_fastrec, pmon_check_ack,
+ pmon_load_fast): New functions. Support for the PMON monitor world.
+ (common_open): New function to merge support for different monitors.
+ (mips_open): Use common_open().
+ (mips_send_command): New function.
+ (mips_send_packet): Scan out-of-sequence packets.
+ (mips_enter_debug, mips_exit_debug): New functions.
+ (pmon_ops): New target definition structure.
+
+Tue Jan 16 11:22:58 1996 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (CLIBS): Add LIBS to allow libraries to be
+ specified on the make command line (via make LIBS=xxx).
+
+
+Fri Jan 12 21:41:58 1996 Jeffrey A Law (law@cygnus.com)
+
+ * symtab.c (find_pc_symtab): Don't lose if OBJF_REORDERED
+ is set but there are no psymtabs.
+
+Fri Jan 12 15:56:12 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * dsrec.c (load_srec): Remove unused variable.
+ * monitor.c (monitor_expect): Don't expect a ^C to echo.
+ * serial.c (serial_open): Add parallel interface.
+ * sh3-rom.c (parallel, parallel_in_use): New.
+ (sh3_load): If parallel_in_use, download though the
+ parallel port.
+ (sh3_open): Open parallel port if specified.
+ (sh3_close): New function.
+ (_inititalize_sh3): Add sh3_close hook and documentation.
+ * monitor.c (monitor_close): Export.
+ * monitor.h (monitor_close): Add prototype.
+
+Fri Jan 12 13:11:42 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Wilfried Moser <wilfried.moser@aut.alcatel.at>:
+ * remote.c (remotetimeout): New GDB variable, use to set the
+ remote timeout for reading.
+
+
+Fri Jan 12 07:14:27 1996 Fred Fish <fnf@cygnus.com>
+
+ * lynx-nat.c, irix4-nat.c, sparc-nat.c: Include gdbcore.h
+ to get "struct core_fns" defined.
+ * Makefile.in (lynx-nat.o, irix4-nat.o, sparc-nat.o):
+ Are dependent upon gdbcore_h.
+
+Thu Jan 11 23:13:24 1996 Per Bothner <bothner@cygnus.com>
+
+ * symfile.c (decrement_reading_symtab): New function.
+ * symfile.c, symtab.h (currently_reading_symtab): New variable.
+ * symfile.c (psymtab_to_symtab): Adjust currently_reading_symtab.
+ * gdbtypes.c (check_typedef): Don't call lookup_symbol if
+ currently_reading_symtab (since that could infinitely recurse).
+
+Thu Jan 11 17:21:25 1996 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (read_struct_type): Trivial simplification.
+
+ * stabsread.c (define-symbol): Use invisible references
+ for TYPE_CODE_SET and TYPE_CODE_BITSTRING too.
+ * valops.c (call_function_by_hand): Likewise.
+ * eval.c (evaluate_subexp_standard): When known, use the formal
+ parameter type as the expected type when evaluating arg expressions.
+ * ch-lang.c (evaluate_subexp_chill): Likewise (for MULTI_SUBSCRIPT).
+
+
+Wed Jan 10 16:08:49 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * configure.in, configure: Recognize rs6000-*-aix4*.
+ * config/powerpc/xm-aix.h: Reduce to include "xm-aix4.h".
+ * config/rs6000/aix4.mh (XM_FILE): Point to xm-aix4.h.
+ * config/rs6000/xm-aix4.h: New file.
+ * config/xm-aix4.h: New file.
+
+Wed Jan 10 11:25:37 1996 Fred Fish <fnf@cygnus.com>
+
+ From Wilfried Moser <wilfried.moser@aut.alcatel.at>:
+ * gdbserver/low-linux.c: New file.
+ * remote.c (remote_read_bytes): Fix aborts on larger packets.
+
+ * config/i386/linux.mh (GDBSERVER_DEPFILES, GDBSERVER_LIBS):
+ Define.
+ * stabsread.c (define_symbol): If register value is too large,
+ tell what it is and what max is.
+
+
+Tue Jan 9 09:33:53 1996 Jeffrey A Law (law@cygnus.com)
+
+ * hpread.c (hpread_build_psymtabs): Finish Jan 4th
+ enum namespace -> enum_namespace change.
+
+Tue Jan 9 04:44:47 1996 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * ch-exp.c (parse_primval): In case ARRAY, add missing
+ FORWARD_TOKEN ().
+
+Mon Jan 8 13:29:34 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-mips.c (mips_receive_header): Recognize \012 instead
+ of \n, but write \n when program sends a \012.
+ * ser-mac.c (mac_input_buffer): Increase size of buffer.
+
+Mon Jan 8 12:00:40 1996 Jeffrey A Law (law@cygnus.com)
+
+ * infptrace.c (initialize_infptrace): Move function out of
+ #ifdef conditional; put code within the function inside an
+ #ifdef conditional.
+
+ * buildsym.c (end_symtab): Remove sort_pending and sort_linevec
+ arguments. Sorting is now dependent on OBJF_REORDERED. All
+ callers/references changed.
+ * dbxread.c (read_ofile_symtab): Correctly determine value for
+ last_source_start_addr for reordered executables.
+ (process_one_symbol): Handle N_FUN with no name as an end of
+ function marker.
+ * partial-stab.h (case N_FN, N_TEXT): Don't assume CUR_SYMBOL_VALUE
+ is the high text address for a psymtab.
+ (case N_SO): Likewise.
+ (case N_FUN): Handle N_FUN with no name as an end of function
+ marker.
+ * minsyms.c (lookup_minimal_symbol_by_pc): Examine all symbols
+ at the same address rather than a random subset of them.
+ * coffread.c (coff_symfile_init): Set OBJF_REORDERED.
+ * elfread.c (elf_symfile_init): Similarly.
+ * somread.c (som_symfile_init): Similarly.
+ * xcoffread.c (xcoff_symfile_init): Similarly.
+
+Fri Jan 5 17:46:01 1996 Stu Grossman (grossman@cygnus.com)
+
+ * stack.c (print_stack_frame print_frame_info) symmisc.c
+ (dump_symtab): Change RETURN_MASK_ERROR to RETURN_MASK_ALL so
+ that catch_errors doesn't get blindsided by QUIT and lose the
+ cleanup chain. This fixes a problem where ^C while in a
+ user-defined command sometimes leaves instream NULL and causes a
+ segfault in command_loop.
+
+Fri Jan 5 13:59:16 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * configure.in, configure: Add `-ldl -lw' for Solaris linking.
+
+Fri Jan 5 12:02:00 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config/sh/sh.mt, config/powerpc/*.mt, config/pa/hppapro.mt,
+ config/m68k/monitor.mt, config/h8500/h8500.mt, config/h8300/h8300.mt:
+ srec.o renamed to dsrec.o.
+
+Thu Jan 4 16:04:54 1996 Stu Grossman (grossman@cygnus.com)
+
+ * breakpoint.c (remove_breakpoint): Change error to warning so
+ that hardware watchpoint removal problems won't leave breakpoint
+ traps in the target.
+ * remote-e7000.c (e7000_insert_breakpoint,
+ e7000_remove_breakpoint): Use e7000 based breakpoints, not memory
+ breakpoints.
+ * (e7000_wait): Adjust PC back by two when we see a breakpoint to
+ compensate for e7000 maladjustment.
+ * sparcl-tdep.c (sparclite_check_watch_resources): Fix logic bug
+ which prevented hardware watchpoints from working.
+
+Thu Jan 4 10:44:17 1996 Fred Fish <fnf@cygnus.com>
+
+ * infptrace.c (udot_info): New function.
+ (PT_*): Define each individually if that one is not defined.
+ * rs6000-nat.c (kernel_u_size): New function
+ Include <sys/user.h> for "struct user"
+ * alpha-nat.c (kernel_u_size): New function.
+ Include <sys/user.h> for "struct user"
+ * sparc-nat.c (kernel_u_size): New function.
+ Include <sys/user.h> for "struct user"
+ * i386b-nat.c (kernel_u_size): New function.
+ * i386v-nat.c (kernel_u_size): New function.
+ * config/i386/nm-fbsd.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/i386/nm-linux.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/sparc/nm-sun4os4.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/alpha/nm-osf2.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+ * config/rs6000/nm-rs6000.h (KERNEL_U_SIZE): Define.
+ (kernel_u_size): Declare.
+
+Thu Jan 4 11:00:01 1996 steve chamberlain <sac@slash.cygnus.com>
+
+ * mdebugread.c (mylookup_symbol): enum namespace becomes
+ enum_namespace type.
+ * symfile.c (add_psymbol_to_list)
+ (add_psymbol_addr_to_list): Ditto.
+ * symtab.c (lookup_partial_symbol): Ditto.
+ (lookup_symbol): Ditto.
+ (lookup_block_symbol): Ditto.
+ * win32-nat.c (handle_load_dll): Use incoming dll base.
+ (child_wait): Catch DLL load errors.
+ (create_child_inferior): Translated between paths correctly.
+
+Wed Jan 3 23:13:53 1996 Fred Fish <fnf@cygnus.com>
+
+ * i386v4-nat.c (supply_gregset, fill_gregset): Subtract NUM_FREGS
+ from NUM_REGS to get number of general registers that we care about.
+ * config/i386/tm-i386.h (REGISTER_BYTES): Define in terms
+ of number of general regs and number of floating point regs.
+
+Wed Jan 3 19:49:54 1996 steve chamberlain <sac@slash.cygnus.com>
+
+ * config/i386/tm-win32.h (IN_SOLIB_CALL_TRAMPOLINE): New.
+ (SKIP_TRAMPOLINE_CODE): New.
+ * config/i386/xm-win32.h (CANT_FORK): Deleted.
+ (SLASH*) Changed to use unix style slash.
+ * symtab.h (namespace enum): becomes typedef to avoid namespace
+ collision in C++.
+ * infcmd.c (path_command): Use empty string if PATH name not set.
+ * i386-tdep.c (skip_trampoline_code): New function.
+ * srec.c: Renamed dsrec.c to avoid filename collision.
+ * Makefile.in: Cope with renaming.
+
+Wed Jan 3 13:09:04 1996 Fred Fish <fnf@cygnus.com>
+
+ * symmisc.c (print_objfile_statistics): Print memory use statistics
+ for objfile psymbol, symbol, and type obstacks.
+
+Tue Jan 2 13:41:14 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/mips/nm-irix5.h: Restore.
+ (TARGET_HAS_HARDWARE_WATCHPOINTS, etc): Define as for Irix 4;
+ from Lee Iverson <leei@ai.sri.com>.
+ * config/mips/irix5.mh (NAT_FILE): Use nm-irix5.h.
+ * config/mips/irix[345].mh (MUNCH_DEFINE): Remove.
+
+For older changes see ChangeLog-95
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/contrib/gdb/gdb/ChangeLog-93 b/contrib/gdb/gdb/ChangeLog-93
new file mode 100644
index 0000000..463154d
--- /dev/null
+++ b/contrib/gdb/gdb/ChangeLog-93
@@ -0,0 +1,7597 @@
+Fri Dec 31 14:33:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * nindy-share/nindy.c: Fix order of arguments to store_unsigned_integer
+ (second and third arguments were reversed).
+ (say): Use varargs.
+
+Fri Dec 31 12:13:47 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote-mips.c: Add timeout parameter to mips_request and
+ mips_receive_packet.
+ (callers): pass in mips_receive_wait except mips_initialize (where
+ we use it to clean up the kludge where we had been changing
+ mips_receive_wait temporarily) and mips_wait (where we pass in
+ -1 for no timeout).
+
+Fri Dec 31 14:33:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stack.c (print_block_frame_locals): Also print LOC_BASEREG variables.
+
+Fri Dec 31 06:55:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (find_methods): Call fprintf_symbol_filtered with DMGL_ANSI.
+
+Thu Dec 30 10:16:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * values.c (unpack_long): Fix garbled error message.
+
+ * remote-mips.c (mips_error): New function.
+ * remote-mips.c: Use it instead of error() most places.
+ * remote-mips.c (mips_receive_packet): New arg throw_error.
+ (mips_initialize): Use it not catch_errors.
+ * defs.h: Declare error_pre_print and warning_pre_print here...
+ * main.c: ...not here.
+
+ * breakpoint.c (breakpoint_chain): Make static.
+ * breakpoint.c, breakpoint.h (frame_in_dummy): New function.
+ * stack.c (print_frame_info): Use it.
+
+Thu Dec 30 07:41:36 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * exec.c (add_to_section_table): Check for SEC_ALLOC instead of
+ SEC_LOAD to handle .bss segments properly.
+
+Thu Dec 30 10:16:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Enable code which assumes that if
+ we jump into the prologue from another function, then it was a
+ subroutine call. #if 0 AT_FUNCTION_START; the above code should
+ take care of this case.
+
+Wed Dec 29 12:32:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valprint.c (val_print_string): Change chunksize from 200
+ to 8.
+
+ * symfile.c (generic_load): If no arguments, get file name
+ from get_exec_file.
+
+ * c-exp.y: Revert Kung's change. "..." is not a type, and the
+ change caused "p (...)0" to dump core.
+ * gdbtypes.c (check_stub_method): Don't pass "..." to
+ parse_and_eval_type. This should fix the bug which Kung was
+ trying to fix.
+
+ * stabsread.c (define_symbol): If we choose not to combine
+ two symbols, don't just ignore the second (LOC_REGISTER) one.
+ * printcmd.c (print_frame_args): If we have a LOC_ARG and a
+ LOC_REGISTER, use the LOC_ARG not the LOC_REGISTER.
+
+Tue Dec 28 15:08:00 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * solib.c (DEBUG_BASE): Remove macro and all references.
+ * solib.c (debug_base_symbols): Add array of symbols to lookup.
+ * solib.c (IGNORE_FIRST_LINK_MAP_ENTRY): Add macro.
+ * solib.c (look_for_base, locate_base): Use debug_base_symbols.
+ * solib.c (find_solib): Use IGNORE_FIRST_LINK_MAP_ENTRY.
+
+Tue Dec 28 12:06:57 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * c-exp.y : fix grammar to parse ellipsis (...)
+
+Mon Dec 27 18:42:14 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stabsread.c (read_type): fix problem when reading static member
+ of a class. caused by change to allow :: inside template
+ instantiated name.
+
+Mon Dec 27 11:07:05 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h: Expand on comments for TYPE_CODE_BITSTRING and
+ TYPE_CODE_STRING a bit.
+
+ * m68k-tdep.c (m68k_skip_prologue, m68k_find_saved_regs):
+ Allow pea %fp; move.l %sp, %fp instead of link instruction to
+ set up the new frame.
+
+ * main.c (init_main): Change "set remotedebug" back to var_zinteger
+ from var_boolean.
+
+ * c-exp.y (yylex): Don't try to deal with nested types.
+
+ * cp-valprint.c (cplus_print_value): Call check_stub_type on
+ TYPE_BASECLASS (type, i) before we look at its name.
+
+ * dbxread.c: Move default definition of GCC_COMPILED_FLAG_SYMBOL
+ from here . . .
+ * symtab.h: . . . to here.
+ * dbxread.c (record_minimal_symbol): Move check for gcc{,2}_compiled.
+ and __gnu_compiled* from here . . .
+ * minsyms.c (prim_record_minimal_symbol_and_info): . . . to here.
+ * minsyms.c (prim_record_minimal_symbol): Call
+ prim_record_minimal_symbol_and_info rather than duplicating code.
+ * minsyms.c, symtab.h (prim_record_minimal_symbol{,_and_info}),
+ coffread.c (record_minimal_symbol),
+ xcoffread.c (RECORD_MINIMAL_SYMBOL), callers: Add objfile parameter.
+
+Sun Dec 26 20:44:02 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * dbxread.c (process_one_symbol): Handle stabs-in-som just like
+ stabs-in-elf.
+ (pastab_build_psymtabs): Likewise.
+
+ * hppa-tdep.c: Change all comments to reference %r3 or frame
+ pointer rather than %r4.
+ (frame_chain, skip_prologue, dig_rp_from_stack): Handle %r3 as the
+ frame pointer.
+
+ * config/pa/tm-hppa.h (FP_REGNUM): Define as %r3.
+ (FIND_FRAME_SAVED_REGS): Handle %r3 as frame pointer.
+ (CALL_DUMMY): Likewise.
+
+Sun Dec 26 16:59:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * exec.c (exec_file_command): If error occurs after we have opened
+ exec_bfd but before we call push_target, make sure to close exec_bfd.
+
+ * infrun.c (wait_for_inferior): Remove confusing and inaccurate
+ stuff about subroutine calls, return, etc., from comment which
+ says "We've wandered out of the step range.".
+
+Sun Dec 26 09:18:10 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): When checking whether the line has
+ changed, check the symtab as well.
+
+Sun Dec 26 09:18:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.c (force_to_range_type): Use switch statement.
+ complain() not warning() if the TYPE_CODE isn't one we know how to
+ deal with gracefully. Use builtin_type_int not
+ lookup_fundamental_type (the objfile we passed to
+ lookup_fundamental_type was sometimes NULL).
+
+ * valops.c (call_function_by_hand, push_word), defs.h (push_word),
+ convex-xdep.c, m88k-nat.c, i386m3-nat.c, mips-tdep.c, mipsm3-nat.c,
+ ns32km3-nat.c, remote-bug.c, m88k-tdep.c, remote-hms.c, remote-mips.c,
+ config/gould/tm-np1.h, hppa-tdep.c (hppa_fix_call_dummy), remote-vx.c:
+ Use REGISTER_SIZE, unsigned LONGEST, and
+ {store,extract}_unsigned_integer, instead of sizeof
+ (REGISTER_TYPE) and REGISTER_TYPE.
+ * All tm.h files: Change REGISTER_TYPE to REGISTER_SIZE.
+ * hppa-tdep.c (pa_print_fp_reg): Remove unused variable val.
+
+ * Makefile.in (ALLDEPFILES): Remove i386ly-nat.c and m68kly-nat.c.
+ Add lynx-nat.c.
+
+Sat Dec 25 20:05:41 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (init_extra_frame_info): Correctly adjust the base
+ of the current frame when "fromleaf" is true. Do not adjust the
+ frame base of the innermost frame if it is a leaf function.
+
+Sat Dec 25 13:39:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): Only combine a p/r pair into a
+ LOC_REGPARM if REG_STRUCT_HAS_ADDR.
+
+Sat Dec 25 09:50:29 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (value_struct_elt): Check for (value)-1 return from
+ search_struct_method.
+
+Sat Dec 25 09:50:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h: Move definitions of TARGET_*_BIT after include of tm.h.
+ The old way (using #undef in tm.h) was ugly and asking for
+ trouble, because it makes it possible for some file to use the
+ wrong definition. Move definition of HOST_CHAR_BIT after definition
+ of TARGET_CHAR_BIT.
+ * config/alpha/tm-alpha.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/z8k/tm-z8k.h: Don't undef TARGET_*_BIT
+ before defining them.
+
+ * mdebugread.c: Change the builtin_type_* in this file to
+ mdebug_type_* and make them static. Use TYPE_CODE_ERROR for
+ complex and float decimal.
+
+ * printcmd.c (disassemble_command): Call wrap_here between printing
+ address and printing instruction.
+
+Fri Dec 24 14:23:57 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (read_type): Don't fall through 'S' case (the case it
+ was falling though happened to do the right thing ("break;") but that
+ is hardly a good thing to assume).
+
+Tue Dec 21 13:32:02 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y (match_dollar_tokens): Fix off-by-one bug.
+ * ch-lang.c (chill_is_varying_struct), ch-lang.h: New function.
+ * ch-lang.c (chill_printstr): Use double quotes, not single quotes.
+ * ch-typeprint.c (chill_type_print_base): Handle TYPE_CODE_BITSTRING.
+ Improve printing of TYPE_CODE_STRING, TYPE_CODE_SET, and
+ TYPE_CODE_STRUCT (including checking chill_is_varying_struct).
+ Print TYPE_DUMMY_RANGE by printing its TYPE_TARGET_TYPE.
+ Handle TYPE_CODE_ENUM.
+ * ch-valprint.c (chill_val_print): Handle TYPE_CODE_BITSTRING.
+ For TYPE_CODE_STRING, never print address. Handle VARYING strings.
+ * gdbtypes.c (force_to_range_type): New.
+ * gdbtypes.c (create_set_type): Make work, following Chill layout.
+ * gdbtypes.h (TYPE_LOW_BOUND, TYPE_HIGH_BOUND, TYPE_DUMMY_RANGE): New.
+ * stabsread.c (read_type): Distinguish string and bitstring from
+ char-array and set.
+ * valarith.c (value_subscript), valops.c (value_coerce_array):
+ Handle STRINGs as well as ARRAYs.
+ * valarith.c (value_bit_index): Fix think. Use new macros.
+
+
+Fri Dec 17 10:45:32 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab (decode_line_1): fix a bug when position char is not
+ set correctly.
+ * c-valprint (c_val_print): handle vtbl printing when vtbl is not
+ set up yet.
+
+Thu Dec 16 16:46:01 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-tdep.c (read_next_frame_reg): If SIGFRAME_REG_SIZE is not
+ defined, define it as 4.
+
+Thu Dec 16 13:08:01 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/m68k/nm-hp300bsd.h: Correctly identify 4.3BSD vs 4.4BSD.
+
+ * config/m68k/tm-hp300bsd.h (REMOTE_BPT_VECTOR): Define.
+
+ * config/m68k/tm-m68k.h (REMOTE_BPT_VECTOR): Allow targets to
+ override.
+ (REMOTE_BREAKPOINT): Likewise.
+
+Thu Dec 16 09:14:58 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hp_function_type): Correctly handle
+ pass-by-value structures > 64bits in size.
+ (process_one_debug_symbol): Likewise.
+
+Mon Dec 13 20:17:39 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Implement support for Chill POWERSETs.
+ * ch-exp.y (operand_2): Implement 'Element IN PowerSet'.
+ * ch-typeprint.c (chill_type_print_base): Handle POWERSETs.
+ * ch-valprint.c (chill_val_print): Handle TYPE_CODE_SET.
+ * eval.c (evaluate_subexp): Implement BINOP_IN.
+ * expression.h (enum exp_opcode): Added BINOP_IN.
+ * gdbtypes.c (create_set_type), gdbtypes.h: New function.
+ * stabsread.c (read_type): If 'S', create a set type.
+ * valarith.c (value_bit_index, value_in), value.h: New functions,
+ for indexing in SETs.
+
+Mon Dec 13 06:42:37 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symfile_init): Check for the existance of stabs
+ after DBX_TEXT_SECT has been initialized.
+
+Tue Nov 23 17:29:28 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/h8300/tm-h8300.h (BREAKPOINT): Insn changed to sleep.
+ (DECP_PC_AFTER_BREAK): Now is 0.
+ * config/h8500/tm-h8500.h (REGISTER_BYTES, REGISTER_BYTE,
+ REGISTER_NAMES): update to new view. (INIT_EXTRA_FRAME_INFO): No
+ extra frame info now.
+ * config/sh/sh.h (NOP): Define NOP insn.
+ * config/z8k/tm-z8k.h (BIG): is now sim_z8001_mode.
+ * config/z8k/z8ksim.mt (TDEPFILES): Add remote-sim.o to list.
+ * ser-go32.c: Lint. (strncasecmp): Removed, now in libiberty.
+ (go32_readchar): Special handling for faster polling. (async
+ structure): Volatile.
+ * h8300-tdep.c (print_register_hook): Allocate and use the right
+ number bytes for the raw register.
+ * h8500-tdep.c (regoff, frame_find_saved_reg, examine_prologue):
+ deleted. (h8500_register_size, h8500_register_virtual_type, ):
+ Use new way of counting registers.
+ * remote-e7000.c (echo_index): deleted. (expect): Better handling
+ of user interrupts. (expect_prompt): Remove never used log file
+ support. (want, want_nopc): Add support for H8/300H.
+ (fetch_regs_from_dump): Treat \r and \n as whitespace.
+ (e7000_drain): Send an "end" command before waiting for output to
+ stop. (e7000_wait): Cope with H8/300H, better handling of user
+ interrupts. (why_stop, expect_n, sub2_from_pc): New function.
+ * remote-utils.c (gr_load_image): call fflush and QUIT more regularly.
+ * utils.c (notice_quit): New function for polling for user interrupts.
+
+Fri Dec 10 15:53:56 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * stabsread.c (read_array_type): Allow negative array bounds,
+ without interpreting that to mean "adjustable."
+ * ch-valprint.c (chill_val_print): Handle RANGE types.
+ * ch-typeprint.c (chill_type_print_base): Handle BOOL.
+ Handle variant records. Handle RANGE types.
+
+Tue Dec 7 15:41:32 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/mips/idt.mt: Use tm-idt.h instead of tm-bigmips.h.
+ * config/mips/idtl.mt: Use tm-idtl.h instead of tm-mips.h.
+ * config/mips/tm-idt.h, config/mips/tm-idtl.h: New files; use
+ different BREAKPOINT value for IDT.
+
+ * mipsread.c: Include bfd.h and coff/sym.h.
+
+Mon Dec 6 16:34:10 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * ser-unix.c (set_tty_state): set the rest of the terminal state
+ pieces.
+
+Mon Dec 6 12:01:37 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Recognize mips* for all mips targets.
+ (mips*el-*-elf*, mips*-*-elf*): New targets; use idt and idtl.
+
+ Added Irix 5 support.
+ * configure.in (mips-sgi-irix5*): New host and target. Use irix5
+ for both.
+ * config/mips/irix5.mh, config/mips/irix5.mt,
+ config/mips/xm-irix5.h, config/mips/nm-irix5.h,
+ config/mips/tm-irix5.h, irix5-nat.c: New files for Irix 5 support.
+ * mdebugread.c: New file, split out of mipsread.c. Added
+ elfmdebug_build_psymtabs routine. Added some checks on external
+ symbols. Changed code to keep ecoff_debug_info and
+ ecoff_debug_swap structs in the psymtab and in global pointers
+ rather than retrieving them from the bfd. Also changed to keep
+ the pending list with the psymtab rather than the objfile (each
+ psymtab for a single objfile points to the same pending list).
+ * mipsread.c: Bulk of file moved into mdebugread.c, leaving just
+ the sym_fns.
+ * Makefile.in (SFILES): Added mdebugread.c.
+ (OBS): Added mdebugread.o.
+ (mdebugread.o): New target.
+ * symfile.h: Declare mdebug_build_psymtabs and
+ elfmdebug_build_psymtabs.
+ * elfread.c (struct elfinfo): Added mdebugsect field.
+ (elf_locate_sections): Remember location of .mdebug section.
+ (elf_symfile_read): Call elfmdebug_build_psymtabs on .mdebug
+ section.
+ * infrun.c (AT_FUNCTION_START): Set to 0 if not already defined.
+ (wait_for_inferior): Use AT_FUNCTION_START if it is defined to see
+ if PC is at the start of a function.
+ * mips-tdep.c (read_next_frame_reg): Use SIGFRAME_REG_SIZE, and
+ give it a default definition.
+ (mips_skip_prologue): Skip instructions which initialize $gp
+ register.
+ (in_sigtramp): New procedure, moved in from mipsread.c.
+ * config/mips/tm-mips.h: Declare in_sigtramp.
+
+ * serial.h (serial_fdopen): Make parameter const to match
+ function definition.
+
+Fri Dec 3 14:20:43 1993 Stu Grossman (grossman at cygnus.com)
+
+ * config/mips/irix4.mh: Enable ser-tcp.o.
+
+Tue Nov 30 15:24:24 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (check): Do not use subdir_do, so that
+ TARGET_FLAGS_TO_PASS is used correctly.
+
+Mon Nov 29 16:10:38 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386-nlmstub.c: Undo I/O redirection changes by Tom Lord.
+ These definitely won't work under Netware.
+
+Mon Nov 29 15:34:58 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stabsread.c(read_struct_field): Fix the check when getting to
+ member functions.
+
+Mon Nov 29 16:48:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ gcc -Wall -O lint:
+ * mips-tdep.c (heuristic_proc_desc): Initialize reg30 to avoid
+ warning. Unnest comment.
+ (init_extra_frame_info): Remove unused variable mask.
+ (MASK): Fully parenthesize.
+ (mips_push_dummy_frame): Remove unused variable val.
+ (mips_skip_prologue): Remove unused variables f and b.
+
+Mon Nov 29 12:23:25 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_symbol, parse_partial_symbols): Do not create
+ (partial) symbols for opaque struct definitions.
+
+Mon Nov 29 11:36:57 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386ly-tdep.c (i386lynx_saved_pc_after_call): Change call_inst
+ to unsigned char to avoid domain warning for some values.
+
+Mon Nov 22 23:42:59 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-e7000.c (e7000_wait): Cope with H8/300 register dump.
+ * config/h8300/h8300hms.mt: Add remote-e7000.
+
+Mon Nov 22 11:03:45 1993 Fred Fish (fnf@cygnus.com)
+
+ Merged changes from kev@spuds.geg.mot.com (Kevin A. Buettner):
+ * gdb/config/m88k/delta88.mh (NATDEPFILES): Added corelow.o and
+ coredep.o to this list.
+ * gdb/m88k-nat.c (m88k_register_u_addr): Avoid error when passed
+ the number for an M88110 extended register by just returning the
+ address of r0.
+
+Sat Nov 20 09:20:51 1993 Fred Fish (fnf@rtl.cygnus.com)
+
+ * go32-xdep.c (re_comp, re_exec): Remove stubs now that gdb
+ always uses it's own version of regex.
+
+Fri Nov 19 18:23:19 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * valops.c(value_struct_elt_for_reference): enhance search operator in
+ c++.
+ * symtab.c(decode_line_1): same as above.
+
+Fri Nov 19 15:08:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): Add comment about use of
+ return_to_top_level directly instead of error. Add comment saying
+ that the '' should not be needed--that the completer should be fixed.
+
+Fri Nov 19 11:00:33 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab.c(decode_line_1): fix the inconsistency of setting
+ breakpoint with '' or without them. The '' is needed when you
+ want name completion.
+
+Thu Nov 18 08:25:50 1993 Fred Fish (fnf@cygnus.com)
+
+ * valprint.c (val_print_string): When looking for a null
+ terminator compare current bufsize to fetchlimit to determine
+ when to stop, instead of computing buffer+fetchlimit which
+ may overflow for very large limits (like "unlimited").
+
+Wed Nov 17 18:23:09 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * eval.c(evaluate_subexp): to use unified search so type conversion
+ operator works in calling method.
+ * valarith.c(value_x_binop, value_x_unop): same as above.
+ * valops.c(search_struct_method): same as above.
+
+Wed Nov 17 18:47:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mipsread.c: Change use of ECOFF information to correspond to
+ changes in bfd/libecoff.h.
+ (mipscoff_symfile_offsets): Made static.
+
+Wed Nov 17 09:43:31 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * valops.c (typecmp): improve prototype matching when calling
+ a method. Make 'p (*(ostream *) &cout) << "lll" ' to work.
+ * eval.c(evalute_subexp): fix operator search problem when call
+ like p x.'operator+'(i).
+
+Tue Nov 16 17:15:03 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386ly-nat.c, i386lynx-nat.c, m68kly-nat.c: Remove. Move
+ common code into lynx-nat.c.
+ * lynx-nat.c: New module. Contains portable code for Lynx native
+ stuff (mostly ptrace related).
+ * config/i386/i386lynx.mh (NATDEPFILES): i386ly-nat.o -> lynx-nat.o
+ * config/m68k/m68klynx.mh (NATDEPFILES): i386ly-nat.o -> lynx-nat.o
+
+ * config/nm-lynx.h, config/tm-lynx.h: New files to contain
+ non-architecture specific native and target defs.
+ * config/i386/nm-i386lynx.h, config/i386/tm-i386lynx.h,
+ config/m68k/nm-m68klynx.h, config/m68k/tm-m68klynx.h: Move all
+ (arch) portable stuff into ../{tm nm}-lynx.h.
+
+Tue Nov 16 13:33:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (gdb_mangle_name): Only assume that the physname is
+ the entire mangled name if it looks like the mangled name of a
+ constructor. Needed for testsuite to work with GCC 2.4.5.
+
+ * a68v-nat.c: Replace with new version from Troy Rollo. The
+ version I am replacing appears to be an old copy of sun3-nat.c.
+ * dstread.c (dst_symfile_read): Replace sort_all_symtab_syms call
+ with loop.
+
+ * Makefile.in (TAGS): Depend on TAGFILES_{NO,WITH}_SRCDIR.
+
+ * Makefile.in: (HFILES,TAGFILES): Split into _WITH_SRCDIR and
+ _NO_SRCDIR versions.
+ (TAGS): Only add srcdir to TAGFILES_NO_SRCDIR.
+ (This is part of a long saga involving me putting srcdir on
+ everything (perhaps for now-obsolete reasons, I forget), Rich
+ removing the srcdir from everything, Stu putting it back some
+ places for Sun make, and me just now getting around to fixing
+ `make TAGS' again).
+
+Mon Nov 15 12:29:10 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stack.c(print_frame_info): print demangled function name
+ ansi style.
+
+Mon Nov 15 14:32:29 1993 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-e7000.c: New file to cope with the Hitachi E7000 ICE.
+ * remote-utils.c, remote-utils.h (gr_load_image): New function to
+ download to target.
+ * h8300-tdep.c, h8500-tdep.c, remote-z8k.c, sh-tdep.c z8k-tdep.c
+ (sim_load): delete.
+ * remote-sim.c (gdbsim_load): Use gr_load_image, rather than
+ sim_load.
+ * config/sh/sh.mt: Add remote-e7000
+
+Mon Nov 15 11:38:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/linux.mh: Remove XM_CLIBS, TERMLIB, SYSV_DEFINE, and
+ REGEX.
+ * config/i386/xm-linux.h: Don't include xm-i386v.h. Define
+ HOST_BYTE_ORDER ourselves. Define HAVE_TERMIOS not HAVE_TERMIO.
+ Define NEED_POSIX_SETPGID. Include unistd.h.
+
+Mon Nov 15 12:29:10 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab.c(gdb_mangle_name): fix the problem with constructor
+ name mangling.
+
+Mon Nov 15 11:38:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h: Add TYPE_FLAG_TARGET_STUB.
+ * gdbtypes.c (check_stub_type): On TYPE_FLAG_TARGET_STUB, do
+ what cleanup_undefined_types does for arrays, except we clear
+ TYPE_FLAG_TARGET_STUB if we fix up the type.
+ * stabsread.c (cleanup_undefined_types): Add comments about how
+ doing arrays here is no longer the clean way to do it.
+ (read_array_type): Set TYPE_FLAG_TARGET_STUB as well as calling
+ add_undefined_type.
+ * c-typeprint.c, ch-typeprint.c: Move call to check_stub_type
+ outside switch so it happens for all type codes.
+ * cp-valprint.c (cp_print_value_fields): Recurse to val_print,
+ instead of c_val_print, so that check_stub_type gets called.
+
+ * gdbtypes.h, gdbtypes.c, m2-lang.c, ch-lang.c, c-lang.c: Remove
+ TYPE_FLAG_SIGNED. It was inconsistently set, never checked
+ (except in recursive_dump_type), and is pointless.
+
+Mon Nov 15 00:40:38 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symfile_init): Look for the $TEXT$ section rather
+ than the .text section.
+
+Sun Nov 14 00:28:13 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c: Remove #if 0'd dbx_class_complaint. We now handle
+ this (more or less) gracefully, and complain() was never a good
+ way of dealing with this.
+
+ * stabsread.c (read_type): Skip the colon when reading a
+ cross-reference. Only complain, not error_type, on unrecognized
+ cross-reference types. error_type, not dump core, if the colon is
+ missing.
+
+Fri Nov 12 16:23:08 1993 Stu Grossman (grossman at cygnus.com)
+
+ * config/m68k/tm-sun3.h: Disable use of alternate breakpoint insn
+ when doing remote stuff.
+
+Fri Nov 12 16:22:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Call lookup_symtab not lookup_partial_symtab.
+
+ * partial-stab.h: Ignore ':' symbol descriptors. Same case as
+ Kung's stabsread.c change.
+
+Fri Nov 12 11:18:02 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * stabsread.c (patch_block_stabs, define_symbol, read_type): in
+ g++ template instantiation, nested class can be part of the
+ params, and '::' can gets into symbol or type names. This is
+ to fix the problem.
+
+ * gdbtypes.c (lookup_struct_elt_type): Handle type ref or pointer
+ to struct/union case.
+
+Fri Nov 12 10:39:31 1993 Stu Grossman (grossman at cygnus.com)
+
+ * coff-solib.c (coff_solib_add): Cast result of alloca().
+ * m68k-tdep.c (m68k_saved_pc_after_call): Get rid of
+ GDB_TARGET_IS_SUN3. Use more general SYSCALL_TRAP macro.
+ * config/m68k/m68klynx.mh (NATDEPFILES): Remove exec.o (it's
+ already in TDEPFILES).
+ * config/m68k/tm-m68k.h (SAVED_PC_AFTER_CALL): Use
+ m68k_saved_pc_after_call.
+ * Remove all Sun3 specific stuff.
+ * (FIX_CALL_DUMMY): Cast arg to bfd_putb32 to unsigned char *.
+ * config/m68k/tm-m68klynx.h: Define SYSCALL_TRAP as trap #10.
+ Disable REMOTE_BREAKPOINT mechanism.
+ * config/m68k/tm-sun3.h: Get rid of GDB_TARGET_IS_SUN3.
+ * Protect from multiple includion.
+ * Move Sun3 specific stuff from tm-m68k.h to here.
+ * Define SYSCALL_TRAP as trap #0.
+ * Remove def of SAVED_PC_AFTER_CALL (now in tm-m68k.h).
+ * gdbserver/low-lynx.c: Redo all register store/fetch stuff to
+ make it portable for 386 and 68k.
+
+Fri Nov 12 09:53:26 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c (init_extra_frame_info): Check to see whether the
+ registers mentioned in the proc_desc have been saved. This
+ generalizes mips_in_lenient_prologue in the sense that we keep
+ searching until we've found saves for all the registers, not just
+ look for a "lenient prologue" pattern.
+ * mips-tdep.c: #if 0 lenient prologue code.
+
+ * mips-tdep.c (heuristic_proc_desc): Don't assume a host short
+ is 16 bits.
+
+Thu Nov 11 19:58:05 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/i386sol2.mh: Comment out corelow.o.
+
+ * printcmd.c (address_info): Use filtered, not unfiltered functions.
+ We should be able to deal with a QUIT here.
+
+Thu Nov 11 15:22:20 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * printcmd.c (address_info): Use fprintf_symbol_filtered
+ to print the symbol name.
+
+ * stabsread.c (define_symbol): Handle cfront lossage for
+ struct/union/enums and typedefs.
+
+ * partial-stab.h (case N_BINCL): Update psymtab_language
+ as appropriate when changing subfiles.
+ (case N_SOL): Update psymtab_language as appropriate when
+ changing subfiles. Add typedef for structs, unions, and enums
+ when processing C++ files.
+
+Thu Nov 11 13:18:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * README: Remove information on languages and just cite the (newly
+ updated) information in doc/gdb.texinfo instead.
+
+ * delta68-nat.c: Fix typos (add missing ");" and stuct -> struct).
+
+Wed Nov 10 09:31:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (process_one_symbol, N_RBRAC): Don't clear
+ within_function just because local_symbols is NULL. It appears
+ that this bug has existed since the 10 Apr 89 change which started
+ clearing within_function here.
+
+ * config/m68k/tm-m68k.h: Clean up CALL_DUMMY comment.
+ * config/m68k/{tm-hp300bsd.h,tm-hp300hpux.h,tm-m68k-em.h,
+ tm-monitor.h,tm-sun3.h,tm-vx68.h}, config/sparc/tm-sparc.h:
+ Define BELIEVE_PCC_PROMOTION.
+ * dbxread.c: Remove BELIEVE_PCC_PROMOTION define. The code which
+ used this was moved to stabsread.c a long time ago.
+
+ * dstread.c (dst_sym_fns): Update for flavours.
+ * symfile.c (find_sym_fns): Add kludge for apollo like for rs/6000.
+ * dstread.c (dst_symfile_offsets): Set objfile->num_sections.
+
+ gcc -Wall lint:
+ * thread.c: Include "gdbcmd.h" and <ctype.h>.
+ * Makefile.in: Update dependency.
+ * thread.c (thread_command): Remove unused variable p.
+ * values.c (unpack_double): Use len instead of TYPE_LENGTH (type).
+ * valprint.c (print_floating): Correctly check sign bit now that
+ we are using unsigned arithmetic.
+ * symtab.c (find_pc_line_range): Remove unused variables exact_match,
+ ind, and l.
+
+Tue Nov 9 17:42:25 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * valarith.c (value_x_binop): fix search operator in class bug
+ * valarith.c (value_x_unop): fix search operator in class bug
+
+Tue Nov 9 19:20:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (init.c): Add udi2go32.o to list of files that we
+ should not try to search for _initialize_* functions.
+
+ * remote-udi.c (udi_wait): Change UDIGdb_StdoutReady back to
+ UDIStdoutReady. It accidentally got changed on 24 Oct 93 when
+ stdout was changed to gdb_stdout. Likewise for UDIGetStdout,
+ UDIStderrReady, and UDIGetStderr.
+
+Tue Nov 9 12:48:06 1993 Tom Lord (lord@cygnus.com)
+
+ * remote-hms.c (hms_wait): fixed too many arguments to putc_unfiltered.
+
+Tue Nov 9 12:20:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (quit): Also call gdb_flush on standard output and error.
+
+ * .gdbinit: Remove "source /.gdbinit". It causes a spurious error
+ if /.gdbinit doesn't exist (and I know of no convention of putting
+ something in /.gdbinit).
+
+Mon Nov 8 18:17:11 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cp-valprint.c (cp_print_value_fields): change output from <no
+ value> to <optimized out or zero length>
+
+Mon Nov 08 17:05:30 1993 Jeffrey Wheat (cassidy@cygnus.com)
+
+ * Makefile.in: Change RUNTEST_FLAGS back to RUNTESTFLAGS
+ Change RUNTEST = runtest to test for existance of
+ a runtest in the source tree first.
+
+Mon Nov 8 10:42:03 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Remove unused variable GCC. Remove "#CC=cc" line
+ which doesn't really relate to anything.
+
+ * Makefile.in (CC_FOR_TARGET): Test for existence of gcc/xgcc, not
+ for existence of gcc/Makefile.
+
+ * inflow.c (terminal_init_inferior), infptrace.c (child_resume):
+ Add comments about use of Lynx PIDGET and how we will want to
+ clean it up.
+
+ * stabsread.c: Remove long_kludge_name code (it was already #if 0).
+ * stabsread.c (read_one_struct_field): Clean up comments to reflect
+ Kung's change of 5 Nov 93.
+ * stabsread.c (read_one_struct_field): Don't give up on unknown
+ visibility character, just shove it in fip->list->visibility.
+ (read_baseclasses): Don't give up on unknown virtual or visibility
+ characters, just assume a reasonable default, complain, and keep
+ going.
+ (attach_fields_to_type): Complain on unrecognized visibility.
+ One result of all this is that '9' (VISIBILITY_IGNORE) can be used
+ in a stab as well as being something which GDB uses internally.
+
+Mon Nov 8 07:57:30 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Remove h8300h, we have multilib now.
+
+Mon Nov 8 06:11:24 1993 D. V. Henkel-Wallace (gumby@cirdan.cygnus.com)
+
+ * configure.in: Add unixware as a configuration alias for x86
+ sysv4
+
+ * config/i386/i386nw.mt: add i387-tdep.o, exec.o to TDEPFILES
+
+Sun Nov 7 23:49:21 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (decode_line_1, decode_line_2): Do not adjust pc by
+ FUNCTION_START_OFFSET if funfirstline is not set.
+
+Fri Nov 5 17:19:30 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * gdbtypes.h : add a field 'ignore_field_bits in cplus_specific,
+ and macros to handle the bits.
+ * stabsread.c (read_one_struct_field): add VISIBILITY_IGNORE, and
+ for field of length 0, set this bit on.
+ * cp-valprint.c (cp_print_value_fields): for VISIBILITY_IGNORE
+ field, print <no value>.
+
+Fri Nov 5 14:43:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Version 4.11.2.
+
+Fri Nov 5 09:49:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * inflow.c (terminal_init_inferior): Temporarily use Lynx PIDGET
+ macro to set process groups.
+ * infptrace.c (child_resume): Temporarily use Lynx PIDGET to
+ specify resumption of all threads.
+ * infrun.c (wait_for_inferior): Fix handling of thread-specific
+ breakpoints for systems where DECR_PC_AFTER_BREAK > 0 (ie: backup
+ PC by the right amount when continuing the thread).
+ * thread.c (thread_apply_command): Add the `thread apply'
+ command to apply a given GDB command to a list of threads.
+
+Fri Nov 5 05:58:03 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (init.c): Don't call sed if filename is empty.
+
+Thu Nov 4 08:27:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (unknown_symchar_complaint): Make message refer to
+ "symbol descriptor" not "symbol type character" for consistency
+ with stabs.texinfo terminology.
+
+ * stabsread.c (read_struct_fields): Accept either '$' or '.' as
+ the character which introduces a cpp_abbrev or anonymous type.
+
+ * c-lang.c (c_printstr): Print "" to stream (like all the other
+ output from this function), not gdb_stdout.
+
+ * dbxread.c (process_one_symbol): Do relocate 'S' symbols by
+ the text offset (revert 12 Oct 93 change).
+
+ * configure.in: Make hppa*-*-hiux* use hppahpux,
+ not non-existent hppahiux.
+
+Wed Nov 3 16:24:09 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * values.c (value_fn_field): when physical name not found, do not
+ error, but return null.
+ * valops.c (value_struct_elt): when name and args match does not
+ mean it is the one, some times a typedef class can have the same
+ member method and args. This probably will not happen with new
+ version of g++, but it does happen in old g++ and cause gdb error.
+
+Wed Nov 3 09:20:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ Merge changes for dos x udi:
+ * Makefile.in (udi2go32.o): add rule to build this file
+ * 29k-share/udi/udi2go32.c: new file
+ * config/a29k/a29k-udi.mt: add udi2go32.o
+ * 29k-share/udi/{udr.c, udip2soc.c}: #ifdef out the entire file
+ if __GO32__ is defined. What a hack.
+
+Wed Nov 3 09:20:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c (putpkt, getpkt): Don't call interrupt_query.
+
+ * findvar.c (value_of_register): Rename val to reg_val to avoid
+ name conflict with some (e.g. tm-m68k.h) REGISTER_CONVERT_TO_VIRTUAL.
+
+ * main.c: Add variables source_line_number, source_file_name,
+ source_error, source_error_allocated, and source_pre_error.
+ (command_line_input): If source_file_name set, increment
+ source_line_number and set error_pre_print with them.
+ (source_command): Set source_* and make a cleanup so they get
+ set back.
+
+Tue Nov 2 16:28:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stack.c (down_silently_command): Add comment about PR 1913.
+
+ * breakpoint.c (insert_breakpoints, delete_breakpoint): Call
+ target_terminal_ours_for_output before attempting output.
+
+ * fork-child.c (fork_inferior): Fix comment so that it suggests
+ "set shell" rather than having "set env SHELL" affect GDB's
+ operation.
+
+Tue Nov 2 15:03:08 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * utils.c (vfprintf_unfiltered): don't use maybe_filtered
+ since it involves a fixed size buffer.
+
+Tue Nov 2 13:42:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * findvar.c (value_of_register, value_from_register),
+ hppa-tdep.c (pa_print_fp_reg), infcmd.c (do_registers_info),
+ valops.c (value_assign): Use REGISTER_CONVERT_TO_* only if
+ REGISTER_CONVERTIBLE is defined, otherwise just copy the content.
+ Pass desired type to REGISTER_CONVERT_TO_*.
+
+ * config/m68k/tm-m68k.h, config/i960/tm-i960.h (REGISTER_CONVERT_*):
+ Pass length of desired type to store/extract_floating.
+ * config/i386/tm-arm.h, config/i386/tm-i386aix.h,
+ config/i386/tm-sun386.h, config/i386/tm-symmetry.h,
+ config/m88k/tm-m88k.h config/rs6000/tm-rs6000.h (REGISTER_CONVERT_*):
+ Use extract_floating and store_floating with length of desired type.
+ * config/m68k/tm-news.h (STORE,EXTRACT_RETURN_VALUE): Add type
+ parameter to REGISTER_CONVERT_*.
+
+ * config/a29k/tm-a29k.h, config/convex/tm-convex.h,
+ config/gould/tm-np1.h, config/gould/tm-pn.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/i386/tm-i386v.h,
+ config/mips/tm-mips.h, config/ns32k/tm-merlin.h,
+ config/ns32k/tm-umax.h, config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/sh/tm-sh.h, config/sparc/tm-sparc.h, config/tahoe/tm-tahoe.h,
+ config/vax/tm-vax.h, config/z8k/tm-z8k.h (REGISTER_CONVERTIBLE,
+ REGISTER_CONVERT_TO_RAW, REGISTER_CONVERT_TO_VIRTUAL): Remove
+ versions for which REGISTER_CONVERTIBLE is always false.
+ * z8k-tdep.c (register_convert_to_virtual, register_convert_to_raw):
+ Remove, no longer used.
+
+ * alpha-tdep.c (alpha_register_convert_to_raw,
+ alpha_register_convert_to_virtual): New routines to handle
+ the different raw formats in alpha floating point registers.
+ * config/alpha/tm-alpha.h (REGISTER_CONVERTIBLE,
+ REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Use them.
+
+Tue Nov 2 12:45:23 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * gdbserver/configure.in: Recognize *-*-lynxos* instead of
+ *-*-lynx*, recognize sparc-*-lynxos*.
+ * gdbserver/Makefile.in (install, install_only): Add.
+ * gdbserver/gdbserver.1: New file, man page for gdbserver.
+
+Tue Nov 2 03:01:01 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Include <time.h> and <sys/types.h>. Change include
+ of "libhppa.h" to "som.h".
+ (BYTES_IN_WORD): Define.
+ (hppa_sym_fns): "hppa" is 4 characters, not 5.
+
+Mon Nov 1 09:40:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c, symtab.h, source.c: Change find_line_pc_range to take
+ a struct symtab_and_line argument, rather than a symtab and a line.
+ Re-write it to be based on the address rather than bogusly adding
+ one to the line number and hoping that has something to do with the
+ end of the line.
+
+ * config/m88k/m88k.mh (NATDEPFILES): Remove exec.o.
+
+ * paread.c (pa_symtab_read): Change comments to say ignoring
+ labels really should be handled by the assembler/compiler.
+
+ * Makefile.in: Add -O to CXXFLAGS.
+
+ * TODO: Expand comments on fast watchpoints.
+
+Sun Oct 31 19:45:06 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symtab_read): Also filter out local symbols
+ starting with "L$".
+
+Sun Oct 31 09:28:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symfile.h (sym_fns), symfile.c (find_sym_fns), xcoffread.c,
+ coffread.c, dbxread.c, elfread.c, mipsread.c, nlmread.c, paread.c:
+ Change from using bfd target name to using the flavour.
+
+ * objfiles.h, infcmd.c, symfile.c: Add comments about how various
+ objfiles get created and when we should blow them away.
+
+Sat Oct 30 08:32:53 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symfile.c (reread_symbols): When re-reading symbols, do all the
+ right operations ourself, rather than calling symbol_file_command.
+ If we re-read something, call clear_symtab_users not just
+ breakpoint_re_set.
+ * objfiles.h, objfiles.c (build_objfile_section_table): No longer
+ static.
+ * symfile.c (clear_symtab_users): Call clear_pc_function_cache.
+ * coffread.c, dbxread.c, elfread.c, mipsread.c, nlmread.c, paread.c
+ (*_symfile_offsets): Set objfile->num_sections.
+ * remote.c (remote_wait), symfile.c (syms_from_objfile):
+ Don't muck with objfile->num_sections now that all the symbol
+ readers set it.
+ * elfread.c: Clean up obsolete comment about handling only DWARF.
+ * paread.c: Remove comment about how we should use an "ordinary"
+ file format with an hppa suffix. There is nothing ordinary about SOM.
+
+ * config/i386/{i386m3.mh,i386mk.mh}, config/mips/mipsm3.mh,
+ config/ns32k/ns32km3.mh: Change MMALLOC_LIB to MMALLOC.
+ * TODO: Update Mach stuff.
+
+Fri Oct 29 16:30:36 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ LynxOS support:
+ * configure.in: Change *-*-lynx* to *-*-lynxos*, add
+ sparc-*-lynxos*.
+ * Makefile.in (ALLDEPFILES): Add m68kly-nat.c, sparcly-nat.c.
+ Rename i386lynx-nat.[co] to i386ly-nat.[co].
+ (ALLCONFIG): Add config/{m68k,sparc}/{m68k,sparc}lynx.m[ht].
+ (m68kly-nat.o, sparcly-nat.o): Add rules.
+ * i386ly-tdep.c: Cosmetics.
+ * i386lynx-nat.c: Removed.
+ * i386ly-nat.c: New file, was i386lynx-nat.c.
+ * m68kly-nat.c: New file.
+ * sparcly-nat.c: New file.
+ * config/xm-lynx.h: New file, cpu-independent host info.
+ * config/i386/i386lynx.mh: Changes for consistency.
+ * config/i386/i386lynx.mt: Ditto.
+ * config/i386/tm-i386lynx.h: Ditto.
+ * config/i386/nm-i386lynx.h: Ditto.
+ * config/i386/xm-i386lynx.h: Include config/xm-lynx.h.
+ * config/m68k/m68klynx.mh, config/m68k/m68klynx.mt,
+ config/m68k/tm-m68klynx.h, config/m68k/nm-m68klynx.h,
+ config/m68k/xm-m68klynx.h: New files, M68K LynxOS support.
+ * config/sparc/sparclynx.mh, config/sparc/sparclynx.mt,
+ config/sparc/tm-sparclynx.h, config/sparc/nm-sparclynx.h,
+ config/sparc/xm-sparclynx.h: New files, Sparc LynxOS support.
+
+Fri Oct 29 08:11:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h, findvar.c (extract_floating, store_floating): New functions.
+ * Move SWAP_TARGET_AND_HOST from defs.h to findvar.c because it is
+ now used only by extract_floating and store_floating.
+ * valprint.c (print_floating): Use unsigned arithmetic. Use
+ extract_unsigned_integer instead of SWAP_TARGET_AND_HOST.
+ Change sizeof (float) to 4 and sizeof (double) to 8 (those are always
+ the relevant sizes for this code, which is in #ifdef IEEE_FLOAT).
+ * values.c (unpack_long, unpack_double, value_from_double),
+ valarith.c (value_binop), stabsread.c (define_symbol):
+ Use extract_floating and store_floating instead of
+ SWAP_TARGET_AND_HOST.
+ * config/m68k/tm-m68k.h, config/i960/tm-i960.h (REGISTER_CONVERT_*):
+ Use extract_floating and store_floating.
+ * config/m88k/tm-m88k.h: Add comments (it should be doing the same).
+ * i386-tdep.c (i386_extract_return_value),
+ * remote-nindy.c (nindy_store_registers): Use store_floating.
+
+Fri Oct 29 09:31:38 1993 Steve Chamberlain (sac@rtl.cygnus.com)
+
+ * remote-sim.c (gdbsim_store_register): Change var name so
+ it compiles with non-ANSI compilers.
+
+Fri Oct 29 08:11:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add idea for "disassemble" with source.
+
+Fri Oct 29 00:41:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.11.1 after release and cvs
+ tagging.
+
+Thu Oct 28 09:14:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Add section on Mach. Stop calling it a "bug list".
+ Remove John's name and email address. Remove item on "always"
+ ("hook-stop" takes care of this). Remove item on executables with
+ no symbols (this works on some machines, at least). Remove item
+ about calling error() during symbol reading (I think all the important
+ ones have been cleaned up). Revise items about signals and remote
+ systems. Remove section on ^Z requiring several continues to make
+ it go (this now works. Perhaps the item is based on confusion over
+ programs (like GDB itself) which catch SIGTSTP and then re-send
+ themselves the signal. PR 2575 might contain relevant info).
+
+Thu Oct 28 16:55:34 1993 Fred Fish (fnf@cygnus.com)
+
+ * NEWS: Note improvements in C++ support, preliminary thread
+ implementation, and LynxOS native and target support for 386.
+
+Thu Oct 28 16:55:34 1993 Fred Fish (fnf@cygnus.com)
+
+ * README: Add note from Peter Schauer about OSF/1 shared
+ libraries. Add note from Pace Willisson about configuring on BSDI
+ BSD/386 release 1.0. Update gdb references to gdb 4.11.
+
+Thu Oct 28 09:14:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * NEWS: Add notes about Alpha and "set remotedebug" for UDI.
+
+ * valops.c (value_assign): Change bitfield code to use a buffer of
+ the correct size, rather than an int.
+
+Wed Oct 27 13:43:07 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/{i386m3.mt,i386m3.mh},
+ config/mips/{mipsm3.mt,mipsm3.mh},
+ config/ns32k/{ns32km3.mt,ns32km3.mh}: Use correct names for TM_FILE
+ and XM_FILE. Replace host files *mach3-xdep.o with native
+ files *m3-nat.o. Replace host file os-mach3.o with native
+ file m3-nat.o.
+
+ * remote-udi.c: Remove LOG_FILE stuff; superceded by "set remotedebug".
+ * remote-mon.c: Remove commented out "set remotedebug" command.
+ * remote-nindy.c: Clean up comment about wanting alternative to
+ options specified on the GDB command line.
+
+ * fork-child.c (fork_inferior): Set inferior_pid before calling
+ init_trace_fun. Move the code which gets us through the shell
+ to new function startup_inferior.
+ * inferior.h: Declare startup_inferior.
+ * procfs.c (procfs_init_inferior), inftarg.c (ptrace_him):
+ Call startup_inferior.
+ * m3-nat.c (m3_trace_him): Call intercept_exec_calls.
+ * config/nm-m3.h: Don't define STARTUP_INFERIOR.
+ * config/i386/tm-i386m3.h, config/ns32k/tm-ns32k.h,
+ config/mips/tm-mipsm3.h: Don't define START_INFERIOR_TRAPS_EXPECTED.
+
+ * m68k-stub.c: Change vector 13 from SIGFPE to SIGBUS.
+
+Tue Oct 26 22:05:03 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mips-tdep.c (mips_pop_frame): If proc_desc is NULL, don't dump core.
+
+Tue Oct 26 15:07:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ gcc -Wall lint:
+ * nlmread.c: Include stabsread.h.
+ * Makefile.in: Update dependencies.
+
+ * remote.c: Change PBUFSIZ back to 400. John's 28 Feb 1992 change
+ to increase it broke the ability to write large chunks of memory
+ with m68k-stub and i386-stub. Now we only use more than 400 on
+ machines where we need that much to write the registers.
+ * remote.c (remote_write_bytes): Eliminate possible abort(). The
+ check for when to abort was off by a few bytes and besides which,
+ it is handled by MAXBUFBYTES, which the caller uses.
+ * m68k-stub.c: Add comments about trap #1 and trap #8 instructions.
+
+Tue Oct 26 08:36:07 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.h (SIM_ADDR): New type (same as CORE_ADDR).
+ (sim_set_pc): Update prototype.
+ (sim_read, sim_write): Ditto, and use unsigned char *buf.
+ (sim_fetch_register, sim_store_register): Use unsigned char *buf.
+ (sim_info): Pass printf function as argument, add verbose argument.
+ (sim_stop_reason): Renamed from sim_stop_signal, fix prototype.
+ * remote-sim.c (gdbsim_wait): Update call to sim_stop_reason.
+ (gdbsim_files_info): Update call to sim_info.
+
+Tue Oct 26 10:41:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_assign): Call reinit_frame_cache when assigning
+ to a register.
+
+Mon Oct 25 11:08:59 1993 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): Fix PC out of objfile bounds
+ check to just use stop_func_name == 0.
+ * remote-udi.c (store_register): Invalidate NPC/PC_REGNUM after
+ changing PC.
+
+Mon Oct 25 14:57:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/{low-lynx.c,low-sparc.c,low-sun3.c}, standalone.c,
+ m3-nat.c, i386m3-nat.c, mipsm3-nat.c, ns32km3-nat.c: bcopy -> memcpy.
+
+ gcc -Wall lint:
+ * breakpoint.c: Include thread.h.
+ * coffread.c: Include stabsread.h.
+ * Makefile.in: Update dependencies.
+ * breakpoint.c (mention): Add bp_call_dummy to switch.
+ * symmisc.c (dump_symtab): Use %d not %ld for line number.
+
+Sun Oct 24 18:29:32 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * every non-obsolete file except utils.c:
+ Change the stream argument to _filtered to GDB_FILE *.
+ Change all references to stdout/stderr to gdb_stdout/gdb_stderr.
+ Replace all calls to stdio output functions with
+ calls to corresponding _unfiltered functions.
+ Replaced calls to fopen for output to gdb_fopen.
+ Added sufficient goo to utils.c and defs.h to make the above
+ work.
+
+ The net effect is that stdio output functions are only directly
+ used in utils.c. Elsewhere, the _unfiltered and _filtered
+ functions and GDB_FILE type are used.
+
+ In the near future, GDB_FILE will stop being equivalant to
+ FILE.
+
+ The semantics of some commands has changed in a very subtle way:
+ called in the right context, they may cause new occurences of
+ prompt_for_continue() behavior.
+
+ Please respect this change by not reintroducing stdio output
+ dependencies in the main body of gdb code. All output from
+ commands should go to a GDB_FILE.
+
+Sun Oct 24 20:16:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * parse.c, parser-defs.h (write_exp_msymbol): New function to write
+ the appropriate expression for a minimal symbol. Taken from c-exp.y
+ and m2-exp.y but handles mst_file_*.
+ * c-exp.y, m2-exp.y: Use it.
+
+Sun Oct 24 09:31:05 1993 Fred Fish (fnf@lisa.cygnus.com)
+
+ * elfread.c (elf_symtab_read): Use bfd convention that both
+ initialized and uninitialized data sections have the SEC_ALLOC
+ flag bit set, but only initialized sections have SEC_LOAD set.
+ SEC_DATA is ignored since it only gets set for initialized
+ data.
+
+Sat Oct 23 14:48:18 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.h (sim_stop): New enum.
+ (sim_stop_signal): Change prototype, result is enum sim_stop.
+ * remote-sim.c (gdbsim_wait): Update call to sim_stop_signal.
+
+Fri Oct 22 07:49:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): Skip the whole thing about "pcc
+ promotion" on little-endian machines.
+
+ * remote-vx.c (vx_wait): Rename pid parameter to pid_to_wait_for.
+ Some compilers (legitimately) don't like variables in the
+ function's outermost block whose name is the the same as the name of
+ a parameter.
+
+ Merge Apollo patches from Troy Rollo (troy@cbme.unsw.edu.au):
+ * dst.h, dstread.c, config/m68k/{apollo68b.mt,tm-apollo68b.h}:
+ New files.
+ * config/m68k/nm-apollo68b.h: Add more defines.
+ * configure.in: Recognize apollo target, not just host.
+
+ * configure.in: Add * to end of all OS names.
+
+Fri Oct 22 06:14:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (ALLPARAM): Add config/m88k/xm-delta88v4.h
+
+Thu Oct 21 12:23:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (init.c): Generate using the source, not munch. This
+ cleans up all kinds of hassles (which nm to use in munch, etc). The
+ new formatting conventions (mostly already followed) are that
+ the name of the _initialize_* routines must start in column zero,
+ and must not be inside #if.
+ * munch: Removed.
+ * Makefile.in: Remove references to munch.
+ * serial.c, remote.c, infptrace.c, maint.c, convex-tdep.c,
+ alpha-tdep.c, hp300ux-nat.c, hppab-nat.c, osfsolib.c, remote-es.c,
+ procfs.c, remote-udi.c, ser-go32.c, ultra3-xdep.c, sh-tdep.c,
+ i960-tdep.c, hppa-tdep.c, h8500-tdep.c, dpx2-nat.c, delta68-nat.c,
+ z8k-tdep.c: Make sure the above conventions are followed. Make
+ sure they are all declared as returning void. Clean up
+ miscellaneous comments and such.
+
+ * sh-tdep.c (sim_load): Add function.
+
+Thu Oct 21 15:58:48 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * remote-mips.c (mips_wait): add pid argument.
+
+Thu Oct 21 12:23:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (c-exp.tab.o): Remove notice about shift/reduce conflicts
+ which no longer occur.
+
+ gcc -Wall lint:
+ * findvar.c (symbol_read_needs_frame), corelow.c (ignore),
+ inflow.c (gdb_has_a_terminal): Make sure to return a value.
+ * regex.h: Declare re_set_syntax.
+ * printcmd.c: Include valprint.h.
+ * infcmd.c, exec.c, maint.c, core.c: Include language.h.
+ * maint.c: Include expression.h.
+ * infrun.c, fork-child.c, corelow.c, inflow.c: Include thread.h.
+ * inftarg.c: Include command.h.
+ * coredep.c: Include value.h.
+ * c-exp.y, m2-exp.y, ch-exp.y: Include bfd.h, symfile.h and objfiles.h.
+ * ch-typeprint.c: Include typeprint.h.
+ * ch-valprint.c: Include c-lang.h.
+ * nlmread.c: Include buildsym.h.
+ * environ.c: Include gdbcore.h. Only include defs.h once.
+ (set_in_environ): Cast const char * to char * when passing to
+ set_gnutarget.
+ * Makefile.in: Update dependencies to reflect all these new includes.
+ Remove unused variables:
+ * printcmd.c (printf_command): args_to_vprintf.
+ * coffread.c (coff_symfile_init): strsection.
+ Move variables to within the #ifdefs where they are used:
+ * symtab.c (gdb_mangle_name): opname.
+ * inftarg.c (child_attach): pid and exec_file.
+ * inftarg.c (child_detach): siggnal.
+ * objfiles.c (allocate_objfile): mapto, md, and fd.
+ * objfiles.c (free_objfile): mmfd.
+ * infrun.c (wait_for_inferior): Include BPSTAT_WHAT_LAST in switch.
+ * infrun.c (wait_for_inferior): Remove unused same_pid label.
+ * inferior.h: Declare set_sigint_trap and clear_sigint_trap.
+ * parser-defs.h: Declare write_exp_elt_block.
+ * stabsread.h: Declare elfstab_offset_sections and
+ coffstab_build_psymtabs.
+
+Thu Oct 21 12:05:08 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ Patch from Jeff Law:
+ * paread.c: Fix references to "hppa" that should now be "som".
+
+Thu Oct 21 12:23:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): Don't use SYMBOL_LINE for functions.
+
+Thu Oct 21 02:59:07 1993 Stu Grossman (grossman at cygnus.com)
+
+ * remote-udi.c (udi_store_registers, store_register): Use
+ UDI29KPC address space when modifying PC. It seems that you can't
+ modify the PC directly (at least in the isstip simulator).
+
+Wed Oct 20 11:35:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.h: Put remote_debug declaration back here. Add baud_rate.
+ * remote.c, remote-udi.c, remote-utils.h: Let target.h take care of
+ declaring these. Those random externs all over are error prone.
+ * Move "set remotebaud" from remote-utils.c to main.c to it applies
+ to remote.c as well.
+
+ * xcoffread.c (xcoff_symfile_read), coffread.c (coff_symfile_read):
+ Sort symtabs for this objfile only, not for all objfiles.
+ * symfile.c, symfile.h (sort_all_symtab_syms): Remove; no longer used.
+
+ * mipsread.c (parse_symbol): In third-eye, a function has a block
+ within it which represents the whole function. Create only one
+ GDB block for both.
+
+Wed Oct 20 17:47:42 1993 Stu Grossman (grossman at cygnus.com)
+
+ * main.c: Make baud_rate and remote_debug be global variables,
+ remove #include "remote-utils.h". This makes it possible to build
+ GDB without remote-utils.c. Also, move setting of remote_debug
+ into main, so that all remote*.c files can use it (not just the
+ serial line ones). And, make baud_rate be an int.
+ * remote-udi.c: Change kiodebug to remote_debug.
+ * remote-utils.c: Move setting of baud rate and debug into main.c.
+ * remote-utils.h: Redefine sr_{get set}_debug and sr_{get set}_baud
+ to use baud_rate and remote_debug globals for compatibility.
+ * remote.c: Use remote_debug and baud_rate globals directly,
+ instead of sr_ functions, so that we don't need to load
+ remote-utils.c.
+ * config/a29k/a29k-udi.mt: Define REMOTE_O as null so that we don't
+ get the default remote* modules.
+
+Wed Oct 20 11:35:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): When combining a LOC_ARG and a
+ LOC_REGISTER, use the type from the LOC_REGISTER, not from the
+ LOC_ARG.
+
+Wed Oct 20 14:34:38 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/i386/xm-go32.h: define some signals if they aren't
+ already defined.
+
+Wed Oct 20 11:35:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (INTERNAL_LDFLAGS): New macro. The new part is
+ that we use CFLAGS and PROFILE_CFLAGS to link.
+ (gdb, rapp, kdb): Use INTERNAL_LDFLAGS instead of
+ LDFLAGS and/or GLOBAL_CFLAGS.
+
+Wed Oct 20 09:29:55 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add $(srcdir) to all refs to 29k-share
+ directories.
+
+Tue Oct 19 17:23:34 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (ALLCONFIG): Add config/i386/{i386m3.mh, i386m3.mt,
+ i386/i386mk.mh i386/i386mk.mt}, config/mips/{mipsm3.mh,
+ mipsm3.mt}, config/ns32k/{ns32km3.mh, ns32m3.mt}
+ * Makefile.in (remote_utils_h): Add remote-sim.h
+ * Makefile.in (NONSRC): Add i386-nlmstub.c
+ * Makefile.in (HFILES): Add coff-solib.h
+
+Tue Oct 19 14:15:40 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * values.c (value_virtual_fn_field): Fix the offset calculation
+ when calling virtual functions. (gdb.t22/virtfunc.exp).
+ * eval.c (evaluate_subexp): same as above.
+
+Tue Oct 19 10:43:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/rs6000/rs6000.mh (TERMCAP): Define to -lcurses.
+
+ * Makefile.in: Define CXXFLAGS.
+
+Tue Oct 19 09:28:52 1993 Stu Grossman (grossman@cygnus.com)
+
+ * sparclite/Makefile.in: Fixup so that this works with Sun make
+ and VPATH.
+
+Tue Oct 19 10:43:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.h (struct bpstat_what): Don't use bitfields.
+
+ * typeprint.c: Add "class CLASS-NAME" to docstring for ptype.
+
+Tue Oct 19 06:17:10 1993 Fred Fish (fnf@cirdan.cygnus.com)
+
+ * Makefile.in (ALLPARAM): Add config/m88k/{nm-delta88v4.h,
+ tm-delta88v4.h, xm-dgux.h}.
+ * Makefile.in (ALLCONFIG): Add config/m88k/{delta88v4.mh,
+ delta88v4.mt}.
+
+ * README: Remove comment about SunOS 5.x programs leaving
+ coredumps. Info from Sun is that this was not in customer
+ releases.
+
+Mon Oct 18 10:28:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c (restore_pc_queue): Call target_terminal_ours after
+ done stepping the inferior.
+
+ * c-exp.y: Remove never-used (because of shift/reduce conflicts)
+ rules for pointers to members.
+ * Makefile.in: Remove notice about expected shift/reduce conflicts.
+
+ * buildsym.c (finish_block): If we pop the context stack and it is
+ not empty, complain () instead of abort ().
+
+Sun Oct 17 19:42:31 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * parse.c, parser-defs.h (follow_types): New function.
+ * c-exp.y (ptype : typebase abs_decl): Use it.
+ * c-exp.y (ptype): Add support for type qualifiers after the
+ typebase. The typebase rule already has support for them before
+ the typebase.
+ * Makefile.in: Change the expected number of shift/reduce
+ conflicts to 6. This is OK--the 2 new conflicts are basically the
+ same as one of the old ones.
+
+Sun Oct 17 13:04:49 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.10.3.
+
+Sun Oct 17 09:18:57 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Clean up comments which were at
+ the top of the file, making them more concise and moving them with
+ the code (Sorry, Randy, but these stream-of-consciousness comments
+ really have to go). Switch the order of the "&&", which makes
+ things clearer and turns out to be an improvement with respect to
+ side effects and speed.
+
+Sun Oct 17 02:06:01 1993 Stu Grossman (grossman at cygnus.com)
+
+ * procfs.c: Handle process exits more elegantly by trapping on
+ entry to _exit. Also, cleanup procinfo list when process dies of
+ it's own accord (as opposed to being killed).
+
+Sat Oct 16 20:47:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m88k/xm-dgux.h: Define NO_PTRACE_H.
+
+ * corelow.c (add_to_thread_list): Need a cast to go from PTR to
+ asection *.
+
+ * infrun.c: Add comment about signals.
+
+ * fork-child.c (fork_inferior): Remove CREATE_INFERIOR_HOOK again.
+ Stu reinstated it (accidently I assume).
+
+Sat Oct 16 15:27:10 1993 Stu Grossman (grossman at cygnus.com)
+
+ * procfs.c (procfs_wait): Losing Unixware can't do poll on /proc
+ files. Use PIOCWSTOP instead.
+ * corelow.c (add_to_thread_list): Fix arg to match prototype.
+
+ * procfs.c (procfs_set_sproc_trap): Don't use this if sproc
+ isn't available.
+ * (procfs_notice_signals): Fix prototype.
+
+Fri Oct 15 22:46:07 1993 Stu Grossman (grossman at cygnus.com)
+
+ * breakpoint.c (breakpoint_thread_match break_command_1):
+ Thread-specific breakpoint support.
+ * breakpoint.h (struct breakpoint): Add thread id field.
+ * fork-child.c (fork_inferior): Move call to init_thread_list()
+ back a bit so that init_trace_fun can do thread functions.
+ * hppa-tdep.c (restore_pc_queue): Add pid to call to target_wait.
+ * hppab-nat.c (child_resume): Handle default pid.
+ * hppah-nat.c (child_resume): Handle default pid.
+ * i386lynx-nat.c (child_wait): New arg pid.
+ * inflow.c (kill_command): Reset thread list.
+ * infptrace.c (child_resume): Handle default pid.
+ * infrun.c: Thread-specific breakpoint support.
+ * inftarg.c (child_wait): Add pid arg.
+ * osfsolib.c (solib_create_inferior_hook): Add pid to call to
+ target_resume.
+ * procfs.c: Multi-thread support.
+ * remote-bug.c (bug_wait): Add pid arg.
+ * remote-hms.c (hms_wait): Add pid arg.
+ * remote-mips.c (mips_wait): Add pid arg.
+ * remote-mon.c (monitor_wait): Add pid arg.
+ * remote-nindy.c (nindy_wait): Add pid arg.
+ * remote-sim.c (gdbsim_wait): Add pid arg.
+ * remote-udi.c (udi_wait): Add pid arg.
+ * remote-vx.c (vx_wait): Add pid arg.
+ * remote-z8k.c (sim_wait): Add pid arg.
+ * remote.c (remote_wait): Add pid arg.
+ * solib.c (solib_create_inferior_hook): Add pid to call to
+ target_resume.
+ * target.h (struct target_ops): Add pid arg to to_wait and
+ to_notice_signals.
+ * thread.c (valid_thread_id): New func to validate thread #s.
+ * (pid_to_thread_id): New func to do the obvious.
+ * thread.h: Prototypes for above.
+
+ * coff-solib.c (coff_solib_add): Use nameoffset field to locate
+ filename.
+
+Fri Oct 15 21:29:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * h8300-tdep.c, h8500-tdep.c: Define sim_load only, but not
+ sim_kill, sim_open, or sim_set_args.
+
+ * stack.c (print_stack_frame): Put catch_errors around
+ print_frame_info so (for example) error printing source doesn't
+ cause auto-displays to get skipped in normal_stop.
+
+ * findvar.c (value_from_register): When preparing to cast a value
+ from REGISTER_VIRTUAL_TYPE to type, copy the REGISTER_VIRTUAL_SIZE;
+ the old code didn't copy the whole thing.
+ * valops.c (value_assign): Add comment.
+
+Fri Oct 15 12:57:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (upgrade_type): Replace bitsize sanity checks and
+ complaint by a comment explaining why they were useless.
+
+Fri Oct 15 14:30:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Move comments on bypassing call dummy breakpoint from stack.c
+ to breakpoint.h.
+
+Fri Oct 15 11:52:56 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (lookup_partial_symtab): If filename is not found and
+ contains no slashes, try again and compare without leading path
+ components.
+ * symtab.c (lookup_symtab_1): Replace open coded version of
+ lookup_partial_symtab with a function call.
+
+Thu Oct 14 20:34:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * fork-child.c (fork_inferior), remote-eb.c (eb_create_inferior),
+ remote-mon.c (monitor_create_inferior), remote-nindy.c
+ (nindy_create_inferior), remote-st.c (st2000_create_inferior),
+ remote-vx.c (vx_create_inferior): Remove CREATE_INFERIOR_HOOK; it
+ is replaced by init_trace_fun.
+ * config/convex/xm-convex.h, convex-xdep.c: Add comments explaining
+ how to do without CREATE_INFERIOR_HOOK for whoever fixes the Convex
+ port.
+
+ * Makefile.in: Add Mach files to ALLDEPFILES, etc.
+ * m3-nat.c: Clean up more hair--message(), cprocs.
+ * configure.in: Recognize Mach targets and hosts.
+ * config/ns32k/tm-umax.h: Add some #ifndef's so tm-ns32km3.h can
+ include this file.
+ * Mach headers in config/*/tm-*.h: Fix includes to match correct
+ locations of files.
+
+Thu Oct 14 21:35:55 1993 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * remote-mon.c (general_open): Set dev_name. Minor tweaking to get
+ it working again.
+ * config/m68k/tm-monitor.h: Remove floating point register names
+ as there aren't any on any of the monitors that use this code.
+
+Wed Oct 13 11:47:23 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inflow.c: Pass pointer to process group, not process group itself,
+ to TIOCSPGRP ioctl.
+
+ * inflow.c (terminal_ours_1): Don't print warning on failure to
+ set process group.
+
+ * printcmd.c (printf_command): Instead of using makeva* and
+ calling vprintf, just make the appropriate calls to printf.
+ * printcmd.c, config/pa/xm-pa.h, config/mips/xm-makeva.h,
+ config/alpha/xm-alpha.h, config/m88k/xm-m88k.h: Remove all
+ traces of makeva*. My apologies to everyone (including me!)
+ who spent so much time getting it to work on various machines,
+ but look at the bright side, at least you won't have to do it
+ again in the future.
+
+ * printcmd.c (printf_command): Make a cleanup for val_args (fixes
+ a memory leak).
+
+Tue Oct 12 22:54:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/xm-mips.h: Remove comment about HAVE_SGTTY vs. usleep.
+
+Tue Oct 12 12:01:29 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: only configure gdbserver for native environments
+
+Tue Oct 12 08:59:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (read_type): Treat a negative type number at the start
+ of a type as a type reference, not as a definition of a type with
+ "50=" omitted. This makes things work on the RS/6000 again (the
+ 14 Sep 1993 change broke it).
+
+ * inflow.c: Use 0 (standard input) not scb->fd.
+ (terminal_ours_1): If printing warning, don't claim it happened in
+ terminal_inferior.
+
+ * blockframe.c (get_prev_frame_info): Don't error() if there are no
+ frames; just return NULL.
+
+ * xcoffsolib.h, xcoffexec.c: Undo the part of Fred's bfd->abfd
+ change which involved structure elements. It was unnecessary and
+ was not consistently done.
+
+ * stabsread.h, stabsread.c, dbxread.c (common_block*, copy_pending):
+ Move common block handling from dbxread.c to stabsread.c.
+ Use the name from the BCOMM instead of the ECOMM.
+ Allocate things on the symbol_obstack.
+ * xcoffread.c (process_xcoff_symbol): Process C_BCOMM, C_ECOMM,
+ and C_ECOML. On unrecognized storage classes, go ahead and call
+ define_symbol (after the complaint).
+
+ * dbxread.c (process_one_symbol): Don't relocate 'S' symbols by
+ the text offset.
+
+Tue Oct 12 12:33:09 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * osfsolib.c (solib_create_inferior_hook): Reset stop_soon_quietly
+ after shared library symbol reading to get rid of warning from
+ heuristic_proc_start.
+
+Tue Oct 12 12:01:29 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * remote-sim.c: fix unterminated character string
+
+Tue Oct 12 08:59:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c: Fix comment about gcc 2.3.3 stab for long long int.
+
+Mon Oct 11 14:27:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m3-nat.c, config/nm-m3.h: Add a target_ops struct and other
+ various things to try to get this to work.
+
+ * symtab.h: Fix comments re headers, sharing blockvectors, etc.
+
+Mon Oct 11 11:46:06 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config/i960/vxworks960.mt (REMOTE_O): add dcache.o and remote-utils.o
+
+Mon Oct 11 02:48:57 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_partial_symbols): Do not add undefined
+ symbols to the partial symbol table.
+ * alpha-tdep.c (init_extra_frame_info): Remove kludge for gcc,
+ gcc has to be compatible with the native tools.
+ * alpha-tdep.c (alpha_push_arguments): Rename NUM_ARG_REGS to
+ ALPHA_NUM_ARG_REGS and move its definition to tm-alpha.h.
+ * config/alpha/tm-alpha.h (FRAME_ARGS_ADDRESS): Change it to the
+ way the native tools define it, update comment.
+
+Fri Oct 8 15:54:06 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * osfsolib.c, remote-sim.c, remote.c, solib.c, xcoffexec.c,
+ xcoffsolib.h: Use 'abfd' for bfd variables instead of 'bfd'.
+ Sun cc doesn't like variable names that match their typedef'd type.
+
+Fri Oct 8 14:56:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inflow.c: Remove unused includes of sys/param.h and sys/types.h.
+
+ * inflow.c, ser-unix.c, ser-go32.c, ser-tcp.c, serial.h,
+ terminal.h, fork-child.c, main.c, utils.c: Move all the process
+ group stuff back to inflow.c and terminal.h; that's a better place
+ for it and fixes problems with trying to get/set the process group
+ of a tty we're doing remote debugging on.
+ * terminal.h: Skip the redefines and includes if HAVE_TERMIOS.
+
+ * findvar.c, value.h (symbol_read_needs_frame): New function.
+ * c-exp.y, m2-exp.y: Call it instead of having our own switch on
+ the symbol's class.
+ * valops.c (value_of_variable): Use symbol_read_needs_frame to
+ decide whether we care about finding a frame.
+
+Fri Oct 8 02:34:21 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (get_frame_block): Do not adjust pc if the frame
+ function was interrupted by a signal.
+
+Thu Oct 7 19:20:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/h8300/tm-h8300.h: Don't define sr_get_debug.
+ * remote-sim.c: Include remote-utils.h.
+ * target.h: Add comment about target_has_execution.
+
+Thu Oct 7 16:14:19 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * h8300-tdep.c (sim_load, sim_kill, sim_open, sim_set_args):
+ New functions.
+ * infrun.c (normal_stop): Don't try and set the pc in the current
+ frame coredump if there isn't one.
+ * remote-sim.c (gdbsim_store_register): Don't
+ SWAP_TARGET_AND_HOST, sim_store_register takes bytes in raw order.
+ (gdbsim_wait): Set status with WSETSTOP.
+ * config/h8300/tm-h8300.h (sr_get_debug): Define
+
+Thu Oct 7 12:56:57 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ New Mach stuff:
+ * config/i386/i386mach.c: Explain this is for the old (probably
+ non-functional and/or obsolete) Mach stuff.
+ * m3-nat.c, config/nm-m3.h,
+ i386m3-nat.c, mipsm3-nat.c, ns32km3-nat.c,
+ config/i386/{i386m3.mh,i386m3.mt,tm-i386m3.h,xm-i386m3.h},
+ config/i386/{i386mk.mh,i386mk.mt,tm-i386mk.h,xm-i386mk.h},
+ config/mips/{mipsm3.mh,mipsm3.mt,tm-mipsm3.h,xm-mipsm3.h},
+ config/ns32k/{ns32km3.mh,ns32km3.mt,tm-ns32km3.h,xm-ns32km3.h}:
+ New files.
+
+ * blockframe.c (find_pc_partial_function): If we call
+ PSYMTAB_TO_SYMTAB, call target_terminal_ours_for_output first.
+ This is needed now that wait_for_inferior passes in endaddr.
+ * infrun.c: Move call to target_terminal_inferior from proceed
+ to resume.
+
+Thu Oct 7 09:22:04 1993 Stu Grossman (grossman at cygnus.com)
+
+ * blockframe.c (find_pc_partial_function): Fix handling for PCs
+ beyond the end of the last function in an objfile.
+ * coff-solib.c (coff_solib_add): Use BFD to get fields from .lib
+ section.
+ * infrun.c (wait_for_inferior): Modify test for subroutine entry
+ to include pc out of bounds of the previous function.
+ * remote.c (remote_wait): Use strtoul for parsing 'N' message.
+ Add code to relocate symfile_objfile->sections.
+
+Thu Oct 7 06:22:43 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/sparc/sun4os4.mh: Add comment saying why we don't use
+ -lresolv.
+
+Thu Oct 7 09:29:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c, breakpoint.h (breakpoint_init_inferior): New function
+ that clears the `inserted' flag for all breakpoints and deletes
+ any breakpoints which should go away between runs of programs.
+ * inflow.c (generic_mourn_inferior), infrun.c (init_wait_for_inferior),
+ remote-es.c (es1800_load), comments in exec.c and corelow.c:
+ Use it instead of mark_breakpoints_out.
+ * breakpoint.c (mark_breakpoints_out): Update comment, tm-rs6000.h
+ uses it in a completely different context.
+ * breakpoint.c (breakpoint_re_set_one): Add bp_call_dummy case.
+
+Thu Oct 7 09:29:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * Makefile.in (REGEX, REGEX1): Always use our own version of
+ regex.c to be consistent across hosts.
+ * source.c (_initialize_source): Initialize regex to use grep
+ style syntax as an approximation to POSIX basic regex syntax.
+
+Wed Oct 6 12:43:47 1993 Jeffrey A Law (law@snake.cs.utah.edu)
+ Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c (frame_chain): Rework so that it correctly
+ handles boundaries where code with a frame pointer calls code
+ without a frame pointer.
+ (dig_fp_from_stack): New function.
+
+Wed Oct 6 12:43:47 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (delete_breakpoint): Don't insert a disabled breakpoint.
+
+ * README: Add Alpha notes from Schauer.
+
+Tue Oct 5 15:26:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (install, uninstall): Remove $$n.1 stuff; I don't
+ understand what it is trying to do, but I suspect it's not doing
+ it.
+
+ * config/ns32k/merlin.mh: Add comment about M_INSTALL.
+ * config/m88k/{delta88.mh,delta88v4.mh}: Remove M_INSTALL and
+ M_UNINSTALL; it tries to install a non-existent file gdb.z.
+ * Makefile.in: Remove M_INSTALL stuff; the above were the only uses.
+
+ * stabsread.c (read_range_type): Remove comment which recommends
+ distinguishing float from complex by the name.
+
+Tue Oct 5 12:17:40 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ Jim Kingdon (kingdon@cygnus.com)
+ Stu Grossman (grossman@cygnus.com)
+
+ Changes to support alpha OSF/1 in native mode.
+ * alpha-nat.c, alpha-tdep.c, config/alpha/alpha-osf1.mt,
+ config/alpha/nm-alpha.h, config/alpha/tm-alpha.h, osfsolib.c:
+ New files.
+ * Makefile.in: Add new files and dependencies.
+ * configure.in: Add alpha target.
+ * config/alpha/alpha-osf1.mh (NATDEPFILES): Add osfsolib.o
+ * config/alpha/alpha-osf1.mh (MH_CFLAGS): Remove, we can handle
+ shared libraries now.
+ * config/alpha/xm-alpha.h: Cleanup, get MAKEVA_* defines right.
+
+ * defs.h (CORE_ADDR): Make its type overridable via CORE_ADDR_TYPE,
+ provide `unsigned int' default.
+ * breakpoint.c (breakpoint_auto_delete): Delete only if we really
+ stopped for the breakpoint.
+ * stabsread.c, stabsread.h (define_symbol): Change valu parameter
+ to a CORE_ADDR.
+ * stabsread.c (read_range_type): Handle the case where the lower
+ bound overflows and the upper doesn't and the range is legal.
+ * infrun.c (resume): Do not step a breakpoint instruction if
+ CANNOT_STEP_BREAKPOINT is defined.
+
+ * inferior.h (CALL_DUMMY_LOCATION): New variant AT_ENTRY_POINT.
+ Now that we have the bp_call_dummy breakpoint the call dummy code
+ is no longer needed. PUSH_DUMMY_FRAME, PUSH_ARGUMENTS and
+ FIX_CALL_DUMMY can be used to set up everything for the dummy.
+ The breakpoint for the dummy is set at the entry point and thats it.
+ * blockframe.c (inside_entry_file, inside_entry_func): Do not stop
+ backtraces if pc is in the call dummy at the entry point.
+ * infcmd.c (run_stack_dummy): Handle AT_ENTRY_POINT case. Use
+ the expected breakpoint pc when setting up the frame for
+ set_momentary_breakpoint.
+ * symfile.c (entry_point_address): New function for AT_ENTRY_POINT
+ support.
+ * valops.c (call_function_by_hand): Handle AT_ENTRY_POINT case.
+
+Tue Oct 5 11:37:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Recognize hppa*-*-hiux* (currently synonym for hpux).
+ Change other hppa host entries to use -*- not -hp-.
+
+Mon Oct 4 19:16:14 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i386-nlmstub.c: New file; debugging stub for i386 NetWare. Must
+ be compiled with NetWare header files and turned into an NLM with
+ nlmconv.
+
+Mon Oct 4 11:02:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * minsyms.c (lookup_minimal_symbol_by_pc): Don't use mst_abs symbols.
+
+ * dbxread.c (process_one_symbol): Make n_opt_found static.
+
+ * Rename i386lynx-tdep.c to i386ly-tdep.c for 14 character file names.
+ * Makefile.in, config/i386/i386lynx.mt: Change accordingly.
+
+ * values.c (record_latest_value): Fetch lazy values and set VALUE_LVAL
+ to not_lval.
+
+Sun Oct 3 15:54:51 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * objfiles.h (objfile): New slot sym_stab_info, use by most
+ stab-reading formats.
+ * gdb-stabs.h (DBX_SYMFILE_INFO): Access sym_stab_info instead of
+ sym_private.
+ * coffread.c (coff_symfile_init): Alloc struct for sym_stab_info.
+ * dbxread.c, elfread.c, paread.c: Change sym_private references to
+ sym_stab_info references.
+
+Sat Oct 2 19:28:35 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mipsread.c, objfiles.c, utils.c: Use PTR not void *. RISC/OS
+ 4.02 lacks void *.
+ * elfread.c: Use void * not PTR inside PARAMS.
+
+ * config/mips/news-mips.mh: Remove coredep.o; mips-nat.o does it.
+ * config/mips/news-mips.mh: Define NAT_FILE not NM_FILE.
+ * config/mips/nm-news-mips.h: Include mips/nm-mips.h not nm-mips.h.
+
+Sat Oct 2 16:05:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in, coff-solib.c, coff-solib.h, i386lynx.mt,
+ tm-i386lynx.h: Add support for SVR3 COFF shared libraries.
+
+Sat Oct 2 15:50:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m88k-nat.c (store_inferior_registers): When writing all registers,
+ don't try to write EXIP_REGNUM or ENIP_REGNUM (not needed for this
+ case, and they cause trouble).
+
+ * TODO: Don't suggest doing fast watchpoints by stepping a line
+ at a time. That would be really hairy and still not fast enough.
+ Do suggest debug registers and page table diddling.
+
+Fri Oct 1 14:54:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (do_examine): Make meaning of 'h', 'w', and 'g' not
+ depend on builtin_type_*. Instead, it is always 2, 4, and 8 bytes
+ like the documentation says.
+ * printcmd.c (decode_format) [CC_HAS_LONG_LONG]: Remove 'l' as
+ synonym for 'g'. This was never documented, it shouldn't depend on
+ CC_HAS_LONG_LONG, and I don't see what's wrong with 'g'.
+
+Fri Oct 1 10:06:35 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * symtab.c: fix a bug in testsuite (virtfunc.exp)
+
+Thu Sep 30 11:30:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m88k-nat.c (fill_gregset): Fix typo (R_SFIP -> R_FIP).
+
+ * c-typeprint.c (c_type_print_base, TYPE_FN_FIELD_STUB code):
+ If demangled name lacks a colon, don't dump core.
+
+ * blockframe.c (find_pc_partial_function): If pst->readin is
+ set, don't try to get symbols from pst.
+
+ * inflow.c (generic_mourn_inferior): Call reinit_frame_cache
+ instead of doing it ourself.
+ * blockframe.c (reinit_frame_cache): Use code which was in
+ generic_mourn_inferior so we can use this function even when
+ we have switched targets.
+ * corelow.c (core_detach): Call reinit_frame_cache.
+ * target.c (target_detach): Don't call generic_mourn_inferior
+ (revert yesterday's change, now handled by core_detach).
+ * objfiles.c (free_objfile): Detach any core file if we call
+ SOLIB_CLEAR. #include target.h.
+
+ * fork-child.c (fork_inferior): Don't call target_terminal_init
+ and target_terminal_inferior until we are sure that the inferior
+ has called gdb_setpgid. This fixes PR 2900 (Schauer tracked it
+ down and was able to reliably reproduce it by putting a sleep()
+ before the gdb_setpgid()).
+
+Thu Sep 30 12:00:49 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-exp.y, m2-exp.y: Change type of address for msymbol to
+ builtin_type_long.
+ * infptrace.c (fetch_register, store_inferior_register,
+ child_xfer_memory): Use PTRACE_XFER_TYPE for the type of ptrace
+ transfers. Provide an `int' default for PTRACE_XFER_TYPE.
+
+Thu Sep 30 11:30:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h (TARGET_*_BIT): Don't use host information (sizeof) in
+ picking defaults.
+
+ * cp-valprint.c (cp_is_vtbl_ptr_type): Continue to accept old form.
+
+Thu Sep 30 11:25:55 1993 Kung Hsu (kung@cygnus.com)
+
+ * cp-valprint.c (cp_is_vtbl_ptr_type):
+ change vtable field name to __vtbl (pr2695).
+
+ * symtab.c (gdb_mangle_name): fix a bug, to get mangled name right.
+
+Wed Sep 29 18:34:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add deps for i386lynx-nat.o and i386lynx-tdep.o to
+ keep non-gnu makes happy.
+
+Wed Sep 29 17:20:54 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hpux_symtab): When a K_END is found for a
+ K_MODULE, clear the have_module and have_name flags.
+
+Wed Sep 29 10:52:19 1993 Kung Hsu (kung@cygnus.com)
+
+ * c-valprint.c: to fix virtual table print bug (pr2695).
+
+Wed Sep 29 10:52:19 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c (target_detach): Call generic_mourn_inferior.
+ * inflow.c (generic_mourn_inferior): Call flush_cached_frames.
+
+Tue Sep 28 23:08:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c, coffread.c, elfread.c: A few changes to comments.
+
+Tue Sep 28 18:39:37 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * configure.in: Rename ...-lynx* to ...-lynxos*.
+ Add m68*-*-lynxos* configuration.
+ * dbxread.c (coffstab_build_psymtabs): New function,
+ interfaces coffread.c to dbxread functions.
+ * coffread.c (coff_symfile_info): Expand to include
+ dbx_symfile_info slots.
+ (coff_symfile_init): Init coff_symfile_info struct.
+ (coff_locate_sections): New functions, finds the stab and stabstr
+ sections.
+ (coff_symfile_read): Call coffstab_build_psymtabs if a stab
+ section is present.
+ (coff_section_offsets): Replace fake version with real offsets.
+
+Tue Sep 28 18:00:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c (run_stack_dummy): Set the frame in the bp_call_dummy
+ breakpoint.
+
+Tue Sep 28 17:53:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/nm-sysv4.h: Include solib.h. Define SVR4_SHARED_LIBS.
+ * config/tm-sysv4.h: Don't include solib.h.
+ * config/xm-sysv4.h: Don't define SVR4_SHARED_LIBS.
+ * config/i386/i386v4.mt (TDEPFILES): Move solib.o from here...
+ * config/i386/i386v4.mh (NATDEPFILES): ...to here.
+ * config/i386/nm-i386v4.h: Include nm-sysv4.h.
+ * config/m68k/amix.mt (TDEPFILES): Move solib.o from here...
+ * config/m68k/amix.mh (NATDEPFILES): ...to here.
+
+Tue Sep 28 09:45:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (print_symbol): Use %02x not %2x for LOC_CONST_BYTES.
+
+ Clean up problems with targets and hosts that have 64 bit longs
+ and pointers and 32 bit ints.
+ * breakpoint.c, buildsym.c, c-lang.c, c-valprint.c, ch-lang.c,
+ ch-valprint.c, core.c, cp-valprint.c, dbxread.c, exec.c,
+ expprint.c, gdbtypes.c, infcmd.c, language.c, language.h,
+ m2-lang.c, maint.c, mips-tdep.c, mipsread.c, partial-stab.h,
+ printcmd.c, remote-vx.c, solib.c, source.c, stack.c, symfile.c,
+ symmisc.c, symtab.c, valops.c, valprint.c, xcoffexec.c:
+ Change all printf formats from %x to %lx if outputting an address.
+ Change la_*_format to use long format.
+ local_hex_string, local_hex_string_custom now take an unsigned long
+ argument, change all callers.
+ * coffread.c (read_coff_symtab): Remove superfluous cast for
+ complaint output.
+ * dbxread.c (end_psymtab): Cast MSYMBOL_INFO to long, not int.
+ * findvar.c, value.h (write_register): Change val to LONGEST.
+ * gdbtypes.h (struct type): Change `bitsize' to long as
+ TYPE_FIELD_STATIC_PHYSNAME uses this field as a pointer.
+ * inferior.h (struct inferior_status): Change type of stop_pc to
+ CORE_ADDR.
+ * language.h (local_octal_string, local_octal_string_custom):
+ Remove prototype, the functions are neither defined nor used.
+ * mipsread.c (parse_symbol): Use temporary variable for bitsize as
+ f->bitsize is a long now.
+ * objfiles.c (add_to_objfile_sections, build_objfile_section_table):
+ Use unsigned long casts instead of int for abusing sections_end
+ pointer as integer.
+ * stack.c (parse_frame_specification): Change type of `args' to
+ CORE_ADDR for SETUP_ARBITRARY_FRAME.
+
+ * printcmd.c (make_vasize): Allow redefinition via MAKEVA_SIZE.
+ * mipsread.c (parse_type): Alpha cc now supports the t->continued
+ bit, update algorithm to match the way the compiler uses it.
+
+Tue Sep 28 12:05:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (fprintfi_filtered): Fix comments.
+
+Mon Sep 27 18:10:08 1993 Stu Grossman (grossman at cygnus.com)
+
+ * coffread.c (read_coff_symtab): Don't call getfilename if there
+ are no auxents.
+
+Mon Sep 27 10:22:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (find_pc_line): Fix comments.
+
+ * remote-udi.c (udi_mourn): Don't pop target.
+
+Fri Sep 24 17:25:41 1993 Stu Grossman (grossman at cygnus.com)
+
+ * corelow.c: Add multi thread/process support for core files with
+ .reg/XXX pseudo-sections.
+ * i386lynx-nat.c thread.h thread.c: Remove unnecessary core file
+ support.
+
+Thu Sep 23 10:49:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (download): Skip zero length sections.
+
+ * valops.c (search_struct_method, value_struct_elt):
+ Use (value)-1, not -1, for error.
+
+ * infcmd.c (step_1), infrun.c (wait_for_inferior): Add comments
+ about SHIFT_INST_REGS.
+
+ * exec.c (exec_file_command): Set text_end based on all code readonly
+ sections, not just ".text".
+
+ * defs.h, infcmd.c, config/z8k/tm-z8k.h, config/m88k/tm-m88k.h,
+ config/sh/tm-sh.h, config/h8300/tm-h8300.h, config/h8500/tm-h8500.h,
+ z8k-tdep.c: Remove all references to ADDR_BITS_SET.
+ * config/m88k/tm-m88k.h: Define TARGET_WRITE_PC.
+
+ * config/m88k/tm-m88k.h, m88k-tdep.c: Add call function stuff.
+
+Thu Sep 23 00:13:06 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-mips.h (STORE_STRUCT_RETURN): Define as noop as
+ the pushing of the struct return address is already handled in
+ mips_push_arguments.
+ * mips-tdep.c (reinit_frame_cache_sfunc): Fix typo in prototype
+ declaration.
+ * mipsread.c (parse_symbol, parse_type, upgrade_type): Add more
+ sanity checks for corrupt symbol entries to avoid core dumps
+ reported by benson@odi.com. Obviously Ultrix 4.3A cc now has
+ the same problems as the OSF/1 alpha cc.
+ * mipsread.c (parse_lines): Iterate over the range of the compressed
+ line number entries, the old iteration sometimes failed to stop
+ and wrote past the end of the LINETABLE. Add sanity check to avoid
+ the same problem in case the line number info is corrupt.
+ * mipsread.c (parse_procedure): Adjust pdr for alpha __sigtramp.
+ * mipsread.c (parse_external, parse_partial_symbols): Ignore stNil
+ symbols that are produced for statics in .o files and stLocal symbols
+ that are produced for every section in OSF/1 dynamically linked
+ executables.
+ * mipsread.c (psymtab_to_symtab_1): Put out `undefined symbols'
+ warning only under `verbose on' as there are many undefined symbols
+ in a dynamically linked executable.
+
+Wed Sep 22 10:28:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i960/nindy960.mt: Don't define REMOTE_O; REMOTE_O was
+ intended only for VxWorks. Remove dcache.o from TDEPFILES now
+ that we pick it up from the default REMOTE_O.
+
+ * breakpoint.c (bpstat_what): Initialize retval.call_dummy and
+ retval.step_resume.
+
+ * mips-tdep.c (mips_frame_chain): If frame size zero, return zero.
+ * rs6000-tdep.c: Add comment about framelessness.
+
+ * remote-nindy.c: Declare ninMemGet and ninMemPut.
+
+Wed Sep 22 08:02:57 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add i386lynx-tdep to the right places.
+ (TARDIRS): Add gdbserver.
+
+ * exec.c (print_section_info): Print entry point.
+ * i386lynx-nat.c (i386lynx_saved_pc_after_call): Move into
+ i386lynx-tdep.c. Add core file support.
+ * i386lynx-tdep.c: New module for Lynx/386 target dependant code.
+ * maint.c: Add `maint info sections' command to print info about all
+ sections that BFD knows about for exec and core files.
+ * sparc-tdep.c (sparc_push_dummy_frame): Update stack pointer
+ before putting frame on the stack. Consolidate writes to reduce
+ traffic for remote debugging.
+ * config/i386/i386lynx.mh (NATDEPFILES): Remove exec.o.
+ * config/i386/i386lynx.mt (TDEPFILES): Add exec.o, i386lynx-tdep.o.
+ * config/i386/nm-i386lynx.h: Add target_pid_to_str().
+ * config/i386/tm-i386lynx.h: Remove target_pid_to_str().
+ * sparclite/Makefile.in: Add deps to keep Sun make happy.
+
+Tue Sep 21 17:48:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.h, breakpoint.c (bpstat_stop_status): Add new argument
+ not_a_breakpoint.
+ * infrun.c (wait_for_inferior): Pass it. Also consolidate the
+ test of whether we are stepping into a CURRENTLY_STEPPING macro.
+
+Tue Sep 21 17:22:34 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * breakpoint.c (bpstat_stop_status),
+ infcmd.c (step_1),
+ infrun.c (wait_for_inferior): collapse SHIFT_INST_REGS ifdef
+ and insert macro.
+
+ * m88k-tdep.c: include ieee-float.h. new global target_is_m88110.
+ new const struct ext_format_m88110 for float format.
+ (pic_prologue_code): add braces.
+ (next_insn): remove unused variable buf.
+ (frame_find_saved_regs): remove unused variables next_addr,
+ saved_regs, regnum.
+ (frame_locals_address): remove unused variables frame, ap.
+ (frame_args_address): remove unused variables frame, ap.
+ (push_parameters): add some breaks and a default case.
+
+ * remote-bug.c: remove redundant includes of value.h, target.h,
+ serial.h.
+ (bug_open): corrected typo, sr_multi_scan -> gr_multi_scan.
+ (bug_fetch_register): special case sfip register for m88110.
+ remove flag bit masking of pc registers. This should be handled
+ by the ADDR_BITS_* macros.
+ (bug_store_register): special case sfip register for m88110.
+ Corrected sprint format for extended registers.
+
+ * config/m88k/tm-m88k.h: white space and comment changes. include
+ ieee-float.h. expanded to cope with m88110 extended registers.
+ (R0_REGNUM, XFP_REGNUM, X0_REGNUM): new macros.
+ (SHIFT_INST_REGS): becomes a real macro.
+
+Tue Sep 21 17:48:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Support bp_call_dummy.
+
+Tue Sep 21 17:06:19 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * elfread.c (record_minimal_symbol_and_info): Guess the section to
+ use from the type.
+ * objfiles.c: Include gdb-stabs.h for SECT_* macros.
+ (objfile_relocate): Relocate textlow and texthigh in psymtabs.
+ Relocate partial symbols. Check that minimal SYMBOL_SECTION is
+ nonnegative before using it.
+ * symtab.h: Adjust section field comment.
+
+ * remote.c (interrupt_query): New function.
+ (remote_interrupt_twice): Call interrupt_query.
+ (putpkt, getpkt): If quit_flag is set, call interrupt_query.
+ (remote_wait): Don't bother with objfile_relocate if the addresses
+ haven't changed.
+ (remote_fetch_registers): If we see a packet that doesn't start
+ with a hex character, fetch a new one.
+
+Tue Sep 21 11:44:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c, remote-utils.c: Use SERIAL_FLUSH_INPUT after opening it.
+
+ * printcmd.c (print_scalar_formatted): When truncating value we are
+ going to print as unsigned, handle it generally for any length
+ less than sizeof (LONGEST), rather than special-casing sizeof (char),
+ sizeof (short), and sizeof (long). Clarify comment on what this
+ is for.
+
+ * symfile.c (deduce_language_from_filename): Accept .cxx for C++.
+ * buildsym.c (start_subfile): Use deduce_language_from_filename
+ rather than checking for .C or .cc ourself.
+
+Mon Sep 20 14:53:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h: Declare argument of re_comp as const char *.
+
+ * remote.c, remote-mips.c: Use sr_get_debug not remote_debug.
+
+ * README: Say using bfd from another release doesn't generally work.
+
+Sat Sep 18 10:13:18 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * mipsread.c (parse_type): Don't complain() if we guessed struct
+ and it was a union, or vice versa.
+
+ * defs.h (make_cleanup): Change PTR to void * when inside PARAMS.
+
+ Some of the following is in #ifdef CALL_DUMMY_BREAKPOINT_OFFSET.
+ * breakpoint.h (enum bptype): Add bp_call_dummy.
+ (struct bpstat_what): Add call_dummy field.
+ * infrun.c (wait_for_inferior): Deal with it.
+ * breakpoint.c (bpstat_what): Deal with call dummy breakpoint.
+ * infcmd.c (run_stack_dummy): Set the call dummy breakpoint.
+ * config/sparc/tm-sparc.h: Define CALL_DUMMY_BREAKPOINT_OFFSET.
+
+ * remote-sim.h: New file.
+ * remote-sim.c: Add remote debug feature. Rename stuff to distinguish
+ interface to simulator from gdb-specific stuff. Other changes.
+ * remote-sp64sim.c: Renamed to remote-sim.c.
+ Use sr_get_debug instead of our own sim_verbose/simif_snoop.
+ Use gnutarget in call to bfd_openr.
+ Rename simif_* to gdbsim_*.
+ * config/sparc/sp64sim.mt: Change remote-sp64sim.c to remote-sim.c.
+
+Fri Sep 17 04:41:17 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * findvar.c (extract_signed_integer): Cast *p to LONGEST before doing
+ the xor and subtract. Otherwise it will not sign extend if the type
+ of LONGEST is larger than int.
+ * cp-valprint.c (cp_print_class_method): Inhibit core dump if
+ domain is an undefined cross reference.
+ * valops.c (call_function_by_hand): Set real_pc to correct
+ value if CALL_DUMMY_LOCATION != ON_STACK.
+
+Thu Sep 16 20:37:06 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * config/a29k/tm-a29k.h (FRAME_CHAIN): If rsize is zero, return zero.
+
+Thu Sep 16 13:16:22 1993 Stu Grossman (grossman at cygnus.com)
+
+ * infrun.c (wait_for_inferior): Allow user to single step within
+ a stack dummy.
+
+Thu Sep 16 12:34:01 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * dbxread.c (copy_pending): Deal with END NULL.
+ (process_one_symbol): Add comments about what common_block NULL means.
+
+Wed Sep 15 14:50:26 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * remote-udi.c, remote-adapt.c, remote-mm.c: Move processor_type
+ to tm-a29k.h and a29k-tdep.c and make it an enum.
+ * a29k-tdep.c (a29k_get_processor_type): New function. Fix many
+ aspects of how we detected the processor type.
+ * remote-udi.c, remote-adapt.c, remote-mm.c (*_open): Call it
+ rather than figuring out the type ourselves.
+
+Thu Sep 16 12:12:59 1993 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c (_trap_low): Do restore/save sequence after
+ setting sp to ensure that we load the previous window from the
+ right place on the stack.
+
+Thu Sep 16 00:36:32 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c: Many changes for alpha ecoff format:
+ Correct sizeof(int) == sizeof(long) assumptions.
+ Replace stParsed hack by putting the parsed types on the pending chain.
+ Replace mips specific ecoff mapping by ECOFF_REG_TO_REGNUM macro,
+ provide default for cross debugging.
+ Swapping the symbol back is no longer needed as the symbol is not
+ modified anymore.
+ Add new alpha basic types, handle btTypedef, handle stStaticProc
+ external symbols .
+ Update and clean up cross_ref for alpha cc cross ref variations.
+ Allocate types on the type_obstack to inhibit storage leaks.
+ * config/mips/tm-mips.h (ECOFF_REG_TO_REGNUM): Define.
+ * gdbtypes.c (recursive_dump_type): Dump TYPE_TAG_NAME if it is set.
+
+Tue Sep 14 09:12:17 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * stabsread.c (read_type): Process "s" (size) type attribute.
+ If type is defined to another type, copy the type.
+
+Tue Sep 14 18:37:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * config/i386/i386v4.mh (NATDEPFILES): Move exec.o from here...
+ * config/i386/i386v4.mt (TDEPFILES): ...to here.
+
+Tue Sep 14 12:21:49 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (remote_utils_h): add serial.h and target.h.
+ (main.o, remote-es.o, remote-nindy.o, remote.o): remove target.h
+ (already in remote_utils_h).
+ (remote-utils.o): new rule.
+
+ * remote-utils.h: include serial.h.
+
+ * serial.h: ifdef protect from multiple inclusion.
+
+ * remote.c, remote-nindy.c, remote-mon.c, remote-es.c: include
+ remote-utils.h.
+
+ * remote.c (remote_open), remote-nindy.c (nindy_open,
+ nindy_files_info), remote-mon.c (general_open), remote-es.c
+ (es1800_open): use remote-utils facilities for baud rate.
+
+Tue Sep 14 09:12:17 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * paread.c, coffread.c, elfread.c, dwarfread.c:
+ Include <time.h> and <sys/types.h> before libbfd.h.
+
+ * paread.c: Define BYTES_IN_WORD before including aout/aout64.h.
+
+ * Makefile.in (a29k-tdep.o): Depend on $(defs_h).
+ * config/a29k/tm-a29k.h (SAVED_PC_AFTER_CALL): Use gr122 not lr0
+ if this is a transparent procedure.
+
+Mon Sep 13 16:06:43 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * remote.c: Define remote_debug to 0 and #if 0 baud_rate. Temporary
+ hack so this file compiles again.
+
+ * remote-utils.c (gr_multi_scan): Cast return value from alloca.
+ (gr_multi_scan): #if 0 never-reached return(-1).
+
+ * remote-udi.c (udi_wait): Return inferior_pid not 0.
+
+Mon Sep 13 14:14:35 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Collect some remote things into remote-utils.
+ * remote-utils.[ch]: new files of functions collected from several
+ different remote targets.
+ * Makefile.in (REMOTE_O): add remote-utils.o.
+ (dcache_h, remote_utils_h): new macros.
+ (HFILES): add $(remote_utils_h).
+ (ALLDEPFILES): add $(remote_utils_h).
+ (dcache.o): new rule.
+ (main.o, remote-bug.o): also depend on $(remote_utils_h).
+ * target.h (remote_debug): extern moved to remote-utils.h.
+ * target.c (find_default_run_target, find_core_target): initialize
+ runable.
+ (remote_debug): moved to remote-utils.c.
+ (_initialize_targets): move declaration of user variable
+ remotedebug to remote-utils.c.
+ * remote-bug.c: include remote-utils.h rather than dcache.h.
+ (bug_close, bug_write, bug_write_cr, desc, bug_dcache, timeout,
+ dev_name, check_open, is_open, readchar, readchar_nofail,
+ pollchar, expect, expect_prompt, get_hex_digit, get_hex_byte,
+ get_hex_word, bug_kill, bug_detach, bug_create_inferior,
+ multi-scan, bug_prepare_to_store, bug_fetch_word,
+ bug_store_word, bug_files_info, bug_mourn, bug_com, bug_device,
+ bug_speed): removed and replaced with facilities from
+ remote-utils.[ch].
+ (bug_read_inferior_memory): renamed to bug_read_memory.
+ (bug_write_inferior_memory): renamed to bug_write_memory.
+ (bug_xfer_inferior_memory): renamed to bug_xfer_memory.
+ (get_word): comment out this unused function for now.
+ (bug_settings, cpu_check_strings): new statics.
+ (bug_open): rewritten to use gr_open.
+ (_initialize_remote_bug): remove declarations of commands bug,
+ device, speed.
+ * main.c: include remote-utils.h.
+ (baud_rate): removed to remote-utils.c.
+ (main): handle baud rate settings using new facilities from
+ remote-utils.
+ * defs.h (baud_rate): removed extern.
+
+ m88110 support via bug-197 monitor.
+ * remote-bug.c (get_reg_name, bug_fetch_register,
+ bug_store_register): added m88110 extended register support.
+ (wait_strings): added bug-197 prompt.
+ (bug_wait): cope with bug-197 prompt.
+ (start_load): cope with either bug-197 or bug-187 prompt.
+
+Mon Sep 13 12:53:09 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * inferior.h, infrun.c, thread.c, infcmd.c: Remove all uses of
+ pc_changed. If it was ever set to a non-zero value, it was before
+ GDB 2.8. It doesn't seem to have any useful function.
+
+ * defs.h: Don't define NORETURN (see comment).
+
+Sat Sep 11 10:46:09 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * m88k-nat.c (fill_gregset): Set r31 and sfip.
+
+Thu Sep 9 10:18:29 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (udi_wait, case UDIStdinNeeded): Use a loop calling
+ getchar() (terminated only on '\n') instead of scanf. Send the
+ '\n' which terminates it to the remote system.
+
+ More gcc lint:
+ * exec.c (ignore): Return 0.
+ * stack.c (return_command): Fetch lazy value directly, not via
+ VALUE_CONTENTS, to avoid "value computed is not used".
+ * inflow.c (new_tty): Move osigttou inside #if.
+
+ * remote.c (remote_fetch_registers): If remote reply is short, just
+ note that fact and keep going (reading extra registers as all bits 0).
+ (remote_store_registers): Send number of registers that were found
+ by remote_fetch_registers.
+ * m68k-tdep.c, config/m68k/tm-m68k.h, config/m68k/tm-*.h: Remove
+ HAVE_68881. Define CANNOT_STORE_REGISTER if ptrace() can't write
+ floating registers.
+ * config/m68k/{tm-m68k-nofp.h,m68k-nofp.mt,tm-m68k-fp.h,m68k-fp.mt}:
+ Remove, replaced by {tm-m68k-em.h,m68k-em.mt}.
+ * Makefile.in, configure.in: Change accordingly.
+
+Thu Sep 9 04:59:03 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (cross_ref): Allow SGI extended symbol types as cross
+ reference targets.
+ * symmisc.c (print_symbol): Use TYPE_TAG_NAME not TYPE_NAME to avoid
+ printing of identities.
+
+Wed Sep 8 19:18:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Deal with step resume breakpoint.
+
+Wed Sep 8 13:01:10 1993 K. Richard Pixley (rich@cygnus.com)
+
+ Gcc lint.
+ * config/m88k/tm-m88k.h (frame_find_saved_regs): prototype.
+ * config/h8300/tm-h8300.h (NUM_REGS): rewrite to avoid nested comment.
+ * blockframe.c (get_prev_frame_info): initialize address.
+ * breakpoint.c (bpstat_copy): initialize retval.
+ (bpstat_stop_status): initialize value_is_zero.
+ (bpstat_what): initialize bs_class.
+ (breakpoint_1, mention): add do-nothing case for bp_step_resume.
+ (break_command_1): initialize cond_end, addr_end, &
+ canonical_strings_chain.
+ (enable_breakpoint): initialize save_selected_frame.
+ * buildsym.c (end_symtab): initialize symtab & linetablesize.
+ * c-exp.y (parse_number): initialize i.
+ * c-typeprint.c (c_type_print_varspec_prefix): include
+ TYPE_CODE_BITSTRING in switch statements and do nothing.
+ * c-valprint.c (c_val_print): removed unused variable c.
+ * ch-valprint.c (chill_val_print): removed unused variable eltlen.
+ * cp-valprint.c (cp_print_class_method): initialize f & j.
+ * eval.c (evaluate_subexp): initialize pc2, arg1, arg2.
+ * expprint.c (print_subexp): initialize myprec, assoc, & tempstr.
+ * findvar.c (value_from_register): initialize first_addr.
+ * gdbtypes.c (lookup_struct_elt_type): localize use of temporary
+ variable typename.
+ * infcmd.c (run_stack_dummy): return zero rather than simple
+ return.
+ * infrun.c (wait_for_inferior): initialize stop_sp, prologue_pc.
+ remove symtab, appears unused.
+ (restore_selected_frame): return 1.
+ * mipsread.c (psymtab_to_symtab_1): initialize first_off.
+ (fixup_sigtramp): initialize b0.
+ * printcmd.c (do_examine): initialize val_type.
+ (print_frame_args): initialize b.
+ * ser-tcp.c (tcp_restore): comment out declaration. Appears
+ unused.
+ * ser-unix.c (hardwire_restore): comment out declaration. Appears
+ unused.
+ (hardwire_send_break): moved variable status into ifdef
+ HAVE_SGTTY.
+ (wait_for): moved variable numfds into ifdef HAVE_SGTTY.
+ * serial.h: comment change only.
+ * stabsread.c (rs6000_builtin_type): initialize rettype.
+ (read_range_type): initialize nbits.
+ * stack.c (print_frame_info): remove unused variable numargs.
+ (parse_frame_specification): remove unused variables arg1, arg2,
+ arg3.
+ (return_command): initialize return_value.
+ * symfile.c (cashier_psymtab): initialize pprev.
+ * symtab.c (find_pc_psymbol): initialize best.
+ (lookup_symbol): initialize s.
+ (make_symbol_completion_list): initialize quote_pos.
+ * thread.c: include command.h.
+ (thread_info): static declaration removed; unused.
+ (info_threads_command): fix == vs = typo.
+ * typeprint.c (whatis_exp): initialize old_chain.
+ * valprint.c (val_print_string): remove unused variable
+ first_addr_err. Initialize old_chain.
+ (_initialize_valprint): white space comment change.
+ * values.c (show_values): rewrite if statement to avoid empty
+ body.
+ (vb_match): remove unused variable fieldtype_target_type.
+
+Wed Sep 8 10:21:33 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (mipsread.o): Depend on $(bfd_h).
+
+Tue Sep 7 13:06:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/Makefile.in (TAGS): config files are in
+ $(srcdir)/../config, not $(srcdir)/config.
+
+ * config/pa/tm-hppa.h: Declare target_read_pc and target_write_pc.
+ (STORE_RETURN_VALUE): Pass the correct offset of the return
+ register to write_register_bytes.
+ * hppa-tdep.c: Use target_write_pc if PCOQ_TAIL_REGNUM was not saved.
+
+Tue Sep 7 14:30:34 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote.c (remote_wait): Don't call error. Instead, call warning
+ inside a loop. User can ^C to get out.
+
+ * config/m68k/tm-m68k.h (FIX_CALL_DUMMY): Changed name of swapping
+ routine to match BFD name change.
+ * config/z8k/tm-z8k.h (FIX_CALL_DUMMY): Likewise.
+
+Mon Sep 6 15:01:57 1993 Jeffrey Wheat (cassidy@cygnus.com)
+
+ * elfread.c: change elf32_symbol_type to elf_symbol_type
+
+Mon Sep 6 15:43:25 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote.c (remote_wait): Added 'W' and 'N' responses.
+
+Fri Sep 3 08:57:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c, utils.c: Add comments about immediate_quit.
+
+ * elfread.c (elf_symtab_read): Don't add symbols starting with ".L"
+ to minimal symbols.
+
+ * target.c (pop_target): Don't try to deal with the stack becoming
+ empty. Shouldn't happen and the code that tried was broken.
+
+ * dcache.c: Cast return value from xmalloc.
+
+ * remote.c: Move setting of immediate_quit from remote_open to
+ remote_start_dummy and set it back to zero when done.
+
+Thu Sep 2 00:07:36 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m88k-tdep.c: Remove a bunch of unused #includes.
+
+ * language.h: Add comment about current_language.
+
+ * mips-tdep.c (_initialize_mips_tdep): Change heuristic-fence-post
+ from var_uinteger to var_zinteger.
+
+ * configure.in: Fix typo (delta88r4 -> delta88v4).
+
+ * config/m88k/xm-delta88.h: Don't include sys/siginfo.h. It was
+ to make this work on SVR4 before SVR4 had its own configuration,
+ and it breaks SVR3.
+
+ * config/m88k/tm-delta88v4.h: Define FRAME_CHAIN_VALID_ALTERNATE.
+
+ * config/m88k/delta88v4.h (NATDEPFILES): Remove infptrace.o inftarg.o.
+
+ * config/m88k/xm-dgux.h: Renamed from config/m88k/xm-m88k.h.
+ * config/m88k/m88k.mh: Use xm-dgux.h.
+ * config/m88k/xm-m88k.h: New file, with HOST_BYTE_ORDER,
+ MAKEVA_END and MAKEVA_ARG.
+ * config/m88k/xm-*.h: Include m88k/xm-m88k.h.
+ * printcmd.c: Remove __INT_VARARGS_H code; now in xm-m88k.h.
+
+Wed Sep 1 19:31:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (udi_wait): Call `warning' not `error'.
+
+ * symtab.c (COMPLETION_LIST_ADD_SYMBOL): If the symbol has a
+ demangling, don't put the mangled form in the completion list.
+
+ * symtab.c, symfile.c, c-exp.y, ch-exp.y, m2-exp.y, buildsym.c,
+ symfile.h, stabsread.c, minsyms.c, solib.c, nlmread.c, dwarfread.c
+ partial-stab.h, symmisc.c, gdbtypes.c: Lint. Remove (or put
+ inside #if) unused variables and labels. Fix unclosed comment.
+ Deal with enumeration values unhandled in switch statements. Make
+ sure non-void functions return values. Include appropriate
+ headers.
+ * dbxread.c (elfstab_build_psymtabs): Don't check for unsigned
+ value < 0.
+
+Wed Sep 1 14:36:00 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * i960-tdep.c, ns32k-pinsn.c, remote-adapt.c, xcoffread.c:
+ index -> strchr.
+
+Wed Sep 1 11:35:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c: Add comment explaining why dcache is disabled.
+ (remote_fetch_word, remote_store_word): Make static and #if 0.
+ They are not called from anywhere.
+
+Wed Sep 1 14:41:28 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * arm-tdep.c, convex-tdep.c, convex-xdep.c, dbxread.c,
+ h8300-tdep.c, h8500-tdep.c, i960-pinsn.c, i960-tdep.c,
+ infptrace.c, m88k-tdep.c, mips-tdep.c, regex.c, remote-vx.c,
+ rs6000-tdep.c, xcoffexec.c, xcoffread.c, z8k-tdep.c,
+ config/arm/tm-arm.h, config/convex/tm-convex.h,
+ config/gould/tm-np1.h, config/gould/tm-pn.h,
+ config/m68k/tm-isi.h, config/ns32k/tm-umax.h,
+ config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/rs6000/tm-rs6000.h, config/tahoe/tm-tahoe.h,
+ config/vax/tm-vax.h: bzero -> memset.
+
+ * regex.c: bcmp -> memcmp.
+
+Wed Sep 1 11:35:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (find_pc_line, find_line_common),
+ symtab.h (struct linetable), xcoffread.c (arrange_linetable):
+ Revise comments re linetable sorting.
+ * buildsym.c (compare_line_numbers): Sort by pc, not by line.
+ * coffread.c: Tell end_symtab to sort the line table.
+
+ * coffread.c: Re-work a lot of the coff-specific stuff to use stuff
+ in buildsym.c. This includes coff_finish_block, coff_context_stack,
+ coff_local_symbols, coff_file_symbols, coff_global_symbols,
+ coff_end_symtab and coff_add_symbol_to_list.
+ (read_enum_type): Deal with it now that we have a "struct pending"
+ not a "struct coff_pending".
+
+ * buildsym.c (end_symtab): Don't realloc subfile->linetable.
+
+Wed Sep 1 13:12:43 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * a68v-nat.c, altos-xdep.c, convex-tdep.c, convex-xdep.c,
+ findvar.c, hppab-nat.c, hppah-nat.c, i386mach-nat.c,
+ irix4-nat.c, m68k-tdep.c, m88k-tdep.c, mipsread.c, regex.c,
+ remote-bug.c, remote-hms.c, rs6000-nat.c, rs6000-tdep.c,
+ sparc-nat.c, stabsread.c, sun3-nat.c, sun386-nat.c, symfile.c,
+ umax-xdep.c, xcoffread.c, 29k-share/udi/udip2soc.c,
+ 29k-share/udi/udr.c, config/a29k/tm-a29k.h, config/arm/tm-arm.h,
+ config/convex/tm-convex.h, config/gould/tm-np1.h,
+ config/gould/tm-pn.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/i386/tm-i386aix.h,
+ config/i386/tm-sun386.h, config/i386/tm-symmetry.h,
+ config/i960/tm-i960.h, config/m68k/tm-news.h,
+ config/m88k/tm-m88k.h, config/mips/tm-mips.h,
+ config/ns32k/tm-merlin.h, config/ns32k/tm-umax.h,
+ config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/rs6000/tm-rs6000.h, config/sh/tm-sh.h,
+ config/tahoe/tm-tahoe.h, config/vax/tm-vax.h,
+ config/z8k/tm-z8k.h, nindy-share/nindy.c: bcopy -> memcpy.
+
+Wed Sep 1 05:05:53 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_partial_symbols): Use language from FDR if it
+ is unambigous. Patch from ptf@delcam.co.uk (Paul Flinders).
+ * mipsread.c (ecoff_symfile_info): New struct to hold the global
+ pending_list.
+ * mipsread.c (mipscoff_symfile_init, parse_partial_symbols):
+ Allocate the global pending list and link it to the objfile.
+ * mipsread.c (is_pending_symbol, add_pending): Use global pending
+ list from objfile. Allocate pending list entries from the
+ psymbol_obstack.
+ * mipsread.c (free_pending): Remove. The pending list is now
+ freed when the psymbol_obstack is freed.
+ * mipsread.c (psymtab_to_symtab1): Remove pending list allocation,
+ the global pending list is used now.
+ * mipsread.c (parse_partial_symbols): Skip only the first
+ file indirect entry when building the dependency list.
+
+Tue Aug 31 15:01:27 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Break dcache code out of remote.c.
+ * dcache.h: white space changes only.
+ * dcache.c: add user settable variable to set whether data caching
+ is in use.
+ * remote.c: include dcache.h. removed data caching code which is
+ now in dcache.c. Compile in data caching again. (data caching
+ is currently off by default.)
+ (remote_read_bytes, remote_write_bytes): change second arg to
+ unsigned char.
+ (remote_dcache): new static variable.
+ * Makefile.in (REMOTE_O): add dcache.o.
+ * config/m88k/m88k.mt (TDEPFILES): removed dcache.o.
+
+ Break dcache code out of remote-nindy.c.
+ * remote-nindy.c: removed dcache code. Changed callers to use new
+ conventions. include dcache.h.
+ (nindy_dcache): new static variable.
+ * config/i960/nindy960.mt (TDEPFILES): added dcache.o.
+
+ Break dcache code out of remote-bug.c into dcache.[hc].
+ * Makefile.in (dcache_h): new macro.
+ (HFILES): added $(dcache_h).
+ (ALLDEPFILES): added dcache.c.
+ (dcache.o): new rule.
+ (remote-bug.o): now depends on $(dcache_h).
+ * remote-bug.c: include dcache.h. remove externs for insque and
+ remque, add extern for bcopy. Prototype bug_close,
+ bug_clear_breakpoints, bug_write_cr. dcache code moved to
+ dcache.[hc]. Changed dcache calling convention to include an
+ initial DCACHE argument.
+ (bug_dcache): new static variable.
+ (bug_read_inferior_memory): change second arg to
+ unsigned char.
+ * dcache.[ch]: new files.
+ * config/m88k/m88k.mt (TDEPFILES): add dcache.o.
+
+Tue Aug 31 10:33:13 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-typeprint.c (c_print_type_base): Treat show = 0 just like
+ show < 0. The only case where we had been distinguishing is that
+ show = 0 used to print "struct " or "enum " instead of
+ "struct {...}" or "enum {...}" which seems clearly wrong.
+
+Mon Aug 30 17:51:32 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * configure.in: recognize m88110 as an m88k.
+
+Mon Aug 30 16:07:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (call_function_by_hand): If we discard cleanups, call
+ bpstat_clear (&inf_status.stop_bpstat).
+
+Mon Aug 30 12:47:46 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.h, dbxread.c (end_psymtab): Return NULL if the psymtab
+ was empty and thrown away.
+ * mipsread.c (parse_partial_symbols): Do not add empty psymtabs to
+ dependency list, skip self dependencies.
+ * mipsread.c (parse_fdr): Removed, obsolete.
+ * mipsread.c (parse_lines): Check for cbLine being zero, not
+ cbLineOffset.
+ * mipsread.c (struct symloc): Add pst_language.
+ * mipsread.c (parse_partial_symbols): Set up proper language for
+ header files, save it in pst_language for psymtab_to_symtab_1.
+ * mipsread.c (psymtab_to_symtab_1): Use pst_language.
+
+Mon Aug 30 10:48:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Fix typo m88*-motorola-svr4* -> sysv4*.
+
+Fri Aug 27 17:09:19 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * paread.c: Include som.h instead of libhppa.h. (From Utah.)
+
+Fri Aug 27 09:30:40 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * symmisc.c (dump_symtab): Use catch_errors around print_symbol.
+ Change calling sequence of print_symbol to fit catch_errors.
+
+ * mips-tdep.c: Call reinit_frame_cache every time the user does
+ "set heuristic-fence-post".
+
+ * gdbserver/low-sun3.c: New file.
+ * gdbserver/Makefile.in, config/m68k/sun3.mh: Change accordingly.
+
+ * Rename files for 14-character limits:
+ gdbserver/remote-gutils.c -> gdbserver/utils.c
+ gdbserver/remote-inflow.c -> gdbserver/low-lynx.c
+ gdbserver/remote-inflow-sparc.c -> gdbserver/low-sparc.c
+ gdbserver/remote-server.c -> gdbserver/server.c
+ remote-monitor.c -> remote-mon.c
+ * Makefile.in, gdbserver/Makefile.in, gdbserver/configure.in,
+ config/m68k/monitor.mt, config/i386/i386lynx.mh,
+ config/sparc/sun4os4.mh: Change accordingly.
+ * gdbserver/Makefile.in: Remove more junk inherited from gdb Makefile.
+
+Thu Aug 26 14:32:51 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c, inferior.h (run_stack_dummy): If we stop somewhere
+ besides the dummy, return 1 rather than calling error().
+ Let caller print the error message. Remove name argument.
+ * valops.c (call_function_by_hand): Deal with changes to calling
+ sequence of run_stack_dummy. Discard restore_inferior_status cleanup
+ if run_stack_dummy returns 1.
+
+ * Version 4.10.2.
+
+ * config/mips/tm-mips.h (EXTRACT_STRUCT_VALUE_ADDRESS):
+ Get struct return address from v0, not a0.
+
+ * infrun.c (restore_inferior_status): Use catch_errors when
+ restoring selected frame.
+
+Wed Aug 25 21:52:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (save_inferior_status, restore_inferior_status):
+ Save and restore the registers too.
+ * inferior.h (struct inferior_status): Add "registers".
+
+Tue Aug 24 00:36:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (end_psymtab): Clean up comment.
+
+ * frame.h, symtab.h, findvar.c (read_var_value): Change basereg
+ support to use LOC_BASEREG rather than SYMBOL_BASEREG_VALID.
+ * dwarfread.c: Use LOC_BASEREG where appropriate.
+ * Various: Support LOC_BASEREG and LOC_BASEREG_ARG.
+
+ * coffread.c (init_lineno, init_stringtab): Don't check whether
+ xmalloc returned NULL.
+
+ * config/vax/xm-vaxult.h: Define NO_PTRACE_H.
+
+ * target.c, target.h: Add "set remotedebug" command.
+ * remote-bug.c, remote.c, remote-mips.c: Remove "set remotedebug" and
+ "set m88ksnoop" options and use generic "set remotedebug" instead.
+ * NEWS: Describe this change.
+
+Mon Aug 23 20:26:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * buildsym.h: Remove declaration of dbxread.c functions.
+ * stabsread.h: Group together dbxread.c functions.
+ Move elfstab_build_psymtabs here from symfile.h.
+ Declare pastab_build_psymtabs.
+ * elfread.c, paread.c: Include stabsread.h (for stabsread_new_init
+ declaration, etc).
+
+Mon Aug 23 17:16:23 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remote-bug.c: rename quiet to bug88k_snoop.
+ (double_scan, multi_scan): generalize double_scan into a scan
+ for multiple patterns. Rename to multi_scan.
+ (bug_wait, bug_write_inferior_memory): adapt to use the new
+ multi_scan in order to catch and represent target bus errors.
+ (bug_scan): currently unused, so comment out.
+ (bug_quiet): removed. Replaced with a standard user settable boolean.
+
+ * m88k-tdep.c: remove include of sys/dir.h. Appears unnecessary
+ and isn't available on solaris.
+
+Mon Aug 23 14:56:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m88k/{delta88v4.mt,delta88v4.mh}: New files
+ * config/m88k/delta88.mh: Fix comment.
+ * config/m88k/tm-delta88.h: Remove unused BCS define.
+ * config/m88k/{tm-delta88v4.h,xm-delta88v4.h,nm-delta88v4.h}:
+ New files.
+ * configure.in: Recognize m88*-motorola-sysv4*.
+ * m88k-nat.c: Always include sys/types.h; don't depend on USG.
+
+Mon Aug 23 12:57:42 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_symbol, parse_type, cross_ref): Pass name of
+ symbol as an argument and use it in complaints.
+ * symmisc.c (dump_psymtab): Dump filenames of dependencies.
+
+Mon Aug 23 1993 Sean Fagan (sef@cygnus.com)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ Add NetBSD support:
+ * configure.in: Recognize netbsd.
+
+Sun Aug 22 22:50:32 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (get_textlow): Don't go past a K_END when looking for a
+ K_FUNCTION. Avoids losing on source files with no functions.
+
+Fri Aug 20 14:01:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-nindy.c: Remove unused include of sys/ioctl.h.
+
+ * frame.h, symtab.h: Revise comments regarding baseregs.
+
+Fri Aug 20 15:07:05 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_partial_symbols, psymtab_to_symtab_1):
+ Set language for psymtab and symtab.
+ * mipsread.c (new_symbol): Set language and initialize demangled
+ name for symbol.
+ * symmisc.c (print_symbol): Use SYMBOL_SOURCE_NAME when printing
+ the symbol type.
+ * symtab.c (decode_line_1): Inhibit coredumps with cfront executables.
+
+Fri Aug 20 14:01:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Move KERNEL_U_ADDR from xm-hp300bsd.h to nm-hp300bsd.h and make
+ it conditionalized on 4.3 vs. 4.4.
+ * config/m68k/nm-hp300bsd.h: Move REGISTER_U_ADDR out of 4.3 and
+ 4.4 sections; it was identical and now works for 4.4.
+
+ * mips-tdep.c (is_delayed): Use INSN*BRANCH* not ANY_DELAY.
+
+ * printcmd.c (MAKEVA_END): Update this version to use "aligner".
+
+Thu Aug 19 22:08:09 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/vax/tm-vax.h (BELIEVE_PCC_PROMOTION): Define.
+ * mipsread.c (parse_symbol, parse_type, cross_ref): Handle corrupt
+ file indirect entries with complaints instead of core dumps. Remove
+ complaint for stTypedef within aggregates.
+
+Thu Aug 19 17:58:39 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (process_coff_symbol): Ignore tagnames like .0fake.
+
+ * coffread.c (coff_read_enum_type): #if 0 out code which changes
+ enum {FALSE, TRUE} into boolean.
+
+ * config/m68k/delta68.m{t,h}: Use nm-delta68.h, etc. not
+ non-existent files nm-delta.h, etc.
+ * config/m68k/tm-delta68.h: Define CANNOT_STORE_REGISTER.
+ * delta68-nat.c: Add "[0]" in offsetof argument.
+ * delta68-nat.c (_initialize_kernel_u_addr): Don't try to set up
+ nl with initializer, just assign to it. Check n_scnum field on
+ return.
+
+Wed Aug 18 21:42:52 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hpux_symtab): Call SET_NAMESTRING for K_MODULE
+ debug symbols.
+
+Wed Aug 18 12:03:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_address), values.c (value_as_pointer): Don't
+ use ADDR_BITS_REMOVE.
+ * defs.h: Try to clarify comment about ADDR_BITS_REMOVE.
+
+ * blockframe.c (block_innermost_frame): Uncomment.
+ Return NULL if passed NULL.
+ * frame.h: Declare it.
+ * expression.h (union exp_element): Add field block.
+ * parse.c (write_exp_elt_block): New function.
+ * expression.h (OP_VAR_VALUE): Now takes additional struct block *.
+ * *-exp.y: Write block for OP_VAR_VALUE.
+ * eval.c, expprint.c, parse.c: Deal with block for OP_VAR_VALUE.
+ * valops.c, value.h (value_of_variable), callers:
+ Add second argument, for block.
+
+ * main.c (gdb_readline): If we read some characters followed by EOF,
+ return them rather than returning NULL.
+
+Tue Aug 17 11:14:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c: Remove unused #ifndef NUMERIC_REG_NAMES and add comment.
+
+Tue Aug 17 15:10:04 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * config/m88k/tm-m88k.h: Fix typo in comment.
+ (FP_REGNUM): define in terms of SP_REGNUM
+ rather than by absolute number. Also clearly comment that this
+ is a convenient lie in order to decrease future confusion.
+ (ACTUAL_FP_REGNUM): new macro for FP.
+ (FRAME_CHAIN_VALID): removed. Standard default works fine.
+ * m88k-tdep.c (frame_chain_valid): redundant, so removed.
+ (NEXT_PROLOGUE_INSN): removed unused fourth arg, fixed all
+ callers.
+ (read_next_frame_reg): declare static.
+ (examine_prologue): removed unused variabel insn2, rename insn1
+ to insn, rewrote comment about finding fp, sp, etc. set frame_fp
+ based on ACTUAL_FP_REGNUM rather than FP_REGNUM which is
+ actually a scammed alias for SP_REGNUM on m88k.
+
+ * frame.h: fixed typo in comment.
+
+Tue Aug 17 11:14:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * 29k-share/udi/udiphcfg.h: Always include udiphunix.h not udiphdos.h.
+
+ * complaints.c (complain): fflush (stdout) after output.
+
+Tue Aug 17 01:43:55 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c, frame.h (sigtramp_saved_pc): New routine to fetch
+ the saved pc from sigcontext on the stack for BSD signal handling.
+ * config/i386/tm-i386bsd.h (SIGTRAMP_START, SIGTRAMP_END, FRAME_CHAIN,
+ FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC, SIGCONTEXT_PC_OFFSET):
+ Define to make backtracing through sigtramp work.
+ * config/vax/tm-vax.h (SIGTRAMP_START, SIGTRAMP_END, TARGET_UPAGES,
+ FRAME_SAVED_PC, SIGCONTEXT_PC_OFFSET): Ditto.
+
+Mon Aug 16 13:52:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (cd_command): If current_directory on entry is "/", then
+ don't append an extra slash.
+ Don't assume that /../.. means /.
+
+ * target.c (target_xfer_memory): Clear errno before calling
+ to_xfer_memory.
+
+ * stack.c (frame_info, print_frame_info): Add comment about using
+ the starting source line number on a line boundary if backtracing
+ through sigtramp.
+
+Mon Aug 16 09:52:33 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Add U Utah contribution notice. Add TODO list.
+ (hp_type_lookup): Use TYPE_NAME and TYPE_TAG_NAME.
+ (process_one_debug_symbol): Likewise.
+
+Mon Aug 16 02:56:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (create_new_frame, get_prev_frame_info):
+ Use the function name when calling IN_SIGTRAMP.
+ * config/m68k/tm-m68k.h (SIG_PC_FP_OFFSET, SIG_SP_FP_OFFSET):
+ Define for correct handling of bachtraces through _sigtramp.
+ * m68k-tdep.c (m68k_find_saved_regs): Adjust saved sp for fake
+ sigtramp frames.
+ * mipsread.c (parse_type): Handle corrupt TIR info with complaint
+ instead of core dump.
+ * mipsread.c (parse_partial_symbols): Put static symbols into the
+ mimimal symbol table, use proper mst_types for all minimal symbols.
+ * stack.c (frame_info, print_frame_info): Use the starting source
+ line number on a line boundary if backtracing through sigtramp.
+
+Fri Aug 13 14:37:05 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remote-bug.c: include gdbcmd.h.
+ (sleep, remque, insque): forward decls added.
+ (bug_fetch_registers, bug_store_registers): forward decls
+ removed.
+ (bug_read_inferior_memory, bug_write_inferior_memory): forward
+ decls added.
+ (srec_frame, srec_max_retries, srec_bytes, srec_echo_pace,
+ srec_sleep, srec_noise): new static variables for user settable
+ options. Mostly these are for debugging and tuning. I don't
+ expect them to stay user settable options for long.
+ (timeout): change default to 4 seconds.
+ (check_open): declare funtion static, force return value.
+ (readchar_nofail): if timeout, then say so if not being quiet.
+ (pollchar, double_scan, bug_scan, bug_srec_write_cr,
+ start_load): new functions.
+ (bug_wait): rewritten to use double scan.
+ (expect): while (1) -> for (;;)
+ (get_hex_digit): rewrite if condition to avoid gcc complaints.
+ (bug_load, bug_create_inferior, bug_open, bug_store_register):
+ removed unused variables.
+ (bug_load): replaced DELTA macro with user settable srec_frame
+ variable. Other minor lint.
+ (find_end_of_word, is_baudrate_right, set_rate, not_bug_wait,
+ gethex, timed_read, translate_addr, bug_before_main_loop):
+ unsused and removed.
+ (bug_resume): add missing first arg, pid.
+ (get_reg_name): use ip rather than cr04.
+ (bug_write, bug_write_cr, but_clear_breakpoints, bug_quiet):
+ declare type, args, and explicitly return.
+ (bug_store_register): straighten out the ip vs cr04 confusion.
+ (bug_write_inferior_memory): rewrite to cope with errors while
+ downloading s-records.
+ (bug_read_inferior_memory): declare static.
+ (bug_clear_breakpoints): expect nobr before prompt.
+ (_initialize_remote_bug): add initializations for srec-bytes,
+ srec-max-retries, srec-frame, srec-noise, srec-sleep,
+ srec-echo-pace.
+
+ * Makefile.in (remote-bug.o): new rule.
+ (ALLDEPFILES): added remote-bug.c
+
+ * remote-hms.c (hms_wait): use -1 for timeout's which means block
+ forever rather than 99999.
+
+ * ser-unix.c (get_tty_state): if a descriptor is not a tty, then
+ simply save encode this fact as the process group and return
+ success rather than an error.
+ (set_tty_state): if process group is -1, do not reset the
+ process group.
+ (hardwire_reachar): comment change.
+
+ * serial.h: comment change.
+
+ * config/m88k/tm-m88k.h: comment change to remove embedded
+ comment.
+ (SKIP_PROLOGUE): skip_prologue returns a value which is expected
+ to reset the pc argument. So reset it.
+
+Fri Aug 13 10:15:24 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.10.1 after release and cvs
+ tagging.
+
+Thu Aug 12 20:40:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/Makefile.in: Use GDBSERVER_LIBS and
+ GDBSERVER_DEPFILES. Also remove much (but not all that could be
+ removed) crud inherited from gdb Makefile.in.
+ * config/i386/i386lynx.mh, config/sparc/sun4os4.mh: Define GDBSERVER_*.
+ * gdbserver/README: Say it works on Sun and change configuration
+ instructions slightly.
+
+Wed Aug 11 18:56:59 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * config/i386/i386v4.mh: use -lsocket and -lnsl, for remote
+ targets that use BSD style network connections
+
+Wed Aug 11 17:54:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-{monitor,bug}.c: Make bug_ops not static (forward declaration
+ of statics doesn't work with SunOS4 /bin/cc).
+ Rename the occurrence in remote-monitor.c to monitor_bug_ops.
+
+Tue Aug 10 13:07:14 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * blockframe.c (find_pc_partial_function),
+ mips-tdep.c (find_proc_desc): Deal with "pathological" case.
+
+Tue Aug 10 14:50:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (wrap_here): Allow indent to be NULL.
+ (fputs_filtered): Don't check for null wrap_indent (wrap_here now
+ guarantees that it isn't, and anyway we were only checking one out
+ of the two places we dereferenced it).
+
+ * objfiles.h (struct objfile): Clean up comments for
+ {obj,sym}_private to clarify what they are private to.
+
+Mon Aug 9 16:45:00 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * stabsread.c, buildsym.c (hashname): Moved function to
+ buildsym.c, as suggested in the sources.
+
+Mon Aug 9 09:53:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c: Make udi_ops extern rather than trying forward
+ declaration of a static variable.
+
+ * hppab-nat.c: Define ptrace to call_ptrace and pass the 5th arg
+ there, rather than using an ANSI C specific macro.
+
+ * 29k-share/udi/udr.c: Include fcntl.h not sys/fcntl.h. Also put
+ sys/types.h near the top (just on general principles).
+
+ * environ.c (set_in_environ): Remove G960BASE and G960BIN; they are
+ no longer used.
+
+ * gdbcore.h: New variable gnutarget.
+ * core.c: Add commands to set and show it.
+ * Callers to bfd_*open*: Pass gnutarget instead of NULL as target.
+ * environ.c (set_in_environ): For GNUTARGET, use set_gnutarget not
+ putenv.
+
+ * symtab.c (decode_line_1): Give error on unmatched single quote.
+
+Sun Aug 8 13:59:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ser-unix.c (hardwire_send_break) [HAVE_SGTTY]: Use select not usleep.
+
+ * remote.c: Add comments about 'd', 'r', and unrecognized requests.
+
+ * inflow.c (terminal_init_inferior): Don't muck with tty state if
+ gdb_has_a_terminal() is false.
+
+Sun Aug 8 10:07:47 1993 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (record_minimal_symbol): Remove prototype and
+ function.
+ * dwarfread.c (add_partial_symbol): Remove code to add minimal
+ symbols and remove comment about limitations. Experiments show
+ that now that gdb handles the ELF symtab better for creating
+ minimal symbols, that no additional information is added by
+ examining the DWARF information, and in fact, given the
+ limitations, the DWARF code was actually making things worse.
+
+Sat Aug 7 10:59:03 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * elfread.c (elf_symtab_read): Properly sort out the bss symbols
+ from the data symbols and give them the correct minimal_symbol_type.
+ Add file static symbols to the minimal symbol table, not just
+ global symbols. Add absolute symbols as well (like _edata, _end).
+ Redo stabs-in-elf special symbol handling now that file static
+ symbols are entered into the into the minimal symbol table.
+ * dwarfread.c (add_partial_symbol): Add comment about limitations
+ of DWARF symbols for distinquishing data from bss when adding
+ minimal symbols. Add file local symbols to minimal symbols.
+
+Thu Aug 5 08:58:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ser-go32.c: Define job_control variable.
+
+Thu Aug 5 15:56:13 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * configure.in: z8k-coff is the same as z8k-sim
+
+Thu Aug 5 08:58:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * 29k-share/udi/udip2soc.c: Include sys/types.h before sys/file.h.
+
+ * config/i386/tm-i386bsd.h (NUM_REGS): There are only 10, not 11.
+
+ * inflow.c: Put all uses of F_GETFL and F_SETFL in #ifdef F_GETFL.
+
+ * 29k-share/udi/udip2soc.c: Include fcntl.h not sys/fcntl.h.
+
+Wed Aug 4 18:32:12 1993 Fred Fish (fnf@cygnus.com)
+
+ * inflow.c (pass_signal): Signal handlers take one int arg;
+ supply an unused one to make it type compatible as an arg to
+ signal().
+
+Tue Aug 3 18:34:14 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/mips/tm-mips.h: Include bfd.h before coff/sym.h.
+
+Tue Aug 3 15:34:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (ALLCONFIG): Add config/i386/i386nw.mt,
+ config/m68k/delta68.mh, config/m68k/delta68.mt,
+ config/m68k/dpx2.mh, config/m68k/dpx2.mt, config/mips/riscos.mh,
+ config/mips/news-mips.mh.
+ * Makefile.in (ALLPARAM): Add config/i386/nm-symmetry.h,
+ config/i386/tm-i386nw.h, config/m68k/nm-delta68.h,
+ config/m68k/tm-delta68.h, config/m68k/xm-delta68.h,
+ config/m68k/nm-dpx2.h, config/m68k/tm-dpx2.h,
+ config/m68k/xm-dpx2.h, config/mips/xm-makeva.h.
+ * Makefile.in (ALLDEPFILES): Add dpx2-nat.c.
+
+Tue Aug 3 12:02:09 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c: Updated for BFD ECOFF changes. Now gets the
+ swapping routines and external structure sizes via the
+ ecoff_backend information. No longer includes coff/mips.h.
+
+Tue Aug 3 10:58:04 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SFILES): Add thread.c
+
+Tue Aug 3 10:21:58 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sp64sim.c (simif_create_inferior): Add FIXME regarding
+ sim_set_args return code.
+
+Mon Aug 2 16:35:31 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (VERSION): bumped to 4.9.4.
+
+ * remote-monitor.c: updated copyright.
+ (bug_ops, monitor_desc): now static.
+ (monitor_desc): in several places, check and/or set to NULL.
+
+ * remote-hms.c (hms_files_info): Add the appropriate items where
+ missing in the printf call.
+
+ * remote-bug.c: new file for m88k bug support.
+
+ * config/m88k/m88k.mt (TDEPFILES): added remote-bug.o.
+
+Mon Aug 2 14:22:09 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * h8300-tdep.c: Use new variable h8300hmode.
+
+Mon Aug 2 12:06:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (typecmp): If we are passing a non-reference to a function
+ which takes a reference, pass the address.
+ (value_arg_coerce): Don't use COERCE_ENUM; we don't want to dereference
+ references here.
+
+ * thread.c (thread_switch): Define as static.
+ (add_thread): Cast return value from xmalloc.
+
+ * gdbtypes.c (fill_in_vptr_fieldno): Call check_stub_type.
+ * gdbtypes.{c,h}: Improve comments on vptr_fieldno.
+
+Mon Aug 2 11:58:52 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * README: Elaborate on gdb C++ support and cfront support.
+
+Mon Aug 2 11:30:57 1993 Stu Grossman (grossman at cygnus.com)
+
+ * i386lynx-nat.c, thread.c, thread.h: Update copyrights.
+
+Mon Aug 2 12:06:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (ALLDEPFILES): Add i386lynx-nat.c.
+
+Mon Aug 2 08:42:50 1993 Stu Grossman (grossman at cygnus.com)
+
+ * gdbserver/remote-inflow.c (create_inferior): Fix comments, and
+ error msg. Setup seperate process group for child.
+ * (write_inferior_memory): Sleep for 1 second and retry on ptrace
+ failure.
+
+Sun Aug 1 22:58:18 1993 Stu Grossman (grossman at cygnus.com)
+
+ * config/i386/i386lynx.mh (NATDEPFILES): Drop coredep (for now).
+ * config/i386/nm-i386bsd.h: Protect from multiple inclusion.
+ * config/i386/nm-i386lynx.h: Lotsa new host porting stuff.
+ * config/i386/tm-i386lynx.h: Define SAVED_PC_AFTER_CALL and
+ target_pid_to_str.
+
+ * Makefile.in (CLIBS): Reorder to make Lynx ld happy.
+ * (HFILES): New file thread.h.
+ * (OBS): New file thread.c.
+ * configure.in: Host config for Lynx/386.
+ * fork-child.c (fork_inferior): Call init_thread_list().
+ * infrun.c (resume): Add pid to invocation of target_resume().
+ * (wait_for_inferior): Pay attention to pid from target_wait().
+ Multi-threading code now uses this to determine what to do.
+ * inftarg.c (child_wait): Conditionalize based on CHILD_WAIT macro.
+ Use target_pid_to_str() macro throughout when printing pid.
+ * inferior.h (child_resume): Add pid to prototype.
+ * hppab-nat.c hppah-nat.c infptrace.c (child_resume): Pass in pid as
+ argument, instead of using inferior_pid.
+ * procfs.c (procfs_resume): Pass in pid as argument. Ignored for
+ now. Use target_pid_to_str() macro throughout for printing process id.
+ * remote-adapt.c (adapt_resume): Pass in pid as argument.
+ * remote-eb.c (eb_resume): Pass in pid as argument.
+ * remote-es.c (es1800_resume): Pass in pid as argument.
+ * remote-hms.c (hms_resume): Pass in pid as argument.
+ * remote-mips.c (mips_resume): Pass in pid as argument.
+ * remote-mm.c (mm_resume): Pass in pid as argument.
+ * remote-monitor.c (monitor_resume): Pass in pid as argument.
+ * remote-nindy.c (nindy_resume): Pass in pid as argument.
+ * remote-sa.sparc.c (remote_resume): Pass in pid as argument.
+ * remote-sim.c (rem_resume): Pass in pid as argument.
+ * remote-sp64sim.c (simif_resume): Pass in pid as argument.
+ * remote-st.c (st2000_resume): Pass in pid as argument.
+ * remote-udi.c (udi_resume): Pass in pid as argument.
+ * remote-vx.c (vx_resume): Pass in pid as argument.
+ * remote-z8k.c (rem_resume): Pass in pid as argument.
+ * remote.c (remote_resume): Pass in pid as argument.
+ * solib.c (solid_create_inferior_hook): Pass inferior_pid to
+ target_resume().
+ * target.c (normal_pid_to_str): New routine to print out process
+ ID normally.
+ * target.h (struct target_ops): Add pid to prototype at
+ to_resume(). (target_resume): Add pid argument.
+ * (target_pid_to_str): Default definition for normal type pids.
+ * thread.h, thread.c: New modules for multi thread/process control.
+
+Sun Aug 1 13:02:42 1993 John Gilmore (gnu@cygnus.com)
+
+ * README: Say that bug-gdb is also the place to send requests
+ for help with GDB.
+
+Sun Aug 1 09:42:13 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (make-proto-gdb-1): Use -f opt on rm of Makefile.
+ * h8500-tdep.c: Add parens around a few macro args.
+
+Fri Jul 30 15:43:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove items about unix-to-unix/rapp debugging (now we
+ have gdbserver), moving xm files to subdirectory, ptype yylval,
+ and file-local symbols.
+
+ * gdbtypes.h: Improve comments about C++ methods.
+
+Fri Jul 30 14:16:32 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * c-exp.y: Add missing 5th arg for one call to lookup_symbol, cast
+ NULL in all other calls to correct pointer types.
+
+Fri Jul 30 15:43:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ From Jeffrey Law:
+ * tm-hppa.h (TARGET_WRITE_PC): Define.
+ * hppa-tdep.c (hppa_fix_call_dummy): If in a syscall,
+ then return the address of the dummy itself rather than
+ the address of $$dyncall.
+ (target_write_pc): New function to store a new PC.
+
+Fri Jul 30 12:51:27 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Always reparse breakpoint
+ conditions, they might contain symbol table references.
+
+Fri Jul 30 12:51:27 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_symbol): Handle opaque struct definitions and
+ type naming for stTypedef symbols.
+
+Fri Jul 30 14:44:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Detect C++ nested types.
+
+Fri Jul 30 11:07:37 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * sp64-tdep.c (sparc64_frame_chain, sparc64_frame_saved_pc): Deleted.
+ (dump_ccreg, sparc_print_register_hook): New fns.
+ * remote-sim.h: New file.
+ * remote-sp64sim.h (sim_*): External fns. (simif_*): Internal fns.
+
+ * config/sparc/sp64.mt: New file.
+ * config/sparc/tm-sp64.h (FRAME_CHAIN, FRAME_SAVED_PC): Deleted.
+ (PRINT_REGISTER_HOOK): Call new fn sparc_print_register_hook.
+
+Fri Jul 30 10:15:01 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (ALLCONFIG): Add config/i386/ptx.mh
+
+Fri Jul 30 08:58:01 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ From J. Law:
+ * infcmd.c (read_pc): Remove PA specific code.
+ * tm-hppa.h (TARGET_READ_PC): Define.
+ * hppa-tdep.c (target_read_pc): New function.
+
+ * symtab.c (gdb_mangle_name): Deal with it if type lacks a name.
+
+Fri Jul 30 07:36:53 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * NEWS: Add note that DEC alpha support is host only, not native.
+ * README: Emphasize that C++ support works best with GNU C++ and
+ stabs debugging format.
+ * delta68-nat.c: Add missing FSF copyright.
+
+Fri Jul 30 08:58:01 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * paread.c (pa_symtab_read): Put file-local symbols in minimal symbols.
+ * hppa-tdep.c (frame_chain_valid): Check that our function has the
+ same address as _start, not that it must be the same symbol.
+
+Fri Jul 30 00:18:40 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (ALLDEPFILES): Add delta68-nat.c
+ * Makefile.in (delta68-nat.o): Add dependency.
+
+Thu Jul 29 12:09:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * value.h (COERCE_ENUM): Use COERCE_REF to coerce refs; value_ind
+ was adequate in gdb 3.5 but not now.
+
+ * valops.c (typecmp): An array in t2 matches a pointer in t1.
+
+ * valops.c (typecmp): When comparing type1& to type2, compare
+ type1 and type2 as leniently as if we were comparing type1 to
+ type2.
+
+ * cp-valprint.c (cplus_print_value): Don't dump core if the
+ baseclass doesn't have a name.
+ * values.c (vb_match): New function, which finds the virtual
+ base class pointer even if the types are nameless.
+ (baseclass_{addr,offset}): Use it.
+
+ * hppa-tdep.c: Make "maintenance print unwind" command from old
+ "unwind" command.
+
+ * remote-udi.c: Remove udi_timer, call to siginterrupt, and associated
+ obsolete junk which apparently had been copied from the
+ pre-serial.h remote.c, but which is no longer used.
+
+Thu Jul 29 12:36:20 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (NONSRC): Need 29k-share/README, not
+ 29k-share/udi/README.
+
+Thu Jul 29 12:09:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * paread.c (pa_symfile_init): If error reading string table, don't
+ use errno in cases where it hasn't been set.
+
+ * ser-unix.c (gdb_setpgid): Pass our pid, not 0, to setpgid.
+
+ * remote-monitor.c (_initialize_monitor): Comment out use of
+ connect_command, since connect_command itself is commented out.
+
+ * remote-monitor.c (generic_open): Parse arguments the same way
+ as remote.c.
+
+ * hppa-tdep.c (pc_in_linker_stub): Fix unclosed comments.
+
+Wed Jul 28 13:19:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/xm-mips.h: Define HAVE_TERMIOS.
+
+ * dbxread.c (record_minimal_symbol): Don't put gcc_compiled or
+ __gnu_compiled* symbols into the minimal symbols.
+
+Wed Jul 28 08:26:58 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-mips.c (_initialize_remote_mips): Added "timeout" and
+ "retransmit-timeout" variables to set mips_receive_wait and
+ mips_retransmit_wait, respectively.
+
+Wed Jul 28 03:58:58 1993 (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (dump_msymbols): Handle new mst_file_* types.
+
+Tue Jul 27 12:07:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c: Remove old comment about download not implemented.
+
+ * serial.h, ser-{unix,go32,tcp}.c: Add flush_input and send_break.
+ * nindy-share/*, remote-nindy.c: Extensive hacking to make it
+ conform to GDB conventions like using memcpy not bcopy, serial.h,
+ etc. This is to make it host on Solaris, AIX, etc.
+ * Makefile.in: Reflect removed nindy-share files.
+ * config/i960/nindy960.mt (TDEPFILES): Remove ttybreak.o.
+
+ * stack.c (print_frame_info): Revise comment about `pathological'
+ case (there was a wrong FIXME about text labels; also asm() can
+ trigger this as well as versions of ar which truncate .o names).
+
+ * buildsym.c (start_subfile): If a .c file includes a .C file, set
+ the language of both of them to C++.
+
+ * config/sparc/xm-sun4os4.h: Define MEM_FNS_DECLARED and include
+ <memory.h>.
+ Include <malloc.h> rather than declaring malloc functions ourself.
+
+ * ser-unix.c (set_tty_state): Don't ignore errors setting process
+ group.
+ * inflow.c (terminal_inferior): If attach_flag set, ignore errors
+ from set_tty_state.
+
+ * fork-child.c (fork_inferior): Only quote exec file if needed.
+
+ * mipsread.c (parse_symbol): Remove 21 Jul 93 change with
+ stTypedef inside an stBlock.
+
+Tue Jul 27 12:36:49 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (breakpoint_1): Walk the breakpoint chain to decide if
+ we have breakpoints or watchpoints as we might have to ignore internal
+ breakpoints.
+
+ Fix gdb core dumps after `file newfile' commands.
+ * symtab.h, symfile.c (clear_symtab_users): New routine which
+ unconditionally clears symtab users. clear_symtab_users_once
+ commented out as it was a noop anyway.
+ * objfiles.c (free_objfile): Don't call clear_symtab_users_once.
+ * objfiles.c (free_all_objfiles), symfile.c (new_symfile_objfile),
+ xcoffexec.c (exec_close): Call clear_symtab_users if necessary.
+ * symfile.c (syms_from_objfile): Install cleanups for errors during
+ symbol reading.
+ * coffread.c, dbxread.c, mipsread.c, xcoffread.c (*_symfile_read):
+ Lint cleanup code, call do_cleanups explicitly.
+ * symfile.c (symbol_file_add): Call new_symfile_objfile and
+ reinit_frame_cache _after_ the new symbols are read in.
+
+Tue Jul 27 01:57:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_type): Do not set tag name for compiler
+ generated fake tag names.
+
+Mon Jul 26 17:31:49 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * config/m88k/m88k.mt (TDEPFILES): add exec.o.
+
+Mon Jul 26 13:17:36 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c: Remove all uses of use_unwind and `set use_unwind'
+ command. Now we use unwind info by default if we can find it.
+
+ * config/sparc: Move VARIABLES_INSIDE_BLOCK and SUN_FIXED_LBRAC_BUG
+ to tm-sparc.h so they are shared between Solaris and SunOS4.
+ * dbxread.c (process_one_symbol): Deal with SunOS4 acc N_STSYM and
+ N_GSYM functions.
+
+ * config/pa/tm-hppa.h (REGISTER_NAMES): Use "fr" rather than "fp"
+ for floating point registers.
+
+ * mipsread.c (parse_symbol): Put stStaticProc symbols in minimal
+ symbols as mst_file_text.
+
+ * hppa-tdep.c (pc_in_linker_stub): Return 0 if can't read memory.
+
+ * stabsread.c (rs6000_builtin_type): Make logical types be
+ TYPE_CODE_BOOL.
+
+Sun Jul 25 23:41:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.{c,h} (struct breakpoint): Replace symtab field with
+ source_file field.
+
+Fri Jul 23 09:57:25 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote.c: Don't error() on errors xferring memory.
+ * target.h: Clean up comments about *xfer_memory.
+
+ * exec.c, corelow.c (target_ops struct): Don't allow
+ {insert,remove}_breakpoints to be defaulted to
+ memory_{insert_remove}_breakpoint.
+
+ * demangle.c: Make it so `help set dem' tells you how to get the
+ list of demangling styles.
+
+Thu Jul 22 15:41:09 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * Makefile.in: Use REMOTE_O macro not remote.o.
+ * config/i960/{nindy960,vxworks960}: Don't use remote.o.
+
+Thu Jul 22 12:43:25 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * coredep.c: If NEED_SYS_CORE_H defined, include <sys/core.h>
+ (can't include it in nm-*.h file because it causes conflicts with
+ a.out symbol definitions).
+ * hp300ux-nat.c (fetch_core_registers): Commented out; obsolete.
+ * config/m68k/hp300hpux.mh (NATDEPFILES): Added coredep.o and
+ corelow.o.
+ * config/m68k/nm-hp300hpux.h (NEED_SYS_CORE_H): Defined.
+ (REGISTER_U_ADDR): Defined.
+ * config/m68k/xm-hp300hpux.h (HAVE_TERMIOS): Define instead of
+ HAVE_TERMIO.
+ * config/pa/xm-hppah.h: Likewise.
+
+Wed Jul 21 11:37:30 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mipsread.c (parse_symbol): when stTypedef and friends occur within
+ an stBlock, skip over the fields of the inner one.
+
+ * mips-tdep.c (init_extra_frame_info): If in lenient prologue, call
+ heuristic_proc_desc rather than just assuming registers not saved.
+
+ * Makefile.in (regex.o): Add dependency.
+
+ * hppa{b,h}-nat.c: Warning, not error, if can't access registers.
+
+ * config/pa/hppa{b,h}.h: Define ATTACH_DETACH.
+
+Wed Jul 21 03:07:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/xm-makeva.h: New file implements va_list alignment
+ restrictions for mips hosts.
+ * config/mips/{xm-irix3.h, xm-mips.h, xm-news-mips.h, xm-riscos.h}:
+ Use it.
+
+Wed Jul 21 00:11:05 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (init_extra_frame_info): Do not check for
+ mips_in_lenient_prologue if it is a dummy frame.
+ * mipsread.c (fixup_sigtramp): Initialize pdr.adr, it is used by
+ mips_in_lenient_prologue.
+
+Tue Jul 20 14:14:59 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hp_array_type): Handle "char foo[]".
+
+Tue Jul 20 12:53:47 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mips-tdep.c (heuristic_proc_start): First time we print the
+ warning, elaborate.
+ (_initialize_mips_tdep): Improve docstring for `set heur'.
+
+ * config/rs6000/tm-rs6000.h: Remove call to insert_step_breakpoint.
+
+ * symtab.c (find_line_symtab): New function, to deal with multiple
+ symtabs with the same name.
+ (find_line_pc{,_range}): Use it.
+ (find_pc_symtab): Add comment about overlapping symtabs.
+
+Mon Jul 19 21:29:14 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * Makefile.in (SFILES): Add nlmread.c.
+ * Makefile.in (OBS): Add nlmread.o.
+ * Makefile.in (nlmread.o): Add new target.
+ * configure.in (i[34]86-*-netware): New configuration.
+ * nlmread.c, config/i386/{i386nw.mt, tm-i386nw.h}: New files
+ for NLM/NetWare support.
+
+Mon Jul 19 11:48:57 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * symtab.h (enum minimal_symbol_type): Add mst_file_*.
+ * partial-stab.h [DBXREAD_ONLY]: Record statics in miminal symbols.
+ * dbxread.c (record_minimal_symbol): Deal with statics.
+ * minsyms.c (lookup_minimal_symbol): Prefer externals to statics.
+
+ * config/i386/xm-i386sco.h: Define HAVE_TERMIOS.
+
+ * printcmd.c, config/pa/xm-pa.h, config/alpha/xm-alpha.h: Make it so
+ arg_bytes field of makeva_list is always aligned.
+ * config/pa/xm-pa.h: Make arglist_address a char *.
+
+ * ser-unix.c: Don't try to use job control with termio.
+
+Sun Jul 18 23:11:28 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ Make breakpoint_re_set_one work with overloaded member functions,
+ `b 123' and `b foo' if foo is a static function.
+ * symtab.c (decode_line_1, decode_line_2): New argument `canonical'
+ to return canonical line specs if requested by the caller.
+ * breakpoint.c, source.c, symtab.c, symtab.h: Change prototypes and
+ callers accordingly.
+ * symtab.c (build_canonical_line_spec): New helper function which
+ constructs the canonical line spec.
+ * breakpoint.c (break_command_1): Use canonical line spec instead
+ of command string as addr_string if necessary.
+ * source.c (line_info): Fix storage leak.
+
+Sun Jul 18 15:22:45 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * infptrace.c: Split out define of PT_KILL; Sequent defines PT_KILL
+ but not the others.
+ * symm-tdep.c: Remove exec_file_command.
+ [_SEQUENT_] (ptx_coff_regno_to_gdb, register_addr): New functions.
+ A few miscellaneous cleanups.
+ * symm-nat.c: Renamed from symm-xdep.c.
+ * All symmetry dependent files: Many changes.
+
+ * mips-tdep.c (mips_skip_prologue): New argument lenient.
+ Use read_memory_nobpt.
+ (is_delayed, mips_in_lenient_prologue): New functions.
+ (init_extra_frame_info): If in the prologue, don't use saved registers.
+ * config/mips/tm-mips.h: Declare mips_skip_prologue.
+
+ * partial-stab.h (N_SO): Add the text offset to valu before, not after,
+ passing it to END_PSYMTAB.
+
+Fri Jul 16 18:48:52 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * symtab.c (find_pc_symtab): Call warning, not printf directly.
+
+ * solib.c (solib_add): Use x{re,m}alloc, not {re,m}alloc.
+
+Fri Jul 16 09:56:42 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c: No longer need to undefine ZMAGIC.
+
+Thu Jul 15 18:03:37 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m88k-pinsn.c: Moved code into opcodes/m88k-dis.c.
+ (print_insn): Now just calls print_insn_m88k.
+
+Thu Jul 15 14:54:05 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * h8300-tdep.c (examine_prologue): Make prototype match definition.
+
+Thu Jul 15 08:34:49 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * NEWS: Mention that remote.c now has a `load' operation.
+
+ * hppa-tdep.c (pc_in_linker_stub): New function.
+ (find_proc_framesize): Return 0 for linker stubs.
+ (rp_saved): Tell the caller where rp is saved.
+ (frame_chain_valid): Return 1 for linker stubs.
+ (frame_saved_pc): Use return value from rp_saved.
+
+ * stack.c (print_frame_info): When checking PC_IN_CALL_DUMMY,
+ pass the sp relative to the frame in question, not the sp in the
+ innermost frame.
+
+Wed Jul 14 17:37:03 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mipsread.c (parse_procedure): Take as argument the symtab to look
+ the name up in. Look it up with mylookup_symbol, not lookup_symbol.
+ (psymtab_to_symtab_1): For stabs, pass the symtab to parse_procedure.
+
+ * mipsread.c (mylookup_symbol): Use strcmp, not STREQ, as we have
+ already checked the first characters.
+
+ Changes from Jeffrey Law:
+ * printcmd.c (makeva_list): Use MAKEVA_EXTRA_INFO to define
+ machine dependent fields in the makeva_list structure.
+ (makeva_size): Allocate extra space to handle gaps made by
+ alignment restrictions.
+ * config/pa/xm-pa.h (MAKEVA_EXTRA_INFO): Define.
+ (MAKEVA_START): Initialize arglist_address field.
+ (MAKEVA_ARG): Always store arguments on natural alignment
+ boundaries. Set arglist_address to the address right after
+ the args.
+ (MAKEVA_END): Simply return the value stored in arglist_address.
+
+Wed Jul 14 13:51:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ch-valprint.c (chill_val_print, case TYPE_CODE_STRING): Print
+ address, not addr.
+
+ * hppah-nat.c (store_inferior_registers): Don't print i in cases
+ where we aren't using it.
+
+ * a29k-tdep.c (get_saved_register): Fix typo.
+
+Wed Jul 14 09:45:52 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Recognize h8300h (variant of h8300).
+
+Wed Jul 14 09:45:52 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * configure.in: Recognize sparc64-*-*.
+
+Tue Jul 13 14:03:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol): Make the caddr_t hack apply to `function
+ returning foo' as well as `pointer to foo'.
+
+ * remote.c [REMOTE_BREAKPOINT]: Use for breakpoint insn if defined.
+ * config/m68k/tm-m68k.h: Define it.
+ * mem-break.c, breakpoint.c: Improve comments.
+
+Tue Jul 13 13:35:31 1993 Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr)
+
+ * config/m68k/tm-dpx2.h: Replace "tm-68k.h" with "m68k/tm-m68k.h".
+ * config/m68k/xm-dpx2.h: Define HAVE_TERMIOS not HAVE_TERMIO.
+
+Tue Jul 13 11:50:38 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * gdbcore.h (read_memory_integer, read_memory_unsigned_integer):
+ Make prototype match definition.
+
+Tue Jul 13 11:15:15 1993 Fred Fish (fnf@cygnus.com)
+
+ * elfread.c: Remove notice about file still being under
+ construction.
+ * Makefile.in (ultra3-xdep.o, umax-xdep.o): Add missing ')'.
+
+Mon Jul 12 17:46:35 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * a29k-tdep.c (read_register_stack): Make val static.
+
+Mon Jul 12 14:10:48 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/h8300/tm-h8300.h (REGISTER_CONVERTIBLE): Change value to 0.
+ (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Move def'n to
+ usual spot.
+
+Mon Jul 12 11:29:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-valprint.c (c_val_print): Fix thinko with unspecified length
+ arrays.
+
+ * hppa-tdep.c (find_proc_framesize): If there is a frame pointer,
+ use it.
+
+Sun Jul 11 19:35:05 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): Use end of block to figure out whether
+ val.end is in the same function, not minimal symbols.
+
+ * source.c (line_info): Add a few more wrap_here's.
+
+ * i386-tdep.c (i386_follow_jump): Do byteswapping where needed and
+ don't make assumptions about sizes of host data types.
+
+ * blockframe.c, symtab.h (find_pc_partial_function): New arg endaddr.
+ * infrun.c, breakpoint.c, printcmd.c: Change callers.
+ * printcmd.c (containing_function_bounds): Remove.
+ * printcmd.c (disassemble_command): Use find_pc_partial_function,
+ not containing_function_bounds.
+ * infcmd.c (step_1): Use find_pc_partial_function rather than
+ trying to roll our own. Move check for a pc between SIGTRAMP_START and
+ SIGTRAMP_END in find_pc_partial_function, not step_1.
+
+ * sparc-tdep.c (sparc_frame_chain, frame_saved_pc):
+ Keep unswapped value in array of char, not REGISTER_TYPE.
+ Use REGISTER_RAW_SIZE not sizeof (REGISTER_TYPE).
+ (sparc_extract_struct_value_address): Use TARGET_PTR_BIT not
+ sizeof (CORE_ADDR).
+
+Thu Jul 1 15:50:05 1993 Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr)
+
+ * configure.in (m68*-bull-sysv*): added support for Bull dpx2.
+ * config/m68k/{t,x,n}m-dpx2.h, dpx2-nat.c: New files.
+ * config/m68k/dpx2.m{h,t}: New files.
+
+Thu Jul 1 15:46:10 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Run through gnu-indent.
+
+Sun Jul 11 12:32:08 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/sparc/tm-sparc.h (PRINT_REGISTER_HOOK): Fix typo, add
+ more parens around macro arg.
+
+Sat Jul 10 09:54:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c: Remove step_resume_{duplicate,shadow}. Replace
+ step_resume_break_address with step_resume_breakpoint (now local
+ to wait_for_inferior).
+ ({insert,remove}_step_breakpoint): Remove.
+ (wait_for_inferior): Set step resume break with
+ set_momentary_breakpoint. Test hitting it with bpstat_stop_status
+ and bpstat_what (stop_step_resume_break removed).
+ * breakpoint.{h,c}, infrun.c: Return value from bpstat_what now struct
+ which includes previous return value as main_action, and a step_resume
+ bit.
+ * breakpoint.c (delete_breakpoint): If breakpoint was inserted, and
+ there is another breakpoint there, insert it.
+ * infrun.c (wait_for_inferior): Rearrange the spaghetti a bit. Use
+ a few more gotos.
+ Various: Clean up and add comments.
+
+ * infrun.c [TDESC]: Remove remaining tdesc code (see ChangeLog
+ for Wed Nov 13 16:45:13 1991).
+
+Fri Jul 9 12:36:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * values.c, value.h (modify_field), callers: Make fieldval a LONGEST.
+
+ * h8300-tdep.c (NEXT_PROLOGUE_INSN): Make pword1 an INSN_WORD *
+ not short *.
+
+ * findvar.c, defs.h
+ ({extract,store}_{signed_integer,unsigned_integer,address}):
+ New routines to replace SWAP_TARGET_AND_HOST.
+ All over: All uses of SWAP_TARGET_AND_HOST on integers replaced.
+
+ * config/sparc/tm-sparc.h: Add comment suggesting that removing
+ ins and locals from the registers array might clean things up.
+
+ * utils.c: Clean up comments about wrap buffer and wrap_here.
+ * printcmd.c (printf_command): Call wrap_here before vprintf.
+
+ * mipsread.c (cross_ref): Set the name to unknown for "struct *" case.
+ Patch from ptf@delcam.co.uk (Paul Flinders).
+
+ * a29k-tdep.c, findvar.c (get_saved_register): Fix byteswapping sins.
+
+Fri Jul 9 09:47:02 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * defs.h, remote-eb.c (TM_FILE_OVERRIDE): Remove it.
+ * mips-tdep.c (init_extra_frame_info): Set proper fci->frame if pc
+ is at the start of the dummy code.
+
+Thu Jul 8 14:48:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-tdep.c (sparc_push_dummy_frame): Skip all the do_save_insn
+ stuff, just write the sp and fp.
+ (sparc_pop_frame): Skip the do_restore_insn; we already restore
+ the sp with the other out registers.
+
+ * hppa-tdep.c (hppa_push_arguments): Allocate enough space for
+ arguments.
+
+ * hppa-tdep.c: Change _initialize_hppab_tdep to _initialize_hppa_tdep.
+
+Thu Jul 8 14:47:00 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * sparc-tdep.c (sparc_frame_chain): Handle sizeof (CORE_ADDR)
+ != sizeof (REGISTER_TYPE).
+ (frame_saved_pc): Ditto.
+
+Thu Jul 8 08:22:05 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * config/h8300/tm-h8300.h: (REGISTER_TYPES): Adjust for h8/300h.
+ (REGISTER_RAW_SIZE): Ditto.
+ (REGISTER_VIRTUAL_TYPE): Use builtin_type_unsigned_long for regs
+ on the h8/300h (ints may still be 16 bits).
+ (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE,
+ EXTRACT_STRUCT_VALUE_ADDRESS): Add FIXME's for h8/300h. Some
+ thought needed here.
+
+ * h8300-tdep.c (print_insn): Call print_insn_h8300h if h8/300h.
+ (examine_prologue): reg_save_depth is 4 if h8/300h.
+
+ * findvar.c (read_register): Provide some support for 64 bit regs.
+ (write_register): Ditto.
+
+Wed Jul 7 14:30:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/nm-riscos.h: machine/machparam.h is always the right
+ place to look for BSD43_NBPG, not machine/vmparam.h
+
+ * infcmd.c (run_stack_dummy): New argument name.
+ Change error message in (another) attempt to make it comprehensible.
+ * valops.c (call_function_by_hand): Pass name to run_stack_dummy.
+ * symtab.h: Declare demangle and asm_demangle since macros use them.
+
+ * eval.c (evaluate_subexp): Add comment about calling a member
+ function of a variable in a register.
+
+ * expression.h: Clean up comment about string in STRUCT_STRUCT etc.
+
+ * config/{rs6000/tm-rs6000.h,sparc/tm-sparc.h,pyr/tm-pyr.h},
+ inferior.h (PC_IN_CALL_DUMMY) [ON_STACK]: Add comments about stack
+ frame tops and bottoms.
+
+ * frame.h, blockframe.c, stack.c, a29k-tdep.c,
+ config/gould/tmp-{pn,np1}.h,
+ config/{sparc/tm-sparc.h,pyr/tm-pyr.h,vax/tm-vax.h}: Remove field
+ next_frame from struct frame_info. It has no purpose beyond
+ ->next->frame and is an artifact from GDB 2.8.
+
+Tue Jul 6 11:51:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Remove gdb before creating a new one.
+ Update init.c atomically.
+
+ * Makefile.in (ALLPARAM): Add config/{alpha/xm-alpha.h,pa/xm-pa.h}.
+ (ALLCONFIG): Add config/alpha/alpha-osf1.mh.
+
+ * infcmd.c (_initialize_infcmd): In docstring for "continue",
+ describe argument as setting ignore count.
+
+Sun Jul 4 15:04:47 1993 Doug Evans (dje@cygnus.com)
+
+ * h8300-tdep.c (examine_prologue): Fix call to
+ read_memory_unsigned_integer.
+
+Fri Jul 2 18:22:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/{x,n}m-irix{3,4}.h: Make some definitions here
+ rather than including xm-bigmips.h.
+
+ * eval.c (evaluate_subexp): Improve error messages for OP_TYPE and
+ default cases.
+
+ * Makefile.in (distclean): Remove y.tab.h.
+
+Fri Jul 2 14:55:48 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * exec.c (exec_file_command): Remove Mar 28 hack as BFD handles
+ file updates properly now.
+ * mipsread.c (mips_coff_new_init): Force reevaluation of sigtramp
+ addresses if switching to a new symbol file.
+ * dbxread.c (process_one_symbol): Avoid dereferencing NULL
+ symbols that might be returned from define_symbol.
+
+Fri Jul 2 13:33:12 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ New target macros for getting at the pc, sp and fp.
+ * infcmd.c (read_pc, write_pc): Modify to use new macros.
+ (read_sp, write_sp, read_fp, write_fp): New functions.
+ * blockframe.c (reinit_frame_cache, get_prev_frame_info):
+ Use new functions.
+ * breakpoint.c (bpstat_alloc): ditto.
+ * infrun.c (wait_for_inferior): ditto.
+ * stack.c (print_frame_info): ditto.
+ * valops (call_function_by_hand): ditto.
+ * corelow.c (core_open): ditto.
+ * h8500-tdep.c: (target_read_sp, target_write_sp, target_read_pc,
+ target_write_pc, target_read_fp, target_write_fp): New functions.
+ * inferior.h (read_sp, write_sp, read_fp, write_fp): Prototypes.
+
+ * config/alpha/xm-alpha.h: Add MAKEVA_END.
+ * config/h8500/tm-h8500.h: Define new macros.
+
+Fri Jul 2 13:51:04 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (mipos-*-riscos*): New host and target; use riscos.
+ * config/mips/nm-riscos.h: If BSD43_NBPG is not defined by
+ vmparam.h, include machparam.h.
+ (KERNEL_U_ADDR): Define to be BSD43_UADDR.
+
+Fri Jul 2 13:39:48 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Give error if unmatched single quote.
+
+ * configure.in, config/m68k/*delta68*, delta68-nat.c: New port.
+
+ * Remove unused STACK_END_ADDR in the following files (in other
+ files it is used for something): tm-mips.h, tm-sun2.h, tm-news.h,
+ tm-a29k, tm-i386v.h, tm-hppa.h, tm-nindy960.h, tm-amix.h,
+ tm-hp300hpux.h, tm-isi.h.
+
+Thu Jul 1 09:51:27 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/mips/nm-riscos.h: Define NBPG and UPAGES.
+ config/mips/xm-riscos.h: Include <sys/types.h>.
+
+ * ser-unix.c (hardwire_noflush_set_tty_state): Use an assignment,
+ not an initializer, to copy the structure.
+
+ * gdbtypes.h (struct type): Add field tag_name.
+ * gdbtypes.c (type_name_no_tag), c-typeprint.c (c_type_print_base):
+ Use it.
+ * {coff,dwarf,mips,stabs}read.c: Set it.
+
+ * xm-sysv4.h: Undefine HAVE_TERMIO.
+
+ * config/mips/nm-riscos.h: Remove unmatched #endif.
+ Define FETCH_INFERIOR_REGISTERS.
+ * config/mips/riscos.mh: Don't include coredep.o; mips-nat.o is enough.
+ Fix misspelling of NAT_FILE.
+ * mips-nat.c (fetch_core_registers): If KERNEL_U_ADDR is not defined,
+ we can still process "modern" core files.
+
+ * ser-unix.c (hardwire_print_tty_state) [HAVE_TERMIOS]: Don't
+ print c_line.
+ (_initialize_ser_hardwire): Just check whether _POSIX_JOB_CONTROL
+ is defined; don't care what it is defined to.
+
+Wed Jun 30 20:06:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/vax/xm-vaxult2.h: Define FD_SET and FD_ZERO.
+
+Tue Jun 29 11:02:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inftarg.c: Remove unused include of terminal.h.
+ * signals.h: Don't undefine signals anymore.
+ * main.c: Use job_control from serial.h.
+ * fork-child.c (fork_inferior): Use gdb_setpgid.
+ * serial.h, ser-unix.c, ser-go32.c: Provide gdb_setpgid.
+ * utils.c (quit): Use current_target->to_terminal_ours to figure
+ out whether we care about lack of job control, rather than __GO32__.
+ * utils.c: Include serial.h not terminal.h
+ (quit): Use job_control not TIOCGPGRP.
+ * terminal.h: Don't undefine TIOCGPGRP.
+ * serial.h, ser-unix.c, ser-go32.c, ser-tcp.c: Add SERIAL_FLUSH_OUTPUT.
+ * utils.c (quit): Use it.
+ * serial.h: Add SERIAL_UN_FDOPEN.
+ * utils.c (quit): Use it.
+ * ser-unix.c: Add process group to ttystate.
+ [HAVE_SGTTY]: Add tchars, ltchars, and lmode to ttystate.
+ * inflow.c: Include serial.h not terminal.h.
+ Use serial.h stuff to replace most of the maze of #ifdef's.
+ * inflow.c, main.c, inferior.h: make gdb_has_a_terminal a function.
+ * serial.h: Document SERIAL_SET_TTY_STATE as being immediate.
+ * ser-unix.c: Use TIOCSETN not TIOCSETP so it is true.
+ * serial.h, ser-unix.c, ser-go32.c, ser-tcp.c:
+ Add SERIAL_PRINT_TTY_STATE, SERIAL_NOFLUSH_SET_TTY_STATE, and
+ SERIAL_SET_PROCESS_GROUP.
+ * inflow.c: Use them.
+ * config/xm-svr4.h, config/rs6000/xm-rs6000.h, config/sparc/sun4os4.h:
+ Define HAVE_TERMIOS.
+ * Various: Remove all use of TIOC*_BROKEN.
+
+Wed Jun 30 12:20:51 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/m68k/tm-sun3.h (BELIEVE_PCC_PROMOTION_TYPE): Define.
+
+Tue Jun 29 13:44:41 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * target.h (target_detach): Turn macro into function.
+ * target.c (target_detach): Define it, do deferred register stores
+ before calling the real target function.
+
+Tue Jun 29 13:15:42 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ * symtab.h (BLOCK_SHOULD_SORT): Do not sort blocks corresponding to
+ a function to avoid printing of function arguments in wrong order
+ due to sorting.
+ * symfile.c (compare_symbols): Remove code for sorting arguments
+ as blocks containing arguments are no longer sorted.
+ * symtab.c (lookup_block_symbol): Update comment accordingly.
+
+Tue Jun 29 11:02:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/pa/tm-hppa.h: Remove unused ARGS_GROW_DOC.
+ (REG_STRUCT_HAS_ADDR): Add comment.
+
+ * infrun.c (wait_for_inferior): Use find_pc_line not find_pc_symtab
+ to check whether there is line number information.
+
+Tue Jun 29 08:29:17 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * remote-udi.c: Fix docstring so that it compiles.
+
+ * remote-mips.c, remote-nindy.c: move bfd.h before symfile.h
+ (for file_ptr).
+
+Tue Jun 29 09:11:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (process_one_symbol): If we find a LOC_BLOCK where we
+ don't expect it, change it to LOC_STATIC so at least we don't coredump.
+
+ * c-typeprint.c (c_type_print_base): Don't error() on invalid type.
+
+ * symtab.h: Add comments about line numbers.
+ * source.c (identify_source_line): Fix off by one bug with line.
+
+Mon Jun 28 19:00:21 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Do not include libhppax. Instead include libhppa.h
+ and hpux-symtab.h. Misc indention fixes.
+ (find_unwind_entry): Add PARAM prototype.
+ (read_hpux_symtab): More fixes for names and sizes of structs,
+ unions, enums, typedefs, and tagdefs.
+ (read_hp_enum_type, read_hp_struct_type): Likewise.
+ (read_hp_set_type, read_hp_subrange_type): Likewise.
+ (hp_type_lookup, process_one_debug_symbol): Likewise.
+ (process_one_debug_symbol): Search forward from the K_FUNCTION for
+ the first K_BEGIN when setting the line number associated with a
+ function. Avoid unnecessary calls to savestring.
+ (hp_alloc_type): Initialize TYPE_CPLUS_SPECIFIC here. Remove
+ most cases where we set it elsewhere.
+ (hppa_sym_fns): Use "hppa" instead of hppax since hpread.c and
+ paread.c use the same BFD backend now. All references changed.
+ (hpux_symfile_init): Allocate space to hold the debugging section
+ contents on the symbol obstack.
+
+Mon Jun 28 10:09:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (makeva*): New interface, for making a va_list.
+ (printf_command): Use it.
+ * config/m88k/xm-delta88.h: Remove VPRINTF define, not needed.
+ * config/pa/xm-pa.h: New file.
+ * config/pa/xm-hppa{b,h}.h: Include it.
+
+ * xcoffread.c: Remove obsolete NO_TYPEDEFS comment.
+
+Sun Jun 27 08:54:55 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valprint.c (val_print_type_code_int): Fix off by one error with
+ eliminating leading zeroes for large little endian integers.
+
+Sun Jun 27 08:58:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/riscos.mh (CC): Use -systype sysv.
+
+ * ser-unix.c: Move #include of <sys/time.h> to HAVE_SGTTY section.
+
+ * Makefile.in (ALLPARAM): Add config/mips/{x,n}-{news-mips,riscos}.h.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-m68k.h: Remove obsolete comment about duplicating
+ CALL_DUMMY between different 68k machines.
+
+Fri Jun 25 17:02:45 1993 Stu Grossman (grossman at cygnus.com)
+
+ * gdbserver/Makefile.in: Add dependancies on server.h.
+ * gdbserver/remote-gutils.c: Remove lots of unused functions and
+ variables.
+ * gdbserver/remote-inflow.c: Remove lots of unused variables and
+ #includes. Also, use PTRACE_* symbols instead of constants.
+ (mywait): Surround calls to wait() with enable/disable_async_io()
+ so that we can be interrupted from GDB while waiting for the
+ child. Also, handle child exit more gracefully.
+ * gdbserver/remote-server.c: Remove lots of unused variables.
+ Move all extern defs into server.h. Redo main loop so that
+ failure from getpkt() causes communications to be re-established.
+ Fix 'k' command so that it restarts the child.
+ * gdbserver/remote-utils.c: Remove lots of unloved vars and
+ subrs. Move many extern decls into server.h. (remote_open): For
+ tcp, seperate usage of proto fd from connected fd. Close proto
+ fd after getting connection. (putpkt/getpkt): Pay attention to
+ errors when reading/writing. Report these to the caller. New
+ routines input_interrupt/enable_async_io/disable_async_io to make
+ it possible to get an I/O interrupt when data arrives from the
+ comm link.
+ * serial.h: New file to contain common defs for all remote files.
+
+Fri Jun 25 17:02:45 1993 Stu Grossman (grossman at cygnus.com)
+
+ * remote.c: Add arg names to prototypes, in a modest effort at
+ clarification. Also add prototypes for some new functions.
+ * (remote_wait): Better error reporting for 'T' responses.
+ * ser-go32.c (strncasecmp): Make str1 & str2 be const.
+ * (dos_async_init): Make usage message reflect requested port #.
+ * ser-tcp.c (tcp_open): Terminate hostname properly to prevent
+ random hostname lookup failures. Add nicer message for unknown
+ host error. (wait_for): Wake up in case of exceptions. Also,
+ restart select() if we got EINTR.
+ * ser-unix.c (wait_for): Restart select() if we got EINTR.
+ * serial.c: (serial_close): Clean up code.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-m68k.h: Remove obsolete comment about duplicating
+ CALL_DUMMY between different 68k machines.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (*.tab.c): Use ./c-exp.tab.c not just c-exp.tab.c.
+ Make comment explaining this comprehensible.
+ (TAGFILES): Include ALLDEPFILES.
+ (ALLDEPFILES): udi2soc.c and udr.c are in 29k-share/udi, not
+ 29k-share/udi/udi.
+ (update-alldeps): Remove; obsolete.
+
+ * remote.c: Move comments regarding packets to top of file with the
+ rest of the protocol comments.
+ Fix incorrect description of 'T' response.
+
+ * README (Reporting Bugs): Refer people to the GDB manual.
+
+ * c-valprint.c (c_val_print): Handle TYPE_CODE_BOOLEAN.
+ * stabsread.c: Type -16 is 4 bytes.
+
+ * remote-udi.c: Improve docstring.
+
+Fri Jun 25 11:16:31 1993 Fred Fish (fnf@cygnus.com)
+
+ * elfread.c (elf_symfile_read): Call bfd_elf_find_section, not
+ bfd_elf32_find_section, to track bfd changes.
+
+Fri Jun 25 11:22:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/riscos.mh (REGEX{,1}, MUNCH_DEFINE, MH_CFLAGS): Define.
+ * config/mips/xm-riscos.h: Define USG.
+
+Thu Jun 24 14:52:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (filename_completer): Don't complete to files ending in ~.
+
+ * NEWS: Mention filename completion and "info line" enhancements.
+
+ * main.c (symbol_completion_function): On "info t foo", return NULL,
+ don't error().
+
+ * main.c (symbol_completion_function): Don't use readline word
+ breaking. Use new calling convention for c->completer and
+ complete_on_cmdlist.
+ * command.h (struct command): Change arguments; now the text passed
+ to completer does not have any word breaking done. New arg word.
+ * symtab.{c,h} (make_symbol_completion_list): Do word breaking. Take
+ word argument.
+ * {main.c,gdbcmd.h} ({filename,noop}_completer): Take word argument.
+ * command.{c,h} (complete_on_cmdlist): Take word argument.
+
+ * command.c (lookup_cmd_1): Doc fix.
+
+Thu Jun 24 13:26:04 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in (OP_INCLUDE): define.
+ (OPCODE_CFLAGS): use OP_INCLUDE.
+
+ * config/i386/ncr3000.mh, config/i386/i386v4.mh,
+ config/i386/i386sol2.mh, config/m68k/hp300hpux.mh,
+ config/m68k/amix.mh, config/mips/irix[34].mh,
+ config/m88k/delta88.mh, config/sparc/sun4sol2.mh (ALLOCA,
+ ALLOCA1): macros removed.
+
+ * config/mips/decstation.mh, config/rs6000/rs6000.mh
+ (MMALLOC_LIB): renamed to MMALLOC.
+
+Wed Jun 23 00:25:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * partial-stab.h: Consolidate case statements for N_LSYM and N_FUN.
+ * dbxread.c: Change comment regarding acc.
+
+Wed Jun 23 16:33:36 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Document a few functions, misc cleanups. Update
+ copyright to reflect the first "release" of this file.
+ (struct hpux_symfile_info): Delete unneeded fields. Keep pointers
+ to the contents of the debug sections rather than offsets within
+ the file itself. Corresponding changes to the accessor macros.
+ (sl_symbol_size, slt_symbuf): Delete unneeded global variables.
+ (slt_symbuf_start, slt_symbuf_end, lntt_symbuf): Likewise.
+ (lntt_symbuf_start, lntt_symbuf_end, gntt_symbuf): Likewise.
+ (gntt_symbuf_start, gntt_symbuf_end): Likewise.
+ (fill_slt_symbuf, fill_lntt_symbuf): Delete unneeded functions.
+ (fill_gntt_symbuf): Likewise.
+ (get_lntt, get_gntt, get_slt): Simplify.
+ (hpux_symfile_init): Read and store the contents of the debugging
+ sections. Do error checking on memory allocation and BFD calls.
+ (read_hpux_symtab): Delete KERNELDEBUG crud. Ignore debug symbols
+ which are not needed for building partial symbol tables. Handle
+ K_CONST, K_TYPEDEF, and K_TAGDEF just like K_SVAR and K_DVAR.
+ (read_ofile_symtab): Delete useless processing_gcc_compilation stuff.
+ (read_hp_struct_type): Initialize TYPE_CPLUS_SPECIFIC.
+ (read_hp_set_type, read_hp_array_type): Likewise.
+ (read_hp_subrange_type, hp_type_lookup): Likewise.
+
+Wed Jun 23 15:04:54 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ Makefile overhaul dropping autodepend features.
+ * Makefile.in: many comment changes. forced consistent use of $()
+ for makefile variables references. dropped leading ./ in file
+ references. Drop $(srcdir)/ prefix on all dependencies.
+ Inserted contents of alldeps.mak and depend.
+ (INCLUDE_CFLAGS): defined as new macro for getting libiberty's
+ include directory into the compilation line.
+ (GDB_CFLAGS): new macro to take up the semantic previously held
+ by INCLUDE_CFLAGS.
+ (LIBIBERTY): dropped ancient subdir macro. I last removed this
+ macro in feb of '92. How does it keep coming back?
+ (MMALLOC_LIB): renamed to MMALLOC.
+ (BFD_SRC_DIR): renamed to BFD_SRC.
+ (BFD_OBJ_DIR): renamed to BFD_DIR.
+ (BFD_LIB): renamed to BFD.
+ (BFD_INCLUDES): renamed to BFD_CFLAGS.
+ (READLINE_DIR): now represents object directory.
+ (RL_LIB): renamed to READLINE.
+ (READLINE_SRC, READLINE_CFLAGS, OPCODES, OPCODES_CFLAGS): new
+ macros.
+ (INTERNAL_CFLAGS): added GDB_CFLAGS, OPCODES_CFLAGS,
+ READLINE_CFLAGS, BFD_CFLAGS. Dropped USER_CFLAGS.
+ (LDFLAGS): removed default assignment.
+ (TEXIDIR, INCLUDE_DEP, MMALLOC_DIR, MMALLOC_DEP, BFD_DEP,
+ READLINE_DEP, LIBIBERTY_DIR, TESTS, depend, STAGESTUFF): unused, so removed.
+ (ALLOCA1, ALLOCA): removed all references. alloca is now in
+ libiberty.
+ (VERSION): unilaterally and arbitrarily bumped to 4.9.3.
+ (SFILES, NONSRC, HFILES, ALLDEPFILES, ALLPARAM, ALLCONFIG):
+ removed all $(srcdir) prefixes.
+ (getopt_h, ieee-float_h, bfd_h, wait_h, dis-asm_h): new macros
+ for potential dependencies. commented out by default.
+ (readline_headers, udiheaders): convenient abbreviations.
+ (gdbcore_h, frame_h, symtab_h, gdbtypes_h, expression_h,
+ value_h, breakpoint_h, command_h, gdbcmd_h, defs_h, inferior_h):
+ new macros used for header file dependencies.
+ (install-info, clean-info): collapse into the info rule.
+ (install): now depends on all.
+ (install-only): new target for installing without depending on
+ all.
+ (uninstall): new target.
+ (config-check, config-check-hosts, config-check-targets): added
+ fixme comments.
+ (ch-exp.tab.c, m2-exp.tab.c): added artificial dependencies in
+ order to force parallel makes into keeping these rules separate.
+ * configure.in: omit cat'ing depend file onto generated Makefile.
+ * alldeps.mak, depend: removed.
+
+ * inferior.h: remove redundant include of symtab.h which is
+ included in value.h via breakpoint.h.
+
+ * alloca.c: removed. alloca is now in libiberty.
+
+ * config/m88k/delta88.mh, config/ns32k/merlin.mh (M_UNINSTALL):
+ new macro to undo what M_INSTALL does.
+
+Wed Jun 23 00:25:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/ns32k/{merlin.mh,xm-merlin.h}: Be consistent about name
+ of gdb-sh.
+
+ * dbxread.c (copy_pending): Change name and function of begi argument
+ to endi, since that is what the caller needs.
+
+ * Makefile.in (TAGFILES): Don't include YYFILES.
+
+ * Makefile.in (HFILES): Include monitor.h.
+
+ * Makefile.in: Include text that used to be in alldeps.mak.
+ Remove config/mips/{bigmips.mh,xm-bigmips} from it.
+ * Makefile.in, configure.in: Remove all traces of alldeps.mak.
+
+ * main.c (main): Print help message on stdout not stderr
+ per standards.texi.
+ New option --version per standards.texi.
+ In help message, show long options with "--" not "-".
+ Don't try to print help message or version until after we have
+ called initialize_all_files.
+
+Tue Jun 22 11:03:13 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Delete useless #if 1 statements.
+ (hp_type_translate): Use T_LONG, T_UNS_LONG, and T_DOUBLE instead
+ of magic integers. Fix handling for T_UNS_INT. Abort if the type
+ passed in is not an "immediate" type.
+ (read_hp_enum_type): Properly compute the size of the type.
+ (read_hp_array_type): Likewise.
+ (hp_type_lookup): Prefix the names of structs, unions and enums
+ with "struct", "union", and "enum" as appropriate.
+
+Tue Jun 22 03:15:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * solib.c (solib_add_common_symbols): Don't call lookup_minimal_symbol.
+ (solib_add): Call special_symbol_handling once, not once per library.
+
+ * procfs.c (procfs_resume): Don't pass a SIGTSTP whose action
+ is SIG_DFL.
+
+ * procfs.c (procfs_resume): Skip the unnecessary PRSVADDR on all
+ systems, not just Solaris.
+
+ * stabsread.c: Include <ctype.h>.
+
+Mon Jun 21 16:09:46 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * fork-child.c (fork_inferior): Quote exec_file so it can contain
+ funky characters.
+
+Mon Jun 21 16:56:47 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (INCLUDE_CFLAGS): Add BFD_INCLUDES for now, since
+ bfd.h is included by target.h, which most of gdb includes.
+ * depend: Hand remove BFD_INCLUDES from ${CC} lines, now that
+ it's in INCLUDE_CFLAGS.
+
+Mon Jun 21 16:09:46 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/i386/*aix*, i386aix-nat.c: New files.
+ * configure.in: Use them.
+ * alldeps.mak: List them.
+ * coffread.c (decode_base_type): Deal with anonymous enum type.
+ * i387-tdep.c (print_387_status_word): Add comment re "top".
+ * i386-tdep.c [I386_AIX_TARGET] (i386_extract_return_value): New func.
+ * dbxread.c: Use SEEK_SET and SEEK_CUR, not L_*. Define them if and
+ only if not defined by a header file.
+ * mipsread.c: Don't define L_SET or L_INCR.
+
+Mon Jun 21 15:10:07 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (BFD_INCLUDES): Bfd.h is now back in bfd build dir.
+ * depend: Hand updated to match.
+
+Mon Jun 21 10:13:42 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Include "demangle.h".
+ (process_one_debug_symbol): Set the SYMBOL_LANGUAGE and
+ SYMBOL_INIT_DEMANGLED_NAME for the current symbol. Adjust
+ SYMBOL_VALUE for local variables in the stack by the size of the
+ current function's stack (found in unwind descriptor). Keep
+ better track of the current unwind descriptor.
+
+Sun Jun 20 13:11:11 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabsread.c (read_struct_fields): Don't call read_cpp_abbrev on $_.
+ (read_cpp_abbrev): Don't complain specially for $_. Also return 0 if
+ we don't recognize the abbrev.
+
+Sun Jun 20 00:24:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * solib.c (solib_add_common_symbols): Add comment about performance.
+
+Fri Jun 18 12:37:36 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/{{x,n}m-riscos.h,riscos.mh}: New files.
+ * configure.in (mips-*-sysv*): Use riscos for host, bigmips for target.
+
+ * config/mips/{{x,n}m-news-mips.h,news-mips.mh}: New files.
+ * config/mips/{bigmips.mh,xm-bigmips.h}: Remove.
+ * configure.in (mips-sony-*): Use news-mips for host.
+
+ * buildsym.h: Doc fix for processing_acc_compilation.
+
+Thu Jun 17 19:57:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_formatted): Don't use tab in wrap_here arg.
+
+Thu Jun 17 17:29:30 1993 Jim Kingdon (kingdon@lisa.cygnus.com)
+
+ * Makefile.in (INTERNAL_CFLAGS): Include ../include as well as
+ ${srcdir}/../include.
+
+ * config/m88k/xm-delta88.h: Comment out unused defines which conflict
+ with system headers.
+ * printcmd.c (printf_command): Cast second arg to vprintf to PTR.
+ Use VPRINTF macro if defined.
+ * config/m88k/xm-delta88.h: Define VPRINTF. Include <sys/siginfo.h>.
+ Define TIOC{GETC,GLTC}_BROKEN.
+ * m88k-nat.c: Uncomment include of <sys/ptrace.h>.
+ * main.c: Rename initialize_{main,cmd_lists,history} to init_* to
+ make things easier on munch (apparently this matters on
+ the delta88 with svr3).
+
+Thu Jun 17 16:53:56 1993 david d `zoo' zuhn (zoo@cygnus.com)
+
+ * Makefile.in: canonicalize install.sh; for use within
+ this directory (and subdirs)
+
+Tue Jun 15 17:01:23 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: remove parentdir support; use INSTALL_XFORM
+
+Thu Jun 17 15:08:35 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * configure.in (alpha-*-osf*), config/alpha/alpha-osf.mh: New
+ host.
+ * sh-tdep.c (frame_find_saved_regs): Use NUM_REGS rather than hard
+ wired (and wrong) constant.
+ * values.c (unpack_long): Add case to unpack when target object is
+ sizeof(int).
+ * config/sh/tm-sh.h (REGISTER_NAMES): Know about the news ones the
+ simulator defines.
+
+Wed Jun 16 16:08:18 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * NEWS: tracking user visible changes starting with
+ vxworks-timeout.
+
+ * remote-vx.c (_initialize_vx): rename user settable option from
+ rpcTimeout to vxworks-timeout.
+
+Wed Jun 16 14:34:10 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hp_type_translate): Fix promotion bugs from
+ char to short and short to int.
+
+Wed Jun 16 12:21:49 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (depend): More makefile diddling.
+ * alldeps.mak, depend: Update to latest automatically built
+ versions.
+
+ * Makefile.in (depend): Bfd.h keeps moving, keep up with it.
+ * alldeps.mak, depend: Update to latest automatically built
+ versions.
+
+Tue Jun 15 12:26:05 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remote-vx.c: include gdbcmd.h for setlist.
+ (_initialize_vx): make rpcTimeout user settable.
+
+Mon Jun 14 09:23:51 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * main.c, gdbcmd.h: Add function filename_completer.
+ * main.c, symfile.c, source.c, exec.c, core.c: Use it for
+ "directory", "source", "cd", "symbol-file" "add-symbol-file",
+ "load", "file", "exec-file", "core-file" commands.
+ (But '/' is a word break, limiting usefulness; see comments).
+
+ * source.c (mod_path): Warning not error if can't find directory.
+
+ * isi-xdep.c: New file.
+ * config/m68k/isi.mh (XDEPFILES): Add isi-xdep.o
+
+Sun Jun 13 09:17:48 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/m68k/xm-news.h: Include <sys/param.h>.
+
+ * m88k-tdep.c (IEEE_isNAN): Remove.
+ config/m88k/tm-m88k.h (INVALID_FLOAT): Return 0. This was the same
+ broken isNAN as on the mips.
+
+ * valprint.c (_initialize_valprint): Use c->function.sfunc not just
+ c->function.
+
+ * dbxread.c (process_one_symbol): If SUN_FIXED_LBRAC_BUG is not
+ defined, don't worry about Sun's silly LBRAC bug.
+ * config/m68k/tm-sun3.h: Define SUN_FIXED_LBRAC_BUG to 0.
+
+ * dbxread.c (process_one_symbol): If there's a symbol before an
+ N_SO, don't error().
+ (case N_BCOMM): complain () not error ().
+
+ * defs.h, main.c (catch_errors): Add return_mask arg.
+ stack.c (print_frame_info): Pass RETURN_MASK_ERROR.
+ other callers: Pass RETURN_MASK_ALL.
+ (return_to_top_level), callers: Add return_reason arg.
+ * utils.c (quit):
+ Use return_to_top_level (RETURN_QUIT) instead of error ().
+ * main.c (main), tm-nindy960.h (ADDITIONAL_OPTION_HANDLER):
+ Use SET_TOP_LEVEL not setjmp (to_top_level).
+ * remote-nindy.c: Use catch_errors not setjmp (to_top_level).
+
+Sat Jun 12 14:40:54 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * solib.c (solib_create_inferior_hook) [SVR4_SHARED_LIBS]:
+ Don't try to get the debug base yet.
+
+ * dbxread.c (process_one_symbol): Set n_opt_found based on whether
+ a non-gcc N_OPT symbol is found. Make SUN_FIXED_LBRAC_BUG a macro
+ which returns 0 or 1 to say whether to do it.
+ * config/sparc/sun4{sol2,os4}.h
+ (SUN_FIXED_LBRAC_BUG,VARIABLES_INSIDE_BLOCK): Use n_opt_found so
+ the right thing happens for both acc and SunOS4 /bin/cc.
+
+ * valprint.c (print_hex_chars): Use local_hex_format_{pre,suf}fix.
+ * printcmd.c (print_scalar_formatted): Use val_print_type_code_int.
+
+ * mips-tdep.c: Remove isa_NAN; it assumed sizeof(host int) == 4 and
+ probably contained byte-order sins too.
+ config/mips/tm-mips.h (INVALID_FLOAT): Define to 0 like most machines.
+ The IEEE_FLOAT code in print_floating takes care of it.
+
+Sat Jun 12 14:47:04 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.9.2.
+ * c-valprint.c (c_val_print): For array of chars printed with
+ string syntax, don't print the address of the array. From
+ bothner@cygnus.com.
+ * c-exp.y (yylex): Recognize '.' as indicating a floating point
+ number regardless of the radix. From wilson@cygnus.com.
+ * valprint.c (set_input_radix_1, set_output_radix_1): New
+ prototypes and functions that do the actual radix setting work.
+ * valprint.c (set_radix, set_output_radix, set_input_radix):
+ Rewrite to use set_input_radix_1 and set_output_radix_1.
+ * valprint.c (initialize_valprint): Enable commands to
+ independently set and show input and output radices.
+ * valprint.c (show_radix): New prototype and function that
+ handles separate input and output radices.
+
+Fri Jun 11 18:39:38 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ Patches from Jeff Law, law@cs.utah.edu:
+ * hppa-pinsn.c: Now uses disassembler from opcode library,
+ this contains only the stub function print_insn.
+
+Fri Jun 11 15:19:59 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * main.c (main): back to two periods for elipse.
+ (print_gdb_version): revised format for configuration info.
+
+Fri Jun 11 10:24:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (INT_MAX): Cast unsigned shift result to int.
+
+Fri Jun 11 10:17:41 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * dbxread.c (process_one_symbol): Rather than having
+ BLOCK_ADDRESS_FUNCTION_RELATIVE a macro, make it a variable which
+ is true if we are doing stabs-in-elf, false otherwise.
+ config/sparc/tm-sun4sol2.h: Don't define it.
+
+Fri Jun 11 13:33:40 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-mips.c (mips_send_packet): Don't print garbage character
+ in debugging info.
+ (mips_request): Don't check that remote pid is 0, because
+ sometimes it isn't.
+ (mips_fetch_registers): Pass a pointer to SWAP_TARGET_AND_HOST,
+ not an integer.
+
+Fri Jun 11 10:17:41 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stack.c (print_frame_info): Use catch_errors around print_frame_args.
+
+ * Makefile.in (install): Don't depend on gdb.
+
+ * Rename remote-es1800.c to remote-es.c
+ and remote-st2000.c to remote-st.c for 14-char filenames.
+ config/m68k/{es1800,st2000}: Use the new names.
+
+ * mips-tdep.c (isa_NAN): Don't return true on -0.
+
+Fri Jun 11 10:24:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (INT_MAX): Cast unsigned shift result to int.
+
+Thu Jun 10 13:26:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * elfread.c (elf_symtab_read): Add bfd section address to bfd
+ symbols, now that they are section relative.
+ * solib.c (bfd_lookup_symbol): Ditto.
+
+Thu Jun 10 11:27:34 1993 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hp_function_type): Adjust SYMBOL_VALUE for
+ arguments in the stack by the size of the current function's stack
+ (found in the unwind descriptor).
+ (process_one_debug_symbol): Likewise. Keep track of the current
+ function's unwind descriptor.
+
+Thu Jun 10 10:56:56 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (depend): Add bfd -I's for paread.c and xcoffexec.c
+ depend: Updated accordingly.
+
+Wed Jun 9 16:08:44 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (*.tab.c): Use mv for atomic update.
+
+ * Makefile.in ({dist,real}clean): Also remove nm.h.
+ (realclean): Also remove ${TESTS}, y.output, yacc.{acts,tmp}.
+ (distclean): Don't rebuild *.tab.c or TAGS.
+
+Wed Jun 9 12:56:58 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in (version.c): add host and target names to version.c.
+ * main.c (main): print three periods for the elipse.
+ (print_gdb_version): also print configuration.
+
+ * udi/udiids.h, udi/udip2soc.c, udi/udiphcfg.h, udi/udiphunix.h,
+ udi/udiproc.h, udi/udipt29k.h, udi/udiptcfg.h, udi/udisoc.h,
+ udi/udr.c: Change AMD copyrights to FSF copyleft '93.
+
+ * remote-eb.c (get_hex_regs, eb_fetch_registers), remote-adapt.c
+ (get_hex_regs, adapt_fetch_registers): cast args to
+ supply_register to avoid gcc warning.
+
+ * config/a29k/a29k.mt (TDEPFILES): drop minimon support. It
+ doesn't compile on solaris and is now obsolete.
+
+ * config/sparc/sun4os4.mh (XM_CLIBS): remove -lresolv. This
+ breaks stock sunos installations.
+
+Wed Jun 9 06:14:33 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * m68k-stub.c: Add comment about frame cache.
+
+ * target.h (target_store_registers): Doc fix re error handling.
+
+ * findvar.c (write_register): Call SWAP_TARGET_AND_HOST regardless
+ of register_valid[regno].
+
+Tue Jun 8 14:42:10 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * symtab.h, dwarfread.c: Doc fix re dependencies.
+
+Tue Jun 8 17:54:09 1993 Rob Savoye (rob@rtl.cygnus.com)
+
+ * serial.c (serial_close): If scb is NULL, don't try to close
+ it.
+ * configure.in: Add support for rom68k and bug boot monitors.
+
+Tue Jun 8 17:39:12 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * coffread.c (init_stringtab): Fix bug where sizeof(long) != 4.
+ * gdbcore.h, core.c (read_memory_unsigned_integer): New function.
+ * findvar.c (read_register, write_register): Fix thinko where
+ sizeof(host long) != sizeof(target int).
+ * h8300-tdep.c: Use new read_memory_unsigned_integer call.
+ * sh-tdep.c (_initialize_sh_tdep): Add memory_size command.
+
+Tue Jun 8 14:42:10 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * Move config/m68k/tm-m68k.h (FRAME_FIND_SAVED_REGS) to
+ m68k-tdep.c (m68k_find_saved_regs). Don't duplicate code between
+ 68881 and non-68881 cases. Check for a pair of movel instructions.
+
+Tue Jun 8 14:52:55 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ First cut at sparc-vxworks targetting.
+ * config/sparc/tm-vxsparc.h, config/sparc/vxsparc.mt: new files.
+ * configure.in: sparc-vxworks gdb_target now vxsparc.
+
+ * remote-eb.c, remote.c: symfile.h requires bfd.h so include it.
+
+Tue Jun 8 14:42:10 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * config/m68k/xm-news.h: add "extern int errno".
+
+Tue Jun 8 13:45:07 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * remove-vx.c (vx_read_register, vx_write_register): collapse
+ ifdef I80960 else (assumes) m68k into parameterizable macros
+ VX_NUM_REGS and VX_SIZE_FPREGS.
+ * config/m68k/tm-vx68.h, config/i960/tm-vx960.h (VX_NUM_REGS,
+ VX_SIZE_FPREGS): new definitions.
+
+Tue Jun 8 11:08:29 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * symfile.{c,h} (generic_load): New function.
+ remote{,-nindy,-eb,-mips}.c: Use it.
+
+Mon Jun 7 20:07:30 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (depend): More sed gubbish to deal with
+ ../bfd/bfd.h being generated during the build.
+ * depend: Re-done with corrected makefile.
+
+Mon Jun 7 16:32:05 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (BFD_SRC_DIR): Renamed def and usages from BFD_DIR.
+ * Makefile.in (BFD_OBJ_DIR): New definition for the bfd build
+ directory to find automatically generated header files and library.
+ * Makefile.in (BFD_LIB): Use BFD_OBJ_DIR.
+ * Makefile.in (LINTFLAGS): Include BFD_OBJ_DIR.
+ * Makefile.in (saber_gdb): Include BFD_OBJ_DIR.
+ * Makefile.in (depend): Include BFD_OBJ_DIR in gcc args.
+ * Makefile.in (paread.o, xcoffexec.o): Remove, now in depend.
+ * depend, alldeps.mak: Rebuild after Makefile.in changes.
+
+Fri Jun 4 10:18:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: change lynx support to CPU-*-lynxos*
+
+ * Makefile.in (subdir_do): change test from existence of directory
+ to existence of Makefile (the directory may exist but not be configured)
+
+Thu Jun 3 01:18:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * config/sparc/xm-sun4sol2.h: define MEM_FNS_DECLARED
+
+Fri Jun 4 10:43:33 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * configure.in (mips-idt-ecoffl*): New target; use idtl.
+ (mips-idt-ecoff*): Added trailing '*'.
+ * config/mips/idtl.mt: New file; like idt.mt, but little endian.
+
+Thu Jun 3 17:36:56 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: Clean up lots of compilation nits.
+
+Thu Jun 3 14:44:57 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Patches from Jeffrey Law <law@cs.utah.edu>.
+ * hppab-nat.c: Eliminate unnecessary ifdefs for
+ FETCH_INFERIOR_REGISTERS, CANNOT_FETCH_REGISTER, and
+ CANNOT_STORE_REGISTER.
+ (fetch_register): Delete code to handle CANNOT_FETCH_REGISTER.
+ * hppa-pinsn.c: Support 'I', 'J', and 'K' in output
+ templates for 1.1 FP computational instructions.
+
+Thu Jun 3 03:34:49 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in: Remove ser-tcp.[co]. (Use XDEPFILES instead.)
+ * alldeps.mak, depend: Rebuild to account for ser-tcp.
+ * config/sparc/sun4os4.mh: Add ser-tcp to XDEPFILES.
+ * gdbserver/Makefile.in (gdbserver): Use -lbsd.
+ * gdbserver/remote-inflow{-sparc}.c (create_inferior): Don't use a
+ shell when running the child, as args have been expanded by the
+ time we get here. Simplify calling convention.
+ * gdbserver/remote-server.c (main): Use new calling convention
+ for create_inferior, remove defunct code for coalescing argv.
+ Remove extra calls to mywait(), as we no longer have to wade
+ through a shell.
+
+ * target.c (target_read_memory_partial): Don't deref errnoptr
+ when checking for null pointer.
+
+Wed Jun 2 19:58:46 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote-es1800.c: Fix typo.
+
+Tue Jun 1 21:22:39 1993 Fred Fish (fnf@cygnus.com)
+
+ * target.c (target_read_memory_partial): Like target_read_memory,
+ but does partial reads, such as reads that bump into the end of
+ the address space.
+ * target.h (target_read_memory_partial): Add prototype.
+ * valprint.c (PRINT_MAX_DEFAULT): New define, initial value 200.
+ * valprint.c (val_print_string): Complete rewrite to fix bug with
+ bumping into end of memory, avoiding unnecessarily long reads, and
+ fixing bug when print_max is set to 0 (unlimited print length).
+ * valprint.c (_initialize_valprint): Use PRINT_MAX_DEFAULT to
+ initialize print_max.
+
+Tue Jun 1 18:11:35 1993 Rob Savoye (rob at darkstar.cygnus.com)
+
+ * configure.in: Add support for rom68k and bug boot monitors.
+
+Mon May 31 10:37:04 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * printcmd.c (print_scalar_formatted): Print integers bigger than
+ LONGEST in hex no matter how big, and no matter what the format
+ and size.
+
+ * stabsread.c (read_type): Skip type attributes if present.
+
+ * stabsread.c (read_huge_number): Don't accept '0' + radix as part
+ of number, just through '0' + radix - 1.
+
+Sun May 30 15:35:21 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SER_HARDWIRE): Temporarily comment out ser-tcp.o.
+
+ * {dbxread.c, dwarfread.c} (read_ofile_symtab): Rewrite to take
+ single parameter, the pointer to the partial symtab, rather than
+ a bunch of args that are derived from the partial symtab. Change
+ prototypes and callers to match.
+
+ * dbxread.c (read_ofile_symtab): Remove "#if 1" around code to
+ set demangling style automatically.
+ * defs.h (CPLUS_MARKER): Clarify comment that this is only for
+ GNU C++, not C++ in general.
+ * symtab.h (general_symbol_info): Simplify by eliminating one
+ structure level for the language dependent info.
+
+Sat May 29 15:59:29 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-typeprint.c (c_type_print_base): Avoid dereferencing NULL
+ names for TYPE_CODE_STRUCT and TYPE_CODE_UNION types.
+ TYPE_CODE_ENUM was already testing for this.
+
+Fri May 28 17:18:05 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in: Add new file ser-tcp.c.
+ * defs.h (memcmp): Add decl for memcmp to #ifndef MEM_FNS_DECLARED.
+ * findvar.c (write_register): See if we are writing back the same
+ value that's already in the register. If so, don't bother.
+ * remote.c (putpkt, getpkt): Improve handling of communication
+ problems.
+ * ser-go32.c: Prototype it to death. Update serial_ops and add
+ dummy routines where appropriate.
+ * ser-tcp.c: New module to implement serial I/O via TCP
+ connections.
+ * ser-unix.c: Clean up getting/setting of tty state. Get rid of
+ SERIAL_RESTORE, add SERIAL_{GET|SET}_TTY_STATE interfaces.
+ * serial.c: Add start of support for connect command.
+ (serial_open): Distinguish between tcp and local devices.
+ * serial.h (struct serial_ops): Get rid of restore, add
+ get_tty_state and set_tty_state. Define protoypes and macros for
+ this mess.
+ * gdbserver/remote-utils.c: Add tcp support. (readchar): Do
+ some real buffering. Handle error conditions gracefully.
+ * gdbserver/remote-inflow-sparc.c: Update to remote-inflow.c
+ (Lynx), remove lots of cruft.
+
+Fri May 28 17:24:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * printcmd.c (print_address_symbolic): turn this into an assigment
+ instead of an initialization (many compilers don't accept
+ structure initialization).
+
+Thu May 27 16:56:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): If several program csects in one
+ source file, give them all the name of the source file, rather than
+ the 2nd and subsequent ones having NULL names.
+
+Thu May 27 06:16:56 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * printcmd.c (print_address_symbolic): Append source filename and
+ linenumber of the symbol if print symbol-filename is on.
+ (initialize_printcmd): `set print symbol-filename'.
+
+Wed May 26 13:46:16 1993 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Add config for Lynx target. Configure gdbserver
+ only for Lynx. Re-do selective configuration of sparclite.
+
+ * gdbserver/{remote-gutils.c remote-server.c Makefile.in
+ configure.in remote-inflow.c remote-utils.c}: New files to
+ support GDB remote server. Currently only works for Lynx.
+
+Wed May 26 10:28:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (define_symbol, case 't'): Only set the name if it
+ is not a pointer type.
+
+ * stabsread.c (define_symbol): Clean up logic; move the read_type
+ calls to inside the switch statement (this improves the error
+ handling).
+
+ * mipsread.c (parse_symbol, parse_partial_symbols): Deal with Fortran
+ common blocks.
+
+Tue May 25 20:44:24 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_formatted, case 'i'): Pass a tab to wrap_here.
+
+ * source.c (line_info): Change "pc" to "address" in messages and
+ use print_address for addresses.
+
+ * source.c (line_info): If we don't find a symtab, print more useful
+ output, including the symbolic address.
+
+ * source.c (line_info): If --fullname, display the source.
+ (identify_source_line), callers: Take pc as argument, rather than
+ assuming innermost frame (emacs doesn't use this, so no one ever
+ noticed).
+ * symtab.h: Declare frame_file_full_name.
+ * main.c: Don't.
+
+Tue May 25 15:30:43 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * breakpoint.c (catch_command_1): Fix typo in error msg.
+
+Tue May 25 16:05:55 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * elfread.c (elf_symfile_read): Update ELF structure and routine
+ names to specify 32-bit versions.
+ (elf_symtab_read): Retrieve size field directly from symbol,
+ instead of using old kludge.
+
+ * mips-pinsn.c (print_insn): Cast address to bfd_vma before
+ calling opcodes library.
+ * z8k-tdep.c (print_insn): Likewise.
+
+Tue May 25 13:06:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c: Remove all uses of error(). Make error_type and
+ read_type_number static.
+ (define_symbol): Don't try to deal with a missing symbol
+ descriptor which isn't followed by digit, '(', or '-'.
+ * stabsread.h: Don't declare read_type_number here.
+ * gdbtypes.h: Don't declare error_type here.
+ * xcoffread.c: Remove NO_TYPEDEFS code.
+
+Tue May 25 09:33:16 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-tdep.c: Removed #include of many header files, and #define
+ of MIPSMAGIC; no longer used.
+
+Tue May 25 09:36:13 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Many places: replace "the inferior" in messages with "the program"
+ or "the program being debugged".
+ * inflow.c (try_writing_regs): Remove; it's been #if 0'd forever
+ and I'm getting sick of maintaining it.
+
+ * config/i386/linux.mh: Don't use \ newline; the awk scripts don't
+ support it.
+
+ * config/i386/go32.mh: Define SER_HARDWIRE.
+ * Makefile.in: Define SER_HARDWIRE.
+ (DEPFILES): Use it.
+ (alldeps.mak): Add SER_HARDWIRE.
+ Remove all references to ser-hardwire.{c,o}.
+ * configure.in: Remove all ser_hardwire and gdb_serial_driver stuff.
+
+Mon May 24 23:50:05 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-nat.c (store_inferior_registers): Fill in all members of
+ inferior_fp_registers by reading them from the inferior before
+ modifying and writing them back.
+ Fixes unexplainable inferior FP exceptions after calls to the inferior
+ or setting of floating point registers.
+ * mips-tdep.c (mips_skip_prologue): Skip move of argument register
+ to register which is generated by gcc-2.4.
+
+Tue May 25 00:42:39 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * hppa-pinsn.c: Define OLD_TABLE before including opcode/hppa.h.
+
+Mon May 24 13:55:14 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/i386/{i386lynx.mh i386lynx.mt nm-i386lynx.h tm-i386lynx.h
+ xm-i386lynx.h}: New configuration for Lynx.
+
+Mon May 24 10:01:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mipsread.c (parse_symbol): Deal with scVar and scVarRegister.
+ * symtab.h: Comment that LOC_REGPARM_ADDR can be call by reference.
+
+ * c-typeprint.c (c_type_print_base): Don't print typedef'd names
+ as struct, union, or enum tags.
+
+Mon May 24 01:10:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (dump_msymbols): Avoid gdb coredump with stripped
+ executable.
+
+Sat May 22 10:03:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior),
+ infcmd.c (program_info, signal_command): Use symbolic signal names.
+
+ * inftarg.c (child_wait): Deal with EINTR and include message from
+ strerror if printing an error message.
+
+ * main.c (command_line_input): Use STOP_SIGNAL not SIGTSTP.
+
+ * stabsread.c: Remove most uses of lookup_fundamental_type.
+ (define_symbol): Use read_type for type of enum constant,
+ not just read_type_number. Also don't call error().
+ (define_symbol): For unrecognized constant type, one complaint (the
+ one from error_type) is enough. Don't make our own in addition.
+ (define_symbol): Don't treat an N_FUN 'R' as a prototype.
+ * gdbtypes.h: Doc fixes.
+
+Sat May 22 03:33:07 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Fix stack unwinding through _sigtramp on Irix. These patches are from
+ Paul Flinders <ptf@delcam.co.uk>.
+ * mipsread.c (fixup_sigtramp): Find _sigtramp on Irix even when the
+ executable uses sigvec.
+ * mips-tdep.c (read_next_frame_reg): Allow tm-file to override
+ sigcontext offsets.
+ * config/mips/tm-irix3.h: Add sigcontext offsets for Irix.
+
+Sat May 22 00:39:01 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Clear stop_signal if it should not
+ be passed to the inferior to make "handle <signal> nopass nostop" work.
+
+Sat May 22 00:21:41 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-irix3.h: Clean up, use tm-bigmips.h and redefine
+ the necessary bits.
+ * findvar.c (value_from_register): Fix uninitialized first_addr
+ which caused problems with assignment of doubles to register variables
+ on some targets.
+ * mipsread.c: Remove TM_FILE_OVERRIDE, include tm.h and provide the
+ missing mips definitions if necessary.
+
+ Fix handling of double register variables for mips targets and big
+ endian hosts. These patches are from Paul Flinders <ptf@delcam.co.uk>.
+ * config/mips/tm-mips.h: Increase MAX_REGISTER_{RAW,VIRTUAL}_SIZE to
+ 8 bytes for doubles.
+ * config/mips/tm-mips.h (REGISTER_CONVERT_TO_TYPE): New macro for
+ conversion of type held in multiple registers to host format.
+ * config/mips/tm-mips.h (REGISTER_CONVERT_FROM_TYPE): New macro,
+ companion to REGISTER_CONVERT_TO_TYPE.
+ * config/mips/tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE):
+ Convert to function calls.
+ * config/mips/tm-mips.h (FIX_CALL_DUMMY): New code for big endian
+ mips targets.
+ * mips-tdep.c (mips_print_register): Raw buffer now needs just
+ MAX_REGISTER_RAW_SIZE bytes.
+ * mips-tdep.c (mips_print_register): Use REGISTER_CONVERT_TO_TYPE
+ (if defined) for doubles.
+ * mips-tdep.c: (mips_extract_return_value, mips_store_return_value):
+ New functions, take care of REGISTER_CONVERT_TO/FROM_TYPE.
+ * valops.c (value_assign): Use REGISTER_CONVERT_TO_TYPE if
+ defined.
+ * findvar.c (value_from_register): Use REGISTER_CONVERT_TO_TYPE if
+ defined.
+
+Fri May 21 09:04:25 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Add i[34]86-*-isc*.
+
+ * stabsread.c: Make sure all complain() pass the address of the struct.
+
+ * xcoffread.c: Make sure all struct complaints are static not auto.
+
+ * Makefile.in: Add rule for xcoffexec.o like that for paread.o.
+
+ * xcoffread.c (process_xcoff_symbol, case C_LSYM): Use define_symbol.
+
+Wed May 19 12:33:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/linux.mh: Re-enable coredumps now that they should work.
+
+Wed May 19 15:44:20 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * config/m68k/tm-m68k.h (FRAME_CHAIN): add missing close paren.
+
+Wed May 19 15:33:57 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/pa/nm-hppab.h: Comment PTRACE_ARG3_TYPE.
+
+Wed May 19 12:33:59 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (INSTALLED_LIBS): New variable.
+
+Tue May 18 14:08:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (quit_command): In the "quit anyway?" message, tell the user
+ whether we are planning to detach or kill the program.
+
+ * config/vax/vaxbsd.mh: Add "NAT_FILE= nm-vax.h".
+ * config/vax/xm-vaxbsd.h: Use <sys/param.h> not <machine/limits.h>
+
+ * infcmd.c (read_pc): Doc fix.
+
+ * printcmd.c (print_address_symbolic): Use %u not %d for offset.
+
+ * blockframe.c (get_prev_frame_info): If pc in sigtramp, set
+ signal_handler_caller.
+ * tm-68k.h (FRAME_{CHAIN,SAVED_PC}): Deal with sigtramp.
+ * tm-hp300bsd.h: Define SIGTRAMP_{START,END} not IN_SIGTRAMP.
+ * inferior.h (IN_SIGTRAMP): Definition moved from infrun.c.
+ Use SIGTRAMP_START if defined.
+ * infcmd.c (step_1): Use SIGTRAMP_{START,END} if needed.
+ * infrun.c (wait_for_inferior): Check IN_SIGTRAMP before SKIP_PROLOGUE.
+
+ * infptrace.c: Remove unused KERNEL_U_ADDR_HPUX code.
+
+ * infcmd.c (step_1): Fix poorly worded error message.
+
+ * config/{i386/linux.mh,m68k/isi.mh} (NATDEPFILES):
+ Comment out corelow.c because core dumps are broken on these machines.
+
+ * Makefile.in (depend): Put "${srcdir}" in generated dependencies
+ if srcdir is not ".".
+ Also put in -I${BFD_DIR} or -I${READLINE_DIR} for files which need it.
+ (INCLUDE_CFLAGS): Remove BFD_DIR and READLINE_DIR.
+ * depend: Update to latest automatically built version.
+
+Tue May 18 08:10:45 1993 Fred Fish (fnf@cygnus.com)
+
+ * ChangeLog, ChangeLog-92: Split ChangeLog at 1993.
+ * Makefile.in (NONSRC): Add ChangeLog-92
+
+Tue May 18 08:03:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * findvar.c ({read,write}_register): Use REGISTER_RAW_SIZE
+ not typo RAW_REGISTER_SIZE.
+
+ * frame.h, inferior.h: Doc fixes.
+
+Mon May 17 15:43:03 1993 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (write_register): Add sanity check for register size.
+ (read_register): Fixup sanity check for register size to be
+ consistent with write_register().
+
+Mon May 17 07:36:20 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * sparclite/Makefile.in: Add dummy info, install and install-info
+ targets.
+
+Thu May 13 07:30:22 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-nindy.c: Removed declaration of coffstrip.
+ * nindy-share/nindy.c: #if 0 coffstrip routine; no longer used.
+
+Wed May 12 00:35:19 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.9.1 after release and cvs
+ tagging.
+
+ * Makefile.in (VERSION): GDB 4.9 release.
+
+Tue May 11 08:04:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * README: Update known bugs to include the Solaris bug that
+ leaves core dumps in the current directory when restarting the
+ inferior with "run". Expand on the testsuite information.
+
+ * Makefile.in (VERSION): Bump to 4.8.96 for what should hopefully
+ be the last 4.9 prerelease test archive.
+
+Mon May 10 22:13:23 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/m68k/xm-hp300bsd.h: Include <sys/param.h> to avoid INT_MAX
+ redefined warnings.
+
+Mon May 10 20:00:43 1993 Fred Fish (fnf@cygnus.com)
+
+ * README, NEWS: Update for gdb 4.9 release.
+
+Mon May 10 19:38:34 1993 John Gilmore (gnu@cygnus.com)
+
+ * ch-exp.y (MAX, MIN): Rename to MAX_TOKEN, MIN_TOKEN.
+ * target.c (MIN): #undef before defining.
+
+Mon May 10 16:03:03 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ Patch from Jeffrey Law:
+ * gdb/config/pa/nm-hppab.h (PTRACE_ARG3_TYPE): Define as caddr_t.
+
+Mon May 10 15:28:27 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * hppa-tdep.c (hppa_push_arguments): Allocate correct amount of
+ memory.
+
+Mon May 10 13:14:46 1993 Fred Fish (fnf@cygnus.com)
+
+ * ch-exp.y (start): Apply work-around to avoid bison warning.
+
+Sun May 9 07:25:02 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (BISON): Remove double quotes around BISON
+ definition when bison is used.
+
+ * configure.in (hppa*-hp-bsd): Change to hppa*-hp-bsd*
+ * configure.in (hppa*-hp-hpux): Change to hppa*-hp-hpux*
+ * configure.in (m68*-hp-bsd): Change to m68*-hp-bsd*
+ * configure.in (m68*-hp-hpux): Change to m68*-hp-hpux*
+ * configure.in (hppa*-*-bsd): Change to hppa*-*-bsd*
+ * configure.in (hppa*-*-hpux): Change to hppa*-*-hpux*
+ * configure.in (m68*-hp-bsd): Change to m68*-hp-bsd*
+ * configure.in (m68*-hp-hpux): Change to m68*-hp-hpux*
+
+ * Makefile.in (VERSION): Bump to 4.8.6.
+
+Sat May 8 12:36:03 1993 Fred Fish (fnf@cygnus.com)
+
+ * config/pa/xm-hppah.h (MALLOC_INCOMPATIBLE): Define it, and
+ include declarations for malloc/realloc/free. Both malloc and
+ realloc return 'void *' for non-ANSI compilations.
+
+Sat May 8 01:39:30 1993 (pes@regent.e-technik.tu-muenchen.de)
+
+ * coffread.c (read_coff_symtab): Don't fclose stream as it is no
+ longer opened twice.
+
+Thu May 6 21:08:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * solib.c (clear_solib): Don't close bfd if it is NULL.
+
+Thu May 6 20:55:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * core.c (dis_asm_read_memory): Cast second arg of
+ target_read_memory to "char *".
+ * breakpoint.c (watchpoint_check): Change arg type from PTR to
+ "char *", to match other functions called by catch_errors().
+
+Thu May 6 15:47:45 1993 Stu Grossman (grossman@cygnus.com)
+
+ * More patches from Jeffrey Law (law@cs.utah.edu).
+ * gdb/config/nm-hppab.h (PTRACE_ARG3_TYPE): Define as caddr_t.
+ * gdb/config/pa/tm-hppah.h (millicode_start, millicode_end):
+ Delete unnecessary declarations.
+
+Thu May 6 15:15:46 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-unix.c (wait_for): Use VTIME to do timeouts instead of
+ poll() for termio{s}.
+
+Thu May 6 10:03:41 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * i386-tdep.c (i386_frame_num_args): Always return -1.
+
+Wed May 5 15:16:33 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Patches from Jeffrey Law <law@cs.utah.edu>.
+ * gdb/hppa-tdep.c: Declare frame_saved_pc.
+ (frameless_function_invocation): New function.
+ (frame_saved_pc, init_extra_frame_info): Use
+ frameless_function_invocation.
+ * gdb/config/pa/tm-hppa.h (SAVED_PC_AFTER_CALL): Use saved_pc_after
+ call instead of just grabbing the value currently in %r2.
+ (FRAMELESS_FUNCTION_INVOCATION): Use frameless_function_invocation.
+ * gdb/config/pa/tm-hppah.h (SAVED_PC_AFTER_CALL): Delete private
+ definition and use the common one in tm-hppa.h.
+ * gdb/hppa-tdep.c (frame_chain_valid): If "use_unwind" is true, then
+ use unwind descriptors to determine if the frame chain is valid.
+ * gdb/hppa-tdep.c (find_dummy_frame_regs): Rework so that
+ it does not assume %r4 is the frame pointer.
+ * gdb/hppa-pinsn.c (print_insn): Handle 'r' and 'R' for break, rsm,
+ and ssm instructions.
+ * gdb/hppa-tdep.c (extract_5r_store, extract_5R_store): New
+ helper functions for print_insn.
+ * gdb/hppa-tdep.c (gcc_p, hpux_cc_p): Delete unused functions.
+ * gdb/config/pa/tm-hppa.h (ABOUT_TO_RETURN): Handle a return
+ which nullifies the following instruction.
+
+Tue May 4 12:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * infptrace.c [FIVE_ARG_PTRACE]: Define ptrace to call_ptrace and
+ pass the 5th arg there, rather than using an ANSI C-specific macro.
+
+ * Makefile.in (depend): Don't include ${CC} command for *.tab.c.
+
+Tue May 4 19:33:12 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.8.5
+ * Makefile.in (INCLUDE_CFLAGS): Add BFD_DIR and READLINE_DIR
+ directories to include search path.
+ * Makefile.in (CLIBS, CDEPS, ADD_FILES, ADD_DEPS): Clean up
+ whitespace.
+ * Makefile.in (depend): For gcc -MM line, use INTERNAL_CFLAGS
+ * Makefile.in (main.o, dbxread.o, coffread.o, mipsread.o,
+ elfread.o, dwarfread.o, stabsread.o, xcoffread.o, xcoffexec.o,
+ xdr_ld.o, xdr_rdb.o, nindy.o, Onindy.o, ttybreak.o, ttyflush.o,
+ udr.o, udip2soc.o): Remove explicit rules, use the ones that
+ are automatically generated in "depend".
+ * Makefile.in (paread.o): Document why a dependency doesn't get
+ automatically generated in "depend" and leave this explicit rule
+ in for now (FIXME).
+ * depend: Update to latest automatically generated version.
+
+Tue May 4 12:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c: Doc fix.
+
+ * Makefile.in (depend): Include $(CC) command in generated output.
+
+Mon May 3 22:51:05 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (NONSRC): Remove ${srcdir}/putenv.c.
+ * Makefile.in (SFILES): Add ${srcdir}/putenv.c.
+ * depend: Update to latest automatically built version.
+
+Mon May 3 19:20:20 1993 Stu Grossman (grossman@cygnus.com)
+
+ * sparclite/Makefile.in: Create default target that does nothing
+ in order to force user to build by hand.
+
+ * sparclite/Makefile: Remove. It's not necessary anymore.
+
+ * ser-unix.c (wait_for): New routine to handle read timeouts,
+ etc. Uses poll() if HAVE_TERMIO[S] is defined, select() otherwise.
+
+Mon May 3 13:52:08 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-pinsn.c (print_insn): Return value.
+
+Sun May 2 11:43:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SFILES): Remove ser-hardwire.c; it is a link made
+ at configuration time and doesn't belong in the distribution archive.
+
+ * Makefile.in (NONSRC): Add 29k-share/README.
+ * Makefile.in (HFILES): Add 29k-share/udi/udiids.h.
+
+ * defs.h (UINT_MAX, LONG_MAX, INT_MAX, INT_MIN): Replace hex
+ constants with slightly more portable definitions (still depends
+ on 2's complement arithmetic though).
+ * config/i386/nm-linux.h: Define NO_SYS_REG_H for no <sys/reg.h>.
+ * i386v-nat.c (sys/reg.h): Conditionalize include on
+ NO_SYS_REG_H. Linux doesn't have <sys/reg.h>.
+ * ser-unix.c (termio.h): Include <termio.h> like other files that
+ include termio.h, not <sys/termio.h> which may not exist (on
+ linux for example).
+
+Sat May 1 16:05:24 1993 Fred Fish (fnf@cygnus.com)
+
+ * valprint.c (print_longest): Change format parameter from a
+ 'char' to an 'int'. We can't have 'char' parameters with the
+ current coding style, where we mix prototypes with pre-ANSI
+ style declarations.
+ * value.h (print_longest): Change format parameter in prototype
+ from a 'char' to an 'int'.
+
+Sat May 1 02:47:20 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-mips.h (STAB_REG_TO_REGNUM): Match it with the gcc
+ definition.
+ * config/mips/tm-irix3.h (STAB_REG_TO_REGNUM): Add.
+ * irix4-nat.c (fill_fpregset): Fix bug with indexing into fpregsetp.
+
+Fri Apr 30 17:45:32 1993 Stu Grossman (grossman@cygnus.com)
+
+ * The following patches are from Jeffrey Law <law@cs.utah.edu>.
+ * config/pa/hppabsd.mh: Add more files to NATDEPFILES.
+ * config/pa/xm-hppa[bh].h: Define FIVE_ARG_PTRACE.
+ * hppab-nat.c: Delete WANT_NATIVE_TARGET ifdefs.
+ ptrace needs 5 arguments, #define ptrace to always
+ pass zero as the 5th argument.
+
+Fri Apr 30 15:54:13 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * configure.in: Match z8k-*-sim for z8000.
+ * config/h8500/tm-h8500.h, h8500-tdep.c: Lint.
+ * remote-hms.c: Update to use new serial protocol.
+
+Fri Apr 30 16:50:38 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * mips-tdep.c: remove include of sys/dir.h. Doesn't seem
+ necessary and Solaris doesn't have it.
+
+ * Makefile.in (clean-info, install, install-info, info, dvi,
+ check, all): do not echo recursion lines.
+
+ * 29k-share/udip2soc.c (UDIConnect): replace union wait with int.
+
+ * config/sparc/sun4sol2.mh (XM_CLIBS): add -lsocket which is
+ required target ports which use sockets (like a29k-udi).
+
+ * remote-udi.c (udi_wait): Use SIGURG, as Solaris doesn't have SIGLOST.
+
+Fri Apr 30 11:05:42 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * ser-unix.c [USE_{TERMIO,ALARM}_TIMEOUT]: New code to deal with
+ systems lacking select().
+
+ * Makefile.in (TAGS): Doc fix. Deal with empty DEPFILES.
+
+Fri Apr 30 10:06:46 1993 Fred Fish (fnf@cygnus.com)
+
+ * alldeps.mak, depend: Update with latest automatically built
+ versions.
+
+Thu Apr 29 12:03:23 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (SFILES): Add ser-unix.c and ser-go32.c.
+
+ * Makefile.in (make-proto-testsuite.dir): New target to make
+ prototype testsuite tree.
+
+ * Makefile.in (VERSION): Bump to 4.8.4.
+
+Thu Apr 29 08:46:22 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabsread.c (define_symbol): If unrecognized constant type,
+ complain() not error().
+
+Thu Apr 29 00:03:59 1993 Fred Fish (fnf@cygnus.com)
+
+ * infptrace.c: Add missing close paren to test for
+ FIVE_ARG_PTRACE defined.
+
+ * defs.h (CC_HAS_LONG_LONG): Set up to define CC_HAS_LONG_LONG
+ when compiling with gcc, but disable it for now. See comment.
+ * defs.h (LONGEST): Define as either "long" or "long long"
+ based on CC_HAS_LONG_LONG.
+ * defs.h (longest_to_int): Use CC_HAS_LONG_LONG to control
+ how longest_to_int is defined.
+ * c-valprint.c (c_val_print): Call print_longest.
+ * expprint.c (dump_expression): Use PRINTF_HAS_LONG_LONG
+ instead of LONG_LONG.
+ * {printcmd.c, gdbtypes.h} (LONG_LONG): Replace usages with
+ CC_HAS_LONG_LONG.
+ * printcmd.c (print_scalar_formatted): Call print_longest
+ and let it figure out what to do for PRINTF_HAS_LONG_LONG.
+ * typeprint.c (print_type_scalar): Call print_longest and let
+ it figure out what to do for PRINTF_HAS_LONG_LONG.
+ * valprint.c (val_print_type_code_int): Call print_longest
+ and let it figure out what to do for PRINTF_HAS_LONG_LONG.
+ * stabsread.c (LONG_LONG): Replace usages with CC_HAS_LONG_LONG.
+ * value.h (struct value): Replace usage of LONG_LONG with
+ CC_HAS_LONG_LONG.
+ * value.h (print_longest): Add prototype.
+ * values.c (LONG_LONG): Replace usages with CC_HAS_LONG_LONG.
+ * values.c (unpack_double): Collapse code that was unnecessarily
+ dependent on CC_HAS_LONG_LONG. Use LONGEST instead of direct types.
+ * values.c (value_from_longest): Remove dependency on
+ CC_HAS_LONG_LONG and just use LONGEST.
+ * solib.c (solib_map_sections): Use bfd_get_filename
+ to access filename field.
+ * solib.c (clear_solib): Save filename and free it later, after
+ bfd_close, since bfd_close may reference it. Use bfd_get_filename
+ to access the field.
+ * config/convex/xm-convex.h (LONG_LONG): Replace with
+ CC_HAS_LONG_LONG. Add define for PRINTF_HAS_LONG_LONG.
+ * doc/gdbint.texinfo (LONG_LONG): Replace with CC_HAS_LONG_LONG.
+ Add PRINTF_HAS_LONG_LONG references.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * inflow.c (kill_command), infcmd.c (attach_command),
+ remote.c (remote_interrupt_twice): In messages for the user, call it
+ "the program" or "the program being debugged" not "the inferior".
+
+ * hp300ux-nat.c: Cast second arg to supply_register calls.
+ (_initialize_kernel_u_addr, getpagesize): New functions.
+ (store_inferior_register_1): Change arg name from value to val.
+ (fetch_core_registers): Make arg core_reg_size unsigned.
+ Pass 5 args to ptrace.
+ * config/m68k/xm-hp300hpux.h: Define FIVE_ARG_PTRACE.
+ Remove KERNEL_U_ADDR stuff.
+ * infptrace.c [FIVE_ARG_PTRACE]: Pass 5th arg to ptrace.
+ * config/m68k/hp300hpux.m{t,h}:
+ Move exec.o from NATDEPFILES to TDEPFILES
+ * config/m68k/hp300hpux.mt: Mention GAS requirement. Remove
+ hp-include stuff. Add m68k-tdep.o to TDEPFILES.
+
+Wed Apr 28 13:27:54 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * ch-exp.y (yylex): Don't STREQ with simplename if it is NULL.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/sparc/xm-sun4os4.h [__STDC__]: Don't use MALLOC_INCOMPATIBLE.
+
+Wed Apr 28 11:39:18 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * doc/gdb.texinfo: make node "Shell Commands" unconditional;
+ describe `set demangle-style arm' (not cfront);
+ mention can type `q' to discard output, when gdb pages
+
+Wed Apr 28 11:32:39 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (search_struct_field): Fix gdb core dump with incomplete
+ stabs info.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * remote.c: Change timeout to 2.
+ (remote_open): Use unpush_target not remote_close.
+ (remote_resume): If siggnal != 0, give warning not error().
+ (remote_wait, remote_interrupt, remote_interrupt_twice):
+ If we get two interrupts, let the user get out if they want.
+ (remote_{kill,mourn}): New functions.
+ i386-stub.c (handle_exception, case 'k'): Don't BREAKPOINT.
+
+Wed Apr 28 09:20:55 1993 Ian Lance Taylor (ian@rtl.cygnus.com)
+
+ * config/sparc/sun4sol2.mh (XM_CLIBS): Define to be -lnsl.
+
+Wed Apr 28 06:11:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Remote targets (mourn): Call unpush_target.
+
+ * config/sparc/xm-sun4os4.h: Declare free() to return int.
+ Remove twisted use of PARAMS.
+
+ * config/rs6000/xm-rs6000.h: Don't define MALLOC_INCOMPATIBLE now
+ that ansidecl.h assumes ANSI on AIX.
+
+Tue Apr 27 10:01:33 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * README: Move most stuff about hacking GDB to doc/gdbint.texinfo.
+ (Known bugs): Remove AIX bugs, revise SPARC struct bug description.
+
+Tue Apr 27 13:44:19 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * expprint.c (print_subexp): Fix bug with OP_SCOPE operator output.
+
+Tue Apr 27 10:01:33 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * remote-vx.c (net_connect): Allow numeric IP address for host.
+
+Mon Apr 26 17:59:38 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * config/sh/sh.mt, config/sh/tm-sh.h, sh-tdep.c: New files.
+
+Mon Apr 26 07:13:32 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * rs6000-tdep.c (branch_dest): Deal with stepping through system call.
+
+ * symtab.h, xcoffread.c: Revise linetable sorting comments.
+
+Sun Apr 25 02:32:16 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (value_cast): A cast might also change the object
+ representation in C++.
+ * dbxread.c (end_psymtab): Copy subpst read_symtab function from pst
+ to get the proper read_symtab function when called from mipsread.c.
+ * mipsread.c (mipscoff_psymtab_to_symtab, psymtab_to_symtab_1):
+ Set cur_bfd in psymtab_to_symtab_1 as CURBFD(pst) is invalid
+ for dummy psymtabs, inhibit processing of dummy psymtabs.
+
+Sat Apr 24 19:59:54 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Changes from (or inspired by) AMD:
+ * remote-udi.c (udi_attach): Assignments to Space and Offset were
+ switched, fix it.
+ (udi_wait): Make error message (UDIGetStdout) match error.
+ (udi_wait): Handle UDIStdinNeeded.
+ * command.c [CANT_FORK]: Use system().
+ * utils.c (prompt_for_continue): Allow quit with 'q'.
+
+ * solib.c (solib_add): Don't call special_symbol_handling if there
+ were errors in symbol_add_stub. Also set so->from_tty before
+ calling symbol_add_stub.
+
+Fri Apr 23 16:17:00 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Merge in HPPA/BSD patches from Utah:
+ * defs.h: Add const to 2nd arg of psignal prototype.
+ * hppah-tdep.c: Renamed to hppa-tdep.c 'cuz it's common code with
+ BSD now.
+ * hppab-core.c: Deleted. No longer useful.
+ * hppab-nat.c: #include more files. Use PT_WUREGS, not
+ PT_WRITE_U.
+ * hppab-tdep.c: Deleted. Supplanted by hppa-tdep.c.
+ * config/pa/hppabsd.mh (NATDEPFILES): Remove hppab-core.o.
+ * config/pa/hppabsd.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o
+ * config/pa/hppahpux.mt (TDEPFILES): hppab-tdep.o => hppa-tdep.o
+ * config/pa/xm-hppab.h: #define SET_STACK_LIMIT_HUGE.
+
+Fri Apr 23 10:34:02 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Fix two bugs found by deja-gnu. One is the incorrect reporting
+ of the PC being in a stack dummy when looking at a core file
+ without symbols. The other is the incorrect passing of char
+ arguments during expression evaluation (ie: p foo('a','b') would
+ mess up the passing of it's args because it wasn't coercing the
+ char's to ints).
+ * hppah-tdep.c: Rename global functions to have consistent hppa_
+ prefix. Make more functions static. Drop hp_ prefix from static
+ functions. (hppa_push_arguments): Call value_arg_coerce to cast
+ char to int args if necessary. (hppa_fix_call_dummy): Create
+ this routine from FIX_CALL_DUMMY macro in tm-hppa.h.
+ * inferior.h (PC_IN_CALL_DUMMY): Check for frame_address being
+ valid (ie: != 0) before doing comparison against PC.
+ * valops.c (call_function_by_hand): Adjust call to FIX_CALL_DUMMY
+ to reflect new arguments.
+ * config/pa/tm-hppa.h (POP_FRAME, PUSH_ARGUMENTS): Use new hppa_
+ prefix for func name. (FIX_CALL_DUMMY): Move code into
+ hppah-tdep.c.
+
+ * testsuite/gdb.t16/gdbme.c, testsuite/gdb.t17/gdbme.c: Add calls
+ to malloc() so that we can test GDB eval of dynamically created
+ arrays (like char strings in `print "foo"').
+
+Fri Apr 23 01:28:14 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * printcmd.c (print_address_symbolic): Search symtabs as well as the
+ minimal symbols for a nearby symbol.
+
+Thu Apr 22 19:44:21 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * coffread.c: Comment changes around minimal symbol recording.
+
+Thu Apr 22 16:24:36 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * command.c: comment changes only.
+
+ * mips-tdep.c (heuristic_fence_post): new static variable.
+ (heuristic_proc_start): use heuristic_fence_post, print better
+ warnings, but only if not stop_soon_quietly.
+ (_initialize_mips_tdep): add_set_cmd for heuristic-fence-post.
+
+Thu Apr 22 14:50:05 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * symtab.h: Fix LOC_REF_ARG comment.
+
+Wed Apr 22 20:21:30 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ and Jim Kingdon (kingdon@cygnus.com)
+
+ * stabsread.c (define_symbol): Combine a 'p', 'r' arg pair to a
+ LOC_REGPARM symbol.
+ * config/sparc/tm-sparc.h (REG_STRUCT_HAS_ADDR): Revise comments.
+ symfile.c (compare_symbols): Don't check first character; STRCMP
+ does that.
+
+ * stabsread.c (define_symbol): Generate a LOC_REGPARM_ADDR for
+ structures that are passed by address in a register.
+ * symtab.h (enum address_class): Add LOC_REGPARM_ADDR.
+ * findvar.c (read_var_value),
+ printcmd.c (address_info, print_frame_args),
+ stack.c (print_frame_arg_vars), symmisc.c (print_{,partial_}symbol),
+ * symtab.c (lookup_block_symbol): Deal with it.
+
+Thu Apr 22 09:07:24 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * objfiles.h (obj_section), objfiles.c (build_objfile_section_table):
+ Add objfile field.
+ * objfiles.c (find_pc_section): Return a struct obj_section *.
+ * sparc-tdep.c (in_solib_trampoline): Deal with find_pc_section return.
+ * symfile.c (syms_from_objfile) [IBM6000_TARGET]:
+ Don't use obj_section hack.
+ * xcoffexec (vmap_symtab): Relocate obj_sections.
+ * printcmd.c (containing_function_bounds): Use find_pc_section.
+
+ * symtab.h: Clean up SYMBOL_VALUE comments.
+
+Wed Apr 21 14:29:57 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stack.c (print_frame_arg_vars), printcmd.c (print_frame_args):
+ Expand comments about LOC_ARG/LOC_LOCAL pairs.
+
+ * coffread.c (read_coff_symtab): Use rewind before fseek.
+
+Wed Apr 21 14:24:19 1993 Per Bothner (bothner@cygnus.com)
+
+ * ch-exp.y: Removed unused structure_primitive_value and FIXME_23.
+ * Makefile.in: Add $(YFLAGS) when using $(YACC).
+ * Makefile.in: Remove message to expect conflicts and unused
+ rules in ch-exp.y, since there no longer are any such.
+
+Wed Apr 21 13:27:50 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * stabs.texinfo: fixed bad xrefs (un-initialized statics)
+
+Tue Apr 20 08:55:11 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffexec.c (xcoff_relocate_core): If no exec file, error()
+ rather than dumping core.
+
+ * Makefile.in: Add ${srcdir}/ to all source files.
+ (alldeps.mak): Add "${srcdir}/" to files when generating alldeps.mak.
+ (TAGS): Deal with srcdir and new config directory scheme.
+ createtags: Remove.
+ Makefile.in (NONSRC): Remove createtags.
+ alldeps.mak: Updated.
+
+ * rs6000-tdep.c: Delete unused function print_frame.
+
+ * frame.h (struct frame_info): Doc fix for next_frame.
+ New field signal_handler_caller.
+ blockframe.c (create_new_frame, get_prev_frame_info),
+ config/rs6000/tm-rs6000.h (INIT_EXTRA_FRAME_INFO): Set it (needs
+ INIT_FRAME_PC_FIRST).
+ stack.c (print_frame_info), rs6000-tdep.c (rs6000_frame_chain):
+ Check it.
+
+Mon Apr 19 22:52:33 1993 Stu Grossman (grossman@cygnus.com)
+
+ * irix4-nat.c (fetch_core_registers): Special version of this for
+ Irix 4.x, which stores regs a bit differently from other /proc
+ based systems.
+ * procfs.c, core-svr4.c: Move fetch_core_registers from procfs.c
+ to new file core-svr4.c.
+ * config/i386/i386sol2.mh, config/i386/i386v4.mh, config/m68k/amix.mh,
+ config/i386/ncr3000.mh, config/sparc/sun4sol2.mh: Add core-svr4.o
+ to NATDEPFILES.
+ * config/mips/irix4.mh: Add corelow.o to NATDEPFILES.
+
+Mon Apr 19 11:13:34 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * i387-tdep.c: Remove unused #includes.
+
+ * configure.in: Match i[34]86-*-sysv3.2 not i[34]86-*-sysv32.
+
+ * config/i386/nm-i386v.h: Define NO_PTRACE_H.
+
+Sun Apr 18 10:39:35 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c: Nuke NO_DEFINE_SYMBOL code. There is no going back.
+
+ * stabsread.c (define_symbol): 'R' is synonym for 'P', not 'r'.
+ xcoffread.c (process_xcoff_symbol, case C_RPSYM):
+ Don't muck with SYMBOL_CLASS.
+
+Fri Apr 16 17:38:33 1993 Stu Grossman (grossman@cygnus.com)
+
+ * munch: Don't use head command. It doesn't exist everywhere.
+
+Fri Apr 16 15:07:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * inflow.c (new_tty): Remove spurious 'o' character at end
+ of #endif line.
+
+Fri Apr 16 12:27:11 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (mips_skip_prologue): Always skip the typical prologue
+ instructions and nothing more.
+ * mipsread.c (add_line): Add comment why we have to combine line number
+ entries for the same line number.
+
+Fri Apr 16 09:42:03 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * symtab.{c,h}: Doc fixes (remove symseg references, last relevant
+ in gdb 2.8!).
+
+Thu Apr 15 21:16:58 1993 Fred Fish (fnf@cygnus.com)
+
+ * depend, alldeps.mak: Update, now that gcc -MM bug is fixed.
+
+Thu Apr 15 12:38:39 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * source.c (select_source_symtab): Clean up comment. Also, if
+ we have a current_source_symtab, and s is NULL, return without
+ doing anything.
+ xcoffread.c (xcoff_symfile_read): Don't call select_source_symtab.
+ breakpoint.c (breakpoint_re_set): Don't call select_source_symtab.
+
+Thu Apr 15 02:37:48 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * dbxread.c (unknown_symchar_complaint): Add new complaint.
+ * stabsread.h: Declare it.
+ * partial-stab.h: Use it.
+
+ * utils.c (malloc_botch): Don't forward-declare if NO_MMALLOC.
+
+Wed Apr 14 17:12:51 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stack.c (print_frame_info): Print specially if dummy frame.
+
+ * breakpoint.c: Add comments regarding within_scope future direction.
+
+ * Version 4.8.3.
+
+ * xcoffread.c (record_include_{begin,end}): Change fatal to complain.
+
+Wed Apr 14 14:03:18 1993 Per Bothner (bothner@cygnus.com)
+
+ * ch-exp.y: Fix thinko that broke parsing of FALSE.
+
+Wed Apr 14 12:49:29 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.c (read_member_functions): Initialize domain for stubbed
+ member functions to avoid gdb core dumps when printing pointers
+ to member functions.
+ * cp-valprint.c (cp_print_class_method): Check for stubbed member
+ functions.
+
+Tue Apr 13 08:28:26 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * expprint.c (print_subexp): If opcode not found in op_print_tab,
+ stop with an error().
+ eval.c (evaluate_subexp): Change error message.
+
+ * objfiles.c (build_objfile_section_table): Cast return value
+ from obstack_finish.
+
+Mon Apr 12 10:53:50 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/rs6000/tm-rs6000.h, rs6000-tdep.c: Move FRAME_CHAIN
+ to rs6000_frame_chain and deal with it if we're in a signal handler.
+ (FRAME_SAVED_PC): Use rs6000_frame_chain.
+
+ * breakpoint.c (within_scope): New function.
+ (enable_breakpoint, watchpoint_check): Use it.
+
+ * source.c (openp): Handle "exec-file ./ls" correctly.
+
+ * breakpoint.c (breakpoint_1): Use wrap_here before "at".
+
+Sat Apr 10 01:32:43 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * ch-exp.y: Clean up lexing of identifiers and
+ reserved words. (E.g. don't recognize FALSEXXX as the
+ keyword FALSE followed by the identifier XXX.)
+ Also, convert identifiers to lower case.
+
+Fri Apr 9 15:53:19 1993 Stu Grossman (grossman@cygnus.com)
+
+ * remote-mips.c, remote-monitor.c, remote-st2000.c: Convert to
+ new serial interface.
+
+Fri Apr 9 15:01:12 1993 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (remote_open): Use SERIAL_OPEN instead of serial_open.
+ (putpkt, getpkt): Use new return codes for SERIAL_READCHAR.
+ * ser-go32.c: Return -1 on most failures, 0 on most successes,
+ and use new return codes for go32_readchar().
+ * ser-unix.c: Ditto. Also, move error handling up to caller for
+ SERIAL_SETBAUDRATE().
+ * serial.c (serial_open): Internal call, not SERIAL_OPEN to get
+ to specific routine.
+ (serial_close): New routine to wrap around device close routine.
+ serial.h: Clean & document return values more clearly.
+
+Fri Apr 9 10:20:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * rs6000-pinsn.c (print_operand): Deal with no operand instructions.
+
+ * rs6000-pinsn.c (print_operand, case LI): Print condition register
+ operand in decimal rather than wrong textual versions.
+
+ * printcmd.c (_initialize_printcmd): Clean up docstring for "x"
+ (mention 't', remove false thing about 'g' only good with 'f').
+
+ * breakpoint.h: move "struct breakpoint" and friends to top of
+ file so that bpstat_find_breakpoint prototype works.
+
+ * solib.c (struct so_list): Add bfd field.
+ (solib_map_sections): Leave bfd open and scratch_pathname allocated.
+ Put the bfd in bfd field of the so_list.
+ (clear_solib): Free bfd name and close_bfd on the bfd.
+
+Fri Apr 9 00:45:41 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * valarith.c (value_subscript): Add COERCE_REF.
+ * ch-exp.y (operand_5): We can generalize the 2nd operand
+ of a string repetition ot 'literal' without ambiguity.
+
+Thu Apr 8 10:15:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.h (struct bpstat): Remove momentary field.
+ Remove bpstat_momentary_breakpoint. This was always kludgy
+ and is no longer used.
+
+ * breakpoint.h: Add enum bpstat_what.
+ breakpoint.h (struct bpstat), breakpoint.c (bpstat_stop_status):
+ stop and print fields of bpstat now per-breakpoint, not just
+ one for the whole chain.
+ breakpoint.{c,h} (bpstat_what): New function.
+ breakpoint.h: Remove bpstat_stop and bpstat_should_print.
+ infrun.c: Replace switch (stop_bpstat->breakpoint_at->type)
+ with call to bpstat_what.
+ README: Remove watchpoint/breakpoint bug from known bugs.
+
+ * breakpoint.h: Prototype bpstat_find_breakpoint.
+
+Thu Apr 8 16:01:21 1993 Fred Fish (fnf@cygnus.com)
+
+ * symtab.c (find_methods, gdb_mangle_name): Note that functions
+ are g++ specific.
+ * symtab.h (VTBL_FNADDR_OFFSET, OPNAME_PREFIX_P, VTBL_PREFIX_P,
+ DESTRUCTOR_PREFIX_P): Note that macros are g++ specific.
+
+Thu Apr 8 12:45:32 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * i960-pinsn.c (tabent): Copied struct definition from
+ opcodes/i960-dis.c.
+
+Thu Apr 8 10:34:37 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.h (DESTRUCTOR_PREFIX_P): New macro to check if physname
+ is a C++ destructor.
+ * symtab.c (gdb_mangle_name): Use it.
+ * symtab.c (find_methods): Do not add destructors to choice list
+ for constructors.
+ * symtab.c (decode_line_1): Make breakpoints on destructors work
+ for gcc-2.x again.
+
+Wed Apr 7 18:43:09 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: Make it use serial port name.
+ * go32-xdep.c: Put in def for strlwr, needed by dir.o in go32 libc.
+
+ * infcmd.c (read_pc): Make sure that we read PC_REGNUM when not
+ in a system call!
+
+Wed Apr 7 15:52:11 1993 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Only configure sparclite subdir when target_cpu
+ is sparclite.
+
+Wed Apr 7 10:11:22 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (struct coff_symbol): Change c_sclass to unsigned char.
+ Remove FIXME comment regarding this.
+
+ * symfile.h: Change NULL->'\0' in comment (that wasn't a typo).
+
+ * xcoffread.c (read_xcoff_symtab): Use E_SYMNMLEN.
+
+Tue Apr 6 22:30:58 1993 K. Richard Pixley (rich@cygnus.com)
+
+ Add section table to objfile struct. Use it for find_pc_section.
+ * objfiles.c (add_to_objfile_sections,
+ build_objfile_section_table, find_pc_section): new functions.
+ (allocate_objfile): build section table.
+ * objfiles.h (struct obj_section): new structure.
+ (struct objfile): add section table.
+ (find_pc_section): new prototype.
+ * solib.[ch] (find_pc_section_from_so_list): removed.
+ * sparc-tdep.c: include objfiles.h for find_pc_section. include
+ symfile.h for objfiles.h.
+ (in_solib_trampoline): adjusted for new find_pc_section
+ prototype. Removed BAD_RICH_HACK ifdefs.
+ * symfile.c (syms_from_objfile): offset objfile sections.
+ (find_pc_section): removed. Also removed BAD_RICH_HACK ifdefs.
+ * symfile.h (find_pc_section): prototype removed. Also fixed
+ comment typo NUL -> NULL.
+ * target.[ch] (find_pc_section_from_targets): removed.
+ * config/sparc/tm-sun4sol2.h (BAD_RICHH_HACK): removed.
+
+Tue Apr 6 21:41:13 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: Format. (go32_open): Use proper return value.
+
+ * configure.in: Undo conditional configdirs hack for sparclite.
+
+Tue Apr 6 17:07:37 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * symtab.c (list_symbols): When call break_command, pass both
+ filename and function name not just function name.
+
+Tue Apr 6 15:00:09 1993 Fred Fish (fnf@cygnus.com)
+
+ (Changes and new files to make "none" a full fledged configuration)
+ * config/none/{nm-none.h, tm-none.h, xm-none.h}: New files.
+ Currently only tm-none.h has any meaningful contents.
+ * config/none/none.mh (NAT_FILE): Use nm-none.h
+ * config/none/none.mh (XM_FILE): Use xm-none.h
+ * config/none/none.mt (TM_FILE): Use tm-none.h
+ * Makefile.in (depend): Remove comment about parse errors in
+ valops.c, it now parses correctly and generates a correct depend
+ line. Remove line that touches xm.h, tm.h, and nm.h; they are
+ now linked to config/none/{xm-none.h, tm-none.h, nm-none.h}.
+
+Tue Apr 6 09:54:29 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * values.c (USE_STRUCT_RETURN): Only use gcc wierdness for gcc1.
+
+ * xcoffread.c (read_xcoff_symtab): Deal correctly with symbols of
+ exactly 8 characters.
+
+Tue Apr 6 10:31:26 1993 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Sparclite uses sparc config dir. Also has it's
+ own tm- & .mt files now. Also add sparclite to configdirs.
+ * go32-xdep.c: Dummy routines for sigsetmask & strlwr.
+ * config/i386/go32.mh: Nullify def of TERMCAP.
+ * config/i386/xm-go32.h: Get rid of redef of EIO.
+ * config/sparc/{sparclite.mh tm-sparclite.h}: New sparclite
+ specific configs. Very similar to sun4os4, but without solib.
+ * sparclite/{Makefile.in configure.in}: First cut at making this
+ dir configgable.
+
+Tue Apr 6 03:10:44 1993 Stu Grossman (grossman@cygnus.com)
+
+ * ser-go32.c: First cut at adapting to new serial interface.
+
+Mon Apr 5 22:29:43 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (SFILES OBS): Add serial.[co] & ser-hardwire.[co].
+ These implement a new serial line interface for talking to remote
+ targets.
+ * configure.in: Link ser-hardwire.c to ser-unix.c for all hosts,
+ EXCEPT go32, which gets ser-go32.c.
+ * remote.c: Use new serial interface. More remote-xxx's to be
+ converted later.
+ * ser-bsd.c, ser-termios.c: Removed.
+ * serial.c: New. Implements common operations for all serial
+ types.
+ * ser-unix.c: New. Unix specific serial operations for various
+ flavors of Unix (Posix, SysV, BSD).
+ * serial.h: Generic serial interface defs.
+ * config/i386/go32.mh, config/i386/i386bsd.h,
+ config/m68k/apollo68b.mh, config/sparc/sun4os4.mh: Remove
+ ser-bsd.o from XDEPFILES. All the magic is now handled in
+ configure.in.
+
+Mon Apr 5 20:48:54 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/h8500/tm-h8500.h: Clean up brain damage found by GCC.
+
+Fri Apr 2 08:23:14 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (xcoff_symfile_offsets): Use 0 not addr for offsets.
+
+ * rs6000-tdep.c (frameless_function_invocation): Don't even think
+ about framelessness except on the innermost frame.
+
+ * xcoffexec.c: Call fatal() not abort().
+
+ * stabsread.c (patch_block_stabs): If stab & no symbol, make
+ a LOC_OPTIMIZED_OUT symbol.
+ symtab.h (enum address_class): Add LOC_OPTIMIZED_OUT.
+ findvar.c (read_var_value), printcmd.c (address_info),
+ symmisc.c (print_{,partial_}symbol), c-exp.y (variable),
+ m2-exp.y (yylex): Deal with it.
+ ch-exp.y (yylex): Deal with it.
+
+Thu Apr 1 18:43:02 1993 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (value_from_register): H8500 specific, check to see
+ if we are looking at short pointer. If so, skip crock.
+ * h8500-tdep.c (h8500_frame_chain): Mask down value from
+ read_memory_integer() to avoid getting messed up by sign extension.
+
+Thu Apr 1 16:44:41 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * sparc-tdep.c (in_solib_trampoline), symfile.c (find_pc_section):
+ ifdef protect using BAD_RICH_HACK. This should be removed soon.
+ * config/sparc/tm-sun4sol2.h (BAD_RICH_HACK): define.
+
+Thu Apr 1 09:01:38 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * i960-pinsn.c, a29k-pinsn.c: Much abridged, just use libopcodes.a.
+
+ * core.c (dis_asm_print_address): New function.
+
+ * core.c (dis_asm_read_memory): Reinstate 4th arg. The prototype
+ has been fixed.
+
+Thu Apr 1 09:34:43 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (bpstat_print, bpstat_stop_status): Change to walk the
+ entire breakpoint chain and print only the first entry that needs to
+ be printed and needs to be stopped for. Fixes problems with printing
+ of multiple breakpoints with different conditions.
+ * breakpoint.c (print_it_done): Renamed from print_it_noop as it
+ effectively stops printing of the breakpoint chain.
+ * breakpoint.c (print_it_noop): New routine to print nothing
+ for this breakpoint entry and dont stop printing.
+ * breakpoint.c (breakpoint_re_set_one): mention the reevaluated
+ watchpoint only if it is enabled.
+ * mipsread.c (parse_procedure): Correct incorrect setjmp procedure
+ descriptor from the library to make backtraces through setjmp work.
+ * mipsread.c (fixup_sigtramp): Correct pcreg and fregoffset for
+ sigtramp.
+ * mips-tdep.c (read_next_frame_reg): Provide correct values for
+ all registers saved within sigtramp, cleanup.
+
+Wed Mar 31 12:52:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-pinsn.c: Much abridged, just calls version in libopcodes.a.
+
+Wed Mar 31 21:23:41 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * core.c (dis_asm_read_memory): drop fourth arg which conflicts
+ with prototype in ../include/dis-asm.h.
+
+Wed Mar 31 12:52:12 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * core.c (dis_asm_{read_memory,memory_error}): New functions.
+ m68k-pinsn.c, h8500-tdep.c, i386-pinsn.c, mips-pinsn.c, z8k-tdep.c:
+ Use read_memory_func interface to disassembler.
+
+Tue Mar 30 15:46:14 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ Teach sparc solaris to next over shared library functions.
+ * solib.[hc] (find_pc_section_from_so_list): new function and
+ prototype.
+ * sparc-tdep.c (in_solib_trampoline): new function.
+ * symfile.[hc] (find_pc_section): new function and prototypes.
+ * target.[hc] (find_pc_section_from_targets): new function and
+ prototypes.
+ * config/sparc/tm-sun4sol2.h (IN_SOLIB_TRAMPOLINE): redefine to
+ in_solib_trampoline.
+
+Tue Mar 30 08:06:24 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Revise comment.
+
+ * command.c (do_setshow_command): Use %u with var_{u,z}integer.
+
+ * command.{c,h}: New var_type var_integer.
+ main.c: Use it for history_size.
+
+ * rs6000-tdep.c, xcoffexec.c, config/rs6000/xm-rs6000.h, breakpoint.c:
+ Lint and byte-order fixups.
+
+ * breakpoint.c (print_it_normal): Return 0 after hitting watchpoint.
+
+ * breakpoint.h (bpstat): New field print_it.
+ breakpoint.c (bpstat_print): Use it.
+ (print_it_normal): New function (from old bpstat_print code).
+ (bpstat_{alloc,stop_status}): Set print_it field.
+
+ * breakpoint.c (bpstat_stop_status): Use catch_errors when
+ evaluating watchpoint condition, via new function watchpoint_check.
+ Also stop if watchpoint disabled due to leaving its block.
+
+ * findvar.c [REG_STRUCT_HAS_ADDR]: Add comment.
+
+Tue Mar 30 00:14:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-pinsn.c: Add missing include of dis-asm.h.
+
+Mon Mar 29 15:03:25 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (clean, distclean, realclean): Recursively apply
+ to subdirs first, rather than last. This avoids, for example,
+ Makefile being removed in a parent directory before the recursive
+ make is run.
+
+ * alldeps.mak, depend: Update for below changes.
+
+ * config/m68k/tm-m68k.h: Renamed from config/m68k/tm-68k.h.
+ * m68k/{tm-3b1.h, tm-altos.h, tm-amix.h, tm-es1800.h,
+ tm-hp300bsd.h, tm-hp300hpux.h, tm-isi.h, tm-news.h, tm-os68k.h,
+ tm-st2000.h, tm-sun2.h, tm-sun3.h, tm-vx68.h}: Include tm-m68k.h
+ instead of tm-68k.h.
+ * Makefile.in (HFILES): tm-68k.h renamed to tm-m68k.h.
+ * README, a29k-pinsn.c, m68k-pinsn.c, m68k-stub.c, remote-vx.c,
+ m68k/{altos.mh, altos.mt, apollo68b.mh, nm-apollo68b.h,
+ nm-hp300bsd.h, config/m68k/xm-apollo68b.h}: Map '68k' to 'm68k'.
+ * a29k/tm-a29k.h, doc/gdbint.texinfo: Account for renaming of
+ tm-68k.h to tm-m68k.h.
+ * m68k/m68k-fp.mt (TM_FILE): tm-68k-fp.h renamed to tm-m68k-fp.h.
+ * m68k/m68k-nofp.mt (TM_FILE): tm-68k-nofp.h renamed to
+ tm-m68k-nofp.h.
+
+ * config/a29k/tm-a29k.h: Renamed from config/a29k/tm-29k.h.
+ * a29k-pinsn.c: Renamed from am29k-pinsn.c.
+ * a29k-tdep.c: Renamed from am29k-tdep.c.
+ * remote-eb.c, config/a29k/tm-ultra3.h: Include renamed tm-a29k.h.
+ * remote-monitor.c, remote-st2000.c, config/a29k/{nm-ultra3.h,
+ tm-a29k.h, xm-ultra3.h}, config/romp/rtbsd.mh, doc/gdbinv-s.texi,
+ testsuite/gdb.t15/funcargs.exp, testsuite/gdb.t17/callfuncs.exp:
+ Map '29k' to 'a29k'.
+ * config/a29k/{a29k-kern.mt, a29k-udi.mt, a29k.mt, ultra3.mt}
+ (TDEPFILES): Use renamed a29k-pinsn.o and a29k-tdep.o.
+ * config/a29k/{a29k-udi.mt, a29k.mt} (TM_FILE): Use renamed
+ tm-a29k.h.
+ * config/a29k/a29k-udi.mt (MT_CFLAGS): Remove TARGET_AM29K
+ define that does not appear anywhere else in the gdb source tree.
+ * doc/gdbinit.texinfo: Document renaming of tm-29k.h to tm-a29k.h.
+
+Mon Mar 29 13:55:29 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.c: Add comments regarding breakpoint_re_set.
+
+ * xcoffread.c (sort_syms, compare_symbols): Remove.
+ (xcoff_symfile_read): Use sort_all_symtab_syms from symfile.c
+ not our own sort_syms (it is identical).
+
+ * xcoffread.c: Nuke NAMES_HAVE_DOT define (not used).
+
+Sun Mar 28 11:24:37 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * breakpoint.c (breakpoint_re_set_one): Fix storage leak.
+ * breakpoint.c (enable_breakpoint): Don't enable watchpoint if it
+ went out of scope.
+ * exec.c (exec_close): Fix storage leak.
+ * exec.c (exec_file_command): Make sure that bfd doesn't realign the
+ output sections when patching an executable.
+ * mips-nat.c (store_inferior_registers): Use REGISTER_PTRACE_ADDR
+ when writing all registers.
+ * mips-tdep.c (mips_push_dummy_frame): Save floating point registers
+ at the right offset in the dummy frame.
+ * mipsread.c (psymtab_to_symtab_1): Do not complain for stProc,
+ stStaticProc and stEnd symbols as they are generated by gcc-2.x.
+ * mipsread.c (mipscoff_new_init): Initialize stabsread and buildsym.
+
+Fri Mar 26 15:25:05 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (TARFILES): Avoid trailing backslash.
+
+Fri Mar 26 11:29:30 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.{c,h}: Add exp_string to struct breakpoint and use
+ it in breakpoint_re_set.
+ * breakpoint.c (watch_command, enable_breakpoint): Fetch lazy values.
+
+ * rs6000-tdep.c (single_step): Misc cleanups (CORE_ADDR not int,
+ don't use sizeof(int) for target stuff, etc).
+
+Thu Mar 25 15:03:53 1993 Fred Fish (fnf@cygnus.com)
+
+ * alldeps.mak, configure.in, i860-break.h, i860-opcode.h,
+ i860-pinsn.c, i860-tdep.c, config/i860/*: Remove incomplete i860
+ support that can't be integrated anyway due to lack of clear
+ authorship.
+
+Thu Mar 25 12:26:50 1993 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (read_register, write_register): Make these capable
+ of reading/writing registers that are shorter than REGISTER_TYPE.
+ * (value_from_register): Install H8500 specific code to return
+ proper value when register is being used as a pointer.
+ * h8500-tdep.c: Remove extra defines of NUM_REGS.
+ (h8500_skip_prologue): Use correct lengths for LINK instructions.
+ (FRAME_CHAIN): Change name to h8500_frame_chain. Rewrite code to
+ chain frames properly by combining frame pointer with T reg.
+ (init_extra_frame_info): Delete. It's now a macro.
+ (frame_args_address): Don't add PTR_SIZE. Stack args are already
+ offset by the correct amount off of the frame pointer.
+ (register_byte): Delete. It's now a macro.
+ (register_raw_size, register_virtual_size): Delete. Replaced by
+ common routine h8500_register_size, cuz there's no difference
+ between the raw & virtual sizes on this machine.
+ (register_convert_to_raw, register_convert_to_virtual): Delete,
+ cuz there's no difference between the raw & virtual forms.
+ Replaced by memcpy in tm file.
+ (register_virtual_type): Rename to h8500_register_virtual_type.
+ Get rid of pointer pseudo-regs, use _REGNUM with all reg names.
+ (_initialize_h8500_tdep): Get rid of crock to ensure that GDB &
+ emulator have same reg offsets. This is all handled in the
+ simulator code now.
+ (h8500_trapped_internalvar): New routine to detect references to
+ convenience vars acting as pointer pseudo-regs.
+ (h8500_value_trapped_internalvar): Conjure up value of pointer
+ pseudo-regs.
+ (h8500_set_trapped_internalvar): Convert set value in real
+ register references.
+ infcmd.c (read_pc, write_pc): Add h8500 specific code to handle
+ code segment register.
+ infrun.c (proceed): Simplify. Call write_pc instead of doing it
+ by hand.
+ (wait_for_inferior): Add h8500 specific code to add stack segment
+ when reading SP register.
+ remote-sim.c (fetch_register): Spacing.
+ tm-h8500.h: #define GDB_TARGET_IS_H8500 to make it easier to
+ detect cruft. Redo all register manipulation stuff. Get rid of
+ pointer pseudo-regs. (INIT_EXTRA_FRAME_INFO): Adds stack segment
+ to frame pointer. (IS_TRAPPED_INTERNALVAL,
+ VALUE_OF_TRAPPED_INTERNALVAR, SET_TRAPPED_INTERNALVAR): Use these
+ to create internal vars for pointer pseudo-regs.
+
+Thu Mar 25 10:10:28 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in: Numerous small changes to macro definitions
+ and rules for building gdb distribution tree. Many macros
+ eliminated or merged, and rules simplified.
+ * alldeps.mak: Update.
+ * depend: Update.
+
+Wed Mar 24 13:52:29 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: recurse through SUBDIRS for dvi target too
+
+Wed Mar 24 08:48:30 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Clean up xcoff relocation.
+ objfiles.h (struct objfiles): Add section_offsets, num_sections.
+ symfile.c (syms_from_objfile), xcoffread.c (xcoff_symfile_offsets):
+ Set them.
+ symtab.h (struct general_symbol_info): Add section field.
+ minsyms.c (prim_record_minimal_symbol{,_and_info}): Set it.
+ xcoffread.c: Set section for symbols and msymbols.
+ (struct symtab): Add block_line_section field.
+ buildsym.c (end_symtab): Set it.
+ (end_symtab and callers): Add section parameter.
+ objfiles.c (objfile_relocate): New funciton.
+ xcoffexec.c (vmap_symtab): Use it.
+ xcoffsolib.h (struct vmap): Remove unused fields.
+ config/rs6000/tm-rs6000.h, stack.c, xcoffexec.c: Remove
+ CORE_NEEDS_RELOCATION, symtab_relocated.
+ config/rs6000/tm-rs6000.h: Remove use of loadinfotext.
+ rs6000-tdep.c: Make loadinfotext static.
+ breakpoint.c (fixup_breakpoints): Doc fix.
+ symtab.h (struct symtab), config/rs6000/tm-rs6000.h, buildsym.c
+ (end_symtab): primary field replaces nonreloc.
+
+Tue Mar 23 00:10:53 1993 John Gilmore (gnu@cygnus.com)
+
+ * symtab.h (struct linetable_entry): Remove confusing comment.
+
+Tue Mar 23 00:01:23 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: add installcheck target
+
+Mon Mar 22 16:17:58 1993 Fred Fish (fnf@cygnus.com)
+
+ * config/{a29k, arm, convex, gould, h8300, i386, i860, i960, m68k,
+ m88k, mips, none, ns32k, pa, pyr, romp, rs6000, sparc, tahoe, vax,
+ z8k}: New directories to hold cpu specific configuration files.
+ Naming follows gcc convention.
+ * config/{*.mt, *.mh}: All target and host makefile fragment
+ config files moved to an appropriate config/<cpu> subdirectory.
+ * nm-*, xm-*, tm-*: All native, host, and target files, which
+ get linked to nm.h, xm.h, and tm.h respectively by configure,
+ moved to appropriate config/<cpu> subdirectory.
+ * nm-sysv4.h, xm-sysv4.h, tm-sysv4.h, tm-sunos.h, nm-trash.h:
+ Native, host, and target files that are common across more than
+ one cpu architecture and included by one of the configured
+ native, host, or target files, get moved to config directory.
+ * Makefile.in (INCLUDE_CFLAGS): Add -I${srcdir}/config to
+ pick up native, host, or target include files moved to one of
+ the config subdirectories, and that are included by other files.
+ * Makefile.in (alldeps.mak): Modify to account for new config
+ directory structure.
+ * alldeps.mak, depend: Update for new config directory structure.
+ * config/*/[ntx]m-*.h: Modify all files that include other
+ [ntx]m-*.h files to use path relative to gdb/config. I.E.
+ "a29k/tm-ultra3.h" includes "a29k/tm-29k.h" rather than just
+ "tm-29k.h".
+ * remote-eb.c (tm-29k.h): Include a29k/tm-29k.h.
+ * mipsread.c (tm-mips.h): Include mips/tm-mips.h.
+ * i860-pinsn.c (tm-i860.h): Include i860/tm-i860.h.
+ * configure.in: Default gdb_host_cpu to host_cpu, and remap
+ the ones where the default is not unique or different than the
+ config subdirectory name. Similarly, handle gdb_target_cpu.
+ Modify configure.in as appropriate to make use of gdb_host_cpu
+ and gdb_target_cpu to find makefile fragments and make links.
+
+Mon Mar 22 12:36:24 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (compare_blocks): Sort blocks with the same start
+ address by decreasing ending address.
+
+Mon Mar 22 20:36:04 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mipsread.c (parse_procedure): Save cur_fdr accross call to
+ lookup_symbol as it might get clobbered by the call.
+
+ * mipsread.c (parse_partial_symbols): Use ADD_PSYMBOL_ADDR_TO_LIST.
+ The previous code did not initialize the language field for the psymtab
+ entry.
+
+Sat Mar 20 00:33:39 1993 John Gilmore (gnu@cygnus.com)
+
+ * c-exp.y (parse_number): Avoid shift warning.
+ * serial.h (struct ttystate): Declare empty one on DOS.
+
+Fri Mar 19 12:59:50 1993 Stu Grossman (grossman@cygnus.com)
+
+ * xm-sun4os4.h: Return type of free() should be void, not int.
+
+ * vx-share/vxWorks.h: Remove #def of NULL.
+
+Fri Mar 19 11:28:18 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * tm-rs6000.h: Nuke no-op STAB_REG_TO_REGNUM.
+
+Fri Mar 19 07:40:09 1993 Steve Chamberlain (sac@cygnus.com)
+
+ * z8k-tdep.c (print_insn): Include the new dis-asm header file.
+
+Thu Mar 18 14:26:57 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * ieee-float.c: Moved to ../libiberty.
+ * ieee-float.h: Moved to ../include.
+ * Makefile.in: Update accordingly.
+ * i386-pinsn.c (print_insn), m68k-pinsn.c (print_insn):
+ Convert to stubs that call disassemblers in ../opcodes/*-dis.c.
+ * m68k-tdep.c: Removed definition of ext_format ext_format_68881;
+ it is now in ../opcodes/m68881-ext.c.
+ * mips-tdep.c (mips_skip_prologue): Try to skip more of the
+ prologue (some callers _do_ care).
+ * mips-pinsn.c (print_insn), z8k-tdep.c (print_insn): Convert to
+ new interface of ../opcodes/*-dis.c.
+ * ch-exp.y: Add #include <ctype.h>.
+
+Thu Mar 18 11:57:49 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffexec.c (exec_close): Don't close exec_bfd twice.
+
+ * xcoffread.c (enter_line_range): endaddr is exclusive, not inclusive.
+
+Wed Mar 17 09:46:31 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (arrange_linetable): Use x{m,re}alloc not {m,re}alloc.
+
+Wed Mar 17 11:28:11 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * z8k-tdep.c (extract_return_value, write_return_value,
+ store_struct_return): New functions from macros in tm-z8k.h.
+
+Wed Mar 17 11:23:06 1993 Fred Fish (fnf@cygnus.com)
+
+ * valops.c (value_arg_coerce): Apply temporary patch to
+ fix problem with coercion of array and function types when
+ passed as arguments to C functions, pending a more complete
+ review of when and how coercion should be done, depending
+ upon context and language.
+
+Wed Mar 17 09:46:31 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (MIN_TBTABSIZ): Change to 12.
+
+ * xcoffread.c (xcoff_symfile_read): Only read stringtab and
+ debugsec if there are a non-zero number of symbols.
+
+Tue Mar 16 18:08:45 1993 John Gilmore (gnu@cygnus.com)
+
+ * command.c (show_user): Avoid fprintf_filtered botch (AGAIN!).
+
+Tue Mar 16 15:18:17 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffexec.c (add_vmap): Wrap symbol read in catch_errors.
+
+ * xcoffread.c (read_symbol_lineno): Look to end of symbols for .bf,
+ not just 50 symbols.
+ (symtbl_num_syms): New variable.
+ (read_xcoff_symtab): Set it.
+ (read_symbol_nvalue): Check for bad symno.
+ (read_symbol_{lineno,nvalue}, callers): Don't pass symtable; it's
+ always symtbl.
+
+Tue Mar 16 10:09:05 1993 Stu Grossman (grossman@cygnus.com)
+
+ * config/rs6000.mh: Get rid of -Dfd_set=int crock.
+ This is defined in defs.h if necessary.
+ * vx-share/vxWorks.h: Remove #defs of min and max.
+ * vx-share/xdr_ld.c, vx-share/xdr_ptrace.c,
+ vx-share/xdr_rdb.c: include defs.h.
+
+Fri Mar 12 09:33:23 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (retrieve_tracebackinfo): Move assignment out
+ of while condition.
+
+ * xcoffread.c (enter_line_range): complain() on bad endoffset.
+ xcoffread.c: Doc fixes.
+
+Tue Mar 9 09:56:12 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * tm-rs6000.h (CORE_NEEDS_RELOCATION): Just call xcoff_relocate_core.
+ xcoffexec.c (xcoff_relocate_core): New function.
+ (text_adjustment): Removed.
+ (add_vmap): Return the vmap.
+ rs6000-tdep.c (add_text_to_loadinfo): No longer static.
+
+Fri Mar 5 05:22:46 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffsolib.h: Add objfile member to struct vmap.
+ xcoff{exec,solib}.c: Use it, not lookup_objfile_bfd.
+ xcoffexec.c (add_vmap): Allocate objfiles here.
+
+Sun Mar 14 02:54:15 1993 John Gilmore (gnu@cygnus.com)
+
+ Support 68000 series without floating point.
+
+ * configure.in (m68000-*-{aout,elf,coff}): New configs.
+ * tm-68k-nofp.h: New file, lacks 68881 support.
+ * config/m68k-nofp.mt: New file.
+
+Sun Mar 14 02:30:08 1993 John Gilmore (gnu@cygnus.com)
+
+ Remove a few remaining underscore/no-underscore remnants from
+ config files.
+
+ * config/{m68k-un.mt, sparc-un.mt}: Remove.
+ * config/m68k-noun.mt: Rename to m68k-fp.mt.
+ * config/sparc-noun.mt: Rename to sparc-em.mt.
+ * tm-68k-noun.h, tm-spc-noun.h: Remove.
+ * tm-68k-un.h: Rename to tm-68k-fp.h.
+ * tm-spc-un.h: Rename to tm-spc-em.h.
+ * tm-sun4sol2.h: Cleanup.
+ * configure.in (m68k-*, sparc-* targets): Corresponding changes.
+
+Sat Mar 13 14:58:22 1993 John Gilmore (gnu@cygnus.com)
+
+ * symmisc.c (std_in, std_out, std_err): Move initializations
+ to runtime code, in case they aren't constant.
+
+Fri Mar 12 16:23:54 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * symtab.c (find_pc_symtab): some object file formats, notably
+ mips, have holes in the address ranges of symtabs. Change
+ this algorithm from first hit to tightest fit.
+
+ * mips-tdep.c (heuristic_proc_start): if we walk the pc into the
+ fence post without finding the enclosing function, then print a
+ warning.
+
+Thu Mar 11 09:33:01 1993 Fred Fish (fnf@cygnus.com)
+
+ * utils.c (fputs_demangled, fprint_symbol): Remove.
+ * utils.c (fprintf_symbol_filtered): New function which combines
+ the functionality of fputs_demangled and fprint_symbol. Uses a
+ caller provided language parameter to select the appropriate
+ demangler, and caller provided args to pass to the demangler.
+ * defs.h (enum language): Move further up in file so enum can
+ be used in prototypes.
+ * defs.h (fputs_demangled, fprint_symbol): Remove prototypes.
+ * defs.h (fprintf_symbol_filtered): Add prototype.
+ * c-typeprint.c (cp_type_print_method_args): Replace calls to
+ fputs_demangled with call to fprintf_symbol_filtered.
+ * cp-valprint.c (demangle.h): Include
+ * cp-valprint.c (cp_print_value_fields): Replace calls to
+ fprint_symbol with calls to fprintf_symbol_filtered.
+ * printcmd.c (print_frame_args): Replace call to fprint_symbol
+ with call to fprintf_symbol_filtered.
+ * stack.c (print_frame_info): Remove obsolete code so we don't
+ have to update fputs_demangled usage in it.
+ * stack.c (print_frame_info, frame_info): Add language variable
+ to pass to fprintf_symbol_demangled and initialize it from the
+ symbol's language. Replace calls to fputs_demangled with calls
+ to fprintf_symbol_filtered.
+ * symtab.c (find_methods): Replace call to fputs_demangled with
+ call to fprintf_symbol_filtered.
+ * ch-valprint.c (demangle.h): Include.
+ * ch-valprint.c (chill_print_value_fields): Replace call to
+ fprint_symbol with call to new fprintf_symbol_filtered.
+
+Wed Mar 10 17:37:11 1993 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump version to 4.8.2.
+
+ * main.c (source_command): Require an explicit pathname of file
+ to source, since previous behavior of defaulting to gdb init file
+ was troublesome and undocumented.
+ * printcmd.c (disassemble_command): Add missing '{}' pair to
+ else with two statements. Bug reported by Stephane Tsacas
+ <slt@isoft.fr>.
+ * symtab.c (find_pc_line): Don't complain about zero length or
+ negative length line numbers for the moment, since we may not own
+ the terminal when called, such as when single stepping. (FIXME)
+ * language.h (CAST_IS_CONVERSION): True if current language is
+ C++ as well as C. Fix from Peter Schauer.
+ * environ.c (get_in_environ, set_in_environ, unset_in_environ):
+ Use STREQN macro rather than bare '!strncmp()'.
+ * environ.c (unset_in_environ): Avoid use of memcpy on
+ overlapping memory regions, as suggested by Paul Eggert
+ <eggert@twinsun.com>.
+ * c-exp.y (%union struct): Remove unused ulval as suggested
+ by Paul Eggert <eggert@twinsun.com>.
+
+Mon Mar 8 19:03:06 1993 Fred Fish (fnf@cygnus.com)
+
+ * main.c (gdbinit): Make static.
+ * main.c (inhibit_gdbinit): Move to file scope.
+ * main.c (main): Remove local inhibit_gdbinit.
+ * main.c (source_command): Don't source '.gdbinit' file by
+ default if gdb has been told to ignore it.
+
+Sun Mar 7 21:58:53 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (MAKEOVERRIDES): Define to be empty for GNU Make
+ 3.63.
+
+Fri Mar 5 17:39:45 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * printcmd.c (print_address_symbolic): Only print if offset
+ is shorter than max_symbolic_offset.
+ (initialize_printcmd): `set print max-symbolic-offset'.
+
+ * am29k-tdep.c (TAGWORD_ZERO_MASK): New #define.
+ (examine_tag): Use it.
+ (read_register_stack): Only look in the local registers for a
+ memory address if it's between rfb and rsp; go to memory otherwise.
+ (initialize_29k): Fix call_scratch_address doc. Remove reginv_com.
+ (reginv_com): Remove ancient kludge command.
+
+Fri Mar 5 17:16:26 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * tm-irix3.h (ZERO_REGNUM): copy this macro from tm-mips.h so that
+ irix4 will again compile.
+
+ * tm-mips.h (GDB_TARGET_IS_MIPS): no longer used, now removed.
+
+ * configure.in: accept mips-sgi-irix4* for irix4.
+
+Fri Mar 5 07:49:48 1993 Steve Chamberlain (sac@lisa.cygnus.com)
+
+ * z8k-tdep.c (print_register_hook): Lint.
+
+Thu Mar 4 17:42:03 1993 John Gilmore (gnu@cygnus.com)
+
+ Lint fixes from Paul Eggert (eggert@twinsun.com):
+
+ * command.c (do_setshow_command): var_uintegers are unsigned.
+ * sparc-tdep.c (save_insn_opcodes, restore_insn_opcodes):
+ unsigned, since they use hex values with the high bit set.
+
+Thu Mar 4 08:22:55 1993 Fred Fish (fnf@cygnus.com)
+
+ Fixes submitted by Karl Berry (karl@nermal.hq.ileaf.com):
+ * m88k-pinsn.c (sprint_address): Use SYMBOL_NAME macro to
+ access symbol name.
+ * m88k-nat-c (SXIP_OFFSET, SNIP_OFFSET, SFIP_OFFSET): Enclose
+ macro definitions in parenthesis.
+
+ * dbxread.c (dbx_symfile_init): Catch the case where there is
+ no string table, but the only way we find out is by reading zero
+ bytes from EOF.
+
+Wed Mar 3 15:51:28 1993 Fred Fish (fnf@cygnus.com)
+
+ * dbxread.c (dbx_symfile_init): Make size of the string table
+ size field a define (DBX_STRINGTAB_SIZE_SIZE). Ensure that the
+ offset to the string table is nonzero and handle the nonexistant
+ string table case, should it occur. Ensure that the string table
+ size read from the file is reasonable, with a minimum lower bound
+ of DBX_STRINGTAB_SIZE_SIZE instead of zero.
+
+Wed Mar 3 07:23:03 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: Changes to build testsuite correctly.
+ (FLAGS_TO_PASS): Added CXX and CXXFLAGS.
+ (CC_FOR_TARGET, CXX, CXX_FOR_TARGET): New variables.
+ (TARGET_FLAGS_TO_PASS): New variable.
+ (SUBDIRS): Added testsuite.
+ (all): Build testsuite using TARGET_FLAGS_TO_PASS, so that
+ testsuite is compiled with CC_FOR_TARGET rather than CC.
+
+Tue Mar 2 17:57:56 1993 Fred Fish (fnf@cygnus.com)
+
+ * dbxread.c (dbx_symfile_init): Fix for nonexistant string table,
+ reported by mycroft@gnu.ai.mit.edu.
+
+ (Ultrix 2.2 support from Michael Rendell <michael@mercury.cs.mun.ca>)
+ * configure.in (vax-*-ultrix2*): New triplet.
+ * config/vaxult2.mh: New file.
+ * xm-vaxult2.h: New file.
+
+ * c-exp.y (parse_number): Change high_bit to unsigned.
+ * demangle.c: Change all references to cfront to ARM, since the
+ actual algorithm is the one specified in the Annotated Reference
+ Manual. This was confusing users into thinking that full cfront
+ support was implemented.
+ * dwarfread.c (CFRONT_PRODUCER): Remove, was never really used.
+ * eval.c (evaluate_subexp): For STRUCTOP_PTR pass the arg type
+ directly to lookup_struct_elt_type, which will do the
+ dereferencing itself.
+ * gdbtypes.c (lookup_struct_elt_type): Expand comments. Fix
+ NULL dereferencing bug for unnamed structs, comment out
+ questionable code.
+
+Mon Mar 1 17:54:41 1993 John Gilmore (gnu@cygnus.com)
+
+ * coffread.c (process_coff_symbol): Change PCC argument correction
+ so that it only happens on big-endian targets; so that it only
+ happens if the short or char argument is aligned on an int
+ boundary; and so that it changes the location, rather than the
+ type, of the argument. These changes tend to parallel similar
+ (old) changes in stabsread.c.
+
+ * coffread.c (coff_read_enum_type): Use the specified size for
+ enums, don't assume that they are int-sized.
+
+ * c-valprint.c (c_val_print): Don't assume enums are the same as
+ ints.
+
+ * coredep.c: Handle NO_PTRACE_H in coredep.c. Fix by Michael
+ Rendell, <michael@mercury.cs.mun.ca>.
+
+Mon Mar 1 09:25:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * language.h (local_decimal_format_custom): Add prototype.
+ * language.c (local_decimal_format_custom): Add function, bug
+ reported by Robert R. Henry (rrh@tera.com).
+
+Fri Feb 26 18:33:18 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * xcoffexec.c (vmap_ldinfo): Fix "/" for '/' typo, reported
+ by Josef Leherbauer, joe@takeFive.co.at.
+
+Wed Feb 24 19:17:11 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * symfile.c (syms_from_objfile), tm-29k.h, tm-3b1.h, tm-68k-un.h,
+ tm-altos.h, tm-arm.h, tm-convex.h, tm-es1800.h, tm-h8300.h,
+ tm-hp300bsd.h, tm-hp300hpux.h, tm-hppa.h, tm-i386bsd.h,
+ tm-i386v.h, tm-i960.h, tm-irix3.h, tm-isi.h, tm-linux.h,
+ tm-m88k.h, tm-merlin.h, tm-mips.h, tm-news.h, tm-np1.h, tm-pn.h,
+ tm-pyr.h, tm-rs6000.h, tm-spc-un.h, tm-sun386.h, tm-sunos.h,
+ tm-symmetry.h, tm-sysv4.h, tm-tahoe.h, tm-umax.h, tm-vax.h,
+ tm-vx68.h, tm-z8k.h: Remove remnants of NAMES_HAVE_UNDERSCORE.
+
+Wed Feb 24 07:41:15 1993 Fred Fish (fnf@cygnus.com)
+
+ * symtab.h (SYMBOL_INIT_DEMANGLED_NAME): Initialize contents
+ of demangled name fields to NULL if no demangling exists for
+ a symbol. SYMBOL_INIT_LANGUAGE_SPECIFIC does this for new
+ symbols if their language is known at the time they are created,
+ but sometimes the language is not known until later.
+
+ * ch-typeprint.c (chill_print_type_base): Name changed to
+ chill_type_print_base to match pattern for C and C++ names.
+ * ch-typeprint.c (chill_print_type): Change "char" to "CHAR"
+ to be consistent with other usages.
+ * ch-typeprint.c (chill_type_print_base): Add support for
+ printing Chill STRUCT types.
+ * ch-valprint.c: Include values.h.
+ * ch-valprint.c (chill_print_value_fields): New function and
+ prototype for printing Chill STRUCT values.
+ * ch-valprint.c (chill_val_print): Fix call to val_print_string
+ that was being called with two args instead of three.
+ * ch-valprint.c (chill_val_print): Call chill_print_value_fields
+ to print Chill STRUCT values.
+
+Tue Feb 23 18:58:11 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * configure.in: added testsuite to configdirs.
+
+Tue Feb 23 11:46:11 1993 Mike Stump (mrs@cygnus.com)
+
+ * doc/stabs.texi: The `this' pointer is now known by the name
+ `this' instead of `$t'.
+
+Tue Feb 23 11:21:33 1993 Fred Fish (fnf@cygnus.com)
+
+ * dwarfread.c (read_tag_string_type): Rewrite to allow forward
+ references of TAG_string_type DIEs in user defined types.
+ * ch-lang.c (chill_create_fundamental_type): Track compiler
+ change that now emits debugging info with the type long for Chill
+ longs.
+
+Mon Feb 22 15:21:54 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * remote-mips.c: New file; implements MIPS remote debugging
+ protocol.
+ * config/idt.mt: New file; uses remote-mips.c
+ * configure.in (mips-idt-ecoff): New target; uses idt.mt.
+
+ * mips-tdep.c (mips_fpu): New variable; controls use of MIPS
+ floating point coprocessor.
+ (mips_push_dummy_frame): If not mips_fpu, don't save floating
+ point registers.
+ (mips_pop_frame): If not mips_fpu, don't restore floating point
+ registers.
+ (_initialize_mips_tdep): New function; let the user reset mips_fpu
+ variable.
+ * tm-mips.h (EXTRACT_RETURN_VALUE, STORE_RETURN_VALUE): If not
+ mips_fpu, don't use fp0 as floating point return register.
+ (FIX_CALL_DUMMY): If not mips_fpu, don't save floating point
+ registers.
+
+Mon Feb 22 07:54:03 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * gdb/testsuite: made modifications to testcases, etc., to allow
+ them to work properly given the reorganization of deja-gnu and the
+ relocation of the testcases from deja-gnu to a "tool" subdirectory.
+
+Sun Feb 21 10:55:55 1993 Mike Werner (mtw@poseidon.cygnus.com)
+
+ * gdb/testsuite: Initial creation of gdb/testsuite.
+ Migrated dejagnu testcases and support files for testing nm to
+ gdb/testsuite from deja-gnu. These files were moved "as is"
+ with no modifications. This migration is part of a major overhaul
+ of dejagnu. The modifications to these testcases, etc., which
+ will allow them to work with the new version of dejagnu will be
+ made in a future update.
+
+Fri Feb 19 18:36:55 1993 John Gilmore (gnu@cygnus.com)
+
+ * NEWS: Add reminders for next release.
+
+Fri Feb 19 10:01:39 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (parse_lines): Correct check for files compiled with
+ -g1.
+
+Fri Feb 19 05:56:15 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): 4.8.1 to distinguish local versions.
+
+Fri Feb 19 01:32:58 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): GDB-4.8 release!
+ * README, NEWS: Update for release.
+
+Thu Feb 18 22:44:40 1993 Stu Grossman (grossman@cygnus.com)
+
+ * am29k-pinsn.c (print_insn): Minor nits with const.
+ * am29k-tdep.c: More minor nits with arg types for
+ supply_register, NULL vs. 0, read_register_gen, & reginv_com.
+
+Thu Feb 18 22:38:03 1993 John Gilmore (gnu@cygnus.com)
+
+ * gcc.patch: Update for a different GCC (G++) bug.
+ * main.c (print_gdb_version): Update copyright year to 1993.
+ * nm-hp300bsd.h: Decide whether this is BSD 4.3 or 4.4,
+ conditionalize this file on it. FIXME, right way is to split
+ these into two config files.
+ (ATTACH_DETACH): Define for BSD 4.4
+ (PTRACE_ARG_TYPE): caddr_t for BSD 4.4, unset for 4.3.
+ (U_REGS_OFFSET): Revise for 4.4.
+ (REGISTER_U_ADDR): Separate for 4.4, but it doesn't work yet.
+ * xm-hp300bsd.h: Move definitions of UINT_MAX, INT_MAX, INT_MIN,
+ LONG_MAX into this file to avoid cpp "redefinition" warnings.
+
+Thu Feb 18 16:13:28 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * nm-hp300bsd.h (PTRACE_ARG3_TYPE): FSF's hp300's have int* not
+ caddr_t.
+
+Thu Feb 18 04:10:06 1993 John Gilmore (gnu@cygnus.com)
+
+ * c-lang.c (c_printstr): Bugfix for length==0 case.
+
+ * c-lang.c (c_printstr): If a C string ends in a null, don't
+ print the null.
+
+Thu Feb 18 02:39:21 1993 Stu Grossman (grossman at cygnus.com)
+
+ * defs.h (STRCMP): Make it work for unsigned chars.
+
+Thu Feb 18 01:56:06 1993 John Gilmore (gnu@cygnus.com)
+
+ * nm-hp300bsd.h (ATTACH_DETACH, PTRACE_ATTACH, PTRACE_DETACH): define.
+ * config/hp300bsd.mh (REGEX, REGEX1): Define.
+ * m68k-pinsn.c (BREAK_UP_BIG_DECL, AND_OTHER_PART): #if __GNUC__,
+ define to kludge the large opcode table into two smaller tables,
+ since GCC take exponential space to build the table. Lint.
+ (NOPCODES): Remove, use "numopcodes" from opcode/m68k.h instead.
+
+Wed Feb 17 19:24:40 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.7.9.
+ * xm-hp300bsd.h: Define PSIGNAL_IN_SIGNAL_H and put a compatible
+ definition here, to handle both BSD 4.3 and 4.4 systems.
+ * mipsread.c (ZMAGIC): #undef to avoid duplicate define.
+ * remote.c (alarm): Move declaration to global level, before
+ first reference to it.
+ * tm-i386bsd.h (NUM_REGS): There are only eleven, not twelve.
+ * dbxread.c (process_one_symbol): Cast to unsigned char, not int.
+
+Wed Feb 17 13:40:29 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * remote.c (readchar): forward declare alarm which otherwise looks
+ like an undeclared variable to gcc.
+
+ * dbxread.c (process_one_symbol): cast enum value N_SO into int
+ when comparing against an int. Avoids superfluous warning from
+ vax ultrix 4.2 cc.
+
+ * inflow.c (set_sigint_trap): add cast to assignment from signal.
+ Avoids superfluous warnings from some systems and/or compilers
+ (like vax ultrix 4.2.)
+
+ * language.c (struct op_print unk_op_print_tab): use the enum
+ values rather naked zeros as initializers. Avoids warnings from
+ ultrix type compilers.
+
+Tue Feb 16 00:53:20 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.7.6.
+ (SFILES_SUBDIR): Add 29k-share/udi_soc.
+ (SFILES_SUBSUBDIR): Move 29k-share/udi files to this macro.
+ (alldeps.mak): Make ALLDEPFILES_SUBSUBDIR for files in sub sub dirs.
+ (ALLDEPFILES_SUBSUBDIR): Depend on this for deeper dep files.
+ (HFILES): Remove all nm-* except nm-trash.h. Add ns32k-opcode.h.
+ (depend): Fix bug where nm-files in config files weren't noticed.
+ (make-proto-gdb-1): Avoid changing directories while building new
+ prototype. Build SFILES_SUBSUBDIR with longer symlinks.
+
+Mon Feb 15 20:48:09 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote.c: Improve error recovery. Allow user to break out
+ of initial connection attempt with INTERRUPT. Treat a timeout
+ while waiting for remote packet like a retry, unless the remote
+ side is actively running user code. Fix a few long printf_filtered's.
+
+ * xcoffread.c (read_xcoff_symtab): Don't use null symbol name for
+ trampoline symbols.
+
+ * buildsym.c (start_subfile): Allow null file name.
+
+Fri Feb 12 15:46:49 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * xcoffread.c (process_xcoff_symbol, read_symbol_lineno): complain
+ expects a pointer to complaint rather than a complaint
+ structure.
+ (process_linenos): free the previously allocated subfile name,
+ then allocate the new one from the heap.
+
+Fri Feb 12 08:06:05 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * h8300-tdep.c, tm-h8300.h: turn off some experimental features
+
+Thu Feb 11 00:59:07 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabsread.c (dbx_lookup_type): Handle negative type numbers.
+ Previously, would bogusly index off the bottom of type_vector.
+ (rs6000_builtin_type): Accept type number as argument.
+ (read_type, case '-'): Handle negatives like any other type number.
+
+ * symfile.c (deduce_language_from_filename): Handle null name.
+
+ * mips-tdep.c (isa_NAN): Fix byte order dependency.
+ Reported by Nobuyuki Hikichi <hikichi@sra.co.jp>,
+ fixed by sato@sm.sony.co.jp.
+
+ * xcoffread.c (parmsym): Don't use an initializer to set up
+ this struct symbol. Set it up in initialize_xcoffread.
+ (read_xcoff_symtab, xcoff_symfile_read): Surround code that only
+ works on real rs/6000 target with #ifndef FAKING_RS6000.
+
+Wed Feb 10 23:42:37 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabsread.c (rs6000_builtin_type): Move function from
+ xcoffread.c:builtin_type.
+ * xcoffread.c (builtin_type): Move to stabsread. Remove
+ IBM6000_HOST dependency. Move misplaced comments.
+ (various): Change printf's to complaints.
+ (patch_block_stabs, process_xcoff_symbol case C_DECL): Add
+ objfile argument to read_type calls under #if 0.
+ (process_xcoff_symbol case C_RSYM): Fix typo in #ifdef.
+ * xcoffexec.c (map_vmap): Don't allocate an objfile for the exec_file.
+ * Makefile.in: xcoffread.o is not built by default.
+ * xm-rs6000.h (IBM6000_HOST): Remove.
+ * config/rs6000.mh (NATDEPFILES): xcoffread.o is native only.
+ * doc/gdbint.texinfo: Eliminate IBM6000_HOST, document
+ IBM6000_TARGET.
+
+Wed Feb 10 18:31:20 1993 Stu Grossman (grossman at cygnus.com)
+
+ * findvar.c (read_var_value): If REG_STRUCT_HAS_ADDR, then set
+ VALUE_LVAL to be lval_memory so that we don't try to modify wild
+ register numbers when user tries to modify elements in structs
+ passed as arguments.
+ * inflow.c (child_terminal_info): Move banner outside of system
+ specific #ifdefs.
+ * tm-hppa.h (REG_STRUCT_HAS_ADDR): Define this for HPPA, which
+ passes struct/union arguments by address.
+
+Wed Feb 10 15:34:46 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Based on patch from Kean Johnston <maw@netcom.com>:
+ * nm-i386sco4.h: New file. Like nm-i386sco.h, but define
+ ATTACH_DETACH, PTRACE_ATTACH and PTRACE_DETACH.
+ * config/i386sco4.mh (NAT_FILE): Use nm-i386sco4.h.
+
+Tue Feb 9 20:07:18 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote-udi.c (FREEZE_MODE): Fix && for & typo. Found and
+ fixed by Lynn D. Shumaker, shumaker@saifr00.cfsat.honeywell.com.
+
+Tue Feb 9 08:18:07 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * config/i386sco4.mh (MUNCH_DEFINE): Pass -p to nm to avoid bug in
+ cc debugging output.
+
+Tue Feb 9 00:19:28 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabsread.c (define_symbol): Complain about unrecognized names
+ that begin with CPLUS_MARKER (often '$'), but don't die. Fix
+ suggested by gb@cs.purdue.edu (Gerald Baumgartner).
+ (read_cpp_abbrev): Don't use the class name as part of the
+ vtable pointer member name (_vptr$) in $vf abbrevs or unrecognized
+ abbrevs. Inspired by Mike Tiemann.
+ (read_tilde_fields): Comment. Remove ancient dead code.
+ Remove erroneous but non-dead code. Simplify. Add complaints.
+ (in general): Remove extraneous (parentheses) in return
+ statements.
+
+Fri Feb 5 14:01:22 1993 John Gilmore (gnu@cygnus.com)
+
+ * coffread.c (coff_lookup_type): Fix fencepost error reported
+ by Art Berggreen, <arg@opal.acc.com>.
+
+ Fix long file name bug reported on SCO Open Desktop 2.0 by Ulf Lunde
+ <Ulf.Lunde@kvatro.no> and Dag H. Wanvik <Dag.H.Wanvik@kvatro.no>:
+
+ * coffread.c (getfilename): Eliminate COFF_NO_LONG_FILE_NAMES
+ test, which is apparently left over from when we used native
+ include files and couldn't depend on the member names being there.
+ * tm-3b1.h, tm-altos.h, tm-i386v.h: Don't set it.
+
+Thu Feb 4 12:23:15 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c: Major overhaul to use new BFD symbol table reading
+ routines. Now swaps information as it is needed, rather than
+ swapping everything when the file is read.
+
+Thu Feb 4 01:52:36 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (TARDIRS): Add sparclite demo dir.
+ (*.tab.c): Change dependency on Makefile to depend on
+ Makefile.in, otherwise it always rebuilds after configuring.
+ Force output *.tab.c file into current directory even in "make"
+ versions that rewrite dependent file names used in command lines.
+
+ * TODO: Remove some things we did.
+ * am29k-opcode.h, convx-opcode: Remove; now in ../include/opcode.
+ * os68k-xdep.c: Remove; useless file (os68k is a target only).
+ * convex-pinsn.c: Use ../include/opcode/convex.h. Add CONST.
+ * symtab.h: Eliminate unnamed unions and structs.
+
+Wed Feb 3 14:48:08 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (VERSION): Roll to 4.7.5.
+
+Tue Feb 2 20:47:42 1993 John Gilmore (gnu@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set_one): Handle watchpoints when
+ re-evaluating symbol pointers.
+
+Tue Feb 2 16:10:31 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (lcurly, rcurly): New nonterminals.
+ * c-exp.y (exp): Use lcurly and rcurly for arrays and UNOP_MEMVAL
+ constructs.
+ * parse.c (free_funcalls): Moved prototype from parser-defs.h,
+ made function static.
+ * parse.c (struct funcall): Moved struct def from parser-defs.h.
+ * parse.c (funcall_chain): Moved from parser-defs.h, made static.
+ * parse.c (start_arglist):
+ * parser-defs.h (free_funcalls): Moved prototype to parse.c.
+ * parser-defs.h (struct funcall): Moved struct def to parse.c.
+ * parser-defs.h (funcall_chain): Moved to parse.c.
+ * printcmd.c (print_frame_nameless_args): Fix prototype.
+ * tm-mips.h (setup_arbitrary_frame): Fix prototype.
+ * tm-sparc.h (setup_arbitrary_frame): Fix prototype.
+ * valops.c (typecmp): Moved prototype from values.h.
+ * value.h (typecmp): Moved prototype to valops.c, made static.
+ * ch-exp.y (yylex): Change way control sequences are disabled.
+
+Tue Feb 2 16:11:43 1993 John Gilmore (gnu@cygnus.com)
+
+ * tm-mips.h, tm-sparc.h: Fix thinko in SETUP_ARBITRARY_FRAME.
+
+Tue Feb 2 15:30:33 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (upgrade_type): Build array types correctly, using
+ create_range_type and create_array_type.
+
+Tue Feb 2 00:19:08 1993 John Gilmore (gnu@cygnus.com)
+
+ * remote-nindy.c: Cleanup.
+
+ * infrun.c (wait_for_inferior): When rolling back the PC after
+ a breakpoint, call write_pc so that NPC gets rolled back as well
+ (for the 29K).
+
+ * blockframe.c (inside_entry_file, inside_main_func,
+ inside_entry_func): PC of zero is always "bottom of stack".
+
+ * printcmd.c (print_frame_args, print_frame_nameless_args):
+ Let print_frame_nameless_args decide whether there are any,
+ laying groundwork for possibly later printing 29K args for
+ functions where we have tag words but no symbols.
+
+Mon Feb 1 18:09:58 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * Makefile.in: fix GDB doc targets for new doc subdir structure
+
+Mon Feb 1 17:56:47 1993 John Gilmore (gnu@cygnus.com)
+
+ * stack.c (parse_frame_specification): Parse as many arguments
+ as there are (up to MAXARGS). Pass all of them in argc, argv
+ format to SETUP_ARBITRARY_FRAME. Put the burden of checking how
+ many there were, onto SETUP_ARBITRARY_FRAME.
+ * tm-mips.h, tm-sparc.h: Corresponding changes.
+ * mips-tdep.c, sparc-tdep.c: Ditto.
+
+Mon Feb 1 17:19:37 1993 John Gilmore (gnu@cygnus.com)
+
+ * hp300ux-nat.c: Update copyrights.
+ * mipsread.c (parse_partial_symbols): Complain about block
+ indexes that go backwards. Fix from Peter Schauer.
+ * symfile.c (syms_from_objfile, symbol_file_add): Allow a
+ symbol-file that has no linkage symbols to be read.
+ * tm-rs6000.h, xm-rs6000.h: (SIGWINCH_HANDLER and friends): Move
+ from tm- file to xm-file, since they're host dependent.
+ * valarith.c (value_binop): Typo.
+
+Mon Feb 1 16:16:59 1993 Stu Grossman (grossman at cygnus.com)
+
+ * sparclite/aload.c: Add copyleft.
+ * sparclite/crt0.s: Add comment at beginning.
+
+Mon Feb 1 14:36:11 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * remote-z8k.c, z8k-tdep.c: support for the Z8001 and Z8002.
+ * parse.c (std_regs): Only declare if NO_STD_REGS is defined.
+
+Sun Jan 31 04:32:48 1993 Michael Tiemann (tiemann@rtl.cygnus.com)
+
+ * values.c (value_headof): Fix typo in which VTBL and ARG were
+ being confused for one another.
+
+ * valops.c (typecmp): Now static.
+
+ * gdbtypes.c (fill_in_vptr_fieldno): Don't ignore the first
+ baseclass--we don't always inherit its virtual function table
+ pointer.
+
+ * eval.c (evaluate_subexp): In OP_FUNCALL case, adjust `this'
+ pointer correctly in case value_struct_elt moves it around.
+
+ * valops.c (typecmp): Now static. Also, now groks references
+ better.
+
+ * gdbtypes.c (lookup_struct_elt_type): Pass NOERR instead of
+ zero on recursive call. If NAME is the name of TYPE, return TYPE.
+
+Sat Jan 30 19:55:52 1993 John Gilmore (gnu@cygnus.com)
+
+ * hppah-nat.c: Eliminate <sys/user.h> and other unnecessary stuff,
+ to avoid "too much defining" error from native C compiler (!).
+
+ * Makefile.in (HFILES): Add typeprint.h.
+ * typeprint.[ch]: Update copyrights.
+
+Thu Jan 28 19:09:02 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Update to match doc/ subdir changes.
+
+ * config/hp300hpux.mh: No cross-host file needed, just native.
+ * config/go32.mh: Remove nonexistent "native" support.
+
+ M88K fixes reported by Carl Greco, <cgreco@Creighton.Edu>:
+ * tm-m88k.h (REGISTER_CONVERT_TO_RAW): Fix typo.
+ * m88k-tdep.c (next_insn): Lint, cleanup.
+ (store_parm_word): Lint.
+
+ * README: Fix typo (reported by karl@hq.ileaf.com).
+
+Wed Jan 27 21:34:21 1993 Fred Fish (fnf@cygnus.com)
+
+ * expression.h (BINOP_CONCAT): Document use for self concatenation
+ an integral number of times.
+ * language.c (binop_type_check): Extend BINOP_CONCAT for self
+ concatenation case.
+ * valarith.c (value_concat): Rewrite to support self
+ concatenation an integral number of times.
+ * Makefile.in (ch-exp.tab.c): Change "expect" message.
+ * ch-exp.y (FIXME's): Make all FIXME tokens distinct, to
+ eliminate hundreds of spurious shift/reduce and reduce/reduce
+ conflicts that mask the 5 real ones.
+ * ch-exp.y (STRING, CONSTANT, SC): Remove unused tokens.
+ * ch-exp.y (integer_literal_expression): Remove production,
+ no longer used.
+
+Thu Jan 21 09:58:36 1993 Fred Fish (fnf@cygnus.com)
+
+ * eval.c (evaluate_subexp): Fix OP_ARRAY, remove code that
+ implied that "no side effects" was nonfunctional.
+ * eval.c (evaluate_subexp): Add BINOP_CONCAT case to deal with
+ character string and bitstring concatenation.
+ * expprint.c (dump_expression): Add case for BINOP_CONCAT.
+ * expression.h (exp_opcode): Add BINOP_CONCAT.
+ * gdbtypes.h (type_code): Add TYPE_CODE_BITSTRING.
+ * language.c (string_type): Add function to determine if a type
+ is a string type.
+ * language.c (binop_type_check): Add case for BINOP_CONCAT.
+ * valarith.c (value_concat): New function to concatenate two
+ values, such as character strings or bitstrings.
+ * valops.c (value_string): Remove error stub and implement
+ function body.
+ * value.h (value_concat): Add prototype.
+ * ch-exp.y (operand_3): Add actions for SLASH_SLASH (//).
+ * ch-exp.y (yylex): Recognize SLASH_SLASH.
+ * ch-lang.c (chill_op_print_tab): Add SLASH_SLASH (//) as
+ BINOP_CONCAT.
+
+Tue Jan 19 14:26:15 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (exp): Add production to support direct creation
+ of array constants using the obvious syntax.
+ * c-valprint.c (c_val_print): Set printed string length.
+ * dwarfread.c (read_tag_string_type): New prototype and
+ function that handles TAG_string_type DIEs.
+ * dwarfread.c (process_dies): Add case for TAG_string_type
+ that calls new read_tag_string_type function.
+ * expprint.c (print_subexp): Add support for OP_ARRAY.
+ * gdbtypes.c (create_range_type, create_array_type): Inherit
+ objfile from the index type.
+ * ch-typeprint.c (chill_print_type): Add case for
+ TYPE_CODE_STRING.
+ * ch-valprint.c (chill_val_print): Fix case for
+ TYPE_CODE_STRING.
+
+Mon Jan 18 11:58:45 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mipsread.c (CODE_MASK, MIPS_IS_STAB, MIPS_MARK_STAB,
+ MIPS_UNMARK_STAB, STABS_SYMBOLS): Removed; now in
+ include/coff/mips.h.
+
+Fri Jan 15 20:26:50 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-exp.y (exp:STRING): Convert C strings into array-of-char
+ constants with an explicit null byte terminator. OP_STRING is
+ now used for real string types.
+ * c-lang.c (builtin_type_*): Move declarations to lang.c since
+ they are used by all languages.
+ * c-lang.c (_initialize_c_language): Move initializations of
+ builtin_type_* to lang.c.
+ * c-typeprint.c (c_type_print_varspec_prefix,
+ c_type_print_varspec_suffix): TYPE_CODE_PASCAL_ARRAY renamed
+ to TYPE_CODE_STRING.
+ * c-valprint.c (c_val_print): Change the way character arrays
+ are printed as strings to be consistent with the way strings
+ are printed when pointer-to-char types are dereferenced.
+ Remove test of print_max before calling val_print_string, which
+ now does it's own test.
+ * eval.c (evaluate_subexp): Add case for OP_ARRAY.
+ * expprint.c (print_subexp, dump_expression): Add case for OP_ARRAY.
+ * expression.h (enum exp_opcode): Add OP_ARRAY and document.
+ * gdbtypes.c (builtin_type_*): Add declarations moved from
+ c-lang.c.
+ * gdbtypes.c (create_string_type): New function to create real
+ string types.
+ * gdbtypes.c (recursive_dump_type): TYPE_CODE_PASCAL_ARRAY
+ renamed to TYPE_CODE_STRING.
+ * gdbtypes.c (_initialize_gdbtypes): Add initializations of
+ builtin_type_* types moved from c-lang.c.
+ * gdbtypes.h (enum type_code): TYPE_CODE_PASCAL_ARRAY renamed
+ to TYPE_CODE_STRING.
+ * gdbtypes.h (builtin_type_string): Add extern declaration.
+ * gdbtypes.h (create_string_type): Add prototype.
+ * m2-lang.c (m2_create_fundamental_type): TYPE_CODE_PASCAL_ARRAY
+ renamed to TYPE_CODE_STRING.
+ * m88k-tdep.c (pushed_size): TYPE_CODE_PASCAL_ARRAY renamed to
+ TYPE_CODE_STRING.
+ * mipsread.c (_initialize_mipsread): TYPE_CODE_PASCAL_ARRAY
+ renamed to TYPE_CODE_STRING.
+ * parse.c (length_of_subexp, prefixify_subexp): Add case for
+ OP_ARRAY.
+ * printcmd.c (print_formatted): Recognize TYPE_CODE_STRING.
+ * typeprint.c (print_type_scalar): TYPE_CODE_PASCAL_ARRAY renamed
+ to TYPE_CODE_STRING.
+ * valops.c (allocate_space_in_inferior): New function and
+ prototype, using code ripped out of value_string.
+ * valops.c (value_string): Rewritten to use new function
+ allocate_space_in_inferior, but temporarily disabled until some
+ other support is in place.
+ * valops.c (value_array): New function to create array constants.
+ * valprint.c (val_print_string): Add comment to document use,
+ complete rewrite to fix several small buglets.
+ * value.h (value_array): Add prototype.
+ * value.h (val_print_string): Change prototype to match rewrite.
+ * ch-valprint.c (chill_val_print): Add case for TYPE_CODE_STRING.
+ * ch-exp.y (match_character_literal): Disable recognition of
+ control sequence form of character literals and document why.
+
+Thu Jan 14 15:48:12 1993 Stu Grossman (grossman at cygnus.com)
+
+ * nindy-share/nindy.c: Add comments to #endif's to clarify
+ grouping.
+
+ * hppa-pinsn.c (print_insn): Use read_memory_integer, instead of
+ read_memory to get byte order right.
+ * hppah-tdep.c (find_unwind_info): Don't read in unwind info
+ anymore. This is done in paread.c now. We expect unwind info
+ to hang off of objfiles, and search all of the objfiles when until
+ we find a match.
+ * (skip_trampoline_code): Cast arg to target_read_memory.
+ * objfiles.h (struct objfile): Add new field obj_private to hold
+ per object file private data (unwind info in this case).
+ * paread.c (read_unwind_info): New routine to read unwind info
+ for the objfile. This data is hung off of obj_private.
+ * tm-hppa.h: Define struct obj_unwind_info, to hold pointers to
+ the unwind info for this objfile. Also define OBJ_UNWIND_INFO to
+ make this easier to access.
+
+Wed Jan 13 20:49:59 1993 Fred Fish (fnf@cygnus.com)
+
+ * c-valprint.c (cp_print_class_member): Add extern decl.
+ * c-valprint.c (c_val_print): Extract code for printing methods
+ and move it to cp_print_class_method in cp-valprint.c.
+ * c-valprint.c (c_val_print): Extract code to print strings and
+ move it to val_print_string in valprint.c.
+ * cp-valprint.c (cp_print_class_method): New function using
+ code extracted from c_val_print.
+ * valprint.c (val_print_string): New function using code
+ extracted from c_val_print.
+ * value.h (val_print_string): Add prototype.
+ * ch-exp.y (CHARACTER_STRING_LITERAL): Set correct token type.
+ * ch-exp.y (literal): Add action for CHARACTER_STRING_LITERAL.
+ * ch-exp.y (tempbuf, tempbufsize, tempbufindex, GROWBY_MIN_SIZE,
+ CHECKBUF, growbuf_by_size): New variables, macros, and support
+ functions for implementing a dynamically expandable temp buffer.
+ * ch-exp.y (match_string_literal): New lexer function.
+ * ch-exp.y (match_bitstring_literal): Dynamic buffer code
+ removed and replaced with new CHECKBUF macro.
+ * ch-exp.y (yylex): Call match_string_literal when appropriate.
+ * ch-valprint.c (ch_val_print): Add code for TYPE_CODE_PTR.
+
+Sat Jan 9 19:59:33 1993 Stu Grossman (grossman at cygnus.com)
+
+ * Makefile.in: Add info for paread.o.
+ * config/hppahpux.mh: Add paread.o to NATDEPFILES.
+
+ * blockframe.c (frameless_look_for_prologue): Correct the
+ comment.
+ * gdbtypes.h, gdbtypes.c: Use const in decl of
+ cplus_struct_default, now that pa-gas assembler has been fixed.
+ * hppah-nat.c: Formatting.
+ * hppah-tdep.c: Remove lots of useless externs for variables we
+ don't use.
+ * (find_unwind_entry): Speed up by using binary search, and a one
+ entry cache.
+ * (rp_saved): New routine to see what unwind info says about RP
+ being saved on the stack frame.
+ * (frame_saved_pc): Look for prologue to see if we need to
+ examine the stack for the saved RP or not.
+ * (init_extra_frame_info): Check for prologue, instead of
+ framesize to determine if we are frameless or not.
+ * (frame_chain_valid): Stop backtraces when we run into _start.
+ * (push_dummy_frame): Reformat to make more readable.
+ * (find_dummy_frame_regs): ditto.
+ * (hp_pop_frame): ditto.
+ * (hp_restore_pc_queue): small cleanup.
+ * (hp_push_arguments): ditto.
+ * (pa_do_registers_info): ditto.
+ * (skip_prologue): New routine created from SKIP_PROLOGUE macro.
+ * tm-hppa.h: Move contents of SKIP_PROLOGUE into hppah-tdep.c.
+ * Define FRAME_CHAIN_VALID.
+ * Turn on BELIEVE_PCC_PROMOTION so that we can access char args
+ passed to functions.
+
+ * paread.c (pa_symtab_read): Use new bfd conventions for
+ accessing linker symbol table.
+ * (pa_symfile_init): Access embedded STAB info via BFD section
+ mechanism and related macros.
+
+
+Sat Jan 9 19:31:43 1993 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c: Use a seperate stack for our traps.
+ * Handle recursive traps.
+ * Remove all trap init code. This needs to be done by the
+ environment.
+ * (set_mem_fault_trap): Call exceptionHandler() to setup this
+ trap.
+ * (handle_exception): See if we are at breakinst, if so, then
+ advance PC sp that users can just step out of breakpoint().
+ * (case 'G'): Don't let GDB hack CWP. Also, copy saved regs to
+ new place if SP has changed.
+ * (case 's'): Get rid of this, we can't do it yet.
+ * (case 't'): New command to test any old random feature.
+ * (case 'r'): New command to reset the system.
+ * (breakpoint): Add label to breakpoint trap instruction so that
+ handle_exception() can detect where we are and get past the
+ breakpoint trivially.
+
+Thu Jan 7 13:33:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-pinsn.c: Actual work now done by opcodes/mips-dis.c.
+
+Thu Jan 7 09:21:51 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: recognise all sparclite variants
+
+Wed Jan 6 10:14:51 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * symfile.c: If O_BINARY isn't defined, set it to 0, call openp for
+ binary files oring in the right bit.
+
+ * main.c, source.c, state.c, symmisc.c: use macros defined in
+ fopen-{bin|both} when fopening files.
+
+Wed Jan 6 08:19:11 1993 Fred Fish (fnf@cygnus.com)
+
+ * defs.h (HOST_CHAR_BIT): New macro, defaults to either CHAR_BIT
+ from a configuration file (typically including <limits.h>), or to
+ TARGET_CHAR_BIT if CHAR_BIT is not defined.
+ * eval.c (evaluate_subexp): Use new BYTES_TO_EXP_ELEM macro.
+ * eval.c (evaluate_subexp): Add case for OP_BITSTRING.
+ * expprint.c (print_subexp): Use new BYTES_TO_EXP_ELEM macro.
+ * exppritn.c (print_subexp, dump_expression): Add case for
+ OP_BITSTRING.
+ * expression.h (OP_BITSTRING): New expression element type for
+ packed bitstrings.
+ * expression.h (EXP_ELEM_TO_BYTES, BYTES_TO_EXP_ELEM): New
+ macros to convert between number of expression elements and bytes
+ to store that many elements.
+ * i960-tdep.c (leafproc_return): Use new macros to access
+ minimal symbol name and address fields.
+ * m88k-pinsn.c (sprint_address): Use new macros to access
+ minimal symbol name and address fields.
+ * nindy-tdep.c (nindy_frame_chain_valid): Use new macro to access
+ minimal symbol address field.
+ * parse.c (write_exp_elt, write_exp_string, prefixify_expression,
+ parse_exp_1): Use new EXP_ELEM_TO_BYTES macro.
+ * parse.c (write_exp_string, length_of_subexp, prefixify_expression):
+ Use new BYTES_TO_EXP_ELEM macro.
+ * parse.c (write_exp_bitstring): New function to write packed
+ bitstrings into the expression element vector.
+ * parse.c (length_of_subexp, prefixify_subexp): Add case for
+ OP_BITSTRING.
+ * parser-defs.h (struct stoken): Document that it is used for
+ OP_BITSTRING as well as OP_STRING.
+ * parser-defs.h (write_exp_bitstring): Add prototype.
+ * ch-exp.y (BIT_STRING_LITERAL): Change token type to sval.
+ * ch-exp.y (NUM, PRED, SUCC, ABS, CARD, MAX, MIN, SIZE, UPPER,
+ LOWER, LENGTH): New tokens for keywords.
+ * ch-exp.y (chill_value_built_in_routine_call, mode_argument,
+ upper_lower_argument, length_argument, array_mode_name,
+ string_mode_name, variant_structure_mode_name): New non-terminals
+ and productions.
+ * ch-exp.y (literal): Useful production for BIT_STRING_LITERAL.
+ * ch-exp.y (match_bitstring_literal): New lexer support function
+ to recognize bitstring literals.
+ * ch-exp.y (tokentab6): New token table for 6 character keywords.
+ * ch-exp.y (tokentab5): Add LOWER, UPPER.
+ * ch-exp.y (tokentab4): Add PRED, SUCC, CARD, SIZE.
+ * ch-exp.y (tokentab3): Add NUM, ABS, MIN, MAX.
+ * ch-exp.y (yylex): Check tokentab6.
+ * ch-exp.y (yylex): Call match_bitstring_literal.
+
+Mon Jan 4 16:54:18 1993 Fred Fish (fnf@cygnus.com)
+
+ * xcoffexec.c (vmap_symtab): Use new macros to access minimal
+ symbol name and value fields.
+
+ * c-exp.y (yylex): Make static, to match prototype and other
+ <lang>-exp.y files.
+
+ * expression.h (exp_opcode): Add BINOP_MOD.
+ * eval.c (evaluate_subexp): Handle new BINOP_MOD.
+ * expprint.c (dump_expression): Handle new BINOP_MOD.
+ * language.c (binop_type_check): Handle new BINOP_MOD.
+ * main.c (float_handler): Re-enable float handler when hit.
+ * valarith.c (language.h): Include, need current_language.
+ * valarith.c (TRUNCATION_TOWARDS_ZERO): Define default macro
+ for integer divide truncates towards zero for negative results.
+ * valarith.c (value_x_binop): Handle BINOP_MOD if seen.
+ * valarith.c (value_binop): Allow arithmetic operations on
+ TYPE_CODE_CHAR variables. Add case to handle new BINOP_MOD.
+ * ch-exp.y (operand_4): Add useful actions for MOD and REM.
+ * ch-exp.y (tokentab3): Add MOD and REM.
+ * ch-exp.y (yylex): Set innermost_block for symbols found
+ in local scopes. Return LOCATION_NAME for local symbols.
+ * ch-lang.c (chill_op_print_tab): Fix MOD entry to use
+ BINOP_MOD instead of BINOP_REM. Add REM entry, using BINOP_REM.
+
+Mon Jan 4 07:35:31 1993 Steve Chamberlain (sac@wahini.cygnus.com)
+
+ * command.c (shell_escape, make_command, _initialize_command):
+ don't create or use fork if CANT_FORK is defined.
+ * serial.h, ser-go32.c: now compiles, but "the obvious problems of
+ code written for the IBM PC" remain.
+ * xm-go32.h: define CANT_FORK
+
+Sun Jan 3 14:24:56 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * remote-sim.c: first attempt at general simulator interface
+ * remote-hms.c: whitespace
+ * h8300-tdep.c: (h8300_skip_prologue, examine_prologue):
+ understand new stack layout. (print_register_hook): print ccr
+ register in a fancy way.
+
+Sun Jan 3 14:16:10 1993 Fred Fish (fnf@cygnus.com)
+
+ * eval.c (language.h): Include.
+ * eval.c (evaluate_subexp_with_coercion): Only coerce arrays
+ to pointer types when the current language is C. It loses for
+ other languages when the lower index bound is nonzero.
+ * valarith.c (value_subscript): Take array lower bounds into
+ account when performing subscripting operations.
+ * valops.c (value_coerce_array): Add comment describing why
+ arrays with nonzero lower bounds are dealt with in value_subscript,
+ rather than in value_coerce_array.
+
+Sat Jan 2 12:16:41 1993 Fred Fish (fnf@cygnus.com)
+
+ * ch-exp.y (FLOAT_LITERAL): Add token.
+ * ch-exp.y (literal): Add FLOAT_LITERAL.
+ * ch-exp.y (match_float_literal): New lexer routine.
+ * ch-exp.y (convert_float): Remove.
+ * ch-exp.y (yylex): Call match_float_literal.
+ * ch-exp.y (yylex): Match single '.' after trying
+ to match floating point literals.
+
+ * eval.c (evaluate_subexp): Add case MULTI_SUBSCRIPT.
+ * expprint.c (print_subexp): Rename BINOP_MULTI_SUBSCRIPT to
+ MULTI_SUBSCRIPT.
+ * expprint.c (dump_expression): New function for dumping
+ expression vectors during gdb debugging.
+ * expression.h (BINOP_MULTI_SUBSCRIPT): Name changed to
+ MULTI_SUBSCRIPT and moved out of BINOP range.
+ * expression.h (DUMP_EXPRESSION): New macro that calls
+ dump_expression if DEBUG_EXPRESSIONS is defined.
+ * m2-exp.y (BINOP_MULTI_SUBSCRIPT): Changed to MULTI_SUBSCRIPT.
+ * parse.c (length_of_subexp, prefixify_subexp): Change
+ BINOP_MULTI_SUBSCRIPT to MULTI_SUBSCRIPT.
+ * parse.c (parse_exp_1): Call DUMP_EXPRESSION before and after
+ prefixify'ing the expression.
+ * printcmd.c (print_command_1): Add comment.
+ * ch-exp.y (expression_list): Add useful actions.
+ * ch-exp.y (value_array_element): Add useful actions.
+ * ch-exp.y (array_primitive_value): Add production.
+ * ch-exp.y (yylex): Recognize ',' as a token.
+
+Fri Jan 1 18:22:02 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: pass prefix and exec_prefix via FLAGS_TO_PASS,
+ POSIXize the recursive makes (make [variable assignments] target{s})
+
+Fri Jan 1 11:56:23 1993 Fred Fish (fnf@cygnus.com)
+
+ * tm-sun4sol2.h (CPLUS_MARKER): Remove, now set in tm-sysv4.h.
+ * tm-sysv4.h (CPLUS_MARKER): By default, g++ uses '.' as the
+ CPLUS_MARKER for all SVR4 systems, so follow suit.
+ * defs.h (strdup_demangled): Remove prototype.
+ * dwarfread.c (enum_type, synthesize_typedef): Use new macro
+ SYMBOL_INIT_LANGUAGE_SPECIFIC.
+ * dwarfread.c (new_symbol): Use SYMBOL_INIT_DEMANGLED_NAME.
+ * minsyms.c (install_minimal_symbols, prim_record_minimal_symbol,
+ prim_record_minimal_symbol_and_info): Use new macro
+ SYMBOL_INIT_LANGUAGE_SPECIFIC.
+ * minsyms.c (install_minimal_symbols): Use new macro
+ SYMBOL_INIT_DEMANGLED_NAME.
+ * stabsread.c (define_symbol): Use new macro
+ SYMBOL_INIT_DEMANGLED_NAME.
+ * symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ Use new macro SYMBOL_INIT_DEMANGLED_NAME.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Use new macro
+ SYMBOL_INIT_DEMANGLED_NAME.
+ * symmisc.c (dump_msymbols, dump_symtab, print_partial_symbol):
+ SYMBOL_DEMANGLED_NAME now tests language itself.
+ * symtab.c (COMPLETION_LIST_ADD_SYMBOL): SYMBOL_DEMANGLED_NAME
+ now tests language itself.
+ * symtab.h (SYMBOL_CPLUS_DEMANGLED_NAME): New macro that does
+ what SYMBOL_DEMANGLED_NAME used to do, directly access the C++
+ mangled name member in the language dependent portion of a symbol.
+ * symtab.h (SYMBOL_DEMANGLED_NAME): New macro that returns the
+ mangled name member appropriate for a symbol's language.
+ * symtab.h (SYMBOL_SOURCE_NAME, SYMBOL_LINKAGE_NAME,
+ SYMBOL_MATCHES_NAME, SYMBOL_MATCHES_REGEXP):
+ SYMBOL_DEMANGLED_NAME now tests language itself.
+ * symtab.h (SYMBOL_INIT_LANGUAGE_SPECIFIC): New macro that
+ initializes language dependent portion of symbol.
+ * symtab.h (SYMBOL_INIT_DEMANGLED_NAME): New macro that
+ demangles and caches the demangled form of symbol names.
+ * utils.c (fputs_demangled, fprint_symbol): Use current language
+ to select an appropriate demangling algorithm.
+ * utils.c (strdup_demangled): Remove, no longer used.
+ * symtab.h (SYMBOL_CHILL_DEMANGLED_NAME): New macro that directly
+ access the Chill mangled name member in the language dependent
+ portion of a symbol.
+ * ch-lang.c (chill_demangle): New function, simple demangler.
+ * defs.h (chill_demangle): Add prototype.
+ * symtab.h (language_dependent_info): Add struct for Chill.
+
+For older changes see ChangeLog-92
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/contrib/gdb/gdb/ChangeLog-94 b/contrib/gdb/gdb/ChangeLog-94
new file mode 100644
index 0000000..a691ace
--- /dev/null
+++ b/contrib/gdb/gdb/ChangeLog-94
@@ -0,0 +1,5705 @@
+Fri Dec 30 17:58:55 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * config/m68k/tm-est.h: Remove cruft.
+
+
+Thu Dec 29 22:40:00 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * Allow up to 10 whitespace separated arguments to user defined
+ commands.
+ * top.c (struct user_args): Structure for holding arguments to
+ user defined commands.
+ (print_command_line): Delete unused "tmp_chain" variable. Clean
+ up flow control by having cases exit in the same manner.
+ Before executing a command or evaluating an expression, substitute
+ the current $arg0..$arg9 values if the command/expression uses them.
+ (arg_cleanup): New function.
+ (setup_user_args, locate_arg, insert_args): Likewise.
+ (execute_user_command): Allow arguments to user defined commands.
+
+ * Allow if/while commands to be used within a breakpoint command
+ list.
+ * breakpoint.c (bpstat_do_actions): Call execute_control_command
+ rather than execute_command (passes entire command structure rather
+ than just the command line text).
+ (breakpoint_1): Use "print_command_line" to print a breakpoint
+ command line (including control structures).
+ * gdbcmd.h (execute_control_command): Provide extern decl.
+ (print_command_line): Likewise.
+ * top.c (execute_control_command): No longer static.
+ (print_command_line): New function to recursively print a command
+ line, including control structures.
+
+Thu Dec 29 18:18:31 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * hppa-tdep.c (pa_print_registers): Extract register values stored
+ in big endian format on big and little endian hosts.
+
+ * array-rom.c: Support for Array Tech LSI33k based RAID disk
+ controller board.
+ * configure.in: Recognize "mips*-*-ecoff*" rather than
+ "mips*-idt-ecoff*" so it'll work for the LSI33k.
+
+ * monitor.[ch], op50-rom.c, rom68k-rom.c, w89k-rom.c: Add support
+ to monitor config structure for supported baud rates for a target
+ and variable stop bits.
+ * monitor.c (monitor_fetch_register): Store register values in big
+ endian format on any host.
+
+Wed Dec 28 19:27:22 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Prefer import stubs over
+ export stubs and actual shared library functions so that lazy
+ binding works correctly. Try both __d_plt_call and __gcc_plt_call
+ trampolines for calling import stubs.
+
+Wed Dec 28 15:29:02 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * a29k-tdep.c (pop_frame): Fix a variable name.
+
+Wed Dec 28 12:21:39 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (push_dummy_frame): Refine code to determine what
+ space ID to place in the stack & inf_status structure.
+ (hppa_pop_frame): Don't walk through trampoline code if popping a
+ call dummy frame.
+ (hppa_fix_call_dummy): Call the stack dummy directly if the
+ current PC is in a shared library.
+
+ * hppa-tdep.c (push_dummy_frame): Return type is void. Clear
+ in_syscall bit in flags. Don't depend on the PC queue registers
+ when in_syscall is set, they're not valid.
+ * config/pa/tm-hppa.h (PUSH_DUMMY_FRAME): Pass inf_status down to
+ push_dummy_frame.
+ (SR4_REGNUM): Define.
+
+ * hppa-tdep.c: Misc. lint changes.
+
+Tue Dec 27 12:32:43 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * breakpoint.c (watchpoint_check): Don't bother restoring the
+ "selected" frame anymore, it's not necessary. Initialize the
+ frame cache before trying to find the current frame in the frame
+ chain.
+
+ * somsolib.c (som_solib_add): Return without loading any shared
+ libraries if symfile_objfile is NULL.
+ (som_solib_create_inferior_hook): Likewise.
+
+Fri Dec 23 17:03:13 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-est.c: New file supports EST-300 CPU32 background
+ mode ICE.
+ * remote-utils.c (sr_com): Call registers_changed.
+ * configure.in (m68*-*-est*): New configuration.
+ * config/m68k/tm-est.h: New file.
+
+Fri Dec 23 16:18:50 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (CLIBS): Put LIBIBERTY last.
+
+Thu Dec 22 09:27:16 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * ser-tcp.c (tcp_open): Cast to struct sockaddr when passing to
+ function which expects that.
+
+Thu Dec 22 13:25:33 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * nlm/gdbserve.c, nlm/ppc.c, nlm/ppc.h: Don't try to use
+ ALTERNATE_MEM_FUNCS.
+
+Wed Dec 21 14:00:26 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c: Now supports xmodem as a remoteloadprotocol.
+
+Tue Dec 20 23:01:17 1994 Stu Grossman (grossman@cygnus.com)
+
+ * config/mips/xm-irix4.h, config/mips/xm-irix5.h: #define
+ _BSD_COMPAT to get reliable signal handling.
+
+Tue Dec 20 11:44:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-tdep.c, a29k-tdep.c, findvar.c (get_saved_register):
+ if !target_has_registers, call error().
+
+ * value.h: Remove obsolete comments about FRAME vs struct
+ frame_info *.
+
+
+Sun Dec 18 11:52:58 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (sparc_pop_frame): Remove erroneous extra argument
+ to write_register.
+
+Sat Dec 17 13:23:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * tm-sparc.c (EXTRA_FRAME_INFO): New field sp_offset.
+ * sparc-tdep.c (sparc_init_extra_frame_info): Set it.
+ (examine_prologue, sparc_init_extra_frame_info): Use ->frame plus
+ ->sp_offset to compute the address something is saved at, not
+ ->bottom.
+
+ * sparc-tdep.c (get_saved_register): New function.
+ * tm-sparc.h: Define GET_SAVED_REGISTER; don't define
+ FRAME_FIND_SAVED_REGS, HAVE_REGISTER_WINDOWS or REGISTER_IN_WINDOW_P.
+ * stack.c (frame_info): Add comment about what to do if
+ FRAME_FIND_SAVED_REGS is not defined.
+
+ * sparc-tdep.c (sparc_init_extra_frame_info): Set ->frame field
+ here. Get it right for flat frames.
+ * sparc-tdep.c (sparc_frame_chain): Instead of returning
+ meaningful value for ->frame field, just return dummy value.
+ This change is needed because the old code didn't deal with mixed
+ flat and non-flat frames.
+
+ * sparc-tdep.c (sparc_pop_frame): Write SP_REGNUM from
+ frame->frame, don't go through saved regs for this.
+
+ * sparc-tdep.c: Move guts of skip_prologue to new function
+ examine_prologue. Check for flat prologue and set is_flat.
+ Provide the caller with the information about what is saved where
+ if desired.
+ (skip_prologue, sparc_frame_find_saved_regs): Call examine_prologue.
+
+ * sparc-tdep.c: Replace union sparc_insn_layout and anonymous
+ union in isannulled, which won't work on a little-endian host,
+ with X_* macros.
+
+ * sparc-tdep.c (sparc_frame_saved_pc): If addr == 0, the saved PC
+ is still in %o7.
+
+ * config/sparc/tm-sparc.h: Define INIT_FRAME_PC and
+ INIT_FRAME_PC_FIRST.
+ * blockframe.c (get_prev_frame_info): Modify comments regarding
+ INIT_FRAME_PC_FIRST and the sparc.
+
+ * sparc-tdep.c (single_step): Use 4 not sizeof (long) for size of
+ instruction.
+
+Sat Dec 17 02:33:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-typeprint.c (c_type_print_base): Use `show' of -1 to print
+ the return type of methods to avoid infinite loops with anonymous
+ types.
+ * valops.c (search_struct_field): Handle anonymous unions.
+
+ * sparc-tdep.c (sunos4_skip_trampoline_code): New function
+ to correctly handle steps into -g compiled PIC objects in the
+ main executable.
+ * config/sparc/tm-sun4os4.h (SKIP_TRAMPOLINE_CODE):
+ Redefine to use sunos4_skip_trampoline_code.
+
+ * dwarfread.c (DWARF_REG_TO_REGNUM): Provide a default mapping
+ from DWARF to GDB register numbering.
+ * dwarfread.c (locval): Use DWARF_REG_TO_REGNUM to map the
+ register value.
+ * config/mips/tm-mipsv4.h (DWARF_REG_TO_REGNUM): Define.
+
+Fri Dec 16 10:56:29 1994 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (uninstall): transform file names.
+
+Thu Dec 15 16:55:35 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * defs.h: Include progress.h.
+ (QUIT): Call PROGRESS.
+ * main.c (main): Call START_PROGRESS and END_PROGRESS, break
+ usage message into shorter strings.
+ * source.c: Change long command help strings into concats of
+ shorter ones, for picky ANSI compilers.
+
+ * top.c (command_loop): For space usage display, show both
+ absolute size and the change from before command execution.
+
+Thu Dec 15 16:40:10 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, main.c (gdb_fputs), top.c: Add stream arg to
+ fputs_unfiltered_hook.
+ * defs.h, top.c, utils.c (error): Add error_hook.
+
+Tue Dec 13 15:15:33 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * breakpoint.c, infrun.c, printcmd.c: Change long command help
+ strings into concats of shorter ones, for picky ANSI compilers.
+
+Mon Dec 12 17:08:02 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ Sparc flat register window support.
+ * sparc-tdep.c (sparc_insn_layout): New union, defines layout of
+ instructions symbolically (used to be local to skip_prologue).
+ (sparc_init_extra_frame_info): New function.
+ (sparc_frame_chain): Add flat cases throughout.
+ (skip_prologue): Add recognition of flat prologues.
+ (sparc_frame_find_saved_regs): Add flat cases.
+ (sparc_pop_frame): Ditto.
+ * config/sparc/tm-sparc.h (EXTRA_FRAME_INFO): New slots.
+ (INIT_EXTRA_FRAME_INFO): Call sparc_init_extra_frame_info.
+ (PRINT_EXTRA_FRAME_INFO): Define.
+
+
+Mon Dec 12 13:06:59 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * f-lang.c: Remove duplicate declaration of
+ builtin_type_f_integer, and only include it in the f_builtin_types
+ once.
+
+ * somread.c (som_symfile_read): Just assign to objfile->obj_private,
+ not OBJ_UNWIND_INFO. Assigning to a cast is a GCC-ism which
+ the HP compiler doesn't like.
+
+
+Fri Dec 9 15:50:05 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (remote_wait): Pass string instead of char to strcpy.
+
+Fri Dec 9 04:43:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/low-lynx.c (mywait): Remove debugging printf.
+
+Thu Dec 8 15:07:29 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * frame.h: Restore pre-Nov 3 comments about FRAME_FP with minor
+ changes. They are correct, unlike the post-Nov 3 comment
+ (FRAME_FP doesn't have any machine-independent relationship with
+ FP_REGNUM or any other such notion of a "frame pointer").
+
+Wed Dec 7 14:50:54 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * gdbserver/remote-utils.c (write_ok): Write "OK", not "Ok", to
+ match stubs and protocol spec.
+ * gdbserver/remote-utils.c (remote_open): Cast to struct sockaddr
+ when passing to function which expects that.
+
+ The following changes aren't quite enough to make things work with
+ LynxOS (apprently kernel problems).
+ * infrun.c (wait_for_inferior): When resuming new thread, pass pid
+ not -1 for remote case.
+ * thread.c (info_threads_command): Give error if !target_has_stack.
+ * infrun.c (start_remote): Call init_thread_list.
+ * thread.c (info_threads_command): Don't call kill for remote
+ debugging target.
+ * target.c (normal_pid_to_str): Print "thread" not "process" for
+ remote.
+ * remote.c, gdbserver/*: Add 'H', 'S', and 'C' requests, 'X'
+ response, and `thread' part of 'T' response.
+ * gdbserver/*: If program exits, send packet to GDB before
+ exiting. Handle termination with a signal the same as exiting
+ with an exitstatus.
+ * remote.c: Don't try to kill program after getting an 'X'
+ response.
+ * infrun.c (wait_for_inferior): Add comment about kill versus mourn.
+
+Thu Dec 8 12:37:38 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * config/pa/tm-pro.h tm-hppap.h, hppapro.mt: Rename tm-hppap.h to
+ tm-pro.h.
+
+Wed Dec 7 18:22:59 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * source.c: Various cosmetic changes.
+ (forward_search_command): Handle very long source lines correctly.
+
+Wed Dec 7 13:21:47 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * hppa-tdep.c: Use GDB_TARGET_IS_PA_ELF so SOM target support will
+ stop being linked in.
+
+ * config/pa/tm-hppap.h: New file. Set GDB_TARGET_IS_PA_ELF,
+ otherwise it looks like BSD-ELF.
+
+Mon Dec 5 21:43:52 1994 Stu Grossman (grossman@cygnus.com)
+
+ * inftarg.c: include <sys/types.h> to get def of pid_t.
+
+Fri Dec 2 15:03:07 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * solib.c (auto_solib_add_at_startup): New global.
+ (solib_create_inferior_hook): Call solib_add only if
+ auto_solib_add_at_startup is nonzero.
+ (_initialize_solib): New command "set auto-solib-add".
+
+Fri Dec 2 12:52:04 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * parse.c (msymbol_addr_type): Replaced by
+ lookup_pointer_type (builtin_type_void).
+
+ * printcmd.c (_initialize_printcmd): Give examine_*_type
+ a name for `ptype $_'.
+
+Fri Dec 2 12:52:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_formatted): Call val_print_string directly,
+ rather than via value_print.
+
+Wed Nov 30 22:27:27 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_get_got_by_pc): New function.
+ * somsolib.h (som_solib_get_got_by_pc): Add extern decl.
+ * hppa-tdep.c (hppa_fix_call_dummy): Handle case where FUN is the
+ function's export stub or real address in a shared library.
+
+Tue Nov 29 13:40:25 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * config/i386/nbsd.mh (REGEX, REGEX1): No longer define.
+
+ * configure.in (i[345]86-*-freebsd*): New configuration.
+ * config/i386/{fbsd.mh,fbsd.mt,nm-fbsd.h}: New files.
+
+Tue Nov 29 12:23:25 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * top.c (read_next_line): Pass annotation suffix "commands"
+ instead of "command", matches documentation.
+
+Mon Nov 28 14:53:21 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/a29k/tm-a29k.h (setup_arbitrary_frame): Replace
+ FRAME_ADDR with CORE_ADDR in prototype.
+
+ * top.c (command_line_input): If annotation suffix is NULL,
+ replace it with an empty string.
+ (read_next_line): Pass "command" as annotation suffix to
+ command_line_input.
+
+Mon Nov 28 11:03:14 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * config/rs6000/tm-rs6000.h (setpgrp): move defn from here...
+ * config/rs6000/xm-rs6000.h: ...to here.
+
+
+Fri Nov 25 21:26:02 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * tm-hppa.h (skip_trampoline_code): Add extern decl.
+ * hppa-tdep.c (hppa_pop_frame): Silently restart the inferior and
+ allow it to execute any return path trampoline code. Stop the
+ inferior and give the user control when the trampoline has
+ finished executing.
+ (in_solib_call_trampoline): Handle export stubs which also perform
+ parameter relocations.
+ (in_solib_return_trampoline): Likewise.
+
+Fri Nov 25 13:37:10 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * coffread.c, symfile.h (coff_getfilename): Make it static again.
+ * xcoffread.c (coff_getfilename): Use a static copy from
+ coffread.c, modified for accessing the static xcoff strtbl.
+
+Fri Nov 25 00:51:05 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (in_solib_call_trampoline): Recognize calls through
+ _sr4export and $$dyncall as trampolines. Likewise for long-call
+ stubs and parameter relocation stubs.
+ (in_solib_return_trampoline): Recognize a return trampoline for
+ return value relocation stubs.
+
+ * hpread.c: Include hp-symtab.h instead of hpux-symtab.h.
+ Various name changes to match those used by hp-symtab.h.
+
+Thu Nov 24 00:39:27 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * blockframe.c (find_pc_partial_function): Inhibit mst_trampoline
+ symbol special handling when INHIBIT_SUNSOLIB_TRANSFER_TABLE_HACK
+ is defined.
+ * infrun.c (IN_SOLIB_CALL_TRAMPOLINE): Renamed from
+ IN_SOLIB_TRAMPOLINE. All callers changed.
+ (IN_SOLIB_RETURN_TRAMPOLINE): Provide default definition.
+ (wait_for_inferior): Handle single stepping through trampolines on
+ return paths from shared libraries.
+ * config/pa/tm-hppa.h (IN_SOLIB_CALL_TRAMPOLINE): Use
+ in_solib_call_trampoline.
+ (IN_SOLIB_RETURN_TRAMPOLINE): Use in_solib_return_trampoline.
+ (INHIBIT_SUNSOLIB_TRANSFER_TABLE_HACK): Define.
+ * hppa-tdep.c (in_solib_call_trampoline): New function.
+ (in_solib_return_trampoline): New function.
+
+Wed Nov 23 21:43:03 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * tm-h8300.h (REMOTE_BREAKPOINT): Define.
+ * h8300-tdep.c (h8300_pop_frame): Remove redundant call.
+
+ * remote-e7000.c (HARD_BREAKPOINTS): Reenable.
+ (BC_BREAKPOINTS): Disable.
+ * sh-tdep.c (print_insn): Cope with big and little endian machines.
+ * sh/sh.mt: Use libsim.a
+ * sh/tm-sh.h (TARGET_BYTE_ORDER_SELECTABLE): New
+ (BREAKPOINT): Changed to be byteorder independent.
+
+Tue Nov 22 19:13:39 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Maintenance commands to report time and space usage.
+ * main.c (display_time, display_space): New globals.
+ (main): Add argument --statistics to enable reporting, display
+ time and space after startup is done.
+ * maint.c (maintenance_time_display, maintenance_space_display):
+ New commands.
+ * top.c (command_loop): Display time and space after command
+ execution.
+
+ * top.c (pre_init_ui_hook): New global.
+ (gdb_init): If pre_init_ui_hook set, call before all other init.
+
+Tue Nov 22 10:25:59 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * a29k-tdep.c (examine_tag): Fix a bug in stack frame size.
+
+Sat Nov 19 03:10:51 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/i386sol2.mh: Reenable core file support.
+
+ * symfile.c (deduce_language_from_filename): Treat .c++ as a
+ C++ extension.
+
+ * valops.c (destructor_name_p): Do not compare the template
+ part for template classes.
+
+Fri Nov 18 14:55:59 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * defs.h, infcmd.c (reg_names): Don't declare as constant.
+ * remote-mips.c (mips_open): Read and set the processor type.
+ * mips-tdep.c (mips_set_processor_type): Always return an int.
+
+Fri Nov 18 10:38:12 1994 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/alpha.c (strtol): Remove, it is provided by NetWare C library.
+ * nlm/gdbserve.def (strtol): Add to import list.
+ * nlm/fake_aio.c: Remove file, no longer used.
+
+ * Makefile.in (LD_FOR_TARGET, NLMCONV_FOR_TARGET): Remove.
+ * nlm/Makefile.in (gdbserve.O): Link with ${CC_FOR_TARGET}.
+ (LD_FOR_TARGET): Remove.
+
+Thu Nov 17 22:09:50 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.h, monitor.c, w89k-rom.c, op50n-rom.c, idp-rom.c: Add
+ support for two variables used to control the load protocol and
+ conversion type.
+
+Thu Nov 17 17:51:12 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Support for different MIPS IDT processor models.
+ * mips-tdep.c (mips_processor_type, tmp_mips_processor_type,
+ mips_generic_reg_names, mips_r3041_reg_names,
+ mips_r3051_reg_names, mips_r3081_reg_names,
+ mips_processor_type_table): New globals.
+ (mips_do_registers_info): Don't display register if name is empty.
+ (mips_set_processor_type_command): New command.
+ (mips_show_processor_type_command): New command.
+ (mips_set_processor_type): New function.
+ (mips_read_processor_type): New function.
+ * config/mips/tm-idt.h (DEFAULT_MIPS_TYPE): New macro.
+ * config/mips/tm-mips.h (DEFAULT_MIPS_TYPE): New macro.
+ (NUM_REGS): Increase to account for all CP0 registers.
+ (REGISTER_NAMES): Add empty names for CP0 registers.
+ (FIRST_EMBED_REGNUM, LAST_EMBED_REGNUM): Adjust.
+ (PRID_REGNUM): New macro.
+
+Wed Nov 16 16:41:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * README: Add warning about termcap in Ultrix and OSF/1.
+
+Wed Nov 16 15:28:29 1994 Rob Savoye (rob@cygnus.com)
+
+
+ * hppa-tdep.c: Remove including sys/dir.h from a target file.
+
+Wed Nov 16 10:31:27 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * config/powerpc/gdbserve.mt (TDEPFILES): Remove fake_aio.o.
+
+ * nlm/gdbserve.c: Include <nwtypes.h> before other NetWare headers.
+ * nlm/ppc.c: Likewise.
+
+ * nlm/ppc.c (strtol): Remove, it is provided by NetWare C Library.
+ (StopBell): New function (stubbed out).
+
+Wed Nov 16 00:12:21 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_trampoline_code): Handle shared library import
+ trampolines.
+
+Tue Nov 15 16:18:52 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * c-exp.y (yylex): Fix a bug in template scanning.
+
+Tue Nov 15 14:25:47 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * i386-stub.c, m68k-stub.c, sparc-stub.c, sparcl-stub.c: Mask out
+ the top bit returned by getDebugChar.
+
+Tue Nov 15 01:03:56 1994 Rob Savoye (rob@slipknot.cygnus.com)
+
+ * op50-rom.c, w89k-rom.c, monitor.c: Modify to usr two variables
+ to set remote load type and protocol.
+ * rom68k-rom.c: Add to_stop in target_ops.
+
+
+Sat Nov 12 21:55:47 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c: Add TODO list.
+ (som_solib_add): Immediately return if $SHLIB_INFO$ sections does
+ not exist or has size zero. Slightly simplify error handling.
+ Keep an internal list of all the loaded shared libraries and
+ various tidbits of information about the loaded shared libraries.
+ Build section tables for each loaded shared library and add those
+ tables to the core target if necessary.
+ (som_solib_create_inferior_hook): Force re-reading of shared
+ libraries at exec time.
+ (som_sharedlibrary_info_command): New function for dumping
+ information about the currently loaded shared libraries.
+ (_initialize_som_solib): New function.
+
+Sat Nov 12 02:26:50 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * Makefile.in (copying.o, f-exp.tab.o, dpx2-nat.o, dstread.o,
+ i386aix-nat.o, i386m3-nat.o, irix5-nat.o, lynx-nat.o, m3-nat.o,
+ mipsm3-nat.o, ns32km3-nat.o, remote-e7000.o, remote-os9k.o):
+ Add dependencies.
+ (copying.o, os9kread.o, remote.o): Update dependencies.
+
+ * valarith.c (value_sub): When subtracting pointers, only
+ check for a match of the pointed to element lengths.
+ Cast element length to LONGEST to obtain a signed result for
+ pointer subtractions.
+
+Fri Nov 11 10:51:07 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * ch-exp.y (yylex): Fix off-by-one error when converting string to
+ lowercase. Null terminate new string.
+
+ * hppa-tdep.c (rp_saved): Handle IMPORT stubs too.
+
+ * somsolib.c (som_solib_add): Check the value of __dld_flags, if
+ it indicates __dld_list is not valid return an error. If it
+ indicates that libraries were not mapped privately, issue a
+ warning.
+
+Thu Nov 10 23:17:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symfile.c (syms_from_objfile): Only call find_lowest_section if
+ no ".text" section exists.
+
+Thu Nov 10 15:16:21 1994 Rob Savoye <rob@rtl.cygnus.com>
+
+ * rom68k-rom.c: New file. Replaces the old remote-mon.c and uses
+ the new generic ROM interface in monitor.c.
+ * config/m68k/monitor.mt: Use new ROM support.
+ * monitor.c: Add support for xmodem download protocol.
+
+Wed Nov 9 18:46:24 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * findvar.c (find_saved_register): Fix a frame variable name.
+ * infcmd.c (finish_command): Ditto.
+
+Tue Nov 8 13:20:14 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove "Watchpoints seem not entirely reliable, though
+ they haven't failed me recently." item--this old (4.6 at least)
+ item is too vague to be useful (some watchpoint bugs have been
+ fixed since then).
+ * TODO: Add explanation of "RPC interface" item.
+
+Mon Nov 7 22:25:21 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (read_unwind_info): Use "text_offset" for linker
+ stub unwind descriptors too.
+
+ * Enable backtracing from inside a SOM shared library back into
+ user code.
+ * hppa-tdep.c (internalize_unwinds): Accept and use new
+ "text_offset" argument for dynamic relocation of
+ region_{start,end} fields in the unwind descriptor.
+ (read_unwind_info): Pass text_offset to internalize unwinds.
+
+Mon Nov 7 14:34:42 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m3-nat.c: Remove comments about arbitrary limit in
+ printf_filtered; that limit is gone.
+
+Mon Nov 7 00:27:16 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * Beginnings of SOM shared library support. Breakpoints and
+ single frame backtracing within the library only. Only works when
+ using the HPUX 9 dynamic linker. More functionality to be added
+ soon.
+
+ * somsolib.c, somsolib.h: New files.
+ * Makefile.in (HFILES_NO_SRCDIR): Add somsolib.h
+ (ALLDEPFILES): Add somsolib.c.
+ (somsolib.o): Add some dependencies.
+ * somread.c (som_symtab_read): Accept multiple section offsets.
+ All callers changed. Adjust all text symbols with the first
+ section offset.
+ * symfile.c (find_lowest_section): Enable this function. Add some
+ tie-breaking logic when sections have the same vma.
+ (syms_from_objfile): Use find_lowest_section rather than looking
+ for ".text" by name. Relax warning to only warn if the lowest
+ section is not a code section.
+ * config/pa/{hppabsd.mh, hppahpux.mh} (NATDEPFILES): Add somsolib.o
+ * config/pa/{nm-hppab.h, nm-hppah.h}: Include somsolib.h.
+
+Sun Nov 6 12:54:54 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * partial-stab.h (N_TEXT): Put back GDB_TARGET_IS_HPPA kludge,
+ it is still needed for GCC-2.6 compiled code.
+ * TODO (GDB_TARGET_IS_HPPA): Note this kludge can be nuked
+ sometime after GCC-2.7 has been released.
+
+ * hppa-tdep.c (frame_saved_pc): Mask off low two bits when
+ retrieving the PC from a signal handler caller. Fix thinko
+ in Stan's last change ("frame", should have been "frame->next").
+ If the next frame is a signal handler caller and it's a system
+ call which has entered the kernel ((PSW & 0x2) != 0), then the
+ saved pc is in %r2 instead of %r31.
+
+Fri Nov 4 23:47:07 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_frame_find_saved_regs): Change "frame" to
+ "frame_info" throughout.
+
+Fri Nov 4 16:26:59 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * sparcl-stub.c: get rid of defs.h.
+
+Fri Nov 4 13:11:54 1994 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * gdbserver/Makefile.in (MMALLOC_CFLAGS): Add -I${MMALLOC_DIR}.
+ Correct definition of MMALLOC_DIR to reflect fact this is
+ gdb/gdbserver/Makefile.in, not gdb/Makefile.in.
+
+ * gdbserver/server.c (main): After we kill the inferior in
+ response to a 'k' request, exit.
+
+ * remote.c (remote_kill): Use catch_errors when calling putpkt.
+ (putpkt): Return int, not void, to match catch_errors calling
+ convention.
+
+Fri Nov 4 10:52:38 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * rs6000-tdep.c (pop_frame): Correct a variable name.
+
+Fri Nov 4 05:43:35 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Re-write item about SIGINT handling to reflect the fact
+ that target_stop now exists.
+
+Thu Nov 3 15:19:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Replace useless FRAME, FRAME_ADDR types with struct frame_info *
+ and CORE_ADDR, respectively.
+ * frame.h (FRAME, FRAME_INFO_ID, FRAME_ADDR): Remove.
+ * blockframe.c (get_frame_info): Remove.
+ * a29k-tdep.c, alpha-tdep.c, blockframe.c, breakpoint.c,
+ breakpoint.h, energize.c, findvar.c, gould-pinsn.c,
+ h8300-tdep.c, h8500-tdep.c, hppa-tdep.c, i386-tdep.c, i960-tdep.c,
+ infcmd.c, inferior.h, infrun.c, m68k-tdep.c, m88k-tdep.c,
+ mips-tdep.c, nindy-tdep.c, printcmd.c, pyr-tdep.c, rs6000-tdep.c,
+ sh-tdep.c, sparc-tdep.c, stack.c, valops.c, z8k-tdep.c,
+ config/a29k/tm-a29k.h, config/alpha/tm-alpha.h,
+ config/gould/tm-pn.h, config/h8300/tm-h8300.h,
+ config/h8500/tm-h8500.h, config/mips/tm-mips.h,
+ config/ns32k/tm-merlin.h, config/ns32k/tm-umax.h,
+ config/pyr/tm-pyr.h, config/sparc/tm-sparc.h): Replace FRAME with
+ struct frame_info * everywhere, replace FRAME_ADDR with CORE_ADDR,
+ rename variables consistently (using `frame' or `fi'), remove
+ calls to get_frame_info and FRAME_INFO_ID, remove comments about
+ FRAME and FRAME_ADDR cruftiness.
+
+Thu Nov 3 14:25:24 1994 Stu Grossman (grossman@cygnus.com)
+
+ * corelow.c, exec.c, inftarg.c, m3-nat.c, op50-rom.c, procfs.c,
+ remote-adapt.c, remote-e7000.c, remote-eb.c, remote-es.c,
+ remote-hms.c, remote-mips.c, remote-mm.c, remote-mon.c,
+ remote-nindy.c, remote-os9k.c, remote-pa.c, remote-sim.c,
+ remote-st.c, remote-udi.c, remote-vx.c, remote-z8k.c, remote.c,
+ w89k-rom.c, target.c, target.h: Add support for target_stop().
+
+Thu Nov 3 01:23:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * osfsolib.c (solib_map_sections, first_link_map_member,
+ next_link_map_member, xfer_link_map_member): Retrieve and use
+ shared library relocation offset from runtime loader structures.
+ Use libxproc.a routines to get a working version if
+ USE_LDR_ROUTINES is defined.
+ * README: Remove item about shared library relocation for
+ Alpha OSF/1.
+
+Wed Nov 2 15:05:39 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * c-exp.y (yylex): scan template names, and scan nested class
+ names.
+
+Wed Nov 2 11:01:55 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/Makefile.in: install gdbserve.nlm.
+
+
+Tue Nov 1 13:00:46 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-valprint.c (c_value_print): Check for plain literal `char'
+ target type when suppressing `(char *)' output for strings.
+
+Mon Oct 31 19:19:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * coffread.c (coff_symfile_init): Remove unused local abfd.
+ * utils.c [NO_MMALLOC] (mmalloc, mrealloc): Define and use size_t
+ instead of long, for compatibility with mmalloc.h.
+
+Sat Oct 29 02:40:40 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * top.c (line_completion_function): Renamed from
+ symbol_completion_function, takes the line buffer and the
+ point in the line buffer as additional arguments.
+ (readline_line_completion_function): New function, interface
+ between readline and line_completion_function.
+ (init_main): Use it.
+ (complete_command): Use line_completion_function instead of
+ abusing rl_line_buffer. Free completion strings after printing
+ them.
+ * symtab.c (completion_list_add_name): Recheck for duplicates
+ if we intend to add a modified symbol.
+
+ * gdbtypes.h (cplus_struct_type): nfn_fields_total no longer
+ includes the number of methods from the baseclasses.
+ * stabsread.c (attach_fn_fields_to_type): No longer add the
+ number of methods from the baseclasses to TYPE_NFN_FIELDS_TOTAL,
+ the baseclass type might not have been completely filled in yet.
+ * symtab.c (total_number_of_methods): New function to compute
+ the total number of methods for a type, including the methods
+ from baseclasses.
+ (decode_line_1): Use it instead of TYPE_NFN_FIELDS_TOTAL to
+ allocate the symbol array for find_methods.
+
+ * stabsread.c (scan_file_globals): Add default case to minimal
+ symbol type switch, to avoid gcc -Wall warnings.
+
+ * config/rs6000/tm-rs6000.h (INIT_EXTRA_FRAME_INFO):
+ Don't test for zero backchain pointer to recognize a signal
+ handler frame, if read() gets interrupted by a signal, the
+ backchain will be non zero.
+ (SIG_FRAME_FP_OFFSET): Move to here from rs6000-tdep.c,
+ improve comment.
+ (SIG_FRAME_PC_OFFSET): New definition.
+ (FRAME_SAVED_PC): Return saved pc from sigcontext if this
+ is a signal handler frame.
+ * rs6000-tdep.c (function_frame_info): Do not error out
+ if we can't access the instructions.
+
+ * config/rs6000/tm-rs6000.h (CONVERT_FROM_FUNC_PTR_ADDR):
+ New definition to get the function address from a function pointer.
+ * valops.c (find_function_addr): Use it when calling a user
+ function through a function pointer.
+
+Fri Oct 28 16:16:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (MMALLOC_DIR): New definition.
+ (MMALLOC): Use MMALLOC_DIR.
+ (MMALLOC_CFLAGS): Look in MMALLOC_DIR for mmalloc.h.
+ (OPCODES): Remove gratuitous "./".
+ * defs.h (mmalloc.h): Include.
+ (mmalloc, mrealloc, etc): Remove decls.
+ (cplus_demangle, cplus_demangle_opname): Remove decls.
+
+Wed Oct 26 15:41:07 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, main.c, top.c: Change sense and name of
+ no_windows variable. Now called use_windows, and defaults to off
+ (for compatibility).
+
+Wed Oct 26 12:20:53 1994 Jim Kingdon <kingdon@cygnus.com>
+
+ * coffread.c (coff_symtab_read): If we get the address from
+ target_lookup_symbol, set the section to -2 not SECT_OFF_BSS.
+ (coff_symtab_read): Set value and section of symbol that
+ process_coff_symbol returns.
+
+Tue Oct 25 09:53:04 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/i386/tm-nbsd.h: Enable longjmp support.
+
+Sat Oct 22 03:41:13 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valarith.c (value_binop): Take care of ANSI `value preserving'
+ rule, which was not addressed by the previous change.
+
+ * rs6000-tdep.c (skip_prologue): Handle `mr r31,r1', which is
+ generated by gcc-2.6, as a synonym for `oril r31,r1,0'.
+
+ * TODO: Remove item about RS/6000 shared libraries.
+
+Thu Oct 20 17:35:45 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, infrun.c (wait_for_inferior), top.c: Call
+ target_wait_hook to allow GUI to handle blocking for inferior. Call
+ call_command_hook in execute_command to provide means for wrapping
+ commands with GUI state change updates.
+
+ * infrun.c (wait_for_inferior): Make sure
+ through_sigtramp_breakpoint is non-null before deleting.
+
+Thu Oct 20 10:26:43 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * config/powerpc/ppc-nw.mt (TDEPFILES): Removed exec.o.
+
+Thu Oct 20 06:56:07 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (coffread.o): Depend on target.h.
+ (remote-vx.o): Depend on gdb-stabs.h objfiles.h symfile.h $(bfd_h).
+
+Wed Oct 19 22:49:31 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Fix typo.
+
+Wed Oct 19 11:32:15 1994 Jim Kingdon <kingdon@cygnus.com>
+
+ * objfiles.c (objfile_relocate): When relocating ->sections, use
+ objfile not symfile_objfile.
+
+ * symtab.h, minsyms.c (minsyms_sort): New function.
+ * objfiles.c (objfile_relocate): Call it.
+
+ * remote-vx.c (vx_add_symbols): Call breakpoint_re_set.
+
+ * objfiles.c, objfiles.h (objfile_to_front): New function.
+ * remote-vx.c (vx_add_symbols): Call it.
+
+ * coffread.c (coff_symtab_read): Handle common symbols the same
+ way that partial-stab.h does.
+
+Wed Oct 19 21:06:12 1994 Rob Savoye (rob@cirdan.cygnus.com)
+
+ * hppa-tdep.c: Remove include files a.out.h, ioctl.h, and
+ machine/psl.h. These are host files.
+
+Wed Oct 19 15:13:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * objfiles.h (struct objfile): Fix comment--minimal_symbol_count
+ does *not* include the terminating NULL msymbol.
+
+Tue Oct 18 20:53:29 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c (monitor_load_srec,monitor_make_srec): Add an asrecord
+ loader that reads files using BFD and converts it on the fly.
+
+Mon Oct 17 18:52:06 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c (set_loadtype_command): Fixed so it doesn't core dump.
+ * monitor.c (monitor_load): check the load type and load the file
+ accordingly. Default to gr_load_image().
+ * monitor.c (monitor_load_ascii_srec): Load an ascii file in
+ srecord format by downloading to the monitor.
+ * w89k-rom.c, op50n-rom.c: set supported load types.
+
+Mon Oct 17 10:29:08 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (ALLDEPFILES): Remove xcoffexec.c.
+ * Makefile.in: Remove xcoffexec.o rule.
+
+ * exec.c (exec_file_command): Add comment.
+
+ Fix data and bss relocation for VxWorks 5.1:
+ * remote-vx.c (vx_add_symbols): New function.
+ (vx_load_command, add_symbol_stub): Call it instead of
+ symbol_file_add.
+ (vx_wait): Remove comment which was wrong to useless.
+ * remote-vx.c: Reindent much of file.
+ * coffread.c (cs_to_section, find_targ_sec): New functions.
+ (process_coff_symbol): Set SYMBOL_SECTION to result
+ from cs_to_section.
+ (coff_symtab_read): Call cs_to_section and deal with result
+ rather than assuming sections are in a certain order. Deal with
+ BSS.
+ * coffread.c: Remove text_bfd_scnum variable.
+
+Sat Oct 15 16:55:48 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * corelow.c: Format to standard.
+ (core_close): Use name instead of bfd_filename.
+
+Fri Oct 14 10:29:08 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * exec.c (map_vmap): Cast return from xmalloc to its proper type,
+ not to PTR.
+
+ * symfile.c (reread_symbols): Include bfd_errmsg string in error
+ message if bfd_close fails.
+ * exec.c (exec_close), solib.c (clear_solib), corelow.c
+ (core_close), objfiles.c (free_objfile), irix5-nat.c
+ (clear_solib), osfsolib.c (clear_solib), remote-utils.c
+ (gr_load_image): Check for errors from bfd_close.
+ * solib.c (look_for_base), remote-utils.c (gr_load_image),
+ remote-udi.c (download), corelow.c (core_open), symfile.c
+ (symfile_bfd_open), symfile.c (generic_load): Add comment
+ regarding error from bfd_close.
+ * remote-udi.c (download), remote-utils.c (gr_load_image): Add
+ comment about bogus handling of errors from bfd_openr.
+ * exec.c (exec_close): Add comment regarding memory leak and
+ dangling reference to vp->name.
+
+Sat Oct 15 03:43:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * eval.c (evaluate_subexp): Make fnptr a LONGEST instead
+ of using longest_to_int.
+
+ * infcmd.c (run_stack_dummy): Reinstate set_current_frame call,
+ mips and alpha targets need the real breakpoint pc for
+ creating the breakpoint frame.
+
+ * stack.c (return_command): Cast return value to the return
+ type of the function from which we return.
+ * values.c (set_return_value): Pass VALUE_CONTENTS unmodified
+ to STORE_RETURN_VALUE.
+
+ * symtab.c (lookup_symbol): Remove search for `static mangled
+ symbols', the search for `static symbols' already looks for
+ mangled and demangled symbols via lookup_block_symbol.
+
+ * valarith.c (value_binop): Use ANSI C arithmetic conversions
+ when performing integral evaluations, implement BINOP_EQUAL and
+ BINOP_LESS.
+ (value_equal, value_less): Use value_binop to perform the
+ comparison if both operands have TYPE_CODE_INT.
+
+ * rs6000-tdep.c (pop_frame): Make sure all registers are valid,
+ as they are written back later. Handle sp restore for frameless
+ functions. Use fdata.nosavedpc instead of fdata.frameless to
+ determine if the pc has been saved.
+ (function_frame_info): Handle `mr r31,r1', which is generated by
+ gcc-2.6, as a synonym for `oril r31,r1,0'.
+ (skip_trampoline_code): Handle shared library trampolines.
+ * xcoffread.c (read_xcoff_symtabs): Record XMC_GL symbols with
+ their real name. Enables setting of breakpoints in shared libraries
+ before the executable is run.
+
+Fri Oct 14 19:39:47 1994 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.h, remote-mon.c: Hack up to so the old ROM monitor
+ interface code still works with the new ROM monitor
+ structures. Fake out a couple of fields.
+
+Fri Oct 14 14:54:37 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * h8500-tdep.c (target_read_sp, target_write_sp, target_read_pc,
+ target_write_pc, target_read_fp, target_write_fp): Rename to
+ h8500_read_sp, etc.
+ (h8500_read_pc, h8500_write_pc): Add pid argument.
+ * config/h8500/tm-h8500.h (TARGET_READ_SP, TARGET_WRITE_SP,
+ TARGET_READ_PC, TARGET_WRITE_PC, TARGET_READ_FP, TARGET_WRITE_FP):
+ Change to match functions above.
+
+Thu Oct 13 13:24:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * NEWS: Add item about if and while.
+
+ * .gdbinit: Restore `end'; it was not excess. Reindent
+ list-objfiles to make this clear. Comment out all of
+ list-objfiles because old gdb's choke on it.
+
+Wed Oct 12 23:19:08 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/mips/tm-bigmips64.h: Just define TARGET_BYTE_ORDER and
+ include tm-mips64.h.
+
+Wed Oct 12 18:02:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (ANNOTATE_OBS): New definition.
+ (COMMON_OBS): Add exec.o.
+ (annotate.o): Remove extra compile rule.
+ * config/*/*.mh, config/*/*.mt: Remove exec.o from *DEPFILES lists
+ everywhere.
+
+ * .gdbinit: Remove excess `end'.
+
+ * exec.c: Merge in RS6000 support from xcoffexec.c.
+ (symfile.h, objfiles.h, xcoffsolib.h): Include.
+ (vmap): New global variable.
+ (exec_close): Close and free objects in vmap chain.
+ (exec_file_command) [IBM6000_TARGET]: Set up initial vmap.
+ (bfdsec_to_vmap, map_vmap): Moved here from xcoffexec.c.
+ (exec_files_info): Print vmap information.
+ * xcoffexec.c: Remove.
+ * config/rs6000/rs6000.mt, config/rs6000/rs6000lynx.mt
+ (TDEPFILES): Use exec.o instead of xcoffexec.o.
+ * TODO: Remove pertinent items.
+
+Wed Oct 12 10:08:19 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * partial-stab.h (N_TEXT): Delete GDB_TARGET_IS_HPPA kludge; they
+ are no longer needed as of gcc-2.6.0.
+
+Tue Oct 11 15:51:01 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * lynx-nat.c (child_wait): Correct handling of byte reversed SPARC
+ Lynx wait status.
+ (fetch_core_registers): Don't try to fetch a register if
+ regmap maps it to -1.
+ * sparc-tdep.c (sparc_frame_find_saved_regs): Use FRAME_SAVED_I0
+ and FRAME_SAVED_L0 when setting saved_regs_addr. SPARC Lynx
+ stores the registers in a weird order.
+
+Sat Oct 8 20:59:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * blockframe.c (reinit_frame_cache): Reinstate select_frame call
+ if inferior_pid is nonzero.
+
+Sat Oct 8 04:27:21 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Speed up GDB startup time by not demangling partial symbols.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST),
+ symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ No longer demangle partial symbols.
+ * symtab.c (lookup_symbol, list_symbols): Handle mangled
+ variables, e.g. C++ static members, via the minimal symbols.
+
+ Handle reordered functions in an objfile, for Irix 5.2 shared
+ libraries.
+ * objfiles.h (OBJF_REORDERED): New bit in the objfile flags,
+ set if the functions in an objfile are reordered.
+ * mdebugread.c (parse_partial_symbols): Detect reordered
+ functions in an objfile.
+ * symtab.c (find_pc_psymtab, find_pc_symtab): Use expensive
+ lookup algorithm if the functions in the objfile are reordered.
+
+ * xcoffexec.c (exec_close): If the current target has a copy
+ of the exec_ops sections, reflect the freeing of the sections
+ in current_target.
+
+ * valops.c (call_function_by_hand): Use `sizeof dummy1', not
+ `sizeof dummy', for constructing the call dummy code.
+
+ * config/sparc/tm-sparc.h: Add PARAMS declarations to all
+ function declarations.
+ * sparc-tdep.c (sparc_pop_frame): Cast result of
+ read_memory_integer to CORE_ADDR when passing it to PC_ADJUST.
+
+ * irix5-nat.c (enable_break): Set breakpoint at the entry point
+ of the executable, to handle the case where main resides in a
+ shared library.
+ * irix5-nat.c (solib_create_inferior_hook): Reset stop_soon_quietly
+ after shared library symbol reading, to get rid of a warning from
+ heuristic_proc_start if the startup code has no symbolic debug info.
+
+ * breakpoint.h (struct breakpoint): Add new fields language
+ and input_radix, to enable breakpoint resetting with the
+ proper language and radix.
+ * breakpoint.c (set_raw_breakpoint): Initialize them.
+ (breakpoint_re_set_one): Use them when resetting the breakpoint.
+ (breakpoint_re_set): Preserve current language and input_radix
+ across breakpoint_re_set_one calls.
+
+ * symtab.c (decode_line_1): Do not build a canonical line
+ specification for `*expr' line specifications.
+
+ * breakpoint.h (bpstat_stop_status): Fix prototype declaration.
+
+Fri Oct 7 08:48:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ The point of these changes is to avoid reading the frame pointer
+ and stack pointer during stepping, to speed things up.
+ A. Changes to not select a frame until we need a selected frame:
+ * blockframe.c (flush_cached_frames): Call select_frame (NULL, -1).
+ * infrun.c (wait_for_inferior): Move call to select_frame back to
+ normal_stop. This reverts a change of 13 Apr 94 (it says Jeff
+ Law, but the change was my idea); the only reason for that change
+ was so we could save and restore the selected frame in
+ wait_for_inferior, and now that flush_cached frames clears the
+ selected frame, that should work OK now.
+ B. Changes to not create a current_frame until we need one:
+ * blockframe.c (get_current_frame): If current_frame is NULL, try
+ to create an innermost frame.
+ * sparc-tdep.c (sparc_pop_frame), infcmd.c (run-stack_dummy),
+ infrun.c (wait_for_inferior), thread.c (thread_switch),
+ convex-tdep.c (set_thread_command), a29k-tdep.c (pop_frame),
+ alpha-tdep.c (alpha_pop_frame), convex-xdep.c (core_file_command),
+ h8300-tdep.c (h8300_pop_frame), h8500-tdep.c (h8300_pop_frame),
+ hppa-tdep.c (hppa_pop_frame), i386-tdep.c (i386_pop_frame),
+ i960-tdep.c (pop_frame), m68k-tdep.c
+ (m68k_pop_frame), mips-tdep.c (mips_pop_frame), rs6000-tdep.c
+ (push_dummy_frame, pop_dummy_frame, pop_frame), sh-tdep.c
+ (pop_frame), config/arm/tm-arm.h (POP_FRAME),
+ config/convex/tm-convex.h (POP_FRAME), config/gould/tm-pn.h
+ (POP_FRAME), config/ns32k/tm-merlin.h (POP_FRAME),
+ config/ns32k/tm-umax.h (POP_FRAME), config/tahoe/tm-tahoe.h
+ (POP_FRAME), config/vax/tm-vax.h (POP_FRAME): Don't
+ call create_new_frame.
+ * corelow.c (core_open), altos-xdep.c (core_file_command),
+ arm-xdep.c (core_file_command), gould-xdep.c (core_file_command),
+ m3-nat.c (select_thread), sun386-nat.c (core_file_command),
+ umax-xdep.c (core_file_command): Don't call create_new_frame; do
+ call flush_cached_frames.
+ * blockframe.c (reinit_frame_cache): Don't call create_new_frame
+ or select_frame.
+ C. Changes to get rid of stop_frame_address and instead only
+ fetch the frame pointer when we need it.
+ * breakpoint.c (bpstat_stop_status): Remove argument
+ frame_address; use FRAME_FP (get_current_frame ()).
+ * infrun.c (wait_for_inferior): Don't pass frame pointer to
+ bpstat_stop_status.
+ * infrun.c (wait_for_inferior): Use FRAME_FP (get_current_frame
+ ()) instead of stop_frame_address.
+ * infrun.c (save_inferior_status, restore_inferior_status),
+ inferior.h (struct inferior_status): Don't save and restore
+ stop_frame_address.
+ * inferior.h, infcmd.c, thread.c (thread_switch), m3-nat.c
+ (select_thread): Remove stop_frame_address and uses thereof.
+ D. Same thing for the stack pointer.
+ * infrun.c (wait_for_inferior): Remove stop_sp and replace
+ uses thereof with read_sp ().
+ E. Change to eliminate one nasty little spot where we were
+ wanting to know the frame pointer from before the current step
+ (idea from GDB 3.5, which saved my ass, because my other ideas of
+ how to fix it were very baroque).
+ * infrun.c: Remove prev_frame_address.
+ * infrun.c (wait_for_inferior, step_over_function): Use
+ step_frame_address instead of prev_frame_address.
+ F. Same basic idea for the stack pointer.
+ * inferior.h, infcmd.c: New variable step_sp.
+ * infcmd.c (step_1, until_next_command): Set it.
+ * infrun.c: Remove prev_sp and replace uses by step_sp.
+ * infrun.c (wait_for_inferior): If we get out of the step
+ range, then set step_sp to the current stack pointer before we
+ start going again.
+
+Fri Oct 7 12:17:17 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * top.c (target_byte_order_auto): New static variable.
+ (set_endian): Mention that ``auto'' is permitted.
+ (set_endian_auto): New static function.
+ (show_endian): Change message based on target_byte_order_auto.
+ (set_endian_from_file): New function.
+ (init_main): Add command ``auto'' to endianlist.
+ * exec.c (exec_file_command): Call set_endian_from_file.
+ * defs.h (set_endian_from_file): Declare.
+
+Thu Oct 6 18:10:41 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/i386.c (flush_i_cache): New function, does nothing.
+ (frame_to_registers, registers_to_frame, set_step_traps,
+ clear_step_traps, do_status): Make non-static.
+
+Thu Oct 6 12:26:42 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/mips/tm-mips.h (GDB_TARGET_IS_MIPS64): If not already
+ defined, define as 0.
+ (FIX_CALL_DUMMY): Rewrite to remove presumption that host and
+ target are similar.
+ * config/mips/tm-idt.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ * config/mips/tm-idtl.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ * config/mips/tm-idt64.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ (BREAKPOINT): Remove definition.
+ * config/mips/tm-idtl64.h (TARGET_BYTE_ORDER_SELECTABLE): Define.
+ (BREAKPOINT): Remove definition.
+ * config/mips/tm-mips64.h (GDB_TARGET_IS_MIPS64): Define with a
+ value of 1, rather than without a value.
+ * config/mips/tm-bigmips64.h (GDB_TARGET_IS_MIPS64): Likewise.
+ * mips-tdep.c: Rewrite uses of GDB_TARGET_IS_MIPS64 to switch at
+ run time rather than at compile time.
+
+ * remote-mips.c (break_insn): Remove.
+ (BREAK_INSN, BREAK_INSN_SIZE): Define.
+ (mips_insert_breakpoint): Use BREAK_INSN, not break_insn.
+ (mips_remove_breakpoint): Likewise.
+
+ * defs.h: If TARGET_BYTE_ORDER_SELECTABLE is defined by tm.h,
+ define TARGET_BYTE_ORDER as target_byte_order, and declare
+ target_byte_order as an extern int, and define BITS_BIG_ENDIAN as
+ a test of TARGET_BYTE_ORDER.
+ * top.c: Several additions if TARGET_BYTE_ORDER_SELECTABLE is
+ defined:
+ (endianlist, target_byte_order): New variables.
+ (set_endian, set_endian_big, set_endian_little): New functions.
+ (show_endian): New function.
+ (init_cmd_lists): Initialize endianlist.
+ (init_main): Add commands ``set endian big'', ``set endian
+ little'', and ``show endian''.
+ * a29k-pinsn.c: Rewrite uses of TARGET_BYTE_ORDER and
+ BITS_BIG_ENDIAN to switch at run time rather than at compile time.
+ * coffread.c, dwarfread.c, findvar.c, mips-tdep.c: Likewise.
+ * remote-os9k.c, stabsread.c, valarith.c, valprint.c: Likewise.
+ * values.c: Likewise.
+
+Wed Oct 5 11:41:24 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/configure.in: ${gdb_host_cpu} defaults to ${host_cpu}.
+
+ * nlm/Makefile.in: Get rid of NWINCLUDES.
+ * config/{alpha,powerpc}/gdbserve.mt: Remove NWINCLUDES.
+ User should now configure with --with-headers.
+
+Mon Oct 3 07:48:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/server.c (main): Silently accept all unrecognized
+ requests and send back a zero length acknowledge. That is what
+ *-stub.c do and is what remote.c expects.
+
+Mon Oct 3 05:11:47 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * corelow.c (core_open): Copy the modified to_sections_end
+ vector from current_target to core_ops too.
+
+ * gdbserver/server.c (main): Silently accept query requests
+ and send back a zero length acknowledge.
+
+Fri Sep 30 17:17:21 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/Makefile.in: Don't define NWINCLUDES.
+ * config/{alpha,powerpc}/gdbserve.mt: define NWINCLUDES.
+
+Fri Sep 30 15:59:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/low-lynx.c (create_inferior): Pass all 4 args to ptrace.
+
+Fri Sep 30 06:42:42 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * lynx-nat.c (child_wait): Use status.w_status, not status, in
+ arithmetic. status is a `union wait'.
+
+ * config/nm-lynx.h (PTRACE_ARG3_TYPE): Define to int, not char *.
+
+ * lynx-nat.c (child_wait): Pass fourth argument to ptrace.
+
+Thu Sep 29 08:22:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Fix comment for yesterday's change.
+
+Wed Sep 28 17:48:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (complete_symtab): If last_source_file is set upon
+ entry, free it.
+
+Wed Sep 28 08:59:14 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab, case C_FILE):
+ Set main_aux before using it.
+
+ * xcoffexec.c (exec_close): If quitting, don't call clear_symtab_users.
+
+ * xcoffread.c (read_xcoff_symtab): Process XTY_LD symbols we were
+ ignoring before. But continue to ignore XMC_DS.
+
+Wed Sep 28 00:35:23 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_read_array_type): Do not change the type code
+ to TYPE_CODE_PTR for "char foo[]". Just make it a zero length
+ array type.
+
+ * hpread.c (hpread_type_translate): Handle T_UNS_LONG types with
+ lengths other than 32bits (HP C 9.69 represents an "unsigned char"
+ as an T_UNS_LONG with length 8).
+
+ * hpread.c (struct hpread_symfile_info): Delete have_module field
+ and accessor macro. Minor indentation fix.
+ (hpread_build_psymtabs, case K_MODULE): Only start a new psymtab
+ and reset state variables have_name & texthigh if pst is NULL.
+ (hpread_build_psymtabs, case K_SRCFILE): Only reset the name of a
+ partial symbol table if pst is non-NULL. If pst is NULL, then
+ start a new psymtab.
+ (hpread_process_one_debug_symbol, case K_MODULE): Now empty.
+ (hpread_process_one_debug_symbol, case K_SRCFILE): Simplify and
+ correct handling of subfiles.
+
+Mon Sep 26 02:59:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * defs.h (misc_command_type): Remove trailing comma from
+ enumerator list.
+
+Sun Sep 25 23:19:58 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_saved_pc): Fix thinko in code to dig saved pc
+ out of an interrupt frame.
+
+Sun Sep 25 12:50:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * infcmd.c (do_registers_info) [INVALID_FLOAT]: Only use if
+ defined.
+ * values.c (unpack_double) [INVALID_FLOAT]: Ditto.
+ * mips-tdep.c (mips_print_register): Don't test float validity.
+ * config/a29k/tm-a29k.h, config/alpha/tm-alpha.h,
+ config/arm/tm-arm.h, config/convex/tm-convex.h,
+ config/h8300/tm-h8300.h, config/h8500/tm-h8500.h,
+ config/i386/tm-i386v.h, config/i386/tm-sun386.h,
+ config/i960/tm-i960.h, config/m68k/tm-m68k.h,
+ config/m88k/tm-m88k.h, config/mips/tm-mips.h,
+ config/ns32k/tm-merlin.h, config/ns32k/tm-nbsd.h,
+ config/ns32k/tm-ns32km3.h, config/ns32k/tm-umax.h,
+ config/pa/tm-hppa.h, config/pyr/tm-pyr.h,
+ config/rs6000/tm-rs6000.h, config/sh/tm-sh.h,
+ config/sparc/tm-sparc.h, config/z8k/tm-z8k.h (INVALID_FLOAT):
+ Remove definition.
+
+Sun Sep 25 06:07:37 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove item about adding general multi-threaded stuff;
+ this is done.
+ Remove item about specifying arbitrary locations of stack frames
+ (this works on some machines).
+ Remove item about debugging functions without a frame pointer
+ (this works on some machines).
+ Remove item about re-writing macros which handle frame chaining and
+ frameless functions. They have been re-written at least once
+ since that item was written.
+ Remove item about gdb catching SIGINT when attached; this is done.
+ Remove item about having list_command not read symbols--why bother?
+
+Sat Sep 24 17:40:10 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * TODO: Append contents of Projects file.
+ * Projects: Remove.
+
+Sat Sep 24 01:47:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * corelow.c (add_solib_stub): Remove copying of to_sections,
+ pass current_target to SOLIB_ADD. The Sep 10 change failed
+ if SOLIB_ADD errored out, or if SOLIB_ADD was trying to access
+ target memory.
+ * corelow.c (core_open): After reading the shared libraries,
+ copy the modified to_sections vector from current_target to
+ core_ops, so that core_close can free it later.
+ * config/rs6000/nm-rs6000.h, rs6000-nat.c (xcoff_relocate_core):
+ Pass down target parameter from SOLIB_ADD and use it instead of
+ directly accessing core_ops.
+
+Fri Sep 23 14:58:49 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * solib.c: *BSD systems need <a.out.h> to be included before
+ <link.h>.
+
+ * i386b-nat.c: Add i386_float_info(), etc.
+ * config/i386/nm-nbsd.h: #define FLOAT_INFO.
+
+ * config/nm-nbsd.h: New file, for generic NetBSD native support.
+ * config/i386/nm-nbsd.h: Use it.
+ * config/sparc/nm-nbsd.h: Use it.
+ * config/ns32k/nm-nbsd.h: Use it.
+
+ * configure.in (i386-*-netbsd): Use config/i386/nbsd.m[ht].
+ (ns32k-*-netbsd): Use config/ns32k/nbsd.m[ht].
+ * config/i386/{nbsd.mh,nbsd.mt,nm-nbsd.h,tm-nbsd.h,xm-nbsd.h}:
+ New files, support for NetBSD/i386.
+ * config/ns32k/{nbsd.mh,nbsd.mh,nm-nbsd.h,tm-nbsd.h,xm-nbsd.h}:
+ New files, support for NetBSD/ns32k.
+
+Tue Sep 20 11:34:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * .gdbinit: Add list-objfiles command.
+
+ * TODO: Reword item regarding NO_STD_REGS.
+
+ * coffread.c (record_minimal_symbol, coff_read_enum_type,
+ coff_read_struct_type): Allocate on symbol_obstack, not directly
+ via malloc/savestring.
+
+Tue Sep 20 15:42:02 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * TODO: Add more items.
+ * tests: Remove the directory and all of its (obsolete) contents.
+
+Tue Sep 20 11:34:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (init_stringtab): When copying length to stringtab,
+ use target format, not host format, since that is what the rest of
+ the code assumes.
+
+Mon Sep 19 15:48:10 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * Makefile.in: Removed prelude.o, i386-nlmstub.o, nlmstub.o,
+ nlmstub.nlm, and nlmstub targets. Removed NWSOURCE and
+ NWINCLUDES definitions.
+ * i386-nlmstub.c: Removed.
+
+Mon Sep 19 07:48:36 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Cast bfd_asymbol_name to
+ char * (from const char *) before assigning. Don't save string we
+ pass to record_minimal_symbol (it already saves it).
+
+
+Sat Sep 17 02:26:58 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * cp-valprint.c (static_field_print): New variable, controls
+ printing of static members.
+ (_initialize_cp_valprint): New print set subcommand
+ "static-members". Turn on printing of static members by default.
+ (cp_print_value_fields): Print static members if necessary.
+
+ * solib.c: Remove inclusion of libelf.h and elf/mips.h.
+ (elf_locate_base): Use only standard BFD functions to collect
+ information about the .dynamic section. Check for DT_MIPS_RLD_MAP
+ tag only if it got defined via the inclusion of <link.h>.
+
+ * f-exp.y: Write block for OP_VAR_VALUE.
+ * f-valprint.c (info_common_command): Handle `info common'
+ without an argument correctly.
+
+ * c-typeprint.c (c_type_print_base): Handle template constructors.
+ * symtab.c (gdb_mangle_name): Handle template method mangling,
+ get rid of GCC_MANGLE_BUG code, which only applied to gcc-2.2.2.
+
+Fri Sep 16 16:06:08 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * gdbtypes.h (TYPE_INDEX_TYPE): New macro.
+ * ch-typeprint.c, ch-valprint.c: Use TYPE_INDEX_TYPE.
+ * ch-valprint.c (chill_val_print): Pass index type directly
+ (instead of its TYPE_TARGET_TYPE) to print_type_scalar.
+ * stabsread.c (read_type): Don't set TYPE_FLAG_TARGET_STUB
+ if the index type is a stub.
+
+Fri Sep 16 17:18:44 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/i386/{i386aix.mh, i386bsd.mh, i386lynx.mh, i386sco.mh,
+ i386sco4.mh, i386sol2.mh, i386v.mh, i386v32.mh, i386v4.mh,
+ ncr3000.mh, ptx.mh, ptx4.mh}, config/m68k/{altos.mh, apollo68v.mh,
+ delta68.mh, dpx2.mh, hp300bsd.mh, hp300hpux.mh, m68klynx.mh,
+ m68kv4.mh}, config/m88k/{delta88.mh, delta88v4.mh},
+ config/mips/riscos.mh, config/pa/hppahpux.mh,
+ config/rs6000/rs6000lynx.mh, config/sparc/{sparclynx.mh,
+ sun4sol2.mh}, config/tahoe/tahoe.mh, config/vax/{vaxbsd.mh,
+ vaxult.mh, vaxult2.mh} (REGEX, REGEX1, SYSV_DEFINE): No longer
+ define.
+ * config/i386/i386sco4.mh (MUNCH_DEFINE): No longer define.
+
+Fri Sep 16 15:40:34 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h (QUIT): Call interactive_hook to allow GUI to interrupt.
+ Also, add decl for symtab_to_filename.
+ * source.c (symtab_to_filename): New. Returns the file
+ associated with a symtab.
+ * top.c: Define interactive_hook. Called during QUIT to animate
+ the GUI.
+
+Fri Sep 16 00:14:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * stabsread.c (read_type): Handle stub types for bitstrings.
+ * stabsread.c (read_array_type): Check for stub domain type
+ using TYPE_FLAG_STUB, not its length.
+ * gdbtypes.c (create_set_type): Handle a stub domain type.
+
+ * ch-exp.y: Get rid of some extra non-terminals, and move
+ their rules into primitive_value.
+ * parser-defs.h: Add comment about unary postfix operators.
+ * ch-lang.c (chill_op_print_tab): Add '->', postfix and prefix.
+ * expprint.c (print_subexp): Recognize unary postfix operator.
+
+Wed Sep 14 18:27:42 1994 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * remote-hms.c: use remote_debug instead of hms_silent toggle.
+ Add warnings about depreciation of `snoop' cmd.
+
+Wed Sep 14 18:18:58 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote-hms.c (hms_read_inferior_memory): Cope when
+ target sends both \r and \n.
+
+Wed Sep 14 17:14:57 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * remote-mips.c (mips_error): Place NORETURN macro correctly.
+ * TODO: Add item about START_INFERIOR_TRAPS_EXPECTED.
+
+Wed Sep 14 14:26:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Fix obsolete comment about
+ mst_solib_trampoline.
+
+ * f-valprint.c (f_val_print): Change cast of valaddr from
+ CORE_ADDR * to char **, since that is how it is used.
+
+ * dbxread.c (read_dbx_dynamic_symtab): Save copy of symbol names
+ using obsavestring, and pass that to prim_record_minimal_symbol.
+ Having the objfile point to bfd_asymbol_name directly doesn't work
+ if we save and restore a mapped symbol file.
+
+
+Tue Sep 13 18:23:26 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * w89k-rom.c, op50-rom.c, monitor.c, config/pa/hppapro.mt: New files
+ to add a generic ROM monitor interface, and support file for the
+ WinBond W89K and the Oki OP50N PA based target boards.
+
+
+Sun Sep 11 22:34:57 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (REGISTER_NAMES): Use r26-r23 for arg0-arg3.
+
+Sun Sep 11 04:36:47 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * irix5-nat.c, osfsolib.c, solib.c (solib_add): Simplify last
+ change by replacing `symbols_added' with `so_last'.
+ * mdebugread.c (parse_external, parse_partial_symbols): Ignore
+ global common symbols, they will be resolved by the runtime loader.
+ * mdebugread.c (parse_symbol, parse_partial_symbols, cross_ref):
+ Handle scSCommon like scCommon symbols.
+
+Sat Sep 10 01:43:28 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * corelow.c (add_solib_stub): Copy to_sections changes from
+ core_ops to current_target after adding the shared libraries.
+ * partial-stab.h (N_EXCL), dbxread.c (add_old_header_file,
+ find_corresponding_bincl_psymtab): Change `repeated header not seen'
+ error to a complaint, simplify complaint.
+ * procfs.c (signalname, errnoname): Make `name' const.
+ * symfile.c (reread_symbols): Use filename from old BFD to
+ reopen the objfile.
+ * values.c (record_latest_value): Don't record value in the
+ history chain until we are sure there won't be an error.
+
+Fri Sep 9 15:52:09 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * nlm/Makefile.in: remove MMALLOC, READLINE, TERMCAP, and other
+ cruft.
+
+ * config/i386/gdbserve.mt: New file, defs for i386 nlm stub.
+
+Thu Sep 8 17:14:43 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote.c (fromhex): Make error more explicit.
+ (read_frame): Don't print bad checksum information unless
+ remote_debugging. Don't use repeat count unless it's > 0.
+ * remote-e7000.c (expect): When echoing, ignore multiple newlines.
+ (e7000_insert_breakpoint, e7000_remove_breakpoint, target_ops):
+ Optionally cope with BC style breakpoints.
+ (e7000_command): After command send directly to the E7000 mark
+ registers as changed.
+ (why_stop, e7000_wait: Understand BC style stop condition.
+ * sh-tdep.c (sh_skip_prologue): Understand more complicated
+ sequences. (frame_find_saved_regs): Likewise.
+ * config/h8500/tm-h8500.h (target_write_pc, TARGET_WRITE_PC):
+ Handle extra arg.
+ * config/i386/xm-go32.h (GDBINIT_FILENAME): Set to gdb.ini.
+ (more work here to come)
+ * config/sh/tm-sh.h (EXTRA_FRAME_INFO): Add f_offset and leaf_function
+ fields.
+
+Thu Sep 8 16:15:34 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * sparclite/Makefile.in: Assorted stuff needed for eload.
+
+ * sparclite/eload.c: Merge in command line argument parsing and
+ error message handling improvements orignally made to aload.c.
+
+Wed Sep 7 23:24:50 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * defs.h (enum misc_command_type, command_control_type): Enums
+ for describing the command and control types.
+ (struct command_line): Add new fields to keep track of the command
+ type and body associated with the command.
+ * top.c: Include value.h. Delete whitespace at the end of lines.
+ (build_command_line, get_command_line): New functions.
+ (execute_control_command, while_command, if_command): Likewise.
+ (realloc_body_list, read_next_line): Likewise.
+ (recurse_read_control_structure): Likewise.
+ (execute_user_command): Call execute_control_command.
+ (read_command_lines): Simplify by calling read_next_line, call
+ read_control_structure for "if" and "while" commands.
+ (free_command_lines): Free new fields in the command structure.
+ (define_command): Reset control_level to zero.
+ (init_main): Install command handlers for "if" and "while" commands.
+
+Tue Sep 6 16:24:07 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * c-typeprint.c (c_type_print_varspec_prefix,
+ c_type_print_varspec_suffix): Add cases for Fortran type codes.
+ * eval.c (evaluate_subexp): For OP_ARRAY expressions in Fortran,
+ call f77_value_literal_string instead.
+ * f_exp.y: Include <string.h>, move include of parser-defs.h.
+ (parse_number): Translate 'd' floats to 'e' so atof() works.
+ (yylex): Remove unused variables.
+ * f-lang.c: Include <string.h>.
+ (get_bf_for_fcn): Remove unused variable.
+ * f-typeprint.c (f_type_print_varspec_prefix,
+ f_type_print_varspec_suffix): Remove unused
+ variables, add cases to switch statements.
+ (f_type_print_base): Remove unused variables.
+ * f-valprint.c (gdbcore.h, command.h): Include.
+ (f77_get_dynamic_lowerbound, f77_get_dynamic_upperbound):
+ Call read_memory_integer with correct number of arguments.
+ (f77_get_dynamic_upperbound): Call f77_get_dynamic_lowerbound
+ with correct argument type.
+ (f77_print_array): Removed unused array array_size_array.
+ (f_val_print): Don't use a CORE_ADDR as a char *.
+ * valops.c (value_cast): Handle COMPLEX and BOOL types.
+ (value_assign): Handle Fortran literal string and complex values.
+ (f77_cast_into_complex, f77_assign_from_literal_string,
+ f77_assign_from_literal_complex): New functions.
+
+Mon Sep 5 14:46:41 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-typeprint.c (chill_type_print_base): Make TYPE_CODE_RANGE
+ case more robust.
+
+Sun Sep 4 16:06:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * i960-tdep.c (signal.h): Don't include.
+
+ * cxux-nat.c (target_is_m88110): Remove definition.
+
+ * configure.in (config/nm-empty.h): If cross only, use instead
+ of config/nm-trash.h.
+ * config/nm-trash.h: Remove.
+ * config/nm-empty.h: New file.
+ * config/i386/nm-m3.h: New file, includes config/nm-m3.h.
+ * config/mips/nm-m3.h: New file, includes config/nm-m3.h.
+ * config/m68k/nm-sysv4.h: New file, includes config/nm-sysv4.h.
+ * config/mips/nm-sysv4.h: New file, includes config/nm-sysv4.h.
+ * config/sparc/nm-sysv4.h: New file, includes config/nm-sysv4.h.
+
+
+Fri Sep 2 17:35:55 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * configure.in: No longer look for nm, tm, and xm headers in
+ config/<header>; they are always in config/<cpu>/<header>.
+
+Fri Sep 2 16:40:03 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * objfiles.c (allocate_objfile): Add the newly-created objfile to
+ the end of the list of objfiles, instead of at the beginning.
+
+ * xcoffread.c (allocate_include_entry): New function, abstracted
+ from code in record_include_begin.
+ (record_include_begin, record_include_end): Call it.
+
+ * blockframe.c (reinit_frame_cache): Test inferior_pid instead of
+ target_has_stack to decide whether to create a real stack frame
+ for the cache.
+
+ * coffread.c (process_coff_symbol) [CXUX_TARGET]: Ignore vendor
+ section.
+ * config/m88k/tm-cxux.h (CXUX_TARGET): Define.
+
+ * h8300-tdep.c: Include "dis-asm.h" instead of <dis-asm.h>.
+
+Fri Sep 2 09:51:46 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * config/sparc/tm-nbsd.h: Add #defines to map NetBSD struct and
+ field names into what is expected by sparc-nat.c.
+
+Thu Sep 1 17:32:54 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * c-typeprint.c (c_typedef_print): Add missing Chill support.
+
+Thu Sep 1 15:41:21 1994 Stu Grossman (grossman@cygnus.com)
+
+ * rs6000-pinsn.c (print_insn): Use powerpc disassembler when
+ doing Power PC.
+ * config/powerpc/tm-ppc-nw.h: Define GDB_TARGET_POWERPC.
+
+ * config/i386/i386lynx.mh, config/m68k/m68klynx.mh,
+ config/rs6000/rs6000lynx.mh, config/sparc/sparclynx.mh: Enable
+ ser-tcp.
+
+ * nlm/Makefile.in: Get rid of NWSOURCE.
+ * nlm/alpha-io.S (inVti, outVti): Remove extraneous ldha's.
+ * nlm/gdbserve.o: Add dummy __main routine.
+ * nlm/gdbserve.def: Turn on debug.
+
+Thu Sep 1 12:36:39 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/xm-nbsd.h: Don't define SET_STACK_LIMIT_HUGE; it is obsolete.
+
+Thu Sep 1 11:01:40 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * config/tm-nbsd.h: New file, support for all NetBSD targets.
+ * config/xm-nbsd.h: fix typo.
+ * config/sparc/{nm,tm,xm}-nbsd.h: New files, renamed from
+ {nm,tm,xm}-sparcnbsd.h to conform to prefered file naming
+ conventions.
+ * configure.in: (sparc-*-netbsd): use config/sparc/nbsd.m[ht].
+
+Wed Aug 31 14:40:33 1994 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * remote-udi.c (udi_read_inferior_memory,udi_write_inferior_memory):
+ change typeo in error msg (`inferrior' -> `inferior').
+
+Wed Aug 31 09:17:02 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * inflow.c (set_sigint_trap, clear_sigint_trap): Check for
+ attach_flag (this check was performed by the callers). Also check
+ inferior_thisrun_terminal.
+ * inftarg.c (child_wait), lynx-nat.c (child_wait),
+ procfs.c (wait_fd), symm-nat.c (child_wait): Don't check
+ attach_flag in deciding whether to call set_sigint_trap and
+ clear_sigint_trap.
+
+ * value.h (struct value): Change literal_data from PTR to char *,
+ since that is the way it is used.
+
+Tue Aug 30 21:56:54 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c (som_symfile_read): Force unwinds to be re-read after
+ reading in a new partial symbol table.
+
+Tue Aug 30 13:14:16 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/h8500/tm-8500.h (DONT_USE_REMOTE): Remove definition,
+ an obsolete conditional.
+ * config/pa/tm-hppa.h (BREAKPOINT) [KERNELDEBUG]: Remove use,
+ an obsolete conditional.
+ * config/rs6000/rs6000.mh, config/rs6000/rs6000.mt: Clean up
+ comments.
+
+Mon Aug 29 14:39:42 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (ns32k-opcode.h): Remove reference.
+ (ns32k-pinsn.o): Update dependencies.
+ * ns32k-opcode.h: Remove file.
+ * ns32k-pinsn.c (print_insn): Call version in libopcodes, remove
+ all other code in this file.
+
+Mon Aug 29 12:04:07 1994 Stu Grossman (grossman@cygnus.com)
+
+ * nlm/configure.in: Stop using cpu.c. Put it in TDEPFILES instead.
+ * config/alpha/gdbserve.mt (TDEPFILES): Remove alpha-patch.o.
+
+ * nlm/Makefile.in: Add rule for .S.o.
+ * nlm/aio.h: Protect from multiple inclusions.
+ * nlm/alpha-io.S: Remove everything we don't need.
+ * nlm/{alpha-patch.c, alpha-patch.h, alpha-uart.c, alpha-uart.h}:
+ Remove, no longer needed.
+ * nlm/alpha.c: Merge in lots of stuff from previous files.
+ * nlm/alpha.h: Don't #include alpha-patch.h. Make
+ breakpoint_insn extern.
+ * Move stuff from alpha-patch.h into here.
+
+ * config/alpha/gdbserve.mt (TDEPFILES): Get rid of alpha-uart.o.
+
+Mon Aug 29 11:34:34 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * annotate.c (annotate_starting): Flush output.
+
+Sat Aug 27 23:32:43 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symfile.c (symbol_file_add): Move reinit_frame_cache call to
+ the callers of symbol_file_add. Gets rid of heuristic fence-post
+ warnings on mips and alpha targets when the PC resides in a shared
+ library which is not yet read in.
+ * coff-solib.c (coff_solib_add), cxux-nat.c (add_shared_symbol_files),
+ irix5-nat.c (solib_add), osfsolib.c (solib_add),
+ remote-vx.c (vx_open), solib.c (solib_add):
+ Add call to reinit_frame_cache after all shared libraries are read in.
+ * remote-udi.c (udi_load), remote-vx.c (vx_load_command),
+ symfile.c (symbol_file_command, add_symbol_file_command):
+ Add call to reinit_frame_cache after symbol_file_add.
+
+Wed Aug 24 17:45:14 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * config/xm-nbsd.h: New file, support for all NetBSD ports.
+ * config/sparc/{nm-sparcnbsd.h,tm-sparcnbsd.h,xm-sparcnbsd.h,
+ sparcnbsd.mh,sparcnbsd.mt}: New files, support for NetBSD/sparc.
+ * configure.in: Add sparc-*-netbsd target.
+
+Wed Aug 24 13:17:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * remote-vx.c (vx_attach): Interpret the command argument as an
+ unsigned long.
+
+Wed Aug 24 13:08:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * configure.in: Change i[34]86 to i[345]86.
+ * nlm/configure.in: Likewise.
+ * gdbserver/configure.in: Likewise.
+
+Wed Aug 24 09:41:09 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * configure.in (i386-*-netware): Automatically configure nlm
+ subdir.
+
+Tue Aug 23 17:51:13 1994 J.T. Conklin (jtc@cygnus.com)
+
+ * nlm/gdbserve.c: conditionalize header file inclusion for either
+ NetWare 4.0 or PIN targets.
+ * nlm/i386.c: include appropriate header files.
+ * nlm/prelude.c: define TERMINATE_BY_UNLOAD for NetWare 4.0
+ targets.
+
+Tue Aug 23 16:54:16 1994 Stu Grossman (grossman@cygnus.com)
+
+ * nlm/ppc.c (set_step_traps clear_step_traps): Cleanups.
+ * nlm/gdbserve.def: Autoload clib.
+
+Tue Aug 23 12:05:19 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * breakpoint.c (condition_command): Call breakpoints_changed.
+
+ * gdbtypes.h: Declare f77_create_literal_string_type and
+ f77_create_literal_complex_type.
+ * valops.c (f77_value_literal_string, f77_value_substring,
+ f77_value_literal_complex): Use xmalloc not malloc.
+ * valops.c (f77_value_literal_string, f77_value_substring):
+ Make addr char * not CORE_ADDR.
+ * value.h (struct value): Add new field literal_data of aligner union.
+ (VALUE_LITERAL_DATA): Use it.
+ * f-lang.h: Declare find_common_for_function.
+ * value.h, valops.c: Split VALUE_SUBSTRING_START into memaddr and
+ myaddr fields of a union. Don't overload it with the frame field
+ (not sure this is necessary; I'm not sure what lval_* codes
+ VALUE_SUBSTRING_* can be used with).
+
+Mon Aug 22 11:45:01 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/a29k/{a29k-kern.mt,a29k-udi.mt,a29k.mt,ultra3.mh,
+ ultra3.mt}: Clean up comments, remove no-longer-used definitions.
+
+ * rs6000-nat.c: Include libbfd.h again, needed until reference
+ to bfd_cache_lookup is cleaned out.
+
+ * config/i386/linux.mh (XM_CLIBS): Add -lm.
+
+Mon Aug 22 10:42:15 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ Work to reduce the interrupts-off duration when running in DOS.
+ * ser-go32.c: (dos_async_ready): See if anything is in the buffer.
+ (dos_async_rx): rewrite to unpack as many characters from the
+ asynctsr as possible into a local buffer.
+
+Fri Aug 19 14:55:45 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Initial Fortran language support, adapted from work by Farooq Butt
+ (fmbutt@engage.sps.mot.com).
+ * Makefile.in: Add Fortran-related files and dependencies.
+ * defs.h (language_fortran): New language enum.
+ * language.h (_LANG_fortran): Define.
+ (MAX_FORTRAN_DIMS): Define.
+ * expression.h: Reformat to standard.
+ (MULTI_F77_SUBSCRIPT, OP_F77_UNDETERMINED_ARGLIST,
+ OP_F77_LITERAL_COMPLEX, OP_F77_SUBSTR): New expression opcodes.
+ * gdbtypes.h (TYPE_CODE_COMPLEX, TYPE_CODE_LITERAL_COMPLEX,
+ TYPE_CODE_LITERAL_STRING): New type codes.
+ (type): New fields upper_bound_type and lower_bound_type.
+ (TYPE_ARRAY_UPPER_BOUND_TYPE, TYPE_ARRAY_LOWER_BOUND_TYPE,
+ TYPE_ARRAY_UPPER_BOUND_VALUE, TYPE_ARRAY_LOWER_BOUND_VALUE): New
+ macros.
+ (builtin_type_f_character, etc): Declare.
+ * value.h (VALUE_LITERAL_DATA, VALUE_SUBSTRING_START): Define.
+ * f-exp.y: New file, Fortran expression grammar.
+ * f-lang.c: New file, Fortran language support functions.
+ * f-lang.h: New file, Fortran language support declarations.
+ * f-typeprint.c: New file, Fortran type printing.
+ * f-valprint.c: New file, Fortran value printing.
+ * eval.c (evaluate_subexp): Add code for new expression opcodes,
+ fix wording of error message.
+ * gdbtypes.c (f77_create_literal_complex_type,
+ f77_create_literal_string_type): New functions.
+ * language.c (set_language_command): Add Fortran info.
+ (calc_f77_array_dims): New function.
+ * parse.c (length_of_subexp, prefixify_subexp): Add cases for new
+ expression opcodes.
+ * symfile.c (deduce_language_from_filename): Recognize .f and .F
+ as Fortran source files.
+ * valops.c (f77_value_literal_string, f77_value_substring,
+ f77_value_literal_complex): New functions.
+
+Fri Aug 19 13:35:01 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-typeprint.c (c_print_type): Assume demangled arguments
+ if a '(' is found in varstring, looking for ')' at the end of
+ varstring did fail with demangled const member functions, which
+ have a trailing `const'.
+ * remote.c (get_offsets, putpkt): Change to `char' buffers,
+ to avoid errors when compiling with DEC c89.
+ (remote_wait): Cast to `char *' before passing buffer to
+ fputs_filtered, to avoid errors when compiling with DEC c89.
+ (remote_wait): Do not return inferior_pid by default, this
+ statement is never reached, which causes warnings from some
+ compilers.
+ * stabsread.c (scan_file_globals): Ignore static minimal symbols.
+ * symfile.c (load_command): If called with no argument, try
+ to get the filename from the executable file.
+ (generic_load): Remove check for NULL filename, it is done
+ in load_command now.
+
+Fri Aug 19 10:36:15 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * Makefile.in (ALLDEPFILES): Add hpread.c.
+ (hpread.o): Add dependencies.
+
+ * somread.c: Do not include "aout/aout64.h". SOM has nothing to
+ do with a.out.
+ (BYTES_IN_WORD): Delete.
+ (som_symfile_read): Call hpread_build_psymtabs to build any
+ minimal symbols based on the HP C native debug symbols.
+ (som_symfile_finish): Call hpread_symfile_finish.
+ (som_symfile_init): Call hpread_symfile_init.
+ * config/pa/tm-hppa.h (HPREAD_ADJUST_STACK_ADDRESS): Define.
+ * hppa-tdep.c (hpread_adjust_stack_address): New function.
+
+ * config/pa/hppabsd.mh (NATDEPFILES): Add hpread.o
+ * config/pa/hppahpux.mh (NATDEPFILES): Likewise.
+ * hpread.c: New file.
+
+Fri Aug 19 00:40:55 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_trampoline_code): Revert incorrect change
+ from June 2, 1994 (what was I thinking?!?). Fix it right this
+ time.
+
+Thu Aug 18 17:01:35 1994 J.T. Conklin (jtc@rtl.cygnus.com)
+
+ * nlm/i386.c, nlm/i386.h: New files that contain i386 specific code.
+
+Thu Aug 18 14:39:46 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * README: Grammar improvements, clarifications, updates.
+
+Wed Aug 17 23:08:53 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (TARGET_FLAGS_TO_PASS): Pass down LD_FOR_TARGET and
+ NLMCONV_FOR_TARGET. (SUBDIRS): Add nlm target.
+ * configure.in (powerpc-*-netware*): Automatically configure nlm
+ subdir.
+ * nlm/Makefile.in: Add {CC NLMCONV LD}_FOR_TARGET. Remove alpha
+ specific stuff. Make things more configurable.
+ * nlm/configure.in: Add powerpc-*-netware* target. Use
+ gdbserve.mt/cpu.c/cpu.h for target stuff. Get rid of tm/xm/nm.h
+ files.
+ * nlm/gdbserve.c: Move Alpha specific stuff into other files.
+ Remove lots of architecture-specific stuff.
+ * nlm/gdbserve.def: Add new imports.
+ * nlm/ppc.c, nlm/ppc.h: New files that contain PowerPC specific code.
+ * nlm/prelude.c: Don't include libhooks.h, get rid of call to
+ register library.
+ * nlm/prelude.o: What was this doing here?
+ * config/alpha/gdbserve.mt: Defs for alpha nlm stub.
+ * config/powerpc/gdbserve.mt: Defs for PowerPC nlm stub.
+ * config/powerpc/ppc-nw.mt: Defs for PowerPC target for GDB.
+ * config/powerpc/tm-ppc-nw.h: Ditto.
+
+ * nlmstub.def: New file, contains imports for 386 nlm stub.
+
+Wed Aug 17 23:17:33 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * remote-pa.c: New file for HPPA embedded support. Currently it's
+ a copy of remote.c.
+ * config/pa/hppabsd.mt,hppahpux.mt,hppaosf.mt: User remote-pa.c.
+
+Wed Aug 17 13:19:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/m68k/tm-delta68.h (EXTRACT_RETURN_VALUE,
+ STORE_RETURN_VALUE): Define to use %a0 for pointers.
+
+Wed Aug 17 07:43:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-mips.c: Remove unused declaration of mips_load.
+
+Tue Aug 16 16:45:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * coffread.c: General cleanup, and support for section offsets.
+ (time.h, sys/types.h, libbfd.h): Don't include.
+ (cur_src_start_addr, cur_src_end_addr): Rename to
+ current_source_start_addr, current_source_end_addr.
+ (nlist_stream_global): Remove.
+ (nlist_bfd_global): New global variable.
+ (coff_symfile_read): Remove code that gets and uses fileno()
+ directly.
+ (read_coff_symtab, enter_linenos, process_coff_symbol): Add
+ section_offsets parameter, add text/data section offset to
+ appropriate symbols' values.
+ (read_one_sym): Use bfd_read instead of fread.
+ (init_stringtab, init_lineno): Change first parameter to a bfd,
+ use bfd routines instead of raw I/O.
+
+Tue Aug 16 15:24:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.c (decode_line_1): If funfirstline and we get a
+ non-LOC_BLOCK symbol (e.g. variable or type), then error().
+
+ * Makefile.in (TARFILES, NONSRC, SFILES_STAND, SFILES_KGDB):
+ Remove; unused.
+ (TAGFILES_NO_SRCDIR): Remove ALLPARAM.
+ (HFILES_NO_SRCDIR): Remove all files in config sub-directory.
+ (TAGS): Also pass result of find on config sub-directory to etags.
+ (ALLPARAM): Remove; now unused.
+
+Sun Aug 14 13:05:26 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.13.1
+ * NEWS, README: Update to match gdb 4.13 release version.
+
+Sat Aug 13 08:22:50 1994 Fred Fish (fnf@cygnus.com)
+
+ Harris CX/UX support, from Bob Rusk (rrusk@mail.csd.harris.com).
+ * cxux-nat.c: Remove dangling #else block.
+ (m88k_harris_core_register_addr): New function.
+
+ * environ.c (init_environ): If no environment, do nothing.
+
+Fri Aug 12 19:30:53 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Delete rest of TODO list. Do not include "libbfd.h",
+ <time.h>, <sys/types.h>, "demangle.h", <sys/file.h>,
+ "expression.h", "language.h", "gdbtypes.h", "demangleh".
+ Move all global variables into the private symbol table structure
+ and add accessor macros. Update some comments.
+ (hpread_build_psymtabs): Delete dbsubc_addr, we don't need it.
+ (hpread_end_psymtab): New function to end a partial symbol table,
+ all callers changed (no more bogus sharing with dbxread.c).
+
+Fri Aug 12 15:52:37 1994 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (remote_wait): Return inferior_pid instead of 0 for
+ `W` message.
+
+Fri Aug 12 11:47:10 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * sparclite/aload.c (sys_error, error): Use vfprintf for variable
+ argument lists.
+
+Thu Aug 11 04:06:42 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * defs.h (concat, basename, buildargv, freeargv, strerrno, strsigno,
+ errno_max, signo_max, strtoerrno, strtosigno): Delete.
+ Include "libiberty.h" instead.
+
+Wed Aug 10 13:23:47 1994 Rick Sladkey (jrs@world.std.com)
+
+ * i386v-nat.c (i386_insert_nonaligned_watchpoint):
+ add additional argument specifying raw address to permit
+ proper release of debug registers.
+ (i386_insert_watchpoint, i386_insert_aligned_watchpoint):
+ change all callers.
+
+Wed Aug 10 16:13:45 1994 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h, top.c: Use `extern' in declarations of GUI hooks, and
+ define them in top.c. Add comments to the hooks.
+
+Wed Aug 10 15:57:43 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.c (gdbsim_ops): Set `to_insert_breakpoint' and
+ `to_remove_breakpoint' fields.
+
+Wed Aug 10 15:46:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c (run_command): Remove comment suggesting using
+ target_has_execution instead of inferior_pid.
+
+Wed Aug 10 10:33:20 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-mips.c (mips_open): add code to handle baud rate.
+
+Tue Aug 9 09:44:42 1994 Stu Grossman (grossman@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Call target_resume() upon
+ detection of new processes.
+
+ * procfs.c (create_procinfo): Return pointer to new procinfo
+ structure.
+ * (do_detach): Spacing & formatting cleanup.
+ * (procfs_wait): Move wait_again label to ensure that we really
+ wait again. On exit from fork, release new child from gdbs'
+ clutches.
+ * (procfs_set_sproc_trap): Enable trapping of fork and vfork.
+
+Mon Aug 08 15:34:13 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_process_one_debug_symbol): Fix block scoping
+ problem (losing localvars on the close-brace instead of after
+ the close brace).
+
+Mon Aug 8 15:09:32 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * i386-nlmstub.c (handle_exception): Wait until the thread has
+ been started before killing the NLM by pointing the PC at
+ _exit().
+
+Sat Aug 6 22:27:30 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-irix5.h (IN_SIGTRAMP): Redefine for Irix 5,
+ Irix 5 has a standard _sigtramp signal handler.
+ * irix5-nat.c (solib_add): Get rid of sigtramp_address handling,
+ it is not needed for a standard _sigtramp signal handler.
+ Add shared library sections to the section table of the target
+ before adding the symbols.
+ * mips-tdep.c (mips_skip_prologue): Do not skip load immediate
+ instructions that do not prepare a stack adjustment.
+ * regex.c (SIGN_EXTEND_CHAR): Update to emacs-19.25 definition,
+ which does the right thing on machines where `char' is unsigned.
+
+Fri Aug 5 17:50:59 1994 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (remote_open): Move setting of inferior_pid prior to
+ call to remote_start_remote. Also use unique value for pid to
+ avoid confusion with read_register_pid & friends.
+ * (remote_wait): Return inferior_pid instead of 0 in all cases.
+
+Fri Aug 5 12:23:02 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * dwarfread.c (bfd.h): Don't include.
+
+Fri Aug 5 09:08:34 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * i386-nlmstub.c (handle_exception): Point the PC at _exit() to
+ kill the program being debugged. KillMe(), the undocumented
+ call intended for this purpose, causes the server to hang.
+
+Thu Aug 4 16:26:06 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote.c (read_frame): Calculate run length encoded checksum
+ correctly.
+ * config/sh/stub.c: New file.
+
+Thu Aug 4 14:34:12 1994 Stu Grossman (grossman@cygnus.com)
+
+ * target.c (find_default_run_target): Make sure to_can_run is set
+ before calling it.
+
+Thu Aug 4 11:46:27 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * TODO: Remove note about fast watchpoints and remove obsolete
+ Mach stuff.
+
+Thu Aug 4 11:08:03 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/i386/xm-i386v4.h, config/m68k/xm-m68kv4.h,
+ config/sparc/xm-sun4sol2.h (NORETURN): Don't define.
+ * config/m88k/tm-cxux.h (ARCH_NUM_REGS): Undefine before defining.
+
+Thu Aug 4 10:26:36 1994 Stu Grossman (grossman@rtl.cygnus.com)
+
+ * target.c (add_target): Don't call clean_target on target
+ vectors anymore.
+ * (unpush_target): Test for to_close being set before calling.
+ * (target_xfer_memory, target_info): Check for to_has_memory
+ before playing with memory.
+
+ * remote.c (remote_open): Set inferior_pid to make kill command
+ happy.
+ * inflow.c (kill_command): Revert change of Aug 2. Use
+ inferior_pid to determine whether to print out "The program is not
+ being run." message.
+
+Thu Aug 4 07:55:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/i386m3.mh (NAT_CLIBS): Add -lmachid and -lnetname.
+ * m3-nat.c, config/nm-m3.h: #if 0 REQUEST_QUIT stuff.
+ * m3-nat.c: Pass argument to return_to_top_level.
+ Declare m3_kill_inferior before use.
+ (port_chain_insert): In "can't happen" case, abort rather than
+ setting `mid' to large decimal constant (which gcc warns about).
+ (get_thread_name): Use cast to convert const char * to char *.
+ (add_mach_specific_commands): #if 0 "thread break" command.
+ (m3_trace_him): Call push_target.
+ (mach_really_wait): New argument pid; remove unused
+ variable pid.
+ (intercept_exec_calls): Call target_terminal_init and
+ target_terminal_inferior once the child execs.
+ * infrun.c (proceed): Pass argument to PREPARE_TO_PROCEED.
+
+Wed Aug 3 22:41:13 1994 Tom Lord (lord@x1.cygnus.com)
+
+ * procfs.c (procfs_mourn_inferior): don't dereference the
+ procinfo pointer after it has been freed.
+
+Wed Aug 3 12:05:13 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Improve pluralization in display
+ of breakpoint hit counts.
+
+ * language.h (struct language_defn): Remove unused field
+ la_longest_float.
+ (longest_float): Remove, no longer used.
+ * language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn): Remove init of la_longest_float field.
+ * c-lang.c (c_language_defn, cplus_language_defn,
+ asm_language_defn): Ditto.
+ * ch-lang.c (chill_language_defn): Ditto.
+ * m2-lang.c (m2_language_defn): Ditto.
+
+Tue Aug 2 10:58:34 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * defs.h (bfd_read, bfd_seek): Remove declarations.
+ * os9kread.c, rs6000-nat.c (libbfd.h): Don't include.
+
+Tue Aug 2 09:50:50 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * inflow.c (kill_command): Fix a bug which prevented target
+ programs to be killed.
+
+Mon Aug 1 18:48:47 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * defs.h: Change two-line declarations to one-line form.
+ (NORETURN): Define as "volatile" only for older GCCs.
+ (ATTR_NORETURN): Define for newer GCCs.
+ * procfs.c (proc_init_failed): Add ATTR_NORETURN to declaration.
+
+Mon Aug 1 16:43:24 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (mention), main.c (fputs_unfiltered): Add comments.
+ * breakpoint.c (delete_breakpoint, enable_breakpoint,
+ disable_breakpoint): Don't call breakpoints_changed; it is now
+ called via the *_breakpoint_hook functions.
+ * annotate.c (_initialize_annotate, breakpoint_changed): New functions.
+
+Mon Aug 1 13:38:04 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * stabsread.c (read_type): Fix a bug in enum size calculation.
+
+Mon Aug 1 01:36:13 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (compare_unwind_entries): Add "const" to both
+ argument types to shut up GCC.
+
+ * hppa-tdep.c (saved_pc_after_call): If the saved PC is in a
+ linker stub, then return the address the stub will return to.
+ (frame_saved_pc): Correctly restart the search for the saved
+ pc when a linker stub is encountered.
+
+ * hppa-tdep.c (inst_saves_gr): Handle 16 and 8 bit instruction
+ register stores emitted by the version 9 HP compilers.
+ (inst_saves_fr): Relax test for a specific base register (%r1);
+ this avoids losing with the version 9 HP compilers.
+ (skip_prologue): Try to skip argument stores emitted by the HP
+ compilers. It's not perfect, but it's better than before.
+
+Fri Jul 29 23:20:30 1994 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (write_pc write_pc_pid): Remove casts to long when
+ calling write_register_pid.
+ * (write_register_pid): Add prototype.
+
+Fri Jul 29 21:56:23 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * remote.c (read_frame): Split readchar/checksum calculation into
+ two parts since evaluation order is undefined.
+
+Fri Jul 29 13:46:08 1994 Fred Fish (fnf@cygnus.com)
+
+ From Kevin A. Buettner (kev@cujo.geg.mot.com).
+ * Makefile.in (coredep.o): Add inferior.h as dependency.
+ * inflow.c: Add F_SETOWN to list of defines to check
+ around code that uses F_SETOWN.
+
+Fri Jul 29 09:59:05 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): If using newlib,
+ set the -L and -B directory prefixes so we can link with it.
+
+Thu Jul 28 14:37:36 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (INSTALLED_LIBS, CLIBS, DEPFILES): Add support for
+ --enable-xxx configure option by adding ENABLE_{CLIBS DEPFILES}
+ where appropriate.
+
+ * General hackery to support alternate user-interface.
+ * breakpoint.c (mention, delete_breakpoint, enable_breakpoint,
+ disable_breakpoint): Call hooks for alternate user-interface.
+ * defs.h: Add declarations for alternate user-interface hooks.
+ * main.c (main): Add --nw (and --nowindows) options to disable
+ the GUI.
+ * (near call to command_loop): Call command_loop_hook if set.
+ * (fputs_unfiltered): Call fputs_unfiltered_hook if set.
+ * stack.c: Call print_frame_info_listing_hook if set.
+ * top.c (gdb_init): Initialize targets.c and utils.c prior to
+ other files to make sure that calls to error and warning will
+ work. Call init_ui_hook after everything else.
+ * utils.c (query): Call query_hook if set.
+ * (gdb_flush): Call flush_hook if set.
+ * Change _initialize_utils to initialize_utils cuz we don't use
+ automatic initialization of utils.c anymore.
+
+
+ * remote.c: Get rid of #ifdef DONT_USE_REMOTE. It's no longer
+ necessary.
+
+Thu Jul 28 14:52:01 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Use newlib if it is
+ there and we are using the gcc from the tree.
+ (LD_FOR_TARGET): Look for ld in ../ld/ld.new.
+
+Thu Jul 28 10:43:36 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (annotate.o): Add dependencies.
+
+Wed Jul 27 14:34:42 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * sparclite/aload.c: Added new -q (quiet) option.
+ return 0 exit status if file was successfully downloaded.
+
+ * nlm/gdbserve.c: merge in command line argument parsing changes
+ and bug fixes made to i386-nlmstub.c.
+
+ * i386-nlmstub.c: The returnLength field must be initialized
+ before portConfig is passed to AIOGetPortConfiguration.
+ Compare command line arguments with strnicmp(); args are
+ case insensitive on netware.
+
+Wed Jul 27 09:24:19 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (DISTSTUFF): Add definition.
+ (diststuff): Add for new distribution support.
+ (gdb.tar.Z, make-proto-gdb.dir, setup-to-dist,
+ gdb-$(VERSION).tar.Z, make-proto-gdb-1, make-proto-testsuite.dir):
+ Remove old distribution building rules, now uses standard
+ distribution support in parent directory Makefile.in.
+
+Tue Jul 26 14:15:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c (push_target): Cast result from xmalloc.
+
+Tue Jul 26 18:20:46 1994 Paul Flinders (ptf@smee)
+
+ * elfread.c (elf_symtab_read): Discard compiler labels generated
+ by the Solaris 2.1/Intel SunPro compiler.
+
+Mon Jul 25 18:19:24 1994 Stu Grossman (grossman@cygnus.com)
+
+ * target.c (nomemory): Fix prototype and routine to take correct
+ args.
+
+Mon Jul 25 15:38:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (clean): Remove libgdb-files.
+
+Mon Jul 25 11:50:57 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * coredep.c: Include inferior.h.
+
+Mon Jul 25 11:36:02 1994 J.T. Conklin (jtc@phishhead.cygnus.com)
+
+ * i386-nlmstub.c: Add support for NODE, PORT and BAUD command
+ line arguments.
+
+Sat Jul 23 14:36:09 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * symfile.c (deduce_language_from_filename): Recognize .S as asm,
+ .cp as C++, alphabetize better.
+
+ * breakpoint.c (ignore, condition): Move usage note into body of
+ help text, so first line can be one-line summary.
+
+Sat Jul 23 00:58:15 1994 Stu Grossman (grossman@cygnus.com)
+
+ * target.c (unpush_target): Fix handling of removal of top target.
+
+Fri Jul 22 17:30:39 1994 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in: Add stuff to build nlmstub.
+ * Add rule for annotate.o to keep Sun make happy.
+ * configure.in: Add config for powerpc/Netware.
+
+ * partial-stab.h (near N_SO): Don't call START_PSYMTAB with null
+ filename. This speeds up handling of trailing N_SO stabs (they
+ mark the end of a .o file).
+
+ * target.c, target.h: Change the way pushing and popping of
+ targets work to support target overlays and inheritance.
+ * corelow.c, hppa-tdep.c, inflow.c, remote-nindy.c, utils.c:
+ Fixup references to current_target, due to previous changes.
+
+ * config/i386/tm-i386nw.h: Enable longjmp support. More work is
+ needed to get the address of longjmp out of the target.
+
+Tue Jul 19 13:25:06 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * main.c: Include <ctype.h>.
+
+Mon Jul 18 15:32:17 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-mips.c (mips_readchar): Fix a bug in checking <IDT>
+ prompt.
+
+Mon Jul 18 14:26:35 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * solib.c (look_for_base): Don't deref exec_bfd if NULL.
+
+Sun Jul 17 15:38:36 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.12.4.
+
+Sun Jul 17 12:20:35 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Harris CX/UX support, from Bob Rusk (rrusk@mail.csd.harris.com).
+ * configure.in (m88*-harris-cxux*): New configuration.
+ * cxux-nat.c, config/m88k/cxux.mh, config/m88k/cxux.mt,
+ config/m88k/xm-cxux.h, config/m88k/tm-cxux.h, config/m88k/nm-cxux.h:
+ New files.
+ * config/m88k/tm-m88k.h: Add comment about Harris OS.
+ (TARGET_WRITE_PC): Pass pid through to register writers.
+
+ * configure.in (m68*): Put vendor-only-specified host configs
+ after vendor-and-os-specified configs.
+ (m68*-atari-sysv4*, m68*-cbm-sysv4*): Replace with m68*-*-sysv4.
+
+ * config/m88k/delta88.mh (MUNCH_DEFINE): Remove.
+ * config/m88k/delta88.mt, config/m88k/delta88v4.mh: Format
+ consistently.
+
+Sat Jul 16 23:39:17 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * elfread.c (elf_symtab_read): Handle error return from
+ bfd_get_dynamic_symtab_upper_bound gracefully.
+
+Sat Jul 16 14:43:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * inferior.h (ARCH_NUM_REGS): New macro, actual number of
+ registers in use by the inferior.
+ * coredep.c (fetch_core_registers, register_addr): Use it.
+ * findvar.c (registers_changed, registers_fetched,
+ read_register_bytes): Ditto.
+ * infcmd.c (do_registers_info, registers_info): Ditto.
+ * infptrace.c (fetch_inferior_registers,
+ store_inferior_registers): Ditto.
+ * stack.c (frame_info): Ditto.
+
+ * coredep.c (CORE_REGISTER_ADDR): New macro.
+ (fetch_core_registers): Use it.
+
+ * breakpoint.c (ignore, condition): Add usage notes to help strings.
+ * symfile.c (add-symbol-file): Add usage note to help string.
+ (add_shared_symbol_files_command): New command.
+
+ gcc -Wall lint.
+ * inferior.h (read_pc_pid): Declare.
+ * breakpoint.c (watchpoint_check): Cache breakpoint in local
+ variable b, remove unused variable other_type_used.
+ * main.c (inferior.h, call-cmds.h): Include.
+ (gdb_init): Declare.
+ * remote.c (remote_wait): Return 0 by default.
+
+Fri Jul 15 16:43:33 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Stop printing at null char option, from Oliver Meyer
+ (omeyer@i3.informatik.rwth-aachen.de).
+ * valprint.h, valprint.c (stop_print_at_null): New global.
+ * valprint.c (_initialize_valprint): New print set subcommand
+ "null-stop".
+ * c-valprint.c (c_val_print): If stop_print_at_null is on, and
+ printing a char array, adjust the number of chars to print.
+
+Fri Jul 15 14:33:40 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ From Kevin A. Buettner (kev@cujo.geg.mot.com).
+ * m88k-tdep.c (examine_prologue): Modified to handle prologues for
+ pic code in addition to prologues where an instruction from the
+ prologue gets moved into the delay slot of a branch instruction
+ immediately following the prologue. A table of potential prologue
+ instructions (prologue_insn_tbl) is now used for picking apart a
+ function prologue.
+ (frame_find_saved_regs): Changed the way in which limit gets set
+ so that the delay slot of branch instructions immediately
+ following the prologue gets examined.
+ (pushed_size, store_parm_word, store_parm, push_parameters,
+ collect_returned_value): Deleted.
+
+Fri Jul 15 01:06:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Handle stepping into leaf
+ functions whose prologue consists of gp loading code only.
+
+Thu Jul 14 14:22:12 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * dbxread.c: Don't include libbfd.h.
+ * dwarfread.c, elfread.c somread.c: Don't include libbfd.h,
+ <time.h>, or <sys/types.h>.
+ * elfread.c (elf_symfile_read): Use only standard BFD functions to
+ collect information about the stab and stab string sections.
+
+Thu Jul 14 13:17:39 1994 Kung Hsu (kung@x1.cygnus.com)
+
+ * stabsread.c (read_huge_number): handle large unsigned number
+ for stabs generated by os9k C compiler.
+
+Wed Jul 13 18:58:15 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Breakpoint hit counts, from Bob Rusk (rrusk@mail.csd.harris.com).
+ * breakpoint.h (hit_count): New breakpoint field.
+ * breakpoint.c (show_breakpoint_hit_counts): New variable.
+ (clear_breakpoint_hit_counts): New function.
+ (bpstat_stop_status): Increment the hit count.
+ (breakpoint_1): Display the hit count.
+ * infcmd.c (run_command): Reset breakpoint hit counts.
+ * target.c (generic_mourn_inferior): Don't clear ignore counts if
+ displaying hit counts.
+
+Tue Jul 12 12:23:15 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * elfread.c (elf_symfile_read): Unconditionally add dynamic
+ symbols for all symbol files. Makes skipping over the
+ trampoline code work when stepping from a function in a shared
+ library into a function in a different shared library for Irix 5.
+ Other ELF targets do not have enough information in their
+ dynamic symbol tables to make this work.
+ (elf_symtab_read): Relocate mst_solib_trampoline address.
+
+Mon Jul 11 16:38:49 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Atari support, from Uwe Seimet (seimet@chemie.uni-kl.de).
+ * configure.in (m68*-atari-sysv4*): New configuration.
+ (m68*-cbm-sysv4*): Use m68kv4 instead of amix.
+ * m68k-tdep.c (R_PS): Define as R_SR if necessary.
+ * config/m68k/m68kv4.mh, config/m68k/m68kv4.mt,
+ config/m68k/tm-m68kv4.h, config/m68k/xm-m68kv4.h: New files.
+ * config/m68k/amix.mh, config/m68k/amix.mt,
+ config/m68k/tm-amix.h, config/m68k/xm-amix.h: Removed, superseded
+ by m68kv4 files.
+
+Sat Jul 9 16:28:43 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (find_function_start_sal): New function to find
+ the start of a function from a function symbol.
+ (decode_line_1, decode_line_2): Use it instead of open coded
+ partial copies of the code.
+ (list_symbols): Quote symbol name before passing it to
+ break_command to enable proper handling of mangled symbols.
+
+Wed Jul 6 20:22:07 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y (match_simple_name_string): Don't lower-case here.
+ * ch-exp.y (yylex): First try name lookup using exact name
+ typed by user; if that fails, try lower-cased name.
+
+Wed Jul 06 12:39:07 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: More cleanups. Delete lots of trailing whitespace.
+ Remove some items from the TODO list and notes throughout code
+ for things which need fixing. Add more comments.
+ Document bogus struct symloc sharing with dbxread.c. Delete more
+ useless variables. Add more PARAM prototypes. Fixup more
+ indention problems that have crept in.
+ (SET_NAMESTRING): Accept new namep and objfile arguments so that
+ it doesn't depend on the variable names on the procedures it's
+ used from.
+ (hpread_symfile_init): Delete incorrect checks for bogus sizes of
+ the debug sections.
+
+Wed Jul 6 00:48:57 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c, elfread.c, mipsread.c, nlmread.c, os9kread.c:
+ Move "no debugging symbols found" test to symfile.c.
+ * symfile.c (syms_from_objfile, reread_symbols): Add
+ "no debugging symbols found" test.
+ * coffread.c (init_stringtab): Handle stripped files with a
+ stringtab offset of zero gracefully.
+ * osfsolib.c (solib_create_inferior_hook): Use DYNAMIC flag from
+ BFD instead of stop_pc heuristic to determine if it is a dynamically
+ linked object file.
+ * procfs.c (wait_fd): Handle ENOENT error return from PIOCWSTOP
+ ioctl, it indicates that the process has exited.
+
+Mon Jul 04 19:48:03 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_symfile_init): Make sure to initialize all the
+ private data to zero. Not having any HP C debug symbols is not an
+ error. Just return.
+
+Mon Jul 4 19:28:56 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (read_unwind_info): ELF unwind information is in the
+ .PARISC.unwind section now.
+
+Mon Jul 4 17:06:26 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * breakpoint.c (mention): Always show breakpoint address if no
+ source file.
+
+Sat Jul 2 01:51:33 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * solib.c (bfd_lookup_symbol, look_for_base): Reinstate to reenable
+ handling of shared libraries for non-ELF executables, but only if
+ HANDLE_SVR4_EXEC_EMULATORS is defined.
+ (locate_base): Try to find debug_base in the dynamic linker
+ for non-ELF executables if HANDLE_SVR4_EXEC_EMULATORS is defined.
+ * config/sparc/tm-sun4sol2.h (HANDLE_SVR4_EXEC_EMULATORS):
+ Define to enable handling of shared libraries for a.out executables,
+ run under Solaris BCP.
+
+Fri Jul 01 19:50:21 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c: Change contribution notice to the Cygnus/Utah agreed
+ upon notice. Delete some stuff from the TODO list. Rework
+ many comments to be clearer. Major cleanups. Consistently
+ use "hpread_" prefix. Delete unnecessary macros, structures
+ variables, fiels, functions and #if 0 code. Mark code which
+ still needs to be cleaned up. PARAMize and make most functions
+ static. Fix error checking when reading in the debug section
+ contents. No more minimal symbol table handling in this code!
+
+Thu Jun 30 13:59:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Print "Program exited normally"
+ regardless of batch_mode.
+ * defs.h, top.c (batch_mode): Removed.
+
+Wed Jun 29 18:53:36 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (dcache_h): Remove redundant definition.
+ (init.c): Add a comment.
+ (top.c): Remove explicit compile action.
+ * breakpoint.c (mention): Share code indicating location of
+ break/watchpoints, don't print address if addressprint is off.
+ * breakpoint.c, c-typeprint.c, c-valprint.c, energize.c, symtab.h
+ (demangle): Remove redundant declarations.
+ * eval.c: Remove redundant function declarations.
+ * objfiles.h: Cosmetic and grammatical improvements.
+ * TODO: Various updates.
+
+ * remote-mips.c: Replace all \r chars with \015.
+ (mips_receive_header): Display control characters readably.
+ (mips_xfer_memory): Add a simple progress display.
+
+Wed Jun 29 13:11:45 1994 Steve Chamberlain (sac@cirdan.cygnus.com)
+
+ * remote-e7000.c (e7000_open): Don't try a tcp open if we're
+ using go32.
+ * remote-hms.c (flush): New function.
+ (expect): Get edge case right.
+ (hms_read_inferior_memory): Be more tolerant of line noise.
+
+Tue Jun 28 14:17:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * configure.in: Use i386m3.mh and i386m3.mt as names of host and
+ target files, not non-existent mach3.mh and mach3.mt.
+
+Wed Jun 29 00:26:17 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (dbx_symfile_read): Unconditionally add dynamic
+ symbols for all symbol files. Makes skipping over the
+ trampoline code work when stepping from a function in a shared
+ library into a function in a different shared library.
+ (read_dbx_dynamic_symtab): Relocate mst_solib_trampoline address.
+
+Tue Jun 28 15:28:01 1994 Stu Grossman (grossman@cygnus.com)
+
+ * dbxread.c, partial-stab.h (near N_SO): SO stabs with blank
+ names mean end of .o file.
+ * infrun.c (wait_for_inferior): Clean up multi-thread logic near
+ top of routine. Handle new thread notification cleanly.
+ * lynx-nat.c (child_wait): General cleanups, handle new LynxOS
+ thread notification scheme.
+ * (child_resume): General cleanups, handle resumption of all
+ threads properly.
+
+Mon Jun 27 09:57:23 1994 Steve Chamberlain (sac@cirdan.cygnus.com)
+
+ * ser-go32.c: Rewrite to run under windows.
+ * ser-e7kpc.c: New file to support the E7000 with the PC ISA
+ bus interface.
+ * serial.c (serial_open): Notice device "pc".
+ * remote-e7000.c: Fix copyright date.
+ (expect): Compare \n and \r the same.
+ (e7000_open): Allow pc as a serial port
+ * sh/sh.mt: Add ser-e7kpc.
+ * h8300/h8300hms.mt: Add ser-e7kpc.
+ * main.c (proc_wait): Don't wait if using go32.
+
+Mon Jun 27 00:35:51 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c: Simplify by using stabsect_build_psymtabs.
+ * dbxread.c (stabsect_build_psymtabs): New argument "text_name"
+ corresponding to the name of the text section. All references
+ changed.
+ (somstab_build_psymtabs): Delete function, no longer needed.
+
+Sun Jun 26 23:54:08 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c: Renamed from paread.c. Changed function names and
+ comments to reflect that this file deals with SOM (an object file
+ format), rather than the PA (a cpu).
+ (Makefile.in): Chaned appropriately.
+ (config/pa/hppabsd.mh, config/pa/hppahpux.mh): Likewise.
+ * dbxread.c (somstab_build_psymtabs): Renamed from
+ pastab_build_psymtabs.
+
+Fri Jun 24 08:15:42 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * core-sol2.c: New file to handle ELF and BCP core file flavours.
+ * config/sparc/sun4sol2.mh (NATDEPFILES): Use it instead of
+ core-svr4.
+ * Makefile.in: Updated for core-sol2.c.
+ * README: Add notes about SPARCworks cc under Solaris 2.x,
+ from Casper H.S. Dik (casper@fwi.uva.nl).
+ * config/mips/xm-makeva.h: Removed, no longer necessary.
+ * Makefile.in, config/mips/xm-irix3.h, config/mips/xm-irix5.h,
+ config/mips/xm-mips.h, config/mips/xm-news-mips.h,
+ config/mips/xm-riscos.h: Remove references to xm-makeva.h
+
+Wed Jun 22 17:48:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdba.el: Put program input and output in a separate buffer.
+
+Wed Jun 22 16:54:15 1994 Fred Fish (fnf@cygnus.com)
+
+ * energize-patches, main.c (main), top.c (gdb_init, pwd_command),
+ top.h: Change all occurances of dirbuf to gdb_dirbuf. Collides
+ with global variable of same name in libnsl.so on UnixWare.
+
+Wed Jun 22 14:40:52 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * symtab.c (decode_line_1): fix a bug in dealing with '<>'
+ embedded in template name.
+
+Tue Jun 21 14:06:46 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * config/i386/nm-linux.h: change calling convention of
+ TARGET_CAN_USE_HARDWARE_WATCHPOINT() and
+ target_insert_watchpoint() and
+ target_remove_watchpoint().
+
+ * config/mips/tm-mips64.h: define FORCE_LONG_LONG to force LONGEST
+ to be long long in gdb.
+ * config/mips/tm-bigmips.h: ditto.
+
+Mon Jun 20 23:54:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * c-lang.c (asm_language_defn): New definitions for language_asm,
+ mostly copied from c_language_defn, to avoid warnings when
+ switching between c and asm stack frames.
+
+Mon Jun 20 13:51:55 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mdebugread.c (parse_symbol): Don't call ecoff_swap_tir_in or
+ ecoff_swap_rndx_in directly; use the debug_swap pointer instead.
+ (upgrade_type, handle_psymbol_enumerators): Likewise.
+ (has_opaque_xref, cross_ref): Likewise.
+ (elfmdebug_build_psymtabs): Call swap->read_debug_info to read
+ debugging information, rather than doing it here.
+ * mipsread.c (mipscoff_symfile_read): Call read_debug_info entry
+ point in ecoff_debug_swap backend structure, rather than calling
+ ecoff_slurp_symbolic_info directly.
+
+Fri Jun 17 20:58:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c: Include annotate.h. Call annotate_field rather
+ than printing annotation directly.
+
+ * main.c: Include string.h.
+
+Thu Jun 16 14:41:37 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * fork-child.c (startup_inferior) [STARTUP_INFERIOR]: If defined,
+ call it instead of doing normal loop.
+ * infcmd.c (attach_command): Don't call wait_for_inferior if
+ running Mach 3.
+ * infrun.c (proceed) [PREPARE_TO_PROCEED]: If defined, call
+ hook that can decide whether to step over the next breakpoint.
+ * utils.c (wrap_here): Abort if wrap_buffer not allocated.
+ (request_quit) [REQUEST_QUIT]: If defined, call it instead of
+ doing normal quit.
+
+ * configure.in: Improve sorting/formatting of hosts and targets.
+ (i[34]86-*-mach3*, i[34]86-*-osf1mk*, mips-*-mach3*,
+ m88*-*-mach3*, ns32k-*-mach3*): Recognize.
+ * Makefile.in (stop-gdb): New target.
+ * stop-gdb.c: New file, utility to get attention of waiting GDBs
+ in Mach 3.
+
+Wed Jun 15 00:41:03 1994 Tom Lord (lord@rtl.cygnus.com)
+
+ * top.c (gdb_init): Init current_directory in gdb_init. Probably
+ the identical initialization can be deleted from main.c, but i
+ haven't done so just in case.
+
+Tue Jun 14 17:24:41 1994 Tom Lord (lord@x1.cygnus.com)
+
+ * gdba.el: Added menu windows and slightly improved window
+ handling to gdba.el. Fixed numerous minor bugs that were causing
+ emacs and gdb to fall out of sync.
+
+Tue Jun 14 16:18:44 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * breakpoint.c: annotate changes lost at merge, put back in.
+
+Mon Jun 13 17:28:50 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config/i386/i386sco.mh, i386sco4.mh (XDEPFILES): Remove
+ i387-tdep.o.
+
+Sun Jun 12 03:51:52 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/m68k/dpx2.mh (NATDEPFILES): Remove duplicate inclusion
+ of inftarg.o.
+ * config/m68k/tm-dpx2.h (CANNOT_STORE_REGISTER): Define to inhibit
+ writing of floating registers, the dpx2 kernel disallows it.
+ * irix5-nat.c (LM_ADDR): The loaded address of the shared library
+ is contained in o_praw.
+ * irix5-nat.c (solib_map_sections): Adjust sections by the
+ difference between the loaded address and the prelinked address.
+ * irix5-nat.c (solib_address): Use LM_ADDR for the loaded start
+ address.
+ * mdebugread.c (parse_symbol): Do not relocate stEnd/scText
+ symbols, their value is absolute.
+ * mdebugread.c (parse_partial_symbols): Handle Irix 5.2 shared
+ libraries fh->adr fields of zero. Relocate minimal symbol values
+ upon readin. Relocate non-stabs symbols upon readin.
+ * mdebugread.c (psymtab_to_symtab_1): Use pst->textlow for the
+ start address of the outermost block.
+ * mdebugread.c (parse_lines, parse_procedure): Pass in pst
+ instead of section_offsets and use relocated pst->textlow for
+ line number and procedure address relocations.
+
+ From gmo@MicroUnity.com (Guillermo A. Loyola):
+ * mdebugread.c (parse_symbol, parse_partial_symbols, cross_ref):
+ Handle SGI Irix5 stIndirect symbol type.
+
+Fri Jun 10 14:52:56 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * breakpoint.c: fix a syntax error native cc does not like.
+
+ * Makefile.in: change sparclite-tdep.c to sparcl-tdep.c.
+ * sparclite/Makefile.in: ditto.
+ * sparcl-tdpe.c: change file name because first 8 chars has to be
+ unique.
+ * sparcl-stub.c: ditto.
+
+ * sparclite/Makefile.in: fix INCLUDE_CFLAGS to have {srcdir}/../config.
+
+Fri Jun 10 10:38:15 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (target_read_pc, target_write_pc): Accept (and
+ ignore) a PID argument.
+ (hppa_pop_frame): Pass a PID to target_write_pc.
+ * config/pa/tm-hppa.h (TARGET_READ_PC, TARGET_WRITE_PC): Accept
+ and pass through a PID argument.
+ (target_read_pc, target_write_pc): Update prototypes.
+
+Thu Jun 9 18:10:44 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * Makefile.in: add new file sparclite-tdep.c.
+ * sparclite/Makefile.in: add new file sparclite-stub.c.
+ * sparclite/hw_breakpoint.note: note for SPARClite hardware breapoint
+ support.
+ * config/sparc/sparclite.mt: add sparclite-tdep.o.
+ * config/sparc/tm-sparclite.h: add hardware breakpoints support
+ defiines and code.
+ * sparclite-tdep.c: new file, contains hardware breakpoint support
+ code.
+ * sparclite-stub.c: new file, stub code that add support hardware
+ breakpoint support.
+ * breakpoint.c: add hardware breakpoint support.
+ * breakpoint.h: add new breakpoint type to support hardware
+ breakpoint.
+ * config/mips/nm-irix4.h: change interface for target dependent
+ code supporting watch point.
+ * config/pa/nm-hppab.h: change interface for target dependent
+ code supporting watch point.
+
+Thu Jun 9 14:59:58 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-os9k.c (rombuf_command): fix a bug accepting rombug
+ output.
+ * stabsread.c (read_struct_fields): os9k nested structure does not
+ have terminating ';', instead it just get to ',' and bit position
+ and length.
+
+Wed Jun 8 23:20:45 1994 Stu Grossman (grossman@cygnus.com)
+
+ * nlmread.c (nlm_symtab_read): Clean up a bit.
+ * (nlm_symfile_read): Record bounds of main() so that backtrace
+ command will know where to stop.
+ * objfiles.c (objfile_relocate): Relocate entry point/func info
+ for backtrace as well.
+ * objfiles.h: Define values for invalid PCs for entry point info.
+ * symfile.c (init_entry_point_info): Initialize invalid values
+ with aforementioned macros.
+ * config/alpha/tm-alphanw.h: Turn on FRAME_CHAIN_VALID_ALTERNATE
+ to cause backtrace to stop when it gets back to main().
+ * config/i386/tm-i386nw.h: Ditto.
+
+Sat Jun 4 18:17:03 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Fix value_print, which used to be ostensibly language-independent,
+ but would print pointers and arrays in C syntax. Instead, call
+ a language-specific function.
+ * language.h (struct language_defn): New functional field
+ la_value_print.
+ (LA_VALUE_PRINT): New macro.
+ * language.c (unk_lang_value_print): New stub/dummy function.
+ (unknown_language_defn, auto_language_defn, local_language_defn):
+ Use it.
+ * c-valprint.c (c_value_print): New function, with code moved from:
+ * valprint.c (value_print): ... here. Now just invoke
+ LA_VALUE_PRINT to do language-specific stuff.
+ * valprint.c (value_print_array_elements): Make non-static.
+ * c-lang.c (c_language_defn, cplus_language_defn): Add
+ c_value_print in the la_value_print field.
+ * m2-lang.c (m2_language_defn): Likewise.
+ * ch-lang.c (chill_language_defn): But here use chill_value_print.
+ * ch-valprint.c (chill_val_print): Print null pointer as NULL.
+ * ch-valprint.c (chill_value_print): New function, based on
+ c_value_print, but use Chill "look and feel."
+ * c-lang.h (c_value_print): New prototype.
+ * ch-lang.h (chill_value_print): New prototype.
+ * value.h (value_print_array_elements): New prototype.
+
+ * ch-valprint.c (chill_val_print, case TYPE_CODE_BITSTRING
+ and case TYPE_CODE_SET): Check that the element type isn't a stub.
+
+Fri Jun 3 09:15:00 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c: Move entire file except for #ifndef MAIN_OVERRIDE code
+ to new file top.c. Make things extern instead of static and
+ similar rearrangements to deal with this.
+ * top.h: New file.
+ * utils.c: Move fputs_unfiltered to main.c. Remove
+ FPUTS_UNFILTERED_OVERRIDE ifndef.
+ * Makefile.in: Change so that gdb uses main.c, utils.c, and top.c,
+ and libgdb uses utils.c and top.c.
+
+Thu Jun 2 23:19:10 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_trampoline_code): Fix typo.
+
+Thu Jun 2 18:09:59 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-valprint.c (chill_val_print_array_elements): New function.
+ A Chill version of val_print_array_elements, it prints the
+ array index labels, in additions ot the array element values.
+ (chill_val_print): Use the new function.
+
+Thu Jun 2 08:50:00 1994 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Add nlm subdir to configdirs for alpha-*-netware
+ target.
+ * defs.h (enum language): Add language_asm.
+ * findvar.c (read_register_bytes read_register_gen
+ write_register_bytes read_register read_register_pid
+ write_register write_register_pid supply_register): Move multi-
+ thread handling down into these routines. Create XXX_pid routines
+ that allow register references to specify the pid.
+ * findvar.c infcmd.c (read_pc read_pc_pid write_pc write_pc_pid
+ read_sp write_sp read_fp write_fp): Move these routines from
+ infcmd to findvar to centralize the whole mess.
+ * i386-nlmstub.c: Portability fixes.
+ * infptrace.c (child_resume): Conditionalize to allow other natives
+ to override it. Remove PIDGET gubbish, it's no longer necessary.
+ * infrun.c (wait_for_inferior): Put registers_changed() before
+ target_wait() to speed up remote debugging.
+ * Replace code that reads registers from other threads with much
+ nicer looking new function calls (see changes to findvar.c).
+ * Don't skip prologues if debugging assembly source.
+ * lynx-nat.c (child_resume): Lynx now needs it's own version of
+ child_resume to handle multi-thread debugging properly.
+ * remote.c: Add O response to get console output from target.
+ * (readchar): Add timeout parameter. Handle SERIAL_EOF and
+ SERIAL_ERROR here to simplify callers.
+ * Change static var timeout to remote_timeout.
+ * (fromhex): Remove unnecessary return -1 at end of routine.
+ * (remote_wait): Turn this into a big switch statement. Add
+ support for O response.
+ * (putpkt): Remove unnecessary handling of SERIAL_EOF/ERROR.
+ * (getpkt): Split getpkt into two parts. read_frame deals with
+ all formatting issues, run-length encoding, and framing. getpkt
+ now handles error recovery, and frame detection.
+ * ser-tcp.c (tcp_readchar): Handle EINTR from read().
+ * ser-unix.c (hardwire_raw): Set CLOCAL so that we ignore modem
+ control. (hardwire_readchar): Handle EINTR from read().
+ * symfile.c (deduce_language_from_filename): Add support for .s
+ files.
+ * config/nm-lynx.h: Define CHILD_WAIT so that lynx-nat.c can
+ override infptrace's child_wait.
+ * config/rs6000/rs6000lynx.mh: Use xm-rs6000ly.h & nm-rs6000ly.h
+ instead of XXXlynx.h.
+ * config/rs6000/rs6000lynx.mt: Use tm-rs6000ly.h instead of
+ tm-rs6000lynx.h.
+ * nlm/gdbserve.c: Portability fixes.
+
+Tue May 31 20:35:44 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * inftarg.c (child_wait): Call proc_wait, not wait.
+ (child_mourn_inferior): Call proc_remove_foreign.
+ * main.c (gdb_init): Call init_proc.
+ * main.c: Provide dummy versions of init_proc, proc_wait, and
+ proc_remove_foreign for the gdb case (the libgdb case provides its
+ own versions of these functions).
+ * Makefile.in (libgdb-files): Add libproc.a.
+
+Wed Jun 1 11:08:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ Hardware watchpoints for Linux, from Rick Sladkey
+ (jrs@world.std.com).
+ * infrun.c (wait_for_inferior) [HAVE_CONTINUABLE_WATCHPOINT]: Add
+ new hardware breakpoint recovery method.
+ * i386v-nat.c (i386_insert_watchpoint,
+ i386_insert_nonaligned_watchpoint, i386_remove_watchpoint,
+ i386_stopped_by_watchpoint) [TARGET_CAN_USE_HARWARE_WATCHPOINT]:
+ New functions to support the 386 hardware debugging registers.
+ * config/i386/nm-linux.h (TARGET_CAN_USE_HARDWARE_WATCHPOINT,
+ HAVE_CONTINUABLE_WATCHPOINT, STOPPED_BY_WATCHPOINT,
+ target_insert_watchpoint, target_remove_watchpoint): Define these
+ macros to use the hardware debugging functions in i386v-nat.c.
+
+Wed May 25 17:06:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Replace libgdb.a with libgdb-files. Make "all"
+ build it.
+
+Thu May 19 09:56:20 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c, target.h: New variables target_activity_function and
+ target_activity_fd.
+ * inflow.c, inferior.h: New functions set_sigio_trap and
+ clear_sigio_trap.
+ * inftarg.c (child_wait), procfs.c (wait_fd): Call them.
+
+Wed May 18 13:01:55 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * remote-sim.h (sim_verbose): Delete.
+ Document callbacks needed.
+ (sim_*): Change result to void where there isn't one.
+ (sim_open): Clarify argument and error response.
+ (sim_close): Declare.
+ (sim_load): Change bfd_handle argument to file name. Clarify result.
+ (sim_create_inferior): Renamed from sim_set_args.
+ (sim_set_pc): Delete.
+ (sim_info): Delete printf_fn argument.
+ * remote-sim.c (gdbsim_kill): Add comment describing purpose.
+ (gdbsim_load): Try sim_load first.
+ (gdbsim_create_inferior): Call sim_create_inferior.
+ (gdbsim_open): Handle args == NULL. Update call to sim_open.
+ (gdbsim_close): Call sim_close.
+ (gdbsim_files_info): Update call to sim_info.
+ (gdbsim_ops): Realign comments.
+
+ * printcmd.c (decode_format): Allow TARGET_PTR_BIT to be non-constant.
+
+Tue May 17 16:45:20 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): For C_FILE symbols, only use
+ the auxent if the symbol's name is ".file". From David Edelsohn
+ <c1dje@watson.ibm.com>.
+
+Tue May 17 11:08:22 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Fix typo.
+
+ * annotate.c (annotate_field_end): Fix typo.
+
+ * Makefile.in: Move annotate.o from COMMON_OBS to OBS.
+
+ * Makefile.in (TSSTART): Remove; no longer used.
+
+ * utils.c (vfprintf_maybe_filtered, vfprintf_unfiltered): Call
+ fputs_unfiltered and exit directly, rather than fatal. The latter
+ calls vfprintf_unfiltered!
+
+ * gdbtypes.h, gdbtypes.c (can_dereference): New function.
+ * value.h, printcmd.c (print_value_flags): Move from here...
+ * annotate.c: ...to here, and make it use can_dereference.
+
+Sat May 14 15:13:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * inflow.c (job_control, attach_flag, generic_mourn_inferior):
+ Remove, needed for both native and cross.
+ * target.c (attach_flag, generic_mourn_inferior): Put here.
+ * utils.c (job_control): Put here.
+ (terminal.h): Don't include anymore.
+
+Sat May 14 09:11:44 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * source.c (find_source_lines): Always use code that was #ifdef
+ BROKEN_LARGE_ALLOCA. Do the cleanup before returning, rather than
+ leaving it on the chain. Reindent much of this function.
+ * config/sparc/{xm-sun4sol2.h,xm-sun4os4.h},
+ config/i386/{xm-sun386.h,xm-i386m3.h,xm-i386mach.h},
+ config/m68k/{sun3os4.h,xm-news.h,xm-hp300hpux.h},
+ config/ns32k/xm-ns32km3.h: Remove all references to
+ BROKEN_LARGE_ALLOCA; with the above change it is no longer needed.
+ * main.c, fork-child.c, many config files: Remove all
+ SET_STACK_LIMIT_HUGE code; with the above changes it should no
+ longer be needed.
+
+ * symtab.c (lookup_partial_symbol): Use if and abort, not assert.
+ This avoids __eprintf troubles.
+
+Fri May 13 08:10:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (main): Surround in #ifndef MAIN_OVERRIDE. Move
+ initialization code which needs to be called even if we bypass the
+ command line stuff into gdb_init.
+ * utils.c (fputs_unfiltered): Surround in #ifndef
+ FPUTS_UNFILTERED_OVERRIDE.
+ * Makefile.in (libgdb.a): New target.
+
+ * utils.c: Rearrange I/O stuff a bit so that all output goes
+ through fputs_unfiltered. Use vasprintf; removes arbitrary limit
+ which made %s not work with arbitrarily large strings.
+ * printcmd.c (printf_command): Use printf_filtered, not
+ printf_unfiltered and printf, now that arbitrary limit is gone.
+
+ gcc -Wall lint:
+ * breakpoint.c (watchpoint_check): Remove unused variable b.
+ * stack.c (print_frame_info): Move sp and buf inside #if.
+ * eval.c (evaluate_subexp): Remove unused variables pp,
+ mangle_ptr, ptr, and mangle_tstr.
+ * valarith.c (value_x_binop): Remove unused variables mangle_tstr
+ and mangle_ptr.
+ * symtab.c (lookup_symtab): Put variable copy inside #if.
+ (decode_line_1): Put variable q1 inside #if 0.
+ * target.h: Declare target_link.
+ * infrun.c (wait_for_inferior): Remove unused variables signame.
+ * remote.c (remote_resume): Remove unused variable name.
+ * c-exp.y (parse_number): Parenthesize operand of shift.
+ * dbxread.c (record_minimal_symbol): Parenthesize operand of &&
+ (this is a semantic change, the warning seems to have detected a bug).
+ * dbxread.c (end_psymtab): Move variable p1 inside #if.
+ * coffread.c: Move variable temptype inside #if.
+ * ch-typeprint.c (chill_type_print_base): Remove unused variable
+ name.
+ * ch-valprint.c: #include typeprint.h and ch-lang.h.
+ (chill_val_print): Remove unused variable in_range.
+ (chill_val_print): Remove statement "length > TYPE_LENGTH (type);".
+ (chill_val_print): Add default case for switch.
+ * stabsread.h: Declare stabsect_build_psymtabs.
+ * os9kread.c (read_minimal_symbols): Make this return void.
+ (os9k_symfile_read): Remove unused variables stb_exist and val.
+ (os9k_symfile_init): Remove unused variable val.
+ (fill_sym): Remove unused variable id.
+ (read_os9k_psymtab): Put variable back_to inside #if 0. Remove
+ unused variable nsl.
+ Remove unused variable symfile_bfd.
+ #if 0 unused variables lbrac_unmatched_complaint and
+ lbrac_mismatch_complaint.
+ Remove declaration for non-existent function os9k_next_symbol_text.
+
+ * annotate.c, annotate.h: New files, containing a function for
+ each annotation which outputs it.
+ * Move breakpoints_changed from breakpoint.c to annotate.c.
+ * breakpoint.c, blockframe.c, infrun.c, cp-valprint.c, main.c,
+ printcmd.c, source.c, stack.c, utils.c, valprint.c:
+ Use annotate.c functions to output annotations.
+ * Makefile.in (OBS): Add annotate.o.
+
+Thu May 12 10:46:27 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (read_unwind_info): Make sure elf_unwind_size and
+ elf_unwind_entries are always initialized.
+
+ * hppa-tdep.c (skip_trampoline_code): Handle argument relocation
+ stubs which return directly to the caller rather than to the stub
+ itself.
+
+Wed May 11 20:11:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * c-exp.y (yyerror): Display a more informative error message.
+ * ch-exp.y (yyerror): Ditto, don't use global yychar.
+ * m2-exp.y (yyerror): Ditto.
+
+Tue May 10 11:57:53 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * inflow.c (job_control): Move definition to front of file.
+
+Tue May 10 14:42:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * maint.c (print_section_table): Rename SEC_SHARED_LIBRARY to
+ SEC_COFF_SHARED_LIBRARY to match corresponding change in bfd.
+
+Fri May 6 13:30:22 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (kdb): Remove old init.c creation commands.
+ * configure.in (sparclite): Match on sparclite*.
+ * sparclite/aload.c (main): Only change section addresses for
+ a.out format object files.
+
+Fri May 6 13:24:04 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * config/i386/go32.mh: Define CC.
+
+Fri May 6 11:56:54 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbserver/Makefile.in: Remove irrelevant definitions and
+ comments inherited from the gdb Makefile.
+ (BFD_DIR, BFD, BFD_SRC, BFD_CFLAGS): Add from gdb Makefile.
+ (VERSION): Update to 4.12.3.
+ (gdbserver): Remove any existing executable first.
+ (distclean, realclean): Remove nm.h.
+ * gdbserver/low-lynx.c: Add Sparc Lynx support.
+ * gdbserver/low-sparc.c, gdbserver/low-sun3.c (sys/wait.h):
+ Don't use absolute pathname.
+
+Thu May 5 12:00:22 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * rs6000-nat.c (vmap_ldinfo): Don't fail if fstat returns an
+ error.
+
+Wed May 4 06:56:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (proceed, normal_stop, wait_for_inferior), breakpoint.c
+ (print_it_normal): Add annotations for the inferior starting and
+ stopping, and for all the various messages related to how it
+ stopped.
+
+ * printcmd.c (do_one_display): Annotate.
+ * stack.c (print_frame_info): Annotate printing of stack frames.
+
+Wed May 4 18:15:51 1994 Stu Grossman (grossman@cygnus.com)
+
+ * remote.c (get_offsets): Handle case where stub doesn't support
+ qOffsets message.
+
+Wed May 4 15:30:39 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ Add partial support for g++ code compiled with -fvtable-thunks.
+ * c-valprint.c (c_val_print): Add vtblprint support
+ when using thunks.
+ * cp-valprint.c (cp_is_vtbl_member): A vtable can be an array of
+ pointers (if using thunks) as well as array of structs (otherwise).
+ * cp-valprint.c (vtbl_ptr_name_old, vtbl_ptr_name): Move to global
+ level, and make the latter non-static (so define_symbol can use it).
+ * stabsread.c (define_symbol): If the type being defined is a
+ pointer type named "__vtbl_ptr_type", set the TYPE_NAME to that name.
+ * symtab.h (VTBL_PREFIX_P): Allow "_VT" as well as "_vt".
+ * values.c (value_virtual_fn_field): Handle thunks.
+ * values.c (value_headof): Minor efficiency hack.
+ * values.c (value_headof): Incomplete thunk support. FIXME.
+
+Wed May 4 06:56:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valprint.c (print_longest): Clarify comment about use_local.
+ * printcmd.c, defs.h (print_address_numeric), callers in
+ symmisc.c, symfile.c, stack.c, source.c, remote.c, infcmd.c,
+ cp-valprint.c, core.c, ch-valprint.c, c-valprint.c, breakpoint.c,
+ exec.c: New argument use_local.
+ * source.c (identify_source_line): Use filtered output. Use
+ print_address_numeric.
+
+ * core.c (memory_error), symtab.c (cplusplus_hint, decode_line_1),
+ language.c (type_error, range_error): Use filtered output.
+ * utils.c (error_begin): Update comment to tell people to use
+ filtered output.
+
+ * Makefile.in (HFILES_WITH_SRCDIR): List bfd.h.
+ (HFILES_NO_SRCDIR): List gdbcore.h not gdbcore_h, so as not to get
+ bfd.h.
+
+Tue May 3 07:41:33 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * procfs.c (procfs_wait): Reinstate code which deduces the signal
+ from the fault, #ifndef FAULTED_USE_SIGINFO.
+ * config/sparc/tm-sun4sol2.h: Define FAULTED_USE_SIGINFO.
+
+Fri Apr 29 18:15:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Annotate each field of the headers.
+ Explicitly annotate each record.
+
+Fri Apr 29 15:56:18 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * xcoffexec.c: Reformat to standards and lint.
+ (language.h): Include.
+ (exec_close): Declare arg "quitting".
+ (file_command): Declare arg "from_tty".
+ (map_vmap): Cast xmalloc result to PTR.
+ * rs6000-nat.c: Reformat to standards and lint.
+ (exec_one_dummy_insn): Use char array for saved instruction.
+ (fixup_breakpoints): Declare.
+ (vmap_ldinfo): Be more informative in fatal error messages.
+ (xcoff_relocate_symtab): Define to return void.
+ * xcoffsolib.h: Reformat to standards, improve comments.
+ * config/rs6000/nm-rs6000.h (xcoff_relocate_symtab): Declare.
+
+Thu Apr 28 08:40:56 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c, defs.h (error_begin): New function.
+ (quit): Print annotation before printing the error message.
+ * main.c (return_to_top_level): Print annotation before doing the
+ longjmp.
+ * symtab.c (decode_line_1): Call error not warning and then
+ return_to_top_level. Call error_begin and printf_unfiltered
+ rather calling warning (before calls to return_to_top_level).
+ * core.c (memory_error): Use error_begin, printf_unfiltered,
+ print_address_numeric and return_to_top_level instead of error.
+ Cleans up a FIXME-32x64.
+ * language.c (type_error, range_error): Call error_begin
+ not just target_terminal_ours.
+
+ * dbxread.c (stabsect_build_psymtabs): Assign to sym_stab_info
+ directly, rather than via DBX_SYMFILE_INFO. A cast on the left
+ side of an assignment is non-portable.
+
+ * utils.c (query): Change syntax of query annotations to be
+ consistent with other input annotations.
+ (prompt_for_continue): Likewise for prompt-for-continue annotation.
+
+Thu Apr 28 01:20:39 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (psymtab_to_symtab_1): Do not call sort_blocks
+ for stabs symtabs.
+ * mips-tdep.c (mips_skip_prologue): Handle prologues for functions
+ that have a stack frame size of 32k or larger (from Paul Flinders).
+ Remove #if 0'd code.
+
+Wed Apr 27 16:33:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * lynx-nat.c (CANNOT_STORE_REGISTER): Add a fallback definition
+ for Lynx platforms that need it.
+ * config/nm-lynx.h (__LYNXOS): Define if not already defined.
+
+Wed Apr 27 16:01:37 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * procfs.c (procfs_wait): Use the signal from the pr_info rather
+ than trying to deduce it from the fault.
+
+Wed Apr 27 12:22:46 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * printcmd.c (print_address_symbolic): Initialize name to empty
+ string to avoid core dump if lookup fails.
+ * remote-e7000.c (printf_e7000debug): Error if target not open.
+
+Tue Apr 26 22:45:24 1994 Stu Grossman (grossman at cygnus.com)
+
+ * i386-nlmstub.c: Update to be more in line with PIN stub.
+ * nlm/gdbserve.c (putDebugChar): Install bug fix from i386-nlmstub.
+ * (hex2mem): Init ptr.
+ * General cleanups to use ConsolePrintf, standard prologues, etc...
+
+Tue Apr 26 10:23:04 1994 Stu Grossman (grossman at cygnus.com)
+
+ * i386-nlmstub.c: More changes to be compatible with remote.c.
+
+ * dbxread.c: Move a bunch of strncmps out of process_one_symbol
+ into (the far less frequently called) dbx_symfile_read.
+
+ * i386-nlmstub.c: An interim version till we get PIN for the x86.
+
+Tue Apr 26 09:50:45 1994 Stu Grossman (grossman at cygnus.com)
+
+ * dbxread.c (record_minimal_symbol): Record the section
+ associated with the symbol to make dynmaic relocation work.
+ * (dbx_symfile_read, process_one_symbol): Fixes to work around
+ Solaris brain-damage which don't apply to relocatable object
+ files.
+ * (stabsect_build_psymtabs): New routine to read stabs out of an
+ arbitrarily named section.
+ * nlmread.c (nlm_symtab_read): Read ALL syms from the NLM, not just
+ globals.
+ * (nlm_symfile_read): Call stabsect_build_psymtabs to read the
+ stabs out of the nlm.
+ * partial-stabs.h (cases 'f' & 'F'): Fixes to work around Solaris
+ brain-damage which don't apply to relocatable object files.
+ * remote.c (putpkt): Improve error reporting and error handling.
+ * (get_offsets): Temporary kludge to force data & bss sections to
+ have the same relocation.
+ * stabsread.c (define_symbol, scan_file_globals): Record section
+ info in sym.
+
+Sat Apr 23 19:05:52 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (breakpoint_1): Annotate each field of output. Add
+ FIXME-32x64 comment.
+
+Fri Apr 22 16:43:54 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Move call to flush_cached_frames
+ to after call to target_wait. This means that flush_cached_frames
+ can call target_terminal_ours if it wants to.
+ * infrun.c (wait_for_inferior) [HAVE_NONSTEPPABLE_WATCHPOINT]: Add
+ comment about why the code is dubious.
+
+ * stabsread.c (read_type): Call read_type, not nonexistent
+ os9k_read_type.
+
+Fri Apr 22 14:25:36 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * remote-os9k.c (rombug_fetch_registers): set trace mode
+ correctly.
+ * remote-os9k.c (rombug_read_inferior_memory): cache data in
+ buffer.
+ * os9kread,c (read_os9k_psymtab): process file symbol to truncate
+ extra info.
+ * os9kread.c (os9k_read_ofile_symtab): proper casting of args
+ passed to process_one_symbol.
+ * stabsread.c (read_type): process os9k functio prototype.
+
+Fri Apr 22 11:27:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * solib.c (symbol_add_stub): If so->textsection is NULL, don't
+ dump core.
+
+Thu Apr 21 07:45:49 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (prompt_for_continue): Annotate prompt.
+ (query): Annotate query.
+ * printcmd.c (print_frame_args): Change syntax of argument
+ annotation to make name and value part of a single group of
+ annotations, not two separate groups.
+ * cp-valprint.c (cp_print_value_fields): Likewise for fields.
+ * valprint.c (val_print_array_elements): Change syntax of
+ annotation to be more concise.
+ * main.c, defs.h (command_line_input): New argument tells what
+ string to include in the annotations.
+ * symtab.c (decode_line_2), main.c (read_command_lines,
+ command_loop): Change callers.
+
+ * breakpoint.c (watch_command): Use (CORE_ADDR)0, not NULL, for
+ target null pointer.
+ * blockframe.c (find_frame_addr_in_frame_chain): Likewise.
+
+ * printcmd.c (output_command): Annotate things we print here too.
+ * printcmd.c (print_command_1): Add "value-history-value" annotation.
+ * Move declaration of print_value_flags from defs.h to value.h.
+ * main.c (command_line_input): Call wrap_here as well as gdb_flush.
+
+Thu Apr 21 09:29:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Reinstall support for sun3,
+ BFD handles sun3 dynamic relocations now.
+ * elfread.c (elf_symtab_read, elf_symfile_read): Handle dynamic
+ symbol table.
+
+Wed Apr 20 19:41:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_command_1): Annotate the top-level expressions
+ that we print.
+ (print_frame_args): Annotate each argument.
+ * printcmd.c, defs.h (print_value_flags): New function.
+ * cp-valprint.c (cp_print_value_fields): Annotate each field.
+ * valprint.c (val_print_array_elements): Annotate each array element.
+
+Wed Apr 20 13:18:41 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * findvar.c (read_var_value): Handle LOC_REPARM_ADDR case correctly,
+ the register contains a pointer to the type, not the type itself.
+
+Mon Apr 11 10:44:35 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * main.c (main): Accept --annotate=N option and make --fullname
+ the same as --annotate=1.
+ (command_line_input): Print annotatation before and after prompt.
+ * blockframe.c (flush_cached_frames): Print annotation.
+ * Rename frame_file_full_name to annotation_level and move it from
+ symtab.h to defs.h.
+ * source.c (identify_source_line): If annotation_level > 1,
+ change output format.
+ * breakpoint.c: Print annotation whenever a breakpoint changes.
+ * main.c: New variable server_command.
+ (command_line_input): Parse "server " and set server_command.
+ (dont_repeat): Check server_command.
+
+Wed Apr 20 08:37:16 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (xcoff_next_symbol_text): Don't return before
+ updating raw_symbol and symnum. Return a value in the case where
+ we complained.
+
+ * dstread.c, coffread.c: Don't define pending_blocks; buildsym.c
+ takes care of it.
+ * parse.c: Don't define block_found; it is defined in symtab.c.
+ * parser-defs.h: Add comment regarding block_found.
+
+Tue Apr 19 09:46:05 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (internalize_unwind_info): Delete unused indexp
+ argument.
+
+Mon Apr 18 13:18:56 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Relocate BFD symbols by
+ section vma. Do not read dynamic relocs for sun3 executables to
+ avoid BFD assertion message.
+
+Mon Apr 18 10:08:07 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * nm-hppab.h (KERNEL_U_ADDR): Define.
+ (FIVE_ARG_PTRACE): Likewise.
+ (CANNOT_STORE_REGISTER): Likewise.
+ * nm-hppah.h (KERNEL_U_ADDR): Define.
+ (FIVE_ARG_PTRACE): Likewise.
+ (CANNOT_STORE_REGISTER): Likewise.
+ (NEED_TEXT_START_END): Likewise.
+
+ * tm-hppah.h (NEED_TEXT_START_END): Delete definition.
+ * xm-hppah.h (KERNEL_U_ADDR): Delete definition.
+ (FIVE_ARG_PTRACE): Likewise.
+ * xm-hppab.h (KERNEL_U_ADDR): Delete definition.
+ (FIVE_ARG_PTRACE): Likewise.
+
+ * hppa-tdep.c (read_unwind_info): Make static.
+ (restore_pc_queue): Indirect through the target vector to
+ reload the register state.
+
+Sat Apr 16 22:20:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (compare_unwind_entries): Delete function. It's been
+ moved into hppa-tdep.c.
+ (read_unwind_info): Likewise.
+ (pa_symfile_read): No longer call read_unwind_info. The unwind
+ tables will be read in as they are needed.
+
+ * hppa-tdep.c (compare_unwind_entries): New function.
+ (read_unwind_info, internalize_unwinds): Likewise.
+ (find_unwind_entry): Read in unwind information on demand.
+
+Fri Apr 15 11:53:46 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * source.c (DIRNAME_SEPARATOR): New macro, replaces all references
+ to : in search path processing.
+ * defs.h (qsort): Rename argument in prototype.
+ * symtab.h (SAYMBOL_VALUE): Rename value field, avoids bugs in
+ some compilers.
+ * breakpoint.c, exec.c, mdebugread.c, mipsread.c, xcoffexec.c
+ (false): Eliminate usages.
+
+Fri Apr 15 11:35:19 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * h8500-tdep.c (initialize_h8500_tdep, large_command):
+ All references to value changed to value_ptrlage_command is now
+ called big_command.
+ All references to value changed to value_ptr.
+ * remote-e7000.c (e7000_wait): Use target_waitstatus and SETSTOP
+ * remote-hms.c (hms_wait): Timeout after five seconds.
+ * ser-go32.c (dosasync_read): Poll if timeout < 0.
+ * config/tm/tm-h8500.h (BEFORE_MAIN_LOOP_HOOK): Deleted.
+ * config/sh/tm-sh.h (BREAKPOINT): Is now sleep opcode.
+
+Thu Apr 14 07:01:56 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * procfs.c (procfs_wait): Protect watchpoint code with appropriate
+ #ifdefs.
+ (procfs_set_watchpoint, procfs_stopped_by_watchpoint): Likewise.
+
+Wed Apr 13 14:52:46 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * breakpoint.h (enum bptype): Add bp_hardware_watchpoint and
+ bp_watchpoint_scope breakpoints.
+ (struct breakpoint): Add val_chain and related_breakpoint fields
+ for use by watchpoints.
+
+ * breakpoint.c (within_scope): Delete. No longer used.
+ (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Provide default definition.
+ (target_{remove,insert}_watchpoint): Likewise.
+ (can_use_hardware_watchpoint): New function.
+ (remove_breakpoint): New function to remove a single breakpoint
+ or hardware watchpoint.
+ (insert_breakpoints): Handle insertion of hardware watchpoints.
+ Store a copy of the value chain derived from the watchpoint
+ expression.
+ (remove_breakpoints): Simplify by using remove_breakpoint.
+ (delete_breakpoint): Likewise.
+ (watchpoint_check): Delete the watchpoint and watchpoint scope
+ breakpoints when the watchpoint goes out of scope. Save & restore
+ the current frame after checking watchpoints.
+ (breakpoint_init_inferior): Likewise (restarting the program
+ makes all local watchpoints go out of scope).
+ (bpstat_stop_status): Handle hardware watchpoints much like normal
+ watchpoints. Delete the watchpoint and watchpoint scope breakpoint
+ when the watchpoint goes out of scope. Remove and reinsert all
+ breakpoints before returning if we stopped when a hardware watchpoint
+ fired.
+ (watch_command): Use a hardware watchpoint when possible. If
+ watching a local expression, build a scope breakpoint too.
+ (map_breakpoint_numbers): Also call given function for any
+ related breakpoints.
+ (disable_breakpoint): Never disable a scope breakpoint.
+ (enable_breakpoint): Handle hardware breakpoints much like normal
+ breakpoints, but recompute the watchpoint_scope breakpoint's
+ frame and address (if we have an associated scope breakpoint).
+ (read_memory_nobpt): Handle hardware watchpoints like normal
+ watchpoints. When necessary handle watchpoint_scope breakpoints.
+ (print_it_normal, bpstat_what, breakpoint_1, mention): Likewise.
+ (clear_command, breakpoint_re_set_one, enable_command): Likewise.
+ (disable_command): Likewise.
+
+ * blockframe.c (find_frame_addr_in_frame_chain): New function.
+ Extern prototype added to frame.h
+
+ * infrun.c (wait_for_inferior): Set current_frame and select
+ a frame before checking if we stopped due to a hardare watchpoint
+ firing. Handle stepping over hardware watchpoints.
+ (normal_stop): Remove unnecessary call to select_frame.
+
+ * value.h (value_release_to_mark): Declare.
+ * values.c (value_release_to_mark): New function.
+
+ * procfs.c (procfs_wait): Add cases for hardware watchpoints.
+ (procfs_set_watchpoint, procfs_stopped_by_watchpoint): New functions.
+
+ * hppab-nat.c (hppa_set_watchpoint): New function.
+
+ * config/pa/nm-hppab.h (STOPPED_BY_WATCHPOINT): Define.
+ (HAVE_STEPPABLE_WATCHPOINT): Define.
+ (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Define.
+ (target_{insert,delete}_watchpoint): Define.
+
+ * config/mips/nm-irix4.h (TARGET_CAN_USE_HARDWARE_WATCHPOINT): Define.
+ (STOPPED_BY_WATCHPOINT, HAVE_NONSTEPPABLE_WATCHPOINT): Likewise.
+ (target_{insert,remove}_watchpoint): Likewise.
+
+Mon Apr 11 19:21:27 1994 Stu Grossman (grossman at cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Ignore symbols of class C_EXT,
+ smtyp XTY_LD, sclass XMC_DS (external data segment label). They
+ often have the same names as debug symbols for functions, and
+ confuse lookup_symbol().
+
+Mon Apr 11 10:44:35 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote.c: Around redefinition of PBUFSIZE, adjust whitespace.
+ * config/pa/tm-hppa.h (REGISTER_BYTES): Use 4 rather than
+ REGISTER_RAW_SIZE (1).
+ Together these changes work around a bug in HP's compiler. Both
+ seem to be necessary.
+
+Mon Apr 11 09:18:24 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (pa_symtab_read): Handle ST_STUB symbols and symbols
+ with scope SS_EXTERNAL. ST_ENTRY symbols in dynamic executables
+ are type mst_solib_trampoline.
+
+Fri Apr 8 17:14:37 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/m68k/es1800.mt: Change comments.
+
+Fri Apr 8 17:14:37 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * config/m68k/monitor.mt (TDEPFILES): Don't include remote-es.o.
+
+Fri Apr 8 15:35:30 1994 Stu Grossman (grossman at cygnus.com)
+
+ * lynx-nat.c: Restore regmap structure for SPARC. It's needed
+ for core files.
+
+Fri Apr 8 14:53:35 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * values.c (unpack_long): Remove obsolete comment about using a
+ switch statement.
+
+ * symfile.c (symbol_file_command): Add comments about command syntax.
+
+Thu Apr 7 17:25:21 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+ Jim Kingdon (kingdon@cygnus.com)
+
+ * infrun.c (IN_SOLIB_TRAMPOLINE): Correct comment, trampolines
+ are in the .plt section.
+ * minsyms.c (lookup_solib_trampoline_symbol_by_pc,
+ find_solib_trampoline_target): New functions for handling
+ stepping into -g compiled shared libraries.
+ * symtab.h (lookup_solib_trampoline_symbol_by_pc,
+ find_solib_trampoline_target): Add prototypes.
+ * config/tm-sunos.h (IN_SOLIB_TRAMPOLINE, SKIP_TRAMPOLINE_CODE):
+ Define to handle stepping into -g compiled shared libraries.
+ * config/tm-sysv4.h (SKIP_TRAMPOLINE_CODE): Define to handle
+ stepping into -g compiled shared libraries.
+
+Thu Apr 7 17:22:54 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * configure.in: Add mips-*-sysv4* support.
+ * config/mips/mipsv4.mh, config/mips/mipsv4.mt,
+ config/mips/tm-mipsv4.h, config/mips/xm-mipsv4.h, mipsv4-nat.c:
+ New files for MIPS SVR4 support.
+ * Makefile.in: Update for new mipsv4 files.
+ * alpha-tdep.c (heuristic_proc_desc, find_proc_desc): Use
+ read_next_frame_reg to obtain the frame relative stack pointer.
+ * mips-tdep.c (heuristic_proc_desc): Use read_next_frame_reg to
+ obtain the frame relative stack pointer.
+ * mdebugread.c (parse_partial_symbols, psymtab_to_symtab1):
+ Handle stStatic and stStaticProc symbols in stabs-in-ecoff output
+ by entering them into the minimal symbol table.
+ * printcmd.c (print_scalar_formatted): Do not try to unpack to
+ a long for float formats.
+ * solib.c: Include "elf/mips.h" only if DT_MIPS_RLD_MAP does not
+ get defined in <link.h>.
+ * solib.c (solib_add): Add shared library sections to the section
+ table of the target before adding the symbols.
+ * partial-stab.h: Relocate static and global functions.
+ * dbxread.c (read_dbx_symtab): Remove unused variable
+ end_of_text_address. Relocate text_addr when passing it
+ to end_psymtab.
+
+ For Alpha OSF/1 targets, enable gdb to set breakpoints in shared
+ library functions before the executable is run. Retrieve dynamic
+ symbols from stripped executables.
+ * mipsread.c (read_alphacoff_dynamic_symtab): New function.
+ * mipsread.c (mipscoff_symfile_read): Use it. Issue warning message
+ if no debugging symbols were found.
+ * alpha-tdep.c (alpha_skip_prologue): Silently return the unaltered
+ pc if memory at the pc is not accessible and GDB_TARGET_HAS_SHARED_LIBS
+ is defined.
+ * config/alpha/nm-alpha.h (GDB_TARGET_HAS_SHARED_LIBS): Define,
+ OSF/1 has shared libraries.
+
+Thu Apr 7 15:11:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * dbxread.c (read_dbx_dynamic_symtab): Adjust for recent changes
+ to BFD handling of dynamic symbols.
+
+Tue Apr 5 15:29:25 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): If FUN is a procedure label,
+ then gets its real address into FUN and its GOT/DP value into %r19.
+
+ * tm-hppa.h (CALL_DUMMY): Use %r20, not %r19 as a temporary.
+
+ * hppa-tdep.c (frameless_function_invocation): If no unwind
+ descriptor was found, then assume this was not a frameless
+ function invocation.
+ (frame_saved_pc): If the saved PC is in a linker stub, then
+ return the return address which the linker stub will return to.
+
+ * xm-hppab.h: Never define USG.
+ * xm-hppah.h: Always define USG.
+
+Tue Apr 5 12:58:47 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * values.c (unpack_long, value_from_longest),
+ valarith.c (value_binop): Allow TYPE_CODE_RANGE.
+
+Fri Apr 1 14:04:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * symfile.c (deduce_language_from_filename): .cpp is a C++ extension.
+
+Fri Apr 1 00:44:00 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ For SVR4 targets, enable gdb to set breakpoints in shared
+ library functions before the executable is run.
+ * elfread.c (elf_symtab_read): Handle symbols for shared library
+ functions.
+ * sparc-tdep.c (in_solib_trampoline): Renamed to in_plt_section
+ and moved to objfiles.c.
+ * objfiles.c (in_plt_section): Moved to here from sparc-tdep.
+ * config/tm-sysv4.h (IN_SOLIB_TRAMPOLINE): Use new in_plt_section.
+ * config/sparc/tm-sun4sol2.h (IN_SOLIB_TRAMPOLINE): Removed,
+ the new generic definition from tm-sysv4.h works for Solaris.
+
+Wed Mar 30 16:14:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * elfread.c (elf_symtab_read): Change storage_needed,
+ number_of_symbols and i to long. Rename get_symtab_upper_bound to
+ bfd_get_symtab_upper_bound. Check for errors from
+ bfd_get_symtab_upper_bound and bfd_canonicalize_symtab.
+ * nlmread.c (nlm_symtab_read): Same changes.
+
+Wed Mar 30 11:43:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (xcoff_next_symbol_text): New function.
+ (read_xcoff_symtab): Set next_symbol_text_func to it.
+ Move raw_symbol outside of read_xcoff_symtab.
+
+ * remote.c (getpkt): Remove unused "out" label.
+
+Wed Mar 30 09:15:42 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * breakpoint.c (print_it_normal): Allow GDB to notify the user
+ about more than one watchpoint being triggered.
+
+Wed Mar 30 08:24:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-dpx2.h: Include tm-m68k.h not nonexistent tm-68k.h.
+
+Wed Mar 30 00:31:49 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * blockframe.c (find_pc_partial_function): mst_file_text
+ symbols do not live in the shared library transfer table.
+ * ch-exp.y (decode_integer_value, match_character_literal,
+ match_bitstring_literal): Guard tolower calls with isupper,
+ tolower on old BSD systems blindly subtracts a constant.
+ * dbxread.c (read_ofile_symtab): Check for __gnu_compiled_* as
+ well when determining the producer of the object file.
+ * mdebugread.c (has_opaque_xref): New function to check for
+ cross reference to an opaque aggregate.
+ * mdebugread.c (parse_symbol, parse_partial_symbols): Do not
+ enter typedefs to opaque aggregates into the symbol tables.
+ * mdebugread.c (parse_external): Remove skip_procedures argument,
+ it has always been 1. Remove code that handled stProc symbols,
+ it was never executed and was wrong, as the index of a
+ stProc symbol points to the local symbol table and not to the
+ auxiliary symbol info. Update caller.
+ * mdebugread.c (parse_partial_symbols): Do not enter external
+ stProc symbols into the partial symbol table, they are already
+ entered into the minimal symbol table.
+ * config/i386/tm-symmetry.h: Clean up, it is now only used for Dynix.
+ Remove all conditionals and definitions for ptx.
+ I386_REGNO_TO_SYMMETRY moved to here from symm-tdep.c.
+ Fix addresses of floating point registers in REGISTER_U_ADDR.
+ STORE_STRUCT_RETURN now handles cc and gcc conventions.
+ FRAME_CHAIN, FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC,
+ IN_SIGTRAMP, SIGCONTEXT_PC_OFFSET defined to make backtracing through
+ signal trampoline code work.
+ * config/i386/xm-symmetry.h: Clean up, it is now only used for Dynix.
+ Remove all conditionals and definitions for ptx.
+ Remove KDB definitions.
+ * symm-nat.c (store_inferior_registers): Fetch registers before
+ storing them to obtain valid floating point control registers.
+ Store fpu registers.
+ * symm-nat.c (print_1167_control_word): Dynix 3.1.1 defines
+ FPA_PCR_CC_C0 and FPA_PCR_CC_C1, avoid duplicate case value.
+ * symm-nat.c (fetch_inferior_registers, child_xfer_memory):
+ Fix typos.
+ * symm-nat.c (child_resume): Update type of `signal' parameter.
+ * symm-tdep.c (I386_REGNO_TO_SYMMETRY): Moved to tm-symmetry.h.
+
+Tue Mar 29 23:01:33 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Use an alternate method for
+ calling import stubs for functions in shared libraries.
+
+Tue Mar 29 21:14:04 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y: Implement SIZE(mode_name) and SIZE(expression).
+
+ * ch-lang.c (chill_is_varying_struct): Magic string is
+ was "<var_length>" is now "__var_length" (more portable).
+
+Tue Mar 29 19:41:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c (getpkt): If we get a timeout, actually retry rather
+ than just giving up the first time it happens.
+ * remote.c: Document sequence numbers.
+ (remote_store_registers): Change syntax of 'P' request so that it
+ never looks like a sequence number.
+
+Tue Mar 29 16:06:01 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * os9kread.c (record_minimal_symbol): add section_offset to
+ relocate minimal symbol table.
+ * os9kread.c (read_minimal_symbols): ditto.
+ * os9kread.c (os9k_symfile_init): increase size of dbg and stb
+ file names.
+ * os9kread.c (read_os9k_psymtab): if there's no dbg file, just
+ return. Also if file addr is 0 leave it 0, not to relocate.
+ * remote-os9k.c (_initialize_remote_os9k): add 'set remotexon',
+ 'set remotexoff' and 'set remotelog' commands.
+
+Tue Mar 29 12:38:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c (remote_store_registers): Add 'P' request to set an
+ individual register.
+ (remote_write_bytes, remote_read_bytes): Use %lx, not %x, to print
+ a target address.
+
+Sat Mar 26 07:05:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/sparc/tm-sparc.h: Define USE_REGISTER_NOT_ARG.
+ * stabsread (define_symbol): If USE_REGISTER_NOT_ARG, go back to
+ combining all 'p' and 'r' pairs into a LOC_REGPARM.
+
+ * command.c (do_setshow_command, case var_string): Never add a
+ space to the end of the string.
+ * NEWS: Document this change.
+ * .gdbinit: Add a space to the "set prompt" command.
+
+Fri Mar 25 12:40:41 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m3-nat.c, i386m3-nat.c, config/i386/i386m3.mh: Many minor
+ changes to make it compile (it doesn't link yet).
+
+ * buildsym.c (start_subfile, patch_subfile_names), demangle.c
+ (set_demangling_style, set_demangling_command): Use savestring not
+ strdup. We were not dealing properly with a NULL return from
+ strdup, and were not declaring strdup (the system header may or
+ may not have it).
+
+ * valprint.c (val_print): Remove inaccurate comment about what
+ types can be stub types.
+
+ * config/i386/ptx.mh (XDEPFILES): Add coredep.o. Delete infptrace.o.
+ * symm-nat.c (child_wait, _initialize_symm_nat, kill_inferior):
+ Supply alternate version if ATTACH_DETACH is not defined.
+ * ptx4-nat.c, config/i386/{nm-ptx4.h, ptx4.mh, ptx.mt, ptx4.mt,
+ tm-ptx.h, tm-ptx4.h, xm-ptx.h, xm-ptx4.h}: New files.
+ * configure.in: Recognize i[34]86-sequent-sysv4* host.
+
+Fri Mar 25 10:14:03 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (skip_prologue): Do nothing if not at the beginning
+ of a function.
+ (skip_trampoline_code): Rewrite and add support for argument
+ relocation stubs stubs, import/export stubs, calls through
+ "_sr4export" and cascaded trampolines.
+
+ * hppa-tdep.c (skip_prologue): Return "pc" not zero
+ if no unwind descriptor is found.
+
+ * tm-hppa.h (NUM_REGS): Bump to 128 registers.
+ (REGISTER_NAMES): Add entries for "right-half" of FP registers.
+ (REGISTER_RAW_SIZE, MAX_REGISTER_RAW_SIZE): Do not treat FP regs
+ differently. All registers are four bytes.
+ (REGISTER_BYTES, REGISTER_BYTE): Simplify now that all registers are
+ the same size.
+ (REGISTER_VIRTUAL_TYPE): Use builtin_type_float for all FP regs.
+
+ * hppa-tdep.c (pa_print_fp_reg): Update to print even numbered FP
+ registers as both single and double values (fetching 2nd 32bit half
+ as necessary). Annotate each register printed with its precision.
+
+ * paread.c (read_unwind_info): Fix off-by-one error.
+
+Fri Mar 25 08:33:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (complete_command): Deal with it if arg is NULL.
+
+Thu Mar 24 07:12:09 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/mips/tm-mips.h (SETUP_ARBITRARY_FRAME): Revise comment
+ regarding using the PC--using the PC is necessary and all the
+ FIXME comments in the world won't make it go away.
+
+ * valops.c (value_at, value_at_lazy): Give error if we dereference
+ a pointer to void.
+ * gdbtypes.h: Fix comments regarding TYPE_CODE_VOID.
+ * stabsread.c: Use 1, not 0, for TYPE_LENGTH of void types.
+
+ * stabsread.c (patch_block_stabs): Add comment about what happens
+ if the definition is in another compilation unit from the stab.
+
+ * dbxread.c (end_psymtab): Add comment about empty psymtabs.
+
+Wed Mar 23 07:50:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (complete_command): New command, from Rick Sladkey
+ <jrs@world.std.com>.
+ (symbol_completion_function): Don't declare rl_point and
+ rl_line_buffer; they are now declared in readline.h.
+ (show_commands): Don't declare history_base; it is declared in
+ history.h.
+ * command.c (lookup_cmd): Don't delete trailing whitespace.
+ Reverts change of 14 May 1989.
+
+Wed Mar 23 16:14:52 1994 Stu Grossman (grossman at cygnus.com)
+
+ * minsyms.c (prim_record_minimal_symbol): Move section deduction
+ code from prim_record_minimal_symbol_and_info() to here. Callers
+ of the latter can legitimately supply a section number of -1.
+
+Wed Mar 23 07:50:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h, gdbtypes.c: Add comments regarding whether static
+ member functions have an element in args for a (nonexistent) this
+ pointer.
+
+Tue Mar 22 20:12:53 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppao.h (NO_PC_SPACE_QUEUE_RESTORE): Define.
+
+ * hppa-tdep.c (hppa_pop_frame): Do not restore the PC space
+ queue if NO_PC_SPACE_QUEUE_RESTORE is defined.
+
+ * stabsread.c (REG_STRUCT_HAS_ADDR): Accept additional argument
+ for the structure's type. All callers changed.
+
+ * valops.c (call_function_by_hand): Check REG_STRUCT_HAS_ADDR
+ for each structure argument rather than assuming it's either
+ true or false for all structure arguments.
+
+ * config/pa/tm-hppa.h (REG_STRUCT_HAS_ADDR): Depend only
+ on the length structure passed, not the compiler used.
+
+ * config/sparc/tm-sparc.h (REG_STRUCT_HAS_ADDR): Accept additional
+ argument for the structure's type.
+
+Tue Mar 22 15:28:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * values.c (set_internalvar): Don't set var->value until we are
+ sure there won't be an error().
+
+ * remote.c (get_offsets): Reinstate comment which was in
+ remote_wait about use of SECT_OFF_TEXT and so on.
+
+Mon Mar 21 13:11:30 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symmisc.c (maintenance_check_symtabs): New function to check
+ consistency of psymtabs and symtabs.
+ * symtab.h (maintenance_check_symtabs): Add prototype.
+ * maint.c: Add new `maint check-symtabs' command.
+ * config/i386/tm-i386aix.h, config/i386/tm-sun386.h,
+ config/i386/tm-symmetry.h (REGISTER_CONVERT_TO_RAW): Fix typo.
+ * config/i386/tm-symmetry.h: Make comment inside #if 0 a real
+ comment.
+ * config/i386/tm-symmetry.h (STORE_STRUCT_RETURN): Cast argument
+ to write_memory to avoid warnings from gcc.
+ * config/i386/xm-symmetry.h: Add missing #endif.
+ * config/i386/nm-symmetry.h (NO_PTRACE_H): Add for Dynix.
+ * config/i386/symmetry.mt (TDEPFILES): Add i386-tdep.o.
+ * config/i386/symmetry.mh (NAT_FILE, NATDEPFILES): Add.
+
+Mon Mar 21 11:50:28 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Use value_ptr.
+ (hppa_push_arguments): Likewise.
+
+Mon Mar 21 11:02:51 1994 Stu Grossman (grossman at cygnus.com)
+
+ * alpha-tdep.c: Gobs of changes (many imported from mips-tdep) to
+ improve remote debugging efficiency. Also fixed problems with
+ doing function calls for programs with no entry points.
+ * infcmd.c (run_stack_dummy): Use CALL_DUMMY_ADDRESS instead of
+ entry_point_address.
+ * inferior.h (PC_IN_CALL_DUMMY): ditto.
+ * mdebugread.c (parse_symbol, parse_procedure, parse_external,
+ parse_lines): Pass section_offsets info to these routines so that
+ we can relocate symbol table entries upon readin.
+ * (psymtab_to_symtab_1): Set symtab->primary to tell
+ objfile_relocate to do relocations for our symbols.
+ * (ecoff_relocate_efi): New routine to relocate adr field of PDRs
+ (which hang off of the symbol table).
+ * Use prim_record_minimal_symbols_and_info instead of
+ prim_record_minimal_symbols to supply section info to make minimal
+ symbol relocations work.
+ * minsyms.c (prim_record_minimal_symbols_and_info): If section is
+ -1, try to deduce it from ms_type.
+ * objfiles.c (objfile_relocate): Use ALL_OBJFILE_SYMTABS where
+ appropriate. Handle relocation of MIPS_EFI symbols special. Also,
+ add code to relocate objfile->sections data structure.
+ * remote.c (get_offsets): Use new protocol message to acquire
+ section offsets from the target.
+ * (remote_wait): Get rid of relocation stuff. That's all handled
+ by objfile_relocate now.
+ * config/alpha/alpha-nw.mt (TM_FILE): Use tm-alphanw.h.
+ * config/alpha/tm-alpha.h: Define CALL_DUMMY_ADDRESS, and
+ VM_MIN_ADDRESS.
+ * config/alpha/tm-alphanw.h: DECR_PC_AFTER_BREAK=0, VM_MIN_ADDRESS=0.
+
+Mon Mar 21 10:09:06 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (_initialize_hpuxread): Don't call add_symtab_fns if
+ HPREAD is not defined.
+
+Sun Mar 20 15:21:57 1994 Doug Evans (dje@cygnus.com)
+
+ * sparc-tdep.c (sparc_frame_find_save_regs): Use REGISTER_RAW_SIZE
+ instead of 4.
+ * sp64-tdep.c (target_ptr_bit, set_target_ptr_bit): Deleted,
+ can no longer set this at run time.
+ * config/sparc/sp64.mt (SIMFILES): Use remote-sim.o now.
+ (TM_CLIBS): Define to -lm, the simulator uses the sqrt() function.
+ * config/sparc/tm-sp64.h (FPS_REGNUM, CPS_REGNUM): Define (so
+ sparc-tdep.c compiles).
+ (TARGET_PTR_BIT): Must be a constant now, fix at 64.
+
+Sat Mar 19 08:51:12 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/{cisco.mt,tm-cisco.h}: New files.
+ * Makefile.in (ALLPARAM, ALLCONFIG): Add them.
+ * configure.in: Recognize m68*-cisco*-*.
+
+ * Makefile.in (TAGS): Use variables directly, rather than using
+ find, to locate TM_FILE, XM_FILE, and NAT_FILE. This is faster
+ and means that these filenames no longer need be unique across all
+ the config/* directories.
+ * configure.in: Put the config/*/ into TM_FILE, etc.
+
+ * m68k-stub.c (computeSignal): Return SIGFPE, not SIGURG, for chk
+ and trapv exceptions.
+
+ * target.h (struct section_table), objfiles.h (struct obj_section):
+ Change name of field sec_ptr to the_bfd_section. More mnemonic
+ and avoids the (sort of, for the ptx compiler) name clash with
+ the name of the typedef.
+ * exec.c, xcoffexec.c, sparc-tdep.c, rs6000-nat.c, osfsolib.c,
+ solib.c, irix5-nat.c, objfiles.c, remote.c: Change users.
+
+ * utils.c: Include readline.h.
+ * Makefile.in (utils.o): Add dependency.
+
+ * remote.c (getpkt): Add support for run-length encoding.
+
+Fri Mar 18 19:11:15 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * utils.c (prompt_for_continue): Call readline, not gdb_readline.
+
+Fri Mar 18 10:25:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dstread.c (record_minimal_symbol): New arg objfile. Pass it to
+ prim_record_minimal_symbol.
+ Callers: Pass it.
+
+ * regex.c (EXTEND_BUFFER): Adjust pointers within buffer by
+ computing their offset from the start of the old buffer and adding
+ to the new buffer, rather than by assuming we can add the
+ difference between the old buffer and the new buffer (it might not
+ fit in an int). Merge in cosmetic differences from emacs regex.c
+ version of this macro.
+
+Wed Mar 16 15:28:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (install-only): Fix use of program_transform_name.
+
+Wed Mar 16 07:18:43 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c: Remove "set print fast-symbolic-addr off" command.
+ The bug which it worked around was fixed on 25 Feb 94 in coffread.c,
+ so I'm nuking the command.
+ * symtab.c (find_addr_symbol): Comment out, no longer used.
+
+ * main.c (main): Don't init_source_path for the -cd argument. Now
+ that source_path doesn't contain the current_directory from when
+ GDB started up, init_source_path is no longer useful (and is
+ harmful because it clobbers a source_path set in $HOME/.gdbinit).
+
+ * TODO: Remove item about line numbers being off. It is useless
+ and confusing without a reproducible test case (it mentions
+ proceed(), but I was able to step through proceed without trouble).
+
+Tue Mar 15 13:39:23 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ For Sunos 4.x targets, enable gdb to set breakpoints in shared
+ library functions before the executable is run. Retrieve dynamic
+ symbols from stripped executables.
+ * symtab.h (minimal_symbol_type): Add mst_solib_trampoline type.
+ * parse.c (write_exp_msymbol), symmisc.c (dump_msymbols),
+ symtab.c (list_symbols): Handle mst_solib_trampoline.
+ * minsyms.c (lookup_minimal_symbol): Handle mst_solib_trampoline
+ for all targets, remove IBM6000_TARGET dependencies.
+ * dbxread.c (read_dbx_dynamic_symtab): New function.
+ * dbxread.c (dbx_symfile_read): Use it.
+ * dbxread.c (SET_NAMESTRING): Set namestring to
+ "<bad string table index>" instead of "foo" if the string index is
+ corrupt.
+ * xcoffread.c (read_xcoff_symtab): Use mst_solib_trampoline instead
+ of mst_unknown.
+ * symtab.c (list_symbols): Take from_tty as parameter and pass it
+ to break_command. Handle mst_file_* minimal symbol types.
+ * config/i386/tm-i386bsd.h: Give just macro name, not args, to #undef.
+
+Tue Mar 15 11:40:43 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * c-exp.y(yylex): fix potential memory overflow.
+
+Tue Mar 15 10:33:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * environ.c (set_in_environ): Eliminate special handling of PATH and
+ GNUTARGET.
+ * putenv.c: Removed, conflicts with system declaration of
+ putenv on RS/6000 running AIX 3.2.5, and above change makes it
+ unnecessary.
+ * Makefile.in: Change accordingly.
+ * procfs.c (procfs_create_inferior): Change comment accordingly.
+
+Tue Mar 15 10:05:27 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * rs6000-tdep.c: Change value to value_ptr.
+
+Sun Mar 13 17:19:03 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (read_hpux_symtab: Correctly determine the namespace
+ and address class of SVAR, DVAR, TYPEDEF, TAGDEF, CONST, and
+ MEMENUM symbols. Do not include function-scoped variables in
+ the partial symbol table.
+
+Sun Mar 13 09:45:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i386m3-nat.c: Include floatformat.h.
+ (get_i387_state): Use memset not bzero.
+
+ * Version 4.12.3.
+
+ * Makefile.in: Enable commented out getopt_h, bfd_h, etc. Change
+ ieee-float.h to floatformat.h.
+
+ * valprint.c (val_print_string): Ignore error if the error
+ happened after a terminating '\0'.
+
+ * c-valprint.c (c_val_print): Never add 1 to return value from
+ val_print_string; just return what it returns.
+
+ * target.h (enum target_signal): Add TARGET_SIGNAL_FIRST, for
+ looping through all of the enums.
+ * infrun.c (signals_info): Use it.
+
+Fri Mar 11 08:08:50 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * main.c (main): When printing warning about bad baud rate, don't
+ use warning(); it relies on current_target which isn't set up yet.
+
+ * breakpoint.c (_initialize_breakpoint): Update docstring for
+ tbreak to match what the code actually does. Don't mention tbreak
+ in docstrings for "enable once" or "enable breakpoints once".
+
+Thu Mar 10 08:52:38 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Don't put a semicolon after
+ while (0). That defeats the whole purpose of using do . . . while (0).
+ * mdebugread.c (parse_partial_symbols): Don't use ?: expression as
+ list for ADD_PSYMBOL_TO_LIST; the macro takes its address and
+ using a ?: expression as an lvalue is not portable.
+
+ * stabsread.c (define_symbol): If REG_STRUCT_HAS_ADDR, also
+ convert a LOC_ARG to a LOC_REF_ARG. Update code which combines
+ 'p' and 'r' symbol descriptors into a single symbol to look for a
+ LOC_REF_ARG.
+ * README, config/sparc/tm-sparc.h: Update comments.
+
+Wed Mar 9 21:43:24 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_type): Do not complain for types with
+ an `indexNil' aux index, these are simply undefined types.
+ Remove indexNil check from caller of parse_type.
+ * mdebugread.c (parse_partial_symbols): Do not enter
+ stGlobal, scCommon symbols into the minimal symbol table, their
+ value is the size of the common, not its address.
+ Handle scInit, scFini, scPData and scXData sections.
+ Use minimal symbol type mst_file_* for stLabel symbols, instead of
+ mst_*.
+ Enter stProc symbols into the global_psymbols list once, not into
+ the static_psymbols_list.
+ Get rid of dummy psymtab if it is empty, to allow proper detection
+ of stripped executables.
+ * mdebugread.c (cross_ref): Allow cross references to Fortran
+ common blocks.
+
+Wed Mar 9 15:23:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (common_block_end, fix_common_block): Stash the
+ struct pending * in the SYMBOL_TYPE, not the SYMBOL_NAMESPACE, so
+ as to not assume that a pointer fits in an enum.
+
+Wed Mar 9 18:56:36 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * os9kread.c (fill_sym): check compiler verion number for pre-
+ UltraC compiler.
+ * os9kread.c (os9k_process_one_symbol): address of symbol is
+ relative to section not module.
+ * stabsread.c (define_symbol): add symbol type 's' as local
+ symbol for os9k.
+ * remote-os9k.c: add command 'set monitor_log' to turn on or off
+ monitor logging.
+ * remote-os9k.c: fix bug in delete breakpoint, single step trace.
+ * remote-os9k.c: fix bug in 'set remotebaud' function.
+ * remote-os9k.c (rombug_link): minimize checking so to improve
+ speed.
+ * symfile.c (symbol_file_command): check if failed to link, also make
+ the command be able to accept more than one filenames.
+ * target.c (target_link): check if failed to link with rombug.
+ * config/i386/tm-i386os9k.h : add #define DECR_PC_AFTER_BREAK 0.
+
+Wed Mar 9 15:23:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-es.c (es1800_child_ops): Don't declare it static.
+
+Tue Mar 8 11:42:39 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/i386/tm-i386v4.h: Give just macro name, not args, to #undef.
+
+Tue Mar 8 06:56:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c: New variable lowest_text_address.
+ (record_minimal_symbol, read_dbx_symtab): Set it.
+ (read_dbx_symtab): Use lowest_text_address + text_size instead of
+ end_of_text_address.
+ * config/gould/tm-pn.h: Add comment regarding END_OF_TEXT_DEFAULT.
+
+ * dbxread.c (end_psymtab): Remove old and commented out
+ capping_global and capping_static. Fix comments regarding
+ N_SO_ADDRESS_MAYBE_MISSING to match the real name of the macro.
+
+ * parser-defs.h: Add "extern" to start of variable declarations so
+ we don't end up with commons.
+ * parse.c: Define these variables.
+
+ * irix5-nat.c (find_solib): Cast o_path to CORE_ADDR when using it
+ as one.
+
+Mon Mar 7 13:00:50 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * alpha-tdep.c: Change value to value_ptr.
+
+Sun Mar 6 17:36:53 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * solib.c (elf_locate_base): New function to locate the address
+ of the dynamic linker's runtime structure in the dynamic info section.
+ * solib.c (locate_base): Use it instead of iterating over the list
+ of mapped address segments.
+ * solib.c (look_for_base, bfd_lookup_symbol): Removed, no longer
+ necessary.
+
+Fri Mar 4 09:50:47 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (pc_in_linker_stub): Move decl to beginning of file.
+ (pc_in_interrupt_handler): New function. Also add PARAM decl.
+ (find_proc_framesize): Deal with HPUX setting SAVE_SP bit for
+ signal trampoline and interrupt routines.
+ (frame_saved_pc): Handle signal trampolines and interrupt routines.
+ (frame_chain, frame_chain_valid): Likewise.
+ (hppa_frame_find_saved_regs): Likewise. Also deal with special
+ saved regs convention for SP.
+
+ * tm-hppa[bho].h: FRAME_FIND_SAVED_PC_IN_SIGTRAMP): Define.
+ (FRAME_BASE_BEFORE_SIGTRAMP): Define.
+ (FRAME_FIND_SAVED_REGS_IN_SIGTRAMP): Define.
+
+ * tm-hppah.h (IN_SIGTRAMP): Define.
+
+Thu Mar 3 12:41:16 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * ch-exp.y (match_simple_name_string): Accept '_' as well as an
+ alphabetic character as the start of a name.
+
+ * sparclite/Makefile.in (all install): Build and install aload.
+
+ * configure.in: Accept i[34]86-*-*sysv32 because that is what
+ config.guess and config.sub produce.
+
+ * mips-tdep.c: Change value to value_ptr.
+
+Wed Mar 2 09:17:55 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * breakpoint.c, breakpoint.h, c-valprint.c, ch-valprint.c,
+ cp-valprint.c, eval.c, expprint.c, findvar.c, language.c,
+ objfiles.h, infcmd.c, printcmd.c, stack.c, typeprint.c,
+ valarith.c, valops.c, valprint.c, value.h, values.c: Replace
+ value with value_ptr. This is for the ptx compiler.
+ * objfiles.h, target.h: Don't declare a "sec_ptr" field using a
+ "sec_ptr" typedef.
+ * symm-nat.c: Add a bunch of stuff for symmetry's ptrace stuff.
+ #if 0 i386_float_info.
+ * symm-tdep.c (round): Remove. Also remove sgttyb.
+ * symm-tdep.c: Remove lots of stuff which duplicates stuff from
+ i386-tdep.c. Remove register_addr and ptx_coff_regno_to_gdb.
+ * i386-tdep.c (i386_frame_find_saved_regs): Put in
+ I386_REGNO_TO_SYMMETRY check in case it is needed for Dynix
+ someday.
+ * config/i386/nm-symmetry.h: Change KERNEL_U_ADDR. Move
+ stuff from PTRACE_READ_REGS, PTRACE_WRITE_REGS macros to
+ symm-nat.c. Define CHILD_WAIT and declare child_wait().
+ * config/i386/tm-symmetry.h: Remove call function stuff; stuff in
+ tm-i386v.h is apparently OK.
+ * config/i386/xm-symmetry.h [_SEQUENT_]: Define HAVE_TERMIOS not
+ HAVE_TERMIO. Define MEM_FNS_DECLARED, NEED_POSIX_SETPGID, and
+ USE_O_NOCTTY.
+
+Wed Mar 2 11:31:08 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * osfsolib.c (xfer_link_map_member): Update to use new
+ target_read_string interface.
+
+Wed Mar 2 09:17:55 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * infrun.c (wait_for_inferior): In checking
+ remove_breakpoints_on_following_step, check
+ through_sigtramp_breakpoint as well as step_resume_breakpoint.
+
+Tue Mar 1 16:22:56 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * os9kread.c (os9k_process_one_symbol): Rename
+ VARIABLES_INSIDE_BLOCK to OS9K_VARIABLES_INSIDE_BLOCK.
+ * symfile.c (symbol_file_command): Check for (CORE_ADDR)-1, not
+ (CORE_ADDR)0, from target_link, since that is what it uses.
+ Process name at end, not during parsing (like we did before Kung's
+ change), so that -readnow and -mapped can appear anywhere.
+ Make text_relocation a local variable.
+ * config/i386/i386os9k.mt: Fix comment.
+ * Makefile.in (ALLDEPFILES): Add remote-os9k.c.
+ * os9kread.c: Put "comments" after #endif inside /* */.
+ * stabsread.h: Add os9k_stabs variable.
+ * stabsread.c (start_stabs), os9kread.c (os9k_process_one_symbol):
+ Set it.
+ * stabsread.c (define_symbol): If os9k_stabs, put a 'V' symbol
+ descriptor in global_symbols not local_symbols.
+ (read_type): If os9k_stabs, accept 'c', 'i', and 'b' type
+ descriptors.
+ (read_type): If os9k_stabs, accept function parameters after 'f'
+ type descriptor.
+ (read_array_type): If os9k_stabs, don't expect index type and
+ expect lower and upper to be separated by ',' not ';'.
+ (read_enum_type): If os9k_stabs, read a number before the first
+ enumeration constant.
+ (os9k_init_type_vector): New function.
+ (dbx_lookup_type): Call it when starting new type vector.
+ * config/i386/tm-i386os9k.h: Define BELIEVE_PCC_PROMOTION.
+ * (os9k_process_one_symbol): Call define_symbol not os9k_define_symbol.
+ * os9kstab.c: Removed.
+ * Makefile.in: Update accordingly.
+ * objfiles.c (objfile_relocate_data): Removed.
+ * remote-os9k.c (rombug_wait): Call objfile_relocate
+ not objfile_relocate_data.
+ * objfiles.h, objfiles.c: Remove find_pc_objfile.
+ * remote-os9k.c (rombug_wait): Call find_pc_section not
+ find_pc_objfile.
+ * main.c (quit_command): Check inferior_pid; revert Kung change.
+ * remote-os9k.c (rombug_create_inferior): Set inferior_pid.
+
+Tue Mar 1 14:56:14 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * os9kread.c: New file to read os9000 style symbo table.
+ * os9kstab.c: new file to read os9000 style stabs.
+ * remote-os9k.c: remote protocol talking to os9000 rombug monitor.
+ * objfiles.c (find_pc_objfile): new function to search objfile
+ from pc.
+ * objfiles.c (objfile_relocate_data): new function to relocate
+ data symbols in symbol table.
+ * objfiles.h: Add two aux fields in struct objfile to handle
+ multiple symbol table files situation like in os9000.
+ * symfile.c: Change so 'symbol-file' command can handle multiple
+ files. Also call target_link() to get relocation infos.
+ * target.c (target_link): new function to get relocation info when
+ a symbol file is requested to load.
+ * main.c (quit_command): take out 'inferior_pid != 0' condition,
+ because in cross mode there's no inferior pid, bit they need to
+ be detached.
+ Makefile.in: add os9kread.c os9kstab.c and .o's.
+ configure.in: add i386os9k target.
+ config/i386/i386os9k.mt: new add.
+ config/i386/tm-i386os9k.h: new add.
+
+Tue Mar 1 13:16:10 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/sparc/tm-sun4sol2.h (IN_SIGTRAMP): Handle ucbsigvechandler.
+ * sparc-tdep.c (sparc_frame_saved_pc): Handle ucbsigvechandler.
+
+Tue Mar 1 11:54:11 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * target.c, target.h (target_read_string): Provide error detection to
+ caller. Put string in malloc'd space, so caller need not impose
+ arbitrary limits.
+ * solib.c (find_solib): Update to use new interface.
+ * irix5-nat.c (find_solib): Read o_path from inferior
+ (clear_solib): Free storage for o_path.
+ * valprint.c (val_print_string): Add comments.
+
+Mon Feb 28 23:54:39 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.c (decode_line_1): Handle the case when skip_quoted does not
+ advance `p'.
+
+Mon Feb 28 12:40:46 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * value.h (struct value): Add modifiable field.
+ * values.c (allocate_value, record_latest_value, value_copy): Set it.
+ (record_latest_value): Don't mess with VALUE_LVAL of value.
+ * valops.c (value_assign): Check it. Reword existing error
+ message on not_lval.
+
+ * mips-tdep.c (mips_step_skips_delay), config/mips/tm-mips.h
+ (STEP_SKIPS_DELAY): Added.
+ * infrun.c (proceed) [STEP_SKIPS_DELAY]: Check for a breakpoint in
+ the delay slot.
+
+ * valprint.c (val_print_string): If errcode is set, always print
+ an error, regardless of force_ellipsis. In the non-EIO case,
+ just print the error message rather than calling error(). Don't
+ access *(bufptr-1) if bufptr points to the start of the buffer.
+ When looking for '\0', don't increment bufptr and addr if bufptr
+ started out already at limit. If an error happens on fetching the
+ first character, don't print the string.
+
+Sun Feb 27 21:05:06 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/m68k/tm-apollo68b.h: Remove HAVE_68881 define; it is
+ obsolete.
+
+ * i387-tdep.c, i386-tdep.c i386v-nat.c, i386aix-nat.c,
+ i386m3-nat.c, config/m68k/tm-m68k.h, i960-tdep.c
+ config/i960/tm-i960.h, remote-nindy.c, config/m88k/tm-m88k.h,
+ m88k-tdep.c: Use floatformat.h instead of ieee-float.h.
+ * sparc-tdep.c: Remove now-obsolete ieee-float.h stuff
+ * findvar.c: Update comment regarding ieee-float.h.
+
+Sun Feb 27 21:39:48 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/tm-i386v4.h (I386V4_SIGTRAMP_SAVED_PC, IN_SIGTRAMP,
+ FRAME_CHAIN, FRAMELESS_FUNCTION_INVOCATION, FRAME_SAVED_PC):
+ Define to make backtracing through the various sigtramp handlers
+ work.
+ * i386-tdep.c (i386v4_sigtramp_saved_pc): New routine to fetch
+ the saved pc from ucontext on the stack for SVR4 signal handling.
+
+Fri Feb 25 09:41:11 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote.c, remote-mon.c, remote-utils.c, remote-utils.h,
+ target.h, remote-es.c, remote-nindy.c: Don't set baud rate if
+ baud_rate is -1. Remove sr_get_baud_rate and sr_set_baud_rate;
+ just use the global variable itself. When printing baud rate,
+ don't print a baud rate if baud_rate is -1.
+
+ * coffread.c (read_coff_symtab): Pass mst_file_* to
+ record_minimal_symbol for C_STAT symbols. Put C_EXT and C_STAT
+ symbols in the minimal symbols regardless of SDB_TYPE.
+
+Thu Feb 24 08:30:33 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * breakpoint.h (enum bptype): New type bp_through_sigtramp.
+ (bpstat_what_main_action): New code BPSTAT_WHAT_THROUGH_SIGTRAMP.
+ * breakpoint.c (bpstat_what): Return BPSTAT_WHAT_THROUGH_SIGTRAMP
+ if we hit a bp_through_sigtramp breakpoint. Remove kludge which
+ ignored bs->stop for a bp_step_resume breakpoint.
+ * infrun.c (wait_for_inferior): Make a through_sigtramp_breakpoint
+ which performs one (the check_sigtramp2 one) of the functions
+ which had been handled by the step_resume_breakpoint. For each
+ use of the step_resume_breakpoint, make it still use the
+ step_resume_breakpoint, use the through_sigtramp_breakpoint, or
+ operate on both.
+ Deal with BPSTAT_WHAT_THROUGH_SIGTRAMP return from bpstat_what.
+ When setting the frame address of the step resume breakpoint, set
+ it to the address for frame *before* the call instruction is
+ executed, not after.
+
+ * mips-tdep.c (mips_print_register): Print integers using
+ print_scalar_formatted rather than duplicating all the
+ CC_HAS_LONG_LONG and so on.
+ (mips_push_dummy_frame): Use read_register_gen rather than using
+ read_register and then putting it back in target format with
+ store_unsigned_integer. If registers are more than 4 bytes, give
+ an error rather than have some registers overwrite other
+ registers.
+ #if 0 unused include of opcode/mips.h.
+
+ * symfile.h: Don't declare arguments for coff_getfilename.
+
+ * defs.h: Revert Kung change regarding FORCE_LONG_LONG.
+
+Thu Feb 24 08:06:52 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * configure.in (hppa*-*-osf*): New configuration.
+ * config/pa/hppaosf.mt: New target makefile fragment.
+ * config/pa/tm-hppao.h: New target include file.
+
+Thu Feb 24 04:29:19 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * exec.c (print_section_info): Print entry point for exec_bfd only.
+ * ser-unix.c (wait_for): Fix typo in HAVE_TERMIO case.
+ * dwarfread.c: Remove second inclusion of <sys/types.h>, which
+ causes problems if <sys/types.h> has no multiple inclusion protection.
+
+Wed Feb 23 16:28:55 1994 Jeffrey A. Law (law@cygnus.com)
+
+ * tm-hppa.h (CALL_DUMMY): Add two NOP instructions to the end of
+ the call dummy to avoid kernel bugs in HPUX, BSD, and OSF1.
+ (CALL_DUMMY_LENGTH): Changed accordingly.
+
+Wed Feb 23 16:21:25 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c (trap_low): Make trap handler work for arbitrary
+ numbers of register windows.
+
+ * sparclite/hello.c: Add factorial function for testing.
+ * salib.c: Use macros instead of constants for I/O addresses to
+ make 931 support easier.
+ * sparclite.h: Change constraint for LOC to "rJ" to force use of
+ register in sta/lda instructions.
+
+Wed Feb 23 10:39:18 1994 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * dbxread.c (process_one_symbol): Set
+ block_address_function_relative for COFF like we do for ELF and SOM.
+
+Sat Feb 19 03:17:32 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (new_psymtab): Pass in section_offsets and set
+ them in the pst.
+ * mdebugread.c (handle_psymbol_enumerators): New function to enter
+ the enumerators of an ecoff enum into the partial symbol table.
+ * mdebugread.c (parse_partial_symbols): Call it.
+ * symfile.c (reread_symbols): Initialize objfile->*_psymbols.next.
+ * symmisc.c (dump_psymtab): Fix typo, clean up output of section
+ offsets. Cast psymtab->read_symtab to PTR before passing it to
+ gdb_print_address.
+ * i386-tdep.c (i386_skip_prologue): Skip over instructions that
+ set up the global offset table pointer in pic compiled code.
+ * config/mips/tm-mips.h (FIX_CALL_DUMMY): For big endian targets,
+ error() on TYPE_CODE_FLT arguments whose size is greater than 8,
+ swap all other TYPE_CODE_FLT arguments as mips_push_arguments
+ ensures that floats are promoted to doubles before they are pushed
+ on the stack.
+
+Fri Feb 18 23:12:59 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparclite/Makefile.in, sparclite/salib.c, sparclite/sparclite.h:
+ Fixup cache_on and flush_i_cache so that they work for both the
+ 930 and 932 processors. Rewrite most low level funcs (uart
+ access & cache stuff) to use new ASI access macros in sparclite.h.
+ Also make it easy to access second serial port.
+
+Fri Feb 18 22:17:33 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * hp300ux-nat.c: Don't incloude <sys/dir.h>, <sys/ioctl.h>, or
+ <sys/stat.h>; not needed.
+
+Fri Feb 18 08:26:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stack.c (print_frame_info): In "pathological" case, don't
+ distrust the line number information.
+
+Fri Feb 18 16:51:14 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * mips-tdep.c (mips_print_register): handle 64 bits register.
+ * valprint.c (print_longest): fix a bug in printing 64 bits value.
+
+Fri Feb 18 08:26:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Version 4.12.2.
+
+ * Makefile.in (install): Do the sed for program_transform_name
+ ourselves instead of worrying about INSTALL_XFORM. This enables
+ users to override INSTALL_PROGRAM in the standard way.
+
+ * Makefile.in (c-exp.tab.o, ch-exp.tab.o, m2-exp.tab.o): Don't
+ depend on Makefile.in.
+
+ * defs.h, valprint.c: Make longest_to_int a function not a macro.
+ Only test against INT_MIN if a LONGEST is bigger than an int.
+
+ * README: Change GhostScript to Ghostscript.
+
+Fri Feb 18 07:30:55 1994 Jim Kingdon (kingdon@cygnus.com)
+
+ * config/rs6000/{tm-rs6000lynx.h,nm-rs6000lynx.h,xm-rs6000lynx.h}:
+ Rename to tm-rs6000ly.h, nm-rs6000ly.h, xm-rs6000ly.h for 14
+ character file names.
+ * Makefile.in (ALLPARAM): Add these files.
+
+ * config/mips/littlemips64.mt: Rename to mipsel64.mt for 14
+ character file names.
+ * Makefile.in: Add Kung's new mips64 files.
+
+Thu Feb 17 17:25:47 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * configure.in: add mips64-*-elf, mips64-*-ecoff, mips64el-*-elf,
+ mips64el-*-ecoff and mips64-big-*.
+ * defs.h: get rid of FORCE_LONG_LONG.
+ * mips-tdep.c (mips_find_saved_regs): add sd and sdc1 instruction
+ parsing. Change register size to be MIPS_REGSIZE.
+
+Thu Feb 17 09:30:22 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * corelow.c, exec.c, irix5-nat.c, mipsread.c, objfiles.c,
+ osfsolib.c, rs6000-nat.c, solib.c, symfile.c, utils.c,
+ xcoffexec.c: Use bfd_get_error and bfd_set_error and new error names.
+
+Fri Feb 11 21:47:24 1994 Steve Chamberlain (sac@sphagnum.cygnus.com)
+
+ * remote-hms.c (readchar, hms_open, hms_fetch_register): Made more robust.
+ (remove_commands, add_commands): Add/remove hms-drain when target
+ is connected.
+
+Fri Feb 11 16:11:38 1994 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in: Add Lynx/rs6000 support.
+ * lynx-nat.c: Clean up some Sparc stuff. Clean up ptrace error
+ messages. Add rs6000 support. Don't try to modify unwritable
+ registers.
+ * rs6000-nat.c: Move lots of native dependent stuff (like core
+ file support) from rs6000-tdep.c & xcoffexec.c to here.
+ * rs6000-tdep.c: Move native dependent stuff to nat.c.
+ * xcoffexec.c: Move native dependent stuff to nat.c.
+ * config/rs6000/nm-rs6000.h: Move defs of SOLIB_* macros to here
+ from tm file.
+ * config/rs6000/tm-rs6000.h: Remove defs of SOLIB_* funcs, cuz they're
+ really native.
+ * config/rs6000/tm-rs6000lynx.h, config/rs6000/xm-rs6000lynx.h:
+ New files to support Lynx/rs6000.
+
+Tue Feb 8 00:32:28 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Remove note about gcc warnings on alpha, these should be
+ gone now.
+ * c-exp.y, ch-exp.y, core.c, corelow.c, eval.c, fork-child.c,
+ m2-exp.y, minsyms.c, nlmread.c, parse.c, putenv.c, regex.c
+ remote-utils.c, stabsread.c: Include <string.h>.
+ * regex.c: Include "defs.h", change re_comp argument to const char *.
+ * infptrace.c (fetch_register, store_inferior_registers): Change
+ regaddr to type CORE_ADDR.
+ * config/alpha/alpha-nw.mt, config/alpha/alpha-osf1.mt (MT_CFLAGS):
+ Remove, no longer necessary now that we use bfd_vma for a CORE_ADDR.
+
+Mon Feb 7 09:21:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * symtab.h: Always define BYTE_BITFIELD to nothing.
+
+Mon Feb 7 08:44:17 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/m68k/{m68k-em.mt,tm-m68k-em.h}: Remove; no longer used.
+ * configure.in: Remove comment about m68k-em.mt.
+ * Makefile.in: Remove references.
+
+Mon Feb 7 08:22:42 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * defs.h [BFD64]: Use BFD_HOST_64_BIT, not nonexistent
+ BFD_HOST_64_TYPE.
+
+Sun Feb 6 15:56:09 1994 Jeff Law (law@wild.cs.utah.edu)
+
+ * hpread.c (hpux_symfile_init): Use obj_som_* rather than obj_* to
+ access BFD private data. Search for the "$TEXT$" space rather
+ than ".text".
+ (hppa_sym_fns): Add bfd target flavour to initializer.
+
+Sun Feb 6 06:55:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.c (target_preopen): If target_kill doesn't remove the
+ target from the stack, use pop_target to do it.
+
+ * coffread.c (process_coff_symbol, case C_TPDEF): Don't set name
+ of TYPE_CODE_PTR or TYPE_CODE_FUNC types. This parallels similar
+ changes to stabsread.c from summer 1993.
+
+ * remote-udi.c (udi_files_info): If prog_name is NULL, just skip
+ printing the program, rather than passing NULL to printf.
+ (udi_detach): Set udi_session_id to -1 so that udi_close doesn't
+ try to call UDIDisconnect again. Print better message.
+ (udi_kill): Just call UDIDisconnect ourselves, rather than doing
+ it via udi_close.
+ (udi_create_inferior): If udi_session_id is negative, open a new
+ TIP rather than giving an error.
+
+ * config/mips/mipsm3.mh, config/i386/i386m3.mh,
+ config/ns32k/ns32km3.mh: Define NAT_FILE.
+ * config/nm-m3.h: Change guard from _OS_MACH3_H_ and _OS_MACH3_H
+ (it was inconsistent and namespace-wrong) to NM_M3_H.
+ * m3-nat.c (mach_really_wait): Change parameter name to ourstatus.
+ (m3_open): New function.
+ (m3_ops): Use it.
+ * TODO: Update Mach section.
+
+ * Makefile.in: Remove "rapp" stuff; it is superseded by gdbserver.
+
+Sun Feb 6 13:26:21 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * printcmd.c (printf_command): Add missing single-letter
+ backslash-escape sequences, and improve error message.
+
+Sun Feb 6 06:55:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * corelow.c (solib_add_stub, core_open): Pass address of from_tty
+ rather than trying to shove an int into a pointer and back out
+ again. This avoids compiler warnings.
+
+ * defs.h (alloca): Declare as void *, not char *, on hpux.
+ Don't prototype it, just declare the return type.
+
+Sun Feb 6 03:25:41 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/tm-sun386.h, config/i386/tm-symmetry.h
+ (REGISTER_CONVERT_TO_RAW): Add missing backslash.
+
+Sat Feb 5 08:03:41 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-mips.c (mips_fetch_registers): If regno is FP_REGNUM or
+ ZERO_REGNUM, just read it as zero without talking to the board.
+
+ * config/i386/tm-i386aix.h (REGISTER_CONVERT_TO_RAW): Add missing
+ backslash.
+ * i386-tdep.c (i386_extract_return_value): Pass TYPE_LENGTH (type)
+ to store_floating, not nonexistent variable len.
+
+ * remote-mips.c (mips_insert_breakpoint, mips_remove_breakpoint):
+ New functions.
+ (mips_store_word): Change calling convention to return errors, and
+ to provide old contents if the caller wants it.
+ (mips_xfer_memory): Deal with errors from mips_store_word.
+ * config/mips/tm-idt.h, config/mips/tm-idtl.h: Remove BREAKPOINT
+ define now that remote-mips.c doesn't use BREAKPOINT.
+
+ * remote-mips.c (mips_create_inferior): Call warning if arguments
+ specified, and then execute "set args" command. Call error, not
+ mips_error, if executable file not specified.
+
+ * remote-e7000.c: Replace "snoop" command (e7000_noecho) with
+ remote_debug.
+
+ * config/rs6000/tm-rs6000.h (STORE_STRUCT_RETURN): Don't cast
+ to unsigned int.
+
+Sat Feb 5 05:27:05 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * value.h (print_longest): Rename "value" to "val" in prototype
+ declaration because some compilers don't like arguments whose
+ names are the same as types.
+ * remote.c (remote_xfer_memory): Cast "myaddr" to unsigned char *
+ before passing it to remote_*_bytes.
+
+Fri Feb 4 15:53:18 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * h8500-tdep.c (saved_pc_after_call): The size of the
+ pc is memory model dependent. (segmented_command,
+ unsegmented_command, _initialize_h8500_tdep): New commands to
+ change memory model.
+ * remote-e7000.c (_initialize_remote_e7000): Change name of snoop
+ command.
+ * remote-hms.c (hms_load): Remove breakpoints when loaded.
+ (hms_wait): Use new status structure
+ (hms_open): Push the target here. (hms_before_main_loop): Not
+ here. (supply_val, hms_fetch_register, hms_store_register): Cope
+ with H8/500 names too. (hms_fetch_register): Take out REGISTER_TYPE.
+ * sh-tdep.c (show_regs, initialize_sh_tdep): New command to print
+ all registers in a compact way.
+
+Fri Feb 4 07:41:13 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * config/rs6000/tm-rs6000.h: Declare rs6000_struct_return_address
+ as CORE_ADDR to match definition in rs6000-tdep.c.
+
+Fri Feb 4 01:14:20 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dwarfread.c (process_dies): Skip nested TAG_compile_unit DIEs.
+ * dwarfread.c (add_partial_symbol): Do not enter opaque aggregate
+ definitions into the psymtab.
+
+Thu Feb 3 12:38:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m68k-stub.c: Treat mc68332 like mc68020 most places. Provide
+ a special exceptionSize for the 68332.
+
+ * remote-udi.c (udi_attach): If no arguments, print error.
+
+Thu Feb 3 17:34:05 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (VERSION): Bump to 4.12.1
+ * NEWS, README: Update to match 4.12 release.
+
+Thu Feb 3 12:38:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * command.c (empty_sfunc): New function.
+ (add_set_cmd): Use it instead of not_just_help_class_command.
+ (not_just_help_class_command): Change calling convention back to
+ what it was before yesterday's change.
+
+ * stabsread.c (read_sun_builtin_type): Skip the semicolon at the end
+ of the type if present.
+
+Wed Feb 2 11:16:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (decode_format): Don't blithely set the size for
+ an address to 'w'. Make it 'g' or 'h', depending on TARGET_PTR_BIT.
+
+ * defs.h: Just typedef CORE_ADDR to bfd_vma. Include bfd.h.
+ If BFD64, make a LONGEST a BFD_HOST_64_BIT.
+ * defs.h (longest_to_int): Don't depend on CC_HAS_LONG_LONG; instead
+ always just check against INT_MIN and INT_MAX (this also fixes things
+ if sizeof (long) > sizeof (int), e.g. Alpha).
+ * config/pa/tm-hppa.h, config/i386/sun386.h, config/rs6000/tm-rs6000.h:
+ Don't define LONGEST or BUILTIN_TYPE_LONGEST.
+ * gdbtypes.h: Remove BUILTIN_TYPE_LONGEST and
+ BUILTIN_TYPE_UNSIGNED_LONGEST.
+ * language.h, c-lang.c, ch-lang.c, m2-lang.c, language.c: Remove
+ longest_int and longest_unsigned_int.
+ * value.h (struct value): Just align to LONGEST, rather than worrying
+ about CC_HAS_LONG_LONG.
+ * valarith.c (value_binop): Figure out type ourself based on
+ sizeof (LONGEST) rather than relying on BUILTIN_TYPE_LONGEST. The
+ point is that we don't depend on CC_HAS_LONG_LONG anymore.
+ * valprint.c (val_print_type_code_int): Just call
+ extract_unsigned_integer directly, rather than going through
+ unpack_long.
+ * printcmd.c (decode_format): Remove code which would sometimes
+ change 'g' size to 'w' for integers. print_scalar_formatted handles
+ printing huge integers well enough, thank you.
+
+ * command.c (add_set_cmd, not_just_help_class_command): Change
+ to make this the sfunc, not cfunc, since that is how we call it.
+ * command.h: Comment difference between sfunc and cfunc.
+ * demangle.c (set_demangling_command): Add third arg since that
+ is how it is called.
+ (_initialize_demangler): Use sfunc, not cfunc, for
+ set_demangling_command, since that is how it is called.
+ Remove show_demangling_command; it has no effect.
+
+ * command.c (shell_escape): Report errors correctly (with error
+ message from strerror).
+
+Wed Feb 2 14:35:41 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): Change CSECT_LEN to use
+ x_scnlen.l rather than x_scnlen to match corresponding change in
+ coff/internal.h.
+
+Wed Feb 2 11:16:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbtypes.h, ch-typeprint.c, ch-valprint.c:
+ Change comments regarding TYPE_CODE_BOOL.
+ * language.c (boolean_type): Always return 1 for TYPE_CODE_BOOL,
+ regardless of the language.
+ (value_true): Just call value_logical_not regardless of language.
+ * coffread.c (coff_read_enum_type), stabsread.c (read_enum_type):
+ Remove #if 0'd code which makes some enums TYPE_CODE_BOOL.
+ * language.h: Improve comment for la_builtin_type_vector.
+ * m2-lang.c (_initialize_m2_language): Don't add any fields to
+ builtin_type_m2_bool.
+
+Tue Feb 1 17:13:32 1994 Kevin Buettner (kev@cujo.geg.mot.com)
+
+ * config/m88k/{tm-delta88.h,tm-delta88v4.h}, m88k-tdep.c:
+ Define IN_SIGTRAMP and backtrace correctly through signal handlers.
+
+Tue Feb 1 22:13:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * procfs.c (wait_fd): Handle EINTR error return from PIOCWSTOP ioctl
+ by restarting the ioctl.
+
+Tue Feb 1 16:16:25 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.h (target_wait): Add comment about calling
+ return_to_top_level.
+
+Tue Feb 1 12:21:00 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * coffread.c (read_one_sym): bfd_coff_swap_aux_in now takes
+ additional arguments.
+ * xcoffread.c (read_xcoff_symtab, read_symbol_lineno): Likewise.
+
+Mon Jan 31 16:10:41 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-stub.c: Remove unnecessary #include of memory.h.
+
+Mon Jan 31 12:12:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c: Remove code which sets saved_regs from
+ init_extra_frame_info and put it in new function mips_find_saved_regs.
+ (READ_FRAME_REG): Remove macro and replace uses with the expansion.
+ * mips-tdep.c, config/mips/tm-mips.h: When examining ->saved_regs,
+ check if it is NULL and call mips_find_saved_regs if so.
+
+ * remote-mips.c: Use unfiltered, not filtered, output most places.
+
+ * blockframe.c (get_prev_frame_info): Detect and stop an infinite
+ backtrace. Revise comments.
+
+Mon Jan 31 09:40:33 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_procedure): Remove _sigtramp kludges for
+ alpha and irix. The _sigtramp case has to be handled properly
+ in the tdep files if we have no ecoff debugging info.
+ * alpha-tdep.c (alpha_frame_saved_pc, alpha_frame_chain),
+ mips-tdep.c (mips_frame_saved_pc): Handle signal handler frames
+ without PC_REGNUM kludge.
+ * mdebugread.c (fixup_sigtramp), mips-tdep.c (read_next_frame_reg):
+ Clean up handling of mips sigtramp frames, improve comments.
+
+Sat Jan 29 23:25:57 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * paread.c (read_unwind_info): Fix typo.
+
+ * paread.c (pa_symtab_read): Update the "check_strange_names"
+ filter to match GCC's current output. Filter out section symbols
+ (which the HP linker sometimes puts in the wrong place).
+
+Sat Jan 29 07:44:59 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * serial.h (SERIAL_SET_TTY_STATE): Comment return value.
+
+ * Makefile.in (TAGS): Just echo one line, rather than the whole thing.
+
+ * Makefile.in: Remove all references to sparcly-nat.c.
+
+ * Makefile.in (HFILES_NO_SRCDIR): Include dcache.h remote-utils.h
+ remote-sim.h directly, rather than via $(remote_utils_h). This avoids
+ duplicating serial.h and target.h.
+
+ * Makefile.in: Don't set M_INSTALL and M_UNINSTALL. These variables
+ are not used anywhere (a 5 Oct 1993 change removed the uses).
+
+ * config/m68k/monitor.mt (TDEPFILE): Add remote-es.o.
+ * config/m68k/es1800.mt: Add comment.
+ * remote-es.c: Extensive changes to update to current conventions.
+
+ * ser-unix.c (wait_for, hardwire_readchar) [HAVE_TERMIO, HAVE_TERMIOS]:
+ If the timeout is too big to fit in c_cc[VTIME], then do multiple reads
+ to achieve the desired timeout.
+ * serial.h (serial_t): Add field timeout_remaining.
+
+Fri Jan 28 08:45:02 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * c-exp.y (yylex): Reenable nested type code.
+
+Fri Jan 28 15:40:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * a29k-tdep.c (examine_tag): Add comment regarding argcount.
+
+ * remote-mips.c (mips_ops): Fix docstring.
+
+ * remote-bug.c (bug_ops): Remove spurious newline from docstring.
+
+ * config/m68k/tm-monitor.h: Changes to bring this into accordance
+ with the old tm-m68k-em.h:
+ (GDBINIT_FILENAME, DEFAULT_PROMPT): Remove.
+ (HAVE_68881): Don't undefine; HAVE_68881 is obsolete.
+ (REGISTER_NAMES): Don't muck with it; what tm-m68k.h has is fine.
+ Add FIXME regarding GET_LONGJMP_TARGET.
+
+ * remote-udi.c (udi_close, udi_detach, udi_kill): Add comments.
+ * infptrace.c (kill_inferior): Add comments.
+ * main.c (quit_command): Call target_close after we kill or
+ detach.
+ * remote-udi.c (udi_close): Don't error() if QUITTING.
+
+Fri Jan 28 11:55:52 1994 Rob Savoye (rob@darkstar.cygnus.com)
+
+ * configure.in: Make m68k-coff and aout add monitor support in
+ addition to the standard serial support.
+
+Fri Jan 28 08:45:02 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * mdebugread.c (psymtab_to_symtab_1): Don't complain on stLabel with
+ index indexNil.
+
+Fri Jan 28 10:40:34 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/pa/tm-hppa.h: Define macro SMASH_TEXT_ADDRESS.
+ * elfread.c (record_minimal_symbol_and_info),
+ dwarfread.c (process_dies), paread.c (pa_symtab_read): Use it.
+
+Thu Jan 27 15:12:23 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i386-stub.c: Add ".text" right before "mem_fault:".
+
+ * main.c (baud_rate): Add FIXME comment about printing -1 value.
+
+ * remote-utils.c (usage): Fix message to be accurate and conform
+ more closely to normal conventions.
+
+ * remote-utils.c (gr_files_info): Have the exec_bfd test control
+ whether to show information about exec_bfd, and not control whether
+ to show information about device and speed.
+
+ * remote-utils.c (gr_open): If sr_get_device returns NULL, give
+ usage message, don't dump core.
+
+ * remote-bug.c (bug_write_memory): Use alloca, not GCC extension
+ for variable size array.
+ (bug_fetch_register, bug_store_register): Rename "value" to
+ "fpreg_buf" because some compilers don't like variables whose
+ names are the same as types.
+ (bug_store_register): Use a cast when converting char * to
+ unsigned char *.
+
+ * symmisc.c (maintenance_print_symbols): Don't refer to the name
+ of the command in error message (the text was referring to the old
+ name of the command).
+
+ * symmisc.c (dump_symtab): Fix args to fprintf_filtered.
+
+ * c-typeprint.c (c_type_print_base): Have SHOW == 0 mean to print
+ full details on structure elements without names. This partially
+ reverts the changes of 1 Jul 1993 and 31 Aug 1993; I think this aspect
+ of those changes was accidental.
+
+ * stack.c (parse_frame_specification): If SETUP_ARBITRARY_FRAME is
+ defined, make it an error to specify a single argument which is not
+ a frame number.
+
+ * Makefile.in (version.c), main.c (print_gdb_version): Use
+ host_alias and target_alias, not host_canonical and
+ target_canonical, to print configuration.
+
+Wed Jan 26 10:57:21 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * parse.c (write_exp_msymbol): Use new type msymbol_addr_type instead
+ of builtin_type_long. It is necessary to get a type which is
+ TARGET_PTR_BIT bits in size; builtin_type_long might not be big enough.
+
+ Fix many sins which will come up in 32 bit x 64 bit GDB, and
+ various miscellaneous things discovered in the process:
+ * printcmd.c, defs.h (print_address_numeric): New function.
+ * c-valprint.c (c_val_print), ch-valprint.c (chill_val_print)
+ breakpoint.c (describe_other_breakpoints, breakpoint_1, mention),
+ cp-valprint.c (cplus_print_value), infcmd.c (jump_command),
+ printcmd.c, stack.c, symfile.c, symmisc.c, valprint.c:
+ Use it.
+ * utils.c, defs.h (gdb_print_address): New function.
+ * expprint (dump_expression), gdbtypes.h: Use it.
+ * breakpoint.c (describe_other_breakpoints),
+ symmisc.c (dump_symtab, print_symbol):
+ Use filtered not unfiltered I/O.
+ (remove_breakpoints): Remove BREAKPOINT_DEBUG code. Might as well
+ just run gdb under a debugger for this (and it had problems with
+ printing addresses, how to print b->shadow, etc.).
+ * buildsym.c (make_blockvector), core.c (memory_error),
+ exec.c (print_section_info), maint.c (print_section_table),
+ mdebugread.c (parse_procedure), solib.c, source.c, symfile.c,
+ symmisc.c, symtab.c, valops.c, valprint.c, xcoffexec.c:
+ Add comments saying code is broken. Marked with "FIXME-32x64".
+ * dbxread.c (process_one_symbol), partial-stab.h (default),
+ remote-vx.c (vx_run_files_info):
+ Don't cast int being passed to local_hex_string.
+ * symmisc.c (print_symbol): Don't cast long being passed to %lx.
+ * symtab.h (general_symbol_info): Add comment about SYMBOL_VALUE
+ only being a long.
+ * symmisc.c (print_symbol): Print "offset" in message for LOC_ARG
+ and LOC_LOCAL.
+ * printcmd.c (print_address): Remove #if 0 code with ADDR_BITS_REMOVE.
+ * source.c: Include <sys/types.h> regardless of USG.
+
+Tue Jan 25 12:58:26 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * valops.c (value_assign): Set `type' after coercing toval.
+ * c-valprint.c (c_val_print), ch-valprint.c (chill_val_print):
+ Use extract_unsigned_integer to get the address of a reference.
+
+Tue Jan 25 11:31:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (STABS_CONTINUE, error_type), partial-stab.h:
+ AIX can use ? instead of \ for continuation. Deal with it.
+
+ * paread.c (read_unwind_info): Just assign to objfile->obj_private,
+ not OBJ_UNWIND_INFO. Assigning to a cast is a GCC-ism which
+ the HP compiler in ANSI mode doesn't like.
+
+ * main.c: When defaulting HAVE_SIGSETMASK based on USG, just do it
+ based on USG, rather than defining HAVE_SIGSETMASK to an
+ expression containing defined. Having a macro used in #if expand
+ to an expression containing "defined" is undefined according to
+ ANSI, and the HP compiler in ANSI mode doesn't do what we wanted
+ it to.
+
+Mon Jan 24 20:51:29 1994 John Gilmore (gnu@cygnus.com)
+
+ * sparc-nat.c (fetch_inferior_registers, store_inferior_registers):
+ Clean up the changes of 11 Jan, as recommended by Peter Schauer.
+
+Fri Jan 21 19:10:44 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * ch-exp.y (match_string_literal): Allow a zero-length string.
+ * ch-lang.c (chill_printstr): Don't print zero-length string funny.
+
+Sat Jan 22 17:08:48 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i386aix-nat.c (i386_float_info): Reverse order of registers before
+ passing them to print_387_status.
+ (print_387_status): Don't subtract top from 7 before using it.
+ * i387-tdep.c: Remove comment about AIX wanting "top" subtracted
+ from 7; the above explains it.
+
+Sat Jan 22 20:25:11 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (init_extra_frame_info): Use frame relative stack
+ pointer value when fixing up the frame at the start of a function.
+
+Sat Jan 22 12:29:13 1994 Stu Grossman (grossman at cygnus.com)
+
+ * lynx-nat.c (fetch_core_registers): Load the I & L regs for the
+ Sparc from the stack.
+
+Sat Jan 22 08:30:42 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote-mips.c (mips_initialize): Clear mips_initializing via
+ cleanup chain, not directly.
+
+ * ser-unix.c (wait_for) [HAVE_TERMIO, HAVE_TERMIOS]: Make a timeout
+ of -1 mean forever, like in the HAVE_SGTTY case. Warn if we are
+ munging the timeout due to the limited range of c_cc[VTIME].
+
+ * fork-child.c, inferior.h (fork_inferior): New argument shell_file.
+ * procfs.c (procfs_create_inferior), inftarg.c (child_create_inferior),
+ m3-nat.c (m3_create_inferior): Pass it.
+ * procfs.c: Remove ptrace function. It was declared in a way which
+ conflicted with the prototype in unistd.h on Solaris.
+
+Sat Jan 22 01:37:40 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (frame_saved_pc): Get the pc from the saved pc
+ in the sigcontext if it is a signal trampoline frame.
+ * config/sparc/tm-sun4sol2.h (IN_SIGTRAMP, SIGCONTEXT_PC_OFFSET):
+ Define for Solaris2.
+
+Sat Jan 22 00:34:47 1994 Stu Grossman (grossman at cygnus.com)
+
+ * sparc-tdep.c, lynx-nat.c, config/sparc/tm-sparc.h,
+ config/sparc/tm-sparclynx.h: Move defs of FRAME_SAVED_I0/L0 to
+ tm-sparc.h so they can be overridden if necessary.
+
+Fri Jan 21 17:49:28 1994 Stu Grossman (grossman at cygnus.com)
+
+ * lynx-nat.c: Add Sparc support.
+ * sparcly-nat.c: Remove. It's useless.
+ * config/sparc/nm-sparclynx.h: Rewrite.
+ * config/sparc/sparclynx.mh (NATDEPFILES): Replace sparcly-nat.o
+ with lynx-nat.o
+ * config/sparc/tm-sparclynx.h: Rewrite.
+
+Fri Jan 21 19:08:48 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * rs6000-pinsn.c: Use the new disassembler in the opcodes
+ directory. Old code was discarded, since the new opcode table has
+ a different format.
+
+Fri Jan 21 14:28:30 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (realclean): Remove info files per make-stds.texi.
+
+Fri Jan 21 12:47:53 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c (end_psymtab): Only patch psymtab textlow and texthigh
+ if N_SO_ADDRESS_MAYBE_MISSING is defined.
+ * config/sparc/tm-sun4sol2.h: Define it.
+
+Thu Jan 20 15:04:24 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * printcmd.c (print_address_symbolic): Unconditionally use msymbol
+ if we did not find a symbol.
+
+Fri Jan 21 08:20:18 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * infptrace.c (child_xfer_memory): Only use if CHILD_XFER_MEMORY
+ is not defined.
+
+ * hppab-nat.c (call_ptrace): Delete redundant function.
+ (kill_inferior, attach, detach, child_resume): Likewise.
+ (child_xfer_memory): Likewise.
+
+ * hppah-nat.c (call_ptrace): Delete redundant function.
+ (kill_inferior, attach, detach, child_resume): Likewise.
+
+ * config/pa/hppabsd.mh (NATDEPFILES): Add infptrace.o.
+
+ * config/pa/hppahpux.mh (NATDEPFILES): Add infptrace.o.
+
+ * config/pa/nm-hppab.h (FETCH_INFERIOR_REGISTERS): Define.
+
+ * config/pa/nm-hppah.h (FETCH_INFERIOR_REGISTERS): define.
+ (CHILD_XFER_MEMORY): Define.
+ (PT_*): Define so that generic infptrace.c code can be used.
+
+Fri Jan 21 09:23:33 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (xcoff_symfile_read): Make second parameter a
+ struct section_offsets *, not a (nonexistent) struct section_offset *.
+
+ * xcoffread.c (read_xcoff_symtab): Make main_aux just a union
+ internal_xcoff_symtab, not an array of one of them. Change lots of
+ "main_aux" to "&main_aux" and so on.
+
+ * coffread.c, xcoffread.c: Include <coff/internal.h>
+ before "symfile.h".
+
+Thu Jan 20 17:30:55 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * coffread.c (coff_getfilename): Make it not static.
+
+ * xcoffread.c (read_xcoff_symtab): complain() not abort().
+
+ * xcoffread.c (struct coff_symbol): Rename c_nsyms to c_naux (removes
+ a completely gratuitous difference between xcoffread.c and coffread.c).
+
+Wed Jan 19 15:09:44 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Don't set frame for
+ step_resume_breakpoint for IN_SIGTRAMP cases.
+
+ * infrun.c (wait_for_inferior), breakpoint.h (struct bpstat_what),
+ breakpoint.c (bpstat_what): Move step_resume from its own field of
+ the struct bpstat_what into the main_action. Make it override
+ other breakpoints. This is a conservative change in the sense
+ that before the step resume breakpoint was a breakpoint.c
+ breakpoint, hitting the step resume breakpoint overrode even
+ calling bpstat_stop_status.
+
+Wed Jan 19 12:40:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (normal_stop): Set stop_pc after popping the dummy frame
+ in case execution was stopped in the called function.
+ * stack.c (print_frame_info, frame_info): If backtracing through
+ a call dummy, handle the starting source line number on a line
+ boundary like backtracing through sigtramp.
+ * sparc-tdep.c (sparc_frame_find_saved_regs): Get frame address
+ for call dummy frame right. Remove old test for dummy frame,
+ it has been unused at least since gdb-3.5.
+ * sparc-tdep.c (sparc_push_dummy_frame): Set return address register
+ of the dummy frame.
+
+Tue Jan 18 16:16:35 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infcmd.c (signal_command): Accept 0 as legitimate signal number.
+
+Tue Jan 18 14:09:25 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (signals_info), target.c (target_signal_from_name):
+ Use ugly casts to avoid enumvar < enumvar or enumvar++.
+
+Mon Jan 17 22:00:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ser-unix.c (hardwire_noflush_set_tty_state): Don't muck with ICANON.
+ * inflow.c (terminal_ours_1): When discussing how to deal with the
+ tty state, make note of query() as well as readline.
+
+ * infrun.c (_initialize_infrun): Add TARGET_SIGNAL_POLL to list of
+ signals for which stop and print are cleared by default.
+
+Mon Jan 17 20:00:51 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (unwind_table_entry): Use one of the
+ reserved fields to hold a stub unwind entry type. Fix typo.
+ (stub_unwind_entry): New structure for raw stub unwind entries.
+ (stub_unwind_types): The types of stubs we may encounter.
+ (UNWIND_ENTRY_SIZE, STUB_UNWIND_ENTRY_SIZE): New defines.
+ * hppa-tdep.c (rp_saved): Use additional information provided
+ by linker stub unwind descriptors.
+ (frameless_function_invocation): Likewise.
+ (frame_chain_valid): Likewise.
+ * paread.c (compare_unwind_entries): New function for sorting
+ unwind table entries.
+ (read_unwind_info): Rewrite to remove dependency on host endianness.
+ Read in data from the $UNWIND_END$ subspace which contains linker
+ stub unwind descriptors. Merge that data into the basic unwind
+ table.
+
+ * hppab-nat.c (_initialize_kernel_u_addr): Delete unwanted functions.
+
+Mon Jan 17 22:00:15 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab, case C_FILE): Accept the name
+ from either the symbol name or the auxent.
+ * coffread.c, symfile.h (coff_getfilename): Renamed from getfilename,
+ no longer static.
+
+Mon Jan 17 13:35:01 1994 Fred Fish (fnf@cygnus.com)
+
+ * Makefile.in (ALLPARAM): Change irix5.h to nm-irix5.h.
+
+Mon Jan 17 12:35:42 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Update notes for alpha port.
+
+Mon Jan 17 11:15:57 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i960-tdep.c (i960_fault_to_signal): Return TARGET_SIGNAL_ILL
+ for operation fault, constraint fault, and type fault.
+
+Sun Jan 16 12:46:01 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (init.c): Add comment explaining formatting conventions.
+
+ * c-exp.y (parse_number): Assign to temporary between the right
+ shifts, to work around a bug in the SCO compiler.
+
+ * Makefile.in (ALLCONFIG, ALLPARAM, ALLDEPFILES, HFILES_NO_SRCDIR):
+ Add various files which were added to GDB recently.
+
+ * xcoffread.c (process_xcoff_symbol): Only change 'V' to 'S' if not
+ within_function.
+
+ * Makefile.in: Add mostlyclean target.
+
+Sat Jan 15 10:20:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Version 4.11.4.
+
+Sat Jan 15 18:27:34 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * main.c (show_commands): Make return type of extern
+ history_get be HIST_ENTRY, rather than struct _hist_entry.
+ (The latter loses with the upcoming merged readline.)
+
+Sat Jan 15 10:20:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * minsyms.c (prim_record_minimal_symbol_and_info): Make tempstring
+ const char *, not char *.
+
+ * symtab.h (struct symbol): Make section short, not unsigned short.
+
+ * symtab.c (lookup_symbol): Add comment about QUIT here.
+
+ * utils.c (fputs_unfiltered): Call fputs, not fputs_maybe_filtered.
+
+ * c-exp.y (parse_number): Check for overflow regardless of range
+ checking. Fix overflow check to use unsigned LONGEST, not
+ unsigned int.
+
+ * c-exp.y (parse_number): Make it so that integer constants are
+ builtin_type_long_long if builtin_type_long isn't big enough or if
+ an "LL" suffix is used. Properly handle "UL" or "LU" suffixes.
+
+ * c-typeprint.c (c_type_print_varspec_suffix, case TYPE_CODE_FUNC):
+ Print our "()" first, then recurse for the target type.
+
+Fri Jan 14 21:55:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-udi.c (udi_create_inferior): Quote empty execfile argument.
+
+ * gdbserver/low-lynx.c: Include <sys/wait.h> not "/usr/include/wait.h".
+
+Fri Jan 14 14:17:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (request_quit): Re-establish signal handler regardless
+ of USG.
+
+ * config/mips/xm-irix4.h: Define HAVE_TERMIOS.
+
+Fri Jan 14 21:55:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i960-tdep.c: Include target.h.
+
+Fri Jan 14 17:12:28 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * lynx-nat.c (sys/wait.h): Don't use absolute pathname.
+
+Fri Jan 14 11:06:10 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * lynx-nat.c (child_wait): Fix thinkos in struct target_waitstatus
+ changes (status -> ourstatus; declare status, etc.).
+ * config/nm-lynx.h: Fix child_wait prototype and include target.h.
+
+Fri Jan 14 14:17:06 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (ALLPARAM): Add config/nm-lynx.h.
+
+Fri Jan 14 11:49:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote-mips.c (mips_request, mips_wait): Correct prototypes.
+
+Fri Jan 14 11:37:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/i386/xm-linux.h: Define HAVE_TERMIOS.
+
+Fri Jan 14 01:04:36 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/alpha/tm-alpha.h (CALL_DUMMY): Improve comment.
+
+Thu Jan 13 10:32:38 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote-vx.c (vx_wait): Only call i960_fault_to_signal if I80960
+ is defined. Otherwise just report TARGET_SIGNAL_UNKNOWN.
+
+ * mips-tdep.c (mips_push_arguments): Byteswap struct_addr before
+ writing it.
+
+ Add search to target vector (#if 0'd until after 4.12):
+ * target.h (to_search, target_search): Add.
+ * gdbcore.h, core.c (generic_search): Add.
+ * remote.c (remote_search): Add.
+ * a29k-tdep.c (init_frame_info): Use target_search to find traceback
+ tag.
+
+ * printcmd.c (print_address_symbolic): If set print fast-symbolic-addr
+ is on, call find_pc_function rather than relying just on the minimal
+ symbols (probably only matters for symbol readers which don't put
+ statics in the minimal symbols, but changing this strikes me as
+ not conservative enough).
+ Initialize name_location in all cases.
+ If no symbol and no msymbol, don't print anything symbolic.
+
+ * a29k-tdep.c (push_dummy_frame): Add comment about saving lr0.
+
+Wed Jan 12 20:53:16 1994 John Gilmore (gnu@cygnus.com)
+
+ * printcmd.c (print_address_symbolic): Make it search the
+ symtabs for variables as well as functions. Add `set print
+ fast-symbolic-addr' and default it to fast (the old way).
+ Print line numbers for data items as well as functions.
+
+ * symtab.c (find_addr_symbol): Return the symtab and the symbol
+ address, if a symbol is found (take two more args pointing to
+ where to store these results).
+
+ * symtab.h (find_addr_symbol): Add prototype.
+
+Wed Jan 12 19:32:11 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * objfiles.h: Fix comments to reflect the fact that the phrase
+ "top of stack" always refers to where the pushing and popping takes
+ place, regardless of whether it is at the highest or lowest address.
+
+Wed Jan 12 13:23:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Do not set TYPE_TAG_NAME for
+ compiler generated tag names.
+ * mdebugread.c (parse_type): Handle cross references to qualified
+ aggregate types.
+ * valops.c (value_struct_elt): Improve error message if the
+ address of a method is requested from an object instance.
+ * valops.c (search_struct_method): Make name_matched non-static
+ to get it initialized correctly.
+ * config/i386/nm-i386sco.h (CANNOT_STORE_REGISTER): Define to
+ exclude segment register which are not writable on newer SCO versions.
+
+Wed Jan 12 14:44:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * go32-xdep.c: Remove unused function uerror.
+ (sigsetmask): Declare return type. Declare argument (to match the
+ way it is called). Explicitly return 0.
+
+Wed Jan 12 01:44:25 1994 John Gilmore (gnu@cygnus.com)
+
+ * symtab.h (struct symbol, general_symbol_info, minimal_symbol,
+ partial_symbol): Shrink the storage sizes of symbols, by making
+ enums into 1-byte bitfields when compiled __GNUC__, moving all the
+ enums and small ints to the end of each struct to improve
+ alignment, and switching the section number from int to unsigned
+ short.
+
+Wed Jan 12 00:16:26 1994 John Gilmore (gnu@cygnus.com)
+
+ * symtab.c (find_addr_symbol): New routine that will find the nearest
+ symbol associated with an address. It does so by exhaustive
+ search of the symtabs, so it's slow but complete.
+
+Tue Jan 11 23:57:30 1994 John Gilmore (gnu@cygnus.com)
+
+ * coffread.c (read_coff_symtab): Set PC bounds of _globals_ symtab
+ to [0,0] rather than [0, end of first source file]. This avoids
+ problems with other parts of GDB looking for linetables in the
+ _globals_ symtab. Eliminate variables num_object_files and
+ first_object_file_end.
+
+Tue Jan 11 00:53:46 1994 John Gilmore (gnu@cygnus.com)
+
+ * a29k-tdep.c (init_frame_info): Cast null arg to examine_tag.
+ (pop_frame): Restore PC2 and LR0 from dummy frames.
+ (push_dummy_frame): Save PC2 and LR0 into dummy frames.
+ (setup_arbitrary_frame): Handle 3 args and set up real frames.
+ * config/a29k/tm-a29k.h (FRAME_NUM_ARGS): Update comments.
+ (DUMMY_FRAME_RSIZE): Add 2 longwords for PC2 and LR0.
+ (SETUP_ARBITRARY_FRAME): Define.
+
+Tue Jan 11 06:59:10 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * infrun.c, config/mips/tm-irix5.h: Remove #if 0'd AT_FUNCTION_START.
+
+Tue Jan 11 14:27:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * remote-udi.c (udi_resume): Correct prototype.
+
+Tue Jan 11 11:10:30 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (FRAME_FIND_SAVED_REGS): Call
+ hppa_frame_find_saved_regs.
+ * hppa-tdep.c (dig_fp_from_stack): Delete function.
+ (prologue_inst_adjust_sp): New function.
+ (is_branch, inst_saves_gr, inst_saves_fr): New functions.
+ (skip_prologue): Completely rewrite to use unwind information.
+ (hppa_frame_find_saved_regs): Likewise.
+
+Tue Jan 11 06:59:10 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * remote-mips.c (mips_wait): Use new function mips_signal_from_protocol
+ to convert a signal number with appropriate bounds checking.
+
+ * remote-mips.c (mips_wait): Fix typos (0x177 -> 0177, 0x377 -> 0377).
+
+Tue Jan 11 00:53:46 1994 John Gilmore (gnu@cygnus.com)
+
+ * stack.c (frame_info): If FRAME_FIND_SAVED_REGS isn't defined,
+ print a newline to end the display anyway.
+
+ * sparc-tdep.c (sparc_pop_frame): Pop the fsr and csr (float and
+ coprocessor status regs) when popping a frame. This fixes
+ float exceptions that occur after calling inferior functions.
+
+ * sparc-nat.c (fetch_inferior_registers, store_inferior_registers):
+ Read and write the fsr (float status register) to/from the child
+ process along with the float regs. Remove Peter Schauer's change
+ of May 24 '93, which has higher overhead and doesn't solve the
+ real problem (which was that FSR wasn't being set).
+
+Mon Jan 10 23:16:42 1994 John Gilmore (gnu@cygnus.com)
+
+ * a29k-tdep.c (examine_prologue): Don't worry if the ASGEQ
+ stack overflow check isn't right after the register stack
+ adjustment instruction. Metaware R2.3u compiler moves other
+ things in front of it. This fix isn't perfect but is what's
+ running.
+
+Mon Jan 10 20:08:23 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * c-valprint.c (c_val_print): Treat TYPE_CODE_RANGE like TYPE_CODE_INT.
+
+ * config/alpha/alpha-netware.mt: Rename to alpha-nw.mt for 14
+ character filenames.
+ * configure.in: Change accordingly.
+
+Mon Jan 10 15:48:36 1994 Tom Lord (lord@rtl.cygnus.com)
+
+ * m68k-stub.c, sparc-stub.c: removed spurious introduction of
+ _filtered io routines from these two files.
+
+Fri Jan 7 12:42:45 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/i386/tm-i386v.h, config/m68k/tm-m68k.h, config/mips/tm-mips.h,
+ config/vax/tm-vax.h (CALL_DUMMY_BREAKPOINT_OFFSET): Define.
+ * mdebugread.c (parse_symbol): Handle enum sh.type produced by
+ DEC c89.
+ * mdebugread.c (add_line): Handle zero linenos produced by DEC c89.
+
+Fri Jan 7 12:55:25 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c (print_sys_errmsg): Call gdb_flush (gdb_stdout) before
+ printing to gdb_stderr.
+
+ * remote-udi.c (udi_kill): Don't close the connection, just set
+ inferior_pid to zero.
+ (udi_mourn): Call remove_breakpoints.
+
+ * remote-udi.c: Remove obsolete need_artificial_traps comment.
+
+ * i386b-nat.c (sregmap): If sEAX, etc., not defined, use tEAX, etc.
+
+Thu Jan 6 07:17:53 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * symtab.c (lookup_symbol): Don't try adding .c to the name.
+
+ * remote-bug.c: At the start of each section, reset srec_frame
+ back to 160.
+
+ * target.h: Add TARGET_WAITKIND_LOADED and TARGET_WAITKIND_SPURIOUS.
+ * target.c (store_waitstatus): Add CHILD_SPECIAL_WAITSTATUS hook.
+ * infrun.c (wait_for_inferior): Replace SIGTRAP_STOP_AFTER_LOAD with
+ code which looks for those two waitkinds. Use switch statement.
+ * config/rs6000/tm-rs6000.h: Replace SIGTRAP_STOP_AFTER_LOAD with
+ CHILD_SPECIAL_WAITSTATUS.
+
+ * procfs.c (procfs_wait): Fix argument name to match 4 Jan changes.
+ * Move target_signal_from_host, target_signal_to_host, and
+ store_waitstatus from inftarg.c to target.c. procfs needs them.
+ * target.c: Include "wait.h" and <signal.h>.
+ * target.h, infrun.c (proceed), proceed callers: Pass new code
+ TARGET_SIGNAL_DEFAULT instead of -1. This avoids problems with
+ enums being treated as unsigned and is cleaner.
+ * infrun.c (signals_info): Don't print TARGET_SIGNAL_DEFAULT or
+ TARGET_SIGNAL_0.
+ * infcmd.c (signal_command), infrun.c (signals_info):
+ Don't allow user to specify numeric equivalent of
+ TARGET_SIGNAL_DEFAULT.
+
+Tue Jan 4 15:34:36 1994 Stu Grossman (grossman@cygnus.com)
+
+ * config/alpha/alpha-netware.mt: New target support for Alpha
+ running Netware.
+ * configure.in: Add alpha-*-netware* target.
+
+Tue Jan 4 14:51:35 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * remote-mips.c (mips_wait): Fix ref to TARGET_WAITKIND_STOPPED.
+
+Tue Jan 4 09:47:14 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * target.h: Add enum target_waitkind, enum target_signal, and
+ struct target_waitstatus. Change status argument to target_wait to
+ be struct target_waitstatus * instead of int *.
+ * target.h, infrun.c, all targets: Change type of signal arguments
+ to resume(), proceed(), and target_resume() from int to enum
+ target_signal.
+ * All targets (*_wait, *_resume): Change accordingly.
+ * infcmd.c (program_info, signal_command), throughout infrun.c,
+ * fork-child.c, solib.c, hppa-tdep.c, osfsolib.c: Use this stuff.
+ * convex-xdep.c, convex-tdep.c: Add FIXME's (getting the Convex
+ signal code stuff right with the new signals would be non-trivial).
+ * inferior.h (stop_signal): Make it enum target_signal not int.
+ * target.c, target.h (target_signal_to_string, target_signal_to_name,
+ target_signal_from_name): New functions.
+ * inftarg.c, target.h (target_signal_to_host, target_signal_from_host,
+ store_waitstatus): New functions.
+ * procfs.c (procfs_notice_signals): Use them.
+ * i960-tdep.c (i960_fault_to_signal): New function, to replace
+ print_fault.
+ * config/i960/tm-i960.h: Don't define PRINT_RANDOM_SIGNAL.
+
+ * objfiles.c (build_objfile_section_table): Don't abort() if
+ objfile->sections is already set.
+
+ * objfiles.c (add_to_objfile_sections): Check SEC_ALLOC not SEC_LOAD
+ to match recent change to exec.c.
+
+ * Version 4.11.3.
+
+ * main.c (print_gdb_version): Change year to 1994.
+
+ * ChangeLog, ChangeLog-93: Split ChangeLog at 1994.
+ * Makefile.in (NONSRC): Add ChangeLog-93.
+
+Mon Jan 3 11:57:29 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabsread.c (read_type): Allow defining several type numbers
+ at once (e.g. "(1,2)=(3,4)="...).
+
+ * stabsread.c (read_enum_type): Use TARGET_INT_BIT not sizeof (int).
+
+ * breakpoint.c (frame_in_dummy): Check PC as well as frame.
+
+Mon Jan 3 02:47:03 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (psymtab_to_symtab_1): Only pass N_STAB symbols
+ to process_one_symbol.
+ * symtab.c (find_pc_psymbol): Search global_psymbols as well to
+ avoid caching a bad endaddr in find_pc_partial_function.
+
+Sun Jan 2 21:41:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/tm-sun3.h: Don't define BELIEVE_PCC_PROMOTION.
+
+Sat Jan 1 04:35:23 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * infrun.c (wait_for_inferior): Do not step or step resume past
+ the end of a one-line function we just stepped into.
+
+For older changes see ChangeLog-93
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/contrib/gdb/gdb/ChangeLog-95 b/contrib/gdb/gdb/ChangeLog-95
new file mode 100644
index 0000000..cdf4dda
--- /dev/null
+++ b/contrib/gdb/gdb/ChangeLog-95
@@ -0,0 +1,4882 @@
+Fri Dec 29 16:30:58 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * symfile.c (find_sym_fns): Add PowerMac to xcoff file recognition
+ kludge.
+
+
+Fri Dec 22 11:05:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (gdb_host): Add support for DG/UX running on x86 as
+ a host.
+ (all x86 targets and hosts): Add support for pentium-pro machines.
+
+ * configure: Rebuild.
+
+ * config/i386/i386dgux.mh: New file for DG/UX running on x86 host.
+
+Thu Dec 21 19:09:20 1995 Rob Savoye <rob@chinadoll.cygnus.com>
+
+ * remote-array.c (array_wait): Poll the keyboard along with the
+ serial port so users can tpye at the target while their
+ application is running.
+
+Thu Dec 21 11:58:52 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (ppcbug-rom.o, srec.o): Add dependencies.
+
+ * monitor.c (monitor_debug): Take prefix, and suffix arguments.
+ Print trailing newline after the suffix.
+ (monitor_printf{,_noecho}): Change monitor_debug calls.
+ (monitor_printf): Call monitor_expect instead of trying to do the
+ expect processing locally so that if there is extra junk, it
+ doesn't hang things up.
+ (readchar): If MO_HANDLE_NL is set, handle \r\n pairs and convert
+ them to a single \r. Use monitor_debug to print out byte read.
+
+ * monitor.h (MO_HANDLE_NL): Add new flag.
+
+ * ppcbug-rom.c (ppcbug_ops{1,2}): Split into two ops, one that
+ uses lo 0 to load, and the other that uses lo 1. Set flag
+ MO_HANDLE_NL.
+ (ppcbug_open{0,1}): Clone and split to handle ppcbug_ops{1,2}.
+ (_initialize_ppcbug_rom): Set up both ppcbug_open{0,1}.
+
+Wed Dec 20 10:54:41 1995 Fred Fish <fnf@cygnus.com>
+
+ * defs.h: Delete extraneous whitespace at end of file.
+ * symfile.h: Move #include of demangle.h outside conditional.
+ * objfiles.h (struct objstats, OBJSTAT, OBJSTATS): New struct and
+ macros to hold per-objfile statistics for internal
+ instrumentation.
+ (struct objfile): Add OBJSTATS member, which is optional.
+ * buildsym.h (next_symbol_text_func): Now takes objfile argument.
+ Also update copyright to 1995.
+ * dbxread.c (dbx_next_symbol_text): Now takes objfile argument.
+ (dbx_symfile_init, coffstab_build_psymtabs, elfstab_build_psymtabs,
+ stabsect_build_psymtabs): Accumulate string table size.
+ (dbx_next_symbol_text, read_dbx_symtab, read_ofile_symtab):
+ Accumulate number of stabs symbols read.
+ * dwarfread.c (new_symbol, symthesize_typedef):
+ Accumulate number of full symbols created.
+ * gdbtypes.c (alloc_type): Accumulate number of types.
+ * maint.c (maintenance_print_statistics): New function.
+ * mdebugread.c (mdebug_next_symbol_text): Now takes objfile
+ argument.
+ * minsyms.c (prim_record_minimal_symbol_and_info): Accumulate
+ number of minimal symbols read.
+ * os9kread.c (read_os9k_psymtab): next_symbol_text takes objfile
+ arg.
+ * partial-stab.h: next_symbol_text takes objfile arg.
+ * stabsread.c (error_type, STABS_CONTINUE): Now takes objfile arg
+ and uses it to call next_symbol_text.
+ * symfile.c (add_psymbol_to_list, add_psymbol_addr_to_list):
+ Accumulate number of partial symbols created.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Accumulate number of partial
+ symbols created.
+ * symmisc.c (print_objfile_statistics): Print the per-objfile
+ internal instrumentation statistics gathered.
+ * xcoffread.c (xcoff_next_symbol_text): Now takes objfile argument.
+
+Fri Dec 15 16:15:55 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * top.c (set_endian_from_file): Use new bfd_big_endian macro.
+
+Fri Dec 15 12:21:10 1995 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mpw-make.sed: Add quotes to RIncludes reference.
+
+Fri Dec 15 13:18:55 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * remote-array.c: Remove bogus setting of baudrate to 4800. Their
+ hardware has real UARTS now.
+
+Mon Dec 11 18:19:16 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (powerpc-*-macos*): New target configuration.
+ * configure: Update.
+ * config/powerpc/macos.mh, config/powerpc/macos.mt,
+ config/powerpc/nm-macos.h, config/powerpc/tm-macos.h, mac-nat.c:
+ New files, native PowerMac debugging support.
+ * Makefile.in (mac-nat.o): Add build rule.
+ * mpw-config.in (enable_cflags): Add support.
+ (m68k-apple-macos, powerpc-apple-macos): Fix natdepfiles to
+ list object file instead of source file.
+ * mpw-make.sed (@ENABLE_CFLAGS@): Don't edit out, replace with
+ value of variable.
+ (install, install-only): Edit MPW-specific installation into
+ place of Unix shell code.
+ * mac-gdb.r: Fix version resources to use symbolic version strings.
+ (cfrg): New resource, code fragment for PowerMac.
+
+
+Mon Dec 11 14:13:03 1995 Fred Fish <fnf@amigalib.com>
+
+ * dbxread.c (process_one_symbol): When looking at the next
+ minimal symbol, check for end of the minimal symbol array
+ (symbol with NULL pointer for name) before dereferencing it.
+
+Mon Dec 11 15:56:55 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * eval.c (evaluate_struct_tuple): Fix thinko.
+
+Mon Dec 11 06:52:02 1995 Wilfried Moser (Alcatel) <moser@rtl.cygnus.com>
+
+ * ch-typeprint.c (chill_type_print_base): Slightly change of printing
+ of variant structures.
+
+Mon Dec 11 00:36:01 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_cast): Handle casts to and from TYPE_CODE_CHAR.
+ * ch-exp.c (match_integer_literal): Fix long long support.
+ * gdbtypes.c (get_discrete_bounds): Make TYPE_LENGTH (type) ==
+ sizeof (LONGEST) case work OK.
+
+Fri Dec 8 21:02:24 1995 Fred Fish <fnf@cygnus.com>
+
+ * coffread.c, dbxread.c, dstread.c, objfiles.c, os9kread.c,
+ symfile.c, symtab.c: Use "obstack.h" rather than <obstack.h>.
+
+Wed Dec 6 16:16:18 1995 Stu Grossman (grossman@cirdan.cygnus.com)
+
+ * remote-mips.c (mips_receive_header): Allow mips_syn_garbage to be
+ user-settable (via set syn-garbage-limit). Setting it to -1 makes
+ it unlimited.
+
+Tue Dec 5 18:33:43 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * gdbtypes.c (check_stub_method): Make sure we get back a function
+ string in the demangled name before we try to use it.
+
+Tue Dec 5 18:08:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_expect_regexp): Make static, add prototype.
+ * (monitor_read_memory_single): Call monitor_expect_regexp with
+ pointer to getmem_resp_delim_pattern, not entire struct.
+
+Tue Dec 5 15:51:25 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * c-lang.h (c_op_print_tab): Don't declare, some compilers
+ consider illegal if structure not defined, and only used
+ in c-lang.c anyway.
+
+Sun Dec 3 12:31:03 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * eval.c (evaluate_subexp_standard case): Fix typo.
+
+Sun Dec 3 11:59:21 1995 Jeffrey A. Law <law@cygnus.com>
+
+ * ch-exp.c (parse_named_record_element): Avoid aggregrate
+ initializations for automatic variables.
+
+ * hppa-tdep.c (hppa_alignof): Fix typo in last change.
+
+Sat Dec 2 19:32:57 1995 Fred Fish <fnf@cygnus.com>
+
+ * symfile.c (global_psymbols, static_psymbols): Remove, unused.
+
+Sat Dec 2 03:02:21 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-tdep.c (heuristic_proc_desc): Add heuristic to
+ determine the return address register, needed for OSF/1-3.2C.
+ * config/alpha/tm-alpha.h (T7_REGNUM, T9_REGNUM): Define.
+
+Fri Dec 1 07:23:57 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppcbug-rom.c (ppcbug_cmds): Turn on MO_GETMEM_READ_SINGLE
+ because PPCbug displays the memory as characters as well as hex.
+ Fix getmem/setmem commands.
+
+ * srec.c (load_srec): Fix off by one typo in last submission.
+
+ * rs6000-tdep.c (push_arguments): Fix typo.
+
+Thu Nov 30 23:54:17 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * language.c (lang_bool_type), language.h: New function.
+ * language.h (LA_BOOL_TYPE): New macro.
+ * eval.c (evaluate_subexp_standard) Use LA_BOOL_TYPE instead
+ of builtin_type_int where appropriate,
+ * valarith.c (value_subscript): Likewise.
+
+ * valops.c (value_slice): Implement (value) bitstring slices.
+ * valprint.c (val_print): If TYPE_LENGTH is zero, don't automatically
+ print "<incomplete type>" - Chill has zero-length (string) types.
+
+ * gdbtypes.c (check_stub_type): Removed; no longes needed.
+ * ch-exp.c (expect, parse_call): Tweak error messages.
+
+Wed Nov 29 13:35:18 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * scm-valprint.c (scm_isymnames): Remove "#@" prefix.
+ (scm_scmval_print): Do not print "#@" prefix.
+
+ * gdbtypes.h (enum type_code): Added TYPE_CODE_TYPEDEF.
+ (check_typedef): New prototype.
+ (CHECK_TYPEDEF): New macro.
+ (TYPE_DUMMY_RANGE): Removed.
+ * gdbtypes.c (get_discrete_bounds): Fix paren error; make more robust.
+ (create_array_type): Don't force_to_range_type; users of the
+ array are responsible for handling non-range index types.
+ (create_set_type): Likewise.
+ (force_to_range_type): Removed.
+ (check_typedef): New function handles stub types and typedefs.
+ (check_stub_type): Just call check_typedef. (To be removed.)
+ (recursive_dump_type): Handle TYPE_CODE_TYPEDEF.
+ * ch-lang.c (type_lower_upper): Use get_discrete_bounds.
+ (evaluate_subexp_chill): Handle string repetition.
+ Re-arrange to handle EVAL_AVOID_SIDE_EFFECTS better.
+ * ch-typeprint.c (chill_type_print_base): Handle TYPE_CODE_TYPEDEF.
+ Pass show=0 in recursive calls various places.
+ (case TYPE_CODE_ARRAY): Don't require index type to have
+ TYPE_CODE_RANGE.
+ (case TYPE_CODE_RANGE): Don't need to support TYPE_DUMMY_RANGE.
+ * gdbtypes.c, ch-lang.c, ch-typeprint.c (numerous places):
+ Add check_typedef/CHECK_TYPEDEF as needed.
+
+ * ch-exp.y: Replaced by ...
+ * ch-exp.c: New file. Use recursive-descent.
+ Recognize labelled array tuples and powerset ranges.
+ * Makefile.in: Update for no longer using yacc for ch-exp.
+
+ * c-lang.c: Make various functions non-static.
+ * c-lang.h: Add bunches of prototypes.
+ * cp-valprint.c (cp_print_value_fields): Also take address.
+ (cp_print_value): Likewise. Use baselcass_offset.
+ * stabsread.c (current_symbol): New static variable.
+ (type_synonym_name): Remove.
+ (read_type): If copying, make copy be a TYPE_CODE_TYPEDEF.
+ (read_array_type): Don't need to handle undefined element type here.
+ (cleanup_undefined_types): Ditto.
+ (read_range_type): Look for Chill ranges.
+ * valops.c (value_assign): Fix case lval_internalvar - don't try
+ to assign into old value (which might be too small!).
+ (value_coerce_array): No longer need special VALUE_REPEATED handling.
+ (value_arg_coerce): Cleaner array->pointer decay mechanism.
+ (search_struct_field): Use baseclass_offset rather than
+ baseclass_addr.
+ (value_slice): Use get_discrete_bounds.
+ * value.h (COERCE_VARYING_ARRAY): Take type argumnt as well.
+ * values.c (baseclass_offset): Change parameter interface.
+ (baseclass_addr): Removed.
+ * c-typeprint.c, c-valprint.c, ch-valprint.c, values.c, valops.c:
+ Add check_typedef/CHECK_TYPEDEF as needed.
+
+ * alpha-tdep.c, c-exp.y, h8500-tdep.c, f-exp.y, f-valprint.c,
+ findvar.c, hppa-tdep.c, infcmd.c, language.c, printcmd.c,
+ rs6000-tdep.c, symmisc.c, symtab.c, mdebugread.c:
+ Add check_typedef/CHECK_TYPEDEF as needed.
+
+ * f-typeprint.c, valarith.c, valprint.c, typeprint.c, eval.c:
+ Add check_typedef/CHECK_TYPEDEF as needed.
+ * f-typeprint.c: Various cleaning up.
+ * valarith.c (value_subscript): Also subscript bitstrings (for Chill).
+ * typeprint.c (print_type_scalar): Also support TYPE_CODE_RANGE.
+ * eval.c (evaluate_subexp_standard case OP_ARRAY): Implement
+ support for labelled array tuples and ranges in powerset tuples.
+ (init_array_element): New function.
+
+ * top.c (command_line_input): Only strip out an initial #-comment.
+ Looking for internal comments is language-specific (breaks Scheme).
+
+ * expression.h (enum exp_opcode): Add BINOP_RANGE.
+ * expprint.c (dump_expression): Support BINOP_RANGE.
+ * eval.c (evaluate_subexp_standard): Handle BINOP_RANGE (as error).
+ (case MULTI_SUBSCRIPT): Fix broken f77 value->int ad hoc conversion.
+ * ch-lang.c (chill_op_print_tab): Support BINOP_RANGE.
+ (evaluate_subexp_chill): Error on BINOP_COMMA.
+
+ * Makefile.in: Clean up so doc stuff stays in doc sub-dir.
+
+Wed Nov 29 16:39:50 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * monitor.c (monitor_debug): New function to print monitor debug
+ output in printable fashion.
+ (monitor_printf{,_noecho}): Call monitor_debug instead of
+ fputs_unfiltered.
+
+ * srec.c (load_srec): When printing srec debug information, do not
+ print the carriage return directly, instead print \\r followed by
+ a newline.
+
+Tue Nov 28 15:25:28 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (target_subdir): Define.
+ (CC_FOR_TARGET, CXX_FOR_TARGET): Use it to find target libraries.
+ * configure.in (X_CFLAGS): Fix typo.
+ (target_subdir): Set to "${target_alias}/" if cross.
+ * configure: Regenerated.
+
+ * dbxread.c (dbx_symfile_read): Set block_address_function_relative
+ for `pe' format files.
+
+Tue Nov 28 11:17:47 1995 Fred Fish <fnf@cygnus.com>
+
+ * magic.h: Renamed to gmagic.h to avoid <magic.h> conflict.
+ * magic.c: Renamed to gmagic.c in sympathy.
+ * eval.c, gmagic.c, config/tm-magic.h:
+ Include "gmagic.h" rather than "magic.h".
+
+Sat Nov 25 02:56:38 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (handle_psymbol_enumerators, parse_symbol):
+ Recognize enums from alpha cc -migrate.
+ (upgrade_type): Pass correct fd to parse_symbol when parsing
+ the index type of an array.
+ (parse_procedure, parse_lines, psymtab_to_symtab_1): Handle
+ unsorted procedure descriptors from Irix 5.x and Alpha OSF/1-3.x
+ shared libraries. Use CORE_ADDR instead of `unsigned long' in
+ procedure descriptor address computations.
+
+ * symtab.c (decode_line_1): Prevent accidental strchr match
+ of a null character with the terminating null character of
+ gdb_completer_quote_characters.
+ (cplusplus_hint): Make sure that only a single quote is printed
+ in the hint message.
+
+Fri Nov 24 16:17:01 1995 Jeffrey A Law (law@cygnus.com)
+
+ * top.c (recurse_read_control_structure): Don't make cleanups
+ here. Callers handle that correctly.
+
+Tue Nov 21 15:16:34 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * config/m68k/xm-hp300hpux.h: Define MMAP_BASE_ADDRESS and MMAP_INCREMENT.
+ Also force HAVE_MMAP to be defined since autoconf is currently broken
+ for detecting a working mmap under hpux.
+ * config/pa/xm-hppah.h (MMAP_BASE_ADDRESS): Tweak MMAP_BASE_ADDRESS
+ to a better value suggested by Jeffrey A Law (law@cygnus.com).
+
+Tue Nov 21 08:48:58 1995 Fred Fish <fnf@cygnus.com>
+
+ * config/pa/xm-hppah.h: Define MMAP_BASE_ADDRESS and MMAP_INCREMENT.
+ Also force HAVE_MMAP to be defined since autoconf is currently broken
+ for detecting a working mmap under hpux.
+ * objfiles.c (map_to_address): Have gdb print a warning when it
+ is compiled with HAVE_MMAP but without both MMAP_BASE_ADDRESS and
+ MMAP_INCREMENT defined (thus making it appear mmap doesn't work).
+
+Mon Nov 20 14:13:53 1995 Stu Grossman (grossman@cygnus.com)
+
+ * infrun.c (wait_for_inferior): Add support for dynamic function
+ trampolines. These are pieces of code between the caller and the
+ callee that figure out the address of the callee's code at run
+ time. Upon entry, we can't figure out the callee's address, so we
+ set a breakpoint within the trampoline where the address will be
+ known, and continue the target. Once we hit the breakpoint, we
+ break at the callee's address and proceed as usual.
+
+Mon Nov 20 11:12:34 1995 Fred Fish <fnf@cygnus.com>
+
+ * objfiles.c (allocate_objfile): Change warning message about mapped
+ symbol tables so that it is obvious that they are not supported on
+ this particular machine rather than implying they are not supported
+ at all in this version of gdb.
+
+Sun Nov 19 05:20:53 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * irix5-nat.c, osfsolib.c (solib_address): Return the name of the
+ containing solib.
+ * stack.c (print_frame_info): Use minimal symbol only if
+ fi->pc is in a known section.
+
+Sat Nov 18 11:19:35 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
+
+ * solib.c (solib_address): Return the name of the containing solib.
+ * solib.h (PC_SOLIB): New macro; define using solib_address.
+ * stack.c (print_frame_info) [PC_SOLIB]: If no function name, try
+ PC_SOLIB on the PC value.
+
+Sat Nov 18 04:09:31 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * annotate.c (annotate_source, annotate_frame_begin): Issue
+ `0x' prefix for the pc value, to remain consistent with previous
+ GDB versions.
+
+ * blockframe.c (find_pc_partial_function), config/pa/tm-hppa.h:
+ Remove Sun shared library transfer hack and
+ INHIBIT_SUNSOLIB_TRANSFER_TABLE_HACK, it is obsoleted by the
+ mst_solib_trampoline minimal symbols.
+
+ * blockframe.c (inside_main_func): Check main_func_*pc against
+ INVALID_ENTRY_*PC, not zero.
+ * symfile.c (init_entry_point_info): Initialize ei.*pc with
+ INVALID_ENTRY_*PC.
+ * mipsread.c (mipscoff_symfile_read): If the entry_file bounds
+ are still unknown after processing the partial symbols, then try
+ to set them from the minimal symbols.
+
+ * infcmd.c (registers_info): Error out if selected_frame is NULL.
+ * stack.c (return_command): Select new current frame silently if
+ not interactive.
+
+ * mipsread.c (read_alphacoff_dynamic_symtab): Ignore additional
+ DT_MIPS_LOCAL_GOTNO and DT_MIPS_GOTSYM entries.
+
+ * irix5-nat.c (solib_create_inferior_hook): Call solib_add only
+ if auto_solib_add_at_startup is nonzero.
+ (_initialize_solib): Add "set auto-solib-add" command.
+ * osfsolib.c (solib_create_inferior_hook): Call solib_add only
+ if auto_solib_add_at_startup is nonzero.
+ (_initialize_solib): Add "set auto-solib-add" command.
+
+Wed Nov 15 17:12:04 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * utils.c: Don't include sys/ioctl.h etc if MPW is host.
+
+Tue Nov 14 17:16:46 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/arm/tm-arm.h (ADDITIONAL_REGISTER_NAMES): Fix r5.
+ (FRAME_SAVED_PC): Minor clean up.
+
+Tue Nov 14 14:51:05 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_load_srec monitor_make_srec): Move all
+ S-record download code into srec.c.
+ * srec.c srec.h: New files. Contain S-record loading routines
+ formerly in monitor.c.
+ * serial.c serial.h: New routine just like fprintf, but uses
+ serial_t instead of FILE *.
+ * sh-tdep.c (frame_find_saved_regs init_extra_frame_info):
+ Don't add four to saved pc (makes things match manual). Also, fix
+ bug where we didn't get pc from stack frame correctly.
+ * config/sh/tm-sh.h (SAVED_PC_AFTER_CALL): Don't add four to
+ saved pc. Real hardware does this for you.
+ * sh3-rom.c (sh3_load): New routine. Sets up for download then
+ calls generic S-record loader.
+ * config/h8300/h8300.mt, config/h8500/h8500.mt,
+ config/m68k/monitor.mt, config/pa/hppapro.mt, config/sh/sh.mt:
+ Add srec.o to TDEPFILES.
+
+Tue Nov 14 15:57:36 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppcbug-rom.c: New file to support the Motorola PPCBUG monitor
+ for PowerPC's.
+
+ * config/powerpc/ppc{,le}-{eabi,sim}.mt (TDEPFILES): Include
+ ppcbug-rom.o, monitor.o, and srec.o
+
+ * config/i386/linux.mt (XDEPFILES): Include ser-tcp.o.
+
+Mon Nov 13 13:12:46 1995 Jeffrey A Law (law@cygnus.com)
+
+ * partial-stab.h: Remove GDB_TARGET_IS_HPPA kludge.
+
+Fri Nov 10 13:08:54 1995 Jeff Law (law@kahlua.cs.utah.edu)
+
+ * terminal.h (HAVE_SGTTY): Fix typo.
+
+Thu Nov 9 17:34:01 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (gdb_target): Build in the simulator for all
+ PowerPC eabi targets, not just eabisim, providing
+ --enable-sim-powerpc is used, or the host compiler is GCC.
+
+Thu Nov 9 14:04:05 1995 Raymond Jou (rjou@mexican.cygnus.com)
+
+ * mpw-config.in: Add variable with names of SIOW libraries.
+ * mpw-make.sed: Add an action to build SIOWgdb.
+
+Wed Nov 8 19:25:22 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Edit @ENABLE_CFLAGS@ out, mpw-configure can
+ add back in if necessary.
+
+Wed Nov 8 15:59:52 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * config/mips/vr4300.mt: Added simulator to default VR4300 build.
+
+Tue Nov 7 16:02:25 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-mips.c (mips_initialize): Fix brain damage found by
+ Jamie. Basically had case statement in the wrong place...
+ * (mips_load): Remove unnecessary `db tty0' command. It's all
+ handled by mips_initialize now.
+
+Tue Nov 7 12:59:14 1995 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mac-gdb.r: Added #ifdef Macgdb.
+
+Tue Nov 7 14:59:51 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * remote-mips.c (mips_initialize): Updated to talk to VR4300 RISQ
+ monitor board.
+
+Mon Nov 6 11:44:11 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * config/mips/{tm-vr4300.h tm-vr4300el.h} (TARGET_MONITOR_PROMPT):
+ Change into real strings.
+
+ * remote-sim.c (gdbsim_open): Moved sim_open() call to after
+ callback initialisation.
+
+Sun Nov 5 00:07:52 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in (AC_CHECK_HEADERS): add stddef.h.
+
+Fri Nov 3 12:30:43 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (COMMON_OBS): Use corefile.o rather than core.o
+ * core.c: Rename to corefile.c.
+ * config/pyr/tm-pyr.h, umax-xdep.c, sun386-nat.c, pyr-xdep.c,
+ Makefile.in (SFILES), gould-xdep.c, coredep.c, armtdep.c,
+ arm-xdep.c, altos-xdep.c: Change core.c references to corefile.c.
+
+ From Graham Stoney <greyham@research.canon.oz.au>.
+ * Makefile.in (remote-array.o): Add rule to build.
+ (ALLDEPFILES): Add remote-array.c
+ * remote-array.c (baud_rate): Remove unnecessary declaration.
+ (baudrate): Remove.
+ (array_files_info): Print global baud_rate not baudrate.
+
+Sat Nov 4 10:21:58 1995 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (INTERNAL_CFLAGS): Add ENABLE_CFLAGS.
+ * fork-child.c (fork_inferior): Add call to
+ TARGET_CREATE_INFERIOR_HOOK to allow target specific code to get
+ control just before the new process executes it's first instruction.
+ * remote-mips.c (mips_initialize): Cleanup a bit. Don't try to
+ receive a packet at first. This speeds up initialization a lot.
+ Use TARGET_MONITOR_PROMPT instead of "<IDT>".
+ (common_breakpoint): Use rresponse instead of rerrflg to inspect
+ error code.
+ * symfile.c (syms_from_objfile reread_symbols): Call
+ TARGET_SYMFILE_POSTREAD to allow target specific code to get
+ control after reading new symbols.
+ * target.h: New macros TARGET_SYMFILE_POSTREAD, and
+ TARGET_CREATE_INFERIOR_HOOK. See above for descriptions.
+ * config/mips/{irix5.mh nm-irix5.h}: Delete nm-irix5.h. Make
+ NAT_FILE point directly at ../nm-sysv4.h.
+ * config/mips/{mipsm3.mh nm-m3.h}: Delete nm-m3.h. Make
+ NAT_FILE point directly at ../nm-m3.h.
+ * config/mips/{mipsv4.mh nm-sysv4.h}: Delete nm-sysv4.h. Make
+ NAT_FILE point directly at ../nm-sysv4.h.
+ * config/mips/nm-mips.h: Improve comment at top of file.
+ * config/mips/tm-mips.h (TARGET_MONITOR_PROMPT): Change
+ definition into a proper string.
+
+Wed Nov 1 20:18:08 1995 Fred Fish <fnf@cygnus.com>
+
+ * config/i386/tm-i386.h: New file containing generic i*86 target
+ definitions.
+ (TARGET_BYTE_ORDER): Moved here from tm-i386v.h.
+ (IEEE_FLOAT): Moved here from tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Define default as 2.
+ (FUNCTION_START_OFFSET): Moved here from tm-i386v.h.
+ (SKIP_PROLOGUE): Moved here from tm-i386v.h.
+ (SAVED_PC_AFTER_CALL): Moved here from tm-i386v.h.
+ (INNER_THAN): Moved here from tm-i386v.h.
+ (BREAKPOINT): Moved here from tm-i386v.h.
+ (DECR_PC_AFTER_BREAK): Moved here from tm-i386v.h.
+ (ABOUT_TO_RETURN): Moved here from tm-i386v.h.
+ (REGISTER_SIZE): Moved here from tm-i386v.h.
+ (NUM_REGS): Moved here from tm-i386v.h.
+ (REGISTER_NAMES): Moved here from tm-i386v.h.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Moved here from tm-i386v.h.
+ (FP_REGNUM): Moved here from tm-i386v.h.
+ (SP_REGNUM): Moved here from tm-i386v.h.
+ (PC_REGNUM): Moved here from tm-i386v.h.
+ (PS_REGNUM): Moved here from tm-i386v.h.
+ (FP0_REGNUM): Moved here from tm-i386aix.h.
+ (FPC_REGNUM): Moved here from tm-sun386.h.
+ (REGISTER_BYTES): Moved here from tm-i386aix.h.
+ (REGISTER_BYTE): Moved here from tm-i386aix.h.
+ (REGISTER_RAW_SIZE): Moved here from tm-i386aix.h.
+ (MAX_REGISTER_RAW_SIZE): Moved here from tm-i386aix.h.
+ (REGISTER_VIRTUAL_SIZE): Moved here from tm-i386aix.h.
+ (MAX_REGISTER_VIRTUAL_SIZE): Moved here from tm-i386aix.h.
+ (EXTRACT_RETURN_VALUE): Moved here from tm-i386aix.h.
+ (STORE_RETURN_VALUE): Moved here from tm-i386aix.h.
+ (REGISTER_VIRTUAL_TYPE): Moved here from tm-i386v.h.
+ (STORE_STRUCT_RETURN): Moved here from tm-i386v.h.
+ (FRAME_CHAIN): Moved here from tm-i386v4.h.
+ (FRAMELESS_FUNCTION_INVOCATION): Moved here from tm-i386v4.h.
+ (FRAME_SAVED_PC): Moved here from tm-i386os9k.h
+ (FRAME_ARGS_ADDRESS): Moved here from tm-i386v.h.
+ (FRAME_LOCALS_ADDRESS): Moved here from tm-i386v.h.
+ (FRAME_NUM_ARGS): Moved here from tm-i386sun.h.
+ (FRAME_ARGS_SKIP): Moved here from tm-i386v.h.
+ (FRAME_FIND_SAVED_REGS): Moved here from tm-i386v.h.
+ (PUSH_DUMMY_FRAME): Moved here from tm-i386v.h.
+ (POP_FRAME): Moved here from tm-i386v.h.
+ (CALL_DUMMY, CALL_DUMMY_LENGTH, CALL_DUMMY_START_OFFSET,
+ CALL_DUMMY_BREAKPOINT_OFFSET, FIX_CALL_DUMMY): Moved here from
+ tm-i386v.h
+ (print_387_control_word, print_387_status_word): Declare prototypes.
+ (struct frame_info, struct frame_saved_regs): Forward decls for
+ prototypes.
+ (SP_ARG0): Moved here from tm-i386v.h.
+
+ * config/i386/tm-i386v.h:
+ (i386/tm-i386.h): Include.
+ (TARGET_BYTE_ORDER): Remove.
+ (IEEE_FLOAT): Remove.
+ (START_INFERIOR_TRAPS_EXPECTED): Undef before redefine to 4.
+ (FUNCTION_START_OFFSET): Remove.
+ (SKIP_PROLOGUE): Remove.
+ (i386_skip_prologue): Remove prototype.
+ (SAVED_PC_AFTER_CALL): Remove.
+ (INNER_THAN): Remove.
+ (BREAKPOINT): Remove.
+ (DECR_PC_AFTER_BREAK): Remove.
+ (ABOUT_TO_RETURN): Remove.
+ (REGISTER_SIZE): Remove.
+ (NUM_REGS): Undef before redefine to 16 (no FP support).
+ (REGISTER_NAMES): Undef before redefine.
+ (FP_REGNUM, SP_REGNUM, PC_REGNUM, PS_REGNUM): Remove.
+ (REGISTER_BYTES): Undef before redefine.
+ (REGISTER_BYTE): Undef before redefine.
+ (REGISTER_RAW_SIZE): Undef before redefine.
+ (REGISTER_VIRTUAL_SIZE): Undef before redefine.
+ (MAX_REGISTER_RAW_SIZE): Undef before redefine.
+ (MAX_REGISTER_VIRTUAL_SIZE): Undef before redefine.
+ (REGISTER_VIRTUAL_TYPE): Undef before redefine.
+ (STORE_STRUCT_RETURN): Undef before redefine.
+ (EXTRACT_RETURN_VALUE): Undef before redefine.
+ (STORE_RETURN_VALUE): Undef before redefine.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Remove.
+ (FRAME_CHAIN): Undef before redefine.
+ (FRAMELESS_FUNCTION_INVOCATION): Undef before redefine.
+ (FRAME_SAVED_PC): Undef before redefine.
+ (FRAME_ARGS_ADDRESS): Remove.
+ (FRAME_LOCALS_ADDRESS): Remove.
+ (FRAME_NUM_ARGS): Undef before redefine.
+ (FRAME_ARGS_SKIP): Remove.
+ (FRAME_FIND_SAVED_REGS): Remove.
+ (PUSH_DUMMY_FRAME): Remove.
+ (POP_FRAME): Remove.
+ (CALL_DUMMY): Remove.
+ (CALL_DUMMY_LENGTH): Remove.
+ (CALL_DUMMY_START_OFFSET): Remove.
+ (CALL_DUMMY_BREAKPOINT_OFFSET): Remove
+ (FIX_CALL_DUMMY): Remove.
+ (print_387_control_word): Remove.
+ (print_387_status_word): Remove.
+ (SP_ARG0): Remove.
+
+ * config/i386/tm-symmetry.h:
+ (TM_SYMMETRY_H): Enclose file in test for define & define if needed.
+ (START_INFERIOR_TRAPS_EXPECTED): Move to after inclusion of
+ tm-i386v4.h or tm-i386v.h, #undef, and #define back to 2.
+ (DECR_PC_AFTER_BREAK): Move to after inclusion of tm-i386v4.h
+ or tm-i386v.h, #undef, and #define to 0.
+ (MAX_REGISTER_RAW_SIZE): Remove.
+ (FRAME_CHAIN): Remove.
+ (FRAMELESS_FUNCTION_INVOCATION): Remove.
+ (FRAME_SAVED_PC): Remove.
+ (print_387_control_word, print_387_status_word): Remove prototypes.
+
+ * config/i386/tm-ptx.h:
+ (TM_PTX_H): Enclose file in test for define & define if needed.
+ (START_INFERIOR_TRAPS_EXPECTED): Move to after inclusion of
+ tm-i386v4.h or tm-i386v.h, #undef, and #define back to 2.
+ (DECR_PC_AFTER_BREAK): Move to after inclusion of tm-i386v4.h
+ or tm-i386v.h, #undef, and #define to 0.
+ (SDB_REG_TO_REGNUM): Remove obsolete commented out define.
+ (print_387_control_word, print_387_status_word): Remove prototypes.
+
+ * config/i386/tm-linux.h:
+ (TM_LINUX_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+
+ * config/i386/tm-i386v4.h:
+ (TM_I386V4_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (FRAME_CHAIN): Moved to tm-i386.h.
+ (FRAMELESS_FUNCTION_INVOCATION): Moved to tm-i386.h.
+ (FRAME_SAVED_PC): Remove.
+ (sigtramp_saved_pc): Define as i386v4_sigtramp_saved_pc.
+ (FRAME_NUM_ARGS): Remove.
+
+ * config/i386/tm-i386os9k.h:
+ (TM_I386OS9K_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (NUM_REGS): Undefine before redefining.
+ (FRAME_CHAIN): Remove.
+ (FRAMELESS_FUNCTION_INVOCATION): Remove.
+ (FRAME_SAVED_PC): Move to tm-i386.h.
+
+ * config/i386/tm-i386nw.h:
+ (TM_I386NW_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+
+ * config/i386/tm-i386bsd.h:
+ (TM_I386BSD_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (FRAMELESS_FUNCTION_INVOCATION): Remove.
+ (FRAME_SAVED_PC): Remove.
+
+ * config/i386/tm-i386aix.h:
+ (i386/tm-i386.h): Include instead of tm-i386v.h.
+ (START_INFERIOR_TRAPS_EXPECTED): Remove.
+ (FP_REGNUM): Remove.
+ (SP_REGNUM): Remove.
+ (PC_REGNUM): Remove.
+ (PS_REGNUM): Remove.
+ (FP0_REGNUM): Moved to tm-i386.h.
+ (NUM_REGS): Remove.
+ (REGISTER_NAMES): Remove.
+ (REGISTER_BYTES): Moved to tm-i386.h.
+ (REGISTER_BYTE): Moved to tm-i386.h.
+ (REGISTER_RAW_SIZE): Moved to tm-i386.h.
+ (MAX_REGISTER_RAW_SIZE): Moved to tm-i386.h.
+ (REGISTER_VIRTUAL_SIZE): Moved to tm-i386.h.
+ (REGISTER_VIRTUAL_TYPE): Removed.
+ (EXTRACT_RETURN_VALUE): Moved to tm-i386.h.
+ (STORE_RETURN_VALUE): Moved to tm-i386.h.
+
+ * config/i386/tm-sun386.h:
+ (TM_SUN386_H): Enclose file in test for define & define if needed.
+ (i386/tm-i386.h): Include.
+ (TARGET_BYTE_ORDER): Remove.
+ (FUNCTION_START_OFFSET): Remove.
+ (SKIP_PROLOGUE): Remove.
+ (SAVED_PC_AFTER_CALL): Remove.
+ (INNER_THAN): Remove.
+ (BREAKPOINT): Remove.
+ (DECR_PC_AFTER_BREAK): Remove.
+ (ABOUT_TO_RETURN): Remove.
+ (REGISTER_SIZE): Remove.
+ (NUM_REGS): Undefine before defining.
+ (REGISTER_NAMES): Undefine before redefining.
+ (REGISTER_BYTES): Undefine before redefining.
+ (REGISTER_BYTE): Undefine before defining.
+ (FP_REGNUM): Undefine before defining.
+ (PC_REGNUM): Undefine before defining.
+ (FPC_REGNUM): Undefine before defining.
+ (REGISTER_RAW_SIZE): Undefine before defining.
+ (FRAME_CHAIN): Undefine before defining.
+ (FRAMELESS_FUNCTION_INVOCATION): Undefine before defining.
+ (FRAME_SAVED_PC): Undefine before defining.
+ (FRAME_NUM_ARGS): Moved to tm-i386.h.
+ (MAX_REGISTER_RAW_SIZE): Remove.
+ (MAX_REGISTER_VIRTUAL_SIZE): Remove.
+ (STORE_STRUCT_RETURN): Remove.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Remove.
+ (FRAME_ARGS_ADDRESS): Remove.
+ (FRAME_LOCALS_ADDRESS): Remove.
+ (FRAME_NUM_ARGS): Undefine before defining.
+ (FRAME_ARGS_SKIP): Remove.
+ (FRAME_FIND_SAVED_REGS): Remove.
+ (PUSH_DUMMY_FRAME): Remove.
+ (POP_FRAME): Remove.
+ (CALL_DUMMY, CALL_DUMMY_LENGTH, CALL_DUMMY_START_OFFSET): Remove.
+ (struct frame_info, struct frame_saved_regs): Remove forward decls
+ for prototypes.
+
+ * config/i386/tm-i386lynx.h (i386/tm-i386.h): Include instead of
+ tm-i386v.h.
+ * config/i386/tm-i386m3.h (i386/tm-i386.h): Include instead of
+ tm-i386v.h.
+
+ * i386-tdep.c (i386_extract_return_value): Make function visible
+ for all i386 targets, but only assume floating point values returned
+ in floating point registers for I386_AIX_TARGET.
+
+ * i386v-nat.c (i386_register_u_addr): Enable code to locate
+ floating point regs in user struct.
+
+Wed Nov 1 15:32:57 1995 Fred Fish <fnf@cygnus.com>
+
+ * breakpoint.c (breakpoint_re_set): Fix typo in comment.
+ * symtab.c (in_prologue): Document func_start and when it is zero
+ don't call SKIP_PROLOGUE (which typically leads unconditionally to
+ an error when we try to access a prologue at address 0).
+
+Tue Oct 31 13:01:15 1995 Fred Fish <fnf@cygnus.com>
+
+ * elfread.c: Include elf-bfd.h rather than libelf.h.
+
+Tue Oct 31 10:42:42 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * win32-nat.c (xlate_exception): Treat a stack overflow like a SEGV.
+
+Sun Oct 29 11:22:05 1995 Fred Fish <fnf@cygnus.com>
+
+ * monitor.c: Include gnu-regex.h rather than system regex.h.
+
+Sat Oct 28 23:51:48 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * defs.h: Test on name __WIN32__ rather than WIN32.
+ * inflow.c (new_tty): Likewise
+ * terminal.h: Likewise.
+ * utils.c (initialize_utils): Likewise.
+ * win32-nat.c (child_create_inferiror): Print error code when failing.
+ * config/i386/win32.mh (XM_CLIBS): Need -lkernel32.
+
+Sat Oct 28 04:52:36 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symtab.h (enum address_class): Add LOC_UNRESOLVED for
+ a location whose address has to be resolved via the minimal
+ symbol table.
+ * buildsym.c (finish_block), findvar.c (symbol_read_needs_frame,
+ read_var_value), printcmd.c (address_info),
+ symmisc.c (print_symbol, print_partial_symbol): Handle
+ LOC_UNRESOLVED.
+ * stabsread.c (scan_file_globals): Change unresolved LOC_STATIC
+ symbols to LOC_UNRESOLVED. Remove rt_common_objfile lookup
+ kludge, global common symbols are now handled by LOC_UNRESOLVED.
+ (scan_file_globals_1): Move code back to scan_file_globals,
+ delete.
+
+Fri Oct 27 09:54:07 1995 Stu Grossman (grossman@cygnus.com)
+
+ * breakpoint.c (breakpoint_re_set): #ifdef GET_LONGJMP_TARGET
+ around calls to create_longjmp_breakpoint. Why install the
+ breakpoints if we can't find the longjmp target?
+ * infrun.c (wait_for_inferior): Cleanup comments near call test.
+ * remote-mips.c: Fixed a bunch of prototypes to avoid char/int
+ complaint from picky compilers. Add comment to mips_expect.
+ Replace all instances of sr_get_debug with remote_debug.
+ * (mips_readchar): Don't jam init string to monitor.
+ mips_initialize() handles that.
+ * (mips_receive_header): Print better message when we get too
+ much garbage.
+ * (mips_request): Allow caller to pass in buff to allow them to
+ analyze the returned message.
+ * (mips_initialize): Re-do initialization to try sending a BREAK,
+ a ^C, and then a download escape sequence. Cleanup protocol
+ startup. Eliminate sleeps. Clear breakpoints (if using monitor
+ breakpoints). Re-init frame.
+ * (mips_detach): Close down target.
+ * (mips_wait): Handle return status with registers, or breakpoint stuff.
+ * (mips_kill): Add ^C handling.
+ * (mips_insert_breakpoint mips_remove_breakpoint): Call new
+ breakpoint stuff if enabled.
+ * (calculate_mask remote_mips_set_watchpoint
+ remote_mips_remove_watchpoint remote_mips_stopped_by_watchpoint):
+ Hardware watchpoint/breakpoint stuff.
+ * (common_breakpoint): Common code for new monitor breakpoint commands.
+ * (mips_load): Don't use `prompt'. It's a global variable.
+ * top.c (dont_repeat_command): New command for use in
+ user-defined commands to suppress auto-repeat (by hittin return key).
+ * valops.c: Add start of auto function-call abandonment capability.
+
+
+Thu Oct 26 22:02:27 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Add support for PowerMac host, add beginnings
+ of native support.
+ * mpw-make.sed: Disable subdir recursion, edit out useless rule.
+ * mac-xdep.c (Values.h): Don't include.
+ (GestaltEqu.h): Include Gestalt.h instead.
+ (do_mouse_down): Comment out control tracking, needs to be
+ updated to use UPP before will work on PowerMac.
+ * config/xm-mpw.h: New file, all-Mac host support.
+ * config/m68k/xm-mpw.h: Move most definitions into generic Mac
+ support.
+ * config/powerpc/xm-mpw.h: New file, PowerMac host support.
+
+Thu Oct 26 15:21:32 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * regex.h: Renamed to gnu-regex.h.
+ * regex.c: Renamed to gnu-regex.c.
+ * Makefile.in (POSSLIBS): Refer to gnu-regex.h and gnu-regex.c.
+ (REGEX, REGEX1): Change to gnu-regex.o instead of regex.o.
+ (regex.o): Renamed to gnu-regex.o; refer to gnu-regex.c.
+ (irix5-nat.o, osfsolib.o, gnu-regex.o, solib.o, source.o, symtab.o):
+ Likewise.
+ * irix5-nat.c, osfsolib.c, gnu-regex.c, solib.c, source.c, symtab.c):
+ Include "gnu-regex.h" instead of "regex.h".
+ * alpha-tdep.c (in_prologue): Rename to alpha_in_prologue, to
+ avoid conflicts with symtab.h.
+
+Tue Oct 24 18:30:18 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * config/pa/hppahpux.mh: Remove hardcoding of X locations.
+ * Makefile.in: Use X11_CFLAGS, X11_LDFLAGS and X11_LIBS.
+ * configure.in: Link X statically on Solaris, SunOS and HPUX.
+
+Tue Oct 24 12:26:14 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_expect_regexp): Same as monitor_expect, but
+ with the obvious extension.
+ (monitor_read_memory_single): Use regexp for getmem.resp_delim
+ because of parsing ambiguities caused by certain monitors.
+ (monitor_read_memory): Use new regexp stuff to parse
+ getmem.resp_delim.
+ * monitor.h (struct memrw_cmd->resp_delim): Document this as a
+ regexp.
+ * sh3-rom.c: Finish off table. Use new regexp capability for
+ getmem commands.
+
+ * infrun.c (wait_for_inferior): Disable questionable code near
+ the step range test. Replace call detection test with much
+ simpler (and more efficient) test that doesn't require prologue
+ examination (as often).
+ * symtab.c symtab.h (in_prologue): New function that indicates
+ whether or not we are in a function prologue. This uses the
+ symbol table, and then falls back to prologue examination if that
+ fails. It's much more efficient for remote debugging because it
+ avoids examining memory, which is very slow. This is used in
+ wait_for_inferior to determine if we've made a function call that
+ needs to be skipped over (for next/nexti).
+ * mips-tdep.c (after_prologue): New function, returns the PC
+ after the prologue. Uses PDRs and the symbol table.
+ (mips_find_saved_regs): Use in_prologue() to avoid costly
+ prologue examination if possible.
+ (mips_skip_prologue): Use after_prologue() if possible to avoid
+ costly prologue examination.
+
+Mon Oct 23 16:03:33 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * configure.in (configdirs): Added support for the VR4300 default
+ builds (mips64*vr4300*el-*-elf*, mips64*vr4300*-*-elf*).
+
+ * configure: Regenerated.
+
+ * remote-mips.c (mips_load): Updated the prompt spotting code to
+ make use of the TARGET_MONITOR_PROMPT manifest.
+
+Sat Oct 21 06:11:49 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-tdep.c, mips-tdep.c (init_extra_frame_info):
+ Do not set saved registers from heuristics for a sigtramp frame.
+
+ * dwarfread.c (enum_type): Determine signedness of enum type
+ from enumerators.
+
+ * mips-tdep.c: Include gdb_string.h, gcc -Wall lint.
+
+ * rs6000-nat.c (xcoff_relocate_core): Fix typo.
+
+ * valops.c (value_repeat): Fix length of memory transfer to
+ match recent allocate_repeat_value change.
+
+Thu Oct 19 19:04:35 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (get_discrete_bounds): Fix typo.
+
+Thu Oct 19 12:15:37 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * defs.h (SEEK_SET, SEEK_CUR): Add default definitions.
+ * dbxread.c, mdebugread.c, os9kread.c (SEEK_SET, SEEK_CUR):
+ Remove default definitions.
+
+ * Makefile.in (CC-LD): Rename to CC_LD, so MPW xform works.
+ (MMALLOC_SRC): Define.
+ (MMALLOC_CFLAGS): Use.
+ (ser-mac.o): Add rule.
+ * dwarfread.c, somread.c, ultra3-nat.c, xcoffread.c: Replace L_SET
+ with SEEK_SET in all calls to bfd_seek.
+ * scm-tags.h (scm_tags): Remove excess comma.
+
+ * mpw-config.in: Adapt to work with autoconf'ed configury;
+ build config.h, add empty definitions to mk.tmp.
+ (powerpc-apple-macos): Make it work.
+ * mpw-make.sed: New file, sed commands to translate Unix makefile
+ into MPW syntax.
+ * mpw-make.in: Remove.
+ * mac-gdb.r: New file, was macgdb.r, renamed for consistency
+ with other tools, now includes cfrg resource.
+ * macgdb.r: Remove.
+ * config/m68k/xm-mpw.h: Remove most of contents, replace with
+ include of include/mpw/mpw.h.
+
+Tue Oct 17 10:38:53 1995 Jeffrey A Law (law@cygnus.com)
+
+ * hppa-tdep.c (frame_chain): Fix more obscure problems caused
+ by system calls that core dump processes without saving all
+ the register state.
+
+ * config/pa/hppahpux.mt (XDEPFILES): Remove bogus definition.
+ * config/pa/hppapro.mt (XDEPFILES): Likewise.
+
+Tue Oct 17 08:04:26 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * NEWS: Fix typo.
+
+Mon Oct 16 18:24:03 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/sh/tm-sh.h (REGISTER_VIRTUAL_TYPE): Return builtin_type_float
+ for FP registers.
+ (REGISTER_NAMES): Add FP register names. Remove ticks, stalls, cycles,
+ insts, plr, and tlr.
+ (NUM_REGS, NUM_REALREGS): Increase from 23 to 41.
+ (FPUL_REGNUM, FP0_REGNUM): New macros.
+
+Mon Oct 16 11:27:06 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-mips.c: Add support for speedy (about 10x faster)
+ downloads.
+
+ * remote-array.c: Move baud_rate initialization from
+ _initialize_array to array_open. It was forcing the baud rate of
+ all targets to be 4800 baud! Seems like I've fixed this before...
+ * config/mips/idt.mt (TDEPFILES): Remove remote-array.o. This
+ has *nothing* to do with IDT!!!
+
+
+ * Makefile.in sh3-rom.c config/sh/sh.mt config/sh/tm-sh.h: Add
+ sh3 monitor support.
+ * monitor.c: Cleanup regexp compilation stuff to make it easier
+ to use several regexps.
+ * monitor.h: Get rid of struct rom_cmd_data. It's no longer used.
+ * config/m68k/tm-monitor.h: Don't redefine NUM_REGS here. It just
+ causes GDB to crash.
+
+ * sparcl-tdep.c: Cleanup serial error handling.
+
+Sun Oct 15 16:19:27 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * rs6000-tdep.c: Don't include a.out.h, improve some formatting.
+
+Fri Oct 13 15:27:49 1995 Stu Grossman (grossman@cygnus.com)
+
+ * dcache.c: Change default value of remotecache to off. It just
+ screws up too many targets.
+ * sparcl-stub.c: Add prototypes to many forward decls.
+ * Create private copies of strlen, strcpy, and memcpy to prevent
+ chaos when user steps into them.
+ * (trap_low handle_exception): Clean up DSU support code
+ (hardware breakpoints). Move lots of stuff from asm-land to
+ C-land (make it much easier to #ifdef if necessary). Also, use
+ trap 255 to get into break mode instead of doing a DSU register
+ write, which may trash the register.
+ * (putpacket): Don't check return value of putDebugChar. It
+ returns void...
+
+Fri Oct 13 14:16:17 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * remote-sim.h: Always include callback.h.
+ (sim_set_callbacks): New declaration.
+
+Fri Oct 13 10:57:40 1995 Jeffrey A Law (law@cygnus.com)
+
+ * somsolib.c (som_solib_add): Just give a warning if a file
+ mentioned in the dld_list can't be found.
+ * config/pa/tm-hppah.h (FRAME_SAVED_PC_IN_SIGTRAMP): Dig out
+ the PC from the PC queues rather than %r31.
+
+Thu Oct 12 13:36:15 1995 Jeffrey A Law (law@cygnus.com)
+
+ * corelow.c (core_open): Don't update the to_sections and
+ to_sections_end fields in core_ops here. It's too late.
+ * irix5-nat.c (solib_add): Update the to_sections and
+ to_sections_end fields in core_ops here if needed.
+ * osfsolib.c (solib_add): Likewise.
+ * rs6000-nat.c (xcoff_relocate_core): Likewise.
+ * solib.c (solib_add): Likewise.
+ * somsolib.c (solib_add): Likewise.
+
+Wed Oct 11 17:25:59 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * Makefile.in (VERSION): Bump version to 4.15.1
+
+Tue Oct 10 15:26:39 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Version 4.15 released.
+ * README: Updated for version 4.15.
+ * NEWS: Updated for 4.15 release.
+
+Tue Oct 10 13:18:50 1995 Fred Fish <fnf@cygnus.com>
+
+ * configure.in: Add AC_PROG_YACC
+ * configure: Regenerate
+ * Makefile.in (BISON): Remove macro definition.
+ (YACC): Set from autoconfig.
+ (FLAGS_TO_PASS): Remove BISON.
+ (TARGET_FLAGS_TO_PASS): Remove BISON.
+
+Tue Oct 10 12:25:11 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * win32-nat.c (child_create_inferior): Pass argv correctly.
+ * Makefile.in (win32-nat.o): Add dependencies.
+
+Mon Oct 9 14:36:29 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * NEWS: Add information about win32 and arm code.
+ * win32-nat.c: Renamed from win32.c.
+ * config/i386/win32.mh: Renamed from config/i386/i386win32.mh.
+ * config/i386/win32.mt: Renamed from config/i386/i386win32.mt.
+ * config/i386/tm-win32.h: Renamed from config/i386/tm-i386win32.h.
+ * config/i386/xm-win32.h: Renamed from config/i386/xm-i386win32.h.
+ * configure.in (i[345]86-*-win32): Updated to cope with filename
+ changes.
+ * configure: Regenerated.
+
+Sun Oct 8 18:01:04 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y (yylex): Also look for '$' following '$'.
+
+Sat Oct 7 22:52:42 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ch-exp.y (yylex): Fix typo.
+
+Fri Oct 6 11:56:49 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * remote-sim.c (gdbsim_open): Put callback initializations here.
+ (_initalize_remote_sim): Not here.
+
+Fri Oct 6 17:08:49 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (execute_control_command): Use 0/1 instead of BFD's
+ true/false.
+
+Fri Oct 6 14:43:19 1995 Stu Grossman (grossman@cygnus.com)
+
+ * sparcl-stub.c: Include sparclite.h to get access to register
+ fondling macros.
+ * (trap_low): Save and restore FP regs if necessary. Also, clean
+ up save and restore of debug unit regs.
+ * (hard_trap_info): Add more architecturally defined traps.
+ * (set_debug_traps): Only set FP disabled trap if FP is disabled.
+ * (get_in_break_mode): Clean up. Get rid of calls to
+ set_hw_breakpoint_trap(). Also, use write_asi macro.
+ * (handle_exception): Clean up `g' and `G' commands. Add `P'
+ command.
+ * (hw_breakpoint): Why was this here!? It's gone now...
+
+Fri Oct 6 11:56:49 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * callback.c (fdbad): Fix typo in comment.
+ (os_close, os_isatty, os_lseek, os_read, os_write): Use if
+ statements rather than || to get correct return value.
+ (os_write_stdout): Pass missing first argument to os_write.
+ * remote-sim.c: Include callback.h.
+ (_initialize_remote_sim): Call sim_set_callbacks and then
+ initialize the callbacks.
+
+Thu Oct 5 17:28:09 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * values.c (allocate_repeat_value): Allocate an array type, and
+ a value of that type; use that instead of setting VALUE_REPEATED.
+ * value.h (struct value): Remove fields repetitions and repeated.
+ (VALUE_REPEATED, VALUE_REPETITIONS): Removed, no longer used.
+ * c-valprint.c, ch-valprint.c, eval.c, printcmd.c, valops.c,
+ value.h, values.c: Simplify, since now VALUE_REPEATED is never
+ used.
+ * valprint.c (value_print_array_elemen): Removed never-used
+ function.
+
+Thu Oct 5 15:14:36 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * parse.c (write_dollar_variable): New function.
+
+ * c-exp.y (yylex): Replace code for recognizing '$'
+ pseudo-variables with a call to write_dollar_variable.
+ Simplify grammar correspondingly.
+ * f-exp.y: Likewise.
+ * m2-exp.y: Likewise.
+ * ch-exp.y: Likewise. (Remove function match_dollar_tokens.)
+ * scm-exp.c (scm_lreadr): Call write_dollar_variable to handle '$'.
+
+Thu Oct 5 13:27:30 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * win32.c: New file; support for debugging on windows NT.
+ * configure.in: (i[345]86-*-win32): New target.
+ * configure: Regnerated.
+ * eval.c (evaluate_subexp_standard): Remove unused name.
+ * serial.c (gdb_string.h): Include.
+ * source.c (value.h): Include.
+ * config/i386/i386win32.mh (XDEPFILES): Add win32.o
+ * config/i386/i386win32.mt: New.
+ * config/i386/tm-i386win32.h: New.
+
+Wed Oct 4 18:41:34 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * expression.h (enum exp_code): Added OP_NAME.
+ * expprint.c (print_subexp): Add OP_NAME support.
+ * parse.c (length_of_subexp, prefixify_subexp): Likewise.
+ * scm-lang.c (scm_unpack, in_eval_c, scm_lookup_name): new function.
+ * scm-lang.h: Declare builtin_type_scm; other minor tweaks.
+ * values.c (unpack_long): If type is SCM, call scm_unpack.
+ * scm-valprint.c (scm_val_print): Use extract_signed_integer,
+ instead unpack_long
+ * scm-lang.c: More Scheme expression parsing from here ...
+ * scm-exp.c: ... to here. New file.
+ Also, provide for gdb to evaluate simple constants and names..
+ * Makefile.in: Note new scm-exp.{c,o}.
+
+Wed Oct 4 17:23:03 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (get_discrete_bounds): New function.
+ (force_to_range_type): Use get_discrete_bounds.
+ * gdbtypes.h (get_discrete_bounds): Add declaration.
+ * valarith.c (value_bit_index): Generalize to use get_discrete_bounds.
+ * ch-valprint.c (chill_val_print): Make (power)sets and bitstring
+ support use get_discrete_bounds and generally be more robust.
+
+Tue Oct 3 16:54:56 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-nrom.c (nrom_ops): Add value for to_thread_alive,
+ add comments naming slots.
+
+Mon Oct 2 21:45:44 1995 Jeff Law (law@hurl)
+
+ * top.c (build_command_line): Demand arguments for if/while
+ commands.
+
+Mon Oct 2 13:08:01 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * Makefile.in (X11_CFLAGS): Set only to @X_INCDIR@.
+
+Sat Sep 30 16:13:36 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * scm-lang.c: Moved Scheme value printing code to ...
+ * scm-valprint.c: ... this new file.
+ Also major improvements in support for printing SCM values.
+ * scm-lang.h: New file.
+ * scm-tags.h: New file.
+ * Makefile.in: Note new scm-valprint.{c,o}.
+
+Sat Sep 30 09:35:02 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in: X_INCDIR and X_LIBDIR added.
+ * Makefile.in: @X_INCDIR@ and @X_LIBDIR@ added.
+ * configure: Regnerated.
+
+Fri Sep 29 02:10:05 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * config/arm/tm-arm.h (FRAME_CHAIN, FRAME_CHAIN_VALID):
+ Any pc > LOWESTPC is ok.
+
+ * remote-rdp.c (rdp_init): Take out variable baud rate stuff.
+ (remote_rdp_detatch): Delete.
+ * breakpoint.c (ctype.h): Don't include twice.
+
+ * Makefile.in (remote-rdp.o): Doesn't need remote-rdp.h
+ * callback.c (os_printf_filtered): fix protos.
+ * defs.h (puts_filtered, puts_unfiltered
+ [v|f|]printf_[un]filtered): Make format arg const.
+ * remote-rdp.c (rdp_init): Attept to sync at different
+ baudrates.
+ * utils.c (puts_filtered, puts_unfiltered
+ [v|f|]printf_[un]filtered): Define prototypes with
+ const in the right place.
+
+Thu Sep 28 17:43:39 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * defs.h (enum language): Add language_scm.
+ * expression.h (enum exp_code): Added OP_EXPRSTRING.
+ * scm-lang.c: Preliminary support for Guile /SCM dialect of Scheme.
+ * expprint.c (print_subexp): Add OP_EXPRSTRING support.
+ * parse.c (length_of_subexp, prefixify_subexp): Likewise.
+ * valops.c (find_function_in_inferior): New function.
+ (value_allocate_space_in_inferior): New function.
+ (allocate_space_in_inferior): Redefine using previous function.
+ * Makefile.in (SFILES): Add scm-lang.c.
+ (COMMON_OBS): Add scm-lang.o
+
+Thu Sep 28 14:32:11 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * callback.[ch]: New files.
+ * remote-rdp.c: Support for the ARM RDP monitor.
+ * Makefile: Update.
+ * arm-tdep.c (arm_othernames): New.
+ (_initialize_arm_tdep): install 'othernames' command.
+ (arm_nullified_insn, shifted_reg_val, arm_get_next_pc): New.
+ * configure.in: Check for termios.h, termio.h and sgtty.h.
+ (i[345]86-*-win32*): New host.
+ * configure: Regenerated.
+ * inflow.c: Clean up inclusions.
+ * main.c (main): Check for WINGDB, not WIN32.
+ * printcmd.c (do_examine): Put QUIT test in loop.
+ * remote-hms.c (e7000_load): Delete.
+ (hms_ops): Point to generic_load instead.
+ * remote-hms.c (hms_ops): Point to generic_load.
+ * remote-sim.c (sim_callback_write_stdout): Becomes
+ gdbsim_write_stdout.
+ (gdbsim_load): Call generic_load.
+ * remote-utils.c (gr_load_image): Delete.
+ * ser-unix.c (terminal.h): Include instead of havig
+ own #if tree.
+ (hardwire_flush_input): Reset input buffer too.
+ * source.c (openp): If WIN32 then open file in binary mode.
+ * terminal.h: Configure IO mechanism using autoconf defines if
+ available and not overriden.
+ * utils.c (quit, pollquit, notice_quit): WIN32 check becomes
+ WINGDB check.
+
+ * config/arm/arm.mt (TDEPFILES): Add remote-rdp.o.
+ * config/arm/tm-arm.h (TARGET_BYTE_ORDER): becomes
+ TARGET_BYTE_ORDER_SELECTABLE.
+ (ADDR_BITS_REMOVE): New.
+ (ORIGINAL_REGISTER_NAMES, ADDITIONAL_REGISTER_NAMES): New.
+ (INST_xx): New.
+ (FRAME_FIND_SAVED_REGS): Pass the right argument.
+ (arm_get_next_pc): Declare.
+
+Wed Sep 27 10:14:36 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (search_struct_field): Also allow "else" as a variant
+ name.
+ * eval.c (evaluate_struct_tuple): New function. Used to evaluate
+ structure tuples. Now also handles Chill variant records.
+ (get_label): New function, used by evaluate_struct_tuple.
+ (evaluate_subexp_standard case OP_ARRAY): Use evaluate_struct_tuple.
+ (evaluate_labeled_field_init): Removed.
+
+ * valops.c (search_struct_field): Generalize to work with Chill
+ variant records.
+
+Sat Sep 23 01:22:23 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_partial_symbols): Reset includes_used
+ and dependencies_used after finishing the partial symbol table.
+
+ * rs6000-tdep.c (push_dummy_frame): Handle lr_offset of zero
+ correctly.
+
+ * rs6000-nat.c (xcoff_relocate_core): Don't relocate data
+ addresses for the main objfile if DONT_RELOCATE_SYMFILE_OBJFILE
+ is defined.
+ * xcoffread.c: gcc -Wall lint. Remove traceback table reading
+ code. The existing code tried to add parameter information for
+ functions compiled without -g, which cannot be done properly
+ for optimized code and produced misleading parameter displays.
+ (ef_complaint, eb_complaint): Make a local static copy to avoid
+ dependency on coffread.c.
+ (read_xcoff_symtab, process_xcoff_symbol, scan_xcoff_symtab):
+ Enter C_EXT/C_HIDEXT symbols into the minimal symbol table only.
+ (read_xcoff_symtab): Ignore C_STAT section auxiliary entry
+ symbols. Complain about unmatched .ef and .eb symbols instead of
+ segfaulting.
+ (process_xcoff_symbol): Determine value of C_GSYM symbols via
+ the global_sym_chain mechanism in stabsread.c.
+ (xcoff_new_init): Call stabsread_new_init and buildsym_new_init.
+ (init_string_tab): Initialize length field bytes in the strtbl.
+ (scan_xcoff_symtab): Skip symbols that start with `$' or `.$'.
+ Set first_fun_line_offset for symbols with two auxents only.
+
+Wed Sep 20 21:06:35 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * op50-rom.c (op50n_cmds): Send ".\r" after the interrupt
+ character.
+
+Wed Sep 20 13:12:56 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target, synonym for
+ realclean. Add GNU standard maintainer-clean echos.
+ * gdbserver/Makefile.in (maintainer-clean): New target, synonym
+ for realclean.
+ * nlm/Makefile.in (maintainer-clean): Likewise.
+
+Wed Sep 20 08:16:03 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * defs.h (xmalloc, xrealloc): Delete, they're declared in libiberty.h.
+ (GETENV_PROVIDED, FCLOSE_PROVIDED): New.
+ * doc/gdbint.texinfo (GETENV_PROVIDED, FCLOSE_PROVIDED): Document.
+ * remote-sim.[ch] (sim_callback_write_stdout): New.
+
+Tue Sep 19 15:28:58 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (create_set_type): Set TYPE_LENGTH in bytes, not bits.
+ * valops.c (value_bitstring): TYPE_LENGTH is bytes, not bits.
+
+ * gdbtypes.c (force_to_range_type): Calculate upper limit of
+ TYPE_CODE_CHAR depending on TYPE_LENGTH (instead of just using 255).
+
+Mon Sep 18 01:43:42 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (auto_solib_add_at_startup): Delete definition. No
+ longer needed.
+
+Sat Sep 16 13:23:36 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/mips/tm-mips.h (UNUSED_REGNUM): Define.
+ * mipsv4-nat.c (supply_gregset): Fill UNUSED_REGNUM register
+ with zero.
+
+Thu Sep 14 17:35:24 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-sim.c (gdbsim_create_inferior): Back out change that
+ broke all simulator configurations except the rs6000.
+
+Thu Sep 14 14:44:59 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * monitor.c (monitor_expect): Discard NULL characters.
+
+Thu Sep 14 14:12:30 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * infcmd.c: Add extern declaration for auto_solib_add_at_startup.
+
+Wed Sep 13 13:33:58 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * symfile.c: Move global variable auto_solib_add_at_startup from
+ solib.c to symfile.c.
+ * solib.c: ditto.
+ * symfile.h: Add extern declaration of the above mentioned variable.
+ * infcmd.c: Take out extern declaration, since it's in symfile.h.
+
+Thu Sep 14 12:39:35 1995 Stu Grossman (grossman@cygnus.com)
+
+ * coffread.c (coff_symtab_read): Complain about unmatched .ef and
+ .eb symbols instead of segfaulting.
+
+Wed Sep 13 13:33:58 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * stabsread.c (read_one_struct_field): Use subfile language instead of
+ global language. Improve efficiency.
+
+Wed Sep 13 08:45:02 1995 Jeff Law (law@fast.cs.utah.edu)
+
+ * somsolib.c (auto_solib_add_at_startup): Define new global variable.
+ (som_solib_create_inferior_hook): Don't add libraries if
+ auto_solib_add_at_startup is zero.
+ (_initialize_som_solib): Add command to toggle
+ auto_solib_add_at_startup.
+
+Tue Sep 12 19:37:24 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * monitor.c (monitor_make_srec): Fix thinkos in computation
+ of addr_size.
+
+Tue Sep 12 15:46:18 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * stabsread.c (read_one_struct_field): Add a patch to handle cfront
+ generated stabs that each field is in full mangled name.
+
+ * stabsread.c: To include language.h and expression.h for the reason
+ above.
+
+ * infcmd.c (attach_command): Add solibs only when
+ auto_solib_add_at_startup is set.
+
+Mon Sep 11 17:22:35 1995 Fred Fish <fnf@cygnus.com>
+
+ * NEWS: Add information about remote target caching.
+
+Sun Sep 10 15:36:21 1995 Fred Fish <fnf@cygnus.com>
+
+ * defs.h: Only include mmalloc.h if NO_MMALLOC is not
+ defined.
+
+Sun Sep 10 10:24:48 1995 Michael Tiemann <tiemann@axon.cygnus.com>
+
+ * tm-ppc-eabi.h (PC_IN_CALL_DUMMY): Redefine this to work with the
+ simulator. FIXME.
+
+ * rs6000-tdep.c (push_dummy_frame): Calculate the correct link
+ register offset from the current frame (don't assume it is always 8).
+ (push_dummy_frame): Add comment about having only 4096 bytes of
+ stack space in the simulator (by default).
+
+ * remote-sim.c (gdbsim_create_inferior): Call
+ `add_text_to_loadinfo' so that gdb can find TOC entries when
+ calling functions in the inferior.
+
+Sun Sep 10 09:00:28 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (fill_fpregset): Fix incorrect FP_MAX_REGNUM
+ substitution.
+ (supply_fpregset): Use FP_MAX_REGNUM.
+
+Sat Sep 9 08:21:52 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * stabsread.c (read_enum_type): Exit loop for putting pending
+ enum symbols into the enum type correctly if we had no pending
+ symbols on entry to read_enum_type.
+
+Fri Sep 8 12:57:41 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * inferior.h: Add extern declaration of inferior_environ.
+ * solib.c (solib_map_sections): To get inferior's env instead of
+ gdb's for LD_LIBRARY_PATH, same for PATH.
+
+ * solib.c (solib_map_sections): Copy full path name into so_list
+ structure so that symbol_file_add can find it.
+
+Tue Sep 5 17:47:53 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * config/sparc/tm-sp64.h (REGISTER_RAW_SIZE): Lower 32 fp regs
+ have size 4.
+ (REGISTER_VIRTUAL_SIZE): Likewise.
+ (REGISTER_VIRTUAL_TYPE): Lower 32 fp regs have type float.
+ Upper 32 fp regs have type double.
+ * sparc-tdep.c (NUM_SPARC_FPREGS): Replace with
+ (FP_REGISTER_BYTES): this, and update all uses.
+ (FP_MAX_REGNUM): Define if not already.
+ (get_saved_register): Handle new sparc64 fp regs.
+ (sparc_frame_find_saved_regs): Likewise.
+ (sparc_print_register_hook): Only print fp regs < 32 as doubles.
+ Add code to handle long doubles when gdb does.
+ (_initialize_sparc_tdep): Use print_insn_sparc64 if sparc64.
+
+Sat Sep 2 06:41:26 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * configure.in: Explicitly `exit 0' for broken shells.
+ * configure: Rebuilt.
+
+ * symtab.c (list_symbols): Add missing blank after
+ `<function, no debug info>' output.
+
+ * valops.c (value_assign): Handle truncation when assigning
+ to bitfields. Use value_copy to construct the return value
+ from toval.
+ * values.c (value_copy): Copy VALUE_FRAME and VALUE_OPTIMIZED_OUT.
+
+Fri Sep 1 08:25:50 1995 James G. Smith <jsmith@beauty.cygnus.com>
+
+ * configure (mips64*vr4300*-*-elf): Support added.
+ * remote-mips.c (mips_readchar): Change to allow build-time prompt
+ string.
+ * config/mips/tm-mips.h: Added TARGET_MONITOR_PROMPT.
+ * config/mips/{vr4300.mt, vr4300el.mt, tm-vr4300.h,
+ tm-vr4300el.h}: Added.
+
+Thu Aug 31 12:48:04 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * config/sh/sh.mt (SIM): Add -lm.
+
+Wed Aug 30 18:10:57 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * rmote-nindy.c (non_dle, nidy_resume, nindy_wait): Changes to
+ conform to GNU coding standards.
+
+ * solib.c (match_main): Modify to follow GNU coding conventions.
+
+Mon Aug 28 17:07:26 1995 Kung Hsu <kung@lisa.cygnus.com>
+
+ * remote.c (remote_wait): Revert 19 July my change which should be
+ customer specific.
+
+Sat Aug 26 00:26:11 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Handle sh.value of zero for enums.
+ Determine signedness of enum type from enumerators.
+ (parse_type): Handle btIndirect types, handle fBitfield for
+ some non-member types.
+ (upgrade_type): Use TYPE_FLAG_TARGET_STUB for arrays with
+ unknown length.
+ (cross_ref): Handle stIndirect forward reference to btTypedef.
+
+ * stabsread.c (read_enum_type): Determine signedness of enum
+ type from enumerators.
+
+ * top.c (execute_command): Remove trailing whitespace from
+ command arguments, except for `set' and `complete' commands.
+ (validate_comname): Allow underscores in user defined command
+ names.
+
+ * values.c (modify_field): Change `Value does not fit in %d bits'
+ error to a warning. Exclude sign extension bits of negative field
+ values from fit check.
+
+Fri Aug 25 11:31:29 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in (powerpc*-*-eabisim*): Only link in the simulator
+ if the target is powerpc{,le}-*-eabisim*, since the simulator
+ needs GCC to build.
+ * config/powerpc/ppc{,le}-sim.mt: Cloned from ppc{,le}-eabi.mt.
+ * config/powerpc/ppc{,le}-eabi.mt: Remove simulator support.
+ * config/powerpc/tm-ppc{,le}-sim.mt: Include tm-ppc{,le}-sim.h.
+
+Wed Aug 23 16:55:35 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/ppc{,le}-eabi.mt (SIM_OBJS, SIM): Link in the
+ PowerPC simulator.
+
+Tue Aug 22 02:00:47 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * tm-hppa.h (EXTRACT_RETURN_VALUE): Fix for FP values.
+
+ * tm-hppa.h (STORE_RETURN_VALUE): Fix to work with -msoft-float
+ calling conventions too. Use the TYPE of the return value, not
+ its length to determine if it should also be copied into the
+ floating point registers.
+
+ * tm-hppa.h (PROLOGUE_FIRSTLINE_OVERLAP): Delete. Causes more
+ problems than it fixes.
+ * hppa-tdep.c (skip_prologue): If we exit the main loop without
+ finding all the register saves, retry again without looking for
+ the registers we could not find the first time.
+
+Mon Aug 21 23:39:56 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_chain_valid): Handle systems where "$START$"
+ calls "main" directly.
+ (skip_prologue): Always assume arguments were saved into the stack
+ since GCC will do so without setting the magic Args_Saved bit in
+ the unwind descriptor.
+
+Mon Aug 21 11:49:17 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-udi.c (udi_wait): Mask off high bits of stop reason.
+ * remote-udi.c (fetch_register): For unfetchable regs, pretend it's
+ done. Fix a bug.
+
+Mon Aug 21 00:45:17 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * Makefile.in (install): Remove "brokensed" hack, unnecessary now
+ that we're using autoconf.
+ (uninstall): Likewise.
+
+
+Sat Aug 19 01:19:34 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdbtypes.c (recursive_dump_type): Add dont_print_type_obstack
+ to inhibit infinite recursion when printing aggregate types.
+
+Fri Aug 18 17:48:55 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * dcache.c (dcache_write_line): Write dirty lines right.
+
+Fri Aug 18 06:26:56 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-tdep.c (isbranch): Fix typo which caused wrong
+ target addresses for annulled branches.
+
+Wed Aug 16 21:54:39 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (PROLOGUE_FIRSTLINE_OVERLAP): Define.
+
+Tue Aug 15 07:51:21 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * remote.c (remote_write_bytes): Chop up large transfers.
+
+Mon Aug 14 17:56:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gcc.patch: Remove, relevant only to long-ago versions of GCC.
+
+Mon Aug 14 13:43:01 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * config/sparc/tm-sparclite.h: Define FRAME_CHAIN_VALID_ALTERNATE.
+ * blockframe.c (inside_main_func): If main func addr range not set,
+ try to set it now.
+
+Sat Aug 12 15:34:54 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * config/powerpc/xm-aix.h (FIVE_ARG_PTRACE): Define.
+ * config/rs6000/xm-rs6000.h (FIVE_ARG_PTRACE): Likewise.
+
+ * configure.in: Recognize aix4 specially as some aspects
+ of aix4 need different handling than aix3.
+ * configure: Updated.
+ * config/powerpc/{aix4.mh,aix4.mt,tm-ppc-aix4.h}: New files
+ specific to aix4 support on the power pc.
+ * config/powerpc/tm-ppc-aix.h (DONT_RELOCATE_SYMFILE_OBJFILE): Do
+ not defined. The aix4 specific target files will do that.
+ * config/rs6000/{aix4,mh,aix4,mt,tm-rs6000-aix4.h}: New files
+ specific to aix4 support on the rs6000.
+
+ * config/rs6000/tm-rs6000.h (CONVERT_FROM_FUNC_PTR_ADDR): Don't
+ do the conversion if the pointer is not a magic aix function
+ pointer.
+ * rs6000-tdep.c: Include objfiles.h and symtab.h.
+ (is_magic_function_pointer): New function.
+
+ * rs6000-tdep.c (skip_prologue): Refine check for frameless
+ functions. Handle b .+4 emitted by aix4 compilers. Only
+ allow one load of a minimal toc pointer. Handle aix4 compiler's
+ code for alloca.
+
+ * rs6000-tdep.c (find_toc_address): Report an error if no toc was
+ found rather than possibly core dumping.
+
+ * partial-stab.h: Handle extra field generated by the aix4 compiler
+ for enumerations.
+ * stabsread.c (read_enum_type): Likewise.
+
+Sat Aug 12 03:18:04 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * rs6000-tdep.c (extract_return_value): Fix returning of values
+ whose length is less than the register size for big endian targets.
+
+Fri Aug 11 13:04:32 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * symtab.c (list_symbols): if break command set breakpoint on
+ matched symbol.
+
+Wed Aug 9 18:59:05 1995 Fred Fish <fnf@cygnus.com>
+
+ * defs.h (strchr, strrchr, strstr, strtok, strerror): Enclose in
+ #ifndefs to protect against previous definitions as macros.
+
+Wed Aug 9 14:51:36 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * xcoffread.c (xcoff_symfile_offset): Revert an unwanted change
+ that got in accidentally with Aug 1 change.
+
+Sat Aug 5 09:07:28 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * remote-hms.c (hms_cmds): Get reg term right.
+ * monitor.c (monitor_fetch_register): If we see
+ a non-hex digit, just stop reading.
+ * remote.c (remote_wait): Change way $O is handled.
+
+Wed Aug 9 11:42:36 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * configure.in (powerpc-*-aix*): Recognize as a new gdb host
+ and target.
+ (powerpc-*-eabi*): Don't set configdirs.
+ (powerpcle-*-eabi*): Likewise.
+ * configure: Updated.
+ * rs6000-nat.c (vmap_ldinfo): Don't relocate data addresses
+ for the main objfile if DONT_RELOCATE_SYMFILE_OBJFILE is
+ defined.
+ * config/powerpc/{aix.mh,aix.mh}: Host and target makefile fragments
+ for powerpc running aix4.
+ * config/powerpc/{nm-aix.h, tm-ppc-aix.h, xm-aix.h}: Native, target
+ and host include files for powerpc running aix4.
+
+Wed Aug 9 08:11:45 1995 Stan Shebs <shebs@cygnus.com>
+
+ * top.c (target_output_hook): Really make it match defs.h (char *
+ is not the same as unsigned char *).
+
+Tue Aug 8 15:13:05 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (CXX_FOR_TARGET): Don't use ${rootme}/../gcc/xgcc
+ unless it is present.
+
+Tue Aug 8 10:50:15 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * top.c (target_output_hook): Make declaration match the one
+ in defs.h.
+
+ * symfile.c (add_psymbol_to_list): Initialize SYMBOL_SECTION.
+ (add_psymbol_addr_to_list): Likewise.
+ * symfile.h (ADD_PSYMBOL_VT_TO_LIST): Likewise.
+
+Mon Aug 7 15:34:29 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * top.c (target_output_hook): New definition.
+ * stack.c (gdb_string.h): Include after defs.h
+ * defs.h (target_output_hook): New declaration.
+ * source.c (mod_path): Fix Win32 \ handling.
+
+Sun Aug 6 22:14:25 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_saved_pc): Don't try to dig a return pointer
+ out of a long branch stub.
+
+Fri Aug 4 13:37:31 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * xcoffread.c (process_linenos): Fix typo in last change.
+
+Thu Aug 3 22:01:26 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * ch-exp.y (write_lower_upper_value): Add prototype so bison
+ generated parser will insert prototype before first func usage.
+ Bison and byacc order the output sections differently. Also
+ make function static.
+
+Thu Aug 3 10:45:37 1995 Fred Fish <fnf@cygnus.com>
+
+ * Update all FSF addresses except those in COPYING* files.
+
+Thu Aug 3 01:38:45 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/alpha/tm-alpha.h (EXTRA_FRAME_INFO): Add pc_reg field.
+ (SKIP_TRAMPOLINE_CODE): Define.
+ * alpha-tdep.c (alpha_frame_saved_pc): Use pc_reg field from
+ frame to find the saved pc register.
+ (alpha_saved_pc_after_call): Skip over shared library trampoline
+ before trying to find the saved pc register.
+ (find_proc_desc): Copy PROC_PC_REG from found proc_desc
+ to heuristic proc_desc.
+ (init_extra_frame_info): Initialize pc_reg field in frame.
+
+Wed Aug 2 18:00:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (m68*-est-*): Use monitor target config.
+ * configure: Update.
+ * config/m68k/est.mt, config/m68k/tm-est.h: Delete.
+ * config/m68k/monitor.mt, config/m68k/tm-monitor.h: Fix comments.
+
+Tue Aug 1 22:52:53 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.14.2
+
+Tue Aug 1 16:04:36 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * xcoffread.c (process_linenos): The value in include file symbol
+ should point to line number table. Currently this value is not
+ set correctly by AIX ld. A fix to get around this bug.
+
+Tue Aug 1 11:44:53 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in: Check for working mmap, ansi headers, string.h,
+ strings.h, and memory.h.
+ * configure: Regenerated.
+
+ * gdb_stat.h: New file, "portable" <sys/stat.h>.
+ * gdb_string.h: New file, "portable" <string.h>.
+
+ * altos-xdep.c, arm-tdep.c, arm-xdep.c, convex-tdep.c,
+ convex-xdep.c, coredep.c, cxux-nat.c, dbxread.c, exec.c,
+ gould-xdep.c, hppa-tdep.c, i386aix-nat.c, i386b-nat.c,
+ i386mach-nat.c, i386v-nat.c, infptrace.c, m88k-nat.c, main.c,
+ mdebugread.c, objfiles.c, os9kread.c, procfs.c, pyr-xdep.c,
+ rs6000-nat.c, source.c, standalone.c, stuff.c, sun386-nat.c,
+ symfile.c, symm-nat.c, symm-tdep.c, symtab.c, top.c, ultra3-nat.c,
+ ultra3-xdep.c, umax-xdep.c, xcoffread.c: Include "gdb_stat.h"
+ instead of <sys/stat.h>.
+
+ * alpha-tdep.c, breakpoint.c, buildsym.c, c-typeprint.c,
+ ch-typeprint.c, coffread.c, command.c, core-sol2.c, core-svr4.c,
+ core.c, corelow.c, cp-valprint.c, dbxread.c, dcache.c, demangle.c,
+ dpx2-nat.c, dstread.c, dwarfread.c, elfread.c, environ.c, eval.c,
+ exec.c, f-lang.c, f-typeprint.c, f-valprint.c, findvar.c,
+ fork-child.c, gdbtypes.c, hpread.c, i386-tdep.c, infcmd.c,
+ inflow.c, infptrace.c, infrun.c, irix5-nat.c, language.c,
+ m2-typeprint.c, main.c, mdebugread.c, minsyms.c, mipsread.c,
+ monitor.c, nlmread.c, objfiles.c, os9kread.c, osfsolib.c, parse.c,
+ printcmd.c, procfs.c, regex.c, remote-adapt.c, remote-arc.c,
+ remote-array.c, remote-bug.c, remote-e7000.c, remote-eb.c,
+ remote-es.c, remote-hms.c, remote-mm.c, remote-os9k.c,
+ remote-pa.c, remote-sim.c, remote-st.c, remote-udi.c,
+ remote-utils.c, remote-vx.c, remote-vx29k.c, remote-vx68.c,
+ remote-vx960.c, remote-vxmips.c, remote-vxsparc.c, remote.c,
+ solib.c, somread.c, source.c, stabsread.c, stack.c, symfile.c,
+ symmisc.c, symtab.c, target.c, top.c, typeprint.c, utils.c,
+ valarith.c, valops.c, valprint.c, values.c, xcoffread.c: Include
+ "gdb_string.h" instead of <string.h>.
+
+ * config/xm-sysv4.h, i386/xm-ptx.h, m68k/xm-sun3os4.h,
+ sparc/xm-sun4os4.h (HAVE_MMAP): Removed.
+
+ * config/xm-lynx.h, config/i386/xm-ptx.h,
+ config/m68k/nm-apollo68b.h, config/m68k/xm-hp300hpux.h,
+ config/mips/xm-irix3.h, config/mips/xm-mips.h,
+ config/mips/xm-news-mips.h, config/mips/xm-riscos.h,
+ config/pa/hppah.h, config/rs6000/xm-rs6000.h,
+ config/sparc/xm-sun4os4.h, config/sparc/xm-sun4sol2.h,
+ config/vax/xm-vaxbsd.h, config/vax/xm-vaxult.h,
+ config/vax/xm-vaxult2.h (MEM_FNS_DECLARED): Removed.
+ * config/mips/xm-irix3.h, config/mips/xm-mips.h,
+ config/pa/xm-hppah.h (memcpy, memset): Removed declarations.
+
+Tue Aug 1 02:08:30 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-tdep.c (mips_extract_return_value): Fix returning of
+ values whose length is less than the register size for big endian
+ targets.
+ * alpha-tdep.c (alpha_extract_return_value,
+ alpha_store_return_value): Use alpha_convert_register_to_*
+ to handle functions returning "float" correctly.
+
+Mon Jul 31 19:12:48 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * h8500-tdep.c: General linting and cleanup.
+ (opcodes/h8500-opc.h): Don't include.
+ (code_size, data_size): Make static.
+ (frame_locals_address, frame_args_address): Remove.
+ (h8300_pop_frame): Rename to h8500_pop_frame.
+ (big_command, medium_command, compact_command, small_command):
+ Define as regular functions rather than with macro trickery.
+ (tm_print_insn): Set to correct disassembler function.
+ * config/h8500/tm-h8500.h: Minor cleanup, add prototypes.
+ (ABOUT_TO_RETURN): #if 0 out.
+ (FRAME_ARGS_ADDRESS, FRAME_LOCALS_ADDRESS): Use usual define.
+ (GDB_TARGET_IS_H8500): Remove duplicate definition.
+ (regoff): Remove, never used.
+ * config/h8500/h8500.mt (TDEPFILES): Add monitor.o.
+
+Mon Jul 31 14:32:30 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in: Check for unistd.h.
+ * configure: Regenerated.
+
+ * command.c, cp-valprint.c, fork-child.c, i386-tdep.c,
+ i386b-nat.c, inflow.c, main.c, maint.c, objfiles.c, solib.c,
+ source.c, stack.c, symfile.c, top.c, utils.c: Include strings.h
+ and/or unistd.h to bring prototypes into scope.
+
+Sun Jul 30 01:40:11 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * rs6000-tdep.c (frame_saved_pc): Check for signal handler caller
+ before trying to determine the start of the function.
+ (skip_prologue): Skip subroutine call which might save the
+ floating point registers only if it is within the first three
+ instructions.
+ Reinstate setting of alloca_reg if setup of a gcc frame pointer
+ is found.
+ (frame_get_cache_fsr): Use new fields in rs6000_framedata.
+
+Sat Jul 29 14:43:35 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * sparclite: Removed subdirectory. aload and eload are now in
+ utils/sparclite, low-level library is in libgloss.
+ * configure.in (sparclite*): Don't configure sparclite subdir.
+ * configure: Update.
+ * Makefile.in (TARDIRS): Remove, no longer used.
+
+Sat Jul 29 01:45:56 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * procfs.c (unconditionally_kill_inferior): Clear current signal
+ if PROCFS_NEED_CLEAR_CURSIG_FOR_KILL is defined.
+ * config/alpha/nm-osf3.h (PROCFS_NEED_CLEAR_CURSIG_FOR_KILL): Define.
+
+ * alpha-tdep.c: Move sigtramp handling of saved registers from
+ read_next_frame_reg to alpha_find_saved_regs, handle saved
+ floating point registers.
+ * mips-tdep.c: Move sigtramp handling of saved registers from
+ read_next_frame_reg to mips_find_saved_regs, handle saved
+ floating point registers.
+ * config/mips/tm-irix3.h, config/mips/tm-irix5.h,
+ config/mips/tm-mipsv4.h (SIGFRAME_FPREGSAVE_OFF): Define.
+
+ * sparc-tdep.c (sparc_pc_adjust): Fix check for `unimp'
+ instruction to handle functions returning structures with
+ large sizes properly.
+
+Fri Jul 28 11:50:17 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * configure, configure.in (z8k-*-sim): deleted.
+
+Thu Jul 27 12:49:28 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_wait): Handle threads exiting.
+
+Thu Jul 27 07:47:50 1995 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000-tdep.c (skip_prologue): Don't assume the update stack
+ instruction is the last in the prologue, since xlc stores the lr
+ after the stack update. Make sure offset is correct sign for
+ large frames.
+ (frame_saved_pc): Move test for signal before frameless.
+
+ * config/rs6000/tm-rs6000.h (DEFAULT_LR_SAVE): Define.
+ * config/powerpc/tm-ppc-eabi.h (DEFAULT_LR_SAVE): Redefine.
+
+Thu Jul 27 01:22:08 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * hppa-tdep.c (hppa_fix_call_dummy): Rewrite code for calling
+ into shared libraries.
+
+Wed Jul 26 23:33:34 1995 Michael Meissner <meissner@cygnus.com>
+
+ * config/rs6000/tm-rs6000.h (rs6000_framedata): Add offsets the
+ gprs, fprs, lr, and cr is stored at.
+ (FRAME_FIND_SAVED_REGS): Use new fields in rs6000_framedata.
+ (function_frame_info): Delete declaration.
+ (SKIP_PROLOGUE): Skip_prologue is now passed a rs6000_framedata
+ structure to fill in.
+ (FRAMELESS_FUNCTION_INVOCATION): Function now longer takes a
+ second argument.
+ (FRAME_SAVED_PC): Call frame_saved_pc.
+
+ * rs6000-tdep.c (skip_prologue): Recognize V.4 prologues as well
+ as AIX style. Fill in rs6000_framedata structure. Remember where
+ the gprs, fprs, cr, and lr are saved.
+ (pop_frame): Use skip_prologue, not function_frame_info, and use
+ new rs6000_framedata fields.
+ (function_frame_info): Function deleted.
+ (frameless_function_invocation): Separate frame_saved_pc support
+ to new function. Recognize V.4 frames.
+ (frame_saved_pc): New function.
+ (frame_get_cache_fsr): Use skip_prologue, not function_frame_info.
+ (frame_initial_stack_address): Ditto.
+
+Wed Jul 26 01:00:37 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * remote.c: Add documentation for extended protocol operations
+ and for thread_alive change from a couple weeks ago.
+ (extended_remote_ops): Declare and define a new target vector
+ for the extended remote protocol.
+ (extended_remote_restart): New function to restart the remote
+ server & process.
+ (remote_open): Just a stub routine.
+ (extended_remote_open): New function to start a remote session
+ using the extended gdb remote protocol.
+ (remote_open_1): New function containing code common to both
+ remote_open and extended_remote_open.
+ (remote_mourn, extended_remote_mourn, remote_mourn_1): Similarly.
+ (extended_remote_create_inferior): New function for the extended
+ remote target.
+ (initialize_remote): Add the extended_remote_ops target vector.
+ * gdbserver/server.c (main, case '!'): Set extended_protocol.
+ (main, case 'k'): If the extended protocol is in use, kill the
+ inferior then start a new one.
+ (main, case 'R'): New command to restart the remote server and
+ inferior process. Only supported when using the extended
+ protocol.
+ (main, server loop): If the inferior terminates while using the
+ extended protocol then start a new one. If getpkt fails when
+ using the extended protocol then exit.
+
+Tue Jul 25 11:43:44 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mdebugread.c (psymtab_to_symtab_1): Relocate encoded stab
+ line numbers using the psymtab's section offsets.
+
+Tue Jul 25 10:43:27 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/rs6000/tm-rs6000.h (rs6000_framedata): Rename from
+ aix_framedata. Change all uses.
+ * rs6000-tdep.c: Change all aix_framedata -> rs6000_framedata.
+
+Sat Jul 22 23:44:18 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * defs.h (ATTR_FORMAT): Disable if ANSI_PROTOTYPES is not defined.
+
+Fri Jul 21 16:50:28 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_thread_alive): New function. Somehow I
+ forgot to check this in with all the other thread_alive changes.
+
+Thu Jul 20 22:22:34 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c (som_symtab_read): Add unsatisfied common symbols to
+ the minimal symbol table. All common symbols are "unsatisfied"
+ when -E is passed to the linker.
+
+Thu Jul 20 15:04:57 1995 Fred Fish <fnf@cygnus.com>
+
+ * top.c (show_endian): Cast first arg of printf_unfiltered to
+ correct type of "char *".
+
+Thu Jul 20 14:18:51 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_wait): A thread_id of zero from wait apparently
+ means the process is single threaded, so there's no need to add
+ it to the thread list. Handle case where multi-threaded process
+ reverts back to a single-threaded process.
+
+ * gdbserver/low-hppabsd.c: Remove error declaration.
+ * gdbserver/low-sparc.c: Likewise.
+ * gdbserver/low-sun3.c: Likewise.
+ * gdbserver/server.h: Remove error and fatal declaration.
+ * gdbserver/utils.c (error): Update to be compatable with recent
+ changes in defs.h.
+ (fatal): Likewise.
+
+Wed Jul 19 22:42:43 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/m68k/tm-m68kv4.h (DWARF_REG_TO_REGNUM): Define to
+ correctly map floating point registers numbers.
+
+ * dwarfread.c (locval, new_symbol): Handle variables that are
+ optimized out.
+
+ * mdebugread.c: Replace all uses of builtin_type_* with
+ mdebug_type_*. Define and initialize mdebug_type_*.
+
+ * serial.h (serial_close): Add additional argument `really_close'.
+ (SERIAL_CLOSE): Update serial_close call accordingly.
+ (SERIAL_UN_FDOPEN): Use serial_close to handle refcnt properly.
+ * serial.c (serial_close): Handle `really_close'.
+ * serial.h (scb_base): Moved to serial.c, made static.
+
+ * valops.c (value_addr): Don't coerce arrays.
+ (typecmp): Coerce arrays instead of calling value_addr if necessary.
+
+Wed Jul 19 18:19:28 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Richard Earnshaw (rearnsha@armltd.co.uk):
+ * infrun.c (wait_for_inferior): Set the convenience variable
+ $_exitcode to the termination code of the inferior.
+ * top.c (quit_command): Accept optional expression to use
+ as parameter to exit().
+
+Wed Jul 19 13:15:32 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote.c (remote_wait): When getting registers, check endianess and
+ do conversion if necessary.
+
+Tue Jul 18 00:41:31 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * gdbserver/low-hppabsd.c: New file.
+ * gdbserver/Makefile.in (SFILES): Add low-hppabsd.c.
+ * config/pa/hppabsd.mh (XDEPFILES): Add ser-tcp.o.
+ (GDBSERVER_DEPFILES): Add low-hppabsd.o.
+ * config/pa/hppaosf.mh: Likewise.
+
+Mon Jul 17 21:35:18 1995 Fred Fish <fnf@cygnus.com>
+
+ * dache.c (struct dcache_block): Change data member from unsigned
+ char to char, since everything passed in and out of dcache is char
+ or casted to appropriate type anyway.
+ (dcache_alloc): Move assignment of db out of test and combine
+ separate tests into if-else.
+ (dcache_peek_byte): Change ptr from unsigned char* to char*.
+ (dcache_peek_byte): Remove now unnecessary cast in read_memory call.
+ (dcache_peek): Change cast of incoming data arg.
+ (dcache_poke): Change cast of addr of incoming data arg.
+ (dcache_info): Mask data passed to printf_filtered to lsbyte only.
+ (dcache_info): Change printf_filtered arg from "% 2x" to " %2x".
+ * target.c (debug_to_thread_alive): Change return type to int and
+ return zero, for type compatibility with other *_thread_alive
+ funcs.
+ (cleanup_target): Change cast of ignore function to match type of the
+ to_thread_alive member.
+ * defs.h (error_hook): Add ATTR_NORETURN.
+ * defs.h (NORETURN, ATTR_NORETURN): Switch from volatile to
+ __attribute__ method with gcc 2.7, to avoid gcc 2.6.3 bug.
+ * remote.c (remote_wait): Cast first arg to strtol, strchr, and
+ strncmp to "const char *" from "unsigned char *".
+ (remote_wait): Cast arg to putpkt and strcpy from "unsigned char *"
+ to "char *".
+ (remote_wait): Change printf format for long arg from "%d" to "%ld".
+ (getpkt): Remove unused variable "bp".
+ (remote_fetch_word, remote_store_word): Ifdef out apparently unused
+ functions.
+ * breakpoint.c (watchpoint_check): Removed unused variables
+ "saved_level" and "saved_frame".
+ * valops.c (value_arg_coerce): Add other enum TYPE_CODE_* and
+ default cases to switch for completeness.
+ * infrun.c (wait_for_inferior): Enclose "have_waited" label
+ in #ifdef that matches the one in which it is referenced.
+ * ser-unix.c (hardwire_noflush_set_tty_state): Enclose otherwise
+ unused variable "state" in #ifdef that matches one in which it is
+ referenced.
+ * eval.c (evaluate_subexp_standard): Remove unused variable "var".
+ * eval.c (evaluate_subexp_standard): Remove unused variable
+ "tmp_symbol".
+ * valarith.c (value_subscript): Remove unused variable
+ "lowerbound", which is redeclared in a nested scope prior to use.
+ * printcmd.c (print_frame_nameless_args): Use "%ld" to print long
+ arg, not "%d".
+ * {mem-break.c, remote-pa.c, remote.c, saber.suppress}:
+ Remove unused static var "check_break_insn_size".
+ * buildsym.c (finish_block): Add other enum LOC_* and default
+ cases to switch for completeness.
+ ch-lang.c (type_lower_upper): Removed unused label "retry".
+ Add other enum TYPE_* and default cases to switch for completeness.
+ * f-typeprint.c (f_type_print_args): Ifdef out unused function
+ that may be used someday when Fortran support is complete.
+ * ch-valprint.c (chill_print_type_scalar): Add other enum
+ TYPE_* and default cases to switch for completeness.
+ (chill_val_print): Remove unused local var "high_bound" that
+ is redeclared in a nested scope prior to use.
+ (chill_var_print): Use "%ld" to print long arg, not "%d".
+ * regex.c (re_compile_fastmap, re_match_2): Add remaining enum
+ types and default to switches for completeness.
+ * minsyms.c (lookup_minimal_symbol_text): Delete unused variable
+ "trampoline_symbol".
+ (prim_record_minimal_symbol_and_info): Return NULL rather than
+ trash.
+ * elfread.c (elf_symtab_read): Don't dereference NULL returns from
+ record_minimal_symbol_and_info.
+ * f-lang.c (saved_function_list_end): Ifdef out unused variable
+ that may be used someday.
+ * f-valprint.c (f_val_print): Remove unused local "straddr".
+
+Mon Jul 17 13:08:00 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabsread.h (struct stab_section_list): Define.
+ (coffstab_build_psymtabs): Remove staboff and stabsize parameters.
+ Add textaddr, textsize, and stabs parameters.
+ * gdb-stabs.h (struct dbx_symfile_info): Remove text_sect field.
+ Add text_addr and text_size fields.
+ (DBX_TEXT_SECT): Don't define.
+ (DBX_TEXT_ADDR, DBX_TEXT_SIZE): Define.
+ * coffread.c: Include <ctype.h>.
+ (struct coff_symfile_info): Remove stabsect and stabindexsect
+ fields. Add textaddr, textsize, and stabsects fields.
+ (coff_locate_sections): Record the address of the .text section,
+ and total the sizes of all sections with names beginning with
+ ".text". Don't bother to record a .stab.index section (COFF
+ doesn't use them). Make a linked list of all sections with names
+ beginning with ".stab".
+ (coff_symfile_read): Adjust call to coffstab_build_psymtabs for
+ new parameters.
+ * dbxread.c (dbx_symfile_read): Use DBX_TEXT_ADDR and
+ DBX_TEXT_SIZE, rather than getting both from DBX_TEXT_SECT.
+ (dbx_symfile_init): Set DBX_TEXT_ADDR and DBX_TEXT_SIZE, not
+ DBX_TEXT_SECT.
+ (elfstab_build_psymtabs): Likewise.
+ (stabsect_build_psymtabs): Likewise.
+ (symbuf_sections, symbuf_left, symbuf_read): New static variables.
+ (fill_symbuf): If symbuf_sections is not NULL, read symbols from
+ multiple sections.
+ (coffstab_build_psymtabs): Remove staboffset and stabsize
+ parameters. Add textaddr, textsize, and stabsects parameters.
+ Set DBX_TEXT_ADDR and DBX_TEXT_SIZE, not DBX_TEXT_SECT. Handle
+ multiple stabs sections.
+ * os9kread.c (os9k_symfile_read): Use DBX_TEXT_ADDR and
+ DBX_TEXT_SIZE, rather than getting both from DBX_TEXT_SECT.
+ (os9k_symfile_init): Set DBX_TEXT_ADDR and DBX_TEXT_SIZE, not
+ DBX_TEXT_SECT.
+
+ * remote-vx.c (vx_ops, vx_run_ops): Initialize new to_thread_alive
+ field.
+
+Sat Jul 15 01:02:53 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * config/alpha/alpha-osf3.mh, config/alpha/nm-osf3.h: New files
+ for OSF/1-3.x procfs support.
+ * configure.in (alpha-dec-osf): Use them when configuring
+ for OSF/1-3.x.
+ * configure: Updated.
+ * target.c: Include <string.h>.
+
+Fri Jul 14 16:16:56 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in, configure.in: Use one variable, frags, to hold
+ pathnames of makefile fragments.
+ * configure: regenerated.
+
+Fri Jul 14 09:49:47 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * procfs.c (procfs_ops): Fix typo in last change.
+
+Thu Jul 13 13:42:38 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * inftarg.c (child_thread_alive): New function to see if a
+ particular thread is still running.
+ (child_ops): Add child_thread_alive entry.
+ * remote.c (remote_thread_alive): New function to see if a
+ particular thread is still alive.
+ (remote_ops): Add remote_thread_alive.
+ * target.c (dummy_target): Add dummy entry for thread_alive.
+ (cleanup_target): de_fault thread_alive too.
+ (update_current_target): INHERIT thread_alive too.
+ (debug_to_thread_alive): New function.
+ (setup_target_debug): Add debug_to_thread_alive.
+ * target.h (struct target_ops): Add to_thread_alive.
+ (target_thread_alive): Define.
+ * thread.c (info_threads_command): Don't call kill; use
+ target_thread_alive instead.
+ * config/nm-lynx.h (CHILD_THREAD_ALIVE): Define.
+ * gdbserver/low-lynx.c (mythread_alive): New function.
+ (mywait): Don't restart any threads after a new thread notification,
+ let the generic code handle it.
+ * gdbserver/low-sparc.c (mythread_alive): Dummy version.
+ * gdbserver/low-sun3.c (mythread_alive): Likewise.
+ * gdbserver/server.c (main): Handle thread_alive requests.
+ * gdbserver/server.h (mythread_alive): Declare.
+ * corelow.c (core_ops): Add dummy entry for thread_alive.
+ * exec.c (exec_ops): Likewise.
+ * m3-nat.c (m3_ops): Likewise.
+ * monitor.c (monitor_ops): Likewise.
+ * procfs.c (procfs_ops): Likewise.
+ * remote-arc.c (arc_ops): Likewise.
+ * remote-array.c (array_ops): Likewise.
+ * remote-e7000.c (e7000_ops): Likewise.
+ * remote-es.c (es1800_ops, es1800_child_ops): Likewise.
+ * remote-mips.c (mips_ops): Likewise.
+ * remote-pa.c (remote_hppro_ops): Likewise.
+ * remote-sim.c (gdbsim_ops): Likewise.
+ * sparcl-tdep.c (sparclite_ops): Likewise.
+
+Tue Jul 11 11:15:55 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * solib.c: Add _DYNAMIC__MGC base symbol for Mentor Graphics Inc.
+ * solib.c (match_main): New function for checking name of main.
+ * solib.c (solib_add): Not to add if solib match main.
+
+Fri Jul 7 14:41:56 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * elfread.c (elf_symtab_read): Fix a bug ignoring compiler
+ generated internal labels ($LM...).
+
+Wed Jul 5 11:38:36 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * defs.h: if __GO32__ or WIN32 the directory separating symbol should
+ be '\' not '/'.
+
+ * remote-nindy (nindy_wait): Use infinite timeout reading after
+ esacpe character.
+
+Tue Jul 4 10:30:22 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * infrun.c (wait_for_inferior): When switching from one thread to
+ another, save infrun's state for the old thread and load infrun's
+ previous state for the new thread.
+ * thread.c (struct thread_info): Add new fields for thread specific
+ state saved/restored in infrun.c.
+ (add_thread): Initialize new fields.
+ (load_infrun_state): New function.
+ (save_infrun_state): New function.
+ * thread.h (load_infrun_state): Provide external decl.
+ (save_infrun_state): Likewise.
+
+ * infrun.c (wait_for_inferior): When we hit a breakpoint for the
+ wrong thread, make sure to write the fixed PC value into the thread
+ that stopped. Restart all threads after single stepping over a
+ breakpoint for a different thread.
+ * breakpoint.c (set_momentary_breakpoint): Make momentary
+ breakpoints thread specific in a multi-threaded program.
+ * lynx-nat.c (child_resume): Add some comments. Correctly
+ choose between the single and multi-threaded step and continue
+ ptrace calls.
+
+Fri Jun 30 16:15:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/h8300/h8300.mt: Renamed from h8300hms.mt.
+ * config/h8500/h8500.mt: Renamed from h8500hms.mt.
+ * config/z8k/z8k.mt: Renamed from z8ksim.mt.
+ * configure, configure.in: Update to reflect renamings.
+
+ * remote-sim.c (sim): New command, passes commands to simulator.
+ (simulator_command): New function.
+ (gdbsim_ops): Clean up.
+ * remote-sim.h (sim_do_command): Declare.
+ * sh-tdep.c (memory_size): Remove command.
+
+ * Makefile.in (SIM, SIM_OBS): New variables.
+ (CLIBS, CDEPS): Add value of SIM.
+ (DEPFILES): Add value of SIM_OBS
+
+ * config/arm/arm.mt, config/h8300/h8300.mt, config/h8500/h8500.mt,
+ config/sh/sh.mt, config/sparc/sp64sim.mt, config/w65/w65.mt,
+ config/z8k/z8k.mt: Remove simulator files from TDEPFILES,
+ define in SIM_OBS and SIM.
+ config/sparc/sp64sim.mt (SIMFILES): Remove.
+
+ * remote-z8k.c: Remove, was superseded by remote-sim.c
+ * Makefile.in, mpw-make.in: Remove references to remote-z8k.c.
+
+Sun Jun 25 15:30:43 1995 Stan Shebs <shebs@cygnus.com>
+
+ * remote.c (remote_read_bytes, remote_write_bytes): Second arg
+ should be char *, not unsigned char *.
+ * dcache.h (memxferfunc): Ditto.
+ * monitor.c (monitor_write_memory, monitor_read_memory_single):
+ Ditto.
+ (monitor_make_srec): Let compiler figure size of hextab.
+
+Sat Jun 24 19:27:37 1995 Jeffrey A. Law <law@rtl.cygnus.com>
+
+ * lynx-nat.c (child_wait): Don't restart new threads and loop
+ to the top of child_wait; let the machine independent code in
+ wait_for_inferior deal with new thread notifications.
+
+Fri Jun 23 11:51:58 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-nindy (nindy_load): Put in target specific load, it's
+ 20 times faster.
+
+Thu Jun 22 20:21:59 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * utils.c (error): Move local `args' outside conditional,
+ move local `string1' inside, declare function as void if
+ non-ANSI compiler, dereference error_hook when calling.
+
+ * mac-xdep.c (stdarg.h): Don't include.
+
+Thu Jun 22 13:12:33 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-nindy.c (nindy_wait): Change timeout in SERIAL_READCHAR.
+
+Wed Jun 21 13:24:41 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppam3-nat.c: Change HP800_THREAD_STATE to TRACE_FLAVOR and
+ HP800_THREAD_STATE_COUNT to TRACE_FLAVOR_SIZE.
+
+Wed Jun 21 05:57:56 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * monitor.c: Turn on caching.
+ (monitor_printf): If a ^C was sent, don't expect to see its
+ echo.
+ (monitor_open): Enable caching.
+ (monitor_resume, monitor_load): Flush cache.
+ (monitor_xfer_memory): Call cache routine.
+ (monitor_dump_regs): New.
+ (monitor_fetch_registers): If monitor_dump_regs available
+ then use it.
+ (monitor_load): Don't ref exec_bfd if it's NULL.
+ (monitor_load_srec): Use new monitor_make_srec calling convention.
+ (monitor_make_srec): Rewrite to cope with two, three and four byte
+ addresses.
+ * remote-hms.c (hms_cmds): Initialze end-of-command delim.
+ * dcache.h, dcache.h: Rewritten.
+ * remote.c: Reenable caching.
+ (getpkt): Reduce MAX_TRIES to 3.
+ (remote_xfer_memory): Use dcache_xfer_memory.
+ * defs.h (error_hook): New.
+ * top.c (error_hook): New definition.
+ * utils.c (error): Use error_hook if initialized.
+ * sparcl-tdep.c (HAVE_SOCKETS): Don't define if GO32 or WIN32. Use
+ HAVE_SOCKETS in place of #ifndef GO32.
+
+Tue Jun 20 22:17:44 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (PSW_*): Define processor status word masks.
+ (INSTRUCTION_NULLIFIED): Allow specific targets to override.
+ * config/pa/tm-hppao.h (INSTRUCTION_NULLIFIED): Define to work
+ around losing mach kernel behavior.
+
+Tue Jun 20 12:03:36 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c (monitor_wait): Don't use the watchdog timeout
+ if its value is 0.
+ * w89k-rom.c (w89k_open): Define to be static.
+
+
+Sat Jun 17 10:17:16 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_add): Validate regexp argument.
+ Don't assume the first entry on dld's library list is the main
+ program. Don't load the same library more than once and don't
+ consider the main program a shared library.
+ (som_solib_sharedlibrary_command): New function
+ (_initialize_som_solib): Add "sharedlibrary" command.
+
+Thu Jun 15 14:54:58 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * array-rom.c: Remove, no longer used.
+
+ * remote-hms.c (hms_open): Make static.
+
+ * mpw-config.in (MacSerial.h): Copy from version in {CIncludes},
+ not {MPW}Interfaces:CIncludes.
+ * ser-mac.c (mac_baud_rate_table): Fix value for 38400 baud.
+
+Wed Jun 14 14:27:07 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y: Remove lots of unsupported productions and names.
+ Add support for IF-expressions, ORIF, ANDIF, NUM, and ADDR.
+
+Tue Jun 13 21:40:11 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * parser-defs.h (enum precedence): Added PREC_BUILTIN_FUNCTION.
+ * expression.h (enum exp_opcode): Added UNOP_LOWER, UNOP_UPPER,
+ UNUP_LENGTH.
+ * expprint.c (dump_expression): Handle the new exp_opcodes.
+ (print_subexp): Handle PREC_BUILTIN_FUNCTION.
+ (print_simple_m2_func): Removed.
+ (print_subexp): Remove support for Modula2 builtin functions.
+ * m2-lang.c (m2_op_print_tab): Add support for builtin functions.
+ * ch-exp.y: Parse LOWER, UPPER, and LENGTH builtins.
+ (write_lower_upper_value): Convenience function for LOWER and UPPER.
+ (upper_lower_argument, length_argument): Removed non-terminals.
+ * ch-lang.c (chill_op_print_tab): Entries for UPPER, LOWER, LENGTH.
+ (type_lower_upper): New function. Calculate LOWER/UPPER of type.
+ (value_chill_length): New function. Calcalate LENGTH of ARRAY/STRING.
+ (evaluate_subexp_chill): Handle UNOP_LOWER, UNOP_UPPER, UNOP_LENGTH.
+
+Mon Jun 12 12:48:13 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ Windows support bits from Steve Chamberlain <sac@slash.cygnus.com>.
+ * defs.h: Don't declare strchr and friends if WIN32.
+ (DIRNAME_SEPARATOR): Move here from source.c.
+ (SLASH_P, SLASH_CHAR, SLASH_STRING, ROOTED_P): New macros,
+ symbolic definitions for filename bits.
+ * top.c (cd_command): Use these.
+ * source.c (mod_path, openp): Ditto.
+ * terminal.h: Disable termio/sgtty definitions if WIN32.
+ * findvar.c (registers_changed): Call registers_changed_hook
+ if it is defined.
+
+Mon Jun 12 12:22:05 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (distclean, realclean): Remove config.cache and
+ config.log.
+
+Mon Jun 12 00:21:59 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c: Include gdb-stabs.h.
+ (som_solib_section_offsets): Use SECT_OFF_XXX rather than 0, 1,
+ etc. Initialize offsets for RODATA & BSS too.
+
+Sat Jun 10 17:59:11 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-tdep.c (frame_chain): Try to compensate for incomplete
+ register information in core files when backtracing.
+
+Fri Jun 9 14:51:38 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-nrom.c: Remove everything but download code. More
+ cleanups.
+
+Thu Jun 8 15:06:00 1995 Stu Grossman (grossman@cygnus.com)
+
+ * defs.h maint.c monitor.c remote-mips.c remote.c: Add support
+ for `watchdog' variable. This allows the user to put an upper
+ limit on the amount of time that GDB will wait for the target to
+ return from a step or continue operation. This will primarily be
+ used for the testsuite, where it is difficult to come up with a
+ reasonable timeout for things like function calls, which can take
+ as long as three minutes under some circumstances. If the
+ watchdog timer expires, GDB will generate an error that looks like
+ `Watchdog has expired.', and will detach from the target.
+
+ * remote-mips.c (mips_open): Setup initial frame from target.
+ Print it out so that user is told where the program is stopped
+ when they attach.
+
+ * remote-nrom.c: Loads of cleanups. Use serial code to open
+ network connections. Use expect() to wait for response to
+ download command.
+
+ * ser-tcp.c (tcp_open): Retry connection if we get ECONNREFUSED.
+
+ * serial.c serial.h (serial_open serial_fdopen serial_close):
+ Allow users to open the same device multiple times. They all get
+ to share the same serial_t. This is about the only way to have
+ multiple active targets use the same device (for download and
+ debug).
+
+ * sparcl-tdep.c: Keep #include <unistd.h> away from GO32.
+
+ * target.c: Add `targetdebug' variable. If this is non-zero,
+ then a special target is put at the top of the target stack which
+ will cause all calls through the target vector to have their args
+ and results printed out.
+
+Wed Jun 7 17:40:37 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y: Handle <primitive_value> "->" <modename>.
+
+Wed Jun 7 17:46:33 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * mem-break.c (LITTLE_BREAKPOINT): If BREAKPOINT and
+ {LITTLE,BIG}_BREAKPOINT are all defined, don't redefine.
+ (BIG_BREAKPOINT): Ditto.
+
+ * config/rs6000/tm-rs6000.h (BREAKPOINT): Define as either
+ BIG_BREAKPOINT or LITTLE_BREAKPOINT depending on the target byte
+ order.
+
+Wed Jun 7 12:41:42 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_section_offsets): Handle relative pathnames.
+
+ * hppa-tdep.c (frame_saved_pc): Handle backtracing through signal
+ handler in dynamically linked executables.
+
+Tue Jun 6 10:44:25 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ From Andrew Cagney <cagney@highland.com.au>
+ * rs6000-tdep.c (single_step): Handle both little and big endian
+ breakpoints.
+ (gdb_print_insn_powerpc): Deal with disassembling both little and
+ big endian PowerPC systems.
+ (_initialize_rs6000_tdep): Use gdb_print_insn_powerpc to handle
+ disassembly, rather that assuming big endian order.
+
+ * config/rs6000/tm-rs6000.h (BREAKPOINT): Delete.
+ (BIG_BREAKPOINT): Define, big endian breakpoint instruction.
+ (LITTLE_BREAKPOINT): Define, little endian breakpoint instruction.
+
+Sat Jun 3 01:54:56 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Add note about Unixware 2.x.
+
+ * dbxread.c (process_one_symbol): Check for exact symbol name
+ match when fixing up N_GSYM and N_STSYM symbols from Sun acc.
+
+ * valprint.c (value_print_array_elements): Use
+ fprintf_filtered to put out `<repeats %u times>',
+ from schwab@issan.informatik.uni-dortmund.de (Andreas Schwab).
+
+ * value.h (struct value): Change `repetitions' field from
+ `short' to `int' type.
+
+
+Wed May 31 12:04:01 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/{configure.in, Makefile.in}: Converted to use autoconf.
+ * nlm/configure: New file, generated with autoconf 2.3.
+
+ * nlm/configure.in: Use sed instead of awk to get the value of
+ cpufile. Awk is not a utility required by the GNU coding
+ standards. This change also fixes the rigid whitespace
+ requirements that were required for awk.
+
+ * sparclite/aload.c: Use a file descriptor instead of a stdio
+ stream for i/o with target board.
+ Use #error if HAVE_TERMIOS is not defined.
+
+ * sparclite/{Makefile.in, configure.in}: Converted to use
+ autoconf.
+ * sparclite/configure: New file, generated with autoconf 2.3.
+
+Sun May 28 23:10:07 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * defs.h: Include either varargs.h or stdarg.h (for va_list).
+ Fix stupid thinko in last change ("..." -> "va_list").
+
+ * defs.h (vprintf_filtered declaration): Add PARAMS prototype;
+ gcc-2.5 chokes on format attributes for unprototyped functions.
+ (vfprintf_filtered declaration): Likewise.
+ (vprintf_unfiltered declaration): Likewise.
+ (vfprintf_unfiltered). Likewise.
+
+Sat May 27 23:54:17 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * configure.in: Use sed instead of awk to get the values of
+ hostfile, targetfile and nativefile. Awk is not a utility
+ required by the GNU coding standards. This change also
+ fixes the rigid whitespace requirements that were required
+ for awk.
+ * configure: regenerated.
+
+Sat May 27 16:24:04 1995 Angela Marie Thomas <angela@cirdan.cygnus.com>
+
+ * sparclite/{Makefile,configure}.in: Add hooks for building with
+ -lsocket & -lnsl for solaris2. Don't build aload/eload for DOS.
+
+Thu May 25 12:46:37 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbserver/remote-utils.c (prepare_resume_reply): Add FIXME
+ comment regarding signal numbering.
+
+Wed May 24 15:49:47 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * arm-tdep.c (_initialize_arm_tdep): Use print_insn_little_arm
+ now.
+
+ * arm-tdep.c (convert_from_extended, convert_to_extended):
+ New.
+ * coffread.c (enter_linenos): Return if linetab 0.
+ * config/arm/arm.mt (TDEPFILES): Add simulator support.
+ * config/arm/tm-arm.h (FRAME_FIND_SAVED_REGS): Fix prototypes.
+
+Mon May 22 19:37:21 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * config/idt.mt: replace monitor and array-rom with the new
+ remote-array.
+
+Mon May 22 15:38:25 1995 Stu Grossman (grossman@cygnus.com)
+
+ * remote-nindy.c: Install Kung patch for PR 6820. I have no idea
+ what this does...
+
+ * breakpoint.c: Move defaults of watchpoint related macros into
+ target.h.
+ * target.h: Macros from breakpoint.c. Conditionalize based on
+ TARGET_HAS_HARDWARE_WATCHPOINTS.
+ * i386v-nat.c procfs.c: Use TARGET_HAS_HARDWARE_WATCHPOINTS
+ instead of TARGET_CAN_USE_HARDWARE_WATCHPOINT to enable watchpoint
+ code.
+ * config/i386/nm-linux.h, config/mips/nm-irix4.h,
+ config/pa/nm-hppab.h, config/sparc/tm-sparclite.h: #define
+ TARGET_HAS_HARDWARE_WATCHPOINTS to enable watchpoint code.
+
+Mon May 22 06:47:30 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c, target.h: Move defaults of watchpoint related
+ macros back to breakpoint.c. Required to get GDB compiling
+ on Solaris again.
+
+Fri May 19 14:49:37 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * defs.h (ATTR_FORMAT): New macro, expands to gcc's format
+ attribute when compiled by gcc.
+ * defs.h, language.h, monitor.h: Changed many function
+ declarations to use ATTR_FORMAT.
+
+ * breakpoint.c (delete_command); source.c (directory_command);
+ top.c (define_command): Changed call to query() that had too
+ many arguments.
+ * printcmd.c (address_info): Changed call to printf_filtered()
+ that had too many arguments.
+
+Fri May 19 09:52:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (wait_for_inferior): Move assignments to stop_signal
+ and stop_pc, and STOPPED_BY_WATCHPOINT code, back where they
+ were--after the switch statement on w.kind. You can't read the
+ registers of an inferior which has exited. Use a goto in the
+ STOPPED_BY_WATCHPOINT code.
+ * infrun.c (wait_for_inferior): Reinstate
+ HAVE_STEPPABLE_WATCHPOINT and HAVE_CONTINUABLE_WATCHPOINT code.
+
+Fri May 19 06:15:40 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * utils.c, complaints.c, language.c, monitor.c, remote-array.c,
+ remote-mips.c, remote-os9k.c, remote-st.c: Conditionalize use of
+ stdarg rather than varargs on ANSI_PROTOTYPES not __STDC__; it
+ must match the definition of PARAMS.
+
+Thu May 18 15:58:46 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * utils.c (fprintf_filtered, fprintf_unfiltered, fprintfi_filtered,
+ printf_filtered, printf_unfiltered, printfi_filtered, query, warning,
+ error, fatal, fatal_dump_core): Use stdarg.h macros when compiling
+ with an ANSI compiler.
+ * complaints.c (complain): Likewise.
+ * language.c (type_error, range_error): Likewise.
+ * monitor.c (monitor_printf, monitor_printf_noecho): Likewise.
+ * remote-array.c (printf_monitor, debuglogs): Likewise.
+ * remote-mips.c (mips_error): Likewise.
+ * remote-os9k.c (printf_monitor): Likewise.
+ * remote-st.c (printf_stdebug): Likewise.
+
+ * defs.h, complaints.h, language.h, monitor.h: Add prototypes to
+ match above changes.
+
+ * printcmd.c: Remove uneeded #include <varargs.h>.
+ * remote-e7000.c: Likewise.
+
+ * f-typeprint.c (f_type_print_base): Fix typo found by above
+ changes.
+
+Wed May 17 11:21:32 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * Makefile.in (xcoffread.o): Depend on partial-stab.h.
+
+ * xcoffsolib.c (sharedlibrary_command): New command.
+ * xcoffsolib.c (solib_info): Call xcoff_relocate_symtab.
+ * xcoffsolib.c: Miscellaneous cleanups.
+
+ * partial-stab.h: Ignore symbol descriptor '-' (for local
+ variables with negative type numbers) without complaint.
+
+ * rs6000-nat.c (vmap_ldinfo): Use bfd_stat rather than our own
+ local emulation thereof. Remove unused variable ostart.
+
+Wed May 17 15:55:53 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (config.status): changed target so that
+ config.status --recheck is executed if configure script changes.
+
+ * monitor.c (monitor_printf): Changed format specification in
+ error message to work with pre-ansi compilers.
+ (monitor_load_srec): reduced length of s-records from 128 to 32
+ bytes so download is more reliable with the rom68k monitor.
+
+ * rom68k-rom.c: Added trailing space to prompt string.
+
+ * config/i386/xm-i386sco.h (HAVE_STRSTR): Removed.
+ * config/i386/xm-go32.h, mswin/xm.h (SYS_SIGLIST_MISSING):
+ Removed.
+ * defs.h, config/{xm-lynx.h, xm-nbsd.h},
+ config/i386/{xm-i386bsd.h, xm-linux.h},
+ config/m68k/xm-hp300bsd.h, config/mips/xm-irix4.h,
+ config/ns32k/xm-ns32km3.h, doc/gdbint.texinfo
+ (PSIGNAL_IN_SIGNAL_H): Removed.
+
+Tue May 16 13:16:06 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * Makefile.in (Makefile): Added config.status to dependency list.
+
+ * configure.in: Added INIT-CMDS argument to AC_OUTPUT which sets
+ gdb_host_cpu, gdb_target_cpu and nativefile.
+ * configure: regenerated.
+
+Mon May 15 23:50:51 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Do not relocate stBlock/scText
+ symbols, their value is the displacement from the procedure address.
+ * top.c (init_main): Add missing newlines to help strings for
+ `if' and `while' commands, fix help string for `show commands'.
+
+Mon May 15 18:37:56 1995 Stu Grossman (grossman@cygnus.com)
+
+ * breakpoint.c: Move defaults of watchpoint related macros into
+ target.h. Use BP_TEMPFLAG and BP_HARDWAREFLAG instead of
+ constants.
+ * infrun.c (wait_for_inferior): Enhance comment near
+ STOPPED_BY_WATCHPOINT.
+ * target.h: Macros from breakpoint.c.
+
+Mon May 15 17:11:38 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * config/i386/{i386sol2.mh, i386v4.mh, ncr3000.mh},
+ config/m68k/m68kv4.mh, config/mips/{irix4.mh, irix5.mh,
+ mipsv4.mh}, config/sparc/sun4so2.mh (INSTALL): Removed, figured
+ out by autoconf.
+ * config/apollo68v.mh (RANLIB): Removed, figured out by autoconf.
+
+ * Makefile.in, configure.in: Converted to use autoconf
+ * aclocal.m4: New file, local autoconf macro definitions.
+ * configure: New file, generated with autoconf 2.3.
+
+Mon May 15 14:46:41 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote.c (remote_kill): Add prototype.
+ * cpu32bug-rom.c (cpu32bug_open): Properly define as static.
+ * config/h8300/h8300hms.mt (TDEPFILES): Add monitor.o.
+
+Mon May 15 12:12:34 1995 Stu Grossman (grossman@cygnus.com)
+
+ * sparclite/salib.c (win_ovf win_unf): Make window size constant
+ into a variable (__WINSIZE) so that it can be controlled via the
+ .h file.
+ * sparclite/sparclite.h: Add SL933 #ifdef to set __WINSIZE to 6
+ for the 933 board.
+
+ * infrun.c: Add #ifdef HP_OS_BUG to all references to
+ trap_expected_after_continue.
+ * (wait_for_inferior): Fix for remote watchpoints. Don't try to
+ insert breakpoints while target is running (this only works on
+ *some* native targets). This may also speed up native watchpoints
+ considerably.
+
+Sat May 13 13:55:04 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dwarfread.c (struct dwfinfo), dbxread.c (struct symloc),
+ mdebugread.c (struct symloc), hpread.c (struct symloc),
+ xcoffread.c (struct symloc): Fix inaccurate comment introduced
+ 20 Apr 1995.
+
+Sat May 13 13:34:18 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * rs6000-tdep.c (find_toc_address): Revise comment.
+ * symfile.c, symfile.h (init_psymbol_list): New function;
+ consolidate duplicated copies from os9kread.c, dbxread.c
+ and dwarfread.c.
+ * defs.h: Declare info_verbose.
+ * xcoffread.c: Extensive changes to support psymtabs.
+
+Fri May 12 13:48:41 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * cpu32bug-rom.c remote-est.c rom68k-rom.c: Update line_term element.
+
+Fri May 12 06:39:30 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * partial-stab.h: Expand comments.
+
+Thu May 11 19:01:37 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * Support debugging using native MACH primitives on hppa*-*-osf*.
+ * configure.in: hppa*-*-osf* != hppa*-*-bsd* anymore.
+ * config/pa/hppaosf.mh: New file.
+ * config/pa/nm-hppao.h: Likewise.
+ * hppam3-nat.c: Likewise.
+ * config/pa/tm-hppao.h (PSW_SS): Define for single-stepping.
+ (MACHINE_CPROC_*_OFFSET): Define.
+ (TRACE_*): Define.
+ (START_INFERIOR_TRAPS_EXPECTED): Delete definition.
+
+Wed May 10 18:59:26 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * hppa-tdep.c (read_unwind_info): Cosmetic cleanup.
+ * (unwind_command): Clean it up and make it print things out
+ nicer.
+ * monitor.c: Add ^C handling capability (mostly ripped off from
+ remote.c).
+ * (monitor_printf): Make it check the command echo.
+ * (monitor_printf_noecho): Similar to above, but doesn't check
+ for echo.
+ * (monitor_stop): No longer waits for prompt. That is the job of
+ the caller. This makes things work much better for monitor_wait,
+ which waits for the prompt itself.
+ * (monitor_open): Deal with new monitor_stop semantics. Also,
+ flush input after sending init strings to get rid of junk that may
+ be output. Also, don't always send \r to remote. Use
+ monitor_ops->line_term cuz proper character isn't always \r.
+ * (monitor_fetch_register): Switch to completely different
+ algorithm to deal with lame-ass monitors which put spaces in the
+ middle of numbers, and prompt with a space!!!!!
+ * (monitor_read_memory_single): New routine to be used with
+ monitors that can only return one byte/short/long at a time. This
+ is selected via MO_GETMEM_READ_SINGLE.
+ * (monitor_load_srec): Use monitor_printf_noecho for sending S
+ records. Most targets don't echo them.
+ * (monitor.h): Get rid of cmd_delim. Add line_delim.
+ * op50n-rom.c (op50n_cmds): Fill it up. Make it work.
+ * w89k-rom.c: Change all eols from \r to \n. Change load_resp to
+ ^Q to prevent error message.
+ * config/pa/tm-hppa.h (CALL_DUMMY (for hppro)): Add special
+ instruction sequence at end to make restore_pc_queue happy.
+
+Wed May 10 15:59:00 1995 Torbjorn Granlund <tege@adder.cygnus.com>
+
+ * remote-est.c (est_open): Make static to match prototype.
+
+Tue May 9 16:58:50 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * configure.in: Add little endian PowerPC support.
+ * config/powerpc/ppcle-eabi.mt: New file for little endian PowerPC
+ support.
+ * config/powerpc/tm-ppcle-eabi.h: ditto.
+
+Mon May 8 12:11:38 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/configure.in (gdb_host, gdb_host_cpu, gdb_target): Removed.
+ These variables not used.
+
+ * config/m68k/monitor.mt (TDEPFILES): Added cpu32bug-rom.o.
+
+Wed May 3 17:54:47 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c (monitor_command): Don't use PROMPT until monitor
+ target is known to be open.
+ (monitor_make_srec): Don't define size of hextab.
+
+Tue May 2 18:32:24 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * configure.in (--enable-netrom): New configuration option.
+ * Makefile.in (REMOTE_OBS): Rename from REMOTE_O, append
+ value of NETROM_OBS.
+ (NETROM_OBS): New variable.
+ * remote-nrom.c: New file, NetROM target support.
+ * config/a29k/a29k-udi.mt, config/i960/vxworks960.mt: Use
+ REMOTE_OBS instead of REMOTE_O.
+
+Fri Apr 28 23:30:00 1995 Stu Grossman (grossman@cygnus.com)
+
+ * array-rom.c (_initialize_array array_open): Move baud_rate
+ initialization from _initxxx to array_open to fix bug with
+ overriding -b command line option.
+
+Thu Apr 27 20:29:34 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (RUNTEST): Fix reference of `srcdir'.
+
+Wed Apr 26 19:01:08 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * remote-hms.c: Rewrite to use new monitor conventions.
+
+Tue Apr 25 11:27:14 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dbxread.c: Add comment explaining lowest_text_address.
+ Add comment regarding stringtab_global and psymtabs.
+
+Sat Apr 22 01:26:29 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * config/pa/tm-hppa.h (EXTRACT_STRUCT_VALUE_ADDRESS): Fix.
+
+ * config/pa/tm-hppa.h (EXTRACT_RETURN_VALUE): Rewrite to correctly
+ handle "short", "int" and small structures returned in registers.
+
+Fri Apr 21 12:57:53 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * minsyms.c: add new function lookup_minimal_symbol_text, to look
+ for text symbol only.
+ * breakpoint.c (create_longjmp_breakpoint): call
+ lookup_minimal_symbol_text instead of lookup_minimal_symbol.
+ * symtab.h: add lookup_minimal_symbol_text prototype.
+
+Fri Apr 21 12:03:44 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * sh-tdep.c (sh-opc.h): Don't include.
+ (gdbcore.h): Include.
+ (frame_find_saved_regs): Remove unused local.
+
+Thu Apr 20 10:12:21 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dwarfread.c (struct dwfinfo), dbxread.c (struct symloc),
+ mdebugread.c (struct symloc), hpread.c (struct symloc): Clean
+ up comments.
+
+Wed Apr 19 16:58:11 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * hppa-tdep.c (deposit_17): New routine to deposit 17 bit
+ constants into PA instructions.
+ * Put #ifdefs around all signal handling code. Not generally
+ needed for embedded boards.
+ * (hppa_fix_call_dummy): Parameterize offsets into call dummy to
+ allow different dummys to be used by this code. Use
+ INSTRUCTION_SIZE instead of REGISTER_SIZE for things.
+ Conditionalize setup of _sr4export fixup. Improve comments.
+ * config/pa/tm-hppa.h: Define INSTRUCTION_SIZE. Use a different
+ call dummy if PA_LEVEL_0 is defined. Better comments for call
+ dummys. Define offsets for LDIL/LDO instructions which load
+ function addresses.
+ * config/pa/tm-pro.h: Get rid of signal handling stuff. Define
+ PA_LEVEL_0 to disable mucking with space regs and such.
+
+Mon Apr 17 15:37:08 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * cpu32bug-rom.c monitor.h op50-rom.c remote-est.c rom68k-rom.c
+ w89k-rom.c: Remove loadtypes, loadprotos and baudrates.
+ * op50-rom.c: Fix copyrights and add load routine to op50n_cmds.
+ * rom68k-rom.c (_initialize_rom68k): Don't set baud rate.
+ * w89k-rom.c: Fix copyrights.
+
+Sun Apr 16 14:00:55 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * monitor.c: Move all xmodem stuff into xmodem.[ch]. Remove
+ unnecessary remoteloadprotocol and remoteloadtype support.
+ * (expect expect_prompt): Change names to monitor_expect and
+ monitor_expect_prompt. Make them global.
+ * (printf_monitor): Change name to monitor_printf. Make global.
+ * (monitor_read_memory): Flush command echo to avoid parsing
+ ambiguity with CPU32Bug monitor.
+ * (monitor_load): Remove remoteloadprotocol and remoteloadtype
+ support. Call target_ops->load_routine, default to
+ monitor_load_srec.
+ * (monitor_load_srec): Remove everything but S-record support.
+ * monitor.h (monitor_ops): Add load_routine to provide monitor
+ specific download capability.
+ * remote-est.c: Clean up copyrights and comments.
+ * w89k-rom.c: Use new xmodem support.
+ * xmodem.c xmodem.h: New files to support xmodem downloads.
+ * rom68k-rom.c remote-est.c: Fix copyrights, add load_routine
+ entry to monitor_ops.
+ * cpu32bug-rom.c: New file to support Moto BCC debuggers.
+ * config/m68k/est.mt (TDEPFILES): Add cpu32bug.o.
+ * config/pa/hppapro.mt (TDEPFILES): Add xmodem.o.
+
+Sat Apr 15 18:00:15 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * rem-multi.shar: Removed; superceded by gdbserver.
+
+Fri Apr 14 12:10:24 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * xcoffread.c (xcoff_sym_fns): Revise comment about merging this
+ with coffread.c.
+
+ * breakpoint.c (fixup_breakpoints): Removed.
+ * rs6000-nat.c (vmap_symtab): Don't call fixup_breakpoints.
+ (vmap_ldinfo, xcoff_relocate_core): Call breakpoint_re_set.
+
+ * coffread.c (coff_symfile_offsets): Allocate SECT_OFF_MAX
+ sections, not just SECT_OFF_MAX-1.
+
+ * rs6000-nat.c (vmap_symtab), xcoffread.c: Re-do section offsets
+ to be indexed by SECT_OFF_* instead of xcoff section numbers.
+ * objfiles.c, remote.c: Remove comments regarding SECT_OFF_*.
+ * symtab.h: Revise comment about block_line_section.
+ * rs6000-nat.c (vmap_symtab): Don't relocate objfile->sections.
+
+Sat Apr 15 14:15:14 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.in (init.c): Don't try to do symbolic {o} in sed
+ command, not allowed by some version of MPW Make.
+ * ser-mac.c (mac-setbaudrate): Make it actually set baud rates.
+
+Sat Apr 15 14:05:09 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * alpha-tdep.c (alpha_push_arguments): Fix typo (TYPE_VALUE ->
+ VALUE_TYPE). Do the cast for TYPE_CODE_BOOL, TYPE_CODE_CHAR,
+ TYPE_CODE_ENUM, and TYPE_CODE_RANGE as well as TYPE_CODE_INT.
+
+Sat Apr 15 14:04:32 1995 Per Bothner <bothner@cygnus.com>
+
+ * alpha-tdep.c (alpha_push_arguments): Only cast to long for
+ TYPE_CODE_INT.
+
+
+Thu Apr 13 16:17:04 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * remote-array.c: New file for Array Tech LSI33k based controller
+ board.
+
+Thu Apr 13 12:23:31 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * a29k-tdep.c (get_longjmp_target): Replace SWAP_TARGET_AND_HOST with
+ extract_address.
+ * remote-vxsparc.c: New file, preliminary check in, this configuration
+ not supported yet.
+ * remote-vxmips.c: ditto.
+
+Thu Apr 13 12:10:14 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * rs6000-tdep.c (xcoff_add_toc_to_loadinfo): Don't use a prototype
+ to declare the function.
+
+Wed Apr 12 16:40:20 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.h (init_monitor_ops): Declare.
+ * rom68k-rom.c: Clarify some comments.
+ (rom68k_open): Define as static, to match decl.
+
+Wed Apr 12 16:36:44 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.gdb: New file.
+ * .gdbinit: Move list-objfiles to gdb.gdb.
+
+ * values.c (set_internalvar): Set modifiable flag of newval.
+
+Wed Apr 12 14:34:31 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * xcoffread.c: Call complain() rather than error() or printing a
+ warning.
+
+
+Tue Apr 11 16:42:37 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * top.c, utils.c, defs.h: Remove error_hook. It is currently
+ unused and would need to hook into error_begin()/return_to_top_level(),
+ instead of error(), if it were to be used.
+
+Tue Apr 11 13:46:25 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * utils.c, defs.h (warning_begin): Renamed from warning_setup, for
+ consistency with error_begin. Also print warning_pre_print.
+ Document it better.
+ * utils.c (warning): Use it.
+ * utils.c (error_begin): Doc fix.
+ * rs6000-nat.c (vmap_ldinfo): If we don't find ldinfo for the
+ symfile_objfile, nuke it.
+
+Tue Apr 11 09:35:20 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * printcmd.c (print_address_numeric): Pass use_local to
+ print_longest, rather than always passing 1.
+
+ * nlm/Makefile.in: Remove comments discussing munch.
+
+
+Mon Apr 10 18:31:57 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ Merge in support for Mac MPW as a host.
+ (Old change descriptions retained for informational value.)
+
+ * mpw-config.in (i386-unknown-go32): Change from aout.
+ (sh-hitachi-hms): New target.
+ * mpw-make.in (BISON): Use byacc instead of bison.
+ (VERSION): Bump to 4.14.1.
+ (*-pinsn.*): Remove mentions everywhere.
+ (all): Don't build MacGDB.
+ (gdb, SiowGDB): Depend on Version.r.
+ (Version.r): Generate from version info.
+ * main.c (main): Pass program name to START_PROGRESS, END_PROGRESS.
+ (main) [MPW]: Remove debugging hook.
+ * mac-xdep.c (debug_openp): New flag.
+ (mac_init): Set flag if env variable defined.
+ * ser-mac.c (mac_open): Clarify error message.
+ (mac_readchar): Call PROGRESS while looping.
+ (mac_write): Call sleep instead of sec_sleep.
+ (sec_sleep): Remove.
+ * source.c (openp) [MPW]: Only print debugging info if debugging.
+ * utils.c (query) [MPW]: Clarify that behavior is a bug.
+
+ * mpw-make.in (init.c): Use open-brace instead of mpw-open-brace.
+
+ * main.c, source.c: Remove hacks that replace long strings
+ with shorter ones, now solved portably.
+
+ * config/m68k/xm-mpw.h (spin.h): Include.
+ (ALMOST_STDC): Only define if MPW_C.
+ * config/m68k/tm-mac.h: New file, Mac target definitions.
+
+ * mpw-config.in (m68k-apple-macos, ppc-apple-macos,
+ i386-unknown-aout): New targets.
+ (mk.tmp): Add *DEPFILES definitions.
+ * mpw-make.in: Remove gC rules, clean up definitions for other
+ include files, bump version, fix bogus \ that should be \Option-d.
+ (init.c): Build correctly.
+
+ * mpw-make.in (HFILES_NO_SRCDIR): Add somsolib.h
+ (ALLDEPFILES): Add somsolib.c.
+ (somsolib.o): Add some dependencies.
+
+ * mpw-config.in: Use nm-empty.h if host is not target.
+ (xdepfiles): Add mac-xdep.c.o.
+ (xm_file): Remove.
+ * mpw-make.in: Add Fortran files.
+ (XDEPFILES): Remove.
+
+ * mpw-config.in (MacSerial.h): Duplicate from standard Serial.h.
+ * ser-mac.c (MacSerial.h): Include instead of Serial.h.
+
+ * mpw-make.in: Use {s} instead of {srcdir} everywhere.
+ (bindir, libdir): Remove extra colon.
+ (source.c): Compile with C instead of gC.
+ (c-exp.tab.c, ch-exp.tab.c, m2-exp.tab.c): Add {o}.
+ (install-only): Don't install MacGDB.
+ * source.c (openp) [MPW]: Add a debugging display.
+ (open_source_file) [MPW]: Use MPW basename finders.
+ [MPW_C]: Briefer versions of help for line and list commands.
+
+ * mpw-make.in: Change references from paread.c to somread.c
+
+ * mpw-make.in (VERSION): Update to 4.12.3.
+ (SiowGDB): New target, GDB using SIOW library.
+ (init-new.c): New target, attempt to generate init.c from sources.
+ (main.c.o, top.c.o): Put each in its own segment.
+ * main.c (main) [MPW]: Always call mac_init.
+ * utils.c (query) [MPW]: Always return "yes" if in MacGDB, output
+ an extra newline otherwise.
+ * mac-xdep.c: More comments in various places, remove junk.
+ (mac_init): Add tests for MPW and SIOW.
+ (use_wne, has_color_qd): Renamed.
+ (use_color_qd): New variable.
+ (grow_window): Only do console resizing to console window,
+ call resize_console_window.
+ (zoom_window): Call resize_console_window.
+ (resize_console_window, scroll_text): New functions.
+ (adjust_console_sizes): Always align viewrect to even multiples of
+ text lines.
+ (adjust_console_text): Always scroll by whole lines.
+ (hacked_vfprintf, hacked_puts, hacked_fputc, hacked_putc): Force a
+ recalculation of scroll positions if a newline was output.
+ (hacked_fflush): Similarly, for flushing.
+ (hacked_fgetc): New function, aborts if called in MacGDB.
+ * ser-mac.c (mac_readchar): Rename starttime to start_time,
+ remove debugging printf.
+ (mac_write): Sleep on first 4 writes.
+ (sec_sleep): New function, works like standard sleep.
+ * macgdb.r: Adjust positioning and contents of About box.
+ Set minimum size to 2000K, preferred size to 5000K.
+ * config/m68k/xm-mpw.h (fgetc): Define as a macro.
+
+ * mpw-make.in (.c.o, .gc.o): Prefix segment names with gdb_.
+ (top.c.o, annotate.c.o): Add build rules.
+ * macgdb.r (SysTypes.r): Include.
+ ('vers'): New resource, version info.
+ (mFile, mEdit, mDebug): Enable all menu items.
+ (mDebug): Add key equivalents for continue, step, next.
+ (wConsole): Add zoom and close boxes to window.
+ * mac-xdep.c (new_console_window): New function, code taken from
+ mac_init.
+ (mac_command_loop): Use GetCaretTime for wait interval, call
+ do_idle on null events.
+ (do_idle): New function.
+ (zoom_window): Implement zooming.
+ (v_scroll_proc): New function, handles vertical scrolling.
+ (activate_window): Do activation of console window.
+ (do_menu_command): Implement items of file, edit, and debug menus.
+ (do_keyboard_command): Fix command extraction.
+ (adjust_console_sizes, adjust_console_text): New functions.
+ (hacked_fprintf, hacked_vfprintf, hacked_fputs, hacked_fputc,
+ hacked_putc): Don't call draw_console.
+ * ser-mac.c (mac_open): Add an error message for invalid ports.
+ (first_mac_write): New global.
+ (mac_write): Use first_mac_write to sleep on first several writes.
+
+ * mpw-make.in (INCLUDE_CFLAGS): Add readline source dir.
+ (READLINE_CFLAGS, READLINE_SRC, READLINE_DIR): Uncomment.
+ (TSOBS): Don't compile inflow.c.
+ (all, install): Add MacGDB.
+ * main.c (main): Do Mac-specific init and command loop if a
+ standalone app, skip full option help message if compiling
+ with MPW C.
+ (gdb_readline): If MPW, add a newline after the (gdb) prompt.
+ * utils.c (_initialize_utils): If MPW, don't try to use termcap to
+ compute the window size.
+ * config/m68k/xm-mpw.h (printf, fprintf, fputs, fputc, putc,
+ fflush): Define as macros that expand into hacked_... versions.
+ (StandAlone, mac_app): Declare.
+ * macgdb.r (SIZE): Set the default partition to 4000K.
+ * mac-xdep.c (readline.h, history.h): Include.
+ (terminal.h): Don't include.
+ (mac_app): Define.
+ (gdb_has_a_terminal): Define Mac-specific version.
+ (do_keyboard_command): Simplify search for command string.
+ (readline): Define as gdb_readline.
+ Add other history/readline stubs to make main gdb link.
+ (hacked_fprintf, hacked_printf, hacked_vfprintf, hacked_fputs,
+ hacked_fputc, hacked_fflush): New functions, intercept output to
+ stdout and stderr, send to console window.
+
+ * mpw-make.in (MacGDB): New target, standalone Mac-hosted gdb.
+ (XDEPFILES): Define.
+ (main.c.o): Compile with gC instead of C.
+ * mac-defs.h: New file, menu etc definitions shared between
+ C and Rez files.
+ * macgdb.r: New file, Rez (resource compiler) resource
+ definitions.
+ * mac-xdep.c: New file, Mac host interface code.
+ * config/m68k/xm-mpw.h (PATHNAME_SEPARATOR): Rename to
+ DIRNAME_SEPARATOR.
+ (PATHNAME_SEPARATOR_STRING): Remove.
+ (SIGQUIT, SIGHUP): Define.
+ (fileno, R_OK): Define.
+
+ * mpw-config.in: New file, MPW configuration fragment.
+ * mpw-make.in: New file, MPW makefile fragment.
+ * config/m68k/xm-mpw.h: New file, MPW host definitions.
+ * ser-mac.c: New file, Mac serial interface.
+
+Mon Apr 10 16:47:57 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * valprint.c (print_longest): Fix a syntax error in #ifdef
+ PRINTF_HAS_LONG_LONG.
+
+ * config/mips/xm-irix5.h: turn on CC_HAS_LONG_LONG and
+ PRINTF_HAS_LONG_LONG.
+ * config/mips/tm-irix5.h: turn on FORCE_LONG_LONG.
+
+Sat Apr 8 02:47:45 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): Use new variable
+ nodebug_var_symbol_type as type of variables which don't have any
+ ecoff debug info associated with them.
+ (parse_symbol, parse_procedure): Use heuristics to determine if
+ functions were compiled without debugging info and change their
+ type to nodebug_function_symbol_type.
+ (_initialize_mdebugread): Initialize nodebug_*_symbol_type.
+
+ * source.c (line_info): Clear sal.pc for `info line' without
+ arguments.
+
+Fri Apr 7 17:43:01 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * monitor.c: make_xmodem_packet and print_xmodem_packet go away.
+ send_xmodem_packet shows up to do the obvious. Lots of fixes to
+ xmodem downloads including resetting of block number at start of
+ new transfers, fix for buffer overrun problem, addition of CRC
+ generation code.
+ * (monitor_open): loadtype_str and loadproto_str now default to
+ first entry in monitor_ops->loadtypes.
+ * (monitor_wait): Lengthen register dump buf, because of verbose
+ Winbond monitor.
+ * (monitor_fetch_register): Report unimplemented registers as 0.
+ * (monitor_read_memory): Only do 16 byte aligned transfers
+ because of formatting weirdness with the Winbond monitor. Also,
+ ignore non-hex, non-whitespace formatting between bytes (same
+ monitor).
+ * (monitor_load): Clean up logic.
+ * (monitor_load_srec): Re-do xmodem support. Move lots of it
+ into send_xmodem_packet.
+ * (getacknak): Get rid of polls and timeouts. Handle CRC
+ requests from receiver.
+ * (monitor_make_srec): Efficiency improvements. Don't call
+ sprintf to output two digit hex numbers.
+ * (crcinit, docrc): New, CRC-16 support routines.
+ * (send_xmodem_packet): New routine to generate either CRC-16 or
+ checksummed xmodem packets.
+
+ * remote-est.c (est_loadtypes), rom68k-rom.c (rom68k_loadtypes):
+ Reduce tables down to only the load types supported by each
+ monitor.
+
+ * w89k-rom.c (w89k_supply_register): Parses output of Winbond
+ register dumps.
+ * (w89k_loadtypes, w89k_loadprotos): Reduce to just srec/xmodem.
+ * (w89k_cmds): Add clear all breakpoints, memory fill, and dump
+ registers commands.
+
+ * config/pa/tm-hppa.h: Define lots register offsets needed by
+ w89k-rom.c.
+
+
+Thu Apr 6 17:00:46 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * Makefile.in (X11_INCLUDES): Define as empty.
+ (X11_CFLAGS): Define as including $(X11_INCLUDES).
+ (X11_LIB_SWITCHES): Define as empty.
+ (X11_LIBS): Define as -lX11.
+
+
+Wed Apr 5 19:57:38 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips-tdep.c (mips_print_register): Remove unused variable
+ our_type and call to init_type. Fixes memory leak. Reindent function.
+
+ * mips-tdep.c (mips_print_register), findvar.c
+ (write_register_bytes): Make buffer char[] instead of unsigned
+ char[].
+
+Mon Apr 3 19:28:14 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * top.c, utils.c, main.c, defs.h: Replace error_pre_print with two
+ variables: error_pre_print (for RETURN_ERROR) and quit_pre_print
+ (for RETURN_QUIT). Fixes a bug whereby typing ^C (e.g. in "maint
+ print sym") could output extraneous stuff.
+ * objfiles.c: Don't declare error_pre_print; defs.h does it.
+
+Mon Apr 3 13:48:28 1995 Stu Grossman (grossman@andros.cygnus.com)
+
+ * monitor.h: Add MO_GETMEM_NEEDS_RANGE flag.
+ * monitor.c (monitor_read_memory): Use previously mentioned flag
+ to send proper format memory examine commands to the w89k monitor.
+ Also, try to handle bizarre format of memory dump...
+
+ * op50-rom.c w89k-rom.c: Update to new monitor.[ch] conventions.
+
+Sat Apr 1 03:22:20 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (process_one_symbol) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Handle relocated symbol address.
+ * partial-stab.h, case N_SO, SOFUN_ADDRESS_MAYBE_MISSING:
+ Do not relocate a zero address.
+
+Thu Mar 30 19:46:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/a29k/tm-a29k.h: Nuke obsolete define CONTROL_END_ADDR; it
+ is nowhere used.
+
+ * stabsread.c (read_range_type): Remove FIXME comment about
+ type-id (I presume this meant a number followed by = followed by a
+ type) versus type number; Per fixed it.
+
+Wed Mar 29 09:56:04 1995 Jason Molenda (crash@phydeaux.cygnus.com)
+
+ * configure.in: sparc-*-sunos5* is same as sparc-*-solaris2*.
+
+Wed Mar 29 18:30:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-e7000.c (why_stop): Add new kinds of strings to expect
+ from the emulator.
+ (e7000_wait): Add interpretations for more stop reasons,
+ including warnings for write protect and cycle address errors.
+
+Wed Mar 29 17:09:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c monitor.h remote-est.c rom68k-rom.c: Add start of
+ support for interrupting target.
+ * monitor.c (monitor_open): Send stop command before doing
+ anything else.
+ * (monitor_load_srec): Fix record size calculation to prevent end
+ of segment from getting trashed.
+ * rom68k-rom.c: Update to latest version of struct monitor_ops.
+ * config/sparc/tm-sparc.h (FIX_CALL_DUMMY): Fix byte-order
+ problems. Makes DOS hosted function calling work.
+ * sparclite/crt0.s: Define _start to make COFF happy.
+
+Wed Mar 29 09:11:51 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * defs.h (atof): Don't provide an external declaration if atof is
+ a macro.
+
+Wed Mar 29 00:01:07 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * rs6000-tdep.c (skip_prologue): Skip saving of LR and CR in
+ the stack frame, fix typos in `st rx,NUM(r1)' and `stu r1,NUM(r1)'
+ tests.
+
+Tue Mar 28 17:04:04 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdbtypes.c (create_range_type): If indextype has TYPE_FLAG_STUB
+ set, set TYPE_FLAG_TARGET_STUB.
+ (check_stub_type): Recalculate TYPE_LENGTH for range type.
+ * stabsread.c (read_range_type): If index type number is followed
+ by '=', back up, call read_type. and assume we have a true range.
+ * gdbtypes.h (TYPE_FLAG_TARGET_STUB): Update comment.
+
+Mon Mar 27 22:51:54 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-nat.c, irix4-nat.c, irix5-nat.c, mipsv4-nat.c,
+ sparc-tdep.c (supply_gregset, supply_fpregset): Fill inaccessible
+ registers with zero to handle recent read_register_bytes change.
+ * irix4-nat.c, irix5-nat.c, mipsv4-nat.c (supply_gregset,
+ fill_gregset): Fix handling of CAUSE_REGNUM.
+ * mips-nat.c (store_inferior_registers): Handle unwritable
+ registers when storing a single register.
+ * config/mips/tm-irix3.h (CAUSE_REGNUM, BADVADDR_REGNUM):
+ Fix definitions.
+
+ * mdebugread.c (parse_symbol, psymtab_to_symtab_1): Clear
+ allocated mips_extra_func_info, if the debug info is corrupt,
+ the PDR to fill it in might be missing.
+
+Mon Mar 27 14:43:00 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * vx-share/regPacket.h: a new file interfacing with vxworks.
+
+Sun Mar 26 13:22:47 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (bpstat_do_actions): Once we've executed the
+ commands, set bs->commands to NULL.
+
+Sat Mar 25 01:16:10 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * buildsym.c (patch_subfile_name): Update last_source_file
+ with the real source file name.
+ * dbxread.c (end_psymtab): Handle static functions in the
+ SOFUN_ADDRESS_MAYBE_MISSING case by passing pst->filename
+ to lookup_minimal_symbol.
+ (process_one_symbol): Ignore extra outermost context from
+ SunPRO cc and acc.
+ * stabsread.c (define_symbol): Do not complain for SunPRO
+ static variable encoding if STATIC_TRANSFORM_NAME is defined.
+ * sparc-tdep.c, config/sparc/tm-sun4sol2.h
+ (sunpro_static_transform_name): Renamed from
+ solaris_static_transform_name.
+ * config/sparc/tm-sun4os4.h (STATIC_TRANSFORM_NAME):
+ Define to sunpro_static_transform_name for acc 3.0 compiled
+ executables.
+ * procfs.c, config/alpha/nm-osf2.h (PROCFS_DONT_TRACE_FAULTS):
+ Renamed from PROCFS_DONT_TRACE_IFAULT, don't trace any faults
+ if defined.
+ * procfs.c (info_proc_siginfo): Cast sip->si_addr to
+ `unsigned long' and use `lx' format for printing it.
+
+Fri Mar 24 15:45:42 1995 Stu Grossman (grossman@cygnus.com)
+
+ * configure.in: Move test for m68*-est-* before m68*-*-coff*.
+ * findvar.c: Move default def of CANNOT_STORE_REGISTER closer to
+ the beginning of the code.
+ * (write_register_gen): New routine. Analogous to
+ read_register_gen.
+ * (write_register_bytes): Another rewrite! Make it smarter about
+ not updating regs with the same value.
+ * monitor.c (printf_monitor readchar): Use stderr instead of
+ stdout to output debug info. Also cleanup readchar a little.
+ * (expect): Make sure that excessive responses are null
+ terminated.
+ * (monitor_open): Check for magic number in monitor_ops struct.
+ Allow multiple commands as init strings. Also, clear all
+ breakpoints.
+ * (monitor_resume monitor_wait): Send a command to dump all the
+ regs for those targets which don't do so when waking up after a
+ continue command.
+ * (monitor_wait): Handle excessive response output better.
+ * (monitor_write_memory): Use block fill, word, and long word
+ commands (if they exist) to write memory more efficiently.
+ * General cleanups to use flag bits instead of individual flag
+ words in monitor_ops struct.
+ * (monitor_command): Return output from command.
+ * (monitor_load_srec): Allocate buffer only once. Use alloca.
+ Wait for load response string instead of using a timeout to start
+ sending S-records. Fix bug where value of srec_frame shrinks. If
+ hashmark is set, print `-' for retransmissions. General cleanups.
+ * (monitor_make_srec): Get rid of S-record default type kludge.
+ * monitor.h: Use seperate struct for memory and register
+ read/write commands. Memory commands can come in byte, word,
+ long, and longlong forms.
+ * (monitor_ops): Change lots of fields. Generalize some stuff.
+ Put all flags into flags word. Allow init to be a list of commands.
+ Add command for clearing all breakpoints, block fill, dumping all
+ registers.
+ * remote-est.c: Rewrite to use new monitor conventions.
+ * config/m68k/est.mt (TDEPFILES): Add monitor.o.
+ * config/m68k/tm-est.h: Set NUM_REGS to 18.
+ * testsuite/gdb.base/break.exp: Lots of cleanups. Use gdb_test
+ more thoroughly.
+
+Thu Mar 23 23:20:00 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_add): Handle case where a shared library
+ referenced by a core file has sections without the SEC_ALLOC bit
+ set (eg stabs sections).
+
+Thu Mar 23 15:07:08 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * breakpoint.c (bpstat_do_actions): For each element in the bpstat
+ chain, do all the commands regardless of whether they run the
+ inferior.
+
+Wed Mar 22 19:17:06 1995 Doug Evans <dje@cygnus.com>
+
+ * mem-break.c (LITTLE_BREAKPOINT, BIG_BREAKPOINT): Define as
+ BREAKPOINT if mono-endian.
+ (break_insn): Deleted.
+ (big_break_insn, little_break_insn): Define.
+ (memory_insert_breakpoint): Handle bi-endian cpus.
+ (BREAKPOINT_LEN): Define.
+ (memory_remove_breakpoint): Use it.
+ (memory_breakpoint_size): Likewise.
+
+Tue Mar 21 17:03:17 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * sparc-stub.c: add nop after 'bg good_wim'.
+ * sparcl-stub.c: ditto.
+
+Tue Mar 21 13:34:12 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (handle_command): Don't print TARGET_SIGNAL_0,
+ TARGET_SIGNAL_UNKNOWN, or TARGET_SIGNAL_DEFAULT.
+
+Mon Mar 20 10:09:59 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppab-nat.c (store_inferior_registers): Sync with HPUX version.
+
+Mon Mar 20 07:34:48 1995 Stu Grossman (grossman@cygnus.com)
+
+ * hppah-nat.c (store_inferior_registers): Move check for
+ CANNOT_STORE_REGISTER to a better place. Fixes ptrace I/O errors
+ found by test suite during function calls, which attempts to write
+ unwritable registers.
+
+Sat Mar 18 02:02:24 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mdebugread.c (parse_symbol): If finishing a function without
+ known parameter type info, set that from parameter symbols.
+ Remove commented-out add_param_to_type support.
+
+Thu Mar 16 16:38:03 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (process_linenos): Make sure filename we pass to
+ start_subfile will cause deduce_language_from_filename to return
+ the correct thing. Reindent function to GNU standards.
+
+Thu Mar 16 15:54:00 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlm/gdbserve.c (handle_exception): #if out call to StopBell,
+ as it is not available on NetWare 3 or PIN.
+ * nlm/ppc.c (StopBell): Removed.
+
+Thu Mar 16 12:14:41 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (read_xcoff_symtab): When creating a dummy parameter
+ inferred from the traceback tags, give its type the name
+ "<non-float parameter>".
+
+ * stabsread.c (rs6000_builtin_type): Recognize types -31 to -34.
+
+Wed Mar 15 15:09:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * findvar.c (read_register_bytes write_register_bytes): Make
+ these routines much smarter about updating registers from the
+ target, only doing so when absolutely necessary. This really
+ speeds up register modification on some remote targets.
+
+ * monitor.c: More cleanups. Get rid of monitor_load_ascii_srec.
+ BFD makes this unnecessary. Lots of debugging speedups.
+ * (expect): NULL terminate return string.
+ * (monitor_open monitor_supply_register parse_register_dump
+ monitor_wait monitor_fetch_register): Switch to using GNU regexp
+ library to parse multi-register displays.
+ * (monitor_read_memory): Read multiple bytes (up to 16) at once.
+ * (monitor_create_inferior): Call clear_proceed_status to make run
+ command notice first breakpoint.
+ * (monitor_load): Clean up. Reset inferior_pid, set pc to start
+ address and reset symbol table stuff to make loads put things into
+ a fresh state.
+ * (monitor_load_srec): Lower sleep time to 1 second.
+
+ * monitor.h (struct monitor_ops): Add register_pattern and
+ supply_register to monitor_ops.
+
+ * rom68k-rom.c: Add new support for handling register dumps.
+ * config/m68k/tm-m68k.h: Define D0_REGNUM and A0_REGNUM for register
+ dump handling.
+
+Wed Mar 15 15:18:27 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * utils.c, defs.h (putchar_unfiltered, fputc_unfiltered): Make
+ argument be an int, not a char. Using a prototype followed by an
+ old-style function definition in a case where an argument is
+ widened is a GCC-ism not supported by the native AIX compiler.
+
+Wed Mar 15 12:22:35 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * nlmstub.def: Removed, this was moved to nlm/gdbserve.def
+ long ago.
+
+ * configure.in (alpha-*-netware*): Removed configuration.
+ * config/alpha/{alpha-nw.mt, gdbserve.mt, tm-alphanw.h}: Removed.
+ * nlm/{README-ALPHA-NETWARE, aio.h, alpha-io.S, alpha-regdef.h,
+ alpha.c, alpha.h, altdebug.h}: Removed.
+
+ * nlm/gdbserve.c (main): Add support for processing BOARD=
+ argument, deprecate NODE=.
+
+Wed Mar 15 10:58:26 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * c-exp.y (yylex): Make an empty character constant an error.
+
+Tue Mar 14 15:00:54 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_arg_coerce): Do possible value_coerce_array
+ before determining type argument to value_cast.
+
+Tue Mar 14 10:41:41 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-es.c: Replace ignore with 0.
+
+Tue Mar 14 05:52:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_repeat), eval.c (evaluate_subexp_standard):
+ If VALUE_REPEATED is already set, just error out.
+
+ * valops.c (value_cast, value_slice), parse.c (follow_types): Add
+ FIXME-type-allocation comments.
+
+ * gdbtypes.h (struct type): Fix comment about what units the
+ TYPE_LENGTH is in.
+
+Mon Mar 13 18:27:25 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * ch-valprint.c (annotate.h): Include.
+ * eval.c (evaluate_subexp_standard): Remove unused variable.
+ (calc_f77_array_dims): Add parens to expression.
+ * f-exp.y (yylex): Add parens to expression, remove unused label.
+ * f-lang.h (calc_f77_array_dims): Declare.
+ * f-valprint.c (f_val_print): Remove unused variables.
+
+Mon Mar 13 15:25:47 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * alpha-tdep.c (find_proc_desc): If pdr.framereg field is -1, don't
+ use the PDR, just examine prologues instead.
+
+
+Fri Mar 10 02:49:40 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ Fix problems with infinite recursion when printing a class
+ that contains a static instance of the class.
+ * cp-valprint.c (dont_print_vb_obstack): Renamed from
+ dont_print_obstack, made static.
+ (dont_print_statmem_obstack): New obstack, controls printing
+ of static member classes.
+ (_initialize_cp_valprint): Initialize it.
+ (cp_print_static_field): New function, handles printing of
+ static members.
+ (cp_print_value_fields): New parameter dont_print_statmem to
+ handle recursive printing of static member classes, use
+ cp_print_static_field to handle printing of static members.
+ * c-valprint.c (cp_print_value_fields): Update prototype and
+ call to include additional dont_print_statmem parameter.
+ * c-valprint.c, f-valprint.c (dont_print_obstack): Remove unused
+ extern declaration.
+
+ * alpha-tdep.c, findvar.c, infptrace.c: Include <string.h>.
+
+ * config/alpha/tm-alpha.h (FRAME_FIND_SAVED_REGS): Call
+ alpha_find_saved_regs if fi->saved_regs is still NULL.
+
+ * elfread.c (elf_symtab_read): Ensure that the filename field
+ of a minsym is nonempty. Ignore solib trampoline symbols from
+ the main symbol table, they might have a bogus value.
+
+ * procfs.c (set_proc_siginfo), config/alpha/alpha-osf2.mh:
+ Fix typos in comments.
+
+Thu Mar 9 17:19:47 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * mdebugread.c (parse_symbol, psymtab_to_symtab_1): Initialize
+ pdr.framereg field of MIPS_EFI_SYMBOL_NAME symbol to -1. That way
+ we know whether the PDR ever got set.
+ * mips-tdep.c (find_proc_desc): If pdr.framereg field is -1, don't
+ use the PDR, just examine prologues instead.
+
+Wed Mar 8 23:35:10 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somsolib.c (som_solib_section_offsets): Get offset of text
+ section right.
+
+Wed Mar 8 16:12:21 1995 Stu Grossman (grossman@cygnus.com)
+
+
+ * source.c (forward_search_command reverse_search_command): Set
+ convenience variable $_ to be the line # of the match.
+ * symtab.c (decode_line_1): Allow convenience variables to be
+ used in line specs (for breakpoints and such).
+
+Wed Mar 8 12:51:00 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.14.1.
+ * NEWS, README: Update for 4.14.
+ * i386v-nat.c (i386_insert_aligned_watchpoint): Fix declaration.
+ (i386_insert_nonaligned_watchpoint): Call aligned instead of
+ generic watchpoint insertion.
+
+Tue Mar 7 19:26:10 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_slice): Do COERCE_VARYING_ARRAY.
+
+Tue Mar 7 00:23:47 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c, array-rom.c, monitor.h, rom68k-rom.c: Move target_ops
+ into monitor.c.
+ * monitor.c (monitor_create_inferior): Allow run command to start
+ program.
+
+ * monitor.c (monitor_load): Set PC to start address when done
+ loading.
+
+ * array-rom.c, monitor.h, rom68k-rom.c: Clean up target_ops.
+ Remove ref to monitor_create_inferior.
+
+ * monitor.c: More general cleanups. Add prototypes, remove
+ unused routines. Fix bug with wrong number of args to error().
+
+ * main.c (main): Don't start up GUI when running under gdb mode
+ in emacs.
+
+ * Makefile.in: Add rules for monitor.o and rom68k-rom.o to make
+ Sun make (with VPATH) work...
+
+ * monitor.c, monitor.h, rom68k-rom.c: Serious cleanup to make IDP
+ (rom68k) target work right.
+ * array-rom.c, op50-rom.c, w89k-rom.c: Partial updates to new
+ monitor.c interface. More work needs to be done here.
+ * config/m68k/tm-monitor.h: Change DECR_PC_AFTER_BREAK to 0 to
+ match the IDP monitor. Also, set NUM_REGS to 18 cuz there's no
+ floating-point for this card.
+
+ * serial.h, ser-go32.c, ser-go32-para.c, ser-mac.c, ser-tcp.c,
+ ser-unix.c: Add SERIAL_SETSTOPBITS to set the number of stopbits
+ (needed for IDP board?!?!?).
+
+ * defs.h, utils.c, remote-hms.c, remote-pa.c, remote.c: Fix defs
+ and usage of fputc_unfiltered and putchar_unfiltered. Eliminate
+ putc_unfiltered (it's superfluous).
+
+ * command.h, command.c, top.c: Add var_enum command type. It's
+ like var_string but allows only only one of the specified strings.
+
+Mon Mar 6 15:03:59 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_cast): Don't use backslash newline--pre-ANSI
+ compilers (such as SunOS4 /bin/cc) don't generally support it
+ except in some contexts.
+
+Fri Mar 3 17:42:48 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (value_cast): Check for cast to array type *before*
+ we coerce array to pointer (in case arg2 is already array).
+
+ * valops.c (call_function_by_hand): Set using_gcc to 2 if using
+ gcc2. Needed for REG_STRUCT_HAS_ADDR to work on sparc.
+ Also check REG_STRUCT_HAS_ADDR for union, array and string types.
+
+ * valops.c (call_function_by_hand): Re-arrange code for pushing
+ paramaters on the stack so we can do better STACK_ALIGN.
+
+ * valops.c (call_function_by_hand): Call error if the number
+ of arguments is fewer than parameter types in function type.
+
+Fri Mar 3 17:13:05 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-tdep.c (sparc_extract_struct_value_address): Move
+ sparc64 support to here.
+ (sparc64_extract_struct_value_address): Deleted.
+ (dump_ccreg): Add a prototype so long long arg -> int.
+ * sparc/tm-sp64.h (USE_STRUCT_CONVENTION): Define.
+ (EXTRACT_STRUCT_VALUE_ADDRESS): Delete.
+
+Fri Mar 3 15:12:12 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_record_lines): New argument "offset". All
+ callers changed. Use it to handle dynamic address relocation.
+ (hpread_build_psymtabs): Adjust texthigh as we read each function
+ debug symbol. Fix computation of texthigh.
+ (hpread_read_subrange_type): Work around macro bugs in HP's
+ compilers.
+ (hpread_process_one_debug_symbol): Correctly map source lines.
+
+ * somread.c (check_strange_names): Filter names emitted by the HP
+ compiler when generating PIC code.
+
+ * valops.c (value_struct_elt_for_reference): Work around macro
+ bugs in HP's compilers.
+ * c-exp.y (block): Likewise.
+
+Fri Mar 3 12:27:28 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * rs6000-tdep.c (push_dummy_frame): Fix order of arguments to
+ store_address.
+
+ * utils.c [_AIX]: Include stddef.h instead of #defining size_t.
+
+Fri Mar 3 12:33:24 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * rs6000-tdep.c (skip_prologue): Skip multiple stores of the saved
+ registers that GCC emits on the PowerPC by default in addition to
+ the store multiple instruction used on the Power series.
+
+Fri Mar 3 00:54:58 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-tdep.c (decode_asi): New function.
+ (sparc_print_register_hook): Pretty print more v9 registers.
+ * sparc/tm-sp64.h (REGISTER_NAMES): Fix some typos.
+
+Thu Mar 2 22:20:22 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * dwarfread.c (struct dieinfo): Use CORE_ADDR for at_{low,high}_pc.
+ (target_to_host): Change result type to CORE_ADDR.
+
+Thu Mar 2 15:13:04 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * rs6000-tdep.c: Fix byte-swapping sins.
+
+Thu Mar 2 16:48:45 1995 Michael Meissner <meissner@cygnus.com>
+
+ * rs6000-tdep.c (branch_dest): Minor code cleanup, don't share
+ code between branch unconditional and branch conditional cases.
+
+Wed Mar 1 09:41:26 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ Various changes for sparc64.
+ * sparc-tdep.c (NUM_SPARC_FPREGS): Define.
+ (SPARC_INTREG_SIZE): Define.
+ (*): Use SPARC_INTREG_SIZE instead of REGISTER_RAW_SIZE (intreg)
+ where appropriate.
+ (enum branch_type): New value `done_retry'.
+ (isbranch): Renamed from isannulled. All callers changed.
+ Support new sparc64 branch insns.
+ (single_step): Handle done_retry.
+ (sparc_extract_struct_value_address): Don't assume 4 byte regs.
+ (get_saved_register): Likewise.
+ (sparc_push_dummy_frame): Likewise.
+ (sparc_frame_find_saved_regs): Likewise.
+ (sparc_pop_frame): Likewise. Don't refer to FPS_REGNUM, CPS_REGNUM,
+ or PS_REGNUM if not sparc64. sparc64 has 64 fp regs.
+ (sparc64_extract_struct_value_address): New function.
+ (dump_ccreg, sparc_print_register_hook): Likewise.
+ * sp64-tdep.c: Deleted.
+ * sparc/tm-sp64.h (GDB_TARGET_IS_SPARC64): Define.
+ (NUM_REGS): Reduce by 2, cle/tle are in the pstate reg.
+ (CC_HAS_LONG_LONG): Define.
+ (REGISTER_NAMES): Delete cle/tle and reorganize.
+ (PS_REGNUM, FPS_REGNUM, CPS_REGNUM): Delete, they're ifdef'd out of
+ sparc-tdep.c now.
+ (REGISTER_BYTES): Update.
+ (REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): Delete.
+ (EXTRACT_RETURN_VALUE): Delete. Use definition in tm-sparc.h.
+ (NO_SINGLE_STEP): Likewise.
+ * sparc/tm-sparc.h (EXTRACT_VALUE_RETURN): Don't assume 4 byte regs.
+ * sparc/sp64.mt: Move simulator support ...
+ * sparc/sp64sim.mt: ... to here.
+
+Wed Mar 1 13:14:42 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-vx960.c: new file for target specific register packaging.
+ * remote-vx68.c: ditto.
+ * config/i960/vxworks960.mt: add remote-vx960.o.
+ * config/m68k/vxworks68.mt: add remote-vx68.o.
+
+Wed Mar 1 13:42:49 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * remote.c (remote_wait): Make calls to strtol be type correct by
+ passing the address of a char * pointer instead of an unsigned
+ char *.
+
+ * rs6000-tdep.c (push_dummy_frame): Cast sp to char * when calling
+ write_memory to make things type correct.
+
+Wed Mar 1 12:17:31 1995 Michael Meissner <meissner@cygnus.com>
+
+ * ch-exp.y, c-exp.y, f-exp.y, m2-exp.y (yy defines): Support the
+ standard Linux yacc by adding more names to be redefined with a
+ prefix.
+
+Tue Feb 28 22:55:47 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-tdep.c (pa_print_registers), monitor.c: Use
+ extract_unsigned_integer and friends, not SWAP_TARGET_AND_HOST.
+ * defs.h, findvar.c: Move SWAP_TARGET_AND_HOST back to findvar.c.
+ Rename it to SWAP_FLOATING to make it clear it is no longer for
+ integers.
+
+Tue Feb 28 14:38:39 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * defs.h (SWAP_TARGET_AND_HOST): check endianess at runtime not
+ compile time.
+
+
+ * vx-share/ptrace.h: merge in WRS new ptrace requests.
+
+ * defs.h: fix a syntax error.
+
+ * a29k-tdep.c (get_longjmp_target): add this function, from WRS.
+ * remote-vx.c: move read_register and write_register out to
+ target specific files.
+ * remote-vx29k.c (get_fp_contnets): add this function, from WRS.
+
+ * defs.h: define SWAP_TARGET_AND_HOST macro.
+ * findvar.c, monitor.c, hppa-tdep.c: remove definition of
+ SWAP_TARGET_AND_HOST.
+
+Tue Feb 28 08:31:40 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * alpha-tdep.c (find_proc_desc): Only attempt to set
+ PROC_LOCALOFF (found_heuristic) if found_heuristic is non-NULL.
+
+Mon Feb 27 11:56:32 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * monitor.c: General gcc -Wall lint cleanup and reformat.
+ (monitor_command): If no args, send an empty command.
+
+Thu Feb 23 21:07:25 1995 Stu Grossman (grossman@cygnus.com)
+
+ * monitor.c (monitor_load_ascii_srec): Add a one second sleep
+ after send LOAD_CMD to prevent loss of first S-record.
+
+Tue Feb 21 20:48:42 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * valops.c (call_function_by_hand): Set using_gcc to 2 if gcc-2.
+ Call error if too few arguments.
+ If REG_STRUCT_HAS_ADDR (structs passed by invisible reference),
+ copy and convert to reference *before* we calculate alignment.
+ Also, make sure structs allocated for return values and invisible
+ reference don't violate STACK_ALIGN.
+
+Tue Feb 21 23:29:59 1995 Per Bothner <bothner@rtl.cygnus.com>
+
+ * ch-exp.y (expression_conversion): Recognize 'ARRAY () TYPE (EXPR)'
+ (same as C's '(TYPE[])EXPR')
+
+Tue Feb 21 11:47:26 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (print_gdb_version): Update the year.
+
+Sun Feb 19 14:31:57 1995 Jim Kingdon <kingdon@rtl.cygnus.com>
+
+ * Makefile.in (CC_FOR_TARGET, CXX_FOR_TARGET): Look for newlib in
+ `..' not in `../..'.
+
+Sun Feb 19 11:05:28 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * procfs.c (unconditionally_kill_inferior): Don't issue a PIOCKILL
+ in addition to a PIOCSSIG to kill the inferior.
+
+Thu Feb 16 15:06:12 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * parse.c (follow_types): Given (TYPE[]) (i.e. with no length),
+ create a 0-length array type, and set BOUND_CANNOT_BE_DETERMINED.
+ * valops.c (value_cast): If a cast like (TYPE[])VALUE (i.e. array
+ of unknown length) use sizeof(VALUE)/sizeof(TYPE) as the length.
+ * c-typeprint.c (c_type_print_varspec_suffix): If array length
+ is 0, print it, but not if upper_bound is BOUND_CANNOT_BE_DETERMINED.
+
+Thu Feb 16 16:06:50 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * dcache.c (insque, remque): Rewrite Linux support.
+
+Wed Feb 15 12:33:20 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * config/powerpc/tm-ppc-eabi.h (TEXT_SEGMENT_BASE): Define as 1.
+
+ * dcache.c (insque, remque): If compiling in standard C on Linux,
+ protect insque and remque with macros to cast the pointer
+ arguments to the proper type.
+
+Tue Feb 14 17:16:41 1995 Stu Grossman (grossman@cygnus.com)
+
+ * annotate.c, breakpoint.c, defs.h, top.c: Replace
+ enable/disable_breakpoint_hook with modify_breakpoint_hook.
+
+Tue Feb 14 16:58:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * expression.h: Move declaration of evaluate_subexp_with_coercion
+ from here...
+ * value.h: ...to here.
+ * expression.h: Don't include value.h
+
+Tue Feb 14 11:46:07 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * expression.h: Move include of value.h until after declaration of
+ enum exp_opcode.
+
+Sun Feb 12 13:47:30 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-e7000.c: Comprehensive cleanup; removal of dead code,
+ simplify code, declare things, format to standards.
+ (inferior.h, value.h, command.h, remote-utils.h): Include.
+ (e7000_login): Rename to e7000_login_command.
+ (e7000_ftp): Rename to e7000_ftp_command.
+ (e7000_drain): Rename to e7000_drain_command.
+
+ * irix5-nat.c (string.h): Include near beginning of file.
+
+Sun Feb 12 12:36:38 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * valops.c (value_arg_coerce): Use VALUE_TYPE not SYMBOL_TYPE on
+ arg, it is a value not a symbol.
+
+ gcc -Wall lint:
+ * eval.c: Move declaration of evaluate_subexp_with_coercion from here..
+ * expression.h: ..to here.
+ * expression.h: Include value.h.
+ * ch-lang.c (evaluate_subexp_chill): Add default case in switch.
+
+Sun Feb 12 11:03:47 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * language.h (struct language_defn): New field evaluate_exp.
+ * c-lang.c (c_language_defn, cplus_language_defn, asm_langauge_defn),
+ f-lang.c (f_language_defn), language.c (unknown_language_defn,
+ auto_language_defn, local_language_defn), m2-lang.c (m2_language_defn):
+ Set evaluate_exp to evaluate_subexp_standard.
+ * ch-lang.c (evaluate_subexp_chill): New function. Chill-specific
+ support for MULTI_SUBSCRIPT.
+ (chill_language_defn): Set evaluate_exp to evaluate_subexp_chill.
+ * eval.c (enum noside): Move from here ....
+ * expression.h (enum noside): ... to here.
+ (evaluate_subexp_standard): New prototype.
+ * eval.c (evaluate_subexp): Renamed to evaluate_subexp_standard.
+ Removed lo-longer-needed test for chill_varying_type.
+ (evaluate_subexp): New. Calls exp->language_defn->evaluate_exp.
+
+ * ch-exp.y (maybe_expression_list): New non-terminal.
+ (primitive_value): Allow empty parameter list.
+
+Sun Feb 12 10:02:16 1995 Per Bothner <bothner@cygnus.com>
+
+ * buildsym.c (finish_block): If finishing a function without known
+ parameter type info, set that from parameter symbols.
+ * c-typeprint.c (c_type_print_varspec_suffix): For TYPE_CODE_FUNC,
+ print parameter types, if available.
+ * ch-typeprint.c (chill_type_print_base): Likewise.
+
+ * gdbtypes.h (struct type): Remove function type field.
+ (TYPE_FUNCTION_TYPE): Remove macro. We can't as simply re-use
+ function types now that we're also storing parameter types.
+ And the payoff is much less.
+ * gdbtypes.c (make_function_type): Don't use/set TYPE_FUNCTION_TYPE.
+ (recursive_dump_type): Don't print TYPE_FUNCTION_TYPE.
+ * dwarfread.c (read_subroutine_type): Don't set TYPE_FUNCTION_TYPE.
+
+ * valops.c (value_arg_coerce): Now takes param_type argument.
+ (call_function_by_hand): Convert arguments with value_arg_coerce
+ early, and overwrite original args with converted args.
+ No longer need multiple calls to value_arg_coerce.
+ (value_arg_push): Removed.
+ * hppa-tdep.c (hppa_push_arguments): No longer call value_arg_coerce.
+ * mips-tdep.c (mips_push_arguments): Likewise.
+ * alpha-tdep.c (alpha_push_arguments): Likewise.
+ * rs6000-tdep.c (push_arguments, ran_out_of_registers_for_arguments):
+ Likewise.
+ * value.h (value_arg_coerce): Remove declaration. (It's now static.)
+
+ * valops.c (value_cast): Do COERCE_VARYING_ARRAY after COERCE_REF.
+
+ * symtab.c (add_param_to_type): Remove (commented-out) function,
+ since that functionality has been re-written.
+ * coffread.c: Remove commented-out add_param_to_type support.
+ * mdebugread.c (parse_symbol): Likewise.
+ * stabsread.c (define_symbol): Likewise.
+
+Sun Feb 12 09:03:47 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * buildsym.c (start_subfile): Set language for f2c like for cfront.
+
+Thu Feb 9 20:20:11 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * op50n-rom.c: Add the control registers.
+
+Thu Feb 9 15:46:39 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (CLIBS): Add $(LIBIBERTY) before, in addition to
+ after, any host/target/native libraries.
+ * dcache.c (insque, remque): Remove declarations.
+ * gdbtypes.h (type_code): Remove trailing comma.
+
+ From Peter Schauer:
+ * xcoffread.c (read_xcoff_symtab) [C_HIDEXT]: Move #ifdef
+ STATIC_NODEBUG_VARS inside case.
+
+Thu Feb 9 07:43:41 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * config/sparc/tm-sun4sol2.h: Define STATIC_TRANSFORM_NAME.
+ * partial-stab.h: Call it.
+ * stabsread.c (define_symbol) [STATIC_TRANSFORM_NAME]: Call
+ STATIC_TRANSFORM_NAME to get the name and use minimal symbols to
+ get the address.
+ * sparc-tdep.c (solaris_static_transform_name): New function.
+
+Thu Feb 9 12:09:09 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * somread.c (som_symtab_read): Handle dynamic relocation for both
+ text and data symbols.
+ (som_symfile_offsets): If objfile is a shared library, then get
+ text and data offsets from the shared library structures.
+ * somsolib.c (som_solib_add): Copy the bfd pointer from the
+ objfile rather than reopening the file again.
+ (som_solib_section_offsets): New function.
+ * somsolib.h (som_solib_section_offsets): Declare.
+
+Wed Feb 8 20:32:18 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * config/sparc/tm-sun4sol2.h, dbxread.c: Rename
+ N_SO_ADDRESS_MAYBE_MISSING to SOFUN_ADDRESS_MAYBE_MISSING.
+ * symtab.h (minimal_symbol) [SOFUN_ADDRESS_MAYBE_MISSING]: Add
+ filename field.
+ * elfread.c (record_minimal_symbol_and_info),
+ minsyms.c, symtab.h (prim_record_minimal_symbol_and_info): Return
+ newly created symbol.
+ * elfread.c (elf_symtab_read) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Set filename field of minimal symbol.
+ * symmisc.c (dump_msymbols) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Print filename field.
+ * minsyms.c, symtab.h (lookup_minimal_symbol): New arg sfile.
+ * symm-tdep.c, somsolib.c, hppa-tdep.c, c-exp.y, f-exp.y,
+ m2-exp.y, nindy-tdep.c, m3-nat.c, irix5-nat.c, hpread.c,
+ os9kread.c, breakpoint.c, alpha-tdep.c, valops.c, symtab.c,
+ printcmd.c, dbxread.c: Change callers to pass NULL for sfile.
+ * dbxread.c (process_one_symbol) [SOFUN_ADDRESS_MAYBE_MISSING]:
+ Find address of function from minimal symbols.
+ * partial-stab.h, case 'f', 'F': Call find_stab_function_addr
+ instead of getting pst->textlow from the stab.
+ * minsyms.c (find_stab_function_addr): New function.
+
+Wed Feb 8 19:19:56 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * monitor.c: Fix so all the output shows up in the GUI command
+ window.
+
+Mon Feb 6 18:50:59 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * i386-tdep.c (_initialize_i386_tdep): Put void decl on separate
+ line, so init.c generation works correctly.
+
+Mon Feb 6 14:44:36 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * config/mips/idt.mt: Add support for the lsi33k target.
+ * config/sparc/sun4sol2.mh: Add support for ser-tcp.
+ * array-rom.c: Finish the rest of the support commands needed by
+ GDB.
+ * mips-tdep.c: Add LSI33k register names and processor type.
+
+Sat Feb 4 13:29:52 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * config/m68k/est.mt (TDEPFILES): Remove m68k-pinsn.o.
+
+Fri Feb 3 16:47:31 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * ser-go32-para.c (dos_read): fix syntax errors.
+
+Fri Feb 3 11:19:20 1995 Stu Grossman (grossman@cygnus.com)
+
+ * core.c (dis_asm_read_memory), defs.h, top.c: Get rid of
+ dis_asm_read_memory_hook. We can now call the disassemblers
+ directly and have no need for this hook anymore.
+ * defs.h, printcmd.c: Make print_insn be static.
+
+ * ser-go32.c (dos_comisr): Make this 8 bit clean.
+ * (dos_open dos_close): Allow multiple opens to the same device.
+ Use a ref count to prevent unwanted deallocations.
+ * sparcl-tdep.c: Put #ifdefs around all socket stuff to make GO32
+ happy.
+ * (sparclite_ops): Switch to download_stratum.
+ * target.h (enum strata): Move download_stratum before
+ process_stratum so that executable targets get pushed on top of
+ download targets.
+
+Thu Feb 2 19:02:45 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * array-rom.c: Remove the non GDB remote protocol config stuff.
+
+ * monitor.c: All reading/writing functions for memory and
+ registers work.
+
+Thu Feb 2 16:11:04 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * ser-go32-para.c: new file for go32 parallel port communication.
+
+Thu Feb 2 13:58:40 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (VERSION): Bump to 4.13.2.
+
+Thu Feb 2 07:27:56 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ Fix compiler warnings:
+ * remote-e7000.c (printf_e7000debug): Rename to puts_e7000debug
+ and have the caller do the sprintf. Saves us from varargs hell.
+ (normal): Define before use.
+ * remote-e7000.c: Reindent a few things.
+
+Wed Feb 1 21:16:42 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * f-typeprint.c (f_type_print_varspec_suffix): Print array index
+ ranges in reverse order.
+ * f-valprint.c (f77_create_arrayprint_offset_tbl): Fix calculation.
+
+ * eval.c (evaluate_subscript): Don't call value_subscript, since
+ it adjusts for lower bound and enforces ranges.
+
+ * expression.h (exp_code): Remove MULTI_F77_SUBSCRIPT, OP_F77_SUBSTR.
+ * eval.c, parse.c: Removed uses of removed opcodes.
+ * eval.c (evaluate_subexp): Clean up handling of
+ OP_UNDETERMINED_ARGLIST (no backtracking, more general).
+
+ * f-valprint.c (f_val_print): Print TYPE_CODE_STRING using
+ LA_PRINT_STRING, and not val_print_string (which reads from inferior).
+
+ * ch-lang.c (chill_is_varying_struct), ch-lang.h: Remve function
+ duplicate function made redundant by chill_varying_type.
+
+ Re-write of f77 string and complex number support:
+
+ * language.h (struct language_defn): New fields string_lower_bound
+ and string_char_type.
+ * c-lang.c (c_language_defn, cplus_language_defn, asm_language_defn),
+ language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn), m2-lang.c (m2_language_defn), f-lang.c
+ (f_language_defn), ch-lang.c (chill_language_defn): Set new fields.
+ * gdbtypes.c (create_string_type): Use new string_char_type field.
+ * valops.c (value_string): Use new string_lower_bound field.
+
+ * defs.h (TARGET_COMPLEX_BIT, TARGET_DOUBLE_COMPLEX_BIT): Removed.
+ * f-lang.c (f_create_fundamental_type, _initialize_f_language),
+ m2-lang.c (m2_create_fundamental_type),
+ gdbtypes.c (_initialize_gdbtypes): Set TYPE_TARGET_TYPE of complex
+ types. Set their TYPE_CODEs to TYPE_CODE_COMPLEX.
+ * mdebugread.c (mdebug_type_complex, mdebug_type_double_complex):
+ Removed. Use builtin_type_complex and builtin_type_double_complex.
+
+ * gdbtypes.h (enum type_code): Removed TYPE_CODE_LITERAL_STRING
+ and TYPE_CODE_LITERAL_COMPLEX.
+ * c-typeprint.c, f-typeprint.c, f-valprint.c, eval.c: Removed uses of
+ TYPE_CODE_LITERAL_STRING and TYPE_CODE_LITERAL_COMPLEX.
+ * gdbtypes.c, gdbtypes.h (f77_create_literal_complex_type,
+ f77_create_literal_string_type): Removed.
+ * value.h (VALUE_LITERAL_DATA, VALUE_SUBSTRING_MEMADDR,
+ VALUE_SUBSTRING_MYADDR): Removed.
+
+ * expression.h (enum exp_opcode): Rename OP_F77_LITERAL_COMPLEX to
+ OP_COMPLEX.
+ * parse.c: Update accordingly.
+
+ * f-valprint.c (f77_print_cmplx): Removed.
+ (f_val_print case TYPE_CODE_COMPLEX): Re-write to use print_floating.
+
+ * f-exp.y (STRING_LITERAL): Use OP_STRING instead of OP_ARRAY.
+ * eval.c (evaluate_subexp): For case OP_ARRAY, don't call
+ f77_value_literal_string.
+ * valops.c, value.h (f77_value_literal_string, f77_value_substring,
+ f77_assign_from_literal_string, f77_assign_from_literal_complex):
+ Removed.
+ (value_assign): No longer need to handle literal types.
+ * valops.c (f77_value_literal_complex), value.h: Re-written and
+ renamed to value_literal_complex. Last arg is now a (complex) type.
+ * valops.c (f77_cast_into_complex): Re-written and renamed to
+ cast_into_complex.
+ * eval.c (evaluate_subexp): Update accordingly.
+
+ * ch-valprint.c (chill_val_print): On TYPE_CODE_STRING, don't
+ print address for non-'s'-formats.
+ * ch-typeprint.c, ch-valprint.c: Use chill_varying_type instead
+ of chill_is_varying_struct.
+
+Wed Feb 1 13:27:33 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ gcc -Wall lint.
+ * alpha-tdep.c (alpha_in_lenient_prologue): Comment out.
+ (after_prologue): Remove unused local b.
+ * procfs.c (thread.h): Include.
+ (pr_flag_table, pr_why_table, faults_table, siginfo_table): Use
+ nested braces in initializer.
+ * top.c (initialize_targets, initialize_utils): Declare.
+ (locate_arg, insert_args): Add parens around tested assignments.
+ * remote-utils.c (sr_scan_args): Remove decl of strtol.
+ * remote.c (thread.h): Include.
+ (remote_wait): Remove unused local p2.
+ * sparc-tdep.c (fill_gregset, fill_fpregset): Remove decls of
+ registers array.
+
+ defs.h (stdlib.h): Include.
+ (exit, perror, atoi, qsort, memcpy, memcmp): Don't declare.
+ (fclose, atof, malloc, realloc, free, strchr, strrchr, strstr,
+ strtok, strerror): Don't specify parameter types in declaration.
+
+Wed Feb 1 12:23:57 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y (value_string_element, string_primitive_value,
+ start_element, left_element, right_element, slice_size,
+ lower_element, upper_element, first_element): Removed.
+ (value_string_slice, value_array_slice): Replaced by ...
+ (slice): New non-terminal, with working slice support.
+ (primitive_value_lparen, rparen): New non-terminals.
+ (maybe_tuple_elements): New non-terminal, to allow empty tuples.
+ (idtokentab): Added "up".
+
+ * value.h (COERCE_VARYING_ARRAY): New macro.
+ * valarith.c (value_subscript): Use it.
+ * valops.c (value_cast): Likewise. Also, do nothing if already
+ correct type, and allow converting from/to range to/from scalar.
+
+ * valops.c, value.h (varying_to_slice, value_slice): New functions.
+ * eval.c (OP_ARRAY): Add cast for array element.
+ * expression.h (TERNOP_SLICE, TERNOP_SLICE_COUNT): New exp_opcodes.
+ * valops.c (chill_varying_type): Moved function frp, here ...
+ * gdbtypes.c (chill_varying_type), gdbtypes.h: ... to here.
+ * parse.c (length_of_subexp, prefixify_subexp): Add support
+ for TERNOP_SLICE, TERNOP_SLICE_COUNT.
+ * expprint.c (print_subexp, dump_expression): Likewise.
+ * eval.c (evaluate_subexp): Likewise.
+
+ * eval.c (evaluate_subexp case MULTI_SUBSCRIPT): Don't call
+ value_x_binop on a Chill varying string.
+
+Tue Jan 31 13:51:53 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config/m68k/monitor.mt,
+ config/pa/{hppabsd.mt,hppahpux.mt,hppaosf.mt,hppapro.mt}: Put
+ depfiles in TDEPFILES not REMOTE_O.
+
+Tue Jan 31 11:14:44 1995 Steve Chamberlain <sac@splat>
+
+ From nigel@algor.co.uk.
+ * ser-go32.c (dos_close): Don't crash if scb null.
+ (dos_sendbreak): New function.
+ (dos_ops): Point to dos_sendbreak.
+ (dos_info): Calculate COM number correctly.
+
+Tue Jan 31 09:40:11 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * xcoffread.c (process_xcoff_symbol): Use new variables
+ func_symbol_type and var_symbol_type as type of functions and
+ variables which don't have any stabs associated with them.
+ Reindent most of function.
+ (_initialize_xcoffread): Initialize *_symbol_type.
+
+ * xcoffread.c (read_xcoff_symtab): Reindent most of function.
+ Put C_HIDEXT symbols in the minimal symbols, rather than ignoring
+ them (this part commented out as I didn't quite get it to work).
+ (cs_to_section, find_targ_sec): New functions, to support above code.
+ * xcoffread.c (RECORD_MINIMAL_SYMBOL): Only skip '.' if it is
+ actually present.
+
+Mon Jan 30 17:34:24 1995 Stu Grossman (grossman@cygnus.com)
+ * sparcl-tdep.c: Add `sparclite' target for doing serial and udp
+ downloads to SPARClite demo boards.
+
+Sun Jan 29 09:43:22 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.c, remote-pa.c: Remove #if 0'd icache code. It has had
+ no hope of working as is for a long time (in particular, shebs' 27
+ Jan 95 change confuses the issue further--target_read_memory and
+ xfer_core_file do *not* do the same thing in this context).
+ Revise comment.
+
+Sat Jan 28 13:40:46 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * elfread.c (elf_symtab_read): Do not test BSF_GLOBAL for
+ procedure linkage table symbols, it is no longer set due to the
+ Jan 6 BFD change in bfd/elfcode.h.
+
+Fri Jan 27 17:08:06 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * top.c (use_windows): Clarify comments.
+
+ * convex-tdep.c (xfer_core_file): Comment out.
+ * config/convex/tm-convex.h (XFER_CORE_FILE): Remove.
+ * remote.c, remote-pa.c (remote_fetch_word): Change xfer_core_file
+ references to target_read_memory.
+ * gdbcore.h (xfer_core_file, core_open, core_detach): Remove
+ declarations.
+ * corelow.c (core_open, core_detach): Make static.
+
+ * arm-tdep.c: Make it compile.
+ (exec_file_command, xfer_core_file): Comment out.
+ (arm_print_insn): Remove, now in libopcodes.
+ (skip_prologue): Comment out most of body.
+ (arm_frame_find_saved_regs): Move here from tm-arm.h.
+ (_initialize_arm_tdep): Set tm_print_insn.
+ * config/arm/tm-arm.h: Remove old refs to first_object_file_end.
+ (XFER_CORE_FILE): Remove.
+ (FRAME_FIND_SAVED_REGS): Call arm_frame_find_saved_regs.
+
+Fri Jan 27 08:48:28 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (CHILL_LIB): Define as in testsuite/Makefile.in.
+
+Thu Jan 26 18:24:41 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * symtab.c (find_pc_line): When subtracting one to get a line
+ number, make sure not to end up with zero.
+
+ * remote-vx.c: Revert all of Kung's changes of 16 Jan. The
+ problems with those changes were (a) the file didn't compile, (b)
+ they changed memset to bzero--memset is correct, (c) they took out
+ code to deal with boards lacking floating point, (d) who knows
+ what I didn't discover in a quick read.
+
+Thu Jan 26 17:32:54 1995 Stu Grossman (grossman@cygnus.com)
+
+ * sparcl-tdep.c: Clean up formatting and indentation.
+
+Thu Jan 26 10:49:59 1995 Steve Chamberlain <sac@splat>
+
+ * remote-hms.c (hms_ops): Change ref of hr_load_image
+ to gr_load_image.
+ (dcache_flush, dcache_hit, dcache_value, dcache_fetch,
+ dcache_poke, dcache_init): Deleted.
+ (hms_open, hms_resume, hms_fetch_word, hms_store_word):
+ Use dcache routines provided by remote-util.h
+
+Thu Jan 26 12:08:31 1995 Michael Meissner <meissner@cygnus.com>
+
+ * configure.in: Add support for powerpc-*-eabi.
+
+ * powerpc/tm-ppc-eabi.h, powerpc/pcc-eabi.mt: New files for
+ PowerPC support.
+
+Wed Jan 25 18:13:14 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * language.h (struct language_defn): New field c_style_arrays.
+ * language.c (unknown_language_defn, auto_language_defn,
+ local_language_defn), c-lang.c (c_language_defn, cplus_language_defn,
+ asm_language_defn): Set c_style_arrays to true.
+ * m2-lang.c (m2_language_defn), ch-lang.c (chill_language_defn),
+ f-lang.c (f_language_defn): Set c_style_arrays to false.
+ * valops.c (value_string): If c_style_array is not set,
+ allocate string in gdb (not inferior) using allocate_value.
+
+ * value.h (COERCE_ARRAY), valops.c (value_addr, value_arg_coerce):
+ Only call value_coerce_array if current_language->c_style_arrays.
+ * values.c: Add #include "language.h". (Needed for COERCE_ARRAY.)
+
+ * valops.c (chill_varying_type): New predicate.
+ * valops.c (value_cast): Support assigning a fixed string or array
+ to a variable string/array structure.
+
+ * valarith.c (value_subscripted_rvalue): Extra parameter lowerbound.
+ Check index>=lowerbound, and then add lowerbound to index here,
+ instead of in caller. Generalize to arbitrary lval_types.
+ (value_subscript): Use enhanced value_subscripted_rvalue if
+ c_style_arrays is false (and index is in range).
+
+
+Wed Jan 25 18:13:14 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * eval.c (evaluate_subexp case OP_ARRAY): Fix calls to memset:
+ TYPE_LENGTH is length in bytes, not bits.
+
+Wed Jan 25 08:19:35 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * infrun.c (proceed): Flush stdout before resuming inferior.
+ * infcmd.c (step_1), annotate.c (annotate_starting):
+ Don't bother to flush here.
+
+Wed Jan 25 01:11:21 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hpread.c (hpread_process_one_debug_symbol): Fix lines garbled
+ by an ill-advised global search and replace.
+
+Tue Jan 24 12:10:28 1995 Stu Grossman (grossman@cygnus.com)
+
+ * gdbtk.tcl (create_registers_window): Work around a radiobutton
+ widget bug to make Options|Natural button work.
+
+ * gdbtk.c (gdb_disassemble): Fix problem with source+assembly and
+ g++ caused by out-of-order pc's.
+ * gdbtk.tcl (files_command): Remove duplicate file names. Also,
+ add scrollbar.
+
+Mon Jan 23 17:21:09 1995 Stu Grossman (grossman@cygnus.com)
+
+ * gdbtk.tcl: Take .gdbtkinit if it exists. Makes gdbtk match the
+ doc!
+
+Mon Jan 23 13:11:46 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ Add support for Chill bitstring literals (e.h. H'FF00').
+ * ch-exp.y (match_bitstring_literal): Fix for proper endianness.
+ * expprint.c (print_subexp): Don't call error on OP_BITSTRING,
+ just print B'<unimlemented>'.
+ * gdbtypes.c (create_set_type): Fix bug in length calculation.
+ * valops.c, value.h (value_bitstring): New function.
+ * eval.c (evaluate_subexp): Implement support for OP_BITSTRING.
+
+ * ch-typeprint.c (chill_type_print_base): For TYPE_CODE_FUNC,
+ check that return type is non-void, and print in proper Chill syntax.
+
+Mon Jan 23 12:20:34 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * Makefile.in: Remove references to remote-mon.c.
+ * remote-mon.c: remove. Replaced by rom68k-rom.c.
+ * rom68k-rom.c: Support for Rom68k monitor.
+
+Mon Jan 23 10:50:57 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (CHILL_FOR_TARGET): Update -L argument to point to
+ gcc/ch/runtime not chillrt, since that is where the chill runtime
+ lives now.
+
+Mon Jan 23 00:06:57 1995 Steve Chamberlain <sac@splat>
+
+ * remote-hms.c (hms_load): Delete.
+ (target_ops): Use hr_load_image.
+
+ * remote-e7000.c, remote-z8k.c, remote-nindy.c (target_ops):
+ Define memory_insert/remove_breakpoint.
+ * xm-go32.h: Remove redundant SIGs.
+
+Thu Jan 19 20:26:58 1995 Steve Chamberlain <sac@splat>
+
+ * ser-go32.c: Rewritten by nigel@algor.co.uk.
+
+Fri Jan 20 15:23:55 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * expression.h (OP_LABELED): New operator, for Chill
+ labeled structre tuples.
+ * ch-exp.y (tuple_element, named_record_element, tuple_elements):
+ New non-terminals, to handle labeled structure tuples.
+ (tuple): Re-define using tuple_elements.
+ * eval.c (evaluate_labeled_field_init): New function, to handle
+ initialization of structure fields, possibly using OP_LABELED.
+ (evaluate_subexp): Use it.
+ * expprint.c (print_subexp case): For OP_ARRAY, use Chill syntax
+ for Chill. Handled OP_LABELED.
+ * parse.c (length_of_subexp, prefixify_subexp): Handle OP_LABELED.
+
+ * eval.c (evaluate_subexp): Handle Chill Powerset tuples.
+ * valarith.c (value_bit_index): Just treat bitstring as represented
+ by an array of bytes. Alignment is handled by compiler.
+
+Wed Jan 18 19:00:29 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * h8300-tdep.c (gdb_print_insn_h8300): Fix typo (&info -> info).
+ * sh-tdep.c (gdb_print_insn_sh): Ditto.
+
+Wed Jan 18 11:25:43 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * remote-os9k.c (rombug_open): Fix a bug in exception handling
+ command.
+ * remote-os9k.c (rombug_write_inferior_memory): reset buffer after
+ write.
+
+Tue Jan 17 09:48:38 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * parse.c (_initialize_parse): Improve wording of names of
+ msym_*_symbol_type.
+
+Tue Jan 17 14:00:58 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * config/mips/tm-mips.h (enum mips_fpu_type): New enum.
+ (mips_fpu): Change type to enum mips_fpu_type.
+ (FIX_CALL_DUMMY): Handle mips_fpu == MIPS_FPU_SINGLE.
+ * mips-tdep.c (mips_fpu): Change type to enum mips_fpu_type.
+ Don't initialize.
+ (mips_fpu_string): New static variable.
+ (mips_push_dummy_frame): Handle mips_fpu == MIPS_FPU_SINGLE.
+ (mips_pop_frame): Likewise.
+ (mips_extract_return_value): Likewise.
+ (mips_store_return_value): Likewise.
+ (mips_set_fpu_command): New static function.
+ (mips_show_fpu_command): New static function.
+ (_initialize_mips_tdep): Change handling of set/show mipsfpu.
+
+Tue Jan 17 09:48:38 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * a29k-tdep.c (gdb_print_insn_a29k): Fix typo (&info -> info).
+
+ * parse.c (write_exp_msymbol): Use new variables
+ msym_*_symbol_type as type of msymbol expression.
+ (_initialize_parse): Initialize them.
+
+Mon Jan 16 18:11:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ General cleanup and simplication of disassembler interface.
+ * a29k-pinsn.c, arm-pinsn.c, convex-pinsn.c, gould-pinsn.c,
+ hppa-pinsn.c, i386-pinsn.c, i960-pinsn.c, m68k-pinsn.c,
+ m88k-pinsn.c, mips-pinsn.c, ns32k-pinsn.c, pyr-pinsn.c,
+ rs6000-pinsn.c, sparc-pinsn.c, tahoe-pinsn.c, vax-pinsn.c: Remove.
+ * gould-tdep.c, ns32k-tdep.c, tahoe-tdep.c, vax-tdep.c: New files,
+ had been -pinsn.c files.
+ * Makefile.in (ALLDEPFILES): Remove removed files.
+ (a29k-pinsn.o, arm-pinsn.o, convex-pinsn.o, gould-pinsn.o,
+ hppa-pinsn.o, i386-pinsn.o, i960-pinsn.o, m68k-pinsn.o,
+ m88k-pinsn.o, mips-pinsn.o, ns32k-pinsn.o, pyr-pinsn.o,
+ rs6000-pinsn.o, sparc-pinsn.o, tahoe-pinsn.o, vax-pinsn.o):
+ Remove compile actions.
+ * arm-tdep.o, gould-tdep.o, ns32k-tdep.o, tahoe-tdep.o,
+ vax-tdep.o: Add compile actions.
+ * defs.h (tm_print_insn): New global.
+ * a29k-tdep.c (gdb_print_insn_a29k): New function.
+ (_initialize_a29k_tdep): Rename from _initialize_29k,
+ set tm_print_insn.
+ * alpha-tdep.c (print_insn): Remove.
+ (_initialize_alpha_tdep): Set tm_print_insn.
+ * arm-tdep.c (arm_print_insn): New function, was print_insn
+ in arm-pinsn.c.
+ * convex-tdep.c (convex_print_insn): New function, was print_insn
+ in convex-pinsn.c.
+ * h8300-tdep.c (print_insn): Remove.
+ (gdb_print_insn_h8300): New function.
+ (_initialize_h8300_tdep): New function.
+ * h8500-tdep.c (print_insn): Remove.
+ (_initialize_h8500_tdep): New function.
+ * hppa-tdep.c (_initialize_hppa_tdep): Set tm_print_insn.
+ * i386-tdep.c (_initialize_i386_tdep): New function.
+ * i960-tdep.c (mem, next_insn): New functions, were in
+ i960-pinsn.c.
+ (_initialize_i960_tdep): Set tm_print_insn.
+ * m68k-tdep.c (_initialize_m68k_tdep): New function.
+ * m88k-tdep.c (_initialize_m88k_tdep): New function.
+ * mips-tdep.c (gdb_print_insn_mips): New function.
+ (_initialize_mips_tdep): Set tm_print_insn.
+ * pyr-tdep.c (pyr_print_insn): New function, was print_insn
+ in pyr-pinsn.c.
+ * rs6000-tdep.c (_initialize_rs6000_tdep): New function.
+ * sh-tdep.c (print_insn): Remove.
+ (gdb_print_insn_sh): New function.
+ (_initialize_sh_tdep): Set tm_print_insn.
+ * sparc-tdep.c (_initialize_sparc_tdep): New function.
+ * w65-tdep.c (print_insn): Remove.
+ (_initialize_w65_tdep): New function.
+ * z8k-tdep.c (print_insn): Remove.
+ (gdb_print_insn_z8k): New function.
+ (_initialize_z8k_tdep): Set tm_print_insn.
+ * printcmd.c (print_insn): New function, generic disassembler.
+ * config/*/*.mt (TDEPFILES): Remove refs to *-pinsn.o.
+
+Mon Jan 16 15:43:29 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * Makefile.in: add new files remote-vx29k.c, config/a29k/tm-vx29k.h,
+ and config/a29k/vx29k.mt.
+ * configure.in: add new configuration a29k-*-vxworks.
+ * remote-vx29k.c: new file merged from WRS.
+ * remote-vx.c: merge changes from WRS.
+ * config/a29k/vx29k.mt: new file for new configuration.
+ * config/a29k/tm-vx29k.h: new header file for newconfiguration.
+
+Sun Jan 15 14:36:19 1995 Steve Chamberlain <sac@splat>
+
+ * breakpoint.h (disable_breakpoint, enable_breakpoint):
+ New declarations.
+ (enum bpdisp): Change name of 'delete' member to 'del'.
+ (struct bpstat): Changed name to 'bpstats'.
+ * breakpoint.c (disable_breakpoint, enable_breakpoint,
+ breakpoint_chain): Made globally visible.
+ (bpstat_stop_status): Use new name for bpstat.
+ (break_command_1, watch_command_1, catch_command_1,
+ breakpoint_auto_delete, denable_delete_breakpoint): Use 'del'
+ instead of 'delete'.
+ (set_breakpoint_sal): New function.
+ * defs.h (registers_changed_hook): New declaration.
+ * infcmd.c (run_stack_dummy): 'delete' is now 'del'.
+ * inflow.c (new_tty): Treat WIN32 in same way as __GO32__
+ * main.c (main): Don't scan options when in WIN32 and exit
+ without entering main loop.
+ * m2-exp.y (m2_elx): Member 'class' is now 'aclass'.
+ * symtab.h (struct symbol, struct partial_symbol): Changed name of
+ member 'class' to 'aclass'.
+ (SYMBOL_CLASS, PSYMBOL_CLASS): Reflect change.
+ * top.c (registers_changed_hook): New definition.
+ * utils.c (quit, notice_quit, initialize_utils): Treate WIN32
+ in same way as __GO32__.
+ * value.h (c_typedef_print): Rename 'new' argument.
+
+ * w65-tdep.c, config/tm-w65.h, config/w65.mt: New files.
+ * configure.in: Suppprt for w65,
+
+
+Sat Jan 14 11:18:11 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * infcmd.c (signal_command): For "signal 0", pass (CORE_ADDR)-1,
+ not stop_pc, to proceed.
+
+ * eval.c (evaluate_subexp): Clear expect_type except for C++ and CHILL.
+
+Fri Jan 13 17:52:57 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * infcmd.c (signal_command): Accept "signal 0"; the change to not
+ accept it was accidental. "handle 0" and "info signal 0" remain
+ illegal, though.
+
+Fri Jan 13 15:19:01 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (all): Don't make libgdb-files.
+ (libgdb): New action, makes libgdb-files.
+
+Thu Jan 12 21:23:25 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * stabsread.c (read_enum_type): When pending enum symbols are
+ put into the enum type, they must be inserted in "backwards
+ order, in case we've overflowed a struct pending buffer.
+
+
+Thu Jan 12 09:33:24 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * README: Add note about SPARCworks cc release 3.0 and higher.
+
+ Add procfs support for Alpha OSF/1-2.x.
+ * config/alpha/nm-osf.h: Renamed from nm-alpha.h, generic
+ OSF/1 native support.
+ * config/alpha/alpha-osf1.mh (NAT_FILE): Changed accordingly.
+ (MUNCH_DEFINE): Removed.
+ * config/alpha/alpha-osf2.mh, config/alpha/nm-osf2.h: New files
+ for procfs support.
+ * configure.in (alpha-dec-osf*): Use alpha-osf2.mh for OSF/1
+ release 2.x and higher, else alpha-osf1.mh, as the procfs support
+ in release 1.x is incomplete.
+ * Makefile.in (ALLCONFIG): Add config/alpha/alpha-osf2.mh.
+ * alpha-nat.c (supply_gregset, fill_gregset, supply_fpgregset,
+ fill_fpgregset): New routines for procfs support.
+ * inftarg.c (_initialize_inftarg): Don't add ptrace support
+ if we have an optional procfs and /proc is accessible.
+ * procfs.c: Include sys/fault.h and sys/syscall.h before
+ including sys/procfs.h.
+ (unconditionally_kill_inferior): If PROCFS_NEED_PIOCSSIG_FOR_KILL
+ is defined, additionally perform a PIOCSSIG to really terminate
+ the inferior.
+ (create_procinfo): Always return a result.
+ (create_procinfo, do_attach): Don't trace T_IFAULT faults if
+ PROCFS_DONT_TRACE_IFAULT is defined.
+ (procfs_init_inferior): Use START_INFERIOR_TRAPS_EXPECTED as
+ argument to startup_inferior if it is defined.
+ (proc_set_exec_trap): If PIOCSSPCACT is defined, use it instead
+ of tracing exits from exec system calls. Needed for the user level
+ loader under Alpha OSF/1.
+ (do_detach): Clear any pending signal if we want to detach from
+ a process without a signal.
+ (set_proc_siginfo): If PROCFS_DONT_PIOCSSIG_CURSIG is defined,
+ don't issue a PIOCSSIG if pr_cursig already contains the signal we
+ intend to set.
+ (info_proc_signals): If PROCFS_SIGPEND_OFFSET is defined, the
+ pending signals are numbered from 1 instead of 0.
+ (info_proc_mappings): Increase size of output format for addresses
+ if BFD_HOST_64_BIT is defined.
+ (procfs_stop): Renamed from child_stop.
+ (_initialize_procfs): Don't add procfs support if we have an
+ optional procfs and /proc is not accessible.
+
+
+Wed Jan 11 17:53:26 1995 Rob Savoye <rob@darkstar.cygnus.com>
+
+ * array-rom.c: Add support for most commands.
+
+ * monitor.c: Add GDB remote protocol for the hybrid environment on
+ the Array board.
+
+Wed Jan 11 00:44:01 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * command.c (show_user_1): Use print_command_line to show a user
+ defined command (including control structures).
+
+ * top.c (init_main): Change documentation for user defined
+ commands to indicate they may accept up to ten arguments.
+
+Tue Jan 10 16:22:41 1995 Jim Kingdon <kingdon@lioth.cygnus.com>
+
+ * mips-tdep.c (mips_skip_prologue): Accept or as well as addu for
+ `move $s8, $sp' instruction.
+
+Sun Jan 8 12:45:34 1995 Jim Kingdon <kingdon@deneb.cygnus.com>
+
+ * target.c, target.h (target_signal_from_command): New function.
+ * infrun.c (handle_command, signals_info), infcmd.c
+ (signal_command): Use it.
+ * infrun.c, infcmd.c: Update docstrings for these commands.
+
+ * target.h (enum target_signal), target.c (signals), target.c
+ (target_signal_from_host, target_signal_to_host): Add
+ TARGET_SIGNAL_REALTIME_* and TARGET_SIGNAL_PRIO for lynx.
+ * config/tm-lynx.h: Define signal numbers for realtime events.
+
+Sat Jan 7 07:23:53 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dbxread.c (process_one_symbol): Handle N_FUN symbols
+ for Sun acc 3.0 under SunOS4.
+
+ Changes to improve handling of runtime common symbols
+ under SunOS4.
+ * minsyms.c (get_symbol_leading_char): New routine to determine
+ the leading symbol character for an objfile.
+ (prim_record_minimal_symbol_and_info, install_minimal_symbols):
+ Use it.
+ * objfiles.h (rt_common_objfile): New global, points to objfile
+ containing the runtime common minimal symbols.
+ * objfiles.c (free_objfile): Mark rt_common_objfile as
+ unallocated before freeing it.
+ * solib.c (allocate_rt_common_objfile): New routine to allocate
+ an objfile for the runtime common minimal symbols.
+ (solib_add_common_symbols): Allocate an objfile for the runtime
+ common symbols if necessary and put common symbols into it.
+ Clean up code and comments.
+ (solib_add, special_symbol_handling): Cleanup comments regarding
+ runtime common symbols.
+ * stabsread.c (scan_file_globals_1): New routine, contains
+ old scan_file_globals code. Checks if there are any unresolved
+ global symbols before starting the expensive minimal symbol table
+ search.
+ (scan_file_globals): Now calls scan_file_globals_1 for the passed
+ objfile and eventually for the runtime common objfile. Complains
+ about any unresolved global symbols and removes them from the
+ global symbol chain to avoid dangling pointers into the symbol
+ table if the symbol table is reread.
+
+Thu Jan 5 17:38:29 1995 Stu Grossman (grossman@cygnus.com)
+
+ * Makefile.in (install_only uninstall): Indent for clarity.
+
+ * core.c (dis_asm_read_memory): Add call to
+ dis_asm_read_memory_hook to provide alternate way for disassembler
+ to read memory.
+
+ * defs.h: Protect from multiple inclusion. Add decl for
+ dis_asm_read_memory_hook.
+
+ * top.c: Make window startup be the default.
+ * Add dis_asm_read_memory_hook.
+
+
+Thu Jan 5 01:16:40 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * stabsread.c (define_symbol): Handle `a' symbol type used for
+ reference parameter passed in a register.
+
+
+Wed Jan 4 12:27:29 1995 Kung Hsu <kung@mexican.cygnus.com>
+
+ * defs.h: move include tm.h up, so that the type LONGEST can
+ also based on the target requirement to determine. In this case
+ target mips64.
+
+ * remote-os9k.c (rombug_open): catch exception e in rombug.
+ * remote-os9k.c (rombug_wait): print message before register display
+ from rombug.
+
+Wed Jan 4 09:18:27 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * top.c (locate_arg): Call strchr not index.
+
+Tue Jan 3 16:52:03 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * ch-exp.y (literal): Recognize NULL.
+ (tuple): Parse simple unlabelled tuples.
+ * eval.c (evaluate_subexp case OP_ARRAY): Use expect_type to
+ evaluate brace-initializer-expressions depending on context.
+ (evaluate_subexp case UNOP_CAST): Pass the target type as
+ expected type when evaluating the expression.
+
+ * ch-typeprint.c (chill_type_print_base): Get names of PTR and
+ BOOL from TYPE_NAME.
+ * ch-valprint.c (chill_print_type_scalar): New function, to handle
+ TYPE_CODE_RANGE better than print_type_scalar does.
+ (chill_val_print_array_elements): Use above new function.
+
+Mon Jan 2 15:02:51 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * remote-udi.c (udi_load): Tell symbol_file_add that the
+ program being loaded is the main program.
+
+For older changes see ChangeLog-94
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/contrib/gdb/gdb/Makefile.in b/contrib/gdb/gdb/Makefile.in
new file mode 100644
index 0000000..77ef7f2
--- /dev/null
+++ b/contrib/gdb/gdb/Makefile.in
@@ -0,0 +1,1534 @@
+# Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+# Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+tooldir = $(libdir)/$(target_alias)
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+docdir = $(datadir)/doc
+
+SHELL = /bin/sh
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+AR = @AR@
+AR_FLAGS = qv
+RANLIB = @RANLIB@
+AWK = @AWK@
+
+# Flags that describe where you can find the termcap library.
+# This can be overridden in the host Makefile fragment file.
+TERMCAP = -ltermcap
+
+# If you are compiling with GCC, make sure that either 1) You have the
+# fixed include files where GCC can reach them, or 2) You use the
+# -traditional flag. Otherwise the ioctl calls in inflow.c
+# will be incorrectly compiled. The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+CC=@CC@
+
+# Directory containing source files.
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+YACC=@YACC@
+
+# where to find makeinfo, preferably one designed for texinfo-2
+MAKEINFO=makeinfo
+
+# Set this up with gcc if you have gnu ld and the loader will print out
+# line numbers for undefined references.
+#CC_LD=gcc -static
+CC_LD=$(CC)
+
+# Where is our "include" directory? Typically $(srcdir)/../include.
+# This is essentially the header file directory for the library
+# routines in libiberty.
+INCLUDE_DIR = $(srcdir)/../include
+INCLUDE_CFLAGS = -I$(INCLUDE_DIR)
+
+# Where is the "-liberty" library? Typically in ../libiberty.
+LIBIBERTY = ../libiberty/libiberty.a
+
+# Where is the MMALLOC library? Typically in ../mmalloc.
+# Note that mmalloc can still be used on systems without mmap().
+# To use your system malloc, comment out the following defines.
+MMALLOC_DIR = ../mmalloc
+MMALLOC_SRC = $(srcdir)/$(MMALLOC_DIR)
+MMALLOC = $(MMALLOC_DIR)/libmmalloc.a
+# To use your system malloc, uncomment MMALLOC_DISABLE.
+#MMALLOC_DISABLE = -DNO_MMALLOC
+# To use mmalloc but disable corruption checking, uncomment MMALLOC_CHECK
+#MMALLOC_CHECK = -DNO_MMALLOC_CHECK
+MMALLOC_CFLAGS = -I$(MMALLOC_SRC) $(MMALLOC_CHECK) $(MMALLOC_DISABLE)
+
+# Where is the BFD library? Typically in ../bfd.
+BFD_DIR = ../bfd
+BFD = $(BFD_DIR)/libbfd.a
+BFD_SRC = $(srcdir)/$(BFD_DIR)
+BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC)
+
+# Where is the READLINE library? Typically in ../readline.
+READLINE_DIR = ../readline
+READLINE = $(READLINE_DIR)/libreadline.a
+READLINE_SRC = $(srcdir)/$(READLINE_DIR)
+READLINE_CFLAGS = -I$(READLINE_SRC)
+
+# Opcodes currently live in one of two places. Either they are in the
+# opcode library, typically ../opcodes, or they are in a header file
+# in INCLUDE_DIR.
+# Where is the "-lopcodes" library, with (some of) the opcode tables and
+# disassemblers?
+OPCODES = ../opcodes/libopcodes.a
+# Where are the other opcode tables which only have header file
+# versions?
+OP_INCLUDE = $(INCLUDE_DIR)/opcode
+OPCODES_CFLAGS = -I$(OP_INCLUDE)
+
+# The simulator is usually nonexistent; targets that include one
+# should set this to list all the .o or .a files to be linked in.
+SIM =
+
+
+ENABLE_CFLAGS= @ENABLE_CFLAGS@
+ENABLE_CLIBS= @ENABLE_CLIBS@
+ENABLE_OBS= @ENABLE_OBS@
+
+# -I. for config files.
+# -I$(srcdir) for gdb internal headers and possibly for gnu-regex.h also.
+# -I$(srcdir)/config for more generic config files.
+
+# It is also possible that you will need to add -I/usr/include/sys if
+# your system doesn't have fcntl.h in /usr/include (which is where it
+# should be according to Posix).
+DEFS = @DEFS@
+GDB_CFLAGS = -I. -I$(srcdir) -I$(srcdir)/config $(DEFS)
+
+# M{H,T}_CFLAGS, if defined, have host- and target-dependent CFLAGS
+# from the config directory.
+GLOBAL_CFLAGS = $(MT_CFLAGS) $(MH_CFLAGS)
+#PROFILE_CFLAGS = -pg
+
+# CFLAGS is specifically reserved for setting from the command line
+# when running make. I.E. "make CFLAGS=-Wmissing-prototypes".
+CFLAGS = -g
+
+# Need to pass this to testsuite for "make check". Probably should be
+# consistent with top-level Makefile.in and gdb/testsuite/Makefile.in
+# so "make check" has the same result no matter where it is run.
+CXXFLAGS = -g -O
+
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) \
+ $(GDB_CFLAGS) $(OPCODES_CFLAGS) $(READLINE_CFLAGS) \
+ $(BFD_CFLAGS) $(MMALLOC_CFLAGS) $(INCLUDE_CFLAGS) $(ENABLE_CFLAGS)
+
+# LDFLAGS is specifically reserved for setting from the command line
+# when running make.
+
+# Profiling options need to go here to work.
+# I think it's perfectly reasonable for a user to set -pg in CFLAGS
+# and have it work; that's why CFLAGS is here.
+INTERNAL_LDFLAGS = $(CFLAGS) $(GLOBAL_CFLAGS) $(PROFILE_CFLAGS) $(LDFLAGS)
+
+# We are using our own version of REGEX now to be consistent across
+# machines.
+REGEX = gnu-regex.o
+REGEX1 = gnu-regex.o
+
+# If your system is missing alloca(), or, more likely, it's there but
+# it doesn't work, then refer to libiberty.
+
+# Libraries and corresponding dependencies for compiling gdb.
+# {X,T}M_CLIBS, defined in *config files, have host- and target-dependent libs.
+# TERMCAP comes after readline, since readline depends on it.
+# If you have the Cygnus libraries installed,
+# you can use 'CLIBS=$(INSTALLED_LIBS)' 'CDEPS='
+INSTALLED_LIBS=-lbfd -lreadline $(TERMCAP) -lopcodes -lmmalloc -liberty \
+ $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) $(ENABLE_CLIBS) @LIBS@
+CLIBS = $(SIM) $(BFD) $(READLINE) $(OPCODES) $(MMALLOC) $(LIBIBERTY) \
+ $(ENABLE_CLIBS) $(TERMCAP) $(XM_CLIBS) $(TM_CLIBS) $(NAT_CLIBS) \
+ $(LIBIBERTY) @LIBS@
+CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \
+ $(OPCODES) $(MMALLOC) $(LIBIBERTY)
+
+ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
+ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES)
+
+VERSION = 4.16
+DIST=gdb
+
+LINT=/usr/5bin/lint
+LINTFLAGS= $(BFD_CFLAGS)
+
+RUNTEST = `if [ -f $${rootsrc}/../dejagnu/runtest ] ; then \
+ echo $${rootsrc}/../dejagnu/runtest ; else echo runtest; \
+ fi`
+
+RUNTESTFLAGS=
+
+# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
+# interface to the serial port. Hopefully if get ported to OS/2, VMS,
+# etc., then there will be (as part of the C library or perhaps as
+# part of libiberty) a POSIX interface. But at least for now the
+# host-dependent makefile fragment might need to use something else
+# besides ser-unix.o
+SER_HARDWIRE = ser-unix.o
+
+# The `remote' debugging target is supported for most architectures,
+# but not all (e.g. 960)
+REMOTE_OBS = remote.o dcache.o remote-utils.o
+
+# This is remote-sim.o if a simulator is to be linked in.
+SIM_OBS =
+
+ANNOTATE_OBS = annotate.o
+
+# Host and target-dependent makefile fragments come in here.
+@host_makefile_frag@
+@target_makefile_frag@
+# End of host and target-dependent makefile fragments
+
+FLAGS_TO_PASS = \
+ "prefix=$(prefix)" \
+ "exec_prefix=$(exec_prefix)" \
+ "against=$(against)" \
+ "AR=$(AR)" \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CHILLFLAGS=$(CHILLFLAGS)" \
+ "CHILL=$(CHILL)" \
+ "CHILL_LIB=$(CHILL_LIB)" \
+ "CXX=$(CXX)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "RANLIB=$(RANLIB)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "RUNTEST=$(RUNTEST)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)"
+
+# Flags that we pass when building the testsuite.
+
+# empty for native, $(target_alias)/ for cross
+target_subdir = @target_subdir@
+
+CC_FOR_TARGET = ` \
+ if [ -f $${rootme}/../gcc/xgcc ] ; then \
+ if [ -f $${rootme}/../$(target_subdir)newlib/Makefile ] ; then \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -idirafter $${rootme}/$(target_subdir)newlib/targ-include -idirafter $${rootsrc}/../$(target_subdir)newlib/libc/include -nostdinc -B$${rootme}/../$(target_subdir)newlib/; \
+ else \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/; \
+ fi; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CC); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi; \
+ fi`
+
+CXX = gcc
+CXX_FOR_TARGET = ` \
+ if [ -f $${rootme}/../gcc/xgcc ] ; then \
+ if [ -f $${rootme}/../$(target_subdir)newlib/Makefile ] ; then \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -idirafter $${rootme}/$(target_subdir)newlib/targ-include -idirafter $${rootsrc}/../$(target_subdir)newlib/libc/include -nostdinc -B$${rootme}/../$(target_subdir)newlib/; \
+ else \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/; \
+ fi; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CXX); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi; \
+ fi`
+
+CHILLFLAGS = $(CFLAGS)
+CHILL = gcc
+CHILL_FOR_TARGET = ` \
+ if [ -f $${rootme}/../gcc/Makefile ] ; then \
+ echo $${rootme}/../gcc/xgcc -B$${rootme}/../gcc/ -L$${rootme}/../gcc/ch/runtime/; \
+ else \
+ if [ "$(host_canonical)" = "$(target_canonical)" ] ; then \
+ echo $(CC); \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi; \
+ fi`
+CHILL_LIB = ` \
+ if [ -f $${rootme}/../gcc/ch/runtime/libchill.a ] ; then \
+ echo $${rootme}/../gcc/ch/runtime/chillrt0.o \
+ $${rootme}/../gcc/ch/runtime/libchill.a; \
+ else \
+ echo -lchill; \
+ fi`
+
+# The use of $$(x_FOR_TARGET) reduces the command line length by not
+# duplicating the lengthy definition.
+TARGET_FLAGS_TO_PASS = \
+ "prefix=$(prefix)" \
+ "exec_prefix=$(exec_prefix)" \
+ "against=$(against)" \
+ 'CC=$$(CC_FOR_TARGET)' \
+ "CC_FOR_TARGET=$(CC_FOR_TARGET)" \
+ "CFLAGS=$(CFLAGS)" \
+ "CHILLFLAGS=$(CHILLFLAGS)" \
+ 'CHILL=$$(CHILL_FOR_TARGET)' \
+ "CHILL_FOR_TARGET=$(CHILL_FOR_TARGET)" \
+ "CHILL_LIB=$(CHILL_LIB)" \
+ 'CXX=$$(CXX_FOR_TARGET)' \
+ "CXX_FOR_TARGET=$(CXX_FOR_TARGET)" \
+ "CXXFLAGS=$(CXXFLAGS)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "RUNTEST=$(RUNTEST)" \
+ "RUNTESTFLAGS=$(RUNTESTFLAGS)"
+
+# All source files that go into linking GDB.
+# Links made at configuration time should not be specified here, since
+# SFILES is used in building the distribution archive.
+
+SFILES = bcache.c blockframe.c breakpoint.c buildsym.c callback.c c-exp.y \
+ c-lang.c c-typeprint.c c-valprint.c ch-exp.c ch-lang.c \
+ ch-typeprint.c ch-valprint.c coffread.c command.c complaints.c \
+ corefile.c cp-valprint.c dbxread.c demangle.c dwarfread.c \
+ elfread.c environ.c eval.c expprint.c \
+ f-exp.y f-lang.c f-typeprint.c f-valprint.c findvar.c \
+ gdbtypes.c infcmd.c inflow.c infrun.c language.c \
+ m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c main.c maint.c \
+ mem-break.c minsyms.c mipsread.c nlmread.c objfiles.c parse.c \
+ printcmd.c remote.c remote-nrom.c scm-exp.c scm-lang.c scm-valprint.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 serial.c ser-unix.c mdebugread.c os9kread.c
+
+LINTFILES = $(SFILES) $(YYFILES) init.c
+
+# "system" headers. Using these in dependencies is a rather personal
+# choice. (-rich, summer 1993)
+# (Why would we not want to depend on them? If one of these changes in a
+# non-binary-compatible way, it is a real pain to remake the right stuff
+# without these dependencies -kingdon, 13 Mar 1994)
+getopt_h = $(INCLUDE_DIR)/getopt.h
+floatformat_h = $(INCLUDE_DIR)/floatformat.h
+bfd_h = $(BFD_DIR)/bfd.h
+wait_h = $(INCLUDE_DIR)/wait.h
+dis-asm_h = $(INCLUDE_DIR)/dis-asm.h
+
+dcache_h = dcache.h
+remote_utils_h = $(dcache_h) serial.h target.h remote-utils.h remote-sim.h
+
+readline_headers = \
+ $(READLINE_SRC)/chardefs.h \
+ $(READLINE_SRC)/history.h \
+ $(READLINE_SRC)/keymaps.h \
+ $(READLINE_SRC)/readline.h
+
+udiheaders = \
+ $(srcdir)/29k-share/udi/udiproc.h \
+ $(srcdir)/29k-share/udi/udiphcfg.h \
+ $(srcdir)/29k-share/udi/udiphunix.h \
+ $(srcdir)/29k-share/udi/udiptcfg.h \
+ $(srcdir)/29k-share/udi/udipt29k.h \
+ $(srcdir)/29k-share/udi/udisoc.h
+
+gdbcore_h = gdbcore.h $(bfd_h)
+
+frame_h = frame.h
+symtab_h = symtab.h bcache.h
+gdbtypes_h = gdbtypes.h
+expression_h = expression.h
+value_h = value.h $(symtab_h) $(gdbtypes_h) $(expression_h)
+
+breakpoint_h = breakpoint.h $(frame_h) $(value_h)
+
+command_h = command.h
+gdbcmd_h = gdbcmd.h $(command_h)
+
+defs_h = defs.h xm.h tm.h nm.h config.status config.h
+
+inferior_h = inferior.h $(breakpoint_h)
+
+# Header files that need to have srcdir added. Note that in the cases
+# where we use a macro like $(gdbcmd_h), things are carefully arranged
+# so that each .h file is listed exactly once (M-x tags-search works
+# wrong if TAGS has files twice). Because this is tricky to get
+# right, it is probably easiest just to list .h files here directly.
+
+HFILES_NO_SRCDIR = bcache.h buildsym.h call-cmds.h coff-solib.h defs.h \
+ dst.h environ.h $(gdbcmd_h) gdbcore.h \
+ gdb-stabs.h $(inferior_h) language.h minimon.h monitor.h \
+ objfiles.h parser-defs.h partial-stab.h serial.h signals.h solib.h \
+ symfile.h stabsread.h target.h terminal.h typeprint.h xcoffsolib.h \
+ c-lang.h ch-lang.h f-lang.h m2-lang.h \
+ complaints.h valprint.h \
+ 29k-share/udi/udiids.h 29k-share/udi_soc nindy-share/b.out.h \
+ nindy-share/block_io.h nindy-share/coff.h \
+ nindy-share/env.h nindy-share/stop.h \
+ vx-share/dbgRpcLib.h vx-share/ptrace.h vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/wait.h vx-share/xdr_ld.h \
+ vx-share/xdr_ptrace.h vx-share/xdr_rdb.h thread.h \
+ dcache.h remote-utils.h remote-sim.h top.h somsolib.h
+
+# Header files that already have srcdir in them, or which are in objdir.
+
+HFILES_WITH_SRCDIR = $(udiheaders) ../bfd/bfd.h
+
+
+# GDB "info" files, which should be included in their entirety
+INFOFILES = gdb.info*
+
+REMOTE_EXAMPLES = m68k-stub.c i386-stub.c sparc-stub.c rem-multi.shar
+
+POSSLIBS = gnu-regex.c gnu-regex.h
+
+# {X,T,NAT}DEPFILES are something of a pain in that it's hard to
+# default their values the way we do for SER_HARDWIRE; in the future
+# maybe much of the stuff now in {X,T,NAT}DEPFILES will go into other
+# variables analogous to SER_HARDWIRE which get defaulted in this
+# Makefile.in
+
+DEPFILES = $(TDEPFILES) $(XDEPFILES) $(SER_HARDWIRE) $(NATDEPFILES) \
+ $(REMOTE_OBS) $(SIM_OBS) $(ENABLE_OBS)
+
+SOURCES = $(SFILES) $(ALLDEPFILES) $(YYFILES)
+# Don't include YYFILES (*.tab.c) because we already include *.y in SFILES,
+# and it's more useful to see it in the .y file.
+TAGFILES_NO_SRCDIR = $(SFILES) $(HFILES_NO_SRCDIR) $(ALLDEPFILES) \
+ $(POSSLIBS)
+TAGFILES_WITH_SRCDIR = $(HFILES_WITH_SRCDIR)
+
+COMMON_OBS = version.o blockframe.o breakpoint.o findvar.o stack.o thread.o \
+ source.o values.o eval.o valops.o valarith.o valprint.o printcmd.o \
+ symtab.o symfile.o symmisc.o infcmd.o infrun.o command.o \
+ expprint.o environ.o gdbtypes.o copying.o $(DEPFILES) \
+ mem-break.o target.o parse.o language.o $(YYOBJ) buildsym.o \
+ exec.o bcache.o objfiles.o minsyms.o maint.o demangle.o \
+ dbxread.o coffread.o elfread.o \
+ dwarfread.o mipsread.o stabsread.o corefile.o \
+ c-lang.o ch-exp.o ch-lang.o f-lang.o m2-lang.o \
+ scm-exp.o scm-lang.o scm-valprint.o complaints.o typeprint.o \
+ c-typeprint.o ch-typeprint.o f-typeprint.o m2-typeprint.o \
+ c-valprint.o cp-valprint.o ch-valprint.o f-valprint.o m2-valprint.o \
+ nlmread.o serial.o mdebugread.o os9kread.o top.o utils.o callback.o
+
+OBS = $(COMMON_OBS) $(ANNOTATE_OBS) main.o
+
+LIBGDB_OBS =
+
+TSOBS = inflow.o
+
+NTSOBS = standalone.o
+
+NTSSTART = kdb-start.o
+
+SUBDIRS = doc testsuite nlm
+
+# For now, shortcut the "configure GDB for fewer languages" stuff.
+YYFILES = c-exp.tab.c f-exp.tab.c m2-exp.tab.c
+YYOBJ = c-exp.tab.o f-exp.tab.o m2-exp.tab.o
+
+# Things which need to be built when making a distribution.
+
+DISTSTUFF = $(YYFILES)
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ $(CC) -c $(INTERNAL_CFLAGS) $<
+
+all: gdb
+ @$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=`echo $(SUBDIRS) | sed 's/testsuite//'`" subdir_do
+
+installcheck:
+
+# The check target can not use subdir_do, because subdir_do does not
+# use TARGET_FLAGS_TO_PASS.
+check: force
+ @if [ -f testsuite/Makefile ]; then \
+ rootme=`pwd`; export rootme; \
+ rootsrc=`cd $(srcdir); pwd`; export rootsrc; \
+ cd testsuite; \
+ $(MAKE) $(TARGET_FLAGS_TO_PASS) check; \
+ else true; fi
+
+info dvi install-info clean-info: force
+ @$(MAKE) $(FLAGS_TO_PASS) DO=$@ "DODIRS=$(SUBDIRS)" subdir_do
+
+gdb.z:gdb.1
+ nroff -man $(srcdir)/gdb.1 | col -b > gdb.t
+ pack gdb.t ; rm -f gdb.t
+ mv gdb.t.z gdb.z
+
+# Traditionally "install" depends on "all". But it may be useful
+# not to; for example, if the user has made some trivial change to a
+# source file and doesn't care about rebuilding or just wants to save the
+# time it takes for make to check that all is up to date.
+# install-only is intended to address that need.
+install: all install-only
+install-only:
+ transformed_name=`t='$(program_transform_name)'; \
+ echo gdb | sed -e $$t` ; \
+ if test "x$$transformed_name" = x; then \
+ transformed_name=gdb ; \
+ else \
+ true ; \
+ fi ; \
+ $(INSTALL_PROGRAM) gdb $(bindir)/$$transformed_name ; \
+ $(INSTALL_DATA) $(srcdir)/gdb.1 $(man1dir)/$$transformed_name.1
+ @$(MAKE) DO=install "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
+
+uninstall: force
+ transformed_name=`t='$(program_transform_name)'; \
+ echo gdb | sed -e $$t` ; \
+ if test "x$$transformed_name" = x; then \
+ transformed_name=gdb ; \
+ else \
+ true ; \
+ fi ; \
+ rm -f $(bindir)/$$transformed_name $(man1dir)/$$transformed_name.1
+ @$(MAKE) DO=uninstall "DODIRS=$(SUBDIRS)" $(FLAGS_TO_PASS) subdir_do
+
+# We do this by grepping through sources. If that turns out to be too slow,
+# maybe we could just require every .o file to have an initialization routine
+# of a given name (remote-udi.o -> _initialize_remote_udi, etc.).
+#
+# Formatting conventions: The name of the _initialize_* routines must start
+# in column zero, and must not be inside #if.
+#
+# Note that the set of files with init functions might change, or the names
+# of the functions might change, so this files needs to depend on all the
+# object files that will be linked into gdb.
+
+init.c: $(OBS) $(TSOBS)
+ @echo Making init.c
+ @rm -f init.c-tmp
+ @echo '/* Do not modify this file. */' >init.c-tmp
+ @echo '/* It is created automatically by the Makefile. */'>>init.c-tmp
+ @echo 'void initialize_all_files () {' >>init.c-tmp
+ @for i in $(OBS) $(TSOBS); do \
+ filename=`echo $$i | sed \
+ -e '/^Onindy.o/d' \
+ -e '/^nindy.o/d' \
+ -e '/ttyflush.o/d' \
+ -e '/xdr_ld.o/d' \
+ -e '/xdr_ptrace.o/d' \
+ -e '/xdr_rdb.o/d' \
+ -e '/udr.o/d' \
+ -e '/udip2soc.o/d' \
+ -e '/udi2go32.o/d' \
+ -e '/version.o/d' \
+ -e '/^[a-z0-9A-Z_]*_[SU].o/d' \
+ -e '/[a-z0-9A-Z_]*-exp.tab.o/d' \
+ -e 's/\.o/.c/'` ; \
+ case $$filename in \
+ "") ;; \
+ *) sed <$(srcdir)/$$filename >>init.c-tmp -n \
+ -e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\([a-z_0-9A-Z]*\).*/ {extern void \1 (); \1 ();}/p' ; ;; \
+ esac ; \
+ done
+ @echo '}' >>init.c-tmp
+ @mv init.c-tmp init.c
+
+.PRECIOUS: init.c
+
+# Removing the old gdb first works better if it is running, at least on SunOS.
+gdb: $(OBS) $(TSOBS) $(ADD_DEPS) $(CDEPS) init.o
+ rm -f gdb
+ $(CC_LD) $(INTERNAL_LDFLAGS) -o gdb \
+ init.o $(OBS) $(TSOBS) $(ADD_FILES) $(CLIBS) $(LOADLIBES)
+
+nlm: force
+ rootme=`pwd`; export rootme; $(MAKE) $(TARGET_FLAGS_TO_PASS) DO=all DODIRS=nlm subdir_do
+
+libgdb: libgdb-files $(LIBGDB_OBS)
+
+# libproc is not listed here because all-libproc is a dependency of all-gui,
+# not all-gdb, and thus might be built after us.
+LIBGDBDEPS=$(COMMON_OBS) $(LIBGDB_OBS) $(TSOBS) $(ADD_DEPS) $(CDEPS) init.o
+# libproc needs to be before libiberty for alloca.
+LIBGDBFILES=$(COMMON_OBS) $(LIBGDB_OBS) $(TSOBS) ../libproc/libproc.a \
+ $(ADD_DEPS) $(CDEPS) init.o
+
+libgdb-files: $(LIBGDBDEPS) Makefile.in
+ -rm -f libgdb-files
+ for i in $(LIBGDBFILES); do\
+ echo $$i >> libgdb-files;\
+ done
+
+saber_gdb: $(SFILES) $(DEPFILES) copying.c version.c
+ #setopt load_flags $(CFLAGS) $(BFD_CFLAGS) -DHOST_SYS=SUN4_SYS
+ #load ./init.c $(SFILES)
+ #unload $(srcdir)/c-exp.y $(srcdir)/m2-exp.y
+ #unload vx-share/*.h
+ #unload nindy-share/[A-Z]*
+ #load c-exp.tab.c m2-exp.tab.c
+ #load copying.c version.c
+ #load ../opcodes/libopcodes.a
+ #load ../libiberty/libiberty.a
+ #load ../bfd/libbfd.a
+ #load ../readline/libreadline.a
+ #load ../mmalloc/libmmalloc.a
+ #load -ltermcap
+ #load `echo " "$(DEPFILES) | sed -e 's/\.o/.c/g' -e 's, , ../,g'`
+ echo "Load .c corresponding to:" $(DEPFILES)
+
+
+# A Mach 3.0 program to force gdb back to command level
+
+stop-gdb: stop-gdb.o
+ ${CC_LD} $(GLOBAL_CFLAGS) $(LDFLAGS) -o stop-gdb \
+ stop-gdb.o $(CLIBS) $(LOADLIBES)
+
+# This is useful when debugging GDB, because some Unix's don't let you run GDB
+# on itself without copying the executable. So "make gdb1" will make
+# gdb and put a copy in gdb1, and you can run it with "gdb gdb1".
+# Removing gdb1 before the copy is the right thing if gdb1 is open
+# in another process.
+gdb1: gdb
+ rm -f gdb1
+ cp gdb gdb1
+
+### fixme - this can't be right.
+# This checks the configure.in file versus the config/ directory.
+config-check: config-check-hosts config-check-targets
+config-check-hosts:
+ grep gdb_host= $(srcdir)/configure.in | \
+ sed -e 's/.*gdb_host=//' -e 's/ ;;$$/.mh/' | sort -u >HOSTconf.o
+ (cd $(srcdir)/config; ls *.mh) >HOSTdir.o
+ diff -u HOSTconf.o HOSTdir.o
+
+### fixme - nor can this.
+config-check-targets:
+ grep gdb_target= $(srcdir)/configure.in | \
+ sed -e 's/.*gdb_target=//' -e 's/ ;;$$/.mh/' | sort -u >TARGconf.o
+ (cd $(srcdir)/config; ls *.mt) >TARGdir.o
+ diff -u HOSTconf.o HOSTdir.o
+
+# FIXME. These are not generated by "make depend" because they only are there
+# for some machines.
+# But these rules don't do what we want; we want to hack the foo.o: tm.h
+# dependency to do the right thing.
+tm-isi.h tm-sun3.h tm-news.h tm-hp300bsd.h tm-altos.h: tm-m68k.h
+tm-hp300hpux.h tm-sun2.h tm-3b1.h: tm-m68k.h
+xm-news1000.h: xm-news.h
+xm-i386-sv32.h: xm-i386.h
+tm-i386gas.h: tm-i386.h
+xm-sun4os4.h: xm-sparc.h
+tm-sun4os4.h: tm-sparc.h
+xm-vaxult.h: xm-vax.h
+xm-vaxbsd.h: xm-vax.h
+
+kdb: $(NTSSTART) $(OBS) $(NTSOBS) $(ADD_DEPS) $(CDEPS)
+ ld -o kdb $(NTSSTART) $(OBS) $(NTSOBS) init.o $(ADD_FILES) \
+ -lc $(CLIBS)
+
+# Put the proper machine-specific files first, so M-. on a machine
+# specific routine gets the one for the correct machine. (FIXME: those
+# files go in twice; we should be removing them from the main list).
+
+# TAGS depends on all the files that go into it so you can rebuild TAGS
+# with `make TAGS' and not have to say `rm TAGS' first.
+
+TAGS: $(TAGFILES_NO_SRCDIR) $(TAGFILES_WITH_SRCDIR)
+ @echo Making TAGS
+ @etags $(srcdir)/$(TM_FILE) \
+ $(srcdir)/$(XM_FILE) \
+ $(srcdir)/$(NAT_FILE) \
+ `(for i in $(DEPFILES) $(TAGFILES_NO_SRCDIR); do \
+ echo $(srcdir)/$$i ; \
+ done ; for i in $(TAGFILES_WITH_SRCDIR); do \
+ echo $$i ; \
+ done) | sed -e 's/\.o$$/\.c/'` \
+ `find $(srcdir)/config -name '*.h' -print`
+
+tags: TAGS
+
+clean mostlyclean:
+ @$(MAKE) $(FLAGS_TO_PASS) DO=clean "DODIRS=$(SUBDIRS)" subdir_do
+ rm -f *.o $(ADD_FILES) *~ init.c-tmp
+ rm -f init.c version.c
+ rm -f gdb core make.log libgdb-files
+ rm -f gdb[0-9]
+
+# This used to depend on c-exp.tab.c m2-exp.tab.c TAGS
+# I believe this is wrong; the makefile standards for distclean just
+# describe removing files; the only sort of "re-create a distribution"
+# functionality described is if the distributed files are unmodified.
+distclean: clean
+ @$(MAKE) $(FLAGS_TO_PASS) DO=distclean "DODIRS=$(SUBDIRS)" subdir_do
+ rm -f nm.h tm.h xm.h config.status config.h stamp-h
+ rm -f y.output yacc.acts yacc.tmp y.tab.h
+ rm -f config.log config.cache
+ rm -f Makefile
+
+maintainer-clean realclean: clean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ @$(MAKE) $(FLAGS_TO_PASS) DO=maintainer-clean "DODIRS=$(SUBDIRS)" subdir_do
+ rm -f c-exp.tab.c f-exp.tab.c m2-exp.tab.c
+ rm -f TAGS $(INFOFILES)
+ rm -f nm.h tm.h xm.h config.status
+ rm -f y.output yacc.acts yacc.tmp
+ rm -f config.log config.cache
+ rm -f Makefile
+
+diststuff: $(DISTSTUFF)
+ cd doc; $(MAKE) $(MFLAGS) all-doc
+
+subdir_do: force
+ @for i in $(DODIRS); do \
+ if [ -f ./$$i/Makefile ] ; then \
+ if (cd ./$$i; \
+ $(MAKE) $(FLAGS_TO_PASS) $(DO)) ; then true ; \
+ else exit 1 ; fi ; \
+ else true ; fi ; \
+ done
+
+Makefile: Makefile.in config.status @frags@
+ $(SHELL) config.status
+
+config.h: stamp-h ; @true
+stamp-h: config.in config.status
+ CONFIG_HEADERS=config.h:config.in $(SHELL) config.status
+
+config.status: configure
+ $(SHELL) config.status --recheck
+
+force:
+
+# Documentation!
+# GDB QUICK REFERENCE (TeX dvi file, CM fonts)
+doc/refcard.dvi:
+ cd doc; $(MAKE) refcard.dvi $(FLAGS_TO_PASS)
+
+# GDB QUICK REFERENCE (PostScript output, common PS fonts)
+doc/refcard.ps:
+ cd doc; $(MAKE) refcard.ps $(FLAGS_TO_PASS)
+
+# GDB MANUAL: TeX dvi file
+doc/gdb.dvi:
+ cd doc; $(MAKE) gdb.dvi $(FLAGS_TO_PASS)
+
+# GDB MANUAL: info file
+doc/gdb.info:
+ cd doc; $(MAKE) gdb.info $(FLAGS_TO_PASS)
+
+# Make copying.c from COPYING
+copying.c: COPYING copying.awk
+ awk -f $(srcdir)/copying.awk < $(srcdir)/COPYING > copying.c
+
+version.c: Makefile
+ echo 'char *version = "$(VERSION)";' >version.c
+ echo 'char *host_name = "$(host_alias)";' >> version.c
+ echo 'char *target_name = "$(target_alias)";' >> version.c
+
+# c-exp.tab.c is generated in objdir from c-exp.y if it doesn't exist
+# in srcdir, then compiled in objdir to c-exp.tab.o.
+
+# If we said c-exp.tab.c rather than ./c-exp.tab.c some makes
+# would sometimes re-write it into $(srcdir)/c-exp.tab.c.
+
+# Remove bogus decls for malloc/realloc/free which conflict with everything
+# else. Strictly speaking c-exp.tab.c should therefore depend on
+# Makefile.in, but that was a pretty big annoyance.
+c-exp.tab.o: c-exp.tab.c
+c-exp.tab.c: c-exp.y
+ $(YACC) $(YFLAGS) $(srcdir)/c-exp.y
+ -sed -e '/extern.*malloc/d' \
+ -e '/extern.*realloc/d' \
+ -e '/extern.*free/d' \
+ -e '/include.*malloc.h/d' \
+ -e 's/malloc/xmalloc/g' \
+ -e 's/realloc/xrealloc/g' \
+ < y.tab.c > c-exp.new
+ -rm y.tab.c
+ mv c-exp.new ./c-exp.tab.c
+
+f-exp.tab.o: f-exp.tab.c
+f-exp.tab.c: f-exp.y c-exp.tab.c
+ $(YACC) $(YFLAGS) $(srcdir)/f-exp.y
+ -sed -e '/extern.*malloc/d' \
+ -e '/extern.*realloc/d' \
+ -e '/extern.*free/d' \
+ -e '/include.*malloc.h/d' \
+ -e 's/malloc/xmalloc/g' \
+ -e 's/realloc/xrealloc/g' \
+ < y.tab.c > f-exp.new
+ -rm y.tab.c
+ mv f-exp.new ./f-exp.tab.c
+
+# m2-exp.tab.c is generated in objdir from m2-exp.y if it doesn't exist
+# in srcdir, then compiled in objdir to m2-exp.tab.o.
+# Remove bogus decls for malloc/realloc/free which conflict with everything
+# else.
+m2-exp.tab.o: m2-exp.tab.c
+m2-exp.tab.c: m2-exp.y
+ $(YACC) $(YFLAGS) $(srcdir)/m2-exp.y
+ -sed -e '/extern.*malloc/d' \
+ -e '/extern.*realloc/d' \
+ -e '/extern.*free/d' \
+ -e '/include.*malloc.h/d' \
+ -e 's/malloc/xmalloc/g' \
+ -e 's/realloc/xrealloc/g' \
+ < y.tab.c > m2-exp.new
+ -rm y.tab.c
+ mv m2-exp.new ./m2-exp.tab.c
+
+# These files are updated atomically, so make never has to remove them
+.PRECIOUS: m2-exp.tab.c f-exp.tab.c c-exp.tab.c
+
+lint: $(LINTFILES)
+ $(LINT) $(INCLUDE_CFLAGS) $(LINTFLAGS) $(LINTFILES) \
+ `echo $(DEPFILES) | sed 's/\.o /\.c /g'`
+
+gdb.cxref: $(SFILES)
+ cxref -I. $(SFILES) >gdb.cxref
+
+force_update:
+
+# GNU Make has an annoying habit of putting *all* the Makefile variables
+# into the environment, unless you include this target as a circumvention.
+# Rumor is that this will be fixed (and this target can be removed)
+# in GNU Make 4.0.
+.NOEXPORT:
+
+# GNU Make 3.63 has a different problem: it keeps tacking command line
+# overrides onto the definition of $(MAKE). This variable setting
+# will remove them.
+MAKEOVERRIDES=
+
+## This is ugly, but I don't want GNU make to put these variables in
+## the environment. Older makes will see this as a set of targets
+## with no dependencies and no actions.
+unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
+
+ALLDEPFILES = 29k-share/udi/udip2soc.c 29k-share/udi/udr.c \
+ 29k-share/udi/udi2go32.c \
+ a29k-tdep.c a68v-nat.c alpha-nat.c alpha-tdep.c \
+ altos-xdep.c arm-convert.s \
+ arm-tdep.c arm-xdep.c coff-solib.c \
+ convex-tdep.c convex-xdep.c \
+ core-sol2.c core-regset.c core-aout.c corelow.c \
+ dcache.c delta68-nat.c dpx2-nat.c dstread.c exec.c fork-child.c \
+ go32-xdep.c gould-tdep.c gould-xdep.c h8300-tdep.c h8500-tdep.c \
+ hp300ux-nat.c hppa-tdep.c hppab-nat.c hppah-nat.c \
+ hpread.c \
+ i386-tdep.c i386b-nat.c i386mach-nat.c i386v-nat.c \
+ i386aix-nat.c i386m3-nat.c i386v4-nat.c i386ly-tdep.c \
+ i387-tdep.c \
+ i960-tdep.c \
+ infptrace.c inftarg.c irix4-nat.c irix5-nat.c isi-xdep.c \
+ lynx-nat.c m3-nat.c \
+ m68k-tdep.c \
+ m88k-nat.c m88k-tdep.c mac-nat.c mips-nat.c \
+ mips-tdep.c mipsm3-nat.c mipsv4-nat.c news-xdep.c \
+ nindy-share/Onindy.c nindy-share/nindy.c \
+ nindy-share/ttyflush.c nindy-tdep.c \
+ ns32k-tdep.c ns32km3-nat.c osfsolib.c \
+ somread.c somsolib.c $(HPREAD_SOURCE) \
+ procfs.c pyr-tdep.c pyr-xdep.c \
+ remote-adapt.c remote-array.c remote-bug.c remote-e7000.c remote-eb.c \
+ remote-es.c remote-hms.c remote-mips.c \
+ remote-mm.c remote-nindy.c remote-os9k.c remote-rdp.c remote-sim.c \
+ remote-st.c remote-utils.c dcache.c \
+ remote-udi.c remote-vx.c remote-vx29k.c \
+ rs6000-nat.c rs6000-tdep.c \
+ ser-go32.c ser-tcp.c sh-tdep.c solib.c sparc-nat.c \
+ sparc-tdep.c sparcl-tdep.c sun3-nat.c sun386-nat.c \
+ symm-tdep.c symm-nat.c \
+ tahoe-tdep.c ultra3-nat.c ultra3-xdep.c umax-xdep.c \
+ vax-tdep.c \
+ vx-share/xdr_ld.c vx-share/xdr_ptrace.c vx-share/xdr_rdb.c \
+ win32-nat.c \
+ xcoffread.c xcoffsolib.c z8k-tdep.c
+
+ALLCONFIG = config/a29k/a29k-kern.mt config/a29k/a29k-udi.mt config/a29k/vx29k.mt\
+ config/a29k/a29k.mt config/a29k/ultra3.mh config/a29k/ultra3.mt \
+ config/alpha/alpha-osf1.mh config/alpha/alpha-osf2.mh \
+ config/alpha/alpha-osf1.mt config/alpha/alpha-nw.mt \
+ config/arm/arm.mh config/arm/arm.mt config/convex/convex.mh \
+ config/convex/convex.mt config/gould/np1.mh config/gould/np1.mt \
+ config/gould/pn.mh config/gould/pn.mt config/h8300/h8300hms.mt \
+ config/h8500/h8500hms.mt config/i386/go32.mh config/i386/i386aix.mh \
+ config/i386/i386aix.mt config/i386/i386aout.mt config/i386/i386bsd.mh \
+ config/i386/i386bsd.mt config/i386/i386lynx.mh \
+ config/i386/i386lynx.mt config/i386/i386m3.mh config/i386/i386m3.mt \
+ config/i386/i386mach.mh config/i386/i386mk.mh config/i386/i386mk.mt \
+ config/i386/i386nw.mt config/i386/i386sco.mh \
+ config/i386/i386sco4.mh \
+ config/i386/i386sol2.mh config/i386/i386sol2.mt config/i386/i386v.mh \
+ config/i386/i386v.mt config/i386/i386v32.mh config/i386/i386v4.mh \
+ config/i386/i386v4.mt config/i386/linux.mh config/i386/linux.mt \
+ config/i386/ncr3000.mh config/i386/ncr3000.mt config/i386/ptx.mh \
+ config/i386/sun386.mh \
+ config/i386/sun386.mt config/i386/symmetry.mh config/i386/symmetry.mt \
+ config/i386/win32.mh config/i386/win32.mt \
+ config/i960/mon960.mt \
+ config/i960/nindy960.mt config/i960/vxworks960.mt config/m68k/3b1.mh \
+ config/m68k/3b1.mt config/m68k/altos.mh config/m68k/altos.mt \
+ config/m68k/amix.mh config/m68k/amix.mt config/m68k/apollo68b.mh \
+ config/m68k/apollo68b.mt \
+ config/m68k/apollo68v.mh \
+ config/m68k/cisco.mt config/m68k/delta68.mh \
+ config/m68k/delta68.mt config/m68k/dpx2.mh config/m68k/dpx2.mt \
+ config/m68k/es1800.mt config/m68k/hp300bsd.mh \
+ config/m68k/hp300bsd.mt config/m68k/hp300hpux.mh \
+ config/m68k/hp300hpux.mt config/m68k/isi.mh config/m68k/isi.mt \
+ config/m68k/m68klynx.mh config/m68k/m68klynx.mt \
+ config/m68k/monitor.mt \
+ config/m68k/news.mh config/m68k/news.mt config/m68k/news1000.mh \
+ config/m68k/os68k.mt config/m68k/st2000.mt config/m68k/sun2os3.mh \
+ config/m68k/sun2os3.mt config/m68k/sun2os4.mh config/m68k/sun2os4.mt \
+ config/m68k/sun3os3.mh config/m68k/sun3os3.mt config/m68k/sun3os4.mh \
+ config/m68k/sun3os4.mt config/m68k/vxworks68.mt config/m88k/delta88.mh \
+ config/m88k/delta88.mt config/m88k/delta88v4.mh \
+ config/m88k/delta88v4.mt config/m88k/m88k.mh config/m88k/m88k.mt \
+ config/mips/bigmips.mt config/mips/bigmips64.mt \
+ config/mips/decstation.mh \
+ config/mips/decstation.mt config/mips/idt.mt config/mips/idtl.mt \
+ config/mips/idt64.mt config/mips/idtl64.mt \
+ config/mips/irix3.mh config/mips/irix3.mt config/mips/irix4.mh \
+ config/mips/irix5.mh config/mips/irix5.mt \
+ config/mips/littlemips.mh config/mips/littlemips.mt \
+ config/mips/mipsel64.mt \
+ config/mips/mipsm3.mh config/mips/mipsm3.mt \
+ config/mips/mipsv4.mh config/mips/mipsv4.mt \
+ config/mips/news-mips.mh config/mips/riscos.mh \
+ config/none/none.mh config/none/none.mt config/ns32k/merlin.mh \
+ config/ns32k/merlin.mt config/ns32k/ns32km3.mh config/ns32k/ns32km3.mt \
+ config/ns32k/umax.mh config/ns32k/umax.mt \
+ config/pa/hppabsd.mh config/pa/hppabsd.mt config/pa/hppahpux.mh \
+ config/pa/hppahpux.mt config/pyr/pyramid.mh config/pyr/pyramid.mt \
+ config/romp/rtbsd.mh config/rs6000/rs6000.mh config/rs6000/rs6000.mt \
+ config/sh/sh.mt config/sparc/sparc-em.mt config/sparc/sparclite.mt \
+ config/sparc/sparclynx.mh config/sparc/sparclynx.mt \
+ config/sparc/sun4os4.mh config/sparc/sun4os4.mt \
+ config/sparc/sun4sol2.mh config/sparc/sun4sol2.mt \
+ config/sparc/vxsparc.mt config/tahoe/tahoe.mh config/tahoe/tahoe.mt \
+ config/vax/vax.mt config/vax/vaxbsd.mh config/vax/vaxult.mh \
+ config/vax/vaxult2.mh config/z8k/z8ksim.mt
+
+
+udip2soc.o: $(srcdir)/29k-share/udi/udip2soc.c $(udiheaders)
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/29k-share/udi/udip2soc.c
+
+udi2go32.o: $(srcdir)/29k-share/udi/udi2go32.c $(udiheaders)
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/29k-share/udi/udi2go32.c
+
+udr.o: $(srcdir)/29k-share/udi/udr.c $(udiheaders)
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/29k-share/udi/udr.c
+
+a29k-tdep.o: a29k-tdep.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h)
+
+a68v-nat.o: a68v-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+alpha-nat.o: alpha-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h
+
+alpha-tdep.o: alpha-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) $(symtab_h) $(dis-asm.h) gdb_string.h
+
+altos-xdep.o: altos-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+annotate.o: annotate.c $(defs_h) annotate.h $(value_h) target.h $(gdbtypes_h)
+
+arm-tdep.o: arm-tdep.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h)
+
+bcache.o: bcache.c bcache.h $(defs_h)
+
+blockframe.o: blockframe.c $(defs_h) $(gdbcore_h) $(inferior_h) \
+ objfiles.h symfile.h target.h
+
+breakpoint.o: breakpoint.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) language.h target.h thread.h gdb_string.h
+
+buildsym.o: buildsym.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+callback.o: callback.c $(defs_h) callback.h
+
+c-lang.o: c-lang.c c-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h)
+
+c-typeprint.o: c-typeprint.c c-lang.h $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
+ target.h typeprint.h $(value_h) gdb_string.h
+
+c-valprint.o: c-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h $(symtab_h) valprint.h $(value_h)
+
+f-lang.o: f-lang.c f-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h) gdb_string.h
+
+f-typeprint.o: f-typeprint.c f-lang.h $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
+ target.h typeprint.h $(value_h) gdb_string.h
+
+f-valprint.o: f-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h $(symtab_h) valprint.h $(value_h) gdb_string.h
+
+ch-exp.o: ch-exp.c ch-lang.h $(defs_h) language.h parser-defs.h $(bfd_h) symfile.h objfiles.h $(value_h)
+
+ch-lang.o: ch-lang.c ch-lang.h $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h)
+
+ch-typeprint.o: ch-typeprint.c ch-lang.h $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) \
+ target.h $(value_h) typeprint.h gdb_string.h
+
+ch-valprint.o: ch-valprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h $(symtab_h) valprint.h $(value_h) c-lang.h
+
+coff-solib.o: coff-solib.c $(defs_h)
+
+coffread.o: coffread.c $(bfd_h) $(breakpoint_h) buildsym.h \
+ complaints.h $(defs_h) $(expression_h) $(gdbtypes_h) objfiles.h \
+ symfile.h $(symtab_h) gdb-stabs.h stabsread.h target.h \
+ gdb_string.h
+
+command.o: command.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbtypes_h) $(symtab_h) $(value_h) gdb_string.h $(wait_h)
+
+complaints.o: complaints.c complaints.h $(defs_h) $(gdbcmd_h)
+
+convex-tdep.o: convex-tdep.c $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h)
+
+convex-xdep.o: convex-xdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h)
+
+copying.o: copying.c $(defs_h) $(gdbcmd_h)
+
+core-aout.o: core-aout.c $(defs_h) $(gdbcore_h) $(value_h) $(inferior_h)
+
+core-sol2.o: core-sol2.c $(command_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h gdb_string.h
+
+core-regset.o: core-regset.c $(command_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h gdb_string.h
+
+corefile.o: corefile.c $(dis-asm_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) target.h language.h gdb_string.h
+
+corelow.o: corelow.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h thread.h gdb_string.h
+
+cp-valprint.o: cp-valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbtypes_h) $(symtab_h) $(value_h) gdb_string.h
+
+dcache.o: dcache.c $(dcache_h) $(defs_h) $(gdbcmd_h) gdb_string.h
+
+dbxread.o: dbxread.c $(breakpoint_h) buildsym.h $(command_h) \
+ complaints.h $(defs_h) $(expression_h) gdb-stabs.h $(gdbcore_h) \
+ $(gdbtypes_h) language.h objfiles.h partial-stab.h stabsread.h \
+ symfile.h $(symtab_h) target.h gdb_string.h
+
+delta68-nat.o: delta68-nat.c $(defs_h)
+
+demangle.o: demangle.c $(defs_h) $(gdbcmd_h) gdb_string.h
+
+dpx2-nat.o: dpx2-nat.c $(defs_h) $(gdbcore_h) gdb_string.h
+
+dstread.o: dstread.c gdb_string.h
+
+dwarfread.o: dwarfread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ $(expression_h) $(gdbtypes_h) language.h objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+elfread.o: elfread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+environ.o: environ.c $(defs_h) environ.h $(gdbcore_h) gdb_string.h
+
+eval.o: eval.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
+ gdb_string.h
+
+exec.o: exec.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
+ target.h language.h gdb_string.h
+
+expprint.o: expprint.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h parser-defs.h $(symtab_h) $(value_h)
+
+findvar.o: findvar.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h
+
+fork-child.o: fork-child.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h thread.h gdb_string.h
+
+
+gdbtypes.o: gdbtypes.c $(bfd_h) complaints.h $(defs_h) $(expression_h) \
+ $(gdbtypes_h) language.h objfiles.h symfile.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h
+
+go32-xdep.o: go32-xdep.c
+
+gould-tdep.o: gould-tdep.c $(OP_INCLUDE)/np1.h $(defs_h) $(frame_h) \
+ $(gdbcore_h) $(symtab_h)
+
+gould-xdep.o: gould-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+h8300-tdep.o: h8300-tdep.c $(defs_h) $(frame_h) $(symtab_h)
+
+h8500-tdep.o: h8500-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h) \
+ $(expression_h) $(frame_h) $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) \
+ $(value_h)
+
+hp300ux-nat.o: hp300ux-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+hppa-tdep.o: hppa-tdep.c $(wait_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) objfiles.h symfile.h target.h
+
+hppab-nat.o: hppab-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h
+hppah-nat.o: hppah-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h
+
+i386-tdep.o: i386-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h
+
+i386aix-nat.o: i386aix-nat.c $(defs_h) $(frame_h) $(inferior_h) \
+ language.h $(gdbcore_h) $(floatformat_h) target.h
+
+i386b-nat.o: i386b-nat.c $(defs_h)
+
+i386ly-nat.o: i386ly-nat.c $(defs_h) $(frame_h) $(inferior_h) target.h
+
+i386ly-tdep.o: i386ly-tdep.c $(defs_h) $(inferior_h) target.h
+
+i386m3-nat.o: i386m3-nat.c $(defs_h) $(inferior_h) $(floatformat_h) target.h
+
+i386mach-nat.o: i386mach-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+i386v-nat.o: i386v-nat.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) language.h target.h
+
+i386v4-nat.o: i386v4-nat.c $(defs_h)
+
+i387-tdep.o: i387-tdep.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) language.h
+
+i960-tdep.o: i960-tdep.c $(floatformat_h) $(defs_h) $(expression_h) \
+ $(frame_h) $(gdbtypes_h) $(symtab_h) $(value_h)
+
+infcmd.o: infcmd.c $(defs_h) environ.h $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) target.h language.h gdb_string.h
+
+inflow.o: inflow.c $(bfd_h) $(command_h) $(defs_h) $(inferior_h) \
+ signals.h target.h terminal.h thread.h gdb_string.h
+
+infptrace.o: infptrace.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h $(wait_h) $(command_h)
+
+infrun.o: infrun.c $(wait_h) $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) target.h thread.h gdb_string.h
+
+inftarg.o: inftarg.c $(wait_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h terminal.h $(command_h)
+
+irix4-nat.o: irix4-nat.c $(defs_h) $(inferior_h) $(gdbcore_h)
+irix5-nat.o: irix5-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) target.h \
+ $(symtab_h) symfile.h objfiles.h $(command_h) $(frame_h) gnu-regex.h \
+ language.h gdb_string.h
+
+isi-xdep.o: isi-xdep.c
+
+language.o: language.c $(bfd_h) $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbtypes_h) language.h parser-defs.h $(symtab_h) \
+ target.h $(value_h) gdb_string.h
+
+lynx-nat.o: lynx-nat.c $(defs_h) $(frame_h) $(inferior_h) $(gdbcore_h) \
+ target.h
+
+m2-lang.o: m2-lang.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h m2-lang.h parser-defs.h $(symtab_h)
+
+m2-typeprint.o: m2-typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) language.h m2-lang.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h
+
+m2-valprint.o: m2-valprint.c $(defs_h) $(gdbtypes_h) $(symtab_h) \
+ valprint.h
+
+m3-nat.o: m3-nat.c $(defs_h) $(inferior_h) $(value_h) language.h target.h \
+ $(wait_h) $(gdbcmd_h) $(gdbcore_h)
+
+m68k-tdep.o: m68k-tdep.c $(defs_h) $(frame_h) $(symtab_h)
+
+m68kly-nat.o: m68kly-nat.c $(defs_h) $(frame_h) $(inferior_h) target.h
+
+m88k-nat.o: m88k-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+m88k-tdep.o: m88k-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+mac-nat.o: mac-nat.c $(defs_h) gdb_string.h
+
+main.o: main.c top.h $(defs_h) gdb_string.h
+
+maint.o: maint.c $(defs_h) $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) language.h \
+ $(expression_h) objfiles.h symfile.h
+
+mdebugread.o: mdebugread.c buildsym.h complaints.h $(bfd_h) $(defs_h) \
+ $(expression_h) gdb-stabs.h $(gdbcore_h) $(gdbtypes_h) language.h \
+ objfiles.h partial-stab.h stabsread.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+mipsm3-nat.o: mipsm3-nat.c $(defs_h) $(inferior_h)
+
+os9kread.o: os9kread.c buildsym.h complaints.h $(bfd_h) $(defs_h) \
+ $(expression_h) gdb-stabs.h $(gdbcore_h) $(gdbtypes_h) language.h \
+ objfiles.h partial-stab.h stabsread.h symfile.h $(symtab_h) \
+ target.h gdb_string.h
+
+mem-break.o: mem-break.c $(defs_h)
+
+minsyms.o: minsyms.c $(bfd_h) $(defs_h) objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+mips-nat.o: mips-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+mips-tdep.o: mips-tdep.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) language.h objfiles.h symfile.h gdb_string.h
+
+mipsread.o: mipsread.c buildsym.h complaints.h $(bfd_h) $(defs_h) \
+ $(expression_h) gdb-stabs.h $(gdbcore_h) $(gdbtypes_h) language.h \
+ objfiles.h partial-stab.h stabsread.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+mipsv4-nat.o: mipsv4-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h
+
+monitor.o: monitor.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h gdb_string.h
+
+news-xdep.o: news-xdep.c
+
+Onindy.o: nindy-share/Onindy.c $(wait_h) nindy-share/block_io.h \
+ nindy-share/env.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/Onindy.c
+
+nindy.o: nindy-share/nindy.c $(wait_h) nindy-share/block_io.h \
+ nindy-share/env.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/nindy.c
+
+nlmread.o: nlmread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) stabsread.h \
+ gdb_string.h
+
+ns32km3-nat.o: ns32km3-nat.c $(defs_h) $(inferior_h)
+
+ttyflush.o: nindy-share/ttyflush.c
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/nindy-share/ttyflush.c
+
+nindy-tdep.o: nindy-tdep.c $(defs_h) $(frame_h) $(symtab_h)
+
+ns32k-tdep.o: ns32k-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h)
+
+objfiles.o: objfiles.c $(bfd_h) $(defs_h) objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+osfsolib.o: osfsolib.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ objfiles.h gnu-regex.h symfile.h target.h language.h gdb_string.h
+
+somread.o: somread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+somsolib.o: somsolib.c $(defs_h)
+
+hpread.o: hpread.c $(bfd_h) buildsym.h complaints.h $(defs_h) \
+ gdb-stabs.h objfiles.h symfile.h $(symtab_h) gdb_string.h
+
+parse.o: parse.c $(command_h) $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \
+ gdb_string.h
+
+ppcbug-rom.o: ppcbug-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+printcmd.o: printcmd.c $(breakpoint_h) $(defs_h) $(expression_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \
+ symfile.h $(symtab_h) target.h gdb_string.h
+
+procfs.o: procfs.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h gdb_string.h
+
+pyr-tdep.o: pyr-tdep.c $(defs_h)
+
+pyr-xdep.o: pyr-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+gnu-regex.o: gnu-regex.c gnu-regex.h $(defs_h) gdb_string.h
+
+remote-adapt.o: remote-adapt.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h gdb_string.h
+
+remote-arc.o: remote-arc.c gdb_string.h
+
+remote-array.o: remote-array.c $(wait_h) $(defs_h) $(gdbcore_h) target.h \
+ gdb_string.h $(command_h) serial.h monitor.h $(remote_utils_h)
+
+remote-rdp.o: remote-rdp.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) gdb_string.h
+
+remote-bug.o: remote-bug.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h $(remote_utils_h) gdb_string.h
+
+remote-e7000.o: remote-e7000.c $(defs_h) $(gdbcore_h) target.h \
+ $(wait_h) serial.h gdb_string.h
+
+remote-eb.o: remote-eb.c $(wait_h) $(srcdir)/config/a29k/tm-a29k.h \
+ $(defs_h) $(gdbcore_h) $(inferior_h) symfile.h target.h terminal.h \
+ gdb_string.h
+
+remote-es.o: remote-es.c $(bfd_h) $(wait_h) $(command_h) $(defs_h) \
+ $(inferior_h) $(remote_utils_h) terminal.h gdb_string.h
+
+remote-hms.o: remote-hms.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) serial.h target.h terminal.h gdb_string.h
+
+remote-mips.o: remote-mips.c $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h) serial.h symfile.h target.h
+
+remote-mm.o: remote-mm.c $(bfd_h) $(wait_h) $(defs_h) $(inferior_h) \
+ minimon.h target.h terminal.h gdb_string.h
+
+remote-nindy.o: remote-nindy.c $(floatformat_h) $(wait_h) $(command_h) \
+ $(defs_h) $(gdbcore_h) $(inferior_h) \
+ nindy-share/env.h nindy-share/stop.h $(remote_utils_h) \
+ symfile.h
+
+remote-os9k.o: remote-os9k.c $(defs_h) $(gdbcore_h) $(wait_h) \
+ $(command_h) monitor.h $(remote_utils_h) $(symtab_h) symfile.h \
+ objfiles.h gdb-stabs.h gdb_string.h
+
+remote-sim.o: remote-sim.c $(wait_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) target.h terminal.h gdb_string.h
+
+remote-st.o: remote-st.c $(wait_h) $(defs_h) $(gdbcore_h) serial.h \
+ target.h gdb_string.h
+
+remote-udi.o: remote-udi.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h terminal.h $(udiheaders) gdb_string.h
+
+remote-vx.o: remote-vx.c $(wait_h) complaints.h $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h) target.h vx-share/dbgRpcLib.h \
+ vx-share/ptrace.h vx-share/xdr_ld.h vx-share/xdr_ptrace.h \
+ vx-share/xdr_rdb.h gdb-stabs.h objfiles.h symfile.h $(bfd_h) \
+ gdb_string.h
+
+remote-vx29k.o: remote-vx29k.c $(wait_h) complaints.h $(defs_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(inferior_h) target.h vx-share/dbgRpcLib.h \
+ vx-share/ptrace.h vx-share/xdr_ld.h vx-share/xdr_ptrace.h \
+ vx-share/xdr_rdb.h gdb_string.h
+
+remote-utils.o: remote-utils.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) \
+ $(inferior_h) $(remote_utils_h) gdb_string.h
+
+remote.o: remote.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) $(remote_utils_h) symfile.h terminal.h gdb_string.h
+
+remote-nrom.o: remote-nrom.c $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) $(remote_utils_h) symfile.h terminal.h
+
+rom68k-rom.o: rom68k-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+rs6000-nat.o: rs6000-nat.c $(bfd_h) $(defs_h) $(inferior_h) target.h
+
+rs6000-tdep.o: rs6000-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h) \
+ target.h xcoffsolib.h
+
+scm-exp.o: $(defs_h) $(value_h) parser-defs.h language.h c-lang.h \
+ scm-lang.h scm-tags.h
+
+scm-lang.o: $(defs_h) $(value_h) parser-defs.h language.h c-lang.h \
+ scm-lang.h scm-tags.h gdb_string.h
+
+scm-valprint.o: $(defs_h) $(value_h) parser-defs.h language.h \
+ scm-lang.h valprint.h
+
+ser-go32.o: ser-go32.c $(defs_h) serial.h
+
+ser-mac.o: ser-mac.c $(defs_h) serial.h signals.h
+
+ser-tcp.o: ser-tcp.c $(defs_h) serial.h signals.h gdb_string.h
+
+ser-unix.o: ser-unix.c $(defs_h) serial.h
+
+serial.o: serial.c $(defs_h) serial.h gdb_string.h
+
+sh-tdep.o: sh-tdep.c $(bfd_h) $(dis-asm_h) \
+ $(srcdir)/../opcodes/sh-opc.h $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbtypes_h) $(symtab_h) $(value_h)
+
+sh3-rom.o: sh3-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+mon960-rom.o: mon960-rom.c monitor.h $(bfd_h) $(wait_h) $(defs_h) $(gdbcmd_h) \
+ $(inferior_h) target.h serial.h terminal.h
+
+solib.o: solib.c $(command_h) $(defs_h) $(gdbcore_h) $(inferior_h) \
+ objfiles.h gnu-regex.h symfile.h target.h gdb_string.h
+
+source.o: source.c $(defs_h) $(expression_h) $(frame_h) $(gdbcmd_h) \
+ $(gdbcore_h) language.h objfiles.h gnu-regex.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+sparc-nat.o: sparc-nat.c $(bfd_h) $(defs_h) $(inferior_h) $(gdbcore_h) \
+ target.h
+
+sparc-tdep.o: sparc-tdep.c $(floatformat_h) $(defs_h) $(gdbcore_h) \
+ $(inferior_h) objfiles.h symfile.h target.h
+
+sparcl-tdep.o: sparcl-tdep.c $(defs_h) $(gdbcore_h) target.h
+
+dsrec.o: dsrec.c $(defs_h) srec.h
+
+stabsread.o: stabsread.c $(bfd_h) $(INCLUDE_DIR)/aout/stab.def \
+ $(INCLUDE_DIR)/aout/stab_gnu.h buildsym.h complaints.h $(defs_h) \
+ $(gdbtypes_h) objfiles.h stabsread.h symfile.h $(symtab_h) \
+ gdb_string.h
+
+stack.o: stack.c $(defs_h) $(gdbcmd_h) $(gdbcore_h) $(inferior_h) \
+ language.h target.h gdb_string.h
+
+sun3-nat.o: sun3-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+sun386-nat.o: sun386-nat.c $(defs_h) $(inferior_h) $(gdbcore_h)
+
+symfile.o: symfile.c $(breakpoint_h) complaints.h $(defs_h) \
+ $(expression_h) $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) \
+ language.h objfiles.h symfile.h $(symtab_h) target.h \
+ gdb_string.h
+
+symm-tdep.o: symm-tdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+symm-nat.o: symm-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+symmisc.o: symmisc.c $(bfd_h) $(breakpoint_h) $(command_h) $(defs_h) \
+ $(expression_h) $(gdbtypes_h) language.h objfiles.h symfile.h \
+ $(symtab_h) gdb_string.h
+
+symtab.o: symtab.c call-cmds.h $(defs_h) $(expression_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbcore_h) $(gdbtypes_h) language.h objfiles.h \
+ gnu-regex.h symfile.h $(symtab_h) target.h $(value_h) \
+ gdb_string.h
+
+tahoe-tdep.o: tahoe-tdep.c $(OP_INCLUDE)/tahoe.h $(defs_h) \
+ $(symtab_h)
+
+target.o: target.c $(bfd_h) $(defs_h) $(gdbcmd_h) $(inferior_h) \
+ objfiles.h symfile.h target.h gdb_string.h
+
+thread.o: thread.c $(defs_h) thread.h $(gdbcmd_h)
+
+top.o: top.c top.h $(bfd_h) $(getopt_h) $(readline_headers) call-cmds.h \
+ $(defs_h) $(gdbcmd_h) $(inferior_h) language.h signals.h \
+ $(remote_utils_h) gdb_string.h
+
+typeprint.o: typeprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h
+
+ultra3-nat.o: ultra3-nat.c $(defs_h) $(gdbcore_h) $(inferior_h)
+ultra3-xdep.o: ultra3-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+umax-xdep.o: umax-xdep.c $(defs_h) $(gdbcore_h) $(inferior_h)
+
+utils.o: utils.c $(bfd_h) $(defs_h) $(expression_h) $(gdbcmd_h) \
+ language.h signals.h target.h terminal.h $(readline_headers) \
+ gdb_string.h
+
+valarith.o: valarith.c $(bfd_h) $(defs_h) $(expression_h) \
+ $(gdbtypes_h) language.h $(symtab_h) target.h $(value_h) \
+ gdb_string.h
+
+valops.o: valops.c $(defs_h) $(gdbcore_h) $(inferior_h) target.h \
+ gdb_string.h
+
+valprint.o: valprint.c $(defs_h) $(expression_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) language.h $(symtab_h) target.h \
+ $(value_h) gdb_string.h
+
+values.o: values.c $(defs_h) $(expression_h) $(frame_h) $(gdbcmd_h) \
+ $(gdbcore_h) $(gdbtypes_h) $(symtab_h) target.h $(value_h) \
+ gdb_string.h scm-lang.h
+
+vax-tdep.o: vax-tdep.c $(OP_INCLUDE)/vax.h $(defs_h) $(symtab_h)
+
+w65-tdep.o : w65-tdep.c
+
+win32-nat.o: win32-nat.c $(gdbcmd_h) $(gdbcore_h) $(inferior_h) $(defs_h) \
+ gdb_string.h
+
+xdr_ld.o: vx-share/xdr_ld.c $(defs_h) vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/xdr_ld.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_ld.c
+
+xdr_ptrace.o: vx-share/xdr_ptrace.c $(defs_h) vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/xdr_ptrace.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_ptrace.c
+
+xdr_rdb.o: vx-share/xdr_rdb.c $(defs_h) vx-share/vxTypes.h \
+ vx-share/vxWorks.h vx-share/xdr_rdb.h
+ $(CC) -c $(INTERNAL_CFLAGS) $(srcdir)/vx-share/xdr_rdb.c
+
+xcoffread.o: xcoffread.c $(bfd_h) $(INCLUDE_DIR)/aout/stab.def \
+ $(INCLUDE_DIR)/aout/stab_gnu.h $(INCLUDE_DIR)/coff/internal.h \
+ $(INCLUDE_DIR)/coff/rs6000.h $(BFD_SRC)/libcoff.h buildsym.h \
+ complaints.h $(defs_h) $(gdbtypes_h) objfiles.h stabsread.h symfile.h \
+ $(symtab_h) partial-stab.h gdb_string.h
+
+xcoffsolib.o: xcoffsolib.c $(bfd_h) $(defs_h) xcoffsolib.h
+
+z8k-tdep.o: z8k-tdep.c $(bfd_h) $(dis-asm_h) $(defs_h) $(frame_h) \
+ $(gdbcmd_h) $(gdbtypes_h) $(symtab_h)
+
+c-exp.tab.o: c-exp.tab.c c-lang.h $(defs_h) $(expression_h) \
+ $(gdbtypes_h) language.h parser-defs.h $(symtab_h) $(value_h) \
+ $(bfd_h) objfiles.h symfile.h
+
+f-exp.tab.o: f-exp.tab.c f-lang.h $(defs_h) $(expression_h) \
+ language.h parser-defs.h $(value_h) $(bfd_h) objfiles.h symfile.h
+
+m2-exp.tab.o: m2-exp.tab.c $(defs_h) $(expression_h) $(gdbtypes_h) \
+ language.h m2-lang.h parser-defs.h $(symtab_h) $(value_h) \
+ $(bfd_h) objfiles.h symfile.h
+
+### end of the gdb Makefile.in.
diff --git a/contrib/gdb/gdb/NEWS b/contrib/gdb/gdb/NEWS
new file mode 100644
index 0000000..979a878
--- /dev/null
+++ b/contrib/gdb/gdb/NEWS
@@ -0,0 +1,1338 @@
+ What has changed in GDB?
+ (Organized release by release)
+
+*** Changes in GDB-4.16:
+
+* New native configurations
+
+Windows 95, x86 Windows NT i[345]86-*-cygwin32
+M68K NetBSD m68k-*-netbsd*
+PowerPC AIX 4.x powerpc-*-aix*
+PowerPC MacOS powerpc-*-macos*
+PowerPC Windows NT powerpcle-*-cygwin32
+RS/6000 AIX 4.x rs6000-*-aix4*
+
+* New targets
+
+ARM with RDP protocol arm-*-*
+I960 with MON960 i960-*-coff
+MIPS VxWorks mips*-*-vxworks*
+MIPS VR4300 with PMON mips64*vr4300{,el}-*-elf*
+PowerPC with PPCBUG monitor powerpc{,le}-*-eabi*
+Hitachi SH3 sh-*-*
+Matra Sparclet sparclet-*-*
+
+* PowerPC simulator
+
+The powerpc-eabi configuration now includes the PSIM simulator,
+contributed by Andrew Cagney, with assistance from Mike Meissner.
+PSIM is a very elaborate model of the PowerPC, including not only
+basic instruction set execution, but also details of execution unit
+performance and I/O hardware. See sim/ppc/README for more details.
+
+* Solaris 2.5
+
+GDB now works with Solaris 2.5.
+
+* Windows 95/NT native
+
+GDB will now work as a native debugger on Windows 95 and Windows NT.
+To build it from source, you must use the "gnu-win32" environment,
+which uses a DLL to emulate enough of Unix to run the GNU tools.
+Further information, binaries, and sources are available at
+ftp.cygnus.com, under pub/gnu-win32.
+
+* dont-repeat command
+
+If a user-defined command includes the command `dont-repeat', then the
+command will not be repeated if the user just types return. This is
+useful if the command is time-consuming to run, so that accidental
+extra keystrokes don't run the same command many times.
+
+* Send break instead of ^C
+
+The standard remote protocol now includes an option to send a break
+rather than a ^C to the target in order to interrupt it. By default,
+GDB will send ^C; to send a break, set the variable `remotebreak' to 1.
+
+* Remote protocol timeout
+
+The standard remote protocol includes a new variable `remotetimeout'
+that allows you to set the number of seconds before GDB gives up trying
+to read from the target. The default value is 2.
+
+* Automatic tracking of dynamic object loading (HPUX and Solaris only)
+
+By default GDB will automatically keep track of objects as they are
+loaded and unloaded by the dynamic linker. By using the command `set
+stop-on-solib-events 1' you can arrange for GDB to stop the inferior
+when shared library events occur, thus allowing you to set breakpoints
+in shared libraries which are explicitly loaded by the inferior.
+
+Note this feature does not work on hpux8. On hpux9 you must link
+/usr/lib/end.o into your program. This feature should work
+automatically on hpux10.
+
+* Irix 5.x hardware watchpoint support
+
+Irix 5 configurations now support the use of hardware watchpoints.
+
+* Mips protocol "SYN garbage limit"
+
+When debugging a Mips target using the `target mips' protocol, you
+may set the number of characters that GDB will ignore by setting
+the `syn-garbage-limit'. A value of -1 means that GDB will ignore
+every character. The default value is 1050.
+
+* Recording and replaying remote debug sessions
+
+If you set `remotelogfile' to the name of a file, gdb will write to it
+a recording of a remote debug session. This recording may then be
+replayed back to gdb using "gdbreplay". See gdbserver/README for
+details. This is useful when you have a problem with GDB while doing
+remote debugging; you can make a recording of the session and send it
+to someone else, who can then recreate the problem.
+
+* Speedups for remote debugging
+
+GDB includes speedups for downloading and stepping MIPS systems using
+the IDT monitor, fast downloads to the Hitachi SH E7000 emulator,
+and more efficient S-record downloading.
+
+* Memory use reductions and statistics collection
+
+GDB now uses less memory and reports statistics about memory usage.
+Try the `maint print statistics' command, for example.
+
+*** Changes in GDB-4.15:
+
+* Psymtabs for XCOFF
+
+The symbol reader for AIX GDB now uses partial symbol tables. This
+can greatly improve startup time, especially for large executables.
+
+* Remote targets use caching
+
+Remote targets now use a data cache to speed up communication with the
+remote side. The data cache could lead to incorrect results because
+it doesn't know about volatile variables, thus making it impossible to
+debug targets which use memory mapped I/O devices. `set remotecache
+off' turns the the data cache off.
+
+* Remote targets may have threads
+
+The standard remote protocol now includes support for multiple threads
+in the target system, using new protocol commands 'H' and 'T'. See
+gdb/remote.c for details.
+
+* NetROM support
+
+If GDB is configured with `--enable-netrom', then it will include
+support for the NetROM ROM emulator from XLNT Designs. The NetROM
+acts as though it is a bank of ROM on the target board, but you can
+write into it over the network. GDB's support consists only of
+support for fast loading into the emulated ROM; to debug, you must use
+another protocol, such as standard remote protocol. The usual
+sequence is something like
+
+ target nrom <netrom-hostname>
+ load <prog>
+ target remote <netrom-hostname>:1235
+
+* Macintosh host
+
+GDB now includes support for the Apple Macintosh, as a host only. It
+may be run as either an MPW tool or as a standalone application, and
+it can debug through the serial port. All the usual GDB commands are
+available, but to the target command, you must supply "serial" as the
+device type instead of "/dev/ttyXX". See mpw-README in the main
+directory for more information on how to build. The MPW configuration
+scripts */mpw-config.in support only a few targets, and only the
+mips-idt-ecoff target has been tested.
+
+* Autoconf
+
+GDB configuration now uses autoconf. This is not user-visible,
+but does simplify configuration and building.
+
+* hpux10
+
+GDB now supports hpux10.
+
+*** Changes in GDB-4.14:
+
+* New native configurations
+
+x86 FreeBSD i[345]86-*-freebsd
+x86 NetBSD i[345]86-*-netbsd
+NS32k NetBSD ns32k-*-netbsd
+Sparc NetBSD sparc-*-netbsd
+
+* New targets
+
+A29K VxWorks a29k-*-vxworks
+HP PA PRO embedded (WinBond W89K & Oki OP50N) hppa*-*-pro*
+CPU32 EST-300 emulator m68*-*-est*
+PowerPC ELF powerpc-*-elf
+WDC 65816 w65-*-*
+
+* Alpha OSF/1 support for procfs
+
+GDB now supports procfs under OSF/1-2.x and higher, which makes it
+possible to attach to running processes. As the mounting of the /proc
+filesystem is optional on the Alpha, GDB automatically determines
+the availability of /proc during startup. This can lead to problems
+if /proc is unmounted after GDB has been started.
+
+* Arguments to user-defined commands
+
+User commands may accept up to 10 arguments separated by whitespace.
+Arguments are accessed within the user command via $arg0..$arg9. A
+trivial example:
+define adder
+ print $arg0 + $arg1 + $arg2
+
+To execute the command use:
+adder 1 2 3
+
+Defines the command "adder" which prints the sum of its three arguments.
+Note the arguments are text substitutions, so they may reference variables,
+use complex expressions, or even perform inferior function calls.
+
+* New `if' and `while' commands
+
+This makes it possible to write more sophisticated user-defined
+commands. Both commands take a single argument, which is the
+expression to evaluate, and must be followed by the commands to
+execute, one per line, if the expression is nonzero, the list being
+terminated by the word `end'. The `if' command list may include an
+`else' word, which causes the following commands to be executed only
+if the expression is zero.
+
+* Fortran source language mode
+
+GDB now includes partial support for Fortran 77. It will recognize
+Fortran programs and can evaluate a subset of Fortran expressions, but
+variables and functions may not be handled correctly. GDB will work
+with G77, but does not yet know much about symbols emitted by other
+Fortran compilers.
+
+* Better HPUX support
+
+Most debugging facilities now work on dynamic executables for HPPAs
+running hpux9 or later. You can attach to running dynamically linked
+processes, but by default the dynamic libraries will be read-only, so
+for instance you won't be able to put breakpoints in them. To change
+that behavior do the following before running the program:
+
+ adb -w a.out
+ __dld_flags?W 0x5
+ control-d
+
+This will cause the libraries to be mapped private and read-write.
+To revert to the normal behavior, do this:
+
+ adb -w a.out
+ __dld_flags?W 0x4
+ control-d
+
+You cannot set breakpoints or examine data in the library until after
+the library is loaded if the function/data symbols do not have
+external linkage.
+
+GDB can now also read debug symbols produced by the HP C compiler on
+HPPAs (sorry, no C++, Fortran or 68k support).
+
+* Target byte order now dynamically selectable
+
+You can choose which byte order to use with a target system, via the
+commands "set endian big" and "set endian little", and you can see the
+current setting by using "show endian". You can also give the command
+"set endian auto", in which case GDB will use the byte order
+associated with the executable. Currently, only embedded MIPS
+configurations support dynamic selection of target byte order.
+
+* New DOS host serial code
+
+This version uses DPMI interrupts to handle buffered I/O, so you
+no longer need to run asynctsr when debugging boards connected to
+a PC's serial port.
+
+*** Changes in GDB-4.13:
+
+* New "complete" command
+
+This lists all the possible completions for the rest of the line, if it
+were to be given as a command itself. This is intended for use by emacs.
+
+* Trailing space optional in prompt
+
+"set prompt" no longer adds a space for you after the prompt you set. This
+allows you to set a prompt which ends in a space or one that does not.
+
+* Breakpoint hit counts
+
+"info break" now displays a count of the number of times the breakpoint
+has been hit. This is especially useful in conjunction with "ignore"; you
+can ignore a large number of breakpoint hits, look at the breakpoint info
+to see how many times the breakpoint was hit, then run again, ignoring one
+less than that number, and this will get you quickly to the last hit of
+that breakpoint.
+
+* Ability to stop printing at NULL character
+
+"set print null-stop" will cause GDB to stop printing the characters of
+an array when the first NULL is encountered. This is useful when large
+arrays actually contain only short strings.
+
+* Shared library breakpoints
+
+In SunOS 4.x, SVR4, and Alpha OSF/1 configurations, you can now set
+breakpoints in shared libraries before the executable is run.
+
+* Hardware watchpoints
+
+There is a new hardware breakpoint for the watch command for sparclite
+targets. See gdb/sparclite/hw_breakpoint.note.
+
+Hardware watchpoints are also now supported under Linux.
+
+* Annotations
+
+Annotations have been added. These are for use with graphical interfaces,
+and are still experimental. Currently only gdba.el uses these.
+
+* Improved Irix 5 support
+
+GDB now works properly with Irix 5.2.
+
+* Improved HPPA support
+
+GDB now works properly with the latest GCC and GAS.
+
+* New native configurations
+
+Sequent PTX4 i[34]86-sequent-ptx4
+HPPA running OSF/1 hppa*-*-osf*
+Atari TT running SVR4 m68*-*-sysv4*
+RS/6000 LynxOS rs6000-*-lynxos*
+
+* New targets
+
+OS/9000 i[34]86-*-os9k
+MIPS R4000 mips64*{,el}-*-{ecoff,elf}
+Sparc64 sparc64-*-*
+
+* Hitachi SH7000 and E7000-PC ICE support
+
+There is now support for communicating with the Hitachi E7000-PC ICE.
+This is available automatically when GDB is configured for the SH.
+
+* Fixes
+
+As usual, a variety of small fixes and improvements, both generic
+and configuration-specific. See the ChangeLog for more detail.
+
+*** Changes in GDB-4.12:
+
+* Irix 5 is now supported
+
+* HPPA support
+
+GDB-4.12 on the HPPA has a number of changes which make it unable
+to debug the output from the currently released versions of GCC and
+GAS (GCC 2.5.8 and GAS-2.2 or PAGAS-1.36). Until the next major release
+of GCC and GAS, versions of these tools designed to work with GDB-4.12
+can be retrieved via anonymous ftp from jaguar.cs.utah.edu:/dist.
+
+
+*** Changes in GDB-4.11:
+
+* User visible changes:
+
+* Remote Debugging
+
+The "set remotedebug" option is now consistent between the mips remote
+target, remote targets using the gdb-specific protocol, UDI (AMD's
+debug protocol for the 29k) and the 88k bug monitor. It is now an
+integer specifying a debug level (normally 0 or 1, but 2 means more
+debugging info for the mips target).
+
+* DEC Alpha native support
+
+GDB now works on the DEC Alpha. GCC 2.4.5 does not produce usable
+debug info, but GDB works fairly well with the DEC compiler and should
+work with a future GCC release. See the README file for a few
+Alpha-specific notes.
+
+* Preliminary thread implementation
+
+GDB now has preliminary thread support for both SGI/Irix and LynxOS.
+
+* LynxOS native and target support for 386
+
+This release has been hosted on LynxOS 2.2, and also can be configured
+to remotely debug programs running under LynxOS (see gdb/gdbserver/README
+for details).
+
+* Improvements in C++ mangling/demangling.
+
+This release has much better g++ debugging, specifically in name
+mangling/demangling, virtual function calls, print virtual table,
+call methods, ...etc.
+
+*** Changes in GDB-4.10:
+
+ * User visible changes:
+
+Remote debugging using the GDB-specific (`target remote') protocol now
+supports the `load' command. This is only useful if you have some
+other way of getting the stub to the target system, and you can put it
+somewhere in memory where it won't get clobbered by the download.
+
+Filename completion now works.
+
+When run under emacs mode, the "info line" command now causes the
+arrow to point to the line specified. Also, "info line" prints
+addresses in symbolic form (as well as hex).
+
+All vxworks based targets now support a user settable option, called
+vxworks-timeout. This option represents the number of seconds gdb
+should wait for responses to rpc's. You might want to use this if
+your vxworks target is, perhaps, a slow software simulator or happens
+to be on the far side of a thin network line.
+
+ * DEC alpha support
+
+This release contains support for using a DEC alpha as a GDB host for
+cross debugging. Native alpha debugging is not supported yet.
+
+
+*** Changes in GDB-4.9:
+
+ * Testsuite
+
+This is the first GDB release which is accompanied by a matching testsuite.
+The testsuite requires installation of dejagnu, which should be available
+via ftp from most sites that carry GNU software.
+
+ * C++ demangling
+
+'Cfront' style demangling has had its name changed to 'ARM' style, to
+emphasize that it was written from the specifications in the C++ Annotated
+Reference Manual, not necessarily to be compatible with AT&T cfront. Despite
+disclaimers, it still generated too much confusion with users attempting to
+use gdb with AT&T cfront.
+
+ * Simulators
+
+GDB now uses a standard remote interface to a simulator library.
+So far, the library contains simulators for the Zilog Z8001/2, the
+Hitachi H8/300, H8/500 and Super-H.
+
+ * New targets supported
+
+H8/300 simulator h8300-hitachi-hms or h8300hms
+H8/500 simulator h8500-hitachi-hms or h8500hms
+SH simulator sh-hitachi-hms or sh
+Z8000 simulator z8k-zilog-none or z8ksim
+IDT MIPS board over serial line mips-idt-ecoff
+
+Cross-debugging to GO32 targets is supported. It requires a custom
+version of the i386-stub.c module which is integrated with the
+GO32 memory extender.
+
+ * New remote protocols
+
+MIPS remote debugging protocol.
+
+ * New source languages supported
+
+This version includes preliminary support for Chill, a Pascal like language
+used by telecommunications companies. Chill support is also being integrated
+into the GNU compiler, but we don't know when it will be publically available.
+
+
+*** Changes in GDB-4.8:
+
+ * HP Precision Architecture supported
+
+GDB now supports HP PA-RISC machines running HPUX. A preliminary
+version of this support was available as a set of patches from the
+University of Utah. GDB does not support debugging of programs
+compiled with the HP compiler, because HP will not document their file
+format. Instead, you must use GCC (version 2.3.2 or later) and PA-GAS
+(as available from jaguar.cs.utah.edu:/dist/pa-gas.u4.tar.Z).
+
+Many problems in the preliminary version have been fixed.
+
+ * Faster and better demangling
+
+We have improved template demangling and fixed numerous bugs in the GNU style
+demangler. It can now handle type modifiers such as `static' or `const'. Wide
+character types (wchar_t) are now supported. Demangling of each symbol is now
+only done once, and is cached when the symbol table for a file is read in.
+This results in a small increase in memory usage for C programs, a moderate
+increase in memory usage for C++ programs, and a fantastic speedup in
+symbol lookups.
+
+`Cfront' style demangling still doesn't work with AT&T cfront. It was written
+from the specifications in the Annotated Reference Manual, which AT&T's
+compiler does not actually implement.
+
+ * G++ multiple inheritance compiler problem
+
+In the 2.3.2 release of gcc/g++, how the compiler resolves multiple
+inheritance lattices was reworked to properly discover ambiguities. We
+recently found an example which causes this new algorithm to fail in a
+very subtle way, producing bad debug information for those classes.
+The file 'gcc.patch' (in this directory) can be applied to gcc to
+circumvent the problem. A future GCC release will contain a complete
+fix.
+
+The previous G++ debug info problem (mentioned below for the gdb-4.7
+release) is fixed in gcc version 2.3.2.
+
+ * Improved configure script
+
+The `configure' script will now attempt to guess your system type if
+you don't supply a host system type. The old scheme of supplying a
+host system triplet is preferable over using this. All the magic is
+done in the new `config.guess' script. Examine it for details.
+
+We have also brought our configure script much more in line with the FSF's
+version. It now supports the --with-xxx options. In particular,
+`--with-minimal-bfd' can be used to make the GDB binary image smaller.
+The resulting GDB will not be able to read arbitrary object file formats --
+only the format ``expected'' to be used on the configured target system.
+We hope to make this the default in a future release.
+
+ * Documentation improvements
+
+There's new internal documentation on how to modify GDB, and how to
+produce clean changes to the code. We implore people to read it
+before submitting changes.
+
+The GDB manual uses new, sexy Texinfo conditionals, rather than arcane
+M4 macros. The new texinfo.tex is provided in this release. Pre-built
+`info' files are also provided. To build `info' files from scratch,
+you will need the latest `makeinfo' release, which will be available in
+a future texinfo-X.Y release.
+
+*NOTE* The new texinfo.tex can cause old versions of TeX to hang.
+We're not sure exactly which versions have this problem, but it has
+been seen in 3.0. We highly recommend upgrading to TeX version 3.141
+or better. If that isn't possible, there is a patch in
+`texinfo/tex3patch' that will modify `texinfo/texinfo.tex' to work
+around this problem.
+
+ * New features
+
+GDB now supports array constants that can be used in expressions typed in by
+the user. The syntax is `{element, element, ...}'. Ie: you can now type
+`print {1, 2, 3}', and it will build up an array in memory malloc'd in
+the target program.
+
+The new directory `gdb/sparclite' contains a program that demonstrates
+how the sparc-stub.c remote stub runs on a Fujitsu SPARClite processor.
+
+ * New native hosts supported
+
+HP/PA-RISC under HPUX using GNU tools hppa1.1-hp-hpux
+386 CPUs running SCO Unix 3.2v4 i386-unknown-sco3.2v4
+
+ * New targets supported
+
+AMD 29k family via UDI a29k-amd-udi or udi29k
+
+ * New file formats supported
+
+BFD now supports reading HP/PA-RISC executables (SOM file format?),
+HPUX core files, and SCO 3.2v2 core files.
+
+ * Major bug fixes
+
+Attaching to processes now works again; thanks for the many bug reports.
+
+We have also stomped on a bunch of core dumps caused by
+printf_filtered("%s") problems.
+
+We eliminated a copyright problem on the rpc and ptrace header files
+for VxWorks, which was discovered at the last minute during the 4.7
+release. You should now be able to build a VxWorks GDB.
+
+You can now interrupt gdb while an attached process is running. This
+will cause the attached process to stop, and give control back to GDB.
+
+We fixed problems caused by using too many file descriptors
+for reading symbols from object files and libraries. This was
+especially a problem for programs that used many (~100) shared
+libraries.
+
+The `step' command now only enters a subroutine if there is line number
+information for the subroutine. Otherwise it acts like the `next'
+command. Previously, `step' would enter subroutines if there was
+any debugging information about the routine. This avoids problems
+when using `cc -g1' on MIPS machines.
+
+ * Internal improvements
+
+GDB's internal interfaces have been improved to make it easier to support
+debugging of multiple languages in the future.
+
+GDB now uses a common structure for symbol information internally.
+Minimal symbols (derived from linkage symbols in object files), partial
+symbols (from a quick scan of debug information), and full symbols
+contain a common subset of information, making it easier to write
+shared code that handles any of them.
+
+ * New command line options
+
+We now accept --silent as an alias for --quiet.
+
+ * Mmalloc licensing
+
+The memory-mapped-malloc library is now licensed under the GNU Library
+General Public License.
+
+*** Changes in GDB-4.7:
+
+ * Host/native/target split
+
+GDB has had some major internal surgery to untangle the support for
+hosts and remote targets. Now, when you configure GDB for a remote
+target, it will no longer load in all of the support for debugging
+local programs on the host. When fully completed and tested, this will
+ensure that arbitrary host/target combinations are possible.
+
+The primary conceptual shift is to separate the non-portable code in
+GDB into three categories. Host specific code is required any time GDB
+is compiled on that host, regardless of the target. Target specific
+code relates to the peculiarities of the target, but can be compiled on
+any host. Native specific code is everything else: it can only be
+built when the host and target are the same system. Child process
+handling and core file support are two common `native' examples.
+
+GDB's use of /proc for controlling Unix child processes is now cleaner.
+It has been split out into a single module under the `target_ops' vector,
+plus two native-dependent functions for each system that uses /proc.
+
+ * New hosts supported
+
+HP/Apollo 68k (under the BSD domain) m68k-apollo-bsd or apollo68bsd
+386 CPUs running various BSD ports i386-unknown-bsd or 386bsd
+386 CPUs running SCO Unix i386-unknown-scosysv322 or i386sco
+
+ * New targets supported
+
+Fujitsu SPARClite sparclite-fujitsu-none or sparclite
+68030 and CPU32 m68030-*-*, m68332-*-*
+
+ * New native hosts supported
+
+386 CPUs running various BSD ports i386-unknown-bsd or 386bsd
+ (386bsd is not well tested yet)
+386 CPUs running SCO Unix i386-unknown-scosysv322 or sco
+
+ * New file formats supported
+
+BFD now supports COFF files for the Zilog Z8000 microprocessor. It
+supports reading of `a.out.adobe' object files, which are an a.out
+format extended with minimal information about multiple sections.
+
+ * New commands
+
+`show copying' is the same as the old `info copying'.
+`show warranty' is the same as `info warrantee'.
+These were renamed for consistency. The old commands continue to work.
+
+`info handle' is a new alias for `info signals'.
+
+You can now define pre-command hooks, which attach arbitrary command
+scripts to any command. The commands in the hook will be executed
+prior to the user's command. You can also create a hook which will be
+executed whenever the program stops. See gdb.texinfo.
+
+ * C++ improvements
+
+We now deal with Cfront style name mangling, and can even extract type
+info from mangled symbols. GDB can automatically figure out which
+symbol mangling style your C++ compiler uses.
+
+Calling of methods and virtual functions has been improved as well.
+
+ * Major bug fixes
+
+The crash that occured when debugging Sun Ansi-C compiled binaries is
+fixed. This was due to mishandling of the extra N_SO stabs output
+by the compiler.
+
+We also finally got Ultrix 4.2 running in house, and fixed core file
+support, with help from a dozen people on the net.
+
+John M. Farrell discovered that the reason that single-stepping was so
+slow on all of the Mips based platforms (primarily SGI and DEC) was
+that we were trying to demangle and lookup a symbol used for internal
+purposes on every instruction that was being stepped through. Changing
+the name of that symbol so that it couldn't be mistaken for a C++
+mangled symbol sped things up a great deal.
+
+Rich Pixley sped up symbol lookups in general by getting much smarter
+about when C++ symbol mangling is necessary. This should make symbol
+completion (TAB on the command line) much faster. It's not as fast as
+we'd like, but it's significantly faster than gdb-4.6.
+
+ * AMD 29k support
+
+A new user controllable variable 'call_scratch_address' can
+specify the location of a scratch area to be used when GDB
+calls a function in the target. This is necessary because the
+usual method of putting the scratch area on the stack does not work
+in systems that have separate instruction and data spaces.
+
+We integrated changes to support the 29k UDI (Universal Debugger
+Interface), but discovered at the last minute that we didn't have all
+of the appropriate copyright paperwork. We are working with AMD to
+resolve this, and hope to have it available soon.
+
+ * Remote interfaces
+
+We have sped up the remote serial line protocol, especially for targets
+with lots of registers. It now supports a new `expedited status' ('T')
+message which can be used in place of the existing 'S' status message.
+This allows the remote stub to send only the registers that GDB
+needs to make a quick decision about single-stepping or conditional
+breakpoints, eliminating the need to fetch the entire register set for
+each instruction being stepped through.
+
+The GDB remote serial protocol now implements a write-through cache for
+registers, only re-reading the registers if the target has run.
+
+There is also a new remote serial stub for SPARC processors. You can
+find it in gdb-4.7/gdb/sparc-stub.c. This was written to support the
+Fujitsu SPARClite processor, but will run on any stand-alone SPARC
+processor with a serial port.
+
+ * Configuration
+
+Configure.in files have become much easier to read and modify. A new
+`table driven' format makes it more obvious what configurations are
+supported, and what files each one uses.
+
+ * Library changes
+
+There is a new opcodes library which will eventually contain all of the
+disassembly routines and opcode tables. At present, it only contains
+Sparc and Z8000 routines. This will allow the assembler, debugger, and
+disassembler (binutils/objdump) to share these routines.
+
+The libiberty library is now copylefted under the GNU Library General
+Public License. This allows more liberal use, and was done so libg++
+can use it. This makes no difference to GDB, since the Library License
+grants all the rights from the General Public License.
+
+ * Documentation
+
+The file gdb-4.7/gdb/doc/stabs.texinfo is a (relatively) complete
+reference to the stabs symbol info used by the debugger. It is (as far
+as we know) the only published document on this fascinating topic. We
+encourage you to read it, compare it to the stabs information on your
+system, and send improvements on the document in general (to
+bug-gdb@prep.ai.mit.edu).
+
+And, of course, many bugs have been fixed.
+
+
+*** Changes in GDB-4.6:
+
+ * Better support for C++ function names
+
+GDB now accepts as input the "demangled form" of C++ overloaded function
+names and member function names, and can do command completion on such names
+(using TAB, TAB-TAB, and ESC-?). The names have to be quoted with a pair of
+single quotes. Examples are 'func (int, long)' and 'obj::operator==(obj&)'.
+Make use of command completion, it is your friend.
+
+GDB also now accepts a variety of C++ mangled symbol formats. They are
+the GNU g++ style, the Cfront (ARM) style, and the Lucid (lcc) style.
+You can tell GDB which format to use by doing a 'set demangle-style {gnu,
+lucid, cfront, auto}'. 'gnu' is the default. Do a 'set demangle-style foo'
+for the list of formats.
+
+ * G++ symbol mangling problem
+
+Recent versions of gcc have a bug in how they emit debugging information for
+C++ methods (when using dbx-style stabs). The file 'gcc.patch' (in this
+directory) can be applied to gcc to fix the problem. Alternatively, if you
+can't fix gcc, you can #define GCC_MANGLE_BUG when compling gdb/symtab.c. The
+usual symptom is difficulty with setting breakpoints on methods. GDB complains
+about the method being non-existent. (We believe that version 2.2.2 of GCC has
+this problem.)
+
+ * New 'maintenance' command
+
+All of the commands related to hacking GDB internals have been moved out of
+the main command set, and now live behind the 'maintenance' command. This
+can also be abbreviated as 'mt'. The following changes were made:
+
+ dump-me -> maintenance dump-me
+ info all-breakpoints -> maintenance info breakpoints
+ printmsyms -> maintenance print msyms
+ printobjfiles -> maintenance print objfiles
+ printpsyms -> maintenance print psymbols
+ printsyms -> maintenance print symbols
+
+The following commands are new:
+
+ maintenance demangle Call internal GDB demangler routine to
+ demangle a C++ link name and prints the result.
+ maintenance print type Print a type chain for a given symbol
+
+ * Change to .gdbinit file processing
+
+We now read the $HOME/.gdbinit file before processing the argv arguments
+(e.g. reading symbol files or core files). This allows global parameters to
+be set, which will apply during the symbol reading. The ./.gdbinit is still
+read after argv processing.
+
+ * New hosts supported
+
+Solaris-2.0 !!! sparc-sun-solaris2 or sun4sol2
+
+Linux support i386-unknown-linux or linux
+
+We are also including code to support the HP/PA running BSD and HPUX. This
+is almost guaranteed not to work, as we didn't have time to test or build it
+for this release. We are including it so that the more adventurous (or
+masochistic) of you can play with it. We also had major problems with the
+fact that the compiler that we got from HP doesn't support the -g option.
+It costs extra.
+
+ * New targets supported
+
+Hitachi H8/300 h8300-hitachi-hms or h8300hms
+
+ * More smarts about finding #include files
+
+GDB now remembers the compilation directory for all include files, and for
+all files from which C is generated (like yacc and lex sources). This
+greatly improves GDB's ability to find yacc/lex sources, and include files,
+especially if you are debugging your program from a directory different from
+the one that contains your sources.
+
+We also fixed a bug which caused difficulty with listing and setting
+breakpoints in include files which contain C code. (In the past, you had to
+try twice in order to list an include file that you hadn't looked at before.)
+
+ * Interesting infernals change
+
+GDB now deals with arbitrary numbers of sections, where the symbols for each
+section must be relocated relative to that section's landing place in the
+target's address space. This work was needed to support ELF with embedded
+stabs used by Solaris-2.0.
+
+ * Bug fixes (of course!)
+
+There have been loads of fixes for the following things:
+ mips, rs6000, 29k/udi, m68k, g++, type handling, elf/dwarf, m88k,
+ i960, stabs, DOS(GO32), procfs, etc...
+
+See the ChangeLog for details.
+
+*** Changes in GDB-4.5:
+
+ * New machines supported (host and target)
+
+IBM RS6000 running AIX rs6000-ibm-aix or rs6000
+
+SGI Irix-4.x mips-sgi-irix4 or iris4
+
+ * New malloc package
+
+GDB now uses a new memory manager called mmalloc, based on gmalloc.
+Mmalloc is capable of handling mutiple heaps of memory. It is also
+capable of saving a heap to a file, and then mapping it back in later.
+This can be used to greatly speedup the startup of GDB by using a
+pre-parsed symbol table which lives in a mmalloc managed heap. For
+more details, please read mmalloc/mmalloc.texi.
+
+ * info proc
+
+The 'info proc' command (SVR4 only) has been enhanced quite a bit. See
+'help info proc' for details.
+
+ * MIPS ecoff symbol table format
+
+The code that reads MIPS symbol table format is now supported on all hosts.
+Thanks to MIPS for releasing the sym.h and symconst.h files to make this
+possible.
+
+ * File name changes for MS-DOS
+
+Many files in the config directories have been renamed to make it easier to
+support GDB on MS-DOSe systems (which have very restrictive file name
+conventions :-( ). MS-DOSe host support (under DJ Delorie's GO32
+environment) is close to working but has some remaining problems. Note
+that debugging of DOS programs is not supported, due to limitations
+in the ``operating system'', but it can be used to host cross-debugging.
+
+ * Cross byte order fixes
+
+Many fixes have been made to support cross debugging of Sparc and MIPS
+targets from hosts whose byte order differs.
+
+ * New -mapped and -readnow options
+
+If memory-mapped files are available on your system through the 'mmap'
+system call, you can use the -mapped option on the `file' or
+`symbol-file' commands to cause GDB to write the symbols from your
+program into a reusable file. If the program you are debugging is
+called `/path/fred', the mapped symbol file will be `./fred.syms'.
+Future GDB debugging sessions will notice the presence of this file,
+and will quickly map in symbol information from it, rather than reading
+the symbol table from the executable program. Using the '-mapped'
+option in a GDB `file' or `symbol-file' command has the same effect as
+starting GDB with the '-mapped' command-line option.
+
+You can cause GDB to read the entire symbol table immediately by using
+the '-readnow' option with any of the commands that load symbol table
+information (or on the GDB command line). This makes the command
+slower, but makes future operations faster.
+
+The -mapped and -readnow options are typically combined in order to
+build a `fred.syms' file that contains complete symbol information.
+A simple GDB invocation to do nothing but build a `.syms' file for future
+use is:
+
+ gdb -batch -nx -mapped -readnow programname
+
+The `.syms' file is specific to the host machine on which GDB is run.
+It holds an exact image of GDB's internal symbol table. It cannot be
+shared across multiple host platforms.
+
+ * longjmp() handling
+
+GDB is now capable of stepping and nexting over longjmp(), _longjmp(), and
+siglongjmp() without losing control. This feature has not yet been ported to
+all systems. It currently works on many 386 platforms, all MIPS-based
+platforms (SGI, DECstation, etc), and Sun3/4.
+
+ * Solaris 2.0
+
+Preliminary work has been put in to support the new Solaris OS from Sun. At
+this time, it can control and debug processes, but it is not capable of
+reading symbols.
+
+ * Bug fixes
+
+As always, many many bug fixes. The major areas were with g++, and mipsread.
+People using the MIPS-based platforms should experience fewer mysterious
+crashes and trashed symbol tables.
+
+*** Changes in GDB-4.4:
+
+ * New machines supported (host and target)
+
+SCO Unix on i386 IBM PC clones i386-sco-sysv or i386sco
+ (except core files)
+BSD Reno on Vax vax-dec-bsd
+Ultrix on Vax vax-dec-ultrix
+
+ * New machines supported (target)
+
+AMD 29000 embedded, using EBMON a29k-none-none
+
+ * C++ support
+
+GDB continues to improve its handling of C++. `References' work better.
+The demangler has also been improved, and now deals with symbols mangled as
+per the Annotated C++ Reference Guide.
+
+GDB also now handles `stabs' symbol information embedded in MIPS
+`ecoff' symbol tables. Since the ecoff format was not easily
+extensible to handle new languages such as C++, this appeared to be a
+good way to put C++ debugging info into MIPS binaries. This option
+will be supported in the GNU C compiler, version 2, when it is
+released.
+
+ * New features for SVR4
+
+GDB now handles SVR4 shared libraries, in the same fashion as SunOS
+shared libraries. Debugging dynamically linked programs should present
+only minor differences from debugging statically linked programs.
+
+The `info proc' command will print out information about any process
+on an SVR4 system (including the one you are debugging). At the moment,
+it prints the address mappings of the process.
+
+If you bring up GDB on another SVR4 system, please send mail to
+bug-gdb@prep.ai.mit.edu to let us know what changes were reqired (if any).
+
+ * Better dynamic linking support in SunOS
+
+Reading symbols from shared libraries which contain debugging symbols
+now works properly. However, there remain issues such as automatic
+skipping of `transfer vector' code during function calls, which
+make it harder to debug code in a shared library, than to debug the
+same code linked statically.
+
+ * New Getopt
+
+GDB is now using the latest `getopt' routines from the FSF. This
+version accepts the -- prefix for options with long names. GDB will
+continue to accept the old forms (-option and +option) as well.
+Various single letter abbreviations for options have been explicity
+added to the option table so that they won't get overshadowed in the
+future by other options that begin with the same letter.
+
+ * Bugs fixed
+
+The `cleanup_undefined_types' bug that many of you noticed has been squashed.
+Many assorted bugs have been handled. Many more remain to be handled.
+See the various ChangeLog files (primarily in gdb and bfd) for details.
+
+
+*** Changes in GDB-4.3:
+
+ * New machines supported (host and target)
+
+Amiga 3000 running Amix m68k-cbm-svr4 or amix
+NCR 3000 386 running SVR4 i386-ncr-svr4 or ncr3000
+Motorola Delta 88000 running Sys V m88k-motorola-sysv or delta88
+
+ * Almost SCO Unix support
+
+We had hoped to support:
+SCO Unix on i386 IBM PC clones i386-sco-sysv or i386sco
+(except for core file support), but we discovered very late in the release
+that it has problems with process groups that render gdb unusable. Sorry
+about that. I encourage people to fix it and post the fixes.
+
+ * Preliminary ELF and DWARF support
+
+GDB can read ELF object files on System V Release 4, and can handle
+debugging records for C, in DWARF format, in ELF files. This support
+is preliminary. If you bring up GDB on another SVR4 system, please
+send mail to bug-gdb@prep.ai.mit.edu to let us know what changes were
+reqired (if any).
+
+ * New Readline
+
+GDB now uses the latest `readline' library. One user-visible change
+is that two tabs will list possible command completions, which previously
+required typing M-? (meta-question mark, or ESC ?).
+
+ * Bugs fixed
+
+The `stepi' bug that many of you noticed has been squashed.
+Many bugs in C++ have been handled. Many more remain to be handled.
+See the various ChangeLog files (primarily in gdb and bfd) for details.
+
+ * State of the MIPS world (in case you wondered):
+
+GDB can understand the symbol tables emitted by the compilers
+supplied by most vendors of MIPS-based machines, including DEC. These
+symbol tables are in a format that essentially nobody else uses.
+
+Some versions of gcc come with an assembler post-processor called
+mips-tfile. This program is required if you want to do source-level
+debugging of gcc-compiled programs. I believe FSF does not ship
+mips-tfile with gcc version 1, but it will eventually come with gcc
+version 2.
+
+Debugging of g++ output remains a problem. g++ version 1.xx does not
+really support it at all. (If you're lucky, you should be able to get
+line numbers and stack traces to work, but no parameters or local
+variables.) With some work it should be possible to improve the
+situation somewhat.
+
+When gcc version 2 is released, you will have somewhat better luck.
+However, even then you will get confusing results for inheritance and
+methods.
+
+We will eventually provide full debugging of g++ output on
+DECstations. This will probably involve some kind of stabs-in-ecoff
+encapulation, but the details have not been worked out yet.
+
+
+*** Changes in GDB-4.2:
+
+ * Improved configuration
+
+Only one copy of `configure' exists now, and it is not self-modifying.
+Porting BFD is simpler.
+
+ * Stepping improved
+
+The `step' and `next' commands now only stop at the first instruction
+of a source line. This prevents the multiple stops that used to occur
+in switch statements, for-loops, etc. `Step' continues to stop if a
+function that has debugging information is called within the line.
+
+ * Bug fixing
+
+Lots of small bugs fixed. More remain.
+
+ * New host supported (not target)
+
+Intel 386 PC clone running Mach i386-none-mach
+
+
+*** Changes in GDB-4.1:
+
+ * Multiple source language support
+
+GDB now has internal scaffolding to handle several source languages.
+It determines the type of each source file from its filename extension,
+and will switch expression parsing and number formatting to match the
+language of the function in the currently selected stack frame.
+You can also specifically set the language to be used, with
+`set language c' or `set language modula-2'.
+
+ * GDB and Modula-2
+
+GDB now has preliminary support for the GNU Modula-2 compiler,
+currently under development at the State University of New York at
+Buffalo. Development of both GDB and the GNU Modula-2 compiler will
+continue through the fall of 1991 and into 1992.
+
+Other Modula-2 compilers are currently not supported, and attempting to
+debug programs compiled with them will likely result in an error as the
+symbol table is read. Feel free to work on it, though!
+
+There are hooks in GDB for strict type checking and range checking,
+in the `Modula-2 philosophy', but they do not currently work.
+
+ * set write on/off
+
+GDB can now write to executable and core files (e.g. patch
+a variable's value). You must turn this switch on, specify
+the file ("exec foo" or "core foo"), *then* modify it, e.g.
+by assigning a new value to a variable. Modifications take
+effect immediately.
+
+ * Automatic SunOS shared library reading
+
+When you run your program, GDB automatically determines where its
+shared libraries (if any) have been loaded, and reads their symbols.
+The `share' command is no longer needed. This also works when
+examining core files.
+
+ * set listsize
+
+You can specify the number of lines that the `list' command shows.
+The default is 10.
+
+ * New machines supported (host and target)
+
+SGI Iris (MIPS) running Irix V3: mips-sgi-irix or iris
+Sony NEWS (68K) running NEWSOS 3.x: m68k-sony-sysv or news
+Ultracomputer (29K) running Sym1: a29k-nyu-sym1 or ultra3
+
+ * New hosts supported (not targets)
+
+IBM RT/PC: romp-ibm-aix or rtpc
+
+ * New targets supported (not hosts)
+
+AMD 29000 embedded with COFF a29k-none-coff
+AMD 29000 embedded with a.out a29k-none-aout
+Ultracomputer remote kernel debug a29k-nyu-kern
+
+ * New remote interfaces
+
+AMD 29000 Adapt
+AMD 29000 Minimon
+
+
+*** Changes in GDB-4.0:
+
+ * New Facilities
+
+Wide output is wrapped at good places to make the output more readable.
+
+Gdb now supports cross-debugging from a host machine of one type to a
+target machine of another type. Communication with the target system
+is over serial lines. The ``target'' command handles connecting to the
+remote system; the ``load'' command will download a program into the
+remote system. Serial stubs for the m68k and i386 are provided. Gdb
+also supports debugging of realtime processes running under VxWorks,
+using SunRPC Remote Procedure Calls over TCP/IP to talk to a debugger
+stub on the target system.
+
+New CPUs supported include the AMD 29000 and Intel 960.
+
+GDB now reads object files and symbol tables via a ``binary file''
+library, which allows a single copy of GDB to debug programs of multiple
+object file types such as a.out and coff.
+
+There is now a GDB reference card in "doc/refcard.tex". (Make targets
+refcard.dvi and refcard.ps are available to format it).
+
+
+ * Control-Variable user interface simplified
+
+All variables that control the operation of the debugger can be set
+by the ``set'' command, and displayed by the ``show'' command.
+
+For example, ``set prompt new-gdb=>'' will change your prompt to new-gdb=>.
+``Show prompt'' produces the response:
+Gdb's prompt is new-gdb=>.
+
+What follows are the NEW set commands. The command ``help set'' will
+print a complete list of old and new set commands. ``help set FOO''
+will give a longer description of the variable FOO. ``show'' will show
+all of the variable descriptions and their current settings.
+
+confirm on/off: Enables warning questions for operations that are
+ hard to recover from, e.g. rerunning the program while
+ it is already running. Default is ON.
+
+editing on/off: Enables EMACS style command line editing
+ of input. Previous lines can be recalled with
+ control-P, the current line can be edited with control-B,
+ you can search for commands with control-R, etc.
+ Default is ON.
+
+history filename NAME: NAME is where the gdb command history
+ will be stored. The default is .gdb_history,
+ or the value of the environment variable
+ GDBHISTFILE.
+
+history size N: The size, in commands, of the command history. The
+ default is 256, or the value of the environment variable
+ HISTSIZE.
+
+history save on/off: If this value is set to ON, the history file will
+ be saved after exiting gdb. If set to OFF, the
+ file will not be saved. The default is OFF.
+
+history expansion on/off: If this value is set to ON, then csh-like
+ history expansion will be performed on
+ command line input. The default is OFF.
+
+radix N: Sets the default radix for input and output. It can be set
+ to 8, 10, or 16. Note that the argument to "radix" is interpreted
+ in the current radix, so "set radix 10" is always a no-op.
+
+height N: This integer value is the number of lines on a page. Default
+ is 24, the current `stty rows'' setting, or the ``li#''
+ setting from the termcap entry matching the environment
+ variable TERM.
+
+width N: This integer value is the number of characters on a line.
+ Default is 80, the current `stty cols'' setting, or the ``co#''
+ setting from the termcap entry matching the environment
+ variable TERM.
+
+Note: ``set screensize'' is obsolete. Use ``set height'' and
+``set width'' instead.
+
+print address on/off: Print memory addresses in various command displays,
+ such as stack traces and structure values. Gdb looks
+ more ``symbolic'' if you turn this off; it looks more
+ ``machine level'' with it on. Default is ON.
+
+print array on/off: Prettyprint arrays. New convenient format! Default
+ is OFF.
+
+print demangle on/off: Print C++ symbols in "source" form if on,
+ "raw" form if off.
+
+print asm-demangle on/off: Same, for assembler level printouts
+ like instructions.
+
+print vtbl on/off: Prettyprint C++ virtual function tables. Default is OFF.
+
+
+ * Support for Epoch Environment.
+
+The epoch environment is a version of Emacs v18 with windowing. One
+new command, ``inspect'', is identical to ``print'', except that if you
+are running in the epoch environment, the value is printed in its own
+window.
+
+
+ * Support for Shared Libraries
+
+GDB can now debug programs and core files that use SunOS shared libraries.
+Symbols from a shared library cannot be referenced
+before the shared library has been linked with the program (this
+happens after you type ``run'' and before the function main() is entered).
+At any time after this linking (including when examining core files
+from dynamically linked programs), gdb reads the symbols from each
+shared library when you type the ``sharedlibrary'' command.
+It can be abbreviated ``share''.
+
+sharedlibrary REGEXP: Load shared object library symbols for files
+ matching a unix regular expression. No argument
+ indicates to load symbols for all shared libraries.
+
+info sharedlibrary: Status of loaded shared libraries.
+
+
+ * Watchpoints
+
+A watchpoint stops execution of a program whenever the value of an
+expression changes. Checking for this slows down execution
+tremendously whenever you are in the scope of the expression, but is
+quite useful for catching tough ``bit-spreader'' or pointer misuse
+problems. Some machines such as the 386 have hardware for doing this
+more quickly, and future versions of gdb will use this hardware.
+
+watch EXP: Set a watchpoint (breakpoint) for an expression.
+
+info watchpoints: Information about your watchpoints.
+
+delete N: Deletes watchpoint number N (same as breakpoints).
+disable N: Temporarily turns off watchpoint number N (same as breakpoints).
+enable N: Re-enables watchpoint number N (same as breakpoints).
+
+
+ * C++ multiple inheritance
+
+When used with a GCC version 2 compiler, GDB supports multiple inheritance
+for C++ programs.
+
+ * C++ exception handling
+
+Gdb now supports limited C++ exception handling. Besides the existing
+ability to breakpoint on an exception handler, gdb can breakpoint on
+the raising of an exception (before the stack is peeled back to the
+handler's context).
+
+catch FOO: If there is a FOO exception handler in the dynamic scope,
+ set a breakpoint to catch exceptions which may be raised there.
+ Multiple exceptions (``catch foo bar baz'') may be caught.
+
+info catch: Lists all exceptions which may be caught in the
+ current stack frame.
+
+
+ * Minor command changes
+
+The command ``call func (arg, arg, ...)'' now acts like the print
+command, except it does not print or save a value if the function's result
+is void. This is similar to dbx usage.
+
+The ``up'' and ``down'' commands now always print the frame they end up
+at; ``up-silently'' and `down-silently'' can be used in scripts to change
+frames without printing.
+
+ * New directory command
+
+'dir' now adds directories to the FRONT of the source search path.
+The path starts off empty. Source files that contain debug information
+about the directory in which they were compiled can be found even
+with an empty path; Sun CC and GCC include this information. If GDB can't
+find your source file in the current directory, type "dir .".
+
+ * Configuring GDB for compilation
+
+For normal use, type ``./configure host''. See README or gdb.texinfo
+for more details.
+
+GDB now handles cross debugging. If you are remotely debugging between
+two different machines, type ``./configure host -target=targ''.
+Host is the machine where GDB will run; targ is the machine
+where the program that you are debugging will run.
diff --git a/contrib/gdb/gdb/README b/contrib/gdb/gdb/README
new file mode 100644
index 0000000..c58bcb7
--- /dev/null
+++ b/contrib/gdb/gdb/README
@@ -0,0 +1,583 @@
+ README for gdb-4.16 release
+ Updated 10-Apr-96 by Fred Fish
+
+This is GDB, the GNU source-level debugger.
+A summary of new features is in the file `NEWS'.
+
+
+Unpacking and Installation -- quick overview
+==========================
+
+In this release, the GDB debugger sources, the generic GNU include
+files, the BFD ("binary file description") library, the readline
+library, and other libraries all have directories of their own
+underneath the gdb-4.16 directory. The idea is that a variety of GNU
+tools can share a common copy of these things. Be aware of variation
+over time--for example don't try to build gdb with a copy of bfd from
+a release other than the gdb release (such as a binutils or gas
+release), especially if the releases are more than a few weeks apart.
+Configuration scripts and makefiles exist to cruise up and down this
+directory tree and automatically build all the pieces in the right
+order.
+
+When you unpack the gdb-4.16.tar.gz file, you'll find a directory
+called `gdb-4.16', which contains:
+
+ COPYING config.sub* libiberty/ opcodes/
+ COPYING.LIB configure* mmalloc/ readline/
+ Makefile.in configure.in move-if-change* sim/
+ README etc/ mpw-README texinfo/
+ bfd/ gdb/ mpw-build.in utils/
+ config/ include/ mpw-config.in
+ config.guess* install.sh* mpw-configure
+
+To build GDB, you can just do:
+
+ cd gdb-4.16
+ ./configure
+ make
+ cp gdb/gdb /usr/local/bin/gdb (or wherever you want)
+
+This will configure and build all the libraries as well as GDB.
+If `configure' can't determine your system type, specify one as its
+argument, e.g., sun4 or decstation.
+
+If you get compiler warnings during this stage, see the `Reporting Bugs'
+section below; there are a few known problems.
+
+GDB can be used as a cross-debugger, running on a machine of one type
+while debugging a program running on a machine of another type. See below.
+
+
+More Documentation
+******************
+
+ The GDB 4 release includes an already-formatted reference card,
+ready for printing with PostScript or Ghostscript, in the `gdb'
+subdirectory of the main source directory. (In `gdb-4.16/gdb/refcard.ps'.)
+If you can use PostScript or Ghostscript with your printer, you can
+print the reference card immediately with `refcard.ps'.
+
+ The release also includes the source for the reference card. You
+can format it, using TeX, by typing:
+
+ make refcard.dvi
+
+ The GDB reference card is designed to print in landscape mode on US
+"letter" size paper; that is, on a sheet 11 inches wide by 8.5 inches
+high. You will need to specify this form of printing as an option to
+your DVI output program.
+
+ All the documentation for GDB comes as part of the machine-readable
+distribution. The documentation is written in Texinfo format, which is
+a documentation system that uses a single source file to produce both
+on-line information and a printed manual. You can use one of the Info
+formatting commands to create the on-line version of the documentation
+and TeX (or `texi2roff') to typeset the printed version.
+
+ GDB includes an already formatted copy of the on-line Info version of
+this manual in the `gdb' subdirectory. The main Info file is
+`gdb-VERSION-NUMBER/gdb/gdb.info', and it refers to subordinate files
+matching `gdb.info*' in the same directory. If necessary, you can
+print out these files, or read them with any editor; but they are
+easier to read using the `info' subsystem in GNU Emacs or the
+standalone `info' program, available as part of the GNU Texinfo
+distribution.
+
+ If you want to format these Info files yourself, you need one of the
+Info formatting programs, such as `texinfo-format-buffer' or `makeinfo'.
+
+ If you have `makeinfo' installed, and are in the top level GDB
+source directory (`gdb-4.16', in the case of version 4.16), you can make
+the Info file by typing:
+
+ cd gdb
+ make gdb.info
+
+ If you want to typeset and print copies of this manual, you need TeX,
+a program to print its DVI output files, and `texinfo.tex', the Texinfo
+definitions file.
+
+ TeX is a typesetting program; it does not print files directly, but
+produces output files called DVI files. To print a typeset document,
+you need a program to print DVI files. If your system has TeX
+installed, chances are it has such a program. The precise command to
+use depends on your system; `lpr -d' is common; another (for PostScript
+devices) is `dvips'. The DVI print command may require a file name
+without any extension or a `.dvi' extension.
+
+ TeX also requires a macro definitions file called `texinfo.tex'.
+This file tells TeX how to typeset a document written in Texinfo
+format. On its own, TeX cannot read, much less typeset a Texinfo file.
+ `texinfo.tex' is distributed with GDB and is located in the
+`gdb-VERSION-NUMBER/texinfo' directory.
+
+ If you have TeX and a DVI printer program installed, you can typeset
+and print this manual. First switch to the the `gdb' subdirectory of
+the main source directory (for example, to `gdb-4.16/gdb') and then type:
+
+ make gdb.dvi
+
+
+Installing GDB
+**************
+
+ GDB comes with a `configure' script that automates the process of
+preparing GDB for installation; you can then use `make' to build the
+`gdb' program.
+
+ The GDB distribution includes all the source code you need for GDB in
+a single directory, whose name is usually composed by appending the
+version number to `gdb'.
+
+ For example, the GDB version 4.16 distribution is in the `gdb-4.16'
+directory. That directory contains:
+
+`gdb-4.16/{COPYING,COPYING.LIB}'
+ Standard GNU license files. Please read them.
+
+`gdb-4.16/bfd'
+ source for the Binary File Descriptor library
+
+`gdb-4.16/config*'
+ script for configuring GDB, along with other support files
+
+`gdb-4.16/gdb'
+ the source specific to GDB itself
+
+`gdb-4.16/include'
+ GNU include files
+
+`gdb-4.16/libiberty'
+ source for the `-liberty' free software library
+
+`gdb-4.16/mmalloc'
+ source for the GNU memory-mapped malloc package
+
+`gdb-4.16/opcodes'
+ source for the library of opcode tables and disassemblers
+
+`gdb-4.16/readline'
+ source for the GNU command-line interface
+
+'gdb-4.16/sim'
+ source for some simulators (z8000, H8/300, H8/500, etc)
+
+ The simplest way to configure and build GDB is to run `configure'
+from the `gdb-VERSION-NUMBER' source directory, which in this example
+is the `gdb-4.16' directory.
+
+ First switch to the `gdb-VERSION-NUMBER' source directory if you are
+not already in it; then run `configure'. Pass the identifier for the
+platform on which GDB will run as an argument.
+
+ For example:
+
+ cd gdb-4.16
+ ./configure HOST
+ make
+
+where HOST is an identifier such as `sun4' or `decstation', that
+identifies the platform where GDB will run.
+
+ Running `configure HOST' followed by `make' builds the `bfd',
+`readline', `mmalloc', and `libiberty' libraries, then `gdb' itself.
+The configured source files, and the binaries, are left in the
+corresponding source directories.
+
+ `configure' is a Bourne-shell (`/bin/sh') script; if your system
+does not recognize this automatically when you run a different shell,
+you may need to run `sh' on it explicitly:
+
+ sh configure HOST
+
+ If you run `configure' from a directory that contains source
+directories for multiple libraries or programs, such as the `gdb-4.16'
+source directory for version 4.16, `configure' creates configuration
+files for every directory level underneath (unless you tell it not to,
+with the `--norecursion' option).
+
+ You can run the `configure' script from any of the subordinate
+directories in the GDB distribution, if you only want to configure that
+subdirectory; but be sure to specify a path to it.
+
+ For example, with version 4.16, type the following to configure only
+the `bfd' subdirectory:
+
+ cd gdb-4.16/bfd
+ ../configure HOST
+
+ You can install `gdb' anywhere; it has no hardwired paths. However,
+you should make sure that the shell on your path (named by the `SHELL'
+environment variable) is publicly readable. Remember that GDB uses the
+shell to start your program--some systems refuse to let GDB debug child
+processes whose programs are not readable.
+
+
+Compiling GDB in another directory
+==================================
+
+ If you want to run GDB versions for several host or target machines,
+you need a different `gdb' compiled for each combination of host and
+target. `configure' is designed to make this easy by allowing you to
+generate each configuration in a separate subdirectory, rather than in
+the source directory. If your `make' program handles the `VPATH'
+feature correctly (GNU `make' and SunOS 'make' are two that should),
+running `make' in each of these directories builds the `gdb' program
+specified there.
+
+ To build `gdb' in a separate directory, run `configure' with the
+`--srcdir' option to specify where to find the source. (You also need
+to specify a path to find `configure' itself from your working
+directory. If the path to `configure' would be the same as the
+argument to `--srcdir', you can leave out the `--srcdir' option; it
+will be assumed.)
+
+ For example, with version 4.16, you can build GDB in a separate
+directory for a Sun 4 like this:
+
+ cd gdb-4.16
+ mkdir ../gdb-sun4
+ cd ../gdb-sun4
+ ../gdb-4.16/configure sun4
+ make
+
+ When `configure' builds a configuration using a remote source
+directory, it creates a tree for the binaries with the same structure
+(and using the same names) as the tree under the source directory. In
+the example, you'd find the Sun 4 library `libiberty.a' in the
+directory `gdb-sun4/libiberty', and GDB itself in `gdb-sun4/gdb'.
+
+ One popular reason to build several GDB configurations in separate
+directories is to configure GDB for cross-compiling (where GDB runs on
+one machine--the host--while debugging programs that run on another
+machine--the target). You specify a cross-debugging target by giving
+the `--target=TARGET' option to `configure'.
+
+ When you run `make' to build a program or library, you must run it
+in a configured directory--whatever directory you were in when you
+called `configure' (or one of its subdirectories).
+
+ The `Makefile' that `configure' generates in each source directory
+also runs recursively. If you type `make' in a source directory such
+as `gdb-4.16' (or in a separate configured directory configured with
+`--srcdir=PATH/gdb-4.16'), you will build all the required libraries,
+and then build GDB.
+
+ When you have multiple hosts or targets configured in separate
+directories, you can run `make' on them in parallel (for example, if
+they are NFS-mounted on each of the hosts); they will not interfere
+with each other.
+
+
+Specifying names for hosts and targets
+======================================
+
+ The specifications used for hosts and targets in the `configure'
+script are based on a three-part naming scheme, but some short
+predefined aliases are also supported. The full naming scheme encodes
+three pieces of information in the following pattern:
+
+ ARCHITECTURE-VENDOR-OS
+
+ For example, you can use the alias `sun4' as a HOST argument or in a
+`--target=TARGET' option. The equivalent full name is
+`sparc-sun-sunos4'.
+
+ The `configure' script accompanying GDB does not provide any query
+facility to list all supported host and target names or aliases.
+`configure' calls the Bourne shell script `config.sub' to map
+abbreviations to full names; you can read the script, if you wish, or
+you can use it to test your guesses on abbreviations--for example:
+
+ % sh config.sub sun4
+ sparc-sun-sunos411
+ % sh config.sub sun3
+ m68k-sun-sunos411
+ % sh config.sub decstation
+ mips-dec-ultrix42
+ % sh config.sub hp300bsd
+ m68k-hp-bsd
+ % sh config.sub i386v
+ i386-unknown-sysv
+ % sh config.sub i786v
+ Invalid configuration `i786v': machine `i786v' not recognized
+
+`config.sub' is also distributed in the GDB source directory
+(`gdb-4.16', for version 4.16).
+
+
+`configure' options
+===================
+
+ Here is a summary of the `configure' options and arguments that are
+most often useful for building GDB. `configure' also has several other
+options not listed here. *note : (configure.info)What Configure Does,
+for a full explanation of `configure'.
+
+ configure [--help]
+ [--prefix=DIR]
+ [--srcdir=PATH]
+ [--norecursion] [--rm]
+ [--target=TARGET] HOST
+
+You may introduce options with a single `-' rather than `--' if you
+prefer; but you may abbreviate option names if you use `--'.
+
+`--help'
+ Display a quick summary of how to invoke `configure'.
+
+`-prefix=DIR'
+ Configure the source to install programs and files under directory
+ `DIR'.
+
+`--srcdir=PATH'
+ *Warning: using this option requires GNU `make', or another `make'
+ that compatibly implements the `VPATH' feature.*
+ Use this option to make configurations in directories separate
+ from the GDB source directories. Among other things, you can use
+ this to build (or maintain) several configurations simultaneously,
+ in separate directories. `configure' writes configuration
+ specific files in the current directory, but arranges for them to
+ use the source in the directory PATH. `configure' will create
+ directories under the working directory in parallel to the source
+ directories below PATH.
+
+`--norecursion'
+ Configure only the directory level where `configure' is executed;
+ do not propagate configuration to subdirectories.
+
+`--rm'
+ Remove the configuration that the other arguments specify.
+
+`--target=TARGET'
+ Configure GDB for cross-debugging programs running on the specified
+ TARGET. Without this option, GDB is configured to debug programs
+ that run on the same machine (HOST) as GDB itself.
+
+ There is no convenient way to generate a list of all available
+ targets.
+
+`HOST ...'
+ Configure GDB to run on the specified HOST.
+
+ There is no convenient way to generate a list of all available
+ hosts.
+
+`configure' accepts other options, for compatibility with configuring
+other GNU tools recursively; but these are the only options that affect
+GDB or its supporting libraries.
+
+
+Languages other than C
+=======================
+
+See the GDB manual (doc/gdb.texinfo) for information on this.
+
+Kernel debugging
+=================
+
+I have't done this myself so I can't really offer any advice.
+Remote debugging over serial lines works fine, but the kernel debugging
+code in here has not been tested in years. Van Jacobson has
+better kernel debugging, but the UC lawyers won't let FSF have it.
+
+
+Remote debugging
+=================
+
+The files m68k-stub.c, i386-stub.c, and sparc-stub.c are examples of
+remote stubs to be used with remote.c. They are designed to run
+standalone on an m68k, i386, or SPARC cpu and communicate properly with
+the remote.c stub over a serial line.
+
+The file rem-multi.shar contains a general stub that can probably
+run on various different flavors of unix to allow debugging over a
+serial line from one machine to another.
+
+Some working remote interfaces for talking to existing ROM monitors
+are:
+ remote-adapt.c AMD 29000 "Adapt"
+ remote-e7000.c Hitachi E7000 ICE
+ remote-eb.c AMD 29000 "EBMON"
+ remote-es.c Ericsson 1800 monitor
+ remote-hms.c Hitachi Micro Systems H8/300 monitor
+ remote-mips.c MIPS remote debugging protocol
+ remote-mm.c AMD 29000 "minimon"
+ remote-nindy.c Intel 960 "Nindy"
+ remote-os9k.c PC running OS/9000
+ remote-sim.c Generalized simulator protocol
+ remote-st.c Tandem ST-2000 monitor
+ remote-udi.c AMD 29000 using the AMD "Universal Debug Interface"
+ remote-vx.c VxWorks realtime kernel
+ remote-z8k.c Zilog Z8000 simulator
+
+Remote-vx.c and the vx-share subdirectory contain a remote interface for the
+VxWorks realtime kernel, which communicates over TCP using the Sun
+RPC library. This would be a useful starting point for other remote-
+via-ethernet back ends.
+
+Remote-udi.c and the 29k-share subdirectory contain a remote interface
+for AMD 29000 programs, which uses the AMD "Universal Debug Interface".
+This allows GDB to talk to software simulators, emulators, and/or bare
+hardware boards, via network or serial interfaces. Note that GDB only
+provides an interface that speaks UDI, not a complete solution. You
+will need something on the other end that also speaks UDI.
+
+
+Reporting Bugs
+===============
+
+The correct address for reporting bugs found in gdb is
+"bug-gdb@prep.ai.mit.edu". Please email all bugs, and all requests for
+help with GDB, to that address. Please include the GDB version number
+(e.g., gdb-4.16), and how you configured it (e.g., "sun4" or "mach386
+host, i586-intel-synopsys target"). Since GDB now supports so many
+different configurations, it is important that you be precise about this.
+If at all possible, you should include the actual banner that GDB prints
+when it starts up, or failing that, the actual configure command that
+you used when configuring GDB.
+
+For more information on how/whether to report bugs, see the GDB Bugs
+section of the GDB manual (gdb/doc/gdb.texinfo).
+
+Known bugs:
+
+ * Under Ultrix 4.2 (DECstation-3100) or Alphas under OSF/1, we have
+ seen problems with backtraces after interrupting the inferior out
+ of a read(). The problem is caused by ptrace() returning an
+ incorrect value for the frame pointer register (register 15 or
+ 30). As far as we can tell, this is a kernel problem. Any help
+ with this would be greatly appreciated.
+
+ * Under Ultrix 4.4 (DECstation-3100), setting the TERMCAP environment
+ variable to a string without a trailing ':' can cause GDB to dump
+ core upon startup. Although the core file makes it look as though
+ GDB code failed, the crash actually occurs within a call to the
+ termcap library function tgetent(). The problem can be solved by
+ using the GNU Termcap library.
+
+ Alphas running OSF/1 (versions 1.0 through 2.1) have the same buggy
+ termcap code, but GDB behaves strangely rather than crashing.
+
+ * On DECstations there are warnings about shift counts out of range in
+ various BFD modules. None of them is a cause for alarm, they are actually
+ a result of bugs in the DECstation compiler.
+
+ * Notes for the DEC Alpha using OSF/1:
+ The debugging output of native cc has two known problems; we view these
+ as compiler bugs.
+ The linker miscompacts symbol tables, which causes gdb to confuse the
+ type of variables or results in `struct <illegal>' type outputs.
+ dbx has the same problems with those executables. A workaround is to
+ specify -Wl,-b when linking, but that will increase the executable size
+ considerably.
+ If a structure has incomplete type in one file (e.g., "struct foo *"
+ without a definition for "struct foo"), gdb will be unable to find the
+ structure definition from another file.
+ It has been reported that the Ultrix 4.3A compiler on decstations has the
+ same problems.
+
+ * Notes for Solaris 2.x, using the SPARCworks cc compiler:
+ You have to compile your program with the -xs option of the SPARCworks
+ compiler to be able to debug your program with gdb.
+ Under Solaris 2.3 you also need patch 101409-03 (Jumbo linker patch).
+ Under Solaris 2.2, if you have patch 101052 installed, make sure
+ that it is at least at revision 101052-06.
+
+ * Under Irix 5 for SGIs, you must have installed the `compiler_dev.hdr'
+ subsystem that is on the IDO CD, otherwise you will get complaints
+ that certain files such as `/usr/include/syms.h' cannot be found.
+
+ * Unixware 2.x is not yet supported.
+
+ * Notes for BSD/386:
+ To compile gdb-4.16 on BSD/386, you must run the configure script and
+ its subscripts with bash. Here is an easy way to do this:
+
+ bash -c 'CONFIG_SHELL=/bin/bash ./configure'
+
+ (configure will report i386-unknown-bsd). Then, compile with the
+ standard "make" command.
+
+GDB can produce warnings about symbols that it does not understand. By
+default, these warnings are disabled. You can enable them by executing
+`set complaint 10' (which you can put in your ~/.gdbinit if you like).
+I recommend doing this if you are working on a compiler, assembler,
+linker, or GDB, since it will point out problems that you may be able
+to fix. Warnings produced during symbol reading indicate some mismatch
+between the object file and GDB's symbol reading code. In many cases,
+it's a mismatch between the specs for the object file format, and what
+the compiler actually outputs or the debugger actually understands.
+
+
+X Windows versus GDB
+=====================
+
+There is an "xxgdb", which seems to work for simple operations,
+which was posted to comp.sources.x.
+
+For those interested in auto display of source and the availability of
+an editor while debugging I suggest trying gdb-mode in GNU Emacs
+(Try typing M-x gdb RETURN). Comments on this mode are welcome.
+
+Those interested in experimenting with a new kind of gdb-mode
+should load gdb/gdba.el into GNU Emacs 19.25 or later. Comments
+on this mode are also welcome.
+
+Writing Code for GDB
+=====================
+
+There is a lot of information about writing code for GDB in the
+internals manual, distributed with GDB in gdb/doc/gdbint.texinfo. You
+can read it by hand, print it by using TeX and texinfo, or process it
+into an `info' file for use with Emacs' info mode or the standalone
+`info' program. In particular, see the nodes Getting Started,
+Debugging GDB, New Architectures, Coding Style, Clean Design, and
+Submitting Patches.
+
+If you are pondering writing anything but a short patch, especially
+take note of the information about copyrights in the node Submitting
+Patches. It can take quite a while to get all the paperwork done, so
+we encourage you to start that process as soon as you decide you are
+planning to work on something, or at least well ahead of when you
+think you will be ready to submit the patches.
+
+
+GDB Testsuite
+=============
+
+There is a DejaGNU based testsuite available for testing your newly
+built GDB, or for regression testing GDBs with local modifications.
+The testsuite is distributed separately from the base GDB distribution
+for the convenience of people that wish to get either GDB or the testsuite
+separately.
+
+The name of the testsuite is gdb-4.16-testsuite.tar.gz. You unpack it in the
+same directory in which you unpacked the base GDB distribution, and it
+will create and populate the directory gdb-4.16/gdb/testsuite.
+
+Running the testsuite requires the prior installation of DejaGNU, which
+is generally available via ftp. Once DejaGNU is installed, you can run
+the tests in one of two ways:
+
+ (1) cd gdb-4.16/gdb (assuming you also unpacked gdb)
+ make check
+
+or
+
+ (2) cd gdb-4.16/gdb/testsuite
+ make site.exp (builds the site specific file)
+ runtest -tool gdb GDB=../gdb (or GDB=<somepath> as appropriate)
+
+The second method gives you slightly more control in case of problems with
+building one or more test executables or if you are using the testsuite
+'standalone', without it being part of the GDB source tree.
+
+See the DejaGNU documentation for further details.
+
+
+(this is for editing this file with GNU emacs)
+Local Variables:
+mode: text
+End:
diff --git a/contrib/gdb/gdb/TODO b/contrib/gdb/gdb/TODO
new file mode 100644
index 0000000..06bd9ac
--- /dev/null
+++ b/contrib/gdb/gdb/TODO
@@ -0,0 +1,468 @@
+If you find inaccuracies in this list, please send mail to
+bug-gdb@prep.ai.mit.edu. If you would like to work on any of these,
+you should consider sending mail to the same address, to find out
+whether anyone else is working on it.
+
+General To Do List
+------------------
+
+This list is probably not up to date, and opinions vary about the
+importance or even desirability of some of the items.
+
+START_INFERIOR_TRAPS_EXPECTED need never be defined to 2, since that
+is its default value. Clean this up.
+
+It should be possible to use symbols from shared libraries before we know
+exactly where the libraries will be loaded. E.g. "b perror" before running
+the program. This could maybe be done as an extension of the "breakpoint
+re-evaluation" after new symbols are loaded.
+
+Make single_step() insert and remove breakpoints in one operation.
+
+Speed up single stepping by avoiding extraneous ptrace calls.
+
+Speed up single stepping by not inserting and removing breakpoints
+each time the inferior starts and stops.
+
+Breakpoints should not be inserted and deleted all the time. Only the
+one(s) there should be removed when we have to step over one. Support
+breakpoints that don't have to be removed to step over them.
+
+Update gdbint.texinfo to include doc on the directory structure and
+the various tricks of building gdb.
+
+Do a tutorial in gdb.texinfo on how to do simple things in gdb.
+E.g. how to set a breakpoint that just prints something and continues.
+How to break on aborts. Etc.
+
+Provide "voodoo" debugging of core files. This creates a zombie
+process as a child of the debugger, and loads it up with the data,
+stack, and regs of the core file. This allows you to call functions
+in the executable, to manipulate the data in the core file.
+
+GDB reopens the source file on every line, as you "next" through it.
+
+Referencing the vtbl member of a struct doesn't work. It prints OK
+if you print the struct, but it gets 0 if you try to deref it.
+
+Persistent command history: A feature where you could save off a list
+of the commands you did, so you can edit it into something that will bring
+the target to the same place every time you source it.
+This would also be useful for automated fast watchpointing; if you go
+past the place where it watchpoints, you just start it over again and
+do it more carefully.
+
+Deal with the SunOS 4.0 and 4.1.1 ptrace bug that loses the registers if
+the stack is paged out.
+
+Finish the C++ exception handling stub routines. Lint points them out
+as unused statics functions.
+
+Perhaps "i source" should take an argument like that of "list".
+
+See if core-aout.c's fetch_core_registers can be used on more machines.
+E.g. MIPS (mips-xdep.c).
+
+unpack_double() does not handle IEEE float on the target unless the host
+is also IEEE. Death on a vax.
+
+Set up interface between GDB and INFO so that you can hop into interactive
+INFO and back out again. When running under Emacs, should use Emacs
+info, else fork the info program. Installation of GDB should install
+its texinfo files into the info tree automagically, including the readline
+texinfo files.
+
+"help address" ought to find the "help set print address" entry.
+
+Remove the VTBL internal guts from printouts of C++ structs, unless
+vtblprint is set.
+
+Remove "at 0xnnnn" from the "b foo" response, if `print address off' and if
+it matches the source line indicated.
+
+The prompt at end of screen should accept space as well as CR.
+
+Check STORE_RETURN_VALUE on all architectures. Check near it in tm-sparc.h
+for other bogosities.
+
+Check for storage leaks in GDB, I'm sure there are a lot!
+
+vtblprint of a vtbl should demangle the names it's printing.
+
+Backtrace should point out what the currently selected frame is, in
+its display, perhaps showing "@3 foo (bar, ...)" or ">3 foo (bar,
+...)" rather than "#3 foo (bar, ...)".
+
+"i program" should work for core files, and display more info, like what
+actually caused it to die.
+
+"x/10i" should shorten the long name, if any, on subsequent lines.
+
+Check through the code for FIXME comments and fix them. dbxread.c,
+blockframe.c, and plenty more. (I count 634 as of 940621 - sts)
+
+"next" over a function that longjumps, never stops until next time you happen
+to get to that spot by accident. E.g. "n" over execute_command which has
+an error.
+
+"set zeroprint off", don't bother printing members of structs which
+are entirely zero. Useful for those big structs with few useful
+members.
+
+GDB does four ioctl's for every command, probably switching terminal modes
+to/from inferior or for readline or something.
+
+terminal_ours versus terminal_inferior: cache state. Switch should be a noop
+if the state is the same, too.
+
+ptype $i6 = void??!
+
+Clean up invalid_float handling so gdb doesn't coredump when it tries to
+access a NaN. While this might work on SPARC, other machines are not
+configured right.
+
+"b value_at ; commands ; continue ; end" stops EVERY OTHER TIME!
+Then once you enter a command, it does the command, runs two more
+times, and then stops again! Bizarre... (This behaviour has been
+modified, but it is not yet 100% predictable when e.g. the commands
+call functions in the child, and while there, the child is interrupted
+with a signal, or hits a breakpoint.)
+
+help completion, help history should work.
+
+Check that we can handle stack trace through varargs AND alloca in same
+function, on 29K.
+
+wait_for_inferior loops forever if wait() gives it an error.
+
+"i frame" shows wrong "arglist at" location, doesn't show where the args
+should be found, only their actual values.
+
+There should be a way for "set" commands to validate the new setting
+before it takes effect.
+
+A mess of floating point opcodes are missing from sparc-opcode.h.
+Also, a little program should test the table for bits that are
+overspecified or underspecified. E.g. if the must-be-ones bits
+and the must-be-zeroes bits leave some fields unexamined, and the format
+string leaves them unprinted, then point this out. If multiple
+non-alias patterns match, point this out too. Finally, there should
+be a sparc-optest.s file that tries each pattern out. This file
+should end up coming back the same (modulo transformation comments)
+if fed to "gas" then the .o is fed to gdb for disassembly.
+
+Eliminate all the core_file_command's in all the xdep files.
+Eliminate separate declarations of registers[] everywhere.
+
+"ena d" is ambiguous, why? "ena delete" seems to think it is a command!
+
+Perhaps move the tdep, xdep, and nat files, into the config
+subdirectories. If not, at least straighten out their names so that
+they all start with the machine name.
+
+inferior_status should include stop_print_frame. It won't need to be
+reset in wait_for_inferior after bpstat_stop_status call, then.
+
+i line VAR produces "Line number not known for symbol ``var''.". I
+thought we were stashing that info now!
+
+We should be able to write to random files at hex offsets like adb.
+
+Make "target xxx" command interruptible.
+
+Handle add_file with separate text, data, and bss addresses. Maybe
+handle separate addresses for each segment in the object file?
+
+Handle free_named_symtab to cope with multiply-loaded object files
+in a dynamic linking environment. Should remember the last copy loaded,
+but not get too snowed if it finds references to the older copy.
+
+Generalize and Standardize the RPC interface to a target program,
+improve it beyond the "ptrace" interface, and see if it can become a
+standard for remote debugging. (This is talking about the vxworks
+interface. Seems unlikely to me that there will be "a standard" for
+remote debugging anytime soon --kingdon, 8 Nov 1994).
+
+Remove all references to:
+ text_offset
+ data_offset
+ text_data_start
+ text_end
+ exec_data_offset
+ ...
+now that we have BFD. All remaining are in machine dependent files.
+
+When quitting with a running program, if a core file was previously
+examined, you get "Couldn't read float regs from core file"...if
+indeed it can't. generic_mourn_inferior...
+
+Have remote targets give a warning on a signal argument to
+target_resume. Or better yet, extend the protocols so that it works
+like it does on the Unix-like systems.
+
+Sort help and info output.
+
+Re-organize help categories into things that tend to fit on a screen
+and hang together.
+
+renote-nindy.c handles interrupts poorly; it error()s out of badly
+chosen places, e.g. leaving current_frame zero, which causes core dumps
+on the next command.
+
+Add in commands like ADB's for searching for patterns, etc. We should
+be able to examine and patch raw unsymboled binaries as well in gdb as
+we can in adb. (E.g. increase the timeout in /bin/login without source).
+
+Those xdep files that call register_addr without defining it are
+probably simply broken. When reconfiguring this part of gdb, I could
+only make guesses about how to redo some of those files, and I
+probably guessed wrong, or left them "for later" when I have a
+machine that can attempt to build them.
+
+When doing "step" or "next", if a few lines of source are skipped between
+the previous line and the current one, print those lines, not just the
+last line of a multiline statement.
+
+When searching for C++ superclasses in value_cast in valops.c, we must
+not search the "fields", only the "superclasses". There might be a
+struct with a field name that matches the superclass name. This can
+happen when the struct was defined before the superclass (before the
+name became a typedef).
+
+Handling of "&" address-of operator needs some serious overhaul
+for ANSI C and consistency on arrays and functions.
+ For "float point[15];":
+ptype &point[4] ==> Attempt to take address of non-lvalue.
+ For "char *malloc();":
+ptype malloc ==> "char *()"; should be same as
+ptype &malloc ==> "char *(*)()"
+call printf ("%x\n", malloc) ==> weird value, should be same as
+call printf ("%x\n", &malloc) ==> correct value
+
+Fix dbxread.c symbol reading in the presence of interrupts. It
+currently leaves a cleanup to blow away the entire symbol table when a
+QUIT occurs. (What's wrong with that? -kingdon, 28 Oct 1993).
+
+Mipsread.c reads include files depth-first, because the dependencies
+in the psymtabs are way too inclusive (it seems to me). Figure out what
+really depends on what, to avoid recursing 20 or 30 times while reading
+real symtabs.
+
+value_add() should be subtracting the lower bound of arrays, if known,
+and possibly checking against the upper bound for error reporting.
+
+mipsread.c symbol table allocation and deallocation should be checked.
+My suspicion is that it's full of memory leaks.
+
+SunOS should have a target_lookup_symbol() for common'd things allocated
+by the shared library linker ld.so.
+
+When listing source lines, check for a preceding \n, to verify that
+the file hasn't changed out from under us.
+
+When listing source lines, eat leading whitespace corresponding to the
+line-number prefix we print. This avoids long lines wrapping.
+
+mipsread.c needs to check for old symtabs and psymtabs for the same
+files, the way it happens for dbxread.c and coffread.c, for VxWorks
+incremental symbol table reloading.
+
+Get all the remote systems (where the protocol allows it) to be able to
+stop the remote system when the GDB user types ^C (like remote.c
+does). For ebmon, use ^Ak.
+
+Possible feature: A version of the "disassemble" command which shows
+both source and assembly code ("set symbol-filename on" is a partial
+solution).
+
+investigate "x/s 0" (right now stops early) (I think maybe GDB is
+using a 0 address for bad purposes internally).
+
+Make "info path" and path_command work again (but independent of the
+environment either of gdb or that we'll pass to the inferior).
+
+Make GDB understand the GCC feature for putting octal constants in
+enums. Make it so overflow on an enum constant does not error_type
+the whole type. Allow arbitrarily large enums with type attributes.
+Put all this stuff in the testsuite.
+
+Make TYPE_CODE_ERROR with a non-zero TYPE_LENGTH more useful (print
+the value in hex; process type attributes). Add this to the
+testsuite. This way future compilers can add new types and old
+versions of GDB can do something halfway reasonable.
+
+Clean up formatting of "info registers" on MIPS and 88k. See if it
+is possible to do this generically across all target architectures.
+
+GDB gets bfd/corefile.c and gdb/corefile.c confused (this should be easy to
+repeat even with something more recent than GDB 4.9).
+
+Check that unmatched RBRAC doesn't abort().
+
+Fix mdebugread.c:parse_type to do fundamental types right (see
+rs6000_builtin_type in stabsread.c for what "right" is--the point is
+that the debug format fixes the sizes of these things and it shouldn't
+depend on stuff like TARGET_PTR_BIT and so on. For mdebug, there seem
+to be separate bt* codes for 64 bit and 32 bit things, and GDB should
+be aware of that). Also use a switch statement for clarity and speed.
+
+Investigate adding symbols in target_load--some targets do, some
+don't.
+
+Put dirname in psymtabs and change lookup*symtab to use dirname (so
+/foo/bar.c works whether compiled by cc /foo/bar.c, or cd /foo; cc
+bar.c).
+
+Merge xcoffread.c and coffread.c. Use breakpoint_re_set instead of
+fixup_breakpoints.
+
+Fix byte order and int size sins in tm-a29k.h
+(EXTRACT_RETURN_VALUE). Perhaps should reproduce bug and verify fix
+(or perhaps should just fix it...).
+
+Make a watchpoint on a constant expression an error (or warning
+perhaps)
+
+Make a watchpoint which contains a function call an error (it is
+broken now, making it work is probably not worth the effort).
+
+Re-do calls to signal() in remote.c, and inflow.c (set_sigint_trap and
+so on) to be independent of the debugging target, using target_stop to
+stop the inferior. Probably the part which is now handled by
+interrupt_query in remote.c can be done without any new features in
+the debugging target.
+
+New test case based on weird.exp but in which type numbers are not
+renumbered (thus multiply defining a type). This currently causes an
+infinite loop on "p v_comb".
+
+Nuke baseclass_addr.
+
+Nuke USG define.
+
+"source file more recent" loses on re-read
+
+Fix 386 floating point so that floating point registers are real
+registers (but code can deal at run-time if they are missing, like
+mips and 68k). This would clean up "info float" and related stuff.
+
+Look at Solaris bug in interrupt.exp. Can get out of syscall with
+PRSABORT (syscall will return EINTR) but merely doing that leads to a
+"can't read memory" error.
+
+gcc -g -c enummask.c then gdb enummask.o, then "p v". GDB complains
+about not being able to access memory location 0.
+
+-------------------- enummask.c
+enum mask
+{
+ ANIMAL = 0,
+ VEGETABLE = 1,
+ MINERAL = 2,
+ BASIC_CATEGORY = 3,
+
+ WHITE = 0,
+ BLUE = 4,
+ GREEN = 8,
+ BLACK = 0xc,
+ COLOR = 0xc,
+
+ ALIVE = 0x10,
+
+ LARGE = 0x20
+} v;
+
+If try to modify value in file with "set write off" should give
+appropriate error not "cannot access memory at address 0x65e0".
+
+Why do we allow a target to omit standard register names (NO_STD_REGS
+in tm-z8k.h)? I thought the standard register names were supposed to
+be just that, standard.
+
+Make DEBUG_EXPRESSIONS a maintenance command, dependent on
+MAINTENANCE_COMMANDS.
+
+Allow core file without exec file on RS/6000.
+
+Make sure "shell" with no arguments works right on DOS.
+
+Make gdb.ini (as well as .gdbinit) be checked on all platforms, so
+the same directory can be NFS-mounted on unix or DOS, and work the
+same way.
+
+cd ~/tmp/<M-?> causes infinite loop (where ~/tmp is a directory).
+
+Get SECT_OFF_TEXT stuff out of objfile_relocate (might be needed to
+get RS/6000 to work right, might not be immediately relevant).
+
+Clean up add_toc_to_loadinfo
+
+Think about attached processes and sharing terminal.
+
+John sez in reference to ignoring errors from tcsegpgrp if attach_flag:
+set_tty_state should not have any trouble with attached processes.
+Instead, the tty handling should leave the pgrp of the tty alone when
+attaching to processes (perhaps pass terminal_init_inferior a flag
+saying whether we're attaching).
+
+PAGE_SIZE redefined warnings on AIX. Probably should be using
+BFD_PAGE_SIZE throughout BFD.
+
+Rewrite proceed, wait_for_inferior, and normal_stop to clean them up.
+Suggestions:
+
+ 1) Make each test in wait_for_inferior a seperate subroutine
+ call.
+ 2) Combine wait_for_inferior and normal_stop to clean up
+ communication via global variables.
+ 3) See if you can find some way to clean up the global
+ variables that are used; possibly group them by data flow
+ and information content?
+
+Work out some kind of way to allow running the inferior to be done as
+a sub-execution of, eg. breakpoint command lists. Currently running
+the inferior interupts any command list execution. This would require
+some rewriting of wait_for_inferior & friends, and hence should
+probably be done in concert with the above.
+
+Add function arguments to gdb user defined functions.
+
+Add convenience variables that refer to exec file, symbol file,
+selected frame source file, selected frame function, selected frame
+line number, etc.
+
+Add a "suspend" subcommand of the "continue" command to suspend gdb
+while continuing execution of the subprocess. Useful when you are
+debugging servers and you want to dodge out and initiate a connection
+to a server running under gdb.
+
+Add stab information to allow reasonable debugging of inline functions
+(possibly they should show up on a stack backtrace? With a note
+indicating that they weren't "real"?).
+
+Modify the naked "until" command to step until past the current source
+line, rather than past the current pc value. This is tricky simply
+because the low level routines have no way of specifying a multi-line
+step range, and there is no way of saying "don't print stuff when we
+stop" from above (otherwise could just call step many times).
+
+Modify the handling of symbols grouped through BINCL/EINCL stabs to
+allocate a partial symtab for each BINCL/EINCL grouping. This will
+seriously decrease the size of inter-psymtab dependencies and hence
+lessen the amount that needs to be read in when a new source file is
+accessed.
+
+Do an "x/i $pc" after each stepi or nexti.
+
+Modify all of the disassemblers to use printf_filtered to get correct
+more filtering.
+
+Modify gdb to work correctly with Pascal.
+
+Add a command for searching memory, a la adb. It specifies size,
+mask, value, start address. ADB searches until it finds it or hits
+an error (or is interrupted).
+
+# Local Variables:
+# mode: text
+# End:
diff --git a/contrib/gdb/gdb/acconfig.h b/contrib/gdb/gdb/acconfig.h
new file mode 100644
index 0000000..bb9b991
--- /dev/null
+++ b/contrib/gdb/gdb/acconfig.h
@@ -0,0 +1,9 @@
+
+/* Define if fpregset_t type is available. */
+#undef HAVE_FPREGSET_T
+
+/* Define if gregset_t type is available. */
+#undef HAVE_GREGSET_T
+
+/* Define if the "%Lg" format works to print long doubles. */
+#undef PRINTF_HAS_LONG_DOUBLE
diff --git a/contrib/gdb/gdb/aclocal.m4 b/contrib/gdb/gdb/aclocal.m4
new file mode 100644
index 0000000..d23d084
--- /dev/null
+++ b/contrib/gdb/gdb/aclocal.m4
@@ -0,0 +1,605 @@
+dnl This file is duplicated in four places:
+dnl * gdb/aclocal.m4
+dnl * gdb/testsuite/aclocal.m4
+dnl * expect/aclocal.m4
+dnl * dejagnu/aclocal.m4
+dnl Consider modifying all copies in parallel.
+dnl written by Rob Savoye <rob@cygnus.com> for Cygnus Support
+dnl CYGNUS LOCAL: This gets the right posix flag for gcc
+AC_DEFUN(CY_AC_TCL_LYNX_POSIX,
+[AC_REQUIRE([AC_PROG_CC])AC_REQUIRE([AC_PROG_CPP])
+AC_MSG_CHECKING([to see if this is LynxOS])
+AC_CACHE_VAL(ac_cv_os_lynx,
+[AC_EGREP_CPP(yes,
+[/*
+ * The old Lynx "cc" only defines "Lynx", but the newer one uses "__Lynx__"
+ */
+#if defined(__Lynx__) || defined(Lynx)
+yes
+#endif
+], ac_cv_os_lynx=yes, ac_cv_os_lynx=no)])
+#
+if test "$ac_cv_os_lynx" = "yes" ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(LYNX)
+ AC_MSG_CHECKING([whether -mposix or -X is available])
+ AC_CACHE_VAL(ac_cv_c_posix_flag,
+ [AC_TRY_COMPILE(,[
+ /*
+ * This flag varies depending on how old the compiler is.
+ * -X is for the old "cc" and "gcc" (based on 1.42).
+ * -mposix is for the new gcc (at least 2.5.8).
+ */
+ #if defined(__GNUC__) && __GNUC__ >= 2
+ choke me
+ #endif
+ ], ac_cv_c_posix_flag=" -mposix", ac_cv_c_posix_flag=" -X")])
+ CC="$CC $ac_cv_c_posix_flag"
+ AC_MSG_RESULT($ac_cv_c_posix_flag)
+ else
+ AC_MSG_RESULT(no)
+fi
+])
+#
+# Sometimes the native compiler is a bogus stub for gcc or /usr/ucb/cc. This
+# makes configure think it's cross compiling. If --target wasn't used, then
+# we can't configure, so something is wrong.
+AC_DEFUN(CY_AC_C_CROSS,
+[# If we cannot run a trivial program, we must be cross compiling.
+AC_MSG_CHECKING(whether cross-compiling)
+AC_CACHE_VAL(ac_cv_c_cross,[
+AC_TRY_RUN([
+ main(){return(0);}],
+ ac_cv_c_cross=no, ac_cv_c_cross=yes, ac_cv_c_cross=yes)
+])
+if test x"${target}" = x"${host}" -a x"${ac_cv_c_cross}" = x"yes"; then
+ dnl this hack is cause the message is so long we don't call AC_MSG_ERROR
+ echo "configure: error: You need to specify --target to cross compile," 1>&2;
+ echo " or the native compiler is broken" 1>&2;
+ exit 1;
+else
+ cross_compiling=$ac_cv_c_cross
+ AC_MSG_RESULT($ac_cv_c_cross)
+fi
+])
+AC_DEFUN(CY_AC_PATH_TCLH, [
+#
+# Ok, lets find the tcl source trees so we can use the headers
+# Warning: transition of version 9 to 10 will break this algorithm
+# because 10 sorts before 9. We also look for just tcl. We have to
+# be careful that we don't match stuff like tclX by accident.
+# the alternative search directory is involked by --with-tclinclude
+#
+no_tcl=true
+AC_MSG_CHECKING(for Tcl private headers)
+AC_ARG_WITH(tclinclude, [ --with-tclinclude directory where tcl private headers are], with_tclinclude=${withval})
+AC_CACHE_VAL(ac_cv_c_tclh,[
+# first check to see if --with-tclinclude was specified
+if test x"${with_tclinclude}" != x ; then
+ if test -f ${with_tclinclude}/tclInt.h ; then
+ ac_cv_c_tclh=`(cd ${with_tclinclude}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tclinclude} directory doesn't contain private headers])
+ fi
+fi
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../tcl \
+ `ls -dr ${srcdir}/../../tcl[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tcl \
+ `ls -dr ${srcdir}/../../../tcl[[0-9]]* 2>/dev/null ` ; do
+ if test -f $i/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i; pwd)`
+ break
+ fi
+ # Tcl 7.5 and greater puts headers in subdirectory.
+ if test -f $i/generic/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i; pwd)`/generic
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse its output
+if test x"${ac_cv_c_tclh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tcl[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tcl[[0-9]]* 2>/dev/null` \
+ /usr/local/src/tcl \
+ /usr/local/lib/tcl \
+ ${prefix}/include ; do
+ if test -f $i/tclInt.h ; then
+ ac_cv_c_tclh=`(cd $i; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tclh}" = x ; then
+ AC_HEADER_CHECK(tclInt.h, ac_cv_c_tclh=installed, ac_cv_c_tclh="")
+fi
+])
+if test x"${ac_cv_c_tclh}" = x ; then
+ TCLHDIR="# no Tcl private headers found"
+ AC_MSG_ERROR([Can't find Tcl private headers])
+fi
+if test x"${ac_cv_c_tclh}" != x ; then
+ no_tcl=""
+ if test x"${ac_cv_c_tkh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TCLHDIR=""
+ else
+ AC_MSG_RESULT([found in ${ac_cv_c_tclh}])
+ # this hack is cause the TCLHDIR won't print if there is a "-I" in it.
+ TCLHDIR="-I${ac_cv_c_tclh}"
+ fi
+fi
+
+AC_MSG_CHECKING([Tcl version])
+rm -rf tclmajor tclminor
+orig_includes="$CPPFLAGS"
+
+if test x"${TCLHDIR}" != x ; then
+ CPPFLAGS="$CPPFLAGS $TCLHDIR"
+fi
+
+AC_TRY_RUN([
+#include <stdio.h>
+#include "tcl.h"
+main() {
+ FILE *maj = fopen("tclmajor","w");
+ FILE *min = fopen("tclminor","w");
+ fprintf(maj,"%d",TCL_MAJOR_VERSION);
+ fprintf(min,"%d",TCL_MINOR_VERSION);
+ fclose(maj);
+ fclose(min);
+ return 0;
+}],
+ tclmajor=`cat tclmajor`
+ tclminor=`cat tclminor`
+ tclversion=$tclmajor.$tclminor
+ AC_MSG_RESULT($tclversion)
+ rm -f tclmajor tclminor
+,
+ AC_MSG_RESULT([can't happen])
+,
+ AC_MSG_ERROR([can't be cross compiled])
+)
+CPPFLAGS="${orig_includes}"
+
+AC_PROVIDE([$0])
+AC_SUBST(TCLHDIR)
+])
+AC_DEFUN(CY_AC_PATH_TCLLIB, [
+#
+# Ok, lets find the tcl library
+# First, look for one uninstalled.
+# the alternative search directory is invoked by --with-tcllib
+#
+
+if test $tclmajor -ge 7 -a $tclminor -ge 4 ; then
+ installedtcllibroot=tcl$tclversion
+else
+ installedtcllibroot=tcl
+fi
+
+if test x"${no_tcl}" = x ; then
+ # we reset no_tcl incase something fails here
+ no_tcl=true
+ AC_ARG_WITH(tcllib, [ --with-tcllib directory where the tcl library is],
+ with_tcllib=${withval})
+ AC_MSG_CHECKING([for Tcl library])
+ AC_CACHE_VAL(ac_cv_c_tcllib,[
+ # First check to see if --with-tcllib was specified.
+ # This requires checking for both the installed and uninstalled name-styles
+ # since we have no idea if it's installed or not.
+ if test x"${with_tcllib}" != x ; then
+ if test -f "${with_tcllib}/lib$installedtcllibroot.so" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/lib$installedtcllibroot.so
+ elif test -f "${with_tcllib}/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/libtcl.so
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be built first.
+ elif test -f "${with_tcllib}/lib$installedtcllibroot.a" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/lib$installedtcllibroot.a
+ elif test -f "${with_tcllib}/libtcl.a" ; then
+ ac_cv_c_tcllib=`(cd ${with_tcllib}; pwd)`/libtcl.a
+ else
+ AC_MSG_ERROR([${with_tcllib} directory doesn't contain libraries])
+ fi
+ fi
+ # then check for a private Tcl library
+ # Since these are uninstalled, use the simple lib name root.
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[[0-9]]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[[0-9]]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[[0-9]]* 2>/dev/null` ; do
+ # Tcl 7.5 and greater puts library in subdir. Look there first.
+ if test -f "$i/unix/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.so
+ break
+ elif test -f "$i/unix/libtcl.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.a
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.so
+ break
+
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be
+ # built first.
+ elif test -f "$i/libtcl.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.a
+ break
+ fi
+ done
+ fi
+ # check in a few common install locations
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ # first look for a freshly built dynamically linked library
+ if test -f "$i/lib$installedtcllibroot.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/lib$installedtcllibroot.so
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be built first.
+ elif test -f "$i/lib$installedtcllibroot.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/lib$installedtcllibroot.a
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[0-9]]* 2>/dev/null` ; do
+ # Tcl 7.5 and greater puts library in subdir. Look there first.
+ if test -f "$i/unix/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.so
+ break
+ elif test -f "$i/unix/libtcl.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtcl.a
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtcl.so" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.so
+ break
+
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtcl will be
+ # built first.
+ elif test -f "$i/libtcl.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/libtcl.a
+ break
+ fi
+ done
+ fi
+
+ # see if one is conveniently installed with the compiler
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ orig_libs="$LIBS"
+ LIBS="$LIBS -l$installedtcllibroot -lm"
+ AC_TRY_RUN([
+ Tcl_AppInit()
+ { exit(0); }], ac_cv_c_tcllib="-l$installedtcllibroot", ac_cv_c_tcllib=""
+ , ac_cv_c_tclib="-l$installedtcllibroot")
+ LIBS="${orig_libs}"
+ fi
+ ])
+ if test x"${ac_cv_c_tcllib}" = x ; then
+ TCLLIB="# no Tcl library found"
+ AC_MSG_WARN(Can't find Tcl library)
+ else
+ TCLLIB=${ac_cv_c_tcllib}
+ AC_MSG_RESULT(found $TCLLIB)
+ no_tcl=
+ fi
+fi
+
+AC_PROVIDE([$0])
+AC_SUBST(TCLLIB)
+])
+AC_DEFUN(CY_AC_PATH_TKH, [
+#
+# Ok, lets find the tk source trees so we can use the headers
+# If the directory (presumably symlink) named "tk" exists, use that one
+# in preference to any others. Same logic is used when choosing library
+# and again with Tcl. The search order is the best place to look first, then in
+# decreasing significance. The loop breaks if the trigger file is found.
+# Note the gross little conversion here of srcdir by cd'ing to the found
+# directory. This converts the path from a relative to an absolute, so
+# recursive cache variables for the path will work right. We check all
+# the possible paths in one loop rather than many seperate loops to speed
+# things up.
+# the alternative search directory is invoked by --with-tkinclude
+#
+AC_MSG_CHECKING(for Tk private headers)
+AC_ARG_WITH(tkinclude, [ --with-tkinclude directory where the tk private headers are],
+ with_tkinclude=${withval})
+no_tk=true
+AC_CACHE_VAL(ac_cv_c_tkh,[
+# first check to see if --with-tkinclude was specified
+if test x"${with_tkinclude}" != x ; then
+ if test -f ${with_tkinclude}/tk.h ; then
+ ac_cv_c_tkh=`(cd ${with_tkinclude}; pwd)`
+ else
+ AC_MSG_ERROR([${with_tkinclude} directory doesn't contain private headers])
+ fi
+fi
+# next check in private source directory
+#
+# since ls returns lowest version numbers first, reverse the entire list
+# and search for the worst fit, overwriting it with better fits as we find them
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../tk \
+ `ls -dr ${srcdir}/../../tk[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../../../tk \
+ `ls -dr ${srcdir}/../../../tk[[0-9]]* 2>/dev/null ` ; do
+ if test -f $i/tk.h ; then
+ ac_cv_c_tkh=`(cd $i; pwd)`
+ break
+ fi
+ # Tk 4.1 and greater puts this in a subdir.
+ if test -f $i/generic/tk.h; then
+ ac_cv_c_tkh=`(cd $i; pwd)`/generic
+ fi
+ done
+fi
+# finally check in a few common install locations
+#
+# since ls returns lowest version numbers first, reverse the entire list
+# and search for the worst fit, overwriting it with better fits as we find them
+if test x"${ac_cv_c_tkh}" = x ; then
+ for i in \
+ `ls -dr /usr/local/src/tk[[0-9]]* 2>/dev/null` \
+ `ls -dr /usr/local/lib/tk[[0-9]]* 2>/dev/null` \
+ /usr/local/src/tk \
+ /usr/local/lib/tk \
+ ${prefix}/include ; do
+ if test -f $i/tk.h ; then
+ ac_cv_c_tkh=`(cd $i; pwd)`
+ break
+ fi
+ done
+fi
+# see if one is installed
+if test x"${ac_cv_c_tkh}" = x ; then
+ AC_HEADER_CHECK(tk.h, ac_cv_c_tkh=installed)
+fi
+])
+if test x"${ac_cv_c_tkh}" != x ; then
+ no_tk=""
+ if test x"${ac_cv_c_tkh}" = x"installed" ; then
+ AC_MSG_RESULT([is installed])
+ TKHDIR=""
+ else
+ AC_MSG_RESULT([found in $ac_cv_c_tkh])
+ # this hack is cause the TKHDIR won't print if there is a "-I" in it.
+ TKHDIR="-I${ac_cv_c_tkh}"
+ fi
+else
+ TKHDIR="# no Tk directory found"
+ AC_MSG_WARN([Can't find Tk private headers])
+ no_tk=true
+fi
+
+# if Tk is installed, extract the major/minor version
+if test x"${no_tk}" = x ; then
+AC_MSG_CHECKING([Tk version])
+rm -rf tkmajor tkminor
+orig_includes="$CPPFLAGS"
+
+if test x"${TCLHDIR}" != x ; then
+ CPPFLAGS="$CPPFLAGS $TCLHDIR"
+fi
+if test x"${TKHDIR}" != x ; then
+ CPPFLAGS="$CPPFLAGS $TKHDIR"
+fi
+if test x"${x_includes}" != x -a x"${x_includes}" != xNONE ; then
+ CPPFLAGS="$CPPFLAGS -I$x_includes"
+fi
+
+AC_TRY_RUN([
+#include <stdio.h>
+#include "tk.h"
+ main() {
+ FILE *maj = fopen("tkmajor","w");
+ FILE *min = fopen("tkminor","w");
+ fprintf(maj,"%d",TK_MAJOR_VERSION);
+ fprintf(min,"%d",TK_MINOR_VERSION);
+ fclose(maj);
+ fclose(min);
+ return 0;
+}],
+ tkmajor=`cat tkmajor`
+ tkminor=`cat tkminor`
+ tkversion=$tkmajor.$tkminor
+ AC_MSG_RESULT($tkversion)
+ rm -f tkmajor tkminor
+,
+ AC_MSG_ERROR([
+cannot compile a simple X program - suspect your xmkmf is
+misconfigured and is incorrectly reporting the location of your X
+include or libraries - report this to your system admin]) ,
+ AC_MSG_ERROR([can't be cross compiled])
+)
+CPPFLAGS="${orig_includes}"
+fi
+
+AC_PROVIDE([$0])
+AC_SUBST(TKHDIR)
+])
+AC_DEFUN(CY_AC_PATH_TKLIB, [
+AC_REQUIRE([CY_AC_PATH_TCL])
+#
+# Ok, lets find the tk library
+# First, look for the latest private (uninstalled) copy
+# Notice that the destinations in backwards priority since the tests have
+# no break.
+# Then we look for either .a, .so, or Makefile. A Makefile is acceptable
+# is it indicates the target has been configured and will (probably)
+# soon be built. This allows an entire tree of Tcl software to be
+# configured at once and then built.
+# the alternative search directory is invoked by --with-tklib
+#
+
+if test x"${no_tk}" = x ; then
+ # reset no_tk incase something fails here
+ no_tk="true"
+
+ if test $tkmajor -ge 4 ; then
+ installedtklibroot=tk$tkversion
+ else
+ installedtkllibroot=tk
+ fi
+
+ AC_ARG_WITH(tklib, [ --with-tklib directory where the tk library is],
+ with_tklib=${withval})
+ AC_MSG_CHECKING([for Tk library])
+ AC_CACHE_VAL(ac_cv_c_tklib,[
+ # first check to see if --with-tklib was specified
+ # This requires checking for both the installed and uninstalled name-styles
+ # since we have no idea if it's installed or not.
+ if test x"${with_tklib}" != x ; then
+ if test -f "${with_tklib}/lib$installedtklibroot.so" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/lib$installedtklibroot.so
+ no_tk=""
+ elif test -f "${with_tklib}/libtk.so" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/libtk.so
+ no_tk=""
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtk will be built
+ elif test -f "${with_tklib}/lib$installedtklibroot.a" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/lib$installedtklibroot.a
+ no_tk=""
+ elif test -f "${with_tklib}/libtk.a" ; then
+ ac_cv_c_tklib=`(cd ${with_tklib}; pwd)`/libtk.a
+ no_tk=""
+ else
+ AC_MSG_ERROR([${with_tklib} directory doesn't contain libraries])
+ fi
+ fi
+ # then check for a private Tk library
+ # Since these are uninstalled, use the simple lib name root.
+ if test x"${ac_cv_c_tklib}" = x ; then
+ for i in \
+ ../tk \
+ `ls -dr ../tk[[0-9]]* 2>/dev/null` \
+ ../../tk \
+ `ls -dr ../../tk[[0-9]]* 2>/dev/null` \
+ ../../../tk \
+ `ls -dr ../../../tk[[0-9]]* 2>/dev/null` ; do
+ # Tk 4.1 and greater puts things in subdirs. Check these first.
+ if test -f "$i/unix/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/unix/libtk.so
+ no_tk=
+ break
+ elif test -f "$i/unix/libtk.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/unix/libtk.a
+ no_tk=
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.so
+ no_tk=
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists we assume its configured and libtk will be built
+ elif test -f "$i/libtk.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.a
+ no_tk=""
+ break
+ fi
+ done
+ fi
+ # finally check in a few common install locations
+ if test x"${ac_cv_c_tklib}" = x ; then
+ for i in `ls -d ${prefix}/lib /usr/local/lib 2>/dev/null` ; do
+ # first look for a freshly built dynamically linked library
+ if test -f "$i/lib$installedtklibroot.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/lib$installedtklibroot.so
+ no_tk=""
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists, we assume it's configured and libtcl will be built
+ elif test -f "$i/lib$installedtklibroot.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/lib$installedtklibroot.a
+ no_tk=""
+ break
+ fi
+ done
+ fi
+ # check in a few other private locations
+ if test x"${ac_cv_c_tklib}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[0-9]]* 2>/dev/null` ; do
+ # Tk 4.1 and greater puts things in subdirs. Check these first.
+ if test -f "$i/unix/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/unix/libtk.so
+ no_tk=
+ break
+ elif test -f "$i/unix/libtk.a" -o -f "$i/unix/Makefile"; then
+ ac_cv_c_tcllib=`(cd $i; pwd)`/unix/libtk.a
+ no_tk=
+ break
+ # look for a freshly built dynamically linked library
+ elif test -f "$i/libtk.so" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.so
+ no_tk=""
+ break
+ # then look for a freshly built statically linked library
+ # if Makefile exists, we assume it's configured and libtcl will be built
+ elif test -f "$i/libtk.a" -o -f "$i/Makefile" ; then
+ ac_cv_c_tklib=`(cd $i; pwd)`/libtk.a
+ no_tk=""
+ break
+ fi
+ done
+ fi
+ # see if one is conveniently installed with the compiler
+ if test x"${ac_cv_c_tklib}" = x ; then
+ AC_REQUIRE([AC_PATH_X])
+ orig_libs="$LIBS"
+ LIBS="$LIBS -l$installedtklibroot $x_libraries $ac_cv_c_tcllib -lm"
+ AC_TRY_RUN([
+ Tcl_AppInit()
+ { exit(0); }], ac_cv_c_tklib="-l$installedtklibroot", ac_cv_c_tklib=""
+ , ac_cv_c_tklib="-l$installedtklibroot")
+ LIBS="${orig_libs}"
+ fi
+ ])
+ if test x"${ac_cv_c_tklib}" = x ; then
+ TKLIB="# no Tk library found"
+ AC_MSG_WARN(Can't find Tk library)
+ else
+ TKLIB=$ac_cv_c_tklib
+ AC_MSG_RESULT(found $TKLIB)
+ no_tk=
+ fi
+fi
+AC_PROVIDE([$0])
+AC_SUBST(TKLIB)
+])
+AC_DEFUN(CY_AC_PATH_TK, [
+ CY_AC_PATH_TKH
+ CY_AC_PATH_TKLIB
+])
+AC_DEFUN(CY_AC_PATH_TCL, [
+ CY_AC_PATH_TCLH
+ CY_AC_PATH_TCLLIB
+])
diff --git a/contrib/gdb/gdb/alpha-nat.c b/contrib/gdb/gdb/alpha-nat.c
new file mode 100644
index 0000000..b027116
--- /dev/null
+++ b/contrib/gdb/gdb/alpha-nat.c
@@ -0,0 +1,243 @@
+/* Low level Alpha interface, for GDB when running native.
+ Copyright 1993, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <sys/user.h>
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 8
+
+/* The definition for JB_PC in machine/reg.h is wrong.
+ And we can't get at the correct definition in setjmp.h as it is
+ not always available (eg. if _POSIX_SOURCE is defined which is the
+ default). As the defintion is unlikely to change (see comment
+ in <setjmp.h>, define the correct value here. */
+
+#undef JB_PC
+#define JB_PC 2
+
+/* Figure out where the longjmp will land.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
+ This routine returns true on success. */
+
+int
+get_longjmp_target (pc)
+ CORE_ADDR *pc;
+{
+ CORE_ADDR jb_addr;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+
+ jb_addr = read_register(A0_REGNUM);
+
+ if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, raw_buffer,
+ sizeof(CORE_ADDR)))
+ return 0;
+
+ *pc = extract_address (raw_buffer, sizeof(CORE_ADDR));
+ return 1;
+}
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them.
+
+ CORE_REG_SECT points to the register values themselves, read into memory.
+ CORE_REG_SIZE is the size of that area.
+ WHICH says which set of registers we are handling (0 = int, 2 = float
+ on machines where they are discontiguous).
+ REG_ADDR is the offset from u.u_ar0 to the register values relative to
+ core_reg_sect. This is used with old-fashioned core files to
+ locate the registers in a large upage-plus-stack ".reg" section.
+ Original upage address X is at location core_reg_sect+x+reg_addr.
+ */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned reg_addr;
+{
+ register int regno;
+ register int addr;
+ int bad_reg = -1;
+
+ /* Table to map a gdb regnum to an index in the core register section.
+ The floating point register values are garbage in OSF/1.2 core files. */
+ static int core_reg_mapping[NUM_REGS] =
+ {
+#define EFL (EF_SIZE / 8)
+ EF_V0, EF_T0, EF_T1, EF_T2, EF_T3, EF_T4, EF_T5, EF_T6,
+ EF_T7, EF_S0, EF_S1, EF_S2, EF_S3, EF_S4, EF_S5, EF_S6,
+ EF_A0, EF_A1, EF_A2, EF_A3, EF_A4, EF_A5, EF_T8, EF_T9,
+ EF_T10, EF_T11, EF_RA, EF_T12, EF_AT, EF_GP, EF_SP, -1,
+ EFL+0, EFL+1, EFL+2, EFL+3, EFL+4, EFL+5, EFL+6, EFL+7,
+ EFL+8, EFL+9, EFL+10, EFL+11, EFL+12, EFL+13, EFL+14, EFL+15,
+ EFL+16, EFL+17, EFL+18, EFL+19, EFL+20, EFL+21, EFL+22, EFL+23,
+ EFL+24, EFL+25, EFL+26, EFL+27, EFL+28, EFL+29, EFL+30, EFL+31,
+ EF_PC, -1
+ };
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ if (CANNOT_FETCH_REGISTER (regno))
+ {
+ supply_register (regno, zerobuf);
+ continue;
+ }
+ addr = 8 * core_reg_mapping[regno];
+ if (addr < 0 || addr >= core_reg_size)
+ {
+ if (bad_reg < 0)
+ bad_reg = regno;
+ }
+ else
+ {
+ supply_register (regno, core_reg_sect + addr);
+ }
+ }
+ if (bad_reg >= 0)
+ {
+ error ("Register %s not found in core file.", reg_names[bad_reg]);
+ }
+}
+
+/* Map gdb internal register number to a ptrace ``address''.
+ These ``addresses'' are defined in <sys/ptrace.h> */
+
+#define REGISTER_PTRACE_ADDR(regno) \
+ (regno < FP0_REGNUM ? GPR_BASE + (regno) \
+ : regno == PC_REGNUM ? PC \
+ : regno >= FP0_REGNUM ? FPR_BASE + ((regno) - FP0_REGNUM) \
+ : 0)
+
+/* Return the ptrace ``address'' of register REGNO. */
+
+unsigned int
+register_addr (regno, blockend)
+ int regno;
+ int blockend;
+{
+ return REGISTER_PTRACE_ADDR (regno);
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#ifdef USE_PROC_FS
+#include <sys/procfs.h>
+
+/*
+ * See the comment in m68k-tdep.c regarding the utility of these functions.
+ */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register long *regp = gregsetp->regs;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regi = 0; regi < 31; regi++)
+ supply_register (regi, (char *)(regp + regi));
+
+ supply_register (PC_REGNUM, (char *)(regp + 31));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (ZERO_REGNUM, zerobuf);
+ supply_register (FP_REGNUM, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register long *regp = gregsetp->regs;
+
+ for (regi = 0; regi < 31; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(long *) &registers[REGISTER_BYTE (regi)];
+
+ if ((regno == -1) || (regno == PC_REGNUM))
+ *(regp + 31) = *(long *) &registers[REGISTER_BYTE (PC_REGNUM)];
+}
+
+/*
+ * Now we do the same thing for floating-point registers.
+ * Again, see the comments in m68k-tdep.c.
+ */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ register long *regp = fpregsetp->regs;
+
+ for (regi = 0; regi < 32; regi++)
+ supply_register (regi + FP0_REGNUM, (char *)(regp + regi));
+}
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ register long *regp = fpregsetp->regs;
+
+ for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ *(regp + regi - FP0_REGNUM) =
+ *(long *) &registers[REGISTER_BYTE (regi)];
+ }
+ }
+}
+#endif
+
+
+/* Register that we are able to handle alpha core file formats. */
+
+static struct core_fns alpha_core_fns =
+{
+ bfd_target_aout_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_alpha ()
+{
+ add_core_fns (&alpha_core_fns);
+}
diff --git a/contrib/gdb/gdb/alpha-tdep.c b/contrib/gdb/gdb/alpha-tdep.c
new file mode 100644
index 0000000..7fbf642
--- /dev/null
+++ b/contrib/gdb/gdb/alpha-tdep.c
@@ -0,0 +1,1274 @@
+/* Target-dependent code for the ALPHA architecture, for GDB, the GNU Debugger.
+ Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "dis-asm.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb_string.h"
+
+/* FIXME: Some of this code should perhaps be merged with mips-tdep.c. */
+
+/* FIXME: Put this declaration in frame.h. */
+extern struct obstack frame_cache_obstack;
+
+
+/* Forward declarations. */
+
+static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
+
+static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR));
+
+static alpha_extra_func_info_t heuristic_proc_desc PARAMS ((CORE_ADDR,
+ CORE_ADDR,
+ struct frame_info *));
+
+static alpha_extra_func_info_t find_proc_desc PARAMS ((CORE_ADDR,
+ struct frame_info *));
+
+#if 0
+static int alpha_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
+#endif
+
+static void reinit_frame_cache_sfunc PARAMS ((char *, int,
+ struct cmd_list_element *));
+
+static CORE_ADDR after_prologue PARAMS ((CORE_ADDR pc,
+ alpha_extra_func_info_t proc_desc));
+
+static int alpha_in_prologue PARAMS ((CORE_ADDR pc,
+ alpha_extra_func_info_t proc_desc));
+
+/* Heuristic_proc_start may hunt through the text section for a long
+ time across a 2400 baud serial line. Allows the user to limit this
+ search. */
+static unsigned int heuristic_fence_post = 0;
+
+/* Layout of a stack frame on the alpha:
+
+ | |
+ pdr members: | 7th ... nth arg, |
+ | `pushed' by caller. |
+ | |
+----------------|-------------------------------|<-- old_sp == vfp
+ ^ ^ ^ ^ | |
+ | | | | | |
+ | |localoff | Copies of 1st .. 6th |
+ | | | | | argument if necessary. |
+ | | | v | |
+ | | | --- |-------------------------------|<-- FRAME_LOCALS_ADDRESS
+ | | | | |
+ | | | | Locals and temporaries. |
+ | | | | |
+ | | | |-------------------------------|
+ | | | | |
+ |-fregoffset | Saved float registers. |
+ | | | | F9 |
+ | | | | . |
+ | | | | . |
+ | | | | F2 |
+ | | v | |
+ | | -------|-------------------------------|
+ | | | |
+ | | | Saved registers. |
+ | | | S6 |
+ |-regoffset | . |
+ | | | . |
+ | | | S0 |
+ | | | pdr.pcreg |
+ | v | |
+ | ----------|-------------------------------|
+ | | |
+ frameoffset | Argument build area, gets |
+ | | 7th ... nth arg for any |
+ | | called procedure. |
+ v | |
+ -------------|-------------------------------|<-- sp
+ | |
+*/
+
+#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr) /* least address */
+#define PROC_HIGH_ADDR(proc) ((proc)->pdr.iline) /* upper address bound */
+#define PROC_DUMMY_FRAME(proc) ((proc)->pdr.iopt) /* frame for CALL_DUMMY */
+#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
+#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
+#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
+#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
+#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
+#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
+#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
+#define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
+#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
+#define _PROC_MAGIC_ 0x0F0F0F0F
+#define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
+#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym = _PROC_MAGIC_)
+
+struct linked_proc_info
+{
+ struct alpha_extra_func_info info;
+ struct linked_proc_info *next;
+} *linked_proc_desc_table = NULL;
+
+
+/* Guaranteed to set frame->saved_regs to some values (it never leaves it
+ NULL). */
+
+void
+alpha_find_saved_regs (frame)
+ struct frame_info *frame;
+{
+ int ireg;
+ CORE_ADDR reg_position;
+ unsigned long mask;
+ alpha_extra_func_info_t proc_desc;
+ int returnreg;
+
+ frame->saved_regs = (struct frame_saved_regs *)
+ obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
+ memset (frame->saved_regs, 0, sizeof (struct frame_saved_regs));
+
+ /* If it is the frame for __sigtramp, the saved registers are located
+ in a sigcontext structure somewhere on the stack. __sigtramp
+ passes a pointer to the sigcontext structure on the stack.
+ If the stack layout for __sigtramp changes, or if sigcontext offsets
+ change, we might have to update this code. */
+#ifndef SIGFRAME_PC_OFF
+#define SIGFRAME_PC_OFF (2 * 8)
+#define SIGFRAME_REGSAVE_OFF (4 * 8)
+#define SIGFRAME_FPREGSAVE_OFF (SIGFRAME_REGSAVE_OFF + 32 * 8 + 8)
+#endif
+ if (frame->signal_handler_caller)
+ {
+ CORE_ADDR sigcontext_pointer_addr;
+ CORE_ADDR sigcontext_addr;
+
+ if (frame->next)
+ sigcontext_pointer_addr = frame->next->frame;
+ else
+ sigcontext_pointer_addr = frame->frame;
+ sigcontext_addr = read_memory_integer(sigcontext_pointer_addr, 8);
+ for (ireg = 0; ireg < 32; ireg++)
+ {
+ reg_position = sigcontext_addr + SIGFRAME_REGSAVE_OFF + ireg * 8;
+ frame->saved_regs->regs[ireg] = reg_position;
+ }
+ for (ireg = 0; ireg < 32; ireg++)
+ {
+ reg_position = sigcontext_addr + SIGFRAME_FPREGSAVE_OFF + ireg * 8;
+ frame->saved_regs->regs[FP0_REGNUM + ireg] = reg_position;
+ }
+ frame->saved_regs->regs[PC_REGNUM] = sigcontext_addr + SIGFRAME_PC_OFF;
+ return;
+ }
+
+ proc_desc = frame->proc_desc;
+ if (proc_desc == NULL)
+ /* I'm not sure how/whether this can happen. Normally when we can't
+ find a proc_desc, we "synthesize" one using heuristic_proc_desc
+ and set the saved_regs right away. */
+ return;
+
+ /* Fill in the offsets for the registers which gen_mask says
+ were saved. */
+
+ reg_position = frame->frame + PROC_REG_OFFSET (proc_desc);
+ mask = PROC_REG_MASK (proc_desc);
+
+ returnreg = PROC_PC_REG (proc_desc);
+
+ /* Note that RA is always saved first, regardless of its actual
+ register number. */
+ if (mask & (1 << returnreg))
+ {
+ frame->saved_regs->regs[returnreg] = reg_position;
+ reg_position += 8;
+ mask &= ~(1 << returnreg); /* Clear bit for RA so we
+ don't save again later. */
+ }
+
+ for (ireg = 0; ireg <= 31 ; ++ireg)
+ if (mask & (1 << ireg))
+ {
+ frame->saved_regs->regs[ireg] = reg_position;
+ reg_position += 8;
+ }
+
+ /* Fill in the offsets for the registers which float_mask says
+ were saved. */
+
+ reg_position = frame->frame + PROC_FREG_OFFSET (proc_desc);
+ mask = PROC_FREG_MASK (proc_desc);
+
+ for (ireg = 0; ireg <= 31 ; ++ireg)
+ if (mask & (1 << ireg))
+ {
+ frame->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
+ reg_position += 8;
+ }
+
+ frame->saved_regs->regs[PC_REGNUM] = frame->saved_regs->regs[returnreg];
+}
+
+static CORE_ADDR
+read_next_frame_reg(fi, regno)
+ struct frame_info *fi;
+ int regno;
+{
+ for (; fi; fi = fi->next)
+ {
+ /* We have to get the saved sp from the sigcontext
+ if it is a signal handler frame. */
+ if (regno == SP_REGNUM && !fi->signal_handler_caller)
+ return fi->frame;
+ else
+ {
+ if (fi->saved_regs == NULL)
+ alpha_find_saved_regs (fi);
+ if (fi->saved_regs->regs[regno])
+ return read_memory_integer(fi->saved_regs->regs[regno], 8);
+ }
+ }
+ return read_register(regno);
+}
+
+CORE_ADDR
+alpha_frame_saved_pc(frame)
+ struct frame_info *frame;
+{
+ alpha_extra_func_info_t proc_desc = frame->proc_desc;
+ /* We have to get the saved pc from the sigcontext
+ if it is a signal handler frame. */
+ int pcreg = frame->signal_handler_caller ? PC_REGNUM : frame->pc_reg;
+
+ if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+ return read_memory_integer(frame->frame - 8, 8);
+
+ return read_next_frame_reg(frame, pcreg);
+}
+
+CORE_ADDR
+alpha_saved_pc_after_call (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR pc = frame->pc;
+ CORE_ADDR tmp;
+ alpha_extra_func_info_t proc_desc;
+ int pcreg;
+
+ /* Skip over shared library trampoline if necessary. */
+ tmp = SKIP_TRAMPOLINE_CODE (pc);
+ if (tmp != 0)
+ pc = tmp;
+
+ proc_desc = find_proc_desc (pc, frame->next);
+ pcreg = proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM;
+
+ return read_register (pcreg);
+}
+
+
+static struct alpha_extra_func_info temp_proc_desc;
+static struct frame_saved_regs temp_saved_regs;
+
+/* This fencepost looks highly suspicious to me. Removing it also
+ seems suspicious as it could affect remote debugging across serial
+ lines. */
+
+static CORE_ADDR
+heuristic_proc_start(pc)
+ CORE_ADDR pc;
+{
+ CORE_ADDR start_pc = pc;
+ CORE_ADDR fence = start_pc - heuristic_fence_post;
+
+ if (start_pc == 0) return 0;
+
+ if (heuristic_fence_post == UINT_MAX
+ || fence < VM_MIN_ADDRESS)
+ fence = VM_MIN_ADDRESS;
+
+ /* search back for previous return */
+ for (start_pc -= 4; ; start_pc -= 4)
+ if (start_pc < fence)
+ {
+ /* It's not clear to me why we reach this point when
+ stop_soon_quietly, but with this test, at least we
+ don't print out warnings for every child forked (eg, on
+ decstation). 22apr93 rich@cygnus.com. */
+ if (!stop_soon_quietly)
+ {
+ static int blurb_printed = 0;
+
+ if (fence == VM_MIN_ADDRESS)
+ warning("Hit beginning of text section without finding");
+ else
+ warning("Hit heuristic-fence-post without finding");
+
+ warning("enclosing function for address 0x%lx", pc);
+ if (!blurb_printed)
+ {
+ printf_filtered ("\
+This warning occurs if you are debugging a function without any symbols\n\
+(for example, in a stripped executable). In that case, you may wish to\n\
+increase the size of the search with the `set heuristic-fence-post' command.\n\
+\n\
+Otherwise, you told GDB there was a function where there isn't one, or\n\
+(more likely) you have encountered a bug in GDB.\n");
+ blurb_printed = 1;
+ }
+ }
+
+ return 0;
+ }
+ else if (ABOUT_TO_RETURN(start_pc))
+ break;
+
+ start_pc += 4; /* skip return */
+ return start_pc;
+}
+
+static alpha_extra_func_info_t
+heuristic_proc_desc(start_pc, limit_pc, next_frame)
+ CORE_ADDR start_pc, limit_pc;
+ struct frame_info *next_frame;
+{
+ CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+ CORE_ADDR cur_pc;
+ int frame_size;
+ int has_frame_reg = 0;
+ unsigned long reg_mask = 0;
+ int pcreg = -1;
+
+ if (start_pc == 0)
+ return NULL;
+ memset (&temp_proc_desc, '\0', sizeof(temp_proc_desc));
+ memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
+ PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
+
+ if (start_pc + 200 < limit_pc)
+ limit_pc = start_pc + 200;
+ frame_size = 0;
+ for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += 4)
+ {
+ char buf[4];
+ unsigned long word;
+ int status;
+
+ status = read_memory_nobpt (cur_pc, buf, 4);
+ if (status)
+ memory_error (status, cur_pc);
+ word = extract_unsigned_integer (buf, 4);
+
+ if ((word & 0xffff0000) == 0x23de0000) /* lda $sp,n($sp) */
+ frame_size += (-word) & 0xffff;
+ else if ((word & 0xfc1f0000) == 0xb41e0000 /* stq reg,n($sp) */
+ && (word & 0xffff0000) != 0xb7fe0000) /* reg != $zero */
+ {
+ int reg = (word & 0x03e00000) >> 21;
+ reg_mask |= 1 << reg;
+ temp_saved_regs.regs[reg] = sp + (short)word;
+
+ /* Starting with OSF/1-3.2C, the system libraries are shipped
+ without local symbols, but they still contain procedure
+ descriptors without a symbol reference. GDB is currently
+ unable to find these procedure descriptors and uses
+ heuristic_proc_desc instead.
+ As some low level compiler support routines (__div*, __add*)
+ use a non-standard return address register, we have to
+ add some heuristics to determine the return address register,
+ or stepping over these routines will fail.
+ Usually the return address register is the first register
+ saved on the stack, but assembler optimization might
+ rearrange the register saves.
+ So we recognize only a few registers (t7, t9, ra) within
+ the procedure prologue as valid return address registers.
+
+ FIXME: Rewriting GDB to access the procedure descriptors,
+ e.g. via the minimal symbol table, might obviate this hack. */
+ if (pcreg == -1
+ && cur_pc < (start_pc + 20)
+ && (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM))
+ pcreg = reg;
+ }
+ else if (word == 0x47de040f) /* bis sp,sp fp */
+ has_frame_reg = 1;
+ }
+ if (pcreg == -1)
+ {
+ /* If we haven't found a valid return address register yet,
+ keep searching in the procedure prologue. */
+ while (cur_pc < (limit_pc + 20) && cur_pc < (start_pc + 20))
+ {
+ char buf[4];
+ unsigned long word;
+ int status;
+
+ status = read_memory_nobpt (cur_pc, buf, 4);
+ if (status)
+ memory_error (status, cur_pc);
+ cur_pc += 4;
+ word = extract_unsigned_integer (buf, 4);
+
+ if ((word & 0xfc1f0000) == 0xb41e0000 /* stq reg,n($sp) */
+ && (word & 0xffff0000) != 0xb7fe0000) /* reg != $zero */
+ {
+ int reg = (word & 0x03e00000) >> 21;
+ if (reg == T7_REGNUM || reg == T9_REGNUM || reg == RA_REGNUM)
+ {
+ pcreg = reg;
+ break;
+ }
+ }
+ }
+ }
+
+ if (has_frame_reg)
+ PROC_FRAME_REG(&temp_proc_desc) = GCC_FP_REGNUM;
+ else
+ PROC_FRAME_REG(&temp_proc_desc) = SP_REGNUM;
+ PROC_FRAME_OFFSET(&temp_proc_desc) = frame_size;
+ PROC_REG_MASK(&temp_proc_desc) = reg_mask;
+ PROC_PC_REG(&temp_proc_desc) = (pcreg == -1) ? RA_REGNUM : pcreg;
+ PROC_LOCALOFF(&temp_proc_desc) = 0; /* XXX - bogus */
+ return &temp_proc_desc;
+}
+
+/* This returns the PC of the first inst after the prologue. If we can't
+ find the prologue, then return 0. */
+
+static CORE_ADDR
+after_prologue (pc, proc_desc)
+ CORE_ADDR pc;
+ alpha_extra_func_info_t proc_desc;
+{
+ struct symtab_and_line sal;
+ CORE_ADDR func_addr, func_end;
+
+ if (!proc_desc)
+ proc_desc = find_proc_desc (pc, NULL);
+
+ if (proc_desc)
+ {
+ /* If function is frameless, then we need to do it the hard way. I
+ strongly suspect that frameless always means prologueless... */
+ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ && PROC_FRAME_OFFSET (proc_desc) == 0)
+ return 0;
+ }
+
+ if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ return 0; /* Unknown */
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.end < func_end)
+ return sal.end;
+
+ /* The line after the prologue is after the end of the function. In this
+ case, tell the caller to find the prologue the hard way. */
+
+ return 0;
+}
+
+/* Return non-zero if we *might* be in a function prologue. Return zero if we
+ are definatly *not* in a function prologue. */
+
+static int
+alpha_in_prologue (pc, proc_desc)
+ CORE_ADDR pc;
+ alpha_extra_func_info_t proc_desc;
+{
+ CORE_ADDR after_prologue_pc;
+
+ after_prologue_pc = after_prologue (pc, proc_desc);
+
+ if (after_prologue_pc == 0
+ || pc < after_prologue_pc)
+ return 1;
+ else
+ return 0;
+}
+
+static alpha_extra_func_info_t
+find_proc_desc (pc, next_frame)
+ CORE_ADDR pc;
+ struct frame_info *next_frame;
+{
+ alpha_extra_func_info_t proc_desc;
+ struct block *b;
+ struct symbol *sym;
+ CORE_ADDR startaddr;
+
+ /* Try to get the proc_desc from the linked call dummy proc_descs
+ if the pc is in the call dummy.
+ This is hairy. In the case of nested dummy calls we have to find the
+ right proc_desc, but we might not yet know the frame for the dummy
+ as it will be contained in the proc_desc we are searching for.
+ So we have to find the proc_desc whose frame is closest to the current
+ stack pointer. */
+
+ if (PC_IN_CALL_DUMMY (pc, 0, 0))
+ {
+ struct linked_proc_info *link;
+ CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+ alpha_extra_func_info_t found_proc_desc = NULL;
+ long min_distance = LONG_MAX;
+
+ for (link = linked_proc_desc_table; link; link = link->next)
+ {
+ long distance = (CORE_ADDR) PROC_DUMMY_FRAME (&link->info) - sp;
+ if (distance > 0 && distance < min_distance)
+ {
+ min_distance = distance;
+ found_proc_desc = &link->info;
+ }
+ }
+ if (found_proc_desc != NULL)
+ return found_proc_desc;
+ }
+
+ b = block_for_pc(pc);
+
+ find_pc_partial_function (pc, NULL, &startaddr, NULL);
+ if (b == NULL)
+ sym = NULL;
+ else
+ {
+ if (startaddr > BLOCK_START (b))
+ /* This is the "pathological" case referred to in a comment in
+ print_frame_info. It might be better to move this check into
+ symbol reading. */
+ sym = NULL;
+ else
+ sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE,
+ 0, NULL);
+ }
+
+ /* If we never found a PDR for this function in symbol reading, then
+ examine prologues to find the information. */
+ if (sym && ((mips_extra_func_info_t) SYMBOL_VALUE (sym))->pdr.framereg == -1)
+ sym = NULL;
+
+ if (sym)
+ {
+ /* IF this is the topmost frame AND
+ * (this proc does not have debugging information OR
+ * the PC is in the procedure prologue)
+ * THEN create a "heuristic" proc_desc (by analyzing
+ * the actual code) to replace the "official" proc_desc.
+ */
+ proc_desc = (alpha_extra_func_info_t)SYMBOL_VALUE(sym);
+ if (next_frame == NULL)
+ {
+ if (PROC_DESC_IS_DUMMY (proc_desc) || alpha_in_prologue (pc, proc_desc))
+ {
+ alpha_extra_func_info_t found_heuristic =
+ heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
+ pc, next_frame);
+ if (found_heuristic)
+ {
+ PROC_LOCALOFF (found_heuristic) =
+ PROC_LOCALOFF (proc_desc);
+ PROC_PC_REG (found_heuristic) = PROC_PC_REG (proc_desc);
+ proc_desc = found_heuristic;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Is linked_proc_desc_table really necessary? It only seems to be used
+ by procedure call dummys. However, the procedures being called ought
+ to have their own proc_descs, and even if they don't,
+ heuristic_proc_desc knows how to create them! */
+
+ register struct linked_proc_info *link;
+ for (link = linked_proc_desc_table; link; link = link->next)
+ if (PROC_LOW_ADDR(&link->info) <= pc
+ && PROC_HIGH_ADDR(&link->info) > pc)
+ return &link->info;
+
+ if (startaddr == 0)
+ startaddr = heuristic_proc_start (pc);
+
+ proc_desc =
+ heuristic_proc_desc (startaddr, pc, next_frame);
+ }
+ return proc_desc;
+}
+
+alpha_extra_func_info_t cached_proc_desc;
+
+CORE_ADDR
+alpha_frame_chain(frame)
+ struct frame_info *frame;
+{
+ alpha_extra_func_info_t proc_desc;
+ CORE_ADDR saved_pc = FRAME_SAVED_PC(frame);
+
+ if (saved_pc == 0 || inside_entry_file (saved_pc))
+ return 0;
+
+ proc_desc = find_proc_desc(saved_pc, frame);
+ if (!proc_desc)
+ return 0;
+
+ cached_proc_desc = proc_desc;
+
+ /* Fetch the frame pointer for a dummy frame from the procedure
+ descriptor. */
+ if (PROC_DESC_IS_DUMMY(proc_desc))
+ return (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
+
+ /* If no frame pointer and frame size is zero, we must be at end
+ of stack (or otherwise hosed). If we don't check frame size,
+ we loop forever if we see a zero size frame. */
+ if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+ && PROC_FRAME_OFFSET (proc_desc) == 0
+ /* The previous frame from a sigtramp frame might be frameless
+ and have frame size zero. */
+ && !frame->signal_handler_caller)
+ {
+ /* The alpha __sigtramp routine is frameless and has a frame size
+ of zero, but we are able to backtrace through it. */
+ char *name;
+ find_pc_partial_function (saved_pc, &name,
+ (CORE_ADDR *)NULL, (CORE_ADDR *)NULL);
+ if (IN_SIGTRAMP (saved_pc, name))
+ return frame->frame;
+ else
+ return 0;
+ }
+ else
+ return read_next_frame_reg(frame, PROC_FRAME_REG(proc_desc))
+ + PROC_FRAME_OFFSET(proc_desc);
+}
+
+void
+init_extra_frame_info (frame)
+ struct frame_info *frame;
+{
+ /* Use proc_desc calculated in frame_chain */
+ alpha_extra_func_info_t proc_desc =
+ frame->next ? cached_proc_desc : find_proc_desc(frame->pc, frame->next);
+
+ frame->saved_regs = NULL;
+ frame->localoff = 0;
+ frame->pc_reg = RA_REGNUM;
+ frame->proc_desc = proc_desc == &temp_proc_desc ? 0 : proc_desc;
+ if (proc_desc)
+ {
+ /* Get the locals offset and the saved pc register from the
+ procedure descriptor, they are valid even if we are in the
+ middle of the prologue. */
+ frame->localoff = PROC_LOCALOFF(proc_desc);
+ frame->pc_reg = PROC_PC_REG(proc_desc);
+
+ /* Fixup frame-pointer - only needed for top frame */
+
+ /* Fetch the frame pointer for a dummy frame from the procedure
+ descriptor. */
+ if (PROC_DESC_IS_DUMMY(proc_desc))
+ frame->frame = (CORE_ADDR) PROC_DUMMY_FRAME(proc_desc);
+
+ /* This may not be quite right, if proc has a real frame register.
+ Get the value of the frame relative sp, procedure might have been
+ interrupted by a signal at it's very start. */
+ else if (frame->pc == PROC_LOW_ADDR (proc_desc) && !PROC_DESC_IS_DUMMY (proc_desc))
+ frame->frame = read_next_frame_reg (frame->next, SP_REGNUM);
+ else
+ frame->frame = read_next_frame_reg (frame->next, PROC_FRAME_REG (proc_desc))
+ + PROC_FRAME_OFFSET (proc_desc);
+
+ if (proc_desc == &temp_proc_desc)
+ {
+ char *name;
+
+ /* Do not set the saved registers for a sigtramp frame,
+ alpha_find_saved_registers will do that for us.
+ We can't use frame->signal_handler_caller, it is not yet set. */
+ find_pc_partial_function (frame->pc, &name,
+ (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ if (!IN_SIGTRAMP (frame->pc, name))
+ {
+ frame->saved_regs = (struct frame_saved_regs*)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_saved_regs));
+ *frame->saved_regs = temp_saved_regs;
+ frame->saved_regs->regs[PC_REGNUM]
+ = frame->saved_regs->regs[RA_REGNUM];
+ }
+ }
+ }
+}
+
+/* ALPHA stack frames are almost impenetrable. When execution stops,
+ we basically have to look at symbol information for the function
+ that we stopped in, which tells us *which* register (if any) is
+ the base of the frame pointer, and what offset from that register
+ the frame itself is at.
+
+ This presents a problem when trying to examine a stack in memory
+ (that isn't executing at the moment), using the "frame" command. We
+ don't have a PC, nor do we have any registers except SP.
+
+ This routine takes two arguments, SP and PC, and tries to make the
+ cached frames look as if these two arguments defined a frame on the
+ cache. This allows the rest of info frame to extract the important
+ arguments without difficulty. */
+
+struct frame_info *
+setup_arbitrary_frame (argc, argv)
+ int argc;
+ CORE_ADDR *argv;
+{
+ if (argc != 2)
+ error ("ALPHA frame specifications require two arguments: sp and pc");
+
+ return create_new_frame (argv[0], argv[1]);
+}
+
+/* The alpha passes the first six arguments in the registers, the rest on
+ the stack. The register arguments are eventually transferred to the
+ argument transfer area immediately below the stack by the called function
+ anyway. So we `push' at least six arguments on the stack, `reload' the
+ argument registers and then adjust the stack pointer to point past the
+ sixth argument. This algorithm simplifies the passing of a large struct
+ which extends from the registers to the stack.
+ If the called function is returning a structure, the address of the
+ structure to be returned is passed as a hidden first argument. */
+
+CORE_ADDR
+alpha_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ register i;
+ int accumulate_size = struct_return ? 8 : 0;
+ int arg_regs_size = ALPHA_NUM_ARG_REGS * 8;
+ struct alpha_arg { char *contents; int len; int offset; };
+ struct alpha_arg *alpha_args =
+ (struct alpha_arg*)alloca (nargs * sizeof (struct alpha_arg));
+ register struct alpha_arg *m_arg;
+ char raw_buffer[sizeof (CORE_ADDR)];
+ int required_arg_regs;
+
+ for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++)
+ {
+ value_ptr arg = args[i];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ /* Cast argument to long if necessary as the compiler does it too. */
+ switch (TYPE_CODE (arg_type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
+ {
+ arg_type = builtin_type_long;
+ arg = value_cast (arg_type, arg);
+ }
+ break;
+ default:
+ break;
+ }
+ m_arg->len = TYPE_LENGTH (arg_type);
+ m_arg->offset = accumulate_size;
+ accumulate_size = (accumulate_size + m_arg->len + 7) & ~7;
+ m_arg->contents = VALUE_CONTENTS(arg);
+ }
+
+ /* Determine required argument register loads, loading an argument register
+ is expensive as it uses three ptrace calls. */
+ required_arg_regs = accumulate_size / 8;
+ if (required_arg_regs > ALPHA_NUM_ARG_REGS)
+ required_arg_regs = ALPHA_NUM_ARG_REGS;
+
+ /* Make room for the arguments on the stack. */
+ if (accumulate_size < arg_regs_size)
+ accumulate_size = arg_regs_size;
+ sp -= accumulate_size;
+
+ /* Keep sp aligned to a multiple of 16 as the compiler does it too. */
+ sp &= ~15;
+
+ /* `Push' arguments on the stack. */
+ for (i = nargs; m_arg--, --i >= 0; )
+ write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
+ if (struct_return)
+ {
+ store_address (raw_buffer, sizeof (CORE_ADDR), struct_addr);
+ write_memory (sp, raw_buffer, sizeof (CORE_ADDR));
+ }
+
+ /* Load the argument registers. */
+ for (i = 0; i < required_arg_regs; i++)
+ {
+ LONGEST val;
+
+ val = read_memory_integer (sp + i * 8, 8);
+ write_register (A0_REGNUM + i, val);
+ write_register (FPA0_REGNUM + i, val);
+ }
+
+ return sp + arg_regs_size;
+}
+
+void
+alpha_push_dummy_frame()
+{
+ int ireg;
+ struct linked_proc_info *link;
+ alpha_extra_func_info_t proc_desc;
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ CORE_ADDR save_address;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ unsigned long mask;
+
+ link = (struct linked_proc_info *) xmalloc(sizeof (struct linked_proc_info));
+ link->next = linked_proc_desc_table;
+ linked_proc_desc_table = link;
+
+ proc_desc = &link->info;
+
+ /*
+ * The registers we must save are all those not preserved across
+ * procedure calls.
+ * In addition, we must save the PC and RA.
+ *
+ * Dummy frame layout:
+ * (high memory)
+ * Saved PC
+ * Saved F30
+ * ...
+ * Saved F0
+ * Saved R29
+ * ...
+ * Saved R0
+ * Saved R26 (RA)
+ * Parameter build area
+ * (low memory)
+ */
+
+/* MASK(i,j) == (1<<i) + (1<<(i+1)) + ... + (1<<j)). Assume i<=j<31. */
+#define MASK(i,j) (((1L << ((j)+1)) - 1) ^ ((1L << (i)) - 1))
+#define GEN_REG_SAVE_MASK (MASK(0,8) | MASK(16,29))
+#define GEN_REG_SAVE_COUNT 24
+#define FLOAT_REG_SAVE_MASK (MASK(0,1) | MASK(10,30))
+#define FLOAT_REG_SAVE_COUNT 23
+ /* The special register is the PC as we have no bit for it in the save masks.
+ alpha_frame_saved_pc knows where the pc is saved in a dummy frame. */
+#define SPECIAL_REG_SAVE_COUNT 1
+
+ PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
+ PROC_FREG_MASK(proc_desc) = FLOAT_REG_SAVE_MASK;
+ /* PROC_REG_OFFSET is the offset from the dummy frame to the saved RA,
+ but keep SP aligned to a multiple of 16. */
+ PROC_REG_OFFSET(proc_desc) =
+ - ((8 * (SPECIAL_REG_SAVE_COUNT
+ + GEN_REG_SAVE_COUNT
+ + FLOAT_REG_SAVE_COUNT)
+ + 15) & ~15);
+ PROC_FREG_OFFSET(proc_desc) =
+ PROC_REG_OFFSET(proc_desc) + 8 * GEN_REG_SAVE_COUNT;
+
+ /* Save general registers.
+ The return address register is the first saved register, all other
+ registers follow in ascending order.
+ The PC is saved immediately below the SP. */
+ save_address = sp + PROC_REG_OFFSET(proc_desc);
+ store_address (raw_buffer, 8, read_register (RA_REGNUM));
+ write_memory (save_address, raw_buffer, 8);
+ save_address += 8;
+ mask = PROC_REG_MASK(proc_desc) & 0xffffffffL;
+ for (ireg = 0; mask; ireg++, mask >>= 1)
+ if (mask & 1)
+ {
+ if (ireg == RA_REGNUM)
+ continue;
+ store_address (raw_buffer, 8, read_register (ireg));
+ write_memory (save_address, raw_buffer, 8);
+ save_address += 8;
+ }
+
+ store_address (raw_buffer, 8, read_register (PC_REGNUM));
+ write_memory (sp - 8, raw_buffer, 8);
+
+ /* Save floating point registers. */
+ save_address = sp + PROC_FREG_OFFSET(proc_desc);
+ mask = PROC_FREG_MASK(proc_desc) & 0xffffffffL;
+ for (ireg = 0; mask; ireg++, mask >>= 1)
+ if (mask & 1)
+ {
+ store_address (raw_buffer, 8, read_register (ireg + FP0_REGNUM));
+ write_memory (save_address, raw_buffer, 8);
+ save_address += 8;
+ }
+
+ /* Set and save the frame address for the dummy.
+ This is tricky. The only registers that are suitable for a frame save
+ are those that are preserved across procedure calls (s0-s6). But if
+ a read system call is interrupted and then a dummy call is made
+ (see testsuite/gdb.t17/interrupt.exp) the dummy call hangs till the read
+ is satisfied. Then it returns with the s0-s6 registers set to the values
+ on entry to the read system call and our dummy frame pointer would be
+ destroyed. So we save the dummy frame in the proc_desc and handle the
+ retrieval of the frame pointer of a dummy specifically. The frame register
+ is set to the virtual frame (pseudo) register, it's value will always
+ be read as zero and will help us to catch any errors in the dummy frame
+ retrieval code. */
+ PROC_DUMMY_FRAME(proc_desc) = sp;
+ PROC_FRAME_REG(proc_desc) = FP_REGNUM;
+ PROC_FRAME_OFFSET(proc_desc) = 0;
+ sp += PROC_REG_OFFSET(proc_desc);
+ write_register (SP_REGNUM, sp);
+
+ PROC_LOW_ADDR(proc_desc) = CALL_DUMMY_ADDRESS ();
+ PROC_HIGH_ADDR(proc_desc) = PROC_LOW_ADDR(proc_desc) + 4;
+
+ SET_PROC_DESC_IS_DUMMY(proc_desc);
+ PROC_PC_REG(proc_desc) = RA_REGNUM;
+}
+
+void
+alpha_pop_frame()
+{
+ register int regnum;
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR new_sp = frame->frame;
+
+ alpha_extra_func_info_t proc_desc = frame->proc_desc;
+
+ write_register (PC_REGNUM, FRAME_SAVED_PC(frame));
+ if (frame->saved_regs == NULL)
+ alpha_find_saved_regs (frame);
+ if (proc_desc)
+ {
+ for (regnum = 32; --regnum >= 0; )
+ if (PROC_REG_MASK(proc_desc) & (1 << regnum))
+ write_register (regnum,
+ read_memory_integer (frame->saved_regs->regs[regnum],
+ 8));
+ for (regnum = 32; --regnum >= 0; )
+ if (PROC_FREG_MASK(proc_desc) & (1 << regnum))
+ write_register (regnum + FP0_REGNUM,
+ read_memory_integer (frame->saved_regs->regs[regnum + FP0_REGNUM], 8));
+ }
+ write_register (SP_REGNUM, new_sp);
+ flush_cached_frames ();
+
+ if (proc_desc && PROC_DESC_IS_DUMMY(proc_desc))
+ {
+ struct linked_proc_info *pi_ptr, *prev_ptr;
+
+ for (pi_ptr = linked_proc_desc_table, prev_ptr = NULL;
+ pi_ptr != NULL;
+ prev_ptr = pi_ptr, pi_ptr = pi_ptr->next)
+ {
+ if (&pi_ptr->info == proc_desc)
+ break;
+ }
+
+ if (pi_ptr == NULL)
+ error ("Can't locate dummy extra frame info\n");
+
+ if (prev_ptr != NULL)
+ prev_ptr->next = pi_ptr->next;
+ else
+ linked_proc_desc_table = pi_ptr->next;
+
+ free (pi_ptr);
+ }
+}
+
+/* To skip prologues, I use this predicate. Returns either PC itself
+ if the code at PC does not look like a function prologue; otherwise
+ returns an address that (if we're lucky) follows the prologue. If
+ LENIENT, then we must skip everything which is involved in setting
+ up the frame (it's OK to skip more, just so long as we don't skip
+ anything which might clobber the registers which are being saved.
+ Currently we must not skip more on the alpha, but we might the lenient
+ stuff some day. */
+
+CORE_ADDR
+alpha_skip_prologue (pc, lenient)
+ CORE_ADDR pc;
+ int lenient;
+{
+ unsigned long inst;
+ int offset;
+ CORE_ADDR post_prologue_pc;
+ char buf[4];
+
+#ifdef GDB_TARGET_HAS_SHARED_LIBS
+ /* Silently return the unaltered pc upon memory errors.
+ This could happen on OSF/1 if decode_line_1 tries to skip the
+ prologue for quickstarted shared library functions when the
+ shared library is not yet mapped in.
+ Reading target memory is slow over serial lines, so we perform
+ this check only if the target has shared libraries. */
+ if (target_read_memory (pc, buf, 4))
+ return pc;
+#endif
+
+ /* See if we can determine the end of the prologue via the symbol table.
+ If so, then return either PC, or the PC after the prologue, whichever
+ is greater. */
+
+ post_prologue_pc = after_prologue (pc, NULL);
+
+ if (post_prologue_pc != 0)
+ return max (pc, post_prologue_pc);
+
+ /* Can't determine prologue from the symbol table, need to examine
+ instructions. */
+
+ /* Skip the typical prologue instructions. These are the stack adjustment
+ instruction and the instructions that save registers on the stack
+ or in the gcc frame. */
+ for (offset = 0; offset < 100; offset += 4)
+ {
+ int status;
+
+ status = read_memory_nobpt (pc + offset, buf, 4);
+ if (status)
+ memory_error (status, pc + offset);
+ inst = extract_unsigned_integer (buf, 4);
+
+ /* The alpha has no delay slots. But let's keep the lenient stuff,
+ we might need it for something else in the future. */
+ if (lenient && 0)
+ continue;
+
+ if ((inst & 0xffff0000) == 0x27bb0000) /* ldah $gp,n($t12) */
+ continue;
+ if ((inst & 0xffff0000) == 0x23bd0000) /* lda $gp,n($gp) */
+ continue;
+ if ((inst & 0xffff0000) == 0x23de0000) /* lda $sp,n($sp) */
+ continue;
+ else if ((inst & 0xfc1f0000) == 0xb41e0000
+ && (inst & 0xffff0000) != 0xb7fe0000)
+ continue; /* stq reg,n($sp) */
+ /* reg != $zero */
+ else if ((inst & 0xfc1f0000) == 0x9c1e0000
+ && (inst & 0xffff0000) != 0x9ffe0000)
+ continue; /* stt reg,n($sp) */
+ /* reg != $zero */
+ else if (inst == 0x47de040f) /* bis sp,sp,fp */
+ continue;
+ else
+ break;
+ }
+ return pc + offset;
+}
+
+#if 0
+/* Is address PC in the prologue (loosely defined) for function at
+ STARTADDR? */
+
+static int
+alpha_in_lenient_prologue (startaddr, pc)
+ CORE_ADDR startaddr;
+ CORE_ADDR pc;
+{
+ CORE_ADDR end_prologue = alpha_skip_prologue (startaddr, 1);
+ return pc >= startaddr && pc < end_prologue;
+}
+#endif
+
+/* The alpha needs a conversion between register and memory format if
+ the register is a floating point register and
+ memory format is float, as the register format must be double
+ or
+ memory format is an integer with 4 bytes or less, as the representation
+ of integers in floating point registers is different. */
+void
+alpha_register_convert_to_virtual (regnum, valtype, raw_buffer, virtual_buffer)
+ int regnum;
+ struct type *valtype;
+ char *raw_buffer;
+ char *virtual_buffer;
+{
+ if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
+ {
+ memcpy (virtual_buffer, raw_buffer, REGISTER_VIRTUAL_SIZE (regnum));
+ return;
+ }
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ double d = extract_floating (raw_buffer, REGISTER_RAW_SIZE (regnum));
+ store_floating (virtual_buffer, TYPE_LENGTH (valtype), d);
+ }
+ else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
+ {
+ unsigned LONGEST l;
+ l = extract_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum));
+ l = ((l >> 32) & 0xc0000000) | ((l >> 29) & 0x3fffffff);
+ store_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype), l);
+ }
+ else
+ error ("Cannot retrieve value from floating point register");
+}
+
+void
+alpha_register_convert_to_raw (valtype, regnum, virtual_buffer, raw_buffer)
+ struct type *valtype;
+ int regnum;
+ char *virtual_buffer;
+ char *raw_buffer;
+{
+ if (TYPE_LENGTH (valtype) >= REGISTER_RAW_SIZE (regnum))
+ {
+ memcpy (raw_buffer, virtual_buffer, REGISTER_RAW_SIZE (regnum));
+ return;
+ }
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ double d = extract_floating (virtual_buffer, TYPE_LENGTH (valtype));
+ store_floating (raw_buffer, REGISTER_RAW_SIZE (regnum), d);
+ }
+ else if (TYPE_CODE (valtype) == TYPE_CODE_INT && TYPE_LENGTH (valtype) <= 4)
+ {
+ unsigned LONGEST l;
+ if (TYPE_UNSIGNED (valtype))
+ l = extract_unsigned_integer (virtual_buffer, TYPE_LENGTH (valtype));
+ else
+ l = extract_signed_integer (virtual_buffer, TYPE_LENGTH (valtype));
+ l = ((l & 0xc0000000) << 32) | ((l & 0x3fffffff) << 29);
+ store_unsigned_integer (raw_buffer, REGISTER_RAW_SIZE (regnum), l);
+ }
+ else
+ error ("Cannot store value in floating point register");
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ extract and copy its value into `valbuf'. */
+
+void
+alpha_extract_return_value (valtype, regbuf, valbuf)
+ struct type *valtype;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ alpha_register_convert_to_virtual (FP0_REGNUM, valtype,
+ regbuf + REGISTER_BYTE (FP0_REGNUM),
+ valbuf);
+ else
+ memcpy (valbuf, regbuf + REGISTER_BYTE (V0_REGNUM), TYPE_LENGTH (valtype));
+}
+
+/* Given a return value in `regbuf' with a type `valtype',
+ write its value into the appropriate register. */
+
+void
+alpha_store_return_value (valtype, valbuf)
+ struct type *valtype;
+ char *valbuf;
+{
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ int regnum = V0_REGNUM;
+ int length = TYPE_LENGTH (valtype);
+
+ if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
+ {
+ regnum = FP0_REGNUM;
+ length = REGISTER_RAW_SIZE (regnum);
+ alpha_register_convert_to_raw (valtype, regnum, valbuf, raw_buffer);
+ }
+ else
+ memcpy (raw_buffer, valbuf, length);
+
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, length);
+}
+
+/* Just like reinit_frame_cache, but with the right arguments to be
+ callable as an sfunc. */
+
+static void
+reinit_frame_cache_sfunc (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ reinit_frame_cache ();
+}
+
+/* This is the definition of CALL_DUMMY_ADDRESS. It's a heuristic that is used
+ to find a convenient place in the text segment to stick a breakpoint to
+ detect the completion of a target function call (ala call_function_by_hand).
+ */
+
+CORE_ADDR
+alpha_call_dummy_address ()
+{
+ CORE_ADDR entry;
+ struct minimal_symbol *sym;
+
+ entry = entry_point_address ();
+
+ if (entry != 0)
+ return entry;
+
+ sym = lookup_minimal_symbol ("_Prelude", NULL, symfile_objfile);
+
+ if (!sym || MSYMBOL_TYPE (sym) != mst_text)
+ return 0;
+ else
+ return SYMBOL_VALUE_ADDRESS (sym) + 4;
+}
+
+void
+_initialize_alpha_tdep ()
+{
+ struct cmd_list_element *c;
+
+ tm_print_insn = print_insn_alpha;
+
+ /* Let the user set the fence post for heuristic_proc_start. */
+
+ /* We really would like to have both "0" and "unlimited" work, but
+ command.c doesn't deal with that. So make it a var_zinteger
+ because the user can always use "999999" or some such for unlimited. */
+ c = add_set_cmd ("heuristic-fence-post", class_support, var_zinteger,
+ (char *) &heuristic_fence_post,
+ "\
+Set the distance searched for the start of a function.\n\
+If you are debugging a stripped executable, GDB needs to search through the\n\
+program for the start of a function. This command sets the distance of the\n\
+search. The only need to set it is when debugging a stripped executable.",
+ &setlist);
+ /* We need to throw away the frame cache when we set this, since it
+ might change our ability to get backtraces. */
+ c->function.sfunc = reinit_frame_cache_sfunc;
+ add_show_from_set (c, &showlist);
+}
diff --git a/contrib/gdb/gdb/annotate.c b/contrib/gdb/gdb/annotate.c
new file mode 100644
index 0000000..282e171
--- /dev/null
+++ b/contrib/gdb/gdb/annotate.c
@@ -0,0 +1,540 @@
+/* Annotation routines for GDB.
+ Copyright 1986, 1989, 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "annotate.h"
+#include "value.h"
+#include "target.h"
+#include "gdbtypes.h"
+#include "breakpoint.h"
+
+static void print_value_flags PARAMS ((struct type *));
+
+static void
+print_value_flags (t)
+ struct type *t;
+{
+ if (can_dereference (t))
+ printf_filtered ("*");
+ else
+ printf_filtered ("-");
+}
+
+void
+breakpoints_changed ()
+{
+ if (annotation_level > 1)
+ {
+ target_terminal_ours ();
+ printf_unfiltered ("\n\032\032breakpoints-invalid\n");
+ }
+}
+
+void
+annotate_breakpoint (num)
+ int num;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoint %d\n", num);
+}
+
+void
+annotate_watchpoint (num)
+ int num;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032watchpoint %d\n", num);
+}
+
+void
+annotate_starting ()
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032starting\n");
+ }
+}
+
+void
+annotate_stopped ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032stopped\n");
+}
+
+void
+annotate_exited (exitstatus)
+ int exitstatus;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032exited %d\n", exitstatus);
+}
+
+void
+annotate_signalled ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signalled\n");
+}
+
+void
+annotate_signal_name ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-name\n");
+}
+
+void
+annotate_signal_name_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-name-end\n");
+}
+
+void
+annotate_signal_string ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-string\n");
+}
+
+void
+annotate_signal_string_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-string-end\n");
+}
+
+void
+annotate_signal ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal\n");
+}
+
+void
+annotate_breakpoints_headers ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoints-headers\n");
+}
+
+void
+annotate_field (num)
+ int num;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field %d\n", num);
+}
+
+void
+annotate_breakpoints_table ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoints-table\n");
+}
+
+void
+annotate_record ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032record\n");
+}
+
+void
+annotate_breakpoints_table_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032breakpoints-table-end\n");
+}
+
+void
+annotate_frames_invalid ()
+{
+ if (annotation_level > 1)
+ {
+ target_terminal_ours ();
+ printf_unfiltered ("\n\032\032frames-invalid\n");
+ }
+}
+
+void
+annotate_field_begin (type)
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032field-begin ");
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_field_name_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field-name-end\n");
+}
+
+void
+annotate_field_value ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field-value\n");
+}
+
+void
+annotate_field_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032field-end\n");
+}
+
+void
+annotate_quit ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032quit\n");
+}
+
+void
+annotate_error ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032error\n");
+}
+
+void
+annotate_error_begin ()
+{
+ if (annotation_level > 1)
+ fprintf_filtered (gdb_stderr, "\n\032\032error-begin\n");
+}
+
+void
+annotate_value_history_begin (histindex, type)
+ int histindex;
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032value-history-begin %d ", histindex);
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_value_begin (type)
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032value-begin ");
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_value_history_value ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032value-history-value\n");
+}
+
+void
+annotate_value_history_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032value-history-end\n");
+}
+
+void
+annotate_value_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032value-end\n");
+}
+
+void
+annotate_display_begin ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-begin\n");
+}
+
+void
+annotate_display_number_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-number-end\n");
+}
+
+void
+annotate_display_format ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-format\n");
+}
+
+void
+annotate_display_expression ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-expression\n");
+}
+
+void
+annotate_display_expression_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-expression-end\n");
+}
+
+void
+annotate_display_value ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-value\n");
+}
+
+void
+annotate_display_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032display-end\n");
+}
+
+void
+annotate_arg_begin ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032arg-begin\n");
+}
+
+void
+annotate_arg_name_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032arg-name-end\n");
+}
+
+void
+annotate_arg_value (type)
+ struct type *type;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032arg-value ");
+ print_value_flags (type);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_arg_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032arg-end\n");
+}
+
+void
+annotate_source (filename, line, character, mid, pc)
+ char *filename;
+ int line;
+ int character;
+ int mid;
+ CORE_ADDR pc;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032source ");
+ else
+ printf_filtered ("\032\032");
+
+ printf_filtered ("%s:%d:%d:%s:0x", filename,
+ line, character,
+ mid ? "middle" : "beg");
+ print_address_numeric (pc, 0, gdb_stdout);
+ printf_filtered ("\n");
+}
+
+void
+annotate_frame_begin (level, pc)
+ int level;
+ CORE_ADDR pc;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032frame-begin %d 0x", level);
+ print_address_numeric (pc, 0, gdb_stdout);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_function_call ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032function-call\n");
+}
+
+void
+annotate_signal_handler_caller ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032signal-handler-caller\n");
+}
+
+void
+annotate_frame_address ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-address\n");
+}
+
+void
+annotate_frame_address_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-address-end\n");
+}
+
+void
+annotate_frame_function_name ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-function-name\n");
+}
+
+void
+annotate_frame_args ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-args\n");
+}
+
+void
+annotate_frame_source_begin ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-begin\n");
+}
+
+void
+annotate_frame_source_file ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-file\n");
+}
+
+void
+annotate_frame_source_file_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-file-end\n");
+}
+
+void
+annotate_frame_source_line ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-line\n");
+}
+
+void
+annotate_frame_source_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-source-end\n");
+}
+
+void
+annotate_frame_where ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-where\n");
+}
+
+void
+annotate_frame_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032frame-end\n");
+}
+
+void
+annotate_array_section_begin (index, elttype)
+ int index;
+ struct type *elttype;
+{
+ if (annotation_level > 1)
+ {
+ printf_filtered ("\n\032\032array-section-begin %d ", index);
+ print_value_flags (elttype);
+ printf_filtered ("\n");
+ }
+}
+
+void
+annotate_elt_rep (repcount)
+ unsigned int repcount;
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032elt-rep %u\n", repcount);
+}
+
+void
+annotate_elt_rep_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032elt-rep-end\n");
+}
+
+void
+annotate_elt ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032elt\n");
+}
+
+void
+annotate_array_section_end ()
+{
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032array-section-end\n");
+}
+
+static void
+breakpoint_changed (b)
+ struct breakpoint *b;
+{
+ breakpoints_changed ();
+}
+
+void
+_initialize_annotate ()
+{
+ if (annotation_level > 1)
+ {
+ delete_breakpoint_hook = breakpoint_changed;
+ modify_breakpoint_hook = breakpoint_changed;
+ }
+}
diff --git a/contrib/gdb/gdb/annotate.h b/contrib/gdb/gdb/annotate.h
new file mode 100644
index 0000000..b91d140
--- /dev/null
+++ b/contrib/gdb/gdb/annotate.h
@@ -0,0 +1,95 @@
+/* Annotation routines for GDB.
+ Copyright 1986, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern void breakpoints_changed PARAMS ((void));
+
+extern void annotate_breakpoint PARAMS ((int));
+extern void annotate_watchpoint PARAMS ((int));
+extern void annotate_starting PARAMS ((void));
+extern void annotate_stopped PARAMS ((void));
+extern void annotate_exited PARAMS ((int));
+extern void annotate_signalled PARAMS ((void));
+extern void annotate_signal_name PARAMS ((void));
+extern void annotate_signal_name_end PARAMS ((void));
+extern void annotate_signal_string PARAMS ((void));
+extern void annotate_signal_string_end PARAMS ((void));
+extern void annotate_signal PARAMS ((void));
+
+extern void annotate_breakpoints_headers PARAMS ((void));
+extern void annotate_field PARAMS ((int));
+extern void annotate_breakpoints_table PARAMS ((void));
+extern void annotate_record PARAMS ((void));
+extern void annotate_breakpoints_table_end PARAMS ((void));
+
+extern void annotate_frames_invalid PARAMS ((void));
+
+#ifdef __STDC__
+struct type;
+#endif
+
+extern void annotate_field_begin PARAMS ((struct type *));
+extern void annotate_field_name_end PARAMS ((void));
+extern void annotate_field_value PARAMS ((void));
+extern void annotate_field_end PARAMS ((void));
+
+extern void annotate_quit PARAMS ((void));
+extern void annotate_error PARAMS ((void));
+extern void annotate_error_begin PARAMS ((void));
+
+extern void annotate_value_history_begin PARAMS ((int, struct type *));
+extern void annotate_value_begin PARAMS ((struct type *));
+extern void annotate_value_history_value PARAMS ((void));
+extern void annotate_value_history_end PARAMS ((void));
+extern void annotate_value_end PARAMS ((void));
+
+extern void annotate_display_begin PARAMS ((void));
+extern void annotate_display_number_end PARAMS ((void));
+extern void annotate_display_format PARAMS ((void));
+extern void annotate_display_expression PARAMS ((void));
+extern void annotate_display_expression_end PARAMS ((void));
+extern void annotate_display_value PARAMS ((void));
+extern void annotate_display_end PARAMS ((void));
+
+extern void annotate_arg_begin PARAMS ((void));
+extern void annotate_arg_name_end PARAMS ((void));
+extern void annotate_arg_value PARAMS ((struct type *));
+extern void annotate_arg_end PARAMS ((void));
+
+extern void annotate_source PARAMS ((char *, int, int, int, CORE_ADDR));
+
+extern void annotate_frame_begin PARAMS ((int, CORE_ADDR));
+extern void annotate_function_call PARAMS ((void));
+extern void annotate_signal_handler_caller PARAMS ((void));
+extern void annotate_frame_address PARAMS ((void));
+extern void annotate_frame_address_end PARAMS ((void));
+extern void annotate_frame_function_name PARAMS ((void));
+extern void annotate_frame_args PARAMS ((void));
+extern void annotate_frame_source_begin PARAMS ((void));
+extern void annotate_frame_source_file PARAMS ((void));
+extern void annotate_frame_source_file_end PARAMS ((void));
+extern void annotate_frame_source_line PARAMS ((void));
+extern void annotate_frame_source_end PARAMS ((void));
+extern void annotate_frame_where PARAMS ((void));
+extern void annotate_frame_end PARAMS ((void));
+
+extern void annotate_array_section_begin PARAMS ((int, struct type *));
+extern void annotate_elt_rep PARAMS ((unsigned int));
+extern void annotate_elt_rep_end PARAMS ((void));
+extern void annotate_elt PARAMS ((void));
+extern void annotate_array_section_end PARAMS ((void));
diff --git a/contrib/gdb/gdb/arm-convert.s b/contrib/gdb/gdb/arm-convert.s
new file mode 100644
index 0000000..416132b
--- /dev/null
+++ b/contrib/gdb/gdb/arm-convert.s
@@ -0,0 +1,16 @@
+ .text
+ .global _convert_from_extended
+
+_convert_from_extended:
+
+ ldfe f0,[a1]
+ stfd f0,[a2]
+ movs pc,lr
+
+ .global _convert_to_extended
+
+_convert_to_extended:
+
+ ldfd f0,[a1]
+ stfe f0,[a2]
+ movs pc,lr
diff --git a/contrib/gdb/gdb/arm-tdep.c b/contrib/gdb/gdb/arm-tdep.c
new file mode 100644
index 0000000..884e9d8
--- /dev/null
+++ b/contrib/gdb/gdb/arm-tdep.c
@@ -0,0 +1,826 @@
+/* Target-dependent code for the Acorn Risc Machine, for GDB, the GNU Debugger.
+ Copyright 1988, 1989, 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#if 0
+#include "gdbcore.h"
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#define N_TXTADDR(hdr) 0x8000
+#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
+
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include <errno.h>
+#endif
+
+
+#if 0
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+/* Structure to describe the chain of shared libraries used
+ by the execfile.
+ e.g. prog shares Xt which shares X11 which shares c. */
+
+struct shared_library {
+ struct exec_header header;
+ char name[SHLIBLEN];
+ CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
+ long data_offset; /* offset of data section in file */
+ int chan; /* file descriptor for the file */
+ struct shared_library *shares; /* library this one shares */
+};
+static struct shared_library *shlib = 0;
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+static CORE_ADDR unshared_text_start;
+
+/* extended header from exec file (for shared library info) */
+
+static struct exec_header exec_header;
+
+void
+exec_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+
+ /* Eliminate all traces of old exec file.
+ Mark text segment as empty. */
+
+ if (execfile)
+ free (execfile);
+ execfile = 0;
+ data_start = 0;
+ data_end -= exec_data_start;
+ text_start = 0;
+ unshared_text_start = 0;
+ text_end = 0;
+ exec_data_start = 0;
+ exec_data_end = 0;
+ if (execchan >= 0)
+ close (execchan);
+ execchan = -1;
+ if (shlib) {
+ close_shared_library(shlib);
+ shlib = 0;
+ }
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &execfile);
+ if (execchan < 0)
+ perror_with_name (filename);
+
+ {
+ struct stat st_exec;
+
+#ifdef HEADER_SEEK_FD
+ HEADER_SEEK_FD (execchan);
+#endif
+
+ val = myread (execchan, &exec_header, sizeof exec_header);
+ exec_aouthdr = exec_header.a_exec;
+
+ if (val < 0)
+ perror_with_name (filename);
+
+ text_start = 0x8000;
+
+ /* Look for shared library if needed */
+ if (exec_header.a_exec.a_magic & MF_USES_SL)
+ shlib = open_shared_library(exec_header.a_shlibname, text_start);
+
+ text_offset = N_TXTOFF (exec_aouthdr);
+ exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
+
+ if (shlib) {
+ unshared_text_start = shared_text_end(shlib) & ~0x7fff;
+ stack_start = shlib->header.a_exec.a_sldatabase;
+ stack_end = STACK_END_ADDR;
+ } else
+ unshared_text_start = 0x8000;
+ text_end = unshared_text_start + exec_aouthdr.a_text;
+
+ exec_data_start = unshared_text_start + exec_aouthdr.a_text;
+ exec_data_end = exec_data_start + exec_aouthdr.a_data;
+
+ data_start = exec_data_start;
+ data_end += exec_data_start;
+
+ fstat (execchan, &st_exec);
+ exec_mtime = st_exec.st_mtime;
+ }
+
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No exec file now.\n");
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+}
+#endif
+
+#if 0
+/* Read from the program's memory (except for inferior processes).
+ This function is misnamed, since it only reads, never writes; and
+ since it will use the core file and/or executable file as necessary.
+
+ It should be extended to write as well as read, FIXME, for patching files.
+
+ Return 0 if address could be read, EIO if addresss out of bounds. */
+
+int
+xfer_core_file (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ register int val;
+ int xferchan;
+ char **xferfile;
+ int fileptr;
+ int returnval = 0;
+
+ while (len > 0)
+ {
+ xferfile = 0;
+ xferchan = 0;
+
+ /* Determine which file the next bunch of addresses reside in,
+ and where in the file. Set the file's read/write pointer
+ to point at the proper place for the desired address
+ and set xferfile and xferchan for the correct file.
+
+ If desired address is nonexistent, leave them zero.
+
+ i is set to the number of bytes that can be handled
+ along with the next address.
+
+ We put the most likely tests first for efficiency. */
+
+ /* Note that if there is no core file
+ data_start and data_end are equal. */
+ if (memaddr >= data_start && memaddr < data_end)
+ {
+ i = min (len, data_end - memaddr);
+ fileptr = memaddr - data_start + data_offset;
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+ /* Note that if there is no core file
+ stack_start and stack_end define the shared library data. */
+ else if (memaddr >= stack_start && memaddr < stack_end)
+ {
+ if (corechan < 0) {
+ struct shared_library *lib;
+ for (lib = shlib; lib; lib = lib->shares)
+ if (memaddr >= lib->header.a_exec.a_sldatabase &&
+ memaddr < lib->header.a_exec.a_sldatabase +
+ lib->header.a_exec.a_data)
+ break;
+ if (lib) {
+ i = min (len, lib->header.a_exec.a_sldatabase +
+ lib->header.a_exec.a_data - memaddr);
+ fileptr = lib->data_offset + memaddr -
+ lib->header.a_exec.a_sldatabase;
+ xferfile = execfile;
+ xferchan = lib->chan;
+ }
+ } else {
+ i = min (len, stack_end - memaddr);
+ fileptr = memaddr - stack_start + stack_offset;
+ xferfile = &corefile;
+ xferchan = corechan;
+ }
+ }
+ else if (corechan < 0
+ && memaddr >= exec_data_start && memaddr < exec_data_end)
+ {
+ i = min (len, exec_data_end - memaddr);
+ fileptr = memaddr - exec_data_start + exec_data_offset;
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ else if (memaddr >= text_start && memaddr < text_end)
+ {
+ struct shared_library *lib;
+ for (lib = shlib; lib; lib = lib->shares)
+ if (memaddr >= lib->text_start &&
+ memaddr < lib->text_start + lib->header.a_exec.a_text)
+ break;
+ if (lib) {
+ i = min (len, lib->header.a_exec.a_text +
+ lib->text_start - memaddr);
+ fileptr = memaddr - lib->text_start + text_offset;
+ xferfile = &execfile;
+ xferchan = lib->chan;
+ } else {
+ i = min (len, text_end - memaddr);
+ fileptr = memaddr - unshared_text_start + text_offset;
+ xferfile = &execfile;
+ xferchan = execchan;
+ }
+ }
+ else if (memaddr < text_start)
+ {
+ i = min (len, text_start - memaddr);
+ }
+ else if (memaddr >= text_end
+ && memaddr < (corechan >= 0? data_start : exec_data_start))
+ {
+ i = min (len, data_start - memaddr);
+ }
+ else if (corechan >= 0
+ && memaddr >= data_end && memaddr < stack_start)
+ {
+ i = min (len, stack_start - memaddr);
+ }
+ else if (corechan < 0 && memaddr >= exec_data_end)
+ {
+ i = min (len, - memaddr);
+ }
+ else if (memaddr >= stack_end && stack_end != 0)
+ {
+ i = min (len, - memaddr);
+ }
+ else
+ {
+ /* Address did not classify into one of the known ranges.
+ This shouldn't happen; we catch the endpoints. */
+ fatal ("Internal: Bad case logic in xfer_core_file.");
+ }
+
+ /* Now we know which file to use.
+ Set up its pointer and transfer the data. */
+ if (xferfile)
+ {
+ if (*xferfile == 0)
+ if (xferfile == &execfile)
+ error ("No program file to examine.");
+ else
+ error ("No core dump file or running program to examine.");
+ val = lseek (xferchan, fileptr, 0);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ val = myread (xferchan, myaddr, i);
+ if (val < 0)
+ perror_with_name (*xferfile);
+ }
+ /* If this address is for nonexistent memory,
+ read zeros if reading, or do nothing if writing.
+ Actually, we never right. */
+ else
+ {
+ memset (myaddr, '\0', i);
+ returnval = EIO;
+ }
+
+ memaddr += i;
+ myaddr += i;
+ len -= i;
+ }
+ return returnval;
+}
+#endif
+
+/* APCS (ARM procedure call standard) defines the following prologue:
+
+ mov ip, sp
+ [stmfd sp!, {a1,a2,a3,a4}]
+ stmfd sp!, {...,fp,ip,lr,pc}
+ [stfe f7, [sp, #-12]!]
+ [stfe f6, [sp, #-12]!]
+ [stfe f5, [sp, #-12]!]
+ [stfe f4, [sp, #-12]!]
+ sub fp, ip, #nn // nn == 20 or 4 depending on second ins
+*/
+
+CORE_ADDR
+skip_prologue(pc)
+CORE_ADDR pc;
+{
+ CORE_ADDR skip_pc = pc;
+#if 0
+ union insn_fmt op;
+
+ op.ins = read_memory_integer(skip_pc, 4);
+ /* look for the "mov ip,sp" */
+ if (op.generic.type != TYPE_ARITHMETIC ||
+ op.arith.opcode != OPCODE_MOV ||
+ op.arith.dest != SPTEMP ||
+ op.arith.operand2 != SP) return pc;
+ skip_pc += 4;
+ /* skip the "stmfd sp!,{a1,a2,a3,a4}" if its there */
+ op.ins = read_memory_integer(skip_pc, 4);
+ if (op.generic.type == TYPE_BLOCK_BRANCH &&
+ op.generic.subtype == SUBTYPE_BLOCK &&
+ op.block.mask == 0xf &&
+ op.block.base == SP &&
+ op.block.is_load == 0 &&
+ op.block.writeback == 1 &&
+ op.block.increment == 0 &&
+ op.block.before == 1) skip_pc += 4;
+ /* skip the "stmfd sp!,{...,fp,ip,lr,pc} */
+ op.ins = read_memory_integer(skip_pc, 4);
+ if (op.generic.type != TYPE_BLOCK_BRANCH ||
+ op.generic.subtype != SUBTYPE_BLOCK ||
+ /* the mask should look like 110110xxxxxx0000 */
+ (op.block.mask & 0xd800) != 0xd800 ||
+ op.block.base != SP ||
+ op.block.is_load != 0 ||
+ op.block.writeback != 1 ||
+ op.block.increment != 0 ||
+ op.block.before != 1) return pc;
+ skip_pc += 4;
+ /* check for "sub fp,ip,#nn" */
+ op.ins = read_memory_integer(skip_pc, 4);
+ if (op.generic.type != TYPE_ARITHMETIC ||
+ op.arith.opcode != OPCODE_SUB ||
+ op.arith.dest != FP ||
+ op.arith.operand1 != SPTEMP) return pc;
+#endif
+ return skip_pc + 4;
+}
+
+void
+arm_frame_find_saved_regs (frame_info, saved_regs_addr)
+ struct frame_info *frame_info;
+ struct frame_saved_regs *saved_regs_addr;
+{
+ register int regnum;
+ register int frame;
+ register int next_addr;
+ register int return_data_save;
+ register int saved_register_mask;
+
+ memset (saved_regs_addr, '\0', sizeof (*saved_regs_addr));
+ frame = frame_info->frame;
+ return_data_save = read_memory_integer (frame, 4) & 0x03fffffc - 12;
+ saved_register_mask = read_memory_integer (return_data_save, 4);
+ next_addr = frame - 12;
+ for (regnum = 4; regnum < 10; regnum++)
+ if (saved_register_mask & (1 << regnum))
+ {
+ next_addr -= 4;
+ saved_regs_addr->regs[regnum] = next_addr;
+ }
+ if (read_memory_integer (return_data_save + 4, 4) == 0xed6d7103)
+ {
+ next_addr -= 12;
+ saved_regs_addr->regs[F0_REGNUM + 7] = next_addr;
+ }
+ if (read_memory_integer (return_data_save + 8, 4) == 0xed6d6103)
+ {
+ next_addr -= 12;
+ saved_regs_addr->regs[F0_REGNUM + 6] = next_addr;
+ }
+ if (read_memory_integer (return_data_save + 12, 4) == 0xed6d5103)
+ {
+ next_addr -= 12;
+ saved_regs_addr->regs[F0_REGNUM + 5] = next_addr;
+ }
+ if (read_memory_integer(return_data_save + 16, 4) == 0xed6d4103)
+ {
+ next_addr -= 12;
+ saved_regs_addr->regs[F0_REGNUM + 4] = next_addr;
+ }
+ saved_regs_addr->regs[SP_REGNUM] = next_addr;
+ saved_regs_addr->regs[PC_REGNUM] = frame - 4;
+ saved_regs_addr->regs[PS_REGNUM] = frame - 4;
+ saved_regs_addr->regs[FP_REGNUM] = frame - 12;
+}
+
+static void
+print_fpu_flags(flags)
+int flags;
+{
+ if (flags & (1 << 0)) fputs("IVO ", stdout);
+ if (flags & (1 << 1)) fputs("DVZ ", stdout);
+ if (flags & (1 << 2)) fputs("OFL ", stdout);
+ if (flags & (1 << 3)) fputs("UFL ", stdout);
+ if (flags & (1 << 4)) fputs("INX ", stdout);
+ putchar('\n');
+}
+
+void
+arm_float_info()
+{
+ register unsigned long status = read_register(FPS_REGNUM);
+ int type;
+
+ type = (status >> 24) & 127;
+ printf("%s FPU type %d\n",
+ (status & (1<<31)) ? "Hardware" : "Software",
+ type);
+ fputs("mask: ", stdout);
+ print_fpu_flags(status >> 16);
+ fputs("flags: ", stdout);
+ print_fpu_flags(status);
+}
+
+
+static void arm_othernames()
+{
+ static int toggle;
+ static char *original[] = ORIGINAL_REGISTER_NAMES;
+ static char *extra_crispy[] = ADDITIONAL_REGISTER_NAMES;
+
+ memcpy (reg_names, toggle ? extra_crispy : original, sizeof(original));
+ toggle = !toggle;
+}
+void
+_initialize_arm_tdep ()
+{
+ tm_print_insn = print_insn_little_arm;
+ add_com ("othernames", class_obscure, arm_othernames);
+}
+
+/* FIXME: Fill in with the 'right thing', see asm
+ template in arm-convert.s */
+
+void
+convert_from_extended (ptr, dbl)
+void *ptr;
+double *dbl;
+{
+ *dbl = *(double*)ptr;
+}
+
+
+void
+convert_to_extended (dbl, ptr)
+void *ptr;
+double *dbl;
+{
+ *(double*)ptr = *dbl;
+}
+
+
+int
+arm_nullified_insn (inst)
+ unsigned long inst;
+{
+ unsigned long cond = inst & 0xf0000000;
+ unsigned long status_reg;
+
+ if (cond == INST_AL || cond == INST_NV)
+ return 0;
+
+ status_reg = read_register (PS_REGNUM);
+
+ switch (cond)
+ {
+ case INST_EQ:
+ return ((status_reg & FLAG_Z) == 0);
+ case INST_NE:
+ return ((status_reg & FLAG_Z) != 0);
+ case INST_CS:
+ return ((status_reg & FLAG_C) == 0);
+ case INST_CC:
+ return ((status_reg & FLAG_C) != 0);
+ case INST_MI:
+ return ((status_reg & FLAG_N) == 0);
+ case INST_PL:
+ return ((status_reg & FLAG_N) != 0);
+ case INST_VS:
+ return ((status_reg & FLAG_V) == 0);
+ case INST_VC:
+ return ((status_reg & FLAG_V) != 0);
+ case INST_HI:
+ return ((status_reg & (FLAG_C | FLAG_Z)) != FLAG_C);
+ case INST_LS:
+ return (((status_reg & (FLAG_C | FLAG_Z)) ^ FLAG_C) == 0);
+ case INST_GE:
+ return (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0));
+ case INST_LT:
+ return (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0));
+ case INST_GT:
+ return (((status_reg & FLAG_Z) != 0) ||
+ (((status_reg & FLAG_N) == 0) != ((status_reg & FLAG_V) == 0)));
+ case INST_LE:
+ return (((status_reg & FLAG_Z) == 0) &&
+ (((status_reg & FLAG_N) == 0) == ((status_reg & FLAG_V) == 0)));
+ }
+ return 0;
+}
+
+
+
+/* taken from remote-arm.c .. */
+
+#define submask(x) ((1L << ((x) + 1)) - 1)
+#define bit(obj,st) (((obj) & (1L << (st))) >> st)
+#define bits(obj,st,fn) \
+ (((obj) & submask (fn) & ~ submask ((st) - 1)) >> (st))
+#define sbits(obj,st,fn) \
+ ((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st))))
+#define BranchDest(addr,instr) \
+ ((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
+#define ARM_PC_32 1
+
+static unsigned long
+shifted_reg_val (inst, carry, pc_val)
+ unsigned long inst;
+ int carry;
+ unsigned long pc_val;
+{
+ unsigned long res, shift;
+ int rm = bits (inst, 0, 3);
+ unsigned long shifttype = bits (inst, 5, 6);
+
+ if (bit(inst, 4))
+ {
+ int rs = bits (inst, 8, 11);
+ shift = (rs == 15 ? pc_val + 8 : read_register (rs)) & 0xFF;
+ }
+ else
+ shift = bits (inst, 7, 11);
+
+ res = (rm == 15
+ ? ((pc_val | (ARM_PC_32 ? 0 : read_register (PS_REGNUM)))
+ + (bit (inst, 4) ? 12 : 8))
+ : read_register (rm));
+
+ switch (shifttype)
+ {
+ case 0: /* LSL */
+ res = shift >= 32 ? 0 : res << shift;
+ break;
+
+ case 1: /* LSR */
+ res = shift >= 32 ? 0 : res >> shift;
+ break;
+
+ case 2: /* ASR */
+ if (shift >= 32) shift = 31;
+ res = ((res & 0x80000000L)
+ ? ~((~res) >> shift) : res >> shift);
+ break;
+
+ case 3: /* ROR/RRX */
+ shift &= 31;
+ if (shift == 0)
+ res = (res >> 1) | (carry ? 0x80000000L : 0);
+ else
+ res = (res >> shift) | (res << (32-shift));
+ break;
+ }
+
+ return res & 0xffffffff;
+}
+
+
+CORE_ADDR
+arm_get_next_pc (pc)
+ CORE_ADDR pc;
+{
+ unsigned long pc_val = (unsigned long) pc;
+ unsigned long this_instr = read_memory_integer (pc, 4);
+ unsigned long status = read_register (PS_REGNUM);
+ CORE_ADDR nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
+
+ if (! arm_nullified_insn (this_instr))
+ {
+ switch (bits(this_instr, 24, 27))
+ {
+ case 0x0: case 0x1: /* data processing */
+ case 0x2: case 0x3:
+ {
+ unsigned long operand1, operand2, result = 0;
+ unsigned long rn;
+ int c;
+
+ if (bits(this_instr, 12, 15) != 15)
+ break;
+
+ if (bits (this_instr, 22, 25) == 0
+ && bits (this_instr, 4, 7) == 9) /* multiply */
+ error ("Illegal update to pc in instruction");
+
+ /* Multiply into PC */
+ c = (status & FLAG_C) ? 1 : 0;
+ rn = bits (this_instr, 16, 19);
+ operand1 = (rn == 15) ? pc_val + 8 : read_register (rn);
+
+ if (bit (this_instr, 25))
+ {
+ unsigned long immval = bits (this_instr, 0, 7);
+ unsigned long rotate = 2 * bits (this_instr, 8, 11);
+ operand2 = ((immval >> rotate) | (immval << (32-rotate))
+ & 0xffffffff);
+ }
+ else /* operand 2 is a shifted register */
+ operand2 = shifted_reg_val (this_instr, c, pc_val);
+
+ switch (bits (this_instr, 21, 24))
+ {
+ case 0x0: /*and*/
+ result = operand1 & operand2;
+ break;
+
+ case 0x1: /*eor*/
+ result = operand1 ^ operand2;
+ break;
+
+ case 0x2: /*sub*/
+ result = operand1 - operand2;
+ break;
+
+ case 0x3: /*rsb*/
+ result = operand2 - operand1;
+ break;
+
+ case 0x4: /*add*/
+ result = operand1 + operand2;
+ break;
+
+ case 0x5: /*adc*/
+ result = operand1 + operand2 + c;
+ break;
+
+ case 0x6: /*sbc*/
+ result = operand1 - operand2 + c;
+ break;
+
+ case 0x7: /*rsc*/
+ result = operand2 - operand1 + c;
+ break;
+
+ case 0x8: case 0x9: case 0xa: case 0xb: /* tst, teq, cmp, cmn */
+ result = (unsigned long) nextpc;
+ break;
+
+ case 0xc: /*orr*/
+ result = operand1 | operand2;
+ break;
+
+ case 0xd: /*mov*/
+ /* Always step into a function. */
+ result = operand2;
+ break;
+
+ case 0xe: /*bic*/
+ result = operand1 & ~operand2;
+ break;
+
+ case 0xf: /*mvn*/
+ result = ~operand2;
+ break;
+ }
+ nextpc = (CORE_ADDR) ADDR_BITS_REMOVE (result);
+
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ break;
+ }
+
+ case 0x4: case 0x5: /* data transfer */
+ case 0x6: case 0x7:
+ if (bit (this_instr, 20))
+ {
+ /* load */
+ if (bits (this_instr, 12, 15) == 15)
+ {
+ /* rd == pc */
+ unsigned long rn;
+ unsigned long base;
+
+ if (bit (this_instr, 22))
+ error ("Illegal update to pc in instruction");
+
+ /* byte write to PC */
+ rn = bits (this_instr, 16, 19);
+ base = (rn == 15) ? pc_val + 8 : read_register (rn);
+ if (bit (this_instr, 24))
+ {
+ /* pre-indexed */
+ int c = (status & FLAG_C) ? 1 : 0;
+ unsigned long offset =
+ (bit (this_instr, 25)
+ ? shifted_reg_val (this_instr, c, pc_val)
+ : bits (this_instr, 0, 11));
+
+ if (bit (this_instr, 23))
+ base += offset;
+ else
+ base -= offset;
+ }
+ nextpc = (CORE_ADDR) read_memory_integer ((CORE_ADDR) base,
+ 4);
+
+ nextpc = ADDR_BITS_REMOVE (nextpc);
+
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ }
+ }
+ break;
+
+ case 0x8: case 0x9: /* block transfer */
+ if (bit (this_instr, 20))
+ {
+ /* LDM */
+ if (bit (this_instr, 15))
+ {
+ /* loading pc */
+ int offset = 0;
+
+ if (bit (this_instr, 23))
+ {
+ /* up */
+ unsigned long reglist = bits (this_instr, 0, 14);
+ unsigned long regbit;
+
+ for (; reglist != 0; reglist &= ~regbit)
+ {
+ regbit = reglist & (-reglist);
+ offset += 4;
+ }
+
+ if (bit (this_instr, 24)) /* pre */
+ offset += 4;
+ }
+ else if (bit (this_instr, 24))
+ offset = -4;
+
+ {
+ unsigned long rn_val =
+ read_register (bits (this_instr, 16, 19));
+ nextpc =
+ (CORE_ADDR) read_memory_integer ((CORE_ADDR) (rn_val
+ + offset),
+ 4);
+ }
+ nextpc = ADDR_BITS_REMOVE (nextpc);
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ }
+ }
+ break;
+
+ case 0xb: /* branch & link */
+ case 0xa: /* branch */
+ {
+ nextpc = BranchDest (pc, this_instr);
+
+ nextpc = ADDR_BITS_REMOVE (nextpc);
+ if (nextpc == pc)
+ error ("Infinite loop detected");
+ break;
+ }
+
+ case 0xc: case 0xd:
+ case 0xe: /* coproc ops */
+ case 0xf: /* SWI */
+ break;
+
+ default:
+ fprintf (stderr, "Bad bit-field extraction\n");
+ return (pc);
+ }
+ }
+
+ return nextpc;
+}
+
diff --git a/contrib/gdb/gdb/arm-xdep.c b/contrib/gdb/gdb/arm-xdep.c
new file mode 100644
index 0000000..b855ac8
--- /dev/null
+++ b/contrib/gdb/gdb/arm-xdep.c
@@ -0,0 +1,276 @@
+/* Acorn Risc Machine host machine support.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "arm-opcode.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#define N_TXTADDR(hdr) 0x8000
+#define N_DATADDR(hdr) (hdr.a_text + 0x8000)
+
+#include "gdbcore.h"
+
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include <errno.h>
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct user u;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
+ - KERNEL_U_ADDR;
+
+ registers_fetched ();
+
+ for (regno = 0; regno < 16; regno++)
+ {
+ regaddr = offset + regno * 4;
+ *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ if (regno == PC_REGNUM)
+ *(int *)&buf[0] = GET_PC_PART(*(int *)&buf[0]);
+ supply_register (regno, buf);
+ }
+ *(int *)&buf[0] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) (offset + PC*4), 0);
+ supply_register (PS_REGNUM, buf); /* set virtual register ps same as pc */
+
+ /* read the floating point registers */
+ offset = (char *) &u.u_fp_regs - (char *)&u;
+ *(int *)buf = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0);
+ supply_register (FPS_REGNUM, buf);
+ for (regno = 16; regno < 24; regno++) {
+ regaddr = offset + 4 + 12 * (regno - 16);
+ for (i = 0; i < 12; i += sizeof(int))
+ *(int *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr + i), 0);
+ supply_register (regno, buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct user u;
+ unsigned long value;
+ unsigned int offset = (char *) &u.u_ar0 - (char *) &u;
+ offset = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0)
+ - KERNEL_U_ADDR;
+
+ if (regno >= 0) {
+ if (regno >= 16) return;
+ regaddr = offset + 4 * regno;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else for (regno = 0; regno < 15; regno++)
+ {
+ regaddr = offset + regno * 4;
+ errno = 0;
+ value = read_register(regno);
+ if (regno == PC_REGNUM)
+ value = SET_PC_PART(read_register (PS_REGNUM), value);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, value);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+/* Structure to describe the chain of shared libraries used
+ by the execfile.
+ e.g. prog shares Xt which shares X11 which shares c. */
+
+struct shared_library {
+ struct exec_header header;
+ char name[SHLIBLEN];
+ CORE_ADDR text_start; /* CORE_ADDR of 1st byte of text, this file */
+ long data_offset; /* offset of data section in file */
+ int chan; /* file descriptor for the file */
+ struct shared_library *shares; /* library this one shares */
+};
+static struct shared_library *shlib = 0;
+
+/* Hook for `exec_file_command' command to call. */
+
+extern void (*exec_file_display_hook) ();
+
+static CORE_ADDR unshared_text_start;
+
+/* extended header from exec file (for shared library info) */
+
+static struct exec_header exec_header;
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset, fp_reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+
+ /* We are depending on exec_file_command having been called
+ previously to set exec_data_start. Since the executable
+ and the core file share the same text segment, the address
+ of the data segment will be the same in both. */
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ stack_start = stack_end - NBPG * u.u_ssize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+ fp_reg_offset = (char *) &u.u_fp_regs - (char *)&u;
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ if (regno < 16)
+ val = lseek (corechan, reg_offset + 4 * regno, 0);
+ else if (regno < 24)
+ val = lseek (corechan, fp_reg_offset + 4 + 12*(regno - 24), 0);
+ else if (regno == 24)
+ val = lseek (corechan, fp_reg_offset, 0);
+ else if (regno == 25)
+ val = lseek (corechan, reg_offset + 4 * PC, 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (reg_names[regno])
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+
+ if (regno == PC_REGNUM)
+ *(int *)buf = GET_PC_PART(*(int *)buf);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename, NULL);
+ }
+
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf ("No core file now.\n");
+}
diff --git a/contrib/gdb/gdb/bcache.c b/contrib/gdb/gdb/bcache.c
new file mode 100644
index 0000000..ae73c11
--- /dev/null
+++ b/contrib/gdb/gdb/bcache.c
@@ -0,0 +1,189 @@
+/* Implement a cached obstack.
+ Written by Fred Fish (fnf@cygnus.com)
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bcache.h"
+#include "gdb_string.h" /* For memcpy declaration */
+
+/* FIXME: Incredibly simplistic hash generator. Probably way too expensive
+ (consider long strings) and unlikely to have good distribution across hash
+ values for typical input. */
+
+static unsigned int
+hash (bytes, count)
+ void *bytes;
+ int count;
+{
+ unsigned int len;
+ unsigned long hashval;
+ unsigned int c;
+ const unsigned char *data = bytes;
+
+ hashval = 0;
+ len = 0;
+ while (count-- > 0)
+ {
+ c = *data++;
+ hashval += c + (c << 17);
+ hashval ^= hashval >> 2;
+ ++len;
+ }
+ hashval += len + (len << 17);
+ hashval ^= hashval >> 2;
+ return (hashval % BCACHE_HASHSIZE);
+}
+
+static void *
+lookup_cache (bytes, count, hashval, bcachep)
+ void *bytes;
+ int count;
+ int hashval;
+ struct bcache *bcachep;
+{
+ void *location = NULL;
+ struct hashlink **hashtablep;
+ struct hashlink *linkp;
+
+ hashtablep = bcachep -> indextable[count];
+ if (hashtablep != NULL)
+ {
+ linkp = hashtablep[hashval];
+ while (linkp != NULL)
+ {
+ if (memcmp (BCACHE_DATA (linkp), bytes, count) == 0)
+ {
+ location = BCACHE_DATA (linkp);
+ break;
+ }
+ linkp = linkp -> next;
+ }
+ }
+ return (location);
+}
+
+void *
+bcache (bytes, count, bcachep)
+ void *bytes;
+ int count;
+ struct bcache *bcachep;
+{
+ int hashval;
+ void *location;
+ struct hashlink *newlink;
+ struct hashlink **linkpp;
+ struct hashlink ***hashtablepp;
+
+ if (count >= BCACHE_MAXLENGTH)
+ {
+ /* Rare enough to just stash unique copies */
+ location = (void *) obstack_alloc (&bcachep->cache, count);
+ bcachep -> cache_bytes += count;
+ memcpy (location, bytes, count);
+ bcachep -> bcache_overflows++;
+ }
+ else
+ {
+ hashval = hash (bytes, count);
+ location = lookup_cache (bytes, count, hashval, bcachep);
+ if (location != NULL)
+ {
+ bcachep -> cache_savings += count;
+ bcachep -> cache_hits++;
+ }
+ else
+ {
+ bcachep -> cache_misses++;
+ hashtablepp = &bcachep -> indextable[count];
+ if (*hashtablepp == NULL)
+ {
+ *hashtablepp = (struct hashlink **)
+ obstack_alloc (&bcachep->cache, BCACHE_HASHSIZE * sizeof (struct hashlink *));
+ bcachep -> cache_bytes += BCACHE_HASHSIZE * sizeof (struct hashlink *);
+ memset (*hashtablepp, 0, BCACHE_HASHSIZE * sizeof (struct hashlink *));
+ }
+ linkpp = &(*hashtablepp)[hashval];
+ newlink = (struct hashlink *)
+ obstack_alloc (&bcachep->cache, BCACHE_DATA_ALIGNMENT + count);
+ bcachep -> cache_bytes += BCACHE_DATA_ALIGNMENT + count;
+ memcpy (BCACHE_DATA (newlink), bytes, count);
+ newlink -> next = *linkpp;
+ *linkpp = newlink;
+ location = BCACHE_DATA (newlink);
+ }
+ }
+ return (location);
+}
+
+#if MAINTENANCE_CMDS
+
+void
+print_bcache_statistics (bcachep, id)
+ struct bcache *bcachep;
+ char *id;
+{
+ struct hashlink **hashtablep;
+ struct hashlink *linkp;
+ int tidx, tcount, hidx, hcount, lcount, lmax, temp, lmaxt, lmaxh;
+
+ for (lmax = lcount = tcount = hcount = tidx = 0; tidx < BCACHE_MAXLENGTH; tidx++)
+ {
+ hashtablep = bcachep -> indextable[tidx];
+ if (hashtablep != NULL)
+ {
+ tcount++;
+ for (hidx = 0; hidx < BCACHE_HASHSIZE; hidx++)
+ {
+ linkp = hashtablep[hidx];
+ if (linkp != NULL)
+ {
+ hcount++;
+ for (temp = 0; linkp != NULL; linkp = linkp -> next)
+ {
+ lcount++;
+ temp++;
+ }
+ if (temp > lmax)
+ {
+ lmax = temp;
+ lmaxt = tidx;
+ lmaxh = hidx;
+ }
+ }
+ }
+ }
+ }
+ printf_filtered (" Cached '%s' statistics:\n", id);
+ printf_filtered (" Cache hits: %d\n", bcachep -> cache_hits);
+ printf_filtered (" Cache misses: %d\n", bcachep -> cache_misses);
+ printf_filtered (" Cache hit ratio: %d%%\n", ((bcachep -> cache_hits) * 100) / (bcachep -> cache_hits + bcachep -> cache_misses));
+ printf_filtered (" Space used for caching: %d\n", bcachep -> cache_bytes);
+ printf_filtered (" Space saved by cache hits: %d\n", bcachep -> cache_savings);
+ printf_filtered (" Number of bcache overflows: %d\n", bcachep -> bcache_overflows);
+ printf_filtered (" Number of index buckets used: %d\n", tcount);
+ printf_filtered (" Number of hash table buckets used: %d\n", hcount);
+ printf_filtered (" Number of chained items: %d\n", lcount);
+ printf_filtered (" Average hash table population: %d%%\n",
+ (hcount * 100) / (tcount * BCACHE_HASHSIZE));
+ printf_filtered (" Average chain length %d\n", lcount / hcount);
+ printf_filtered (" Maximum chain length %d at %d:%d\n", lmax, lmaxt, lmaxh);
+}
+
+#endif /* MAINTENANCE_CMDS */
diff --git a/contrib/gdb/gdb/bcache.h b/contrib/gdb/gdb/bcache.h
new file mode 100644
index 0000000..48b71e2
--- /dev/null
+++ b/contrib/gdb/gdb/bcache.h
@@ -0,0 +1,72 @@
+/* Include file cached obstack implementation.
+ Written by Fred Fish (fnf@cygnus.com)
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef BCACHE_H
+#define BCACHE_H 1
+
+#define BCACHE_HASHLENGTH 12 /* Number of bits in hash value */
+#define BCACHE_HASHSIZE (1 << BCACHE_HASHLENGTH)
+#define BCACHE_MAXLENGTH 128
+
+/* Note that the user data is stored in data[]. Since it can be any type,
+ it needs to have the same alignment as the most strict alignment of
+ any type on the host machine. So do it the same way obstack does. */
+
+struct hashlink {
+ struct hashlink *next;
+ union {
+ char data[1];
+ double dummy;
+ } d;
+};
+
+/* BCACHE_DATA is used to get the address of the cached data. */
+
+#define BCACHE_DATA(p) ((p)->d.data)
+
+/* BCACHE_DATA_ALIGNMENT is used to get the offset of the start of
+ cached data within the hashlink struct. This value, plus the
+ size of the cached data, is the amount of space to allocate for
+ a hashlink struct to hold the next pointer and the data. */
+
+#define BCACHE_DATA_ALIGNMENT \
+ (((char *) &BCACHE_DATA((struct hashlink*) 0) - (char *) 0))
+
+struct bcache {
+ struct obstack cache;
+ struct hashlink **indextable[BCACHE_MAXLENGTH];
+ int cache_hits;
+ int cache_misses;
+ int cache_bytes;
+ int cache_savings;
+ int bcache_overflows;
+};
+
+extern void *
+bcache PARAMS ((void *bytes, int count, struct bcache *bcachep));
+
+#if MAINTENANCE_CMDS
+
+extern void
+print_bcache_statistics PARAMS ((struct bcache *, char *));
+
+#endif /* MAINTENANCE_CMDS */
+
+#endif /* BCACHE_H */
diff --git a/contrib/gdb/gdb/blockframe.c b/contrib/gdb/gdb/blockframe.c
new file mode 100644
index 0000000..d98f6a4
--- /dev/null
+++ b/contrib/gdb/gdb/blockframe.c
@@ -0,0 +1,854 @@
+/* Get info from stack frames;
+ convert between frames, blocks, functions and pc values.
+ Copyright 1986, 1987, 1988, 1989, 1991, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "frame.h"
+#include "gdbcore.h"
+#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
+ to call this function from FRAME_CHAIN_VALID; the reason for
+ doing so is that some machines have no way of detecting bottom
+ of stack.
+
+ A PC of zero is always considered to be the bottom of the stack. */
+
+int
+inside_entry_file (addr)
+ CORE_ADDR addr;
+{
+ if (addr == 0)
+ return 1;
+ if (symfile_objfile == 0)
+ return 0;
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+ /* Do not stop backtracing if the pc is in the call dummy
+ at the entry point. */
+ if (PC_IN_CALL_DUMMY (addr, 0, 0))
+ return 0;
+#endif
+ return (addr >= symfile_objfile -> ei.entry_file_lowpc &&
+ addr < symfile_objfile -> ei.entry_file_highpc);
+}
+
+/* Test a specified PC value to see if it is in the range of addresses
+ that correspond to the main() function. See comments above for why
+ we might want to do this.
+
+ Typically called from FRAME_CHAIN_VALID.
+
+ A PC of zero is always considered to be the bottom of the stack. */
+
+int
+inside_main_func (pc)
+CORE_ADDR pc;
+{
+struct symbol *mainsym;
+ if (pc == 0)
+ return 1;
+ if (symfile_objfile == 0)
+ return 0;
+
+ /* If the addr range is not set up at symbol reading time, set it up now.
+ This is for FRAME_CHAIN_VALID_ALTERNATE. I do this for coff, because
+ it is unable to set it up and symbol reading time. */
+
+ if (symfile_objfile -> ei.main_func_lowpc == INVALID_ENTRY_LOWPC &&
+ symfile_objfile -> ei.main_func_highpc == INVALID_ENTRY_HIGHPC)
+ {
+ mainsym = lookup_symbol ("main", NULL, VAR_NAMESPACE, NULL, NULL);
+ if (mainsym && SYMBOL_CLASS(mainsym) == LOC_BLOCK)
+ {
+ symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
+ symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
+ }
+
+ }
+ return (symfile_objfile -> ei.main_func_lowpc <= pc &&
+ symfile_objfile -> ei.main_func_highpc > pc);
+}
+
+/* Test a specified PC value to see if it is in the range of addresses
+ that correspond to the process entry point function. See comments
+ in objfiles.h for why we might want to do this.
+
+ Typically called from FRAME_CHAIN_VALID.
+
+ A PC of zero is always considered to be the bottom of the stack. */
+
+int
+inside_entry_func (pc)
+CORE_ADDR pc;
+{
+ if (pc == 0)
+ return 1;
+ if (symfile_objfile == 0)
+ return 0;
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+ /* Do not stop backtracing if the pc is in the call dummy
+ at the entry point. */
+ if (PC_IN_CALL_DUMMY (pc, 0, 0))
+ return 0;
+#endif
+ return (symfile_objfile -> ei.entry_func_lowpc <= pc &&
+ symfile_objfile -> ei.entry_func_highpc > pc);
+}
+
+/* Info about the innermost stack frame (contents of FP register) */
+
+static struct frame_info *current_frame;
+
+/* Cache for frame addresses already read by gdb. Valid only while
+ inferior is stopped. Control variables for the frame cache should
+ be local to this module. */
+
+struct obstack frame_cache_obstack;
+
+/* Return the innermost (currently executing) stack frame. */
+
+struct frame_info *
+get_current_frame ()
+{
+ if (current_frame == NULL)
+ {
+ if (target_has_stack)
+ current_frame = create_new_frame (read_fp (), read_pc ());
+ else
+ error ("No stack.");
+ }
+ return current_frame;
+}
+
+void
+set_current_frame (frame)
+ struct frame_info *frame;
+{
+ current_frame = frame;
+}
+
+/* Create an arbitrary (i.e. address specified by user) or innermost frame.
+ Always returns a non-NULL value. */
+
+struct frame_info *
+create_new_frame (addr, pc)
+ CORE_ADDR addr;
+ CORE_ADDR pc;
+{
+ struct frame_info *fi;
+ char *name;
+
+ fi = (struct frame_info *)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_info));
+
+ /* Arbitrary frame */
+ fi->next = NULL;
+ fi->prev = NULL;
+ fi->frame = addr;
+ fi->pc = pc;
+ find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
+ fi->signal_handler_caller = IN_SIGTRAMP (fi->pc, name);
+
+#ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO (0, fi);
+#endif
+
+ return fi;
+}
+
+/* Return the frame that called FI.
+ If FI is the original frame (it has no caller), return 0. */
+
+struct frame_info *
+get_prev_frame (frame)
+ struct frame_info *frame;
+{
+ return get_prev_frame_info (frame);
+}
+
+/* Return the frame that FRAME calls (NULL if FRAME is the innermost
+ frame). */
+
+struct frame_info *
+get_next_frame (frame)
+ struct frame_info *frame;
+{
+ return frame->next;
+}
+
+/* Flush the entire frame cache. */
+
+void
+flush_cached_frames ()
+{
+ /* Since we can't really be sure what the first object allocated was */
+ obstack_free (&frame_cache_obstack, 0);
+ obstack_init (&frame_cache_obstack);
+
+ current_frame = NULL; /* Invalidate cache */
+ select_frame (NULL, -1);
+ annotate_frames_invalid ();
+}
+
+/* Flush the frame cache, and start a new one if necessary. */
+
+void
+reinit_frame_cache ()
+{
+ flush_cached_frames ();
+
+ /* FIXME: The inferior_pid test is wrong if there is a corefile. */
+ if (inferior_pid != 0)
+ {
+ select_frame (get_current_frame (), 0);
+ }
+}
+
+/* If a machine allows frameless functions, it should define a macro
+ FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) in param.h. FI is the struct
+ frame_info for the frame, and FRAMELESS should be set to nonzero
+ if it represents a frameless function invocation. */
+
+/* Return nonzero if the function for this frame lacks a prologue. Many
+ machines can define FRAMELESS_FUNCTION_INVOCATION to just call this
+ function. */
+
+int
+frameless_look_for_prologue (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR func_start, after_prologue;
+ func_start = (get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET);
+ if (func_start)
+ {
+ after_prologue = func_start;
+#ifdef SKIP_PROLOGUE_FRAMELESS_P
+ /* This is faster, since only care whether there *is* a prologue,
+ not how long it is. */
+ SKIP_PROLOGUE_FRAMELESS_P (after_prologue);
+#else
+ SKIP_PROLOGUE (after_prologue);
+#endif
+ return after_prologue == func_start;
+ }
+ else
+ /* If we can't find the start of the function, we don't really
+ know whether the function is frameless, but we should be able
+ to get a reasonable (i.e. best we can do under the
+ circumstances) backtrace by saying that it isn't. */
+ return 0;
+}
+
+/* Default a few macros that people seldom redefine. */
+
+#if !defined (INIT_FRAME_PC)
+#define INIT_FRAME_PC(fromleaf, prev) \
+ prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) : \
+ prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
+#endif
+
+#ifndef FRAME_CHAIN_COMBINE
+#define FRAME_CHAIN_COMBINE(chain, thisframe) (chain)
+#endif
+
+/* Return a structure containing various interesting information
+ about the frame that called NEXT_FRAME. Returns NULL
+ if there is no such frame. */
+
+struct frame_info *
+get_prev_frame_info (next_frame)
+ struct frame_info *next_frame;
+{
+ CORE_ADDR address = 0;
+ struct frame_info *prev;
+ int fromleaf = 0;
+ char *name;
+
+ /* If the requested entry is in the cache, return it.
+ Otherwise, figure out what the address should be for the entry
+ we're about to add to the cache. */
+
+ if (!next_frame)
+ {
+#if 0
+ /* This screws value_of_variable, which just wants a nice clean
+ NULL return from block_innermost_frame if there are no frames.
+ I don't think I've ever seen this message happen otherwise.
+ And returning NULL here is a perfectly legitimate thing to do. */
+ if (!current_frame)
+ {
+ error ("You haven't set up a process's stack to examine.");
+ }
+#endif
+
+ return current_frame;
+ }
+
+ /* If we have the prev one, return it */
+ if (next_frame->prev)
+ return next_frame->prev;
+
+ /* On some machines it is possible to call a function without
+ setting up a stack frame for it. On these machines, we
+ define this macro to take two args; a frameinfo pointer
+ identifying a frame and a variable to set or clear if it is
+ or isn't leafless. */
+#ifdef FRAMELESS_FUNCTION_INVOCATION
+ /* Still don't want to worry about this except on the innermost
+ frame. This macro will set FROMLEAF if NEXT_FRAME is a
+ frameless function invocation. */
+ if (!(next_frame->next))
+ {
+ FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf);
+ if (fromleaf)
+ address = FRAME_FP (next_frame);
+ }
+#endif
+
+ if (!fromleaf)
+ {
+ /* Two macros defined in tm.h specify the machine-dependent
+ actions to be performed here.
+ First, get the frame's chain-pointer.
+ If that is zero, the frame is the outermost frame or a leaf
+ called by the outermost frame. This means that if start
+ calls main without a frame, we'll return 0 (which is fine
+ anyway).
+
+ Nope; there's a problem. This also returns when the current
+ routine is a leaf of main. This is unacceptable. We move
+ this to after the ffi test; I'd rather have backtraces from
+ start go curfluy than have an abort called from main not show
+ main. */
+ address = FRAME_CHAIN (next_frame);
+ if (!FRAME_CHAIN_VALID (address, next_frame))
+ return 0;
+ address = FRAME_CHAIN_COMBINE (address, next_frame);
+ }
+ if (address == 0)
+ return 0;
+
+ prev = (struct frame_info *)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_info));
+
+ if (next_frame)
+ next_frame->prev = prev;
+ prev->next = next_frame;
+ prev->prev = (struct frame_info *) 0;
+ prev->frame = address;
+ prev->signal_handler_caller = 0;
+
+/* This change should not be needed, FIXME! We should
+ determine whether any targets *need* INIT_FRAME_PC to happen
+ after INIT_EXTRA_FRAME_INFO and come up with a simple way to
+ express what goes on here.
+
+ INIT_EXTRA_FRAME_INFO is called from two places: create_new_frame
+ (where the PC is already set up) and here (where it isn't).
+ INIT_FRAME_PC is only called from here, always after
+ INIT_EXTRA_FRAME_INFO.
+
+ The catch is the MIPS, where INIT_EXTRA_FRAME_INFO requires the PC
+ value (which hasn't been set yet). Some other machines appear to
+ require INIT_EXTRA_FRAME_INFO before they can do INIT_FRAME_PC. Phoo.
+
+ We shouldn't need INIT_FRAME_PC_FIRST to add more complication to
+ an already overcomplicated part of GDB. gnu@cygnus.com, 15Sep92.
+
+ Assuming that some machines need INIT_FRAME_PC after
+ INIT_EXTRA_FRAME_INFO, one possible scheme:
+
+ SETUP_INNERMOST_FRAME()
+ Default version is just create_new_frame (read_fp ()),
+ read_pc ()). Machines with extra frame info would do that (or the
+ local equivalent) and then set the extra fields.
+ SETUP_ARBITRARY_FRAME(argc, argv)
+ 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. 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, 31Jan94, 14Dec94. */
+
+#ifdef INIT_FRAME_PC_FIRST
+ INIT_FRAME_PC_FIRST (fromleaf, prev);
+#endif
+
+#ifdef INIT_EXTRA_FRAME_INFO
+ INIT_EXTRA_FRAME_INFO(fromleaf, prev);
+#endif
+
+ /* This entry is in the frame queue now, which is good since
+ 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))
+ prev->signal_handler_caller = 1;
+
+ return prev;
+}
+
+CORE_ADDR
+get_frame_pc (frame)
+ struct frame_info *frame;
+{
+ return frame->pc;
+}
+
+#if defined (FRAME_FIND_SAVED_REGS)
+/* Find the addresses in which registers are saved in FRAME. */
+
+void
+get_frame_saved_regs (frame, saved_regs_addr)
+ struct frame_info *frame;
+ struct frame_saved_regs *saved_regs_addr;
+{
+ FRAME_FIND_SAVED_REGS (frame, *saved_regs_addr);
+}
+#endif
+
+/* Return the innermost lexical block in execution
+ in a specified stack frame. The frame address is assumed valid. */
+
+struct block *
+get_frame_block (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR pc;
+
+ pc = frame->pc;
+ if (frame->next != 0 && frame->next->signal_handler_caller == 0)
+ /* We are not in the innermost frame and we were not interrupted
+ by a signal. We need to subtract one to get the correct block,
+ in case the call instruction was the last instruction of the block.
+ If there are any machines on which the saved pc does not point to
+ after the call insn, we probably want to make frame->pc point after
+ the call insn anyway. */
+ --pc;
+ return block_for_pc (pc);
+}
+
+struct block *
+get_current_block ()
+{
+ return block_for_pc (read_pc ());
+}
+
+CORE_ADDR
+get_pc_function_start (pc)
+ CORE_ADDR pc;
+{
+ register struct block *bl;
+ register struct symbol *symbol;
+ register struct minimal_symbol *msymbol;
+ CORE_ADDR fstart;
+
+ if ((bl = block_for_pc (pc)) != NULL &&
+ (symbol = block_function (bl)) != NULL)
+ {
+ bl = SYMBOL_BLOCK_VALUE (symbol);
+ fstart = BLOCK_START (bl);
+ }
+ else if ((msymbol = lookup_minimal_symbol_by_pc (pc)) != NULL)
+ {
+ fstart = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ else
+ {
+ fstart = 0;
+ }
+ return (fstart);
+}
+
+/* Return the symbol for the function executing in frame FRAME. */
+
+struct symbol *
+get_frame_function (frame)
+ struct frame_info *frame;
+{
+ register struct block *bl = get_frame_block (frame);
+ if (bl == 0)
+ return 0;
+ return block_function (bl);
+}
+
+/* Return the blockvector immediately containing the innermost lexical block
+ containing the specified pc value, or 0 if there is none.
+ PINDEX is a pointer to the index value of the block. If PINDEX
+ is NULL, we don't pass this information back to the caller. */
+
+struct blockvector *
+blockvector_for_pc (pc, pindex)
+ register CORE_ADDR pc;
+ int *pindex;
+{
+ register struct block *b;
+ register int bot, top, half;
+ register struct symtab *s;
+ struct blockvector *bl;
+
+ /* First search all symtabs for one whose file contains our pc */
+ s = find_pc_symtab (pc);
+ if (s == 0)
+ return 0;
+
+ bl = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bl, 0);
+
+ /* Then search that symtab for the smallest block that wins. */
+ /* Use binary search to find the last block that starts before PC. */
+
+ bot = 0;
+ top = BLOCKVECTOR_NBLOCKS (bl);
+
+ while (top - bot > 1)
+ {
+ half = (top - bot + 1) >> 1;
+ b = BLOCKVECTOR_BLOCK (bl, bot + half);
+ if (BLOCK_START (b) <= pc)
+ bot += half;
+ else
+ top = bot + half;
+ }
+
+ /* Now search backward for a block that ends after PC. */
+
+ while (bot >= 0)
+ {
+ b = BLOCKVECTOR_BLOCK (bl, bot);
+ if (BLOCK_END (b) > pc)
+ {
+ if (pindex)
+ *pindex = bot;
+ return bl;
+ }
+ bot--;
+ }
+
+ return 0;
+}
+
+/* Return the innermost lexical block containing the specified pc value,
+ or 0 if there is none. */
+
+struct block *
+block_for_pc (pc)
+ register CORE_ADDR pc;
+{
+ register struct blockvector *bl;
+ int index;
+
+ bl = blockvector_for_pc (pc, &index);
+ if (bl)
+ return BLOCKVECTOR_BLOCK (bl, index);
+ return 0;
+}
+
+/* Return the function containing pc value PC.
+ Returns 0 if function is not known. */
+
+struct symbol *
+find_pc_function (pc)
+ CORE_ADDR pc;
+{
+ register struct block *b = block_for_pc (pc);
+ if (b == 0)
+ return 0;
+ return block_function (b);
+}
+
+/* These variables are used to cache the most recent result
+ * of find_pc_partial_function. */
+
+static CORE_ADDR cache_pc_function_low = 0;
+static CORE_ADDR cache_pc_function_high = 0;
+static char *cache_pc_function_name = 0;
+
+/* Clear cache, e.g. when symbol table is discarded. */
+
+void
+clear_pc_function_cache()
+{
+ cache_pc_function_low = 0;
+ cache_pc_function_high = 0;
+ cache_pc_function_name = (char *)0;
+}
+
+/* Finds the "function" (text symbol) that is smaller than PC but
+ greatest of all of the potential text symbols. Sets *NAME and/or
+ *ADDRESS conditionally if that pointer is non-null. If ENDADDR is
+ non-null, then set *ENDADDR to be the end of the function
+ (exclusive), but passing ENDADDR as non-null means that the
+ function might cause symbols to be read. This function either
+ succeeds or fails (not halfway succeeds). If it succeeds, it sets
+ *NAME, *ADDRESS, and *ENDADDR to real information and returns 1.
+ If it fails, it sets *NAME, *ADDRESS, and *ENDADDR to zero
+ and returns 0. */
+
+int
+find_pc_partial_function (pc, name, address, endaddr)
+ CORE_ADDR pc;
+ char **name;
+ CORE_ADDR *address;
+ CORE_ADDR *endaddr;
+{
+ struct partial_symtab *pst;
+ struct symbol *f;
+ struct minimal_symbol *msymbol;
+ struct partial_symbol *psb;
+ struct obj_section *sec;
+
+ if (pc >= cache_pc_function_low && pc < cache_pc_function_high)
+ goto return_cached_value;
+
+ /* If sigtramp is in the u area, it counts as a function (especially
+ important for step_1). */
+#if defined SIGTRAMP_START
+ if (IN_SIGTRAMP (pc, (char *)NULL))
+ {
+ cache_pc_function_low = SIGTRAMP_START;
+ cache_pc_function_high = SIGTRAMP_END;
+ cache_pc_function_name = "<sigtramp>";
+
+ goto return_cached_value;
+ }
+#endif
+
+ msymbol = lookup_minimal_symbol_by_pc (pc);
+ pst = find_pc_psymtab (pc);
+ if (pst)
+ {
+ /* Need to read the symbols to get a good value for the end address. */
+ if (endaddr != NULL && !pst->readin)
+ {
+ /* Need to get the terminal in case symbol-reading produces
+ output. */
+ target_terminal_ours_for_output ();
+ PSYMTAB_TO_SYMTAB (pst);
+ }
+
+ if (pst->readin)
+ {
+ /* Checking whether the msymbol has a larger value is for the
+ "pathological" case mentioned in print_frame_info. */
+ f = find_pc_function (pc);
+ if (f != NULL
+ && (msymbol == NULL
+ || (BLOCK_START (SYMBOL_BLOCK_VALUE (f))
+ >= SYMBOL_VALUE_ADDRESS (msymbol))))
+ {
+ cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
+ cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
+ cache_pc_function_name = SYMBOL_NAME (f);
+ goto return_cached_value;
+ }
+ }
+ else
+ {
+ /* Now that static symbols go in the minimal symbol table, perhaps
+ we could just ignore the partial symbols. But at least for now
+ we use the partial or minimal symbol, whichever is larger. */
+ psb = find_pc_psymbol (pst, pc);
+
+ if (psb
+ && (msymbol == NULL ||
+ (SYMBOL_VALUE_ADDRESS (psb)
+ >= SYMBOL_VALUE_ADDRESS (msymbol))))
+ {
+ /* This case isn't being cached currently. */
+ if (address)
+ *address = SYMBOL_VALUE_ADDRESS (psb);
+ if (name)
+ *name = SYMBOL_NAME (psb);
+ /* endaddr non-NULL can't happen here. */
+ return 1;
+ }
+ }
+ }
+
+ /* Not in the normal symbol tables, see if the pc is in a known section.
+ If it's not, then give up. This ensures that anything beyond the end
+ of the text seg doesn't appear to be part of the last function in the
+ text segment. */
+
+ sec = find_pc_section (pc);
+
+ if (!sec)
+ msymbol = NULL;
+
+ /* Must be in the minimal symbol table. */
+ if (msymbol == NULL)
+ {
+ /* No available symbol. */
+ if (name != NULL)
+ *name = 0;
+ if (address != NULL)
+ *address = 0;
+ if (endaddr != NULL)
+ *endaddr = 0;
+ return 0;
+ }
+
+ cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
+ cache_pc_function_name = SYMBOL_NAME (msymbol);
+
+ /* Use the lesser of the next minimal symbol, or the end of the section, as
+ the end of the function. */
+
+ if (SYMBOL_NAME (msymbol + 1) != NULL
+ && SYMBOL_VALUE_ADDRESS (msymbol + 1) < sec->endaddr)
+ cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + 1);
+ else
+ /* We got the start address from the last msymbol in the objfile.
+ So the end address is the end of the section. */
+ cache_pc_function_high = sec->endaddr;
+
+ return_cached_value:
+ if (address)
+ *address = cache_pc_function_low;
+ if (name)
+ *name = cache_pc_function_name;
+ if (endaddr)
+ *endaddr = cache_pc_function_high;
+ return 1;
+}
+
+/* Return the innermost stack frame executing inside of BLOCK,
+ or NULL if there is no such frame. If BLOCK is NULL, just return NULL. */
+
+struct frame_info *
+block_innermost_frame (block)
+ struct block *block;
+{
+ struct frame_info *frame;
+ register CORE_ADDR start;
+ register CORE_ADDR end;
+
+ if (block == NULL)
+ return NULL;
+
+ start = BLOCK_START (block);
+ end = BLOCK_END (block);
+
+ frame = NULL;
+ while (1)
+ {
+ frame = get_prev_frame (frame);
+ if (frame == NULL)
+ return NULL;
+ if (frame->pc >= start && frame->pc < end)
+ return frame;
+ }
+}
+
+/* Return the full FRAME which corresponds to the given CORE_ADDR
+ or NULL if no FRAME on the chain corresponds to CORE_ADDR. */
+
+struct frame_info *
+find_frame_addr_in_frame_chain (frame_addr)
+ CORE_ADDR frame_addr;
+{
+ struct frame_info *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. */
+
+CORE_ADDR
+sigtramp_saved_pc (frame)
+ struct frame_info *frame;
+{
+ CORE_ADDR sigcontext_addr;
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ int ptrbytes = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+ int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
+
+ /* Get sigcontext address, it is the third parameter on the stack. */
+ if (frame->next)
+ sigcontext_addr = read_memory_integer (FRAME_ARGS_ADDRESS (frame->next)
+ + FRAME_ARGS_SKIP
+ + sigcontext_offs,
+ ptrbytes);
+ else
+ sigcontext_addr = read_memory_integer (read_register (SP_REGNUM)
+ + sigcontext_offs,
+ ptrbytes);
+
+ /* Don't cause a memory_error when accessing sigcontext in case the stack
+ layout has changed or the stack is corrupt. */
+ target_read_memory (sigcontext_addr + SIGCONTEXT_PC_OFFSET, buf, ptrbytes);
+ return extract_unsigned_integer (buf, ptrbytes);
+}
+#endif /* SIGCONTEXT_PC_OFFSET */
+
+void
+_initialize_blockframe ()
+{
+ obstack_init (&frame_cache_obstack);
+}
diff --git a/contrib/gdb/gdb/breakpoint.c b/contrib/gdb/gdb/breakpoint.c
new file mode 100644
index 0000000..3930e7a
--- /dev/null
+++ b/contrib/gdb/gdb/breakpoint.c
@@ -0,0 +1,4117 @@
+/* Everything about breakpoints, for GDB.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "breakpoint.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "value.h"
+#include "command.h"
+#include "inferior.h"
+#include "thread.h"
+#include "target.h"
+#include "language.h"
+#include "gdb_string.h"
+#include "demangle.h"
+#include "annotate.h"
+
+/* local function prototypes */
+
+static void
+catch_command_1 PARAMS ((char *, int, int));
+
+static void
+enable_delete_command PARAMS ((char *, int));
+
+static void
+enable_delete_breakpoint PARAMS ((struct breakpoint *));
+
+static void
+enable_once_command PARAMS ((char *, int));
+
+static void
+enable_once_breakpoint PARAMS ((struct breakpoint *));
+
+static void
+disable_command PARAMS ((char *, int));
+
+static void
+enable_command PARAMS ((char *, int));
+
+static void
+map_breakpoint_numbers PARAMS ((char *, void (*)(struct breakpoint *)));
+
+static void
+ignore_command PARAMS ((char *, int));
+
+static int
+breakpoint_re_set_one PARAMS ((char *));
+
+static void
+delete_command PARAMS ((char *, int));
+
+static void
+clear_command PARAMS ((char *, int));
+
+static void
+catch_command PARAMS ((char *, int));
+
+static struct symtabs_and_lines
+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));
+
+static void
+break_command_1 PARAMS ((char *, int, int));
+
+static void
+mention PARAMS ((struct breakpoint *));
+
+static struct breakpoint *
+set_raw_breakpoint PARAMS ((struct symtab_and_line));
+
+static void
+check_duplicates PARAMS ((CORE_ADDR));
+
+static void
+describe_other_breakpoints PARAMS ((CORE_ADDR));
+
+static void
+breakpoints_info PARAMS ((char *, int));
+
+static void
+breakpoint_1 PARAMS ((int, int));
+
+static bpstat
+bpstat_alloc PARAMS ((struct breakpoint *, bpstat));
+
+static int
+breakpoint_cond_eval PARAMS ((char *));
+
+static void
+cleanup_executing_breakpoints PARAMS ((int));
+
+static void
+commands_command PARAMS ((char *, int));
+
+static void
+condition_command PARAMS ((char *, int));
+
+static int
+get_number PARAMS ((char **));
+
+static void
+set_breakpoint_count PARAMS ((int));
+
+static int
+remove_breakpoint PARAMS ((struct breakpoint *));
+
+extern int addressprint; /* Print machine addresses? */
+
+/* Are we executing breakpoint commands? */
+static int executing_breakpoint_commands;
+
+/* Walk the following statement or block through all breakpoints.
+ ALL_BREAKPOINTS_SAFE does so even if the statment deletes the current
+ breakpoint. */
+
+#define ALL_BREAKPOINTS(b) for (b = breakpoint_chain; b; b = b->next)
+
+#define ALL_BREAKPOINTS_SAFE(b,tmp) \
+ for (b = breakpoint_chain; \
+ b? (tmp=b->next, 1): 0; \
+ b = tmp)
+
+/* 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;
+
+/* Number of last breakpoint made. */
+
+static int breakpoint_count;
+
+/* Set breakpoint count to NUM. */
+
+static void
+set_breakpoint_count (num)
+ int num;
+{
+ breakpoint_count = num;
+ set_internalvar (lookup_internalvar ("bpnum"),
+ 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
+ not valid, and "break" with no arg is an error.
+
+ This set by print_stack_frame, which calls set_default_breakpoint. */
+
+int default_breakpoint_valid;
+CORE_ADDR default_breakpoint_address;
+struct symtab *default_breakpoint_symtab;
+int default_breakpoint_line;
+
+/* *PP is a string denoting a breakpoint. Get the number of the breakpoint.
+ Advance *PP after the string and any trailing whitespace.
+
+ Currently the string can either be a number or "$" followed by the name
+ of a convenience variable. Making it an expression wouldn't work well
+ for map_breakpoint_numbers (e.g. "4 + 5 + 6"). */
+static int
+get_number (pp)
+ char **pp;
+{
+ int retval;
+ char *p = *pp;
+
+ if (p == NULL)
+ /* Empty line means refer to the last breakpoint. */
+ return breakpoint_count;
+ else if (*p == '$')
+ {
+ /* Make a copy of the name, so we can null-terminate it
+ to pass to lookup_internalvar(). */
+ char *varname;
+ char *start = ++p;
+ value_ptr val;
+
+ while (isalnum (*p) || *p == '_')
+ p++;
+ varname = (char *) alloca (p - start + 1);
+ strncpy (varname, start, p - start);
+ varname[p - start] = '\0';
+ val = value_of_internalvar (lookup_internalvar (varname));
+ if (TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_INT)
+ error (
+"Convenience variables used to specify breakpoints must have integer values."
+ );
+ retval = (int) value_as_long (val);
+ }
+ else
+ {
+ if (*p == '-')
+ ++p;
+ while (*p >= '0' && *p <= '9')
+ ++p;
+ if (p == *pp)
+ /* There is no number here. (e.g. "cond a == b"). */
+ error_no_arg ("breakpoint number");
+ retval = atoi (*pp);
+ }
+ if (!(isspace (*p) || *p == '\0'))
+ error ("breakpoint number expected");
+ while (isspace (*p))
+ p++;
+ *pp = p;
+ return retval;
+}
+
+/* condition N EXP -- set break condition of breakpoint N to EXP. */
+
+static void
+condition_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b;
+ char *p;
+ register int bnum;
+
+ if (arg == 0)
+ error_no_arg ("breakpoint number");
+
+ p = arg;
+ bnum = get_number (&p);
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bnum)
+ {
+ if (b->cond)
+ {
+ free ((PTR)b->cond);
+ b->cond = 0;
+ }
+ if (b->cond_string != NULL)
+ free ((PTR)b->cond_string);
+
+ if (*p == 0)
+ {
+ b->cond = 0;
+ b->cond_string = NULL;
+ if (from_tty)
+ printf_filtered ("Breakpoint %d now unconditional.\n", bnum);
+ }
+ else
+ {
+ arg = p;
+ /* I don't know if it matters whether this is the string the user
+ typed in or the decompiled expression. */
+ b->cond_string = savestring (arg, strlen (arg));
+ b->cond = parse_exp_1 (&arg, block_for_pc (b->address), 0);
+ if (*arg)
+ error ("Junk at end of expression");
+ }
+ breakpoints_changed ();
+ return;
+ }
+
+ error ("No breakpoint number %d.", bnum);
+}
+
+/* ARGSUSED */
+static void
+commands_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b;
+ char *p;
+ register int bnum;
+ struct command_line *l;
+
+ /* If we allowed this, we would have problems with when to
+ free the storage, if we change the commands currently
+ being read from. */
+
+ if (executing_breakpoint_commands)
+ error ("Can't use the \"commands\" command among a breakpoint's commands.");
+
+ p = arg;
+ bnum = get_number (&p);
+ if (p && *p)
+ error ("Unexpected extra arguments following breakpoint number.");
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bnum)
+ {
+ if (from_tty && input_from_terminal_p ())
+ printf_filtered ("Type commands for when breakpoint %d is hit, one per line.\n\
+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);
+}
+
+extern int memory_breakpoint_size; /* from mem-break.c */
+
+/* Like target_read_memory() but if breakpoints are inserted, return
+ the shadow contents instead of the breakpoints themselves.
+
+ Read "memory data" from whatever target or inferior we have.
+ Returns zero if successful, errno value if not. EIO is used
+ for address out of bounds. If breakpoints are inserted, returns
+ shadow contents, not the breakpoints themselves. From breakpoint.c. */
+
+int
+read_memory_nobpt (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ unsigned len;
+{
+ int status;
+ struct breakpoint *b;
+
+ if (memory_breakpoint_size < 0)
+ /* No breakpoints on this machine. FIXME: This should be
+ dependent on the debugging target. Probably want
+ target_insert_breakpoint to return a size, saying how many
+ bytes of the shadow contents are used, or perhaps have
+ something like target_xfer_shadow. */
+ return target_read_memory (memaddr, myaddr, len);
+
+ ALL_BREAKPOINTS (b)
+ {
+ 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
+ we are reading. */
+ continue;
+ else if (b->address >= memaddr + len)
+ /* The breakpoint is entirely after the chunk of memory we
+ are reading. */
+ continue;
+ else
+ {
+ /* Copy the breakpoint from the shadow contents, and recurse
+ for the things before and after. */
+
+ /* Addresses and length of the part of the breakpoint that
+ we need to copy. */
+ CORE_ADDR membpt = b->address;
+ unsigned int bptlen = memory_breakpoint_size;
+ /* Offset within shadow_contents. */
+ int bptoffset = 0;
+
+ if (membpt < memaddr)
+ {
+ /* Only copy the second part of the breakpoint. */
+ bptlen -= memaddr - membpt;
+ bptoffset = memaddr - membpt;
+ membpt = memaddr;
+ }
+
+ if (membpt + bptlen > memaddr + len)
+ {
+ /* Only copy the first part of the breakpoint. */
+ bptlen -= (membpt + bptlen) - (memaddr + len);
+ }
+
+ memcpy (myaddr + membpt - memaddr,
+ b->shadow_contents + bptoffset, bptlen);
+
+ if (membpt > memaddr)
+ {
+ /* Copy the section of memory before the breakpoint. */
+ status = read_memory_nobpt (memaddr, myaddr, membpt - memaddr);
+ if (status != 0)
+ return status;
+ }
+
+ if (membpt + bptlen < memaddr + len)
+ {
+ /* Copy the section of memory after the breakpoint. */
+ status = read_memory_nobpt
+ (membpt + bptlen,
+ myaddr + membpt + bptlen - memaddr,
+ memaddr + len - (membpt + bptlen));
+ if (status != 0)
+ return status;
+ }
+ return 0;
+ }
+ }
+ /* Nothing overlaps. Just call read_memory_noerr. */
+ return target_read_memory (memaddr, myaddr, len);
+}
+
+/* insert_breakpoints is used when starting or continuing the program.
+ remove_breakpoints is used when the program stops.
+ Both return zero if successful,
+ or an `errno' value if could not write the inferior. */
+
+int
+insert_breakpoints ()
+{
+ register struct breakpoint *b, *temp;
+ int val = 0;
+ int disabled_breaks = 0;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->type != bp_watchpoint
+ && b->type != bp_hardware_watchpoint
+ && b->type != bp_read_watchpoint
+ && b->type != bp_access_watchpoint
+ && b->enable != disabled
+ && b->enable != shlib_disabled
+ && ! b->inserted
+ && ! b->duplicate)
+ {
+ 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. */
+#if defined (DISABLE_UNSETTABLE_BREAK)
+ if (DISABLE_UNSETTABLE_BREAK (b->address))
+ {
+ val = 0;
+ b->enable = shlib_disabled;
+ if (!disabled_breaks)
+ {
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr,
+ "Cannot insert breakpoint %d:\n", b->number);
+ printf_filtered ("Temporarily disabling shared library breakpoints:\n");
+ }
+ disabled_breaks = 1;
+ printf_filtered ("%d ", b->number);
+ }
+ else
+#endif
+ {
+ target_terminal_ours_for_output ();
+ fprintf_unfiltered (gdb_stderr, "Cannot insert breakpoint %d:\n", b->number);
+#ifdef ONE_PROCESS_WRITETEXT
+ fprintf_unfiltered (gdb_stderr,
+ "The same program may be running in another process.\n");
+#endif
+ memory_error (val, b->address); /* which bombs us out */
+ }
+ }
+ 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)
+ {
+ struct frame_info *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
+ {
+ struct frame_info *fi =
+ find_frame_addr_in_frame_chain (b->watchpoint_frame);
+ within_current_scope = (fi != NULL);
+ if (within_current_scope)
+ select_frame (fi, -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;
+
+ ALL_BREAKPOINTS (b)
+ {
+ 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)
+ warning ("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;
+}
+
+/* Clear the "inserted" flag in all breakpoints. */
+
+void
+mark_breakpoints_out ()
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ b->inserted = 0;
+}
+
+/* Clear the "inserted" flag in all breakpoints and delete any breakpoints
+ which should go away between runs of the program. */
+
+void
+breakpoint_init_inferior ()
+{
+ register struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ b->inserted = 0;
+
+ /* If the call dummy breakpoint is at the entry point it will
+ cause problems when the inferior is rerun, so we better
+ 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);
+ }
+}
+
+/* breakpoint_here_p (PC) returns 1 if an enabled breakpoint exists at PC.
+ When continuing from a location with a breakpoint,
+ we actually single step once before calling insert_breakpoints. */
+
+int
+breakpoint_here_p (pc)
+ CORE_ADDR pc;
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->address == pc)
+ return 1;
+
+ 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)
+ struct frame_info *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. */
+
+int
+breakpoint_thread_match (pc, pid)
+ CORE_ADDR pc;
+ int pid;
+{
+ struct breakpoint *b;
+ int thread;
+
+ thread = pid_to_thread_id (pid);
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->address == pc
+ && (b->thread == -1 || b->thread == thread))
+ return 1;
+
+ return 0;
+}
+
+
+/* bpstat stuff. External routines' interfaces are documented
+ in breakpoint.h. */
+
+/* Clear a bpstat so that it says we are not at any breakpoint.
+ Also free any storage that is part of a bpstat. */
+
+void
+bpstat_clear (bsp)
+ bpstat *bsp;
+{
+ bpstat p;
+ bpstat q;
+
+ if (bsp == 0)
+ return;
+ p = *bsp;
+ while (p != NULL)
+ {
+ q = p->next;
+ if (p->old_val != NULL)
+ value_free (p->old_val);
+ free ((PTR)p);
+ p = q;
+ }
+ *bsp = NULL;
+}
+
+/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
+ is part of the bpstat is copied as well. */
+
+bpstat
+bpstat_copy (bs)
+ bpstat bs;
+{
+ bpstat p = NULL;
+ bpstat tmp;
+ bpstat retval = NULL;
+
+ if (bs == NULL)
+ return bs;
+
+ for (; bs != NULL; bs = bs->next)
+ {
+ tmp = (bpstat) xmalloc (sizeof (*tmp));
+ memcpy (tmp, bs, sizeof (*tmp));
+ if (p == NULL)
+ /* This is the first thing in the chain. */
+ retval = tmp;
+ else
+ p->next = tmp;
+ p = tmp;
+ }
+ p->next = NULL;
+ return retval;
+}
+
+/* Find the bpstat associated with this breakpoint */
+
+bpstat
+bpstat_find_breakpoint(bsp, breakpoint)
+ bpstat bsp;
+ struct breakpoint *breakpoint;
+{
+ if (bsp == NULL) return NULL;
+
+ for (;bsp != NULL; bsp = bsp->next) {
+ if (bsp->breakpoint_at == breakpoint) return bsp;
+ }
+ return NULL;
+}
+
+/* Return the breakpoint number of the first breakpoint we are stopped
+ at. *BSP upon return is a bpstat which points to the remaining
+ breakpoints stopped at (but which is not guaranteed to be good for
+ anything but further calls to bpstat_num).
+ Return 0 if passed a bpstat which does not indicate any breakpoints. */
+
+int
+bpstat_num (bsp)
+ bpstat *bsp;
+{
+ struct breakpoint *b;
+
+ if ((*bsp) == NULL)
+ return 0; /* No more breakpoint values */
+ else
+ {
+ b = (*bsp)->breakpoint_at;
+ *bsp = (*bsp)->next;
+ if (b == NULL)
+ return -1; /* breakpoint that's been deleted since */
+ else
+ return b->number; /* We have its number */
+ }
+}
+
+/* Modify BS so that the actions will not be performed. */
+
+void
+bpstat_clear_actions (bs)
+ bpstat bs;
+{
+ for (; bs != NULL; bs = bs->next)
+ {
+ bs->commands = NULL;
+ if (bs->old_val != NULL)
+ {
+ value_free (bs->old_val);
+ bs->old_val = NULL;
+ }
+ }
+}
+
+/* Stub for cleaning up our state if we error-out of a breakpoint command */
+/* ARGSUSED */
+static void
+cleanup_executing_breakpoints (ignore)
+ int ignore;
+{
+ executing_breakpoint_commands = 0;
+}
+
+/* Execute all the commands associated with all the breakpoints at this
+ location. Any of these commands could cause the process to proceed
+ beyond this point, etc. We look out for such changes by checking
+ the global "breakpoint_proceeded" after each command. */
+
+void
+bpstat_do_actions (bsp)
+ bpstat *bsp;
+{
+ bpstat bs;
+ struct cleanup *old_chain;
+ struct command_line *cmd;
+
+ executing_breakpoint_commands = 1;
+ old_chain = make_cleanup (cleanup_executing_breakpoints, 0);
+
+top:
+ bs = *bsp;
+
+ breakpoint_proceeded = 0;
+ for (; bs != NULL; bs = bs->next)
+ {
+ cmd = bs->commands;
+ while (cmd != NULL)
+ {
+ execute_control_command (cmd);
+ cmd = cmd->next;
+ }
+ if (breakpoint_proceeded)
+ /* The inferior is proceeded by the command; bomb out now.
+ The bpstat chain has been blown away by wait_for_inferior.
+ But since execution has stopped again, there is a new bpstat
+ to look at, so start over. */
+ goto top;
+ else
+ bs->commands = NULL;
+ }
+
+ executing_breakpoint_commands = 0;
+ discard_cleanups (old_chain);
+}
+
+/* This is the normal print_it function for a bpstat. In the future,
+ much of this logic could (should?) be moved to bpstat_stop_status,
+ by having it set different print_it functions. */
+
+static int
+print_it_normal (bs)
+ bpstat bs;
+{
+ /* bs->breakpoint_at can be NULL if it was a momentary breakpoint
+ which has since been deleted. */
+ if (bs->breakpoint_at == NULL
+ || (bs->breakpoint_at->type != bp_breakpoint
+ && 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 ||
+ 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;
+ }
+ 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))
+ {
+ annotate_watchpoint (bs->breakpoint_at->number);
+ mention (bs->breakpoint_at);
+ printf_filtered ("\nOld value = ");
+ value_print (bs->old_val, gdb_stdout, 0, Val_pretty_default);
+ printf_filtered ("\nNew value = ");
+ value_print (bs->breakpoint_at->val, gdb_stdout, 0,
+ Val_pretty_default);
+ printf_filtered ("\n");
+ value_free (bs->old_val);
+ bs->old_val = NULL;
+ /* 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;
+}
+
+/* Print a message indicating what happened. Returns nonzero to
+ say that only the source line should be printed after this (zero
+ return means print the frame as well as the source line). */
+/* Currently we always return zero. */
+int
+bpstat_print (bs)
+ bpstat bs;
+{
+ int val;
+
+ if (bs == NULL)
+ return 0;
+
+ val = (*bs->print_it) (bs);
+ if (val >= 0)
+ return val;
+
+ /* Maybe another breakpoint in the chain caused us to stop.
+ (Currently all watchpoints go on the bpstat whether hit or
+ not. That probably could (should) be changed, provided care is taken
+ with respect to bpstat_explains_signal). */
+ if (bs->next)
+ return bpstat_print (bs->next);
+
+ /* We reached the end of the chain without printing anything. */
+ return 0;
+}
+
+/* Evaluate the expression EXP and return 1 if value is zero.
+ This is used inside a catch_errors to evaluate the breakpoint condition.
+ The argument is a "struct expression *" that has been cast to char * to
+ make it pass through catch_errors. */
+
+static int
+breakpoint_cond_eval (exp)
+ char *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. */
+
+static bpstat
+bpstat_alloc (b, cbs)
+ register struct breakpoint *b;
+ bpstat cbs; /* Current "bs" value */
+{
+ bpstat bs;
+
+ bs = (bpstat) xmalloc (sizeof (*bs));
+ cbs->next = bs;
+ bs->breakpoint_at = b;
+ /* If the condition is false, etc., don't do the commands. */
+ bs->commands = NULL;
+ bs->old_val = NULL;
+ bs->print_it = print_it_normal;
+ return bs;
+}
+
+/* Possible return values for watchpoint_check (this can't be an enum
+ because of check_errors). */
+/* 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
+
+#define BP_TEMPFLAG 1
+#define BP_HARDWAREFLAG 2
+
+/* Check watchpoint condition. */
+
+static int
+watchpoint_check (p)
+ char *p;
+{
+ bpstat bs = (bpstat) p;
+ struct breakpoint *b;
+ struct frame_info *fr;
+ int within_current_scope;
+
+ b = bs->breakpoint_at;
+
+ if (b->exp_valid_block == NULL)
+ within_current_scope = 1;
+ else
+ {
+ /* There is no current frame at this moment. If we're going to have
+ any chance of handling watchpoints on local variables, we'll need
+ the frame chain (so we can determine if we're in scope). */
+ reinit_frame_cache();
+ 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
+ the user. */
+ select_frame (fr, -1);
+ }
+
+ if (within_current_scope)
+ {
+ /* We use value_{,free_to_}mark because it could be a
+ *long* time before we return to the command level and
+ call free_all_values. We can't call free_all_values because
+ we might be in the middle of evaluating a function call. */
+
+ 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 = b->val;
+ b->val = new_val;
+ /* We will stop here */
+ return WP_VALUE_CHANGED;
+ }
+ else
+ {
+ /* Nothing changed, don't do anything. */
+ value_free_to_mark (mark);
+ /* We won't stop here */
+ return WP_VALUE_NOT_CHANGED;
+ }
+ }
+ else
+ {
+ /* This seems like the only logical thing to do because
+ if we temporarily ignored the watchpoint, then when
+ we reenter the block in which it is valid it contains
+ garbage (in the case of a function, it may have two
+ garbage values, one before and one after the prologue).
+ 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). */
+ printf_filtered ("\
+Watchpoint %d deleted because the program has left the block in\n\
+which its expression is valid.\n", bs->breakpoint_at->number);
+ if (b->related_breakpoint)
+ delete_breakpoint (b->related_breakpoint);
+ delete_breakpoint (b);
+
+ return WP_DELETED;
+ }
+}
+
+/* This is used when everything which needs to be printed has
+ already been printed. But we still want to print the frame. */
+static int
+print_it_done (bs)
+ bpstat bs;
+{
+ return 0;
+}
+
+/* This is used when nothing should be printed for this bpstat entry. */
+
+static int
+print_it_noop (bs)
+ bpstat bs;
+{
+ return -1;
+}
+
+/* Get a bpstat associated with having just stopped at address *PC
+ and frame address CORE_ADDRESS. Update *PC to point at the
+ breakpoint (if we hit a breakpoint). NOT_A_BREAKPOINT is nonzero
+ if this is known to not be a real breakpoint (it could still be a
+ watchpoint, though). */
+
+/* Determine whether we stopped at a breakpoint, etc, or whether we
+ don't understand this stop. Result is a chain of bpstat's such that:
+
+ if we don't understand the stop, the result is a null pointer.
+
+ if we understand why we stopped, the result is not null.
+
+ Each element of the chain refers to a particular breakpoint or
+ watchpoint at which we have stopped. (We may have stopped for
+ several reasons concurrently.)
+
+ Each element of the chain has valid next, breakpoint_at,
+ commands, FIXME??? fields.
+
+ */
+
+bpstat
+bpstat_stop_status (pc, not_a_breakpoint)
+ CORE_ADDR *pc;
+ int not_a_breakpoint;
+{
+ register struct breakpoint *b, *temp;
+ CORE_ADDR bp_addr;
+#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
+ /* True if we've hit a breakpoint (as opposed to a watchpoint). */
+ int real_breakpoint = 0;
+#endif
+ /* Root of the chain of bpstat's */
+ struct bpstats 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;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ if (b->enable == disabled
+ || b->enable == shlib_disabled)
+ continue;
+
+ 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_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;
+
+ sprintf (message, message1, b->number);
+ if (b->type == bp_watchpoint || b->type == bp_hardware_watchpoint)
+ {
+ 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:
+ /* Stop. */
+ break;
+ case WP_VALUE_NOT_CHANGED:
+ /* Don't stop. */
+ bs->print_it = print_it_noop;
+ bs->stop = 0;
+ continue;
+ default:
+ /* Can't happen. */
+ /* FALLTHROUGH */
+ 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;
+
+ /* 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;
+#endif
+
+ if (b->frame && b->frame != (get_current_frame ())->frame)
+ bs->stop = 0;
+ else
+ {
+ int value_is_zero = 0;
+
+ if (b->cond)
+ {
+ /* Need to select the frame, with all that implies
+ so that the conditions will have the right context. */
+ select_frame (get_current_frame (), 0);
+ value_is_zero
+ = catch_errors (breakpoint_cond_eval, (char *)(b->cond),
+ "Error in testing breakpoint condition:\n",
+ RETURN_MASK_ALL);
+ /* FIXME-someday, should give breakpoint # */
+ free_all_values ();
+ }
+ if (b->cond && value_is_zero)
+ {
+ bs->stop = 0;
+ }
+ else if (b->ignore_count > 0)
+ {
+ b->ignore_count--;
+ bs->stop = 0;
+ }
+ else
+ {
+ /* We will stop here */
+ if (b->disposition == disable)
+ b->enable = disabled;
+ bs->commands = b->commands;
+ if (b->silent)
+ bs->print = 0;
+ if (bs->commands && STREQ ("silent", bs->commands->line))
+ {
+ bs->commands = bs->commands->next;
+ bs->print = 0;
+ }
+ }
+ }
+ /* Print nothing for this entry if we dont stop or if we dont print. */
+ if (bs->stop == 0 || bs->print == 0)
+ bs->print_it = print_it_noop;
+ }
+
+ bs->next = NULL; /* Terminate the chain */
+ bs = root_bs->next; /* Re-grab the head of the chain */
+#if DECR_PC_AFTER_BREAK != 0 || defined (SHIFT_INST_REGS)
+ if (bs)
+ {
+ if (real_breakpoint)
+ {
+ *pc = bp_addr;
+#if defined (SHIFT_INST_REGS)
+ SHIFT_INST_REGS();
+#else /* No SHIFT_INST_REGS. */
+ write_pc (bp_addr);
+#endif /* No SHIFT_INST_REGS. */
+ }
+ }
+#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;
+}
+
+/* Tell what to do about this bpstat. */
+struct bpstat_what
+bpstat_what (bs)
+ bpstat bs;
+{
+ /* Classify each bpstat as one of the following. */
+ enum class {
+ /* This bpstat element has no effect on the main_action. */
+ no_effect = 0,
+
+ /* There was a watchpoint, stop but don't print. */
+ wp_silent,
+
+ /* There was a watchpoint, stop and print. */
+ wp_noisy,
+
+ /* There was a breakpoint but we're not stopping. */
+ bp_nostop,
+
+ /* There was a breakpoint, stop but don't print. */
+ bp_silent,
+
+ /* There was a breakpoint, stop and print. */
+ bp_noisy,
+
+ /* We hit the longjmp breakpoint. */
+ long_jump,
+
+ /* We hit the longjmp_resume breakpoint. */
+ long_resume,
+
+ /* We hit the step_resume breakpoint. */
+ step_resume,
+
+ /* We hit the through_sigtramp breakpoint. */
+ through_sig,
+
+ /* We hit the shared library event breakpoint. */
+ shlib_event,
+
+ /* This is just used to count how many enums there are. */
+ class_last
+ };
+
+ /* Here is the table which drives this routine. So that we can
+ format it pretty, we define some abbreviations for the
+ enum bpstat_what codes. */
+#define kc BPSTAT_WHAT_KEEP_CHECKING
+#define ss BPSTAT_WHAT_STOP_SILENT
+#define sn BPSTAT_WHAT_STOP_NOISY
+#define sgl BPSTAT_WHAT_SINGLE
+#define slr BPSTAT_WHAT_SET_LONGJMP_RESUME
+#define clr BPSTAT_WHAT_CLEAR_LONGJMP_RESUME
+#define clrs BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE
+#define sr BPSTAT_WHAT_STEP_RESUME
+#define ts BPSTAT_WHAT_THROUGH_SIGTRAMP
+#define shl BPSTAT_WHAT_CHECK_SHLIBS
+
+/* "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. */
+#define err BPSTAT_WHAT_STOP_NOISY
+
+ /* Given an old action and a class, come up with a new action. */
+ /* One interesting property of this table is that wp_silent is the same
+ as bp_silent and wp_noisy is the same as bp_noisy. That is because
+ after stopping, the check for whether to step over a breakpoint
+ (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 */
+ /* kc ss sn sgl slr clr clrs sr ts shl
+ */
+/*no_effect*/ {kc, ss, sn, sgl, slr, clr, clrs, sr, ts, shl},
+/*wp_silent*/ {ss, ss, sn, ss, ss, ss, ss, sr, ts, shl},
+/*wp_noisy*/ {sn, sn, sn, sn, sn, sn, sn, sr, ts, shl},
+/*bp_nostop*/ {sgl, ss, sn, sgl, slr, clrs, clrs, sr, ts, shl},
+/*bp_silent*/ {ss, ss, sn, ss, ss, ss, ss, sr, ts, shl},
+/*bp_noisy*/ {sn, sn, sn, sn, sn, sn, sn, sr, ts, shl},
+/*long_jump*/ {slr, ss, sn, slr, err, err, err, sr, ts, shl},
+/*long_resume*/ {clr, ss, sn, clrs, err, err, err, sr, ts, shl},
+/*step_resume*/ {sr, sr, sr, sr, sr, sr, sr, sr, ts, shl},
+/*through_sig*/ {ts, ts, ts, ts, ts, ts, ts, ts, ts, shl},
+/*shlib*/ {shl, shl, shl, shl, shl, shl, shl, shl, ts, shl}
+ };
+#undef kc
+#undef ss
+#undef sn
+#undef sgl
+#undef slr
+#undef clr
+#undef clrs
+#undef err
+#undef sr
+#undef ts
+#undef shl
+ enum bpstat_what_main_action current_action = BPSTAT_WHAT_KEEP_CHECKING;
+ struct bpstat_what retval;
+
+ retval.call_dummy = 0;
+ for (; bs != NULL; bs = bs->next)
+ {
+ enum class bs_class = no_effect;
+ if (bs->breakpoint_at == NULL)
+ /* I suspect this can happen if it was a momentary breakpoint
+ which has since been deleted. */
+ continue;
+ switch (bs->breakpoint_at->type)
+ {
+ case bp_breakpoint:
+ case bp_hardware_breakpoint:
+ case bp_until:
+ case bp_finish:
+ if (bs->stop)
+ {
+ if (bs->print)
+ bs_class = bp_noisy;
+ else
+ bs_class = bp_silent;
+ }
+ else
+ 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)
+ bs_class = wp_noisy;
+ else
+ bs_class = wp_silent;
+ }
+ else
+ /* There was a watchpoint, but we're not stopping. This requires
+ no further action. */
+ bs_class = no_effect;
+ break;
+ case bp_longjmp:
+ bs_class = long_jump;
+ break;
+ case bp_longjmp_resume:
+ bs_class = long_resume;
+ break;
+ case bp_step_resume:
+ if (bs->stop)
+ {
+ bs_class = step_resume;
+ }
+ else
+ /* It is for the wrong frame. */
+ bs_class = bp_nostop;
+ break;
+ case bp_through_sigtramp:
+ bs_class = through_sig;
+ break;
+ case bp_watchpoint_scope:
+ bs_class = bp_nostop;
+ break;
+ case bp_shlib_event:
+ bs_class = shlib_event;
+ break;
+ case bp_call_dummy:
+ /* Make sure the action is stop (silent or noisy), so infrun.c
+ pops the dummy frame. */
+ bs_class = bp_silent;
+ retval.call_dummy = 1;
+ break;
+ }
+ current_action = table[(int)bs_class][(int)current_action];
+ }
+ retval.main_action = current_action;
+ return retval;
+}
+
+/* Nonzero if we should step constantly (e.g. watchpoints on machines
+ without hardware support). This isn't related to a specific bpstat,
+ just to things like whether watchpoints are set. */
+
+int
+bpstat_should_step ()
+{
+ struct breakpoint *b;
+ ALL_BREAKPOINTS (b)
+ if (b->enable == enabled && b->type == bp_watchpoint)
+ return 1;
+ return 0;
+}
+
+/* Print information on breakpoint number BNUM, or -1 if all.
+ If WATCHPOINTS is zero, process only breakpoints; if WATCHPOINTS
+ is nonzero, process only watchpoints. */
+
+static void
+breakpoint_1 (bnum, allflag)
+ int bnum;
+ int allflag;
+{
+ register struct breakpoint *b;
+ register struct command_line *l;
+ register struct symbol *sym;
+ CORE_ADDR last_addr = (CORE_ADDR)-1;
+ int found_a_breakpoint = 0;
+ static char *bptypes[] = {"breakpoint", "hw breakpoint",
+ "until", "finish", "watchpoint",
+ "hw watchpoint", "read watchpoint",
+ "acc watchpoint", "longjmp",
+ "longjmp resume", "step resume",
+ "sigtramp",
+ "watchpoint scope", "call dummy",
+ "shlib events" };
+ static char *bpdisps[] = {"del", "dis", "keep"};
+ static char bpenables[] = "ny";
+ char wrap_indent[80];
+
+ ALL_BREAKPOINTS (b)
+ if (bnum == -1
+ || bnum == b->number)
+ {
+/* We only print out user settable breakpoints unless the allflag is set. */
+ if (!allflag
+ && b->type != bp_breakpoint
+ && 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++)
+ {
+ 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]);
+
+ strcpy (wrap_indent, " ");
+ if (addressprint)
+ strcat (wrap_indent, " ");
+ switch (b->type)
+ {
+ case bp_watchpoint:
+ 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:
+ case bp_shlib_event:
+ if (addressprint)
+ {
+ 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)
+ {
+ sym = find_pc_function (b->address);
+ if (sym)
+ {
+ fputs_filtered ("in ", gdb_stdout);
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), gdb_stdout);
+ wrap_here (wrap_indent);
+ fputs_filtered (" at ", gdb_stdout);
+ }
+ fputs_filtered (b->source_file, gdb_stdout);
+ printf_filtered (":%d", b->line_number);
+ }
+ else
+ print_address_symbolic (b->address, gdb_stdout, demangle, " ");
+ break;
+ }
+
+ printf_filtered ("\n");
+
+ if (b->frame)
+ {
+ 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 time%s\n",
+ b->hit_count, (b->hit_count == 1 ? "" : "s"));
+ }
+
+ if (b->ignore_count)
+ {
+ annotate_field (8);
+
+ printf_filtered ("\tignore next %d hits\n", b->ignore_count);
+ }
+
+ if ((l = b->commands))
+ {
+ annotate_field (9);
+
+ while (l)
+ {
+ print_command_line (l, 4);
+ l = l->next;
+ }
+ }
+ }
+
+ if (!found_a_breakpoint)
+ {
+ if (bnum == -1)
+ printf_filtered ("No breakpoints or watchpoints.\n");
+ else
+ printf_filtered ("No breakpoint or watchpoint number %d.\n", bnum);
+ }
+ else
+ /* Compare against (CORE_ADDR)-1 in case some compiler decides
+ 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 */
+static void
+breakpoints_info (bnum_exp, from_tty)
+ char *bnum_exp;
+ int from_tty;
+{
+ int bnum = -1;
+
+ if (bnum_exp)
+ bnum = parse_and_eval_address (bnum_exp);
+
+ breakpoint_1 (bnum, 0);
+}
+
+#if MAINTENANCE_CMDS
+
+/* ARGSUSED */
+static void
+maintenance_info_breakpoints (bnum_exp, from_tty)
+ char *bnum_exp;
+ int from_tty;
+{
+ int bnum = -1;
+
+ if (bnum_exp)
+ bnum = parse_and_eval_address (bnum_exp);
+
+ breakpoint_1 (bnum, 1);
+}
+
+#endif
+
+/* Print a message describing any breakpoints set at PC. */
+
+static void
+describe_other_breakpoints (pc)
+ register CORE_ADDR pc;
+{
+ register int others = 0;
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->address == pc)
+ others++;
+ if (others > 0)
+ {
+ printf_filtered ("Note: breakpoint%s ", (others > 1) ? "s" : "");
+ ALL_BREAKPOINTS (b)
+ if (b->address == pc)
+ {
+ others--;
+ printf_filtered
+ ("%d%s%s ",
+ b->number,
+ ((b->enable == disabled || b->enable == shlib_disabled)
+ ? " (disabled)" : ""),
+ (others > 1) ? "," : ((others == 1) ? " and" : ""));
+ }
+ printf_filtered ("also set at pc ");
+ print_address_numeric (pc, 1, gdb_stdout);
+ printf_filtered (".\n");
+ }
+}
+
+/* Set the default place to put a breakpoint
+ for the `break' command with no arguments. */
+
+void
+set_default_breakpoint (valid, addr, symtab, line)
+ int valid;
+ CORE_ADDR addr;
+ struct symtab *symtab;
+ int line;
+{
+ default_breakpoint_valid = valid;
+ default_breakpoint_address = addr;
+ default_breakpoint_symtab = symtab;
+ default_breakpoint_line = line;
+}
+
+/* Rescan breakpoints at address ADDRESS,
+ marking the first one as "first" and any others as "duplicates".
+ This is so that the bpt instruction is only inserted once. */
+
+static void
+check_duplicates (address)
+ CORE_ADDR address;
+{
+ register struct breakpoint *b;
+ register int count = 0;
+
+ if (address == 0) /* Watchpoints are uninteresting */
+ return;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable != disabled
+ && b->enable != shlib_disabled
+ && b->address == address)
+ {
+ count++;
+ b->duplicate = count > 1;
+ }
+}
+
+/* Low level routine to set a breakpoint.
+ Takes as args the three things that every breakpoint must have.
+ Returns the breakpoint object so caller can set other things.
+ Does not set the breakpoint number!
+ Does not print anything.
+
+ ==> This routine should not be called if there is a chance of later
+ error(); otherwise it leaves a bogus breakpoint on the chain. Validate
+ your arguments BEFORE calling this routine! */
+
+static struct breakpoint *
+set_raw_breakpoint (sal)
+ struct symtab_and_line sal;
+{
+ register struct breakpoint *b, *b1;
+
+ b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint));
+ memset (b, 0, sizeof (*b));
+ b->address = sal.pc;
+ if (sal.symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file = savestring (sal.symtab->filename,
+ strlen (sal.symtab->filename));
+ b->language = current_language->la_language;
+ b->input_radix = input_radix;
+ b->thread = -1;
+ b->line_number = sal.line;
+ b->enable = enabled;
+ b->next = 0;
+ b->silent = 0;
+ b->ignore_count = 0;
+ b->commands = NULL;
+ b->frame = 0;
+
+ /* Add this breakpoint to the end of the chain
+ so that a list of breakpoints will come out in order
+ of increasing numbers. */
+
+ b1 = breakpoint_chain;
+ if (b1 == 0)
+ breakpoint_chain = b;
+ else
+ {
+ while (b1->next)
+ b1 = b1->next;
+ b1->next = b;
+ }
+
+ check_duplicates (sal.pc);
+ breakpoints_changed ();
+
+ return b;
+}
+
+static int internal_breakpoint_number = -1;
+
+#ifdef GET_LONGJMP_TARGET
+
+static void
+create_longjmp_breakpoint (func_name)
+ char *func_name;
+{
+ struct symtab_and_line sal;
+ struct breakpoint *b;
+
+ if (func_name != NULL)
+ {
+ struct minimal_symbol *m;
+
+ m = lookup_minimal_symbol_text (func_name, NULL, (struct objfile *)NULL);
+ if (m)
+ sal.pc = SYMBOL_VALUE_ADDRESS (m);
+ else
+ return;
+ }
+ else
+ sal.pc = 0;
+
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ b = set_raw_breakpoint (sal);
+ if (!b) return;
+
+ b->type = func_name != NULL ? bp_longjmp : bp_longjmp_resume;
+ b->disposition = donttouch;
+ b->enable = disabled;
+ b->silent = 1;
+ if (func_name)
+ b->addr_string = strsave(func_name);
+ b->number = internal_breakpoint_number--;
+}
+
+#endif /* #ifdef GET_LONGJMP_TARGET */
+
+/* Call this routine when stepping and nexting to enable a breakpoint if we do
+ a longjmp(). When we hit that breakpoint, call
+ set_longjmp_resume_breakpoint() to figure out where we are going. */
+
+void
+enable_longjmp_breakpoint()
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->type == bp_longjmp)
+ {
+ b->enable = enabled;
+ check_duplicates (b->address);
+ }
+}
+
+void
+disable_longjmp_breakpoint()
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if ( b->type == bp_longjmp
+ || b->type == bp_longjmp_resume)
+ {
+ b->enable = disabled;
+ check_duplicates (b->address);
+ }
+}
+
+#ifdef SOLIB_ADD
+void
+remove_solib_event_breakpoints ()
+{
+ register struct breakpoint *b, *temp;
+
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->type == bp_shlib_event)
+ delete_breakpoint (b);
+}
+
+void
+create_solib_event_breakpoint (address)
+ CORE_ADDR address;
+{
+ struct breakpoint *b;
+ struct symtab_and_line sal;
+
+ sal.pc = address;
+ sal.symtab = NULL;
+ sal.line = 0;
+ b = set_raw_breakpoint (sal);
+ b->number = internal_breakpoint_number--;
+ b->disposition = donttouch;
+ b->type = bp_shlib_event;
+}
+
+/* Try to reenable any breakpoints in shared libraries. */
+void
+re_enable_breakpoints_in_shlibs ()
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->enable == shlib_disabled)
+ {
+ char buf[1];
+
+ /* Do not reenable the breakpoint if the shared library
+ is still not mapped in. */
+ if (target_read_memory (b->address, buf, 1) == 0)
+ b->enable = enabled;
+ }
+}
+
+#endif
+
+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.
+
+ FIXME - This ought to be done by setting a temporary breakpoint that gets
+ deleted automatically...
+*/
+
+void
+set_longjmp_resume_breakpoint(pc, frame)
+ CORE_ADDR pc;
+ struct frame_info *frame;
+{
+ register struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ if (b->type == bp_longjmp_resume)
+ {
+ b->address = pc;
+ b->enable = enabled;
+ if (frame != NULL)
+ b->frame = frame->frame;
+ else
+ b->frame = 0;
+ check_duplicates (b->address);
+ return;
+ }
+}
+
+/* Set a breakpoint that will evaporate an end of command
+ at address specified by SAL.
+ Restrict it to frame FRAME if FRAME is nonzero. */
+
+struct breakpoint *
+set_momentary_breakpoint (sal, frame, type)
+ struct symtab_and_line sal;
+ struct frame_info *frame;
+ enum bptype type;
+{
+ register struct breakpoint *b;
+ b = set_raw_breakpoint (sal);
+ b->type = type;
+ b->enable = enabled;
+ b->disposition = donttouch;
+ b->frame = (frame ? frame->frame : 0);
+
+ /* If we're debugging a multi-threaded program, then we
+ want momentary breakpoints to be active in only a
+ single thread of control. */
+ if (in_thread_list (inferior_pid))
+ b->thread = pid_to_thread_id (inferior_pid);
+
+ return b;
+}
+
+#if 0
+void
+clear_momentary_breakpoints ()
+{
+ register struct breakpoint *b, *temp;
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ if (b->disposition == delete)
+ {
+ delete_breakpoint (b);
+ break;
+ }
+}
+#endif
+
+/* Tell the user we have just set a breakpoint B. */
+
+static void
+mention (b)
+ struct breakpoint *b;
+{
+ int say_where = 0;
+
+ /* FIXME: This is misplaced; mention() is called by things (like hitting a
+ watchpoint) other than breakpoint creation. It should be possible to
+ clean this up and at the same time replace the random calls to
+ breakpoint_changed with this hook, as has already been done for
+ delete_breakpoint_hook and so on. */
+ if (create_breakpoint_hook)
+ create_breakpoint_hook (b);
+
+ switch (b->type)
+ {
+ case bp_watchpoint:
+ printf_filtered ("Watchpoint %d: ", b->number);
+ 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", 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:
+ case bp_shlib_event:
+ 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");
+}
+
+#if 0
+/* Nobody calls this currently. */
+/* Set a breakpoint from a symtab and line.
+ If TEMPFLAG is nonzero, it is a temporary breakpoint.
+ ADDR_STRING is a malloc'd string holding the name of where we are
+ setting the breakpoint. This is used later to re-set it after the
+ program is relinked and symbols are reloaded.
+ Print the same confirmation messages that the breakpoint command prints. */
+
+void
+set_breakpoint (s, line, tempflag, addr_string)
+ struct symtab *s;
+ int line;
+ int tempflag;
+ char *addr_string;
+{
+ register struct breakpoint *b;
+ struct symtab_and_line sal;
+
+ sal.symtab = s;
+ sal.line = line;
+ sal.pc = 0;
+ resolve_sal_pc (&sal); /* Might error out */
+ describe_other_breakpoints (sal.pc);
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = bp_breakpoint;
+ b->cond = 0;
+ b->addr_string = addr_string;
+ b->enable = enabled;
+ b->disposition = tempflag ? delete : donttouch;
+
+ mention (b);
+}
+#endif /* 0 */
+
+/* Set a breakpoint according to ARG (function, linenum or *address)
+ flag: first bit : 0 non-temporary, 1 temporary.
+ second bit : 0 normal breakpoint, 1 hardware breakpoint. */
+
+static void
+break_command_1 (arg, flag, from_tty)
+ char *arg;
+ int flag, from_tty;
+{
+ int tempflag, hardwareflag;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ register struct expression *cond = 0;
+ register struct breakpoint *b;
+
+ /* Pointers in arg to the start, and one past the end, of the condition. */
+ char *cond_start = NULL;
+ char *cond_end = NULL;
+ /* Pointers in arg to the start, and one past the end,
+ of the address part. */
+ char *addr_start = NULL;
+ char *addr_end = NULL;
+ struct cleanup *old_chain;
+ struct cleanup *canonical_strings_chain = NULL;
+ char **canonical = (char **)NULL;
+ int i;
+ int thread;
+
+ hardwareflag = flag & BP_HARDWAREFLAG;
+ tempflag = flag & BP_TEMPFLAG;
+
+ sals.sals = NULL;
+ sals.nelts = 0;
+
+ sal.line = sal.pc = sal.end = 0;
+ sal.symtab = 0;
+
+ /* If no arg given, or if first arg is 'if ', use the default breakpoint. */
+
+ if (!arg || (arg[0] == 'i' && arg[1] == 'f'
+ && (arg[2] == ' ' || arg[2] == '\t')))
+ {
+ if (default_breakpoint_valid)
+ {
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ sal.pc = default_breakpoint_address;
+ sal.line = default_breakpoint_line;
+ sal.symtab = default_breakpoint_symtab;
+ sals.sals[0] = sal;
+ sals.nelts = 1;
+ }
+ else
+ error ("No default breakpoint address now.");
+ }
+ else
+ {
+ addr_start = arg;
+
+ /* Force almost all breakpoints to be in terms of the
+ current_source_symtab (which is decode_line_1's default). This
+ should produce the results we want almost all of the time while
+ leaving default_breakpoint_* alone. */
+ if (default_breakpoint_valid
+ && (!current_source_symtab
+ || (arg && (*arg == '+' || *arg == '-'))))
+ sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
+ default_breakpoint_line, &canonical);
+ else
+ sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, &canonical);
+
+ addr_end = arg;
+ }
+
+ if (! sals.nelts)
+ return;
+
+ /* Make sure that all storage allocated in decode_line_1 gets freed in case
+ the following `for' loop errors out. */
+ old_chain = make_cleanup (free, sals.sals);
+ if (canonical != (char **)NULL)
+ {
+ make_cleanup (free, canonical);
+ canonical_strings_chain = make_cleanup (null_cleanup, 0);
+ for (i = 0; i < sals.nelts; i++)
+ {
+ if (canonical[i] != NULL)
+ make_cleanup (free, canonical[i]);
+ }
+ }
+
+ thread = -1; /* No specific thread yet */
+
+ /* Resolve all line numbers to PC's, and verify that conditions
+ can be parsed, before setting any breakpoints. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ char *tok, *end_tok;
+ int toklen;
+
+ resolve_sal_pc (&sals.sals[i]);
+
+ tok = arg;
+
+ while (tok && *tok)
+ {
+ 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, block_for_pc (sals.sals[i].pc), 0);
+ cond_end = tok;
+ }
+ else if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0)
+ {
+ char *tmptok;
+
+ tok = end_tok + 1;
+ tmptok = tok;
+ thread = strtol (tok, &tok, 0);
+ if (tok == tmptok)
+ error ("Junk after thread keyword.");
+ if (!valid_thread_id (thread))
+ error ("Unknown thread %d\n", thread);
+ }
+ else
+ 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)
+ discard_cleanups (canonical_strings_chain);
+
+ /* Now set all the breakpoints. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ sal = sals.sals[i];
+
+ if (from_tty)
+ describe_other_breakpoints (sal.pc);
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = hardwareflag ? bp_hardware_breakpoint : bp_breakpoint;
+ b->cond = cond;
+ b->thread = thread;
+
+ /* If a canonical line spec is needed use that instead of the
+ command string. */
+ if (canonical != (char **)NULL && canonical[i] != NULL)
+ b->addr_string = canonical[i];
+ else if (addr_start)
+ b->addr_string = savestring (addr_start, addr_end - addr_start);
+ if (cond_start)
+ b->cond_string = savestring (cond_start, cond_end - cond_start);
+
+ b->enable = enabled;
+ b->disposition = tempflag ? del : donttouch;
+
+ mention (b);
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf_filtered ("Multiple breakpoints were set.\n");
+ printf_filtered ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ }
+ do_cleanups (old_chain);
+}
+
+/* Helper function for break_command_1 and disassemble_command. */
+
+void
+resolve_sal_pc (sal)
+ struct symtab_and_line *sal;
+{
+ CORE_ADDR pc;
+
+ if (sal->pc == 0 && sal->symtab != 0)
+ {
+ pc = find_line_pc (sal->symtab, sal->line);
+ if (pc == 0)
+ error ("No line %d in file \"%s\".",
+ sal->line, sal->symtab->filename);
+ sal->pc = pc;
+ }
+}
+
+void
+break_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ break_command_1 (arg, 0, from_tty);
+}
+
+static void
+tbreak_command (arg, from_tty)
+ char *arg;
+ int 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_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, *mark;
+ struct frame_info *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;
+ sal.line = 0;
+
+ /* Parse arguments. */
+ innermost_block = NULL;
+ 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->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 = 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->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 = del;
+
+ /* 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
+ because it uses the mechanisms of breakpoints. */
+
+/* ARGSUSED */
+void
+until_break_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct frame_info *prev_frame = get_prev_frame (selected_frame);
+ struct breakpoint *breakpoint;
+ struct cleanup *old_chain;
+
+ clear_proceed_status ();
+
+ /* Set a breakpoint where the user wants it and at return from
+ this function */
+
+ if (default_breakpoint_valid)
+ sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
+ default_breakpoint_line, (char ***)NULL);
+ else
+ sals = decode_line_1 (&arg, 1, (struct symtab *)NULL, 0, (char ***)NULL);
+
+ if (sals.nelts != 1)
+ error ("Couldn't get information on specified line.");
+
+ sal = sals.sals[0];
+ free ((PTR)sals.sals); /* malloc'd, so freed */
+
+ if (*arg)
+ error ("Junk at end of arguments.");
+
+ resolve_sal_pc (&sal);
+
+ breakpoint = set_momentary_breakpoint (sal, selected_frame, bp_until);
+
+ old_chain = make_cleanup(delete_breakpoint, breakpoint);
+
+ /* Keep within the current frame */
+
+ if (prev_frame)
+ {
+ sal = find_pc_line (prev_frame->pc, 0);
+ sal.pc = prev_frame->pc;
+ breakpoint = set_momentary_breakpoint (sal, prev_frame, bp_until);
+ make_cleanup(delete_breakpoint, breakpoint);
+ }
+
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+ do_cleanups(old_chain);
+}
+
+#if 0
+/* These aren't used; I don't konw what they were for. */
+/* Set a breakpoint at the catch clause for NAME. */
+static int
+catch_breakpoint (name)
+ char *name;
+{
+}
+
+static int
+disable_catch_breakpoint ()
+{
+}
+
+static int
+delete_catch_breakpoint ()
+{
+}
+
+static int
+enable_catch_breakpoint ()
+{
+}
+#endif /* 0 */
+
+struct sal_chain
+{
+ struct sal_chain *next;
+ struct symtab_and_line sal;
+};
+
+#if 0
+/* This isn't used; I don't know what it was for. */
+/* For each catch clause identified in ARGS, run FUNCTION
+ with that clause as an argument. */
+static struct symtabs_and_lines
+map_catch_names (args, function)
+ char *args;
+ int (*function)();
+{
+ register char *p = args;
+ register char *p1;
+ struct symtabs_and_lines sals;
+#if 0
+ struct sal_chain *sal_chain = 0;
+#endif
+
+ if (p == 0)
+ error_no_arg ("one or more catch names");
+
+ sals.nelts = 0;
+ sals.sals = NULL;
+
+ while (*p)
+ {
+ p1 = p;
+ /* Don't swallow conditional part. */
+ if (p1[0] == 'i' && p1[1] == 'f'
+ && (p1[2] == ' ' || p1[2] == '\t'))
+ break;
+
+ if (isalpha (*p1))
+ {
+ p1++;
+ while (isalnum (*p1) || *p1 == '_' || *p1 == '$')
+ p1++;
+ }
+
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be catch names.");
+
+ *p1 = 0;
+#if 0
+ if (function (p))
+ {
+ struct sal_chain *next
+ = (struct sal_chain *)alloca (sizeof (struct sal_chain));
+ next->next = sal_chain;
+ next->sal = get_catch_sal (p);
+ sal_chain = next;
+ goto win;
+ }
+#endif
+ printf_unfiltered ("No catch clause for exception %s.\n", p);
+#if 0
+ win:
+#endif
+ p = p1;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+}
+#endif /* 0 */
+
+/* This shares a lot of code with `print_frame_label_vars' from stack.c. */
+
+static struct symtabs_and_lines
+get_catch_sals (this_level_only)
+ int this_level_only;
+{
+ register struct blockvector *bl;
+ register struct block *block;
+ int index, have_default = 0;
+ CORE_ADDR pc;
+ struct symtabs_and_lines sals;
+ struct sal_chain *sal_chain = 0;
+ char *blocks_searched;
+
+ /* Not sure whether an error message is always the correct response,
+ but it's better than a core dump. */
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ block = get_frame_block (selected_frame);
+ pc = selected_frame->pc;
+
+ sals.nelts = 0;
+ sals.sals = NULL;
+
+ if (block == 0)
+ error ("No symbol table info available.\n");
+
+ bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
+ blocks_searched = (char *) alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+ memset (blocks_searched, 0, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+
+ while (block != 0)
+ {
+ CORE_ADDR end = BLOCK_END (block) - 4;
+ int last_index;
+
+ if (bl != blockvector_for_pc (end, &index))
+ error ("blockvector blotch");
+ if (BLOCKVECTOR_BLOCK (bl, index) != block)
+ error ("blockvector botch");
+ last_index = BLOCKVECTOR_NBLOCKS (bl);
+ index += 1;
+
+ /* Don't print out blocks that have gone by. */
+ while (index < last_index
+ && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < pc)
+ index++;
+
+ while (index < last_index
+ && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < end)
+ {
+ if (blocks_searched[index] == 0)
+ {
+ struct block *b = BLOCKVECTOR_BLOCK (bl, index);
+ int nsyms;
+ register int i;
+ register struct symbol *sym;
+
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ if (STREQ (SYMBOL_NAME (sym), "default"))
+ {
+ if (have_default)
+ continue;
+ have_default = 1;
+ }
+ if (SYMBOL_CLASS (sym) == LOC_LABEL)
+ {
+ struct sal_chain *next = (struct sal_chain *)
+ alloca (sizeof (struct sal_chain));
+ next->next = sal_chain;
+ next->sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0);
+ sal_chain = next;
+ }
+ }
+ blocks_searched[index] = 1;
+ }
+ index++;
+ }
+ if (have_default)
+ break;
+ if (sal_chain && this_level_only)
+ break;
+
+ /* After handling the function's top-level block, stop.
+ Don't continue to its superblock, the block of
+ per-file symbols. */
+ if (BLOCK_FUNCTION (block))
+ break;
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ if (sal_chain)
+ {
+ struct sal_chain *tmp_chain;
+
+ /* Count the number of entries. */
+ for (index = 0, tmp_chain = sal_chain; tmp_chain;
+ tmp_chain = tmp_chain->next)
+ index++;
+
+ sals.nelts = index;
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (index * sizeof (struct symtab_and_line));
+ for (index = 0; sal_chain; sal_chain = sal_chain->next, index++)
+ sals.sals[index] = sal_chain->sal;
+ }
+
+ return sals;
+}
+
+/* Commands to deal with catching exceptions. */
+
+static void
+catch_command_1 (arg, tempflag, from_tty)
+ char *arg;
+ int tempflag;
+ int from_tty;
+{
+ /* First, translate ARG into something we can deal with in terms
+ of breakpoints. */
+
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ register struct expression *cond = 0;
+ register struct breakpoint *b;
+ char *save_arg;
+ int i;
+
+ sal.line = sal.pc = sal.end = 0;
+ sal.symtab = 0;
+
+ /* If no arg given, or if first arg is 'if ', all active catch clauses
+ are breakpointed. */
+
+ if (!arg || (arg[0] == 'i' && arg[1] == 'f'
+ && (arg[2] == ' ' || arg[2] == '\t')))
+ {
+ /* Grab all active catch clauses. */
+ sals = get_catch_sals (0);
+ }
+ else
+ {
+ /* Grab selected catch clauses. */
+ error ("catch NAME not implemented");
+#if 0
+ /* This isn't used; I don't know what it was for. */
+ sals = map_catch_names (arg, catch_breakpoint);
+#endif
+ }
+
+ if (! sals.nelts)
+ return;
+
+ save_arg = arg;
+ for (i = 0; i < sals.nelts; i++)
+ {
+ resolve_sal_pc (&sals.sals[i]);
+
+ while (arg && *arg)
+ {
+ if (arg[0] == 'i' && arg[1] == 'f'
+ && (arg[2] == ' ' || arg[2] == '\t'))
+ cond = parse_exp_1 ((arg += 2, &arg),
+ block_for_pc (sals.sals[i].pc), 0);
+ else
+ error ("Junk at end of arguments.");
+ }
+ arg = save_arg;
+ }
+
+ for (i = 0; i < sals.nelts; i++)
+ {
+ sal = sals.sals[i];
+
+ if (from_tty)
+ describe_other_breakpoints (sal.pc);
+
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = bp_breakpoint;
+ b->cond = cond;
+ b->enable = enabled;
+ b->disposition = tempflag ? del : donttouch;
+
+ mention (b);
+ }
+
+ if (sals.nelts > 1)
+ {
+ printf_unfiltered ("Multiple breakpoints were set.\n");
+ printf_unfiltered ("Use the \"delete\" command to delete unwanted breakpoints.\n");
+ }
+ free ((PTR)sals.sals);
+}
+
+/* Used by the gui, could be made a worker for other things. */
+
+struct breakpoint *
+set_breakpoint_sal (sal)
+struct symtab_and_line sal;
+{
+ struct breakpoint *b;
+ b = set_raw_breakpoint (sal);
+ set_breakpoint_count (breakpoint_count + 1);
+ b->number = breakpoint_count;
+ b->type = bp_breakpoint;
+ b->cond = 0;
+ b->thread = -1;
+ return b;
+}
+
+#if 0
+/* These aren't used; I don't know what they were for. */
+/* Disable breakpoints on all catch clauses described in ARGS. */
+static void
+disable_catch (args)
+ char *args;
+{
+ /* Map the disable command to catch clauses described in ARGS. */
+}
+
+/* Enable breakpoints on all catch clauses described in ARGS. */
+static void
+enable_catch (args)
+ char *args;
+{
+ /* Map the disable command to catch clauses described in ARGS. */
+}
+
+/* Delete breakpoints on all catch clauses in the active scope. */
+static void
+delete_catch (args)
+ char *args;
+{
+ /* Map the delete command to catch clauses described in ARGS. */
+}
+#endif /* 0 */
+
+static void
+catch_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ catch_command_1 (arg, 0, from_tty);
+}
+
+static void
+clear_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register struct breakpoint *b, *b1;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ register struct breakpoint *found;
+ int i;
+
+ if (arg)
+ {
+ sals = decode_line_spec (arg, 1);
+ }
+ else
+ {
+ sals.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
+ sal.line = default_breakpoint_line;
+ sal.symtab = default_breakpoint_symtab;
+ sal.pc = 0;
+ if (sal.symtab == 0)
+ error ("No source file specified.");
+
+ sals.sals[0] = sal;
+ sals.nelts = 1;
+ }
+
+ for (i = 0; i < sals.nelts; i++)
+ {
+ /* If exact pc given, clear bpts at that pc.
+ But if sal.pc is zero, clear all bpts on specified line. */
+ sal = sals.sals[i];
+ found = (struct breakpoint *) 0;
+ while (breakpoint_chain
+ && (sal.pc
+ ? breakpoint_chain->address == sal.pc
+ : (breakpoint_chain->source_file != NULL
+ && sal.symtab != NULL
+ && STREQ (breakpoint_chain->source_file,
+ sal.symtab->filename)
+ && breakpoint_chain->line_number == sal.line)))
+ {
+ b1 = breakpoint_chain;
+ breakpoint_chain = b1->next;
+ b1->next = found;
+ found = b1;
+ }
+
+ 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
+ && sal.symtab != NULL
+ && STREQ (b->next->source_file, sal.symtab->filename)
+ && b->next->line_number == sal.line)))
+ {
+ b1 = b->next;
+ b->next = b1->next;
+ b1->next = found;
+ found = b1;
+ }
+
+ if (found == 0)
+ {
+ if (arg)
+ error ("No breakpoint at %s.", arg);
+ else
+ error ("No breakpoint at this line.");
+ }
+
+ if (found->next) from_tty = 1; /* Always report if deleted more than one */
+ if (from_tty) printf_unfiltered ("Deleted breakpoint%s ", found->next ? "s" : "");
+ breakpoints_changed ();
+ while (found)
+ {
+ if (from_tty) printf_unfiltered ("%d ", found->number);
+ b1 = found->next;
+ delete_breakpoint (found);
+ found = b1;
+ }
+ if (from_tty) putchar_unfiltered ('\n');
+ }
+ free ((PTR)sals.sals);
+}
+
+/* Delete breakpoint in BS if they are `delete' breakpoints.
+ This is called after any breakpoint is hit, or after errors. */
+
+void
+breakpoint_auto_delete (bs)
+ bpstat bs;
+{
+ for (; bs; bs = bs->next)
+ if (bs->breakpoint_at && bs->breakpoint_at->disposition == del
+ && bs->stop)
+ delete_breakpoint (bs->breakpoint_at);
+}
+
+/* Delete a breakpoint and clean up all traces of it in the data structures. */
+
+void
+delete_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ register struct breakpoint *b;
+ register bpstat bs;
+
+ if (delete_breakpoint_hook)
+ delete_breakpoint_hook (bpt);
+
+ if (bpt->inserted)
+ remove_breakpoint (bpt);
+
+ if (breakpoint_chain == bpt)
+ breakpoint_chain = bpt->next;
+
+ ALL_BREAKPOINTS (b)
+ if (b->next == bpt)
+ {
+ b->next = bpt->next;
+ break;
+ }
+
+ 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
+ && bpt->type != bp_hardware_watchpoint
+ && bpt->type != bp_read_watchpoint
+ && bpt->type != bp_access_watchpoint)
+ {
+ ALL_BREAKPOINTS (b)
+ if (b->address == bpt->address
+ && !b->duplicate
+ && b->enable != disabled
+ && b->enable != shlib_disabled)
+ {
+ int val;
+ val = target_insert_breakpoint (b->address, b->shadow_contents);
+ if (val != 0)
+ {
+ 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
+ b->inserted = 1;
+ }
+ }
+
+ free_command_lines (&bpt->commands);
+ if (bpt->cond)
+ free (bpt->cond);
+ if (bpt->cond_string != NULL)
+ free (bpt->cond_string);
+ if (bpt->addr_string != NULL)
+ free (bpt->addr_string);
+ if (bpt->exp_string != NULL)
+ free (bpt->exp_string);
+ if (bpt->source_file != NULL)
+ free (bpt->source_file);
+
+ /* 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. */
+ for (bs = stop_bpstat; bs; bs = bs->next)
+ if (bs->breakpoint_at == bpt)
+ bs->breakpoint_at = NULL;
+ free ((PTR)bpt);
+}
+
+static void
+delete_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+
+ if (arg == 0)
+ {
+ /* Ask user only if there are some breakpoints to delete. */
+ if (!from_tty
+ || (breakpoint_chain && query ("Delete all breakpoints? ")))
+ {
+ /* No arg; clear all breakpoints. */
+ while (breakpoint_chain)
+ delete_breakpoint (breakpoint_chain);
+ }
+ }
+ else
+ map_breakpoint_numbers (arg, delete_breakpoint);
+}
+
+/* Reset a breakpoint given it's struct breakpoint * BINT.
+ The value we return ends up being the return value from catch_errors.
+ Unused in this case. */
+
+static int
+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;
+ enum enable save_enable;
+
+ switch (b->type)
+ {
+ case bp_breakpoint:
+ case bp_hardware_breakpoint:
+ if (b->addr_string == NULL)
+ {
+ /* Anything without a string can't be re-set. */
+ delete_breakpoint (b);
+ return 0;
+ }
+ /* In case we have a problem, disable this breakpoint. We'll restore
+ its status if we succeed. */
+ save_enable = b->enable;
+ b->enable = disabled;
+
+ set_language (b->language);
+ input_radix = b->input_radix;
+ s = b->addr_string;
+ sals = decode_line_1 (&s, 1, (struct symtab *)NULL, 0, (char ***)NULL);
+ for (i = 0; i < sals.nelts; i++)
+ {
+ resolve_sal_pc (&sals.sals[i]);
+
+ /* Reparse conditions, they might contain references to the
+ old symtab. */
+ if (b->cond_string != NULL)
+ {
+ s = b->cond_string;
+ if (b->cond)
+ free ((PTR)b->cond);
+ b->cond = parse_exp_1 (&s, block_for_pc (sals.sals[i].pc), 0);
+ }
+
+ /* We need to re-set the breakpoint if the address changes...*/
+ if (b->address != sals.sals[i].pc
+ /* ...or new and old breakpoints both have source files, and
+ the source file name or the line number changes... */
+ || (b->source_file != NULL
+ && sals.sals[i].symtab != NULL
+ && (!STREQ (b->source_file, sals.sals[i].symtab->filename)
+ || b->line_number != sals.sals[i].line)
+ )
+ /* ...or we switch between having a source file and not having
+ one. */
+ || ((b->source_file == NULL) != (sals.sals[i].symtab == NULL))
+ )
+ {
+ if (b->source_file != NULL)
+ free (b->source_file);
+ if (sals.sals[i].symtab == NULL)
+ b->source_file = NULL;
+ else
+ b->source_file =
+ savestring (sals.sals[i].symtab->filename,
+ strlen (sals.sals[i].symtab->filename));
+ b->line_number = sals.sals[i].line;
+ b->address = sals.sals[i].pc;
+
+ 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. */
+ }
+ free ((PTR)sals.sals);
+ 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
+ been re-read? We could save the filename and functionname, but
+ if the context is more local than that, the best we could do would
+ be something like how many levels deep and which index at that
+ particular level, but that's going to be less stable than filenames
+ or functionnames. */
+ /* 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))
+ value_fetch_lazy (b->val);
+
+ if (b->cond_string != NULL)
+ {
+ s = b->cond_string;
+ b->cond = parse_exp_1 (&s, (struct block *)0, 0);
+ }
+ if (b->enable == enabled)
+ mention (b);
+ value_free_to_mark (mark);
+ break;
+
+ default:
+ printf_filtered ("Deleting unknown breakpoint type %d\n", b->type);
+ /* fall through */
+ /* Delete longjmp breakpoints, they will be reset later by
+ breakpoint_re_set. */
+ case bp_longjmp:
+ case bp_longjmp_resume:
+ delete_breakpoint (b);
+ break;
+
+ /* This breakpoint is special, it's set up when the inferior
+ starts and we really don't want to touch it. */
+ case bp_shlib_event:
+
+ /* Keep temporary breakpoints, which can be encountered when we step
+ over a dlopen call and SOLIB_ADD is resetting the breakpoints.
+ Otherwise these should have been blown away via the cleanup chain
+ or by breakpoint_init_inferior when we rerun the executable. */
+ case bp_until:
+ case bp_finish:
+ case bp_watchpoint_scope:
+ case bp_call_dummy:
+ case bp_step_resume:
+ break;
+ }
+
+ return 0;
+}
+
+/* Re-set all breakpoints after symbols have been re-loaded. */
+void
+breakpoint_re_set ()
+{
+ struct breakpoint *b, *temp;
+ enum language save_language;
+ int save_input_radix;
+ static char message1[] = "Error in re-setting breakpoint %d:\n";
+ char message[sizeof (message1) + 30 /* slop */];
+
+ save_language = current_language->la_language;
+ save_input_radix = input_radix;
+ ALL_BREAKPOINTS_SAFE (b, temp)
+ {
+ sprintf (message, message1, b->number); /* Format possible error msg */
+ catch_errors (breakpoint_re_set_one, (char *) b, message,
+ RETURN_MASK_ALL);
+ }
+ set_language (save_language);
+ input_radix = save_input_radix;
+
+#ifdef GET_LONGJMP_TARGET
+ create_longjmp_breakpoint ("longjmp");
+ create_longjmp_breakpoint ("_longjmp");
+ create_longjmp_breakpoint ("siglongjmp");
+ create_longjmp_breakpoint (NULL);
+#endif
+
+#if 0
+ /* Took this out (temporarily at least), since it produces an extra
+ blank line at startup. This messes up the gdbtests. -PB */
+ /* Blank line to finish off all those mention() messages we just printed. */
+ printf_filtered ("\n");
+#endif
+}
+
+/* Set ignore-count of breakpoint number BPTNUM to COUNT.
+ If from_tty is nonzero, it prints a message to that effect,
+ which ends with a period (no newline). */
+
+void
+set_ignore_count (bptnum, count, from_tty)
+ int bptnum, count, from_tty;
+{
+ register struct breakpoint *b;
+
+ if (count < 0)
+ count = 0;
+
+ ALL_BREAKPOINTS (b)
+ if (b->number == bptnum)
+ {
+ b->ignore_count = count;
+ if (!from_tty)
+ return;
+ else if (count == 0)
+ printf_filtered ("Will stop next time breakpoint %d is reached.",
+ bptnum);
+ else if (count == 1)
+ printf_filtered ("Will ignore next crossing of breakpoint %d.",
+ bptnum);
+ else
+ printf_filtered ("Will ignore next %d crossings of breakpoint %d.",
+ count, bptnum);
+ breakpoints_changed ();
+ return;
+ }
+
+ error ("No breakpoint number %d.", bptnum);
+}
+
+/* Clear the ignore counts of all breakpoints. */
+void
+breakpoint_clear_ignore_counts ()
+{
+ struct breakpoint *b;
+
+ ALL_BREAKPOINTS (b)
+ b->ignore_count = 0;
+}
+
+/* Command to set ignore-count of breakpoint N to COUNT. */
+
+static void
+ignore_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *p = args;
+ register int num;
+
+ if (p == 0)
+ error_no_arg ("a breakpoint number");
+
+ num = get_number (&p);
+
+ if (*p == 0)
+ error ("Second argument (specified ignore-count) is missing.");
+
+ set_ignore_count (num,
+ longest_to_int (value_as_long (parse_and_eval (p))),
+ from_tty);
+ printf_filtered ("\n");
+ breakpoints_changed ();
+}
+
+/* Call FUNCTION on each of the breakpoints
+ whose numbers are given in ARGS. */
+
+static void
+map_breakpoint_numbers (args, function)
+ char *args;
+ void (*function) PARAMS ((struct breakpoint *));
+{
+ register char *p = args;
+ char *p1;
+ register int num;
+ register struct breakpoint *b;
+
+ if (p == 0)
+ error_no_arg ("one or more breakpoint numbers");
+
+ while (*p)
+ {
+ p1 = p;
+
+ num = get_number (&p1);
+
+ 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_unfiltered ("No breakpoint number %d.\n", num);
+ win:
+ p = p1;
+ }
+}
+
+void
+enable_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ struct frame_info *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;
+ check_duplicates (bpt->address);
+
+ 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)
+ {
+ struct frame_info *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);
+ return;
+ }
+ }
+
+ if (save_selected_frame_level >= 0)
+ select_frame (save_selected_frame, save_selected_frame_level);
+ value_free_to_mark (mark);
+ }
+
+ if (modify_breakpoint_hook)
+ modify_breakpoint_hook (bpt);
+}
+
+/* ARGSUSED */
+static void
+enable_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ 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;
+ }
+ else
+ map_breakpoint_numbers (args, enable_breakpoint);
+}
+
+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;
+
+ check_duplicates (bpt->address);
+
+ if (modify_breakpoint_hook)
+ modify_breakpoint_hook (bpt);
+}
+
+/* ARGSUSED */
+static void
+disable_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register struct breakpoint *bpt;
+ if (args == 0)
+ ALL_BREAKPOINTS (bpt)
+ 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:
+ disable_breakpoint (bpt);
+ default:
+ continue;
+ }
+ else
+ map_breakpoint_numbers (args, disable_breakpoint);
+}
+
+static void
+enable_once_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ struct frame_info *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)
+ {
+ struct frame_info *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 */
+static void
+enable_once_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ map_breakpoint_numbers (args, enable_once_breakpoint);
+}
+
+static void
+enable_delete_breakpoint (bpt)
+ struct breakpoint *bpt;
+{
+ bpt->enable = enabled;
+ bpt->disposition = del;
+
+ check_duplicates (bpt->address);
+ breakpoints_changed ();
+}
+
+/* ARGSUSED */
+static void
+enable_delete_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ map_breakpoint_numbers (args, enable_delete_breakpoint);
+}
+
+/* Use default_breakpoint_'s, or nothing if they aren't valid. */
+
+struct symtabs_and_lines
+decode_line_spec_1 (string, funfirstline)
+ char *string;
+ int funfirstline;
+{
+ struct symtabs_and_lines sals;
+ if (string == 0)
+ error ("Empty line specification.");
+ if (default_breakpoint_valid)
+ sals = decode_line_1 (&string, funfirstline,
+ default_breakpoint_symtab, default_breakpoint_line,
+ (char ***)NULL);
+ else
+ sals = decode_line_1 (&string, funfirstline,
+ (struct symtab *)NULL, 0, (char ***)NULL);
+ if (*string)
+ error ("Junk at end of line specification: %s", string);
+ return sals;
+}
+
+void
+_initialize_breakpoint ()
+{
+ breakpoint_chain = 0;
+ /* Don't bother to call set_breakpoint_count. $bpnum isn't useful
+ before a breakpoint is set. */
+ breakpoint_count = 0;
+
+ add_com ("ignore", class_breakpoint, ignore_command,
+ "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\
+Give breakpoint number as argument after \"commands\".\n\
+With no argument, the targeted breakpoint is the last one set.\n\
+The commands themselves follow starting on the next line.\n\
+Type a line containing \"end\" to indicate the end of them.\n\
+Give \"silent\" as the first line to make the breakpoint silent;\n\
+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\
+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 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\
+Give breakpoint numbers (separated by spaces) as arguments.\n\
+With no subcommand, breakpoints are enabled until you command otherwise.\n\
+This is used to cancel the effect of the \"disable\" command.\n\
+With a subcommand you can enable temporarily.",
+ &enablelist, "enable ", 1, &cmdlist);
+
+ add_abbrev_prefix_cmd ("breakpoints", class_breakpoint, enable_command,
+ "Enable some breakpoints.\n\
+Give breakpoint numbers (separated by spaces) as arguments.\n\
+This is used to cancel the effect of the \"disable\" command.\n\
+May be abbreviated to simply \"enable\".\n",
+ &enablebreaklist, "enable breakpoints ", 1, &enablelist);
+
+ 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.",
+ &enablebreaklist);
+
+ add_cmd ("delete", no_class, enable_delete_command,
+ "Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it is deleted.",
+ &enablebreaklist);
+
+ add_cmd ("delete", no_class, enable_delete_command,
+ "Enable breakpoints and delete when hit. Give breakpoint numbers.\n\
+If a breakpoint is hit while enabled in this fashion, it is deleted.",
+ &enablelist);
+
+ 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.",
+ &enablelist);
+
+ add_prefix_cmd ("disable", class_breakpoint, disable_command,
+ "Disable some breakpoints.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To disable all breakpoints, give no argument.\n\
+A disabled breakpoint is not forgotten, but has no effect until reenabled.",
+ &disablelist, "disable ", 1, &cmdlist);
+ add_com_alias ("dis", "disable", class_breakpoint, 1);
+ add_com_alias ("disa", "disable", class_breakpoint, 1);
+
+ add_cmd ("breakpoints", class_alias, disable_command,
+ "Disable some breakpoints.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To disable all breakpoints, give no argument.\n\
+A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\
+This command may be abbreviated \"disable\".",
+ &disablelist);
+
+ add_prefix_cmd ("delete", class_breakpoint, delete_command,
+ "Delete some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.\n\
+\n\
+Also a prefix command for deletion of other GDB objects.\n\
+The \"unset\" command is also an alias for \"delete\".",
+ &deletelist, "delete ", 1, &cmdlist);
+ add_com_alias ("d", "delete", class_breakpoint, 1);
+
+ add_cmd ("breakpoints", class_alias, delete_command,
+ "Delete some breakpoints or auto-display expressions.\n\
+Arguments are breakpoint numbers with spaces in between.\n\
+To delete all breakpoints, give no argument.\n\
+This command may be abbreviated \"delete\".",
+ &deletelist);
+
+ add_com ("clear", class_breakpoint, clear_command,
+ concat ("Clear breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, all breakpoints in that line are cleared.\n\
+If function is specified, breakpoints at beginning of function are cleared.\n\
+If an address is specified, breakpoints at that address are cleared.\n\n",
+"With no argument, clears all breakpoints in the line that the selected frame\n\
+is executing in.\n\
+\n\
+See also the \"delete\" command which clears breakpoints by number.", NULL));
+
+ add_com ("break", class_breakpoint, break_command,
+ concat ("Set breakpoint at specified line or function.\n\
+Argument may be line number, function name, or \"*\" and an address.\n\
+If line number is specified, break at start of code for that line.\n\
+If function is specified, break at start of code for that function.\n\
+If an address is specified, break at that exact address.\n",
+"With no arg, uses current execution address of selected stack frame.\n\
+This is useful for breaking on return to a stack frame.\n\
+\n\
+Multiple breakpoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.", NULL));
+ add_com_alias ("b", "break", class_run, 1);
+ add_com_alias ("br", "break", class_run, 1);
+ add_com_alias ("bre", "break", class_run, 1);
+ add_com_alias ("brea", "break", class_run, 1);
+
+ add_info ("breakpoints", breakpoints_info,
+ concat ("Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
+The \"Type\" column indicates one of:\n\
+\tbreakpoint - normal breakpoint\n\
+\twatchpoint - watchpoint\n\
+The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
+the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
+breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
+address and file/line number respectively.\n\n",
+"Convenience variable \"$_\" and default examine address for \"x\"\n\
+are set to the address of the last breakpoint listed.\n\n\
+Convenience variable \"$bpnum\" contains the number of the last\n\
+breakpoint set.", NULL));
+
+#if MAINTENANCE_CMDS
+
+ add_cmd ("breakpoints", class_maintenance, maintenance_info_breakpoints,
+ concat ("Status of all breakpoints, or breakpoint number NUMBER.\n\
+The \"Type\" column indicates one of:\n\
+\tbreakpoint - normal breakpoint\n\
+\twatchpoint - watchpoint\n\
+\tlongjmp - internal breakpoint used to step through longjmp()\n\
+\tlongjmp resume - internal breakpoint at the target of longjmp()\n\
+\tuntil - internal breakpoint used by the \"until\" command\n\
+\tfinish - internal breakpoint used by the \"finish\" command\n",
+"The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
+the disposition of the breakpoint after it gets hit. \"dis\" means that the\n\
+breakpoint will be disabled. The \"Address\" and \"What\" columns indicate the\n\
+address and file/line number respectively.\n\n",
+"Convenience variable \"$_\" and default examine address for \"x\"\n\
+are set to the address of the last breakpoint listed.\n\n\
+Convenience variable \"$bpnum\" contains the number of the last\n\
+breakpoint set.", NULL),
+ &maintenanceinfolist);
+
+#endif /* MAINTENANCE_CMDS */
+
+ add_com ("catch", class_breakpoint, catch_command,
+ "Set breakpoints to catch exceptions that are raised.\n\
+Argument may be a single exception to catch, multiple exceptions\n\
+to catch, or the default exception \"default\". If no arguments\n\
+are given, breakpoints are set at all exception handlers catch clauses\n\
+within the current scope.\n\
+\n\
+A condition specified for the catch applies to all breakpoints set\n\
+with this command\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.");
+
+ add_com ("watch", class_breakpoint, watch_command,
+ "Set a watchpoint for an expression.\n\
+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''.");
+
+}
diff --git a/contrib/gdb/gdb/breakpoint.h b/contrib/gdb/gdb/breakpoint.h
new file mode 100644
index 0000000..90970cd
--- /dev/null
+++ b/contrib/gdb/gdb/breakpoint.h
@@ -0,0 +1,424 @@
+/* Data structures associated with breakpoints in GDB.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (BREAKPOINT_H)
+#define BREAKPOINT_H 1
+
+#include "frame.h"
+#include "value.h"
+
+/* This is the maximum number of bytes a breakpoint instruction can take.
+ Feel free to increase it. It's just used in a few places to size
+ arrays that should be independent of the target architecture. */
+
+#define BREAKPOINT_MAX 16
+
+/* Type of breakpoint. */
+/* FIXME In the future, we should fold all other breakpoint-like things into
+ here. This includes:
+
+ * single-step (for machines where we have to simulate single stepping)
+ (probably, though perhaps it is better for it to look as much as
+ possible like a single-step to wait_for_inferior). */
+
+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() */
+
+ /* Used by wait_for_inferior for stepping over subroutine calls, for
+ 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
+ have no way of cleaning up the breakpoint in these (obscure) situations.
+ (Probably can solve this by noticing longjmp, "return", etc., it's
+ similar to noticing when a watchpoint on a local variable goes out
+ of scope (with hardware support for watchpoints)). */
+ bp_call_dummy,
+
+ /* Some dynamic linkers (HP, maybe Solaris) can arrange for special
+ code in the inferior to run when significant events occur in the
+ dynamic linker (for example a library is loaded or unloaded).
+
+ By placing a breakpoint in this magic code GDB will get control
+ when these significant events occur. GDB can then re-examine
+ the dynamic linker's data structures to discover any newly loaded
+ dynamic libraries. */
+ bp_shlib_event
+};
+
+/* States of enablement of breakpoint. */
+
+enum enable { disabled, enabled, shlib_disabled};
+
+/* Disposition of breakpoint. Ie: what to do after hitting it. */
+
+enum bpdisp {
+ del, /* Delete it */
+ disable, /* Disable it */
+ donttouch /* Leave it alone */
+};
+
+/* Note that the ->silent field is not currently used by any commands
+ (though the code is in there if it was to be, and set_raw_breakpoint
+ does set it to 0). I implemented it because I thought it would be
+ useful for a hack I had to put in; I'm going to leave it in because
+ I can see how there might be times when it would indeed be useful */
+
+/* This is for a breakpoint or a watchpoint. */
+
+struct breakpoint
+{
+ struct breakpoint *next;
+ /* Type of breakpoint. */
+ enum bptype type;
+ /* Zero means disabled; remember the info but don't break here. */
+ enum enable enable;
+ /* What to do with this breakpoint after we hit it. */
+ enum bpdisp disposition;
+ /* Number assigned to distinguish breakpoints. */
+ int number;
+
+ /* Address to break at, or NULL if not a breakpoint. */
+ CORE_ADDR address;
+
+ /* Line number of this address. Only matters if address is
+ non-NULL. */
+
+ int line_number;
+
+ /* Source file name of this address. Only matters if address is
+ non-NULL. */
+
+ char *source_file;
+
+ /* Non-zero means a silent breakpoint (don't print frame info
+ if we stop here). */
+ unsigned char silent;
+ /* Number of stops at this breakpoint that should
+ be continued automatically before really stopping. */
+ int ignore_count;
+ /* "Real" contents of byte where breakpoint has been inserted.
+ Valid only when breakpoints are in the program. Under the complete
+ control of the target insert_breakpoint and remove_breakpoint routines.
+ No other code should assume anything about the value(s) here. */
+ char shadow_contents[BREAKPOINT_MAX];
+ /* Nonzero if this breakpoint is now inserted. Only matters if address
+ is non-NULL. */
+ char inserted;
+ /* Nonzero if this is not the first breakpoint in the list
+ for the given address. Only matters if address is non-NULL. */
+ char duplicate;
+ /* Chain of command lines to execute when this breakpoint is hit. */
+ struct command_line *commands;
+ /* Stack depth (address of frame). If nonzero, break only if fp
+ equals this. */
+ CORE_ADDR frame;
+ /* Conditional. Break only if this expression's value is nonzero. */
+ struct expression *cond;
+
+ /* String we used to set the breakpoint (malloc'd). Only matters if
+ address is non-NULL. */
+ char *addr_string;
+ /* Language we used to set the breakpoint. */
+ enum language language;
+ /* Input radix we used to set the breakpoint. */
+ int input_radix;
+ /* String form of the breakpoint condition (malloc'd), or NULL if there
+ is no condition. */
+ char *cond_string;
+ /* String form of exp (malloc'd), or NULL if none. */
+ char *exp_string;
+
+ /* The expression we are watching, or NULL if not a watchpoint. */
+ struct expression *exp;
+ /* The largest block within which it is valid, or NULL if it is
+ 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_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. */
+ CORE_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").
+ This provides the ability to determine whether we have stopped at a
+ breakpoint, and what we should do about it. */
+
+typedef struct bpstats *bpstat;
+
+/* Interface: */
+/* Clear a bpstat so that it says we are not at any breakpoint.
+ Also free any storage that is part of a bpstat. */
+extern void bpstat_clear PARAMS ((bpstat *));
+
+/* Return a copy of a bpstat. Like "bs1 = bs2" but all storage that
+ is part of the bpstat is copied as well. */
+extern bpstat bpstat_copy PARAMS ((bpstat));
+
+extern bpstat bpstat_stop_status PARAMS ((CORE_ADDR *, int));
+
+/* This bpstat_what stuff tells wait_for_inferior what to do with a
+ breakpoint (a challenging task). */
+
+enum bpstat_what_main_action {
+ /* Perform various other tests; that is, this bpstat does not
+ say to perform any action (e.g. failed watchpoint and nothing
+ else). */
+ BPSTAT_WHAT_KEEP_CHECKING,
+
+ /* Rather than distinguish between noisy and silent stops here, it
+ might be cleaner to have bpstat_print make that decision (also
+ taking into account stop_print_frame and source_only). But the
+ implications are a bit scary (interaction with auto-displays, etc.),
+ so I won't try it. */
+
+ /* Stop silently. */
+ BPSTAT_WHAT_STOP_SILENT,
+
+ /* Stop and print. */
+ BPSTAT_WHAT_STOP_NOISY,
+
+ /* Remove breakpoints, single step once, then put them back in and
+ go back to what we were doing. It's possible that this should be
+ removed from the main_action and put into a separate field, to more
+ cleanly handle BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE. */
+ BPSTAT_WHAT_SINGLE,
+
+ /* Set longjmp_resume breakpoint, remove all other breakpoints,
+ and continue. The "remove all other breakpoints" part is required
+ if we are also stepping over another breakpoint as well as doing
+ the longjmp handling. */
+ BPSTAT_WHAT_SET_LONGJMP_RESUME,
+
+ /* Clear longjmp_resume breakpoint, then handle as
+ BPSTAT_WHAT_KEEP_CHECKING. */
+ BPSTAT_WHAT_CLEAR_LONGJMP_RESUME,
+
+ /* 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,
+
+ /* Check the dynamic linker's data structures for new libraries, then
+ keep checking. */
+ BPSTAT_WHAT_CHECK_SHLIBS,
+
+ /* This is just used to keep track of how many enums there are. */
+ BPSTAT_WHAT_LAST
+};
+
+struct bpstat_what {
+ enum bpstat_what_main_action main_action;
+
+ /* 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
+ useful one). */
+ int call_dummy;
+};
+
+/* Tell what to do about this bpstat. */
+struct bpstat_what bpstat_what PARAMS ((bpstat));
+
+/* Find the bpstat associated with a breakpoint. NULL otherwise. */
+bpstat bpstat_find_breakpoint PARAMS ((bpstat, struct breakpoint *));
+
+/* Nonzero if a signal that we got in wait() was due to circumstances
+ explained by the BS. */
+/* Currently that is true if we have hit a breakpoint, or if there is
+ a watchpoint enabled. */
+#define bpstat_explains_signal(bs) ((bs) != NULL)
+
+/* Nonzero if we should step constantly (e.g. watchpoints on machines
+ without hardware support). This isn't related to a specific bpstat,
+ just to things like whether watchpoints are set. */
+extern int bpstat_should_step PARAMS ((void));
+
+/* Print a message indicating what happened. Returns nonzero to
+ say that only the source line should be printed after this (zero
+ return means print the frame as well as the source line). */
+extern int bpstat_print PARAMS ((bpstat));
+
+/* Return the breakpoint number of the first breakpoint we are stopped
+ at. *BSP upon return is a bpstat which points to the remaining
+ breakpoints stopped at (but which is not guaranteed to be good for
+ anything but further calls to bpstat_num).
+ Return 0 if passed a bpstat which does not indicate any breakpoints. */
+extern int bpstat_num PARAMS ((bpstat *));
+
+/* Perform actions associated with having stopped at *BSP. Actually, we just
+ use this for breakpoint commands. Perhaps other actions will go here
+ later, but this is executed at a late time (from the command loop). */
+extern void bpstat_do_actions PARAMS ((bpstat *));
+
+/* Modify BS so that the actions will not be performed. */
+extern void bpstat_clear_actions PARAMS ((bpstat));
+
+/* Implementation: */
+struct bpstats
+{
+ /* Linked list because there can be two breakpoints at the
+ same place, and a bpstat reflects the fact that both have been hit. */
+ bpstat next;
+ /* Breakpoint that we are at. */
+ struct breakpoint *breakpoint_at;
+ /* Commands left to be done. */
+ struct command_line *commands;
+ /* Old value associated with a watchpoint. */
+ value_ptr old_val;
+
+ /* Nonzero if this breakpoint tells us to print the frame. */
+ char print;
+
+ /* Nonzero if this breakpoint tells us to stop. */
+ char stop;
+
+ /* Function called by bpstat_print to print stuff associated with
+ this element of the bpstat chain. Returns 0 or 1 just like
+ bpstat_print, or -1 if it can't deal with it. */
+ int (*print_it) PARAMS((bpstat bs));
+};
+
+/* Prototypes for breakpoint-related functions. */
+
+#ifdef __STDC__ /* Forward declarations for prototypes */
+struct frame_info;
+#endif
+
+extern int breakpoint_here_p PARAMS ((CORE_ADDR));
+
+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));
+
+extern void breakpoint_re_set PARAMS ((void));
+
+extern void clear_momentary_breakpoints PARAMS ((void));
+
+extern struct breakpoint *set_momentary_breakpoint
+ PARAMS ((struct symtab_and_line, struct frame_info *, enum bptype));
+
+extern void set_ignore_count PARAMS ((int, int, int));
+
+extern void set_default_breakpoint PARAMS ((int, CORE_ADDR, struct symtab *, int));
+
+extern void mark_breakpoints_out PARAMS ((void));
+
+extern void breakpoint_init_inferior PARAMS ((void));
+
+extern void delete_breakpoint PARAMS ((struct breakpoint *));
+
+extern void breakpoint_auto_delete PARAMS ((bpstat));
+
+extern void breakpoint_clear_ignore_counts PARAMS ((void));
+
+extern void break_command PARAMS ((char *, int));
+
+extern int insert_breakpoints PARAMS ((void));
+
+extern int remove_breakpoints PARAMS ((void));
+
+extern void enable_longjmp_breakpoint PARAMS ((void));
+
+extern void disable_longjmp_breakpoint PARAMS ((void));
+
+extern void set_longjmp_resume_breakpoint PARAMS ((CORE_ADDR,
+ struct frame_info *));
+
+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. */
+
+extern void disable_current_display PARAMS ((void));
+
+extern void do_displays PARAMS ((void));
+
+extern void disable_display PARAMS ((int));
+
+extern void clear_displays PARAMS ((void));
+
+extern void disable_breakpoint PARAMS ((struct breakpoint *));
+
+extern void enable_breakpoint PARAMS ((struct breakpoint *));
+
+extern void create_solib_event_breakpoint PARAMS ((CORE_ADDR));
+
+extern void remove_solib_event_breakpoints PARAMS ((void));
+
+extern void re_enable_breakpoints_in_shlibs PARAMS ((void));
+
+#endif /* !defined (BREAKPOINT_H) */
diff --git a/contrib/gdb/gdb/buildsym.c b/contrib/gdb/gdb/buildsym.c
new file mode 100644
index 0000000..5a5847a
--- /dev/null
+++ b/contrib/gdb/gdb/buildsym.c
@@ -0,0 +1,1039 @@
+/* Support routines for building symbol tables in GDB's internal format.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module provides subroutines used for creating and adding to
+ the symbol table. These routines are called from various symbol-
+ file-reading routines.
+
+ Routines to support specific debugging information formats (stabs,
+ DWARF, etc) belong somewhere else. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "symfile.h" /* Needed for "struct complaint" */
+#include "objfiles.h"
+#include "gdbtypes.h"
+#include "complaints.h"
+#include "gdb_string.h"
+
+/* Ask buildsym.h to define the vars it normally declares `extern'. */
+#define EXTERN /**/
+#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 *));
+
+static struct blockvector *
+make_blockvector PARAMS ((struct objfile *));
+
+
+/* Initial sizes of data structures. These are realloc'd larger if needed,
+ and realloc'd down to the size actually used, when completed. */
+
+#define INITIAL_CONTEXT_STACK_SIZE 10
+#define INITIAL_LINE_VECTOR_LENGTH 1000
+
+
+/* Complaints about the symbols we have encountered. */
+
+struct complaint innerblock_complaint =
+ {"inner block not inside outer block in %s", 0, 0};
+
+struct complaint innerblock_anon_complaint =
+ {"inner block not inside outer block", 0, 0};
+
+struct complaint blockvector_complaint =
+ {"block at 0x%lx out of order", 0, 0};
+
+
+/* maintain the lists of symbols and blocks */
+
+/* Add a symbol to one of the lists of symbols. */
+
+void
+add_symbol_to_list (symbol, listhead)
+ struct symbol *symbol;
+ struct pending **listhead;
+{
+ register struct pending *link;
+
+ /* We keep PENDINGSIZE symbols in each link of the list.
+ If we don't have a link with room in it, add a new link. */
+ if (*listhead == NULL || (*listhead)->nsyms == PENDINGSIZE)
+ {
+ if (free_pendings)
+ {
+ link = free_pendings;
+ free_pendings = link->next;
+ }
+ else
+ {
+ link = (struct pending *) xmalloc (sizeof (struct pending));
+ }
+
+ link->next = *listhead;
+ *listhead = link;
+ link->nsyms = 0;
+ }
+
+ (*listhead)->symbol[(*listhead)->nsyms++] = symbol;
+}
+
+/* Find a symbol named NAME on a LIST. NAME need not be '\0'-terminated;
+ LENGTH is the length of the name. */
+
+struct symbol *
+find_symbol_in_list (list, name, length)
+ struct pending *list;
+ char *name;
+ int length;
+{
+ int j;
+ char *pp;
+
+ while (list != NULL)
+ {
+ for (j = list->nsyms; --j >= 0; )
+ {
+ pp = SYMBOL_NAME (list->symbol[j]);
+ if (*pp == *name && strncmp (pp, name, length) == 0 &&
+ pp[length] == '\0')
+ {
+ return (list->symbol[j]);
+ }
+ }
+ list = list->next;
+ }
+ return (NULL);
+}
+
+/* At end of reading syms, or in case of quit,
+ really free as many `struct pending's as we can easily find. */
+
+/* ARGSUSED */
+void
+really_free_pendings (foo)
+ int foo;
+{
+ struct pending *next, *next1;
+#if 0
+ struct pending_block *bnext, *bnext1;
+#endif
+
+ for (next = free_pendings; next; next = next1)
+ {
+ next1 = next->next;
+ free ((PTR)next);
+ }
+ free_pendings = NULL;
+
+#if 0 /* Now we make the links in the symbol_obstack, so don't free them. */
+ for (bnext = pending_blocks; bnext; bnext = bnext1)
+ {
+ bnext1 = bnext->next;
+ free ((PTR)bnext);
+ }
+#endif
+ pending_blocks = NULL;
+
+ for (next = file_symbols; next != NULL; next = next1)
+ {
+ next1 = next->next;
+ free ((PTR)next);
+ }
+ file_symbols = NULL;
+
+ for (next = global_symbols; next != NULL; next = next1)
+ {
+ next1 = next->next;
+ free ((PTR)next);
+ }
+ global_symbols = NULL;
+}
+
+/* Take one of the lists of symbols and make a block from it.
+ Keep the order the symbols have in the list (reversed from the input file).
+ Put the block on the list of pending blocks. */
+
+void
+finish_block (symbol, listhead, old_blocks, start, end, objfile)
+ struct symbol *symbol;
+ struct pending **listhead;
+ struct pending_block *old_blocks;
+ CORE_ADDR start, end;
+ struct objfile *objfile;
+{
+ register struct pending *next, *next1;
+ register struct block *block;
+ register struct pending_block *pblock;
+ struct pending_block *opblock;
+ register int i;
+ register int j;
+
+ /* Count the length of the list of symbols. */
+
+ for (next = *listhead, i = 0;
+ next;
+ i += next->nsyms, next = next->next)
+ {
+ /*EMPTY*/;
+ }
+
+ block = (struct block *) obstack_alloc (&objfile -> symbol_obstack,
+ (sizeof (struct block) + ((i - 1) * sizeof (struct symbol *))));
+
+ /* Copy the symbols into the block. */
+
+ BLOCK_NSYMS (block) = i;
+ for (next = *listhead; next; next = next->next)
+ {
+ for (j = next->nsyms - 1; j >= 0; j--)
+ {
+ BLOCK_SYM (block, --i) = next->symbol[j];
+ }
+ }
+
+ BLOCK_START (block) = start;
+ BLOCK_END (block) = end;
+ /* Superblock filled in when containing block is made */
+ BLOCK_SUPERBLOCK (block) = NULL;
+ BLOCK_GCC_COMPILED (block) = processing_gcc_compilation;
+
+ /* Put the block in as the value of the symbol that names it. */
+
+ if (symbol)
+ {
+ struct type *ftype = SYMBOL_TYPE (symbol);
+ SYMBOL_BLOCK_VALUE (symbol) = block;
+ BLOCK_FUNCTION (block) = symbol;
+
+ if (TYPE_NFIELDS (ftype) <= 0)
+ {
+ /* No parameter type information is recorded with the function's
+ type. Set that from the type of the parameter symbols. */
+ int nparams = 0, iparams;
+ struct symbol *sym;
+ for (i = 0; i < BLOCK_NSYMS (block); i++)
+ {
+ sym = BLOCK_SYM (block, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ nparams++;
+ break;
+ case LOC_UNDEF:
+ case LOC_CONST:
+ case LOC_STATIC:
+ case LOC_REGISTER:
+ case LOC_LOCAL:
+ case LOC_TYPEDEF:
+ case LOC_LABEL:
+ case LOC_BLOCK:
+ case LOC_CONST_BYTES:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ case LOC_UNRESOLVED:
+ case LOC_OPTIMIZED_OUT:
+ default:
+ break;
+ }
+ }
+ if (nparams > 0)
+ {
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+
+ for (i = iparams = 0; iparams < nparams; i++)
+ {
+ sym = BLOCK_SYM (block, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
+ iparams++;
+ break;
+ case LOC_UNDEF:
+ case LOC_CONST:
+ case LOC_STATIC:
+ case LOC_REGISTER:
+ case LOC_LOCAL:
+ case LOC_TYPEDEF:
+ case LOC_LABEL:
+ case LOC_BLOCK:
+ case LOC_CONST_BYTES:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ case LOC_UNRESOLVED:
+ case LOC_OPTIMIZED_OUT:
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ BLOCK_FUNCTION (block) = NULL;
+ }
+
+ /* Now "free" the links of the list, and empty the list. */
+
+ for (next = *listhead; next; next = next1)
+ {
+ next1 = next->next;
+ next->next = free_pendings;
+ free_pendings = next;
+ }
+ *listhead = NULL;
+
+ /* Install this block as the superblock
+ of all blocks made since the start of this scope
+ that don't have superblocks yet. */
+
+ opblock = NULL;
+ for (pblock = pending_blocks; pblock != old_blocks; pblock = pblock->next)
+ {
+ if (BLOCK_SUPERBLOCK (pblock->block) == NULL)
+ {
+#if 1
+ /* Check to be sure the blocks are nested as we receive them.
+ If the compiler/assembler/linker work, this just burns a small
+ amount of time. */
+ if (BLOCK_START (pblock->block) < BLOCK_START (block) ||
+ BLOCK_END (pblock->block) > BLOCK_END (block))
+ {
+ if (symbol)
+ {
+ complain (&innerblock_complaint,
+ SYMBOL_SOURCE_NAME (symbol));
+ }
+ else
+ {
+ complain (&innerblock_anon_complaint);
+ }
+ BLOCK_START (pblock->block) = BLOCK_START (block);
+ BLOCK_END (pblock->block) = BLOCK_END (block);
+ }
+#endif
+ BLOCK_SUPERBLOCK (pblock->block) = block;
+ }
+ opblock = pblock;
+ }
+
+ /* Record this block on the list of all blocks in the file.
+ Put it after opblock, or at the beginning if opblock is 0.
+ This puts the block in the list after all its subblocks. */
+
+ /* Allocate in the symbol_obstack to save time.
+ It wastes a little space. */
+ pblock = (struct pending_block *)
+ obstack_alloc (&objfile -> symbol_obstack,
+ sizeof (struct pending_block));
+ pblock->block = block;
+ if (opblock)
+ {
+ pblock->next = opblock->next;
+ opblock->next = pblock;
+ }
+ else
+ {
+ pblock->next = pending_blocks;
+ pending_blocks = pblock;
+ }
+}
+
+static struct blockvector *
+make_blockvector (objfile)
+ struct objfile *objfile;
+{
+ register struct pending_block *next;
+ register struct blockvector *blockvector;
+ register int i;
+
+ /* Count the length of the list of blocks. */
+
+ for (next = pending_blocks, i = 0; next; next = next->next, i++) {;}
+
+ blockvector = (struct blockvector *)
+ obstack_alloc (&objfile -> symbol_obstack,
+ (sizeof (struct blockvector)
+ + (i - 1) * sizeof (struct block *)));
+
+ /* Copy the blocks into the blockvector.
+ This is done in reverse order, which happens to put
+ the blocks into the proper order (ascending starting address).
+ finish_block has hair to insert each block into the list
+ after its subblocks in order to make sure this is true. */
+
+ BLOCKVECTOR_NBLOCKS (blockvector) = i;
+ for (next = pending_blocks; next; next = next->next)
+ {
+ BLOCKVECTOR_BLOCK (blockvector, --i) = next->block;
+ }
+
+#if 0 /* Now we make the links in the obstack, so don't free them. */
+ /* Now free the links of the list, and empty the list. */
+
+ for (next = pending_blocks; next; next = next1)
+ {
+ next1 = next->next;
+ free (next);
+ }
+#endif
+ pending_blocks = NULL;
+
+#if 1 /* FIXME, shut this off after a while to speed up symbol reading. */
+ /* Some compilers output blocks in the wrong order, but we depend
+ on their being in the right order so we can binary search.
+ Check the order and moan about it. FIXME. */
+ if (BLOCKVECTOR_NBLOCKS (blockvector) > 1)
+ {
+ for (i = 1; i < BLOCKVECTOR_NBLOCKS (blockvector); i++)
+ {
+ 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)));
+ }
+ }
+ }
+#endif
+
+ return (blockvector);
+}
+
+
+/* Start recording information about source code that came from an included
+ (or otherwise merged-in) source file with a different name. NAME is
+ the name of the file (cannot be NULL), DIRNAME is the directory in which
+ it resides (or NULL if not known). */
+
+void
+start_subfile (name, dirname)
+ char *name;
+ char *dirname;
+{
+ register struct subfile *subfile;
+
+ /* See if this subfile is already known as a subfile of the
+ current main source file. */
+
+ for (subfile = subfiles; subfile; subfile = subfile->next)
+ {
+ if (STREQ (subfile->name, name))
+ {
+ current_subfile = subfile;
+ return;
+ }
+ }
+
+ /* This subfile is not known. Add an entry for it.
+ Make an entry for this subfile in the list of all subfiles
+ of the current main source file. */
+
+ subfile = (struct subfile *) xmalloc (sizeof (struct subfile));
+ subfile->next = subfiles;
+ subfiles = subfile;
+ current_subfile = subfile;
+
+ /* Save its name and compilation directory name */
+ 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;
+
+ /* Default the source language to whatever can be deduced from
+ the filename. If nothing can be deduced (such as for a C/C++
+ include file with a ".h" extension), then inherit whatever
+ language the previous subfile had. This kludgery is necessary
+ because there is no standard way in some object formats to
+ record the source language. Also, when symtabs are allocated
+ we try to deduce a language then as well, but it is too late
+ for us to use that information while reading symbols, since
+ symtabs aren't allocated until after all the symbols have
+ been processed for a given source file. */
+
+ subfile->language = deduce_language_from_filename (subfile->name);
+ if (subfile->language == language_unknown &&
+ subfile->next != NULL)
+ {
+ subfile->language = subfile->next->language;
+ }
+
+ /* cfront output is a C program, so in most ways it looks like a C
+ program. But to demangle we need to set the language to C++. We
+ can distinguish cfront code by the fact that it has #line
+ directives which specify a file name ending in .C.
+
+ So if the filename of this subfile ends in .C, then change the language
+ of any pending subfiles from C to C++. We also accept any other C++
+ suffixes accepted by deduce_language_from_filename (in particular,
+ some people use .cxx with cfront). */
+ /* Likewise for f2c. */
+
+ if (subfile->name)
+ {
+ struct subfile *s;
+ enum language sublang = deduce_language_from_filename (subfile->name);
+
+ if (sublang == language_cplus || sublang == language_fortran)
+ for (s = subfiles; s != NULL; s = s->next)
+ if (s->language == language_c)
+ s->language = sublang;
+ }
+
+ /* And patch up this file if necessary. */
+ if (subfile->language == language_c
+ && subfile->next != NULL
+ && (subfile->next->language == language_cplus
+ || subfile->next->language == language_fortran))
+ {
+ subfile->language = subfile->next->language;
+ }
+}
+
+/* For stabs readers, the first N_SO symbol is assumed to be the source
+ file name, and the subfile struct is initialized using that assumption.
+ If another N_SO symbol is later seen, immediately following the first
+ one, then the first one is assumed to be the directory name and the
+ second one is really the source file name.
+
+ So we have to patch up the subfile struct by moving the old name value to
+ dirname and remembering the new name. Some sanity checking is performed
+ to ensure that the state of the subfile struct is reasonable and that the
+ old name we are assuming to be a directory name actually is (by checking
+ for a trailing '/'). */
+
+void
+patch_subfile_names (subfile, name)
+ struct subfile *subfile;
+ char *name;
+{
+ if (subfile != NULL && subfile->dirname == NULL && subfile->name != NULL
+ && subfile->name[strlen(subfile->name)-1] == '/')
+ {
+ subfile->dirname = subfile->name;
+ subfile->name = savestring (name, strlen (name));
+ last_source_file = name;
+
+ /* Default the source language to whatever can be deduced from
+ the filename. If nothing can be deduced (such as for a C/C++
+ include file with a ".h" extension), then inherit whatever
+ language the previous subfile had. This kludgery is necessary
+ because there is no standard way in some object formats to
+ record the source language. Also, when symtabs are allocated
+ we try to deduce a language then as well, but it is too late
+ for us to use that information while reading symbols, since
+ symtabs aren't allocated until after all the symbols have
+ been processed for a given source file. */
+
+ subfile->language = deduce_language_from_filename (subfile->name);
+ if (subfile->language == language_unknown &&
+ subfile->next != NULL)
+ {
+ subfile->language = subfile->next->language;
+ }
+ }
+}
+
+
+/* Handle the N_BINCL and N_EINCL symbol types
+ that act like N_SOL for switching source files
+ (different subfiles, as we call them) within one object file,
+ but using a stack rather than in an arbitrary order. */
+
+void
+push_subfile ()
+{
+ register struct subfile_stack *tem
+ = (struct subfile_stack *) xmalloc (sizeof (struct subfile_stack));
+
+ tem->next = subfile_stack;
+ subfile_stack = tem;
+ if (current_subfile == NULL || current_subfile->name == NULL)
+ {
+ abort ();
+ }
+ tem->name = current_subfile->name;
+}
+
+char *
+pop_subfile ()
+{
+ register char *name;
+ register struct subfile_stack *link = subfile_stack;
+
+ if (link == NULL)
+ {
+ abort ();
+ }
+ name = link->name;
+ subfile_stack = link->next;
+ free ((PTR)link);
+ return (name);
+}
+
+
+/* Add a linetable entry for line number LINE and address PC to the line
+ vector for SUBFILE. */
+
+void
+record_line (subfile, line, pc)
+ register struct subfile *subfile;
+ int line;
+ CORE_ADDR pc;
+{
+ struct linetable_entry *e;
+ /* Ignore the dummy line number in libg.o */
+
+ if (line == 0xffff)
+ {
+ return;
+ }
+
+ /* Make sure line vector exists and is big enough. */
+ if (!subfile->line_vector)
+ {
+ subfile->line_vector_length = INITIAL_LINE_VECTOR_LENGTH;
+ subfile->line_vector = (struct linetable *)
+ xmalloc (sizeof (struct linetable)
+ + subfile->line_vector_length * sizeof (struct linetable_entry));
+ subfile->line_vector->nitems = 0;
+ }
+
+ if (subfile->line_vector->nitems + 1 >= subfile->line_vector_length)
+ {
+ subfile->line_vector_length *= 2;
+ subfile->line_vector = (struct linetable *)
+ xrealloc ((char *) subfile->line_vector, (sizeof (struct linetable)
+ + subfile->line_vector_length * sizeof (struct linetable_entry)));
+ }
+
+ e = subfile->line_vector->item + subfile->line_vector->nitems++;
+ e->line = line; e->pc = pc;
+}
+
+
+/* Needed in order to sort line tables from IBM xcoff files. Sigh! */
+
+static int
+compare_line_numbers (ln1p, ln2p)
+ const PTR ln1p;
+ const PTR ln2p;
+{
+ struct linetable_entry *ln1 = (struct linetable_entry *) ln1p;
+ struct linetable_entry *ln2 = (struct linetable_entry *) ln2p;
+
+ /* Note: this code does not assume that CORE_ADDRs can fit in ints.
+ Please keep it that way. */
+ if (ln1->pc < ln2->pc)
+ return -1;
+
+ if (ln1->pc > ln2->pc)
+ return 1;
+
+ /* If pc equal, sort by line. I'm not sure whether this is optimum
+ behavior (see comment at struct linetable in symtab.h). */
+ return ln1->line - ln2->line;
+}
+
+
+/* Start a new symtab for a new source file.
+ Called, for example, when a stabs symbol of type N_SO is seen, or when
+ a DWARF TAG_compile_unit DIE is seen.
+ It indicates the start of data for one original source file. */
+
+void
+start_symtab (name, dirname, start_addr)
+ char *name;
+ char *dirname;
+ CORE_ADDR start_addr;
+{
+
+ last_source_file = name;
+ last_source_start_addr = start_addr;
+ file_symbols = NULL;
+ global_symbols = NULL;
+ within_function = 0;
+
+ /* Context stack is initially empty. Allocate first one with room for
+ 10 levels; reuse it forever afterward. */
+ if (context_stack == NULL)
+ {
+ context_stack_size = INITIAL_CONTEXT_STACK_SIZE;
+ context_stack = (struct context_stack *)
+ xmalloc (context_stack_size * sizeof (struct context_stack));
+ }
+ context_stack_depth = 0;
+
+ /* Initialize the list of sub source files with one entry
+ for this file (the top-level source file). */
+
+ subfiles = NULL;
+ current_subfile = NULL;
+ start_subfile (name, dirname);
+}
+
+/* Finish the symbol definitions for one main source file,
+ close off all the lexical contexts for that file
+ (creating struct block's for them), then make the struct symtab
+ for that file and put it in the list of all such.
+
+ END_ADDR is the address of the end of the file's text.
+ SECTION is the section number (in objfile->section_offsets) of
+ the blockvector and linetable.
+
+ Note that it is possible for end_symtab() to return NULL. In particular,
+ for the DWARF case at least, it will return NULL when it finds a
+ compilation unit that has exactly one DIE, a TAG_compile_unit DIE. This
+ can happen when we link in an object file that was compiled from an empty
+ source file. Returning NULL is probably not the correct thing to do,
+ because then gdb will never know about this empty file (FIXME). */
+
+struct symtab *
+end_symtab (end_addr, objfile, section)
+ CORE_ADDR end_addr;
+ struct objfile *objfile;
+ int section;
+{
+ register struct symtab *symtab = NULL;
+ register struct blockvector *blockvector;
+ register struct subfile *subfile;
+ register struct context_stack *cstk;
+ struct subfile *nextsub;
+
+ /* Finish the lexical context of the last function in the file;
+ pop the context stack. */
+
+ if (context_stack_depth > 0)
+ {
+ context_stack_depth--;
+ cstk = &context_stack[context_stack_depth];
+ /* Make a block for the local symbols within. */
+ finish_block (cstk->name, &local_symbols, cstk->old_blocks,
+ cstk->start_addr, end_addr, objfile);
+
+ if (context_stack_depth > 0)
+ {
+ /* This is said to happen with SCO. The old coffread.c code
+ simply emptied the context stack, so we do the same. FIXME:
+ Find out why it is happening. This is not believed to happen
+ in most cases (even for coffread.c); it used to be an abort(). */
+ static struct complaint msg =
+ {"Context stack not empty in end_symtab", 0, 0};
+ complain (&msg);
+ context_stack_depth = 0;
+ }
+ }
+
+ /* Reordered executables may have out of order pending blocks; if
+ OBJF_REORDERED is true, then sort the pending blocks. */
+ if ((objfile->flags & OBJF_REORDERED) && pending_blocks)
+ {
+ /* FIXME! Remove this horrid bubble sort and use qsort!!!
+ It'd be a whole lot easier if they weren't in a linked list!!! */
+ int swapped;
+ do
+ {
+ struct pending_block *pb, *pbnext;
+
+ pb = pending_blocks;
+ pbnext = pb->next;
+ swapped = 0;
+
+ while (pbnext)
+ {
+ /* swap blocks if unordered! */
+
+ if (BLOCK_START(pb->block) < BLOCK_START(pbnext->block))
+ {
+ struct block *tmp = pb->block;
+ pb->block = pbnext->block;
+ pbnext->block = tmp;
+ swapped = 1;
+ }
+ pb = pbnext;
+ pbnext = pbnext->next;
+ }
+ } while (swapped);
+ }
+
+ /* Cleanup any undefined types that have been left hanging around
+ (this needs to be done before the finish_blocks so that
+ file_symbols is still good).
+
+ Both cleanup_undefined_types and finish_global_stabs are stabs
+ specific, but harmless for other symbol readers, since on gdb
+ startup or when finished reading stabs, the state is set so these
+ are no-ops. FIXME: Is this handled right in case of QUIT? Can
+ we make this cleaner? */
+
+ cleanup_undefined_types ();
+ finish_global_stabs (objfile);
+
+ if (pending_blocks == NULL
+ && file_symbols == NULL
+ && global_symbols == NULL)
+ {
+ /* Ignore symtabs that have no functions with real debugging info */
+ blockvector = NULL;
+ }
+ else
+ {
+ /* Define the STATIC_BLOCK & GLOBAL_BLOCK, and build the blockvector. */
+ finish_block (0, &file_symbols, 0, last_source_start_addr, end_addr,
+ objfile);
+ finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr,
+ objfile);
+ blockvector = make_blockvector (objfile);
+ }
+
+#ifdef PROCESS_LINENUMBER_HOOK
+ PROCESS_LINENUMBER_HOOK (); /* Needed for xcoff. */
+#endif
+
+ /* Now create the symtab objects proper, one for each subfile. */
+ /* (The main file is the last one on the chain.) */
+
+ for (subfile = subfiles; subfile; subfile = nextsub)
+ {
+ int linetablesize = 0;
+ /* If we have blocks of symbols, make a symtab.
+ Otherwise, just ignore this file and any line number info in it. */
+ symtab = NULL;
+ if (blockvector)
+ {
+ if (subfile->line_vector)
+ {
+ linetablesize = sizeof (struct linetable) +
+ subfile->line_vector->nitems * sizeof (struct linetable_entry);
+#if 0
+ /* I think this is artifact from before it went on the obstack.
+ I doubt we'll need the memory between now and when we
+ free it later in this function. */
+ /* First, shrink the linetable to make more memory. */
+ subfile->line_vector = (struct linetable *)
+ xrealloc ((char *) subfile->line_vector, linetablesize);
+#endif
+
+ /* Like the pending blocks, the line table may be scrambled
+ in reordered executables. Sort it if OBJF_REORDERED is
+ true. */
+ if (objfile->flags & OBJF_REORDERED)
+ qsort (subfile->line_vector->item,
+ subfile->line_vector->nitems,
+ sizeof (struct linetable_entry), compare_line_numbers);
+ }
+
+ /* Now, allocate a symbol table. */
+ symtab = allocate_symtab (subfile->name, objfile);
+
+ /* Fill in its components. */
+ symtab->blockvector = blockvector;
+ if (subfile->line_vector)
+ {
+ /* Reallocate the line table on the symbol obstack */
+ symtab->linetable = (struct linetable *)
+ obstack_alloc (&objfile -> symbol_obstack, linetablesize);
+ memcpy (symtab->linetable, subfile->line_vector, linetablesize);
+ }
+ else
+ {
+ symtab->linetable = NULL;
+ }
+ symtab->block_line_section = section;
+ if (subfile->dirname)
+ {
+ /* Reallocate the dirname on the symbol obstack */
+ symtab->dirname = (char *)
+ obstack_alloc (&objfile -> symbol_obstack,
+ strlen (subfile -> dirname) + 1);
+ strcpy (symtab->dirname, subfile->dirname);
+ }
+ else
+ {
+ symtab->dirname = NULL;
+ }
+ symtab->free_code = free_linetable;
+ symtab->free_ptr = NULL;
+
+ /* Use whatever language we have been using for this subfile,
+ not the one that was deduced in allocate_symtab from the
+ filename. We already did our own deducing when we created
+ the subfile, and we may have altered our opinion of what
+ language it is from things we found in the symbols. */
+ symtab->language = subfile->language;
+
+ /* All symtabs for the main file and the subfiles share a
+ blockvector, so we need to clear primary for everything but
+ the main file. */
+
+ symtab->primary = 0;
+ }
+ if (subfile->name != NULL)
+ {
+ free ((PTR) subfile->name);
+ }
+ if (subfile->dirname != NULL)
+ {
+ free ((PTR) subfile->dirname);
+ }
+ if (subfile->line_vector != NULL)
+ {
+ free ((PTR) subfile->line_vector);
+ }
+
+ nextsub = subfile->next;
+ free ((PTR)subfile);
+ }
+
+ /* Set this for the main source file. */
+ if (symtab)
+ {
+ symtab->primary = 1;
+ }
+
+ last_source_file = NULL;
+ current_subfile = NULL;
+
+ return (symtab);
+}
+
+
+/* Push a context block. Args are an identifying nesting level (checkable
+ when you pop it), and the starting PC address of this context. */
+
+struct context_stack *
+push_context (desc, valu)
+ int desc;
+ CORE_ADDR valu;
+{
+ register struct context_stack *new;
+
+ if (context_stack_depth == context_stack_size)
+ {
+ context_stack_size *= 2;
+ context_stack = (struct context_stack *)
+ xrealloc ((char *) context_stack,
+ (context_stack_size * sizeof (struct context_stack)));
+ }
+
+ new = &context_stack[context_stack_depth++];
+ new->depth = desc;
+ new->locals = local_symbols;
+ new->old_blocks = pending_blocks;
+ new->start_addr = valu;
+ new->name = NULL;
+
+ local_symbols = NULL;
+
+ return (new);
+}
+
+
+/* Compute a small integer hash code for the given name. */
+
+int
+hashname (name)
+ char *name;
+{
+ register char *p = name;
+ register int total = p[0];
+ register int c;
+
+ c = p[1];
+ total += c << 2;
+ if (c)
+ {
+ c = p[2];
+ total += c << 4;
+ if (c)
+ {
+ total += p[3] << 6;
+ }
+ }
+
+ /* Ensure result is positive. */
+ if (total < 0)
+ {
+ total += (1000 << 6);
+ }
+ return (total % HASHSIZE);
+}
+
+
+/* Initialize anything that needs initializing when starting to read
+ a fresh piece of a symbol file, e.g. reading in the stuff corresponding
+ to a psymtab. */
+
+void
+buildsym_init ()
+{
+ free_pendings = NULL;
+ file_symbols = NULL;
+ global_symbols = NULL;
+ pending_blocks = NULL;
+}
+
+/* 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). */
+
+void
+buildsym_new_init ()
+{
+ buildsym_init ();
+}
+
+/* Initializer for this module */
+
+void
+_initialize_buildsym ()
+{
+}
diff --git a/contrib/gdb/gdb/buildsym.h b/contrib/gdb/gdb/buildsym.h
new file mode 100644
index 0000000..58529c7
--- /dev/null
+++ b/contrib/gdb/gdb/buildsym.h
@@ -0,0 +1,259 @@
+/* Build symbol tables in GDB's internal format.
+ Copyright (C) 1986-1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (BUILDSYM_H)
+#define BUILDSYM_H 1
+
+/* This module provides definitions used for creating and adding to
+ the symbol table. These routines are called from various symbol-
+ file-reading routines.
+
+ They originated in dbxread.c of gdb-4.2, and were split out to
+ make xcoffread.c more maintainable by sharing code.
+
+ Variables declared in this file can be defined by #define-ing
+ the name EXTERN to null. It is used to declare variables that
+ are normally extern, but which get defined in a single module
+ using this technique. */
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+#define HASHSIZE 127 /* Size of things hashed via hashname() */
+
+/* Name of source file whose symbol data we are now processing.
+ This comes from a symbol of type N_SO. */
+
+EXTERN char *last_source_file;
+
+/* Core address of start of text of current source file.
+ This too comes from the N_SO symbol. */
+
+EXTERN CORE_ADDR last_source_start_addr;
+
+/* The list of sub-source-files within the current individual compilation.
+ Each file gets its own symtab with its own linetable and associated info,
+ but they all share one blockvector. */
+
+struct subfile
+{
+ struct subfile *next;
+ char *name;
+ char *dirname;
+ struct linetable *line_vector;
+ int line_vector_length;
+ enum language language;
+};
+
+EXTERN struct subfile *subfiles;
+
+EXTERN struct subfile *current_subfile;
+
+/* Global variable which, when set, indicates that we are processing a
+ .o file compiled with gcc */
+
+EXTERN unsigned char processing_gcc_compilation;
+
+/* When set, we are processing a .o file compiled by sun acc. This is
+ misnamed; it refers to all stabs-in-elf implementations which use
+ N_UNDF the way Sun does, including Solaris gcc. Hopefully all
+ stabs-in-elf implementations ever invented will choose to be
+ compatible. */
+
+EXTERN unsigned char processing_acc_compilation;
+
+/* Count symbols as they are processed, for error messages. */
+
+EXTERN unsigned int symnum;
+
+/* Record the symbols defined for each context in a list.
+ We don't create a struct block for the context until we
+ know how long to make it. */
+
+#define PENDINGSIZE 100
+
+struct pending
+{
+ struct pending *next;
+ int nsyms;
+ struct symbol *symbol[PENDINGSIZE];
+};
+
+/* List of free `struct pending' structures for reuse. */
+
+EXTERN struct pending *free_pendings;
+
+/* Here are the three lists that symbols are put on. */
+
+EXTERN struct pending *file_symbols; /* static at top level, and types */
+
+EXTERN struct pending *global_symbols; /* global functions and variables */
+
+EXTERN struct pending *local_symbols; /* everything local to lexic context */
+
+/* Stack representing unclosed lexical contexts
+ (that will become blocks, eventually). */
+
+struct context_stack
+{
+ /* Outer locals at the time we entered */
+
+ struct pending *locals;
+
+ /* Pointer into blocklist as of entry */
+
+ struct pending_block *old_blocks;
+
+ /* Name of function, if any, defining context*/
+
+ struct symbol *name;
+
+ /* PC where this context starts */
+
+ CORE_ADDR start_addr;
+
+ /* Temp slot for exception handling. */
+
+ CORE_ADDR end_addr;
+
+ /* For error-checking matching push/pop */
+
+ int depth;
+
+};
+
+EXTERN struct context_stack *context_stack;
+
+/* Index of first unused entry in context stack. */
+
+EXTERN int context_stack_depth;
+
+/* Currently allocated size of context stack. */
+
+EXTERN int context_stack_size;
+
+/* Macro "function" for popping contexts from the stack. Pushing is done
+ by a real function, push_context. This returns a pointer to a struct
+ context_stack. */
+
+#define pop_context() (&context_stack[--context_stack_depth]);
+
+/* Nonzero if within a function (so symbols should be local,
+ if nothing says specifically). */
+
+EXTERN int within_function;
+
+/* List of blocks already made (lexical contexts already closed).
+ This is used at the end to make the blockvector. */
+
+struct pending_block
+{
+ struct pending_block *next;
+ struct block *block;
+};
+
+EXTERN struct pending_block *pending_blocks;
+
+
+struct subfile_stack
+{
+ struct subfile_stack *next;
+ char *name;
+};
+
+EXTERN struct subfile_stack *subfile_stack;
+
+#define next_symbol_text(objfile) (*next_symbol_text_func)(objfile)
+
+/* Function to invoke get the next symbol. Return the symbol name. */
+
+EXTERN char *(*next_symbol_text_func) PARAMS ((struct objfile *));
+
+/* Vector of types defined so far, indexed by their type numbers.
+ Used for both stabs and coff.
+ (In newer sun systems, dbx uses a pair of numbers in parens,
+ as in "(SUBFILENUM,NUMWITHINSUBFILE)". Then these numbers must be
+ translated through the type_translations hash table to get
+ the index into the type vector.) */
+
+EXTERN struct type **type_vector;
+
+/* Number of elements allocated for type_vector currently. */
+
+EXTERN int type_vector_length;
+
+/* Initial size of type vector. Is realloc'd larger if needed,
+ and realloc'd down to the size actually used, when completed. */
+
+#define INITIAL_TYPE_VECTOR_LENGTH 160
+
+extern void
+add_symbol_to_list PARAMS ((struct symbol *, struct pending **));
+
+extern struct symbol *
+find_symbol_in_list PARAMS ((struct pending *, char *, int));
+
+extern void
+finish_block PARAMS ((struct symbol *, struct pending **,
+ struct pending_block *, CORE_ADDR, CORE_ADDR,
+ struct objfile *));
+
+extern void
+really_free_pendings PARAMS ((int foo));
+
+extern void
+start_subfile PARAMS ((char *, char *));
+
+extern void
+patch_subfile_names PARAMS ((struct subfile *subfile, char *name));
+
+extern void
+push_subfile PARAMS ((void));
+
+extern char *
+pop_subfile PARAMS ((void));
+
+extern struct symtab *
+end_symtab PARAMS ((CORE_ADDR, struct objfile *, int));
+
+extern void
+scan_file_globals PARAMS ((struct objfile *));
+
+extern void
+buildsym_new_init PARAMS ((void));
+
+extern void
+buildsym_init PARAMS ((void));
+
+extern struct context_stack *
+push_context PARAMS ((int, CORE_ADDR));
+
+extern void
+record_line PARAMS ((struct subfile *, int, CORE_ADDR));
+
+extern void
+start_symtab PARAMS ((char *, char *, CORE_ADDR));
+
+extern int
+hashname PARAMS ((char *));
+
+#undef EXTERN
+
+#endif /* defined (BUILDSYM_H) */
diff --git a/contrib/gdb/gdb/c-exp.tab.c b/contrib/gdb/gdb/c-exp.tab.c
new file mode 100644
index 0000000..0c6249b
--- /dev/null
+++ b/contrib/gdb/gdb/c-exp.tab.c
@@ -0,0 +1,2705 @@
+
+/* A Bison parser, made from ./c-exp.y with Bison version GNU Bison version 1.24
+ */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define INT 258
+#define FLOAT 259
+#define STRING 260
+#define NAME 261
+#define TYPENAME 262
+#define NAME_OR_INT 263
+#define STRUCT 264
+#define CLASS 265
+#define UNION 266
+#define ENUM 267
+#define SIZEOF 268
+#define UNSIGNED 269
+#define COLONCOLON 270
+#define TEMPLATE 271
+#define ERROR 272
+#define SIGNED_KEYWORD 273
+#define LONG 274
+#define SHORT 275
+#define INT_KEYWORD 276
+#define CONST_KEYWORD 277
+#define VOLATILE_KEYWORD 278
+#define DOUBLE_KEYWORD 279
+#define VARIABLE 280
+#define ASSIGN_MODIFY 281
+#define THIS 282
+#define ABOVE_COMMA 283
+#define OROR 284
+#define ANDAND 285
+#define EQUAL 286
+#define NOTEQUAL 287
+#define LEQ 288
+#define GEQ 289
+#define LSH 290
+#define RSH 291
+#define UNARY 292
+#define INCREMENT 293
+#define DECREMENT 294
+#define ARROW 295
+#define BLOCKNAME 296
+
+#line 38 "./c-exp.y"
+
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "c-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth c_maxdepth
+#define yyparse c_parse
+#define yylex c_lex
+#define yyerror c_error
+#define yylval c_lval
+#define yychar c_char
+#define yydebug c_debug
+#define yypact c_pact
+#define yyr1 c_r1
+#define yyr2 c_r2
+#define yydef c_def
+#define yychk c_chk
+#define yypgo c_pgo
+#define yyact c_act
+#define yyexca c_exca
+#define yyerrflag c_errflag
+#define yynerrs c_nerrs
+#define yyps c_ps
+#define yypv c_pv
+#define yys c_s
+#define yy_yys c_yys
+#define yystate c_state
+#define yytmp c_tmp
+#define yyv c_v
+#define yy_yyv c_yyv
+#define yyval c_val
+#define yylloc c_lloc
+#define yyreds c_reds /* With YYDEBUG defined */
+#define yytoks c_toks /* With YYDEBUG defined */
+#define yylhs c_yylhs
+#define yylen c_yylen
+#define yydefred c_yydefred
+#define yydgoto c_yydgoto
+#define yysindex c_yysindex
+#define yyrindex c_yyrindex
+#define yygindex c_yygindex
+#define yytable c_yytable
+#define yycheck c_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+
+#line 117 "./c-exp.y"
+typedef union
+ {
+ LONGEST lval;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val_int;
+ struct {
+ DOUBLEST dval;
+ struct type *type;
+ } typed_val_float;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ } YYSTYPE;
+#line 142 "./c-exp.y"
+
+/* YYSTYPE gets defined by %union */
+static int
+parse_number PARAMS ((char *, int, int, YYSTYPE *));
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 211
+#define YYFLAG -32768
+#define YYNTBASE 66
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 296 ? yytranslate[x] : 88)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 59, 2, 2, 2, 50, 36, 2, 57,
+ 62, 48, 46, 28, 47, 55, 49, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 65, 2, 39,
+ 30, 40, 31, 45, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 56, 2, 61, 35, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 63, 34, 64, 60, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 29, 32, 33, 37, 38, 41, 42, 43,
+ 44, 51, 52, 53, 54, 58
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 2, 4, 6, 8, 12, 15, 18, 21, 24,
+ 27, 30, 33, 36, 39, 42, 46, 50, 55, 59,
+ 63, 68, 73, 74, 80, 82, 83, 85, 89, 91,
+ 95, 100, 105, 109, 113, 117, 121, 125, 129, 133,
+ 137, 141, 145, 149, 153, 157, 161, 165, 169, 173,
+ 177, 181, 185, 191, 195, 199, 201, 203, 205, 207,
+ 209, 214, 216, 218, 220, 224, 228, 232, 237, 239,
+ 242, 244, 246, 249, 252, 255, 259, 263, 265, 268,
+ 270, 273, 275, 279, 282, 284, 287, 289, 292, 296,
+ 299, 303, 305, 309, 311, 313, 315, 317, 320, 324,
+ 327, 331, 335, 340, 343, 347, 349, 352, 355, 358,
+ 361, 364, 367, 369, 372, 374, 380, 383, 386, 388,
+ 390, 392, 394, 396, 400, 402, 404, 406, 408, 410
+};
+
+static const short yyrhs[] = { 68,
+ 0, 67, 0, 82, 0, 69, 0, 68, 28, 69,
+ 0, 48, 69, 0, 36, 69, 0, 47, 69, 0,
+ 59, 69, 0, 60, 69, 0, 52, 69, 0, 53,
+ 69, 0, 69, 52, 0, 69, 53, 0, 13, 69,
+ 0, 69, 54, 86, 0, 69, 54, 76, 0, 69,
+ 54, 48, 69, 0, 69, 55, 86, 0, 69, 55,
+ 76, 0, 69, 55, 48, 69, 0, 69, 56, 68,
+ 61, 0, 0, 69, 57, 70, 72, 62, 0, 63,
+ 0, 0, 69, 0, 72, 28, 69, 0, 64, 0,
+ 71, 72, 73, 0, 71, 82, 73, 69, 0, 57,
+ 82, 62, 69, 0, 57, 68, 62, 0, 69, 45,
+ 69, 0, 69, 48, 69, 0, 69, 49, 69, 0,
+ 69, 50, 69, 0, 69, 46, 69, 0, 69, 47,
+ 69, 0, 69, 43, 69, 0, 69, 44, 69, 0,
+ 69, 37, 69, 0, 69, 38, 69, 0, 69, 41,
+ 69, 0, 69, 42, 69, 0, 69, 39, 69, 0,
+ 69, 40, 69, 0, 69, 36, 69, 0, 69, 35,
+ 69, 0, 69, 34, 69, 0, 69, 33, 69, 0,
+ 69, 32, 69, 0, 69, 31, 69, 65, 69, 0,
+ 69, 30, 69, 0, 69, 26, 69, 0, 3, 0,
+ 8, 0, 4, 0, 75, 0, 25, 0, 13, 57,
+ 82, 62, 0, 5, 0, 27, 0, 58, 0, 74,
+ 15, 86, 0, 74, 15, 86, 0, 83, 15, 86,
+ 0, 83, 15, 60, 86, 0, 76, 0, 15, 86,
+ 0, 87, 0, 83, 0, 83, 22, 0, 83, 23,
+ 0, 83, 78, 0, 83, 22, 78, 0, 83, 23,
+ 78, 0, 48, 0, 48, 78, 0, 36, 0, 36,
+ 78, 0, 79, 0, 57, 78, 62, 0, 79, 80,
+ 0, 80, 0, 79, 81, 0, 81, 0, 56, 61,
+ 0, 56, 3, 61, 0, 57, 62, 0, 57, 85,
+ 62, 0, 77, 0, 83, 15, 48, 0, 7, 0,
+ 21, 0, 19, 0, 20, 0, 19, 21, 0, 14,
+ 19, 21, 0, 19, 19, 0, 19, 19, 21, 0,
+ 14, 19, 19, 0, 14, 19, 19, 21, 0, 20,
+ 21, 0, 14, 20, 21, 0, 24, 0, 19, 24,
+ 0, 9, 86, 0, 10, 86, 0, 11, 86, 0,
+ 12, 86, 0, 14, 84, 0, 14, 0, 18, 84,
+ 0, 18, 0, 16, 86, 39, 82, 40, 0, 22,
+ 83, 0, 23, 83, 0, 7, 0, 21, 0, 19,
+ 0, 20, 0, 82, 0, 85, 28, 82, 0, 6,
+ 0, 58, 0, 7, 0, 8, 0, 6, 0, 58,
+ 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 223, 224, 227, 234, 235, 240, 243, 246, 250, 254,
+ 258, 262, 266, 270, 274, 278, 284, 291, 295, 302,
+ 310, 314, 318, 322, 328, 332, 335, 339, 343, 346,
+ 353, 359, 365, 371, 375, 379, 383, 387, 391, 395,
+ 399, 403, 407, 411, 415, 419, 423, 427, 431, 435,
+ 439, 443, 447, 451, 455, 461, 468, 479, 486, 489,
+ 493, 501, 526, 533, 550, 561, 577, 590, 615, 616,
+ 650, 708, 714, 715, 716, 718, 720, 724, 726, 728,
+ 730, 732, 735, 737, 742, 749, 751, 755, 757, 761,
+ 763, 775, 776, 781, 783, 785, 787, 789, 791, 793,
+ 795, 797, 799, 801, 803, 805, 807, 809, 812, 815,
+ 818, 821, 823, 825, 827, 829, 836, 837, 840, 841,
+ 847, 853, 862, 867, 874, 875, 876, 877, 880, 881
+};
+
+static const char * const yytname[] = { "$","error","$undefined.","INT","FLOAT",
+"STRING","NAME","TYPENAME","NAME_OR_INT","STRUCT","CLASS","UNION","ENUM","SIZEOF",
+"UNSIGNED","COLONCOLON","TEMPLATE","ERROR","SIGNED_KEYWORD","LONG","SHORT","INT_KEYWORD",
+"CONST_KEYWORD","VOLATILE_KEYWORD","DOUBLE_KEYWORD","VARIABLE","ASSIGN_MODIFY",
+"THIS","','","ABOVE_COMMA","'='","'?'","OROR","ANDAND","'|'","'^'","'&'","EQUAL",
+"NOTEQUAL","'<'","'>'","LEQ","GEQ","LSH","RSH","'@'","'+'","'-'","'*'","'/'",
+"'%'","UNARY","INCREMENT","DECREMENT","ARROW","'.'","'['","'('","BLOCKNAME",
+"'!'","'~'","']'","')'","'{'","'}'","':'","start","type_exp","exp1","exp","@1",
+"lcurly","arglist","rcurly","block","variable","qualified_name","ptype","abs_decl",
+"direct_abs_decl","array_mod","func_mod","type","typebase","typename","nonempty_typelist",
+"name","name_not_typename",""
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 66, 66, 67, 68, 68, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 70, 69, 71, 72, 72, 72, 73, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 74, 74, 75, 76, 76, 75, 75,
+ 75, 77, 77, 77, 77, 77, 77, 78, 78, 78,
+ 78, 78, 79, 79, 79, 79, 79, 80, 80, 81,
+ 81, 82, 82, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 83, 83, 83, 83, 84, 84,
+ 84, 84, 85, 85, 86, 86, 86, 86, 87, 87
+};
+
+static const short yyr2[] = { 0,
+ 1, 1, 1, 1, 3, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 3, 3, 4, 3, 3,
+ 4, 4, 0, 5, 1, 0, 1, 3, 1, 3,
+ 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 5, 3, 3, 1, 1, 1, 1, 1,
+ 4, 1, 1, 1, 3, 3, 3, 4, 1, 2,
+ 1, 1, 2, 2, 2, 3, 3, 1, 2, 1,
+ 2, 1, 3, 2, 1, 2, 1, 2, 3, 2,
+ 3, 1, 3, 1, 1, 1, 1, 2, 3, 2,
+ 3, 3, 4, 2, 3, 1, 2, 2, 2, 2,
+ 2, 2, 1, 2, 1, 5, 2, 2, 1, 1,
+ 1, 1, 1, 3, 1, 1, 1, 1, 1, 1
+};
+
+static const short yydefact[] = { 0,
+ 56, 58, 62, 129, 94, 57, 0, 0, 0, 0,
+ 0, 113, 0, 0, 115, 96, 97, 95, 0, 0,
+ 106, 60, 63, 0, 0, 0, 0, 0, 0, 130,
+ 0, 0, 25, 2, 1, 4, 26, 0, 59, 69,
+ 92, 3, 72, 71, 125, 127, 128, 126, 108, 109,
+ 110, 111, 0, 15, 0, 119, 121, 122, 120, 112,
+ 70, 0, 121, 122, 114, 100, 98, 107, 104, 117,
+ 118, 7, 8, 6, 11, 12, 0, 0, 9, 10,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 14, 0, 0, 0, 23, 27,
+ 0, 0, 0, 0, 73, 74, 80, 78, 0, 0,
+ 75, 82, 85, 87, 0, 0, 102, 99, 105, 0,
+ 101, 33, 0, 5, 55, 54, 0, 52, 51, 50,
+ 49, 48, 42, 43, 46, 47, 44, 45, 40, 41,
+ 34, 38, 39, 35, 36, 37, 127, 0, 17, 16,
+ 0, 20, 19, 0, 26, 0, 29, 30, 0, 66,
+ 93, 0, 67, 76, 77, 81, 79, 0, 88, 90,
+ 0, 123, 72, 0, 0, 84, 86, 61, 103, 0,
+ 32, 0, 18, 21, 22, 0, 28, 31, 68, 89,
+ 83, 0, 0, 91, 116, 53, 24, 124, 0, 0,
+ 0
+};
+
+static const short yydefgoto[] = { 209,
+ 34, 77, 36, 165, 37, 111, 168, 38, 39, 40,
+ 41, 121, 122, 123, 124, 182, 55, 60, 184, 173,
+ 44
+};
+
+static const short yypact[] = { 241,
+-32768,-32768,-32768,-32768,-32768,-32768, 5, 5, 5, 5,
+ 302, 24, 5, 5, 73, 66, 27,-32768, 212, 212,
+-32768,-32768,-32768, 241, 241, 241, 241, 241, 241, 32,
+ 241, 241,-32768,-32768, -1, 523, 241, 42,-32768,-32768,
+-32768,-32768, 3,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+-32768,-32768, 241, 43, 52,-32768, 70, 50,-32768,-32768,
+-32768, 64,-32768,-32768,-32768, 60,-32768,-32768,-32768,-32768,
+-32768, 43, 43, 43, 43, 43, -7, 44, 43, 43,
+ 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
+ 241, 241, 241, 241, 241, 241, 241, 241, 241, 241,
+ 241, 241, 241,-32768,-32768, 439, 458, 241,-32768, 523,
+ -18, 41, 5, 8, 16, 16, 16, 16, 4, 382,
+-32768, -34,-32768,-32768, 45, 26, 83,-32768,-32768, 212,
+-32768,-32768, 241, 523, 523, 523, 487, 575, 599, 622,
+ 644, 665, 684, 684, 143, 143, 143, 143, 226, 226,
+ 69, 287, 287, 43, 43, 43, 94, 241,-32768,-32768,
+ 241,-32768,-32768, -11, 241, 241,-32768,-32768, 241, 95,
+-32768, 5,-32768,-32768,-32768,-32768,-32768, 67,-32768,-32768,
+ 49,-32768, 13, -4, 152,-32768,-32768, 363,-32768, 72,
+ 43, 241, 43, 43,-32768, 12, 523, 43,-32768,-32768,
+-32768, 65, 212,-32768,-32768, 550,-32768,-32768, 127, 129,
+-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768, 6, 51,-32768,-32768, 14, 53,-32768,-32768, -65,
+-32768, 40,-32768, 47, 55, 1, 0, 163,-32768, -5,
+-32768
+};
+
+
+#define YYLAST 741
+
+
+static const short yytable[] = { 43,
+ 42, 49, 50, 51, 52, 35, 178, 61, 62, 166,
+ 45, 46, 47, 45, 46, 47, 81, 114, 70, 71,
+ 81, 119, 185, 203, 115, 116, 81, 202, 43, 78,
+ 56, 45, 46, 47, 115, 116, 43, 112, 117, 166,
+ 159, 162, 57, 58, 59, 167, -64, 69, 117, 195,
+ 118, 117, 43, 125, 132, 171, 113, 204, 119, 120,
+ 118, 54, 48, 118, 179, 48, 126, 172, 119, 120,
+ 129, 119, 120, 207, 72, 73, 74, 75, 76, 56,
+ 131, 79, 80, 48, 66, 172, 67, 110, 127, 68,
+ 128, 63, 64, 59, 104, 105, 106, 107, 108, 109,
+ 160, 163, 130, 189, 167, 133, 188, 170, -94, -65,
+ 201, 205, 171, 164, 99, 100, 101, 102, 103, 183,
+ 104, 105, 106, 107, 108, 109, 210, 200, 211, 183,
+ 190, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
+ 153, 154, 155, 156, 174, 175, 176, 177, 5, 181,
+ 7, 8, 9, 10, 169, 12, 199, 14, 186, 15,
+ 16, 17, 18, 19, 20, 21, 187, 65, 196, 0,
+ 0, 0, 0, 191, 183, 96, 97, 98, 99, 100,
+ 101, 102, 103, 0, 104, 105, 106, 107, 108, 109,
+ 0, 0, 183, 208, 0, 0, 0, 0, 193, 0,
+ 0, 194, 0, 180, 0, 110, 197, 0, 5, 198,
+ 7, 8, 9, 10, 0, 12, 0, 14, 0, 15,
+ 16, 17, 18, 19, 20, 21, 0, 0, 191, 0,
+ 0, 0, 206, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 0, 15, 16,
+ 17, 18, 19, 20, 21, 22, 0, 23, 0, 0,
+ 98, 99, 100, 101, 102, 103, 24, 104, 105, 106,
+ 107, 108, 109, 0, 0, 0, 0, 25, 26, 0,
+ 0, 0, 27, 28, 0, 0, 0, 29, 30, 31,
+ 32, 0, 0, 33, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 0, 15,
+ 16, 17, 18, 19, 20, 21, 22, 0, 23, 0,
+ 0, 0, 0, 0, 101, 102, 103, 24, 104, 105,
+ 106, 107, 108, 109, 0, 0, 0, 0, 25, 26,
+ 0, 0, 0, 27, 28, 0, 0, 0, 53, 30,
+ 31, 32, 0, 0, 33, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 0,
+ 15, 16, 17, 18, 19, 20, 21, 22, 5, 23,
+ 7, 8, 9, 10, 0, 12, 0, 14, 0, 15,
+ 16, 17, 18, 19, 20, 21, 0, 0, 0, 0,
+ 0, 0, 0, 0, 27, 28, 0, 117, 0, 29,
+ 30, 31, 32, 0, 0, 33, 0, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 119, 120, 0,
+ 0, 0, 0, 180, 45, 157, 47, 7, 8, 9,
+ 10, 0, 12, 0, 14, 0, 15, 16, 17, 18,
+ 19, 20, 21, 45, 157, 47, 7, 8, 9, 10,
+ 0, 12, 0, 14, 0, 15, 16, 17, 18, 19,
+ 20, 21, 0, 0, 0, 0, 158, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 48, 0, 0, 0,
+ 0, 0, 0, 0, 0, 161, 0, 0, 0, 0,
+ 0, 0, 82, 0, 0, 48, 83, 84, 85, 86,
+ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
+ 97, 98, 99, 100, 101, 102, 103, 0, 104, 105,
+ 106, 107, 108, 109, 0, 0, 0, 0, 82, 0,
+ 0, 192, 83, 84, 85, 86, 87, 88, 89, 90,
+ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,
+ 101, 102, 103, 0, 104, 105, 106, 107, 108, 109,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
+ 0, 104, 105, 106, 107, 108, 109, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 0, 104, 105, 106, 107,
+ 108, 109, 87, 88, 89, 90, 91, 92, 93, 94,
+ 95, 96, 97, 98, 99, 100, 101, 102, 103, 0,
+ 104, 105, 106, 107, 108, 109, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+ 102, 103, 0, 104, 105, 106, 107, 108, 109, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 0, 104, 105, 106, 107, 108,
+ 109, 90, 91, 92, 93, 94, 95, 96, 97, 98,
+ 99, 100, 101, 102, 103, 0, 104, 105, 106, 107,
+ 108, 109, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 0, 104, 105, 106, 107, 108,
+ 109
+};
+
+static const short yycheck[] = { 0,
+ 0, 7, 8, 9, 10, 0, 3, 13, 14, 28,
+ 6, 7, 8, 6, 7, 8, 28, 15, 19, 20,
+ 28, 56, 57, 28, 22, 23, 28, 15, 29, 29,
+ 7, 6, 7, 8, 22, 23, 37, 37, 36, 28,
+ 106, 107, 19, 20, 21, 64, 15, 21, 36, 61,
+ 48, 36, 53, 53, 62, 48, 15, 62, 56, 57,
+ 48, 11, 58, 48, 61, 58, 15, 60, 56, 57,
+ 21, 56, 57, 62, 24, 25, 26, 27, 28, 7,
+ 21, 31, 32, 58, 19, 60, 21, 37, 19, 24,
+ 21, 19, 20, 21, 52, 53, 54, 55, 56, 57,
+ 106, 107, 39, 21, 64, 62, 62, 113, 15, 15,
+ 62, 40, 48, 108, 46, 47, 48, 49, 50, 120,
+ 52, 53, 54, 55, 56, 57, 0, 61, 0, 130,
+ 130, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
+ 100, 101, 102, 103, 115, 116, 117, 118, 7, 120,
+ 9, 10, 11, 12, 112, 14, 172, 16, 122, 18,
+ 19, 20, 21, 22, 23, 24, 122, 15, 165, -1,
+ -1, -1, -1, 133, 185, 43, 44, 45, 46, 47,
+ 48, 49, 50, -1, 52, 53, 54, 55, 56, 57,
+ -1, -1, 203, 203, -1, -1, -1, -1, 158, -1,
+ -1, 161, -1, 62, -1, 165, 166, -1, 7, 169,
+ 9, 10, 11, 12, -1, 14, -1, 16, -1, 18,
+ 19, 20, 21, 22, 23, 24, -1, -1, 188, -1,
+ -1, -1, 192, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, -1, 18, 19,
+ 20, 21, 22, 23, 24, 25, -1, 27, -1, -1,
+ 45, 46, 47, 48, 49, 50, 36, 52, 53, 54,
+ 55, 56, 57, -1, -1, -1, -1, 47, 48, -1,
+ -1, -1, 52, 53, -1, -1, -1, 57, 58, 59,
+ 60, -1, -1, 63, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 13, 14, 15, 16, -1, 18,
+ 19, 20, 21, 22, 23, 24, 25, -1, 27, -1,
+ -1, -1, -1, -1, 48, 49, 50, 36, 52, 53,
+ 54, 55, 56, 57, -1, -1, -1, -1, 47, 48,
+ -1, -1, -1, 52, 53, -1, -1, -1, 57, 58,
+ 59, 60, -1, -1, 63, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15, 16, -1,
+ 18, 19, 20, 21, 22, 23, 24, 25, 7, 27,
+ 9, 10, 11, 12, -1, 14, -1, 16, -1, 18,
+ 19, 20, 21, 22, 23, 24, -1, -1, -1, -1,
+ -1, -1, -1, -1, 52, 53, -1, 36, -1, 57,
+ 58, 59, 60, -1, -1, 63, -1, -1, -1, 48,
+ -1, -1, -1, -1, -1, -1, -1, 56, 57, -1,
+ -1, -1, -1, 62, 6, 7, 8, 9, 10, 11,
+ 12, -1, 14, -1, 16, -1, 18, 19, 20, 21,
+ 22, 23, 24, 6, 7, 8, 9, 10, 11, 12,
+ -1, 14, -1, 16, -1, 18, 19, 20, 21, 22,
+ 23, 24, -1, -1, -1, -1, 48, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 58, -1, -1, -1,
+ -1, -1, -1, -1, -1, 48, -1, -1, -1, -1,
+ -1, -1, 26, -1, -1, 58, 30, 31, 32, 33,
+ 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, -1, 52, 53,
+ 54, 55, 56, 57, -1, -1, -1, -1, 26, -1,
+ -1, 65, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, -1, 52, 53, 54, 55, 56, 57,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
+ -1, 52, 53, 54, 55, 56, 57, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, -1, 52, 53, 54, 55,
+ 56, 57, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, -1,
+ 52, 53, 54, 55, 56, 57, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, -1, 52, 53, 54, 55, 56, 57, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, -1, 52, 53, 54, 55, 56,
+ 57, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 50, -1, 52, 53, 54, 55,
+ 56, 57, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, 48, 49, 50, -1, 52, 53, 54, 55, 56,
+ 57
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/unsupported/share/bison.simple"
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 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
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#endif /* alloca not defined. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT return(0)
+#define YYABORT return(1)
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (from, to, count)
+ char *from;
+ char *to;
+ int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *from, char *to, int count)
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 192 "/usr/unsupported/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#else
+#define YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#endif
+
+int
+yyparse(YYPARSE_PARAM)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to xreallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to xreallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+ yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+ yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 3:
+#line 228 "./c-exp.y"
+{ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(yyvsp[0].tval);
+ write_exp_elt_opcode(OP_TYPE);;
+ break;}
+case 5:
+#line 236 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_COMMA); ;
+ break;}
+case 6:
+#line 241 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_IND); ;
+ break;}
+case 7:
+#line 244 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_ADDR); ;
+ break;}
+case 8:
+#line 247 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_NEG); ;
+ break;}
+case 9:
+#line 251 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); ;
+ break;}
+case 10:
+#line 255 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_COMPLEMENT); ;
+ break;}
+case 11:
+#line 259 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_PREINCREMENT); ;
+ break;}
+case 12:
+#line 263 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_PREDECREMENT); ;
+ break;}
+case 13:
+#line 267 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_POSTINCREMENT); ;
+ break;}
+case 14:
+#line 271 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_POSTDECREMENT); ;
+ break;}
+case 15:
+#line 275 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_SIZEOF); ;
+ break;}
+case 16:
+#line 279 "./c-exp.y"
+{ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (STRUCTOP_PTR); ;
+ break;}
+case 17:
+#line 285 "./c-exp.y"
+{ /* exp->type::name becomes exp->*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MPTR); ;
+ break;}
+case 18:
+#line 292 "./c-exp.y"
+{ write_exp_elt_opcode (STRUCTOP_MPTR); ;
+ break;}
+case 19:
+#line 296 "./c-exp.y"
+{ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); ;
+ break;}
+case 20:
+#line 303 "./c-exp.y"
+{ /* exp.type::name becomes exp.*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MEMBER); ;
+ break;}
+case 21:
+#line 311 "./c-exp.y"
+{ write_exp_elt_opcode (STRUCTOP_MEMBER); ;
+ break;}
+case 22:
+#line 315 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_SUBSCRIPT); ;
+ break;}
+case 23:
+#line 321 "./c-exp.y"
+{ start_arglist (); ;
+ break;}
+case 24:
+#line 323 "./c-exp.y"
+{ write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); ;
+ break;}
+case 25:
+#line 329 "./c-exp.y"
+{ start_arglist (); ;
+ break;}
+case 27:
+#line 336 "./c-exp.y"
+{ arglist_len = 1; ;
+ break;}
+case 28:
+#line 340 "./c-exp.y"
+{ arglist_len++; ;
+ break;}
+case 29:
+#line 344 "./c-exp.y"
+{ yyval.lval = end_arglist () - 1; ;
+ break;}
+case 30:
+#line 347 "./c-exp.y"
+{ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+ write_exp_elt_opcode (OP_ARRAY); ;
+ break;}
+case 31:
+#line 354 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_elt_type (yyvsp[-2].tval);
+ write_exp_elt_opcode (UNOP_MEMVAL); ;
+ break;}
+case 32:
+#line 360 "./c-exp.y"
+{ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (yyvsp[-2].tval);
+ write_exp_elt_opcode (UNOP_CAST); ;
+ break;}
+case 33:
+#line 366 "./c-exp.y"
+{ ;
+ break;}
+case 34:
+#line 372 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_REPEAT); ;
+ break;}
+case 35:
+#line 376 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_MUL); ;
+ break;}
+case 36:
+#line 380 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_DIV); ;
+ break;}
+case 37:
+#line 384 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_REM); ;
+ break;}
+case 38:
+#line 388 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_ADD); ;
+ break;}
+case 39:
+#line 392 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_SUB); ;
+ break;}
+case 40:
+#line 396 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_LSH); ;
+ break;}
+case 41:
+#line 400 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_RSH); ;
+ break;}
+case 42:
+#line 404 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_EQUAL); ;
+ break;}
+case 43:
+#line 408 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_NOTEQUAL); ;
+ break;}
+case 44:
+#line 412 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_LEQ); ;
+ break;}
+case 45:
+#line 416 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_GEQ); ;
+ break;}
+case 46:
+#line 420 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_LESS); ;
+ break;}
+case 47:
+#line 424 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_GTR); ;
+ break;}
+case 48:
+#line 428 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_AND); ;
+ break;}
+case 49:
+#line 432 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_XOR); ;
+ break;}
+case 50:
+#line 436 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_IOR); ;
+ break;}
+case 51:
+#line 440 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_AND); ;
+ break;}
+case 52:
+#line 444 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_OR); ;
+ break;}
+case 53:
+#line 448 "./c-exp.y"
+{ write_exp_elt_opcode (TERNOP_COND); ;
+ break;}
+case 54:
+#line 452 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN); ;
+ break;}
+case 55:
+#line 456 "./c-exp.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode (yyvsp[-1].opcode);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); ;
+ break;}
+case 56:
+#line 462 "./c-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (yyvsp[0].typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)(yyvsp[0].typed_val_int.val));
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 57:
+#line 469 "./c-exp.y"
+{ YYSTYPE val;
+ parse_number (yyvsp[0].ssym.stoken.ptr, yyvsp[0].ssym.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ ;
+ break;}
+case 58:
+#line 480 "./c-exp.y"
+{ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (yyvsp[0].typed_val_float.type);
+ write_exp_elt_dblcst (yyvsp[0].typed_val_float.dval);
+ write_exp_elt_opcode (OP_DOUBLE); ;
+ break;}
+case 61:
+#line 494 "./c-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ CHECK_TYPEDEF (yyvsp[-1].tval);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (yyvsp[-1].tval));
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 62:
+#line 502 "./c-exp.y"
+{ /* C strings are converted into array constants with
+ an explicit null byte added at the end. Thus
+ the array upper bound is the string length.
+ There is no such thing in C as a completely empty
+ string. */
+ char *sp = yyvsp[0].sval.ptr; int count = yyvsp[0].sval.length;
+ while (count-- > 0)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST)(*sp++));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST)'\0');
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) (yyvsp[0].sval.length));
+ write_exp_elt_opcode (OP_ARRAY); ;
+ break;}
+case 63:
+#line 527 "./c-exp.y"
+{ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS); ;
+ break;}
+case 64:
+#line 534 "./c-exp.y"
+{
+ if (yyvsp[0].ssym.sym != 0)
+ yyval.bval = SYMBOL_BLOCK_VALUE (yyvsp[0].ssym.sym);
+ else
+ {
+ struct symtab *tem =
+ lookup_symtab (copy_name (yyvsp[0].ssym.stoken));
+ if (tem)
+ yyval.bval = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), STATIC_BLOCK);
+ else
+ error ("No file or function \"%s\".",
+ copy_name (yyvsp[0].ssym.stoken));
+ }
+ ;
+ break;}
+case 65:
+#line 551 "./c-exp.y"
+{ struct symbol *tem
+ = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+ error ("No function \"%s\" in specified context.",
+ copy_name (yyvsp[0].sval));
+ yyval.bval = SYMBOL_BLOCK_VALUE (tem); ;
+ break;}
+case 66:
+#line 562 "./c-exp.y"
+{ struct symbol *sym;
+ sym = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name (yyvsp[0].sval));
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* block_found is set by lookup_symbol. */
+ write_exp_elt_block (block_found);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); ;
+ break;}
+case 67:
+#line 578 "./c-exp.y"
+{
+ struct type *type = yyvsp[-2].tval;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (OP_SCOPE);
+ ;
+ break;}
+case 68:
+#line 591 "./c-exp.y"
+{
+ struct type *type = yyvsp[-3].tval;
+ struct stoken tmp_token;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ if (!STREQ (type_name_no_tag (type), yyvsp[0].sval.ptr))
+ error ("invalid destructor `%s::~%s'",
+ type_name_no_tag (type), yyvsp[0].sval.ptr);
+
+ tmp_token.ptr = (char*) alloca (yyvsp[0].sval.length + 2);
+ tmp_token.length = yyvsp[0].sval.length + 1;
+ tmp_token.ptr[0] = '~';
+ memcpy (tmp_token.ptr+1, yyvsp[0].sval.ptr, yyvsp[0].sval.length);
+ tmp_token.ptr[tmp_token.length] = 0;
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string (tmp_token);
+ write_exp_elt_opcode (OP_SCOPE);
+ ;
+ break;}
+case 70:
+#line 617 "./c-exp.y"
+{
+ char *name = copy_name (yyvsp[0].sval);
+ struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
+ sym =
+ lookup_symbol (name, (const struct block *) NULL,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym)
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else
+ if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.", name);
+ ;
+ break;}
+case 71:
+#line 651 "./c-exp.y"
+{ struct symbol *sym = yyvsp[0].ssym.sym;
+
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else if (yyvsp[0].ssym.is_a_field_of_this)
+ {
+ /* C++: it hangs off of `this'. Must
+ not inadvertently convert from a method call
+ to data ref. */
+ if (innermost_block == 0 ||
+ contained_in (block_found, innermost_block))
+ innermost_block = block_found;
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string (yyvsp[0].ssym.stoken);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name (yyvsp[0].ssym.stoken);
+
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name (yyvsp[0].ssym.stoken));
+ }
+ ;
+ break;}
+case 75:
+#line 717 "./c-exp.y"
+{ yyval.tval = follow_types (yyvsp[-1].tval); ;
+ break;}
+case 76:
+#line 719 "./c-exp.y"
+{ yyval.tval = follow_types (yyvsp[-2].tval); ;
+ break;}
+case 77:
+#line 721 "./c-exp.y"
+{ yyval.tval = follow_types (yyvsp[-2].tval); ;
+ break;}
+case 78:
+#line 725 "./c-exp.y"
+{ push_type (tp_pointer); yyval.voidval = 0; ;
+ break;}
+case 79:
+#line 727 "./c-exp.y"
+{ push_type (tp_pointer); yyval.voidval = yyvsp[0].voidval; ;
+ break;}
+case 80:
+#line 729 "./c-exp.y"
+{ push_type (tp_reference); yyval.voidval = 0; ;
+ break;}
+case 81:
+#line 731 "./c-exp.y"
+{ push_type (tp_reference); yyval.voidval = yyvsp[0].voidval; ;
+ break;}
+case 83:
+#line 736 "./c-exp.y"
+{ yyval.voidval = yyvsp[-1].voidval; ;
+ break;}
+case 84:
+#line 738 "./c-exp.y"
+{
+ push_type_int (yyvsp[0].lval);
+ push_type (tp_array);
+ ;
+ break;}
+case 85:
+#line 743 "./c-exp.y"
+{
+ push_type_int (yyvsp[0].lval);
+ push_type (tp_array);
+ yyval.voidval = 0;
+ ;
+ break;}
+case 86:
+#line 750 "./c-exp.y"
+{ push_type (tp_function); ;
+ break;}
+case 87:
+#line 752 "./c-exp.y"
+{ push_type (tp_function); ;
+ break;}
+case 88:
+#line 756 "./c-exp.y"
+{ yyval.lval = -1; ;
+ break;}
+case 89:
+#line 758 "./c-exp.y"
+{ yyval.lval = yyvsp[-1].typed_val_int.val; ;
+ break;}
+case 90:
+#line 762 "./c-exp.y"
+{ yyval.voidval = 0; ;
+ break;}
+case 91:
+#line 764 "./c-exp.y"
+{ free ((PTR)yyvsp[-1].tvec); yyval.voidval = 0; ;
+ break;}
+case 93:
+#line 777 "./c-exp.y"
+{ yyval.tval = lookup_member_type (builtin_type_int, yyvsp[-2].tval); ;
+ break;}
+case 94:
+#line 782 "./c-exp.y"
+{ yyval.tval = yyvsp[0].tsym.type; ;
+ break;}
+case 95:
+#line 784 "./c-exp.y"
+{ yyval.tval = builtin_type_int; ;
+ break;}
+case 96:
+#line 786 "./c-exp.y"
+{ yyval.tval = builtin_type_long; ;
+ break;}
+case 97:
+#line 788 "./c-exp.y"
+{ yyval.tval = builtin_type_short; ;
+ break;}
+case 98:
+#line 790 "./c-exp.y"
+{ yyval.tval = builtin_type_long; ;
+ break;}
+case 99:
+#line 792 "./c-exp.y"
+{ yyval.tval = builtin_type_unsigned_long; ;
+ break;}
+case 100:
+#line 794 "./c-exp.y"
+{ yyval.tval = builtin_type_long_long; ;
+ break;}
+case 101:
+#line 796 "./c-exp.y"
+{ yyval.tval = builtin_type_long_long; ;
+ break;}
+case 102:
+#line 798 "./c-exp.y"
+{ yyval.tval = builtin_type_unsigned_long_long; ;
+ break;}
+case 103:
+#line 800 "./c-exp.y"
+{ yyval.tval = builtin_type_unsigned_long_long; ;
+ break;}
+case 104:
+#line 802 "./c-exp.y"
+{ yyval.tval = builtin_type_short; ;
+ break;}
+case 105:
+#line 804 "./c-exp.y"
+{ yyval.tval = builtin_type_unsigned_short; ;
+ break;}
+case 106:
+#line 806 "./c-exp.y"
+{ yyval.tval = builtin_type_double; ;
+ break;}
+case 107:
+#line 808 "./c-exp.y"
+{ yyval.tval = builtin_type_long_double; ;
+ break;}
+case 108:
+#line 810 "./c-exp.y"
+{ yyval.tval = lookup_struct (copy_name (yyvsp[0].sval),
+ expression_context_block); ;
+ break;}
+case 109:
+#line 813 "./c-exp.y"
+{ yyval.tval = lookup_struct (copy_name (yyvsp[0].sval),
+ expression_context_block); ;
+ break;}
+case 110:
+#line 816 "./c-exp.y"
+{ yyval.tval = lookup_union (copy_name (yyvsp[0].sval),
+ expression_context_block); ;
+ break;}
+case 111:
+#line 819 "./c-exp.y"
+{ yyval.tval = lookup_enum (copy_name (yyvsp[0].sval),
+ expression_context_block); ;
+ break;}
+case 112:
+#line 822 "./c-exp.y"
+{ yyval.tval = lookup_unsigned_typename (TYPE_NAME(yyvsp[0].tsym.type)); ;
+ break;}
+case 113:
+#line 824 "./c-exp.y"
+{ yyval.tval = builtin_type_unsigned_int; ;
+ break;}
+case 114:
+#line 826 "./c-exp.y"
+{ yyval.tval = lookup_signed_typename (TYPE_NAME(yyvsp[0].tsym.type)); ;
+ break;}
+case 115:
+#line 828 "./c-exp.y"
+{ yyval.tval = builtin_type_int; ;
+ break;}
+case 116:
+#line 830 "./c-exp.y"
+{ yyval.tval = lookup_template_type(copy_name(yyvsp[-3].sval), yyvsp[-1].tval,
+ expression_context_block);
+ ;
+ break;}
+case 117:
+#line 836 "./c-exp.y"
+{ yyval.tval = yyvsp[0].tval; ;
+ break;}
+case 118:
+#line 837 "./c-exp.y"
+{ yyval.tval = yyvsp[0].tval; ;
+ break;}
+case 120:
+#line 842 "./c-exp.y"
+{
+ yyval.tsym.stoken.ptr = "int";
+ yyval.tsym.stoken.length = 3;
+ yyval.tsym.type = builtin_type_int;
+ ;
+ break;}
+case 121:
+#line 848 "./c-exp.y"
+{
+ yyval.tsym.stoken.ptr = "long";
+ yyval.tsym.stoken.length = 4;
+ yyval.tsym.type = builtin_type_long;
+ ;
+ break;}
+case 122:
+#line 854 "./c-exp.y"
+{
+ yyval.tsym.stoken.ptr = "short";
+ yyval.tsym.stoken.length = 5;
+ yyval.tsym.type = builtin_type_short;
+ ;
+ break;}
+case 123:
+#line 863 "./c-exp.y"
+{ yyval.tvec = (struct type **) xmalloc (sizeof (struct type *) * 2);
+ yyval.ivec[0] = 1; /* Number of types in vector */
+ yyval.tvec[1] = yyvsp[0].tval;
+ ;
+ break;}
+case 124:
+#line 868 "./c-exp.y"
+{ int len = sizeof (struct type *) * (++(yyvsp[-2].ivec[0]) + 1);
+ yyval.tvec = (struct type **) xrealloc ((char *) yyvsp[-2].tvec, len);
+ yyval.tvec[yyval.ivec[0]] = yyvsp[0].tval;
+ ;
+ break;}
+case 125:
+#line 874 "./c-exp.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+case 126:
+#line 875 "./c-exp.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+case 127:
+#line 876 "./c-exp.y"
+{ yyval.sval = yyvsp[0].tsym.stoken; ;
+ break;}
+case 128:
+#line 877 "./c-exp.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 487 "/usr/unsupported/share/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) xmalloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+}
+#line 891 "./c-exp.y"
+
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ /* FIXME: Shouldn't these be unsigned? We don't deal with negative values
+ here, and we do kind of silly things like cast to unsigned. */
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ unsigned LONGEST un;
+
+ register int i = 0;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+
+ /* Number of "L" suffixes encountered. */
+ int long_p = 0;
+
+ /* We have found a "L" or "U" suffix. */
+ int found_suffix = 0;
+
+ unsigned LONGEST high_bit;
+ struct type *signed_type;
+ struct type *unsigned_type;
+
+ if (parsed_float)
+ {
+ char c;
+
+ /* It's a float since it contains a point or an exponent. */
+
+ if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
+ sscanf (p, "%g", &putithere->typed_val_float.dval);
+ else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
+ sscanf (p, "%lg", &putithere->typed_val_float.dval);
+ else
+ {
+#ifdef PRINTF_HAS_LONG_DOUBLE
+ sscanf (p, "%Lg", &putithere->typed_val_float.dval);
+#else
+ /* Scan it into a double, then assign it to the long double.
+ This at least wins with values representable in the range
+ of doubles. */
+ double temp;
+ sscanf (p, "%lg", &temp);
+ putithere->typed_val_float.dval = temp;
+#endif
+ }
+
+ /* See if it has `f' or `l' suffix (float or long double). */
+
+ c = tolower (p[len - 1]);
+
+ if (c == 'f')
+ putithere->typed_val_float.type = builtin_type_float;
+ else if (c == 'l')
+ putithere->typed_val_float.type = builtin_type_long_double;
+ else if (isdigit (c) || c == '.')
+ putithere->typed_val_float.type = builtin_type_double;
+ else
+ return ERROR;
+
+ return FLOAT;
+ }
+
+ /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+ if (p[0] == '0')
+ switch (p[1])
+ {
+ case 'x':
+ case 'X':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ case 'd':
+ case 'D':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 10;
+ len -= 2;
+ }
+ break;
+
+ default:
+ base = 8;
+ break;
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - '0';
+ }
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - 'a' + 10;
+ }
+ else if (c == 'l')
+ {
+ ++long_p;
+ found_suffix = 1;
+ }
+ else if (c == 'u')
+ {
+ unsigned_p = 1;
+ found_suffix = 1;
+ }
+ else
+ return ERROR; /* Char not a digit */
+ }
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+
+ /* Portably test for overflow (only works for nonzero values, so make
+ a second check for zero). FIXME: Can't we just make n and prevn
+ unsigned and avoid this? */
+ if (c != 'l' && c != 'u' && (prevn >= n) && n != 0)
+ unsigned_p = 1; /* Try something unsigned */
+
+ /* Portably test for unsigned overflow.
+ FIXME: This check is wrong; for example it doesn't find overflow
+ on 0x123456789 when LONGEST is 32 bits. */
+ if (c != 'l' && c != 'u' && n != 0)
+ {
+ if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n))
+ error ("Numeric constant too large.");
+ }
+ prevn = n;
+ }
+
+ /* An integer constant is an int, a long, or a long long. An L
+ suffix forces it to be long; an LL suffix forces it to be long
+ long. If not forced to a larger size, it gets the first type of
+ the above that it fits in. To figure out whether it fits, we
+ shift it right and see whether anything remains. Note that we
+ can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
+ operation, because many compilers will warn about such a shift
+ (which always produces a zero result). Sometimes TARGET_INT_BIT
+ or TARGET_LONG_BIT will be that big, sometimes not. To deal with
+ the case where it is we just always shift the value more than
+ once, with fewer bits each time. */
+
+ un = (unsigned LONGEST)n >> 2;
+ if (long_p == 0
+ && (un >> (TARGET_INT_BIT - 2)) == 0)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+
+ /* A large decimal (not hex or octal) constant (between INT_MAX
+ and UINT_MAX) is a long or unsigned long, according to ANSI,
+ never an unsigned int, but this code treats it as unsigned
+ int. This probably should be fixed. GCC gives a warning on
+ such constants. */
+
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+ else if (long_p <= 1
+ && (un >> (TARGET_LONG_BIT - 2)) == 0)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = (((unsigned LONGEST)1)
+ << (TARGET_LONG_LONG_BIT - 32 - 1)
+ << 16
+ << 16);
+ if (high_bit == 0)
+ /* A long long does not fit in a LONGEST. */
+ high_bit =
+ (unsigned LONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1);
+ unsigned_type = builtin_type_unsigned_long_long;
+ signed_type = builtin_type_long_long;
+ }
+
+ putithere->typed_val_int.val = n;
+
+ /* If the high bit of the worked out type is set then this number
+ has to be unsigned. */
+
+ if (unsigned_p || (n & high_bit))
+ {
+ putithere->typed_val_int.type = unsigned_type;
+ }
+ else
+ {
+ putithere->typed_val_int.type = signed_type;
+ }
+
+ return INT;
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static const struct token tokentab3[] =
+ {
+ {">>=", ASSIGN_MODIFY, BINOP_RSH},
+ {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+ };
+
+static const struct token tokentab2[] =
+ {
+ {"+=", ASSIGN_MODIFY, BINOP_ADD},
+ {"-=", ASSIGN_MODIFY, BINOP_SUB},
+ {"*=", ASSIGN_MODIFY, BINOP_MUL},
+ {"/=", ASSIGN_MODIFY, BINOP_DIV},
+ {"%=", ASSIGN_MODIFY, BINOP_REM},
+ {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR},
+ {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND},
+ {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR},
+ {"++", INCREMENT, BINOP_END},
+ {"--", DECREMENT, BINOP_END},
+ {"->", ARROW, BINOP_END},
+ {"&&", ANDAND, BINOP_END},
+ {"||", OROR, BINOP_END},
+ {"::", COLONCOLON, BINOP_END},
+ {"<<", LSH, BINOP_END},
+ {">>", RSH, BINOP_END},
+ {"==", EQUAL, BINOP_END},
+ {"!=", NOTEQUAL, BINOP_END},
+ {"<=", LEQ, BINOP_END},
+ {">=", GEQ, BINOP_END}
+ };
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ int c;
+ int namelen;
+ unsigned int i;
+ char *tokstart;
+ char *tokptr;
+ int tempbufindex;
+ static char *tempbuf;
+ static int tempbufsize;
+
+ retry:
+
+ tokstart = lexptr;
+ /* See if it is a special token of length 3. */
+ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+ if (STREQN (tokstart, tokentab3[i].operator, 3))
+ {
+ lexptr += 3;
+ yylval.opcode = tokentab3[i].opcode;
+ return tokentab3[i].token;
+ }
+
+ /* See if it is a special token of length 2. */
+ for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+ if (STREQN (tokstart, tokentab2[i].operator, 2))
+ {
+ lexptr += 2;
+ yylval.opcode = tokentab2[i].opcode;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ /* We either have a character constant ('0' or '\177' for example)
+ or we have a quoted symbol reference ('foo(int,int)' in C++
+ for example). */
+ lexptr++;
+ c = *lexptr++;
+ if (c == '\\')
+ c = parse_escape (&lexptr);
+ else if (c == '\'')
+ error ("Empty character constant.");
+
+ yylval.typed_val_int.val = c;
+ yylval.typed_val_int.type = builtin_type_char;
+
+ c = *lexptr++;
+ if (c != '\'')
+ {
+ namelen = skip_quoted (tokstart) - tokstart;
+ if (namelen > 2)
+ {
+ lexptr = tokstart + namelen;
+ if (lexptr[-1] != '\'')
+ error ("Unmatched single quote.");
+ namelen -= 2;
+ tokstart++;
+ goto tryname;
+ }
+ error ("Invalid character constant.");
+ }
+ return INT;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] < '0' || lexptr[1] > '9')
+ goto symbol; /* Nope, must be a symbol. */
+ /* FALL THRU into number case. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ /* This test includes !hex because 'e' is a valid hex digit
+ and thus does not indicate a floating point number when
+ the radix is hex. */
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ /* This test does not include !hex, because a '.' always indicates
+ a decimal floating point number regardless of the radix. */
+ else if (!got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ /* We will take any letters or digits. parse_number will
+ complain if past the radix, or if L or U are not final. */
+ else if ((*p < '0' || *p > '9')
+ && ((*p < 'a' || *p > 'z')
+ && (*p < 'A' || *p > 'Z')))
+ break;
+ }
+ toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ symbol:
+ lexptr++;
+ return c;
+
+ case '"':
+
+ /* Build the gdb internal form of the input string in tempbuf,
+ translating any standard C escape forms seen. Note that the
+ buffer is null byte terminated *only* for the convenience of
+ debugging gdb itself and printing the buffer contents when
+ the buffer contains no embedded nulls. Gdb does not depend
+ upon the buffer being null byte terminated, it uses the length
+ string instead. This allows gdb to handle C strings (as well
+ as strings in other languages) with embedded null bytes */
+
+ tokptr = ++tokstart;
+ tempbufindex = 0;
+
+ do {
+ /* Grow the static temp buffer if necessary, including allocating
+ the first one on demand. */
+ if (tempbufindex + 1 >= tempbufsize)
+ {
+ tempbuf = (char *) xrealloc (tempbuf, tempbufsize += 64);
+ }
+ switch (*tokptr)
+ {
+ case '\0':
+ case '"':
+ /* Do nothing, loop will terminate. */
+ break;
+ case '\\':
+ tokptr++;
+ c = parse_escape (&tokptr);
+ if (c == -1)
+ {
+ continue;
+ }
+ tempbuf[tempbufindex++] = c;
+ break;
+ default:
+ tempbuf[tempbufindex++] = *tokptr++;
+ break;
+ }
+ } while ((*tokptr != '"') && (*tokptr != '\0'));
+ if (*tokptr++ != '"')
+ {
+ error ("Unterminated string in expression.");
+ }
+ tempbuf[tempbufindex] = '\0'; /* See note above */
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = tokptr;
+ return (STRING);
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
+ {
+ if (c == '<')
+ {
+ int i = namelen;
+ while (tokstart[++i] && tokstart[i] != '>');
+ if (tokstart[i] == '>')
+ namelen = i;
+ }
+ c = tokstart[++namelen];
+ }
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ lexptr += namelen;
+
+ tryname:
+
+ /* Catch specific keywords. Should be done with a data structure. */
+ switch (namelen)
+ {
+ case 8:
+ if (STREQN (tokstart, "unsigned", 8))
+ return UNSIGNED;
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "template", 8))
+ return TEMPLATE;
+ if (STREQN (tokstart, "volatile", 8))
+ return VOLATILE_KEYWORD;
+ break;
+ case 6:
+ if (STREQN (tokstart, "struct", 6))
+ return STRUCT;
+ if (STREQN (tokstart, "signed", 6))
+ return SIGNED_KEYWORD;
+ if (STREQN (tokstart, "sizeof", 6))
+ return SIZEOF;
+ if (STREQN (tokstart, "double", 6))
+ return DOUBLE_KEYWORD;
+ break;
+ case 5:
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "class", 5))
+ return CLASS;
+ if (STREQN (tokstart, "union", 5))
+ return UNION;
+ if (STREQN (tokstart, "short", 5))
+ return SHORT;
+ if (STREQN (tokstart, "const", 5))
+ return CONST_KEYWORD;
+ break;
+ case 4:
+ if (STREQN (tokstart, "enum", 4))
+ return ENUM;
+ if (STREQN (tokstart, "long", 4))
+ return LONG;
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "this", 4))
+ {
+ static const char this_name[] =
+ { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
+
+ if (lookup_symbol (this_name, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL))
+ return THIS;
+ }
+ break;
+ case 3:
+ if (STREQN (tokstart, "int", 3))
+ return INT_KEYWORD;
+ break;
+ default:
+ break;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return VARIABLE;
+ }
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions or symtabs. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+ int is_a_field_of_this = 0;
+ int hextype;
+
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE,
+ current_language->la_language == language_cplus
+ ? &is_a_field_of_this : (int *) NULL,
+ (struct symtab **) NULL);
+ /* Call lookup_symtab, not lookup_partial_symtab, in case there are
+ no psymtabs (coff, xcoff, or some future change to blow away the
+ psymtabs once once symbols are read). */
+ if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
+ lookup_symtab (tmp))
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return BLOCKNAME;
+ }
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+#if 1
+ /* Despite the following flaw, we need to keep this code enabled.
+ Because we can get called from check_stub_method, if we don't
+ handle nested types then it screws many operations in any
+ program which uses nested types. */
+ /* In "A::x", if x is a member function of A and there happens
+ to be a type (nested or not, since the stabs don't make that
+ distinction) named x, then this code incorrectly thinks we
+ are dealing with nested types rather than a member function. */
+
+ char *p;
+ char *namestart;
+ struct symbol *best_sym;
+
+ /* Look ahead to detect nested types. This probably should be
+ done in the grammar, but trying seemed to introduce a lot
+ of shift/reduce and reduce/reduce conflicts. It's possible
+ that it could be done, though. Or perhaps a non-grammar, but
+ less ad hoc, approach would work well. */
+
+ /* Since we do not currently have any way of distinguishing
+ a nested type from a non-nested one (the stabs don't tell
+ us whether a type is nested), we just ignore the
+ containing type. */
+
+ p = lexptr;
+ best_sym = sym;
+ while (1)
+ {
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ if (*p == ':' && p[1] == ':')
+ {
+ /* Skip the `::'. */
+ p += 2;
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ namestart = p;
+ while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
+ || (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z'))
+ ++p;
+ if (p != namestart)
+ {
+ struct symbol *cur_sym;
+ /* As big as the whole rest of the expression, which is
+ at least big enough. */
+ char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
+ char *tmp1;
+
+ tmp1 = ncopy;
+ memcpy (tmp1, tmp, strlen (tmp));
+ tmp1 += strlen (tmp);
+ memcpy (tmp1, "::", 2);
+ tmp1 += 2;
+ memcpy (tmp1, namestart, p - namestart);
+ tmp1[p - namestart] = '\0';
+ cur_sym = lookup_symbol (ncopy, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (cur_sym)
+ {
+ if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
+ {
+ best_sym = cur_sym;
+ lexptr = p;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ yylval.tsym.type = SYMBOL_TYPE (best_sym);
+#else /* not 0 */
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+#endif /* not 0 */
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym &&
+ ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
+ (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/contrib/gdb/gdb/c-exp.y b/contrib/gdb/gdb/c-exp.y
new file mode 100644
index 0000000..f1156e6
--- /dev/null
+++ b/contrib/gdb/gdb/c-exp.y
@@ -0,0 +1,1641 @@
+/* YACC parser for C expressions, for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Parse a C expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result.
+
+ Note that malloc's and realloc's in this file are transformed to
+ xmalloc and xrealloc respectively by the same sed command in the
+ makefile that remaps any other malloc/realloc inserted by the parser
+ generator. Doing this with #defines and trying to control the interaction
+ with include files (<malloc.h> and <stdlib.h> for example) just became
+ too messy, particularly when such includes can be inserted at random
+ times by the parser generator. */
+
+%{
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "c-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth c_maxdepth
+#define yyparse c_parse
+#define yylex c_lex
+#define yyerror c_error
+#define yylval c_lval
+#define yychar c_char
+#define yydebug c_debug
+#define yypact c_pact
+#define yyr1 c_r1
+#define yyr2 c_r2
+#define yydef c_def
+#define yychk c_chk
+#define yypgo c_pgo
+#define yyact c_act
+#define yyexca c_exca
+#define yyerrflag c_errflag
+#define yynerrs c_nerrs
+#define yyps c_ps
+#define yypv c_pv
+#define yys c_s
+#define yy_yys c_yys
+#define yystate c_state
+#define yytmp c_tmp
+#define yyv c_v
+#define yy_yyv c_yyv
+#define yyval c_val
+#define yylloc c_lloc
+#define yyreds c_reds /* With YYDEBUG defined */
+#define yytoks c_toks /* With YYDEBUG defined */
+#define yylhs c_yylhs
+#define yylen c_yylen
+#define yydefred c_yydefred
+#define yydgoto c_yydgoto
+#define yysindex c_yysindex
+#define yyrindex c_yyrindex
+#define yygindex c_yygindex
+#define yytable c_yytable
+#define yycheck c_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+%}
+
+/* Although the yacc "value" of an expression is not used,
+ since the result is stored in the structure being created,
+ other node types do have values. */
+
+%union
+ {
+ LONGEST lval;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val_int;
+ struct {
+ DOUBLEST dval;
+ struct type *type;
+ } typed_val_float;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ }
+
+%{
+/* YYSTYPE gets defined by %union */
+static int
+parse_number PARAMS ((char *, int, int, YYSTYPE *));
+%}
+
+%type <voidval> exp exp1 type_exp start variable qualified_name lcurly
+%type <lval> rcurly
+%type <tval> type typebase
+%type <tvec> nonempty_typelist
+/* %type <bval> block */
+
+/* Fancy type parsing. */
+%type <voidval> func_mod direct_abs_decl abs_decl
+%type <tval> ptype
+%type <lval> array_mod
+
+%token <typed_val_int> INT
+%token <typed_val_float> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+ and both convey their data as strings.
+ But a TYPENAME is a string that happens to be defined as a typedef
+ or builtin type name (such as int or char)
+ and a NAME is any other symbol.
+ Contexts where this distinction is not important can use the
+ nonterminal "name", which matches either NAME or TYPENAME. */
+
+%token <sval> STRING
+%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <tsym> TYPENAME
+%type <sval> name
+%type <ssym> name_not_typename
+%type <tsym> typename
+
+/* A NAME_OR_INT is a symbol which is not known in the symbol table,
+ but which would parse as a valid number in the current input radix.
+ E.g. "c" when input_radix==16. Depending on the parse, it will be
+ turned into a name or into a number. */
+
+%token <ssym> NAME_OR_INT
+
+%token STRUCT CLASS UNION ENUM SIZEOF UNSIGNED COLONCOLON
+%token TEMPLATE
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD
+
+%token <voidval> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+/* C++ */
+%token THIS
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left OROR
+%left ANDAND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left '<' '>' LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY INCREMENT DECREMENT
+%right ARROW '.' '[' '('
+%token <ssym> BLOCKNAME
+%type <bval> block
+%left COLONCOLON
+
+
+%%
+
+start : exp1
+ | type_exp
+ ;
+
+type_exp: type
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE);}
+ ;
+
+/* Expressions, including the comma operator. */
+exp1 : exp
+ | exp1 ',' exp
+ { write_exp_elt_opcode (BINOP_COMMA); }
+ ;
+
+/* Expressions, not including the comma operator. */
+exp : '*' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_IND); }
+
+exp : '&' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_ADDR); }
+
+exp : '-' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_NEG); }
+ ;
+
+exp : '!' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+ ;
+
+exp : '~' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_COMPLEMENT); }
+ ;
+
+exp : INCREMENT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_PREINCREMENT); }
+ ;
+
+exp : DECREMENT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_PREDECREMENT); }
+ ;
+
+exp : exp INCREMENT %prec UNARY
+ { write_exp_elt_opcode (UNOP_POSTINCREMENT); }
+ ;
+
+exp : exp DECREMENT %prec UNARY
+ { write_exp_elt_opcode (UNOP_POSTDECREMENT); }
+ ;
+
+exp : SIZEOF exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+exp : exp ARROW name
+ { write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_PTR); }
+ ;
+
+exp : exp ARROW qualified_name
+ { /* exp->type::name becomes exp->*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MPTR); }
+ ;
+exp : exp ARROW '*' exp
+ { write_exp_elt_opcode (STRUCTOP_MPTR); }
+ ;
+
+exp : exp '.' name
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
+
+exp : exp '.' qualified_name
+ { /* exp.type::name becomes exp.*(&type::name) */
+ /* Note: this doesn't work if name is a
+ static member! FIXME */
+ write_exp_elt_opcode (UNOP_ADDR);
+ write_exp_elt_opcode (STRUCTOP_MEMBER); }
+ ;
+
+exp : exp '.' '*' exp
+ { write_exp_elt_opcode (STRUCTOP_MEMBER); }
+ ;
+
+exp : exp '[' exp1 ']'
+ { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+ ;
+
+exp : exp '('
+ /* This is to save the value of arglist_len
+ being accumulated by an outer function call. */
+ { start_arglist (); }
+ arglist ')' %prec ARROW
+ { write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); }
+ ;
+
+lcurly : '{'
+ { start_arglist (); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+rcurly : '}'
+ { $$ = end_arglist () - 1; }
+ ;
+exp : lcurly arglist rcurly %prec ARROW
+ { write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) $3);
+ write_exp_elt_opcode (OP_ARRAY); }
+ ;
+
+exp : lcurly type rcurly exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_MEMVAL); }
+ ;
+
+exp : '(' type ')' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+exp : '(' exp1 ')'
+ { }
+ ;
+
+/* Binary operators in order of decreasing precedence. */
+
+exp : exp '@' exp
+ { write_exp_elt_opcode (BINOP_REPEAT); }
+ ;
+
+exp : exp '*' exp
+ { write_exp_elt_opcode (BINOP_MUL); }
+ ;
+
+exp : exp '/' exp
+ { write_exp_elt_opcode (BINOP_DIV); }
+ ;
+
+exp : exp '%' exp
+ { write_exp_elt_opcode (BINOP_REM); }
+ ;
+
+exp : exp '+' exp
+ { write_exp_elt_opcode (BINOP_ADD); }
+ ;
+
+exp : exp '-' exp
+ { write_exp_elt_opcode (BINOP_SUB); }
+ ;
+
+exp : exp LSH exp
+ { write_exp_elt_opcode (BINOP_LSH); }
+ ;
+
+exp : exp RSH exp
+ { write_exp_elt_opcode (BINOP_RSH); }
+ ;
+
+exp : exp EQUAL exp
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+ ;
+
+exp : exp NOTEQUAL exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ ;
+
+exp : exp LEQ exp
+ { write_exp_elt_opcode (BINOP_LEQ); }
+ ;
+
+exp : exp GEQ exp
+ { write_exp_elt_opcode (BINOP_GEQ); }
+ ;
+
+exp : exp '<' exp
+ { write_exp_elt_opcode (BINOP_LESS); }
+ ;
+
+exp : exp '>' exp
+ { write_exp_elt_opcode (BINOP_GTR); }
+ ;
+
+exp : exp '&' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+ ;
+
+exp : exp '^' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+ ;
+
+exp : exp '|' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+ ;
+
+exp : exp ANDAND exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+ ;
+
+exp : exp OROR exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+ ;
+
+exp : exp '?' exp ':' exp %prec '?'
+ { write_exp_elt_opcode (TERNOP_COND); }
+ ;
+
+exp : exp '=' exp
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+ ;
+
+exp : exp ASSIGN_MODIFY exp
+ { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode ($2);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : INT
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST)($1.val));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : NAME_OR_INT
+ { YYSTYPE val;
+ parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val_int.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val_int.val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+
+exp : FLOAT
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_dblcst ($1.dval);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : VARIABLE
+ /* Already written by write_dollar_variable. */
+ ;
+
+exp : SIZEOF '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ CHECK_TYPEDEF ($3);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : STRING
+ { /* C strings are converted into array constants with
+ an explicit null byte added at the end. Thus
+ the array upper bound is the string length.
+ There is no such thing in C as a completely empty
+ string. */
+ char *sp = $1.ptr; int count = $1.length;
+ while (count-- > 0)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST)(*sp++));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_char);
+ write_exp_elt_longcst ((LONGEST)'\0');
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) ($1.length));
+ write_exp_elt_opcode (OP_ARRAY); }
+ ;
+
+/* C++. */
+exp : THIS
+ { write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS); }
+ ;
+
+/* end of C++. */
+
+block : BLOCKNAME
+ {
+ if ($1.sym != 0)
+ $$ = SYMBOL_BLOCK_VALUE ($1.sym);
+ else
+ {
+ struct symtab *tem =
+ lookup_symtab (copy_name ($1.stoken));
+ if (tem)
+ $$ = BLOCKVECTOR_BLOCK (BLOCKVECTOR (tem), STATIC_BLOCK);
+ else
+ error ("No file or function \"%s\".",
+ copy_name ($1.stoken));
+ }
+ }
+ ;
+
+block : block COLONCOLON name
+ { struct symbol *tem
+ = lookup_symbol (copy_name ($3), $1,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+ error ("No function \"%s\" in specified context.",
+ copy_name ($3));
+ $$ = SYMBOL_BLOCK_VALUE (tem); }
+ ;
+
+variable: block COLONCOLON name
+ { struct symbol *sym;
+ sym = lookup_symbol (copy_name ($3), $1,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name ($3));
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* block_found is set by lookup_symbol. */
+ write_exp_elt_block (block_found);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+qualified_name: typebase COLONCOLON name
+ {
+ struct type *type = $1;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string ($3);
+ write_exp_elt_opcode (OP_SCOPE);
+ }
+ | typebase COLONCOLON '~' name
+ {
+ struct type *type = $1;
+ struct stoken tmp_token;
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION)
+ error ("`%s' is not defined as an aggregate type.",
+ TYPE_NAME (type));
+
+ if (!STREQ (type_name_no_tag (type), $4.ptr))
+ error ("invalid destructor `%s::~%s'",
+ type_name_no_tag (type), $4.ptr);
+
+ tmp_token.ptr = (char*) alloca ($4.length + 2);
+ tmp_token.length = $4.length + 1;
+ tmp_token.ptr[0] = '~';
+ memcpy (tmp_token.ptr+1, $4.ptr, $4.length);
+ tmp_token.ptr[tmp_token.length] = 0;
+ write_exp_elt_opcode (OP_SCOPE);
+ write_exp_elt_type (type);
+ write_exp_string (tmp_token);
+ write_exp_elt_opcode (OP_SCOPE);
+ }
+ ;
+
+variable: qualified_name
+ | COLONCOLON name
+ {
+ char *name = copy_name ($2);
+ struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
+ sym =
+ lookup_symbol (name, (const struct block *) NULL,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym)
+ {
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else
+ if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.", name);
+ }
+ ;
+
+variable: name_not_typename
+ { struct symbol *sym = $1.sym;
+
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else if ($1.is_a_field_of_this)
+ {
+ /* C++: it hangs off of `this'. Must
+ not inadvertently convert from a method call
+ to data ref. */
+ if (innermost_block == 0 ||
+ contained_in (block_found, innermost_block))
+ innermost_block = block_found;
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (OP_THIS);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ write_exp_string ($1.stoken);
+ write_exp_elt_opcode (STRUCTOP_PTR);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name ($1.stoken);
+
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1.stoken));
+ }
+ }
+ ;
+
+
+ptype : typebase
+ /* "const" and "volatile" are curently ignored. A type qualifier
+ before the type is currently handled in the typebase rule.
+ The reason for recognizing these here (shift/reduce conflicts)
+ might be obsolete now that some pointer to member rules have
+ been deleted. */
+ | typebase CONST_KEYWORD
+ | typebase VOLATILE_KEYWORD
+ | typebase abs_decl
+ { $$ = follow_types ($1); }
+ | typebase CONST_KEYWORD abs_decl
+ { $$ = follow_types ($1); }
+ | typebase VOLATILE_KEYWORD abs_decl
+ { $$ = follow_types ($1); }
+ ;
+
+abs_decl: '*'
+ { push_type (tp_pointer); $$ = 0; }
+ | '*' abs_decl
+ { push_type (tp_pointer); $$ = $2; }
+ | '&'
+ { push_type (tp_reference); $$ = 0; }
+ | '&' abs_decl
+ { push_type (tp_reference); $$ = $2; }
+ | direct_abs_decl
+ ;
+
+direct_abs_decl: '(' abs_decl ')'
+ { $$ = $2; }
+ | direct_abs_decl array_mod
+ {
+ push_type_int ($2);
+ push_type (tp_array);
+ }
+ | array_mod
+ {
+ push_type_int ($1);
+ push_type (tp_array);
+ $$ = 0;
+ }
+
+ | direct_abs_decl func_mod
+ { push_type (tp_function); }
+ | func_mod
+ { push_type (tp_function); }
+ ;
+
+array_mod: '[' ']'
+ { $$ = -1; }
+ | '[' INT ']'
+ { $$ = $2.val; }
+ ;
+
+func_mod: '(' ')'
+ { $$ = 0; }
+ | '(' nonempty_typelist ')'
+ { free ((PTR)$2); $$ = 0; }
+ ;
+
+/* We used to try to recognize more pointer to member types here, but
+ that didn't work (shift/reduce conflicts meant that these rules never
+ got executed). The problem is that
+ int (foo::bar::baz::bizzle)
+ is a function type but
+ int (foo::bar::baz::bizzle::*)
+ is a pointer to member type. Stroustrup loses again! */
+
+type : ptype
+ | typebase COLONCOLON '*'
+ { $$ = lookup_member_type (builtin_type_int, $1); }
+ ;
+
+typebase /* Implements (approximately): (type-qualifier)* type-specifier */
+ : TYPENAME
+ { $$ = $1.type; }
+ | INT_KEYWORD
+ { $$ = builtin_type_int; }
+ | LONG
+ { $$ = builtin_type_long; }
+ | SHORT
+ { $$ = builtin_type_short; }
+ | LONG INT_KEYWORD
+ { $$ = builtin_type_long; }
+ | UNSIGNED LONG INT_KEYWORD
+ { $$ = builtin_type_unsigned_long; }
+ | LONG LONG
+ { $$ = builtin_type_long_long; }
+ | LONG LONG INT_KEYWORD
+ { $$ = builtin_type_long_long; }
+ | UNSIGNED LONG LONG
+ { $$ = builtin_type_unsigned_long_long; }
+ | UNSIGNED LONG LONG INT_KEYWORD
+ { $$ = builtin_type_unsigned_long_long; }
+ | SHORT INT_KEYWORD
+ { $$ = builtin_type_short; }
+ | UNSIGNED SHORT INT_KEYWORD
+ { $$ = builtin_type_unsigned_short; }
+ | DOUBLE_KEYWORD
+ { $$ = builtin_type_double; }
+ | LONG DOUBLE_KEYWORD
+ { $$ = builtin_type_long_double; }
+ | STRUCT name
+ { $$ = lookup_struct (copy_name ($2),
+ expression_context_block); }
+ | CLASS name
+ { $$ = lookup_struct (copy_name ($2),
+ expression_context_block); }
+ | UNION name
+ { $$ = lookup_union (copy_name ($2),
+ expression_context_block); }
+ | ENUM name
+ { $$ = lookup_enum (copy_name ($2),
+ expression_context_block); }
+ | UNSIGNED typename
+ { $$ = lookup_unsigned_typename (TYPE_NAME($2.type)); }
+ | UNSIGNED
+ { $$ = builtin_type_unsigned_int; }
+ | SIGNED_KEYWORD typename
+ { $$ = lookup_signed_typename (TYPE_NAME($2.type)); }
+ | SIGNED_KEYWORD
+ { $$ = builtin_type_int; }
+ | TEMPLATE name '<' type '>'
+ { $$ = lookup_template_type(copy_name($2), $4,
+ expression_context_block);
+ }
+ /* "const" and "volatile" are curently ignored. A type qualifier
+ after the type is handled in the ptype rule. I think these could
+ be too. */
+ | CONST_KEYWORD typebase { $$ = $2; }
+ | VOLATILE_KEYWORD typebase { $$ = $2; }
+ ;
+
+typename: TYPENAME
+ | INT_KEYWORD
+ {
+ $$.stoken.ptr = "int";
+ $$.stoken.length = 3;
+ $$.type = builtin_type_int;
+ }
+ | LONG
+ {
+ $$.stoken.ptr = "long";
+ $$.stoken.length = 4;
+ $$.type = builtin_type_long;
+ }
+ | SHORT
+ {
+ $$.stoken.ptr = "short";
+ $$.stoken.length = 5;
+ $$.type = builtin_type_short;
+ }
+ ;
+
+nonempty_typelist
+ : type
+ { $$ = (struct type **) malloc (sizeof (struct type *) * 2);
+ $<ivec>$[0] = 1; /* Number of types in vector */
+ $$[1] = $1;
+ }
+ | nonempty_typelist ',' type
+ { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
+ $$ = (struct type **) realloc ((char *) $1, len);
+ $$[$<ivec>$[0]] = $3;
+ }
+ ;
+
+name : NAME { $$ = $1.stoken; }
+ | BLOCKNAME { $$ = $1.stoken; }
+ | TYPENAME { $$ = $1.stoken; }
+ | NAME_OR_INT { $$ = $1.stoken; }
+ ;
+
+name_not_typename : NAME
+ | BLOCKNAME
+/* These would be useful if name_not_typename was useful, but it is just
+ a fake for "variable", so these cause reduce/reduce conflicts because
+ the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
+ =exp) or just an exp. If name_not_typename was ever used in an lvalue
+ context where only a name could occur, this might be useful.
+ | NAME_OR_INT
+ */
+ ;
+
+%%
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ /* FIXME: Shouldn't these be unsigned? We don't deal with negative values
+ here, and we do kind of silly things like cast to unsigned. */
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ unsigned LONGEST un;
+
+ register int i = 0;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+
+ /* Number of "L" suffixes encountered. */
+ int long_p = 0;
+
+ /* We have found a "L" or "U" suffix. */
+ int found_suffix = 0;
+
+ unsigned LONGEST high_bit;
+ struct type *signed_type;
+ struct type *unsigned_type;
+
+ if (parsed_float)
+ {
+ char c;
+
+ /* It's a float since it contains a point or an exponent. */
+
+ if (sizeof (putithere->typed_val_float.dval) <= sizeof (float))
+ sscanf (p, "%g", &putithere->typed_val_float.dval);
+ else if (sizeof (putithere->typed_val_float.dval) <= sizeof (double))
+ sscanf (p, "%lg", &putithere->typed_val_float.dval);
+ else
+ {
+#ifdef PRINTF_HAS_LONG_DOUBLE
+ sscanf (p, "%Lg", &putithere->typed_val_float.dval);
+#else
+ /* Scan it into a double, then assign it to the long double.
+ This at least wins with values representable in the range
+ of doubles. */
+ double temp;
+ sscanf (p, "%lg", &temp);
+ putithere->typed_val_float.dval = temp;
+#endif
+ }
+
+ /* See if it has `f' or `l' suffix (float or long double). */
+
+ c = tolower (p[len - 1]);
+
+ if (c == 'f')
+ putithere->typed_val_float.type = builtin_type_float;
+ else if (c == 'l')
+ putithere->typed_val_float.type = builtin_type_long_double;
+ else if (isdigit (c) || c == '.')
+ putithere->typed_val_float.type = builtin_type_double;
+ else
+ return ERROR;
+
+ return FLOAT;
+ }
+
+ /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+ if (p[0] == '0')
+ switch (p[1])
+ {
+ case 'x':
+ case 'X':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ case 'd':
+ case 'D':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 10;
+ len -= 2;
+ }
+ break;
+
+ default:
+ base = 8;
+ break;
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - '0';
+ }
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ {
+ if (found_suffix)
+ return ERROR;
+ n += i = c - 'a' + 10;
+ }
+ else if (c == 'l')
+ {
+ ++long_p;
+ found_suffix = 1;
+ }
+ else if (c == 'u')
+ {
+ unsigned_p = 1;
+ found_suffix = 1;
+ }
+ else
+ return ERROR; /* Char not a digit */
+ }
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+
+ /* Portably test for overflow (only works for nonzero values, so make
+ a second check for zero). FIXME: Can't we just make n and prevn
+ unsigned and avoid this? */
+ if (c != 'l' && c != 'u' && (prevn >= n) && n != 0)
+ unsigned_p = 1; /* Try something unsigned */
+
+ /* Portably test for unsigned overflow.
+ FIXME: This check is wrong; for example it doesn't find overflow
+ on 0x123456789 when LONGEST is 32 bits. */
+ if (c != 'l' && c != 'u' && n != 0)
+ {
+ if ((unsigned_p && (unsigned LONGEST) prevn >= (unsigned LONGEST) n))
+ error ("Numeric constant too large.");
+ }
+ prevn = n;
+ }
+
+ /* An integer constant is an int, a long, or a long long. An L
+ suffix forces it to be long; an LL suffix forces it to be long
+ long. If not forced to a larger size, it gets the first type of
+ the above that it fits in. To figure out whether it fits, we
+ shift it right and see whether anything remains. Note that we
+ can't shift sizeof (LONGEST) * HOST_CHAR_BIT bits or more in one
+ operation, because many compilers will warn about such a shift
+ (which always produces a zero result). Sometimes TARGET_INT_BIT
+ or TARGET_LONG_BIT will be that big, sometimes not. To deal with
+ the case where it is we just always shift the value more than
+ once, with fewer bits each time. */
+
+ un = (unsigned LONGEST)n >> 2;
+ if (long_p == 0
+ && (un >> (TARGET_INT_BIT - 2)) == 0)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+
+ /* A large decimal (not hex or octal) constant (between INT_MAX
+ and UINT_MAX) is a long or unsigned long, according to ANSI,
+ never an unsigned int, but this code treats it as unsigned
+ int. This probably should be fixed. GCC gives a warning on
+ such constants. */
+
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+ else if (long_p <= 1
+ && (un >> (TARGET_LONG_BIT - 2)) == 0)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = (((unsigned LONGEST)1)
+ << (TARGET_LONG_LONG_BIT - 32 - 1)
+ << 16
+ << 16);
+ if (high_bit == 0)
+ /* A long long does not fit in a LONGEST. */
+ high_bit =
+ (unsigned LONGEST)1 << (sizeof (LONGEST) * HOST_CHAR_BIT - 1);
+ unsigned_type = builtin_type_unsigned_long_long;
+ signed_type = builtin_type_long_long;
+ }
+
+ putithere->typed_val_int.val = n;
+
+ /* If the high bit of the worked out type is set then this number
+ has to be unsigned. */
+
+ if (unsigned_p || (n & high_bit))
+ {
+ putithere->typed_val_int.type = unsigned_type;
+ }
+ else
+ {
+ putithere->typed_val_int.type = signed_type;
+ }
+
+ return INT;
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static const struct token tokentab3[] =
+ {
+ {">>=", ASSIGN_MODIFY, BINOP_RSH},
+ {"<<=", ASSIGN_MODIFY, BINOP_LSH}
+ };
+
+static const struct token tokentab2[] =
+ {
+ {"+=", ASSIGN_MODIFY, BINOP_ADD},
+ {"-=", ASSIGN_MODIFY, BINOP_SUB},
+ {"*=", ASSIGN_MODIFY, BINOP_MUL},
+ {"/=", ASSIGN_MODIFY, BINOP_DIV},
+ {"%=", ASSIGN_MODIFY, BINOP_REM},
+ {"|=", ASSIGN_MODIFY, BINOP_BITWISE_IOR},
+ {"&=", ASSIGN_MODIFY, BINOP_BITWISE_AND},
+ {"^=", ASSIGN_MODIFY, BINOP_BITWISE_XOR},
+ {"++", INCREMENT, BINOP_END},
+ {"--", DECREMENT, BINOP_END},
+ {"->", ARROW, BINOP_END},
+ {"&&", ANDAND, BINOP_END},
+ {"||", OROR, BINOP_END},
+ {"::", COLONCOLON, BINOP_END},
+ {"<<", LSH, BINOP_END},
+ {">>", RSH, BINOP_END},
+ {"==", EQUAL, BINOP_END},
+ {"!=", NOTEQUAL, BINOP_END},
+ {"<=", LEQ, BINOP_END},
+ {">=", GEQ, BINOP_END}
+ };
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ int c;
+ int namelen;
+ unsigned int i;
+ char *tokstart;
+ char *tokptr;
+ int tempbufindex;
+ static char *tempbuf;
+ static int tempbufsize;
+
+ retry:
+
+ tokstart = lexptr;
+ /* See if it is a special token of length 3. */
+ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++)
+ if (STREQN (tokstart, tokentab3[i].operator, 3))
+ {
+ lexptr += 3;
+ yylval.opcode = tokentab3[i].opcode;
+ return tokentab3[i].token;
+ }
+
+ /* See if it is a special token of length 2. */
+ for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++)
+ if (STREQN (tokstart, tokentab2[i].operator, 2))
+ {
+ lexptr += 2;
+ yylval.opcode = tokentab2[i].opcode;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ /* We either have a character constant ('0' or '\177' for example)
+ or we have a quoted symbol reference ('foo(int,int)' in C++
+ for example). */
+ lexptr++;
+ c = *lexptr++;
+ if (c == '\\')
+ c = parse_escape (&lexptr);
+ else if (c == '\'')
+ error ("Empty character constant.");
+
+ yylval.typed_val_int.val = c;
+ yylval.typed_val_int.type = builtin_type_char;
+
+ c = *lexptr++;
+ if (c != '\'')
+ {
+ namelen = skip_quoted (tokstart) - tokstart;
+ if (namelen > 2)
+ {
+ lexptr = tokstart + namelen;
+ if (lexptr[-1] != '\'')
+ error ("Unmatched single quote.");
+ namelen -= 2;
+ tokstart++;
+ goto tryname;
+ }
+ error ("Invalid character constant.");
+ }
+ return INT;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] < '0' || lexptr[1] > '9')
+ goto symbol; /* Nope, must be a symbol. */
+ /* FALL THRU into number case. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ /* This test includes !hex because 'e' is a valid hex digit
+ and thus does not indicate a floating point number when
+ the radix is hex. */
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ /* This test does not include !hex, because a '.' always indicates
+ a decimal floating point number regardless of the radix. */
+ else if (!got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ /* We will take any letters or digits. parse_number will
+ complain if past the radix, or if L or U are not final. */
+ else if ((*p < '0' || *p > '9')
+ && ((*p < 'a' || *p > 'z')
+ && (*p < 'A' || *p > 'Z')))
+ break;
+ }
+ toktype = parse_number (tokstart, p - tokstart, got_dot|got_e, &yylval);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ symbol:
+ lexptr++;
+ return c;
+
+ case '"':
+
+ /* Build the gdb internal form of the input string in tempbuf,
+ translating any standard C escape forms seen. Note that the
+ buffer is null byte terminated *only* for the convenience of
+ debugging gdb itself and printing the buffer contents when
+ the buffer contains no embedded nulls. Gdb does not depend
+ upon the buffer being null byte terminated, it uses the length
+ string instead. This allows gdb to handle C strings (as well
+ as strings in other languages) with embedded null bytes */
+
+ tokptr = ++tokstart;
+ tempbufindex = 0;
+
+ do {
+ /* Grow the static temp buffer if necessary, including allocating
+ the first one on demand. */
+ if (tempbufindex + 1 >= tempbufsize)
+ {
+ tempbuf = (char *) realloc (tempbuf, tempbufsize += 64);
+ }
+ switch (*tokptr)
+ {
+ case '\0':
+ case '"':
+ /* Do nothing, loop will terminate. */
+ break;
+ case '\\':
+ tokptr++;
+ c = parse_escape (&tokptr);
+ if (c == -1)
+ {
+ continue;
+ }
+ tempbuf[tempbufindex++] = c;
+ break;
+ default:
+ tempbuf[tempbufindex++] = *tokptr++;
+ break;
+ }
+ } while ((*tokptr != '"') && (*tokptr != '\0'));
+ if (*tokptr++ != '"')
+ {
+ error ("Unterminated string in expression.");
+ }
+ tempbuf[tempbufindex] = '\0'; /* See note above */
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = tokptr;
+ return (STRING);
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
+ {
+ if (c == '<')
+ {
+ int i = namelen;
+ while (tokstart[++i] && tokstart[i] != '>');
+ if (tokstart[i] == '>')
+ namelen = i;
+ }
+ c = tokstart[++namelen];
+ }
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ lexptr += namelen;
+
+ tryname:
+
+ /* Catch specific keywords. Should be done with a data structure. */
+ switch (namelen)
+ {
+ case 8:
+ if (STREQN (tokstart, "unsigned", 8))
+ return UNSIGNED;
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "template", 8))
+ return TEMPLATE;
+ if (STREQN (tokstart, "volatile", 8))
+ return VOLATILE_KEYWORD;
+ break;
+ case 6:
+ if (STREQN (tokstart, "struct", 6))
+ return STRUCT;
+ if (STREQN (tokstart, "signed", 6))
+ return SIGNED_KEYWORD;
+ if (STREQN (tokstart, "sizeof", 6))
+ return SIZEOF;
+ if (STREQN (tokstart, "double", 6))
+ return DOUBLE_KEYWORD;
+ break;
+ case 5:
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "class", 5))
+ return CLASS;
+ if (STREQN (tokstart, "union", 5))
+ return UNION;
+ if (STREQN (tokstart, "short", 5))
+ return SHORT;
+ if (STREQN (tokstart, "const", 5))
+ return CONST_KEYWORD;
+ break;
+ case 4:
+ if (STREQN (tokstart, "enum", 4))
+ return ENUM;
+ if (STREQN (tokstart, "long", 4))
+ return LONG;
+ if (current_language->la_language == language_cplus
+ && STREQN (tokstart, "this", 4))
+ {
+ static const char this_name[] =
+ { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' };
+
+ if (lookup_symbol (this_name, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL))
+ return THIS;
+ }
+ break;
+ case 3:
+ if (STREQN (tokstart, "int", 3))
+ return INT_KEYWORD;
+ break;
+ default:
+ break;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return VARIABLE;
+ }
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions or symtabs. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+ int is_a_field_of_this = 0;
+ int hextype;
+
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE,
+ current_language->la_language == language_cplus
+ ? &is_a_field_of_this : (int *) NULL,
+ (struct symtab **) NULL);
+ /* Call lookup_symtab, not lookup_partial_symtab, in case there are
+ no psymtabs (coff, xcoff, or some future change to blow away the
+ psymtabs once once symbols are read). */
+ if ((sym && SYMBOL_CLASS (sym) == LOC_BLOCK) ||
+ lookup_symtab (tmp))
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return BLOCKNAME;
+ }
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+#if 1
+ /* Despite the following flaw, we need to keep this code enabled.
+ Because we can get called from check_stub_method, if we don't
+ handle nested types then it screws many operations in any
+ program which uses nested types. */
+ /* In "A::x", if x is a member function of A and there happens
+ to be a type (nested or not, since the stabs don't make that
+ distinction) named x, then this code incorrectly thinks we
+ are dealing with nested types rather than a member function. */
+
+ char *p;
+ char *namestart;
+ struct symbol *best_sym;
+
+ /* Look ahead to detect nested types. This probably should be
+ done in the grammar, but trying seemed to introduce a lot
+ of shift/reduce and reduce/reduce conflicts. It's possible
+ that it could be done, though. Or perhaps a non-grammar, but
+ less ad hoc, approach would work well. */
+
+ /* Since we do not currently have any way of distinguishing
+ a nested type from a non-nested one (the stabs don't tell
+ us whether a type is nested), we just ignore the
+ containing type. */
+
+ p = lexptr;
+ best_sym = sym;
+ while (1)
+ {
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ if (*p == ':' && p[1] == ':')
+ {
+ /* Skip the `::'. */
+ p += 2;
+ /* Skip whitespace. */
+ while (*p == ' ' || *p == '\t' || *p == '\n')
+ ++p;
+ namestart = p;
+ while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9')
+ || (*p >= 'a' && *p <= 'z')
+ || (*p >= 'A' && *p <= 'Z'))
+ ++p;
+ if (p != namestart)
+ {
+ struct symbol *cur_sym;
+ /* As big as the whole rest of the expression, which is
+ at least big enough. */
+ char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3);
+ char *tmp1;
+
+ tmp1 = ncopy;
+ memcpy (tmp1, tmp, strlen (tmp));
+ tmp1 += strlen (tmp);
+ memcpy (tmp1, "::", 2);
+ tmp1 += 2;
+ memcpy (tmp1, namestart, p - namestart);
+ tmp1[p - namestart] = '\0';
+ cur_sym = lookup_symbol (ncopy, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (cur_sym)
+ {
+ if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF)
+ {
+ best_sym = cur_sym;
+ lexptr = p;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+ else
+ break;
+ }
+
+ yylval.tsym.type = SYMBOL_TYPE (best_sym);
+#else /* not 0 */
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+#endif /* not 0 */
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym &&
+ ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10) ||
+ (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/contrib/gdb/gdb/c-lang.c b/contrib/gdb/gdb/c-lang.c
new file mode 100644
index 0000000..66ee3e1
--- /dev/null
+++ b/contrib/gdb/gdb/c-lang.c
@@ -0,0 +1,478 @@
+/* C language support routines for GDB, the GNU debugger.
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.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
+ characters and strings is language specific. */
+
+static void
+emit_char (c, stream, quoter)
+ register int c;
+ GDB_FILE *stream;
+ int quoter;
+{
+
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (c == '\\' || c == quoter)
+ {
+ fputs_filtered ("\\", stream);
+ }
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\n':
+ fputs_filtered ("\\n", stream);
+ break;
+ case '\b':
+ fputs_filtered ("\\b", stream);
+ break;
+ case '\t':
+ fputs_filtered ("\\t", stream);
+ break;
+ case '\f':
+ fputs_filtered ("\\f", stream);
+ break;
+ case '\r':
+ fputs_filtered ("\\r", stream);
+ break;
+ case '\033':
+ fputs_filtered ("\\e", stream);
+ break;
+ case '\007':
+ fputs_filtered ("\\a", stream);
+ break;
+ default:
+ fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
+ break;
+ }
+ }
+}
+
+void
+c_printchar (c, stream)
+ int c;
+ GDB_FILE *stream;
+{
+ fputs_filtered ("'", stream);
+ emit_char (c, stream, '\'');
+ fputs_filtered ("'", stream);
+}
+
+/* Print the character string STRING, printing at most LENGTH characters.
+ Printing stops early if the number hits print_max; repeat counts
+ are printed as appropriate. Print ellipses at the end if we
+ had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. */
+
+void
+c_printstr (stream, string, length, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ register unsigned int i;
+ unsigned int things_printed = 0;
+ int in_quotes = 0;
+ int need_comma = 0;
+ extern int inspect_it;
+ extern int repeat_count_threshold;
+ extern int print_max;
+
+ /* If the string was not truncated due to `set print elements', and
+ the last byte of it is a null, we don't print that, in traditional C
+ style. */
+ if ((!force_ellipses) && length > 0 && string[length-1] == '\0')
+ length--;
+
+ if (length == 0)
+ {
+ fputs_filtered ("\"\"", stream);
+ return;
+ }
+
+ for (i = 0; i < length && things_printed < print_max; ++i)
+ {
+ /* Position of the character we are examining
+ to see whether it is repeated. */
+ unsigned int rep1;
+ /* Number of repetitions we have detected so far. */
+ unsigned int reps;
+
+ QUIT;
+
+ if (need_comma)
+ {
+ fputs_filtered (", ", stream);
+ need_comma = 0;
+ }
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < length && string[rep1] == string[i])
+ {
+ ++rep1;
+ ++reps;
+ }
+
+ if (reps > repeat_count_threshold)
+ {
+ if (in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\\", ", stream);
+ else
+ fputs_filtered ("\", ", stream);
+ in_quotes = 0;
+ }
+ c_printchar (string[i], stream);
+ fprintf_filtered (stream, " <repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += repeat_count_threshold;
+ need_comma = 1;
+ }
+ else
+ {
+ if (!in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\\"", stream);
+ else
+ fputs_filtered ("\"", stream);
+ in_quotes = 1;
+ }
+ emit_char (string[i], stream, '"');
+ ++things_printed;
+ }
+ }
+
+ /* Terminate the quotes if necessary. */
+ if (in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\\"", stream);
+ else
+ fputs_filtered ("\"", stream);
+ }
+
+ if (force_ellipses || i < length)
+ fputs_filtered ("...", stream);
+}
+
+/* Create a fundamental C type using default reasonable for the current
+ target machine.
+
+ Some object/debugging file formats (DWARF version 1, COFF, etc) do not
+ define fundamental types such as "int" or "double". Others (stabs or
+ DWARF version 2, etc) do define fundamental types. For the formats which
+ don't provide fundamental types, gdb can create such types using this
+ function.
+
+ FIXME: Some compilers distinguish explicitly signed integral types
+ (signed short, signed int, signed long) from "regular" integral types
+ (short, int, long) in the debugging information. There is some dis-
+ agreement as to how useful this feature is. In particular, gcc does
+ not support this. Also, only some debugging formats allow the
+ distinction to be passed on to a debugger. For now, we always just
+ use "short", "int", or "long" as the type name, for both the implicit
+ and explicitly signed types. This also makes life easier for the
+ gdb test suite since we don't have to account for the differences
+ in output depending upon what the compiler and debugging format
+ support. We will probably have to re-examine the issue when gdb
+ starts taking it's fundamental type information directly from the
+ debugging information supplied by the compiler. fnf@cygnus.com */
+
+struct type *
+c_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ default:
+ /* FIXME: For now, if we are asked to produce a type not in this
+ language, create the equivalent of a C integer type with the
+ name "<?type?>". When all the dust settles from the type
+ reconstruction work, this should probably become an error. */
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "<?type?>", objfile);
+ warning ("internal error: no C/C++ fundamental type %d", typeid);
+ break;
+ case FT_VOID:
+ type = init_type (TYPE_CODE_VOID,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "void", objfile);
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "char", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "signed char", objfile);
+ break;
+ case FT_UNSIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
+ break;
+ case FT_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile);
+ break;
+ case FT_SIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile); /* FIXME-fnf */
+ break;
+ case FT_UNSIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
+ break;
+ case FT_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", objfile);
+ break;
+ case FT_SIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
+ break;
+ case FT_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile);
+ break;
+ case FT_SIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
+ break;
+ case FT_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long long", objfile);
+ break;
+ case FT_SIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "signed long long", objfile);
+ break;
+ case FT_UNSIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
+ break;
+ case FT_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "float", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "double", objfile);
+ break;
+ case FT_EXT_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "long double", objfile);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+
+const struct op_print c_op_print_tab[] =
+ {
+ {",", BINOP_COMMA, PREC_COMMA, 0},
+ {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+ {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+ {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+ {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+ {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+ {"<=", BINOP_LEQ, PREC_ORDER, 0},
+ {">=", BINOP_GEQ, PREC_ORDER, 0},
+ {">", BINOP_GTR, PREC_ORDER, 0},
+ {"<", BINOP_LESS, PREC_ORDER, 0},
+ {">>", BINOP_RSH, PREC_SHIFT, 0},
+ {"<<", BINOP_LSH, PREC_SHIFT, 0},
+ {"+", BINOP_ADD, PREC_ADD, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"%", BINOP_REM, PREC_MUL, 0},
+ {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+ {"*", UNOP_IND, PREC_PREFIX, 0},
+ {"&", UNOP_ADDR, PREC_PREFIX, 0},
+ {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+ {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+ {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+ /* C++ */
+ {"::", BINOP_SCOPE, PREC_PREFIX, 0},
+ {NULL, 0, 0, 0}
+};
+
+struct type ** const (c_builtin_types[]) =
+{
+ &builtin_type_int,
+ &builtin_type_long,
+ &builtin_type_short,
+ &builtin_type_char,
+ &builtin_type_float,
+ &builtin_type_double,
+ &builtin_type_void,
+ &builtin_type_long_long,
+ &builtin_type_signed_char,
+ &builtin_type_unsigned_char,
+ &builtin_type_unsigned_short,
+ &builtin_type_unsigned_int,
+ &builtin_type_unsigned_long,
+ &builtin_type_unsigned_long_long,
+ &builtin_type_long_double,
+ &builtin_type_complex,
+ &builtin_type_double_complex,
+ 0
+};
+
+const struct language_defn c_language_defn = {
+ "c", /* Language name */
+ language_c,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ c_parse,
+ c_error,
+ evaluate_subexp_standard,
+ 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 */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+const struct language_defn cplus_language_defn = {
+ "c++", /* Language name */
+ language_cplus,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ c_parse,
+ c_error,
+ evaluate_subexp_standard,
+ 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 */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ 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,
+ evaluate_subexp_standard,
+ 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 */
+ {"", "", "", ""}, /* 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 */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+void
+_initialize_c_language ()
+{
+ add_language (&c_language_defn);
+ add_language (&cplus_language_defn);
+ add_language (&asm_language_defn);
+}
diff --git a/contrib/gdb/gdb/c-lang.h b/contrib/gdb/gdb/c-lang.h
new file mode 100644
index 0000000..fbd8b69
--- /dev/null
+++ b/contrib/gdb/gdb/c-lang.h
@@ -0,0 +1,84 @@
+/* C language support definitions for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+#endif
+
+extern int
+c_parse PARAMS ((void)); /* Defined in c-exp.y */
+
+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 *, GDB_FILE *, int, int));
+
+extern 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));
+
+/* These are in c-lang.c: */
+
+extern void c_printchar PARAMS ((int, GDB_FILE*));
+
+extern void c_printstr PARAMS ((GDB_FILE *, char *, unsigned int, int));
+
+extern struct type * c_create_fundamental_type PARAMS ((struct objfile*, int));
+
+extern struct type ** const (c_builtin_types[]);
+
+/* These are in c-typeprint.c: */
+
+extern void
+c_type_print_base PARAMS ((struct type *, GDB_FILE *, int, int));
+
+extern void
+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,
+ GDB_FILE *));
+/* These are in cp-valprint.c */
+
+extern void
+cp_type_print_method_args PARAMS ((struct type **, char *, char *, int,
+ GDB_FILE *));
+
+extern int vtblprint; /* Controls printing of vtbl's */
+
+extern void
+cp_print_class_member PARAMS ((char *, struct type *, GDB_FILE *, char *));
+
+extern void
+cp_print_class_method PARAMS ((char *, struct type *, GDB_FILE *));
+
+extern void
+cp_print_value_fields PARAMS ((struct type *, char *, CORE_ADDR,
+ GDB_FILE *, int, int, enum val_prettyprint,
+ struct type**, int));
+
+extern int
+cp_is_vtbl_ptr_type PARAMS ((struct type *));
+
+extern int
+cp_is_vtbl_member PARAMS ((struct type *));
diff --git a/contrib/gdb/gdb/c-typeprint.c b/contrib/gdb/gdb/c-typeprint.c
new file mode 100644
index 0000000..a7a5341
--- /dev/null
+++ b/contrib/gdb/gdb/c-typeprint.c
@@ -0,0 +1,831 @@
+/* Support for printing C and C++ types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "c-lang.h"
+#include "typeprint.h"
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <ctype.h>
+
+static void
+c_type_print_args PARAMS ((struct type *, GDB_FILE *));
+
+static void
+c_type_print_varspec_suffix PARAMS ((struct type *, GDB_FILE *, int, int, int));
+
+static void
+cp_type_print_derivation_info PARAMS ((GDB_FILE *, struct type *));
+
+void
+c_type_print_varspec_prefix PARAMS ((struct type *, GDB_FILE *, int, int));
+
+
+/* Print a description of a type in the format of a
+ typedef for the current language.
+ NEW is the new name for a type TYPE. */
+
+void
+c_typedef_print (type, new, stream)
+ struct type *type;
+ struct symbol *new;
+ GDB_FILE *stream;
+{
+ CHECK_TYPEDEF (type);
+ switch (current_language->la_language)
+ {
+#ifdef _LANG_c
+ case language_c:
+ case language_cplus:
+ fprintf_filtered(stream, "typedef ");
+ type_print(type,"",stream,0);
+ if(TYPE_NAME ((SYMBOL_TYPE (new))) == 0
+ || !STREQ (TYPE_NAME ((SYMBOL_TYPE (new))), SYMBOL_NAME (new)))
+ fprintf_filtered(stream, " %s", SYMBOL_SOURCE_NAME(new));
+ break;
+#endif
+#ifdef _LANG_m2
+ case language_m2:
+ fprintf_filtered(stream, "TYPE ");
+ if(!TYPE_NAME(SYMBOL_TYPE(new)) ||
+ !STREQ (TYPE_NAME(SYMBOL_TYPE(new)), SYMBOL_NAME(new)))
+ fprintf_filtered(stream, "%s = ", SYMBOL_SOURCE_NAME(new));
+ else
+ fprintf_filtered(stream, "<builtin> = ");
+ type_print(type,"",stream,0);
+ break;
+#endif
+#ifdef _LANG_chill
+ case language_chill:
+ fprintf_filtered(stream, "SYNMODE ");
+ if(!TYPE_NAME(SYMBOL_TYPE(new)) ||
+ !STREQ (TYPE_NAME(SYMBOL_TYPE(new)), SYMBOL_NAME(new)))
+ fprintf_filtered(stream, "%s = ", SYMBOL_SOURCE_NAME(new));
+ else
+ fprintf_filtered(stream, "<builtin> = ");
+ type_print(type,"",stream,0);
+ break;
+#endif
+ default:
+ error("Language not supported.");
+ }
+ fprintf_filtered(stream, ";\n");
+}
+
+
+/* LEVEL is the depth to indent lines by. */
+
+void
+c_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ register enum type_code code;
+ int demangled_args;
+
+ if (show > 0)
+ CHECK_TYPEDEF (type);
+
+ c_type_print_base (type, stream, show, level);
+ code = TYPE_CODE (type);
+ if ((varstring != NULL && *varstring != '\0')
+ ||
+ /* Need a space if going to print stars or brackets;
+ but not if we will print just a type name. */
+ ((show > 0 || TYPE_NAME (type) == 0)
+ &&
+ (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
+ || code == TYPE_CODE_METHOD
+ || code == TYPE_CODE_ARRAY
+ || code == TYPE_CODE_MEMBER
+ || code == TYPE_CODE_REF)))
+ fputs_filtered (" ", stream);
+ c_type_print_varspec_prefix (type, stream, show, 0);
+
+ fputs_filtered (varstring, stream);
+
+ /* For demangled function names, we have the arglist as part of the name,
+ so don't print an additional pair of ()'s */
+
+ demangled_args = strchr(varstring, '(') != NULL;
+ c_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
+
+}
+
+/* Print the C++ method arguments ARGS to the file STREAM. */
+
+void
+cp_type_print_method_args (args, prefix, varstring, staticp, stream)
+ struct type **args;
+ char *prefix;
+ char *varstring;
+ int staticp;
+ GDB_FILE *stream;
+{
+ int i;
+
+ fprintf_symbol_filtered (stream, prefix, language_cplus, DMGL_ANSI);
+ fprintf_symbol_filtered (stream, varstring, language_cplus, DMGL_ANSI);
+ fputs_filtered (" (", stream);
+ if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID)
+ {
+ i = !staticp; /* skip the class variable */
+ while (1)
+ {
+ type_print (args[i++], "", stream, 0);
+ if (!args[i])
+ {
+ fprintf_filtered (stream, " ...");
+ break;
+ }
+ else if (args[i]->code != TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream, ", ");
+ }
+ else break;
+ }
+ }
+ fprintf_filtered (stream, ")");
+}
+
+/* If TYPE is a derived type, then print out derivation information.
+ Print only the actual base classes of this type, not the base classes
+ of the base classes. I.E. for the derivation hierarchy:
+
+ class A { int a; };
+ class B : public A {int b; };
+ class C : public B {int c; };
+
+ Print the type of class C as:
+
+ class C : public B {
+ int c;
+ }
+
+ Not as the following (like gdb used to), which is not legal C++ syntax for
+ derived types and may be confused with the multiple inheritance form:
+
+ class C : public B : public A {
+ int c;
+ }
+
+ In general, gdb should try to print the types as closely as possible to
+ the form that they appear in the source code. */
+
+static void
+cp_type_print_derivation_info (stream, type)
+ GDB_FILE *stream;
+ struct type *type;
+{
+ char *name;
+ int i;
+
+ for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+ {
+ fputs_filtered (i == 0 ? ": " : ", ", stream);
+ fprintf_filtered (stream, "%s%s ",
+ BASETYPE_VIA_PUBLIC (type, i) ? "public" : "private",
+ BASETYPE_VIA_VIRTUAL(type, i) ? " virtual" : "");
+ name = type_name_no_tag (TYPE_BASECLASS (type, i));
+ fprintf_filtered (stream, "%s", name ? name : "(null)");
+ }
+ if (i > 0)
+ {
+ fputs_filtered (" ", stream);
+ }
+}
+
+/* Print any asterisks or open-parentheses needed before the
+ variable name (to describe its type).
+
+ On outermost call, pass 0 for PASSED_A_PTR.
+ On outermost call, SHOW > 0 means should ignore
+ any typename for TYPE and show its details.
+ SHOW is always zero on recursive calls. */
+
+void
+c_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
+ struct type *type;
+ GDB_FILE *stream;
+ int show;
+ int passed_a_ptr;
+{
+ char *name;
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ fprintf_filtered (stream, "*");
+ break;
+
+ case TYPE_CODE_MEMBER:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ fprintf_filtered (stream, " ");
+ name = type_name_no_tag (TYPE_DOMAIN_TYPE (type));
+ if (name)
+ fputs_filtered (name, stream);
+ else
+ c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
+ fprintf_filtered (stream, "::");
+ break;
+
+ case TYPE_CODE_METHOD:
+ if (passed_a_ptr)
+ fprintf_unfiltered (stream, "(");
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ {
+ fprintf_filtered (stream, " ");
+ c_type_print_base (TYPE_DOMAIN_TYPE (type), stream, 0, passed_a_ptr);
+ fprintf_filtered (stream, "::");
+ }
+ break;
+
+ case TYPE_CODE_REF:
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ fprintf_filtered (stream, "&");
+ break;
+
+ case TYPE_CODE_FUNC:
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ break;
+
+ case TYPE_CODE_ARRAY:
+ c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ break;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* These types need no prefix. They are listed here so that
+ gcc -Wall will reveal any types that haven't been handled. */
+ break;
+ }
+}
+
+static void
+c_type_print_args (type, stream)
+ struct type *type;
+ GDB_FILE *stream;
+{
+ int i;
+ struct type **args;
+
+ fprintf_filtered (stream, "(");
+ args = TYPE_ARG_TYPES (type);
+ if (args != NULL)
+ {
+ if (args[1] == NULL)
+ {
+ fprintf_filtered (stream, "...");
+ }
+ else
+ {
+ for (i = 1;
+ args[i] != NULL && args[i]->code != TYPE_CODE_VOID;
+ i++)
+ {
+ c_print_type (args[i], "", stream, -1, 0);
+ if (args[i+1] == NULL)
+ {
+ fprintf_filtered (stream, "...");
+ }
+ else if (args[i+1]->code != TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream, ",");
+ wrap_here (" ");
+ }
+ }
+ }
+ }
+ fprintf_filtered (stream, ")");
+}
+
+/* Print any array sizes, function arguments or close parentheses
+ needed after the variable name (to describe its type).
+ Args work like c_type_print_varspec_prefix. */
+
+static void
+c_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
+ struct type *type;
+ GDB_FILE *stream;
+ int show;
+ int passed_a_ptr;
+ int demangled_args;
+{
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+
+ fprintf_filtered (stream, "[");
+ if (TYPE_LENGTH (type) >= 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0
+ && TYPE_ARRAY_UPPER_BOUND_TYPE(type) != BOUND_CANNOT_BE_DETERMINED)
+ fprintf_filtered (stream, "%d",
+ (TYPE_LENGTH (type)
+ / TYPE_LENGTH (TYPE_TARGET_TYPE (type))));
+ fprintf_filtered (stream, "]");
+
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ break;
+
+ case TYPE_CODE_MEMBER:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ break;
+
+ case TYPE_CODE_METHOD:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ if (passed_a_ptr)
+ {
+ c_type_print_args (type, stream);
+ }
+ break;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0);
+ break;
+
+ case TYPE_CODE_FUNC:
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+ if (!demangled_args)
+ { int i, len = TYPE_NFIELDS (type);
+ fprintf_filtered (stream, "(");
+ for (i = 0; i < len; i++)
+ {
+ if (i > 0)
+ {
+ fputs_filtered (", ", stream);
+ wrap_here (" ");
+ }
+ c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
+ }
+ fprintf_filtered (stream, ")");
+ }
+ c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr, 0);
+ break;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* These types do not need a suffix. They are listed so that
+ gcc -Wall will report types that may not have been considered. */
+ break;
+ }
+}
+
+/* Print the name of the type (or the ultimate pointer target,
+ function value or array element), or the description of a
+ structure or union.
+
+ SHOW positive means print details about the type (e.g. enum values),
+ and print structure elements passing SHOW - 1 for show.
+ 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 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. */
+
+void
+c_type_print_base (type, stream, show, level)
+ struct type *type;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ register int i;
+ register int len;
+ register int lastval;
+ char *mangled_name;
+ char *demangled_name;
+ enum {s_none, s_public, s_private, s_protected} section_type;
+ QUIT;
+
+ wrap_here (" ");
+ if (type == NULL)
+ {
+ fputs_filtered ("<type unknown>", stream);
+ return;
+ }
+
+ /* When SHOW is zero or less, and there is a valid type name, then always
+ just print the type name directly from the type. */
+ /* If we have "typedef struct foo {. . .} bar;" do we want to print it
+ as "struct foo" or as "bar"? Pick the latter, because C++ folk tend
+ to expect things like "class5 *foo" rather than "struct class5 *foo". */
+
+ if (show <= 0
+ && TYPE_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ return;
+ }
+
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_METHOD:
+ c_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_STRUCT:
+ if (HAVE_CPLUS_STRUCT (type))
+ {
+ fprintf_filtered (stream, "class ");
+ }
+ else
+ {
+ fprintf_filtered (stream, "struct ");
+ }
+ goto struct_union;
+
+ case TYPE_CODE_UNION:
+ fprintf_filtered (stream, "union ");
+
+ struct_union:
+ if (TYPE_TAG_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_TAG_NAME (type), stream);
+ if (show > 0)
+ fputs_filtered (" ", stream);
+ }
+ wrap_here (" ");
+ 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 || TYPE_TAG_NAME (type) == NULL)
+ {
+ cp_type_print_derivation_info (stream, type);
+
+ fprintf_filtered (stream, "{\n");
+ if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
+ {
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
+ else
+ fprintfi_filtered (level + 4, stream, "<no data fields>\n");
+ }
+
+ /* Start off with no specific section type, so we can print
+ one for the first field we find, and use that section type
+ thereafter until we find another type. */
+
+ section_type = s_none;
+
+ /* If there is a base class for this type,
+ do not print the field that it occupies. */
+
+ len = TYPE_NFIELDS (type);
+ for (i = TYPE_N_BASECLASSES (type); i < len; i++)
+ {
+ QUIT;
+ /* Don't print out virtual function table. */
+ if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5)
+ && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5]))
+ continue;
+
+ /* If this is a C++ class we can print the various C++ section
+ labels. */
+
+ if (HAVE_CPLUS_STRUCT (type))
+ {
+ if (TYPE_FIELD_PROTECTED (type, i))
+ {
+ if (section_type != s_protected)
+ {
+ section_type = s_protected;
+ fprintfi_filtered (level + 2, stream,
+ "protected:\n");
+ }
+ }
+ else if (TYPE_FIELD_PRIVATE (type, i))
+ {
+ if (section_type != s_private)
+ {
+ section_type = s_private;
+ fprintfi_filtered (level + 2, stream, "private:\n");
+ }
+ }
+ else
+ {
+ if (section_type != s_public)
+ {
+ section_type = s_public;
+ fprintfi_filtered (level + 2, stream, "public:\n");
+ }
+ }
+ }
+
+ print_spaces_filtered (level + 4, stream);
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ fprintf_filtered (stream, "static ");
+ }
+ c_print_type (TYPE_FIELD_TYPE (type, i),
+ TYPE_FIELD_NAME (type, i),
+ stream, show - 1, level + 4);
+ if (!TYPE_FIELD_STATIC (type, i)
+ && TYPE_FIELD_PACKED (type, i))
+ {
+ /* It is a bitfield. This code does not attempt
+ to look at the bitpos and reconstruct filler,
+ unnamed fields. This would lead to misleading
+ results if the compiler does not put out fields
+ for such things (I don't know what it does). */
+ fprintf_filtered (stream, " : %d",
+ TYPE_FIELD_BITSIZE (type, i));
+ }
+ fprintf_filtered (stream, ";\n");
+ }
+
+ /* If there are both fields and methods, put a space between. */
+ len = TYPE_NFN_FIELDS (type);
+ if (len && section_type != s_none)
+ fprintf_filtered (stream, "\n");
+
+ /* C++: print out the methods */
+
+ for (i = 0; i < len; i++)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i);
+ char *method_name = TYPE_FN_FIELDLIST_NAME (type, i);
+ char *name = type_name_no_tag (type);
+ int is_constructor = name && STREQ(method_name, name);
+ for (j = 0; j < len2; j++)
+ {
+ char *physname = TYPE_FN_FIELD_PHYSNAME (f, j);
+ int is_full_physname_constructor =
+ ((physname[0]=='_' && physname[1]=='_' &&
+ (isdigit(physname[2])
+ || physname[2]=='Q'
+ || physname[2]=='t'))
+ || (strncmp(physname, "__ct__", 6) == 0));
+
+ QUIT;
+ if (TYPE_FN_FIELD_PROTECTED (f, j))
+ {
+ if (section_type != s_protected)
+ {
+ section_type = s_protected;
+ fprintfi_filtered (level + 2, stream,
+ "protected:\n");
+ }
+ }
+ else if (TYPE_FN_FIELD_PRIVATE (f, j))
+ {
+ if (section_type != s_private)
+ {
+ section_type = s_private;
+ fprintfi_filtered (level + 2, stream, "private:\n");
+ }
+ }
+ else
+ {
+ if (section_type != s_public)
+ {
+ section_type = s_public;
+ fprintfi_filtered (level + 2, stream, "public:\n");
+ }
+ }
+
+ print_spaces_filtered (level + 4, stream);
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ fprintf_filtered (stream, "virtual ");
+ else if (TYPE_FN_FIELD_STATIC_P (f, j))
+ fprintf_filtered (stream, "static ");
+ if (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)) == 0)
+ {
+ /* Keep GDB from crashing here. */
+ fprintf_unfiltered (stream, "<undefined type> %s;\n",
+ TYPE_FN_FIELD_PHYSNAME (f, j));
+ break;
+ }
+ else if (!is_constructor && !is_full_physname_constructor)
+ {
+ type_print (TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (f, j)),
+ "", stream, -1);
+ fputs_filtered (" ", stream);
+ }
+ if (TYPE_FN_FIELD_STUB (f, j))
+ {
+ /* Build something we can demangle. */
+ mangled_name = gdb_mangle_name (type, i, j);
+ demangled_name =
+ cplus_demangle (mangled_name,
+ DMGL_ANSI | DMGL_PARAMS);
+ if (demangled_name == NULL)
+ fprintf_filtered (stream, "<badly mangled name %s>",
+ mangled_name);
+ else
+ {
+ char *demangled_no_class =
+ strchr (demangled_name, ':');
+
+ if (demangled_no_class == NULL)
+ demangled_no_class = demangled_name;
+ else
+ {
+ if (*++demangled_no_class == ':')
+ ++demangled_no_class;
+ }
+ fputs_filtered (demangled_no_class, stream);
+ free (demangled_name);
+ }
+ free (mangled_name);
+ }
+ else if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+ && is_cplus_marker (TYPE_FN_FIELD_PHYSNAME (f, j)[1]))
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1,
+ "~", method_name, 0, stream);
+ else
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "",
+ method_name,
+ TYPE_FN_FIELD_STATIC_P (f, j),
+ stream);
+
+ fprintf_filtered (stream, ";\n");
+ }
+ }
+
+ fprintfi_filtered (level, stream, "}");
+ }
+ break;
+
+ case TYPE_CODE_ENUM:
+ fprintf_filtered (stream, "enum ");
+ if (TYPE_TAG_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_TAG_NAME (type), stream);
+ if (show > 0)
+ fputs_filtered (" ", stream);
+ }
+
+ wrap_here (" ");
+ 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 || TYPE_TAG_NAME (type) == NULL)
+ {
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ lastval = 0;
+ 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:
+ fprintf_filtered (stream, "void");
+ break;
+
+ case TYPE_CODE_UNDEF:
+ fprintf_filtered (stream, "struct <unknown>");
+ break;
+
+ case TYPE_CODE_ERROR:
+ fprintf_filtered (stream, "<unknown type>");
+ break;
+
+ case TYPE_CODE_RANGE:
+ /* This should not occur */
+ fprintf_filtered (stream, "<range type>");
+ break;
+
+ default:
+ /* Handle types not explicitly handled by the other cases,
+ such as fundamental types. For these, just print whatever
+ the type name is, as recorded in the type itself. If there
+ is no type name, then complain. */
+ if (TYPE_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ }
+ else
+ {
+ /* At least for dump_symtab, it is important that this not be
+ an error (). */
+ fprintf_filtered (stream, "<invalid type code %d>",
+ TYPE_CODE (type));
+ }
+ break;
+ }
+}
+
diff --git a/contrib/gdb/gdb/c-valprint.c b/contrib/gdb/gdb/c-valprint.c
new file mode 100644
index 0000000..a16f87c
--- /dev/null
+++ b/contrib/gdb/gdb/c-valprint.c
@@ -0,0 +1,469 @@
+/* Support for printing C values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "demangle.h"
+#include "valprint.h"
+#include "language.h"
+#include "c-lang.h"
+
+
+/* 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
+ target byte order.
+
+ If the data are a string pointer, returns the number of string characters
+ printed.
+
+ If DEREF_REF is nonzero, then dereference references, otherwise just print
+ them like pointers.
+
+ The PRETTY parameter controls prettyprinting. */
+
+int
+c_val_print (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;
+{
+ register unsigned int i = 0; /* Number of characters printed */
+ unsigned len;
+ struct type *elttype;
+ unsigned eltlen;
+ LONGEST val;
+ CORE_ADDR addr;
+
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ {
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ eltlen = TYPE_LENGTH (elttype);
+ len = TYPE_LENGTH (type) / eltlen;
+ if (prettyprint_arrays)
+ {
+ 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)
+ || ((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;
+ }
+ else
+ {
+ fprintf_filtered (stream, "{");
+ /* If this is a virtual function table, print the 0th
+ entry specially, and the rest of the members normally. */
+ if (cp_is_vtbl_ptr_type (elttype))
+ {
+ i = 1;
+ fprintf_filtered (stream, "%d vtable entries", len - 1);
+ }
+ else
+ {
+ i = 0;
+ }
+ val_print_array_elements (type, valaddr, address, stream,
+ format, deref_ref, recurse, pretty, i);
+ fprintf_filtered (stream, "}");
+ }
+ break;
+ }
+ /* Array of unspecified length: treat like pointer to first elt. */
+ addr = address;
+ goto print_unpacked_pointer;
+
+ case TYPE_CODE_PTR:
+ if (format && format != 's')
+ {
+ 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;
+ }
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_CODE (elttype) == TYPE_CODE_METHOD)
+ {
+ cp_print_class_method (valaddr, type, stream);
+ }
+ else if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
+ {
+ cp_print_class_member (valaddr,
+ TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (type)),
+ stream, "&");
+ }
+ else
+ {
+ addr = unpack_pointer (type, valaddr);
+ print_unpacked_pointer:
+
+ if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
+ {
+ /* Try to print what function it points to. */
+ print_address_demangle (addr, stream, demangle);
+ /* Return value is irrelevant except for string pointers. */
+ return (0);
+ }
+
+ if (addressprint && format != 's')
+ {
+ print_address_numeric (addr, 1, stream);
+ }
+
+ /* For a pointer to char or unsigned char, also print the string
+ pointed to, unless pointer is null. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && (format == 0 || format == 's')
+ && addr != 0)
+ {
+ i = val_print_string (addr, 0, stream);
+ }
+ else if (cp_is_vtbl_member(type))
+ {
+ /* print vtbl's nicely */
+ CORE_ADDR vt_address = unpack_pointer (type, valaddr);
+
+ struct minimal_symbol *msymbol =
+ lookup_minimal_symbol_by_pc (vt_address);
+ if ((msymbol != NULL) &&
+ (vt_address == SYMBOL_VALUE_ADDRESS (msymbol)))
+ {
+ fputs_filtered (" <", stream);
+ fputs_filtered (SYMBOL_SOURCE_NAME (msymbol), stream);
+ fputs_filtered (">", stream);
+ }
+ if (vt_address && vtblprint)
+ {
+ 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;
+
+ if (msymbol != NULL)
+ wsym = lookup_symbol (SYMBOL_NAME(msymbol), block,
+ VAR_NAMESPACE, &is_this_fld, &s);
+
+ if (wsym)
+ {
+ wtype = SYMBOL_TYPE(wsym);
+ }
+ else
+ {
+ wtype = TYPE_TARGET_TYPE(type);
+ }
+ vt_val = value_at (wtype, vt_address);
+ val_print (VALUE_TYPE (vt_val), VALUE_CONTENTS (vt_val),
+ VALUE_ADDRESS (vt_val), stream, format,
+ deref_ref, recurse + 1, pretty);
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ }
+ }
+
+ /* 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;
+
+ case TYPE_CODE_MEMBER:
+ error ("not implemented: member type in c_val_print");
+ break;
+
+ case TYPE_CODE_REF:
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_CODE (elttype) == TYPE_CODE_MEMBER)
+ {
+ cp_print_class_member (valaddr,
+ TYPE_DOMAIN_TYPE (elttype),
+ stream, "");
+ break;
+ }
+ if (addressprint)
+ {
+ fprintf_filtered (stream, "@");
+ print_address_numeric
+ (extract_address (valaddr,
+ TARGET_PTR_BIT / HOST_CHAR_BIT), 1, stream);
+ if (deref_ref)
+ fputs_filtered (": ", stream);
+ }
+ /* De-reference the reference. */
+ if (deref_ref)
+ {
+ if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
+ {
+ value_ptr deref_val =
+ value_at
+ (TYPE_TARGET_TYPE (type),
+ unpack_pointer (lookup_pointer_type (builtin_type_void),
+ valaddr));
+ val_print (VALUE_TYPE (deref_val),
+ VALUE_CONTENTS (deref_val),
+ VALUE_ADDRESS (deref_val), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ else
+ fputs_filtered ("???", stream);
+ }
+ break;
+
+ case TYPE_CODE_UNION:
+ if (recurse && !unionprint)
+ {
+ fprintf_filtered (stream, "{...}");
+ break;
+ }
+ /* Fall through. */
+ case TYPE_CODE_STRUCT:
+ 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);
+ }
+ else
+ cp_print_value_fields (type, valaddr, address, stream, format,
+ recurse, pretty, NULL, 0);
+ break;
+
+ case TYPE_CODE_ENUM:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ len = TYPE_NFIELDS (type);
+ val = unpack_long (type, valaddr);
+ for (i = 0; i < len; i++)
+ {
+ QUIT;
+ if (val == TYPE_FIELD_BITPOS (type, i))
+ {
+ break;
+ }
+ }
+ if (i < len)
+ {
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ }
+ else
+ {
+ print_longest (stream, 'd', 0, val);
+ }
+ break;
+
+ case TYPE_CODE_FUNC:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ /* FIXME, we should consider, at least for ANSI C language, eliminating
+ the distinction made between FUNCs and POINTERs to FUNCs. */
+ fprintf_filtered (stream, "{");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, "} ");
+ /* Try to print what function it points to, and its address. */
+ print_address_demangle (address, stream, demangle);
+ break;
+
+ case TYPE_CODE_BOOL:
+ format = format ? format : output_format;
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ {
+ val = unpack_long (type, valaddr);
+ if (val == 0)
+ fputs_filtered ("false", stream);
+ else if (val == 1)
+ fputs_filtered ("true", stream);
+ else
+ print_longest (stream, 'd', 0, val);
+ }
+ break;
+
+ 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)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ val_print_type_code_int (type, valaddr, stream);
+ /* C and C++ has no single byte int type, char is used instead.
+ Since we don't know whether the value is really intended to
+ be used as an integer or a character, print the character
+ equivalent as well. */
+ if (TYPE_LENGTH (type) == 1)
+ {
+ fputs_filtered (" ", stream);
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
+ stream);
+ }
+ }
+ break;
+
+ case TYPE_CODE_CHAR:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ fprintf_filtered (stream, TYPE_UNSIGNED (type) ? "%u" : "%d",
+ unpack_long (type, valaddr));
+ fputs_filtered (" ", stream);
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr), stream);
+ }
+ break;
+
+ case TYPE_CODE_FLT:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ print_floating (valaddr, type, stream);
+ }
+ break;
+
+ case TYPE_CODE_VOID:
+ fprintf_filtered (stream, "void");
+ break;
+
+ case TYPE_CODE_ERROR:
+ fprintf_filtered (stream, "<error type>");
+ 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"
+ and no complete type for struct foo in that file. */
+ fprintf_filtered (stream, "<incomplete type>");
+ break;
+
+ default:
+ error ("Invalid C/C++ type code %d in symbol table.", TYPE_CODE (type));
+ }
+ 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;
+{
+ 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_NAME (type) == NULL &&
+ TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL &&
+ STREQ (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char"))
+ {
+ /* 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/contrib/gdb/gdb/call-cmds.h b/contrib/gdb/gdb/call-cmds.h
new file mode 100644
index 0000000..4c02004
--- /dev/null
+++ b/contrib/gdb/gdb/call-cmds.h
@@ -0,0 +1,28 @@
+/* Prototypes for GDB commands that are called internally by other functions.
+ Copyright 1992 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern void
+initialize_all_files PARAMS ((void));
+
+extern void
+exec_file_command PARAMS ((char *, int));
+
+extern void
+core_file_command PARAMS ((char *, int));
+
+extern void
+break_command PARAMS ((char *, int));
diff --git a/contrib/gdb/gdb/callback.c b/contrib/gdb/gdb/callback.c
new file mode 100644
index 0000000..d59ecda
--- /dev/null
+++ b/contrib/gdb/gdb/callback.c
@@ -0,0 +1,349 @@
+/* Host callback routines for GDB.
+ Copyright 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file provides a standard way for targets to talk to the host OS
+ level.
+
+ This interface will probably need a bit more banging to make it
+ smooth. Currently the simulator uses this file to provide the
+ callbacks for itself when it's built standalone, which is rather
+ ugly. */
+
+#ifndef INSIDE_SIMULATOR
+#include "defs.h"
+#endif
+
+#include "ansidecl.h"
+#include "callback.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+
+
+
+/* Set the callback copy of errno from what we see now. */
+static int
+wrap (p, val)
+ host_callback *p;
+ int val;
+{
+ p->last_errno = errno;
+ return val;
+}
+
+/* Make sure the FD provided is ok. If not, return non-zero
+ and set errno. */
+
+static int
+fdbad (p, fd)
+ host_callback *p;
+ int fd;
+{
+ if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd])
+ {
+ p->last_errno = EINVAL;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+fdmap (p, fd)
+ host_callback *p;
+ int fd;
+{
+ return p->fdmap[fd];
+}
+
+int
+os_close (p, fd)
+ host_callback *p;
+ int fd;
+{
+ int result;
+
+ result = fdbad (p, fd);
+ if (result)
+ return result;
+ result = wrap (p, close (fdmap (p, fd)));
+ return result;
+}
+
+int
+os_get_errno (p)
+ host_callback *p;
+{
+ /* !!! fixme, translate from host to taget errno value */
+ return p->last_errno;
+}
+
+
+int
+os_isatty (p, fd)
+ host_callback *p;
+ int fd;
+{
+ int result;
+
+ result = fdbad (p, fd);
+ if (result)
+ return result;
+ result = wrap (p, isatty (fdmap (fd)));
+ return result;
+}
+
+int
+os_lseek (p, fd, off, way)
+ host_callback *p;
+ int fd;
+ long off;
+ int way;
+{
+ int result;
+
+ result = fdbad (p, fd);
+ if (result)
+ return result;
+ result = lseek (fdmap (p, fd), off, way);
+ return result;
+}
+
+int
+os_open (p, name, flags)
+ host_callback *p;
+ const char *name;
+ int flags;
+{
+ int i;
+ for (i = 0; i < MAX_CALLBACK_FDS; i++)
+ {
+ if (!p->fdopen[i])
+ {
+ int f = open (name, flags);
+ if (f < 0)
+ {
+ p->last_errno = errno;
+ return f;
+ }
+ p->fdopen[i] = 1;
+ p->fdmap[i] = f;
+ return i;
+ }
+ }
+ p->last_errno = EMFILE;
+ return -1;
+}
+
+int
+os_read (p, fd, buf, len)
+ host_callback *p;
+ int fd;
+ char *buf;
+ int len;
+{
+ int result;
+
+ result = fdbad (p, fd);
+ if (result)
+ return result;
+ result = wrap (p, read (fdmap (p, fd), buf, len));
+ return result;
+}
+
+int
+os_read_stdin (p, buf, len)
+ host_callback *p;
+ char *buf;
+ int len;
+{
+ return wrap (p, read (0, buf, len));
+}
+
+int
+os_write (p, fd, buf, len)
+ host_callback *p;
+ int fd;
+ const char *buf;
+ int len;
+{
+ int result;
+
+ result = fdbad (p, fd);
+ if (result)
+ return result;
+ result = wrap (p, write (fdmap (p, fd), buf, len));
+ return result;
+}
+
+/* ignore the grossness of INSIDE_SIMULATOR, it will go away one day. */
+int
+os_write_stdout (p, buf, len)
+ host_callback *p;
+ const char *buf;
+ int len;
+{
+#ifdef INSIDE_SIMULATOR
+ return os_write (p, 1, buf, len);
+#else
+ int i;
+ char b[2];
+ for (i = 0; i< len; i++)
+ {
+ b[0] = buf[i];
+ b[1] = 0;
+ if (target_output_hook)
+ target_output_hook (b);
+ else
+ fputs_filtered (b, gdb_stdout);
+ }
+ return len;
+#endif
+}
+
+int
+os_rename (p, f1, f2)
+ host_callback *p;
+ const char *f1;
+ const char *f2;
+{
+ return wrap (p, rename (f1, f2));
+}
+
+
+int
+os_system (p, s)
+ host_callback *p;
+ const char *s;
+{
+ return wrap (p, system (s));
+}
+
+long
+os_time (p, t)
+ host_callback *p;
+ long *t;
+{
+ return wrap (p, time (t));
+}
+
+
+int
+os_unlink (p, f1)
+ host_callback *p;
+ const char *f1;
+{
+ return wrap (p, unlink (f1));
+}
+
+
+int
+os_shutdown (p)
+host_callback *p;
+{
+ int i;
+ for (i = 0; i < MAX_CALLBACK_FDS; i++)
+ {
+ if (p->fdopen[i] && !p->alwaysopen[i]) {
+ close (p->fdmap[i]);
+ p->fdopen[i] = 0;
+ }
+ }
+ return 1;
+}
+
+int os_init(p)
+host_callback *p;
+{
+ int i;
+ os_shutdown (p);
+ for (i= 0; i < 3; i++)
+ {
+ p->fdmap[i] = i;
+ p->fdopen[i] = 1;
+ p->alwaysopen[i] = 1;
+ }
+ return 1;
+}
+
+
+/* !!fixme!!
+ This bit is ugly. When the interface has settled down I'll
+ move the whole file into sim/common and remove this bit. */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+os_printf_filtered (host_callback *p, const char *format, ...)
+#else
+os_printf_filtered (p, va_alist)
+ host_callback *p;
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+
+#ifdef INSIDE_SIMULATOR
+ vprintf (format, args);
+#else
+ vfprintf_filtered (stdout, format, args);
+#endif
+
+ va_end (args);
+}
+
+host_callback default_callback =
+{
+ os_close,
+ os_get_errno,
+ os_isatty,
+ os_lseek,
+ os_open,
+ os_read,
+ os_read_stdin,
+ os_rename,
+ os_system,
+ os_time,
+ os_unlink,
+ os_write,
+ os_write_stdout,
+
+ os_shutdown,
+ os_init,
+
+ os_printf_filtered,
+
+ 0, /* last errno */
+};
diff --git a/contrib/gdb/gdb/callback.h b/contrib/gdb/gdb/callback.h
new file mode 100644
index 0000000..b97c3b2
--- /dev/null
+++ b/contrib/gdb/gdb/callback.h
@@ -0,0 +1,41 @@
+#ifndef CALLBACK_H
+#define CALLBACK_H
+typedef struct host_callback_struct host_callback;
+
+#define MAX_CALLBACK_FDS 10
+
+struct host_callback_struct
+{
+ int (*close) PARAMS ((host_callback *,int));
+ int (*get_errno) PARAMS ((host_callback *));
+ int (*isatty) PARAMS ((host_callback *, int));
+ int (*lseek) PARAMS ((host_callback *, int, long , int));
+ int (*open) PARAMS ((host_callback *, const char*, int mode));
+ int (*read) PARAMS ((host_callback *,int, char *, int));
+ int (*read_stdin) PARAMS (( host_callback *, char *, int));
+ int (*rename) PARAMS ((host_callback *, const char *, const char *));
+ int (*system) PARAMS ((host_callback *, const char *));
+ long (*time) PARAMS ((host_callback *, long *));
+ int (*unlink) PARAMS ((host_callback *, const char *));
+ int (*write) PARAMS ((host_callback *,int, const char *, int));
+ int (*write_stdout) PARAMS ((host_callback *, const char *, int));
+
+
+ /* Used when the target has gone away, so we can close open
+ handles and free memory etc etc. */
+ int (*shutdown) PARAMS ((host_callback *));
+ int (*init) PARAMS ((host_callback *));
+
+ /* Talk to the user on a console. */
+ void (*printf_filtered) PARAMS ((host_callback *, const char *, ...));
+
+ int last_errno; /* host format */
+
+ int fdmap[MAX_CALLBACK_FDS];
+ char fdopen[MAX_CALLBACK_FDS];
+ char alwaysopen[MAX_CALLBACK_FDS];
+};
+#endif
+
+
+extern host_callback default_callback;
diff --git a/contrib/gdb/gdb/ch-exp.c b/contrib/gdb/gdb/ch-exp.c
new file mode 100644
index 0000000..f6f522a
--- /dev/null
+++ b/contrib/gdb/gdb/ch-exp.c
@@ -0,0 +1,2090 @@
+/* Parser for GNU CHILL (CCITT High-Level Language) -*- C -*-
+ Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Parse a Chill expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result.
+
+ Note that the language accepted by this parser is more liberal
+ than the one accepted by an actual Chill compiler. For example, the
+ language rule that a simple name string can not be one of the reserved
+ simple name strings is not enforced (e.g "case" is not treated as a
+ reserved name). Another example is that Chill is a strongly typed
+ language, and certain expressions that violate the type constraints
+ may still be evaluated if gdb can do so in a meaningful manner, while
+ such expressions would be rejected by the compiler. The reason for
+ this more liberal behavior is the philosophy that the debugger
+ is intended to be a tool that is used by the programmer when things
+ go wrong, and as such, it should provide as few artificial barriers
+ to it's use as possible. If it can do something meaningful, even
+ something that violates language contraints that are enforced by the
+ compiler, it should do so without complaint.
+
+ */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include "expression.h"
+#include "language.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "ch-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+typedef union
+
+ {
+ LONGEST lval;
+ unsigned LONGEST ulval;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val;
+ double dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ }YYSTYPE;
+
+enum ch_terminal {
+ END_TOKEN = 0,
+ /* '\001' ... '\xff' come first. */
+ OPEN_PAREN = '(',
+ TOKEN_NOT_READ = 999,
+ INTEGER_LITERAL,
+ BOOLEAN_LITERAL,
+ CHARACTER_LITERAL,
+ FLOAT_LITERAL,
+ GENERAL_PROCEDURE_NAME,
+ LOCATION_NAME,
+ EMPTINESS_LITERAL,
+ CHARACTER_STRING_LITERAL,
+ BIT_STRING_LITERAL,
+ TYPENAME,
+ FIELD_NAME,
+ CASE,
+ OF,
+ ESAC,
+ LOGIOR,
+ ORIF,
+ LOGXOR,
+ LOGAND,
+ ANDIF,
+ NOTEQUAL,
+ GEQ,
+ LEQ,
+ IN,
+ SLASH_SLASH,
+ MOD,
+ REM,
+ NOT,
+ POINTER,
+ RECEIVE,
+ UP,
+ IF,
+ THEN,
+ ELSE,
+ FI,
+ ELSIF,
+ ILLEGAL_TOKEN,
+ NUM,
+ PRED,
+ SUCC,
+ ABS,
+ CARD,
+ MAX_TOKEN,
+ MIN_TOKEN,
+ ADDR_TOKEN,
+ SIZE,
+ UPPER,
+ LOWER,
+ LENGTH,
+ ARRAY,
+ GDB_VARIABLE,
+ GDB_ASSIGNMENT
+};
+
+/* Forward declarations. */
+static void parse_expr ();
+static void parse_primval ();
+static void parse_untyped_expr ();
+static int parse_opt_untyped_expr ();
+static void parse_if_expression_body PARAMS((void));
+static void write_lower_upper_value PARAMS ((enum exp_opcode, struct type *));
+static enum ch_terminal ch_lex ();
+
+#define MAX_LOOK_AHEAD 2
+static enum ch_terminal terminal_buffer[MAX_LOOK_AHEAD+1] = {
+ TOKEN_NOT_READ, TOKEN_NOT_READ, TOKEN_NOT_READ};
+static YYSTYPE yylval;
+static YYSTYPE val_buffer[MAX_LOOK_AHEAD+1];
+
+/*int current_token, lookahead_token;*/
+
+#ifdef __GNUC__
+__inline__
+#endif
+static enum ch_terminal
+PEEK_TOKEN()
+{
+ if (terminal_buffer[0] == TOKEN_NOT_READ)
+ {
+ terminal_buffer[0] = ch_lex ();
+ val_buffer[0] = yylval;
+ }
+ return terminal_buffer[0];
+}
+#define PEEK_LVAL() val_buffer[0]
+#define PEEK_TOKEN1() peek_token_(1)
+#define PEEK_TOKEN2() peek_token_(2)
+static enum ch_terminal
+peek_token_ (i)
+ int i;
+{
+ if (i > MAX_LOOK_AHEAD)
+ fatal ("internal error - too much lookahead");
+ if (terminal_buffer[i] == TOKEN_NOT_READ)
+ {
+ terminal_buffer[i] = ch_lex ();
+ val_buffer[i] = yylval;
+ }
+ return terminal_buffer[i];
+}
+
+#if 0
+
+static void
+pushback_token (code, node)
+ enum ch_terminal code;
+ YYSTYPE node;
+{
+ int i;
+ if (terminal_buffer[MAX_LOOK_AHEAD] != TOKEN_NOT_READ)
+ fatal ("internal error - cannot pushback token");
+ for (i = MAX_LOOK_AHEAD; i > 0; i--)
+ {
+ terminal_buffer[i] = terminal_buffer[i - 1];
+ val_buffer[i] = val_buffer[i - 1];
+ }
+ terminal_buffer[0] = code;
+ val_buffer[0] = node;
+}
+
+#endif
+
+static void
+forward_token_()
+{
+ int i;
+ for (i = 0; i < MAX_LOOK_AHEAD; i++)
+ {
+ terminal_buffer[i] = terminal_buffer[i+1];
+ val_buffer[i] = val_buffer[i+1];
+ }
+ terminal_buffer[MAX_LOOK_AHEAD] = TOKEN_NOT_READ;
+}
+#define FORWARD_TOKEN() forward_token_()
+
+/* Skip the next token.
+ if it isn't TOKEN, the parser is broken. */
+
+void
+require(token)
+ enum ch_terminal token;
+{
+ if (PEEK_TOKEN() != token)
+ {
+ char buf[80];
+ sprintf (buf, "internal parser error - expected token %d", (int)token);
+ fatal(buf);
+ }
+ FORWARD_TOKEN();
+}
+
+int
+check_token (token)
+ enum ch_terminal token;
+{
+ if (PEEK_TOKEN() != token)
+ return 0;
+ FORWARD_TOKEN ();
+ return 1;
+}
+
+/* return 0 if expected token was not found,
+ else return 1.
+*/
+int
+expect(token, message)
+ enum ch_terminal token;
+ char *message;
+{
+ if (PEEK_TOKEN() != token)
+ {
+ if (message)
+ error (message);
+ else if (token < 256)
+ error ("syntax error - expected a '%c' here \"%s\"", token, lexptr);
+ else
+ error ("syntax error");
+ return 0;
+ }
+ else
+ FORWARD_TOKEN();
+ return 1;
+}
+
+#if 0
+static tree
+parse_opt_name_string (allow_all)
+ int allow_all; /* 1 if ALL is allowed as a postfix */
+{
+ int token = PEEK_TOKEN();
+ tree name;
+ if (token != NAME)
+ {
+ if (token == ALL && allow_all)
+ {
+ FORWARD_TOKEN ();
+ return ALL_POSTFIX;
+ }
+ return NULL_TREE;
+ }
+ name = PEEK_LVAL();
+ for (;;)
+ {
+ FORWARD_TOKEN ();
+ token = PEEK_TOKEN();
+ if (token != '!')
+ return name;
+ FORWARD_TOKEN();
+ token = PEEK_TOKEN();
+ if (token == ALL && allow_all)
+ return get_identifier3(IDENTIFIER_POINTER (name), "!", "*");
+ if (token != NAME)
+ {
+ if (pass == 1)
+ error ("'%s!' is not followed by an identifier",
+ IDENTIFIER_POINTER (name));
+ return name;
+ }
+ name = get_identifier3(IDENTIFIER_POINTER(name),
+ "!", IDENTIFIER_POINTER(PEEK_LVAL()));
+ }
+}
+
+static tree
+parse_simple_name_string ()
+{
+ int token = PEEK_TOKEN();
+ tree name;
+ if (token != NAME)
+ {
+ error ("expected a name here");
+ return error_mark_node;
+ }
+ name = PEEK_LVAL ();
+ FORWARD_TOKEN ();
+ return name;
+}
+
+static tree
+parse_name_string ()
+{
+ tree name = parse_opt_name_string (0);
+ if (name)
+ return name;
+ if (pass == 1)
+ error ("expected a name string here");
+ return error_mark_node;
+}
+
+/* Matches: <name_string>
+ Returns if pass 1: the identifier.
+ Returns if pass 2: a decl or value for identifier. */
+
+static tree
+parse_name ()
+{
+ tree name = parse_name_string ();
+ if (pass == 1 || ignoring)
+ return name;
+ else
+ {
+ tree decl = lookup_name (name);
+ if (decl == NULL_TREE)
+ {
+ error ("`%s' undeclared", IDENTIFIER_POINTER (name));
+ return error_mark_node;
+ }
+ else if (TREE_CODE (TREE_TYPE (decl)) == ERROR_MARK)
+ return error_mark_node;
+ else if (TREE_CODE (decl) == CONST_DECL)
+ return DECL_INITIAL (decl);
+ else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+ return convert_from_reference (decl);
+ else
+ return decl;
+ }
+}
+#endif
+
+#if 0
+static void
+pushback_paren_expr (expr)
+ tree expr;
+{
+ if (pass == 1 && !ignoring)
+ expr = build1 (PAREN_EXPR, NULL_TREE, expr);
+ pushback_token (EXPR, expr);
+}
+#endif
+
+/* Matches: <case label> */
+
+static void
+parse_case_label ()
+{
+ if (check_token (ELSE))
+ error ("ELSE in tuples labels not implemented");
+ /* Does not handle the case of a mode name. FIXME */
+ parse_expr ();
+ if (check_token (':'))
+ {
+ parse_expr ();
+ write_exp_elt_opcode (BINOP_RANGE);
+ }
+}
+
+static int
+parse_opt_untyped_expr ()
+{
+ switch (PEEK_TOKEN ())
+ {
+ case ',':
+ case ':':
+ case ')':
+ return 0;
+ default:
+ parse_untyped_expr ();
+ return 1;
+ }
+}
+
+static void
+parse_unary_call ()
+{
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ parse_expr ();
+ expect (')', NULL);
+}
+
+/* Parse NAME '(' MODENAME ')'. */
+
+struct type *
+parse_mode_call ()
+{
+ struct type *type;
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ if (PEEK_TOKEN () != TYPENAME)
+ error ("expect MODENAME here `%s'", lexptr);
+ type = PEEK_LVAL().tsym.type;
+ FORWARD_TOKEN ();
+ expect (')', NULL);
+ return type;
+}
+
+struct type *
+parse_mode_or_normal_call ()
+{
+ struct type *type;
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ if (PEEK_TOKEN () == TYPENAME)
+ {
+ type = PEEK_LVAL().tsym.type;
+ FORWARD_TOKEN ();
+ }
+ else
+ {
+ parse_expr ();
+ type = NULL;
+ }
+ expect (')', NULL);
+ return type;
+}
+
+/* Parse something that looks like a function call.
+ Assume we have parsed the function, and are at the '('. */
+
+static void
+parse_call ()
+{
+ int arg_count;
+ require ('(');
+ /* This is to save the value of arglist_len
+ being accumulated for each dimension. */
+ start_arglist ();
+ if (parse_opt_untyped_expr ())
+ {
+ int tok = PEEK_TOKEN ();
+ arglist_len = 1;
+ if (tok == UP || tok == ':')
+ {
+ FORWARD_TOKEN ();
+ parse_expr ();
+ expect (')', "expected ')' to terminate slice");
+ end_arglist ();
+ write_exp_elt_opcode (tok == UP ? TERNOP_SLICE_COUNT
+ : TERNOP_SLICE);
+ return;
+ }
+ while (check_token (','))
+ {
+ parse_untyped_expr ();
+ arglist_len++;
+ }
+ }
+ else
+ arglist_len = 0;
+ expect (')', NULL);
+ arg_count = end_arglist ();
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst (arg_count);
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+}
+
+static void
+parse_named_record_element ()
+{
+ struct stoken label;
+
+ label = PEEK_LVAL ().sval;
+ expect (FIELD_NAME, "expected a field name here `%s'", lexptr);
+ if (check_token (','))
+ parse_named_record_element ();
+ else if (check_token (':'))
+ parse_expr ();
+ else
+ error ("syntax error near `%s' in named record tuple element", lexptr);
+ write_exp_elt_opcode (OP_LABELED);
+ write_exp_string (label);
+ write_exp_elt_opcode (OP_LABELED);
+}
+
+/* Returns one or nore TREE_LIST nodes, in reverse order. */
+
+static void
+parse_tuple_element ()
+{
+ if (PEEK_TOKEN () == FIELD_NAME)
+ {
+ /* Parse a labelled structure tuple. */
+ parse_named_record_element ();
+ return;
+ }
+
+ if (check_token ('('))
+ {
+ if (check_token ('*'))
+ {
+ expect (')', "missing ')' after '*' case label list");
+ error ("(*) not implemented in case label list");
+ }
+ else
+ {
+ parse_case_label ();
+ while (check_token (','))
+ {
+ parse_case_label ();
+ write_exp_elt_opcode (BINOP_COMMA);
+ }
+ expect (')', NULL);
+ }
+ }
+ else
+ parse_untyped_expr ();
+ if (check_token (':'))
+ {
+ /* A powerset range or a labeled Array. */
+ parse_untyped_expr ();
+ write_exp_elt_opcode (BINOP_RANGE);
+ }
+}
+
+/* Matches: a COMMA-separated list of tuple elements.
+ Returns a list (of TREE_LIST nodes). */
+static void
+parse_opt_element_list ()
+{
+ arglist_len = 0;
+ if (PEEK_TOKEN () == ']')
+ return;
+ for (;;)
+ {
+ parse_tuple_element ();
+ arglist_len++;
+ if (PEEK_TOKEN () == ']')
+ break;
+ if (!check_token (','))
+ error ("bad syntax in tuple");
+ }
+}
+
+/* Parses: '[' elements ']'
+ If modename is non-NULL it prefixed the tuple. */
+
+static void
+parse_tuple (mode)
+ struct type *mode;
+{
+ require ('[');
+ start_arglist ();
+ parse_opt_element_list ();
+ expect (']', "missing ']' after tuple");
+ write_exp_elt_opcode (OP_ARRAY);
+ write_exp_elt_longcst ((LONGEST) 0);
+ write_exp_elt_longcst ((LONGEST) end_arglist () - 1);
+ write_exp_elt_opcode (OP_ARRAY);
+ if (mode)
+ {
+ struct type *type = check_typedef (mode);
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_SET)
+ error ("invalid tuple mode");
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (mode);
+ write_exp_elt_opcode (UNOP_CAST);
+ }
+}
+
+static void
+parse_primval ()
+{
+ struct type *type;
+ enum exp_opcode op;
+ char *op_name;
+ switch (PEEK_TOKEN ())
+ {
+ case INTEGER_LITERAL:
+ case CHARACTER_LITERAL:
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (PEEK_LVAL ().typed_val.type);
+ write_exp_elt_longcst (PEEK_LVAL ().typed_val.val);
+ write_exp_elt_opcode (OP_LONG);
+ FORWARD_TOKEN ();
+ break;
+ case BOOLEAN_LITERAL:
+ write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) PEEK_LVAL ().ulval);
+ write_exp_elt_opcode (OP_BOOL);
+ FORWARD_TOKEN ();
+ break;
+ case FLOAT_LITERAL:
+ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_double);
+ write_exp_elt_dblcst (PEEK_LVAL ().dval);
+ write_exp_elt_opcode (OP_DOUBLE);
+ FORWARD_TOKEN ();
+ break;
+ case EMPTINESS_LITERAL:
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (lookup_pointer_type (builtin_type_void));
+ write_exp_elt_longcst (0);
+ write_exp_elt_opcode (OP_LONG);
+ FORWARD_TOKEN ();
+ break;
+ case CHARACTER_STRING_LITERAL:
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string (PEEK_LVAL ().sval);
+ write_exp_elt_opcode (OP_STRING);
+ FORWARD_TOKEN ();
+ break;
+ case BIT_STRING_LITERAL:
+ write_exp_elt_opcode (OP_BITSTRING);
+ write_exp_bitstring (PEEK_LVAL ().sval);
+ write_exp_elt_opcode (OP_BITSTRING);
+ FORWARD_TOKEN ();
+ break;
+ case ARRAY:
+ FORWARD_TOKEN ();
+ /* This is pseudo-Chill, similar to C's '(TYPE[])EXPR'
+ which casts to an artificial array. */
+ expect ('(', NULL);
+ expect (')', NULL);
+ if (PEEK_TOKEN () != TYPENAME)
+ error ("missing MODENAME after ARRAY()");
+ type = PEEK_LVAL().tsym.type;
+ FORWARD_TOKEN ();
+ expect ('(', NULL);
+ parse_expr ();
+ expect (')', "missing right parenthesis");
+ type = create_array_type ((struct type *) NULL, type,
+ create_range_type ((struct type *) NULL,
+ builtin_type_int, 0, 0));
+ TYPE_ARRAY_UPPER_BOUND_TYPE(type) = BOUND_CANNOT_BE_DETERMINED;
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (type);
+ write_exp_elt_opcode (UNOP_CAST);
+ break;
+#if 0
+ case CONST:
+ case EXPR:
+ val = PEEK_LVAL();
+ FORWARD_TOKEN ();
+ break;
+#endif
+ case '(':
+ FORWARD_TOKEN ();
+ parse_expr ();
+ expect (')', "missing right parenthesis");
+ break;
+ case '[':
+ parse_tuple (NULL);
+ break;
+ case GENERAL_PROCEDURE_NAME:
+ case LOCATION_NAME:
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (PEEK_LVAL ().ssym.sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ FORWARD_TOKEN ();
+ break;
+ case GDB_VARIABLE: /* gdb specific */
+ FORWARD_TOKEN ();
+ break;
+ case NUM:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_opcode (UNOP_CAST);
+ break;
+ case CARD:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CARD);
+ break;
+ case MAX_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CHMAX);
+ break;
+ case MIN_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_CHMIN);
+ break;
+ case PRED: op_name = "PRED"; goto unimplemented_unary_builtin;
+ case SUCC: op_name = "SUCC"; goto unimplemented_unary_builtin;
+ case ABS: op_name = "ABS"; goto unimplemented_unary_builtin;
+ unimplemented_unary_builtin:
+ parse_unary_call ();
+ error ("not implemented: %s builtin function", op_name);
+ break;
+ case ADDR_TOKEN:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_ADDR);
+ break;
+ case SIZE:
+ type = parse_mode_or_normal_call ();
+ if (type)
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ CHECK_TYPEDEF (type);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (type));
+ write_exp_elt_opcode (OP_LONG);
+ }
+ else
+ write_exp_elt_opcode (UNOP_SIZEOF);
+ break;
+ case LOWER:
+ op = UNOP_LOWER;
+ goto lower_upper;
+ case UPPER:
+ op = UNOP_UPPER;
+ goto lower_upper;
+ lower_upper:
+ type = parse_mode_or_normal_call ();
+ write_lower_upper_value (op, type);
+ break;
+ case LENGTH:
+ parse_unary_call ();
+ write_exp_elt_opcode (UNOP_LENGTH);
+ break;
+ case TYPENAME:
+ type = PEEK_LVAL ().tsym.type;
+ FORWARD_TOKEN ();
+ switch (PEEK_TOKEN())
+ {
+ case '[':
+ parse_tuple (type);
+ break;
+ case '(':
+ FORWARD_TOKEN ();
+ parse_expr ();
+ expect (')', "missing right parenthesis");
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (type);
+ write_exp_elt_opcode (UNOP_CAST);
+ break;
+ default:
+ error ("typename in invalid context");
+ }
+ break;
+
+ default:
+ error ("invalid expression syntax at `%s'", lexptr);
+ }
+ for (;;)
+ {
+ switch (PEEK_TOKEN ())
+ {
+ case FIELD_NAME:
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string (PEEK_LVAL ().sval);
+ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ FORWARD_TOKEN ();
+ continue;
+ case POINTER:
+ FORWARD_TOKEN ();
+ if (PEEK_TOKEN () == TYPENAME)
+ {
+ type = PEEK_LVAL ().tsym.type;
+ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (lookup_pointer_type (type));
+ write_exp_elt_opcode (UNOP_CAST);
+ FORWARD_TOKEN ();
+ }
+ write_exp_elt_opcode (UNOP_IND);
+ continue;
+ case OPEN_PAREN:
+ parse_call ();
+ continue;
+ case CHARACTER_STRING_LITERAL:
+ case CHARACTER_LITERAL:
+ case BIT_STRING_LITERAL:
+ /* Handle string repetition. (See comment in parse_operand5.) */
+ parse_primval ();
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst (1);
+ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ continue;
+ case END_TOKEN:
+ case TOKEN_NOT_READ:
+ case INTEGER_LITERAL:
+ case BOOLEAN_LITERAL:
+ case FLOAT_LITERAL:
+ case GENERAL_PROCEDURE_NAME:
+ case LOCATION_NAME:
+ case EMPTINESS_LITERAL:
+ case TYPENAME:
+ case CASE:
+ case OF:
+ case ESAC:
+ case LOGIOR:
+ case ORIF:
+ case LOGXOR:
+ case LOGAND:
+ case ANDIF:
+ case NOTEQUAL:
+ case GEQ:
+ case LEQ:
+ case IN:
+ case SLASH_SLASH:
+ case MOD:
+ case REM:
+ case NOT:
+ case RECEIVE:
+ case UP:
+ case IF:
+ case THEN:
+ case ELSE:
+ case FI:
+ case ELSIF:
+ case ILLEGAL_TOKEN:
+ case NUM:
+ case PRED:
+ case SUCC:
+ case ABS:
+ case CARD:
+ case MAX_TOKEN:
+ case MIN_TOKEN:
+ case ADDR_TOKEN:
+ case SIZE:
+ case UPPER:
+ case LOWER:
+ case LENGTH:
+ case ARRAY:
+ case GDB_VARIABLE:
+ case GDB_ASSIGNMENT:
+ break;
+ }
+ break;
+ }
+ return;
+}
+
+static void
+parse_operand6 ()
+{
+ if (check_token (RECEIVE))
+ {
+ parse_primval ();
+ error ("not implemented: RECEIVE expression");
+ }
+ else if (check_token (POINTER))
+ {
+ parse_primval ();
+ write_exp_elt_opcode (UNOP_ADDR);
+ }
+ else
+ parse_primval();
+}
+
+static void
+parse_operand5()
+{
+ enum exp_opcode op;
+ /* We are supposed to be looking for a <string repetition operator>,
+ but in general we can't distinguish that from a parenthesized
+ expression. This is especially difficult if we allow the
+ string operand to be a constant expression (as requested by
+ some users), and not just a string literal.
+ Consider: LPRN expr RPRN LPRN expr RPRN
+ Is that a function call or string repetition?
+ Instead, we handle string repetition in parse_primval,
+ and build_generalized_call. */
+ switch (PEEK_TOKEN())
+ {
+ case NOT: op = UNOP_LOGICAL_NOT; break;
+ case '-': op = UNOP_NEG; break;
+ default:
+ op = OP_NULL;
+ }
+ if (op != OP_NULL)
+ FORWARD_TOKEN();
+ parse_operand6();
+ if (op != OP_NULL)
+ write_exp_elt_opcode (op);
+}
+
+static void
+parse_operand4 ()
+{
+ enum exp_opcode op;
+ parse_operand5();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case '*': op = BINOP_MUL; break;
+ case '/': op = BINOP_DIV; break;
+ case MOD: op = BINOP_MOD; break;
+ case REM: op = BINOP_REM; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand5();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_operand3 ()
+{
+ enum exp_opcode op;
+ parse_operand4 ();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case '+': op = BINOP_ADD; break;
+ case '-': op = BINOP_SUB; break;
+ case SLASH_SLASH: op = BINOP_CONCAT; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand4();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_operand2 ()
+{
+ enum exp_opcode op;
+ parse_operand3 ();
+ for (;;)
+ {
+ if (check_token (IN))
+ {
+ parse_operand3();
+ write_exp_elt_opcode (BINOP_IN);
+ }
+ else
+ {
+ switch (PEEK_TOKEN())
+ {
+ case '>': op = BINOP_GTR; break;
+ case GEQ: op = BINOP_GEQ; break;
+ case '<': op = BINOP_LESS; break;
+ case LEQ: op = BINOP_LEQ; break;
+ case '=': op = BINOP_EQUAL; break;
+ case NOTEQUAL: op = BINOP_NOTEQUAL; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand3();
+ write_exp_elt_opcode (op);
+ }
+ }
+}
+
+static void
+parse_operand1 ()
+{
+ enum exp_opcode op;
+ parse_operand2 ();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case LOGAND: op = BINOP_BITWISE_AND; break;
+ case ANDIF: op = BINOP_LOGICAL_AND; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand2();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_operand0 ()
+{
+ enum exp_opcode op;
+ parse_operand1();
+ for (;;)
+ {
+ switch (PEEK_TOKEN())
+ {
+ case LOGIOR: op = BINOP_BITWISE_IOR; break;
+ case LOGXOR: op = BINOP_BITWISE_XOR; break;
+ case ORIF: op = BINOP_LOGICAL_OR; break;
+ default:
+ return;
+ }
+ FORWARD_TOKEN();
+ parse_operand1();
+ write_exp_elt_opcode (op);
+ }
+}
+
+static void
+parse_expr ()
+{
+ parse_operand0 ();
+ if (check_token (GDB_ASSIGNMENT))
+ {
+ parse_expr ();
+ write_exp_elt_opcode (BINOP_ASSIGN);
+ }
+}
+
+static void
+parse_then_alternative ()
+{
+ expect (THEN, "missing 'THEN' in 'IF' expression");
+ parse_expr ();
+}
+
+static void
+parse_else_alternative ()
+{
+ if (check_token (ELSIF))
+ parse_if_expression_body ();
+ else if (check_token (ELSE))
+ parse_expr ();
+ else
+ error ("missing ELSE/ELSIF in IF expression");
+}
+
+/* Matches: <boolean expression> <then alternative> <else alternative> */
+
+static void
+parse_if_expression_body ()
+{
+ parse_expr ();
+ parse_then_alternative ();
+ parse_else_alternative ();
+ write_exp_elt_opcode (TERNOP_COND);
+}
+
+static void
+parse_if_expression ()
+{
+ require (IF);
+ parse_if_expression_body ();
+ expect (FI, "missing 'FI' at end of conditional expression");
+}
+
+/* An <untyped_expr> is a superset of <expr>. It also includes
+ <conditional expressions> and untyped <tuples>, whose types
+ are not given by their constituents. Hence, these are only
+ allowed in certain contexts that expect a certain type.
+ You should call convert() to fix up the <untyped_expr>. */
+
+static void
+parse_untyped_expr ()
+{
+ switch (PEEK_TOKEN())
+ {
+ case IF:
+ parse_if_expression ();
+ return;
+ case CASE:
+ error ("not implemented: CASE expression");
+ case '(':
+ switch (PEEK_TOKEN1())
+ {
+ case IF:
+ case CASE:
+ goto skip_lprn;
+ case '[':
+ skip_lprn:
+ FORWARD_TOKEN ();
+ parse_untyped_expr ();
+ expect (')', "missing ')'");
+ return;
+ default: ;
+ /* fall through */
+ }
+ default:
+ parse_operand0 ();
+ }
+}
+
+int
+chill_parse ()
+{
+ terminal_buffer[0] = TOKEN_NOT_READ;
+ if (PEEK_TOKEN () == TYPENAME && PEEK_TOKEN1 () == END_TOKEN)
+ {
+ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(PEEK_LVAL ().tsym.type);
+ write_exp_elt_opcode(OP_TYPE);
+ FORWARD_TOKEN ();
+ }
+ else
+ parse_expr ();
+ if (terminal_buffer[0] != END_TOKEN)
+ {
+ if (comma_terminates && terminal_buffer[0] == ',')
+ lexptr--; /* Put the comma back. */
+ else
+ error ("Junk after end of expression.");
+ }
+ return 0;
+}
+
+
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. */
+
+static char *tempbuf; /* Current buffer contents */
+static int tempbufsize; /* Size of allocated buffer */
+static int tempbufindex; /* Current index into buffer */
+
+#define GROWBY_MIN_SIZE 64 /* Minimum amount to grow buffer by */
+
+#define CHECKBUF(size) \
+ do { \
+ if (tempbufindex + (size) >= tempbufsize) \
+ { \
+ growbuf_by_size (size); \
+ } \
+ } while (0);
+
+/* Grow the static temp buffer if necessary, including allocating the first one
+ on demand. */
+
+static void
+growbuf_by_size (count)
+ int count;
+{
+ int growby;
+
+ growby = max (count, GROWBY_MIN_SIZE);
+ tempbufsize += growby;
+ if (tempbuf == NULL)
+ {
+ tempbuf = (char *) xmalloc (tempbufsize);
+ }
+ else
+ {
+ tempbuf = (char *) xrealloc (tempbuf, tempbufsize);
+ }
+}
+
+/* Try to consume a simple name string token. If successful, returns
+ a pointer to a nullbyte terminated copy of the name that can be used
+ in symbol table lookups. If not successful, returns NULL. */
+
+static char *
+match_simple_name_string ()
+{
+ char *tokptr = lexptr;
+
+ if (isalpha (*tokptr) || *tokptr == '_')
+ {
+ char *result;
+ do {
+ tokptr++;
+ } while (isalnum (*tokptr) || (*tokptr == '_'));
+ yylval.sval.ptr = lexptr;
+ yylval.sval.length = tokptr - lexptr;
+ lexptr = tokptr;
+ result = copy_name (yylval.sval);
+ return result;
+ }
+ return (NULL);
+}
+
+/* Start looking for a value composed of valid digits as set by the base
+ in use. Note that '_' characters are valid anywhere, in any quantity,
+ and are simply ignored. Since we must find at least one valid digit,
+ or reject this token as an integer literal, we keep track of how many
+ digits we have encountered. */
+
+static int
+decode_integer_value (base, tokptrptr, ivalptr)
+ int base;
+ char **tokptrptr;
+ LONGEST *ivalptr;
+{
+ char *tokptr = *tokptrptr;
+ int temp;
+ int digits = 0;
+
+ while (*tokptr != '\0')
+ {
+ temp = *tokptr;
+ if (isupper (temp))
+ temp = tolower (temp);
+ tokptr++;
+ switch (temp)
+ {
+ case '_':
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ temp -= '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ temp -= 'a';
+ temp += 10;
+ break;
+ default:
+ temp = base;
+ break;
+ }
+ if (temp < base)
+ {
+ digits++;
+ *ivalptr *= base;
+ *ivalptr += temp;
+ }
+ else
+ {
+ /* Found something not in domain for current base. */
+ tokptr--; /* Unconsume what gave us indigestion. */
+ break;
+ }
+ }
+
+ /* If we didn't find any digits, then we don't have a valid integer
+ value, so reject the entire token. Otherwise, update the lexical
+ scan pointer, and return non-zero for success. */
+
+ if (digits == 0)
+ {
+ return (0);
+ }
+ else
+ {
+ *tokptrptr = tokptr;
+ return (1);
+ }
+}
+
+static int
+decode_integer_literal (valptr, tokptrptr)
+ LONGEST *valptr;
+ char **tokptrptr;
+{
+ char *tokptr = *tokptrptr;
+ int base = 0;
+ LONGEST ival = 0;
+ int explicit_base = 0;
+
+ /* Look for an explicit base specifier, which is optional. */
+
+ switch (*tokptr)
+ {
+ case 'd':
+ case 'D':
+ explicit_base++;
+ base = 10;
+ tokptr++;
+ break;
+ case 'b':
+ case 'B':
+ explicit_base++;
+ base = 2;
+ tokptr++;
+ break;
+ case 'h':
+ case 'H':
+ explicit_base++;
+ base = 16;
+ tokptr++;
+ break;
+ case 'o':
+ case 'O':
+ explicit_base++;
+ base = 8;
+ tokptr++;
+ break;
+ default:
+ base = 10;
+ break;
+ }
+
+ /* If we found an explicit base ensure that the character after the
+ explicit base is a single quote. */
+
+ if (explicit_base && (*tokptr++ != '\''))
+ {
+ return (0);
+ }
+
+ /* Attempt to decode whatever follows as an integer value in the
+ indicated base, updating the token pointer in the process and
+ computing the value into ival. Also, if we have an explicit
+ base, then the next character must not be a single quote, or we
+ have a bitstring literal, so reject the entire token in this case.
+ Otherwise, update the lexical scan pointer, and return non-zero
+ for success. */
+
+ if (!decode_integer_value (base, &tokptr, &ival))
+ {
+ return (0);
+ }
+ else if (explicit_base && (*tokptr == '\''))
+ {
+ return (0);
+ }
+ else
+ {
+ *valptr = ival;
+ *tokptrptr = tokptr;
+ return (1);
+ }
+}
+
+/* If it wasn't for the fact that floating point values can contain '_'
+ characters, we could just let strtod do all the hard work by letting it
+ try to consume as much of the current token buffer as possible and
+ find a legal conversion. Unfortunately we need to filter out the '_'
+ characters before calling strtod, which we do by copying the other
+ legal chars to a local buffer to be converted. However since we also
+ need to keep track of where the last unconsumed character in the input
+ buffer is, we have transfer only as many characters as may compose a
+ legal floating point value. */
+
+static enum ch_terminal
+match_float_literal ()
+{
+ char *tokptr = lexptr;
+ char *buf;
+ char *copy;
+ double dval;
+ extern double strtod ();
+
+ /* Make local buffer in which to build the string to convert. This is
+ required because underscores are valid in chill floating point numbers
+ but not in the string passed to strtod to convert. The string will be
+ no longer than our input string. */
+
+ copy = buf = (char *) alloca (strlen (tokptr) + 1);
+
+ /* Transfer all leading digits to the conversion buffer, discarding any
+ underscores. */
+
+ while (isdigit (*tokptr) || *tokptr == '_')
+ {
+ if (*tokptr != '_')
+ {
+ *copy++ = *tokptr;
+ }
+ tokptr++;
+ }
+
+ /* Now accept either a '.', or one of [eEdD]. Dot is legal regardless
+ of whether we found any leading digits, and we simply accept it and
+ continue on to look for the fractional part and/or exponent. One of
+ [eEdD] is legal only if we have seen digits, and means that there
+ is no fractional part. If we find neither of these, then this is
+ not a floating point number, so return failure. */
+
+ switch (*tokptr++)
+ {
+ case '.':
+ /* Accept and then look for fractional part and/or exponent. */
+ *copy++ = '.';
+ break;
+
+ case 'e':
+ case 'E':
+ case 'd':
+ case 'D':
+ if (copy == buf)
+ {
+ return (0);
+ }
+ *copy++ = 'e';
+ goto collect_exponent;
+ break;
+
+ default:
+ return (0);
+ break;
+ }
+
+ /* We found a '.', copy any fractional digits to the conversion buffer, up
+ to the first nondigit, non-underscore character. */
+
+ while (isdigit (*tokptr) || *tokptr == '_')
+ {
+ if (*tokptr != '_')
+ {
+ *copy++ = *tokptr;
+ }
+ tokptr++;
+ }
+
+ /* Look for an exponent, which must start with one of [eEdD]. If none
+ is found, jump directly to trying to convert what we have collected
+ so far. */
+
+ switch (*tokptr)
+ {
+ case 'e':
+ case 'E':
+ case 'd':
+ case 'D':
+ *copy++ = 'e';
+ tokptr++;
+ break;
+ default:
+ goto convert_float;
+ break;
+ }
+
+ /* Accept an optional '-' or '+' following one of [eEdD]. */
+
+ collect_exponent:
+ if (*tokptr == '+' || *tokptr == '-')
+ {
+ *copy++ = *tokptr++;
+ }
+
+ /* Now copy an exponent into the conversion buffer. Note that at the
+ moment underscores are *not* allowed in exponents. */
+
+ while (isdigit (*tokptr))
+ {
+ *copy++ = *tokptr++;
+ }
+
+ /* If we transfered any chars to the conversion buffer, try to interpret its
+ contents as a floating point value. If any characters remain, then we
+ must not have a valid floating point string. */
+
+ convert_float:
+ *copy = '\0';
+ if (copy != buf)
+ {
+ dval = strtod (buf, &copy);
+ if (*copy == '\0')
+ {
+ yylval.dval = dval;
+ lexptr = tokptr;
+ return (FLOAT_LITERAL);
+ }
+ }
+ return (0);
+}
+
+/* Recognize a string literal. A string literal is a sequence
+ of characters enclosed in matching single or double quotes, except that
+ a single character inside single quotes is a character literal, which
+ we reject as a string literal. To embed the terminator character inside
+ a string, it is simply doubled (I.E. "this""is""one""string") */
+
+static enum ch_terminal
+match_string_literal ()
+{
+ char *tokptr = lexptr;
+ int in_ctrlseq = 0;
+ LONGEST ival;
+
+ for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+ {
+ CHECKBUF (1);
+ tryagain: ;
+ if (in_ctrlseq)
+ {
+ /* skip possible whitespaces */
+ while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+ tokptr++;
+ if (*tokptr == ')')
+ {
+ in_ctrlseq = 0;
+ tokptr++;
+ goto tryagain;
+ }
+ else if (*tokptr != ',')
+ error ("Invalid control sequence");
+ tokptr++;
+ /* skip possible whitespaces */
+ while ((*tokptr == ' ' || *tokptr == '\t') && *tokptr)
+ tokptr++;
+ if (!decode_integer_literal (&ival, &tokptr))
+ error ("Invalid control sequence");
+ tokptr--;
+ }
+ else if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ {
+ ival = *tokptr++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else if (*tokptr == '^')
+ {
+ if (*(tokptr + 1) == '(')
+ {
+ in_ctrlseq = 1;
+ tokptr += 2;
+ if (!decode_integer_literal (&ival, &tokptr))
+ error ("Invalid control sequence");
+ tokptr--;
+ }
+ else if (*(tokptr + 1) == '^')
+ ival = *tokptr++;
+ else
+ error ("Invalid control sequence");
+ }
+ else
+ ival = *tokptr;
+ tempbuf[tempbufindex++] = ival;
+ }
+ if (in_ctrlseq)
+ error ("Invalid control sequence");
+
+ if (*tokptr == '\0' /* no terminator */
+ || (tempbufindex == 1 && *tokptr == '\'')) /* char literal */
+ {
+ return (0);
+ }
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return (CHARACTER_STRING_LITERAL);
+ }
+}
+
+/* Recognize a character literal. A character literal is single character
+ or a control sequence, enclosed in single quotes. A control sequence
+ is a comma separated list of one or more integer literals, enclosed
+ in parenthesis and introduced with a circumflex character.
+
+ EX: 'a' '^(7)' '^(7,8)'
+
+ As a GNU chill extension, the syntax C'xx' is also recognized as a
+ character literal, where xx is a hex value for the character.
+
+ Note that more than a single character, enclosed in single quotes, is
+ a string literal.
+
+ Returns CHARACTER_LITERAL if a match is found.
+ */
+
+static enum ch_terminal
+match_character_literal ()
+{
+ char *tokptr = lexptr;
+ LONGEST ival = 0;
+
+ if ((*tokptr == 'c' || *tokptr == 'C') && (*(tokptr + 1) == '\''))
+ {
+ /* We have a GNU chill extension form, so skip the leading "C'",
+ decode the hex value, and then ensure that we have a trailing
+ single quote character. */
+ tokptr += 2;
+ if (!decode_integer_value (16, &tokptr, &ival) || (*tokptr != '\''))
+ {
+ return (0);
+ }
+ tokptr++;
+ }
+ else if (*tokptr == '\'')
+ {
+ tokptr++;
+
+ /* Determine which form we have, either a control sequence or the
+ single character form. */
+
+ if (*tokptr == '^')
+ {
+ if (*(tokptr + 1) == '(')
+ {
+ /* Match and decode a control sequence. Return zero if we don't
+ find a valid integer literal, or if the next unconsumed character
+ after the integer literal is not the trailing ')'. */
+ tokptr += 2;
+ if (!decode_integer_literal (&ival, &tokptr) || (*tokptr++ != ')'))
+ {
+ return (0);
+ }
+ }
+ else if (*(tokptr + 1) == '^')
+ {
+ ival = *tokptr;
+ tokptr += 2;
+ }
+ else
+ /* fail */
+ error ("Invalid control sequence");
+ }
+ else if (*tokptr == '\'')
+ {
+ /* this must be duplicated */
+ ival = *tokptr;
+ tokptr += 2;
+ }
+ else
+ {
+ ival = *tokptr++;
+ }
+
+ /* The trailing quote has not yet been consumed. If we don't find
+ it, then we have no match. */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ /* Not a character literal. */
+ return (0);
+ }
+ yylval.typed_val.val = ival;
+ yylval.typed_val.type = builtin_type_chill_char;
+ lexptr = tokptr;
+ return (CHARACTER_LITERAL);
+}
+
+/* Recognize an integer literal, as specified in Z.200 sec 5.2.4.2.
+ Note that according to 5.2.4.2, a single "_" is also a valid integer
+ literal, however GNU-chill requires there to be at least one "digit"
+ in any integer literal. */
+
+static enum ch_terminal
+match_integer_literal ()
+{
+ char *tokptr = lexptr;
+ LONGEST ival;
+
+ if (!decode_integer_literal (&ival, &tokptr))
+ {
+ return (0);
+ }
+ else
+ {
+ yylval.typed_val.val = ival;
+#if defined(CC_HAS_LONG_LONG) && defined(__STDC__)
+ if (ival > (LONGEST)2147483647U || ival < -(LONGEST)2147483648U)
+ yylval.typed_val.type = builtin_type_long_long;
+ else
+#endif
+ yylval.typed_val.type = builtin_type_int;
+ lexptr = tokptr;
+ return (INTEGER_LITERAL);
+ }
+}
+
+/* Recognize a bit-string literal, as specified in Z.200 sec 5.2.4.8
+ Note that according to 5.2.4.8, a single "_" is also a valid bit-string
+ literal, however GNU-chill requires there to be at least one "digit"
+ in any bit-string literal. */
+
+static enum ch_terminal
+match_bitstring_literal ()
+{
+ register char *tokptr = lexptr;
+ int bitoffset = 0;
+ int bitcount = 0;
+ int bits_per_char;
+ int digit;
+
+ tempbufindex = 0;
+ CHECKBUF (1);
+ tempbuf[0] = 0;
+
+ /* Look for the required explicit base specifier. */
+
+ switch (*tokptr++)
+ {
+ case 'b':
+ case 'B':
+ bits_per_char = 1;
+ break;
+ case 'o':
+ case 'O':
+ bits_per_char = 3;
+ break;
+ case 'h':
+ case 'H':
+ bits_per_char = 4;
+ break;
+ default:
+ return (0);
+ break;
+ }
+
+ /* Ensure that the character after the explicit base is a single quote. */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+
+ while (*tokptr != '\0' && *tokptr != '\'')
+ {
+ digit = *tokptr;
+ if (isupper (digit))
+ digit = tolower (digit);
+ tokptr++;
+ switch (digit)
+ {
+ case '_':
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ digit -= '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ digit -= 'a';
+ digit += 10;
+ break;
+ default:
+ /* this is not a bitstring literal, probably an integer */
+ return 0;
+ }
+ if (digit >= 1 << bits_per_char)
+ {
+ /* Found something not in domain for current base. */
+ error ("Too-large digit in bitstring or integer.");
+ }
+ else
+ {
+ /* Extract bits from digit, packing them into the bitstring byte. */
+ int k = TARGET_BYTE_ORDER == BIG_ENDIAN ? bits_per_char - 1 : 0;
+ for (; TARGET_BYTE_ORDER == BIG_ENDIAN ? k >= 0 : k < bits_per_char;
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? k-- : k++)
+ {
+ bitcount++;
+ if (digit & (1 << k))
+ {
+ tempbuf[tempbufindex] |=
+ (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ ? (1 << (HOST_CHAR_BIT - 1 - bitoffset))
+ : (1 << bitoffset);
+ }
+ bitoffset++;
+ if (bitoffset == HOST_CHAR_BIT)
+ {
+ bitoffset = 0;
+ tempbufindex++;
+ CHECKBUF(1);
+ tempbuf[tempbufindex] = 0;
+ }
+ }
+ }
+ }
+
+ /* Verify that we consumed everything up to the trailing single quote,
+ and that we found some bits (IE not just underbars). */
+
+ if (*tokptr++ != '\'')
+ {
+ return (0);
+ }
+ else
+ {
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = bitcount;
+ lexptr = tokptr;
+ return (BIT_STRING_LITERAL);
+ }
+}
+
+struct token
+{
+ char *operator;
+ int token;
+};
+
+static const struct token idtokentab[] =
+{
+ { "array", ARRAY },
+ { "length", LENGTH },
+ { "lower", LOWER },
+ { "upper", UPPER },
+ { "andif", ANDIF },
+ { "pred", PRED },
+ { "succ", SUCC },
+ { "card", CARD },
+ { "size", SIZE },
+ { "orif", ORIF },
+ { "num", NUM },
+ { "abs", ABS },
+ { "max", MAX_TOKEN },
+ { "min", MIN_TOKEN },
+ { "mod", MOD },
+ { "rem", REM },
+ { "not", NOT },
+ { "xor", LOGXOR },
+ { "and", LOGAND },
+ { "in", IN },
+ { "or", LOGIOR },
+ { "up", UP },
+ { "addr", ADDR_TOKEN },
+ { "null", EMPTINESS_LITERAL }
+};
+
+static const struct token tokentab2[] =
+{
+ { ":=", GDB_ASSIGNMENT },
+ { "//", SLASH_SLASH },
+ { "->", POINTER },
+ { "/=", NOTEQUAL },
+ { "<=", LEQ },
+ { ">=", GEQ }
+};
+
+/* Read one token, getting characters through lexptr. */
+/* This is where we will check to make sure that the language and the
+ operators used are compatible. */
+
+static enum ch_terminal
+ch_lex ()
+{
+ unsigned int i;
+ enum ch_terminal token;
+ char *inputname;
+ struct symbol *sym;
+
+ /* Skip over any leading whitespace. */
+ while (isspace (*lexptr))
+ {
+ lexptr++;
+ }
+ /* Look for special single character cases which can't be the first
+ character of some other multicharacter token. */
+ switch (*lexptr)
+ {
+ case '\0':
+ return END_TOKEN;
+ case ',':
+ case '=':
+ case ';':
+ case '!':
+ case '+':
+ case '*':
+ case '(':
+ case ')':
+ case '[':
+ case ']':
+ return (*lexptr++);
+ }
+ /* Look for characters which start a particular kind of multicharacter
+ token, such as a character literal, register name, convenience
+ variable name, string literal, etc. */
+ switch (*lexptr)
+ {
+ case '\'':
+ case '\"':
+ /* First try to match a string literal, which is any
+ sequence of characters enclosed in matching single or double
+ quotes, except that a single character inside single quotes
+ is a character literal, so we have to catch that case also. */
+ token = match_string_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ if (*lexptr == '\'')
+ {
+ token = match_character_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ }
+ break;
+ case 'C':
+ case 'c':
+ token = match_character_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ break;
+ case '$':
+ yylval.sval.ptr = lexptr;
+ do {
+ lexptr++;
+ } while (isalnum (*lexptr) || *lexptr == '_' || *lexptr == '$');
+ yylval.sval.length = lexptr - yylval.sval.ptr;
+ write_dollar_variable (yylval.sval);
+ return GDB_VARIABLE;
+ break;
+ }
+ /* See if it is a special token of length 2. */
+ for (i = 0; i < sizeof (tokentab2) / sizeof (tokentab2[0]); i++)
+ {
+ if (STREQN (lexptr, tokentab2[i].operator, 2))
+ {
+ lexptr += 2;
+ return (tokentab2[i].token);
+ }
+ }
+ /* Look for single character cases which which could be the first
+ character of some other multicharacter token, but aren't, or we
+ would already have found it. */
+ switch (*lexptr)
+ {
+ case '-':
+ case ':':
+ case '/':
+ case '<':
+ case '>':
+ return (*lexptr++);
+ }
+ /* Look for a float literal before looking for an integer literal, so
+ we match as much of the input stream as possible. */
+ token = match_float_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ token = match_bitstring_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+ token = match_integer_literal ();
+ if (token != 0)
+ {
+ return (token);
+ }
+
+ /* Try to match a simple name string, and if a match is found, then
+ further classify what sort of name it is and return an appropriate
+ token. Note that attempting to match a simple name string consumes
+ the token from lexptr, so we can't back out if we later find that
+ we can't classify what sort of name it is. */
+
+ inputname = match_simple_name_string ();
+
+ if (inputname != NULL)
+ {
+ char *simplename = (char*) alloca (strlen (inputname) + 1);
+
+ char *dptr = simplename, *sptr = inputname;
+ for (; *sptr; sptr++)
+ *dptr++ = isupper (*sptr) ? tolower(*sptr) : *sptr;
+ *dptr = '\0';
+
+ /* See if it is a reserved identifier. */
+ for (i = 0; i < sizeof (idtokentab) / sizeof (idtokentab[0]); i++)
+ {
+ if (STREQ (simplename, idtokentab[i].operator))
+ {
+ return (idtokentab[i].token);
+ }
+ }
+
+ /* Look for other special tokens. */
+ if (STREQ (simplename, "true"))
+ {
+ yylval.ulval = 1;
+ return (BOOLEAN_LITERAL);
+ }
+ if (STREQ (simplename, "false"))
+ {
+ yylval.ulval = 0;
+ return (BOOLEAN_LITERAL);
+ }
+
+ sym = lookup_symbol (inputname, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym == NULL && strcmp (inputname, simplename) != 0)
+ {
+ sym = lookup_symbol (simplename, expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ }
+ if (sym != NULL)
+ {
+ yylval.ssym.stoken.ptr = NULL;
+ yylval.ssym.stoken.length = 0;
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = 0; /* FIXME, C++'ism */
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_BLOCK:
+ /* Found a procedure name. */
+ return (GENERAL_PROCEDURE_NAME);
+ case LOC_STATIC:
+ /* Found a global or local static variable. */
+ return (LOCATION_NAME);
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ if (innermost_block == NULL
+ || contained_in (block_found, innermost_block))
+ {
+ innermost_block = block_found;
+ }
+ return (LOCATION_NAME);
+ break;
+ case LOC_CONST:
+ case LOC_LABEL:
+ return (LOCATION_NAME);
+ break;
+ case LOC_TYPEDEF:
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ case LOC_UNDEF:
+ case LOC_CONST_BYTES:
+ case LOC_OPTIMIZED_OUT:
+ error ("Symbol \"%s\" names no location.", inputname);
+ break;
+ case LOC_UNRESOLVED:
+ error ("unhandled SYMBOL_CLASS in ch_lex()");
+ break;
+ }
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ {
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ }
+ else
+ {
+ error ("No symbol \"%s\" in current context.", inputname);
+ }
+ }
+
+ /* Catch single character tokens which are not part of some
+ longer token. */
+
+ switch (*lexptr)
+ {
+ case '.': /* Not float for example. */
+ lexptr++;
+ while (isspace (*lexptr)) lexptr++;
+ inputname = match_simple_name_string ();
+ if (!inputname)
+ return '.';
+ return FIELD_NAME;
+ }
+
+ return (ILLEGAL_TOKEN);
+}
+
+static void
+write_lower_upper_value (opcode, type)
+ enum exp_opcode opcode; /* Either UNOP_LOWER or UNOP_UPPER */
+ struct type *type;
+{
+ if (type == NULL)
+ write_exp_elt_opcode (opcode);
+ else
+ {
+ extern LONGEST type_lower_upper ();
+ struct type *result_type;
+ LONGEST val = type_lower_upper (opcode, type, &result_type);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (result_type);
+ write_exp_elt_longcst (val);
+ write_exp_elt_opcode (OP_LONG);
+ }
+}
+
+void
+chill_error (msg)
+ char *msg;
+{
+ /* Never used. */
+}
diff --git a/contrib/gdb/gdb/ch-lang.c b/contrib/gdb/gdb/ch-lang.c
new file mode 100644
index 0000000..8504d67
--- /dev/null
+++ b/contrib/gdb/gdb/ch-lang.c
@@ -0,0 +1,653 @@
+/* Chill language support routines for GDB, the GNU debugger.
+ Copyright 1992, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "ch-lang.h"
+
+
+/* For now, Chill uses a simple mangling algorithm whereby you simply
+ discard everything after the occurance of two successive CPLUS_MARKER
+ characters to derive the demangled form. */
+
+char *
+chill_demangle (mangled)
+ const char *mangled;
+{
+ const char *joiner = NULL;
+ char *demangled;
+ const char *cp = mangled;
+
+ while (*cp)
+ {
+ if (is_cplus_marker (*cp))
+ {
+ joiner = cp;
+ break;
+ }
+ cp++;
+ }
+ if (joiner != NULL && *(joiner + 1) == *joiner)
+ {
+ demangled = savestring (mangled, joiner - mangled);
+ }
+ else
+ {
+ demangled = NULL;
+ }
+ return (demangled);
+}
+
+static void
+chill_printchar (c, stream)
+ register int c;
+ GDB_FILE *stream;
+{
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (c == '\'' || c == '^')
+ fprintf_filtered (stream, "'%c%c'", c, c);
+ else
+ fprintf_filtered (stream, "'%c'", c);
+ }
+ else
+ {
+ fprintf_filtered (stream, "'^(%u)'", (unsigned int) c);
+ }
+}
+
+/* Print the character string STRING, printing at most LENGTH characters.
+ Printing stops early if the number hits print_max; repeat counts
+ are printed as appropriate. Print ellipses at the end if we
+ had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.
+ Note that gdb maintains the length of strings without counting the
+ terminating null byte, while chill strings are typically written with
+ an explicit null byte. So we always assume an implied null byte
+ until gdb is able to maintain non-null terminated strings as well
+ as null terminated strings (FIXME).
+ */
+
+static void
+chill_printstr (stream, string, length, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ register unsigned int i;
+ unsigned int things_printed = 0;
+ int in_literal_form = 0;
+ int in_control_form = 0;
+ int need_slashslash = 0;
+ unsigned int c;
+ extern int repeat_count_threshold;
+ extern int print_max;
+
+ if (length == 0)
+ {
+ fputs_filtered ("\"\"", stream);
+ return;
+ }
+
+ for (i = 0; i < length && things_printed < print_max; ++i)
+ {
+ /* Position of the character we are examining
+ to see whether it is repeated. */
+ unsigned int rep1;
+ /* Number of repetitions we have detected so far. */
+ unsigned int reps;
+
+ QUIT;
+
+ if (need_slashslash)
+ {
+ fputs_filtered ("//", stream);
+ need_slashslash = 0;
+ }
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < length && string[rep1] == string[i])
+ {
+ ++rep1;
+ ++reps;
+ }
+
+ c = string[i];
+ if (reps > repeat_count_threshold)
+ {
+ if (in_control_form || in_literal_form)
+ {
+ if (in_control_form)
+ fputs_filtered (")", stream);
+ fputs_filtered ("\"//", stream);
+ in_control_form = in_literal_form = 0;
+ }
+ chill_printchar (c, stream);
+ fprintf_filtered (stream, "<repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += repeat_count_threshold;
+ need_slashslash = 1;
+ }
+ else
+ {
+ if (! in_literal_form && ! in_control_form)
+ fputs_filtered ("\"", stream);
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (!in_literal_form)
+ {
+ if (in_control_form)
+ {
+ fputs_filtered (")", stream);
+ in_control_form = 0;
+ }
+ in_literal_form = 1;
+ }
+ fprintf_filtered (stream, "%c", c);
+ if (c == '"' || c == '^')
+ /* duplicate this one as must be done at input */
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ if (!in_control_form)
+ {
+ if (in_literal_form)
+ {
+ in_literal_form = 0;
+ }
+ fputs_filtered ("^(", stream);
+ in_control_form = 1;
+ }
+ else
+ fprintf_filtered (stream, ",");
+ c = c & 0xff;
+ fprintf_filtered (stream, "%u", (unsigned int) c);
+ }
+ ++things_printed;
+ }
+ }
+
+ /* Terminate the quotes if necessary. */
+ if (in_control_form)
+ {
+ fputs_filtered (")", stream);
+ }
+ if (in_literal_form || in_control_form)
+ {
+ fputs_filtered ("\"", stream);
+ }
+ if (force_ellipses || (i < length))
+ {
+ fputs_filtered ("...", stream);
+ }
+}
+
+static struct type *
+chill_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ default:
+ /* FIXME: For now, if we are asked to produce a type not in this
+ language, create the equivalent of a C integer type with the
+ name "<?type?>". When all the dust settles from the type
+ reconstruction work, this should probably become an error. */
+ type = init_type (TYPE_CODE_INT, 2, 0, "<?type?>", objfile);
+ warning ("internal error: no chill fundamental type %d", typeid);
+ break;
+ case FT_VOID:
+ /* FIXME: Currently the GNU Chill compiler emits some DWARF entries for
+ typedefs, unrelated to anything directly in the code being compiled,
+ that have some FT_VOID types. Just fake it for now. */
+ type = init_type (TYPE_CODE_VOID, 0, 0, "<?VOID?>", objfile);
+ break;
+ case FT_BOOLEAN:
+ type = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED, "BOOL", objfile);
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED, "CHAR", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ 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, 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);
+ break;
+ case FT_INTEGER: /* FIXME? */
+ 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, 0, "LONG", objfile);
+ break;
+ case FT_UNSIGNED_INTEGER: /* FIXME? */
+ case FT_UNSIGNED_LONG: /* Chill longs are 4 bytes */
+ type = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED, "ULONG", objfile);
+ break;
+ case FT_FLOAT:
+ type = init_type (TYPE_CODE_FLT, 4, 0, "REAL", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT, 8, 0, "LONG_REAL", objfile);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table of operators and their precedences for printing expressions. */
+
+static const struct op_print chill_op_print_tab[] = {
+ {"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"MOD", BINOP_MOD, PREC_MUL, 0},
+ {"REM", BINOP_REM, PREC_MUL, 0},
+ {"SIZE",UNOP_SIZEOF, PREC_BUILTIN_FUNCTION, 0},
+ {"LOWER",UNOP_LOWER, PREC_BUILTIN_FUNCTION, 0},
+ {"UPPER",UNOP_UPPER, PREC_BUILTIN_FUNCTION, 0},
+ {"CARD",UNOP_CARD, PREC_BUILTIN_FUNCTION, 0},
+ {"MAX",UNOP_CHMAX, PREC_BUILTIN_FUNCTION, 0},
+ {"MIN",UNOP_CHMIN, PREC_BUILTIN_FUNCTION, 0},
+ {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"=", BINOP_EQUAL, PREC_EQUAL, 0},
+ {"/=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+ {"<=", BINOP_LEQ, PREC_ORDER, 0},
+ {">=", BINOP_GEQ, PREC_ORDER, 0},
+ {">", BINOP_GTR, PREC_ORDER, 0},
+ {"<", BINOP_LESS, PREC_ORDER, 0},
+ {"+", BINOP_ADD, PREC_ADD, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"//", BINOP_CONCAT, PREC_PREFIX, 0}, /* FIXME: precedence? */
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"->", UNOP_IND, PREC_SUFFIX, 1},
+ {"->", UNOP_ADDR, PREC_PREFIX, 0},
+ {":", BINOP_RANGE, PREC_ASSIGN, 0},
+ {NULL, 0, 0, 0}
+};
+
+/* The built-in types of Chill. */
+
+struct type *builtin_type_chill_bool;
+struct type *builtin_type_chill_char;
+struct type *builtin_type_chill_long;
+struct type *builtin_type_chill_ulong;
+struct type *builtin_type_chill_real;
+
+struct type ** const (chill_builtin_types[]) =
+{
+ &builtin_type_chill_bool,
+ &builtin_type_chill_char,
+ &builtin_type_chill_long,
+ &builtin_type_chill_ulong,
+ &builtin_type_chill_real,
+ 0
+};
+
+/* Calculate LOWER or UPPER of TYPE.
+ Returns the result as an integer.
+ *RESULT_TYPE is the appropriate type for the result. */
+
+LONGEST
+type_lower_upper (op, type, result_type)
+ enum exp_opcode op; /* Either UNOP_LOWER or UNOP_UPPER */
+ struct type *type;
+ struct type **result_type;
+{
+ LONGEST low, high;
+ *result_type = type;
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRUCT:
+ *result_type = builtin_type_int;
+ if (chill_varying_type (type))
+ return type_lower_upper (op, TYPE_FIELD_TYPE (type, 1), result_type);
+ break;
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_STRING:
+ type = TYPE_FIELD_TYPE (type, 0); /* Get index type */
+
+ /* ... fall through ... */
+ case TYPE_CODE_RANGE:
+ *result_type = TYPE_TARGET_TYPE (type);
+ return op == UNOP_LOWER ? TYPE_LOW_BOUND (type) : TYPE_HIGH_BOUND (type);
+
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ if (get_discrete_bounds (type, &low, &high) >= 0)
+ {
+ *result_type = type;
+ return op == UNOP_LOWER ? low : high;
+ }
+ break;
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_COMPLEX:
+ default:
+ break;
+ }
+ error ("unknown mode for LOWER/UPPER builtin");
+}
+
+static value_ptr
+value_chill_length (val)
+ value_ptr val;
+{
+ LONGEST tmp;
+ struct type *type = VALUE_TYPE (val);
+ struct type *ttype;
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_STRING:
+ tmp = type_lower_upper (UNOP_UPPER, type, &ttype)
+ - type_lower_upper (UNOP_LOWER, type, &ttype) + 1;
+ break;
+ case TYPE_CODE_STRUCT:
+ if (chill_varying_type (type))
+ {
+ tmp = unpack_long (TYPE_FIELD_TYPE (type, 0), VALUE_CONTENTS (val));
+ break;
+ }
+ /* ... else fall through ... */
+ default:
+ error ("bad argument to LENGTH builtin");
+ }
+ return value_from_longest (builtin_type_int, tmp);
+}
+
+static value_ptr
+value_chill_card (val)
+ value_ptr val;
+{
+ LONGEST tmp = 0;
+ struct type *type = VALUE_TYPE (val);
+ CHECK_TYPEDEF (type);
+
+ if (TYPE_CODE (type) == TYPE_CODE_SET)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (type);
+ LONGEST lower_bound, upper_bound;
+ int i;
+
+ get_discrete_bounds (range_type, &lower_bound, &upper_bound);
+ for (i = lower_bound; i <= upper_bound; i++)
+ if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
+ tmp++;
+ }
+ else
+ error ("bad argument to CARD builtin");
+
+ return value_from_longest (builtin_type_int, tmp);
+}
+
+static value_ptr
+value_chill_max_min (op, val)
+ enum exp_opcode op;
+ value_ptr val;
+{
+ LONGEST tmp = 0;
+ struct type *type = VALUE_TYPE (val);
+ struct type *elttype;
+ CHECK_TYPEDEF (type);
+
+ if (TYPE_CODE (type) == TYPE_CODE_SET)
+ {
+ LONGEST lower_bound, upper_bound;
+ int i, empty = 1;
+
+ elttype = TYPE_INDEX_TYPE (type);
+ CHECK_TYPEDEF (elttype);
+ get_discrete_bounds (elttype, &lower_bound, &upper_bound);
+
+ if (op == UNOP_CHMAX)
+ {
+ for (i = upper_bound; i >= lower_bound; i--)
+ {
+ if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
+ {
+ tmp = i;
+ empty = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = lower_bound; i <= upper_bound; i++)
+ {
+ if (value_bit_index (type, VALUE_CONTENTS (val), i) > 0)
+ {
+ tmp = i;
+ empty = 0;
+ break;
+ }
+ }
+ }
+ if (empty)
+ error ("%s for empty powerset", op == UNOP_CHMAX ? "MAX" : "MIN");
+ }
+ else
+ error ("bad argument to %s builtin", op == UNOP_CHMAX ? "MAX" : "MIN");
+
+ return value_from_longest (TYPE_CODE (elttype) == TYPE_CODE_RANGE
+ ? TYPE_TARGET_TYPE (elttype)
+ : elttype,
+ tmp);
+}
+
+static value_ptr
+evaluate_subexp_chill (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ int pc = *pos;
+ struct type *type;
+ int tem, nargs;
+ value_ptr arg1;
+ value_ptr *argvec;
+ enum exp_opcode op = exp->elts[*pos].opcode;
+ switch (op)
+ {
+ case MULTI_SUBSCRIPT:
+ if (noside == EVAL_SKIP)
+ break;
+ (*pos) += 3;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ type = check_typedef (VALUE_TYPE (arg1));
+
+ if (nargs == 1 && TYPE_CODE (type) == TYPE_CODE_INT)
+ {
+ /* Looks like string repetition. */
+ value_ptr string = evaluate_subexp_with_coercion (exp, pos, noside);
+ return value_concat (arg1, string);
+ }
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ if (!type || TYPE_CODE (type) != TYPE_CODE_FUNC)
+ error ("reference value used as function");
+ /* ... fall through ... */
+ case TYPE_CODE_FUNC:
+ /* It's a function call. */
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ break;
+
+ /* Allocate arg vector, including space for the function to be
+ called in argvec[0] and a terminating NULL */
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 2));
+ argvec[0] = arg1;
+ tem = 1;
+ for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++)
+ {
+ argvec[tem]
+ = evaluate_subexp_chill (TYPE_FIELD_TYPE (type, tem-1),
+ exp, pos, noside);
+ }
+ for (; tem <= nargs; tem++)
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem] = 0; /* signal end of arglist */
+
+ return call_function_by_hand (argvec[0], nargs, argvec + 1);
+ default:
+ break;
+ }
+
+ while (nargs-- > 0)
+ {
+ value_ptr index = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg1 = value_subscript (arg1, index);
+ }
+ return (arg1);
+
+ case UNOP_LOWER:
+ case UNOP_UPPER:
+ (*pos)++;
+ if (noside == EVAL_SKIP)
+ {
+ (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, EVAL_SKIP);
+ goto nosideret;
+ }
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos,
+ EVAL_AVOID_SIDE_EFFECTS);
+ tem = type_lower_upper (op, VALUE_TYPE (arg1), &type);
+ return value_from_longest (type, tem);
+
+ case UNOP_LENGTH:
+ (*pos)++;
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
+ return value_chill_length (arg1);
+
+ case UNOP_CARD:
+ (*pos)++;
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
+ return value_chill_card (arg1);
+
+ case UNOP_CHMAX:
+ case UNOP_CHMIN:
+ (*pos)++;
+ arg1 = (*exp->language_defn->evaluate_exp) (NULL_TYPE, exp, pos, noside);
+ return value_chill_max_min (op, arg1);
+
+ case BINOP_COMMA:
+ error ("',' operator used in invalid context");
+
+ default:
+ break;
+ }
+
+ return evaluate_subexp_standard (expect_type, exp, pos, noside);
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+const struct language_defn chill_language_defn = {
+ "chill",
+ language_chill,
+ chill_builtin_types,
+ range_check_on,
+ type_check_on,
+ chill_parse, /* parser */
+ chill_error, /* parser error function */
+ evaluate_subexp_chill,
+ chill_printchar, /* print a character constant */
+ chill_printstr, /* function to print a string constant */
+ 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 */
+ chill_value_print, /* Print a top-levl value */
+ {"", "B'", "", ""}, /* Binary format info */
+ {"O'%lo", "O'", "o", ""}, /* Octal format info */
+ {"D'%ld", "D'", "d", ""}, /* Decimal format info */
+ {"H'%lx", "H'", "x", ""}, /* Hex format info */
+ chill_op_print_tab, /* expression operators for printing */
+ 0, /* arrays are first-class (not c-style) */
+ 0, /* String lower bound */
+ &builtin_type_chill_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+/* Initialization for Chill */
+
+void
+_initialize_chill_language ()
+{
+ builtin_type_chill_bool =
+ init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "BOOL", (struct objfile *) NULL);
+ builtin_type_chill_char =
+ init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "CHAR", (struct objfile *) NULL);
+ builtin_type_chill_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0,
+ "LONG", (struct objfile *) NULL);
+ builtin_type_chill_ulong =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "ULONG", (struct objfile *) NULL);
+ builtin_type_chill_real =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "LONG_REAL", (struct objfile *) NULL);
+
+ add_language (&chill_language_defn);
+}
diff --git a/contrib/gdb/gdb/ch-lang.h b/contrib/gdb/gdb/ch-lang.h
new file mode 100644
index 0000000..f09a35b
--- /dev/null
+++ b/contrib/gdb/gdb/ch-lang.h
@@ -0,0 +1,39 @@
+/* Chill language support definitions for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+#endif
+
+extern int
+chill_parse PARAMS ((void)); /* Defined in ch-exp.y */
+
+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 *, GDB_FILE *, int, int));
+
+extern 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));
diff --git a/contrib/gdb/gdb/ch-typeprint.c b/contrib/gdb/gdb/ch-typeprint.c
new file mode 100644
index 0000000..a6b1944
--- /dev/null
+++ b/contrib/gdb/gdb/ch-typeprint.c
@@ -0,0 +1,346 @@
+/* Support for printing Chill types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "ch-lang.h"
+#include "typeprint.h"
+
+#include "gdb_string.h"
+#include <errno.h>
+
+static void
+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;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ if (varstring != NULL && *varstring != '\0')
+ {
+ fputs_filtered (varstring, stream);
+ fputs_filtered (" ", stream);
+ }
+ chill_type_print_base (type, stream, show, level);
+}
+
+/* Print the name of the type (or the ultimate pointer target,
+ function value or array element).
+
+ SHOW nonzero means don't print this type as just its name;
+ show its real definition even if it has a name.
+ SHOW zero means print just typename or tag if there is one
+ SHOW negative means abbreviate structure elements.
+ SHOW is decremented for printing of structure elements.
+
+ LEVEL is the depth to indent by.
+ We increase it for some recursive calls. */
+
+static void
+chill_type_print_base (type, stream, show, level)
+ struct type *type;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ register int len;
+ register int i;
+ struct type *index_type;
+ struct type *range_type;
+ LONGEST low_bound;
+ LONGEST high_bound;
+
+ QUIT;
+
+ wrap_here (" ");
+ if (type == NULL)
+ {
+ fputs_filtered ("<type unknown>", stream);
+ return;
+ }
+
+ /* When SHOW is zero or less, and there is a valid type name, then always
+ just print the type name directly from the type. */
+
+ if ((show <= 0) && (TYPE_NAME (type) != NULL))
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ return;
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ break;
+ case TYPE_CODE_PTR:
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream,
+ TYPE_NAME (type) ? TYPE_NAME (type) : "PTR");
+ break;
+ }
+ fprintf_filtered (stream, "REF ");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, 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,
+ TYPE_NAME (type) ? TYPE_NAME (type) : "BOOL");
+ break;
+
+ case TYPE_CODE_ARRAY:
+ fputs_filtered ("ARRAY (", stream);
+ range_type = TYPE_FIELD_TYPE (type, 0);
+ if (TYPE_CODE (range_type) != TYPE_CODE_RANGE)
+ chill_print_type (range_type, "", stream, 0, level);
+ else
+ {
+ index_type = TYPE_TARGET_TYPE (range_type);
+ low_bound = TYPE_FIELD_BITPOS (range_type, 0);
+ high_bound = TYPE_FIELD_BITPOS (range_type, 1);
+ print_type_scalar (index_type, low_bound, stream);
+ fputs_filtered (":", stream);
+ print_type_scalar (index_type, high_bound, stream);
+ }
+ fputs_filtered (") ", stream);
+ chill_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, 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_INDEX_TYPE (type), "", 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 ("CHARS (", stream);
+ print_type_scalar (index_type, high_bound + 1, stream);
+ fputs_filtered (")", stream);
+ break;
+
+ case TYPE_CODE_MEMBER:
+ fprintf_filtered (stream, "MEMBER ");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ break;
+ case TYPE_CODE_REF:
+ fprintf_filtered (stream, "/*LOC*/ ");
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+ case TYPE_CODE_FUNC:
+ fprintf_filtered (stream, "PROC (");
+ len = TYPE_NFIELDS (type);
+ for (i = 0; i < len; i++)
+ {
+ struct type *param_type = TYPE_FIELD_TYPE (type, i);
+ if (i > 0)
+ {
+ fputs_filtered (", ", stream);
+ wrap_here (" ");
+ }
+ if (TYPE_CODE (param_type) == TYPE_CODE_REF)
+ {
+ chill_type_print_base (TYPE_TARGET_TYPE (param_type),
+ stream, 0, level);
+ fputs_filtered (" LOC", stream);
+ }
+ else
+ chill_type_print_base (param_type, stream, show, level);
+ }
+ fprintf_filtered (stream, ")");
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
+ {
+ fputs_filtered (" RETURNS (", stream);
+ chill_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ fputs_filtered (")", stream);
+ }
+ break;
+
+ case TYPE_CODE_STRUCT:
+ if (chill_varying_type (type))
+ {
+ chill_type_print_base (TYPE_FIELD_TYPE (type, 1),
+ stream, 0, level);
+ fputs_filtered (" VARYING", stream);
+ }
+ else
+ {
+ fprintf_filtered (stream, "STRUCT ");
+
+ fprintf_filtered (stream, "(\n");
+ if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0))
+ {
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ {
+ fprintfi_filtered (level + 4, stream, "<incomplete type>\n");
+ }
+ else
+ {
+ fprintfi_filtered (level + 4, stream, "<no data fields>\n");
+ }
+ }
+ else
+ {
+ 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);
+ 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);
+ }
+ }
+ print_spaces_filtered (level + 4, stream);
+ fputs_filtered ("ESAC", stream);
+ }
+ else
+ chill_print_type (field_type,
+ TYPE_FIELD_NAME (type, i),
+ stream, show - 1, level + 4);
+ if (i < (len - 1))
+ {
+ fputs_filtered (",", stream);
+ }
+ fputs_filtered ("\n", stream);
+ }
+ }
+ fprintfi_filtered (level, stream, ")");
+ }
+ break;
+
+ case TYPE_CODE_RANGE:
+ {
+ struct type *target = TYPE_TARGET_TYPE (type);
+ if (target && TYPE_NAME (target))
+ fputs_filtered (TYPE_NAME (target), stream);
+ else
+ fputs_filtered ("RANGE", stream);
+ if (target == NULL)
+ target = builtin_type_long;
+ fputs_filtered (" (", stream);
+ print_type_scalar (target, TYPE_LOW_BOUND (type), stream);
+ fputs_filtered (":", stream);
+ print_type_scalar (target, TYPE_HIGH_BOUND (type), stream);
+ fputs_filtered (")", stream);
+ }
+ 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_UNION:
+ case TYPE_CODE_METHOD:
+ error ("missing language support in chill_type_print_base");
+ break;
+
+ default:
+
+ /* Handle types not explicitly handled by the other cases,
+ such as fundamental types. For these, just print whatever
+ the type name is, as recorded in the type itself. If there
+ is no type name, then complain. */
+
+ if (TYPE_NAME (type) != NULL)
+ {
+ fputs_filtered (TYPE_NAME (type), stream);
+ }
+ else
+ {
+ error ("Unrecognized type code (%d) in symbol table.",
+ TYPE_CODE (type));
+ }
+ break;
+ }
+}
diff --git a/contrib/gdb/gdb/ch-valprint.c b/contrib/gdb/gdb/ch-valprint.c
new file mode 100644
index 0000000..de66d46
--- /dev/null
+++ b/contrib/gdb/gdb/ch-valprint.c
@@ -0,0 +1,664 @@
+/* Support for printing Chill values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "valprint.h"
+#include "expression.h"
+#include "value.h"
+#include "language.h"
+#include "demangle.h"
+#include "c-lang.h" /* For c_val_print */
+#include "typeprint.h"
+#include "ch-lang.h"
+#include "annotate.h"
+
+static void
+chill_print_value_fields PARAMS ((struct type *, char *, GDB_FILE *, int, int,
+ enum val_prettyprint, struct type **));
+
+
+/* Print integral scalar data VAL, of type TYPE, onto stdio stream STREAM.
+ Used to print data from type structures in a specified type. For example,
+ array bounds may be characters or booleans in some languages, and this
+ allows the ranges to be printed in their "natural" form rather than as
+ decimal integer values. */
+
+void
+chill_print_type_scalar (type, val, stream)
+ struct type *type;
+ LONGEST val;
+ GDB_FILE *stream;
+{
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_RANGE:
+ if (TYPE_TARGET_TYPE (type))
+ {
+ chill_print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
+ return;
+ }
+ break;
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ default:
+ break;
+ }
+ print_type_scalar (type, val, stream);
+}
+
+/* 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);
+
+ elttype = check_typedef (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);
+ chill_print_type_scalar (index_type, low_bound + i, stream);
+ if (reps > 1)
+ {
+ fputs_filtered (":", stream);
+ chill_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, "...");
+ }
+}
+
+/* In certain cases it could happen, that an array type doesn't
+ have a length (this have to do with seizing). The reason is
+ shown in the following stabs:
+
+ .stabs "m_x:Tt81=s36i:1,0,32;ar:82=ar80;0;1;83=xsm_struct:,32,256;;",128,0,25,0
+
+ .stabs "m_struct:Tt83=s16f1:9,0,16;f2:85=*84,32,32;f3:84,64,64;;",128,0,10,0
+
+ When processing t81, the array ar80 doesn't have a length, cause
+ struct m_struct is specified extern at thse moment. Afterwards m_struct
+ gets specified and updated, but not the surrounding type.
+
+ So we walk through array's till we find a type with a length and
+ calculate the array length.
+
+ FIXME: Where may this happen too ?
+ */
+
+static void
+calculate_array_length (type)
+ struct type *type;
+{
+ struct type *target_type;
+ struct type *range_type;
+ LONGEST lower_bound, upper_bound;
+
+ if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+ /* not an array, stop processing */
+ return;
+
+ target_type = TYPE_TARGET_TYPE (type);
+ range_type = TYPE_FIELD_TYPE (type, 0);
+ lower_bound = TYPE_FIELD_BITPOS (range_type, 0);
+ upper_bound = TYPE_FIELD_BITPOS (range_type, 1);
+
+ if (TYPE_LENGTH (target_type) == 0 &&
+ TYPE_CODE (target_type) == TYPE_CODE_ARRAY)
+ /* we've got another array */
+ calculate_array_length (target_type);
+
+ TYPE_LENGTH (type) = (upper_bound - lower_bound + 1) * TYPE_LENGTH (target_type);
+}
+
+/* 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
+ target byte order.
+
+ If the data are a string pointer, returns the number of string characters
+ printed.
+
+ If DEREF_REF is nonzero, then dereference references, otherwise just print
+ them like pointers.
+
+ The PRETTY parameter controls prettyprinting. */
+
+int
+chill_val_print (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;
+{
+ LONGEST val;
+ unsigned int i = 0; /* Number of characters printed. */
+ struct type *elttype;
+ CORE_ADDR addr;
+
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ if (TYPE_LENGTH (type) == 0)
+ /* see comment function calculate_array_length */
+ calculate_array_length (type);
+
+ if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+ {
+ if (prettyprint_arrays)
+ {
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ fprintf_filtered (stream, "[");
+ chill_val_print_array_elements (type, valaddr, address, stream,
+ format, deref_ref, recurse, pretty);
+ fprintf_filtered (stream, "]");
+ }
+ else
+ {
+ error ("unimplemented in chill_val_print; unspecified array length");
+ }
+ break;
+
+ case TYPE_CODE_INT:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ val_print_type_code_int (type, valaddr, stream);
+ }
+ break;
+
+ case TYPE_CODE_CHAR:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
+ stream);
+ }
+ break;
+
+ case TYPE_CODE_FLT:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ else
+ {
+ print_floating (valaddr, type, stream);
+ }
+ break;
+
+ case TYPE_CODE_BOOL:
+ format = format ? format : output_format;
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ }
+ 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");
+ }
+ 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"
+ and no complete type for struct foo in that file. */
+ fprintf_filtered (stream, "<incomplete type>");
+ break;
+
+ case TYPE_CODE_PTR:
+ if (format && format != 's')
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ addr = unpack_pointer (type, valaddr);
+ elttype = check_typedef (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)
+ {
+ /* Try to print what function it points to. */
+ print_address_demangle (addr, stream, demangle);
+ /* Return value is irrelevant except for string pointers. */
+ return (0);
+ }
+ if (addressprint && format != 's')
+ {
+ print_address_numeric (addr, 1, stream);
+ }
+
+ /* For a pointer to char or unsigned char, also print the string
+ pointed to, unless pointer is null. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_CHAR
+ && (format == 0 || format == 's')
+ && addr != 0
+ && /* If print_max is UINT_MAX, the alloca below will fail.
+ In that case don't try to print the string. */
+ print_max < UINT_MAX)
+ {
+ i = val_print_string (addr, 0, stream);
+ }
+ /* Return number of characters printed, plus one for the
+ terminating null if we have "reached the end". */
+ return (i + (print_max && i != print_max));
+ break;
+
+ case TYPE_CODE_STRING:
+ i = TYPE_LENGTH (type);
+ LA_PRINT_STRING (stream, valaddr, i, 0);
+ /* Return number of characters printed, plus one for the terminating
+ null if we have "reached the end". */
+ return (i + (print_max && i != print_max));
+ break;
+
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_SET:
+ elttype = TYPE_INDEX_TYPE (type);
+ CHECK_TYPEDEF (elttype);
+ if (TYPE_FLAGS (elttype) & TYPE_FLAG_STUB)
+ {
+ fprintf_filtered (stream, "<incomplete type>");
+ gdb_flush (stream);
+ break;
+ }
+ {
+ struct type *range = elttype;
+ LONGEST low_bound, high_bound;
+ 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);
+
+ i = get_discrete_bounds (range, &low_bound, &high_bound);
+ maybe_bad_bstring:
+ if (i < 0)
+ {
+ fputs_filtered ("<error value>", stream);
+ goto done;
+ }
+
+ for (i = low_bound; i <= high_bound; i++)
+ {
+ int element = value_bit_index (type, valaddr, i);
+ if (element < 0)
+ {
+ i = element;
+ goto maybe_bad_bstring;
+ }
+ if (is_bitstring)
+ fprintf_filtered (stream, "%d", element);
+ else if (element)
+ {
+ if (need_comma)
+ fputs_filtered (", ", stream);
+ chill_print_type_scalar (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;
+ chill_print_type_scalar (range, j, stream);
+ }
+ }
+ }
+ done:
+ if (is_bitstring)
+ fputs_filtered ("'", stream);
+ else
+ fputs_filtered ("]", stream);
+ }
+ break;
+
+ case TYPE_CODE_STRUCT:
+ if (chill_varying_type (type))
+ {
+ struct type *inner = check_typedef (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,
+ "<dynamic length %ld > 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;
+
+ case TYPE_CODE_REF:
+ if (addressprint)
+ {
+ 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);
+ }
+ /* De-reference the reference. */
+ if (deref_ref)
+ {
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_UNDEF)
+ {
+ value_ptr deref_val =
+ value_at
+ (TYPE_TARGET_TYPE (type),
+ unpack_pointer (lookup_pointer_type (builtin_type_void),
+ valaddr));
+ val_print (VALUE_TYPE (deref_val),
+ VALUE_CONTENTS (deref_val),
+ VALUE_ADDRESS (deref_val), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ else
+ fputs_filtered ("???", stream);
+ }
+ break;
+
+ case TYPE_CODE_ENUM:
+ c_val_print (type, valaddr, address, stream, format,
+ 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:
+ default:
+ /* 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);
+ }
+ gdb_flush (stream);
+ return (0);
+}
+
+/* Mutually recursive subroutines of cplus_print_value and c_val_print to
+ print out a structure's fields: cp_print_value_fields and cplus_print_value.
+
+ TYPE, VALADDR, STREAM, RECURSE, and PRETTY have the
+ same meanings as in cplus_print_value and c_val_print.
+
+ DONT_PRINT is an array of baseclass types that we
+ should not print, or zero if called from top level. */
+
+static void
+chill_print_value_fields (type, valaddr, stream, format, recurse, pretty,
+ dont_print)
+ struct type *type;
+ char *valaddr;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print;
+{
+ int i, len;
+ int fields_seen = 0;
+
+ CHECK_TYPEDEF (type);
+
+ fprintf_filtered (stream, "[");
+ len = TYPE_NFIELDS (type);
+ if (len == 0)
+ {
+ fprintf_filtered (stream, "<No data fields>");
+ }
+ else
+ {
+ for (i = 0; i < len; i++)
+ {
+ if (fields_seen)
+ {
+ fprintf_filtered (stream, ", ");
+ }
+ fields_seen = 1;
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ else
+ {
+ wrap_here (n_spaces (2 + 2 * recurse));
+ }
+ fputs_filtered (".", stream);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_chill, DMGL_NO_OPTS);
+ fputs_filtered (": ", stream);
+ if (TYPE_FIELD_PACKED (type, i))
+ {
+ value_ptr v;
+
+ /* Bitfields require special handling, especially due to byte
+ order problems. */
+ v = value_from_longest (TYPE_FIELD_TYPE (type, i),
+ unpack_field_as_long (type, valaddr, i));
+
+ chill_val_print (TYPE_FIELD_TYPE (type, i), VALUE_CONTENTS (v), 0,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ else
+ {
+ chill_val_print (TYPE_FIELD_TYPE (type, i),
+ valaddr + TYPE_FIELD_BITPOS (type, i) / 8,
+ 0, stream, format, 0, recurse + 1, pretty);
+ }
+ }
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ }
+ fprintf_filtered (stream, "]");
+}
+
+int
+chill_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ struct type *type = VALUE_TYPE (val);
+ struct type *real_type = check_typedef (type);
+
+ /* If it is a pointer, indicate what it points to.
+
+ Print type also if it is a reference. */
+
+ if (TYPE_CODE (real_type) == TYPE_CODE_PTR ||
+ TYPE_CODE (real_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/contrib/gdb/gdb/coff-solib.c b/contrib/gdb/gdb/coff-solib.c
new file mode 100644
index 0000000..c0cfcf5
--- /dev/null
+++ b/contrib/gdb/gdb/coff-solib.c
@@ -0,0 +1,131 @@
+/* Handle COFF SVR3 shared libraries for GDB, the GNU Debugger.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+
+#include "frame.h"
+#include "bfd.h"
+#include "gdbcore.h"
+#include "symtab.h"
+
+/*
+
+GLOBAL FUNCTION
+
+ coff_solib_add -- add a shared library files to the symtab list. We
+ examine the `.lib' section of the exec file and determine the names of
+ the shared libraries.
+
+ This function is responsible for discovering those names and
+ addresses, and saving sufficient information about them to allow
+ their symbols to be read at a later time.
+
+SYNOPSIS
+
+ void coff_solib_add (char *arg_string, int from_tty,
+ struct target_ops *target)
+
+DESCRIPTION
+
+*/
+
+void
+coff_solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ asection *libsect;
+
+ libsect = bfd_get_section_by_name (exec_bfd, ".lib");
+
+ if (libsect)
+ {
+ int libsize;
+ unsigned char *lib;
+ struct libent
+ {
+ bfd_byte len[4];
+ bfd_byte nameoffset[4];
+ };
+
+ libsize = bfd_section_size (exec_bfd, libsect);
+
+ lib = (unsigned char *) alloca (libsize);
+
+ bfd_get_section_contents (exec_bfd, libsect, lib, 0, libsize);
+
+ while (libsize > 0)
+ {
+ struct libent *ent;
+ struct objfile *objfile;
+ int len, nameoffset;
+ char *filename;
+
+ ent = (struct libent *)lib;
+
+ len = bfd_get_32 (exec_bfd, ent->len);
+
+ nameoffset = bfd_get_32 (exec_bfd, ent->nameoffset);
+
+ if (len <= 0)
+ break;
+
+ filename = (char *)ent + nameoffset * 4;
+
+ objfile = symbol_file_add (filename, from_tty,
+ 0, /* addr */
+ 0, /* not mainline */
+ 0, /* not mapped */
+ 0); /* Not readnow */
+ libsize -= len * 4;
+ lib += len * 4;
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ coff_solib_create_inferior_hook -- shared library startup support
+
+SYNOPSIS
+
+ void coff_solib_create_inferior_hook()
+
+DESCRIPTION
+
+ When gdb starts up the inferior, the kernel maps in the shared
+ libraries. We get here with the target stopped at it's first
+ instruction, and the libraries already mapped. At this point, this
+ function gets called via expansion of the macro
+ SOLIB_CREATE_INFERIOR_HOOK.
+ */
+
+void
+coff_solib_create_inferior_hook()
+{
+ coff_solib_add ((char *) 0, 0, (struct target_ops *) 0);
+}
diff --git a/contrib/gdb/gdb/coff-solib.h b/contrib/gdb/gdb/coff-solib.h
new file mode 100644
index 0000000..d154234
--- /dev/null
+++ b/contrib/gdb/gdb/coff-solib.h
@@ -0,0 +1,60 @@
+/* COFF (SVR3) Shared library declarations for GDB, the GNU Debugger.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct target_ops;
+#endif
+
+/* Called when we free all symtabs, to free the shared library information
+ as well. */
+
+#if 0
+#define CLEAR_SOLIB coff_clear_solib
+
+extern void
+coff_clear_solib PARAMS ((void));
+#endif
+
+/* Called to add symbols from a shared library to gdb's symbol table. */
+
+#define SOLIB_ADD(filename, from_tty, targ) \
+ coff_solib_add (filename, from_tty, targ)
+
+extern void
+coff_solib_add PARAMS ((char *, int, struct target_ops *));
+
+/* Function to be called when the inferior starts up, to discover the names
+ of shared libraries that are dynamically linked, the base addresses to
+ which they are linked, and sufficient information to read in their symbols
+ at a later time. */
+
+#define SOLIB_CREATE_INFERIOR_HOOK(PID) coff_solib_create_inferior_hook()
+
+extern void
+coff_solib_create_inferior_hook PARAMS((void)); /* solib.c */
+
+/* If we can't set a breakpoint, and it's in a shared library, just
+ disable it. */
+
+#if 0
+#define DISABLE_UNSETTABLE_BREAK(addr) coff_solib_address(addr)
+
+extern int
+solib_address PARAMS ((CORE_ADDR)); /* solib.c */
+#endif
diff --git a/contrib/gdb/gdb/coffread.c b/contrib/gdb/gdb/coffread.c
new file mode 100644
index 0000000..bd2a700
--- /dev/null
+++ b/contrib/gdb/gdb/coffread.c
@@ -0,0 +1,2164 @@
+/* Read coff symbol tables and convert to internal format, for GDB.
+ Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996
+ Free Software Foundation, Inc.
+ Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "breakpoint.h"
+
+#include "bfd.h"
+#include "obstack.h"
+
+#include "gdb_string.h"
+#include <ctype.h>
+
+#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"
+#include "target.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 */
+
+ CORE_ADDR textaddr; /* Addr of .text section. */
+ unsigned int textsize; /* Size of .text section. */
+ struct stab_section_list *stabsects; /* .stab sections. */
+ asection *stabstrsect; /* Section pointer for .stab section */
+ char *stabstrdata;
+};
+
+/* Translate an external name string into a user-visible name. */
+#define EXTERNAL_NAME(string, abfd) \
+ (string[0] == bfd_get_symbol_leading_char(abfd)? string+1: string)
+
+/* To be an sdb debug type, type must have at least a basic or primary
+ derived type. Using this rather than checking against T_NULL is
+ said to prevent core dumps if we try to operate on Michael Bloom
+ dbx-in-coff file. */
+
+#define SDB_TYPE(type) (BTYPE(type) | (type & N_TMASK))
+
+/* Convert from an sdb register number to an internal gdb register number.
+ This should be defined in tm.h, if REGISTER_NAMES is not set up
+ to map one to one onto the sdb register numbers. */
+
+#ifndef SDB_REG_TO_REGNUM
+# define SDB_REG_TO_REGNUM(value) (value)
+#endif
+
+/* Core address of start and end of text of current source file.
+ This comes from a ".text" symbol where x_nlinno > 0. */
+
+static CORE_ADDR current_source_start_addr;
+static CORE_ADDR current_source_end_addr;
+
+/* The addresses of the symbol table stream and number of symbols
+ of the object file we are reading (as copied into core). */
+
+static bfd *nlist_bfd_global;
+static int nlist_nsyms_global;
+
+/* Vector of line number information. */
+
+static struct linetable *line_vector;
+
+/* Index of next entry to go in line_vector_index. */
+
+static int line_vector_index;
+
+/* Last line number recorded in the line vector. */
+
+static int prev_line_number;
+
+/* Number of elements allocated for line_vector currently. */
+
+static int line_vector_length;
+
+/* Pointers to scratch storage, used for reading raw symbols and auxents. */
+
+static char *temp_sym;
+static char *temp_aux;
+
+/* Local variables that hold the shift and mask values for the
+ COFF file that we are currently reading. These come back to us
+ from BFD, and are referenced by their macro names, as well as
+ internally to the BTYPE, ISPTR, ISFCN, ISARY, ISTAG, and DECREF
+ macros from include/coff/internal.h . */
+
+static unsigned local_n_btmask;
+static unsigned local_n_btshft;
+static unsigned local_n_tmask;
+static unsigned local_n_tshift;
+
+#define N_BTMASK local_n_btmask
+#define N_BTSHFT local_n_btshft
+#define N_TMASK local_n_tmask
+#define N_TSHIFT local_n_tshift
+
+/* Local variables that hold the sizes in the file of various COFF structures.
+ (We only need to know this to read them from the file -- BFD will then
+ translate the data in them, into `internal_xxx' structs in the right
+ byte order, alignment, etc.) */
+
+static unsigned local_linesz;
+static unsigned local_symesz;
+static unsigned local_auxesz;
+
+/* Chain of typedefs of pointers to empty struct/union types.
+ They are chained thru the SYMBOL_VALUE_CHAIN. */
+
+static struct symbol *opaque_type_chain[HASHSIZE];
+
+/* Complaints about various problems in the file being read */
+
+struct complaint ef_complaint =
+ {"Unmatched .ef symbol(s) ignored starting at symnum %d", 0, 0};
+
+struct complaint ef_stack_complaint =
+ {"`.ef' symbol without matching `.bf' symbol ignored starting at symnum %d", 0, 0};
+
+struct complaint eb_stack_complaint =
+ {"`.eb' symbol without matching `.bb' symbol ignored starting at symnum %d", 0, 0};
+
+struct complaint bf_no_aux_complaint =
+ {"`.bf' symbol %d has no aux entry", 0, 0};
+
+struct complaint ef_no_aux_complaint =
+ {"`.ef' symbol %d has no aux entry", 0, 0};
+
+struct complaint lineno_complaint =
+ {"Line number pointer %d lower than start of line numbers", 0, 0};
+
+struct complaint unexpected_type_complaint =
+ {"Unexpected type for symbol %s", 0, 0};
+
+struct complaint bad_sclass_complaint =
+ {"Bad n_sclass for symbol %s", 0, 0};
+
+struct complaint misordered_blocks_complaint =
+ {"Blocks out of order at address %x", 0, 0};
+
+struct complaint tagndx_bad_complaint =
+ {"Symbol table entry for %s has bad tagndx value", 0, 0};
+
+struct complaint eb_complaint =
+ {"Mismatched .eb symbol ignored starting at symnum %d", 0, 0};
+
+/* Simplified internal version of coff symbol table information */
+
+struct coff_symbol {
+ char *c_name;
+ int c_symnum; /* symbol number of this entry */
+ int c_naux; /* 0 if syment only, 1 if syment + auxent, etc */
+ long c_value;
+ int c_sclass;
+ int c_secnum;
+ unsigned int c_type;
+};
+
+static struct type *coff_read_struct_type PARAMS ((int, int, int));
+
+static struct type *decode_base_type PARAMS ((struct coff_symbol *,
+ unsigned int,
+ union internal_auxent *));
+
+static struct type *decode_type PARAMS ((struct coff_symbol *, unsigned int,
+ union internal_auxent *));
+
+static struct type *decode_function_type PARAMS ((struct coff_symbol *,
+ unsigned int,
+ union internal_auxent *));
+
+static struct type *coff_read_enum_type PARAMS ((int, int, int));
+
+static struct symbol *process_coff_symbol PARAMS ((struct coff_symbol *,
+ union internal_auxent *,
+ struct section_offsets *,
+ struct objfile *));
+
+static void patch_opaque_types PARAMS ((struct symtab *));
+
+static void patch_type PARAMS ((struct type *, struct type *));
+
+static void enter_linenos PARAMS ((long, int, int, struct section_offsets *));
+
+static void free_linetab PARAMS ((void));
+
+static int init_lineno PARAMS ((bfd *, long, int));
+
+static char *getsymname PARAMS ((struct internal_syment *));
+
+static char *coff_getfilename PARAMS ((union internal_auxent *));
+
+static void free_stringtab PARAMS ((void));
+
+static int init_stringtab PARAMS ((bfd *, long));
+
+static void read_one_sym PARAMS ((struct coff_symbol *,
+ struct internal_syment *,
+ union internal_auxent *));
+
+static void coff_symtab_read PARAMS ((long, int, struct section_offsets *,
+ struct objfile *));
+
+static void find_linenos PARAMS ((bfd *, sec_ptr, PTR));
+
+static void coff_symfile_init PARAMS ((struct objfile *));
+
+static void coff_new_init PARAMS ((struct objfile *));
+
+static void 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,
+ struct objfile *));
+
+static void coff_end_symtab PARAMS ((struct objfile *));
+
+static void complete_symtab PARAMS ((char *, CORE_ADDR, unsigned int));
+
+static void coff_start_symtab PARAMS ((void));
+
+static void coff_record_line PARAMS ((int, CORE_ADDR));
+
+static struct type *coff_alloc_type PARAMS ((int));
+
+static struct type **coff_lookup_type PARAMS ((int));
+
+static void coff_locate_sections PARAMS ((bfd *, asection *, PTR));
+
+/* We are called once per section from coff_symfile_read. 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.
+
+ FIXME: The section names should not be hardwired strings (what
+ should they be? I don't think most object file formats have enough
+ section flags to specify what kind of debug section it is
+ -kingdon). */
+
+static void
+coff_locate_sections (abfd, sectp, csip)
+ bfd *abfd;
+ asection *sectp;
+ PTR csip;
+{
+ register struct coff_symfile_info *csi;
+ const char *name;
+
+ csi = (struct coff_symfile_info *) csip;
+ name = bfd_get_section_name (abfd, sectp);
+ if (STREQ (name, ".text"))
+ {
+ csi->textaddr = bfd_section_vma (abfd, sectp);
+ csi->textsize += bfd_section_size (abfd, sectp);
+ }
+ else if (strncmp (name, ".text", sizeof ".text" - 1) == 0)
+ {
+ csi->textsize += bfd_section_size (abfd, sectp);
+ }
+ else if (STREQ (name, ".stabstr"))
+ {
+ csi->stabstrsect = sectp;
+ }
+ else if (strncmp (name, ".stab", sizeof ".stab" - 1) == 0)
+ {
+ const char *s;
+
+ /* We can have multiple .stab sections if linked with
+ --split-by-reloc. */
+ for (s = name + sizeof ".stab" - 1; *s != '\0'; s++)
+ if (! isdigit (*s))
+ break;
+ if (*s == '\0')
+ {
+ struct stab_section_list *n, **pn;
+
+ n = ((struct stab_section_list *)
+ xmalloc (sizeof (struct stab_section_list)));
+ n->section = sectp;
+ n->next = NULL;
+ for (pn = &csi->stabsects; *pn != NULL; pn = &(*pn)->next)
+ ;
+ *pn = n;
+
+ /* This will be run after coffstab_build_psymtabs is called
+ in coff_symfile_read, at which point we no longer need
+ the information. */
+ make_cleanup (free, n);
+ }
+ }
+}
+
+/* Return the section_offsets* that CS points to. */
+static int cs_to_section PARAMS ((struct coff_symbol *, struct objfile *));
+
+struct find_targ_sec_arg {
+ int targ_index;
+ int *resultp;
+};
+
+static void find_targ_sec PARAMS ((bfd *, asection *, void *));
+
+static void find_targ_sec (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ struct find_targ_sec_arg *args = (struct find_targ_sec_arg *)obj;
+ if (sect->target_index == args->targ_index)
+ {
+ /* This is the section. Figure out what SECT_OFF_* code it is. */
+ if (bfd_get_section_flags (abfd, sect) & SEC_CODE)
+ *args->resultp = SECT_OFF_TEXT;
+ else if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
+ *args->resultp = SECT_OFF_DATA;
+ else
+ *args->resultp = SECT_OFF_BSS;
+ }
+}
+
+/* Return the section number (SECT_OFF_*) that CS points to. */
+static int
+cs_to_section (cs, objfile)
+ struct coff_symbol *cs;
+ struct objfile *objfile;
+{
+ int off = SECT_OFF_TEXT;
+ struct find_targ_sec_arg args;
+ args.targ_index = cs->c_secnum;
+ args.resultp = &off;
+ bfd_map_over_sections (objfile->obfd, find_targ_sec, &args);
+ return off;
+}
+
+/* Look up a coff type-number index. Return the address of the slot
+ where the type for that index is stored.
+ The type-number is in INDEX.
+
+ This can be used for finding the type associated with that index
+ or for associating a new type with the index. */
+
+static struct type **
+coff_lookup_type (index)
+ register int index;
+{
+ if (index >= type_vector_length)
+ {
+ int old_vector_length = type_vector_length;
+
+ type_vector_length *= 2;
+ if (index /* is still */ >= type_vector_length)
+ type_vector_length = index * 2;
+
+ type_vector = (struct type **)
+ xrealloc ((char *) type_vector,
+ type_vector_length * sizeof (struct type *));
+ memset (&type_vector[old_vector_length], 0,
+ (type_vector_length - old_vector_length) * sizeof(struct type *));
+ }
+ return &type_vector[index];
+}
+
+/* Make sure there is a type allocated for type number index
+ and return the type object.
+ This can create an empty (zeroed) type object. */
+
+static struct type *
+coff_alloc_type (index)
+ int index;
+{
+ register struct type **type_addr = coff_lookup_type (index);
+ register struct type *type = *type_addr;
+
+ /* If we are referring to a type not known at all yet,
+ allocate an empty type for it.
+ We will fill it in later if we find out how. */
+ if (type == NULL)
+ {
+ type = alloc_type (current_objfile);
+ *type_addr = type;
+ }
+ return type;
+}
+
+/* Record a line number entry for line LINE at address PC.
+ FIXME: Use record_line instead. */
+
+static void
+coff_record_line (line, pc)
+ int line;
+ CORE_ADDR pc;
+{
+ struct linetable_entry *e;
+ /* Make sure line vector is big enough. */
+
+ if (line_vector_index + 2 >= line_vector_length)
+ {
+ line_vector_length *= 2;
+ line_vector = (struct linetable *)
+ xrealloc ((char *) line_vector, sizeof (struct linetable)
+ + (line_vector_length
+ * sizeof (struct linetable_entry)));
+ }
+
+ e = line_vector->item + line_vector_index++;
+ e->line = line; e->pc = pc;
+}
+
+/* Start a new symtab for a new source file.
+ This is called when a COFF ".file" symbol is seen;
+ it indicates the start of data for one original source file. */
+
+static void
+coff_start_symtab ()
+{
+ start_symtab (
+ /* We fill in the filename later. start_symtab puts
+ this pointer into last_source_file and we put it in
+ subfiles->name, which end_symtab frees; that's why
+ it must be malloc'd. */
+ savestring ("", 0),
+ /* We never know the directory name for COFF. */
+ NULL,
+ /* The start address is irrelevant, since we set
+ last_source_start_addr in coff_end_symtab. */
+ 0);
+
+ /* Initialize the source file line number information for this file. */
+
+ if (line_vector) /* Unlikely, but maybe possible? */
+ free ((PTR)line_vector);
+ line_vector_index = 0;
+ line_vector_length = 1000;
+ prev_line_number = -2; /* Force first line number to be explicit */
+ line_vector = (struct linetable *)
+ xmalloc (sizeof (struct linetable)
+ + line_vector_length * sizeof (struct linetable_entry));
+}
+
+/* Save the vital information from when starting to read a file,
+ for use when closing off the current file.
+ NAME is the file name the symbols came from, START_ADDR is the first
+ text address for the file, and SIZE is the number of bytes of text. */
+
+static void
+complete_symtab (name, start_addr, size)
+ char *name;
+ CORE_ADDR start_addr;
+ unsigned int size;
+{
+ if (last_source_file != NULL)
+ free (last_source_file);
+ last_source_file = savestring (name, strlen (name));
+ current_source_start_addr = start_addr;
+ current_source_end_addr = start_addr + size;
+
+ if (current_objfile -> ei.entry_point >= current_source_start_addr &&
+ current_objfile -> ei.entry_point < current_source_end_addr)
+ {
+ current_objfile -> ei.entry_file_lowpc = current_source_start_addr;
+ current_objfile -> ei.entry_file_highpc = current_source_end_addr;
+ }
+}
+
+/* Finish the symbol definitions for one main source file,
+ close off all the lexical contexts for that file
+ (creating struct block's for them), then make the
+ struct symtab for that file and put it in the list of all such. */
+
+static void
+coff_end_symtab (objfile)
+ struct objfile *objfile;
+{
+ struct symtab *symtab;
+
+ last_source_start_addr = current_source_start_addr;
+
+ /* For no good reason, this file stores the number of entries in a
+ separate variable instead of in line_vector->nitems. Fix it. */
+ if (line_vector)
+ line_vector->nitems = line_vector_index;
+
+ /* For COFF, we only have one subfile, so we can just look at
+ subfiles and not worry about there being other elements in the
+ chain. We fill in various fields now because we didn't know them
+ before (or because doing it now is simply an artifact of how this
+ file used to be written). */
+ subfiles->line_vector = line_vector;
+ subfiles->name = last_source_file;
+
+ symtab = end_symtab (current_source_end_addr, objfile, 0);
+
+ if (symtab != NULL)
+ free_named_symtabs (symtab->filename);
+
+ /* Reinitialize for beginning of new file. */
+ line_vector = 0;
+ line_vector_length = -1;
+ last_source_file = NULL;
+}
+
+static void
+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
+ (obsavestring (name, strlen (name), &objfile->symbol_obstack),
+ address, type,
+ objfile);
+}
+
+/* coff_symfile_init ()
+ is the coff-specific initialization routine for reading symbols.
+ It is passed a struct objfile which contains, among other things,
+ the BFD for the file whose symbols are being read, and a slot for
+ a pointer to "private data" which we fill with cookies and other
+ treats for coff_symfile_read ().
+
+ We will only be called if this is a COFF or COFF-like file.
+ BFD handles figuring out the format of the file, and code in symtab.c
+ uses BFD's determination to vector to us.
+
+ The ultimate result is a new symtab (or, FIXME, eventually a psymtab). */
+
+static void
+coff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ /* Allocate struct to keep track of stab reading. */
+ objfile->sym_stab_info = (PTR)
+ xmmalloc (objfile->md, sizeof (struct dbx_symfile_info));
+
+ memset ((PTR) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_private = xmmalloc (objfile->md,
+ sizeof (struct coff_symfile_info));
+
+ memset (objfile->sym_private, 0, sizeof (struct coff_symfile_info));
+
+ /* COFF objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+
+ init_entry_point_info (objfile);
+}
+
+/* This function is called for every section; it finds the outer limits
+ of the line table (minimum and maximum file offset) so that the
+ mainline code can read the whole thing for efficiency. */
+
+/* ARGSUSED */
+static void
+find_linenos (abfd, asect, vpinfo)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR vpinfo;
+{
+ struct coff_symfile_info *info;
+ int size, count;
+ file_ptr offset, maxoff;
+
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ count = asect->lineno_count;
+/* End of warning */
+
+ if (count == 0)
+ return;
+ size = count * local_linesz;
+
+ info = (struct coff_symfile_info *)vpinfo;
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ offset = asect->line_filepos;
+/* End of warning */
+
+ if (offset < info->min_lineno_offset || info->min_lineno_offset == 0)
+ info->min_lineno_offset = offset;
+
+ maxoff = offset + size;
+ if (maxoff > info->max_lineno_offset)
+ info->max_lineno_offset = maxoff;
+}
+
+
+/* The BFD for this file -- only good while we're actively reading
+ symbols into a psymtab or a symtab. */
+
+static bfd *symfile_bfd;
+
+/* Read a symbol file, after initialization by coff_symfile_init. */
+
+/* ARGSUSED */
+static void
+coff_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ struct coff_symfile_info *info;
+ struct dbx_symfile_info *dbxinfo;
+ bfd *abfd = objfile->obfd;
+ coff_data_type *cdata = coff_data (abfd);
+ char *name = bfd_get_filename (abfd);
+ register int val;
+ int num_symbols;
+ int symtab_offset;
+ int stringtab_offset;
+ struct cleanup *back_to;
+ int stabstrsize;
+
+ info = (struct coff_symfile_info *) objfile -> sym_private;
+ dbxinfo = (struct dbx_symfile_info *) objfile->sym_stab_info;
+ symfile_bfd = abfd; /* Kludge for swap routines */
+
+/* WARNING WILL ROBINSON! ACCESSING BFD-PRIVATE DATA HERE! FIXME! */
+ 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 */
+ num_symbols * cdata->local_symesz;
+
+ /* Set a few file-statics that give us specific information about
+ the particular COFF file format we're reading. */
+ local_linesz = cdata->local_linesz;
+ local_n_btmask = cdata->local_n_btmask;
+ local_n_btshft = cdata->local_n_btshft;
+ local_n_tmask = cdata->local_n_tmask;
+ local_n_tshift = cdata->local_n_tshift;
+ local_linesz = cdata->local_linesz;
+ local_symesz = cdata->local_symesz;
+ local_auxesz = cdata->local_auxesz;
+
+ /* Allocate space for raw symbol and aux entries, based on their
+ space requirements as reported by BFD. */
+ temp_sym = (char *) xmalloc
+ (cdata->local_symesz + cdata->local_auxesz);
+ temp_aux = temp_sym + cdata->local_symesz;
+ back_to = make_cleanup (free_current_contents, &temp_sym);
+/* End of warning */
+
+ /* Read the line number table, all at once. */
+ info->min_lineno_offset = 0;
+ info->max_lineno_offset = 0;
+ bfd_map_over_sections (abfd, find_linenos, (PTR) info);
+
+ make_cleanup (free_linetab, 0);
+ val = init_lineno (abfd, info->min_lineno_offset,
+ info->max_lineno_offset - info->min_lineno_offset);
+ if (val < 0)
+ error ("\"%s\": error reading line numbers\n", name);
+
+ /* Now read the string table, all at once. */
+
+ make_cleanup (free_stringtab, 0);
+ val = init_stringtab (abfd, stringtab_offset);
+ if (val < 0)
+ error ("\"%s\": can't get string table", name);
+
+ init_minimal_symbol_collection ();
+ make_cleanup (discard_minimal_symbols, 0);
+
+ /* Now that the executable file is positioned at symbol table,
+ process it and define symbols accordingly. */
+
+ coff_symtab_read ((long) symtab_offset, num_symbols, section_offsets,
+ objfile);
+
+ /* Sort symbols alphabetically within each block. */
+
+ {
+ 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. */
+
+ install_minimal_symbols (objfile);
+
+ bfd_map_over_sections (abfd, coff_locate_sections, (PTR) info);
+
+ if (info->stabsects)
+ {
+ /* FIXME: dubious. Why can't we use something normal like
+ bfd_get_section_contents? */
+ bfd_seek (abfd, abfd->where, 0);
+
+ stabstrsize = bfd_section_size (abfd, info->stabstrsect);
+
+ coffstab_build_psymtabs (objfile,
+ section_offsets,
+ mainline,
+ info->textaddr, info->textsize,
+ info->stabsects,
+ info->stabstrsect->filepos, stabstrsize);
+ }
+
+ do_cleanups (back_to);
+}
+
+static void
+coff_new_init (ignore)
+ struct objfile *ignore;
+{
+}
+
+/* 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. */
+
+static void
+coff_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_private != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_private);
+ }
+}
+
+
+/* Given pointers to a symbol table in coff style exec file,
+ analyze them and create struct symtab's describing the symbols.
+ NSYMS is the number of symbols in the symbol table.
+ We read them one at a time using read_one_sym (). */
+
+static void
+coff_symtab_read (symtab_offset, nsyms, section_offsets, objfile)
+ long symtab_offset;
+ int nsyms;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+ struct coff_symbol coff_symbol;
+ register struct coff_symbol *cs = &coff_symbol;
+ static struct internal_syment main_sym;
+ static union internal_auxent main_aux;
+ struct coff_symbol fcn_cs_saved;
+ static struct internal_syment fcn_sym_saved;
+ static union internal_auxent fcn_aux_saved;
+ struct symtab *s;
+ /* A .file is open. */
+ int in_source_file = 0;
+ int next_file_symnum = -1;
+ /* Name of the current file. */
+ char *filestring = "";
+ int depth = 0;
+ int fcn_first_line = 0;
+ int fcn_last_line = 0;
+ int fcn_start_addr = 0;
+ long fcn_line_ptr = 0;
+ int val;
+ CORE_ADDR tmpaddr;
+
+ /* Work around a stdio bug in SunOS4.1.1 (this makes me nervous....
+ it's hard to know I've really worked around it. The fix should be
+ harmless, anyway). The symptom of the bug is that the first
+ fread (in read_one_sym), will (in my example) actually get data
+ from file offset 268, when the fseek was to 264 (and ftell shows
+ 264). This causes all hell to break loose. I was unable to
+ reproduce this on a short test program which operated on the same
+ file, performing (I think) the same sequence of operations.
+
+ It stopped happening when I put in this (former) rewind().
+
+ FIXME: Find out if this has been reported to Sun, whether it has
+ been fixed in a later release, etc. */
+
+ bfd_seek (objfile->obfd, 0, 0);
+
+ /* Position to read the symbol table. */
+ val = bfd_seek (objfile->obfd, (long) symtab_offset, 0);
+ if (val < 0)
+ perror_with_name (objfile->name);
+
+ current_objfile = objfile;
+ nlist_bfd_global = objfile->obfd;
+ nlist_nsyms_global = nsyms;
+ last_source_file = NULL;
+ memset (opaque_type_chain, 0, sizeof opaque_type_chain);
+
+ if (type_vector) /* Get rid of previous one */
+ free ((PTR) type_vector);
+ type_vector_length = 160;
+ type_vector = (struct type **)
+ xmalloc (type_vector_length * sizeof (struct type *));
+ memset (type_vector, 0, type_vector_length * sizeof (struct type *));
+
+ coff_start_symtab ();
+
+ symnum = 0;
+ while (symnum < nsyms)
+ {
+ QUIT; /* Make this command interruptable. */
+
+ read_one_sym (cs, &main_sym, &main_aux);
+
+#ifdef SEM
+ temp_sem_val = cs->c_name[0] << 24 | cs->c_name[1] << 16 |
+ cs->c_name[2] << 8 | cs->c_name[3];
+ if (int_sem_val == temp_sem_val)
+ last_coffsem = (int) strtol (cs->c_name+4, (char **) NULL, 10);
+#endif
+
+ if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE)
+ {
+ if (last_source_file)
+ coff_end_symtab (objfile);
+
+ coff_start_symtab ();
+ complete_symtab ("_globals_", 0, 0);
+ /* done with all files, everything from here on out is globals */
+ }
+
+ /* Special case for file with type declarations only, no text. */
+ if (!last_source_file && SDB_TYPE (cs->c_type)
+ && cs->c_secnum == N_DEBUG)
+ complete_symtab (filestring, 0, 0);
+
+ /* Typedefs should not be treated as symbol definitions. */
+ if (ISFCN (cs->c_type) && cs->c_sclass != C_TPDEF)
+ {
+ /* Record all functions -- external and static -- in minsyms. */
+ tmpaddr = cs->c_value + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ record_minimal_symbol (cs->c_name, tmpaddr, mst_text, objfile);
+
+ fcn_line_ptr = main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ fcn_start_addr = tmpaddr;
+ fcn_cs_saved = *cs;
+ fcn_sym_saved = main_sym;
+ fcn_aux_saved = main_aux;
+ continue;
+ }
+
+ switch (cs->c_sclass)
+ {
+ case C_EFCN:
+ case C_EXTDEF:
+ case C_ULABEL:
+ case C_USTATIC:
+ case C_LINE:
+ case C_ALIAS:
+ case C_HIDDEN:
+ complain (&bad_sclass_complaint, cs->c_name);
+ break;
+
+ case C_FILE:
+ /* c_value field contains symnum of next .file entry in table
+ or symnum of first global after last .file. */
+ next_file_symnum = cs->c_value;
+ if (cs->c_naux > 0)
+ filestring = coff_getfilename (&main_aux);
+ else
+ filestring = "";
+
+ /* Complete symbol table for last object file
+ containing debugging information. */
+ if (last_source_file)
+ {
+ coff_end_symtab (objfile);
+ coff_start_symtab ();
+ }
+ in_source_file = 1;
+ break;
+
+ case C_STAT:
+ if (cs->c_name[0] == '.')
+ {
+ if (STREQ (cs->c_name, ".text")) {
+ /* FIXME: don't wire in ".text" as section name
+ or symbol name! */
+ /* Check for in_source_file deals with case of
+ a file with debugging symbols
+ followed by a later file with no symbols. */
+ if (in_source_file)
+ complete_symtab (filestring,
+ cs->c_value + ANOFFSET (section_offsets, SECT_OFF_TEXT),
+ main_aux.x_scn.x_scnlen);
+ in_source_file = 0;
+ }
+ /* flush rest of '.' symbols */
+ break;
+ }
+ else if (!SDB_TYPE (cs->c_type)
+ && cs->c_name[0] == 'L'
+ && (strncmp (cs->c_name, "LI%", 3) == 0
+ || strncmp (cs->c_name, "LF%", 3) == 0
+ || strncmp (cs->c_name,"LC%",3) == 0
+ || strncmp (cs->c_name,"LP%",3) == 0
+ || strncmp (cs->c_name,"LPB%",4) == 0
+ || strncmp (cs->c_name,"LBB%",4) == 0
+ || strncmp (cs->c_name,"LBE%",4) == 0
+ || strncmp (cs->c_name,"LPBX%",5) == 0))
+ /* At least on a 3b1, gcc generates swbeg and string labels
+ that look like this. Ignore them. */
+ break;
+ /* fall in for static symbols that don't start with '.' */
+ case C_EXT:
+ {
+ /* 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 (now
+ gone) "set fast-symbolic-addr off" kludge. */
+
+ /* FIXME: should use mst_abs, and not relocate, if absolute. */
+ enum minimal_symbol_type ms_type;
+ int sec;
+
+ if (cs->c_secnum == N_UNDEF)
+ {
+ /* This is a common symbol. See if the target
+ environment knows where it has been relocated to. */
+ CORE_ADDR reladdr;
+ if (target_lookup_symbol (cs->c_name, &reladdr))
+ {
+ /* Error in lookup; ignore symbol. */
+ break;
+ }
+ tmpaddr = reladdr;
+ /* The address has already been relocated; make sure that
+ objfile_relocate doesn't relocate it again. */
+ sec = -2;
+ ms_type = cs->c_sclass == C_STAT ? mst_file_bss : mst_bss;
+ }
+ else
+ {
+ sec = cs_to_section (cs, objfile);
+ tmpaddr = cs->c_value;
+ if (cs->c_sclass != C_STAT)
+ tmpaddr += ANOFFSET (section_offsets, sec);
+
+ switch (sec)
+ {
+ case SECT_OFF_TEXT:
+ case SECT_OFF_RODATA:
+ ms_type =
+ cs->c_sclass == C_STAT ? mst_file_text : mst_text;
+ break;
+ case SECT_OFF_DATA:
+ ms_type =
+ cs->c_sclass == C_STAT ? mst_file_data : mst_data;
+ break;
+ case SECT_OFF_BSS:
+ ms_type =
+ cs->c_sclass == C_STAT ? mst_file_bss : mst_bss;
+ break;
+ default:
+ ms_type = mst_unknown;
+ break;
+ }
+ }
+
+ if (cs->c_name[0] != '@' /* Skip tdesc symbols */)
+ prim_record_minimal_symbol_and_info
+ (obsavestring (cs->c_name, strlen (cs->c_name),
+ &objfile->symbol_obstack),
+ tmpaddr,
+ ms_type,
+ NULL,
+ sec,
+ objfile);
+
+ if (SDB_TYPE (cs->c_type))
+ {
+ struct symbol *sym;
+ sym = process_coff_symbol
+ (cs, &main_aux, section_offsets, objfile);
+ SYMBOL_VALUE (sym) = tmpaddr;
+ SYMBOL_SECTION (sym) = sec;
+ }
+ }
+ break;
+
+ case C_FCN:
+ if (STREQ (cs->c_name, ".bf"))
+ {
+ within_function = 1;
+
+ /* value contains address of first non-init type code */
+ /* main_aux.x_sym.x_misc.x_lnsz.x_lnno
+ contains line number of '{' } */
+ if (cs->c_naux != 1)
+ complain (&bf_no_aux_complaint, cs->c_symnum);
+ fcn_first_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno;
+
+ /* Might want to check that locals are 0 and
+ context_stack_depth is zero, and complain if not. */
+
+ depth = 0;
+ new = push_context (depth, fcn_start_addr);
+ fcn_cs_saved.c_name = getsymname (&fcn_sym_saved);
+ new->name =
+ process_coff_symbol (&fcn_cs_saved, &fcn_aux_saved,
+ section_offsets, objfile);
+ }
+ else if (STREQ (cs->c_name, ".ef"))
+ {
+ /* the value of .ef is the address of epilogue code;
+ not useful for gdb. */
+ /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno
+ contains number of lines to '}' */
+
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&ef_stack_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
+
+ new = pop_context ();
+ /* Stack must be empty now. */
+ if (context_stack_depth > 0 || new == NULL)
+ {
+ complain (&ef_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
+ if (cs->c_naux != 1)
+ {
+ complain (&ef_no_aux_complaint, cs->c_symnum);
+ fcn_last_line = 0x7FFFFFFF;
+ }
+ else
+ {
+ fcn_last_line = main_aux.x_sym.x_misc.x_lnsz.x_lnno;
+ }
+ enter_linenos (fcn_line_ptr, fcn_first_line, fcn_last_line,
+ section_offsets);
+
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr,
+#if defined (FUNCTION_EPILOGUE_SIZE)
+ /* This macro should be defined only on
+ machines where the
+ fcn_aux_saved.x_sym.x_misc.x_fsize
+ field is always zero.
+ So use the .bf record information that
+ points to the epilogue and add the size
+ of the epilogue. */
+ cs->c_value
+ + FUNCTION_EPILOGUE_SIZE
+ + ANOFFSET (section_offsets, SECT_OFF_TEXT),
+#else
+ fcn_cs_saved.c_value
+ + fcn_aux_saved.x_sym.x_misc.x_fsize
+ + ANOFFSET (section_offsets, SECT_OFF_TEXT),
+#endif
+ objfile
+ );
+ within_function = 0;
+ }
+ break;
+
+ case C_BLOCK:
+ if (STREQ (cs->c_name, ".bb"))
+ {
+ tmpaddr = cs->c_value;
+ tmpaddr += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ push_context (++depth, tmpaddr);
+ }
+ else if (STREQ (cs->c_name, ".eb"))
+ {
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&eb_stack_complaint, cs->c_symnum);
+ break;
+ }
+
+ new = pop_context ();
+ if (depth-- != new->depth)
+ {
+ complain (&eb_complaint, symnum);
+ break;
+ }
+ if (local_symbols && context_stack_depth > 0)
+ {
+ tmpaddr =
+ cs->c_value + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ /* Make a block for the local symbols within. */
+ finish_block (0, &local_symbols, new->old_blocks,
+ new->start_addr, tmpaddr, objfile);
+ }
+ /* Now pop locals of block just finished. */
+ local_symbols = new->locals;
+ }
+ break;
+
+ default:
+ process_coff_symbol (cs, &main_aux, section_offsets, objfile);
+ break;
+ }
+ }
+
+ if (last_source_file)
+ coff_end_symtab (objfile);
+
+ /* Patch up any opaque types (references to types that are not defined
+ in the file where they are referenced, e.g. "struct foo *bar"). */
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ patch_opaque_types (s);
+
+ current_objfile = NULL;
+}
+
+/* Routines for reading headers and symbols from executable. */
+
+/* Read the next symbol, swap it, and return it in both internal_syment
+ form, and coff_symbol form. Also return its first auxent, if any,
+ in internal_auxent form, and skip any other auxents. */
+
+static void
+read_one_sym (cs, sym, aux)
+ register struct coff_symbol *cs;
+ register struct internal_syment *sym;
+ register union internal_auxent *aux;
+{
+ int i;
+
+ cs->c_symnum = symnum;
+ bfd_read (temp_sym, local_symesz, 1, nlist_bfd_global);
+ bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *)sym);
+ cs->c_naux = sym->n_numaux & 0xff;
+ if (cs->c_naux >= 1)
+ {
+ bfd_read (temp_aux, local_auxesz, 1, nlist_bfd_global);
+ bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass,
+ 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++)
+ bfd_read (temp_aux, local_auxesz, 1, nlist_bfd_global);
+ }
+ cs->c_name = getsymname (sym);
+ cs->c_value = sym->n_value;
+ cs->c_sclass = (sym->n_sclass & 0xff);
+ cs->c_secnum = sym->n_scnum;
+ cs->c_type = (unsigned) sym->n_type;
+ if (!SDB_TYPE (cs->c_type))
+ cs->c_type = 0;
+
+ symnum += 1 + cs->c_naux;
+}
+
+/* Support for string table handling */
+
+static char *stringtab = NULL;
+
+static int
+init_stringtab (abfd, offset)
+ bfd *abfd;
+ long offset;
+{
+ long length;
+ int val;
+ unsigned char lengthbuf[4];
+
+ 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 (bfd_seek (abfd, offset, 0) < 0)
+ return -1;
+
+ val = bfd_read ((char *)lengthbuf, sizeof lengthbuf, 1, abfd);
+ length = bfd_h_get_32 (symfile_bfd, lengthbuf);
+
+ /* If no string table is needed, then the file may end immediately
+ after the symbols. Just return with `stringtab' set to null. */
+ if (val != sizeof lengthbuf || length < sizeof lengthbuf)
+ return 0;
+
+ stringtab = (char *) xmalloc (length);
+ /* This is in target format (probably not very useful, and not currently
+ used), not host format. */
+ memcpy (stringtab, lengthbuf, sizeof lengthbuf);
+ if (length == sizeof length) /* Empty table -- just the count */
+ return 0;
+
+ val = bfd_read (stringtab + sizeof lengthbuf, length - sizeof lengthbuf, 1, abfd);
+ if (val != length - sizeof lengthbuf || stringtab[length - 1] != '\0')
+ return -1;
+
+ return 0;
+}
+
+static void
+free_stringtab ()
+{
+ if (stringtab)
+ free (stringtab);
+ stringtab = NULL;
+}
+
+static char *
+getsymname (symbol_entry)
+ struct internal_syment *symbol_entry;
+{
+ static char buffer[SYMNMLEN+1];
+ char *result;
+
+ if (symbol_entry->_n._n_n._n_zeroes == 0)
+ {
+ /* FIXME: Probably should be detecting corrupt symbol files by
+ seeing whether offset points to within the stringtab. */
+ result = stringtab + symbol_entry->_n._n_n._n_offset;
+ }
+ else
+ {
+ strncpy (buffer, symbol_entry->_n._n_name, SYMNMLEN);
+ buffer[SYMNMLEN] = '\0';
+ result = buffer;
+ }
+ return result;
+}
+
+/* Extract the file name from the aux entry of a C_FILE symbol. Return
+ only the last component of the name. Result is in static storage and
+ is only good for temporary use. */
+
+static char *
+coff_getfilename (aux_entry)
+ union internal_auxent *aux_entry;
+{
+ static char buffer[BUFSIZ];
+ register char *temp;
+ char *result;
+
+ if (aux_entry->x_file.x_n.x_zeroes == 0)
+ strcpy (buffer, stringtab + aux_entry->x_file.x_n.x_offset);
+ else
+ {
+ strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN);
+ buffer[FILNMLEN] = '\0';
+ }
+ result = buffer;
+
+ /* FIXME: We should not be throwing away the information about what
+ directory. It should go into dirname of the symtab, or some such
+ place. */
+ if ((temp = strrchr (result, '/')) != NULL)
+ result = temp + 1;
+ return (result);
+}
+
+/* Support for line number handling. */
+
+static char *linetab = NULL;
+static long linetab_offset;
+static unsigned long linetab_size;
+
+/* Read in all the line numbers for fast lookups later. Leave them in
+ external (unswapped) format in memory; we'll swap them as we enter
+ them into GDB's data structures. */
+
+static int
+init_lineno (abfd, offset, size)
+ bfd *abfd;
+ long offset;
+ int size;
+{
+ int val;
+
+ linetab_offset = offset;
+ linetab_size = size;
+
+ free_linetab();
+
+ if (size == 0)
+ return 0;
+
+ if (bfd_seek (abfd, offset, 0) < 0)
+ return -1;
+
+ /* Allocate the desired table, plus a sentinel */
+ linetab = (char *) xmalloc (size + local_linesz);
+
+ val = bfd_read (linetab, size, 1, abfd);
+ if (val != size)
+ return -1;
+
+ /* Terminate it with an all-zero sentinel record */
+ memset (linetab + size, 0, local_linesz);
+
+ return 0;
+}
+
+static void
+free_linetab ()
+{
+ if (linetab)
+ free (linetab);
+ linetab = NULL;
+}
+
+#if !defined (L_LNNO32)
+#define L_LNNO32(lp) ((lp)->l_lnno)
+#endif
+
+static void
+enter_linenos (file_offset, first_line, last_line, section_offsets)
+ long file_offset;
+ register int first_line;
+ register int last_line;
+ struct section_offsets *section_offsets;
+{
+ register char *rawptr;
+ struct internal_lineno lptr;
+
+ if (!linetab)
+ return ;
+ if (file_offset < linetab_offset)
+ {
+ complain (&lineno_complaint, file_offset);
+ if (file_offset > linetab_size) /* Too big to be an offset? */
+ return;
+ file_offset += linetab_offset; /* Try reading at that linetab offset */
+ }
+
+ rawptr = &linetab[file_offset - linetab_offset];
+
+ /* skip first line entry for each function */
+ rawptr += local_linesz;
+ /* line numbers start at one for the first line of the function */
+ first_line--;
+
+ for (;;) {
+ bfd_coff_swap_lineno_in (symfile_bfd, rawptr, &lptr);
+ rawptr += local_linesz;
+ /* The next function, or the sentinel, will have L_LNNO32 zero; we exit. */
+ if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line)
+ coff_record_line (first_line + L_LNNO32 (&lptr),
+ lptr.l_addr.l_paddr
+ + ANOFFSET (section_offsets, SECT_OFF_TEXT));
+ else
+ break;
+ }
+}
+
+static void
+patch_type (type, real_type)
+ struct type *type;
+ struct type *real_type;
+{
+ register struct type *target = TYPE_TARGET_TYPE (type);
+ register struct type *real_target = TYPE_TARGET_TYPE (real_type);
+ int field_size = TYPE_NFIELDS (real_target) * sizeof (struct field);
+
+ TYPE_LENGTH (target) = TYPE_LENGTH (real_target);
+ TYPE_NFIELDS (target) = TYPE_NFIELDS (real_target);
+ TYPE_FIELDS (target) = (struct field *) TYPE_ALLOC (target, field_size);
+
+ memcpy (TYPE_FIELDS (target), TYPE_FIELDS (real_target), field_size);
+
+ if (TYPE_NAME (real_target))
+ {
+ if (TYPE_NAME (target))
+ free (TYPE_NAME (target));
+ TYPE_NAME (target) = concat (TYPE_NAME (real_target), NULL);
+ }
+}
+
+/* Patch up all appropriate typedef symbols in the opaque_type_chains
+ so that they can be used to print out opaque data structures properly. */
+
+static void
+patch_opaque_types (s)
+ struct symtab *s;
+{
+ register struct block *b;
+ register int i;
+ register struct symbol *real_sym;
+
+ /* Go through the per-file symbols only */
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ for (i = BLOCK_NSYMS (b) - 1; i >= 0; i--)
+ {
+ /* Find completed typedefs to use to fix opaque ones.
+ Remove syms from the chain when their types are stored,
+ but search the whole chain, as there may be several syms
+ from different files with the same name. */
+ real_sym = BLOCK_SYM (b, i);
+ if (SYMBOL_CLASS (real_sym) == LOC_TYPEDEF &&
+ SYMBOL_NAMESPACE (real_sym) == VAR_NAMESPACE &&
+ TYPE_CODE (SYMBOL_TYPE (real_sym)) == TYPE_CODE_PTR &&
+ TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (real_sym))) != 0)
+ {
+ register char *name = SYMBOL_NAME (real_sym);
+ register int hash = hashname (name);
+ register struct symbol *sym, *prev;
+
+ prev = 0;
+ for (sym = opaque_type_chain[hash]; sym;)
+ {
+ if (name[0] == SYMBOL_NAME (sym)[0] &&
+ STREQ (name + 1, SYMBOL_NAME (sym) + 1))
+ {
+ if (prev)
+ {
+ SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym);
+ }
+ else
+ {
+ opaque_type_chain[hash] = SYMBOL_VALUE_CHAIN (sym);
+ }
+
+ patch_type (SYMBOL_TYPE (sym), SYMBOL_TYPE (real_sym));
+
+ if (prev)
+ {
+ sym = SYMBOL_VALUE_CHAIN (prev);
+ }
+ else
+ {
+ sym = opaque_type_chain[hash];
+ }
+ }
+ else
+ {
+ prev = sym;
+ sym = SYMBOL_VALUE_CHAIN (sym);
+ }
+ }
+ }
+ }
+}
+
+static struct symbol *
+process_coff_symbol (cs, aux, section_offsets, objfile)
+ register struct coff_symbol *cs;
+ register union internal_auxent *aux;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ register struct symbol *sym
+ = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ char *name;
+
+ memset (sym, 0, sizeof (struct symbol));
+ name = cs->c_name;
+ name = EXTERNAL_NAME (name, objfile->obfd);
+ SYMBOL_NAME (sym) = obstack_copy0 (&objfile->symbol_obstack, name,
+ strlen (name));
+
+ /* default assumptions */
+ SYMBOL_VALUE (sym) = cs->c_value;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_SECTION (sym) = cs_to_section (cs, objfile);
+
+ if (ISFCN (cs->c_type))
+ {
+ SYMBOL_VALUE (sym) += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ SYMBOL_TYPE(sym) =
+ lookup_function_type (decode_function_type (cs, cs->c_type, aux));
+
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ if (cs->c_sclass == C_STAT)
+ add_symbol_to_list (sym, &file_symbols);
+ else if (cs->c_sclass == C_EXT)
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ else
+ {
+ SYMBOL_TYPE (sym) = decode_type (cs, cs->c_type, aux);
+ switch (cs->c_sclass)
+ {
+ case C_NULL:
+ break;
+
+ case C_AUTO:
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case C_EXT:
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
+ SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ add_symbol_to_list (sym, &global_symbols);
+ break;
+
+ case C_STAT:
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = (CORE_ADDR) cs->c_value;
+ SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ if (within_function) {
+ /* Static symbol of local scope */
+ add_symbol_to_list (sym, &local_symbols);
+ }
+ else {
+ /* Static symbol at top level of file */
+ add_symbol_to_list (sym, &file_symbols);
+ }
+ break;
+
+#ifdef C_GLBLREG /* AMD coff */
+ case C_GLBLREG:
+#endif
+ case C_REG:
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM(cs->c_value);
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case C_LABEL:
+ break;
+
+ case C_ARG:
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ add_symbol_to_list (sym, &local_symbols);
+#if !defined (BELIEVE_PCC_PROMOTION)
+ if (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. */
+ 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));
+ }
+ }
+#endif
+ break;
+
+ case C_REGPARM:
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = SDB_REG_TO_REGNUM(cs->c_value);
+ add_symbol_to_list (sym, &local_symbols);
+#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. */
+ 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;
+
+ case C_TPDEF:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+
+ /* If type has no name, give it one */
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+ {
+ 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);
+ }
+#ifdef CXUX_TARGET
+ /* Ignore vendor section for Harris CX/UX targets. */
+ else if (cs->c_name[0] == '$')
+ break;
+#endif /* CXUX_TARGET */
+
+ /* Keep track of any type which points to empty structured type,
+ so it can be filled from a definition from another file. A
+ simple forward reference (TYPE_CODE_UNDEF) is not an
+ empty structured type, though; the forward references
+ work themselves out via the magic of coff_lookup_type. */
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_PTR &&
+ TYPE_LENGTH (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) == 0 &&
+ TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (sym))) !=
+ TYPE_CODE_UNDEF)
+ {
+ register int i = hashname (SYMBOL_NAME (sym));
+
+ SYMBOL_VALUE_CHAIN (sym) = opaque_type_chain[i];
+ opaque_type_chain[i] = sym;
+ }
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case C_STRTAG:
+ case C_UNTAG:
+ case C_ENTAG:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+
+ /* Some compilers try to be helpful by inventing "fake"
+ names for anonymous enums, structures, and unions, like
+ "~0fake" or ".0fake". Thanks, but no thanks... */
+ if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0)
+ if (SYMBOL_NAME(sym) != NULL
+ && *SYMBOL_NAME(sym) != '~'
+ && *SYMBOL_NAME(sym) != '.')
+ TYPE_TAG_NAME (SYMBOL_TYPE (sym)) =
+ concat (SYMBOL_NAME (sym), NULL);
+
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return sym;
+}
+
+/* Decode a coff type specifier; return the type that is meant. */
+
+static struct type *
+decode_type (cs, c_type, aux)
+ register struct coff_symbol *cs;
+ unsigned int c_type;
+ register union internal_auxent *aux;
+{
+ register struct type *type = 0;
+ unsigned int new_c_type;
+
+ if (c_type & ~N_BTMASK)
+ {
+ new_c_type = DECREF (c_type);
+ if (ISPTR (c_type))
+ {
+ type = decode_type (cs, new_c_type, aux);
+ type = lookup_pointer_type (type);
+ }
+ else if (ISFCN (c_type))
+ {
+ type = decode_type (cs, new_c_type, aux);
+ type = lookup_function_type (type);
+ }
+ else if (ISARY (c_type))
+ {
+ int i, n;
+ register unsigned short *dim;
+ struct type *base_type, *index_type, *range_type;
+
+ /* Define an array type. */
+ /* auxent refers to array, not base type */
+ if (aux->x_sym.x_tagndx.l == 0)
+ cs->c_naux = 0;
+
+ /* shift the indices down */
+ dim = &aux->x_sym.x_fcnary.x_ary.x_dimen[0];
+ i = 1;
+ n = dim[0];
+ for (i = 0; *dim && i < DIMNUM - 1; i++, dim++)
+ *dim = *(dim + 1);
+ *dim = 0;
+
+ base_type = decode_type (cs, new_c_type, aux);
+ index_type = lookup_fundamental_type (current_objfile, FT_INTEGER);
+ range_type =
+ create_range_type ((struct type *) NULL, index_type, 0, n - 1);
+ type =
+ create_array_type ((struct type *) NULL, base_type, range_type);
+ }
+ return type;
+ }
+
+ /* Reference to existing type. This only occurs with the
+ struct, union, and enum types. EPI a29k coff
+ fakes us out by producing aux entries with a nonzero
+ x_tagndx for definitions of structs, unions, and enums, so we
+ have to check the c_sclass field. SCO 3.2v4 cc gets confused
+ with pointers to pointers to defined structs, and generates
+ negative x_tagndx fields. */
+ if (cs->c_naux > 0 && aux->x_sym.x_tagndx.l != 0)
+ {
+ if (cs->c_sclass != C_STRTAG
+ && cs->c_sclass != C_UNTAG
+ && cs->c_sclass != C_ENTAG
+ && aux->x_sym.x_tagndx.l >= 0)
+ {
+ type = coff_alloc_type (aux->x_sym.x_tagndx.l);
+ return type;
+ }
+ else
+ {
+ complain (&tagndx_bad_complaint, cs->c_name);
+ /* And fall through to decode_base_type... */
+ }
+ }
+
+ return decode_base_type (cs, BTYPE (c_type), aux);
+}
+
+/* Decode a coff type specifier for function definition;
+ return the type that the function returns. */
+
+static struct type *
+decode_function_type (cs, c_type, aux)
+ register struct coff_symbol *cs;
+ unsigned int c_type;
+ register union internal_auxent *aux;
+{
+ if (aux->x_sym.x_tagndx.l == 0)
+ cs->c_naux = 0; /* auxent refers to function, not base type */
+
+ return decode_type (cs, DECREF (c_type), aux);
+}
+
+/* basic C types */
+
+static struct type *
+decode_base_type (cs, c_type, aux)
+ register struct coff_symbol *cs;
+ unsigned int c_type;
+ register union internal_auxent *aux;
+{
+ struct type *type;
+
+ switch (c_type)
+ {
+ case T_NULL:
+ /* shows up with "void (*foo)();" structure members */
+ return lookup_fundamental_type (current_objfile, FT_VOID);
+
+#if 0
+/* DGUX actually defines both T_ARG and T_VOID to the same value. */
+#ifdef T_ARG
+ case T_ARG:
+ /* Shows up in DGUX, I think. Not sure where. */
+ return lookup_fundamental_type (current_objfile, FT_VOID); /* shouldn't show up here */
+#endif
+#endif /* 0 */
+
+#ifdef T_VOID
+ case T_VOID:
+ /* Intel 960 COFF has this symbol and meaning. */
+ return lookup_fundamental_type (current_objfile, FT_VOID);
+#endif
+
+ case T_CHAR:
+ return lookup_fundamental_type (current_objfile, FT_CHAR);
+
+ case T_SHORT:
+ return lookup_fundamental_type (current_objfile, FT_SHORT);
+
+ case T_INT:
+ return lookup_fundamental_type (current_objfile, FT_INTEGER);
+
+ case T_LONG:
+ return lookup_fundamental_type (current_objfile, FT_LONG);
+
+ case T_FLOAT:
+ return lookup_fundamental_type (current_objfile, FT_FLOAT);
+
+ case T_DOUBLE:
+ return lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+
+ case T_LNGDBL:
+ return lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
+
+ case T_STRUCT:
+ if (cs->c_naux != 1)
+ {
+ /* anonymous structure type */
+ type = coff_alloc_type (cs->c_symnum);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ TYPE_NAME (type) = NULL;
+ /* This used to set the tag to "<opaque>". But I think setting it
+ to NULL is right, and the printing code can print it as
+ "struct {...}". */
+ TYPE_TAG_NAME (type) = NULL;
+ INIT_CPLUS_SPECIFIC(type);
+ TYPE_LENGTH (type) = 0;
+ TYPE_FIELDS (type) = 0;
+ TYPE_NFIELDS (type) = 0;
+ }
+ else
+ {
+ type = coff_read_struct_type (cs->c_symnum,
+ aux->x_sym.x_misc.x_lnsz.x_size,
+ aux->x_sym.x_fcnary.x_fcn.x_endndx.l);
+ }
+ return type;
+
+ case T_UNION:
+ if (cs->c_naux != 1)
+ {
+ /* anonymous union type */
+ type = coff_alloc_type (cs->c_symnum);
+ TYPE_NAME (type) = NULL;
+ /* This used to set the tag to "<opaque>". But I think setting it
+ to NULL is right, and the printing code can print it as
+ "union {...}". */
+ TYPE_TAG_NAME (type) = NULL;
+ INIT_CPLUS_SPECIFIC(type);
+ TYPE_LENGTH (type) = 0;
+ TYPE_FIELDS (type) = 0;
+ TYPE_NFIELDS (type) = 0;
+ }
+ else
+ {
+ type = coff_read_struct_type (cs->c_symnum,
+ aux->x_sym.x_misc.x_lnsz.x_size,
+ aux->x_sym.x_fcnary.x_fcn.x_endndx.l);
+ }
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ return type;
+
+ case T_ENUM:
+ if (cs->c_naux != 1)
+ {
+ /* anonymous enum type */
+ type = coff_alloc_type (cs->c_symnum);
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_NAME (type) = NULL;
+ /* This used to set the tag to "<opaque>". But I think setting it
+ to NULL is right, and the printing code can print it as
+ "enum {...}". */
+ TYPE_TAG_NAME (type) = NULL;
+ TYPE_LENGTH (type) = 0;
+ TYPE_FIELDS (type) = 0;
+ TYPE_NFIELDS(type) = 0;
+ }
+ else
+ {
+ type = coff_read_enum_type (cs->c_symnum,
+ aux->x_sym.x_misc.x_lnsz.x_size,
+ aux->x_sym.x_fcnary.x_fcn.x_endndx.l);
+ }
+ return type;
+
+ case T_MOE:
+ /* shouldn't show up here */
+ break;
+
+ case T_UCHAR:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+
+ case T_USHORT:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+
+ case T_UINT:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+
+ case T_ULONG:
+ return lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
+ }
+ complain (&unexpected_type_complaint, cs->c_name);
+ return lookup_fundamental_type (current_objfile, FT_VOID);
+}
+
+/* This page contains subroutines of read_type. */
+
+/* Read the description of a structure (or union type) and return an
+ object describing the type. */
+
+static struct type *
+coff_read_struct_type (index, length, lastsym)
+ int index;
+ int length;
+ int lastsym;
+{
+ struct nextfield
+ {
+ struct nextfield *next;
+ struct field field;
+ };
+
+ register struct type *type;
+ register struct nextfield *list = 0;
+ struct nextfield *new;
+ int nfields = 0;
+ register int n;
+ char *name;
+ struct coff_symbol member_sym;
+ register struct coff_symbol *ms = &member_sym;
+ struct internal_syment sub_sym;
+ union internal_auxent sub_aux;
+ int done = 0;
+
+ type = coff_alloc_type (index);
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ INIT_CPLUS_SPECIFIC(type);
+ TYPE_LENGTH (type) = length;
+
+ while (!done && symnum < lastsym && symnum < nlist_nsyms_global)
+ {
+ read_one_sym (ms, &sub_sym, &sub_aux);
+ name = ms->c_name;
+ name = EXTERNAL_NAME (name, current_objfile->obfd);
+
+ switch (ms->c_sclass)
+ {
+ case C_MOS:
+ case C_MOU:
+
+ /* Get space to record the next field's data. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ /* Save the data. */
+ list->field.name =
+ obsavestring (name,
+ strlen (name),
+ &current_objfile->symbol_obstack);
+ list->field.type = decode_type (ms, ms->c_type, &sub_aux);
+ list->field.bitpos = 8 * ms->c_value;
+ list->field.bitsize = 0;
+ nfields++;
+ break;
+
+ case C_FIELD:
+
+ /* Get space to record the next field's data. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new->next = list;
+ list = new;
+
+ /* Save the data. */
+ list->field.name =
+ obsavestring (name,
+ strlen (name),
+ &current_objfile->symbol_obstack);
+ list->field.type = decode_type (ms, ms->c_type, &sub_aux);
+ list->field.bitpos = ms->c_value;
+ list->field.bitsize = sub_aux.x_sym.x_misc.x_lnsz.x_size;
+ nfields++;
+ break;
+
+ case C_EOS:
+ done = 1;
+ break;
+ }
+ }
+ /* Now create the vector of fields, and record how big it is. */
+
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nfields);
+
+ /* Copy the saved-up fields into the field vector. */
+
+ for (n = nfields; list; list = list->next)
+ TYPE_FIELD (type, --n) = list->field;
+
+ return type;
+}
+
+/* Read a definition of an enumeration type,
+ and create and return a suitable type object.
+ Also defines the symbols that represent the values of the type. */
+
+/* ARGSUSED */
+static struct type *
+coff_read_enum_type (index, length, lastsym)
+ int index;
+ int length;
+ int lastsym;
+{
+ register struct symbol *sym;
+ register struct type *type;
+ int nsyms = 0;
+ int done = 0;
+ struct pending **symlist;
+ struct coff_symbol member_sym;
+ register struct coff_symbol *ms = &member_sym;
+ struct internal_syment sub_sym;
+ union internal_auxent sub_aux;
+ struct pending *osyms, *syms;
+ int o_nsyms;
+ register int n;
+ char *name;
+
+ type = coff_alloc_type (index);
+ if (within_function)
+ symlist = &local_symbols;
+ else
+ symlist = &file_symbols;
+ osyms = *symlist;
+ o_nsyms = osyms ? osyms->nsyms : 0;
+
+ while (!done && symnum < lastsym && symnum < nlist_nsyms_global)
+ {
+ read_one_sym (ms, &sub_sym, &sub_aux);
+ name = ms->c_name;
+ name = EXTERNAL_NAME (name, current_objfile->obfd);
+
+ switch (ms->c_sclass)
+ {
+ case C_MOE:
+ sym = (struct symbol *) obstack_alloc
+ (&current_objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+
+ SYMBOL_NAME (sym) =
+ obsavestring (name, strlen (name),
+ &current_objfile->symbol_obstack);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE (sym) = ms->c_value;
+ add_symbol_to_list (sym, symlist);
+ nsyms++;
+ break;
+
+ case C_EOS:
+ /* Sometimes the linker (on 386/ix 2.0.2 at least) screws
+ up the count of how many symbols to read. So stop
+ on .eos. */
+ done = 1;
+ break;
+ }
+ }
+
+ /* Now fill in the fields of the type-structure. */
+
+ if (length > 0)
+ TYPE_LENGTH (type) = length;
+ else
+ TYPE_LENGTH (type) = TARGET_INT_BIT / TARGET_CHAR_BIT; /* Assume ints */
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nsyms);
+
+ /* Find the symbols for the values and put them into the type.
+ The symbols can be found in the symlist that we put them on
+ to cause them to be defined. osyms contains the old value
+ of that symlist; everything up to there was defined by us. */
+ /* Note that we preserve the order of the enum constants, so
+ that in something like "enum {FOO, LAST_THING=FOO}" we print
+ FOO, not LAST_THING. */
+
+ for (syms = *symlist, n = 0; syms; syms = syms->next)
+ {
+ int j = 0;
+
+ if (syms == osyms)
+ j = o_nsyms;
+ for (; j < syms->nsyms; j++,n++)
+ {
+ struct symbol *xsym = syms->symbol[j];
+ SYMBOL_TYPE (xsym) = type;
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_VALUE (type, n) = 0;
+ TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+ return type;
+}
+
+struct section_offsets *
+coff_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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);
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+/* Register our ability to parse symbols for coff BFD files. */
+
+static struct sym_fns coff_sym_fns =
+{
+ 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 */
+ coff_symfile_finish, /* sym_finish: finished with file, cleanup */
+ coff_symfile_offsets, /* sym_offsets: xlate external to internal form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_coffread ()
+{
+ add_symtab_fns (&coff_sym_fns);
+}
diff --git a/contrib/gdb/gdb/command.c b/contrib/gdb/gdb/command.c
new file mode 100644
index 0000000..a5477dd
--- /dev/null
+++ b/contrib/gdb/gdb/command.c
@@ -0,0 +1,1466 @@
+/* Handle lists of commands, their decoding and documentation, for GDB.
+ Copyright 1986, 1989, 1990, 1991 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "value.h"
+#include "wait.h"
+#include <ctype.h>
+#include "gdb_string.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Prototypes for local functions */
+
+static void
+undef_cmd_error PARAMS ((char *, char *));
+
+static void
+show_user PARAMS ((char *, int));
+
+static void
+show_user_1 PARAMS ((struct cmd_list_element *, GDB_FILE *));
+
+static void
+make_command PARAMS ((char *, int));
+
+static void
+shell_escape PARAMS ((char *, int));
+
+static int
+parse_binary_operation PARAMS ((char *));
+
+static void
+print_doc_line PARAMS ((GDB_FILE *, char *));
+
+/* Add element named NAME.
+ CLASS is the top level category into which commands are broken down
+ for "help" purposes.
+ FUN should be the function to execute the command;
+ it will get a character string as argument, with leading
+ and trailing blanks already eliminated.
+
+ DOC is a documentation string for the command.
+ Its first line should be a complete sentence.
+ It should start with ? for a command that is an abbreviation
+ or with * for a command that most users don't need to know about.
+
+ Add this command to command list *LIST. */
+
+struct cmd_list_element *
+add_cmd (name, class, fun, doc, list)
+ char *name;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+ delete_cmd (name, list);
+ c->next = *list;
+ c->name = name;
+ c->class = class;
+ c->function.cfunc = fun;
+ c->doc = doc;
+ c->hook = NULL;
+ c->prefixlist = NULL;
+ c->prefixname = NULL;
+ c->allow_unknown = 0;
+ c->abbrev_flag = 0;
+ c->completer = make_symbol_completion_list;
+ c->type = not_set_cmd;
+ c->var = NULL;
+ c->var_type = var_boolean;
+ c->enums = NULL;
+ c->user_commands = NULL;
+ c->hookee = NULL;
+ c->cmd_pointer = NULL;
+ *list = c;
+ return c;
+}
+
+/* Same as above, except that the abbrev_flag is set. */
+
+#if 0 /* Currently unused */
+
+struct cmd_list_element *
+add_abbrev_cmd (name, class, fun, doc, list)
+ char *name;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ char *doc;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c
+ = add_cmd (name, class, fun, doc, list);
+
+ c->abbrev_flag = 1;
+ return c;
+}
+
+#endif
+
+struct cmd_list_element *
+add_alias_cmd (name, oldname, class, abbrev_flag, list)
+ char *name;
+ char *oldname;
+ enum command_class class;
+ int abbrev_flag;
+ struct cmd_list_element **list;
+{
+ /* Must do this since lookup_cmd tries to side-effect its first arg */
+ char *copied_name;
+ register struct cmd_list_element *old;
+ register struct cmd_list_element *c;
+ copied_name = (char *) alloca (strlen (oldname) + 1);
+ strcpy (copied_name, oldname);
+ old = lookup_cmd (&copied_name, *list, "", 1, 1);
+
+ if (old == 0)
+ {
+ delete_cmd (name, list);
+ return 0;
+ }
+
+ c = add_cmd (name, class, old->function.cfunc, old->doc, list);
+ c->prefixlist = old->prefixlist;
+ c->prefixname = old->prefixname;
+ c->allow_unknown = old->allow_unknown;
+ c->abbrev_flag = abbrev_flag;
+ c->cmd_pointer = old;
+ return c;
+}
+
+/* Like add_cmd but adds an element for a command prefix:
+ a name that should be followed by a subcommand to be looked up
+ in another command list. PREFIXLIST should be the address
+ of the variable containing that list. */
+
+struct cmd_list_element *
+add_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+ allow_unknown, list)
+ char *name;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ return c;
+}
+
+/* Like add_prefix_cmd but sets the abbrev_flag on the new command. */
+
+struct cmd_list_element *
+add_abbrev_prefix_cmd (name, class, fun, doc, prefixlist, prefixname,
+ allow_unknown, list)
+ char *name;
+ enum command_class class;
+ void (*fun) PARAMS ((char *, int));
+ char *doc;
+ struct cmd_list_element **prefixlist;
+ char *prefixname;
+ int allow_unknown;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c = add_cmd (name, class, fun, doc, list);
+ c->prefixlist = prefixlist;
+ c->prefixname = prefixname;
+ c->allow_unknown = allow_unknown;
+ c->abbrev_flag = 1;
+ return c;
+}
+
+/* This is an empty "cfunc". */
+void
+not_just_help_class_command (args, from_tty)
+ char *args;
+ int 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.
+ VAR_TYPE is the kind of thing we are setting.
+ VAR is address of the variable being controlled by this command.
+ DOC is the documentation string. */
+
+struct cmd_list_element *
+add_set_cmd (name, class, var_type, var, doc, list)
+ char *name;
+ enum command_class class;
+ var_types var_type;
+ char *var;
+ char *doc;
+ struct cmd_list_element **list;
+{
+ struct cmd_list_element *c
+ = 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;
+}
+
+/* Add element named NAME to command list LIST (the list for set
+ or some sublist thereof).
+ CLASS is as in add_cmd.
+ ENUMLIST is a list of strings which may follow NAME.
+ VAR is address of the variable which will contain the matching string
+ (from ENUMLIST).
+ DOC is the documentation string. */
+
+struct cmd_list_element *
+add_set_enum_cmd (name, class, enumlist, var, doc, list)
+ char *name;
+ enum command_class class;
+ char *enumlist[];
+ char *var;
+ char *doc;
+ struct cmd_list_element **list;
+{
+ struct cmd_list_element *c
+ = add_set_cmd (name, class, var_enum, var, doc, list);
+
+ c->enums = enumlist;
+
+ return c;
+}
+
+/* Where SETCMD has already been added, add the corresponding show
+ command to LIST and return a pointer to it. */
+struct cmd_list_element *
+add_show_from_set (setcmd, list)
+ struct cmd_list_element *setcmd;
+ struct cmd_list_element **list;
+{
+ struct cmd_list_element *showcmd =
+ (struct cmd_list_element *) xmalloc (sizeof (struct cmd_list_element));
+
+ memcpy (showcmd, setcmd, sizeof (struct cmd_list_element));
+ delete_cmd (showcmd->name, list);
+ showcmd->type = show_cmd;
+
+ /* Replace "set " at start of docstring with "show ". */
+ if (setcmd->doc[0] == 'S' && setcmd->doc[1] == 'e'
+ && setcmd->doc[2] == 't' && setcmd->doc[3] == ' ')
+ showcmd->doc = concat ("Show ", setcmd->doc + 4, NULL);
+ else
+ fprintf_unfiltered (gdb_stderr, "GDB internal error: Bad docstring for set command\n");
+
+ showcmd->next = *list;
+ *list = showcmd;
+ return showcmd;
+}
+
+/* Remove the command named NAME from the command list. */
+
+void
+delete_cmd (name, list)
+ char *name;
+ struct cmd_list_element **list;
+{
+ register struct cmd_list_element *c;
+ struct cmd_list_element *p;
+
+ while (*list && STREQ ((*list)->name, name))
+ {
+ if ((*list)->hookee)
+ (*list)->hookee->hook = 0; /* Hook slips out of its mouth */
+ p = (*list)->next;
+ free ((PTR)*list);
+ *list = p;
+ }
+
+ if (*list)
+ for (c = *list; c->next;)
+ {
+ if (STREQ (c->next->name, name))
+ {
+ if (c->next->hookee)
+ c->next->hookee->hook = 0; /* hooked cmd gets away. */
+ p = c->next->next;
+ free ((PTR)c->next);
+ c->next = p;
+ }
+ else
+ c = c->next;
+ }
+}
+
+/* This command really has to deal with two things:
+ * 1) I want documentation on *this string* (usually called by
+ * "help commandname").
+ * 2) I want documentation on *this list* (usually called by
+ * giving a command that requires subcommands. Also called by saying
+ * just "help".)
+ *
+ * I am going to split this into two seperate comamnds, help_cmd and
+ * help_list.
+ */
+
+void
+help_cmd (command, stream)
+ char *command;
+ GDB_FILE *stream;
+{
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
+
+ if (!command)
+ {
+ help_list (cmdlist, "", all_classes, stream);
+ return;
+ }
+
+ c = lookup_cmd (&command, cmdlist, "", 0, 0);
+
+ if (c == 0)
+ return;
+
+ /* There are three cases here.
+ If c->prefixlist is nonzero, we have a prefix command.
+ Print its documentation, then list its subcommands.
+
+ If c->function is nonzero, we really have a command.
+ Print its documentation and return.
+
+ If c->function is zero, we have a class name.
+ Print its documentation (as if it were a command)
+ and then set class to the number of this class
+ so that the commands in the class will be listed. */
+
+ fputs_filtered (c->doc, stream);
+ fputs_filtered ("\n", stream);
+
+ if (c->prefixlist == 0 && c->function.cfunc != NULL)
+ return;
+ fprintf_filtered (stream, "\n");
+
+ /* If this is a prefix command, print it's subcommands */
+ if (c->prefixlist)
+ help_list (*c->prefixlist, c->prefixname, all_commands, stream);
+
+ /* If this is a class name, print all of the commands in the class */
+ if (c->function.cfunc == NULL)
+ help_list (cmdlist, "", c->class, stream);
+
+ if (c->hook)
+ fprintf_filtered (stream, "\nThis command has a hook defined: %s\n",
+ c->hook->name);
+}
+
+/*
+ * Get a specific kind of help on a command list.
+ *
+ * LIST is the list.
+ * CMDTYPE is the prefix to use in the title string.
+ * CLASS is the class with which to list the nodes of this list (see
+ * documentation for help_cmd_list below), As usual, ALL_COMMANDS for
+ * everything, ALL_CLASSES for just classes, and non-negative for only things
+ * in a specific class.
+ * and STREAM is the output stream on which to print things.
+ * If you call this routine with a class >= 0, it recurses.
+ */
+void
+help_list (list, cmdtype, class, stream)
+ struct cmd_list_element *list;
+ char *cmdtype;
+ enum command_class class;
+ GDB_FILE *stream;
+{
+ int len;
+ char *cmdtype1, *cmdtype2;
+
+ /* If CMDTYPE is "foo ", CMDTYPE1 gets " foo" and CMDTYPE2 gets "foo sub" */
+ len = strlen (cmdtype);
+ cmdtype1 = (char *) alloca (len + 1);
+ cmdtype1[0] = 0;
+ cmdtype2 = (char *) alloca (len + 4);
+ cmdtype2[0] = 0;
+ if (len)
+ {
+ cmdtype1[0] = ' ';
+ strncpy (cmdtype1 + 1, cmdtype, len - 1);
+ cmdtype1[len] = 0;
+ strncpy (cmdtype2, cmdtype, len - 1);
+ strcpy (cmdtype2 + len - 1, " sub");
+ }
+
+ if (class == all_classes)
+ fprintf_filtered (stream, "List of classes of %scommands:\n\n", cmdtype2);
+ else
+ fprintf_filtered (stream, "List of %scommands:\n\n", cmdtype2);
+
+ help_cmd_list (list, class, cmdtype, (int)class >= 0, stream);
+
+ if (class == all_classes)
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by a class name for a list of commands in that class.",
+ cmdtype1);
+
+ fprintf_filtered (stream, "\n\
+Type \"help%s\" followed by %scommand name for full documentation.\n\
+Command name abbreviations are allowed if unambiguous.\n",
+ cmdtype1, cmdtype2);
+}
+
+/* Print only the first line of STR on STREAM. */
+static void
+print_doc_line (stream, str)
+ GDB_FILE *stream;
+ char *str;
+{
+ static char *line_buffer = 0;
+ static int line_size;
+ register char *p;
+
+ if (!line_buffer)
+ {
+ line_size = 80;
+ line_buffer = (char *) xmalloc (line_size);
+ }
+
+ p = str;
+ while (*p && *p != '\n' && *p != '.' && *p != ',')
+ p++;
+ if (p - str > line_size - 1)
+ {
+ line_size = p - str + 1;
+ free ((PTR)line_buffer);
+ line_buffer = (char *) xmalloc (line_size);
+ }
+ strncpy (line_buffer, str, p - str);
+ line_buffer[p - str] = '\0';
+ if (islower (line_buffer[0]))
+ line_buffer[0] = toupper (line_buffer[0]);
+ fputs_filtered (line_buffer, stream);
+}
+
+/*
+ * Implement a help command on command list LIST.
+ * RECURSE should be non-zero if this should be done recursively on
+ * all sublists of LIST.
+ * PREFIX is the prefix to print before each command name.
+ * STREAM is the stream upon which the output should be written.
+ * CLASS should be:
+ * A non-negative class number to list only commands in that
+ * class.
+ * ALL_COMMANDS to list all commands in list.
+ * ALL_CLASSES to list all classes in list.
+ *
+ * Note that RECURSE will be active on *all* sublists, not just the
+ * ones selected by the criteria above (ie. the selection mechanism
+ * is at the low level, not the high-level).
+ */
+void
+help_cmd_list (list, class, prefix, recurse, stream)
+ struct cmd_list_element *list;
+ enum command_class class;
+ char *prefix;
+ int recurse;
+ GDB_FILE *stream;
+{
+ register struct cmd_list_element *c;
+
+ for (c = list; c; c = c->next)
+ {
+ if (c->abbrev_flag == 0 &&
+ (class == all_commands
+ || (class == all_classes && c->function.cfunc == NULL)
+ || (class == c->class && c->function.cfunc != NULL)))
+ {
+ fprintf_filtered (stream, "%s%s -- ", prefix, c->name);
+ print_doc_line (stream, c->doc);
+ fputs_filtered ("\n", stream);
+ }
+ if (recurse
+ && c->prefixlist != 0
+ && c->abbrev_flag == 0)
+ help_cmd_list (*c->prefixlist, class, c->prefixname, 1, stream);
+ }
+}
+
+/* This routine takes a line of TEXT and a CLIST in which to start the
+ lookup. When it returns it will have incremented the text pointer past
+ the section of text it matched, set *RESULT_LIST to point to the list in
+ which the last word was matched, and will return a pointer to the cmd
+ list element which the text matches. It will return NULL if no match at
+ all was possible. It will return -1 (cast appropriately, ick) if ambigous
+ matches are possible; in this case *RESULT_LIST will be set to point to
+ the list in which there are ambiguous choices (and *TEXT will be set to
+ the ambiguous text string).
+
+ If the located command was an abbreviation, this routine returns the base
+ command of the abbreviation.
+
+ It does no error reporting whatsoever; control will always return
+ to the superior routine.
+
+ In the case of an ambiguous return (-1), *RESULT_LIST will be set to point
+ at the prefix_command (ie. the best match) *or* (special case) will be NULL
+ if no prefix command was ever found. For example, in the case of "info a",
+ "info" matches without ambiguity, but "a" could be "args" or "address", so
+ *RESULT_LIST is set to the cmd_list_element for "info". So in this case
+ RESULT_LIST should not be interpeted as a pointer to the beginning of a
+ list; it simply points to a specific command. In the case of an ambiguous
+ return *TEXT is advanced past the last non-ambiguous prefix (e.g.
+ "info t" can be "info types" or "info target"; upon return *TEXT has been
+ advanced past "info ").
+
+ If RESULT_LIST is NULL, don't set *RESULT_LIST (but don't otherwise
+ affect the operation).
+
+ This routine does *not* modify the text pointed to by TEXT.
+
+ If IGNORE_HELP_CLASSES is nonzero, ignore any command list elements which
+ are actually help classes rather than commands (i.e. the function field of
+ the struct cmd_list_element is NULL). */
+
+struct cmd_list_element *
+lookup_cmd_1 (text, clist, result_list, ignore_help_classes)
+ char **text;
+ struct cmd_list_element *clist, **result_list;
+ int ignore_help_classes;
+{
+ char *p, *command;
+ int len, tmp, nfound;
+ struct cmd_list_element *found, *c;
+
+ while (**text == ' ' || **text == '\t')
+ (*text)++;
+
+ /* Treating underscores as part of command words is important
+ so that "set args_foo()" doesn't get interpreted as
+ "set args _foo()". */
+ for (p = *text;
+ *p && (isalnum(*p) || *p == '-' || *p == '_');
+ p++)
+ ;
+
+ /* If nothing but whitespace, return 0. */
+ if (p == *text)
+ return 0;
+
+ len = p - *text;
+
+ /* *text and p now bracket the first command word to lookup (and
+ it's length is len). We copy this into a local temporary,
+ converting to lower case as we go. */
+
+ command = (char *) alloca (len + 1);
+ for (tmp = 0; tmp < len; tmp++)
+ {
+ char x = (*text)[tmp];
+ command[tmp] = isupper(x) ? tolower(x) : x;
+ }
+ command[len] = '\0';
+
+ /* Look it up. */
+ found = 0;
+ nfound = 0;
+ for (c = clist; c; c = c->next)
+ if (!strncmp (command, c->name, len)
+ && (!ignore_help_classes || c->function.cfunc))
+ {
+ found = c;
+ nfound++;
+ if (c->name[len] == '\0')
+ {
+ nfound = 1;
+ break;
+ }
+ }
+
+ /* If nothing matches, we have a simple failure. */
+ if (nfound == 0)
+ return 0;
+
+ if (nfound > 1)
+ {
+ if (result_list != NULL)
+ /* Will be modified in calling routine
+ if we know what the prefix command is. */
+ *result_list = 0;
+ return (struct cmd_list_element *) -1; /* Ambiguous. */
+ }
+
+ /* We've matched something on this list. Move text pointer forward. */
+
+ *text = p;
+
+ /* If this was an abbreviation, use the base command instead. */
+
+ if (found->cmd_pointer)
+ found = found->cmd_pointer;
+
+ /* If we found a prefix command, keep looking. */
+
+ if (found->prefixlist)
+ {
+ c = lookup_cmd_1 (text, *found->prefixlist, result_list,
+ ignore_help_classes);
+ if (!c)
+ {
+ /* Didn't find anything; this is as far as we got. */
+ if (result_list != NULL)
+ *result_list = clist;
+ return found;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* We've gotten this far properley, but the next step
+ is ambiguous. We need to set the result list to the best
+ we've found (if an inferior hasn't already set it). */
+ if (result_list != NULL)
+ if (!*result_list)
+ /* This used to say *result_list = *found->prefixlist
+ If that was correct, need to modify the documentation
+ at the top of this function to clarify what is supposed
+ to be going on. */
+ *result_list = found;
+ return c;
+ }
+ else
+ {
+ /* We matched! */
+ return c;
+ }
+ }
+ else
+ {
+ if (result_list != NULL)
+ *result_list = clist;
+ return found;
+ }
+}
+
+/* All this hair to move the space to the front of cmdtype */
+
+static void
+undef_cmd_error (cmdtype, q)
+ char *cmdtype, *q;
+{
+ error ("Undefined %scommand: \"%s\". Try \"help%s%.*s\".",
+ cmdtype,
+ q,
+ *cmdtype? " ": "",
+ strlen(cmdtype)-1,
+ cmdtype);
+}
+
+/* Look up the contents of *LINE as a command in the command list LIST.
+ LIST is a chain of struct cmd_list_element's.
+ If it is found, return the struct cmd_list_element for that command
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message.
+
+ If INGNORE_HELP_CLASSES is nonzero, ignore any command list
+ elements which are actually help classes rather than commands (i.e.
+ the function field of the struct cmd_list_element is 0). */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown, ignore_help_classes)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+ int 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)
+ {
+ if (!allow_unknown)
+ {
+ if (!*line)
+ error ("Lack of needed %scommand", cmdtype);
+ else
+ {
+ char *p = *line, *q;
+
+ while (isalnum(*p) || *p == '-')
+ p++;
+
+ q = (char *) alloca (p - *line + 1);
+ strncpy (q, *line, p - *line);
+ q[p-*line] = '\0';
+ undef_cmd_error (cmdtype, q);
+ }
+ }
+ else
+ return 0;
+ }
+ else if (c == (struct cmd_list_element *) -1)
+ {
+ /* Ambigous. Local values should be off prefixlist or called
+ values. */
+ int local_allow_unknown = (last_list ? last_list->allow_unknown :
+ allow_unknown);
+ char *local_cmdtype = last_list ? last_list->prefixname : cmdtype;
+ struct cmd_list_element *local_list =
+ (last_list ? *(last_list->prefixlist) : list);
+
+ if (local_allow_unknown < 0)
+ {
+ if (last_list)
+ return last_list; /* Found something. */
+ else
+ return 0; /* Found nothing. */
+ }
+ else
+ {
+ /* Report as error. */
+ int amb_len;
+ char ambbuf[100];
+
+ for (amb_len = 0;
+ ((*line)[amb_len] && (*line)[amb_len] != ' '
+ && (*line)[amb_len] != '\t');
+ amb_len++)
+ ;
+
+ ambbuf[0] = 0;
+ for (c = local_list; c; c = c->next)
+ if (!strncmp (*line, c->name, amb_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < (int)sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", local_cmdtype,
+ *line, ambbuf);
+ return 0; /* lint */
+ }
+ }
+ else
+ {
+ /* We've got something. It may still not be what the caller
+ wants (if this command *needs* a subcommand). */
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ if (c->prefixlist && **line && !c->allow_unknown)
+ undef_cmd_error (c->prefixname, *line);
+
+ /* Seems to be what he wants. Return it. */
+ return c;
+ }
+ return 0;
+}
+
+#if 0
+/* Look up the contents of *LINE as a command in the command list LIST.
+ LIST is a chain of struct cmd_list_element's.
+ If it is found, return the struct cmd_list_element for that command
+ and update *LINE to point after the command name, at the first argument.
+ If not found, call error if ALLOW_UNKNOWN is zero
+ otherwise (or if error returns) return zero.
+ Call error if specified command is ambiguous,
+ unless ALLOW_UNKNOWN is negative.
+ CMDTYPE precedes the word "command" in the error message. */
+
+struct cmd_list_element *
+lookup_cmd (line, list, cmdtype, allow_unknown)
+ char **line;
+ struct cmd_list_element *list;
+ char *cmdtype;
+ int allow_unknown;
+{
+ register char *p;
+ register struct cmd_list_element *c, *found;
+ int nfound;
+ char ambbuf[100];
+ char *processed_cmd;
+ int i, cmd_len;
+
+ /* Skip leading whitespace. */
+
+ while (**line == ' ' || **line == '\t')
+ (*line)++;
+
+ /* Clear out trailing whitespace. */
+
+ p = *line + strlen (*line);
+ while (p != *line && (p[-1] == ' ' || p[-1] == '\t'))
+ p--;
+ *p = 0;
+
+ /* Find end of command name. */
+
+ p = *line;
+ while (*p == '-' || isalnum(*p))
+ p++;
+
+ /* Look up the command name.
+ If exact match, keep that.
+ Otherwise, take command abbreviated, if unique. Note that (in my
+ opinion) a null string does *not* indicate ambiguity; simply the
+ end of the argument. */
+
+ if (p == *line)
+ {
+ if (!allow_unknown)
+ error ("Lack of needed %scommand", cmdtype);
+ return 0;
+ }
+
+ /* Copy over to a local buffer, converting to lowercase on the way.
+ This is in case the command being parsed is a subcommand which
+ doesn't match anything, and that's ok. We want the original
+ untouched for the routine of the original command. */
+
+ processed_cmd = (char *) alloca (p - *line + 1);
+ for (cmd_len = 0; cmd_len < p - *line; cmd_len++)
+ {
+ char x = (*line)[cmd_len];
+ if (isupper(x))
+ processed_cmd[cmd_len] = tolower(x);
+ else
+ processed_cmd[cmd_len] = x;
+ }
+ processed_cmd[cmd_len] = '\0';
+
+ /* Check all possibilities in the current command list. */
+ found = 0;
+ nfound = 0;
+ for (c = list; c; c = c->next)
+ {
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ found = c;
+ nfound++;
+ if (c->name[cmd_len] == 0)
+ {
+ nfound = 1;
+ break;
+ }
+ }
+ }
+
+ /* Report error for undefined command name. */
+
+ if (nfound != 1)
+ {
+ if (nfound > 1 && allow_unknown >= 0)
+ {
+ ambbuf[0] = 0;
+ for (c = list; c; c = c->next)
+ if (!strncmp (processed_cmd, c->name, cmd_len))
+ {
+ if (strlen (ambbuf) + strlen (c->name) + 6 < sizeof ambbuf)
+ {
+ if (strlen (ambbuf))
+ strcat (ambbuf, ", ");
+ strcat (ambbuf, c->name);
+ }
+ else
+ {
+ strcat (ambbuf, "..");
+ break;
+ }
+ }
+ error ("Ambiguous %scommand \"%s\": %s.", cmdtype,
+ processed_cmd, ambbuf);
+ }
+ else if (!allow_unknown)
+ error ("Undefined %scommand: \"%s\".", cmdtype, processed_cmd);
+ return 0;
+ }
+
+ /* Skip whitespace before the argument. */
+
+ while (*p == ' ' || *p == '\t') p++;
+ *line = p;
+
+ if (found->prefixlist && *p)
+ {
+ c = lookup_cmd (line, *found->prefixlist, found->prefixname,
+ found->allow_unknown);
+ if (c)
+ return c;
+ }
+
+ return found;
+}
+#endif
+
+/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
+
+/* Return a vector of char pointers which point to the different
+ possible completions in LIST of TEXT.
+
+ WORD points in the same buffer as TEXT, and completions should be
+ returned relative to this position. For example, suppose TEXT is "foo"
+ and we want to complete to "foobar". If WORD is "oo", return
+ "oobar"; if WORD is "baz/foo", return "baz/foobar". */
+
+char **
+complete_on_cmdlist (list, text, word)
+ struct cmd_list_element *list;
+ char *text;
+ char *word;
+{
+ struct cmd_list_element *ptr;
+ char **matchlist;
+ int sizeof_matchlist;
+ int matches;
+ int textlen = strlen (text);
+
+ sizeof_matchlist = 10;
+ matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
+ matches = 0;
+
+ for (ptr = list; ptr; ptr = ptr->next)
+ if (!strncmp (ptr->name, text, textlen)
+ && !ptr->abbrev_flag
+ && (ptr->function.cfunc
+ || ptr->prefixlist))
+ {
+ if (matches == sizeof_matchlist)
+ {
+ sizeof_matchlist *= 2;
+ matchlist = (char **) xrealloc ((char *)matchlist,
+ (sizeof_matchlist
+ * sizeof (char *)));
+ }
+
+ matchlist[matches] = (char *)
+ xmalloc (strlen (word) + strlen (ptr->name) + 1);
+ if (word == text)
+ strcpy (matchlist[matches], ptr->name);
+ else if (word > text)
+ {
+ /* Return some portion of ptr->name. */
+ strcpy (matchlist[matches], ptr->name + (word - text));
+ }
+ else
+ {
+ /* Return some of text plus ptr->name. */
+ strncpy (matchlist[matches], word, text - word);
+ matchlist[matches][text - word] = '\0';
+ strcat (matchlist[matches], ptr->name);
+ }
+ ++matches;
+ }
+
+ if (matches == 0)
+ {
+ free ((PTR)matchlist);
+ matchlist = 0;
+ }
+ else
+ {
+ matchlist = (char **) xrealloc ((char *)matchlist, ((matches + 1)
+ * sizeof (char *)));
+ matchlist[matches] = (char *) 0;
+ }
+
+ return matchlist;
+}
+
+/* Helper function for SYMBOL_COMPLETION_FUNCTION. */
+
+/* Return a vector of char pointers which point to the different
+ possible completions in CMD of TEXT.
+
+ WORD points in the same buffer as TEXT, and completions should be
+ returned relative to this position. For example, suppose TEXT is "foo"
+ and we want to complete to "foobar". If WORD is "oo", return
+ "oobar"; if WORD is "baz/foo", return "baz/foobar". */
+
+char **
+complete_on_enum (enumlist, text, word)
+ char **enumlist;
+ char *text;
+ char *word;
+{
+ char **matchlist;
+ int sizeof_matchlist;
+ int matches;
+ int textlen = strlen (text);
+ int i;
+ char *name;
+
+ sizeof_matchlist = 10;
+ matchlist = (char **) xmalloc (sizeof_matchlist * sizeof (char *));
+ matches = 0;
+
+ for (i = 0; (name = enumlist[i]) != NULL; i++)
+ if (strncmp (name, text, textlen) == 0)
+ {
+ if (matches == sizeof_matchlist)
+ {
+ sizeof_matchlist *= 2;
+ matchlist = (char **) xrealloc ((char *)matchlist,
+ (sizeof_matchlist
+ * sizeof (char *)));
+ }
+
+ matchlist[matches] = (char *)
+ xmalloc (strlen (word) + strlen (name) + 1);
+ if (word == text)
+ strcpy (matchlist[matches], name);
+ else if (word > text)
+ {
+ /* Return some portion of name. */
+ strcpy (matchlist[matches], name + (word - text));
+ }
+ else
+ {
+ /* Return some of text plus name. */
+ strncpy (matchlist[matches], word, text - word);
+ matchlist[matches][text - word] = '\0';
+ strcat (matchlist[matches], name);
+ }
+ ++matches;
+ }
+
+ if (matches == 0)
+ {
+ free ((PTR)matchlist);
+ matchlist = 0;
+ }
+ else
+ {
+ matchlist = (char **) xrealloc ((char *)matchlist, ((matches + 1)
+ * sizeof (char *)));
+ matchlist[matches] = (char *) 0;
+ }
+
+ return matchlist;
+}
+
+static int
+parse_binary_operation (arg)
+ char *arg;
+{
+ int length;
+
+ if (!arg || !*arg)
+ return 1;
+
+ length = strlen (arg);
+
+ while (arg[length - 1] == ' ' || arg[length - 1] == '\t')
+ length--;
+
+ if (!strncmp (arg, "on", length)
+ || !strncmp (arg, "1", length)
+ || !strncmp (arg, "yes", length))
+ return 1;
+ else
+ if (!strncmp (arg, "off", length)
+ || !strncmp (arg, "0", length)
+ || !strncmp (arg, "no", length))
+ return 0;
+ else
+ {
+ error ("\"on\" or \"off\" expected.");
+ return 0;
+ }
+}
+
+/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
+ of the argument, and FROM_TTY is nonzero if this command is being entered
+ directly by the user (i.e. these are just like any other
+ command). C is the command list element for the command. */
+void
+do_setshow_command (arg, from_tty, c)
+ char *arg;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (c->type == set_cmd)
+ {
+ switch (c->var_type)
+ {
+ case var_string:
+ {
+ char *new;
+ char *p;
+ char *q;
+ int ch;
+
+ if (arg == NULL)
+ arg = "";
+ new = (char *) xmalloc (strlen (arg) + 2);
+ p = arg; q = new;
+ while ((ch = *p++) != '\000')
+ {
+ if (ch == '\\')
+ {
+ /* \ 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);
+ if (ch == 0)
+ break; /* C loses */
+ else if (ch > 0)
+ *q++ = ch;
+ }
+ else
+ *q++ = ch;
+ }
+#if 0
+ if (*(p - 1) != '\\')
+ *q++ = ' ';
+#endif
+ *q++ = '\0';
+ new = (char *) xrealloc (new, q - new);
+ if (*(char **)c->var != NULL)
+ free (*(char **)c->var);
+ *(char **) c->var = new;
+ }
+ break;
+ case var_string_noescape:
+ if (arg == NULL)
+ arg = "";
+ if (*(char **)c->var != NULL)
+ free (*(char **)c->var);
+ *(char **) c->var = savestring (arg, strlen (arg));
+ break;
+ case var_filename:
+ if (arg == NULL)
+ error_no_arg ("filename to set it to.");
+ if (*(char **)c->var != NULL)
+ free (*(char **)c->var);
+ *(char **)c->var = tilde_expand (arg);
+ break;
+ case var_boolean:
+ *(int *) c->var = parse_binary_operation (arg);
+ break;
+ case var_uinteger:
+ if (arg == NULL)
+ error_no_arg ("integer to set it to.");
+ *(unsigned int *) c->var = parse_and_eval_address (arg);
+ if (*(unsigned int *) c->var == 0)
+ *(unsigned int *) c->var = UINT_MAX;
+ break;
+ case var_integer:
+ {
+ unsigned int val;
+ if (arg == NULL)
+ error_no_arg ("integer to set it to.");
+ val = parse_and_eval_address (arg);
+ if (val == 0)
+ *(int *) c->var = INT_MAX;
+ else if (val >= INT_MAX)
+ error ("integer %u out of range", val);
+ else
+ *(int *) c->var = val;
+ break;
+ }
+ case var_zinteger:
+ if (arg == NULL)
+ error_no_arg ("integer to set it to.");
+ *(int *) c->var = parse_and_eval_address (arg);
+ break;
+ case var_enum:
+ {
+ int i;
+ int len;
+ int nmatches;
+ char *match;
+ char *p;
+
+ p = strchr (arg, ' ');
+
+ if (p)
+ len = p - arg;
+ else
+ len = strlen (arg);
+
+ nmatches = 0;
+ for (i = 0; c->enums[i]; i++)
+ if (strncmp (arg, c->enums[i], len) == 0)
+ {
+ match = c->enums[i];
+ nmatches++;
+ }
+
+ if (nmatches <= 0)
+ error ("Undefined item: \"%s\".", arg);
+
+ if (nmatches > 1)
+ error ("Ambiguous item \"%s\".", arg);
+
+ *(char **)c->var = match;
+ }
+ break;
+ default:
+ error ("gdb internal error: bad var_type in do_setshow_command");
+ }
+ }
+ else if (c->type == show_cmd)
+ {
+ /* Print doc minus "show" at start. */
+ print_doc_line (gdb_stdout, c->doc + 5);
+
+ fputs_filtered (" is ", gdb_stdout);
+ wrap_here (" ");
+ switch (c->var_type)
+ {
+ case var_string:
+ {
+ unsigned char *p;
+ fputs_filtered ("\"", gdb_stdout);
+ for (p = *(unsigned char **) c->var; *p != '\0'; p++)
+ gdb_printchar (*p, gdb_stdout, '"');
+ fputs_filtered ("\"", gdb_stdout);
+ }
+ break;
+ case var_string_noescape:
+ case var_filename:
+ case var_enum:
+ 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", gdb_stdout);
+ break;
+ case var_uinteger:
+ if (*(unsigned int *) c->var == UINT_MAX) {
+ fputs_filtered ("unlimited", gdb_stdout);
+ break;
+ }
+ /* else fall through */
+ case var_zinteger:
+ fprintf_filtered (gdb_stdout, "%u", *(unsigned int *) c->var);
+ break;
+ case var_integer:
+ if (*(int *) c->var == INT_MAX)
+ {
+ fputs_filtered ("unlimited", gdb_stdout);
+ }
+ else
+ fprintf_filtered (gdb_stdout, "%d", *(int *) c->var);
+ break;
+
+ default:
+ error ("gdb internal error: bad var_type in do_setshow_command");
+ }
+ fputs_filtered (".\n", gdb_stdout);
+ }
+ else
+ error ("gdb internal error: bad cmd_type in do_setshow_command");
+ (*c->function.sfunc) (NULL, from_tty, c);
+}
+
+/* Show all the settings in a list of show commands. */
+
+void
+cmd_show_list (list, from_tty, prefix)
+ struct cmd_list_element *list;
+ int from_tty;
+ char *prefix;
+{
+ for (; list != NULL; list = list->next) {
+ /* If we find a prefix, run its list, prefixing our output by its
+ prefix (with "show " skipped). */
+ if (list->prefixlist && !list->abbrev_flag)
+ cmd_show_list (*list->prefixlist, from_tty, list->prefixname + 5);
+ if (list->type == show_cmd)
+ {
+ fputs_filtered (prefix, gdb_stdout);
+ fputs_filtered (list->name, gdb_stdout);
+ fputs_filtered (": ", gdb_stdout);
+ do_setshow_command ((char *)NULL, from_tty, list);
+ }
+ }
+}
+
+/* ARGSUSED */
+static void
+shell_escape (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+#ifdef CANT_FORK
+ /* FIXME: what about errors (I don't know how GO32 system() handles
+ them)? */
+ system (arg);
+#else /* Can fork. */
+ int rc, status, pid;
+ char *p, *user_shell;
+
+ if ((user_shell = (char *) getenv ("SHELL")) == NULL)
+ user_shell = "/bin/sh";
+
+ /* Get the name of the shell for arg0 */
+ if ((p = strrchr (user_shell, '/')) == NULL)
+ p = user_shell;
+ else
+ p++; /* Get past '/' */
+
+ if ((pid = fork()) == 0)
+ {
+ if (!arg)
+ execl (user_shell, p, 0);
+ else
+ execl (user_shell, p, "-c", arg, 0);
+
+ fprintf_unfiltered (gdb_stderr, "Cannot execute %s: %s\n", user_shell,
+ safe_strerror (errno));
+ gdb_flush (gdb_stderr);
+ _exit (0177);
+ }
+
+ if (pid != -1)
+ while ((rc = wait (&status)) != pid && rc != -1)
+ ;
+ else
+ error ("Fork failed");
+#endif /* Can fork. */
+}
+
+static void
+make_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ char *p;
+
+ if (arg == 0)
+ p = "make";
+ else
+ {
+ p = xmalloc (sizeof("make ") + strlen(arg));
+ strcpy (p, "make ");
+ strcpy (p + sizeof("make ")-1, arg);
+ }
+
+ shell_escape (p, from_tty);
+}
+
+static void
+show_user_1 (c, stream)
+ struct cmd_list_element *c;
+ GDB_FILE *stream;
+{
+ register struct command_line *cmdlines;
+
+ cmdlines = c->user_commands;
+ if (!cmdlines)
+ return;
+ fputs_filtered ("User command ", stream);
+ fputs_filtered (c->name, stream);
+ fputs_filtered (":\n", stream);
+
+ while (cmdlines)
+ {
+ print_command_line (cmdlines, 4);
+ cmdlines = cmdlines->next;
+ }
+ fputs_filtered ("\n", stream);
+}
+
+/* ARGSUSED */
+static void
+show_user (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct cmd_list_element *c;
+ extern struct cmd_list_element *cmdlist;
+
+ if (args)
+ {
+ c = lookup_cmd (&args, cmdlist, "", 0, 1);
+ if (c->class != class_user)
+ error ("Not a user command.");
+ show_user_1 (c, gdb_stdout);
+ }
+ else
+ {
+ for (c = cmdlist; c; c = c->next)
+ {
+ if (c->class == class_user)
+ show_user_1 (c, gdb_stdout);
+ }
+ }
+}
+
+void
+_initialize_command ()
+{
+ add_com ("shell", class_support, shell_escape,
+ "Execute the rest of the line as a shell command. \n\
+With no arguments, run an inferior shell.");
+ add_com ("make", class_support, make_command,
+ "Run the ``make'' program using the rest of the line as arguments.");
+ add_cmd ("user", no_class, show_user,
+ "Show definitions of user defined commands.\n\
+Argument is the name of the user defined command.\n\
+With no argument, show definitions of all user defined commands.", &showlist);
+}
diff --git a/contrib/gdb/gdb/command.h b/contrib/gdb/gdb/command.h
new file mode 100644
index 0000000..5a20923
--- /dev/null
+++ b/contrib/gdb/gdb/command.h
@@ -0,0 +1,259 @@
+/* Header file for command-reading library command.c.
+ Copyright (C) 1986, 1989, 1990 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (COMMAND_H)
+#define COMMAND_H 1
+
+/* Not a set/show command. Note that some commands which begin with
+ "set" or "show" might be in this category, if their syntax does
+ not fall into one of the following categories. */
+typedef enum cmd_types {
+ not_set_cmd,
+ set_cmd,
+ show_cmd
+} cmd_types;
+
+/* Types of "set" or "show" command. */
+typedef enum var_types {
+ /* "on" or "off". *VAR is an integer which is nonzero for on,
+ zero for off. */
+ var_boolean,
+ /* Unsigned Integer. *VAR is an unsigned int. The user can type 0
+ to mean "unlimited", which is stored in *VAR as UINT_MAX. */
+ var_uinteger,
+
+ /* Like var_uinteger but signed. *VAR is an int. The user can type 0
+ to mean "unlimited", which is stored in *VAR as INT_MAX. */
+ var_integer,
+
+ /* String which the user enters with escapes (e.g. the user types \n and
+ it is a real newline in the stored string).
+ *VAR is a malloc'd string, or NULL if the string is empty. */
+ var_string,
+ /* String which stores what the user types verbatim.
+ *VAR is a malloc'd string, or NULL if the string is empty. */
+ var_string_noescape,
+ /* String which stores a filename.
+ *VAR is a malloc'd string, or NULL if the string is empty. */
+ var_filename,
+ /* ZeroableInteger. *VAR is an int. Like Unsigned Integer except
+ that zero really means zero. */
+ var_zinteger,
+ /* Enumerated type. Can only have one of the specified values. *VAR is a
+ char pointer to the name of the element that we find. */
+ var_enum
+} var_types;
+
+/* This structure records one command'd definition. */
+
+struct cmd_list_element
+ {
+ /* Points to next command in this list. */
+ struct cmd_list_element *next;
+
+ /* Name of this command. */
+ char *name;
+
+ /* Command class; class values are chosen by application program. */
+ enum command_class class;
+
+ /* Function definition of this command.
+ NO_FUNCTION for command class names and for help topics that
+ are not really commands. */
+ 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;
+# define NO_FUNCTION ((void (*) PARAMS((char *args, int from_tty))) 0)
+
+ /* Documentation of this command (or help topic).
+ First line is brief documentation; remaining lines form, with it,
+ the full documentation. First line should end with a period.
+ Entire string should also end with a period, not a newline. */
+ char *doc;
+
+ /* Hook for another command to be executed before this command. */
+ struct cmd_list_element *hook;
+
+ /* Nonzero identifies a prefix command. For them, the address
+ of the variable containing the list of subcommands. */
+ struct cmd_list_element **prefixlist;
+
+ /* For prefix commands only:
+ String containing prefix commands to get here: this one
+ plus any others needed to get to it. Should end in a space.
+ It is used before the word "command" in describing the
+ commands reached through this prefix. */
+ char *prefixname;
+
+ /* For prefix commands only:
+ nonzero means do not get an error if subcommand is not
+ recognized; call the prefix's own function in that case. */
+ char allow_unknown;
+
+ /* Nonzero says this is an abbreviation, and should not
+ be mentioned in lists of commands.
+ This allows "br<tab>" to complete to "break", which it
+ otherwise wouldn't. */
+ char abbrev_flag;
+
+ /* Completion routine for this command. TEXT is the text beyond
+ what was matched for the command itself (leading whitespace is
+ skipped). It stops where we are supposed to stop completing
+ (rl_point) and is '\0' terminated.
+
+ Return value is a malloc'd vector of pointers to possible completions
+ terminated with NULL. If there are no completions, returning a pointer
+ to a NULL would work but returning NULL itself is also valid.
+ WORD points in the same buffer as TEXT, and completions should be
+ returned relative to this position. For example, suppose TEXT is "foo"
+ and we want to complete to "foobar". If WORD is "oo", return
+ "oobar"; if WORD is "baz/foo", return "baz/foobar". */
+ char ** (*completer) PARAMS ((char *text, char *word));
+
+ /* Type of "set" or "show" command (or SET_NOT_SET if not "set"
+ or "show"). */
+ cmd_types type;
+
+ /* Pointer to variable affected by "set" and "show". Doesn't matter
+ if type is not_set. */
+ char *var;
+
+ /* What kind of variable is *VAR? */
+ var_types var_type;
+
+ /* Pointer to NULL terminated list of enumerated values (like argv). */
+ char **enums;
+
+ /* Pointer to command strings of user-defined commands */
+ struct command_line *user_commands;
+
+ /* Pointer to command that is hooked by this one,
+ so the hook can be removed when this one is deleted. */
+ struct cmd_list_element *hookee;
+
+ /* Pointer to command that is aliased by this one, so the
+ aliased command can be located in case it has been hooked. */
+ struct cmd_list_element *cmd_pointer;
+ };
+
+/* Forward-declarations of the entry-points of command.c. */
+
+extern struct cmd_list_element *
+add_cmd PARAMS ((char *, enum command_class, void (*fun) (char *, int),
+ char *, struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_alias_cmd PARAMS ((char *, char *, enum command_class, int,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_prefix_cmd PARAMS ((char *, enum command_class, void (*fun) (char *, int),
+ char *, struct cmd_list_element **, char *, int,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_abbrev_prefix_cmd PARAMS ((char *, enum command_class,
+ void (*fun) (char *, int), char *,
+ struct cmd_list_element **, char *, int,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+lookup_cmd PARAMS ((char **, struct cmd_list_element *, char *, int, int));
+
+extern struct cmd_list_element *
+lookup_cmd_1 PARAMS ((char **, struct cmd_list_element *,
+ struct cmd_list_element **, int));
+
+extern void
+add_com PARAMS ((char *, enum command_class, void (*fun)(char *, int),
+ char *));
+
+extern void
+add_com_alias PARAMS ((char *, char *, enum command_class, int));
+
+extern void
+add_info PARAMS ((char *, void (*fun) (char *, int), char *));
+
+extern void
+add_info_alias PARAMS ((char *, char *, int));
+
+extern char **
+complete_on_cmdlist PARAMS ((struct cmd_list_element *, char *, char *));
+
+extern char **
+complete_on_enum PARAMS ((char **enumlist, char *, char *));
+
+extern void
+delete_cmd PARAMS ((char *, struct cmd_list_element **));
+
+extern void
+help_cmd PARAMS ((char *, GDB_FILE *));
+
+extern void
+help_list PARAMS ((struct cmd_list_element *, char *, enum command_class,
+ GDB_FILE *));
+
+extern void
+help_cmd_list PARAMS ((struct cmd_list_element *, enum command_class, char *,
+ int, GDB_FILE *));
+
+extern struct cmd_list_element *
+add_set_cmd PARAMS ((char *, enum command_class, var_types, char *, char *,
+ struct cmd_list_element **));
+
+extern struct cmd_list_element *
+add_set_enum_cmd PARAMS ((char *name, enum command_class, char *list[],
+ char *var, char *doc, struct cmd_list_element **c));
+
+extern struct cmd_list_element *
+add_show_from_set PARAMS ((struct cmd_list_element *,
+ struct cmd_list_element **));
+
+/* Do a "set" or "show" command. ARG is NULL if no argument, or the text
+ of the argument, and FROM_TTY is nonzero if this command is being entered
+ directly by the user (i.e. these are just like any other
+ command). C is the command list element for the command. */
+
+extern void
+do_setshow_command PARAMS ((char *, int, struct cmd_list_element *));
+
+/* Do a "show" command for each thing on a command list. */
+
+extern void
+cmd_show_list PARAMS ((struct cmd_list_element *, int, char *));
+
+extern void
+error_no_arg PARAMS ((char *));
+
+extern void
+dont_repeat PARAMS ((void));
+
+/* Used to mark commands that don't do anything. If we just leave the
+ function field NULL, the command is interpreted as a help topic, or
+ as a class of commands. */
+
+extern void
+not_just_help_class_command PARAMS ((char *, int));
+
+#endif /* !defined (COMMAND_H) */
diff --git a/contrib/gdb/gdb/complaints.c b/contrib/gdb/gdb/complaints.c
new file mode 100644
index 0000000..9db8b4a
--- /dev/null
+++ b/contrib/gdb/gdb/complaints.c
@@ -0,0 +1,171 @@
+/* Support for complaint handling during symbol reading in GDB.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "complaints.h"
+#include "gdbcmd.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+/* Structure to manage complaints about symbol file contents. */
+
+struct complaint complaint_root[1] = {
+ {
+ (char *) NULL, /* Complaint message */
+ 0, /* Complaint counter */
+ complaint_root /* Next complaint. */
+ }
+};
+
+/* How many complaints about a particular thing should be printed before
+ we stop whining about it? Default is no whining at all, since so many
+ systems have ill-constructed symbol files. */
+
+static unsigned int stop_whining = 0;
+
+/* Should each complaint be self explanatory, or should we assume that
+ a series of complaints is being produced?
+ case 0: self explanatory message.
+ case 1: First message of a series that must start off with explanation.
+ case 2: Subsequent message, when user already knows we are reading
+ symbols and we can just state our piece. */
+
+static int complaint_series = 0;
+
+/* External variables and functions referenced. */
+
+extern int info_verbose;
+
+
+/* Functions to handle complaints during symbol reading. */
+
+/* Print a complaint about the input symbols, and link the complaint block
+ into a chain for later handling. */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+complain (struct complaint *complaint, ...)
+#else
+complain (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, complaint);
+#else
+ struct complaint *complaint;
+
+ va_start (args);
+ complaint = va_arg (args, struct complaint *);
+#endif
+
+ complaint -> counter++;
+ if (complaint -> next == NULL)
+ {
+ complaint -> next = complaint_root -> next;
+ complaint_root -> next = complaint;
+ }
+ if (complaint -> counter > stop_whining)
+ {
+ return;
+ }
+ wrap_here ("");
+
+ switch (complaint_series + (info_verbose << 1))
+ {
+
+ /* Isolated messages, must be self-explanatory. */
+ case 0:
+ begin_line ();
+ puts_filtered ("During symbol reading, ");
+ wrap_here ("");
+ vprintf_filtered (complaint -> message, args);
+ puts_filtered (".\n");
+ break;
+
+ /* First of a series, without `set verbose'. */
+ case 1:
+ begin_line ();
+ puts_filtered ("During symbol reading...");
+ vprintf_filtered (complaint -> message, args);
+ puts_filtered ("...");
+ wrap_here ("");
+ complaint_series++;
+ break;
+
+ /* Subsequent messages of a series, or messages under `set verbose'.
+ (We'll already have produced a "Reading in symbols for XXX..."
+ message and will clean up at the end with a newline.) */
+ default:
+ vprintf_filtered (complaint -> message, args);
+ puts_filtered ("...");
+ wrap_here ("");
+ }
+ /* 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. */
+ gdb_flush (gdb_stdout);
+ va_end (args);
+}
+
+/* Clear out all complaint counters that have ever been incremented.
+ If sym_reading is 1, be less verbose about successive complaints,
+ since the messages are appearing all together during a command that
+ reads symbols (rather than scattered around as psymtabs get fleshed
+ out into symtabs at random times). If noisy is 1, we are in a
+ noisy symbol reading command, and our caller will print enough
+ context for the user to figure it out. */
+
+void
+clear_complaints (sym_reading, noisy)
+ int sym_reading;
+ int noisy;
+{
+ struct complaint *p;
+
+ for (p = complaint_root -> next; p != complaint_root; p = p -> next)
+ {
+ p -> counter = 0;
+ }
+
+ if (!sym_reading && !noisy && complaint_series > 1)
+ {
+ /* Terminate previous series, since caller won't. */
+ puts_filtered ("\n");
+ }
+
+ complaint_series = sym_reading ? 1 + noisy : 0;
+}
+
+void
+_initialize_complaints ()
+{
+ add_show_from_set
+ (add_set_cmd ("complaints", class_support, var_zinteger,
+ (char *) &stop_whining,
+ "Set max number of complaints about incorrect symbols.",
+ &setlist),
+ &showlist);
+
+}
diff --git a/contrib/gdb/gdb/complaints.h b/contrib/gdb/gdb/complaints.h
new file mode 100644
index 0000000..022bc19
--- /dev/null
+++ b/contrib/gdb/gdb/complaints.h
@@ -0,0 +1,46 @@
+/* Definitions for complaint handling during symbol reading in GDB.
+ Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* Support for complaining about things in the symbol file that aren't
+ catastrophic.
+
+ Each such thing gets a counter. The first time we have the problem,
+ during a symbol read, we report it. At the end of symbol reading,
+ if verbose, we report how many of each problem we had. */
+
+struct complaint
+{
+ char *message;
+ unsigned counter;
+ struct complaint *next;
+};
+
+/* Root of the chain of complaints that have at some point been issued.
+ This is used to reset the counters, and/or report the total counts. */
+
+extern struct complaint complaint_root[1];
+
+/* Functions that handle complaints. (in complaints.c) */
+
+extern void
+complain PARAMS ((struct complaint *, ...));
+
+extern void
+clear_complaints PARAMS ((int, int));
diff --git a/contrib/gdb/gdb/config.in b/contrib/gdb/gdb/config.in
new file mode 100644
index 0000000..a5c51ad
--- /dev/null
+++ b/contrib/gdb/gdb/config.in
@@ -0,0 +1,90 @@
+/* config.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+#undef _ALL_SOURCE
+#endif
+
+/* Define if the `long double' type works. */
+#undef HAVE_LONG_DOUBLE
+
+/* Define if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* Define if on MINIX. */
+#undef _MINIX
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define if you need to in order for stat and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+#undef STAT_MACROS_BROKEN
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if fpregset_t type is available. */
+#undef HAVE_FPREGSET_T
+
+/* Define if gregset_t type is available. */
+#undef HAVE_GREGSET_T
+
+/* Define if the "%Lg" format works to print long doubles. */
+#undef PRINTF_HAS_LONG_DOUBLE
+
+/* Define if you have the getpagesize function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define if you have the sbrk function. */
+#undef HAVE_SBRK
+
+/* Define if you have the setpgid function. */
+#undef HAVE_SETPGID
+
+/* Define if you have the valloc function. */
+#undef HAVE_VALLOC
+
+/* Define if you have the <endian.h> header file. */
+#undef HAVE_ENDIAN_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <link.h> header file. */
+#undef HAVE_LINK_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define if you have the <stddef.h> header file. */
+#undef HAVE_STDDEF_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <sys/procfs.h> header file. */
+#undef HAVE_SYS_PROCFS_H
+
+/* Define if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the dl library (-ldl). */
+#undef HAVE_LIBDL
diff --git a/contrib/gdb/gdb/config/i386/cygwin32.mh b/contrib/gdb/gdb/config/i386/cygwin32.mh
new file mode 100644
index 0000000..25f15cf
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/cygwin32.mh
@@ -0,0 +1,6 @@
+MH_CFLAGS=
+XM_FILE=xm-cygwin32.h
+TERMCAP=
+NATDEPFILES=win32-nat.o
+XM_CLIBS=-lkernel32
+
diff --git a/contrib/gdb/gdb/config/i386/cygwin32.mt b/contrib/gdb/gdb/config/i386/cygwin32.mt
new file mode 100644
index 0000000..22b4547
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/cygwin32.mt
@@ -0,0 +1,6 @@
+# Target: Intel 386 run win32
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-cygwin32.h
+
+
+
diff --git a/contrib/gdb/gdb/config/i386/fbsd.mh b/contrib/gdb/gdb/config/i386/fbsd.mh
new file mode 100644
index 0000000..881fa65
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/fbsd.mh
@@ -0,0 +1,5 @@
+# Host: Intel 386 running FreeBSD
+XDEPFILES=
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o core-aout.o i386b-nat.o
+XM_FILE= xm-i386bsd.h
+NAT_FILE= nm-fbsd.h
diff --git a/contrib/gdb/gdb/config/i386/fbsd.mt b/contrib/gdb/gdb/config/i386/fbsd.mt
new file mode 100644
index 0000000..790e137
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/fbsd.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running FreeBSD
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-i386bsd.h
diff --git a/contrib/gdb/gdb/config/i386/gdbserve.mt b/contrib/gdb/gdb/config/i386/gdbserve.mt
new file mode 100644
index 0000000..d8a7cba
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/gdbserve.mt
@@ -0,0 +1,3 @@
+# Target: GDBSERVE.NLM running on a i386
+TDEPFILES= i386.o
+CPU_FILE= i386
diff --git a/contrib/gdb/gdb/config/i386/go32.mh b/contrib/gdb/gdb/config/i386/go32.mh
new file mode 100644
index 0000000..521c7b7
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/go32.mh
@@ -0,0 +1,9 @@
+MH_CFLAGS=-D__GO32__ -D__MSDOS__
+XDEPFILES= go32-xdep.o
+XM_FILE= xm-go32.h
+TERMCAP=
+HOST_IPC=-DDOS_IPC
+SER_HARDWIRE= ser-go32.o
+CC=i386-go32-gcc -O2 -fno-omit-frame-pointer
+
+
diff --git a/contrib/gdb/gdb/config/i386/i386aix.mh b/contrib/gdb/gdb/config/i386/i386aix.mh
new file mode 100644
index 0000000..751f813
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386aix.mh
@@ -0,0 +1,12 @@
+# Host: IBM PS/2 (i386) running AIX PS/2
+
+XM_FILE= xm-i386aix.h
+XDEPFILES=
+
+NAT_FILE= nm-i386aix.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o i386aix-nat.o
+
+TERMCAP=-lcurses
+
+# Use gcc. Only coff output can be debugged
+CC=gcc
diff --git a/contrib/gdb/gdb/config/i386/i386aix.mt b/contrib/gdb/gdb/config/i386/i386aix.mt
new file mode 100644
index 0000000..12e0e1f
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386aix.mt
@@ -0,0 +1,7 @@
+# This port, for aix ps/2 (i386), will allow you to debug the coff
+# output generated gcc-2.3.3 + gas. It will not understand IBM's
+# proprietary debug info.
+#
+# Target: IBM PS/2 (i386) running AIX PS/2
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386aix.h
diff --git a/contrib/gdb/gdb/config/i386/i386aout.mt b/contrib/gdb/gdb/config/i386/i386aout.mt
new file mode 100644
index 0000000..1c94ba5
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386aout.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 with a.out
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386v.h
diff --git a/contrib/gdb/gdb/config/i386/i386bsd.mh b/contrib/gdb/gdb/config/i386/i386bsd.mh
new file mode 100644
index 0000000..f95c6ed
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386bsd.mh
@@ -0,0 +1,7 @@
+# Host: Intel 386 running 386BSD
+
+XM_FILE= xm-i386bsd.h
+XDEPFILES=
+
+NAT_FILE= nm-i386bsd.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o core-aout.o i386b-nat.o
diff --git a/contrib/gdb/gdb/config/i386/i386bsd.mt b/contrib/gdb/gdb/config/i386/i386bsd.mt
new file mode 100644
index 0000000..ef61731
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386bsd.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running BSD
+TM_FILE= tm-i386bsd.h
+TDEPFILES= i386-tdep.o
diff --git a/contrib/gdb/gdb/config/i386/i386dgux.mh b/contrib/gdb/gdb/config/i386/i386dgux.mh
new file mode 100644
index 0000000..bc2cee2
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386dgux.mh
@@ -0,0 +1,14 @@
+# Host: Intel 386 running DGUX, cloned from SVR4
+
+XM_FILE= xm-i386v4.h
+XDEPFILES= ser-tcp.o
+# for network communication
+XM_CLIBS= -lsocket -lnsl
+
+NAT_FILE= nm-i386v4.h
+NATDEPFILES= corelow.o core-regset.o solib.o procfs.o fork-child.o i386v4-nat.o
+
+# SVR4 comes standard with terminfo, and in some implementations, the
+# old termcap descriptions are incomplete. So ensure that we use the
+# new terminfo interface and latest terminal descriptions.
+TERMCAP=-lcurses
diff --git a/contrib/gdb/gdb/config/i386/i386gnu.mh b/contrib/gdb/gdb/config/i386/i386gnu.mh
new file mode 100644
index 0000000..af3186e
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386gnu.mh
@@ -0,0 +1,36 @@
+# Host: Intel 386 running the GNU Hurd
+XDEPFILES= i387-tdep.o
+NATDEPFILES= i386gnu-nat.o gnu-nat.o fork-child.o solib.o notify_S.o process_reply_S.o msg_reply_S.o msg_U.o exc_request_U.o exc_request_S.o
+XM_FILE= xm-i386gnu.h
+NAT_FILE= nm-gnu.h
+
+# Use our own user stubs for the msg rpcs, so we can make them time out, in
+# case the program is fucked, or we guess the wrong signal thread.
+msg-MIGUFLAGS = -D'MSG_IMPORTS=waittime 1000;'
+
+# ick
+MIG = mig
+MIGCOM = $(MIG) -cc cat - /dev/null
+
+# Reply servers need special massaging of the code mig generates, to make
+# them work correctly for error returns in some cases.
+%_reply_S.h %_reply_S.c: %_reply.defs
+ $(CPP) $(CPPFLAGS) -DSERVERPREFIX=S_ -x c $< \
+ | $(MIGCOM) -sheader $*_reply_S.h -server $*_reply_S.raw -user /dev/null -header /dev/null \
+ && $(AWK) -f $(srcdir)/reply_mig_hack.awk < $*_reply_S.raw > $*_reply_S.c
+# Normal servers
+%_S.h %_S.c: %.defs
+ $(CPP) $(CPPFLAGS) -DSERVERPREFIX=S_ -x c $< \
+ | $(MIGCOM) -sheader $*_S.h -server $*_S.c -user /dev/null -header /dev/null
+# User rpc stubs
+%_U.h %_U.c: %.defs
+ $(CPP) $(CPPFLAGS) $($*-MIGUFLAGS) -x c $< \
+ | $(MIGCOM) -sheader /dev/null -server /dev/null -user $*_U.c -header $*_U.h
+
+gnu-nat.o: process_reply_S.h exc_request_S.h notify_S.h msg_reply_S.h exc_request_U.h msg_U.h
+
+gnu-nat.o i386gnu-nat.o: gnu-nat.h
+
+# Don't use the mmalloc library in Mach 3.
+MMALLOC =
+MMALLOC_DISABLE = -DNO_MMALLOC
diff --git a/contrib/gdb/gdb/config/i386/i386gnu.mt b/contrib/gdb/gdb/config/i386/i386gnu.mt
new file mode 100644
index 0000000..64fb018
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386gnu.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386/elf/GNU Hurd
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386gnu.h
diff --git a/contrib/gdb/gdb/config/i386/i386lynx.mh b/contrib/gdb/gdb/config/i386/i386lynx.mh
new file mode 100644
index 0000000..9cb086f
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386lynx.mh
@@ -0,0 +1,11 @@
+# Host: Intel 386 running LynxOS
+
+XM_FILE= xm-i386lynx.h
+XM_CLIBS= -lbsd
+XDEPFILES= ser-tcp.o
+
+NAT_FILE= nm-i386lynx.h
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o lynx-nat.o
+
+GDBSERVER_LIBS= -lbsd
+GDBSERVER_DEPFILES= low-lynx.o
diff --git a/contrib/gdb/gdb/config/i386/i386lynx.mt b/contrib/gdb/gdb/config/i386/i386lynx.mt
new file mode 100644
index 0000000..6704b43
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386lynx.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running LynxOS
+TDEPFILES= coff-solib.o i386-tdep.o i386ly-tdep.o
+TM_FILE= tm-i386lynx.h
diff --git a/contrib/gdb/gdb/config/i386/i386m3.mh b/contrib/gdb/gdb/config/i386/i386m3.mh
new file mode 100644
index 0000000..66f9847
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386m3.mh
@@ -0,0 +1,11 @@
+# Host: Intel 386 running Mach3
+
+XDEPFILES= i387-tdep.o core-aout.o
+NATDEPFILES= i386m3-nat.o m3-nat.o fork-child.o
+NAT_CLIBS= -lmachid -lnetname -lmach
+XM_FILE= xm-i386m3.h
+NAT_FILE= nm-m3.h
+
+# Don't use the mmalloc library in Mach 3.
+MMALLOC =
+MMALLOC_DISABLE = -DNO_MMALLOC
diff --git a/contrib/gdb/gdb/config/i386/i386m3.mt b/contrib/gdb/gdb/config/i386/i386m3.mt
new file mode 100644
index 0000000..e985ae3
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386m3.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 with a.out under Mach 3
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386m3.h
diff --git a/contrib/gdb/gdb/config/i386/i386mach.mh b/contrib/gdb/gdb/config/i386/i386mach.mh
new file mode 100644
index 0000000..44766c5
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386mach.mh
@@ -0,0 +1,10 @@
+# Host: Intel 386 running Mach
+
+# This is for mach2, maybe, or is obsolete (and seems to have only
+# host and native, not target). Once we get the mach3 stuff working,
+# I think it can go away.
+
+XDEPFILES=
+XM_FILE= xm-i386mach.h
+NAT_FILE= nm-i386mach.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o i386mach-nat.o
diff --git a/contrib/gdb/gdb/config/i386/i386mk.mh b/contrib/gdb/gdb/config/i386/i386mk.mh
new file mode 100644
index 0000000..cf1da57
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386mk.mh
@@ -0,0 +1,8 @@
+# Host: Intel 386 running Mach3 with OSF 1/MK
+
+XDEPFILES= os-mach3.o i386mach3-xdep.o i387-tdep.o
+XM_FILE= xm-i386osf1mk.h
+
+# Don't use the mmalloc library in Mach 3.
+MMALLOC =
+MMALLOC_DISABLE = -DNO_MMALLOC
diff --git a/contrib/gdb/gdb/config/i386/i386mk.mt b/contrib/gdb/gdb/config/i386/i386mk.mt
new file mode 100644
index 0000000..aa2f6a4
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386mk.mt
@@ -0,0 +1,6 @@
+# Target: Intel 386 with a.out in osf 1/mk
+TDEPFILES= i386-tdep.o
+TM_FILE= tm-i386osf1mk.h
+TM_CFLAGS= -I/usr/mach3/include
+TM_CLIBS= /usr/mach3/ccs/lib/libmachid.a /usr/mach3/ccs/lib/libnetname.a /usr/mach3/ccs/lib/libmach.a
+OBJFORMATS= dbxread.o
diff --git a/contrib/gdb/gdb/config/i386/i386nw.mt b/contrib/gdb/gdb/config/i386/i386nw.mt
new file mode 100644
index 0000000..3109c42
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386nw.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running NetWare
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386nw.h
diff --git a/contrib/gdb/gdb/config/i386/i386os9k.mt b/contrib/gdb/gdb/config/i386/i386os9k.mt
new file mode 100644
index 0000000..5a8794d
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386os9k.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running OS9000
+TDEPFILES= i386-tdep.o remote-os9k.o
+TM_FILE= tm-i386os9k.h
diff --git a/contrib/gdb/gdb/config/i386/i386sco.mh b/contrib/gdb/gdb/config/i386/i386sco.mh
new file mode 100644
index 0000000..69076b5
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386sco.mh
@@ -0,0 +1,13 @@
+# Host: Intel 386 running SCO Unix (pre-SVR4)
+
+XM_FILE= xm-i386sco.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386sco.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
+
+#msg The SCO C compiler cannot parse symtab.h when value.h has been included.
+#msg This is a bug in the compiler; the code is valid.
+#msg Therefore, you must use GCC to compile GDB on SCO machines.
+CC=gcc -D_POSIX_SOURCE=1
diff --git a/contrib/gdb/gdb/config/i386/i386sco4.mh b/contrib/gdb/gdb/config/i386/i386sco4.mh
new file mode 100644
index 0000000..a13f993
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386sco4.mh
@@ -0,0 +1,12 @@
+# Host: Intel 386 running SCO Unix 3.2v4
+
+XM_FILE= xm-i386sco.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386sco4.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
+
+# The cc compiler mishandles const in cases like
+# struct type ** const (c_builtin_types[]) =
+MH_CFLAGS=-Dconst=
diff --git a/contrib/gdb/gdb/config/i386/i386sco5.mh b/contrib/gdb/gdb/config/i386/i386sco5.mh
new file mode 100644
index 0000000..441a59c
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386sco5.mh
@@ -0,0 +1,17 @@
+# Host: Intel 386 running SCO OpenServer 5
+# Much like 3.2v4, except we don't have to avoid problems with const
+
+XM_FILE= xm-i386sco.h
+
+#
+# Not all configurations of SCO OpenServer 5 come with the TCP/IP
+# runtime, but all come with the development system, so we always
+# have socket(), gethostbyname(), and friends.
+#
+XDEPFILES= ser-tcp.o
+XM_CLIBS= -lPW -lsocket
+
+NAT_FILE= nm-i386sco5.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corefile.o core-aout.o corelow.o \
+ i386v-nat.o solib.o
+
diff --git a/contrib/gdb/gdb/config/i386/i386sol2.mh b/contrib/gdb/gdb/config/i386/i386sol2.mh
new file mode 100644
index 0000000..d73ded2
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386sol2.mh
@@ -0,0 +1,12 @@
+# Host: Intel 386 running Solaris 2 (SVR4)
+
+XM_FILE= xm-i386v4.h
+XDEPFILES=
+
+NAT_FILE= nm-i386v4.h
+NATDEPFILES= core-regset.o procfs.o fork-child.o i386v4-nat.o corelow.o
+
+# SVR4 comes standard with terminfo, and in some implementations, the
+# old termcap descriptions are incomplete. So ensure that we use the
+# new terminfo interface and latest terminal descriptions.
+TERMCAP=-ltermlib
diff --git a/contrib/gdb/gdb/config/i386/i386sol2.mt b/contrib/gdb/gdb/config/i386/i386sol2.mt
new file mode 100644
index 0000000..0bbf9b36
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386sol2.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SVR4
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-i386v4.h
diff --git a/contrib/gdb/gdb/config/i386/i386v.mh b/contrib/gdb/gdb/config/i386/i386v.mh
new file mode 100644
index 0000000..d67a30f
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386v.mh
@@ -0,0 +1,8 @@
+# Host: Intel 386 running System V
+
+XM_FILE= xm-i386v.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386v.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
diff --git a/contrib/gdb/gdb/config/i386/i386v.mt b/contrib/gdb/gdb/config/i386/i386v.mt
new file mode 100644
index 0000000..7242d3e
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386v.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running System V
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386v.h
diff --git a/contrib/gdb/gdb/config/i386/i386v32.mh b/contrib/gdb/gdb/config/i386/i386v32.mh
new file mode 100644
index 0000000..5b4175f
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386v32.mh
@@ -0,0 +1,9 @@
+# Host: Intel 386 running System V release 3.2
+
+XM_FILE= xm-i386v32.h
+XDEPFILES=
+XM_CLIBS= -lPW
+
+NAT_FILE= nm-i386v.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o core-aout.o i386v-nat.o
+
diff --git a/contrib/gdb/gdb/config/i386/i386v4.mh b/contrib/gdb/gdb/config/i386/i386v4.mh
new file mode 100644
index 0000000..aa70125
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386v4.mh
@@ -0,0 +1,14 @@
+# Host: Intel 386 running SVR4
+
+XM_FILE= xm-i386v4.h
+XDEPFILES=
+# for network communication
+XM_CLIBS= -lsocket -lnsl
+
+NAT_FILE= nm-i386v4.h
+NATDEPFILES= corelow.o core-regset.o solib.o procfs.o fork-child.o i386v4-nat.o
+
+# SVR4 comes standard with terminfo, and in some implementations, the
+# old termcap descriptions are incomplete. So ensure that we use the
+# new terminfo interface and latest terminal descriptions.
+TERMCAP=-ltermlib
diff --git a/contrib/gdb/gdb/config/i386/i386v4.mt b/contrib/gdb/gdb/config/i386/i386v4.mt
new file mode 100644
index 0000000..c22b675
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/i386v4.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SVR4
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-i386v4.h
diff --git a/contrib/gdb/gdb/config/i386/linux.mh b/contrib/gdb/gdb/config/i386/linux.mh
new file mode 100644
index 0000000..13c3310
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/linux.mh
@@ -0,0 +1,13 @@
+# Host: Intel 386 running Linux
+
+XM_FILE= xm-linux.h
+XDEPFILES= ser-tcp.o
+
+# Needed for frexp() in libiberty for older a.out based systems and should be
+# harmless to include for newer linux systems.
+XM_CLIBS= -lm
+
+NAT_FILE= nm-linux.h
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o core-regset.o i386v-nat.o i386v4-nat.o
+
+GDBSERVER_DEPFILES= low-linux.o
diff --git a/contrib/gdb/gdb/config/i386/linux.mt b/contrib/gdb/gdb/config/i386/linux.mt
new file mode 100644
index 0000000..b9d7404
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/linux.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 with a.out and ELF
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-linux.h
diff --git a/contrib/gdb/gdb/config/i386/nbsd.mh b/contrib/gdb/gdb/config/i386/nbsd.mh
new file mode 100644
index 0000000..5b3bd2b
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nbsd.mh
@@ -0,0 +1,5 @@
+# Host: Intel 386 running NetBSD
+XDEPFILES=
+NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o i386b-nat.o
+XM_FILE= xm-nbsd.h
+NAT_FILE= nm-nbsd.h
diff --git a/contrib/gdb/gdb/config/i386/nbsd.mt b/contrib/gdb/gdb/config/i386/nbsd.mt
new file mode 100644
index 0000000..7570850
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nbsd.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running NetBSD
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-nbsd.h
diff --git a/contrib/gdb/gdb/config/i386/ncr3000.mh b/contrib/gdb/gdb/config/i386/ncr3000.mh
new file mode 100644
index 0000000..1dbe1d1
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/ncr3000.mh
@@ -0,0 +1,21 @@
+# Host: NCR 3000 (Intel 386 running SVR4)
+
+# The NCR 3000 ships with a MetaWare compiler installed as /bin/cc.
+# This compiler not only emits obnoxious copyright messages every time
+# you run it, but it chokes and dies on a whole bunch of GNU source
+# files. Default to using the AT&T compiler installed in /usr/ccs/ATT/cc.
+# Unfortunately though, the AT&T compiler sometimes generates code that
+# the assembler barfs on if -g is used, so disable it by default as well.
+CC = /usr/ccs/ATT/cc
+CFLAGS =
+
+XM_FILE= xm-i386v4.h
+XDEPFILES=
+
+NAT_FILE= nm-i386v4.h
+NATDEPFILES= corelow.o core-regset.o procfs.o fork-child.o i386v4-nat.o
+
+# SVR4 comes standard with terminfo, and in some implementations, the
+# old termcap descriptions are incomplete. So ensure that we use the
+# new terminfo interface and latest terminal descriptions.
+TERMCAP=-ltermlib
diff --git a/contrib/gdb/gdb/config/i386/ncr3000.mt b/contrib/gdb/gdb/config/i386/ncr3000.mt
new file mode 100644
index 0000000..0bbf9b36
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/ncr3000.mt
@@ -0,0 +1,3 @@
+# Target: Intel 386 running SVR4
+TDEPFILES= i386-tdep.o i387-tdep.o solib.o
+TM_FILE= tm-i386v4.h
diff --git a/contrib/gdb/gdb/config/i386/nm-fbsd.h b/contrib/gdb/gdb/config/i386/nm-fbsd.h
new file mode 100644
index 0000000..f04f352
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-fbsd.h
@@ -0,0 +1,101 @@
+/* Native-dependent definitions for Intel 386 running BSD Unix, for GDB.
+ Copyright 1986, 1987, 1989, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_FREEBSD_H
+#define NM_FREEBSD_H
+
+/* Be shared lib aware */
+#include "solib.h"
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#include <machine/vmparam.h>
+#define KERNEL_U_ADDR USRSTACK
+
+#define FLOAT_INFO extern i386_float_info (); \
+ i386_float_info ()
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+#define PTRACE_ARG3_TYPE char*
+
+/* 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
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+#endif /* NM_FREEBSD_H */
diff --git a/contrib/gdb/gdb/config/i386/nm-gnu.h b/contrib/gdb/gdb/config/i386/nm-gnu.h
new file mode 100644
index 0000000..95f25a5
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-gnu.h
@@ -0,0 +1,22 @@
+/* Native-dependent definitions for Intel 386 running the GNU Hurd
+ Copyright 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include the generic hurd definitions. */
+
+#include "nm-gnu.h"
diff --git a/contrib/gdb/gdb/config/i386/nm-i386aix.h b/contrib/gdb/gdb/config/i386/nm-i386aix.h
new file mode 100644
index 0000000..4240393
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386aix.h
@@ -0,0 +1,42 @@
+/* Native support for i386 aix ps/2.
+ Copyright 1986, 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Changes for IBM AIX PS/2 by Minh Tran-Le (tranle@intellicorp.com)
+ * Revision: 5-May-93 00:11:35
+ */
+
+#ifndef NM_I386AIX_H
+#define NM_I386AIX_H 1
+
+/* code to execute to print interesting information about the
+ * floating point processor (if any)
+ * No need to define if there is nothing to do.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+#undef KERNEL_U_ADDR
+#define KERNEL_U_ADDR 0xf03fd000
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#endif /* NM_I386AIX_H */
diff --git a/contrib/gdb/gdb/config/i386/nm-i386bsd.h b/contrib/gdb/gdb/config/i386/nm-i386bsd.h
new file mode 100644
index 0000000..7366f2d
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386bsd.h
@@ -0,0 +1,39 @@
+/* Native-dependent definitions for Intel 386 running BSD Unix, for GDB.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_I386BSD_H
+#define NM_I386BSD_H
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#include <machine/vmparam.h>
+#define KERNEL_U_ADDR USRSTACK
+
+#undef FLOAT_INFO /* No float info yet */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+#define PTRACE_ARG3_TYPE char*
+
+#endif /* NM_I386BSD_H */
diff --git a/contrib/gdb/gdb/config/i386/nm-i386lynx.h b/contrib/gdb/gdb/config/i386/nm-i386lynx.h
new file mode 100644
index 0000000..e29821f
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386lynx.h
@@ -0,0 +1,25 @@
+/* Native-dependent definitions for Intel 386 running LynxOS.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_I386LYNX_H
+#define NM_I386LYNX_H
+
+#include "nm-lynx.h"
+
+#endif /* NM_I386LYNX_H */
diff --git a/contrib/gdb/gdb/config/i386/nm-i386mach.h b/contrib/gdb/gdb/config/i386/nm-i386mach.h
new file mode 100644
index 0000000..f01d2b1
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386mach.h
@@ -0,0 +1,26 @@
+/* Native definitions for Mach on an Intel 386
+ Copyright (C) 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+/* #define ATTACH_DETACH 1 */
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
diff --git a/contrib/gdb/gdb/config/i386/nm-i386sco.h b/contrib/gdb/gdb/config/i386/nm-i386sco.h
new file mode 100644
index 0000000..f15a8e9
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386sco.h
@@ -0,0 +1,47 @@
+/* Native support for i386.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if 0
+/* code to execute to print interesting information about the
+ floating point processor (if any)
+ No need to define if there is nothing to do.
+ On the 386, unfortunately this code is host-dependent (and lives
+ in the i386-xdep.c file), so we can't
+ do this unless we *know* we aren't cross-debugging. FIXME.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+#endif /*0*/
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+/*
+ * SysV doesn't always have a <ptrace.h> or <sys/ptrace.h> file
+ * (why, I don't know), and we don't need it.
+ */
+#define NO_PTRACE_H
+
+/* When calling functions on SCO, sometimes we get an error writing some
+ of the segment registers. This would appear to be a kernel
+ bug/non-feature. */
+#define CANNOT_STORE_REGISTER(regno) ((regno) == 14 || (regno) == 15)
diff --git a/contrib/gdb/gdb/config/i386/nm-i386sco4.h b/contrib/gdb/gdb/config/i386/nm-i386sco4.h
new file mode 100644
index 0000000..41daef5
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386sco4.h
@@ -0,0 +1,32 @@
+/* Native support for SCO 3.2v4.
+ Copyright 1993 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. By Ian Lance Taylor
+ <ian@cygnus.com> based on work by Martin Walker <maw@netcom.com>.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* SCO 3.2v4 is actually just like SCO 3.2v2, except that it
+ additionally supports attaching to a process. */
+
+#include "i386/nm-i386sco.h"
+
+#define ATTACH_DETACH
+
+/* SCO, in its wisdom, does not provide <sys/ptrace.h>. infptrace.c
+ does not have defaults for these values. */
+#define PTRACE_ATTACH 10
+#define PTRACE_DETACH 11
diff --git a/contrib/gdb/gdb/config/i386/nm-i386sco5.h b/contrib/gdb/gdb/config/i386/nm-i386sco5.h
new file mode 100644
index 0000000..dcc14e4
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386sco5.h
@@ -0,0 +1,41 @@
+/* Native support for SCO OpenServer 5
+ Copyright 1996 Free Software Foundation, Inc.
+ By Robert Lipe <robertl@dgii.com>. Based on
+ work by Ian Lance Taylor <ian@cygnus.com. and
+ Martin Walker <maw@netcom.com>.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+/* SCO OpenServer 5 is a superset of 3.2v4. It is actually quite
+ close to SVR4 [ elf, dynamic libes, mmap ] but misses a few things
+ like /proc. */
+
+#include "i386/nm-i386sco.h"
+
+/* Since the native compilers [ and linkers ] are licensed from USL,
+ we'll try convincing GDB of this... */
+
+#include "solib.h" /* Pick up shared library support */
+#define SVR4_SHARED_LIBS
+
+#define ATTACH_DETACH
+
+/* SCO, does not provide <sys/ptrace.h>. infptrace.c does not
+ have defaults for these values. */
+
+#define PTRACE_ATTACH 10
+#define PTRACE_DETACH 11
diff --git a/contrib/gdb/gdb/config/i386/nm-i386v.h b/contrib/gdb/gdb/config/i386/nm-i386v.h
new file mode 100644
index 0000000..babdd7c
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386v.h
@@ -0,0 +1,38 @@
+/* Native support for i386.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if 0
+/* code to execute to print interesting information about the
+ floating point processor (if any)
+ No need to define if there is nothing to do.
+ On the 386, unfortunately this code is host-dependent (and lives
+ in the i386-xdep.c file), so we can't
+ do this unless we *know* we aren't cross-debugging. FIXME.
+ */
+#define FLOAT_INFO { i386_float_info (); }
+#endif /*0*/
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+#define NO_PTRACE_H
diff --git a/contrib/gdb/gdb/config/i386/nm-i386v4.h b/contrib/gdb/gdb/config/i386/nm-i386v4.h
new file mode 100644
index 0000000..59d69f8
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-i386v4.h
@@ -0,0 +1,21 @@
+/* Native support for i386 running SVR4.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-sysv4.h"
diff --git a/contrib/gdb/gdb/config/i386/nm-linux.h b/contrib/gdb/gdb/config/i386/nm-linux.h
new file mode 100644
index 0000000..d6d3a5d
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-linux.h
@@ -0,0 +1,82 @@
+/* Native support for linux, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1992, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_LINUX_H
+#define NM_LINUX_H
+
+#include "i386/nm-i386v.h"
+
+/* Return sizeof user struct to callers in less machine dependent routines */
+
+#define KERNEL_U_SIZE kernel_u_size()
+extern int kernel_u_size PARAMS ((void));
+
+/* Tell gdb that we can attach and detach other processes */
+#define ATTACH_DETACH
+
+#define U_REGS_OFFSET 0
+
+/* Linux uses the SYSV i386v-nat.c support, but doesn't have <sys/reg.h> */
+
+#define NO_SYS_REG_H
+
+/* Linux supports the 386 hardware debugging registers. */
+
+#define TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(type, cnt, ot) 1
+
+/* After a watchpoint trap, the PC points to the instruction after
+ the one that caused the trap. Therefore we don't need to step over it.
+ But we do need to reset the status register to avoid another trap. */
+#define HAVE_CONTINUABLE_WATCHPOINT
+
+#define STOPPED_BY_WATCHPOINT(W) \
+ i386_stopped_by_watchpoint (inferior_pid)
+
+/* Use these macros for watchpoint insertion/removal. */
+
+#define target_insert_watchpoint(addr, len, type) \
+ i386_insert_watchpoint (inferior_pid, addr, len, 2)
+
+#define target_remove_watchpoint(addr, len, type) \
+ i386_remove_watchpoint (inferior_pid, addr, len)
+
+/* We define this if link.h is available, because with ELF we use SVR4 style
+ shared libraries. */
+
+#ifdef HAVE_LINK_H
+#include "solib.h" /* Support for shared libraries. */
+#define SVR4_SHARED_LIBS
+#endif
+
+#if 0
+/* We need prototypes for these somewhere, and this file is the logical
+ spot, but they can't go here because CORE_ADDR is not defined at the
+ time this file is included in defs.h. FIXME - fnf */
+extern CORE_ADDR
+i386_stopped_by_watchpoint PARAM ((int));
+extern int
+i386_insert_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len, int rw));
+extern int
+i386_remove_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len));
+#endif
+
+#endif /* #ifndef NM_LINUX_H */
diff --git a/contrib/gdb/gdb/config/i386/nm-m3.h b/contrib/gdb/gdb/config/i386/nm-m3.h
new file mode 100644
index 0000000..5127091
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-m3.h
@@ -0,0 +1,22 @@
+/* Native-dependent definitions for Intel 386 running Mach 3.
+ Copyright 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include the generic Mach 3 definitions. */
+
+#include "nm-m3.h"
diff --git a/contrib/gdb/gdb/config/i386/nm-nbsd.h b/contrib/gdb/gdb/config/i386/nm-nbsd.h
new file mode 100644
index 0000000..b59fec6
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-nbsd.h
@@ -0,0 +1,34 @@
+/* Native-dependent definitions for Intel 386 running NetBSD, for GDB.
+ Copyright 1986, 1987, 1989, 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_NBSD_H
+#define NM_NBSD_H
+
+/* Get generic NetBSD native definitions. */
+#include "nm-nbsd.h"
+
+/* #define FLOAT_INFO { i386_float_info(); } */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+ (addr) = i386_register_u_addr ((blockend),(regno));
+
+extern int
+i386_register_u_addr PARAMS ((int, int));
+
+#endif /* NM_NBSD_H */
diff --git a/contrib/gdb/gdb/config/i386/nm-ptx4.h b/contrib/gdb/gdb/config/i386/nm-ptx4.h
new file mode 100644
index 0000000..5e6cd56
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-ptx4.h
@@ -0,0 +1,62 @@
+/* Definitions to make GDB run on a Sequent Symmetry under ptx
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "nm-sysv4.h"
+
+#undef USE_PROC_FS
+
+#include "nm-symmetry.h"
+
+#define PTRACE_READ_REGS(pid,regaddr) mptrace (XPT_RREGS, (pid), (regaddr), 0)
+#define PTRACE_WRITE_REGS(pid,regaddr) \
+ mptrace (XPT_WREGS, (pid), (regaddr), 0)
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We must fetch all the regs before storing, since we store all at once. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+#define CHILD_WAIT
+struct target_waitstatus;
+extern int child_wait PARAMS ((int, struct target_waitstatus *));
+
+/*
+ * ptx does attach as of ptx version 2.1. Prior to that, the interface
+ * exists but does not work.
+ *
+ * FIXME: Using attach/detach requires using the ptx MPDEBUGGER
+ * interface. There are still problems with that, so for now don't
+ * enable attach/detach. If you turn it on anyway, it will mostly
+ * work, but has a number of bugs. -fubar, 2/94.
+ */
+/*#define ATTACH_DETACH 1*/
+#undef ATTACH_DETACH
+#define PTRACE_ATTACH XPT_DEBUG
+#define PTRACE_DETACH XPT_UNDEBUG
+/*
+ * The following drivel is needed because there are two ptrace-ish
+ * calls on ptx: ptrace() and mptrace(), each of which does about half
+ * of the ptrace functions.
+ */
+#define PTRACE_ATTACH_CALL(pid) ptx_do_attach(pid)
+#define PTRACE_DETACH_CALL(pid, signo) ptx_do_detach(pid, signo)
diff --git a/contrib/gdb/gdb/config/i386/nm-sun386.h b/contrib/gdb/gdb/config/i386/nm-sun386.h
new file mode 100644
index 0000000..f7a904b
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-sun386.h
@@ -0,0 +1,27 @@
+/* Native support for Sun 386i, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do implement the attach and detach commands. */
+
+#define ATTACH_DETACH
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+#define FETCH_INFERIOR_REGISTERS
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
diff --git a/contrib/gdb/gdb/config/i386/nm-symmetry.h b/contrib/gdb/gdb/config/i386/nm-symmetry.h
new file mode 100644
index 0000000..e8fb6b9
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/nm-symmetry.h
@@ -0,0 +1,47 @@
+/* Definitions to make GDB run on a Sequent Symmetry under dynix 3.0,
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* We must fetch all the regs before storing, since we store all at once. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+#ifdef _SEQUENT_
+#define CHILD_WAIT
+extern int child_wait PARAMS ((int, struct target_waitstatus *));
+#endif
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#ifdef _SEQUENT_
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/mc_vmparam.h>
+/* VA_UAREA is defined in <sys/mc_vmparam.h>, and is dependant upon
+ sizeof(struct user) */
+#define KERNEL_U_ADDR (VA_UAREA) /* ptx */
+#else
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG)) /* dynix */
+#define NO_PTRACE_H
+#endif
diff --git a/contrib/gdb/gdb/config/i386/ptx.mh b/contrib/gdb/gdb/config/i386/ptx.mh
new file mode 100644
index 0000000..e623538
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/ptx.mh
@@ -0,0 +1,7 @@
+# Host: Sequent Symmetry running ptx 1.3, with Weitek 1167 or i387
+
+XM_FILE= xm-ptx.h
+XDEPFILES= inftarg.o fork-child.o symm-nat.o corelow.o core-aout.o
+XM_CLIBS= -lPW -lseq
+
+NAT_FILE= nm-symmetry.h
diff --git a/contrib/gdb/gdb/config/i386/ptx.mt b/contrib/gdb/gdb/config/i386/ptx.mt
new file mode 100644
index 0000000..757df33
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/ptx.mt
@@ -0,0 +1,3 @@
+# Target: Sequent Symmetry running ptx 2.0, with Weitek 1167 or i387.
+TDEPFILES= symm-tdep.o i387-tdep.o i386-tdep.o
+TM_FILE= tm-ptx.h
diff --git a/contrib/gdb/gdb/config/i386/ptx4.mh b/contrib/gdb/gdb/config/i386/ptx4.mh
new file mode 100644
index 0000000..7b9d11b
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/ptx4.mh
@@ -0,0 +1,7 @@
+# Host: Sequent Symmetry running ptx 1.3, with Weitek 1167 or i387
+
+XM_FILE= xm-ptx4.h
+XDEPFILES= inftarg.o fork-child.o symm-nat.o corelow.o core-aout.o solib.o core-regset.o
+XM_CLIBS= -lseq
+
+NAT_FILE= nm-ptx4.h
diff --git a/contrib/gdb/gdb/config/i386/ptx4.mt b/contrib/gdb/gdb/config/i386/ptx4.mt
new file mode 100644
index 0000000..f347809
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/ptx4.mt
@@ -0,0 +1,3 @@
+# Target: Sequent Symmetry running ptx 4.0, with Weitek 1167 or i387.
+TDEPFILES= symm-tdep.o i387-tdep.o i386-tdep.o
+TM_FILE= tm-ptx4.h
diff --git a/contrib/gdb/gdb/config/i386/sun386.mh b/contrib/gdb/gdb/config/i386/sun386.mh
new file mode 100644
index 0000000..d249661
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/sun386.mh
@@ -0,0 +1,5 @@
+# Host: Sun 386i
+XDEPFILES=
+XM_FILE= xm-sun386.h
+NAT_FILE= nm-sun386.h
+NATDEPFILES= infptrace.o inftarg.o fork-child.o sun386-nat.o
diff --git a/contrib/gdb/gdb/config/i386/sun386.mt b/contrib/gdb/gdb/config/i386/sun386.mt
new file mode 100644
index 0000000..665ca64
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/sun386.mt
@@ -0,0 +1,3 @@
+# Target: Sun 386i target configuration file.
+TDEPFILES= i386-tdep.o solib.o
+TM_FILE= tm-sun386.h
diff --git a/contrib/gdb/gdb/config/i386/symmetry.mh b/contrib/gdb/gdb/config/i386/symmetry.mh
new file mode 100644
index 0000000..69c05bc
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/symmetry.mh
@@ -0,0 +1,5 @@
+# Host: Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+XDEPFILES=
+XM_FILE= xm-symmetry.h
+NAT_FILE= nm-symmetry.h
+NATDEPFILES= inftarg.o fork-child.o corelow.o core-aout.o symm-nat.o
diff --git a/contrib/gdb/gdb/config/i386/symmetry.mt b/contrib/gdb/gdb/config/i386/symmetry.mt
new file mode 100644
index 0000000..a3dba70
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/symmetry.mt
@@ -0,0 +1,3 @@
+# Target: Sequent Symmetry running Dynix 3.0, with Weitek 1167 or i387.
+TDEPFILES= i386-tdep.o symm-tdep.o i387-tdep.o
+TM_FILE= tm-symmetry.h
diff --git a/contrib/gdb/gdb/config/i386/tm-cygwin32.h b/contrib/gdb/gdb/config/i386/tm-cygwin32.h
new file mode 100644
index 0000000..f7464ba
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-cygwin32.h
@@ -0,0 +1,125 @@
+/* Macro definitions for i386 running under the win32 API Unix.
+ Copyright 1995, 1996 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "i386/tm-i386v.h"
+
+#undef MAX_REGISTER_RAW_SIZE
+#undef MAX_REGISTER_VIRTUAL_SIZE
+#undef NUM_REGS
+#undef REGISTER_BYTE
+#undef REGISTER_BYTES
+#undef REGISTER_CONVERTIBLE
+#undef REGISTER_CONVERT_TO_RAW
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#undef REGISTER_NAMES
+#undef REGISTER_RAW_SIZE
+#undef REGISTER_VIRTUAL_SIZE
+#undef REGISTER_VIRTUAL_TYPE
+
+/* Number of machine registers */
+
+#define NUM_REGS 24
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* the order of the first 8 registers must match the compiler's
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "ps", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ "st", "st(1)","st(2)","st(3)",\
+ "st(4)","st(5)","st(6)","st(7)",}
+
+#define FP0_REGNUM 16
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#define REGISTER_BYTES (16 * 4 + 8 * 10)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#define REGISTER_BYTE(N) (((N) < 16) ? (N) * 4 : (((N) - 16) * 10) + (16 * 4))
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#define REGISTER_RAW_SIZE(N) (((N) < 16) ? 4 : 10)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < 16) ? 4 : 10)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 10
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#define REGISTER_CONVERTIBLE(N) \
+ ((N < FP0_REGNUM) ? 0 : 1)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+extern void
+i387_to_double PARAMS ((char *, char *));
+
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ i387_to_double ((FROM), (char *)&val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+extern void
+double_to_i387 PARAMS ((char *, char *));
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ double_to_i387((char *)&val, (TO)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N < FP0_REGNUM) ? builtin_type_int : \
+ builtin_type_double)
+
+#define NAMES_HAVE_UNDERSCORE
+
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) skip_trampoline_code (pc, name)
+#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc, 0)
+extern CORE_ADDR skip_trampoline_code PARAMS ((CORE_ADDR pc, char *name));
diff --git a/contrib/gdb/gdb/config/i386/tm-i386.h b/contrib/gdb/gdb/config/i386/tm-i386.h
new file mode 100644
index 0000000..8f8090b
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386.h
@@ -0,0 +1,309 @@
+/* Macro definitions for GDB on an Intel i[345]86.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+#ifndef TM_I386_H
+#define TM_I386_H 1
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct frame_info;
+struct frame_saved_regs;
+struct type;
+#endif
+
+#define TARGET_BYTE_ORDER LITTLE_ENDIAN
+
+/* Used for example in valprint.c:print_floating() to enable checking
+ for NaN's */
+
+#define IEEE_FLOAT
+
+/* Number of traps that happen between exec'ing the shell to run an
+ inferior, and when we finally get to the inferior code. This is 2
+ on most implementations. */
+
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Offset from address of function to start of its code.
+ Zero on most machines. */
+
+#define FUNCTION_START_OFFSET 0
+
+/* Advance PC across any function entry prologue instructions to reach some
+ "real" code. */
+
+#define SKIP_PROLOGUE(frompc) {(frompc) = i386_skip_prologue((frompc));}
+
+extern int i386_skip_prologue PARAMS ((int));
+
+/* Immediately after a function call, return the saved pc. Can't always go
+ through the frames for this because on some machines the new frame is not
+ set up until the new function executes some instructions. */
+
+#define SAVED_PC_AFTER_CALL(frame) (read_memory_integer (read_register (SP_REGNUM), 4))
+
+/* Stack grows downward. */
+
+#define INNER_THAN <
+
+/* Sequence of bytes for breakpoint instruction. */
+
+#define BREAKPOINT {0xcc}
+
+/* Amount PC must be decremented by after a breakpoint. This is often the
+ number of bytes in BREAKPOINT but not always. */
+
+#define DECR_PC_AFTER_BREAK 1
+
+/* Nonzero if instruction at PC is a return instruction. */
+
+#define ABOUT_TO_RETURN(pc) (read_memory_integer ((pc), 1) == 0xc3)
+
+/* 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_SIZE 4
+
+/* Number of machine registers */
+
+#define NUM_FREGS 0 /*8*/ /* Number of FP regs */
+#define NUM_REGS (16 + NUM_FREGS) /* Basic i*86 regs + FP regs */
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ The order of the first 8 registers must match the compiler's numbering
+ scheme (which is the same as the 386 scheme) and also regmap in the various
+ *-nat.c files. */
+
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "eflags", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ "st0", "st1", "st2", "st3", \
+ "st4", "st5", "st6", "st7", \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define FP_REGNUM 5 /* (ebp) Contains address of executing stack frame */
+#define SP_REGNUM 4 /* (usp) Contains address of top of stack */
+#define PC_REGNUM 8 /* (eip) Contains program counter */
+#define PS_REGNUM 9 /* (ps) Contains processor status */
+
+#define FP0_REGNUM 16 /* (st0) 387 register */
+#define FPC_REGNUM 25 /* 80387 control register */
+
+/* Total amount of space needed to store our copies of the machine's register
+ state, the array `registers'. */
+
+#define REGISTER_BYTES ((NUM_REGS - NUM_FREGS)*4 + NUM_FREGS*10)
+
+/* Index within `registers' of the first byte of the space for register N. */
+
+#define REGISTER_BYTE(N) \
+ (((N) < FP0_REGNUM) ? ((N) * 4) : ((((N) - FP0_REGNUM) * 10) + 64))
+
+/* Number of bytes of storage in the actual machine representation for
+ register N. All registers are 4 bytes, except 387 st(0) - st(7),
+ which are 80 bits each. */
+
+#define REGISTER_RAW_SIZE(N) (((N) < FP0_REGNUM) ? 4 : 10)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < FP0_REGNUM) ? 4 : 8)
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 8
+
+/* 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 used for things other than address. */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM) \
+ ? lookup_pointer_type (builtin_type_void) \
+ : (((N) < FP0_REGNUM) \
+ ? builtin_type_int \
+ : builtin_type_double))
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { (SP) -= sizeof (ADDR); \
+ write_memory ((SP), (char *) &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ i386_extract_return_value ((TYPE),(REGBUF),(VALBUF))
+
+extern void i386_extract_return_value PARAMS ((struct type *, char [], char *));
+
+/* Write into appropriate registers a function return value of type TYPE, given
+ in virtual format. */
+
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ { \
+ if (TYPE_CODE (TYPE) == TYPE_CODE_FLT) \
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), (VALBUF), \
+ TYPE_LENGTH (TYPE)); \
+ else \
+ write_register_bytes (0, (VALBUF), TYPE_LENGTH (TYPE)); \
+ }
+
+/* Extract from an array REGBUF containing the (raw) register state the address
+ in which a function should return its structure value, as a CORE_ADDR (or an
+ expression that can be used as one). */
+
+#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)(REGBUF))
+
+/* The following redefines make backtracing through sigtramp work.
+ They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
+ from the sigcontext structure which is pushed by the kernel on the
+ user stack, along with a pointer to it. */
+
+/* FRAME_CHAIN takes a frame's nominal address and produces the frame's
+ chain-pointer.
+ In the case of the i386, the frame's nominal address
+ is the address of a 4-byte word containing the calling frame's address. */
+
+#define FRAME_CHAIN(thisframe) \
+ ((thisframe)->signal_handler_caller \
+ ? (thisframe)->frame \
+ : (!inside_entry_file ((thisframe)->pc) \
+ ? read_memory_integer ((thisframe)->frame, 4) \
+ : 0))
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ do { \
+ if ((FI)->signal_handler_caller) \
+ (FRAMELESS) = 0; \
+ else \
+ (FRAMELESS) = frameless_look_for_prologue(FI); \
+ } while (0)
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+#define FRAME_SAVED_PC(FRAME) \
+ (((FRAME)->signal_handler_caller \
+ ? sigtramp_saved_pc (FRAME) \
+ : read_memory_integer ((FRAME)->frame + 4, 4)) \
+ )
+
+extern CORE_ADDR sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+#define FRAME_ARGS_ADDRESS(fi) ((fi)->frame)
+
+#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
+
+/* Return number of args passed to a frame. Can return -1, meaning no way
+ to tell, which is typical now that the C compiler delays popping them. */
+
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = i386_frame_num_args(fi)
+
+extern int i386_frame_num_args PARAMS ((struct frame_info *));
+
+/* Return number of bytes at start of arglist that are not really args. */
+
+#define FRAME_ARGS_SKIP 8
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame. */
+
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ i386_frame_find_saved_regs ((frame_info), &(frame_saved_regs)); }
+
+extern void i386_frame_find_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+
+
+/* Things needed for making the inferior call functions. */
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+#define PUSH_DUMMY_FRAME { i386_push_dummy_frame (); }
+
+extern void i386_push_dummy_frame PARAMS ((void));
+
+/* Discard from the stack the innermost frame, restoring all registers. */
+
+#define POP_FRAME { i386_pop_frame (); }
+
+extern void i386_pop_frame PARAMS ((void));
+
+
+/* this is
+ * call 11223344 (32 bit relative)
+ * int3
+ */
+
+#define CALL_DUMMY { 0x223344e8, 0xcc11 }
+
+#define CALL_DUMMY_LENGTH 8
+
+#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. */
+
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ int from, to, delta, loc; \
+ loc = (int)(read_register (SP_REGNUM) - CALL_DUMMY_LENGTH); \
+ from = loc + 5; \
+ to = (int)(fun); \
+ delta = to - from; \
+ *((char *)(dummyname) + 1) = (delta & 0xff); \
+ *((char *)(dummyname) + 2) = ((delta >> 8) & 0xff); \
+ *((char *)(dummyname) + 3) = ((delta >> 16) & 0xff); \
+ *((char *)(dummyname) + 4) = ((delta >> 24) & 0xff); \
+}
+
+extern void print_387_control_word PARAMS ((unsigned int));
+extern void print_387_status_word PARAMS ((unsigned int));
+
+/* Offset from SP to first arg on stack at first instruction of a function */
+
+#define SP_ARG0 (1 * 4)
+
+#endif /* ifndef TM_I386_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-i386aix.h b/contrib/gdb/gdb/config/i386/tm-i386aix.h
new file mode 100644
index 0000000..b0121fa
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386aix.h
@@ -0,0 +1,67 @@
+/* Macro defintions for IBM AIX PS/2 (i386).
+ Copyright 1986, 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Changes for IBM AIX PS/2 by Minh Tran-Le (tranle@intellicorp.com). */
+
+#ifndef TM_I386AIX_H
+#define TM_I386AIX_H 1
+
+#include "i386/tm-i386.h"
+#include <sys/reg.h>
+
+#ifndef I386
+# define I386 1
+#endif
+#ifndef I386_AIX_TARGET
+# define I386_AIX_TARGET 1
+#endif
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) \
+ ((N < FP0_REGNUM) ? 0 : 1)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ i387_to_double ((FROM), (char *)&val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+extern void
+i387_to_double PARAMS ((char *, char *));
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ double_to_i387((char *)&val, (TO)); \
+}
+extern void
+double_to_i387 PARAMS ((char *, char *));
+
+#endif /* TM_I386AIX_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-i386bsd.h b/contrib/gdb/gdb/config/i386/tm-i386bsd.h
new file mode 100644
index 0000000..0b0e3d9
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386bsd.h
@@ -0,0 +1,43 @@
+/* Macro definitions for i386 running under BSD Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386BSD_H
+#define TM_I386BSD_H 1
+
+#include "i386/tm-i386.h"
+
+/* 386BSD cannot handle the segment registers. */
+/* BSDI can't handle them either. */
+
+#undef NUM_REGS
+#define NUM_REGS 10
+
+/* On 386 bsd, sigtramp is above the user stack and immediately below
+ the user area. Using constants here allows for cross debugging.
+ These are tested for BSDI but should work on 386BSD. */
+
+#define SIGTRAMP_START 0xfdbfdfc0
+#define SIGTRAMP_END 0xfdbfe000
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+/* Offset to saved PC in sigcontext, from <sys/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 20
+
+#endif /* ifndef TM_I386BSD_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-i386gnu.h b/contrib/gdb/gdb/config/i386/tm-i386gnu.h
new file mode 100644
index 0000000..a6e3c08
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386gnu.h
@@ -0,0 +1,48 @@
+/* Macro definitions for i386, GNU Hurd
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include common definitions for gnu systems */
+#include "nm-gnu.h"
+
+/* Thread flavors used in re-setting the T bit.
+ * @@ this is also bad for cross debugging.
+ */
+#define THREAD_STATE_FLAVOR i386_THREAD_STATE
+#define THREAD_STATE_SIZE i386_THREAD_STATE_COUNT
+#define THREAD_STATE_SET_TRACED(state) \
+ ((struct i386_thread_state *)state)->efl |= 0x100
+#define THREAD_STATE_CLEAR_TRACED(state) \
+ ((((struct i386_thread_state *)state)->efl &= ~0x100), 1)
+
+/* we can do it */
+#define ATTACH_DETACH 1
+
+/* Sigh. There should be a file for i386 but no sysv stuff in it */
+#include "i386/tm-i386v.h"
+
+/* I want to test this float info code. See comment in tm-i386v.h */
+#undef FLOAT_INFO
+#define FLOAT_INFO { i386_mach3_float_info (); }
+
+/* Address of end of stack space.
+ * for MACH, see <machine/vmparam.h>
+ * @@@ I don't know what is in the 5 ints...
+ */
+#undef STACK_END_ADDR
+#define STACK_END_ADDR (0xc0000000-sizeof(int [5]))
diff --git a/contrib/gdb/gdb/config/i386/tm-i386lynx.h b/contrib/gdb/gdb/config/i386/tm-i386lynx.h
new file mode 100644
index 0000000..9e732b3
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386lynx.h
@@ -0,0 +1,33 @@
+/* Macro definitions for Intel 386 running under LynxOS.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386LYNX_H
+#define TM_I386LYNX_H
+
+#include "tm-lynx.h"
+
+/* Most definitions from sysv could be used. */
+#include "i386/tm-i386.h"
+
+#undef SAVED_PC_AFTER_CALL
+
+#define SAVED_PC_AFTER_CALL i386lynx_saved_pc_after_call
+CORE_ADDR i386lynx_saved_pc_after_call ();
+
+#endif /* TM_I386LYNX_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-i386m3.h b/contrib/gdb/gdb/config/i386/tm-i386m3.h
new file mode 100644
index 0000000..2f97505
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386m3.h
@@ -0,0 +1,60 @@
+/* Macro definitions for i386, Mach 3.0
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Include common definitions for Mach3 systems */
+#include "nm-m3.h"
+
+/* Define offsets to access CPROC stack when it does not have
+ * a kernel thread.
+ */
+#define MACHINE_CPROC_SP_OFFSET 20
+#define MACHINE_CPROC_PC_OFFSET 16
+#define MACHINE_CPROC_FP_OFFSET 12
+
+/* Thread flavors used in re-setting the T bit.
+ * @@ this is also bad for cross debugging.
+ */
+#define TRACE_FLAVOR i386_THREAD_STATE
+#define TRACE_FLAVOR_SIZE i386_THREAD_STATE_COUNT
+#define TRACE_SET(x,state) \
+ ((struct i386_thread_state *)state)->efl |= 0x100
+#define TRACE_CLEAR(x,state) \
+ ((((struct i386_thread_state *)state)->efl &= ~0x100), 1)
+
+/* we can do it */
+#define ATTACH_DETACH 1
+
+/* Define this if the C compiler puts an underscore at the front
+ of external names before giving them to the linker. */
+
+#define NAMES_HAVE_UNDERSCORE
+
+/* Sigh. There should be a file for i386 but no sysv stuff in it */
+#include "i386/tm-i386.h"
+
+/* I want to test this float info code. See comment in tm-i386v.h */
+#undef FLOAT_INFO
+#define FLOAT_INFO { i386_mach3_float_info (); }
+
+/* Address of end of stack space.
+ * for MACH, see <machine/vmparam.h>
+ * @@@ I don't know what is in the 5 ints...
+ */
+#undef STACK_END_ADDR
+#define STACK_END_ADDR (0xc0000000-sizeof(int [5]))
diff --git a/contrib/gdb/gdb/config/i386/tm-i386mk.h b/contrib/gdb/gdb/config/i386/tm-i386mk.h
new file mode 100644
index 0000000..3625efb
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386mk.h
@@ -0,0 +1,25 @@
+/* Macro definitions for i386, Mach 3.0, OSF 1/MK
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Until OSF switches to a newer Mach kernel that has
+ * a different get_emul_vector() interface.
+ */
+#define MK67 1
+
+#include "i386/tm-i386m3.h"
diff --git a/contrib/gdb/gdb/config/i386/tm-i386nw.h b/contrib/gdb/gdb/config/i386/tm-i386nw.h
new file mode 100644
index 0000000..43a1e1a
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386nw.h
@@ -0,0 +1,49 @@
+/* Macro definitions for i386 running NetWare.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386NW_H
+#define TM_I386NW_H 1
+
+#include "i386/tm-i386.h"
+
+/* Stop backtracing when we wander into main. */
+
+#define FRAME_CHAIN_VALID_ALTERNATE
+
+
+/* Offsets (in target ints) into jmp_buf. Not defined in any system header
+ file, so we have to step through setjmp/longjmp with a debugger and figure
+ them out. */
+
+#define JB_ELEMENT_SIZE 4 /* jmp_buf[] is array of ints */
+
+#define JB_PC 6 /* Setjmp()'s return PC saved here */
+
+/* Figure out where the longjmp will land. Slurp the args out of the stack.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+#endif /* ifndef TM_I386NW_H */
+
diff --git a/contrib/gdb/gdb/config/i386/tm-i386os9k.h b/contrib/gdb/gdb/config/i386/tm-i386os9k.h
new file mode 100644
index 0000000..75de74e
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386os9k.h
@@ -0,0 +1,63 @@
+/* Macro definitions for i386 running under BSD Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386OS9K_H
+#define TM_I386OS9K_H 1
+
+#include "i386/tm-i386.h"
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS (16) /* Basic i*86 regs */
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ The order of the first 8 registers must match the compiler's numbering
+ scheme (which is the same as the 386 scheme) and also regmap in the various
+ *-nat.c files. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "eflags", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ }
+
+#define DATABASE_REG 3 /* ebx */
+
+/* Amount PC must be decremented by after a breakpoint. This is often the
+ number of bytes in BREAKPOINT but not always (such as now). */
+
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+/* On 386 bsd, sigtramp is above the user stack and immediately below
+ the user area. Using constants here allows for cross debugging.
+ These are tested for BSDI but should work on 386BSD. */
+#define SIGTRAMP_START 0xfdbfdfc0
+#define SIGTRAMP_END 0xfdbfe000
+
+/* Saved Pc. Get it from sigcontext if within sigtramp. */
+
+/* Offset to saved PC in sigcontext, from <sys/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 20
+
+#define BELIEVE_PCC_PROMOTION 1
+
+#endif /* #ifndef TM_I386OS9K_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-i386v.h b/contrib/gdb/gdb/config/i386/tm-i386v.h
new file mode 100644
index 0000000..235558b
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386v.h
@@ -0,0 +1,161 @@
+/* Macro definitions for i386, Unix System V.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386V_H
+#define TM_I386V_H 1
+
+/* First pick up the generic *86 target file. */
+
+#include "i386/tm-i386.h"
+
+/* Number of traps that happen between exec'ing the shell to run an
+ inferior, and when we finally get to the inferior code. This is
+ 2 on most implementations. Override here to 4. */
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 4
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS 16
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* the order of the first 8 registers must match the compiler's
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "ps", "cs", "ss", \
+ "ds", "es", "fs", "gs", \
+ }
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (NUM_REGS * 4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) ((N)*4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) (4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#undef REGISTER_VIRTUAL_SIZE
+#define REGISTER_VIRTUAL_SIZE(N) (4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#undef MAX_REGISTER_RAW_SIZE
+#define MAX_REGISTER_RAW_SIZE 4
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have. */
+
+#undef MAX_REGISTER_VIRTUAL_SIZE
+#define MAX_REGISTER_VIRTUAL_SIZE 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
+ used for things other than address. */
+
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+ ((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM ? \
+ lookup_pointer_type (builtin_type_void) : builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+#undef STORE_STRUCT_RETURN
+#define STORE_STRUCT_RETURN(ADDR, SP) \
+ { (SP) -= sizeof (ADDR); \
+ write_memory ((SP), (char *) &(ADDR), sizeof (ADDR)); }
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy ((VALBUF), (REGBUF), TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#undef STORE_RETURN_VALUE
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (0, VALBUF, TYPE_LENGTH (TYPE))
+
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer. */
+
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#undef FRAMELESS_FUNCTION_INVOCATION
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+ (FRAMELESS) = frameless_look_for_prologue(FI)
+
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+#undef FRAME_NUM_ARGS
+#define FRAME_NUM_ARGS(numargs, fi) (numargs) = -1
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct frame_info;
+struct frame_saved_regs;
+#endif
+
+extern int
+i386_frame_num_args PARAMS ((struct frame_info *));
+
+#endif /* ifndef TM_I386V_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-i386v4.h b/contrib/gdb/gdb/config/i386/tm-i386v4.h
new file mode 100644
index 0000000..0a1e56d
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-i386v4.h
@@ -0,0 +1,78 @@
+/* Macro definitions for GDB on an Intel i386 running SVR4.
+ Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygnus.com)
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_I386V4_H
+#define TM_I386V4_H 1
+
+/* Pick up most of what we need from the generic i386 target include file. */
+
+#include "i386/tm-i386.h"
+
+/* Pick up more stuff from the generic SVR4 host include file. */
+
+#include "tm-sysv4.h"
+
+/* Use the alternate method of determining valid frame chains. */
+
+#define FRAME_CHAIN_VALID_ALTERNATE
+
+/* Offsets (in target ints) into jmp_buf. Not defined in any system header
+ file, so we have to step through setjmp/longjmp with a debugger and figure
+ them out. Note that <setjmp> defines _JBLEN as 10, which is the default
+ if no specific machine is selected, even though we only use 6 slots. */
+
+#define JB_ELEMENT_SIZE sizeof(int) /* jmp_buf[_JBLEN] is array of ints */
+
+#define JB_EBX 0
+#define JB_ESI 1
+#define JB_EDI 2
+#define JB_EBP 3
+#define JB_ESP 4
+#define JB_EDX 5
+
+#define JB_PC JB_EDX /* Setjmp()'s return PC saved in EDX */
+
+/* Figure out where the longjmp will land. Slurp the args out of the stack.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+/* The following redefines make backtracing through sigtramp work.
+ They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
+ from the ucontext structure which is pushed by the kernel on the
+ user stack. Unfortunately there are three variants of sigtramp handlers. */
+
+#define I386V4_SIGTRAMP_SAVED_PC
+#define IN_SIGTRAMP(pc, name) ((name) \
+ && (STREQ ("_sigreturn", name) \
+ || STREQ ("_sigacthandler", name) \
+ || STREQ ("sigvechandler", name)))
+
+/* Saved Pc. Get it from ucontext if within sigtramp. */
+
+#define sigtramp_saved_pc i386v4_sigtramp_saved_pc
+extern CORE_ADDR i386v4_sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+#endif /* ifndef TM_I386V4_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-linux.h b/contrib/gdb/gdb/config/i386/tm-linux.h
new file mode 100644
index 0000000..d8cbf26
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-linux.h
@@ -0,0 +1,35 @@
+/* Definitions to target GDB to Linux on 386.
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_LINUX_H
+#define TM_LINUX_H
+
+/* FIXME: If nothing else gets added to this file, it could be removed
+ and configure could just use tm-i386.h instead. -fnf */
+
+#include "i386/tm-i386.h"
+
+/* Offset to saved PC in sigcontext, from <linux/signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 38
+
+/* We need this file for the SOLIB_TRAMPOLINE stuff. */
+
+#include "tm-sysv4.h"
+
+#endif /* #ifndef TM_LINUX_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-nbsd.h b/contrib/gdb/gdb/config/i386/tm-nbsd.h
new file mode 100644
index 0000000..cf5159f
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-nbsd.h
@@ -0,0 +1,42 @@
+/* Macro definitions for i386 running under NetBSD.
+ Copyright 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_NBSD_H
+#define TM_NBSD_H
+
+#include "i386/tm-i386bsd.h"
+#include "tm-nbsd.h"
+
+#undef NUM_REGS
+#define NUM_REGS 16
+
+#define JB_ELEMENT_SIZE sizeof(int) /* jmp_buf[_JBLEN] is array of ints */
+#define JB_PC 0 /* Setjmp()'s return PC saved here */
+
+/* Figure out where the longjmp will land. Slurp the args out of the stack.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into ADDR.
+ This routine returns true on success */
+
+extern int
+get_longjmp_target PARAMS ((CORE_ADDR *));
+
+#define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
+
+#endif /* TM_NBSD_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-ptx.h b/contrib/gdb/gdb/config/i386/tm-ptx.h
new file mode 100644
index 0000000..c9f67d7
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-ptx.h
@@ -0,0 +1,232 @@
+/* Target machine definitions for GDB on a Sequent Symmetry under ptx
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Symmetry version by Jay Vosburgh (fubar@sequent.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_PTX_H
+#define TM_PTX_H 1
+
+/* I don't know if this will work for cross-debugging, even if you do get
+ a copy of the right include file. */
+
+#include <sys/reg.h>
+
+#ifdef SEQUENT_PTX4
+#include "i386/tm-i386v4.h"
+#else /* !SEQUENT_PTX4 */
+#include "i386/tm-i386v.h"
+#endif
+
+/* Number of traps that happen between exec'ing the shell to run an
+ inferior, and when we finally get to the inferior code. This is 2
+ on most implementations. Here we have to undo what tm-i386v.h gave
+ us and restore the default. */
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Amount PC must be decremented by after a breakpoint. This is often the
+ number of bytes in BREAKPOINT but not always (such as now). */
+
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+#if 0
+ --- this code can't be used unless we know we are running native,
+ since it uses host specific ptrace calls.
+/* code for 80387 fpu. Functions are from i386-dep.c, copied into
+ * symm-dep.c.
+ */
+#define FLOAT_INFO { i386_float_info(); }
+#endif
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS 49
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ The order of the first 8 registers must match the compiler's numbering
+ scheme (which is the same as the 386 scheme) and also regmap in the various
+ *-nat.c files. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \
+ "esp", "ebp", "esi", "edi", \
+ "eip", "eflags", "st0", "st1", \
+ "st2", "st3", "st4", "st5", \
+ "st6", "st7", "fp1", "fp2", \
+ "fp3", "fp4", "fp5", "fp6", \
+ "fp7", "fp8", "fp9", "fp10", \
+ "fp11", "fp12", "fp13", "fp14", \
+ "fp15", "fp16", "fp17", "fp18", \
+ "fp19", "fp20", "fp21", "fp22", \
+ "fp23", "fp24", "fp25", "fp26", \
+ "fp27", "fp28", "fp29", "fp30", \
+ "fp31" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define EAX_REGNUM 0
+#define ECX_REGNUM 1
+#define EDX_REGNUM 2
+#define EBX_REGNUM 3
+
+#define ESP_REGNUM 4
+#define EBP_REGNUM 5
+
+#define ESI_REGNUM 6
+#define EDI_REGNUM 7
+
+#define EIP_REGNUM 8
+#define EFLAGS_REGNUM 9
+
+#define ST0_REGNUM 10
+#define ST1_REGNUM 11
+#define ST2_REGNUM 12
+#define ST3_REGNUM 13
+
+#define ST4_REGNUM 14
+#define ST5_REGNUM 15
+#define ST6_REGNUM 16
+#define ST7_REGNUM 17
+
+#define FP1_REGNUM 18 /* first 1167 register */
+/* Get %fp2 - %fp31 by addition, since they are contiguous */
+
+#undef SP_REGNUM
+#define SP_REGNUM ESP_REGNUM /* Contains address of top of stack */
+#undef FP_REGNUM
+#define FP_REGNUM EBP_REGNUM /* Contains address of executing stack frame */
+#undef PC_REGNUM
+#define PC_REGNUM EIP_REGNUM /* Contains program counter */
+#undef PS_REGNUM
+#define PS_REGNUM EFLAGS_REGNUM /* Contains processor status */
+
+/*
+ * For ptx, this is a little bit bizarre, since the register block
+ * is below the u area in memory. This means that blockend here ends
+ * up being negative (for the call from coredep.c) since the value in
+ * u.u_ar0 will be less than KERNEL_U_ADDR (and coredep.c passes us
+ * u.u_ar0 - KERNEL_U_ADDR in blockend). Since we also define
+ * FETCH_INFERIOR_REGISTERS (and supply our own functions for that),
+ * the core file case will be the only use of this function.
+ */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ (addr) = ptx_register_u_addr((blockend), (regno)); }
+
+extern int
+ptx_register_u_addr PARAMS ((int, int));
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. 10 i*86 registers, 8 i387
+ registers, and 31 Weitek 1167 registers */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES ((10 * 4) + (8 * 10) + (31 * 4))
+
+/* Index within `registers' of the first byte of the space for register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+(((N) < ST0_REGNUM) ? ((N) * 4) : \
+ ((N) < FP1_REGNUM) ? (40 + (((N) - ST0_REGNUM) * 10)) : \
+ (40 + 80 + (((N) - FP1_REGNUM) * 4)))
+
+/* Number of bytes of storage in the actual machine representation for
+ register N. All registers are 4 bytes, except 387 st(0) - st(7),
+ which are 80 bits each. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) \
+(((N) < ST0_REGNUM) ? 4 : \
+ ((N) < FP1_REGNUM) ? 10 : \
+ 4)
+
+/* Largest value REGISTER_RAW_SIZE can have. */
+
+#undef MAX_REGISTER_RAW_SIZE
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) \
+((N < ST0_REGNUM) ? 0 : \
+ (N < FP1_REGNUM) ? 1 : \
+ 0)
+
+/* Convert data from raw format for register REGNUM
+ to virtual format for register REGNUM. */
+extern const struct floatformat floatformat_i387_ext; /* from floatformat.h */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+((REGNUM < ST0_REGNUM) ? (void)memcpy ((TO), (FROM), 4) : \
+ (REGNUM < FP1_REGNUM) ? (void)floatformat_to_double(&floatformat_i387_ext, \
+ (FROM),(TO)) : \
+ (void)memcpy ((TO), (FROM), 4))
+
+/* Convert data from virtual format for register REGNUM
+ to raw format for register REGNUM. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+((REGNUM < ST0_REGNUM) ? (void)memcpy ((TO), (FROM), 4) : \
+ (REGNUM < FP1_REGNUM) ? (void)floatformat_from_double(&floatformat_i387_ext, \
+ (FROM),(TO)) : \
+ (void)memcpy ((TO), (FROM), 4))
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+/*
+ * Note: the 1167 registers (the last line, builtin_type_float) are
+ * generally used in pairs, with each pair being treated as a double.
+ * It it also possible to use them singly as floats. I'm not sure how
+ * in gdb to treat the register pair pseudo-doubles. -fubar
+ */
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+((N < ST0_REGNUM) ? builtin_type_int : \
+ (N < FP1_REGNUM) ? builtin_type_double : \
+ builtin_type_float)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ symmetry_extract_return_value(TYPE, REGBUF, VALBUF)
+
+/*
+#undef FRAME_FIND_SAVED_REGS
+#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
+{ ptx_frame_find_saved_regs((frame_info), &(frame_saved_regs)); }
+*/
+
+#endif /* ifndef TM_PTX_H */
diff --git a/contrib/gdb/gdb/config/i386/tm-ptx4.h b/contrib/gdb/gdb/config/i386/tm-ptx4.h
new file mode 100644
index 0000000..a576acc
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-ptx4.h
@@ -0,0 +1,24 @@
+/* Target machine definitions for GDB on a Sequent Symmetry under ptx
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Symmetry version by Jay Vosburgh (fubar@sequent.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define SEQUENT_PTX4
+
+#include "tm-ptx.h"
diff --git a/contrib/gdb/gdb/config/i386/tm-sun386.h b/contrib/gdb/gdb/config/i386/tm-sun386.h
new file mode 100644
index 0000000..259fd51
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-sun386.h
@@ -0,0 +1,205 @@
+/* Parameters for a Sun 386i target machine, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (TM_SUN386_H)
+#define TM_SUN386_H 1
+
+#include "i386/tm-i386.h"
+
+#ifndef sun386
+#define sun386
+#endif
+#define GDB_TARGET_IS_SUN386 1
+#define SUNOS4
+#define USE_MACHINE_REG_H
+
+/* Perhaps some day this will work even without the following #define */
+#define COFF_ENCAPSULATE
+
+#ifdef COFF_ENCAPSULATE
+/* Avoid conflicts between our include files and <sys/exec.h>
+ (maybe not needed anymore). */
+#define _EXEC_
+#endif
+
+/* sun386 ptrace seems unable to change the frame pointer */
+#define PTRACE_FP_BUG
+
+/* Address of end of stack space. */
+
+#define STACK_END_ADDR 0xfc000000
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS 35
+
+/* Initializer for an array of names of registers. There should be NUM_REGS
+ strings in this initializer. The order of the first 8 registers must match
+ the compiler's numbering scheme (which is the same as the 386 scheme) also,
+ this table must match regmap in i386-pinsn.c. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "gs", "fs", "es", "ds", \
+ "edi", "esi", "ebp", "esp", \
+ "ebx", "edx", "ecx", "eax", \
+ "retaddr", "trapnum", "errcode", "ip", \
+ "cs", "ps", "sp", "ss", \
+ "fst0", "fst1", "fst2", "fst3", \
+ "fst4", "fst5", "fst6", "fst7", \
+ "fctrl", "fstat", "ftag", "fip", \
+ "fcs", "fopoff", "fopsel" \
+ }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#undef FP_REGNUM
+#define FP_REGNUM 6 /* (ebp) Contains address of executing stack frame */
+#undef SP_REGNUM
+#define SP_REGNUM 18 /* (usp) Contains address of top of stack */
+#undef PS_REGNUM
+#define PS_REGNUM 17 /* (ps) Contains processor status */
+#undef PC_REGNUM
+#define PC_REGNUM 15 /* (eip) Contains program counter */
+#undef FP0_REGNUM
+#define FP0_REGNUM 20 /* Floating point register 0 */
+#undef FPC_REGNUM
+#define FPC_REGNUM 28 /* 80387 control register */
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES (20*4+8*10+7*4)
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+ ((N) >= FPC_REGNUM ? (((N) - FPC_REGNUM) * 4) + 160 \
+ : (N) >= FP0_REGNUM ? (((N) - FP0_REGNUM) * 10) + 80 \
+ : (N) * 4)
+
+/* Number of bytes of storage in the actual machine representation
+ for register N. */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 10 : 4)
+
+/* Number of bytes of storage in the program's representation
+ for register N. */
+
+#undef REGISTER_VIRTUAL_SIZE
+#define REGISTER_VIRTUAL_SIZE(N) (((unsigned)((N) - FP0_REGNUM)) < 8 ? 8 : 4)
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) (((unsigned)((N) - FP0_REGNUM)) < 8)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ i387_to_double ((FROM), (char *)&val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+extern void
+i387_to_double PARAMS ((char *, char *));
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ double_to_i387((char *)&val, (TO)); \
+}
+extern void
+double_to_i387 PARAMS ((char *, char *));
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+ (((unsigned)((N) - FP0_REGNUM)) < 8 ? builtin_type_double : builtin_type_int)
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ memcpy (VALBUF, REGBUF + REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), TYPE_LENGTH (TYPE))
+
+/* Write into appropriate registers a function return value
+ of type TYPE, given in virtual format. */
+
+#undef STORE_RETURN_VALUE
+#define STORE_RETURN_VALUE(TYPE,VALBUF) \
+ write_register_bytes (REGISTER_BYTE (TYPE_CODE (TYPE) == TYPE_CODE_FLT ? FP0_REGNUM : 11), VALBUF, TYPE_LENGTH (TYPE))
+
+/* Describe the pointer in each stack frame to the previous stack frame
+ (its caller). */
+
+/* FRAME_CHAIN takes a frame's nominal address
+ and produces the frame's chain-pointer. */
+
+#undef FRAME_CHAIN
+#define FRAME_CHAIN(thisframe) \
+ (!inside_entry_file ((thisframe)->pc) ? \
+ read_memory_integer ((thisframe)->frame, 4) :\
+ 0)
+
+/* Define other aspects of the stack frame. */
+
+/* A macro that tells us whether the function invocation represented
+ by FI does not have a frame on the stack associated with it. If it
+ does not, FRAMELESS is set to 1, else 0. */
+
+#undef FRAMELESS_FUNCTION_INVOCATION
+#define FRAMELESS_FUNCTION_INVOCATION(FI, FRAMELESS) \
+{ (FRAMELESS) = frameless_look_for_prologue (FI); }
+
+#undef FRAME_SAVED_PC
+#define FRAME_SAVED_PC(FRAME) (read_memory_integer ((FRAME)->frame + 4, 4))
+
+/* Insert the specified number of args and function address
+ into a call sequence of the above form stored at DUMMYNAME. */
+
+#undef FIX_CALL_DUMMY
+#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
+{ \
+ *(int *)((char *)(dummyname) + 1) = (int)(fun) - (pc) - 5; \
+}
+
+#endif /* !defined (TM_SUN386_H) */
+
diff --git a/contrib/gdb/gdb/config/i386/tm-symmetry.h b/contrib/gdb/gdb/config/i386/tm-symmetry.h
new file mode 100644
index 0000000..11931d4
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/tm-symmetry.h
@@ -0,0 +1,321 @@
+/* Target machine definitions for GDB on a Sequent Symmetry under dynix 3.0,
+ with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+ Symmetry version by Jay Vosburgh (fubar@sequent.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_SYMMETRY_H
+#define TM_SYMMETRY_H 1
+
+/* I don't know if this will work for cross-debugging, even if you do get
+ a copy of the right include file. */
+#include <machine/reg.h>
+
+#include "i386/tm-i386v.h"
+
+#undef START_INFERIOR_TRAPS_EXPECTED
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+/* Amount PC must be decremented by after a breakpoint. This is often the
+ number of bytes in BREAKPOINT but not always (such as now). */
+
+#undef DECR_PC_AFTER_BREAK
+#define DECR_PC_AFTER_BREAK 0
+
+#if 0
+/* --- this code can't be used unless we know we are running native,
+ since it uses host specific ptrace calls. */
+/* code for 80387 fpu. Functions are from i386-dep.c, copied into
+ * symm-dep.c.
+ */
+#define FLOAT_INFO { i386_float_info(); }
+#endif
+
+/* Number of machine registers */
+
+#undef NUM_REGS
+#define NUM_REGS 49
+
+/* Initializer for an array of names of registers.
+ There should be NUM_REGS strings in this initializer. */
+
+/* Initializer for an array of names of registers. There should be at least
+ NUM_REGS strings in this initializer. Any excess ones are simply ignored.
+ Symmetry registers are in this weird order to match the register numbers
+ in the symbol table entries. If you change the order, things will probably
+ break mysteriously for no apparent reason. Also note that the st(0)...
+ st(7) 387 registers are represented as st0...st7. */
+
+#undef REGISTER_NAMES
+#define REGISTER_NAMES { "eax", "edx", "ecx", "st0", "st1", \
+ "ebx", "esi", "edi", "st2", "st3", \
+ "st4", "st5", "st6", "st7", "esp", \
+ "ebp", "eip", "eflags","fp1", "fp2", \
+ "fp3", "fp4", "fp5", "fp6", "fp7", \
+ "fp8", "fp9", "fp10", "fp11", "fp12", \
+ "fp13", "fp14", "fp15", "fp16", "fp17", \
+ "fp18", "fp19", "fp20", "fp21", "fp22", \
+ "fp23", "fp24", "fp25", "fp26", "fp27", \
+ "fp28", "fp29", "fp30", "fp31" }
+
+/* Register numbers of various important registers.
+ Note that some of these values are "real" register numbers,
+ and correspond to the general registers of the machine,
+ and some are "phony" register numbers which are too large
+ to be actual register numbers as far as the user is concerned
+ but do serve to get the desired values when passed to read_register. */
+
+#define EAX_REGNUM 0
+#define EDX_REGNUM 1
+#define ECX_REGNUM 2
+#define ST0_REGNUM 3
+#define ST1_REGNUM 4
+#define EBX_REGNUM 5
+#define ESI_REGNUM 6
+#define EDI_REGNUM 7
+#define ST2_REGNUM 8
+#define ST3_REGNUM 9
+
+#define ST4_REGNUM 10
+#define ST5_REGNUM 11
+#define ST6_REGNUM 12
+#define ST7_REGNUM 13
+
+#define FP1_REGNUM 18 /* first 1167 register */
+/* Get %fp2 - %fp31 by addition, since they are contiguous */
+
+#undef SP_REGNUM
+#define SP_REGNUM 14 /* (usp) Contains address of top of stack */
+#define ESP_REGNUM 14
+#undef FP_REGNUM
+#define FP_REGNUM 15 /* (ebp) Contains address of executing stack frame */
+#define EBP_REGNUM 15
+#undef PC_REGNUM
+#define PC_REGNUM 16 /* (eip) Contains program counter */
+#define EIP_REGNUM 16
+#undef PS_REGNUM
+#define PS_REGNUM 17 /* (ps) Contains processor status */
+#define EFLAGS_REGNUM 17
+
+/*
+ * Following macro translates i386 opcode register numbers to Symmetry
+ * register numbers. This is used by i386_frame_find_saved_regs.
+ *
+ * %eax %ecx %edx %ebx %esp %ebp %esi %edi
+ * i386 0 1 2 3 4 5 6 7
+ * Symmetry 0 2 1 5 14 15 6 7
+ *
+ */
+#define I386_REGNO_TO_SYMMETRY(n) \
+((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
+
+/* The magic numbers below are offsets into u_ar0 in the user struct.
+ * They live in <machine/reg.h>. Gdb calls this macro with blockend
+ * holding u.u_ar0 - KERNEL_U_ADDR. Only the registers listed are
+ * saved in the u area (along with a few others that aren't useful
+ * here. See <machine/reg.h>).
+ */
+
+#define REGISTER_U_ADDR(addr, blockend, regno) \
+{ struct user foo; /* needed for finding fpu regs */ \
+switch (regno) { \
+ case 0: \
+ addr = blockend + EAX * sizeof(int); break; \
+ case 1: \
+ addr = blockend + EDX * sizeof(int); break; \
+ case 2: \
+ addr = blockend + ECX * sizeof(int); break; \
+ case 3: /* st(0) */ \
+ addr = ((int)&foo.u_fpusave.fpu_stack[0][0] - (int)&foo); \
+ break; \
+ case 4: /* st(1) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[1][0] - (int)&foo); \
+ break; \
+ case 5: \
+ addr = blockend + EBX * sizeof(int); break; \
+ case 6: \
+ addr = blockend + ESI * sizeof(int); break; \
+ case 7: \
+ addr = blockend + EDI * sizeof(int); break; \
+ case 8: /* st(2) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[2][0] - (int)&foo); \
+ break; \
+ case 9: /* st(3) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[3][0] - (int)&foo); \
+ break; \
+ case 10: /* st(4) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[4][0] - (int)&foo); \
+ break; \
+ case 11: /* st(5) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[5][0] - (int)&foo); \
+ break; \
+ case 12: /* st(6) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[6][0] - (int)&foo); \
+ break; \
+ case 13: /* st(7) */ \
+ addr = ((int) &foo.u_fpusave.fpu_stack[7][0] - (int)&foo); \
+ break; \
+ case 14: \
+ addr = blockend + ESP * sizeof(int); break; \
+ case 15: \
+ addr = blockend + EBP * sizeof(int); break; \
+ case 16: \
+ addr = blockend + EIP * sizeof(int); break; \
+ case 17: \
+ addr = blockend + FLAGS * sizeof(int); break; \
+ case 18: /* fp1 */ \
+ case 19: /* fp2 */ \
+ case 20: /* fp3 */ \
+ case 21: /* fp4 */ \
+ case 22: /* fp5 */ \
+ case 23: /* fp6 */ \
+ case 24: /* fp7 */ \
+ case 25: /* fp8 */ \
+ case 26: /* fp9 */ \
+ case 27: /* fp10 */ \
+ case 28: /* fp11 */ \
+ case 29: /* fp12 */ \
+ case 30: /* fp13 */ \
+ case 31: /* fp14 */ \
+ case 32: /* fp15 */ \
+ case 33: /* fp16 */ \
+ case 34: /* fp17 */ \
+ case 35: /* fp18 */ \
+ case 36: /* fp19 */ \
+ case 37: /* fp20 */ \
+ case 38: /* fp21 */ \
+ case 39: /* fp22 */ \
+ case 40: /* fp23 */ \
+ case 41: /* fp24 */ \
+ case 42: /* fp25 */ \
+ case 43: /* fp26 */ \
+ case 44: /* fp27 */ \
+ case 45: /* fp28 */ \
+ case 46: /* fp29 */ \
+ case 47: /* fp30 */ \
+ case 48: /* fp31 */ \
+ addr = ((int) &foo.u_fpasave.fpa_regs[(regno)-18] - (int)&foo); \
+ } \
+}
+
+/* Total amount of space needed to store our copies of the machine's
+ register state, the array `registers'. 10 i*86 registers, 8 i387
+ registers, and 31 Weitek 1167 registers */
+
+#undef REGISTER_BYTES
+#define REGISTER_BYTES ((10 * 4) + (8 * 10) + (31 * 4))
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+#undef REGISTER_BYTE
+#define REGISTER_BYTE(N) \
+(((N) < 3) ? ((N) * 4) : \
+((N) < 5) ? ((((N) - 2) * 10) + 2) : \
+((N) < 8) ? ((((N) - 5) * 4) + 32) : \
+((N) < 14) ? ((((N) - 8) * 10) + 44) : \
+ ((((N) - 14) * 4) + 104))
+
+/* Number of bytes of storage in the actual machine representation
+ * for register N. All registers are 4 bytes, except 387 st(0) - st(7),
+ * which are 80 bits each.
+ */
+
+#undef REGISTER_RAW_SIZE
+#define REGISTER_RAW_SIZE(N) \
+(((N) < 3) ? 4 : \
+((N) < 5) ? 10 : \
+((N) < 8) ? 4 : \
+((N) < 14) ? 10 : \
+ 4)
+
+/* Nonzero if register N requires conversion
+ from raw format to virtual format. */
+
+#undef REGISTER_CONVERTIBLE
+#define REGISTER_CONVERTIBLE(N) \
+(((N) < 3) ? 0 : \
+((N) < 5) ? 1 : \
+((N) < 8) ? 0 : \
+((N) < 14) ? 1 : \
+ 0)
+
+#include "floatformat.h"
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+ to virtual format with type TYPE in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+ double val; \
+ floatformat_to_double (&floatformat_i387_ext, (FROM), &val); \
+ store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+/* Convert data from virtual format with type TYPE in buffer FROM
+ to raw format for register REGNUM in buffer TO. */
+
+#undef REGISTER_CONVERT_TO_RAW
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+ double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+ floatformat_from_double (&floatformat_i387_ext, &val, (TO)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+ of data in register N. */
+
+#undef REGISTER_VIRTUAL_TYPE
+#define REGISTER_VIRTUAL_TYPE(N) \
+((N < 3) ? builtin_type_int : \
+(N < 5) ? builtin_type_double : \
+(N < 8) ? builtin_type_int : \
+(N < 14) ? builtin_type_double : \
+ builtin_type_int)
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function.
+ Native cc passes the address in eax, gcc (up to version 2.5.8)
+ passes it on the stack. gcc should be fixed in future versions to
+ adopt native cc conventions. */
+
+#undef STORE_STRUCT_RETURN
+#define STORE_STRUCT_RETURN(ADDR, SP) write_register(0, (ADDR))
+
+/* Extract from an array REGBUF containing the (raw) register state
+ a function return value of type TYPE, and copy that, in virtual format,
+ into VALBUF. */
+
+#undef EXTRACT_RETURN_VALUE
+#define EXTRACT_RETURN_VALUE(TYPE,REGBUF,VALBUF) \
+ symmetry_extract_return_value(TYPE, REGBUF, VALBUF)
+
+/* The following redefines make backtracing through sigtramp work.
+ They manufacture a fake sigtramp frame and obtain the saved pc in sigtramp
+ from the sigcontext structure which is pushed by the kernel on the
+ user stack, along with a pointer to it. */
+
+#define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigcode", name))
+
+/* Offset to saved PC in sigcontext, from <signal.h>. */
+#define SIGCONTEXT_PC_OFFSET 16
+
+#endif /* ifndef TM_SYMMETRY_H */
+
diff --git a/contrib/gdb/gdb/config/i386/xm-cygwin32.h b/contrib/gdb/gdb/config/i386/xm-cygwin32.h
new file mode 100644
index 0000000..becbebe
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-cygwin32.h
@@ -0,0 +1,41 @@
+/* Definitions for hosting on WIN32, for GDB.
+ Copyright 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include "fopen-bin.h"
+
+#define GDBINIT_FILENAME "gdb.ini"
+
+
+#define SLASH_P(X) ((X)=='\\' || (X) == '/')
+#define ROOTED_P(X) ((SLASH_P((X)[0]))|| ((X)[1] ==':'))
+#define SLASH_CHAR '/'
+#define SLASH_STRING "/"
+
+
+/* If we longjmp out of the signal handler we never get another one.
+ So disable immediate_quit inside request_quit */
+#define REQUEST_QUIT
+
+
+
+
+
+
diff --git a/contrib/gdb/gdb/config/i386/xm-go32.h b/contrib/gdb/gdb/config/i386/xm-go32.h
new file mode 100644
index 0000000..0797833
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-go32.h
@@ -0,0 +1,31 @@
+/* Definitions for hosting on GO32, for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#include "fopen-bin.h"
+
+/* Define this lseek(n) != nth byte of file */
+#define LSEEK_NOT_LINEAR
+
+#define CANT_FORK
+
+#undef QUIT
+#define QUIT { pollquit(); }
+
+#define GDBINIT_FILENAME "gdb.ini"
diff --git a/contrib/gdb/gdb/config/i386/xm-i386aix.h b/contrib/gdb/gdb/config/i386/xm-i386aix.h
new file mode 100644
index 0000000..652a149
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386aix.h
@@ -0,0 +1,33 @@
+/* Macro defintions for AIX PS/2 (i386)
+ Copyright 1986, 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Changed for IBM AIX ps/2 by Minh Tran Le (tranle@intellicorp.com)
+ * Revision: 23-Oct-92 17:42:49
+ */
+
+#include "i386/xm-i386v.h"
+
+#undef HAVE_TERMIO
+#define HAVE_SGTTY
+
+#include <limits.h>
+
+/* Use setpgid instead of setpgrp on AIX */
+#define NEED_POSIX_SETPGID
diff --git a/contrib/gdb/gdb/config/i386/xm-i386bsd.h b/contrib/gdb/gdb/config/i386/xm-i386bsd.h
new file mode 100644
index 0000000..8a852a2
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386bsd.h
@@ -0,0 +1,23 @@
+/* Host-dependent definitions for Intel 386 running BSD Unix, for GDB.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include <machine/limits.h> /* for INT_MIN, to avoid "INT_MIN
+ redefined" warnings from defs.h */
diff --git a/contrib/gdb/gdb/config/i386/xm-i386gnu.h b/contrib/gdb/gdb/config/i386/xm-i386gnu.h
new file mode 100644
index 0000000..60307b2
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386gnu.h
@@ -0,0 +1,23 @@
+/* Definitions to make GDB run on the GNU Hurd on an Intel 386
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Do implement the attach and detach commands. */
+#define ATTACH_DETACH 1
diff --git a/contrib/gdb/gdb/config/i386/xm-i386lynx.h b/contrib/gdb/gdb/config/i386/xm-i386lynx.h
new file mode 100644
index 0000000..6078cb6
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386lynx.h
@@ -0,0 +1,24 @@
+/* Host-dependent definitions for Intel 386 running LynxOS.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Get generic LynxOS host definitions. */
+
+#include "xm-lynx.h"
diff --git a/contrib/gdb/gdb/config/i386/xm-i386m3.h b/contrib/gdb/gdb/config/i386/xm-i386m3.h
new file mode 100644
index 0000000..615c80b
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386m3.h
@@ -0,0 +1,38 @@
+/* Definitions to make GDB run on Mach 3 on an Intel 386
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Avoid "INT_MIN redefined" warnings -- by defining it here, exactly
+ the same as in the system <machine/machtypes.h> file. */
+#undef INT_MIN
+#define INT_MIN 0x80000000
+
+/* Do implement the attach and detach commands. */
+#define ATTACH_DETACH 1
+
+/* Not needeed */
+#define KERNEL_U_ADDR 0
+
+#ifndef EMULATOR_BASE
+/* For EMULATOR_BASE and EMULATOR_END.
+ * OSF 1/MK has different values in some other place.
+ */
+#include <machine/vmparam.h>
+#endif /* EMULATOR_BASE */
diff --git a/contrib/gdb/gdb/config/i386/xm-i386mach.h b/contrib/gdb/gdb/config/i386/xm-i386mach.h
new file mode 100644
index 0000000..c50da67
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386mach.h
@@ -0,0 +1,35 @@
+/* Definitions to make GDB run on Mach on an Intel 386
+ Copyright (C) 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* Avoid "INT_MIN redefined" warnings -- by defining it here, exactly
+ the same as in the system <machine/machtypes.h> file. */
+#undef INT_MIN
+#define INT_MIN 0x80000000
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR (0x80000000 - (UPAGES * NBPG))
+
+/* <errno.h> only defines this if __STDC__!!! */
+extern int errno;
+
+extern char *strdup();
diff --git a/contrib/gdb/gdb/config/i386/xm-i386mk.h b/contrib/gdb/gdb/config/i386/xm-i386mk.h
new file mode 100644
index 0000000..7bbe02f
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386mk.h
@@ -0,0 +1,25 @@
+/* Definitions to make GDB run on Mach 3 OSF 1/MK on an Intel 386
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HAVE_TERMIO 1
+
+#define EMULATOR_BASE 0xa0000000
+#define EMULATOR_END 0xa0040000
+
+#include "xm-i386mach3.h"
diff --git a/contrib/gdb/gdb/config/i386/xm-i386sco.h b/contrib/gdb/gdb/config/i386/xm-i386sco.h
new file mode 100644
index 0000000..31fa7e6
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386sco.h
@@ -0,0 +1,42 @@
+/* Macro defintions for i386, running SCO Unix System V/386 3.2.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* In 3.2v4 <sys/user.h> requires on <sys/dir.h>. */
+#include <sys/types.h>
+#include <sys/dir.h>
+
+#include "i386/xm-i386v.h"
+
+/* Apparently there is inconsistency among various System V's about what
+ the name of this field is. */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
+
+/* SCO 3.2v2 and later have job control. */
+/* SCO 3.2v4 I know has termios; I'm not sure about earlier versions.
+ GDB does not currently support the termio/job control combination. */
+#undef HAVE_TERMIO
+#define HAVE_TERMIOS
+
+/* SCO's assembler doesn't grok dollar signs in identifiers.
+ So we use dots instead. This item must be coordinated with G++. */
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'
+
+/* Use setpgid instead of setpgrp on SCO */
+#define NEED_POSIX_SETPGID
diff --git a/contrib/gdb/gdb/config/i386/xm-i386v.h b/contrib/gdb/gdb/config/i386/xm-i386v.h
new file mode 100644
index 0000000..480dfd6
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386v.h
@@ -0,0 +1,45 @@
+/* Host support for i386.
+ Copyright 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+ Changes for 80386 by Pace Willisson (pace@prep.ai.mit.edu), July 1988.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+/* I'm running gdb 3.4 under 386/ix 2.0.2, which is a derivative of AT&T's
+Sys V/386 3.2.
+
+On some machines, gdb crashes when it's starting up while calling the
+vendor's termio tgetent() routine. It always works when run under
+itself (actually, under 3.2, it's not an infinitely recursive bug.)
+After some poking around, it appears that depending on the environment
+size, or whether you're running YP, or the phase of the moon or something,
+the stack is not always long-aligned when main() is called, and tgetent()
+takes strong offense at that. On some machines this bug never appears, but
+on those where it does, it occurs quite reliably. */
+#define ALIGN_STACK_ON_STARTUP
+
+/* define USG if you are using sys5 /usr/include's */
+#define USG
+
+#define HAVE_TERMIO
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#define KERNEL_U_ADDR 0xe0000000
+
diff --git a/contrib/gdb/gdb/config/i386/xm-i386v32.h b/contrib/gdb/gdb/config/i386/xm-i386v32.h
new file mode 100644
index 0000000..daaac80
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386v32.h
@@ -0,0 +1,24 @@
+/* Macro defintions for i386, running System V 3.2.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "i386/xm-i386v.h"
+
+/* Apparently there is inconsistency among various System V's about what
+ the name of this field is. */
+#define U_FPSTATE(u) u.u_fps.u_fpstate
diff --git a/contrib/gdb/gdb/config/i386/xm-i386v4.h b/contrib/gdb/gdb/config/i386/xm-i386v4.h
new file mode 100644
index 0000000..7d5aff0
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-i386v4.h
@@ -0,0 +1,37 @@
+/* Macro definitions for GDB on an Intel i386 running SVR4.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Pick up most of what we need from the generic i386 host include file. */
+
+#include "i386/xm-i386v.h"
+
+/* Pick up more stuff from the generic SVR4 host include file. */
+
+#include "xm-sysv4.h"
+
+/* If you expect to use the mmalloc package to obtain mapped symbol files,
+ for now you have to specify some parameters that determine how gdb places
+ the mappings in it's address space. See the comments in map_to_address()
+ for details. This is expected to only be a short term solution. Yes it
+ is a kludge.
+ FIXME: Make this more automatic. */
+
+#define MMAP_BASE_ADDRESS 0x81000000 /* First mapping here */
+#define MMAP_INCREMENT 0x01000000 /* Increment to next mapping */
diff --git a/contrib/gdb/gdb/config/i386/xm-linux.h b/contrib/gdb/gdb/config/i386/xm-linux.h
new file mode 100644
index 0000000..5004926
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-linux.h
@@ -0,0 +1,46 @@
+/* Native support for linux, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef XM_LINUX_H
+#define XM_LINUX_H
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#define HAVE_TERMIOS
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+#define KERNEL_U_ADDR 0x0
+
+#define NEED_POSIX_SETPGID
+
+/* Need R_OK etc, but USG isn't defined. */
+#include <unistd.h>
+
+/* If you expect to use the mmalloc package to obtain mapped symbol files,
+ for now you have to specify some parameters that determine how gdb places
+ the mappings in it's address space. See the comments in map_to_address()
+ for details. This is expected to only be a short term solution. Yes it
+ is a kludge.
+ FIXME: Make this more automatic. */
+
+#define MMAP_BASE_ADDRESS 0x20000000 /* First mapping here */
+#define MMAP_INCREMENT 0x01000000 /* Increment to next mapping */
+
+#endif /* #ifndef XM_LINUX_H */
diff --git a/contrib/gdb/gdb/config/i386/xm-nbsd.h b/contrib/gdb/gdb/config/i386/xm-nbsd.h
new file mode 100644
index 0000000..b5624ac
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-nbsd.h
@@ -0,0 +1,21 @@
+/* Parameters for execution on a i386 running NetBSD, for GDB.
+ Copyright 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Get generic NetBSD host definitions. */
+#include "xm-nbsd.h"
diff --git a/contrib/gdb/gdb/config/i386/xm-ptx.h b/contrib/gdb/gdb/config/i386/xm-ptx.h
new file mode 100644
index 0000000..99b46cc
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-ptx.h
@@ -0,0 +1,41 @@
+/* Definitions to make GDB run on a Sequent Symmetry under ptx, with
+ Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1992, 1993, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Symmetry version by Jay Vosburgh (fubar@sequent.com) */
+
+#ifdef _SEQUENT_PTX4_
+#include "xm-sysv4.h"
+#endif /* _SEQUENT_PTX4_ */
+
+/* This machine doesn't have the siginterrupt call. */
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+#undef HAVE_TERMIO
+#define HAVE_TERMIOS
+#define USG
+
+#define NEED_POSIX_SETPGID
+
+#define USE_O_NOCTTY
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/contrib/gdb/gdb/config/i386/xm-ptx4.h b/contrib/gdb/gdb/config/i386/xm-ptx4.h
new file mode 100644
index 0000000..bdbdefd
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-ptx4.h
@@ -0,0 +1,25 @@
+/* Definitions to make GDB run on a Sequent Symmetry under ptx, with
+ Weitek 1167 and i387 support. Copyright 1986, 1987, 1989, 1992,
+ 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Symmetry version by Jay Vosburgh (fubar@sequent.com) */
+
+#include "xm-sysv4.h"
+
+#include "xm-ptx.h"
diff --git a/contrib/gdb/gdb/config/i386/xm-sun386.h b/contrib/gdb/gdb/config/i386/xm-sun386.h
new file mode 100644
index 0000000..51c3b58
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-sun386.h
@@ -0,0 +1,20 @@
+/* Host support for Sun 386i, for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/contrib/gdb/gdb/config/i386/xm-symmetry.h b/contrib/gdb/gdb/config/i386/xm-symmetry.h
new file mode 100644
index 0000000..52e9a9a
--- /dev/null
+++ b/contrib/gdb/gdb/config/i386/xm-symmetry.h
@@ -0,0 +1,28 @@
+/* Definitions to make GDB run on a Sequent Symmetry under
+ dynix 3.1, with Weitek 1167 and i387 support.
+ Copyright 1986, 1987, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Symmetry version by Jay Vosburgh (fubar@sequent.com) */
+
+/* This machine doesn't have the siginterrupt call. */
+#define NO_SIGINTERRUPT
+
+#define HAVE_WAIT_STRUCT
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
diff --git a/contrib/gdb/gdb/config/nm-empty.h b/contrib/gdb/gdb/config/nm-empty.h
new file mode 100644
index 0000000..7069d8c
--- /dev/null
+++ b/contrib/gdb/gdb/config/nm-empty.h
@@ -0,0 +1,2 @@
+/* This is just a dummy file to symlink to when GDB is configured as a
+ cross-only debugger. */
diff --git a/contrib/gdb/gdb/config/nm-gnu.h b/contrib/gdb/gdb/config/nm-gnu.h
new file mode 100644
index 0000000..f59a2dc
--- /dev/null
+++ b/contrib/gdb/gdb/config/nm-gnu.h
@@ -0,0 +1,46 @@
+/* Common declarations for the GNU Hurd
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */
+
+#ifndef __NM_GNU_H__
+#define __NM_GNU_H__
+
+#include <unistd.h>
+#include <mach.h>
+#include <mach/exception.h>
+
+#include "solib.h" /* Support for shared libraries. */
+
+#undef target_pid_to_str
+#define target_pid_to_str(pid) gnu_target_pid_to_str(pid)
+extern char *gnu_target_pid_to_str (int pid);
+
+/* Before storing, we need to read all the registers. */
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Don't do wait_for_inferior on attach. */
+#define ATTACH_NO_WAIT
+
+/* Use SVR4 style shared library support */
+#define SVR4_SHARED_LIBS
+#define NO_CORE_OPS
+
+#define MAINTENANCE_CMDS 1
+
+#endif /* __NM_GNU_H__ */
diff --git a/contrib/gdb/gdb/config/nm-lynx.h b/contrib/gdb/gdb/config/nm-lynx.h
new file mode 100644
index 0000000..8781a9a
--- /dev/null
+++ b/contrib/gdb/gdb/config/nm-lynx.h
@@ -0,0 +1,83 @@
+/* Native-dependent definitions for LynxOS.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_LYNX_H
+#define NM_LYNX_H
+
+#include <sys/conf.h>
+#include <sys/kernel.h>
+/* sys/kernel.h should define this, but doesn't always, sigh. */
+#ifndef __LYNXOS
+#define __LYNXOS
+#endif
+#include <sys/mem.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/itimer.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include "thread.h"
+
+/* This is the amount to subtract from u.u_ar0 to get the offset in
+ the core file of the register values. */
+
+#define KERNEL_U_ADDR USRSTACK
+
+#undef FLOAT_INFO /* No float info yet */
+
+/* As of LynxOS 2.2.2 (beta 8/15/94), this is int. Previous versions seem to
+ have had no prototype, so I'm not sure why GDB used to define this to
+ char *. */
+#define PTRACE_ARG3_TYPE int
+
+/* Override copies of {fetch,store}_inferior_registers in infptrace.c. */
+
+#define FETCH_INFERIOR_REGISTERS
+
+/* Thread ID of stopped thread. */
+
+#define WIFTID(x) (((union wait *)&x)->w_tid)
+
+/* Override child_wait in inftarg.c */
+
+#define CHILD_WAIT
+
+/* Override child_resume in infptrace.c */
+
+#define CHILD_RESUME
+
+/* Override child_thread_alive in intarg.c */
+
+#define CHILD_THREAD_ALIVE
+
+#include "target.h"
+
+extern int child_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+/* Lynx needs a special definition of this so that we can
+ print out the pid and thread number seperatly. */
+
+#undef target_pid_to_str
+
+#define target_pid_to_str(PID) lynx_pid_to_str (PID)
+
+extern char *lynx_pid_to_str PARAMS ((int pid));
+
+#endif /* NM_LYNX_H */
diff --git a/contrib/gdb/gdb/config/nm-m3.h b/contrib/gdb/gdb/config/nm-m3.h
new file mode 100644
index 0000000..6ea5256
--- /dev/null
+++ b/contrib/gdb/gdb/config/nm-m3.h
@@ -0,0 +1,123 @@
+/* Mach 3.0 common definitions and global vars.
+
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef NM_M3_H
+#define NM_M3_H
+
+#include <mach.h>
+
+/* Mach3 doesn't declare errno in <errno.h>. */
+extern int errno;
+
+/* Task port of our debugged inferior. */
+
+extern task_t inferior_task;
+
+/* Thread port of the current thread in the inferior. */
+
+extern thread_t current_thread;
+
+/* If nonzero, we must suspend/abort && resume threads
+ * when setting or getting the state.
+ */
+extern int must_suspend_thread;
+
+#define PREPARE_TO_PROCEED(select_it) mach3_prepare_to_proceed(select_it)
+
+/* Try to get the privileged host port for authentication to machid
+ *
+ * If you can get this, you may debug anything on this host.
+ *
+ * If you can't, gdb gives it's own task port as the
+ * authentication port
+ */
+#define mach_privileged_host_port() task_by_pid(-1)
+
+/*
+ * This is the MIG ID number of the emulator/server bsd_execve() RPC call.
+ *
+ * It SHOULD never change, but if it does, gdb `run'
+ * command won't work until you fix this define.
+ *
+ */
+#define MIG_EXEC_SYSCALL_ID 101000
+
+/* If our_message_port gets a msg with this ID,
+ * GDB suspends it's inferior and enters command level.
+ * (Useful at least if ^C does not work)
+ */
+#define GDB_MESSAGE_ID_STOP 0x41151
+
+/* wait3 WNOHANG is defined in <sys/wait.h> but
+ * for some reason gdb does not want to include
+ * that file.
+ *
+ * If your system defines WNOHANG differently, this has to be changed.
+ */
+#define WNOHANG 1
+
+/* Before storing, we need to read all the registers. */
+
+#define CHILD_PREPARE_TO_STORE() read_register_bytes (0, NULL, REGISTER_BYTES)
+
+/* Check if the inferior exists */
+#define MACH_ERROR_NO_INFERIOR \
+ do if (!MACH_PORT_VALID (inferior_task)) \
+ error ("Inferior task does not exist."); while(0)
+
+/* Error handler for mach calls */
+#define CHK(str,ret) \
+ do if (ret != KERN_SUCCESS) \
+ error ("Gdb %s [%d] %s : %s\n",__FILE__,__LINE__,str, \
+ mach_error_string(ret)); while(0)
+
+/* This is from POE9 emulator/emul_stack.h
+ */
+/*
+ * Top of emulator stack holds link and reply port.
+ */
+struct emul_stack_top {
+ struct emul_stack_top *link;
+ mach_port_t reply_port;
+};
+
+#define EMULATOR_STACK_SIZE (4096*4)
+
+#define THREAD_ALLOWED_TO_BREAK(mid) mach_thread_for_breakpoint (mid)
+
+#define THREAD_PARSE_ID(arg) mach_thread_parse_id (arg)
+
+#define THREAD_OUTPUT_ID(mid) mach_thread_output_id (mid)
+
+#define ATTACH_TO_THREAD attach_to_thread
+
+/* Don't do wait_for_inferior on attach. */
+#define ATTACH_NO_WAIT
+
+/* Do Mach 3 dependent operations when ^C or a STOP is requested */
+#define DO_QUIT() mach3_quit ()
+
+#if 0
+/* This is bogus. It is NOT OK to quit out of target_wait. */
+/* If in mach_msg() and ^C is typed set immediate_quit */
+#define REQUEST_QUIT() mach3_request_quit ()
+#endif
+
+#endif /* NM_M3_H */
diff --git a/contrib/gdb/gdb/config/nm-nbsd.h b/contrib/gdb/gdb/config/nm-nbsd.h
new file mode 100644
index 0000000..bc1d6a6
--- /dev/null
+++ b/contrib/gdb/gdb/config/nm-nbsd.h
@@ -0,0 +1,86 @@
+/* Native-dependent definitions for NetBSD.
+ Copyright 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is the amount to subtract from u.u_ar0
+ to get the offset in the core file of the register values. */
+
+#include <machine/vmparam.h>
+
+#define KERNEL_U_ADDR USRSTACK
+
+#define PTRACE_ARG3_TYPE char*
+
+#define FETCH_INFERIOR_REGISTERS
+
+#define ATTACH_DETACH
+
+#include "solib.h" /* Support for shared libraries. */
+
+/* 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
diff --git a/contrib/gdb/gdb/config/nm-sysv4.h b/contrib/gdb/gdb/config/nm-sysv4.h
new file mode 100644
index 0000000..e4978d0
--- /dev/null
+++ b/contrib/gdb/gdb/config/nm-sysv4.h
@@ -0,0 +1,34 @@
+/* Definitions for running gdb on a host machine running any flavor of SVR4.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "solib.h" /* Support for shared libraries. */
+
+/* Use SVR4 style shared library support */
+
+#define SVR4_SHARED_LIBS
+
+/* SVR4 has /proc support, so use it instead of ptrace. */
+
+#define USE_PROC_FS
+
+/* SVR4 machines can easily do attach and detach via /proc (procfs.c)
+ support */
+
+#define ATTACH_DETACH
diff --git a/contrib/gdb/gdb/config/tm-lynx.h b/contrib/gdb/gdb/config/tm-lynx.h
new file mode 100644
index 0000000..7107241
--- /dev/null
+++ b/contrib/gdb/gdb/config/tm-lynx.h
@@ -0,0 +1,34 @@
+/* Macro definitions for LynxOS targets.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef TM_LYNX_H
+#define TM_LYNX_H
+
+/* Override number of expected traps from sysv. */
+#define START_INFERIOR_TRAPS_EXPECTED 2
+
+#include "coff-solib.h" /* COFF shared library support */
+
+/* Lynx's signal.h doesn't seem to have any macros for what signal numbers
+ the real-time events are. */
+#define REALTIME_LO 33
+/* One more than the last one. */
+#define REALTIME_HI 64
+
+#endif /* TM_LYNX_H */
diff --git a/contrib/gdb/gdb/config/tm-nbsd.h b/contrib/gdb/gdb/config/tm-nbsd.h
new file mode 100644
index 0000000..e295d85
--- /dev/null
+++ b/contrib/gdb/gdb/config/tm-nbsd.h
@@ -0,0 +1,19 @@
+/* Target machine sub-description for NetBSD.
+ This is included by other tm-*.h files to specify NetBSD-specific stuff.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
diff --git a/contrib/gdb/gdb/config/tm-sunos.h b/contrib/gdb/gdb/config/tm-sunos.h
new file mode 100644
index 0000000..26ec3cf
--- /dev/null
+++ b/contrib/gdb/gdb/config/tm-sunos.h
@@ -0,0 +1,31 @@
+/* Target machine sub-description for SunOS version 4.
+ This is included by other tm-*.h files to specify SunOS-specific stuff.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "solib.h" /* Support for shared libraries. */
+
+/* Return non-zero if we are in a shared library trampoline code stub. */
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) \
+ lookup_solib_trampoline_symbol_by_pc (pc)
+
+/* If PC is in a shared library trampoline code, return the PC
+ where the function itself actually starts. If not, return 0. */
+
+#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
diff --git a/contrib/gdb/gdb/config/tm-sysv4.h b/contrib/gdb/gdb/config/tm-sysv4.h
new file mode 100644
index 0000000..2c08541
--- /dev/null
+++ b/contrib/gdb/gdb/config/tm-sysv4.h
@@ -0,0 +1,45 @@
+/* Macro definitions for GDB on all SVR4 target systems.
+ Copyright 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* For SVR4 shared libraries, each call to a library routine goes through
+ a small piece of trampoline code in the ".plt" section.
+ The horribly ugly wait_for_inferior() routine uses this macro to detect
+ when we have stepped into one of these fragments.
+ We do not use lookup_solib_trampoline_symbol_by_pc, because
+ we cannot always find the shared library trampoline symbols
+ (e.g. on Irix5). */
+
+#define IN_SOLIB_CALL_TRAMPOLINE(pc, name) in_plt_section((pc), (name))
+extern int in_plt_section PARAMS ((CORE_ADDR, char *));
+
+/* If PC is in a shared library trampoline code, return the PC
+ where the function itself actually starts. If not, return 0. */
+
+#define SKIP_TRAMPOLINE_CODE(pc) find_solib_trampoline_target (pc)
+
+/* It is unknown which, if any, SVR4 assemblers do not accept dollar signs
+ in identifiers. The default in G++ is to use dots instead, for all SVR4
+ systems, so we make that our default also. FIXME: There should be some
+ way to get G++ to tell us what CPLUS_MARKER it is using, perhaps by
+ stashing it in the debugging information as part of the name of an
+ invented symbol ("gcc_cplus_marker$" for example). */
+
+#undef CPLUS_MARKER
+#define CPLUS_MARKER '.'
diff --git a/contrib/gdb/gdb/config/xm-aix4.h b/contrib/gdb/gdb/config/xm-aix4.h
new file mode 100644
index 0000000..31bb6da
--- /dev/null
+++ b/contrib/gdb/gdb/config/xm-aix4.h
@@ -0,0 +1,96 @@
+/* Parameters for hosting on an PowerPC, for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Corporation.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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. */
+
+/* The following text is taken from config/rs6000.mh:
+ * # The IBM version of /usr/include/rpc/rpc.h has a bug -- it says
+ * # `extern fd_set svc_fdset;' without ever defining the type fd_set.
+ * # Unfortunately this occurs in the vx-share code, which is not configured
+ * # like the rest of GDB (e.g. it doesn't include "defs.h").
+ * # We circumvent this bug by #define-ing fd_set here, but undefining it in
+ * # the xm-rs6000.h file before ordinary modules try to use it. FIXME, IBM!
+ * MH_CFLAGS='-Dfd_set=int'
+ * So, here we do the undefine...which has to occur before we include
+ * <sys/select.h> below.
+ */
+#undef fd_set
+
+#include <sys/select.h>
+
+/* Big end is at the low address */
+
+#define HOST_BYTE_ORDER BIG_ENDIAN
+
+/* At least as of AIX 3.2, we have termios. */
+#define HAVE_TERMIOS 1
+/* #define HAVE_TERMIO 1 */
+
+#define USG 1
+#define HAVE_SIGSETMASK 1
+
+#define FIVE_ARG_PTRACE
+
+/* AIX declares the mem functions differently than defs.h does. AIX is
+ right, but defs.h works on more old systems. For now, override it. */
+
+#define MEM_FNS_DECLARED 1
+
+/* This system requires that we open a terminal with O_NOCTTY for it to
+ not become our controlling terminal. */
+
+#define USE_O_NOCTTY
+
+/* Brain death inherited from PC's pervades. */
+#undef NULL
+#define NULL 0
+
+/* The IBM compiler requires this in order to properly compile alloca(). */
+#pragma alloca
+
+/* There is no vfork. */
+
+#define vfork fork
+
+/* Signal handler for SIGWINCH `window size changed'. */
+
+#define SIGWINCH_HANDLER aix_resizewindow
+extern void aix_resizewindow ();
+
+/* `lines_per_page' and `chars_per_line' are local to utils.c. Rectify this. */
+
+#define SIGWINCH_HANDLER_BODY \
+ \
+/* Respond to SIGWINCH `window size changed' signal, and reset GDB's \
+ window settings approproatelt. */ \
+ \
+void \
+aix_resizewindow () \
+{ \
+ int fd = fileno (stdout); \
+ if (isatty (fd)) { \
+ int val; \
+ \
+ val = atoi (termdef (fd, 'l')); \
+ if (val > 0) \
+ lines_per_page = val; \
+ val = atoi (termdef (fd, 'c')); \
+ if (val > 0) \
+ chars_per_line = val; \
+ } \
+}
diff --git a/contrib/gdb/gdb/config/xm-lynx.h b/contrib/gdb/gdb/config/xm-lynx.h
new file mode 100644
index 0000000..6f19abd
--- /dev/null
+++ b/contrib/gdb/gdb/config/xm-lynx.h
@@ -0,0 +1,22 @@
+/* Host-dependent definitions for any CPU running LynxOS.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* for INT_MIN, to avoid "INT_MIN redefined" warnings from defs.h */
+
+#include <limits.h>
diff --git a/contrib/gdb/gdb/config/xm-mpw.h b/contrib/gdb/gdb/config/xm-mpw.h
new file mode 100644
index 0000000..0c473d7
--- /dev/null
+++ b/contrib/gdb/gdb/config/xm-mpw.h
@@ -0,0 +1,81 @@
+/* Macro definitions for running GDB on Apple Macintoshes.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "mpw.h"
+
+#include "fopen-bin.h"
+
+#include "spin.h"
+
+#define CANT_FORK
+
+/* Map these standard functions to versions that can do I/O in a console
+ window. */
+
+#define printf hacked_printf
+#define fprintf hacked_fprintf
+#define vprintf hacked_vfprintf
+#define fputs hacked_fputs
+#define fputc hacked_fputc
+#undef putc
+#define putc hacked_putc
+#define fflush hacked_fflush
+
+#define fgetc hacked_fgetc
+
+#define POSIX_UTIME
+
+/* No declaration of strdup in MPW's string.h, oddly enough. */
+
+char *strdup (char *s1);
+
+/* '.' indicates drivers on the Mac, so we need a different filename. */
+
+#define GDBINIT_FILENAME "_gdbinit"
+
+/* Commas are more common to separate dirnames in a path on Macs. */
+
+#define DIRNAME_SEPARATOR ','
+
+/* This is a real crufty hack. */
+
+#define HAVE_TERMIO
+
+/* Addons to the basic MPW-supported signal list. */
+
+#ifndef SIGQUIT
+#define SIGQUIT (1<<6)
+#endif
+#ifndef SIGHUP
+#define SIGHUP (1<<7)
+#endif
+
+/* If __STDC__ is on, then this definition will be missing. */
+
+#ifndef fileno
+#define fileno(p) (p)->_file
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#endif
+
+extern int StandAlone;
+
+extern int mac_app;
diff --git a/contrib/gdb/gdb/config/xm-nbsd.h b/contrib/gdb/gdb/config/xm-nbsd.h
new file mode 100644
index 0000000..5d52270
--- /dev/null
+++ b/contrib/gdb/gdb/config/xm-nbsd.h
@@ -0,0 +1,37 @@
+/* Host-dependent definitions for any CPU running NetBSD.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* We have to include these files now, so that GDB will not make
+ competing definitions in defs.h. */
+#include <limits.h>
+
+#include <machine/endian.h>
+#if BYTE_ORDER == BIG_ENDIAN
+#define HOST_BYTE_ORDER BIG_ENDIAN
+#else
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+#endif
+
+/* NetBSD has termios facilities. */
+#define HAVE_TERMIOS
+
+#if 0
+#define CC_HAS_LONG_LONG 1
+#define PRINTF_HAS_LONG_LONG 1
+#endif
diff --git a/contrib/gdb/gdb/config/xm-sysv4.h b/contrib/gdb/gdb/config/xm-sysv4.h
new file mode 100644
index 0000000..1ffe8fa
--- /dev/null
+++ b/contrib/gdb/gdb/config/xm-sysv4.h
@@ -0,0 +1,36 @@
+/* Definitions for running gdb on a host machine running any flavor of SVR4.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* SVR4 has termios facilities. */
+
+#undef HAVE_TERMIO
+#define HAVE_TERMIOS
+
+/* SVR4 is a derivative of System V Release 3 (USG) */
+
+#define USG
+
+/* Use setpgid(0,0) to run inferior in a separate process group */
+
+#define NEED_POSIX_SETPGID
+
+/* We have to include these files now, so that GDB will not make
+ competing definitions in defs.h. */
+#include <limits.h>
diff --git a/contrib/gdb/gdb/configure b/contrib/gdb/gdb/configure
new file mode 100644
index 0000000..e8a1ad9
--- /dev/null
+++ b/contrib/gdb/gdb/configure
@@ -0,0 +1,2745 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.8
+# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-netrom "
+ac_help="$ac_help
+ --enable-gm "
+ac_help="$ac_help
+ --enable-sim-powerpc "
+ac_help="$ac_help
+ --enable-gdbtk "
+ac_help="$ac_help
+ --with-x use the X Window System"
+ac_help="$ac_help
+ --with-tclinclude directory where tcl private headers are"
+ac_help="$ac_help
+ --with-tcllib directory where the tcl library is"
+ac_help="$ac_help
+ --with-tkinclude directory where the tk private headers are"
+ac_help="$ac_help
+ --with-tklib directory where the tk library is"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.8"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=main.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ ac_prog_rejected=no
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:622: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+ if test "${CFLAGS+set}" != set; then
+ echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_gcc_g=yes
+else
+ ac_cv_prog_gcc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
+ if test $ac_cv_prog_gcc_g = yes; then
+ CFLAGS="-g -O"
+ else
+ CFLAGS="-O"
+ fi
+ fi
+else
+ GCC=
+ test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 674 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:680: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 689 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:695: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for AIX""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 717 "configure"
+#include "confdefs.h"
+#ifdef _AIX
+ yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "yes" >/dev/null 2>&1; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6; cat >> confdefs.h <<\EOF
+#define _ALL_SOURCE 1
+EOF
+
+else
+ rm -rf conftest*
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+
+
+ac_safe=`echo "minix/config.h" | tr './\055' '___'`
+echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 744 "configure"
+#include "confdefs.h"
+#include <minix/config.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:749: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ MINIX=yes
+else
+ echo "$ac_t""no" 1>&6
+MINIX=
+fi
+
+if test "$MINIX" = yes; then
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _POSIX_1_SOURCE 2
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define _MINIX 1
+EOF
+
+fi
+
+echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
+if test -d /etc/conf/kconfig.d &&
+ grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
+then
+ echo "$ac_t""yes" 1>&6
+ ISC=yes # If later tests want to check for ISC.
+ cat >> confdefs.h <<\EOF
+#define _POSIX_SOURCE 1
+EOF
+
+ if test "$GCC" = yes; then
+ CC="$CC -posix"
+ else
+ CC="$CC -Xp"
+ fi
+else
+ echo "$ac_t""no" 1>&6
+ ISC=
+fi
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`$ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+if test $host != $build; then
+ ac_tool_prefix=${host_alias}-
+else
+ ac_tool_prefix=
+fi
+
+# Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_AR" && ac_cv_prog_AR="ar"
+fi
+fi
+AR="$ac_cv_prog_AR"
+if test -n "$AR"; then
+ echo "$ac_t""$AR" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+
+# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "$ac_cv_prog_RANLIB"; then
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ RANLIB=":"
+fi
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_YACC="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+ echo "$ac_t""$YACC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+for ac_prog in mawk gawk nawk awk
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_AWK="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+AWK="$ac_cv_prog_AWK"
+if test -n "$AWK"; then
+ echo "$ac_t""$AWK" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$AWK" && break
+done
+
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/.. $srcdir/`cd $srcdir;pwd`/..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/.. $srcdir/`cd $srcdir;pwd`/.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`$ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`$ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+# If we cannot run a trivial program, we must be cross compiling.
+echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_cross=yes
+else
+cat > conftest.$ac_ext <<EOF
+#line 1225 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+{ (eval echo configure:1229: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_c_cross=no
+else
+ ac_cv_c_cross=yes
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_cross" 1>&6
+cross_compiling=$ac_cv_c_cross
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1247 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1255: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1270 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1288 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+cat > conftest.$ac_ext <<EOF
+#line 1309 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+{ (eval echo configure:1320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+for ac_hdr in limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h sys/procfs.h link.h endian.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1347 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1352: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | tr 'abcdefghijklmnopqrstuvwxyz./\055' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ___'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1381 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(S_ISBLK) && defined(S_IFDIR)
+# if S_ISBLK (S_IFDIR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISBLK) && defined(S_IFCHR)
+# if S_ISBLK (S_IFCHR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISLNK) && defined(S_IFREG)
+# if S_ISLNK (S_IFREG)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISSOCK) && defined(S_IFREG)
+# if S_ISSOCK (S_IFREG)
+You lose.
+# endif
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "You lose" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_header_stat_broken=yes
+else
+ rm -rf conftest*
+ ac_cv_header_stat_broken=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_header_stat_broken" 1>&6
+if test $ac_cv_header_stat_broken = yes; then
+ cat >> confdefs.h <<\EOF
+#define STAT_MACROS_BROKEN 1
+EOF
+
+fi
+
+
+for ac_func in setpgid sbrk
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1439 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1461: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking for gregset_t type""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'gdb_cv_have_gregset_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1489 "configure"
+#include "confdefs.h"
+#include <sys/procfs.h>
+int main() { return 0; }
+int t() {
+gregset_t *gregsetp = 0
+; return 0; }
+EOF
+if { (eval echo configure:1497: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ gdb_cv_have_gregset_t=yes
+else
+ rm -rf conftest*
+ gdb_cv_have_gregset_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$gdb_cv_have_gregset_t" 1>&6
+if test $gdb_cv_have_gregset_t = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_GREGSET_T 1
+EOF
+
+fi
+
+echo $ac_n "checking for fpregset_t type""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'gdb_cv_have_fpregset_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1521 "configure"
+#include "confdefs.h"
+#include <sys/procfs.h>
+int main() { return 0; }
+int t() {
+fpregset_t *fpregsetp = 0
+; return 0; }
+EOF
+if { (eval echo configure:1529: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ gdb_cv_have_fpregset_t=yes
+else
+ rm -rf conftest*
+ gdb_cv_have_fpregset_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$gdb_cv_have_fpregset_t" 1>&6
+if test $gdb_cv_have_fpregset_t = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_FPREGSET_T 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for long double support in compiler""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_c_long_double'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1554 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+long double foo;
+; return 0; }
+EOF
+if { (eval echo configure:1562: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_long_double=yes
+else
+ rm -rf conftest*
+ ac_cv_c_long_double=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_c_long_double" 1>&6
+if test $ac_cv_c_long_double = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_LONG_DOUBLE 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for long double support in printf""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'gdb_cv_printf_has_long_double'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ gdb_cv_printf_has_long_double=no
+else
+cat > conftest.$ac_ext <<EOF
+#line 1590 "configure"
+#include "confdefs.h"
+
+int main () {
+ char buf[16];
+ long double f = 3.141592653;
+ sprintf (buf, "%Lg", f);
+ return (strncmp ("3.14159", buf, 7));
+}
+EOF
+{ (eval echo configure:1600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ gdb_cv_printf_has_long_double=yes
+else
+ gdb_cv_printf_has_long_double=no
+fi
+fi
+rm -fr conftest*
+fi
+
+if test $gdb_cv_printf_has_long_double = yes; then
+ cat >> confdefs.h <<\EOF
+#define PRINTF_HAS_LONG_DOUBLE 1
+EOF
+
+fi
+echo "$ac_t""$gdb_cv_printf_has_long_double" 1>&6
+
+for ac_func in valloc getpagesize
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1625 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+char $ac_func();
+
+int main() { return 0; }
+int t() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1647: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking for working mmap""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_func_mmap'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_func_mmap=no
+else
+cat > conftest.$ac_ext <<EOF
+#line 1677 "configure"
+#include "confdefs.h"
+
+/* Thanks to Mike Haertel and Jim Avera for this test. */
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#ifndef HAVE_GETPAGESIZE
+# include <sys/param.h>
+# ifdef EXEC_PAGESIZE
+# define getpagesize() EXEC_PAGESIZE
+# else
+# ifdef NBPG
+# define getpagesize() NBPG * CLSIZE
+# ifndef CLSIZE
+# define CLSIZE 1
+# endif
+# else
+# ifdef NBPC
+# define getpagesize() NBPC
+# else
+# define getpagesize() PAGESIZE /* SVR4 */
+# endif
+# endif
+# endif
+#endif
+
+#ifndef HAVE_VALLOC
+# define valloc malloc
+#endif
+
+#ifdef __cplusplus
+extern "C" { void *valloc(unsigned), *malloc(unsigned); }
+#else
+char *valloc(), *malloc();
+#endif
+
+int
+main()
+{
+ char *buf1, *buf2, *buf3;
+ int i = getpagesize(), j;
+ int i2 = i * 2;
+ int fd;
+
+ buf1 = (char *)valloc(i2);
+ buf2 = (char *)valloc(i);
+ buf3 = (char *)malloc(i2);
+ for (j = 0; j < i2; ++j)
+ *(buf1 + j) = rand();
+ fd = open("conftestmmap", O_CREAT | O_RDWR, 0666);
+ write(fd, buf1, i2);
+ mmap(buf2, i, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, fd, 0);
+ for (j = 0; j < i; ++j)
+ if (*(buf1 + j) != *(buf2 + j))
+ exit(1);
+ lseek(fd, (long)i, 0);
+ read(fd, buf2, i); /* read into mapped memory -- file should not change */
+ /* (it does in i386 SVR4.0 - Jim Avera, jima@netcom.com) */
+ lseek(fd, (long)0, 0);
+ read(fd, buf3, i2);
+ for (j = 0; j < i2; ++j)
+ if (*(buf1 + j) != *(buf3 + j))
+ exit(1);
+ exit(0);
+}
+
+EOF
+{ (eval echo configure:1746: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+ ac_cv_func_mmap=yes
+else
+ ac_cv_func_mmap=no
+fi
+fi
+rm -fr conftest*
+fi
+
+echo "$ac_t""$ac_cv_func_mmap" 1>&6
+if test $ac_cv_func_mmap = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_MMAP 1
+EOF
+
+fi
+
+
+ENABLE_CFLAGS=
+ENABLE_CLIBS=
+ENABLE_OBS=
+
+# Check whether --enable-netrom or --disable-netrom was given.
+if test "${enable_netrom+set}" = set; then
+ enableval="$enable_netrom"
+ case "${enableval}" in
+yes) enable_netrom=yes ;;
+no) enable_netrom=no ;;
+*) { echo "configure: error: bad value ${enableval} given for netrom option" 1>&2; exit 1; } ;;
+esac
+fi
+
+
+if test "${enable_netrom}" = "yes"; then
+ ENABLE_OBS="${ENABLE_OBS} remote-nrom.o"
+fi
+
+
+# Check whether --enable-sim-powerpc or --disable-sim-powerpc was given.
+if test "${enable_sim_powerpc+set}" = set; then
+ enableval="$enable_sim_powerpc"
+ case "${enableval}" in
+yes) powerpc_sim=yes ;;
+no) powerpc_sim=no ;;
+*) { echo "configure: error: bad value ${enableval} given for sim-powerpc option" 1>&2; exit 1; } ;;
+esac
+else
+ if test x"$GCC" != x""; then powerpc_sim=yes; else powerpc_sim=no; fi
+fi
+
+
+
+
+
+
+
+# target_subdir is used by the testsuite to find the target libraries.
+target_subdir=
+if test "${host}" != "${target}"; then
+ target_subdir="${target_alias}/"
+fi
+
+
+configdirs="doc testsuite"
+
+
+# Map host cpu into the config cpu subdirectory name.
+# The default is $host_cpu.
+
+case "${host_cpu}" in
+
+c[12]) gdb_host_cpu=convex ;;
+hppa*) gdb_host_cpu=pa ;;
+i[3456]86) gdb_host_cpu=i386 ;;
+m68*) gdb_host_cpu=m68k ;;
+m88*) gdb_host_cpu=m88k ;;
+np1) gdb_host_cpu=gould ;;
+pyramid) gdb_host_cpu=pyr ;;
+powerpc*) gdb_host_cpu=powerpc ;;
+sparc64) gdb_host_cpu=sparc ;;
+*) gdb_host_cpu=$host_cpu ;;
+
+esac
+
+# map host info into gdb names.
+
+case "${host}" in
+
+a29k-*-*) gdb_host=ultra3 ;;
+
+alpha-*-osf1*) gdb_host=alpha-osf1 ;;
+alpha-*-osf2*) gdb_host=alpha-osf2 ;;
+alpha-*-osf[3456789]*) gdb_host=alpha-osf3 ;;
+
+arm-*-*) gdb_host=arm ;;
+
+c[12]-*-*) gdb_host=convex ;;
+
+hppa*-*-bsd*) gdb_host=hppabsd ;;
+hppa*-*-hiux*) gdb_host=hppahpux ;;
+hppa*-*-hpux*) gdb_host=hppahpux ;;
+hppa*-*-osf*) gdb_host=hppaosf ;;
+
+i[3456]86-ncr-*) gdb_host=ncr3000 ;;
+i[3456]86-sequent-bsd*) gdb_host=symmetry ;; # dynix
+i[3456]86-sequent-sysv4*) gdb_host=ptx4 ;;
+i[3456]86-sequent-sysv*) gdb_host=ptx ;;
+i[3456]86-*-aix*) gdb_host=i386aix ;;
+i[3456]86-*-bsd*) gdb_host=i386bsd ;;
+i[3456]86-*-dgux*) gdb_host=i386dgux ;;
+i[3456]86-*-freebsd*) gdb_host=fbsd ;;
+i[3456]86-*-netbsd*) gdb_host=nbsd ;;
+i[3456]86-*-go32*) gdb_host=go32 ;;
+i[3456]86-*-linux*) gdb_host=linux ;;
+i[3456]86-*-lynxos*) gdb_host=i386lynx ;;
+i[3456]86-*-mach3*) gdb_host=i386m3 ;;
+i[3456]86-*-mach*) gdb_host=i386mach ;;
+i[3456]86-*-gnu*) gdb_host=i386gnu ;;
+i[3456]86-*-osf1mk*) gdb_host=osf1mk ;;
+i[3456]86-*-sco3.2v5*) gdb_host=i386sco5 ;;
+i[3456]86-*-sco3.2v4*) gdb_host=i386sco4 ;;
+i[3456]86-*-sco*) gdb_host=i386sco ;;
+i[3456]86-*-solaris*) gdb_host=i386sol2 ;;
+i[3456]86-*-sunos*) gdb_host=sun386 ;;
+i[3456]86-*-sysv3.2*) gdb_host=i386v32 ;;
+i[3456]86-*-sysv32*) gdb_host=i386v32 ;;
+i[3456]86-*-sysv4*) gdb_host=i386v4 ;;
+i[3456]86-*-unixware) gdb_host=i386v4 ;;
+i[3456]86-*-sysv*) gdb_host=i386v ;;
+i[3456]86-*-isc*) gdb_host=i386v32 ;;
+i[3456]86-*-os9k) gdb_host=i386os9k ;;
+i[3456]86-*-cygwin32) gdb_host=cygwin32 ;;
+m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;;
+m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;;
+m68030-sony-*) gdb_host=news1000 ;;
+
+m68*-altos-*) gdb_host=altos ;;
+m68*-apollo*-sysv*) gdb_host=apollo68v ;;
+m68*-apollo*-bsd*) gdb_host=apollo68b ;;
+m68*-att-*) gdb_host=3b1 ;;
+m68*-bull*-sysv*) gdb_host=dpx2 ;;
+m68*-hp-bsd*) gdb_host=hp300bsd ;;
+m68*-hp-hpux*) gdb_host=hp300hpux ;;
+m68*-isi-*) gdb_host=isi ;;
+m68*-*-lynxos*) gdb_host=m68klynx ;;
+m68*-*-netbsd*) gdb_host=nbsd ;;
+m68*-*-sysv4*) gdb_host=m68kv4 ;;
+m68*-motorola-*) gdb_host=delta68 ;;
+m68*-sony-*) gdb_host=news ;;
+m68*-sun-sunos3*) gdb_host=sun3os3 ;;
+m68*-sun-sunos4*) gdb_host=sun3os4 ;;
+m68*-sun-*) gdb_host=sun3os4 ;;
+
+m88*-harris-cxux*) gdb_host=cxux ;;
+m88*-motorola-sysv4*) gdb_host=delta88v4 ;;
+m88*-motorola-sysv*) gdb_host=delta88 ;;
+m88*-*-mach3*) gdb_host=mach3 ;;
+m88*-*-*) gdb_host=m88k ;;
+
+mips-dec-mach3*) gdb_host=mach3 ;;
+mips-dec-*) gdb_host=decstation ;;
+mips-little-*) gdb_host=littlemips ;;
+mips-sgi-irix3*) gdb_host=irix3 ;;
+mips-sgi-irix4*) gdb_host=irix4 ;;
+mips-sgi-irix5*) gdb_host=irix5 ;;
+mips-sony-*) gdb_host=news-mips ;;
+mips-*-mach3*) gdb_host=mach3 ;;
+mips-*-sysv4*) gdb_host=mipsv4 ;;
+mips-*-sysv*) gdb_host=riscos ;;
+mips-*-riscos*) gdb_host=riscos ;;
+
+none-*-*) gdb_host=none ;;
+
+np1-*-*) gdb_host=np1 ;;
+
+ns32k-*-mach3*) gdb_host=mach3 ;;
+ns32k-*-netbsd*) gdb_host=nbsd ;;
+ns32k-umax-*) gdb_host=umax ;;
+ns32k-utek-sysv*) gdb_host=merlin ;;
+
+powerpc-*-aix*) gdb_host=aix ;;
+powerpcle-*-cygwin32) gdb_host=cygwin32 ;;
+pn-*-*) gdb_host=pn ;;
+
+pyramid-*-*) gdb_host=pyramid ;;
+
+romp-*-*) gdb_host=rtbsd ;;
+
+rs6000-*-lynxos*) gdb_host=rs6000lynx ;;
+rs6000-*-aix4*) gdb_host=aix4 ;;
+rs6000-*-*) gdb_host=rs6000 ;;
+
+sparc-*-lynxos*) gdb_host=sparclynx ;;
+sparc-*-netbsd*) gdb_host=nbsd ;;
+sparc-*-solaris2*) gdb_host=sun4sol2 ;;
+sparc-*-sunos4*) gdb_host=sun4os4 ;;
+sparc-*-sunos5*) gdb_host=sun4sol2 ;;
+sparc-*-*) gdb_host=sun4os4 ;;
+sparc64-*-*) gdb_host=sun4sol2 ;;
+
+tahoe-*-*) gdb_host=tahoe ;;
+
+vax-*-bsd*) gdb_host=vaxbsd ;;
+vax-*-ultrix2*) gdb_host=vaxult2 ;;
+vax-*-ultrix*) gdb_host=vaxult ;;
+
+w65-*-*) gdb_host=w65 ;;
+
+esac
+
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+
+case "${target_cpu}" in
+
+alpha) gdb_target_cpu=alpha ;;
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[3456]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+m88*) gdb_target_cpu=m88k ;;
+mips*) gdb_target_cpu=mips ;;
+np1) gdb_target_cpu=gould ;;
+powerpc*) gdb_target_cpu=powerpc ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+
+esac
+
+# map target info into gdb names.
+
+case "${target}" in
+
+a29k-*-aout*) gdb_target=a29k ;;
+a29k-*-coff*) gdb_target=a29k ;;
+a29k-*-elf*) gdb_target=a29k ;;
+a29k-*-ebmon*) gdb_target=a29k ;;
+a29k-*-kern*) gdb_target=a29k-kern ;;
+a29k-*-none*) gdb_target=a29k ;;
+a29k-*-sym1*) gdb_target=ultra3 ;;
+a29k-*-udi*) gdb_target=a29k-udi ;;
+a29k-*-vxworks*) gdb_target=vx29k ;;
+
+alpha-*-osf*) gdb_target=alpha-osf1 ;;
+
+
+arm-*-*) gdb_target=arm ;;
+
+c1-*-*) gdb_target=convex ;;
+c2-*-*) gdb_target=convex ;;
+
+h8300-*-*) gdb_target=h8300 ;;
+h8500-*-*) gdb_target=h8500 ;;
+
+sh-*-*) gdb_target=sh ;;
+
+
+hppa*-*-bsd*) gdb_target=hppabsd ;;
+hppa*-*-pro*) gdb_target=hppapro ;;
+hppa*-*-hpux*) gdb_target=hppahpux ;;
+hppa*-*-hiux*) gdb_target=hppahpux ;;
+hppa*-*-osf*) gdb_target=hppaosf ;;
+
+i[3456]86-sequent-bsd*) gdb_target=symmetry ;;
+i[3456]86-sequent-sysv4*) gdb_target=ptx4 ;;
+i[3456]86-sequent-sysv*) gdb_target=ptx ;;
+i[3456]86-ncr-*) gdb_target=ncr3000 ;;
+i[3456]86-*-aout*) gdb_target=i386aout ;;
+i[3456]86-*-coff*) gdb_target=i386v ;;
+i[3456]86-*-elf*) gdb_target=i386v ;;
+i[3456]86-*-aix*) gdb_target=i386aix ;;
+i[3456]86-*-bsd*) gdb_target=i386bsd ;;
+i[3456]86-*-freebsd*) gdb_target=fbsd ;;
+i[3456]86-*-netbsd*) gdb_target=nbsd ;;
+i[3456]86-*-os9k) gdb_target=i386os9k ;;
+i[3456]86-*-go32*) gdb_target=i386aout ;;
+i[3456]86-*-lynxos*) gdb_target=i386lynx
+ configdirs="${configdirs} gdbserver" ;;
+i[3456]86-*-solaris*) gdb_target=i386sol2 ;;
+i[3456]86-*-sunos*) gdb_target=sun386 ;;
+i[3456]86-*-sysv4*) gdb_target=i386v4 ;;
+i[3456]86-*-sco*) gdb_target=i386v ;;
+i[3456]86-*-sysv*) gdb_target=i386v ;;
+i[3456]86-*-linux*) gdb_target=linux
+ configdirs="${configdirs} gdbserver" ;;
+i[3456]86-*-isc*) gdb_target=i386v ;;
+i[3456]86-*-mach3*) gdb_target=i386m3 ;;
+i[3456]86-*-mach*) gdb_target=i386mach ;;
+i[3456]86-*-gnu*) gdb_target=i386gnu ;;
+i[3456]86-*-netware*) gdb_target=i386nw
+ configdirs="${configdirs} nlm" ;;
+i[3456]86-*-osf1mk*) gdb_target=i386mk ;;
+i[3456]86-*-cygwin32) gdb_target=cygwin32 ;;
+i960-*-bout*) gdb_target=vxworks960 ;;
+i960-nindy-coff*) gdb_target=nindy960 ;;
+i960-*-coff*) gdb_target=mon960 ;;
+i960-nindy-elf*) gdb_target=nindy960 ;;
+i960-*-elf*) gdb_target=mon960 ;;
+
+i960-*-nindy*) gdb_target=nindy960 ;;
+i960-*-vxworks*) gdb_target=vxworks960 ;;
+
+m68000-*-sunos3*) gdb_target=sun2os3 ;;
+m68000-*-sunos4*) gdb_target=sun2os4 ;;
+
+m68*-apollo*-bsd*) gdb_target=apollo68b ;;
+m68*-bull-sysv*) gdb_target=dpx2 ;;
+m68*-hp-bsd*) gdb_target=hp300bsd ;;
+m68*-hp-hpux*) gdb_target=hp300hpux ;;
+m68*-altos-*) gdb_target=altos ;;
+m68*-att-*) gdb_target=3b1 ;;
+m68*-cisco*-*) gdb_target=cisco ;;
+m68*-ericsson-*) gdb_target=es1800 ;;
+m68*-isi-*) gdb_target=isi ;;
+m68*-motorola-*) gdb_target=delta68 ;;
+m68*-netx-*) gdb_target=vxworks68 ;;
+m68*-sony-*) gdb_target=news ;;
+m68*-tandem-*) gdb_target=st2000 ;;
+m68*-rom68k-*) gdb_target=monitor ;;
+m68*-*bug-*) gdb_target=monitor ;;
+m68*-monitor-*) gdb_target=monitor ;;
+m68*-est-*) gdb_target=monitor ;;
+m68*-*-aout*) gdb_target=monitor ;;
+m68*-*-coff*) gdb_target=monitor ;;
+m68*-*-elf*) gdb_target=monitor ;;
+m68*-*-lynxos*) gdb_target=m68klynx
+ configdirs="${configdirs} gdbserver" ;;
+m68*-*-netbsd*) gdb_target=nbsd ;;
+m68*-*-os68k*) gdb_target=os68k ;;
+m68*-*-sunos3*) gdb_target=sun3os3 ;;
+m68*-*-sunos4*) gdb_target=sun3os4 ;;
+m68*-*-sysv4*) gdb_target=m68kv4 ;;
+m68*-*-vxworks*) gdb_target=vxworks68 ;;
+
+m88*-harris-cxux*) gdb_target=cxux ;;
+m88*-motorola-sysv4*) gdb_target=delta88v4 ;;
+m88*-*-mach3*) gdb_target=mach3 ;;
+m88*-motorola-*) gdb_target=delta88 ;;
+m88*-*-*) gdb_target=m88k ;;
+
+mips64*-big-*) gdb_target=bigmips64 ;;
+mips*-big-*) gdb_target=bigmips ;;
+mips*-dec-mach3*) gdb_target=mach3 ;;
+mips*-dec-*) gdb_target=decstation ;;
+mips64*el-*-ecoff*) gdb_target=embedl64 ;;
+mips64*-*-ecoff*) gdb_target=embed64 ;;
+mips64*vr4300*el-*-elf*) gdb_target=vr4300el ;;
+mips64*vr4300*-*-elf*) gdb_target=vr4300 ;;
+mips64*el-*-elf*) gdb_target=embedl64 ;;
+mips64*-*-elf*) gdb_target=embed64 ;;
+mips*el-*-ecoff*) gdb_target=embedl ;;
+mips*-*-ecoff*) gdb_target=embed ;;
+mips*el-*-elf*) gdb_target=embedl ;;
+mips*-*-elf*) gdb_target=embed ;;
+mips*-little-*) gdb_target=littlemips ;;
+mips*-sgi-irix5*) gdb_target=irix5 ;;
+mips*-sgi-*) gdb_target=irix3 ;;
+mips*-sony-*) gdb_target=bigmips ;;
+mips*-*-mach3*) gdb_target=mach3 ;;
+mips*-*-sysv4*) gdb_target=mipsv4 ;;
+mips*-*-sysv*) gdb_target=bigmips ;;
+mips*-*-riscos*) gdb_target=bigmips ;;
+mips*-*-vxworks*) gdb_target=vxmips ;;
+
+none-*-*) gdb_target=none ;;
+
+np1-*-*) gdb_target=np1 ;;
+
+ns32k-*-mach3*) gdb_target=mach3 ;;
+ns32k-*-netbsd*) gdb_target=nbsd ;;
+ns32k-utek-sysv*) gdb_target=merlin ;;
+ns32k-utek-*) gdb_target=umax ;;
+
+pn-*-*) gdb_target=pn ;;
+powerpc-*-macos*) gdb_target=macos ;;
+powerpc-*-netware*) gdb_target=ppc-nw
+ configdirs="${configdirs} nlm" ;;
+
+powerpc-*-aix4*) gdb_target=aix4 ;;
+powerpc-*-aix*) gdb_target=aix ;;
+powerpcle-*-cygwin32) gdb_target=cygwin32 ;;
+powerpc-*-eabi*) if test x"$powerpc_sim" = x"yes"; then
+ gdb_target=ppc-sim
+ else
+ gdb_target=ppc-eabi
+ fi ;;
+powerpcle-*-eabi*) if test x"$powerpc_sim" = x"yes"; then
+ gdb_target=ppcle-sim
+ else
+ gdb_target=ppcle-eabi
+ fi ;;
+
+pyramid-*-*) gdb_target=pyramid ;;
+
+rs6000-*-lynxos*) gdb_target=rs6000lynx ;;
+rs6000-*-aix4*) gdb_target=aix4 ;;
+rs6000-*-*) gdb_target=rs6000 ;;
+
+sparc-*-aout*) gdb_target=sparc-em ;;
+sparc-*-coff*) gdb_target=sparc-em ;;
+sparc-*-elf*) gdb_target=sparc-em ;;
+sparc-*-lynxos*) gdb_target=sparclynx
+ configdirs="${configdirs} gdbserver" ;;
+sparc-*-netbsd*) gdb_target=nbsd ;;
+sparc-*-solaris2*) gdb_target=sun4sol2 ;;
+sparc-*-sunos4*) gdb_target=sun4os4 ;;
+sparc-*-sunos5*) gdb_target=sun4sol2 ;;
+sparc-*-vxworks*) gdb_target=vxsparc ;;
+sparc-*-*) gdb_target=sun4os4 ;;
+# Use sparc-em for sparclet for now.
+sparclet-*-*) gdb_target=sparc-em ;;
+sparclite*-*-*) gdb_target=sparclite ;;
+sparc64-*-solaris2*) gdb_target=sp64sol2 ;;
+sparc64-*-*) gdb_target=sp64 ;;
+
+tahoe-*-*) gdb_target=tahoe ;;
+
+vax-*-*) gdb_target=vax ;;
+
+w65-*-*) gdb_target=w65 ;;
+
+z8k-*-coff*) gdb_target=z8k ;;
+
+esac
+
+
+frags=
+host_makefile_frag=${srcdir}/config/${gdb_host_cpu}/${gdb_host}.mh
+if test ! -f ${host_makefile_frag}; then
+{ echo "configure: error: "*** Gdb does not support host ${host}"" 1>&2; exit 1; }
+fi
+frags="$frags $host_makefile_frag"
+
+target_makefile_frag=${srcdir}/config/${gdb_target_cpu}/${gdb_target}.mt
+if test ! -f ${target_makefile_frag}; then
+{ echo "configure: error: "*** Gdb does not support target ${target}"" 1>&2; exit 1; }
+fi
+frags="$frags $target_makefile_frag"
+
+
+
+
+
+hostfile=`sed -n '
+s/XM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+
+targetfile=`sed -n '
+s/TM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${target_makefile_frag}`
+
+# these really aren't orthogonal true/false values of the same condition,
+# but shells are slow enough that I like to reuse the test conditions
+# whenever possible
+if test "${target}" = "${host}"; then
+nativefile=`sed -n '
+s/NAT_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+else
+# GDBserver is only useful in a "native" enviroment
+configdirs=`echo $configdirs | sed 's/gdbserver//'`
+fi
+
+
+# If hostfile (XM_FILE) and/or targetfile (TM_FILE) and/or nativefile
+# (NAT_FILE) is not set in config/*/*.m[ht] files, we don't make the
+# corresponding links. But we have to remove the xm.h files and tm.h
+# files anyway, e.g. when switching from "configure host" to
+# "configure none".
+
+files=
+links=
+rm -f xm.h
+if test "${hostfile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${hostfile}"
+links="${links} xm.h"
+fi
+rm -f tm.h
+if test "${targetfile}" != ""; then
+files="${files} config/${gdb_target_cpu}/${targetfile}"
+links="${links} tm.h"
+fi
+rm -f nm.h
+if test "${nativefile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${nativefile}"
+links="${links} nm.h"
+else
+# A cross-only configuration.
+files="${files} config/nm-empty.h"
+links="${links} nm.h"
+fi
+
+
+
+subdirs="$configdirs"
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+ >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.8"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile config.h:config.in" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@AR@%$AR%g
+s%@RANLIB@%$RANLIB%g
+s%@YACC@%$YACC%g
+s%@AWK@%$AWK%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@X_CFLAGS@%$X_CFLAGS%g
+s%@X_PRE_LIBS@%$X_PRE_LIBS%g
+s%@X_LIBS@%$X_LIBS%g
+s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g
+s%@TCLHDIR@%$TCLHDIR%g
+s%@TCLLIB@%$TCLLIB%g
+s%@TKHDIR@%$TKHDIR%g
+s%@TKLIB@%$TKLIB%g
+s%@ENABLE_GDBTK@%$ENABLE_GDBTK%g
+s%@X_LDFLAGS@%$X_LDFLAGS%g
+s%@ENABLE_CFLAGS@%$ENABLE_CFLAGS%g
+s%@ENABLE_CLIBS@%$ENABLE_CLIBS%g
+s%@ENABLE_OBS@%$ENABLE_OBS%g
+s%@target_subdir@%$target_subdir%g
+/@host_makefile_frag@/r $host_makefile_frag
+s%@host_makefile_frag@%%g
+/@target_makefile_frag@/r $target_makefile_frag
+s%@target_makefile_frag@%%g
+s%@frags@%$frags%g
+s%@subdirs@%$subdirs%g
+
+CEOF
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust relative srcdir, etc. for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+fi; done
+rm -f conftest.subs
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+CONFIG_HEADERS=${CONFIG_HEADERS-"config.h:config.in"}
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ cp $ac_given_srcdir/$ac_file_in conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+# Maximum number of lines to put in a single here document.
+ac_max_here_lines=12
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+ac_sources="$files"
+ac_dests="$links"
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+srcdir=$ac_given_srcdir
+while test -n "$ac_sources"; do
+ set $ac_dests; ac_dest=$1; shift; ac_dests=$*
+ set $ac_sources; ac_source=$1; shift; ac_sources=$*
+
+ echo "linking $srcdir/$ac_source to $ac_dest"
+
+ if test ! -r $srcdir/$ac_source; then
+ { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; }
+ fi
+ rm -f $ac_dest
+
+ # Make relative symlinks.
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then
+ # The dest file is in a subdirectory.
+ test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir"
+ ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dest_dir_suffix.
+ ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dest_dir_suffix= ac_dots=
+ fi
+
+ case "$srcdir" in
+ [/$]*) ac_rel_source="$srcdir/$ac_source" ;;
+ *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;;
+ esac
+
+ # Make a symlink if possible; otherwise try a hard link.
+ if ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+ ln $srcdir/$ac_source $ac_dest; then :
+ else
+ { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; }
+ fi
+done
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+gdb_host_cpu=$gdb_host_cpu
+gdb_target_cpu=$gdb_target_cpu
+nativefile=$nativefile
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+if test "${nativefile}" = ""; then
+sed -e '/^NATDEPFILES= /s//# NATDEPFILES= /' \
+ < Makefile > Makefile.tem
+mv -f Makefile.tem Makefile
+fi
+
+sed -e '/^TM_FILE[ ]*=/s,^TM_FILE[ ]*=[ ]*,&config/'"${gdb_target_cpu}"'/,
+/^XM_FILE[ ]*=/s,^XM_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,
+/^NAT_FILE[ ]*=/s,^NAT_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,' <Makefile >Makefile.tmp
+mv -f Makefile.tmp Makefile
+
+case ${srcdir} in
+.)
+;;
+*)
+grep "source ${srcdir}/.gdbinit" .gdbinit >/dev/null 2>/dev/null || \
+echo "source ${srcdir}/.gdbinit" >> .gdbinit
+esac
+
+case x$CONFIG_HEADERS in
+xconfig.h:config.in)
+echo > stamp-h ;;
+esac
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+if test "$no_recursion" != yes; then
+
+ # Remove --cache-file and --srcdir arguments so they do not pile up.
+ ac_sub_configure_args=
+ ac_prev=
+ for ac_arg in $ac_configure_args; do
+ if test -n "$ac_prev"; then
+ ac_prev=
+ continue
+ fi
+ case "$ac_arg" in
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ ;;
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ ;;
+ *) ac_sub_configure_args="$ac_sub_configure_args $ac_arg" ;;
+ esac
+ done
+
+ for ac_config_dir in $configdirs; do
+
+ # Do not complain, so a configure script can configure whichever
+ # parts of a large source tree are present.
+ if test ! -d $srcdir/$ac_config_dir; then
+ continue
+ fi
+
+ echo configuring in $ac_config_dir
+
+ case "$srcdir" in
+ .) ;;
+ *)
+ if test -d ./$ac_config_dir || mkdir ./$ac_config_dir; then :;
+ else
+ { echo "configure: error: can not create `pwd`/$ac_config_dir" 1>&2; exit 1; }
+ fi
+ ;;
+ esac
+
+ ac_popdir=`pwd`
+ cd $ac_config_dir
+
+ case "$srcdir" in
+ .) # No --srcdir option. We are building in place.
+ ac_sub_srcdir=$srcdir ;;
+ /*) # Absolute path.
+ ac_sub_srcdir=$srcdir/$ac_config_dir ;;
+ *) # Relative path.
+ ac_sub_srcdir=../$srcdir/$ac_config_dir ;;
+ esac
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_sub_srcdir/configure; then
+ ac_sub_configure=$ac_sub_srcdir/configure
+ elif test -f $ac_sub_srcdir/configure.in; then
+ ac_sub_configure=$ac_configure
+ else
+ echo "configure: warning: no configuration information is in $ac_config_dir" 1>&2
+ ac_sub_configure=
+ fi
+
+ # The recursion is here.
+ if test -n "$ac_sub_configure"; then
+
+ # Make the cache file name correct relative to the subdirectory.
+ # A "../" for each directory in /$ac_config_dir.
+ ac_dots=`echo $ac_config_dir|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'`
+ case "$cache_file" in
+ /*) ac_sub_cache_file=$cache_file ;;
+ *) # Relative path.
+ ac_sub_cache_file="$ac_dots$cache_file" ;;
+ esac
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo "running ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir"
+ # The eval makes quoting arguments work.
+ if eval ${CONFIG_SHELL-/bin/sh} $ac_sub_configure $ac_sub_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_sub_srcdir
+ then :
+ else
+ { echo "configure: error: $ac_sub_configure failed for $ac_config_dir" 1>&2; exit 1; }
+ fi
+ fi
+
+ cd $ac_popdir
+ done
+fi
+
+
+exit 0
+
diff --git a/contrib/gdb/gdb/configure.in b/contrib/gdb/gdb/configure.in
new file mode 100644
index 0000000..0967fd1
--- /dev/null
+++ b/contrib/gdb/gdb/configure.in
@@ -0,0 +1,615 @@
+dnl Autoconf configure script for GDB, the GNU debugger.
+dnl Copyright 1995, 1996 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GDB.
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.3)dnl
+AC_INIT(main.c)
+AC_CONFIG_HEADER(config.h:config.in)
+
+AC_PROG_CC
+AC_AIX
+AC_MINIX
+AC_ISC_POSIX
+
+AC_PROG_INSTALL
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_PROG_YACC
+AC_PROG_AWK
+
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/..)
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+AC_HEADER_STDC
+AC_CHECK_HEADERS(limits.h memory.h string.h strings.h unistd.h termios.h termio.h sgtty.h stddef.h sys/procfs.h link.h endian.h)
+AC_HEADER_STAT
+
+AC_CHECK_FUNCS(setpgid sbrk)
+
+AC_MSG_CHECKING([for gregset_t type])
+AC_CACHE_VAL(gdb_cv_have_gregset_t,
+[AC_TRY_LINK([#include <sys/procfs.h>],[gregset_t *gregsetp = 0],
+gdb_cv_have_gregset_t=yes, gdb_cv_have_gregset_t=no)])
+AC_MSG_RESULT($gdb_cv_have_gregset_t)
+if test $gdb_cv_have_gregset_t = yes; then
+ AC_DEFINE(HAVE_GREGSET_T)
+fi
+
+AC_MSG_CHECKING([for fpregset_t type])
+AC_CACHE_VAL(gdb_cv_have_fpregset_t,
+[AC_TRY_LINK([#include <sys/procfs.h>],[fpregset_t *fpregsetp = 0],
+gdb_cv_have_fpregset_t=yes, gdb_cv_have_fpregset_t=no)])
+AC_MSG_RESULT($gdb_cv_have_fpregset_t)
+if test $gdb_cv_have_fpregset_t = yes; then
+ AC_DEFINE(HAVE_FPREGSET_T)
+fi
+
+dnl See if compiler supports "long double" type. Can't use AC_C_LONG_DOUBLE
+dnl because autoconf complains about cross-compilation issues. However, this
+dnl code uses the same variables as the macro for compatibility.
+
+AC_MSG_CHECKING(for long double support in compiler)
+AC_CACHE_VAL(ac_cv_c_long_double,
+[AC_TRY_COMPILE(, [long double foo;],
+ac_cv_c_long_double=yes, ac_cv_c_long_double=no)])
+AC_MSG_RESULT($ac_cv_c_long_double)
+if test $ac_cv_c_long_double = yes; then
+ AC_DEFINE(HAVE_LONG_DOUBLE)
+fi
+
+dnl See if the compiler and runtime support printing long doubles
+
+AC_MSG_CHECKING(for long double support in printf)
+AC_CACHE_VAL(gdb_cv_printf_has_long_double,
+[AC_TRY_RUN([
+int main () {
+ char buf[16];
+ long double f = 3.141592653;
+ sprintf (buf, "%Lg", f);
+ return (strncmp ("3.14159", buf, 7));
+}],
+gdb_cv_printf_has_long_double=yes,
+gdb_cv_printf_has_long_double=no,
+gdb_cv_printf_has_long_double=no)])
+if test $gdb_cv_printf_has_long_double = yes; then
+ AC_DEFINE(PRINTF_HAS_LONG_DOUBLE)
+fi
+AC_MSG_RESULT($gdb_cv_printf_has_long_double)
+
+AC_FUNC_MMAP
+
+dnl Handle optional features that can be enabled.
+ENABLE_CFLAGS=
+ENABLE_CLIBS=
+ENABLE_OBS=
+
+AC_ARG_ENABLE(netrom,
+[ --enable-netrom ],
+[case "${enableval}" in
+yes) enable_netrom=yes ;;
+no) enable_netrom=no ;;
+*) AC_MSG_ERROR(bad value ${enableval} given for netrom option) ;;
+esac])
+
+if test "${enable_netrom}" = "yes"; then
+ ENABLE_OBS="${ENABLE_OBS} remote-nrom.o"
+fi
+
+
+AC_ARG_ENABLE(sim-powerpc,
+[ --enable-sim-powerpc ],
+[case "${enableval}" in
+yes) powerpc_sim=yes ;;
+no) powerpc_sim=no ;;
+*) AC_MSG_ERROR(bad value ${enableval} given for sim-powerpc option) ;;
+esac],[if test x"$GCC" != x""; then powerpc_sim=yes; else powerpc_sim=no; fi])
+
+
+AC_SUBST(ENABLE_CFLAGS)
+AC_SUBST(ENABLE_CLIBS)
+AC_SUBST(ENABLE_OBS)
+
+# target_subdir is used by the testsuite to find the target libraries.
+target_subdir=
+if test "${host}" != "${target}"; then
+ target_subdir="${target_alias}/"
+fi
+AC_SUBST(target_subdir)
+
+configdirs="doc testsuite"
+
+dnl
+changequote(,)dnl
+
+# Map host cpu into the config cpu subdirectory name.
+# The default is $host_cpu.
+
+case "${host_cpu}" in
+
+c[12]) gdb_host_cpu=convex ;;
+hppa*) gdb_host_cpu=pa ;;
+i[3456]86) gdb_host_cpu=i386 ;;
+m68*) gdb_host_cpu=m68k ;;
+m88*) gdb_host_cpu=m88k ;;
+np1) gdb_host_cpu=gould ;;
+pyramid) gdb_host_cpu=pyr ;;
+powerpc*) gdb_host_cpu=powerpc ;;
+sparc64) gdb_host_cpu=sparc ;;
+*) gdb_host_cpu=$host_cpu ;;
+
+esac
+
+# map host info into gdb names.
+
+case "${host}" in
+
+a29k-*-*) gdb_host=ultra3 ;;
+
+alpha-*-osf1*) gdb_host=alpha-osf1 ;;
+alpha-*-osf2*) gdb_host=alpha-osf2 ;;
+alpha-*-osf[3456789]*) gdb_host=alpha-osf3 ;;
+
+arm-*-*) gdb_host=arm ;;
+
+c[12]-*-*) gdb_host=convex ;;
+
+hppa*-*-bsd*) gdb_host=hppabsd ;;
+hppa*-*-hiux*) gdb_host=hppahpux ;;
+hppa*-*-hpux*) gdb_host=hppahpux ;;
+hppa*-*-osf*) gdb_host=hppaosf ;;
+
+i[3456]86-ncr-*) gdb_host=ncr3000 ;;
+i[3456]86-sequent-bsd*) gdb_host=symmetry ;; # dynix
+i[3456]86-sequent-sysv4*) gdb_host=ptx4 ;;
+i[3456]86-sequent-sysv*) gdb_host=ptx ;;
+i[3456]86-*-aix*) gdb_host=i386aix ;;
+i[3456]86-*-bsd*) gdb_host=i386bsd ;;
+i[3456]86-*-dgux*) gdb_host=i386dgux ;;
+i[3456]86-*-freebsd*) gdb_host=fbsd ;;
+i[3456]86-*-netbsd*) gdb_host=nbsd ;;
+i[3456]86-*-go32*) gdb_host=go32 ;;
+i[3456]86-*-linux*) gdb_host=linux ;;
+i[3456]86-*-lynxos*) gdb_host=i386lynx ;;
+i[3456]86-*-mach3*) gdb_host=i386m3 ;;
+i[3456]86-*-mach*) gdb_host=i386mach ;;
+i[3456]86-*-gnu*) gdb_host=i386gnu ;;
+i[3456]86-*-osf1mk*) gdb_host=osf1mk ;;
+i[3456]86-*-sco3.2v5*) gdb_host=i386sco5 ;;
+i[3456]86-*-sco3.2v4*) gdb_host=i386sco4 ;;
+i[3456]86-*-sco*) gdb_host=i386sco ;;
+i[3456]86-*-solaris*) gdb_host=i386sol2 ;;
+i[3456]86-*-sunos*) gdb_host=sun386 ;;
+i[3456]86-*-sysv3.2*) gdb_host=i386v32 ;;
+i[3456]86-*-sysv32*) gdb_host=i386v32 ;;
+i[3456]86-*-sysv4*) gdb_host=i386v4 ;;
+i[3456]86-*-unixware) gdb_host=i386v4 ;;
+i[3456]86-*-sysv*) gdb_host=i386v ;;
+i[3456]86-*-isc*) gdb_host=i386v32 ;;
+i[3456]86-*-os9k) gdb_host=i386os9k ;;
+i[3456]86-*-cygwin32) gdb_host=cygwin32 ;;
+m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;;
+m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;;
+m68030-sony-*) gdb_host=news1000 ;;
+
+m68*-altos-*) gdb_host=altos ;;
+m68*-apollo*-sysv*) gdb_host=apollo68v ;;
+m68*-apollo*-bsd*) gdb_host=apollo68b ;;
+m68*-att-*) gdb_host=3b1 ;;
+m68*-bull*-sysv*) gdb_host=dpx2 ;;
+m68*-hp-bsd*) gdb_host=hp300bsd ;;
+m68*-hp-hpux*) gdb_host=hp300hpux ;;
+m68*-isi-*) gdb_host=isi ;;
+m68*-*-lynxos*) gdb_host=m68klynx ;;
+m68*-*-netbsd*) gdb_host=nbsd ;;
+m68*-*-sysv4*) gdb_host=m68kv4 ;;
+m68*-motorola-*) gdb_host=delta68 ;;
+m68*-sony-*) gdb_host=news ;;
+m68*-sun-sunos3*) gdb_host=sun3os3 ;;
+m68*-sun-sunos4*) gdb_host=sun3os4 ;;
+m68*-sun-*) gdb_host=sun3os4 ;;
+
+m88*-harris-cxux*) gdb_host=cxux ;;
+m88*-motorola-sysv4*) gdb_host=delta88v4 ;;
+m88*-motorola-sysv*) gdb_host=delta88 ;;
+m88*-*-mach3*) gdb_host=mach3 ;;
+m88*-*-*) gdb_host=m88k ;;
+
+mips-dec-mach3*) gdb_host=mach3 ;;
+mips-dec-*) gdb_host=decstation ;;
+mips-little-*) gdb_host=littlemips ;;
+mips-sgi-irix3*) gdb_host=irix3 ;;
+mips-sgi-irix4*) gdb_host=irix4 ;;
+mips-sgi-irix5*) gdb_host=irix5 ;;
+mips-sony-*) gdb_host=news-mips ;;
+mips-*-mach3*) gdb_host=mach3 ;;
+mips-*-sysv4*) gdb_host=mipsv4 ;;
+mips-*-sysv*) gdb_host=riscos ;;
+mips-*-riscos*) gdb_host=riscos ;;
+
+none-*-*) gdb_host=none ;;
+
+np1-*-*) gdb_host=np1 ;;
+
+ns32k-*-mach3*) gdb_host=mach3 ;;
+ns32k-*-netbsd*) gdb_host=nbsd ;;
+ns32k-umax-*) gdb_host=umax ;;
+ns32k-utek-sysv*) gdb_host=merlin ;;
+
+powerpc-*-aix*) gdb_host=aix ;;
+powerpcle-*-cygwin32) gdb_host=cygwin32 ;;
+pn-*-*) gdb_host=pn ;;
+
+pyramid-*-*) gdb_host=pyramid ;;
+
+romp-*-*) gdb_host=rtbsd ;;
+
+rs6000-*-lynxos*) gdb_host=rs6000lynx ;;
+rs6000-*-aix4*) gdb_host=aix4 ;;
+rs6000-*-*) gdb_host=rs6000 ;;
+
+sparc-*-lynxos*) gdb_host=sparclynx ;;
+sparc-*-netbsd*) gdb_host=nbsd ;;
+sparc-*-solaris2*) gdb_host=sun4sol2 ;;
+sparc-*-sunos4*) gdb_host=sun4os4 ;;
+sparc-*-sunos5*) gdb_host=sun4sol2 ;;
+sparc-*-*) gdb_host=sun4os4 ;;
+sparc64-*-*) gdb_host=sun4sol2 ;;
+
+tahoe-*-*) gdb_host=tahoe ;;
+
+vax-*-bsd*) gdb_host=vaxbsd ;;
+vax-*-ultrix2*) gdb_host=vaxult2 ;;
+vax-*-ultrix*) gdb_host=vaxult ;;
+
+w65-*-*) gdb_host=w65 ;;
+
+esac
+
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+
+case "${target_cpu}" in
+
+alpha) gdb_target_cpu=alpha ;;
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[3456]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+m88*) gdb_target_cpu=m88k ;;
+mips*) gdb_target_cpu=mips ;;
+np1) gdb_target_cpu=gould ;;
+powerpc*) gdb_target_cpu=powerpc ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+
+esac
+
+# map target info into gdb names.
+
+case "${target}" in
+
+a29k-*-aout*) gdb_target=a29k ;;
+a29k-*-coff*) gdb_target=a29k ;;
+a29k-*-elf*) gdb_target=a29k ;;
+a29k-*-ebmon*) gdb_target=a29k ;;
+a29k-*-kern*) gdb_target=a29k-kern ;;
+a29k-*-none*) gdb_target=a29k ;;
+a29k-*-sym1*) gdb_target=ultra3 ;;
+a29k-*-udi*) gdb_target=a29k-udi ;;
+a29k-*-vxworks*) gdb_target=vx29k ;;
+
+alpha-*-osf*) gdb_target=alpha-osf1 ;;
+
+
+arm-*-*) gdb_target=arm ;;
+
+c1-*-*) gdb_target=convex ;;
+c2-*-*) gdb_target=convex ;;
+
+h8300-*-*) gdb_target=h8300 ;;
+h8500-*-*) gdb_target=h8500 ;;
+
+sh-*-*) gdb_target=sh ;;
+
+
+hppa*-*-bsd*) gdb_target=hppabsd ;;
+hppa*-*-pro*) gdb_target=hppapro ;;
+hppa*-*-hpux*) gdb_target=hppahpux ;;
+hppa*-*-hiux*) gdb_target=hppahpux ;;
+hppa*-*-osf*) gdb_target=hppaosf ;;
+
+i[3456]86-sequent-bsd*) gdb_target=symmetry ;;
+i[3456]86-sequent-sysv4*) gdb_target=ptx4 ;;
+i[3456]86-sequent-sysv*) gdb_target=ptx ;;
+i[3456]86-ncr-*) gdb_target=ncr3000 ;;
+i[3456]86-*-aout*) gdb_target=i386aout ;;
+i[3456]86-*-coff*) gdb_target=i386v ;;
+i[3456]86-*-elf*) gdb_target=i386v ;;
+i[3456]86-*-aix*) gdb_target=i386aix ;;
+i[3456]86-*-bsd*) gdb_target=i386bsd ;;
+i[3456]86-*-freebsd*) gdb_target=fbsd ;;
+i[3456]86-*-netbsd*) gdb_target=nbsd ;;
+i[3456]86-*-os9k) gdb_target=i386os9k ;;
+i[3456]86-*-go32*) gdb_target=i386aout ;;
+i[3456]86-*-lynxos*) gdb_target=i386lynx
+ configdirs="${configdirs} gdbserver" ;;
+i[3456]86-*-solaris*) gdb_target=i386sol2 ;;
+i[3456]86-*-sunos*) gdb_target=sun386 ;;
+i[3456]86-*-sysv4*) gdb_target=i386v4 ;;
+i[3456]86-*-sco*) gdb_target=i386v ;;
+i[3456]86-*-sysv*) gdb_target=i386v ;;
+i[3456]86-*-linux*) gdb_target=linux
+ configdirs="${configdirs} gdbserver" ;;
+i[3456]86-*-isc*) gdb_target=i386v ;;
+i[3456]86-*-mach3*) gdb_target=i386m3 ;;
+i[3456]86-*-mach*) gdb_target=i386mach ;;
+i[3456]86-*-gnu*) gdb_target=i386gnu ;;
+i[3456]86-*-netware*) gdb_target=i386nw
+ configdirs="${configdirs} nlm" ;;
+i[3456]86-*-osf1mk*) gdb_target=i386mk ;;
+i[3456]86-*-cygwin32) gdb_target=cygwin32 ;;
+i960-*-bout*) gdb_target=vxworks960 ;;
+i960-nindy-coff*) gdb_target=nindy960 ;;
+i960-*-coff*) gdb_target=mon960 ;;
+i960-nindy-elf*) gdb_target=nindy960 ;;
+i960-*-elf*) gdb_target=mon960 ;;
+
+i960-*-nindy*) gdb_target=nindy960 ;;
+i960-*-vxworks*) gdb_target=vxworks960 ;;
+
+m68000-*-sunos3*) gdb_target=sun2os3 ;;
+m68000-*-sunos4*) gdb_target=sun2os4 ;;
+
+m68*-apollo*-bsd*) gdb_target=apollo68b ;;
+m68*-bull-sysv*) gdb_target=dpx2 ;;
+m68*-hp-bsd*) gdb_target=hp300bsd ;;
+m68*-hp-hpux*) gdb_target=hp300hpux ;;
+m68*-altos-*) gdb_target=altos ;;
+m68*-att-*) gdb_target=3b1 ;;
+m68*-cisco*-*) gdb_target=cisco ;;
+m68*-ericsson-*) gdb_target=es1800 ;;
+m68*-isi-*) gdb_target=isi ;;
+m68*-motorola-*) gdb_target=delta68 ;;
+m68*-netx-*) gdb_target=vxworks68 ;;
+m68*-sony-*) gdb_target=news ;;
+m68*-tandem-*) gdb_target=st2000 ;;
+m68*-rom68k-*) gdb_target=monitor ;;
+m68*-*bug-*) gdb_target=monitor ;;
+m68*-monitor-*) gdb_target=monitor ;;
+m68*-est-*) gdb_target=monitor ;;
+m68*-*-aout*) gdb_target=monitor ;;
+m68*-*-coff*) gdb_target=monitor ;;
+m68*-*-elf*) gdb_target=monitor ;;
+m68*-*-lynxos*) gdb_target=m68klynx
+ configdirs="${configdirs} gdbserver" ;;
+m68*-*-netbsd*) gdb_target=nbsd ;;
+m68*-*-os68k*) gdb_target=os68k ;;
+m68*-*-sunos3*) gdb_target=sun3os3 ;;
+m68*-*-sunos4*) gdb_target=sun3os4 ;;
+m68*-*-sysv4*) gdb_target=m68kv4 ;;
+m68*-*-vxworks*) gdb_target=vxworks68 ;;
+
+m88*-harris-cxux*) gdb_target=cxux ;;
+m88*-motorola-sysv4*) gdb_target=delta88v4 ;;
+m88*-*-mach3*) gdb_target=mach3 ;;
+m88*-motorola-*) gdb_target=delta88 ;;
+m88*-*-*) gdb_target=m88k ;;
+
+mips64*-big-*) gdb_target=bigmips64 ;;
+mips*-big-*) gdb_target=bigmips ;;
+mips*-dec-mach3*) gdb_target=mach3 ;;
+mips*-dec-*) gdb_target=decstation ;;
+mips64*el-*-ecoff*) gdb_target=embedl64 ;;
+mips64*-*-ecoff*) gdb_target=embed64 ;;
+mips64*vr4300*el-*-elf*) gdb_target=vr4300el ;;
+mips64*vr4300*-*-elf*) gdb_target=vr4300 ;;
+mips64*el-*-elf*) gdb_target=embedl64 ;;
+mips64*-*-elf*) gdb_target=embed64 ;;
+mips*el-*-ecoff*) gdb_target=embedl ;;
+mips*-*-ecoff*) gdb_target=embed ;;
+mips*el-*-elf*) gdb_target=embedl ;;
+mips*-*-elf*) gdb_target=embed ;;
+mips*-little-*) gdb_target=littlemips ;;
+mips*-sgi-irix5*) gdb_target=irix5 ;;
+mips*-sgi-*) gdb_target=irix3 ;;
+mips*-sony-*) gdb_target=bigmips ;;
+mips*-*-mach3*) gdb_target=mach3 ;;
+mips*-*-sysv4*) gdb_target=mipsv4 ;;
+mips*-*-sysv*) gdb_target=bigmips ;;
+mips*-*-riscos*) gdb_target=bigmips ;;
+mips*-*-vxworks*) gdb_target=vxmips ;;
+
+none-*-*) gdb_target=none ;;
+
+np1-*-*) gdb_target=np1 ;;
+
+ns32k-*-mach3*) gdb_target=mach3 ;;
+ns32k-*-netbsd*) gdb_target=nbsd ;;
+ns32k-utek-sysv*) gdb_target=merlin ;;
+ns32k-utek-*) gdb_target=umax ;;
+
+pn-*-*) gdb_target=pn ;;
+powerpc-*-macos*) gdb_target=macos ;;
+powerpc-*-netware*) gdb_target=ppc-nw
+ configdirs="${configdirs} nlm" ;;
+
+powerpc-*-aix4*) gdb_target=aix4 ;;
+powerpc-*-aix*) gdb_target=aix ;;
+powerpcle-*-cygwin32) gdb_target=cygwin32 ;;
+powerpc-*-eabi*) if test x"$powerpc_sim" = x"yes"; then
+ gdb_target=ppc-sim
+ else
+ gdb_target=ppc-eabi
+ fi ;;
+powerpcle-*-eabi*) if test x"$powerpc_sim" = x"yes"; then
+ gdb_target=ppcle-sim
+ else
+ gdb_target=ppcle-eabi
+ fi ;;
+
+pyramid-*-*) gdb_target=pyramid ;;
+
+rs6000-*-lynxos*) gdb_target=rs6000lynx ;;
+rs6000-*-aix4*) gdb_target=aix4 ;;
+rs6000-*-*) gdb_target=rs6000 ;;
+
+sparc-*-aout*) gdb_target=sparc-em ;;
+sparc-*-coff*) gdb_target=sparc-em ;;
+sparc-*-elf*) gdb_target=sparc-em ;;
+sparc-*-lynxos*) gdb_target=sparclynx
+ configdirs="${configdirs} gdbserver" ;;
+sparc-*-netbsd*) gdb_target=nbsd ;;
+sparc-*-solaris2*) gdb_target=sun4sol2 ;;
+sparc-*-sunos4*) gdb_target=sun4os4 ;;
+sparc-*-sunos5*) gdb_target=sun4sol2 ;;
+sparc-*-vxworks*) gdb_target=vxsparc ;;
+sparc-*-*) gdb_target=sun4os4 ;;
+# Use sparc-em for sparclet for now.
+sparclet-*-*) gdb_target=sparc-em ;;
+sparclite*-*-*) gdb_target=sparclite ;;
+sparc64-*-solaris2*) gdb_target=sp64sol2 ;;
+sparc64-*-*) gdb_target=sp64 ;;
+
+tahoe-*-*) gdb_target=tahoe ;;
+
+vax-*-*) gdb_target=vax ;;
+
+w65-*-*) gdb_target=w65 ;;
+
+z8k-*-coff*) gdb_target=z8k ;;
+
+esac
+
+dnl
+changequote([,])dnl
+
+frags=
+host_makefile_frag=${srcdir}/config/${gdb_host_cpu}/${gdb_host}.mh
+if test ! -f ${host_makefile_frag}; then
+AC_MSG_ERROR("*** Gdb does not support host ${host}")
+fi
+frags="$frags $host_makefile_frag"
+
+target_makefile_frag=${srcdir}/config/${gdb_target_cpu}/${gdb_target}.mt
+if test ! -f ${target_makefile_frag}; then
+AC_MSG_ERROR("*** Gdb does not support target ${target}")
+fi
+frags="$frags $target_makefile_frag"
+
+AC_SUBST_FILE(host_makefile_frag)
+AC_SUBST_FILE(target_makefile_frag)
+AC_SUBST(frags)
+
+changequote(,)dnl
+hostfile=`sed -n '
+s/XM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+
+targetfile=`sed -n '
+s/TM_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${target_makefile_frag}`
+
+# these really aren't orthogonal true/false values of the same condition,
+# but shells are slow enough that I like to reuse the test conditions
+# whenever possible
+if test "${target}" = "${host}"; then
+nativefile=`sed -n '
+s/NAT_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${host_makefile_frag}`
+else
+# GDBserver is only useful in a "native" enviroment
+configdirs=`echo $configdirs | sed 's/gdbserver//'`
+fi
+changequote([,])
+
+# If hostfile (XM_FILE) and/or targetfile (TM_FILE) and/or nativefile
+# (NAT_FILE) is not set in config/*/*.m[ht] files, we don't make the
+# corresponding links. But we have to remove the xm.h files and tm.h
+# files anyway, e.g. when switching from "configure host" to
+# "configure none".
+
+files=
+links=
+rm -f xm.h
+if test "${hostfile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${hostfile}"
+links="${links} xm.h"
+fi
+rm -f tm.h
+if test "${targetfile}" != ""; then
+files="${files} config/${gdb_target_cpu}/${targetfile}"
+links="${links} tm.h"
+fi
+rm -f nm.h
+if test "${nativefile}" != ""; then
+files="${files} config/${gdb_host_cpu}/${nativefile}"
+links="${links} nm.h"
+else
+# A cross-only configuration.
+files="${files} config/nm-empty.h"
+links="${links} nm.h"
+fi
+
+AC_LINK_FILES($files, $links)
+
+AC_CONFIG_SUBDIRS($configdirs)
+AC_OUTPUT(Makefile,
+[
+dnl Autoconf doesn't provide a mechanism for modifying definitions
+dnl provided by makefile fragments.
+dnl
+if test "${nativefile}" = ""; then
+sed -e '/^NATDEPFILES= /s//# NATDEPFILES= /' \
+ < Makefile > Makefile.tem
+mv -f Makefile.tem Makefile
+fi
+
+changequote(,)dnl
+sed -e '/^TM_FILE[ ]*=/s,^TM_FILE[ ]*=[ ]*,&config/'"${gdb_target_cpu}"'/,
+/^XM_FILE[ ]*=/s,^XM_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,
+/^NAT_FILE[ ]*=/s,^NAT_FILE[ ]*=[ ]*,&config/'"${gdb_host_cpu}"'/,' <Makefile >Makefile.tmp
+mv -f Makefile.tmp Makefile
+changequote([,])dnl
+
+case ${srcdir} in
+.)
+;;
+*)
+grep "source ${srcdir}/.gdbinit" .gdbinit >/dev/null 2>/dev/null || \
+echo "source ${srcdir}/.gdbinit" >> .gdbinit
+esac
+
+case x$CONFIG_HEADERS in
+xconfig.h:config.in)
+echo > stamp-h ;;
+esac
+],
+[
+gdb_host_cpu=$gdb_host_cpu
+gdb_target_cpu=$gdb_target_cpu
+nativefile=$nativefile
+])
+
+exit 0
+
diff --git a/contrib/gdb/gdb/copying.awk b/contrib/gdb/gdb/copying.awk
new file mode 100644
index 0000000..ab8efe8
--- /dev/null
+++ b/contrib/gdb/gdb/copying.awk
@@ -0,0 +1,77 @@
+BEGIN {
+ FS="\"";
+ print "/* ==> Do not modify this file!! It is created automatically";
+ print " by copying.awk. Modify copying.awk instead. <== */";
+ print ""
+ print "#include \"defs.h\""
+ print "#include \"command.h\""
+ print "#include \"gdbcmd.h\""
+ print ""
+ print "static void"
+ print "show_copying_command PARAMS ((char *, int));"
+ print ""
+ print "static void"
+ print "show_warranty_command PARAMS ((char *, int));"
+ print ""
+ print "extern int immediate_quit;";
+ print "static void";
+ print "show_copying_command (ignore, from_tty)";
+ print " char *ignore;";
+ print " int from_tty;";
+ print "{";
+ print " immediate_quit++;";
+ }
+NR == 1,/^[ ]*NO WARRANTY[ ]*$/ {
+ if ($0 ~ / /)
+ {
+ printf " printf_filtered (\"\\n\");\n";
+ }
+ else if ($0 !~ /^[ ]*NO WARRANTY[ ]*$/)
+ {
+ printf " printf_filtered (\"";
+ for (i = 1; i < NF; i++)
+ printf "%s\\\"", $i;
+ printf "%s\\n\");\n", $NF;
+ }
+ }
+/^[ ]*NO WARRANTY[ ]*$/ {
+ print " immediate_quit--;";
+ print "}";
+ print "";
+ print "static void";
+ print "show_warranty_command (ignore, from_tty)";
+ print " char *ignore;";
+ print " int from_tty;";
+ print "{";
+ print " immediate_quit++;";
+ }
+/^[ ]*NO WARRANTY[ ]*$/, /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/{
+ if (! ($0 ~ /^[ ]*END OF TERMS AND CONDITIONS[ ]*$/))
+ {
+ printf " printf_filtered (\"";
+ for (i = 1; i < NF; i++)
+ printf "%s\\\"", $i;
+ printf "%s\\n\");\n", $NF;
+ }
+ }
+END {
+ print " immediate_quit--;";
+ print "}";
+ print "";
+ print "void"
+ print "_initialize_copying ()";
+ print "{";
+ print " add_cmd (\"copying\", no_class, show_copying_command,";
+ print " \"Conditions for redistributing copies of GDB.\",";
+ print " &showlist);";
+ print " add_cmd (\"warranty\", no_class, show_warranty_command,";
+ print " \"Various kinds of warranty you do not have.\",";
+ print " &showlist);";
+ print "";
+ print " /* For old-timers, allow \"info copying\", etc. */";
+ print " add_info (\"copying\", show_copying_command,";
+ print " \"Conditions for redistributing copies of GDB.\");";
+ print " add_info (\"warranty\", show_warranty_command,";
+ print " \"Various kinds of warranty you do not have.\");";
+ print "}";
+ }
diff --git a/contrib/gdb/gdb/copying.c b/contrib/gdb/gdb/copying.c
new file mode 100644
index 0000000..ffc884a
--- /dev/null
+++ b/contrib/gdb/gdb/copying.c
@@ -0,0 +1,327 @@
+/* ==> Do not modify this file!! It is created automatically
+ by copying.awk. Modify copying.awk instead. <== */
+
+#include "defs.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+static void
+show_copying_command PARAMS ((char *, int));
+
+static void
+show_warranty_command PARAMS ((char *, int));
+
+extern int immediate_quit;
+static void
+show_copying_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ immediate_quit++;
+ printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
+ printf_filtered (" Version 2, June 1991\n");
+ printf_filtered ("\n");
+ printf_filtered (" Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n");
+ printf_filtered (" 675 Mass Ave, Cambridge, MA 02139, USA\n");
+ printf_filtered (" Everyone is permitted to copy and distribute verbatim copies\n");
+ printf_filtered (" of this license document, but changing it is not allowed.\n");
+ printf_filtered ("\n");
+ printf_filtered (" Preamble\n");
+ printf_filtered ("\n");
+ printf_filtered (" The licenses for most software are designed to take away your\n");
+ printf_filtered ("freedom to share and change it. By contrast, the GNU General Public\n");
+ printf_filtered ("License is intended to guarantee your freedom to share and change free\n");
+ printf_filtered ("software--to make sure the software is free for all its users. This\n");
+ printf_filtered ("General Public License applies to most of the Free Software\n");
+ printf_filtered ("Foundation's software and to any other program whose authors commit to\n");
+ printf_filtered ("using it. (Some other Free Software Foundation software is covered by\n");
+ printf_filtered ("the GNU Library General Public License instead.) You can apply it to\n");
+ printf_filtered ("your programs, too.\n");
+ printf_filtered ("\n");
+ printf_filtered (" When we speak of free software, we are referring to freedom, not\n");
+ printf_filtered ("price. Our General Public Licenses are designed to make sure that you\n");
+ printf_filtered ("have the freedom to distribute copies of free software (and charge for\n");
+ printf_filtered ("this service if you wish), that you receive source code or can get it\n");
+ printf_filtered ("if you want it, that you can change the software or use pieces of it\n");
+ printf_filtered ("in new free programs; and that you know you can do these things.\n");
+ printf_filtered ("\n");
+ printf_filtered (" To protect your rights, we need to make restrictions that forbid\n");
+ printf_filtered ("anyone to deny you these rights or to ask you to surrender the rights.\n");
+ printf_filtered ("These restrictions translate to certain responsibilities for you if you\n");
+ printf_filtered ("distribute copies of the software, or if you modify it.\n");
+ printf_filtered ("\n");
+ printf_filtered (" For example, if you distribute copies of such a program, whether\n");
+ printf_filtered ("gratis or for a fee, you must give the recipients all the rights that\n");
+ printf_filtered ("you have. You must make sure that they, too, receive or can get the\n");
+ printf_filtered ("source code. And you must show them these terms so they know their\n");
+ printf_filtered ("rights.\n");
+ printf_filtered ("\n");
+ printf_filtered (" We protect your rights with two steps: (1) copyright the software, and\n");
+ printf_filtered ("(2) offer you this license which gives you legal permission to copy,\n");
+ printf_filtered ("distribute and/or modify the software.\n");
+ printf_filtered ("\n");
+ printf_filtered (" Also, for each author's protection and ours, we want to make certain\n");
+ printf_filtered ("that everyone understands that there is no warranty for this free\n");
+ printf_filtered ("software. If the software is modified by someone else and passed on, we\n");
+ printf_filtered ("want its recipients to know that what they have is not the original, so\n");
+ printf_filtered ("that any problems introduced by others will not reflect on the original\n");
+ printf_filtered ("authors' reputations.\n");
+ printf_filtered ("\n");
+ printf_filtered (" Finally, any free program is threatened constantly by software\n");
+ printf_filtered ("patents. We wish to avoid the danger that redistributors of a free\n");
+ printf_filtered ("program will individually obtain patent licenses, in effect making the\n");
+ printf_filtered ("program proprietary. To prevent this, we have made it clear that any\n");
+ printf_filtered ("patent must be licensed for everyone's free use or not licensed at all.\n");
+ printf_filtered ("\n");
+ printf_filtered (" The precise terms and conditions for copying, distribution and\n");
+ printf_filtered ("modification follow.\n");
+ printf_filtered ("\n");
+ printf_filtered (" GNU GENERAL PUBLIC LICENSE\n");
+ printf_filtered (" TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n");
+ printf_filtered ("\n");
+ printf_filtered (" 0. This License applies to any program or other work which contains\n");
+ printf_filtered ("a notice placed by the copyright holder saying it may be distributed\n");
+ printf_filtered ("under the terms of this General Public License. The \"Program\", below,\n");
+ printf_filtered ("refers to any such program or work, and a \"work based on the Program\"\n");
+ printf_filtered ("means either the Program or any derivative work under copyright law:\n");
+ printf_filtered ("that is to say, a work containing the Program or a portion of it,\n");
+ printf_filtered ("either verbatim or with modifications and/or translated into another\n");
+ printf_filtered ("language. (Hereinafter, translation is included without limitation in\n");
+ printf_filtered ("the term \"modification\".) Each licensee is addressed as \"you\".\n");
+ printf_filtered ("\n");
+ printf_filtered ("Activities other than copying, distribution and modification are not\n");
+ printf_filtered ("covered by this License; they are outside its scope. The act of\n");
+ printf_filtered ("running the Program is not restricted, and the output from the Program\n");
+ printf_filtered ("is covered only if its contents constitute a work based on the\n");
+ printf_filtered ("Program (independent of having been made by running the Program).\n");
+ printf_filtered ("Whether that is true depends on what the Program does.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 1. You may copy and distribute verbatim copies of the Program's\n");
+ printf_filtered ("source code as you receive it, in any medium, provided that you\n");
+ printf_filtered ("conspicuously and appropriately publish on each copy an appropriate\n");
+ printf_filtered ("copyright notice and disclaimer of warranty; keep intact all the\n");
+ printf_filtered ("notices that refer to this License and to the absence of any warranty;\n");
+ printf_filtered ("and give any other recipients of the Program a copy of this License\n");
+ printf_filtered ("along with the Program.\n");
+ printf_filtered ("\n");
+ printf_filtered ("You may charge a fee for the physical act of transferring a copy, and\n");
+ printf_filtered ("you may at your option offer warranty protection in exchange for a fee.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 2. You may modify your copy or copies of the Program or any portion\n");
+ printf_filtered ("of it, thus forming a work based on the Program, and copy and\n");
+ printf_filtered ("distribute such modifications or work under the terms of Section 1\n");
+ printf_filtered ("above, provided that you also meet all of these conditions:\n");
+ printf_filtered ("\n");
+ printf_filtered (" a) You must cause the modified files to carry prominent notices\n");
+ printf_filtered (" stating that you changed the files and the date of any change.\n");
+ printf_filtered ("\n");
+ printf_filtered (" b) You must cause any work that you distribute or publish, that in\n");
+ printf_filtered (" whole or in part contains or is derived from the Program or any\n");
+ printf_filtered (" part thereof, to be licensed as a whole at no charge to all third\n");
+ printf_filtered (" parties under the terms of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" c) If the modified program normally reads commands interactively\n");
+ printf_filtered (" when run, you must cause it, when started running for such\n");
+ printf_filtered (" interactive use in the most ordinary way, to print or display an\n");
+ printf_filtered (" announcement including an appropriate copyright notice and a\n");
+ printf_filtered (" notice that there is no warranty (or else, saying that you provide\n");
+ printf_filtered (" a warranty) and that users may redistribute the program under\n");
+ printf_filtered (" these conditions, and telling the user how to view a copy of this\n");
+ printf_filtered (" License. (Exception: if the Program itself is interactive but\n");
+ printf_filtered (" does not normally print such an announcement, your work based on\n");
+ printf_filtered (" the Program is not required to print an announcement.)\n");
+ printf_filtered ("\n");
+ printf_filtered ("These requirements apply to the modified work as a whole. If\n");
+ printf_filtered ("identifiable sections of that work are not derived from the Program,\n");
+ printf_filtered ("and can be reasonably considered independent and separate works in\n");
+ printf_filtered ("themselves, then this License, and its terms, do not apply to those\n");
+ printf_filtered ("sections when you distribute them as separate works. But when you\n");
+ printf_filtered ("distribute the same sections as part of a whole which is a work based\n");
+ printf_filtered ("on the Program, the distribution of the whole must be on the terms of\n");
+ printf_filtered ("this License, whose permissions for other licensees extend to the\n");
+ printf_filtered ("entire whole, and thus to each and every part regardless of who wrote it.\n");
+ printf_filtered ("\n");
+ printf_filtered ("Thus, it is not the intent of this section to claim rights or contest\n");
+ printf_filtered ("your rights to work written entirely by you; rather, the intent is to\n");
+ printf_filtered ("exercise the right to control the distribution of derivative or\n");
+ printf_filtered ("collective works based on the Program.\n");
+ printf_filtered ("\n");
+ printf_filtered ("In addition, mere aggregation of another work not based on the Program\n");
+ printf_filtered ("with the Program (or with a work based on the Program) on a volume of\n");
+ printf_filtered ("a storage or distribution medium does not bring the other work under\n");
+ printf_filtered ("the scope of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 3. You may copy and distribute the Program (or a work based on it,\n");
+ printf_filtered ("under Section 2) in object code or executable form under the terms of\n");
+ printf_filtered ("Sections 1 and 2 above provided that you also do one of the following:\n");
+ printf_filtered ("\n");
+ printf_filtered (" a) Accompany it with the complete corresponding machine-readable\n");
+ printf_filtered (" source code, which must be distributed under the terms of Sections\n");
+ printf_filtered (" 1 and 2 above on a medium customarily used for software interchange; or,\n");
+ printf_filtered ("\n");
+ printf_filtered (" b) Accompany it with a written offer, valid for at least three\n");
+ printf_filtered (" years, to give any third party, for a charge no more than your\n");
+ printf_filtered (" cost of physically performing source distribution, a complete\n");
+ printf_filtered (" machine-readable copy of the corresponding source code, to be\n");
+ printf_filtered (" distributed under the terms of Sections 1 and 2 above on a medium\n");
+ printf_filtered (" customarily used for software interchange; or,\n");
+ printf_filtered ("\n");
+ printf_filtered (" c) Accompany it with the information you received as to the offer\n");
+ printf_filtered (" to distribute corresponding source code. (This alternative is\n");
+ printf_filtered (" allowed only for noncommercial distribution and only if you\n");
+ printf_filtered (" received the program in object code or executable form with such\n");
+ printf_filtered (" an offer, in accord with Subsection b above.)\n");
+ printf_filtered ("\n");
+ printf_filtered ("The source code for a work means the preferred form of the work for\n");
+ printf_filtered ("making modifications to it. For an executable work, complete source\n");
+ printf_filtered ("code means all the source code for all modules it contains, plus any\n");
+ printf_filtered ("associated interface definition files, plus the scripts used to\n");
+ printf_filtered ("control compilation and installation of the executable. However, as a\n");
+ printf_filtered ("special exception, the source code distributed need not include\n");
+ printf_filtered ("anything that is normally distributed (in either source or binary\n");
+ printf_filtered ("form) with the major components (compiler, kernel, and so on) of the\n");
+ printf_filtered ("operating system on which the executable runs, unless that component\n");
+ printf_filtered ("itself accompanies the executable.\n");
+ printf_filtered ("\n");
+ printf_filtered ("If distribution of executable or object code is made by offering\n");
+ printf_filtered ("access to copy from a designated place, then offering equivalent\n");
+ printf_filtered ("access to copy the source code from the same place counts as\n");
+ printf_filtered ("distribution of the source code, even though third parties are not\n");
+ printf_filtered ("compelled to copy the source along with the object code.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 4. You may not copy, modify, sublicense, or distribute the Program\n");
+ printf_filtered ("except as expressly provided under this License. Any attempt\n");
+ printf_filtered ("otherwise to copy, modify, sublicense or distribute the Program is\n");
+ printf_filtered ("void, and will automatically terminate your rights under this License.\n");
+ printf_filtered ("However, parties who have received copies, or rights, from you under\n");
+ printf_filtered ("this License will not have their licenses terminated so long as such\n");
+ printf_filtered ("parties remain in full compliance.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 5. You are not required to accept this License, since you have not\n");
+ printf_filtered ("signed it. However, nothing else grants you permission to modify or\n");
+ printf_filtered ("distribute the Program or its derivative works. These actions are\n");
+ printf_filtered ("prohibited by law if you do not accept this License. Therefore, by\n");
+ printf_filtered ("modifying or distributing the Program (or any work based on the\n");
+ printf_filtered ("Program), you indicate your acceptance of this License to do so, and\n");
+ printf_filtered ("all its terms and conditions for copying, distributing or modifying\n");
+ printf_filtered ("the Program or works based on it.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 6. Each time you redistribute the Program (or any work based on the\n");
+ printf_filtered ("Program), the recipient automatically receives a license from the\n");
+ printf_filtered ("original licensor to copy, distribute or modify the Program subject to\n");
+ printf_filtered ("these terms and conditions. You may not impose any further\n");
+ printf_filtered ("restrictions on the recipients' exercise of the rights granted herein.\n");
+ printf_filtered ("You are not responsible for enforcing compliance by third parties to\n");
+ printf_filtered ("this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 7. If, as a consequence of a court judgment or allegation of patent\n");
+ printf_filtered ("infringement or for any other reason (not limited to patent issues),\n");
+ printf_filtered ("conditions are imposed on you (whether by court order, agreement or\n");
+ printf_filtered ("otherwise) that contradict the conditions of this License, they do not\n");
+ printf_filtered ("excuse you from the conditions of this License. If you cannot\n");
+ printf_filtered ("distribute so as to satisfy simultaneously your obligations under this\n");
+ printf_filtered ("License and any other pertinent obligations, then as a consequence you\n");
+ printf_filtered ("may not distribute the Program at all. For example, if a patent\n");
+ printf_filtered ("license would not permit royalty-free redistribution of the Program by\n");
+ printf_filtered ("all those who receive copies directly or indirectly through you, then\n");
+ printf_filtered ("the only way you could satisfy both it and this License would be to\n");
+ printf_filtered ("refrain entirely from distribution of the Program.\n");
+ printf_filtered ("\n");
+ printf_filtered ("If any portion of this section is held invalid or unenforceable under\n");
+ printf_filtered ("any particular circumstance, the balance of the section is intended to\n");
+ printf_filtered ("apply and the section as a whole is intended to apply in other\n");
+ printf_filtered ("circumstances.\n");
+ printf_filtered ("\n");
+ printf_filtered ("It is not the purpose of this section to induce you to infringe any\n");
+ printf_filtered ("patents or other property right claims or to contest validity of any\n");
+ printf_filtered ("such claims; this section has the sole purpose of protecting the\n");
+ printf_filtered ("integrity of the free software distribution system, which is\n");
+ printf_filtered ("implemented by public license practices. Many people have made\n");
+ printf_filtered ("generous contributions to the wide range of software distributed\n");
+ printf_filtered ("through that system in reliance on consistent application of that\n");
+ printf_filtered ("system; it is up to the author/donor to decide if he or she is willing\n");
+ printf_filtered ("to distribute software through any other system and a licensee cannot\n");
+ printf_filtered ("impose that choice.\n");
+ printf_filtered ("\n");
+ printf_filtered ("This section is intended to make thoroughly clear what is believed to\n");
+ printf_filtered ("be a consequence of the rest of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 8. If the distribution and/or use of the Program is restricted in\n");
+ printf_filtered ("certain countries either by patents or by copyrighted interfaces, the\n");
+ printf_filtered ("original copyright holder who places the Program under this License\n");
+ printf_filtered ("may add an explicit geographical distribution limitation excluding\n");
+ printf_filtered ("those countries, so that distribution is permitted only in or among\n");
+ printf_filtered ("countries not thus excluded. In such case, this License incorporates\n");
+ printf_filtered ("the limitation as if written in the body of this License.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 9. The Free Software Foundation may publish revised and/or new versions\n");
+ printf_filtered ("of the General Public License from time to time. Such new versions will\n");
+ printf_filtered ("be similar in spirit to the present version, but may differ in detail to\n");
+ printf_filtered ("address new problems or concerns.\n");
+ printf_filtered ("\n");
+ printf_filtered ("Each version is given a distinguishing version number. If the Program\n");
+ printf_filtered ("specifies a version number of this License which applies to it and \"any\n");
+ printf_filtered ("later version\", you have the option of following the terms and conditions\n");
+ printf_filtered ("either of that version or of any later version published by the Free\n");
+ printf_filtered ("Software Foundation. If the Program does not specify a version number of\n");
+ printf_filtered ("this License, you may choose any version ever published by the Free Software\n");
+ printf_filtered ("Foundation.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 10. If you wish to incorporate parts of the Program into other free\n");
+ printf_filtered ("programs whose distribution conditions are different, write to the author\n");
+ printf_filtered ("to ask for permission. For software which is copyrighted by the Free\n");
+ printf_filtered ("Software Foundation, write to the Free Software Foundation; we sometimes\n");
+ printf_filtered ("make exceptions for this. Our decision will be guided by the two goals\n");
+ printf_filtered ("of preserving the free status of all derivatives of our free software and\n");
+ printf_filtered ("of promoting the sharing and reuse of software generally.\n");
+ printf_filtered ("\n");
+ immediate_quit--;
+}
+
+static void
+show_warranty_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ immediate_quit++;
+ printf_filtered (" NO WARRANTY\n");
+ printf_filtered ("\n");
+ printf_filtered (" 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n");
+ printf_filtered ("FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n");
+ printf_filtered ("OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n");
+ printf_filtered ("PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n");
+ printf_filtered ("OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n");
+ printf_filtered ("MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n");
+ printf_filtered ("TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n");
+ printf_filtered ("PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n");
+ printf_filtered ("REPAIR OR CORRECTION.\n");
+ printf_filtered ("\n");
+ printf_filtered (" 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n");
+ printf_filtered ("WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n");
+ printf_filtered ("REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n");
+ printf_filtered ("INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n");
+ printf_filtered ("OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n");
+ printf_filtered ("TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n");
+ printf_filtered ("YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n");
+ printf_filtered ("PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n");
+ printf_filtered ("POSSIBILITY OF SUCH DAMAGES.\n");
+ printf_filtered ("\n");
+ immediate_quit--;
+}
+
+void
+_initialize_copying ()
+{
+ add_cmd ("copying", no_class, show_copying_command,
+ "Conditions for redistributing copies of GDB.",
+ &showlist);
+ add_cmd ("warranty", no_class, show_warranty_command,
+ "Various kinds of warranty you do not have.",
+ &showlist);
+
+ /* For old-timers, allow "info copying", etc. */
+ add_info ("copying", show_copying_command,
+ "Conditions for redistributing copies of GDB.");
+ add_info ("warranty", show_warranty_command,
+ "Various kinds of warranty you do not have.");
+}
diff --git a/contrib/gdb/gdb/core-aout.c b/contrib/gdb/gdb/core-aout.c
new file mode 100644
index 0000000..7103a9c
--- /dev/null
+++ b/contrib/gdb/gdb/core-aout.c
@@ -0,0 +1,143 @@
+/* Extract registers from a "standard" core file, for GDB.
+ Copyright (C) 1988-1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Typically used on systems that have a.out format executables.
+ corefile.c is supposed to contain the more machine-independent
+ aspects of reading registers from core files, while this file is
+ more machine specific. */
+
+#include "defs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include "gdbcore.h"
+#include "value.h" /* For supply_register. */
+#include "inferior.h" /* For ARCH_NUM_REGS. */
+
+/* These are needed on various systems to expand REGISTER_U_ADDR. */
+#ifndef USG
+#include <sys/dir.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/user.h>
+#ifndef NO_PTRACE_H
+# ifdef PTRACE_IN_WRONG_PLACE
+# include <ptrace.h>
+# else /* !PTRACE_IN_WRONG_PLACE */
+# include <sys/ptrace.h>
+# endif /* !PTRACE_IN_WRONG_PLACE */
+#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 <sys/core.h>
+#endif
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them.
+
+ CORE_REG_SECT points to the register values themselves, read into memory.
+ CORE_REG_SIZE is the size of that area.
+ WHICH says which set of registers we are handling (0 = int, 2 = float
+ on machines where they are discontiguous).
+ REG_ADDR is the offset from u.u_ar0 to the register values relative to
+ core_reg_sect. This is used with old-fashioned core files to
+ locate the registers in a large upage-plus-stack ".reg" section.
+ Original upage address X is at location core_reg_sect+x+reg_addr.
+ */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned reg_addr;
+{
+ register int regno;
+ 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
+ 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 > (int) core_reg_size)
+ reg_ptr -= KERNEL_U_ADDR;
+
+ for (regno = 0; regno < numregs; regno++)
+ {
+ addr = CORE_REGISTER_ADDR (regno, reg_ptr);
+ if (addr >= core_reg_size) {
+ if (bad_reg < 0)
+ bad_reg = regno;
+ } else {
+ supply_register (regno, core_reg_sect + addr);
+ }
+ }
+ if (bad_reg >= 0)
+ {
+ error ("Register %s not found in core file.", reg_names[bad_reg]);
+ }
+}
+
+
+#ifdef REGISTER_U_ADDR
+
+/* Return the address in the core dump or inferior of register REGNO.
+ BLOCKEND is the address of the end of the user structure. */
+
+unsigned int
+register_addr (regno, blockend)
+ int regno;
+ int blockend;
+{
+ int addr;
+
+ if (regno < 0 || regno >= ARCH_NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+#endif /* REGISTER_U_ADDR */
+
+
+/* Register that we are able to handle aout (trad-core) file formats. */
+
+static struct core_fns aout_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_aout ()
+{
+ add_core_fns (&aout_core_fns);
+}
diff --git a/contrib/gdb/gdb/core-regset.c b/contrib/gdb/gdb/core-regset.c
new file mode 100644
index 0000000..68b0845
--- /dev/null
+++ b/contrib/gdb/gdb/core-regset.c
@@ -0,0 +1,130 @@
+/* Machine independent GDB support for core files on systems using "regsets".
+ Copyright 1993-1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* N O T E S
+
+This file is used by most systems that implement /proc. For these systems,
+the general registers are laid out the same way in both the core file and
+the gregset_p structure. The current exception to this is Irix-4.*, where
+the gregset_p structure is split up into two pieces in the core file.
+
+The general register and floating point register sets are manipulated by
+separate ioctl's. This file makes the assumption that if FP0_REGNUM is
+defined, then support for the floating point register set is desired,
+regardless of whether or not the actual target has floating point hardware.
+
+ */
+
+#include "defs.h"
+
+#include <time.h>
+#ifdef HAVE_SYS_PROCFS_H
+#include <sys/procfs.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#include "gdb_string.h"
+
+#include "inferior.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcore.h"
+
+/*
+
+GLOBAL FUNCTION
+
+ fetch_core_registers -- fetch current registers from core file
+
+SYNOPSIS
+
+ void fetch_core_registers (char *core_reg_sect,
+ unsigned core_reg_size,
+ int which, unsigned in reg_addr)
+
+DESCRIPTION
+
+ Read the values of either the general register set (WHICH equals 0)
+ or the floating point register set (WHICH equals 2) from the core
+ file data (pointed to by CORE_REG_SECT), and update gdb's idea of
+ their current values. The CORE_REG_SIZE parameter is ignored.
+
+NOTES
+
+ Use the indicated sizes to validate the gregset and fpregset
+ structures.
+*/
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned int reg_addr; /* Unused in this version */
+{
+#if defined (HAVE_GREGSET_T) && defined (HAVE_FPREGSET_T)
+ gregset_t gregset;
+ fpregset_t fpregset;
+
+ if (which == 0)
+ {
+ if (core_reg_size != sizeof (gregset))
+ {
+ warning ("wrong size gregset struct in core file");
+ }
+ else
+ {
+ memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
+ supply_gregset (&gregset);
+ }
+ }
+ else if (which == 2)
+ {
+ if (core_reg_size != sizeof (fpregset))
+ {
+ warning ("wrong size fpregset struct in core file");
+ }
+ else
+ {
+ memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
+#if defined (FP0_REGNUM)
+ supply_fpregset (&fpregset);
+#endif
+ }
+ }
+#endif /* defined(HAVE_GREGSET_T) && defined (HAVE_FPREGSET_T) */
+}
+
+
+/* Register that we are able to handle ELF file formats using standard
+ procfs "regset" structures. */
+
+static struct core_fns regset_core_fns =
+{
+ bfd_target_elf_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_regset ()
+{
+ add_core_fns (&regset_core_fns);
+}
diff --git a/contrib/gdb/gdb/core-sol2.c b/contrib/gdb/gdb/core-sol2.c
new file mode 100644
index 0000000..5f43002
--- /dev/null
+++ b/contrib/gdb/gdb/core-sol2.c
@@ -0,0 +1,133 @@
+/* Machine independent support for Solaris 2 core files for GDB.
+ Copyright 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* Solaris comes with two flavours of core files, cores generated by
+ an ELF executable and cores generated by programs that were
+ run under BCP (the part of Solaris which allows it to run SunOS4
+ a.out files).
+ This file combines the core register fetching from core-regset.c
+ and sparc-nat.c to be able to read both flavours. */
+
+#include "defs.h"
+#undef gregset_t
+#undef fpregset_t
+
+#include <time.h>
+#include <sys/regset.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "gdb_string.h"
+
+#include "inferior.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcore.h"
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned int reg_addr; /* Unused in this version */
+{
+ prgregset_t prgregset;
+ prfpregset_t prfpregset;
+
+ if (which == 0)
+ {
+ if (core_reg_size == sizeof (prgregset))
+ {
+ memcpy ((char *) &prgregset, core_reg_sect, sizeof (prgregset));
+ supply_gregset (&prgregset);
+ }
+ else if (core_reg_size == sizeof (struct regs))
+ {
+#define gregs ((struct regs *)core_reg_sect)
+ /* G0 *always* holds 0. */
+ *(int *)&registers[REGISTER_BYTE (0)] = 0;
+
+ /* The globals and output registers. */
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &gregs->r_g1,
+ 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = gregs->r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = gregs->r_pc;
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = gregs->r_npc;
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = gregs->r_y;
+
+ /* My best guess at where to get the locals and input
+ registers is exactly where they usually are, right above
+ the stack pointer. If the core dump was caused by a bus error
+ from blowing away the stack pointer (as is possible) then this
+ won't work, but it's worth the try. */
+ {
+ int sp;
+
+ sp = *(int *)&registers[REGISTER_BYTE (SP_REGNUM)];
+ if (0 != target_read_memory (sp,
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM)))
+ {
+ warning ("couldn't read input and local registers from core file\n");
+ }
+ }
+ }
+ else
+ {
+ warning ("wrong size gregset struct in core file");
+ }
+ }
+ else if (which == 2)
+ {
+ if (core_reg_size == sizeof (prfpregset))
+ {
+ memcpy ((char *) &prfpregset, core_reg_sect, sizeof (prfpregset));
+ supply_fpregset (&prfpregset);
+ }
+ else if (core_reg_size >= sizeof (struct fpu))
+ {
+#define fpuregs ((struct fpu *) core_reg_sect)
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &fpuregs->fpu_fr,
+ sizeof (fpuregs->fpu_fr));
+ memcpy (&registers[REGISTER_BYTE (FPS_REGNUM)], &fpuregs->fpu_fsr,
+ sizeof (FPU_FSR_TYPE));
+ }
+ else
+ {
+ warning ("wrong size fpregset struct in core file");
+ }
+ }
+}
+
+
+/* Register that we are able to handle solaris core file formats. */
+
+static struct core_fns solaris_core_fns =
+{
+ bfd_target_elf_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_solaris ()
+{
+ add_core_fns (&solaris_core_fns);
+}
diff --git a/contrib/gdb/gdb/corefile.c b/contrib/gdb/gdb/corefile.c
new file mode 100644
index 0000000..a916bf8
--- /dev/null
+++ b/contrib/gdb/gdb/corefile.c
@@ -0,0 +1,339 @@
+/* Core dump and executable file functions above target vector, for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "dis-asm.h"
+#include "language.h"
+
+extern char registers[];
+
+/* Hook for `exec_file_command' command to call. */
+
+void (*exec_file_display_hook) PARAMS ((char *)) = NULL;
+
+/* Binary file diddling handle for the core file. */
+
+bfd *core_bfd = NULL;
+
+
+/* Backward compatability with old way of specifying core files. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ struct target_ops *t;
+
+ dont_repeat (); /* Either way, seems bogus. */
+
+ t = find_core_target ();
+ if (t != NULL)
+ if (!filename)
+ (t->to_detach) (filename, from_tty);
+ else
+ (t->to_open) (filename, from_tty);
+ else
+ error ("GDB can't read core files on this machine.");
+}
+
+
+/* Call this to specify the hook for exec_file_command to call back.
+ This is called from the x-window display code. */
+
+void
+specify_exec_file_hook (hook)
+ void (*hook) PARAMS ((char *));
+{
+ exec_file_display_hook = hook;
+}
+
+/* The exec file must be closed before running an inferior.
+ If it is needed again after the inferior dies, it must
+ be reopened. */
+
+void
+close_exec_file ()
+{
+#ifdef FIXME
+ if (exec_bfd)
+ bfd_tempclose (exec_bfd);
+#endif
+}
+
+void
+reopen_exec_file ()
+{
+#ifdef FIXME
+ if (exec_bfd)
+ bfd_reopen (exec_bfd);
+#endif
+}
+
+/* If we have both a core file and an exec file,
+ print a warning if they don't go together. */
+
+void
+validate_files ()
+{
+ if (exec_bfd && core_bfd)
+ {
+ if (!core_file_matches_executable_p (core_bfd, exec_bfd))
+ warning ("core file may not match specified executable file.");
+ else if (bfd_get_mtime(exec_bfd) > bfd_get_mtime(core_bfd))
+ warning ("exec file is newer than core file.");
+ }
+}
+
+/* Return the name of the executable file as a string.
+ ERR nonzero means get error if there is none specified;
+ otherwise return 0 in that case. */
+
+char *
+get_exec_file (err)
+ int err;
+{
+ if (exec_bfd) return bfd_get_filename(exec_bfd);
+ if (!err) return NULL;
+
+ error ("No executable file specified.\n\
+Use the \"file\" or \"exec-file\" command.");
+ return NULL;
+}
+
+
+/* Report a memory error with error(). */
+
+void
+memory_error (status, memaddr)
+ int status;
+ CORE_ADDR memaddr;
+{
+ if (status == EIO)
+ {
+ /* Actually, address between memaddr and memaddr + len
+ was out of bounds. */
+ 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_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);
+ }
+}
+
+/* Same as target_read_memory, but report an error if can't read. */
+void
+read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int status;
+ status = target_read_memory (memaddr, myaddr, len);
+ if (status != 0)
+ memory_error (status, memaddr);
+}
+
+/* Like target_read_memory, but slightly different parameters. */
+
+int
+dis_asm_read_memory (memaddr, myaddr, len, info)
+ bfd_vma memaddr;
+ bfd_byte *myaddr;
+ int len;
+ disassemble_info *info;
+{
+ return target_read_memory (memaddr, (char *) myaddr, len);
+}
+
+/* Like memory_error with slightly different parameters. */
+void
+dis_asm_memory_error (status, memaddr, info)
+ int status;
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ memory_error (status, memaddr);
+}
+
+/* Like print_address with slightly different parameters. */
+void
+dis_asm_print_address (addr, info)
+ bfd_vma addr;
+ struct disassemble_info *info;
+{
+ print_address (addr, info->stream);
+}
+
+/* Same as target_write_memory, but report an error if can't write. */
+void
+write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int status;
+
+ status = target_write_memory (memaddr, myaddr, len);
+ if (status != 0)
+ memory_error (status, memaddr);
+}
+
+/* Read an integer from debugged memory, given address and number of bytes. */
+
+LONGEST
+read_memory_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char buf[sizeof (LONGEST)];
+
+ read_memory (memaddr, buf, len);
+ return extract_signed_integer (buf, len);
+}
+
+unsigned LONGEST
+read_memory_unsigned_integer (memaddr, len)
+ CORE_ADDR memaddr;
+ int len;
+{
+ char buf[sizeof (unsigned LONGEST)];
+
+ read_memory (memaddr, buf, 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;
+
+/* Same thing, except it is "auto" not NULL for the default case. */
+static char *gnutarget_string;
+
+static void set_gnutarget_command
+ PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_gnutarget_command (ignore, from_tty, c)
+ char *ignore;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (STREQ (gnutarget_string, "auto"))
+ gnutarget = NULL;
+ else
+ gnutarget = gnutarget_string;
+}
+
+/* Set the gnutarget. */
+void
+set_gnutarget (newtarget)
+ char *newtarget;
+{
+ if (gnutarget_string != NULL)
+ free (gnutarget_string);
+ gnutarget_string = savestring (newtarget, strlen (newtarget));
+ set_gnutarget_command (NULL, 0, NULL);
+}
+
+void
+_initialize_core()
+{
+ struct cmd_list_element *c;
+ c = add_cmd ("core-file", class_files, core_file_command,
+ "Use FILE as core dump for examining memory and registers.\n\
+No arg means have no core file. This command has been superseded by the\n\
+`target core' and `detach' commands.", &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_set_cmd ("gnutarget", class_files, var_string_noescape,
+ (char *) &gnutarget_string,
+ "Set the current BFD target.\n\
+Use `set gnutarget auto' to specify automatic detection.",
+ &setlist);
+ c->function.sfunc = set_gnutarget_command;
+ add_show_from_set (c, &showlist);
+
+ if (getenv ("GNUTARGET"))
+ set_gnutarget (getenv ("GNUTARGET"));
+ else
+ set_gnutarget ("auto");
+}
diff --git a/contrib/gdb/gdb/corelow.c b/contrib/gdb/gdb/corelow.c
new file mode 100644
index 0000000..48bc184
--- /dev/null
+++ b/contrib/gdb/gdb/corelow.c
@@ -0,0 +1,419 @@
+/* Core dump and executable file functions below target vector, for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "symtab.h"
+#include "command.h"
+#include "bfd.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "thread.h"
+
+/* List of all available core_fns. On gdb startup, each core file register
+ reader calls add_core_fns() to register information on each core format it
+ is prepared to read. */
+
+static struct core_fns *core_file_fns = NULL;
+
+static void core_files_info PARAMS ((struct target_ops *));
+
+#ifdef SOLIB_ADD
+static int solib_add_stub PARAMS ((char *));
+#endif
+
+static void core_open PARAMS ((char *, int));
+
+static void core_detach PARAMS ((char *, int));
+
+static void core_close PARAMS ((int));
+
+static void get_core_registers PARAMS ((int));
+
+/* Link a new core_fns into the global core_file_fns list. Called on gdb
+ startup by the _initialize routine in each core file register reader, to
+ register information about each format the the reader is prepared to
+ handle. */
+
+void
+add_core_fns (cf)
+ struct core_fns *cf;
+{
+ cf -> next = core_file_fns;
+ core_file_fns = cf;
+}
+
+
+/* Discard all vestiges of any previous core file and mark data and stack
+ spaces as empty. */
+
+/* ARGSUSED */
+static void
+core_close (quitting)
+ int quitting;
+{
+ char *name;
+
+ inferior_pid = 0; /* Avoid confusion from thread stuff */
+
+ if (core_bfd)
+ {
+ name = bfd_get_filename (core_bfd);
+ if (!bfd_close (core_bfd))
+ warning ("cannot close \"%s\": %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ free (name);
+ core_bfd = NULL;
+#ifdef CLEAR_SOLIB
+ CLEAR_SOLIB ();
+#endif
+ if (core_ops.to_sections)
+ {
+ free ((PTR)core_ops.to_sections);
+ core_ops.to_sections = NULL;
+ core_ops.to_sections_end = NULL;
+ }
+ }
+}
+
+#ifdef SOLIB_ADD
+/* 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_ttyp)
+ char *from_ttyp;
+{
+ SOLIB_ADD (NULL, *(int *)from_ttyp, &current_target);
+ re_enable_breakpoints_in_shlibs ();
+ return 0;
+}
+#endif /* SOLIB_ADD */
+
+/* Look for sections whose names start with `.reg/' so that we can extract the
+ list of threads in a core file. */
+
+static void
+add_to_thread_list (abfd, asect, reg_sect_arg)
+ bfd *abfd;
+ asection *asect;
+ PTR reg_sect_arg;
+{
+ int thread_id;
+ asection *reg_sect = (asection *) reg_sect_arg;
+
+ if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
+ return;
+
+ thread_id = atoi (bfd_section_name (abfd, asect) + 5);
+
+ add_thread (thread_id);
+
+/* Warning, Will Robinson, looking at BFD private data! */
+
+ if (asect->filepos == reg_sect->filepos) /* Did we find .reg? */
+ inferior_pid = thread_id; /* Yes, make it current */
+}
+
+/* This routine opens and sets up the core file bfd. */
+
+static void
+core_open (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ const char *p;
+ int siggy;
+ struct cleanup *old_chain;
+ char *temp;
+ bfd *temp_bfd;
+ int ontop;
+ int scratch_chan;
+
+ target_preopen (from_tty);
+ if (!filename)
+ {
+ error (core_bfd ?
+ "No core file specified. (Use `detach' to stop debugging a core file.)"
+ : "No core file specified.");
+ }
+
+ filename = tilde_expand (filename);
+ if (filename[0] != '/')
+ {
+ temp = concat (current_directory, "/", filename, NULL);
+ free (filename);
+ filename = temp;
+ }
+
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = open (filename, write_files ? O_RDWR : O_RDONLY, 0);
+ if (scratch_chan < 0)
+ perror_with_name (filename);
+
+ temp_bfd = bfd_fdopenr (filename, gnutarget, scratch_chan);
+ if (temp_bfd == NULL)
+ perror_with_name (filename);
+
+ if (!bfd_check_format (temp_bfd, bfd_core))
+ {
+ /* Do it after the err msg */
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ make_cleanup (bfd_close, temp_bfd);
+ 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. */
+
+ discard_cleanups (old_chain); /* Don't free filename any more */
+ unpush_target (&core_ops);
+ core_bfd = temp_bfd;
+ old_chain = make_cleanup (core_close, core_bfd);
+
+ validate_files ();
+
+ /* Find the data section */
+ if (build_section_table (core_bfd, &core_ops.to_sections,
+ &core_ops.to_sections_end))
+ error ("\"%s\": Can't find sections: %s",
+ bfd_get_filename (core_bfd), bfd_errmsg (bfd_get_error ()));
+
+ ontop = !push_target (&core_ops);
+ discard_cleanups (old_chain);
+
+ p = bfd_core_file_failing_command (core_bfd);
+ if (p)
+ printf_filtered ("Core was generated by `%s'.\n", p);
+
+ siggy = bfd_core_file_failing_signal (core_bfd);
+ if (siggy > 0)
+ printf_filtered ("Program terminated with signal %d, %s.\n", siggy,
+ safe_strsignal (siggy));
+
+ /* Build up thread list from BFD sections. */
+
+ init_thread_list ();
+ bfd_map_over_sections (core_bfd, add_to_thread_list,
+ bfd_get_section_by_name (core_bfd, ".reg"));
+
+ if (ontop)
+ {
+ /* Fetch all registers from core file. */
+ target_fetch_registers (-1);
+
+ /* Add symbols and section mappings for any shared libraries. */
+#ifdef SOLIB_ADD
+ catch_errors (solib_add_stub, &from_tty, (char *)0,
+ RETURN_MASK_ALL);
+#endif
+
+ /* Now, set up the frame cache, and print the top of stack. */
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ }
+ else
+ {
+ warning (
+"you won't be able to access this core file until you terminate\n\
+your %s; do ``info files''", target_longname);
+ }
+}
+
+static void
+core_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Too many arguments");
+ unpush_target (&core_ops);
+ reinit_frame_cache ();
+ if (from_tty)
+ printf_filtered ("No core file now.\n");
+}
+
+/* Get the registers out of a core file. This is the machine-
+ independent part. Fetch_core_registers is the machine-dependent
+ part, typically implemented in the xm-file for each architecture. */
+
+/* We just get all the registers, so we don't use regno. */
+
+/* ARGSUSED */
+static void
+get_core_registers (regno)
+ int regno;
+{
+ sec_ptr reg_sec;
+ unsigned size;
+ char *the_regs;
+ char secname[10];
+ enum bfd_flavour our_flavour = bfd_get_flavour (core_bfd);
+ struct core_fns *cf;
+
+ if (core_file_fns == NULL)
+ {
+ fprintf_filtered (gdb_stderr,
+ "Can't fetch registers from this type of core file\n");
+ return;
+ }
+
+ /* Thread support. If inferior_pid is non-zero, then we have found a core
+ file with threads (or multiple processes). In that case, we need to
+ use the appropriate register section, else we just use `.reg'. */
+
+ /* XXX - same thing needs to be done for floating-point (.reg2) sections. */
+
+ if (inferior_pid)
+ sprintf (secname, ".reg/%d", inferior_pid);
+ else
+ strcpy (secname, ".reg");
+
+ reg_sec = bfd_get_section_by_name (core_bfd, secname);
+ if (!reg_sec)
+ goto cant;
+ size = bfd_section_size (core_bfd, reg_sec);
+ the_regs = alloca (size);
+ /* Look for the core functions that match this flavor. Default to the
+ first one if nothing matches. */
+ for (cf = core_file_fns; cf != NULL; cf = cf -> next)
+ {
+ if (our_flavour == cf -> core_flavour)
+ {
+ break;
+ }
+ }
+ if (cf == NULL)
+ {
+ cf = core_file_fns;
+ }
+ if (cf != NULL &&
+ bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size) &&
+ cf -> core_read_registers != NULL)
+ {
+ (cf -> core_read_registers (the_regs, size, 0,
+ (unsigned) bfd_section_vma (abfd,reg_sec)));
+ }
+ else
+ {
+cant:
+ 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. */
+ reg_sec = bfd_get_section_by_name (core_bfd, ".reg2");
+ if (reg_sec)
+ {
+ size = bfd_section_size (core_bfd, reg_sec);
+ the_regs = alloca (size);
+ if (cf != NULL &&
+ bfd_get_section_contents (core_bfd, reg_sec, the_regs, (file_ptr)0, size) &&
+ cf -> core_read_registers != NULL)
+ {
+ (cf -> core_read_registers (the_regs, size, 2,
+ (unsigned) bfd_section_vma (abfd,reg_sec)));
+ }
+ else
+ {
+ fprintf_filtered (gdb_stderr,
+ "Couldn't fetch register set 2 from core file: %s\n",
+ bfd_errmsg (bfd_get_error ()));
+ }
+ }
+ registers_fetched ();
+}
+
+static void
+core_files_info (t)
+ struct target_ops *t;
+{
+ print_section_info (t, core_bfd);
+}
+
+/* If mourn is being called in all the right places, this could be say
+ `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */
+
+static int
+ignore (addr, contents)
+ CORE_ADDR addr;
+ char *contents;
+{
+ return 0;
+}
+
+struct target_ops core_ops = {
+ "core", /* to_shortname */
+ "Local core dump file", /* to_longname */
+ "Use a core file as a target. Specify the filename of the core file.", /* to_doc */
+ core_open, /* to_open */
+ core_close, /* to_close */
+ find_default_attach, /* to_attach */
+ core_detach, /* to_detach */
+ 0, /* to_resume */
+ 0, /* to_wait */
+ get_core_registers, /* to_fetch_registers */
+ 0, /* to_store_registers */
+ 0, /* to_prepare_to_store */
+ xfer_memory, /* to_xfer_memory */
+ core_files_info, /* to_files_info */
+ ignore, /* to_insert_breakpoint */
+ ignore, /* to_remove_breakpoint */
+ 0, /* to_terminal_init */
+ 0, /* to_terminal_inferior */
+ 0, /* to_terminal_ours_for_output */
+ 0, /* to_terminal_ours */
+ 0, /* to_terminal_info */
+ 0, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ find_default_create_inferior, /* to_create_inferior */
+ 0, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ core_stratum, /* to_stratum */
+ 0, /* to_next */
+ 0, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 0, /* to_has_execution */
+ 0, /* to_sections */
+ 0, /* to_sections_end */
+ OPS_MAGIC, /* to_magic */
+};
+
+void
+_initialize_corelow()
+{
+ add_target (&core_ops);
+}
diff --git a/contrib/gdb/gdb/cp-valprint.c b/contrib/gdb/gdb/cp-valprint.c
new file mode 100644
index 0000000..48f4905
--- /dev/null
+++ b/contrib/gdb/gdb/cp-valprint.c
@@ -0,0 +1,600 @@
+/* Support for printing C++ values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "demangle.h"
+#include "annotate.h"
+#include "gdb_string.h"
+#include "c-lang.h"
+
+int vtblprint; /* Controls printing of vtbl's */
+int objectprint; /* Controls looking up an object's derived type
+ using what we find in its vtables. */
+static int static_field_print; /* Controls printing of static fields. */
+
+static struct obstack dont_print_vb_obstack;
+static struct obstack dont_print_statmem_obstack;
+
+static void
+cp_print_static_field PARAMS ((struct type *, value_ptr, GDB_FILE *, int, int,
+ enum val_prettyprint));
+
+static void
+cp_print_value PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *,
+ int, int, enum val_prettyprint, struct type **));
+
+void
+cp_print_class_method (valaddr, type, stream)
+ char *valaddr;
+ struct type *type;
+ GDB_FILE *stream;
+{
+ struct type *domain;
+ struct fn_field *f = NULL;
+ int j = 0;
+ int len2;
+ int offset;
+ char *kind = "";
+ CORE_ADDR addr;
+ struct symbol *sym;
+ unsigned len;
+ unsigned int i;
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ domain = TYPE_DOMAIN_TYPE (target_type);
+ if (domain == (struct type *)NULL)
+ {
+ fprintf_filtered (stream, "<unknown>");
+ return;
+ }
+ addr = unpack_pointer (lookup_pointer_type (builtin_type_void), valaddr);
+ if (METHOD_PTR_IS_VIRTUAL (addr))
+ {
+ offset = METHOD_PTR_TO_VOFFSET (addr);
+ len = TYPE_NFN_FIELDS (domain);
+ for (i = 0; i < len; i++)
+ {
+ f = TYPE_FN_FIELDLIST1 (domain, i);
+ len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
+ {
+ kind = "virtual ";
+ goto common;
+ }
+ }
+ }
+ }
+ else
+ {
+ sym = find_pc_function (addr);
+ if (sym == 0)
+ {
+ error ("invalid pointer to member function");
+ }
+ len = TYPE_NFN_FIELDS (domain);
+ for (i = 0; i < len; i++)
+ {
+ f = TYPE_FN_FIELDLIST1 (domain, i);
+ len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
+
+ for (j = 0; j < len2; j++)
+ {
+ QUIT;
+ if (TYPE_FN_FIELD_STUB (f, j))
+ check_stub_method (domain, i, j);
+ if (STREQ (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
+ {
+ goto common;
+ }
+ }
+ }
+ }
+ common:
+ if (i < len)
+ {
+ fprintf_filtered (stream, "&");
+ c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE (f, j), stream, 0, 0);
+ fprintf_unfiltered (stream, kind);
+ if (TYPE_FN_FIELD_PHYSNAME (f, j)[0] == '_'
+ && is_cplus_marker (TYPE_FN_FIELD_PHYSNAME (f, j)[1]))
+ {
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j) + 1, "~",
+ TYPE_FN_FIELDLIST_NAME (domain, i),
+ 0, stream);
+ }
+ else
+ {
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "",
+ TYPE_FN_FIELDLIST_NAME (domain, i),
+ 0, stream);
+ }
+ }
+ else
+ {
+ fprintf_filtered (stream, "(");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, ") %d", (int) addr >> 3);
+ }
+}
+
+/* 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". */
+
+int
+cp_is_vtbl_ptr_type(type)
+ struct type *type;
+{
+ char *typename = type_name_no_tag (type);
+
+ return (typename != NULL
+ && (STREQ (typename, vtbl_ptr_name)
+ || STREQ (typename, vtbl_ptr_name_old)));
+}
+
+/* Return truth value for the assertion that TYPE is of the type
+ "pointer to virtual function table". */
+
+int
+cp_is_vtbl_member(type)
+ struct type *type;
+{
+ if (TYPE_CODE (type) == TYPE_CODE_PTR)
+ {
+ 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;
+}
+
+/* Mutually recursive subroutines of cp_print_value and c_val_print to
+ print out a structure's fields: cp_print_value_fields and cp_print_value.
+
+ TYPE, VALADDR, ADDRESS, STREAM, RECURSE, and PRETTY have the
+ same meanings as in cp_print_value and c_val_print.
+
+ DONT_PRINT is an array of baseclass types that we
+ should not print, or zero if called from top level. */
+
+void
+cp_print_value_fields (type, valaddr, address, stream, format, recurse, pretty,
+ dont_print_vb, dont_print_statmem)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print_vb;
+ int dont_print_statmem;
+{
+ int i, len, n_baseclasses;
+ struct obstack tmp_obstack;
+ char *last_dont_print = obstack_next_free (&dont_print_statmem_obstack);
+
+ CHECK_TYPEDEF (type);
+
+ fprintf_filtered (stream, "{");
+ len = TYPE_NFIELDS (type);
+ n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ /* Print out baseclasses such that we don't print
+ duplicates of virtual baseclasses. */
+ if (n_baseclasses > 0)
+ cp_print_value (type, valaddr, address, stream,
+ format, recurse+1, pretty, dont_print_vb);
+
+ if (!len && n_baseclasses == 1)
+ fprintf_filtered (stream, "<No data fields>");
+ else
+ {
+ extern int inspect_it;
+ int fields_seen = 0;
+
+ if (dont_print_statmem == 0)
+ {
+ /* If we're at top level, carve out a completely fresh
+ chunk of the obstack and use that until this particular
+ invocation returns. */
+ tmp_obstack = dont_print_statmem_obstack;
+ obstack_finish (&dont_print_statmem_obstack);
+ }
+
+ for (i = n_baseclasses; i < len; i++)
+ {
+ /* If requested, skip printing of static fields. */
+ if (!static_field_print && TYPE_FIELD_STATIC (type, i))
+ continue;
+ if (fields_seen)
+ fprintf_filtered (stream, ", ");
+ else if (n_baseclasses > 0)
+ {
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ fputs_filtered ("members of ", stream);
+ fputs_filtered (type_name_no_tag (type), stream);
+ fputs_filtered (": ", stream);
+ }
+ }
+ fields_seen = 1;
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 + 2 * recurse, stream);
+ }
+ else
+ {
+ wrap_here (n_spaces (2 + 2 * recurse));
+ }
+ if (inspect_it)
+ {
+ if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR)
+ fputs_filtered ("\"( ptr \"", stream);
+ else
+ fputs_filtered ("\"( nodef \"", stream);
+ if (TYPE_FIELD_STATIC (type, i))
+ fputs_filtered ("static ", stream);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ fputs_filtered ("\" \"", stream);
+ fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+ language_cplus,
+ DMGL_PARAMS | DMGL_ANSI);
+ fputs_filtered ("\") \"", stream);
+ }
+ else
+ {
+ annotate_field_begin (TYPE_FIELD_TYPE (type, i));
+
+ if (TYPE_FIELD_STATIC (type, i))
+ fputs_filtered ("static ", stream);
+ 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_STATIC (type, i) && TYPE_FIELD_PACKED (type, i))
+ {
+ value_ptr v;
+
+ /* Bitfields require special handling, especially due to byte
+ order problems. */
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_filtered ("<optimized out or zero length>", stream);
+ }
+ else
+ {
+ v = value_from_longest (TYPE_FIELD_TYPE (type, i),
+ unpack_field_as_long (type, valaddr, i));
+
+ val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0,
+ stream, format, 0, recurse + 1, pretty);
+ }
+ }
+ else
+ {
+ if (TYPE_FIELD_IGNORE (type, i))
+ {
+ fputs_filtered ("<optimized out or zero length>", stream);
+ }
+ else if (TYPE_FIELD_STATIC (type, i))
+ {
+ value_ptr v;
+ char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i);
+ struct symbol *sym =
+ lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym == NULL)
+ fputs_filtered ("<optimized out>", stream);
+ else
+ {
+ v = value_at (TYPE_FIELD_TYPE (type, i),
+ (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+ cp_print_static_field (TYPE_FIELD_TYPE (type, i), v,
+ stream, format, recurse + 1,
+ pretty);
+ }
+ }
+ 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 (dont_print_statmem == 0)
+ {
+ /* Free the space used to deal with the printing
+ of the members from top level. */
+ obstack_free (&dont_print_statmem_obstack, last_dont_print);
+ dont_print_statmem_obstack = tmp_obstack;
+ }
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ }
+ fprintf_filtered (stream, "}");
+}
+
+/* Special val_print routine to avoid printing multiple copies of virtual
+ baseclasses. */
+
+static void
+cp_print_value (type, valaddr, address, stream, format, recurse, pretty,
+ dont_print_vb)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+ struct type **dont_print_vb;
+{
+ struct obstack tmp_obstack;
+ struct type **last_dont_print
+ = (struct type **)obstack_next_free (&dont_print_vb_obstack);
+ int i, n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ if (dont_print_vb == 0)
+ {
+ /* If we're at top level, carve out a completely fresh
+ chunk of the obstack and use that until this particular
+ invocation returns. */
+ tmp_obstack = dont_print_vb_obstack;
+ /* Bump up the high-water mark. Now alpha is omega. */
+ obstack_finish (&dont_print_vb_obstack);
+ }
+
+ for (i = 0; i < n_baseclasses; i++)
+ {
+ int boffset;
+ struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
+ char *basename = TYPE_NAME (baseclass);
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ struct type **first_dont_print
+ = (struct type **)obstack_base (&dont_print_vb_obstack);
+
+ int j = (struct type **)obstack_next_free (&dont_print_vb_obstack)
+ - first_dont_print;
+
+ while (--j >= 0)
+ if (baseclass == first_dont_print[j])
+ goto flush_it;
+
+ obstack_ptr_grow (&dont_print_vb_obstack, baseclass);
+ }
+
+ boffset = baseclass_offset (type, i , valaddr, address);
+
+ if (pretty)
+ {
+ fprintf_filtered (stream, "\n");
+ print_spaces_filtered (2 * recurse, stream);
+ }
+ fputs_filtered ("<", stream);
+ /* Not sure what the best notation is in the case where there is no
+ baseclass name. */
+ fputs_filtered (basename ? basename : "", stream);
+ fputs_filtered ("> = ", stream);
+ if (boffset == -1)
+ fprintf_filtered (stream, "<invalid address>");
+ else
+ cp_print_value_fields (baseclass, valaddr + boffset, address + boffset,
+ stream, format, recurse, pretty,
+ (struct type **) obstack_base (&dont_print_vb_obstack),
+ 0);
+ fputs_filtered (", ", stream);
+
+ flush_it:
+ ;
+ }
+
+ if (dont_print_vb == 0)
+ {
+ /* Free the space used to deal with the printing
+ of this type from top level. */
+ obstack_free (&dont_print_vb_obstack, last_dont_print);
+ /* Reset watermark so that we can continue protecting
+ ourselves from whatever we were protecting ourselves. */
+ dont_print_vb_obstack = tmp_obstack;
+ }
+}
+
+/* Print value of a static member.
+ To avoid infinite recursion when printing a class that contains
+ a static instance of the class, we keep the addresses of all printed
+ static member classes in an obstack and refuse to print them more
+ than once.
+
+ VAL contains the value to print, TYPE, STREAM, RECURSE, and PRETTY
+ have the same meanings as in c_val_print. */
+
+static void
+cp_print_static_field (type, val, stream, format, recurse, pretty)
+ struct type *type;
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ {
+ CORE_ADDR *first_dont_print;
+ int i;
+
+ first_dont_print
+ = (CORE_ADDR *)obstack_base (&dont_print_statmem_obstack);
+ i = (CORE_ADDR *)obstack_next_free (&dont_print_statmem_obstack)
+ - first_dont_print;
+
+ while (--i >= 0)
+ {
+ if (VALUE_ADDRESS (val) == first_dont_print[i])
+ {
+ fputs_filtered ("<same as static member of an already seen type>",
+ stream);
+ return;
+ }
+ }
+
+ obstack_grow (&dont_print_statmem_obstack, (char *) &VALUE_ADDRESS (val),
+ sizeof (CORE_ADDR));
+
+ CHECK_TYPEDEF (type);
+ cp_print_value_fields (type, VALUE_CONTENTS (val), VALUE_ADDRESS (val),
+ stream, format, recurse, pretty, NULL, 1);
+ return;
+ }
+ val_print (type, VALUE_CONTENTS (val), VALUE_ADDRESS (val),
+ stream, format, 0, recurse, pretty);
+}
+
+void
+cp_print_class_member (valaddr, domain, stream, prefix)
+ char *valaddr;
+ struct type *domain;
+ GDB_FILE *stream;
+ char *prefix;
+{
+
+ /* VAL is a byte offset into the structure type DOMAIN.
+ Find the name of the field for that offset and
+ print it. */
+ int extra = 0;
+ int bits = 0;
+ register unsigned int i;
+ unsigned len = TYPE_NFIELDS (domain);
+ /* @@ Make VAL into bit offset */
+ LONGEST val = unpack_long (builtin_type_int, valaddr) << 3;
+ for (i = TYPE_N_BASECLASSES (domain); i < len; i++)
+ {
+ int bitpos = TYPE_FIELD_BITPOS (domain, i);
+ QUIT;
+ if (val == bitpos)
+ break;
+ if (val < bitpos && i != 0)
+ {
+ /* Somehow pointing into a field. */
+ i -= 1;
+ extra = (val - TYPE_FIELD_BITPOS (domain, i));
+ if (extra & 0x7)
+ bits = 1;
+ else
+ extra >>= 3;
+ break;
+ }
+ }
+ if (i < len)
+ {
+ char *name;
+ fprintf_filtered (stream, prefix);
+ name = type_name_no_tag (domain);
+ if (name)
+ fputs_filtered (name, stream);
+ else
+ c_type_print_base (domain, stream, 0, 0);
+ fprintf_filtered (stream, "::");
+ fputs_filtered (TYPE_FIELD_NAME (domain, i), stream);
+ if (extra)
+ fprintf_filtered (stream, " + %d bytes", extra);
+ if (bits)
+ fprintf_filtered (stream, " (offset in bits)");
+ }
+ else
+ fprintf_filtered (stream, "%d", val >> 3);
+}
+
+void
+_initialize_cp_valprint ()
+{
+ add_show_from_set
+ (add_set_cmd ("static-members", class_support, var_boolean,
+ (char *)&static_field_print,
+ "Set printing of C++ static members.",
+ &setprintlist),
+ &showprintlist);
+ /* Turn on printing of static fields. */
+ static_field_print = 1;
+
+ add_show_from_set
+ (add_set_cmd ("vtbl", class_support, var_boolean, (char *)&vtblprint,
+ "Set printing of C++ virtual function tables.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("object", class_support, var_boolean, (char *)&objectprint,
+ "Set printing of object's derived type based on vtable info.",
+ &setprintlist),
+ &showprintlist);
+
+ /* Give people the defaults which they are used to. */
+ objectprint = 0;
+ vtblprint = 0;
+ obstack_begin (&dont_print_vb_obstack, 32 * sizeof (struct type *));
+ obstack_specify_allocation (&dont_print_statmem_obstack,
+ 32 * sizeof (CORE_ADDR), sizeof (CORE_ADDR),
+ xmalloc, free);
+}
diff --git a/contrib/gdb/gdb/cpu32bug-rom.c b/contrib/gdb/gdb/cpu32bug-rom.c
new file mode 100644
index 0000000..43f76f6
--- /dev/null
+++ b/contrib/gdb/gdb/cpu32bug-rom.c
@@ -0,0 +1,171 @@
+/* Remote debugging interface for CPU32Bug Rom monitor for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+ Written by Stu Grossman of Cygnus Support
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void cpu32bug_open PARAMS ((char *args, int from_tty));
+
+static void
+cpu32bug_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] != 'R')
+ return;
+ regno = PS_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] != 'C')
+ return;
+ regno = PC_REGNUM;
+ break;
+ case 'D':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + D0_REGNUM;
+ break;
+ case 'A':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + A0_REGNUM;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes an "A7".
+ */
+
+static char *cpu32bug_regnames[NUM_REGS] =
+{
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+ "SR", "PC",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops cpu32bug_ops;
+
+static char *cpu32bug_inits[] = {"\r", NULL};
+
+static struct monitor_ops cpu32bug_cmds =
+{
+ MO_CLR_BREAK_USES_ADDR,
+ cpu32bug_inits, /* Init strings */
+ "g\r", /* continue command */
+ "t\r", /* single step */
+ NULL, /* interrupt command */
+ "br %x\r", /* set a breakpoint */
+ "nobr %x\r", /* clear a breakpoint */
+ "nobr\r", /* clear all breakpoints */
+ "bf %x:%x %x;b\r", /* fill (start count val) */
+ {
+ "ms %x %02x\r", /* setmem.cmdb (addr, value) */
+ "ms %x %04x\r", /* setmem.cmdw (addr, value) */
+ "ms %x %08x\r", /* setmem.cmdl (addr, value) */
+ NULL, /* setmem.cmdll (addr, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL, /* setreg.term_cmd */
+ },
+ {
+ "md %x:%x;b\r", /* getmem.cmdb (addr, len) */
+ "md %x:%x;b\r", /* getmem.cmdw (addr, len) */
+ "md %x:%x;b\r", /* getmem.cmdl (addr, len) */
+ NULL, /* getmem.cmdll (addr, len) */
+ " ", /* getmem.resp_delim */
+ NULL, /* getmem.term */
+ NULL, /* getmem.term_cmd */
+ },
+ {
+ "rs %s %x\r", /* setreg.cmd (name, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL /* setreg.term_cmd */
+ },
+ {
+ "rs %s\r", /* getreg.cmd (name) */
+ "=", /* getreg.resp_delim */
+ NULL, /* getreg.term */
+ NULL /* getreg.term_cmd */
+ },
+ "rd\r", /* dump_registers */
+ "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)", /* register_pattern */
+ cpu32bug_supply_register, /* supply_register */
+ NULL, /* load_routine (defaults to SRECs) */
+ "lo\r", /* download command */
+ "lo\r\n", /* load response */
+ "CPU32Bug>", /* monitor command prompt */
+ "\r", /* end-of-line terminator */
+ NULL, /* optional command terminator */
+ &cpu32bug_ops, /* target operations */
+ SERIAL_1_STOPBITS, /* number of stop bits */
+ cpu32bug_regnames, /* registers names */
+ MONITOR_OPS_MAGIC /* magic */
+ };
+
+static void
+cpu32bug_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &cpu32bug_cmds, from_tty);
+}
+
+void
+_initialize_cpu32bug_rom ()
+{
+ init_monitor_ops (&cpu32bug_ops);
+
+ cpu32bug_ops.to_shortname = "cpu32bug";
+ cpu32bug_ops.to_longname = "CPU32Bug monitor";
+ cpu32bug_ops.to_doc = "Debug via the CPU32Bug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ cpu32bug_ops.to_open = cpu32bug_open;
+
+ add_target (&cpu32bug_ops);
+}
diff --git a/contrib/gdb/gdb/cxux-nat.c b/contrib/gdb/gdb/cxux-nat.c
new file mode 100644
index 0000000..2ed1430
--- /dev/null
+++ b/contrib/gdb/gdb/cxux-nat.c
@@ -0,0 +1,523 @@
+/* Native support for Motorola 88k running Harris CX/UX.
+ Copyright 1988, 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include "gdbcore.h"
+#include <sys/user.h>
+
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "symtab.h"
+
+#ifndef USER /* added to support BCS ptrace_user */
+#define USER ptrace_user
+#endif
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include "symtab.h"
+#include "setjmp.h"
+#include "value.h"
+
+#include <sys/ptrace.h>
+
+/* CX/UX provides them already, but as word offsets instead of char offsets */
+#define SXIP_OFFSET (PT_SXIP * 4)
+#define SNIP_OFFSET (PT_SNIP * 4)
+#define SFIP_OFFSET (PT_SFIP * 4)
+#define PSR_OFFSET (PT_PSR * sizeof(int))
+#define FPSR_OFFSET (PT_FPSR * sizeof(int))
+#define FPCR_OFFSET (PT_FPCR * sizeof(int))
+
+#define XREGADDR(r) (((char *)&u.pt_x0-(char *)&u) + \
+ ((r)-X0_REGNUM)*sizeof(X_REGISTER_RAW_TYPE))
+
+extern int have_symbol_file_p();
+
+extern jmp_buf stack_jmp;
+
+extern int errno;
+extern char registers[REGISTER_BYTES];
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct USER u;
+ unsigned int offset;
+
+ offset = (char *) &u.pt_r0 - (char *) &u;
+ regaddr = offset; /* byte offset to r0;*/
+
+/* offset = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
+ for (regno = 0; regno < PC_REGNUM; regno++)
+ {
+ /*regaddr = register_addr (regno, offset);*/
+ /* 88k enhancement */
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+ /* now load up registers 32-37; special pc registers */
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) PSR_OFFSET,0);
+ supply_register (PSR_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPSR_OFFSET,0);
+ supply_register (FPSR_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPCR_OFFSET,0);
+ supply_register (FPCR_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET ,0);
+ supply_register (SXIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,0);
+ supply_register (SNIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,0);
+ supply_register (SFIP_REGNUM, buf);
+
+ if (target_is_m88110)
+ {
+ for (regaddr = XREGADDR(X0_REGNUM), regno = X0_REGNUM;
+ regno < NUM_REGS;
+ regno++, regaddr += 16)
+ {
+ X_REGISTER_RAW_TYPE xval;
+
+ *(int *) &xval.w1 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ *(int *) &xval.w2 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr+4), 0);
+ *(int *) &xval.w3 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr+8), 0);
+ *(int *) &xval.w4 = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (regaddr+12), 0);
+ supply_register(regno, (void *)&xval);
+ }
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct USER u;
+
+ unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
+
+ regaddr = offset;
+
+ /* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
+ svr3 doesn't run on an 88110, or the kernel isolates the different (not
+ completely sure this is true, but seems to be. */
+ if (regno >= 0)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ if (regno < PC_REGNUM)
+ {
+ regaddr = offset + regno * sizeof (int);
+ errno = 0;
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else if (regno == PSR_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) PSR_OFFSET, read_register(regno));
+ else if (regno == FPSR_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPSR_OFFSET, read_register(regno));
+ else if (regno == FPCR_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPCR_OFFSET, read_register(regno));
+ else if (regno == SXIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register(regno));
+ else if (regno == SNIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register(regno));
+ else if (regno == SFIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register(regno));
+ else if (target_is_m88110 && regno < NUM_REGS)
+ {
+ X_REGISTER_RAW_TYPE xval;
+
+ read_register_bytes(REGISTER_BYTE(regno), (char *)&xval,
+ sizeof(X_REGISTER_RAW_TYPE));
+ regaddr = XREGADDR(regno);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, xval.w1);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+4, xval.w2);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+8, xval.w3);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr+12, xval.w4);
+ }
+ else
+ printf_unfiltered ("Bad register number for store_inferior routine\n");
+ }
+ else
+ {
+ for (regno = 0; regno < PC_REGNUM; regno++)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ errno = 0;
+ regaddr = offset + regno * sizeof (int);
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) PSR_OFFSET, read_register(regno));
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPSR_OFFSET,read_register(regno));
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) FPCR_OFFSET,read_register(regno));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET,read_register(SXIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,read_register(SNIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,read_register(SFIP_REGNUM));
+ if (target_is_m88110)
+ {
+ for (regno = X0_REGNUM; regno < NUM_REGS; regno++)
+ {
+ X_REGISTER_RAW_TYPE xval;
+
+ read_register_bytes(REGISTER_BYTE(regno), (char *)&xval,
+ sizeof(X_REGISTER_RAW_TYPE));
+ regaddr = XREGADDR(regno);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, xval.w1);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+4), xval.w2);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+8), xval.w3);
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) (regaddr+12), xval.w4);
+ }
+ }
+ }
+}
+
+/* blockend is the address of the end of the user structure */
+
+m88k_register_u_addr (blockend, regnum)
+ int blockend, regnum;
+{
+ struct USER u;
+ int ustart = blockend - sizeof (struct USER);
+
+ if (regnum < PSR_REGNUM)
+ return (ustart + ((int) &u.pt_r0 - (int) &u) +
+ REGISTER_SIZE * regnum);
+ else if (regnum == PSR_REGNUM)
+ return (ustart + ((int) &u.pt_psr) - (int) &u);
+ else if (regnum == FPSR_REGNUM)
+ return (ustart + ((int) &u.pt_fpsr) - (int) &u);
+ else if (regnum == FPCR_REGNUM)
+ return (ustart + ((int) &u.pt_fpcr) - (int) &u);
+ else if (regnum == SXIP_REGNUM)
+ return (ustart + SXIP_OFFSET);
+ else if (regnum == SNIP_REGNUM)
+ return (ustart + SNIP_OFFSET);
+ else if (regnum == SFIP_REGNUM)
+ return (ustart + SFIP_OFFSET);
+ else if (target_is_m88110)
+ return (ustart + ((int) &u.pt_x0 - (int) &u) + /* Must be X register */
+ sizeof(u.pt_x0) * (regnum - X0_REGNUM));
+ else
+ return (blockend + REGISTER_SIZE * regnum);
+}
+
+#ifdef USE_PROC_FS
+
+#include <sys/procfs.h>
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi=0; regi <= SP_REGNUM; regi++)
+ supply_register (regi, (char *) (regp + regi));
+
+ supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
+ supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
+ supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
+ supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
+ supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
+ supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+
+ for (regi = 0 ; regi <= R_R31 ; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(int *) &registers[REGISTER_BYTE(regi)];
+
+ if ((regno == -1) || (regno == SXIP_REGNUM))
+ *(regp + R_XIP) = *(int *) &registers[REGISTER_BYTE(SXIP_REGNUM)];
+ if ((regno == -1) || (regno == SNIP_REGNUM))
+ *(regp + R_NIP) = *(int *) &registers[REGISTER_BYTE(SNIP_REGNUM)];
+ if ((regno == -1) || (regno == SFIP_REGNUM))
+ *(regp + R_FIP) = *(int *) &registers[REGISTER_BYTE(SFIP_REGNUM)];
+ if ((regno == -1) || (regno == PSR_REGNUM))
+ *(regp + R_PSR) = *(int *) &registers[REGISTER_BYTE(PSR_REGNUM)];
+ if ((regno == -1) || (regno == FPSR_REGNUM))
+ *(regp + R_FPSR) = *(int *) &registers[REGISTER_BYTE(FPSR_REGNUM)];
+ if ((regno == -1) || (regno == FPCR_REGNUM))
+ *(regp + R_FPCR) = *(int *) &registers[REGISTER_BYTE(FPCR_REGNUM)];
+}
+
+#endif /* USE_PROC_FS */
+
+/* This support adds the equivalent of adb's % command. When
+ the `add-shared-symbol-files' command is given, this routine scans
+ the dynamic linker's link map and reads the minimal symbols
+ from each shared object file listed in the map. */
+
+struct link_map {
+ unsigned long l_addr; /* address at which object is mapped */
+ char *l_name; /* full name of loaded object */
+ void *l_ld; /* dynamic structure of object */
+ struct link_map *l_next; /* next link object */
+ struct link_map *l_prev; /* previous link object */
+};
+
+#define LINKS_MAP_POINTER "_ld_tail"
+#define LIBC_FILE "/usr/lib/libc.so.1"
+#define SHARED_OFFSET 0xf0001000
+
+#ifndef PATH_MAX
+#define PATH_MAX 1023 /* maximum size of path name on OS */
+#endif
+
+void
+add_shared_symbol_files ()
+{
+ void *desc;
+ struct link_map *ld_map, *lm, lms;
+ struct minimal_symbol *minsym;
+ struct objfile *objfile;
+ char *path_name;
+
+ if (! inferior_pid)
+ {
+ warning ("The program has not yet been started.");
+ return;
+ }
+
+ objfile = symbol_file_add (LIBC_FILE, 0, 0, 0, 0, 1);
+ minsym = lookup_minimal_symbol (LINKS_MAP_POINTER, objfile);
+
+ ld_map = (struct link_map *)
+ read_memory_integer (((int)SYMBOL_VALUE_ADDRESS(minsym) + SHARED_OFFSET), 4);
+ lm = ld_map;
+ while (lm)
+ {
+ int local_errno = 0;
+
+ read_memory ((CORE_ADDR)lm, (char*)&lms, sizeof (struct link_map));
+ if (lms.l_name)
+ {
+ if (target_read_string ((CORE_ADDR)lms.l_name, &path_name,
+ PATH_MAX, &local_errno))
+ {
+ symbol_file_add (path_name, 1, lms.l_addr, 0, 0, 0);
+ free(path_name);
+ }
+ }
+ /* traverse links in reverse order so that we get the
+ the symbols the user actually gets. */
+ lm = lms.l_prev;
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+#if defined(_ES_MP)
+
+#include <sys/regset.h>
+
+unsigned int
+m88k_harris_core_register_addr (regno, reg_ptr)
+ int regno, reg_ptr;
+{
+ unsigned int word_offset;
+
+ switch (regno)
+ {
+ case PSR_REGNUM:
+ word_offset = R_EPSR;
+ break;
+ case FPSR_REGNUM:
+ word_offset = R_FPSR;
+ break;
+ case FPCR_REGNUM:
+ word_offset = R_FPCR;
+ break;
+ case SXIP_REGNUM:
+ word_offset = R_EXIP;
+ break;
+ case SNIP_REGNUM:
+ word_offset = R_ENIP;
+ break;
+ case SFIP_REGNUM:
+ word_offset = R_EFIP;
+ break;
+ default:
+ if (regno <= FP_REGNUM)
+ word_offset = regno;
+ else
+ word_offset = ((regno - X0_REGNUM) * 4);
+ }
+ return (word_offset * 4);
+}
+
+#endif /* _ES_MP */
+
+void
+_initialize_m88k_nat()
+{
+#ifdef _ES_MP
+ /* Enable 88110 support, as we don't support the 88100 under ES/MP. */
+
+ target_is_m88110 = 1;
+#elif defined(_CX_UX)
+ /* Determine whether we're running on an 88100 or an 88110. */
+ target_is_m88110 = (sinfo(SYSMACHINE,0) == SYS5800);
+#endif /* _CX_UX */
+}
+
+#ifdef _ES_MP
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi = 0 ; regi < R_R31 ; regi++)
+ {
+ supply_register (regi, (char *) (regp + regi));
+ }
+ supply_register (PSR_REGNUM, (char *) (regp + R_EPSR));
+ supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
+ supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
+ supply_register (SXIP_REGNUM, (char *) (regp + R_EXIP));
+ supply_register (SNIP_REGNUM, (char *) (regp + R_ENIP));
+ supply_register (SFIP_REGNUM, (char *) (regp + R_EFIP));
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ char *from;
+
+ for (regi = FP0_REGNUM ; regi <= FPLAST_REGNUM ; regi++)
+ {
+ from = (char *) &((*fpregsetp)[regi-FP0_REGNUM]);
+ supply_register (regi, from);
+ }
+}
+
+#endif /* _ES_MP */
+
+#ifdef _CX_UX
+
+#include <sys/regset.h>
+
+unsigned int m88k_harris_core_register_addr(int regno, int reg_ptr)
+{
+ unsigned int word_offset;
+
+ switch (regno) {
+ case PSR_REGNUM : word_offset = R_PSR; break;
+ case FPSR_REGNUM : word_offset = R_FPSR; break;
+ case FPCR_REGNUM : word_offset = R_FPCR; break;
+ case SXIP_REGNUM : word_offset = R_XIP; break;
+ case SNIP_REGNUM : word_offset = R_NIP; break;
+ case SFIP_REGNUM : word_offset = R_FIP; break;
+ default :
+ if (regno <= FP_REGNUM)
+ word_offset = regno;
+ else
+ word_offset = ((regno - X0_REGNUM) * 4) + R_X0;
+ }
+ return (word_offset * 4);
+}
+
+#endif /* _CX_UX */
diff --git a/contrib/gdb/gdb/dbxread.c b/contrib/gdb/gdb/dbxread.c
new file mode 100644
index 0000000..2bc60be
--- /dev/null
+++ b/contrib/gdb/gdb/dbxread.c
@@ -0,0 +1,2556 @@
+/* Read dbx symbol tables and convert to internal format, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module provides three functions: dbx_symfile_init,
+ which initializes to read a symbol file; dbx_new_init, which
+ discards existing cached information when all symbols are being
+ discarded; and dbx_symfile_read, which reads a symbol table
+ from a file.
+
+ dbx_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. dbx_psymtab_to_symtab() is the function that does this */
+
+#include "defs.h"
+#include "gdb_string.h"
+
+#if defined(USG) || defined(__CYGNUSCLIB__)
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#include "obstack.h"
+#include <sys/param.h>
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#include "gdb_stat.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "target.h"
+#include "gdbcore.h" /* for bfd stuff */
+#include "libaout.h" /* FIXME Secret internal BFD stuff for a.out */
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "demangle.h"
+#include "language.h" /* Needed inside partial-stab.h */
+#include "complaints.h"
+
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h" /* We always use GNU stabs, not native, now */
+
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc {
+
+ /* Offset within the file symbol table of first local symbol for this
+ file. */
+
+ int ldsymoff;
+
+ /* Length (in bytes) of the section of the symbol table devoted to
+ this file's symbols (actually, the section bracketed may contain
+ more than just this file's symbols). If ldsymlen is 0, the only
+ reason for this thing's existence is the dependency list. Nothing
+ else will happen when it is read in. */
+
+ int ldsymlen;
+
+ /* The size of each symbol in the symbol file (in external form). */
+
+ int symbol_size;
+
+ /* Further information needed to locate the symbols if they are in
+ an ELF file. */
+
+ int symbol_offset;
+ int string_offset;
+ int file_string_offset;
+};
+
+#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
+#define LDSYMLEN(p) (((struct symloc *)((p)->read_symtab_private))->ldsymlen)
+#define SYMLOC(p) ((struct symloc *)((p)->read_symtab_private))
+#define SYMBOL_SIZE(p) (SYMLOC(p)->symbol_size)
+#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
+#define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
+#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
+
+
+/* Macro to determine which symbols to ignore when reading the first symbol
+ of a file. Some machines override this definition. */
+#ifndef IGNORE_SYMBOL
+/* This code is used on Ultrix systems. Ignore it */
+#define IGNORE_SYMBOL(type) (type == (int)N_NSYMS)
+#endif
+
+/* Remember what we deduced to be the source language of this psymtab. */
+
+static enum language psymtab_language = language_unknown;
+
+/* Nonzero means give verbose info on gdb action. From main.c. */
+extern int info_verbose;
+
+/* The BFD for this file -- implicit parameter to next_symbol_text. */
+
+static bfd *symfile_bfd;
+
+/* The size of each symbol in the symbol file (in external form).
+ This is set by dbx_symfile_read when building psymtabs, and by
+ dbx_psymtab_to_symtab when building symtabs. */
+
+static unsigned symbol_size;
+
+/* This is the offset of the symbol table in the executable file */
+static unsigned symbol_table_offset;
+
+/* This is the offset of the string table in the executable file */
+static unsigned string_table_offset;
+
+/* For elf+stab executables, the n_strx field is not a simple index
+ into the string table. Instead, each .o file has a base offset
+ in the string table, and the associated symbols contain offsets
+ from this base. The following two variables contain the base
+ offset for the current and next .o files. */
+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;
+
+/* The lowest text address we have yet encountered. This is needed
+ because in an a.out file, there is no header field which tells us
+ what address the program is actually going to be loaded at, so we
+ need to make guesses based on the symbols (which *are* relocated to
+ reflect the address it will be loaded at). */
+static CORE_ADDR lowest_text_address;
+
+/* Complaints about the symbols we have encountered. */
+
+struct complaint lbrac_complaint =
+ {"bad block start address patched", 0, 0};
+
+struct complaint string_table_offset_complaint =
+ {"bad string table offset in symbol %d", 0, 0};
+
+struct complaint unknown_symtype_complaint =
+ {"unknown symbol type %s", 0, 0};
+
+struct complaint unknown_symchar_complaint =
+ {"unknown symbol descriptor `%c'", 0, 0};
+
+struct complaint lbrac_rbrac_complaint =
+ {"block start larger than block end", 0, 0};
+
+struct complaint lbrac_unmatched_complaint =
+ {"unmatched N_LBRAC before symtab pos %d", 0, 0};
+
+struct complaint lbrac_mismatch_complaint =
+ {"N_LBRAC/N_RBRAC symbol mismatch at symtab pos %d", 0, 0};
+
+struct complaint repeated_header_complaint =
+ {"\"repeated\" header file %s not previously seen, at symtab pos %d", 0, 0};
+
+/* During initial symbol readin, we need to have a structure to keep
+ track of which psymtabs have which bincls in them. This structure
+ is used during readin to setup the list of dependencies within each
+ partial symbol table. */
+
+struct header_file_location
+{
+ char *name; /* Name of header file */
+ int instance; /* See above */
+ struct partial_symtab *pst; /* Partial symtab that has the
+ BINCL/EINCL defs for this file */
+};
+
+/* The actual list and controling variables */
+static struct header_file_location *bincl_list, *next_bincl;
+static int bincls_allocated;
+
+/* Local function prototypes */
+
+static void
+free_header_files PARAMS ((void));
+
+static void
+init_header_files PARAMS ((void));
+
+static void
+read_ofile_symtab PARAMS ((struct partial_symtab *));
+
+static void
+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));
+
+static void
+free_bincl_list PARAMS ((struct objfile *));
+
+static struct partial_symtab *
+find_corresponding_bincl_psymtab PARAMS ((char *, int));
+
+static void
+add_bincl_to_list PARAMS ((struct partial_symtab *, char *, int));
+
+static void
+init_bincl_list PARAMS ((int, struct objfile *));
+
+static char *
+dbx_next_symbol_text PARAMS ((struct objfile *));
+
+static void
+fill_symbuf PARAMS ((bfd *));
+
+static void
+dbx_symfile_init PARAMS ((struct objfile *));
+
+static void
+dbx_new_init PARAMS ((struct objfile *));
+
+static void
+dbx_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+dbx_symfile_finish PARAMS ((struct objfile *));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, int, struct objfile *));
+
+static void
+add_new_header_file PARAMS ((char *, int));
+
+static void
+add_old_header_file PARAMS ((char *, int));
+
+static void
+add_this_object_header_file PARAMS ((int));
+
+/* Free up old header file tables */
+
+static void
+free_header_files ()
+{
+ register int i;
+
+ if (header_files != NULL)
+ {
+ for (i = 0; i < n_header_files; i++)
+ {
+ free (header_files[i].name);
+ }
+ free ((PTR)header_files);
+ header_files = NULL;
+ n_header_files = 0;
+ }
+ if (this_object_header_files)
+ {
+ free ((PTR)this_object_header_files);
+ this_object_header_files = NULL;
+ }
+ n_allocated_header_files = 0;
+ n_allocated_this_object_header_files = 0;
+}
+
+/* Allocate new header file tables */
+
+static void
+init_header_files ()
+{
+ n_header_files = 0;
+ n_allocated_header_files = 10;
+ header_files = (struct header_file *)
+ xmalloc (10 * sizeof (struct header_file));
+
+ n_allocated_this_object_header_files = 10;
+ this_object_header_files = (int *) xmalloc (10 * sizeof (int));
+}
+
+/* Add header file number I for this object file
+ at the next successive FILENUM. */
+
+static void
+add_this_object_header_file (i)
+ int i;
+{
+ if (n_this_object_header_files == n_allocated_this_object_header_files)
+ {
+ n_allocated_this_object_header_files *= 2;
+ this_object_header_files
+ = (int *) xrealloc ((char *) this_object_header_files,
+ n_allocated_this_object_header_files * sizeof (int));
+ }
+
+ this_object_header_files[n_this_object_header_files++] = i;
+}
+
+/* Add to this file an "old" header file, one already seen in
+ a previous object file. NAME is the header file's name.
+ INSTANCE is its instance code, to select among multiple
+ symbol tables for the same header file. */
+
+static void
+add_old_header_file (name, instance)
+ char *name;
+ int instance;
+{
+ register struct header_file *p = header_files;
+ register int i;
+
+ for (i = 0; i < n_header_files; i++)
+ if (STREQ (p[i].name, name) && instance == p[i].instance)
+ {
+ add_this_object_header_file (i);
+ return;
+ }
+ complain (&repeated_header_complaint, name, symnum);
+}
+
+/* Add to this file a "new" header file: definitions for its types follow.
+ NAME is the header file's name.
+ Most often this happens only once for each distinct header file,
+ but not necessarily. If it happens more than once, INSTANCE has
+ a different value each time, and references to the header file
+ use INSTANCE values to select among them.
+
+ dbx output contains "begin" and "end" markers for each new header file,
+ but at this level we just need to know which files there have been;
+ so we record the file when its "begin" is seen and ignore the "end". */
+
+static void
+add_new_header_file (name, instance)
+ char *name;
+ int instance;
+{
+ register int i;
+
+ /* Make sure there is room for one more header file. */
+
+ if (n_header_files == n_allocated_header_files)
+ {
+ n_allocated_header_files *= 2;
+ header_files = (struct header_file *)
+ xrealloc ((char *) header_files,
+ (n_allocated_header_files * sizeof (struct header_file)));
+ }
+
+ /* Create an entry for this header file. */
+
+ i = n_header_files++;
+ header_files[i].name = savestring (name, strlen(name));
+ header_files[i].instance = instance;
+ header_files[i].length = 10;
+ header_files[i].vector
+ = (struct type **) xmalloc (10 * sizeof (struct type *));
+ memset (header_files[i].vector, 0, 10 * sizeof (struct type *));
+
+ add_this_object_header_file (i);
+}
+
+#if 0
+static struct type **
+explicit_lookup_type (real_filenum, index)
+ int real_filenum, index;
+{
+ register struct header_file *f = &header_files[real_filenum];
+
+ if (index >= f->length)
+ {
+ f->length *= 2;
+ f->vector = (struct type **)
+ xrealloc (f->vector, f->length * sizeof (struct type *));
+ memset (&f->vector[f->length / 2],
+ '\0', f->length * sizeof (struct type *) / 2);
+ }
+ return &f->vector[index];
+}
+#endif
+
+static void
+record_minimal_symbol (name, address, type, objfile)
+ char *name;
+ CORE_ADDR address;
+ int type;
+ struct objfile *objfile;
+{
+ enum minimal_symbol_type ms_type;
+ int section;
+
+ switch (type)
+ {
+ 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;
+ 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:
+ 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;
+
+ /* Check for __DYNAMIC, which is used by Sun shared libraries.
+ Record it as global even if it's local, not global, so
+ lookup_minimal_symbol can find it. We don't check symbol_leading_char
+ because for SunOS4 it always is '_'. */
+ if (name[8] == 'C' && STREQ ("__DYNAMIC", name))
+ ms_type = mst_data;
+
+ /* Same with virtual function tables, both global and static. */
+ {
+ char *tempstring = name;
+ if (tempstring[0] == bfd_get_symbol_leading_char (objfile->obfd))
+ ++tempstring;
+ 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;
+ }
+
+ 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,
+ NULL,
+ section,
+ objfile);
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to dbx_symfile_init, which
+ put all the relevant info into a "struct dbx_symfile_info",
+ hung off the objfile structure.
+
+ SECTION_OFFSETS contains offsets relative to which the symbols in the
+ various sections are (depending where the sections were actually loaded).
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file). */
+
+static void
+dbx_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline; /* FIXME comments above */
+{
+ bfd *sym_bfd;
+ 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), "pe", 2))
+ || (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)
+ perror_with_name (objfile->name);
+
+ /* If we are reinitializing, or if we have never loaded syms yet, init */
+ if (mainline
+ || objfile->global_psymbols.size == 0
+ || objfile->static_psymbols.size == 0)
+ init_psymbol_list (objfile, DBX_SYMCOUNT (objfile));
+
+ symbol_size = DBX_SYMBOL_SIZE (objfile);
+ symbol_table_offset = DBX_SYMTAB_OFFSET (objfile);
+
+ pending_blocks = 0;
+ back_to = make_cleanup (really_free_pendings, 0);
+
+ init_minimal_symbol_collection ();
+ make_cleanup (discard_minimal_symbols, 0);
+
+ /* Now that the symbol table data of the executable file are all in core,
+ process them and define symbols accordingly. */
+
+ read_dbx_symtab (section_offsets, objfile,
+ DBX_TEXT_ADDR (objfile),
+ DBX_TEXT_SIZE (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);
+
+ do_cleanups (back_to);
+}
+
+/* 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 void
+dbx_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+ init_header_files ();
+}
+
+
+/* dbx_symfile_init ()
+ is the dbx-specific initialization routine for reading symbols.
+ It is passed a struct objfile which contains, among other things,
+ the BFD for the file whose symbols are being read, and a slot for a pointer
+ to "private data" which we fill with goodies.
+
+ We read the string table into malloc'd space and stash a pointer to it.
+
+ Since BFD doesn't know how to read debug symbols in a format-independent
+ way (and may never do so...), we have to do it ourselves. We will never
+ be called unless this is an a.out (or very similar) file.
+ FIXME, there should be a cleaner peephole into the BFD environment here. */
+
+#define DBX_STRINGTAB_SIZE_SIZE sizeof(long) /* FIXME */
+
+static void
+dbx_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ asection *text_sect;
+ unsigned char size_temp[DBX_STRINGTAB_SIZE_SIZE];
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (PTR)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+
+ /* FIXME POKING INSIDE BFD DATA STRUCTURES */
+#define STRING_TABLE_OFFSET (sym_bfd->origin + obj_str_filepos (sym_bfd))
+#define SYMBOL_TABLE_OFFSET (sym_bfd->origin + obj_sym_filepos (sym_bfd))
+
+ /* FIXME POKING INSIDE BFD DATA STRUCTURES */
+
+ DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL;
+
+ text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!text_sect)
+ error ("Can't find .text section in symbol file");
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+ DBX_SYMBOL_SIZE (objfile) = obj_symbol_entry_size (sym_bfd);
+ DBX_SYMCOUNT (objfile) = bfd_get_symcount (sym_bfd);
+ DBX_SYMTAB_OFFSET (objfile) = SYMBOL_TABLE_OFFSET;
+
+ /* Read the string table and stash it away in the psymbol_obstack. It is
+ only needed as long as we need to expand psymbols into full symbols,
+ so when we blow away the psymbol the string table goes away as well.
+ Note that gdb used to use the results of attempting to malloc the
+ string table, based on the size it read, as a form of sanity check
+ for botched byte swapping, on the theory that a byte swapped string
+ table size would be so totally bogus that the malloc would fail. Now
+ that we put in on the psymbol_obstack, we can't do this since gdb gets
+ a fatal error (out of virtual memory) if the size is bogus. We can
+ however at least check to see if the size is less than the size of
+ the size field itself, or larger than the size of the entire file.
+ Note that all valid string tables have a size greater than zero, since
+ the bytes used to hold the size are included in the count. */
+
+ if (STRING_TABLE_OFFSET == 0)
+ {
+ /* It appears that with the existing bfd code, STRING_TABLE_OFFSET
+ will never be zero, even when there is no string table. This
+ would appear to be a bug in bfd. */
+ DBX_STRINGTAB_SIZE (objfile) = 0;
+ DBX_STRINGTAB (objfile) = NULL;
+ }
+ else
+ {
+ val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+
+ memset ((PTR) size_temp, 0, sizeof (size_temp));
+ val = bfd_read ((PTR) size_temp, sizeof (size_temp), 1, sym_bfd);
+ if (val < 0)
+ {
+ perror_with_name (name);
+ }
+ else if (val == 0)
+ {
+ /* With the existing bfd code, STRING_TABLE_OFFSET will be set to
+ EOF if there is no string table, and attempting to read the size
+ from EOF will read zero bytes. */
+ DBX_STRINGTAB_SIZE (objfile) = 0;
+ DBX_STRINGTAB (objfile) = NULL;
+ }
+ else
+ {
+ /* Read some data that would appear to be the string table size.
+ If there really is a string table, then it is probably the right
+ size. Byteswap if necessary and validate the size. Note that
+ the minimum is DBX_STRINGTAB_SIZE_SIZE. If we just read some
+ random data that happened to be at STRING_TABLE_OFFSET, because
+ bfd can't tell us there is no string table, the sanity checks may
+ or may not catch this. */
+ DBX_STRINGTAB_SIZE (objfile) = bfd_h_get_32 (sym_bfd, size_temp);
+
+ if (DBX_STRINGTAB_SIZE (objfile) < sizeof (size_temp)
+ || 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));
+ OBJSTAT (objfile, sz_strtab += DBX_STRINGTAB_SIZE (objfile));
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, STRING_TABLE_OFFSET, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), DBX_STRINGTAB_SIZE (objfile), 1,
+ sym_bfd);
+ if (val != DBX_STRINGTAB_SIZE (objfile))
+ perror_with_name (name);
+ }
+ }
+}
+
+/* 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. */
+
+static void
+dbx_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile->sym_stab_info);
+ }
+ free_header_files ();
+}
+
+
+/* Buffer for reading the symbol table entries. */
+static struct internal_nlist symbuf[4096];
+static int symbuf_idx;
+static int symbuf_end;
+
+/* Name of last function encountered. Used in Solaris to approximate
+ object file boundaries. */
+static char *last_function_name;
+
+/* The address in memory of the string table of the object file we are
+ reading (which might not be the "main" object file, but might be a
+ shared library or some other dynamically loaded thing). This is
+ set by read_dbx_symtab when building psymtabs, and by
+ read_ofile_symtab when building symtabs, and is used only by
+ next_symbol_text. FIXME: If that is true, we don't need it when
+ building psymtabs, right? */
+static char *stringtab_global;
+
+/* These variables are used to control fill_symbuf when the stabs
+ symbols are not contiguous (as may be the case when a COFF file is
+ linked using --split-by-reloc). */
+static struct stab_section_list *symbuf_sections;
+static unsigned int symbuf_left;
+static unsigned int symbuf_read;
+
+/* Refill the symbol table input buffer
+ and set the variables that control fetching entries from it.
+ Reports an error if no data available.
+ This function can read past the end of the symbol table
+ (into the string table) but this does no harm. */
+
+static void
+fill_symbuf (sym_bfd)
+ bfd *sym_bfd;
+{
+ unsigned int count;
+ int nbytes;
+
+ if (symbuf_sections == NULL)
+ count = sizeof (symbuf);
+ else
+ {
+ if (symbuf_left <= 0)
+ {
+ file_ptr filepos = symbuf_sections->section->filepos;
+ if (bfd_seek (sym_bfd, filepos, SEEK_SET) != 0)
+ perror_with_name (bfd_get_filename (sym_bfd));
+ symbuf_left = bfd_section_size (sym_bfd, symbuf_sections->section);
+ symbol_table_offset = filepos - symbuf_read;
+ symbuf_sections = symbuf_sections->next;
+ }
+
+ count = symbuf_left;
+ if (count > sizeof (symbuf))
+ count = sizeof (symbuf);
+ }
+
+ nbytes = bfd_read ((PTR)symbuf, count, 1, sym_bfd);
+ if (nbytes < 0)
+ perror_with_name (bfd_get_filename (sym_bfd));
+ else if (nbytes == 0)
+ error ("Premature end of file reading symbol table");
+ symbuf_end = nbytes / symbol_size;
+ symbuf_idx = 0;
+ symbuf_left -= nbytes;
+ symbuf_read += nbytes;
+}
+
+#define SWAP_SYMBOL(symp, abfd) \
+ { \
+ (symp)->n_strx = bfd_h_get_32(abfd, \
+ (unsigned char *)&(symp)->n_strx); \
+ (symp)->n_desc = bfd_h_get_16 (abfd, \
+ (unsigned char *)&(symp)->n_desc); \
+ (symp)->n_value = bfd_h_get_32 (abfd, \
+ (unsigned char *)&(symp)->n_value); \
+ }
+
+/* Invariant: The symbol pointed to by symbuf_idx is the first one
+ that hasn't been swapped. Swap the symbol at the same time
+ that symbuf_idx is incremented. */
+
+/* dbx allows the text of a symbol name to be continued into the
+ next symbol name! When such a continuation is encountered
+ (a \ at the end of the text of a name)
+ call this function to get the continuation. */
+
+static char *
+dbx_next_symbol_text (objfile)
+ struct objfile *objfile;
+{
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (symfile_bfd);
+ symnum++;
+ SWAP_SYMBOL(&symbuf[symbuf_idx], symfile_bfd);
+ OBJSTAT (objfile, n_stabs++);
+ return symbuf[symbuf_idx++].n_strx + stringtab_global
+ + file_string_table_offset;
+}
+
+/* Initialize the list of bincls to contain none and have some
+ allocated. */
+
+static void
+init_bincl_list (number, objfile)
+ int number;
+ struct objfile *objfile;
+{
+ bincls_allocated = number;
+ next_bincl = bincl_list = (struct header_file_location *)
+ xmmalloc (objfile -> md, bincls_allocated * sizeof(struct header_file_location));
+}
+
+/* Add a bincl to the list. */
+
+static void
+add_bincl_to_list (pst, name, instance)
+ struct partial_symtab *pst;
+ char *name;
+ int instance;
+{
+ if (next_bincl >= bincl_list + bincls_allocated)
+ {
+ int offset = next_bincl - bincl_list;
+ bincls_allocated *= 2;
+ bincl_list = (struct header_file_location *)
+ xmrealloc (pst->objfile->md, (char *)bincl_list,
+ bincls_allocated * sizeof (struct header_file_location));
+ next_bincl = bincl_list + offset;
+ }
+ next_bincl->pst = pst;
+ next_bincl->instance = instance;
+ next_bincl++->name = name;
+}
+
+/* Given a name, value pair, find the corresponding
+ bincl in the list. Return the partial symtab associated
+ with that header_file_location. */
+
+static struct partial_symtab *
+find_corresponding_bincl_psymtab (name, instance)
+ char *name;
+ int instance;
+{
+ struct header_file_location *bincl;
+
+ for (bincl = bincl_list; bincl < next_bincl; bincl++)
+ if (bincl->instance == instance
+ && STREQ (name, bincl->name))
+ return bincl->pst;
+
+ complain (&repeated_header_complaint, name, symnum);
+ return (struct partial_symtab *) 0;
+}
+
+/* Free the storage allocated for the bincl list. */
+
+static void
+free_bincl_list (objfile)
+ struct objfile *objfile;
+{
+ mfree (objfile -> md, (PTR)bincl_list);
+ 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;
+ char *name;
+
+ /* 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;
+ }
+
+ name = (char *) bfd_asymbol_name (*rel->sym_ptr_ptr);
+ prim_record_minimal_symbol
+ (obsavestring (name, strlen (name), &objfile -> symbol_obstack),
+ 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.
+ SYMFILE_NAME is the name of the file we are reading from
+ and SECTION_OFFSETS is the set of offsets for the various sections
+ of the file (a set of zeros if the mainline program). */
+
+static void
+read_dbx_symtab (section_offsets, objfile, text_addr, text_size)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+ CORE_ADDR text_addr;
+ int text_size;
+{
+ register struct internal_nlist *bufp = 0; /* =0 avoids gcc -Wall glitch */
+ register char *namestring;
+ int nsl;
+ int past_first_source_file = 0;
+ CORE_ADDR last_o_file_start = 0;
+ CORE_ADDR last_function_start = 0;
+ struct cleanup *back_to;
+ bfd *abfd;
+
+ /* Current partial symtab */
+ struct partial_symtab *pst;
+
+ /* List of current psymtab's include files */
+ char **psymtab_include_list;
+ int includes_allocated;
+ int includes_used;
+
+ /* Index within current psymtab dependency list */
+ struct partial_symtab **dependency_list;
+ int dependencies_used, dependencies_allocated;
+
+ /* FIXME. We probably want to change stringtab_global rather than add this
+ while processing every symbol entry. FIXME. */
+ file_string_table_offset = 0;
+ next_file_string_table_offset = 0;
+
+ stringtab_global = DBX_STRINGTAB (objfile);
+
+ pst = (struct partial_symtab *) 0;
+
+ includes_allocated = 30;
+ includes_used = 0;
+ psymtab_include_list = (char **) alloca (includes_allocated *
+ sizeof (char *));
+
+ dependencies_allocated = 30;
+ dependencies_used = 0;
+ dependency_list =
+ (struct partial_symtab **) alloca (dependencies_allocated *
+ sizeof (struct partial_symtab *));
+
+ /* Init bincl list */
+ init_bincl_list (20, objfile);
+ back_to = make_cleanup (free_bincl_list, objfile);
+
+ last_source_file = NULL;
+
+ lowest_text_address = (CORE_ADDR)-1;
+
+ symfile_bfd = objfile->obfd; /* For next_text_symbol */
+ abfd = objfile->obfd;
+ symbuf_end = symbuf_idx = 0;
+ next_symbol_text_func = dbx_next_symbol_text;
+
+ for (symnum = 0; symnum < DBX_SYMCOUNT (objfile); symnum++)
+ {
+ /* Get the symbol for this run and pull out some info */
+ QUIT; /* allow this to be interruptable */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (abfd);
+ bufp = &symbuf[symbuf_idx++];
+
+ /*
+ * Special case to speed up readin.
+ */
+ if (bufp->n_type == (unsigned char)N_SLINE) continue;
+
+ SWAP_SYMBOL (bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ /* Ok. There is a lot of code duplicated in the rest of this
+ switch statement (for efficiency reasons). Since I don't
+ like duplicating code, I will do my penance here, and
+ describe the code which is duplicated:
+
+ *) The assignment to namestring.
+ *) The call to strchr.
+ *) The addition of a partial symbol the the two partial
+ symbol lists. This last is a large section of code, so
+ I've imbedded it in the following macro.
+ */
+
+/* Set namestring based on bufp. If the string table index is invalid,
+ give a fake name, and print a single error message per symbol file read,
+ rather than abort the symbol reading or flood the user with messages. */
+
+/*FIXME: Too many adds and indirections in here for the inner loop. */
+#define SET_NAMESTRING()\
+ if (((unsigned)bufp->n_strx + file_string_table_offset) >= \
+ DBX_STRINGTAB_SIZE (objfile)) { \
+ complain (&string_table_offset_complaint, symnum); \
+ namestring = "<bad string table offset>"; \
+ } else \
+ namestring = bufp->n_strx + file_string_table_offset + \
+ DBX_STRINGTAB (objfile)
+
+#define CUR_SYMBOL_TYPE bufp->n_type
+#define CUR_SYMBOL_VALUE bufp->n_value
+#define DBXREAD_ONLY
+#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms)\
+ start_psymtab(ofile, secoff, fname, low, symoff, global_syms, static_syms)
+#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps)\
+ end_psymtab(pst,ilist,ninc,c_off,c_text,dep_list,n_deps)
+
+#include "partial-stab.h"
+ }
+
+ /* If there's stuff to be cleaned up, clean it up. */
+ if (DBX_SYMCOUNT (objfile) > 0 /* We have some syms */
+/*FIXME, does this have a bug at start address 0? */
+ && last_o_file_start
+ && objfile -> ei.entry_point < bufp->n_value
+ && objfile -> ei.entry_point >= last_o_file_start)
+ {
+ objfile -> ei.entry_file_lowpc = last_o_file_start;
+ objfile -> ei.entry_file_highpc = bufp->n_value;
+ }
+
+ if (pst)
+ {
+ end_psymtab (pst, psymtab_include_list, includes_used,
+ 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);
+ }
+
+ do_cleanups (back_to);
+}
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+
+struct partial_symtab *
+start_psymtab (objfile, section_offsets,
+ filename, textlow, ldsymoff, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ CORE_ADDR textlow;
+ int ldsymoff;
+ struct partial_symbol **global_syms;
+ struct partial_symbol **static_syms;
+{
+ struct partial_symtab *result =
+ start_psymtab_common(objfile, section_offsets,
+ filename, textlow, global_syms, static_syms);
+
+ result->read_symtab_private = (char *)
+ obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct symloc));
+ LDSYMOFF(result) = ldsymoff;
+ result->read_symtab = dbx_psymtab_to_symtab;
+ SYMBOL_SIZE(result) = symbol_size;
+ SYMBOL_OFFSET(result) = symbol_table_offset;
+ STRING_OFFSET(result) = string_table_offset;
+ FILE_STRING_OFFSET(result) = file_string_table_offset;
+
+ /* If we're handling an ELF file, drag some section-relocation info
+ for this source file out of the ELF symbol table, to compensate for
+ Sun brain death. This replaces the section_offsets in this psymtab,
+ if successful. */
+ elfstab_offset_sections (objfile, result);
+
+ /* Deduce the source language from the filename for this psymtab. */
+ psymtab_language = deduce_language_from_filename (filename);
+
+ return result;
+}
+
+/* Close off the current usage of PST.
+ Returns PST or NULL if the partial symtab was empty and thrown away.
+
+ FIXME: List variables and peculiarities of same. */
+
+struct partial_symtab *
+end_psymtab (pst, include_list, num_includes, capping_symbol_offset,
+ capping_text, dependency_list, number_dependencies)
+ struct partial_symtab *pst;
+ char **include_list;
+ int num_includes;
+ int capping_symbol_offset;
+ CORE_ADDR capping_text;
+ struct partial_symtab **dependency_list;
+ int number_dependencies;
+{
+ int i;
+ struct objfile *objfile = pst -> objfile;
+
+ if (capping_symbol_offset != -1)
+ LDSYMLEN(pst) = capping_symbol_offset - LDSYMOFF(pst);
+ pst->texthigh = capping_text;
+
+#ifdef SOFUN_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.
+ The first trick is in partial-stab.h: if we see a static
+ or global function, and the textlow for the current pst
+ is still 0, then we use that function's address for
+ the textlow of the pst. */
+
+ /* Now, to fill in texthigh, we remember the last function seen
+ in the .o file (also in partial-stab.h). Also, there's a hack in
+ bfd/elf.c and gdb/elfread.c to pass the ELF st_size field
+ to here via the misc_info field. Therefore, we can fill in
+ a reliable texthigh by taking the address plus size of the
+ last function in the file. */
+
+ if (pst->texthigh == 0 && last_function_name) {
+ char *p;
+ int n;
+ struct minimal_symbol *minsym;
+
+ p = strchr (last_function_name, ':');
+ if (p == NULL)
+ p = last_function_name;
+ n = p - last_function_name;
+ p = alloca (n + 1);
+ strncpy (p, last_function_name, n);
+ p[n] = 0;
+
+ minsym = lookup_minimal_symbol (p, pst->filename, objfile);
+
+ if (minsym)
+ pst->texthigh = SYMBOL_VALUE_ADDRESS (minsym) +
+ (long) MSYMBOL_INFO (minsym);
+
+ last_function_name = NULL;
+ }
+
+ /* 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 SOFUN_ADDRESS_MAYBE_MISSING. */
+ pst->textlow = pst->texthigh;
+
+ /* If we know our own starting text address, then walk through all other
+ psymtabs for this objfile, and if any didn't know their ending text
+ address, set it to our starting address. Take care to not set our
+ 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;
+ /* if this file has only data, then make textlow match texthigh */
+ if (p1->textlow == 0)
+ p1->textlow = p1->texthigh;
+ }
+ }
+ }
+
+ /* End of kludge for patching Solaris textlow and texthigh. */
+#endif /* SOFUN_ADDRESS_MAYBE_MISSING. */
+
+ pst->n_global_syms =
+ objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset);
+ pst->n_static_syms =
+ objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset);
+
+ pst->number_of_dependencies = number_dependencies;
+ if (number_dependencies)
+ {
+ pst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ number_dependencies * sizeof (struct partial_symtab *));
+ memcpy (pst->dependencies, dependency_list,
+ number_dependencies * sizeof (struct partial_symtab *));
+ }
+ else
+ pst->dependencies = 0;
+
+ for (i = 0; i < num_includes; i++)
+ {
+ struct partial_symtab *subpst =
+ allocate_psymtab (include_list[i], objfile);
+
+ subpst->section_offsets = pst->section_offsets;
+ subpst->read_symtab_private =
+ (char *) obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct symloc));
+ LDSYMOFF(subpst) =
+ LDSYMLEN(subpst) =
+ subpst->textlow =
+ subpst->texthigh = 0;
+
+ /* We could save slight bits of space by only making one of these,
+ shared by the entire set of include files. FIXME-someday. */
+ subpst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct partial_symtab *));
+ subpst->dependencies[0] = pst;
+ subpst->number_of_dependencies = 1;
+
+ subpst->globals_offset =
+ subpst->n_global_syms =
+ subpst->statics_offset =
+ subpst->n_static_syms = 0;
+
+ subpst->readin = 0;
+ subpst->symtab = 0;
+ subpst->read_symtab = pst->read_symtab;
+ }
+
+ sort_pst_symbols (pst);
+
+ /* If there is already a psymtab or symtab for a file of this name, remove it.
+ (If there is a symtab, more drastic things also happen.)
+ This happens in VxWorks. */
+ 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. */
+ /* 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 */
+
+ 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 */
+
+ pst->next = pst->objfile->free_psymtabs;
+ pst->objfile->free_psymtabs = pst;
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *)NULL;
+ }
+ return pst;
+}
+
+static void
+dbx_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ /* Read in all partial symtabs on which this one is dependent */
+ for (i = 0; i < pst->number_of_dependencies; i++)
+ if (!pst->dependencies[i]->readin)
+ {
+ /* Inform about additional files that need to be read in. */
+ if (info_verbose)
+ {
+ fputs_filtered (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ dbx_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ if (LDSYMLEN(pst)) /* Otherwise it's a dummy */
+ {
+ /* Init stuff necessary for reading in symbols */
+ stabsread_init ();
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+ file_string_table_offset = FILE_STRING_OFFSET (pst);
+ symbol_size = SYMBOL_SIZE (pst);
+
+ /* Read in this file's symbols */
+ bfd_seek (pst->objfile->obfd, SYMBOL_OFFSET (pst), SEEK_SET);
+ read_ofile_symtab (pst);
+ sort_symtab_syms (pst->symtab);
+
+ do_cleanups (old_chain);
+ }
+
+ pst->readin = 1;
+}
+
+/* Read in all of the symbols for a given psymtab for real.
+ Be verbose about it if the user wants that. */
+
+static void
+dbx_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ bfd *sym_bfd;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ if (LDSYMLEN(pst) || pst->number_of_dependencies)
+ {
+ /* Print the message now, before reading the string table,
+ to avoid disconcerting pauses. */
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ gdb_flush (gdb_stdout);
+ }
+
+ sym_bfd = pst->objfile->obfd;
+
+ next_symbol_text_func = dbx_next_symbol_text;
+
+ dbx_psymtab_to_symtab_1 (pst);
+
+ /* 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);
+
+ /* Finish up the debug error message. */
+ if (info_verbose)
+ printf_filtered ("done.\n");
+ }
+}
+
+/* Read in a defined section of a specific object file's symbols. */
+
+static void
+read_ofile_symtab (pst)
+ struct partial_symtab *pst;
+{
+ register char *namestring;
+ register struct internal_nlist *bufp;
+ unsigned char type;
+ unsigned max_symnum;
+ register bfd *abfd;
+ struct objfile *objfile;
+ int sym_offset; /* Offset to start of symbols to read */
+ int sym_size; /* Size of symbols to read */
+ CORE_ADDR text_offset; /* Start of text segment for symbols */
+ int text_size; /* Size of text segment for symbols */
+ struct section_offsets *section_offsets;
+
+ objfile = pst->objfile;
+ sym_offset = LDSYMOFF(pst);
+ sym_size = LDSYMLEN(pst);
+ text_offset = pst->textlow;
+ text_size = pst->texthigh - pst->textlow;
+ section_offsets = pst->section_offsets;
+
+ current_objfile = objfile;
+ subfile_stack = NULL;
+
+ stringtab_global = DBX_STRINGTAB (objfile);
+ last_source_file = NULL;
+
+ abfd = objfile->obfd;
+ symfile_bfd = objfile->obfd; /* Implicit param to next_text_symbol */
+ symbuf_end = symbuf_idx = 0;
+
+ /* It is necessary to actually read one symbol *before* the start
+ of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
+ occurs before the N_SO symbol.
+
+ Detecting this in read_dbx_symtab
+ would slow down initial readin, so we look for it here instead. */
+ if (!processing_acc_compilation && sym_offset >= (int)symbol_size)
+ {
+ bfd_seek (symfile_bfd, sym_offset - symbol_size, SEEK_CUR);
+ fill_symbuf (abfd);
+ bufp = &symbuf[symbuf_idx++];
+ SWAP_SYMBOL (bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ SET_NAMESTRING ();
+
+ 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
+ producer. */
+
+ if (processing_gcc_compilation)
+ {
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ }
+ }
+ else
+ {
+ /* The N_SO starting this symtab is the first symbol, so we
+ better not check the symbol before it. I'm not this can
+ happen, but it doesn't hurt to check for it. */
+ bfd_seek (symfile_bfd, sym_offset, SEEK_CUR);
+ processing_gcc_compilation = 0;
+ }
+
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf (abfd);
+ bufp = &symbuf[symbuf_idx];
+ if (bufp->n_type != (unsigned char)N_SO)
+ error("First symbol in segment of executable not a source symbol");
+
+ max_symnum = sym_size / symbol_size;
+
+ for (symnum = 0;
+ symnum < max_symnum;
+ symnum++)
+ {
+ QUIT; /* Allow this to be interruptable */
+ if (symbuf_idx == symbuf_end)
+ fill_symbuf(abfd);
+ bufp = &symbuf[symbuf_idx++];
+ SWAP_SYMBOL (bufp, abfd);
+ OBJSTAT (objfile, n_stabs++);
+
+ type = bufp->n_type;
+
+ SET_NAMESTRING ();
+
+ if (type & N_STAB) {
+ process_one_symbol (type, bufp->n_desc, bufp->n_value,
+ namestring, section_offsets, objfile);
+ }
+ /* We skip checking for a new .o or -l file; that should never
+ happen in this routine. */
+ else if (type == N_TEXT)
+ {
+ /* I don't think this code will ever be executed, because
+ the GCC_COMPILED_FLAG_SYMBOL usually is right before
+ the N_SO symbol which starts this source file.
+ However, there is no reason not to accept
+ the GCC_COMPILED_FLAG_SYMBOL anywhere. */
+
+ if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 1;
+ else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 2;
+
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ }
+ else if (type & N_EXT || type == (unsigned char)N_TEXT
+ || type == (unsigned char)N_NBTEXT
+ ) {
+ /* Global symbol: see if we came across a dbx defintion for
+ a corresponding symbol. If so, store the value. Remove
+ syms from the chain when their values are stored, but
+ search the whole chain, as there may be several syms from
+ different files with the same name. */
+ /* This is probably not true. Since the files will be read
+ in one at a time, each reference to a global symbol will
+ be satisfied in each file as it appears. So we skip this
+ section. */
+ ;
+ }
+ }
+
+ current_objfile = NULL;
+
+ /* In a Solaris elf file, this variable, which comes from the
+ value of the N_SO symbol, will still be 0. Luckily, text_offset,
+ which comes from pst->textlow is correct. */
+ if (last_source_start_addr == 0)
+ last_source_start_addr = text_offset;
+
+ /* In reordered executables last_source_start_addr may not be the
+ lower bound for this symtab, instead use text_offset which comes
+ from pst->textlow which is correct. */
+ if (last_source_start_addr > text_offset)
+ last_source_start_addr = text_offset;
+
+ pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+}
+
+
+/* This handles a single symbol from the symbol-file, building symbols
+ into a GDB symtab. It takes these arguments and an implicit argument.
+
+ TYPE is the type field of the ".stab" symbol entry.
+ DESC is the desc field of the ".stab" entry.
+ VALU is the value field of the ".stab" entry.
+ NAME is the symbol name, in our address space.
+ SECTION_OFFSETS is a set of amounts by which the sections of this object
+ file were relocated when it was loaded into memory.
+ All symbols that refer
+ to memory locations need to be offset by these amounts.
+ OBJFILE is the object file from which we are reading symbols.
+ It is used in end_symtab. */
+
+void
+process_one_symbol (type, desc, valu, name, section_offsets, objfile)
+ int type, desc;
+ CORE_ADDR valu;
+ char *name;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+#ifdef SUN_FIXED_LBRAC_BUG
+ /* If SUN_FIXED_LBRAC_BUG is defined, then it tells us whether we need
+ to correct the address of N_LBRAC's. If it is not defined, then
+ we never need to correct the addresses. */
+
+ /* This records the last pc address we've seen. We depend on there being
+ an SLINE or FUN or SO before the first LBRAC, since the variable does
+ not get reset in between reads of different symbol files. */
+ static CORE_ADDR last_pc_address;
+#endif
+
+ register struct context_stack *new;
+ /* This remembers the address of the start of a function. It is used
+ because in Solaris 2, N_LBRAC, N_RBRAC, and N_SLINE entries are
+ relative to the current function's start address. On systems
+ other than Solaris 2, this just holds the SECT_OFF_TEXT value, and is
+ used to relocate these symbol types rather than SECTION_OFFSETS. */
+ static CORE_ADDR function_start_offset;
+
+ /* 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;
+
+ /* The stab type used for the definition of the last function.
+ N_STSYM or N_GSYM for SunOS4 acc; N_FUN for other compilers. */
+ static int function_stab_type = 0;
+
+ 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. */
+ function_start_offset = ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
+ /* Something is wrong if we see real data before
+ seeing a source file name. */
+
+ if (last_source_file == NULL && type != (unsigned char)N_SO)
+ {
+ /* Ignore any symbols which appear before an N_SO symbol. Currently
+ no one puts symbols there, but we should deal gracefully with the
+ case. A complain()t might be in order (if !IGNORE_SYMBOL (type)),
+ but this should not be an error (). */
+ return;
+ }
+
+ switch (type)
+ {
+ case N_FUN:
+ case N_FNAME:
+
+ if (! strcmp (name, ""))
+ {
+ /* This N_FUN marks the end of a function. This closes off the
+ current block. */
+ within_function = 0;
+ new = pop_context ();
+
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ function_start_offset, function_start_offset + valu,
+ objfile);
+ break;
+ }
+
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ goto define_a_symbol;
+
+ case N_LBRAC:
+ /* This "symbol" just indicates the start of an inner lexical
+ context within a function. */
+
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (n_opt_found && desc == 1)
+ break;
+
+#if defined(BLOCK_ADDRESS_ABSOLUTE)
+ /* Relocate for dynamic loading (?). */
+ valu += function_start_offset;
+#else
+ if (block_address_function_relative)
+ /* Relocate for Sun ELF acc fn-relative syms. */
+ valu += function_start_offset;
+ else
+ /* On most machines, the block addresses are relative to the
+ N_SO, the linker did not relocate them (sigh). */
+ valu += last_source_start_addr;
+#endif
+
+#ifdef SUN_FIXED_LBRAC_BUG
+ if (!SUN_FIXED_LBRAC_BUG && valu < last_pc_address) {
+ /* Patch current LBRAC pc value to match last handy pc value */
+ complain (&lbrac_complaint);
+ valu = last_pc_address;
+ }
+#endif
+ new = push_context (desc, valu);
+ break;
+
+ case N_RBRAC:
+ /* This "symbol" just indicates the end of an inner lexical
+ context that was started with N_LBRAC. */
+
+ /* Ignore extra outermost context from SunPRO cc and acc. */
+ if (n_opt_found && desc == 1)
+ break;
+
+#if defined(BLOCK_ADDRESS_ABSOLUTE)
+ /* Relocate for dynamic loading (?). */
+ valu += function_start_offset;
+#else
+ if (block_address_function_relative)
+ /* Relocate for Sun ELF acc fn-relative syms. */
+ valu += function_start_offset;
+ else
+ /* On most machines, the block addresses are relative to the
+ N_SO, the linker did not relocate them (sigh). */
+ valu += last_source_start_addr;
+#endif
+
+ new = pop_context();
+ if (desc != new->depth)
+ complain (&lbrac_mismatch_complaint, symnum);
+
+ /* Some compilers put the variable decls inside of an
+ LBRAC/RBRAC block. This macro should be nonzero if this
+ is true. DESC is N_DESC from the N_RBRAC symbol.
+ GCC_P is true if we've detected the GCC_COMPILED_SYMBOL
+ or the GCC2_COMPILED_SYMBOL. */
+#if !defined (VARIABLES_INSIDE_BLOCK)
+#define VARIABLES_INSIDE_BLOCK(desc, gcc_p) 0
+#endif
+
+ /* Can only use new->locals as local symbols here if we're in
+ gcc or on a machine that puts them before the lbrack. */
+ if (!VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+ local_symbols = new->locals;
+
+ if (context_stack_depth
+ > !VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+ {
+ /* 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)
+ {
+ /* 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);
+ }
+ }
+ 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;
+ break;
+
+ case N_FN:
+ case N_FN_SEQ:
+ /* This kind of symbol indicates the start of an object file. */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+
+ case N_SO:
+ /* This type of symbol indicates the start of data
+ for one source file.
+ Finish the symbol table of the previous source file
+ (if any) and start accumulating a new symbol table. */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+
+ n_opt_found = 0;
+
+#ifdef SUN_FIXED_LBRAC_BUG
+ last_pc_address = valu; /* Save for SunOS bug circumcision */
+#endif
+
+#ifdef PCC_SOL_BROKEN
+ /* pcc bug, occasionally puts out SO for SOL. */
+ if (context_stack_depth > 0)
+ {
+ start_subfile (name, NULL);
+ break;
+ }
+#endif
+ if (last_source_file)
+ {
+ /* Check if previous symbol was also an N_SO (with some
+ sanity checks). If so, that one was actually the directory
+ name, and the current one is the real file name.
+ Patch things up. */
+ if (previous_stab_code == (unsigned char) N_SO)
+ {
+ patch_subfile_names (current_subfile, name);
+ break; /* Ignore repeated SOs */
+ }
+ end_symtab (valu, 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
+ included in the compilation of the main source file
+ (whose name was given in the N_SO symbol.) */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ start_subfile (name, current_subfile->dirname);
+ break;
+
+ case N_BINCL:
+ push_subfile ();
+ add_new_header_file (name, valu);
+ start_subfile (name, current_subfile->dirname);
+ break;
+
+ case N_EINCL:
+ start_subfile (pop_subfile (), current_subfile->dirname);
+ break;
+
+ case N_EXCL:
+ add_old_header_file (name, valu);
+ break;
+
+ case N_SLINE:
+ /* This type of "symbol" really just records
+ one line-number -- core-address correspondence.
+ Enter it in the line list for this symbol table. */
+ /* Relocate for dynamic loading and for ELF acc fn-relative syms. */
+ valu += function_start_offset;
+#ifdef SUN_FIXED_LBRAC_BUG
+ last_pc_address = valu; /* Save for SunOS bug circumcision */
+#endif
+ record_line (current_subfile, desc, valu);
+ break;
+
+ case N_BCOMM:
+ common_block_start (name, objfile);
+ break;
+
+ case N_ECOMM:
+ common_block_end (objfile);
+ break;
+
+ /* The following symbol types need to have the appropriate offset added
+ to their value; then we process symbol definitions in the name. */
+
+ case N_STSYM: /* Static symbol in data seg */
+ case N_LCSYM: /* Static symbol in BSS seg */
+ case N_ROSYM: /* Static symbol in Read-only data seg */
+ /* HORRID HACK DEPT. However, it's Sun's furgin' fault.
+ Solaris2's stabs-in-elf makes *most* symbols relative
+ but leaves a few absolute (at least for Solaris 2.1 and version
+ 2.0.1 of the SunPRO compiler). N_STSYM and friends sit on the fence.
+ .stab "foo:S...",N_STSYM is absolute (ld relocates it)
+ .stab "foo:V...",N_STSYM is relative (section base subtracted).
+ This leaves us no choice but to search for the 'S' or 'V'...
+ (or pass the whole section_offsets stuff down ONE MORE function
+ call level, which we really don't want to do). */
+ {
+ char *p;
+
+ /* .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)
+ {
+ 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) {
+ case N_STSYM: goto case_N_STSYM;
+ case N_LCSYM: goto case_N_LCSYM;
+ case N_ROSYM: goto case_N_ROSYM;
+ default: abort();
+ }
+ }
+
+ case_N_STSYM: /* Static symbol in data seg */
+ case N_DSLINE: /* Source line number, data seg */
+ valu += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ goto define_a_symbol;
+
+ case_N_LCSYM: /* Static symbol in BSS seg */
+ case N_BSLINE: /* Source line number, bss seg */
+ /* N_BROWS: overlaps with N_BSLINE */
+ valu += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ goto define_a_symbol;
+
+ case_N_ROSYM: /* Static symbol in Read-only data seg */
+ valu += ANOFFSET (section_offsets, SECT_OFF_RODATA);
+ goto define_a_symbol;
+
+ case N_ENTRY: /* Alternate entry point */
+ /* Relocate for dynamic loading */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ goto define_a_symbol;
+
+ /* The following symbol types we don't know how to process. Handle
+ them in a "default" way, but complain to people who care. */
+ default:
+ case N_CATCH: /* Exception handler catcher */
+ case N_EHDECL: /* Exception handler name */
+ case N_PC: /* Global symbol in Pascal */
+ case N_M2C: /* Modula-2 compilation unit */
+ /* N_MOD2: overlaps with N_EHDECL */
+ case N_SCOPE: /* Modula-2 scope information */
+ case N_ECOML: /* End common (local name) */
+ case N_NBTEXT: /* Gould Non-Base-Register symbols??? */
+ case N_NBDATA:
+ case N_NBBSS:
+ case N_NBSTS:
+ case N_NBLCS:
+ complain (&unknown_symtype_complaint, local_hex_string (type));
+ /* FALLTHROUGH */
+
+ /* The following symbol types don't need the address field relocated,
+ since it is either unused, or is absolute. */
+ define_a_symbol:
+ case N_GSYM: /* Global variable */
+ case N_NSYMS: /* Number of symbols (ultrix) */
+ case N_NOMAP: /* No map? (ultrix) */
+ case N_RSYM: /* Register variable */
+ case N_DEFD: /* Modula-2 GNU module dependency */
+ case N_SSYM: /* Struct or union element */
+ case N_LSYM: /* Local symbol in stack */
+ case N_PSYM: /* Parameter variable */
+ case N_LENG: /* Length of preceding symbol type */
+ if (name)
+ {
+ int deftype;
+ char *colon_pos = strchr (name, ':');
+ if (colon_pos == NULL)
+ deftype = '\0';
+ else
+ deftype = colon_pos[1];
+
+ switch (deftype)
+ {
+ case 'f':
+ case 'F':
+ function_stab_type = type;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Deal with the SunPRO 3.0 compiler which omits the address
+ from N_FUN symbols. */
+ if (type == N_FUN
+ && valu == ANOFFSET (section_offsets, SECT_OFF_TEXT))
+ {
+ struct minimal_symbol *msym;
+ char *p;
+ int n;
+
+ p = strchr (name, ':');
+ if (p == NULL)
+ p = name;
+ n = p - name;
+ p = alloca (n + 1);
+ strncpy (p, name, n);
+ p[n] = 0;
+
+ msym = lookup_minimal_symbol (p, last_source_file,
+ objfile);
+ if (msym)
+ valu = SYMBOL_VALUE_ADDRESS (msym);
+ }
+#endif
+
+#ifdef SUN_FIXED_LBRAC_BUG
+ /* The Sun acc compiler, under SunOS4, puts out
+ functions with N_GSYM or N_STSYM. The problem is
+ that the address of the symbol is no good (for N_GSYM
+ it doesn't even attept an address; for N_STSYM it
+ puts out an address but then it gets relocated
+ relative to the data segment, not the text segment).
+ Currently we can't fix this up later as we do for
+ some types of symbol in scan_file_globals.
+ Fortunately we do have a way of finding the address -
+ we know that the value in last_pc_address is either
+ the one we want (if we're dealing with the first
+ function in an object file), or somewhere in the
+ previous function. This means that we can use the
+ minimal symbol table to get the address. */
+
+ /* Starting with release 3.0, the Sun acc compiler,
+ under SunOS4, puts out functions with N_FUN and a value
+ of zero. This gets relocated to the start of the text
+ segment of the module, which is no good either.
+ Under SunOS4 we can deal with this as N_SLINE and N_SO
+ entries contain valid absolute addresses.
+ Release 3.0 acc also puts out N_OPT entries, which makes
+ it possible to discern acc from cc or gcc. */
+
+ if (type == N_GSYM || type == N_STSYM
+ || (type == N_FUN
+ && n_opt_found && !block_address_function_relative))
+ {
+ struct minimal_symbol *m;
+ int l = colon_pos - name;
+
+ m = lookup_minimal_symbol_by_pc (last_pc_address);
+ if (m && STREQN (SYMBOL_NAME (m), name, l)
+ && SYMBOL_NAME (m) [l] == '\0')
+ /* last_pc_address was in this function */
+ valu = SYMBOL_VALUE (m);
+ else if (m && SYMBOL_NAME (m+1)
+ && STREQN (SYMBOL_NAME (m+1), name, l)
+ && SYMBOL_NAME (m+1) [l] == '\0')
+ /* last_pc_address was in last function */
+ valu = SYMBOL_VALUE (m+1);
+ else
+ /* Not found - use last_pc_address (for finish_block) */
+ valu = last_pc_address;
+ }
+
+ last_pc_address = valu; /* Save for SunOS bug circumcision */
+#endif
+
+ if (block_address_function_relative)
+ /* For Solaris 2.0 compilers, the block addresses and
+ N_SLINE's are relative to the start of the
+ function. On normal systems, and when using gcc on
+ Solaris 2.0, these addresses are just absolute, or
+ relative to the N_SO, depending on
+ BLOCK_ADDRESS_ABSOLUTE. */
+ function_start_offset = valu;
+
+ within_function = 1;
+ if (context_stack_depth > 0)
+ {
+ new = pop_context ();
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ }
+ /* Stack must be empty now. */
+ if (context_stack_depth != 0)
+ complain (&lbrac_unmatched_complaint, symnum);
+
+ new = push_context (0, valu);
+ new->name = define_symbol (valu, name, desc, type, objfile);
+ break;
+
+ default:
+ define_symbol (valu, name, desc, type, objfile);
+ break;
+ }
+ }
+ break;
+
+ /* We use N_OPT to carry the gcc2_compiled flag. Sun uses it
+ for a bunch of other flags, too. Someday we may parse their
+ flags; for now we ignore theirs and hope they'll ignore ours. */
+ case N_OPT: /* Solaris 2: Compiler options */
+ if (name)
+ {
+ if (STREQ (name, GCC2_COMPILED_FLAG_SYMBOL))
+ {
+ processing_gcc_compilation = 2;
+#if 1 /* Works, but is experimental. -fnf */
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+#endif
+ }
+ else
+ n_opt_found = 1;
+ }
+ break;
+
+ /* The following symbol types can be ignored. */
+ case N_OBJ: /* Solaris 2: Object file dir and name */
+ /* N_UNDF: Solaris 2: file separator mark */
+ /* N_UNDF: -- we will never encounter it, since we only process one
+ file's symbols at once. */
+ case N_ENDM: /* Solaris 2: End of module */
+ case N_MAIN: /* Name of main routine. */
+ break;
+ }
+
+ previous_stab_code = type;
+}
+
+/* FIXME: The only difference between this and elfstab_build_psymtabs
+ is the call to install_minimal_symbols for elf, and the support for
+ split sections. If the differences are really that small, the code
+ should be shared. */
+
+/* Scan and build partial symbols for an coff symbol file.
+ The coff file has already been processed to get its minimal symbols.
+
+ 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).
+ TEXTADDR is the address of the text section.
+ TEXTSIZE is the size of the text section.
+ STABSECTS is the list of .stab sections in OBJFILE.
+ STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
+ .stabstr section exists.
+
+ This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
+ adjusted for coff details. */
+
+void
+coffstab_build_psymtabs (objfile, section_offsets, mainline,
+ textaddr, textsize, stabsects,
+ stabstroffset, stabstrsize)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ CORE_ADDR textaddr;
+ unsigned int textsize;
+ struct stab_section_list *stabsects;
+ file_ptr stabstroffset;
+ unsigned int stabstrsize;
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ struct dbx_symfile_info *info;
+ unsigned int stabsize;
+
+ /* There is already a dbx_symfile_info allocated by our caller.
+ It might even contain some info from the coff symtab to help us. */
+ info = (struct dbx_symfile_info *) objfile->sym_stab_info;
+
+ DBX_TEXT_ADDR (objfile) = textaddr;
+ DBX_TEXT_SIZE (objfile) = textsize;
+
+#define COFF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
+ DBX_SYMBOL_SIZE (objfile) = COFF_STABS_SYMBOL_SIZE;
+ DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+
+ if (stabstrsize > bfd_get_size (sym_bfd))
+ error ("ridiculous string table size: %d bytes", stabstrsize);
+ DBX_STRINGTAB (objfile) = (char *)
+ obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
+ OBJSTAT (objfile, sz_strtab += stabstrsize+1);
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, 1, sym_bfd);
+ if (val != stabstrsize)
+ perror_with_name (name);
+
+ stabsread_new_init ();
+ buildsym_new_init ();
+ free_header_files ();
+ init_header_files ();
+
+ processing_acc_compilation = 1;
+
+ /* In a coff file, we've already installed the minimal symbols that came
+ from the coff (non-stab) symbol table, so always act like an
+ incremental load here. */
+ if (stabsects->next == NULL)
+ {
+ stabsize = bfd_section_size (sym_bfd, stabsects->section);
+ DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
+ DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
+ }
+ else
+ {
+ struct stab_section_list *stabsect;
+
+ DBX_SYMCOUNT (objfile) = 0;
+ for (stabsect = stabsects; stabsect != NULL; stabsect = stabsect->next)
+ {
+ stabsize = bfd_section_size (sym_bfd, stabsect->section);
+ DBX_SYMCOUNT (objfile) += stabsize / DBX_SYMBOL_SIZE (objfile);
+ }
+
+ DBX_SYMTAB_OFFSET (objfile) = stabsects->section->filepos;
+
+ symbuf_sections = stabsects->next;
+ symbuf_left = bfd_section_size (sym_bfd, stabsects->section);
+ symbuf_read = 0;
+ }
+
+ dbx_symfile_read (objfile, section_offsets, 0);
+}
+
+/* Scan and build partial symbols for an ELF symbol file.
+ This ELF file has already been processed to get its minimal symbols,
+ and any DWARF symbols that were in it.
+
+ 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).
+ STABOFFSET and STABSIZE define the location in OBJFILE where the .stab
+ section exists.
+ STABSTROFFSET and STABSTRSIZE define the location in OBJFILE where the
+ .stabstr section exists.
+
+ This routine is mostly copied from dbx_symfile_init and dbx_symfile_read,
+ adjusted for elf details. */
+
+void
+elfstab_build_psymtabs (objfile, section_offsets, mainline,
+ staboffset, stabsize,
+ stabstroffset, stabstrsize)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ file_ptr staboffset;
+ unsigned int stabsize;
+ file_ptr stabstroffset;
+ unsigned int stabstrsize;
+{
+ int val;
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ struct dbx_symfile_info *info;
+ asection *text_sect;
+
+ /* There is already a dbx_symfile_info allocated by our caller.
+ It might even contain some info from the ELF symtab to help us. */
+ info = (struct dbx_symfile_info *) objfile->sym_stab_info;
+
+ text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!text_sect)
+ error ("Can't find .text section in symbol file");
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+#define ELF_STABS_SYMBOL_SIZE 12 /* XXX FIXME XXX */
+ DBX_SYMBOL_SIZE (objfile) = ELF_STABS_SYMBOL_SIZE;
+ DBX_SYMCOUNT (objfile) = stabsize / DBX_SYMBOL_SIZE (objfile);
+ DBX_STRINGTAB_SIZE (objfile) = stabstrsize;
+ DBX_SYMTAB_OFFSET (objfile) = staboffset;
+
+ if (stabstrsize > bfd_get_size (sym_bfd))
+ error ("ridiculous string table size: %d bytes", stabstrsize);
+ DBX_STRINGTAB (objfile) = (char *)
+ obstack_alloc (&objfile->psymbol_obstack, stabstrsize+1);
+ OBJSTAT (objfile, sz_strtab += stabstrsize+1);
+
+ /* Now read in the string table in one big gulp. */
+
+ val = bfd_seek (sym_bfd, stabstroffset, SEEK_SET);
+ if (val < 0)
+ perror_with_name (name);
+ val = bfd_read (DBX_STRINGTAB (objfile), stabstrsize, 1, sym_bfd);
+ if (val != stabstrsize)
+ perror_with_name (name);
+
+ stabsread_new_init ();
+ buildsym_new_init ();
+ free_header_files ();
+ init_header_files ();
+ install_minimal_symbols (objfile);
+
+ processing_acc_compilation = 1;
+
+ /* In an elf file, we've already installed the minimal symbols that came
+ from the elf (non-stab) symbol table, so always act like an
+ incremental load here. */
+ dbx_symfile_read (objfile, section_offsets, 0);
+}
+
+/* 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).
+ 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
+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;
+ asection *text_sect;
+
+ 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));
+
+ text_sect = bfd_get_section_by_name (sym_bfd, text_name);
+ if (!text_sect)
+ error ("Can't find %s section in symbol file", text_name);
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+ 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);
+ OBJSTAT (objfile, sz_strtab += 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);
+
+ /* Now, do an incremental load */
+
+ 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
+ of how to represent it for fast symbol reading. */
+
+static struct section_offsets *
+dbx_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+static struct sym_fns aout_sym_fns =
+{
+ 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 */
+ 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 */
+};
+
+void
+_initialize_dbxread ()
+{
+ add_symtab_fns(&aout_sym_fns);
+}
diff --git a/contrib/gdb/gdb/dcache.c b/contrib/gdb/gdb/dcache.c
new file mode 100644
index 0000000..9f44e96
--- /dev/null
+++ b/contrib/gdb/gdb/dcache.c
@@ -0,0 +1,564 @@
+/* Caching code. Typically used by remote back ends for
+ caching remote memory.
+
+ Copyright 1992, 1993, 1995 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "dcache.h"
+#include "gdbcmd.h"
+#include "gdb_string.h"
+
+
+/*
+ The data cache could lead to incorrect results because it doesn't know
+ about volatile variables, thus making it impossible to debug
+ functions which use memory mapped I/O devices.
+
+ set remotecache 0
+
+ In those cases.
+
+ In general the dcache speeds up performance, some speed improvement
+ comes from the actual caching mechanism, but the major gain is in
+ the reduction of the remote protocol overhead; instead of reading
+ or writing a large area of memory in 4 byte requests, the cache
+ bundles up the requests into 32 byte (actually LINE_SIZE) chunks.
+ Reducing the overhead to an eighth of what it was. This is very
+ obvious when displaying a large amount of data,
+
+ eg, x/200x 0
+
+ caching | no yes
+ ----------------------------
+ first time | 4 sec 2 sec improvement due to chunking
+ second time | 4 sec 0 sec improvement due to caching
+
+ The cache structure is unusual, we keep a number of cache blocks
+ (DCACHE_SIZE) and each one caches a LINE_SIZEed area of memory.
+ Within each line we remember the address of the line (always a
+ multiple of the LINE_SIZE) and a vector of bytes over the range.
+ There's another vector which contains the state of the bytes.
+
+ ENTRY_BAD means that the byte is just plain wrong, and has no
+ correspondence with anything else (as it would when the cache is
+ turned on, but nothing has been done to it.
+
+ ENTRY_DIRTY means that the byte has some data in it which should be
+ written out to the remote target one day, but contains correct
+ data. ENTRY_OK means that the data is the same in the cache as it
+ is in remote memory.
+
+
+ The ENTRY_DIRTY state is necessary because GDB likes to write large
+ lumps of memory in small bits. If the caching mechanism didn't
+ maintain the DIRTY information, then something like a two byte
+ write would mean that the entire cache line would have to be read,
+ the two bytes modified and then written out again. The alternative
+ would be to not read in the cache line in the first place, and just
+ write the two bytes directly into target memory. The trouble with
+ that is that it really nails performance, because of the remote
+ protocol overhead. This way, all those little writes are bundled
+ up into an entire cache line write in one go, without having to
+ read the cache line in the first place.
+
+
+ */
+
+
+/* This value regulates the number of cache blocks stored.
+ Smaller values reduce the time spent searching for a cache
+ line, and reduce memory requirements, but increase the risk
+ of a line not being in memory */
+
+#define DCACHE_SIZE 64
+
+/* This value regulates the size of a cache line. Smaller values
+ reduce the time taken to read a single byte, but reduce overall
+ throughput. */
+
+#define LINE_SIZE_POWER (5)
+#define LINE_SIZE (1 << LINE_SIZE_POWER)
+
+/* Each cache block holds LINE_SIZE bytes of data
+ starting at a multiple-of-LINE_SIZE address. */
+
+#define LINE_SIZE_MASK ((LINE_SIZE - 1))
+#define XFORM(x) ((x) & LINE_SIZE_MASK)
+#define MASK(x) ((x) & ~LINE_SIZE_MASK)
+
+
+#define ENTRY_BAD 0 /* data at this byte is wrong */
+#define ENTRY_DIRTY 1 /* data at this byte needs to be written back */
+#define ENTRY_OK 2 /* data at this byte is same as in memory */
+
+
+struct dcache_block
+{
+ struct dcache_block *p; /* next in list */
+ unsigned int addr; /* Address for which data is recorded. */
+ char data[LINE_SIZE]; /* bytes at given address */
+ unsigned char state[LINE_SIZE]; /* what state the data is in */
+
+ /* whether anything in state is dirty - used to speed up the
+ dirty scan. */
+ int anydirty;
+
+ int refs;
+};
+
+
+struct dcache_struct
+{
+ /* Function to actually read the target memory. */
+ memxferfunc read_memory;
+
+ /* Function to actually write the target memory */
+ memxferfunc write_memory;
+
+ /* free list */
+ struct dcache_block *free_head;
+ struct dcache_block *free_tail;
+
+ /* in use list */
+ struct dcache_block *valid_head;
+ struct dcache_block *valid_tail;
+
+ /* The cache itself. */
+ struct dcache_block *the_cache;
+
+ /* potentially, if the cache was enabled, and then turned off, and
+ then turned on again, the stuff in it could be stale, so this is
+ used to mark it */
+ int cache_has_stuff;
+} ;
+
+int remote_dcache = 0;
+
+DCACHE *last_cache; /* Used by info dcache */
+
+
+
+/* Free all the data cache blocks, thus discarding all cached data. */
+
+void
+dcache_flush (dcache)
+ DCACHE *dcache;
+{
+ int i;
+ dcache->valid_head = 0;
+ dcache->valid_tail = 0;
+
+ dcache->free_head = 0;
+ dcache->free_tail = 0;
+
+ for (i = 0; i < DCACHE_SIZE; i++)
+ {
+ struct dcache_block *db = dcache->the_cache + i;
+
+ if (!dcache->free_head)
+ dcache->free_head = db;
+ else
+ dcache->free_tail->p = db;
+ dcache->free_tail = db;
+ db->p = 0;
+ }
+
+ dcache->cache_has_stuff = 0;
+
+ return;
+}
+
+/* If addr is present in the dcache, return the address of the block
+ containing it. */
+static
+struct dcache_block *
+dcache_hit (dcache, addr)
+ DCACHE *dcache;
+ unsigned int addr;
+{
+ register struct dcache_block *db;
+
+ /* Search all cache blocks for one that is at this address. */
+ db = dcache->valid_head;
+
+ while (db)
+ {
+ if (MASK(addr) == db->addr)
+ {
+ db->refs++;
+ return db;
+ }
+ db = db->p;
+ }
+
+ return NULL;
+}
+
+/* Make sure that anything in this line which needs to
+ be written is. */
+
+static int
+dcache_write_line (dcache, db)
+ DCACHE *dcache;
+ register struct dcache_block *db;
+{
+ int s;
+ int e;
+ s = 0;
+ if (db->anydirty)
+ {
+ for (s = 0; s < LINE_SIZE; s++)
+ {
+ if (db->state[s] == ENTRY_DIRTY)
+ {
+ int len = 0;
+ for (e = s ; e < LINE_SIZE; e++, len++)
+ if (db->state[e] != ENTRY_DIRTY)
+ break;
+ {
+ /* all bytes from s..s+len-1 need to
+ be written out */
+ int done = 0;
+ while (done < len) {
+ int t = dcache->write_memory (db->addr + s + done,
+ db->data + s + done,
+ len - done);
+ if (t == 0)
+ return 0;
+ done += t;
+ }
+ memset (db->state + s, ENTRY_OK, len);
+ s = e;
+ }
+ }
+ }
+ db->anydirty = 0;
+ }
+ return 1;
+}
+
+
+/* Get a free cache block, put or keep it on the valid list,
+ and return its address. The caller should store into the block
+ the address and data that it describes, then remque it from the
+ free list and insert it into the valid list. This procedure
+ prevents errors from creeping in if a memory retrieval is
+ interrupted (which used to put garbage blocks in the valid
+ list...). */
+static
+struct dcache_block *
+dcache_alloc (dcache)
+ DCACHE *dcache;
+{
+ register struct dcache_block *db;
+
+ if (remote_dcache == 0)
+ abort ();
+
+ /* Take something from the free list */
+ db = dcache->free_head;
+ if (db)
+ {
+ dcache->free_head = db->p;
+ }
+ else
+ {
+ /* Nothing left on free list, so grab one from the valid list */
+ db = dcache->valid_head;
+ dcache->valid_head = db->p;
+
+ dcache_write_line (dcache, db);
+ }
+
+ /* append this line to end of valid list */
+ if (!dcache->valid_head)
+ dcache->valid_head = db;
+ else
+ dcache->valid_tail->p = db;
+ dcache->valid_tail = db;
+ db->p = 0;
+
+ return db;
+}
+
+/* Using the data cache DCACHE return the contents of the byte at
+ address ADDR in the remote machine.
+
+ Returns 0 on error. */
+
+int
+dcache_peek_byte (dcache, addr, ptr)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ char *ptr;
+{
+ register struct dcache_block *db = dcache_hit (dcache, addr);
+ int ok=1;
+ int done = 0;
+ if (db == 0
+ || db->state[XFORM (addr)] == ENTRY_BAD)
+ {
+ if (db)
+ {
+ dcache_write_line (dcache, db);
+ }
+ else
+ db = dcache_alloc (dcache);
+ immediate_quit++;
+ db->addr = MASK (addr);
+ while (done < LINE_SIZE)
+ {
+ int try =
+ (*dcache->read_memory)
+ (db->addr + done,
+ db->data + done,
+ LINE_SIZE - done);
+ if (try == 0)
+ return 0;
+ done += try;
+ }
+ immediate_quit--;
+
+ memset (db->state, ENTRY_OK, sizeof (db->data));
+ db->anydirty = 0;
+ }
+ *ptr = db->data[XFORM (addr)];
+ return ok;
+}
+
+/* Using the data cache DCACHE return the contents of the word at
+ address ADDR in the remote machine.
+
+ Returns 0 on error. */
+
+int
+dcache_peek (dcache, addr, data)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ int *data;
+{
+ char *dp = (char *) data;
+ int i;
+ for (i = 0; i < (int) sizeof (int); i++)
+ {
+ if (!dcache_peek_byte (dcache, addr + i, dp + i))
+ return 0;
+ }
+ return 1;
+}
+
+
+/* Writeback any dirty lines to the remote. */
+static int
+dcache_writeback (dcache)
+ DCACHE *dcache;
+{
+ struct dcache_block *db;
+
+ db = dcache->valid_head;
+
+ while (db)
+ {
+ if (!dcache_write_line (dcache, db))
+ return 0;
+ db = db->p;
+ }
+ return 1;
+}
+
+
+/* Using the data cache DCACHE return the contents of the word at
+ address ADDR in the remote machine. */
+int
+dcache_fetch (dcache, addr)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+{
+ int res;
+ dcache_peek (dcache, addr, &res);
+ return res;
+}
+
+
+/* Write the byte at PTR into ADDR in the data cache.
+ Return zero on write error.
+ */
+
+int
+dcache_poke_byte (dcache, addr, ptr)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ char *ptr;
+{
+ register struct dcache_block *db = dcache_hit (dcache, addr);
+
+ if (!db)
+ {
+ db = dcache_alloc (dcache);
+ db->addr = MASK (addr);
+ memset (db->state, ENTRY_BAD, sizeof (db->data));
+ }
+
+ db->data[XFORM (addr)] = *ptr;
+ db->state[XFORM (addr)] = ENTRY_DIRTY;
+ db->anydirty = 1;
+ return 1;
+}
+
+/* Write the word at ADDR both in the data cache and in the remote machine.
+ Return zero on write error.
+ */
+
+int
+dcache_poke (dcache, addr, data)
+ DCACHE *dcache;
+ CORE_ADDR addr;
+ int data;
+{
+ char *dp = (char *) (&data);
+ int i;
+ for (i = 0; i < (int) sizeof (int); i++)
+ {
+ if (!dcache_poke_byte (dcache, addr + i, dp + i))
+ return 0;
+ }
+ dcache_writeback (dcache);
+ return 1;
+}
+
+
+/* Initialize the data cache. */
+DCACHE *
+dcache_init (reading, writing)
+ memxferfunc reading;
+ memxferfunc writing;
+{
+ int csize = sizeof (struct dcache_block) * DCACHE_SIZE;
+ DCACHE *dcache;
+
+ dcache = (DCACHE *) xmalloc (sizeof (*dcache));
+ dcache->read_memory = reading;
+ dcache->write_memory = writing;
+
+ dcache->the_cache = (struct dcache_block *) xmalloc (csize);
+ memset (dcache->the_cache, 0, csize);
+
+ dcache_flush (dcache);
+
+ last_cache = dcache;
+ return dcache;
+}
+
+/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+ to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
+ nonzero.
+
+ Returns length of data written or read; 0 for error.
+
+ This routine is indended to be called by remote_xfer_ functions. */
+
+int
+dcache_xfer_memory (dcache, memaddr, myaddr, len, should_write)
+ DCACHE *dcache;
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+{
+ int i;
+
+ if (remote_dcache)
+ {
+ int (*xfunc) ()
+ = should_write ? dcache_poke_byte : dcache_peek_byte;
+
+ for (i = 0; i < len; i++)
+ {
+ if (!xfunc (dcache, memaddr + i, myaddr + i))
+ return 0;
+ }
+ dcache->cache_has_stuff = 1;
+ dcache_writeback (dcache);
+ }
+ else
+ {
+ int (*xfunc) ()
+ = should_write ? dcache->write_memory : dcache->read_memory;
+
+ if (dcache->cache_has_stuff)
+ dcache_flush (dcache);
+
+ len = xfunc (memaddr, myaddr, len);
+ }
+ return len;
+}
+
+static void
+dcache_info (exp, tty)
+ char *exp;
+ int tty;
+{
+ struct dcache_block *p;
+
+ if (!remote_dcache)
+ {
+ printf_filtered ("Dcache not enabled\n");
+ return;
+ }
+ printf_filtered ("Dcache enabled, line width %d, depth %d\n",
+ LINE_SIZE, DCACHE_SIZE);
+
+ printf_filtered ("Cache state:\n");
+
+ for (p = last_cache->valid_head; p; p = p->p)
+ {
+ int j;
+ printf_filtered ("Line at %08xd, referenced %d times\n",
+ p->addr, p->refs);
+
+ for (j = 0; j < LINE_SIZE; j++)
+ printf_filtered ("%02x", p->data[j] & 0xFF);
+ printf_filtered ("\n");
+
+ for (j = 0; j < LINE_SIZE; j++)
+ printf_filtered (" %2x", p->state[j]);
+ printf_filtered ("\n");
+ }
+}
+
+void
+_initialize_dcache ()
+{
+ add_show_from_set
+ (add_set_cmd ("remotecache", class_support, var_boolean,
+ (char *) &remote_dcache,
+ "\
+Set cache use for remote targets.\n\
+When on, use data caching for remote targets. For many remote targets\n\
+this option can offer better throughput for reading target memory.\n\
+Unfortunately, gdb does not currently know anything about volatile\n\
+registers and thus data caching will produce incorrect results with\n\
+volatile registers are in use. By default, this option is on.",
+ &setlist),
+ &showlist);
+
+ add_info ("dcache", dcache_info,
+ "Print information on the dcache performance.");
+
+}
diff --git a/contrib/gdb/gdb/dcache.h b/contrib/gdb/gdb/dcache.h
new file mode 100644
index 0000000..a0b762a
--- /dev/null
+++ b/contrib/gdb/gdb/dcache.h
@@ -0,0 +1,50 @@
+/* Declarations for caching. Typically used by remote back ends for
+ caching remote memory.
+
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef DCACHE_H
+#define DCACHE_H
+
+typedef int (*memxferfunc) PARAMS((CORE_ADDR memaddr,
+ char *myaddr,
+ int len));
+
+typedef struct dcache_struct DCACHE;
+
+/* Using the data cache DCACHE return the contents of the word at
+ address ADDR in the remote machine. */
+int dcache_fetch PARAMS((DCACHE *dcache, CORE_ADDR addr));
+
+/* Flush DCACHE. */
+void dcache_flush PARAMS((DCACHE *dcache));
+
+/* Initialize DCACHE. */
+DCACHE *dcache_init PARAMS((memxferfunc reading, memxferfunc writing));
+
+/* Write the word at ADDR both in the data cache and in the remote machine. */
+int dcache_poke PARAMS((DCACHE *dcache, CORE_ADDR addr, int data));
+
+/* Simple to call from <remote>_xfer_memory */
+
+int dcache_xfer_memory PARAMS((DCACHE *cache, CORE_ADDR mem, char *my, int len, int should_write));
+
+/* Write the bytes at ADDR into the data cache and the remote machine. */
+int dcache_poke_block PARAMS((DCACHE *cache, CORE_ADDR mem, char* my, int len));
+#endif /* DCACHE_H */
diff --git a/contrib/gdb/gdb/defs.h b/contrib/gdb/gdb/defs.h
new file mode 100644
index 0000000..a1d181f
--- /dev/null
+++ b/contrib/gdb/gdb/defs.h
@@ -0,0 +1,973 @@
+/* Basic, host-specific, and target-specific definitions for GDB.
+ Copyright (C) 1986, 1989, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef DEFS_H
+#define DEFS_H
+
+#include "config.h" /* Generated by configure */
+#include <stdio.h>
+#include <errno.h> /* System call error return status */
+
+/* Just in case they're not defined in stdio.h. */
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+/* First include ansidecl.h so we can use the various macro definitions
+ here and in all subsequent file inclusions. */
+
+#include "ansidecl.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "libiberty.h"
+
+/* libiberty.h can't declare this one, but evidently we can. */
+extern char *strsignal PARAMS ((int));
+
+#include "progress.h"
+
+#ifndef NO_MMALLOC
+#include "mmalloc.h"
+#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))
+
+/* Gdb does *lots* of string compares. Use macros to speed them up by
+ avoiding function calls if the first characters are not the same. */
+
+#define STRCMP(a,b) (*(a) == *(b) ? strcmp ((a), (b)) : (int)*(a) - (int)*(b))
+#define STREQ(a,b) (*(a) == *(b) ? !strcmp ((a), (b)) : 0)
+#define STREQN(a,b,c) (*(a) == *(b) ? !strncmp ((a), (b), (c)) : 0)
+
+/* The character GNU C++ uses to build identifiers that must be unique from
+ the program's identifiers (such as $this and $$vptr). */
+#define CPLUS_MARKER '$' /* May be overridden to '.' for SysV */
+
+/* Check if a character is one of the commonly used C++ marker characters. */
+extern int is_cplus_marker PARAMS ((int));
+
+extern int quit_flag;
+extern int immediate_quit;
+extern int sevenbit_strings;
+
+extern void quit PARAMS ((void));
+
+#define QUIT { \
+ if (quit_flag) quit (); \
+ if (interactive_hook) interactive_hook (); \
+ PROGRESS (1); \
+}
+
+/* Command classes are top-level categories into which commands are broken
+ down for "help" purposes.
+ Notes on classes: class_alias is for alias commands which are not
+ abbreviations of the original command. class-pseudo is for commands
+ which are not really commands nor help topics ("stop"). */
+
+enum command_class
+{
+ /* Special args to help_list */
+ all_classes = -2, all_commands = -1,
+ /* Classes of commands */
+ no_class = -1, class_run = 0, class_vars, class_stack,
+ class_files, class_support, class_info, class_breakpoint,
+ class_alias, class_obscure, class_user, class_maintenance,
+ class_pseudo
+};
+
+/* Languages represented in the symbol table and elsewhere.
+ This should probably be in language.h, but since enum's can't
+ be forward declared to satisfy opaque references before their
+ actual definition, needs to be here. */
+
+enum language
+{
+ language_unknown, /* Language not known */
+ language_auto, /* Placeholder for automatic setting */
+ language_c, /* C */
+ language_cplus, /* C++ */
+ language_chill, /* Chill */
+ language_fortran, /* Fortran */
+ language_m2, /* Modula-2 */
+ language_asm, /* Assembly language */
+ language_scm /* Scheme / Guile */
+};
+
+/* the cleanup list records things that have to be undone
+ if an error happens (descriptors to be closed, memory to be freed, etc.)
+ Each link in the chain records a function to call and an
+ argument to give it.
+
+ Use make_cleanup to add an element to the cleanup chain.
+ Use do_cleanups to do all cleanup actions back to a given
+ point in the chain. Use discard_cleanups to remove cleanups
+ from the chain back to a given point, not doing them. */
+
+struct cleanup
+{
+ struct cleanup *next;
+ void (*function) PARAMS ((PTR));
+ PTR arg;
+};
+
+
+/* The ability to declare that a function never returns is useful, but
+ not really required to compile GDB successfully, so the NORETURN and
+ ATTR_NORETURN macros normally expand into nothing. */
+
+/* If compiling with older versions of GCC, a function may be declared
+ "volatile" to indicate that it does not return. */
+
+#ifndef NORETURN
+# if defined(__GNUC__) \
+ && (__GNUC__ == 1 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7))
+# define NORETURN volatile
+# else
+# define NORETURN /* nothing */
+# endif
+#endif
+
+/* GCC 2.5 and later versions define a function attribute "noreturn",
+ which is the preferred way to declare that a function never returns.
+ However GCC 2.7 appears to be the first version in which this fully
+ works everywhere we use it. */
+
+#ifndef ATTR_NORETURN
+# if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 7
+# define ATTR_NORETURN __attribute__ ((noreturn))
+# else
+# define ATTR_NORETURN /* nothing */
+# endif
+#endif
+
+#ifndef ATTR_FORMAT
+# if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 4 && defined (__ANSI_PROTOTYPES)
+# define ATTR_FORMAT(type, x, y) __attribute__ ((format(type, x, y)))
+# else
+# define ATTR_FORMAT(type, x, y) /* nothing */
+# endif
+#endif
+
+/* Needed for various prototypes */
+
+#ifdef __STDC__
+struct symtab;
+struct breakpoint;
+#endif
+
+/* From blockframe.c */
+
+extern int inside_entry_func PARAMS ((CORE_ADDR));
+
+extern int inside_entry_file PARAMS ((CORE_ADDR addr));
+
+extern int inside_main_func PARAMS ((CORE_ADDR pc));
+
+/* From ch-lang.c, for the moment. (FIXME) */
+
+extern char *chill_demangle PARAMS ((const char *));
+
+/* From utils.c */
+
+extern int strcmp_iw PARAMS ((const char *, const char *));
+
+extern char *safe_strerror PARAMS ((int));
+
+extern char *safe_strsignal PARAMS ((int));
+
+extern void init_malloc PARAMS ((void *));
+
+extern void request_quit PARAMS ((int));
+
+extern void do_cleanups PARAMS ((struct cleanup *));
+
+extern void discard_cleanups PARAMS ((struct cleanup *));
+
+/* The bare make_cleanup function is one of those rare beasts that
+ takes almost any type of function as the first arg and anything that
+ will fit in a "void *" as the second arg.
+
+ Should be, once all calls and called-functions are cleaned up:
+extern struct cleanup *
+make_cleanup PARAMS ((void (*function) (void *), void *));
+
+ Until then, lint and/or various type-checking compiler options will
+ complain about make_cleanup calls. It'd be wrong to just cast things,
+ since the type actually passed when the function is called would be
+ wrong. */
+
+extern struct cleanup *make_cleanup ();
+
+extern struct cleanup *save_cleanups PARAMS ((void));
+
+extern void restore_cleanups PARAMS ((struct cleanup *));
+
+extern void free_current_contents PARAMS ((char **));
+
+extern void null_cleanup PARAMS ((char **));
+
+extern int myread PARAMS ((int, char *, int));
+
+extern int query PARAMS((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+/* Annotation stuff. */
+
+extern int annotation_level; /* in stack.c */
+
+extern void begin_line PARAMS ((void));
+
+extern void wrap_here PARAMS ((char *));
+
+extern void reinitialize_more_filter PARAMS ((void));
+
+typedef FILE GDB_FILE;
+#define gdb_stdout stdout
+#define gdb_stderr stderr
+
+extern void 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 int fputc_unfiltered PARAMS ((int c, GDB_FILE *));
+
+extern int putchar_unfiltered PARAMS ((int c));
+
+extern void puts_filtered PARAMS ((const char *));
+
+extern void puts_unfiltered PARAMS ((const char *));
+
+extern void vprintf_filtered PARAMS ((const char *, va_list))
+ ATTR_FORMAT(printf, 1, 0);
+
+extern void vfprintf_filtered PARAMS ((FILE *, const char *, va_list))
+ ATTR_FORMAT(printf, 2, 0);
+
+extern void fprintf_filtered PARAMS ((FILE *, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+extern void fprintfi_filtered PARAMS ((int, FILE *, const char *, ...))
+ ATTR_FORMAT(printf, 3, 4);
+
+extern void printf_filtered PARAMS ((const char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+extern void printfi_filtered PARAMS ((int, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+extern void vprintf_unfiltered PARAMS ((const char *, va_list))
+ ATTR_FORMAT(printf, 1, 0);
+
+extern void vfprintf_unfiltered PARAMS ((FILE *, const char *, va_list))
+ ATTR_FORMAT(printf, 2, 0);
+
+extern void fprintf_unfiltered PARAMS ((FILE *, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+extern void printf_unfiltered PARAMS ((const char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+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, GDB_FILE *, int));
+
+extern void gdb_print_address PARAMS ((void *, GDB_FILE *));
+
+extern void fprintf_symbol_filtered PARAMS ((GDB_FILE *, char *,
+ enum language, int));
+
+extern void perror_with_name PARAMS ((char *));
+
+extern void print_sys_errmsg PARAMS ((char *, int));
+
+/* From regex.c or libc. BSD 4.4 declares this with the argument type as
+ "const char *" in unistd.h, so we can't declare the argument
+ as "char *". */
+
+extern char *re_comp PARAMS ((const char *));
+
+/* From symfile.c */
+
+extern void symbol_file_command PARAMS ((char *, int));
+
+/* From top.c */
+
+extern char *skip_quoted PARAMS ((char *));
+
+extern char *gdb_readline PARAMS ((char *));
+
+extern char *command_line_input PARAMS ((char *, int, char *));
+
+extern void print_prompt PARAMS ((void));
+
+extern int input_from_terminal_p PARAMS ((void));
+
+extern int info_verbose;
+
+/* From printcmd.c */
+
+extern void set_next_address PARAMS ((CORE_ADDR));
+
+extern void print_address_symbolic PARAMS ((CORE_ADDR, GDB_FILE *, int,
+ char *));
+
+extern void print_address_numeric PARAMS ((CORE_ADDR, int, GDB_FILE *));
+
+extern void print_address PARAMS ((CORE_ADDR, GDB_FILE *));
+
+/* From source.c */
+
+extern int openp PARAMS ((char *, int, char *, int, int, char **));
+
+extern void mod_path PARAMS ((char *, char **));
+
+extern void directory_command PARAMS ((char *, int));
+
+extern void init_source_path PARAMS ((void));
+
+extern char *symtab_to_filename PARAMS ((struct symtab *));
+
+/* From findvar.c */
+
+extern int read_relative_register_raw_bytes PARAMS ((int, char *));
+
+/* From readline (but not in any readline .h files). */
+
+extern char *tilde_expand PARAMS ((char *));
+
+/* Control types for commands */
+
+enum misc_command_type
+{
+ ok_command,
+ end_command,
+ else_command,
+ nop_command
+};
+
+enum command_control_type
+{
+ simple_control,
+ break_control,
+ continue_control,
+ while_control,
+ if_control,
+ invalid_control
+};
+
+/* Structure for saved commands lines
+ (for breakpoints, defined commands, etc). */
+
+struct command_line
+{
+ struct command_line *next;
+ char *line;
+ enum command_control_type control_type;
+ int body_count;
+ struct command_line **body_list;
+};
+
+extern struct command_line *read_command_lines PARAMS ((void));
+
+extern void free_command_lines PARAMS ((struct command_line **));
+
+/* String containing the current directory (what getwd would return). */
+
+extern char *current_directory;
+
+/* Default radixes for input and output. Only some values supported. */
+extern unsigned input_radix;
+extern unsigned output_radix;
+
+/* Possibilities for prettyprint parameters to routines which print
+ things. Like enum language, this should be in value.h, but needs
+ to be here for the same reason. FIXME: If we can eliminate this
+ as an arg to LA_VAL_PRINT, then we can probably move it back to
+ value.h. */
+
+enum val_prettyprint
+{
+ Val_no_prettyprint = 0,
+ Val_prettyprint,
+ /* Use the default setting which the user has specified. */
+ Val_pretty_default
+};
+
+
+/* Host machine definition. This will be a symlink to one of the
+ xm-*.h files, built by the `configure' script. */
+
+#include "xm.h"
+
+/* Native machine support. This will be a symlink to one of the
+ nm-*.h files, built by the `configure' script. */
+
+#include "nm.h"
+
+/* Target machine definition. This will be a symlink to one of the
+ tm-*.h files, built by the `configure' script. */
+
+#include "tm.h"
+
+/* 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 */
+#ifndef FOPEN_RB
+#include "fopen-same.h"
+#endif
+
+/*
+ * Allow things in gdb to be declared "const". If compiling ANSI, it
+ * just works. If compiling with gcc but non-ansi, redefine to __const__.
+ * If non-ansi, non-gcc, then eliminate "const" entirely, making those
+ * objects be read-write rather than read-only.
+ */
+
+#ifndef const
+#ifndef __STDC__
+# ifdef __GNUC__
+# define const __const__
+# else
+# define const /*nothing*/
+# endif /* GNUC */
+#endif /* STDC */
+#endif /* const */
+
+#ifndef volatile
+#ifndef __STDC__
+# ifdef __GNUC__
+# define volatile __volatile__
+# else
+# define volatile /*nothing*/
+# endif /* GNUC */
+#endif /* STDC */
+#endif /* volatile */
+
+/* Defaults for system-wide constants (if not defined by xm.h, we fake it). */
+
+#if !defined (UINT_MAX)
+#define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */
+#endif
+
+#if !defined (INT_MAX)
+#define INT_MAX ((int)(UINT_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */
+#endif
+
+#if !defined (INT_MIN)
+#define INT_MIN (-INT_MAX - 1) /* 0x80000000 for 32-bits */
+#endif
+
+#if !defined (ULONG_MAX)
+#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF for 32-bits */
+#endif
+
+#if !defined (LONG_MAX)
+#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */
+#endif
+
+#ifdef BFD64
+
+/* This is to make sure that LONGEST is at least as big as CORE_ADDR. */
+
+#define LONGEST BFD_HOST_64_BIT
+
+#else /* No BFD64 */
+
+/* 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.
+
+ 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)
+# 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. */
+
+#ifndef LONGEST
+# ifdef CC_HAS_LONG_LONG
+# define LONGEST long long
+# else
+# define LONGEST long
+# 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. */
+
+extern int longest_to_int PARAMS ((LONGEST));
+
+/* Assorted functions we can declare, now that const and volatile are
+ defined. */
+
+extern char *savestring PARAMS ((const char *, int));
+
+extern char *msavestring PARAMS ((void *, const char *, int));
+
+extern char *strsave PARAMS ((const char *));
+
+extern char *mstrsave PARAMS ((void *, const char *));
+
+extern PTR xmmalloc PARAMS ((PTR, long));
+
+extern PTR xmrealloc PARAMS ((PTR, PTR, long));
+
+extern int parse_escape PARAMS ((char **));
+
+extern char *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 error message, when an error occurs. */
+
+extern char *quit_pre_print;
+
+/* Message to be printed before the warning message, when a warning occurs. */
+
+extern char *warning_pre_print;
+
+extern NORETURN void error PARAMS((char *, ...)) ATTR_NORETURN;
+
+extern void error_begin PARAMS ((void));
+
+extern NORETURN void fatal PARAMS((char *, ...)) ATTR_NORETURN;
+
+extern NORETURN void nomem PARAMS ((long)) ATTR_NORETURN;
+
+/* Reasons for calling return_to_top_level. */
+enum return_reason {
+ /* User interrupt. */
+ RETURN_QUIT,
+
+ /* Any other error. */
+ RETURN_ERROR
+};
+
+#define RETURN_MASK_QUIT (1 << (int)RETURN_QUIT)
+#define RETURN_MASK_ERROR (1 << (int)RETURN_ERROR)
+#define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_ERROR)
+typedef int return_mask;
+
+extern NORETURN void
+return_to_top_level PARAMS ((enum return_reason)) ATTR_NORETURN;
+
+extern int
+catch_errors PARAMS ((int (*) (char *), void *, char *, return_mask));
+
+extern void warning_begin PARAMS ((void));
+
+extern void warning PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+/* Global functions from other, non-gdb GNU thingies.
+ Libiberty thingies are no longer declared here. We include libiberty.h
+ above, instead. */
+
+#ifndef GETENV_PROVIDED
+extern char *getenv PARAMS ((const char *));
+#endif
+
+/* From other system libraries */
+
+#ifdef __STDC__
+#include <stddef.h>
+#include <stdlib.h>
+#endif
+
+
+/* We take the address of fclose later, but some stdio's forget
+ to declare this. We can't always declare it since there's
+ no way to declare the parameters without upsetting some compiler
+ somewhere. */
+
+#ifndef FCLOSE_PROVIDED
+extern int fclose ();
+#endif
+
+#ifndef atof
+extern double atof ();
+#endif
+
+#ifndef MALLOC_INCOMPATIBLE
+
+extern PTR malloc ();
+
+extern PTR realloc ();
+
+extern void free ();
+
+#endif /* MALLOC_INCOMPATIBLE */
+
+#ifndef __WIN32__
+
+#ifndef strchr
+extern char *strchr ();
+#endif
+
+#ifndef strrchr
+extern char *strrchr ();
+#endif
+
+#ifndef strstr
+extern char *strstr ();
+#endif
+
+#ifndef strtok
+extern char *strtok ();
+#endif
+
+#ifndef strerror
+extern char *strerror ();
+#endif
+
+#endif /* !__WIN32__ */
+
+/* Various possibilities for alloca. */
+#ifndef alloca
+# ifdef __GNUC__
+# define alloca __builtin_alloca
+# else /* Not GNU C */
+# ifdef sparc
+# include <alloca.h> /* NOTE: Doesn't declare alloca() */
+# endif
+
+/* 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 /* Don't use void *. */
+# endif /* Not GNU C */
+#endif /* alloca not defined */
+
+/* HOST_BYTE_ORDER must be defined to one of these. */
+
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
+
+#if !defined (BIG_ENDIAN)
+#define BIG_ENDIAN 4321
+#endif
+
+#if !defined (LITTLE_ENDIAN)
+#define LITTLE_ENDIAN 1234
+#endif
+
+/* Target-system-dependent parameters for GDB. */
+
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+/* The target endianness is selectable at runtime. Define
+ TARGET_BYTE_ORDER to be a variable. The user can use the `set
+ endian' command to change it. */
+#undef TARGET_BYTE_ORDER
+#define TARGET_BYTE_ORDER target_byte_order
+extern int target_byte_order;
+#endif
+
+extern void set_endian_from_file PARAMS ((bfd *));
+
+/* Number of bits in a char or unsigned char for the target machine.
+ Just like CHAR_BIT in <limits.h> 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 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 <limits.h>) 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. */
+
+#if !defined (BITS_BIG_ENDIAN)
+#ifndef TARGET_BYTE_ORDER_SELECTABLE
+
+#if TARGET_BYTE_ORDER == BIG_ENDIAN
+#define BITS_BIG_ENDIAN 1
+#endif /* Big endian. */
+
+#if TARGET_BYTE_ORDER == LITTLE_ENDIAN
+#define BITS_BIG_ENDIAN 0
+#endif /* Little endian. */
+
+#else /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
+
+#define BITS_BIG_ENDIAN (TARGET_BYTE_ORDER == BIG_ENDIAN)
+
+#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
+#endif /* BITS_BIG_ENDIAN not defined. */
+
+/* In findvar.c. */
+
+extern LONGEST extract_signed_integer PARAMS ((void *, int));
+
+extern unsigned LONGEST extract_unsigned_integer PARAMS ((void *, int));
+
+extern int extract_long_unsigned_integer PARAMS ((void *, int, LONGEST *));
+
+extern CORE_ADDR extract_address PARAMS ((void *, int));
+
+extern void store_signed_integer PARAMS ((void *, int, LONGEST));
+
+extern void store_unsigned_integer PARAMS ((void *, int, unsigned LONGEST));
+
+extern void store_address PARAMS ((void *, int, CORE_ADDR));
+
+/* Use `long double' if the host compiler supports it. (Note that this is not
+ necessarily any longer than `double'. On SunOS/gcc, it's the same as
+ double.) This is necessary because GDB internally converts all floating
+ point values to the widest type supported by the host.
+
+ There are problems however, when the target `long double' is longer than the
+ host's `long double'. In general, we'll probably reduce the precision of
+ any such values and print a warning. */
+
+
+#ifdef HAVE_LONG_DOUBLE
+typedef long double DOUBLEST;
+#else
+typedef double DOUBLEST;
+#endif
+
+extern DOUBLEST extract_floating PARAMS ((void *, int));
+
+extern void store_floating PARAMS ((void *, int, DOUBLEST));
+
+/* 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.
+ for special purposes. ADDR_BITS_REMOVE takes out any such bits
+ so we get a "real" address such as one would find in a symbol
+ table. This is used only for addresses of instructions, and even then
+ I'm not sure it's used in all contexts. It exists to deal with there
+ being a few stray bits in the PC which would mislead us, not as some sort
+ of generic thing to handle alignment or segmentation (it's possible it
+ should be in TARGET_READ_PC instead). */
+#if !defined (ADDR_BITS_REMOVE)
+#define ADDR_BITS_REMOVE(addr) (addr)
+#endif /* No ADDR_BITS_REMOVE. */
+
+/* From valops.c */
+
+extern CORE_ADDR push_bytes PARAMS ((CORE_ADDR, char *, int));
+
+extern CORE_ADDR 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
+ for a specific environment. For example, the maintenance commands
+ are there for the benefit of gdb maintainers. As another example,
+ some environments really don't need gdb's that are able to read N
+ different object file formats. In order to make it possible (but
+ not necessarily recommended) to build "stripped down" versions of
+ gdb, the following defines control selective compilation of those
+ parts of gdb which can be safely left out when necessary. Note that
+ the default is to include everything. */
+
+#ifndef MAINTENANCE_CMDS
+#define MAINTENANCE_CMDS 1
+#endif
+
+#ifdef MAINTENANCE_CMDS
+extern int watchdog;
+#endif
+
+#include "dis-asm.h" /* Get defs for disassemble_info */
+
+extern int dis_asm_read_memory PARAMS ((bfd_vma memaddr, bfd_byte *myaddr,
+ int len, disassemble_info *info));
+
+extern void dis_asm_memory_error PARAMS ((int status, bfd_vma memaddr,
+ disassemble_info *info));
+
+extern void dis_asm_print_address PARAMS ((bfd_vma addr,
+ disassemble_info *info));
+
+extern int (*tm_print_insn) PARAMS ((bfd_vma, disassemble_info*));
+
+/* Hooks for alternate command interfaces. */
+
+#ifdef __STDC__
+struct target_waitstatus;
+struct cmd_list_element;
+#endif
+
+extern void (*init_ui_hook) PARAMS ((void));
+extern void (*command_loop_hook) PARAMS ((void));
+extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer,
+ FILE *stream));
+extern void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s,
+ int line, int stopline,
+ int noerror));
+extern int (*query_hook) PARAMS (());
+extern void (*flush_hook) PARAMS ((FILE *stream));
+extern void (*create_breakpoint_hook) PARAMS ((struct breakpoint *b));
+extern void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+extern void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+extern void (*target_output_hook) PARAMS ((char *));
+extern void (*interactive_hook) PARAMS ((void));
+extern void (*registers_changed_hook) PARAMS ((void));
+
+extern int (*target_wait_hook) PARAMS ((int pid,
+ struct target_waitstatus *status));
+
+extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c,
+ char *cmd, int from_tty));
+
+extern NORETURN void (*error_hook) PARAMS (()) ATTR_NORETURN;
+
+
+
+/* Inhibit window interface if non-zero. */
+
+extern int use_windows;
+
+/* Symbolic definitions of filename-related things. */
+/* FIXME, this doesn't work very well if host and executable
+ filesystems conventions are different. */
+
+#ifndef DIRNAME_SEPARATOR
+#define DIRNAME_SEPARATOR ':'
+#endif
+
+#ifndef SLASH_P
+#if defined(__GO32__)||defined(__WIN32__)
+#define SLASH_P(X) ((X)=='\\')
+#else
+#define SLASH_P(X) ((X)=='/')
+#endif
+#endif
+
+#ifndef SLASH_CHAR
+#if defined(__GO32__)||defined(__WIN32__)
+#define SLASH_CHAR '\\'
+#else
+#define SLASH_CHAR '/'
+#endif
+#endif
+
+#ifndef SLASH_STRING
+#if defined(__GO32__)||defined(__WIN32__)
+#define SLASH_STRING "\\"
+#else
+#define SLASH_STRING "/"
+#endif
+#endif
+
+#ifndef ROOTED_P
+#define ROOTED_P(X) (SLASH_P((X)[0]))
+#endif
+
+#endif /* #ifndef DEFS_H */
diff --git a/contrib/gdb/gdb/demangle.c b/contrib/gdb/gdb/demangle.c
new file mode 100644
index 0000000..bb3f092
--- /dev/null
+++ b/contrib/gdb/gdb/demangle.c
@@ -0,0 +1,206 @@
+/* Basic C++ demangling support for GDB.
+ Copyright 1991, 1992, 1996 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file contains support code for C++ demangling that is common
+ to a styles of demangling, and GDB specific. */
+
+#include "defs.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "demangle.h"
+#include "gdb_string.h"
+
+/* Select the default C++ demangling style to use. The default is "auto",
+ which allows gdb to attempt to pick an appropriate demangling style for
+ the executable it has loaded. It can be set to a specific style ("gnu",
+ "lucid", "arm", etc.) in which case gdb will never attempt to do auto
+ selection of the style unless you do an explicit "set demangle auto".
+ To select one of these as the default, set DEFAULT_DEMANGLING_STYLE in
+ the appropriate target configuration file. */
+
+#ifndef DEFAULT_DEMANGLING_STYLE
+# define DEFAULT_DEMANGLING_STYLE AUTO_DEMANGLING_STYLE_STRING
+#endif
+
+/* String name for the current demangling style. Set by the "set demangling"
+ command, printed as part of the output by the "show demangling" command. */
+
+static char *current_demangling_style_string;
+
+/* List of supported demangling styles. Contains the name of the style as
+ seen by the user, and the enum value that corresponds to that style. */
+
+static const struct demangler
+{
+ char *demangling_style_name;
+ enum demangling_styles demangling_style;
+ char *demangling_style_doc;
+} demanglers [] =
+{
+ {AUTO_DEMANGLING_STYLE_STRING,
+ auto_demangling,
+ "Automatic selection based on executable"},
+ {GNU_DEMANGLING_STYLE_STRING,
+ gnu_demangling,
+ "GNU (g++) style demangling"},
+ {LUCID_DEMANGLING_STYLE_STRING,
+ lucid_demangling,
+ "Lucid (lcc) style demangling"},
+ {ARM_DEMANGLING_STYLE_STRING,
+ arm_demangling,
+ "ARM style demangling"},
+ {NULL, unknown_demangling, NULL}
+};
+
+/* 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.
+
+ if the user has entered a string that matches a known demangling style
+ name in the demanglers[] array then just leave the string alone and update
+ the current_demangling_style enum value to match.
+
+ if the user has entered a string that doesn't match, including an empty
+ string, then print a list of the currently known styles and restore
+ the current_demangling_style_string to match the current_demangling_style
+ enum value.
+
+ Note: Assumes that current_demangling_style_string always points to
+ a malloc'd string, even if it is a null-string. */
+
+static void
+set_demangling_command (ignore, from_tty, c)
+ char *ignore;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ const struct demangler *dem;
+
+ /* First just try to match whatever style name the user supplied with
+ one of the known ones. Don't bother special casing for an empty
+ name, we just treat it as any other style name that doesn't match.
+ If we match, update the current demangling style enum. */
+
+ for (dem = demanglers; dem -> demangling_style_name != NULL; dem++)
+ {
+ if (STREQ (current_demangling_style_string,
+ dem -> demangling_style_name))
+ {
+ current_demangling_style = dem -> demangling_style;
+ break;
+ }
+ }
+
+ /* Check to see if we found a match. If not, gripe about any non-empty
+ style name and supply a list of valid ones. FIXME: This should
+ probably be done with some sort of completion and with help. */
+
+ if (dem -> demangling_style_name == NULL)
+ {
+ if (*current_demangling_style_string != '\0')
+ {
+ printf_unfiltered ("Unknown demangling style `%s'.\n",
+ current_demangling_style_string);
+ }
+ printf_unfiltered ("The currently understood settings are:\n\n");
+ for (dem = demanglers; dem -> demangling_style_name != NULL; dem++)
+ {
+ 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 =
+ savestring (dem -> demangling_style_name,
+ strlen (dem -> demangling_style_name));
+ }
+ }
+ if (current_demangling_style == unknown_demangling)
+ {
+ /* This can happen during initialization if gdb is compiled with
+ a DEMANGLING_STYLE value that is unknown, so pick the first
+ one as the default. */
+ current_demangling_style = demanglers[0].demangling_style;
+ current_demangling_style_string =
+ 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);
+ }
+ }
+}
+
+/* Fake a "set demangling" command. */
+
+void
+set_demangling_style (style)
+ char *style;
+{
+ if (current_demangling_style_string != NULL)
+ {
+ free (current_demangling_style_string);
+ }
+ current_demangling_style_string = savestring (style, strlen (style));
+ set_demangling_command ((char *) NULL, 0);
+}
+
+/* In order to allow a single demangler executable to demangle strings
+ using various common values of CPLUS_MARKER, as well as any specific
+ one set at compile time, we maintain a string containing all the
+ commonly used ones, and check to see if the marker we are looking for
+ is in that string. CPLUS_MARKER is usually '$' on systems where the
+ assembler can deal with that. Where the assembler can't, it's usually
+ '.' (but on many systems '.' is used for other things). We put the
+ current defined CPLUS_MARKER first (which defaults to '$'), followed
+ by the next most common value, followed by an explicit '$' in case
+ the value of CPLUS_MARKER is not '$'.
+
+ We could avoid this if we could just get g++ to tell us what the actual
+ cplus marker character is as part of the debug information, perhaps by
+ ensuring that it is the character that terminates the gcc<n>_compiled
+ marker symbol (FIXME). */
+
+static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
+
+int
+is_cplus_marker (c)
+ int c;
+{
+ return c && strchr (cplus_markers, c) != NULL;
+}
+
+void
+_initialize_demangler ()
+{
+ struct cmd_list_element *set, *show;
+
+ set = add_set_cmd ("demangle-style", class_support, var_string_noescape,
+ (char *) &current_demangling_style_string,
+ "Set the current C++ demangling style.\n\
+Use `set demangle-style' without arguments for a list of demangling styles.",
+ &setlist);
+ show = add_show_from_set (set, &showlist);
+ set -> function.sfunc = set_demangling_command;
+
+ /* Set the default demangling style chosen at compilation time. */
+ set_demangling_style (DEFAULT_DEMANGLING_STYLE);
+ set_cplus_marker_for_demangling (CPLUS_MARKER);
+}
diff --git a/contrib/gdb/gdb/doc/ChangeLog b/contrib/gdb/gdb/doc/ChangeLog
new file mode 100644
index 0000000..42e8393
--- /dev/null
+++ b/contrib/gdb/gdb/doc/ChangeLog
@@ -0,0 +1,1206 @@
+Sat Mar 16 15:10:20 1996 Fred Fish <fnf@cygnus.com>
+
+ From Peter Schauer <Peter.Schauer@Regent.E-Technik.TU-Muenchen.DE>
+ * gdb.texinfo (Expressions): Fix erroneous array constant example.
+
+Sat Mar 16 13:28:45 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdb.texinfo: Add missing "@bullet" to some "@itemize" commands.
+
+Sat Feb 10 03:28:36 1996 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.texinfo (Print settings): Document
+ `set/show print static-members' commands.
+
+Wed Jan 10 14:16:37 1996 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (Native): Document name change, coredep.c to
+ core-aout.c.
+
+Wed Dec 13 12:35:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * stabs.texinfo (Include Files): Document the values the SunOS4
+ linker creates for N_BINCL/N_EINCL/N_EXCL stabs.
+
+Fri Dec 8 21:08:44 1995 Fred Fish <fnf@cygnus.com>
+
+ * gdbint.texinfo (Releases): Change gdb.tar.Z to gdb.tar.gz.
+ Fix typo.
+
+Wed Sep 20 13:14:10 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New target, synonym for
+ realclean.
+
+Thu Aug 3 10:45:37 1995 Fred Fish <fnf@cygnus.com>
+
+ * Update all FSF addresses except those in COPYING* files.
+
+Wed Jul 19 18:43:03 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ From Richard Earnshaw (rearnsha@armltd.co.uk):
+ * gdb.texinfo (convenience variables): Document $_exitcode.
+ (quit): Document optional expression to use as exit code.
+
+Thu Jun 22 21:27:33 1995 Victoria Mixon <victoria@cygnus.com>
+
+ * gdb.texinfo, remote.texi: Brought up to date with various
+ GDB changes.
+
+Tue Jun 20 14:35:38 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * gdb.texinfo: Update dates and versions, fix comments about
+ hardware watchpoints in future releases and about the
+ sharedlibrary command.
+
+Mon May 8 09:30:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Remove node `XCOFF differences'. Describe value of
+ C_FUN stab. Other cleanups.
+
+Wed Apr 19 07:02:19 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.texi (Bootstrapping): Clarify that flush_i_cache is only
+ for the sparc stub.
+
+Tue Apr 11 11:41:49 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi: Clarify which addresses have differing formats
+ depending on the language and which do not.
+
+Tue Mar 28 16:56:22 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * remote.texi (NetWare): Changed example to use BOARD= instead of
+ NODE= argument to reflect correspoding change to gdbserve.nlm.
+
+Fri Mar 17 06:47:02 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Mention the fact that
+ GDB, as well as AIX dbx, supports the size type attribute.
+
+Thu Mar 16 12:11:32 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Document types -31 to -34.
+
+Mon Mar 13 16:49:13 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdb.texinfo (Define): Document $arg0... arguments to commands,
+ and new 'if' and 'while' commands.
+
+Fri Feb 17 15:24:35 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * gdb.texinfo (Artificial arrays): Note use of coerce-to-array-type.
+
+Wed Feb 15 11:59:18 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * all-cfg.texi: New flag, GDBSERVE, for NetWare's gdbserve.nlm.
+ * remote.texi (NetWare): New node, how to use gdbserve.nlm on
+ NetWare targets. Mostly stolen from the Server node.
+
+Fri Feb 10 20:20:08 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Setting): Talk about the language of a source file
+ versus the working language. The old documentation did not match
+ what GDB did.
+
+Wed Feb 1 20:26:36 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Source Files): Document N_SO used to mark the end
+ of a source file.
+
+Mon Jan 23 14:23:37 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Processes): New node.
+
+Tue Jan 17 14:09:03 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * remote.texi: Update documentation of set/show mipsfpu.
+
+
+Sun Sep 4 16:47:21 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Removed mentions of some incorrectly placed and
+ obsolete conditionals, described some others.
+
+Mon Aug 1 15:42:39 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo: Remove references to BROKEN_LARGE_ALLOCA and
+ SET_STACK_LIMIT_HUGE; they were removed from GDB 14 May 1994.
+
+Mon Aug 1 15:12:02 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Put regex conditionals in their own table.
+
+Tue Jul 26 18:32:52 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Removed mentions of many obsolete conditionals,
+ described or fixed the descriptions of many others.
+
+Sun Jul 17 14:14:03 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdb.texinfo: Add some more credits.
+ * gdbint.texinfo: Capitalize GDB consistently, describe some
+ macros and remove some.
+
+Thu Jul 14 18:43:17 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * gdbint.texinfo: Removed mentions of many incorrectly placed and
+ obsolete conditionals, described some others.
+
+Tue Jul 12 12:23:15 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.texinfo (help targets): Changed to `help target', which
+ is the correct gdb command.
+
+Wed Jun 22 18:00:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi (TODO): New node, for keeping track of annotations
+ suggested but not yet implemented.
+
+Wed Jun 1 16:10:45 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Statics): Value of xcoff C_BSTAT points to
+ another symbol, it is not the address itself.
+
+Thu May 5 20:23:36 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * stabs.texinfo (Stab Section Basics): Add comment about alignment
+ of stabs-in-coff sections.
+
+Wed May 4 06:26:11 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi: Change edition to 0.5 and date to May 1994.
+ Add index.
+ (Frames): New node, for frame annotation.
+ (Displays): New node, for display annotation.
+
+ * remote.texi (MIPS Remote): Say that set timeout doesn't apply
+ when waiting for your program to stop.
+
+Fri Apr 29 18:24:46 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi (Breakpoint Info): Document annotation of header
+ fields and record annotation.
+
+Thu Apr 28 07:44:28 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * annotate.texi: New file, to document annotations.
+
+Thu Apr 21 14:20:51 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in (clean): Don't remove GDBvn.texi (apparently on Jan
+ 16 I meant to make this change but did not). Do remove gdb-cfg.texi.
+
+Wed Apr 20 11:22:48 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stab Section Basics): Say what is in .stab
+ section, and say n_strx field is compilation unit relative.
+ * stabs.texinfo: Don't use @code for a.out when it is the name of
+ an object file format.
+
+Wed Apr 13 20:29:54 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * gdb.texinfo: Refer to file names, not path names, per rms
+ convention.
+ (Arguments): Fix typo.
+
+Thu Mar 24 08:09:12 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Global Variables): Talk about stabs in files
+ where variables are referenced, but not defined.
+
+Wed Mar 23 07:16:36 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Move stuff on @ and # type descriptors from node
+ Cplusplus to new nodes Member Type Descriptor and Method Type
+ Descriptor. Re-write stuff for #.
+
+Wed Mar 16 08:20:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Print Settings): Don't document "set print
+ fast-symbolic-addr off". The bug which it worked around was fixed
+ on 25 Feb 94 in coffread.c, so I'm nuking the command.
+
+ * stabs.texinfo (Alternate Entry Points): New node, rewritten from
+ N_ENTRY node.
+
+ * stabs.texinfo (Type Descriptors): Add 'Y' type descriptor.
+
+Tue Mar 15 08:43:02 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo (Host Conditionals, Target Conditionals): Remove
+ references to ieee-float.c.
+
+Fri Mar 11 08:09:40 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Set Breaks): Update documentation for tbreak to
+ match what the code actually does.
+
+Wed Mar 9 19:43:05 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Symbol Descriptors): Add OS9000 symbol descriptor s.
+
+Tue Mar 1 17:04:43 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * stabs.texinfo (Type Descriptors): Add OS9000 type descriptors c,
+ i, and b.
+
+Wed Feb 23 10:44:18 1994 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * stabs.texinfo: Document N_RBRAC as function relative for COFF as
+ well as for ELF and SOM. Unify the descriptions of ELF and SOM
+ as "stabs in sections" rather than just saying "ELF and SOM".
+ Also make that stuff apply to COFF.
+
+Fri Feb 18 08:25:58 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Formatting Documentation): Change GhostScript to
+ Ghostscript.
+
+Fri Feb 4 06:31:31 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Continuing and Stepping): When talking about "step"
+ versus functions without line numbers, also mention stepping into
+ them as well as "step" when you are in them. Tell the user how to
+ deal with the situation. Add comment about "debugging information".
+
+Thu Feb 3 11:39:59 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Enumerations): Document restriction on where
+ enumeration types can appear and still win with GDB.
+
+Wed Feb 2 11:29:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Document format for type
+ -16.
+
+Thu Jan 27 16:53:56 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Selection, Frame Info): Update information about
+ arbitrary frame specficiations.
+
+Wed Jan 26 15:31:57 1994 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, remote.texi: general editing pass prior to Net release
+
+Tue Jan 25 12:12:04 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (String Field): Discuss continuing stabs with ?.
+
+Wed Jan 19 06:39:24 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * stabs.texinfo (Non-Stab Symbol Types): Mention N_SET* | N_EXT.
+
+Sun Jan 16 12:43:32 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Re-do stuff about C_BSTAT and move from XCOFF
+ Differences node to Statics node.
+ (Statics): Discuss XCOFF use of V symbol descriptor.
+
+ * Makefile.in: Remove refcard.dvi and GDBvn.texi in realclean,
+ not clean.
+
+Wed Jan 12 21:29:54 1994 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo (Print Settings): Document `set print
+ fast-symbolic-addr' and improve the doc for some other
+ `set print's.
+
+Mon Jan 3 17:23:07 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (String Field): Talk about defining several type
+ numbers at once.
+ Fix lint regarding changing node ELF Transformations to
+ ELF and SOM Transformations.
+
+Fri Dec 31 00:42:43 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Insert Peter Kessler's name as inventor (I think).
+
+Tue Dec 28 09:30:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Cross-References): `::' is for nested types only
+ within <>.
+ (Structures): Document static members.
+
+Mon Dec 27 13:55:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Document S type attribute.
+
+Sun Dec 26 20:46:36 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * stabs.texinfo: Add notes about stabs-in-som where appropriate.
+
+Fri Dec 3 19:13:19 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Fix a few typos.
+
+Sun Nov 28 18:06:25 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, remote.texi: formatting improvements
+
+ * gdb.texinfo (New Features): mention threads.
+ (Summary, C): fix xrefs in newly contributed text.
+ (Threads): index entries, clarifications, example
+ (passim): minor typos fixed, phrasing improvements
+
+ * remote.texi (Bootstrapping): rephrase text on ^C and add index
+ entries; (Server): explain use of gdbserver w/real-time systems,
+ add example of conflicting TCP port; (MIPS Remote) break up
+ running text into table, highlighting commands, and add example.
+
+Wed Nov 24 14:15:56 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * refcard.tex: avoid bad linebreaks even when REFEDITS=psrc.sed
+
+Fri Nov 12 16:10:58 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Nested Symbols): New node.
+ (String Field, Symbol Descriptors, Cross-References): Refer to it.
+
+Thu Nov 11 13:26:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs in ELF): Clarify how Bbss.bss work with respect
+ to picking which Bbss.bss symbol to use, and (because there seems to
+ be no good way of doing it) re-write some of the text to make it
+ sound like Bbss.bss isn't such a great idea after all (as currently
+ designed).
+
+ * gdb.texinfo (C): In addition to saying people have to use g++ for
+ good results, say they have to use stabs. Specifically say cfront
+ doesn't work well.
+ (Summary): Merge in information on Modula-2, Pascal, and Chill from
+ the gdb README. Add xrefs to places where the support for the various
+ languages is described in detail.
+
+Mon Nov 8 11:47:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Clean up stuff about visibility and virtual
+ characters.
+
+ * stabs.texinfo (N_M2C): Cite Sun doc.
+
+Fri Nov 5 16:27:27 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: updates re threads.
+ * remote.texinfo: avoid index entries starting with digits.
+
+Tue Nov 2 09:08:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Enumerations): Talk about large, negative and
+ octal values. Clean up cross reference to type attributes.
+ (String Field): Say that GDB 4.11 supports size attribute.
+
+Sun Oct 31 13:31:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.texi (VxWorks Remote): Clarify that rebuilding VxWorks kernel
+ is a mandatory step. Make the stuff about that more concise.
+
+Wed Oct 27 00:25:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Class Names): New node.
+
+ * gdb.texinfo (Command Files): Explain order of init file reading.
+
+ * remote.texi (Bootstrapping): Talk about getting the serial driver
+ to deal with ^C sent by gdb to stop the remote system.
+
+Mon Oct 25 03:25:41 1993 Tom Lord (lord@cygnus.com)
+
+ * libgdb.texinfo (I/O): incorporated better phrasing from rich.
+
+ * libgdb.texinfo (Defining Commands): made the DOC arg
+ to gdb_define_app_command a char * instead of char **
+ per a suggestion from kingdon.
+
+ * libgdb.texinfo: total rewrite from a different starting
+ premise.
+
+Wed Oct 20 18:07:44 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Local Variable Parameters): Re-write paragraph on
+ floats passed as doubles (to improve clarity).
+
+Tue Oct 19 14:21:18 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo (Source Path): index entries for $cwd, $pdir
+
+ * a4rc.sed: update to work with Andreas Vogel papersize params
+
+ * refcard.tex: use Andreas Vogel simplifications of papersize
+ params; remove useless version info; update copyright date.
+
+Tue Oct 19 10:46:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Symbols): Add class NAME to doc for ptype.
+
+Tue Oct 12 09:11:45 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Files): Say what address the load command loads it at.
+
+ * stabs.texinfo (Common Blocks): Minor cleanups.
+
+ * stabs.texinfo: Update ld stabs in elf relocation to reflect the fact
+ that Sun has backed away from the linker kludge and thus the relevant
+ issue is changes to the SunPRO tools, not the Solaris linker.
+
+ * stabs.texinfo (Traditional Integer Types): Clean up description
+ of octal bounds a little bit. Document extra leading zeroes.
+
+Thu Oct 7 16:15:37 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Signaling): Update for symbolic symbol names
+ and add a section explaining the difference between the GDB
+ signal command and the shell kill utility.
+
+Wed Oct 6 13:23:01 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * libgdb.texinfo: added `@' to braces that were unescaped.
+
+Mon Oct 4 10:42:18 1993 Tom Lord (lord@rtl.cygnus.com)
+
+ * libgdb.texinfo: new file. Spec for the gdb library.
+
+Sun Oct 3 15:26:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Include Files): Fix typo (start -> end).
+
+Thu Sep 30 18:24:56 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, remote.texi: assorted small improvements, mostly
+ from Melissa at FSF's editing pass.
+
+Thu Sep 30 11:54:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo: Remove stuff about ar and 14 character filenames.
+ I believe this was fixed by the 13 Sep 89 change to print_frame_info.
+ Also, modern versions of ar like BSD 4.4 or SVR4 don't have this bug.
+
+Wed Sep 22 21:22:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * remote.texi (Bootstrapping): Discuss 386 call gates.
+
+Sat Sep 18 17:10:44 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * stabs.texinfo (Based Variables): New node.
+
+Thu Sep 16 17:48:55 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Re-write discussions of
+ names, sizes, and formats to suggest how not to lose.
+
+Sat Sep 11 09:35:11 1993 Jim Kingdon (kingdon@poseidon.cygnus.com)
+
+ * stabs.texinfo (Methods): Fix typo.
+
+Fri Sep 10 06:34:20 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * gdb.texinfo: Fix a few typos.
+
+Wed Sep 8 09:11:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo: Clarify how well it works with Fortran.
+
+ * stabs.texinfo (Stabs In ELF, Statics, ELF Transformations):
+ More on relocating stabs in ELF files.
+
+Tue Sep 7 13:45:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs In ELF): Talk about N_FUN value.
+
+Mon Sep 6 19:23:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Local Variable Parameters): Talk about nameless
+ parameters on VAX.
+
+Fri Sep 3 17:06:08 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: @up/@down -> @raisesections/@lowersections
+
+Fri Sep 3 12:04:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Make info author notice match the TeX author notice.
+
+Tue Aug 31 13:21:06 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * stabs.texinfo: Initial-caps all words in node names and
+ non-trivial words in section names.
+
+Mon Aug 30 11:13:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Many minor cleanups.
+
+ * stabs.texinfo: Remove @deffn except from Expanded Reference node.
+
+Sat Aug 28 12:08:09 1993 David J. MacKenzie (djm@edison.eng.umd.edu)
+
+ * stabs.texinfo: Remove full description of big example.
+ It's not really helpful; just use pieces of it where appropriate.
+ Add more Texinfo formatting directives (@samp, etc.).
+ Use @deffn to define stab types.
+ Eliminate some wordiness. Break up some nodes.
+ Add an (alphabetized) index of symbol types.
+ Use consistent capitalization style in node and section names.
+
+Thu Aug 26 06:36:31 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * gdb.texinfo: Change typo "Two two" to "The two".
+
+Sun Aug 22 12:15:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (XCOFF-differences): Remove references to
+ non-existent types N_DECL and N_RPSYM.
+
+ * stabs.texinfo (String Field): Say that type attributes bug is
+ fixed in GDB 4.10, since it is.
+
+ * stabs.texinfo: Clean up djm cleanups, and more cleanups of my own.
+
+Sat Aug 21 04:32:28 1993 David MacKenzie (djm@cygnus.com)
+
+ * stabs.texinfo: Formatting cleanups.
+
+Fri Aug 20 20:49:53 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: When explaining the n_type of a stab, standardize
+ how we do it ('#' as a comment indicator, "36 is N_FUN" as text,
+ no tabs, use @r).
+ (Global Variables): Clean up.
+
+Tue Aug 17 15:57:27 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stack Variables): Re-write.
+
+Mon Aug 16 21:20:08 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs-in-elf): Talk about getting the start
+ addresses of a source file. Also revise formatting.
+ Change "object module" or "object file" to "source file".
+ Various: Miscellaneous cleanups.
+
+Thu Aug 12 15:11:51 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Point to mangling info in gcc's gpcompare.texi.
+
+Tue Aug 10 16:57:49 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * gdbint.texinfo: Removed many nonsensical machine-collected
+ host and target conditionals, described some of the remainder.
+
+Tue Aug 10 13:28:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo (Getting Started): Use @itemize, not @table.
+
+ * gdbint.texinfo (Top): Add name to @top line, and re-write the
+ paragraph which follows.
+
+ * gdbint.texinfo (Host): Use @code not @samp for Makefile
+ variables. Looks better and avoids overful hbox.
+
+Fri Jul 30 18:26:21 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Procedures): Improve stuff on nested functions.
+
+Thu Jul 29 15:10:58 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * remote.texi: (MIPS Remote) clearer doc for set/show timeout,
+ retransmit-timeout
+
+Thu Jul 29 13:16:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdbint.texinfo: Update statement about `some ancient Unix
+ systems, like Ultrix 4.0' to Ultrix 4.2.
+
+Wed Jul 28 15:26:53 1993 Roland H. Pesch (pesch@el_bosque.cygnus.com)
+
+ * h8-cfg.texi, all-cfg.texi: new flag GDBSERVER
+
+ * Makefile.in: depend on remote.texi rather than gdbinv-s.texi
+
+ * remote.texi: (Server) New node on gdbserver. (Remote Serial,
+ ST2000 Remote, MIPS Remote): mention `host:port' syntax for TCP.
+
+ * remote.texi: new name for former gdbinv-s.texi
+
+ * gdb.texinfo: use remote.texi rather than gdbinv-s.texi
+
+Wed Jul 28 08:26:24 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * gdbinv-s.texi: Documented timeout and retransmit-timeout
+ variables for MIPS remote debugging protocol.
+
+Mon Jul 26 13:00:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): FORTRAN LOGICAL fix.
+
+Tue Jul 20 16:30:41 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * Makefile.in (refcard.dvi): Use srcdir where necessary.
+
+Mon Jul 19 12:02:50 1993 Roland H. Pesch (pesch@cygnus.com)
+
+ * gdb.texinfo: repair conditional bugs in text markup
+
+Fri Jul 16 18:57:50 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, all-cfg.texi, h8-cfg.texi: introduce MOD2 switch
+ to select Modula-2 material.
+
+Thu Jul 15 13:15:01 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Cleanups regarding statics.
+
+ * gdbinv-s.texi (Bootstrapping): Document exceptionHandler.
+ (Debug Session): Mention exceptionHandler. Add xref to Bootstrapping.
+
+Mon Jul 12 13:37:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: N_MAIN is sometimes used for C.
+
+Fri Jul 9 09:47:02 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdbint.texinfo (Host, Target Conditionals): Remove TM_FILE_OVERRIDE.
+
+Tue Jul 6 12:41:28 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo (Target Conditionals): Remove NO_TYPEDEFS,
+ removed from the code by Kingdon.
+
+Tue Jul 6 12:24:34 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * gdb.texinfo (Break Commands): Remove stuff about flushing terminal
+ input when evaluating breakpoint conditions; the bug has been fixed.
+
+ * gdb.texinfo (Continuing and Stepping): Argument to "continue"
+ sets the ignore count to N-1, not to N.
+
+Thu Jul 1 14:57:42 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * refcard.tex (\hoffset): correct longstanding error to match
+ intended offset; avoids cutting off edge on some printers
+
+Wed Jun 30 18:23:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Parameters): Say that order of stabs is significant.
+
+Fri Jun 25 21:34:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Common Blocks): Say what Sun FORTRAN does.
+
+Fri Jun 25 16:15:10 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * Makefile.in: (REFEDITS) new var to control whether PS or CM
+ fonts and whether US or A4 paper for GDB refcard; (refcard.dvi)
+ collect sed edits if any, apply to refcard before formatting;
+ (refcard.ps) stop implying PS fonts if PS output requested;
+ (lrefcard.ps) delete extra target for variant PS fonts
+
+ * refcard.tex: parametrize papersize dependent info, collect
+ in easily replaced spot
+
+ * a4rc.sed: new file, edits to refcard for A4 paper
+
+Fri Jun 25 14:21:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Type -16 is 4 bytes.
+
+Wed Jun 23 15:02:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Negative Type Numbers): Minor character cleanups.
+
+Tue Jun 22 16:31:52 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Express disapproval of 'D' symbol descriptor
+ politely rather than rudely.
+
+Fri Jun 18 19:42:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Document common blocks.
+
+Fri Jun 18 12:12:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * stabs.texinfo: Add some basic info about stabs-in-elf.
+
+Fri Jun 18 13:57:09 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Top): Minor cleanup.
+
+Mon Jun 14 16:16:51 1993 david d `zoo' zuhn (zoo at rtl.cygnus.com)
+
+ * Makefile.in (install-info): remove parentdir support
+
+Tue Jun 15 18:11:39 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo (Copying): delete this node and references to it;
+ RMS says this manual need not carry GPL. (passim): Improvements
+ from last round at FSF, largely due to Ian Taylor review, and
+ minor formatting improvements.
+
+ * gdbinv-s.texi (passim): Improvements from last round at FSF,
+ largely due to Ian Taylor review. (Debug Session): minor edits to
+ new text.
+
+Sun Jun 13 12:52:39 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (realclean): Remove info and dvi files too.
+
+Sat Jun 12 16:09:22 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * {all,h8}-config.texi: Rename to *-cfg.texi for 14 char filenames.
+ * Makefile.in: Change accordingly. gdb-config.texi -> gdb-cfg.texi.
+ * gdb.texinfo: Change accordingly.
+
+ * stabs.texinfo: Clean up N_{L,R}BRAC. Discuss what addresses of
+ N_{L,R}BRAC,N_SLINE are relative to.
+
+Fri Jun 11 15:15:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (GDBvn.texi): Update atomically.
+
+Wed Jun 9 10:58:16 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdbinv-s.texi (Debug Session): Document exceptionHook.
+
+Tue Jun 8 13:42:04 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdb.texinfo (Print Settings): Move all stuff relating to symbolic
+ addresses together. Also motivate the set print symbol-filename
+ command and suggest other solutions.
+
+Tue Jun 1 22:46:43 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdb.texinfo (set print elements): Note that the number of
+ elements is set to unlimited by "set print elements 0".
+
+Mon May 31 08:06:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Builtin Type Descriptors): Try to clarify what
+ NF_LDOUBLE means.
+ (Stab Types): Include Solaris stab types.
+ (Procedures): Document Solaris extensions.
+
+Thu May 27 06:20:42 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * gdb.texinfo: Add `set print symbol-filename' doc.
+
+Wed May 26 00:26:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Arrays): Talk about type definition vs. type
+ information.
+
+ * stabs.texinfo (Builtin Type Descriptors): Talk about omitting
+ the trailing semicolon.
+
+Tue May 25 14:49:42 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Line Numbers, Source Files): Re-write these two nodes
+ and merge in other parts of the document addressing these subjects.
+ gdbint.texinfo (XCOFF): Remove info which is now in stabs.texinfo.
+
+ * stabs.texinfo (Subranges, Arrays): Try to explain about the semicolon
+ at the end of a range type.
+
+ * stabs.texinfo (Subranges): "A offset" and "T offset" are not
+ AIX extensions.
+
+Mon May 24 09:00:33 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Stabs Format): Misc fixes.
+
+Sat May 22 10:40:56 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Constants): Allow an `e' constant to be non-enum.
+ (Traditional builtin types): Document convex convention for long long.
+ (Negative builtin types): Discuss type names, and misc fixes.
+
+Fri May 21 11:20:31 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Builtin Type Descriptors): Document the floating
+ point types used with @samp{R} type descriptor.
+ (Symbol Descriptors): Describe how to handle conflict between
+ different meanings of @samp{P} symbol descriptor.
+
+Thu May 20 13:35:10 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo: Remove node Quick Reference and put its children
+ directly under the main menu.
+
+ * stabs.texinfo: Many more changes to bring it into line with
+ AIX documentation and reality. I think it now has all the
+ information from the AIX documentation, except that I burned
+ out when I got to variant records (Pascal and Modula-2) and
+ all the COBOL types. Oh well, we can add them later when we're
+ worrying more about those languages.
+
+ * stabs.texinfo (Automatic variables): Talk about what it means
+ to omit the symbol descriptor.
+
+Tue May 18 17:59:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stabs.texinfo (Parameters): Add "(sometimes)" when describing
+ gcc2 behavior with promoted args.
+
+Fri May 14 21:35:29 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: include readline appendices in info version of manual
+
+Fri May 7 11:56:18 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.texi (Remote Serial): describe new ^C behavior in
+ target remote.
+
+ * gdb.texinfo (Machine Code): more index entries for disassemble
+
+Fri May 7 10:12:30 1993 Fred Fish (fnf@cygnus.com)
+
+ * Clarify the intended use of the gdb-testers and gdb-patches
+ mailing lists, and shrink gzip comment.
+
+Thu May 6 16:39:50 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo (Shell Commands): do not mention SHELL env var in
+ DOSHOST configuration of manual.
+
+ * gdb.texinfo (MIPS Stack): new node.
+
+ * all-config.texi (MIPS) new switch.
+
+ * gdbinv-s.texi (Nindy Options) Remove two instances of future
+ tense; (MIPS Remote) new node.
+
+ * gdb.texinfo (passim) rephrases to work around makeinfo @value
+ bug; (Environment) less passive, other small cleanups in text about
+ .cshrc/.bashrc; (Invoking GDB) new MIPS Remote menu entry;
+ (Remote) new MIPS Remote menu entry.
+
+Thu Apr 29 09:36:25 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo: Many changes to include information from the
+ AIX documentation.
+
+ * gdb.texinfo (Environment): Mention pitfall with .cshrc.
+
+Tue Apr 27 14:02:57 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdbint.texinfo (new node Debugging GDB, elsewhere):
+ Move a bunch of information from ../README.
+ (Getting Started): New node.
+
+Fri Apr 23 17:21:13 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.texi, gdb.texinfo: include Hitachi SH target
+
+ * gdb.texinfo: advance manual revision dates to present
+
+ * gdbinv-s.texi, gdb.texinfo, all-config.texi, h8-config.texi:
+ stop using silly Roman numerals in @set variable names
+
+Fri Apr 23 07:30:01 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Parameters): Keep trying to get this right.
+
+Wed Apr 21 15:18:47 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Parameters): More on "local parameters".
+
+Mon Apr 19 08:00:51 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Parameters): Re-do "local parameters" section.
+
+Sun Apr 18 09:47:45 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo (Symbol descriptors): Re-do using @table and @xref.
+ (Parameters): Rewrite.
+ (xcoff-differences, Sun-differences): Minor changes.
+
+Thu Apr 15 02:35:24 1993 John Gilmore (gnu@cacophony.cygnus.com)
+
+ * stabs.texinfo: Minor cleanup.
+
+Wed Apr 14 17:31:00 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * gdbint.texinfo: Minor xcoff stuff.
+
+Wed Apr 7 14:11:07 1993 Fred Fish (fnf@cygnus.com)
+
+ * gdbint.texinfo: Update for new config directory structure.
+ Add info about internal type data structures.
+
+Mon Apr 5 09:06:30 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (SFILES_INCLUDED): gdb-config.texi is no longer in
+ $(srcdir).
+ (gdb-config.texi): Depend on file in $(srcdir).
+
+Fri Apr 2 16:55:13 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo: Fixes about N_SO.
+
+Fri Mar 26 18:00:35 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: include list of nonstandard init file names
+
+ * *-config.texi: new switch GENERIC for text that applies *only*
+ to (usual) multiple-target version of manual
+
+ * gdb.texinfo, gdbinv-s.texi: Update conditional markup to correct
+ h8 config
+
+ * gdb.texinfo: depend on latest fixed makeinfo, use conditionals
+ in menus (rather than conditionally selected multiple alternative
+ menus).
+
+ * Makefile.in: define and use DOC_CONFIG var to select
+ configuration for GDB user manual.
+
+ * gdb-config.texi: delete from repository, generate from Makefile.
+
+ * all-config.texi: normal `generic' configuration file, formerly
+ stored as gdb-config.texi
+
+Wed Mar 24 14:03:19 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: add dvi target to build all .dvi files
+
+Tue Mar 23 16:03:24 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, gdvinv-s.texinfo: formatting improvements.
+
+Fri Mar 19 21:46:50 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Doc NO_MMALLOC and NO_MMALLOC_CHECK as
+ host conditionals.
+ * stabs.texinfo: More array fixes inspired by Jim's.
+
+Fri Mar 19 10:23:34 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stabs.texinfo: Fixes re arrays and continuations.
+
+ * gdbint.texinfo: Add XCOFF node.
+
+Mon Mar 8 15:52:18 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo: Add `set print max-symbolic-offset' doc.
+
+Sun Feb 21 17:09:38 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * stabs.texinfo: Fix for array types to mention lower bounds.
+
+Thu Feb 18 01:19:49 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Update PTRACE_ARG3_TYPE doc, pull PT_*.
+
+Wed Feb 17 08:15:24 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Remove SET_STACK_LIMIT_HUGE from target defines.
+
+Thu Feb 11 10:38:40 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Fix thinko (NM_FILE => NAT_FILE). Found
+ by Michael Ben-Gershon <mybg@CS.HUJI.AC.IL>.
+
+Wed Feb 10 23:59:19 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Eliminate IBM6000_HOST, document IBM6000_TARGET.
+
+Tue Feb 9 18:26:21 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, gdbinv-s.texi: misc updates
+
+Sat Feb 6 10:25:47 1993 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Brief documentation for longjmp support,
+ from an email msg by Stu.
+
+Fri Feb 5 14:10:15 1993 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Fix description of floating point "range"
+ types (which really define basic types). Reported by Jim Meehan,
+ <meehan@src.dec.com>.
+
+ * gdbint.texinfo: Remove COFF_NO_LONG_FILE_NAMES define, now gone.
+
+Thu Feb 4 13:56:46 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * gdbint.texinfo: Slightly expand section on supporting a new
+ object file format.
+
+Thu Feb 4 01:49:04 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (refcard.ps, lrefcard.ps): Remove psref.tex
+ intermediate file.
+
+Tue Feb 2 12:18:06 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, gdbinv-s.texi: miscellaneous stylistic cleanups
+
+Mon Feb 1 15:35:47 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.texi: z8000 simulator target name is just "sim"
+
+ * gdbinv-s.texi: Mention that Z8000 simulator can simulate Z8001
+ as well as Z8002.
+
+Sat Nov 28 06:51:35 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Add sections on clean design and on how to send
+ in changes.
+
+Mon Nov 9 23:57:02 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Add how to declare the result of make_cleanup.
+
+Mon Oct 26 11:09:47 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo: Fix typo, reported by Karl Berry.
+
+Fri Oct 23 00:41:21 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo: Add opcodes dir to GDB distribution description.
+
+Sat Oct 10 18:04:58 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * gdbint.texinfo: fixed a stray email address (needs @@),
+ added @table @code to node "Native Conditionals"
+
+Tue Sep 22 00:34:15 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Describe coding style of GDB.
+
+Mon Sep 21 19:32:16 1992 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Minor wording changes.
+
+Tue Sep 15 02:57:09 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Improve release doc slightly.
+
+Fri Sep 11 01:34:25 1992 John Gilmore (gnu@sphagnum.cygnus.com)
+
+ * gdbint.texinfo: Improve doc of GDB config macros.
+
+Wed Sep 9 16:52:06 1992 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Remove Bothner's changes for C++ nested types.
+ These will be reinserted when examined.
+
+Mon Aug 24 01:17:55 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Make a start at documenting all the #if macros
+ in GDB. At least list them all, and start separating them into
+ host-specific and target-specific.
+
+Tue Aug 18 15:59:13 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdbinv-s.m4.in: refrain from using @cartouche for just a few
+ examples (not consistent w others).
+ gdb.texinfo: issue disclaimer paragraph on cmdline options only
+ for generic vn of doc
+
+Tue Aug 18 14:53:27 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: always create installation directories.
+
+Tue Aug 18 14:11:50 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: in h8 config, do not describe searching commands.
+
+Mon Aug 17 18:07:59 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo, none.m4, h8.m4, gdbinv-s.m4.in: improve H8/300
+ conditionals; introduce a few generic switches that may be
+ useful for other cross-dev or dos-hosted configs.
+
+ * gdb.texinfo: fix typo in "info reg" description
+
+Sun Aug 16 01:16:18 1992 John Gilmore (gnu@cygnus.com)
+
+ * stabs.texinfo: Minor updates from running TeX over it.
+ * Makefile.in (stabs.dvi, stabs.ps): Add.
+
+Sat Aug 15 20:52:24 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * stabs.texinfo: Stabs documentation, written by Julia Menapace.
+ First pass at converting it to texinfo.
+
+Sat Aug 15 03:14:59 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdb.texinfo, refcard.tex: Document mult args on `info reg'.
+ * Makefile.in (refcard.ps, lrefcard.ps): Add missing $(srdir).
+
+Fri Aug 14 21:08:47 1992 John Gilmore (gnu@cygnus.com)
+
+ * gdbint.texinfo: Add section on partial symbol tables.
+
+Sat Jun 20 16:31:10 1992 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: document `set remotedebug' and `set
+ rstack_high_address'.
+
+Thu May 14 17:09:48 1992 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * gdb.texinfo: slight expansion of new text on reading info files
+ * gdbinv-s.m4.in: correct and expand info on cross-debugging
+ H8/300 from DOS.
+
+Tue May 12 12:22:47 1992 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: `info user' => `show user'. Noticed by David Taylor.
+
+Mon May 11 19:06:27 1992 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: Say how to read the `info' files.
+
+Tue May 5 12:11:38 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: gm4 -> m4.
+
+Fri Apr 10 17:50:43 1992 John Gilmore (gnu at rtl.cygnus.com)
+
+ * gdb.texinfo: Update for GDB-4.5. Move `Formatting
+ Documentation' ahead of `Installing GDB' to match README.
+ Update shared library doc, -readnow and -mapped, and directory
+ structure (add glob and mmalloc). Update configure doc.
+
+Tue Mar 24 23:28:38 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: remove $(srcdir) from gdb.info rule.
+
+Sat Mar 7 18:44:50 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * Makefile.in: commented out gdb-all.texinfo rule. This is
+ temporary.
+
+Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in: removed traces of namesubdir,
+ -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
+ copyrights to '92, changed some from Cygnus to FSF.
+
+Fri Dec 13 09:47:31 1991 John Gilmore (gnu at cygnus.com)
+
+ * gdb.texinfo: Improve how we ask for bug reports.
+
+Tue Dec 10 04:07:21 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: infodir belongs in datadir.
+
+Fri Dec 6 23:57:34 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: remove spaces following hyphens, bsd make can't
+ cope. install using INSTALL_DATA. added clean-info. added
+ standards.text support.
+
+Thu Dec 5 22:46:12 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: idestdir and ddestdir go away. Added copyrights
+ and shift gpl to v2. Added ChangeLog if it didn't exist. docdir
+ and mandir now keyed off datadir by default.
+
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/contrib/gdb/gdb/doc/GDBvn.texi b/contrib/gdb/gdb/doc/GDBvn.texi
new file mode 100644
index 0000000..f90e24d
--- /dev/null
+++ b/contrib/gdb/gdb/doc/GDBvn.texi
@@ -0,0 +1 @@
+@set GDBVN 4.16
diff --git a/contrib/gdb/gdb/doc/Makefile.in b/contrib/gdb/gdb/doc/Makefile.in
new file mode 100644
index 0000000..385b444
--- /dev/null
+++ b/contrib/gdb/gdb/doc/Makefile.in
@@ -0,0 +1,331 @@
+##Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+# Makefile for GDB documentation.
+# This file is part of GDB.
+
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+srcdir = .
+
+prefix = /usr/local
+
+infodir = $(prefix)/info
+
+SHELL = /bin/sh
+
+INSTALL = install -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+
+# main GDB source directory
+gdbdir = $(srcdir)/..
+
+# where to find texinfo; GDB dist should include a recent one
+TEXIDIR=${gdbdir}/../texinfo
+
+# where to find makeinfo, preferably one designed for texinfo-2
+MAKEINFO=makeinfo
+
+# where to find texi2roff, ditto
+TEXI2ROFF=texi2roff
+
+# Where is the source dir for the READLINE library doc?
+# Traditionally readline is in .. or .
+READLINE_DIR = ${gdbdir}/../readline/doc
+
+SET_TEXINPUTS = TEXINPUTS=${TEXIDIR}:.:$(srcdir):$(READLINE_DIR):$$TEXINPUTS
+
+# There may be alternate predefined collections of switches to configure
+# the GDB manual. Normally this is not done in synch with the software
+# config system, since this choice tends to be independent; most people
+# want a doc config of `all' for a generic manual, regardless of sw config.
+DOC_CONFIG = all
+
+# This list of sed edits will edit the GDB reference card
+# for what fonts and what papersize to use.
+# By default (NO edits applied), the refcard uses:
+# - Computer Modern (CM) fonts
+# - US letter paper (8.5x11in)
+# List some of the following files for alternative fonts and paper:
+# a4rc.sed use A4 paper (297 x 210 mm)
+# psrc.sed use PostScript fonts (Karl Berry short TeX names)
+# lpsrc.sed use PostScript fonts (full PostScript names in TeX)
+# e.g. for A4, Postscript: REFEDITS = a4rc.sed psrc.sed
+# for A4, CM fonts: REFEDITS = a4rc.sed
+# for US, PS fonts: REFEDITS = psrc.sed
+# for default:
+REFEDITS =
+
+# Don Knuth's TeX formatter
+TEX = tex
+
+# auxiliary program for sorting Texinfo indices
+TEXINDEX = texindex
+
+# Main GDB manual's source files
+SFILES_INCLUDED = gdb-cfg.texi $(srcdir)/remote.texi
+
+SFILES_LOCAL = $(srcdir)/gdb.texinfo GDBvn.texi $(SFILES_INCLUDED)
+
+SFILES_DOC = $(SFILES_LOCAL) \
+ $(READLINE_DIR)/rluser.texinfo $(READLINE_DIR)/inc-hist.texi
+
+#### Host, target, and site specific Makefile fragments come in here.
+###
+
+all install:
+
+info: gdb.info gdbint.info stabs.info
+dvi: gdb.dvi refcard.dvi gdbint.dvi
+all-doc: gdb.info gdb.dvi refcard.dvi gdb-internals gdbint.dvi
+
+install-info: info
+ for i in *.info* ; do \
+ $(INSTALL_DATA) $$i $(infodir)/$$i ; \
+ done
+
+STAGESTUFF = *.info* gdb-all.texi GDBvn.texi
+
+# Copy the object files from a particular stage into a subdirectory.
+stage1: force
+ -mkdir stage1
+ -mv $(STAGESTUFF) stage1
+
+stage2: force
+ -mkdir stage2
+ -mv $(STAGESTUFF) stage2
+
+stage3: force
+ -mkdir stage3
+ -mv $(STAGESTUFF) stage3
+
+against=stage2
+
+comparison: force
+ for i in $(STAGESTUFF) ; do cmp $$i $(against)/$$i ; done
+
+de-stage1: force
+ -(cd stage1 ; mv -f * ..)
+ -rmdir stage1
+
+de-stage2: force
+ -(cd stage2 ; mv -f * ..)
+ -rmdir stage2
+
+de-stage3: force
+ -(cd stage3 ; mv -f * ..)
+ -rmdir stage3
+
+clean-info:
+ rm -f gdb.info* gdbint.info* stabs.info*
+
+clean-dvi:
+ rm -f gdb.dvi gdbint.dvi stabs.dvi sedref.dvi
+
+mostlyclean: clean-info clean-dvi
+ rm -f gdb.?? gdb.??? gdb.mm gdb.ms gdb.me
+ rm -f links2roff
+ rm -f refcard.ps lrefcard.ps refcard.log sedref.* *~
+ rm -f gdbint.?? gdbint.??? stabs.?? stabs.???
+
+clean: mostlyclean
+ rm -f rluser.texinfo inc-hist.texi gdb-cfg.texi
+
+distclean: clean
+ rm -f Makefile config.status
+
+# GDBvn.texi and refcard.dvi are distributed, so they should not be
+# removed by "clean" or "distclean".
+maintainer-clean realclean: distclean clean-dvi clean-info
+ rm -f GDBvn.texi refcard.dvi
+
+# GDB QUICK REFERENCE (dvi output)
+refcard.dvi : refcard.tex $(REFEDITS)
+ if [ -z "$(REFEDITS)" ]; then \
+ cp $(srcdir)/refcard.tex sedref.tex ; \
+ else \
+ echo > tmp.sed ; \
+ for f in "$(REFEDITS)" ; do \
+ cat $(srcdir)/$$f >>tmp.sed ; done ; \
+ sed -f tmp.sed $(srcdir)/refcard.tex >sedref.tex ; \
+ fi
+ $(SET_TEXINPUTS) $(TEX) sedref.tex
+ mv sedref.dvi refcard.dvi
+ rm -f sedref.log sedref.tex tmp.sed
+
+refcard.ps : refcard.dvi
+ dvips -t landscape refcard.dvi -o
+
+# File to record current GDB version number (copied from main dir Makefile.in)
+GDBvn.texi : ${gdbdir}/Makefile.in
+ echo "@set GDBVN `sed <$(srcdir)/../Makefile.in -n 's/VERSION = //p'`" > ./GDBvn.new
+ mv GDBvn.new GDBvn.texi
+
+# Updated atomically
+.PRECIOUS: GDBvn.texi
+
+# Choose configuration for GDB manual (normally `all'; normally not tied into
+# `configure' script because most users prefer generic version of manual,
+# not one for their binary config---which may not be specifically
+# defined anyways).
+gdb-cfg.texi: ${srcdir}/${DOC_CONFIG}-cfg.texi
+ ln -s ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi || \
+ ln ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi || \
+ cp ${srcdir}/${DOC_CONFIG}-cfg.texi gdb-cfg.texi
+
+# GDB MANUAL: texinfo source, using @set/@clear/@value/@ifset/@ifclear
+# If your texinfo or makeinfo don't support these, get a new texinfo release
+#
+# The nonsense with GDBvn.texi gets this to run with both Sun and GNU make.
+# Note that we can *generate* GDBvn.texi, but since we distribute one in the
+# source directory for the benefit of people who *don't* use this makefile,
+# VPATH will often tell make not to bother building it, because the one
+# in the srcdir is up to date. (if not, then make should build one here).
+
+# GDB MANUAL: TeX dvi file
+gdb.dvi: ${SFILES_DOC}
+ if [ ! -f ./GDBvn.texi ]; then \
+ ln -s $(srcdir)/GDBvn.texi . || \
+ ln $(srcdir)/GDBvn.texi . || \
+ cp $(srcdir)/GDBvn.texi . ; else true; fi
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ $(TEXINDEX) gdb.??
+ $(SET_TEXINPUTS) $(TEX) gdb.texinfo
+ rm -f gdb.?? gdb.log gdb.aux gdb.toc gdb.??s
+
+# GDB MANUAL: info file
+# We're using texinfo2, and older makeinfo's may not be able to
+# cope with all the markup.
+gdb.info: ${SFILES_DOC}
+ $(MAKEINFO) -I ${READLINE_DIR} -I $(srcdir) -o ./gdb.info gdb.texinfo
+
+# GDB MANUAL: roff translations
+# Try to use a recent texi2roff. v2 was put on prep in jan91.
+# If you want an index, see texi2roff doc for postprocessing
+# and add -i to texi2roff invocations below.
+# Workarounds for texi2roff-2 (probably fixed in later texi2roff's, delete
+# corresponding -e lines when later texi2roff's are current)
+# + @ifinfo's deleted explicitly due to texi2roff-2 bug w nested constructs.
+# + @c's deleted explicitly because texi2roff sees texinfo commands in them
+# + @ (that's at-BLANK) not recognized by texi2roff, turned into blank
+# + @alphaenumerate is ridiculously new, turned into @enumerate
+
+# texi2roff doesn't have a notion of include dirs, so we have to fake
+# it out for gdb manual's include files---but only if not configured
+# in main sourcedir.
+links2roff: $(SFILES_INCLUDED)
+ if [ ! -f gdb.texinfo ]; then \
+ ln -s $(SFILES_INCLUDED) . || \
+ ln $(SFILES_INCLUDED) . || \
+ cp $(SFILES_INCLUDED) . ; \
+ fi
+ touch links2roff
+
+# "Readline" appendices. Get them also due to lack of includes,
+# regardless of whether or not configuring in main sourcedir.
+# @ftable removed due to bug in texi2roff-2; if your texi2roff
+# is newer, try just ln or cp
+rluser.texinfo: ${READLINE_DIR}/rluser.texinfo
+ sed -e 's/^@ftable/@table/g' \
+ -e 's/^@end ftable/@end table/g' \
+ ${READLINE_DIR}/rluser.texinfo > ./rluser.texinfo
+
+inc-hist.texi: ${READLINE_DIR}/inc-hist.texi
+ ln -s ${READLINE_DIR}/inc-hist.texi . || \
+ ln ${READLINE_DIR}/inc-hist.texi . || \
+ cp ${READLINE_DIR}/inc-hist.texi .
+
+# gdb manual suitable for [gtn]roff -me
+gdb.me: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -me | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.me
+
+# gdb manual suitable for [gtn]roff -ms
+gdb.ms: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -ms | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.ms
+
+# gdb manual suitable for [tn]roff -mm
+# '@noindent's removed due to texi2roff-2 mm bug; if yours is newer,
+# try leaving them in
+gdb.mm: $(SFILES_LOCAL) links2roff rluser.texinfo inc-hist.texi
+ sed -e '/\\input texinfo/d' \
+ -e '/@c TEXI2ROFF-KILL/,/@c END TEXI2ROFF-KILL/d' \
+ -e '/^@ifinfo/,/^@end ifinfo/d' \
+ -e '/^@c /d' \
+ -e 's/{.*,,/{/' \
+ -e '/@noindent/d' \
+ -e 's/@ / /g' \
+ -e 's/^@alphaenumerate/@enumerate/g' \
+ -e 's/^@end alphaenumerate/@end enumerate/g' \
+ $(srcdir)/gdb.texinfo | \
+ $(TEXI2ROFF) -mm | \
+ sed -e 's/---/\\(em/g' \
+ >gdb.mm
+
+
+# GDB INTERNALS MANUAL: TeX dvi file
+gdbint.dvi : gdbint.texinfo
+ $(SET_TEXINPUTS) $(TEX) gdbint.texinfo
+ $(TEXINDEX) gdbint.??
+ $(SET_TEXINPUTS) $(TEX) gdbint.texinfo
+ rm -f gdbint.?? gdbint.aux gdbint.cps gdbint.fns gdbint.kys \
+ gdbint.log gdbint.pgs gdbint.toc gdbint.tps gdbint.vrs
+
+# GDB INTERNALS MANUAL: info file
+gdb-internals: gdbint.info
+
+gdbint.info: gdbint.texinfo
+ $(MAKEINFO) -o gdbint.info $(srcdir)/gdbint.texinfo
+
+stabs.info: stabs.texinfo
+ $(MAKEINFO) -o stabs.info $(srcdir)/stabs.texinfo
+
+# STABS DOCUMENTATION: TeX dvi file
+stabs.dvi : stabs.texinfo
+ $(SET_TEXINPUTS) $(TEX) stabs.texinfo
+ $(TEXINDEX) stabs.??
+ $(SET_TEXINPUTS) $(TEX) stabs.texinfo
+ rm -f stabs.?? stabs.aux stabs.cps stabs.fns stabs.kys \
+ stabs.log stabs.pgs stabs.toc stabs.tps stabs.vrs
+
+stabs.ps: stabs.dvi
+ dvips -o stabs.ps stabs
+
+force:
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
diff --git a/contrib/gdb/gdb/doc/a4rc.sed b/contrib/gdb/gdb/doc/a4rc.sed
new file mode 100644
index 0000000..2292290
--- /dev/null
+++ b/contrib/gdb/gdb/doc/a4rc.sed
@@ -0,0 +1,11 @@
+/--- Papersize params:/,/--- end papersize params/c\
+%------- Papersize params:\
+%% A4 paper (297x210mm)\
+%%\
+\\totalwidth=297mm % total width of paper\
+\\totalheight=210mm % total height of paper\
+\\hmargin=5mm % horizontal margin width\
+\\vmargin=10mm % vertical margin width\
+\\secskip=.6pc % space between refcard secs\
+\\lskip=1pt % extra skip between \\sec entries\
+%------- end papersize params
diff --git a/contrib/gdb/gdb/doc/all-cfg.texi b/contrib/gdb/gdb/doc/all-cfg.texi
new file mode 100644
index 0000000..5b549c2
--- /dev/null
+++ b/contrib/gdb/gdb/doc/all-cfg.texi
@@ -0,0 +1,120 @@
+@c GDB MANUAL configuration file.
+@c Copyright (c) 1993 Free Software Foundation, Inc.
+@c
+@c NOTE: While the GDB manual is configurable (by changing these
+@c switches), its configuration is ***NOT*** automatically tied in to
+@c source configuration---because the authors expect that, save in
+@c unusual cases, the most inclusive form of the manual is appropriate
+@c no matter how the program itself is configured.
+@c
+@c The only automatically-varying variable is the GDB version number,
+@c which the Makefile rewrites based on the VERSION variable from
+@c `../Makefile.in'.
+@c
+@c GDB version number is recorded in the variable GDBVN
+@include GDBvn.texi
+@c
+@c ----------------------------------------------------------------------
+@c PLATFORM FLAGS:
+@set GENERIC
+@c
+@c Hitachi H8/300 target:
+@set H8
+@c Hitachi H8/300 target ONLY:
+@clear H8EXCLUSIVE
+@c
+@c remote MIPS target:
+@set MIPS
+@c
+@c SPARC target:
+@set SPARC
+@c
+@c AMD 29000 target:
+@set AMD29K
+@c
+@c Intel 960 target:
+@set I960
+@c
+@c Tandem ST2000 (phone switch) target:
+@set ST2000
+@c
+@c Zilog 8000 target:
+@set Z8K
+@c
+@c Lucid "Energize" environment:
+@clear LUCID
+@c
+@c Wind River Systems VxWorks environment:
+@set VXWORKS
+@c
+@c ----------------------------------------------------------------------
+@c DOC FEATURE FLAGS:
+@c
+@c Include change-from-old?
+@set NOVEL
+@c
+@c Bare-board target?
+@clear BARETARGET
+@c
+@c Restrict languages discussed to C?
+@c This is backward. As time permits, change this to language-specific
+@c switches for what to include.
+@clear CONLY
+@c Discuss Fortran?
+@set FORTRAN
+@c
+@c Discuss Modula 2?
+@set MOD2
+@c
+@c Specifically for host machine running DOS?
+@clear DOSHOST
+@c
+@c Talk about CPU simulator targets?
+@set SIMS
+@c
+@c Is manual stand-alone, or part of an agglomeration, with overall GPL?
+@clear AGGLOMERATION
+@c
+@c Remote serial line settings of interest?
+@set SERIAL
+@c
+@c Discuss features requiring Posix or similar OS environment?
+@set POSIX
+@c
+@c Discuss remote serial debugging stub?
+@set REMOTESTUB
+@c
+@c Discuss gdbserver?
+@set GDBSERVER
+@c
+@c Discuss gdbserve.nlm?
+@set GDBSERVE
+@c
+@c Refrain from discussing how to configure sw and format doc?
+@clear PRECONFIGURED
+@c
+@c Refrain from referring to unfree publications?
+@set FSFDOC
+@c
+@c ----------------------------------------------------------------------
+@c STRINGS:
+@c
+@c Name of GDB program. Used also for (gdb) prompt string.
+@set GDBP gdb
+@c
+@c Name of GDB product. Used in running text.
+@set GDBN GDB
+@c
+@c Name of GDB initialization file.
+@set GDBINIT .gdbinit
+@c
+@c Name of host. Should not be used in generic configs, but generic
+@c value may catch some flubs.
+@set HOST machine specific
+@c
+@c Name of GCC product
+@set NGCC GCC
+@c
+@c Name of GCC program
+@set GCC gcc
+
diff --git a/contrib/gdb/gdb/doc/annotate.texi b/contrib/gdb/gdb/doc/annotate.texi
new file mode 100644
index 0000000..9d5850d
--- /dev/null
+++ b/contrib/gdb/gdb/doc/annotate.texi
@@ -0,0 +1,717 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename annotate.info
+@settitle GDB Annotations
+@setchapternewpage off
+@c %**end of header
+
+@set EDITION 0.5
+@set DATE May 1994
+
+@ifinfo
+This file documents GDB annotations.
+
+This is Edition @value{EDITION}, @value{DATE}, of @cite{GDB
+Annotations}. Copyright 1994 Free Software Foundation
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@titlepage
+@title GDB Annotations
+@subtitle Edition @value{EDITION}
+@subtitle @value{DATE}
+@author Cygnus Support
+@page
+@vskip 0pt plus 1filll
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Copyright @copyright{} 1994 Free Software Foundation
+@end titlepage
+
+@ifinfo
+@node Top
+@top GDB Annotations
+
+This file describes annotations in GDB, the GNU symbolic debugger.
+Annotations are designed to interface GDB to graphical user interfaces
+or other similar programs which want to interact with GDB at a
+relatively high level.
+
+This is Edition @value{EDITION}, @value{DATE}.
+
+@menu
+* General:: What annotations are; the general syntax.
+* Server:: Issuing a command without affecting user state.
+* Values:: Values are marked as such.
+* Frames:: Stack frames are annotated.
+* Displays:: GDB can be told to display something periodically.
+* Prompting:: Annotations marking GDB's need for input.
+* Errors:: Annotations for error messages.
+* Breakpoint Info:: Information on breakpoints.
+* Invalidation:: Some annotations describe things now invalid.
+* Running:: Whether the program is running, how it stopped, etc.
+* Source:: Annotations describing source code.
+* TODO:: Annotations which might be added in the future.
+* Index:: Index
+@end menu
+@end ifinfo
+
+@node General
+@chapter What is an Annotation?
+
+To produce annotations, start GDB with the @code{--annotate=2} option.
+
+Annotations start with a newline character, two @samp{control-z}
+characters, and the name of the annotation. If there is no additional
+information associated with this annotation, the name of the annotation
+is followed immediately by a newline. If there is additional
+information, the name of the annotation is followed by a space, the
+additional information, and a newline. The additional information
+cannot contain newline characters.
+
+Any output not beginning with a newline and two @samp{control-z}
+characters denotes literal output from GDB. Currently there is no need
+for GDB to output a newline followed by two @samp{control-z} characters,
+but if there was such a need, the annotations could be extended with an
+@samp{escape} annotation which means those three characters as output.
+
+A simple example of starting up GDB with annotations is:
+
+@example
+$ gdb --annotate=2
+GDB is free software and you are welcome to distribute copies of it
+ under certain conditions; type "show copying" to see the conditions.
+There is absolutely no warranty for GDB; type "show warranty" for details.
+GDB 4.12.3 (sparc-sun-sunos4.1.3),
+Copyright 1994 Free Software Foundation, Inc.
+
+^Z^Zpre-prompt
+(gdb)
+^Z^Zprompt
+quit
+
+^Z^Zpost-prompt
+$
+@end example
+
+Here @samp{quit} is input to GDB; the rest is output from GDB. The three
+lines beginning @samp{^Z^Z} (where @samp{^Z} denotes a @samp{control-z}
+character) are annotations; the rest is output from GDB.
+
+@node Server
+@chapter The Server Prefix
+
+To issue a command to GDB without affecting certain aspects of the state
+which is seen by users, prefix it with @samp{server }. This means that
+this command will not affect the command history, nor will it affect
+GDB's notion of which command to repeat if @key{RET} is pressed on a
+line by itself.
+
+The server prefix does not affect the recording of values into the value
+history; to print a value without recording it into the value history,
+use the @code{output} command instead of the @code{print} command.
+
+@node Values
+@chapter Values
+
+When a value is printed in various contexts, GDB uses annotations to
+delimit the value from the surrounding text.
+
+@findex value-history-begin
+@findex value-history-value
+@findex value-history-end
+If a value is printed using @code{print} and added to the value history,
+the annotation looks like
+
+@example
+^Z^Zvalue-history-begin @var{history-number} @var{value-flags}
+@var{history-string}
+^Z^Zvalue-history-value
+@var{the-value}
+^Z^Zvalue-history-end
+@end example
+
+where @var{history-number} is the number it is getting in the value
+history, @var{history-string} is a string, such as @samp{$5 = }, which
+introduces the value to the user, @var{the-value} is the output
+corresponding to the value itself, and @var{value-flags} is @samp{*} for
+a value which can be dereferenced and @samp{-} for a value which cannot.
+
+@findex value-begin
+@findex value-end
+If the value is not added to the value history (it is an invalid float
+or it is printed with the @code{output} command), the annotation is similar:
+
+@example
+^Z^Zvalue-begin @var{value-flags}
+@var{the-value}
+^Z^Zvalue-end
+@end example
+
+@findex arg-begin
+@findex arg-name-end
+@findex arg-value
+@findex arg-end
+When GDB prints an argument to a function (for example, in the output
+from the @code{backtrace} command), it annotates it as follows:
+
+@example
+^Z^Zarg-begin
+@var{argument-name}
+^Z^Zarg-name-end
+@var{separator-string}
+^Z^Zarg-value @var{value-flags}
+@var{the-value}
+^Z^Zarg-end
+@end example
+
+where @var{argument-name} is the name of the argument,
+@var{separator-string} is text which separates the name from the value
+for the user's benefit (such as @samp{=}), and @var{value-flags} and
+@var{the-value} have the same meanings as in a
+@code{value-history-begin} annotation.
+
+@findex field-begin
+@findex field-name-end
+@findex field-value
+@findex field-end
+When printing a structure, GDB annotates it as follows:
+
+@example
+^Z^Zfield-begin @var{value-flags}
+@var{field-name}
+^Z^Zfield-name-end
+@var{separator-string}
+^Z^Zfield-value
+@var{the-value}
+^Z^Zfield-end
+@end example
+
+where @var{field-name} is the name of the field, @var{separator-string}
+is text which separates the name from the value for the user's benefit
+(such as @samp{=}), and @var{value-flags} and @var{the-value} have the
+same meanings as in a @code{value-history-begin} annotation.
+
+When printing an array, GDB annotates it as follows:
+
+@example
+^Z^Zarray-section-begin @var{array-index} @var{value-flags}
+@end example
+
+where @var{array-index} is the index of the first element being
+annotated and @var{value-flags} has the same meaning as in a
+@code{value-history-begin} annotation. This is followed by any number
+of elements, where is element can be either a single element:
+
+@findex elt
+@example
+@samp{,} @var{whitespace} ; @r{omitted for the first element}
+@var{the-value}
+^Z^Zelt
+@end example
+
+or a repeated element
+
+@findex elt-rep
+@findex elt-rep-end
+@example
+@samp{,} @var{whitespace} ; @r{omitted for the first element}
+@var{the-value}
+^Z^Zelt-rep @var{number-of-repititions}
+@var{repetition-string}
+^Z^Zelt-rep-end
+@end example
+
+In both cases, @var{the-value} is the output for the value of the
+element and @var{whitespace} can contain spaces, tabs, and newlines. In
+the repeated case, @var{number-of-repititons} is the number of
+consecutive array elements which contain that value, and
+@var{repetition-string} is a string which is designed to convey to the
+user that repitition is being depicted.
+
+@findex array-section-end
+Once all the array elements have been output, the array annotation is
+ended with
+
+@example
+^Z^Zarray-section-end
+@end example
+
+@node Frames
+@chapter Frames
+
+Whenever GDB prints a frame, it annotates it. For example, this applies
+to frames printed when GDB stops, output from commands such as
+@code{backtrace} or @code{up}, etc.
+
+@findex frame-begin
+The frame annotation begins with
+
+@example
+^Z^Zframe-begin @var{level} @var{address}
+@var{level-string}
+@end example
+
+where @var{level} is the number of the frame (0 is the innermost frame,
+and other frames have positive numbers), @var{address} is the address of
+the code executing in that frame, and @var{level-string} is a string
+designed to convey the level to the user. @var{address} is in the form
+@samp{0x} followed by one or more lowercase hex digits (note that this
+does not depend on the language). The frame ends with
+
+@findex frame-end
+@example
+^Z^Zframe-end
+@end example
+
+Between these annotations is the main body of the frame, which can
+consist of
+
+@itemize @bullet
+@item
+@findex function-call
+@example
+^Z^Zfunction-call
+@var{function-call-string}
+@end example
+
+where @var{function-call-string} is text designed to convey to the user
+that this frame is associated with a function call made by GDB to a
+function in the program being debugged.
+
+@item
+@findex signal-handler-caller
+@example
+^Z^Zsignal-handler-caller
+@var{signal-handler-caller-string}
+@end example
+
+where @var{signal-handler-caller-string} is text designed to convey to
+the user that this frame is associated with whatever mechanism is used
+by this operating system to call a signal handler (it is the frame which
+calls the signal handler, not the frame for the signal handler itself).
+
+@item
+A normal frame.
+
+@findex frame-address
+@findex frame-address-end
+This can optionally (depending on whether this is thought of as
+interesting information for the user to see) begin with
+
+@example
+^Z^Zframe-address
+@var{address}
+^Z^Zframe-address-end
+@var{separator-string}
+@end example
+
+where @var{address} is the address executing in the frame (the same
+address as in the @code{frame-begin} annotation, but printed in a form
+which is intended for user consumption---in particular, the syntax varies
+depending on the language), and @var{separator-string} is a string
+intended to separate this address from what follows for the user's
+benefit.
+
+@findex frame-function-name
+@findex frame-args
+Then comes
+
+@example
+^Z^Zframe-function-name
+@var{function-name}
+^Z^Zframe-args
+@var{arguments}
+@end example
+
+where @var{function-name} is the name of the function executing in the
+frame, or @samp{??} if not known, and @var{arguments} are the arguments
+to the frame, with parentheses around them (each argument is annotated
+individually as well @pxref{Values}).
+
+@findex frame-source-begin
+@findex frame-source-file
+@findex frame-source-file-end
+@findex frame-source-line
+@findex frame-source-end
+If source information is available, a reference to it is then printed:
+
+@example
+^Z^Zframe-source-begin
+@var{source-intro-string}
+^Z^Zframe-source-file
+@var{filename}
+^Z^Zframe-source-file-end
+:
+^Z^Zframe-source-line
+@var{line-number}
+^Z^Zframe-source-end
+@end example
+
+where @var{source-intro-string} separates for the user's benefit the
+reference from the text which precedes it, @var{filename} is the name of
+the source file, and @var{line-number} is the line number within that
+file (the first line is line 1).
+
+@findex frame-where
+If GDB prints some information about where the frame is from (which
+library, which load segment, etc.; currently only done on the RS/6000),
+it is annotated with
+
+@example
+^Z^Zframe-where
+@var{information}
+@end example
+
+Then, if source is to actually be displayed for this frame (for example,
+this is not true for output from the @code{backtrace} command), then a
+@code{source} annotation (@pxref{Source}) is displayed. Unlike most
+annotations, this is output instead of the normal text which would be
+output, not in addition.
+@end itemize
+
+@node Displays
+@chapter Displays
+
+@findex display-begin
+@findex display-number-end
+@findex display-format
+@findex display-expression
+@findex display-expression-end
+@findex display-value
+@findex display-end
+When GDB is told to display something using the @code{display} command,
+the results of the display are annotated:
+
+@example
+^Z^Zdisplay-begin
+@var{number}
+^Z^Zdisplay-number-end
+@var{number-separator}
+^Z^Zdisplay-format
+@var{format}
+^Z^Zdisplay-expression
+@var{expression}
+^Z^Zdisplay-expression-end
+@var{expression-separator}
+^Z^Zdisplay-value
+@var{value}
+^Z^Zdisplay-end
+@end example
+
+where @var{number} is the number of the display, @var{number-separator}
+is intended to separate the number from what follows for the user,
+@var{format} includes information such as the size, format, or other
+information about how the value is being displayed, @var{expression} is
+the expression being displayed, @var{expression-separator} is intended
+to separate the expression from the text that follows for the user,
+and @var{value} is the actual value being displayed.
+
+@node Prompting
+@chapter Annotation for GDB Input
+
+When GDB prompts for input, it annotates this fact so it is possible
+to know when to send output, when the output from a given command is
+over, etc.
+
+Different kinds of input each have a different @dfn{input type}. Each
+input type has three annotations: a @code{pre-} annotation, which
+denotes the beginning of any prompt which is being output, a plain
+annotation, which denotes the end of the prompt, and then a @code{post-}
+annotation which denotes the end of any echo which may (or may not) be
+associated with the input. For example, the @code{prompt} input type
+features the following annotations:
+
+@example
+^Z^Zpre-prompt
+^Z^Zprompt
+^Z^Zpost-prompt
+@end example
+
+The input types are
+
+@table @code
+@findex pre-prompt
+@findex prompt
+@findex post-prompt
+@item prompt
+When GDB is prompting for a command (the main GDB prompt).
+
+@findex pre-commands
+@findex commands
+@findex post-commands
+@item commands
+When GDB prompts for a set of commands, like in the @code{commands}
+command. The annotations are repeated for each command which is input.
+
+@findex pre-overload-choice
+@findex overload-choice
+@findex post-overload-choice
+@item overload-choice
+When GDB wants the user to select between various overloaded functions.
+
+@findex pre-query
+@findex query
+@findex post-query
+@item query
+When GDB wants the user to confirm a potentially dangerous operation.
+
+@findex pre-prompt-for-continue
+@findex prompt-for-continue
+@findex post-prompt-for-continue
+@item prompt-for-continue
+When GDB is asking the user to press return to continue. Note: Don't
+expect this to work well; instead use @code{set height 0} to disable
+prompting. This is because the counting of lines is buggy in the
+presence of annotations.
+@end table
+
+@node Errors
+@chapter Errors
+
+@findex quit
+@example
+^Z^Zquit
+@end example
+
+This annotation occurs right before GDB responds to an interrupt.
+
+@findex error
+@example
+^Z^Zerror
+@end example
+
+This annotation occurs right before GDB responds to an error.
+
+Quit and error annotations indicate that any annotations which GDB was
+in the middle of may end abruptly. For example, if a
+@code{value-history-begin} annotation is followed by a @code{error}, one
+cannot expect to receive the matching @code{value-history-end}. One
+cannot expect not to receive it either, however; an error annotation
+does not necessarily mean that GDB is immediately returning all the way
+to the top level.
+
+@findex error-begin
+A quit or error annotation may be preceded by
+
+@example
+^Z^Zerror-begin
+@end example
+
+Any output between that and the quit or error annotation is the error
+message.
+
+Warning messages are not yet annotated.
+@c If we want to change that, need to fix warning(), type_error(),
+@c range_error(), and possibly other places.
+
+@node Breakpoint Info
+@chapter Information on Breakpoints
+
+The output from the @code{info breakpoints} command is annotated as follows:
+
+@findex breakpoints-headers
+@findex breakpoints-table
+@example
+^Z^Zbreakpoints-headers
+@var{header-entry}
+^Z^Zbreakpoints-table
+@end example
+
+where @var{header-entry} has the same syntax as an entry (see below) but
+instead of containing data, it contains strings which are intended to
+convey the meaning of each field to the user. This is followed by any
+number of entries. If a field does not apply for this entry, it is
+omitted. Fields may contain trailing whitespace. Each entry consists
+of:
+
+@findex record
+@findex field
+@example
+^Z^Zrecord
+^Z^Zfield 0
+@var{number}
+^Z^Zfield 1
+@var{type}
+^Z^Zfield 2
+@var{disposition}
+^Z^Zfield 3
+@var{enable}
+^Z^Zfield 4
+@var{address}
+^Z^Zfield 5
+@var{what}
+^Z^Zfield 6
+@var{frame}
+^Z^Zfield 7
+@var{condition}
+^Z^Zfield 8
+@var{ignore-count}
+^Z^Zfield 9
+@var{commands}
+@end example
+
+Note that @var{address} is intended for user consumption---the syntax
+varies depending on the language.
+
+The output ends with
+
+@findex breakpoints-table-end
+@example
+^Z^Zbreakpoints-table-end
+@end example
+
+@node Invalidation
+@chapter Invalidation Notices
+
+The following annotations say that certain pieces of state may have
+changed.
+
+@table @code
+@findex frames-invalid
+@item ^Z^Zframes-invalid
+
+The frames (for example, output from the @code{backtrace} command) may
+have changed.
+
+@findex breakpoints-invalid
+@item ^Z^Zbreakpoints-invalid
+
+The breakpoints may have changed. For example, the user just added or
+deleted a breakpoint.
+@end table
+
+@node Running
+@chapter Running the Program
+
+@findex starting
+@findex stopping
+When the program starts executing due to a GDB command such as
+@code{step} or @code{continue},
+
+@example
+^Z^Zstarting
+@end example
+
+is output. When the program stops,
+
+@example
+^Z^Zstopped
+@end example
+
+is output. Before the @code{stopped} annotation, a variety of
+annotations describe how the program stopped.
+
+@table @code
+@findex exited
+@item ^Z^Zexited @var{exit-status}
+The program exited, and @var{exit-status} is the exit status (zero for
+successful exit, otherwise nonzero).
+
+@findex signalled
+@findex signal-name
+@findex signal-name-end
+@findex signal-string
+@findex signal-string-end
+@item ^Z^Zsignalled
+The program exited with a signal. After the @code{^Z^Zsignalled}, the
+annotation continues:
+
+@example
+@var{intro-text}
+^Z^Zsignal-name
+@var{name}
+^Z^Zsignal-name-end
+@var{middle-text}
+^Z^Zsignal-string
+@var{string}
+^Z^Zsignal-string-end
+@var{end-text}
+@end example
+
+where @var{name} is the name of the signal, such as @code{SIGILL} or
+@code{SIGSEGV}, and @var{string} is the explanation of the signal, such
+as @code{Illegal Instruction} or @code{Segmentation fault}.
+@var{intro-text}, @var{middle-text}, and @var{end-text} are for the
+user's benefit and have no particular format.
+
+@findex signal
+@item ^Z^Zsignal
+The syntax of this annotation is just like @code{signalled}, but GDB is
+just saying that the program received the signal, not that it was
+terminated with it.
+
+@findex breakpoint
+@item ^Z^Zbreakpoint @var{number}
+The program hit breakpoint number @var{number}.
+
+@findex watchpoint
+@item ^Z^Zwatchpoint @var{number}
+The program hit watchpoint number @var{number}.
+@end table
+
+@node Source
+@chapter Displaying Source
+
+@findex source
+The following annotation is used instead of displaying source code:
+
+@example
+^Z^Zsource @var{filename}:@var{line}:@var{character}:@var{middle}:@var{addr}
+@end example
+
+where @var{filename} is an absolute file name indicating which source
+file, @var{line} is the line number within that file (where 1 is the
+first line in the file), @var{character} is the character position
+within the file (where 0 is the first character in the file) (for most
+debug formats this will necessarily point to the beginning of a line),
+@var{middle} is @samp{middle} if @var{addr} is in the middle of the
+line, or @samp{beg} if @var{addr} is at the beginning of the line, and
+@var{addr} is the address in the target program associated with the
+source which is being displayed. @var{addr} is in the form @samp{0x}
+followed by one or more lowercase hex digits (note that this does not
+depend on the language).
+
+@node TODO
+@chapter Annotations We Might Want in the Future
+
+@format
+ - target-invalid
+ the target might have changed (registers, heap contents, or
+ execution status). For performance, we might eventually want
+ to hit `registers-invalid' and `all-registers-invalid' with
+ greater precision
+
+ - systematic annotation for set/show parameters (including
+ invalidation notices).
+
+ - similarly, `info' returns a list of candidates for invalidation
+ notices.
+@end format
+
+@node Index
+@unnumbered Index
+
+@printindex fn
+
+@bye
diff --git a/contrib/gdb/gdb/doc/configure.in b/contrib/gdb/gdb/doc/configure.in
new file mode 100644
index 0000000..1d2b47e
--- /dev/null
+++ b/contrib/gdb/gdb/doc/configure.in
@@ -0,0 +1,7 @@
+srcname="GDB doc"
+srctrigger=gdb.texinfo
+# per-host:
+# per-target:
+
+files=""
+links=""
diff --git a/contrib/gdb/gdb/doc/gdb.texinfo b/contrib/gdb/gdb/doc/gdb.texinfo
new file mode 100644
index 0000000..89bfa83
--- /dev/null
+++ b/contrib/gdb/gdb/doc/gdb.texinfo
@@ -0,0 +1,9282 @@
+\input texinfo @c -*-texinfo-*-
+@c Copyright 1988 1989 1990 1991 1992 1993 1994 1995
+@c Free Software Foundation, Inc.
+@c
+@c %**start of header
+@c makeinfo ignores cmds prev to setfilename, so its arg cannot make use
+@c of @set vars. However, you can override filename with makeinfo -o.
+@setfilename gdb.info
+@c
+@include gdb-cfg.texi
+@c
+@ifset GENERIC
+@settitle Debugging with @value{GDBN}
+@end ifset
+@ifclear GENERIC
+@settitle Debugging with @value{GDBN} (@value{TARGET})
+@end ifclear
+@clear RENAMED
+@setchapternewpage odd
+@c %**end of header
+
+@iftex
+@c @smallbook
+@c @cropmarks
+@end iftex
+
+@finalout
+@syncodeindex ky cp
+
+@c readline appendices use @vindex
+@syncodeindex vr cp
+
+@c !!set GDB manual's edition---not the same as GDB version!
+@set EDITION 4.12
+
+@c !!set GDB manual's revision date
+@set DATE January 1994
+
+@c GDB CHANGELOG CONSULTED BETWEEN:
+@c Fri Oct 11 23:27:06 1991 John Gilmore (gnu at cygnus.com)
+@c Sat Dec 22 02:51:40 1990 John Gilmore (gnu at cygint)
+
+@c THIS MANUAL REQUIRES TEXINFO-2 macros and info-makers to format properly.
+
+@ifinfo
+@c This is a dir.info fragment to support semi-automated addition of
+@c manuals to an info tree. zoo@cygnus.com is developing this facility.
+@format
+START-INFO-DIR-ENTRY
+* Gdb: (gdb). The @sc{gnu} debugger.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+@c
+@c
+@ifinfo
+This file documents the @sc{gnu} debugger @value{GDBN}.
+
+
+This is Edition @value{EDITION}, @value{DATE},
+of @cite{Debugging with @value{GDBN}: the @sc{gnu} Source-Level Debugger}
+for @value{GDBN} Version @value{GDBVN}.
+
+Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@titlepage
+@title Debugging with @value{GDBN}
+@subtitle The @sc{gnu} Source-Level Debugger
+@ifclear GENERIC
+@subtitle (@value{TARGET})
+@end ifclear
+@sp 1
+@subtitle Edition @value{EDITION}, for @value{GDBN} version @value{GDBVN}
+@subtitle @value{DATE}
+@author Richard M. Stallman and Cygnus Support
+@page
+@tex
+{\parskip=0pt
+\hfill (Send bugs and comments on @value{GDBN} to bug-gdb\@prep.ai.mit.edu.)\par
+\hfill {\it Debugging with @value{GDBN}}\par
+\hfill \TeX{}info \texinfoversion\par
+\hfill doc\@cygnus.com\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+Free Software Foundation, Inc.
+@sp 2
+Published by the Free Software Foundation @*
+59 Temple Place - Suite 330, @*
+Boston, MA 02111-1307 USA @*
+Printed copies are available for $20 each. @*
+ISBN 1-882114-11-6 @*
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end titlepage
+@page
+
+@ifinfo
+@node Top
+@top Debugging with @value{GDBN}
+
+This file describes @value{GDBN}, the @sc{gnu} symbolic debugger.
+
+This is Edition @value{EDITION}, @value{DATE}, for @value{GDBN} Version
+@value{GDBVN}.
+
+@menu
+* Summary:: Summary of @value{GDBN}
+@ifclear BARETARGET
+* Sample Session:: A sample @value{GDBN} session
+@end ifclear
+
+* Invocation:: Getting in and out of @value{GDBN}
+* Commands:: @value{GDBN} commands
+* Running:: Running programs under @value{GDBN}
+* Stopping:: Stopping and continuing
+* Stack:: Examining the stack
+* Source:: Examining source files
+* Data:: Examining data
+@ifclear CONLY
+* Languages:: Using @value{GDBN} with different languages
+@end ifclear
+@ifset CONLY
+* C:: C language support
+@end ifset
+@c remnant makeinfo bug, blank line needed after two end-ifs?
+
+* Symbols:: Examining the symbol table
+* Altering:: Altering execution
+* GDB Files:: @value{GDBN} files
+* Targets:: Specifying a debugging target
+* Controlling GDB:: Controlling @value{GDBN}
+* Sequences:: Canned sequences of commands
+@ifclear DOSHOST
+* Emacs:: Using @value{GDBN} under @sc{gnu} Emacs
+@end ifclear
+
+* GDB Bugs:: Reporting bugs in @value{GDBN}
+* Command Line Editing:: Facilities of the readline library
+* Using History Interactively::
+@c @ifset NOVEL
+@c * Renamed Commands::
+@c @end ifset
+@ifclear PRECONFIGURED
+* Formatting Documentation:: How to format and print @value{GDBN} documentation
+* Installing GDB:: Installing GDB
+@end ifclear
+
+* Index:: Index
+@end menu
+@end ifinfo
+
+@node Summary
+@unnumbered Summary of @value{GDBN}
+
+The purpose of a debugger such as @value{GDBN} is to allow you to see what is
+going on ``inside'' another program while it executes---or what another
+program was doing at the moment it crashed.
+
+@value{GDBN} can do four main kinds of things (plus other things in support of
+these) to help you catch bugs in the act:
+
+@itemize @bullet
+@item
+Start your program, specifying anything that might affect its behavior.
+
+@item
+Make your program stop on specified conditions.
+
+@item
+Examine what has happened, when your program has stopped.
+
+@item
+Change things in your program, so you can experiment with correcting the
+effects of one bug and go on to learn about another.
+@end itemize
+
+@ifclear CONLY
+You can use @value{GDBN} to debug programs written in C or C++.
+@c "MOD2" used as a "miscellaneous languages" flag here.
+@c This is acceptable while there is no real doc for Chill and Pascal.
+@ifclear MOD2
+For more information, see @ref{Support,,Supported languages}.
+@end ifclear
+@ifset MOD2
+For more information, see @ref{C,,C and C++}.
+
+Support for Modula-2 and Chill is partial. For information on Modula-2,
+see @ref{Modula-2,,Modula-2}. There is no further documentation on Chill yet.
+
+Debugging Pascal programs which use sets, subranges, file variables, or nested
+functions does not currently work. @value{GDBN} does not support
+entering expressions, printing values, or similar features using Pascal syntax.
+
+@end ifset
+@ifset FORTRAN
+@cindex Fortran
+@value{GDBN} can be used to debug programs written in Fortran, although
+it does not yet support entering expressions, printing values, or
+similar features using Fortran syntax. It may be necessary to refer to
+some variables with a trailing underscore.
+@end ifset
+@end ifclear
+
+@menu
+* Free Software:: Freely redistributable software
+* Contributors:: Contributors to GDB
+@end menu
+
+@node Free Software
+@unnumberedsec Free software
+
+@value{GDBN} is @dfn{free software}, protected by the @sc{gnu}
+General Public License
+(GPL). The GPL gives you the freedom to copy or adapt a licensed
+program---but every person getting a copy also gets with it the
+freedom to modify that copy (which means that they must get access to
+the source code), and the freedom to distribute further copies.
+Typical software companies use copyrights to limit your freedoms; the
+Free Software Foundation uses the GPL to preserve these freedoms.
+
+Fundamentally, the General Public License is a license which says that
+you have these freedoms and that you cannot take these freedoms away
+from anyone else.
+
+@node Contributors
+@unnumberedsec Contributors to GDB
+
+Richard Stallman was the original author of GDB, and of many other @sc{gnu}
+programs. Many others have contributed to its development. This
+section attempts to credit major contributors. One of the virtues of
+free software is that everyone is free to contribute to it; with
+regret, we cannot actually acknowledge everyone here. The file
+@file{ChangeLog} in the @value{GDBN} distribution approximates a blow-by-blow
+account.
+
+Changes much prior to version 2.0 are lost in the mists of time.
+
+@quotation
+@emph{Plea:} Additions to this section are particularly welcome. If you
+or your friends (or enemies, to be evenhanded) have been unfairly
+omitted from this list, we would like to add your names!
+@end quotation
+
+So that they may not regard their long labor as thankless, we
+particularly thank those who shepherded GDB through major releases:
+Stan Shebs (release 4.14),
+Fred Fish (releases 4.13, 4.12, 4.11, 4.10, and 4.9),
+Stu Grossman and John Gilmore (releases 4.8, 4.7, 4.6, 4.5, and 4.4),
+John Gilmore (releases 4.3, 4.2, 4.1, 4.0, and 3.9);
+Jim Kingdon (releases 3.5, 3.4, and 3.3);
+and Randy Smith (releases 3.2, 3.1, and 3.0).
+As major maintainer of @value{GDBN} for some period, each
+contributed significantly to the structure, stability, and capabilities
+of the entire debugger.
+
+Richard Stallman, assisted at various times by Peter TerMaat, Chris
+Hanson, and Richard Mlynarik, handled releases through 2.8.
+
+@ifclear CONLY
+Michael Tiemann is the author of most of the @sc{gnu} C++ support in GDB,
+with significant additional contributions from Per Bothner. James
+Clark wrote the @sc{gnu} C++ demangler. Early work on C++ was by Peter
+TerMaat (who also did much general update work leading to release 3.0).
+@end ifclear
+
+@value{GDBN} 4 uses the BFD subroutine library to examine multiple
+object-file formats; BFD was a joint project of David V.
+Henkel-Wallace, Rich Pixley, Steve Chamberlain, and John Gilmore.
+
+David Johnson wrote the original COFF support; Pace Willison did
+the original support for encapsulated COFF.
+
+Adam de Boor and Bradley Davis contributed the ISI Optimum V support.
+Per Bothner, Noboyuki Hikichi, and Alessandro Forin contributed MIPS
+support.
+Jean-Daniel Fekete contributed Sun 386i support.
+Chris Hanson improved the HP9000 support.
+Noboyuki Hikichi and Tomoyuki Hasei contributed Sony/News OS 3 support.
+David Johnson contributed Encore Umax support.
+Jyrki Kuoppala contributed Altos 3068 support.
+Jeff Law contributed HP PA and SOM support.
+Keith Packard contributed NS32K support.
+Doug Rabson contributed Acorn Risc Machine support.
+Bob Rusk contributed Harris Nighthawk CX-UX support.
+Chris Smith contributed Convex support (and Fortran debugging).
+Jonathan Stone contributed Pyramid support.
+Michael Tiemann contributed SPARC support.
+Tim Tucker contributed support for the Gould NP1 and Gould Powernode.
+Pace Willison contributed Intel 386 support.
+Jay Vosburgh contributed Symmetry support.
+
+Rich Schaefer and Peter Schauer helped with support of SunOS shared
+libraries.
+
+Jay Fenlason and Roland McGrath ensured that @value{GDBN} and GAS agree about
+several machine instruction sets.
+
+Patrick Duval, Ted Goldstein, Vikram Koka and Glenn Engel helped
+develop remote debugging. Intel Corporation and Wind River Systems
+contributed remote debugging modules for their products.
+
+Brian Fox is the author of the readline libraries providing
+command-line editing and command history.
+
+Andrew Beers of SUNY Buffalo wrote the language-switching code,
+@ifset MOD2
+the Modula-2 support,
+@end ifset
+and contributed the Languages chapter of this manual.
+
+Fred Fish wrote most of the support for Unix System Vr4.
+@ifclear CONLY
+He also enhanced the command-completion support to cover C++ overloaded
+symbols.
+@end ifclear
+
+Hitachi America, Ltd. sponsored the support for Hitachi microprocessors.
+
+Kung Hsu, Jeff Law, and Rick Sladkey added support for hardware
+watchpoints.
+
+Stu Grossman wrote gdbserver.
+
+Jim Kingdon, Peter Schauer, Ian Taylor, and Stu Grossman made
+nearly innumerable bug fixes and cleanups throughout GDB.
+
+@ifclear BARETARGET
+@node Sample Session
+@chapter A Sample @value{GDBN} Session
+
+You can use this manual at your leisure to read all about @value{GDBN}.
+However, a handful of commands are enough to get started using the
+debugger. This chapter illustrates those commands.
+
+@iftex
+In this sample session, we emphasize user input like this: @b{input},
+to make it easier to pick out from the surrounding output.
+@end iftex
+
+@c FIXME: this example may not be appropriate for some configs, where
+@c FIXME...primary interest is in remote use.
+
+One of the preliminary versions of @sc{gnu} @code{m4} (a generic macro
+processor) exhibits the following bug: sometimes, when we change its
+quote strings from the default, the commands used to capture one macro
+definition within another stop working. In the following short @code{m4}
+session, we define a macro @code{foo} which expands to @code{0000}; we
+then use the @code{m4} built-in @code{defn} to define @code{bar} as the
+same thing. However, when we change the open quote string to
+@code{<QUOTE>} and the close quote string to @code{<UNQUOTE>}, the same
+procedure fails to define a new synonym @code{baz}:
+
+@smallexample
+$ @b{cd gnu/m4}
+$ @b{./m4}
+@b{define(foo,0000)}
+
+@b{foo}
+0000
+@b{define(bar,defn(`foo'))}
+
+@b{bar}
+0000
+@b{changequote(<QUOTE>,<UNQUOTE>)}
+
+@b{define(baz,defn(<QUOTE>foo<UNQUOTE>))}
+@b{baz}
+@b{C-d}
+m4: End of input: 0: fatal error: EOF in string
+@end smallexample
+
+@noindent
+Let us use @value{GDBN} to try to see what is going on.
+
+@smallexample
+$ @b{@value{GDBP} m4}
+@c FIXME: this falsifies the exact text played out, to permit smallbook
+@c FIXME... format to come out better.
+@value{GDBN} is free software and you are welcome to distribute copies
+ of it under certain conditions; type "show copying" to see
+ the conditions.
+There is absolutely no warranty for @value{GDBN}; type "show warranty"
+ for details.
+
+@value{GDBN} @value{GDBVN}, Copyright 1995 Free Software Foundation, Inc...
+(@value{GDBP})
+@end smallexample
+
+@noindent
+@value{GDBN} reads only enough symbol data to know where to find the
+rest when needed; as a result, the first prompt comes up very quickly.
+We now tell @value{GDBN} to use a narrower display width than usual, so
+that examples fit in this manual.
+
+@smallexample
+(@value{GDBP}) @b{set width 70}
+@end smallexample
+
+@noindent
+We need to see how the @code{m4} built-in @code{changequote} works.
+Having looked at the source, we know the relevant subroutine is
+@code{m4_changequote}, so we set a breakpoint there with the @value{GDBN}
+@code{break} command.
+
+@smallexample
+(@value{GDBP}) @b{break m4_changequote}
+Breakpoint 1 at 0x62f4: file builtin.c, line 879.
+@end smallexample
+
+@noindent
+Using the @code{run} command, we start @code{m4} running under @value{GDBN}
+control; as long as control does not reach the @code{m4_changequote}
+subroutine, the program runs as usual:
+
+@smallexample
+(@value{GDBP}) @b{run}
+Starting program: /work/Editorial/gdb/gnu/m4/m4
+@b{define(foo,0000)}
+
+@b{foo}
+0000
+@end smallexample
+
+@noindent
+To trigger the breakpoint, we call @code{changequote}. @value{GDBN}
+suspends execution of @code{m4}, displaying information about the
+context where it stops.
+
+@smallexample
+@b{changequote(<QUOTE>,<UNQUOTE>)}
+
+Breakpoint 1, m4_changequote (argc=3, argv=0x33c70)
+ at builtin.c:879
+879 if (bad_argc(TOKEN_DATA_TEXT(argv[0]),argc,1,3))
+@end smallexample
+
+@noindent
+Now we use the command @code{n} (@code{next}) to advance execution to
+the next line of the current function.
+
+@smallexample
+(@value{GDBP}) @b{n}
+882 set_quotes((argc >= 2) ? TOKEN_DATA_TEXT(argv[1])\
+ : nil,
+@end smallexample
+
+@noindent
+@code{set_quotes} looks like a promising subroutine. We can go into it
+by using the command @code{s} (@code{step}) instead of @code{next}.
+@code{step} goes to the next line to be executed in @emph{any}
+subroutine, so it steps into @code{set_quotes}.
+
+@smallexample
+(@value{GDBP}) @b{s}
+set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
+ at input.c:530
+530 if (lquote != def_lquote)
+@end smallexample
+
+@noindent
+The display that shows the subroutine where @code{m4} is now
+suspended (and its arguments) is called a stack frame display. It
+shows a summary of the stack. We can use the @code{backtrace}
+command (which can also be spelled @code{bt}), to see where we are
+in the stack as a whole: the @code{backtrace} command displays a
+stack frame for each active subroutine.
+
+@smallexample
+(@value{GDBP}) @b{bt}
+#0 set_quotes (lq=0x34c78 "<QUOTE>", rq=0x34c88 "<UNQUOTE>")
+ at input.c:530
+#1 0x6344 in m4_changequote (argc=3, argv=0x33c70)
+ at builtin.c:882
+#2 0x8174 in expand_macro (sym=0x33320) at macro.c:242
+#3 0x7a88 in expand_token (obs=0x0, t=209696, td=0xf7fffa30)
+ at macro.c:71
+#4 0x79dc in expand_input () at macro.c:40
+#5 0x2930 in main (argc=0, argv=0xf7fffb20) at m4.c:195
+@end smallexample
+
+@noindent
+We step through a few more lines to see what happens. The first two
+times, we can use @samp{s}; the next two times we use @code{n} to avoid
+falling into the @code{xstrdup} subroutine.
+
+@smallexample
+(@value{GDBP}) @b{s}
+0x3b5c 532 if (rquote != def_rquote)
+(@value{GDBP}) @b{s}
+0x3b80 535 lquote = (lq == nil || *lq == '\0') ? \
+def_lquote : xstrdup(lq);
+(@value{GDBP}) @b{n}
+536 rquote = (rq == nil || *rq == '\0') ? def_rquote\
+ : xstrdup(rq);
+(@value{GDBP}) @b{n}
+538 len_lquote = strlen(rquote);
+@end smallexample
+
+@noindent
+The last line displayed looks a little odd; we can examine the variables
+@code{lquote} and @code{rquote} to see if they are in fact the new left
+and right quotes we specified. We use the command @code{p}
+(@code{print}) to see their values.
+
+@smallexample
+(@value{GDBP}) @b{p lquote}
+$1 = 0x35d40 "<QUOTE>"
+(@value{GDBP}) @b{p rquote}
+$2 = 0x35d50 "<UNQUOTE>"
+@end smallexample
+
+@noindent
+@code{lquote} and @code{rquote} are indeed the new left and right quotes.
+To look at some context, we can display ten lines of source
+surrounding the current line with the @code{l} (@code{list}) command.
+
+@smallexample
+(@value{GDBP}) @b{l}
+533 xfree(rquote);
+534
+535 lquote = (lq == nil || *lq == '\0') ? def_lquote\
+ : xstrdup (lq);
+536 rquote = (rq == nil || *rq == '\0') ? def_rquote\
+ : xstrdup (rq);
+537
+538 len_lquote = strlen(rquote);
+539 len_rquote = strlen(lquote);
+540 @}
+541
+542 void
+@end smallexample
+
+@noindent
+Let us step past the two lines that set @code{len_lquote} and
+@code{len_rquote}, and then examine the values of those variables.
+
+@smallexample
+(@value{GDBP}) @b{n}
+539 len_rquote = strlen(lquote);
+(@value{GDBP}) @b{n}
+540 @}
+(@value{GDBP}) @b{p len_lquote}
+$3 = 9
+(@value{GDBP}) @b{p len_rquote}
+$4 = 7
+@end smallexample
+
+@noindent
+That certainly looks wrong, assuming @code{len_lquote} and
+@code{len_rquote} are meant to be the lengths of @code{lquote} and
+@code{rquote} respectively. We can set them to better values using
+the @code{p} command, since it can print the value of
+any expression---and that expression can include subroutine calls and
+assignments.
+
+@smallexample
+(@value{GDBP}) @b{p len_lquote=strlen(lquote)}
+$5 = 7
+(@value{GDBP}) @b{p len_rquote=strlen(rquote)}
+$6 = 9
+@end smallexample
+
+@noindent
+Is that enough to fix the problem of using the new quotes with the
+@code{m4} built-in @code{defn}? We can allow @code{m4} to continue
+executing with the @code{c} (@code{continue}) command, and then try the
+example that caused trouble initially:
+
+@smallexample
+(@value{GDBP}) @b{c}
+Continuing.
+
+@b{define(baz,defn(<QUOTE>foo<UNQUOTE>))}
+
+baz
+0000
+@end smallexample
+
+@noindent
+Success! The new quotes now work just as well as the default ones. The
+problem seems to have been just the two typos defining the wrong
+lengths. We allow @code{m4} exit by giving it an EOF as input:
+
+@smallexample
+@b{C-d}
+Program exited normally.
+@end smallexample
+
+@noindent
+The message @samp{Program exited normally.} is from @value{GDBN}; it
+indicates @code{m4} has finished executing. We can end our @value{GDBN}
+session with the @value{GDBN} @code{quit} command.
+
+@smallexample
+(@value{GDBP}) @b{quit}
+@end smallexample
+@end ifclear
+
+@node Invocation
+@chapter Getting In and Out of @value{GDBN}
+
+This chapter discusses how to start @value{GDBN}, and how to get out of it.
+The essentials are:
+@itemize @bullet
+@item
+type @samp{@value{GDBP}} to start GDB.
+@item
+type @kbd{quit} or @kbd{C-d} to exit.
+@end itemize
+
+@menu
+* Invoking GDB:: How to start @value{GDBN}
+* Quitting GDB:: How to quit @value{GDBN}
+* Shell Commands:: How to use shell commands inside @value{GDBN}
+@end menu
+
+@node Invoking GDB
+@section Invoking @value{GDBN}
+
+@ifset H8EXCLUSIVE
+For details on starting up @value{GDBP} as a
+remote debugger attached to a Hitachi microprocessor, see @ref{Hitachi
+Remote,,@value{GDBN} and Hitachi Microprocessors}.
+@end ifset
+
+Invoke @value{GDBN} by running the program @code{@value{GDBP}}. Once started,
+@value{GDBN} reads commands from the terminal until you tell it to exit.
+
+You can also run @code{@value{GDBP}} with a variety of arguments and options,
+to specify more of your debugging environment at the outset.
+
+@ifset GENERIC
+The command-line options described here are designed
+to cover a variety of situations; in some environments, some of these
+options may effectively be unavailable.
+@end ifset
+
+The most usual way to start @value{GDBN} is with one argument,
+specifying an executable program:
+
+@example
+@value{GDBP} @var{program}
+@end example
+
+@ifclear BARETARGET
+@noindent
+You can also start with both an executable program and a core file
+specified:
+
+@example
+@value{GDBP} @var{program} @var{core}
+@end example
+
+You can, instead, specify a process ID as a second argument, if you want
+to debug a running process:
+
+@example
+@value{GDBP} @var{program} 1234
+@end example
+
+@noindent
+would attach @value{GDBN} to process @code{1234} (unless you also have a file
+named @file{1234}; @value{GDBN} does check for a core file first).
+
+Taking advantage of the second command-line argument requires a fairly
+complete operating system; when you use @value{GDBN} as a remote debugger
+attached to a bare board, there may not be any notion of ``process'',
+and there is often no way to get a core dump.
+@end ifclear
+
+You can run @code{gdb} without printing the front material, which describes
+@value{GDBN}'s non-warranty, by specifying @code{-silent}:
+
+@smallexample
+@value{GDBP} @var{-silent}
+@end smallexample
+
+@noindent
+You can further control how @value{GDBN} starts up by using command-line
+options. @value{GDBN} itself can remind you of the options available.
+
+@noindent
+Type
+
+@example
+@value{GDBP} -help
+@end example
+
+@noindent
+to display all available options and briefly describe their use
+(@samp{@value{GDBP} -h} is a shorter equivalent).
+
+All options and command line arguments you give are processed
+in sequential order. The order makes a difference when the
+@samp{-x} option is used.
+
+
+@menu
+@ifclear GENERIC
+@ifset REMOTESTUB
+* Remote Serial:: @value{GDBN} remote serial protocol
+@end ifset
+@ifset I960
+* i960-Nindy Remote:: @value{GDBN} with a remote i960 (Nindy)
+@end ifset
+@ifset AMD29K
+* UDI29K Remote:: The UDI protocol for AMD29K
+* EB29K Remote:: The EBMON protocol for AMD29K
+@end ifset
+@ifset VXWORKS
+* VxWorks Remote:: @value{GDBN} and VxWorks
+@end ifset
+@ifset ST2000
+* ST2000 Remote:: @value{GDBN} with a Tandem ST2000
+@end ifset
+@ifset H8
+* Hitachi Remote:: @value{GDBN} and Hitachi Microprocessors
+@end ifset
+@ifset MIPS
+* MIPS Remote:: @value{GDBN} and MIPS boards
+@end ifset
+@ifset SIMS
+* Simulator:: Simulated CPU target
+@end ifset
+@end ifclear
+@c remnant makeinfo bug requires this blank line after *two* end-ifblahs:
+
+* File Options:: Choosing files
+* Mode Options:: Choosing modes
+@end menu
+
+@ifclear GENERIC
+@include remote.texi
+@end ifclear
+
+@node File Options
+@subsection Choosing files
+
+@ifclear BARETARGET
+When @value{GDBN} starts, it reads any arguments other than options as
+specifying an executable file and core file (or process ID). This is
+the same as if the arguments were specified by the @samp{-se} and
+@samp{-c} options respectively. (@value{GDBN} reads the first argument
+that does not have an associated option flag as equivalent to the
+@samp{-se} option followed by that argument; and the second argument
+that does not have an associated option flag, if any, as equivalent to
+the @samp{-c} option followed by that argument.)
+@end ifclear
+@ifset BARETARGET
+When @value{GDBN} starts, it reads any argument other than options as
+specifying an executable file. This is the same as if the argument was
+specified by the @samp{-se} option.
+@end ifset
+
+Many options have both long and short forms; both are shown in the
+following list. @value{GDBN} also recognizes the long forms if you truncate
+them, so long as enough of the option is present to be unambiguous.
+(If you prefer, you can flag option arguments with @samp{--} rather
+than @samp{-}, though we illustrate the more usual convention.)
+
+@table @code
+@item -symbols @var{file}
+@itemx -s @var{file}
+Read symbol table from file @var{file}.
+
+@item -exec @var{file}
+@itemx -e @var{file}
+Use file @var{file} as the executable file to execute when
+@ifset BARETARGET
+appropriate.
+@end ifset
+@ifclear BARETARGET
+appropriate, and for examining pure data in conjunction with a core
+dump.
+@end ifclear
+
+@item -se @var{file}
+Read symbol table from file @var{file} and use it as the executable
+file.
+
+@ifclear BARETARGET
+@item -core @var{file}
+@itemx -c @var{file}
+Use file @var{file} as a core dump to examine.
+
+@item -c @var{number}
+Connect to process ID @var{number}, as with the @code{attach} command
+(unless there is a file in core-dump format named @var{number}, in which
+case @samp{-c} specifies that file as a core dump to read).
+@end ifclear
+
+@item -command @var{file}
+@itemx -x @var{file}
+Execute @value{GDBN} commands from file @var{file}. @xref{Command
+Files,, Command files}.
+
+@item -directory @var{directory}
+@itemx -d @var{directory}
+Add @var{directory} to the path to search for source files.
+
+@ifclear BARETARGET
+@item -m
+@itemx -mapped
+@emph{Warning: this option depends on operating system facilities that are not
+supported on all systems.}@*
+If memory-mapped files are available on your system through the @code{mmap}
+system call, you can use this option
+to have @value{GDBN} write the symbols from your
+program into a reusable file in the current directory. If the program you are debugging is
+called @file{/tmp/fred}, the mapped symbol file is @file{./fred.syms}.
+Future @value{GDBN} debugging sessions notice the presence of this file,
+and can quickly map in symbol information from it, rather than reading
+the symbol table from the executable program.
+
+The @file{.syms} file is specific to the host machine where @value{GDBN}
+is run. It holds an exact image of the internal @value{GDBN} symbol
+table. It cannot be shared across multiple host platforms.
+@end ifclear
+
+@item -r
+@itemx -readnow
+Read each symbol file's entire symbol table immediately, rather than
+the default, which is to read it incrementally as it is needed.
+This makes startup slower, but makes future operations faster.
+@end table
+
+@ifclear BARETARGET
+The @code{-mapped} and @code{-readnow} options are typically combined in
+order to build a @file{.syms} file that contains complete symbol
+information. (@xref{Files,,Commands to specify files}, for information
+
+a @file{.syms} file for future use is:
+
+@example
+ gdb -batch -nx -mapped -readnow programname
+@end example
+@end ifclear
+
+@node Mode Options
+@subsection Choosing modes
+
+You can run @value{GDBN} in various alternative modes---for example, in
+batch mode or quiet mode.
+
+@table @code
+@item -nx
+@itemx -n
+Do not execute commands from any initialization files (normally called
+@file{@value{GDBINIT}}). Normally, the commands in these files are
+executed after all the command options and arguments have been
+processed. @xref{Command Files,,Command files}.
+
+@item -quiet
+@itemx -q
+``Quiet''. Do not print the introductory and copyright messages. These
+messages are also suppressed in batch mode.
+
+@item -batch
+Run in batch mode. Exit with status @code{0} after processing all the
+command files specified with @samp{-x} (and all commands from
+initialization files, if not inhibited with @samp{-n}). Exit with
+nonzero status if an error occurs in executing the @value{GDBN} commands
+in the command files.
+
+Batch mode may be useful for running @value{GDBN} as a filter, for example to
+download and run a program on another computer; in order to make this
+more useful, the message
+
+@example
+Program exited normally.
+@end example
+
+@noindent
+(which is ordinarily issued whenever a program running under @value{GDBN} control
+terminates) is not issued when running in batch mode.
+
+@item -cd @var{directory}
+Run @value{GDBN} using @var{directory} as its working directory,
+instead of the current directory.
+
+@ifset LUCID
+@item -context @var{authentication}
+When the Energize programming system starts up @value{GDBN}, it uses this
+option to trigger an alternate mode of interaction.
+@var{authentication} is a pair of numeric codes that identify @value{GDBN}
+as a client in the Energize environment. Avoid this option when you run
+@value{GDBN} directly from the command line. See @ref{Energize,,Using
+@value{GDBN} with Energize} for more discussion of using @value{GDBN} with Energize.
+@end ifset
+
+@ifclear DOSHOST
+@item -fullname
+@itemx -f
+@sc{gnu} Emacs sets this option when it runs @value{GDBN} as a subprocess. It tells @value{GDBN}
+to output the full file name and line number in a standard,
+recognizable fashion each time a stack frame is displayed (which
+includes each time your program stops). This recognizable format looks
+like two @samp{\032} characters, followed by the file name, line number
+and character position separated by colons, and a newline. The
+Emacs-to-@value{GDBN} interface program uses the two @samp{\032} characters as
+a signal to display the source code for the frame.
+@end ifclear
+
+@ifset SERIAL
+@item -b @var{bps}
+Set the line speed (baud rate or bits per second) of any serial
+interface used by @value{GDBN} for remote debugging.
+
+@item -tty @var{device}
+Run using @var{device} for your program's standard input and output.
+@c FIXME: kingdon thinks there is more to -tty. Investigate.
+@end ifset
+@end table
+
+@node Quitting GDB
+@section Quitting @value{GDBN}
+@cindex exiting @value{GDBN}
+@cindex leaving @value{GDBN}
+
+@table @code
+@kindex quit @r{[}@var{expression}@r{]}
+@kindex q
+@item quit
+To exit @value{GDBN}, use the @code{quit} command (abbreviated @code{q}), or
+type an end-of-file character (usually @kbd{C-d}). If you do not supply
+@var{expression}, @value{GDBN} will terminate normally; otherwise it will
+terminate using the result of @var{expression} as the error code.
+@end table
+
+@cindex interrupt
+An interrupt (often @kbd{C-c}) does not exit from @value{GDBN}, but rather
+terminates the action of any @value{GDBN} command that is in progress and
+returns to @value{GDBN} command level. It is safe to type the interrupt
+character at any time because @value{GDBN} does not allow it to take effect
+until a time when it is safe.
+
+@ifclear BARETARGET
+If you have been using @value{GDBN} to control an attached process or
+device, you can release it with the @code{detach} command
+(@pxref{Attach, ,Debugging an already-running process}).
+@end ifclear
+
+@node Shell Commands
+@section Shell commands
+
+If you need to execute occasional shell commands during your
+debugging session, there is no need to leave or suspend @value{GDBN}; you can
+just use the @code{shell} command.
+
+@table @code
+@kindex shell
+@cindex shell escape
+@item shell @var{command string}
+Invoke a the standard shell to execute @var{command string}.
+@ifclear DOSHOST
+If it exists, the environment variable @code{SHELL} determines which
+shell to run. Otherwise @value{GDBN} uses @code{/bin/sh}.
+@end ifclear
+@end table
+
+The utility @code{make} is often needed in development environments.
+You do not have to use the @code{shell} command for this purpose in
+@value{GDBN}:
+
+@table @code
+@kindex make
+@cindex calling make
+@item make @var{make-args}
+Execute the @code{make} program with the specified
+arguments. This is equivalent to @samp{shell make @var{make-args}}.
+@end table
+
+@node Commands
+@chapter @value{GDBN} Commands
+
+You can abbreviate a @value{GDBN} command to the first few letters of the command
+name, if that abbreviation is unambiguous; and you can repeat certain
+@value{GDBN} commands by typing just @key{RET}. You can also use the @key{TAB}
+key to get @value{GDBN} to fill out the rest of a word in a command (or to
+show you the alternatives available, if there is more than one possibility).
+
+@menu
+* Command Syntax:: How to give commands to @value{GDBN}
+* Completion:: Command completion
+* Help:: How to ask @value{GDBN} for help
+@end menu
+
+@node Command Syntax
+@section Command syntax
+
+A @value{GDBN} command is a single line of input. There is no limit on
+how long it can be. It starts with a command name, which is followed by
+arguments whose meaning depends on the command name. For example, the
+command @code{step} accepts an argument which is the number of times to
+step, as in @samp{step 5}. You can also use the @code{step} command
+with no arguments. Some command names do not allow any arguments.
+
+@cindex abbreviation
+@value{GDBN} command names may always be truncated if that abbreviation is
+unambiguous. Other possible command abbreviations are listed in the
+documentation for individual commands. In some cases, even ambiguous
+abbreviations are allowed; for example, @code{s} is specially defined as
+equivalent to @code{step} even though there are other commands whose
+names start with @code{s}. You can test abbreviations by using them as
+arguments to the @code{help} command.
+
+@cindex repeating commands
+@kindex RET
+A blank line as input to @value{GDBN} (typing just @key{RET}) means to
+repeat the previous command. Certain commands (for example, @code{run})
+will not repeat this way; these are commands whose unintentional
+repetition might cause trouble and which you are unlikely to want to
+repeat.
+
+The @code{list} and @code{x} commands, when you repeat them with
+@key{RET}, construct new arguments rather than repeating
+exactly as typed. This permits easy scanning of source or memory.
+
+@value{GDBN} can also use @key{RET} in another way: to partition lengthy
+output, in a way similar to the common utility @code{more}
+(@pxref{Screen Size,,Screen size}). Since it is easy to press one
+@key{RET} too many in this situation, @value{GDBN} disables command
+repetition after any command that generates this sort of display.
+
+@kindex #
+@cindex comment
+Any text from a @kbd{#} to the end of the line is a comment; it does
+nothing. This is useful mainly in command files (@pxref{Command
+Files,,Command files}).
+
+@node Completion
+@section Command completion
+
+@cindex completion
+@cindex word completion
+@value{GDBN} can fill in the rest of a word in a command for you, if there is
+only one possibility; it can also show you what the valid possibilities
+are for the next word in a command, at any time. This works for @value{GDBN}
+commands, @value{GDBN} subcommands, and the names of symbols in your program.
+
+Press the @key{TAB} key whenever you want @value{GDBN} to fill out the rest
+of a word. If there is only one possibility, @value{GDBN} fills in the
+word, and waits for you to finish the command (or press @key{RET} to
+enter it). For example, if you type
+
+@c FIXME "@key" does not distinguish its argument sufficiently to permit
+@c complete accuracy in these examples; space introduced for clarity.
+@c If texinfo enhancements make it unnecessary, it would be nice to
+@c replace " @key" by "@key" in the following...
+@example
+(@value{GDBP}) info bre @key{TAB}
+@end example
+
+@noindent
+@value{GDBN} fills in the rest of the word @samp{breakpoints}, since that is
+the only @code{info} subcommand beginning with @samp{bre}:
+
+@example
+(@value{GDBP}) info breakpoints
+@end example
+
+@noindent
+You can either press @key{RET} at this point, to run the @code{info
+breakpoints} command, or backspace and enter something else, if
+@samp{breakpoints} does not look like the command you expected. (If you
+were sure you wanted @code{info breakpoints} in the first place, you
+might as well just type @key{RET} immediately after @samp{info bre},
+to exploit command abbreviations rather than command completion).
+
+If there is more than one possibility for the next word when you press
+@key{TAB}, @value{GDBN} sounds a bell. You can either supply more
+characters and try again, or just press @key{TAB} a second time;
+@value{GDBN} displays all the possible completions for that word. For
+example, you might want to set a breakpoint on a subroutine whose name
+begins with @samp{make_}, but when you type @kbd{b make_@key{TAB}} @value{GDBN}
+just sounds the bell. Typing @key{TAB} again displays all the
+function names in your program that begin with those characters, for
+example:
+
+@example
+(@value{GDBP}) b make_ @key{TAB}
+@exdent @value{GDBN} sounds bell; press @key{TAB} again, to see:
+make_a_section_from_file make_environ
+make_abs_section make_function_type
+make_blockvector make_pointer_type
+make_cleanup make_reference_type
+make_command make_symbol_completion_list
+(@value{GDBP}) b make_
+@end example
+
+@noindent
+After displaying the available possibilities, @value{GDBN} copies your
+partial input (@samp{b make_} in the example) so you can finish the
+command.
+
+If you just want to see the list of alternatives in the first place, you
+can press @kbd{M-?} rather than pressing @key{TAB} twice. @kbd{M-?}
+means @kbd{@key{META} ?}. You can type this
+@ifclear DOSHOST
+either by holding down a
+key designated as the @key{META} shift on your keyboard (if there is
+one) while typing @kbd{?}, or
+@end ifclear
+as @key{ESC} followed by @kbd{?}.
+
+@cindex quotes in commands
+@cindex completion of quoted strings
+Sometimes the string you need, while logically a ``word'', may contain
+parentheses or other characters that @value{GDBN} normally excludes from its
+notion of a word. To permit word completion to work in this situation,
+you may enclose words in @code{'} (single quote marks) in @value{GDBN} commands.
+
+@ifclear CONLY
+The most likely situation where you might need this is in typing the
+name of a C++ function. This is because C++ allows function overloading
+(multiple definitions of the same function, distinguished by argument
+type). For example, when you want to set a breakpoint you may need to
+distinguish whether you mean the version of @code{name} that takes an
+@code{int} parameter, @code{name(int)}, or the version that takes a
+@code{float} parameter, @code{name(float)}. To use the word-completion
+facilities in this situation, type a single quote @code{'} at the
+beginning of the function name. This alerts @value{GDBN} that it may need to
+consider more information than usual when you press @key{TAB} or
+@kbd{M-?} to request word completion:
+
+@example
+(@value{GDBP}) b 'bubble( @key{M-?}
+bubble(double,double) bubble(int,int)
+(@value{GDBP}) b 'bubble(
+@end example
+
+In some cases, @value{GDBN} can tell that completing a name requires using
+quotes. When this happens, @value{GDBN} inserts the quote for you (while
+completing as much as it can) if you do not type the quote in the first
+place:
+
+@example
+(@value{GDBP}) b bub @key{TAB}
+@exdent @value{GDBN} alters your input line to the following, and rings a bell:
+(@value{GDBP}) b 'bubble(
+@end example
+
+@noindent
+In general, @value{GDBN} can tell that a quote is needed (and inserts it) if
+you have not yet started typing the argument list when you ask for
+completion on an overloaded symbol.
+@end ifclear
+
+
+@node Help
+@section Getting help
+@cindex online documentation
+@kindex help
+
+You can always ask @value{GDBN} itself for information on its commands,
+using the command @code{help}.
+
+@table @code
+@kindex h
+@item help
+@itemx h
+You can use @code{help} (abbreviated @code{h}) with no arguments to
+display a short list of named classes of commands:
+
+@smallexample
+(@value{GDBP}) help
+List of classes of commands:
+
+running -- Running the program
+stack -- Examining the stack
+data -- Examining data
+breakpoints -- Making program stop at certain points
+files -- Specifying and examining files
+status -- Status inquiries
+support -- Support facilities
+user-defined -- User-defined commands
+aliases -- Aliases of other commands
+obscure -- Obscure features
+
+Type "help" followed by a class name for a list of
+commands in that class.
+Type "help" followed by command name for full
+documentation.
+Command name abbreviations are allowed if unambiguous.
+(@value{GDBP})
+@end smallexample
+
+@item help @var{class}
+Using one of the general help classes as an argument, you can get a
+list of the individual commands in that class. For example, here is the
+help display for the class @code{status}:
+
+@smallexample
+(@value{GDBP}) help status
+Status inquiries.
+
+List of commands:
+
+@c Line break in "show" line falsifies real output, but needed
+@c to fit in smallbook page size.
+show -- Generic command for showing things set
+ with "set"
+info -- Generic command for printing status
+
+Type "help" followed by command name for full
+documentation.
+Command name abbreviations are allowed if unambiguous.
+(@value{GDBP})
+@end smallexample
+
+@item help @var{command}
+With a command name as @code{help} argument, @value{GDBN} displays a
+short paragraph on how to use that command.
+
+@kindex complete
+@item complete @var{args}
+The @code{complete @var{args}} command lists all the possible completions
+for the beginning of a command. Use @var{args} to specify the beginning of the
+command you want completed. For example:
+
+@smallexample
+complete i
+@end smallexample
+
+@noindent results in:
+
+@smallexample
+info
+inspect
+ignore
+@end smallexample
+
+@noindent This is intended for use by @sc{gnu} Emacs.
+@end table
+
+In addition to @code{help}, you can use the @value{GDBN} commands @code{info}
+and @code{show} to inquire about the state of your program, or the state
+of @value{GDBN} itself. Each command supports many topics of inquiry; this
+manual introduces each of them in the appropriate context. The listings
+under @code{info} and under @code{show} in the Index point to
+all the sub-commands. @xref{Index}.
+
+@c @group
+@table @code
+@kindex info
+@kindex i
+@item info
+This command (abbreviated @code{i}) is for describing the state of your
+program. For example, you can list the arguments given to your program
+with @code{info args}, list the registers currently in use with @code{info
+registers}, or list the breakpoints you have set with @code{info breakpoints}.
+You can get a complete list of the @code{info} sub-commands with
+@w{@code{help info}}.
+
+@kindex set
+@item set
+You can assign the result of an expresson to an environment variable with
+@code{set}. For example, you can set the @value{GDBN} prompt to a $-sign with
+@code{set prompt $}.
+
+@kindex show
+@item show
+In contrast to @code{info}, @code{show} is for describing the state of
+@value{GDBN} itself.
+You can change most of the things you can @code{show}, by using the
+related command @code{set}; for example, you can control what number
+system is used for displays with @code{set radix}, or simply inquire
+which is currently in use with @code{show radix}.
+
+@kindex info set
+To display all the settable parameters and their current
+values, you can use @code{show} with no arguments; you may also use
+@code{info set}. Both commands produce the same display.
+@c FIXME: "info set" violates the rule that "info" is for state of
+@c FIXME...program. Ck w/ GNU: "info set" to be called something else,
+@c FIXME...or change desc of rule---eg "state of prog and debugging session"?
+@end table
+@c @end group
+
+Here are three miscellaneous @code{show} subcommands, all of which are
+exceptional in lacking corresponding @code{set} commands:
+
+@table @code
+@kindex show version
+@cindex version number
+@item show version
+Show what version of @value{GDBN} is running. You should include this
+information in @value{GDBN} bug-reports. If multiple versions of @value{GDBN} are in
+use at your site, you may occasionally want to determine which version
+of @value{GDBN} you are running; as @value{GDBN} evolves, new commands are introduced,
+and old ones may wither away. The version number is also announced
+when you start @value{GDBN}.
+
+@kindex show copying
+@item show copying
+Display information about permission for copying @value{GDBN}.
+
+@kindex show warranty
+@item show warranty
+Display the @sc{gnu} ``NO WARRANTY'' statement.
+@end table
+
+@node Running
+@chapter Running Programs Under @value{GDBN}
+
+When you run a program under @value{GDBN}, you must first generate
+debugging information when you compile it.
+@ifclear BARETARGET
+You may start @value{GDBN} with its arguments, if any, in an environment
+of your choice. You may redirect your program's input and output, debug an
+already running process, or kill a child process.
+@end ifclear
+
+@menu
+* Compilation:: Compiling for debugging
+* Starting:: Starting your program
+@ifclear BARETARGET
+* Arguments:: Your program's arguments
+* Environment:: Your program's environment
+* Working Directory:: Your program's working directory
+* Input/Output:: Your program's input and output
+* Attach:: Debugging an already-running process
+* Kill Process:: Killing the child process
+* Process Information:: Additional process information
+* Threads:: Debugging programs with multiple threads
+* Processes:: Debugging programs with multiple processes
+@end ifclear
+@end menu
+
+@node Compilation
+@section Compiling for debugging
+
+In order to debug a program effectively, you need to generate
+debugging information when you compile it. This debugging information
+is stored in the object file; it describes the data type of each
+variable or function and the correspondence between source line numbers
+and addresses in the executable code.
+
+To request debugging information, specify the @samp{-g} option when you run
+the compiler.
+
+Many C compilers are unable to handle the @samp{-g} and @samp{-O}
+options together. Using those compilers, you cannot generate optimized
+executables containing debugging information.
+
+@value{NGCC}, the @sc{gnu} C compiler, supports @samp{-g} with or without
+@samp{-O}, making it possible to debug optimized code. We recommend
+that you @emph{always} use @samp{-g} whenever you compile a program.
+You may think your program is correct, but there is no sense in pushing
+your luck.
+
+@cindex optimized code, debugging
+@cindex debugging optimized code
+When you debug a program compiled with @samp{-g -O}, remember that the
+optimizer is rearranging your code; the debugger shows you what is
+really there. Do not be too surprised when the execution path does not
+exactly match your source file! An extreme example: if you define a
+variable, but never use it, @value{GDBN} never sees that
+variable---because the compiler optimizes it out of existence.
+
+Some things do not work as well with @samp{-g -O} as with just
+@samp{-g}, particularly on machines with instruction scheduling. If in
+doubt, recompile with @samp{-g} alone, and if this fixes the problem,
+please report it to us as a bug (including a test case!).
+
+Older versions of the @sc{gnu} C compiler permitted a variant option
+@w{@samp{-gg}} for debugging information. @value{GDBN} no longer supports this
+format; if your @sc{gnu} C compiler has this option, do not use it.
+
+@need 2000
+@node Starting
+@section Starting your program
+@cindex starting
+@cindex running
+
+@table @code
+@kindex run
+@item run
+@itemx r
+Use the @code{run} command to start your program under @value{GDBN}. You must
+first specify the program name
+@ifset VXWORKS
+(except on VxWorks)
+@end ifset
+with an argument to @value{GDBN} (@pxref{Invocation, ,Getting In and
+Out of @value{GDBN}}), or by using the @code{file} or @code{exec-file}
+command (@pxref{Files, ,Commands to specify files}).
+
+@end table
+
+@ifclear BARETARGET
+If you are running your program in an execution environment that
+supports processes, @code{run} creates an inferior process and makes
+that process run your program. (In environments without processes,
+@code{run} jumps to the start of your program.)
+
+The execution of a program is affected by certain information it
+receives from its superior. @value{GDBN} provides ways to specify this
+information, which you must do @emph{before} starting your program. (You
+can change it after starting your program, but such changes only affect
+your program the next time you start it.) This information may be
+divided into four categories:
+
+@table @asis
+@item The @emph{arguments.}
+Specify the arguments to give your program as the arguments of the
+@code{run} command. If a shell is available on your target, the shell
+is used to pass the arguments, so that you may use normal conventions
+(such as wildcard expansion or variable substitution) in describing
+the arguments. In Unix systems, you can control which shell is used
+with the @code{SHELL} environment variable. @xref{Arguments, ,Your
+program's arguments}.
+
+@item The @emph{environment.}
+Your program normally inherits its environment from @value{GDBN}, but you can
+use the @value{GDBN} commands @code{set environment} and @code{unset
+environment} to change parts of the environment that affect
+your program. @xref{Environment, ,Your program's environment}.
+
+@item The @emph{working directory.}
+Your program inherits its working directory from @value{GDBN}. You can set
+the @value{GDBN} working directory with the @code{cd} command in @value{GDBN}.
+@xref{Working Directory, ,Your program's working directory}.
+
+@item The @emph{standard input and output.}
+Your program normally uses the same device for standard input and
+standard output as @value{GDBN} is using. You can redirect input and output
+in the @code{run} command line, or you can use the @code{tty} command to
+set a different device for your program.
+@xref{Input/Output, ,Your program's input and output}.
+
+@cindex pipes
+@emph{Warning:} While input and output redirection work, you cannot use
+pipes to pass the output of the program you are debugging to another
+program; if you attempt this, @value{GDBN} is likely to wind up debugging the
+wrong program.
+@end table
+@end ifclear
+
+When you issue the @code{run} command, your program begins to execute
+immediately. @xref{Stopping, ,Stopping and continuing}, for discussion
+of how to arrange for your program to stop. Once your program has
+stopped, you may call functions in your program, using the @code{print}
+or @code{call} commands. @xref{Data, ,Examining Data}.
+
+If the modification time of your symbol file has changed since the last
+time @value{GDBN} read its symbols, @value{GDBN} discards its symbol
+table, and reads it again. When it does this, @value{GDBN} tries to retain
+your current breakpoints.
+
+@ifclear BARETARGET
+@node Arguments
+@section Your program's arguments
+
+@cindex arguments (to your program)
+The arguments to your program can be specified by the arguments of the
+@code{run} command. They are passed to a shell, which expands wildcard
+characters and performs redirection of I/O, and thence to your program.
+Your @code{SHELL} environment variable (if it exists) specifies what
+shell @value{GDBN} uses. If you do not define @code{SHELL},
+@value{GDBN} uses @code{/bin/sh}.
+
+@code{run} with no arguments uses the same arguments used by the previous
+@code{run}, or those set by the @code{set args} command.
+
+@kindex set args
+@table @code
+@item set args
+Specify the arguments to be used the next time your program is run. If
+@code{set args} has no arguments, @code{run} executes your program
+with no arguments. Once you have run your program with arguments,
+using @code{set args} before the next @code{run} is the only way to run
+it again without arguments.
+
+@kindex show args
+@item show args
+Show the arguments to give your program when it is started.
+@end table
+
+@node Environment
+@section Your program's environment
+
+@cindex environment (of your program)
+The @dfn{environment} consists of a set of environment variables and
+their values. Environment variables conventionally record such things as
+your user name, your home directory, your terminal type, and your search
+path for programs to run. Usually you set up environment variables with
+the shell and they are inherited by all the other programs you run. When
+debugging, it can be useful to try running your program with a modified
+environment without having to start @value{GDBN} over again.
+
+@table @code
+@kindex path
+@item path @var{directory}
+Add @var{directory} to the front of the @code{PATH} environment variable
+(the search path for executables), for both @value{GDBN} and your program.
+You may specify several directory names, separated by @samp{:} or
+whitespace. If @var{directory} is already in the path, it is moved to
+the front, so it is searched sooner.
+
+You can use the string @samp{$cwd} to refer to whatever is the current
+working directory at the time @value{GDBN} searches the path. If you
+use @samp{.} instead, it refers to the directory where you executed the
+@code{path} command. @value{GDBN} replaces @samp{.} in the
+@var{directory} argument (with the current path) before adding
+@var{directory} to the search path.
+@c 'path' is explicitly nonrepeatable, but RMS points out it is silly to
+@c document that, since repeating it would be a no-op.
+
+@kindex show paths
+@item show paths
+Display the list of search paths for executables (the @code{PATH}
+environment variable).
+
+@kindex show environment
+@item show environment @r{[}@var{varname}@r{]}
+Print the value of environment variable @var{varname} to be given to
+your program when it starts. If you do not supply @var{varname},
+print the names and values of all environment variables to be given to
+your program. You can abbreviate @code{environment} as @code{env}.
+
+@kindex set environment
+@item set environment @var{varname} @r{[}=@r{]} @var{value}
+Set environment variable @var{varname} to @var{value}. The value
+changes for your program only, not for @value{GDBN} itself. @var{value} may
+be any string; the values of environment variables are just strings, and
+any interpretation is supplied by your program itself. The @var{value}
+parameter is optional; if it is eliminated, the variable is set to a
+null value.
+@c "any string" here does not include leading, trailing
+@c blanks. Gnu asks: does anyone care?
+
+For example, this command:
+
+@example
+set env USER = foo
+@end example
+
+@noindent
+tells a Unix program, when subsequently run, that its user is named
+@samp{foo}. (The spaces around @samp{=} are used for clarity here; they
+are not actually required.)
+
+@kindex unset environment
+@item unset environment @var{varname}
+Remove variable @var{varname} from the environment to be passed to your
+program. This is different from @samp{set env @var{varname} =};
+@code{unset environment} removes the variable from the environment,
+rather than assigning it an empty value.
+@end table
+
+@emph{Warning:} @value{GDBN} runs your program using the shell indicated
+by your @code{SHELL} environment variable if it exists (or
+@code{/bin/sh} if not). If your @code{SHELL} variable names a shell
+that runs an initialization file---such as @file{.cshrc} for C-shell, or
+@file{.bashrc} for BASH---any variables you set in that file affect
+your program. You may wish to move setting of environment variables to
+files that are only run when you sign on, such as @file{.login} or
+@file{.profile}.
+
+@node Working Directory
+@section Your program's working directory
+
+@cindex working directory (of your program)
+Each time you start your program with @code{run}, it inherits its
+working directory from the current working directory of @value{GDBN}.
+The @value{GDBN} working directory is initially whatever it inherited
+from its parent process (typically the shell), but you can specify a new
+working directory in @value{GDBN} with the @code{cd} command.
+
+The @value{GDBN} working directory also serves as a default for the commands
+that specify files for @value{GDBN} to operate on. @xref{Files, ,Commands to
+specify files}.
+
+@table @code
+@kindex cd
+@item cd @var{directory}
+Set the @value{GDBN} working directory to @var{directory}.
+
+@kindex pwd
+@item pwd
+Print the @value{GDBN} working directory.
+@end table
+
+@node Input/Output
+@section Your program's input and output
+
+@cindex redirection
+@cindex i/o
+@cindex terminal
+By default, the program you run under @value{GDBN} does input and output to
+the same terminal that @value{GDBN} uses. @value{GDBN} switches the terminal
+to its own terminal modes to interact with you, but it records the terminal
+modes your program was using and switches back to them when you continue
+running your program.
+
+@table @code
+@kindex info terminal
+@item info terminal
+Displays information recorded by @value{GDBN} about the terminal modes your
+program is using.
+@end table
+
+You can redirect your program's input and/or output using shell
+redirection with the @code{run} command. For example,
+
+@example
+run > outfile
+@end example
+
+@noindent
+starts your program, diverting its output to the file @file{outfile}.
+
+@kindex tty
+@cindex controlling terminal
+Another way to specify where your program should do input and output is
+with the @code{tty} command. This command accepts a file name as
+argument, and causes this file to be the default for future @code{run}
+commands. It also resets the controlling terminal for the child
+process, for future @code{run} commands. For example,
+
+@example
+tty /dev/ttyb
+@end example
+
+@noindent
+directs that processes started with subsequent @code{run} commands
+default to do input and output on the terminal @file{/dev/ttyb} and have
+that as their controlling terminal.
+
+An explicit redirection in @code{run} overrides the @code{tty} command's
+effect on the input/output device, but not its effect on the controlling
+terminal.
+
+When you use the @code{tty} command or redirect input in the @code{run}
+command, only the input @emph{for your program} is affected. The input
+for @value{GDBN} still comes from your terminal.
+
+@node Attach
+@section Debugging an already-running process
+@kindex attach
+@cindex attach
+
+@table @code
+@item attach @var{process-id}
+This command attaches to a running process---one that was started
+outside @value{GDBN}. (@code{info files} shows your active
+targets.) The command takes as argument a process ID. The usual way to
+find out the process-id of a Unix process is with the @code{ps} utility,
+or with the @samp{jobs -l} shell command.
+
+@code{attach} does not repeat if you press @key{RET} a second time after
+executing the command.
+@end table
+
+To use @code{attach}, your program must be running in an environment
+which supports processes; for example, @code{attach} does not work for
+programs on bare-board targets that lack an operating system. You must
+also have permission to send the process a signal.
+
+When using @code{attach}, you should first use the @code{file} command
+to specify the program running in the process and load its symbol table.
+@xref{Files, ,Commands to Specify Files}.
+
+The first thing @value{GDBN} does after arranging to debug the specified
+process is to stop it. You can examine and modify an attached process
+with all the @value{GDBN} commands that are ordinarily available when you start
+processes with @code{run}. You can insert breakpoints; you can step and
+continue; you can modify storage. If you would rather the process
+continue running, you may use the @code{continue} command after
+attaching @value{GDBN} to the process.
+
+@table @code
+@kindex detach
+@item detach
+When you have finished debugging the attached process, you can use the
+@code{detach} command to release it from @value{GDBN} control. Detaching
+the process continues its execution. After the @code{detach} command,
+that process and @value{GDBN} become completely independent once more, and you
+are ready to @code{attach} another process or start one with @code{run}.
+@code{detach} does not repeat if you press @key{RET} again after
+executing the command.
+@end table
+
+If you exit @value{GDBN} or use the @code{run} command while you have an
+attached process, you kill that process. By default, @value{GDBN} asks
+for confirmation if you try to do either of these things; you can
+control whether or not you need to confirm by using the @code{set
+confirm} command (@pxref{Messages/Warnings, ,Optional warnings and
+messages}).
+
+@node Kill Process
+@c @group
+@section Killing the child process
+
+@table @code
+@kindex kill
+@item kill
+Kill the child process in which your program is running under @value{GDBN}.
+@end table
+
+This command is useful if you wish to debug a core dump instead of a
+running process. @value{GDBN} ignores any core dump file while your program
+is running.
+@c @end group
+
+On some operating systems, a program cannot be executed outside @value{GDBN}
+while you have breakpoints set on it inside @value{GDBN}. You can use the
+@code{kill} command in this situation to permit running your program
+outside the debugger.
+
+The @code{kill} command is also useful if you wish to recompile and
+relink your program, since on many systems it is impossible to modify an
+executable file while it is running in a process. In this case, when you
+next type @code{run}, @value{GDBN} notices that the file has changed, and
+reads the symbol table again (while trying to preserve your current
+breakpoint settings).
+
+@node Process Information
+@section Additional process information
+
+@kindex /proc
+@cindex process image
+Some operating systems provide a facility called @samp{/proc} that can
+be used to examine the image of a running process using file-system
+subroutines. If @value{GDBN} is configured for an operating system with this
+facility, the command @code{info proc} is available to report on several
+kinds of information about the process running your program.
+@code{info proc} works only on SVR4 systems that support @code{procfs}.
+
+@table @code
+@kindex info proc
+@item info proc
+Summarize available information about the process.
+
+@kindex info proc mappings
+@item info proc mappings
+Report on the address ranges accessible in the program, with information
+on whether your program may read, write, or execute each range.
+
+@kindex info proc times
+@item info proc times
+Starting time, user CPU time, and system CPU time for your program and
+its children.
+
+@kindex info proc id
+@item info proc id
+Report on the process IDs related to your program: its own process ID,
+the ID of its parent, the process group ID, and the session ID.
+
+@kindex info proc status
+@item info proc status
+General information on the state of the process. If the process is
+stopped, this report includes the reason for stopping, and any signal
+received.
+
+@item info proc all
+Show all the above information about the process.
+@end table
+
+@node Threads
+@section Debugging programs with multiple threads
+
+@cindex threads of execution
+@cindex multiple threads
+@cindex switching threads
+In some operating systems, a single program may have more than one
+@dfn{thread} of execution. The precise semantics of threads differ from
+one operating system to another, but in general the threads of a single
+program are akin to multiple processes---except that they share one
+address space (that is, they can all examine and modify the same
+variables). On the other hand, each thread has its own registers and
+execution stack, and perhaps private memory.
+
+@value{GDBN} provides these facilities for debugging multi-thread
+programs:
+
+@itemize @bullet
+@item automatic notification of new threads
+@item @samp{thread @var{threadno}}, a command to switch among threads
+@item @samp{info threads}, a command to inquire about existing threads
+@item @samp{thread apply [@var{threadno}] [@var{all}] @var{args}},
+a command to apply a command to a list of threads
+@item thread-specific breakpoints
+@end itemize
+
+@quotation
+@emph{Warning:} These facilities are not yet available on every
+@value{GDBN} configuration where the operating system supports threads.
+If your @value{GDBN} does not support threads, these commands have no
+effect. For example, a system without thread support shows no output
+from @samp{info threads}, and always rejects the @code{thread} command,
+like this:
+
+@smallexample
+(@value{GDBP}) info threads
+(@value{GDBP}) thread 1
+Thread ID 1 not known. Use the "info threads" command to
+see the IDs of currently known threads.
+@end smallexample
+@c FIXME to implementors: how hard would it be to say "sorry, this GDB
+@c doesn't support threads"?
+@end quotation
+
+@cindex focus of debugging
+@cindex current thread
+The @value{GDBN} thread debugging facility allows you to observe all
+threads while your program runs---but whenever @value{GDBN} takes
+control, one thread in particular is always the focus of debugging.
+This thread is called the @dfn{current thread}. Debugging commands show
+program information from the perspective of the current thread.
+
+@kindex New @var{systag}
+@cindex thread identifier (system)
+@c FIXME-implementors!! It would be more helpful if the [New...] message
+@c included GDB's numeric thread handle, so you could just go to that
+@c thread without first checking `info threads'.
+Whenever @value{GDBN} detects a new thread in your program, it displays
+the target system's identification for the thread with a message in the
+form @samp{[New @var{systag}]}. @var{systag} is a thread identifier
+whose form varies depending on the particular system. For example, on
+LynxOS, you might see
+
+@example
+[New process 35 thread 27]
+@end example
+
+@noindent
+when @value{GDBN} notices a new thread. In contrast, on an SGI system,
+the @var{systag} is simply something like @samp{process 368}, with no
+further qualifier.
+
+@c FIXME!! (1) Does the [New...] message appear even for the very first
+@c thread of a program, or does it only appear for the
+@c second---i.e., when it becomes obvious we have a multithread
+@c program?
+@c (2) *Is* there necessarily a first thread always? Or do some
+@c multithread systems permit starting a program with multiple
+@c threads ab initio?
+
+@cindex thread number
+@cindex thread identifier (GDB)
+For debugging purposes, @value{GDBN} associates its own thread
+number---always a single integer---with each thread in your program.
+
+@table @code
+@kindex info threads
+@item info threads
+Display a summary of all threads currently in your
+program. @value{GDBN} displays for each thread (in this order):
+
+@enumerate
+@item the thread number assigned by @value{GDBN}
+
+@item the target system's thread identifier (@var{systag})
+
+@item the current stack frame summary for that thread
+@end enumerate
+
+@noindent
+An asterisk @samp{*} to the left of the @value{GDBN} thread number
+indicates the current thread.
+
+For example,
+@end table
+@c end table here to get a little more width for example
+
+@smallexample
+(@value{GDBP}) info threads
+ 3 process 35 thread 27 0x34e5 in sigpause ()
+ 2 process 35 thread 23 0x34e5 in sigpause ()
+* 1 process 35 thread 13 main (argc=1, argv=0x7ffffff8)
+ at threadtest.c:68
+@end smallexample
+
+@table @code
+@kindex thread @var{threadno}
+@item thread @var{threadno}
+Make thread number @var{threadno} the current thread. The command
+argument @var{threadno} is the internal @value{GDBN} thread number, as
+shown in the first field of the @samp{info threads} display.
+@value{GDBN} responds by displaying the system identifier of the thread
+you selected, and its current stack frame summary:
+
+@smallexample
+@c FIXME!! This example made up; find a @value{GDBN} w/threads and get real one
+(@value{GDBP}) thread 2
+[Switching to process 35 thread 23]
+0x34e5 in sigpause ()
+@end smallexample
+
+@noindent
+As with the @samp{[New @dots{}]} message, the form of the text after
+@samp{Switching to} depends on your system's conventions for identifying
+threads.
+
+@kindex thread apply
+@item thread apply [@var{threadno}] [@var{all}] @var{args}
+The @code{thread apply} command allows you to apply a command to one or
+more threads. Specify the numbers of the threads that you want affected
+with the command argument @var{threadno}. @var{threadno} is the internal
+@value{GDBN} thread number, as shown in the first field of the @samp{info
+threads} display. To apply a command to all threads, use
+@code{thread apply all} @var{args}.
+@end table
+
+@cindex automatic thread selection
+@cindex switching threads automatically
+@cindex threads, automatic switching
+Whenever @value{GDBN} stops your program, due to a breakpoint or a
+signal, it automatically selects the thread where that breakpoint or
+signal happened. @value{GDBN} alerts you to the context switch with a
+message of the form @samp{[Switching to @var{systag}]} to identify the
+thread.
+
+@xref{Thread Stops,,Stopping and starting multi-thread programs}, for
+more information about how @value{GDBN} behaves when you stop and start
+programs with multiple threads.
+
+@xref{Set Watchpoints,,Setting watchpoints}, for information about
+watchpoints in programs with multiple threads.
+@end ifclear
+
+@node Processes
+@section Debugging programs with multiple processes
+
+@cindex fork, debugging programs which call
+@cindex multiple processes
+@cindex processes, multiple
+@value{GDBN} has no special support for debugging programs which create
+additional processes using the @code{fork} function. When a program
+forks, @value{GDBN} will continue to debug the parent process and the
+child process will run unimpeded. If you have set a breakpoint in any
+code which the child then executes, the child will get a @code{SIGTRAP}
+signal which (unless it catches the signal) will cause it to terminate.
+
+However, if you want to debug the child process there is a workaround
+which isn't too painful. Put a call to @code{sleep} in the code which
+the child process executes after the fork. It may be useful to sleep
+only if a certain environment variable is set, or a certain file exists,
+so that the delay need not occur when you don't want to run @value{GDBN}
+on the child. While the child is sleeping, use the @code{ps} program to
+get its process ID. Then tell @value{GDBN} (a new invocation of
+@value{GDBN} if you are also debugging the parent process) to attach to
+the child process (see @ref{Attach}). From that point on you can debug
+the child process just like any other process which you attached to.
+
+@node Stopping
+@chapter Stopping and Continuing
+
+The principal purposes of using a debugger are so that you can stop your
+program before it terminates; or so that, if your program runs into
+trouble, you can investigate and find out why.
+
+Inside @value{GDBN}, your program may stop for any of several reasons, such
+as
+@ifclear BARETARGET
+a signal,
+@end ifclear
+a breakpoint, or reaching a new line after a @value{GDBN}
+command such as @code{step}. You may then examine and change
+variables, set new breakpoints or remove old ones, and then continue
+execution. Usually, the messages shown by @value{GDBN} provide ample
+explanation of the status of your program---but you can also explicitly
+request this information at any time.
+
+@table @code
+@kindex info program
+@item info program
+Display information about the status of your program: whether it is
+running or not,
+@ifclear BARETARGET
+what process it is,
+@end ifclear
+and why it stopped.
+@end table
+
+@menu
+@ifclear CONLY
+* Breakpoints:: Breakpoints, watchpoints, and exceptions
+@end ifclear
+@ifset CONLY
+* Breakpoints:: Breakpoints and watchpoints
+@end ifset
+@c Remnant makeinfo bug requires blank line after *successful* end-if in menu:
+
+* Continuing and Stepping:: Resuming execution
+@ifset POSIX
+* Signals:: Signals
+@end ifset
+@ifclear BARETARGET
+* Thread Stops:: Stopping and starting multi-thread programs
+@end ifclear
+@end menu
+
+@c makeinfo node-defaulting requires adjacency of @node and sectioning cmds
+@c ...hence distribute @node Breakpoints over two possible @if expansions.
+@c
+@ifclear CONLY
+@node Breakpoints
+@section Breakpoints, watchpoints, and exceptions
+@end ifclear
+@ifset CONLY
+@node Breakpoints
+@section Breakpoints and watchpoints
+@end ifset
+
+@cindex breakpoints
+A @dfn{breakpoint} makes your program stop whenever a certain point in
+the program is reached. For each breakpoint, you can add
+conditions to control in finer detail whether your program stops.
+You can set breakpoints with the @code{break} command and its variants
+(@pxref{Set Breaks, ,Setting breakpoints}), to specify the place where
+your program should stop by line number, function name or exact address
+in the program.
+@ifclear CONLY
+In languages with exception handling (such as @sc{gnu} C++), you can also set
+breakpoints where an exception is raised (@pxref{Exception Handling,,
+Breakpoints and exceptions}).
+@end ifclear
+
+In SunOS 4.x, SVR4, and Alpha OSF/1 configurations, you can now set
+breakpoints in shared libraries before the executable is run.
+
+@cindex watchpoints
+@cindex memory tracing
+@cindex breakpoint on memory address
+@cindex breakpoint on variable modification
+A @dfn{watchpoint} is a special breakpoint that stops your program
+when the value of an expression changes. You must use a different
+command to set watchpoints (@pxref{Set Watchpoints, ,Setting
+watchpoints}), but aside from that, you can manage a watchpoint like
+any other breakpoint: you enable, disable, and delete both breakpoints
+and watchpoints using the same commands.
+
+You can arrange to have values from your program displayed automatically
+whenever @value{GDBN} stops at a breakpoint. @xref{Auto Display,,
+Automatic display}.
+
+@cindex breakpoint numbers
+@cindex numbers for breakpoints
+@value{GDBN} assigns a number to each breakpoint or watchpoint when you
+create it; these numbers are successive integers starting with one. In
+many of the commands for controlling various features of breakpoints you
+use the breakpoint number to say which breakpoint you want to change.
+Each breakpoint may be @dfn{enabled} or @dfn{disabled}; if disabled, it has
+no effect on your program until you enable it again.
+
+@menu
+* Set Breaks:: Setting breakpoints
+* Set Watchpoints:: Setting watchpoints
+@ifclear CONLY
+* Exception Handling:: Breakpoints and exceptions
+@end ifclear
+
+* Delete Breaks:: Deleting breakpoints
+* Disabling:: Disabling breakpoints
+* Conditions:: Break conditions
+* Break Commands:: Breakpoint command lists
+@ifclear CONLY
+* Breakpoint Menus:: Breakpoint menus
+@end ifclear
+@c @ifclear BARETARGET
+@c * Error in Breakpoints:: ``Cannot insert breakpoints''
+@c @end ifclear
+@end menu
+
+@node Set Breaks
+@subsection Setting breakpoints
+
+@c FIXME LMB what does GDB do if no code on line of breakpt?
+@c consider in particular declaration with/without initialization.
+@c
+@c FIXME 2 is there stuff on this already? break at fun start, already init?
+
+@kindex break
+@kindex b
+@kindex $bpnum
+@cindex latest breakpoint
+Breakpoints are set with the @code{break} command (abbreviated
+@code{b}). The debugger convenience variable @samp{$bpnum} records the
+number of the breakpoints you've set most recently; see @ref{Convenience
+Vars,, Convenience variables}, for a discussion of what you can do with
+convenience variables.
+
+You have several ways to say where the breakpoint should go.
+
+@table @code
+@item break @var{function}
+Set a breakpoint at entry to function @var{function}.
+@ifclear CONLY
+When using source languages that permit overloading of symbols, such as
+C++, @var{function} may refer to more than one possible place to break.
+@xref{Breakpoint Menus,,Breakpoint menus}, for a discussion of that situation.
+@end ifclear
+
+@item break +@var{offset}
+@itemx break -@var{offset}
+Set a breakpoint some number of lines forward or back from the position
+at which execution stopped in the currently selected frame.
+
+@item break @var{linenum}
+Set a breakpoint at line @var{linenum} in the current source file.
+That file is the last file whose source text was printed. This
+breakpoint stops your program just before it executes any of the
+code on that line.
+
+@item break @var{filename}:@var{linenum}
+Set a breakpoint at line @var{linenum} in source file @var{filename}.
+
+@item break @var{filename}:@var{function}
+Set a breakpoint at entry to function @var{function} found in file
+@var{filename}. Specifying a file name as well as a function name is
+superfluous except when multiple files contain similarly named
+functions.
+
+@item break *@var{address}
+Set a breakpoint at address @var{address}. You can use this to set
+breakpoints in parts of your program which do not have debugging
+information or source files.
+
+@item break
+When called without any arguments, @code{break} sets a breakpoint at
+the next instruction to be executed in the selected stack frame
+(@pxref{Stack, ,Examining the Stack}). In any selected frame but the
+innermost, this makes your program stop as soon as control
+returns to that frame. This is similar to the effect of a
+@code{finish} command in the frame inside the selected frame---except
+that @code{finish} does not leave an active breakpoint. If you use
+@code{break} without an argument in the innermost frame, @value{GDBN} stops
+the next time it reaches the current location; this may be useful
+inside loops.
+
+@value{GDBN} normally ignores breakpoints when it resumes execution, until at
+least one instruction has been executed. If it did not do this, you
+would be unable to proceed past a breakpoint without first disabling the
+breakpoint. This rule applies whether or not the breakpoint already
+existed when your program stopped.
+
+@item break @dots{} if @var{cond}
+Set a breakpoint with condition @var{cond}; evaluate the expression
+@var{cond} each time the breakpoint is reached, and stop only if the
+value is nonzero---that is, if @var{cond} evaluates as true.
+@samp{@dots{}} stands for one of the possible arguments described
+above (or no argument) specifying where to break. @xref{Conditions,
+,Break conditions}, for more information on breakpoint conditions.
+
+@kindex tbreak
+@item tbreak @var{args}
+Set a breakpoint enabled only for one stop. @var{args} are the
+same as for the @code{break} command, and the breakpoint is set in the same
+way, but the breakpoint is automatically deleted after the first time your
+program stops there. @xref{Disabling, ,Disabling breakpoints}.
+
+@kindex hbreak
+@item hbreak @var{args}
+Set a hardware-assisted breakpoint. @var{args} are the same as for the
+@code{break} command and the breakpoint is set in the same way, but the
+breakpoint requires hardware support and some target hardware may not
+have this support. The main purpose of this is EPROM/ROM code
+debugging, so you can set a breakpoint at an instruction without
+changing the instruction. This can be used with the new trap-generation
+provided by SPARClite DSU. DSU will generate traps when a program accesses
+some date or instruction address that is assigned to the debug registers.
+However the hardware breakpoint registers can only take two data breakpoints,
+and @value{GDBN} will reject this command if more than two are used.
+Delete or disable usused hardware breakpoints before setting
+new ones. @xref{Conditions, ,Break conditions}.
+
+@kindex thbreak
+@item thbreak @var{args}
+Set a hardware-assisted breakpoint enabled only for one stop. @var{args}
+are the same as for the @code{hbreak} command and the breakpoint is set in
+the same way. However, like the @code{tbreak} command,
+the breakpoint is automatically deleted after the
+first time your program stops there. Also, like the @code{hbreak}
+command, the breakpoint requires hardware support and some target hardware
+may not have this support. @xref{Disabling, ,Disabling breakpoints}.
+Also @xref{Conditions, ,Break conditions}.
+
+@kindex rbreak
+@cindex regular expression
+@item rbreak @var{regex}
+@c FIXME what kind of regexp?
+Set breakpoints on all functions matching the regular expression
+@var{regex}. This command
+sets an unconditional breakpoint on all matches, printing a list of all
+breakpoints it set. Once these breakpoints are set, they are treated
+just like the breakpoints set with the @code{break} command. You can
+delete them, disable them, or make them conditional the same way as any
+other breakpoint.
+
+@ifclear CONLY
+When debugging C++ programs, @code{rbreak} is useful for setting
+breakpoints on overloaded functions that are not members of any special
+classes.
+@end ifclear
+
+@kindex info breakpoints
+@cindex @code{$_} and @code{info breakpoints}
+@item info breakpoints @r{[}@var{n}@r{]}
+@itemx info break @r{[}@var{n}@r{]}
+@itemx info watchpoints @r{[}@var{n}@r{]}
+Print a table of all breakpoints and watchpoints set and not
+deleted, with the following columns for each breakpoint:
+
+@table @emph
+@item Breakpoint Numbers
+@item Type
+Breakpoint or watchpoint.
+@item Disposition
+Whether the breakpoint is marked to be disabled or deleted when hit.
+@item Enabled or Disabled
+Enabled breakpoints are marked with @samp{y}. @samp{n} marks breakpoints
+that are not enabled.
+@item Address
+Where the breakpoint is in your program, as a memory address
+@item What
+Where the breakpoint is in the source for your program, as a file and
+line number.
+@end table
+
+@noindent
+If a breakpoint is conditional, @code{info break} shows the condition on
+the line following the affected breakpoint; breakpoint commands, if any,
+are listed after that.
+
+@noindent
+@code{info break} with a breakpoint
+number @var{n} as argument lists only that breakpoint. The
+convenience variable @code{$_} and the default examining-address for
+the @code{x} command are set to the address of the last breakpoint
+listed (@pxref{Memory, ,Examining memory}).
+
+@noindent
+@code{info break} now displays a count of the number of times the
+breakpoint has been hit. This is especially useful in conjunction with
+the @code{ignore} command. You can ignore a large number of breakpoint
+hits, look at the breakpoint info to see how many times the
+breakpoint was hit, and then run again, ignoring one less than that
+number. This will get you quickly to the last hit of that breakpoint.
+@end table
+
+@value{GDBN} allows you to set any number of breakpoints at the same place in
+your program. There is nothing silly or meaningless about this. When
+the breakpoints are conditional, this is even useful
+(@pxref{Conditions, ,Break conditions}).
+
+@cindex negative breakpoint numbers
+@cindex internal @value{GDBN} breakpoints
+@value{GDBN} itself sometimes sets breakpoints in your program for special
+purposes, such as proper handling of @code{longjmp} (in C programs).
+These internal breakpoints are assigned negative numbers, starting with
+@code{-1}; @samp{info breakpoints} does not display them.
+
+You can see these breakpoints with the @value{GDBN} maintenance command
+@samp{maint info breakpoints}.
+
+@table @code
+@kindex maint info breakpoints
+@item maint info breakpoints
+Using the same format as @samp{info breakpoints}, display both the
+breakpoints you've set explicitly, and those @value{GDBN} is using for
+internal purposes. Internal breakpoints are shown with negative
+breakpoint numbers. The type column identifies what kind of breakpoint
+is shown:
+
+@table @code
+@item breakpoint
+Normal, explicitly set breakpoint.
+
+@item watchpoint
+Normal, explicitly set watchpoint.
+
+@item longjmp
+Internal breakpoint, used to handle correctly stepping through
+@code{longjmp} calls.
+
+@item longjmp resume
+Internal breakpoint at the target of a @code{longjmp}.
+
+@item until
+Temporary internal breakpoint used by the @value{GDBN} @code{until} command.
+
+@item finish
+Temporary internal breakpoint used by the @value{GDBN} @code{finish} command.
+@end table
+
+@end table
+
+
+@node Set Watchpoints
+@subsection Setting watchpoints
+@cindex setting watchpoints
+
+You can use a watchpoint to stop execution whenever the value of an
+expression changes, without having to predict a particular place
+where this may happen.
+
+Watchpoints currently execute two orders of magnitude more slowly than
+other breakpoints, but this can be well worth it to catch errors where
+you have no clue what part of your program is the culprit.
+
+@c FIXME - did Stan mean to @ignore this out?
+@ignore
+Some processors provide special hardware to support watchpoint
+evaluation; @value{GDBN} will use such hardware if it is available,
+and if the support code has been added for that configuration.
+@end ignore
+
+@table @code
+@kindex watch
+@item watch @var{expr}
+Set a watchpoint for an expression. @value{GDBN} will break when @var{expr}
+is written into by the program and its value changes.
+This can be used with the new trap-generation provided by
+SPARClite DSU. DSU will generate traps when a program accesses
+some date or instruction address that is assigned to the debug registers.
+For the data addresses, DSU facilitates the @code{watch} command.
+However the hardware breakpoint registers can only take two data watchpoints,
+and both watchpoints must be the same kind. For example, you can set two
+watchpoints with @code{watch} commands, two with @code{rwatch}
+commands, @strong{or} two with @code{awatch} commands, but you cannot set one
+watchpoint with one command and the other with a different command.
+@value{GBDN} will reject the command if you try to mix watchpoints.
+Delete or disable unused watchpoint commands before setting new ones.
+
+@kindex rwatch
+@item rwatch @var{expr}
+Set a watchpoint that will break when watch @var{args} is read by the program.
+If you use both watchpoints, both must be set with the @code{rwatch}
+command.
+
+@kindex awatch
+@item awatch @var{expr}
+Set a watchpoint that will break when @var{args} is read and written into
+by the program. If you use both watchpoints, both must be set with the
+@code{awatch} command.
+
+@kindex info watchpoints
+@item info watchpoints
+This command prints a list of watchpoints and breakpoints; it is the
+same as @code{info break}.
+@end table
+
+@ifclear BARETARGET
+@quotation
+@cindex watchpoints and threads
+@cindex threads and watchpoints
+@emph{Warning:} in multi-thread programs, watchpoints have only limited
+usefulness. With the current watchpoint implementation, @value{GDBN}
+can only watch the value of an expression @emph{in a single thread}. If
+you are confident that the expression can only change due to the current
+thread's activity (and if you are also confident that no other thread
+can become current), then you can use watchpoints as usual. However,
+@value{GDBN} may not notice when a non-current thread's activity changes
+the expression.
+@end quotation
+@end ifclear
+
+@ifclear CONLY
+@node Exception Handling
+@subsection Breakpoints and exceptions
+@cindex exception handlers
+
+Some languages, such as @sc{gnu} C++, implement exception handling. You can
+use @value{GDBN} to examine what caused your program to raise an exception,
+and to list the exceptions your program is prepared to handle at a
+given point in time.
+
+@table @code
+@kindex catch
+@item catch @var{exceptions}
+You can set breakpoints at active exception handlers by using the
+@code{catch} command. @var{exceptions} is a list of names of exceptions
+to catch.
+@end table
+
+You can use @code{info catch} to list active exception handlers.
+@xref{Frame Info, ,Information about a frame}.
+
+There are currently some limitations to exception handling in @value{GDBN}:
+
+@itemize @bullet
+@item
+If you call a function interactively, @value{GDBN} normally returns
+control to you when the function has finished executing. If the call
+raises an exception, however, the call may bypass the mechanism that
+returns control to you and cause your program to simply continue
+running until it hits a breakpoint, catches a signal that @value{GDBN} is
+listening for, or exits.
+
+@item
+You cannot raise an exception interactively.
+
+@item
+You cannot install an exception handler interactively.
+@end itemize
+
+@cindex raise exceptions
+Sometimes @code{catch} is not the best way to debug exception handling:
+if you need to know exactly where an exception is raised, it is better to
+stop @emph{before} the exception handler is called, since that way you
+can see the stack before any unwinding takes place. If you set a
+breakpoint in an exception handler instead, it may not be easy to find
+out where the exception was raised.
+
+To stop just before an exception handler is called, you need some
+knowledge of the implementation. In the case of @sc{gnu} C++, exceptions are
+raised by calling a library function named @code{__raise_exception}
+which has the following ANSI C interface:
+
+@example
+ /* @var{addr} is where the exception identifier is stored.
+ ID is the exception identifier. */
+ void __raise_exception (void **@var{addr}, void *@var{id});
+@end example
+
+@noindent
+To make the debugger catch all exceptions before any stack
+unwinding takes place, set a breakpoint on @code{__raise_exception}
+(@pxref{Breakpoints, ,Breakpoints; watchpoints; and exceptions}).
+
+With a conditional breakpoint (@pxref{Conditions, ,Break conditions})
+that depends on the value of @var{id}, you can stop your program when
+a specific exception is raised. You can use multiple conditional
+breakpoints to stop your program when any of a number of exceptions are
+raised.
+@end ifclear
+
+@node Delete Breaks
+@subsection Deleting breakpoints
+
+@cindex clearing breakpoints, watchpoints
+@cindex deleting breakpoints, watchpoints
+It is often necessary to eliminate a breakpoint or watchpoint once it
+has done its job and you no longer want your program to stop there. This
+is called @dfn{deleting} the breakpoint. A breakpoint that has been
+deleted no longer exists; it is forgotten.
+
+With the @code{clear} command you can delete breakpoints according to
+where they are in your program. With the @code{delete} command you can
+delete individual breakpoints or watchpoints by specifying their
+breakpoint numbers.
+
+It is not necessary to delete a breakpoint to proceed past it. @value{GDBN}
+automatically ignores breakpoints on the first instruction to be executed
+when you continue execution without changing the execution address.
+
+@table @code
+@item clear
+@kindex clear
+Delete any breakpoints at the next instruction to be executed in the
+selected stack frame (@pxref{Selection, ,Selecting a frame}). When
+the innermost frame is selected, this is a good way to delete a
+breakpoint where your program just stopped.
+
+@item clear @var{function}
+@itemx clear @var{filename}:@var{function}
+Delete any breakpoints set at entry to the function @var{function}.
+
+@item clear @var{linenum}
+@itemx clear @var{filename}:@var{linenum}
+Delete any breakpoints set at or within the code of the specified line.
+
+@cindex delete breakpoints
+@kindex delete
+@kindex d
+@item delete @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+Delete the breakpoints or watchpoints of the numbers specified as
+arguments. If no argument is specified, delete all breakpoints (@value{GDBN}
+asks confirmation, unless you have @code{set confirm off}). You
+can abbreviate this command as @code{d}.
+@end table
+
+@node Disabling
+@subsection Disabling breakpoints
+
+@kindex disable breakpoints
+@kindex enable breakpoints
+Rather than deleting a breakpoint or watchpoint, you might prefer to
+@dfn{disable} it. This makes the breakpoint inoperative as if it had
+been deleted, but remembers the information on the breakpoint so that
+you can @dfn{enable} it again later.
+
+You disable and enable breakpoints and watchpoints with the
+@code{enable} and @code{disable} commands, optionally specifying one or
+more breakpoint numbers as arguments. Use @code{info break} or
+@code{info watch} to print a list of breakpoints or watchpoints if you
+do not know which numbers to use.
+
+A breakpoint or watchpoint can have any of four different states of
+enablement:
+
+@itemize @bullet
+@item
+Enabled. The breakpoint stops your program. A breakpoint set
+with the @code{break} command starts out in this state.
+@item
+Disabled. The breakpoint has no effect on your program.
+@item
+Enabled once. The breakpoint stops your program, but then becomes
+disabled. A breakpoint set with the @code{tbreak} command starts out in
+this state.
+@item
+Enabled for deletion. The breakpoint stops your program, but
+immediately after it does so it is deleted permanently.
+@end itemize
+
+You can use the following commands to enable or disable breakpoints and
+watchpoints:
+
+@table @code
+@kindex disable breakpoints
+@kindex disable
+@kindex dis
+@item disable @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+Disable the specified breakpoints---or all breakpoints, if none are
+listed. A disabled breakpoint has no effect but is not forgotten. All
+options such as ignore-counts, conditions and commands are remembered in
+case the breakpoint is enabled again later. You may abbreviate
+@code{disable} as @code{dis}.
+
+@kindex enable breakpoints
+@kindex enable
+@item enable @r{[}breakpoints@r{]} @r{[}@var{bnums}@dots{}@r{]}
+Enable the specified breakpoints (or all defined breakpoints). They
+become effective once again in stopping your program.
+
+@item enable @r{[}breakpoints@r{]} once @var{bnums}@dots{}
+Enable the specified breakpoints temporarily. @value{GDBN} disables any
+of these breakpoints immediately after stopping your program.
+
+@item enable @r{[}breakpoints@r{]} delete @var{bnums}@dots{}
+Enable the specified breakpoints to work once, then die. @value{GDBN}
+deletes any of these breakpoints as soon as your program stops there.
+@end table
+
+Except for a breakpoint set with @code{tbreak} (@pxref{Set Breaks,
+,Setting breakpoints}), breakpoints that you set are initially enabled;
+subsequently, they become disabled or enabled only when you use one of
+the commands above. (The command @code{until} can set and delete a
+breakpoint of its own, but it does not change the state of your other
+breakpoints; see @ref{Continuing and Stepping, ,Continuing and
+stepping}.)
+
+@node Conditions
+@subsection Break conditions
+@cindex conditional breakpoints
+@cindex breakpoint conditions
+
+@c FIXME what is scope of break condition expr? Context where wanted?
+@c in particular for a watchpoint?
+The simplest sort of breakpoint breaks every time your program reaches a
+specified place. You can also specify a @dfn{condition} for a
+breakpoint. A condition is just a Boolean expression in your
+programming language (@pxref{Expressions, ,Expressions}). A breakpoint with
+a condition evaluates the expression each time your program reaches it,
+and your program stops only if the condition is @emph{true}.
+
+This is the converse of using assertions for program validation; in that
+situation, you want to stop when the assertion is violated---that is,
+when the condition is false. In C, if you want to test an assertion expressed
+by the condition @var{assert}, you should set the condition
+@samp{! @var{assert}} on the appropriate breakpoint.
+
+Conditions are also accepted for watchpoints; you may not need them,
+since a watchpoint is inspecting the value of an expression anyhow---but
+it might be simpler, say, to just set a watchpoint on a variable name,
+and specify a condition that tests whether the new value is an interesting
+one.
+
+Break conditions can have side effects, and may even call functions in
+your program. This can be useful, for example, to activate functions
+that log program progress, or to use your own print functions to
+format special data structures. The effects are completely predictable
+unless there is another enabled breakpoint at the same address. (In
+that case, @value{GDBN} might see the other breakpoint first and stop your
+program without checking the condition of this one.) Note that
+breakpoint commands are usually more convenient and flexible for the
+purpose of performing side effects when a breakpoint is reached
+(@pxref{Break Commands, ,Breakpoint command lists}).
+
+Break conditions can be specified when a breakpoint is set, by using
+@samp{if} in the arguments to the @code{break} command. @xref{Set
+Breaks, ,Setting breakpoints}. They can also be changed at any time
+with the @code{condition} command. The @code{watch} command does not
+recognize the @code{if} keyword; @code{condition} is the only way to
+impose a further condition on a watchpoint.
+
+@table @code
+@kindex condition
+@item condition @var{bnum} @var{expression}
+Specify @var{expression} as the break condition for breakpoint or
+watchpoint number @var{bnum}. After you set a condition, breakpoint
+@var{bnum} stops your program only if the value of @var{expression} is
+true (nonzero, in C). When you use @code{condition}, @value{GDBN}
+checks @var{expression} immediately for syntactic correctness, and to
+determine whether symbols in it have referents in the context of your
+breakpoint.
+@c FIXME so what does GDB do if there is no referent? Moreover, what
+@c about watchpoints?
+@value{GDBN} does
+not actually evaluate @var{expression} at the time the @code{condition}
+command is given, however. @xref{Expressions, ,Expressions}.
+
+@item condition @var{bnum}
+Remove the condition from breakpoint number @var{bnum}. It becomes
+an ordinary unconditional breakpoint.
+@end table
+
+@cindex ignore count (of breakpoint)
+A special case of a breakpoint condition is to stop only when the
+breakpoint has been reached a certain number of times. This is so
+useful that there is a special way to do it, using the @dfn{ignore
+count} of the breakpoint. Every breakpoint has an ignore count, which
+is an integer. Most of the time, the ignore count is zero, and
+therefore has no effect. But if your program reaches a breakpoint whose
+ignore count is positive, then instead of stopping, it just decrements
+the ignore count by one and continues. As a result, if the ignore count
+value is @var{n}, the breakpoint does not stop the next @var{n} times
+your program reaches it.
+
+@table @code
+@kindex ignore
+@item ignore @var{bnum} @var{count}
+Set the ignore count of breakpoint number @var{bnum} to @var{count}.
+The next @var{count} times the breakpoint is reached, your program's
+execution does not stop; other than to decrement the ignore count, @value{GDBN}
+takes no action.
+
+To make the breakpoint stop the next time it is reached, specify
+a count of zero.
+
+When you use @code{continue} to resume execution of your program from a
+breakpoint, you can specify an ignore count directly as an argument to
+@code{continue}, rather than using @code{ignore}. @xref{Continuing and
+Stepping,,Continuing and stepping}.
+
+If a breakpoint has a positive ignore count and a condition, the
+condition is not checked. Once the ignore count reaches zero,
+@value{GDBN} resumes checking the condition.
+
+You could achieve the effect of the ignore count with a condition such
+as @w{@samp{$foo-- <= 0}} using a debugger convenience variable that
+is decremented each time. @xref{Convenience Vars, ,Convenience
+variables}.
+@end table
+
+@node Break Commands
+@subsection Breakpoint command lists
+
+@cindex breakpoint commands
+You can give any breakpoint (or watchpoint) a series of commands to
+execute when your program stops due to that breakpoint. For example, you
+might want to print the values of certain expressions, or enable other
+breakpoints.
+
+@table @code
+@kindex commands
+@kindex end
+@item commands @r{[}@var{bnum}@r{]}
+@itemx @dots{} @var{command-list} @dots{}
+@itemx end
+Specify a list of commands for breakpoint number @var{bnum}. The commands
+themselves appear on the following lines. Type a line containing just
+@code{end} to terminate the commands.
+
+To remove all commands from a breakpoint, type @code{commands} and
+follow it immediately with @code{end}; that is, give no commands.
+
+With no @var{bnum} argument, @code{commands} refers to the last
+breakpoint or watchpoint set (not to the breakpoint most recently
+encountered).
+@end table
+
+Pressing @key{RET} as a means of repeating the last @value{GDBN} command is
+disabled within a @var{command-list}.
+
+You can use breakpoint commands to start your program up again. Simply
+use the @code{continue} command, or @code{step}, or any other command
+that resumes execution.
+
+Any other commands in the command list, after a command that resumes
+execution, are ignored. This is because any time you resume execution
+(even with a simple @code{next} or @code{step}), you may encounter
+another breakpoint---which could have its own command list, leading to
+ambiguities about which list to execute.
+
+@kindex silent
+If the first command you specify in a command list is @code{silent}, the
+usual message about stopping at a breakpoint is not printed. This may
+be desirable for breakpoints that are to print a specific message and
+then continue. If none of the remaining commands print anything, you
+see no sign that the breakpoint was reached. @code{silent} is
+meaningful only at the beginning of a breakpoint command list.
+
+The commands @code{echo}, @code{output}, and @code{printf} allow you to
+print precisely controlled output, and are often useful in silent
+breakpoints. @xref{Output, ,Commands for controlled output}.
+
+For example, here is how you could use breakpoint commands to print the
+value of @code{x} at entry to @code{foo} whenever @code{x} is positive.
+
+@example
+break foo if x>0
+commands
+silent
+printf "x is %d\n",x
+cont
+end
+@end example
+
+One application for breakpoint commands is to compensate for one bug so
+you can test for another. Put a breakpoint just after the erroneous line
+of code, give it a condition to detect the case in which something
+erroneous has been done, and give it commands to assign correct values
+to any variables that need them. End with the @code{continue} command
+so that your program does not stop, and start with the @code{silent}
+command so that no output is produced. Here is an example:
+
+@example
+break 403
+commands
+silent
+set x = y + 4
+cont
+end
+@end example
+
+@ifclear CONLY
+@node Breakpoint Menus
+@subsection Breakpoint menus
+@cindex overloading
+@cindex symbol overloading
+
+Some programming languages (notably C++) permit a single function name
+to be defined several times, for application in different contexts.
+This is called @dfn{overloading}. When a function name is overloaded,
+@samp{break @var{function}} is not enough to tell @value{GDBN} where you want
+a breakpoint. If you realize this is a problem, you can use
+something like @samp{break @var{function}(@var{types})} to specify which
+particular version of the function you want. Otherwise, @value{GDBN} offers
+you a menu of numbered choices for different possible breakpoints, and
+waits for your selection with the prompt @samp{>}. The first two
+options are always @samp{[0] cancel} and @samp{[1] all}. Typing @kbd{1}
+sets a breakpoint at each definition of @var{function}, and typing
+@kbd{0} aborts the @code{break} command without setting any new
+breakpoints.
+
+For example, the following session excerpt shows an attempt to set a
+breakpoint at the overloaded symbol @code{String::after}.
+We choose three particular definitions of that function name:
+
+@c FIXME! This is likely to change to show arg type lists, at least
+@smallexample
+(@value{GDBP}) b String::after
+[0] cancel
+[1] all
+[2] file:String.cc; line number:867
+[3] file:String.cc; line number:860
+[4] file:String.cc; line number:875
+[5] file:String.cc; line number:853
+[6] file:String.cc; line number:846
+[7] file:String.cc; line number:735
+> 2 4 6
+Breakpoint 1 at 0xb26c: file String.cc, line 867.
+Breakpoint 2 at 0xb344: file String.cc, line 875.
+Breakpoint 3 at 0xafcc: file String.cc, line 846.
+Multiple breakpoints were set.
+Use the "delete" command to delete unwanted
+ breakpoints.
+(@value{GDBP})
+@end smallexample
+@end ifclear
+
+@c @ifclear BARETARGET
+@c @node Error in Breakpoints
+@c @subsection ``Cannot insert breakpoints''
+@c
+@c FIXME!! 14/6/95 Is there a real example of this? Let's use it.
+@c
+@c Under some operating systems, breakpoints cannot be used in a program if
+@c any other process is running that program. In this situation,
+@c attempting to run or continue a program with a breakpoint causes
+@c @value{GDBN} to stop the other process.
+@c
+@c When this happens, you have three ways to proceed:
+@c
+@c @enumerate
+@c @item
+@c Remove or disable the breakpoints, then continue.
+@c
+@c @item
+@c Suspend @value{GDBN}, and copy the file containing your program to a new
+@c name. Resume @value{GDBN} and use the @code{exec-file} command to specify
+@c that @value{GDBN} should run your program under that name.
+@c Then start your program again.
+@c
+@c @item
+@c Relink your program so that the text segment is nonsharable, using the
+@c linker option @samp{-N}. The operating system limitation may not apply
+@c to nonsharable executables.
+@c @end enumerate
+@c @end ifclear
+
+@node Continuing and Stepping
+@section Continuing and stepping
+
+@cindex stepping
+@cindex continuing
+@cindex resuming execution
+@dfn{Continuing} means resuming program execution until your program
+completes normally. In contrast, @dfn{stepping} means executing just
+one more ``step'' of your program, where ``step'' may mean either one
+line of source code, or one machine instruction (depending on what
+particular command you use). Either when continuing
+or when stepping, your program may stop even sooner, due to
+@ifset BARETARGET
+a breakpoint.
+@end ifset
+@ifclear BARETARGET
+a breakpoint or a signal. (If due to a signal, you may want to use
+@code{handle}, or use @samp{signal 0} to resume execution.
+@xref{Signals, ,Signals}.)
+@end ifclear
+
+@table @code
+@kindex continue
+@kindex c
+@kindex fg
+@item continue @r{[}@var{ignore-count}@r{]}
+@itemx c @r{[}@var{ignore-count}@r{]}
+@itemx fg @r{[}@var{ignore-count}@r{]}
+Resume program execution, at the address where your program last stopped;
+any breakpoints set at that address are bypassed. The optional argument
+@var{ignore-count} allows you to specify a further number of times to
+ignore a breakpoint at this location; its effect is like that of
+@code{ignore} (@pxref{Conditions, ,Break conditions}).
+
+The argument @var{ignore-count} is meaningful only when your program
+stopped due to a breakpoint. At other times, the argument to
+@code{continue} is ignored.
+
+The synonyms @code{c} and @code{fg} are provided purely for convenience,
+and have exactly the same behavior as @code{continue}.
+@end table
+
+To resume execution at a different place, you can use @code{return}
+(@pxref{Returning, ,Returning from a function}) to go back to the
+calling function; or @code{jump} (@pxref{Jumping, ,Continuing at a
+different address}) to go to an arbitrary location in your program.
+
+A typical technique for using stepping is to set a breakpoint
+@ifclear CONLY
+(@pxref{Breakpoints, ,Breakpoints; watchpoints; and exceptions})
+@end ifclear
+@ifset CONLY
+(@pxref{Breakpoints, ,Breakpoints and watchpoints})
+@end ifset
+at the
+beginning of the function or the section of your program where a
+problem is believed to lie, run your program until it stops at that
+breakpoint, and then step through the suspect area, examining the
+variables that are interesting, until you see the problem happen.
+
+@table @code
+@kindex step
+@kindex s
+@item step
+Continue running your program until control reaches a different source
+line, then stop it and return control to @value{GDBN}. This command is
+abbreviated @code{s}.
+
+@quotation
+@c "without debugging information" is imprecise; actually "without line
+@c numbers in the debugging information". (gcc -g1 has debugging info but
+@c not line numbers). But it seems complex to try to make that
+@c distinction here.
+@emph{Warning:} If you use the @code{step} command while control is
+within a function that was compiled without debugging information,
+execution proceeds until control reaches a function that does have
+debugging information. Likewise, it will not step into a function which
+is compiled without debugging information. To step through functions
+without debugging information, use the @code{stepi} command, described
+below.
+@end quotation
+
+The @code{step} command now only stops at the first instruction of a
+source line. This prevents the multiple stops that used to occur in
+switch statements, for loops, etc. @code{step} continues to stop if a
+function that has debugging information is called within the line.
+
+Also, the @code{step} command now only enters a subroutine if there is line
+number information for the subroutine. Otherwise it acts like the
+@code{next} command. This avoids problems when using @code{cc -gl}
+on MIPS machines. Previously, @code{step} entered subroutines if there
+was any debugging information about the routine.
+
+@item step @var{count}
+Continue running as in @code{step}, but do so @var{count} times. If a
+breakpoint is reached,
+@ifclear BARETARGET
+or a signal not related to stepping occurs before @var{count} steps,
+@end ifclear
+stepping stops right away.
+
+@kindex next
+@kindex n
+@item next @r{[}@var{count}@r{]}
+Continue to the next source line in the current (innermost) stack frame.
+This is similar to @code{step}, but function calls that appear within the line
+of code are executed without stopping. Execution stops when control
+reaches a different line of code at the original stack level that was
+executing when you gave the @code{next} command. This command is abbreviated
+@code{n}.
+
+An argument @var{count} is a repeat count, as for @code{step}.
+
+
+@c FIX ME!! Do we delete this, or is there a way it fits in with
+@c the following paragraph? --- Vctoria
+@c
+@c @code{next} within a function that lacks debugging information acts like
+@c @code{step}, but any function calls appearing within the code of the
+@c function are executed without stopping.
+
+The @code{next} command now only stops at the first instruction of a
+source line. This prevents the multiple stops that used to occur in
+swtch statements, for loops, etc.
+
+@kindex finish
+@item finish
+Continue running until just after function in the selected stack frame
+returns. Print the returned value (if any).
+
+Contrast this with the @code{return} command (@pxref{Returning,
+,Returning from a function}).
+
+@kindex until
+@itemx u
+@kindex u
+@item until
+Continue running until a source line past the current line, in the
+current stack frame, is reached. This command is used to avoid single
+stepping through a loop more than once. It is like the @code{next}
+command, except that when @code{until} encounters a jump, it
+automatically continues execution until the program counter is greater
+than the address of the jump.
+
+This means that when you reach the end of a loop after single stepping
+though it, @code{until} makes your program continue execution until it
+exits the loop. In contrast, a @code{next} command at the end of a loop
+simply steps back to the beginning of the loop, which forces you to step
+through the next iteration.
+
+@code{until} always stops your program if it attempts to exit the current
+stack frame.
+
+@code{until} may produce somewhat counterintuitive results if the order
+of machine code does not match the order of the source lines. For
+example, in the following excerpt from a debugging session, the @code{f}
+(@code{frame}) command shows that execution is stopped at line
+@code{206}; yet when we use @code{until}, we get to line @code{195}:
+
+@example
+(@value{GDBP}) f
+#0 main (argc=4, argv=0xf7fffae8) at m4.c:206
+206 expand_input();
+(@value{GDBP}) until
+195 for ( ; argc > 0; NEXTARG) @{
+@end example
+
+This happened because, for execution efficiency, the compiler had
+generated code for the loop closure test at the end, rather than the
+start, of the loop---even though the test in a C @code{for}-loop is
+written before the body of the loop. The @code{until} command appeared
+to step back to the beginning of the loop when it advanced to this
+expression; however, it has not really gone to an earlier
+statement---not in terms of the actual machine code.
+
+@code{until} with no argument works by means of single
+instruction stepping, and hence is slower than @code{until} with an
+argument.
+
+@item until @var{location}
+@itemx u @var{location}
+Continue running your program until either the specified location is
+reached, or the current stack frame returns. @var{location} is any of
+the forms of argument acceptable to @code{break} (@pxref{Set Breaks,
+,Setting breakpoints}). This form of the command uses breakpoints,
+and hence is quicker than @code{until} without an argument.
+
+@kindex stepi
+@kindex si
+@item stepi
+@itemx si
+Execute one machine instruction, then stop and return to the debugger.
+
+It is often useful to do @samp{display/i $pc} when stepping by machine
+instructions. This makes @value{GDBN} automatically display the next
+instruction to be executed, each time your program stops. @xref{Auto
+Display,, Automatic display}.
+
+An argument is a repeat count, as in @code{step}.
+
+@need 750
+@kindex nexti
+@kindex ni
+@item nexti
+@itemx ni
+Execute one machine instruction, but if it is a function call,
+proceed until the function returns.
+
+An argument is a repeat count, as in @code{next}.
+@end table
+
+@ifset POSIX
+@node Signals
+@section Signals
+@cindex signals
+
+A signal is an asynchronous event that can happen in a program. The
+operating system defines the possible kinds of signals, and gives each
+kind a name and a number. For example, in Unix @code{SIGINT} is the
+signal a program gets when you type an interrupt (often @kbd{C-c});
+@code{SIGSEGV} is the signal a program gets from referencing a place in
+memory far away from all the areas in use; @code{SIGALRM} occurs when
+the alarm clock timer goes off (which happens only if your program has
+requested an alarm).
+
+@cindex fatal signals
+Some signals, including @code{SIGALRM}, are a normal part of the
+functioning of your program. Others, such as @code{SIGSEGV}, indicate
+errors; these signals are @dfn{fatal} (kill your program immediately) if the
+program has not specified in advance some other way to handle the signal.
+@code{SIGINT} does not indicate an error in your program, but it is normally
+fatal so it can carry out the purpose of the interrupt: to kill the program.
+
+@value{GDBN} has the ability to detect any occurrence of a signal in your
+program. You can tell @value{GDBN} in advance what to do for each kind of
+signal.
+
+@cindex handling signals
+Normally, @value{GDBN} is set up to ignore non-erroneous signals like @code{SIGALRM}
+(so as not to interfere with their role in the functioning of your program)
+but to stop your program immediately whenever an error signal happens.
+You can change these settings with the @code{handle} command.
+
+@table @code
+@kindex info signals
+@item info signals
+Print a table of all the kinds of signals and how @value{GDBN} has been told to
+handle each one. You can use this to see the signal numbers of all
+the defined types of signals.
+
+@code{info handle} is the new alias for @code{info signals}.
+
+@kindex handle
+@item handle @var{signal} @var{keywords}@dots{}
+Change the way @value{GDBN} handles signal @var{signal}. @var{signal} can
+be the number of a signal or its name (with or without the @samp{SIG} at the
+beginning). The @var{keywords} say what change to make.
+@end table
+
+@c @group
+The keywords allowed by the @code{handle} command can be abbreviated.
+Their full names are:
+
+@table @code
+@item nostop
+@value{GDBN} should not stop your program when this signal happens. It may
+still print a message telling you that the signal has come in.
+
+@item stop
+@value{GDBN} should stop your program when this signal happens. This implies
+the @code{print} keyword as well.
+
+@item print
+@value{GDBN} should print a message when this signal happens.
+
+@item noprint
+@value{GDBN} should not mention the occurrence of the signal at all. This
+implies the @code{nostop} keyword as well.
+
+@item pass
+@value{GDBN} should allow your program to see this signal; your program
+can handle the signal, or else it may terminate if the signal is fatal
+and not handled.
+
+@item nopass
+@value{GDBN} should not allow your program to see this signal.
+@end table
+@c @end group
+
+When a signal stops your program, the signal is not visible until you
+continue. Your program sees the signal then, if @code{pass} is in
+effect for the signal in question @emph{at that time}. In other words,
+after @value{GDBN} reports a signal, you can use the @code{handle}
+command with @code{pass} or @code{nopass} to control whether your
+program sees that signal when you continue.
+
+You can also use the @code{signal} command to prevent your program from
+seeing a signal, or cause it to see a signal it normally would not see,
+or to give it any signal at any time. For example, if your program stopped
+due to some sort of memory reference error, you might store correct
+values into the erroneous variables and continue, hoping to see more
+execution; but your program would probably terminate immediately as
+a result of the fatal signal once it saw the signal. To prevent this,
+you can continue with @samp{signal 0}. @xref{Signaling, ,Giving your
+program a signal}.
+@end ifset
+
+@ifclear BARETARGET
+@node Thread Stops
+@section Stopping and starting multi-thread programs
+
+When your program has multiple threads (@pxref{Threads,, Debugging
+programs with multiple threads}), you can choose whether to set
+breakpoints on all threads, or on a particular thread.
+
+@table @code
+@cindex breakpoints and threads
+@cindex thread breakpoints
+@kindex break @dots{} thread @var{threadno}
+@item break @var{linespec} thread @var{threadno}
+@itemx break @var{linespec} thread @var{threadno} if @dots{}
+@var{linespec} specifies source lines; there are several ways of
+writing them, but the effect is always to specify some source line.
+
+Use the qualifier @samp{thread @var{threadno}} with a breakpoint command
+to specify that you only want @value{GDBN} to stop the program when a
+particular thread reaches this breakpoint. @var{threadno} is one of the
+numeric thread identifiers assigned by @value{GDBN}, shown in the first
+column of the @samp{info threads} display.
+
+If you do not specify @samp{thread @var{threadno}} when you set a
+breakpoint, the breakpoint applies to @emph{all} threads of your
+program.
+
+You can use the @code{thread} qualifier on conditional breakpoints as
+well; in this case, place @samp{thread @var{threadno}} before the
+breakpoint condition, like this:
+
+@smallexample
+(gdb) break frik.c:13 thread 28 if bartab > lim
+@end smallexample
+
+@end table
+
+@cindex stopped threads
+@cindex threads, stopped
+Whenever your program stops under @value{GDBN} for any reason,
+@emph{all} threads of execution stop, not just the current thread. This
+allows you to examine the overall state of the program, including
+switching between threads, without worrying that things may change
+underfoot.
+
+@cindex continuing threads
+@cindex threads, continuing
+Conversely, whenever you restart the program, @emph{all} threads start
+executing. @emph{This is true even when single-stepping} with commands
+like @code{step} or @code{next}.
+
+In particular, @value{GDBN} cannot single-step all threads in lockstep.
+Since thread scheduling is up to your debugging target's operating
+system (not controlled by @value{GDBN}), other threads may
+execute more than one statement while the current thread completes a
+single step. Moreover, in general other threads stop in the middle of a
+statement, rather than at a clean statement boundary, when the program
+stops.
+
+You might even find your program stopped in another thread after
+continuing or even single-stepping. This happens whenever some other
+thread runs into a breakpoint, a signal, or an exception before the
+first thread completes whatever you requested.
+@end ifclear
+
+@node Stack
+@chapter Examining the Stack
+
+When your program has stopped, the first thing you need to know is where it
+stopped and how it got there.
+
+@cindex call stack
+Each time your program performs a function call, information about the call
+is generated.
+That information includes the location of the call in your program,
+the arguments of the call,
+and the local variables of the function being called.
+The information is saved in a block of data called a @dfn{stack frame}.
+The stack frames are allocated in a region of memory called the @dfn{call
+stack}.
+
+When your program stops, the @value{GDBN} commands for examining the
+stack allow you to see all of this information.
+
+@cindex selected frame
+One of the stack frames is @dfn{selected} by @value{GDBN} and many
+@value{GDBN} commands refer implicitly to the selected frame. In
+particular, whenever you ask @value{GDBN} for the value of a variable in
+your program, the value is found in the selected frame. There are
+special @value{GDBN} commands to select whichever frame you are
+interested in. @xref{Selection, ,Selecting a frame}.
+
+When your program stops, @value{GDBN} automatically selects the
+currently executing frame and describes it briefly, similar to the
+@code{frame} command (@pxref{Frame Info, ,Information about a frame}).
+
+@menu
+* Frames:: Stack frames
+* Backtrace:: Backtraces
+* Selection:: Selecting a frame
+* Frame Info:: Information on a frame
+@ifset MIPS
+* MIPS Stack:: MIPS machines and the function stack
+@end ifset
+@end menu
+
+@node Frames
+@section Stack frames
+
+@cindex frame
+@cindex stack frame
+The call stack is divided up into contiguous pieces called @dfn{stack
+frames}, or @dfn{frames} for short; each frame is the data associated
+with one call to one function. The frame contains the arguments given
+to the function, the function's local variables, and the address at
+which the function is executing.
+
+@cindex initial frame
+@cindex outermost frame
+@cindex innermost frame
+When your program is started, the stack has only one frame, that of the
+function @code{main}. This is called the @dfn{initial} frame or the
+@dfn{outermost} frame. Each time a function is called, a new frame is
+made. Each time a function returns, the frame for that function invocation
+is eliminated. If a function is recursive, there can be many frames for
+the same function. The frame for the function in which execution is
+actually occurring is called the @dfn{innermost} frame. This is the most
+recently created of all the stack frames that still exist.
+
+@cindex frame pointer
+Inside your program, stack frames are identified by their addresses. A
+stack frame consists of many bytes, each of which has its own address; each
+kind of computer has a convention for choosing one byte whose
+address serves as the address of the frame. Usually this address is kept
+in a register called the @dfn{frame pointer register} while execution is
+going on in that frame.
+
+@cindex frame number
+@value{GDBN} assigns numbers to all existing stack frames, starting with
+zero for the innermost frame, one for the frame that called it,
+and so on upward. These numbers do not really exist in your program;
+they are assigned by @value{GDBN} to give you a way of designating stack
+frames in @value{GDBN} commands.
+
+@c below produces an acceptable overful hbox. --mew 13aug1993
+@cindex frameless execution
+Some compilers provide a way to compile functions so that they operate
+without stack frames. (For example, the @code{@value{GCC}} option
+@samp{-fomit-frame-pointer} generates functions without a frame.)
+This is occasionally done with heavily used library functions to save
+the frame setup time. @value{GDBN} has limited facilities for dealing
+with these function invocations. If the innermost function invocation
+has no stack frame, @value{GDBN} nevertheless regards it as though
+it had a separate frame, which is numbered zero as usual, allowing
+correct tracing of the function call chain. However, @value{GDBN} has
+no provision for frameless functions elsewhere in the stack.
+
+@table @code
+@kindex frame
+@item frame @var{args}
+The @code{frame} command allows you to move from one stack frame to another,
+and to print the stack frame you select. @var{args} may be either the
+address of the frame of the stack frame number. Without an argument,
+@code{frame} prints the current stack frame.
+
+@kindex select-frame
+@item select-frame
+The @code{select-frame} command allows you to move from one stack frame
+to another without printing the frame. This is the silent version of
+@code{frame}.
+@end table
+
+@node Backtrace
+@section Backtraces
+
+A backtrace is a summary of how your program got where it is. It shows one
+line per frame, for many frames, starting with the currently executing
+frame (frame zero), followed by its caller (frame one), and on up the
+stack.
+
+@table @code
+@kindex backtrace
+@kindex bt
+@item backtrace
+@itemx bt
+Print a backtrace of the entire stack: one line per frame for all
+frames in the stack.
+
+You can stop the backtrace at any time by typing the system interrupt
+character, normally @kbd{C-c}.
+
+@item backtrace @var{n}
+@itemx bt @var{n}
+Similar, but print only the innermost @var{n} frames.
+
+@item backtrace -@var{n}
+@itemx bt -@var{n}
+Similar, but print only the outermost @var{n} frames.
+@end table
+
+@kindex where
+@kindex info stack
+@kindex info s
+The names @code{where} and @code{info stack} (abbreviated @code{info s})
+are additional aliases for @code{backtrace}.
+
+Each line in the backtrace shows the frame number and the function name.
+The program counter value is also shown---unless you use @code{set
+print address off}. The backtrace also shows the source file name and
+line number, as well as the arguments to the function. The program
+counter value is omitted if it is at the beginning of the code for that
+line number.
+
+Here is an example of a backtrace. It was made with the command
+@samp{bt 3}, so it shows the innermost three frames.
+
+@smallexample
+@group
+#0 m4_traceon (obs=0x24eb0, argc=1, argv=0x2b8c8)
+ at builtin.c:993
+#1 0x6e38 in expand_macro (sym=0x2b600) at macro.c:242
+#2 0x6840 in expand_token (obs=0x0, t=177664, td=0xf7fffb08)
+ at macro.c:71
+(More stack frames follow...)
+@end group
+@end smallexample
+
+@noindent
+The display for frame zero does not begin with a program counter
+value, indicating that your program has stopped at the beginning of the
+code for line @code{993} of @code{builtin.c}.
+
+@node Selection
+@section Selecting a frame
+
+Most commands for examining the stack and other data in your program work on
+whichever stack frame is selected at the moment. Here are the commands for
+selecting a stack frame; all of them finish by printing a brief description
+of the stack frame just selected.
+
+@table @code
+@kindex frame
+@kindex f
+@item frame @var{n}
+@itemx f @var{n}
+Select frame number @var{n}. Recall that frame zero is the innermost
+(currently executing) frame, frame one is the frame that called the
+innermost one, and so on. The highest-numbered frame is the one for
+@code{main}.
+
+@item frame @var{addr}
+@itemx f @var{addr}
+Select the frame at address @var{addr}. This is useful mainly if the
+chaining of stack frames has been damaged by a bug, making it
+impossible for @value{GDBN} to assign numbers properly to all frames. In
+addition, this can be useful when your program has multiple stacks and
+switches between them.
+
+@ifclear H8EXCLUSIVE
+On the SPARC architecture, @code{frame} needs two addresses to
+select an arbitrary frame: a frame pointer and a stack pointer.
+
+On the MIPS and Alpha architecture, it needs two addresses: a stack
+pointer and a program counter.
+
+On the 29k architecture, it needs three addresses: a register stack
+pointer, a program counter, and a memory stack pointer.
+@c note to future updaters: this is conditioned on a flag
+@c SETUP_ARBITRARY_FRAME in the tm-*.h files. The above is up to date
+@c as of 27 Jan 1994.
+@end ifclear
+
+@kindex up
+@item up @var{n}
+Move @var{n} frames up the stack. For positive numbers @var{n}, this
+advances toward the outermost frame, to higher frame numbers, to frames
+that have existed longer. @var{n} defaults to one.
+
+@kindex down
+@kindex do
+@item down @var{n}
+Move @var{n} frames down the stack. For positive numbers @var{n}, this
+advances toward the innermost frame, to lower frame numbers, to frames
+that were created more recently. @var{n} defaults to one. You may
+abbreviate @code{down} as @code{do}.
+@end table
+
+All of these commands end by printing two lines of output describing the
+frame. The first line shows the frame number, the function name, the
+arguments, and the source file and line number of execution in that
+frame. The second line shows the text of that source line.
+
+@need 1000
+For example:
+
+@smallexample
+@group
+(@value{GDBP}) up
+#1 0x22f0 in main (argc=1, argv=0xf7fffbf4, env=0xf7fffbfc)
+ at env.c:10
+10 read_input_file (argv[i]);
+@end group
+@end smallexample
+
+After such a printout, the @code{list} command with no arguments
+prints ten lines centered on the point of execution in the frame.
+@xref{List, ,Printing source lines}.
+
+@table @code
+@kindex down-silently
+@kindex up-silently
+@item up-silently @var{n}
+@itemx down-silently @var{n}
+These two commands are variants of @code{up} and @code{down},
+respectively; they differ in that they do their work silently, without
+causing display of the new frame. They are intended primarily for use
+in @value{GDBN} command scripts, where the output might be unnecessary and
+distracting.
+@end table
+
+@node Frame Info
+@section Information about a frame
+
+There are several other commands to print information about the selected
+stack frame.
+
+@table @code
+@item frame
+@itemx f
+When used without any argument, this command does not change which
+frame is selected, but prints a brief description of the currently
+selected stack frame. It can be abbreviated @code{f}. With an
+argument, this command is used to select a stack frame.
+@xref{Selection, ,Selecting a frame}.
+
+@kindex info frame
+@kindex info f
+@item info frame
+@itemx info f
+This command prints a verbose description of the selected stack frame,
+including:
+
+@itemize @bullet
+@item
+the address of the frame
+@item
+the address of the next frame down (called by this frame)
+@item
+the address of the next frame up (caller of this frame)
+@item
+the language in which the source code corresponding to this frame is written
+@item
+the address of the frame's arguments
+@item
+the program counter saved in it (the address of execution in the caller frame)
+@item
+which registers were saved in the frame
+@end itemize
+
+@noindent The verbose description is useful when
+something has gone wrong that has made the stack format fail to fit
+the usual conventions.
+
+@item info frame @var{addr}
+@itemx info f @var{addr}
+Print a verbose description of the frame at address @var{addr}, without
+selecting that frame. The selected frame remains unchanged by this
+command. This requires the same kind of address (more than one for some
+architectures) that you specify in the @code{frame} command.
+@xref{Selection, ,Selecting a frame}.
+
+@kindex info args
+@item info args
+Print the arguments of the selected frame, each on a separate line.
+
+@item info locals
+@kindex info locals
+Print the local variables of the selected frame, each on a separate
+line. These are all variables (declared either static or automatic)
+accessible at the point of execution of the selected frame.
+
+@ifclear CONLY
+@kindex info catch
+@cindex catch exceptions
+@cindex exception handlers
+@item info catch
+Print a list of all the exception handlers that are active in the
+current stack frame at the current point of execution. To see other
+exception handlers, visit the associated frame (using the @code{up},
+@code{down}, or @code{frame} commands); then type @code{info catch}.
+@xref{Exception Handling, ,Breakpoints and exceptions}.
+@end ifclear
+@end table
+
+@ifset MIPS
+@node MIPS Stack
+@section MIPS machines and the function stack
+
+@cindex stack on MIPS
+@cindex MIPS stack
+MIPS based computers use an unusual stack frame, which sometimes
+requires @value{GDBN} to search backward in the object code to find the
+beginning of a function.
+
+@cindex response time, MIPS debugging
+To improve response time (especially for embedded applications, where
+@value{GDBN} may be restricted to a slow serial line for this search)
+you may want to limit the size of this search, using one of these
+commands:
+
+@table @code
+@cindex @code{heuristic-fence-post} (MIPS)
+@item set heuristic-fence-post @var{limit}
+Restrict @value{GDBN} to examining at most @var{limit} bytes in its search
+for the beginning of a function. A value of @var{0} (the default)
+means there is no limit. However, except for @var{0}, the larger the
+limit the more bytes @code{heuristic-fence-post} must search and
+therefore the longer it takes to run.
+
+@item show heuristic-fence-post
+Display the current limit.
+@end table
+
+@noindent
+These commands are available @emph{only} when @value{GDBN} is configured
+for debugging programs on MIPS processors.
+@end ifset
+
+@node Source
+@chapter Examining Source Files
+
+@value{GDBN} can print parts of your program's source, since the debugging
+information recorded in the program tells @value{GDBN} what source files were
+used to build it. When your program stops, @value{GDBN} spontaneously prints
+the line where it stopped. Likewise, when you select a stack frame
+(@pxref{Selection, ,Selecting a frame}), @value{GDBN} prints the line where
+execution in that frame has stopped. You can print other portions of
+source files by explicit command.
+
+@ifclear DOSHOST
+If you use @value{GDBN} through its @sc{gnu} Emacs interface, you may prefer
+to use
+Emacs facilities to view source; @pxref{Emacs, ,Using @value{GDBN} under @sc{gnu} Emacs}.
+@end ifclear
+
+@menu
+* List:: Printing source lines
+@ifclear DOSHOST
+* Search:: Searching source files
+@end ifclear
+
+* Source Path:: Specifying source directories
+* Machine Code:: Source and machine code
+@end menu
+
+@node List
+@section Printing source lines
+
+@kindex list
+@kindex l
+To print lines from a source file, use the @code{list} command
+(abbreviated @code{l}). By default, ten lines are printed.
+There are several ways to specify what part of the file you want to print.
+
+Here are the forms of the @code{list} command most commonly used:
+
+@table @code
+@item list @var{linenum}
+Print lines centered around line number @var{linenum} in the
+current source file.
+
+@item list @var{function}
+Print lines centered around the beginning of function
+@var{function}.
+
+@item list
+Print more lines. If the last lines printed were printed with a
+@code{list} command, this prints lines following the last lines
+printed; however, if the last line printed was a solitary line printed
+as part of displaying a stack frame (@pxref{Stack, ,Examining the
+Stack}), this prints lines centered around that line.
+
+@item list -
+Print lines just before the lines last printed.
+@end table
+
+By default, @value{GDBN} prints ten source lines with any of these forms of
+the @code{list} command. You can change this using @code{set listsize}:
+
+@table @code
+@kindex set listsize
+@item set listsize @var{count}
+Make the @code{list} command display @var{count} source lines (unless
+the @code{list} argument explicitly specifies some other number).
+
+@kindex show listsize
+@item show listsize
+Display the number of lines that @code{list} prints.
+@end table
+
+Repeating a @code{list} command with @key{RET} discards the argument,
+so it is equivalent to typing just @code{list}. This is more useful
+than listing the same lines again. An exception is made for an
+argument of @samp{-}; that argument is preserved in repetition so that
+each repetition moves up in the source file.
+
+@cindex linespec
+In general, the @code{list} command expects you to supply zero, one or two
+@dfn{linespecs}. Linespecs specify source lines; there are several ways
+of writing them but the effect is always to specify some source line.
+Here is a complete description of the possible arguments for @code{list}:
+
+@table @code
+@item list @var{linespec}
+Print lines centered around the line specified by @var{linespec}.
+
+@item list @var{first},@var{last}
+Print lines from @var{first} to @var{last}. Both arguments are
+linespecs.
+
+@item list ,@var{last}
+Print lines ending with @var{last}.
+
+@item list @var{first},
+Print lines starting with @var{first}.
+
+@item list +
+Print lines just after the lines last printed.
+
+@item list -
+Print lines just before the lines last printed.
+
+@item list
+As described in the preceding table.
+@end table
+
+Here are the ways of specifying a single source line---all the
+kinds of linespec.
+
+@table @code
+@item @var{number}
+Specifies line @var{number} of the current source file.
+When a @code{list} command has two linespecs, this refers to
+the same source file as the first linespec.
+
+@item +@var{offset}
+Specifies the line @var{offset} lines after the last line printed.
+When used as the second linespec in a @code{list} command that has
+two, this specifies the line @var{offset} lines down from the
+first linespec.
+
+@item -@var{offset}
+Specifies the line @var{offset} lines before the last line printed.
+
+@item @var{filename}:@var{number}
+Specifies line @var{number} in the source file @var{filename}.
+
+@item @var{function}
+Specifies the line that begins the body of the function @var{function}.
+For example: in C, this is the line with the open brace.
+
+@item @var{filename}:@var{function}
+Specifies the line of the open-brace that begins the body of the
+function @var{function} in the file @var{filename}. You only need the
+file name with a function name to avoid ambiguity when there are
+identically named functions in different source files.
+
+@item *@var{address}
+Specifies the line containing the program address @var{address}.
+@var{address} may be any expression.
+@end table
+
+@ifclear DOSHOST
+@node Search
+@section Searching source files
+@cindex searching
+@kindex reverse-search
+
+There are two commands for searching through the current source file for a
+regular expression.
+
+@table @code
+@kindex search
+@kindex forward-search
+@item forward-search @var{regexp}
+@itemx search @var{regexp}
+The command @samp{forward-search @var{regexp}} checks each line,
+starting with the one following the last line listed, for a match for
+@var{regexp}. It lists the line that is found. You can use the
+synonym @samp{search @var{regexp}} or abbreviate the command name as
+@code{fo}.
+
+@item reverse-search @var{regexp}
+The command @samp{reverse-search @var{regexp}} checks each line, starting
+with the one before the last line listed and going backward, for a match
+for @var{regexp}. It lists the line that is found. You can abbreviate
+this command as @code{rev}.
+@end table
+@end ifclear
+
+@node Source Path
+@section Specifying source directories
+
+@cindex source path
+@cindex directories for source files
+Executable programs sometimes do not record the directories of the source
+files from which they were compiled, just the names. Even when they do,
+the directories could be moved between the compilation and your debugging
+session. @value{GDBN} has a list of directories to search for source files;
+this is called the @dfn{source path}. Each time @value{GDBN} wants a source file,
+it tries all the directories in the list, in the order they are present
+in the list, until it finds a file with the desired name. Note that
+the executable search path is @emph{not} used for this purpose. Neither is
+the current working directory, unless it happens to be in the source
+path.
+
+If @value{GDBN} cannot find a source file in the source path, and the
+object program records a directory, @value{GDBN} tries that directory
+too. If the source path is empty, and there is no record of the
+compilation directory, @value{GDBN} looks in the current directory as a
+last resort.
+
+Whenever you reset or rearrange the source path, @value{GDBN} clears out
+any information it has cached about where source files are found and where
+each line is in the file.
+
+@kindex directory
+@kindex dir
+When you start @value{GDBN}, its source path is empty.
+To add other directories, use the @code{directory} command.
+
+@table @code
+@item directory @var{dirname} @dots{}
+@item dir @var{dirname} @dots{}
+Add directory @var{dirname} to the front of the source path. Several
+directory names may be given to this command, separated by @samp{:} or
+whitespace. You may specify a directory that is already in the source
+path; this moves it forward, so @value{GDBN} searches it sooner.
+
+@kindex cdir
+@kindex cwd
+@kindex $cdir
+@kindex $cwd
+@cindex compilation directory
+@cindex current directory
+@cindex working directory
+@cindex directory, current
+@cindex directory, compilation
+You can use the string @samp{$cdir} to refer to the compilation
+directory (if one is recorded), and @samp{$cwd} to refer to the current
+working directory. @samp{$cwd} is not the same as @samp{.}---the former
+tracks the current working directory as it changes during your @value{GDBN}
+session, while the latter is immediately expanded to the current
+directory at the time you add an entry to the source path.
+
+@item directory
+Reset the source path to empty again. This requires confirmation.
+
+@c RET-repeat for @code{directory} is explicitly disabled, but since
+@c repeating it would be a no-op we do not say that. (thanks to RMS)
+
+@item show directories
+@kindex show directories
+Print the source path: show which directories it contains.
+@end table
+
+If your source path is cluttered with directories that are no longer of
+interest, @value{GDBN} may sometimes cause confusion by finding the wrong
+versions of source. You can correct the situation as follows:
+
+@enumerate
+@item
+Use @code{directory} with no argument to reset the source path to empty.
+
+@item
+Use @code{directory} with suitable arguments to reinstall the
+directories you want in the source path. You can add all the
+directories in one command.
+@end enumerate
+
+@node Machine Code
+@section Source and machine code
+
+You can use the command @code{info line} to map source lines to program
+addresses (and vice versa), and the command @code{disassemble} to display
+a range of addresses as machine instructions. When run under @sc{gnu} Emacs
+mode, the @code{info line} command now causes the arrow to point to the
+line specified. Also, @code{info line} prints addresses in symbolic form as
+well as hex.
+
+@table @code
+@kindex info line
+@item info line @var{linespec}
+Print the starting and ending addresses of the compiled code for
+source line @var{linespec}. You can specify source lines in any of
+the ways understood by the @code{list} command (@pxref{List, ,Printing
+source lines}).
+@end table
+
+For example, we can use @code{info line} to discover the location of
+the object code for the first line of function
+@code{m4_changequote}:
+
+@smallexample
+(@value{GDBP}) info line m4_changecom
+Line 895 of "builtin.c" starts at pc 0x634c and ends at 0x6350.
+@end smallexample
+
+@noindent
+We can also inquire (using @code{*@var{addr}} as the form for
+@var{linespec}) what source line covers a particular address:
+@smallexample
+(@value{GDBP}) info line *0x63ff
+Line 926 of "builtin.c" starts at pc 0x63e4 and ends at 0x6404.
+@end smallexample
+
+@cindex @code{$_} and @code{info line}
+After @code{info line}, the default address for the @code{x} command
+is changed to the starting address of the line, so that @samp{x/i} is
+sufficient to begin examining the machine code (@pxref{Memory,
+,Examining memory}). Also, this address is saved as the value of the
+convenience variable @code{$_} (@pxref{Convenience Vars, ,Convenience
+variables}).
+
+@table @code
+@kindex disassemble
+@cindex assembly instructions
+@cindex instructions, assembly
+@cindex machine instructions
+@cindex listing machine instructions
+@item disassemble
+This specialized command dumps a range of memory as machine
+instructions. The default memory range is the function surrounding the
+program counter of the selected frame. A single argument to this
+command is a program counter value; @value{GDBN} dumps the function
+surrounding this value. Two arguments specify a range of addresses
+(first inclusive, second exclusive) to dump.
+@end table
+
+@ifclear H8EXCLUSIVE
+We can use @code{disassemble} to inspect the object code
+range shown in the last @code{info line} example (the example
+shows SPARC machine instructions):
+
+
+@smallexample
+(@value{GDBP}) disas 0x63e4 0x6404
+Dump of assembler code from 0x63e4 to 0x6404:
+0x63e4 <builtin_init+5340>: ble 0x63f8 <builtin_init+5360>
+0x63e8 <builtin_init+5344>: sethi %hi(0x4c00), %o0
+0x63ec <builtin_init+5348>: ld [%i1+4], %o0
+0x63f0 <builtin_init+5352>: b 0x63fc <builtin_init+5364>
+0x63f4 <builtin_init+5356>: ld [%o0+4], %o0
+0x63f8 <builtin_init+5360>: or %o0, 0x1a4, %o0
+0x63fc <builtin_init+5364>: call 0x9288 <path_search>
+0x6400 <builtin_init+5368>: nop
+End of assembler dump.
+@end smallexample
+@end ifclear
+
+@ifset H8EXCLUSIVE
+For example, here is the beginning of the output for the
+disassembly of a function @code{fact}:
+
+
+@smallexample
+(@value{GDBP}) disas fact
+Dump of assembler code for function fact:
+to 0x808c:
+0x802c <fact>: 6d f2 mov.w r2,@@-r7
+0x802e <fact+2>: 6d f3 mov.w r3,@@-r7
+0x8030 <fact+4>: 6d f6 mov.w r6,@@-r7
+0x8032 <fact+6>: 0d 76 mov.w r7,r6
+0x8034 <fact+8>: 6f 70 00 08 mov.w @@(0x8,r7),r0
+0x8038 <fact+12> 19 11 sub.w r1,r1
+ .
+ .
+ .
+@end smallexample
+@end ifset
+
+@node Data
+@chapter Examining Data
+
+@cindex printing data
+@cindex examining data
+@kindex print
+@kindex inspect
+@c "inspect" is not quite a synonym if you are using Epoch, which we do not
+@c document because it is nonstandard... Under Epoch it displays in a
+@c different window or something like that.
+The usual way to examine data in your program is with the @code{print}
+command (abbreviated @code{p}), or its synonym @code{inspect}.
+@ifclear CONLY
+It evaluates and prints the value of an expression of the language your
+program is written in (@pxref{Languages, ,Using @value{GDBN} with Different
+Languages}).
+@end ifclear
+
+@table @code
+@item print @var{exp}
+@itemx print /@var{f} @var{exp}
+@var{exp} is an expression (in the source language). By default the
+value of @var{exp} is printed in a format appropriate to its data type;
+you can choose a different format by specifying @samp{/@var{f}}, where
+@var{f} is a letter specifying the format; @pxref{Output Formats,,Output
+formats}.
+
+@item print
+@itemx print /@var{f}
+If you omit @var{exp}, @value{GDBN} displays the last value again (from the
+@dfn{value history}; @pxref{Value History, ,Value history}). This allows you to
+conveniently inspect the same value in an alternative format.
+@end table
+
+A more low-level way of examining data is with the @code{x} command.
+It examines data in memory at a specified address and prints it in a
+specified format. @xref{Memory, ,Examining memory}.
+
+If you are interested in information about types, or about how the fields
+of a struct
+@ifclear CONLY
+or class
+@end ifclear
+are declared, use the @code{ptype @var{exp}}
+command rather than @code{print}. @xref{Symbols, ,Examining the Symbol Table}.
+
+@menu
+* Expressions:: Expressions
+* Variables:: Program variables
+* Arrays:: Artificial arrays
+* Output Formats:: Output formats
+* Memory:: Examining memory
+* Auto Display:: Automatic display
+* Print Settings:: Print settings
+* Value History:: Value history
+* Convenience Vars:: Convenience variables
+* Registers:: Registers
+@ifclear HAVE-FLOAT
+* Floating Point Hardware:: Floating point hardware
+@end ifclear
+@end menu
+
+@node Expressions
+@section Expressions
+
+@cindex expressions
+@code{print} and many other @value{GDBN} commands accept an expression and
+compute its value. Any kind of constant, variable or operator defined
+by the programming language you are using is valid in an expression in
+@value{GDBN}. This includes conditional expressions, function calls, casts
+and string constants. It unfortunately does not include symbols defined
+by preprocessor @code{#define} commands.
+
+@value{GDBN} now supports array constants in expressions input by
+the user. The syntax is @var{@{element, element@dots{}@}}. For example,
+you can now use the command @code{print @{1, 2, 3@}} to build up an array in
+memory that is malloc'd in the target program.
+
+@ifclear CONLY
+Because C is so widespread, most of the expressions shown in examples in
+this manual are in C. @xref{Languages, , Using @value{GDBN} with Different
+Languages}, for information on how to use expressions in other
+languages.
+
+In this section, we discuss operators that you can use in @value{GDBN}
+expressions regardless of your programming language.
+
+Casts are supported in all languages, not just in C, because it is so
+useful to cast a number into a pointer in order to examine a structure
+at that address in memory.
+@c FIXME: casts supported---Mod2 true?
+@end ifclear
+
+@value{GDBN} supports these operators, in addition to those common
+to programming languages:
+
+@table @code
+@item @@
+@samp{@@} is a binary operator for treating parts of memory as arrays.
+@xref{Arrays, ,Artificial arrays}, for more information.
+
+@item ::
+@samp{::} allows you to specify a variable in terms of the file or
+function where it is defined. @xref{Variables, ,Program variables}.
+
+@cindex @{@var{type}@}
+@cindex type casting memory
+@cindex memory, viewing as typed object
+@cindex casts, to view memory
+@item @{@var{type}@} @var{addr}
+Refers to an object of type @var{type} stored at address @var{addr} in
+memory. @var{addr} may be any expression whose value is an integer or
+pointer (but parentheses are required around binary operators, just as in
+a cast). This construct is allowed regardless of what kind of data is
+normally supposed to reside at @var{addr}.
+@end table
+
+@node Variables
+@section Program variables
+
+The most common kind of expression to use is the name of a variable
+in your program.
+
+Variables in expressions are understood in the selected stack frame
+(@pxref{Selection, ,Selecting a frame}); they must be either:
+
+@itemize @bullet
+@item
+global (or static)
+@end itemize
+
+@noindent or
+
+@itemize @bullet
+@item
+visible according to the scope rules of the
+programming language from the point of execution in that frame
+@end itemize
+
+@noindent This means that in the function
+
+@example
+foo (a)
+ int a;
+@{
+ bar (a);
+ @{
+ int b = test ();
+ bar (b);
+ @}
+@}
+@end example
+
+@noindent
+you can examine and use the variable @code{a} whenever your program is
+executing within the function @code{foo}, but you can only use or
+examine the variable @code{b} while your program is executing inside
+the block where @code{b} is declared.
+
+@cindex variable name conflict
+There is an exception: you can refer to a variable or function whose
+scope is a single source file even if the current execution point is not
+in this file. But it is possible to have more than one such variable or
+function with the same name (in different source files). If that
+happens, referring to that name has unpredictable effects. If you wish,
+you can specify a static variable in a particular function or file,
+using the colon-colon notation:
+
+@cindex colon-colon
+@iftex
+@c info cannot cope with a :: index entry, but why deprive hard copy readers?
+@kindex ::
+@end iftex
+@example
+@var{file}::@var{variable}
+@var{function}::@var{variable}
+@end example
+
+@noindent
+Here @var{file} or @var{function} is the name of the context for the
+static @var{variable}. In the case of file names, you can use quotes to
+make sure @value{GDBN} parses the file name as a single word---for example,
+to print a global value of @code{x} defined in @file{f2.c}:
+
+@example
+(@value{GDBP}) p 'f2.c'::x
+@end example
+
+@ifclear CONLY
+@cindex C++ scope resolution
+This use of @samp{::} is very rarely in conflict with the very similar
+use of the same notation in C++. @value{GDBN} also supports use of the C++
+scope resolution operator in @value{GDBN} expressions.
+@c FIXME: Um, so what happens in one of those rare cases where it's in
+@c conflict?? --mew
+@end ifclear
+
+@cindex wrong values
+@cindex variable values, wrong
+@quotation
+@emph{Warning:} Occasionally, a local variable may appear to have the
+wrong value at certain points in a function---just after entry to a new
+scope, and just before exit.
+@end quotation
+You may see this problem when you are stepping by machine instructions.
+This is because, on most machines, it takes more than one instruction to
+set up a stack frame (including local variable definitions); if you are
+stepping by machine instructions, variables may appear to have the wrong
+values until the stack frame is completely built. On exit, it usually
+also takes more than one machine instruction to destroy a stack frame;
+after you begin stepping through that group of instructions, local
+variable definitions may be gone.
+
+@node Arrays
+@section Artificial arrays
+
+@cindex artificial array
+@kindex @@
+It is often useful to print out several successive objects of the
+same type in memory; a section of an array, or an array of
+dynamically determined size for which only a pointer exists in the
+program.
+
+You can do this by referring to a contiguous span of memory as an
+@dfn{artificial array}, using the binary operator @samp{@@}. The left
+operand of @samp{@@} should be the first element of the desired array
+and be an individual object. The right operand should be the desired length
+of the array. The result is an array value whose elements are all of
+the type of the left argument. The first element is actually the left
+argument; the second element comes from bytes of memory immediately
+following those that hold the first element, and so on. Here is an
+example. If a program says
+
+@example
+int *array = (int *) malloc (len * sizeof (int));
+@end example
+
+@noindent
+you can print the contents of @code{array} with
+
+@example
+p *array@@len
+@end example
+
+The left operand of @samp{@@} must reside in memory. Array values made
+with @samp{@@} in this way behave just like other arrays in terms of
+subscripting, and are coerced to pointers when used in expressions.
+Artificial arrays most often appear in expressions via the value history
+(@pxref{Value History, ,Value history}), after printing one out.
+
+Another way to create an artificial array is to use a cast.
+This re-interprets a value as if it were an array.
+The value need not be in memory:
+@example
+(@value{GDBP}) p/x (short[2])0x12345678
+$1 = @{0x1234, 0x5678@}
+@end example
+
+As a convenience, if you leave the array length out (as in
+@samp{(@var{type})[])@var{value}}) gdb calculates the size to fill
+the value (as @samp{sizeof(@var{value})/sizeof(@var{type})}:
+@example
+(@value{GDBP}) p/x (short[])0x12345678
+$2 = @{0x1234, 0x5678@}
+@end example
+
+Sometimes the artificial array mechanism is not quite enough; in
+moderately complex data structures, the elements of interest may not
+actually be adjacent---for example, if you are interested in the values
+of pointers in an array. One useful work-around in this situation is
+to use a convenience variable (@pxref{Convenience Vars, ,Convenience
+variables}) as a counter in an expression that prints the first
+interesting value, and then repeat that expression via @key{RET}. For
+instance, suppose you have an array @code{dtab} of pointers to
+structures, and you are interested in the values of a field @code{fv}
+in each structure. Here is an example of what you might type:
+
+@example
+set $i = 0
+p dtab[$i++]->fv
+@key{RET}
+@key{RET}
+@dots{}
+@end example
+
+@node Output Formats
+@section Output formats
+
+@cindex formatted output
+@cindex output formats
+By default, @value{GDBN} prints a value according to its data type. Sometimes
+this is not what you want. For example, you might want to print a number
+in hex, or a pointer in decimal. Or you might want to view data in memory
+at a certain address as a character string or as an instruction. To do
+these things, specify an @dfn{output format} when you print a value.
+
+The simplest use of output formats is to say how to print a value
+already computed. This is done by starting the arguments of the
+@code{print} command with a slash and a format letter. The format
+letters supported are:
+
+@table @code
+@item x
+Regard the bits of the value as an integer, and print the integer in
+hexadecimal.
+
+@item d
+Print as integer in signed decimal.
+
+@item u
+Print as integer in unsigned decimal.
+
+@item o
+Print as integer in octal.
+
+@item t
+Print as integer in binary. The letter @samp{t} stands for ``two''.
+@footnote{@samp{b} cannot be used because these format letters are also
+used with the @code{x} command, where @samp{b} stands for ``byte'';
+@pxref{Memory,,Examining memory}.}
+
+@item a
+@cindex unknown address, locating
+Print as an address, both absolute in hexadecimal and as an offset from
+the nearest preceding symbol. You can use this format used to discover
+where (in what function) an unknown address is located:
+
+@example
+(@value{GDBP}) p/a 0x54320
+$3 = 0x54320 <_initialize_vx+396>
+@end example
+
+@item c
+Regard as an integer and print it as a character constant.
+
+@item f
+Regard the bits of the value as a floating point number and print
+using typical floating point syntax.
+@end table
+
+For example, to print the program counter in hex (@pxref{Registers}), type
+
+@example
+p/x $pc
+@end example
+
+@noindent
+Note that no space is required before the slash; this is because command
+names in @value{GDBN} cannot contain a slash.
+
+To reprint the last value in the value history with a different format,
+you can use the @code{print} command with just a format and no
+expression. For example, @samp{p/x} reprints the last value in hex.
+
+@node Memory
+@section Examining memory
+
+You can use the command @code{x} (for ``examine'') to examine memory in
+any of several formats, independently of your program's data types.
+
+@cindex examining memory
+@table @code
+@kindex x
+@item x/@var{nfu} @var{addr}
+@itemx x @var{addr}
+@itemx x
+Use the @code{x} command to examine memory.
+@end table
+
+@var{n}, @var{f}, and @var{u} are all optional parameters that specify how
+much memory to display and how to format it; @var{addr} is an
+expression giving the address where you want to start displaying memory.
+If you use defaults for @var{nfu}, you need not type the slash @samp{/}.
+Several commands set convenient defaults for @var{addr}.
+
+@table @r
+@item @var{n}, the repeat count
+The repeat count is a decimal integer; the default is 1. It specifies
+how much memory (counting by units @var{u}) to display.
+@c This really is **decimal**; unaffected by 'set radix' as of GDB
+@c 4.1.2.
+
+@item @var{f}, the display format
+The display format is one of the formats used by @code{print},
+@samp{s} (null-terminated string), or @samp{i} (machine instruction).
+The default is @samp{x} (hexadecimal) initially.
+The default changes each time you use either @code{x} or @code{print}.
+
+@item @var{u}, the unit size
+The unit size is any of
+
+@table @code
+@item b
+Bytes.
+@item h
+Halfwords (two bytes).
+@item w
+Words (four bytes). This is the initial default.
+@item g
+Giant words (eight bytes).
+@end table
+
+Each time you specify a unit size with @code{x}, that size becomes the
+default unit the next time you use @code{x}. (For the @samp{s} and
+@samp{i} formats, the unit size is ignored and is normally not written.)
+
+@item @var{addr}, starting display address
+@var{addr} is the address where you want @value{GDBN} to begin displaying
+memory. The expression need not have a pointer value (though it may);
+it is always interpreted as an integer address of a byte of memory.
+@xref{Expressions, ,Expressions}, for more information on expressions. The default for
+@var{addr} is usually just after the last address examined---but several
+other commands also set the default address: @code{info breakpoints} (to
+the address of the last breakpoint listed), @code{info line} (to the
+starting address of a line), and @code{print} (if you use it to display
+a value from memory).
+@end table
+
+For example, @samp{x/3uh 0x54320} is a request to display three halfwords
+(@code{h}) of memory, formatted as unsigned decimal integers (@samp{u}),
+starting at address @code{0x54320}. @samp{x/4xw $sp} prints the four
+words (@samp{w}) of memory above the stack pointer (here, @samp{$sp};
+@pxref{Registers}) in hexadecimal (@samp{x}).
+
+Since the letters indicating unit sizes are all distinct from the
+letters specifying output formats, you do not have to remember whether
+unit size or format comes first; either order works. The output
+specifications @samp{4xw} and @samp{4wx} mean exactly the same thing.
+(However, the count @var{n} must come first; @samp{wx4} does not work.)
+
+Even though the unit size @var{u} is ignored for the formats @samp{s}
+and @samp{i}, you might still want to use a count @var{n}; for example,
+@samp{3i} specifies that you want to see three machine instructions,
+including any operands. The command @code{disassemble} gives an
+alternative way of inspecting machine instructions; @pxref{Machine
+Code,,Source and machine code}.
+
+All the defaults for the arguments to @code{x} are designed to make it
+easy to continue scanning memory with minimal specifications each time
+you use @code{x}. For example, after you have inspected three machine
+instructions with @samp{x/3i @var{addr}}, you can inspect the next seven
+with just @samp{x/7}. If you use @key{RET} to repeat the @code{x} command,
+the repeat count @var{n} is used again; the other arguments default as
+for successive uses of @code{x}.
+
+@cindex @code{$_}, @code{$__}, and value history
+The addresses and contents printed by the @code{x} command are not saved
+in the value history because there is often too much of them and they
+would get in the way. Instead, @value{GDBN} makes these values available for
+subsequent use in expressions as values of the convenience variables
+@code{$_} and @code{$__}. After an @code{x} command, the last address
+examined is available for use in expressions in the convenience variable
+@code{$_}. The contents of that address, as examined, are available in
+the convenience variable @code{$__}.
+
+If the @code{x} command has a repeat count, the address and contents saved
+are from the last memory unit printed; this is not the same as the last
+address printed if several units were printed on the last line of output.
+
+@node Auto Display
+@section Automatic display
+@cindex automatic display
+@cindex display of expressions
+
+If you find that you want to print the value of an expression frequently
+(to see how it changes), you might want to add it to the @dfn{automatic
+display list} so that @value{GDBN} prints its value each time your program stops.
+Each expression added to the list is given a number to identify it;
+to remove an expression from the list, you specify that number.
+The automatic display looks like this:
+
+@example
+2: foo = 38
+3: bar[5] = (struct hack *) 0x3804
+@end example
+
+@noindent
+This display shows item numbers, expressions and their current values. As with
+displays you request manually using @code{x} or @code{print}, you can
+specify the output format you prefer; in fact, @code{display} decides
+whether to use @code{print} or @code{x} depending on how elaborate your
+format specification is---it uses @code{x} if you specify a unit size,
+or one of the two formats (@samp{i} and @samp{s}) that are only
+supported by @code{x}; otherwise it uses @code{print}.
+
+@table @code
+@kindex display
+@item display @var{exp}
+Add the expression @var{exp} to the list of expressions to display
+each time your program stops. @xref{Expressions, ,Expressions}.
+
+@code{display} does not repeat if you press @key{RET} again after using it.
+
+@item display/@var{fmt} @var{exp}
+For @var{fmt} specifying only a display format and not a size or
+count, add the expression @var{exp} to the auto-display list but
+arrange to display it each time in the specified format @var{fmt}.
+@xref{Output Formats,,Output formats}.
+
+@item display/@var{fmt} @var{addr}
+For @var{fmt} @samp{i} or @samp{s}, or including a unit-size or a
+number of units, add the expression @var{addr} as a memory address to
+be examined each time your program stops. Examining means in effect
+doing @samp{x/@var{fmt} @var{addr}}. @xref{Memory, ,Examining memory}.
+@end table
+
+For example, @samp{display/i $pc} can be helpful, to see the machine
+instruction about to be executed each time execution stops (@samp{$pc}
+is a common name for the program counter; @pxref{Registers}).
+
+@table @code
+@kindex delete display
+@kindex undisplay
+@item undisplay @var{dnums}@dots{}
+@itemx delete display @var{dnums}@dots{}
+Remove item numbers @var{dnums} from the list of expressions to display.
+
+@code{undisplay} does not repeat if you press @key{RET} after using it.
+(Otherwise you would just get the error @samp{No display number @dots{}}.)
+
+@kindex disable display
+@item disable display @var{dnums}@dots{}
+Disable the display of item numbers @var{dnums}. A disabled display
+item is not printed automatically, but is not forgotten. It may be
+enabled again later.
+
+@kindex enable display
+@item enable display @var{dnums}@dots{}
+Enable display of item numbers @var{dnums}. It becomes effective once
+again in auto display of its expression, until you specify otherwise.
+
+@item display
+Display the current values of the expressions on the list, just as is
+done when your program stops.
+
+@kindex info display
+@item info display
+Print the list of expressions previously set up to display
+automatically, each one with its item number, but without showing the
+values. This includes disabled expressions, which are marked as such.
+It also includes expressions which would not be displayed right now
+because they refer to automatic variables not currently available.
+@end table
+
+If a display expression refers to local variables, then it does not make
+sense outside the lexical context for which it was set up. Such an
+expression is disabled when execution enters a context where one of its
+variables is not defined. For example, if you give the command
+@code{display last_char} while inside a function with an argument
+@code{last_char}, @value{GDBN} displays this argument while your program
+continues to stop inside that function. When it stops elsewhere---where
+there is no variable @code{last_char}---the display is disabled
+automatically. The next time your program stops where @code{last_char}
+is meaningful, you can enable the display expression once again.
+
+@node Print Settings
+@section Print settings
+
+@cindex format options
+@cindex print settings
+@value{GDBN} provides the following ways to control how arrays, structures,
+and symbols are printed.
+
+@noindent
+These settings are useful for debugging programs in any language:
+
+@table @code
+@kindex set print address
+@item set print address
+@itemx set print address on
+@value{GDBN} prints memory addresses showing the location of stack
+traces, structure values, pointer values, breakpoints, and so forth,
+even when it also displays the contents of those addresses. The default
+is @code{on}. For example, this is what a stack frame display looks like with
+@code{set print address on}:
+
+@smallexample
+@group
+(@value{GDBP}) f
+#0 set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>")
+ at input.c:530
+530 if (lquote != def_lquote)
+@end group
+@end smallexample
+
+@item set print address off
+Do not print addresses when displaying their contents. For example,
+this is the same stack frame displayed with @code{set print address off}:
+
+@smallexample
+@group
+(@value{GDBP}) set print addr off
+(@value{GDBP}) f
+#0 set_quotes (lq="<<", rq=">>") at input.c:530
+530 if (lquote != def_lquote)
+@end group
+@end smallexample
+
+You can use @samp{set print address off} to eliminate all machine
+dependent displays from the @value{GDBN} interface. For example, with
+@code{print address off}, you should get the same text for backtraces on
+all machines---whether or not they involve pointer arguments.
+
+@kindex show print address
+@item show print address
+Show whether or not addresses are to be printed.
+@end table
+
+When @value{GDBN} prints a symbolic address, it normally prints the
+closest earlier symbol plus an offset. If that symbol does not uniquely
+identify the address (for example, it is a name whose scope is a single
+source file), you may need to clarify. One way to do this is with
+@code{info line}, for example @samp{info line *0x4537}. Alternately,
+you can set @value{GDBN} to print the source file and line number when
+it prints a symbolic address:
+
+@table @code
+@kindex set print symbol-filename
+@item set print symbol-filename on
+Tell @value{GDBN} to print the source file name and line number of a
+symbol in the symbolic form of an address.
+
+@item set print symbol-filename off
+Do not print source file name and line number of a symbol. This is the
+default.
+
+@kindex show print symbol-filename
+@item show print symbol-filename
+Show whether or not @value{GDBN} will print the source file name and
+line number of a symbol in the symbolic form of an address.
+@end table
+
+Another situation where it is helpful to show symbol filenames and line
+numbers is when disassembling code; @value{GDBN} shows you the line
+number and source file that corresponds to each instruction.
+
+Also, you may wish to see the symbolic form only if the address being
+printed is reasonably close to the closest earlier symbol:
+
+@table @code
+@kindex set print max-symbolic-offset
+@item set print max-symbolic-offset @var{max-offset}
+Tell @value{GDBN} to only display the symbolic form of an address if the
+offset between the closest earlier symbol and the address is less than
+@var{max-offset}. The default is 0, which tells @value{GDBN}
+to always print the symbolic form of an address if any symbol precedes it.
+
+@kindex show print max-symbolic-offset
+@item show print max-symbolic-offset
+Ask how large the maximum offset is that @value{GDBN} prints in a
+symbolic address.
+@end table
+
+@cindex wild pointer, interpreting
+@cindex pointer, finding referent
+If you have a pointer and you are not sure where it points, try
+@samp{set print symbol-filename on}. Then you can determine the name
+and source file location of the variable where it points, using
+@samp{p/a @var{pointer}}. This interprets the address in symbolic form.
+For example, here @value{GDBN} shows that a variable @code{ptt} points
+at another variable @code{t}, defined in @file{hi2.c}:
+
+@example
+(@value{GDBP}) set print symbol-filename on
+(@value{GDBP}) p/a ptt
+$4 = 0xe008 <t in hi2.c>
+@end example
+
+@quotation
+@emph{Warning:} For pointers that point to a local variable, @samp{p/a}
+does not show the symbol name and filename of the referent, even with
+the appropriate @code{set print} options turned on.
+@end quotation
+
+Other settings control how different kinds of objects are printed:
+
+@table @code
+@kindex set print array
+@item set print array
+@itemx set print array on
+Pretty print arrays. This format is more convenient to read,
+but uses more space. The default is off.
+
+@item set print array off
+Return to compressed format for arrays.
+
+@kindex show print array
+@item show print array
+Show whether compressed or pretty format is selected for displaying
+arrays.
+
+@kindex set print elements
+@item set print elements @var{number-of-elements}
+Set a limit on how many elements of an array @value{GDBN} will print.
+If @value{GDBN} is printing a large array, it stops printing after it has
+printed the number of elements set by the @code{set print elements} command.
+This limit also applies to the display of strings.
+Setting @var{number-of-elements} to zero means that the printing is unlimited.
+
+@kindex show print elements
+@item show print elements
+Display the number of elements of a large array that @value{GDBN} will print.
+If the number is 0, then the printing is unlimited.
+
+@kindex set print null-stop
+@item set print null-stop
+Cause @value{GDBN} to stop printing the characters of an array when the first
+@sc{NULL} is encountered. This is useful when large arrays actually
+contain only short strings.
+
+@kindex set print pretty
+@item set print pretty on
+Cause @value{GDBN} to print structures in an indented format with one member
+per line, like this:
+
+@smallexample
+@group
+$1 = @{
+ next = 0x0,
+ flags = @{
+ sweet = 1,
+ sour = 1
+ @},
+ meat = 0x54 "Pork"
+@}
+@end group
+@end smallexample
+
+@item set print pretty off
+Cause @value{GDBN} to print structures in a compact format, like this:
+
+@smallexample
+@group
+$1 = @{next = 0x0, flags = @{sweet = 1, sour = 1@}, \
+meat = 0x54 "Pork"@}
+@end group
+@end smallexample
+
+@noindent
+This is the default format.
+
+@kindex show print pretty
+@item show print pretty
+Show which format @value{GDBN} is using to print structures.
+
+@kindex set print sevenbit-strings
+@item set print sevenbit-strings on
+Print using only seven-bit characters; if this option is set,
+@value{GDBN} displays any eight-bit characters (in strings or
+character values) using the notation @code{\}@var{nnn}. This setting is
+best if you are working in English (@sc{ascii}) and you use the
+high-order bit of characters as a marker or ``meta'' bit.
+
+@item set print sevenbit-strings off
+Print full eight-bit characters. This allows the use of more
+international character sets, and is the default.
+
+@kindex show print sevenbit-strings
+@item show print sevenbit-strings
+Show whether or not @value{GDBN} is printing only seven-bit characters.
+
+@kindex set print union
+@item set print union on
+Tell @value{GDBN} to print unions which are contained in structures. This
+is the default setting.
+
+@item set print union off
+Tell @value{GDBN} not to print unions which are contained in structures.
+
+@kindex show print union
+@item show print union
+Ask @value{GDBN} whether or not it will print unions which are contained in
+structures.
+
+For example, given the declarations
+
+@smallexample
+typedef enum @{Tree, Bug@} Species;
+typedef enum @{Big_tree, Acorn, Seedling@} Tree_forms;
+typedef enum @{Caterpillar, Cocoon, Butterfly@}
+ Bug_forms;
+
+struct thing @{
+ Species it;
+ union @{
+ Tree_forms tree;
+ Bug_forms bug;
+ @} form;
+@};
+
+struct thing foo = @{Tree, @{Acorn@}@};
+@end smallexample
+
+@noindent
+with @code{set print union on} in effect @samp{p foo} would print
+
+@smallexample
+$1 = @{it = Tree, form = @{tree = Acorn, bug = Cocoon@}@}
+@end smallexample
+
+@noindent
+and with @code{set print union off} in effect it would print
+
+@smallexample
+$1 = @{it = Tree, form = @{...@}@}
+@end smallexample
+@end table
+
+@ifclear CONLY
+@need 1000
+@noindent
+These settings are of interest when debugging C++ programs:
+
+@table @code
+@cindex demangling
+@kindex set print demangle
+@item set print demangle
+@itemx set print demangle on
+Print C++ names in their source form rather than in the encoded
+(``mangled'') form passed to the assembler and linker for type-safe
+linkage. The default is @samp{on}.
+
+@kindex show print demangle
+@item show print demangle
+Show whether C++ names are printed in mangled or demangled form.
+
+@kindex set print asm-demangle
+@item set print asm-demangle
+@itemx set print asm-demangle on
+Print C++ names in their source form rather than their mangled form, even
+in assembler code printouts such as instruction disassemblies.
+The default is off.
+
+@kindex show print asm-demangle
+@item show print asm-demangle
+Show whether C++ names in assembly listings are printed in mangled
+or demangled form.
+
+@kindex set demangle-style
+@cindex C++ symbol decoding style
+@cindex symbol decoding style, C++
+@item set demangle-style @var{style}
+Choose among several encoding schemes used by different compilers to
+represent C++ names. The choices for @var{style} are currently:
+
+@table @code
+@item auto
+Allow @value{GDBN} to choose a decoding style by inspecting your program.
+
+@item gnu
+Decode based on the @sc{gnu} C++ compiler (@code{g++}) encoding algorithm.
+This is the default.
+
+@item lucid
+Decode based on the Lucid C++ compiler (@code{lcc}) encoding algorithm.
+
+@item arm
+Decode using the algorithm in the @cite{C++ Annotated Reference Manual}.
+@strong{Warning:} this setting alone is not sufficient to allow
+debugging @code{cfront}-generated executables. @value{GDBN} would
+require further enhancement to permit that.
+
+@item foo
+Show the list of formats.
+@end table
+
+@kindex show demangle-style
+@item show demangle-style
+Display the encoding style currently in use for decoding C++ symbols.
+
+@kindex set print object
+@item set print object
+@itemx set print object on
+When displaying a pointer to an object, identify the @emph{actual}
+(derived) type of the object rather than the @emph{declared} type, using
+the virtual function table.
+
+@item set print object off
+Display only the declared type of objects, without reference to the
+virtual function table. This is the default setting.
+
+@kindex show print object
+@item show print object
+Show whether actual, or declared, object types are displayed.
+
+@kindex set print static-members
+@item set print static-members
+@itemx set print static-members on
+Print static members when displaying a C++ object. The default is on.
+
+@item set print static-members off
+Do not print static members when displaying a C++ object.
+
+@kindex show print static-members
+@item show print static-members
+Show whether C++ static members are printed, or not.
+
+@kindex set print vtbl
+@item set print vtbl
+@itemx set print vtbl on
+Pretty print C++ virtual function tables. The default is off.
+
+@item set print vtbl off
+Do not pretty print C++ virtual function tables.
+
+@kindex show print vtbl
+@item show print vtbl
+Show whether C++ virtual function tables are pretty printed, or not.
+@end table
+@end ifclear
+
+@node Value History
+@section Value history
+
+@cindex value history
+Values printed by the @code{print} command are saved in the @value{GDBN}
+@dfn{value history}. This allows you to refer to them in other expressions.
+Values are kept until the symbol table is re-read or discarded
+(for example with the @code{file} or @code{symbol-file} commands).
+When the symbol table changes, the value history is discarded,
+since the values may contain pointers back to the types defined in the
+symbol table.
+
+@cindex @code{$}
+@cindex @code{$$}
+@cindex history number
+The values printed are given @dfn{history numbers} by which you can
+refer to them. These are successive integers starting with one.
+@code{print} shows you the history number assigned to a value by
+printing @samp{$@var{num} = } before the value; here @var{num} is the
+history number.
+
+To refer to any previous value, use @samp{$} followed by the value's
+history number. The way @code{print} labels its output is designed to
+remind you of this. Just @code{$} refers to the most recent value in
+the history, and @code{$$} refers to the value before that.
+@code{$$@var{n}} refers to the @var{n}th value from the end; @code{$$2}
+is the value just prior to @code{$$}, @code{$$1} is equivalent to
+@code{$$}, and @code{$$0} is equivalent to @code{$}.
+
+For example, suppose you have just printed a pointer to a structure and
+want to see the contents of the structure. It suffices to type
+
+@example
+p *$
+@end example
+
+If you have a chain of structures where the component @code{next} points
+to the next one, you can print the contents of the next one with this:
+
+@example
+p *$.next
+@end example
+
+@noindent
+You can print successive links in the chain by repeating this
+command---which you can do by just typing @key{RET}.
+
+Note that the history records values, not expressions. If the value of
+@code{x} is 4 and you type these commands:
+
+@example
+print x
+set x=5
+@end example
+
+@noindent
+then the value recorded in the value history by the @code{print} command
+remains 4 even though the value of @code{x} has changed.
+
+@table @code
+@kindex show values
+@item show values
+Print the last ten values in the value history, with their item numbers.
+This is like @samp{p@ $$9} repeated ten times, except that @code{show
+values} does not change the history.
+
+@item show values @var{n}
+Print ten history values centered on history item number @var{n}.
+
+@item show values +
+Print ten history values just after the values last printed. If no more
+values are available, @code{show values +} produces no display.
+@end table
+
+Pressing @key{RET} to repeat @code{show values @var{n}} has exactly the
+same effect as @samp{show values +}.
+
+@node Convenience Vars
+@section Convenience variables
+
+@cindex convenience variables
+@value{GDBN} provides @dfn{convenience variables} that you can use within
+@value{GDBN} to hold on to a value and refer to it later. These variables
+exist entirely within @value{GDBN}; they are not part of your program, and
+setting a convenience variable has no direct effect on further execution
+of your program. That is why you can use them freely.
+
+Convenience variables are prefixed with @samp{$}. Any name preceded by
+@samp{$} can be used for a convenience variable, unless it is one of
+the predefined machine-specific register names (@pxref{Registers}).
+(Value history references, in contrast, are @emph{numbers} preceded
+by @samp{$}. @xref{Value History, ,Value history}.)
+
+You can save a value in a convenience variable with an assignment
+expression, just as you would set a variable in your program.
+For example:
+
+@example
+set $foo = *object_ptr
+@end example
+
+@noindent
+would save in @code{$foo} the value contained in the object pointed to by
+@code{object_ptr}.
+
+Using a convenience variable for the first time creates it, but its
+value is @code{void} until you assign a new value. You can alter the
+value with another assignment at any time.
+
+Convenience variables have no fixed types. You can assign a convenience
+variable any type of value, including structures and arrays, even if
+that variable already has a value of a different type. The convenience
+variable, when used as an expression, has the type of its current value.
+
+@table @code
+@kindex show convenience
+@item show convenience
+Print a list of convenience variables used so far, and their values.
+Abbreviated @code{show con}.
+@end table
+
+One of the ways to use a convenience variable is as a counter to be
+incremented or a pointer to be advanced. For example, to print
+a field from successive elements of an array of structures:
+
+@example
+set $i = 0
+print bar[$i++]->contents
+@end example
+
+@noindent Repeat that command by typing @key{RET}.
+
+Some convenience variables are created automatically by @value{GDBN} and given
+values likely to be useful.
+
+@table @code
+@kindex $_
+@item $_
+The variable @code{$_} is automatically set by the @code{x} command to
+the last address examined (@pxref{Memory, ,Examining memory}). Other
+commands which provide a default address for @code{x} to examine also
+set @code{$_} to that address; these commands include @code{info line}
+and @code{info breakpoint}. The type of @code{$_} is @code{void *}
+except when set by the @code{x} command, in which case it is a pointer
+to the type of @code{$__}.
+
+@kindex $__
+@item $__
+The variable @code{$__} is automatically set by the @code{x} command
+to the value found in the last address examined. Its type is chosen
+to match the format in which the data was printed.
+
+@item $_exitcode
+@kindex $_exitcode
+The variable @code{$_exitcode} is automatically set to the exit code when
+the program being debugged terminates.
+@end table
+
+@node Registers
+@section Registers
+
+@cindex registers
+You can refer to machine register contents, in expressions, as variables
+with names starting with @samp{$}. The names of registers are different
+for each machine; use @code{info registers} to see the names used on
+your machine.
+
+@table @code
+@kindex info registers
+@item info registers
+Print the names and values of all registers except floating-point
+registers (in the selected stack frame).
+
+@kindex info all-registers
+@cindex floating point registers
+@item info all-registers
+Print the names and values of all registers, including floating-point
+registers.
+
+@item info registers @var{regname} @dots{}
+Print the @dfn{relativized} value of each specified register @var{regname}.
+As discussed in detail below, register values are normally relative to
+the selected stack frame. @var{regname} may be any register name valid on
+the machine you are using, with or without the initial @samp{$}.
+@end table
+
+@value{GDBN} has four ``standard'' register names that are available (in
+expressions) on most machines---whenever they do not conflict with an
+architecture's canonical mnemonics for registers. The register names
+@code{$pc} and @code{$sp} are used for the program counter register and
+the stack pointer. @code{$fp} is used for a register that contains a
+pointer to the current stack frame, and @code{$ps} is used for a
+register that contains the processor status. For example,
+you could print the program counter in hex with
+
+@example
+p/x $pc
+@end example
+
+@noindent
+or print the instruction to be executed next with
+
+@example
+x/i $pc
+@end example
+
+@noindent
+or add four to the stack pointer@footnote{This is a way of removing
+one word from the stack, on machines where stacks grow downward in
+memory (most machines, nowadays). This assumes that the innermost
+stack frame is selected; setting @code{$sp} is not allowed when other
+stack frames are selected. To pop entire frames off the stack,
+regardless of machine architecture, use @code{return};
+@pxref{Returning, ,Returning from a function}.} with
+
+@example
+set $sp += 4
+@end example
+
+Whenever possible, these four standard register names are available on
+your machine even though the machine has different canonical mnemonics,
+so long as there is no conflict. The @code{info registers} command
+shows the canonical names. For example, on the SPARC, @code{info
+registers} displays the processor status register as @code{$psr} but you
+can also refer to it as @code{$ps}.
+
+@value{GDBN} always considers the contents of an ordinary register as an
+integer when the register is examined in this way. Some machines have
+special registers which can hold nothing but floating point; these
+registers are considered to have floating point values. There is no way
+to refer to the contents of an ordinary register as floating point value
+(although you can @emph{print} it as a floating point value with
+@samp{print/f $@var{regname}}).
+
+Some registers have distinct ``raw'' and ``virtual'' data formats. This
+means that the data format in which the register contents are saved by
+the operating system is not the same one that your program normally
+sees. For example, the registers of the 68881 floating point
+coprocessor are always saved in ``extended'' (raw) format, but all C
+programs expect to work with ``double'' (virtual) format. In such
+cases, @value{GDBN} normally works with the virtual format only (the format
+that makes sense for your program), but the @code{info registers} command
+prints the data in both formats.
+
+Normally, register values are relative to the selected stack frame
+(@pxref{Selection, ,Selecting a frame}). This means that you get the
+value that the register would contain if all stack frames farther in
+were exited and their saved registers restored. In order to see the
+true contents of hardware registers, you must select the innermost
+frame (with @samp{frame 0}).
+
+However, @value{GDBN} must deduce where registers are saved, from the machine
+code generated by your compiler. If some registers are not saved, or if
+@value{GDBN} is unable to locate the saved registers, the selected stack
+frame makes no difference.
+
+@ifset AMD29K
+@table @code
+@kindex set rstack_high_address
+@cindex AMD 29K register stack
+@cindex register stack, AMD29K
+@item set rstack_high_address @var{address}
+On AMD 29000 family processors, registers are saved in a separate
+``register stack''. There is no way for @value{GDBN} to determine the extent
+of this stack. Normally, @value{GDBN} just assumes that the stack is ``large
+enough''. This may result in @value{GDBN} referencing memory locations that
+do not exist. If necessary, you can get around this problem by
+specifying the ending address of the register stack with the @code{set
+rstack_high_address} command. The argument should be an address, which
+you probably want to precede with @samp{0x} to specify in
+hexadecimal.
+
+@kindex show rstack_high_address
+@item show rstack_high_address
+Display the current limit of the register stack, on AMD 29000 family
+processors.
+@end table
+@end ifset
+
+@ifclear HAVE-FLOAT
+@node Floating Point Hardware
+@section Floating point hardware
+@cindex floating point
+
+Depending on the configuration, @value{GDBN} may be able to give
+you more information about the status of the floating point hardware.
+
+@table @code
+@kindex info float
+@item info float
+Display hardware-dependent information about the floating
+point unit. The exact contents and layout vary depending on the
+floating point chip. Currently, @samp{info float} is supported on
+the ARM and x86 machines.
+@end table
+@end ifclear
+
+@ifclear CONLY
+@node Languages
+@chapter Using @value{GDBN} with Different Languages
+@cindex languages
+
+@ifset MOD2
+Although programming languages generally have common aspects, they are
+rarely expressed in the same manner. For instance, in ANSI C,
+dereferencing a pointer @code{p} is accomplished by @code{*p}, but in
+Modula-2, it is accomplished by @code{p^}. Values can also be
+represented (and displayed) differently. Hex numbers in C appear as
+@samp{0x1ae}, while in Modula-2 they appear as @samp{1AEH}.
+@end ifset
+
+@cindex working language
+Language-specific information is built into @value{GDBN} for some languages,
+allowing you to express operations like the above in your program's
+native language, and allowing @value{GDBN} to output values in a manner
+consistent with the syntax of your program's native language. The
+language you use to build expressions is called the @dfn{working
+language}.
+
+@menu
+* Setting:: Switching between source languages
+* Show:: Displaying the language
+@ifset MOD2
+* Checks:: Type and range checks
+@end ifset
+
+* Support:: Supported languages
+@end menu
+
+@node Setting
+@section Switching between source languages
+
+There are two ways to control the working language---either have @value{GDBN}
+set it automatically, or select it manually yourself. You can use the
+@code{set language} command for either purpose. On startup, @value{GDBN}
+defaults to setting the language automatically. The working language is
+used to determine how expressions you type are interpreted, how values
+are printed, etc.
+
+In addition to the working language, every source file that
+@value{GDBN} knows about has its own working language. For some object
+file formats, the compiler might indicate which language a particular
+source file is in. However, most of the time @value{GDBN} infers the
+language from the name of the file. The language of a source file
+controls whether C++ names are demangled---this way @code{backtrace} can
+show each frame appropriately for its own language. There is no way to
+set the language of a source file from within @value{GDBN}.
+
+This is most commonly a problem when you use a program, such
+as @code{cfront} or @code{f2c}, that generates C but is written in
+another language. In that case, make the
+program use @code{#line} directives in its C output; that way
+@value{GDBN} will know the correct language of the source code of the original
+program, and will display that source code, not the generated C code.
+
+@menu
+* Filenames:: Filename extensions and languages.
+* Manually:: Setting the working language manually
+* Automatically:: Having @value{GDBN} infer the source language
+@end menu
+
+@node Filenames
+@subsection List of filename extensions and languages
+
+If a source file name ends in one of the following extensions, then
+@value{GDBN} infers that its language is the one indicated.
+
+@table @file
+@ifset MOD2
+@item .mod
+Modula-2 source file
+@end ifset
+
+@item .c
+C source file
+
+@item .C
+@itemx .cc
+@itemx .cxx
+@itemx .cpp
+@itemx .cp
+@itemx .c++
+C++ source file
+
+@item .ch
+@itemx .c186
+@itemx .c286
+CHILL source file.
+
+@item .s
+@itemx .S
+Assembler source file. This actually behaves almost like C, but
+@value{GDBN} does not skip over function prologues when stepping.
+@end table
+
+@node Manually
+@subsection Setting the working language
+
+If you allow @value{GDBN} to set the language automatically,
+expressions are interpreted the same way in your debugging session and
+your program.
+
+@kindex set language
+If you wish, you may set the language manually. To do this, issue the
+command @samp{set language @var{lang}}, where @var{lang} is the name of
+a language, such as
+@ifclear MOD2
+@code{c}.
+@end ifclear
+@ifset MOD2
+@code{c} or @code{modula-2}.
+@end ifset
+For a list of the supported languages, type @samp{set language}.
+
+@ifset MOD2
+Setting the language manually prevents @value{GDBN} from updating the working
+language automatically. This can lead to confusion if you try
+to debug a program when the working language is not the same as the
+source language, when an expression is acceptable to both
+languages---but means different things. For instance, if the current
+source file were written in C, and @value{GDBN} was parsing Modula-2, a
+command such as:
+
+@example
+print a = b + c
+@end example
+
+@noindent
+might not have the effect you intended. In C, this means to add
+@code{b} and @code{c} and place the result in @code{a}. The result
+printed would be the value of @code{a}. In Modula-2, this means to compare
+@code{a} to the result of @code{b+c}, yielding a @code{BOOLEAN} value.
+@end ifset
+
+@node Automatically
+@subsection Having @value{GDBN} infer the source language
+
+To have @value{GDBN} set the working language automatically, use
+@samp{set language local} or @samp{set language auto}. @value{GDBN}
+then infers the working language. That is, when your program stops in a
+frame (usually by encountering a breakpoint), @value{GDBN} sets the
+working language to the language recorded for the function in that
+frame. If the language for a frame is unknown (that is, if the function
+or block corresponding to the frame was defined in a source file that
+does not have a recognized extension), the current working language is
+not changed, and @value{GDBN} issues a warning.
+
+This may not seem necessary for most programs, which are written
+entirely in one source language. However, program modules and libraries
+written in one source language can be used by a main program written in
+a different source language. Using @samp{set language auto} in this
+case frees you from having to set the working language manually.
+
+@node Show
+@section Displaying the language
+
+The following commands help you find out which language is the
+working language, and also what language source files were written in.
+
+@kindex show language
+@kindex info frame
+@kindex info source
+@table @code
+@item show language
+Display the current working language. This is the
+language you can use with commands such as @code{print} to
+build and compute expressions that may involve variables in your program.
+
+@item info frame
+Display the source language for this frame. This language becomes the
+working language if you use an identifier from this frame.
+@xref{Frame Info, ,Information about a frame}, to identify the other
+information listed here.
+
+@item info source
+Display the source language of this source file.
+@xref{Symbols, ,Examining the Symbol Table}, to identify the other
+information listed here.
+@end table
+
+@ifset MOD2
+@node Checks
+@section Type and range checking
+
+@quotation
+@emph{Warning:} In this release, the @value{GDBN} commands for type and range
+checking are included, but they do not yet have any effect. This
+section documents the intended facilities.
+@end quotation
+@c FIXME remove warning when type/range code added
+
+Some languages are designed to guard you against making seemingly common
+errors through a series of compile- and run-time checks. These include
+checking the type of arguments to functions and operators, and making
+sure mathematical overflows are caught at run time. Checks such as
+these help to ensure a program's correctness once it has been compiled
+by eliminating type mismatches, and providing active checks for range
+errors when your program is running.
+
+@value{GDBN} can check for conditions like the above if you wish.
+Although @value{GDBN} does not check the statements in your program, it
+can check expressions entered directly into @value{GDBN} for evaluation via
+the @code{print} command, for example. As with the working language,
+@value{GDBN} can also decide whether or not to check automatically based on
+your program's source language. @xref{Support, ,Supported languages},
+for the default settings of supported languages.
+
+@menu
+* Type Checking:: An overview of type checking
+* Range Checking:: An overview of range checking
+@end menu
+
+@cindex type checking
+@cindex checks, type
+@node Type Checking
+@subsection An overview of type checking
+
+Some languages, such as Modula-2, are strongly typed, meaning that the
+arguments to operators and functions have to be of the correct type,
+otherwise an error occurs. These checks prevent type mismatch
+errors from ever causing any run-time problems. For example,
+
+@smallexample
+1 + 2 @result{} 3
+@exdent but
+@error{} 1 + 2.3
+@end smallexample
+
+The second example fails because the @code{CARDINAL} 1 is not
+type-compatible with the @code{REAL} 2.3.
+
+For the expressions you use in @value{GDBN} commands, you can tell the
+@value{GDBN} type checker to skip checking;
+to treat any mismatches as errors and abandon the expression;
+or to only issue warnings when type mismatches occur,
+but evaluate the expression anyway. When you choose the last of
+these, @value{GDBN} evaluates expressions like the second example above, but
+also issues a warning.
+
+Even if you turn type checking off, there may be other reasons
+related to type that prevent @value{GDBN} from evaluating an expression.
+For instance, @value{GDBN} does not know how to add an @code{int} and
+a @code{struct foo}. These particular type errors have nothing to do
+with the language in use, and usually arise from expressions, such as
+the one described above, which make little sense to evaluate anyway.
+
+Each language defines to what degree it is strict about type. For
+instance, both Modula-2 and C require the arguments to arithmetical
+operators to be numbers. In C, enumerated types and pointers can be
+represented as numbers, so that they are valid arguments to mathematical
+operators. @xref{Support, ,Supported languages}, for further
+details on specific languages.
+
+@value{GDBN} provides some additional commands for controlling the type checker:
+
+@kindex set check
+@kindex set check type
+@kindex show check type
+@table @code
+@item set check type auto
+Set type checking on or off based on the current working language.
+@xref{Support, ,Supported languages}, for the default settings for
+each language.
+
+@item set check type on
+@itemx set check type off
+Set type checking on or off, overriding the default setting for the
+current working language. Issue a warning if the setting does not
+match the language default. If any type mismatches occur in
+evaluating an expression while typechecking is on, @value{GDBN} prints a
+message and aborts evaluation of the expression.
+
+@item set check type warn
+Cause the type checker to issue warnings, but to always attempt to
+evaluate the expression. Evaluating the expression may still
+be impossible for other reasons. For example, @value{GDBN} cannot add
+numbers and structures.
+
+@item show type
+Show the current setting of the type checker, and whether or not @value{GDBN}
+is setting it automatically.
+@end table
+
+@cindex range checking
+@cindex checks, range
+@node Range Checking
+@subsection An overview of range checking
+
+In some languages (such as Modula-2), it is an error to exceed the
+bounds of a type; this is enforced with run-time checks. Such range
+checking is meant to ensure program correctness by making sure
+computations do not overflow, or indices on an array element access do
+not exceed the bounds of the array.
+
+For expressions you use in @value{GDBN} commands, you can tell
+@value{GDBN} to treat range errors in one of three ways: ignore them,
+always treat them as errors and abandon the expression, or issue
+warnings but evaluate the expression anyway.
+
+A range error can result from numerical overflow, from exceeding an
+array index bound, or when you type a constant that is not a member
+of any type. Some languages, however, do not treat overflows as an
+error. In many implementations of C, mathematical overflow causes the
+result to ``wrap around'' to lower values---for example, if @var{m} is
+the largest integer value, and @var{s} is the smallest, then
+
+@example
+@var{m} + 1 @result{} @var{s}
+@end example
+
+This, too, is specific to individual languages, and in some cases
+specific to individual compilers or machines. @xref{Support, ,
+Supported languages}, for further details on specific languages.
+
+@value{GDBN} provides some additional commands for controlling the range checker:
+
+@kindex set check
+@kindex set check range
+@kindex show check range
+@table @code
+@item set check range auto
+Set range checking on or off based on the current working language.
+@xref{Support, ,Supported languages}, for the default settings for
+each language.
+
+@item set check range on
+@itemx set check range off
+Set range checking on or off, overriding the default setting for the
+current working language. A warning is issued if the setting does not
+match the language default. If a range error occurs, then a message
+is printed and evaluation of the expression is aborted.
+
+@item set check range warn
+Output messages when the @value{GDBN} range checker detects a range error,
+but attempt to evaluate the expression anyway. Evaluating the
+expression may still be impossible for other reasons, such as accessing
+memory that the process does not own (a typical example from many Unix
+systems).
+
+@item show range
+Show the current setting of the range checker, and whether or not it is
+being set automatically by @value{GDBN}.
+@end table
+@end ifset
+
+@node Support
+@section Supported languages
+
+@ifset MOD2
+@value{GDBN} 4 supports C, C++, and Modula-2.
+@end ifset
+@ifclear MOD2
+@value{GDBN} 4 supports C, and C++.
+@end ifclear
+Some @value{GDBN} features may be used in expressions regardless of the
+language you use: the @value{GDBN} @code{@@} and @code{::} operators,
+and the @samp{@{type@}addr} construct (@pxref{Expressions,
+,Expressions}) can be used with the constructs of any supported
+language.
+
+The following sections detail to what degree each source language is
+supported by @value{GDBN}. These sections are not meant to be language
+tutorials or references, but serve only as a reference guide to what the
+@value{GDBN} expression parser accepts, and what input and output
+formats should look like for different languages. There are many good
+books written on each of these languages; please look to these for a
+language reference or tutorial.
+
+@ifset MOD2
+@menu
+* C:: C and C++
+* Modula-2:: Modula-2
+@end menu
+
+@node C
+@subsection C and C++
+@cindex C and C++
+@cindex expressions in C or C++
+
+Since C and C++ are so closely related, many features of @value{GDBN} apply
+to both languages. Whenever this is the case, we discuss those languages
+together.
+@end ifset
+@ifclear MOD2
+@c Cancel this below, under same condition, at end of this chapter!
+@raisesections
+@end ifclear
+
+@cindex C++
+@kindex g++
+@cindex @sc{gnu} C++
+The C++ debugging facilities are jointly implemented by the @sc{gnu} C++
+compiler and @value{GDBN}. Therefore, to debug your C++ code
+effectively, you must compile your C++ programs with the @sc{gnu} C++
+compiler, @code{g++}.
+
+For best results when debugging C++ programs, use the stabs debugging
+format. You can select that format explicitly with the @code{g++}
+command-line options @samp{-gstabs} or @samp{-gstabs+}. See
+@ref{Debugging Options,,Options for Debugging Your Program or @sc{gnu} CC,
+gcc.info, Using @sc{gnu} CC}, for more information.
+@end ifclear
+@ifset CONLY
+@node C
+@chapter C Language Support
+@cindex C language
+@cindex expressions in C
+
+Information specific to the C language is built into @value{GDBN} so that you
+can use C expressions while degugging. This also permits @value{GDBN} to
+output values in a manner consistent with C conventions.
+
+@menu
+* C Operators:: C operators
+* C Constants:: C constants
+* Debugging C:: @value{GDBN} and C
+@end menu
+@end ifset
+@ifclear CONLY
+@menu
+* C Operators:: C and C++ operators
+* C Constants:: C and C++ constants
+* Cplus expressions:: C++ expressions
+* C Defaults:: Default settings for C and C++
+@ifset MOD2
+* C Checks:: C and C++ type and range checks
+@end ifset
+
+* Debugging C:: @value{GDBN} and C
+* Debugging C plus plus:: Special features for C++
+@end menu
+@end ifclear
+
+@ifclear CONLY
+@cindex C and C++ operators
+@node C Operators
+@subsubsection C and C++ operators
+@end ifclear
+@ifset CONLY
+@cindex C operators
+@node C Operators
+@section C operators
+@end ifset
+
+Operators must be defined on values of specific types. For instance,
+@code{+} is defined on numbers, but not on structures. Operators are
+often defined on groups of types.
+
+@ifclear CONLY
+For the purposes of C and C++, the following definitions hold:
+@end ifclear
+
+@itemize @bullet
+@item
+@emph{Integral types} include @code{int} with any of its storage-class
+specifiers; @code{char}; and @code{enum}.
+
+@item
+@emph{Floating-point types} include @code{float} and @code{double}.
+
+@item
+@emph{Pointer types} include all types defined as @code{(@var{type}
+*)}.
+
+@item
+@emph{Scalar types} include all of the above.
+@end itemize
+
+@noindent
+The following operators are supported. They are listed here
+in order of increasing precedence:
+
+@table @code
+@item ,
+The comma or sequencing operator. Expressions in a comma-separated list
+are evaluated from left to right, with the result of the entire
+expression being the last expression evaluated.
+
+@item =
+Assignment. The value of an assignment expression is the value
+assigned. Defined on scalar types.
+
+@item @var{op}=
+Used in an expression of the form @w{@code{@var{a} @var{op}= @var{b}}},
+and translated to @w{@code{@var{a} = @var{a op b}}}.
+@w{@code{@var{op}=}} and @code{=} have the same precendence.
+@var{op} is any one of the operators @code{|}, @code{^}, @code{&},
+@code{<<}, @code{>>}, @code{+}, @code{-}, @code{*}, @code{/}, @code{%}.
+
+@item ?:
+The ternary operator. @code{@var{a} ? @var{b} : @var{c}} can be thought
+of as: if @var{a} then @var{b} else @var{c}. @var{a} should be of an
+integral type.
+
+@item ||
+Logical @sc{or}. Defined on integral types.
+
+@item &&
+Logical @sc{and}. Defined on integral types.
+
+@item |
+Bitwise @sc{or}. Defined on integral types.
+
+@item ^
+Bitwise exclusive-@sc{or}. Defined on integral types.
+
+@item &
+Bitwise @sc{and}. Defined on integral types.
+
+@item ==@r{, }!=
+Equality and inequality. Defined on scalar types. The value of these
+expressions is 0 for false and non-zero for true.
+
+@item <@r{, }>@r{, }<=@r{, }>=
+Less than, greater than, less than or equal, greater than or equal.
+Defined on scalar types. The value of these expressions is 0 for false
+and non-zero for true.
+
+@item <<@r{, }>>
+left shift, and right shift. Defined on integral types.
+
+@item @@
+The @value{GDBN} ``artificial array'' operator (@pxref{Expressions, ,Expressions}).
+
+@item +@r{, }-
+Addition and subtraction. Defined on integral types, floating-point types and
+pointer types.
+
+@item *@r{, }/@r{, }%
+Multiplication, division, and modulus. Multiplication and division are
+defined on integral and floating-point types. Modulus is defined on
+integral types.
+
+@item ++@r{, }--
+Increment and decrement. When appearing before a variable, the
+operation is performed before the variable is used in an expression;
+when appearing after it, the variable's value is used before the
+operation takes place.
+
+@item *
+Pointer dereferencing. Defined on pointer types. Same precedence as
+@code{++}.
+
+@item &
+Address operator. Defined on variables. Same precedence as @code{++}.
+
+@ifclear CONLY
+For debugging C++, @value{GDBN} implements a use of @samp{&} beyond what is
+allowed in the C++ language itself: you can use @samp{&(&@var{ref})}
+(or, if you prefer, simply @samp{&&@var{ref}}) to examine the address
+where a C++ reference variable (declared with @samp{&@var{ref}}) is
+stored.
+@end ifclear
+
+@item -
+Negative. Defined on integral and floating-point types. Same
+precedence as @code{++}.
+
+@item !
+Logical negation. Defined on integral types. Same precedence as
+@code{++}.
+
+@item ~
+Bitwise complement operator. Defined on integral types. Same precedence as
+@code{++}.
+
+
+@item .@r{, }->
+Structure member, and pointer-to-structure member. For convenience,
+@value{GDBN} regards the two as equivalent, choosing whether to dereference a
+pointer based on the stored type information.
+Defined on @code{struct} and @code{union} data.
+
+@item []
+Array indexing. @code{@var{a}[@var{i}]} is defined as
+@code{*(@var{a}+@var{i})}. Same precedence as @code{->}.
+
+@item ()
+Function parameter list. Same precedence as @code{->}.
+
+@ifclear CONLY
+@item ::
+C++ scope resolution operator. Defined on
+@code{struct}, @code{union}, and @code{class} types.
+@end ifclear
+
+@item ::
+Doubled colons
+@ifclear CONLY
+also
+@end ifclear
+represent the @value{GDBN} scope operator (@pxref{Expressions,
+,Expressions}).
+@ifclear CONLY
+Same precedence as @code{::}, above.
+@end ifclear
+@end table
+
+@ifclear CONLY
+@cindex C and C++ constants
+@node C Constants
+@subsubsection C and C++ constants
+
+@value{GDBN} allows you to express the constants of C and C++ in the
+following ways:
+@end ifclear
+@ifset CONLY
+@cindex C constants
+@node C Constants
+@section C constants
+
+@value{GDBN} allows you to express the constants of C in the
+following ways:
+@end ifset
+
+@itemize @bullet
+@item
+Integer constants are a sequence of digits. Octal constants are
+specified by a leading @samp{0} (i.e. zero), and hexadecimal constants by
+a leading @samp{0x} or @samp{0X}. Constants may also end with a letter
+@samp{l}, specifying that the constant should be treated as a
+@code{long} value.
+
+@item
+Floating point constants are a sequence of digits, followed by a decimal
+point, followed by a sequence of digits, and optionally followed by an
+exponent. An exponent is of the form:
+@samp{@w{e@r{[[}+@r{]|}-@r{]}@var{nnn}}}, where @var{nnn} is another
+sequence of digits. The @samp{+} is optional for positive exponents.
+
+@item
+Enumerated constants consist of enumerated identifiers, or their
+integral equivalents.
+
+@item
+Character constants are a single character surrounded by single quotes
+(@code{'}), or a number---the ordinal value of the corresponding character
+(usually its @sc{ASCII} value). Within quotes, the single character may
+be represented by a letter or by @dfn{escape sequences}, which are of
+the form @samp{\@var{nnn}}, where @var{nnn} is the octal representation
+of the character's ordinal value; or of the form @samp{\@var{x}}, where
+@samp{@var{x}} is a predefined special character---for example,
+@samp{\n} for newline.
+
+@item
+String constants are a sequence of character constants surrounded
+by double quotes (@code{"}).
+
+@item
+Pointer constants are an integral value. You can also write pointers
+to constants using the C operator @samp{&}.
+
+@item
+Array constants are comma-separated lists surrounded by braces @samp{@{}
+and @samp{@}}; for example, @samp{@{1,2,3@}} is a three-element array of
+integers, @samp{@{@{1,2@}, @{3,4@}, @{5,6@}@}} is a three-by-two array,
+and @samp{@{&"hi", &"there", &"fred"@}} is a three-element array of pointers.
+@end itemize
+
+@ifclear CONLY
+@node Cplus expressions
+@subsubsection C++ expressions
+
+@cindex expressions in C++
+@value{GDBN} expression handling has a number of extensions to
+interpret a significant subset of C++ expressions.
+
+@cindex C++ support, not in @sc{coff}
+@cindex @sc{coff} versus C++
+@cindex C++ and object formats
+@cindex object formats and C++
+@cindex a.out and C++
+@cindex @sc{ecoff} and C++
+@cindex @sc{xcoff} and C++
+@cindex @sc{elf}/stabs and C++
+@cindex @sc{elf}/@sc{dwarf} and C++
+@c FIXME!! GDB may eventually be able to debug C++ using DWARF; check
+@c periodically whether this has happened...
+@quotation
+@emph{Warning:} @value{GDBN} can only debug C++ code if you compile with
+the @sc{gnu} C++ compiler. Moreover, C++ debugging depends on the use of
+additional debugging information in the symbol table, and thus requires
+special support. @value{GDBN} has this support @emph{only} with the
+stabs debug format. In particular, if your compiler generates a.out,
+MIPS @sc{ecoff}, RS/6000 @sc{xcoff}, or @sc{elf} with stabs extensions
+to the symbol table, these facilities are all available. (With @sc{gnu} CC,
+you can use the @samp{-gstabs} option to request stabs debugging
+extensions explicitly.) Where the object code format is standard
+@sc{coff} or @sc{dwarf} in @sc{elf}, on the other hand, most of the C++
+support in @value{GDBN} does @emph{not} work.
+@end quotation
+
+@enumerate
+
+@cindex member functions
+@item
+Member function calls are allowed; you can use expressions like
+
+@example
+count = aml->GetOriginal(x, y)
+@end example
+
+@kindex this
+@cindex namespace in C++
+@item
+While a member function is active (in the selected stack frame), your
+expressions have the same namespace available as the member function;
+that is, @value{GDBN} allows implicit references to the class instance
+pointer @code{this} following the same rules as C++.
+
+@cindex call overloaded functions
+@cindex type conversions in C++
+@item
+You can call overloaded functions; @value{GDBN} resolves the function
+call to the right definition, with one restriction---you must use
+arguments of the type required by the function that you want to call.
+@value{GDBN} does not perform conversions requiring constructors or
+user-defined type operators.
+
+@cindex reference declarations
+@item
+@value{GDBN} understands variables declared as C++ references; you can use
+them in expressions just as you do in C++ source---they are automatically
+dereferenced.
+
+In the parameter list shown when @value{GDBN} displays a frame, the values of
+reference variables are not displayed (unlike other variables); this
+avoids clutter, since references are often used for large structures.
+The @emph{address} of a reference variable is always shown, unless
+you have specified @samp{set print address off}.
+
+@item
+@value{GDBN} supports the C++ name resolution operator @code{::}---your
+expressions can use it just as expressions in your program do. Since
+one scope may be defined in another, you can use @code{::} repeatedly if
+necessary, for example in an expression like
+@samp{@var{scope1}::@var{scope2}::@var{name}}. @value{GDBN} also allows
+resolving name scope by reference to source files, in both C and C++
+debugging (@pxref{Variables, ,Program variables}).
+@end enumerate
+
+@node C Defaults
+@subsubsection C and C++ defaults
+@cindex C and C++ defaults
+
+If you allow @value{GDBN} to set type and range checking automatically, they
+both default to @code{off} whenever the working language changes to
+C or C++. This happens regardless of whether you or @value{GDBN}
+selects the working language.
+
+If you allow @value{GDBN} to set the language automatically, it recognizes
+source files whose names end with @file{.c}, @file{.C}, or @file{.cc}, and
+when @value{GDBN} enters code compiled from one of these files,
+it sets the working language to C or C++.
+@xref{Automatically, ,Having @value{GDBN} infer the source language}, for
+further details.
+
+@ifset MOD2
+@c Type checking is (a) primarily motivated by Modula-2, and (b)
+@c unimplemented. If (b) changes, it might make sense to let this node
+@c appear even if Mod-2 does not, but meanwhile ignore it. roland 16jul93.
+@node C Checks
+@subsubsection C and C++ type and range checks
+@cindex C and C++ checks
+
+By default, when @value{GDBN} parses C or C++ expressions, type checking
+is not used. However, if you turn type checking on, @value{GDBN}
+considers two variables type equivalent if:
+
+@itemize @bullet
+@item
+The two variables are structured and have the same structure, union, or
+enumerated tag.
+
+@item
+The two variables have the same type name, or types that have been
+declared equivalent through @code{typedef}.
+
+@ignore
+@c leaving this out because neither J Gilmore nor R Pesch understand it.
+@c FIXME--beers?
+@item
+The two @code{struct}, @code{union}, or @code{enum} variables are
+declared in the same declaration. (Note: this may not be true for all C
+compilers.)
+@end ignore
+@end itemize
+
+Range checking, if turned on, is done on mathematical operations. Array
+indices are not checked, since they are often used to index a pointer
+that is not itself an array.
+@end ifset
+@end ifclear
+
+@ifclear CONLY
+@node Debugging C
+@subsubsection @value{GDBN} and C
+@end ifclear
+@ifset CONLY
+@node Debugging C
+@section @value{GDBN} and C
+@end ifset
+
+The @code{set print union} and @code{show print union} commands apply to
+the @code{union} type. When set to @samp{on}, any @code{union} that is
+inside a @code{struct}
+@ifclear CONLY
+or @code{class}
+@end ifclear
+is also printed.
+Otherwise, it appears as @samp{@{...@}}.
+
+The @code{@@} operator aids in the debugging of dynamic arrays, formed
+with pointers and a memory allocation function. @xref{Expressions,
+,Expressions}.
+
+@ifclear CONLY
+@node Debugging C plus plus
+@subsubsection @value{GDBN} features for C++
+
+@cindex commands for C++
+Some @value{GDBN} commands are particularly useful with C++, and some are
+designed specifically for use with C++. Here is a summary:
+
+@table @code
+@cindex break in overloaded functions
+@item @r{breakpoint menus}
+When you want a breakpoint in a function whose name is overloaded,
+@value{GDBN} breakpoint menus help you specify which function definition
+you want. @xref{Breakpoint Menus,,Breakpoint menus}.
+
+@cindex overloading in C++
+@item rbreak @var{regex}
+Setting breakpoints using regular expressions is helpful for setting
+breakpoints on overloaded functions that are not members of any special
+classes.
+@xref{Set Breaks, ,Setting breakpoints}.
+
+@cindex C++ exception handling
+@item catch @var{exceptions}
+@itemx info catch
+Debug C++ exception handling using these commands. @xref{Exception
+Handling, ,Breakpoints and exceptions}.
+
+@cindex inheritance
+@item ptype @var{typename}
+Print inheritance relationships as well as other information for type
+@var{typename}.
+@xref{Symbols, ,Examining the Symbol Table}.
+
+@cindex C++ symbol display
+@item set print demangle
+@itemx show print demangle
+@itemx set print asm-demangle
+@itemx show print asm-demangle
+Control whether C++ symbols display in their source form, both when
+displaying code as C++ source and when displaying disassemblies.
+@xref{Print Settings, ,Print settings}.
+
+@item set print object
+@itemx show print object
+Choose whether to print derived (actual) or declared types of objects.
+@xref{Print Settings, ,Print settings}.
+
+@item set print vtbl
+@itemx show print vtbl
+Control the format for printing virtual function tables.
+@xref{Print Settings, ,Print settings}.
+
+@item @r{Overloaded symbol names}
+You can specify a particular definition of an overloaded symbol, using
+the same notation that is used to declare such symbols in C++: type
+@code{@var{symbol}(@var{types})} rather than just @var{symbol}. You can
+also use the @value{GDBN} command-line word completion facilities to list the
+available choices, or to finish the type list for you.
+@xref{Completion,, Command completion}, for details on how to do this.
+@end table
+@ifclear MOD2
+@c cancels "raisesections" under same conditions near bgn of chapter
+@lowersections
+@end ifclear
+
+@ifset MOD2
+@node Modula-2
+@subsection Modula-2
+@cindex Modula-2
+
+The extensions made to @value{GDBN} to support Modula-2 only support
+output from the @sc{gnu} Modula-2 compiler (which is currently being
+developed). Other Modula-2 compilers are not currently supported, and
+attempting to debug executables produced by them is most likely
+to give an error as @value{GDBN} reads in the executable's symbol
+table.
+
+@cindex expressions in Modula-2
+@menu
+* M2 Operators:: Built-in operators
+* Built-In Func/Proc:: Built-in functions and procedures
+* M2 Constants:: Modula-2 constants
+* M2 Defaults:: Default settings for Modula-2
+* Deviations:: Deviations from standard Modula-2
+* M2 Checks:: Modula-2 type and range checks
+* M2 Scope:: The scope operators @code{::} and @code{.}
+* GDB/M2:: @value{GDBN} and Modula-2
+@end menu
+
+@node M2 Operators
+@subsubsection Operators
+@cindex Modula-2 operators
+
+Operators must be defined on values of specific types. For instance,
+@code{+} is defined on numbers, but not on structures. Operators are
+often defined on groups of types. For the purposes of Modula-2, the
+following definitions hold:
+
+@itemize @bullet
+
+@item
+@emph{Integral types} consist of @code{INTEGER}, @code{CARDINAL}, and
+their subranges.
+
+@item
+@emph{Character types} consist of @code{CHAR} and its subranges.
+
+@item
+@emph{Floating-point types} consist of @code{REAL}.
+
+@item
+@emph{Pointer types} consist of anything declared as @code{POINTER TO
+@var{type}}.
+
+@item
+@emph{Scalar types} consist of all of the above.
+
+@item
+@emph{Set types} consist of @code{SET} and @code{BITSET} types.
+
+@item
+@emph{Boolean types} consist of @code{BOOLEAN}.
+@end itemize
+
+@noindent
+The following operators are supported, and appear in order of
+increasing precedence:
+
+@table @code
+@item ,
+Function argument or array index separator.
+
+@item :=
+Assignment. The value of @var{var} @code{:=} @var{value} is
+@var{value}.
+
+@item <@r{, }>
+Less than, greater than on integral, floating-point, or enumerated
+types.
+
+@item <=@r{, }>=
+Less than, greater than, less than or equal to, greater than or equal to
+on integral, floating-point and enumerated types, or set inclusion on
+set types. Same precedence as @code{<}.
+
+@item =@r{, }<>@r{, }#
+Equality and two ways of expressing inequality, valid on scalar types.
+Same precedence as @code{<}. In @value{GDBN} scripts, only @code{<>} is
+available for inequality, since @code{#} conflicts with the script
+comment character.
+
+@item IN
+Set membership. Defined on set types and the types of their members.
+Same precedence as @code{<}.
+
+@item OR
+Boolean disjunction. Defined on boolean types.
+
+@item AND@r{, }&
+Boolean conjuction. Defined on boolean types.
+
+@item @@
+The @value{GDBN} ``artificial array'' operator (@pxref{Expressions, ,Expressions}).
+
+@item +@r{, }-
+Addition and subtraction on integral and floating-point types, or union
+and difference on set types.
+
+@item *
+Multiplication on integral and floating-point types, or set intersection
+on set types.
+
+@item /
+Division on floating-point types, or symmetric set difference on set
+types. Same precedence as @code{*}.
+
+@item DIV@r{, }MOD
+Integer division and remainder. Defined on integral types. Same
+precedence as @code{*}.
+
+@item -
+Negative. Defined on @code{INTEGER} and @code{REAL} data.
+
+@item ^
+Pointer dereferencing. Defined on pointer types.
+
+@item NOT
+Boolean negation. Defined on boolean types. Same precedence as
+@code{^}.
+
+@item .
+@code{RECORD} field selector. Defined on @code{RECORD} data. Same
+precedence as @code{^}.
+
+@item []
+Array indexing. Defined on @code{ARRAY} data. Same precedence as @code{^}.
+
+@item ()
+Procedure argument list. Defined on @code{PROCEDURE} objects. Same precedence
+as @code{^}.
+
+@item ::@r{, }.
+@value{GDBN} and Modula-2 scope operators.
+@end table
+
+@quotation
+@emph{Warning:} Sets and their operations are not yet supported, so @value{GDBN}
+treats the use of the operator @code{IN}, or the use of operators
+@code{+}, @code{-}, @code{*}, @code{/}, @code{=}, , @code{<>}, @code{#},
+@code{<=}, and @code{>=} on sets as an error.
+@end quotation
+
+@cindex Modula-2 built-ins
+@node Built-In Func/Proc
+@subsubsection Built-in functions and procedures
+
+Modula-2 also makes available several built-in procedures and functions.
+In describing these, the following metavariables are used:
+
+@table @var
+
+@item a
+represents an @code{ARRAY} variable.
+
+@item c
+represents a @code{CHAR} constant or variable.
+
+@item i
+represents a variable or constant of integral type.
+
+@item m
+represents an identifier that belongs to a set. Generally used in the
+same function with the metavariable @var{s}. The type of @var{s} should
+be @code{SET OF @var{mtype}} (where @var{mtype} is the type of @var{m}).
+
+@item n
+represents a variable or constant of integral or floating-point type.
+
+@item r
+represents a variable or constant of floating-point type.
+
+@item t
+represents a type.
+
+@item v
+represents a variable.
+
+@item x
+represents a variable or constant of one of many types. See the
+explanation of the function for details.
+@end table
+
+All Modula-2 built-in procedures also return a result, described below.
+
+@table @code
+@item ABS(@var{n})
+Returns the absolute value of @var{n}.
+
+@item CAP(@var{c})
+If @var{c} is a lower case letter, it returns its upper case
+equivalent, otherwise it returns its argument
+
+@item CHR(@var{i})
+Returns the character whose ordinal value is @var{i}.
+
+@item DEC(@var{v})
+Decrements the value in the variable @var{v}. Returns the new value.
+
+@item DEC(@var{v},@var{i})
+Decrements the value in the variable @var{v} by @var{i}. Returns the
+new value.
+
+@item EXCL(@var{m},@var{s})
+Removes the element @var{m} from the set @var{s}. Returns the new
+set.
+
+@item FLOAT(@var{i})
+Returns the floating point equivalent of the integer @var{i}.
+
+@item HIGH(@var{a})
+Returns the index of the last member of @var{a}.
+
+@item INC(@var{v})
+Increments the value in the variable @var{v}. Returns the new value.
+
+@item INC(@var{v},@var{i})
+Increments the value in the variable @var{v} by @var{i}. Returns the
+new value.
+
+@item INCL(@var{m},@var{s})
+Adds the element @var{m} to the set @var{s} if it is not already
+there. Returns the new set.
+
+@item MAX(@var{t})
+Returns the maximum value of the type @var{t}.
+
+@item MIN(@var{t})
+Returns the minimum value of the type @var{t}.
+
+@item ODD(@var{i})
+Returns boolean TRUE if @var{i} is an odd number.
+
+@item ORD(@var{x})
+Returns the ordinal value of its argument. For example, the ordinal
+value of a character is its ASCII value (on machines supporting the
+ASCII character set). @var{x} must be of an ordered type, which include
+integral, character and enumerated types.
+
+@item SIZE(@var{x})
+Returns the size of its argument. @var{x} can be a variable or a type.
+
+@item TRUNC(@var{r})
+Returns the integral part of @var{r}.
+
+@item VAL(@var{t},@var{i})
+Returns the member of the type @var{t} whose ordinal value is @var{i}.
+@end table
+
+@quotation
+@emph{Warning:} Sets and their operations are not yet supported, so
+@value{GDBN} treats the use of procedures @code{INCL} and @code{EXCL} as
+an error.
+@end quotation
+
+@cindex Modula-2 constants
+@node M2 Constants
+@subsubsection Constants
+
+@value{GDBN} allows you to express the constants of Modula-2 in the following
+ways:
+
+@itemize @bullet
+
+@item
+Integer constants are simply a sequence of digits. When used in an
+expression, a constant is interpreted to be type-compatible with the
+rest of the expression. Hexadecimal integers are specified by a
+trailing @samp{H}, and octal integers by a trailing @samp{B}.
+
+@item
+Floating point constants appear as a sequence of digits, followed by a
+decimal point and another sequence of digits. An optional exponent can
+then be specified, in the form @samp{E@r{[}+@r{|}-@r{]}@var{nnn}}, where
+@samp{@r{[}+@r{|}-@r{]}@var{nnn}} is the desired exponent. All of the
+digits of the floating point constant must be valid decimal (base 10)
+digits.
+
+@item
+Character constants consist of a single character enclosed by a pair of
+like quotes, either single (@code{'}) or double (@code{"}). They may
+also be expressed by their ordinal value (their ASCII value, usually)
+followed by a @samp{C}.
+
+@item
+String constants consist of a sequence of characters enclosed by a
+pair of like quotes, either single (@code{'}) or double (@code{"}).
+Escape sequences in the style of C are also allowed. @xref{C
+Constants, ,C and C++ constants}, for a brief explanation of escape
+sequences.
+
+@item
+Enumerated constants consist of an enumerated identifier.
+
+@item
+Boolean constants consist of the identifiers @code{TRUE} and
+@code{FALSE}.
+
+@item
+Pointer constants consist of integral values only.
+
+@item
+Set constants are not yet supported.
+@end itemize
+
+@node M2 Defaults
+@subsubsection Modula-2 defaults
+@cindex Modula-2 defaults
+
+If type and range checking are set automatically by @value{GDBN}, they
+both default to @code{on} whenever the working language changes to
+Modula-2. This happens regardless of whether you, or @value{GDBN},
+selected the working language.
+
+If you allow @value{GDBN} to set the language automatically, then entering
+code compiled from a file whose name ends with @file{.mod} sets the
+working language to Modula-2. @xref{Automatically, ,Having @value{GDBN} set
+the language automatically}, for further details.
+
+@node Deviations
+@subsubsection Deviations from standard Modula-2
+@cindex Modula-2, deviations from
+
+A few changes have been made to make Modula-2 programs easier to debug.
+This is done primarily via loosening its type strictness:
+
+@itemize @bullet
+@item
+Unlike in standard Modula-2, pointer constants can be formed by
+integers. This allows you to modify pointer variables during
+debugging. (In standard Modula-2, the actual address contained in a
+pointer variable is hidden from you; it can only be modified
+through direct assignment to another pointer variable or expression that
+returned a pointer.)
+
+@item
+C escape sequences can be used in strings and characters to represent
+non-printable characters. @value{GDBN} prints out strings with these
+escape sequences embedded. Single non-printable characters are
+printed using the @samp{CHR(@var{nnn})} format.
+
+@item
+The assignment operator (@code{:=}) returns the value of its right-hand
+argument.
+
+@item
+All built-in procedures both modify @emph{and} return their argument.
+@end itemize
+
+@node M2 Checks
+@subsubsection Modula-2 type and range checks
+@cindex Modula-2 checks
+
+@quotation
+@emph{Warning:} in this release, @value{GDBN} does not yet perform type or
+range checking.
+@end quotation
+@c FIXME remove warning when type/range checks added
+
+@value{GDBN} considers two Modula-2 variables type equivalent if:
+
+@itemize @bullet
+@item
+They are of types that have been declared equivalent via a @code{TYPE
+@var{t1} = @var{t2}} statement
+
+@item
+They have been declared on the same line. (Note: This is true of the
+@sc{gnu} Modula-2 compiler, but it may not be true of other compilers.)
+@end itemize
+
+As long as type checking is enabled, any attempt to combine variables
+whose types are not equivalent is an error.
+
+Range checking is done on all mathematical operations, assignment, array
+index bounds, and all built-in functions and procedures.
+
+@node M2 Scope
+@subsubsection The scope operators @code{::} and @code{.}
+@cindex scope
+@kindex .
+@cindex colon, doubled as scope operator
+@ifinfo
+@kindex colon-colon
+@c Info cannot handle :: but TeX can.
+@end ifinfo
+@iftex
+@kindex ::
+@end iftex
+
+There are a few subtle differences between the Modula-2 scope operator
+(@code{.}) and the @value{GDBN} scope operator (@code{::}). The two have
+similar syntax:
+
+@example
+
+@var{module} . @var{id}
+@var{scope} :: @var{id}
+@end example
+
+@noindent
+where @var{scope} is the name of a module or a procedure,
+@var{module} the name of a module, and @var{id} is any declared
+identifier within your program, except another module.
+
+Using the @code{::} operator makes @value{GDBN} search the scope
+specified by @var{scope} for the identifier @var{id}. If it is not
+found in the specified scope, then @value{GDBN} searches all scopes
+enclosing the one specified by @var{scope}.
+
+Using the @code{.} operator makes @value{GDBN} search the current scope for
+the identifier specified by @var{id} that was imported from the
+definition module specified by @var{module}. With this operator, it is
+an error if the identifier @var{id} was not imported from definition
+module @var{module}, or if @var{id} is not an identifier in
+@var{module}.
+
+@node GDB/M2
+@subsubsection @value{GDBN} and Modula-2
+
+Some @value{GDBN} commands have little use when debugging Modula-2 programs.
+Five subcommands of @code{set print} and @code{show print} apply
+specifically to C and C++: @samp{vtbl}, @samp{demangle},
+@samp{asm-demangle}, @samp{object}, and @samp{union}. The first four
+apply to C++, and the last to the C @code{union} type, which has no direct
+analogue in Modula-2.
+
+The @code{@@} operator (@pxref{Expressions, ,Expressions}), while available
+while using any language, is not useful with Modula-2. Its
+intent is to aid the debugging of @dfn{dynamic arrays}, which cannot be
+created in Modula-2 as they can in C or C++. However, because an
+address can be specified by an integral constant, the construct
+@samp{@{@var{type}@}@var{adrexp}} is still useful. (@pxref{Expressions, ,Expressions})
+
+@cindex @code{#} in Modula-2
+In @value{GDBN} scripts, the Modula-2 inequality operator @code{#} is
+interpreted as the beginning of a comment. Use @code{<>} instead.
+@end ifset
+@end ifclear
+
+@node Symbols
+@chapter Examining the Symbol Table
+
+The commands described in this section allow you to inquire about the
+symbols (names of variables, functions and types) defined in your
+program. This information is inherent in the text of your program and
+does not change as your program executes. @value{GDBN} finds it in your
+program's symbol table, in the file indicated when you started @value{GDBN}
+(@pxref{File Options, ,Choosing files}), or by one of the
+file-management commands (@pxref{Files, ,Commands to specify files}).
+
+@cindex symbol names
+@cindex names of symbols
+@cindex quoting names
+Occasionally, you may need to refer to symbols that contain unusual
+characters, which @value{GDBN} ordinarily treats as word delimiters. The
+most frequent case is in referring to static variables in other
+source files (@pxref{Variables,,Program variables}). File names
+are recorded in object files as debugging symbols, but @value{GDBN} would
+ordinarily parse a typical file name, like @file{foo.c}, as the three words
+@samp{foo} @samp{.} @samp{c}. To allow @value{GDBN} to recognize
+@samp{foo.c} as a single symbol, enclose it in single quotes; for example,
+
+@example
+p 'foo.c'::x
+@end example
+
+@noindent
+looks up the value of @code{x} in the scope of the file @file{foo.c}.
+
+@table @code
+@kindex info address
+@item info address @var{symbol}
+Describe where the data for @var{symbol} is stored. For a register
+variable, this says which register it is kept in. For a non-register
+local variable, this prints the stack-frame offset at which the variable
+is always stored.
+
+Note the contrast with @samp{print &@var{symbol}}, which does not work
+at all for a register variable, and for a stack local variable prints
+the exact address of the current instantiation of the variable.
+
+@kindex whatis
+@item whatis @var{exp}
+Print the data type of expression @var{exp}. @var{exp} is not
+actually evaluated, and any side-effecting operations (such as
+assignments or function calls) inside it do not take place.
+@xref{Expressions, ,Expressions}.
+
+@item whatis
+Print the data type of @code{$}, the last value in the value history.
+
+@kindex ptype
+@item ptype @var{typename}
+Print a description of data type @var{typename}. @var{typename} may be
+the name of a type, or for C code it may have the form
+@ifclear CONLY
+@samp{class @var{class-name}},
+@end ifclear
+@samp{struct @var{struct-tag}}, @samp{union @var{union-tag}} or
+@samp{enum @var{enum-tag}}.
+
+@item ptype @var{exp}
+@itemx ptype
+Print a description of the type of expression @var{exp}. @code{ptype}
+differs from @code{whatis} by printing a detailed description, instead
+of just the name of the type.
+
+For example, for this variable declaration:
+
+@example
+struct complex @{double real; double imag;@} v;
+@end example
+
+@noindent
+the two commands give this output:
+
+@example
+@group
+(@value{GDBP}) whatis v
+type = struct complex
+(@value{GDBP}) ptype v
+type = struct complex @{
+ double real;
+ double imag;
+@}
+@end group
+@end example
+
+@noindent
+As with @code{whatis}, using @code{ptype} without an argument refers to
+the type of @code{$}, the last value in the value history.
+
+@kindex info types
+@item info types @var{regexp}
+@itemx info types
+Print a brief description of all types whose name matches @var{regexp}
+(or all types in your program, if you supply no argument). Each
+complete typename is matched as though it were a complete line; thus,
+@samp{i type value} gives information on all types in your program whose
+name includes the string @code{value}, but @samp{i type ^value$} gives
+information only on types whose complete name is @code{value}.
+
+This command differs from @code{ptype} in two ways: first, like
+@code{whatis}, it does not print a detailed description; second, it
+lists all source files where a type is defined.
+
+@kindex info source
+@item info source
+Show the name of the current source file---that is, the source file for
+the function containing the current point of execution---and the language
+it was written in.
+
+@kindex info sources
+@item info sources
+Print the names of all source files in your program for which there is
+debugging information, organized into two lists: files whose symbols
+have already been read, and files whose symbols will be read when needed.
+
+@kindex info functions
+@item info functions
+Print the names and data types of all defined functions.
+
+@item info functions @var{regexp}
+Print the names and data types of all defined functions
+whose names contain a match for regular expression @var{regexp}.
+Thus, @samp{info fun step} finds all functions whose names
+include @code{step}; @samp{info fun ^step} finds those whose names
+start with @code{step}.
+
+@kindex info variables
+@item info variables
+Print the names and data types of all variables that are declared
+outside of functions (i.e., excluding local variables).
+
+@item info variables @var{regexp}
+Print the names and data types of all variables (except for local
+variables) whose names contain a match for regular expression
+@var{regexp}.
+
+@ignore
+This was never implemented.
+@kindex info methods
+@item info methods
+@itemx info methods @var{regexp}
+The @code{info methods} command permits the user to examine all defined
+methods within C++ program, or (with the @var{regexp} argument) a
+specific set of methods found in the various C++ classes. Many
+C++ classes provide a large number of methods. Thus, the output
+from the @code{ptype} command can be overwhelming and hard to use. The
+@code{info-methods} command filters the methods, printing only those
+which match the regular-expression @var{regexp}.
+@end ignore
+
+@cindex reloading symbols
+Some systems allow individual object files that make up your program to
+be replaced without stopping and restarting your program.
+@ifset VXWORKS
+For example, in VxWorks you can simply recompile a defective object file
+and keep on running.
+@end ifset
+If you are running on one of these systems, you can allow @value{GDBN} to
+reload the symbols for automatically relinked modules:
+
+@table @code
+@kindex set symbol-reloading
+@item set symbol-reloading on
+Replace symbol definitions for the corresponding source file when an
+object file with a particular name is seen again.
+
+@item set symbol-reloading off
+Do not replace symbol definitions when re-encountering object files of
+the same name. This is the default state; if you are not running on a
+system that permits automatically relinking modules, you should leave
+@code{symbol-reloading} off, since otherwise @value{GDBN} may discard symbols
+when linking large programs, that may contain several modules (from
+different directories or libraries) with the same name.
+
+@kindex show symbol-reloading
+@item show symbol-reloading
+Show the current @code{on} or @code{off} setting.
+@end table
+
+@kindex maint print symbols
+@cindex symbol dump
+@kindex maint print psymbols
+@cindex partial symbol dump
+@item maint print symbols @var{filename}
+@itemx maint print psymbols @var{filename}
+@itemx maint print msymbols @var{filename}
+Write a dump of debugging symbol data into the file @var{filename}.
+These commands are used to debug the @value{GDBN} symbol-reading code. Only
+symbols with debugging data are included. If you use @samp{maint print
+symbols}, @value{GDBN} includes all the symbols for which it has already
+collected full details: that is, @var{filename} reflects symbols for
+only those files whose symbols @value{GDBN} has read. You can use the
+command @code{info sources} to find out which files these are. If you
+use @samp{maint print psymbols} instead, the dump shows information about
+symbols that @value{GDBN} only knows partially---that is, symbols defined in
+files that @value{GDBN} has skimmed, but not yet read completely. Finally,
+@samp{maint print msymbols} dumps just the minimal symbol information
+required for each object file from which @value{GDBN} has read some symbols.
+@xref{Files, ,Commands to specify files}, for a discussion of how
+@value{GDBN} reads symbols (in the description of @code{symbol-file}).
+@end table
+
+@node Altering
+@chapter Altering Execution
+
+Once you think you have found an error in your program, you might want to
+find out for certain whether correcting the apparent error would lead to
+correct results in the rest of the run. You can find the answer by
+experiment, using the @value{GDBN} features for altering execution of the
+program.
+
+For example, you can store new values into variables or memory
+locations,
+@ifclear BARETARGET
+give your program a signal, restart it
+@end ifclear
+@ifset BARETARGET
+restart your program
+@end ifset
+at a different address, or even return prematurely from a function.
+
+@menu
+* Assignment:: Assignment to variables
+* Jumping:: Continuing at a different address
+@ifclear BARETARGET
+* Signaling:: Giving your program a signal
+@end ifclear
+
+* Returning:: Returning from a function
+* Calling:: Calling your program's functions
+* Patching:: Patching your program
+@end menu
+
+@node Assignment
+@section Assignment to variables
+
+@cindex assignment
+@cindex setting variables
+To alter the value of a variable, evaluate an assignment expression.
+@xref{Expressions, ,Expressions}. For example,
+
+@example
+print x=4
+@end example
+
+@noindent
+stores the value 4 into the variable @code{x}, and then prints the
+value of the assignment expression (which is 4).
+@ifclear CONLY
+@xref{Languages, ,Using @value{GDBN} with Different Languages}, for more
+information on operators in supported languages.
+@end ifclear
+
+@kindex set variable
+@cindex variables, setting
+If you are not interested in seeing the value of the assignment, use the
+@code{set} command instead of the @code{print} command. @code{set} is
+really the same as @code{print} except that the expression's value is
+not printed and is not put in the value history (@pxref{Value History,
+,Value history}). The expression is evaluated only for its effects.
+
+If the beginning of the argument string of the @code{set} command
+appears identical to a @code{set} subcommand, use the @code{set
+variable} command instead of just @code{set}. This command is identical
+to @code{set} except for its lack of subcommands. For example, if
+your program has a variable @code{width}, you get
+an error if you try to set a new value with just @samp{set width=13},
+because @value{GDBN} has the command @code{set width}:
+
+@example
+(@value{GDBP}) whatis width
+type = double
+(@value{GDBP}) p width
+$4 = 13
+(@value{GDBP}) set width=47
+Invalid syntax in expression.
+@end example
+
+@noindent
+The invalid expression, of course, is @samp{=47}. In
+order to actually set the program's variable @code{width}, use
+
+@example
+(@value{GDBP}) set var width=47
+@end example
+
+@value{GDBN} allows more implicit conversions in assignments than C; you can
+freely store an integer value into a pointer variable or vice versa,
+and you can convert any structure to any other structure that is the
+same length or shorter.
+@comment FIXME: how do structs align/pad in these conversions?
+@comment /doc@cygnus.com 18dec1990
+
+To store values into arbitrary places in memory, use the @samp{@{@dots{}@}}
+construct to generate a value of specified type at a specified address
+(@pxref{Expressions, ,Expressions}). For example, @code{@{int@}0x83040} refers
+to memory location @code{0x83040} as an integer (which implies a certain size
+and representation in memory), and
+
+@example
+set @{int@}0x83040 = 4
+@end example
+
+@noindent
+stores the value 4 into that memory location.
+
+@node Jumping
+@section Continuing at a different address
+
+Ordinarily, when you continue your program, you do so at the place where
+it stopped, with the @code{continue} command. You can instead continue at
+an address of your own choosing, with the following commands:
+
+@table @code
+@kindex jump
+@item jump @var{linespec}
+Resume execution at line @var{linespec}. Execution stops again
+immediately if there is a breakpoint there. @xref{List, ,Printing
+source lines}, for a description of the different forms of
+@var{linespec}.
+
+The @code{jump} command does not change the current stack frame, or
+the stack pointer, or the contents of any memory location or any
+register other than the program counter. If line @var{linespec} is in
+a different function from the one currently executing, the results may
+be bizarre if the two functions expect different patterns of arguments or
+of local variables. For this reason, the @code{jump} command requests
+confirmation if the specified line is not in the function currently
+executing. However, even bizarre results are predictable if you are
+well acquainted with the machine-language code of your program.
+
+@item jump *@var{address}
+Resume execution at the instruction at address @var{address}.
+@end table
+
+You can get much the same effect as the @code{jump} command by storing a
+new value into the register @code{$pc}. The difference is that this
+does not start your program running; it only changes the address of where it
+@emph{will} run when you continue. For example,
+
+@example
+set $pc = 0x485
+@end example
+
+@noindent
+makes the next @code{continue} command or stepping command execute at
+address @code{0x485}, rather than at the address where your program stopped.
+@xref{Continuing and Stepping, ,Continuing and stepping}.
+
+The most common occasion to use the @code{jump} command is to back up--
+perhaps with more breakpoints set--over a portion of a program that has
+already executed, in order to examine its execution in more detail.
+
+@ifclear BARETARGET
+@c @group
+@node Signaling
+@section Giving your program a signal
+
+@table @code
+@kindex signal
+@item signal @var{signal}
+Resume execution where your program stopped, but immediately give it the
+signal @var{signal}. @var{signal} can be the name or the number of a
+signal. For example, on many systems @code{signal 2} and @code{signal
+SIGINT} are both ways of sending an interrupt signal.
+
+Alternatively, if @var{signal} is zero, continue execution without
+giving a signal. This is useful when your program stopped on account of
+a signal and would ordinary see the signal when resumed with the
+@code{continue} command; @samp{signal 0} causes it to resume without a
+signal.
+
+@code{signal} does not repeat when you press @key{RET} a second time
+after executing the command.
+@end table
+@c @end group
+
+Invoking the @code{signal} command is not the same as invoking the
+@code{kill} utility from the shell. Sending a signal with @code{kill}
+causes @value{GDBN} to decide what to do with the signal depending on
+the signal handling tables (@pxref{Signals}). The @code{signal} command
+passes the signal directly to your program.
+
+@end ifclear
+
+@node Returning
+@section Returning from a function
+
+@table @code
+@cindex returning from a function
+@kindex return
+@item return
+@itemx return @var{expression}
+You can cancel execution of a function call with the @code{return}
+command. If you give an
+@var{expression} argument, its value is used as the function's return
+value.
+@end table
+
+When you use @code{return}, @value{GDBN} discards the selected stack frame
+(and all frames within it). You can think of this as making the
+discarded frame return prematurely. If you wish to specify a value to
+be returned, give that value as the argument to @code{return}.
+
+This pops the selected stack frame (@pxref{Selection, ,Selecting a
+frame}), and any other frames inside of it, leaving its caller as the
+innermost remaining frame. That frame becomes selected. The
+specified value is stored in the registers used for returning values
+of functions.
+
+The @code{return} command does not resume execution; it leaves the
+program stopped in the state that would exist if the function had just
+returned. In contrast, the @code{finish} command (@pxref{Continuing
+and Stepping, ,Continuing and stepping}) resumes execution until the
+selected stack frame returns naturally.
+
+@node Calling
+@section Calling program functions
+
+@cindex calling functions
+@kindex call
+@table @code
+@item call @var{expr}
+Evaluate the expression @var{expr} without displaying @code{void}
+returned values.
+@end table
+
+You can use this variant of the @code{print} command if you want to
+execute a function from your program, but without cluttering the output
+with @code{void} returned values. If the result is not void, it
+is printed and saved in the value history.
+
+A new user-controlled variable, @var{call_scratch_address}, specifies
+the location of a scratch area to be used when @value{GDBN} calls a
+function in the target. This is necessary because the usual method
+of putting the scratch area on the stack does not work in systems that
+have separate instruction and data spaces.
+
+@node Patching
+@section Patching programs
+@cindex patching binaries
+@cindex writing into executables
+@ifclear BARETARGET
+@cindex writing into corefiles
+@end ifclear
+
+By default, @value{GDBN} opens the file containing your program's executable
+code
+@ifclear BARETARGET
+(or the corefile)
+@end ifclear
+read-only. This prevents accidental alterations
+to machine code; but it also prevents you from intentionally patching
+your program's binary.
+
+If you'd like to be able to patch the binary, you can specify that
+explicitly with the @code{set write} command. For example, you might
+want to turn on internal debugging flags, or even to make emergency
+repairs.
+
+@table @code
+@kindex set write
+@item set write on
+@itemx set write off
+If you specify @samp{set write on}, @value{GDBN} opens executable
+@ifclear BARETARGET
+and core
+@end ifclear
+files for both reading and writing; if you specify @samp{set write
+off} (the default), @value{GDBN} opens them read-only.
+
+If you have already loaded a file, you must load it again (using the
+@code{exec-file}
+@ifclear BARETARGET
+or @code{core-file}
+@end ifclear
+command) after changing @code{set write}, for your new setting to take
+effect.
+
+@item show write
+@kindex show write
+Display whether executable files
+@ifclear BARETARGET
+and core files
+@end ifclear
+are opened for writing as well as reading.
+@end table
+
+@node GDB Files
+@chapter @value{GDBN} Files
+
+@value{GDBN} needs to know the file name of the program to be debugged, both in
+order to read its symbol table and in order to start your program.
+@ifclear BARETARGET
+To debug a core dump of a previous run, you must also tell @value{GDBN}
+the name of the core dump file.
+@end ifclear
+
+@menu
+* Files:: Commands to specify files
+* Symbol Errors:: Errors reading symbol files
+@end menu
+
+@node Files
+@section Commands to specify files
+@cindex symbol table
+
+@ifclear BARETARGET
+@cindex core dump file
+You may want to specify executable and core dump file names.
+The usual way to do this is at start-up time, using the arguments to
+@value{GDBN}'s start-up commands (@pxref{Invocation, ,
+Getting In and Out of @value{GDBN}}).
+@end ifclear
+@ifset BARETARGET
+The usual way to specify an executable file name is with
+the command argument given when you start @value{GDBN}, (@pxref{Invocation,
+,Getting In and Out of @value{GDBN}}.
+@end ifset
+
+Occasionally it is necessary to change to a different file during a
+@value{GDBN} session. Or you may run @value{GDBN} and forget to specify
+a file you want to use. In these situations the @value{GDBN} commands
+to specify new files are useful.
+
+@table @code
+@cindex executable file
+@kindex file
+@item file @var{filename}
+Use @var{filename} as the program to be debugged. It is read for its
+symbols and for the contents of pure memory. It is also the program
+executed when you use the @code{run} command. If you do not specify a
+directory and the file is not found in the @value{GDBN} working directory,
+@value{GDBN} uses the environment variable @code{PATH} as a list of
+directories to search, just as the shell does when looking for a program
+to run. You can change the value of this variable, for both @value{GDBN}
+and your program, using the @code{path} command.
+
+On systems with memory-mapped files, an auxiliary file
+@file{@var{filename}.syms} may hold symbol table information for
+@var{filename}. If so, @value{GDBN} maps in the symbol table from
+@file{@var{filename}.syms}, starting up more quickly. See the
+descriptions of the file options @samp{-mapped} and @samp{-readnow}
+(available on the command line, and with the commands @code{file},
+@code{symbol-file}, or @code{add-symbol-file}, described below),
+for more information.
+
+@item file
+@code{file} with no argument makes @value{GDBN} discard any information it
+has on both executable file and the symbol table.
+
+@kindex exec-file
+@item exec-file @r{[} @var{filename} @r{]}
+Specify that the program to be run (but not the symbol table) is found
+in @var{filename}. @value{GDBN} searches the environment variable @code{PATH}
+if necessary to locate your program. Omitting @var{filename} means to
+discard information on the executable file.
+
+@kindex symbol-file
+@item symbol-file @r{[} @var{filename} @r{]}
+Read symbol table information from file @var{filename}. @code{PATH} is
+searched when necessary. Use the @code{file} command to get both symbol
+table and program to run from the same file.
+
+@code{symbol-file} with no argument clears out @value{GDBN} information on your
+program's symbol table.
+
+The @code{symbol-file} command causes @value{GDBN} to forget the contents
+of its convenience variables, the value history, and all breakpoints and
+auto-display expressions. This is because they may contain pointers to
+the internal data recording symbols and data types, which are part of
+the old symbol table data being discarded inside @value{GDBN}.
+
+@code{symbol-file} does not repeat if you press @key{RET} again after
+executing it once.
+
+When @value{GDBN} is configured for a particular environment, it
+understands debugging information in whatever format is the standard
+generated for that environment; you may use either a @sc{gnu} compiler, or
+other compilers that adhere to the local conventions. Best results are
+usually obtained from @sc{gnu} compilers; for example, using @code{@value{GCC}}
+you can generate debugging information for optimized code.
+
+On some kinds of object files, the @code{symbol-file} command does not
+normally read the symbol table in full right away. Instead, it scans
+the symbol table quickly to find which source files and which symbols
+are present. The details are read later, one source file at a time,
+as they are needed.
+
+The purpose of this two-stage reading strategy is to make @value{GDBN} start up
+faster. For the most part, it is invisible except for occasional
+pauses while the symbol table details for a particular source file are
+being read. (The @code{set verbose} command can turn these pauses
+into messages if desired. @xref{Messages/Warnings, ,Optional warnings
+and messages}.)
+
+We have not implemented the two-stage strategy for COFF yet. When the
+symbol table is stored in COFF format, @code{symbol-file} reads the
+symbol table data in full right away.
+
+@kindex readnow
+@cindex reading symbols immediately
+@cindex symbols, reading immediately
+@kindex mapped
+@cindex memory-mapped symbol file
+@cindex saving symbol table
+@item symbol-file @var{filename} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+@itemx file @var{filename} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+You can override the @value{GDBN} two-stage strategy for reading symbol
+tables by using the @samp{-readnow} option with any of the commands that
+load symbol table information, if you want to be sure @value{GDBN} has the
+entire symbol table available.
+
+@ifclear BARETARGET
+If memory-mapped files are available on your system through the
+@code{mmap} system call, you can use another option, @samp{-mapped}, to
+cause @value{GDBN} to write the symbols for your program into a reusable
+file. Future @value{GDBN} debugging sessions map in symbol information
+from this auxiliary symbol file (if the program has not changed), rather
+than spending time reading the symbol table from the executable
+program. Using the @samp{-mapped} option has the same effect as
+starting @value{GDBN} with the @samp{-mapped} command-line option.
+
+You can use both options together, to make sure the auxiliary symbol
+file has all the symbol information for your program.
+
+The auxiliary symbol file for a program called @var{myprog} is called
+@samp{@var{myprog}.syms}. Once this file exists (so long as it is newer
+than the corresponding executable), @value{GDBN} always attempts to use
+it when you debug @var{myprog}; no special options or commands are
+needed.
+
+The @file{.syms} file is specific to the host machine where you run
+@value{GDBN}. It holds an exact image of the internal @value{GDBN}
+symbol table. It cannot be shared across multiple host platforms.
+
+@c FIXME: for now no mention of directories, since this seems to be in
+@c flux. 13mar1992 status is that in theory GDB would look either in
+@c current dir or in same dir as myprog; but issues like competing
+@c GDB's, or clutter in system dirs, mean that in practice right now
+@c only current dir is used. FFish says maybe a special GDB hierarchy
+@c (eg rooted in val of env var GDBSYMS) could exist for mappable symbol
+@c files.
+
+@kindex core
+@kindex core-file
+@item core-file @r{[} @var{filename} @r{]}
+Specify the whereabouts of a core dump file to be used as the ``contents
+of memory''. Traditionally, core files contain only some parts of the
+address space of the process that generated them; @value{GDBN} can access the
+executable file itself for other parts.
+
+@code{core-file} with no argument specifies that no core file is
+to be used.
+
+Note that the core file is ignored when your program is actually running
+under @value{GDBN}. So, if you have been running your program and you wish to
+debug a core file instead, you must kill the subprocess in which the
+program is running. To do this, use the @code{kill} command
+(@pxref{Kill Process, ,Killing the child process}).
+@end ifclear
+
+@kindex load @var{filename}
+@item load @var{filename}
+@ifset GENERIC
+Depending on what remote debugging facilities are configured into
+@value{GDBN}, the @code{load} command may be available. Where it exists, it
+is meant to make @var{filename} (an executable) available for debugging
+on the remote system---by downloading, or dynamic linking, for example.
+@code{load} also records the @var{filename} symbol table in @value{GDBN}, like
+the @code{add-symbol-file} command.
+
+If your @value{GDBN} does not have a @code{load} command, attempting to
+execute it gets the error message ``@code{You can't do that when your
+target is @dots{}}''
+@end ifset
+
+The file is loaded at whatever address is specified in the executable.
+For some object file formats, you can specify the load address when you
+link the program; for other formats, like a.out, the object file format
+specifies a fixed address.
+@c FIXME! This would be a good place for an xref to the GNU linker doc.
+
+@ifset VXWORKS
+On VxWorks, @code{load} links @var{filename} dynamically on the
+current target system as well as adding its symbols in @value{GDBN}.
+@end ifset
+
+@ifset I960
+@cindex download to Nindy-960
+With the Nindy interface to an Intel 960 board, @code{load}
+downloads @var{filename} to the 960 as well as adding its symbols in
+@value{GDBN}.
+@end ifset
+
+@ifset H8
+@cindex download to H8/300 or H8/500
+@cindex H8/300 or H8/500 download
+@cindex download to Hitachi SH
+@cindex Hitachi SH download
+When you select remote debugging to a Hitachi SH, H8/300, or H8/500 board
+(@pxref{Hitachi Remote,,@value{GDBN} and Hitachi Microprocessors}),
+the @code{load} command downloads your program to the Hitachi board and also
+opens it as the current executable target for @value{GDBN} on your host
+(like the @code{file} command).
+@end ifset
+
+@code{load} does not repeat if you press @key{RET} again after using it.
+
+@ifclear BARETARGET
+@kindex add-symbol-file
+@cindex dynamic linking
+@item add-symbol-file @var{filename} @var{address}
+@itemx add-symbol-file @var{filename} @var{address} @r{[} -readnow @r{]} @r{[} -mapped @r{]}
+The @code{add-symbol-file} command reads additional symbol table information
+from the file @var{filename}. You would use this command when @var{filename}
+has been dynamically loaded (by some other means) into the program that
+is running. @var{address} should be the memory address at which the
+file has been loaded; @value{GDBN} cannot figure this out for itself.
+You can specify @var{address} as an expression.
+
+The symbol table of the file @var{filename} is added to the symbol table
+originally read with the @code{symbol-file} command. You can use the
+@code{add-symbol-file} command any number of times; the new symbol data thus
+read keeps adding to the old. To discard all old symbol data instead,
+use the @code{symbol-file} command.
+
+@code{add-symbol-file} does not repeat if you press @key{RET} after using it.
+
+You can use the @samp{-mapped} and @samp{-readnow} options just as with
+the @code{symbol-file} command, to change how @value{GDBN} manages the symbol
+table information for @var{filename}.
+
+@kindex add-shared-symbol-file
+@item add-shared-symbol-file
+The @code{add-shared-symbol-file} command can be used only under Harris' CXUX
+operating system for the Motorola 88k. @value{GDBN} automatically looks for
+shared libraries, however if @value{GDBN} does not find yours, you can run
+@code{add-shared-symbol-file}. It takes no arguments.
+@end ifclear
+
+@kindex section
+@item section
+The @code{section} command changes the base address of section SECTION of
+the exec file to ADDR. This can be used if the exec file does not contain
+section addresses, (such as in the a.out format), or when the addresses
+specified in the file itself are wrong. Each section must be changed
+separately. The ``info files'' command lists all the sections and their
+addresses.
+
+@kindex info files
+@kindex info target
+@item info files
+@itemx info target
+@code{info files} and @code{info target} are synonymous; both print
+the current target (@pxref{Targets, ,Specifying a Debugging Target}),
+including the
+@ifclear BARETARGET
+names of the executable and core dump files
+@end ifclear
+@ifset BARETARGET
+name of the executable file
+@end ifset
+currently in use by @value{GDBN}, and the files from which symbols were
+loaded. The command @code{help target} lists all possible targets
+rather than current ones.
+@end table
+
+All file-specifying commands allow both absolute and relative file names
+as arguments. @value{GDBN} always converts the file name to an absolute file
+name and remembers it that way.
+
+@ifclear BARETARGET
+@cindex shared libraries
+@value{GDBN} supports SunOS, SVr4, Irix 5, and IBM RS/6000 shared libraries.
+@value{GDBN} automatically loads symbol definitions from shared libraries
+when you use the @code{run} command, or when you examine a core file.
+(Before you issue the @code{run} command, @value{GDBN} does not understand
+references to a function in a shared library, however---unless you are
+debugging a core file).
+@c FIXME: some @value{GDBN} release may permit some refs to undef
+@c FIXME...symbols---eg in a break cmd---assuming they are from a shared
+@c FIXME...lib; check this from time to time when updating manual
+
+@table @code
+@kindex info sharedlibrary
+@kindex info share
+@item info share
+@itemx info sharedlibrary
+Print the names of the shared libraries which are currently loaded.
+
+@kindex sharedlibrary
+@kindex share
+@item sharedlibrary @var{regex}
+@itemx share @var{regex}
+
+Load shared object library symbols for files matching a
+Unix regular expression.
+As with files loaded automatically, it only loads shared libraries
+required by your program for a core file or after typing @code{run}. If
+@var{regex} is omitted all shared libraries required by your program are
+loaded.
+@end table
+@end ifclear
+
+@node Symbol Errors
+@section Errors reading symbol files
+
+While reading a symbol file, @value{GDBN} occasionally encounters problems,
+such as symbol types it does not recognize, or known bugs in compiler
+output. By default, @value{GDBN} does not notify you of such problems, since
+they are relatively common and primarily of interest to people
+debugging compilers. If you are interested in seeing information
+about ill-constructed symbol tables, you can either ask @value{GDBN} to print
+only one message about each such type of problem, no matter how many
+times the problem occurs; or you can ask @value{GDBN} to print more messages,
+to see how many times the problems occur, with the @code{set
+complaints} command (@pxref{Messages/Warnings, ,Optional warnings and
+messages}).
+
+The messages currently printed, and their meanings, include:
+
+@table @code
+@item inner block not inside outer block in @var{symbol}
+
+The symbol information shows where symbol scopes begin and end
+(such as at the start of a function or a block of statements). This
+error indicates that an inner scope block is not fully contained
+in its outer scope blocks.
+
+@value{GDBN} circumvents the problem by treating the inner block as if it had
+the same scope as the outer block. In the error message, @var{symbol}
+may be shown as ``@code{(don't know)}'' if the outer block is not a
+function.
+
+@item block at @var{address} out of order
+
+The symbol information for symbol scope blocks should occur in
+order of increasing addresses. This error indicates that it does not
+do so.
+
+@value{GDBN} does not circumvent this problem, and has trouble
+locating symbols in the source file whose symbols it is reading. (You
+can often determine what source file is affected by specifying
+@code{set verbose on}. @xref{Messages/Warnings, ,Optional warnings and
+messages}.)
+
+@item bad block start address patched
+
+The symbol information for a symbol scope block has a start address
+smaller than the address of the preceding source line. This is known
+to occur in the SunOS 4.1.1 (and earlier) C compiler.
+
+@value{GDBN} circumvents the problem by treating the symbol scope block as
+starting on the previous source line.
+
+@item bad string table offset in symbol @var{n}
+
+@cindex foo
+Symbol number @var{n} contains a pointer into the string table which is
+larger than the size of the string table.
+
+@value{GDBN} circumvents the problem by considering the symbol to have the
+name @code{foo}, which may cause other problems if many symbols end up
+with this name.
+
+@item unknown symbol type @code{0x@var{nn}}
+
+The symbol information contains new data types that @value{GDBN} does not yet
+know how to read. @code{0x@var{nn}} is the symbol type of the misunderstood
+information, in hexadecimal.
+
+@value{GDBN} circumvents the error by ignoring this symbol information. This
+usually allows you to debug your program, though certain symbols
+are not accessible. If you encounter such a problem and feel like
+debugging it, you can debug @code{@value{GDBP}} with itself, breakpoint on
+@code{complain}, then go up to the function @code{read_dbx_symtab} and
+examine @code{*bufp} to see the symbol.
+
+@item stub type has NULL name
+@value{GDBN} could not find the full definition for
+@ifclear CONLY
+a struct or class.
+@end ifclear
+@ifset CONLY
+a struct.
+@end ifset
+
+@ifclear CONLY
+@item const/volatile indicator missing (ok if using g++ v1.x), got@dots{}
+
+The symbol information for a C++ member function is missing some
+information that recent versions of the compiler should have output
+for it.
+@end ifclear
+
+@item info mismatch between compiler and debugger
+
+@value{GDBN} could not parse a type specification output by the compiler.
+@end table
+
+@node Targets
+@chapter Specifying a Debugging Target
+@cindex debugging target
+@kindex target
+
+A @dfn{target} is the execution environment occupied by your program.
+@ifclear BARETARGET
+Often, @value{GDBN} runs in the same host environment as your program; in
+that case, the debugging target is specified as a side effect when you
+use the @code{file} or @code{core} commands. When you need more
+flexibility---for example, running @value{GDBN} on a physically separate
+host, or controlling a standalone system over a serial port or a
+realtime system over a TCP/IP connection---you
+@end ifclear
+@ifset BARETARGET
+You
+@end ifset
+can use the @code{target} command to specify one of the target types
+configured for @value{GDBN} (@pxref{Target Commands, ,Commands for managing
+targets}).
+
+@menu
+* Active Targets:: Active targets
+* Target Commands:: Commands for managing targets
+* Remote:: Remote debugging
+@end menu
+
+@node Active Targets
+@section Active targets
+@cindex stacking targets
+@cindex active targets
+@cindex multiple targets
+
+@ifclear BARETARGET
+There are three classes of targets: processes, core files, and
+executable files. @value{GDBN} can work concurrently on up to three active
+targets, one in each class. This allows you to (for example) start a
+process and inspect its activity without abandoning your work on a core
+file.
+
+For example, if you execute @samp{gdb a.out}, then the executable file
+@code{a.out} is the only active target. If you designate a core file as
+well---presumably from a prior run that crashed and coredumped---then
+@value{GDBN} has two active targets and uses them in tandem, looking
+first in the corefile target, then in the executable file, to satisfy
+requests for memory addresses. (Typically, these two classes of target
+are complementary, since core files contain only a program's
+read-write memory---variables and so on---plus machine status, while
+executable files contain only the program text and initialized data.)
+@end ifclear
+
+When you type @code{run}, your executable file becomes an active process
+target as well. When a process target is active, all @value{GDBN} commands
+requesting memory addresses refer to that target; addresses in an
+@ifclear BARETARGET
+active core file or
+@end ifclear
+executable file target are obscured while the process
+target is active.
+
+@ifset BARETARGET
+Use the @code{exec-file} command to select a
+new executable target (@pxref{Files, ,Commands to specify
+files}).
+@end ifset
+@ifclear BARETARGET
+Use the @code{core-file} and @code{exec-file} commands to select a
+new core file or executable target (@pxref{Files, ,Commands to specify
+files}). To specify as a target a process that is already running, use
+the @code{attach} command (@pxref{Attach, ,Debugging an
+already-running process}).
+@end ifclear
+
+@node Target Commands
+@section Commands for managing targets
+
+@table @code
+@item target @var{type} @var{parameters}
+Connects the @value{GDBN} host environment to a target
+@ifset BARETARGET
+machine.
+@end ifset
+@ifclear BARETARGET
+machine or process. A target is typically a protocol for talking to
+debugging facilities. You use the argument @var{type} to specify the
+type or protocol of the target machine.
+
+Further @var{parameters} are interpreted by the target protocol, but
+typically include things like device names or host names to connect
+with, process numbers, and baud rates.
+@end ifclear
+
+The @code{target} command does not repeat if you press @key{RET} again
+after executing the command.
+
+@kindex help target
+@item help target
+Displays the names of all targets available. To display targets
+currently selected, use either @code{info target} or @code{info files}
+(@pxref{Files, ,Commands to specify files}).
+
+@item help target @var{name}
+Describe a particular target, including any parameters necessary to
+select it.
+
+@kindex set gnutarget
+@item set gnutarget @var{args}
+@value{GDBN}uses its own library BFD to read your files. @value{GDBN}
+knows whether it is reading an @dfn{executable},
+a @dfn{core}, or a @dfn{.o} file, however you can specify the file format
+with the @code{set gnutarget} command. Unlike most @code{target} commands,
+with @code{gnutarget} the @code{target} refers to a program, not a machine.
+
+@emph{Warning:} To specify a file format with @code{set gnutarget},
+you must know the actual BFD name.
+
+@noindent @xref{Files, , Commands to specify files}.
+
+@kindex show gnutarget
+@item show gnutarget
+Use the @code{show gnutarget} command to display what file format
+@code{gnutarget} is set to read. If you have not set @code{gnutarget},
+@value{GDBN} will determine the file format for each file automatically
+and @code{show gnutarget} displays @code{The current BDF target is "auto"}.
+@end table
+
+Here are some common targets (available, or not, depending on the GDB
+configuration):
+
+@table @code
+@kindex target exec
+@item target exec @var{program}
+An executable file. @samp{target exec @var{program}} is the same as
+@samp{exec-file @var{program}}.
+
+@ifclear BARETARGET
+@kindex target core
+@item target core @var{filename}
+A core dump file. @samp{target core @var{filename}} is the same as
+@samp{core-file @var{filename}}.
+@end ifclear
+
+@ifset REMOTESTUB
+@kindex target remote
+@item target remote @var{dev}
+Remote serial target in GDB-specific protocol. The argument @var{dev}
+specifies what serial device to use for the connection (e.g.
+@file{/dev/ttya}). @xref{Remote, ,Remote debugging}. @code{target remote}
+now supports the @code{load} command. This is only useful if you have
+some other way of getting the stub to the target system, and you can put
+it somewhere in memory where it won't get clobbered by the download.
+@end ifset
+
+@ifset SIMS
+@kindex target sim
+@item target sim
+CPU simulator. @xref{Simulator,,Simulated CPU Target}.
+@end ifset
+
+@ifset AMD29K
+@kindex target udi
+@item target udi @var{keyword}
+Remote AMD29K target, using the AMD UDI protocol. The @var{keyword}
+argument specifies which 29K board or simulator to use. @xref{UDI29K
+Remote,,The UDI protocol for AMD29K}.
+
+@kindex target amd-eb
+@item target amd-eb @var{dev} @var{speed} @var{PROG}
+@cindex AMD EB29K
+Remote PC-resident AMD EB29K board, attached over serial lines.
+@var{dev} is the serial device, as for @code{target remote};
+@var{speed} allows you to specify the linespeed; and @var{PROG} is the
+name of the program to be debugged, as it appears to DOS on the PC.
+@xref{EB29K Remote, ,The EBMON protocol for AMD29K}.
+
+@end ifset
+@ifset H8
+@kindex target hms
+@item target hms @var{dev}
+A Hitachi SH, H8/300, or H8/500 board, attached via serial line to your host.
+@ifclear H8EXCLUSIVE
+Use special commands @code{device} and @code{speed} to control the serial
+line and the communications speed used.
+@end ifclear
+@xref{Hitachi Remote,,@value{GDBN} and Hitachi Microprocessors}.
+
+@end ifset
+@ifset I960
+@kindex target nindy
+@item target nindy @var{devicename}
+An Intel 960 board controlled by a Nindy Monitor. @var{devicename} is
+the name of the serial device to use for the connection, e.g.
+@file{/dev/ttya}. @xref{i960-Nindy Remote, ,@value{GDBN} with a remote i960 (Nindy)}.
+
+@end ifset
+@ifset ST2000
+@kindex target st2000
+@item target st2000 @var{dev} @var{speed}
+A Tandem ST2000 phone switch, running Tandem's STDBUG protocol. @var{dev}
+is the name of the device attached to the ST2000 serial line;
+@var{speed} is the communication line speed. The arguments are not used
+if @value{GDBN} is configured to connect to the ST2000 using TCP or Telnet.
+@xref{ST2000 Remote,,@value{GDBN} with a Tandem ST2000}.
+@end ifset
+
+@ifset VXWORKS
+@kindex target vxworks
+@item target vxworks @var{machinename}
+A VxWorks system, attached via TCP/IP. The argument @var{machinename}
+is the target system's machine name or IP address.
+@xref{VxWorks Remote, ,@value{GDBN} and VxWorks}.
+@end ifset
+
+@kindex target cpu32bug
+@item target cpu32bug @var{dev}
+CPU32BUG monitor, running on a CPU32 (M68K) board.
+
+@kindex target op50n
+@item target op50n @var{dev}
+OP50N monitor, running on an OKI HPPA board.
+
+@kindex target w89k
+@item target w89k @var{dev}
+W89K monitor, running on a Winbond HPPA board.
+
+@kindex target est
+@item target est @var{dev}
+EST-300 ICE monitor, running on a CPU32 (M68K) board.
+
+@kindex target rom68k
+@item target rom68k @var{dev}
+ROM 68K monitor, running on an IDP board.
+
+@kindex target array
+@item target array @var{dev}
+Array Tech LSI33K RAID controller board.
+
+@kindex target sparclite
+@item target sparclite @var{dev}
+Fujitsu sparclite boards, used only for the purpose of loading.
+You must use an additional command to debug the program.
+For example: target remote @var{dev} using @value{GDBN} standard
+remote protocol.
+@end table
+
+@ifset GENERIC
+Different targets are available on different configurations of @value{GDBN};
+your configuration may have more or fewer targets.
+@end ifset
+
+@section Choosing target byte order
+@cindex choosing target byte order
+@cindex target byte order
+@kindex set endian big
+@kindex set endian little
+@kindex set endian auto
+@kindex show endian
+
+You can now choose which byte order to use with a target system.
+Use the @code{set endian big} and @code{set endian little} commands.
+Use the @code{set endian auto} command to instruct
+@value{GDBN} to use the byte order associated with the executable.
+You can see the current setting for byte order with the @code{show endian}
+command.
+
+@emph{Warning:} Currently, only embedded MIPS configurations support
+dynamic selection of target byte order.
+
+@node Remote
+@section Remote debugging
+@cindex remote debugging
+
+If you are trying to debug a program running on a machine that cannot run
+@value{GDBN} in the usual way, it is often useful to use remote debugging.
+For example, you might use remote debugging on an operating system kernel,
+or on a small system which does not have a general purpose operating system
+powerful enough to run a full-featured debugger.
+
+Some configurations of @value{GDBN} have special serial or TCP/IP interfaces
+to make this work with particular debugging targets. In addition,
+@value{GDBN} comes with a generic serial protocol (specific to @value{GDBN},
+but not specific to any particular target system) which you can use if you
+write the remote stubs---the code that runs on the remote system to
+communicate with @value{GDBN}.
+
+Other remote targets may be available in your
+configuration of @value{GDBN}; use @code{help target} to list them.
+
+@ifset GENERIC
+@c Text on starting up GDB in various specific cases; it goes up front
+@c in manuals configured for any of those particular situations, here
+@c otherwise.
+@menu
+@ifset REMOTESTUB
+* Remote Serial:: @value{GDBN} remote serial protocol
+@end ifset
+@ifset I960
+* i960-Nindy Remote:: @value{GDBN} with a remote i960 (Nindy)
+@end ifset
+@ifset AMD29K
+* UDI29K Remote:: The UDI protocol for AMD29K
+* EB29K Remote:: The EBMON protocol for AMD29K
+@end ifset
+@ifset VXWORKS
+* VxWorks Remote:: @value{GDBN} and VxWorks
+@end ifset
+@ifset ST2000
+* ST2000 Remote:: @value{GDBN} with a Tandem ST2000
+@end ifset
+@ifset H8
+* Hitachi Remote:: @value{GDBN} and Hitachi Microprocessors
+@end ifset
+@ifset MIPS
+* MIPS Remote:: @value{GDBN} and MIPS boards
+@end ifset
+@ifset SIMS
+* Simulator:: Simulated CPU target
+@end ifset
+@end menu
+
+@include remote.texi
+@end ifset
+
+@node Controlling GDB
+@chapter Controlling @value{GDBN}
+
+You can alter the way @value{GDBN} interacts with you by using
+the @code{set} command. For commands controlling how @value{GDBN} displays
+data, @pxref{Print Settings, ,Print settings}; other settings are described
+here.
+
+@menu
+* Prompt:: Prompt
+* Editing:: Command editing
+* History:: Command history
+* Screen Size:: Screen size
+* Numbers:: Numbers
+* Messages/Warnings:: Optional warnings and messages
+@end menu
+
+@node Prompt
+@section Prompt
+
+@cindex prompt
+
+@value{GDBN} indicates its readiness to read a command by printing a string
+called the @dfn{prompt}. This string is normally @samp{(@value{GDBP})}. You
+can change the prompt string with the @code{set prompt} command. For
+instance, when debugging @value{GDBN} with @value{GDBN}, it is useful to change
+the prompt in one of the @value{GDBN} sessions so that you can always tell
+which one you are talking to.
+
+@emph{Note:} @code{set prompt} no longer adds a space for you after the
+prompt you set. This allows you to set a prompt which ends in a space
+or a prompt that does not.
+
+@table @code
+@kindex set prompt
+@item set prompt @var{newprompt}
+Directs @value{GDBN} to use @var{newprompt} as its prompt string henceforth.
+
+@kindex show prompt
+@item show prompt
+Prints a line of the form: @samp{Gdb's prompt is: @var{your-prompt}}
+@end table
+
+@node Editing
+@section Command editing
+@cindex readline
+@cindex command line editing
+
+@value{GDBN} reads its input commands via the @dfn{readline} interface. This
+@sc{gnu} library provides consistent behavior for programs which provide a
+command line interface to the user. Advantages are @sc{gnu} Emacs-style
+or @dfn{vi}-style inline editing of commands, @code{csh}-like history
+substitution, and a storage and recall of command history across
+debugging sessions.
+
+You may control the behavior of command line editing in @value{GDBN} with the
+command @code{set}.
+
+@table @code
+@kindex set editing
+@cindex editing
+@item set editing
+@itemx set editing on
+Enable command line editing (enabled by default).
+
+@item set editing off
+Disable command line editing.
+
+@kindex show editing
+@item show editing
+Show whether command line editing is enabled.
+@end table
+
+@node History
+@section Command history
+
+@value{GDBN} can keep track of the commands you type during your
+debugging sessions, so that you can be certain of precisely what
+happened. Use these commands to manage the @value{GDBN} command
+history facility.
+
+@table @code
+@cindex history substitution
+@cindex history file
+@kindex set history filename
+@kindex GDBHISTFILE
+@item set history filename @var{fname}
+Set the name of the @value{GDBN} command history file to @var{fname}.
+This is the file where @value{GDBN} reads an initial command history
+list, and where it writes the command history from this session when it
+exits. You can access this list through history expansion or through
+the history command editing characters listed below. This file defaults
+to the value of the environment variable @code{GDBHISTFILE}, or to
+@file{./.gdb_history} if this variable is not set.
+
+@cindex history save
+@kindex set history save
+@item set history save
+@itemx set history save on
+Record command history in a file, whose name may be specified with the
+@code{set history filename} command. By default, this option is disabled.
+
+@item set history save off
+Stop recording command history in a file.
+
+@cindex history size
+@kindex set history size
+@item set history size @var{size}
+Set the number of commands which @value{GDBN} keeps in its history list.
+This defaults to the value of the environment variable
+@code{HISTSIZE}, or to 256 if this variable is not set.
+@end table
+
+@cindex history expansion
+History expansion assigns special meaning to the character @kbd{!}.
+@ifset have-readline-appendices
+@xref{Event Designators}.
+@end ifset
+
+Since @kbd{!} is also the logical not operator in C, history expansion
+is off by default. If you decide to enable history expansion with the
+@code{set history expansion on} command, you may sometimes need to
+follow @kbd{!} (when it is used as logical not, in an expression) with
+a space or a tab to prevent it from being expanded. The readline
+history facilities do not attempt substitution on the strings
+@kbd{!=} and @kbd{!(}, even when history expansion is enabled.
+
+The commands to control history expansion are:
+
+@table @code
+@kindex set history expansion
+@item set history expansion on
+@itemx set history expansion
+Enable history expansion. History expansion is off by default.
+
+@item set history expansion off
+Disable history expansion.
+
+The readline code comes with more complete documentation of
+editing and history expansion features. Users unfamiliar with @sc{gnu} Emacs
+or @code{vi} may wish to read it.
+@ifset have-readline-appendices
+@xref{Command Line Editing}.
+@end ifset
+
+@c @group
+@kindex show history
+@item show history
+@itemx show history filename
+@itemx show history save
+@itemx show history size
+@itemx show history expansion
+These commands display the state of the @value{GDBN} history parameters.
+@code{show history} by itself displays all four states.
+@c @end group
+@end table
+
+@table @code
+@kindex show commands
+@item show commands
+Display the last ten commands in the command history.
+
+@item show commands @var{n}
+Print ten commands centered on command number @var{n}.
+
+@item show commands +
+Print ten commands just after the commands last printed.
+@end table
+
+@node Screen Size
+@section Screen size
+@cindex size of screen
+@cindex pauses in output
+
+Certain commands to @value{GDBN} may produce large amounts of
+information output to the screen. To help you read all of it,
+@value{GDBN} pauses and asks you for input at the end of each page of
+output. Type @key{RET} when you want to continue the output, or @kbd{q}
+to discard the remaining output. Also, the screen width setting
+determines when to wrap lines of output. Depending on what is being
+printed, @value{GDBN} tries to break the line at a readable place,
+rather than simply letting it overflow onto the following line.
+
+Normally @value{GDBN} knows the size of the screen from the termcap data base
+together with the value of the @code{TERM} environment variable and the
+@code{stty rows} and @code{stty cols} settings. If this is not correct,
+you can override it with the @code{set height} and @code{set
+width} commands:
+
+@table @code
+@kindex set height
+@kindex set width
+@kindex show width
+@kindex show height
+@item set height @var{lpp}
+@itemx show height
+@itemx set width @var{cpl}
+@itemx show width
+These @code{set} commands specify a screen height of @var{lpp} lines and
+a screen width of @var{cpl} characters. The associated @code{show}
+commands display the current settings.
+
+If you specify a height of zero lines, @value{GDBN} does not pause during
+output no matter how long the output is. This is useful if output is to a
+file or to an editor buffer.
+
+Likewise, you can specify @samp{set width 0} to prevent @value{GDBN}
+from wrapping its output.
+@end table
+
+@node Numbers
+@section Numbers
+@cindex number representation
+@cindex entering numbers
+
+You can always enter numbers in octal, decimal, or hexadecimal in @value{GDBN} by
+the usual conventions: octal numbers begin with @samp{0}, decimal
+numbers end with @samp{.}, and hexadecimal numbers begin with @samp{0x}.
+Numbers that begin with none of these are, by default, entered in base
+10; likewise, the default display for numbers---when no particular
+format is specified---is base 10. You can change the default base for
+both input and output with the @code{set radix} command.
+
+@table @code
+@kindex set input-radix
+@item set input-radix @var{base}
+Set the default base for numeric input. Supported choices
+for @var{base} are decimal 8, 10, or 16. @var{base} must itself be
+specified either unambiguously or using the current default radix; for
+example, any of
+
+@smallexample
+set radix 012
+set radix 10.
+set radix 0xa
+@end smallexample
+
+@noindent
+sets the base to decimal. On the other hand, @samp{set radix 10}
+leaves the radix unchanged no matter what it was.
+
+@kindex set output-radix
+@item set output-radix @var{base}
+Set the default base for numeric display. Supported choices
+for @var{base} are decimal 8, 10, or 16. @var{base} must itself be
+specified either unambiguously or using the current default radix.
+
+@kindex show input-radix
+@item show input-radix
+Display the current default base for numeric input.
+
+@kindex show output-radix
+@item show output-radix
+Display the current default base for numeric display.
+@end table
+
+@node Messages/Warnings
+@section Optional warnings and messages
+
+By default, @value{GDBN} is silent about its inner workings. If you are running
+on a slow machine, you may want to use the @code{set verbose} command.
+This makes @value{GDBN} tell you when it does a lengthy internal operation, so
+you will not think it has crashed.
+
+Currently, the messages controlled by @code{set verbose} are those
+which announce that the symbol table for a source file is being read;
+see @code{symbol-file} in @ref{Files, ,Commands to specify files}.
+
+@table @code
+@kindex set verbose
+@item set verbose on
+Enables @value{GDBN} output of certain informational messages.
+
+@item set verbose off
+Disables @value{GDBN} output of certain informational messages.
+
+@kindex show verbose
+@item show verbose
+Displays whether @code{set verbose} is on or off.
+@end table
+
+By default, if @value{GDBN} encounters bugs in the symbol table of an object
+file, it is silent; but if you are debugging a compiler, you may find
+this information useful (@pxref{Symbol Errors, ,Errors reading symbol files}).
+
+@table @code
+@kindex set complaints
+@item set complaints @var{limit}
+Permits @value{GDBN} to output @var{limit} complaints about each type of unusual
+symbols before becoming silent about the problem. Set @var{limit} to
+zero to suppress all complaints; set it to a large number to prevent
+complaints from being suppressed.
+
+@kindex show complaints
+@item show complaints
+Displays how many symbol complaints @value{GDBN} is permitted to produce.
+@end table
+
+By default, @value{GDBN} is cautious, and asks what sometimes seems to be a
+lot of stupid questions to confirm certain commands. For example, if
+you try to run a program which is already running:
+
+@example
+(@value{GDBP}) run
+The program being debugged has been started already.
+Start it from the beginning? (y or n)
+@end example
+
+If you are willing to unflinchingly face the consequences of your own
+commands, you can disable this ``feature'':
+
+@table @code
+@kindex set confirm
+@cindex flinching
+@cindex confirmation
+@cindex stupid questions
+@item set confirm off
+Disables confirmation requests.
+
+@item set confirm on
+Enables confirmation requests (the default).
+
+@kindex show confirm
+@item show confirm
+Displays state of confirmation requests.
+@end table
+
+@node Sequences
+@chapter Canned Sequences of Commands
+
+Aside from breakpoint commands (@pxref{Break Commands, ,Breakpoint
+command lists}), @value{GDBN} provides two ways to store sequences of commands
+for execution as a unit: user-defined commands and command files.
+
+@menu
+* Define:: User-defined commands
+* Hooks:: User-defined command hooks
+* Command Files:: Command files
+* Output:: Commands for controlled output
+@end menu
+
+@node Define
+@section User-defined commands
+
+@cindex user-defined command
+A @dfn{user-defined command} is a sequence of @value{GDBN} commands to which
+you assign a new name as a command. This is done with the @code{define}
+command. User commands may accept up to 10 arguments separated by whitespace.
+Arguments are accessed within the user command via @var{$arg0@dots{}$arg9}.
+A trivial example:
+
+@smallexample
+define adder
+ print $arg0 + $arg1 + $arg2
+@end smallexample
+
+@noindent To execute the command use:
+
+@smallexample
+adder 1 2 3
+@end smallexample
+
+@noindent This defines the command @code{adder}, which prints the sum of
+its three arguments. Note the arguments are text substitutions, so they may
+reference variables, use complex expressions, or even perform inferior
+functions calls.
+
+@table @code
+@kindex define
+@item define @var{commandname}
+Define a command named @var{commandname}. If there is already a command
+by that name, you are asked to confirm that you want to redefine it.
+
+The definition of the command is made up of other @value{GDBN} command lines,
+which are given following the @code{define} command. The end of these
+commands is marked by a line containing @code{end}.
+
+@kindex if
+@kindex else
+@item if
+Takes a single argument, which is an expression to evaluate.
+It is followed by a series of commands that are executed
+only if the expression is true (nonzero).
+There can then optionally be a line @code{else}, followed
+by a series of commands that are only executed if the expression
+was false. The end of the list is marked by a line containing @code{end}.
+
+@kindex while
+@item while
+The syntax is similar to @code{if}: the command takes a single argument,
+which is an expression to evaluate, and must be followed by the commands to
+execute, one per line, terminated by an @code{end}.
+The commands are executed repeatedly as long as the expression
+evaluates to true.
+
+@kindex document
+@item document @var{commandname}
+Document the user-defined command @var{commandname}, so that it can be
+accessed by @code{help}. The command @var{commandname} must already be
+defined. This command reads lines of documentation just as @code{define}
+reads the lines of the command definition, ending with @code{end}.
+After the @code{document} command is finished, @code{help} on command
+@var{commandname} displays the documentation you have written.
+
+You may use the @code{document} command again to change the
+documentation of a command. Redefining the command with @code{define}
+does not change the documentation.
+
+@kindex help user-defined
+@item help user-defined
+List all user-defined commands, with the first line of the documentation
+(if any) for each.
+
+@kindex show user
+@item show user
+@itemx show user @var{commandname}
+Display the @value{GDBN} commands used to define @var{commandname} (but not its
+documentation). If no @var{commandname} is given, display the
+definitions for all user-defined commands.
+@end table
+
+When user-defined commands are executed, the
+commands of the definition are not printed. An error in any command
+stops execution of the user-defined command.
+
+If used interactively, commands that would ask for confirmation proceed
+without asking when used inside a user-defined command. Many @value{GDBN}
+commands that normally print messages to say what they are doing omit the
+messages when used in a user-defined command.
+
+@node Hooks
+@section User-defined command hooks
+@cindex command files
+
+You may define @emph{hooks}, which are a special kind of user-defined
+command. Whenever you run the command @samp{foo}, if the user-defined
+command @samp{hook-foo} exists, it is executed (with no arguments)
+before that command.
+
+In addition, a pseudo-command, @samp{stop} exists. Defining
+(@samp{hook-stop}) makes the associated commands execute every time
+execution stops in your program: before breakpoint commands are run,
+displays are printed, or the stack frame is printed.
+
+@ifclear BARETARGET
+For example, to ignore @code{SIGALRM} signals while
+single-stepping, but treat them normally during normal execution,
+you could define:
+
+@example
+define hook-stop
+handle SIGALRM nopass
+end
+
+define hook-run
+handle SIGALRM pass
+end
+
+define hook-continue
+handle SIGLARM pass
+end
+@end example
+@end ifclear
+
+You can define a hook for any single-word command in @value{GDBN}, but
+not for command aliases; you should define a hook for the basic command
+name, e.g. @code{backtrace} rather than @code{bt}.
+@c FIXME! So how does Joe User discover whether a command is an alias
+@c or not?
+If an error occurs during the execution of your hook, execution of
+@value{GDBN} commands stops and @value{GDBN} issues a prompt
+(before the command that you actually typed had a chance to run).
+
+If you try to define a hook which does not match any known command, you
+get a warning from the @code{define} command.
+
+@node Command Files
+@section Command files
+
+@cindex command files
+A command file for @value{GDBN} is a file of lines that are @value{GDBN}
+commands. Comments (lines starting with @kbd{#}) may also be included.
+An empty line in a command file does nothing; it does not mean to repeat
+the last command, as it would from the terminal.
+
+@cindex init file
+@cindex @file{@value{GDBINIT}}
+When you start @value{GDBN}, it automatically executes commands from its
+@dfn{init files}. These are files named @file{@value{GDBINIT}}.
+@value{GDBN} reads the init file (if any) in your home directory, then
+processes command line options and operands, and then reads the init
+file (if any) in the current working directory. This is so the init
+file in your home directory can set options (such as @code{set
+complaints}) which affect the processing of the command line options and
+operands. The init files are not executed if you use the @samp{-nx}
+option; @pxref{Mode Options, ,Choosing modes}.
+
+@ifset GENERIC
+@cindex init file name
+On some configurations of @value{GDBN}, the init file is known by a
+different name (these are typically environments where a specialized
+form of @value{GDBN} may need to coexist with other forms,
+hence a different name
+for the specialized version's init file). These are the environments
+with special init file names:
+
+@kindex .vxgdbinit
+@itemize @bullet
+@item
+VxWorks (Wind River Systems real-time OS): @samp{.vxgdbinit}
+
+@kindex .os68gdbinit
+@item
+OS68K (Enea Data Systems real-time OS): @samp{.os68gdbinit}
+
+@kindex .esgdbinit
+@item
+ES-1800 (Ericsson Telecom AB M68000 emulator): @samp{.esgdbinit}
+@end itemize
+@end ifset
+
+You can also request the execution of a command file with the
+@code{source} command:
+
+@table @code
+@kindex source
+@item source @var{filename}
+Execute the command file @var{filename}.
+@end table
+
+The lines in a command file are executed sequentially. They are not
+printed as they are executed. An error in any command terminates execution
+of the command file.
+
+Commands that would ask for confirmation if used interactively proceed
+without asking when used in a command file. Many @value{GDBN} commands that
+normally print messages to say what they are doing omit the messages
+when called from command files.
+
+@node Output
+@section Commands for controlled output
+
+During the execution of a command file or a user-defined command, normal
+@value{GDBN} output is suppressed; the only output that appears is what is
+explicitly printed by the commands in the definition. This section
+describes three commands useful for generating exactly the output you
+want.
+
+@table @code
+@kindex echo
+@item echo @var{text}
+@c I do not consider backslash-space a standard C escape sequence
+@c because it is not in ANSI.
+Print @var{text}. Nonprinting characters can be included in
+@var{text} using C escape sequences, such as @samp{\n} to print a
+newline. @strong{No newline is printed unless you specify one.}
+In addition to the standard C escape sequences, a backslash followed
+by a space stands for a space. This is useful for displaying a
+string with spaces at the beginning or the end, since leading and
+trailing spaces are otherwise trimmed from all arguments.
+To print @samp{@w{ }and foo =@w{ }}, use the command
+@samp{echo \@w{ }and foo = \@w{ }}.
+
+A backslash at the end of @var{text} can be used, as in C, to continue
+the command onto subsequent lines. For example,
+
+@example
+echo This is some text\n\
+which is continued\n\
+onto several lines.\n
+@end example
+
+produces the same output as
+
+@example
+echo This is some text\n
+echo which is continued\n
+echo onto several lines.\n
+@end example
+
+@kindex output
+@item output @var{expression}
+Print the value of @var{expression} and nothing but that value: no
+newlines, no @samp{$@var{nn} = }. The value is not entered in the
+value history either. @xref{Expressions, ,Expressions}, for more information
+on expressions.
+
+@item output/@var{fmt} @var{expression}
+Print the value of @var{expression} in format @var{fmt}. You can use
+the same formats as for @code{print}. @xref{Output Formats,,Output
+formats}, for more information.
+
+@kindex printf
+@item printf @var{string}, @var{expressions}@dots{}
+Print the values of the @var{expressions} under the control of
+@var{string}. The @var{expressions} are separated by commas and may be
+either numbers or pointers. Their values are printed as specified by
+@var{string}, exactly as if your program were to execute the C
+subroutine
+
+@example
+printf (@var{string}, @var{expressions}@dots{});
+@end example
+
+For example, you can print two values in hex like this:
+
+@smallexample
+printf "foo, bar-foo = 0x%x, 0x%x\n", foo, bar-foo
+@end smallexample
+
+The only backslash-escape sequences that you can use in the format
+string are the simple ones that consist of backslash followed by a
+letter.
+@end table
+
+@ifclear DOSHOST
+@node Emacs
+@chapter Using @value{GDBN} under @sc{gnu} Emacs
+
+@cindex Emacs
+@cindex @sc{gnu} Emacs
+A special interface allows you to use @sc{gnu} Emacs to view (and
+edit) the source files for the program you are debugging with
+@value{GDBN}.
+
+To use this interface, use the command @kbd{M-x gdb} in Emacs. Give the
+executable file you want to debug as an argument. This command starts
+@value{GDBN} as a subprocess of Emacs, with input and output through a newly
+created Emacs buffer.
+
+Using @value{GDBN} under Emacs is just like using @value{GDBN} normally except for two
+things:
+
+@itemize @bullet
+@item
+All ``terminal'' input and output goes through the Emacs buffer.
+@end itemize
+
+This applies both to @value{GDBN} commands and their output, and to the input
+and output done by the program you are debugging.
+
+This is useful because it means that you can copy the text of previous
+commands and input them again; you can even use parts of the output
+in this way.
+
+All the facilities of Emacs' Shell mode are available for interacting
+with your program. In particular, you can send signals the usual
+way---for example, @kbd{C-c C-c} for an interrupt, @kbd{C-c C-z} for a
+stop.
+
+@itemize @bullet
+@item
+@value{GDBN} displays source code through Emacs.
+@end itemize
+
+Each time @value{GDBN} displays a stack frame, Emacs automatically finds the
+source file for that frame and puts an arrow (@samp{=>}) at the
+left margin of the current line. Emacs uses a separate buffer for
+source display, and splits the screen to show both your @value{GDBN} session
+and the source.
+
+Explicit @value{GDBN} @code{list} or search commands still produce output as
+usual, but you probably have no reason to use them from Emacs.
+
+@quotation
+@emph{Warning:} If the directory where your program resides is not your
+current directory, it can be easy to confuse Emacs about the location of
+the source files, in which case the auxiliary display buffer does not
+appear to show your source. @value{GDBN} can find programs by searching your
+environment's @code{PATH} variable, so the @value{GDBN} input and output
+session proceeds normally; but Emacs does not get enough information
+back from @value{GDBN} to locate the source files in this situation. To
+avoid this problem, either start @value{GDBN} mode from the directory where
+your program resides, or specify an absolute file name when prompted for the
+@kbd{M-x gdb} argument.
+
+A similar confusion can result if you use the @value{GDBN} @code{file} command to
+switch to debugging a program in some other location, from an existing
+@value{GDBN} buffer in Emacs.
+@end quotation
+
+By default, @kbd{M-x gdb} calls the program called @file{gdb}. If
+you need to call @value{GDBN} by a different name (for example, if you keep
+several configurations around, with different names) you can set the
+Emacs variable @code{gdb-command-name}; for example,
+
+@example
+(setq gdb-command-name "mygdb")
+@end example
+
+@noindent
+(preceded by @kbd{ESC ESC}, or typed in the @code{*scratch*} buffer, or
+in your @file{.emacs} file) makes Emacs call the program named
+``@code{mygdb}'' instead.
+
+In the @value{GDBN} I/O buffer, you can use these special Emacs commands in
+addition to the standard Shell mode commands:
+
+@table @kbd
+@item C-h m
+Describe the features of Emacs' @value{GDBN} Mode.
+
+@item M-s
+Execute to another source line, like the @value{GDBN} @code{step} command; also
+update the display window to show the current file and location.
+
+@item M-n
+Execute to next source line in this function, skipping all function
+calls, like the @value{GDBN} @code{next} command. Then update the display window
+to show the current file and location.
+
+@item M-i
+Execute one instruction, like the @value{GDBN} @code{stepi} command; update
+display window accordingly.
+
+@item M-x gdb-nexti
+Execute to next instruction, using the @value{GDBN} @code{nexti} command; update
+display window accordingly.
+
+@item C-c C-f
+Execute until exit from the selected stack frame, like the @value{GDBN}
+@code{finish} command.
+
+@item M-c
+Continue execution of your program, like the @value{GDBN} @code{continue}
+command.
+
+@emph{Warning:} In Emacs v19, this command is @kbd{C-c C-p}.
+
+@item M-u
+Go up the number of frames indicated by the numeric argument
+(@pxref{Arguments, , Numeric Arguments, Emacs, The @sc{gnu} Emacs Manual}),
+like the @value{GDBN} @code{up} command.
+
+@emph{Warning:} In Emacs v19, this command is @kbd{C-c C-u}.
+
+@item M-d
+Go down the number of frames indicated by the numeric argument, like the
+@value{GDBN} @code{down} command.
+
+@emph{Warning:} In Emacs v19, this command is @kbd{C-c C-d}.
+
+@item C-x &
+Read the number where the cursor is positioned, and insert it at the end
+of the @value{GDBN} I/O buffer. For example, if you wish to disassemble code
+around an address that was displayed earlier, type @kbd{disassemble};
+then move the cursor to the address display, and pick up the
+argument for @code{disassemble} by typing @kbd{C-x &}.
+
+You can customize this further by defining elements of the list
+@code{gdb-print-command}; once it is defined, you can format or
+otherwise process numbers picked up by @kbd{C-x &} before they are
+inserted. A numeric argument to @kbd{C-x &} indicates that you
+wish special formatting, and also acts as an index to pick an element of the
+list. If the list element is a string, the number to be inserted is
+formatted using the Emacs function @code{format}; otherwise the number
+is passed as an argument to the corresponding list element.
+@end table
+
+In any source file, the Emacs command @kbd{C-x SPC} (@code{gdb-break})
+tells @value{GDBN} to set a breakpoint on the source line point is on.
+
+If you accidentally delete the source-display buffer, an easy way to get
+it back is to type the command @code{f} in the @value{GDBN} buffer, to
+request a frame display; when you run under Emacs, this recreates
+the source buffer if necessary to show you the context of the current
+frame.
+
+The source files displayed in Emacs are in ordinary Emacs buffers
+which are visiting the source files in the usual way. You can edit
+the files with these buffers if you wish; but keep in mind that @value{GDBN}
+communicates with Emacs in terms of line numbers. If you add or
+delete lines from the text, the line numbers that @value{GDBN} knows cease
+to correspond properly with the code.
+
+@c The following dropped because Epoch is nonstandard. Reactivate
+@c if/when v19 does something similar. ---doc@cygnus.com 19dec1990
+@ignore
+@kindex Emacs Epoch environment
+@kindex Epoch
+@kindex inspect
+
+Version 18 of @sc{gnu} Emacs has a built-in window system
+called the @code{epoch}
+environment. Users of this environment can use a new command,
+@code{inspect} which performs identically to @code{print} except that
+each value is printed in its own window.
+@end ignore
+@end ifclear
+
+@ifset LUCID
+@node Energize
+@chapter Using @value{GDBN} with Energize
+
+@cindex Energize
+The Energize Programming System is an integrated development environment
+that includes a point-and-click interface to many programming tools.
+When you use @value{GDBN} in this environment, you can use the standard
+Energize graphical interface to drive @value{GDBN}; you can also, if you
+choose, type @value{GDBN} commands as usual in a debugging window. Even if
+you use the graphical interface, the debugging window (which uses Emacs,
+and resembles the standard @sc{gnu} Emacs interface to
+@value{GDBN}) displays the
+equivalent commands, so that the history of your debugging session is
+properly reflected.
+
+When Energize starts up a @value{GDBN} session, it uses one of the
+command-line options @samp{-energize} or @samp{-cadillac} (``cadillac''
+is the name of the communications protocol used by the Energize system).
+This option makes @value{GDBN} run as one of the tools in the Energize Tool
+Set: it sends all output to the Energize kernel, and accept input from
+it as well.
+
+See the user manual for the Energize Programming System for
+information on how to use the Energize graphical interface and the other
+development tools that Energize integrates with @value{GDBN}.
+
+@end ifset
+
+@node GDB Bugs
+@chapter Reporting Bugs in @value{GDBN}
+@cindex bugs in @value{GDBN}
+@cindex reporting bugs in @value{GDBN}
+
+Your bug reports play an essential role in making @value{GDBN} reliable.
+
+Reporting a bug may help you by bringing a solution to your problem, or it
+may not. But in any case the principal function of a bug report is to help
+the entire community by making the next version of @value{GDBN} work better. Bug
+reports are your contribution to the maintenance of @value{GDBN}.
+
+In order for a bug report to serve its purpose, you must include the
+information that enables us to fix the bug.
+
+@menu
+* Bug Criteria:: Have you found a bug?
+* Bug Reporting:: How to report bugs
+@end menu
+
+@node Bug Criteria
+@section Have you found a bug?
+@cindex bug criteria
+
+If you are not sure whether you have found a bug, here are some guidelines:
+
+@itemize @bullet
+@cindex fatal signal
+@cindex debugger crash
+@cindex crash of debugger
+@item
+If the debugger gets a fatal signal, for any input whatever, that is a
+@value{GDBN} bug. Reliable debuggers never crash.
+
+@cindex error on valid input
+@item
+If @value{GDBN} produces an error message for valid input, that is a bug.
+
+@cindex invalid input
+@item
+If @value{GDBN} does not produce an error message for invalid input,
+that is a bug. However, you should note that your idea of
+``invalid input'' might be our idea of ``an extension'' or ``support
+for traditional practice''.
+
+@item
+If you are an experienced user of debugging tools, your suggestions
+for improvement of @value{GDBN} are welcome in any case.
+@end itemize
+
+@node Bug Reporting
+@section How to report bugs
+@cindex bug reports
+@cindex @value{GDBN} bugs, reporting
+
+A number of companies and individuals offer support for @sc{gnu} products.
+If you obtained @value{GDBN} from a support organization, we recommend you
+contact that organization first.
+
+You can find contact information for many support companies and
+individuals in the file @file{etc/SERVICE} in the @sc{gnu} Emacs
+distribution.
+
+In any event, we also recommend that you send bug reports for @value{GDBN} to one
+of these addresses:
+
+@example
+bug-gdb@@prep.ai.mit.edu
+@{ucbvax|mit-eddie|uunet@}!prep.ai.mit.edu!bug-gdb
+@end example
+
+@strong{Do not send bug reports to @samp{info-gdb}, or to
+@samp{help-gdb}, or to any newsgroups.} Most users of @value{GDBN} do not want to
+receive bug reports. Those that do have arranged to receive @samp{bug-gdb}.
+
+The mailing list @samp{bug-gdb} has a newsgroup @samp{gnu.gdb.bug} which
+serves as a repeater. The mailing list and the newsgroup carry exactly
+the same messages. Often people think of posting bug reports to the
+newsgroup instead of mailing them. This appears to work, but it has one
+problem which can be crucial: a newsgroup posting often lacks a mail
+path back to the sender. Thus, if we need to ask for more information,
+we may be unable to reach you. For this reason, it is better to send
+bug reports to the mailing list.
+
+As a last resort, send bug reports on paper to:
+
+@example
+@sc{gnu} Debugger Bugs
+Free Software Foundation Inc.
+59 Temple Place - Suite 330
+Boston, MA 02111-1307
+USA
+@end example
+
+The fundamental principle of reporting bugs usefully is this:
+@strong{report all the facts}. If you are not sure whether to state a
+fact or leave it out, state it!
+
+Often people omit facts because they think they know what causes the
+problem and assume that some details do not matter. Thus, you might
+assume that the name of the variable you use in an example does not matter.
+Well, probably it does not, but one cannot be sure. Perhaps the bug is a
+stray memory reference which happens to fetch from the location where that
+name is stored in memory; perhaps, if the name were different, the contents
+of that location would fool the debugger into doing the right thing despite
+the bug. Play it safe and give a specific, complete example. That is the
+easiest thing for you to do, and the most helpful.
+
+Keep in mind that the purpose of a bug report is to enable us to fix
+the bug if it is new to us.
+@c
+@c FIX ME!!--What the heck does the following sentence mean,
+@c in the context of the one above?
+@c
+@c It is not as important as what happens if the bug is already known.
+@c
+Therefore, always write your bug reports on
+the assumption that the bug has not been reported previously.
+
+Sometimes people give a few sketchy facts and ask, ``Does this ring a
+bell?'' Those bug reports are useless, and we urge everyone to
+@emph{refuse to respond to them} except to chide the sender to report
+bugs properly.
+
+To enable us to fix the bug, you should include all these things:
+
+@itemize @bullet
+@item
+The version of @value{GDBN}. @value{GDBN} announces it if you start with no
+arguments; you can also print it at any time using @code{show version}.
+
+Without this, we will not know whether there is any point in looking for
+the bug in the current version of @value{GDBN}.
+
+@item
+The type of machine you are using, and the operating system name and
+version number.
+
+@item
+What compiler (and its version) was used to compile @value{GDBN}---e.g.
+``@value{GCC}--2.0''.
+
+@item
+What compiler (and its version) was used to compile the program you
+are debugging---e.g. ``@value{GCC}--2.0''.
+
+@item
+The command arguments you gave the compiler to compile your example and
+observe the bug. For example, did you use @samp{-O}? To guarantee
+you will not omit something important, list them all. A copy of the
+Makefile (or the output from make) is sufficient.
+
+If we were to try to guess the arguments, we would probably guess wrong
+and then we might not encounter the bug.
+
+@item
+A complete input script, and all necessary source files, that will
+reproduce the bug.
+
+@item
+A description of what behavior you observe that you believe is
+incorrect. For example, ``It gets a fatal signal.''
+
+Of course, if the bug is that @value{GDBN} gets a fatal signal, then we will
+certainly notice it. But if the bug is incorrect output, we might not
+notice unless it is glaringly wrong. You might as well not give us a
+chance to make a mistake.
+
+Even if the problem you experience is a fatal signal, you should still
+say so explicitly. Suppose something strange is going on, such as,
+your copy of @value{GDBN} is out of synch, or you have encountered a
+bug in the C library on your system. (This has happened!) Your copy
+might crash and ours would not. If you told us to expect a crash,
+then when ours fails to crash, we would know that the bug was not
+happening for us. If you had not told us to expect a crash, then we
+would not be able to draw any conclusion from our observations.
+
+@item
+If you wish to suggest changes to the @value{GDBN} source, send us context
+diffs. If you even discuss something in the @value{GDBN} source, refer to
+it by context, not by line number.
+
+The line numbers in our development sources will not match those in your
+sources. Your line numbers would convey no useful information to us.
+@end itemize
+
+Here are some things that are not necessary:
+
+@itemize @bullet
+@item
+A description of the envelope of the bug.
+
+Often people who encounter a bug spend a lot of time investigating
+which changes to the input file will make the bug go away and which
+changes will not affect it.
+
+This is often time consuming and not very useful, because the way we
+will find the bug is by running a single example under the debugger
+with breakpoints, not by pure deduction from a series of examples.
+We recommend that you save your time for something else.
+
+Of course, if you can find a simpler example to report @emph{instead}
+of the original one, that is a convenience for us. Errors in the
+output will be easier to spot, running under the debugger will take
+less time, and so on.
+
+However, simplification is not vital; if you do not want to do this,
+report the bug anyway and send us the entire test case you used.
+
+@item
+A patch for the bug.
+
+A patch for the bug does help us if it is a good one. But do not omit
+the necessary information, such as the test case, on the assumption that
+a patch is all we need. We might see problems with your patch and decide
+to fix the problem another way, or we might not understand it at all.
+
+Sometimes with a program as complicated as @value{GDBN} it is very hard to
+construct an example that will make the program follow a certain path
+through the code. If you do not send us the example, we will not be able
+to construct one, so we will not be able to verify that the bug is fixed.
+
+And if we cannot understand what bug you are trying to fix, or why your
+patch should be an improvement, we will not install it. A test case will
+help us to understand.
+
+@item
+A guess about what the bug is or what it depends on.
+
+Such guesses are usually wrong. Even we cannot guess right about such
+things without first using the debugger to find the facts.
+@end itemize
+
+@c The readline documentation is distributed with the readline code
+@c and consists of the two following files:
+@c rluser.texinfo
+@c inc-hist.texi
+@c Use -I with makeinfo to point to the appropriate directory,
+@c environment var TEXINPUTS with TeX.
+@include rluser.texinfo
+@include inc-hist.texi
+
+@ifset NOVEL
+@ifset RENAMED
+@node Renamed Commands
+@appendix Renamed Commands
+
+The following commands were renamed in @value{GDBN} 4, in order to make the
+command set as a whole more consistent and easier to use and remember:
+
+@kindex add-syms
+@kindex delete environment
+@kindex info copying
+@kindex info convenience
+@kindex info directories
+@kindex info editing
+@kindex info history
+@kindex info targets
+@kindex info values
+@kindex info version
+@kindex info warranty
+@kindex set addressprint
+@kindex set arrayprint
+@kindex set prettyprint
+@kindex set screen-height
+@kindex set screen-width
+@kindex set unionprint
+@kindex set vtblprint
+@kindex set demangle
+@kindex set asm-demangle
+@kindex set sevenbit-strings
+@kindex set array-max
+@kindex set caution
+@kindex set history write
+@kindex show addressprint
+@kindex show arrayprint
+@kindex show prettyprint
+@kindex show screen-height
+@kindex show screen-width
+@kindex show unionprint
+@kindex show vtblprint
+@kindex show demangle
+@kindex show asm-demangle
+@kindex show sevenbit-strings
+@kindex show array-max
+@kindex show caution
+@kindex show history write
+@kindex unset
+
+@c TEXI2ROFF-KILL
+@ifinfo
+@c END TEXI2ROFF-KILL
+@example
+OLD COMMAND NEW COMMAND
+@c TEXI2ROFF-KILL
+--------------- -------------------------------
+@c END TEXI2ROFF-KILL
+add-syms add-symbol-file
+delete environment unset environment
+info convenience show convenience
+info copying show copying
+info directories show directories
+info editing show commands
+info history show values
+info targets help target
+info values show values
+info version show version
+info warranty show warranty
+set/show addressprint set/show print address
+set/show array-max set/show print elements
+set/show arrayprint set/show print array
+set/show asm-demangle set/show print asm-demangle
+set/show caution set/show confirm
+set/show demangle set/show print demangle
+set/show history write set/show history save
+set/show prettyprint set/show print pretty
+set/show screen-height set/show height
+set/show screen-width set/show width
+set/show sevenbit-strings set/show print sevenbit-strings
+set/show unionprint set/show print union
+set/show vtblprint set/show print vtbl
+
+unset [No longer an alias for delete]
+@end example
+@c TEXI2ROFF-KILL
+@end ifinfo
+
+@tex
+\vskip \parskip\vskip \baselineskip
+\halign{\tt #\hfil &\qquad#&\tt #\hfil\cr
+{\bf Old Command} &&{\bf New Command}\cr
+add-syms &&add-symbol-file\cr
+delete environment &&unset environment\cr
+info convenience &&show convenience\cr
+info copying &&show copying\cr
+info directories &&show directories \cr
+info editing &&show commands\cr
+info history &&show values\cr
+info targets &&help target\cr
+info values &&show values\cr
+info version &&show version\cr
+info warranty &&show warranty\cr
+set{\rm / }show addressprint &&set{\rm / }show print address\cr
+set{\rm / }show array-max &&set{\rm / }show print elements\cr
+set{\rm / }show arrayprint &&set{\rm / }show print array\cr
+set{\rm / }show asm-demangle &&set{\rm / }show print asm-demangle\cr
+set{\rm / }show caution &&set{\rm / }show confirm\cr
+set{\rm / }show demangle &&set{\rm / }show print demangle\cr
+set{\rm / }show history write &&set{\rm / }show history save\cr
+set{\rm / }show prettyprint &&set{\rm / }show print pretty\cr
+set{\rm / }show screen-height &&set{\rm / }show height\cr
+set{\rm / }show screen-width &&set{\rm / }show width\cr
+set{\rm / }show sevenbit-strings &&set{\rm / }show print sevenbit-strings\cr
+set{\rm / }show unionprint &&set{\rm / }show print union\cr
+set{\rm / }show vtblprint &&set{\rm / }show print vtbl\cr
+\cr
+unset &&\rm(No longer an alias for delete)\cr
+}
+@end tex
+@c END TEXI2ROFF-KILL
+@end ifset
+@end ifset
+
+@ifclear PRECONFIGURED
+@node Formatting Documentation
+@appendix Formatting Documentation
+
+@cindex @value{GDBN} reference card
+@cindex reference card
+The @value{GDBN} 4 release includes an already-formatted reference card, ready
+for printing with PostScript or Ghostscript, in the @file{gdb}
+subdirectory of the main source directory@footnote{In
+@file{gdb-@value{GDBVN}/gdb/refcard.ps} of the version @value{GDBVN}
+release.}. If you can use PostScript or Ghostscript with your printer,
+you can print the reference card immediately with @file{refcard.ps}.
+
+The release also includes the source for the reference card. You
+can format it, using @TeX{}, by typing:
+
+@example
+make refcard.dvi
+@end example
+
+The @value{GDBN} reference card is designed to print in @dfn{landscape}
+mode on US ``letter'' size paper;
+that is, on a sheet 11 inches wide by 8.5 inches
+high. You will need to specify this form of printing as an option to
+your @sc{dvi} output program.
+
+@cindex documentation
+
+All the documentation for @value{GDBN} comes as part of the machine-readable
+distribution. The documentation is written in Texinfo format, which is
+a documentation system that uses a single source file to produce both
+on-line information and a printed manual. You can use one of the Info
+formatting commands to create the on-line version of the documentation
+and @TeX{} (or @code{texi2roff}) to typeset the printed version.
+
+@value{GDBN} includes an already formatted copy of the on-line Info version of
+this manual in the @file{gdb} subdirectory. The main Info file is
+@file{gdb-@r{version-number}/gdb/gdb.info}, and it refers to
+subordinate files matching @samp{gdb.info*} in the same directory. If
+necessary, you can print out these files, or read them with any editor;
+but they are easier to read using the @code{info} subsystem in @sc{gnu} Emacs
+or the standalone @code{info} program, available as part of the @sc{gnu}
+Texinfo distribution.
+
+If you want to format these Info files yourself, you need one of the
+Info formatting programs, such as @code{texinfo-format-buffer} or
+@code{makeinfo}.
+
+If you have @code{makeinfo} installed, and are in the top level @value{GDBN}
+source directory (@file{gdb-@value{GDBVN}}, in the case of version @value{GDBVN}), you can
+make the Info file by typing:
+
+@example
+cd gdb
+make gdb.info
+@end example
+
+If you want to typeset and print copies of this manual, you need @TeX{},
+a program to print its @sc{dvi} output files, and @file{texinfo.tex}, the
+Texinfo definitions file.
+
+@TeX{} is a typesetting program; it does not print files directly, but
+produces output files called @sc{dvi} files. To print a typeset
+document, you need a program to print @sc{dvi} files. If your system
+has @TeX{} installed, chances are it has such a program. The precise
+command to use depends on your system; @kbd{lpr -d} is common; another
+(for PostScript devices) is @kbd{dvips}. The @sc{dvi} print command may
+require a file name without any extension or a @samp{.dvi} extension.
+
+@TeX{} also requires a macro definitions file called
+@file{texinfo.tex}. This file tells @TeX{} how to typeset a document
+written in Texinfo format. On its own, @TeX{} cannot either read or
+typeset a Texinfo file. @file{texinfo.tex} is distributed with GDB
+and is located in the @file{gdb-@var{version-number}/texinfo}
+directory.
+
+If you have @TeX{} and a @sc{dvi} printer program installed, you can
+typeset and print this manual. First switch to the the @file{gdb}
+subdirectory of the main source directory (for example, to
+@file{gdb-@value{GDBVN}/gdb}) and then type:
+
+@example
+make gdb.dvi
+@end example
+
+@node Installing GDB
+@appendix Installing @value{GDBN}
+@cindex configuring @value{GDBN}
+@cindex installation
+
+@value{GDBN} comes with a @code{configure} script that automates the process
+of preparing @value{GDBN} for installation; you can then use @code{make} to
+build the @code{gdb} program.
+@iftex
+@c irrelevant in info file; it's as current as the code it lives with.
+@footnote{If you have a more recent version of @value{GDBN} than @value{GDBVN},
+look at the @file{README} file in the sources; we may have improved the
+installation procedures since publishing this manual.}
+@end iftex
+
+The @value{GDBN} distribution includes all the source code you need for
+@value{GDBN} in a single directory, whose name is usually composed by
+appending the version number to @samp{gdb}.
+
+For example, the @value{GDBN} version @value{GDBVN} distribution is in the
+@file{gdb-@value{GDBVN}} directory. That directory contains:
+
+@table @code
+@item gdb-@value{GDBVN}/configure @r{(and supporting files)}
+script for configuring @value{GDBN} and all its supporting libraries
+
+@item gdb-@value{GDBVN}/gdb
+the source specific to @value{GDBN} itself
+
+@item gdb-@value{GDBVN}/bfd
+source for the Binary File Descriptor library
+
+@item gdb-@value{GDBVN}/include
+@sc{gnu} include files
+
+@item gdb-@value{GDBVN}/libiberty
+source for the @samp{-liberty} free software library
+
+@item gdb-@value{GDBVN}/opcodes
+source for the library of opcode tables and disassemblers
+
+@item gdb-@value{GDBVN}/readline
+source for the @sc{gnu} command-line interface
+
+@item gdb-@value{GDBVN}/glob
+source for the @sc{gnu} filename pattern-matching subroutine
+
+@item gdb-@value{GDBVN}/mmalloc
+source for the @sc{gnu} memory-mapped malloc package
+@end table
+
+The simplest way to configure and build @value{GDBN} is to run @code{configure}
+from the @file{gdb-@var{version-number}} source directory, which in
+this example is the @file{gdb-@value{GDBVN}} directory.
+
+First switch to the @file{gdb-@var{version-number}} source directory
+if you are not already in it; then run @code{configure}. Pass the
+identifier for the platform on which @value{GDBN} will run as an
+argument.
+
+For example:
+
+@example
+cd gdb-@value{GDBVN}
+./configure @var{host}
+make
+@end example
+
+@noindent
+where @var{host} is an identifier such as @samp{sun4} or
+@samp{decstation}, that identifies the platform where @value{GDBN} will run.
+(You can often leave off @var{host}; @code{configure} tries to guess the
+correct value by examining your system.)
+
+Running @samp{configure @var{host}} and then running @code{make} builds the
+@file{bfd}, @file{readline}, @file{mmalloc}, and @file{libiberty}
+libraries, then @code{gdb} itself. The configured source files, and the
+binaries, are left in the corresponding source directories.
+
+@need 750
+@code{configure} is a Bourne-shell (@code{/bin/sh}) script; if your
+system does not recognize this automatically when you run a different
+shell, you may need to run @code{sh} on it explicitly:
+
+@example
+sh configure @var{host}
+@end example
+
+If you run @code{configure} from a directory that contains source
+directories for multiple libraries or programs, such as the
+@file{gdb-@value{GDBVN}} source directory for version @value{GDBVN}, @code{configure}
+creates configuration files for every directory level underneath (unless
+you tell it not to, with the @samp{--norecursion} option).
+
+You can run the @code{configure} script from any of the
+subordinate directories in the @value{GDBN} distribution if you only want to
+configure that subdirectory, but be sure to specify a path to it.
+
+For example, with version @value{GDBVN}, type the following to configure only
+the @code{bfd} subdirectory:
+
+@example
+@group
+cd gdb-@value{GDBVN}/bfd
+../configure @var{host}
+@end group
+@end example
+
+You can install @code{@value{GDBP}} anywhere; it has no hardwired paths.
+However, you should make sure that the shell on your path (named by
+the @samp{SHELL} environment variable) is publicly readable. Remember
+that @value{GDBN} uses the shell to start your program---some systems refuse to
+let @value{GDBN} debug child processes whose programs are not readable.
+
+@menu
+* Separate Objdir:: Compiling @value{GDBN} in another directory
+* Config Names:: Specifying names for hosts and targets
+* configure Options:: Summary of options for configure
+@end menu
+
+@node Separate Objdir
+@section Compiling @value{GDBN} in another directory
+
+If you want to run @value{GDBN} versions for several host or target machines,
+you need a different @code{gdb} compiled for each combination of
+host and target. @code{configure} is designed to make this easy by
+allowing you to generate each configuration in a separate subdirectory,
+rather than in the source directory. If your @code{make} program
+handles the @samp{VPATH} feature (@sc{gnu} @code{make} does), running
+@code{make} in each of these directories builds the @code{gdb}
+program specified there.
+
+To build @code{gdb} in a separate directory, run @code{configure}
+with the @samp{--srcdir} option to specify where to find the source.
+(You also need to specify a path to find @code{configure}
+itself from your working directory. If the path to @code{configure}
+would be the same as the argument to @samp{--srcdir}, you can leave out
+the @samp{--srcdir} option; it is assumed.)
+
+For example, with version @value{GDBVN}, you can build @value{GDBN} in a
+separate directory for a Sun 4 like this:
+
+@example
+@group
+cd gdb-@value{GDBVN}
+mkdir ../gdb-sun4
+cd ../gdb-sun4
+../gdb-@value{GDBVN}/configure sun4
+make
+@end group
+@end example
+
+When @code{configure} builds a configuration using a remote source
+directory, it creates a tree for the binaries with the same structure
+(and using the same names) as the tree under the source directory. In
+the example, you'd find the Sun 4 library @file{libiberty.a} in the
+directory @file{gdb-sun4/libiberty}, and @value{GDBN} itself in
+@file{gdb-sun4/gdb}.
+
+One popular reason to build several @value{GDBN} configurations in separate
+directories is to configure @value{GDBN} for cross-compiling (where
+@value{GDBN} runs on one machine---the @dfn{host}---while debugging
+programs that run on another machine---the @dfn{target}).
+You specify a cross-debugging target by
+giving the @samp{--target=@var{target}} option to @code{configure}.
+
+When you run @code{make} to build a program or library, you must run
+it in a configured directory---whatever directory you were in when you
+called @code{configure} (or one of its subdirectories).
+
+The @code{Makefile} that @code{configure} generates in each source
+directory also runs recursively. If you type @code{make} in a source
+directory such as @file{gdb-@value{GDBVN}} (or in a separate configured
+directory configured with @samp{--srcdir=@var{dirname}/gdb-@value{GDBVN}}), you
+will build all the required libraries, and then build GDB.
+
+When you have multiple hosts or targets configured in separate
+directories, you can run @code{make} on them in parallel (for example,
+if they are NFS-mounted on each of the hosts); they will not interfere
+with each other.
+
+@node Config Names
+@section Specifying names for hosts and targets
+
+The specifications used for hosts and targets in the @code{configure}
+script are based on a three-part naming scheme, but some short predefined
+aliases are also supported. The full naming scheme encodes three pieces
+of information in the following pattern:
+
+@example
+@var{architecture}-@var{vendor}-@var{os}
+@end example
+
+For example, you can use the alias @code{sun4} as a @var{host} argument,
+or as the value for @var{target} in a @code{--target=@var{target}}
+option. The equivalent full name is @samp{sparc-sun-sunos4}.
+
+The @code{configure} script accompanying @value{GDBN} does not provide
+any query facility to list all supported host and target names or
+aliases. @code{configure} calls the Bourne shell script
+@code{config.sub} to map abbreviations to full names; you can read the
+script, if you wish, or you can use it to test your guesses on
+abbreviations---for example:
+
+@smallexample
+% sh config.sub sun4
+sparc-sun-sunos4.1.1
+% sh config.sub sun3
+m68k-sun-sunos4.1.1
+% sh config.sub decstation
+mips-dec-ultrix4.2
+% sh config.sub hp300bsd
+m68k-hp-bsd
+% sh config.sub i386v
+i386-unknown-sysv
+% sh config.sub i786v
+Invalid configuration `i786v': machine `i786v' not recognized
+@end smallexample
+
+@noindent
+@code{config.sub} is also distributed in the @value{GDBN} source
+directory (@file{gdb-@value{GDBVN}}, for version @value{GDBVN}).
+
+@node configure Options
+@section @code{configure} options
+
+Here is a summary of the @code{configure} options and arguments that
+are most often useful for building @value{GDBN}. @code{configure} also has
+several other options not listed here. @inforef{What Configure
+Does,,configure.info}, for a full explanation of @code{configure}.
+
+@example
+configure @r{[}--help@r{]}
+ @r{[}--prefix=@var{dir}@r{]}
+ @r{[}--srcdir=@var{dirname}@r{]}
+ @r{[}--norecursion@r{]} @r{[}--rm@r{]}
+ @r{[}--target=@var{target}@r{]} @var{host}
+@end example
+
+@noindent
+You may introduce options with a single @samp{-} rather than
+@samp{--} if you prefer; but you may abbreviate option names if you use
+@samp{--}.
+
+@table @code
+@item --help
+Display a quick summary of how to invoke @code{configure}.
+
+@item -prefix=@var{dir}
+Configure the source to install programs and files under directory
+@file{@var{dir}}.
+
+@c avoid splitting the warning from the explanation:
+@need 2000
+@item --srcdir=@var{dirname}
+@strong{Warning: using this option requires @sc{gnu} @code{make}, or another
+@code{make} that implements the @code{VPATH} feature.}@*
+Use this option to make configurations in directories separate from the
+@value{GDBN} source directories. Among other things, you can use this to
+build (or maintain) several configurations simultaneously, in separate
+directories. @code{configure} writes configuration specific files in
+the current directory, but arranges for them to use the source in the
+directory @var{dirname}. @code{configure} creates directories under
+the working directory in parallel to the source directories below
+@var{dirname}.
+
+@item --norecursion
+Configure only the directory level where @code{configure} is executed; do not
+propagate configuration to subdirectories.
+
+@item --rm
+@emph{Remove} files otherwise built during configuration.
+
+@c This does not work (yet if ever). FIXME.
+@c @item --parse=@var{lang} @dots{}
+@c Configure the @value{GDBN} expression parser to parse the listed languages.
+@c @samp{all} configures @value{GDBN} for all supported languages. To get a
+@c list of all supported languages, omit the argument. Without this
+@c option, @value{GDBN} is configured to parse all supported languages.
+
+@item --target=@var{target}
+Configure @value{GDBN} for cross-debugging programs running on the specified
+@var{target}. Without this option, @value{GDBN} is configured to debug
+programs that run on the same machine (@var{host}) as @value{GDBN} itself.
+
+There is no convenient way to generate a list of all available targets.
+
+@item @var{host} @dots{}
+Configure @value{GDBN} to run on the specified @var{host}.
+
+There is no convenient way to generate a list of all available hosts.
+@end table
+
+@noindent
+@code{configure} accepts other options, for compatibility with
+configuring other @sc{gnu} tools recursively; but these are the only
+options that affect @value{GDBN} or its supporting libraries.
+@end ifclear
+
+@node Index
+@unnumbered Index
+
+@printindex cp
+
+@tex
+% I think something like @colophon should be in texinfo. In the
+% meantime:
+\long\def\colophon{\hbox to0pt{}\vfill
+\centerline{The body of this manual is set in}
+\centerline{\fontname\tenrm,}
+\centerline{with headings in {\bf\fontname\tenbf}}
+\centerline{and examples in {\tt\fontname\tentt}.}
+\centerline{{\it\fontname\tenit\/},}
+\centerline{{\bf\fontname\tenbf}, and}
+\centerline{{\sl\fontname\tensl\/}}
+\centerline{are used for emphasis.}\vfill}
+\page\colophon
+% Blame: doc@cygnus.com, 1991.
+@end tex
+
+@contents
+@bye
diff --git a/contrib/gdb/gdb/doc/gdbint.texinfo b/contrib/gdb/gdb/doc/gdbint.texinfo
new file mode 100644
index 0000000..c7f4390
--- /dev/null
+++ b/contrib/gdb/gdb/doc/gdbint.texinfo
@@ -0,0 +1,2543 @@
+\input texinfo
+@setfilename gdbint.info
+@c $Id: gdbint.texinfo,v 1.84 1996/01/11 20:08:19 fnf Exp $
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Gdb-Internals: (gdbint). The GNU debugger's internals.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This file documents the internals of the GNU debugger GDB.
+
+Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+Contributed by Cygnus Support. Written by John Gilmore.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy or distribute modified versions of this
+manual under the terms of the GPL (for which purpose this text may be
+regarded as a program in the language TeX).
+@end ifinfo
+
+@setchapternewpage off
+@settitle GDB Internals
+@titlepage
+@title{Working in GDB}
+@subtitle{A guide to the internals of the GNU debugger}
+@author John Gilmore
+@author Cygnus Support
+@page
+@tex
+\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision: 1.84 $} % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@end titlepage
+
+@node Top
+@c Perhaps this should be the title of the document (but only for info,
+@c not for TeX). Existing GNU manuals seem inconsistent on this point.
+@top Scope of this Document
+
+This document documents the internals of the GNU debugger, GDB. It is
+intended to document aspects of GDB which apply across many different
+parts of GDB (for example, @pxref{Coding Style}), or which are global
+aspects of design (for example, what are the major modules and which
+files document them in detail?). Information which pertains to specific
+data structures, functions, variables, etc., should be put in comments
+in the source code, not here. It is more likely to get noticed and kept
+up to date there. Some of the information in this document should
+probably be moved into comments.
+
+@menu
+* README:: The README File
+* Getting Started:: Getting started working on GDB
+* Debugging GDB:: Debugging GDB with itself
+* New Architectures:: Defining a New Host or Target Architecture
+* Config:: Adding a New Configuration
+* Host:: Adding a New Host
+* Native:: Adding a New Native Configuration
+* Target:: Adding a New Target
+* Languages:: Defining New Source Languages
+* Releases:: Configuring GDB for Release
+* Partial Symbol Tables:: How GDB reads symbols quickly at startup
+* Types:: How GDB keeps track of types
+* BFD support for GDB:: How BFD and GDB interface
+* Symbol Reading:: Defining New Symbol Readers
+* Cleanups:: Cleanups
+* Wrapping:: Wrapping Output Lines
+* Frames:: Keeping track of function calls
+* Remote Stubs:: Code that runs in targets and talks to GDB
+* Longjmp Support:: Stepping through longjmp's in the target
+* Coding Style:: Strunk and White for GDB maintainers
+* Clean Design:: Frank Lloyd Wright for GDB maintainers
+* Submitting Patches:: How to get your changes into GDB releases
+* Host Conditionals:: What features exist in the host
+* Target Conditionals:: What features exist in the target
+* Native Conditionals:: Conditionals for when host and target are same
+* Obsolete Conditionals:: Conditionals that don't exist any more
+* XCOFF:: The Object file format used on IBM's RS/6000
+@end menu
+
+@node README
+@chapter The @file{README} File
+
+Check the @file{README} file, it often has useful information that does not
+appear anywhere else in the directory.
+
+@node Getting Started
+@chapter Getting Started Working on GDB
+
+GDB is a large and complicated program, and if you first starting to
+work on it, it can be hard to know where to start. Fortunately, if you
+know how to go about it, there are ways to figure out what is going on:
+
+@itemize @bullet
+@item
+This manual, the GDB Internals manual, has information which applies
+generally to many parts of GDB.
+
+@item
+Information about particular functions or data structures are located in
+comments with those functions or data structures. If you run across a
+function or a global variable which does not have a comment correctly
+explaining what is does, this can be thought of as a bug in GDB; feel
+free to submit a bug report, with a suggested comment if you can figure
+out what the comment should say (@pxref{Submitting Patches}). If you
+find a comment which is actually wrong, be especially sure to report that.
+
+Comments explaining the function of macros defined in host, target, or
+native dependent files can be in several places. Sometimes they are
+repeated every place the macro is defined. Sometimes they are where the
+macro is used. Sometimes there is a header file which supplies a
+default definition of the macro, and the comment is there. This manual
+also has a list of macros (@pxref{Host Conditionals}, @pxref{Target
+Conditionals}, @pxref{Native Conditionals}, and @pxref{Obsolete
+Conditionals}) with some documentation.
+
+@item
+Start with the header files. Once you some idea of how GDB's internal
+symbol tables are stored (see @file{symtab.h}, @file{gdbtypes.h}), you
+will find it much easier to understand the code which uses and creates
+those symbol tables.
+
+@item
+You may wish to process the information you are getting somehow, to
+enhance your understanding of it. Summarize it, translate it to another
+language, add some (perhaps trivial or non-useful) feature to GDB, use
+the code to predict what a test case would do and write the test case
+and verify your prediction, etc. If you are reading code and your eyes
+are starting to glaze over, this is a sign you need to use a more active
+approach.
+
+@item
+Once you have a part of GDB to start with, you can find more
+specifically the part you are looking for by stepping through each
+function with the @code{next} command. Do not use @code{step} or you
+will quickly get distracted; when the function you are stepping through
+calls another function try only to get a big-picture understanding
+(perhaps using the comment at the beginning of the function being
+called) of what it does. This way you can identify which of the
+functions being called by the function you are stepping through is the
+one which you are interested in. You may need to examine the data
+structures generated at each stage, with reference to the comments in
+the header files explaining what the data structures are supposed to
+look like.
+
+Of course, this same technique can be used if you are just reading the
+code, rather than actually stepping through it. The same general
+principle applies---when the code you are looking at calls something
+else, just try to understand generally what the code being called does,
+rather than worrying about all its details.
+
+@item
+A good place to start when tracking down some particular area is with a
+command which invokes that feature. Suppose you want to know how
+single-stepping works. As a GDB user, you know that the @code{step}
+command invokes single-stepping. The command is invoked via command
+tables (see @file{command.h}); by convention the function which actually
+performs the command is formed by taking the name of the command and
+adding @samp{_command}, or in the case of an @code{info} subcommand,
+@samp{_info}. For example, the @code{step} command invokes the
+@code{step_command} function and the @code{info display} command invokes
+@code{display_info}. When this convention is not followed, you might
+have to use @code{grep} or @kbd{M-x tags-search} in emacs, or run GDB on
+itself and set a breakpoint in @code{execute_command}.
+
+@item
+If all of the above fail, it may be appropriate to ask for information
+on @code{bug-gdb}. But @emph{never} post a generic question like ``I was
+wondering if anyone could give me some tips about understanding
+GDB''---if we had some magic secret we would put it in this manual.
+Suggestions for improving the manual are always welcome, of course.
+@end itemize
+
+Good luck!
+
+@node Debugging GDB
+@chapter Debugging GDB with itself
+If GDB is limping on your machine, this is the preferred way to get it
+fully functional. Be warned that in some ancient Unix systems, like
+Ultrix 4.2, a program can't be running in one process while it is being
+debugged in another. Rather than typing the command @code{@w{./gdb
+./gdb}}, which works on Suns and such, you can copy @file{gdb} to
+@file{gdb2} and then type @code{@w{./gdb ./gdb2}}.
+
+When you run GDB in the GDB source directory, it will read a
+@file{.gdbinit} file that sets up some simple things to make debugging
+gdb easier. The @code{info} command, when executed without a subcommand
+in a GDB being debugged by gdb, will pop you back up to the top level
+gdb. See @file{.gdbinit} for details.
+
+If you use emacs, you will probably want to do a @code{make TAGS} after
+you configure your distribution; this will put the machine dependent
+routines for your local machine where they will be accessed first by
+@kbd{M-.}
+
+Also, make sure that you've either compiled GDB with your local cc, or
+have run @code{fixincludes} if you are compiling with gcc.
+
+@node New Architectures
+@chapter Defining a New Host or Target Architecture
+
+When building support for a new host and/or target, much of the work you
+need to do is handled by specifying configuration files;
+@pxref{Config,,Adding a New Configuration}. Further work can be
+divided into ``host-dependent'' (@pxref{Host,,Adding a New Host}) and
+``target-dependent'' (@pxref{Target,,Adding a New Target}). The
+following discussion is meant to explain the difference between hosts
+and targets.
+
+@heading What is considered ``host-dependent'' versus ``target-dependent''?
+
+@dfn{Host} refers to attributes of the system where GDB runs.
+@dfn{Target} refers to the system where the program being debugged
+executes. In most cases they are the same machine, in which case
+a third type of @dfn{Native} attributes come into play.
+
+Defines and include files needed to build on the host are host support.
+Examples are tty support, system defined types, host byte order, host
+float format.
+
+Defines and information needed to handle the target format are target
+dependent. Examples are the stack frame format, instruction set,
+breakpoint instruction, registers, and how to set up and tear down the stack
+to call a function.
+
+Information that is only needed when the host and target are the same,
+is native dependent. One example is Unix child process support; if the
+host and target are not the same, doing a fork to start the target
+process is a bad idea. The various macros needed for finding the
+registers in the @code{upage}, running @code{ptrace}, and such are all in the
+native-dependent files.
+
+Another example of native-dependent code is support for features
+that are really part of the target environment, but which require
+@code{#include} files that are only available on the host system.
+Core file handling and @code{setjmp} handling are two common cases.
+
+When you want to make GDB work ``native'' on a particular
+machine, you have to include all three kinds of information.
+
+The dependent information in GDB is organized into files by naming
+conventions.
+
+Host-Dependent Files
+@table @file
+@item config/*/*.mh
+Sets Makefile parameters
+@item config/*/xm-*.h
+Global #include's and #define's and definitions
+@item *-xdep.c
+Global variables and functions
+@end table
+
+Native-Dependent Files
+@table @file
+@item config/*/*.mh
+Sets Makefile parameters (for @emph{both} host and native)
+@item config/*/nm-*.h
+#include's and #define's and definitions. This file
+is only included by the small number of modules that need it,
+so beware of doing feature-test #define's from its macros.
+@item *-nat.c
+global variables and functions
+@end table
+
+Target-Dependent Files
+@table @file
+@item config/*/*.mt
+Sets Makefile parameters
+@item config/*/tm-*.h
+Global #include's and #define's and definitions
+@item *-tdep.c
+Global variables and functions
+@end table
+
+At this writing, most supported hosts have had their host and native
+dependencies sorted out properly. There are a few stragglers, which
+can be recognized by the absence of NATDEPFILES lines in their
+@file{config/*/*.mh}.
+
+@node Config
+@chapter Adding a New Configuration
+
+Most of the work in making GDB compile on a new machine is in specifying
+the configuration of the machine. This is done in a dizzying variety of
+header files and configuration scripts, which we hope to make more
+sensible soon. Let's say your new host is called an @var{xxx} (e.g.
+@samp{sun4}), and its full three-part configuration name is
+@code{@var{xarch}-@var{xvend}-@var{xos}} (e.g. @samp{sparc-sun-sunos4}). In
+particular:
+
+In the top level directory, edit @file{config.sub} and add @var{xarch},
+@var{xvend}, and @var{xos} to the lists of supported architectures,
+vendors, and operating systems near the bottom of the file. Also, add
+@var{xxx} as an alias that maps to
+@code{@var{xarch}-@var{xvend}-@var{xos}}. You can test your changes by
+running
+
+@example
+./config.sub @var{xxx}
+@end example
+@noindent
+and
+@example
+./config.sub @code{@var{xarch}-@var{xvend}-@var{xos}}
+@end example
+@noindent
+which should both respond with @code{@var{xarch}-@var{xvend}-@var{xos}}
+and no error messages.
+
+Now, go to the @file{bfd} directory and
+create a new file @file{bfd/hosts/h-@var{xxx}.h}. Examine the
+other @file{h-*.h} files as templates, and create one that brings in the
+right include files for your system, and defines any host-specific
+macros needed by BFD, the Binutils, GNU LD, or the Opcodes directories.
+(They all share the bfd @file{hosts} directory and the @file{configure.host}
+file.)
+
+Then edit @file{bfd/configure.host}. Add a line to recognize your
+@code{@var{xarch}-@var{xvend}-@var{xos}} configuration, and set
+@code{my_host} to @var{xxx} when you recognize it. This will cause your
+file @file{h-@var{xxx}.h} to be linked to @file{sysdep.h} at configuration
+time. When creating the line that recognizes your configuration,
+only match the fields that you really need to match; e.g. don't
+match the architecture or manufacturer if the OS is sufficient
+to distinguish the configuration that your @file{h-@var{xxx}.h} file supports.
+Don't match the manufacturer name unless you really need to.
+This should make future ports easier.
+
+Also, if this host requires any changes to the Makefile, create a file
+@file{bfd/config/@var{xxx}.mh}, which includes the required lines.
+
+It's possible that the @file{libiberty} and @file{readline} directories
+won't need any changes for your configuration, but if they do, you can
+change the @file{configure.in} file there to recognize your system and
+map to an @file{mh-@var{xxx}} file. Then add @file{mh-@var{xxx}}
+to the @file{config/} subdirectory, to set any makefile variables you
+need. The only current options in there are things like @samp{-DSYSV}.
+(This @file{mh-@var{xxx}} naming convention differs from elsewhere
+in GDB, by historical accident. It should be cleaned up so that all
+such files are called @file{@var{xxx}.mh}.)
+
+Aha! Now to configure GDB itself! Edit
+@file{gdb/configure.in} to recognize your system and set @code{gdb_host}
+to @var{xxx}, and (unless your desired target is already available) also
+set @code{gdb_target} to something appropriate (for instance,
+@var{xxx}). To handle new hosts, modify the segment after the comment
+@samp{# per-host}; to handle new targets, modify after @samp{#
+per-target}.
+@c Would it be simpler to just use different per-host and per-target
+@c *scripts*, and call them from {configure} ?
+
+Finally, you'll need to specify and define GDB's host-, native-, and
+target-dependent @file{.h} and @file{.c} files used for your
+configuration; the next two chapters discuss those.
+
+
+@node Host
+@chapter Adding a New Host
+
+Once you have specified a new configuration for your host
+(@pxref{Config,,Adding a New Configuration}), there are three remaining
+pieces to making GDB work on a new machine. First, you have to make it
+host on the new machine (compile there, handle that machine's terminals
+properly, etc). If you will be cross-debugging to some other kind of
+system that's already supported, you are done.
+
+If you want to use GDB to debug programs that run on the new machine,
+you have to get it to understand the machine's object files, symbol
+files, and interfaces to processes; @pxref{Target,,Adding a New Target}
+and @pxref{Native,,Adding a New Native Configuration}
+
+Several files control GDB's configuration for host systems:
+
+@table @file
+@item gdb/config/@var{arch}/@var{xxx}.mh
+Specifies Makefile fragments needed when hosting on machine @var{xxx}.
+In particular, this lists the required machine-dependent object files,
+by defining @samp{XDEPFILES=@dots{}}. Also
+specifies the header file which describes host @var{xxx}, by defining
+@code{XM_FILE= xm-@var{xxx}.h}. You can also define @code{CC},
+@code{REGEX} and @code{REGEX1}, @code{SYSV_DEFINE}, @code{XM_CFLAGS},
+@code{XM_ADD_FILES}, @code{XM_CLIBS}, @code{XM_CDEPS},
+etc.; see @file{Makefile.in}.
+
+@item gdb/config/@var{arch}/xm-@var{xxx}.h
+(@file{xm.h} is a link to this file, created by configure).
+Contains C macro definitions describing the host system environment,
+such as byte order, host C compiler and library, ptrace support,
+and core file structure. Crib from existing @file{xm-*.h} files
+to create a new one.
+
+@item gdb/@var{xxx}-xdep.c
+Contains any miscellaneous C code required for this machine
+as a host. On many machines it doesn't exist at all. If it does
+exist, put @file{@var{xxx}-xdep.o} into the @code{XDEPFILES} line
+in @file{gdb/config/mh-@var{xxx}}.
+@end table
+
+@subheading Generic Host Support Files
+
+There are some ``generic'' versions of routines that can be used by
+various systems. These can be customized in various ways by macros
+defined in your @file{xm-@var{xxx}.h} file. If these routines work for
+the @var{xxx} host, you can just include the generic file's name (with
+@samp{.o}, not @samp{.c}) in @code{XDEPFILES}.
+
+Otherwise, if your machine needs custom support routines, you will need
+to write routines that perform the same functions as the generic file.
+Put them into @code{@var{xxx}-xdep.c}, and put @code{@var{xxx}-xdep.o}
+into @code{XDEPFILES}.
+
+@table @file
+@item ser-bsd.c
+This contains serial line support for Berkeley-derived Unix systems.
+
+@item ser-go32.c
+This contains serial line support for 32-bit programs running under DOS
+using the GO32 execution environment.
+
+@item ser-termios.c
+This contains serial line support for System V-derived Unix systems.
+@end table
+
+Now, you are now ready to try configuring GDB to compile using your system
+as its host. From the top level (above @file{bfd}, @file{gdb}, etc), do:
+
+@example
+./configure @var{xxx} --target=vxworks960
+@end example
+
+This will configure your system to cross-compile for VxWorks on
+the Intel 960, which is probably not what you really want, but it's
+a test case that works at this stage. (You haven't set up to be
+able to debug programs that run @emph{on} @var{xxx} yet.)
+
+If this succeeds, you can try building it all with:
+
+@example
+make
+@end example
+
+Repeat until the program configures, compiles, links, and runs.
+When run, it won't be able to do much (unless you have a VxWorks/960
+board on your network) but you will know that the host support is
+pretty well done.
+
+Good luck! Comments and suggestions about this section are particularly
+welcome; send them to @samp{bug-gdb@@prep.ai.mit.edu}.
+
+@node Native
+@chapter Adding a New Native Configuration
+
+If you are making GDB run native on the @var{xxx} machine, you have
+plenty more work to do. Several files control GDB's configuration for
+native support:
+
+@table @file
+@item gdb/config/@var{xarch}/@var{xxx}.mh
+Specifies Makefile fragments needed when hosting @emph{or native}
+on machine @var{xxx}.
+In particular, this lists the required native-dependent object files,
+by defining @samp{NATDEPFILES=@dots{}}. Also
+specifies the header file which describes native support on @var{xxx},
+by defining @samp{NAT_FILE= nm-@var{xxx}.h}.
+You can also define @samp{NAT_CFLAGS},
+@samp{NAT_ADD_FILES}, @samp{NAT_CLIBS}, @samp{NAT_CDEPS},
+etc.; see @file{Makefile.in}.
+
+@item gdb/config/@var{arch}/nm-@var{xxx}.h
+(@file{nm.h} is a link to this file, created by configure).
+Contains C macro definitions describing the native system environment,
+such as child process control and core file support.
+Crib from existing @file{nm-*.h} files to create a new one.
+
+@item gdb/@var{xxx}-nat.c
+Contains any miscellaneous C code required for this native support
+of this machine. On some machines it doesn't exist at all.
+@end table
+
+@subheading Generic Native Support Files
+
+There are some ``generic'' versions of routines that can be used by
+various systems. These can be customized in various ways by macros
+defined in your @file{nm-@var{xxx}.h} file. If these routines work for
+the @var{xxx} host, you can just include the generic file's name (with
+@samp{.o}, not @samp{.c}) in @code{NATDEPFILES}.
+
+Otherwise, if your machine needs custom support routines, you will need
+to write routines that perform the same functions as the generic file.
+Put them into @code{@var{xxx}-nat.c}, and put @code{@var{xxx}-nat.o}
+into @code{NATDEPFILES}.
+
+@table @file
+
+@item inftarg.c
+This contains the @emph{target_ops vector} that supports Unix child
+processes on systems which use ptrace and wait to control the child.
+
+@item procfs.c
+This contains the @emph{target_ops vector} that supports Unix child
+processes on systems which use /proc to control the child.
+
+@item fork-child.c
+This does the low-level grunge that uses Unix system calls
+to do a "fork and exec" to start up a child process.
+
+@item infptrace.c
+This is the low level interface to inferior processes for systems
+using the Unix @code{ptrace} call in a vanilla way.
+
+@item core-aout.c::fetch_core_registers()
+Support for reading registers out of a core file. This routine calls
+@code{register_addr()}, see below.
+Now that BFD is used to read core files, virtually all machines should
+use @code{core-aout.c}, and should just provide @code{fetch_core_registers} in
+@code{@var{xxx}-nat.c} (or @code{REGISTER_U_ADDR} in @code{nm-@var{xxx}.h}).
+
+@item core-aout.c::register_addr()
+If your @code{nm-@var{xxx}.h} file defines the macro
+@code{REGISTER_U_ADDR(addr, blockend, regno)}, it should be defined to
+set @code{addr} to the offset within the @samp{user}
+struct of GDB register number @code{regno}. @code{blockend} is the
+offset within the ``upage'' of @code{u.u_ar0}.
+If @code{REGISTER_U_ADDR} is defined,
+@file{core-aout.c} will define the @code{register_addr()} function and use
+the macro in it. If you do not define @code{REGISTER_U_ADDR}, but you
+are using the standard @code{fetch_core_registers()}, you will need to
+define your own version of @code{register_addr()}, put it into your
+@code{@var{xxx}-nat.c} file, and be sure @code{@var{xxx}-nat.o} is in
+the @code{NATDEPFILES} list. If you have your own
+@code{fetch_core_registers()}, you may not need a separate
+@code{register_addr()}. Many custom @code{fetch_core_registers()}
+implementations simply locate the registers themselves.@refill
+@end table
+
+When making GDB run native on a new operating system,
+to make it possible to debug
+core files, you will need to either write specific code for parsing your
+OS's core files, or customize @file{bfd/trad-core.c}. First, use
+whatever @code{#include} files your machine uses to define the struct of
+registers that is accessible (possibly in the u-area) in a core file
+(rather than @file{machine/reg.h}), and an include file that defines whatever
+header exists on a core file (e.g. the u-area or a @samp{struct core}). Then
+modify @code{trad_unix_core_file_p()} to use these values to set up the
+section information for the data segment, stack segment, any other
+segments in the core file (perhaps shared library contents or control
+information), ``registers'' segment, and if there are two discontiguous
+sets of registers (e.g. integer and float), the ``reg2'' segment. This
+section information basically delimits areas in the core file in a
+standard way, which the section-reading routines in BFD know how to seek
+around in.
+
+Then back in GDB, you need a matching routine called
+@code{fetch_core_registers()}. If you can use the generic one, it's in
+@file{core-aout.c}; if not, it's in your @file{@var{xxx}-nat.c} file.
+It will be passed a char pointer to the entire ``registers'' segment,
+its length, and a zero; or a char pointer to the entire ``regs2''
+segment, its length, and a 2. The routine should suck out the supplied
+register values and install them into GDB's ``registers'' array.
+(@xref{New Architectures,,Defining a New Host or Target Architecture},
+for more info about this.)
+
+If your system uses @file{/proc} to control processes, and uses ELF
+format core files, then you may be able to use the same routines
+for reading the registers out of processes and out of core files.
+
+@node Target
+@chapter Adding a New Target
+
+For a new target called @var{ttt}, first specify the configuration as
+described in @ref{Config,,Adding a New Configuration}. If your new
+target is the same as your new host, you've probably already done that.
+
+A variety of files specify attributes of the GDB target environment:
+
+@table @file
+@item gdb/config/@var{arch}/@var{ttt}.mt
+Contains a Makefile fragment specific to this target.
+Specifies what object files are needed for target @var{ttt}, by
+defining @samp{TDEPFILES=@dots{}}.
+Also specifies the header file which describes @var{ttt}, by defining
+@samp{TM_FILE= tm-@var{ttt}.h}. You can also define @samp{TM_CFLAGS},
+@samp{TM_CLIBS}, @samp{TM_CDEPS},
+and other Makefile variables here; see @file{Makefile.in}.
+
+@item gdb/config/@var{arch}/tm-@var{ttt}.h
+(@file{tm.h} is a link to this file, created by configure).
+Contains macro definitions about the target machine's
+registers, stack frame format and instructions.
+Crib from existing @file{tm-*.h} files when building a new one.
+
+@item gdb/@var{ttt}-tdep.c
+Contains any miscellaneous code required for this target machine.
+On some machines it doesn't exist at all. Sometimes the macros
+in @file{tm-@var{ttt}.h} become very complicated, so they are
+implemented as functions here instead, and the macro is simply
+defined to call the function.
+
+@item gdb/exec.c
+Defines functions for accessing files that are
+executable on the target system. These functions open and examine an
+exec file, extract data from one, write data to one, print information
+about one, etc. Now that executable files are handled with BFD, every
+target should be able to use the generic exec.c rather than its
+own custom code.
+
+@item gdb/@var{arch}-pinsn.c
+Prints (disassembles) the target machine's instructions.
+This file is usually shared with other target machines which use the
+same processor, which is why it is @file{@var{arch}-pinsn.c} rather
+than @file{@var{ttt}-pinsn.c}.
+
+@item gdb/@var{arch}-opcode.h
+Contains some large initialized
+data structures describing the target machine's instructions.
+This is a bit strange for a @file{.h} file, but it's OK since
+it is only included in one place. @file{@var{arch}-opcode.h} is shared
+between the debugger and the assembler, if the GNU assembler has been
+ported to the target machine.
+
+@item gdb/config/@var{arch}/tm-@var{arch}.h
+This often exists to describe the basic layout of the target machine's
+processor chip (registers, stack, etc).
+If used, it is included by @file{tm-@var{xxx}.h}. It can
+be shared among many targets that use the same processor.
+
+@item gdb/@var{arch}-tdep.c
+Similarly, there are often common subroutines that are shared by all
+target machines that use this particular architecture.
+@end table
+
+When adding support for a new target machine, there are various areas
+of support that might need change, or might be OK.
+
+If you are using an existing object file format (a.out or COFF),
+there is probably little to be done. See @file{bfd/doc/bfd.texinfo}
+for more information on writing new a.out or COFF versions.
+
+If you need to add a new object file format, you must first add it to
+BFD. This is beyond the scope of this document right now. Basically
+you must build a transfer vector (of type @code{bfd_target}), which will
+mean writing all the required routines, and add it to the list in
+@file{bfd/targets.c}.
+
+You must then arrange for the BFD code to provide access to the
+debugging symbols. Generally GDB will have to call swapping routines
+from BFD and a few other BFD internal routines to locate the debugging
+information. As much as possible, GDB should not depend on the BFD
+internal data structures.
+
+For some targets (e.g., COFF), there is a special transfer vector used
+to call swapping routines, since the external data structures on various
+platforms have different sizes and layouts. Specialized routines that
+will only ever be implemented by one object file format may be called
+directly. This interface should be described in a file
+@file{bfd/libxxx.h}, which is included by GDB.
+
+If you are adding a new operating system for an existing CPU chip, add a
+@file{tm-@var{xos}.h} file that describes the operating system
+facilities that are unusual (extra symbol table info; the breakpoint
+instruction needed; etc). Then write a
+@file{tm-@var{xarch}-@var{xos}.h} that just @code{#include}s
+@file{tm-@var{xarch}.h} and @file{tm-@var{xos}.h}. (Now that we have
+three-part configuration names, this will probably get revised to
+separate the @var{xos} configuration from the @var{xarch}
+configuration.)
+
+
+@node Languages
+@chapter Adding a Source Language to GDB
+
+To add other languages to GDB's expression parser, follow the following steps:
+
+@table @emph
+@item Create the expression parser.
+
+This should reside in a file @file{@var{lang}-exp.y}. Routines for building
+parsed expressions into a @samp{union exp_element} list are in @file{parse.c}.
+
+Since we can't depend upon everyone having Bison, and YACC produces
+parsers that define a bunch of global names, the following lines
+@emph{must} be included at the top of the YACC parser, to prevent
+the various parsers from defining the same global names:
+
+@example
+#define yyparse @var{lang}_parse
+#define yylex @var{lang}_lex
+#define yyerror @var{lang}_error
+#define yylval @var{lang}_lval
+#define yychar @var{lang}_char
+#define yydebug @var{lang}_debug
+#define yypact @var{lang}_pact
+#define yyr1 @var{lang}_r1
+#define yyr2 @var{lang}_r2
+#define yydef @var{lang}_def
+#define yychk @var{lang}_chk
+#define yypgo @var{lang}_pgo
+#define yyact @var{lang}_act
+#define yyexca @var{lang}_exca
+#define yyerrflag @var{lang}_errflag
+#define yynerrs @var{lang}_nerrs
+@end example
+
+At the bottom of your parser, define a @code{struct language_defn} and
+initialize it with the right values for your language. Define an
+@code{initialize_@var{lang}} routine and have it call
+@samp{add_language(@var{lang}_language_defn)} to tell the rest of GDB
+that your language exists. You'll need some other supporting variables
+and functions, which will be used via pointers from your
+@code{@var{lang}_language_defn}. See the declaration of @code{struct
+language_defn} in @file{language.h}, and the other @file{*-exp.y} files,
+for more information.
+
+@item Add any evaluation routines, if necessary
+
+If you need new opcodes (that represent the operations of the language),
+add them to the enumerated type in @file{expression.h}. Add support
+code for these operations in @code{eval.c:evaluate_subexp()}. Add cases
+for new opcodes in two functions from @file{parse.c}:
+@code{prefixify_subexp()} and @code{length_of_subexp()}. These compute
+the number of @code{exp_element}s that a given operation takes up.
+
+@item Update some existing code
+
+Add an enumerated identifier for your language to the enumerated type
+@code{enum language} in @file{defs.h}.
+
+Update the routines in @file{language.c} so your language is included. These
+routines include type predicates and such, which (in some cases) are
+language dependent. If your language does not appear in the switch
+statement, an error is reported.
+
+Also included in @file{language.c} is the code that updates the variable
+@code{current_language}, and the routines that translate the
+@code{language_@var{lang}} enumerated identifier into a printable
+string.
+
+Update the function @code{_initialize_language} to include your language. This
+function picks the default language upon startup, so is dependent upon
+which languages that GDB is built for.
+
+Update @code{allocate_symtab} in @file{symfile.c} and/or symbol-reading
+code so that the language of each symtab (source file) is set properly.
+This is used to determine the language to use at each stack frame level.
+Currently, the language is set based upon the extension of the source
+file. If the language can be better inferred from the symbol
+information, please set the language of the symtab in the symbol-reading
+code.
+
+Add helper code to @code{expprint.c:print_subexp()} to handle any new
+expression opcodes you have added to @file{expression.h}. Also, add the
+printed representations of your operators to @code{op_print_tab}.
+
+@item Add a place of call
+
+Add a call to @code{@var{lang}_parse()} and @code{@var{lang}_error} in
+@code{parse.c:parse_exp_1()}.
+
+@item Use macros to trim code
+
+The user has the option of building GDB for some or all of the
+languages. If the user decides to build GDB for the language
+@var{lang}, then every file dependent on @file{language.h} will have the
+macro @code{_LANG_@var{lang}} defined in it. Use @code{#ifdef}s to
+leave out large routines that the user won't need if he or she is not
+using your language.
+
+Note that you do not need to do this in your YACC parser, since if GDB
+is not build for @var{lang}, then @file{@var{lang}-exp.tab.o} (the
+compiled form of your parser) is not linked into GDB at all.
+
+See the file @file{configure.in} for how GDB is configured for different
+languages.
+
+@item Edit @file{Makefile.in}
+
+Add dependencies in @file{Makefile.in}. Make sure you update the macro
+variables such as @code{HFILES} and @code{OBJS}, otherwise your code may
+not get linked in, or, worse yet, it may not get @code{tar}red into the
+distribution!
+@end table
+
+
+@node Releases
+@chapter Configuring GDB for Release
+
+From the top level directory (containing @file{gdb}, @file{bfd},
+@file{libiberty}, and so on):
+@example
+make -f Makefile.in gdb.tar.gz
+@end example
+
+This will properly configure, clean, rebuild any files that are
+distributed pre-built (e.g. @file{c-exp.tab.c} or @file{refcard.ps}),
+and will then make a tarfile. (If the top level directory has already
+been configured, you can just do @code{make gdb.tar.gz} instead.)
+
+This procedure requires:
+@itemize @bullet
+@item symbolic links
+@item @code{makeinfo} (texinfo2 level)
+@item @TeX{}
+@item @code{dvips}
+@item @code{yacc} or @code{bison}
+@end itemize
+@noindent
+@dots{} and the usual slew of utilities (@code{sed}, @code{tar}, etc.).
+
+@subheading TEMPORARY RELEASE PROCEDURE FOR DOCUMENTATION
+
+@file{gdb.texinfo} is currently marked up using the texinfo-2 macros,
+which are not yet a default for anything (but we have to start using
+them sometime).
+
+For making paper, the only thing this implies is the right generation of
+@file{texinfo.tex} needs to be included in the distribution.
+
+For making info files, however, rather than duplicating the texinfo2
+distribution, generate @file{gdb-all.texinfo} locally, and include the files
+@file{gdb.info*} in the distribution. Note the plural; @code{makeinfo} will
+split the document into one overall file and five or so included files.
+
+
+@node Partial Symbol Tables
+@chapter Partial Symbol Tables
+
+GDB has three types of symbol tables.
+
+@itemize @bullet
+@item full symbol tables (symtabs). These contain the main
+information about symbols and addresses.
+@item partial symbol tables (psymtabs). These contain enough
+information to know when to read the corresponding
+part of the full symbol table.
+@item minimal symbol tables (msymtabs). These contain information
+gleaned from non-debugging symbols.
+@end itemize
+
+This section describes partial symbol tables.
+
+A psymtab is constructed by doing a very quick pass over an executable
+file's debugging information. Small amounts of information are
+extracted -- enough to identify which parts of the symbol table will
+need to be re-read and fully digested later, when the user needs the
+information. The speed of this pass causes GDB to start up very
+quickly. Later, as the detailed rereading occurs, it occurs in small
+pieces, at various times, and the delay therefrom is mostly invisible to
+the user. (@xref{Symbol Reading}.)
+
+The symbols that show up in a file's psymtab should be, roughly, those
+visible to the debugger's user when the program is not running code from
+that file. These include external symbols and types, static
+symbols and types, and enum values declared at file scope.
+
+The psymtab also contains the range of instruction addresses that the
+full symbol table would represent.
+
+The idea is that there are only two ways for the user (or much of
+the code in the debugger) to reference a symbol:
+
+@itemize @bullet
+
+@item by its address
+(e.g. execution stops at some address which is inside a function
+in this file). The address will be noticed to be in the
+range of this psymtab, and the full symtab will be read in.
+@code{find_pc_function}, @code{find_pc_line}, and other @code{find_pc_@dots{}}
+functions handle this.
+
+@item by its name
+(e.g. the user asks to print a variable, or set a breakpoint on a
+function). Global names and file-scope names will be found in the
+psymtab, which will cause the symtab to be pulled in. Local names will
+have to be qualified by a global name, or a file-scope name, in which
+case we will have already read in the symtab as we evaluated the
+qualifier. Or, a local symbol can be referenced when
+we are "in" a local scope, in which case the first case applies.
+@code{lookup_symbol} does most of the work here.
+
+@end itemize
+
+The only reason that psymtabs exist is to cause a symtab to be read in
+at the right moment. Any symbol that can be elided from a psymtab,
+while still causing that to happen, should not appear in it. Since
+psymtabs don't have the idea of scope, you can't put local symbols in
+them anyway. Psymtabs don't have the idea of the type of a symbol,
+either, so types need not appear, unless they will be referenced by
+name.
+
+It is a bug for GDB to behave one way when only a psymtab has been read,
+and another way if the corresponding symtab has been read in. Such
+bugs are typically caused by a psymtab that does not contain all the
+visible symbols, or which has the wrong instruction address ranges.
+
+The psymtab for a particular section of a symbol-file (objfile)
+could be thrown away after the symtab has been read in. The symtab
+should always be searched before the psymtab, so the psymtab will
+never be used (in a bug-free environment). Currently,
+psymtabs are allocated on an obstack, and all the psymbols themselves
+are allocated in a pair of large arrays on an obstack, so there is
+little to be gained by trying to free them unless you want to do a lot
+more work.
+
+@node Types
+@chapter Types
+
+Fundamental Types (e.g., FT_VOID, FT_BOOLEAN).
+
+These are the fundamental types that GDB uses internally. Fundamental
+types from the various debugging formats (stabs, ELF, etc) are mapped into
+one of these. They are basically a union of all fundamental types that
+gdb knows about for all the languages that GDB knows about.
+
+Type Codes (e.g., TYPE_CODE_PTR, TYPE_CODE_ARRAY).
+
+Each time GDB builds an internal type, it marks it with one of these
+types. The type may be a fundamental type, such as TYPE_CODE_INT, or
+a derived type, such as TYPE_CODE_PTR which is a pointer to another
+type. Typically, several FT_* types map to one TYPE_CODE_* type, and
+are distinguished by other members of the type struct, such as whether
+the type is signed or unsigned, and how many bits it uses.
+
+Builtin Types (e.g., builtin_type_void, builtin_type_char).
+
+These are instances of type structs that roughly correspond to fundamental
+types and are created as global types for GDB to use for various ugly
+historical reasons. We eventually want to eliminate these. Note for
+example that builtin_type_int initialized in gdbtypes.c is basically the
+same as a TYPE_CODE_INT type that is initialized in c-lang.c for an
+FT_INTEGER fundamental type. The difference is that the builtin_type is
+not associated with any particular objfile, and only one instance exists,
+while c-lang.c builds as many TYPE_CODE_INT types as needed, with each
+one associated with some particular objfile.
+
+@node BFD support for GDB
+@chapter Binary File Descriptor Library Support for GDB
+
+BFD provides support for GDB in several ways:
+
+@table @emph
+@item identifying executable and core files
+BFD will identify a variety of file types, including a.out, coff, and
+several variants thereof, as well as several kinds of core files.
+
+@item access to sections of files
+BFD parses the file headers to determine the names, virtual addresses,
+sizes, and file locations of all the various named sections in files
+(such as the text section or the data section). GDB simply calls
+BFD to read or write section X at byte offset Y for length Z.
+
+@item specialized core file support
+BFD provides routines to determine the failing command name stored
+in a core file, the signal with which the program failed, and whether
+a core file matches (i.e. could be a core dump of) a particular executable
+file.
+
+@item locating the symbol information
+GDB uses an internal interface of BFD to determine where to find the
+symbol information in an executable file or symbol-file. GDB itself
+handles the reading of symbols, since BFD does not ``understand'' debug
+symbols, but GDB uses BFD's cached information to find the symbols,
+string table, etc.
+@end table
+
+@c The interface for symbol reading is described in @ref{Symbol
+@c Reading,,Symbol Reading}.
+
+
+@node Symbol Reading
+@chapter Symbol Reading
+
+GDB reads symbols from "symbol files". The usual symbol file is the
+file containing the program which GDB is debugging. GDB can be directed
+to use a different file for symbols (with the ``symbol-file''
+command), and it can also read more symbols via the ``add-file'' and ``load''
+commands, or while reading symbols from shared libraries.
+
+Symbol files are initially opened by @file{symfile.c} using the BFD
+library. BFD identifies the type of the file by examining its header.
+@code{symfile_init} then uses this identification to locate a
+set of symbol-reading functions.
+
+Symbol reading modules identify themselves to GDB by calling
+@code{add_symtab_fns} during their module initialization. The argument
+to @code{add_symtab_fns} is a @code{struct sym_fns} which contains
+the name (or name prefix) of the symbol format, the length of the prefix,
+and pointers to four functions. These functions are called at various
+times to process symbol-files whose identification matches the specified
+prefix.
+
+The functions supplied by each module are:
+
+@table @code
+@item @var{xxx}_symfile_init(struct sym_fns *sf)
+
+Called from @code{symbol_file_add} when we are about to read a new
+symbol file. This function should clean up any internal state
+(possibly resulting from half-read previous files, for example)
+and prepare to read a new symbol file. Note that the symbol file
+which we are reading might be a new "main" symbol file, or might
+be a secondary symbol file whose symbols are being added to the
+existing symbol table.
+
+The argument to @code{@var{xxx}_symfile_init} is a newly allocated
+@code{struct sym_fns} whose @code{bfd} field contains the BFD
+for the new symbol file being read. Its @code{private} field
+has been zeroed, and can be modified as desired. Typically,
+a struct of private information will be @code{malloc}'d, and
+a pointer to it will be placed in the @code{private} field.
+
+There is no result from @code{@var{xxx}_symfile_init}, but it can call
+@code{error} if it detects an unavoidable problem.
+
+@item @var{xxx}_new_init()
+
+Called from @code{symbol_file_add} when discarding existing symbols.
+This function need only handle
+the symbol-reading module's internal state; the symbol table data
+structures visible to the rest of GDB will be discarded by
+@code{symbol_file_add}. It has no arguments and no result.
+It may be called after @code{@var{xxx}_symfile_init}, if a new symbol
+table is being read, or may be called alone if all symbols are
+simply being discarded.
+
+@item @var{xxx}_symfile_read(struct sym_fns *sf, CORE_ADDR addr, int mainline)
+
+Called from @code{symbol_file_add} to actually read the symbols from a
+symbol-file into a set of psymtabs or symtabs.
+
+@code{sf} points to the struct sym_fns originally passed to
+@code{@var{xxx}_sym_init} for possible initialization. @code{addr} is the
+offset between the file's specified start address and its true address
+in memory. @code{mainline} is 1 if this is the main symbol table being
+read, and 0 if a secondary symbol file (e.g. shared library or
+dynamically loaded file) is being read.@refill
+@end table
+
+In addition, if a symbol-reading module creates psymtabs when
+@var{xxx}_symfile_read is called, these psymtabs will contain a pointer to
+a function @code{@var{xxx}_psymtab_to_symtab}, which can be called from
+any point in the GDB symbol-handling code.
+
+@table @code
+@item @var{xxx}_psymtab_to_symtab (struct partial_symtab *pst)
+
+Called from @code{psymtab_to_symtab} (or the PSYMTAB_TO_SYMTAB
+macro) if the psymtab has not already been read in and had its
+@code{pst->symtab} pointer set. The argument is the psymtab
+to be fleshed-out into a symtab. Upon return, pst->readin
+should have been set to 1, and pst->symtab should contain a
+pointer to the new corresponding symtab, or zero if there
+were no symbols in that part of the symbol file.
+@end table
+
+
+@node Cleanups
+@chapter Cleanups
+
+Cleanups are a structured way to deal with things that need to be done
+later. When your code does something (like @code{malloc} some memory, or open
+a file) that needs to be undone later (e.g. free the memory or close
+the file), it can make a cleanup. The cleanup will be done at some
+future point: when the command is finished, when an error occurs, or
+when your code decides it's time to do cleanups.
+
+You can also discard cleanups, that is, throw them away without doing
+what they say. This is only done if you ask that it be done.
+
+Syntax:
+
+@table @code
+@item struct cleanup *@var{old_chain};
+Declare a variable which will hold a cleanup chain handle.
+
+@item @var{old_chain} = make_cleanup (@var{function}, @var{arg});
+Make a cleanup which will cause @var{function} to be called with @var{arg}
+(a @code{char *}) later. The result, @var{old_chain}, is a handle that can be
+passed to @code{do_cleanups} or @code{discard_cleanups} later. Unless you are
+going to call @code{do_cleanups} or @code{discard_cleanups} yourself,
+you can ignore the result from @code{make_cleanup}.
+
+
+@item do_cleanups (@var{old_chain});
+Perform all cleanups done since @code{make_cleanup} returned @var{old_chain}.
+E.g.:
+@example
+make_cleanup (a, 0);
+old = make_cleanup (b, 0);
+do_cleanups (old);
+@end example
+@noindent
+will call @code{b()} but will not call @code{a()}. The cleanup that calls @code{a()} will remain
+in the cleanup chain, and will be done later unless otherwise discarded.@refill
+
+@item discard_cleanups (@var{old_chain});
+Same as @code{do_cleanups} except that it just removes the cleanups from the
+chain and does not call the specified functions.
+
+@end table
+
+Some functions, e.g. @code{fputs_filtered()} or @code{error()}, specify that they
+``should not be called when cleanups are not in place''. This means
+that any actions you need to reverse in the case of an error or
+interruption must be on the cleanup chain before you call these functions,
+since they might never return to your code (they @samp{longjmp} instead).
+
+
+@node Wrapping
+@chapter Wrapping Output Lines
+
+Output that goes through @code{printf_filtered} or @code{fputs_filtered} or
+@code{fputs_demangled} needs only to have calls to @code{wrap_here} added
+in places that would be good breaking points. The utility routines
+will take care of actually wrapping if the line width is exceeded.
+
+The argument to @code{wrap_here} is an indentation string which is printed
+@emph{only} if the line breaks there. This argument is saved away and used
+later. It must remain valid until the next call to @code{wrap_here} or
+until a newline has been printed through the @code{*_filtered} functions.
+Don't pass in a local variable and then return!
+
+It is usually best to call @code{wrap_here()} after printing a comma or space.
+If you call it before printing a space, make sure that your indentation
+properly accounts for the leading space that will print if the line wraps
+there.
+
+Any function or set of functions that produce filtered output must finish
+by printing a newline, to flush the wrap buffer, before switching to
+unfiltered (``@code{printf}'') output. Symbol reading routines that print
+warnings are a good example.
+
+
+@node Frames
+@chapter Frames
+
+A frame is a construct that GDB uses to keep track of calling and called
+functions.
+
+@table @code
+@item FRAME_FP
+in the machine description has no meaning to the machine-independent
+part of GDB, except that it is used when setting up a new frame from
+scratch, as follows:
+
+@example
+ create_new_frame (read_register (FP_REGNUM), read_pc ()));
+@end example
+
+Other than that, all the meaning imparted to @code{FP_REGNUM} is imparted by
+the machine-dependent code. So, @code{FP_REGNUM} can have any value that
+is convenient for the code that creates new frames. (@code{create_new_frame}
+calls @code{INIT_EXTRA_FRAME_INFO} if it is defined; that is where you should
+use the @code{FP_REGNUM} value, if your frames are nonstandard.)
+
+@item FRAME_CHAIN
+Given a GDB frame, determine the address of the calling function's
+frame. This will be used to create a new GDB frame struct, and then
+@code{INIT_EXTRA_FRAME_INFO} and @code{INIT_FRAME_PC} will be called for
+the new frame.
+@end table
+
+@node Remote Stubs
+@chapter Remote Stubs
+
+GDB's file @file{remote.c} talks a serial protocol to code that runs
+in the target system. GDB provides several sample ``stubs'' that can
+be integrated into target programs or operating systems for this purpose;
+they are named @file{*-stub.c}.
+
+The GDB user's manual describes how to put such a stub into your target
+code. What follows is a discussion of integrating the SPARC stub
+into a complicated operating system (rather than a simple program),
+by Stu Grossman, the author of this stub.
+
+The trap handling code in the stub assumes the following upon entry to
+trap_low:
+
+@enumerate
+@item %l1 and %l2 contain pc and npc respectively at the time of the trap
+@item traps are disabled
+@item you are in the correct trap window
+@end enumerate
+
+As long as your trap handler can guarantee those conditions, then there is no
+reason why you shouldn't be able to `share' traps with the stub. The stub has
+no requirement that it be jumped to directly from the hardware trap vector.
+That is why it calls @code{exceptionHandler()}, which is provided by the external
+environment. For instance, this could setup the hardware traps to actually
+execute code which calls the stub first, and then transfers to its own trap
+handler.
+
+For the most point, there probably won't be much of an issue with `sharing'
+traps, as the traps we use are usually not used by the kernel, and often
+indicate unrecoverable error conditions. Anyway, this is all controlled by a
+table, and is trivial to modify.
+The most important trap for us is for @code{ta 1}. Without that, we
+can't single step or do breakpoints. Everything else is unnecessary
+for the proper operation of the debugger/stub.
+
+From reading the stub, it's probably not obvious how breakpoints work. They
+are simply done by deposit/examine operations from GDB.
+
+@node Longjmp Support
+@chapter Longjmp Support
+
+GDB has support for figuring out that the target is doing a
+@code{longjmp} and for stopping at the target of the jump, if we are
+stepping. This is done with a few specialized internal breakpoints,
+which are visible in the @code{maint info breakpoint} command.
+
+To make this work, you need to define a macro called
+@code{GET_LONGJMP_TARGET}, which will examine the @code{jmp_buf}
+structure and extract the longjmp target address. Since @code{jmp_buf}
+is target specific, you will need to define it in the appropriate
+@file{tm-xxx.h} file. Look in @file{tm-sun4os4.h} and
+@file{sparc-tdep.c} for examples of how to do this.
+
+@node Coding Style
+@chapter Coding Style
+
+GDB is generally written using the GNU coding standards, as described in
+@file{standards.texi}, which is available for anonymous FTP from GNU
+archive sites. There are some additional considerations for GDB
+maintainers that reflect the unique environment and style of GDB
+maintenance. If you follow these guidelines, GDB will be more
+consistent and easier to maintain.
+
+GDB's policy on the use of prototypes is that prototypes are used
+to @emph{declare} functions but never to @emph{define} them. Simple
+macros are used in the declarations, so that a non-ANSI compiler can
+compile GDB without trouble. The simple macro calls are used like
+this:
+
+@example @code
+extern int
+memory_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+@end example
+
+Note the double parentheses around the parameter types. This allows
+an arbitrary number of parameters to be described, without freaking
+out the C preprocessor. When the function has no parameters, it
+should be described like:
+
+@example @code
+void
+noprocess PARAMS ((void));
+@end example
+
+The @code{PARAMS} macro expands to its argument in ANSI C, or to a simple
+@code{()} in traditional C.
+
+All external functions should have a @code{PARAMS} declaration in a
+header file that callers include. All static functions should have such
+a declaration near the top of their source file.
+
+We don't have a gcc option that will properly check that these rules
+have been followed, but it's GDB policy, and we periodically check it
+using the tools available (plus manual labor), and clean up any remnants.
+
+@node Clean Design
+@chapter Clean Design
+
+In addition to getting the syntax right, there's the little question of
+semantics. Some things are done in certain ways in GDB because long
+experience has shown that the more obvious ways caused various kinds of
+trouble. In particular:
+
+@table @bullet
+@item
+You can't assume the byte order of anything that comes from a
+target (including @var{value}s, object files, and instructions). Such
+things must be byte-swapped using @code{SWAP_TARGET_AND_HOST} in GDB,
+or one of the swap routines defined in @file{bfd.h}, such as @code{bfd_get_32}.
+
+@item
+You can't assume that you know what interface is being used to talk to
+the target system. All references to the target must go through the
+current @code{target_ops} vector.
+
+@item
+You can't assume that the host and target machines are the same machine
+(except in the ``native'' support modules).
+In particular, you can't assume that the target machine's header files
+will be available on the host machine. Target code must bring along its
+own header files -- written from scratch or explicitly donated by their
+owner, to avoid copyright problems.
+
+@item
+Insertion of new @code{#ifdef}'s will be frowned upon. It's much better
+to write the code portably than to conditionalize it for various systems.
+
+@item
+New @code{#ifdef}'s which test for specific compilers or manufacturers
+or operating systems are unacceptable. All @code{#ifdef}'s should test
+for features. The information about which configurations contain which
+features should be segregated into the configuration files. Experience
+has proven far too often that a feature unique to one particular system
+often creeps into other systems; and that a conditional based on
+some predefined macro for your current system will become worthless
+over time, as new versions of your system come out that behave differently
+with regard to this feature.
+
+@item
+Adding code that handles specific architectures, operating systems, target
+interfaces, or hosts, is not acceptable in generic code. If a hook
+is needed at that point, invent a generic hook and define it for your
+configuration, with something like:
+
+@example
+#ifdef WRANGLE_SIGNALS
+ WRANGLE_SIGNALS (signo);
+#endif
+@end example
+
+In your host, target, or native configuration file, as appropriate,
+define @code{WRANGLE_SIGNALS} to do the machine-dependent thing. Take
+a bit of care in defining the hook, so that it can be used by other
+ports in the future, if they need a hook in the same place.
+
+If the hook is not defined, the code should do whatever "most" machines
+want. Using @code{#ifdef}, as above, is the preferred way to do this,
+but sometimes that gets convoluted, in which case use
+
+@example
+#ifndef SPECIAL_FOO_HANDLING
+#define SPECIAL_FOO_HANDLING(pc, sp) (0)
+#endif
+@end example
+
+where the macro is used or in an appropriate header file.
+
+Whether to include a @dfn{small} hook, a hook around the exact pieces of
+code which are system-dependent, or whether to replace a whole function
+with a hook depends on the case. A good example of this dilemma can be
+found in @code{get_saved_register}. All machines that GDB 2.8 ran on
+just needed the @code{FRAME_FIND_SAVED_REGS} hook to find the saved
+registers. Then the SPARC and Pyramid came along, and
+@code{HAVE_REGISTER_WINDOWS} and @code{REGISTER_IN_WINDOW_P} were
+introduced. Then the 29k and 88k required the @code{GET_SAVED_REGISTER}
+hook. The first three are examples of small hooks; the latter replaces
+a whole function. In this specific case, it is useful to have both
+kinds; it would be a bad idea to replace all the uses of the small hooks
+with @code{GET_SAVED_REGISTER}, since that would result in much
+duplicated code. Other times, duplicating a few lines of code here or
+there is much cleaner than introducing a large number of small hooks.
+
+Another way to generalize GDB along a particular interface is with an
+attribute struct. For example, GDB has been generalized to handle
+multiple kinds of remote interfaces -- not by #ifdef's everywhere, but
+by defining the "target_ops" structure and having a current target (as
+well as a stack of targets below it, for memory references). Whenever
+something needs to be done that depends on which remote interface we are
+using, a flag in the current target_ops structure is tested (e.g.
+`target_has_stack'), or a function is called through a pointer in the
+current target_ops structure. In this way, when a new remote interface
+is added, only one module needs to be touched -- the one that actually
+implements the new remote interface. Other examples of
+attribute-structs are BFD access to multiple kinds of object file
+formats, or GDB's access to multiple source languages.
+
+Please avoid duplicating code. For example, in GDB 3.x all the code
+interfacing between @code{ptrace} and the rest of GDB was duplicated in
+@file{*-dep.c}, and so changing something was very painful. In GDB 4.x,
+these have all been consolidated into @file{infptrace.c}.
+@file{infptrace.c} can deal with variations between systems the same way
+any system-independent file would (hooks, #if defined, etc.), and
+machines which are radically different don't need to use infptrace.c at
+all.
+
+@item
+@emph{Do} write code that doesn't depend on the sizes of C data types,
+the format of the host's floating point numbers, the alignment of anything,
+or the order of evaluation of expressions. In short, follow good
+programming practices for writing portable C code.
+
+@end table
+
+@node Submitting Patches
+@chapter Submitting Patches
+
+Thanks for thinking of offering your changes back to the community of
+GDB users. In general we like to get well designed enhancements.
+Thanks also for checking in advance about the best way to transfer the
+changes.
+
+The two main problems with getting your patches in are,
+
+@table @bullet
+@item
+The GDB maintainers will only install ``cleanly designed'' patches.
+You may not always agree on what is clean design.
+@pxref{Coding Style}, @pxref{Clean Design}.
+
+@item
+If the maintainers don't have time to put the patch in when it
+arrives, or if there is any question about a patch, it
+goes into a large queue with everyone else's patches and
+bug reports.
+@end table
+
+I don't know how to get past these problems except by continuing to try.
+
+There are two issues here -- technical and legal.
+
+The legal issue is that to incorporate substantial changes requires a
+copyright assignment from you and/or your employer, granting ownership
+of the changes to the Free Software Foundation. You can get the
+standard document for doing this by sending mail to
+@code{gnu@@prep.ai.mit.edu} and asking for it. I recommend that people
+write in "All programs owned by the Free Software Foundation" as "NAME
+OF PROGRAM", so that changes in many programs (not just GDB, but GAS,
+Emacs, GCC, etc) can be contributed with only one piece of legalese
+pushed through the bureacracy and filed with the FSF. I can't start
+merging changes until this paperwork is received by the FSF (their
+rules, which I follow since I maintain it for them).
+
+Technically, the easiest way to receive changes is to receive each
+feature as a small context diff or unidiff, suitable for "patch".
+Each message sent to me should include the changes to C code and
+header files for a single feature, plus ChangeLog entries for each
+directory where files were modified, and diffs for any changes needed
+to the manuals (gdb/doc/gdb.texi or gdb/doc/gdbint.texi). If there
+are a lot of changes for a single feature, they can be split down
+into multiple messages.
+
+In this way, if I read and like the feature, I can add it to the
+sources with a single patch command, do some testing, and check it in.
+If you leave out the ChangeLog, I have to write one. If you leave
+out the doc, I have to puzzle out what needs documenting. Etc.
+
+The reason to send each change in a separate message is that I will
+not install some of the changes. They'll be returned to you with
+questions or comments. If I'm doing my job, my message back to you
+will say what you have to fix in order to make the change acceptable.
+The reason to have separate messages for separate features is so
+that other changes (which I @emph{am} willing to accept) can be installed
+while one or more changes are being reworked. If multiple features
+are sent in a single message, I tend to not put in the effort to sort
+out the acceptable changes from the unacceptable, so none of the
+features get installed until all are acceptable.
+
+If this sounds painful or authoritarian, well, it is. But I get a lot
+of bug reports and a lot of patches, and most of them don't get
+installed because I don't have the time to finish the job that the bug
+reporter or the contributor could have done. Patches that arrive
+complete, working, and well designed, tend to get installed on the day
+they arrive. The others go into a queue and get installed if and when
+I scan back over the queue -- which can literally take months
+sometimes. It's in both our interests to make patch installation easy
+-- you get your changes installed, and I make some forward progress on
+GDB in a normal 12-hour day (instead of them having to wait until I
+have a 14-hour or 16-hour day to spend cleaning up patches before I
+can install them).
+
+Please send patches to @code{bug-gdb@@prep.ai.mit.edu}, if they are less
+than about 25,000 characters. If longer than that, either make them
+available somehow (e.g. anonymous FTP), and announce it on
+@code{bug-gdb}, or send them directly to the GDB maintainers at
+@code{gdb-patches@@cygnus.com}.
+
+@node Host Conditionals
+@chapter Host Conditionals
+
+When GDB is configured and compiled, various macros are defined or left
+undefined, to control compilation based on the attributes of the host
+system. These macros and their meanings (or if the meaning is not
+documented here, then one of the source files where they are used is
+indicated) are:
+
+@emph{NOTE: For now, both host and target conditionals are here.
+Eliminate target conditionals from this list as they are identified.}
+
+@table @code
+
+@item BLOCK_ADDRESS_FUNCTION_RELATIVE
+dbxread.c
+
+@item GDBINIT_FILENAME
+The default name of GDB's initialization file (normally @file{.gdbinit}).
+
+@item MEM_FNS_DECLARED
+Your host config file defines this if it includes
+declarations of @code{memcpy} and @code{memset}. Define this
+to avoid conflicts between the native include
+files and the declarations in @file{defs.h}.
+
+@item NO_SYS_FILE
+Define this if your system does not have a @code{<sys/file.h>}.
+
+@item SIGWINCH_HANDLER
+If your host defines @code{SIGWINCH}, you can define this to
+be the name of a function to be called if @code{SIGWINCH} is received.
+
+@item SIGWINCH_HANDLER_BODY
+Define this to expand into code that will define the function
+named by the expansion of @code{SIGWINCH_HANDLER}.
+
+@item ADDITIONAL_OPTIONS
+main.c
+@item ADDITIONAL_OPTION_CASES
+main.c
+@item ADDITIONAL_OPTION_HANDLER
+main.c
+@item ADDITIONAL_OPTION_HELP
+main.c
+
+@item AIX_BUGGY_PTRACE_CONTINUE
+infptrace.c
+
+@item ALIGN_STACK_ON_STARTUP
+Define this if your system is of a sort that will crash in @code{tgetent}
+if the stack happens not to be longword-aligned when @code{main} is
+called. This is a rare situation, but is known to occur on several
+different types of systems.
+
+@item CFRONT_PRODUCER
+dwarfread.c
+@item DBX_PARM_SYMBOL_CLASS
+stabsread.c
+
+@item DEFAULT_PROMPT
+The default value of the prompt string (normally @code{"(gdb) "}).
+
+@item DEV_TTY
+symmisc.c
+@item DO_REGISTERS_INFO
+infcmd.c
+
+@item FCLOSE_PROVIDED
+Define this if the system declares @code{fclose} in the headers included in
+@code{defs.h}. This isn't needed unless your compiler is unusually anal.
+
+@sc{ANSI} definition.
+
+@item FILES_INFO_HOOK
+target.c
+@item FLOAT_INFO
+infcmd.c
+
+@item FOPEN_RB
+Define this if binary files are opened the same way as text files.
+
+@item GCC2_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_MANGLE_BUG
+symtab.c
+@item GCC_PRODUCER
+dwarfread.c
+
+@item GETENV_PROVIDED
+Define this if the system declares @code{getenv} in its headers included in
+@code{defs.h}. This isn't needed unless your compiler is unusually anal.
+
+@item GPLUS_PRODUCER
+dwarfread.c
+
+@item HAVE_MMAP
+In some cases, use the system call @code{mmap} for reading symbol
+tables. For some machines this allows for sharing and quick updates.
+
+@item HAVE_SIGSETMASK
+Define this if the host system has job control, but does not
+define @code{sigsetmask()}.
+Currently, this is only true of the RS/6000.
+
+@item HAVE_TERMIO
+inflow.c
+
+@item HOST_BYTE_ORDER
+The ordering of bytes in the host.
+This must be defined to be either @code{BIG_ENDIAN} or @code{LITTLE_ENDIAN}.
+
+@item INT_MAX
+@item INT_MIN
+@item LONG_MAX
+@item UINT_MAX
+@item ULONG_MAX
+Values for host-side constants.
+
+@item ISATTY
+Substitute for isatty, if not available.
+
+@item KERNEL_DEBUGGING
+tm-ultra3.h
+
+@item KERNEL_U_ADDR
+Define this to the address of the @code{u} structure (the ``user struct'',
+also known as the ``u-page'') in kernel virtual memory. GDB needs to know
+this so that it can subtract this address from absolute addresses in
+the upage, that are obtained via ptrace or from core files. On systems
+that don't need this value, set it to zero.
+
+@item KERNEL_U_ADDR_BSD
+Define this to cause GDB to determine the address of @code{u} at runtime,
+by using Berkeley-style @code{nlist} on the kernel's image in the root
+directory.
+
+@item KERNEL_U_ADDR_HPUX
+Define this to cause GDB to determine the address of @code{u} at runtime,
+by using HP-style @code{nlist} on the kernel's image in the root
+directory.
+
+@item LCC_PRODUCER
+dwarfread.c
+
+@item LONGEST
+This is the longest integer type available on the host.
+If not defined, it will default to @code{long long} or @code{long},
+depending on @code{CC_HAS_LONG_LONG}.
+
+@item CC_HAS_LONG_LONG
+Define this if the host C compiler supports ``long long''.
+This will be defined automatically if GNU CC is used to compile GDB.
+
+@item PRINTF_HAS_LONG_LONG
+Define this if the host can handle printing of long long integers via a
+format directive ``ll''.
+
+@item LSEEK_NOT_LINEAR
+source.c
+@item L_LNNO32
+coffread.c
+
+@item L_SET
+This macro is used as the argument to lseek (or, most commonly, bfd_seek).
+FIXME, should be replaced by SEEK_SET instead, which is the POSIX equivalent.
+
+@item MAINTENANCE_CMDS
+If the value of this is 1, then a number of optional maintenance commands
+are compiled in.
+
+@item MALLOC_INCOMPATIBLE
+Define this if the system's prototype for @code{malloc} differs from the
+@sc{ANSI} definition.
+
+@item MMAP_BASE_ADDRESS
+When using HAVE_MMAP, the first mapping should go at this address.
+
+@item MMAP_INCREMENT
+when using HAVE_MMAP, this is the increment between mappings.
+
+@item NEED_POSIX_SETPGID
+Define this to use the POSIX version of @code{setpgid} to determine
+whether job control is available.
+
+@item NORETURN
+If defined, this should be one or more tokens, such as @code{volatile},
+that can be used in both the declaration and definition of functions
+to indicate that they never return. The default is already set
+correctly if compiling with GCC.
+This will almost never need to be defined.
+
+@item ATTR_NORETURN
+If defined, this should be one or more tokens, such as
+@code{__attribute__ ((noreturn))}, that can be used in the declarations
+of functions to indicate that they never return. The default is already
+set correctly if compiling with GCC.
+This will almost never need to be defined.
+
+@item NOTICE_SIGNAL_HANDLING_CHANGE
+infrun.c
+@item NO_HIF_SUPPORT
+remote-mm.c
+@item NO_JOB_CONTROL
+signals.h
+
+@item NO_MMALLOC
+GDB will use the @code{mmalloc} library for memory allocation for symbol
+reading, unless this symbol is defined. Define it on systems
+on which @code{mmalloc} does not
+work for some reason. One example is the DECstation, where its RPC
+library can't cope with our redefinition of @code{malloc} to call
+@code{mmalloc}. When defining @code{NO_MMALLOC}, you will also have
+to override the setting of @code{MMALLOC_LIB} to empty, in the Makefile.
+Therefore, this define is usually set on the command line by overriding
+@code{MMALLOC_DISABLE} in @file{config/*/*.mh}, rather than by defining
+it in @file{xm-*.h}.
+
+@item NO_MMALLOC_CHECK
+Define this if you are using @code{mmalloc}, but don't want the overhead
+of checking the heap with @code{mmcheck}.
+
+@item NO_SIGINTERRUPT
+remote-adapt.c
+@item NUMERIC_REG_NAMES
+mips-tdep.c
+@item N_SETV
+dbxread.c
+@item N_SET_MAGIC
+hppabsd-tdep.c
+@item ONE_PROCESS_WRITETEXT
+breakpoint.c
+@item O_BINARY
+exec.c
+@item O_RDONLY
+xm-ultra3.h
+@item PCC_SOL_BROKEN
+dbxread.c
+@item PC_LOAD_SEGMENT
+stack.c
+@item PRINT_RANDOM_SIGNAL
+infcmd.c
+@item PRINT_REGISTER_HOOK
+infcmd.c
+@item PROCESS_LINENUMBER_HOOK
+buildsym.c
+@item PROLOGUE_FIRSTLINE_OVERLAP
+infrun.c
+@item PUSH_ARGUMENTS
+valops.c
+@item PYRAMID_CONTROL_FRAME_DEBUGGING
+pyr-xdep.c
+@item PYRAMID_CORE
+pyr-xdep.c
+@item PYRAMID_PTRACE
+pyr-xdep.c
+@item REGISTER_BYTES
+remote.c
+@item REG_STACK_SEGMENT
+exec.c
+@item REG_STRUCT_HAS_ADDR
+findvar.c
+@item R_FP
+dwarfread.c
+@item R_OK
+xm-altos.h
+@item SEEK_END
+state.c
+@item SEEK_SET
+state.c
+@item SEM
+coffread.c
+
+@item SHELL_COMMAND_CONCAT
+infrun.c
+@item SHELL_FILE
+infrun.c
+@item SHIFT_INST_REGS
+breakpoint.c
+@item SIGTRAP_STOP_AFTER_LOAD
+infrun.c
+@item STACK_ALIGN
+valops.c
+@item STOP_SIGNAL
+main.c
+@item SUN4_COMPILER_FEATURE
+infrun.c
+@item SUN_FIXED_LBRAC_BUG
+dbxread.c
+@item SVR4_SHARED_LIBS
+solib.c
+@item SYMBOL_RELOADING_DEFAULT
+symfile.c
+@item TIOCGETC
+inflow.c
+@item TIOCGLTC
+inflow.c
+@item TIOCGPGRP
+inflow.c
+@item TIOCLGET
+inflow.c
+@item TIOCLSET
+inflow.c
+@item TIOCNOTTY
+inflow.c
+@item UPAGES
+altos-xdep.c
+@item USE_O_NOCTTY
+inflow.c
+
+@item USG
+Means that System V (prior to SVR4) include files are in use.
+(FIXME: This symbol is abused in @file{infrun.c}, @file{regex.c},
+@file{remote-nindy.c}, and @file{utils.c} for other things, at the moment.)
+
+@item WRS_ORIG
+remote-vx.c
+@item alloca
+defs.h
+@item const
+defs.h
+
+@item lint
+Define this to help lint in some stupid way.
+
+@item volatile
+Define this to override the defaults of @code{__volatile__} or @code{/**/}.
+
+@end table
+
+Platform-specific host conditionals.
+
+@table @code
+
+@item ALTOS
+altos-xdep.c
+@item ALTOS_AS
+xm-altos.h
+@item MOTOROLA
+xm-altos.h
+@item NBPG
+altos-xdep.c
+
+@item BCS
+tm-delta88.h
+
+@item DELTA88
+m88k-xdep.c
+@item DGUX
+m88k-xdep.c
+
+@item F_OK
+xm-ultra3.h
+
+@end table
+
+Regex conditionals.
+
+@table @code
+
+@item C_ALLOCA
+regex.c
+@item NFAILURES
+regex.c
+@item RE_NREGS
+regex.h
+@item SIGN_EXTEND_CHAR
+regex.c
+@item SWITCH_ENUM_BUG
+regex.c
+@item SYNTAX_TABLE
+regex.c
+@item Sword
+regex.c
+@item sparc
+regex.c
+@item test
+regex.c
+
+@end table
+
+@node Target Conditionals
+@chapter Target Conditionals
+
+When GDB is configured and compiled, various macros are defined or left
+undefined, to control compilation based on the attributes of the target
+system. These macros and their meanings are:
+
+@emph{NOTE: For now, both host and target conditionals are here.
+Eliminate host conditionals from this list as they are identified.}
+
+@table @code
+
+@item PUSH_DUMMY_FRAME
+Used in @samp{call_function_by_hand} to create an artificial stack frame.
+
+@item POP_FRAME
+Used in @samp{call_function_by_hand} to remove an artificial stack frame.
+
+@item BLOCK_ADDRESS_FUNCTION_RELATIVE
+dbxread.c
+@item PYRAMID_CONTROL_FRAME_DEBUGGING
+pyr-xdep.c
+@item ADDITIONAL_OPTIONS
+main.c
+@item ADDITIONAL_OPTION_CASES
+main.c
+@item ADDITIONAL_OPTION_HANDLER
+main.c
+@item ADDITIONAL_OPTION_HELP
+main.c
+
+@item ADDR_BITS_REMOVE (addr)
+If a raw machine address includes any bits that are not really part
+of the address, then define this macro to expand into an expression
+that zeros those bits in @var{addr}. For example, the two low-order
+bits of a Motorola 88K address may be used by some kernels for their
+own purposes, since addresses must always be 4-byte aligned, and so
+are of no use for addressing. Those bits should be filtered out with
+an expression such as @code{((addr) & ~3)}.
+
+@item ALIGN_STACK_ON_STARTUP
+main.c
+@item ALTOS
+altos-xdep.c
+@item ALTOS_AS
+xm-altos.h
+@item BCS
+tm-delta88.h
+
+@item BEFORE_MAIN_LOOP_HOOK
+Define this to expand into any code that you want to execute before
+the main loop starts. Although this is not, strictly speaking,
+a target conditional, that is how it is currently being used.
+Note that if a configuration were to define it one way for a host
+and a different way for the target, GDB will probably not compile,
+let alone run correctly.
+
+@item BELIEVE_PCC_PROMOTION
+coffread.c
+@item BELIEVE_PCC_PROMOTION_TYPE
+stabsread.c
+
+@item BITS_BIG_ENDIAN
+Define this if the numbering of bits in the targets does *not* match
+the endianness of the target byte order.
+A value of 1 means that the bits are numbered in a big-endian order,
+0 means little-endian.
+
+@item BLOCK_ADDRESS_ABSOLUTE
+dbxread.c
+@item BREAKPOINT
+tm-m68k.h
+
+@item CALL_DUMMY
+valops.c
+@item CALL_DUMMY_LOCATION
+inferior.h
+@item CALL_DUMMY_STACK_ADJUST
+valops.c
+
+@item CANNOT_FETCH_REGISTER (regno)
+A C expression that should be nonzero if @var{regno} cannot be
+fetched from an inferior process.
+This is only relevant if @code{FETCH_INFERIOR_REGISTERS} is not
+defined.
+
+@item CANNOT_STORE_REGISTER (regno)
+A C expression that should be nonzero if @var{regno} should not be
+written to the target. This is often the case for program counters,
+status words, and other special registers. If this is not defined,
+GDB will assume that all registers may be written.
+
+@item CFRONT_PRODUCER
+dwarfread.c
+
+@item DO_DEFERRED_STORES
+@item CLEAR_DEFERRED_STORES
+Define this to execute any deferred stores of registers into the inferior,
+and to cancel any deferred stores.
+
+Currently only implemented correctly for native Sparc configurations?
+
+@item CPLUS_MARKER
+Define this to expand into the character that G++ uses to
+distinguish compiler-generated identifiers from programmer-specified
+identifiers. By default, this expands into @code{'$'}.
+Most System V targets should define this to @code{'.'}.
+
+@item DBX_PARM_SYMBOL_CLASS
+stabsread.c
+
+@item DECR_PC_AFTER_BREAK
+Define this to be the amount by which to decrement the PC after
+the program encounters a breakpoint.
+This is often the number of bytes in BREAKPOINT, though not always.
+For most targets this value will be 0.
+
+@item DECR_PC_AFTER_HW_BREAK
+Similarly, for hardware breakpoints.
+
+@item DELTA88
+m88k-xdep.c
+@item DEV_TTY
+symmisc.c
+@item DGUX
+m88k-xdep.c
+
+@item DISABLE_UNSETTABLE_BREAK addr
+If defined, this should evaluate to 1 if @var{addr} is in a shared
+library in which breakpoints cannot be set and so should be disabled.
+
+@item DO_REGISTERS_INFO
+infcmd.c
+
+@item END_OF_TEXT_DEFAULT
+This is an expression that should designate the end of the text section
+(? FIXME ?)
+
+@item EXTRACT_RETURN_VALUE
+tm-m68k.h
+@item EXTRACT_STRUCT_VALUE_ADDRESS
+values.c
+
+@item EXTRA_FRAME_INFO
+If defined, this must be a list of slots that may be inserted into
+the @code{frame_info} structure defined in @code{frame.h}.
+
+@item EXTRA_SYMTAB_INFO
+If defined, this must be a list of slots that may be inserted into
+the @code{symtab} structure defined in @code{symtab.h}.
+
+@item FILES_INFO_HOOK
+target.c
+@item FLOAT_INFO
+infcmd.c
+@item FP0_REGNUM
+a68v-xdep.c
+@item FPC_REGNUM
+mach386-xdep.c
+@item FP_REGNUM
+parse.c
+@item FRAMELESS_FUNCTION_INVOCATION
+blockframe.c
+@item FRAME_ARGS_ADDRESS_CORRECT
+stack.c
+
+@item FRAME_CHAIN
+Given FRAME, return a pointer to the calling frame.
+
+@item FRAME_CHAIN_COMBINE
+blockframe.c
+@item FRAME_CHAIN_VALID
+frame.h
+@item FRAME_CHAIN_VALID_ALTERNATE
+frame.h
+@item FRAME_FIND_SAVED_REGS
+stack.c
+@item FRAME_GET_BASEREG_VALUE
+frame.h
+
+@item FRAME_NUM_ARGS (val, fi)
+For the frame described by fi, set val to the number of arguments
+that are being passed.
+
+@item FRAME_SPECIFICATION_DYADIC
+stack.c
+
+@item FRAME_SAVED_PC
+Given FRAME, return the pc saved there. That is, the return address.
+
+@item FUNCTION_EPILOGUE_SIZE
+For some COFF targets, the @code{x_sym.x_misc.x_fsize} field of the
+function end symbol is 0. For such targets, you must define
+@code{FUNCTION_EPILOGUE_SIZE} to expand into the standard size
+of a function's epilogue.
+
+@item GCC2_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_COMPILED_FLAG_SYMBOL
+dbxread.c
+@item GCC_MANGLE_BUG
+symtab.c
+@item GCC_PRODUCER
+dwarfread.c
+
+@item GDB_TARGET_IS_HPPA
+This determines whether horrible kludge code in dbxread.c and partial-stab.h
+is used to mangle multiple-symbol-table files from HPPA's. This should all
+be ripped out, and a scheme like elfread.c used.
+
+@item GDB_TARGET_IS_MACH386
+mach386-xdep.c
+@item GDB_TARGET_IS_SUN3
+a68v-xdep.c
+@item GDB_TARGET_IS_SUN386
+sun386-xdep.c
+
+@item GET_LONGJMP_TARGET
+For most machines, this is a target-dependent parameter. On the DECstation
+and the Iris, this is a native-dependent parameter, since <setjmp.h> is
+needed to define it.
+
+This macro determines the target PC address that longjmp() will jump
+to, assuming that we have just stopped at a longjmp breakpoint. It
+takes a CORE_ADDR * as argument, and stores the target PC value through
+this pointer. It examines the current state of the machine as needed.
+
+@item GET_SAVED_REGISTER
+Define this if you need to supply your own definition for the
+function @code{get_saved_register}.
+Currently this is only done for the a29k.
+
+@item GPLUS_PRODUCER
+dwarfread.c
+
+@item GR64_REGNUM
+Very a29k-specific.
+
+@item HAVE_REGISTER_WINDOWS
+Define this if the target has register windows.
+@item REGISTER_IN_WINDOW_P regnum
+Define this to be an expression that is 1 is the given register is
+in the window.
+
+@item IBM6000_TARGET
+Shows that we are configured for an IBM RS/6000 target. This conditional
+should be eliminated (FIXME) and replaced by feature-specific macros.
+It was introduced in haste and we are repenting at leisure.
+
+@item IEEE_FLOAT
+Define this if the target system uses IEEE-format floating point numbers.
+
+@item IGNORE_SYMBOL type
+This seems to be no longer used.
+
+@item INIT_EXTRA_FRAME_INFO (fromleaf, fci)
+If defined, this should be a C expression or statement that fills
+in the @code{EXTRA_FRAME_INFO} slots of the given frame @var{fci}.
+
+@item INIT_EXTRA_SYMTAB_INFO
+symfile.c
+
+@item INIT_FRAME_PC (fromleaf, prev)
+This is a C statement that sets the pc of the frame pointed
+to by @var{prev}. [By default...]
+
+@item INNER_THAN
+Define this to be either @code{<} if the target's stack grows
+downward in memory, or @code{>} is the stack grows upwards.
+
+@item IN_SIGTRAMP pc name
+Define this to return true if the given pc and/or name indicates
+that the current function is a sigtramp.
+
+@item SIGTRAMP_START
+@item SIGTRAMP_END
+Define these to be the start and end address of the sigtramp.
+These will be used if defined, and @code{IN_SIGTRAMP} is not;
+otherwise the name of the sigtramp will be assumed to be @code{_sigtramp}.
+
+@item IN_SOLIB_TRAMPOLINE pc name
+Define this to evaluate to nonzero if the program is stopped in
+the trampoline that connects to a shared library.
+
+@item IS_TRAPPED_INTERNALVAR name
+This is an ugly hook to allow the specification of special actions
+that should occur as a side-effect of setting the value of a variable
+internal to GDB. Currently only used by the h8500.
+Note that this could be either a host or target conditional.
+
+@item KERNEL_DEBUGGING
+tm-ultra3.h
+@item LCC_PRODUCER
+dwarfread.c
+@item L_LNNO32
+coffread.c
+@item MIPSEL
+mips-tdep.c
+@item MOTOROLA
+xm-altos.h
+@item NBPG
+altos-xdep.c
+
+@item NEED_TEXT_START_END
+Define this if GDB should determine the start and end addresses
+of the text section. (Seems dubious.)
+
+@item NOTICE_SIGNAL_HANDLING_CHANGE
+infrun.c
+@item NO_HIF_SUPPORT
+remote-mm.c
+@item NO_SIGINTERRUPT
+remote-adapt.c
+
+@item NO_SINGLE_STEP
+Define this if the target does not support single-stepping.
+If this is defined, you must supply, in @code{*-tdep.c}, the function
+@code{single_step}, which takes a pid as argument and returns nothing.
+It must insert breakpoints at each possible destinations of the next
+instruction. See @code{sparc-tdep.c} and @code{rs6000-tdep.c}
+for examples.
+
+@item NUMERIC_REG_NAMES
+mips-tdep.c
+@item N_SETV
+dbxread.c
+@item N_SET_MAGIC
+hppabsd-tdep.c
+@item ONE_PROCESS_WRITETEXT
+breakpoint.c
+@item PCC_SOL_BROKEN
+dbxread.c
+@item PC_IN_CALL_DUMMY
+inferior.h
+@item PC_LOAD_SEGMENT
+stack.c
+
+@item PC_REGNUM
+If the program counter is kept in a register, then define this macro
+to be the number of that register.
+This need be defined only if @code{TARGET_WRITE_PC} is not defined.
+
+@item NPC_REGNUM
+The number of the ``next program counter'' register, if defined.
+
+@item NNPC_REGNUM
+The number of the ``next next program counter'' register, if defined.
+Currently, this is only defined for the Motorola 88K.
+
+@item PRINT_RANDOM_SIGNAL
+infcmd.c
+@item PRINT_REGISTER_HOOK
+infcmd.c
+
+@item PRINT_TYPELESS_INTEGER
+This is an obscure substitute for @code{print_longest} that
+seems to have been defined for the Convex target.
+
+@item PROCESS_LINENUMBER_HOOK
+buildsym.c
+@item PROLOGUE_FIRSTLINE_OVERLAP
+infrun.c
+@item PS_REGNUM
+parse.c
+@item PUSH_ARGUMENTS
+valops.c
+@item REGISTER_BYTES
+remote.c
+
+@item REGISTER_NAMES
+Define this to expand into an initializer of an array of strings.
+Each string is the name of a register.
+[more detail]
+
+@item REG_STACK_SEGMENT
+exec.c
+@item REG_STRUCT_HAS_ADDR
+findvar.c
+@item R_FP
+dwarfread.c
+@item R_OK
+xm-altos.h
+
+@item SDB_REG_TO_REGNUM
+Define this to convert sdb register numbers
+into GDB regnums. If not defined, no conversion will be done.
+
+@item SEEK_END
+state.c
+@item SEEK_SET
+state.c
+@item SEM
+coffread.c
+@item SHELL_COMMAND_CONCAT
+infrun.c
+@item SHELL_FILE
+infrun.c
+@item SHIFT_INST_REGS
+breakpoint.c
+@item SIGTRAP_STOP_AFTER_LOAD
+infrun.c
+
+@item SKIP_PROLOGUE
+A C statement that advances the PC across any function entry
+prologue instructions so as to reach ``real'' code.
+
+@item SKIP_PROLOGUE_FRAMELESS_P
+A C statement that should behave similarly, but that can stop
+as soon as the function is known to have a frame.
+If not defined, @code{SKIP_PROLOGUE} will be used instead.
+
+@item SKIP_TRAMPOLINE_CODE (pc)
+If the target machine has trampoline code that sits between callers
+and the functions being called, then define this macro to return
+a new PC that is at the start of the real function.
+
+@item SP_REGNUM
+parse.c
+
+@item STAB_REG_TO_REGNUM
+Define this to convert stab register numbers (as gotten from `r' declarations)
+into GDB regnums. If not defined, no conversion will be done.
+
+@item STACK_ALIGN
+valops.c
+@item STOP_SIGNAL
+main.c
+
+@item STORE_RETURN_VALUE (type, valbuf)
+A C expression that stores a function return value of type @var{type},
+where @var{valbuf} is the address of the value to be stored.
+
+@item SUN4_COMPILER_FEATURE
+infrun.c
+@item SUN_FIXED_LBRAC_BUG
+dbxread.c
+@item SVR4_SHARED_LIBS
+solib.c
+@item SYMBOL_RELOADING_DEFAULT
+symfile.c
+
+@item TARGET_BYTE_ORDER
+The ordering of bytes in the target.
+This must be defined to be either @code{BIG_ENDIAN} or @code{LITTLE_ENDIAN}.
+
+@item TARGET_CHAR_BIT
+Number of bits in a char; defaults to 8.
+
+@item TARGET_COMPLEX_BIT
+Number of bits in a complex number; defaults to @code{2 * TARGET_FLOAT_BIT}.
+
+@item TARGET_DOUBLE_BIT
+Number of bits in a double float; defaults to @code{8 * TARGET_CHAR_BIT}.
+
+@item TARGET_DOUBLE_COMPLEX_BIT
+Number of bits in a double complex; defaults to @code{2 * TARGET_DOUBLE_BIT}.
+
+@item TARGET_FLOAT_BIT
+Number of bits in a float; defaults to @code{4 * TARGET_CHAR_BIT}.
+
+@item TARGET_INT_BIT
+Number of bits in an integer; defaults to @code{4 * TARGET_CHAR_BIT}.
+
+@item TARGET_LONG_BIT
+Number of bits in a long integer; defaults to @code{4 * TARGET_CHAR_BIT}.
+
+@item TARGET_LONG_DOUBLE_BIT
+Number of bits in a long double float;
+defaults to @code{2 * TARGET_DOUBLE_BIT}.
+
+@item TARGET_LONG_LONG_BIT
+Number of bits in a long long integer; defaults to @code{2 * TARGET_LONG_BIT}.
+
+@item TARGET_PTR_BIT
+Number of bits in a pointer; defaults to @code{TARGET_INT_BIT}.
+
+@item TARGET_SHORT_BIT
+Number of bits in a short integer; defaults to @code{2 * TARGET_CHAR_BIT}.
+
+@item TARGET_READ_PC
+@item TARGET_WRITE_PC (val, pid)
+@item TARGET_READ_SP
+@item TARGET_WRITE_SP
+@item TARGET_READ_FP
+@item TARGET_WRITE_FP
+These change the behavior of @code{read_pc}, @code{write_pc},
+@code{read_sp}, @code{write_sp}, @code{read_fp} and @code{write_fp}.
+For most targets, these may be left undefined. GDB will call the
+read and write register functions with the relevant @code{_REGNUM} argument.
+
+These macros are useful when a target keeps one of these registers in a
+hard to get at place; for example, part in a segment register and part
+in an ordinary register.
+
+@item USE_STRUCT_CONVENTION (gcc_p, type)
+If defined, this must be an expression that is nonzero if a value
+of the given @var{type} being returned from a function must have
+space allocated for it on the stack. @var{gcc_p} is true if the
+function being considered is known to have been compiled by GCC;
+this is helpful for systems where GCC is known to use different calling
+convention than other compilers.
+
+@item VARIABLES_INSIDE_BLOCK (desc, gcc_p)
+For dbx-style debugging information, if the compiler puts variable
+declarations inside LBRAC/RBRAC blocks, this should be defined
+to be nonzero. @var{desc} is the value of @code{n_desc} from the
+@code{N_RBRAC} symbol, and @var{gcc_p} is true if GDB has noticed
+the presence of either the @code{GCC_COMPILED_SYMBOL} or the
+@code{GCC2_COMPILED_SYMBOL}.
+By default, this is 0.
+
+@item OS9K_VARIABLES_INSIDE_BLOCK (desc, gcc_p)
+Similarly, for OS/9000. Defaults to 1.
+
+@item WRS_ORIG
+remote-vx.c
+
+@item test
+(Define this to enable testing code in regex.c.)
+
+@end table
+
+Motorola M68K target conditionals.
+
+@table @code
+
+@item BPT_VECTOR
+Define this to be the 4-bit location of the breakpoint trap vector.
+If not defined, it will default to @code{0xf}.
+
+@item REMOTE_BPT_VECTOR
+Defaults to @code{1}.
+
+@end table
+
+@node Native Conditionals
+@chapter Native Conditionals
+
+When GDB is configured and compiled, various macros are defined or left
+undefined, to control compilation when the host and target systems
+are the same. These macros should be defined (or left undefined)
+in @file{nm-@var{system}.h}.
+
+@table @code
+
+@item ATTACH_DETACH
+If defined, then GDB will include support for the @code{attach} and
+@code{detach} commands.
+
+@item CHILD_PREPARE_TO_STORE
+If the machine stores all registers at once in the child process,
+then define this to ensure that all values are correct.
+This usually entails a read from the child.
+
+[Note that this is incorrectly defined in @file{xm-@var{system}.h}
+files currently.]
+
+@item FETCH_INFERIOR_REGISTERS
+Define this if the native-dependent code will provide its
+own routines
+@code{fetch_inferior_registers} and @code{store_inferior_registers} in
+@file{@var{HOST}-nat.c}.
+If this symbol is @emph{not} defined, and @file{infptrace.c}
+is included in this configuration, the default routines in
+@file{infptrace.c} are used for these functions.
+
+@item GET_LONGJMP_TARGET
+For most machines, this is a target-dependent parameter. On the DECstation
+and the Iris, this is a native-dependent parameter, since <setjmp.h> is
+needed to define it.
+
+This macro determines the target PC address that longjmp() will jump
+to, assuming that we have just stopped at a longjmp breakpoint. It
+takes a CORE_ADDR * as argument, and stores the target PC value through
+this pointer. It examines the current state of the machine as needed.
+
+@item PROC_NAME_FMT
+Defines the format for the name of a @file{/proc} device. Should be
+defined in @file{nm.h} @emph{only} in order to override the default
+definition in @file{procfs.c}.
+
+@item PTRACE_FP_BUG
+mach386-xdep.c
+
+@item PTRACE_ARG3_TYPE
+The type of the third argument to the @code{ptrace} system call, if it exists
+and is different from @code{int}.
+
+@item REGISTER_U_ADDR
+Defines the offset of the registers in the ``u area''; @pxref{Host}.
+
+@item SOLIB_ADD (filename, from_tty, targ)
+Define this to expand into an expression that will cause the symbols
+in @var{filename} to be added to GDB's symbol table.
+
+@item SOLIB_CREATE_INFERIOR_HOOK
+Define this to expand into any shared-library-relocation code
+that you want to be run just after the child process has been forked.
+
+@item START_INFERIOR_TRAPS_EXPECTED
+When starting an inferior, GDB normally expects to trap twice;
+once when the shell execs, and once when the program itself execs.
+If the actual number of traps is something other than 2, then
+define this macro to expand into the number expected.
+
+@item USE_PROC_FS
+This determines whether small routines in @file{*-tdep.c}, which
+translate register values
+between GDB's internal representation and the /proc representation,
+are compiled.
+
+@item U_REGS_OFFSET
+This is the offset of the registers in the upage. It need only be
+defined if the generic ptrace register access routines in
+@file{infptrace.c} are being used (that is,
+@file{infptrace.c} is configured in, and
+@code{FETCH_INFERIOR_REGISTERS} is not defined). If the default value
+from @file{infptrace.c} is good enough, leave it undefined.
+
+The default value means that u.u_ar0 @emph{points to} the location of the
+registers. I'm guessing that @code{#define U_REGS_OFFSET 0} means that
+u.u_ar0 @emph{is} the location of the registers.
+
+@item CLEAR_SOLIB
+objfiles.c
+
+@item DEBUG_PTRACE
+Define this to debug ptrace calls.
+
+@end table
+
+@node Obsolete Conditionals
+@chapter Obsolete Conditionals
+
+Fragments of old code in GDB sometimes reference or set the following
+configuration macros. They should not be used by new code, and
+old uses should be removed as those parts of the debugger are
+otherwise touched.
+
+@table @code
+
+@item STACK_END_ADDR
+This macro used to define where the end of the stack appeared, for use
+in interpreting core file formats that don't record this address in the
+core file itself. This information is now configured in BFD, and GDB
+gets the info portably from there. The values in GDB's configuration
+files should be moved into BFD configuration files (if needed there),
+and deleted from all of GDB's config files.
+
+Any @file{@var{foo}-xdep.c} file that references STACK_END_ADDR
+is so old that it has never been converted to use BFD. Now that's old!
+
+@end table
+
+@node XCOFF
+@chapter The XCOFF Object File Format
+
+The IBM RS/6000 running AIX uses an object file format called xcoff.
+The COFF sections, symbols, and line numbers are used, but debugging
+symbols are dbx-style stabs whose strings are located in the
+@samp{.debug} section (rather than the string table). For more
+information, @xref{Top,,,stabs,The Stabs Debugging Format}, and search
+for XCOFF.
+
+The shared library scheme has a nice clean interface for figuring out
+what shared libraries are in use, but the catch is that everything which
+refers to addresses (symbol tables and breakpoints at least) needs to be
+relocated for both shared libraries and the main executable. At least
+using the standard mechanism this can only be done once the program has
+been run (or the core file has been read).
+
+@contents
+@bye
diff --git a/contrib/gdb/gdb/doc/h8-cfg.texi b/contrib/gdb/gdb/doc/h8-cfg.texi
new file mode 100644
index 0000000..823c7c2
--- /dev/null
+++ b/contrib/gdb/gdb/doc/h8-cfg.texi
@@ -0,0 +1,47 @@
+@c GDB version number is recorded in the variable GDBVN
+@include GDBvn.texi
+@c
+@set AGGLOMERATION
+@clear AMD29K
+@set BARETARGET
+@clear CONLY
+@set DOSHOST
+@clear FORTRAN
+@clear FSFDOC
+@clear GDBSERVER
+@clear GENERIC
+@set H8
+@set H8EXCLUSIVE
+@clear HAVE-FLOAT
+@clear I960
+@clear MOD2
+@clear NOVEL
+@clear POSIX
+@set PRECONFIGURED
+@clear REMOTESTUB
+@set SIMS
+@clear SERIAL
+@clear SPARC
+@clear ST2000
+@clear VXWORKS
+@clear Z8K
+@c ----------------------------------------------------------------------
+@c STRINGS:
+@c
+@c Name of GDB program. Used also for (gdb) prompt string.
+@set GDBP gdb
+@c
+@c Name of GDB product. Used in running text.
+@set GDBN GDB
+@c
+@c Name of GDB initialization file.
+@set GDBINIT .gdbinit
+@c
+@c Name of target.
+@set TARGET Hitachi Microprocessors
+@c
+@c Name of GCC product
+@set NGCC GCC
+@c
+@c Name of GCC program
+@set GCC gcc
diff --git a/contrib/gdb/gdb/doc/libgdb.texinfo b/contrib/gdb/gdb/doc/libgdb.texinfo
new file mode 100644
index 0000000..4fadcb2
--- /dev/null
+++ b/contrib/gdb/gdb/doc/libgdb.texinfo
@@ -0,0 +1,878 @@
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename libgdb.info
+@settitle Libgdb
+@setchapternewpage off
+@c %**end of header
+
+@ifinfo
+This file documents libgdb, the GNU symbolic debugger in a library.
+
+This is Edition 0.3, Oct 1993, of @cite{Libgdb}.
+Copyright 1993 Cygnus Support
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ifinfo
+
+@c This title page illustrates only one of the
+@c two methods of forming a title page.
+
+@titlepage
+@title Libgdb
+@subtitle Version 0.3
+@subtitle Oct 1993
+@author Thomas Lord
+
+@c The following two commands
+@c start the copyright page.
+@page
+@vskip 0pt plus 1filll
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Copyright @copyright{} 1993 Cygnus Support
+@end titlepage
+
+@ifinfo
+@node Top, Overview, (dir), (dir)
+
+This info file documents libgdb: an API for GDB, the GNU symbolic debugger.
+
+@menu
+* Overview:: The basics of libgdb and this document.
+* Interpreter:: Libgdb is an Interpreter-Based Server.
+* Top Level:: You Provide the Top Level for the Libgdb
+ Command Interpreter .
+* I/O:: How the Server's I/O Can be Used.
+* Invoking:: Invoking the Interpreter, Executing
+ Commands.
+* Defining Commands:: How New Commands are Created.
+* Variables:: How Builtin Variables are Defined.
+* Asynchronous:: Scheduling Asynchronous Computations.
+* Commands:: Debugger Commands for Libgdb Applications
+@end menu
+
+@end ifinfo
+@node Overview, Interpreter, top, top
+@comment node-name, next, previous, up
+@chapter Overview
+@cindex overview
+@cindex definitions
+
+@heading Function and Purpose
+
+Libgdb is a package which provides an API to the functionality of GDB,
+the GNU symbolic debugger. It is specifically intended to support the
+development of a symbolic debugger with a graphic interface.
+
+
+@heading This Document
+
+This document is a specification of the libgdb API. It is written in
+the form of a programmer's manual. So the goal of this document is to
+explain what functions make up the API, and how they can be used in a
+running application.
+
+
+@heading Terminology
+
+In this document, @dfn{libgdb} refers to a library containing the
+functions defined herein, @dfn{application} refers to any program built
+with that library.
+
+
+@heading Dependencies
+
+Programs which are linked with libgdb must be linked with libbfd,
+libopcodes, libiberty, and libmmalloc.
+
+@heading Acknowledgments
+
+Essential contributions to this design were made by Stu Grossman, Jim
+Kingdon, and Rich Pixley.
+
+@node Interpreter, Top Level, Overview, Top
+@comment node-name, next, previous, up
+@chapter Libgdb is an Interpreter Based Server
+@cindex interpreter
+@cindex server
+
+To understand libgdb, it is necessary to understand how the library is
+structured. Historically, GDB is written as a small interpreter for a
+simple command language. The commands of the language perform useful
+debugging functions.
+
+Libgdb is built from GDB by turning the interpreter into a debugging
+server. The server reads debugging commands from any source and
+interprets them, directing the output arbitrarily.
+
+In addition to changing GDB from a tty-based program to a server, a
+number of new GDB commands have been added to make the server more
+useful for a program with a graphic interface.
+
+Finally, libgdb includes provisions for asynchronous processing within
+the application.
+
+Most operations that can be carried out with libgdb involve the GDB
+command interpreter. The usual mode of operation is that the operation
+is expressed as a string of GDB commands, which the interpreter is then
+invoked to carry out. The output from commands executed in this manner
+can be redirected in a variety of useful ways for further processing by
+the application.
+
+The command interpreter provides an extensive system of hooks so an
+application can monitor any aspect of the debugging library's state. An
+application can set its own breakpoints and attach commands and
+conditions to those. It is possible to attach hooks to any debugger
+command; the hooks are invoked whenever that command is about to be
+invoked. By means of these, the displays of a graphical interface can
+be kept fully up to date at all times.
+
+We show you how to define new primitives in the command language. By
+defining new primitives and using them in breakpoint scripts and command
+hooks, an application can schedule the execution of arbitrary C-code at
+almost any point of interest in the operation of libgdb.
+
+We show you how to define new GDB convenience variables for which your
+code computes a value on demand. Referring to such variables in a
+breakpoint condition is a convenient way to conditionalize breakpoints
+in novel ways.
+
+To summarize: in libgdb, the gdb command language is turned into a
+debugging server. The server takes commands as input, and the server's
+output is redirectable. An application uses libgdb by formatting
+debugging commands and invoking the interpreter. The application might
+maintain breakpoints, watchpoints and many kinds of hooks. An application
+can define new primitives for the interpreter.
+
+@node Top Level, I/O, Interpreter, Top
+@chapter You Provide the Top Level for the Libgdb Command Interpreter
+@cindex {top level}
+
+When you use libgdb, your code is providing a @dfn{top level} for the
+command language interpreter. The top level is significant because it
+provides commands for the the interpreter to execute. In addition, the
+top level is responsible for handling some kinds of errors, and
+performing certain cleanup operations on behalf of the interpreter.
+
+@heading Initialization
+
+Before calling any other libgdb functions, call this:
+
+@deftypefun void gdb_init (void)
+Perform one-time initialization for libgdb.
+@end deftypefun
+
+An application may wish to evaluate specific gdb commands as part of its
+own initialization. The details of how this can be accomplished are
+explained below.
+
+@heading The Top-Level Loop
+
+There is a strong presumption in libgdb that the application has
+the form of a loop. Here is what such a loop might look like:
+
+@example
+while (gdb_still_going ())
+ @{
+ if (!GDB_TOP_LEVEL ())
+ @{
+ char * command;
+ gdb_start_top_loop ();
+ command = process_events ();
+ gdb_execute_command (command);
+ gdb_finish_top_loop ();
+ @}
+ @}
+@end example
+
+The function @code{gdb_still_going} returns 1 until the gdb command
+`quit' is run.
+
+The macro @code{GDB_TOP_LEVEL} invokes setjmp to set the top level error
+handler. When a command results in an error, the interpreter exits with
+a longjmp. There is nothing special libgdb requires of the top level
+error handler other than it be present and that it restart the top level
+loop. Errors are explained in detail in a later chapter.
+
+Each time through the top level loop two important things happen: a
+debugger command is constructed on the basis of user input, and the
+interpreter is invoked to execute that command. In the sample code, the
+call to the imaginary function @code{process_events} represents the
+point at which a graphical interface should read input events until
+ready to execute a debugger command. The call to
+@code{gdb_execute_command} invokes the command interpreter (what happens
+to the output from the command will be explained later).
+
+Libgdb manages some resources using the top-level loop. The primary
+reason for this is error-handling: even if a command terminates with an
+error, it may already have allocated resources which need to be freed.
+The freeing of such resources takes place at the top-level, regardless
+of how the the command exits. The calls to @code{gdb_start_top_loop}
+and @code{gdb_finish_top_loop} let libgdb know when it is safe to
+perform operations associated with these resources.
+
+@heading Breakpoint Commands
+
+Breakpoint commands are scripts of GDB operations associated with
+particular breakpoints. When a breakpoint is reached, its associated
+commands are executed.
+
+Breakpoint commands are invoked by the libgdb function
+@code{gdb_finish_top_loop}.
+
+Notice that if control returns to the top-level error handler, the
+execution of breakpoint commands is bypassed. This can happen as a
+result of errors during either @code{gdb_execute_command} or
+@code{gdb_finish_top_loop}.
+
+@heading Application Initialization
+
+Sometimes it is inconvenient to execute commands via a command loop for
+example, the commands an application uses to initialize itself. An
+alternative to @code{execute_command} is @code{execute_catching_errors}.
+When @code{execute_catching_errors} is used, no top level error handler
+need be in effect, and it is not necessary to call
+@code{gdb_start_top_loop} or @code{gdb_finish_top_loop}.
+
+
+@heading Cleanup
+
+The debugger command ``quit'' performs all necessary cleanup for libgdb.
+After it has done so, it changes the return value of
+@code{gdb_still_going} to 0 and returns to the top level error handler.
+
+
+@node I/O, Invoking, Top Level, Top
+@comment node-name, next, previous, up
+@chapter How the Server's I/O Can be Used
+@cindex I/O
+
+In the last chapter it was pointed out that a libgdb application is
+responsible for providing commands for the interpreter to execute.
+However some commands require further input (for example, the ``quit''
+command might ask for confirmation). Almost all commands produce output
+of some kind. The purpose of this section is to explain how libgdb
+performs its I/O, and how an application can take advantage of
+this.
+
+
+@heading I/O Vectors
+
+Libgdb has no fixed strategy for I/O. Instead, all operations are
+performed by functions called via structures of function pointers.
+Applications supply theses structures and can change them at any
+time.
+
+@deftp Type {struct gdb_input_vector}
+@deftpx Type {struct gdb_output_vector}
+These structures contain a set of function pointers. Each function
+determines how a particular type of i/o is performed. The details of
+these strucutres are explained below.
+
+The application allocates these structures, initializes them to all bits
+zero, fills in the function pointers, and then registers names for them
+them with libgdb.
+@end deftp
+
+@deftypefun void gdb_name_input_vector (@var{name}, @var{vec})
+@deftypefunx void gdb_remove_input_vector (@var{name}, @var{vec})
+@deftypefunx void gdb_name_output_vector (@var{name}, @var{vec})
+@deftypefunx void gdb_remove_input_vector (@var{name}, @var{vec})
+@example
+ char * @var{name};
+ struct gdb_output_vector * @var{vec};
+@end example
+These functions are used to give and remove names to i/o vectors. Note
+that if a name is used twice, the most recent definition applies.
+@end deftypefun
+
+
+
+@subheading Output
+
+An output vector is a structure with at least these fields:
+
+@example
+struct gdb_output_vector
+@{
+ /* output */
+ void (*put_string) (struct gdb_output_vector *, char * str);
+@}
+@end example
+
+Use the function @code{memset} or something equivalent to initialize an
+output vector to all bits zero. Then fill in the function pointer with
+your function.
+
+A debugger command can produce three kinds of output: error messages
+(such as when trying to delete a non-existent breakpoint), informational
+messages (such as the notification printed when a breakpoint is hit),
+and the output specifically requested by a command (for example, the
+value printed by the ``print'' command). At any given time, then,
+libgdb has three output vectors. These are called the @dfn{error},
+@dfn{info}, @dfn{value} vector respectively.
+
+@subheading Input
+
+@example
+struct gdb_input_vector
+@{
+ int (*query) (struct gdb_input_vector *,
+ char * prompt,
+ int quit_allowed);
+ int * (*selection) (struct gdb_input_vector *,
+ char * prompt,
+ char ** choices);
+ char * (*read_string) (struct gdb_input_vector *,
+ char * prompt);
+ char ** (*read_strings) (struct gdb_input_vector *,
+ char * prompt);
+@}
+@end example
+
+Use the function @code{memset} or something equivalent to initialize an
+input vector to all bits zero. Then fill in the function pointers with
+your functions.
+
+There are four kinds of input requests explicitly made by libgdb.
+
+A @dfn{query} is a yes or no question. The user can respond to a query
+with an affirmative or negative answer, or by telling gdb to abort the
+command (in some cases an abort is not permitted). Query should return
+'y' or 'n' or 0 to abort.
+
+A @dfn{selection} is a list of options from which the user selects a subset.
+Selections should return a NULL terminated array of integers, which are
+indexes into the array of choices. It can return NULL instead to abort
+the command. The array returned by this function will be passed to
+@code{free} by libgdb.
+
+A @dfn{read_string} asks the user to supply an arbitrary string. It may
+return NULL to abort the command. The string returned by @code{read_string}
+should be allocated by @code{malloc}; it will be freed by libgdb.
+
+A @dfn{read_strings} asks the user to supply multiple lines of input
+(for example, the body of a command created using `define'). It, too,
+may return NULL to abort. The array and the strings returned by this
+function will be freed by libgdb.
+
+@heading I/O Redirection from the Application Top-Level
+
+@deftypefun struct gdb_io_vecs gdb_set_io (struct gdb_io_vecs *)
+@example
+
+struct gdb_io_vecs
+@{
+ struct gdb_input_vector * input;
+ struct gdb_output_vector * error;
+ struct gdb_output_vector * info;
+ struct gdb_output_vector * value;
+@}
+@end example
+
+This establishes a new set of i/o vectors, and returns the old setting.
+Any of the pointers in this structure may be NULL, indicating that the
+current value should be used.
+
+This function is useful for setting up i/o vectors before any libgdb
+commands have been invoked (hence before any input or output has taken
+place).
+@end deftypefun
+
+It is explained in a later chapter how to redirect output temporarily.
+(@xref{Invoking}.)
+
+@heading I/O Redirection in Debugger Commands
+
+A libgdb application creates input and output vectors and assigns them names.
+Which input and output vectors are used by libgdb is established by
+executing these debugger commands:
+
+@defun {set input-vector} name
+@defunx {set error-output-vector} name
+@defunx {set info-output-vector} name
+@defunx {set value-output-vector} name
+Choose an I/O vector by name.
+@end defun
+
+
+A few debugger commands are for use only within commands defined using
+the debugger command `define' (they have no effect at other times).
+These commands exist so that an application can maintain hooks which
+redirect output without affecting the global I/O vectors.
+
+@defun with-input-vector name
+@defunx with-error-output-vector name
+@defunx with-info-output-vector name
+@defunx with-value-output-vector name
+Set an I/O vector, but only temporarily. The setting has effect only
+within the command definition in which it occurs.
+@end defun
+
+
+@heading Initial Conditions
+
+When libgdb is initialized, a set of default I/O vectors is put in
+place. The default vectors are called @code{default-input-vector},
+@code{default-output-vector}, &c.
+
+The default query function always returns `y'. Other input functions
+always abort. The default output functions discard output silently.
+
+
+@node Invoking, Defining Commands, I/O, Top
+@chapter Invoking the Interpreter, Executing Commands
+@cindex {executing commands}
+@cindex {invoking the interpreter}
+
+This section introduces the libgdb functions which invoke the command
+interpreter.
+
+@deftypefun void gdb_execute_command (@var{command})
+@example
+char * @var{command};
+@end example
+Interpret the argument debugger command. An error handler must be set
+when this function is called. (@xref{Top Level}.)
+@end deftypefun
+
+It is possible to override the current I/O vectors for the duration of a
+single command:
+
+@deftypefun void gdb_execute_with_io (@var{command}, @var{vecs})
+@example
+char * @var{command};
+struct gdb_io_vecs * @var{vecs};
+
+struct gdb_io_vecs
+@{
+ struct gdb_input_vector * input;
+ struct gdb_output_vector * error;
+ struct gdb_output_vector * info;
+ struct gdb_output_vector * value;
+@}
+@end example
+
+Execute @var{command}, temporarily using the i/o vectors in @var{vecs}.
+
+Any of the vectors may be NULL, indicating that the current value should
+be used. An error handler must be in place when this function is used.
+@end deftypefun
+
+@deftypefun {struct gdb_str_output} gdb_execute_for_strings (@var{cmd})
+@example
+char * cmd;
+@end example
+@deftypefunx {struct gdb_str_output} gdb_execute_for_strings2 (@var{cmd}, @var{input})
+@example
+char * cmd;
+struct gdb_input_vector * input;
+@end example
+@page
+@example
+struct gdb_str_output
+@{
+ char * error;
+ char * info;
+ char * value;
+@};
+@end example
+
+Execute @var{cmd}, collecting its output as strings. If no error
+occurs, all three strings will be present in the structure, the
+empty-string rather than NULL standing for no output of a particular
+kind.
+
+If the command aborts with an error, then the @code{value} field will be
+NULL, though the other two strings will be present.
+
+In all cases, the strings returned are allocated by malloc and should be
+freed by the caller.
+
+The first form listed uses the current input vector, but overrides the
+current output vector. The second form additionally allows the input
+vector to be overridden.
+
+This function does not require that an error handler be installed.
+@end deftypefun
+
+@deftypefun void execute_catching_errors (@var{command})
+@example
+char * @var{command};
+@end example
+Like @code{execute_command} except that no error handler is required.
+@end deftypefun
+
+@deftypefun void execute_with_text (@var{command}, @var{text})
+@example
+char * @var{command};
+char ** @var{text};
+@end example
+Like @code{execute_catching_errors}, except that the input vector is
+overridden. The new input vector handles only calls to @code{query} (by
+returning 'y') and calls to @code{read_strings} by returning a copy of
+@var{text} and the strings it points to.
+
+This form of execute_command is useful for commands like @code{define},
+@code{document}, and @code{commands}.
+@end deftypefun
+
+
+
+@node Defining Commands, Variables, Invoking, Top
+@comment node-name, next, previous, up
+@chapter How New Commands are Created
+@cindex {commands, defining}
+
+Applications are, of course, free to take advantage of the existing GDB
+macro definition capability (the @code{define} and @code{document}
+functions).
+
+In addition, an application can add new primitives to the GDB command
+language.
+
+@deftypefun void gdb_define_app_command (@var{name}, @var{fn}, @var{doc})
+@example
+char * @var{name};
+gdb_cmd_fn @var{fn};
+char * @var{doc};
+
+typedef void (*gdb_cmd_fn) (char * args);
+@end example
+
+Create a new command call @var{name}. The new command is in the
+@code{application} help class. When invoked, the command-line arguments
+to the command are passed as a single string.
+
+Calling this function twice with the same name replaces an earlier
+definition, but application commands can not replace builtin commands of
+the same name.
+
+The documentation string of the command is set to a copy the string
+@var{doc}.
+@end deftypefun
+
+@node Variables, Asynchronous, Defining Commands, Top
+@comment node-name, next, previous, up
+@chapter How Builtin Variables are Defined
+@cindex {variables, defining}
+
+Convenience variables provide a way for values maintained by libgdb to
+be referenced in expressions (e.g. @code{$bpnum}). Libgdb includes a
+means by which the application can define new, integer valued
+convenience variables:
+@page
+@deftypefun void gdb_define_int_var (@var{name}, @var{fn}, @var{fn_arg})
+@example
+char * @var{name};
+int (*@var{fn}) (void *);
+void * @var{fn_arg};
+@end example
+This function defines (or undefines) a convenience variable called @var{name}.
+If @var{fn} is NULL, the variable becomes undefined. Otherwise,
+@var{fn} is a function which, when passed @var{fn_arg} returns the value
+of the newly defined variable.
+
+No libgdb functions should be called by @var{fn}.
+@end deftypefun
+
+One use for this function is to create breakpoint conditions computed in
+novel ways. This is done by defining a convenience variable and
+referring to that variable in a breakpoint condition expression.
+
+
+@node Asynchronous, Commands, Variables, Top
+@chapter Scheduling Asynchronous Computations
+@cindex asynchronous
+
+
+A running libgdb function can take a long time. Libgdb includes a hook
+so that an application can run intermittently during long debugger
+operations.
+
+@deftypefun void gdb_set_poll_fn (@var{fn}, @var{fn_arg})
+@example
+void (*@var{fn})(void * fn_arg, int (*gdb_poll)());
+void * @var{fn_arg};
+@end example
+Arrange to call @var{fn} periodically during lengthy debugger operations.
+If @var{fn} is NULL, polling is turned off. @var{fn} should take two
+arguments: an opaque pointer passed as @var{fn_arg} to
+@code{gdb_set_poll_fn}, and a function pointer. The function pointer
+passed to @var{fn} is provided by libgdb and points to a function that
+returns 0 when the poll function should return. That is, when
+@code{(*gdb_poll)()} returns 0, libgdb is ready to continue @var{fn}
+should return quickly.
+
+It is possible that @code{(*gdb_poll)()} will return 0 the first time it
+is called, so it is reasonable for an application to do minimal processing
+before checking whether to return.
+
+No libgdb functions should be called from an application's poll function,
+with one exception: @code{gdb_request_quit}.
+@end deftypefun
+
+
+@deftypefun void gdb_request_quit (void)
+This function, if called from a poll function, requests that the
+currently executing libgdb command be interrupted as soon as possible,
+and that control be returned to the top-level via an error.
+
+The quit is not immediate. It will not occur until at least after the
+application's poll function returns.
+@end deftypefun
+
+@node Commands, Top, Asynchronous, Top
+@comment node-name, next, previous, up
+@chapter Debugger Commands for Libgdb Applications
+
+The debugger commands available to libgdb applications are the same commands
+available interactively via GDB. This section is an overview of the
+commands newly created as part of libgdb.
+
+This section is not by any means a complete reference to the GDB command
+language. See the GDB manual for such a reference.
+
+@menu
+* Command Hooks:: Setting Hooks to Execute With Debugger Commands.
+* View Commands:: View Commands Mirror Show Commands
+* Breakpoints:: The Application Can Have Its Own Breakpoints
+@end menu
+
+@node Command Hooks, View Commands, Commands, Commands
+@comment node-name, next, previous, up
+@section Setting Hooks to Execute With Debugger Commands.
+
+Debugger commands support hooks. A command hook is executed just before
+the interpreter invokes the hooked command.
+
+There are two hooks allowed for every command. By convention, one hook
+is for use by users, the other is for use by the application.
+
+A user hook is created for a command XYZZY by using
+@code{define-command} to create a command called @code{hook-XYZZY}.
+
+An application hook is created for a command XYZZY by using
+@code{define-command} to create a command called @code{apphook-XYZZY}.
+
+Application hooks are useful for interfaces which wish to continuously
+monitor certain aspects of debugger state. The application can set a
+hook on all commands that might modify the watched state. When the hook
+is executed, it can use i/o redirection to notify parts of the
+application that previous data may be out of date. After the top-level loop
+resumes, the application can recompute any values that may have changed.
+(@xref{I/O}.)
+
+@node View Commands, Breakpoints, Command Hooks, Commands
+@comment node-name, next, previous, up
+@section View Commands Mirror Show Commands
+
+The GDB command language contains many @code{set} and @code{show}
+commands. These commands are used to modify or examine parameters to
+the debugger.
+
+It is difficult to get the current state of a parameter from the
+@code{show} command because @code{show} is very verbose.
+
+@example
+(gdb) show check type
+Type checking is "auto; currently off".
+(gdb) show width
+Number of characters gdb thinks are in a line is 80.
+@end example
+
+For every @code{show} command, libgdb includes a @code{view} command.
+@code{view} is like @code{show} without the verbose commentary:
+
+@example
+(gdb) view check type
+auto; currently off
+(gdb) view width
+80
+@end example
+
+(The precise format of the ouput from @code{view} is subject to change.
+In particular, @code{view} may one-day print values which can be used as
+arguments to the corresponding @code{set} command.)
+
+@node Breakpoints, Structured Output, View Commands, Commands
+@comment node-name, next, previous, up
+@section The Application Can Have Its Own Breakpoints
+
+The GDB breakpoint commands were written with a strong presumption that
+all breakpoints are managed by a human user. Therefore, the command
+language contains commands like `delete' which affect all breakpoints
+without discrimination.
+
+In libgdb, there is added support for breakpoints and watchpoints which
+are set by the application and which should not be affected by ordinary,
+indiscriminate commands. These are called @dfn{protected} breakpoints.
+
+@deffn {Debugger Command} break-protected ...
+@deffnx {Debugger Command} watch-protected ...
+These work like @code{break} and @code{watch} except that the resulting
+breakpoint is given a negative number. Negative numbered breakpoints do
+not appear in the output of @code{info breakpoints} but do in that of
+@code{info all-breakpoints}. Negative numbered breakpoints are not
+affected by commands which ordinarily affect `all' breakpoints (e.g.
+@code{delete} with no arguments).
+
+Note that libgdb itself creates protected breakpoints, so programs
+should not rely on being able to allocate particular protected
+breakpoint numbers for themselves.
+@end deffn
+
+More than one breakpoint may be set at a given location. Libgdb adds
+the concept of @dfn{priority} to breakpoints. A priority is an integer,
+assigned to each breakpoint. When a breakpoint is reached, the
+conditions of all breakpoints at the same location are evaluated in
+order of ascending priority. When breakpoint commands are executed,
+they are also executed in ascending priority (until all have been
+executed, an error occurs, or one set of commands continues the
+target).
+
+@deffn {Debugger Command} priority n bplist
+Set the priority for breakpoints @var{bplist} to @var{n}.
+By default, breakpoints are assigned a priority of zero.
+@end deffn
+
+@node Structured Output, Commands, Breakpoints, Commands
+@comment node-name, next, previous, up
+@section Structured Output, The @code{Explain} Command
+
+(This section may be subject to considerable revision.)
+
+When GDB prints a the value of an expression, the printed representation
+contains information that can be usefully fed back into future commands
+and expressions. For example,
+
+@example
+(gdb) print foo
+$16 = @{v = 0x38ae0, v_length = 40@}
+@end example
+
+On the basis of this output, a user knows, for example, that
+@code{$16.v} refers to a pointer valued @code{0x38ae0}
+
+A new output command helps to make information like this available to
+the application.
+
+@deffn {Debugger Command} explain expression
+@deffnx {Debugger Command} explain /format expression
+Print the value of @var{expression} in the manner of the @code{print}
+command, but embed that output in a list syntax containing information
+about the structure of the output.
+@end deffn
+
+As an example, @code{explain argv} might produce this output:
+
+@example
+(exp-attribute
+ ((expression "$19")
+ (type "char **")
+ (address "48560")
+ (deref-expression "*$19"))
+ "$19 = 0x3800\n")
+@end example
+
+The syntax of output from @code{explain} is:
+
+@example
+<explanation> := <quoted-string>
+ | (exp-concat <explanation> <explanation>*)
+ | (exp-attribute <property-list> <explanation>)
+
+<property-list> := ( <property-pair>* )
+
+<property-pair> := ( <property-name> <quoted-string> )
+@end example
+
+The string-concatenation of all of the @code{<quoted-string>} (except
+those in property lists) yields the output generated by the equivalent
+@code{print} command. Quoted strings may contain quotes and backslashes
+if they are escaped by backslash. "\n" in a quoted string stands for
+newline; unescaped newlines do not occur within the strings output by
+@code{explain}.
+
+Property names are made up of alphabetic characters, dashes, and
+underscores.
+
+The set of properties is open-ended. As GDB acquires support for new
+source languages and other new capabilities, new property types may be
+added to the output of this command. Future commands may offer
+applications some selectivity concerning which properties are reported.
+
+The initial set of properties defined includes:
+
+@itemize @bullet
+@item @code{expression}
+
+This is an expression, such as @code{$42} or @code{$42.x}. The
+expression can be used to refer to the value printed in the attributed
+part of the string.
+
+@item @code{type}
+
+This is a user-readable name for the type of the attributed value.
+
+@item @code{address}
+
+If the value is stored in a target register, this is a register number.
+If the value is stored in a GDB convenience variable, this is an integer
+that is unique among all the convenience variables. Otherwise, this is
+the address in the target where the value is stored.
+
+@item @code{deref-expression}
+
+If the attributed value is a pointer type, this is an expression that
+refers to the dereferenced value.
+@end itemize
+
+Here is a larger example, using the same object passed to @code{print}
+in an earlier example of this section.
+
+@example
+(gdb) explain foo
+(exp-attribute
+ ( (expression "$16")
+ (type "struct bytecode_vector")
+ (address 14336) )
+ (exp-concat
+ "$16 = @{"
+ (exp-attribute
+ ( (expression "$16.v")
+ (type "char *")
+ (address 14336)
+ (deref-expression "*$16.v") )
+ "v = 0x38ae0")
+ (exp-attribute
+ ( (expression "$16.v_length")
+ (type "int")
+ (address 14340) )
+ ", v_length = 40")
+ "@}\n"))
+@end example
+
+It is undefined how libgdb will indent these lines of output or
+where newlines will be included.
+
+@bye
diff --git a/contrib/gdb/gdb/doc/lpsrc.sed b/contrib/gdb/gdb/doc/lpsrc.sed
new file mode 100644
index 0000000..1c7af4a
--- /dev/null
+++ b/contrib/gdb/gdb/doc/lpsrc.sed
@@ -0,0 +1,13 @@
+/font defs: ---/,/end font defs ---/c\
+%-------------------- PostScript (long names) font defs: -----------------\
+\\font\\bbf=Times-Bold at 10pt\
+\\font\\vbbf=Times-Bold at 12pt\
+\\font\\smrm=Times-Roman at 6pt\
+\\font\\brm=Times-Roman at 10pt\
+\\font\\rm=Times-Roman at 8pt\
+\\font\\it=Times-Italic at 8pt\
+\\font\\tt=Courier at 8pt\
+% Used only for \copyright, replacing plain TeX macro.\
+\\font\\sym=Symbol at 7pt\
+\\def\\copyright{{\\sym\\char'323}}\
+%-------------------- end font defs ---------------------------------
diff --git a/contrib/gdb/gdb/doc/psrc.sed b/contrib/gdb/gdb/doc/psrc.sed
new file mode 100644
index 0000000..9bb557e
--- /dev/null
+++ b/contrib/gdb/gdb/doc/psrc.sed
@@ -0,0 +1,13 @@
+/font defs: ---/,/end font defs ---/c\
+%-------------------- PostScript (K Berry names) font defs: --------------\
+\\font\\bbf=ptmb at 10pt\
+\\font\\vbbf=ptmb at 12pt\
+\\font\\smrm=ptmr at 6pt\
+\\font\\brm=ptmr at 10pt\
+\\font\\rm=ptmr at 8pt\
+\\font\\it=ptmri at 8pt\
+\\font\\tt=pcrr at 8pt\
+% Used only for \copyright, replacing plain TeX macro.\
+\\font\\sym=psyr at 7pt\
+\\def\\copyright{{\\sym\\char'323}}\
+%-------------------- end font defs ---------------------------------
diff --git a/contrib/gdb/gdb/doc/refcard.dvi b/contrib/gdb/gdb/doc/refcard.dvi
new file mode 100644
index 0000000..e152395
--- /dev/null
+++ b/contrib/gdb/gdb/doc/refcard.dvi
Binary files differ
diff --git a/contrib/gdb/gdb/doc/refcard.tex b/contrib/gdb/gdb/doc/refcard.tex
new file mode 100644
index 0000000..c57c2d8
--- /dev/null
+++ b/contrib/gdb/gdb/doc/refcard.tex
@@ -0,0 +1,645 @@
+%%%%%%%%%%%%%%%% gdb-refcard.tex %%%%%%%%%%%%%%%%
+
+%This file is TeX source for a reference card describing GDB, the GNU debugger.
+%Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
+%Permission is granted to make and distribute verbatim copies of
+%this reference provided the copyright notices and permission notices
+%are preserved on all copies.
+%
+%TeX markup is a programming language; accordingly this file is source
+%for a program to generate a reference.
+%
+%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
+%the Free Software Foundation; either version 1, or (at your option)
+%any later version.
+%
+%This program is distributed in the hope that it will be useful, but
+%WITHOUT ANY WARRANTY; without even the implied warranty of
+%MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+%General Public License for more details.
+%
+%You can find a copy of the GNU General Public License in the GDB
+%manual; or write to the Free Software Foundation, Inc.,
+%59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+%
+%You can contact the author at: doc@cygnus.com
+%
+% Documentation Department
+% Cygnus Support
+% 1937 Landings Drive
+% Mountain View, CA 94043 USA
+%
+% +1 415 903 1400
+%
+%
+%
+% 22-AUG-1993 Andreas Vogel
+%
+% Modifications made in order to handle different papersizes correctly.
+% You only have to set the total width and height of the paper, the
+% horizontal and vertical margin space measured from *paper edge*
+% and the interline and interspec spacing.
+% In order to support a new papersize, you have to fiddle with the
+% latter four dimensions. Just try out a few values.
+% All other values will be computed at process time so it should be
+% quite easy to support different paper sizes - only four values to
+% guess :-)
+%
+% To find the configuration places, just search for the string
+% "CONFIGURATION".
+%
+% Andreas Vogel (av@ssw.de)
+%
+%
+%
+% Uncomment the following `magnification' command if you want to print
+% out in a larger font. Caution! You may need larger paper. You had
+% best avoid using 3-column output if you try this. See the ``Three
+% column format'' section below if you want to print in three column
+% format.
+%
+%\magnification=\magstep 1
+%
+% NOTE ON INTENTIONAL OMISSIONS: This reference card includes most GDB
+% commands, but due to space constraints there are some things I chose
+% to omit. In general, not all synonyms for commands are covered, nor
+% all variations of a command.
+% The GDB-under-Emacs section omits gdb-mode functions without default
+% keybindings. GDB startup options are not described.
+% set print sevenbit-strings, set symbol-reloading omitted.
+% printsyms, printpsyms, omitted since they're for GDB maintenance primarily
+% share omitted due to obsolescence
+% set check range/type omitted at least til code is in GDB.
+%
+%-------------------- Three column format -----------------------
+
+%%%% --- To disable three column format, comment out this entire section
+
+% Three-column format for landscape printing
+
+%-------- Papersize defs:
+
+\newdimen\totalwidth \newdimen\totalheight
+\newdimen\hmargin \newdimen\vmargin
+\newdimen\secskip \newdimen\lskip
+\newdimen\barwidth \newdimen\barheight
+\newdimen\intersecwidth
+
+%%
+%% START CONFIGURATION - PAPERSIZE DEFINITIONS
+%------- Papersize params:
+%% US letter paper (8.5x11in)
+%%
+\totalwidth=11in % total width of paper
+\totalheight=8.5in % total height of paper
+\hmargin=.25in % horizontal margin width
+\vmargin=.25in % vertical margin width
+\secskip=1pc % space between refcard secs
+\lskip=2pt % extra skip between \sec entries
+%------- end papersize params
+%%
+%% change according to personal taste, not papersize dependent
+%%
+\barwidth=.1pt % width of the cropmark bar
+\barheight=2pt % height of the cropmark bar
+\intersecwidth=0.5em % width between \itmwid and \dfnwid
+%%
+%% END CONFIGURATION - PAPERSIZE DEFINITIONS
+%%
+
+%%
+%% values to be computed - nothing to configure
+%%
+\newdimen\fullhsize % width of area without margins
+\newdimen\itmwid % width of item column
+\newdimen\dfnwid % width of definition column
+\newdimen\temp % only for temporary use
+
+%%
+%% adjust the offsets so the margins are measured *from paper edge*
+%%
+\hoffset=-1in \advance \hoffset by \hmargin
+\voffset=-1in \advance \voffset by \vmargin
+
+%%
+%% fullhsize = totalwidth - (2 * hmargin)
+%%
+\fullhsize=\totalwidth
+\temp=\hmargin \multiply \temp by 2 \advance \fullhsize by -\temp
+
+%%
+%% hsize = (fullhsize - (4 * hmargin) - (2 * barwidth)) / 3
+%%
+\hsize=\fullhsize
+\temp=\hmargin \multiply \temp by 4 \advance \hsize by -\temp
+\temp=\barwidth \multiply \temp by 2 \advance \hsize by -\temp
+\divide \hsize by 3
+
+%%
+%% vsize = totalheight - (2 * vmargin)
+%%
+\vsize=\totalheight
+\temp=\vmargin \multiply \temp by 2 \advance \vsize by -\temp
+
+%%
+%% itmwid = (hsize - intersecwidth) * 1/3
+%% dfnwid = (hsize - intersecwidth) * 2/3
+%%
+\temp=\hsize \advance \temp by -\intersecwidth \divide \temp by 3
+\itmwid=\temp
+\dfnwid=\hsize \advance \dfnwid by -\itmwid
+
+%-------- end papersize defs
+
+
+\def\fulline{\hbox to \fullhsize}
+\let\lcr=L \newbox\leftcolumn\newbox\centercolumn
+\output={\if L\lcr
+ \global\setbox\leftcolumn=\columnbox \global\let\lcr=C
+ \else
+ \if C\lcr
+ \global\setbox\centercolumn=\columnbox \global\let\lcr=R
+ \else \tripleformat \global\let\lcr=L
+ \fi
+ \fi
+% \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+ }
+
+%%
+%% START CONFIGURATION - ALTERNATIVE FOLDING GUIDES
+%%
+%% For NO printed folding guide,
+%% comment out other \def\vdecor's and uncomment:
+
+%\def\vdecor{\hskip\hmargin plus1fil\hskip\barwidth plus1fil\hskip\hmargin plus1fil}
+
+%% For SOLID LINE folding guide,
+%% comment out other \def\vdecor's and uncomment:
+
+%\def\vdecor{\hskip\hmargin plus1fil \vrule width \barwidth \hskip\hmargin plus1fil}
+
+%% For SMALL MARKS NEAR TOP AND BOTTOM as folding guide,
+%% comment out other \def\vdecor's and uncomment:
+
+\def\vdecor{\hskip\hmargin plus1fil
+\vbox to \vsize{\hbox to \barwidth{\vrule height\barheight width\barwidth}\vfill
+\hbox to \barwidth{\vrule height\barheight width\barwidth}}%THIS PERCENT SIGN IS ESSENTIAL
+\hskip\hmargin plus1fil}
+
+%%
+%% END CONFIGURATION - ALTERNATIVES FOR FOLDING GUIDES
+%%
+
+\def\tripleformat{\shipout\vbox{\fulline{\box\leftcolumn\vdecor
+ \box\centercolumn\vdecor
+ \columnbox}
+ }
+ \advancepageno}
+\def\columnbox{\leftline{\pagebody}}
+\def\bye{\par\vfill
+ \supereject
+ \if R\lcr \null\vfill\eject\fi
+ \end}
+
+%-------------------- end three column format -----------------------
+
+%-------------------- Computer Modern font defs: --------------------
+\font\bbf=cmbx10
+\font\vbbf=cmbx12
+\font\smrm=cmr6
+\font\brm=cmr10
+\font\rm=cmr7
+\font\it=cmti7
+\font\tt=cmtt8
+%-------------------- end font defs ---------------------------------
+
+%
+\hyphenpenalty=5000\tolerance=2000\raggedright\raggedbottom
+\normalbaselineskip=9pt\baselineskip=9pt
+%
+\parindent=0pt
+\parskip=0pt
+\footline={\vbox to0pt{\hss}}
+%
+\def\ctl#1{{\tt C-#1}}
+\def\opt#1{{\brm[{\rm #1}]}}
+\def\xtra#1{\noalign{\smallskip{\tt#1}}}
+%
+\long\def\sec#1;#2\endsec{\vskip \secskip
+\halign{%
+%COL 1 (of halign):
+\vtop{\hsize=\itmwid\tt
+##\par\vskip \lskip }\hfil
+%COL 2 (of halign):
+&\vtop{\hsize=\dfnwid\hangafter=1\hangindent=\intersecwidth
+\rm ##\par\vskip \lskip}\cr
+%Tail of \long\def fills in halign body with \sec args:
+\noalign{{\bbf #1}\vskip \lskip}
+#2
+}
+}
+
+{\vbbf GDB QUICK REFERENCE}\hfil{\smrm GDB Version 4}\qquad
+
+\sec Essential Commands;
+gdb {\it program} \opt{{\it core}}&debug {\it program} \opt{using
+coredump {\it core}}\cr
+b \opt{\it file\tt:}{\it function}&set breakpoint at {\it function} \opt{in \it file}\cr
+run \opt{{\it arglist}}&start your program \opt{with {\it arglist}}\cr
+bt& backtrace: display program stack\cr
+p {\it expr}&display the value of an expression\cr
+c &continue running your program\cr
+n &next line, stepping over function calls\cr
+s &next line, stepping into function calls\cr
+\endsec
+
+\sec Starting GDB;
+gdb&start GDB, with no debugging files\cr
+gdb {\it program}&begin debugging {\it program}\cr
+gdb {\it program core}&debug coredump {\it core} produced by {\it
+program}\cr
+gdb --help&describe command line options\cr
+\endsec
+
+\sec Stopping GDB;
+quit&exit GDB; also {\tt q} or {\tt EOF} (eg \ctl{d})\cr
+INTERRUPT&(eg \ctl{c}) terminate current command, or send to running process\cr
+\endsec
+
+\sec Getting Help;
+help&list classes of commands\cr
+help {\it class}&one-line descriptions for commands in {\it class}\cr
+help {\it command}&describe {\it command}\cr
+\endsec
+
+\sec Executing your Program;
+run {\it arglist}&start your program with {\it arglist}\cr
+run&start your program with current argument list\cr
+run $\ldots$ <{\it inf} >{\it outf}&start your program with input, output
+redirected\cr
+\cr
+kill&kill running program\cr
+\cr
+tty {\it dev}&use {\it dev} as stdin and stdout for next {\tt run}\cr
+set args {\it arglist}&specify {\it arglist} for next
+{\tt run}\cr
+set args&specify empty argument list\cr
+show args&display argument list\cr
+\cr
+show env&show all environment variables\cr
+show env {\it var}&show value of environment variable {\it var}\cr
+set env {\it var} {\it string}&set environment variable {\it var}\cr
+unset env {\it var}&remove {\it var} from environment\cr
+\endsec
+
+\sec Shell Commands;
+cd {\it dir}&change working directory to {\it dir}\cr
+pwd&Print working directory\cr
+make $\ldots$&call ``{\tt make}''\cr
+shell {\it cmd}&execute arbitrary shell command string\cr
+\endsec
+
+\vfill
+\line{\smrm \opt{ } surround optional arguments \hfill $\ldots$ show
+one or more arguments}
+\vskip\baselineskip
+\centerline{\smrm \copyright 1991, 1992, 1993 Free Software Foundation, Inc.\qquad Permissions on back}
+\eject
+\sec Breakpoints and Watchpoints;
+break \opt{\it file\tt:}{\it line}\par
+b \opt{\it file\tt:}{\it line}&set breakpoint at {\it line} number \opt{in \it file}\par
+eg:\quad{\tt break main.c:37}\quad\cr
+break \opt{\it file\tt:}{\it func}&set breakpoint at {\it
+func} \opt{in \it file}\cr
+break +{\it offset}\par
+break -{\it offset}&set break at {\it offset} lines from current stop\cr
+break *{\it addr}&set breakpoint at address {\it addr}\cr
+break&set breakpoint at next instruction\cr
+break $\ldots$ if {\it expr}&break conditionally on nonzero {\it expr}\cr
+cond {\it n} \opt{\it expr}&new conditional expression on breakpoint
+{\it n}; make unconditional if no {\it expr}\cr
+tbreak $\ldots$&temporary break; disable when reached\cr
+rbreak {\it regex}&break on all functions matching {\it regex}\cr
+watch {\it expr}&set a watchpoint for expression {\it expr}\cr
+catch {\it x}&break at C++ handler for exception {\it x}\cr
+\cr
+info break&show defined breakpoints\cr
+info watch&show defined watchpoints\cr
+\cr
+clear&delete breakpoints at next instruction\cr
+clear \opt{\it file\tt:}{\it fun}&delete breakpoints at entry to {\it fun}()\cr
+clear \opt{\it file\tt:}{\it line}&delete breakpoints on source line \cr
+delete \opt{{\it n}}&delete breakpoints
+\opt{or breakpoint {\it n}}\cr
+\cr
+disable \opt{{\it n}}&disable breakpoints
+\opt{or breakpoint {\it n}}
+\cr
+enable \opt{{\it n}}&enable breakpoints
+\opt{or breakpoint {\it n}}
+\cr
+enable once \opt{{\it n}}&enable breakpoints \opt{or breakpoint {\it n}};
+disable again when reached
+\cr
+enable del \opt{{\it n}}&enable breakpoints \opt{or breakpoint {\it n}};
+delete when reached
+\cr
+\cr
+ignore {\it n} {\it count}&ignore breakpoint {\it n}, {\it count}
+times\cr
+\cr
+commands {\it n}\par
+\qquad \opt{\tt silent}\par
+\qquad {\it command-list}&execute GDB {\it command-list} every time breakpoint {\it n} is reached. \opt{{\tt silent} suppresses default
+display}\cr
+end&end of {\it command-list}\cr
+\endsec
+
+\sec Program Stack;
+backtrace \opt{\it n}\par
+bt \opt{\it n}&print trace of all frames in stack; or of {\it n}
+frames---innermost if {\it n}{\tt >0}, outermost if {\it n}{\tt <0}\cr
+frame \opt{\it n}&select frame number {\it n} or frame at address {\it
+n}; if no {\it n}, display current frame\cr
+up {\it n}&select frame {\it n} frames up\cr
+down {\it n}&select frame {\it n} frames down\cr
+info frame \opt{\it addr}&describe selected frame, or frame at
+{\it addr}\cr
+info args&arguments of selected frame\cr
+info locals&local variables of selected frame\cr
+info reg \opt{\it rn}$\ldots$\par
+info all-reg \opt{\it rn}&register values \opt{for regs {\it rn\/}} in
+selected frame; {\tt all-reg} includes floating point\cr
+info catch&exception handlers active in selected frame\cr
+\endsec
+
+\vfill\eject
+\sec Execution Control;
+continue \opt{\it count}\par
+c \opt{\it count}&continue running; if {\it count} specified, ignore
+this breakpoint next {\it count} times\cr
+\cr
+step \opt{\it count}\par
+s \opt{\it count}&execute until another line reached; repeat {\it count} times if
+specified\cr
+stepi \opt{\it count}\par
+si \opt{\it count}&step by machine instructions rather than source
+lines\cr
+\cr
+next \opt{\it count}\par
+n \opt{\it count}&execute next line, including any function calls\cr
+nexti \opt{\it count}\par
+ni \opt{\it count}&next machine instruction rather than source
+line\cr
+\cr
+until \opt{\it location}&run until next instruction (or {\it
+location})\cr
+finish&run until selected stack frame returns\cr
+return \opt{\it expr}&pop selected stack frame without executing
+\opt{setting return value}\cr
+signal {\it num}&resume execution with signal {\it s} (none if {\tt 0})\cr
+jump {\it line}\par
+jump *{\it address}&resume execution at specified {\it line} number or
+{\it address}\cr
+set var={\it expr}&evaluate {\it expr} without displaying it; use for
+altering program variables\cr
+\endsec
+
+\sec Display;
+print \opt{\tt/{\it f}\/} \opt{\it expr}\par
+p \opt{\tt/{\it f}\/} \opt{\it expr}&show value of {\it expr} \opt{or
+last value \tt \$} according to format {\it f}:\cr
+\qquad x&hexadecimal\cr
+\qquad d&signed decimal\cr
+\qquad u&unsigned decimal\cr
+\qquad o&octal\cr
+\qquad t&binary\cr
+\qquad a&address, absolute and relative\cr
+\qquad c&character\cr
+\qquad f&floating point\cr
+call \opt{\tt /{\it f}\/} {\it expr}&like {\tt print} but does not display
+{\tt void}\cr
+x \opt{\tt/{\it Nuf}\/} {\it expr}&examine memory at address {\it expr};
+optional format spec follows slash\cr
+\quad {\it N}&count of how many units to display\cr
+\quad {\it u}&unit size; one of\cr
+&{\tt\qquad b}\ individual bytes\cr
+&{\tt\qquad h}\ halfwords (two bytes)\cr
+&{\tt\qquad w}\ words (four bytes)\cr
+&{\tt\qquad g}\ giant words (eight bytes)\cr
+\quad {\it f}&printing format. Any {\tt print} format, or\cr
+&{\tt\qquad s}\ null-terminated string\cr
+&{\tt\qquad i}\ machine instructions\cr
+disassem \opt{\it addr}&display memory as machine instructions\cr
+\endsec
+
+\sec Automatic Display;
+display \opt{\tt/\it f\/} {\it expr}&show value of {\it expr} each time
+program stops \opt{according to format {\it f}\/}\cr
+display&display all enabled expressions on list\cr
+undisplay {\it n}&remove number(s) {\it n} from list of
+automatically displayed expressions\cr
+disable disp {\it n}&disable display for expression(s) number {\it
+n}\cr
+enable disp {\it n}&enable display for expression(s) number {\it
+n}\cr
+info display&numbered list of display expressions\cr
+\endsec
+
+\vfill\eject
+
+\sec Expressions;
+{\it expr}&an expression in C, C++, or Modula-2 (including function calls), or:\cr
+{\it addr\/}@{\it len}&an array of {\it len} elements beginning at {\it
+addr}\cr
+{\it file}::{\it nm}&a variable or function {\it nm} defined in {\it
+file}\cr
+$\tt\{${\it type}$\tt\}${\it addr}&read memory at {\it addr} as specified
+{\it type}\cr
+\$&most recent displayed value\cr
+\${\it n}&{\it n}th displayed value\cr
+\$\$&displayed value previous to \$\cr
+\$\${\it n}&{\it n}th displayed value back from \$\cr
+\$\_&last address examined with {\tt x}\cr
+\$\_\_&value at address \$\_\cr
+\${\it var}&convenience variable; assign any value\cr
+\cr
+show values \opt{{\it n}}&show last 10 values \opt{or surrounding
+\${\it n}}\cr
+show conv&display all convenience variables\cr
+\endsec
+
+\sec Symbol Table;
+info address {\it s}&show where symbol {\it s} is stored\cr
+info func \opt{\it regex}&show names, types of defined functions
+(all, or matching {\it regex})\cr
+info var \opt{\it regex}&show names, types of global variables (all,
+or matching {\it regex})\cr
+whatis \opt{\it expr}\par
+ptype \opt{\it expr}&show data type of {\it expr} \opt{or \tt \$}
+without evaluating; {\tt ptype} gives more detail\cr
+ptype {\it type}&describe type, struct, union, or enum\cr
+\endsec
+
+\sec GDB Scripts;
+source {\it script}&read, execute GDB commands from file {\it
+script}\cr
+\cr
+define {\it cmd}\par
+\qquad {\it command-list}&create new GDB command {\it cmd};
+execute script defined by {\it command-list}\cr
+end&end of {\it command-list}\cr
+document {\it cmd}\par
+\qquad {\it help-text}&create online documentation
+for new GDB command {\it cmd}\cr
+end&end of {\it help-text}\cr
+\endsec
+
+\sec Signals;
+handle {\it signal} {\it act}&specify GDB actions for {\it signal}:\cr
+\quad print&announce signal\cr
+\quad noprint&be silent for signal\cr
+\quad stop&halt execution on signal\cr
+\quad nostop&do not halt execution\cr
+\quad pass&allow your program to handle signal\cr
+\quad nopass&do not allow your program to see signal\cr
+info signals&show table of signals, GDB action for each\cr
+\endsec
+
+\sec Debugging Targets;
+target {\it type} {\it param}&connect to target machine, process, or file\cr
+help target&display available targets\cr
+attach {\it param}&connect to another process\cr
+detach&release target from GDB control\cr
+\endsec
+
+\vfill\eject
+\sec Controlling GDB;
+set {\it param} {\it value}&set one of GDB's internal parameters\cr
+show {\it param}&display current setting of parameter\cr
+\xtra{\rm Parameters understood by {\tt set} and {\tt show}:}
+\quad complaint {\it limit}&number of messages on unusual symbols\cr
+\quad confirm {\it on/off}&enable or disable cautionary queries\cr
+\quad editing {\it on/off}&control {\tt readline} command-line editing\cr
+\quad height {\it lpp}&number of lines before pause in display\cr
+\quad language {\it lang}&Language for GDB expressions ({\tt auto}, {\tt c} or
+{\tt modula-2})\cr
+\quad listsize {\it n}&number of lines shown by {\tt list}\cr
+\quad prompt {\it str}&use {\it str} as GDB prompt\cr
+\quad radix {\it base}&octal, decimal, or hex number representation\cr
+\quad verbose {\it on/off}&control messages when loading
+symbols\cr
+\quad width {\it cpl}&number of characters before line folded\cr
+\quad write {\it on/off}&Allow or forbid patching binary, core files
+(when reopened with {\tt exec} or {\tt core})
+\cr
+\quad history $\ldots$\par
+\quad h $\ldots$&groups with the following options:\cr
+\quad h exp {\it off/on}&disable/enable {\tt readline} history expansion\cr
+\quad h file {\it filename}&file for recording GDB command history\cr
+\quad h size {\it size}&number of commands kept in history list\cr
+\quad h save {\it off/on}&control use of external file for
+command history\cr
+\cr
+\quad print $\ldots$\par
+\quad p $\ldots$&groups with the following options:\cr
+\quad p address {\it on/off}&print memory addresses in stacks,
+values\cr
+\quad p array {\it off/on}&compact or attractive format for
+arrays\cr
+\quad p demangl {\it on/off}&source (demangled) or internal form for C++
+symbols\cr
+\quad p asm-dem {\it on/off}&demangle C++ symbols in
+machine-instruction output\cr
+\quad p elements {\it limit}&number of array elements to display\cr
+\quad p object {\it on/off}&print C++ derived types for objects\cr
+\quad p pretty {\it off/on}&struct display: compact or indented\cr
+\quad p union {\it on/off}&display of union members\cr
+\quad p vtbl {\it off/on}&display of C++ virtual function
+tables\cr
+\cr
+show commands&show last 10 commands\cr
+show commands {\it n}&show 10 commands around number {\it n}\cr
+show commands +&show next 10 commands\cr
+\endsec
+
+\sec Working Files;
+file \opt{\it file}&use {\it file} for both symbols and executable;
+with no arg, discard both\cr
+core \opt{\it file}&read {\it file} as coredump; or discard\cr
+exec \opt{\it file}&use {\it file} as executable only; or discard\cr
+symbol \opt{\it file}&use symbol table from {\it file}; or discard\cr
+load {\it file}&dynamically link {\it file\/} and add its symbols\cr
+add-sym {\it file} {\it addr}&read additional symbols from {\it file},
+dynamically loaded at {\it addr}\cr
+info files&display working files and targets in use\cr
+path {\it dirs}&add {\it dirs} to front of path searched for
+executable and symbol files\cr
+show path&display executable and symbol file path\cr
+info share&list names of shared libraries currently loaded\cr
+\endsec
+
+\vfill\eject
+\sec Source Files;
+dir {\it names}&add directory {\it names} to front of source path\cr
+dir&clear source path\cr
+show dir&show current source path\cr
+\cr
+list&show next ten lines of source\cr
+list -&show previous ten lines\cr
+list {\it lines}&display source surrounding {\it lines},
+specified as:\cr
+\quad{\opt{\it file\tt:}\it num}&line number \opt{in named file}\cr
+\quad{\opt{\it file\tt:}\it function}&beginning of function \opt{in
+named file}\cr
+\quad{\tt +\it off}&{\it off} lines after last printed\cr
+\quad{\tt -\it off}&{\it off} lines previous to last printed\cr
+\quad{\tt*\it address}&line containing {\it address}\cr
+list {\it f},{\it l}&from line {\it f} to line {\it l}\cr
+info line {\it num}&show starting, ending addresses of compiled code for
+source line {\it num}\cr
+info source&show name of current source file\cr
+info sources&list all source files in use\cr
+forw {\it regex}&search following source lines for {\it regex}\cr
+rev {\it regex}&search preceding source lines for {\it regex}\cr
+\endsec
+
+\sec GDB under GNU Emacs;
+M-x gdb&run GDB under Emacs\cr
+\ctl{h} m&describe GDB mode\cr
+M-s&step one line ({\tt step})\cr
+M-n&next line ({\tt next})\cr
+M-i&step one instruction ({\tt stepi})\cr
+\ctl{c} \ctl{f}&finish current stack frame ({\tt finish})\cr
+M-c&continue ({\tt cont})\cr
+M-u&up {\it arg} frames ({\tt up})\cr
+M-d&down {\it arg} frames ({\tt down})\cr
+\ctl{x} \&&copy number from point, insert at end\cr
+\ctl{x} SPC&(in source file) set break at point\cr
+\endsec
+
+\sec GDB License;
+show copying&Display GNU General Public License\cr
+show warranty&There is NO WARRANTY for GDB. Display full no-warranty
+statement.\cr
+\endsec
+
+
+\vfill
+{\smrm\parskip=6pt
+\centerline{Copyright \copyright 1991, 1992, 1993 Free Software Foundation, Inc.}
+\centerline{Cygnus Support (doc@cygnus.com)}
+\centerline{The author assumes no responsibility for any errors on this card.}
+
+This card may be freely distributed under the terms of the GNU
+General Public License.
+
+\centerline{Please contribute to development of this card by
+annotating it.}
+
+GDB itself is free software; you are welcome to distribute copies of
+it under the terms of the GNU General Public License. There is
+absolutely no warranty for GDB.
+}
+\end
diff --git a/contrib/gdb/gdb/doc/remote.texi b/contrib/gdb/gdb/doc/remote.texi
new file mode 100644
index 0000000..b878e19
--- /dev/null
+++ b/contrib/gdb/gdb/doc/remote.texi
@@ -0,0 +1,1531 @@
+@c -*- Texinfo -*-
+@c Copyright (c) 1990 1991 1992 1993 Free Software Foundation, Inc.
+@c This file is part of the source for the GDB manual.
+@c This text diverted to "Remote Debugging" section in general case;
+@c however, if we're doing a manual specifically for one of these, it
+@c belongs up front (in "Getting In and Out" chapter).
+
+@ifset REMOTESTUB
+@node Remote Serial
+@subsection The @value{GDBN} remote serial protocol
+
+@cindex remote serial debugging, overview
+To debug a program running on another machine (the debugging
+@dfn{target} machine), you must first arrange for all the usual
+prerequisites for the program to run by itself. For example, for a C
+program, you need:
+
+@enumerate
+@item
+A startup routine to set up the C runtime environment; these usually
+have a name like @file{crt0}. The startup routine may be supplied by
+your hardware supplier, or you may have to write your own.
+
+@item
+You probably need a C subroutine library to support your program's
+subroutine calls, notably managing input and output.
+
+@item
+A way of getting your program to the other machine---for example, a
+download program. These are often supplied by the hardware
+manufacturer, but you may have to write your own from hardware
+documentation.
+@end enumerate
+
+The next step is to arrange for your program to use a serial port to
+communicate with the machine where @value{GDBN} is running (the @dfn{host}
+machine). In general terms, the scheme looks like this:
+
+@table @emph
+@item On the host,
+@value{GDBN} already understands how to use this protocol; when everything
+else is set up, you can simply use the @samp{target remote} command
+(@pxref{Targets,,Specifying a Debugging Target}).
+
+@item On the target,
+you must link with your program a few special-purpose subroutines that
+implement the @value{GDBN} remote serial protocol. The file containing these
+subroutines is called a @dfn{debugging stub}.
+
+@ifset GDBSERVER
+On certain remote targets, you can use an auxiliary program
+@code{gdbserver} instead of linking a stub into your program.
+@xref{Server,,Using the @code{gdbserver} program}, for details.
+@end ifset
+@end table
+
+The debugging stub is specific to the architecture of the remote
+machine; for example, use @file{sparc-stub.c} to debug programs on
+@sc{sparc} boards.
+
+@cindex remote serial stub list
+These working remote stubs are distributed with @value{GDBN}:
+
+@table @code
+@item sparc-stub.c
+@kindex sparc-stub.c
+For @sc{sparc} architectures.
+
+@item m68k-stub.c
+@kindex m68k-stub.c
+@cindex Motorola 680x0
+@cindex m680x0
+For Motorola 680x0 architectures.
+
+@item i386-stub.c
+@kindex i386-stub.c
+@cindex Intel
+@cindex i386
+For Intel 386 and compatible architectures.
+@end table
+
+The @file{README} file in the @value{GDBN} distribution may list other
+recently added stubs.
+
+@menu
+* Stub Contents:: What the stub can do for you
+* Bootstrapping:: What you must do for the stub
+* Debug Session:: Putting it all together
+* Protocol:: Outline of the communication protocol
+@ifset GDBSERVER
+* Server:: Using the `gdbserver' program
+@end ifset
+@ifset GDBSERVE
+* NetWare:: Using the `gdbserve.nlm' program
+@end ifset
+@end menu
+
+@node Stub Contents
+@subsubsection What the stub can do for you
+
+@cindex remote serial stub
+The debugging stub for your architecture supplies these three
+subroutines:
+
+@table @code
+@item set_debug_traps
+@kindex set_debug_traps
+@cindex remote serial stub, initialization
+This routine arranges for @code{handle_exception} to run when your
+program stops. You must call this subroutine explicitly near the
+beginning of your program.
+
+@item handle_exception
+@kindex handle_exception
+@cindex remote serial stub, main routine
+This is the central workhorse, but your program never calls it
+explicitly---the setup code arranges for @code{handle_exception} to
+run when a trap is triggered.
+
+@code{handle_exception} takes control when your program stops during
+execution (for example, on a breakpoint), and mediates communications
+with @value{GDBN} on the host machine. This is where the communications
+protocol is implemented; @code{handle_exception} acts as the @value{GDBN}
+representative on the target machine; it begins by sending summary
+information on the state of your program, then continues to execute,
+retrieving and transmitting any information @value{GDBN} needs, until you
+execute a @value{GDBN} command that makes your program resume; at that point,
+@code{handle_exception} returns control to your own code on the target
+machine.
+
+@item breakpoint
+@cindex @code{breakpoint} subroutine, remote
+Use this auxiliary subroutine to make your program contain a
+breakpoint. Depending on the particular situation, this may be the only
+way for @value{GDBN} to get control. For instance, if your target
+machine has some sort of interrupt button, you won't need to call this;
+pressing the interrupt button transfers control to
+@code{handle_exception}---in effect, to @value{GDBN}. On some machines,
+simply receiving characters on the serial port may also trigger a trap;
+again, in that situation, you don't need to call @code{breakpoint} from
+your own program---simply running @samp{target remote} from the host
+@value{GDBN} session gets control.
+
+Call @code{breakpoint} if none of these is true, or if you simply want
+to make certain your program stops at a predetermined point for the
+start of your debugging session.
+@end table
+
+@node Bootstrapping
+@subsubsection What you must do for the stub
+
+@cindex remote stub, support routines
+The debugging stubs that come with @value{GDBN} are set up for a particular
+chip architecture, but they have no information about the rest of your
+debugging target machine.
+
+First of all you need to tell the stub how to communicate with the
+serial port.
+
+@table @code
+@item int getDebugChar()
+@kindex getDebugChar
+Write this subroutine to read a single character from the serial port.
+It may be identical to @code{getchar} for your target system; a
+different name is used to allow you to distinguish the two if you wish.
+
+@item void putDebugChar(int)
+@kindex putDebugChar
+Write this subroutine to write a single character to the serial port.
+It may be identical to @code{putchar} for your target system; a
+different name is used to allow you to distinguish the two if you wish.
+@end table
+
+@cindex control C, and remote debugging
+@cindex interrupting remote targets
+If you want @value{GDBN} to be able to stop your program while it is
+running, you need to use an interrupt-driven serial driver, and arrange
+for it to stop when it receives a @code{^C} (@samp{\003}, the control-C
+character). That is the character which @value{GDBN} uses to tell the
+remote system to stop.
+
+Getting the debugging target to return the proper status to @value{GDBN}
+probably requires changes to the standard stub; one quick and dirty way
+is to just execute a breakpoint instruction (the ``dirty'' part is that
+@value{GDBN} reports a @code{SIGTRAP} instead of a @code{SIGINT}).
+
+Other routines you need to supply are:
+
+@table @code
+@item void exceptionHandler (int @var{exception_number}, void *@var{exception_address})
+@kindex exceptionHandler
+Write this function to install @var{exception_address} in the exception
+handling tables. You need to do this because the stub does not have any
+way of knowing what the exception handling tables on your target system
+are like (for example, the processor's table might be in @sc{rom},
+containing entries which point to a table in @sc{ram}).
+@var{exception_number} is the exception number which should be changed;
+its meaning is architecture-dependent (for example, different numbers
+might represent divide by zero, misaligned access, etc). When this
+exception occurs, control should be transferred directly to
+@var{exception_address}, and the processor state (stack, registers,
+and so on) should be just as it is when a processor exception occurs. So if
+you want to use a jump instruction to reach @var{exception_address}, it
+should be a simple jump, not a jump to subroutine.
+
+For the 386, @var{exception_address} should be installed as an interrupt
+gate so that interrupts are masked while the handler runs. The gate
+should be at privilege level 0 (the most privileged level). The
+@sc{sparc} and 68k stubs are able to mask interrup themselves without
+help from @code{exceptionHandler}.
+
+@item void flush_i_cache()
+@kindex flush_i_cache
+(sparc and sparclite only) Write this subroutine to flush the
+instruction cache, if any, on your target machine. If there is no
+instruction cache, this subroutine may be a no-op.
+
+On target machines that have instruction caches, @value{GDBN} requires this
+function to make certain that the state of your program is stable.
+@end table
+
+@noindent
+You must also make sure this library routine is available:
+
+@table @code
+@item void *memset(void *, int, int)
+@kindex memset
+This is the standard library function @code{memset} that sets an area of
+memory to a known value. If you have one of the free versions of
+@code{libc.a}, @code{memset} can be found there; otherwise, you must
+either obtain it from your hardware manufacturer, or write your own.
+@end table
+
+If you do not use the GNU C compiler, you may need other standard
+library subroutines as well; this varies from one stub to another,
+but in general the stubs are likely to use any of the common library
+subroutines which @code{gcc} generates as inline code.
+
+
+@node Debug Session
+@subsubsection Putting it all together
+
+@cindex remote serial debugging summary
+In summary, when your program is ready to debug, you must follow these
+steps.
+
+@enumerate
+@item
+Make sure you have the supporting low-level routines
+(@pxref{Bootstrapping,,What you must do for the stub}):
+@display
+@code{getDebugChar}, @code{putDebugChar},
+@code{flush_i_cache}, @code{memset}, @code{exceptionHandler}.
+@end display
+
+@item
+Insert these lines near the top of your program:
+
+@example
+set_debug_traps();
+breakpoint();
+@end example
+
+@item
+For the 680x0 stub only, you need to provide a variable called
+@code{exceptionHook}. Normally you just use:
+
+@example
+void (*exceptionHook)() = 0;
+@end example
+
+but if before calling @code{set_debug_traps}, you set it to point to a
+function in your program, that function is called when
+@code{@value{GDBN}} continues after stopping on a trap (for example, bus
+error). The function indicated by @code{exceptionHook} is called with
+one parameter: an @code{int} which is the exception number.
+
+@item
+Compile and link together: your program, the @value{GDBN} debugging stub for
+your target architecture, and the supporting subroutines.
+
+@item
+Make sure you have a serial connection between your target machine and
+the @value{GDBN} host, and identify the serial port on the host.
+
+@item
+@c The "remote" target now provides a `load' command, so we should
+@c document that. FIXME.
+Download your program to your target machine (or get it there by
+whatever means the manufacturer provides), and start it.
+
+@item
+To start remote debugging, run @value{GDBN} on the host machine, and specify
+as an executable file the program that is running in the remote machine.
+This tells @value{GDBN} how to find your program's symbols and the contents
+of its pure text.
+
+@cindex serial line, @code{target remote}
+Then establish communication using the @code{target remote} command.
+Its argument specifies how to communicate with the target
+machine---either via a devicename attached to a direct serial line, or a
+TCP port (usually to a terminal server which in turn has a serial line
+to the target). For example, to use a serial line connected to the
+device named @file{/dev/ttyb}:
+
+@example
+target remote /dev/ttyb
+@end example
+
+@cindex TCP port, @code{target remote}
+To use a TCP connection, use an argument of the form
+@code{@var{host}:port}. For example, to connect to port 2828 on a
+terminal server named @code{manyfarms}:
+
+@example
+target remote manyfarms:2828
+@end example
+@end enumerate
+
+Now you can use all the usual commands to examine and change data and to
+step and continue the remote program.
+
+To resume the remote program and stop debugging it, use the @code{detach}
+command.
+
+@cindex interrupting remote programs
+@cindex remote programs, interrupting
+Whenever @value{GDBN} is waiting for the remote program, if you type the
+interrupt character (often @key{C-C}), @value{GDBN} attempts to stop the
+program. This may or may not succeed, depending in part on the hardware
+and the serial drivers the remote system uses. If you type the
+interrupt character once again, @value{GDBN} displays this prompt:
+
+@example
+Interrupted while waiting for the program.
+Give up (and stop debugging it)? (y or n)
+@end example
+
+If you type @kbd{y}, @value{GDBN} abandons the remote debugging session.
+(If you decide you want to try again later, you can use @samp{target
+remote} again to connect once more.) If you type @kbd{n}, @value{GDBN}
+goes back to waiting.
+
+@node Protocol
+@subsubsection Communication protocol
+
+@cindex debugging stub, example
+@cindex remote stub, example
+@cindex stub example, remote debugging
+The stub files provided with @value{GDBN} implement the target side of the
+communication protocol, and the @value{GDBN} side is implemented in the
+@value{GDBN} source file @file{remote.c}. Normally, you can simply allow
+these subroutines to communicate, and ignore the details. (If you're
+implementing your own stub file, you can still ignore the details: start
+with one of the existing stub files. @file{sparc-stub.c} is the best
+organized, and therefore the easiest to read.)
+
+However, there may be occasions when you need to know something about
+the protocol---for example, if there is only one serial port to your
+target machine, you might want your program to do something special if
+it recognizes a packet meant for @value{GDBN}.
+
+@cindex protocol, @value{GDBN} remote serial
+@cindex serial protocol, @value{GDBN} remote
+@cindex remote serial protocol
+All @value{GDBN} commands and responses (other than acknowledgements, which
+are single characters) are sent as a packet which includes a
+checksum. A packet is introduced with the character @samp{$}, and ends
+with the character @samp{#} followed by a two-digit checksum:
+
+@example
+$@var{packet info}#@var{checksum}
+@end example
+
+@cindex checksum, for @value{GDBN} remote
+@noindent
+@var{checksum} is computed as the modulo 256 sum of the @var{packet
+info} characters.
+
+When either the host or the target machine receives a packet, the first
+response expected is an acknowledgement: a single character, either
+@samp{+} (to indicate the package was received correctly) or @samp{-}
+(to request retransmission).
+
+The host (@value{GDBN}) sends commands, and the target (the debugging stub
+incorporated in your program) sends data in response. The target also
+sends data when your program stops.
+
+Command packets are distinguished by their first character, which
+identifies the kind of command.
+
+These are some of the commands currently supported (for a complete list of
+commands, look in @file{gdb/remote.c.}):
+
+@table @code
+@item g
+Requests the values of CPU registers.
+
+@item G
+Sets the values of CPU registers.
+
+@item m@var{addr},@var{count}
+Read @var{count} bytes at location @var{addr}.
+
+@item M@var{addr},@var{count}:@dots{}
+Write @var{count} bytes at location @var{addr}.
+
+@need 500
+@item c
+@itemx c@var{addr}
+Resume execution at the current address (or at @var{addr} if supplied).
+
+@need 500
+@item s
+@itemx s@var{addr}
+Step the target program for one instruction, from either the current
+program counter or from @var{addr} if supplied.
+
+@item k
+Kill the target program.
+
+@item ?
+Report the most recent signal. To allow you to take advantage of the
+@value{GDBN} signal handling commands, one of the functions of the debugging
+stub is to report CPU traps as the corresponding POSIX signal values.
+
+@item T
+Allows the remote stub to send only the registers that @value{GDBN} needs
+to make a quick decision about single-stepping or conditional breakpoints.
+This eliminates the need to fetch the entire register set for each instruction
+being stepped through.
+
+The @value{GDBN} remote serial protocol now implements a write-through
+cache for registers. @value{GDBN} only re-reads the registers if the
+target has run.
+@end table
+
+@kindex set remotedebug
+@kindex show remotedebug
+@cindex packets, reporting on stdout
+@cindex serial connections, debugging
+If you have trouble with the serial connection, you can use the command
+@code{set remotedebug}. This makes @value{GDBN} report on all packets sent
+back and forth across the serial line to the remote machine. The
+packet-debugging information is printed on the @value{GDBN} standard output
+stream. @code{set remotedebug off} turns it off, and @code{show
+remotedebug} shows you its current state.
+
+@ifset GDBSERVER
+@node Server
+@subsubsection Using the @code{gdbserver} program
+
+@kindex gdbserver
+@cindex remote connection without stubs
+@code{gdbserver} is a control program for Unix-like systems, which
+allows you to connect your program with a remote @value{GDBN} via
+@code{target remote}---but without linking in the usual debugging stub.
+
+@code{gdbserver} is not a complete replacement for the debugging stubs,
+because it requires essentially the same operating-system facilities
+that @value{GDBN} itself does. In fact, a system that can run
+@code{gdbserver} to connect to a remote @value{GDBN} could also run
+@value{GDBN} locally! @code{gdbserver} is sometimes useful nevertheless,
+because it is a much smaller program than @value{GDBN} itself. It is
+also easier to port than all of @value{GDBN}, so you may be able to get
+started more quickly on a new system by using @code{gdbserver}.
+Finally, if you develop code for real-time systems, you may find that
+the tradeoffs involved in real-time operation make it more convenient to
+do as much development work as possible on another system, for example
+by cross-compiling. You can use @code{gdbserver} to make a similar
+choice for debugging.
+
+@value{GDBN} and @code{gdbserver} communicate via either a serial line
+or a TCP connection, using the standard @value{GDBN} remote serial
+protocol.
+
+@table @emph
+@item On the target machine,
+you need to have a copy of the program you want to debug.
+@code{gdbserver} does not need your program's symbol table, so you can
+strip the program if necessary to save space. @value{GDBN} on the host
+system does all the symbol handling.
+
+To use the server, you must tell it how to communicate with @value{GDBN};
+the name of your program; and the arguments for your program. The
+syntax is:
+
+@smallexample
+target> gdbserver @var{comm} @var{program} [ @var{args} @dots{} ]
+@end smallexample
+
+@var{comm} is either a device name (to use a serial line) or a TCP
+hostname and portnumber. For example, to debug Emacs with the argument
+@samp{foo.txt} and communicate with @value{GDBN} over the serial port
+@file{/dev/com1}:
+
+@smallexample
+target> gdbserver /dev/com1 emacs foo.txt
+@end smallexample
+
+@code{gdbserver} waits passively for the host @value{GDBN} to communicate
+with it.
+
+To use a TCP connection instead of a serial line:
+
+@smallexample
+target> gdbserver host:2345 emacs foo.txt
+@end smallexample
+
+The only difference from the previous example is the first argument,
+specifying that you are communicating with the host @value{GDBN} via
+TCP. The @samp{host:2345} argument means that @code{gdbserver} is to
+expect a TCP connection from machine @samp{host} to local TCP port 2345.
+(Currently, the @samp{host} part is ignored.) You can choose any number
+you want for the port number as long as it does not conflict with any
+TCP ports already in use on the target system (for example, @code{23} is
+reserved for @code{telnet}).@footnote{If you choose a port number that
+conflicts with another service, @code{gdbserver} prints an error message
+and exits.} You must use the same port number with the host @value{GDBN}
+@code{target remote} command.
+
+@item On the @value{GDBN} host machine,
+you need an unstripped copy of your program, since @value{GDBN} needs
+symbols and debugging information. Start up @value{GDBN} as usual,
+using the name of the local copy of your program as the first argument.
+(You may also need the @w{@samp{--baud}} option if the serial line is
+running at anything other than 9600 bps.) After that, use @code{target
+remote} to establish communications with @code{gdbserver}. Its argument
+is either a device name (usually a serial device, like
+@file{/dev/ttyb}), or a TCP port descriptor in the form
+@code{@var{host}:@var{PORT}}. For example:
+
+@smallexample
+(@value{GDBP}) target remote /dev/ttyb
+@end smallexample
+
+@noindent
+communicates with the server via serial line @file{/dev/ttyb}, and
+
+@smallexample
+(@value{GDBP}) target remote the-target:2345
+@end smallexample
+
+@noindent
+communicates via a TCP connection to port 2345 on host @w{@file{the-target}}.
+For TCP connections, you must start up @code{gdbserver} prior to using
+the @code{target remote} command. Otherwise you may get an error whose
+text depends on the host system, but which usually looks something like
+@samp{Connection refused}.
+@end table
+@end ifset
+
+@ifset GDBSERVE
+@node NetWare
+@subsubsection Using the @code{gdbserve.nlm} program
+
+@kindex gdbserve.nlm
+@code{gdbserve.nlm} is a control program for NetWare systems, which
+allows you to connect your program with a remote @value{GDBN} via
+@code{target remote}.
+
+@value{GDBN} and @code{gdbserve.nlm} communicate via a serial line,
+using the standard @value{GDBN} remote serial protocol.
+
+@table @emph
+@item On the target machine,
+you need to have a copy of the program you want to debug.
+@code{gdbserve.nlm} does not need your program's symbol table, so you
+can strip the program if necessary to save space. @value{GDBN} on the
+host system does all the symbol handling.
+
+To use the server, you must tell it how to communicate with
+@value{GDBN}; the name of your program; and the arguments for your
+program. The syntax is:
+
+@smallexample
+load gdbserve [ BOARD=@var{board} ] [ PORT=@var{port} ]
+ [ BAUD=@var{baud} ] @var{program} [ @var{args} @dots{} ]
+@end smallexample
+
+@var{board} and @var{port} specify the serial line; @var{baud} specifies
+the baud rate used by the connection. @var{port} and @var{node} default
+to 0, @var{baud} defaults to 9600 bps.
+
+For example, to debug Emacs with the argument @samp{foo.txt}and
+communicate with @value{GDBN} over serial port number 2 or board 1
+using a 19200 bps connection:
+
+@smallexample
+load gdbserve BOARD=1 PORT=2 BAUD=19200 emacs foo.txt
+@end smallexample
+
+@item On the @value{GDBN} host machine,
+you need an unstripped copy of your program, since @value{GDBN} needs
+symbols and debugging information. Start up @value{GDBN} as usual,
+using the name of the local copy of your program as the first argument.
+(You may also need the @w{@samp{--baud}} option if the serial line is
+running at anything other than 9600 bps. After that, use @code{target
+remote} to establish communications with @code{gdbserve.nlm}. Its
+argument is a device name (usually a serial device, like
+@file{/dev/ttyb}). For example:
+
+@smallexample
+(@value{GDBP}) target remote /dev/ttyb
+@end smallexample
+
+@noindent
+communications with the server via serial line @file{/dev/ttyb}.
+@end table
+@end ifset
+
+@end ifset
+
+@ifset I960
+@node i960-Nindy Remote
+@subsection @value{GDBN} with a remote i960 (Nindy)
+
+@cindex Nindy
+@cindex i960
+@dfn{Nindy} is a ROM Monitor program for Intel 960 target systems. When
+@value{GDBN} is configured to control a remote Intel 960 using Nindy, you can
+tell @value{GDBN} how to connect to the 960 in several ways:
+
+@itemize @bullet
+@item
+Through command line options specifying serial port, version of the
+Nindy protocol, and communications speed;
+
+@item
+By responding to a prompt on startup;
+
+@item
+By using the @code{target} command at any point during your @value{GDBN}
+session. @xref{Target Commands, ,Commands for managing targets}.
+
+@end itemize
+
+@menu
+* Nindy Startup:: Startup with Nindy
+* Nindy Options:: Options for Nindy
+* Nindy Reset:: Nindy reset command
+@end menu
+
+@node Nindy Startup
+@subsubsection Startup with Nindy
+
+If you simply start @code{@value{GDBP}} without using any command-line
+options, you are prompted for what serial port to use, @emph{before} you
+reach the ordinary @value{GDBN} prompt:
+
+@example
+Attach /dev/ttyNN -- specify NN, or "quit" to quit:
+@end example
+
+@noindent
+Respond to the prompt with whatever suffix (after @samp{/dev/tty})
+identifies the serial port you want to use. You can, if you choose,
+simply start up with no Nindy connection by responding to the prompt
+with an empty line. If you do this and later wish to attach to Nindy,
+use @code{target} (@pxref{Target Commands, ,Commands for managing targets}).
+
+@node Nindy Options
+@subsubsection Options for Nindy
+
+These are the startup options for beginning your @value{GDBN} session with a
+Nindy-960 board attached:
+
+@table @code
+@item -r @var{port}
+Specify the serial port name of a serial interface to be used to connect
+to the target system. This option is only available when @value{GDBN} is
+configured for the Intel 960 target architecture. You may specify
+@var{port} as any of: a full pathname (e.g. @samp{-r /dev/ttya}), a
+device name in @file{/dev} (e.g. @samp{-r ttya}), or simply the unique
+suffix for a specific @code{tty} (e.g. @samp{-r a}).
+
+@item -O
+(An uppercase letter ``O'', not a zero.) Specify that @value{GDBN} should use
+the ``old'' Nindy monitor protocol to connect to the target system.
+This option is only available when @value{GDBN} is configured for the Intel 960
+target architecture.
+
+@quotation
+@emph{Warning:} if you specify @samp{-O}, but are actually trying to
+connect to a target system that expects the newer protocol, the connection
+fails, appearing to be a speed mismatch. @value{GDBN} repeatedly
+attempts to reconnect at several different line speeds. You can abort
+this process with an interrupt.
+@end quotation
+
+@item -brk
+Specify that @value{GDBN} should first send a @code{BREAK} signal to the target
+system, in an attempt to reset it, before connecting to a Nindy target.
+
+@quotation
+@emph{Warning:} Many target systems do not have the hardware that this
+requires; it only works with a few boards.
+@end quotation
+@end table
+
+The standard @samp{-b} option controls the line speed used on the serial
+port.
+
+@c @group
+@node Nindy Reset
+@subsubsection Nindy reset command
+
+@table @code
+@item reset
+@kindex reset
+For a Nindy target, this command sends a ``break'' to the remote target
+system; this is only useful if the target has been equipped with a
+circuit to perform a hard reset (or some other interesting action) when
+a break is detected.
+@end table
+@c @end group
+@end ifset
+
+@ifset AMD29K
+@node UDI29K Remote
+@subsection The UDI protocol for AMD29K
+
+@cindex UDI
+@cindex AMD29K via UDI
+@value{GDBN} supports AMD's UDI (``Universal Debugger Interface'')
+protocol for debugging the a29k processor family. To use this
+configuration with AMD targets running the MiniMON monitor, you need the
+program @code{MONTIP}, available from AMD at no charge. You can also
+use @value{GDBN} with the UDI-conformant a29k simulator program
+@code{ISSTIP}, also available from AMD.
+
+@table @code
+@item target udi @var{keyword}
+@kindex udi
+Select the UDI interface to a remote a29k board or simulator, where
+@var{keyword} is an entry in the AMD configuration file @file{udi_soc}.
+This file contains keyword entries which specify parameters used to
+connect to a29k targets. If the @file{udi_soc} file is not in your
+working directory, you must set the environment variable @samp{UDICONF}
+to its pathname.
+@end table
+
+@node EB29K Remote
+@subsection The EBMON protocol for AMD29K
+
+@cindex EB29K board
+@cindex running 29K programs
+
+AMD distributes a 29K development board meant to fit in a PC, together
+with a DOS-hosted monitor program called @code{EBMON}. As a shorthand
+term, this development system is called the ``EB29K''. To use
+@value{GDBN} from a Unix system to run programs on the EB29K board, you
+must first connect a serial cable between the PC (which hosts the EB29K
+board) and a serial port on the Unix system. In the following, we
+assume you've hooked the cable between the PC's @file{COM1} port and
+@file{/dev/ttya} on the Unix system.
+
+@menu
+* Comms (EB29K):: Communications setup
+* gdb-EB29K:: EB29K cross-debugging
+* Remote Log:: Remote log
+@end menu
+
+@node Comms (EB29K)
+@subsubsection Communications setup
+
+The next step is to set up the PC's port, by doing something like this
+in DOS on the PC:
+
+@example
+C:\> MODE com1:9600,n,8,1,none
+@end example
+
+@noindent
+This example---run on an MS DOS 4.0 system---sets the PC port to 9600
+bps, no parity, eight data bits, one stop bit, and no ``retry'' action;
+you must match the communications parameters when establishing the Unix
+end of the connection as well.
+@c FIXME: Who knows what this "no retry action" crud from the DOS manual may
+@c mean? It's optional; leave it out? ---doc@cygnus.com, 25feb91
+
+To give control of the PC to the Unix side of the serial line, type
+the following at the DOS console:
+
+@example
+C:\> CTTY com1
+@end example
+
+@noindent
+(Later, if you wish to return control to the DOS console, you can use
+the command @code{CTTY con}---but you must send it over the device that
+had control, in our example over the @file{COM1} serial line).
+
+From the Unix host, use a communications program such as @code{tip} or
+@code{cu} to communicate with the PC; for example,
+
+@example
+cu -s 9600 -l /dev/ttya
+@end example
+
+@noindent
+The @code{cu} options shown specify, respectively, the linespeed and the
+serial port to use. If you use @code{tip} instead, your command line
+may look something like the following:
+
+@example
+tip -9600 /dev/ttya
+@end example
+
+@noindent
+Your system may require a different name where we show
+@file{/dev/ttya} as the argument to @code{tip}. The communications
+parameters, including which port to use, are associated with the
+@code{tip} argument in the ``remote'' descriptions file---normally the
+system table @file{/etc/remote}.
+@c FIXME: What if anything needs doing to match the "n,8,1,none" part of
+@c the DOS side's comms setup? cu can support -o (odd
+@c parity), -e (even parity)---apparently no settings for no parity or
+@c for character size. Taken from stty maybe...? John points out tip
+@c can set these as internal variables, eg ~s parity=none; man stty
+@c suggests that it *might* work to stty these options with stdin or
+@c stdout redirected... ---doc@cygnus.com, 25feb91
+
+@kindex EBMON
+Using the @code{tip} or @code{cu} connection, change the DOS working
+directory to the directory containing a copy of your 29K program, then
+start the PC program @code{EBMON} (an EB29K control program supplied
+with your board by AMD). You should see an initial display from
+@code{EBMON} similar to the one that follows, ending with the
+@code{EBMON} prompt @samp{#}---
+
+@example
+C:\> G:
+
+G:\> CD \usr\joe\work29k
+
+G:\USR\JOE\WORK29K> EBMON
+Am29000 PC Coprocessor Board Monitor, version 3.0-18
+Copyright 1990 Advanced Micro Devices, Inc.
+Written by Gibbons and Associates, Inc.
+
+Enter '?' or 'H' for help
+
+PC Coprocessor Type = EB29K
+I/O Base = 0x208
+Memory Base = 0xd0000
+
+Data Memory Size = 2048KB
+Available I-RAM Range = 0x8000 to 0x1fffff
+Available D-RAM Range = 0x80002000 to 0x801fffff
+
+PageSize = 0x400
+Register Stack Size = 0x800
+Memory Stack Size = 0x1800
+
+CPU PRL = 0x3
+Am29027 Available = No
+Byte Write Available = Yes
+
+# ~.
+@end example
+
+Then exit the @code{cu} or @code{tip} program (done in the example by
+typing @code{~.} at the @code{EBMON} prompt). @code{EBMON} keeps
+running, ready for @value{GDBN} to take over.
+
+For this example, we've assumed what is probably the most convenient
+way to make sure the same 29K program is on both the PC and the Unix
+system: a PC/NFS connection that establishes ``drive @code{G:}'' on the
+PC as a file system on the Unix host. If you do not have PC/NFS or
+something similar connecting the two systems, you must arrange some
+other way---perhaps floppy-disk transfer---of getting the 29K program
+from the Unix system to the PC; @value{GDBN} does @emph{not} download it over the
+serial line.
+
+@node gdb-EB29K
+@subsubsection EB29K cross-debugging
+
+Finally, @code{cd} to the directory containing an image of your 29K
+program on the Unix system, and start @value{GDBN}---specifying as argument the
+name of your 29K program:
+
+@example
+cd /usr/joe/work29k
+@value{GDBP} myfoo
+@end example
+
+@need 500
+Now you can use the @code{target} command:
+
+@example
+target amd-eb /dev/ttya 9600 MYFOO
+@c FIXME: test above 'target amd-eb' as spelled, with caps! caps are meant to
+@c emphasize that this is the name as seen by DOS (since I think DOS is
+@c single-minded about case of letters). ---doc@cygnus.com, 25feb91
+@end example
+
+@noindent
+In this example, we've assumed your program is in a file called
+@file{myfoo}. Note that the filename given as the last argument to
+@code{target amd-eb} should be the name of the program as it appears to DOS.
+In our example this is simply @code{MYFOO}, but in general it can include
+a DOS path, and depending on your transfer mechanism may not resemble
+the name on the Unix side.
+
+At this point, you can set any breakpoints you wish; when you are ready
+to see your program run on the 29K board, use the @value{GDBN} command
+@code{run}.
+
+To stop debugging the remote program, use the @value{GDBN} @code{detach}
+command.
+
+To return control of the PC to its console, use @code{tip} or @code{cu}
+once again, after your @value{GDBN} session has concluded, to attach to
+@code{EBMON}. You can then type the command @code{q} to shut down
+@code{EBMON}, returning control to the DOS command-line interpreter.
+Type @code{CTTY con} to return command input to the main DOS console,
+and type @kbd{~.} to leave @code{tip} or @code{cu}.
+
+@node Remote Log
+@subsubsection Remote log
+@kindex eb.log
+@cindex log file for EB29K
+
+The @code{target amd-eb} command creates a file @file{eb.log} in the
+current working directory, to help debug problems with the connection.
+@file{eb.log} records all the output from @code{EBMON}, including echoes
+of the commands sent to it. Running @samp{tail -f} on this file in
+another window often helps to understand trouble with @code{EBMON}, or
+unexpected events on the PC side of the connection.
+
+@end ifset
+
+@ifset ST2000
+@node ST2000 Remote
+@subsection @value{GDBN} with a Tandem ST2000
+
+To connect your ST2000 to the host system, see the manufacturer's
+manual. Once the ST2000 is physically attached, you can run:
+
+@example
+target st2000 @var{dev} @var{speed}
+@end example
+
+@noindent
+to establish it as your debugging environment. @var{dev} is normally
+the name of a serial device, such as @file{/dev/ttya}, connected to the
+ST2000 via a serial line. You can instead specify @var{dev} as a TCP
+connection (for example, to a serial line attached via a terminal
+concentrator) using the syntax @code{@var{hostname}:@var{portnumber}}.
+
+The @code{load} and @code{attach} commands are @emph{not} defined for
+this target; you must load your program into the ST2000 as you normally
+would for standalone operation. @value{GDBN} reads debugging information
+(such as symbols) from a separate, debugging version of the program
+available on your host computer.
+@c FIXME!! This is terribly vague; what little content is here is
+@c basically hearsay.
+
+@cindex ST2000 auxiliary commands
+These auxiliary @value{GDBN} commands are available to help you with the ST2000
+environment:
+
+@table @code
+@item st2000 @var{command}
+@kindex st2000 @var{cmd}
+@cindex STDBUG commands (ST2000)
+@cindex commands to STDBUG (ST2000)
+Send a @var{command} to the STDBUG monitor. See the manufacturer's
+manual for available commands.
+
+@item connect
+@cindex connect (to STDBUG)
+Connect the controlling terminal to the STDBUG command monitor. When
+you are done interacting with STDBUG, typing either of two character
+sequences gets you back to the @value{GDBN} command prompt:
+@kbd{@key{RET}~.} (Return, followed by tilde and period) or
+@kbd{@key{RET}~@key{C-d}} (Return, followed by tilde and control-D).
+@end table
+@end ifset
+
+@ifset VXWORKS
+@node VxWorks Remote
+@subsection @value{GDBN} and VxWorks
+@cindex VxWorks
+
+@value{GDBN} enables developers to spawn and debug tasks running on networked
+VxWorks targets from a Unix host. Already-running tasks spawned from
+the VxWorks shell can also be debugged. @value{GDBN} uses code that runs on
+both the Unix host and on the VxWorks target. The program
+@code{gdb} is installed and executed on the Unix host. (It may be
+installed with the name @code{vxgdb}, to distinguish it from a
+@value{GDBN} for debugging programs on the host itself.)
+
+@table @code
+@item VxWorks-timeout @var{args}
+@kindex vxworks-timeout
+All VxWorks-based targets now support the option @code{vxworks-timeout}.
+This option is set by the user, and @var{args} represents the number of
+seconds @value{GDBN} waits for responses to rpc's. You might use this if
+your VxWorks target is a slow software simulator or is on the far side
+of a thin network line.
+@end table
+
+The following information on connecting to VxWorks was current when
+this manual was produced; newer releases of VxWorks may use revised
+procedures.
+
+@kindex INCLUDE_RDB
+To use @value{GDBN} with VxWorks, you must rebuild your VxWorks kernel
+to include the remote debugging interface routines in the VxWorks
+library @file{rdb.a}. To do this, define @code{INCLUDE_RDB} in the
+VxWorks configuration file @file{configAll.h} and rebuild your VxWorks
+kernel. The resulting kernel contains @file{rdb.a}, and spawns the
+source debugging task @code{tRdbTask} when VxWorks is booted. For more
+information on configuring and remaking VxWorks, see the manufacturer's
+manual.
+@c VxWorks, see the @cite{VxWorks Programmer's Guide}.
+
+Once you have included @file{rdb.a} in your VxWorks system image and set
+your Unix execution search path to find @value{GDBN}, you are ready to
+run @value{GDBN}. From your Unix host, run @code{gdb} (or @code{vxgdb},
+depending on your installation).
+
+@value{GDBN} comes up showing the prompt:
+
+@example
+(vxgdb)
+@end example
+
+@menu
+* VxWorks Connection:: Connecting to VxWorks
+* VxWorks Download:: VxWorks download
+* VxWorks Attach:: Running tasks
+@end menu
+
+@node VxWorks Connection
+@subsubsection Connecting to VxWorks
+
+The @value{GDBN} command @code{target} lets you connect to a VxWorks target on the
+network. To connect to a target whose host name is ``@code{tt}'', type:
+
+@example
+(vxgdb) target vxworks tt
+@end example
+
+@need 750
+@value{GDBN} displays messages like these:
+
+@smallexample
+Attaching remote machine across net...
+Connected to tt.
+@end smallexample
+
+@need 1000
+@value{GDBN} then attempts to read the symbol tables of any object modules
+loaded into the VxWorks target since it was last booted. @value{GDBN} locates
+these files by searching the directories listed in the command search
+path (@pxref{Environment, ,Your program's environment}); if it fails
+to find an object file, it displays a message such as:
+
+@example
+prog.o: No such file or directory.
+@end example
+
+When this happens, add the appropriate directory to the search path with
+the @value{GDBN} command @code{path}, and execute the @code{target}
+command again.
+
+@node VxWorks Download
+@subsubsection VxWorks download
+
+@cindex download to VxWorks
+If you have connected to the VxWorks target and you want to debug an
+object that has not yet been loaded, you can use the @value{GDBN}
+@code{load} command to download a file from Unix to VxWorks
+incrementally. The object file given as an argument to the @code{load}
+command is actually opened twice: first by the VxWorks target in order
+to download the code, then by @value{GDBN} in order to read the symbol
+table. This can lead to problems if the current working directories on
+the two systems differ. If both systems have NFS mounted the same
+filesystems, you can avoid these problems by using absolute paths.
+Otherwise, it is simplest to set the working directory on both systems
+to the directory in which the object file resides, and then to reference
+the file by its name, without any path. For instance, a program
+@file{prog.o} may reside in @file{@var{vxpath}/vw/demo/rdb} in VxWorks
+and in @file{@var{hostpath}/vw/demo/rdb} on the host. To load this
+program, type this on VxWorks:
+
+@example
+-> cd "@var{vxpath}/vw/demo/rdb"
+@end example
+v
+Then, in @value{GDBN}, type:
+
+@example
+(vxgdb) cd @var{hostpath}/vw/demo/rdb
+(vxgdb) load prog.o
+@end example
+
+@value{GDBN} displays a response similar to this:
+
+@smallexample
+Reading symbol data from wherever/vw/demo/rdb/prog.o... done.
+@end smallexample
+
+You can also use the @code{load} command to reload an object module
+after editing and recompiling the corresponding source file. Note that
+this makes @value{GDBN} delete all currently-defined breakpoints,
+auto-displays, and convenience variables, and to clear the value
+history. (This is necessary in order to preserve the integrity of
+debugger data structures that reference the target system's symbol
+table.)
+
+@node VxWorks Attach
+@subsubsection Running tasks
+
+@cindex running VxWorks tasks
+You can also attach to an existing task using the @code{attach} command as
+follows:
+
+@example
+(vxgdb) attach @var{task}
+@end example
+
+@noindent
+where @var{task} is the VxWorks hexadecimal task ID. The task can be running
+or suspended when you attach to it. Running tasks are suspended at
+the time of attachment.
+@end ifset
+
+@ifset H8
+@node Hitachi Remote
+@subsection @value{GDBN} and Hitachi microprocessors
+@value{GDBN} needs to know these things to talk to your
+Hitachi SH, H8/300, or H8/500:
+
+@enumerate
+@item
+that you want to use @samp{target hms}, the remote debugging interface
+for Hitachi microprocessors, or @samp{target e7000}, the in-circuit
+emulator for the Hitachi SH and the Hitachi 300H. (@samp{target hms} is
+the default when GDB is configured specifically for the Hitachi SH,
+H8/300, or H8/500.)
+
+@item
+what serial device connects your host to your Hitachi board (the first
+serial device available on your host is the default).
+
+@ifclear H8EXCLUSIVE
+@c this is only for Unix hosts, not of interest to Hitachi
+@item
+what speed to use over the serial device.
+@end ifclear
+@end enumerate
+
+@menu
+* Hitachi Boards:: Connecting to Hitachi boards.
+* Hitachi ICE:: Using the E7000 In-Circuit Emulator.
+* Hitachi Special:: Special @value{GDBN} commands for Hitachi micros.
+@end menu
+
+@node Hitachi Boards
+@subsubsection Connecting to Hitachi boards
+
+@ifclear H8EXCLUSIVE
+@c only for Unix hosts
+@kindex device
+@cindex serial device, Hitachi micros
+Use the special @code{@value{GDBP}} command @samp{device @var{port}} if you
+need to explicitly set the serial device. The default @var{port} is the
+first available port on your host. This is only necessary on Unix
+hosts, where it is typically something like @file{/dev/ttya}.
+
+@kindex speed
+@cindex serial line speed, Hitachi micros
+@code{@value{GDBP}} has another special command to set the communications
+speed: @samp{speed @var{bps}}. This command also is only used from Unix
+hosts; on DOS hosts, set the line speed as usual from outside GDB with
+the DOS @kbd{mode} command (for instance, @w{@samp{mode
+com2:9600,n,8,1,p}} for a 9600 bps connection).
+
+The @samp{device} and @samp{speed} commands are available only when you
+use a Unix host to debug your Hitachi microprocessor programs. If you
+use a DOS host,
+@end ifclear
+@value{GDBN} depends on an auxiliary terminate-and-stay-resident program
+called @code{asynctsr} to communicate with the development board
+through a PC serial port. You must also use the DOS @code{mode} command
+to set up the serial port on the DOS side.
+
+@ifset DOSHOST
+The following sample session illustrates the steps needed to start a
+program under @value{GDBN} control on an H8/300. The example uses a
+sample H8/300 program called @file{t.x}. The procedure is the same for
+the Hitachi SH and the H8/500.
+
+First hook up your development board. In this example, we use a
+board attached to serial port @code{COM2}; if you use a different serial
+port, substitute its name in the argument of the @code{mode} command.
+When you call @code{asynctsr}, the auxiliary comms program used by the
+degugger, you give it just the numeric part of the serial port's name;
+for example, @samp{asyncstr 2} below runs @code{asyncstr} on
+@code{COM2}.
+
+@example
+C:\H8300\TEST> asynctsr 2
+C:\H8300\TEST> mode com2:9600,n,8,1,p
+
+Resident portion of MODE loaded
+
+COM2: 9600, n, 8, 1, p
+
+@end example
+
+@quotation
+@emph{Warning:} We have noticed a bug in PC-NFS that conflicts with
+@code{asynctsr}. If you also run PC-NFS on your DOS host, you may need to
+disable it, or even boot without it, to use @code{asynctsr} to control
+your development board.
+@end quotation
+
+@kindex target hms
+Now that serial communications are set up, and the development board is
+connected, you can start up @value{GDBN}. Call @code{@value{GDBP}} with
+the name of your program as the argument. @code{@value{GDBP}} prompts
+you, as usual, with the prompt @samp{(@value{GDBP})}. Use two special
+commands to begin your debugging session: @samp{target hms} to specify
+cross-debugging to the Hitachi board, and the @code{load} command to
+download your program to the board. @code{load} displays the names of
+the program's sections, and a @samp{*} for each 2K of data downloaded.
+(If you want to refresh @value{GDBN} data on symbols or on the
+executable file without downloading, use the @value{GDBN} commands
+@code{file} or @code{symbol-file}. These commands, and @code{load}
+itself, are described in @ref{Files,,Commands to specify files}.)
+
+@smallexample
+(eg-C:\H8300\TEST) @value{GDBP} t.x
+GDB is free software and you are welcome to distribute copies
+ of it under certain conditions; type "show copying" to see
+ the conditions.
+There is absolutely no warranty for GDB; type "show warranty"
+for details.
+GDB @value{GDBVN}, Copyright 1992 Free Software Foundation, Inc...
+(gdb) target hms
+Connected to remote H8/300 HMS system.
+(gdb) load t.x
+.text : 0x8000 .. 0xabde ***********
+.data : 0xabde .. 0xad30 *
+.stack : 0xf000 .. 0xf014 *
+@end smallexample
+
+At this point, you're ready to run or debug your program. From here on,
+you can use all the usual @value{GDBN} commands. The @code{break} command
+sets breakpoints; the @code{run} command starts your program;
+@code{print} or @code{x} display data; the @code{continue} command
+resumes execution after stopping at a breakpoint. You can use the
+@code{help} command at any time to find out more about @value{GDBN} commands.
+
+Remember, however, that @emph{operating system} facilities aren't
+available on your development board; for example, if your program hangs,
+you can't send an interrupt---but you can press the @sc{reset} switch!
+
+Use the @sc{reset} button on the development board
+@itemize @bullet
+@item
+to interrupt your program (don't use @kbd{ctl-C} on the DOS host---it has
+no way to pass an interrupt signal to the development board); and
+
+@item
+to return to the @value{GDBN} command prompt after your program finishes
+normally. The communications protocol provides no other way for @value{GDBN}
+to detect program completion.
+@end itemize
+
+In either case, @value{GDBN} sees the effect of a @sc{reset} on the
+development board as a ``normal exit'' of your program.
+@end ifset
+
+@node Hitachi ICE
+@subsubsection Using the E7000 in-circuit emulator
+
+@kindex target e7000
+You can use the E7000 in-circuit emulator to develop code for either the
+Hitachi SH or the H8/300H. Use one of these forms of the @samp{target
+e7000} command to connect @value{GDBN} to your E7000:
+
+@table @code
+@item target e7000 @var{port} @var{speed}
+Use this form if your E7000 is connected to a serial port. The
+@var{port} argument identifies what serial port to use (for example,
+@samp{com2}). The third argument is the line speed in bits per second
+(for example, @samp{9600}).
+
+@item target e7000 @var{hostname}
+If your E7000 is installed as a host on a TCP/IP network, you can just
+specify its hostname; @value{GDBN} uses @code{telnet} to connect.
+@end table
+
+@node Hitachi Special
+@subsubsection Special @value{GDBN} commands for Hitachi micros
+
+Some @value{GDBN} commands are available only on the H8/300 or the
+H8/500 configurations:
+
+@table @code
+@kindex set machine
+@kindex show machine
+@item set machine h8300
+@itemx set machine h8300h
+Condition @value{GDBN} for one of the two variants of the H8/300
+architecture with @samp{set machine}. You can use @samp{show machine}
+to check which variant is currently in effect.
+
+@kindex set memory @var{mod}
+@cindex memory models, H8/500
+@item set memory @var{mod}
+@itemx show memory
+Specify which H8/500 memory model (@var{mod}) you are using with
+@samp{set memory}; check which memory model is in effect with @samp{show
+memory}. The accepted values for @var{mod} are @code{small},
+@code{big}, @code{medium}, and @code{compact}.
+@end table
+
+@end ifset
+
+@ifset MIPS
+@node MIPS Remote
+@subsection @value{GDBN} and remote MIPS boards
+
+@cindex MIPS boards
+@value{GDBN} can use the MIPS remote debugging protocol to talk to a
+MIPS board attached to a serial line. This is available when
+you configure @value{GDBN} with @samp{--target=mips-idt-ecoff}.
+
+@need 1000
+Use these @value{GDBN} commands to specify the connection to your target board:
+
+@table @code
+@item target mips @var{port}
+@kindex target mips @var{port}
+To run a program on the board, start up @code{@value{GDBP}} with the
+name of your program as the argument. To connect to the board, use the
+command @samp{target mips @var{port}}, where @var{port} is the name of
+the serial port connected to the board. If the program has not already
+been downloaded to the board, you may use the @code{load} command to
+download it. You can then use all the usual @value{GDBN} commands.
+
+For example, this sequence connects to the target board through a serial
+port, and loads and runs a program called @var{prog} through the
+debugger:
+
+@example
+host$ @value{GDBP} @var{prog}
+GDB is free software and @dots{}
+(gdb) target mips /dev/ttyb
+(gdb) load @var{prog}
+(gdb) run
+@end example
+
+@item target mips @var{hostname}:@var{portnumber}
+On some @value{GDBN} host configurations, you can specify a TCP
+connection (for instance, to a serial line managed by a terminal
+concentrator) instead of a serial port, using the syntax
+@samp{@var{hostname}:@var{portnumber}}.
+@end table
+
+@noindent
+@value{GDBN} also supports these special commands for MIPS targets:
+
+@table @code
+@item set processor @var{args}
+@itemx show processor
+@kindex set processor @var{args}
+@kindex show processor
+Use the @code{set processor} command to set the type of MIPS
+processor when you want to access processor-type-specific registers.
+For example, @code{set processor @var{r3041}} tells @value{GDBN}
+to use the CPO registers appropriate for the 3041 chip.
+Use the @code{show processor} command to see what MIPS processor @value{GDBN}
+is using. Use the @code{info reg} command to see what registers
+@value{GDBN} is using.
+
+@item set mipsfpu double
+@itemx set mipsfpu single
+@itemx set mipsfpu none
+@itemx show mipsfpu
+@kindex set mipsfpu
+@kindex show mipsfpu
+@cindex MIPS remote floating point
+@cindex floating point, MIPS remote
+If your target board does not support the MIPS floating point
+coprocessor, you should use the command @samp{set mipsfpu none} (if you
+need this, you may wish to put the command in your @value{GDBINIT}
+file). This tells @value{GDBN} how to find the return value of
+functions which return floating point values. It also allows
+@value{GDBN} to avoid saving the floating point registers when calling
+functions on the board. If you are using a floating point coprocessor
+with only single precision floating point support, as on the @sc{r4650}
+processor, use the command @samp{set mipsfpu single}. The default
+double precision floating point coprocessor may be selected using
+@samp{set mipsfpu double}.
+
+In previous versions the only choices were double precision or no
+floating point, so @samp{set mipsfpu on} will select double precision
+and @samp{set mipsfpu off} will select no floating point.
+
+As usual, you can inquire about the @code{mipsfpu} variable with
+@samp{show mipsfpu}.
+
+@item set remotedebug @var{n}
+@itemx show remotedebug
+@kindex set remotedebug
+@kindex show remotedebug
+@cindex @code{remotedebug}, MIPS protocol
+@cindex MIPS @code{remotedebug} protocol
+@c FIXME! For this to be useful, you must know something about the MIPS
+@c FIXME...protocol. Where is it described?
+You can see some debugging information about communications with the board
+by setting the @code{remotedebug} variable. If you set it to @code{1} using
+@samp{set remotedebug 1}, every packet is displayed. If you set it
+to @code{2}, every character is displayed. You can check the current value
+at any time with the command @samp{show remotedebug}.
+
+@item set timeout @var{seconds}
+@itemx set retransmit-timeout @var{seconds}
+@itemx show timeout
+@itemx show retransmit-timeout
+@cindex @code{timeout}, MIPS protocol
+@cindex @code{retransmit-timeout}, MIPS protocol
+@kindex set timeout
+@kindex show timeout
+@kindex set retransmit-timeout
+@kindex show retransmit-timeout
+You can control the timeout used while waiting for a packet, in the MIPS
+remote protocol, with the @code{set timeout @var{seconds}} command. The
+default is 5 seconds. Similarly, you can control the timeout used while
+waiting for an acknowledgement of a packet with the @code{set
+retransmit-timeout @var{seconds}} command. The default is 3 seconds.
+You can inspect both values with @code{show timeout} and @code{show
+retransmit-timeout}. (These commands are @emph{only} available when
+@value{GDBN} is configured for @samp{--target=mips-idt-ecoff}.)
+
+The timeout set by @code{set timeout} does not apply when @value{GDBN}
+is waiting for your program to stop. In that case, @value{GDBN} waits
+forever because it has no way of knowing how long the program is going
+to run before stopping.
+@end table
+@end ifset
+
+@ifset SIMS
+@node Simulator
+@subsection Simulated CPU target
+
+@ifset GENERIC
+@cindex simulator
+@cindex simulator, Z8000
+@cindex Z8000 simulator
+@cindex simulator, H8/300 or H8/500
+@cindex H8/300 or H8/500 simulator
+@cindex simulator, Hitachi SH
+@cindex Hitachi SH simulator
+@cindex CPU simulator
+For some configurations, @value{GDBN} includes a CPU simulator that you
+can use instead of a hardware CPU to debug your programs. Currently,
+a simulator is available when @value{GDBN} is configured to debug Zilog
+Z8000 or Hitachi microprocessor targets.
+@end ifset
+
+@ifclear GENERIC
+@ifset H8
+@cindex simulator, H8/300 or H8/500
+@cindex Hitachi H8/300 or H8/500 simulator
+@cindex simulator, Hitachi SH
+@cindex Hitachi SH simulator
+When configured for debugging Hitachi microprocessor targets,
+@value{GDBN} includes a CPU simulator for the target chip (a Hitachi SH,
+H8/300, or H8/500).
+@end ifset
+
+@ifset Z8K
+@cindex simulator, Z8000
+@cindex Zilog Z8000 simulator
+When configured for debugging Zilog Z8000 targets, @value{GDBN} includes
+a Z8000 simulator.
+@end ifset
+@end ifclear
+
+@ifset Z8K
+For the Z8000 family, @samp{target sim} simulates either the Z8002 (the
+unsegmented variant of the Z8000 architecture) or the Z8001 (the
+segmented variant). The simulator recognizes which architecture is
+appropriate by inspecting the object code.
+@end ifset
+
+@table @code
+@item target sim
+@kindex sim
+@kindex target sim
+Debug programs on a simulated CPU
+@ifset GENERIC
+(which CPU depends on the @value{GDBN} configuration)
+@end ifset
+@end table
+
+@noindent
+After specifying this target, you can debug programs for the simulated
+CPU in the same style as programs for your host computer; use the
+@code{file} command to load a new program image, the @code{run} command
+to run your program, and so on.
+
+As well as making available all the usual machine registers (see
+@code{info reg}), this debugging target provides three additional items
+of information as specially named registers:
+
+@table @code
+@item cycles
+Counts clock-ticks in the simulator.
+
+@item insts
+Counts instructions run in the simulator.
+
+@item time
+Execution time in 60ths of a second.
+@end table
+
+You can refer to these values in @value{GDBN} expressions with the usual
+conventions; for example, @w{@samp{b fputc if $cycles>5000}} sets a
+conditional breakpoint that suspends only after at least 5000
+simulated clock ticks.
+@end ifset
diff --git a/contrib/gdb/gdb/doc/stabs.texinfo b/contrib/gdb/gdb/doc/stabs.texinfo
new file mode 100644
index 0000000..b0d26c3
--- /dev/null
+++ b/contrib/gdb/gdb/doc/stabs.texinfo
@@ -0,0 +1,4004 @@
+\input texinfo
+@setfilename stabs.info
+
+@c @finalout
+
+@ifinfo
+@format
+START-INFO-DIR-ENTRY
+* Stabs: (stabs). The "stabs" debugging information format.
+END-INFO-DIR-ENTRY
+@end format
+@end ifinfo
+
+@ifinfo
+This document describes the stabs debugging symbol tables.
+
+Copyright 1992, 1993 Free Software Foundation, Inc.
+Contributed by Cygnus Support. Written by Julia Menapace, Jim Kingdon,
+and David MacKenzie.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@ignore
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+
+@end ignore
+Permission is granted to copy or distribute modified versions of this
+manual under the terms of the GPL (for which purpose this text may be
+regarded as a program in the language TeX).
+@end ifinfo
+
+@setchapternewpage odd
+@settitle STABS
+@titlepage
+@title The ``stabs'' debug format
+@author Julia Menapace, Jim Kingdon, David MacKenzie
+@author Cygnus Support
+@page
+@tex
+\def\$#1${{#1}} % Kluge: collect RCS revision info without $...$
+\xdef\manvers{\$Revision: 2.125 $} % For use in headers, footers too
+{\parskip=0pt
+\hfill Cygnus Support\par
+\hfill \manvers\par
+\hfill \TeX{}info \texinfoversion\par
+}
+@end tex
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1992, 1993 Free Software Foundation, Inc.
+Contributed by Cygnus Support.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+@end titlepage
+
+@ifinfo
+@node Top
+@top The "stabs" representation of debugging information
+
+This document describes the stabs debugging format.
+
+@menu
+* Overview:: Overview of stabs
+* Program Structure:: Encoding of the structure of the program
+* Constants:: Constants
+* Variables::
+* Types:: Type definitions
+* Symbol Tables:: Symbol information in symbol tables
+* Cplusplus:: Stabs specific to C++
+* Stab Types:: Symbol types in a.out files
+* Symbol Descriptors:: Table of symbol descriptors
+* Type Descriptors:: Table of type descriptors
+* Expanded Reference:: Reference information by stab type
+* Questions:: Questions and anomolies
+* Sun Differences:: Differences between GNU stabs and Sun
+ native stabs
+* Stab Sections:: In some object file formats, stabs are
+ in sections.
+* Symbol Types Index:: Index of symbolic stab symbol type names.
+@end menu
+@end ifinfo
+
+
+@node Overview
+@chapter Overview of Stabs
+
+@dfn{Stabs} refers to a format for information that describes a program
+to a debugger. This format was apparently invented by
+Peter Kessler at
+the University of California at Berkeley, for the @code{pdx} Pascal
+debugger; the format has spread widely since then.
+
+This document is one of the few published sources of documentation on
+stabs. It is believed to be comprehensive for stabs used by C. The
+lists of symbol descriptors (@pxref{Symbol Descriptors}) and type
+descriptors (@pxref{Type Descriptors}) are believed to be completely
+comprehensive. Stabs for COBOL-specific features and for variant
+records (used by Pascal and Modula-2) are poorly documented here.
+
+@c FIXME: Need to document all OS9000 stuff in GDB; see all references
+@c to os9k_stabs in stabsread.c.
+
+Other sources of information on stabs are @cite{Dbx and Dbxtool
+Interfaces}, 2nd edition, by Sun, 1988, and @cite{AIX Version 3.2 Files
+Reference}, Fourth Edition, September 1992, "dbx Stabstring Grammar" in
+the a.out section, page 2-31. This document is believed to incorporate
+the information from those two sources except where it explicitly directs
+you to them for more information.
+
+@menu
+* Flow:: Overview of debugging information flow
+* Stabs Format:: Overview of stab format
+* String Field:: The string field
+* C Example:: A simple example in C source
+* Assembly Code:: The simple example at the assembly level
+@end menu
+
+@node Flow
+@section Overview of Debugging Information Flow
+
+The GNU C compiler compiles C source in a @file{.c} file into assembly
+language in a @file{.s} file, which the assembler translates into
+a @file{.o} file, which the linker combines with other @file{.o} files and
+libraries to produce an executable file.
+
+With the @samp{-g} option, GCC puts in the @file{.s} file additional
+debugging information, which is slightly transformed by the assembler
+and linker, and carried through into the final executable. This
+debugging information describes features of the source file like line
+numbers, the types and scopes of variables, and function names,
+parameters, and scopes.
+
+For some object file formats, the debugging information is encapsulated
+in assembler directives known collectively as @dfn{stab} (symbol table)
+directives, which are interspersed with the generated code. Stabs are
+the native format for debugging information in the a.out and XCOFF
+object file formats. The GNU tools can also emit stabs in the COFF and
+ECOFF object file formats.
+
+The assembler adds the information from stabs to the symbol information
+it places by default in the symbol table and the string table of the
+@file{.o} file it is building. The linker consolidates the @file{.o}
+files into one executable file, with one symbol table and one string
+table. Debuggers use the symbol and string tables in the executable as
+a source of debugging information about the program.
+
+@node Stabs Format
+@section Overview of Stab Format
+
+There are three overall formats for stab assembler directives,
+differentiated by the first word of the stab. The name of the directive
+describes which combination of four possible data fields follows. It is
+either @code{.stabs} (string), @code{.stabn} (number), or @code{.stabd}
+(dot). IBM's XCOFF assembler uses @code{.stabx} (and some other
+directives such as @code{.file} and @code{.bi}) instead of
+@code{.stabs}, @code{.stabn} or @code{.stabd}.
+
+The overall format of each class of stab is:
+
+@example
+.stabs "@var{string}",@var{type},@var{other},@var{desc},@var{value}
+.stabn @var{type},@var{other},@var{desc},@var{value}
+.stabd @var{type},@var{other},@var{desc}
+.stabx "@var{string}",@var{value},@var{type},@var{sdb-type}
+@end example
+
+@c what is the correct term for "current file location"? My AIX
+@c assembler manual calls it "the value of the current location counter".
+For @code{.stabn} and @code{.stabd}, there is no @var{string} (the
+@code{n_strx} field is zero; see @ref{Symbol Tables}). For
+@code{.stabd}, the @var{value} field is implicit and has the value of
+the current file location. For @code{.stabx}, the @var{sdb-type} field
+is unused for stabs and can always be set to zero. The @var{other}
+field is almost always unused and can be set to zero.
+
+The number in the @var{type} field gives some basic information about
+which type of stab this is (or whether it @emph{is} a stab, as opposed
+to an ordinary symbol). Each valid type number defines a different stab
+type; further, the stab type defines the exact interpretation of, and
+possible values for, any remaining @var{string}, @var{desc}, or
+@var{value} fields present in the stab. @xref{Stab Types}, for a list
+in numeric order of the valid @var{type} field values for stab directives.
+
+@node String Field
+@section The String Field
+
+For most stabs the string field holds the meat of the
+debugging information. The flexible nature of this field
+is what makes stabs extensible. For some stab types the string field
+contains only a name. For other stab types the contents can be a great
+deal more complex.
+
+The overall format of the string field for most stab types is:
+
+@example
+"@var{name}:@var{symbol-descriptor} @var{type-information}"
+@end example
+
+@var{name} is the name of the symbol represented by the stab; it can
+contain a pair of colons (@pxref{Nested Symbols}). @var{name} can be
+omitted, which means the stab represents an unnamed object. For
+example, @samp{:t10=*2} defines type 10 as a pointer to type 2, but does
+not give the type a name. Omitting the @var{name} field is supported by
+AIX dbx and GDB after about version 4.8, but not other debuggers. GCC
+sometimes uses a single space as the name instead of omitting the name
+altogether; apparently that is supported by most debuggers.
+
+The @var{symbol-descriptor} following the @samp{:} is an alphabetic
+character that tells more specifically what kind of symbol the stab
+represents. If the @var{symbol-descriptor} is omitted, but type
+information follows, then the stab represents a local variable. For a
+list of symbol descriptors, see @ref{Symbol Descriptors}. The @samp{c}
+symbol descriptor is an exception in that it is not followed by type
+information. @xref{Constants}.
+
+@var{type-information} is either a @var{type-number}, or
+@samp{@var{type-number}=}. A @var{type-number} alone is a type
+reference, referring directly to a type that has already been defined.
+
+The @samp{@var{type-number}=} form is a type definition, where the
+number represents a new type which is about to be defined. The type
+definition may refer to other types by number, and those type numbers
+may be followed by @samp{=} and nested definitions. Also, the Lucid
+compiler will repeat @samp{@var{type-number}=} more than once if it
+wants to define several type numbers at once.
+
+In a type definition, if the character that follows the equals sign is
+non-numeric then it is a @var{type-descriptor}, and tells what kind of
+type is about to be defined. Any other values following the
+@var{type-descriptor} vary, depending on the @var{type-descriptor}.
+@xref{Type Descriptors}, for a list of @var{type-descriptor} values. If
+a number follows the @samp{=} then the number is a @var{type-reference}.
+For a full description of types, @ref{Types}.
+
+There is an AIX extension for type attributes. Following the @samp{=}
+are any number of type attributes. Each one starts with @samp{@@} and
+ends with @samp{;}. Debuggers, including AIX's dbx and GDB 4.10, skip
+any type attributes they do not recognize. GDB 4.9 and other versions
+of dbx may not do this. Because of a conflict with C++
+(@pxref{Cplusplus}), new attributes should not be defined which begin
+with a digit, @samp{(}, or @samp{-}; GDB may be unable to distinguish
+those from the C++ type descriptor @samp{@@}. The attributes are:
+
+@table @code
+@item a@var{boundary}
+@var{boundary} is an integer specifying the alignment. I assume it
+applies to all variables of this type.
+
+@item p@var{integer}
+Pointer class (for checking). Not sure what this means, or how
+@var{integer} is interpreted.
+
+@item P
+Indicate this is a packed type, meaning that structure fields or array
+elements are placed more closely in memory, to save memory at the
+expense of speed.
+
+@item s@var{size}
+Size in bits of a variable of this type. This is fully supported by GDB
+4.11 and later.
+
+@item S
+Indicate that this type is a string instead of an array of characters,
+or a bitstring instead of a set. It doesn't change the layout of the
+data being represented, but does enable the debugger to know which type
+it is.
+@end table
+
+All of this can make the string field quite long. All versions of GDB,
+and some versions of dbx, can handle arbitrarily long strings. But many
+versions of dbx (or assemblers or linkers, I'm not sure which)
+cretinously limit the strings to about 80 characters, so compilers which
+must work with such systems need to split the @code{.stabs} directive
+into several @code{.stabs} directives. Each stab duplicates every field
+except the string field. The string field of every stab except the last
+is marked as continued with a backslash at the end (in the assembly code
+this may be written as a double backslash, depending on the assembler).
+Removing the backslashes and concatenating the string fields of each
+stab produces the original, long string. Just to be incompatible (or so
+they don't have to worry about what the assembler does with
+backslashes), AIX can use @samp{?} instead of backslash.
+
+@node C Example
+@section A Simple Example in C Source
+
+To get the flavor of how stabs describe source information for a C
+program, let's look at the simple program:
+
+@example
+main()
+@{
+ printf("Hello world");
+@}
+@end example
+
+When compiled with @samp{-g}, the program above yields the following
+@file{.s} file. Line numbers have been added to make it easier to refer
+to parts of the @file{.s} file in the description of the stabs that
+follows.
+
+@node Assembly Code
+@section The Simple Example at the Assembly Level
+
+This simple ``hello world'' example demonstrates several of the stab
+types used to describe C language source files.
+
+@example
+1 gcc2_compiled.:
+2 .stabs "/cygint/s1/users/jcm/play/",100,0,0,Ltext0
+3 .stabs "hello.c",100,0,0,Ltext0
+4 .text
+5 Ltext0:
+6 .stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0
+7 .stabs "char:t2=r2;0;127;",128,0,0,0
+8 .stabs "long int:t3=r1;-2147483648;2147483647;",128,0,0,0
+9 .stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
+10 .stabs "long unsigned int:t5=r1;0;-1;",128,0,0,0
+11 .stabs "short int:t6=r1;-32768;32767;",128,0,0,0
+12 .stabs "long long int:t7=r1;0;-1;",128,0,0,0
+13 .stabs "short unsigned int:t8=r1;0;65535;",128,0,0,0
+14 .stabs "long long unsigned int:t9=r1;0;-1;",128,0,0,0
+15 .stabs "signed char:t10=r1;-128;127;",128,0,0,0
+16 .stabs "unsigned char:t11=r1;0;255;",128,0,0,0
+17 .stabs "float:t12=r1;4;0;",128,0,0,0
+18 .stabs "double:t13=r1;8;0;",128,0,0,0
+19 .stabs "long double:t14=r1;8;0;",128,0,0,0
+20 .stabs "void:t15=15",128,0,0,0
+21 .align 4
+22 LC0:
+23 .ascii "Hello, world!\12\0"
+24 .align 4
+25 .global _main
+26 .proc 1
+27 _main:
+28 .stabn 68,0,4,LM1
+29 LM1:
+30 !#PROLOGUE# 0
+31 save %sp,-136,%sp
+32 !#PROLOGUE# 1
+33 call ___main,0
+34 nop
+35 .stabn 68,0,5,LM2
+36 LM2:
+37 LBB2:
+38 sethi %hi(LC0),%o1
+39 or %o1,%lo(LC0),%o0
+40 call _printf,0
+41 nop
+42 .stabn 68,0,6,LM3
+43 LM3:
+44 LBE2:
+45 .stabn 68,0,6,LM4
+46 LM4:
+47 L1:
+48 ret
+49 restore
+50 .stabs "main:F1",36,0,0,_main
+51 .stabn 192,0,0,LBB2
+52 .stabn 224,0,0,LBE2
+@end example
+
+@node Program Structure
+@chapter Encoding the Structure of the Program
+
+The elements of the program structure that stabs encode include the name
+of the main function, the names of the source and include files, the
+line numbers, procedure names and types, and the beginnings and ends of
+blocks of code.
+
+@menu
+* Main Program:: Indicate what the main program is
+* Source Files:: The path and name of the source file
+* Include Files:: Names of include files
+* Line Numbers::
+* Procedures::
+* Nested Procedures::
+* Block Structure::
+* Alternate Entry Points:: Entering procedures except at the beginning.
+@end menu
+
+@node Main Program
+@section Main Program
+
+@findex N_MAIN
+Most languages allow the main program to have any name. The
+@code{N_MAIN} stab type tells the debugger the name that is used in this
+program. Only the string field is significant; it is the name of
+a function which is the main program. Most C compilers do not use this
+stab (they expect the debugger to assume that the name is @code{main}),
+but some C compilers emit an @code{N_MAIN} stab for the @code{main}
+function. I'm not sure how XCOFF handles this.
+
+@node Source Files
+@section Paths and Names of the Source Files
+
+@findex N_SO
+Before any other stabs occur, there must be a stab specifying the source
+file. This information is contained in a symbol of stab type
+@code{N_SO}; the string field contains the name of the file. The
+value of the symbol is the start address of the portion of the
+text section corresponding to that file.
+
+With the Sun Solaris2 compiler, the desc field contains a
+source-language code.
+@c Do the debuggers use it? What are the codes? -djm
+
+Some compilers (for example, GCC2 and SunOS4 @file{/bin/cc}) also
+include the directory in which the source was compiled, in a second
+@code{N_SO} symbol preceding the one containing the file name. This
+symbol can be distinguished by the fact that it ends in a slash. Code
+from the @code{cfront} C++ compiler can have additional @code{N_SO} symbols for
+nonexistent source files after the @code{N_SO} for the real source file;
+these are believed to contain no useful information.
+
+For example:
+
+@example
+.stabs "/cygint/s1/users/jcm/play/",100,0,0,Ltext0 # @r{100 is N_SO}
+.stabs "hello.c",100,0,0,Ltext0
+ .text
+Ltext0:
+@end example
+
+@findex C_FILE
+Instead of @code{N_SO} symbols, XCOFF uses a @code{.file} assembler
+directive which assembles to a @code{C_FILE} symbol; explaining this in
+detail is outside the scope of this document.
+
+@c FIXME: Exactly when should the empty N_SO be used? Why?
+If it is useful to indicate the end of a source file, this is done with
+an @code{N_SO} symbol with an empty string for the name. The value is
+the address of the end of the text section for the file. For some
+systems, there is no indication of the end of a source file, and you
+just need to figure it ended when you see an @code{N_SO} for a different
+source file, or a symbol ending in @code{.o} (which at least some
+linkers insert to mark the start of a new @code{.o} file).
+
+@node Include Files
+@section Names of Include Files
+
+There are several schemes for dealing with include files: the
+traditional @code{N_SOL} approach, Sun's @code{N_BINCL} approach, and the
+XCOFF @code{C_BINCL} approach (which despite the similar name has little in
+common with @code{N_BINCL}).
+
+@findex N_SOL
+An @code{N_SOL} symbol specifies which include file subsequent symbols
+refer to. The string field is the name of the file and the value is the
+text address corresponding to the end of the previous include file and
+the start of this one. To specify the main source file again, use an
+@code{N_SOL} symbol with the name of the main source file.
+
+@findex N_BINCL
+@findex N_EINCL
+@findex N_EXCL
+The @code{N_BINCL} approach works as follows. An @code{N_BINCL} symbol
+specifies the start of an include file. In an object file, only the
+string is significant; the Sun linker puts data into some of the other
+fields. The end of the include file is marked by an @code{N_EINCL}
+symbol (which has no string field). In an object file, there is no
+significant data in the @code{N_EINCL} symbol. @code{N_BINCL} and
+@code{N_EINCL} can be nested.
+
+If the linker detects that two source files have identical stabs between
+an @code{N_BINCL} and @code{N_EINCL} pair (as will generally be the case
+for a header file), then it only puts out the stabs once. Each
+additional occurance is replaced by an @code{N_EXCL} symbol. I believe
+the Sun (SunOS4, not sure about Solaris) linker is the only one which
+supports this feature.
+
+The SunOS4 linker sets the value of a @code{N_BINCL} symbol to the total
+of all the characters in the stabs strings included in the header file,
+omitting the file number. The value of an @code{N_EXCL} symbol is the
+same as the value of the @code{N_BINCL} symbol it replaces. I do not
+know if this information is used by anything. The @code{N_EINCL} value,
+and the values of the other and description fields for all three, appear
+to always be zero.
+
+@findex C_BINCL
+@findex C_EINCL
+For the start of an include file in XCOFF, use the @file{.bi} assembler
+directive, which generates a @code{C_BINCL} symbol. A @file{.ei}
+directive, which generates a @code{C_EINCL} symbol, denotes the end of
+the include file. Both directives are followed by the name of the
+source file in quotes, which becomes the string for the symbol.
+The value of each symbol, produced automatically by the assembler
+and linker, is the offset into the executable of the beginning
+(inclusive, as you'd expect) or end (inclusive, as you would not expect)
+of the portion of the COFF line table that corresponds to this include
+file. @code{C_BINCL} and @code{C_EINCL} do not nest.
+
+@node Line Numbers
+@section Line Numbers
+
+@findex N_SLINE
+An @code{N_SLINE} symbol represents the start of a source line. The
+desc field contains the line number and the value contains the code
+address for the start of that source line. On most machines the address
+is absolute; for stabs in sections (@pxref{Stab Sections}), it is
+relative to the function in which the @code{N_SLINE} symbol occurs.
+
+@findex N_DSLINE
+@findex N_BSLINE
+GNU documents @code{N_DSLINE} and @code{N_BSLINE} symbols for line
+numbers in the data or bss segments, respectively. They are identical
+to @code{N_SLINE} but are relocated differently by the linker. They
+were intended to be used to describe the source location of a variable
+declaration, but I believe that GCC2 actually puts the line number in
+the desc field of the stab for the variable itself. GDB has been
+ignoring these symbols (unless they contain a string field) since
+at least GDB 3.5.
+
+For single source lines that generate discontiguous code, such as flow
+of control statements, there may be more than one line number entry for
+the same source line. In this case there is a line number entry at the
+start of each code range, each with the same line number.
+
+XCOFF does not use stabs for line numbers. Instead, it uses COFF line
+numbers (which are outside the scope of this document). Standard COFF
+line numbers cannot deal with include files, but in XCOFF this is fixed
+with the @code{C_BINCL} method of marking include files (@pxref{Include
+Files}).
+
+@node Procedures
+@section Procedures
+
+@findex N_FUN, for functions
+@findex N_FNAME
+@findex N_STSYM, for functions (Sun acc)
+@findex N_GSYM, for functions (Sun acc)
+All of the following stabs normally use the @code{N_FUN} symbol type.
+However, Sun's @code{acc} compiler on SunOS4 uses @code{N_GSYM} and
+@code{N_STSYM}, which means that the value of the stab for the function
+is useless and the debugger must get the address of the function from
+the non-stab symbols instead. On systems where non-stab symbols have
+leading underscores, the stabs will lack underscores and the debugger
+needs to know about the leading underscore to match up the stab and the
+non-stab symbol. BSD Fortran is said to use @code{N_FNAME} with the
+same restriction; the value of the symbol is not useful (I'm not sure it
+really does use this, because GDB doesn't handle this and no one has
+complained).
+
+@findex C_FUN
+A function is represented by an @samp{F} symbol descriptor for a global
+(extern) function, and @samp{f} for a static (local) function. For
+a.out, the value of the symbol is the address of the start of the
+function; it is already relocated. For stabs in ELF, the SunPRO
+compiler version 2.0.1 and GCC put out an address which gets relocated
+by the linker. In a future release SunPRO is planning to put out zero,
+in which case the address can be found from the ELF (non-stab) symbol.
+Because looking things up in the ELF symbols would probably be slow, I'm
+not sure how to find which symbol of that name is the right one, and
+this doesn't provide any way to deal with nested functions, it would
+probably be better to make the value of the stab an address relative to
+the start of the file, or just absolute. See @ref{ELF Linker
+Relocation} for more information on linker relocation of stabs in ELF
+files. For XCOFF, the stab uses the @code{C_FUN} storage class and the
+value of the stab is meaningless; the address of the function can be
+found from the csect symbol (XTY_LD/XMC_PR).
+
+The type information of the stab represents the return type of the
+function; thus @samp{foo:f5} means that foo is a function returning type
+5. There is no need to try to get the line number of the start of the
+function from the stab for the function; it is in the next
+@code{N_SLINE} symbol.
+
+@c FIXME: verify whether the "I suspect" below is true or not.
+Some compilers (such as Sun's Solaris compiler) support an extension for
+specifying the types of the arguments. I suspect this extension is not
+used for old (non-prototyped) function definitions in C. If the
+extension is in use, the type information of the stab for the function
+is followed by type information for each argument, with each argument
+preceded by @samp{;}. An argument type of 0 means that additional
+arguments are being passed, whose types and number may vary (@samp{...}
+in ANSI C). GDB has tolerated this extension (parsed the syntax, if not
+necessarily used the information) since at least version 4.8; I don't
+know whether all versions of dbx tolerate it. The argument types given
+here are not redundant with the symbols for the formal parameters
+(@pxref{Parameters}); they are the types of the arguments as they are
+passed, before any conversions might take place. For example, if a C
+function which is declared without a prototype takes a @code{float}
+argument, the value is passed as a @code{double} but then converted to a
+@code{float}. Debuggers need to use the types given in the arguments
+when printing values, but when calling the function they need to use the
+types given in the symbol defining the function.
+
+If the return type and types of arguments of a function which is defined
+in another source file are specified (i.e., a function prototype in ANSI
+C), traditionally compilers emit no stab; the only way for the debugger
+to find the information is if the source file where the function is
+defined was also compiled with debugging symbols. As an extension the
+Solaris compiler uses symbol descriptor @samp{P} followed by the return
+type of the function, followed by the arguments, each preceded by
+@samp{;}, as in a stab with symbol descriptor @samp{f} or @samp{F}.
+This use of symbol descriptor @samp{P} can be distinguished from its use
+for register parameters (@pxref{Register Parameters}) by the fact that it has
+symbol type @code{N_FUN}.
+
+The AIX documentation also defines symbol descriptor @samp{J} as an
+internal function. I assume this means a function nested within another
+function. It also says symbol descriptor @samp{m} is a module in
+Modula-2 or extended Pascal.
+
+Procedures (functions which do not return values) are represented as
+functions returning the @code{void} type in C. I don't see why this couldn't
+be used for all languages (inventing a @code{void} type for this purpose if
+necessary), but the AIX documentation defines @samp{I}, @samp{P}, and
+@samp{Q} for internal, global, and static procedures, respectively.
+These symbol descriptors are unusual in that they are not followed by
+type information.
+
+The following example shows a stab for a function @code{main} which
+returns type number @code{1}. The @code{_main} specified for the value
+is a reference to an assembler label which is used to fill in the start
+address of the function.
+
+@example
+.stabs "main:F1",36,0,0,_main # @r{36 is N_FUN}
+@end example
+
+The stab representing a procedure is located immediately following the
+code of the procedure. This stab is in turn directly followed by a
+group of other stabs describing elements of the procedure. These other
+stabs describe the procedure's parameters, its block local variables, and
+its block structure.
+
+@node Nested Procedures
+@section Nested Procedures
+
+For any of the symbol descriptors representing procedures, after the
+symbol descriptor and the type information is optionally a scope
+specifier. This consists of a comma, the name of the procedure, another
+comma, and the name of the enclosing procedure. The first name is local
+to the scope specified, and seems to be redundant with the name of the
+symbol (before the @samp{:}). This feature is used by GCC, and
+presumably Pascal, Modula-2, etc., compilers, for nested functions.
+
+If procedures are nested more than one level deep, only the immediately
+containing scope is specified. For example, this code:
+
+@example
+int
+foo (int x)
+@{
+ int bar (int y)
+ @{
+ int baz (int z)
+ @{
+ return x + y + z;
+ @}
+ return baz (x + 2 * y);
+ @}
+ return x + bar (3 * x);
+@}
+@end example
+
+@noindent
+produces the stabs:
+
+@example
+.stabs "baz:f1,baz,bar",36,0,0,_baz.15 # @r{36 is N_FUN}
+.stabs "bar:f1,bar,foo",36,0,0,_bar.12
+.stabs "foo:F1",36,0,0,_foo
+@end example
+
+@node Block Structure
+@section Block Structure
+
+@findex N_LBRAC
+@findex N_RBRAC
+@c For GCC 2.5.8 or so stabs-in-coff, these are absolute instead of
+@c function relative (as documented below). But GDB has never been able
+@c to deal with that (it had wanted them to be relative to the file, but
+@c I just fixed that (between GDB 4.12 and 4.13)), so it is function
+@c relative just like ELF and SOM and the below documentation.
+The program's block structure is represented by the @code{N_LBRAC} (left
+brace) and the @code{N_RBRAC} (right brace) stab types. The variables
+defined inside a block precede the @code{N_LBRAC} symbol for most
+compilers, including GCC. Other compilers, such as the Convex, Acorn
+RISC machine, and Sun @code{acc} compilers, put the variables after the
+@code{N_LBRAC} symbol. The values of the @code{N_LBRAC} and
+@code{N_RBRAC} symbols are the start and end addresses of the code of
+the block, respectively. For most machines, they are relative to the
+starting address of this source file. For the Gould NP1, they are
+absolute. For stabs in sections (@pxref{Stab Sections}), they are
+relative to the function in which they occur.
+
+The @code{N_LBRAC} and @code{N_RBRAC} stabs that describe the block
+scope of a procedure are located after the @code{N_FUN} stab that
+represents the procedure itself.
+
+Sun documents the desc field of @code{N_LBRAC} and
+@code{N_RBRAC} symbols as containing the nesting level of the block.
+However, dbx seems to not care, and GCC always sets desc to
+zero.
+
+@findex .bb
+@findex .be
+@findex C_BLOCK
+For XCOFF, block scope is indicated with @code{C_BLOCK} symbols. If the
+name of the symbol is @samp{.bb}, then it is the beginning of the block;
+if the name of the symbol is @samp{.be}; it is the end of the block.
+
+@node Alternate Entry Points
+@section Alternate Entry Points
+
+@findex N_ENTRY
+@findex C_ENTRY
+Some languages, like Fortran, have the ability to enter procedures at
+some place other than the beginning. One can declare an alternate entry
+point. The @code{N_ENTRY} stab is for this; however, the Sun FORTRAN
+compiler doesn't use it. According to AIX documentation, only the name
+of a @code{C_ENTRY} stab is significant; the address of the alternate
+entry point comes from the corresponding external symbol. A previous
+revision of this document said that the value of an @code{N_ENTRY} stab
+was the address of the alternate entry point, but I don't know the
+source for that information.
+
+@node Constants
+@chapter Constants
+
+The @samp{c} symbol descriptor indicates that this stab represents a
+constant. This symbol descriptor is an exception to the general rule
+that symbol descriptors are followed by type information. Instead, it
+is followed by @samp{=} and one of the following:
+
+@table @code
+@item b @var{value}
+Boolean constant. @var{value} is a numeric value; I assume it is 0 for
+false or 1 for true.
+
+@item c @var{value}
+Character constant. @var{value} is the numeric value of the constant.
+
+@item e @var{type-information} , @var{value}
+Constant whose value can be represented as integral.
+@var{type-information} is the type of the constant, as it would appear
+after a symbol descriptor (@pxref{String Field}). @var{value} is the
+numeric value of the constant. GDB 4.9 does not actually get the right
+value if @var{value} does not fit in a host @code{int}, but it does not
+do anything violent, and future debuggers could be extended to accept
+integers of any size (whether unsigned or not). This constant type is
+usually documented as being only for enumeration constants, but GDB has
+never imposed that restriction; I don't know about other debuggers.
+
+@item i @var{value}
+Integer constant. @var{value} is the numeric value. The type is some
+sort of generic integer type (for GDB, a host @code{int}); to specify
+the type explicitly, use @samp{e} instead.
+
+@item r @var{value}
+Real constant. @var{value} is the real value, which can be @samp{INF}
+(optionally preceded by a sign) for infinity, @samp{QNAN} for a quiet
+NaN (not-a-number), or @samp{SNAN} for a signalling NaN. If it is a
+normal number the format is that accepted by the C library function
+@code{atof}.
+
+@item s @var{string}
+String constant. @var{string} is a string enclosed in either @samp{'}
+(in which case @samp{'} characters within the string are represented as
+@samp{\'} or @samp{"} (in which case @samp{"} characters within the
+string are represented as @samp{\"}).
+
+@item S @var{type-information} , @var{elements} , @var{bits} , @var{pattern}
+Set constant. @var{type-information} is the type of the constant, as it
+would appear after a symbol descriptor (@pxref{String Field}).
+@var{elements} is the number of elements in the set (does this means
+how many bits of @var{pattern} are actually used, which would be
+redundant with the type, or perhaps the number of bits set in
+@var{pattern}? I don't get it), @var{bits} is the number of bits in the
+constant (meaning it specifies the length of @var{pattern}, I think),
+and @var{pattern} is a hexadecimal representation of the set. AIX
+documentation refers to a limit of 32 bytes, but I see no reason why
+this limit should exist. This form could probably be used for arbitrary
+constants, not just sets; the only catch is that @var{pattern} should be
+understood to be target, not host, byte order and format.
+@end table
+
+The boolean, character, string, and set constants are not supported by
+GDB 4.9, but it ignores them. GDB 4.8 and earlier gave an error
+message and refused to read symbols from the file containing the
+constants.
+
+The above information is followed by @samp{;}.
+
+@node Variables
+@chapter Variables
+
+Different types of stabs describe the various ways that variables can be
+allocated: on the stack, globally, in registers, in common blocks,
+statically, or as arguments to a function.
+
+@menu
+* Stack Variables:: Variables allocated on the stack.
+* Global Variables:: Variables used by more than one source file.
+* Register Variables:: Variables in registers.
+* Common Blocks:: Variables statically allocated together.
+* Statics:: Variables local to one source file.
+* Based Variables:: Fortran pointer based variables.
+* Parameters:: Variables for arguments to functions.
+@end menu
+
+@node Stack Variables
+@section Automatic Variables Allocated on the Stack
+
+If a variable's scope is local to a function and its lifetime is only as
+long as that function executes (C calls such variables
+@dfn{automatic}), it can be allocated in a register (@pxref{Register
+Variables}) or on the stack.
+
+@findex N_LSYM, for stack variables
+@findex C_LSYM
+Each variable allocated on the stack has a stab with the symbol
+descriptor omitted. Since type information should begin with a digit,
+@samp{-}, or @samp{(}, only those characters precluded from being used
+for symbol descriptors. However, the Acorn RISC machine (ARM) is said
+to get this wrong: it puts out a mere type definition here, without the
+preceding @samp{@var{type-number}=}. This is a bad idea; there is no
+guarantee that type descriptors are distinct from symbol descriptors.
+Stabs for stack variables use the @code{N_LSYM} stab type, or
+@code{C_LSYM} for XCOFF.
+
+The value of the stab is the offset of the variable within the
+local variables. On most machines this is an offset from the frame
+pointer and is negative. The location of the stab specifies which block
+it is defined in; see @ref{Block Structure}.
+
+For example, the following C code:
+
+@example
+int
+main ()
+@{
+ int x;
+@}
+@end example
+
+produces the following stabs:
+
+@example
+.stabs "main:F1",36,0,0,_main # @r{36 is N_FUN}
+.stabs "x:1",128,0,0,-12 # @r{128 is N_LSYM}
+.stabn 192,0,0,LBB2 # @r{192 is N_LBRAC}
+.stabn 224,0,0,LBE2 # @r{224 is N_RBRAC}
+@end example
+
+@xref{Procedures} for more information on the @code{N_FUN} stab, and
+@ref{Block Structure} for more information on the @code{N_LBRAC} and
+@code{N_RBRAC} stabs.
+
+@node Global Variables
+@section Global Variables
+
+@findex N_GSYM
+@findex C_GSYM
+@c FIXME: verify for sure that it really is C_GSYM on XCOFF
+A variable whose scope is not specific to just one source file is
+represented by the @samp{G} symbol descriptor. These stabs use the
+@code{N_GSYM} stab type (C_GSYM for XCOFF). The type information for
+the stab (@pxref{String Field}) gives the type of the variable.
+
+For example, the following source code:
+
+@example
+char g_foo = 'c';
+@end example
+
+@noindent
+yields the following assembly code:
+
+@example
+.stabs "g_foo:G2",32,0,0,0 # @r{32 is N_GSYM}
+ .global _g_foo
+ .data
+_g_foo:
+ .byte 99
+@end example
+
+The address of the variable represented by the @code{N_GSYM} is not
+contained in the @code{N_GSYM} stab. The debugger gets this information
+from the external symbol for the global variable. In the example above,
+the @code{.global _g_foo} and @code{_g_foo:} lines tell the assembler to
+produce an external symbol.
+
+Some compilers, like GCC, output @code{N_GSYM} stabs only once, where
+the variable is defined. Other compilers, like SunOS4 /bin/cc, output a
+@code{N_GSYM} stab for each compilation unit which references the
+variable.
+
+@node Register Variables
+@section Register Variables
+
+@findex N_RSYM
+@findex C_RSYM
+@c According to an old version of this manual, AIX uses C_RPSYM instead
+@c of C_RSYM. I am skeptical; this should be verified.
+Register variables have their own stab type, @code{N_RSYM}
+(@code{C_RSYM} for XCOFF), and their own symbol descriptor, @samp{r}.
+The stab's value is the number of the register where the variable data
+will be stored.
+@c .stabs "name:type",N_RSYM,0,RegSize,RegNumber (Sun doc)
+
+AIX defines a separate symbol descriptor @samp{d} for floating point
+registers. This seems unnecessary; why not just just give floating
+point registers different register numbers? I have not verified whether
+the compiler actually uses @samp{d}.
+
+If the register is explicitly allocated to a global variable, but not
+initialized, as in:
+
+@example
+register int g_bar asm ("%g5");
+@end example
+
+@noindent
+then the stab may be emitted at the end of the object file, with
+the other bss symbols.
+
+@node Common Blocks
+@section Common Blocks
+
+A common block is a statically allocated section of memory which can be
+referred to by several source files. It may contain several variables.
+I believe Fortran is the only language with this feature.
+
+@findex N_BCOMM
+@findex N_ECOMM
+@findex C_BCOMM
+@findex C_ECOMM
+A @code{N_BCOMM} stab begins a common block and an @code{N_ECOMM} stab
+ends it. The only field that is significant in these two stabs is the
+string, which names a normal (non-debugging) symbol that gives the
+address of the common block. According to IBM documentation, only the
+@code{N_BCOMM} has the name of the common block (even though their
+compiler actually puts it both places).
+
+@findex N_ECOML
+@findex C_ECOML
+The stabs for the members of the common block are between the
+@code{N_BCOMM} and the @code{N_ECOMM}; the value of each stab is the
+offset within the common block of that variable. IBM uses the
+@code{C_ECOML} stab type, and there is a corresponding @code{N_ECOML}
+stab type, but Sun's Fortran compiler uses @code{N_GSYM} instead. The
+variables within a common block use the @samp{V} symbol descriptor (I
+believe this is true of all Fortran variables). Other stabs (at least
+type declarations using @code{C_DECL}) can also be between the
+@code{N_BCOMM} and the @code{N_ECOMM}.
+
+@node Statics
+@section Static Variables
+
+Initialized static variables are represented by the @samp{S} and
+@samp{V} symbol descriptors. @samp{S} means file scope static, and
+@samp{V} means procedure scope static. One exception: in XCOFF, IBM's
+xlc compiler always uses @samp{V}, and whether it is file scope or not
+is distinguished by whether the stab is located within a function.
+
+@c This is probably not worth mentioning; it is only true on the sparc
+@c for `double' variables which although declared const are actually in
+@c the data segment (the text segment can't guarantee 8 byte alignment).
+@c (although GCC
+@c 2.4.5 has a bug in that it uses @code{N_FUN}, so neither dbx nor GDB can
+@c find the variables)
+@findex N_STSYM
+@findex N_LCSYM
+@findex N_FUN, for variables
+@findex N_ROSYM
+In a.out files, @code{N_STSYM} means the data section, @code{N_FUN}
+means the text section, and @code{N_LCSYM} means the bss section. For
+those systems with a read-only data section separate from the text
+section (Solaris), @code{N_ROSYM} means the read-only data section.
+
+For example, the source lines:
+
+@example
+static const int var_const = 5;
+static int var_init = 2;
+static int var_noinit;
+@end example
+
+@noindent
+yield the following stabs:
+
+@example
+.stabs "var_const:S1",36,0,0,_var_const # @r{36 is N_FUN}
+@dots{}
+.stabs "var_init:S1",38,0,0,_var_init # @r{38 is N_STSYM}
+@dots{}
+.stabs "var_noinit:S1",40,0,0,_var_noinit # @r{40 is N_LCSYM}
+@end example
+
+@findex C_STSYM
+@findex C_BSTAT
+@findex C_ESTAT
+In XCOFF files, the stab type need not indicate the section;
+@code{C_STSYM} can be used for all statics. Also, each static variable
+is enclosed in a static block. A @code{C_BSTAT} (emitted with a
+@samp{.bs} assembler directive) symbol begins the static block; its
+value is the symbol number of the csect symbol whose value is the
+address of the static block, its section is the section of the variables
+in that static block, and its name is @samp{.bs}. A @code{C_ESTAT}
+(emitted with a @samp{.es} assembler directive) symbol ends the static
+block; its name is @samp{.es} and its value and section are ignored.
+
+In ECOFF files, the storage class is used to specify the section, so the
+stab type need not indicate the section.
+
+In ELF files, for the SunPRO compiler version 2.0.1, symbol descriptor
+@samp{S} means that the address is absolute (the linker relocates it)
+and symbol descriptor @samp{V} means that the address is relative to the
+start of the relevant section for that compilation unit. SunPRO has
+plans to have the linker stop relocating stabs; I suspect that their the
+debugger gets the address from the corresponding ELF (not stab) symbol.
+I'm not sure how to find which symbol of that name is the right one.
+The clean way to do all this would be to have a the value of a symbol
+descriptor @samp{S} symbol be an offset relative to the start of the
+file, just like everything else, but that introduces obvious
+compatibility problems. For more information on linker stab relocation,
+@xref{ELF Linker Relocation}.
+
+@node Based Variables
+@section Fortran Based Variables
+
+Fortran (at least, the Sun and SGI dialects of FORTRAN-77) has a feature
+which allows allocating arrays with @code{malloc}, but which avoids
+blurring the line between arrays and pointers the way that C does. In
+stabs such a variable uses the @samp{b} symbol descriptor.
+
+For example, the Fortran declarations
+
+@example
+real foo, foo10(10), foo10_5(10,5)
+pointer (foop, foo)
+pointer (foo10p, foo10)
+pointer (foo105p, foo10_5)
+@end example
+
+produce the stabs
+
+@example
+foo:b6
+foo10:bar3;1;10;6
+foo10_5:bar3;1;5;ar3;1;10;6
+@end example
+
+In this example, @code{real} is type 6 and type 3 is an integral type
+which is the type of the subscripts of the array (probably
+@code{integer}).
+
+The @samp{b} symbol descriptor is like @samp{V} in that it denotes a
+statically allocated symbol whose scope is local to a function; see
+@xref{Statics}. The value of the symbol, instead of being the address
+of the variable itself, is the address of a pointer to that variable.
+So in the above example, the value of the @code{foo} stab is the address
+of a pointer to a real, the value of the @code{foo10} stab is the
+address of a pointer to a 10-element array of reals, and the value of
+the @code{foo10_5} stab is the address of a pointer to a 5-element array
+of 10-element arrays of reals.
+
+@node Parameters
+@section Parameters
+
+Formal parameters to a function are represented by a stab (or sometimes
+two; see below) for each parameter. The stabs are in the order in which
+the debugger should print the parameters (i.e., the order in which the
+parameters are declared in the source file). The exact form of the stab
+depends on how the parameter is being passed.
+
+@findex N_PSYM
+@findex C_PSYM
+Parameters passed on the stack use the symbol descriptor @samp{p} and
+the @code{N_PSYM} symbol type (or @code{C_PSYM} for XCOFF). The value
+of the symbol is an offset used to locate the parameter on the stack;
+its exact meaning is machine-dependent, but on most machines it is an
+offset from the frame pointer.
+
+As a simple example, the code:
+
+@example
+main (argc, argv)
+ int argc;
+ char **argv;
+@end example
+
+produces the stabs:
+
+@example
+.stabs "main:F1",36,0,0,_main # @r{36 is N_FUN}
+.stabs "argc:p1",160,0,0,68 # @r{160 is N_PSYM}
+.stabs "argv:p20=*21=*2",160,0,0,72
+@end example
+
+The type definition of @code{argv} is interesting because it contains
+several type definitions. Type 21 is pointer to type 2 (char) and
+@code{argv} (type 20) is pointer to type 21.
+
+@c FIXME: figure out what these mean and describe them coherently.
+The following symbol descriptors are also said to go with @code{N_PSYM}.
+The value of the symbol is said to be an offset from the argument
+pointer (I'm not sure whether this is true or not).
+
+@example
+pP (<<??>>)
+pF Fortran function parameter
+X (function result variable)
+@end example
+
+@menu
+* Register Parameters::
+* Local Variable Parameters::
+* Reference Parameters::
+* Conformant Arrays::
+@end menu
+
+@node Register Parameters
+@subsection Passing Parameters in Registers
+
+If the parameter is passed in a register, then traditionally there are
+two symbols for each argument:
+
+@example
+.stabs "arg:p1" . . . ; N_PSYM
+.stabs "arg:r1" . . . ; N_RSYM
+@end example
+
+Debuggers use the second one to find the value, and the first one to
+know that it is an argument.
+
+@findex C_RPSYM
+@findex N_RSYM, for parameters
+Because that approach is kind of ugly, some compilers use symbol
+descriptor @samp{P} or @samp{R} to indicate an argument which is in a
+register. Symbol type @code{C_RPSYM} is used in XCOFF and @code{N_RSYM}
+is used otherwise. The symbol's value is the register number. @samp{P}
+and @samp{R} mean the same thing; the difference is that @samp{P} is a
+GNU invention and @samp{R} is an IBM (XCOFF) invention. As of version
+4.9, GDB should handle either one.
+
+There is at least one case where GCC uses a @samp{p} and @samp{r} pair
+rather than @samp{P}; this is where the argument is passed in the
+argument list and then loaded into a register.
+
+According to the AIX documentation, symbol descriptor @samp{D} is for a
+parameter passed in a floating point register. This seems
+unnecessary---why not just use @samp{R} with a register number which
+indicates that it's a floating point register? I haven't verified
+whether the system actually does what the documentation indicates.
+
+@c FIXME: On the hppa this is for any type > 8 bytes, I think, and not
+@c for small structures (investigate).
+On the sparc and hppa, for a @samp{P} symbol whose type is a structure
+or union, the register contains the address of the structure. On the
+sparc, this is also true of a @samp{p} and @samp{r} pair (using Sun
+@code{cc}) or a @samp{p} symbol. However, if a (small) structure is
+really in a register, @samp{r} is used. And, to top it all off, on the
+hppa it might be a structure which was passed on the stack and loaded
+into a register and for which there is a @samp{p} and @samp{r} pair! I
+believe that symbol descriptor @samp{i} is supposed to deal with this
+case (it is said to mean "value parameter by reference, indirect
+access"; I don't know the source for this information), but I don't know
+details or what compilers or debuggers use it, if any (not GDB or GCC).
+It is not clear to me whether this case needs to be dealt with
+differently than parameters passed by reference (@pxref{Reference Parameters}).
+
+@node Local Variable Parameters
+@subsection Storing Parameters as Local Variables
+
+There is a case similar to an argument in a register, which is an
+argument that is actually stored as a local variable. Sometimes this
+happens when the argument was passed in a register and then the compiler
+stores it as a local variable. If possible, the compiler should claim
+that it's in a register, but this isn't always done.
+
+If a parameter is passed as one type and converted to a smaller type by
+the prologue (for example, the parameter is declared as a @code{float},
+but the calling conventions specify that it is passed as a
+@code{double}), then GCC2 (sometimes) uses a pair of symbols. The first
+symbol uses symbol descriptor @samp{p} and the type which is passed.
+The second symbol has the type and location which the parameter actually
+has after the prologue. For example, suppose the following C code
+appears with no prototypes involved:
+
+@example
+void
+subr (f)
+ float f;
+@{
+@end example
+
+if @code{f} is passed as a double at stack offset 8, and the prologue
+converts it to a float in register number 0, then the stabs look like:
+
+@example
+.stabs "f:p13",160,0,3,8 # @r{160 is @code{N_PSYM}, here 13 is @code{double}}
+.stabs "f:r12",64,0,3,0 # @r{64 is @code{N_RSYM}, here 12 is @code{float}}
+@end example
+
+In both stabs 3 is the line number where @code{f} is declared
+(@pxref{Line Numbers}).
+
+@findex N_LSYM, for parameter
+GCC, at least on the 960, has another solution to the same problem. It
+uses a single @samp{p} symbol descriptor for an argument which is stored
+as a local variable but uses @code{N_LSYM} instead of @code{N_PSYM}. In
+this case, the value of the symbol is an offset relative to the local
+variables for that function, not relative to the arguments; on some
+machines those are the same thing, but not on all.
+
+@c This is mostly just background info; the part that logically belongs
+@c here is the last sentence.
+On the VAX or on other machines in which the calling convention includes
+the number of words of arguments actually passed, the debugger (GDB at
+least) uses the parameter symbols to keep track of whether it needs to
+print nameless arguments in addition to the formal parameters which it
+has printed because each one has a stab. For example, in
+
+@example
+extern int fprintf (FILE *stream, char *format, @dots{});
+@dots{}
+fprintf (stdout, "%d\n", x);
+@end example
+
+there are stabs for @code{stream} and @code{format}. On most machines,
+the debugger can only print those two arguments (because it has no way
+of knowing that additional arguments were passed), but on the VAX or
+other machines with a calling convention which indicates the number of
+words of arguments, the debugger can print all three arguments. To do
+so, the parameter symbol (symbol descriptor @samp{p}) (not necessarily
+@samp{r} or symbol descriptor omitted symbols) needs to contain the
+actual type as passed (for example, @code{double} not @code{float} if it
+is passed as a double and converted to a float).
+
+@node Reference Parameters
+@subsection Passing Parameters by Reference
+
+If the parameter is passed by reference (e.g., Pascal @code{VAR}
+parameters), then the symbol descriptor is @samp{v} if it is in the
+argument list, or @samp{a} if it in a register. Other than the fact
+that these contain the address of the parameter rather than the
+parameter itself, they are identical to @samp{p} and @samp{R},
+respectively. I believe @samp{a} is an AIX invention; @samp{v} is
+supported by all stabs-using systems as far as I know.
+
+@node Conformant Arrays
+@subsection Passing Conformant Array Parameters
+
+@c Is this paragraph correct? It is based on piecing together patchy
+@c information and some guesswork
+Conformant arrays are a feature of Modula-2, and perhaps other
+languages, in which the size of an array parameter is not known to the
+called function until run-time. Such parameters have two stabs: a
+@samp{x} for the array itself, and a @samp{C}, which represents the size
+of the array. The value of the @samp{x} stab is the offset in the
+argument list where the address of the array is stored (it this right?
+it is a guess); the value of the @samp{C} stab is the offset in the
+argument list where the size of the array (in elements? in bytes?) is
+stored.
+
+@node Types
+@chapter Defining Types
+
+The examples so far have described types as references to previously
+defined types, or defined in terms of subranges of or pointers to
+previously defined types. This chapter describes the other type
+descriptors that may follow the @samp{=} in a type definition.
+
+@menu
+* Builtin Types:: Integers, floating point, void, etc.
+* Miscellaneous Types:: Pointers, sets, files, etc.
+* Cross-References:: Referring to a type not yet defined.
+* Subranges:: A type with a specific range.
+* Arrays:: An aggregate type of same-typed elements.
+* Strings:: Like an array but also has a length.
+* Enumerations:: Like an integer but the values have names.
+* Structures:: An aggregate type of different-typed elements.
+* Typedefs:: Giving a type a name.
+* Unions:: Different types sharing storage.
+* Function Types::
+@end menu
+
+@node Builtin Types
+@section Builtin Types
+
+Certain types are built in (@code{int}, @code{short}, @code{void},
+@code{float}, etc.); the debugger recognizes these types and knows how
+to handle them. Thus, don't be surprised if some of the following ways
+of specifying builtin types do not specify everything that a debugger
+would need to know about the type---in some cases they merely specify
+enough information to distinguish the type from other types.
+
+The traditional way to define builtin types is convolunted, so new ways
+have been invented to describe them. Sun's @code{acc} uses special
+builtin type descriptors (@samp{b} and @samp{R}), and IBM uses negative
+type numbers. GDB accepts all three ways, as of version 4.8; dbx just
+accepts the traditional builtin types and perhaps one of the other two
+formats. The following sections describe each of these formats.
+
+@menu
+* Traditional Builtin Types:: Put on your seatbelts and prepare for kludgery
+* Builtin Type Descriptors:: Builtin types with special type descriptors
+* Negative Type Numbers:: Builtin types using negative type numbers
+@end menu
+
+@node Traditional Builtin Types
+@subsection Traditional Builtin Types
+
+This is the traditional, convoluted method for defining builtin types.
+There are several classes of such type definitions: integer, floating
+point, and @code{void}.
+
+@menu
+* Traditional Integer Types::
+* Traditional Other Types::
+@end menu
+
+@node Traditional Integer Types
+@subsubsection Traditional Integer Types
+
+Often types are defined as subranges of themselves. If the bounding values
+fit within an @code{int}, then they are given normally. For example:
+
+@example
+.stabs "int:t1=r1;-2147483648;2147483647;",128,0,0,0 # @r{128 is N_LSYM}
+.stabs "char:t2=r2;0;127;",128,0,0,0
+@end example
+
+Builtin types can also be described as subranges of @code{int}:
+
+@example
+.stabs "unsigned short:t6=r1;0;65535;",128,0,0,0
+@end example
+
+If the lower bound of a subrange is 0 and the upper bound is -1,
+the type is an unsigned integral type whose bounds are too
+big to describe in an @code{int}. Traditionally this is only used for
+@code{unsigned int} and @code{unsigned long}:
+
+@example
+.stabs "unsigned int:t4=r1;0;-1;",128,0,0,0
+@end example
+
+For larger types, GCC 2.4.5 puts out bounds in octal, with one or more
+leading zeroes. In this case a negative bound consists of a number
+which is a 1 bit (for the sign bit) followed by a 0 bit for each bit in
+the number (except the sign bit), and a positive bound is one which is a
+1 bit for each bit in the number (except possibly the sign bit). All
+known versions of dbx and GDB version 4 accept this (at least in the
+sense of not refusing to process the file), but GDB 3.5 refuses to read
+the whole file containing such symbols. So GCC 2.3.3 did not output the
+proper size for these types. As an example of octal bounds, the string
+fields of the stabs for 64 bit integer types look like:
+
+@c .stabs directives, etc., omitted to make it fit on the page.
+@example
+long int:t3=r1;001000000000000000000000;000777777777777777777777;
+long unsigned int:t5=r1;000000000000000000000000;001777777777777777777777;
+@end example
+
+If the lower bound of a subrange is 0 and the upper bound is negative,
+the type is an unsigned integral type whose size in bytes is the
+absolute value of the upper bound. I believe this is a Convex
+convention for @code{unsigned long long}.
+
+If the lower bound of a subrange is negative and the upper bound is 0,
+the type is a signed integral type whose size in bytes is
+the absolute value of the lower bound. I believe this is a Convex
+convention for @code{long long}. To distinguish this from a legitimate
+subrange, the type should be a subrange of itself. I'm not sure whether
+this is the case for Convex.
+
+@node Traditional Other Types
+@subsubsection Traditional Other Types
+
+If the upper bound of a subrange is 0 and the lower bound is positive,
+the type is a floating point type, and the lower bound of the subrange
+indicates the number of bytes in the type:
+
+@example
+.stabs "float:t12=r1;4;0;",128,0,0,0
+.stabs "double:t13=r1;8;0;",128,0,0,0
+@end example
+
+However, GCC writes @code{long double} the same way it writes
+@code{double}, so there is no way to distinguish.
+
+@example
+.stabs "long double:t14=r1;8;0;",128,0,0,0
+@end example
+
+Complex types are defined the same way as floating-point types; there is
+no way to distinguish a single-precision complex from a double-precision
+floating-point type.
+
+The C @code{void} type is defined as itself:
+
+@example
+.stabs "void:t15=15",128,0,0,0
+@end example
+
+I'm not sure how a boolean type is represented.
+
+@node Builtin Type Descriptors
+@subsection Defining Builtin Types Using Builtin Type Descriptors
+
+This is the method used by Sun's @code{acc} for defining builtin types.
+These are the type descriptors to define builtin types:
+
+@table @code
+@c FIXME: clean up description of width and offset, once we figure out
+@c what they mean
+@item b @var{signed} @var{char-flag} @var{width} ; @var{offset} ; @var{nbits} ;
+Define an integral type. @var{signed} is @samp{u} for unsigned or
+@samp{s} for signed. @var{char-flag} is @samp{c} which indicates this
+is a character type, or is omitted. I assume this is to distinguish an
+integral type from a character type of the same size, for example it
+might make sense to set it for the C type @code{wchar_t} so the debugger
+can print such variables differently (Solaris does not do this). Sun
+sets it on the C types @code{signed char} and @code{unsigned char} which
+arguably is wrong. @var{width} and @var{offset} appear to be for small
+objects stored in larger ones, for example a @code{short} in an
+@code{int} register. @var{width} is normally the number of bytes in the
+type. @var{offset} seems to always be zero. @var{nbits} is the number
+of bits in the type.
+
+Note that type descriptor @samp{b} used for builtin types conflicts with
+its use for Pascal space types (@pxref{Miscellaneous Types}); they can
+be distinguished because the character following the type descriptor
+will be a digit, @samp{(}, or @samp{-} for a Pascal space type, or
+@samp{u} or @samp{s} for a builtin type.
+
+@item w
+Documented by AIX to define a wide character type, but their compiler
+actually uses negative type numbers (@pxref{Negative Type Numbers}).
+
+@item R @var{fp-type} ; @var{bytes} ;
+Define a floating point type. @var{fp-type} has one of the following values:
+
+@table @code
+@item 1 (NF_SINGLE)
+IEEE 32-bit (single precision) floating point format.
+
+@item 2 (NF_DOUBLE)
+IEEE 64-bit (double precision) floating point format.
+
+@item 3 (NF_COMPLEX)
+@item 4 (NF_COMPLEX16)
+@item 5 (NF_COMPLEX32)
+@c "GDB source" really means @file{include/aout/stab_gnu.h}, but trying
+@c to put that here got an overfull hbox.
+These are for complex numbers. A comment in the GDB source describes
+them as Fortran @code{complex}, @code{double complex}, and
+@code{complex*16}, respectively, but what does that mean? (i.e., Single
+precision? Double precison?).
+
+@item 6 (NF_LDOUBLE)
+Long double. This should probably only be used for Sun format
+@code{long double}, and new codes should be used for other floating
+point formats (@code{NF_DOUBLE} can be used if a @code{long double} is
+really just an IEEE double, of course).
+@end table
+
+@var{bytes} is the number of bytes occupied by the type. This allows a
+debugger to perform some operations with the type even if it doesn't
+understand @var{fp-type}.
+
+@item g @var{type-information} ; @var{nbits}
+Documented by AIX to define a floating type, but their compiler actually
+uses negative type numbers (@pxref{Negative Type Numbers}).
+
+@item c @var{type-information} ; @var{nbits}
+Documented by AIX to define a complex type, but their compiler actually
+uses negative type numbers (@pxref{Negative Type Numbers}).
+@end table
+
+The C @code{void} type is defined as a signed integral type 0 bits long:
+@example
+.stabs "void:t19=bs0;0;0",128,0,0,0
+@end example
+The Solaris compiler seems to omit the trailing semicolon in this case.
+Getting sloppy in this way is not a swift move because if a type is
+embedded in a more complex expression it is necessary to be able to tell
+where it ends.
+
+I'm not sure how a boolean type is represented.
+
+@node Negative Type Numbers
+@subsection Negative Type Numbers
+
+This is the method used in XCOFF for defining builtin types.
+Since the debugger knows about the builtin types anyway, the idea of
+negative type numbers is simply to give a special type number which
+indicates the builtin type. There is no stab defining these types.
+
+There are several subtle issues with negative type numbers.
+
+One is the size of the type. A builtin type (for example the C types
+@code{int} or @code{long}) might have different sizes depending on
+compiler options, the target architecture, the ABI, etc. This issue
+doesn't come up for IBM tools since (so far) they just target the
+RS/6000; the sizes indicated below for each size are what the IBM
+RS/6000 tools use. To deal with differing sizes, either define separate
+negative type numbers for each size (which works but requires changing
+the debugger, and, unless you get both AIX dbx and GDB to accept the
+change, introduces an incompatibility), or use a type attribute
+(@pxref{String Field}) to define a new type with the appropriate size
+(which merely requires a debugger which understands type attributes,
+like AIX dbx or GDB). For example,
+
+@example
+.stabs "boolean:t10=@@s8;-16",128,0,0,0
+@end example
+
+defines an 8-bit boolean type, and
+
+@example
+.stabs "boolean:t10=@@s64;-16",128,0,0,0
+@end example
+
+defines a 64-bit boolean type.
+
+A similar issue is the format of the type. This comes up most often for
+floating-point types, which could have various formats (particularly
+extended doubles, which vary quite a bit even among IEEE systems).
+Again, it is best to define a new negative type number for each
+different format; changing the format based on the target system has
+various problems. One such problem is that the Alpha has both VAX and
+IEEE floating types. One can easily imagine one library using the VAX
+types and another library in the same executable using the IEEE types.
+Another example is that the interpretation of whether a boolean is true
+or false can be based on the least significant bit, most significant
+bit, whether it is zero, etc., and different compilers (or different
+options to the same compiler) might provide different kinds of boolean.
+
+The last major issue is the names of the types. The name of a given
+type depends @emph{only} on the negative type number given; these do not
+vary depending on the language, the target system, or anything else.
+One can always define separate type numbers---in the following list you
+will see for example separate @code{int} and @code{integer*4} types
+which are identical except for the name. But compatibility can be
+maintained by not inventing new negative type numbers and instead just
+defining a new type with a new name. For example:
+
+@example
+.stabs "CARDINAL:t10=-8",128,0,0,0
+@end example
+
+Here is the list of negative type numbers. The phrase @dfn{integral
+type} is used to mean twos-complement (I strongly suspect that all
+machines which use stabs use twos-complement; most machines use
+twos-complement these days).
+
+@table @code
+@item -1
+@code{int}, 32 bit signed integral type.
+
+@item -2
+@code{char}, 8 bit type holding a character. Both GDB and dbx on AIX
+treat this as signed. GCC uses this type whether @code{char} is signed
+or not, which seems like a bad idea. The AIX compiler (@code{xlc}) seems to
+avoid this type; it uses -5 instead for @code{char}.
+
+@item -3
+@code{short}, 16 bit signed integral type.
+
+@item -4
+@code{long}, 32 bit signed integral type.
+
+@item -5
+@code{unsigned char}, 8 bit unsigned integral type.
+
+@item -6
+@code{signed char}, 8 bit signed integral type.
+
+@item -7
+@code{unsigned short}, 16 bit unsigned integral type.
+
+@item -8
+@code{unsigned int}, 32 bit unsigned integral type.
+
+@item -9
+@code{unsigned}, 32 bit unsigned integral type.
+
+@item -10
+@code{unsigned long}, 32 bit unsigned integral type.
+
+@item -11
+@code{void}, type indicating the lack of a value.
+
+@item -12
+@code{float}, IEEE single precision.
+
+@item -13
+@code{double}, IEEE double precision.
+
+@item -14
+@code{long double}, IEEE double precision. The compiler claims the size
+will increase in a future release, and for binary compatibility you have
+to avoid using @code{long double}. I hope when they increase it they
+use a new negative type number.
+
+@item -15
+@code{integer}. 32 bit signed integral type.
+
+@item -16
+@code{boolean}. 32 bit type. GDB and GCC assume that zero is false,
+one is true, and other values have unspecified meaning. I hope this
+agrees with how the IBM tools use the type.
+
+@item -17
+@code{short real}. IEEE single precision.
+
+@item -18
+@code{real}. IEEE double precision.
+
+@item -19
+@code{stringptr}. @xref{Strings}.
+
+@item -20
+@code{character}, 8 bit unsigned character type.
+
+@item -21
+@code{logical*1}, 8 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -22
+@code{logical*2}, 16 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -23
+@code{logical*4}, 32 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -24
+@code{logical}, 32 bit type. This Fortran type has a split
+personality in that it is used for boolean variables, but can also be
+used for unsigned integers. 0 is false, 1 is true, and other values are
+non-boolean.
+
+@item -25
+@code{complex}. A complex type consisting of two IEEE single-precision
+floating point values.
+
+@item -26
+@code{complex}. A complex type consisting of two IEEE double-precision
+floating point values.
+
+@item -27
+@code{integer*1}, 8 bit signed integral type.
+
+@item -28
+@code{integer*2}, 16 bit signed integral type.
+
+@item -29
+@code{integer*4}, 32 bit signed integral type.
+
+@item -30
+@code{wchar}. Wide character, 16 bits wide, unsigned (what format?
+Unicode?).
+
+@item -31
+@code{long long}, 64 bit signed integral type.
+
+@item -32
+@code{unsigned long long}, 64 bit unsigned integral type.
+
+@item -33
+@code{logical*8}, 64 bit unsigned integral type.
+
+@item -34
+@code{integer*8}, 64 bit signed integral type.
+@end table
+
+@node Miscellaneous Types
+@section Miscellaneous Types
+
+@table @code
+@item b @var{type-information} ; @var{bytes}
+Pascal space type. This is documented by IBM; what does it mean?
+
+This use of the @samp{b} type descriptor can be distinguished
+from its use for builtin integral types (@pxref{Builtin Type
+Descriptors}) because the character following the type descriptor is
+always a digit, @samp{(}, or @samp{-}.
+
+@item B @var{type-information}
+A volatile-qualified version of @var{type-information}. This is
+a Sun extension. References and stores to a variable with a
+volatile-qualified type must not be optimized or cached; they
+must occur as the user specifies them.
+
+@item d @var{type-information}
+File of type @var{type-information}. As far as I know this is only used
+by Pascal.
+
+@item k @var{type-information}
+A const-qualified version of @var{type-information}. This is a Sun
+extension. A variable with a const-qualified type cannot be modified.
+
+@item M @var{type-information} ; @var{length}
+Multiple instance type. The type seems to composed of @var{length}
+repetitions of @var{type-information}, for example @code{character*3} is
+represented by @samp{M-2;3}, where @samp{-2} is a reference to a
+character type (@pxref{Negative Type Numbers}). I'm not sure how this
+differs from an array. This appears to be a Fortran feature.
+@var{length} is a bound, like those in range types; see @ref{Subranges}.
+
+@item S @var{type-information}
+Pascal set type. @var{type-information} must be a small type such as an
+enumeration or a subrange, and the type is a bitmask whose length is
+specified by the number of elements in @var{type-information}.
+
+In CHILL, if it is a bitstring instead of a set, also use the @samp{S}
+type attribute (@pxref{String Field}).
+
+@item * @var{type-information}
+Pointer to @var{type-information}.
+@end table
+
+@node Cross-References
+@section Cross-References to Other Types
+
+A type can be used before it is defined; one common way to deal with
+that situation is just to use a type reference to a type which has not
+yet been defined.
+
+Another way is with the @samp{x} type descriptor, which is followed by
+@samp{s} for a structure tag, @samp{u} for a union tag, or @samp{e} for
+a enumerator tag, followed by the name of the tag, followed by @samp{:}.
+If the name contains @samp{::} between a @samp{<} and @samp{>} pair (for
+C++ templates), such a @samp{::} does not end the name---only a single
+@samp{:} ends the name; see @ref{Nested Symbols}.
+
+For example, the following C declarations:
+
+@example
+struct foo;
+struct foo *bar;
+@end example
+
+@noindent
+produce:
+
+@example
+.stabs "bar:G16=*17=xsfoo:",32,0,0,0
+@end example
+
+Not all debuggers support the @samp{x} type descriptor, so on some
+machines GCC does not use it. I believe that for the above example it
+would just emit a reference to type 17 and never define it, but I
+haven't verified that.
+
+Modula-2 imported types, at least on AIX, use the @samp{i} type
+descriptor, which is followed by the name of the module from which the
+type is imported, followed by @samp{:}, followed by the name of the
+type. There is then optionally a comma followed by type information for
+the type. This differs from merely naming the type (@pxref{Typedefs}) in
+that it identifies the module; I don't understand whether the name of
+the type given here is always just the same as the name we are giving
+it, or whether this type descriptor is used with a nameless stab
+(@pxref{String Field}), or what. The symbol ends with @samp{;}.
+
+@node Subranges
+@section Subrange Types
+
+The @samp{r} type descriptor defines a type as a subrange of another
+type. It is followed by type information for the type of which it is a
+subrange, a semicolon, an integral lower bound, a semicolon, an
+integral upper bound, and a semicolon. The AIX documentation does not
+specify the trailing semicolon, in an effort to specify array indexes
+more cleanly, but a subrange which is not an array index has always
+included a trailing semicolon (@pxref{Arrays}).
+
+Instead of an integer, either bound can be one of the following:
+
+@table @code
+@item A @var{offset}
+The bound is passed by reference on the stack at offset @var{offset}
+from the argument list. @xref{Parameters}, for more information on such
+offsets.
+
+@item T @var{offset}
+The bound is passed by value on the stack at offset @var{offset} from
+the argument list.
+
+@item a @var{register-number}
+The bound is pased by reference in register number
+@var{register-number}.
+
+@item t @var{register-number}
+The bound is passed by value in register number @var{register-number}.
+
+@item J
+There is no bound.
+@end table
+
+Subranges are also used for builtin types; see @ref{Traditional Builtin Types}.
+
+@node Arrays
+@section Array Types
+
+Arrays use the @samp{a} type descriptor. Following the type descriptor
+is the type of the index and the type of the array elements. If the
+index type is a range type, it ends in a semicolon; otherwise
+(for example, if it is a type reference), there does not
+appear to be any way to tell where the types are separated. In an
+effort to clean up this mess, IBM documents the two types as being
+separated by a semicolon, and a range type as not ending in a semicolon
+(but this is not right for range types which are not array indexes,
+@pxref{Subranges}). I think probably the best solution is to specify
+that a semicolon ends a range type, and that the index type and element
+type of an array are separated by a semicolon, but that if the index
+type is a range type, the extra semicolon can be omitted. GDB (at least
+through version 4.9) doesn't support any kind of index type other than a
+range anyway; I'm not sure about dbx.
+
+It is well established, and widely used, that the type of the index,
+unlike most types found in the stabs, is merely a type definition, not
+type information (@pxref{String Field}) (that is, it need not start with
+@samp{@var{type-number}=} if it is defining a new type). According to a
+comment in GDB, this is also true of the type of the array elements; it
+gives @samp{ar1;1;10;ar1;1;10;4} as a legitimate way to express a two
+dimensional array. According to AIX documentation, the element type
+must be type information. GDB accepts either.
+
+The type of the index is often a range type, expressed as the type
+descriptor @samp{r} and some parameters. It defines the size of the
+array. In the example below, the range @samp{r1;0;2;} defines an index
+type which is a subrange of type 1 (integer), with a lower bound of 0
+and an upper bound of 2. This defines the valid range of subscripts of
+a three-element C array.
+
+For example, the definition:
+
+@example
+char char_vec[3] = @{'a','b','c'@};
+@end example
+
+@noindent
+produces the output:
+
+@example
+.stabs "char_vec:G19=ar1;0;2;2",32,0,0,0
+ .global _char_vec
+ .align 4
+_char_vec:
+ .byte 97
+ .byte 98
+ .byte 99
+@end example
+
+If an array is @dfn{packed}, the elements are spaced more
+closely than normal, saving memory at the expense of speed. For
+example, an array of 3-byte objects might, if unpacked, have each
+element aligned on a 4-byte boundary, but if packed, have no padding.
+One way to specify that something is packed is with type attributes
+(@pxref{String Field}). In the case of arrays, another is to use the
+@samp{P} type descriptor instead of @samp{a}. Other than specifying a
+packed array, @samp{P} is identical to @samp{a}.
+
+@c FIXME-what is it? A pointer?
+An open array is represented by the @samp{A} type descriptor followed by
+type information specifying the type of the array elements.
+
+@c FIXME: what is the format of this type? A pointer to a vector of pointers?
+An N-dimensional dynamic array is represented by
+
+@example
+D @var{dimensions} ; @var{type-information}
+@end example
+
+@c Does dimensions really have this meaning? The AIX documentation
+@c doesn't say.
+@var{dimensions} is the number of dimensions; @var{type-information}
+specifies the type of the array elements.
+
+@c FIXME: what is the format of this type? A pointer to some offsets in
+@c another array?
+A subarray of an N-dimensional array is represented by
+
+@example
+E @var{dimensions} ; @var{type-information}
+@end example
+
+@c Does dimensions really have this meaning? The AIX documentation
+@c doesn't say.
+@var{dimensions} is the number of dimensions; @var{type-information}
+specifies the type of the array elements.
+
+@node Strings
+@section Strings
+
+Some languages, like C or the original Pascal, do not have string types,
+they just have related things like arrays of characters. But most
+Pascals and various other languages have string types, which are
+indicated as follows:
+
+@table @code
+@item n @var{type-information} ; @var{bytes}
+@var{bytes} is the maximum length. I'm not sure what
+@var{type-information} is; I suspect that it means that this is a string
+of @var{type-information} (thus allowing a string of integers, a string
+of wide characters, etc., as well as a string of characters). Not sure
+what the format of this type is. This is an AIX feature.
+
+@item z @var{type-information} ; @var{bytes}
+Just like @samp{n} except that this is a gstring, not an ordinary
+string. I don't know the difference.
+
+@item N
+Pascal Stringptr. What is this? This is an AIX feature.
+@end table
+
+Languages, such as CHILL which have a string type which is basically
+just an array of characters use the @samp{S} type attribute
+(@pxref{String Field}).
+
+@node Enumerations
+@section Enumerations
+
+Enumerations are defined with the @samp{e} type descriptor.
+
+@c FIXME: Where does this information properly go? Perhaps it is
+@c redundant with something we already explain.
+The source line below declares an enumeration type at file scope.
+The type definition is located after the @code{N_RBRAC} that marks the end of
+the previous procedure's block scope, and before the @code{N_FUN} that marks
+the beginning of the next procedure's block scope. Therefore it does not
+describe a block local symbol, but a file local one.
+
+The source line:
+
+@example
+enum e_places @{first,second=3,last@};
+@end example
+
+@noindent
+generates the following stab:
+
+@example
+.stabs "e_places:T22=efirst:0,second:3,last:4,;",128,0,0,0
+@end example
+
+The symbol descriptor (@samp{T}) says that the stab describes a
+structure, enumeration, or union tag. The type descriptor @samp{e},
+following the @samp{22=} of the type definition narrows it down to an
+enumeration type. Following the @samp{e} is a list of the elements of
+the enumeration. The format is @samp{@var{name}:@var{value},}. The
+list of elements ends with @samp{;}. The fact that @var{value} is
+specified as an integer can cause problems if the value is large. GCC
+2.5.2 tries to output it in octal in that case with a leading zero,
+which is probably a good thing, although GDB 4.11 supports octal only in
+cases where decimal is perfectly good. Negative decimal values are
+supported by both GDB and dbx.
+
+There is no standard way to specify the size of an enumeration type; it
+is determined by the architecture (normally all enumerations types are
+32 bits). Type attributes can be used to specify an enumeration type of
+another size for debuggers which support them; see @ref{String Field}.
+
+Enumeration types are unusual in that they define symbols for the
+enumeration values (@code{first}, @code{second}, and @code{third} in the
+above example), and even though these symbols are visible in the file as
+a whole (rather than being in a more local namespace like structure
+member names), they are defined in the type definition for the
+enumeration type rather than each having their own symbol. In order to
+be fast, GDB will only get symbols from such types (in its initial scan
+of the stabs) if the type is the first thing defined after a @samp{T} or
+@samp{t} symbol descriptor (the above example fulfills this
+requirement). If the type does not have a name, the compiler should
+emit it in a nameless stab (@pxref{String Field}); GCC does this.
+
+@node Structures
+@section Structures
+
+The encoding of structures in stabs can be shown with an example.
+
+The following source code declares a structure tag and defines an
+instance of the structure in global scope. Then a @code{typedef} equates the
+structure tag with a new type. Seperate stabs are generated for the
+structure tag, the structure @code{typedef}, and the structure instance. The
+stabs for the tag and the @code{typedef} are emited when the definitions are
+encountered. Since the structure elements are not initialized, the
+stab and code for the structure variable itself is located at the end
+of the program in the bss section.
+
+@example
+struct s_tag @{
+ int s_int;
+ float s_float;
+ char s_char_vec[8];
+ struct s_tag* s_next;
+@} g_an_s;
+
+typedef struct s_tag s_typedef;
+@end example
+
+The structure tag has an @code{N_LSYM} stab type because, like the
+enumeration, the symbol has file scope. Like the enumeration, the
+symbol descriptor is @samp{T}, for enumeration, structure, or tag type.
+The type descriptor @samp{s} following the @samp{16=} of the type
+definition narrows the symbol type to structure.
+
+Following the @samp{s} type descriptor is the number of bytes the
+structure occupies, followed by a description of each structure element.
+The structure element descriptions are of the form @var{name:type, bit
+offset from the start of the struct, number of bits in the element}.
+
+@c FIXME: phony line break. Can probably be fixed by using an example
+@c with fewer fields.
+@example
+# @r{128 is N_LSYM}
+.stabs "s_tag:T16=s20s_int:1,0,32;s_float:12,32,32;
+ s_char_vec:17=ar1;0;7;2,64,64;s_next:18=*16,128,32;;",128,0,0,0
+@end example
+
+In this example, the first two structure elements are previously defined
+types. For these, the type following the @samp{@var{name}:} part of the
+element description is a simple type reference. The other two structure
+elements are new types. In this case there is a type definition
+embedded after the @samp{@var{name}:}. The type definition for the
+array element looks just like a type definition for a standalone array.
+The @code{s_next} field is a pointer to the same kind of structure that
+the field is an element of. So the definition of structure type 16
+contains a type definition for an element which is a pointer to type 16.
+
+If a field is a static member (this is a C++ feature in which a single
+variable appears to be a field of every structure of a given type) it
+still starts out with the field name, a colon, and the type, but then
+instead of a comma, bit position, comma, and bit size, there is a colon
+followed by the name of the variable which each such field refers to.
+
+If the structure has methods (a C++ feature), they follow the non-method
+fields; see @ref{Cplusplus}.
+
+@node Typedefs
+@section Giving a Type a Name
+
+@findex N_LSYM, for types
+@findex C_DECL, for types
+To give a type a name, use the @samp{t} symbol descriptor. The type
+is specified by the type information (@pxref{String Field}) for the stab.
+For example,
+
+@example
+.stabs "s_typedef:t16",128,0,0,0 # @r{128 is N_LSYM}
+@end example
+
+specifies that @code{s_typedef} refers to type number 16. Such stabs
+have symbol type @code{N_LSYM} (or @code{C_DECL} for XCOFF).
+
+If you are specifying the tag name for a structure, union, or
+enumeration, use the @samp{T} symbol descriptor instead. I believe C is
+the only language with this feature.
+
+If the type is an opaque type (I believe this is a Modula-2 feature),
+AIX provides a type descriptor to specify it. The type descriptor is
+@samp{o} and is followed by a name. I don't know what the name
+means---is it always the same as the name of the type, or is this type
+descriptor used with a nameless stab (@pxref{String Field})? There
+optionally follows a comma followed by type information which defines
+the type of this type. If omitted, a semicolon is used in place of the
+comma and the type information, and the type is much like a generic
+pointer type---it has a known size but little else about it is
+specified.
+
+@node Unions
+@section Unions
+
+@example
+union u_tag @{
+ int u_int;
+ float u_float;
+ char* u_char;
+@} an_u;
+@end example
+
+This code generates a stab for a union tag and a stab for a union
+variable. Both use the @code{N_LSYM} stab type. If a union variable is
+scoped locally to the procedure in which it is defined, its stab is
+located immediately preceding the @code{N_LBRAC} for the procedure's block
+start.
+
+The stab for the union tag, however, is located preceding the code for
+the procedure in which it is defined. The stab type is @code{N_LSYM}. This
+would seem to imply that the union type is file scope, like the struct
+type @code{s_tag}. This is not true. The contents and position of the stab
+for @code{u_type} do not convey any infomation about its procedure local
+scope.
+
+@c FIXME: phony line break. Can probably be fixed by using an example
+@c with fewer fields.
+@smallexample
+# @r{128 is N_LSYM}
+.stabs "u_tag:T23=u4u_int:1,0,32;u_float:12,0,32;u_char:21,0,32;;",
+ 128,0,0,0
+@end smallexample
+
+The symbol descriptor @samp{T}, following the @samp{name:} means that
+the stab describes an enumeration, structure, or union tag. The type
+descriptor @samp{u}, following the @samp{23=} of the type definition,
+narrows it down to a union type definition. Following the @samp{u} is
+the number of bytes in the union. After that is a list of union element
+descriptions. Their format is @var{name:type, bit offset into the
+union, number of bytes for the element;}.
+
+The stab for the union variable is:
+
+@example
+.stabs "an_u:23",128,0,0,-20 # @r{128 is N_LSYM}
+@end example
+
+@samp{-20} specifies where the variable is stored (@pxref{Stack
+Variables}).
+
+@node Function Types
+@section Function Types
+
+Various types can be defined for function variables. These types are
+not used in defining functions (@pxref{Procedures}); they are used for
+things like pointers to functions.
+
+The simple, traditional, type is type descriptor @samp{f} is followed by
+type information for the return type of the function, followed by a
+semicolon.
+
+This does not deal with functions for which the number and types of the
+parameters are part of the type, as in Modula-2 or ANSI C. AIX provides
+extensions to specify these, using the @samp{f}, @samp{F}, @samp{p}, and
+@samp{R} type descriptors.
+
+First comes the type descriptor. If it is @samp{f} or @samp{F}, this
+type involves a function rather than a procedure, and the type
+information for the return type of the function follows, followed by a
+comma. Then comes the number of parameters to the function and a
+semicolon. Then, for each parameter, there is the name of the parameter
+followed by a colon (this is only present for type descriptors @samp{R}
+and @samp{F} which represent Pascal function or procedure parameters),
+type information for the parameter, a comma, 0 if passed by reference or
+1 if passed by value, and a semicolon. The type definition ends with a
+semicolon.
+
+For example, this variable definition:
+
+@example
+int (*g_pf)();
+@end example
+
+@noindent
+generates the following code:
+
+@example
+.stabs "g_pf:G24=*25=f1",32,0,0,0
+ .common _g_pf,4,"bss"
+@end example
+
+The variable defines a new type, 24, which is a pointer to another new
+type, 25, which is a function returning @code{int}.
+
+@node Symbol Tables
+@chapter Symbol Information in Symbol Tables
+
+This chapter describes the format of symbol table entries
+and how stab assembler directives map to them. It also describes the
+transformations that the assembler and linker make on data from stabs.
+
+@menu
+* Symbol Table Format::
+* Transformations On Symbol Tables::
+@end menu
+
+@node Symbol Table Format
+@section Symbol Table Format
+
+Each time the assembler encounters a stab directive, it puts
+each field of the stab into a corresponding field in a symbol table
+entry of its output file. If the stab contains a string field, the
+symbol table entry for that stab points to a string table entry
+containing the string data from the stab. Assembler labels become
+relocatable addresses. Symbol table entries in a.out have the format:
+
+@c FIXME: should refer to external, not internal.
+@example
+struct internal_nlist @{
+ unsigned long n_strx; /* index into string table of name */
+ unsigned char n_type; /* type of symbol */
+ unsigned char n_other; /* misc info (usually empty) */
+ unsigned short n_desc; /* description field */
+ bfd_vma n_value; /* value of symbol */
+@};
+@end example
+
+If the stab has a string, the @code{n_strx} field holds the offset in
+bytes of the string within the string table. The string is terminated
+by a NUL character. If the stab lacks a string (for example, it was
+produced by a @code{.stabn} or @code{.stabd} directive), the
+@code{n_strx} field is zero.
+
+Symbol table entries with @code{n_type} field values greater than 0x1f
+originated as stabs generated by the compiler (with one random
+exception). The other entries were placed in the symbol table of the
+executable by the assembler or the linker.
+
+@node Transformations On Symbol Tables
+@section Transformations on Symbol Tables
+
+The linker concatenates object files and does fixups of externally
+defined symbols.
+
+You can see the transformations made on stab data by the assembler and
+linker by examining the symbol table after each pass of the build. To
+do this, use @samp{nm -ap}, which dumps the symbol table, including
+debugging information, unsorted. For stab entries the columns are:
+@var{value}, @var{other}, @var{desc}, @var{type}, @var{string}. For
+assembler and linker symbols, the columns are: @var{value}, @var{type},
+@var{string}.
+
+The low 5 bits of the stab type tell the linker how to relocate the
+value of the stab. Thus for stab types like @code{N_RSYM} and
+@code{N_LSYM}, where the value is an offset or a register number, the
+low 5 bits are @code{N_ABS}, which tells the linker not to relocate the
+value.
+
+Where the value of a stab contains an assembly language label,
+it is transformed by each build step. The assembler turns it into a
+relocatable address and the linker turns it into an absolute address.
+
+@menu
+* Transformations On Static Variables::
+* Transformations On Global Variables::
+* Stab Section Transformations:: For some object file formats,
+ things are a bit different.
+@end menu
+
+@node Transformations On Static Variables
+@subsection Transformations on Static Variables
+
+This source line defines a static variable at file scope:
+
+@example
+static int s_g_repeat
+@end example
+
+@noindent
+The following stab describes the symbol:
+
+@example
+.stabs "s_g_repeat:S1",38,0,0,_s_g_repeat
+@end example
+
+@noindent
+The assembler transforms the stab into this symbol table entry in the
+@file{.o} file. The location is expressed as a data segment offset.
+
+@example
+00000084 - 00 0000 STSYM s_g_repeat:S1
+@end example
+
+@noindent
+In the symbol table entry from the executable, the linker has made the
+relocatable address absolute.
+
+@example
+0000e00c - 00 0000 STSYM s_g_repeat:S1
+@end example
+
+@node Transformations On Global Variables
+@subsection Transformations on Global Variables
+
+Stabs for global variables do not contain location information. In
+this case, the debugger finds location information in the assembler or
+linker symbol table entry describing the variable. The source line:
+
+@example
+char g_foo = 'c';
+@end example
+
+@noindent
+generates the stab:
+
+@example
+.stabs "g_foo:G2",32,0,0,0
+@end example
+
+The variable is represented by two symbol table entries in the object
+file (see below). The first one originated as a stab. The second one
+is an external symbol. The upper case @samp{D} signifies that the
+@code{n_type} field of the symbol table contains 7, @code{N_DATA} with
+local linkage. The stab's value is zero since the value is not used for
+@code{N_GSYM} stabs. The value of the linker symbol is the relocatable
+address corresponding to the variable.
+
+@example
+00000000 - 00 0000 GSYM g_foo:G2
+00000080 D _g_foo
+@end example
+
+@noindent
+These entries as transformed by the linker. The linker symbol table
+entry now holds an absolute address:
+
+@example
+00000000 - 00 0000 GSYM g_foo:G2
+@dots{}
+0000e008 D _g_foo
+@end example
+
+@node Stab Section Transformations
+@subsection Transformations of Stabs in separate sections
+
+For object file formats using stabs in separate sections (@pxref{Stab
+Sections}), use @code{objdump --stabs} instead of @code{nm} to show the
+stabs in an object or executable file. @code{objdump} is a GNU utility;
+Sun does not provide any equivalent.
+
+The following example is for a stab whose value is an address is
+relative to the compilation unit (@pxref{ELF Linker Relocation}). For
+example, if the source line
+
+@example
+static int ld = 5;
+@end example
+
+appears within a function, then the assembly language output from the
+compiler contains:
+
+@example
+.Ddata.data:
+@dots{}
+ .stabs "ld:V(0,3)",0x26,0,4,.L18-Ddata.data # @r{0x26 is N_STSYM}
+@dots{}
+.L18:
+ .align 4
+ .word 0x5
+@end example
+
+Because the value is formed by subtracting one symbol from another, the
+value is absolute, not relocatable, and so the object file contains
+
+@example
+Symnum n_type n_othr n_desc n_value n_strx String
+31 STSYM 0 4 00000004 680 ld:V(0,3)
+@end example
+
+without any relocations, and the executable file also contains
+
+@example
+Symnum n_type n_othr n_desc n_value n_strx String
+31 STSYM 0 4 00000004 680 ld:V(0,3)
+@end example
+
+@node Cplusplus
+@chapter GNU C++ Stabs
+
+@menu
+* Class Names:: C++ class names are both tags and typedefs.
+* Nested Symbols:: C++ symbol names can be within other types.
+* Basic Cplusplus Types::
+* Simple Classes::
+* Class Instance::
+* Methods:: Method definition
+* Method Type Descriptor:: The @samp{#} type descriptor
+* Member Type Descriptor:: The @samp{@@} type descriptor
+* Protections::
+* Method Modifiers::
+* Virtual Methods::
+* Inheritence::
+* Virtual Base Classes::
+* Static Members::
+@end menu
+
+@node Class Names
+@section C++ Class Names
+
+In C++, a class name which is declared with @code{class}, @code{struct},
+or @code{union}, is not only a tag, as in C, but also a type name. Thus
+there should be stabs with both @samp{t} and @samp{T} symbol descriptors
+(@pxref{Typedefs}).
+
+To save space, there is a special abbreviation for this case. If the
+@samp{T} symbol descriptor is followed by @samp{t}, then the stab
+defines both a type name and a tag.
+
+For example, the C++ code
+
+@example
+struct foo @{int x;@};
+@end example
+
+can be represented as either
+
+@example
+.stabs "foo:T19=s4x:1,0,32;;",128,0,0,0 # @r{128 is N_LSYM}
+.stabs "foo:t19",128,0,0,0
+@end example
+
+or
+
+@example
+.stabs "foo:Tt19=s4x:1,0,32;;",128,0,0,0
+@end example
+
+@node Nested Symbols
+@section Defining a Symbol Within Another Type
+
+In C++, a symbol (such as a type name) can be defined within another type.
+@c FIXME: Needs example.
+
+In stabs, this is sometimes represented by making the name of a symbol
+which contains @samp{::}. Such a pair of colons does not end the name
+of the symbol, the way a single colon would (@pxref{String Field}). I'm
+not sure how consistently used or well thought out this mechanism is.
+So that a pair of colons in this position always has this meaning,
+@samp{:} cannot be used as a symbol descriptor.
+
+For example, if the string for a stab is @samp{foo::bar::baz:t5=*6},
+then @code{foo::bar::baz} is the name of the symbol, @samp{t} is the
+symbol descriptor, and @samp{5=*6} is the type information.
+
+@node Basic Cplusplus Types
+@section Basic Types For C++
+
+<< the examples that follow are based on a01.C >>
+
+
+C++ adds two more builtin types to the set defined for C. These are
+the unknown type and the vtable record type. The unknown type, type
+16, is defined in terms of itself like the void type.
+
+The vtable record type, type 17, is defined as a structure type and
+then as a structure tag. The structure has four fields: delta, index,
+pfn, and delta2. pfn is the function pointer.
+
+<< In boilerplate $vtbl_ptr_type, what are the fields delta,
+index, and delta2 used for? >>
+
+This basic type is present in all C++ programs even if there are no
+virtual methods defined.
+
+@display
+.stabs "struct_name:sym_desc(type)type_def(17)=type_desc(struct)struct_bytes(8)
+ elem_name(delta):type_ref(short int),bit_offset(0),field_bits(16);
+ elem_name(index):type_ref(short int),bit_offset(16),field_bits(16);
+ elem_name(pfn):type_def(18)=type_desc(ptr to)type_ref(void),
+ bit_offset(32),field_bits(32);
+ elem_name(delta2):type_def(short int);bit_offset(32),field_bits(16);;"
+ N_LSYM, NIL, NIL
+@end display
+
+@smallexample
+.stabs "$vtbl_ptr_type:t17=s8
+ delta:6,0,16;index:6,16,16;pfn:18=*15,32,32;delta2:6,32,16;;"
+ ,128,0,0,0
+@end smallexample
+
+@display
+.stabs "name:sym_dec(struct tag)type_ref($vtbl_ptr_type)",N_LSYM,NIL,NIL,NIL
+@end display
+
+@example
+.stabs "$vtbl_ptr_type:T17",128,0,0,0
+@end example
+
+@node Simple Classes
+@section Simple Class Definition
+
+The stabs describing C++ language features are an extension of the
+stabs describing C. Stabs representing C++ class types elaborate
+extensively on the stab format used to describe structure types in C.
+Stabs representing class type variables look just like stabs
+representing C language variables.
+
+Consider the following very simple class definition.
+
+@example
+class baseA @{
+public:
+ int Adat;
+ int Ameth(int in, char other);
+@};
+@end example
+
+The class @code{baseA} is represented by two stabs. The first stab describes
+the class as a structure type. The second stab describes a structure
+tag of the class type. Both stabs are of stab type @code{N_LSYM}. Since the
+stab is not located between an @code{N_FUN} and an @code{N_LBRAC} stab this indicates
+that the class is defined at file scope. If it were, then the @code{N_LSYM}
+would signify a local variable.
+
+A stab describing a C++ class type is similar in format to a stab
+describing a C struct, with each class member shown as a field in the
+structure. The part of the struct format describing fields is
+expanded to include extra information relevent to C++ class members.
+In addition, if the class has multiple base classes or virtual
+functions the struct format outside of the field parts is also
+augmented.
+
+In this simple example the field part of the C++ class stab
+representing member data looks just like the field part of a C struct
+stab. The section on protections describes how its format is
+sometimes extended for member data.
+
+The field part of a C++ class stab representing a member function
+differs substantially from the field part of a C struct stab. It
+still begins with @samp{name:} but then goes on to define a new type number
+for the member function, describe its return type, its argument types,
+its protection level, any qualifiers applied to the method definition,
+and whether the method is virtual or not. If the method is virtual
+then the method description goes on to give the vtable index of the
+method, and the type number of the first base class defining the
+method.
+
+When the field name is a method name it is followed by two colons rather
+than one. This is followed by a new type definition for the method.
+This is a number followed by an equal sign and the type of the method.
+Normally this will be a type declared using the @samp{#} type
+descriptor; see @ref{Method Type Descriptor}; static member functions
+are declared using the @samp{f} type descriptor instead; see
+@ref{Function Types}.
+
+The format of an overloaded operator method name differs from that of
+other methods. It is @samp{op$::@var{operator-name}.} where
+@var{operator-name} is the operator name such as @samp{+} or @samp{+=}.
+The name ends with a period, and any characters except the period can
+occur in the @var{operator-name} string.
+
+The next part of the method description represents the arguments to the
+method, preceeded by a colon and ending with a semi-colon. The types of
+the arguments are expressed in the same way argument types are expressed
+in C++ name mangling. In this example an @code{int} and a @code{char}
+map to @samp{ic}.
+
+This is followed by a number, a letter, and an asterisk or period,
+followed by another semicolon. The number indicates the protections
+that apply to the member function. Here the 2 means public. The
+letter encodes any qualifier applied to the method definition. In
+this case, @samp{A} means that it is a normal function definition. The dot
+shows that the method is not virtual. The sections that follow
+elaborate further on these fields and describe the additional
+information present for virtual methods.
+
+
+@display
+.stabs "class_name:sym_desc(type)type_def(20)=type_desc(struct)struct_bytes(4)
+ field_name(Adat):type(int),bit_offset(0),field_bits(32);
+
+ method_name(Ameth)::type_def(21)=type_desc(method)return_type(int);
+ :arg_types(int char);
+ protection(public)qualifier(normal)virtual(no);;"
+ N_LSYM,NIL,NIL,NIL
+@end display
+
+@smallexample
+.stabs "baseA:t20=s4Adat:1,0,32;Ameth::21=##1;:ic;2A.;;",128,0,0,0
+
+.stabs "class_name:sym_desc(struct tag)",N_LSYM,NIL,NIL,NIL
+
+.stabs "baseA:T20",128,0,0,0
+@end smallexample
+
+@node Class Instance
+@section Class Instance
+
+As shown above, describing even a simple C++ class definition is
+accomplished by massively extending the stab format used in C to
+describe structure types. However, once the class is defined, C stabs
+with no modifications can be used to describe class instances. The
+following source:
+
+@example
+main () @{
+ baseA AbaseA;
+@}
+@end example
+
+@noindent
+yields the following stab describing the class instance. It looks no
+different from a standard C stab describing a local variable.
+
+@display
+.stabs "name:type_ref(baseA)", N_LSYM, NIL, NIL, frame_ptr_offset
+@end display
+
+@example
+.stabs "AbaseA:20",128,0,0,-20
+@end example
+
+@node Methods
+@section Method Definition
+
+The class definition shown above declares Ameth. The C++ source below
+defines Ameth:
+
+@example
+int
+baseA::Ameth(int in, char other)
+@{
+ return in;
+@};
+@end example
+
+
+This method definition yields three stabs following the code of the
+method. One stab describes the method itself and following two describe
+its parameters. Although there is only one formal argument all methods
+have an implicit argument which is the @code{this} pointer. The @code{this}
+pointer is a pointer to the object on which the method was called. Note
+that the method name is mangled to encode the class name and argument
+types. Name mangling is described in the @sc{arm} (@cite{The Annotated
+C++ Reference Manual}, by Ellis and Stroustrup, @sc{isbn}
+0-201-51459-1); @file{gpcompare.texi} in Cygnus GCC distributions
+describes the differences between GNU mangling and @sc{arm}
+mangling.
+@c FIXME: Use @xref, especially if this is generally installed in the
+@c info tree.
+@c FIXME: This information should be in a net release, either of GCC or
+@c GDB. But gpcompare.texi doesn't seem to be in the FSF GCC.
+
+@example
+.stabs "name:symbol_desriptor(global function)return_type(int)",
+ N_FUN, NIL, NIL, code_addr_of_method_start
+
+.stabs "Ameth__5baseAic:F1",36,0,0,_Ameth__5baseAic
+@end example
+
+Here is the stab for the @code{this} pointer implicit argument. The
+name of the @code{this} pointer is always @code{this}. Type 19, the
+@code{this} pointer is defined as a pointer to type 20, @code{baseA},
+but a stab defining @code{baseA} has not yet been emited. Since the
+compiler knows it will be emited shortly, here it just outputs a cross
+reference to the undefined symbol, by prefixing the symbol name with
+@samp{xs}.
+
+@example
+.stabs "name:sym_desc(register param)type_def(19)=
+ type_desc(ptr to)type_ref(baseA)=
+ type_desc(cross-reference to)baseA:",N_RSYM,NIL,NIL,register_number
+
+.stabs "this:P19=*20=xsbaseA:",64,0,0,8
+@end example
+
+The stab for the explicit integer argument looks just like a parameter
+to a C function. The last field of the stab is the offset from the
+argument pointer, which in most systems is the same as the frame
+pointer.
+
+@example
+.stabs "name:sym_desc(value parameter)type_ref(int)",
+ N_PSYM,NIL,NIL,offset_from_arg_ptr
+
+.stabs "in:p1",160,0,0,72
+@end example
+
+<< The examples that follow are based on A1.C >>
+
+@node Method Type Descriptor
+@section The @samp{#} Type Descriptor
+
+This is like the @samp{f} type descriptor for functions (@pxref{Function
+Types}), except that a function which uses the @samp{#} type descriptor
+takes an extra argument as its first argument, for the @code{this}
+pointer. The @samp{#} type descriptor is optionally followed by the
+types of the arguments, then another @samp{#}. If the types of the
+arguments are omitted, so that the second @samp{#} immediately follows
+the @samp{#} which is the type descriptor, the arguments are being
+omitted (to save space) and can be deduced from the mangled name of the
+method. After the second @samp{#} there is type information for the
+return type of the method and a semicolon.
+
+Note that although such a type will normally be used to describe fields
+in structures, unions, or classes, for at least some versions of the
+compiler it can also be used in other contexts.
+
+@node Member Type Descriptor
+@section The @samp{@@} Type Descriptor
+
+The @samp{@@} type descriptor is for a member (class and variable) type.
+It is followed by type information for the offset basetype, a comma, and
+type information for the type of the field being pointed to. (FIXME:
+this is acknowledged to be gibberish. Can anyone say what really goes
+here?).
+
+Note that there is a conflict between this and type attributes
+(@pxref{String Field}); both use type descriptor @samp{@@}.
+Fortunately, the @samp{@@} type descriptor used in this C++ sense always
+will be followed by a digit, @samp{(}, or @samp{-}, and type attributes
+never start with those things.
+
+@node Protections
+@section Protections
+
+In the simple class definition shown above all member data and
+functions were publicly accessable. The example that follows
+contrasts public, protected and privately accessable fields and shows
+how these protections are encoded in C++ stabs.
+
+If the character following the @samp{@var{field-name}:} part of the
+string is @samp{/}, then the next character is the visibility. @samp{0}
+means private, @samp{1} means protected, and @samp{2} means public.
+Debuggers should ignore visibility characters they do not recognize, and
+assume a reasonable default (such as public) (GDB 4.11 does not, but
+this should be fixed in the next GDB release). If no visibility is
+specified the field is public. The visibility @samp{9} means that the
+field has been optimized out and is public (there is no way to specify
+an optimized out field with a private or protected visibility).
+Visibility @samp{9} is not supported by GDB 4.11; this should be fixed
+in the next GDB release.
+
+The following C++ source:
+
+@example
+class vis @{
+private:
+ int priv;
+protected:
+ char prot;
+public:
+ float pub;
+@};
+@end example
+
+@noindent
+generates the following stab:
+
+@example
+# @r{128 is N_LSYM}
+.stabs "vis:T19=s12priv:/01,0,32;prot:/12,32,8;pub:12,64,32;;",128,0,0,0
+@end example
+
+@samp{vis:T19=s12} indicates that type number 19 is a 12 byte structure
+named @code{vis} The @code{priv} field has public visibility
+(@samp{/0}), type int (@samp{1}), and offset and size @samp{,0,32;}.
+The @code{prot} field has protected visibility (@samp{/1}), type char
+(@samp{2}) and offset and size @samp{,32,8;}. The @code{pub} field has
+type float (@samp{12}), and offset and size @samp{,64,32;}.
+
+Protections for member functions are signified by one digit embeded in
+the field part of the stab describing the method. The digit is 0 if
+private, 1 if protected and 2 if public. Consider the C++ class
+definition below:
+
+@example
+class all_methods @{
+private:
+ int priv_meth(int in)@{return in;@};
+protected:
+ char protMeth(char in)@{return in;@};
+public:
+ float pubMeth(float in)@{return in;@};
+@};
+@end example
+
+It generates the following stab. The digit in question is to the left
+of an @samp{A} in each case. Notice also that in this case two symbol
+descriptors apply to the class name struct tag and struct type.
+
+@display
+.stabs "class_name:sym_desc(struct tag&type)type_def(21)=
+ sym_desc(struct)struct_bytes(1)
+ meth_name::type_def(22)=sym_desc(method)returning(int);
+ :args(int);protection(private)modifier(normal)virtual(no);
+ meth_name::type_def(23)=sym_desc(method)returning(char);
+ :args(char);protection(protected)modifier(normal)virual(no);
+ meth_name::type_def(24)=sym_desc(method)returning(float);
+ :args(float);protection(public)modifier(normal)virtual(no);;",
+ N_LSYM,NIL,NIL,NIL
+@end display
+
+@smallexample
+.stabs "all_methods:Tt21=s1priv_meth::22=##1;:i;0A.;protMeth::23=##2;:c;1A.;
+ pubMeth::24=##12;:f;2A.;;",128,0,0,0
+@end smallexample
+
+@node Method Modifiers
+@section Method Modifiers (@code{const}, @code{volatile}, @code{const volatile})
+
+<< based on a6.C >>
+
+In the class example described above all the methods have the normal
+modifier. This method modifier information is located just after the
+protection information for the method. This field has four possible
+character values. Normal methods use @samp{A}, const methods use
+@samp{B}, volatile methods use @samp{C}, and const volatile methods use
+@samp{D}. Consider the class definition below:
+
+@example
+class A @{
+public:
+ int ConstMeth (int arg) const @{ return arg; @};
+ char VolatileMeth (char arg) volatile @{ return arg; @};
+ float ConstVolMeth (float arg) const volatile @{return arg; @};
+@};
+@end example
+
+This class is described by the following stab:
+
+@display
+.stabs "class(A):sym_desc(struct)type_def(20)=type_desc(struct)struct_bytes(1)
+ meth_name(ConstMeth)::type_def(21)sym_desc(method)
+ returning(int);:arg(int);protection(public)modifier(const)virtual(no);
+ meth_name(VolatileMeth)::type_def(22)=sym_desc(method)
+ returning(char);:arg(char);protection(public)modifier(volatile)virt(no)
+ meth_name(ConstVolMeth)::type_def(23)=sym_desc(method)
+ returning(float);:arg(float);protection(public)modifer(const volatile)
+ virtual(no);;", @dots{}
+@end display
+
+@example
+.stabs "A:T20=s1ConstMeth::21=##1;:i;2B.;VolatileMeth::22=##2;:c;2C.;
+ ConstVolMeth::23=##12;:f;2D.;;",128,0,0,0
+@end example
+
+@node Virtual Methods
+@section Virtual Methods
+
+<< The following examples are based on a4.C >>
+
+The presence of virtual methods in a class definition adds additional
+data to the class description. The extra data is appended to the
+description of the virtual method and to the end of the class
+description. Consider the class definition below:
+
+@example
+class A @{
+public:
+ int Adat;
+ virtual int A_virt (int arg) @{ return arg; @};
+@};
+@end example
+
+This results in the stab below describing class A. It defines a new
+type (20) which is an 8 byte structure. The first field of the class
+struct is @samp{Adat}, an integer, starting at structure offset 0 and
+occupying 32 bits.
+
+The second field in the class struct is not explicitly defined by the
+C++ class definition but is implied by the fact that the class
+contains a virtual method. This field is the vtable pointer. The
+name of the vtable pointer field starts with @samp{$vf} and continues with a
+type reference to the class it is part of. In this example the type
+reference for class A is 20 so the name of its vtable pointer field is
+@samp{$vf20}, followed by the usual colon.
+
+Next there is a type definition for the vtable pointer type (21).
+This is in turn defined as a pointer to another new type (22).
+
+Type 22 is the vtable itself, which is defined as an array, indexed by
+a range of integers between 0 and 1, and whose elements are of type
+17. Type 17 was the vtable record type defined by the boilerplate C++
+type definitions, as shown earlier.
+
+The bit offset of the vtable pointer field is 32. The number of bits
+in the field are not specified when the field is a vtable pointer.
+
+Next is the method definition for the virtual member function @code{A_virt}.
+Its description starts out using the same format as the non-virtual
+member functions described above, except instead of a dot after the
+@samp{A} there is an asterisk, indicating that the function is virtual.
+Since is is virtual some addition information is appended to the end
+of the method description.
+
+The first number represents the vtable index of the method. This is a
+32 bit unsigned number with the high bit set, followed by a
+semi-colon.
+
+The second number is a type reference to the first base class in the
+inheritence hierarchy defining the virtual member function. In this
+case the class stab describes a base class so the virtual function is
+not overriding any other definition of the method. Therefore the
+reference is to the type number of the class that the stab is
+describing (20).
+
+This is followed by three semi-colons. One marks the end of the
+current sub-section, one marks the end of the method field, and the
+third marks the end of the struct definition.
+
+For classes containing virtual functions the very last section of the
+string part of the stab holds a type reference to the first base
+class. This is preceeded by @samp{~%} and followed by a final semi-colon.
+
+@display
+.stabs "class_name(A):type_def(20)=sym_desc(struct)struct_bytes(8)
+ field_name(Adat):type_ref(int),bit_offset(0),field_bits(32);
+ field_name(A virt func ptr):type_def(21)=type_desc(ptr to)type_def(22)=
+ sym_desc(array)index_type_ref(range of int from 0 to 1);
+ elem_type_ref(vtbl elem type),
+ bit_offset(32);
+ meth_name(A_virt)::typedef(23)=sym_desc(method)returning(int);
+ :arg_type(int),protection(public)normal(yes)virtual(yes)
+ vtable_index(1);class_first_defining(A);;;~%first_base(A);",
+ N_LSYM,NIL,NIL,NIL
+@end display
+
+@c FIXME: bogus line break.
+@example
+.stabs "A:t20=s8Adat:1,0,32;$vf20:21=*22=ar1;0;1;17,32;
+ A_virt::23=##1;:i;2A*-2147483647;20;;;~%20;",128,0,0,0
+@end example
+
+@node Inheritence
+@section Inheritence
+
+Stabs describing C++ derived classes include additional sections that
+describe the inheritence hierarchy of the class. A derived class stab
+also encodes the number of base classes. For each base class it tells
+if the base class is virtual or not, and if the inheritence is private
+or public. It also gives the offset into the object of the portion of
+the object corresponding to each base class.
+
+This additional information is embeded in the class stab following the
+number of bytes in the struct. First the number of base classes
+appears bracketed by an exclamation point and a comma.
+
+Then for each base type there repeats a series: a virtual character, a
+visibilty character, a number, a comma, another number, and a
+semi-colon.
+
+The virtual character is @samp{1} if the base class is virtual and
+@samp{0} if not. The visibility character is @samp{2} if the derivation
+is public, @samp{1} if it is protected, and @samp{0} if it is private.
+Debuggers should ignore virtual or visibility characters they do not
+recognize, and assume a reasonable default (such as public and
+non-virtual) (GDB 4.11 does not, but this should be fixed in the next
+GDB release).
+
+The number following the virtual and visibility characters is the offset
+from the start of the object to the part of the object pertaining to the
+base class.
+
+After the comma, the second number is a type_descriptor for the base
+type. Finally a semi-colon ends the series, which repeats for each
+base class.
+
+The source below defines three base classes @code{A}, @code{B}, and
+@code{C} and the derived class @code{D}.
+
+
+@example
+class A @{
+public:
+ int Adat;
+ virtual int A_virt (int arg) @{ return arg; @};
+@};
+
+class B @{
+public:
+ int B_dat;
+ virtual int B_virt (int arg) @{return arg; @};
+@};
+
+class C @{
+public:
+ int Cdat;
+ virtual int C_virt (int arg) @{return arg; @};
+@};
+
+class D : A, virtual B, public C @{
+public:
+ int Ddat;
+ virtual int A_virt (int arg ) @{ return arg+1; @};
+ virtual int B_virt (int arg) @{ return arg+2; @};
+ virtual int C_virt (int arg) @{ return arg+3; @};
+ virtual int D_virt (int arg) @{ return arg; @};
+@};
+@end example
+
+Class stabs similar to the ones described earlier are generated for
+each base class.
+
+@c FIXME!!! the linebreaks in the following example probably make the
+@c examples literally unusable, but I don't know any other way to get
+@c them on the page.
+@c One solution would be to put some of the type definitions into
+@c separate stabs, even if that's not exactly what the compiler actually
+@c emits.
+@smallexample
+.stabs "A:T20=s8Adat:1,0,32;$vf20:21=*22=ar1;0;1;17,32;
+ A_virt::23=##1;:i;2A*-2147483647;20;;;~%20;",128,0,0,0
+
+.stabs "B:Tt25=s8Bdat:1,0,32;$vf25:21,32;B_virt::26=##1;
+ :i;2A*-2147483647;25;;;~%25;",128,0,0,0
+
+.stabs "C:Tt28=s8Cdat:1,0,32;$vf28:21,32;C_virt::29=##1;
+ :i;2A*-2147483647;28;;;~%28;",128,0,0,0
+@end smallexample
+
+In the stab describing derived class @code{D} below, the information about
+the derivation of this class is encoded as follows.
+
+@display
+.stabs "derived_class_name:symbol_descriptors(struct tag&type)=
+ type_descriptor(struct)struct_bytes(32)!num_bases(3),
+ base_virtual(no)inheritence_public(no)base_offset(0),
+ base_class_type_ref(A);
+ base_virtual(yes)inheritence_public(no)base_offset(NIL),
+ base_class_type_ref(B);
+ base_virtual(no)inheritence_public(yes)base_offset(64),
+ base_class_type_ref(C); @dots{}
+@end display
+
+@c FIXME! fake linebreaks.
+@smallexample
+.stabs "D:Tt31=s32!3,000,20;100,25;0264,28;$vb25:24,128;Ddat:
+ 1,160,32;A_virt::32=##1;:i;2A*-2147483647;20;;B_virt:
+ :32:i;2A*-2147483647;25;;C_virt::32:i;2A*-2147483647;
+ 28;;D_virt::32:i;2A*-2147483646;31;;;~%20;",128,0,0,0
+@end smallexample
+
+@node Virtual Base Classes
+@section Virtual Base Classes
+
+A derived class object consists of a concatination in memory of the data
+areas defined by each base class, starting with the leftmost and ending
+with the rightmost in the list of base classes. The exception to this
+rule is for virtual inheritence. In the example above, class @code{D}
+inherits virtually from base class @code{B}. This means that an
+instance of a @code{D} object will not contain its own @code{B} part but
+merely a pointer to a @code{B} part, known as a virtual base pointer.
+
+In a derived class stab, the base offset part of the derivation
+information, described above, shows how the base class parts are
+ordered. The base offset for a virtual base class is always given as 0.
+Notice that the base offset for @code{B} is given as 0 even though
+@code{B} is not the first base class. The first base class @code{A}
+starts at offset 0.
+
+The field information part of the stab for class @code{D} describes the field
+which is the pointer to the virtual base class @code{B}. The vbase pointer
+name is @samp{$vb} followed by a type reference to the virtual base class.
+Since the type id for @code{B} in this example is 25, the vbase pointer name
+is @samp{$vb25}.
+
+@c FIXME!! fake linebreaks below
+@smallexample
+.stabs "D:Tt31=s32!3,000,20;100,25;0264,28;$vb25:24,128;Ddat:1,
+ 160,32;A_virt::32=##1;:i;2A*-2147483647;20;;B_virt::32:i;
+ 2A*-2147483647;25;;C_virt::32:i;2A*-2147483647;28;;D_virt:
+ :32:i;2A*-2147483646;31;;;~%20;",128,0,0,0
+@end smallexample
+
+Following the name and a semicolon is a type reference describing the
+type of the virtual base class pointer, in this case 24. Type 24 was
+defined earlier as the type of the @code{B} class @code{this} pointer. The
+@code{this} pointer for a class is a pointer to the class type.
+
+@example
+.stabs "this:P24=*25=xsB:",64,0,0,8
+@end example
+
+Finally the field offset part of the vbase pointer field description
+shows that the vbase pointer is the first field in the @code{D} object,
+before any data fields defined by the class. The layout of a @code{D}
+class object is a follows, @code{Adat} at 0, the vtable pointer for
+@code{A} at 32, @code{Cdat} at 64, the vtable pointer for C at 96, the
+virtual base pointer for @code{B} at 128, and @code{Ddat} at 160.
+
+
+@node Static Members
+@section Static Members
+
+The data area for a class is a concatenation of the space used by the
+data members of the class. If the class has virtual methods, a vtable
+pointer follows the class data. The field offset part of each field
+description in the class stab shows this ordering.
+
+<< How is this reflected in stabs? See Cygnus bug #677 for some info. >>
+
+@node Stab Types
+@appendix Table of Stab Types
+
+The following are all the possible values for the stab type field, for
+a.out files, in numeric order. This does not apply to XCOFF, but
+it does apply to stabs in sections (@pxref{Stab Sections}). Stabs in
+ECOFF use these values but add 0x8f300 to distinguish them from non-stab
+symbols.
+
+The symbolic names are defined in the file @file{include/aout/stabs.def}.
+
+@menu
+* Non-Stab Symbol Types:: Types from 0 to 0x1f
+* Stab Symbol Types:: Types from 0x20 to 0xff
+@end menu
+
+@node Non-Stab Symbol Types
+@appendixsec Non-Stab Symbol Types
+
+The following types are used by the linker and assembler, not by stab
+directives. Since this document does not attempt to describe aspects of
+object file format other than the debugging format, no details are
+given.
+
+@c Try to get most of these to fit on a single line.
+@iftex
+@tableindent=1.5in
+@end iftex
+
+@table @code
+@item 0x0 N_UNDF
+Undefined symbol
+
+@item 0x2 N_ABS
+File scope absolute symbol
+
+@item 0x3 N_ABS | N_EXT
+External absolute symbol
+
+@item 0x4 N_TEXT
+File scope text symbol
+
+@item 0x5 N_TEXT | N_EXT
+External text symbol
+
+@item 0x6 N_DATA
+File scope data symbol
+
+@item 0x7 N_DATA | N_EXT
+External data symbol
+
+@item 0x8 N_BSS
+File scope BSS symbol
+
+@item 0x9 N_BSS | N_EXT
+External BSS symbol
+
+@item 0x0c N_FN_SEQ
+Same as @code{N_FN}, for Sequent compilers
+
+@item 0x0a N_INDR
+Symbol is indirected to another symbol
+
+@item 0x12 N_COMM
+Common---visible after shared library dynamic link
+
+@item 0x14 N_SETA
+@itemx 0x15 N_SETA | N_EXT
+Absolute set element
+
+@item 0x16 N_SETT
+@itemx 0x17 N_SETT | N_EXT
+Text segment set element
+
+@item 0x18 N_SETD
+@itemx 0x19 N_SETD | N_EXT
+Data segment set element
+
+@item 0x1a N_SETB
+@itemx 0x1b N_SETB | N_EXT
+BSS segment set element
+
+@item 0x1c N_SETV
+@itemx 0x1d N_SETV | N_EXT
+Pointer to set vector
+
+@item 0x1e N_WARNING
+Print a warning message during linking
+
+@item 0x1f N_FN
+File name of a @file{.o} file
+@end table
+
+@node Stab Symbol Types
+@appendixsec Stab Symbol Types
+
+The following symbol types indicate that this is a stab. This is the
+full list of stab numbers, including stab types that are used in
+languages other than C.
+
+@table @code
+@item 0x20 N_GSYM
+Global symbol; see @ref{Global Variables}.
+
+@item 0x22 N_FNAME
+Function name (for BSD Fortran); see @ref{Procedures}.
+
+@item 0x24 N_FUN
+Function name (@pxref{Procedures}) or text segment variable
+(@pxref{Statics}).
+
+@item 0x26 N_STSYM
+Data segment file-scope variable; see @ref{Statics}.
+
+@item 0x28 N_LCSYM
+BSS segment file-scope variable; see @ref{Statics}.
+
+@item 0x2a N_MAIN
+Name of main routine; see @ref{Main Program}.
+
+@item 0x2c N_ROSYM
+Variable in @code{.rodata} section; see @ref{Statics}.
+
+@item 0x30 N_PC
+Global symbol (for Pascal); see @ref{N_PC}.
+
+@item 0x32 N_NSYMS
+Number of symbols (according to Ultrix V4.0); see @ref{N_NSYMS}.
+
+@item 0x34 N_NOMAP
+No DST map; see @ref{N_NOMAP}.
+
+@c FIXME: describe this solaris feature in the body of the text (see
+@c comments in include/aout/stab.def).
+@item 0x38 N_OBJ
+Object file (Solaris2).
+
+@c See include/aout/stab.def for (a little) more info.
+@item 0x3c N_OPT
+Debugger options (Solaris2).
+
+@item 0x40 N_RSYM
+Register variable; see @ref{Register Variables}.
+
+@item 0x42 N_M2C
+Modula-2 compilation unit; see @ref{N_M2C}.
+
+@item 0x44 N_SLINE
+Line number in text segment; see @ref{Line Numbers}.
+
+@item 0x46 N_DSLINE
+Line number in data segment; see @ref{Line Numbers}.
+
+@item 0x48 N_BSLINE
+Line number in bss segment; see @ref{Line Numbers}.
+
+@item 0x48 N_BROWS
+Sun source code browser, path to @file{.cb} file; see @ref{N_BROWS}.
+
+@item 0x4a N_DEFD
+GNU Modula2 definition module dependency; see @ref{N_DEFD}.
+
+@item 0x4c N_FLINE
+Function start/body/end line numbers (Solaris2).
+
+@item 0x50 N_EHDECL
+GNU C++ exception variable; see @ref{N_EHDECL}.
+
+@item 0x50 N_MOD2
+Modula2 info "for imc" (according to Ultrix V4.0); see @ref{N_MOD2}.
+
+@item 0x54 N_CATCH
+GNU C++ @code{catch} clause; see @ref{N_CATCH}.
+
+@item 0x60 N_SSYM
+Structure of union element; see @ref{N_SSYM}.
+
+@item 0x62 N_ENDM
+Last stab for module (Solaris2).
+
+@item 0x64 N_SO
+Path and name of source file; see @ref{Source Files}.
+
+@item 0x80 N_LSYM
+Stack variable (@pxref{Stack Variables}) or type (@pxref{Typedefs}).
+
+@item 0x82 N_BINCL
+Beginning of an include file (Sun only); see @ref{Include Files}.
+
+@item 0x84 N_SOL
+Name of include file; see @ref{Include Files}.
+
+@item 0xa0 N_PSYM
+Parameter variable; see @ref{Parameters}.
+
+@item 0xa2 N_EINCL
+End of an include file; see @ref{Include Files}.
+
+@item 0xa4 N_ENTRY
+Alternate entry point; see @ref{Alternate Entry Points}.
+
+@item 0xc0 N_LBRAC
+Beginning of a lexical block; see @ref{Block Structure}.
+
+@item 0xc2 N_EXCL
+Place holder for a deleted include file; see @ref{Include Files}.
+
+@item 0xc4 N_SCOPE
+Modula2 scope information (Sun linker); see @ref{N_SCOPE}.
+
+@item 0xe0 N_RBRAC
+End of a lexical block; see @ref{Block Structure}.
+
+@item 0xe2 N_BCOMM
+Begin named common block; see @ref{Common Blocks}.
+
+@item 0xe4 N_ECOMM
+End named common block; see @ref{Common Blocks}.
+
+@item 0xe8 N_ECOML
+Member of a common block; see @ref{Common Blocks}.
+
+@c FIXME: How does this really work? Move it to main body of document.
+@item 0xea N_WITH
+Pascal @code{with} statement: type,,0,0,offset (Solaris2).
+
+@item 0xf0 N_NBTEXT
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf2 N_NBDATA
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf4 N_NBBSS
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf6 N_NBSTS
+Gould non-base registers; see @ref{Gould}.
+
+@item 0xf8 N_NBLCS
+Gould non-base registers; see @ref{Gould}.
+@end table
+
+@c Restore the default table indent
+@iftex
+@tableindent=.8in
+@end iftex
+
+@node Symbol Descriptors
+@appendix Table of Symbol Descriptors
+
+The symbol descriptor is the character which follows the colon in many
+stabs, and which tells what kind of stab it is. @xref{String Field},
+for more information about their use.
+
+@c Please keep this alphabetical
+@table @code
+@c In TeX, this looks great, digit is in italics. But makeinfo insists
+@c on putting it in `', not realizing that @var should override @code.
+@c I don't know of any way to make makeinfo do the right thing. Seems
+@c like a makeinfo bug to me.
+@item @var{digit}
+@itemx (
+@itemx -
+Variable on the stack; see @ref{Stack Variables}.
+
+@item :
+C++ nested symbol; see @xref{Nested Symbols}
+
+@item a
+Parameter passed by reference in register; see @ref{Reference Parameters}.
+
+@item b
+Based variable; see @ref{Based Variables}.
+
+@item c
+Constant; see @ref{Constants}.
+
+@item C
+Conformant array bound (Pascal, maybe other languages); @ref{Conformant
+Arrays}. Name of a caught exception (GNU C++). These can be
+distinguished because the latter uses @code{N_CATCH} and the former uses
+another symbol type.
+
+@item d
+Floating point register variable; see @ref{Register Variables}.
+
+@item D
+Parameter in floating point register; see @ref{Register Parameters}.
+
+@item f
+File scope function; see @ref{Procedures}.
+
+@item F
+Global function; see @ref{Procedures}.
+
+@item G
+Global variable; see @ref{Global Variables}.
+
+@item i
+@xref{Register Parameters}.
+
+@item I
+Internal (nested) procedure; see @ref{Nested Procedures}.
+
+@item J
+Internal (nested) function; see @ref{Nested Procedures}.
+
+@item L
+Label name (documented by AIX, no further information known).
+
+@item m
+Module; see @ref{Procedures}.
+
+@item p
+Argument list parameter; see @ref{Parameters}.
+
+@item pP
+@xref{Parameters}.
+
+@item pF
+Fortran Function parameter; see @ref{Parameters}.
+
+@item P
+Unfortunately, three separate meanings have been independently invented
+for this symbol descriptor. At least the GNU and Sun uses can be
+distinguished by the symbol type. Global Procedure (AIX) (symbol type
+used unknown); see @ref{Procedures}. Register parameter (GNU) (symbol
+type @code{N_PSYM}); see @ref{Parameters}. Prototype of function
+referenced by this file (Sun @code{acc}) (symbol type @code{N_FUN}).
+
+@item Q
+Static Procedure; see @ref{Procedures}.
+
+@item R
+Register parameter; see @ref{Register Parameters}.
+
+@item r
+Register variable; see @ref{Register Variables}.
+
+@item S
+File scope variable; see @ref{Statics}.
+
+@item s
+Local variable (OS9000).
+
+@item t
+Type name; see @ref{Typedefs}.
+
+@item T
+Enumeration, structure, or union tag; see @ref{Typedefs}.
+
+@item v
+Parameter passed by reference; see @ref{Reference Parameters}.
+
+@item V
+Procedure scope static variable; see @ref{Statics}.
+
+@item x
+Conformant array; see @ref{Conformant Arrays}.
+
+@item X
+Function return variable; see @ref{Parameters}.
+@end table
+
+@node Type Descriptors
+@appendix Table of Type Descriptors
+
+The type descriptor is the character which follows the type number and
+an equals sign. It specifies what kind of type is being defined.
+@xref{String Field}, for more information about their use.
+
+@table @code
+@item @var{digit}
+@itemx (
+Type reference; see @ref{String Field}.
+
+@item -
+Reference to builtin type; see @ref{Negative Type Numbers}.
+
+@item #
+Method (C++); see @ref{Method Type Descriptor}.
+
+@item *
+Pointer; see @ref{Miscellaneous Types}.
+
+@item &
+Reference (C++).
+
+@item @@
+Type Attributes (AIX); see @ref{String Field}. Member (class and variable)
+type (GNU C++); see @ref{Member Type Descriptor}.
+
+@item a
+Array; see @ref{Arrays}.
+
+@item A
+Open array; see @ref{Arrays}.
+
+@item b
+Pascal space type (AIX); see @ref{Miscellaneous Types}. Builtin integer
+type (Sun); see @ref{Builtin Type Descriptors}. Const and volatile
+qualfied type (OS9000).
+
+@item B
+Volatile-qualified type; see @ref{Miscellaneous Types}.
+
+@item c
+Complex builtin type (AIX); see @ref{Builtin Type Descriptors}.
+Const-qualified type (OS9000).
+
+@item C
+COBOL Picture type. See AIX documentation for details.
+
+@item d
+File type; see @ref{Miscellaneous Types}.
+
+@item D
+N-dimensional dynamic array; see @ref{Arrays}.
+
+@item e
+Enumeration type; see @ref{Enumerations}.
+
+@item E
+N-dimensional subarray; see @ref{Arrays}.
+
+@item f
+Function type; see @ref{Function Types}.
+
+@item F
+Pascal function parameter; see @ref{Function Types}
+
+@item g
+Builtin floating point type; see @ref{Builtin Type Descriptors}.
+
+@item G
+COBOL Group. See AIX documentation for details.
+
+@item i
+Imported type (AIX); see @ref{Cross-References}. Volatile-qualified
+type (OS9000).
+
+@item k
+Const-qualified type; see @ref{Miscellaneous Types}.
+
+@item K
+COBOL File Descriptor. See AIX documentation for details.
+
+@item M
+Multiple instance type; see @ref{Miscellaneous Types}.
+
+@item n
+String type; see @ref{Strings}.
+
+@item N
+Stringptr; see @ref{Strings}.
+
+@item o
+Opaque type; see @ref{Typedefs}.
+
+@item p
+Procedure; see @ref{Function Types}.
+
+@item P
+Packed array; see @ref{Arrays}.
+
+@item r
+Range type; see @ref{Subranges}.
+
+@item R
+Builtin floating type; see @ref{Builtin Type Descriptors} (Sun). Pascal
+subroutine parameter; see @ref{Function Types} (AIX). Detecting this
+conflict is possible with careful parsing (hint: a Pascal subroutine
+parameter type will always contain a comma, and a builtin type
+descriptor never will).
+
+@item s
+Structure type; see @ref{Structures}.
+
+@item S
+Set type; see @ref{Miscellaneous Types}.
+
+@item u
+Union; see @ref{Unions}.
+
+@item v
+Variant record. This is a Pascal and Modula-2 feature which is like a
+union within a struct in C. See AIX documentation for details.
+
+@item w
+Wide character; see @ref{Builtin Type Descriptors}.
+
+@item x
+Cross-reference; see @ref{Cross-References}.
+
+@item Y
+Used by IBM's xlC C++ compiler (for structures, I think).
+
+@item z
+gstring; see @ref{Strings}.
+@end table
+
+@node Expanded Reference
+@appendix Expanded Reference by Stab Type
+
+@c FIXME: This appendix should go away; see N_PSYM or N_SO for an example.
+
+For a full list of stab types, and cross-references to where they are
+described, see @ref{Stab Types}. This appendix just covers certain
+stabs which are not yet described in the main body of this document;
+eventually the information will all be in one place.
+
+Format of an entry:
+
+The first line is the symbol type (see @file{include/aout/stab.def}).
+
+The second line describes the language constructs the symbol type
+represents.
+
+The third line is the stab format with the significant stab fields
+named and the rest NIL.
+
+Subsequent lines expand upon the meaning and possible values for each
+significant stab field.
+
+Finally, any further information.
+
+@menu
+* N_PC:: Pascal global symbol
+* N_NSYMS:: Number of symbols
+* N_NOMAP:: No DST map
+* N_M2C:: Modula-2 compilation unit
+* N_BROWS:: Path to .cb file for Sun source code browser
+* N_DEFD:: GNU Modula2 definition module dependency
+* N_EHDECL:: GNU C++ exception variable
+* N_MOD2:: Modula2 information "for imc"
+* N_CATCH:: GNU C++ "catch" clause
+* N_SSYM:: Structure or union element
+* N_SCOPE:: Modula2 scope information (Sun only)
+* Gould:: non-base register symbols used on Gould systems
+* N_LENG:: Length of preceding entry
+@end menu
+
+@node N_PC
+@section N_PC
+
+@deffn @code{.stabs} N_PC
+@findex N_PC
+Global symbol (for Pascal).
+
+@example
+"name" -> "symbol_name" <<?>>
+value -> supposedly the line number (stab.def is skeptical)
+@end example
+
+@display
+@file{stabdump.c} says:
+
+global pascal symbol: name,,0,subtype,line
+<< subtype? >>
+@end display
+@end deffn
+
+@node N_NSYMS
+@section N_NSYMS
+
+@deffn @code{.stabn} N_NSYMS
+@findex N_NSYMS
+Number of symbols (according to Ultrix V4.0).
+
+@display
+ 0, files,,funcs,lines (stab.def)
+@end display
+@end deffn
+
+@node N_NOMAP
+@section N_NOMAP
+
+@deffn @code{.stabs} N_NOMAP
+@findex N_NOMAP
+No DST map for symbol (according to Ultrix V4.0). I think this means a
+variable has been optimized out.
+
+@display
+ name, ,0,type,ignored (stab.def)
+@end display
+@end deffn
+
+@node N_M2C
+@section N_M2C
+
+@deffn @code{.stabs} N_M2C
+@findex N_M2C
+Modula-2 compilation unit.
+
+@example
+"string" -> "unit_name,unit_time_stamp[,code_time_stamp]"
+desc -> unit_number
+value -> 0 (main unit)
+ 1 (any other unit)
+@end example
+
+See @cite{Dbx and Dbxtool Interfaces}, 2nd edition, by Sun, 1988, for
+more information.
+
+@end deffn
+
+@node N_BROWS
+@section N_BROWS
+
+@deffn @code{.stabs} N_BROWS
+@findex N_BROWS
+Sun source code browser, path to @file{.cb} file
+
+<<?>>
+"path to associated @file{.cb} file"
+
+Note: N_BROWS has the same value as N_BSLINE.
+@end deffn
+
+@node N_DEFD
+@section N_DEFD
+
+@deffn @code{.stabn} N_DEFD
+@findex N_DEFD
+GNU Modula2 definition module dependency.
+
+GNU Modula-2 definition module dependency. The value is the
+modification time of the definition file. The other field is non-zero
+if it is imported with the GNU M2 keyword @code{%INITIALIZE}. Perhaps
+@code{N_M2C} can be used if there are enough empty fields?
+@end deffn
+
+@node N_EHDECL
+@section N_EHDECL
+
+@deffn @code{.stabs} N_EHDECL
+@findex N_EHDECL
+GNU C++ exception variable <<?>>.
+
+"@var{string} is variable name"
+
+Note: conflicts with @code{N_MOD2}.
+@end deffn
+
+@node N_MOD2
+@section N_MOD2
+
+@deffn @code{.stab?} N_MOD2
+@findex N_MOD2
+Modula2 info "for imc" (according to Ultrix V4.0)
+
+Note: conflicts with @code{N_EHDECL} <<?>>
+@end deffn
+
+@node N_CATCH
+@section N_CATCH
+
+@deffn @code{.stabn} N_CATCH
+@findex N_CATCH
+GNU C++ @code{catch} clause
+
+GNU C++ @code{catch} clause. The value is its address. The desc field
+is nonzero if this entry is immediately followed by a @code{CAUGHT} stab
+saying what exception was caught. Multiple @code{CAUGHT} stabs means
+that multiple exceptions can be caught here. If desc is 0, it means all
+exceptions are caught here.
+@end deffn
+
+@node N_SSYM
+@section N_SSYM
+
+@deffn @code{.stabn} N_SSYM
+@findex N_SSYM
+Structure or union element.
+
+The value is the offset in the structure.
+
+<<?looking at structs and unions in C I didn't see these>>
+@end deffn
+
+@node N_SCOPE
+@section N_SCOPE
+
+@deffn @code{.stab?} N_SCOPE
+@findex N_SCOPE
+Modula2 scope information (Sun linker)
+<<?>>
+@end deffn
+
+@node Gould
+@section Non-base registers on Gould systems
+
+@deffn @code{.stab?} N_NBTEXT
+@deffnx @code{.stab?} N_NBDATA
+@deffnx @code{.stab?} N_NBBSS
+@deffnx @code{.stab?} N_NBSTS
+@deffnx @code{.stab?} N_NBLCS
+@findex N_NBTEXT
+@findex N_NBDATA
+@findex N_NBBSS
+@findex N_NBSTS
+@findex N_NBLCS
+These are used on Gould systems for non-base registers syms.
+
+However, the following values are not the values used by Gould; they are
+the values which GNU has been documenting for these values for a long
+time, without actually checking what Gould uses. I include these values
+only because perhaps some someone actually did something with the GNU
+information (I hope not, why GNU knowingly assigned wrong values to
+these in the header file is a complete mystery to me).
+
+@example
+240 0xf0 N_NBTEXT ??
+242 0xf2 N_NBDATA ??
+244 0xf4 N_NBBSS ??
+246 0xf6 N_NBSTS ??
+248 0xf8 N_NBLCS ??
+@end example
+@end deffn
+
+@node N_LENG
+@section N_LENG
+
+@deffn @code{.stabn} N_LENG
+@findex N_LENG
+Second symbol entry containing a length-value for the preceding entry.
+The value is the length.
+@end deffn
+
+@node Questions
+@appendix Questions and Anomalies
+
+@itemize @bullet
+@item
+@c I think this is changed in GCC 2.4.5 to put the line number there.
+For GNU C stabs defining local and global variables (@code{N_LSYM} and
+@code{N_GSYM}), the desc field is supposed to contain the source
+line number on which the variable is defined. In reality the desc
+field is always 0. (This behavior is defined in @file{dbxout.c} and
+putting a line number in desc is controlled by @samp{#ifdef
+WINNING_GDB}, which defaults to false). GDB supposedly uses this
+information if you say @samp{list @var{var}}. In reality, @var{var} can
+be a variable defined in the program and GDB says @samp{function
+@var{var} not defined}.
+
+@item
+In GNU C stabs, there seems to be no way to differentiate tag types:
+structures, unions, and enums (symbol descriptor @samp{T}) and typedefs
+(symbol descriptor @samp{t}) defined at file scope from types defined locally
+to a procedure or other more local scope. They all use the @code{N_LSYM}
+stab type. Types defined at procedure scope are emited after the
+@code{N_RBRAC} of the preceding function and before the code of the
+procedure in which they are defined. This is exactly the same as
+types defined in the source file between the two procedure bodies.
+GDB overcompensates by placing all types in block #1, the block for
+symbols of file scope. This is true for default, @samp{-ansi} and
+@samp{-traditional} compiler options. (Bugs gcc/1063, gdb/1066.)
+
+@item
+What ends the procedure scope? Is it the proc block's @code{N_RBRAC} or the
+next @code{N_FUN}? (I believe its the first.)
+@end itemize
+
+@node Sun Differences
+@appendix Differences Between GNU Stabs and Sun Native Stabs
+
+@c FIXME: Merge all this stuff into the main body of the document.
+
+@itemize @bullet
+@item
+GNU C stabs define @emph{all} types, file or procedure scope, as
+@code{N_LSYM}. Sun doc talks about using @code{N_GSYM} too.
+
+@item
+Sun C stabs use type number pairs in the format
+(@var{file-number},@var{type-number}) where @var{file-number} is a
+number starting with 1 and incremented for each sub-source file in the
+compilation. @var{type-number} is a number starting with 1 and
+incremented for each new type defined in the compilation. GNU C stabs
+use the type number alone, with no source file number.
+@end itemize
+
+@node Stab Sections
+@appendix Using Stabs in Their Own Sections
+
+Many object file formats allow tools to create object files with custom
+sections containing any arbitrary data. For any such object file
+format, stabs can be embedded in special sections. This is how stabs
+are used with ELF and SOM, and aside from ECOFF and XCOFF, is how stabs
+are used with COFF.
+
+@menu
+* Stab Section Basics:: How to embed stabs in sections
+* ELF Linker Relocation:: Sun ELF hacks
+@end menu
+
+@node Stab Section Basics
+@appendixsec How to Embed Stabs in Sections
+
+The assembler creates two custom sections, a section named @code{.stab}
+which contains an array of fixed length structures, one struct per stab,
+and a section named @code{.stabstr} containing all the variable length
+strings that are referenced by stabs in the @code{.stab} section. The
+byte order of the stabs binary data depends on the object file format.
+For ELF, it matches the byte order of the ELF file itself, as determined
+from the @code{EI_DATA} field in the @code{e_ident} member of the ELF
+header. For SOM, it is always big-endian (is this true??? FIXME). For
+COFF, it matches the byte order of the COFF headers. The meaning of the
+fields is the same as for a.out (@pxref{Symbol Table Format}), except
+that the @code{n_strx} field is relative to the strings for the current
+compilation unit (which can be found using the synthetic N_UNDF stab
+described below), rather than the entire string table.
+
+The first stab in the @code{.stab} section for each compilation unit is
+synthetic, generated entirely by the assembler, with no corresponding
+@code{.stab} directive as input to the assembler. This stab contains
+the following fields:
+
+@table @code
+@item n_strx
+Offset in the @code{.stabstr} section to the source filename.
+
+@item n_type
+@code{N_UNDF}.
+
+@item n_other
+Unused field, always zero.
+This may eventually be used to hold overflows from the count in
+the @code{n_desc} field.
+
+@item n_desc
+Count of upcoming symbols, i.e., the number of remaining stabs for this
+source file.
+
+@item n_value
+Size of the string table fragment associated with this source file, in
+bytes.
+@end table
+
+The @code{.stabstr} section always starts with a null byte (so that string
+offsets of zero reference a null string), followed by random length strings,
+each of which is null byte terminated.
+
+The ELF section header for the @code{.stab} section has its
+@code{sh_link} member set to the section number of the @code{.stabstr}
+section, and the @code{.stabstr} section has its ELF section
+header @code{sh_type} member set to @code{SHT_STRTAB} to mark it as a
+string table. SOM and COFF have no way of linking the sections together
+or marking them as string tables.
+
+For COFF, the @code{.stab} and @code{.stabstr} sections are simply
+concatenated by the linker. GDB then uses the @code{n_desc} fields to
+figure out the extent of the original sections. Similarly, the
+@code{n_value} fields of the header symbols are added together in order
+to get the actual position of the strings in a desired @code{.stabstr}
+section. Although this design obviates any need for the linker to relocate
+or otherwise manipulate @code{.stab} and @code{.stabstr} sections, it also
+requires some care to ensure that the offsets are calculated correctly.
+For instance, if the linker were to pad in between the @code{.stabstr}
+sections before concatenating, then the offsets to strings in the middle
+of the executable's @code{.stabstr} section would be wrong.
+
+@node ELF Linker Relocation
+@appendixsec Having the Linker Relocate Stabs in ELF
+
+This section describes some Sun hacks for Stabs in ELF; it does not
+apply to COFF or SOM.
+
+To keep linking fast, you don't want the linker to have to relocate very
+many stabs. Making sure this is done for @code{N_SLINE},
+@code{N_RBRAC}, and @code{N_LBRAC} stabs is the most important thing
+(see the descriptions of those stabs for more information). But Sun's
+stabs in ELF has taken this further, to make all addresses in the
+@code{n_value} field (functions and static variables) relative to the
+source file. For the @code{N_SO} symbol itself, Sun simply omits the
+address. To find the address of each section corresponding to a given
+source file, the compiler puts out symbols giving the address of each
+section for a given source file. Since these are ELF (not stab)
+symbols, the linker relocates them correctly without having to touch the
+stabs section. They are named @code{Bbss.bss} for the bss section,
+@code{Ddata.data} for the data section, and @code{Drodata.rodata} for
+the rodata section. For the text section, there is no such symbol (but
+there should be, see below). For an example of how these symbols work,
+@xref{Stab Section Transformations}. GCC does not provide these symbols;
+it instead relies on the stabs getting relocated. Thus addresses which
+would normally be relative to @code{Bbss.bss}, etc., are already
+relocated. The Sun linker provided with Solaris 2.2 and earlier
+relocates stabs using normal ELF relocation information, as it would do
+for any section. Sun has been threatening to kludge their linker to not
+do this (to speed up linking), even though the correct way to avoid
+having the linker do these relocations is to have the compiler no longer
+output relocatable values. Last I heard they had been talked out of the
+linker kludge. See Sun point patch 101052-01 and Sun bug 1142109. With
+the Sun compiler this affects @samp{S} symbol descriptor stabs
+(@pxref{Statics}) and functions (@pxref{Procedures}). In the latter
+case, to adopt the clean solution (making the value of the stab relative
+to the start of the compilation unit), it would be necessary to invent a
+@code{Ttext.text} symbol, analogous to the @code{Bbss.bss}, etc.,
+symbols. I recommend this rather than using a zero value and getting
+the address from the ELF symbols.
+
+Finding the correct @code{Bbss.bss}, etc., symbol is difficult, because
+the linker simply concatenates the @code{.stab} sections from each
+@file{.o} file without including any information about which part of a
+@code{.stab} section comes from which @file{.o} file. The way GDB does
+this is to look for an ELF @code{STT_FILE} symbol which has the same
+name as the last component of the file name from the @code{N_SO} symbol
+in the stabs (for example, if the file name is @file{../../gdb/main.c},
+it looks for an ELF @code{STT_FILE} symbol named @code{main.c}). This
+loses if different files have the same name (they could be in different
+directories, a library could have been copied from one system to
+another, etc.). It would be much cleaner to have the @code{Bbss.bss}
+symbols in the stabs themselves. Having the linker relocate them there
+is no more work than having the linker relocate ELF symbols, and it
+solves the problem of having to associate the ELF and stab symbols.
+However, no one has yet designed or implemented such a scheme.
+
+@node Symbol Types Index
+@unnumbered Symbol Types Index
+
+@printindex fn
+
+@contents
+@bye
diff --git a/contrib/gdb/gdb/dwarfread.c b/contrib/gdb/gdb/dwarfread.c
new file mode 100644
index 0000000..ed82009
--- /dev/null
+++ b/contrib/gdb/gdb/dwarfread.c
@@ -0,0 +1,3883 @@
+/* DWARF debugging format support for GDB.
+ Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996
+ 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.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+
+FIXME: Do we need to generate dependencies in partial symtabs?
+(Perhaps we don't need to).
+
+FIXME: Resolve minor differences between what information we put in the
+partial symbol table and what dbxread puts in. For example, we don't yet
+put enum constants there. And dbxread seems to invent a lot of typedefs
+we never see. Use the new printpsym command to see the partial symbol table
+contents.
+
+FIXME: Figure out a better way to tell gdb about the name of the function
+contain the user's entry point (I.E. main())
+
+FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for
+other things to work on, if you get bored. :-)
+
+*/
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "elf/dwarf.h"
+#include "buildsym.h"
+#include "demangle.h"
+#include "expression.h" /* Needed for enum exp_opcode in language.h, sigh... */
+#include "language.h"
+#include "complaints.h"
+
+#include <fcntl.h>
+#include "gdb_string.h"
+
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+
+/* Some macros to provide DIE info for complaints. */
+
+#define DIE_ID (curdie!=NULL ? curdie->die_ref : 0)
+#define DIE_NAME (curdie!=NULL && curdie->at_name!=NULL) ? curdie->at_name : ""
+
+/* Complaints that can be issued during DWARF debug info reading. */
+
+struct complaint no_bfd_get_N =
+{
+ "DIE @ 0x%x \"%s\", no bfd support for %d byte data object", 0, 0
+};
+
+struct complaint malformed_die =
+{
+ "DIE @ 0x%x \"%s\", malformed DIE, bad length (%d bytes)", 0, 0
+};
+
+struct complaint bad_die_ref =
+{
+ "DIE @ 0x%x \"%s\", reference to DIE (0x%x) outside compilation unit", 0, 0
+};
+
+struct complaint unknown_attribute_form =
+{
+ "DIE @ 0x%x \"%s\", unknown attribute form (0x%x)", 0, 0
+};
+
+struct complaint unknown_attribute_length =
+{
+ "DIE @ 0x%x \"%s\", unknown attribute length, skipped remaining attributes", 0, 0
+};
+
+struct complaint unexpected_fund_type =
+{
+ "DIE @ 0x%x \"%s\", unexpected fundamental type 0x%x", 0, 0
+};
+
+struct complaint unknown_type_modifier =
+{
+ "DIE @ 0x%x \"%s\", unknown type modifier %u", 0, 0
+};
+
+struct complaint volatile_ignored =
+{
+ "DIE @ 0x%x \"%s\", type modifier 'volatile' ignored", 0, 0
+};
+
+struct complaint const_ignored =
+{
+ "DIE @ 0x%x \"%s\", type modifier 'const' ignored", 0, 0
+};
+
+struct complaint botched_modified_type =
+{
+ "DIE @ 0x%x \"%s\", botched modified type decoding (mtype 0x%x)", 0, 0
+};
+
+struct complaint op_deref2 =
+{
+ "DIE @ 0x%x \"%s\", OP_DEREF2 address 0x%x not handled", 0, 0
+};
+
+struct complaint op_deref4 =
+{
+ "DIE @ 0x%x \"%s\", OP_DEREF4 address 0x%x not handled", 0, 0
+};
+
+struct complaint basereg_not_handled =
+{
+ "DIE @ 0x%x \"%s\", BASEREG %d not handled", 0, 0
+};
+
+struct complaint dup_user_type_allocation =
+{
+ "DIE @ 0x%x \"%s\", internal error: duplicate user type allocation", 0, 0
+};
+
+struct complaint dup_user_type_definition =
+{
+ "DIE @ 0x%x \"%s\", internal error: duplicate user type definition", 0, 0
+};
+
+struct complaint missing_tag =
+{
+ "DIE @ 0x%x \"%s\", missing class, structure, or union tag", 0, 0
+};
+
+struct complaint bad_array_element_type =
+{
+ "DIE @ 0x%x \"%s\", bad array element type attribute 0x%x", 0, 0
+};
+
+struct complaint subscript_data_items =
+{
+ "DIE @ 0x%x \"%s\", can't decode subscript data items", 0, 0
+};
+
+struct complaint unhandled_array_subscript_format =
+{
+ "DIE @ 0x%x \"%s\", array subscript format 0x%x not handled yet", 0, 0
+};
+
+struct complaint unknown_array_subscript_format =
+{
+ "DIE @ 0x%x \"%s\", unknown array subscript format %x", 0, 0
+};
+
+struct complaint not_row_major =
+{
+ "DIE @ 0x%x \"%s\", array not row major; not handled correctly", 0, 0
+};
+
+struct complaint missing_at_name =
+{
+ "DIE @ 0x%x, AT_name tag missing", 0, 0
+};
+
+typedef unsigned int DIE_REF; /* Reference to a DIE */
+
+#ifndef GCC_PRODUCER
+#define GCC_PRODUCER "GNU C "
+#endif
+
+#ifndef GPLUS_PRODUCER
+#define GPLUS_PRODUCER "GNU C++ "
+#endif
+
+#ifndef LCC_PRODUCER
+#define LCC_PRODUCER "NCR C/C++"
+#endif
+
+#ifndef CHILL_PRODUCER
+#define CHILL_PRODUCER "GNU Chill "
+#endif
+
+/* Provide a default mapping from a DWARF register number to a gdb REGNUM. */
+#ifndef DWARF_REG_TO_REGNUM
+#define DWARF_REG_TO_REGNUM(num) (num)
+#endif
+
+/* Flags to target_to_host() that tell whether or not the data object is
+ expected to be signed. Used, for example, when fetching a signed
+ integer in the target environment which is used as a signed integer
+ in the host environment, and the two environments have different sized
+ ints. In this case, *somebody* has to sign extend the smaller sized
+ int. */
+
+#define GET_UNSIGNED 0 /* No sign extension required */
+#define GET_SIGNED 1 /* Sign extension required */
+
+/* Defines for things which are specified in the document "DWARF Debugging
+ Information Format" published by UNIX International, Programming Languages
+ SIG. These defines are based on revision 1.0.0, Jan 20, 1992. */
+
+#define SIZEOF_DIE_LENGTH 4
+#define SIZEOF_DIE_TAG 2
+#define SIZEOF_ATTRIBUTE 2
+#define SIZEOF_FORMAT_SPECIFIER 1
+#define SIZEOF_FMT_FT 2
+#define SIZEOF_LINETBL_LENGTH 4
+#define SIZEOF_LINETBL_LINENO 4
+#define SIZEOF_LINETBL_STMT 2
+#define SIZEOF_LINETBL_DELTA 4
+#define SIZEOF_LOC_ATOM_CODE 1
+
+#define FORM_FROM_ATTR(attr) ((attr) & 0xF) /* Implicitly specified */
+
+/* Macros that return the sizes of various types of data in the target
+ environment.
+
+ FIXME: Currently these are just compile time constants (as they are in
+ other parts of gdb as well). They need to be able to get the right size
+ either from the bfd or possibly from the DWARF info. It would be nice if
+ the DWARF producer inserted DIES that describe the fundamental types in
+ the target environment into the DWARF info, similar to the way dbx stabs
+ producers produce information about their fundamental types. */
+
+#define TARGET_FT_POINTER_SIZE(objfile) (TARGET_PTR_BIT / TARGET_CHAR_BIT)
+#define TARGET_FT_LONG_SIZE(objfile) (TARGET_LONG_BIT / TARGET_CHAR_BIT)
+
+/* The Amiga SVR4 header file <dwarf.h> defines AT_element_list as a
+ FORM_BLOCK2, and this is the value emitted by the AT&T compiler.
+ However, the Issue 2 DWARF specification from AT&T defines it as
+ a FORM_BLOCK4, as does the latest specification from UI/PLSIG.
+ For backwards compatibility with the AT&T compiler produced executables
+ we define AT_short_element_list for this variant. */
+
+#define AT_short_element_list (0x00f0|FORM_BLOCK2)
+
+/* External variables referenced. */
+
+extern int info_verbose; /* From main.c; nonzero => verbose */
+extern char *warning_pre_print; /* From utils.c */
+
+/* The DWARF debugging information consists of two major pieces,
+ one is a block of DWARF Information Entries (DIE's) and the other
+ is a line number table. The "struct dieinfo" structure contains
+ the information for a single DIE, the one currently being processed.
+
+ In order to make it easier to randomly access the attribute fields
+ of the current DIE, which are specifically unordered within the DIE,
+ each DIE is scanned and an instance of the "struct dieinfo"
+ structure is initialized.
+
+ Initialization is done in two levels. The first, done by basicdieinfo(),
+ just initializes those fields that are vital to deciding whether or not
+ to use this DIE, how to skip past it, etc. The second, done by the
+ function completedieinfo(), fills in the rest of the information.
+
+ Attributes which have block forms are not interpreted at the time
+ the DIE is scanned, instead we just save pointers to the start
+ of their value fields.
+
+ Some fields have a flag <name>_p that is set when the value of the
+ field is valid (I.E. we found a matching attribute in the DIE). Since
+ we may want to test for the presence of some attributes in the DIE,
+ such as AT_low_pc, without restricting the values of the field,
+ we need someway to note that we found such an attribute.
+
+ */
+
+typedef char BLOCK;
+
+struct dieinfo {
+ char * die; /* Pointer to the raw DIE data */
+ unsigned long die_length; /* Length of the raw DIE data */
+ DIE_REF die_ref; /* Offset of this DIE */
+ unsigned short die_tag; /* Tag for this DIE */
+ unsigned long at_padding;
+ unsigned long at_sibling;
+ BLOCK * at_location;
+ char * at_name;
+ unsigned short at_fund_type;
+ BLOCK * at_mod_fund_type;
+ unsigned long at_user_def_type;
+ BLOCK * at_mod_u_d_type;
+ unsigned short at_ordering;
+ BLOCK * at_subscr_data;
+ unsigned long at_byte_size;
+ unsigned short at_bit_offset;
+ unsigned long at_bit_size;
+ BLOCK * at_element_list;
+ unsigned long at_stmt_list;
+ CORE_ADDR at_low_pc;
+ CORE_ADDR at_high_pc;
+ unsigned long at_language;
+ unsigned long at_member;
+ unsigned long at_discr;
+ BLOCK * at_discr_value;
+ BLOCK * at_string_length;
+ char * at_comp_dir;
+ char * at_producer;
+ unsigned long at_start_scope;
+ unsigned long at_stride_size;
+ unsigned long at_src_info;
+ char * at_prototyped;
+ unsigned int has_at_low_pc:1;
+ unsigned int has_at_stmt_list:1;
+ unsigned int has_at_byte_size:1;
+ unsigned int short_element_list:1;
+};
+
+static int diecount; /* Approximate count of dies for compilation unit */
+static struct dieinfo *curdie; /* For warnings and such */
+
+static char *dbbase; /* Base pointer to dwarf info */
+static int dbsize; /* Size of dwarf info in bytes */
+static int dbroff; /* Relative offset from start of .debug section */
+static char *lnbase; /* Base pointer to line section */
+static int isreg; /* Kludge to identify register variables */
+static int optimized_out; /* Kludge to identify optimized out variables */
+/* Kludge to identify basereg references. Nonzero if we have an offset
+ relative to a basereg. */
+static int offreg;
+/* Which base register is it relative to? */
+static int basereg;
+
+/* This value is added to each symbol value. FIXME: Generalize to
+ the section_offsets structure used by dbxread (once this is done,
+ pass the appropriate section number to end_symtab). */
+static CORE_ADDR baseaddr; /* Add to each symbol value */
+
+/* The section offsets used in the current psymtab or symtab. FIXME,
+ only used to pass one value (baseaddr) at the moment. */
+static struct section_offsets *base_section_offsets;
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct dwfinfo {
+ /* Always the absolute file offset to the start of the ".debug"
+ section for the file containing the DIE's being accessed. */
+ file_ptr dbfoff;
+ /* Relative offset from the start of the ".debug" section to the
+ first DIE to be accessed. When building the partial symbol
+ table, this value will be zero since we are accessing the
+ entire ".debug" section. When expanding a partial symbol
+ table entry, this value will be the offset to the first
+ DIE for the compilation unit containing the symbol that
+ triggers the expansion. */
+ int dbroff;
+ /* The size of the chunk of DIE's being examined, in bytes. */
+ int dblength;
+ /* The absolute file offset to the line table fragment. Ignored
+ when building partial symbol tables, but used when expanding
+ them, and contains the absolute file offset to the fragment
+ of the ".line" section containing the line numbers for the
+ current compilation unit. */
+ file_ptr lnfoff;
+};
+
+#define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)
+#define DBROFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbroff)
+#define DBLENGTH(p) (((struct dwfinfo *)((p)->read_symtab_private))->dblength)
+#define LNFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->lnfoff)
+
+/* The generic symbol table building routines have separate lists for
+ file scope symbols and all all other scopes (local scopes). So
+ we need to select the right one to pass to add_symbol_to_list().
+ We do it by keeping a pointer to the correct list in list_in_scope.
+
+ FIXME: The original dwarf code just treated the file scope as the first
+ local scope, and all other local scopes as nested local scopes, and worked
+ fine. Check to see if we really need to distinguish these in buildsym.c */
+
+struct pending **list_in_scope = &file_symbols;
+
+/* DIES which have user defined types or modified user defined types refer to
+ other DIES for the type information. Thus we need to associate the offset
+ of a DIE for a user defined type with a pointer to the type information.
+
+ Originally this was done using a simple but expensive algorithm, with an
+ array of unsorted structures, each containing an offset/type-pointer pair.
+ This array was scanned linearly each time a lookup was done. The result
+ was that gdb was spending over half it's startup time munging through this
+ array of pointers looking for a structure that had the right offset member.
+
+ The second attempt used the same array of structures, but the array was
+ sorted using qsort each time a new offset/type was recorded, and a binary
+ search was used to find the type pointer for a given DIE offset. This was
+ even slower, due to the overhead of sorting the array each time a new
+ offset/type pair was entered.
+
+ The third attempt uses a fixed size array of type pointers, indexed by a
+ value derived from the DIE offset. Since the minimum DIE size is 4 bytes,
+ we can divide any DIE offset by 4 to obtain a unique index into this fixed
+ size array. Since each element is a 4 byte pointer, it takes exactly as
+ much memory to hold this array as to hold the DWARF info for a given
+ compilation unit. But it gets freed as soon as we are done with it.
+ This has worked well in practice, as a reasonable tradeoff between memory
+ consumption and speed, without having to resort to much more complicated
+ algorithms. */
+
+static struct type **utypes; /* Pointer to array of user type pointers */
+static int numutypes; /* Max number of user type pointers */
+
+/* Maintain an array of referenced fundamental types for the current
+ compilation unit being read. For DWARF version 1, we have to construct
+ the fundamental types on the fly, since no information about the
+ fundamental types is supplied. Each such fundamental type is created by
+ calling a language dependent routine to create the type, and then a
+ pointer to that type is then placed in the array at the index specified
+ by it's FT_<TYPENAME> value. The array has a fixed size set by the
+ FT_NUM_MEMBERS compile time constant, which is the number of predefined
+ fundamental types gdb knows how to construct. */
+
+static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */
+
+/* Record the language for the compilation unit which is currently being
+ processed. We know it once we have seen the TAG_compile_unit DIE,
+ and we need it while processing the DIE's for that compilation unit.
+ It is eventually saved in the symtab structure, but we don't finalize
+ the symtab struct until we have processed all the DIE's for the
+ compilation unit. We also need to get and save a pointer to the
+ language struct for this language, so we can call the language
+ dependent routines for doing things such as creating fundamental
+ types. */
+
+static enum language cu_language;
+static const struct language_defn *cu_language_defn;
+
+/* Forward declarations of static functions so we don't have to worry
+ about ordering within this file. */
+
+static int
+attribute_size PARAMS ((unsigned int));
+
+static CORE_ADDR
+target_to_host PARAMS ((char *, int, int, struct objfile *));
+
+static void
+add_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+handle_producer PARAMS ((char *));
+
+static void
+read_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static void
+read_func_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static void
+read_lexical_block_scope PARAMS ((struct dieinfo *, char *, char *,
+ struct objfile *));
+
+static void
+scan_partial_symbols PARAMS ((char *, char *, struct objfile *));
+
+static void
+scan_compilation_units PARAMS ((char *, char *, file_ptr,
+ file_ptr, struct objfile *));
+
+static void
+add_partial_symbol PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+basicdieinfo PARAMS ((struct dieinfo *, char *, struct objfile *));
+
+static void
+completedieinfo PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+dwarf_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+static void
+psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static void
+read_ofile_symtab PARAMS ((struct partial_symtab *));
+
+static void
+process_dies PARAMS ((char *, char *, struct objfile *));
+
+static void
+read_structure_scope PARAMS ((struct dieinfo *, char *, char *,
+ struct objfile *));
+
+static struct type *
+decode_array_element_type PARAMS ((char *));
+
+static struct type *
+decode_subscript_data_item PARAMS ((char *, char *));
+
+static void
+dwarf_read_array_type PARAMS ((struct dieinfo *));
+
+static void
+read_tag_pointer_type PARAMS ((struct dieinfo *dip));
+
+static void
+read_tag_string_type PARAMS ((struct dieinfo *dip));
+
+static void
+read_subroutine_type PARAMS ((struct dieinfo *, char *, char *));
+
+static void
+read_enumeration PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static struct type *
+struct_type PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
+
+static struct type *
+enum_type PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+decode_line_numbers PARAMS ((char *));
+
+static struct type *
+decode_die_type PARAMS ((struct dieinfo *));
+
+static struct type *
+decode_mod_fund_type PARAMS ((char *));
+
+static struct type *
+decode_mod_u_d_type PARAMS ((char *));
+
+static struct type *
+decode_modified_type PARAMS ((char *, unsigned int, int));
+
+static struct type *
+decode_fund_type PARAMS ((unsigned int));
+
+static char *
+create_name PARAMS ((char *, struct obstack *));
+
+static struct type *
+lookup_utype PARAMS ((DIE_REF));
+
+static struct type *
+alloc_utype PARAMS ((DIE_REF, struct type *));
+
+static struct symbol *
+new_symbol PARAMS ((struct dieinfo *, struct objfile *));
+
+static void
+synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *,
+ struct type *));
+
+static int
+locval PARAMS ((char *));
+
+static void
+set_cu_language PARAMS ((struct dieinfo *));
+
+static struct type *
+dwarf_fundamental_type PARAMS ((struct objfile *, int));
+
+
+/*
+
+LOCAL FUNCTION
+
+ dwarf_fundamental_type -- lookup or create a fundamental type
+
+SYNOPSIS
+
+ struct type *
+ dwarf_fundamental_type (struct objfile *objfile, int typeid)
+
+DESCRIPTION
+
+ DWARF version 1 doesn't supply any fundamental type information,
+ so gdb has to construct such types. It has a fixed number of
+ fundamental types that it knows how to construct, which is the
+ union of all types that it knows how to construct for all languages
+ that it knows about. These are enumerated in gdbtypes.h.
+
+ As an example, assume we find a DIE that references a DWARF
+ fundamental type of FT_integer. We first look in the ftypes
+ array to see if we already have such a type, indexed by the
+ gdb internal value of FT_INTEGER. If so, we simply return a
+ pointer to that type. If not, then we ask an appropriate
+ language dependent routine to create a type FT_INTEGER, using
+ defaults reasonable for the current target machine, and install
+ that type in ftypes for future reference.
+
+RETURNS
+
+ Pointer to a fundamental type.
+
+*/
+
+static struct type *
+dwarf_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
+ {
+ error ("internal error - invalid fundamental type id %d", typeid);
+ }
+
+ /* Look for this particular type in the fundamental type vector. If one is
+ not found, create and install one appropriate for the current language
+ and the current target machine. */
+
+ if (ftypes[typeid] == NULL)
+ {
+ ftypes[typeid] = cu_language_defn -> la_fund_type(objfile, typeid);
+ }
+
+ return (ftypes[typeid]);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ set_cu_language -- set local copy of language for compilation unit
+
+SYNOPSIS
+
+ void
+ set_cu_language (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Decode the language attribute for a compilation unit DIE and
+ remember what the language was. We use this at various times
+ when processing DIE's for a given compilation unit.
+
+RETURNS
+
+ No return value.
+
+ */
+
+static void
+set_cu_language (dip)
+ struct dieinfo *dip;
+{
+ switch (dip -> at_language)
+ {
+ case LANG_C89:
+ case LANG_C:
+ cu_language = language_c;
+ break;
+ case LANG_C_PLUS_PLUS:
+ cu_language = language_cplus;
+ break;
+ case LANG_CHILL:
+ cu_language = language_chill;
+ break;
+ case LANG_MODULA2:
+ cu_language = language_m2;
+ break;
+ case LANG_ADA83:
+ case LANG_COBOL74:
+ case LANG_COBOL85:
+ case LANG_FORTRAN77:
+ case LANG_FORTRAN90:
+ case LANG_PASCAL83:
+ /* We don't know anything special about these yet. */
+ cu_language = language_unknown;
+ break;
+ default:
+ /* If no at_language, try to deduce one from the filename */
+ cu_language = deduce_language_from_filename (dip -> at_name);
+ break;
+ }
+ cu_language_defn = language_def (cu_language);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ dwarf_build_psymtabs -- build partial symtabs from DWARF debug info
+
+SYNOPSIS
+
+ void dwarf_build_psymtabs (struct objfile *objfile,
+ struct section_offsets *section_offsets,
+ int mainline, file_ptr dbfoff, unsigned int dbfsize,
+ file_ptr lnoffset, unsigned int lnsize)
+
+DESCRIPTION
+
+ This function is called upon to build partial symtabs from files
+ containing DIE's (Dwarf Information Entries) and DWARF line numbers.
+
+ It is passed a bfd* containing the DIES
+ and line number information, the corresponding filename for that
+ file, a base address for relocating the symbols, a flag indicating
+ whether or not this debugging information is from a "main symbol
+ table" rather than a shared library or dynamically linked file,
+ and file offset/size pairs for the DIE information and line number
+ information.
+
+RETURNS
+
+ No return value.
+
+ */
+
+void
+dwarf_build_psymtabs (objfile, section_offsets, mainline, dbfoff, dbfsize,
+ lnoffset, lnsize)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+ file_ptr dbfoff;
+ unsigned int dbfsize;
+ file_ptr lnoffset;
+ unsigned int lnsize;
+{
+ bfd *abfd = objfile->obfd;
+ struct cleanup *back_to;
+
+ current_objfile = objfile;
+ dbsize = dbfsize;
+ dbbase = xmalloc (dbsize);
+ dbroff = 0;
+ if ((bfd_seek (abfd, dbfoff, SEEK_SET) != 0) ||
+ (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
+ {
+ free (dbbase);
+ error ("can't read DWARF data from '%s'", bfd_get_filename (abfd));
+ }
+ back_to = make_cleanup (free, dbbase);
+
+ /* If we are reinitializing, or if we have never loaded syms yet, init.
+ Since we have no idea how many DIES we are looking at, we just guess
+ some arbitrary value. */
+
+ if (mainline || objfile -> global_psymbols.size == 0 ||
+ objfile -> static_psymbols.size == 0)
+ {
+ init_psymbol_list (objfile, 1024);
+ }
+
+ /* Save the relocation factor where everybody can see it. */
+
+ base_section_offsets = section_offsets;
+ baseaddr = ANOFFSET (section_offsets, 0);
+
+ /* Follow the compilation unit sibling chain, building a partial symbol
+ table entry for each one. Save enough information about each compilation
+ unit to locate the full DWARF information later. */
+
+ scan_compilation_units (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile);
+
+ do_cleanups (back_to);
+ current_objfile = NULL;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_lexical_block_scope -- process all dies in a lexical block
+
+SYNOPSIS
+
+ static void read_lexical_block_scope (struct dieinfo *dip,
+ char *thisdie, char *enddie)
+
+DESCRIPTION
+
+ Process all the DIES contained within a lexical block scope.
+ Start a new scope, process the dies, and then close the scope.
+
+ */
+
+static void
+read_lexical_block_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+
+ push_context (0, dip -> at_low_pc);
+ process_dies (thisdie + dip -> die_length, enddie, objfile);
+ new = pop_context ();
+ if (local_symbols != NULL)
+ {
+ finish_block (0, &local_symbols, new -> old_blocks, new -> start_addr,
+ dip -> at_high_pc, objfile);
+ }
+ local_symbols = new -> locals;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ lookup_utype -- look up a user defined type from die reference
+
+SYNOPSIS
+
+ static type *lookup_utype (DIE_REF die_ref)
+
+DESCRIPTION
+
+ Given a DIE reference, lookup the user defined type associated with
+ that DIE, if it has been registered already. If not registered, then
+ return NULL. Alloc_utype() can be called to register an empty
+ type for this reference, which will be filled in later when the
+ actual referenced DIE is processed.
+ */
+
+static struct type *
+lookup_utype (die_ref)
+ DIE_REF die_ref;
+{
+ struct type *type = NULL;
+ int utypeidx;
+
+ utypeidx = (die_ref - dbroff) / 4;
+ if ((utypeidx < 0) || (utypeidx >= numutypes))
+ {
+ complain (&bad_die_ref, DIE_ID, DIE_NAME);
+ }
+ else
+ {
+ type = *(utypes + utypeidx);
+ }
+ return (type);
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ alloc_utype -- add a user defined type for die reference
+
+SYNOPSIS
+
+ static type *alloc_utype (DIE_REF die_ref, struct type *utypep)
+
+DESCRIPTION
+
+ Given a die reference DIE_REF, and a possible pointer to a user
+ defined type UTYPEP, register that this reference has a user
+ defined type and either use the specified type in UTYPEP or
+ make a new empty type that will be filled in later.
+
+ We should only be called after calling lookup_utype() to verify that
+ there is not currently a type registered for DIE_REF.
+ */
+
+static struct type *
+alloc_utype (die_ref, utypep)
+ DIE_REF die_ref;
+ struct type *utypep;
+{
+ struct type **typep;
+ int utypeidx;
+
+ utypeidx = (die_ref - dbroff) / 4;
+ typep = utypes + utypeidx;
+ if ((utypeidx < 0) || (utypeidx >= numutypes))
+ {
+ utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ complain (&bad_die_ref, DIE_ID, DIE_NAME);
+ }
+ else if (*typep != NULL)
+ {
+ utypep = *typep;
+ complain (&dup_user_type_allocation, DIE_ID, DIE_NAME);
+ }
+ else
+ {
+ if (utypep == NULL)
+ {
+ utypep = alloc_type (current_objfile);
+ }
+ *typep = utypep;
+ }
+ return (utypep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ free_utypes -- free the utypes array and reset pointer & count
+
+SYNOPSIS
+
+ static void free_utypes (PTR dummy)
+
+DESCRIPTION
+
+ Called via do_cleanups to free the utypes array, reset the pointer to NULL,
+ and set numutypes back to zero. This ensures that the utypes does not get
+ referenced after being freed.
+ */
+
+static void
+free_utypes (dummy)
+ PTR dummy;
+{
+ free (utypes);
+ utypes = NULL;
+ numutypes = 0;
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ decode_die_type -- return a type for a specified die
+
+SYNOPSIS
+
+ static struct type *decode_die_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Given a pointer to a die information structure DIP, decode the
+ type of the die and return a pointer to the decoded type. All
+ dies without specific types default to type int.
+ */
+
+static struct type *
+decode_die_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *type = NULL;
+
+ if (dip -> at_fund_type != 0)
+ {
+ type = decode_fund_type (dip -> at_fund_type);
+ }
+ else if (dip -> at_mod_fund_type != NULL)
+ {
+ type = decode_mod_fund_type (dip -> at_mod_fund_type);
+ }
+ else if (dip -> at_user_def_type)
+ {
+ if ((type = lookup_utype (dip -> at_user_def_type)) == NULL)
+ {
+ type = alloc_utype (dip -> at_user_def_type, NULL);
+ }
+ }
+ else if (dip -> at_mod_u_d_type)
+ {
+ type = decode_mod_u_d_type (dip -> at_mod_u_d_type);
+ }
+ else
+ {
+ type = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ }
+ return (type);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ struct_type -- compute and return the type for a struct or union
+
+SYNOPSIS
+
+ static struct type *struct_type (struct dieinfo *dip, char *thisdie,
+ char *enddie, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given pointer to a die information structure for a die which
+ defines a union or structure (and MUST define one or the other),
+ and pointers to the raw die data that define the range of dies which
+ define the members, compute and return the user defined type for the
+ structure or union.
+ */
+
+static struct type *
+struct_type (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct nextfield {
+ struct nextfield *next;
+ struct field field;
+ };
+ struct nextfield *list = NULL;
+ struct nextfield *new;
+ int nfields = 0;
+ int n;
+ struct dieinfo mbr;
+ char *nextdie;
+ int anonymous_size;
+
+ if ((type = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* No forward references created an empty type, so install one now */
+ type = alloc_utype (dip -> die_ref, NULL);
+ }
+ INIT_CPLUS_SPECIFIC(type);
+ switch (dip -> die_tag)
+ {
+ case TAG_class_type:
+ TYPE_CODE (type) = TYPE_CODE_CLASS;
+ break;
+ case TAG_structure_type:
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ break;
+ case TAG_union_type:
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ break;
+ default:
+ /* Should never happen */
+ TYPE_CODE (type) = TYPE_CODE_UNDEF;
+ complain (&missing_tag, DIE_ID, DIE_NAME);
+ break;
+ }
+ /* Some compilers try to be helpful by inventing "fake" names for
+ anonymous enums, structures, and unions, like "~0fake" or ".0fake".
+ Thanks, but no thanks... */
+ if (dip -> at_name != NULL
+ && *dip -> at_name != '~'
+ && *dip -> at_name != '.')
+ {
+ TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack,
+ "", "", dip -> at_name);
+ }
+ /* Use whatever size is known. Zero is a valid size. We might however
+ wish to check has_at_byte_size to make sure that some byte size was
+ given explicitly, but DWARF doesn't specify that explicit sizes of
+ zero have to present, so complaining about missing sizes should
+ probably not be the default. */
+ TYPE_LENGTH (type) = dip -> at_byte_size;
+ thisdie += dip -> die_length;
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&mbr, thisdie, objfile);
+ completedieinfo (&mbr, objfile);
+ if (mbr.die_length <= SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else if (mbr.at_sibling != 0)
+ {
+ nextdie = dbbase + mbr.at_sibling - dbroff;
+ }
+ else
+ {
+ nextdie = thisdie + mbr.die_length;
+ }
+ switch (mbr.die_tag)
+ {
+ case TAG_member:
+ /* Get space to record the next field's data. */
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new -> next = list;
+ list = new;
+ /* Save the data. */
+ list -> field.name =
+ obsavestring (mbr.at_name, strlen (mbr.at_name),
+ &objfile -> type_obstack);
+ list -> field.type = decode_die_type (&mbr);
+ list -> field.bitpos = 8 * locval (mbr.at_location);
+ /* Handle bit fields. */
+ list -> field.bitsize = mbr.at_bit_size;
+ if (BITS_BIG_ENDIAN)
+ {
+ /* For big endian bits, the at_bit_offset gives the
+ additional bit offset from the MSB of the containing
+ anonymous object to the MSB of the field. We don't
+ have to do anything special since we don't need to
+ know the size of the anonymous object. */
+ list -> field.bitpos += mbr.at_bit_offset;
+ }
+ else
+ {
+ /* For little endian bits, we need to have a non-zero
+ at_bit_size, so that we know we are in fact dealing
+ with a bitfield. Compute the bit offset to the MSB
+ of the anonymous object, subtract off the number of
+ bits from the MSB of the field to the MSB of the
+ object, and then subtract off the number of bits of
+ the field itself. The result is the bit offset of
+ the LSB of the field. */
+ if (mbr.at_bit_size > 0)
+ {
+ if (mbr.has_at_byte_size)
+ {
+ /* The size of the anonymous object containing
+ the bit field is explicit, so use the
+ indicated size (in bytes). */
+ anonymous_size = mbr.at_byte_size;
+ }
+ else
+ {
+ /* The size of the anonymous object containing
+ the bit field matches the size of an object
+ of the bit field's type. DWARF allows
+ at_byte_size to be left out in such cases, as
+ a debug information size optimization. */
+ anonymous_size = TYPE_LENGTH (list -> field.type);
+ }
+ list -> field.bitpos +=
+ anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+ }
+ }
+ nfields++;
+ break;
+ default:
+ process_dies (thisdie, nextdie, objfile);
+ break;
+ }
+ thisdie = nextdie;
+ }
+ /* Now create the vector of fields, and record how big it is. We may
+ not even have any fields, if this DIE was generated due to a reference
+ to an anonymous structure or union. In this case, TYPE_FLAG_STUB is
+ set, which clues gdb in to the fact that it needs to search elsewhere
+ for the full structure definition. */
+ if (nfields == 0)
+ {
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ }
+ else
+ {
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nfields);
+ /* Copy the saved-up fields into the field vector. */
+ for (n = nfields; list; list = list -> next)
+ {
+ TYPE_FIELD (type, --n) = list -> field;
+ }
+ }
+ return (type);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_structure_scope -- process all dies within struct or union
+
+SYNOPSIS
+
+ static void read_structure_scope (struct dieinfo *dip,
+ char *thisdie, char *enddie, struct objfile *objfile)
+
+DESCRIPTION
+
+ Called when we find the DIE that starts a structure or union
+ scope (definition) to process all dies that define the members
+ of the structure or union. DIP is a pointer to the die info
+ struct for the DIE that names the structure or union.
+
+NOTES
+
+ Note that we need to call struct_type regardless of whether or not
+ the DIE has an at_name attribute, since it might be an anonymous
+ structure or union. This gets the type entered into our set of
+ user defined types.
+
+ However, if the structure is incomplete (an opaque struct/union)
+ then suppress creating a symbol table entry for it since gdb only
+ wants to find the one with the complete definition. Note that if
+ it is complete, we just call new_symbol, which does it's own
+ checking about whether the struct/union is anonymous or not (and
+ suppresses creating a symbol table entry itself).
+
+ */
+
+static void
+read_structure_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct symbol *sym;
+
+ type = struct_type (dip, thisdie, enddie, objfile);
+ if (!(TYPE_FLAGS (type) & TYPE_FLAG_STUB))
+ {
+ sym = new_symbol (dip, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_TYPE (sym) = type;
+ if (cu_language == language_cplus)
+ {
+ synthesize_typedef (dip, objfile, type);
+ }
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_array_element_type -- decode type of the array elements
+
+SYNOPSIS
+
+ static struct type *decode_array_element_type (char *scan, char *end)
+
+DESCRIPTION
+
+ As the last step in decoding the array subscript information for an
+ array DIE, we need to decode the type of the array elements. We are
+ passed a pointer to this last part of the subscript information and
+ must return the appropriate type. If the type attribute is not
+ recognized, just warn about the problem and return type int.
+ */
+
+static struct type *
+decode_array_element_type (scan)
+ char *scan;
+{
+ struct type *typep;
+ DIE_REF die_ref;
+ unsigned short attribute;
+ unsigned short fundtype;
+ int nbytes;
+
+ attribute = target_to_host (scan, SIZEOF_ATTRIBUTE, GET_UNSIGNED,
+ current_objfile);
+ scan += SIZEOF_ATTRIBUTE;
+ if ((nbytes = attribute_size (attribute)) == -1)
+ {
+ complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ }
+ else
+ {
+ switch (attribute)
+ {
+ case AT_fund_type:
+ fundtype = target_to_host (scan, nbytes, GET_UNSIGNED,
+ current_objfile);
+ typep = decode_fund_type (fundtype);
+ break;
+ case AT_mod_fund_type:
+ typep = decode_mod_fund_type (scan);
+ break;
+ case AT_user_def_type:
+ die_ref = target_to_host (scan, nbytes, GET_UNSIGNED,
+ current_objfile);
+ if ((typep = lookup_utype (die_ref)) == NULL)
+ {
+ typep = alloc_utype (die_ref, NULL);
+ }
+ break;
+ case AT_mod_u_d_type:
+ typep = decode_mod_u_d_type (scan);
+ break;
+ default:
+ complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ break;
+ }
+ }
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_subscript_data_item -- decode array subscript item
+
+SYNOPSIS
+
+ static struct type *
+ decode_subscript_data_item (char *scan, char *end)
+
+DESCRIPTION
+
+ The array subscripts and the data type of the elements of an
+ array are described by a list of data items, stored as a block
+ of contiguous bytes. There is a data item describing each array
+ dimension, and a final data item describing the element type.
+ The data items are ordered the same as their appearance in the
+ source (I.E. leftmost dimension first, next to leftmost second,
+ etc).
+
+ The data items describing each array dimension consist of four
+ parts: (1) a format specifier, (2) type type of the subscript
+ index, (3) a description of the low bound of the array dimension,
+ and (4) a description of the high bound of the array dimension.
+
+ The last data item is the description of the type of each of
+ the array elements.
+
+ We are passed a pointer to the start of the block of bytes
+ containing the remaining data items, and a pointer to the first
+ byte past the data. This function recursively decodes the
+ remaining data items and returns a type.
+
+ If we somehow fail to decode some data, we complain about it
+ and return a type "array of int".
+
+BUGS
+ FIXME: This code only implements the forms currently used
+ by the AT&T and GNU C compilers.
+
+ The end pointer is supplied for error checking, maybe we should
+ use it for that...
+ */
+
+static struct type *
+decode_subscript_data_item (scan, end)
+ char *scan;
+ char *end;
+{
+ struct type *typep = NULL; /* Array type we are building */
+ struct type *nexttype; /* Type of each element (may be array) */
+ struct type *indextype; /* Type of this index */
+ struct type *rangetype;
+ unsigned int format;
+ unsigned short fundtype;
+ unsigned long lowbound;
+ unsigned long highbound;
+ int nbytes;
+
+ format = target_to_host (scan, SIZEOF_FORMAT_SPECIFIER, GET_UNSIGNED,
+ current_objfile);
+ scan += SIZEOF_FORMAT_SPECIFIER;
+ switch (format)
+ {
+ case FMT_ET:
+ typep = decode_array_element_type (scan);
+ break;
+ case FMT_FT_C_C:
+ fundtype = target_to_host (scan, SIZEOF_FMT_FT, GET_UNSIGNED,
+ current_objfile);
+ indextype = decode_fund_type (fundtype);
+ scan += SIZEOF_FMT_FT;
+ nbytes = TARGET_FT_LONG_SIZE (current_objfile);
+ lowbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+ scan += nbytes;
+ highbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+ scan += nbytes;
+ nexttype = decode_subscript_data_item (scan, end);
+ if (nexttype == NULL)
+ {
+ /* Munged subscript data or other problem, fake it. */
+ complain (&subscript_data_items, DIE_ID, DIE_NAME);
+ nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ }
+ rangetype = create_range_type ((struct type *) NULL, indextype,
+ lowbound, highbound);
+ typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
+ break;
+ case FMT_FT_C_X:
+ case FMT_FT_X_C:
+ case FMT_FT_X_X:
+ case FMT_UT_C_C:
+ case FMT_UT_C_X:
+ case FMT_UT_X_C:
+ case FMT_UT_X_X:
+ complain (&unhandled_array_subscript_format, DIE_ID, DIE_NAME, format);
+ nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+ typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
+ break;
+ default:
+ complain (&unknown_array_subscript_format, DIE_ID, DIE_NAME, format);
+ nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+ typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
+ break;
+ }
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ dwarf_read_array_type -- read TAG_array_type DIE
+
+SYNOPSIS
+
+ static void dwarf_read_array_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Extract all information from a TAG_array_type DIE and add to
+ the user defined type vector.
+ */
+
+static void
+dwarf_read_array_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *type;
+ struct type *utype;
+ char *sub;
+ char *subend;
+ unsigned short blocksz;
+ int nbytes;
+
+ if (dip -> at_ordering != ORD_row_major)
+ {
+ /* FIXME: Can gdb even handle column major arrays? */
+ complain (&not_row_major, DIE_ID, DIE_NAME);
+ }
+ if ((sub = dip -> at_subscr_data) != NULL)
+ {
+ nbytes = attribute_size (AT_subscr_data);
+ blocksz = target_to_host (sub, nbytes, GET_UNSIGNED, current_objfile);
+ subend = sub + nbytes + blocksz;
+ sub += nbytes;
+ type = decode_subscript_data_item (sub, subend);
+ if ((utype = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* Install user defined type that has not been referenced yet. */
+ alloc_utype (dip -> die_ref, type);
+ }
+ else if (TYPE_CODE (utype) == TYPE_CODE_UNDEF)
+ {
+ /* Ick! A forward ref has already generated a blank type in our
+ slot, and this type probably already has things pointing to it
+ (which is what caused it to be created in the first place).
+ If it's just a place holder we can plop our fully defined type
+ on top of it. We can't recover the space allocated for our
+ new type since it might be on an obstack, but we could reuse
+ it if we kept a list of them, but it might not be worth it
+ (FIXME). */
+ *utype = *type;
+ }
+ else
+ {
+ /* Double ick! Not only is a type already in our slot, but
+ someone has decorated it. Complain and leave it alone. */
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_tag_pointer_type -- read TAG_pointer_type DIE
+
+SYNOPSIS
+
+ static void read_tag_pointer_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Extract all information from a TAG_pointer_type DIE and add to
+ the user defined type vector.
+ */
+
+static void
+read_tag_pointer_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *type;
+ struct type *utype;
+
+ type = decode_die_type (dip);
+ if ((utype = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ utype = lookup_pointer_type (type);
+ alloc_utype (dip -> die_ref, utype);
+ }
+ else
+ {
+ TYPE_TARGET_TYPE (utype) = type;
+ TYPE_POINTER_TYPE (type) = utype;
+
+ /* We assume the machine has only one representation for pointers! */
+ /* FIXME: This confuses host<->target data representations, and is a
+ poor assumption besides. */
+
+ TYPE_LENGTH (utype) = sizeof (char *);
+ TYPE_CODE (utype) = TYPE_CODE_PTR;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_tag_string_type -- read TAG_string_type DIE
+
+SYNOPSIS
+
+ static void read_tag_string_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+ Extract all information from a TAG_string_type DIE and add to
+ the user defined type vector. It isn't really a user defined
+ type, but it behaves like one, with other DIE's using an
+ AT_user_def_type attribute to reference it.
+ */
+
+static void
+read_tag_string_type (dip)
+ struct dieinfo *dip;
+{
+ struct type *utype;
+ struct type *indextype;
+ struct type *rangetype;
+ unsigned long lowbound = 0;
+ unsigned long highbound;
+
+ if (dip -> has_at_byte_size)
+ {
+ /* A fixed bounds string */
+ highbound = dip -> at_byte_size - 1;
+ }
+ else
+ {
+ /* A varying length string. Stub for now. (FIXME) */
+ highbound = 1;
+ }
+ indextype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ rangetype = create_range_type ((struct type *) NULL, indextype, lowbound,
+ highbound);
+
+ utype = lookup_utype (dip -> die_ref);
+ if (utype == NULL)
+ {
+ /* No type defined, go ahead and create a blank one to use. */
+ utype = alloc_utype (dip -> die_ref, (struct type *) NULL);
+ }
+ else
+ {
+ /* Already a type in our slot due to a forward reference. Make sure it
+ is a blank one. If not, complain and leave it alone. */
+ if (TYPE_CODE (utype) != TYPE_CODE_UNDEF)
+ {
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ return;
+ }
+ }
+
+ /* Create the string type using the blank type we either found or created. */
+ utype = create_string_type (utype, rangetype);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_subroutine_type -- process TAG_subroutine_type dies
+
+SYNOPSIS
+
+ static void read_subroutine_type (struct dieinfo *dip, char thisdie,
+ char *enddie)
+
+DESCRIPTION
+
+ Handle DIES due to C code like:
+
+ struct foo {
+ int (*funcp)(int a, long l); (Generates TAG_subroutine_type DIE)
+ int b;
+ };
+
+NOTES
+
+ The parameter DIES are currently ignored. See if gdb has a way to
+ include this info in it's type system, and decode them if so. Is
+ this what the type structure's "arg_types" field is for? (FIXME)
+ */
+
+static void
+read_subroutine_type (dip, thisdie, enddie)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+{
+ struct type *type; /* Type that this function returns */
+ struct type *ftype; /* Function that returns above type */
+
+ /* Decode the type that this subroutine returns */
+
+ type = decode_die_type (dip);
+
+ /* Check to see if we already have a partially constructed user
+ defined type for this DIE, from a forward reference. */
+
+ if ((ftype = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* This is the first reference to one of these types. Make
+ a new one and place it in the user defined types. */
+ ftype = lookup_function_type (type);
+ alloc_utype (dip -> die_ref, ftype);
+ }
+ else if (TYPE_CODE (ftype) == TYPE_CODE_UNDEF)
+ {
+ /* We have an existing partially constructed type, so bash it
+ into the correct type. */
+ TYPE_TARGET_TYPE (ftype) = type;
+ TYPE_LENGTH (ftype) = 1;
+ TYPE_CODE (ftype) = TYPE_CODE_FUNC;
+ }
+ else
+ {
+ complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_enumeration -- process dies which define an enumeration
+
+SYNOPSIS
+
+ static void read_enumeration (struct dieinfo *dip, char *thisdie,
+ char *enddie, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to a die which begins an enumeration, process all
+ the dies that define the members of the enumeration.
+
+NOTES
+
+ Note that we need to call enum_type regardless of whether or not we
+ have a symbol, since we might have an enum without a tag name (thus
+ no symbol for the tagname).
+ */
+
+static void
+read_enumeration (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct symbol *sym;
+
+ type = enum_type (dip, objfile);
+ sym = new_symbol (dip, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_TYPE (sym) = type;
+ if (cu_language == language_cplus)
+ {
+ synthesize_typedef (dip, objfile, type);
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ enum_type -- decode and return a type for an enumeration
+
+SYNOPSIS
+
+ static type *enum_type (struct dieinfo *dip, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to a die information structure for the die which
+ starts an enumeration, process all the dies that define the members
+ of the enumeration and return a type pointer for the enumeration.
+
+ At the same time, for each member of the enumeration, create a
+ symbol for it with namespace VAR_NAMESPACE and class LOC_CONST,
+ and give it the type of the enumeration itself.
+
+NOTES
+
+ Note that the DWARF specification explicitly mandates that enum
+ constants occur in reverse order from the source program order,
+ for "consistency" and because this ordering is easier for many
+ compilers to generate. (Draft 6, sec 3.8.5, Enumeration type
+ Entries). Because gdb wants to see the enum members in program
+ source order, we have to ensure that the order gets reversed while
+ we are processing them.
+ */
+
+static struct type *
+enum_type (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ struct type *type;
+ struct nextfield {
+ struct nextfield *next;
+ struct field field;
+ };
+ struct nextfield *list = NULL;
+ struct nextfield *new;
+ int nfields = 0;
+ int n;
+ char *scan;
+ char *listend;
+ unsigned short blocksz;
+ struct symbol *sym;
+ int nbytes;
+ int unsigned_enum = 1;
+
+ if ((type = lookup_utype (dip -> die_ref)) == NULL)
+ {
+ /* No forward references created an empty type, so install one now */
+ type = alloc_utype (dip -> die_ref, NULL);
+ }
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ /* Some compilers try to be helpful by inventing "fake" names for
+ anonymous enums, structures, and unions, like "~0fake" or ".0fake".
+ Thanks, but no thanks... */
+ if (dip -> at_name != NULL
+ && *dip -> at_name != '~'
+ && *dip -> at_name != '.')
+ {
+ TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack,
+ "", "", dip -> at_name);
+ }
+ if (dip -> at_byte_size != 0)
+ {
+ TYPE_LENGTH (type) = dip -> at_byte_size;
+ }
+ if ((scan = dip -> at_element_list) != NULL)
+ {
+ if (dip -> short_element_list)
+ {
+ nbytes = attribute_size (AT_short_element_list);
+ }
+ else
+ {
+ nbytes = attribute_size (AT_element_list);
+ }
+ blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile);
+ listend = scan + nbytes + blocksz;
+ scan += nbytes;
+ while (scan < listend)
+ {
+ new = (struct nextfield *) alloca (sizeof (struct nextfield));
+ new -> next = list;
+ list = new;
+ list -> field.type = NULL;
+ list -> field.bitsize = 0;
+ list -> field.bitpos =
+ target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED,
+ objfile);
+ scan += TARGET_FT_LONG_SIZE (objfile);
+ list -> field.name = obsavestring (scan, strlen (scan),
+ &objfile -> type_obstack);
+ scan += strlen (scan) + 1;
+ nfields++;
+ /* Handcraft a new symbol for this enum member. */
+ sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = create_name (list -> field.name,
+ &objfile->symbol_obstack);
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_VALUE (sym) = list -> field.bitpos;
+ if (SYMBOL_VALUE (sym) < 0)
+ unsigned_enum = 0;
+ add_symbol_to_list (sym, list_in_scope);
+ }
+ /* Now create the vector of fields, and record how big it is. This is
+ where we reverse the order, by pulling the members off the list in
+ reverse order from how they were inserted. If we have no fields
+ (this is apparently possible in C++) then skip building a field
+ vector. */
+ if (nfields > 0)
+ {
+ if (unsigned_enum)
+ TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) * nfields);
+ /* Copy the saved-up fields into the field vector. */
+ for (n = 0; (n < nfields) && (list != NULL); list = list -> next)
+ {
+ TYPE_FIELD (type, n++) = list -> field;
+ }
+ }
+ }
+ return (type);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_func_scope -- process all dies within a function scope
+
+DESCRIPTION
+
+ Process all dies within a given function scope. We are passed
+ a die information structure pointer DIP for the die which
+ starts the function scope, and pointers into the raw die data
+ that define the dies within the function scope.
+
+ For now, we ignore lexical block scopes within the function.
+ The problem is that AT&T cc does not define a DWARF lexical
+ block scope for the function itself, while gcc defines a
+ lexical block scope for the function. We need to think about
+ how to handle this difference, or if it is even a problem.
+ (FIXME)
+ */
+
+static void
+read_func_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+
+ /* AT_name is absent if the function is described with an
+ AT_abstract_origin tag.
+ Ignore the function description for now to avoid GDB core dumps.
+ FIXME: Add code to handle AT_abstract_origin tags properly. */
+ if (dip -> at_name == NULL)
+ {
+ complain (&missing_at_name, DIE_ID);
+ return;
+ }
+
+ if (objfile -> ei.entry_point >= dip -> at_low_pc &&
+ objfile -> ei.entry_point < dip -> at_high_pc)
+ {
+ objfile -> ei.entry_func_lowpc = dip -> at_low_pc;
+ objfile -> ei.entry_func_highpc = dip -> at_high_pc;
+ }
+ if (STREQ (dip -> at_name, "main")) /* FIXME: hardwired name */
+ {
+ objfile -> ei.main_func_lowpc = dip -> at_low_pc;
+ objfile -> ei.main_func_highpc = dip -> at_high_pc;
+ }
+ new = push_context (0, dip -> at_low_pc);
+ new -> name = new_symbol (dip, objfile);
+ list_in_scope = &local_symbols;
+ process_dies (thisdie + dip -> die_length, enddie, objfile);
+ new = pop_context ();
+ /* Make a block for the local symbols within. */
+ finish_block (new -> name, &local_symbols, new -> old_blocks,
+ new -> start_addr, dip -> at_high_pc, objfile);
+ list_in_scope = &file_symbols;
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ handle_producer -- process the AT_producer attribute
+
+DESCRIPTION
+
+ Perform any operations that depend on finding a particular
+ AT_producer attribute.
+
+ */
+
+static void
+handle_producer (producer)
+ char *producer;
+{
+
+ /* If this compilation unit was compiled with g++ or gcc, then set the
+ processing_gcc_compilation flag. */
+
+ processing_gcc_compilation =
+ STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+ || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER))
+ || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+
+ /* Select a demangling style if we can identify the producer and if
+ the current style is auto. We leave the current style alone if it
+ is not auto. We also leave the demangling style alone if we find a
+ gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
+
+ if (AUTO_DEMANGLING)
+ {
+ if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER)))
+ {
+ set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
+ }
+ }
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ read_file_scope -- process all dies within a file scope
+
+DESCRIPTION
+
+ Process all dies within a given file scope. We are passed a
+ pointer to the die information structure for the die which
+ starts the file scope, and pointers into the raw die data which
+ mark the range of dies within the file scope.
+
+ When the partial symbol table is built, the file offset for the line
+ number table for each compilation unit is saved in the partial symbol
+ table entry for that compilation unit. As the symbols for each
+ compilation unit are read, the line number table is read into memory
+ and the variable lnbase is set to point to it. Thus all we have to
+ do is use lnbase to access the line number table for the current
+ compilation unit.
+ */
+
+static void
+read_file_scope (dip, thisdie, enddie, objfile)
+ struct dieinfo *dip;
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ struct cleanup *back_to;
+ struct symtab *symtab;
+
+ if (objfile -> ei.entry_point >= dip -> at_low_pc &&
+ objfile -> ei.entry_point < dip -> at_high_pc)
+ {
+ objfile -> ei.entry_file_lowpc = dip -> at_low_pc;
+ objfile -> ei.entry_file_highpc = dip -> at_high_pc;
+ }
+ set_cu_language (dip);
+ if (dip -> at_producer != NULL)
+ {
+ handle_producer (dip -> at_producer);
+ }
+ numutypes = (enddie - thisdie) / 4;
+ utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *));
+ back_to = make_cleanup (free_utypes, NULL);
+ memset (utypes, 0, numutypes * sizeof (struct type *));
+ memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+ start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc);
+ decode_line_numbers (lnbase);
+ process_dies (thisdie + dip -> die_length, enddie, objfile);
+
+ symtab = end_symtab (dip -> at_high_pc, objfile, 0);
+ if (symtab != NULL)
+ {
+ symtab -> language = cu_language;
+ }
+ do_cleanups (back_to);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ process_dies -- process a range of DWARF Information Entries
+
+SYNOPSIS
+
+ static void process_dies (char *thisdie, char *enddie,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Process all DIE's in a specified range. May be (and almost
+ certainly will be) called recursively.
+ */
+
+static void
+process_dies (thisdie, enddie, objfile)
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ char *nextdie;
+ struct dieinfo di;
+
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&di, thisdie, objfile);
+ if (di.die_length < SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else if (di.die_tag == TAG_padding)
+ {
+ nextdie = thisdie + di.die_length;
+ }
+ else
+ {
+ completedieinfo (&di, objfile);
+ if (di.at_sibling != 0)
+ {
+ nextdie = dbbase + di.at_sibling - dbroff;
+ }
+ else
+ {
+ 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:
+ /* 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:
+ if (di.has_at_low_pc)
+ {
+ read_func_scope (&di, thisdie, nextdie, objfile);
+ }
+ break;
+ case TAG_lexical_block:
+ read_lexical_block_scope (&di, thisdie, nextdie, objfile);
+ break;
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ read_structure_scope (&di, thisdie, nextdie, objfile);
+ break;
+ case TAG_enumeration_type:
+ read_enumeration (&di, thisdie, nextdie, objfile);
+ break;
+ case TAG_subroutine_type:
+ read_subroutine_type (&di, thisdie, nextdie);
+ break;
+ case TAG_array_type:
+ dwarf_read_array_type (&di);
+ break;
+ case TAG_pointer_type:
+ read_tag_pointer_type (&di);
+ break;
+ case TAG_string_type:
+ read_tag_string_type (&di);
+ break;
+ default:
+ new_symbol (&di, objfile);
+ break;
+ }
+ }
+ thisdie = nextdie;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_line_numbers -- decode a line number table fragment
+
+SYNOPSIS
+
+ static void decode_line_numbers (char *tblscan, char *tblend,
+ long length, long base, long line, long pc)
+
+DESCRIPTION
+
+ Translate the DWARF line number information to gdb form.
+
+ The ".line" section contains one or more line number tables, one for
+ each ".line" section from the objects that were linked.
+
+ The AT_stmt_list attribute for each TAG_source_file entry in the
+ ".debug" section contains the offset into the ".line" section for the
+ start of the table for that file.
+
+ The table itself has the following structure:
+
+ <table length><base address><source statement entry>
+ 4 bytes 4 bytes 10 bytes
+
+ The table length is the total size of the table, including the 4 bytes
+ for the length information.
+
+ The base address is the address of the first instruction generated
+ for the source file.
+
+ Each source statement entry has the following structure:
+
+ <line number><statement position><address delta>
+ 4 bytes 2 bytes 4 bytes
+
+ The line number is relative to the start of the file, starting with
+ line 1.
+
+ The statement position either -1 (0xFFFF) or the number of characters
+ from the beginning of the line to the beginning of the statement.
+
+ The address delta is the difference between the base address and
+ the address of the first instruction for the statement.
+
+ Note that we must copy the bytes from the packed table to our local
+ variables before attempting to use them, to avoid alignment problems
+ on some machines, particularly RISC processors.
+
+BUGS
+
+ Does gdb expect the line numbers to be sorted? They are now by
+ chance/luck, but are not required to be. (FIXME)
+
+ The line with number 0 is unused, gdb apparently can discover the
+ span of the last line some other way. How? (FIXME)
+ */
+
+static void
+decode_line_numbers (linetable)
+ char *linetable;
+{
+ char *tblscan;
+ char *tblend;
+ unsigned long length;
+ unsigned long base;
+ unsigned long line;
+ unsigned long pc;
+
+ if (linetable != NULL)
+ {
+ tblscan = tblend = linetable;
+ length = target_to_host (tblscan, SIZEOF_LINETBL_LENGTH, GET_UNSIGNED,
+ current_objfile);
+ tblscan += SIZEOF_LINETBL_LENGTH;
+ tblend += length;
+ base = target_to_host (tblscan, TARGET_FT_POINTER_SIZE (objfile),
+ GET_UNSIGNED, current_objfile);
+ tblscan += TARGET_FT_POINTER_SIZE (objfile);
+ base += baseaddr;
+ while (tblscan < tblend)
+ {
+ line = target_to_host (tblscan, SIZEOF_LINETBL_LINENO, GET_UNSIGNED,
+ current_objfile);
+ tblscan += SIZEOF_LINETBL_LINENO + SIZEOF_LINETBL_STMT;
+ pc = target_to_host (tblscan, SIZEOF_LINETBL_DELTA, GET_UNSIGNED,
+ current_objfile);
+ tblscan += SIZEOF_LINETBL_DELTA;
+ pc += base;
+ if (line != 0)
+ {
+ record_line (current_subfile, line, pc);
+ }
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ locval -- compute the value of a location attribute
+
+SYNOPSIS
+
+ static int locval (char *loc)
+
+DESCRIPTION
+
+ Given pointer to a string of bytes that define a location, compute
+ the location and return the value.
+ A location description containing no atoms indicates that the
+ object is optimized out. The global optimized_out flag is set for
+ those, the return value is meaningless.
+
+ When computing values involving the current value of the frame pointer,
+ the value zero is used, which results in a value relative to the frame
+ pointer, rather than the absolute value. This is what GDB wants
+ anyway.
+
+ When the result is a register number, the global isreg flag is set,
+ otherwise it is cleared. This is a kludge until we figure out a better
+ way to handle the problem. Gdb's design does not mesh well with the
+ DWARF notion of a location computing interpreter, which is a shame
+ because the flexibility goes unused.
+
+NOTES
+
+ Note that stack[0] is unused except as a default error return.
+ Note that stack overflow is not yet handled.
+ */
+
+static int
+locval (loc)
+ char *loc;
+{
+ unsigned short nbytes;
+ unsigned short locsize;
+ auto long stack[64];
+ int stacki;
+ char *end;
+ int loc_atom_code;
+ int loc_value_size;
+
+ nbytes = attribute_size (AT_location);
+ locsize = target_to_host (loc, nbytes, GET_UNSIGNED, current_objfile);
+ loc += nbytes;
+ end = loc + locsize;
+ stacki = 0;
+ stack[stacki] = 0;
+ isreg = 0;
+ offreg = 0;
+ optimized_out = 1;
+ loc_value_size = TARGET_FT_LONG_SIZE (current_objfile);
+ while (loc < end)
+ {
+ optimized_out = 0;
+ loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED,
+ current_objfile);
+ loc += SIZEOF_LOC_ATOM_CODE;
+ switch (loc_atom_code)
+ {
+ case 0:
+ /* error */
+ loc = end;
+ break;
+ case OP_REG:
+ /* push register (number) */
+ stack[++stacki]
+ = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size,
+ GET_UNSIGNED,
+ current_objfile));
+ loc += loc_value_size;
+ isreg = 1;
+ break;
+ case OP_BASEREG:
+ /* push value of register (number) */
+ /* Actually, we compute the value as if register has 0, so the
+ value ends up being the offset from that register. */
+ offreg = 1;
+ basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED,
+ current_objfile);
+ loc += loc_value_size;
+ stack[++stacki] = 0;
+ break;
+ case OP_ADDR:
+ /* push address (relocated address) */
+ stack[++stacki] = target_to_host (loc, loc_value_size,
+ GET_UNSIGNED, current_objfile);
+ loc += loc_value_size;
+ break;
+ case OP_CONST:
+ /* push constant (number) FIXME: signed or unsigned! */
+ stack[++stacki] = target_to_host (loc, loc_value_size,
+ GET_SIGNED, current_objfile);
+ loc += loc_value_size;
+ break;
+ case OP_DEREF2:
+ /* pop, deref and push 2 bytes (as a long) */
+ complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]);
+ break;
+ case OP_DEREF4: /* pop, deref and push 4 bytes (as a long) */
+ complain (&op_deref4, DIE_ID, DIE_NAME, stack[stacki]);
+ break;
+ case OP_ADD: /* pop top 2 items, add, push result */
+ stack[stacki - 1] += stack[stacki];
+ stacki--;
+ break;
+ }
+ }
+ return (stack[stacki]);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ read_ofile_symtab -- build a full symtab entry from chunk of DIE's
+
+SYNOPSIS
+
+ static void read_ofile_symtab (struct partial_symtab *pst)
+
+DESCRIPTION
+
+ When expanding a partial symbol table entry to a full symbol table
+ entry, this is the function that gets called to read in the symbols
+ for the compilation unit. A pointer to the newly constructed symtab,
+ which is now the new first one on the objfile's symtab list, is
+ stashed in the partial symbol table entry.
+ */
+
+static void
+read_ofile_symtab (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *back_to;
+ unsigned long lnsize;
+ file_ptr foffset;
+ bfd *abfd;
+ char lnsizedata[SIZEOF_LINETBL_LENGTH];
+
+ abfd = pst -> objfile -> obfd;
+ current_objfile = pst -> objfile;
+
+ /* Allocate a buffer for the entire chunk of DIE's for this compilation
+ unit, seek to the location in the file, and read in all the DIE's. */
+
+ diecount = 0;
+ dbsize = DBLENGTH (pst);
+ dbbase = xmalloc (dbsize);
+ dbroff = DBROFF(pst);
+ foffset = DBFOFF(pst) + dbroff;
+ base_section_offsets = pst->section_offsets;
+ baseaddr = ANOFFSET (pst->section_offsets, 0);
+ if (bfd_seek (abfd, foffset, SEEK_SET) ||
+ (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
+ {
+ free (dbbase);
+ error ("can't read DWARF data");
+ }
+ back_to = make_cleanup (free, dbbase);
+
+ /* If there is a line number table associated with this compilation unit
+ then read the size of this fragment in bytes, from the fragment itself.
+ Allocate a buffer for the fragment and read it in for future
+ processing. */
+
+ lnbase = NULL;
+ if (LNFOFF (pst))
+ {
+ if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) ||
+ (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=
+ sizeof (lnsizedata)))
+ {
+ error ("can't read DWARF line number table size");
+ }
+ lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH,
+ GET_UNSIGNED, pst -> objfile);
+ lnbase = xmalloc (lnsize);
+ if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) ||
+ (bfd_read (lnbase, lnsize, 1, abfd) != lnsize))
+ {
+ free (lnbase);
+ error ("can't read DWARF line numbers");
+ }
+ make_cleanup (free, lnbase);
+ }
+
+ process_dies (dbbase, dbbase + dbsize, pst -> objfile);
+ do_cleanups (back_to);
+ current_objfile = NULL;
+ pst -> symtab = pst -> objfile -> symtabs;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ psymtab_to_symtab_1 -- do grunt work for building a full symtab entry
+
+SYNOPSIS
+
+ static void psymtab_to_symtab_1 (struct partial_symtab *pst)
+
+DESCRIPTION
+
+ Called once for each partial symbol table entry that needs to be
+ expanded into a full symbol table entry.
+
+*/
+
+static void
+psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ int i;
+ struct cleanup *old_chain;
+
+ if (pst != NULL)
+ {
+ if (pst->readin)
+ {
+ warning ("psymtab for %s already read in. Shouldn't happen.",
+ pst -> filename);
+ }
+ else
+ {
+ /* Read in all partial symtabs on which this one is dependent */
+ for (i = 0; i < pst -> number_of_dependencies; i++)
+ {
+ if (!pst -> dependencies[i] -> readin)
+ {
+ /* Inform about additional files that need to be read in. */
+ if (info_verbose)
+ {
+ fputs_filtered (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...",
+ pst -> dependencies[i] -> filename);
+ wrap_here ("");
+ gdb_flush (gdb_stdout); /* Flush output */
+ }
+ psymtab_to_symtab_1 (pst -> dependencies[i]);
+ }
+ }
+ if (DBLENGTH (pst)) /* Otherwise it's a dummy */
+ {
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+ read_ofile_symtab (pst);
+ if (info_verbose)
+ {
+ printf_filtered ("%d DIE's, sorting...", diecount);
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ }
+ sort_symtab_syms (pst -> symtab);
+ do_cleanups (old_chain);
+ }
+ pst -> readin = 1;
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ dwarf_psymtab_to_symtab -- build a full symtab entry from partial one
+
+SYNOPSIS
+
+ static void dwarf_psymtab_to_symtab (struct partial_symtab *pst)
+
+DESCRIPTION
+
+ This is the DWARF support entry point for building a full symbol
+ table entry from a partial symbol table entry. We are passed a
+ pointer to the partial symbol table entry that needs to be expanded.
+
+*/
+
+static void
+dwarf_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+
+ if (pst != NULL)
+ {
+ if (pst -> readin)
+ {
+ warning ("psymtab for %s already read in. Shouldn't happen.",
+ pst -> filename);
+ }
+ else
+ {
+ if (DBLENGTH (pst) || pst -> number_of_dependencies)
+ {
+ /* Print the message now, before starting serious work, to avoid
+ disconcerting pauses. */
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...",
+ pst -> filename);
+ gdb_flush (gdb_stdout);
+ }
+
+ psymtab_to_symtab_1 (pst);
+
+#if 0 /* FIXME: Check to see what dbxread is doing here and see if
+ we need to do an equivalent or is this something peculiar to
+ stabs/a.out format.
+ 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);
+#endif
+
+ /* Finish up the verbose info message. */
+ if (info_verbose)
+ {
+ printf_filtered ("done.\n");
+ gdb_flush (gdb_stdout);
+ }
+ }
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ add_enum_psymbol -- add enumeration members to partial symbol table
+
+DESCRIPTION
+
+ Given pointer to a DIE that is known to be for an enumeration,
+ extract the symbolic names of the enumeration members and add
+ partial symbols for them.
+*/
+
+static void
+add_enum_psymbol (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ char *scan;
+ char *listend;
+ unsigned short blocksz;
+ int nbytes;
+
+ if ((scan = dip -> at_element_list) != NULL)
+ {
+ if (dip -> short_element_list)
+ {
+ nbytes = attribute_size (AT_short_element_list);
+ }
+ else
+ {
+ nbytes = attribute_size (AT_element_list);
+ }
+ blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile);
+ scan += nbytes;
+ listend = scan + blocksz;
+ while (scan < listend)
+ {
+ scan += TARGET_FT_LONG_SIZE (objfile);
+ add_psymbol_to_list (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
+ &objfile -> static_psymbols, 0, 0, cu_language,
+ objfile);
+ scan += strlen (scan) + 1;
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ add_partial_symbol -- add symbol to partial symbol table
+
+DESCRIPTION
+
+ Given a DIE, if it is one of the types that we want to
+ add to a partial symbol table, finish filling in the die info
+ and then add a partial symbol table entry for it.
+
+NOTES
+
+ The caller must ensure that the DIE has a valid name attribute.
+*/
+
+static void
+add_partial_symbol (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ switch (dip -> die_tag)
+ {
+ case TAG_global_subroutine:
+ add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile -> global_psymbols,
+ 0, dip -> at_low_pc, cu_language, objfile);
+ break;
+ case TAG_global_variable:
+ add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile -> global_psymbols,
+ 0, 0, cu_language, objfile);
+ break;
+ case TAG_subroutine:
+ add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile -> static_psymbols,
+ 0, dip -> at_low_pc, cu_language, objfile);
+ break;
+ case TAG_local_variable:
+ add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile -> static_psymbols,
+ 0, 0, cu_language, objfile);
+ break;
+ case TAG_typedef:
+ add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile -> static_psymbols,
+ 0, 0, cu_language, objfile);
+ break;
+ case TAG_class_type:
+ 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,
+ 0, 0, cu_language, objfile);
+ if (cu_language == language_cplus)
+ {
+ /* For C++, these implicitly act as typedefs as well. */
+ add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile -> static_psymbols,
+ 0, 0, cu_language, objfile);
+ }
+ break;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ scan_partial_symbols -- scan DIE's within a single compilation unit
+
+DESCRIPTION
+
+ Process the DIE's within a single compilation unit, looking for
+ interesting DIE's that contribute to the partial symbol table entry
+ for this compilation unit.
+
+NOTES
+
+ There are some DIE's that may appear both at file scope and within
+ the scope of a function. We are only interested in the ones at file
+ scope, and the only way to tell them apart is to keep track of the
+ scope. For example, consider the test case:
+
+ static int i;
+ main () { int j; }
+
+ for which the relevant DWARF segment has the structure:
+
+ 0x51:
+ 0x23 global subrtn sibling 0x9b
+ name main
+ fund_type FT_integer
+ low_pc 0x800004cc
+ high_pc 0x800004d4
+
+ 0x74:
+ 0x23 local var sibling 0x97
+ name j
+ fund_type FT_integer
+ location OP_BASEREG 0xe
+ OP_CONST 0xfffffffc
+ OP_ADD
+ 0x97:
+ 0x4
+
+ 0x9b:
+ 0x1d local var sibling 0xb8
+ name i
+ fund_type FT_integer
+ location OP_ADDR 0x800025dc
+
+ 0xb8:
+ 0x4
+
+ We want to include the symbol 'i' in the partial symbol table, but
+ not the symbol 'j'. In essence, we want to skip all the dies within
+ the scope of a TAG_global_subroutine DIE.
+
+ Don't attempt to add anonymous structures or unions since they have
+ no name. Anonymous enumerations however are processed, because we
+ want to extract their member names (the check for a tag name is
+ done later).
+
+ Also, for variables and subroutines, check that this is the place
+ where the actual definition occurs, rather than just a reference
+ to an external.
+ */
+
+static void
+scan_partial_symbols (thisdie, enddie, objfile)
+ char *thisdie;
+ char *enddie;
+ struct objfile *objfile;
+{
+ char *nextdie;
+ char *temp;
+ struct dieinfo di;
+
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&di, thisdie, objfile);
+ if (di.die_length < SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else
+ {
+ nextdie = thisdie + di.die_length;
+ /* To avoid getting complete die information for every die, we
+ only do it (below) for the cases we are interested in. */
+ switch (di.die_tag)
+ {
+ case TAG_global_subroutine:
+ case TAG_subroutine:
+ completedieinfo (&di, objfile);
+ if (di.at_name && (di.has_at_low_pc || di.at_location))
+ {
+ add_partial_symbol (&di, objfile);
+ /* If there is a sibling attribute, adjust the nextdie
+ pointer to skip the entire scope of the subroutine.
+ Apply some sanity checking to make sure we don't
+ overrun or underrun the range of remaining DIE's */
+ if (di.at_sibling != 0)
+ {
+ temp = dbbase + di.at_sibling - dbroff;
+ if ((temp < thisdie) || (temp >= enddie))
+ {
+ complain (&bad_die_ref, DIE_ID, DIE_NAME,
+ di.at_sibling);
+ }
+ else
+ {
+ nextdie = temp;
+ }
+ }
+ }
+ break;
+ case TAG_global_variable:
+ case TAG_local_variable:
+ completedieinfo (&di, objfile);
+ if (di.at_name && (di.has_at_low_pc || di.at_location))
+ {
+ add_partial_symbol (&di, objfile);
+ }
+ break;
+ case TAG_typedef:
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ completedieinfo (&di, objfile);
+ if (di.at_name)
+ {
+ add_partial_symbol (&di, objfile);
+ }
+ break;
+ case TAG_enumeration_type:
+ completedieinfo (&di, objfile);
+ if (di.at_name)
+ {
+ add_partial_symbol (&di, objfile);
+ }
+ add_enum_psymbol (&di, objfile);
+ break;
+ }
+ }
+ thisdie = nextdie;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ scan_compilation_units -- build a psymtab entry for each compilation
+
+DESCRIPTION
+
+ This is the top level dwarf parsing routine for building partial
+ symbol tables.
+
+ It scans from the beginning of the DWARF table looking for the first
+ TAG_compile_unit DIE, and then follows the sibling chain to locate
+ each additional TAG_compile_unit DIE.
+
+ For each TAG_compile_unit DIE it creates a partial symtab structure,
+ calls a subordinate routine to collect all the compilation unit's
+ global DIE's, file scope DIEs, typedef DIEs, etc, and then links the
+ new partial symtab structure into the partial symbol table. It also
+ records the appropriate information in the partial symbol table entry
+ to allow the chunk of DIE's and line number table for this compilation
+ unit to be located and re-read later, to generate a complete symbol
+ table entry for the compilation unit.
+
+ Thus it effectively partitions up a chunk of DIE's for multiple
+ compilation units into smaller DIE chunks and line number tables,
+ and associates them with a partial symbol table entry.
+
+NOTES
+
+ If any compilation unit has no line number table associated with
+ it for some reason (a missing at_stmt_list attribute, rather than
+ just one with a value of zero, which is valid) then we ensure that
+ the recorded file offset is zero so that the routine which later
+ reads line number table fragments knows that there is no fragment
+ to read.
+
+RETURNS
+
+ Returns no value.
+
+ */
+
+static void
+scan_compilation_units (thisdie, enddie, dbfoff, lnoffset, objfile)
+ char *thisdie;
+ char *enddie;
+ file_ptr dbfoff;
+ file_ptr lnoffset;
+ struct objfile *objfile;
+{
+ char *nextdie;
+ struct dieinfo di;
+ struct partial_symtab *pst;
+ int culength;
+ int curoff;
+ file_ptr curlnoffset;
+
+ while (thisdie < enddie)
+ {
+ basicdieinfo (&di, thisdie, objfile);
+ if (di.die_length < SIZEOF_DIE_LENGTH)
+ {
+ break;
+ }
+ else if (di.die_tag != TAG_compile_unit)
+ {
+ nextdie = thisdie + di.die_length;
+ }
+ else
+ {
+ completedieinfo (&di, objfile);
+ set_cu_language (&di);
+ if (di.at_sibling != 0)
+ {
+ nextdie = dbbase + di.at_sibling - dbroff;
+ }
+ else
+ {
+ nextdie = thisdie + di.die_length;
+ }
+ curoff = thisdie - dbbase;
+ culength = nextdie - thisdie;
+ curlnoffset = di.has_at_stmt_list ? lnoffset + di.at_stmt_list : 0;
+
+ /* First allocate a new partial symbol table structure */
+
+ pst = start_psymtab_common (objfile, base_section_offsets,
+ di.at_name, di.at_low_pc,
+ objfile -> global_psymbols.next,
+ objfile -> static_psymbols.next);
+
+ pst -> texthigh = di.at_high_pc;
+ pst -> read_symtab_private = (char *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct dwfinfo));
+ DBFOFF (pst) = dbfoff;
+ DBROFF (pst) = curoff;
+ DBLENGTH (pst) = culength;
+ LNFOFF (pst) = curlnoffset;
+ pst -> read_symtab = dwarf_psymtab_to_symtab;
+
+ /* Now look for partial symbols */
+
+ scan_partial_symbols (thisdie + di.die_length, nextdie, objfile);
+
+ pst -> n_global_syms = objfile -> global_psymbols.next -
+ (objfile -> global_psymbols.list + pst -> globals_offset);
+ pst -> n_static_syms = objfile -> static_psymbols.next -
+ (objfile -> static_psymbols.list + pst -> statics_offset);
+ sort_pst_symbols (pst);
+ /* If there is already a psymtab or symtab for a file of this name,
+ remove it. (If there is a symtab, more drastic things also
+ happen.) This happens in VxWorks. */
+ free_named_symtabs (pst -> filename);
+ }
+ thisdie = nextdie;
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ new_symbol -- make a symbol table entry for a new symbol
+
+SYNOPSIS
+
+ static struct symbol *new_symbol (struct dieinfo *dip,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to a DWARF information entry, figure out if we need
+ to make a symbol table entry for it, and if so, create a new entry
+ and return a pointer to it.
+ */
+
+static struct symbol *
+new_symbol (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ struct symbol *sym = NULL;
+
+ if (dip -> at_name != NULL)
+ {
+ sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack,
+ sizeof (struct symbol));
+ OBJSTAT (objfile, n_syms++);
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = create_name (dip -> at_name,
+ &objfile->symbol_obstack);
+ /* default assumptions */
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_TYPE (sym) = decode_die_type (dip);
+
+ /* If this symbol is from a C++ compilation, then attempt to cache the
+ demangled form for future reference. This is a typical time versus
+ space tradeoff, that was decided in favor of time because it sped up
+ C++ symbol lookups by a factor of about 20. */
+
+ SYMBOL_LANGUAGE (sym) = cu_language;
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile -> symbol_obstack);
+ switch (dip -> die_tag)
+ {
+ case TAG_label:
+ SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc;
+ SYMBOL_CLASS (sym) = LOC_LABEL;
+ break;
+ case TAG_global_subroutine:
+ case TAG_subroutine:
+ SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc;
+ SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ if (dip -> die_tag == TAG_global_subroutine)
+ {
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ else
+ {
+ add_symbol_to_list (sym, list_in_scope);
+ }
+ break;
+ case TAG_global_variable:
+ if (dip -> at_location != NULL)
+ {
+ SYMBOL_VALUE (sym) = locval (dip -> at_location);
+ add_symbol_to_list (sym, &global_symbols);
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE (sym) += baseaddr;
+ }
+ break;
+ case TAG_local_variable:
+ if (dip -> at_location != NULL)
+ {
+ SYMBOL_VALUE (sym) = locval (dip -> at_location);
+ add_symbol_to_list (sym, list_in_scope);
+ if (optimized_out)
+ {
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ }
+ else if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ }
+ else if (offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG;
+ SYMBOL_BASEREG (sym) = basereg;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE (sym) += baseaddr;
+ }
+ }
+ break;
+ case TAG_formal_parameter:
+ if (dip -> at_location != NULL)
+ {
+ SYMBOL_VALUE (sym) = locval (dip -> at_location);
+ }
+ add_symbol_to_list (sym, list_in_scope);
+ if (isreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ }
+ else if (offreg)
+ {
+ SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+ SYMBOL_BASEREG (sym) = basereg;
+ }
+ else
+ {
+ SYMBOL_CLASS (sym) = LOC_ARG;
+ }
+ break;
+ case TAG_unspecified_parameters:
+ /* From varargs functions; gdb doesn't seem to have any interest in
+ this information, so just ignore it for now. (FIXME?) */
+ break;
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ case TAG_enumeration_type:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ case TAG_typedef:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ break;
+ default:
+ /* Not a tag we recognize. Hopefully we aren't processing trash
+ data, but since we must specifically ignore things we don't
+ recognize, there is nothing else we should do at this point. */
+ break;
+ }
+ }
+ return (sym);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ synthesize_typedef -- make a symbol table entry for a "fake" typedef
+
+SYNOPSIS
+
+ static void synthesize_typedef (struct dieinfo *dip,
+ struct objfile *objfile,
+ struct type *type);
+
+DESCRIPTION
+
+ Given a pointer to a DWARF information entry, synthesize a typedef
+ for the name in the DIE, using the specified type.
+
+ This is used for C++ class, structs, unions, and enumerations to
+ set up the tag name as a type.
+
+ */
+
+static void
+synthesize_typedef (dip, objfile, type)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+ struct type *type;
+{
+ struct symbol *sym = NULL;
+
+ if (dip -> at_name != NULL)
+ {
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ OBJSTAT (objfile, n_syms++);
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = create_name (dip -> at_name,
+ &objfile->symbol_obstack);
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
+ SYMBOL_TYPE (sym) = type;
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, list_in_scope);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_mod_fund_type -- decode a modified fundamental type
+
+SYNOPSIS
+
+ static struct type *decode_mod_fund_type (char *typedata)
+
+DESCRIPTION
+
+ Decode a block of data containing a modified fundamental
+ type specification. TYPEDATA is a pointer to the block,
+ which starts with a length containing the size of the rest
+ of the block. At the end of the block is a fundmental type
+ code value that gives the fundamental type. Everything
+ in between are type modifiers.
+
+ We simply compute the number of modifiers and call the general
+ function decode_modified_type to do the actual work.
+*/
+
+static struct type *
+decode_mod_fund_type (typedata)
+ char *typedata;
+{
+ struct type *typep = NULL;
+ unsigned short modcount;
+ int nbytes;
+
+ /* Get the total size of the block, exclusive of the size itself */
+
+ nbytes = attribute_size (AT_mod_fund_type);
+ modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile);
+ typedata += nbytes;
+
+ /* Deduct the size of the fundamental type bytes at the end of the block. */
+
+ modcount -= attribute_size (AT_fund_type);
+
+ /* Now do the actual decoding */
+
+ typep = decode_modified_type (typedata, modcount, AT_mod_fund_type);
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_mod_u_d_type -- decode a modified user defined type
+
+SYNOPSIS
+
+ static struct type *decode_mod_u_d_type (char *typedata)
+
+DESCRIPTION
+
+ Decode a block of data containing a modified user defined
+ type specification. TYPEDATA is a pointer to the block,
+ which consists of a two byte length, containing the size
+ of the rest of the block. At the end of the block is a
+ four byte value that gives a reference to a user defined type.
+ Everything in between are type modifiers.
+
+ We simply compute the number of modifiers and call the general
+ function decode_modified_type to do the actual work.
+*/
+
+static struct type *
+decode_mod_u_d_type (typedata)
+ char *typedata;
+{
+ struct type *typep = NULL;
+ unsigned short modcount;
+ int nbytes;
+
+ /* Get the total size of the block, exclusive of the size itself */
+
+ nbytes = attribute_size (AT_mod_u_d_type);
+ modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile);
+ typedata += nbytes;
+
+ /* Deduct the size of the reference type bytes at the end of the block. */
+
+ modcount -= attribute_size (AT_user_def_type);
+
+ /* Now do the actual decoding */
+
+ typep = decode_modified_type (typedata, modcount, AT_mod_u_d_type);
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_modified_type -- decode modified user or fundamental type
+
+SYNOPSIS
+
+ static struct type *decode_modified_type (char *modifiers,
+ unsigned short modcount, int mtype)
+
+DESCRIPTION
+
+ Decode a modified type, either a modified fundamental type or
+ a modified user defined type. MODIFIERS is a pointer to the
+ block of bytes that define MODCOUNT modifiers. Immediately
+ following the last modifier is a short containing the fundamental
+ type or a long containing the reference to the user defined
+ type. Which one is determined by MTYPE, which is either
+ AT_mod_fund_type or AT_mod_u_d_type to indicate what modified
+ type we are generating.
+
+ We call ourself recursively to generate each modified type,`
+ until MODCOUNT reaches zero, at which point we have consumed
+ all the modifiers and generate either the fundamental type or
+ user defined type. When the recursion unwinds, each modifier
+ is applied in turn to generate the full modified type.
+
+NOTES
+
+ If we find a modifier that we don't recognize, and it is not one
+ of those reserved for application specific use, then we issue a
+ warning and simply ignore the modifier.
+
+BUGS
+
+ We currently ignore MOD_const and MOD_volatile. (FIXME)
+
+ */
+
+static struct type *
+decode_modified_type (modifiers, modcount, mtype)
+ char *modifiers;
+ unsigned int modcount;
+ int mtype;
+{
+ struct type *typep = NULL;
+ unsigned short fundtype;
+ DIE_REF die_ref;
+ char modifier;
+ int nbytes;
+
+ if (modcount == 0)
+ {
+ switch (mtype)
+ {
+ case AT_mod_fund_type:
+ nbytes = attribute_size (AT_fund_type);
+ fundtype = target_to_host (modifiers, nbytes, GET_UNSIGNED,
+ current_objfile);
+ typep = decode_fund_type (fundtype);
+ break;
+ case AT_mod_u_d_type:
+ nbytes = attribute_size (AT_user_def_type);
+ die_ref = target_to_host (modifiers, nbytes, GET_UNSIGNED,
+ current_objfile);
+ if ((typep = lookup_utype (die_ref)) == NULL)
+ {
+ typep = alloc_utype (die_ref, NULL);
+ }
+ break;
+ default:
+ complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype);
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ break;
+ }
+ }
+ else
+ {
+ modifier = *modifiers++;
+ typep = decode_modified_type (modifiers, --modcount, mtype);
+ switch (modifier)
+ {
+ case MOD_pointer_to:
+ typep = lookup_pointer_type (typep);
+ break;
+ case MOD_reference_to:
+ typep = lookup_reference_type (typep);
+ break;
+ case MOD_const:
+ complain (&const_ignored, DIE_ID, DIE_NAME); /* FIXME */
+ break;
+ case MOD_volatile:
+ complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */
+ break;
+ default:
+ if (!(MOD_lo_user <= (unsigned char) modifier
+ && (unsigned char) modifier <= MOD_hi_user))
+ {
+ complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier);
+ }
+ break;
+ }
+ }
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ decode_fund_type -- translate basic DWARF type to gdb base type
+
+DESCRIPTION
+
+ Given an integer that is one of the fundamental DWARF types,
+ translate it to one of the basic internal gdb types and return
+ a pointer to the appropriate gdb type (a "struct type *").
+
+NOTES
+
+ For robustness, if we are asked to translate a fundamental
+ type that we are unprepared to deal with, we return int so
+ callers can always depend upon a valid type being returned,
+ and so gdb may at least do something reasonable by default.
+ If the type is not in the range of those types defined as
+ application specific types, we also issue a warning.
+*/
+
+static struct type *
+decode_fund_type (fundtype)
+ unsigned int fundtype;
+{
+ struct type *typep = NULL;
+
+ switch (fundtype)
+ {
+
+ case FT_void:
+ typep = dwarf_fundamental_type (current_objfile, FT_VOID);
+ break;
+
+ case FT_boolean: /* Was FT_set in AT&T version */
+ typep = dwarf_fundamental_type (current_objfile, FT_BOOLEAN);
+ break;
+
+ case FT_pointer: /* (void *) */
+ typep = dwarf_fundamental_type (current_objfile, FT_VOID);
+ typep = lookup_pointer_type (typep);
+ break;
+
+ case FT_char:
+ typep = dwarf_fundamental_type (current_objfile, FT_CHAR);
+ break;
+
+ case FT_signed_char:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+ break;
+
+ case FT_unsigned_char:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+ break;
+
+ case FT_short:
+ typep = dwarf_fundamental_type (current_objfile, FT_SHORT);
+ break;
+
+ case FT_signed_short:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_SHORT);
+ break;
+
+ case FT_unsigned_short:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+ break;
+
+ case FT_integer:
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ break;
+
+ case FT_signed_integer:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+ break;
+
+ case FT_unsigned_integer:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+ break;
+
+ case FT_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_LONG);
+ break;
+
+ case FT_signed_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG);
+ break;
+
+ case FT_unsigned_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
+ break;
+
+ case FT_long_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_LONG_LONG);
+ break;
+
+ case FT_signed_long_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG);
+ break;
+
+ case FT_unsigned_long_long:
+ typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG);
+ break;
+
+ case FT_float:
+ typep = dwarf_fundamental_type (current_objfile, FT_FLOAT);
+ break;
+
+ case FT_dbl_prec_float:
+ typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+ break;
+
+ case FT_ext_prec_float:
+ typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
+ break;
+
+ case FT_complex:
+ typep = dwarf_fundamental_type (current_objfile, FT_COMPLEX);
+ break;
+
+ case FT_dbl_prec_complex:
+ typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
+ break;
+
+ case FT_ext_prec_complex:
+ typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX);
+ break;
+
+ }
+
+ if (typep == NULL)
+ {
+ typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+ if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
+ {
+ complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype);
+ }
+ }
+
+ return (typep);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ create_name -- allocate a fresh copy of a string on an obstack
+
+DESCRIPTION
+
+ Given a pointer to a string and a pointer to an obstack, allocates
+ a fresh copy of the string on the specified obstack.
+
+*/
+
+static char *
+create_name (name, obstackp)
+ char *name;
+ struct obstack *obstackp;
+{
+ int length;
+ char *newname;
+
+ length = strlen (name) + 1;
+ newname = (char *) obstack_alloc (obstackp, length);
+ strcpy (newname, name);
+ return (newname);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ basicdieinfo -- extract the minimal die info from raw die data
+
+SYNOPSIS
+
+ void basicdieinfo (char *diep, struct dieinfo *dip,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to raw DIE data, and a pointer to an instance of a
+ die info structure, this function extracts the basic information
+ from the DIE data required to continue processing this DIE, along
+ with some bookkeeping information about the DIE.
+
+ The information we absolutely must have includes the DIE tag,
+ and the DIE length. If we need the sibling reference, then we
+ will have to call completedieinfo() to process all the remaining
+ DIE information.
+
+ Note that since there is no guarantee that the data is properly
+ aligned in memory for the type of access required (indirection
+ through anything other than a char pointer), and there is no
+ guarantee that it is in the same byte order as the gdb host,
+ we call a function which deals with both alignment and byte
+ swapping issues. Possibly inefficient, but quite portable.
+
+ We also take care of some other basic things at this point, such
+ as ensuring that the instance of the die info structure starts
+ out completely zero'd and that curdie is initialized for use
+ in error reporting if we have a problem with the current die.
+
+NOTES
+
+ All DIE's must have at least a valid length, thus the minimum
+ DIE size is SIZEOF_DIE_LENGTH. In order to have a valid tag, the
+ DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they
+ are forced to be TAG_padding DIES.
+
+ Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying
+ that if a padding DIE is used for alignment and the amount needed is
+ less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big
+ enough to align to the next alignment boundry.
+
+ We do some basic sanity checking here, such as verifying that the
+ length of the die would not cause it to overrun the recorded end of
+ the buffer holding the DIE info. If we find a DIE that is either
+ too small or too large, we force it's length to zero which should
+ cause the caller to take appropriate action.
+ */
+
+static void
+basicdieinfo (dip, diep, objfile)
+ struct dieinfo *dip;
+ char *diep;
+ struct objfile *objfile;
+{
+ curdie = dip;
+ memset (dip, 0, sizeof (struct dieinfo));
+ dip -> die = diep;
+ dip -> die_ref = dbroff + (diep - dbbase);
+ dip -> die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED,
+ objfile);
+ if ((dip -> die_length < SIZEOF_DIE_LENGTH) ||
+ ((diep + dip -> die_length) > (dbbase + dbsize)))
+ {
+ complain (&malformed_die, DIE_ID, DIE_NAME, dip -> die_length);
+ dip -> die_length = 0;
+ }
+ else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
+ {
+ dip -> die_tag = TAG_padding;
+ }
+ else
+ {
+ diep += SIZEOF_DIE_LENGTH;
+ dip -> die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED,
+ objfile);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ completedieinfo -- finish reading the information for a given DIE
+
+SYNOPSIS
+
+ void completedieinfo (struct dieinfo *dip, struct objfile *objfile)
+
+DESCRIPTION
+
+ Given a pointer to an already partially initialized die info structure,
+ scan the raw DIE data and finish filling in the die info structure
+ from the various attributes found.
+
+ Note that since there is no guarantee that the data is properly
+ aligned in memory for the type of access required (indirection
+ through anything other than a char pointer), and there is no
+ guarantee that it is in the same byte order as the gdb host,
+ we call a function which deals with both alignment and byte
+ swapping issues. Possibly inefficient, but quite portable.
+
+NOTES
+
+ Each time we are called, we increment the diecount variable, which
+ keeps an approximate count of the number of dies processed for
+ each compilation unit. This information is presented to the user
+ if the info_verbose flag is set.
+
+ */
+
+static void
+completedieinfo (dip, objfile)
+ struct dieinfo *dip;
+ struct objfile *objfile;
+{
+ char *diep; /* Current pointer into raw DIE data */
+ char *end; /* Terminate DIE scan here */
+ unsigned short attr; /* Current attribute being scanned */
+ unsigned short form; /* Form of the attribute */
+ int nbytes; /* Size of next field to read */
+
+ diecount++;
+ diep = dip -> die;
+ end = diep + dip -> die_length;
+ diep += SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG;
+ while (diep < end)
+ {
+ attr = target_to_host (diep, SIZEOF_ATTRIBUTE, GET_UNSIGNED, objfile);
+ diep += SIZEOF_ATTRIBUTE;
+ if ((nbytes = attribute_size (attr)) == -1)
+ {
+ complain (&unknown_attribute_length, DIE_ID, DIE_NAME);
+ diep = end;
+ continue;
+ }
+ switch (attr)
+ {
+ case AT_fund_type:
+ dip -> at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_ordering:
+ dip -> at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_bit_offset:
+ dip -> at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_sibling:
+ dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_stmt_list:
+ dip -> at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> has_at_stmt_list = 1;
+ break;
+ case AT_low_pc:
+ dip -> at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> at_low_pc += baseaddr;
+ dip -> has_at_low_pc = 1;
+ break;
+ case AT_high_pc:
+ dip -> at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> at_high_pc += baseaddr;
+ break;
+ case AT_language:
+ dip -> at_language = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_user_def_type:
+ dip -> at_user_def_type = target_to_host (diep, nbytes,
+ GET_UNSIGNED, objfile);
+ break;
+ case AT_byte_size:
+ dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ dip -> has_at_byte_size = 1;
+ break;
+ case AT_bit_size:
+ dip -> at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_member:
+ dip -> at_member = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_discr:
+ dip -> at_discr = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_location:
+ dip -> at_location = diep;
+ break;
+ case AT_mod_fund_type:
+ dip -> at_mod_fund_type = diep;
+ break;
+ case AT_subscr_data:
+ dip -> at_subscr_data = diep;
+ break;
+ case AT_mod_u_d_type:
+ dip -> at_mod_u_d_type = diep;
+ break;
+ case AT_element_list:
+ dip -> at_element_list = diep;
+ dip -> short_element_list = 0;
+ break;
+ case AT_short_element_list:
+ dip -> at_element_list = diep;
+ dip -> short_element_list = 1;
+ break;
+ case AT_discr_value:
+ dip -> at_discr_value = diep;
+ break;
+ case AT_string_length:
+ dip -> at_string_length = diep;
+ break;
+ case AT_name:
+ dip -> at_name = diep;
+ break;
+ case AT_comp_dir:
+ /* For now, ignore any "hostname:" portion, since gdb doesn't
+ know how to deal with it. (FIXME). */
+ dip -> at_comp_dir = strrchr (diep, ':');
+ if (dip -> at_comp_dir != NULL)
+ {
+ dip -> at_comp_dir++;
+ }
+ else
+ {
+ dip -> at_comp_dir = diep;
+ }
+ break;
+ case AT_producer:
+ dip -> at_producer = diep;
+ break;
+ case AT_start_scope:
+ dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_stride_size:
+ dip -> at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_src_info:
+ dip -> at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED,
+ objfile);
+ break;
+ case AT_prototyped:
+ dip -> at_prototyped = diep;
+ break;
+ default:
+ /* Found an attribute that we are unprepared to handle. However
+ it is specifically one of the design goals of DWARF that
+ consumers should ignore unknown attributes. As long as the
+ form is one that we recognize (so we know how to skip it),
+ we can just ignore the unknown attribute. */
+ break;
+ }
+ form = FORM_FROM_ATTR (attr);
+ switch (form)
+ {
+ case FORM_DATA2:
+ diep += 2;
+ break;
+ case FORM_DATA4:
+ case FORM_REF:
+ diep += 4;
+ break;
+ case FORM_DATA8:
+ diep += 8;
+ break;
+ case FORM_ADDR:
+ diep += TARGET_FT_POINTER_SIZE (objfile);
+ break;
+ case FORM_BLOCK2:
+ diep += 2 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile);
+ break;
+ case FORM_BLOCK4:
+ diep += 4 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile);
+ break;
+ case FORM_STRING:
+ diep += strlen (diep) + 1;
+ break;
+ default:
+ complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
+ diep = end;
+ break;
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ target_to_host -- swap in target data to host
+
+SYNOPSIS
+
+ target_to_host (char *from, int nbytes, int signextend,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given pointer to data in target format in FROM, a byte count for
+ the size of the data in NBYTES, a flag indicating whether or not
+ the data is signed in SIGNEXTEND, and a pointer to the current
+ objfile in OBJFILE, convert the data to host format and return
+ the converted value.
+
+NOTES
+
+ FIXME: If we read data that is known to be signed, and expect to
+ use it as signed data, then we need to explicitly sign extend the
+ result until the bfd library is able to do this for us.
+
+ FIXME: Would a 32 bit target ever need an 8 byte result?
+
+ */
+
+static CORE_ADDR
+target_to_host (from, nbytes, signextend, objfile)
+ char *from;
+ int nbytes;
+ int signextend; /* FIXME: Unused */
+ struct objfile *objfile;
+{
+ CORE_ADDR rtnval;
+
+ switch (nbytes)
+ {
+ case 8:
+ rtnval = bfd_get_64 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ case 4:
+ rtnval = bfd_get_32 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ case 2:
+ rtnval = bfd_get_16 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ case 1:
+ rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from);
+ break;
+ default:
+ complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes);
+ rtnval = 0;
+ break;
+ }
+ return (rtnval);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ attribute_size -- compute size of data for a DWARF attribute
+
+SYNOPSIS
+
+ static int attribute_size (unsigned int attr)
+
+DESCRIPTION
+
+ Given a DWARF attribute in ATTR, compute the size of the first
+ piece of data associated with this attribute and return that
+ size.
+
+ Returns -1 for unrecognized attributes.
+
+ */
+
+static int
+attribute_size (attr)
+ unsigned int attr;
+{
+ int nbytes; /* Size of next data for this attribute */
+ unsigned short form; /* Form of the attribute */
+
+ form = FORM_FROM_ATTR (attr);
+ switch (form)
+ {
+ case FORM_STRING: /* A variable length field is next */
+ nbytes = 0;
+ break;
+ case FORM_DATA2: /* Next 2 byte field is the data itself */
+ case FORM_BLOCK2: /* Next 2 byte field is a block length */
+ nbytes = 2;
+ break;
+ case FORM_DATA4: /* Next 4 byte field is the data itself */
+ case FORM_BLOCK4: /* Next 4 byte field is a block length */
+ case FORM_REF: /* Next 4 byte field is a DIE offset */
+ nbytes = 4;
+ break;
+ case FORM_DATA8: /* Next 8 byte field is the data itself */
+ nbytes = 8;
+ break;
+ case FORM_ADDR: /* Next field size is target sizeof(void *) */
+ nbytes = TARGET_FT_POINTER_SIZE (objfile);
+ break;
+ default:
+ complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
+ nbytes = -1;
+ break;
+ }
+ return (nbytes);
+}
diff --git a/contrib/gdb/gdb/elfread.c b/contrib/gdb/gdb/elfread.c
new file mode 100644
index 0000000..9a7a0fe
--- /dev/null
+++ b/contrib/gdb/gdb/elfread.c
@@ -0,0 +1,826 @@
+/* Read ELF (Executable and Linking Format) object files for GDB.
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "gdb_string.h"
+#include "elf-bfd.h"
+#include "elf/mips.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "complaints.h"
+#include "demangle.h"
+
+/* The struct elfinfo is available only during ELF symbol table and
+ psymtab reading. It is destroyed at the complation of psymtab-reading.
+ It's local to elf_symfile_read. */
+
+struct elfinfo {
+ file_ptr dboffset; /* Offset to dwarf debug section */
+ unsigned int dbsize; /* Size of dwarf debug section */
+ file_ptr lnoffset; /* Offset to dwarf line number section */
+ 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... */
+
+struct complaint section_info_complaint =
+ {"elf/stab section information %s without a preceding file symbol", 0, 0};
+
+struct complaint section_info_dup_complaint =
+ {"duplicated elf/stab section information for %s", 0, 0};
+
+struct complaint stab_info_mismatch_complaint =
+ {"elf/stab section information missing for %s", 0, 0};
+
+struct complaint stab_info_questionable_complaint =
+ {"elf/stab section information questionable for %s", 0, 0};
+
+static void
+elf_symfile_init PARAMS ((struct objfile *));
+
+static void
+elf_new_init PARAMS ((struct objfile *));
+
+static void
+elf_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+elf_symfile_finish PARAMS ((struct objfile *));
+
+static void
+elf_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *, int));
+
+static void
+free_elfinfo PARAMS ((void *));
+
+static struct section_offsets *
+elf_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static struct minimal_symbol *
+record_minimal_symbol_and_info PARAMS ((char *, CORE_ADDR,
+ enum minimal_symbol_type, char *,
+ struct objfile *));
+
+static void
+elf_locate_sections PARAMS ((bfd *, asection *, void *));
+
+/* We are called once per section from elf_symfile_read. 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.
+
+ For now we recognize the dwarf debug information sections and
+ line number sections from matching their section names. The
+ ELF definition is no real help here since it has no direct
+ knowledge of DWARF (by design, so any debugging format can be
+ used).
+
+ We also recognize the ".stab" sections used by the Sun compilers
+ released with Solaris 2.
+
+ FIXME: The section names should not be hardwired strings (what
+ should they be? I don't think most object file formats have enough
+ section flags to specify what kind of debug section it is
+ -kingdon). */
+
+static void
+elf_locate_sections (ignore_abfd, sectp, eip)
+ bfd *ignore_abfd;
+ asection *sectp;
+ PTR eip;
+{
+ register struct elfinfo *ei;
+
+ ei = (struct elfinfo *) eip;
+ if (STREQ (sectp -> name, ".debug"))
+ {
+ ei -> dboffset = sectp -> filepos;
+ ei -> dbsize = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp -> name, ".line"))
+ {
+ ei -> lnoffset = sectp -> filepos;
+ ei -> lnsize = bfd_get_section_size_before_reloc (sectp);
+ }
+ else if (STREQ (sectp -> name, ".stab"))
+ {
+ ei -> stabsect = sectp;
+ }
+ else if (STREQ (sectp -> name, ".stab.index"))
+ {
+ ei -> stabindexsect = sectp;
+ }
+ else if (STREQ (sectp -> name, ".mdebug"))
+ {
+ ei -> mdebugsect = sectp;
+ }
+}
+
+#if 0 /* Currently unused */
+
+char *
+elf_interpreter (abfd)
+ bfd *abfd;
+{
+ sec_ptr interp_sec;
+ unsigned size;
+ char *interp = NULL;
+
+ interp_sec = bfd_get_section_by_name (abfd, ".interp");
+ if (interp_sec)
+ {
+ size = bfd_section_size (abfd, interp_sec);
+ interp = alloca (size);
+ if (bfd_get_section_contents (abfd, interp_sec, interp, (file_ptr)0,
+ size))
+ {
+ interp = savestring (interp, size - 1);
+ }
+ else
+ {
+ interp = NULL;
+ }
+ }
+ return (interp);
+}
+
+#endif
+
+static struct minimal_symbol *
+record_minimal_symbol_and_info (name, address, ms_type, info, objfile)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ char *info; /* FIXME, is this really char *? */
+ struct objfile *objfile;
+{
+ int section;
+
+ /* Guess the section from the type. This is likely to be wrong in
+ some cases. */
+ switch (ms_type)
+ {
+ 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:
+ section = SECT_OFF_DATA;
+ break;
+ case mst_bss:
+ case mst_file_bss:
+ section = SECT_OFF_BSS;
+ break;
+ default:
+ section = -1;
+ break;
+ }
+
+ name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
+ return prim_record_minimal_symbol_and_info
+ (name, address, ms_type, info, section, objfile);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ elf_symtab_read -- read the symbol table of an ELF file
+
+SYNOPSIS
+
+ void elf_symtab_read (bfd *abfd, CORE_ADDR addr,
+ struct objfile *objfile, int dynamic)
+
+DESCRIPTION
+
+ Given an open bfd, a base address to relocate symbols to, and a
+ flag that specifies whether or not this bfd is for an executable
+ or not (may be shared library for example), add all the global
+ function and data symbols to the minimal symbol table.
+
+ In stabs-in-ELF, as implemented by Sun, there are some local symbols
+ defined in the ELF symbol table, which can be used to locate
+ the beginnings of sections from each ".o" file that was linked to
+ form the executable objfile. We gather any such info and record it
+ in data structures hung off the objfile's private data.
+
+*/
+
+static void
+elf_symtab_read (abfd, addr, objfile, dynamic)
+ bfd *abfd;
+ CORE_ADDR addr;
+ struct objfile *objfile;
+ int dynamic;
+{
+ long storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ long number_of_symbols;
+ long i;
+ int index;
+ struct cleanup *back_to;
+ CORE_ADDR symaddr;
+ enum minimal_symbol_type ms_type;
+ /* If sectinfo is nonNULL, it contains section info that should end up
+ filed in the objfile. */
+ struct stab_section_info *sectinfo = NULL;
+ /* If filesym is nonzero, it points to a file symbol, but we haven't
+ seen any section info for it yet. */
+ asymbol *filesym = 0;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Name of filesym, as saved on the symbol_obstack. */
+ char *filesymname = obsavestring ("", 0, &objfile->symbol_obstack);
+#endif
+ struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
+ objfile->sym_stab_info;
+ unsigned long size;
+ 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);
+ 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];
+ if (sym -> name == NULL || *sym -> name == '\0')
+ {
+ /* Skip names that don't exist (shouldn't happen), or names
+ that are null strings (may happen). */
+ continue;
+ }
+
+ if (dynamic
+ && sym -> section == &bfd_und_section
+ && (sym -> flags & BSF_FUNCTION))
+ {
+ struct minimal_symbol *msym;
+
+ /* Symbol is a reference to a function defined in
+ a shared library.
+ If its value is non zero then it is usually the address
+ of the corresponding entry in the procedure linkage table,
+ relative to the base address.
+ 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. */
+ symaddr = sym -> value;
+ if (symaddr == 0)
+ continue;
+ symaddr += addr;
+ msym = record_minimal_symbol_and_info
+ ((char *) sym -> name, symaddr,
+ mst_solib_trampoline, NULL, objfile);
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (msym != NULL)
+ msym->filename = filesymname;
+#endif
+ 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. */
+ if (dynamic && !stripped)
+ continue;
+ if (sym -> flags & BSF_FILE)
+ {
+ /* STT_FILE debugging symbol that helps stabs-in-elf debugging.
+ Chain any old one onto the objfile; remember new sym. */
+ if (sectinfo != NULL)
+ {
+ sectinfo -> next = dbx -> stab_section_info;
+ dbx -> stab_section_info = sectinfo;
+ sectinfo = NULL;
+ }
+ filesym = sym;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ filesymname =
+ obsavestring ((char *)filesym->name, strlen (filesym->name),
+ &objfile->symbol_obstack);
+#endif
+ }
+ else if (sym -> flags & (BSF_GLOBAL | BSF_LOCAL | BSF_WEAK))
+ {
+ struct minimal_symbol *msym;
+
+ /* Select global/local/weak symbols. Note that bfd puts abs
+ symbols in their own section, so all symbols we are
+ interested in will have a section. */
+ /* 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;
+ }
+ /* 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)
+ {
+ /* 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)
+ {
+ 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;
+ default:
+ ms_type = mst_abs;
+ }
+ }
+ else if (sym -> section -> flags & SEC_CODE)
+ {
+ if (sym -> flags & BSF_GLOBAL)
+ {
+ ms_type = mst_text;
+ }
+ else if ((sym->name[0] == '.' && sym->name[1] == 'L')
+ || ((sym -> flags & BSF_LOCAL)
+ && sym->name[0] == '$'
+ && 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
+ delta m88k SVR4, it loses. So to have us check too
+ should be harmless (but I encourage people to fix this
+ in the assembler instead of adding checks here). */
+ continue;
+ else
+ {
+ ms_type = mst_file_text;
+ }
+ }
+ else if (sym -> section -> flags & SEC_ALLOC)
+ {
+ if (sym -> flags & BSF_GLOBAL)
+ {
+ if (sym -> section -> flags & SEC_LOAD)
+ {
+ ms_type = mst_data;
+ }
+ else
+ {
+ ms_type = mst_bss;
+ }
+ }
+ else if (sym -> flags & BSF_LOCAL)
+ {
+ /* Named Local variable in a Data section. Check its
+ name for stabs-in-elf. The STREQ macro checks the
+ first character inline, so we only actually do a
+ strcmp function call on names that start with 'B'
+ or 'D' */
+ index = SECT_OFF_MAX;
+ if (STREQ ("Bbss.bss", sym -> name))
+ {
+ index = SECT_OFF_BSS;
+ }
+ else if (STREQ ("Ddata.data", sym -> name))
+ {
+ index = SECT_OFF_DATA;
+ }
+ else if (STREQ ("Drodata.rodata", sym -> name))
+ {
+ index = SECT_OFF_RODATA;
+ }
+ if (index != SECT_OFF_MAX)
+ {
+ /* Found a special local symbol. Allocate a
+ sectinfo, if needed, and fill it in. */
+ if (sectinfo == NULL)
+ {
+ sectinfo = (struct stab_section_info *)
+ xmmalloc (objfile -> md, sizeof (*sectinfo));
+ memset ((PTR) sectinfo, 0, sizeof (*sectinfo));
+ if (filesym == NULL)
+ {
+ complain (&section_info_complaint,
+ sym -> name);
+ }
+ else
+ {
+ sectinfo -> filename =
+ (char *) filesym -> name;
+ }
+ }
+ if (sectinfo -> sections[index] != 0)
+ {
+ complain (&section_info_dup_complaint,
+ sectinfo -> filename);
+ }
+ /* Bfd symbols are section relative. */
+ symaddr = sym -> value + sym -> section -> vma;
+ /* Relocate non-absolute symbols by base address. */
+ if (sym -> section != &bfd_abs_section)
+ {
+ symaddr += addr;
+ }
+ sectinfo -> sections[index] = symaddr;
+ /* The special local symbols don't go in the
+ minimal symbol table, so ignore this one. */
+ continue;
+ }
+ /* Not a special stabs-in-elf symbol, do regular
+ symbol processing. */
+ if (sym -> section -> flags & SEC_LOAD)
+ {
+ ms_type = mst_file_data;
+ }
+ else
+ {
+ ms_type = mst_file_bss;
+ }
+ }
+ else
+ {
+ ms_type = mst_unknown;
+ }
+ }
+ else
+ {
+ /* FIXME: Solaris2 shared libraries include lots of
+ odd "absolute" and "undefined" symbols, that play
+ hob with actions like finding what function the PC
+ is in. Ignore them if they aren't text, data, or bss. */
+ /* ms_type = mst_unknown; */
+ continue; /* Skip this symbol. */
+ }
+ /* Pass symbol size field in via BFD. FIXME!!! */
+ size = ((elf_symbol_type *) sym) -> internal_elf_sym.st_size;
+ msym = record_minimal_symbol_and_info
+ ((char *) sym -> name, symaddr,
+ ms_type, (PTR) size, objfile);
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (msym != NULL)
+ msym->filename = filesymname;
+#endif
+ }
+ }
+ do_cleanups (back_to);
+ }
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to elf_symfile_init, which
+ currently does nothing.
+
+ SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
+ in each section. We simplify it down to a single offset for all
+ symbols. FIXME.
+
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file).
+
+ This function 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.
+
+ We look for sections with specific names, to tell us what debug
+ format to look for: FIXME!!!
+
+ dwarf_build_psymtabs() builds psymtabs for DWARF 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
+ for linking. We process this also, and use the information to
+ build gdb's minimal symbol table. This gives us some minimal debugging
+ capability even for files compiled without -g. */
+
+static void
+elf_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline;
+{
+ bfd *abfd = objfile->obfd;
+ struct elfinfo ei;
+ struct cleanup *back_to;
+ CORE_ADDR offset;
+
+ init_minimal_symbol_collection ();
+ back_to = make_cleanup (discard_minimal_symbols, 0);
+
+ memset ((char *) &ei, 0, sizeof (ei));
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (PTR)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+ memset ((char *) objfile->sym_stab_info, 0, sizeof (struct dbx_symfile_info));
+ make_cleanup (free_elfinfo, (PTR) objfile);
+
+ /* Process the normal ELF symbol table first. This may write some
+ chain of info into the dbx_symfile_info in objfile->sym_stab_info,
+ which can later be used by elfstab_offset_sections. */
+
+ /* FIXME, should take a section_offsets param, not just an offset. */
+ offset = ANOFFSET (section_offsets, 0);
+ 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... */
+
+ bfd_map_over_sections (abfd, elf_locate_sections, (PTR) &ei);
+ if (ei.dboffset && ei.lnoffset)
+ {
+ /* DWARF sections */
+ dwarf_build_psymtabs (objfile,
+ section_offsets, mainline,
+ ei.dboffset, ei.dbsize,
+ ei.lnoffset, ei.lnsize);
+ }
+ if (ei.stabsect)
+ {
+ asection *str_sect;
+
+ /* Stab sections have an associated string table that looks like
+ a separate section. */
+ str_sect = bfd_get_section_by_name (abfd, ".stabstr");
+
+ /* FIXME should probably warn about a stab section without a stabstr. */
+ if (str_sect)
+ elfstab_build_psymtabs (objfile,
+ section_offsets,
+ mainline,
+ ei.stabsect->filepos,
+ bfd_section_size (abfd, ei.stabsect),
+ str_sect->filepos,
+ bfd_section_size (abfd, str_sect));
+ }
+ if (ei.mdebugsect)
+ {
+ 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
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ do_cleanups (back_to);
+}
+
+/* This cleans up the objfile's sym_stab_info pointer, and the chain of
+ stab_section_info's, that might be dangling from it. */
+
+static void
+free_elfinfo (objp)
+ PTR objp;
+{
+ struct objfile *objfile = (struct objfile *)objp;
+ struct dbx_symfile_info *dbxinfo = (struct dbx_symfile_info *)
+ objfile->sym_stab_info;
+ struct stab_section_info *ssi, *nssi;
+
+ ssi = dbxinfo->stab_section_info;
+ while (ssi)
+ {
+ nssi = ssi->next;
+ mfree (objfile->md, ssi);
+ ssi = nssi;
+ }
+
+ dbxinfo->stab_section_info = 0; /* Just say No mo info about this. */
+}
+
+
+/* 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).
+
+ We reinitialize buildsym, since we may be reading stabs from an ELF file. */
+
+static void
+elf_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+/* 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. */
+
+static void
+elf_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_stab_info);
+ }
+}
+
+/* ELF specific initialization routine for reading symbols.
+
+ It is passed a pointer to a struct sym_fns which contains, among other
+ things, the BFD for the file whose symbols are being read, and a slot for
+ a pointer to "private data" which we can fill with goodies.
+
+ For now at least, we have nothing in particular to do, so this function is
+ just a stub. */
+
+static void
+elf_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ /* ELF objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+}
+
+/* ELF specific parsing routine for section offsets.
+
+ Plain and simple for now. */
+
+static
+struct section_offsets *
+elf_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+/* When handling an ELF file that contains Sun STABS debug info,
+ some of the debug info is relative to the particular chunk of the
+ section that was generated in its individual .o file. E.g.
+ offsets to static variables are relative to the start of the data
+ segment *for that module before linking*. This information is
+ painfully squirreled away in the ELF symbol table as local symbols
+ with wierd names. Go get 'em when needed. */
+
+void
+elfstab_offset_sections (objfile, pst)
+ struct objfile *objfile;
+ struct partial_symtab *pst;
+{
+ char *filename = pst->filename;
+ struct dbx_symfile_info *dbx = (struct dbx_symfile_info *)
+ objfile->sym_stab_info;
+ struct stab_section_info *maybe = dbx->stab_section_info;
+ struct stab_section_info *questionable = 0;
+ int i;
+ char *p;
+
+ /* The ELF symbol info doesn't include path names, so strip the path
+ (if any) from the psymtab filename. */
+ while (0 != (p = strchr (filename, '/')))
+ filename = p+1;
+
+ /* FIXME: This linear search could speed up significantly
+ if it was chained in the right order to match how we search it,
+ and if we unchained when we found a match. */
+ for (; maybe; maybe = maybe->next)
+ {
+ if (filename[0] == maybe->filename[0]
+ && STREQ (filename, maybe->filename))
+ {
+ /* We found a match. But there might be several source files
+ (from different directories) with the same name. */
+ if (0 == maybe->found)
+ break;
+ questionable = maybe; /* Might use it later. */
+ }
+ }
+
+ if (maybe == 0 && questionable != 0)
+ {
+ complain (&stab_info_questionable_complaint, filename);
+ maybe = questionable;
+ }
+
+ if (maybe)
+ {
+ /* Found it! Allocate a new psymtab struct, and fill it in. */
+ maybe->found++;
+ pst->section_offsets = (struct section_offsets *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct section_offsets) +
+ sizeof (pst->section_offsets->offsets) * (SECT_OFF_MAX-1));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (pst->section_offsets, i) = maybe->sections[i];
+ return;
+ }
+
+ /* We were unable to find any offsets for this file. Complain. */
+ if (dbx->stab_section_info) /* If there *is* any info, */
+ complain (&stab_info_mismatch_complaint, filename);
+}
+
+/* Register that we are able to handle ELF object file formats. */
+
+static struct sym_fns elf_sym_fns =
+{
+ 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 */
+ elf_symfile_finish, /* sym_finish: finished with file, cleanup */
+ elf_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_elfread ()
+{
+ add_symtab_fns (&elf_sym_fns);
+}
diff --git a/contrib/gdb/gdb/environ.c b/contrib/gdb/gdb/environ.c
new file mode 100644
index 0000000..77296be
--- /dev/null
+++ b/contrib/gdb/gdb/environ.c
@@ -0,0 +1,194 @@
+/* environ.c -- library for manipulating environments for GNU.
+ Copyright (C) 1986, 1989 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
+
+#include "defs.h"
+#include "environ.h"
+#include "gdb_string.h"
+#include "gdbcore.h"
+
+
+/* Return a new environment object. */
+
+struct environ *
+make_environ ()
+{
+ register struct environ *e;
+
+ e = (struct environ *) xmalloc (sizeof (struct environ));
+
+ e->allocated = 10;
+ e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
+ e->vector[0] = 0;
+ return e;
+}
+
+/* Free an environment and all the strings in it. */
+
+void
+free_environ (e)
+ register struct environ *e;
+{
+ register char **vector = e->vector;
+
+ while (*vector)
+ free (*vector++);
+
+ free (e);
+}
+
+/* Copy the environment given to this process into E.
+ Also copies all the strings in it, so we can be sure
+ that all strings in these environments are safe to free. */
+
+void
+init_environ (e)
+ register struct environ *e;
+{
+ extern char **environ;
+ register int i;
+
+ if (environ == NULL)
+ return;
+
+ for (i = 0; environ[i]; i++) /*EMPTY*/;
+
+ if (e->allocated < i)
+ {
+ e->allocated = max (i, e->allocated + 10);
+ e->vector = (char **) xrealloc ((char *)e->vector,
+ (e->allocated + 1) * sizeof (char *));
+ }
+
+ memcpy (e->vector, environ, (i + 1) * sizeof (char *));
+
+ while (--i >= 0)
+ {
+ register int len = strlen (e->vector[i]);
+ register char *new = (char *) xmalloc (len + 1);
+ memcpy (new, e->vector[i], len + 1);
+ e->vector[i] = new;
+ }
+}
+
+/* Return the vector of environment E.
+ This is used to get something to pass to execve. */
+
+char **
+environ_vector (e)
+ struct environ *e;
+{
+ return e->vector;
+}
+
+/* Return the value in environment E of variable VAR. */
+
+char *
+get_in_environ (e, var)
+ const struct environ *e;
+ const char *var;
+{
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (; (s = *vector) != NULL; vector++)
+ if (STREQN (s, var, len) && s[len] == '=')
+ return &s[len + 1];
+
+ return 0;
+}
+
+/* Store the value in E of VAR as VALUE. */
+
+void
+set_in_environ (e, var, value)
+ struct environ *e;
+ const char *var;
+ const char *value;
+{
+ register int i;
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (i = 0; (s = vector[i]) != NULL; i++)
+ if (STREQN (s, var, len) && s[len] == '=')
+ break;
+
+ if (s == 0)
+ {
+ if (i == e->allocated)
+ {
+ e->allocated += 10;
+ vector = (char **) xrealloc ((char *)vector,
+ (e->allocated + 1) * sizeof (char *));
+ e->vector = vector;
+ }
+ vector[i + 1] = 0;
+ }
+ else
+ free (s);
+
+ s = (char *) xmalloc (len + strlen (value) + 2);
+ strcpy (s, var);
+ strcat (s, "=");
+ strcat (s, value);
+ vector[i] = 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? */
+
+ return;
+}
+
+/* Remove the setting for variable VAR from environment E. */
+
+void
+unset_in_environ (e, var)
+ struct environ *e;
+ char *var;
+{
+ register int len = strlen (var);
+ register char **vector = e->vector;
+ register char *s;
+
+ for (; (s = *vector) != NULL; vector++)
+ {
+ if (STREQN (s, var, len) && s[len] == '=')
+ {
+ free (s);
+ /* Walk through the vector, shuffling args down by one, including
+ the NULL terminator. Can't use memcpy() here since the regions
+ overlap, and memmove() might not be available. */
+ while ((vector[0] = vector[1]) != NULL)
+ {
+ vector++;
+ }
+ break;
+ }
+ }
+}
diff --git a/contrib/gdb/gdb/environ.h b/contrib/gdb/gdb/environ.h
new file mode 100644
index 0000000..87a538a
--- /dev/null
+++ b/contrib/gdb/gdb/environ.h
@@ -0,0 +1,58 @@
+/* Header for environment manipulation library.
+ Copyright 1989, 1992 Free Software Foundation.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (ENVIRON_H)
+#define ENVIRON_H 1
+
+/* We manipulate environments represented as these structures. */
+
+struct environ
+{
+ /* Number of usable slots allocated in VECTOR.
+ VECTOR always has one slot not counted here,
+ to hold the terminating zero. */
+ int allocated;
+ /* A vector of slots, ALLOCATED + 1 of them.
+ The first few slots contain strings "VAR=VALUE"
+ and the next one contains zero.
+ Then come some unused slots. */
+ char **vector;
+};
+
+extern struct environ *
+make_environ PARAMS ((void));
+
+extern void
+free_environ PARAMS ((struct environ *));
+
+extern void
+init_environ PARAMS ((struct environ *));
+
+extern char *
+get_in_environ PARAMS ((const struct environ *, const char *));
+
+extern void
+set_in_environ PARAMS ((struct environ *, const char *,
+ const char *));
+
+extern void
+unset_in_environ PARAMS ((struct environ *, char *));
+
+extern char **
+environ_vector PARAMS ((struct environ *));
+
+#endif /* defined (ENVIRON_H) */
diff --git a/contrib/gdb/gdb/eval.c b/contrib/gdb/gdb/eval.c
new file mode 100644
index 0000000..ed9fd53
--- /dev/null
+++ b/contrib/gdb/gdb/eval.c
@@ -0,0 +1,1780 @@
+/* Evaluate expressions for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#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 */
+#include "f-lang.h" /* for array bound stuff */
+
+/* Prototypes for local functions. */
+
+static value_ptr evaluate_subexp_for_sizeof PARAMS ((struct expression *,
+ int *));
+
+static value_ptr evaluate_subexp_for_address PARAMS ((struct expression *,
+ int *, enum noside));
+
+#ifdef __GNUC__
+inline
+#endif
+static value_ptr
+evaluate_subexp (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ return (*exp->language_defn->evaluate_exp) (expect_type, exp, pos, noside);
+}
+
+/* Parse the string EXP as a C expression, evaluate it,
+ and return the result as a number. */
+
+CORE_ADDR
+parse_and_eval_address (exp)
+ char *exp;
+{
+ struct expression *expr = parse_expression (exp);
+ register CORE_ADDR addr;
+ register struct cleanup *old_chain =
+ make_cleanup (free_current_contents, &expr);
+
+ addr = value_as_pointer (evaluate_expression (expr));
+ do_cleanups (old_chain);
+ return addr;
+}
+
+/* Like parse_and_eval_address but takes a pointer to a char * variable
+ and advanced that variable across the characters parsed. */
+
+CORE_ADDR
+parse_and_eval_address_1 (expptr)
+ char **expptr;
+{
+ struct expression *expr = parse_exp_1 (expptr, (struct block *)0, 0);
+ register CORE_ADDR addr;
+ register struct cleanup *old_chain =
+ make_cleanup (free_current_contents, &expr);
+
+ addr = value_as_pointer (evaluate_expression (expr));
+ do_cleanups (old_chain);
+ return addr;
+}
+
+value_ptr
+parse_and_eval (exp)
+ char *exp;
+{
+ struct expression *expr = parse_expression (exp);
+ register value_ptr val;
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+ do_cleanups (old_chain);
+ return val;
+}
+
+/* Parse up to a comma (or to a closeparen)
+ in the string EXPP as an expression, evaluate it, and return the value.
+ EXPP is advanced to point to the comma. */
+
+value_ptr
+parse_to_comma_and_eval (expp)
+ char **expp;
+{
+ struct expression *expr = parse_exp_1 (expp, (struct block *) 0, 1);
+ register value_ptr val;
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+ do_cleanups (old_chain);
+ return val;
+}
+
+/* Evaluate an expression in internal prefix form
+ such as is constructed by parse.y.
+
+ See expression.h for info on the format of an expression. */
+
+value_ptr
+evaluate_expression (exp)
+ struct expression *exp;
+{
+ int pc = 0;
+ return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_NORMAL);
+}
+
+/* Evaluate an expression, avoiding all memory references
+ and getting a value whose type alone is correct. */
+
+value_ptr
+evaluate_type (exp)
+ struct expression *exp;
+{
+ int pc = 0;
+ return evaluate_subexp (NULL_TYPE, exp, &pc, EVAL_AVOID_SIDE_EFFECTS);
+}
+
+/* If the next expression is an OP_LABELED, skips past it,
+ returning the label. Otherwise, does nothing and returns NULL. */
+
+static char*
+get_label (exp, pos)
+ register struct expression *exp;
+ int *pos;
+{
+ if (exp->elts[*pos].opcode == OP_LABELED)
+ {
+ int pc = (*pos)++;
+ char *name = &exp->elts[pc + 2].string;
+ int tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ return name;
+ }
+ else
+ return NULL;
+}
+
+/* This function evaluates tupes (in Chill) or brace-initializers
+ (in C/C++) for structure types. */
+
+static value_ptr
+evaluate_struct_tuple (struct_val, exp, pos, noside, nargs)
+ value_ptr struct_val;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+ int nargs;
+{
+ struct type *struct_type = check_typedef (VALUE_TYPE (struct_val));
+ struct type *substruct_type = struct_type;
+ struct type *field_type;
+ int fieldno = -1;
+ int variantno = -1;
+ int subfieldno = -1;
+ while (--nargs >= 0)
+ {
+ int pc = *pos;
+ value_ptr val = NULL;
+ int nlabels = 0;
+ int bitpos, bitsize;
+ char *addr;
+
+ /* Skip past the labels, and count them. */
+ while (get_label (exp, pos) != NULL)
+ nlabels++;
+
+ do
+ {
+ char *label = get_label (exp, &pc);
+ if (label)
+ {
+ for (fieldno = 0; fieldno < TYPE_NFIELDS (struct_type);
+ fieldno++)
+ {
+ char *field_name = TYPE_FIELD_NAME (struct_type, fieldno);
+ if (field_name != NULL && STREQ (field_name, label))
+ {
+ variantno = -1;
+ subfieldno = fieldno;
+ substruct_type = struct_type;
+ goto found;
+ }
+ }
+ for (fieldno = 0; fieldno < TYPE_NFIELDS (struct_type);
+ fieldno++)
+ {
+ char *field_name = TYPE_FIELD_NAME (struct_type, fieldno);
+ field_type = TYPE_FIELD_TYPE (struct_type, fieldno);
+ if ((field_name == 0 || *field_name == '\0')
+ && TYPE_CODE (field_type) == TYPE_CODE_UNION)
+ {
+ variantno = 0;
+ for (; variantno < TYPE_NFIELDS (field_type);
+ variantno++)
+ {
+ substruct_type
+ = TYPE_FIELD_TYPE (field_type, variantno);
+ if (TYPE_CODE (substruct_type) == TYPE_CODE_STRUCT)
+ {
+ for (subfieldno = 0;
+ subfieldno < TYPE_NFIELDS (substruct_type);
+ subfieldno++)
+ {
+ if (STREQ (TYPE_FIELD_NAME (substruct_type,
+ subfieldno),
+ label))
+ {
+ goto found;
+ }
+ }
+ }
+ }
+ }
+ }
+ error ("there is no field named %s", label);
+ found:
+ ;
+ }
+ else
+ {
+ /* Unlabelled tuple element - go to next field. */
+ if (variantno >= 0)
+ {
+ subfieldno++;
+ if (subfieldno >= TYPE_NFIELDS (substruct_type))
+ {
+ variantno = -1;
+ substruct_type = struct_type;
+ }
+ }
+ if (variantno < 0)
+ {
+ fieldno++;
+ subfieldno = fieldno;
+ if (fieldno >= TYPE_NFIELDS (struct_type))
+ error ("too many initializers");
+ field_type = TYPE_FIELD_TYPE (struct_type, fieldno);
+ if (TYPE_CODE (field_type) == TYPE_CODE_UNION
+ && TYPE_FIELD_NAME (struct_type, fieldno)[0] == '0')
+ error ("don't know which variant you want to set");
+ }
+ }
+
+ /* Here, struct_type is the type of the inner struct,
+ while substruct_type is the type of the inner struct.
+ These are the same for normal structures, but a variant struct
+ contains anonymous union fields that contain substruct fields.
+ The value fieldno is the index of the top-level (normal or
+ anonymous union) field in struct_field, while the value
+ subfieldno is the index of the actual real (named inner) field
+ in substruct_type. */
+
+ field_type = TYPE_FIELD_TYPE (substruct_type, subfieldno);
+ if (val == 0)
+ val = evaluate_subexp (field_type, exp, pos, noside);
+
+ /* Now actually set the field in struct_val. */
+
+ /* Assign val to field fieldno. */
+ if (VALUE_TYPE (val) != field_type)
+ val = value_cast (field_type, val);
+
+ bitsize = TYPE_FIELD_BITSIZE (substruct_type, subfieldno);
+ bitpos = TYPE_FIELD_BITPOS (struct_type, fieldno);
+ if (variantno >= 0)
+ bitpos += TYPE_FIELD_BITPOS (substruct_type, subfieldno);
+ addr = VALUE_CONTENTS (struct_val) + bitpos / 8;
+ if (bitsize)
+ modify_field (addr, value_as_long (val),
+ bitpos % 8, bitsize);
+ else
+ memcpy (addr, VALUE_CONTENTS (val),
+ TYPE_LENGTH (VALUE_TYPE (val)));
+ } while (--nlabels > 0);
+ }
+ return struct_val;
+}
+
+/* Recursive helper function for setting elements of array tuples for Chill.
+ The target is ARRAY (which has bounds LOW_BOUND to HIGH_BOUND);
+ the element value is ELEMENT;
+ EXP, POS and NOSIDE are as usual.
+ Evaluates index expresions and sets the specified element(s) of
+ ARRAY to ELEMENT.
+ Returns last index value. */
+
+static LONGEST
+init_array_element (array, element, exp, pos, noside, low_bound, high_bound)
+ value_ptr array, element;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ LONGEST index;
+ int element_size = TYPE_LENGTH (VALUE_TYPE (element));
+ if (exp->elts[*pos].opcode == BINOP_COMMA)
+ {
+ (*pos)++;
+ init_array_element (array, element, exp, pos, noside,
+ low_bound, high_bound);
+ return init_array_element (array, element,
+ exp, pos, noside, low_bound, high_bound);
+ }
+ else if (exp->elts[*pos].opcode == BINOP_RANGE)
+ {
+ LONGEST low, high;
+ (*pos)++;
+ low = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ high = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ if (low < low_bound || high > high_bound)
+ error ("tuple range index out of range");
+ for (index = low ; index <= high; index++)
+ {
+ memcpy (VALUE_CONTENTS_RAW (array)
+ + (index - low_bound) * element_size,
+ VALUE_CONTENTS (element), element_size);
+ }
+ }
+ else
+ {
+ index = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ if (index < low_bound || index > high_bound)
+ error ("tuple index out of range");
+ memcpy (VALUE_CONTENTS_RAW (array) + (index - low_bound) * element_size,
+ VALUE_CONTENTS (element), element_size);
+ }
+ return index;
+}
+
+value_ptr
+evaluate_subexp_standard (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op;
+ int tem, tem2, tem3;
+ register int pc, pc2 = 0, oldpos;
+ register value_ptr arg1 = NULL, arg2 = NULL, arg3;
+ struct type *type;
+ int nargs;
+ value_ptr *argvec;
+ int upper, lower, retcode;
+ int code;
+
+ /* This expect_type crap should not be used for C. C expressions do
+ not have any notion of expected types, never has and (goddess
+ willing) never will. The C++ code uses it for some twisted
+ purpose (I haven't investigated but I suspect it just the usual
+ combination of Stroustrup figuring out some crazy language
+ feature and Tiemann figuring out some crazier way to try to
+ implement it). CHILL has the tuple stuff; I don't know enough
+ about CHILL to know whether expected types is the way to do it.
+ FORTRAN I don't know. */
+ if (exp->language_defn->la_language != language_cplus
+ && exp->language_defn->la_language != language_chill)
+ expect_type = NULL_TYPE;
+
+ pc = (*pos)++;
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case OP_SCOPE:
+ tem = longest_to_int (exp->elts[pc + 2].longconst);
+ (*pos) += 4 + BYTES_TO_EXP_ELEM (tem + 1);
+ arg1 = value_struct_elt_for_reference (exp->elts[pc + 1].type,
+ 0,
+ exp->elts[pc + 1].type,
+ &exp->elts[pc + 3].string,
+ expect_type);
+ if (arg1 == NULL)
+ error ("There is no field named %s", &exp->elts[pc + 3].string);
+ return arg1;
+
+ case OP_LONG:
+ (*pos) += 3;
+ return value_from_longest (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].longconst);
+
+ case OP_DOUBLE:
+ (*pos) += 3;
+ return value_from_double (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].doubleconst);
+
+ case OP_VAR_VALUE:
+ (*pos) += 3;
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct symbol * sym = exp->elts[pc + 2].symbol;
+ enum lval_type lv;
+
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_CONST:
+ case LOC_LABEL:
+ case LOC_CONST_BYTES:
+ lv = not_lval;
+ break;
+
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ lv = lval_register;
+ break;
+
+ default:
+ lv = lval_memory;
+ break;
+ }
+
+ return value_zero (SYMBOL_TYPE (sym), lv);
+ }
+ else
+ return value_of_variable (exp->elts[pc + 2].symbol,
+ exp->elts[pc + 1].block);
+
+ case OP_LAST:
+ (*pos) += 2;
+ return
+ access_value_history (longest_to_int (exp->elts[pc + 1].longconst));
+
+ case OP_REGISTER:
+ (*pos) += 2;
+ return value_of_register (longest_to_int (exp->elts[pc + 1].longconst));
+
+ case OP_BOOL:
+ (*pos) += 2;
+ return value_from_longest (LA_BOOL_TYPE,
+ exp->elts[pc + 1].longconst);
+
+ case OP_INTERNALVAR:
+ (*pos) += 2;
+ return value_of_internalvar (exp->elts[pc + 1].internalvar);
+
+ case OP_STRING:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_string (&exp->elts[pc + 2].string, tem);
+
+ case OP_BITSTRING:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos)
+ += 3 + BYTES_TO_EXP_ELEM ((tem + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_bitstring (&exp->elts[pc + 2].string, tem);
+ break;
+
+ case OP_ARRAY:
+ (*pos) += 3;
+ tem2 = longest_to_int (exp->elts[pc + 1].longconst);
+ tem3 = longest_to_int (exp->elts[pc + 2].longconst);
+ nargs = tem3 - tem2 + 1;
+ type = expect_type ? check_typedef (expect_type) : NULL_TYPE;
+
+ if (expect_type != NULL_TYPE && noside != EVAL_SKIP
+ && TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ {
+ value_ptr rec = allocate_value (expect_type);
+ memset (VALUE_CONTENTS_RAW (rec), '\0', TYPE_LENGTH (type));
+ return evaluate_struct_tuple (rec, exp, pos, noside, nargs);
+ }
+
+ if (expect_type != NULL_TYPE && noside != EVAL_SKIP
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY)
+ {
+ struct type *range_type = TYPE_FIELD_TYPE (type, 0);
+ struct type *element_type = TYPE_TARGET_TYPE (type);
+ value_ptr array = allocate_value (expect_type);
+ int element_size = TYPE_LENGTH (check_typedef (element_type));
+ LONGEST low_bound, high_bound, index;
+ if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+ {
+ low_bound = 0;
+ high_bound = (TYPE_LENGTH (type) / element_size) - 1;
+ }
+ index = low_bound;
+ memset (VALUE_CONTENTS_RAW (array), 0, TYPE_LENGTH (expect_type));
+ for (tem = nargs; --nargs >= 0; )
+ {
+ value_ptr element;
+ int index_pc = 0;
+ if (exp->elts[*pos].opcode == BINOP_RANGE)
+ {
+ index_pc = ++(*pos);
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ }
+ element = evaluate_subexp (element_type, exp, pos, noside);
+ if (VALUE_TYPE (element) != element_type)
+ element = value_cast (element_type, element);
+ if (index_pc)
+ {
+ int continue_pc = *pos;
+ *pos = index_pc;
+ index = init_array_element (array, element, exp, pos, noside,
+ low_bound, high_bound);
+ *pos = continue_pc;
+ }
+ else
+ {
+ memcpy (VALUE_CONTENTS_RAW (array)
+ + (index - low_bound) * element_size,
+ VALUE_CONTENTS (element),
+ element_size);
+ }
+ index++;
+ }
+ return array;
+ }
+
+ if (expect_type != NULL_TYPE && noside != EVAL_SKIP
+ && TYPE_CODE (type) == TYPE_CODE_SET)
+ {
+ value_ptr set = allocate_value (expect_type);
+ char *valaddr = VALUE_CONTENTS_RAW (set);
+ struct type *element_type = TYPE_INDEX_TYPE (type);
+ LONGEST low_bound, high_bound;
+ if (get_discrete_bounds (element_type, &low_bound, &high_bound) < 0)
+ error ("(power)set type with unknown size");
+ memset (valaddr, '\0', TYPE_LENGTH (type));
+ for (tem = 0; tem < nargs; tem++)
+ {
+ LONGEST range_low, range_high;
+ value_ptr elem_val;
+ if (exp->elts[*pos].opcode == BINOP_RANGE)
+ {
+ (*pos)++;
+ elem_val = evaluate_subexp (element_type, exp, pos, noside);
+ range_low = value_as_long (elem_val);
+ elem_val = evaluate_subexp (element_type, exp, pos, noside);
+ range_high = value_as_long (elem_val);
+ }
+ else
+ {
+ elem_val = evaluate_subexp (element_type, exp, pos, noside);
+ range_low = range_high = value_as_long (elem_val);
+ }
+ if (range_low > range_high)
+ {
+ warning ("empty POWERSET tuple range");
+ continue;
+ }
+ if (range_low < low_bound || range_high > high_bound)
+ error ("POWERSET tuple element out of range");
+ range_low -= low_bound;
+ range_high -= low_bound;
+ for ( ; range_low <= range_high; range_low++)
+ {
+ int bit_index = (unsigned) range_low % TARGET_CHAR_BIT;
+ if (BITS_BIG_ENDIAN)
+ bit_index = TARGET_CHAR_BIT - 1 - bit_index;
+ valaddr [(unsigned) range_low / TARGET_CHAR_BIT]
+ |= 1 << bit_index;
+ }
+ }
+ return set;
+ }
+
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * nargs);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ /* Ensure that array expressions are coerced into pointer objects. */
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ }
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_array (tem2, tem3, argvec);
+
+ case TERNOP_SLICE:
+ {
+ value_ptr array = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ int lowbound
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ int upper
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ return value_slice (array, lowbound, upper - lowbound + 1);
+ }
+
+ case TERNOP_SLICE_COUNT:
+ {
+ value_ptr array = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ int lowbound
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ int length
+ = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ return value_slice (array, lowbound, length);
+ }
+
+ case TERNOP_COND:
+ /* Skip third and second args to evaluate the first one. */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (value_logical_not (arg1))
+ {
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ return arg2;
+ }
+
+ case OP_FUNCALL:
+ (*pos) += 2;
+ op = exp->elts[*pos].opcode;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ /* Allocate arg vector, including space for the function to be
+ called in argvec[0] and a terminating NULL */
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 3));
+ if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ LONGEST fnptr;
+
+ nargs++;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (op == STRUCTOP_MEMBER)
+ {
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+
+ /* If the function is a virtual function, then the
+ aggregate value (providing the structure) plays
+ its part by providing the vtable. Otherwise,
+ it is just along for the ride: call the function
+ directly. */
+
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ fnptr = value_as_long (arg1);
+
+ if (METHOD_PTR_IS_VIRTUAL(fnptr))
+ {
+ int fnoffset = METHOD_PTR_TO_VOFFSET(fnptr);
+ struct type *basetype;
+ struct type *domain_type =
+ TYPE_DOMAIN_TYPE (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
+ int i, j;
+ basetype = TYPE_TARGET_TYPE (VALUE_TYPE (arg2));
+ if (domain_type != basetype)
+ arg2 = value_cast(lookup_pointer_type (domain_type), arg2);
+ basetype = TYPE_VPTR_BASETYPE (domain_type);
+ for (i = TYPE_NFN_FIELDS (basetype) - 1; i >= 0; i--)
+ {
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (basetype, i);
+ /* If one is virtual, then all are virtual. */
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, 0))
+ for (j = TYPE_FN_FIELDLIST_LENGTH (basetype, i) - 1; j >= 0; --j)
+ if ((int) TYPE_FN_FIELD_VOFFSET (f, j) == fnoffset)
+ {
+ value_ptr temp = value_ind (arg2);
+ arg1 = value_virtual_fn_field (&temp, f, j, domain_type, 0);
+ arg2 = value_addr (temp);
+ goto got_it;
+ }
+ }
+ if (i < 0)
+ error ("virtual function at index %d not found", fnoffset);
+ }
+ else
+ {
+ VALUE_TYPE (arg1) = lookup_pointer_type (TYPE_TARGET_TYPE (VALUE_TYPE (arg1)));
+ }
+ got_it:
+
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ /* Hair for method invocations */
+ int tem2;
+
+ nargs++;
+ /* First, evaluate the structure into arg2 */
+ pc2 = (*pos)++;
+ tem2 = longest_to_int (exp->elts[pc2 + 1].longconst);
+ *pos += 3 + BYTES_TO_EXP_ELEM (tem2 + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (op == STRUCTOP_STRUCT)
+ {
+ /* If v is a variable in a register, and the user types
+ v.method (), this will produce an error, because v has
+ no address.
+
+ A possible way around this would be to allocate a
+ copy of the variable on the stack, copy in the
+ contents, call the function, and copy out the
+ contents. I.e. convert this from call by reference
+ to call by copy-return (or whatever it's called).
+ However, this does not work because it is not the
+ same: the method being called could stash a copy of
+ the address, and then future uses through that address
+ (after the method returns) would be expected to
+ use the variable itself, not some copy of it. */
+ arg2 = evaluate_subexp_for_address (exp, pos, noside);
+ }
+ else
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+ /* Now, say which argument to start evaluating from */
+ tem = 2;
+ }
+ else
+ {
+ argvec[0] = evaluate_subexp_with_coercion (exp, pos, noside);
+ tem = 1;
+ type = VALUE_TYPE (argvec[0]);
+ if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ if (type && TYPE_CODE (type) == TYPE_CODE_FUNC)
+ {
+ for (; tem <= nargs && tem <= TYPE_NFIELDS (type); tem++)
+ {
+ argvec[tem] = evaluate_subexp (TYPE_FIELD_TYPE (type, tem-1),
+ exp, pos, noside);
+ }
+ }
+ }
+
+ for (; tem <= nargs; tem++)
+ {
+ /* Ensure that array expressions are coerced into pointer objects. */
+
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ }
+
+ /* signal end of arglist */
+ argvec[tem] = 0;
+
+ if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
+ {
+ int static_memfuncp;
+ value_ptr temp = arg2;
+ char tstr[64];
+
+ argvec[1] = arg2;
+ 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));
+ argvec[1] = arg2;
+
+ if (static_memfuncp)
+ {
+ argvec[1] = argvec[0];
+ nargs--;
+ argvec++;
+ }
+ }
+ else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
+ {
+ argvec[1] = arg2;
+ argvec[0] = arg1;
+ }
+
+ do_call_it:
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type, call an
+ error. This can happen if somebody tries to turn a variable into
+ a function call. This is here because people often want to
+ call, eg, strcmp, which gdb doesn't know is a function. If
+ gdb isn't asked for it's opinion (ie. through "whatis"),
+ it won't offer it. */
+
+ struct type *ftype =
+ TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0]));
+
+ if (ftype)
+ return allocate_value (TYPE_TARGET_TYPE (VALUE_TYPE (argvec[0])));
+ else
+ error ("Expression of type other than \"Function returning ...\" used as function");
+ }
+ return call_function_by_hand (argvec[0], nargs, argvec + 1);
+
+ case OP_F77_UNDETERMINED_ARGLIST:
+
+ /* Remember that in F77, functions, substring ops and
+ array subscript operations cannot be disambiguated
+ at parse time. We have made all array subscript operations,
+ substring operations as well as function calls come here
+ and we now have to discover what the heck this thing actually was.
+ If it is a function, we process just as if we got an OP_FUNCALL. */
+
+ nargs = longest_to_int (exp->elts[pc+1].longconst);
+ (*pos) += 2;
+
+ /* First determine the type code we are dealing with. */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ type = check_typedef (VALUE_TYPE (arg1));
+ code = TYPE_CODE (type);
+
+ switch (code)
+ {
+ case TYPE_CODE_ARRAY:
+ goto multi_f77_subscript;
+
+ case TYPE_CODE_STRING:
+ goto op_f77_substr;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_FUNC:
+ /* It's a function call. */
+ /* Allocate arg vector, including space for the function to be
+ called in argvec[0] and a terminating NULL */
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * (nargs + 2));
+ argvec[0] = arg1;
+ tem = 1;
+ for (; tem <= nargs; tem++)
+ argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem] = 0; /* signal end of arglist */
+ goto do_call_it;
+
+ default:
+ error ("Cannot perform substring on this type");
+ }
+
+ op_f77_substr:
+ /* We have a substring operation on our hands here,
+ let us get the string we will be dealing with */
+
+ /* Now evaluate the 'from' and 'to' */
+
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ if (nargs < 2)
+ return value_subscript (arg1, arg2);
+
+ arg3 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ tem2 = value_as_long (arg2);
+ tem3 = value_as_long (arg3);
+
+ return value_slice (arg1, tem2, tem3 - tem2 + 1);
+
+ case OP_COMPLEX:
+ /* We have a complex number, There should be 2 floating
+ point numbers that compose it */
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ return value_literal_complex (arg1, arg2, builtin_type_f_complex_s16);
+
+ case STRUCTOP_STRUCT:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
+ &exp->elts[pc + 2].string,
+ 0),
+ lval_memory);
+ else
+ {
+ value_ptr temp = arg1;
+ return value_struct_elt (&temp, NULL, &exp->elts[pc + 2].string,
+ NULL, "structure");
+ }
+
+ case STRUCTOP_PTR:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
+ &exp->elts[pc + 2].string,
+ 0),
+ lval_memory);
+ else
+ {
+ value_ptr temp = arg1;
+ return value_struct_elt (&temp, NULL, &exp->elts[pc + 2].string,
+ NULL, "structure pointer");
+ }
+
+
+ case STRUCTOP_MEMBER:
+ arg1 = evaluate_subexp_for_address (exp, pos, noside);
+ goto handle_pointer_to_member;
+ case STRUCTOP_MPTR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ handle_pointer_to_member:
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ type = check_typedef (VALUE_TYPE (arg2));
+ if (TYPE_CODE (type) != TYPE_CODE_PTR)
+ goto bad_pointer_to_member;
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ if (TYPE_CODE (type) == TYPE_CODE_METHOD)
+ error ("not implemented: pointer-to-method in pointer-to-member construct");
+ if (TYPE_CODE (type) != TYPE_CODE_MEMBER)
+ goto bad_pointer_to_member;
+ /* Now, convert these values to an address. */
+ arg1 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
+ arg1);
+ arg3 = value_from_longest (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+ value_as_long (arg1) + value_as_long (arg2));
+ return value_ind (arg3);
+ bad_pointer_to_member:
+ error("non-pointer-to-member value used in pointer-to-member construct");
+
+ case BINOP_CONCAT:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ else
+ return value_concat (arg1, arg2);
+
+ case BINOP_ASSIGN:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ else
+ return value_assign (arg1, arg2);
+
+ case BINOP_ASSIGN_MODIFY:
+ (*pos) += 2;
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ op = exp->elts[pc + 1].opcode;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op);
+ else if (op == BINOP_ADD)
+ arg2 = value_add (arg1, arg2);
+ else if (op == BINOP_SUB)
+ arg2 = value_sub (arg1, arg2);
+ else
+ arg2 = value_binop (arg1, arg2, op);
+ return value_assign (arg1, arg2);
+
+ case BINOP_ADD:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ else
+ return value_add (arg1, arg2);
+
+ case BINOP_SUB:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ else
+ return value_sub (arg1, arg2);
+
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_REM:
+ case BINOP_MOD:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ else
+ if (noside == EVAL_AVOID_SIDE_EFFECTS
+ && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD))
+ return value_zero (VALUE_TYPE (arg1), not_lval);
+ else
+ return value_binop (arg1, arg2, op);
+
+ case BINOP_RANGE:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ error ("':' operator used in invalid context");
+
+ case BINOP_SUBSCRIPT:
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the user attempts to subscript something that has no target
+ type (like a plain int variable for example), then report this
+ as an error. */
+
+ type = TYPE_TARGET_TYPE (check_typedef (VALUE_TYPE (arg1)));
+ if (type)
+ return value_zero (type, VALUE_LVAL (arg1));
+ else
+ error ("cannot subscript something of type `%s'",
+ TYPE_NAME (VALUE_TYPE (arg1)));
+ }
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ 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;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+ while (nargs-- > 0)
+ {
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+ /* FIXME: EVAL_SKIP handling may not be correct. */
+ if (noside == EVAL_SKIP)
+ {
+ if (nargs > 0)
+ {
+ continue;
+ }
+ else
+ {
+ goto nosideret;
+ }
+ }
+ /* FIXME: EVAL_AVOID_SIDE_EFFECTS handling may not be correct. */
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the user attempts to subscript something that has no target
+ type (like a plain int variable for example), then report this
+ as an error. */
+
+ type = TYPE_TARGET_TYPE (check_typedef (VALUE_TYPE (arg1)));
+ if (type != NULL)
+ {
+ arg1 = value_zero (type, VALUE_LVAL (arg1));
+ noside = EVAL_SKIP;
+ continue;
+ }
+ else
+ {
+ error ("cannot subscript something of type `%s'",
+ TYPE_NAME (VALUE_TYPE (arg1)));
+ }
+ }
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg1 = value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ arg1 = value_subscript (arg1, arg2);
+ }
+ }
+ return (arg1);
+
+ multi_f77_subscript:
+ {
+ int subscript_array[MAX_FORTRAN_DIMS+1]; /* 1-based array of
+ subscripts, max == 7 */
+ int array_size_array[MAX_FORTRAN_DIMS+1];
+ int ndimensions=1,i;
+ struct type *tmp_type;
+ int offset_item; /* The array offset where the item lives */
+
+ if (nargs > MAX_FORTRAN_DIMS)
+ error ("Too many subscripts for F77 (%d Max)", MAX_FORTRAN_DIMS);
+
+ tmp_type = check_typedef (VALUE_TYPE (arg1));
+ ndimensions = calc_f77_array_dims (type);
+
+ if (nargs != ndimensions)
+ error ("Wrong number of subscripts");
+
+ /* Now that we know we have a legal array subscript expression
+ let us actually find out where this element exists in the array. */
+
+ offset_item = 0;
+ for (i = 1; i <= nargs; i++)
+ {
+ /* Evaluate each subscript, It must be a legal integer in F77 */
+ arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+
+ /* Fill in the subscript and array size arrays */
+
+ subscript_array[i] = value_as_long (arg2);
+
+ retcode = f77_get_dynamic_upperbound (tmp_type, &upper);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain dynamic upper bound");
+
+ retcode = f77_get_dynamic_lowerbound (tmp_type, &lower);
+ if (retcode == BOUND_FETCH_ERROR)
+ error("Cannot obtain dynamic lower bound");
+
+ array_size_array[i] = upper - lower + 1;
+
+ /* Zero-normalize subscripts so that offsetting will work. */
+
+ subscript_array[i] -= lower;
+
+ /* If we are at the bottom of a multidimensional
+ array type then keep a ptr to the last ARRAY
+ type around for use when calling value_subscript()
+ below. This is done because we pretend to value_subscript
+ that we actually have a one-dimensional array
+ of base element type that we apply a simple
+ offset to. */
+
+ if (i < nargs)
+ tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type));
+ }
+
+ /* Now let us calculate the offset for this item */
+
+ offset_item = subscript_array[ndimensions];
+
+ for (i = ndimensions - 1; i >= 1; i--)
+ offset_item =
+ array_size_array[i] * offset_item + subscript_array[i];
+
+ /* Construct a value node with the value of the offset */
+
+ arg2 = value_from_longest (builtin_type_f_integer, offset_item);
+
+ /* Let us now play a dirty trick: we will take arg1
+ which is a value node pointing to the topmost level
+ of the multidimensional array-set and pretend
+ that it is actually a array of the final element
+ type, this will ensure that value_subscript()
+ returns the correct type value */
+
+ VALUE_TYPE (arg1) = tmp_type;
+ return value_ind (value_add (value_coerce_array (arg1), arg2));
+ }
+
+ case BINOP_LOGICAL_AND:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ goto nosideret;
+ }
+
+ oldpos = *pos;
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ *pos = oldpos;
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_logical_not (arg1);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
+ (tem ? EVAL_SKIP : noside));
+ return value_from_longest (LA_BOOL_TYPE,
+ (LONGEST) (!tem && !value_logical_not (arg2)));
+ }
+
+ case BINOP_LOGICAL_OR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ goto nosideret;
+ }
+
+ oldpos = *pos;
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ *pos = oldpos;
+
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_logical_not (arg1);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos,
+ (!tem ? EVAL_SKIP : noside));
+ return value_from_longest (LA_BOOL_TYPE,
+ (LONGEST) (!tem || !value_logical_not (arg2)));
+ }
+
+ case BINOP_EQUAL:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_NOTEQUAL:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) ! tem);
+ }
+
+ case BINOP_LESS:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_less (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_GTR:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_less (arg2, arg1);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_GEQ:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_less (arg2, arg1) || value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_LEQ:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (binop_user_defined_p (op, arg1, arg2))
+ {
+ return value_x_binop (arg1, arg2, op, OP_NULL);
+ }
+ else
+ {
+ tem = value_less (arg1, arg2) || value_equal (arg1, arg2);
+ return value_from_longest (LA_BOOL_TYPE, (LONGEST) tem);
+ }
+
+ case BINOP_REPEAT:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (TYPE_CODE (VALUE_TYPE (arg2)) != TYPE_CODE_INT)
+ error ("Non-integral right operand for \"@\" operator.");
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ return allocate_repeat_value (VALUE_TYPE (arg1),
+ longest_to_int (value_as_long (arg2)));
+ }
+ else
+ return value_repeat (arg1, longest_to_int (value_as_long (arg2)));
+
+ case BINOP_COMMA:
+ evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ case UNOP_NEG:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op);
+ else
+ return value_neg (arg1);
+
+ case UNOP_COMPLEMENT:
+ /* C++: check for and handle destructor names. */
+ op = exp->elts[*pos].opcode;
+
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (UNOP_COMPLEMENT, arg1))
+ return value_x_unop (arg1, UNOP_COMPLEMENT);
+ else
+ return value_complement (arg1);
+
+ case UNOP_LOGICAL_NOT:
+ arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (unop_user_defined_p (op, arg1))
+ return value_x_unop (arg1, op);
+ else
+ return value_from_longest (builtin_type_int,
+ (LONGEST) value_logical_not (arg1));
+
+ case UNOP_IND:
+ if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
+ expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ type = check_typedef (VALUE_TYPE (arg1));
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF
+ /* In C you can dereference an array to get the 1st elt. */
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY
+ )
+ return value_zero (TYPE_TARGET_TYPE (type),
+ lval_memory);
+ else if (TYPE_CODE (type) == TYPE_CODE_INT)
+ /* GDB allows dereferencing an int. */
+ return value_zero (builtin_type_int, lval_memory);
+ else
+ error ("Attempt to take contents of a non-pointer value.");
+ }
+ return value_ind (arg1);
+
+ case UNOP_ADDR:
+ /* C++: check for and handle pointer to members. */
+
+ op = exp->elts[*pos].opcode;
+
+ if (noside == EVAL_SKIP)
+ {
+ if (op == OP_SCOPE)
+ {
+ int temm = longest_to_int (exp->elts[pc+3].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (temm + 1);
+ }
+ else
+ evaluate_subexp (expect_type, exp, pos, EVAL_SKIP);
+ goto nosideret;
+ }
+
+ return evaluate_subexp_for_address (exp, pos, noside);
+
+ case UNOP_SIZEOF:
+ if (noside == EVAL_SKIP)
+ {
+ evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+ goto nosideret;
+ }
+ return evaluate_subexp_for_sizeof (exp, pos);
+
+ case UNOP_CAST:
+ (*pos) += 2;
+ type = exp->elts[pc + 1].type;
+ arg1 = evaluate_subexp (type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (type != VALUE_TYPE (arg1))
+ arg1 = value_cast (type, arg1);
+ return arg1;
+
+ case UNOP_MEMVAL:
+ (*pos) += 2;
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ return value_zero (exp->elts[pc + 1].type, lval_memory);
+ else
+ return value_at_lazy (exp->elts[pc + 1].type,
+ value_as_pointer (arg1));
+
+ case UNOP_PREINCREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ return value_assign (arg1, arg2);
+ }
+
+ case UNOP_PREDECREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ return value_assign (arg1, arg2);
+ }
+
+ case UNOP_POSTINCREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_add (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ value_assign (arg1, arg2);
+ return arg1;
+ }
+
+ case UNOP_POSTDECREMENT:
+ arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+ if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+ return arg1;
+ else if (unop_user_defined_p (op, arg1))
+ {
+ return value_x_unop (arg1, op);
+ }
+ else
+ {
+ arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
+ (LONGEST) 1));
+ value_assign (arg1, arg2);
+ return arg1;
+ }
+
+ case OP_THIS:
+ (*pos) += 1;
+ return value_of_this (1);
+
+ case OP_TYPE:
+ error ("Attempt to use a type name as an expression");
+
+ default:
+ /* Removing this case and compiling with gcc -Wall reveals that
+ a lot of cases are hitting this case. Some of these should
+ probably be removed from expression.h (e.g. do we need a BINOP_SCOPE
+ and an OP_SCOPE?); others are legitimate expressions which are
+ (apparently) not fully implemented.
+
+ If there are any cases landing here which mean a user error,
+ then they should be separate cases, with more descriptive
+ error messages. */
+
+ error ("\
+GDB does not (yet) know how to evaluate that kind of expression");
+ }
+
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+ and return the address of that subexpression.
+ Advance *POS over the subexpression.
+ If the subexpression isn't an lvalue, get an error.
+ NOSIDE may be EVAL_AVOID_SIDE_EFFECTS;
+ then only the type of the result need be correct. */
+
+static value_ptr
+evaluate_subexp_for_address (exp, pos, noside)
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op;
+ register int pc;
+ struct symbol *var;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case UNOP_IND:
+ (*pos)++;
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+ case UNOP_MEMVAL:
+ (*pos) += 3;
+ return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
+ evaluate_subexp (NULL_TYPE, exp, pos, noside));
+
+ case OP_VAR_VALUE:
+ var = exp->elts[pc + 2].symbol;
+
+ /* C++: The "address" of a reference should yield the address
+ * of the object pointed to. Let value_addr() deal with it. */
+ if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_REF)
+ goto default_case;
+
+ (*pos) += 4;
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ struct type *type =
+ lookup_pointer_type (SYMBOL_TYPE (var));
+ enum address_class sym_class = SYMBOL_CLASS (var);
+
+ if (sym_class == LOC_CONST
+ || sym_class == LOC_CONST_BYTES
+ || sym_class == LOC_REGISTER
+ || sym_class == LOC_REGPARM)
+ error ("Attempt to take address of register or constant.");
+
+ return
+ value_zero (type, not_lval);
+ }
+ else
+ return
+ locate_var_value
+ (var,
+ block_innermost_frame (exp->elts[pc + 1].block));
+
+ default:
+ default_case:
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ 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);
+ else
+ error ("Attempt to take address of non-lval");
+ }
+ return value_addr (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+ }
+}
+
+/* Evaluate like `evaluate_subexp' except coercing arrays to pointers.
+ When used in contexts where arrays will be coerced anyway, this is
+ equivalent to `evaluate_subexp' but much faster because it avoids
+ actually fetching array contents (perhaps obsolete now that we have
+ VALUE_LAZY).
+
+ Note that we currently only do the coercion for C expressions, where
+ arrays are zero based and the coercion is correct. For other languages,
+ with nonzero based arrays, coercion loses. Use CAST_IS_CONVERSION
+ to decide if coercion is appropriate.
+
+ */
+
+value_ptr
+evaluate_subexp_with_coercion (exp, pos, noside)
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ register enum exp_opcode op;
+ register int pc;
+ register value_ptr val;
+ struct symbol *var;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ case OP_VAR_VALUE:
+ var = exp->elts[pc + 2].symbol;
+ if (TYPE_CODE (check_typedef (SYMBOL_TYPE (var))) == TYPE_CODE_ARRAY
+ && CAST_IS_CONVERSION)
+ {
+ (*pos) += 4;
+ val =
+ locate_var_value
+ (var, block_innermost_frame (exp->elts[pc + 1].block));
+ return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (SYMBOL_TYPE (var))),
+ val);
+ }
+ /* FALLTHROUGH */
+
+ default:
+ return evaluate_subexp (NULL_TYPE, exp, pos, noside);
+ }
+}
+
+/* Evaluate a subexpression of EXP, at index *POS,
+ and return a value for the size of that subexpression.
+ Advance *POS over the subexpression. */
+
+static value_ptr
+evaluate_subexp_for_sizeof (exp, pos)
+ register struct expression *exp;
+ register int *pos;
+{
+ enum exp_opcode op;
+ register int pc;
+ struct type *type;
+ value_ptr val;
+
+ pc = (*pos);
+ op = exp->elts[pc].opcode;
+
+ switch (op)
+ {
+ /* This case is handled specially
+ so that we avoid creating a value for the result type.
+ If the result type is very big, it's desirable not to
+ create a value unnecessarily. */
+ case UNOP_IND:
+ (*pos)++;
+ val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ type = check_typedef (VALUE_TYPE (val));
+ type = check_typedef (TYPE_TARGET_TYPE (type));
+ return value_from_longest (builtin_type_int, (LONGEST)
+ TYPE_LENGTH (type));
+
+ case UNOP_MEMVAL:
+ (*pos) += 3;
+ type = check_typedef (exp->elts[pc + 1].type);
+ return value_from_longest (builtin_type_int,
+ (LONGEST) TYPE_LENGTH (type));
+
+ case OP_VAR_VALUE:
+ (*pos) += 4;
+ type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
+ return
+ value_from_longest (builtin_type_int, (LONGEST) TYPE_LENGTH (type));
+
+ default:
+ val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+ return value_from_longest (builtin_type_int,
+ (LONGEST) TYPE_LENGTH (VALUE_TYPE (val)));
+ }
+}
+
+/* Parse a type expression in the string [P..P+LENGTH). */
+
+struct type *
+parse_and_eval_type (p, length)
+ char *p;
+ int length;
+{
+ char *tmp = (char *)alloca (length + 4);
+ struct expression *expr;
+ tmp[0] = '(';
+ memcpy (tmp+1, p, length);
+ tmp[length+1] = ')';
+ tmp[length+2] = '0';
+ tmp[length+3] = '\0';
+ expr = parse_expression (tmp);
+ if (expr->elts[0].opcode != UNOP_CAST)
+ error ("Internal error in eval_type.");
+ return expr->elts[1].type;
+}
+
+int
+calc_f77_array_dims (array_type)
+ struct type *array_type;
+{
+ int ndimen = 1;
+ struct type *tmp_type;
+
+ if ((TYPE_CODE(array_type) != TYPE_CODE_ARRAY))
+ error ("Can't get dimensions for a non-array type");
+
+ tmp_type = array_type;
+
+ while ((tmp_type = TYPE_TARGET_TYPE (tmp_type)))
+ {
+ if (TYPE_CODE (tmp_type) == TYPE_CODE_ARRAY)
+ ++ndimen;
+ }
+ return ndimen;
+}
diff --git a/contrib/gdb/gdb/exc_request.defs b/contrib/gdb/gdb/exc_request.defs
new file mode 100644
index 0000000..9b5ed2e
--- /dev/null
+++ b/contrib/gdb/gdb/exc_request.defs
@@ -0,0 +1,51 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1993,1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * Abstract:
+ * MiG definitions file for Mach exception interface (request half).
+ */
+
+subsystem exc 2400;
+
+#include <mach/std_types.defs>
+
+#ifdef USERPREFIX
+userprefix USERPREFIX;
+#endif
+
+#ifdef SERVERPREFIX
+serverprefix SERVERPREFIX;
+#endif
+
+simpleroutine exception_raise_request (
+ exception_port : mach_port_t;
+ replyport reply : mach_port_send_once_t;
+ thread : mach_port_t;
+ task : mach_port_t;
+ exception : integer_t;
+ code : integer_t;
+ subcode : integer_t);
diff --git a/contrib/gdb/gdb/exec.c b/contrib/gdb/gdb/exec.c
new file mode 100644
index 0000000..dc71a49
--- /dev/null
+++ b/contrib/gdb/gdb/exec.c
@@ -0,0 +1,677 @@
+/* Work with executable files, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include "gdb_string.h"
+
+#include "gdbcore.h"
+
+#include <ctype.h>
+#include "gdb_stat.h"
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#include "xcoffsolib.h"
+
+struct vmap *map_vmap PARAMS ((bfd *, bfd *));
+
+/* Prototypes for local functions */
+
+static void add_to_section_table PARAMS ((bfd *, sec_ptr, PTR));
+
+static void exec_close PARAMS ((int));
+
+static void file_command PARAMS ((char *, int));
+
+static void set_section_command PARAMS ((char *, int));
+
+static void exec_files_info PARAMS ((struct target_ops *));
+
+extern int info_verbose;
+
+/* The Binary File Descriptor handle for the executable file. */
+
+bfd *exec_bfd = NULL;
+
+/* Whether to open exec and core files read-only or read-write. */
+
+int write_files = 0;
+
+/* Text start and end addresses (KLUDGE) if needed */
+
+#ifdef NEED_TEXT_START_END
+CORE_ADDR text_start = 0;
+CORE_ADDR text_end = 0;
+#endif
+
+struct vmap *vmap;
+
+/* Forward decl */
+
+extern struct target_ops exec_ops;
+
+/* ARGSUSED */
+static void
+exec_close (quitting)
+ int quitting;
+{
+ int need_symtab_cleanup = 0;
+ struct vmap *vp, *nxt;
+
+ for (nxt = vmap; nxt != NULL; )
+ {
+ vp = nxt;
+ nxt = vp->nxt;
+
+ /* if there is an objfile associated with this bfd,
+ free_objfile() will do proper cleanup of objfile *and* bfd. */
+
+ if (vp->objfile)
+ {
+ free_objfile (vp->objfile);
+ need_symtab_cleanup = 1;
+ }
+ else if (vp->bfd != exec_bfd)
+ /* FIXME-leak: We should be freeing vp->name too, I think. */
+ if (!bfd_close (vp->bfd))
+ warning ("cannot close \"%s\": %s",
+ vp->name, bfd_errmsg (bfd_get_error ()));
+
+ /* FIXME: This routine is #if 0'd in symfile.c. What should we
+ be doing here? Should we just free everything in
+ vp->objfile->symtabs? Should free_objfile do that?
+ FIXME-as-well: free_objfile already free'd vp->name, so it isn't
+ valid here. */
+ free_named_symtabs (vp->name);
+ free (vp);
+ }
+
+ vmap = NULL;
+
+ if (exec_bfd)
+ {
+ char *name = bfd_get_filename (exec_bfd);
+
+ if (!bfd_close (exec_bfd))
+ warning ("cannot close \"%s\": %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ free (name);
+ exec_bfd = NULL;
+ }
+
+ if (exec_ops.to_sections)
+ {
+ free ((PTR)exec_ops.to_sections);
+ exec_ops.to_sections = NULL;
+ exec_ops.to_sections_end = NULL;
+ }
+}
+
+/* Process the first arg in ARGS as the new exec file.
+
+ Note that we have to explicitly ignore additional args, since we can
+ be called from file_command(), which also calls symbol_file_command()
+ which can take multiple args. */
+
+void
+exec_file_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ char *filename;
+
+ target_preopen (from_tty);
+
+ /* Remove any previous exec file. */
+ unpush_target (&exec_ops);
+
+ /* Now open and digest the file the user requested, if any. */
+
+ if (args)
+ {
+ char *scratch_pathname;
+ int scratch_chan;
+
+ /* Scan through the args and pick up the first non option arg
+ as the filename. */
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ nomem (0);
+
+ make_cleanup (freeargv, (char *) argv);
+
+ for (; (*argv != NULL) && (**argv == '-'); argv++) {;}
+ if (*argv == NULL)
+ error ("no exec file name was specified");
+
+ filename = tilde_expand (*argv);
+ make_cleanup (free, filename);
+
+ scratch_chan = openp (getenv ("PATH"), 1, filename,
+ write_files? O_RDWR|O_BINARY: O_RDONLY|O_BINARY, 0,
+ &scratch_pathname);
+ if (scratch_chan < 0)
+ perror_with_name (filename);
+ exec_bfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+
+ if (!exec_bfd)
+ error ("\"%s\": could not open as an executable file: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+
+ /* At this point, scratch_pathname and exec_bfd->name both point to the
+ same malloc'd string. However exec_close() will attempt to free it
+ via the exec_bfd->name pointer, so we need to make another copy and
+ leave exec_bfd as the new owner of the original copy. */
+ scratch_pathname = strdup (scratch_pathname);
+ make_cleanup (free, scratch_pathname);
+
+ if (!bfd_check_format (exec_bfd, bfd_object))
+ {
+ /* 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 ()));
+ }
+
+ /* FIXME - This should only be run for RS6000, but the ifdef is a poor
+ way to accomplish. */
+#ifdef IBM6000_TARGET
+ /* Setup initial vmap. */
+
+ map_vmap (exec_bfd, 0);
+ if (vmap == NULL)
+ {
+ /* Make sure to close exec_bfd, or else "run" might try to use
+ it. */
+ exec_close (0);
+ error ("\"%s\": can't find the file sections: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+#endif /* IBM6000_TARGET */
+
+ if (build_section_table (exec_bfd, &exec_ops.to_sections,
+ &exec_ops.to_sections_end))
+ {
+ /* Make sure to close exec_bfd, or else "run" might try to use
+ it. */
+ exec_close (0);
+ error ("\"%s\": can't find the file sections: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+
+#ifdef NEED_TEXT_START_END
+
+ /* text_end is sometimes used for where to put call dummies. A
+ few ports use these for other purposes too. */
+
+ {
+ struct section_table *p;
+
+ /* Set text_start to the lowest address of the start of any
+ readonly code section and set text_end to the highest
+ address of the end of any readonly code section. */
+ /* FIXME: The comment above does not match the code. The code
+ checks for sections with are either code *or* readonly. */
+
+ 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->the_bfd_section)
+ & (SEC_CODE | SEC_READONLY))
+ {
+ if (text_start > p->addr)
+ text_start = p->addr;
+ if (text_end < p->endaddr)
+ text_end = p->endaddr;
+ }
+ }
+#endif
+
+ validate_files ();
+
+ set_endian_from_file (exec_bfd);
+
+ push_target (&exec_ops);
+
+ /* Tell display code (if any) about the changed file name. */
+ if (exec_file_display_hook)
+ (*exec_file_display_hook) (filename);
+ }
+ else if (from_tty)
+ printf_unfiltered ("No exec file now.\n");
+}
+
+/* Set both the exec file and the symbol file, in one command.
+ What a novelty. Why did GDB go through four major releases before this
+ command was added? */
+
+static void
+file_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ /* FIXME, if we lose on reading the symbol file, we should revert
+ the exec file, but that's rough. */
+ exec_file_command (arg, from_tty);
+ symbol_file_command (arg, from_tty);
+}
+
+
+/* Locate all mappable sections of a BFD file.
+ table_pp_char is a char * to get it through bfd_map_over_sections;
+ we cast it back to its proper type. */
+
+static void
+add_to_section_table (abfd, asect, table_pp_char)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR table_pp_char;
+{
+ struct section_table **table_pp = (struct section_table **)table_pp_char;
+ flagword aflag;
+
+ aflag = bfd_get_section_flags (abfd, asect);
+ if (!(aflag & SEC_ALLOC))
+ return;
+ if (0 == bfd_section_size (abfd, asect))
+ return;
+ (*table_pp)->bfd = abfd;
+ (*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)++;
+}
+
+/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
+ Returns 0 if OK, 1 on error. */
+
+int
+build_section_table (some_bfd, start, end)
+ bfd *some_bfd;
+ struct section_table **start, **end;
+{
+ unsigned count;
+
+ count = bfd_count_sections (some_bfd);
+ if (*start)
+ free ((PTR)*start);
+ *start = (struct section_table *) xmalloc (count * sizeof (**start));
+ *end = *start;
+ bfd_map_over_sections (some_bfd, add_to_section_table, (char *)end);
+ if (*end > *start + count)
+ abort();
+ /* We could realloc the table, but it probably loses for most files. */
+ return 0;
+}
+
+static void
+bfdsec_to_vmap(abfd, sect, arg3)
+ bfd *abfd;
+ sec_ptr sect;
+ PTR arg3;
+{
+ struct vmap_and_bfd *vmap_bfd = (struct vmap_and_bfd *) arg3;
+ struct vmap *vp;
+
+ vp = vmap_bfd->pvmap;
+
+ if ((bfd_get_section_flags (abfd, sect) & SEC_LOAD) == 0)
+ return;
+
+ if (STREQ (bfd_section_name (abfd, sect), ".text"))
+ {
+ vp->tstart = 0;
+ vp->tend = vp->tstart + bfd_section_size (abfd, sect);
+
+ /* When it comes to this adjustment value, in contrast to our previous
+ belief shared objects should behave the same as the main load segment.
+ This is the offset from the beginning of text section to the first
+ real instruction. */
+
+ vp->tadj = sect->filepos - bfd_section_vma (abfd, sect);
+ }
+ else if (STREQ (bfd_section_name (abfd, sect), ".data"))
+ {
+ vp->dstart = 0;
+ vp->dend = vp->dstart + bfd_section_size (abfd, sect);
+ }
+ /* Silently ignore other types of sections. (FIXME?) */
+}
+
+/* Make a vmap for ABFD which might be a member of the archive ARCH.
+ Return the new vmap. */
+
+struct vmap *
+map_vmap (abfd, arch)
+ bfd *abfd;
+ bfd *arch;
+{
+ struct vmap_and_bfd vmap_bfd;
+ struct vmap *vp, **vpp;
+
+ vp = (struct vmap *) xmalloc (sizeof (*vp));
+ memset ((char *) vp, '\0', sizeof (*vp));
+ vp->nxt = 0;
+ vp->bfd = abfd;
+ vp->name = bfd_get_filename (arch ? arch : abfd);
+ vp->member = arch ? bfd_get_filename (abfd) : "";
+
+ vmap_bfd.pbfd = arch;
+ vmap_bfd.pvmap = vp;
+ bfd_map_over_sections (abfd, bfdsec_to_vmap, &vmap_bfd);
+
+ /* Find the end of the list and append. */
+ for (vpp = &vmap; *vpp; vpp = &(*vpp)->nxt)
+ ;
+ *vpp = vp;
+
+ return vp;
+}
+
+/* Read or write the exec file.
+
+ Args are address within a BFD file, address within gdb address-space,
+ length, and a flag indicating whether to read or write.
+
+ Result is a length:
+
+ 0: We cannot handle this address and length.
+ > 0: We have handled N bytes starting at this address.
+ (If N == length, we did it all.) We might be able
+ to handle more bytes beyond this length, but no
+ promises.
+ < 0: We cannot handle this address, but if somebody
+ else handles (-N) bytes, we can start from there.
+
+ The same routine is used to handle both core and exec files;
+ we just tail-call it with more arguments to select between them. */
+
+int
+xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ boolean res;
+ struct section_table *p;
+ CORE_ADDR nextsectaddr, memend;
+ boolean (*xfer_fn) PARAMS ((bfd *, sec_ptr, PTR, file_ptr, bfd_size_type));
+
+ if (len <= 0)
+ abort();
+
+ memend = memaddr + len;
+ xfer_fn = write ? bfd_set_section_contents : bfd_get_section_contents;
+ nextsectaddr = memend;
+
+ for (p = target->to_sections; p < target->to_sections_end; p++)
+ {
+ if (p->addr <= memaddr)
+ if (p->endaddr >= memend)
+ {
+ /* Entire transfer is within this section. */
+ res = xfer_fn (p->bfd, p->the_bfd_section, myaddr,
+ memaddr - p->addr, len);
+ return (res != 0) ? len : 0;
+ }
+ else if (p->endaddr <= memaddr)
+ {
+ /* This section ends before the transfer starts. */
+ continue;
+ }
+ else
+ {
+ /* This section overlaps the transfer. Just do half. */
+ len = p->endaddr - memaddr;
+ 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;
+ }
+
+ if (nextsectaddr >= memend)
+ return 0; /* We can't help */
+ else
+ return - (nextsectaddr - memaddr); /* Next boundary where we can help */
+}
+
+#ifdef FIXME
+#ifdef REG_STACK_SEGMENT
+/* MOVE TO BFD... */
+ /* Pyramids and AM29000s have an extra segment in the virtual address space
+ for the (control) stack of register-window frames. The AM29000 folk
+ call it the "register stack" rather than the "memory stack". */
+ else if (memaddr >= reg_stack_start && memaddr < reg_stack_end)
+ {
+ i = min (len, reg_stack_end - memaddr);
+ fileptr = memaddr - reg_stack_start + reg_stack_offset;
+ wanna_xfer = coredata;
+ }
+#endif /* REG_STACK_SEGMENT */
+#endif /* FIXME */
+
+void
+print_section_info (t, abfd)
+ struct target_ops *t;
+ bfd *abfd;
+{
+ struct section_table *p;
+
+ printf_filtered ("\t`%s', ", bfd_get_filename(abfd));
+ wrap_here (" ");
+ printf_filtered ("file type %s.\n", bfd_get_target(abfd));
+ 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");
+ }
+}
+
+static void
+exec_files_info (t)
+ struct target_ops *t;
+{
+ print_section_info (t, exec_bfd);
+
+ if (vmap)
+ {
+ struct vmap *vp;
+
+ printf_unfiltered ("\tMapping info for file `%s'.\n", vmap->name);
+ printf_unfiltered ("\t %8.8s %8.8s %8.8s %8.8s %8.8s %s\n",
+ "tstart", "tend", "dstart", "dend", "section",
+ "file(member)");
+
+ for (vp = vmap; vp; vp = vp->nxt)
+ printf_unfiltered ("\t0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x %s%s%s%s\n",
+ vp->tstart, vp->tend, vp->dstart, vp->dend, vp->name,
+ *vp->member ? "(" : "", vp->member,
+ *vp->member ? ")" : "");
+ }
+}
+
+static void
+set_section_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct section_table *p;
+ char *secname;
+ unsigned seclen;
+ unsigned long secaddr;
+ char secprint[100];
+ long offset;
+
+ if (args == 0)
+ error ("Must specify section name and its virtual address");
+
+ /* Parse out section name */
+ for (secname = args; !isspace(*args); args++) ;
+ seclen = args - secname;
+
+ /* Parse out new virtual address */
+ 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->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;
+ if (from_tty)
+ exec_files_info(&exec_ops);
+ return;
+ }
+ }
+ if (seclen >= sizeof (secprint))
+ seclen = sizeof (secprint) - 1;
+ strncpy (secprint, secname, seclen);
+ secprint[seclen] = '\0';
+ error ("Section %s not found", secprint);
+}
+
+/* If mourn is being called in all the right places, this could be say
+ `gdb internal error' (since generic_mourn calls breakpoint_init_inferior). */
+
+static int
+ignore (addr, contents)
+ CORE_ADDR addr;
+ char *contents;
+{
+ return 0;
+}
+
+struct target_ops exec_ops = {
+ "exec", /* to_shortname */
+ "Local exec file", /* to_longname */
+ "Use an executable file as a target.\n\
+Specify the filename of the executable file.", /* to_doc */
+ exec_file_command, /* to_open */
+ exec_close, /* to_close */
+ find_default_attach, /* to_attach */
+ 0, /* to_detach */
+ 0, /* to_resume */
+ 0, /* to_wait */
+ 0, /* to_fetch_registers */
+ 0, /* to_store_registers */
+ 0, /* to_prepare_to_store */
+ xfer_memory, /* to_xfer_memory */
+ exec_files_info, /* to_files_info */
+ ignore, /* to_insert_breakpoint */
+ ignore, /* to_remove_breakpoint */
+ 0, /* to_terminal_init */
+ 0, /* to_terminal_inferior */
+ 0, /* to_terminal_ours_for_output */
+ 0, /* to_terminal_ours */
+ 0, /* to_terminal_info */
+ 0, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ find_default_create_inferior, /* to_create_inferior */
+ 0, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ file_stratum, /* to_stratum */
+ 0, /* to_next */
+ 0, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 0, /* to_has_stack */
+ 0, /* to_has_registers */
+ 0, /* to_has_execution */
+ 0, /* to_sections */
+ 0, /* to_sections_end */
+ OPS_MAGIC, /* to_magic */
+};
+
+void
+_initialize_exec()
+{
+ struct cmd_list_element *c;
+
+ c = add_cmd ("file", class_files, file_command,
+ "Use FILE as program to be debugged.\n\
+It is read for its symbols, for getting the contents of pure memory,\n\
+and it is the program executed when you use the `run' command.\n\
+If FILE cannot be found as specified, your execution directory path\n\
+($PATH) is searched for a command of that name.\n\
+No arg means to have no executable file and no symbols.", &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_cmd ("exec-file", class_files, exec_file_command,
+ "Use FILE as program for getting contents of pure memory.\n\
+If FILE cannot be found as specified, your execution directory path\n\
+is searched for a command of that name.\n\
+No arg means have no executable file.", &cmdlist);
+ c->completer = filename_completer;
+
+ add_com ("section", class_files, set_section_command,
+ "Change the base address of section SECTION of the exec file to ADDR.\n\
+This can be used if the exec file does not contain section addresses,\n\
+(such as in the a.out format), or when the addresses specified in the\n\
+file itself are wrong. Each section must be changed separately. The\n\
+``info files'' command lists all the sections and their addresses.");
+
+ add_show_from_set
+ (add_set_cmd ("write", class_support, var_boolean, (char *)&write_files,
+ "Set writing into executable and core files.",
+ &setlist),
+ &showlist);
+
+ add_target (&exec_ops);
+}
diff --git a/contrib/gdb/gdb/expprint.c b/contrib/gdb/gdb/expprint.c
new file mode 100644
index 0000000..b44ada2
--- /dev/null
+++ b/contrib/gdb/gdb/expprint.c
@@ -0,0 +1,634 @@
+/* Print in infix form a struct expression.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "language.h"
+#include "parser-defs.h"
+
+/* Prototypes for local functions */
+
+static void
+print_subexp PARAMS ((struct expression *, int *, GDB_FILE *, enum precedence));
+
+void
+print_expression (exp, stream)
+ struct expression *exp;
+ GDB_FILE *stream;
+{
+ int pc = 0;
+ print_subexp (exp, &pc, stream, PREC_NULL);
+}
+
+/* Print the subexpression of EXP that starts in position POS, on STREAM.
+ PREC is the precedence of the surrounding operator;
+ if the precedence of the main operator of this subexpression is less,
+ parentheses are needed here. */
+
+static void
+print_subexp (exp, pos, stream, prec)
+ register struct expression *exp;
+ register int *pos;
+ GDB_FILE *stream;
+ enum precedence prec;
+{
+ register unsigned tem;
+ register const struct op_print *op_print_tab;
+ register int pc;
+ unsigned nargs;
+ register char *op_str;
+ int assign_modify = 0;
+ enum exp_opcode opcode;
+ enum precedence myprec = PREC_NULL;
+ /* Set to 1 for a right-associative operator. */
+ int assoc = 0;
+ value_ptr val;
+ char *tempstr = NULL;
+
+ op_print_tab = exp->language_defn->la_op_print_tab;
+ pc = (*pos)++;
+ opcode = exp->elts[pc].opcode;
+ switch (opcode)
+ {
+ /* Common ops */
+
+ case OP_SCOPE:
+ myprec = PREC_PREFIX;
+ assoc = 0;
+ fputs_filtered (type_name_no_tag (exp->elts[pc + 1].type), stream);
+ fputs_filtered ("::", stream);
+ nargs = longest_to_int (exp->elts[pc + 2].longconst);
+ (*pos) += 4 + BYTES_TO_EXP_ELEM (nargs + 1);
+ fputs_filtered (&exp->elts[pc + 3].string, stream);
+ return;
+
+ case OP_LONG:
+ (*pos) += 3;
+ value_print (value_from_longest (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].longconst),
+ stream, 0, Val_no_prettyprint);
+ return;
+
+ case OP_DOUBLE:
+ (*pos) += 3;
+ value_print (value_from_double (exp->elts[pc + 1].type,
+ exp->elts[pc + 2].doubleconst),
+ stream, 0, Val_no_prettyprint);
+ return;
+
+ case OP_VAR_VALUE:
+ {
+ struct block *b;
+ (*pos) += 3;
+ b = exp->elts[pc + 1].block;
+ if (b != NULL
+ && BLOCK_FUNCTION (b) != NULL
+ && SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)) != NULL)
+ {
+ fputs_filtered (SYMBOL_SOURCE_NAME (BLOCK_FUNCTION (b)), stream);
+ fputs_filtered ("::", stream);
+ }
+ fputs_filtered (SYMBOL_SOURCE_NAME (exp->elts[pc + 2].symbol), stream);
+ }
+ return;
+
+ case OP_LAST:
+ (*pos) += 2;
+ fprintf_filtered (stream, "$%d",
+ longest_to_int (exp->elts[pc + 1].longconst));
+ return;
+
+ case OP_REGISTER:
+ (*pos) += 2;
+ fprintf_filtered (stream, "$%s",
+ reg_names[longest_to_int (exp->elts[pc + 1].longconst)]);
+ return;
+
+ case OP_BOOL:
+ (*pos) += 2;
+ fprintf_filtered (stream, "%s",
+ longest_to_int (exp->elts[pc + 1].longconst)
+ ? "TRUE" : "FALSE");
+ return;
+
+ case OP_INTERNALVAR:
+ (*pos) += 2;
+ fprintf_filtered (stream, "$%s",
+ internalvar_name (exp->elts[pc + 1].internalvar));
+ return;
+
+ case OP_FUNCALL:
+ (*pos) += 2;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered (" (", stream);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem != 0)
+ fputs_filtered (", ", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fputs_filtered (")", stream);
+ return;
+
+ case OP_NAME:
+ case OP_EXPRSTRING:
+ nargs = longest_to_int (exp -> elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ return;
+
+ case OP_STRING:
+ nargs = longest_to_int (exp -> elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (nargs + 1);
+ /* LA_PRINT_STRING will print using the current repeat count threshold.
+ If necessary, we can temporarily set it to zero, or pass it as an
+ additional parameter to LA_PRINT_STRING. -fnf */
+ LA_PRINT_STRING (stream, &exp->elts[pc + 2].string, nargs, 0);
+ return;
+
+ case OP_BITSTRING:
+ nargs = longest_to_int (exp -> elts[pc + 1].longconst);
+ (*pos)
+ += 3 + BYTES_TO_EXP_ELEM ((nargs + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT);
+ fprintf (stream, "B'<unimplemented>'");
+ return;
+
+ case OP_ARRAY:
+ (*pos) += 3;
+ nargs = longest_to_int (exp->elts[pc + 2].longconst);
+ nargs -= longest_to_int (exp->elts[pc + 1].longconst);
+ nargs++;
+ tem = 0;
+ if (exp->elts[pc + 4].opcode == OP_LONG
+ && exp->elts[pc + 5].type == builtin_type_char
+ && exp->language_defn->la_language == language_c)
+ {
+ /* Attempt to print C character arrays using string syntax.
+ Walk through the args, picking up one character from each
+ of the OP_LONG expression elements. If any array element
+ does not match our expection of what we should find for
+ a simple string, revert back to array printing. Note that
+ the last expression element is an explicit null terminator
+ byte, which doesn't get printed. */
+ tempstr = alloca (nargs);
+ pc += 4;
+ while (tem < nargs)
+ {
+ if (exp->elts[pc].opcode != OP_LONG
+ || exp->elts[pc + 1].type != builtin_type_char)
+ {
+ /* Not a simple array of char, use regular array printing. */
+ tem = 0;
+ break;
+ }
+ else
+ {
+ tempstr[tem++] =
+ longest_to_int (exp->elts[pc + 2].longconst);
+ pc += 4;
+ }
+ }
+ }
+ if (tem > 0)
+ {
+ LA_PRINT_STRING (stream, tempstr, nargs - 1, 0);
+ (*pos) = pc;
+ }
+ else
+ {
+ int is_chill = exp->language_defn->la_language == language_chill;
+ fputs_filtered (is_chill ? " [" : " {", stream);
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem != 0)
+ {
+ fputs_filtered (", ", stream);
+ }
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fputs_filtered (is_chill ? "]" : "}", stream);
+ }
+ return;
+
+ case OP_LABELED:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+
+ if (exp->language_defn->la_language == language_chill)
+ {
+ fputs_filtered (".", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered (exp->elts[*pos].opcode == OP_LABELED ? ", "
+ : ": ",
+ stream);
+ }
+ else
+ {
+ /* Gcc support both these syntaxes. Unsure which is preferred. */
+#if 1
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered (": ", stream);
+#else
+ fputs_filtered (".", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ fputs_filtered ("=", stream);
+#endif
+ }
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ return;
+
+ case TERNOP_COND:
+ if ((int) prec > (int) PREC_COMMA)
+ fputs_filtered ("(", stream);
+ /* Print the subexpressions, forcing parentheses
+ around any binary operations within them.
+ This is more parentheses than are strictly necessary,
+ but it looks clearer. */
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ fputs_filtered (" ? ", stream);
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ fputs_filtered (" : ", stream);
+ print_subexp (exp, pos, stream, PREC_HYPER);
+ if ((int) prec > (int) PREC_COMMA)
+ fputs_filtered (")", stream);
+ return;
+
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("(", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ fputs_filtered (opcode == TERNOP_SLICE ? " : " : " UP ", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ fputs_filtered (")", stream);
+ return;
+
+ case STRUCTOP_STRUCT:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered (".", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ return;
+
+ /* Will not occur for Modula-2 */
+ case STRUCTOP_PTR:
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("->", stream);
+ fputs_filtered (&exp->elts[pc + 2].string, stream);
+ return;
+
+
+ case BINOP_SUBSCRIPT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("[", stream);
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ fputs_filtered ("]", stream);
+ return;
+
+ case UNOP_POSTINCREMENT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("++", stream);
+ return;
+
+ case UNOP_POSTDECREMENT:
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered ("--", stream);
+ return;
+
+ case UNOP_CAST:
+ (*pos) += 2;
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered ("(", stream);
+ fputs_filtered ("(", stream);
+ type_print (exp->elts[pc + 1].type, "", stream, 0);
+ fputs_filtered (") ", stream);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered (")", stream);
+ return;
+
+ case UNOP_MEMVAL:
+ (*pos) += 2;
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered ("(", stream);
+ if (exp->elts[pc + 1].type->code == TYPE_CODE_FUNC &&
+ exp->elts[pc + 3].opcode == OP_LONG) {
+ /* We have a minimal symbol fn, probably. It's encoded
+ as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address).
+ Swallow the OP_LONG (including both its opcodes); ignore
+ its type; print the value in the type of the MEMVAL. */
+ (*pos) += 4;
+ val = value_at_lazy (exp->elts[pc + 1].type,
+ (CORE_ADDR) exp->elts[pc + 5].longconst);
+ value_print (val, stream, 0, Val_no_prettyprint);
+ } else {
+ fputs_filtered ("{", stream);
+ type_print (exp->elts[pc + 1].type, "", stream, 0);
+ fputs_filtered ("} ", stream);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ }
+ if ((int) prec > (int) PREC_PREFIX)
+ fputs_filtered (")", stream);
+ return;
+
+ case BINOP_ASSIGN_MODIFY:
+ opcode = exp->elts[pc + 1].opcode;
+ (*pos) += 2;
+ myprec = PREC_ASSIGN;
+ assoc = 1;
+ assign_modify = 1;
+ op_str = "???";
+ for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
+ if (op_print_tab[tem].opcode == opcode)
+ {
+ op_str = op_print_tab[tem].string;
+ break;
+ }
+ if (op_print_tab[tem].opcode != opcode)
+ /* Not found; don't try to keep going because we don't know how
+ to interpret further elements. */
+ error ("Invalid expression");
+ break;
+
+ /* C++ ops */
+
+ case OP_THIS:
+ ++(*pos);
+ fputs_filtered ("this", stream);
+ return;
+
+ /* Modula-2 ops */
+
+ case MULTI_SUBSCRIPT:
+ (*pos) += 2;
+ nargs = longest_to_int (exp->elts[pc + 1].longconst);
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fprintf_unfiltered (stream, " [");
+ for (tem = 0; tem < nargs; tem++)
+ {
+ if (tem != 0)
+ fprintf_unfiltered (stream, ", ");
+ print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
+ }
+ fprintf_unfiltered (stream, "]");
+ return;
+
+ case BINOP_VAL:
+ (*pos)+=2;
+ fprintf_unfiltered(stream,"VAL(");
+ type_print(exp->elts[pc+1].type,"",stream,0);
+ fprintf_unfiltered(stream,",");
+ print_subexp(exp,pos,stream,PREC_PREFIX);
+ fprintf_unfiltered(stream,")");
+ return;
+
+ case BINOP_INCL:
+ case BINOP_EXCL:
+ error("print_subexp: Not implemented.");
+
+ /* Default ops */
+
+ default:
+ op_str = "???";
+ for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
+ if (op_print_tab[tem].opcode == opcode)
+ {
+ op_str = op_print_tab[tem].string;
+ myprec = op_print_tab[tem].precedence;
+ assoc = op_print_tab[tem].right_assoc;
+ break;
+ }
+ if (op_print_tab[tem].opcode != opcode)
+ /* Not found; don't try to keep going because we don't know how
+ to interpret further elements. For example, this happens
+ if opcode is OP_TYPE. */
+ error ("Invalid expression");
+ }
+
+ /* Note that PREC_BUILTIN will always emit parentheses. */
+ if ((int) myprec < (int) prec)
+ fputs_filtered ("(", stream);
+ if ((int) opcode > (int) BINOP_END)
+ {
+ if (assoc)
+ {
+ /* Unary postfix operator. */
+ print_subexp (exp, pos, stream, PREC_SUFFIX);
+ fputs_filtered (op_str, stream);
+ }
+ else
+ {
+ /* Unary prefix operator. */
+ fputs_filtered (op_str, stream);
+ if (myprec == PREC_BUILTIN_FUNCTION)
+ fputs_filtered ("(", stream);
+ print_subexp (exp, pos, stream, PREC_PREFIX);
+ if (myprec == PREC_BUILTIN_FUNCTION)
+ fputs_filtered (")", stream);
+ }
+ }
+ else
+ {
+ /* Binary operator. */
+ /* Print left operand.
+ If operator is right-associative,
+ increment precedence for this operand. */
+ print_subexp (exp, pos, stream,
+ (enum precedence) ((int) myprec + assoc));
+ /* Print the operator itself. */
+ if (assign_modify)
+ fprintf_filtered (stream, " %s= ", op_str);
+ else if (op_str[0] == ',')
+ fprintf_filtered (stream, "%s ", op_str);
+ else
+ fprintf_filtered (stream, " %s ", op_str);
+ /* Print right operand.
+ If operator is left-associative,
+ increment precedence for this operand. */
+ print_subexp (exp, pos, stream,
+ (enum precedence) ((int) myprec + !assoc));
+ }
+
+ if ((int) myprec < (int) prec)
+ fputs_filtered (")", stream);
+}
+
+/* Return the operator corresponding to opcode OP as
+ a string. NULL indicates that the opcode was not found in the
+ current language table. */
+char *
+op_string(op)
+ enum exp_opcode op;
+{
+ int tem;
+ register const struct op_print *op_print_tab;
+
+ op_print_tab = current_language->la_op_print_tab;
+ for (tem = 0; op_print_tab[tem].opcode != OP_NULL; tem++)
+ if (op_print_tab[tem].opcode == op)
+ return op_print_tab[tem].string;
+ return NULL;
+}
+
+#ifdef DEBUG_EXPRESSIONS
+
+/* Support for dumping the raw data from expressions in a human readable
+ form. */
+
+void
+dump_expression (exp, stream, note)
+ struct expression *exp;
+ GDB_FILE *stream;
+ char *note;
+{
+ int elt;
+ char *opcode_name;
+ char *eltscan;
+ int eltsize;
+
+ 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));
+ fprintf_filtered (stream, "\t%5s %20s %16s %s\n", "Index", "Opcode",
+ "Hex Value", "String Value");
+ for (elt = 0; elt < exp -> nelts; elt++)
+ {
+ fprintf_filtered (stream, "\t%5d ", elt);
+ switch (exp -> elts[elt].opcode)
+ {
+ default: opcode_name = "<unknown>"; break;
+ case OP_NULL: opcode_name = "OP_NULL"; break;
+ case BINOP_ADD: opcode_name = "BINOP_ADD"; break;
+ case BINOP_SUB: opcode_name = "BINOP_SUB"; break;
+ case BINOP_MUL: opcode_name = "BINOP_MUL"; break;
+ case BINOP_DIV: opcode_name = "BINOP_DIV"; break;
+ case BINOP_REM: opcode_name = "BINOP_REM"; break;
+ case BINOP_MOD: opcode_name = "BINOP_MOD"; break;
+ case BINOP_LSH: opcode_name = "BINOP_LSH"; break;
+ case BINOP_RSH: opcode_name = "BINOP_RSH"; break;
+ case BINOP_LOGICAL_AND: opcode_name = "BINOP_LOGICAL_AND"; break;
+ case BINOP_LOGICAL_OR: opcode_name = "BINOP_LOGICAL_OR"; break;
+ case BINOP_BITWISE_AND: opcode_name = "BINOP_BITWISE_AND"; break;
+ case BINOP_BITWISE_IOR: opcode_name = "BINOP_BITWISE_IOR"; break;
+ case BINOP_BITWISE_XOR: opcode_name = "BINOP_BITWISE_XOR"; break;
+ case BINOP_EQUAL: opcode_name = "BINOP_EQUAL"; break;
+ case BINOP_NOTEQUAL: opcode_name = "BINOP_NOTEQUAL"; break;
+ case BINOP_LESS: opcode_name = "BINOP_LESS"; break;
+ case BINOP_GTR: opcode_name = "BINOP_GTR"; break;
+ case BINOP_LEQ: opcode_name = "BINOP_LEQ"; break;
+ case BINOP_GEQ: opcode_name = "BINOP_GEQ"; break;
+ case BINOP_REPEAT: opcode_name = "BINOP_REPEAT"; break;
+ case BINOP_ASSIGN: opcode_name = "BINOP_ASSIGN"; break;
+ case BINOP_COMMA: opcode_name = "BINOP_COMMA"; break;
+ case BINOP_SUBSCRIPT: opcode_name = "BINOP_SUBSCRIPT"; break;
+ case MULTI_SUBSCRIPT: opcode_name = "MULTI_SUBSCRIPT"; break;
+ case BINOP_EXP: opcode_name = "BINOP_EXP"; break;
+ case BINOP_MIN: opcode_name = "BINOP_MIN"; break;
+ case BINOP_MAX: opcode_name = "BINOP_MAX"; break;
+ case BINOP_SCOPE: opcode_name = "BINOP_SCOPE"; break;
+ case STRUCTOP_MEMBER: opcode_name = "STRUCTOP_MEMBER"; break;
+ case STRUCTOP_MPTR: opcode_name = "STRUCTOP_MPTR"; break;
+ case BINOP_INTDIV: opcode_name = "BINOP_INTDIV"; break;
+ case BINOP_ASSIGN_MODIFY: opcode_name = "BINOP_ASSIGN_MODIFY"; break;
+ case BINOP_VAL: opcode_name = "BINOP_VAL"; break;
+ case BINOP_INCL: opcode_name = "BINOP_INCL"; break;
+ case BINOP_EXCL: opcode_name = "BINOP_EXCL"; break;
+ case BINOP_CONCAT: opcode_name = "BINOP_CONCAT"; break;
+ case BINOP_RANGE: opcode_name = "BINOP_RANGE"; break;
+ case BINOP_END: opcode_name = "BINOP_END"; break;
+ case TERNOP_COND: opcode_name = "TERNOP_COND"; break;
+ case TERNOP_SLICE: opcode_name = "TERNOP_SLICE"; break;
+ case TERNOP_SLICE_COUNT: opcode_name = "TERNOP_SLICE_COUNT"; break;
+ case OP_LONG: opcode_name = "OP_LONG"; break;
+ case OP_DOUBLE: opcode_name = "OP_DOUBLE"; break;
+ case OP_VAR_VALUE: opcode_name = "OP_VAR_VALUE"; break;
+ case OP_LAST: opcode_name = "OP_LAST"; break;
+ case OP_REGISTER: opcode_name = "OP_REGISTER"; break;
+ case OP_INTERNALVAR: opcode_name = "OP_INTERNALVAR"; break;
+ case OP_FUNCALL: opcode_name = "OP_FUNCALL"; break;
+ case OP_STRING: opcode_name = "OP_STRING"; break;
+ case OP_BITSTRING: opcode_name = "OP_BITSTRING"; break;
+ case OP_ARRAY: opcode_name = "OP_ARRAY"; break;
+ case UNOP_CAST: opcode_name = "UNOP_CAST"; break;
+ case UNOP_MEMVAL: opcode_name = "UNOP_MEMVAL"; break;
+ case UNOP_NEG: opcode_name = "UNOP_NEG"; break;
+ case UNOP_LOGICAL_NOT: opcode_name = "UNOP_LOGICAL_NOT"; break;
+ case UNOP_COMPLEMENT: opcode_name = "UNOP_COMPLEMENT"; break;
+ case UNOP_IND: opcode_name = "UNOP_IND"; break;
+ case UNOP_ADDR: opcode_name = "UNOP_ADDR"; break;
+ case UNOP_PREINCREMENT: opcode_name = "UNOP_PREINCREMENT"; break;
+ case UNOP_POSTINCREMENT: opcode_name = "UNOP_POSTINCREMENT"; break;
+ case UNOP_PREDECREMENT: opcode_name = "UNOP_PREDECREMENT"; break;
+ case UNOP_POSTDECREMENT: opcode_name = "UNOP_POSTDECREMENT"; break;
+ case UNOP_SIZEOF: opcode_name = "UNOP_SIZEOF"; break;
+ case UNOP_LOWER: opcode_name = "UNOP_LOWER"; break;
+ case UNOP_UPPER: opcode_name = "UNOP_UPPER"; break;
+ case UNOP_LENGTH: opcode_name = "UNOP_LENGTH"; break;
+ case UNOP_PLUS: opcode_name = "UNOP_PLUS"; break;
+ case UNOP_CAP: opcode_name = "UNOP_CAP"; break;
+ case UNOP_CHR: opcode_name = "UNOP_CHR"; break;
+ case UNOP_ORD: opcode_name = "UNOP_ORD"; break;
+ case UNOP_ABS: opcode_name = "UNOP_ABS"; break;
+ case UNOP_FLOAT: opcode_name = "UNOP_FLOAT"; break;
+ case UNOP_HIGH: opcode_name = "UNOP_HIGH"; break;
+ case UNOP_MAX: opcode_name = "UNOP_MAX"; break;
+ case UNOP_MIN: opcode_name = "UNOP_MIN"; break;
+ case UNOP_ODD: opcode_name = "UNOP_ODD"; break;
+ case UNOP_TRUNC: opcode_name = "UNOP_TRUNC"; break;
+ case OP_BOOL: opcode_name = "OP_BOOL"; break;
+ case OP_M2_STRING: opcode_name = "OP_M2_STRING"; break;
+ case STRUCTOP_STRUCT: opcode_name = "STRUCTOP_STRUCT"; break;
+ case STRUCTOP_PTR: opcode_name = "STRUCTOP_PTR"; break;
+ case OP_THIS: opcode_name = "OP_THIS"; break;
+ case OP_SCOPE: opcode_name = "OP_SCOPE"; break;
+ case OP_TYPE: opcode_name = "OP_TYPE"; break;
+ case OP_LABELED: opcode_name = "OP_LABELED"; break;
+ }
+ fprintf_filtered (stream, "%20s ", opcode_name);
+ fprintf_filtered (stream,
+#if defined (PRINTF_HAS_LONG_LONG)
+ "%ll16x ",
+#else
+ "%l16x ",
+#endif
+ exp -> elts[elt].longconst);
+
+ for (eltscan = (char *) &exp->elts[elt],
+ eltsize = sizeof (union exp_element) ;
+ eltsize-- > 0;
+ eltscan++)
+ {
+ fprintf_filtered (stream, "%c",
+ isprint (*eltscan) ? (*eltscan & 0xFF) : '.');
+ }
+ fprintf_filtered (stream, "\n");
+ }
+}
+
+#endif /* DEBUG_EXPRESSIONS */
diff --git a/contrib/gdb/gdb/expression.h b/contrib/gdb/gdb/expression.h
new file mode 100644
index 0000000..6526db1
--- /dev/null
+++ b/contrib/gdb/gdb/expression.h
@@ -0,0 +1,386 @@
+/* Definitions for expressions stored in reversed prefix form, for GDB.
+ Copyright 1986, 1989, 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (EXPRESSION_H)
+#define EXPRESSION_H 1
+
+#ifdef __STDC__
+struct block; /* Forward declaration for prototypes */
+#endif
+
+/* Definitions for saved C expressions. */
+
+/* An expression is represented as a vector of union exp_element's.
+ Each exp_element is an opcode, except that some opcodes cause
+ the following exp_element to be treated as a long or double constant
+ or as a variable. The opcodes are obeyed, using a stack for temporaries.
+ The value is left on the temporary stack at the end. */
+
+/* When it is necessary to include a string,
+ it can occupy as many exp_elements as it needs.
+ We find the length of the string using strlen,
+ divide to find out how many exp_elements are used up,
+ and skip that many. Strings, like numbers, are indicated
+ by the preceding opcode. */
+
+enum exp_opcode
+{
+ /* Used when it's necessary to pass an opcode which will be ignored,
+ or to catch uninitialized values. */
+ OP_NULL,
+
+/* BINOP_... operate on two values computed by following subexpressions,
+ replacing them by one result value. They take no immediate arguments. */
+
+ BINOP_ADD, /* + */
+ BINOP_SUB, /* - */
+ BINOP_MUL, /* * */
+ BINOP_DIV, /* / */
+ BINOP_REM, /* % */
+ BINOP_MOD, /* mod (Knuth 1.2.4) */
+ BINOP_LSH, /* << */
+ BINOP_RSH, /* >> */
+ BINOP_LOGICAL_AND, /* && */
+ BINOP_LOGICAL_OR, /* || */
+ BINOP_BITWISE_AND, /* & */
+ BINOP_BITWISE_IOR, /* | */
+ BINOP_BITWISE_XOR, /* ^ */
+ BINOP_EQUAL, /* == */
+ BINOP_NOTEQUAL, /* != */
+ BINOP_LESS, /* < */
+ BINOP_GTR, /* > */
+ BINOP_LEQ, /* <= */
+ BINOP_GEQ, /* >= */
+ BINOP_REPEAT, /* @ */
+ BINOP_ASSIGN, /* = */
+ BINOP_COMMA, /* , */
+ BINOP_SUBSCRIPT, /* x[y] */
+ BINOP_EXP, /* Exponentiation */
+
+ /* C++. */
+
+ BINOP_MIN, /* <? */
+ BINOP_MAX, /* >? */
+ BINOP_SCOPE, /* :: */
+
+ /* STRUCTOP_MEMBER is used for pointer-to-member constructs.
+ X . * Y translates into X STRUCTOP_MEMBER Y. */
+ STRUCTOP_MEMBER,
+
+ /* STRUCTOP_MPTR is used for pointer-to-member constructs
+ when X is a pointer instead of an aggregate. */
+ STRUCTOP_MPTR,
+
+ /* end of C++. */
+
+ /* For Modula-2 integer division DIV */
+ BINOP_INTDIV,
+
+ BINOP_ASSIGN_MODIFY, /* +=, -=, *=, and so on.
+ The following exp_element is another opcode,
+ a BINOP_, saying how to modify.
+ Then comes another BINOP_ASSIGN_MODIFY,
+ making three exp_elements in total. */
+
+ /* Modula-2 standard (binary) procedures */
+ BINOP_VAL,
+ BINOP_INCL,
+ BINOP_EXCL,
+
+ /* Concatenate two operands, such as character strings or bitstrings.
+ If the first operand is a integer expression, then it means concatenate
+ the second operand with itself that many times. */
+ BINOP_CONCAT,
+
+ /* For Chill and Pascal. */
+ BINOP_IN, /* Returns 1 iff ARG1 IN ARG2. */
+
+ /* This is the "colon operator" used various places in Chill. */
+ BINOP_RANGE,
+
+ /* This must be the highest BINOP_ value, for expprint.c. */
+ BINOP_END,
+
+ /* Operates on three values computed by following subexpressions. */
+ TERNOP_COND, /* ?: */
+
+ /* A sub-string/sub-array. Chill syntax: OP1(OP2:OP3).
+ Return elements OP2 through OP3 of OP1. */
+ TERNOP_SLICE,
+
+ /* A sub-string/sub-array. Chill syntax: OP1(OP2 UP OP3).
+ Return OP3 elements of OP1, starting with element OP2. */
+ TERNOP_SLICE_COUNT,
+
+ /* Multidimensional subscript operator, such as Modula-2 x[a,b,...].
+ The dimensionality is encoded in the operator, like the number of
+ function arguments in OP_FUNCALL, I.E. <OP><dimension><OP>.
+ The value of the first following subexpression is subscripted
+ by each of the next following subexpressions, one per dimension. */
+ MULTI_SUBSCRIPT,
+
+ /* The OP_... series take immediate following arguments.
+ After the arguments come another OP_... (the same one)
+ so that the grouping can be recognized from the end. */
+
+ /* OP_LONG is followed by a type pointer in the next exp_element
+ and the long constant value in the following exp_element.
+ Then comes another OP_LONG.
+ Thus, the operation occupies four exp_elements. */
+ OP_LONG,
+
+ /* OP_DOUBLE is similar but takes a DOUBLEST constant instead of a long. */
+ OP_DOUBLE,
+
+ /* OP_VAR_VALUE takes one struct block * in the following element,
+ and one struct symbol * in the following exp_element, followed by
+ another OP_VAR_VALUE, making four exp_elements. If the block is
+ non-NULL, evaluate the symbol relative to the innermost frame
+ executing in that block; if the block is NULL use the selected frame. */
+ OP_VAR_VALUE,
+
+ /* OP_LAST is followed by an integer in the next exp_element.
+ The integer is zero for the last value printed,
+ or it is the absolute number of a history element.
+ With another OP_LAST at the end, this makes three exp_elements. */
+ OP_LAST,
+
+ /* OP_REGISTER is followed by an integer in the next exp_element.
+ This is the number of a register to fetch (as an int).
+ With another OP_REGISTER at the end, this makes three exp_elements. */
+ OP_REGISTER,
+
+ /* OP_INTERNALVAR is followed by an internalvar ptr in the next exp_element.
+ With another OP_INTERNALVAR at the end, this makes three exp_elements. */
+ OP_INTERNALVAR,
+
+ /* OP_FUNCALL is followed by an integer in the next exp_element.
+ The integer is the number of args to the function call.
+ That many plus one values from following subexpressions
+ are used, the first one being the function.
+ The integer is followed by a repeat of OP_FUNCALL,
+ making three exp_elements. */
+ OP_FUNCALL,
+
+ /* This is EXACTLY like OP_FUNCALL but is semantically different.
+ In F77, array subscript expressions, substring expressions
+ and function calls are all exactly the same syntactically. They may
+ only be dismabiguated at runtime. Thus this operator, which
+ indicates that we have found something of the form <name> ( <stuff> ) */
+ OP_F77_UNDETERMINED_ARGLIST,
+
+ /* The following OP is a special one, it introduces a F77 complex
+ literal. It is followed by exactly two args that are doubles. */
+ OP_COMPLEX,
+
+ /* OP_STRING represents a string constant.
+ Its format is the same as that of a STRUCTOP, but the string
+ data is just made into a string constant when the operation
+ is executed. */
+ OP_STRING,
+
+ /* OP_BITSTRING represents a packed bitstring constant.
+ Its format is the same as that of a STRUCTOP, but the bitstring
+ data is just made into a bitstring constant when the operation
+ is executed. */
+ OP_BITSTRING,
+
+ /* OP_ARRAY creates an array constant out of the following subexpressions.
+ It is followed by two exp_elements, the first containing an integer
+ that is the lower bound of the array and the second containing another
+ integer that is the upper bound of the array. The second integer is
+ followed by a repeat of OP_ARRAY, making four exp_elements total.
+ The bounds are used to compute the number of following subexpressions
+ to consume, as well as setting the bounds in the created array constant.
+ The type of the elements is taken from the type of the first subexp,
+ and they must all match. */
+ OP_ARRAY,
+
+ /* UNOP_CAST is followed by a type pointer in the next exp_element.
+ With another UNOP_CAST at the end, this makes three exp_elements.
+ It casts the value of the following subexpression. */
+ UNOP_CAST,
+
+ /* UNOP_MEMVAL is followed by a type pointer in the next exp_element
+ With another UNOP_MEMVAL at the end, this makes three exp_elements.
+ It casts the contents of the word addressed by the value of the
+ following subexpression. */
+ UNOP_MEMVAL,
+
+ /* UNOP_... operate on one value from a following subexpression
+ and replace it with a result. They take no immediate arguments. */
+
+ UNOP_NEG, /* Unary - */
+ UNOP_LOGICAL_NOT, /* Unary ! */
+ UNOP_COMPLEMENT, /* Unary ~ */
+ UNOP_IND, /* Unary * */
+ UNOP_ADDR, /* Unary & */
+ UNOP_PREINCREMENT, /* ++ before an expression */
+ UNOP_POSTINCREMENT, /* ++ after an expression */
+ UNOP_PREDECREMENT, /* -- before an expression */
+ UNOP_POSTDECREMENT, /* -- after an expression */
+ UNOP_SIZEOF, /* Unary sizeof (followed by expression) */
+
+ UNOP_PLUS, /* Unary plus */
+
+ UNOP_CAP, /* Modula-2 standard (unary) procedures */
+ UNOP_CHR,
+ UNOP_ORD,
+ UNOP_ABS,
+ UNOP_FLOAT,
+ UNOP_HIGH,
+ UNOP_MAX,
+ UNOP_MIN,
+ UNOP_ODD,
+ UNOP_TRUNC,
+
+ /* Chill builtin functions. */
+ UNOP_LOWER, UNOP_UPPER, UNOP_LENGTH, UNOP_CARD, UNOP_CHMAX, UNOP_CHMIN,
+
+ OP_BOOL, /* Modula-2 builtin BOOLEAN type */
+ OP_M2_STRING, /* Modula-2 string constants */
+
+ /* STRUCTOP_... operate on a value from a following subexpression
+ by extracting a structure component specified by a string
+ that appears in the following exp_elements (as many as needed).
+ STRUCTOP_STRUCT is used for "." and STRUCTOP_PTR for "->".
+ They differ only in the error message given in case the value is
+ not suitable or the structure component specified is not found.
+
+ The length of the string follows the opcode, followed by
+ BYTES_TO_EXP_ELEM(length) elements containing the data of the
+ string, followed by the length again and the opcode again. */
+
+ STRUCTOP_STRUCT,
+ STRUCTOP_PTR,
+
+
+ /* C++ */
+ /* OP_THIS is just a placeholder for the class instance variable.
+ It just comes in a tight (OP_THIS, OP_THIS) pair. */
+ OP_THIS,
+
+ /* OP_SCOPE surrounds a type name and a field name. The type
+ name is encoded as one element, but the field name stays as
+ a string, which, of course, is variable length. */
+ OP_SCOPE,
+
+ /* Used to represent named structure field values in brace initializers
+ (or tuples as they are called in Chill).
+ The gcc C syntax is NAME:VALUE or .NAME=VALUE, the Chill syntax is
+ .NAME:VALUE. Multiple labels (as in the Chill syntax
+ .NAME1,.NAME2:VALUE) is represented as if it were
+ .NAME1:(.NAME2:VALUE) (though that is not valid Chill syntax).
+
+ The NAME is represented as for STRUCTOP_STRUCT; VALUE follows. */
+ OP_LABELED,
+
+ /* OP_TYPE is for parsing types, and used with the "ptype" command
+ so we can look up types that are qualified by scope, either with
+ the GDB "::" operator, or the Modula-2 '.' operator. */
+ OP_TYPE,
+
+ /* An un-looked-up identifier. */
+ OP_NAME,
+
+ /* An unparsed expression. Used for Scheme (for now at least) */
+ OP_EXPRSTRING
+};
+
+union exp_element
+{
+ enum exp_opcode opcode;
+ struct symbol *symbol;
+ LONGEST longconst;
+ DOUBLEST doubleconst;
+ /* Really sizeof (union exp_element) characters (or less for the last
+ element of a string). */
+ char string;
+ struct type *type;
+ struct internalvar *internalvar;
+ struct block *block;
+};
+
+struct expression
+{
+ const struct language_defn *language_defn; /* language it was entered in */
+ int nelts;
+ union exp_element elts[1];
+};
+
+/* Macros for converting between number of expression elements and bytes
+ to store that many expression elements. */
+
+#define EXP_ELEM_TO_BYTES(elements) \
+ ((elements) * sizeof (union exp_element))
+#define BYTES_TO_EXP_ELEM(bytes) \
+ (((bytes) + sizeof (union exp_element) - 1) / sizeof (union exp_element))
+
+/* From parse.c */
+
+extern struct expression *parse_expression PARAMS ((char *));
+
+extern struct expression *parse_exp_1 PARAMS ((char **, struct block *, int));
+
+/* The innermost context required by the stack and register variables
+ we've encountered so far. To use this, set it to NULL, then call
+ parse_<whatever>, then look at it. */
+extern struct block *innermost_block;
+
+/* From eval.c */
+
+/* Values of NOSIDE argument to eval_subexp. */
+
+enum noside
+{
+ EVAL_NORMAL,
+ EVAL_SKIP, /* Only effect is to increment pos. */
+ EVAL_AVOID_SIDE_EFFECTS /* Don't modify any variables or
+ call any functions. The value
+ returned will have the correct
+ type, and will have an
+ approximately correct lvalue
+ type (inaccuracy: anything that is
+ listed as being in a register in
+ the function in which it was
+ declared will be lval_register). */
+};
+
+extern struct value* evaluate_subexp_standard
+PARAMS ((struct type *, struct expression *, int*, enum noside));
+
+/* From expprint.c */
+
+extern void print_expression PARAMS ((struct expression *, GDB_FILE *));
+
+extern char *op_string PARAMS ((enum exp_opcode));
+
+/* To enable dumping of all parsed expressions in a human readable
+ form, define DEBUG_EXPRESSIONS. This is a compile time constant
+ at the moment, since it's not clear that this feature is important
+ enough to include by default. */
+
+#ifdef DEBUG_EXPRESSIONS
+extern void 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 */
+#endif /* DEBUG_EXPRESSIONS */
+
+#endif /* !defined (EXPRESSION_H) */
diff --git a/contrib/gdb/gdb/f-exp.tab.c b/contrib/gdb/gdb/f-exp.tab.c
new file mode 100644
index 0000000..5ba51da
--- /dev/null
+++ b/contrib/gdb/gdb/f-exp.tab.c
@@ -0,0 +1,2089 @@
+
+/* A Bison parser, made from ./f-exp.y with Bison version GNU Bison version 1.24
+ */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define INT 258
+#define FLOAT 259
+#define STRING_LITERAL 260
+#define BOOLEAN_LITERAL 261
+#define NAME 262
+#define TYPENAME 263
+#define NAME_OR_INT 264
+#define SIZEOF 265
+#define ERROR 266
+#define INT_KEYWORD 267
+#define INT_S2_KEYWORD 268
+#define LOGICAL_S1_KEYWORD 269
+#define LOGICAL_S2_KEYWORD 270
+#define LOGICAL_KEYWORD 271
+#define REAL_KEYWORD 272
+#define REAL_S8_KEYWORD 273
+#define REAL_S16_KEYWORD 274
+#define COMPLEX_S8_KEYWORD 275
+#define COMPLEX_S16_KEYWORD 276
+#define COMPLEX_S32_KEYWORD 277
+#define BOOL_AND 278
+#define BOOL_OR 279
+#define BOOL_NOT 280
+#define CHARACTER 281
+#define VARIABLE 282
+#define ASSIGN_MODIFY 283
+#define ABOVE_COMMA 284
+#define EQUAL 285
+#define NOTEQUAL 286
+#define LESSTHAN 287
+#define GREATERTHAN 288
+#define LEQ 289
+#define GEQ 290
+#define LSH 291
+#define RSH 292
+#define UNARY 293
+
+#line 43 "./f-exp.y"
+
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "f-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth f_maxdepth
+#define yyparse f_parse
+#define yylex f_lex
+#define yyerror f_error
+#define yylval f_lval
+#define yychar f_char
+#define yydebug f_debug
+#define yypact f_pact
+#define yyr1 f_r1
+#define yyr2 f_r2
+#define yydef f_def
+#define yychk f_chk
+#define yypgo f_pgo
+#define yyact f_act
+#define yyexca f_exca
+#define yyerrflag f_errflag
+#define yynerrs f_nerrs
+#define yyps f_ps
+#define yypv f_pv
+#define yys f_s
+#define yy_yys f_yys
+#define yystate f_state
+#define yytmp f_tmp
+#define yyv f_v
+#define yy_yyv f_yyv
+#define yyval f_val
+#define yylloc f_lloc
+#define yyreds f_reds /* With YYDEBUG defined */
+#define yytoks f_toks /* With YYDEBUG defined */
+#define yylhs f_yylhs
+#define yylen f_yylen
+#define yydefred f_yydefred
+#define yydgoto f_yydgoto
+#define yysindex f_yysindex
+#define yyrindex f_yyrindex
+#define yygindex f_yygindex
+#define yytable f_yytable
+#define yycheck f_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 1 /* Default to no yydebug support */
+#endif
+
+int yyparse PARAMS ((void));
+
+static int yylex PARAMS ((void));
+
+void yyerror PARAMS ((char *));
+
+
+#line 118 "./f-exp.y"
+typedef union
+ {
+ LONGEST lval;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val;
+ DOUBLEST dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ } YYSTYPE;
+#line 140 "./f-exp.y"
+
+/* YYSTYPE gets defined by %union */
+static int parse_number PARAMS ((char *, int, int, YYSTYPE *));
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 125
+#define YYFLAG -32768
+#define YYNTBASE 55
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 293 ? yytranslate[x] : 71)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 49, 35, 2, 51,
+ 52, 47, 45, 29, 46, 2, 48, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 54, 2, 2,
+ 31, 2, 32, 44, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 34, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 33, 2, 53, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 30, 36, 37, 38, 39, 40, 41,
+ 42, 43, 50
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 2, 4, 6, 10, 13, 16, 19, 22, 25,
+ 28, 29, 35, 36, 38, 40, 44, 48, 52, 56,
+ 61, 65, 69, 73, 77, 81, 85, 89, 93, 97,
+ 101, 105, 109, 113, 117, 121, 125, 129, 133, 137,
+ 141, 145, 147, 149, 151, 153, 155, 160, 162, 164,
+ 166, 168, 170, 173, 175, 178, 180, 183, 185, 189,
+ 192, 194, 197, 201, 203, 205, 207, 209, 211, 213,
+ 215, 217, 219, 221, 223, 225, 227, 229, 231, 235,
+ 237, 239, 241
+};
+
+static const short yyrhs[] = { 57,
+ 0, 56, 0, 63, 0, 51, 57, 52, 0, 47,
+ 57, 0, 35, 57, 0, 46, 57, 0, 25, 57,
+ 0, 53, 57, 0, 10, 57, 0, 0, 57, 51,
+ 58, 59, 52, 0, 0, 57, 0, 60, 0, 59,
+ 29, 57, 0, 57, 54, 57, 0, 57, 29, 57,
+ 0, 51, 61, 52, 0, 51, 63, 52, 57, 0,
+ 57, 44, 57, 0, 57, 47, 57, 0, 57, 48,
+ 57, 0, 57, 49, 57, 0, 57, 45, 57, 0,
+ 57, 46, 57, 0, 57, 42, 57, 0, 57, 43,
+ 57, 0, 57, 36, 57, 0, 57, 37, 57, 0,
+ 57, 40, 57, 0, 57, 41, 57, 0, 57, 38,
+ 57, 0, 57, 39, 57, 0, 57, 35, 57, 0,
+ 57, 34, 57, 0, 57, 33, 57, 0, 57, 23,
+ 57, 0, 57, 24, 57, 0, 57, 31, 57, 0,
+ 57, 28, 57, 0, 3, 0, 9, 0, 4, 0,
+ 62, 0, 27, 0, 10, 51, 63, 52, 0, 6,
+ 0, 5, 0, 70, 0, 64, 0, 68, 0, 68,
+ 65, 0, 47, 0, 47, 65, 0, 35, 0, 35,
+ 65, 0, 66, 0, 51, 65, 52, 0, 66, 67,
+ 0, 67, 0, 51, 52, 0, 51, 69, 52, 0,
+ 8, 0, 12, 0, 13, 0, 26, 0, 16, 0,
+ 15, 0, 14, 0, 17, 0, 18, 0, 19, 0,
+ 20, 0, 21, 0, 22, 0, 8, 0, 63, 0,
+ 69, 29, 63, 0, 7, 0, 8, 0, 9, 0,
+ 7, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 217, 218, 221, 227, 232, 235, 238, 242, 246, 250,
+ 259, 261, 267, 270, 274, 277, 281, 286, 290, 294,
+ 302, 306, 310, 314, 318, 322, 326, 330, 334, 338,
+ 342, 346, 350, 354, 358, 362, 366, 370, 375, 379,
+ 383, 389, 396, 405, 412, 415, 418, 426, 433, 441,
+ 485, 488, 489, 532, 534, 536, 538, 540, 543, 545,
+ 547, 551, 553, 558, 560, 562, 564, 566, 568, 570,
+ 572, 574, 576, 578, 580, 582, 586, 590, 595, 602,
+ 604, 606, 610
+};
+
+static const char * const yytname[] = { "$","error","$undefined.","INT","FLOAT",
+"STRING_LITERAL","BOOLEAN_LITERAL","NAME","TYPENAME","NAME_OR_INT","SIZEOF",
+"ERROR","INT_KEYWORD","INT_S2_KEYWORD","LOGICAL_S1_KEYWORD","LOGICAL_S2_KEYWORD",
+"LOGICAL_KEYWORD","REAL_KEYWORD","REAL_S8_KEYWORD","REAL_S16_KEYWORD","COMPLEX_S8_KEYWORD",
+"COMPLEX_S16_KEYWORD","COMPLEX_S32_KEYWORD","BOOL_AND","BOOL_OR","BOOL_NOT",
+"CHARACTER","VARIABLE","ASSIGN_MODIFY","','","ABOVE_COMMA","'='","'?'","'|'",
+"'^'","'&'","EQUAL","NOTEQUAL","LESSTHAN","GREATERTHAN","LEQ","GEQ","LSH","RSH",
+"'@'","'+'","'-'","'*'","'/'","'%'","UNARY","'('","')'","'~'","':'","start",
+"type_exp","exp","@1","arglist","substring","complexnum","variable","type","ptype",
+"abs_decl","direct_abs_decl","func_mod","typebase","nonempty_typelist","name_not_typename",
+""
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 55, 55, 56, 57, 57, 57, 57, 57, 57, 57,
+ 58, 57, 59, 59, 59, 59, 60, 61, 57, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 62,
+ 63, 64, 64, 65, 65, 65, 65, 65, 66, 66,
+ 66, 67, 67, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 68, -1, 69, 69, -1,
+ -1, -1, 70
+};
+
+static const short yyr2[] = { 0,
+ 1, 1, 1, 3, 2, 2, 2, 2, 2, 2,
+ 0, 5, 0, 1, 1, 3, 3, 3, 3, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 1, 1, 1, 1, 4, 1, 1, 1,
+ 1, 1, 2, 1, 2, 1, 2, 1, 3, 2,
+ 1, 2, 3, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 1,
+ 1, 1, 1
+};
+
+static const short yydefact[] = { 0,
+ 42, 44, 49, 48, 83, 64, 43, 0, 65, 66,
+ 70, 69, 68, 71, 72, 73, 74, 75, 76, 0,
+ 67, 46, 0, 0, 0, 0, 0, 2, 1, 45,
+ 3, 51, 52, 50, 0, 10, 8, 6, 7, 5,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 11, 56, 54, 0, 53,
+ 58, 61, 0, 0, 4, 19, 0, 38, 39, 41,
+ 40, 37, 36, 35, 29, 30, 33, 34, 31, 32,
+ 27, 28, 21, 25, 26, 22, 23, 24, 13, 57,
+ 55, 62, 78, 0, 0, 0, 60, 47, 18, 20,
+ 14, 0, 15, 59, 0, 63, 0, 0, 12, 79,
+ 17, 16, 0, 0, 0
+};
+
+static const short yydefgoto[] = { 123,
+ 28, 41, 99, 112, 113, 42, 30, 103, 32, 70,
+ 71, 72, 33, 105, 34
+};
+
+static const short yypact[] = { 75,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768, 126,-32768,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 135,
+-32768,-32768, 135, 135, 135, 75, 135,-32768, 309,-32768,
+-32768,-32768, -34,-32768, 75, -49, -49, -49, -49, -49,
+ 279, -46, -45, -49, 135, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 135, 135, 135, 135, 135, 135,
+ 135, 135, 135, 135, 135,-32768, -34, -34, 206,-32768,
+ -42,-32768, -36, 135,-32768,-32768, 135, 355, 336, 309,
+ 309, 390, 407, 161, 221, 221, -11, -11, -11, -11,
+ 22, 22, 58, -37, -37, -49, -49, -49, 135,-32768,
+-32768,-32768,-32768, -33, -26, 230,-32768, 186, 309, -49,
+ 250, -24,-32768,-32768, 397,-32768, 135, 135,-32768,-32768,
+ 309, 309, 15, 18,-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768, 0,-32768,-32768,-32768,-32768,-32768, 4,-32768, -25,
+-32768, -50,-32768,-32768,-32768
+};
+
+
+#define YYLAST 458
+
+
+static const short yytable[] = { 29,
+ 67, 66, 115, 31, 118, 76, 77, 36, 106, 63,
+ 64, 65, 68, 66, 124, 108, 69, 125, 114, 37,
+ 107, 0, 38, 39, 40, 116, 44, 119, 0, 43,
+ 58, 59, 60, 61, 62, 63, 64, 65, 73, 66,
+ 0, 100, 101, 104, 78, 79, 80, 81, 82, 83,
+ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93,
+ 94, 95, 96, 97, 98, 60, 61, 62, 63, 64,
+ 65, 0, 66, 109, 0, 0, 110, 1, 2, 3,
+ 4, 5, 6, 7, 8, 0, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 0, 111, 20,
+ 21, 22, 61, 62, 63, 64, 65, 110, 66, 23,
+ 0, 0, 0, 0, 0, 0, 121, 122, 120, 0,
+ 24, 25, 0, 0, 0, 26, 0, 27, 1, 2,
+ 3, 4, 5, 0, 7, 8, 0, 1, 2, 3,
+ 4, 5, 0, 7, 8, 0, 0, 0, 0, 0,
+ 20, 0, 22, 0, 0, 0, 0, 0, 0, 20,
+ 23, 22, 0, 0, 0, 0, 0, 0, 0, 23,
+ 0, 24, 25, 0, 0, 0, 35, 0, 27, 0,
+ 24, 25, 0, 0, 0, 26, 0, 27, 1, 2,
+ 3, 4, 5, 0, 7, 8, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 20, 66, 22, 6, 0, 0, 0, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19, 0, 0,
+ 0, 21, 0, 0, 0, 0, 26, 6, 27, 0,
+ 67, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 68, 0, 0, 21, 69, 102, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
+ 0, 66, 45, 46, 0, 0, 0, 47, 0, 0,
+ 48, 102, 49, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 0,
+ 66, 45, 46, 117, 0, 0, 47, 74, 0, 48,
+ 0, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 0, 66,
+ 75, 45, 46, 0, 0, 0, 47, 0, 0, 48,
+ 0, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65, 45, 66,
+ 0, 0, 0, 0, 0, 0, 0, 0, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 0, 66, 49, 50, 51,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ 62, 63, 64, 65, 6, 66, 0, 0, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 0,
+ 0, 0, 21, 50, 51, 52, 53, 54, 55, 56,
+ 57, 58, 59, 60, 61, 62, 63, 64, 65, 0,
+ 66, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+ 60, 61, 62, 63, 64, 65, 0, 66
+};
+
+static const short yycheck[] = { 0,
+ 35, 51, 29, 0, 29, 52, 52, 8, 51, 47,
+ 48, 49, 47, 51, 0, 52, 51, 0, 52, 20,
+ 71, -1, 23, 24, 25, 52, 27, 52, -1, 26,
+ 42, 43, 44, 45, 46, 47, 48, 49, 35, 51,
+ -1, 67, 68, 69, 45, 46, 47, 48, 49, 50,
+ 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
+ 61, 62, 63, 64, 65, 44, 45, 46, 47, 48,
+ 49, -1, 51, 74, -1, -1, 77, 3, 4, 5,
+ 6, 7, 8, 9, 10, -1, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, -1, 99, 25,
+ 26, 27, 45, 46, 47, 48, 49, 108, 51, 35,
+ -1, -1, -1, -1, -1, -1, 117, 118, 115, -1,
+ 46, 47, -1, -1, -1, 51, -1, 53, 3, 4,
+ 5, 6, 7, -1, 9, 10, -1, 3, 4, 5,
+ 6, 7, -1, 9, 10, -1, -1, -1, -1, -1,
+ 25, -1, 27, -1, -1, -1, -1, -1, -1, 25,
+ 35, 27, -1, -1, -1, -1, -1, -1, -1, 35,
+ -1, 46, 47, -1, -1, -1, 51, -1, 53, -1,
+ 46, 47, -1, -1, -1, 51, -1, 53, 3, 4,
+ 5, 6, 7, -1, 9, 10, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 25, 51, 27, 8, -1, -1, -1, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, -1, -1,
+ -1, 26, -1, -1, -1, -1, 51, 8, 53, -1,
+ 35, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 47, -1, -1, 26, 51, 52, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ -1, 51, 23, 24, -1, -1, -1, 28, -1, -1,
+ 31, 52, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, -1,
+ 51, 23, 24, 54, -1, -1, 28, 29, -1, 31,
+ -1, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, -1, 51,
+ 52, 23, 24, -1, -1, -1, 28, -1, -1, 31,
+ -1, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 23, 51,
+ -1, -1, -1, -1, -1, -1, -1, -1, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, -1, 51, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 47, 48, 49, 8, 51, -1, -1, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, -1,
+ -1, -1, 26, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, -1,
+ 51, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, -1, 51
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/unsupported/share/bison.simple"
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 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
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#endif /* alloca not defined. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT return(0)
+#define YYABORT return(1)
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (from, to, count)
+ char *from;
+ char *to;
+ int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *from, char *to, int count)
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 192 "/usr/unsupported/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#else
+#define YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#endif
+
+int
+yyparse(YYPARSE_PARAM)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to xreallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to xreallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+ yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+ yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 3:
+#line 222 "./f-exp.y"
+{ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(yyvsp[0].tval);
+ write_exp_elt_opcode(OP_TYPE); ;
+ break;}
+case 4:
+#line 228 "./f-exp.y"
+{ ;
+ break;}
+case 5:
+#line 233 "./f-exp.y"
+{ write_exp_elt_opcode (UNOP_IND); ;
+ break;}
+case 6:
+#line 236 "./f-exp.y"
+{ write_exp_elt_opcode (UNOP_ADDR); ;
+ break;}
+case 7:
+#line 239 "./f-exp.y"
+{ write_exp_elt_opcode (UNOP_NEG); ;
+ break;}
+case 8:
+#line 243 "./f-exp.y"
+{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); ;
+ break;}
+case 9:
+#line 247 "./f-exp.y"
+{ write_exp_elt_opcode (UNOP_COMPLEMENT); ;
+ break;}
+case 10:
+#line 251 "./f-exp.y"
+{ write_exp_elt_opcode (UNOP_SIZEOF); ;
+ break;}
+case 11:
+#line 260 "./f-exp.y"
+{ start_arglist (); ;
+ break;}
+case 12:
+#line 262 "./f-exp.y"
+{ write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST); ;
+ break;}
+case 14:
+#line 271 "./f-exp.y"
+{ arglist_len = 1; ;
+ break;}
+case 15:
+#line 275 "./f-exp.y"
+{ arglist_len = 2;;
+ break;}
+case 16:
+#line 278 "./f-exp.y"
+{ arglist_len++; ;
+ break;}
+case 17:
+#line 282 "./f-exp.y"
+{ ;
+ break;}
+case 18:
+#line 287 "./f-exp.y"
+{ ;
+ break;}
+case 19:
+#line 291 "./f-exp.y"
+{ write_exp_elt_opcode(OP_COMPLEX); ;
+ break;}
+case 20:
+#line 295 "./f-exp.y"
+{ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (yyvsp[-2].tval);
+ write_exp_elt_opcode (UNOP_CAST); ;
+ break;}
+case 21:
+#line 303 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_REPEAT); ;
+ break;}
+case 22:
+#line 307 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_MUL); ;
+ break;}
+case 23:
+#line 311 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_DIV); ;
+ break;}
+case 24:
+#line 315 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_REM); ;
+ break;}
+case 25:
+#line 319 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_ADD); ;
+ break;}
+case 26:
+#line 323 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_SUB); ;
+ break;}
+case 27:
+#line 327 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_LSH); ;
+ break;}
+case 28:
+#line 331 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_RSH); ;
+ break;}
+case 29:
+#line 335 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_EQUAL); ;
+ break;}
+case 30:
+#line 339 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_NOTEQUAL); ;
+ break;}
+case 31:
+#line 343 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_LEQ); ;
+ break;}
+case 32:
+#line 347 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_GEQ); ;
+ break;}
+case 33:
+#line 351 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_LESS); ;
+ break;}
+case 34:
+#line 355 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_GTR); ;
+ break;}
+case 35:
+#line 359 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_AND); ;
+ break;}
+case 36:
+#line 363 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_XOR); ;
+ break;}
+case 37:
+#line 367 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_IOR); ;
+ break;}
+case 38:
+#line 371 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_AND); ;
+ break;}
+case 39:
+#line 376 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_OR); ;
+ break;}
+case 40:
+#line 380 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN); ;
+ break;}
+case 41:
+#line 384 "./f-exp.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode (yyvsp[-1].opcode);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); ;
+ break;}
+case 42:
+#line 390 "./f-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (yyvsp[0].typed_val.type);
+ write_exp_elt_longcst ((LONGEST)(yyvsp[0].typed_val.val));
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 43:
+#line 397 "./f-exp.y"
+{ YYSTYPE val;
+ parse_number (yyvsp[0].ssym.stoken.ptr, yyvsp[0].ssym.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val.val);
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 44:
+#line 406 "./f-exp.y"
+{ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_f_real_s8);
+ write_exp_elt_dblcst (yyvsp[0].dval);
+ write_exp_elt_opcode (OP_DOUBLE); ;
+ break;}
+case 47:
+#line 419 "./f-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_f_integer);
+ CHECK_TYPEDEF (yyvsp[-1].tval);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (yyvsp[-1].tval));
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 48:
+#line 427 "./f-exp.y"
+{ write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+ write_exp_elt_opcode (OP_BOOL);
+ ;
+ break;}
+case 49:
+#line 434 "./f-exp.y"
+{
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (OP_STRING);
+ ;
+ break;}
+case 50:
+#line 442 "./f-exp.y"
+{ struct symbol *sym = yyvsp[0].ssym.sym;
+
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name (yyvsp[0].ssym.stoken);
+
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name (yyvsp[0].ssym.stoken));
+ }
+ ;
+ break;}
+case 53:
+#line 490 "./f-exp.y"
+{
+ /* This is where the interesting stuff happens. */
+ int done = 0;
+ int array_size;
+ struct type *follow_type = yyvsp[-1].tval;
+ struct type *range_type;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = pop_type_int ();
+ if (array_size != -1)
+ {
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_f_integer, 0,
+ array_size - 1);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ }
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ yyval.tval = follow_type;
+ ;
+ break;}
+case 54:
+#line 533 "./f-exp.y"
+{ push_type (tp_pointer); yyval.voidval = 0; ;
+ break;}
+case 55:
+#line 535 "./f-exp.y"
+{ push_type (tp_pointer); yyval.voidval = yyvsp[0].voidval; ;
+ break;}
+case 56:
+#line 537 "./f-exp.y"
+{ push_type (tp_reference); yyval.voidval = 0; ;
+ break;}
+case 57:
+#line 539 "./f-exp.y"
+{ push_type (tp_reference); yyval.voidval = yyvsp[0].voidval; ;
+ break;}
+case 59:
+#line 544 "./f-exp.y"
+{ yyval.voidval = yyvsp[-1].voidval; ;
+ break;}
+case 60:
+#line 546 "./f-exp.y"
+{ push_type (tp_function); ;
+ break;}
+case 61:
+#line 548 "./f-exp.y"
+{ push_type (tp_function); ;
+ break;}
+case 62:
+#line 552 "./f-exp.y"
+{ yyval.voidval = 0; ;
+ break;}
+case 63:
+#line 554 "./f-exp.y"
+{ free ((PTR)yyvsp[-1].tvec); yyval.voidval = 0; ;
+ break;}
+case 64:
+#line 559 "./f-exp.y"
+{ yyval.tval = yyvsp[0].tsym.type; ;
+ break;}
+case 65:
+#line 561 "./f-exp.y"
+{ yyval.tval = builtin_type_f_integer; ;
+ break;}
+case 66:
+#line 563 "./f-exp.y"
+{ yyval.tval = builtin_type_f_integer_s2; ;
+ break;}
+case 67:
+#line 565 "./f-exp.y"
+{ yyval.tval = builtin_type_f_character; ;
+ break;}
+case 68:
+#line 567 "./f-exp.y"
+{ yyval.tval = builtin_type_f_logical;;
+ break;}
+case 69:
+#line 569 "./f-exp.y"
+{ yyval.tval = builtin_type_f_logical_s2;;
+ break;}
+case 70:
+#line 571 "./f-exp.y"
+{ yyval.tval = builtin_type_f_logical_s1;;
+ break;}
+case 71:
+#line 573 "./f-exp.y"
+{ yyval.tval = builtin_type_f_real;;
+ break;}
+case 72:
+#line 575 "./f-exp.y"
+{ yyval.tval = builtin_type_f_real_s8;;
+ break;}
+case 73:
+#line 577 "./f-exp.y"
+{ yyval.tval = builtin_type_f_real_s16;;
+ break;}
+case 74:
+#line 579 "./f-exp.y"
+{ yyval.tval = builtin_type_f_complex_s8;;
+ break;}
+case 75:
+#line 581 "./f-exp.y"
+{ yyval.tval = builtin_type_f_complex_s16;;
+ break;}
+case 76:
+#line 583 "./f-exp.y"
+{ yyval.tval = builtin_type_f_complex_s32;;
+ break;}
+case 78:
+#line 591 "./f-exp.y"
+{ yyval.tvec = (struct type **) xmalloc (sizeof (struct type *) * 2);
+ yyval.ivec[0] = 1; /* Number of types in vector */
+ yyval.tvec[1] = yyvsp[0].tval;
+ ;
+ break;}
+case 79:
+#line 596 "./f-exp.y"
+{ int len = sizeof (struct type *) * (++(yyvsp[-2].ivec[0]) + 1);
+ yyval.tvec = (struct type **) xrealloc ((char *) yyvsp[-2].tvec, len);
+ yyval.tvec[yyval.ivec[0]] = yyvsp[0].tval;
+ ;
+ break;}
+case 80:
+#line 603 "./f-exp.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+case 81:
+#line 605 "./f-exp.y"
+{ yyval.sval = yyvsp[0].tsym.stoken; ;
+ break;}
+case 82:
+#line 607 "./f-exp.y"
+{ yyval.sval = yyvsp[0].ssym.stoken; ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 487 "/usr/unsupported/share/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) xmalloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+}
+#line 620 "./f-exp.y"
+
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ register int i;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+ int long_p = 0;
+ unsigned LONGEST high_bit;
+ struct type *signed_type;
+ struct type *unsigned_type;
+
+ if (parsed_float)
+ {
+ /* It's a float since it contains a point or an exponent. */
+ /* [dD] is not understood as an exponent by atof, change it to 'e'. */
+ char *tmp, *tmp2;
+
+ tmp = strsave (p);
+ for (tmp2 = tmp; *tmp2; ++tmp2)
+ if (*tmp2 == 'd' || *tmp2 == 'D')
+ *tmp2 = 'e';
+ putithere->dval = atof (tmp);
+ free (tmp);
+ return FLOAT;
+ }
+
+ /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+ if (p[0] == '0')
+ switch (p[1])
+ {
+ case 'x':
+ case 'X':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ case 'd':
+ case 'D':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 10;
+ len -= 2;
+ }
+ break;
+
+ default:
+ base = 8;
+ break;
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ n += i = c - '0';
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ n += i = c - 'a' + 10;
+ else if (len == 0 && c == 'l')
+ long_p = 1;
+ else if (len == 0 && c == 'u')
+ unsigned_p = 1;
+ else
+ return ERROR; /* Char not a digit */
+ }
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+
+ /* Portably test for overflow (only works for nonzero values, so make
+ a second check for zero). */
+ if ((prevn >= n) && n != 0)
+ unsigned_p=1; /* Try something unsigned */
+ /* If range checking enabled, portably test for unsigned overflow. */
+ if (RANGE_CHECK && n != 0)
+ {
+ if ((unsigned_p && (unsigned)prevn >= (unsigned)n))
+ range_error("Overflow on numeric constant.");
+ }
+ prevn = n;
+ }
+
+ /* If the number is too big to be an int, or it's got an l suffix
+ then it's a long. Work out if this has to be a long by
+ shifting right and and seeing if anything remains, and the
+ target int size is different to the target long size.
+
+ In the expression below, we could have tested
+ (n >> TARGET_INT_BIT)
+ to see if it was zero,
+ but too many compilers warn about that, when ints and longs
+ are the same size. So we shift it twice, with fewer bits
+ each time, for the same result. */
+
+ if ((TARGET_INT_BIT != TARGET_LONG_BIT
+ && ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */
+ || long_p)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+
+ putithere->typed_val.val = n;
+
+ /* If the high bit of the worked out type is set then this number
+ has to be unsigned. */
+
+ if (unsigned_p || (n & high_bit))
+ putithere->typed_val.type = unsigned_type;
+ else
+ putithere->typed_val.type = signed_type;
+
+ return INT;
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static const struct token dot_ops[] =
+{
+ { ".and.", BOOL_AND, BINOP_END },
+ { ".AND.", BOOL_AND, BINOP_END },
+ { ".or.", BOOL_OR, BINOP_END },
+ { ".OR.", BOOL_OR, BINOP_END },
+ { ".not.", BOOL_NOT, BINOP_END },
+ { ".NOT.", BOOL_NOT, BINOP_END },
+ { ".eq.", EQUAL, BINOP_END },
+ { ".EQ.", EQUAL, BINOP_END },
+ { ".eqv.", EQUAL, BINOP_END },
+ { ".NEQV.", NOTEQUAL, BINOP_END },
+ { ".neqv.", NOTEQUAL, BINOP_END },
+ { ".EQV.", EQUAL, BINOP_END },
+ { ".ne.", NOTEQUAL, BINOP_END },
+ { ".NE.", NOTEQUAL, BINOP_END },
+ { ".le.", LEQ, BINOP_END },
+ { ".LE.", LEQ, BINOP_END },
+ { ".ge.", GEQ, BINOP_END },
+ { ".GE.", GEQ, BINOP_END },
+ { ".gt.", GREATERTHAN, BINOP_END },
+ { ".GT.", GREATERTHAN, BINOP_END },
+ { ".lt.", LESSTHAN, BINOP_END },
+ { ".LT.", LESSTHAN, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+struct f77_boolean_val
+{
+ char *name;
+ int value;
+};
+
+static const struct f77_boolean_val boolean_values[] =
+{
+ { ".true.", 1 },
+ { ".TRUE.", 1 },
+ { ".false.", 0 },
+ { ".FALSE.", 0 },
+ { NULL, 0 }
+};
+
+static const struct token f77_keywords[] =
+{
+ { "complex_16", COMPLEX_S16_KEYWORD, BINOP_END },
+ { "complex_32", COMPLEX_S32_KEYWORD, BINOP_END },
+ { "character", CHARACTER, BINOP_END },
+ { "integer_2", INT_S2_KEYWORD, BINOP_END },
+ { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END },
+ { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END },
+ { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "integer", INT_KEYWORD, BINOP_END },
+ { "logical", LOGICAL_KEYWORD, BINOP_END },
+ { "real_16", REAL_S16_KEYWORD, BINOP_END },
+ { "complex", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "sizeof", SIZEOF, BINOP_END },
+ { "real_8", REAL_S8_KEYWORD, BINOP_END },
+ { "real", REAL_KEYWORD, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. Ripped off from ch-exp.y */
+
+static char *tempbuf; /* Current buffer contents */
+static int tempbufsize; /* Size of allocated buffer */
+static int tempbufindex; /* Current index into buffer */
+
+#define GROWBY_MIN_SIZE 64 /* Minimum amount to grow buffer by */
+
+#define CHECKBUF(size) \
+ do { \
+ if (tempbufindex + (size) >= tempbufsize) \
+ { \
+ growbuf_by_size (size); \
+ } \
+ } while (0);
+
+
+/* Grow the static temp buffer if necessary, including allocating the first one
+ on demand. */
+
+static void
+growbuf_by_size (count)
+ int count;
+{
+ int growby;
+
+ growby = max (count, GROWBY_MIN_SIZE);
+ tempbufsize += growby;
+ if (tempbuf == NULL)
+ tempbuf = (char *) xmalloc (tempbufsize);
+ else
+ tempbuf = (char *) xrealloc (tempbuf, tempbufsize);
+}
+
+/* Blatantly ripped off from ch-exp.y. This routine recognizes F77
+ string-literals.
+
+ Recognize a string literal. A string literal is a nonzero sequence
+ of characters enclosed in matching single quotes, except that
+ a single character inside single quotes is a character literal, which
+ we reject as a string literal. To embed the terminator character inside
+ a string, it is simply doubled (I.E. 'this''is''one''string') */
+
+static int
+match_string_literal ()
+{
+ char *tokptr = lexptr;
+
+ for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+ {
+ CHECKBUF (1);
+ if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ tokptr++;
+ else
+ break;
+ }
+ tempbuf[tempbufindex++] = *tokptr;
+ }
+ if (*tokptr == '\0' /* no terminator */
+ || tempbufindex == 0) /* no string */
+ return 0;
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return STRING_LITERAL;
+ }
+}
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ int c;
+ int namelen;
+ unsigned int i,token;
+ char *tokstart;
+
+ retry:
+
+ tokstart = lexptr;
+
+ /* First of all, let us make sure we are not dealing with the
+ special tokens .true. and .false. which evaluate to 1 and 0. */
+
+ if (*lexptr == '.')
+ {
+ for (i = 0; boolean_values[i].name != NULL; i++)
+ {
+ if STREQN (tokstart, boolean_values[i].name,
+ strlen (boolean_values[i].name))
+ {
+ lexptr += strlen (boolean_values[i].name);
+ yylval.lval = boolean_values[i].value;
+ return BOOLEAN_LITERAL;
+ }
+ }
+ }
+
+ /* See if it is a special .foo. operator */
+
+ for (i = 0; dot_ops[i].operator != NULL; i++)
+ if (STREQN (tokstart, dot_ops[i].operator, strlen (dot_ops[i].operator)))
+ {
+ lexptr += strlen (dot_ops[i].operator);
+ yylval.opcode = dot_ops[i].opcode;
+ return dot_ops[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ token = match_string_literal ();
+ if (token != 0)
+ return (token);
+ break;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] < '0' || lexptr[1] > '9')
+ goto symbol; /* Nope, must be a symbol. */
+ /* FALL THRU into number case. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0, got_d = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!hex && !got_d && (*p == 'd' || *p == 'D'))
+ got_dot = got_d = 1;
+ else if (!hex && !got_dot && *p == '.')
+ got_dot = 1;
+ else if (((got_e && (p[-1] == 'e' || p[-1] == 'E'))
+ || (got_d && (p[-1] == 'd' || p[-1] == 'D')))
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ /* We will take any letters or digits. parse_number will
+ complain if past the radix, or if L or U are not final. */
+ else if ((*p < '0' || *p > '9')
+ && ((*p < 'a' || *p > 'z')
+ && (*p < 'A' || *p > 'Z')))
+ break;
+ }
+ toktype = parse_number (tokstart, p - tokstart, got_dot|got_e|got_d,
+ &yylval);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ symbol:
+ lexptr++;
+ return c;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen]);
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ return 0;
+
+ lexptr += namelen;
+
+ /* Catch specific keywords. */
+
+ for (i = 0; f77_keywords[i].operator != NULL; i++)
+ if (STREQN(tokstart, f77_keywords[i].operator,
+ strlen(f77_keywords[i].operator)))
+ {
+ /* lexptr += strlen(f77_keywords[i].operator); */
+ yylval.opcode = f77_keywords[i].opcode;
+ return f77_keywords[i].token;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return VARIABLE;
+ }
+
+ /* Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+ int is_a_field_of_this = 0;
+ int hextype;
+
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE,
+ current_language->la_language == language_cplus
+ ? &is_a_field_of_this : NULL,
+ NULL);
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym
+ && ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10)
+ || (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/contrib/gdb/gdb/f-exp.y b/contrib/gdb/gdb/f-exp.y
new file mode 100644
index 0000000..528d215
--- /dev/null
+++ b/contrib/gdb/gdb/f-exp.y
@@ -0,0 +1,1170 @@
+/* YACC parser for Fortran expressions, for GDB.
+ Copyright 1986, 1989, 1990, 1991, 1993, 1994
+ Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C parser by Farooq Butt
+ (fmbutt@engage.sps.mot.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This was blantantly ripped off the C expression parser, please
+ be aware of that as you look at its basic structure -FMB */
+
+/* Parse a F77 expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result.
+
+ Note that malloc's and realloc's in this file are transformed to
+ xmalloc and xrealloc respectively by the same sed command in the
+ makefile that remaps any other malloc/realloc inserted by the parser
+ generator. Doing this with #defines and trying to control the interaction
+ with include files (<malloc.h> and <stdlib.h> for example) just became
+ too messy, particularly when such includes can be inserted at random
+ times by the parser generator. */
+
+%{
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "f-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth f_maxdepth
+#define yyparse f_parse
+#define yylex f_lex
+#define yyerror f_error
+#define yylval f_lval
+#define yychar f_char
+#define yydebug f_debug
+#define yypact f_pact
+#define yyr1 f_r1
+#define yyr2 f_r2
+#define yydef f_def
+#define yychk f_chk
+#define yypgo f_pgo
+#define yyact f_act
+#define yyexca f_exca
+#define yyerrflag f_errflag
+#define yynerrs f_nerrs
+#define yyps f_ps
+#define yypv f_pv
+#define yys f_s
+#define yy_yys f_yys
+#define yystate f_state
+#define yytmp f_tmp
+#define yyv f_v
+#define yy_yyv f_yyv
+#define yyval f_val
+#define yylloc f_lloc
+#define yyreds f_reds /* With YYDEBUG defined */
+#define yytoks f_toks /* With YYDEBUG defined */
+#define yylhs f_yylhs
+#define yylen f_yylen
+#define yydefred f_yydefred
+#define yydgoto f_yydgoto
+#define yysindex f_yysindex
+#define yyrindex f_yyrindex
+#define yygindex f_yygindex
+#define yytable f_yytable
+#define yycheck f_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 1 /* Default to no yydebug support */
+#endif
+
+int yyparse PARAMS ((void));
+
+static int yylex PARAMS ((void));
+
+void yyerror PARAMS ((char *));
+
+%}
+
+/* Although the yacc "value" of an expression is not used,
+ since the result is stored in the structure being created,
+ other node types do have values. */
+
+%union
+ {
+ LONGEST lval;
+ struct {
+ LONGEST val;
+ struct type *type;
+ } typed_val;
+ DOUBLEST dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ struct ttype tsym;
+ struct symtoken ssym;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ }
+
+%{
+/* YYSTYPE gets defined by %union */
+static int parse_number PARAMS ((char *, int, int, YYSTYPE *));
+%}
+
+%type <voidval> exp type_exp start variable
+%type <tval> type typebase
+%type <tvec> nonempty_typelist
+/* %type <bval> block */
+
+/* Fancy type parsing. */
+%type <voidval> func_mod direct_abs_decl abs_decl
+%type <tval> ptype
+
+%token <typed_val> INT
+%token <dval> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+ and both convey their data as strings.
+ But a TYPENAME is a string that happens to be defined as a typedef
+ or builtin type name (such as int or char)
+ and a NAME is any other symbol.
+ Contexts where this distinction is not important can use the
+ nonterminal "name", which matches either NAME or TYPENAME. */
+
+%token <sval> STRING_LITERAL
+%token <lval> BOOLEAN_LITERAL
+%token <ssym> NAME
+%token <tsym> TYPENAME
+%type <sval> name
+%type <ssym> name_not_typename
+%type <tsym> typename
+
+/* A NAME_OR_INT is a symbol which is not known in the symbol table,
+ but which would parse as a valid number in the current input radix.
+ E.g. "c" when input_radix==16. Depending on the parse, it will be
+ turned into a name or into a number. */
+
+%token <ssym> NAME_OR_INT
+
+%token SIZEOF
+%token ERROR
+
+/* Special type cases, put in to allow the parser to distinguish different
+ legal basetypes. */
+%token INT_KEYWORD INT_S2_KEYWORD LOGICAL_S1_KEYWORD LOGICAL_S2_KEYWORD
+%token LOGICAL_KEYWORD REAL_KEYWORD REAL_S8_KEYWORD REAL_S16_KEYWORD
+%token COMPLEX_S8_KEYWORD COMPLEX_S16_KEYWORD COMPLEX_S32_KEYWORD
+%token BOOL_AND BOOL_OR BOOL_NOT
+%token <lval> CHARACTER
+
+%token <voidval> VARIABLE
+
+%token <opcode> ASSIGN_MODIFY
+
+%left ','
+%left ABOVE_COMMA
+%right '=' ASSIGN_MODIFY
+%right '?'
+%left BOOL_OR
+%right BOOL_NOT
+%left BOOL_AND
+%left '|'
+%left '^'
+%left '&'
+%left EQUAL NOTEQUAL
+%left LESSTHAN GREATERTHAN LEQ GEQ
+%left LSH RSH
+%left '@'
+%left '+' '-'
+%left '*' '/' '%'
+%right UNARY
+%right '('
+
+
+%%
+
+start : exp
+ | type_exp
+ ;
+
+type_exp: type
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE); }
+ ;
+
+exp : '(' exp ')'
+ { }
+ ;
+
+/* Expressions, not including the comma operator. */
+exp : '*' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_IND); }
+
+exp : '&' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_ADDR); }
+
+exp : '-' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_NEG); }
+ ;
+
+exp : BOOL_NOT exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+ ;
+
+exp : '~' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_COMPLEMENT); }
+ ;
+
+exp : SIZEOF exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+/* No more explicit array operators, we treat everything in F77 as
+ a function call. The disambiguation as to whether we are
+ doing a subscript operation or a function call is done
+ later in eval.c. */
+
+exp : exp '('
+ { start_arglist (); }
+ arglist ')'
+ { write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_F77_UNDETERMINED_ARGLIST); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : substring
+ { arglist_len = 2;}
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+substring: exp ':' exp %prec ABOVE_COMMA
+ { }
+ ;
+
+
+complexnum: exp ',' exp
+ { }
+ ;
+
+exp : '(' complexnum ')'
+ { write_exp_elt_opcode(OP_COMPLEX); }
+ ;
+
+exp : '(' type ')' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+/* Binary operators in order of decreasing precedence. */
+
+exp : exp '@' exp
+ { write_exp_elt_opcode (BINOP_REPEAT); }
+ ;
+
+exp : exp '*' exp
+ { write_exp_elt_opcode (BINOP_MUL); }
+ ;
+
+exp : exp '/' exp
+ { write_exp_elt_opcode (BINOP_DIV); }
+ ;
+
+exp : exp '%' exp
+ { write_exp_elt_opcode (BINOP_REM); }
+ ;
+
+exp : exp '+' exp
+ { write_exp_elt_opcode (BINOP_ADD); }
+ ;
+
+exp : exp '-' exp
+ { write_exp_elt_opcode (BINOP_SUB); }
+ ;
+
+exp : exp LSH exp
+ { write_exp_elt_opcode (BINOP_LSH); }
+ ;
+
+exp : exp RSH exp
+ { write_exp_elt_opcode (BINOP_RSH); }
+ ;
+
+exp : exp EQUAL exp
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+ ;
+
+exp : exp NOTEQUAL exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ ;
+
+exp : exp LEQ exp
+ { write_exp_elt_opcode (BINOP_LEQ); }
+ ;
+
+exp : exp GEQ exp
+ { write_exp_elt_opcode (BINOP_GEQ); }
+ ;
+
+exp : exp LESSTHAN exp
+ { write_exp_elt_opcode (BINOP_LESS); }
+ ;
+
+exp : exp GREATERTHAN exp
+ { write_exp_elt_opcode (BINOP_GTR); }
+ ;
+
+exp : exp '&' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+ ;
+
+exp : exp '^' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+ ;
+
+exp : exp '|' exp
+ { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+ ;
+
+exp : exp BOOL_AND exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+ ;
+
+
+exp : exp BOOL_OR exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+ ;
+
+exp : exp '=' exp
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+ ;
+
+exp : exp ASSIGN_MODIFY exp
+ { write_exp_elt_opcode (BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode ($2);
+ write_exp_elt_opcode (BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : INT
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type ($1.type);
+ write_exp_elt_longcst ((LONGEST)($1.val));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : NAME_OR_INT
+ { YYSTYPE val;
+ parse_number ($1.stoken.ptr, $1.stoken.length, 0, &val);
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (val.typed_val.type);
+ write_exp_elt_longcst ((LONGEST)val.typed_val.val);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : FLOAT
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_f_real_s8);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : VARIABLE
+ ;
+
+exp : SIZEOF '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_f_integer);
+ CHECK_TYPEDEF ($3);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : BOOLEAN_LITERAL
+ { write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL);
+ }
+ ;
+
+exp : STRING_LITERAL
+ {
+ write_exp_elt_opcode (OP_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_STRING);
+ }
+ ;
+
+variable: name_not_typename
+ { struct symbol *sym = $1.sym;
+
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ break;
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name ($1.stoken);
+
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1.stoken));
+ }
+ }
+ ;
+
+
+type : ptype
+ ;
+
+ptype : typebase
+ | typebase abs_decl
+ {
+ /* This is where the interesting stuff happens. */
+ int done = 0;
+ int array_size;
+ struct type *follow_type = $1;
+ struct type *range_type;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = pop_type_int ();
+ if (array_size != -1)
+ {
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_f_integer, 0,
+ array_size - 1);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ }
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ $$ = follow_type;
+ }
+ ;
+
+abs_decl: '*'
+ { push_type (tp_pointer); $$ = 0; }
+ | '*' abs_decl
+ { push_type (tp_pointer); $$ = $2; }
+ | '&'
+ { push_type (tp_reference); $$ = 0; }
+ | '&' abs_decl
+ { push_type (tp_reference); $$ = $2; }
+ | direct_abs_decl
+ ;
+
+direct_abs_decl: '(' abs_decl ')'
+ { $$ = $2; }
+ | direct_abs_decl func_mod
+ { push_type (tp_function); }
+ | func_mod
+ { push_type (tp_function); }
+ ;
+
+func_mod: '(' ')'
+ { $$ = 0; }
+ | '(' nonempty_typelist ')'
+ { free ((PTR)$2); $$ = 0; }
+ ;
+
+typebase /* Implements (approximately): (type-qualifier)* type-specifier */
+ : TYPENAME
+ { $$ = $1.type; }
+ | INT_KEYWORD
+ { $$ = builtin_type_f_integer; }
+ | INT_S2_KEYWORD
+ { $$ = builtin_type_f_integer_s2; }
+ | CHARACTER
+ { $$ = builtin_type_f_character; }
+ | LOGICAL_KEYWORD
+ { $$ = builtin_type_f_logical;}
+ | LOGICAL_S2_KEYWORD
+ { $$ = builtin_type_f_logical_s2;}
+ | LOGICAL_S1_KEYWORD
+ { $$ = builtin_type_f_logical_s1;}
+ | REAL_KEYWORD
+ { $$ = builtin_type_f_real;}
+ | REAL_S8_KEYWORD
+ { $$ = builtin_type_f_real_s8;}
+ | REAL_S16_KEYWORD
+ { $$ = builtin_type_f_real_s16;}
+ | COMPLEX_S8_KEYWORD
+ { $$ = builtin_type_f_complex_s8;}
+ | COMPLEX_S16_KEYWORD
+ { $$ = builtin_type_f_complex_s16;}
+ | COMPLEX_S32_KEYWORD
+ { $$ = builtin_type_f_complex_s32;}
+ ;
+
+typename: TYPENAME
+ ;
+
+nonempty_typelist
+ : type
+ { $$ = (struct type **) malloc (sizeof (struct type *) * 2);
+ $<ivec>$[0] = 1; /* Number of types in vector */
+ $$[1] = $1;
+ }
+ | nonempty_typelist ',' type
+ { int len = sizeof (struct type *) * (++($<ivec>1[0]) + 1);
+ $$ = (struct type **) realloc ((char *) $1, len);
+ $$[$<ivec>$[0]] = $3;
+ }
+ ;
+
+name : NAME
+ { $$ = $1.stoken; }
+ | TYPENAME
+ { $$ = $1.stoken; }
+ | NAME_OR_INT
+ { $$ = $1.stoken; }
+ ;
+
+name_not_typename : NAME
+/* These would be useful if name_not_typename was useful, but it is just
+ a fake for "variable", so these cause reduce/reduce conflicts because
+ the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable,
+ =exp) or just an exp. If name_not_typename was ever used in an lvalue
+ context where only a name could occur, this might be useful.
+ | NAME_OR_INT
+ */
+ ;
+
+%%
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (p, len, parsed_float, putithere)
+ register char *p;
+ register int len;
+ int parsed_float;
+ YYSTYPE *putithere;
+{
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ register int i;
+ register int c;
+ register int base = input_radix;
+ int unsigned_p = 0;
+ int long_p = 0;
+ unsigned LONGEST high_bit;
+ struct type *signed_type;
+ struct type *unsigned_type;
+
+ if (parsed_float)
+ {
+ /* It's a float since it contains a point or an exponent. */
+ /* [dD] is not understood as an exponent by atof, change it to 'e'. */
+ char *tmp, *tmp2;
+
+ tmp = strsave (p);
+ for (tmp2 = tmp; *tmp2; ++tmp2)
+ if (*tmp2 == 'd' || *tmp2 == 'D')
+ *tmp2 = 'e';
+ putithere->dval = atof (tmp);
+ free (tmp);
+ return FLOAT;
+ }
+
+ /* Handle base-switching prefixes 0x, 0t, 0d, 0 */
+ if (p[0] == '0')
+ switch (p[1])
+ {
+ case 'x':
+ case 'X':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 16;
+ len -= 2;
+ }
+ break;
+
+ case 't':
+ case 'T':
+ case 'd':
+ case 'D':
+ if (len >= 3)
+ {
+ p += 2;
+ base = 10;
+ len -= 2;
+ }
+ break;
+
+ default:
+ base = 8;
+ break;
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ if (c >= 'A' && c <= 'Z')
+ c += 'a' - 'A';
+ if (c != 'l' && c != 'u')
+ n *= base;
+ if (c >= '0' && c <= '9')
+ n += i = c - '0';
+ else
+ {
+ if (base > 10 && c >= 'a' && c <= 'f')
+ n += i = c - 'a' + 10;
+ else if (len == 0 && c == 'l')
+ long_p = 1;
+ else if (len == 0 && c == 'u')
+ unsigned_p = 1;
+ else
+ return ERROR; /* Char not a digit */
+ }
+ if (i >= base)
+ return ERROR; /* Invalid digit in this base */
+
+ /* Portably test for overflow (only works for nonzero values, so make
+ a second check for zero). */
+ if ((prevn >= n) && n != 0)
+ unsigned_p=1; /* Try something unsigned */
+ /* If range checking enabled, portably test for unsigned overflow. */
+ if (RANGE_CHECK && n != 0)
+ {
+ if ((unsigned_p && (unsigned)prevn >= (unsigned)n))
+ range_error("Overflow on numeric constant.");
+ }
+ prevn = n;
+ }
+
+ /* If the number is too big to be an int, or it's got an l suffix
+ then it's a long. Work out if this has to be a long by
+ shifting right and and seeing if anything remains, and the
+ target int size is different to the target long size.
+
+ In the expression below, we could have tested
+ (n >> TARGET_INT_BIT)
+ to see if it was zero,
+ but too many compilers warn about that, when ints and longs
+ are the same size. So we shift it twice, with fewer bits
+ each time, for the same result. */
+
+ if ((TARGET_INT_BIT != TARGET_LONG_BIT
+ && ((n >> 2) >> (TARGET_INT_BIT-2))) /* Avoid shift warning */
+ || long_p)
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_LONG_BIT-1);
+ unsigned_type = builtin_type_unsigned_long;
+ signed_type = builtin_type_long;
+ }
+ else
+ {
+ high_bit = ((unsigned LONGEST)1) << (TARGET_INT_BIT-1);
+ unsigned_type = builtin_type_unsigned_int;
+ signed_type = builtin_type_int;
+ }
+
+ putithere->typed_val.val = n;
+
+ /* If the high bit of the worked out type is set then this number
+ has to be unsigned. */
+
+ if (unsigned_p || (n & high_bit))
+ putithere->typed_val.type = unsigned_type;
+ else
+ putithere->typed_val.type = signed_type;
+
+ return INT;
+}
+
+struct token
+{
+ char *operator;
+ int token;
+ enum exp_opcode opcode;
+};
+
+static const struct token dot_ops[] =
+{
+ { ".and.", BOOL_AND, BINOP_END },
+ { ".AND.", BOOL_AND, BINOP_END },
+ { ".or.", BOOL_OR, BINOP_END },
+ { ".OR.", BOOL_OR, BINOP_END },
+ { ".not.", BOOL_NOT, BINOP_END },
+ { ".NOT.", BOOL_NOT, BINOP_END },
+ { ".eq.", EQUAL, BINOP_END },
+ { ".EQ.", EQUAL, BINOP_END },
+ { ".eqv.", EQUAL, BINOP_END },
+ { ".NEQV.", NOTEQUAL, BINOP_END },
+ { ".neqv.", NOTEQUAL, BINOP_END },
+ { ".EQV.", EQUAL, BINOP_END },
+ { ".ne.", NOTEQUAL, BINOP_END },
+ { ".NE.", NOTEQUAL, BINOP_END },
+ { ".le.", LEQ, BINOP_END },
+ { ".LE.", LEQ, BINOP_END },
+ { ".ge.", GEQ, BINOP_END },
+ { ".GE.", GEQ, BINOP_END },
+ { ".gt.", GREATERTHAN, BINOP_END },
+ { ".GT.", GREATERTHAN, BINOP_END },
+ { ".lt.", LESSTHAN, BINOP_END },
+ { ".LT.", LESSTHAN, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+struct f77_boolean_val
+{
+ char *name;
+ int value;
+};
+
+static const struct f77_boolean_val boolean_values[] =
+{
+ { ".true.", 1 },
+ { ".TRUE.", 1 },
+ { ".false.", 0 },
+ { ".FALSE.", 0 },
+ { NULL, 0 }
+};
+
+static const struct token f77_keywords[] =
+{
+ { "complex_16", COMPLEX_S16_KEYWORD, BINOP_END },
+ { "complex_32", COMPLEX_S32_KEYWORD, BINOP_END },
+ { "character", CHARACTER, BINOP_END },
+ { "integer_2", INT_S2_KEYWORD, BINOP_END },
+ { "logical_1", LOGICAL_S1_KEYWORD, BINOP_END },
+ { "logical_2", LOGICAL_S2_KEYWORD, BINOP_END },
+ { "complex_8", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "integer", INT_KEYWORD, BINOP_END },
+ { "logical", LOGICAL_KEYWORD, BINOP_END },
+ { "real_16", REAL_S16_KEYWORD, BINOP_END },
+ { "complex", COMPLEX_S8_KEYWORD, BINOP_END },
+ { "sizeof", SIZEOF, BINOP_END },
+ { "real_8", REAL_S8_KEYWORD, BINOP_END },
+ { "real", REAL_KEYWORD, BINOP_END },
+ { NULL, 0, 0 }
+};
+
+/* Implementation of a dynamically expandable buffer for processing input
+ characters acquired through lexptr and building a value to return in
+ yylval. Ripped off from ch-exp.y */
+
+static char *tempbuf; /* Current buffer contents */
+static int tempbufsize; /* Size of allocated buffer */
+static int tempbufindex; /* Current index into buffer */
+
+#define GROWBY_MIN_SIZE 64 /* Minimum amount to grow buffer by */
+
+#define CHECKBUF(size) \
+ do { \
+ if (tempbufindex + (size) >= tempbufsize) \
+ { \
+ growbuf_by_size (size); \
+ } \
+ } while (0);
+
+
+/* Grow the static temp buffer if necessary, including allocating the first one
+ on demand. */
+
+static void
+growbuf_by_size (count)
+ int count;
+{
+ int growby;
+
+ growby = max (count, GROWBY_MIN_SIZE);
+ tempbufsize += growby;
+ if (tempbuf == NULL)
+ tempbuf = (char *) malloc (tempbufsize);
+ else
+ tempbuf = (char *) realloc (tempbuf, tempbufsize);
+}
+
+/* Blatantly ripped off from ch-exp.y. This routine recognizes F77
+ string-literals.
+
+ Recognize a string literal. A string literal is a nonzero sequence
+ of characters enclosed in matching single quotes, except that
+ a single character inside single quotes is a character literal, which
+ we reject as a string literal. To embed the terminator character inside
+ a string, it is simply doubled (I.E. 'this''is''one''string') */
+
+static int
+match_string_literal ()
+{
+ char *tokptr = lexptr;
+
+ for (tempbufindex = 0, tokptr++; *tokptr != '\0'; tokptr++)
+ {
+ CHECKBUF (1);
+ if (*tokptr == *lexptr)
+ {
+ if (*(tokptr + 1) == *lexptr)
+ tokptr++;
+ else
+ break;
+ }
+ tempbuf[tempbufindex++] = *tokptr;
+ }
+ if (*tokptr == '\0' /* no terminator */
+ || tempbufindex == 0) /* no string */
+ return 0;
+ else
+ {
+ tempbuf[tempbufindex] = '\0';
+ yylval.sval.ptr = tempbuf;
+ yylval.sval.length = tempbufindex;
+ lexptr = ++tokptr;
+ return STRING_LITERAL;
+ }
+}
+
+/* Read one token, getting characters through lexptr. */
+
+static int
+yylex ()
+{
+ int c;
+ int namelen;
+ unsigned int i,token;
+ char *tokstart;
+
+ retry:
+
+ tokstart = lexptr;
+
+ /* First of all, let us make sure we are not dealing with the
+ special tokens .true. and .false. which evaluate to 1 and 0. */
+
+ if (*lexptr == '.')
+ {
+ for (i = 0; boolean_values[i].name != NULL; i++)
+ {
+ if STREQN (tokstart, boolean_values[i].name,
+ strlen (boolean_values[i].name))
+ {
+ lexptr += strlen (boolean_values[i].name);
+ yylval.lval = boolean_values[i].value;
+ return BOOLEAN_LITERAL;
+ }
+ }
+ }
+
+ /* See if it is a special .foo. operator */
+
+ for (i = 0; dot_ops[i].operator != NULL; i++)
+ if (STREQN (tokstart, dot_ops[i].operator, strlen (dot_ops[i].operator)))
+ {
+ lexptr += strlen (dot_ops[i].operator);
+ yylval.opcode = dot_ops[i].opcode;
+ return dot_ops[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '\'':
+ token = match_string_literal ();
+ if (token != 0)
+ return (token);
+ break;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] < '0' || lexptr[1] > '9')
+ goto symbol; /* Nope, must be a symbol. */
+ /* FALL THRU into number case. */
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0, got_d = 0, toktype;
+ register char *p = tokstart;
+ int hex = input_radix > 10;
+
+ if (c == '0' && (p[1] == 'x' || p[1] == 'X'))
+ {
+ p += 2;
+ hex = 1;
+ }
+ else if (c == '0' && (p[1]=='t' || p[1]=='T' || p[1]=='d' || p[1]=='D'))
+ {
+ p += 2;
+ hex = 0;
+ }
+
+ for (;; ++p)
+ {
+ if (!hex && !got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!hex && !got_d && (*p == 'd' || *p == 'D'))
+ got_dot = got_d = 1;
+ else if (!hex && !got_dot && *p == '.')
+ got_dot = 1;
+ else if (((got_e && (p[-1] == 'e' || p[-1] == 'E'))
+ || (got_d && (p[-1] == 'd' || p[-1] == 'D')))
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ /* We will take any letters or digits. parse_number will
+ complain if past the radix, or if L or U are not final. */
+ else if ((*p < '0' || *p > '9')
+ && ((*p < 'a' || *p > 'z')
+ && (*p < 'A' || *p > 'Z')))
+ break;
+ }
+ toktype = parse_number (tokstart, p - tokstart, got_dot|got_e|got_d,
+ &yylval);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '|':
+ case '&':
+ case '^':
+ case '~':
+ case '!':
+ case '@':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '?':
+ case ':':
+ case '=':
+ case '{':
+ case '}':
+ symbol:
+ lexptr++;
+ return c;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen]);
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ return 0;
+
+ lexptr += namelen;
+
+ /* Catch specific keywords. */
+
+ for (i = 0; f77_keywords[i].operator != NULL; i++)
+ if (STREQN(tokstart, f77_keywords[i].operator,
+ strlen(f77_keywords[i].operator)))
+ {
+ /* lexptr += strlen(f77_keywords[i].operator); */
+ yylval.opcode = f77_keywords[i].opcode;
+ return f77_keywords[i].token;
+ }
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return VARIABLE;
+ }
+
+ /* Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+ int is_a_field_of_this = 0;
+ int hextype;
+
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE,
+ current_language->la_language == language_cplus
+ ? &is_a_field_of_this : NULL,
+ NULL);
+ if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ yylval.tsym.type = SYMBOL_TYPE (sym);
+ return TYPENAME;
+ }
+ if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0)
+ return TYPENAME;
+
+ /* Input names that aren't symbols but ARE valid hex numbers,
+ when the input radix permits them, can be names or numbers
+ depending on the parse. Note we support radixes > 16 here. */
+ if (!sym
+ && ((tokstart[0] >= 'a' && tokstart[0] < 'a' + input_radix - 10)
+ || (tokstart[0] >= 'A' && tokstart[0] < 'A' + input_radix - 10)))
+ {
+ YYSTYPE newlval; /* Its value is ignored. */
+ hextype = parse_number (tokstart, namelen, 0, &newlval);
+ if (hextype == INT)
+ {
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME_OR_INT;
+ }
+ }
+
+ /* Any other kind of symbol */
+ yylval.ssym.sym = sym;
+ yylval.ssym.is_a_field_of_this = is_a_field_of_this;
+ return NAME;
+ }
+}
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/contrib/gdb/gdb/f-lang.c b/contrib/gdb/gdb/f-lang.c
new file mode 100644
index 0000000..57a6809
--- /dev/null
+++ b/contrib/gdb/gdb/f-lang.c
@@ -0,0 +1,944 @@
+/* Fortran language support routines for GDB, the GNU debugger.
+ Copyright 1993, 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C parser by Farooq Butt
+ (fmbutt@engage.sps.mot.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "f-lang.h"
+
+/* The built-in types of F77. FIXME: integer*4 is missing, plain
+ logical is missing (builtin_type_logical is logical*4). */
+
+struct type *builtin_type_f_character;
+struct type *builtin_type_f_logical;
+struct type *builtin_type_f_logical_s1;
+struct type *builtin_type_f_logical_s2;
+struct type *builtin_type_f_integer;
+struct type *builtin_type_f_integer_s2;
+struct type *builtin_type_f_real;
+struct type *builtin_type_f_real_s8;
+struct type *builtin_type_f_real_s16;
+struct type *builtin_type_f_complex_s8;
+struct type *builtin_type_f_complex_s16;
+struct type *builtin_type_f_complex_s32;
+struct type *builtin_type_f_void;
+
+/* 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
+ characters and strings is language specific.
+ FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true F77 version. */
+
+static void
+emit_char (c, stream, quoter)
+ register int c;
+ FILE *stream;
+ int quoter;
+{
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (c == '\\' || c == quoter)
+ fputs_filtered ("\\", stream);
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\n':
+ fputs_filtered ("\\n", stream);
+ break;
+ case '\b':
+ fputs_filtered ("\\b", stream);
+ break;
+ case '\t':
+ fputs_filtered ("\\t", stream);
+ break;
+ case '\f':
+ fputs_filtered ("\\f", stream);
+ break;
+ case '\r':
+ fputs_filtered ("\\r", stream);
+ break;
+ case '\033':
+ fputs_filtered ("\\e", stream);
+ break;
+ case '\007':
+ fputs_filtered ("\\a", stream);
+ break;
+ default:
+ fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
+ break;
+ }
+ }
+}
+
+/* FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true F77version. */
+
+static void
+f_printchar (c, stream)
+ int c;
+ FILE *stream;
+{
+ fputs_filtered ("'", stream);
+ emit_char (c, stream, '\'');
+ fputs_filtered ("'", stream);
+}
+
+/* Print the character string STRING, printing at most LENGTH characters.
+ Printing stops early if the number hits print_max; repeat counts
+ are printed as appropriate. Print ellipses at the end if we
+ had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.
+ FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true F77 version. */
+
+static void
+f_printstr (stream, string, length, force_ellipses)
+ FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ register unsigned int i;
+ unsigned int things_printed = 0;
+ int in_quotes = 0;
+ int need_comma = 0;
+ extern int inspect_it;
+ extern int repeat_count_threshold;
+ extern int print_max;
+
+ if (length == 0)
+ {
+ fputs_filtered ("''", stdout);
+ return;
+ }
+
+ for (i = 0; i < length && things_printed < print_max; ++i)
+ {
+ /* Position of the character we are examining
+ to see whether it is repeated. */
+ unsigned int rep1;
+ /* Number of repetitions we have detected so far. */
+ unsigned int reps;
+
+ QUIT;
+
+ if (need_comma)
+ {
+ fputs_filtered (", ", stream);
+ need_comma = 0;
+ }
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < length && string[rep1] == string[i])
+ {
+ ++rep1;
+ ++reps;
+ }
+
+ if (reps > repeat_count_threshold)
+ {
+ if (in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\', ", stream);
+ else
+ fputs_filtered ("', ", stream);
+ in_quotes = 0;
+ }
+ f_printchar (string[i], stream);
+ fprintf_filtered (stream, " <repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += repeat_count_threshold;
+ need_comma = 1;
+ }
+ else
+ {
+ if (!in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\'", stream);
+ else
+ fputs_filtered ("'", stream);
+ in_quotes = 1;
+ }
+ emit_char (string[i], stream, '"');
+ ++things_printed;
+ }
+ }
+
+ /* Terminate the quotes if necessary. */
+ if (in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\'", stream);
+ else
+ fputs_filtered ("'", stream);
+ }
+
+ if (force_ellipses || i < length)
+ fputs_filtered ("...", stream);
+}
+
+/* FIXME: This is a copy of c_create_fundamental_type(), before
+ all the non-C types were stripped from it. Needs to be fixed
+ by an experienced F77 programmer. */
+
+static struct type *
+f_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ case FT_VOID:
+ type = init_type (TYPE_CODE_VOID,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "VOID", objfile);
+ break;
+ case FT_BOOLEAN:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "boolean", objfile);
+ break;
+ case FT_STRING:
+ type = init_type (TYPE_CODE_STRING,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "string", objfile);
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "character", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "integer*1", objfile);
+ break;
+ case FT_UNSIGNED_CHAR:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "logical*1", objfile);
+ break;
+ case FT_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "integer*2", objfile);
+ break;
+ case FT_SIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile); /* FIXME-fnf */
+ break;
+ case FT_UNSIGNED_SHORT:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "logical*2", objfile);
+ break;
+ case FT_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "integer*4", objfile);
+ break;
+ case FT_SIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "integer", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_INTEGER:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "logical*4", objfile);
+ break;
+ case FT_FIXED_DECIMAL:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "fixed decimal", objfile);
+ break;
+ case FT_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile);
+ break;
+ case FT_SIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
+ break;
+ case FT_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long long", objfile);
+ break;
+ case FT_SIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "signed long long", objfile);
+ break;
+ case FT_UNSIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
+ break;
+ case FT_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "real", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "real*8", objfile);
+ break;
+ case FT_FLOAT_DECIMAL:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "floating decimal", objfile);
+ break;
+ case FT_EXT_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "real*16", objfile);
+ break;
+ case FT_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "complex*8", objfile);
+ TYPE_TARGET_TYPE (type) = builtin_type_f_real;
+ break;
+ case FT_DBL_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "complex*16", objfile);
+ TYPE_TARGET_TYPE (type) = builtin_type_f_real_s8;
+ break;
+ case FT_EXT_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "complex*32", objfile);
+ TYPE_TARGET_TYPE (type) = builtin_type_f_real_s16;
+ break;
+ default:
+ /* FIXME: For now, if we are asked to produce a type not in this
+ language, create the equivalent of a C integer type with the
+ name "<?type?>". When all the dust settles from the type
+ reconstruction work, this should probably become an error. */
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "<?type?>", objfile);
+ warning ("internal error: no F77 fundamental type %d", typeid);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table of operators and their precedences for printing expressions. */
+
+static const struct op_print f_op_print_tab[] = {
+ { "+", BINOP_ADD, PREC_ADD, 0 },
+ { "+", UNOP_PLUS, PREC_PREFIX, 0 },
+ { "-", BINOP_SUB, PREC_ADD, 0 },
+ { "-", UNOP_NEG, PREC_PREFIX, 0 },
+ { "*", BINOP_MUL, PREC_MUL, 0 },
+ { "/", BINOP_DIV, PREC_MUL, 0 },
+ { "DIV", BINOP_INTDIV, PREC_MUL, 0 },
+ { "MOD", BINOP_REM, PREC_MUL, 0 },
+ { "=", BINOP_ASSIGN, PREC_ASSIGN, 1 },
+ { ".OR.", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0 },
+ { ".AND.", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0 },
+ { ".NOT.", UNOP_LOGICAL_NOT, PREC_PREFIX, 0 },
+ { ".EQ.", BINOP_EQUAL, PREC_EQUAL, 0 },
+ { ".NE.", BINOP_NOTEQUAL, PREC_EQUAL, 0 },
+ { ".LE.", BINOP_LEQ, PREC_ORDER, 0 },
+ { ".GE.", BINOP_GEQ, PREC_ORDER, 0 },
+ { ".GT.", BINOP_GTR, PREC_ORDER, 0 },
+ { ".LT.", BINOP_LESS, PREC_ORDER, 0 },
+ { "**", UNOP_IND, PREC_PREFIX, 0 },
+ { "@", BINOP_REPEAT, PREC_REPEAT, 0 },
+ { NULL, 0, 0, 0 }
+};
+
+struct type ** const (f_builtin_types[]) =
+{
+ &builtin_type_f_character,
+ &builtin_type_f_logical,
+ &builtin_type_f_logical_s1,
+ &builtin_type_f_logical_s2,
+ &builtin_type_f_integer,
+ &builtin_type_f_integer_s2,
+ &builtin_type_f_real,
+ &builtin_type_f_real_s8,
+ &builtin_type_f_real_s16,
+ &builtin_type_f_complex_s8,
+ &builtin_type_f_complex_s16,
+#if 0
+ &builtin_type_f_complex_s32,
+#endif
+ &builtin_type_f_void,
+ 0
+};
+
+int c_value_print();
+
+const struct language_defn f_language_defn = {
+ "fortran",
+ language_fortran,
+ f_builtin_types,
+ range_check_on,
+ type_check_on,
+ f_parse, /* parser */
+ f_error, /* parser error function */
+ evaluate_subexp_standard,
+ f_printchar, /* Print character constant */
+ f_printstr, /* function to print string constant */
+ f_create_fundamental_type, /* Create fundamental type in this language */
+ f_print_type, /* Print a type using appropriate syntax */
+ f_val_print, /* Print a value using appropriate syntax */
+ c_value_print, /* FIXME */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%o", "0", "o", ""}, /* Octal format info */
+ {"%d", "", "d", ""}, /* Decimal format info */
+ {"0x%x", "0x", "x", ""}, /* Hex format info */
+ f_op_print_tab, /* expression operators for printing */
+ 0, /* arrays are first-class (not c-style) */
+ 1, /* String lower bound */
+ &builtin_type_f_character, /* Type of string elements */
+ LANG_MAGIC
+ };
+
+void
+_initialize_f_language ()
+{
+ builtin_type_f_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "VOID", (struct objfile *) NULL);
+
+ builtin_type_f_character =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "character", (struct objfile *) NULL);
+
+ builtin_type_f_logical_s1 =
+ init_type (TYPE_CODE_BOOL, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "logical*1", (struct objfile *) NULL);
+
+ builtin_type_f_integer_s2 =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "integer*2", (struct objfile *) NULL);
+
+ builtin_type_f_logical_s2 =
+ init_type (TYPE_CODE_BOOL, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "logical*2", (struct objfile *) NULL);
+
+ builtin_type_f_integer =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "integer", (struct objfile *) NULL);
+
+ builtin_type_f_logical =
+ init_type (TYPE_CODE_BOOL, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "logical*4", (struct objfile *) NULL);
+
+ builtin_type_f_real =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "real", (struct objfile *) NULL);
+
+ builtin_type_f_real_s8 =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "real*8", (struct objfile *) NULL);
+
+ builtin_type_f_real_s16 =
+ init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "real*16", (struct objfile *) NULL);
+
+ builtin_type_f_complex_s8 =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex*8", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_f_complex_s8) = builtin_type_f_real;
+
+ builtin_type_f_complex_s16 =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex*16", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_f_complex_s16) = builtin_type_f_real_s8;
+
+ /* We have a new size == 4 double floats for the
+ complex*32 data type */
+
+ builtin_type_f_complex_s32 =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex*32", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_f_complex_s32) = builtin_type_f_real_s16;
+
+ builtin_type_string =
+ init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "character string", (struct objfile *) NULL);
+
+ add_language (&f_language_defn);
+}
+
+/* Following is dubious stuff that had been in the xcoff reader. */
+
+struct saved_fcn
+{
+ long line_offset; /* Line offset for function */
+ struct saved_fcn *next;
+};
+
+
+struct saved_bf_symnum
+{
+ long symnum_fcn; /* Symnum of function (i.e. .function directive) */
+ long symnum_bf; /* Symnum of .bf for this function */
+ struct saved_bf_symnum *next;
+};
+
+typedef struct saved_fcn SAVED_FUNCTION, *SAVED_FUNCTION_PTR;
+typedef struct saved_bf_symnum SAVED_BF, *SAVED_BF_PTR;
+
+
+SAVED_BF_PTR allocate_saved_bf_node()
+{
+ SAVED_BF_PTR new;
+
+ new = (SAVED_BF_PTR) xmalloc (sizeof (SAVED_BF));
+ return(new);
+}
+
+SAVED_FUNCTION *allocate_saved_function_node()
+{
+ SAVED_FUNCTION *new;
+
+ new = (SAVED_FUNCTION *) xmalloc (sizeof (SAVED_FUNCTION));
+ return(new);
+}
+
+SAVED_F77_COMMON_PTR allocate_saved_f77_common_node()
+{
+ SAVED_F77_COMMON_PTR new;
+
+ new = (SAVED_F77_COMMON_PTR) xmalloc (sizeof (SAVED_F77_COMMON));
+ return(new);
+}
+
+COMMON_ENTRY_PTR allocate_common_entry_node()
+{
+ COMMON_ENTRY_PTR new;
+
+ new = (COMMON_ENTRY_PTR) xmalloc (sizeof (COMMON_ENTRY));
+ return(new);
+}
+
+
+SAVED_F77_COMMON_PTR head_common_list=NULL; /* Ptr to 1st saved COMMON */
+SAVED_F77_COMMON_PTR tail_common_list=NULL; /* Ptr to last saved COMMON */
+SAVED_F77_COMMON_PTR current_common=NULL; /* Ptr to current COMMON */
+
+static SAVED_BF_PTR saved_bf_list=NULL; /* Ptr to (.bf,function)
+ list*/
+#if 0
+static SAVED_BF_PTR saved_bf_list_end=NULL; /* Ptr to above list's end */
+#endif
+static SAVED_BF_PTR current_head_bf_list=NULL; /* Current head of above list
+ */
+
+#if 0
+static SAVED_BF_PTR tmp_bf_ptr; /* Generic temporary for use
+ in macros */
+#endif
+
+/* The following function simply enters a given common block onto
+ the global common block chain */
+
+void add_common_block(name,offset,secnum,func_stab)
+ char *name;
+ CORE_ADDR offset;
+ int secnum;
+ char *func_stab;
+
+{
+ SAVED_F77_COMMON_PTR tmp;
+ char *c,*local_copy_func_stab;
+
+ /* If the COMMON block we are trying to add has a blank
+ name (i.e. "#BLNK_COM") then we set it to __BLANK
+ because the darn "#" character makes GDB's input
+ parser have fits. */
+
+
+ if (STREQ(name,BLANK_COMMON_NAME_ORIGINAL) ||
+ STREQ(name,BLANK_COMMON_NAME_MF77))
+ {
+
+ free(name);
+ name = alloca(strlen(BLANK_COMMON_NAME_LOCAL) + 1);
+ strcpy(name,BLANK_COMMON_NAME_LOCAL);
+ }
+
+ tmp = allocate_saved_f77_common_node();
+
+ local_copy_func_stab = xmalloc (strlen(func_stab) + 1);
+ strcpy(local_copy_func_stab,func_stab);
+
+ tmp->name = xmalloc(strlen(name) + 1);
+
+ /* local_copy_func_stab is a stabstring, let us first extract the
+ function name from the stab by NULLing out the ':' character. */
+
+
+ c = NULL;
+ c = strchr(local_copy_func_stab,':');
+
+ if (c)
+ *c = '\0';
+ else
+ error("Malformed function STAB found in add_common_block()");
+
+
+ tmp->owning_function = xmalloc (strlen(local_copy_func_stab) + 1);
+
+ strcpy(tmp->owning_function,local_copy_func_stab);
+
+ strcpy(tmp->name,name);
+ tmp->offset = offset;
+ tmp->next = NULL;
+ tmp->entries = NULL;
+ tmp->secnum = secnum;
+
+ current_common = tmp;
+
+ if (head_common_list == NULL)
+ {
+ head_common_list = tail_common_list = tmp;
+ }
+ else
+ {
+ tail_common_list->next = tmp;
+ tail_common_list = tmp;
+ }
+
+}
+
+
+/* The following function simply enters a given common entry onto
+ the "current_common" block that has been saved away. */
+
+void add_common_entry(entry_sym_ptr)
+ struct symbol *entry_sym_ptr;
+{
+ COMMON_ENTRY_PTR tmp;
+
+
+
+ /* The order of this list is important, since
+ we expect the entries to appear in decl.
+ order when we later issue "info common" calls */
+
+ tmp = allocate_common_entry_node();
+
+ tmp->next = NULL;
+ tmp->symbol = entry_sym_ptr;
+
+ if (current_common == NULL)
+ error("Attempt to add COMMON entry with no block open!");
+ else
+ {
+ if (current_common->entries == NULL)
+ {
+ current_common->entries = tmp;
+ current_common->end_of_entries = tmp;
+ }
+ else
+ {
+ current_common->end_of_entries->next = tmp;
+ current_common->end_of_entries = tmp;
+ }
+ }
+
+
+}
+
+/* This routine finds the first encountred COMMON block named "name" */
+
+SAVED_F77_COMMON_PTR find_first_common_named(name)
+ char *name;
+{
+
+ SAVED_F77_COMMON_PTR tmp;
+
+ tmp = head_common_list;
+
+ while (tmp != NULL)
+ {
+ if (STREQ(tmp->name,name))
+ return(tmp);
+ else
+ tmp = tmp->next;
+ }
+ return(NULL);
+}
+
+/* This routine finds the first encountred COMMON block named "name"
+ that belongs to function funcname */
+
+SAVED_F77_COMMON_PTR find_common_for_function(name, funcname)
+ char *name;
+ char *funcname;
+{
+
+ SAVED_F77_COMMON_PTR tmp;
+
+ tmp = head_common_list;
+
+ while (tmp != NULL)
+ {
+ if (STREQ(tmp->name,name) && STREQ(tmp->owning_function,funcname))
+ return(tmp);
+ else
+ tmp = tmp->next;
+ }
+ return(NULL);
+}
+
+
+
+
+/* The following function is called to patch up the offsets
+ for the statics contained in the COMMON block named
+ "name." */
+
+
+void patch_common_entries (blk, offset, secnum)
+ SAVED_F77_COMMON_PTR blk;
+ CORE_ADDR offset;
+ int secnum;
+{
+ COMMON_ENTRY_PTR entry;
+
+ blk->offset = offset; /* Keep this around for future use. */
+
+ entry = blk->entries;
+
+ while (entry != NULL)
+ {
+ SYMBOL_VALUE (entry->symbol) += offset;
+ SYMBOL_SECTION (entry->symbol) = secnum;
+
+ entry = entry->next;
+ }
+ blk->secnum = secnum;
+}
+
+
+/* Patch all commons named "name" that need patching.Since COMMON
+ blocks occur with relative infrequency, we simply do a linear scan on
+ the name. Eventually, the best way to do this will be a
+ hashed-lookup. Secnum is the section number for the .bss section
+ (which is where common data lives). */
+
+
+void patch_all_commons_by_name (name, offset, secnum)
+ char *name;
+ CORE_ADDR offset;
+ int secnum;
+{
+
+ SAVED_F77_COMMON_PTR tmp;
+
+ /* For blank common blocks, change the canonical reprsentation
+ of a blank name */
+
+ if ((STREQ(name,BLANK_COMMON_NAME_ORIGINAL)) ||
+ (STREQ(name,BLANK_COMMON_NAME_MF77)))
+ {
+ free(name);
+ name = alloca(strlen(BLANK_COMMON_NAME_LOCAL) + 1);
+ strcpy(name,BLANK_COMMON_NAME_LOCAL);
+ }
+
+ tmp = head_common_list;
+
+ while (tmp != NULL)
+ {
+ if (COMMON_NEEDS_PATCHING(tmp))
+ if (STREQ(tmp->name,name))
+ patch_common_entries(tmp,offset,secnum);
+
+ tmp = tmp->next;
+ }
+
+}
+
+
+
+
+
+/* This macro adds the symbol-number for the start of the function
+ (the symbol number of the .bf) referenced by symnum_fcn to a
+ list. This list, in reality should be a FIFO queue but since
+ #line pragmas sometimes cause line ranges to get messed up
+ we simply create a linear list. This list can then be searched
+ first by a queueing algorithm and upon failure fall back to
+ a linear scan. */
+
+#if 0
+#define ADD_BF_SYMNUM(bf_sym,fcn_sym) \
+ \
+ if (saved_bf_list == NULL) \
+{ \
+ tmp_bf_ptr = allocate_saved_bf_node(); \
+ \
+ tmp_bf_ptr->symnum_bf = (bf_sym); \
+ tmp_bf_ptr->symnum_fcn = (fcn_sym); \
+ tmp_bf_ptr->next = NULL; \
+ \
+ current_head_bf_list = saved_bf_list = tmp_bf_ptr; \
+ saved_bf_list_end = tmp_bf_ptr; \
+ } \
+else \
+{ \
+ tmp_bf_ptr = allocate_saved_bf_node(); \
+ \
+ tmp_bf_ptr->symnum_bf = (bf_sym); \
+ tmp_bf_ptr->symnum_fcn = (fcn_sym); \
+ tmp_bf_ptr->next = NULL; \
+ \
+ saved_bf_list_end->next = tmp_bf_ptr; \
+ saved_bf_list_end = tmp_bf_ptr; \
+ }
+#endif
+
+/* This function frees the entire (.bf,function) list */
+
+void
+ clear_bf_list()
+{
+
+ SAVED_BF_PTR tmp = saved_bf_list;
+ SAVED_BF_PTR next = NULL;
+
+ while (tmp != NULL)
+ {
+ next = tmp->next;
+ free(tmp);
+ tmp=next;
+ }
+ saved_bf_list = NULL;
+}
+
+int global_remote_debug;
+
+long
+get_bf_for_fcn (the_function)
+ long the_function;
+{
+ SAVED_BF_PTR tmp;
+ int nprobes = 0;
+
+ /* First use a simple queuing algorithm (i.e. look and see if the
+ item at the head of the queue is the one you want) */
+
+ if (saved_bf_list == NULL)
+ fatal ("cannot get .bf node off empty list");
+
+ if (current_head_bf_list != NULL)
+ if (current_head_bf_list->symnum_fcn == the_function)
+ {
+ if (global_remote_debug)
+ fprintf(stderr,"*");
+
+ tmp = current_head_bf_list;
+ current_head_bf_list = current_head_bf_list->next;
+ return(tmp->symnum_bf);
+ }
+
+ /* If the above did not work (probably because #line directives were
+ used in the sourcefile and they messed up our internal tables) we now do
+ the ugly linear scan */
+
+ if (global_remote_debug)
+ fprintf(stderr,"\ndefaulting to linear scan\n");
+
+ nprobes = 0;
+ tmp = saved_bf_list;
+ while (tmp != NULL)
+ {
+ nprobes++;
+ if (tmp->symnum_fcn == the_function)
+ {
+ if (global_remote_debug)
+ fprintf(stderr,"Found in %d probes\n",nprobes);
+ current_head_bf_list = tmp->next;
+ return(tmp->symnum_bf);
+ }
+ tmp= tmp->next;
+ }
+
+ return(-1);
+}
+
+static SAVED_FUNCTION_PTR saved_function_list=NULL;
+#if 0 /* Currently unused */
+static SAVED_FUNCTION_PTR saved_function_list_end=NULL;
+#endif
+
+void clear_function_list()
+{
+ SAVED_FUNCTION_PTR tmp = saved_function_list;
+ SAVED_FUNCTION_PTR next = NULL;
+
+ while (tmp != NULL)
+ {
+ next = tmp->next;
+ free(tmp);
+ tmp = next;
+ }
+
+ saved_function_list = NULL;
+}
diff --git a/contrib/gdb/gdb/f-lang.h b/contrib/gdb/gdb/f-lang.h
new file mode 100644
index 0000000..226b399
--- /dev/null
+++ b/contrib/gdb/gdb/f-lang.h
@@ -0,0 +1,94 @@
+/* Fortran language support definitions for GDB, the GNU debugger.
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C definitions by Farooq Butt
+ (fmbutt@engage.sps.mot.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern int f_parse PARAMS ((void));
+
+extern void f_error PARAMS ((char *)); /* Defined in f-exp.y */
+
+extern void f_print_type PARAMS ((struct type *, char *, FILE *, int, int));
+
+extern int f_val_print PARAMS ((struct type *, char *, CORE_ADDR, FILE *,
+ int, int, int, enum val_prettyprint));
+
+/* Language-specific data structures */
+
+struct common_entry
+{
+ struct symbol *symbol; /* The symbol node corresponding
+ to this component */
+ struct common_entry *next; /* The next component */
+};
+
+struct saved_f77_common
+{
+ char *name; /* Name of COMMON */
+ char *owning_function; /* Name of parent function */
+ int secnum; /* Section # of .bss */
+ CORE_ADDR offset; /* Offset from .bss for
+ this block */
+ struct common_entry *entries; /* List of block's components */
+ struct common_entry *end_of_entries; /* ptr. to end of components */
+ struct saved_f77_common *next; /* Next saved COMMON block */
+};
+
+typedef struct saved_f77_common SAVED_F77_COMMON, *SAVED_F77_COMMON_PTR;
+
+typedef struct common_entry COMMON_ENTRY, *COMMON_ENTRY_PTR;
+
+extern SAVED_F77_COMMON_PTR head_common_list; /* Ptr to 1st saved COMMON */
+extern SAVED_F77_COMMON_PTR tail_common_list; /* Ptr to last saved COMMON */
+extern SAVED_F77_COMMON_PTR current_common; /* Ptr to current COMMON */
+
+extern SAVED_F77_COMMON_PTR find_common_for_function PARAMS ((char *, char *));
+
+#define UNINITIALIZED_SECNUM -1
+#define COMMON_NEEDS_PATCHING(blk) ((blk)->secnum == UNINITIALIZED_SECNUM)
+
+#define BLANK_COMMON_NAME_ORIGINAL "#BLNK_COM" /* XLF assigned */
+#define BLANK_COMMON_NAME_MF77 "__BLNK__" /* MF77 assigned */
+#define BLANK_COMMON_NAME_LOCAL "__BLANK" /* Local GDB */
+
+#define BOUND_FETCH_OK 1
+#define BOUND_FETCH_ERROR -999
+
+/* When reasonable array bounds cannot be fetched, such as when
+you ask to 'mt print symbols' and there is no stack frame and
+therefore no way of knowing the bounds of stack-based arrays,
+we have to assign default bounds, these are as good as any... */
+
+#define DEFAULT_UPPER_BOUND 999999
+#define DEFAULT_LOWER_BOUND -999999
+
+extern char *real_main_name; /* Name of main function */
+extern int real_main_c_value; /* C_value field of main function */
+
+extern int f77_get_dynamic_upperbound PARAMS ((struct type *, int *));
+
+extern int f77_get_dynamic_lowerbound PARAMS ((struct type *, int *));
+
+extern void f77_get_dynamic_array_length PARAMS ((struct type *));
+
+extern int calc_f77_array_dims PARAMS ((struct type *));
+
+#define DEFAULT_DOTMAIN_NAME_IN_MF77 ".MAIN_"
+#define DEFAULT_MAIN_NAME_IN_MF77 "MAIN_"
+#define DEFAULT_DOTMAIN_NAME_IN_XLF_BUGGY ".main "
+#define DEFAULT_DOTMAIN_NAME_IN_XLF ".main"
diff --git a/contrib/gdb/gdb/f-typeprint.c b/contrib/gdb/gdb/f-typeprint.c
new file mode 100644
index 0000000..3ab6237
--- /dev/null
+++ b/contrib/gdb/gdb/f-typeprint.c
@@ -0,0 +1,454 @@
+/* Support for printing Fortran types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C version by Farooq Butt
+ (fmbutt@engage.sps.mot.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "f-lang.h"
+#include "typeprint.h"
+#include "frame.h" /* ??? */
+
+#include "gdb_string.h"
+#include <errno.h>
+
+#if 0 /* Currently unused */
+static void f_type_print_args PARAMS ((struct type *, FILE *));
+#endif
+
+static void f_type_print_varspec_suffix PARAMS ((struct type *, FILE *,
+ int, int, int));
+
+void f_type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int));
+
+void f_type_print_base PARAMS ((struct type *, FILE *, int, int));
+
+
+/* LEVEL is the depth to indent lines by. */
+
+void
+f_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ FILE *stream;
+ int show;
+ int level;
+{
+ register enum type_code code;
+ int demangled_args;
+
+ f_type_print_base (type, stream, show, level);
+ code = TYPE_CODE (type);
+ if ((varstring != NULL && *varstring != '\0')
+ ||
+ /* Need a space if going to print stars or brackets;
+ but not if we will print just a type name. */
+ ((show > 0 || TYPE_NAME (type) == 0)
+ &&
+ (code == TYPE_CODE_PTR || code == TYPE_CODE_FUNC
+ || code == TYPE_CODE_METHOD
+ || code == TYPE_CODE_ARRAY
+ || code == TYPE_CODE_MEMBER
+ || code == TYPE_CODE_REF)))
+ fputs_filtered (" ", stream);
+ f_type_print_varspec_prefix (type, stream, show, 0);
+
+ fputs_filtered (varstring, stream);
+
+ /* For demangled function names, we have the arglist as part of the name,
+ so don't print an additional pair of ()'s */
+
+ demangled_args = varstring[strlen(varstring) - 1] == ')';
+ f_type_print_varspec_suffix (type, stream, show, 0, demangled_args);
+}
+
+/* Print any asterisks or open-parentheses needed before the
+ variable name (to describe its type).
+
+ On outermost call, pass 0 for PASSED_A_PTR.
+ On outermost call, SHOW > 0 means should ignore
+ any typename for TYPE and show its details.
+ SHOW is always zero on recursive calls. */
+
+void
+f_type_print_varspec_prefix (type, stream, show, passed_a_ptr)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int passed_a_ptr;
+{
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ f_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1);
+ break;
+
+ case TYPE_CODE_FUNC:
+ f_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, "(");
+ break;
+
+ case TYPE_CODE_ARRAY:
+ f_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0);
+ break;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_REF:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* These types need no prefix. They are listed here so that
+ gcc -Wall will reveal any types that haven't been handled. */
+ break;
+ }
+}
+
+#if 0 /* Currently unused */
+
+static void
+f_type_print_args (type, stream)
+ struct type *type;
+ FILE *stream;
+{
+ int i;
+ struct type **args;
+
+ fprintf_filtered (stream, "(");
+ args = TYPE_ARG_TYPES (type);
+ if (args != NULL)
+ {
+ if (args[1] == NULL)
+ {
+ fprintf_filtered (stream, "...");
+ }
+ else
+ {
+ for (i = 1; args[i] != NULL && args[i]->code != TYPE_CODE_VOID; i++)
+ {
+ f_print_type (args[i], "", stream, -1, 0);
+ if (args[i+1] == NULL)
+ fprintf_filtered (stream, "...");
+ else if (args[i+1]->code != TYPE_CODE_VOID)
+ {
+ fprintf_filtered (stream, ",");
+ wrap_here (" ");
+ }
+ }
+ }
+ }
+ fprintf_filtered (stream, ")");
+}
+
+#endif /* 0 */
+
+/* Print any array sizes, function arguments or close parentheses
+ needed after the variable name (to describe its type).
+ Args work like c_type_print_varspec_prefix. */
+
+static void
+f_type_print_varspec_suffix (type, stream, show, passed_a_ptr, demangled_args)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int passed_a_ptr;
+ int demangled_args;
+{
+ int upper_bound, lower_bound;
+ int lower_bound_was_default = 0;
+ static int arrayprint_recurse_level = 0;
+ int retcode;
+
+ if (type == 0)
+ return;
+
+ if (TYPE_NAME (type) && show <= 0)
+ return;
+
+ QUIT;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_ARRAY:
+ arrayprint_recurse_level++;
+
+ if (arrayprint_recurse_level == 1)
+ fprintf_filtered(stream,"(");
+
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY)
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+
+ retcode = f77_get_dynamic_lowerbound (type,&lower_bound);
+
+ lower_bound_was_default = 0;
+
+ if (retcode == BOUND_FETCH_ERROR)
+ fprintf_filtered (stream,"???");
+ else
+ if (lower_bound == 1) /* The default */
+ lower_bound_was_default = 1;
+ else
+ fprintf_filtered (stream,"%d",lower_bound);
+
+ if (lower_bound_was_default)
+ lower_bound_was_default = 0;
+ else
+ fprintf_filtered(stream,":");
+
+ /* Make sure that, if we have an assumed size array, we
+ print out a warning and print the upperbound as '*' */
+
+ if (TYPE_ARRAY_UPPER_BOUND_TYPE(type) == BOUND_CANNOT_BE_DETERMINED)
+ fprintf_filtered (stream, "*");
+ else
+ {
+ retcode = f77_get_dynamic_upperbound(type,&upper_bound);
+
+ if (retcode == BOUND_FETCH_ERROR)
+ fprintf_filtered(stream,"???");
+ else
+ fprintf_filtered(stream,"%d",upper_bound);
+ }
+
+ if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_ARRAY)
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0);
+ if (arrayprint_recurse_level == 1)
+ fprintf_filtered (stream, ")");
+ else
+ fprintf_filtered(stream,",");
+ arrayprint_recurse_level--;
+ break;
+
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_REF:
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0);
+ fprintf_filtered(stream,")");
+ break;
+
+ case TYPE_CODE_FUNC:
+ f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0,
+ passed_a_ptr, 0);
+ if (passed_a_ptr)
+ fprintf_filtered (stream, ")");
+
+ fprintf_filtered (stream, "()");
+ break;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_COMPLEX:
+ case TYPE_CODE_TYPEDEF:
+ /* These types do not need a suffix. They are listed so that
+ gcc -Wall will report types that may not have been considered. */
+ break;
+ }
+}
+
+void
+print_equivalent_f77_float_type (type, stream)
+ struct type *type;
+ FILE *stream;
+{
+ /* Override type name "float" and make it the
+ appropriate real. XLC stupidly outputs -12 as a type
+ for real when it really should be outputting -18 */
+
+ fprintf_filtered (stream, "real*%d", TYPE_LENGTH (type));
+}
+
+/* Print the name of the type (or the ultimate pointer target,
+ function value or array element), or the description of a
+ structure or union.
+
+ SHOW nonzero means don't print this type as just its name;
+ show its real definition even if it has a name.
+ SHOW zero means print just typename or struct tag if there is one
+ SHOW negative means abbreviate structure elements.
+ SHOW is decremented for printing of structure elements.
+
+ LEVEL is the depth to indent by.
+ We increase it for some recursive calls. */
+
+void
+f_type_print_base (type, stream, show, level)
+ struct type *type;
+ FILE *stream;
+ int show;
+ int level;
+{
+ int retcode;
+ int upper_bound;
+
+ QUIT;
+
+ wrap_here (" ");
+ if (type == NULL)
+ {
+ fputs_filtered ("<type unknown>", stream);
+ return;
+ }
+
+ /* When SHOW is zero or less, and there is a valid type name, then always
+ just print the type name directly from the type. */
+
+ if ((show <= 0) && (TYPE_NAME (type) != NULL))
+ {
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ print_equivalent_f77_float_type (type, stream);
+ else
+ fputs_filtered (TYPE_NAME (type), stream);
+ return;
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_TYPEDEF:
+ f_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ break;
+
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_FUNC:
+ f_type_print_base (TYPE_TARGET_TYPE (type), stream, show, level);
+ break;
+
+ case TYPE_CODE_PTR:
+ fprintf_filtered (stream, "PTR TO -> ( ");
+ f_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level);
+ break;
+
+ case TYPE_CODE_VOID:
+ fprintf_filtered (stream, "VOID");
+ break;
+
+ case TYPE_CODE_UNDEF:
+ fprintf_filtered (stream, "struct <unknown>");
+ break;
+
+ case TYPE_CODE_ERROR:
+ fprintf_filtered (stream, "<unknown type>");
+ break;
+
+ case TYPE_CODE_RANGE:
+ /* This should not occur */
+ fprintf_filtered (stream, "<range type>");
+ break;
+
+ case TYPE_CODE_CHAR:
+ /* Override name "char" and make it "character" */
+ fprintf_filtered (stream, "character");
+ break;
+
+ case TYPE_CODE_INT:
+ /* There may be some character types that attempt to come
+ through as TYPE_CODE_INT since dbxstclass.h is so
+ C-oriented, we must change these to "character" from "char". */
+
+ if (STREQ (TYPE_NAME (type), "char"))
+ fprintf_filtered (stream, "character");
+ else
+ goto default_case;
+ break;
+
+ case TYPE_CODE_COMPLEX:
+ fprintf_filtered (stream, "complex*%d", TYPE_LENGTH (type));
+ break;
+
+ case TYPE_CODE_FLT:
+ print_equivalent_f77_float_type (type, stream);
+ break;
+
+ case TYPE_CODE_STRING:
+ /* Strings may have dynamic upperbounds (lengths) like arrays. */
+
+ if (TYPE_ARRAY_UPPER_BOUND_TYPE (type) == BOUND_CANNOT_BE_DETERMINED)
+ fprintf_filtered (stream, "character*(*)");
+ else
+ {
+ retcode = f77_get_dynamic_upperbound (type, &upper_bound);
+
+ if (retcode == BOUND_FETCH_ERROR)
+ fprintf_filtered (stream, "character*???");
+ else
+ fprintf_filtered (stream, "character*%d", upper_bound);
+ }
+ break;
+
+ default_case:
+ default:
+ /* Handle types not explicitly handled by the other cases,
+ such as fundamental types. For these, just print whatever
+ the type name is, as recorded in the type itself. If there
+ is no type name, then complain. */
+ if (TYPE_NAME (type) != NULL)
+ fputs_filtered (TYPE_NAME (type), stream);
+ else
+ error ("Invalid type code (%d) in symbol table.", TYPE_CODE (type));
+ break;
+ }
+}
diff --git a/contrib/gdb/gdb/f-valprint.c b/contrib/gdb/gdb/f-valprint.c
new file mode 100644
index 0000000..1143b9d
--- /dev/null
+++ b/contrib/gdb/gdb/f-valprint.c
@@ -0,0 +1,748 @@
+/* Support for printing Fortran values for GDB, the GNU debugger.
+ Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Motorola. Adapted from the C definitions by Farooq Butt
+ (fmbutt@engage.sps.mot.com), additionally worked over by Stan Shebs.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "demangle.h"
+#include "valprint.h"
+#include "language.h"
+#include "f-lang.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "command.h"
+
+extern unsigned int print_max; /* No of array elements to print */
+
+extern int calc_f77_array_dims PARAMS ((struct type *));
+
+int f77_array_offset_tbl[MAX_FORTRAN_DIMS+1][2];
+
+/* Array which holds offsets to be applied to get a row's elements
+ for a given array. Array also holds the size of each subarray. */
+
+/* The following macro gives us the size of the nth dimension, Where
+ n is 1 based. */
+
+#define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1])
+
+/* The following gives us the offset for row n where n is 1-based. */
+
+#define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0])
+
+int
+f77_get_dynamic_lowerbound (type, lower_bound)
+ struct type *type;
+ int *lower_bound;
+{
+ CORE_ADDR current_frame_addr;
+ CORE_ADDR ptr_to_lower_bound;
+
+ switch (TYPE_ARRAY_LOWER_BOUND_TYPE (type))
+ {
+ case BOUND_BY_VALUE_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ *lower_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_LOWER_BOUND_VALUE (type),
+ 4);
+ }
+ else
+ {
+ *lower_bound = DEFAULT_LOWER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_SIMPLE:
+ *lower_bound = TYPE_ARRAY_LOWER_BOUND_VALUE (type);
+ break;
+
+ case BOUND_CANNOT_BE_DETERMINED:
+ error ("Lower bound may not be '*' in F77");
+ break;
+
+ case BOUND_BY_REF_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ ptr_to_lower_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_LOWER_BOUND_VALUE (type),
+ 4);
+ *lower_bound = read_memory_integer (ptr_to_lower_bound, 4);
+ }
+ else
+ {
+ *lower_bound = DEFAULT_LOWER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_BY_REF_IN_REG:
+ case BOUND_BY_VALUE_IN_REG:
+ default:
+ error ("??? unhandled dynamic array bound type ???");
+ break;
+ }
+ return BOUND_FETCH_OK;
+}
+
+int
+f77_get_dynamic_upperbound (type, upper_bound)
+ struct type *type;
+ int *upper_bound;
+{
+ CORE_ADDR current_frame_addr = 0;
+ CORE_ADDR ptr_to_upper_bound;
+
+ switch (TYPE_ARRAY_UPPER_BOUND_TYPE (type))
+ {
+ case BOUND_BY_VALUE_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ *upper_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_UPPER_BOUND_VALUE (type),
+ 4);
+ }
+ else
+ {
+ *upper_bound = DEFAULT_UPPER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_SIMPLE:
+ *upper_bound = TYPE_ARRAY_UPPER_BOUND_VALUE (type);
+ break;
+
+ case BOUND_CANNOT_BE_DETERMINED:
+ /* we have an assumed size array on our hands. Assume that
+ upper_bound == lower_bound so that we show at least
+ 1 element.If the user wants to see more elements, let
+ him manually ask for 'em and we'll subscript the
+ array and show him */
+ f77_get_dynamic_lowerbound (type, upper_bound);
+ break;
+
+ case BOUND_BY_REF_ON_STACK:
+ current_frame_addr = selected_frame->frame;
+ if (current_frame_addr > 0)
+ {
+ ptr_to_upper_bound =
+ read_memory_integer (current_frame_addr +
+ TYPE_ARRAY_UPPER_BOUND_VALUE (type),
+ 4);
+ *upper_bound = read_memory_integer(ptr_to_upper_bound, 4);
+ }
+ else
+ {
+ *upper_bound = DEFAULT_UPPER_BOUND;
+ return BOUND_FETCH_ERROR;
+ }
+ break;
+
+ case BOUND_BY_REF_IN_REG:
+ case BOUND_BY_VALUE_IN_REG:
+ default:
+ error ("??? unhandled dynamic array bound type ???");
+ break;
+ }
+ return BOUND_FETCH_OK;
+}
+
+/* Obtain F77 adjustable array dimensions */
+
+void
+f77_get_dynamic_length_of_aggregate (type)
+ struct type *type;
+{
+ int upper_bound = -1;
+ int lower_bound = 1;
+ int retcode;
+
+ /* Recursively go all the way down into a possibly multi-dimensional
+ F77 array and get the bounds. For simple arrays, this is pretty
+ easy but when the bounds are dynamic, we must be very careful
+ to add up all the lengths correctly. Not doing this right
+ will lead to horrendous-looking arrays in parameter lists.
+
+ This function also works for strings which behave very
+ similarly to arrays. */
+
+ if (TYPE_CODE(TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY
+ || TYPE_CODE(TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRING)
+ f77_get_dynamic_length_of_aggregate (TYPE_TARGET_TYPE (type));
+
+ /* Recursion ends here, start setting up lengths. */
+ retcode = f77_get_dynamic_lowerbound (type, &lower_bound);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain valid array lower bound");
+
+ retcode = f77_get_dynamic_upperbound (type, &upper_bound);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain valid array upper bound");
+
+ /* Patch in a valid length value. */
+
+ TYPE_LENGTH (type) =
+ (upper_bound - lower_bound + 1) * TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type)));
+}
+
+/* Function that sets up the array offset,size table for the array
+ type "type". */
+
+void
+f77_create_arrayprint_offset_tbl (type, stream)
+ struct type *type;
+ FILE *stream;
+{
+ struct type *tmp_type;
+ int eltlen;
+ int ndimen = 1;
+ int upper, lower, retcode;
+
+ tmp_type = type;
+
+ while ((TYPE_CODE (tmp_type) == TYPE_CODE_ARRAY))
+ {
+ if (TYPE_ARRAY_UPPER_BOUND_TYPE (tmp_type) == BOUND_CANNOT_BE_DETERMINED)
+ fprintf_filtered (stream, "<assumed size array> ");
+
+ retcode = f77_get_dynamic_upperbound (tmp_type, &upper);
+ if (retcode == BOUND_FETCH_ERROR)
+ error ("Cannot obtain dynamic upper bound");
+
+ retcode = f77_get_dynamic_lowerbound(tmp_type,&lower);
+ if (retcode == BOUND_FETCH_ERROR)
+ error("Cannot obtain dynamic lower bound");
+
+ F77_DIM_SIZE (ndimen) = upper - lower + 1;
+
+ tmp_type = TYPE_TARGET_TYPE (tmp_type);
+ ndimen++;
+ }
+
+ /* Now we multiply eltlen by all the offsets, so that later we
+ can print out array elements correctly. Up till now we
+ know an offset to apply to get the item but we also
+ have to know how much to add to get to the next item */
+
+ ndimen--;
+ eltlen = TYPE_LENGTH (tmp_type);
+ F77_DIM_OFFSET (ndimen) = eltlen;
+ while (--ndimen > 0)
+ {
+ eltlen *= F77_DIM_SIZE (ndimen + 1);
+ F77_DIM_OFFSET (ndimen) = eltlen;
+ }
+}
+
+/* Actual function which prints out F77 arrays, Valaddr == address in
+ the superior. Address == the address in the inferior. */
+
+void
+f77_print_array_1 (nss, ndimensions, type, valaddr, address,
+ stream, format, deref_ref, recurse, pretty)
+ int nss;
+ int ndimensions;
+ char *valaddr;
+ struct type *type;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ int i;
+
+ if (nss != ndimensions)
+ {
+ for (i = 0; i< F77_DIM_SIZE(nss); i++)
+ {
+ fprintf_filtered (stream, "( ");
+ f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type),
+ valaddr + i * F77_DIM_OFFSET (nss),
+ address + i * F77_DIM_OFFSET (nss),
+ stream, format, deref_ref, recurse, pretty, i);
+ fprintf_filtered (stream, ") ");
+ }
+ }
+ else
+ {
+ for (i = 0; (i < F77_DIM_SIZE (nss) && i < print_max); i++)
+ {
+ val_print (TYPE_TARGET_TYPE (type),
+ valaddr + i * F77_DIM_OFFSET (ndimensions),
+ address + i * F77_DIM_OFFSET (ndimensions),
+ stream, format, deref_ref, recurse, pretty);
+
+ if (i != (F77_DIM_SIZE (nss) - 1))
+ fprintf_filtered (stream, ", ");
+
+ if (i == print_max - 1)
+ fprintf_filtered (stream, "...");
+ }
+ }
+}
+
+/* This function gets called to print an F77 array, we set up some
+ stuff and then immediately call f77_print_array_1() */
+
+void
+f77_print_array (type, valaddr, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ int ndimensions;
+
+ ndimensions = calc_f77_array_dims (type);
+
+ if (ndimensions > MAX_FORTRAN_DIMS || ndimensions < 0)
+ error ("Type node corrupt! F77 arrays cannot have %d subscripts (%d Max)",
+ ndimensions, MAX_FORTRAN_DIMS);
+
+ /* Since F77 arrays are stored column-major, we set up an
+ offset table to get at the various row's elements. The
+ offset table contains entries for both offset and subarray size. */
+
+ f77_create_arrayprint_offset_tbl (type, stream);
+
+ f77_print_array_1 (1, ndimensions, type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+}
+
+
+/* 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
+ target byte order.
+
+ If the data are a string pointer, returns the number of string characters
+ printed.
+
+ If DEREF_REF is nonzero, then dereference references, otherwise just print
+ them like pointers.
+
+ The PRETTY parameter controls prettyprinting. */
+
+int
+f_val_print (type, valaddr, address, stream, format, deref_ref, recurse,
+ pretty)
+ struct type *type;
+ char *valaddr;
+ CORE_ADDR address;
+ FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ register unsigned int i = 0; /* Number of characters printed */
+ struct type *elttype;
+ LONGEST val;
+ CORE_ADDR addr;
+
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRING:
+ f77_get_dynamic_length_of_aggregate (type);
+ LA_PRINT_STRING (stream, valaddr, TYPE_LENGTH (type), 0);
+ break;
+
+ case TYPE_CODE_ARRAY:
+ fprintf_filtered (stream, "(");
+ f77_print_array (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+ fprintf_filtered (stream, ")");
+ break;
+#if 0
+ /* Array of unspecified length: treat like pointer to first elt. */
+ valaddr = (char *) &address;
+ /* FALL THROUGH */
+#endif
+ case TYPE_CODE_PTR:
+ if (format && format != 's')
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ else
+ {
+ addr = unpack_pointer (type, valaddr);
+ elttype = check_typedef (TYPE_TARGET_TYPE (type));
+
+ if (TYPE_CODE (elttype) == TYPE_CODE_FUNC)
+ {
+ /* Try to print what function it points to. */
+ print_address_demangle (addr, stream, demangle);
+ /* Return value is irrelevant except for string pointers. */
+ return 0;
+ }
+
+ if (addressprint && format != 's')
+ fprintf_filtered (stream, "0x%x", addr);
+
+ /* For a pointer to char or unsigned char, also print the string
+ pointed to, unless pointer is null. */
+ if (TYPE_LENGTH (elttype) == 1
+ && TYPE_CODE (elttype) == TYPE_CODE_INT
+ && (format == 0 || format == 's')
+ && addr != 0)
+ i = val_print_string (addr, 0, stream);
+
+ /* Return number of characters printed, plus one for the
+ terminating null if we have "reached the end". */
+ return (i + (print_max && i != print_max));
+ }
+ break;
+
+ case TYPE_CODE_FUNC:
+ if (format)
+ {
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ break;
+ }
+ /* FIXME, we should consider, at least for ANSI C language, eliminating
+ the distinction made between FUNCs and POINTERs to FUNCs. */
+ fprintf_filtered (stream, "{");
+ type_print (type, "", stream, -1);
+ fprintf_filtered (stream, "} ");
+ /* Try to print what function it points to, and its address. */
+ print_address_demangle (address, stream, demangle);
+ break;
+
+ case TYPE_CODE_INT:
+ format = format ? format : output_format;
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ {
+ val_print_type_code_int (type, valaddr, stream);
+ /* C and C++ has no single byte int type, char is used instead.
+ Since we don't know whether the value is really intended to
+ be used as an integer or a character, print the character
+ equivalent as well. */
+ if (TYPE_LENGTH (type) == 1)
+ {
+ fputs_filtered (" ", stream);
+ LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr),
+ stream);
+ }
+ }
+ break;
+
+ case TYPE_CODE_FLT:
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ print_floating (valaddr, type, stream);
+ break;
+
+ case TYPE_CODE_VOID:
+ fprintf_filtered (stream, "VOID");
+ break;
+
+ case TYPE_CODE_ERROR:
+ fprintf_filtered (stream, "<error type>");
+ break;
+
+ case TYPE_CODE_RANGE:
+ /* FIXME, we should not ever have to print one of these yet. */
+ fprintf_filtered (stream, "<range type>");
+ break;
+
+ case TYPE_CODE_BOOL:
+ format = format ? format : output_format;
+ if (format)
+ print_scalar_formatted (valaddr, type, format, 0, stream);
+ else
+ {
+ val = 0;
+ switch (TYPE_LENGTH(type))
+ {
+ case 1:
+ val = unpack_long (builtin_type_f_logical_s1, valaddr);
+ break ;
+
+ case 2:
+ val = unpack_long (builtin_type_f_logical_s2, valaddr);
+ break ;
+
+ case 4:
+ val = unpack_long (builtin_type_f_logical, valaddr);
+ break ;
+
+ default:
+ error ("Logicals of length %d bytes not supported",
+ TYPE_LENGTH (type));
+
+ }
+
+ if (val == 0)
+ fprintf_filtered (stream, ".FALSE.");
+ else
+ if (val == 1)
+ fprintf_filtered (stream, ".TRUE.");
+ else
+ /* Not a legitimate logical type, print as an integer. */
+ {
+ /* Bash the type code temporarily. */
+ TYPE_CODE (type) = TYPE_CODE_INT;
+ f_val_print (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+ /* Restore the type code so later uses work as intended. */
+ TYPE_CODE (type) = TYPE_CODE_BOOL;
+ }
+ }
+ break;
+
+ case TYPE_CODE_COMPLEX:
+ switch (TYPE_LENGTH (type))
+ {
+ case 8: type = builtin_type_f_real; break;
+ case 16: type = builtin_type_f_real_s8; break;
+ case 32: type = builtin_type_f_real_s16; break;
+ default:
+ error ("Cannot print out complex*%d variables", TYPE_LENGTH(type));
+ }
+ fputs_filtered ("(", stream);
+ print_floating (valaddr, type, stream);
+ fputs_filtered (",", stream);
+ print_floating (valaddr, type, stream);
+ fputs_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"
+ and no complete type for struct foo in that file. */
+ fprintf_filtered (stream, "<incomplete type>");
+ break;
+
+ default:
+ error ("Invalid F77 type code %d in symbol table.", TYPE_CODE (type));
+ }
+ fflush (stream);
+ return 0;
+}
+
+void
+list_all_visible_commons (funname)
+ char *funname;
+{
+ SAVED_F77_COMMON_PTR tmp;
+
+ tmp = head_common_list;
+
+ printf_filtered ("All COMMON blocks visible at this level:\n\n");
+
+ while (tmp != NULL)
+ {
+ if (STREQ(tmp->owning_function,funname))
+ printf_filtered ("%s\n", tmp->name);
+
+ tmp = tmp->next;
+ }
+}
+
+/* This function is used to print out the values in a given COMMON
+ block. It will always use the most local common block of the
+ given name */
+
+static void
+info_common_command (comname, from_tty)
+ char *comname;
+ int from_tty;
+{
+ SAVED_F77_COMMON_PTR the_common;
+ COMMON_ENTRY_PTR entry;
+ struct frame_info *fi;
+ register char *funname = 0;
+ struct symbol *func;
+
+ /* We have been told to display the contents of F77 COMMON
+ block supposedly visible in this function. Let us
+ first make sure that it is visible and if so, let
+ us display its contents */
+
+ fi = selected_frame;
+
+ if (fi == NULL)
+ error ("No frame selected");
+
+ /* The following is generally ripped off from stack.c's routine
+ print_frame_info() */
+
+ func = find_pc_function (fi->pc);
+ if (func)
+ {
+ /* In certain pathological cases, the symtabs give the wrong
+ function (when we are in the first function in a file which
+ is compiled without debugging symbols, the previous function
+ is compiled with debugging symbols, and the "foo.o" symbol
+ that is supposed to tell us where the file with debugging symbols
+ ends has been truncated by ar because it is longer than 15
+ characters).
+
+ So look in the minimal symbol tables as well, and if it comes
+ up with a larger address for the function use that instead.
+ I don't think this can ever cause any problems; there shouldn't
+ be any minimal symbols in the middle of a function.
+ FIXME: (Not necessarily true. What about text labels) */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL
+ && (SYMBOL_VALUE_ADDRESS (msymbol)
+ > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
+ funname = SYMBOL_NAME (msymbol);
+ else
+ funname = SYMBOL_NAME (func);
+ }
+ else
+ {
+ register struct minimal_symbol *msymbol =
+ lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL)
+ funname = SYMBOL_NAME (msymbol);
+ }
+
+ /* If comname is NULL, we assume the user wishes to see the
+ which COMMON blocks are visible here and then return */
+
+ if (comname == 0)
+ {
+ list_all_visible_commons (funname);
+ return;
+ }
+
+ the_common = find_common_for_function (comname,funname);
+
+ if (the_common)
+ {
+ if (STREQ(comname,BLANK_COMMON_NAME_LOCAL))
+ printf_filtered ("Contents of blank COMMON block:\n");
+ else
+ printf_filtered ("Contents of F77 COMMON block '%s':\n",comname);
+
+ printf_filtered ("\n");
+ entry = the_common->entries;
+
+ while (entry != NULL)
+ {
+ printf_filtered ("%s = ",SYMBOL_NAME(entry->symbol));
+ print_variable_value (entry->symbol,fi,stdout);
+ printf_filtered ("\n");
+ entry = entry->next;
+ }
+ }
+ else
+ printf_filtered ("Cannot locate the common block %s in function '%s'\n",
+ comname, funname);
+}
+
+/* This function is used to determine whether there is a
+ F77 common block visible at the current scope called 'comname'. */
+
+int
+there_is_a_visible_common_named (comname)
+ char *comname;
+{
+ SAVED_F77_COMMON_PTR the_common;
+ struct frame_info *fi;
+ register char *funname = 0;
+ struct symbol *func;
+
+ if (comname == NULL)
+ error ("Cannot deal with NULL common name!");
+
+ fi = selected_frame;
+
+ if (fi == NULL)
+ error ("No frame selected");
+
+ /* The following is generally ripped off from stack.c's routine
+ print_frame_info() */
+
+ func = find_pc_function (fi->pc);
+ if (func)
+ {
+ /* In certain pathological cases, the symtabs give the wrong
+ function (when we are in the first function in a file which
+ is compiled without debugging symbols, the previous function
+ is compiled with debugging symbols, and the "foo.o" symbol
+ that is supposed to tell us where the file with debugging symbols
+ ends has been truncated by ar because it is longer than 15
+ characters).
+
+ So look in the minimal symbol tables as well, and if it comes
+ up with a larger address for the function use that instead.
+ I don't think this can ever cause any problems; there shouldn't
+ be any minimal symbols in the middle of a function.
+ FIXME: (Not necessarily true. What about text labels) */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL
+ && (SYMBOL_VALUE_ADDRESS (msymbol)
+ > BLOCK_START (SYMBOL_BLOCK_VALUE (func))))
+ funname = SYMBOL_NAME (msymbol);
+ else
+ funname = SYMBOL_NAME (func);
+ }
+ else
+ {
+ register struct minimal_symbol *msymbol =
+ lookup_minimal_symbol_by_pc (fi->pc);
+
+ if (msymbol != NULL)
+ funname = SYMBOL_NAME (msymbol);
+ }
+
+ the_common = find_common_for_function (comname, funname);
+
+ return (the_common ? 1 : 0);
+}
+
+void
+_initialize_f_valprint ()
+{
+ add_info ("common", info_common_command,
+ "Print out the values contained in a Fortran COMMON block.");
+}
diff --git a/contrib/gdb/gdb/findvar.c b/contrib/gdb/gdb/findvar.c
new file mode 100644
index 0000000..1dce905
--- /dev/null
+++ b/contrib/gdb/gdb/findvar.c
@@ -0,0 +1,1444 @@
+/* Find a variable's value in memory, for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "frame.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdb_string.h"
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+static void write_register_pid PARAMS ((int regno, LONGEST val, int pid));
+
+/* Basic byte-swapping routines. GDB has needed these for a long time...
+ All extract a target-format integer at ADDR which is LEN bytes long. */
+
+#if TARGET_CHAR_BIT != 8 || HOST_CHAR_BIT != 8
+ /* 8 bit characters are a pretty safe assumption these days, so we
+ assume it throughout all these swapping routines. If we had to deal with
+ 9 bit characters, we would need to make len be in bits and would have
+ to re-write these routines... */
+ you lose
+#endif
+
+LONGEST
+extract_signed_integer (addr, len)
+ PTR addr;
+ int len;
+{
+ LONGEST retval;
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ if (len > (int) sizeof (LONGEST))
+ error ("\
+That operation is not available on integers of more than %d bytes.",
+ sizeof (LONGEST));
+
+ /* Start at the most significant end of the integer, and work towards
+ the least significant. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ p = startaddr;
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST)*p ^ 0x80) - 0x80;
+ for (++p; p < endaddr; ++p)
+ retval = (retval << 8) | *p;
+ }
+ else
+ {
+ p = endaddr - 1;
+ /* Do the sign extension once at the start. */
+ retval = ((LONGEST)*p ^ 0x80) - 0x80;
+ for (--p; p >= startaddr; --p)
+ retval = (retval << 8) | *p;
+ }
+ return retval;
+}
+
+unsigned LONGEST
+extract_unsigned_integer (addr, len)
+ PTR addr;
+ int len;
+{
+ unsigned LONGEST retval;
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ if (len > (int) sizeof (unsigned LONGEST))
+ error ("\
+That operation is not available on integers of more than %d bytes.",
+ sizeof (unsigned LONGEST));
+
+ /* Start at the most significant end of the integer, and work towards
+ the least significant. */
+ retval = 0;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = startaddr; p < endaddr; ++p)
+ retval = (retval << 8) | *p;
+ }
+ else
+ {
+ for (p = endaddr - 1; p >= startaddr; --p)
+ retval = (retval << 8) | *p;
+ }
+ return retval;
+}
+
+/* Sometimes a long long unsigned integer can be extracted as a
+ LONGEST value. This is done so that we can print these values
+ better. If this integer can be converted to a LONGEST, this
+ function returns 1 and sets *PVAL. Otherwise it returns 0. */
+
+int
+extract_long_unsigned_integer (addr, orig_len, pval)
+ PTR addr;
+ int orig_len;
+ LONGEST *pval;
+{
+ char *p, *first_addr;
+ int len;
+
+ len = orig_len;
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = (char *) addr;
+ len > (int) sizeof (LONGEST) && p < (char *) addr + orig_len;
+ p++)
+ {
+ if (*p == 0)
+ len--;
+ else
+ break;
+ }
+ first_addr = p;
+ }
+ else
+ {
+ first_addr = (char *) addr;
+ for (p = (char *) addr + orig_len - 1;
+ len > (int) sizeof (LONGEST) && p >= (char *) addr;
+ p--)
+ {
+ if (*p == 0)
+ len--;
+ else
+ break;
+ }
+ }
+
+ if (len <= (int) sizeof (LONGEST))
+ {
+ *pval = (LONGEST) extract_unsigned_integer (first_addr,
+ sizeof (LONGEST));
+ return 1;
+ }
+
+ return 0;
+}
+
+CORE_ADDR
+extract_address (addr, len)
+ PTR addr;
+ int len;
+{
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+ return extract_unsigned_integer (addr, len);
+}
+
+void
+store_signed_integer (addr, len, val)
+ PTR addr;
+ int len;
+ LONGEST val;
+{
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ /* Start at the least significant end of the integer, and work towards
+ the most significant. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = endaddr - 1; p >= startaddr; --p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+ else
+ {
+ for (p = startaddr; p < endaddr; ++p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+}
+
+void
+store_unsigned_integer (addr, len, val)
+ PTR addr;
+ int len;
+ unsigned LONGEST val;
+{
+ unsigned char *p;
+ unsigned char *startaddr = (unsigned char *)addr;
+ unsigned char *endaddr = startaddr + len;
+
+ /* Start at the least significant end of the integer, and work towards
+ the most significant. */
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = endaddr - 1; p >= startaddr; --p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+ else
+ {
+ for (p = startaddr; p < endaddr; ++p)
+ {
+ *p = val & 0xff;
+ val >>= 8;
+ }
+ }
+}
+
+void
+store_address (addr, len, val)
+ PTR addr;
+ int len;
+ CORE_ADDR val;
+{
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+ store_unsigned_integer (addr, len, (LONGEST)val);
+}
+
+/* Swap LEN bytes at BUFFER between target and host byte-order. */
+#define SWAP_FLOATING(buffer,len) \
+ do \
+ { \
+ if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER) \
+ { \
+ char tmp; \
+ char *p = (char *)(buffer); \
+ char *q = ((char *)(buffer)) + len - 1; \
+ for (; p < q; p++, q--) \
+ { \
+ tmp = *q; \
+ *q = *p; \
+ *p = tmp; \
+ } \
+ } \
+ } \
+ while (0)
+
+/* There are various problems with the extract_floating and store_floating
+ routines.
+
+ 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. */
+
+DOUBLEST
+extract_floating (addr, len)
+ PTR addr;
+ int len;
+{
+ if (len == sizeof (float))
+ {
+ float retval;
+ memcpy (&retval, addr, sizeof (retval));
+ SWAP_FLOATING (&retval, sizeof (retval));
+ return retval;
+ }
+ else if (len == sizeof (double))
+ {
+ double retval;
+ memcpy (&retval, addr, sizeof (retval));
+ SWAP_FLOATING (&retval, sizeof (retval));
+ return retval;
+ }
+ else if (len == sizeof (DOUBLEST))
+ {
+ DOUBLEST retval;
+ memcpy (&retval, addr, sizeof (retval));
+ SWAP_FLOATING (&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;
+ DOUBLEST val;
+{
+ if (len == sizeof (float))
+ {
+ float floatval = val;
+ SWAP_FLOATING (&floatval, sizeof (floatval));
+ memcpy (addr, &floatval, sizeof (floatval));
+ }
+ else if (len == sizeof (double))
+ {
+ double doubleval = val;
+
+ SWAP_FLOATING (&doubleval, sizeof (doubleval));
+ memcpy (addr, &doubleval, sizeof (doubleval));
+ }
+ else if (len == sizeof (DOUBLEST))
+ {
+ SWAP_FLOATING (&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
+ has been saved in memory. Or return zero if it has not been saved.
+ If REGNUM specifies the SP, the value we return is actually
+ the SP value, not an address where it was saved. */
+
+CORE_ADDR
+find_saved_register (frame, regnum)
+ struct frame_info *frame;
+ int regnum;
+{
+ struct frame_saved_regs saved_regs;
+
+ register struct frame_info *frame1 = NULL;
+ register CORE_ADDR addr = 0;
+
+ if (frame == NULL) /* No regs saved if want current frame */
+ return 0;
+
+#ifdef HAVE_REGISTER_WINDOWS
+ /* We assume that a register in a register window will only be saved
+ in one place (since the name changes and/or disappears as you go
+ towards inner frames), so we only call get_frame_saved_regs on
+ the current frame. This is directly in contradiction to the
+ usage below, which assumes that registers used in a frame must be
+ saved in a lower (more interior) frame. This change is a result
+ of working on a register window machine; get_frame_saved_regs
+ always returns the registers saved within a frame, within the
+ context (register namespace) of that frame. */
+
+ /* However, note that we don't want this to return anything if
+ nothing is saved (if there's a frame inside of this one). Also,
+ callers to this routine asking for the stack pointer want the
+ stack pointer saved for *this* frame; this is returned from the
+ next frame. */
+
+ if (REGISTER_IN_WINDOW_P(regnum))
+ {
+ frame1 = get_next_frame (frame);
+ if (!frame1) return 0; /* Registers of this frame are active. */
+
+ /* Get the SP from the next frame in; it will be this
+ current frame. */
+ if (regnum != SP_REGNUM)
+ frame1 = frame;
+
+ get_frame_saved_regs (frame1, &saved_regs);
+ return saved_regs.regs[regnum]; /* ... which might be zero */
+ }
+#endif /* HAVE_REGISTER_WINDOWS */
+
+ /* Note that this next routine assumes that registers used in
+ frame x will be saved only in the frame that x calls and
+ frames interior to it. This is not true on the sparc, but the
+ above macro takes care of it, so we should be all right. */
+ while (1)
+ {
+ QUIT;
+ frame1 = get_prev_frame (frame1);
+ if (frame1 == 0 || frame1 == frame)
+ break;
+ get_frame_saved_regs (frame1, &saved_regs);
+ if (saved_regs.regs[regnum])
+ addr = saved_regs.regs[regnum];
+ }
+
+ return addr;
+}
+
+/* Find register number REGNUM relative to FRAME and put its (raw,
+ target format) contents in *RAW_BUFFER. Set *OPTIMIZED if the
+ variable was optimized out (and thus can't be fetched). Set *LVAL
+ to lval_memory, lval_register, or not_lval, depending on whether
+ the value was fetched from memory, from a register, or in a strange
+ and non-modifiable way (e.g. a frame pointer which was calculated
+ rather than fetched). Set *ADDRP to the address, either in memory
+ on as a REGISTER_BYTE offset into the registers array.
+
+ Note that this implementation never sets *LVAL to not_lval. But
+ it can be replaced by defining GET_SAVED_REGISTER and supplying
+ your own.
+
+ The argument RAW_BUFFER must point to aligned memory. */
+
+void
+get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval)
+ char *raw_buffer;
+ int *optimized;
+ CORE_ADDR *addrp;
+ struct frame_info *frame;
+ int regnum;
+ enum lval_type *lval;
+{
+ CORE_ADDR addr;
+
+ if (!target_has_registers)
+ error ("No registers.");
+
+ /* Normal systems don't optimize out things with register numbers. */
+ if (optimized != NULL)
+ *optimized = 0;
+ addr = find_saved_register (frame, regnum);
+ if (addr != 0)
+ {
+ if (lval != NULL)
+ *lval = lval_memory;
+ if (regnum == SP_REGNUM)
+ {
+ if (raw_buffer != NULL)
+ {
+ /* Put it back in target format. */
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), addr);
+ }
+ if (addrp != NULL)
+ *addrp = 0;
+ return;
+ }
+ if (raw_buffer != NULL)
+ read_memory (addr, raw_buffer, REGISTER_RAW_SIZE (regnum));
+ }
+ else
+ {
+ if (lval != NULL)
+ *lval = lval_register;
+ addr = REGISTER_BYTE (regnum);
+ if (raw_buffer != NULL)
+ read_register_gen (regnum, raw_buffer);
+ }
+ if (addrp != NULL)
+ *addrp = addr;
+}
+#endif /* GET_SAVED_REGISTER. */
+
+/* Copy the bytes of register REGNUM, relative to the current stack frame,
+ into our memory at MYADDR, in target byte order.
+ The number of bytes copied is REGISTER_RAW_SIZE (REGNUM).
+
+ Returns 1 if could not be read, 0 if could. */
+
+int
+read_relative_register_raw_bytes (regnum, myaddr)
+ int regnum;
+ char *myaddr;
+{
+ int optim;
+ if (regnum == FP_REGNUM && selected_frame)
+ {
+ /* Put it back in target format. */
+ store_address (myaddr, REGISTER_RAW_SIZE(FP_REGNUM),
+ FRAME_FP(selected_frame));
+ return 0;
+ }
+
+ get_saved_register (myaddr, &optim, (CORE_ADDR *) NULL, selected_frame,
+ regnum, (enum lval_type *)NULL);
+ return optim;
+}
+
+/* Return a `value' with the contents of register REGNUM
+ in its virtual format, with the type specified by
+ REGISTER_VIRTUAL_TYPE. */
+
+value_ptr
+value_of_register (regnum)
+ int regnum;
+{
+ CORE_ADDR addr;
+ int optim;
+ register value_ptr reg_val;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ enum lval_type lval;
+
+ get_saved_register (raw_buffer, &optim, &addr,
+ selected_frame, regnum, &lval);
+
+ 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.
+
+ The caller is responsible for making
+ sure that the inferior is stopped before calling the fetching routines,
+ or it will get garbage. (a change from GDB version 3, in which
+ the caller got the value from the last stop). */
+
+/* Contents of the registers in target byte order.
+ We allocate some extra slop since we do a lot of memcpy's around `registers',
+ and failing-soft is better than failing hard. */
+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;
+ int numregs = ARCH_NUM_REGS;
+
+ registers_pid = -1;
+
+ for (i = 0; i < numregs; i++)
+ register_valid[i] = 0;
+
+ if (registers_changed_hook)
+ registers_changed_hook ();
+}
+
+/* Indicate that all registers have been fetched, so mark them all valid. */
+void
+registers_fetched ()
+{
+ int i;
+ int numregs = ARCH_NUM_REGS;
+ for (i = 0; i < numregs; i++)
+ register_valid[i] = 1;
+}
+
+/* read_register_bytes and write_register_bytes are generally a *BAD* idea.
+ They are inefficient because they need to check for partial updates, which
+ can only be done by scanning through all of the registers and seeing if the
+ bytes that are being read/written fall inside of an invalid register. [The
+ main reason this is necessary is that register sizes can vary, so a simple
+ index won't suffice.] It is far better to call read_register_gen if you
+ want to get at the raw register contents, as it only takes a regno as an
+ argument, and therefore can't do a partial register update. It would also
+ be good to have a write_register_gen for similar reasons.
+
+ Prior to the recent fixes to check for partial updates, both read and
+ write_register_bytes always checked to see if any registers were stale, and
+ then called target_fetch_registers (-1) to update the whole set. This
+ caused really slowed things down for remote targets. */
+
+/* Copy INLEN bytes of consecutive data from registers
+ starting with the INREGBYTE'th byte of register data
+ into memory at MYADDR. */
+
+void
+read_register_bytes (inregbyte, myaddr, inlen)
+ int inregbyte;
+ char *myaddr;
+ int inlen;
+{
+ int inregend = inregbyte + inlen;
+ int regno;
+
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ /* See if we are trying to read bytes from out-of-date registers. If so,
+ update just those registers. */
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int regstart, regend;
+ int startin, endin;
+
+ if (register_valid[regno])
+ continue;
+
+ regstart = REGISTER_BYTE (regno);
+ regend = regstart + REGISTER_RAW_SIZE (regno);
+
+ startin = regstart >= inregbyte && regstart < inregend;
+ endin = regend > inregbyte && regend <= inregend;
+
+ if (!startin && !endin)
+ continue;
+
+ /* We've found an invalid register where at least one byte will be read.
+ Update it from the target. */
+
+ target_fetch_registers (regno);
+
+ if (!register_valid[regno])
+ error ("read_register_bytes: Couldn't update register %d.", regno);
+ }
+
+ if (myaddr != NULL)
+ memcpy (myaddr, &registers[inregbyte], inlen);
+}
+
+/* Read register REGNO into memory at MYADDR, which must be large enough
+ for REGISTER_RAW_BYTES (REGNO). Target byte-order.
+ If the register is known to be the size of a CORE_ADDR or smaller,
+ read_register can be used instead. */
+void
+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, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno));
+}
+
+/* Write register REGNO at MYADDR to the target. MYADDR points at
+ REGISTER_RAW_BYTES(REGNO), which must be in target byte-order. */
+
+void
+write_register_gen (regno, myaddr)
+ int regno;
+ char *myaddr;
+{
+ int size;
+
+ /* On the sparc, writing %g0 is a no-op, so we don't even want to change
+ the registers array if something writes to this register. */
+ if (CANNOT_STORE_REGISTER (regno))
+ return;
+
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ size = REGISTER_RAW_SIZE(regno);
+
+ /* 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]
+ && memcmp (&registers[REGISTER_BYTE (regno)], myaddr, size) == 0)
+ return;
+
+ target_prepare_to_store ();
+
+ memcpy (&registers[REGISTER_BYTE (regno)], myaddr, size);
+
+ register_valid [regno] = 1;
+
+ target_store_registers (regno);
+}
+
+/* Copy INLEN bytes of consecutive data from memory at MYADDR
+ into registers starting with the MYREGSTART'th byte of register data. */
+
+void
+write_register_bytes (myregstart, myaddr, inlen)
+ int myregstart;
+ char *myaddr;
+ int inlen;
+{
+ int myregend = myregstart + inlen;
+ int regno;
+
+ target_prepare_to_store ();
+
+ /* Scan through the registers updating any that are covered by the range
+ myregstart<=>myregend using write_register_gen, which does nice things
+ like handling threads, and avoiding updates when the new and old contents
+ are the same. */
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int regstart, regend;
+ int startin, endin;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ regstart = REGISTER_BYTE (regno);
+ regend = regstart + REGISTER_RAW_SIZE (regno);
+
+ startin = regstart >= myregstart && regstart < myregend;
+ endin = regend > myregstart && regend <= myregend;
+
+ if (!startin && !endin)
+ continue; /* Register is completely out of range */
+
+ if (startin && endin) /* register is completely in range */
+ {
+ write_register_gen (regno, myaddr + (regstart - myregstart));
+ continue;
+ }
+
+ /* We may be doing a partial update of an invalid register. Update it
+ from the target before scribbling on it. */
+ read_register_gen (regno, regbuf);
+
+ if (startin)
+ memcpy (registers + regstart,
+ myaddr + regstart - myregstart,
+ myregend - regstart);
+ else /* endin */
+ memcpy (registers + myregstart,
+ myaddr,
+ regend - myregstart);
+ target_store_registers (regno);
+ }
+}
+
+/* Return the raw contents of register REGNO, regarding it as an integer. */
+/* This probably should be returning LONGEST rather than CORE_ADDR. */
+
+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);
+
+ return extract_address (&registers[REGISTER_BYTE (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;
+}
+
+/* Store VALUE, into the raw contents of register number REGNO. */
+
+void
+write_register (regno, val)
+ int regno;
+ LONGEST val;
+{
+ PTR buf;
+ int size;
+
+ /* On the sparc, writing %g0 is a no-op, so we don't even want to change
+ the registers array if something writes to this register. */
+ 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);
+
+ /* 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]
+ && memcmp (&registers[REGISTER_BYTE (regno)], buf, size) == 0)
+ return;
+
+ target_prepare_to_store ();
+
+ memcpy (&registers[REGISTER_BYTE (regno)], buf, size);
+
+ register_valid [regno] = 1;
+
+ target_store_registers (regno);
+}
+
+static 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. */
+
+void
+supply_register (regno, val)
+ int regno;
+ char *val;
+{
+ if (registers_pid != inferior_pid)
+ {
+ registers_changed ();
+ registers_pid = inferior_pid;
+ }
+
+ register_valid[regno] = 1;
+ memcpy (&registers[REGISTER_BYTE (regno)], val, REGISTER_RAW_SIZE (regno));
+
+ /* On some architectures, e.g. HPPA, there are a few stray bits in some
+ registers, that the rest of the code would like to ignore. */
+#ifdef CLEAN_UP_REGISTER_VALUE
+ CLEAN_UP_REGISTER_VALUE(regno, &registers[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, val, inferior_pid);
+#ifdef NPC_REGNUM
+ write_register_pid (NPC_REGNUM, val + 4, inferior_pid);
+#ifdef NNPC_REGNUM
+ write_register_pid (NNPC_REGNUM, 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, val, pid);
+#ifdef NPC_REGNUM
+ write_register_pid (NPC_REGNUM, val + 4, pid);
+#ifdef NNPC_REGNUM
+ write_register_pid (NNPC_REGNUM, 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
+ be non-NULL. */
+int
+symbol_read_needs_frame (sym)
+ struct symbol *sym;
+{
+ switch (SYMBOL_CLASS (sym))
+ {
+ /* All cases listed explicitly so that gcc -Wall will detect it if
+ we failed to consider one. */
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ return 1;
+
+ case LOC_UNDEF:
+ case LOC_CONST:
+ case LOC_STATIC:
+ case LOC_TYPEDEF:
+
+ case LOC_LABEL:
+ /* Getting the address of a label can be done independently of the block,
+ even if some *uses* of that address wouldn't work so well without
+ the right frame. */
+
+ case LOC_BLOCK:
+ case LOC_CONST_BYTES:
+ case LOC_UNRESOLVED:
+ case LOC_OPTIMIZED_OUT:
+ return 0;
+ }
+ return 1;
+}
+
+/* Given a struct symbol for a variable,
+ and a stack frame id, read the value of the variable
+ and return a (pointer to a) struct value containing the value.
+ If the variable cannot be found, return a zero pointer.
+ If FRAME is NULL, use the selected_frame. */
+
+value_ptr
+read_var_value (var, frame)
+ register struct symbol *var;
+ struct frame_info *frame;
+{
+ register value_ptr v;
+ struct type *type = SYMBOL_TYPE (var);
+ CORE_ADDR addr;
+ register int len;
+
+ v = allocate_value (type);
+ VALUE_LVAL (v) = lval_memory; /* The most likely possibility. */
+ len = TYPE_LENGTH (type);
+
+ if (frame == NULL) frame = selected_frame;
+
+ switch (SYMBOL_CLASS (var))
+ {
+ case LOC_CONST:
+ /* Put the constant back in target format. */
+ store_signed_integer (VALUE_CONTENTS_RAW (v), len,
+ (LONGEST) SYMBOL_VALUE (var));
+ VALUE_LVAL (v) = not_lval;
+ return v;
+
+ case LOC_LABEL:
+ /* Put the constant back in target format. */
+ store_address (VALUE_CONTENTS_RAW (v), len, SYMBOL_VALUE_ADDRESS (var));
+ VALUE_LVAL (v) = not_lval;
+ return v;
+
+ case LOC_CONST_BYTES:
+ {
+ char *bytes_addr;
+ bytes_addr = SYMBOL_VALUE_BYTES (var);
+ memcpy (VALUE_CONTENTS_RAW (v), bytes_addr, len);
+ VALUE_LVAL (v) = not_lval;
+ return v;
+ }
+
+ case LOC_STATIC:
+ addr = SYMBOL_VALUE_ADDRESS (var);
+ break;
+
+ case LOC_ARG:
+ if (frame == NULL)
+ return 0;
+ addr = FRAME_ARGS_ADDRESS (frame);
+ if (!addr)
+ return 0;
+ addr += SYMBOL_VALUE (var);
+ break;
+
+ case LOC_REF_ARG:
+ if (frame == NULL)
+ return 0;
+ addr = FRAME_ARGS_ADDRESS (frame);
+ if (!addr)
+ return 0;
+ addr += SYMBOL_VALUE (var);
+ addr = read_memory_unsigned_integer
+ (addr, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+ break;
+
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ if (frame == NULL)
+ return 0;
+ addr = FRAME_LOCALS_ADDRESS (frame);
+ addr += SYMBOL_VALUE (var);
+ break;
+
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ get_saved_register (buf, NULL, NULL, frame, SYMBOL_BASEREG (var),
+ NULL);
+ addr = extract_address (buf, REGISTER_RAW_SIZE (SYMBOL_BASEREG (var)));
+ addr += SYMBOL_VALUE (var);
+ break;
+ }
+
+ case LOC_TYPEDEF:
+ error ("Cannot look up value of a typedef");
+ break;
+
+ case LOC_BLOCK:
+ VALUE_ADDRESS (v) = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+ return v;
+
+ case LOC_REGISTER:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ {
+ struct block *b;
+
+ if (frame == NULL)
+ return 0;
+ b = get_frame_block (frame);
+
+
+ if (SYMBOL_CLASS (var) == LOC_REGPARM_ADDR)
+ {
+ addr =
+ value_as_pointer (value_from_register (lookup_pointer_type (type),
+ SYMBOL_VALUE (var),
+ frame));
+ VALUE_LVAL (v) = lval_memory;
+ }
+ else
+ return value_from_register (type, SYMBOL_VALUE (var), frame);
+ }
+ break;
+
+ case LOC_UNRESOLVED:
+ {
+ struct minimal_symbol *msym;
+
+ msym = lookup_minimal_symbol (SYMBOL_NAME (var), NULL, NULL);
+ if (msym == NULL)
+ return 0;
+ addr = SYMBOL_VALUE_ADDRESS (msym);
+ }
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ VALUE_LVAL (v) = not_lval;
+ VALUE_OPTIMIZED_OUT (v) = 1;
+ return v;
+
+ default:
+ error ("Cannot look up value of a botched symbol.");
+ break;
+ }
+
+ VALUE_ADDRESS (v) = addr;
+ VALUE_LAZY (v) = 1;
+ return v;
+}
+
+/* Return a value of type TYPE, stored in register REGNUM, in frame
+ FRAME. */
+
+value_ptr
+value_from_register (type, regnum, frame)
+ struct type *type;
+ int regnum;
+ struct frame_info *frame;
+{
+ char raw_buffer [MAX_REGISTER_RAW_SIZE];
+ CORE_ADDR addr;
+ int optim;
+ value_ptr v = allocate_value (type);
+ char *value_bytes = 0;
+ int value_bytes_copied = 0;
+ int num_storage_locs;
+ enum lval_type lval;
+ int len;
+
+ CHECK_TYPEDEF (type);
+ len = TYPE_LENGTH (type);
+
+ VALUE_REGNO (v) = regnum;
+
+ num_storage_locs = (len > REGISTER_VIRTUAL_SIZE (regnum) ?
+ ((len - 1) / REGISTER_RAW_SIZE (regnum)) + 1 :
+ 1);
+
+ if (num_storage_locs > 1
+#ifdef GDB_TARGET_IS_H8500
+ || TYPE_CODE (type) == TYPE_CODE_PTR
+#endif
+ )
+ {
+ /* Value spread across multiple storage locations. */
+
+ int local_regnum;
+ int mem_stor = 0, reg_stor = 0;
+ int mem_tracking = 1;
+ CORE_ADDR last_addr = 0;
+ CORE_ADDR first_addr = 0;
+
+ value_bytes = (char *) alloca (len + MAX_REGISTER_RAW_SIZE);
+
+ /* Copy all of the data out, whereever it may be. */
+
+#ifdef GDB_TARGET_IS_H8500
+/* This piece of hideosity is required because the H8500 treats registers
+ differently depending upon whether they are used as pointers or not. As a
+ pointer, a register needs to have a page register tacked onto the front.
+ An alternate way to do this would be to have gcc output different register
+ numbers for the pointer & non-pointer form of the register. But, it
+ doesn't, so we're stuck with this. */
+
+ if (TYPE_CODE (type) == TYPE_CODE_PTR
+ && len > 2)
+ {
+ int page_regnum;
+
+ switch (regnum)
+ {
+ case R0_REGNUM: case R1_REGNUM: case R2_REGNUM: case R3_REGNUM:
+ page_regnum = SEG_D_REGNUM;
+ break;
+ case R4_REGNUM: case R5_REGNUM:
+ page_regnum = SEG_E_REGNUM;
+ break;
+ case R6_REGNUM: case R7_REGNUM:
+ page_regnum = SEG_T_REGNUM;
+ break;
+ }
+
+ value_bytes[0] = 0;
+ get_saved_register (value_bytes + 1,
+ &optim,
+ &addr,
+ frame,
+ page_regnum,
+ &lval);
+
+ if (lval == lval_register)
+ reg_stor++;
+ else
+ mem_stor++;
+ first_addr = addr;
+ last_addr = addr;
+
+ get_saved_register (value_bytes + 2,
+ &optim,
+ &addr,
+ frame,
+ regnum,
+ &lval);
+
+ if (lval == lval_register)
+ reg_stor++;
+ else
+ {
+ mem_stor++;
+ mem_tracking = mem_tracking && (addr == last_addr);
+ }
+ last_addr = addr;
+ }
+ else
+#endif /* GDB_TARGET_IS_H8500 */
+ for (local_regnum = regnum;
+ value_bytes_copied < len;
+ (value_bytes_copied += REGISTER_RAW_SIZE (local_regnum),
+ ++local_regnum))
+ {
+ get_saved_register (value_bytes + value_bytes_copied,
+ &optim,
+ &addr,
+ frame,
+ local_regnum,
+ &lval);
+
+ if (regnum == local_regnum)
+ first_addr = addr;
+ if (lval == lval_register)
+ reg_stor++;
+ else
+ {
+ mem_stor++;
+
+ mem_tracking =
+ (mem_tracking
+ && (regnum == local_regnum
+ || addr == last_addr));
+ }
+ last_addr = addr;
+ }
+
+ if ((reg_stor && mem_stor)
+ || (mem_stor && !mem_tracking))
+ /* Mixed storage; all of the hassle we just went through was
+ for some good purpose. */
+ {
+ VALUE_LVAL (v) = lval_reg_frame_relative;
+ VALUE_FRAME (v) = FRAME_FP (frame);
+ VALUE_FRAME_REGNUM (v) = regnum;
+ }
+ else if (mem_stor)
+ {
+ VALUE_LVAL (v) = lval_memory;
+ VALUE_ADDRESS (v) = first_addr;
+ }
+ else if (reg_stor)
+ {
+ VALUE_LVAL (v) = lval_register;
+ VALUE_ADDRESS (v) = first_addr;
+ }
+ else
+ fatal ("value_from_register: Value not stored anywhere!");
+
+ VALUE_OPTIMIZED_OUT (v) = optim;
+
+ /* Any structure stored in more than one register will always be
+ an integral number of registers. Otherwise, you'd need to do
+ some fiddling with the last register copied here for little
+ endian machines. */
+
+ /* Copy into the contents section of the value. */
+ memcpy (VALUE_CONTENTS_RAW (v), value_bytes, len);
+
+ /* Finally do any conversion necessary when extracting this
+ type from more than one register. */
+#ifdef REGISTER_CONVERT_TO_TYPE
+ REGISTER_CONVERT_TO_TYPE(regnum, type, VALUE_CONTENTS_RAW(v));
+#endif
+ return v;
+ }
+
+ /* Data is completely contained within a single register. Locate the
+ register's contents in a real register or in core;
+ read the data in raw format. */
+
+ get_saved_register (raw_buffer, &optim, &addr, frame, regnum, &lval);
+ VALUE_OPTIMIZED_OUT (v) = optim;
+ VALUE_LVAL (v) = lval;
+ VALUE_ADDRESS (v) = addr;
+
+ /* Convert raw data to virtual format if necessary. */
+
+#ifdef REGISTER_CONVERTIBLE
+ if (REGISTER_CONVERTIBLE (regnum))
+ {
+ REGISTER_CONVERT_TO_VIRTUAL (regnum, type,
+ raw_buffer, VALUE_CONTENTS_RAW (v));
+ }
+ else
+#endif
+ {
+ /* Raw and virtual formats are the same for this register. */
+
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN && len < REGISTER_RAW_SIZE (regnum))
+ {
+ /* Big-endian, and we want less than full size. */
+ VALUE_OFFSET (v) = REGISTER_RAW_SIZE (regnum) - len;
+ }
+
+ memcpy (VALUE_CONTENTS_RAW (v), raw_buffer + VALUE_OFFSET (v), len);
+ }
+
+ return v;
+}
+
+/* Given a struct symbol for a variable or function,
+ and a stack frame id,
+ return a (pointer to a) struct value containing the properly typed
+ address. */
+
+value_ptr
+locate_var_value (var, frame)
+ register struct symbol *var;
+ struct frame_info *frame;
+{
+ CORE_ADDR addr = 0;
+ struct type *type = SYMBOL_TYPE (var);
+ value_ptr lazy_value;
+
+ /* Evaluate it first; if the result is a memory address, we're fine.
+ Lazy evaluation pays off here. */
+
+ lazy_value = read_var_value (var, frame);
+ if (lazy_value == 0)
+ error ("Address of \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var));
+
+ if (VALUE_LAZY (lazy_value)
+ || TYPE_CODE (type) == TYPE_CODE_FUNC)
+ {
+ addr = VALUE_ADDRESS (lazy_value);
+ return value_from_longest (lookup_pointer_type (type), (LONGEST) addr);
+ }
+
+ /* Not a memory address; check what the problem was. */
+ switch (VALUE_LVAL (lazy_value))
+ {
+ case lval_register:
+ case lval_reg_frame_relative:
+ error ("Address requested for identifier \"%s\" which is in a register.",
+ SYMBOL_SOURCE_NAME (var));
+ break;
+
+ default:
+ error ("Can't take address of \"%s\" which isn't an lvalue.",
+ SYMBOL_SOURCE_NAME (var));
+ break;
+ }
+ return 0; /* For lint -- never reached */
+}
diff --git a/contrib/gdb/gdb/fork-child.c b/contrib/gdb/gdb/fork-child.c
new file mode 100644
index 0000000..df289d4
--- /dev/null
+++ b/contrib/gdb/gdb/fork-child.c
@@ -0,0 +1,309 @@
+/* Fork a Unix child process, and set up to debug it, for GDB.
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#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 <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+extern char **environ;
+
+#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,
+ 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;
+ static char default_shell_file[] = SHELL_FILE;
+ int len;
+ /* 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
+ to you in the parent process. It's only used by humans for debugging. */
+ static int debug_setpgrp = 657473;
+ char **save_our_env;
+
+ /* If no exec file handed to us, get it from the exec-file command -- with
+ a good, common error message if none is specified. */
+ if (exec_file == 0)
+ exec_file = get_exec_file(1);
+
+ /* 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-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;
+
+ /* Multiplying the length of exec_file by 4 is to account for the fact
+ that it may expand when quoted; it is a worst-case number based on
+ every character being '. */
+ len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop*/ 12;
+ /* If desired, concat something onto the front of ALLARGS.
+ SHELL_COMMAND is the result. */
+#ifdef SHELL_COMMAND_CONCAT
+ shell_command = (char *) alloca (strlen (SHELL_COMMAND_CONCAT) + len);
+ strcpy (shell_command, SHELL_COMMAND_CONCAT);
+#else
+ shell_command = (char *) alloca (len);
+ shell_command[0] = '\0';
+#endif
+ strcat (shell_command, "exec ");
+
+ /* Now add exec_file, quoting as necessary. */
+ {
+ char *p;
+ int need_to_quote;
+
+ /* Quoting in this style is said to work with all shells. But csh
+ on IRIX 4.0.1 can't deal with it. So we only quote it if we need
+ to. */
+ p = exec_file;
+ while (1)
+ {
+ switch (*p)
+ {
+ case '\'':
+ case '"':
+ case '(':
+ case ')':
+ case '$':
+ case '&':
+ case ';':
+ case '<':
+ case '>':
+ case ' ':
+ case '\n':
+ case '\t':
+ need_to_quote = 1;
+ goto end_scan;
+
+ case '\0':
+ need_to_quote = 0;
+ goto end_scan;
+
+ default:
+ break;
+ }
+ ++p;
+ }
+ end_scan:
+ if (need_to_quote)
+ {
+ strcat (shell_command, "'");
+ for (p = exec_file; *p != '\0'; ++p)
+ {
+ if (*p == '\'')
+ strcat (shell_command, "'\\''");
+ else
+ strncat (shell_command, p, 1);
+ }
+ strcat (shell_command, "'");
+ }
+ else
+ strcat (shell_command, exec_file);
+ }
+
+ strcat (shell_command, " ");
+ strcat (shell_command, allargs);
+
+ /* exec is said to fail if the executable is open. */
+ close_exec_file ();
+
+ /* Retain a copy of our environment variables, since the child will
+ replace the value of environ and if we're vforked, we have to
+ restore it. */
+ save_our_env = environ;
+
+ /* Tell the terminal handling subsystem what tty we plan to run on;
+ it will just record the information for later. */
+
+ new_tty_prefork (inferior_io_terminal);
+
+ /* It is generally good practice to flush any possible pending stdio
+ output prior to doing a fork, to avoid the possibility of both the
+ parent and child flushing the same data after the fork. */
+
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
+#if defined(USG) && !defined(HAVE_VFORK)
+ pid = fork ();
+#else
+ if (debug_fork)
+ pid = fork ();
+ else
+ pid = vfork ();
+#endif
+
+ if (pid < 0)
+ perror_with_name ("vfork");
+
+ if (pid == 0)
+ {
+ if (debug_fork)
+ sleep (debug_fork);
+
+ /* Run inferior in a separate process group. */
+ debug_setpgrp = gdb_setpgid ();
+ if (debug_setpgrp == -1)
+ perror("setpgrp failed in child");
+
+ /* Ask the tty subsystem to switch to the one we specified earlier
+ (or to share the current terminal, if none was specified). */
+
+ new_tty ();
+
+ /* Changing the signal handlers for the inferior after
+ a vfork can also change them for the superior, so we don't mess
+ with signals here. See comments in
+ initialize_signals for how we get the right signal handlers
+ for the inferior. */
+
+ /* "Trace me, Dr. Memory!" */
+ (*traceme_fun) ();
+
+ /* There is no execlpe call, so we have to set the environment
+ for our child in the global variable. If we've vforked, this
+ clobbers the parent, but environ is restored a few lines down
+ in the parent. By the way, yes we do need to look down the
+ path to find $SHELL. Rich Pixley says so, and I agree. */
+ environ = env;
+ execlp (shell_file, shell_file, "-c", shell_command, (char *)0);
+
+ fprintf_unfiltered (gdb_stderr, "Cannot exec %s: %s.\n", shell_file,
+ safe_strerror (errno));
+ gdb_flush (gdb_stderr);
+ _exit (0177);
+ }
+
+ /* Restore our environment in case a vforked child clob'd it. */
+ environ = save_our_env;
+
+ 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. */
+
+ /* Allow target dependant code to play with the new process. This might be
+ used to have target-specific code initialize a variable in the new process
+ prior to executing the first instruction. */
+ TARGET_CREATE_INFERIOR_HOOK (pid);
+
+#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. */
+
+ clear_proceed_status ();
+
+ 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 != 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 */
+ resume (0, stop_signal);
+ }
+ else
+ {
+ /* We handle SIGTRAP, however; it means child did an exec. */
+ if (!terminal_initted)
+ {
+ /* Now that the child has exec'd we know it has already set its
+ process group. On POSIX systems, tcsetpgrp will fail with
+ EPERM if we try it before the child's setpgid. */
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ terminal_initted = 1;
+ }
+ if (0 == --pending_execs)
+ break;
+ resume (0, TARGET_SIGNAL_0); /* Just make it go on */
+ }
+ }
+#endif /* STARTUP_INFERIOR */
+ stop_soon_quietly = 0;
+}
diff --git a/contrib/gdb/gdb/frame.h b/contrib/gdb/gdb/frame.h
new file mode 100644
index 0000000..d9dc0f8
--- /dev/null
+++ b/contrib/gdb/gdb/frame.h
@@ -0,0 +1,196 @@
+/* Definitions for dealing with stack frames, for GDB, the GNU debugger.
+ Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (FRAME_H)
+#define FRAME_H 1
+
+/* We keep a cache of stack frames, each of which is a "struct
+ frame_info". The innermost one gets allocated (in
+ wait_for_inferior) each time the inferior stops; current_frame
+ points to it. Additional frames get allocated (in
+ get_prev_frame_info) as needed, and are chained through the next
+ and prev fields. Any time that the frame cache becomes invalid
+ (most notably when we execute something, but also if we change how
+ we interpret the frames (e.g. "set heuristic-fence-post" in
+ mips-tdep.c, or anything which reads new symbols)), we should call
+ reinit_frame_cache. */
+
+struct frame_info
+ {
+ /* Nominal address of the frame described. See comments at FRAME_FP
+ about what this means outside the *FRAME* macros; in the *FRAME*
+ macros, it can mean whatever makes most sense for this machine. */
+ CORE_ADDR frame;
+
+ /* Address at which execution is occurring in this frame.
+ For the innermost frame, it's the current pc.
+ For other frames, it is a pc saved in the next frame. */
+ CORE_ADDR pc;
+
+ /* Nonzero if this is a frame associated with calling a signal handler.
+
+ Set by machine-dependent code. On some machines, if
+ the machine-dependent code fails to check for this, the backtrace
+ will look relatively normal. For example, on the i386
+ #3 0x158728 in sighold ()
+ On other machines (e.g. rs6000), the machine-dependent code better
+ set this to prevent us from trying to print it like a normal frame. */
+ int signal_handler_caller;
+
+ /* Anything extra for this structure that may have been defined
+ in the machine dependent files. */
+#ifdef EXTRA_FRAME_INFO
+ EXTRA_FRAME_INFO
+#endif
+
+ /* We should probably also store a "struct frame_saved_regs" here.
+ This is already done by some machines (e.g. config/m88k/tm-m88k.h)
+ but there is no reason it couldn't be general. */
+
+ /* Pointers to the next and previous frame_info's in the frame cache. */
+ struct frame_info *next, *prev;
+ };
+
+/* Describe the saved registers of a frame. */
+
+struct frame_saved_regs
+ {
+
+ /* For each register, address of where it was saved on entry to
+ the frame, or zero if it was not saved on entry to this frame.
+ This includes special registers such as pc and fp saved in
+ special ways in the stack frame. The SP_REGNUM is even more
+ special, the address here is the sp for the next frame, not the
+ address where the sp was saved. */
+
+ CORE_ADDR regs[NUM_REGS];
+ };
+
+/* Return the frame address from FR. Except in the machine-dependent
+ *FRAME* macros, a frame address has no defined meaning other than
+ as a magic cookie which identifies a frame over calls to the
+ inferior. The only known exception is inferior.h
+ (PC_IN_CALL_DUMMY) [ON_STACK]; see comments there. You cannot
+ assume that a frame address contains enough information to
+ reconstruct the frame; if you want more than just to identify the
+ frame (e.g. be able to fetch variables relative to that frame),
+ then save the whole struct frame_info (and the next struct
+ frame_info, since the latter is used for fetching variables on some
+ machines). */
+
+#define FRAME_FP(fi) ((fi)->frame)
+
+/* Define a default FRAME_CHAIN_VALID, in the form that is suitable for most
+ targets. If FRAME_CHAIN_VALID returns zero it means that the given frame
+ is the outermost one and has no caller.
+
+ If a particular target needs a different definition, then it can override
+ the definition here by providing one in the tm file. */
+
+#if !defined (FRAME_CHAIN_VALID)
+
+#if defined (FRAME_CHAIN_VALID_ALTERNATE)
+
+/* Use the alternate method of avoiding running up off the end of the frame
+ chain or following frames back into the startup code. See the comments
+ in objfiles.h. */
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ ((chain) != 0 \
+ && !inside_main_func ((thisframe) -> pc) \
+ && !inside_entry_func ((thisframe) -> pc))
+
+#else
+
+#define FRAME_CHAIN_VALID(chain, thisframe) \
+ ((chain) != 0 \
+ && !inside_entry_file (FRAME_SAVED_PC (thisframe)))
+
+#endif /* FRAME_CHAIN_VALID_ALTERNATE */
+
+#endif /* FRAME_CHAIN_VALID */
+
+/* The stack frame that the user has specified for commands to act on.
+ Note that one cannot assume this is the address of valid data. */
+
+extern struct frame_info *selected_frame;
+
+/* Level of the selected frame:
+ 0 for innermost, 1 for its caller, ...
+ or -1 for frame specified by address with no defined level. */
+
+extern int selected_frame_level;
+
+extern struct frame_info *get_prev_frame_info PARAMS ((struct frame_info *));
+
+extern struct frame_info *create_new_frame PARAMS ((CORE_ADDR, CORE_ADDR));
+
+extern void flush_cached_frames PARAMS ((void));
+
+extern void reinit_frame_cache PARAMS ((void));
+
+extern void get_frame_saved_regs PARAMS ((struct frame_info *,
+ struct frame_saved_regs *));
+
+extern void set_current_frame PARAMS ((struct frame_info *));
+
+extern struct frame_info *get_prev_frame PARAMS ((struct frame_info *));
+
+extern struct frame_info *get_current_frame PARAMS ((void));
+
+extern struct frame_info *get_next_frame PARAMS ((struct frame_info *));
+
+extern struct block *get_frame_block PARAMS ((struct frame_info *));
+
+extern struct block *get_current_block PARAMS ((void));
+
+extern struct block *get_selected_block PARAMS ((void));
+
+extern struct symbol *get_frame_function PARAMS ((struct frame_info *));
+
+extern CORE_ADDR get_frame_pc PARAMS ((struct frame_info *));
+
+extern CORE_ADDR get_pc_function_start PARAMS ((CORE_ADDR));
+
+extern struct block * block_for_pc PARAMS ((CORE_ADDR));
+
+extern int frameless_look_for_prologue PARAMS ((struct frame_info *));
+
+extern void print_frame_args PARAMS ((struct symbol *, struct frame_info *,
+ int, GDB_FILE *));
+
+extern struct frame_info *find_relative_frame PARAMS ((struct frame_info *, int*));
+
+extern void print_stack_frame PARAMS ((struct frame_info *, int, int));
+
+extern void select_frame PARAMS ((struct frame_info *, int));
+
+extern void record_selected_frame PARAMS ((CORE_ADDR *, int *));
+
+extern void print_frame_info PARAMS ((struct frame_info *, int, int, int));
+
+extern CORE_ADDR find_saved_register PARAMS ((struct frame_info *, int));
+
+extern struct frame_info *block_innermost_frame PARAMS ((struct block *));
+
+extern struct frame_info *find_frame_addr_in_frame_chain PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR sigtramp_saved_pc PARAMS ((struct frame_info *));
+
+#endif /* !defined (FRAME_H) */
diff --git a/contrib/gdb/gdb/gdb-stabs.h b/contrib/gdb/gdb/gdb-stabs.h
new file mode 100644
index 0000000..cb7b621
--- /dev/null
+++ b/contrib/gdb/gdb/gdb-stabs.h
@@ -0,0 +1,78 @@
+/* Definitions for symbol-reading containing "stabs", for GDB.
+ Copyright 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by John Gilmore.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file exists to hold the common definitions required of most of
+ the symbol-readers that end up using stabs. The common use of
+ these `symbol-type-specific' customizations of the generic data
+ structures makes the stabs-oriented symbol readers able to call
+ each others' functions as required. */
+
+#if !defined (GDBSTABS_H)
+#define GDBSTABS_H
+
+/* Offsets in the psymtab's section_offsets array for various kinds of
+ stabs symbols. Every psymtab built from stabs will have these offsets
+ filled in by these guidelines, so that when actually reading symbols, the
+ proper offset can simply be selected and added to the symbol value. */
+
+#define SECT_OFF_TEXT 0
+#define SECT_OFF_DATA 1
+#define SECT_OFF_BSS 2
+#define SECT_OFF_RODATA 3
+#define SECT_OFF_MAX 4 /* Count of possible values */
+
+/* The stab_section_info chain remembers info from the ELF symbol table,
+ while psymtabs are being built for the other symbol tables in the
+ objfile. It is destroyed at the complation of psymtab-reading.
+ Any info that was used from it has been copied into psymtabs. */
+
+struct stab_section_info {
+ char *filename;
+ CORE_ADDR sections[SECT_OFF_MAX];
+ struct stab_section_info *next;
+ int found; /* Count of times it's found in searching */
+};
+
+/* Information is passed among various dbxread routines for accessing
+ symbol files. A pointer to this structure is kept in the sym_stab_info
+ field of the objfile struct. */
+
+struct dbx_symfile_info {
+ CORE_ADDR text_addr; /* Start of text section */
+ int text_size; /* Size of text section */
+ int symcount; /* How many symbols are there in the file */
+ char *stringtab; /* The actual string table */
+ int stringtab_size; /* Its size */
+ file_ptr symtab_offset; /* Offset in file to symbol table */
+ int symbol_size; /* Bytes in a single symbol */
+ struct stab_section_info *stab_section_info; /* section starting points
+ of the original .o files before linking. */
+};
+
+#define DBX_SYMFILE_INFO(o) ((struct dbx_symfile_info *)((o)->sym_stab_info))
+#define DBX_TEXT_ADDR(o) (DBX_SYMFILE_INFO(o)->text_addr)
+#define DBX_TEXT_SIZE(o) (DBX_SYMFILE_INFO(o)->text_size)
+#define DBX_SYMCOUNT(o) (DBX_SYMFILE_INFO(o)->symcount)
+#define DBX_STRINGTAB(o) (DBX_SYMFILE_INFO(o)->stringtab)
+#define DBX_STRINGTAB_SIZE(o) (DBX_SYMFILE_INFO(o)->stringtab_size)
+#define DBX_SYMTAB_OFFSET(o) (DBX_SYMFILE_INFO(o)->symtab_offset)
+#define DBX_SYMBOL_SIZE(o) (DBX_SYMFILE_INFO(o)->symbol_size)
+
+#endif /* GDBSTABS_H */
diff --git a/contrib/gdb/gdb/gdb.1 b/contrib/gdb/gdb/gdb.1
new file mode 100644
index 0000000..cb1cba1
--- /dev/null
+++ b/contrib/gdb/gdb/gdb.1
@@ -0,0 +1,371 @@
+.\" Copyright (c) 1991 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.\" $Id: gdb.1,v 1.3 1991/12/13 22:22:58 pesch Exp $
+.TH gdb 1 "4nov1991" "GNU Tools" "GNU Tools"
+.SH NAME
+gdb \- The GNU Debugger
+.SH SYNOPSIS
+.na
+.TP
+.B gdb
+.RB "[\|" \-help "\|]"
+.RB "[\|" \-nx "\|]"
+.RB "[\|" \-q "\|]"
+.RB "[\|" \-batch "\|]"
+.RB "[\|" \-cd=\c
+.I dir\c
+\|]
+.RB "[\|" \-f "\|]"
+.RB "[\|" "\-b\ "\c
+.IR bps "\|]"
+.RB "[\|" "\-tty="\c
+.IR dev "\|]"
+.RB "[\|" "\-s "\c
+.I symfile\c
+\&\|]
+.RB "[\|" "\-e "\c
+.I prog\c
+\&\|]
+.RB "[\|" "\-se "\c
+.I prog\c
+\&\|]
+.RB "[\|" "\-c "\c
+.I core\c
+\&\|]
+.RB "[\|" "\-x "\c
+.I cmds\c
+\&\|]
+.RB "[\|" "\-d "\c
+.I dir\c
+\&\|]
+.RB "[\|" \c
+.I prog\c
+.RB "[\|" \c
+.IR core \||\| procID\c
+\&\|]\&\|]
+.ad b
+.SH DESCRIPTION
+The purpose of a debugger such as GDB is to allow you to see what is
+going on ``inside'' another program while it executes\(em\&or what another
+program was doing at the moment it crashed.
+
+GDB can do four main kinds of things (plus other things in support of
+these) to help you catch bugs in the act:
+
+.TP
+\ \ \ \(bu
+Start your program, specifying anything that might affect its behavior.
+
+.TP
+\ \ \ \(bu
+Make your program stop on specified conditions.
+
+.TP
+\ \ \ \(bu
+Examine what has happened, when your program has stopped.
+
+.TP
+\ \ \ \(bu
+Change things in your program, so you can experiment with correcting the
+effects of one bug and go on to learn about another.
+.PP
+
+You can use GDB to debug programs written in C, C++, and Modula-2.
+Fortran support will be added when a GNU Fortran compiler is ready.
+
+GDB is invoked with the shell command \c
+.B gdb\c
+\&. Once started, it reads
+commands from the terminal until you tell it to exit with the GDB
+command \c
+.B quit\c
+\&. You can get online help from \c
+.B gdb\c
+\& itself
+by using the command \c
+.B help\c
+\&.
+
+You can run \c
+.B gdb\c
+\& with no arguments or options; but the most
+usual way to start GDB is with one argument or two, specifying an
+executable program as the argument:
+.sp
+.br
+gdb\ program
+.br
+.sp
+
+You can also start with both an executable program and a core file specified:
+.sp
+.br
+gdb\ program\ core
+.br
+.sp
+
+You can, instead, specify a process ID as a second argument, if you want
+to debug a running process:
+.sp
+.br
+gdb\ program\ 1234
+.br
+.sp
+
+would attach GDB to process \c
+.B 1234\c
+\& (unless you also have a file
+named `\|\c
+.B 1234\c
+\&\|'; GDB does check for a core file first).
+
+Here are some of the most frequently needed GDB commands:
+.TP
+.B break \fR[\|\fIfile\fB:\fR\|]\fIfunction
+\&
+Set a breakpoint at \c
+.I function\c
+\& (in \c
+.I file\c
+\&).
+.TP
+.B run \fR[\|\fIarglist\fR\|]
+Start your program (with \c
+.I arglist\c
+\&, if specified).
+.TP
+.B bt
+Backtrace: display the program stack.
+.TP
+.BI print " expr"\c
+\&
+Display the value of an expression.
+.TP
+.B c
+Continue running your program (after stopping, e.g. at a breakpoint).
+.TP
+.B next
+Execute next program line (after stopping); step \c
+.I over\c
+\& any
+function calls in the line.
+.TP
+.B step
+Execute next program line (after stopping); step \c
+.I into\c
+\& any
+function calls in the line.
+.TP
+.B help \fR[\|\fIname\fR\|]
+Show information about GDB command \c
+.I name\c
+\&, or general information
+about using GDB.
+.TP
+.B quit
+Exit from GDB.
+.PP
+For full details on GDB, see \c
+.I
+Using GDB: A Guide to the GNU Source-Level Debugger\c
+\&, by Richard M. Stallman and Roland H. Pesch. The same text is available online
+as the \c
+.B gdb\c
+\& entry in the \c
+.B info\c
+\& program.
+.SH OPTIONS
+Any arguments other than options specify an executable
+file and core file (or process ID); that is, the first argument
+encountered with no
+associated option flag is equivalent to a `\|\c
+.B \-se\c
+\&\|' option, and the
+second, if any, is equivalent to a `\|\c
+.B \-c\c
+\&\|' option if it's the name of a file. Many options have
+both long and short forms; both are shown here. The long forms are also
+recognized if you truncate them, so long as enough of the option is
+present to be unambiguous. (If you prefer, you can flag option
+arguments with `\|\c
+.B +\c
+\&\|' rather than `\|\c
+.B \-\c
+\&\|', though we illustrate the
+more usual convention.)
+
+All the options and command line arguments you give are processed
+in sequential order. The order makes a difference when the
+`\|\c
+.B \-x\c
+\&\|' option is used.
+
+.TP
+.B \-help
+.TP
+.B \-h
+List all options, with brief explanations.
+
+.TP
+.BI "\-symbols=" "file"\c
+.TP
+.BI "\-s " "file"\c
+\&
+Read symbol table from file \c
+.I file\c
+\&.
+
+.TP
+.BI "\-exec=" "file"\c
+.TP
+.BI "\-e " "file"\c
+\&
+Use file \c
+.I file\c
+\& as the executable file to execute when
+appropriate, and for examining pure data in conjunction with a core
+dump.
+
+.TP
+.BI "\-se=" "file"\c
+\&
+Read symbol table from file \c
+.I file\c
+\& and use it as the executable
+file.
+
+.TP
+.BI "\-core=" "file"\c
+.TP
+.BI "\-c " "file"\c
+\&
+Use file \c
+.I file\c
+\& as a core dump to examine.
+
+.TP
+.BI "\-command=" "file"\c
+.TP
+.BI "\-x " "file"\c
+\&
+Execute GDB commands from file \c
+.I file\c
+\&.
+
+.TP
+.BI "\-directory=" "directory"\c
+.TP
+.BI "\-d " "directory"\c
+\&
+Add \c
+.I directory\c
+\& to the path to search for source files.
+.PP
+
+.TP
+.B \-nx
+.TP
+.B \-n
+Do not execute commands from any `\|\c
+.B .gdbinit\c
+\&\|' initialization files.
+Normally, the commands in these files are executed after all the
+command options and arguments have been processed.
+
+
+.TP
+.B \-quiet
+.TP
+.B \-q
+``Quiet''. Do not print the introductory and copyright messages. These
+messages are also suppressed in batch mode.
+
+.TP
+.B \-batch
+Run in batch mode. Exit with status \c
+.B 0\c
+\& after processing all the command
+files specified with `\|\c
+.B \-x\c
+\&\|' (and `\|\c
+.B .gdbinit\c
+\&\|', if not inhibited).
+Exit with nonzero status if an error occurs in executing the GDB
+commands in the command files.
+
+Batch mode may be useful for running GDB as a filter, for example to
+download and run a program on another computer; in order to make this
+more useful, the message
+.sp
+.br
+Program\ exited\ normally.
+.br
+.sp
+
+(which is ordinarily issued whenever a program running under GDB control
+terminates) is not issued when running in batch mode.
+
+.TP
+.BI "\-cd=" "directory"\c
+\&
+Run GDB using \c
+.I directory\c
+\& as its working directory,
+instead of the current directory.
+
+.TP
+.B \-fullname
+.TP
+.B \-f
+Emacs sets this option when it runs GDB as a subprocess. It tells GDB
+to output the full file name and line number in a standard,
+recognizable fashion each time a stack frame is displayed (which
+includes each time the program stops). This recognizable format looks
+like two `\|\c
+.B \032\c
+\&\|' characters, followed by the file name, line number
+and character position separated by colons, and a newline. The
+Emacs-to-GDB interface program uses the two `\|\c
+.B \032\c
+\&\|' characters as
+a signal to display the source code for the frame.
+
+.TP
+.BI "\-b " "bps"\c
+\&
+Set the line speed (baud rate or bits per second) of any serial
+interface used by GDB for remote debugging.
+
+.TP
+.BI "\-tty=" "device"\c
+\&
+Run using \c
+.I device\c
+\& for your program's standard input and output.
+.PP
+
+.SH "SEE ALSO"
+.RB "`\|" gdb "\|'"
+entry in
+.B info\c
+\&;
+.I
+Using GDB: A Guide to the GNU Source-Level Debugger\c
+, Richard M. Stallman and Roland H. Pesch, July 1991.
+.SH COPYING
+Copyright (c) 1991 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/contrib/gdb/gdb/gdb.gdb b/contrib/gdb/gdb/gdb.gdb
new file mode 100644
index 0000000..4377841
--- /dev/null
+++ b/contrib/gdb/gdb/gdb.gdb
@@ -0,0 +1,35 @@
+# Examples of using gdb's command language to print out various gdb data
+# structures.
+
+define list-objfiles
+ set $obj = object_files
+ printf "objfile bfd msyms name\n"
+ while $obj != 0
+ printf "0x%-8x 0x%-8x %6d %s\n", $obj, $obj->obfd, \
+ $obj->minimal_symbol_count, $obj->name
+ set var $obj = $obj->next
+ end
+end
+document list-objfiles
+Print a table of the current objfiles.
+end
+
+define print-values
+ printf "Location Offset Size Lazy Contents0-3 Lval\n"
+ set $val = $arg0
+ while $val != 0
+ printf "%8x %6d %10d %4d %12x ", $val->location.address, \
+ $val->offset, \
+ $val->type->length, $val->lazy, $val->aligner.contents[0]
+ output $val->lval
+ printf "\n"
+ set $val = $val->next
+ end
+end
+document print-values
+Print a list of values.
+Takes one argument, the value to print, and prints all the values which
+are chained through the next field. Thus the most recently created values
+will be listed first. The "Contents0-3" field gives the first "int"
+of the VALUE_CONTENTS; not the entire contents.
+end
diff --git a/contrib/gdb/gdb/gdb_stat.h b/contrib/gdb/gdb/gdb_stat.h
new file mode 100644
index 0000000..b871b29
--- /dev/null
+++ b/contrib/gdb/gdb/gdb_stat.h
@@ -0,0 +1,68 @@
+/* Portable <sys/stat.h>
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined(GDB_STAT_H)
+#define GDB_STAT_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISREG
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISSOCK
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
+#endif
+
+#if !defined(S_ISBLK) && defined(S_IFBLK)
+#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
+#endif
+#if !defined(S_ISCHR) && defined(S_IFCHR)
+#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
+#endif
+#if !defined(S_ISDIR) && defined(S_IFDIR)
+#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+#if !defined(S_ISREG) && defined(S_IFREG)
+#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
+#endif
+#if !defined(S_ISFIFO) && defined(S_IFIFO)
+#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
+#endif
+#if !defined(S_ISLNK) && defined(S_IFLNK)
+#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
+#endif
+#if !defined(S_ISSOCK) && defined(S_IFSOCK)
+#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
+#endif
+#if !defined(S_ISMPB) && defined(S_IFMPB) /* V7 */
+#define S_ISMPB(m) (((m) & S_IFMT) == S_IFMPB)
+#define S_ISMPC(m) (((m) & S_IFMT) == S_IFMPC)
+#endif
+#if !defined(S_ISNWK) && defined(S_IFNWK) /* HP/UX */
+#define S_ISNWK(m) (((m) & S_IFMT) == S_IFNWK)
+#endif
+
+#endif /* !defined(GDB_STAT_H) */
diff --git a/contrib/gdb/gdb/gdb_string.h b/contrib/gdb/gdb/gdb_string.h
new file mode 100644
index 0000000..4fb53bb
--- /dev/null
+++ b/contrib/gdb/gdb/gdb_string.h
@@ -0,0 +1,48 @@
+/* Portable <string.h>
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined(GDB_STRING_H)
+#define GDB_STRING_H
+
+#ifdef STDC_HEADERS
+#include <string.h>
+#else
+# ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+extern char *strchr();
+extern char *strrchr();
+extern char *strstr();
+extern char *strtok();
+extern char *strerror();
+# ifdef HAVE_MEMORY_H
+# include <memory.h>
+# else
+extern void *memset();
+extern void *memcpy();
+extern void *memmove();
+extern int memcmp();
+# endif
+#endif
+
+extern char *strdup();
+
+#endif /* !defined(GDB_STRING_H) */
diff --git a/contrib/gdb/gdb/gdba.el b/contrib/gdb/gdb/gdba.el
new file mode 100644
index 0000000..0f71586
--- /dev/null
+++ b/contrib/gdb/gdb/gdba.el
@@ -0,0 +1,2607 @@
+(defmacro gud (form)
+ (` (save-excursion (set-buffer "*gud-a.out*") (, form))))
+
+(defun dbug (foo &optional fun)
+ (save-excursion
+ (set-buffer (get-buffer-create "*trace*"))
+ (goto-char (point-max))
+ (insert "***" (symbol-name foo) "\n")
+ (if fun
+ (funcall fun))))
+
+
+;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, dbx, or xdb
+;;; under Emacs
+
+;; Author: Eric S. Raymond <esr@snark.thyrsus.com>
+;; Maintainer: FSF
+;; Version: 1.3
+;; Keywords: unix, tools
+
+;; Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; if not, write to the Free Software
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; The ancestral gdb.el was by W. Schelter <wfs@rascal.ics.utexas.edu>
+;; It was later rewritten by rms. Some ideas were due to Masanobu.
+;; Grand Unification (sdb/dbx support) by Eric S. Raymond <esr@thyrsus.com>
+;; The overloading code was then rewritten by Barry Warsaw <bwarsaw@cen.com>,
+;; who also hacked the mode to use comint.el. Shane Hartman <shane@spr.com>
+;; added support for xdb (HPUX debugger).
+
+;; Cygnus Support added support for gdb's --annotate=2.
+
+;;; Code:
+
+(require 'comint)
+(require 'etags)
+
+;; ======================================================================
+;; GUD commands must be visible in C buffers visited by GUD
+
+(defvar gud-key-prefix "\C-x\C-a"
+ "Prefix of all GUD commands valid in C buffers.")
+
+(global-set-key (concat gud-key-prefix "\C-l") 'gud-refresh)
+(global-set-key "\C-x " 'gud-break) ;; backward compatibility hack
+
+;; ======================================================================
+;; the overloading mechanism
+
+(defun gud-overload-functions (gud-overload-alist)
+ "Overload functions defined in GUD-OVERLOAD-ALIST.
+This association list has elements of the form
+ (ORIGINAL-FUNCTION-NAME OVERLOAD-FUNCTION)"
+ (mapcar
+ (function (lambda (p) (fset (car p) (symbol-function (cdr p)))))
+ gud-overload-alist))
+
+(defun gud-massage-args (file args)
+ (error "GUD not properly entered."))
+
+(defun gud-marker-filter (str)
+ (error "GUD not properly entered."))
+
+(defun gud-find-file (f)
+ (error "GUD not properly entered."))
+
+;; ======================================================================
+;; command definition
+
+;; This macro is used below to define some basic debugger interface commands.
+;; Of course you may use `gud-def' with any other debugger command, including
+;; user defined ones.
+
+;; A macro call like (gud-def FUNC NAME KEY DOC) expands to a form
+;; which defines FUNC to send the command NAME to the debugger, gives
+;; it the docstring DOC, and binds that function to KEY in the GUD
+;; major mode. The function is also bound in the global keymap with the
+;; GUD prefix.
+
+(defmacro gud-def (func cmd key &optional doc)
+ "Define FUNC to be a command sending STR and bound to KEY, with
+optional doc string DOC. Certain %-escapes in the string arguments
+are interpreted specially if present. These are:
+
+ %f name (without directory) of current source file.
+ %d directory of current source file.
+ %l number of current source line
+ %e text of the C lvalue or function-call expression surrounding point.
+ %a text of the hexadecimal address surrounding point
+ %p prefix argument to the command (if any) as a number
+
+ The `current' source file is the file of the current buffer (if
+we're in a C file) or the source file current at the last break or
+step (if we're in the GUD buffer).
+ The `current' line is that of the current buffer (if we're in a
+source file) or the source line number at the last break or step (if
+we're in the GUD buffer)."
+ (list 'progn
+ (list 'defun func '(arg)
+ (or doc "")
+ '(interactive "p")
+ (list 'gud-call cmd 'arg))
+ (if key
+ (list 'define-key
+ '(current-local-map)
+ (concat "\C-c" key)
+ (list 'quote func)))
+ (if key
+ (list 'global-set-key
+ (list 'concat 'gud-key-prefix key)
+ (list 'quote func)))))
+
+;; Where gud-display-frame should put the debugging arrow. This is
+;; set by the marker-filter, which scans the debugger's output for
+;; indications of the current program counter.
+(defvar gud-last-frame nil)
+
+;; Used by gud-refresh, which should cause gud-display-frame to redisplay
+;; the last frame, even if it's been called before and gud-last-frame has
+;; been set to nil.
+(defvar gud-last-last-frame nil)
+
+;; All debugger-specific information is collected here.
+;; Here's how it works, in case you ever need to add a debugger to the mode.
+;;
+;; Each entry must define the following at startup:
+;;
+;;<name>
+;; comint-prompt-regexp
+;; gud-<name>-massage-args
+;; gud-<name>-marker-filter
+;; gud-<name>-find-file
+;;
+;; The job of the massage-args method is to modify the given list of
+;; debugger arguments before running the debugger.
+;;
+;; The job of the marker-filter method is to detect file/line markers in
+;; strings and set the global gud-last-frame to indicate what display
+;; action (if any) should be triggered by the marker. Note that only
+;; whatever the method *returns* is displayed in the buffer; thus, you
+;; can filter the debugger's output, interpreting some and passing on
+;; the rest.
+;;
+;; The job of the find-file method is to visit and return the buffer indicated
+;; by the car of gud-tag-frame. This may be a file name, a tag name, or
+;; something else.
+
+;; ======================================================================
+;; gdb functions
+
+;;; History of argument lists passed to gdb.
+(defvar gud-gdb-history nil)
+
+(defun gud-gdb-massage-args (file args)
+ (cons "--annotate=2" (cons file args)))
+
+
+;;
+;; In this world, there are gdb instance objects (of unspecified
+;; representation) and buffers associated with those objects.
+;;
+
+;;
+;; gdb-instance objects
+;;
+
+(defun make-gdb-instance (proc)
+ "Create a gdb instance object from a gdb process."
+ (setq last-proc proc)
+ (let ((instance (cons 'gdb-instance proc)))
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (setq gdb-buffer-instance instance)
+ (progn
+ (mapcar 'make-variable-buffer-local gdb-instance-variables)
+ (setq gdb-buffer-type 'gud)
+ ;; If we're taking over the buffer of another process,
+ ;; take over it's ancillery buffers as well.
+ ;;
+ (let ((dead (or old-gdb-buffer-instance)))
+ (mapcar
+ (function
+ (lambda (b)
+ (progn
+ (set-buffer b)
+ (if (eq dead gdb-buffer-instance)
+ (setq gdb-buffer-instance instance)))))
+ (buffer-list)))))
+ instance))
+
+(defun gdb-instance-process (inst) (cdr inst))
+
+;;; The list of instance variables is built up by the expansions of
+;;; DEF-GDB-VARIABLE
+;;;
+(defvar gdb-instance-variables '()
+ "A list of variables that are local to the gud buffer associated
+with a gdb instance.")
+
+(defmacro def-gdb-variable
+ (name accessor setter &optional default doc)
+ (`
+ (progn
+ (defvar (, name) (, default) (, (or doc "undocumented")))
+ (if (not (memq '(, name) gdb-instance-variables))
+ (setq gdb-instance-variables
+ (cons '(, name) gdb-instance-variables)))
+ (, (and accessor
+ (`
+ (defun (, accessor) (instance)
+ (let
+ ((buffer (gdb-get-instance-buffer instance 'gud)))
+ (and buffer
+ (save-excursion
+ (set-buffer buffer)
+ (, name))))))))
+ (, (and setter
+ (`
+ (defun (, setter) (instance val)
+ (let
+ ((buffer (gdb-get-instance-buffer instance 'gud)))
+ (and buffer
+ (save-excursion
+ (set-buffer buffer)
+ (setq (, name) val)))))))))))
+
+(defmacro def-gdb-var (root-symbol &optional default doc)
+ (let* ((root (symbol-name root-symbol))
+ (accessor (intern (concat "gdb-instance-" root)))
+ (setter (intern (concat "set-gdb-instance-" root)))
+ (var-name (intern (concat "gdb-" root))))
+ (` (def-gdb-variable
+ (, var-name) (, accessor) (, setter)
+ (, default) (, doc)))))
+
+(def-gdb-var buffer-instance nil
+ "In an instance buffer, the buffer's instance.")
+
+(def-gdb-var buffer-type nil
+ "One of the symbols bound in gdb-instance-buffer-rules")
+
+(def-gdb-var burst ""
+ "A string of characters from gdb that have not yet been processed.")
+
+(def-gdb-var input-queue ()
+ "A list of high priority gdb command objects.")
+
+(def-gdb-var idle-input-queue ()
+ "A list of low priority gdb command objects.")
+
+(def-gdb-var prompting nil
+ "True when gdb is idle with no pending input.")
+
+(def-gdb-var output-sink 'user
+ "The disposition of the output of the current gdb command.
+Possible values are these symbols:
+
+ user -- gdb output should be copied to the gud buffer
+ for the user to see.
+
+ inferior -- gdb output should be copied to the inferior-io buffer
+
+ pre-emacs -- output should be ignored util the post-prompt
+ annotation is received. Then the output-sink
+ becomes:...
+ emacs -- output should be collected in the partial-output-buffer
+ for subsequent processing by a command. This is the
+ disposition of output generated by commands that
+ gud mode sends to gdb on its own behalf.
+ post-emacs -- ignore input until the prompt annotation is
+ received, then go to USER disposition.
+")
+
+(def-gdb-var current-item nil
+ "The most recent command item sent to gdb.")
+
+(def-gdb-var pending-triggers '()
+ "A list of trigger functions that have run later than their output
+handlers.")
+
+(defun in-gdb-instance-context (instance form)
+ "Funcall `form' in the gud buffer of `instance'"
+ (save-excursion
+ (set-buffer (gdb-get-instance-buffer instance 'gud))
+ (funcall form)))
+
+;; end of instance vars
+
+;;
+;; finding instances
+;;
+
+(defun gdb-proc->instance (proc)
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ gdb-buffer-instance))
+
+(defun gdb-mru-instance-buffer ()
+ "Return the most recently used (non-auxiliary) gdb gud buffer."
+ (save-excursion
+ (gdb-goto-first-gdb-instance (buffer-list))))
+
+(defun gdb-goto-first-gdb-instance (blist)
+ "Use gdb-mru-instance-buffer -- not this."
+ (and blist
+ (progn
+ (set-buffer (car blist))
+ (or (and gdb-buffer-instance
+ (eq gdb-buffer-type 'gud)
+ (car blist))
+ (gdb-goto-first-gdb-instance (cdr blist))))))
+
+(defun buffer-gdb-instance (buf)
+ (save-excursion
+ (set-buffer buf)
+ gdb-buffer-instance))
+
+(defun gdb-needed-default-instance ()
+ "Return the most recently used gdb instance or signal an error."
+ (let ((buffer (gdb-mru-instance-buffer)))
+ (or (and buffer (buffer-gdb-instance buffer))
+ (error "No instance of gdb found."))))
+
+(defun gdb-instance-target-string (instance)
+ "The apparent name of the program being debugged by a gdb instance.
+For sure this the root string used in smashing together the gud
+buffer's name, even if that doesn't happen to be the name of a
+program."
+ (in-gdb-instance-context
+ instance
+ (function (lambda () gud-target-name))))
+
+
+
+;;
+;; Instance Buffers.
+;;
+
+;; More than one buffer can be associated with a gdb instance.
+;;
+;; Each buffer has a TYPE -- a symbol that identifies the function
+;; of that particular buffer.
+;;
+;; The usual gud interaction buffer is given the type `gud' and
+;; is constructed specially.
+;;
+;; Others are constructed by gdb-get-create-instance-buffer and
+;; named according to the rules set forth in the gdb-instance-buffer-rules-assoc
+
+(defun gdb-get-instance-buffer (instance key)
+ "Return the instance buffer for `instance' tagged with type `key'.
+The key should be one of the cars in `gdb-instance-buffer-rules-assoc'."
+ (save-excursion
+ (gdb-look-for-tagged-buffer instance key (buffer-list))))
+
+(defun gdb-get-create-instance-buffer (instance key)
+ "Create a new gdb instance buffer of the type specified by `key'.
+The key should be one of the cars in `gdb-instance-buffer-rules-assoc'."
+ (or (gdb-get-instance-buffer instance key)
+ (let* ((rules (assoc key gdb-instance-buffer-rules-assoc))
+ (name (funcall (gdb-rules-name-maker rules) instance))
+ (new (get-buffer-create name)))
+ (save-excursion
+ (set-buffer new)
+ (make-variable-buffer-local 'gdb-buffer-type)
+ (setq gdb-buffer-type key)
+ (make-variable-buffer-local 'gdb-buffer-instance)
+ (setq gdb-buffer-instance instance)
+ (if (cdr (cdr rules))
+ (funcall (car (cdr (cdr rules)))))
+ new))))
+
+(defun gdb-rules-name-maker (rules) (car (cdr rules)))
+
+(defun gdb-look-for-tagged-buffer (instance key bufs)
+ (let ((retval nil))
+ (while (and (not retval) bufs)
+ (set-buffer (car bufs))
+ (if (and (eq gdb-buffer-instance instance)
+ (eq gdb-buffer-type key))
+ (setq retval (car bufs)))
+ (setq bufs (cdr bufs))
+ )
+ retval))
+
+(defun gdb-instance-buffer-p (buf)
+ (save-excursion
+ (set-buffer buf)
+ (and gdb-buffer-type
+ (not (eq gdb-buffer-type 'gud)))))
+
+;;
+;; This assoc maps buffer type symbols to rules. Each rule is a list of
+;; at least one and possible more functions. The functions have these
+;; roles in defining a buffer type:
+;;
+;; NAME - take an instance, return a name for this type buffer for that
+;; instance.
+;; The remaining function(s) are optional:
+;;
+;; MODE - called in new new buffer with no arguments, should establish
+;; the proper mode for the buffer.
+;;
+
+(defvar gdb-instance-buffer-rules-assoc '())
+
+(defun gdb-set-instance-buffer-rules (buffer-type &rest rules)
+ (let ((binding (assoc buffer-type gdb-instance-buffer-rules-assoc)))
+ (if binding
+ (setcdr binding rules)
+ (setq gdb-instance-buffer-rules-assoc
+ (cons (cons buffer-type rules)
+ gdb-instance-buffer-rules-assoc)))))
+
+(gdb-set-instance-buffer-rules 'gud 'error) ; gud buffers are an exception to the rules
+
+;;
+;; partial-output buffers
+;;
+;; These accumulate output from a command executed on
+;; behalf of emacs (rather than the user).
+;;
+
+(gdb-set-instance-buffer-rules 'gdb-partial-output-buffer
+ 'gdb-partial-output-name)
+
+(defun gdb-partial-output-name (instance)
+ (concat "*partial-output-"
+ (gdb-instance-target-string instance)
+ "*"))
+
+
+(gdb-set-instance-buffer-rules 'gdb-inferior-io
+ 'gdb-inferior-io-name
+ 'gud-inferior-io-mode)
+
+(defun gdb-inferior-io-name (instance)
+ (concat "*input/output of "
+ (gdb-instance-target-string instance)
+ "*"))
+
+(defvar gdb-inferior-io-mode-map (copy-keymap comint-mode-map))
+(define-key comint-mode-map "\C-c\C-c" 'gdb-inferior-io-interrupt)
+(define-key comint-mode-map "\C-c\C-z" 'gdb-inferior-io-stop)
+(define-key comint-mode-map "\C-c\C-\\" 'gdb-inferior-io-quit)
+(define-key comint-mode-map "\C-c\C-d" 'gdb-inferior-io-eof)
+
+(defun gud-inferior-io-mode ()
+ "Major mode for gud inferior-io.
+
+\\{comint-mode-map}"
+ ;; We want to use comint because it has various nifty and familiar
+ ;; features. We don't need a process, but comint wants one, so create
+ ;; a dummy one.
+ (make-comint (substring (buffer-name) 1 (- (length (buffer-name)) 1))
+ "/bin/cat")
+ (setq major-mode 'gud-inferior-io-mode)
+ (setq mode-name "Debuggee I/O")
+ (setq comint-input-sender 'gud-inferior-io-sender)
+)
+
+(defun gud-inferior-io-sender (proc string)
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (let ((instance gdb-buffer-instance))
+ (set-buffer (gdb-get-instance-buffer instance 'gud))
+ (let ((gud-proc (get-buffer-process (current-buffer))))
+ (process-send-string gud-proc string)
+ (process-send-string gud-proc "\n")
+ ))
+ ))
+
+(defun gdb-inferior-io-interrupt (instance)
+ "Interrupt the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (interrupt-process
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp))
+
+(defun gdb-inferior-io-quit (instance)
+ "Send quit signal to the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (quit-process
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp))
+
+(defun gdb-inferior-io-stop (instance)
+ "Stop the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (stop-process
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud)) comint-ptyp))
+
+(defun gdb-inferior-io-eof (instance)
+ "Send end-of-file to the program being debugged."
+ (interactive (list (gdb-needed-default-instance)))
+ (process-send-eof
+ (get-buffer-process (gdb-get-instance-buffer instance 'gud))))
+
+
+;;
+;; gdb communications
+;;
+
+;; INPUT: things sent to gdb
+;;
+;; Each instance has a high and low priority
+;; input queue. Low priority input is sent only
+;; when the high priority queue is idle.
+;;
+;; The queues are lists. Each element is either
+;; a string (indicating user or user-like input)
+;; or a list of the form:
+;;
+;; (INPUT-STRING HANDLER-FN)
+;;
+;;
+;; The handler function will be called from the
+;; partial-output buffer when the command completes.
+;; This is the way to write commands which
+;; invoke gdb commands autonomously.
+;;
+;; These lists are consumed tail first.
+;;
+
+(defun gdb-send (proc string)
+ "A comint send filter for gdb.
+This filter may simply queue output for a later time."
+ (let ((instance (gdb-proc->instance proc)))
+ (gdb-instance-enqueue-input instance (concat string "\n"))))
+
+;; Note: Stuff enqueued here will be sent to the next prompt, even if it
+;; is a query, or other non-top-level prompt. To guarantee stuff will get
+;; sent to the top-level prompt, currently it must be put in the idle queue.
+;; ^^^^^^^^^
+;; [This should encourage gud extentions that invoke gdb commands to let
+;; the user go first; it is not a bug. -t]
+;;
+
+(defun gdb-instance-enqueue-input (instance item)
+ (if (gdb-instance-prompting instance)
+ (progn
+ (gdb-send-item instance item)
+ (set-gdb-instance-prompting instance nil))
+ (set-gdb-instance-input-queue
+ instance
+ (cons item (gdb-instance-input-queue instance)))))
+
+(defun gdb-instance-dequeue-input (instance)
+ (let ((queue (gdb-instance-input-queue instance)))
+ (and queue
+ (if (not (cdr queue))
+ (let ((answer (car queue)))
+ (set-gdb-instance-input-queue instance '())
+ answer)
+ (gdb-take-last-elt queue)))))
+
+(defun gdb-instance-enqueue-idle-input (instance item)
+ (if (and (gdb-instance-prompting instance)
+ (not (gdb-instance-input-queue instance)))
+ (progn
+ (gdb-send-item instance item)
+ (set-gdb-instance-prompting instance nil))
+ (set-gdb-instance-idle-input-queue
+ instance
+ (cons item (gdb-instance-idle-input-queue instance)))))
+
+(defun gdb-instance-dequeue-idle-input (instance)
+ (let ((queue (gdb-instance-idle-input-queue instance)))
+ (and queue
+ (if (not (cdr queue))
+ (let ((answer (car queue)))
+ (set-gdb-instance-idle-input-queue instance '())
+ answer)
+ (gdb-take-last-elt queue)))))
+
+; Don't use this in general.
+(defun gdb-take-last-elt (l)
+ (if (cdr (cdr l))
+ (gdb-take-last-elt (cdr l))
+ (let ((answer (car (cdr l))))
+ (setcdr l '())
+ answer)))
+
+
+;;
+;; output -- things gdb prints to emacs
+;;
+;; GDB output is a stream interrupted by annotations.
+;; Annotations can be recognized by their beginning
+;; with \C-j\C-z\C-z<tag><opt>\C-j
+;;
+;; The tag is a string obeying symbol syntax.
+;;
+;; The optional part `<opt>' can be either the empty string
+;; or a space followed by more data relating to the annotation.
+;; For example, the SOURCE annotation is followed by a filename,
+;; line number and various useless goo. This data must not include
+;; any newlines.
+;;
+
+
+(defun gud-gdb-marker-filter (string)
+ "A gud marker filter for gdb."
+ ;; Bogons don't tell us the process except through scoping crud.
+ (let ((instance (gdb-proc->instance proc)))
+ (gdb-output-burst instance string)))
+
+(defvar gdb-annotation-rules
+ '(("frames-invalid" gdb-invalidate-frames)
+ ("breakpoints-invalid" gdb-invalidate-breakpoints)
+ ("pre-prompt" gdb-pre-prompt)
+ ("prompt" gdb-prompt)
+ ("commands" gdb-subprompt)
+ ("overload-choice" gdb-subprompt)
+ ("query" gdb-subprompt)
+ ("prompt-for-continue" gdb-subprompt)
+ ("post-prompt" gdb-post-prompt)
+ ("source" gdb-source)
+ ("starting" gdb-starting)
+ ("exited" gdb-stopping)
+ ("signalled" gdb-stopping)
+ ("signal" gdb-stopping)
+ ("breakpoint" gdb-stopping)
+ ("watchpoint" gdb-stopping)
+ ("stopped" gdb-stopped)
+ )
+ "An assoc mapping annotation tags to functions which process them.")
+
+
+(defun gdb-ignore-annotation (instance args)
+ nil)
+
+(defconst gdb-source-spec-regexp
+ "\\(.*\\):\\([0-9]*\\):[0-9]*:[a-z]*:0x[a-f0-9]*")
+
+;; Do not use this except as an annotation handler."
+(defun gdb-source (instance args)
+ (string-match gdb-source-spec-regexp args)
+ ;; Extract the frame position from the marker.
+ (setq gud-last-frame
+ (cons
+ (substring args (match-beginning 1) (match-end 1))
+ (string-to-int (substring args
+ (match-beginning 2)
+ (match-end 2))))))
+
+;; An annotation handler for `prompt'.
+;; This sends the next command (if any) to gdb.
+(defun gdb-prompt (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) t)
+ ((eq sink 'post-emacs)
+ (set-gdb-instance-output-sink instance 'user))
+ (t
+ (set-gdb-instance-output-sink instance 'user)
+ (error "Phase error in gdb-prompt (got %s)" sink))))
+ (let ((highest (gdb-instance-dequeue-input instance)))
+ (if highest
+ (gdb-send-item instance highest)
+ (let ((lowest (gdb-instance-dequeue-idle-input instance)))
+ (if lowest
+ (gdb-send-item instance lowest)
+ (progn
+ (set-gdb-instance-prompting instance t)
+ (gud-display-frame)))))))
+
+;; An annotation handler for non-top-level prompts.
+(defun gdb-subprompt (instance ignored)
+ (let ((highest (gdb-instance-dequeue-input instance)))
+ (if highest
+ (gdb-send-item instance highest)
+ (set-gdb-instance-prompting instance t))))
+
+(defun gdb-send-item (instance item)
+ (set-gdb-instance-current-item instance item)
+ (if (stringp item)
+ (progn
+ (set-gdb-instance-output-sink instance 'user)
+ (process-send-string (gdb-instance-process instance)
+ item))
+ (progn
+ (gdb-clear-partial-output instance)
+ (set-gdb-instance-output-sink instance 'pre-emacs)
+ (process-send-string (gdb-instance-process instance)
+ (car item)))))
+
+;; An annotation handler for `pre-prompt'.
+;; This terminates the collection of output from a previous
+;; command if that happens to be in effect.
+(defun gdb-pre-prompt (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) t)
+ ((eq sink 'emacs)
+ (set-gdb-instance-output-sink instance 'post-emacs)
+ (let ((handler
+ (car (cdr (gdb-instance-current-item instance)))))
+ (save-excursion
+ (set-buffer (gdb-get-create-instance-buffer
+ instance 'gdb-partial-output-buffer))
+ (funcall handler))))
+ (t
+ (set-gdb-instance-output-sink instance 'user)
+ (error "Output sink phase error 1.")))))
+
+;; An annotation handler for `starting'. This says that I/O for the subprocess
+;; is now the program being debugged, not GDB.
+(defun gdb-starting (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user)
+ (set-gdb-instance-output-sink instance 'inferior)
+ ;; FIXME: need to send queued input
+ )
+ (t (error "Unexpected `starting' annotation")))))
+
+;; An annotation handler for `exited' and other annotations which say that
+;; I/O for the subprocess is now GDB, not the program being debugged.
+(defun gdb-stopping (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'inferior)
+ (set-gdb-instance-output-sink instance 'user)
+ )
+ (t (error "Unexpected stopping annotation")))))
+
+;; An annotation handler for `stopped'. It is just like gdb-stopping, except
+;; that if we already set the output sink to 'user in gdb-stopping, that is
+;; fine.
+(defun gdb-stopped (instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'inferior)
+ (set-gdb-instance-output-sink instance 'user)
+ )
+ ((eq sink 'user)
+ t)
+ (t (error "Unexpected stopping annotation")))))
+
+;; An annotation handler for `post-prompt'.
+;; This begins the collection of output from the current
+;; command if that happens to be appropriate."
+(defun gdb-post-prompt (instance ignored)
+ (gdb-invalidate-registers instance ignored)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) t)
+ ((eq sink 'pre-emacs)
+ (set-gdb-instance-output-sink instance 'emacs))
+
+ (t
+ (set-gdb-instance-output-sink instance 'user)
+ (error "Output sink phase error 3.")))))
+
+;; Handle a burst of output from a gdb instance.
+;; This function is (indirectly) used as a gud-marker-filter.
+;; It must return output (if any) to be insterted in the gud
+;; buffer.
+
+(defun gdb-output-burst (instance string)
+ "Handle a burst of output from a gdb instance.
+This function is (indirectly) used as a gud-marker-filter.
+It must return output (if any) to be insterted in the gud
+buffer."
+
+ (save-match-data
+ (let (
+ ;; Recall the left over burst from last time
+ (burst (concat (gdb-instance-burst instance) string))
+ ;; Start accumulating output for the gud buffer
+ (output ""))
+
+ ;; Process all the complete markers in this chunk.
+
+ (while (string-match "\n\032\032\\(.*\\)\n" burst)
+ (let ((annotation (substring burst
+ (match-beginning 1)
+ (match-end 1))))
+
+ ;; Stuff prior to the match is just ordinary output.
+ ;; It is either concatenated to OUTPUT or directed
+ ;; elsewhere.
+ (setq output
+ (gdb-concat-output
+ instance
+ output
+ (substring burst 0 (match-beginning 0))))
+
+ ;; Take that stuff off the burst.
+ (setq burst (substring burst (match-end 0)))
+
+ ;; Parse the tag from the annotation, and maybe its arguments.
+ (string-match "\\(\\S-*\\) ?\\(.*\\)" annotation)
+ (let* ((annotation-type (substring annotation
+ (match-beginning 1)
+ (match-end 1)))
+ (annotation-arguments (substring annotation
+ (match-beginning 2)
+ (match-end 2)))
+ (annotation-rule (assoc annotation-type
+ gdb-annotation-rules)))
+ ;; Call the handler for this annotation.
+ (if annotation-rule
+ (funcall (car (cdr annotation-rule))
+ instance
+ annotation-arguments)
+ ;; Else the annotation is not recognized. Ignore it silently,
+ ;; so that GDB can add new annotations without causing
+ ;; us to blow up.
+ ))))
+
+
+ ;; Does the remaining text end in a partial line?
+ ;; If it does, then keep part of the burst until we get more.
+ (if (string-match "\n\\'\\|\n\032\\'\\|\n\032\032.*\\'"
+ burst)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output
+ (gdb-concat-output
+ instance
+ output
+ (substring burst 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq burst (substring burst (match-beginning 0))))
+
+ ;; In case we know the burst contains no partial annotations:
+ (progn
+ (setq output (gdb-concat-output instance output burst))
+ (setq burst "")))
+
+ ;; Save the remaining burst for the next call to this function.
+ (set-gdb-instance-burst instance burst)
+ output)))
+
+(defun gdb-concat-output (instance so-far new)
+ (let ((sink (gdb-instance-output-sink instance)))
+ (cond
+ ((eq sink 'user) (concat so-far new))
+ ((or (eq sink 'pre-emacs) (eq sink 'post-emacs)) so-far)
+ ((eq sink 'emacs)
+ (gdb-append-to-partial-output instance new)
+ so-far)
+ ((eq sink 'inferior)
+ (gdb-append-to-inferior-io instance new)
+ so-far)
+ (t (error "Bogon output sink %S" sink)))))
+
+(defun gdb-append-to-partial-output (instance string)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-partial-output-buffer))
+ (goto-char (point-max))
+ (insert string)))
+
+(defun gdb-clear-partial-output (instance)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-partial-output-buffer))
+ (delete-region (point-min) (point-max))))
+
+(defun gdb-append-to-inferior-io (instance string)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-inferior-io))
+ (goto-char (point-max))
+ (insert-before-markers string))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-inferior-io)))
+
+(defun gdb-clear-inferior-io (instance)
+ (save-excursion
+ (set-buffer
+ (gdb-get-create-instance-buffer
+ instance 'gdb-inferior-io))
+ (delete-region (point-min) (point-max))))
+
+
+
+;; One trick is to have a command who's output is always available in
+;; a buffer of it's own, and is always up to date. We build several
+;; buffers of this type.
+;;
+;; There are two aspects to this: gdb has to tell us when the output
+;; for that command might have changed, and we have to be able to run
+;; the command behind the user's back.
+;;
+;; The idle input queue and the output phasing associated with
+;; the instance variable `(gdb-instance-output-sink instance)' help
+;; us to run commands behind the user's back.
+;;
+;; Below is the code for specificly managing buffers of output from one
+;; command.
+;;
+
+
+;; The trigger function is suitable for use in the assoc GDB-ANNOTATION-RULES
+;; It adds an idle input for the command we are tracking. It should be the
+;; annotation rule binding of whatever gdb sends to tell us this command
+;; might have changed it's output.
+;;
+;; NAME is the fucntion name. DEMAND-PREDICATE tests if output is really needed.
+;; GDB-COMMAND is a string of such. OUTPUT-HANDLER is the function bound to the
+;; input in the input queue (see comment about ``gdb communications'' above).
+(defmacro def-gdb-auto-update-trigger (name demand-predicate gdb-command output-handler)
+ (`
+ (defun (, name) (instance &optional ignored)
+ (if (and ((, demand-predicate) instance)
+ (not (member '(, name)
+ (gdb-instance-pending-triggers instance))))
+ (progn
+ (gdb-instance-enqueue-idle-input
+ instance
+ (list (, gdb-command) '(, output-handler)))
+ (set-gdb-instance-pending-triggers
+ instance
+ (cons '(, name)
+ (gdb-instance-pending-triggers instance))))))))
+
+(defmacro def-gdb-auto-update-handler (name trigger buf-key)
+ (`
+ (defun (, name) ()
+ (set-gdb-instance-pending-triggers
+ instance
+ (delq '(, trigger)
+ (gdb-instance-pending-triggers instance)))
+ (let ((buf (gdb-get-instance-buffer instance
+ '(, buf-key))))
+ (and buf
+ (save-excursion
+ (set-buffer buf)
+ (let ((p (point))
+ (buffer-read-only nil))
+ (delete-region (point-min) (point-max))
+ (insert-buffer (gdb-get-create-instance-buffer
+ instance
+ 'gdb-partial-output-buffer))
+ (goto-char p))))))))
+
+(defmacro def-gdb-auto-updated-buffer
+ (buffer-key trigger-name gdb-command output-handler-name)
+ (`
+ (progn
+ (def-gdb-auto-update-trigger (, trigger-name)
+ ;; The demand predicate:
+ (lambda (instance)
+ (gdb-get-instance-buffer instance '(, buffer-key)))
+ (, gdb-command)
+ (, output-handler-name))
+ (def-gdb-auto-update-handler (, output-handler-name)
+ (, trigger-name) (, buffer-key)))))
+
+
+
+;;
+;; Breakpoint buffers
+;;
+;; These display the output of `info breakpoints'.
+;;
+
+
+(gdb-set-instance-buffer-rules 'gdb-breakpoints-buffer
+ 'gdb-breakpoints-buffer-name
+ 'gud-breakpoints-mode)
+
+(def-gdb-auto-updated-buffer gdb-breakpoints-buffer
+ ;; This defines the auto update rule for buffers of type
+ ;; `gdb-breakpoints-buffer'.
+ ;;
+ ;; It defines a function to serve as the annotation handler that
+ ;; handles the `foo-invalidated' message. That function is called:
+ gdb-invalidate-breakpoints
+
+ ;; To update the buffer, this command is sent to gdb.
+ "server info breakpoints\n"
+
+ ;; This also defines a function to be the handler for the output
+ ;; from the command above. That function will copy the output into
+ ;; the appropriately typed buffer. That function will be called:
+ gdb-info-breakpoints-handler)
+
+(defun gdb-breakpoints-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*breakpoints of " (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-breakpoints-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-breakpoints-buffer)))
+
+(defun gud-frame-breakpoints-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-breakpoints-buffer)))
+
+(defvar gud-breakpoints-mode-map nil)
+(setq gud-breakpoints-mode-map (make-keymap))
+(suppress-keymap gud-breakpoints-mode-map)
+(define-key gud-breakpoints-mode-map " " 'gud-toggle-bp-this-line)
+(define-key gud-breakpoints-mode-map "d" 'gud-delete-bp-this-line)
+
+(defun gud-breakpoints-mode ()
+ "Major mode for gud breakpoints.
+
+\\{gud-breakpoints-mode-map}"
+ (setq major-mode 'gud-breakpoints-mode)
+ (setq mode-name "Breakpoints")
+ (use-local-map gud-breakpoints-mode-map)
+ (setq buffer-read-only t)
+ (gdb-invalidate-breakpoints gdb-buffer-instance))
+
+(defun gud-toggle-bp-this-line ()
+ (interactive)
+ (save-excursion
+ (beginning-of-line 1)
+ (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)"))
+ (error "Not recognized as breakpoint line (demo foo).")
+ (gdb-instance-enqueue-idle-input
+ gdb-buffer-instance
+ (list
+ (concat
+ (if (eq ?y (char-after (match-beginning 2)))
+ "server disable "
+ "server enable ")
+ (buffer-substring (match-beginning 0)
+ (match-end 1))
+ "\n")
+ '(lambda () nil)))
+ )))
+
+(defun gud-delete-bp-this-line ()
+ (interactive)
+ (save-excursion
+ (beginning-of-line 1)
+ (if (not (looking-at "\\([0-9]*\\)\\s-*\\S-*\\s-*\\S-*\\s-*\\(.\\)"))
+ (error "Not recognized as breakpoint line (demo foo).")
+ (gdb-instance-enqueue-idle-input
+ gdb-buffer-instance
+ (list
+ (concat
+ "server delete "
+ (buffer-substring (match-beginning 0)
+ (match-end 1))
+ "\n")
+ '(lambda () nil)))
+ )))
+
+
+
+
+;;
+;; Frames buffers. These display a perpetually correct bactracktrace
+;; (from the command `where').
+;;
+;; Alas, if your stack is deep, they are costly.
+;;
+
+(gdb-set-instance-buffer-rules 'gdb-stack-buffer
+ 'gdb-stack-buffer-name
+ 'gud-frames-mode)
+
+(def-gdb-auto-updated-buffer gdb-stack-buffer
+ gdb-invalidate-frames
+ "server where\n"
+ gdb-info-frames-handler)
+
+(defun gdb-stack-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*stack frames of "
+ (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-stack-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-stack-buffer)))
+
+(defun gud-frame-stack-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-stack-buffer)))
+
+(defvar gud-frames-mode-map nil)
+(setq gud-frames-mode-map (make-keymap))
+(suppress-keymap gud-frames-mode-map)
+(define-key gud-frames-mode-map [mouse-2]
+ 'gud-frames-select-by-mouse)
+
+(defun gud-frames-mode ()
+ "Major mode for gud frames.
+
+\\{gud-frames-mode-map}"
+ (setq major-mode 'gud-frames-mode)
+ (setq mode-name "Frames")
+ (setq buffer-read-only t)
+ (use-local-map gud-frames-mode-map)
+ (gdb-invalidate-frames gdb-buffer-instance))
+
+(defun gud-get-frame-number ()
+ (save-excursion
+ (let* ((pos (re-search-backward "^#\\([0-9]*\\)" nil t))
+ (n (or (and pos
+ (string-to-int
+ (buffer-substring (match-beginning 1)
+ (match-end 1))))
+ 0)))
+ n)))
+
+(defun gud-frames-select-by-mouse (e)
+ (interactive "e")
+ (let (selection)
+ (save-excursion
+ (set-buffer (window-buffer (posn-window (event-end e))))
+ (save-excursion
+ (goto-char (posn-point (event-end e)))
+ (setq selection (gud-get-frame-number))))
+ (select-window (posn-window (event-end e)))
+ (save-excursion
+ (set-buffer (gdb-get-instance-buffer (gdb-needed-default-instance) 'gud))
+ (gud-call "fr %p" selection)
+ (gud-display-frame))))
+
+
+;;
+;; Registers buffers
+;;
+
+(def-gdb-auto-updated-buffer gdb-registers-buffer
+ gdb-invalidate-registers
+ "server info registers\n"
+ gdb-info-registers-handler)
+
+(gdb-set-instance-buffer-rules 'gdb-registers-buffer
+ 'gdb-registers-buffer-name
+ 'gud-registers-mode)
+
+(defvar gud-registers-mode-map nil)
+(setq gud-registers-mode-map (make-keymap))
+(suppress-keymap gud-registers-mode-map)
+
+(defun gud-registers-mode ()
+ "Major mode for gud registers.
+
+\\{gud-registers-mode-map}"
+ (setq major-mode 'gud-registers-mode)
+ (setq mode-name "Registers")
+ (setq buffer-read-only t)
+ (use-local-map gud-registers-mode-map)
+ (gdb-invalidate-registers gdb-buffer-instance))
+
+(defun gdb-registers-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*registers of " (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-registers-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-registers-buffer)))
+
+(defun gud-frame-registers-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-registers-buffer)))
+
+
+
+;;;; Menu windows:
+
+
+;; MENU-LIST is ((option option option...) (option option ...)...)
+;;
+(defun gud-display-menu (menu-list)
+ (setq fill-column (min 120 (- (window-width)
+ (min 8 (window-width)))))
+ (while menu-list
+ (mapcar (function (lambda (x) (insert (symbol-name x) " "))) (car menu-list))
+ (fill-paragraph nil)
+ (insert "\n\n")
+ (setq menu-list (cdr menu-list)))
+ (goto-char (point-min))
+ (while (re-search-forward "\\([^ \n]+\\)\\(\n\\| \\)" nil t)
+ (put-text-property (match-beginning 1) (match-end 1)
+ 'mouse-face 'highlight))
+ (goto-char (point-min)))
+
+(defun gud-goto-menu (menu)
+ (setq gud-menu-position menu)
+ (let ((buffer-read-only nil))
+ (delete-region (point-min) (point-max))
+ (gud-display-menu menu)))
+
+(defun gud-menu-pick (event)
+ "Choose an item from a gdb command menu."
+ (interactive "e")
+ (let (choice)
+ (save-excursion
+ (set-buffer (window-buffer (posn-window (event-start event))))
+ (goto-char (posn-point (event-start event)))
+ (let (beg end)
+ (skip-chars-forward "^ \t\n")
+ (setq end (point))
+ (skip-chars-backward "^ \t\n")
+ (setq beg (point))
+ (setq choice (buffer-substring beg end))
+ (message choice)
+ (gud-invoke-menu (intern choice))))))
+
+(defun gud-invoke-menu (symbol)
+ (let ((meaning (assoc symbol gud-menu-rules)))
+ (cond
+ ((and (consp meaning)
+ (consp (car (cdr meaning))))
+ (gud-goto-menu (car (cdr meaning))))
+ (meaning (call-interactively (car (cdr meaning)))))))
+
+
+
+(gdb-set-instance-buffer-rules 'gdb-command-buffer
+ 'gdb-command-buffer-name
+ 'gud-command-mode)
+
+(defvar gud-command-mode-map nil)
+(setq gud-command-mode-map (make-keymap))
+(suppress-keymap gud-command-mode-map)
+(define-key gud-command-mode-map [mouse-2] 'gud-menu-pick)
+
+(defun gud-command-mode ()
+ "Major mode for gud menu.
+
+\\{gud-command-mode-map}" (interactive) (setq major-mode 'gud-command-mode)
+ (setq mode-name "Menu") (setq buffer-read-only t) (use-local-map
+ gud-command-mode-map) (make-variable-buffer-local 'gud-menu-position)
+ (if (not gud-menu-position) (gud-goto-menu gud-running-menu)))
+
+(defun gdb-command-buffer-name (instance)
+ (save-excursion
+ (set-buffer (process-buffer (gdb-instance-process instance)))
+ (concat "*menu of " (gdb-instance-target-string instance) "*")))
+
+(defun gud-display-command-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-command-buffer)
+ 6))
+
+(defun gud-frame-command-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance
+ 'gdb-command-buffer)))
+
+(defvar gud-selected-menu-titles ())
+(setq gud-selected-menu-titles
+ '(RUNNING STACK DATA BREAKPOINTS FILES))
+
+(setq gud-running-menu
+ (list
+ '(RUNNING stack breakpoints files)
+ '(target run next step continue finish stepi kill help-running)))
+
+(setq gud-stack-menu
+ (list
+ '(running STACK breakpoints files)
+ '(up down frame backtrace return help-stack)))
+
+(setq gud-data-menu
+ (list
+ '(running stack DATA breakpoints files)
+ '(whatis ptype print set display undisplay disassemble help-data)))
+
+(setq gud-breakpoints-menu
+ (list
+ '(running stack BREAKPOINTS files)
+ '(awatch rwatch watch break delete enable disable condition ignore help-breakpoints)))
+
+(setq gud-files-menu
+ (list
+ '(running stack breakpoints FILES)
+ '(file core-file help-files)
+ '(exec-file load symbol-file add-symbol-file sharedlibrary)))
+
+(setq gud-menu-rules
+ (list
+ (list 'running gud-running-menu)
+ (list 'RUNNING gud-running-menu)
+ (list 'stack gud-stack-menu)
+ (list 'STACK gud-stack-menu)
+ (list 'data gud-data-menu)
+ (list 'DATA gud-data-menu)
+ (list 'breakpoints gud-breakpoints-menu)
+ (list 'BREAKPOINTS gud-breakpoints-menu)
+ (list 'files gud-files-menu)
+ (list 'FILES gud-files-menu)
+
+ (list 'target 'gud-target)
+ (list 'kill 'gud-kill)
+ (list 'stepi 'gud-stepi)
+ (list 'step 'gud-step)
+ (list 'next 'gud-next)
+ (list 'finish 'gud-finish)
+ (list 'continue 'gud-cont)
+ (list 'run 'gud-run)
+
+ (list 'backtrace 'gud-backtrace)
+ (list 'frame 'gud-frame)
+ (list 'down 'gud-down)
+ (list 'up 'gud-up)
+ (list 'return 'gud-return)
+
+ (list 'file 'gud-file)
+ (list 'core-file 'gud-core-file)
+ (list 'cd 'gud-cd)
+
+ (list 'exec-file 'gud-exec-file)
+ (list 'load 'gud-load)
+ (list 'symbol-file 'gud-symbol-file)
+ (list 'add-symbol-file 'gud-add-symbol-file)
+ (list 'sharedlibrary 'gud-sharedlibrary)
+ ))
+
+
+
+
+(defun gdb-call-showing-gud (instance command)
+ (gud-display-gud-buffer instance)
+ (comint-input-sender (gdb-instance-process instance) command))
+
+(defvar gud-target-history ())
+
+(defun gud-temp-buffer-show (buf)
+ (let ((ow (selected-window)))
+ (unwind-protect
+ (progn
+ (pop-to-buffer buf)
+
+ ;; This insertion works around a bug in emacs.
+ ;; The bug is that all the empty space after a
+ ;; highlighted word that terminates a buffer
+ ;; gets highlighted. That's really ugly, so
+ ;; make sure a highlighted word can't ever
+ ;; terminate the buffer.
+ (goto-char (point-max))
+ (insert "\n")
+ (goto-char (point-min))
+
+ (if (< (window-height) 10)
+ (enlarge-window (- 10 (window-height)))))
+ (select-window ow))))
+
+(defun gud-target (instance command)
+ (interactive
+ (let* ((instance (gdb-needed-default-instance))
+ (temp-buffer-show-function (function gud-temp-buffer-show))
+ (target-name (completing-read (format "Target type: ")
+ '(("remote")
+ ("core")
+ ("child")
+ ("exec"))
+ nil
+ t
+ nil
+ 'gud-target-history)))
+ (list instance
+ (cond
+ ((equal target-name "child") "run")
+
+ ((equal target-name "core")
+ (concat "target core "
+ (read-file-name "core file: "
+ nil
+ "core"
+ t)))
+
+ ((equal target-name "exec")
+ (concat "target exec "
+ (read-file-name "exec file: "
+ nil
+ "a.out"
+ t)))
+
+ ((equal target-name "remote")
+ (concat "target remote "
+ (read-file-name "serial line for remote: "
+ "/dev/"
+ "ttya"
+ t)))
+
+ (t "echo No such target command!")))))
+
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-backtrace ()
+ (interactive)
+ (let ((instance (gdb-needed-default-instance)))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance)
+ "backtrace"))))
+
+(defun gud-frame ()
+ (interactive)
+ (let ((instance (gdb-needed-default-instance)))
+ (apply comint-input-sender
+ (list (gdb-instance-process instance)
+ "frame"))))
+
+(defun gud-return (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "return " (read-string "Expression to return: ")))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+(defun gud-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "file " (read-file-name "Executable to debug: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-core-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "core " (read-file-name "Core file to debug: "
+ nil
+ "core-file"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-cd (dir)
+ (interactive "FChange GDB's default directory: ")
+ (let ((instance (gdb-needed-default-instance)))
+ (save-excursion
+ (set-buffer (gdb-get-instance-buffer instance 'gud))
+ (cd dir))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance)
+ (concat "cd " dir)))))
+
+
+(defun gud-exec-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "exec-file " (read-file-name "Init memory from executable: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-load (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "load " (read-file-name "Dynamicly load from file: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+(defun gud-symbol-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "symbol-file " (read-file-name "Read symbol table from file: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+(defun gud-add-symbol-file (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "add-symbol-file "
+ (read-file-name "Add symbols from file: "
+ nil
+ "a.out"
+ t)))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+(defun gud-sharedlibrary (instance command)
+ (interactive
+ (let ((temp-buffer-show-function (function gud-temp-buffer-show)))
+ (list (gdb-needed-default-instance)
+ (concat "sharedlibrary "
+ (read-string "Load symbols for files matching regexp: ")))))
+ (gud-display-gud-buffer instance)
+ (apply comint-input-sender
+ (list (gdb-instance-process instance) command)))
+
+
+
+
+
+;;;; Window management
+
+
+;;; FIXME: This should only return true for buffers in the current instance
+(defun gud-protected-buffer-p (buffer)
+ "Is BUFFER a buffer which we want to leave displayed?"
+ (save-excursion
+ (set-buffer buffer)
+ (or gdb-buffer-type
+ overlay-arrow-position)))
+
+;;; The way we abuse the dedicated-p flag is pretty gross, but seems
+;;; to do the right thing. Seeing as there is no way for Lisp code to
+;;; get at the use_time field of a window, I'm not sure there exists a
+;;; more elegant solution without writing C code.
+
+(defun gud-display-buffer (buf &optional size)
+ (let ((must-split nil)
+ (answer nil))
+ (unwind-protect
+ (progn
+ (walk-windows
+ '(lambda (win)
+ (if (gud-protected-buffer-p (window-buffer win))
+ (set-window-dedicated-p win t))))
+ (setq answer (get-buffer-window buf))
+ (if (not answer)
+ (let ((window (get-lru-window)))
+ (if window
+ (progn
+ (set-window-buffer window buf)
+ (setq answer window))
+ (setq must-split t)))))
+ (walk-windows
+ '(lambda (win)
+ (if (gud-protected-buffer-p (window-buffer win))
+ (set-window-dedicated-p win nil)))))
+ (if must-split
+ (let* ((largest (get-largest-window))
+ (cur-size (window-height largest))
+ (new-size (and size (< size cur-size) (- cur-size size))))
+ (setq answer (split-window largest new-size))
+ (set-window-buffer answer buf)))
+ answer))
+
+(defun existing-source-window (buffer)
+ (catch 'found
+ (save-excursion
+ (walk-windows
+ (function
+ (lambda (win)
+ (if (and overlay-arrow-position
+ (eq (window-buffer win)
+ (marker-buffer overlay-arrow-position)))
+ (progn
+ (set-window-buffer win buffer)
+ (throw 'found win))))))
+ nil)))
+
+(defun gud-display-source-buffer (buffer)
+ (or (existing-source-window buffer)
+ (gud-display-buffer buffer)))
+
+(defun gud-frame-buffer (buf)
+ (save-excursion
+ (set-buffer buf)
+ (make-frame)))
+
+
+
+;;; Shared keymap initialization:
+
+(defun make-windows-menu (map)
+ (define-key map [menu-bar displays]
+ (cons "GDB-Windows" (make-sparse-keymap "GDB-Windows")))
+ (define-key map [menu-bar displays gdb]
+ '("Gdb" . gud-display-gud-buffer))
+ (define-key map [menu-bar displays registers]
+ '("Registers" . gud-display-registers-buffer))
+ (define-key map [menu-bar displays frames]
+ '("Stack" . gud-display-stack-buffer))
+ (define-key map [menu-bar displays breakpoints]
+ '("Breakpoints" . gud-display-breakpoints-buffer))
+ (define-key map [menu-bar displays commands]
+ '("Commands" . gud-display-command-buffer)))
+
+(defun gud-display-gud-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-display-buffer
+ (gdb-get-create-instance-buffer instance 'gud)))
+
+(make-windows-menu gud-breakpoints-mode-map)
+(make-windows-menu gud-frames-mode-map)
+(make-windows-menu gud-registers-mode-map)
+
+
+
+(defun make-frames-menu (map)
+ (define-key map [menu-bar frames]
+ (cons "GDB-Frames" (make-sparse-keymap "GDB-Frames")))
+ (define-key map [menu-bar frames gdb]
+ '("Gdb" . gud-frame-gud-buffer))
+ (define-key map [menu-bar frames registers]
+ '("Registers" . gud-frame-registers-buffer))
+ (define-key map [menu-bar frames frames]
+ '("Stack" . gud-frame-stack-buffer))
+ (define-key map [menu-bar frames breakpoints]
+ '("Breakpoints" . gud-frame-breakpoints-buffer))
+ (define-key map [menu-bar displays commands]
+ '("Commands" . gud-display-command-buffer)))
+
+(defun gud-frame-gud-buffer (instance)
+ (interactive (list (gdb-needed-default-instance)))
+ (gud-frame-buffer
+ (gdb-get-create-instance-buffer instance 'gud)))
+
+(make-frames-menu gud-breakpoints-mode-map)
+(make-frames-menu gud-frames-mode-map)
+(make-frames-menu gud-registers-mode-map)
+
+
+(defun gud-gdb-find-file (f)
+ (find-file-noselect f))
+
+;;;###autoload
+(defun gdb (command-line)
+ "Run gdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run gdb (like this): "
+ (if (consp gud-gdb-history)
+ (car gud-gdb-history)
+ "gdb ")
+ nil nil
+ '(gud-gdb-history . 1))))
+ (gud-overload-functions
+ '((gud-massage-args . gud-gdb-massage-args)
+ (gud-marker-filter . gud-gdb-marker-filter)
+ (gud-find-file . gud-gdb-find-file)
+ ))
+
+ (let* ((words (gud-chop-words command-line))
+ (program (car words))
+ (file-word (let ((w (cdr words)))
+ (while (and w (= ?- (aref (car w) 0)))
+ (setq w (cdr w)))
+ (car w)))
+ (args (delq file-word (cdr words)))
+ (file (expand-file-name file-word))
+ (filepart (file-name-nondirectory file))
+ (buffer-name (concat "*gud-" filepart "*")))
+ (setq gdb-first-time (not (get-buffer-process buffer-name))))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "break %f:%l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "tbreak %f:%l" "\C-t" "Set breakpoint at current line.")
+ (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-kill "kill" nil "Kill the program.")
+ (gud-def gud-run "run" nil "Run the program.")
+ (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-step "step %p" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+ (gud-def gud-cont "cont" "\C-r" "Continue with display.")
+ (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+ (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "^(.*gdb[+]?) *")
+ (setq comint-input-sender 'gdb-send)
+ (run-hooks 'gdb-mode-hook)
+ (let ((instance
+ (make-gdb-instance (get-buffer-process (current-buffer)))
+ ))
+ (if gdb-first-time (gdb-clear-inferior-io instance)))
+ )
+
+
+;; ======================================================================
+;; sdb functions
+
+;;; History of argument lists passed to sdb.
+(defvar gud-sdb-history nil)
+
+(defvar gud-sdb-needs-tags (not (file-exists-p "/var"))
+ "If nil, we're on a System V Release 4 and don't need the tags hack.")
+
+(defvar gud-sdb-lastfile nil)
+
+(defun gud-sdb-massage-args (file args)
+ (cons file args))
+
+(defun gud-sdb-marker-filter (string)
+ (cond
+ ;; System V Release 3.2 uses this format
+ ((string-match "\\(^0x\\w* in \\|^\\|\n\\)\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ string)
+ (setq gud-last-frame
+ (cons
+ (substring string (match-beginning 2) (match-end 2))
+ (string-to-int
+ (substring string (match-beginning 3) (match-end 3))))))
+ ;; System V Release 4.0
+ ((string-match "^\\(BREAKPOINT\\|STEPPED\\) process [0-9]+ function [^ ]+ in \\(.+\\)\n"
+ string)
+ (setq gud-sdb-lastfile
+ (substring string (match-beginning 2) (match-end 2))))
+ ((and gud-sdb-lastfile (string-match "^\\([0-9]+\\):" string))
+ (setq gud-last-frame
+ (cons
+ gud-sdb-lastfile
+ (string-to-int
+ (substring string (match-beginning 1) (match-end 1))))))
+ (t
+ (setq gud-sdb-lastfile nil)))
+ string)
+
+(defun gud-sdb-find-file (f)
+ (if gud-sdb-needs-tags
+ (find-tag-noselect f)
+ (find-file-noselect f)))
+
+;;;###autoload
+(defun sdb (command-line)
+ "Run sdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run sdb (like this): "
+ (if (consp gud-sdb-history)
+ (car gud-sdb-history)
+ "sdb ")
+ nil nil
+ '(gud-sdb-history . 1))))
+ (if (and gud-sdb-needs-tags
+ (not (and (boundp 'tags-file-name) (file-exists-p tags-file-name))))
+ (error "The sdb support requires a valid tags table to work."))
+ (gud-overload-functions '((gud-massage-args . gud-sdb-massage-args)
+ (gud-marker-filter . gud-sdb-marker-filter)
+ (gud-find-file . gud-sdb-find-file)
+ ))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "%l b" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "%l c" "\C-t" "Set temporary breakpoint at current line.")
+ (gud-def gud-remove "%l d" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s %p" "\C-s" "Step one source line with display.")
+ (gud-def gud-stepi "i %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-print "%e/" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "\\(^\\|\n\\)\\*")
+ (run-hooks 'sdb-mode-hook)
+ )
+
+;; ======================================================================
+;; dbx functions
+
+;;; History of argument lists passed to dbx.
+(defvar gud-dbx-history nil)
+
+(defun gud-dbx-massage-args (file args)
+ (cons file args))
+
+(defun gud-dbx-marker-filter (string)
+ (if (or (string-match
+ "stopped in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
+ string)
+ (string-match
+ "signal .* in .* at line \\([0-9]*\\) in file \"\\([^\"]*\\)\""
+ string))
+ (setq gud-last-frame
+ (cons
+ (substring string (match-beginning 2) (match-end 2))
+ (string-to-int
+ (substring string (match-beginning 1) (match-end 1))))))
+ string)
+
+(defun gud-dbx-find-file (f)
+ (find-file-noselect f))
+
+;;;###autoload
+(defun dbx (command-line)
+ "Run dbx on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run dbx (like this): "
+ (if (consp gud-dbx-history)
+ (car gud-dbx-history)
+ "dbx ")
+ nil nil
+ '(gud-dbx-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-dbx-massage-args)
+ (gud-marker-filter . gud-dbx-marker-filter)
+ (gud-find-file . gud-dbx-find-file)
+ ))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "file \"%d%f\"\nstop at %l"
+ "\C-b" "Set breakpoint at current line.")
+;; (gud-def gud-break "stop at \"%f\":%l"
+;; "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "step %p" "\C-s" "Step one line with display.")
+ (gud-def gud-stepi "stepi %p" "\C-i" "Step one instruction with display.")
+ (gud-def gud-next "next %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "cont" "\C-r" "Continue with display.")
+ (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
+ (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
+ (gud-def gud-print "print %e" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "^[^)]*dbx) *")
+ (run-hooks 'dbx-mode-hook)
+ )
+
+;; ======================================================================
+;; xdb (HP PARISC debugger) functions
+
+;;; History of argument lists passed to xdb.
+(defvar gud-xdb-history nil)
+
+(defvar gud-xdb-directories nil
+ "*A list of directories that xdb should search for source code.
+If nil, only source files in the program directory
+will be known to xdb.
+
+The file names should be absolute, or relative to the directory
+containing the executable being debugged.")
+
+(defun gud-xdb-massage-args (file args)
+ (nconc (let ((directories gud-xdb-directories)
+ (result nil))
+ (while directories
+ (setq result (cons (car directories) (cons "-d" result)))
+ (setq directories (cdr directories)))
+ (nreverse (cons file result)))
+ args))
+
+(defun gud-xdb-file-name (f)
+ "Transform a relative pathname to a full pathname in xdb mode"
+ (let ((result nil))
+ (if (file-exists-p f)
+ (setq result (expand-file-name f))
+ (let ((directories gud-xdb-directories))
+ (while directories
+ (let ((path (concat (car directories) "/" f)))
+ (if (file-exists-p path)
+ (setq result (expand-file-name path)
+ directories nil)))
+ (setq directories (cdr directories)))))
+ result))
+
+;; xdb does not print the lines all at once, so we have to accumulate them
+(defvar gud-xdb-accumulation "")
+
+(defun gud-xdb-marker-filter (string)
+ (let (result)
+ (if (or (string-match comint-prompt-regexp string)
+ (string-match ".*\012" string))
+ (setq result (concat gud-xdb-accumulation string)
+ gud-xdb-accumulation "")
+ (setq gud-xdb-accumulation (concat gud-xdb-accumulation string)))
+ (if result
+ (if (or (string-match "\\([^\n \t:]+\\): [^:]+: \\([0-9]+\\):" result)
+ (string-match "[^: \t]+:[ \t]+\\([^:]+\\): [^:]+: \\([0-9]+\\):"
+ result))
+ (let ((line (string-to-int
+ (substring result (match-beginning 2) (match-end 2))))
+ (file (gud-xdb-file-name
+ (substring result (match-beginning 1) (match-end 1)))))
+ (if file
+ (setq gud-last-frame (cons file line))))))
+ (or result "")))
+
+(defun gud-xdb-find-file (f)
+ (let ((realf (gud-xdb-file-name f)))
+ (if realf (find-file-noselect realf))))
+
+;;;###autoload
+(defun xdb (command-line)
+ "Run xdb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger.
+
+You can set the variable 'gud-xdb-directories' to a list of program source
+directories if your program contains sources from more than one directory."
+ (interactive
+ (list (read-from-minibuffer "Run xdb (like this): "
+ (if (consp gud-xdb-history)
+ (car gud-xdb-history)
+ "xdb ")
+ nil nil
+ '(gud-xdb-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-xdb-massage-args)
+ (gud-marker-filter . gud-xdb-marker-filter)
+ (gud-find-file . gud-xdb-find-file)))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "b %f:%l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-tbreak "b %f:%l\\t" "\C-t"
+ "Set temporary breakpoint at current line.")
+ (gud-def gud-remove "db" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s %p" "\C-s" "Step one line with display.")
+ (gud-def gud-next "S %p" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-up "up %p" "<" "Up (numeric arg) stack frames.")
+ (gud-def gud-down "down %p" ">" "Down (numeric arg) stack frames.")
+ (gud-def gud-finish "bu\\t" "\C-f" "Finish executing current function.")
+ (gud-def gud-print "p %e" "\C-p" "Evaluate C expression at point.")
+
+ (setq comint-prompt-regexp "^>")
+ (make-local-variable 'gud-xdb-accumulation)
+ (setq gud-xdb-accumulation "")
+ (run-hooks 'xdb-mode-hook))
+
+;; ======================================================================
+;; perldb functions
+
+;;; History of argument lists passed to perldb.
+(defvar gud-perldb-history nil)
+
+(defun gud-perldb-massage-args (file args)
+ (cons "-d" (cons file (cons "-emacs" args))))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings. We
+;; might even receive a big chunk with several markers in it. If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(defvar gud-perldb-marker-acc "")
+
+(defun gud-perldb-marker-filter (string)
+ (save-match-data
+ (setq gud-perldb-marker-acc (concat gud-perldb-marker-acc string))
+ (let ((output ""))
+
+ ;; Process all the complete markers in this chunk.
+ (while (string-match "^\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ gud-perldb-marker-acc)
+ (setq
+
+ ;; Extract the frame position from the marker.
+ gud-last-frame
+ (cons (substring gud-perldb-marker-acc (match-beginning 1) (match-end 1))
+ (string-to-int (substring gud-perldb-marker-acc
+ (match-beginning 2)
+ (match-end 2))))
+
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-perldb-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+ gud-perldb-marker-acc (substring gud-perldb-marker-acc (match-end 0))))
+
+ ;; Does the remaining text look like it might end with the
+ ;; beginning of another marker? If it does, then keep it in
+ ;; gud-perldb-marker-acc until we receive the rest of it. Since we
+ ;; know the full marker regexp above failed, it's pretty simple to
+ ;; test for marker starts.
+ (if (string-match "^\032.*\\'" gud-perldb-marker-acc)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output (concat output (substring gud-perldb-marker-acc
+ 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq gud-perldb-marker-acc
+ (substring gud-perldb-marker-acc (match-beginning 0))))
+
+ (setq output (concat output gud-perldb-marker-acc)
+ gud-perldb-marker-acc ""))
+
+ output)))
+
+(defun gud-perldb-find-file (f)
+ (find-file-noselect f))
+
+;;;###autoload
+(defun perldb (command-line)
+ "Run perldb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run perldb (like this): "
+ (if (consp gud-perldb-history)
+ (car gud-perldb-history)
+ "perl ")
+ nil nil
+ '(gud-perldb-history . 1))))
+ (gud-overload-functions '((gud-massage-args . gud-perldb-massage-args)
+ (gud-marker-filter . gud-perldb-marker-filter)
+ (gud-find-file . gud-perldb-find-file)
+ ))
+
+ (gud-common-init command-line)
+
+ (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
+ (gud-def gud-remove "d %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+; (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+; (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+; (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "%e" "\C-p" "Evaluate perl expression at point.")
+
+ (setq comint-prompt-regexp "^ DB<[0-9]+> ")
+ (run-hooks 'perldb-mode-hook)
+ )
+
+;;
+;; End of debugger-specific information
+;;
+
+
+;;; When we send a command to the debugger via gud-call, it's annoying
+;;; to see the command and the new prompt inserted into the debugger's
+;;; buffer; we have other ways of knowing the command has completed.
+;;;
+;;; If the buffer looks like this:
+;;; --------------------
+;;; (gdb) set args foo bar
+;;; (gdb) -!-
+;;; --------------------
+;;; (the -!- marks the location of point), and we type `C-x SPC' in a
+;;; source file to set a breakpoint, we want the buffer to end up like
+;;; this:
+;;; --------------------
+;;; (gdb) set args foo bar
+;;; Breakpoint 1 at 0x92: file make-docfile.c, line 49.
+;;; (gdb) -!-
+;;; --------------------
+;;; Essentially, the old prompt is deleted, and the command's output
+;;; and the new prompt take its place.
+;;;
+;;; Not echoing the command is easy enough; you send it directly using
+;;; comint-input-sender, and it never enters the buffer. However,
+;;; getting rid of the old prompt is trickier; you don't want to do it
+;;; when you send the command, since that will result in an annoying
+;;; flicker as the prompt is deleted, redisplay occurs while Emacs
+;;; waits for a response from the debugger, and the new prompt is
+;;; inserted. Instead, we'll wait until we actually get some output
+;;; from the subprocess before we delete the prompt. If the command
+;;; produced no output other than a new prompt, that prompt will most
+;;; likely be in the first chunk of output received, so we will delete
+;;; the prompt and then replace it with an identical one. If the
+;;; command produces output, the prompt is moving anyway, so the
+;;; flicker won't be annoying.
+;;;
+;;; So - when we want to delete the prompt upon receipt of the next
+;;; chunk of debugger output, we position gud-delete-prompt-marker at
+;;; the start of the prompt; the process filter will notice this, and
+;;; delete all text between it and the process output marker. If
+;;; gud-delete-prompt-marker points nowhere, we leave the current
+;;; prompt alone.
+(defvar gud-delete-prompt-marker nil)
+
+
+(defvar gdbish-comint-mode-map (copy-keymap comint-mode-map))
+(define-key gdbish-comint-mode-map "\C-c\M-\C-r" 'gud-display-registers-buffer)
+(define-key gdbish-comint-mode-map "\C-c\M-\C-f" 'gud-display-stack-buffer)
+(define-key gdbish-comint-mode-map "\C-c\M-\C-b" 'gud-display-breakpoints-buffer)
+
+(make-windows-menu gdbish-comint-mode-map)
+(make-frames-menu gdbish-comint-mode-map)
+
+(defun gud-mode ()
+ "Major mode for interacting with an inferior debugger process.
+
+ You start it up with one of the commands M-x gdb, M-x sdb, M-x dbx,
+or M-x xdb. Each entry point finishes by executing a hook; `gdb-mode-hook',
+`sdb-mode-hook', `dbx-mode-hook' or `xdb-mode-hook' respectively.
+
+After startup, the following commands are available in both the GUD
+interaction buffer and any source buffer GUD visits due to a breakpoint stop
+or step operation:
+
+\\[gud-break] sets a breakpoint at the current file and line. In the
+GUD buffer, the current file and line are those of the last breakpoint or
+step. In a source buffer, they are the buffer's file and current line.
+
+\\[gud-remove] removes breakpoints on the current file and line.
+
+\\[gud-refresh] displays in the source window the last line referred to
+in the gud buffer.
+
+\\[gud-step], \\[gud-next], and \\[gud-stepi] do a step-one-line,
+step-one-line (not entering function calls), and step-one-instruction
+and then update the source window with the current file and position.
+\\[gud-cont] continues execution.
+
+\\[gud-print] tries to find the largest C lvalue or function-call expression
+around point, and sends it to the debugger for value display.
+
+The above commands are common to all supported debuggers except xdb which
+does not support stepping instructions.
+
+Under gdb, sdb and xdb, \\[gud-tbreak] behaves exactly like \\[gud-break],
+except that the breakpoint is temporary; that is, it is removed when
+execution stops on it.
+
+Under gdb, dbx, and xdb, \\[gud-up] pops up through an enclosing stack
+frame. \\[gud-down] drops back down through one.
+
+If you are using gdb or xdb, \\[gud-finish] runs execution to the return from
+the current function and stops.
+
+All the keystrokes above are accessible in the GUD buffer
+with the prefix C-c, and in all buffers through the prefix C-x C-a.
+
+All pre-defined functions for which the concept make sense repeat
+themselves the appropriate number of times if you give a prefix
+argument.
+
+You may use the `gud-def' macro in the initialization hook to define other
+commands.
+
+Other commands for interacting with the debugger process are inherited from
+comint mode, which see."
+ (interactive)
+ (comint-mode)
+ (setq major-mode 'gud-mode)
+ (setq mode-name "Debugger")
+ (setq mode-line-process '(": %s"))
+ (use-local-map (copy-keymap gdbish-comint-mode-map))
+ (setq gud-last-frame nil)
+ (make-local-variable 'comint-prompt-regexp)
+ (make-local-variable 'gud-delete-prompt-marker)
+ (setq gud-delete-prompt-marker (make-marker))
+ (run-hooks 'gud-mode-hook)
+)
+
+(defvar gud-comint-buffer nil)
+
+;; Chop STRING into words separated by SPC or TAB and return a list of them.
+(defun gud-chop-words (string)
+ (let ((i 0) (beg 0)
+ (len (length string))
+ (words nil))
+ (while (< i len)
+ (if (memq (aref string i) '(?\t ? ))
+ (progn
+ (setq words (cons (substring string beg i) words)
+ beg (1+ i))
+ (while (and (< beg len) (memq (aref string beg) '(?\t ? )))
+ (setq beg (1+ beg)))
+ (setq i (1+ beg)))
+ (setq i (1+ i))))
+ (if (< beg len)
+ (setq words (cons (substring string beg) words)))
+ (nreverse words)))
+
+(defvar gud-target-name "--unknown--"
+ "The apparent name of the program being debugged in a gud buffer.
+For sure this the root string used in smashing together the gud
+buffer's name, even if that doesn't happen to be the name of a
+program.")
+
+;; Perform initializations common to all debuggers.
+(defun gud-common-init (command-line)
+ (let* ((words (gud-chop-words command-line))
+ (program (car words))
+ (file-word (let ((w (cdr words)))
+ (while (and w (= ?- (aref (car w) 0)))
+ (setq w (cdr w)))
+ (car w)))
+ (args (delq file-word (cdr words)))
+ (file (expand-file-name file-word))
+ (filepart (file-name-nondirectory file))
+ (buffer-name (concat "*gud-" filepart "*")))
+ (switch-to-buffer buffer-name)
+ (setq default-directory (file-name-directory file))
+ (or (bolp) (newline))
+ (insert "Current directory is " default-directory "\n")
+ (let ((old-instance gdb-buffer-instance))
+ (apply 'make-comint (concat "gud-" filepart) program nil
+ (gud-massage-args file args))
+ (gud-mode)
+ (make-variable-buffer-local 'old-gdb-buffer-instance)
+ (setq old-gdb-buffer-instance old-instance))
+ (make-variable-buffer-local 'gud-target-name)
+ (setq gud-target-name filepart))
+ (set-process-filter (get-buffer-process (current-buffer)) 'gud-filter)
+ (set-process-sentinel (get-buffer-process (current-buffer)) 'gud-sentinel)
+ (gud-set-buffer)
+ )
+
+(defun gud-set-buffer ()
+ (cond ((eq major-mode 'gud-mode)
+ (setq gud-comint-buffer (current-buffer)))))
+
+;; These functions are responsible for inserting output from your debugger
+;; into the buffer. The hard work is done by the method that is
+;; the value of gud-marker-filter.
+
+(defun gud-filter (proc string)
+ ;; Here's where the actual buffer insertion is done
+ (let ((inhibit-quit t))
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (let (moving output-after-point)
+ (save-excursion
+ (goto-char (process-mark proc))
+ ;; If we have been so requested, delete the debugger prompt.
+ (if (marker-buffer gud-delete-prompt-marker)
+ (progn
+ (delete-region (point) gud-delete-prompt-marker)
+ (set-marker gud-delete-prompt-marker nil)))
+ (insert-before-markers (gud-marker-filter string))
+ (setq moving (= (point) (process-mark proc)))
+ (setq output-after-point (< (point) (process-mark proc)))
+ ;; Check for a filename-and-line number.
+ ;; Don't display the specified file
+ ;; unless (1) point is at or after the position where output appears
+ ;; and (2) this buffer is on the screen.
+ (if (and gud-last-frame
+ (not output-after-point)
+ (get-buffer-window (current-buffer)))
+ (gud-display-frame)))
+ (if moving (goto-char (process-mark proc)))))))
+
+(defun gud-proc-died (proc)
+ ;; Stop displaying an arrow in a source file.
+ (setq overlay-arrow-position nil)
+
+ ;; Kill the dummy process, so that C-x C-c won't worry about it.
+ (save-excursion
+ (set-buffer (process-buffer proc))
+ (kill-process
+ (get-buffer-process
+ (gdb-get-instance-buffer gdb-buffer-instance 'gdb-inferior-io))))
+ )
+
+(defun gud-sentinel (proc msg)
+ (cond ((null (buffer-name (process-buffer proc)))
+ ;; buffer killed
+ (gud-proc-died proc)
+ (set-process-buffer proc nil))
+ ((memq (process-status proc) '(signal exit))
+ (gud-proc-died proc)
+
+ ;; Fix the mode line.
+ (setq mode-line-process
+ (concat ": "
+ (symbol-name (process-status proc))))
+ (let* ((obuf (current-buffer)))
+ ;; save-excursion isn't the right thing if
+ ;; process-buffer is current-buffer
+ (unwind-protect
+ (progn
+ ;; Write something in *compilation* and hack its mode line,
+ (set-buffer (process-buffer proc))
+ ;; Force mode line redisplay soon
+ (set-buffer-modified-p (buffer-modified-p))
+ (if (eobp)
+ (insert ?\n mode-name " " msg)
+ (save-excursion
+ (goto-char (point-max))
+ (insert ?\n mode-name " " msg)))
+ ;; If buffer and mode line will show that the process
+ ;; is dead, we can delete it now. Otherwise it
+ ;; will stay around until M-x list-processes.
+ (delete-process proc))
+ ;; Restore old buffer, but don't restore old point
+ ;; if obuf is the gud buffer.
+ (set-buffer obuf))))))
+
+(defun gud-display-frame ()
+ "Find and obey the last filename-and-line marker from the debugger.
+Obeying it means displaying in another window the specified file and line."
+ (interactive)
+ (if gud-last-frame
+ (progn
+; (gud-set-buffer)
+ (gud-display-line (car gud-last-frame) (cdr gud-last-frame))
+ (setq gud-last-last-frame gud-last-frame
+ gud-last-frame nil))))
+
+;; Make sure the file named TRUE-FILE is in a buffer that appears on the screen
+;; and that its line LINE is visible.
+;; Put the overlay-arrow on the line LINE in that buffer.
+;; Most of the trickiness in here comes from wanting to preserve the current
+;; region-restriction if that's possible. We use an explicit display-buffer
+;; to get around the fact that this is called inside a save-excursion.
+
+(defun gud-display-line (true-file line)
+ (let* ((buffer (gud-find-file true-file))
+ (window (gud-display-source-buffer buffer))
+ (pos))
+ (if (not window)
+ (error "foo bar baz"))
+;;; (if (equal buffer (current-buffer))
+;;; nil
+;;; (setq buffer-read-only nil))
+ (save-excursion
+;;; (setq buffer-read-only t)
+ (set-buffer buffer)
+ (save-restriction
+ (widen)
+ (goto-line line)
+ (setq pos (point))
+ (setq overlay-arrow-string "=>")
+ (or overlay-arrow-position
+ (setq overlay-arrow-position (make-marker)))
+ (set-marker overlay-arrow-position (point) (current-buffer)))
+ (cond ((or (< pos (point-min)) (> pos (point-max)))
+ (widen)
+ (goto-char pos))))
+ (set-window-point window overlay-arrow-position)))
+
+;;; The gud-call function must do the right thing whether its invoking
+;;; keystroke is from the GUD buffer itself (via major-mode binding)
+;;; or a C buffer. In the former case, we want to supply data from
+;;; gud-last-frame. Here's how we do it:
+
+(defun gud-format-command (str arg)
+ (let ((insource (not (eq (current-buffer) gud-comint-buffer))))
+ (if (string-match "\\(.*\\)%f\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (file-name-nondirectory (if insource
+ (buffer-file-name)
+ (car gud-last-frame)))
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%d\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (file-name-directory (if insource
+ (buffer-file-name)
+ (car gud-last-frame)))
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%l\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (if insource
+ (save-excursion
+ (beginning-of-line)
+ (save-restriction (widen)
+ (1+ (count-lines 1 (point)))))
+ (cdr gud-last-frame))
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%e\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (find-c-expr)
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%a\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (gud-read-address)
+ (substring str (match-beginning 2) (match-end 2)))))
+ (if (string-match "\\(.*\\)%p\\(.*\\)" str)
+ (setq str (concat
+ (substring str (match-beginning 1) (match-end 1))
+ (if arg (int-to-string arg) "")
+ (substring str (match-beginning 2) (match-end 2)))))
+ )
+ str
+ )
+
+(defun gud-read-address ()
+ "Return a string containing the core-address found in the buffer at point."
+ (save-excursion
+ (let ((pt (point)) found begin)
+ (setq found (if (search-backward "0x" (- pt 7) t) (point)))
+ (cond
+ (found (forward-char 2)
+ (buffer-substring found
+ (progn (re-search-forward "[^0-9a-f]")
+ (forward-char -1)
+ (point))))
+ (t (setq begin (progn (re-search-backward "[^0-9]")
+ (forward-char 1)
+ (point)))
+ (forward-char 1)
+ (re-search-forward "[^0-9]")
+ (forward-char -1)
+ (buffer-substring begin (point)))))))
+
+(defun gud-call (fmt &optional arg)
+ (let ((msg (gud-format-command fmt arg)))
+ (message "Command: %s" msg)
+ (sit-for 0)
+ (gud-basic-call msg)))
+
+(defun gud-basic-call (command)
+ "Invoke the debugger COMMAND displaying source in other window."
+ (interactive)
+ (gud-set-buffer)
+ (let ((proc (get-buffer-process gud-comint-buffer)))
+
+ ;; Arrange for the current prompt to get deleted.
+ (save-excursion
+ (set-buffer gud-comint-buffer)
+ (goto-char (process-mark proc))
+ (beginning-of-line)
+ (if (looking-at comint-prompt-regexp)
+ (set-marker gud-delete-prompt-marker (point)))
+ (apply comint-input-sender (list proc command)))))
+
+(defun gud-refresh (&optional arg)
+ "Fix up a possibly garbled display, and redraw the arrow."
+ (interactive "P")
+ (recenter arg)
+ (or gud-last-frame (setq gud-last-frame gud-last-last-frame))
+ (gud-display-frame))
+
+;;; Code for parsing expressions out of C code. The single entry point is
+;;; find-c-expr, which tries to return an lvalue expression from around point.
+;;;
+;;; The rest of this file is a hacked version of gdbsrc.el by
+;;; Debby Ayers <ayers@asc.slb.com>,
+;;; Rich Schaefer <schaefer@asc.slb.com> Schlumberger, Austin, Tx.
+
+(defun find-c-expr ()
+ "Returns the C expr that surrounds point."
+ (interactive)
+ (save-excursion
+ (let ((p) (expr) (test-expr))
+ (setq p (point))
+ (setq expr (expr-cur))
+ (setq test-expr (expr-prev))
+ (while (expr-compound test-expr expr)
+ (setq expr (cons (car test-expr) (cdr expr)))
+ (goto-char (car expr))
+ (setq test-expr (expr-prev)))
+ (goto-char p)
+ (setq test-expr (expr-next))
+ (while (expr-compound expr test-expr)
+ (setq expr (cons (car expr) (cdr test-expr)))
+ (setq test-expr (expr-next))
+ )
+ (buffer-substring (car expr) (cdr expr)))))
+
+(defun expr-cur ()
+ "Returns the expr that point is in; point is set to beginning of expr.
+The expr is represented as a cons cell, where the car specifies the point in
+the current buffer that marks the beginning of the expr and the cdr specifies
+the character after the end of the expr."
+ (let ((p (point)) (begin) (end))
+ (expr-backward-sexp)
+ (setq begin (point))
+ (expr-forward-sexp)
+ (setq end (point))
+ (if (>= p end)
+ (progn
+ (setq begin p)
+ (goto-char p)
+ (expr-forward-sexp)
+ (setq end (point))
+ )
+ )
+ (goto-char begin)
+ (cons begin end)))
+
+(defun expr-backward-sexp ()
+ "Version of `backward-sexp' that catches errors."
+ (condition-case nil
+ (backward-sexp)
+ (error t)))
+
+(defun expr-forward-sexp ()
+ "Version of `forward-sexp' that catches errors."
+ (condition-case nil
+ (forward-sexp)
+ (error t)))
+
+(defun expr-prev ()
+ "Returns the previous expr, point is set to beginning of that expr.
+The expr is represented as a cons cell, where the car specifies the point in
+the current buffer that marks the beginning of the expr and the cdr specifies
+the character after the end of the expr"
+ (let ((begin) (end))
+ (expr-backward-sexp)
+ (setq begin (point))
+ (expr-forward-sexp)
+ (setq end (point))
+ (goto-char begin)
+ (cons begin end)))
+
+(defun expr-next ()
+ "Returns the following expr, point is set to beginning of that expr.
+The expr is represented as a cons cell, where the car specifies the point in
+the current buffer that marks the beginning of the expr and the cdr specifies
+the character after the end of the expr."
+ (let ((begin) (end))
+ (expr-forward-sexp)
+ (expr-forward-sexp)
+ (setq end (point))
+ (expr-backward-sexp)
+ (setq begin (point))
+ (cons begin end)))
+
+(defun expr-compound-sep (span-start span-end)
+ "Returns '.' for '->' & '.', returns ' ' for white space,
+returns '?' for other punctuation."
+ (let ((result ? )
+ (syntax))
+ (while (< span-start span-end)
+ (setq syntax (char-syntax (char-after span-start)))
+ (cond
+ ((= syntax ? ) t)
+ ((= syntax ?.) (setq syntax (char-after span-start))
+ (cond
+ ((= syntax ?.) (setq result ?.))
+ ((and (= syntax ?-) (= (char-after (+ span-start 1)) ?>))
+ (setq result ?.)
+ (setq span-start (+ span-start 1)))
+ (t (setq span-start span-end)
+ (setq result ??)))))
+ (setq span-start (+ span-start 1)))
+ result))
+
+(defun expr-compound (first second)
+ "Non-nil if concatenating FIRST and SECOND makes a single C token.
+The two exprs are represented as a cons cells, where the car
+specifies the point in the current buffer that marks the beginning of the
+expr and the cdr specifies the character after the end of the expr.
+Link exprs of the form:
+ Expr -> Expr
+ Expr . Expr
+ Expr (Expr)
+ Expr [Expr]
+ (Expr) Expr
+ [Expr] Expr"
+ (let ((span-start (cdr first))
+ (span-end (car second))
+ (syntax))
+ (setq syntax (expr-compound-sep span-start span-end))
+ (cond
+ ((= (car first) (car second)) nil)
+ ((= (cdr first) (cdr second)) nil)
+ ((= syntax ?.) t)
+ ((= syntax ? )
+ (setq span-start (char-after (- span-start 1)))
+ (setq span-end (char-after span-end))
+ (cond
+ ((= span-start ?) ) t )
+ ((= span-start ?] ) t )
+ ((= span-end ?( ) t )
+ ((= span-end ?[ ) t )
+ (t nil))
+ )
+ (t nil))))
+
+(provide 'gud)
+
+;;; gud.el ends here
diff --git a/contrib/gdb/gdb/gdbcmd.h b/contrib/gdb/gdb/gdbcmd.h
new file mode 100644
index 0000000..2459f81
--- /dev/null
+++ b/contrib/gdb/gdb/gdbcmd.h
@@ -0,0 +1,106 @@
+/* Header file for GDB-specific command-line stuff.
+ Copyright 1986, 1989, 1990, 1992 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (GDBCMD_H)
+#define GDBCMD_H 1
+
+#include "command.h"
+
+/* Chain containing all defined commands. */
+
+extern struct cmd_list_element *cmdlist;
+
+/* Chain containing all defined info subcommands. */
+
+extern struct cmd_list_element *infolist;
+
+/* Chain containing all defined enable subcommands. */
+
+extern struct cmd_list_element *enablelist;
+
+/* Chain containing all defined disable subcommands. */
+
+extern struct cmd_list_element *disablelist;
+
+/* Chain containing all defined delete subcommands. */
+
+extern struct cmd_list_element *deletelist;
+
+/* Chain containing all defined "enable breakpoint" subcommands. */
+
+extern struct cmd_list_element *enablebreaklist;
+
+/* Chain containing all defined set subcommands */
+
+extern struct cmd_list_element *setlist;
+
+/* Chain containing all defined unset subcommands */
+
+extern struct cmd_list_element *unsetlist;
+
+/* Chain containing all defined show subcommands. */
+
+extern struct cmd_list_element *showlist;
+
+/* Chain containing all defined \"set history\". */
+
+extern struct cmd_list_element *sethistlist;
+
+/* Chain containing all defined \"show history\". */
+
+extern struct cmd_list_element *showhistlist;
+
+/* Chain containing all defined \"unset history\". */
+
+extern struct cmd_list_element *unsethistlist;
+
+/* Chain containing all defined maintenance subcommands. */
+
+extern struct cmd_list_element *maintenancelist;
+
+/* Chain containing all defined "maintenance info" subcommands. */
+
+extern struct cmd_list_element *maintenanceinfolist;
+
+/* Chain containing all defined "maintenance print" subcommands. */
+
+extern struct cmd_list_element *maintenanceprintlist;
+
+extern struct cmd_list_element *setprintlist;
+
+extern struct cmd_list_element *showprintlist;
+
+extern struct cmd_list_element *setchecklist;
+
+extern struct cmd_list_element *showchecklist;
+
+extern void
+execute_user_command PARAMS ((struct cmd_list_element *, char *));
+
+extern void
+execute_command PARAMS ((char *, int));
+
+enum command_control_type
+execute_control_command PARAMS ((struct command_line *));
+
+void print_command_line PARAMS ((struct command_line *, unsigned int));
+
+extern char **noop_completer PARAMS ((char *, char *));
+
+extern char **filename_completer PARAMS ((char *, char *));
+
+#endif /* !defined (GDBCMD_H) */
diff --git a/contrib/gdb/gdb/gdbcore.h b/contrib/gdb/gdb/gdbcore.h
new file mode 100644
index 0000000..bf7cb32
--- /dev/null
+++ b/contrib/gdb/gdb/gdbcore.h
@@ -0,0 +1,155 @@
+/* Machine independent variables that describe the core file under GDB.
+ Copyright 1986, 1987, 1989, 1990, 1992, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Interface routines for core, executable, etc. */
+
+#if !defined (GDBCORE_H)
+#define GDBCORE_H 1
+
+#include "bfd.h"
+
+/* Return the name of the executable file as a string.
+ ERR nonzero means get error if there is none specified;
+ otherwise return 0 in that case. */
+
+extern char *get_exec_file PARAMS ((int err));
+
+/* Nonzero if there is a core file. */
+
+extern int have_core_file_p PARAMS ((void));
+
+/* Read "memory data" from whatever target or inferior we have.
+ Returns zero if successful, errno value if not. EIO is used for
+ address out of bounds. If breakpoints are inserted, returns shadow
+ contents, not the breakpoints themselves. From breakpoint.c. */
+
+extern int read_memory_nobpt PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ unsigned len));
+
+/* Report a memory error with error(). */
+
+extern void memory_error PARAMS ((int status, CORE_ADDR memaddr));
+
+/* Like target_read_memory, but report an error if can't read. */
+
+extern void read_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+/* Read an integer from debugged memory, given address and number of
+ bytes. */
+
+extern LONGEST read_memory_integer PARAMS ((CORE_ADDR memaddr, int len));
+
+/* Read an unsigned integer from debugged memory, given address and
+ number of bytes. */
+
+extern unsigned LONGEST read_memory_unsigned_integer PARAMS ((CORE_ADDR memaddr, int len));
+
+/* 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 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));
+
+extern void specify_exec_file_hook PARAMS ((void (*hook) (char *filename)));
+
+/* Binary File Diddlers for the exec and core files */
+
+extern bfd *core_bfd;
+extern bfd *exec_bfd;
+
+/* Whether to open exec and core files read-only or read-write. */
+
+extern int write_files;
+
+extern void core_file_command PARAMS ((char *filename, int from_tty));
+
+extern void exec_file_command PARAMS ((char *filename, int from_tty));
+
+extern void validate_files PARAMS ((void));
+
+extern unsigned int register_addr PARAMS ((int regno, int blockend));
+
+extern void registers_fetched PARAMS ((void));
+
+#if !defined (KERNEL_U_ADDR)
+extern CORE_ADDR kernel_u_addr;
+#define KERNEL_U_ADDR kernel_u_addr
+#endif
+
+/* The target vector for core files. */
+
+extern struct target_ops core_ops;
+
+/* The current default bfd target. */
+
+extern char *gnutarget;
+
+extern void set_gnutarget PARAMS ((char *));
+
+/* Structure to keep track of core register reading functions for
+ various core file types. */
+
+struct core_fns {
+
+ /* BFD flavour that we handle. Note that bfd_target_unknown_flavour matches
+ anything, and if there is no better match, this function will be called
+ as the default. */
+
+ enum bfd_flavour core_flavour;
+
+ /* Extract the register values out of the core file and store them where
+ `read_register' will find them.
+
+ CORE_REG_SECT points to the register values themselves, read into
+ memory.
+
+ CORE_REG_SIZE is the size of that area.
+
+ WHICH says which set of registers we are handling (0 = int, 2 = float on
+ machines where they are discontiguous).
+
+ REG_ADDR is the offset from u.u_ar0 to the register values relative to
+ core_reg_sect. This is used with old-fashioned core files to locate the
+ registers in a large upage-plus-stack ".reg" section. Original upage
+ address X is at location core_reg_sect+x+reg_addr. */
+
+ void (*core_read_registers) PARAMS ((char *core_reg_sect, unsigned core_reg_size,
+ int which, unsigned reg_addr));
+
+ /* Finds the next struct core_fns. They are allocated and initialized
+ in whatever module implements the functions pointed to; an
+ initializer calls add_core_fns to add them to the global chain. */
+
+ struct core_fns *next;
+
+};
+
+extern void add_core_fns PARAMS ((struct core_fns *cf));
+
+#endif /* !defined (GDBCORE_H) */
diff --git a/contrib/gdb/gdb/gdbserver/Makefile.in b/contrib/gdb/gdb/gdbserver/Makefile.in
new file mode 100644
index 0000000..2ce6fac
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/Makefile.in
@@ -0,0 +1,245 @@
+#Copyright 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+prefix = /usr/local
+
+program_transform_name =
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+tooldir = $(libdir)/$(target_alias)
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+docdir = $(datadir)/doc
+
+SHELL = /bin/sh
+
+INSTALL = `cd $(srcdir)/../..;pwd`/install.sh -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+INSTALL_XFORM = $(INSTALL) -t='$(program_transform_name)'
+INSTALL_XFORM1 = $(INSTALL_XFORM) -b=.1
+
+AR = ar
+AR_FLAGS = qv
+RANLIB = ranlib
+
+# If you are compiling with GCC, make sure that either 1) You use the
+# -traditional flag, or 2) You have the fixed include files where GCC
+# can reach them. Otherwise the ioctl calls in inflow.c
+# will be incorrectly compiled. The "fixincludes" script in the gcc
+# distribution will fix your include files up.
+#CC=cc
+#CC=gcc -traditional
+GCC=gcc
+
+# Directory containing source files. Don't clean up the spacing,
+# this exact string is matched for by the "configure" script.
+srcdir = .
+
+# It is also possible that you will need to add -I/usr/include/sys to the
+# CFLAGS section if your system doesn't have fcntl.h in /usr/include (which
+# is where it should be according to Posix).
+
+# Set this up with gcc if you have gnu ld and the loader will print out
+# line numbers for undefinded refs.
+#CC-LD=gcc -static
+CC-LD=${CC}
+
+# Where is the "include" directory? Traditionally ../include or ./include
+INCLUDE_DIR = ${srcdir}/../../include
+INCLUDE_DEP = $$(INCLUDE_DIR)
+
+# Where is the source dir for the MMALLOC library? Traditionally ../mmalloc
+# or ./mmalloc (When we want the binary library built from it, we use
+# ${MMALLOC_DIR}${subdir}.)
+# Note that mmalloc can still be used on systems without mmap().
+# To use your system malloc, comment out the following defines.
+MMALLOC_DIR = ${srcdir}/../../mmalloc
+MMALLOC_DEP = $$(MMALLOC_DIR)
+# To use your system malloc, uncomment MMALLOC_DISABLE.
+#MMALLOC_DISABLE = -DNO_MMALLOC
+# To use mmalloc but disable corruption checking, uncomment MMALLOC_CHECK
+#MMALLOC_CHECK = -DNO_MMALLOC_CHECK
+MMALLOC_CFLAGS = ${MMALLOC_CHECK} ${MMALLOC_DISABLE} -I${MMALLOC_DIR}
+
+# Where are the BFD library?
+BFD_DIR = ../../bfd
+BFD = $(BFD_DIR)/libbfd.a
+BFD_SRC = $(srcdir)/$(BFD_DIR)
+BFD_CFLAGS = -I$(BFD_DIR) -I$(BFD_SRC)
+
+# Where is the source dir for the READLINE library? Traditionally in .. or .
+# (For the binary library built from it, we use ${READLINE_DIR}${subdir}.)
+READLINE_DIR = ${srcdir}/../readline
+READLINE_DEP = $$(READLINE_DIR)
+
+# All the includes used for CFLAGS and for lint.
+# -I. for config files.
+# -I${srcdir} possibly for regex.h also.
+# -I${srcdir}/config for more generic config files.
+INCLUDE_CFLAGS = -I. -I${srcdir} -I${srcdir}/.. -I${srcdir}/../config -I$(INCLUDE_DIR)
+
+# M{H,T}_CFLAGS, if defined, has host- and target-dependent CFLAGS
+# from the config/ directory.
+GLOBAL_CFLAGS = ${MT_CFLAGS} ${MH_CFLAGS}
+#PROFILE_CFLAGS = -pg
+
+# CFLAGS is specifically reserved for setting from the command line
+# when running make. I.E. "make CFLAGS=-Wmissing-prototypes".
+CFLAGS = -g
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = ${CFLAGS} ${GLOBAL_CFLAGS} ${PROFILE_CFLAGS} \
+ ${BFD_CFLAGS} ${MMALLOC_CFLAGS} ${INCLUDE_CFLAGS}
+
+# LDFLAGS is specifically reserved for setting from the command line
+# when running make.
+
+# Perhaps should come from parent Makefile
+VERSION = gdbserver-4.12.3
+DIST=gdb
+
+LINT=/usr/5bin/lint
+LINTFLAGS= $(BFD_CFLAGS)
+
+# Host and target-dependent makefile fragments come in here.
+####
+# End of host and target-dependent makefile fragments
+
+# All source files that go into linking GDB remote server.
+
+SFILES = $(srcdir)/low-lynx.c $(srcdir)/low-sparc.c $(srcdir)/low-sun3.c \
+ $(srcdir)/low-hppabsd.c \
+ $(srcdir)/utils.c $(srcdir)/server.c $(srcdir)/remote-utils.c
+
+DEPFILES = $(GDBSERVER_DEPFILES)
+
+SOURCES = $(SFILES) $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
+
+OBS = utils.o $(GDBSERVER_DEPFILES) server.o remote-utils.o
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ ${CC} -c ${INTERNAL_CFLAGS} $<
+
+all: gdbserver gdbreplay
+
+# Traditionally "install" depends on "all". But it may be useful
+# not to; for example, if the user has made some trivial change to a
+# source file and doesn't care about rebuilding or just wants to save the
+# time it takes for make to check that all is up to date.
+# install-only is intended to address that need.
+install: all install-only
+install-only:
+ $(INSTALL_XFORM) gdbserver $(bindir)/gdbserver
+ $(INSTALL_XFORM1) $(srcdir)/gdbserver.1 $(man1dir)/gdbserver.1
+
+uninstall: force
+ rm -f $(bindir)/gdbserver $(man1dir)/gdbserver.1
+
+installcheck:
+check:
+info dvi:
+install-info:
+clean-info:
+
+gdbserver: $(OBS) ${ADD_DEPS} ${CDEPS}
+ rm -f gdbserver
+ ${CC-LD} $(GLOBAL_CFLAGS) $(LDFLAGS) -o gdbserver $(OBS) \
+ $(GDBSERVER_LIBS)
+
+config.status:
+ @echo "You must configure gdbserver. Look at the README file for details."
+ @false
+
+# Put the proper machine-specific files first, so M-. on a machine
+# specific routine gets the one for the correct machine.
+# The xyzzy stuff below deals with empty DEPFILES
+TAGS: ${TAGFILES}
+ etags `find ${srcdir}/../config -name $(TM_FILE) -print` \
+ `find ${srcdir}/../config -name ${XM_FILE} -print` \
+ `find ${srcdir}/../config -name ${NAT_FILE} -print` \
+ `for i in yzzy ${DEPFILES}; do \
+ if [ x$$i != xyzzy ]; then \
+ echo ${srcdir}/$$i | sed -e 's/\.o$$/\.c/' ; \
+ fi; \
+ done` \
+ ${TAGFILES}
+tags: TAGS
+
+clean:
+ rm -f *.o ${ADD_FILES} *~
+ rm -f gdbserver core make.log
+
+distclean: clean
+ rm -f nm.h tm.h xm.h config.status
+ rm -f Makefile
+
+maintainer-clean realclean: clean
+ rm -f nm.h tm.h xm.h config.status
+ rm -f Makefile
+
+STAGESTUFF=${OBS} ${TSOBS} ${NTSOBS} ${ADD_FILES} init.c init.o version.c gdb
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
+
+force:
+
+version.c: Makefile
+ echo 'char *version = "$(VERSION)";' >version.c
+
+# GNU Make has an annoying habit of putting *all* the Makefile variables
+# into the environment, unless you include this target as a circumvention.
+# Rumor is that this will be fixed (and this target can be removed)
+# in GNU Make 4.0.
+.NOEXPORT:
+
+# GNU Make 3.63 has a different problem: it keeps tacking command line
+# overrides onto the definition of $(MAKE). This variable setting
+# will remove them.
+MAKEOVERRIDES=
+
+## This is ugly, but I don't want GNU make to put these variables in
+## the environment. Older makes will see this as a set of targets
+## with no dependencies and no actions.
+unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
+
+server.o : ${srcdir}/server.c ${srcdir}/server.h
+remote-utils.o : ${srcdir}/remote-utils.c ${srcdir}/server.h
+low-lynx.o : ${srcdir}/low-lynx.c ${srcdir}/server.h
+low-sparc.o : $(srcdir)/low-sparc.c $(srcdir)/server.h
+low-sun3.o : $(srcdir)/low-sun3.c $(srcdir)/server.h
+low-hppabsd.o : $(srcdir)/low-hppabsd.c $(srcdir)/server.h
+utils.o : ${srcdir}/utils.c ${srcdir}/server.h
+
+# This is the end of "Makefile.in".
diff --git a/contrib/gdb/gdb/gdbserver/README b/contrib/gdb/gdb/gdbserver/README
new file mode 100644
index 0000000..2281bf6
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/README
@@ -0,0 +1,127 @@
+ README for GDBserver & GDBreplay
+ by Stu Grossman and Fred Fish
+
+Introduction:
+
+This is GDBserver, a remote server for Un*x-like systems. It can be used to
+control the execution of a program on a target system from a GDB on a different
+host. GDB and GDBserver communicate using the standard remote serial protocol
+implemented in remote.c, and various *-stub.c files. They communicate via
+either a serial line or a TCP connection.
+
+Usage (server (target) side):
+
+First, you need to have a copy of the program you want to debug put onto
+the target system. The program can be stripped to save space if needed, as
+GDBserver doesn't care about symbols. All symbol handling is taken care of by
+the GDB running on the host system.
+
+To use the server, you log on to the target system, and run the `gdbserver'
+program. You must tell it (a) how to communicate with GDB, (b) the name of
+your program, and (c) its arguments. The general syntax is:
+
+ target> gdbserver COMM PROGRAM [ARGS ...]
+
+For example, using a serial port, you might say:
+
+ target> gdbserver /dev/com1 emacs foo.txt
+
+This tells gdbserver to debug emacs with an argument of foo.txt, and to
+communicate with GDB via /dev/com1. Gdbserver now waits patiently for the
+host GDB to communicate with it.
+
+To use a TCP connection, you could say:
+
+ target> gdbserver host:2345 emacs foo.txt
+
+This says pretty much the same thing as the last example, except that we are
+going to communicate with the host GDB via TCP. The `host:2345' argument means
+that we are expecting to see a TCP connection from `host' to local TCP port
+2345. (Currently, the `host' part is ignored.) You can choose any number you
+want for the port number as long as it does not conflict with any existing TCP
+ports on the target system. This same port number must be used in the host
+GDBs `target remote' command, which will be described shortly. Note that if
+you chose a port number that conflicts with another service, gdbserver will
+print an error message and exit.
+
+Usage (host side):
+
+You need an unstripped copy of the target program on your host system, since
+GDB needs to examine it's symbol tables and such. Start up GDB as you normally
+would, with the target program as the first argument. (You may need to use the
+--baud option if the serial line is running at anything except 9600 baud.)
+Ie: `gdb TARGET-PROG', or `gdb --baud BAUD TARGET-PROG'. After that, the only
+new command you need to know about is `target remote'. It's argument is either
+a device name (usually a serial device, like `/dev/ttyb'), or a HOST:PORT
+descriptor. For example:
+
+ (gdb) target remote /dev/ttyb
+
+communicates with the server via serial line /dev/ttyb, and:
+
+ (gdb) target remote the-target:2345
+
+communicates via a TCP connection to port 2345 on host `the-target', where
+you previously started up gdbserver with the same port number. Note that for
+TCP connections, you must start up gdbserver prior to using the `target remote'
+command, otherwise you may get an error that looks something like
+`Connection refused'.
+
+Building:
+
+Configuring gdbserver you should specify the same machine for host and
+target (which are the machine that gdbserver is going to run on. This
+is not the same as the machine that gdb is going to run on; building
+gdbserver automatically as part of building a whole tree of tools does
+not currently work if cross-compilation is involved (we don't get the
+right CC in the Makefile, to start with)).
+
+gdbserver should work on sparc-sun-sunos4* or Lynx. The following
+instructions pertain to Lynx. To build the server for Lynx, make a
+new copy of the distribution onto a disk that is NFS shared with the
+Lynx system. Lets say that's in a directory called xyzzy. Then,
+follow these steps under the host system:
+
+ 1) cd xyzzy/gdb/gdbserver
+ 2) ../../configure i386-none-lynx
+
+When that completes, do the following on the Lynx system:
+
+ 3) cd xyzzy/gdb/gdbserver
+ 4) make CC=gcc
+
+It should build with only a minor complaint about NULL being redefined. That's
+a LynxOS problem, and can be ignored.
+
+It's also possible that you may have a cross-compiler to Lynx. In that case,
+you can skip the stuff about NFS. You would replace steps 3 & 4 with:
+
+ make CC=lynx-target-compiler...
+
+Using GDBreplay:
+
+A special hacked down version of gdbserver can be used to replay remote
+debug log files created by gdb. Before using the gdb "target" command to
+initiate a remote debug session, use "set remotelogfile <filename>" to tell
+gdb that you want to make a recording of the serial or tcp session. Note
+that when replaying the session, gdb communicates with gdbreplay via tcp,
+regardless of whether the original session was via a serial link or tcp.
+
+Once you are done with the remote debug session, start gdbreplay and
+tell it the name of the log file and the host and port number that gdb
+should connect to (typically the same as the host running gdb):
+
+ $ gdbreplay logfile host:port
+
+Then start gdb (preferably in a different screen or window) and use the
+"target" command to connect to gdbreplay:
+
+ (gdb) target remote host:port
+
+Repeat the same sequence of user commands to gdb that you gave in the
+original debug session. Gdb should not be able to tell that it is talking
+to gdbreplay rather than a real target, all other things being equal. Note
+that gdbreplay echos the command lines to stderr, as well as the contents of
+the packets it sends and receives. The last command echoed by gdbreplay is
+the next command that needs to be typed to gdb to continue the session in
+sync with the original session.
diff --git a/contrib/gdb/gdb/gdbserver/configure.in b/contrib/gdb/gdb/gdbserver/configure.in
new file mode 100644
index 0000000..67215bd
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/configure.in
@@ -0,0 +1,335 @@
+srcname="Remote GDB server"
+srctrigger=server.c
+gdb_serial_driver=../ser-unix.c
+
+# per-host:
+
+# per-target:
+
+# Hack alert! We want this directory to be configured only for the target,
+# which is where it will be running, so we just eliminate the per-host section,
+# and make the per-target stuff setup host & host_cpu according to the target.
+
+host_cpu=$target_cpu
+host=$target
+
+# Map host cpu into the config cpu subdirectory name.
+# The default is $host_cpu.
+
+case "${host_cpu}" in
+
+c[12]) gdb_host_cpu=convex ;;
+hppa*) gdb_host_cpu=pa ;;
+i[345]86) gdb_host_cpu=i386 ;;
+m68*) gdb_host_cpu=m68k ;;
+np1) gdb_host_cpu=gould ;;
+pyramid) gdb_host_cpu=pyr ;;
+*) gdb_host_cpu=$target_cpu ;;
+
+esac
+
+# map host info into gdb names.
+
+case "${host}" in
+
+a29k-*-*) gdb_host=ultra3 ;;
+
+arm-*-*) gdb_host=arm ;;
+
+c[12]-*-*) gdb_host=convex ;;
+
+hppa*-hp-bsd*) gdb_host=hppabsd ;;
+hppa*-hp-hpux*) gdb_host=hppahpux ;;
+
+i[345]86-ncr-*) gdb_host=ncr3000 ;;
+i[345]86-sequent-*) gdb_host=symmetry ;;
+
+i[345]86-*-bsd*) gdb_host=i386bsd ;;
+i[345]86-*-lynxos*) gdb_host=i386lynx ;;
+i[345]86-*-go32) gdb_host=go32
+ gdb_serial_driver=ser-go32.c
+ ;;
+i[345]86-*-linux*) gdb_host=linux ;;
+i[345]86-*-mach) gdb_host=i386mach ;;
+i[345]86-*-sco3.2v4*) gdb_host=i386sco4 ;;
+i[345]86-*-sco*) gdb_host=i386sco ;;
+i[345]86-*-solaris*) gdb_host=i386sol2 ;;
+i[345]86-*-sunos*) gdb_host=sun386 ;;
+i[345]86-*-sysv3.2) gdb_host=i386v32 ;;
+i[345]86-*-sysv4*) gdb_host=i386v4 ;;
+i[345]86-*-sysv*) gdb_host=i386v ;;
+
+m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;;
+m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;;
+m68030-sony-*) gdb_host=news1000 ;;
+
+m68*-altos-*) gdb_host=altos ;;
+m68*-apollo*-sysv*) gdb_host=apollo68v ;;
+m68*-apollo*-bsd*) gdb_host=apollo68b ;;
+m68*-att-*) gdb_host=3b1 ;;
+m68*-cbm-sysv4*) gdb_host=amix ;;
+m68*-hp-bsd*) gdb_host=hp300bsd ;;
+m68*-hp-hpux*) gdb_host=hp300hpux ;;
+m68*-isi-*) gdb_host=isi ;;
+m68*-*-lynxos*) gdb_host=m68klynx ;;
+m68*-sony-*) gdb_host=news ;;
+m68*-sun-sunos3*) gdb_host=sun3os3 ;;
+m68*-sun-sunos4*) gdb_host=sun3os4 ;;
+m68*-sun-*) gdb_host=sun3os4 ;;
+
+m88k-motorola-*) gdb_host=delta88 ;;
+m88k-*-*) gdb_host=m88k ;;
+
+mips-dec-*) gdb_host=decstation ;;
+mips-little-*) gdb_host=littlemips ;;
+mips-sgi-irix3) gdb_host=irix3 ;;
+mips-sgi-irix4*) gdb_host=irix4 ;;
+mips-sony-*) gdb_host=bigmips ;;
+
+none-*-*) gdb_host=none ;;
+
+np1-*-*) gdb_host=np1 ;;
+
+ns32k-umax-*) gdb_host=umax ;;
+ns32k-utek-sysv) gdb_host=merlin ;;
+
+pn-*-*) gdb_host=pn ;;
+
+pyramid-*-*) gdb_host=pyramid ;;
+
+romp-*-*) gdb_host=rtbsd ;;
+
+rs6000-*-*) gdb_host=rs6000 ;;
+
+sparc-*-lynxos*) gdb_host=sparclynx ;;
+sparc-*-solaris2*) gdb_host=sun4sol2 ;;
+sparc-*-sunos4*) gdb_host=sun4os4 ;;
+sparc-*-*) gdb_host=sun4os4 ;;
+
+tahoe-*-*) gdb_host=tahoe ;;
+
+vax-*-bsd*) gdb_host=vaxbsd ;;
+vax-*-ultrix2*) gdb_host=vaxult2 ;;
+vax-*-ultrix*) gdb_host=vaxult ;;
+
+esac
+
+if [ ! -f ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ]; then
+ echo '***' "GDB remote does not support host ${host}" 1>&2
+ exit 1
+fi
+
+# We really shouldn't depend on there being a space after XM_FILE= ...
+hostfile=`awk '$1 == "XM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+
+# per-target:
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+
+case "${target_cpu}" in
+
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[345]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+np1) gdb_target_cpu=gould ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+
+esac
+
+# map target info into gdb names.
+
+case "${target}" in
+
+a29k-*-aout) gdb_target=a29k ;;
+a29k-*-coff) gdb_target=a29k ;;
+a29k-*-elf) gdb_target=a29k ;;
+a29k-*-ebmon) gdb_target=a29k ;;
+a29k-*-kern) gdb_target=a29k-kern ;;
+a29k-*-none) gdb_target=a29k ;;
+a29k-*-sym1) gdb_target=ultra3 ;;
+a29k-*-udi) gdb_target=a29k-udi ;;
+
+arm-*-*) gdb_target=arm ;;
+
+c1-*-*) gdb_target=convex ;;
+c2-*-*) gdb_target=convex ;;
+
+h8300-*-*) gdb_target=h8300hms ;;
+h8500-*-*) gdb_target=h8500hms ;;
+
+sh-*-*) gdb_target=sh ;;
+
+hppa*-*-bsd*) gdb_target=hppabsd ;;
+hppa*-*-hpux*) gdb_target=hppahpux ;;
+
+i[345]86-sequent-*) gdb_target=symmetry ;;
+i[345]86-ncr-*) gdb_target=ncr3000 ;;
+
+i[345]86-*-aout) gdb_target=i386aout ;;
+i[345]86-*-coff) gdb_target=i386v ;;
+i[345]86-*-elf) gdb_target=i386v ;;
+
+i[345]86-*-bsd*) gdb_target=i386bsd ;;
+i[345]86-*-lynxos*) gdb_target=i386lynx ;;
+i[345]86-*-go32) gdb_target=i386aout ;;
+i[345]86-*-solaris*) gdb_target=i386sol2 ;;
+i[345]86-*-sunos*) gdb_target=sun386 ;;
+i[345]86-*-sysv4*) gdb_target=i386v4 ;;
+i[345]86-*-sco*) gdb_target=i386v ;;
+i[345]86-*-sysv*) gdb_target=i386v ;;
+i[345]86-*-linux*) gdb_target=linux ;;
+
+i960-*-bout) gdb_target=vxworks960 ;;
+i960-*-coff) gdb_target=nindy960 ;;
+i960-*-elf) gdb_target=nindy960 ;;
+
+i960-*-nindy) gdb_target=nindy960 ;;
+i960-*-vxworks) gdb_target=vxworks960 ;;
+
+m68000-*-aout) gdb_target=m68k-nofp ;;
+m68000-*-coff) gdb_target=m68k-nofp ;;
+m68000-*-elf) gdb_target=m68k-nofp ;;
+m68000-*-sunos3*) gdb_target=sun2os3 ;;
+m68000-*-sunos4*) gdb_target=sun2os4 ;;
+
+m68*-cbm-sysv4*) gdb_target=amix ;;
+m68*-hp-bsd*) gdb_target=hp300bsd ;;
+m68*-hp-hpux*) gdb_target=hp300hpux ;;
+
+m68*-altos-*) gdb_target=altos ;;
+m68*-att-*) gdb_target=3b1 ;;
+m68*-ericsson-*) gdb_target=es1800 ;;
+m68*-isi-*) gdb_target=isi ;;
+m68*-netx-*) gdb_target=vxworks68 ;;
+m68*-sony-*) gdb_target=news ;;
+m68*-tandem-*) gdb_target=st2000 ;;
+
+m68*-*-aout) gdb_target=m68k-fp ;;
+m68*-*-coff) gdb_target=m68k-fp ;;
+m68*-*-elf) gdb_target=m68k-fp ;;
+m68*-*-lynxos*) gdb_target=m68klynx ;;
+m68*-*-os68k) gdb_target=os68k ;;
+m68*-*-sunos3*) gdb_target=sun3os3 ;;
+m68*-*-sunos4*) gdb_target=sun3os4 ;;
+m68*-*-vxworks*) gdb_target=vxworks68 ;;
+
+m88k-motorola-*) gdb_target=delta88 ;;
+m88k-*-*) gdb_target=m88k ;;
+
+mips-big-*) gdb_target=bigmips ;;
+mips-dec-*) gdb_target=decstation ;;
+mips-idt-ecoff) gdb_target=idt ;;
+mips-little-*) gdb_target=littlemips ;;
+mips-sgi-*) gdb_target=irix3 ;;
+mips-sony-*) gdb_target=bigmips ;;
+
+none-*-*) gdb_target=none ;;
+
+np1-*-*) gdb_target=np1 ;;
+
+ns32k-utek-sysv) gdb_target=merlin ;;
+ns32k-utek-*) gdb_target=umax ;;
+
+pn-*-*) gdb_target=pn ;;
+
+pyramid-*-*) gdb_target=pyramid ;;
+
+rs6000-*-*) gdb_target=rs6000 ;;
+
+sparc-*-aout) gdb_target=sparc-em ;;
+sparc-*-coff) gdb_target=sparc-em ;;
+sparc-*-elf) gdb_target=sparc-em ;;
+sparc-*-lynxos*) gdb_target=sparclynx ;;
+sparc-*-solaris2*) gdb_target=sun4sol2 ;;
+sparc-*-sunos4*) gdb_target=sun4os4 ;;
+sparc-*-vxworks*) gdb_target=sparc-em ;;
+sparc-*-*) gdb_target=sun4os4 ;;
+sparclite*-*-*) gdb_target=sparclite ;;
+
+tahoe-*-*) gdb_target=tahoe ;;
+vax-*-*) gdb_target=vax ;;
+
+z8k-*-sim) gdb_target=z8ksim ;;
+esac
+
+if [ ! -f ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt ]; then
+ echo '***' "GDB remote does not support target ${target}" 1>&2
+ exit 1
+fi
+
+if [ -z "${removing}" ] ; then
+ cat ${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh ${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt | awk '$1 == "#msg" {
+ print substr($0,6)}'
+fi
+
+# We really shouldn't depend on there being a space after TM_FILE= ...
+targetfile=`awk '$1 == "TM_FILE=" { print $2 }' <${srcdir}/../config/${gdb_target_cpu}/${gdb_target}.mt`
+
+if [ "${target}" = "${host}" ] ; then
+ nativefile=`awk '$1 == "NAT_FILE=" { print $2 }' <${srcdir}/../config/${gdb_host_cpu}/${gdb_host}.mh`
+fi
+
+host_makefile_frag=../config/${gdb_host_cpu}/${gdb_host}.mh
+target_makefile_frag=../config/${gdb_target_cpu}/${gdb_target}.mt
+
+# If hostfile (XM_FILE) and/or targetfile (TM_FILE) and/or nativefile
+# (NAT_FILE) is not set in the ?config/* file, we don't make the
+# corresponding links. But we have to remove the xm.h files and tm.h
+# files anyway, e.g. when switching from "configure host" to
+# "configure none".
+
+files=
+links=
+rm -f xm.h
+rm -f ser-hardwire.c
+if [ "${hostfile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${hostfile} ]; then
+ files="${files} ../config/${hostfile}"
+ else
+ files="${files} ../config/${gdb_host_cpu}/${hostfile}"
+ fi
+ links="${links} xm.h"
+
+# files="${files} ${gdb_serial_driver}"
+# links="${links} ser-hardwire.c"
+fi
+rm -f tm.h
+if [ "${targetfile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${targetfile} ]; then
+ files="${files} ../config/${targetfile}"
+ else
+ files="${files} ../config/${gdb_target_cpu}/${targetfile}"
+ fi
+ links="${links} tm.h"
+fi
+rm -f nm.h
+if [ "${nativefile}" != "" ]; then
+ if [ -f ${srcdir}/../config/${nativefile} ]; then
+ files="${files} ../config/${nativefile}"
+ else
+ files="${files} ../config/${gdb_host_cpu}/${nativefile}"
+ fi
+ links="${links} nm.h"
+# temporary scaffolding until all hosts have the host/target/native
+# split in place.
+else
+ files="${files} ../config/nm-trash.h"
+ links="${links} nm.h"
+fi
+
+if [ ${target_cpu} = "sparclite" ]; then
+ configdirs="${configdirs} sparclite"
+fi
+
+# post-target:
+
+if [ "${nativefile}" = "" ] ; then
+ sed -e '/^NATDEPFILES= /s//# NATDEPFILES= /' \
+ < Makefile > Makefile.tem
+ mv -f Makefile.tem Makefile
+fi
diff --git a/contrib/gdb/gdb/gdbserver/gdbreplay.c b/contrib/gdb/gdb/gdbserver/gdbreplay.c
new file mode 100644
index 0000000..4d5795a
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/gdbreplay.c
@@ -0,0 +1,319 @@
+/* Replay a remote debug session logfile for GDB.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <sgtty.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <signal.h>
+#include <ctype.h>
+
+/* Sort of a hack... */
+#define EOL (EOF - 1)
+
+static int remote_desc;
+
+/* Print the system error message for errno, and also mention STRING
+ as the file name for which the error was encountered.
+ Then return to command level. */
+
+void
+perror_with_name (string)
+ char *string;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ extern int errno;
+ char *err;
+ char *combined;
+
+ err = (errno < sys_nerr) ? sys_errlist[errno] : "unknown error";
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+ fprintf (stderr, "\n%s.\n", combined);
+ fflush (stderr);
+ exit (1);
+}
+
+static void
+sync_error (fp, desc, expect, got)
+ FILE *fp;
+ char *desc;
+ int expect;
+ int got;
+{
+ fprintf (stderr, "\n%s\n", desc);
+ fprintf (stderr, "At logfile offset %ld, expected '0x%x' got '0x%x'\n",
+ ftell (fp), expect, got);
+ fflush (stderr);
+ exit (1);
+}
+
+void
+remote_close()
+{
+ close (remote_desc);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+void
+remote_open (name)
+ char *name;
+{
+ struct sgttyb sg;
+ extern char *strchr ();
+
+ if (!strchr (name, ':'))
+ {
+ fprintf (stderr, "%s: Must specify tcp connection as host:addr\n", name);
+ fflush (stderr);
+ exit (1);
+ }
+ else
+ {
+ char *port_str;
+ int port;
+ struct sockaddr_in sockaddr;
+ int tmp;
+ struct protoent *protoent;
+ int tmp_desc;
+
+ port_str = strchr (name, ':');
+
+ port = atoi (port_str + 1);
+
+ tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
+ if (tmp_desc < 0)
+ perror_with_name ("Can't open socket");
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp,
+ sizeof(tmp));
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons(port);
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind (tmp_desc, (struct sockaddr *)&sockaddr, sizeof (sockaddr))
+ || listen (tmp_desc, 1))
+ perror_with_name ("Can't bind address");
+
+ tmp = sizeof (sockaddr);
+ remote_desc = accept (tmp_desc, (struct sockaddr *)&sockaddr, &tmp);
+ if (remote_desc == -1)
+ perror_with_name ("Accept failed");
+
+ protoent = getprotobyname ("tcp");
+ if (!protoent)
+ perror_with_name ("getprotobyname");
+
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
+
+ /* Tell TCP not to delay small packets. This greatly speeds up
+ interactive response. */
+ tmp = 1;
+ setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY,
+ (char *)&tmp, sizeof(tmp));
+
+ close (tmp_desc); /* No longer need this */
+
+ signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbreplay simply
+ exits when the remote side dies. */
+ }
+
+ fcntl (remote_desc, F_SETFL, FASYNC);
+
+ fprintf (stderr, "Replay logfile using %s\n", name);
+ fflush (stderr);
+}
+
+static int tohex (ch)
+ int ch;
+{
+ if (ch >= '0' && ch <= '9')
+ {
+ return (ch - '0');
+ }
+ if (ch >= 'A' && ch <= 'F')
+ {
+ return (ch - 'A' + 10);
+ }
+ if (ch >= 'a' && ch <= 'f')
+ {
+ return (ch - 'a' + 10);
+ }
+ fprintf (stderr, "\nInvalid hex digit '%c'\n", ch);
+ fflush (stderr);
+ exit (1);
+}
+
+static int
+logchar (fp)
+ FILE *fp;
+{
+ int ch;
+ int ch2;
+
+ ch = fgetc (fp);
+ fputc (ch, stdout);
+ fflush (stdout);
+ switch (ch)
+ {
+ case '\n':
+ ch = EOL;
+ break;
+ case '\\':
+ ch = fgetc (fp);
+ fputc (ch, stdout);
+ fflush (stdout);
+ switch (ch)
+ {
+ case '\\': break;
+ case 'b': ch = '\b'; break;
+ case 'f': ch = '\f'; break;
+ case 'n': ch = '\n'; break;
+ case 'r': ch = '\r'; break;
+ case 't': ch = '\t'; break;
+ case 'v': ch = '\v'; break;
+ case 'x':
+ ch2 = fgetc (fp);
+ fputc (ch2, stdout);
+ fflush (stdout);
+ ch = tohex (ch2) << 4;
+ ch2 = fgetc (fp);
+ fputc (ch2, stdout);
+ fflush (stdout);
+ ch |= tohex (ch2);
+ break;
+ default:
+ /* Treat any other char as just itself */
+ break;
+ }
+ default:
+ break;
+ }
+ return (ch);
+}
+
+/* Accept input from gdb and match with chars from fp (after skipping one
+ blank) up until a \n is read from fp (which is not matched) */
+
+void
+expect (fp)
+ FILE *fp;
+{
+ int fromlog;
+ unsigned char fromgdb;
+
+ if ((fromlog = logchar (fp)) != ' ')
+ {
+ sync_error (fp, "Sync error during gdb read of leading blank", ' ',
+ fromlog);
+ }
+ do
+ {
+ fromlog = logchar (fp);
+ if (fromlog == EOL)
+ {
+ break;
+ }
+ read (remote_desc, &fromgdb, 1);
+ } while (fromlog == fromgdb);
+ if (fromlog != EOL)
+ {
+ sync_error (fp, "Sync error during read of gdb packet", fromlog,
+ fromgdb);
+ }
+}
+
+/* Play data back to gdb from fp (after skipping leading blank) up until a
+ \n is read from fp (which is discarded and not sent to gdb). */
+
+void
+play (fp)
+ FILE *fp;
+{
+ int fromlog;
+ char ch;
+
+ if ((fromlog = logchar (fp)) != ' ')
+ {
+ sync_error (fp, "Sync error skipping blank during write to gdb", ' ',
+ fromlog);
+ }
+ while ((fromlog = logchar (fp)) != EOL)
+ {
+ ch = fromlog;
+ write (remote_desc, &ch, 1);
+ }
+}
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ FILE *fp;
+ int ch;
+
+ if (argc < 3)
+ {
+ fprintf (stderr, "Usage: gdbreplay <logfile> <host:port>\n");
+ fflush (stderr);
+ exit (1);
+ }
+ fp = fopen (argv[1], "r");
+ if (fp == NULL)
+ {
+ perror_with_name (argv[1]);
+ }
+ remote_open (argv[2]);
+ while ((ch = logchar (fp)) != EOF)
+ {
+ switch (ch)
+ {
+ case 'w':
+ /* data sent from gdb to gdbreplay, accept and match it */
+ expect (fp);
+ break;
+ case 'r':
+ /* data sent from gdbreplay to gdb, play it */
+ play (fp);
+ break;
+ case 'c':
+ /* Command executed by gdb */
+ while ((ch = logchar (fp)) != EOL);
+ break;
+ }
+ }
+ remote_close ();
+ exit (0);
+}
+
diff --git a/contrib/gdb/gdb/gdbserver/gdbserver.1 b/contrib/gdb/gdb/gdbserver/gdbserver.1
new file mode 100644
index 0000000..9d3fdcd
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/gdbserver.1
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1993 Free Software Foundation
+.\" See section COPYING for conditions for redistribution
+.TH gdbserver 1 "2 November 1993" "Cygnus Support" "GNU Development Tools"
+.SH NAME
+gdbserver \- Remote Server for the GNU Debugger
+.SH SYNOPSIS
+.na
+.TP
+.B gdbserver
+.RB tty
+.RB prog
+.RB "[\|" args... "\|]"
+.ad b
+.SH DESCRIPTION
+GDBSERVER is a program that allows you to run GDB on a different machine
+than the one which is running the program being debugged.
+
+Usage (server (target) side):
+
+First, you need to have a copy of the program you want to debug put onto
+the target system. The program can be stripped to save space if needed, as
+GDBserver doesn't care about symbols. All symbol handling is taken care of by
+the GDB running on the host system.
+
+To use the server, you log on to the target system, and run the `gdbserver'
+program. You must tell it (a) how to communicate with GDB, (b) the name of
+your program, and (c) its arguments. The general syntax is:
+
+ target> gdbserver COMM PROGRAM [ARGS ...]
+
+For example, using a serial port, you might say:
+
+ target> gdbserver /dev/com1 emacs foo.txt
+
+This tells gdbserver to debug emacs with an argument of foo.txt, and to
+communicate with GDB via /dev/com1. Gdbserver now waits patiently for the
+host GDB to communicate with it.
+
+To use a TCP connection, you could say:
+
+ target> gdbserver host:2345 emacs foo.txt
+
+This says pretty much the same thing as the last example, except that we are
+going to communicate with the host GDB via TCP. The `host:2345' argument means
+that we are expecting to see a TCP connection from `host' to local TCP port
+2345. (Currently, the `host' part is ignored.) You can choose any number you
+want for the port number as long as it does not conflict with any existing TCP
+ports on the target system. This same port number must be used in the host
+GDBs `target remote' command, which will be described shortly. Note that if
+you chose a port number that conflicts with another service, gdbserver will
+print an error message and exit.
+
+Usage (host side):
+
+You need an unstripped copy of the target program on your host system, since
+GDB needs to examine it's symbol tables and such. Start up GDB as you normally
+would, with the target program as the first argument. (You may need to use the
+--baud option if the serial line is running at anything except 9600 baud.)
+Ie: `gdb TARGET-PROG', or `gdb --baud BAUD TARGET-PROG'. After that, the only
+new command you need to know about is `target remote'. It's argument is either
+a device name (usually a serial device, like `/dev/ttyb'), or a HOST:PORT
+descriptor. For example:
+
+ (gdb) target remote /dev/ttyb
+
+communicates with the server via serial line /dev/ttyb, and:
+
+ (gdb) target remote the-target:2345
+
+communicates via a TCP connection to port 2345 on host `the-target', where
+you previously started up gdbserver with the same port number. Note that for
+TCP connections, you must start up gdbserver prior to using the `target remote'
+command, otherwise you may get an error that looks something like
+`Connection refused'.
+.SH OPTIONS
+You have to supply the name of the program to debug
+and the tty to communicate on; the remote GDB will do everything else.
+Any remaining arguments will be passed to the program verbatim.
+.SH "SEE ALSO"
+.RB "`\|" gdb "\|'"
+entry in
+.B info\c
+\&;
+.I
+Using GDB: A Guide to the GNU Source-Level Debugger\c
+, Richard M. Stallman and Roland H. Pesch, July 1991.
+.SH COPYING
+Copyright (c) 1993 Free Software Foundation, Inc.
+.PP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.PP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.PP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
diff --git a/contrib/gdb/gdb/gdbserver/low-hppabsd.c b/contrib/gdb/gdb/gdbserver/low-hppabsd.c
new file mode 100644
index 0000000..337e6ed
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/low-hppabsd.c
@@ -0,0 +1,379 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PT_TRACE_ME, 0, 0, 0, 0);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PT_STEP : PT_CONTINUE, inferior_pid, 1, signal, 0);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area. */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+ ptrace (PT_READ_U, inferior_pid, \
+ (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
+ - KERNEL_U_ADDR
+#endif
+
+unsigned int
+register_addr (regno, blockend)
+ int regno;
+ int blockend;
+{
+ int addr;
+
+ if (regno < 0 || regno >= ARCH_NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &registers[ regno * 4 + i] = ptrace (PT_RUREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "reading register %d: %s", regno, err);
+ error (msg);
+ goto error_exit;
+ }
+ }
+ error_exit:;
+}
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1 || regno == 0)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ extern char registers[];
+ register int i;
+ unsigned int offset = U_REGS_OFFSET;
+ int scratch;
+
+ if (regno >= 0)
+ {
+ if (CANNOT_STORE_REGISTER (regno))
+ return;
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ {
+ scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ scratch, 0);
+ if (errno != 0)
+ {
+ /* Error, even if attached. Failing to write these two
+ registers is pretty serious. */
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i], 0);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "writing register %d: %s",
+ regno, err);
+ error (msg);
+ return;
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ else
+ for (regno = 0; regno < NUM_REGS; regno++)
+ store_inferior_registers (regno);
+}
+
+/* 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
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0, 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i], 0);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/contrib/gdb/gdb/gdbserver/low-linux.c b/contrib/gdb/gdb/gdbserver/low-linux.c
new file mode 100644
index 0000000..34dc643
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/low-linux.c
@@ -0,0 +1,420 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#if 0
+#include <sgtty.h>
+#endif
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+#if 0
+#include <machine/reg.h>
+#endif
+
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PTRACE_TRACEME, 0, 0, 0);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (PTRACE_KILL, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area. */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+ ptrace (PT_READ_U, inferior_pid, \
+ (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
+ - KERNEL_U_ADDR
+#endif
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+int
+i386_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+#if 0
+ /* this will be needed if fp registers are reinstated */
+ /* for now, you can look at them with 'info float'
+ * sys5 wont let you change them with ptrace anyway
+ */
+ if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
+ {
+ int ubase, fpstate;
+ struct user u;
+ ubase = blockend + 4 * (SS + 1) - KSTKSZ;
+ fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
+ return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+ }
+ else
+#endif
+ return (blockend + 4 * regmap[regnum]);
+
+}
+
+unsigned int
+register_addr (regno, blockend)
+ int regno;
+ int blockend;
+{
+ int addr;
+
+ if (regno < 0 || regno >= ARCH_NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ REGISTER_U_ADDR (addr, blockend, regno);
+
+ return addr;
+}
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ errno = 0;
+ *(int *) &registers[ regno * 4 + i] = ptrace (PTRACE_PEEKUSR, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "reading register %d: %s", regno, err);
+ error (msg);
+ goto error_exit;
+ }
+ }
+ error_exit:;
+}
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno == -1 || regno == 0)
+ for (regno = 0; regno < NUM_REGS-NUM_FREGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+ register int i;
+ unsigned int offset = U_REGS_OFFSET;
+ int scratch;
+
+ if (regno >= 0)
+ {
+#if 0
+ if (CANNOT_STORE_REGISTER (regno))
+ return;
+#endif
+ regaddr = register_addr (regno, offset);
+ errno = 0;
+#if 0
+ if (regno == PCOQ_HEAD_REGNUM || regno == PCOQ_TAIL_REGNUM)
+ {
+ scratch = *(int *) &registers[REGISTER_BYTE (regno)] | 0x3;
+ ptrace (PT_WUREGS, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ scratch, 0);
+ if (errno != 0)
+ {
+ /* Error, even if attached. Failing to write these two
+ registers is pretty serious. */
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else
+#endif
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(int))
+ {
+ errno = 0;
+ ptrace (PTRACE_POKEUSR, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(int *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ /* Warning, not error, in case we are attached; sometimes the
+ kernel doesn't let us at the registers. */
+ char *err = strerror (errno);
+ char *msg = alloca (strlen (err) + 128);
+ sprintf (msg, "writing register %d: %s",
+ regno, err);
+ error (msg);
+ return;
+ }
+ regaddr += sizeof(int);
+ }
+ }
+ else
+ for (regno = 0; regno < NUM_REGS-NUM_FREGS; regno++)
+ store_inferior_registers (regno);
+}
+
+/* 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
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (PTRACE_PEEKTEXT, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (PTRACE_POKETEXT, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/contrib/gdb/gdb/gdbserver/low-lynx.c b/contrib/gdb/gdb/gdbserver/low-lynx.c
new file mode 100644
index 0000000..3444f7a
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/low-lynx.c
@@ -0,0 +1,746 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1986, 1987, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#define LYNXOS
+#include <sys/mem.h>
+#include <sys/signal.h>
+#include <sys/file.h>
+#include <sys/kernel.h>
+#ifndef __LYNXOS
+#define __LYNXOS
+#endif
+#include <sys/itimer.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/proc.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/fpp.h>
+
+char registers[REGISTER_BYTES];
+
+#include <sys/ptrace.h>
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ int pgrp;
+
+ /* Switch child to it's own process group so that signals won't
+ directly affect gdbserver. */
+
+ pgrp = getpid();
+ setpgrp(0, pgrp);
+ ioctl (0, TIOCSPGRP, &pgrp);
+
+ ptrace (PTRACE_TRACEME, 0, (PTRACE_ARG3_TYPE)0, 0);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "GDBserver (process %d): Cannot exec %s: %s.\n",
+ getpid(), program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (PTRACE_KILL, inferior_pid, 0, 0);
+ wait (0);
+
+ inferior_pid = 0;
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ /* Arggh. Apparently pthread_kill only works for threads within
+ the process that calls pthread_kill.
+
+ We want to avoid the lynx signal extensions as they simply don't
+ map well to the generic gdb interface we want to keep.
+
+ All we want to do is determine if a particular thread is alive;
+ it appears as if we can just make a harmless thread specific
+ ptrace call to do that. */
+ return (ptrace (PTRACE_THREADUSER,
+ BUILDPID (PIDGET (inferior_pid), pid), 0, 0) != -1);
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ while (1)
+ {
+ enable_async_io();
+
+ pid = wait (&w);
+
+ disable_async_io();
+
+ if (pid != PIDGET(inferior_pid))
+ perror_with_name ("wait");
+
+ thread_from_wait = w.w_tid;
+ inferior_pid = BUILDPID (inferior_pid, w.w_tid);
+
+ if (WIFSTOPPED(w)
+ && WSTOPSIG(w) == SIGTRAP)
+ {
+ int realsig;
+
+ realsig = ptrace (PTRACE_GETTRACESIG, inferior_pid,
+ (PTRACE_ARG3_TYPE)0, 0);
+
+ if (realsig == SIGNEWTHREAD)
+ {
+ /* It's a new thread notification. Nothing to do here since
+ the machine independent code in wait_for_inferior will
+ add the thread to the thread list and restart the thread
+ when pid != inferior_pid and pid is not in the thread list.
+ We don't even want to muck with realsig -- the code in
+ wait_for_inferior expects SIGTRAP. */
+ ;
+ }
+ }
+ break;
+ }
+
+ if (WIFEXITED (w))
+ {
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT,
+ BUILDPID (inferior_pid, cont_thread == -1 ? 0 : cont_thread),
+ 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+
+/* Mapping between GDB register #s and offsets into econtext. Must be
+ consistent with REGISTER_NAMES macro in various tmXXX.h files. */
+
+#define X(ENTRY)(offsetof(struct econtext, ENTRY))
+
+#ifdef I386
+/* Mappings from tm-i386v.h */
+
+static int regmap[] =
+{
+ X(eax),
+ X(ecx),
+ X(edx),
+ X(ebx),
+ X(esp), /* sp */
+ X(ebp), /* fp */
+ X(esi),
+ X(edi),
+ X(eip), /* pc */
+ X(flags), /* ps */
+ X(cs),
+ X(ss),
+ X(ds),
+ X(es),
+ X(ecode), /* Lynx doesn't give us either fs or gs, so */
+ X(fault), /* we just substitute these two in the hopes
+ that they are useful. */
+};
+#endif
+
+#ifdef M68K
+/* Mappings from tm-m68k.h */
+
+static int regmap[] =
+{
+ X(regs[0]), /* d0 */
+ X(regs[1]), /* d1 */
+ X(regs[2]), /* d2 */
+ X(regs[3]), /* d3 */
+ X(regs[4]), /* d4 */
+ X(regs[5]), /* d5 */
+ X(regs[6]), /* d6 */
+ X(regs[7]), /* d7 */
+ X(regs[8]), /* a0 */
+ X(regs[9]), /* a1 */
+ X(regs[10]), /* a2 */
+ X(regs[11]), /* a3 */
+ X(regs[12]), /* a4 */
+ X(regs[13]), /* a5 */
+ X(regs[14]), /* fp */
+ 0, /* sp */
+ X(status), /* ps */
+ X(pc),
+
+ X(fregs[0*3]), /* fp0 */
+ X(fregs[1*3]), /* fp1 */
+ X(fregs[2*3]), /* fp2 */
+ X(fregs[3*3]), /* fp3 */
+ X(fregs[4*3]), /* fp4 */
+ X(fregs[5*3]), /* fp5 */
+ X(fregs[6*3]), /* fp6 */
+ X(fregs[7*3]), /* fp7 */
+
+ X(fcregs[0]), /* fpcontrol */
+ X(fcregs[1]), /* fpstatus */
+ X(fcregs[2]), /* fpiaddr */
+ X(ssw), /* fpcode */
+ X(fault), /* fpflags */
+};
+#endif
+
+#ifdef SPARC
+/* Mappings from tm-sparc.h */
+
+#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
+
+static int regmap[] =
+{
+ -1, /* g0 */
+ X(g1),
+ X(g2),
+ X(g3),
+ X(g4),
+ -1, /* g5->g7 aren't saved by Lynx */
+ -1,
+ -1,
+
+ X(o[0]),
+ X(o[1]),
+ X(o[2]),
+ X(o[3]),
+ X(o[4]),
+ X(o[5]),
+ X(o[6]), /* sp */
+ X(o[7]), /* ra */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* l0 -> l7 */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* i0 -> i7 */
+
+ FX(f.fregs[0]), /* f0 */
+ FX(f.fregs[1]),
+ FX(f.fregs[2]),
+ FX(f.fregs[3]),
+ FX(f.fregs[4]),
+ FX(f.fregs[5]),
+ FX(f.fregs[6]),
+ FX(f.fregs[7]),
+ FX(f.fregs[8]),
+ FX(f.fregs[9]),
+ FX(f.fregs[10]),
+ FX(f.fregs[11]),
+ FX(f.fregs[12]),
+ FX(f.fregs[13]),
+ FX(f.fregs[14]),
+ FX(f.fregs[15]),
+ FX(f.fregs[16]),
+ FX(f.fregs[17]),
+ FX(f.fregs[18]),
+ FX(f.fregs[19]),
+ FX(f.fregs[20]),
+ FX(f.fregs[21]),
+ FX(f.fregs[22]),
+ FX(f.fregs[23]),
+ FX(f.fregs[24]),
+ FX(f.fregs[25]),
+ FX(f.fregs[26]),
+ FX(f.fregs[27]),
+ FX(f.fregs[28]),
+ FX(f.fregs[29]),
+ FX(f.fregs[30]),
+ FX(f.fregs[31]),
+
+ X(y),
+ X(psr),
+ X(wim),
+ X(tbr),
+ X(pc),
+ X(npc),
+ FX(fsr), /* fpsr */
+ -1, /* cpsr */
+};
+#endif
+
+#ifdef SPARC
+
+/* This routine handles some oddball cases for Sparc registers and LynxOS.
+ In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
+ It also handles knows where to find the I & L regs on the stack. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+#if 0
+ int whatregs = 0;
+
+#define WHATREGS_FLOAT 1
+#define WHATREGS_GEN 2
+#define WHATREGS_STACK 4
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETREGS,
+ BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+
+ memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
+ supply_register (G0_REGNUM, buf);
+ supply_register (TBR_REGNUM, (char *)&ec.tbr);
+
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+ for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
+ register_valid[i] = 1;
+
+ supply_register (PS_REGNUM, (char *)&ec.psr);
+ supply_register (Y_REGNUM, (char *)&ec.y);
+ supply_register (PC_REGNUM, (char *)&ec.pc);
+ supply_register (NPC_REGNUM, (char *)&ec.npc);
+ supply_register (WIM_REGNUM, (char *)&ec.wim);
+
+ memcpy (&registers[REGISTER_BYTE (O0_REGNUM)], ec.o,
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+ for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ CORE_ADDR sp;
+ int i;
+
+ sp = read_register (SP_REGNUM);
+
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE(I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 0);
+ for (i = I0_REGNUM; i <= I7_REGNUM; i++)
+ register_valid[i] = 1;
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE(L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 0);
+ for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+ for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
+ register_valid[i] = 1;
+
+ supply_register (FPS_REGNUM, (char *)&fc.fsr);
+ }
+#endif
+}
+
+/* This routine handles storing of the I & L regs for the Sparc. The trick
+ here is that they actually live on the stack. The really tricky part is
+ that when changing the stack pointer, the I & L regs must be written to
+ where the new SP points, otherwise the regs will be incorrect when the
+ process is started up again. We assume that the I & L regs are valid at
+ this point. */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+#if 0
+ int whatregs = 0;
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else if (regno == SP_REGNUM)
+ whatregs = WHATREGS_STACK | WHATREGS_GEN;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ int retval;
+
+ ec.tbr = read_register (TBR_REGNUM);
+ memcpy (&ec.g1, &registers[REGISTER_BYTE (G1_REGNUM)],
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ ec.psr = read_register (PS_REGNUM);
+ ec.y = read_register (Y_REGNUM);
+ ec.pc = read_register (PC_REGNUM);
+ ec.npc = read_register (NPC_REGNUM);
+ ec.wim = read_register (WIM_REGNUM);
+
+ memcpy (ec.o, &registers[REGISTER_BYTE (O0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ int regoffset;
+ CORE_ADDR sp;
+
+ sp = read_register (SP_REGNUM);
+
+ if (regno == -1 || regno == SP_REGNUM)
+ {
+ if (!register_valid[L0_REGNUM+5])
+ abort();
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE (I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 1);
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 1);
+ }
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ {
+ if (!register_valid[regno])
+ abort();
+ if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
+ + FRAME_SAVED_L0;
+ else
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
+ + FRAME_SAVED_I0;
+ target_xfer_memory (sp + regoffset, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno), 1);
+ }
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+
+/* We read fcontext first so that we can get good values for fq_t... */
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+
+ memcpy (fc.f.fregs, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+
+ fc.fsr = read_register (FPS_REGNUM);
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETFPREGS, BUILDPID (inferior_pid, general_thread), (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("Sparc fetch_inferior_registers(ptrace)");
+ }
+#endif
+}
+#endif /* SPARC */
+
+#ifndef SPARC
+
+/* Return the offset relative to the start of the per-thread data to the
+ saved context block. */
+
+static unsigned long
+lynx_registers_addr()
+{
+ CORE_ADDR stblock;
+ int ecpoff = offsetof(st_t, ecp);
+ CORE_ADDR ecp;
+
+ errno = 0;
+ stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE)0, 0);
+ if (errno)
+ perror_with_name ("PTRACE_THREADUSER");
+
+ ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE)ecpoff, 0);
+ if (errno)
+ perror_with_name ("lynx_registers_addr(PTRACE_PEEKTHREAD)");
+
+ return ecp - stblock;
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long reg;
+ unsigned long ecp;
+
+ ecp = lynx_registers_addr();
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int ptrace_fun = PTRACE_PEEKTHREAD;
+
+#ifdef PTRACE_PEEKUSP
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
+#endif
+
+ errno = 0;
+ reg = ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), 0);
+ if (errno)
+ perror_with_name ("fetch_inferior_registers(PTRACE_PEEKTHREAD)");
+
+ *(unsigned long *)&registers[REGISTER_BYTE (regno)] = reg;
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long reg;
+ unsigned long ecp;
+
+ ecp = lynx_registers_addr();
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ int ptrace_fun = PTRACE_POKEUSER;
+
+#ifdef PTRACE_POKEUSP
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
+#endif
+
+ reg = *(unsigned long *)&registers[REGISTER_BYTE (regno)];
+
+ errno = 0;
+ ptrace (ptrace_fun, BUILDPID (inferior_pid, general_thread),
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno]), reg);
+ if (errno)
+ perror_with_name ("PTRACE_POKEUSER");
+ }
+}
+
+#endif /* ! SPARC */
+
+/* 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
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+void
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread), addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (PTRACE_PEEKTEXT, BUILDPID (inferior_pid, general_thread),
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ while (1)
+ {
+ errno = 0;
+ ptrace (PTRACE_POKETEXT, BUILDPID (inferior_pid, general_thread), addr, buffer[i]);
+ if (errno)
+ {
+ fprintf(stderr, "\
+ptrace (PTRACE_POKETEXT): errno=%d, pid=0x%x, addr=0x%x, buffer[i] = 0x%x\n",
+ errno, BUILDPID (inferior_pid, general_thread),
+ addr, buffer[i]);
+ fprintf(stderr, "Sleeping for 1 second\n");
+ sleep(1);
+ }
+ else
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/contrib/gdb/gdb/gdbserver/low-sparc.c b/contrib/gdb/gdb/gdbserver/low-sparc.c
new file mode 100644
index 0000000..6f9810e
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/low-sparc.c
@@ -0,0 +1,334 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1986, 1987, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <sys/wait.h>
+#include "frame.h"
+#include "inferior.h"
+/***************************
+#include "initialize.h"
+****************************/
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+extern int sys_nerr;
+extern char **sys_errlist;
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PTRACE_TRACEME);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ int i;
+
+ /* Global and Out regs are fetched directly, as well as the control
+ registers. If we're getting one of the in or local regs,
+ and the stack pointer has not yet been fetched,
+ we have to do that first, since they're found in memory relative
+ to the stack pointer. */
+
+ if (ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0))
+ perror("ptrace_getregs");
+
+ registers[REGISTER_BYTE (0)] = 0;
+ memcpy (&registers[REGISTER_BYTE (1)], &inferior_registers.r_g1,
+ 15 * REGISTER_RAW_SIZE (G0_REGNUM));
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)] = inferior_registers.r_npc;
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)] = inferior_registers.r_y;
+
+ /* Floating point registers */
+
+ if (ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers,
+ 0))
+ perror("ptrace_getfpregs");
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fpu_fr);
+
+ /* These regs are saved on the stack by the kernel. Only read them
+ all (16 ptrace calls!) if we really need them. */
+
+ read_inferior_memory (*(CORE_ADDR*)&registers[REGISTER_BYTE (SP_REGNUM)],
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM));
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+ CORE_ADDR sp = *(CORE_ADDR *)&registers[REGISTER_BYTE (SP_REGNUM)];
+
+ write_inferior_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16*REGISTER_RAW_SIZE (L0_REGNUM));
+
+ memcpy (&inferior_registers.r_g1, &registers[REGISTER_BYTE (G1_REGNUM)],
+ 15 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ inferior_registers.r_ps =
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc =
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+ inferior_registers.r_npc =
+ *(int *)&registers[REGISTER_BYTE (NPC_REGNUM)];
+ inferior_registers.r_y =
+ *(int *)&registers[REGISTER_BYTE (Y_REGNUM)];
+
+ if (ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0))
+ perror("ptrace_setregs");
+
+ memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fpu_fr);
+
+ if (ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0))
+ perror("ptrace_setfpregs");
+}
+
+/* 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
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/contrib/gdb/gdb/gdbserver/low-sun3.c b/contrib/gdb/gdb/gdbserver/low-sun3.c
new file mode 100644
index 0000000..c84b79f
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/low-sun3.c
@@ -0,0 +1,313 @@
+/* Low level interface to ptrace, for the remote server for GDB.
+ Copyright (C) 1986, 1987, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "<sys/wait.h>"
+#include "frame.h"
+#include "inferior.h"
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sgtty.h>
+#include <fcntl.h>
+
+/***************Begin MY defs*********************/
+int quit_flag = 0;
+char registers[REGISTER_BYTES];
+
+/* Index within `registers' of the first byte of the space for
+ register N. */
+
+
+char buf2[MAX_REGISTER_RAW_SIZE];
+/***************End MY defs*********************/
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+extern int sys_nerr;
+extern char **sys_errlist;
+extern char **environ;
+extern int errno;
+extern int inferior_pid;
+void quit (), perror_with_name ();
+int query ();
+
+/* Start an inferior process and returns its pid.
+ ALLARGS is a vector of program-name and args.
+ ENV is the environment vector to pass. */
+
+int
+create_inferior (program, allargs)
+ char *program;
+ char **allargs;
+{
+ int pid;
+
+ pid = fork ();
+ if (pid < 0)
+ perror_with_name ("fork");
+
+ if (pid == 0)
+ {
+ ptrace (PTRACE_TRACEME);
+
+ execv (program, allargs);
+
+ fprintf (stderr, "Cannot exec %s: %s.\n", program,
+ errno < sys_nerr ? sys_errlist[errno] : "unknown error");
+ fflush (stderr);
+ _exit (0177);
+ }
+
+ return pid;
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+ ptrace (8, inferior_pid, 0, 0);
+ wait (0);
+ /*************inferior_died ();****VK**************/
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+mythread_alive (pid)
+ int pid;
+{
+ return 1;
+}
+
+/* Wait for process, returns status */
+
+unsigned char
+mywait (status)
+ char *status;
+{
+ int pid;
+ union wait w;
+
+ pid = wait (&w);
+ if (pid != inferior_pid)
+ perror_with_name ("wait");
+
+ if (WIFEXITED (w))
+ {
+ fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+ *status = 'W';
+ return ((unsigned char) WEXITSTATUS (w));
+ }
+ else if (!WIFSTOPPED (w))
+ {
+ fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+ *status = 'X';
+ return ((unsigned char) WTERMSIG (w));
+ }
+
+ fetch_inferior_registers (0);
+
+ *status = 'T';
+ return ((unsigned char) WSTOPSIG (w));
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+myresume (step, signal)
+ int step;
+ int signal;
+{
+ errno = 0;
+ ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, inferior_pid, 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+#ifdef FP0_REGNUM
+ ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+#endif
+
+ memcpy (registers, &inferior_registers, 16 * 4);
+#ifdef FP0_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ *(int *)&registers[REGISTER_BYTE (PS_REGNUM)] = inferior_registers.r_ps;
+ *(int *)&registers[REGISTER_BYTE (PC_REGNUM)] = inferior_registers.r_pc;
+#ifdef FP0_REGNUM
+ memcpy
+ (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.fps_control,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.fps_regs);
+#endif
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (ignored)
+ int ignored;
+{
+ struct regs inferior_registers;
+ struct fp_status inferior_fp_registers;
+
+ memcpy (&inferior_registers, registers, 16 * 4);
+#ifdef FP0_REGNUM
+ memcpy (&inferior_fp_registers,
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.fps_regs);
+#endif
+ inferior_registers.r_ps = *(int *)&registers[REGISTER_BYTE (PS_REGNUM)];
+ inferior_registers.r_pc = *(int *)&registers[REGISTER_BYTE (PC_REGNUM)];
+
+#ifdef FP0_REGNUM
+ memcpy (&inferior_fp_registers.fps_control,
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ (sizeof inferior_fp_registers
+ - sizeof inferior_fp_registers.fps_regs));
+#endif
+
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+#if FP0_REGNUM
+ ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+#endif
+}
+
+/* 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
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. */
+
+read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ buffer[i] = ptrace (1, inferior_pid, addr, 0);
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR.
+ On failure (cannot write the inferior)
+ returns the value of errno. */
+
+int
+write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+ extern int errno;
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (1, inferior_pid, addr, 0);
+
+ if (count > 1)
+ {
+ buffer[count - 1]
+ = ptrace (1, inferior_pid,
+ addr + (count - 1) * sizeof (int), 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ ptrace (4, inferior_pid, addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+void
+initialize ()
+{
+ inferior_pid = 0;
+}
+
+int
+have_inferior_p ()
+{
+ return inferior_pid != 0;
+}
diff --git a/contrib/gdb/gdb/gdbserver/remote-utils.c b/contrib/gdb/gdb/gdbserver/remote-utils.c
new file mode 100644
index 0000000..ff2183e
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/remote-utils.c
@@ -0,0 +1,479 @@
+/* Remote utility routines for the remote server for GDB.
+ Copyright (C) 1986, 1989, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+#include <stdio.h>
+#include <sgtty.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+
+static int kiodebug = 0;
+static int remote_desc;
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+void
+remote_open (name)
+ char *name;
+{
+ struct sgttyb sg;
+
+ if (!strchr (name, ':'))
+ {
+ remote_desc = open (name, O_RDWR);
+ if (remote_desc < 0)
+ perror_with_name ("Could not open remote device");
+
+ ioctl (remote_desc, TIOCGETP, &sg);
+ sg.sg_flags = RAW;
+ ioctl (remote_desc, TIOCSETP, &sg);
+ }
+ else
+ {
+ char *port_str;
+ int port;
+ struct sockaddr_in sockaddr;
+ int tmp;
+ struct protoent *protoent;
+ int tmp_desc;
+
+ port_str = strchr (name, ':');
+
+ port = atoi (port_str + 1);
+
+ tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
+ if (tmp_desc < 0)
+ perror_with_name ("Can't open socket");
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp,
+ sizeof(tmp));
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons(port);
+ sockaddr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind (tmp_desc, (struct sockaddr *)&sockaddr, sizeof (sockaddr))
+ || listen (tmp_desc, 1))
+ perror_with_name ("Can't bind address");
+
+ tmp = sizeof (sockaddr);
+ remote_desc = accept (tmp_desc, (struct sockaddr *)&sockaddr, &tmp);
+ if (remote_desc == -1)
+ perror_with_name ("Accept failed");
+
+ protoent = getprotobyname ("tcp");
+ if (!protoent)
+ perror_with_name ("getprotobyname");
+
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (tmp_desc, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
+
+ /* Tell TCP not to delay small packets. This greatly speeds up
+ interactive response. */
+ tmp = 1;
+ setsockopt (remote_desc, protoent->p_proto, TCP_NODELAY,
+ (char *)&tmp, sizeof(tmp));
+
+ close (tmp_desc); /* No longer need this */
+
+ signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply
+ exits when the remote side dies. */
+ }
+
+ fcntl (remote_desc, F_SETFL, FASYNC);
+
+ fprintf (stderr, "Remote debugging using %s\n", name);
+}
+
+void
+remote_close()
+{
+ close (remote_desc);
+}
+
+/* Convert hex digit A to a number. */
+
+static int
+fromhex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else
+ error ("Reply contains invalid hex digit");
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0' + nib;
+ else
+ return 'a' + nib - 10;
+}
+
+/* Send a packet to the remote machine, with error checking.
+ The data of the packet is in BUF. Returns >= 0 on success, -1 otherwise. */
+
+int
+putpkt (buf)
+ char *buf;
+{
+ int i;
+ unsigned char csum = 0;
+ char buf2[2000];
+ char buf3[1];
+ int cnt = strlen (buf);
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ /* Send it over and over until we get a positive ack. */
+
+ do
+ {
+ int cc;
+
+ if (write (remote_desc, buf2, p - buf2) != p - buf2)
+ {
+ perror ("putpkt(write)");
+ return -1;
+ }
+
+ cc = read (remote_desc, buf3, 1);
+ if (cc <= 0)
+ {
+ if (cc == 0)
+ fprintf (stderr, "putpkt(read): Got EOF\n");
+ else
+ perror ("putpkt(read)");
+
+ return -1;
+ }
+ }
+ while (buf3[0] != '+');
+
+ return 1; /* Success! */
+}
+
+/* Come here when we get an input interrupt from the remote side. This
+ interrupt should only be active while we are waiting for the child to do
+ something. About the only thing that should come through is a ^C, which
+ will cause us to send a SIGINT to the child. */
+
+static void
+input_interrupt()
+{
+ int cc;
+ char c;
+
+ cc = read (remote_desc, &c, 1);
+
+ if (cc != 1 || c != '\003')
+ {
+ fprintf(stderr, "input_interrupt, cc = %d c = %d\n", cc, c);
+ return;
+ }
+
+ kill (inferior_pid, SIGINT);
+}
+
+void
+enable_async_io()
+{
+ signal (SIGIO, input_interrupt);
+}
+
+void
+disable_async_io()
+{
+ signal (SIGIO, SIG_IGN);
+}
+
+/* Returns next char from remote GDB. -1 if error. */
+
+static int
+readchar ()
+{
+ static char buf[BUFSIZ];
+ static int bufcnt = 0;
+ static char *bufp;
+
+ if (bufcnt-- > 0)
+ return *bufp++ & 0x7f;
+
+ bufcnt = read (remote_desc, buf, sizeof (buf));
+
+ if (bufcnt <= 0)
+ {
+ if (bufcnt == 0)
+ fprintf (stderr, "readchar: Got EOF\n");
+ else
+ perror ("readchar");
+
+ return -1;
+ }
+
+ bufp = buf;
+ bufcnt--;
+ return *bufp++ & 0x7f;
+}
+
+/* Read a packet from the remote machine, with error checking,
+ and store it in BUF. Returns length of packet, or negative if error. */
+
+int
+getpkt (buf)
+ char *buf;
+{
+ char *bp;
+ unsigned char csum, c1, c2;
+ int c;
+
+ while (1)
+ {
+ csum = 0;
+
+ while (1)
+ {
+ c = readchar ();
+ if (c == '$')
+ break;
+ if (c < 0)
+ return -1;
+ }
+
+ bp = buf;
+ while (1)
+ {
+ c = readchar ();
+ if (c < 0)
+ return -1;
+ if (c == '#')
+ break;
+ *bp++ = c;
+ csum += c;
+ }
+ *bp = 0;
+
+ c1 = fromhex (readchar ());
+ c2 = fromhex (readchar ());
+ if (csum == (c1 << 4) + c2)
+ break;
+
+ fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
+ (c1 << 4) + c2, csum, buf);
+ write (remote_desc, "-", 1);
+ }
+
+ write (remote_desc, "+", 1);
+ return bp - buf;
+}
+
+void
+write_ok (buf)
+ char *buf;
+{
+ buf[0] = 'O';
+ buf[1] = 'K';
+ buf[2] = '\0';
+}
+
+void
+write_enn (buf)
+ char *buf;
+{
+ buf[0] = 'E';
+ buf[1] = 'N';
+ buf[2] = 'N';
+ buf[3] = '\0';
+}
+
+void
+convert_int_to_ascii (from, to, n)
+ char *from, *to;
+ int n;
+{
+ int nib;
+ char ch;
+ while (n--)
+ {
+ ch = *from++;
+ nib = ((ch & 0xf0) >> 4) & 0x0f;
+ *to++ = tohex (nib);
+ nib = ch & 0x0f;
+ *to++ = tohex (nib);
+ }
+ *to++ = 0;
+}
+
+
+void
+convert_ascii_to_int (from, to, n)
+ char *from, *to;
+ int n;
+{
+ int nib1, nib2;
+ while (n--)
+ {
+ nib1 = fromhex (*from++);
+ nib2 = fromhex (*from++);
+ *to++ = (((nib1 & 0x0f) << 4) & 0xf0) | (nib2 & 0x0f);
+ }
+}
+
+static char *
+outreg(regno, buf)
+ int regno;
+ char *buf;
+{
+ extern char registers[];
+
+ *buf++ = tohex (regno >> 4);
+ *buf++ = tohex (regno & 0xf);
+ *buf++ = ':';
+ convert_int_to_ascii (&registers[REGISTER_BYTE (regno)], buf, 4);
+ buf += 8;
+ *buf++ = ';';
+
+ return buf;
+}
+
+void
+prepare_resume_reply (buf, status, signal)
+ char *buf;
+ char status;
+ unsigned char signal;
+{
+ int nib;
+ char ch;
+
+ *buf++ = status;
+
+ /* FIXME! Should be converting this signal number (numbered
+ according to the signal numbering of the system we are running on)
+ to the signal numbers used by the gdb protocol (see enum target_signal
+ in gdb/target.h). */
+ nib = ((signal & 0xf0) >> 4);
+ *buf++ = tohex (nib);
+ nib = signal & 0x0f;
+ *buf++ = tohex (nib);
+
+ if (status == 'T')
+ {
+ buf = outreg (PC_REGNUM, buf);
+ buf = outreg (FP_REGNUM, buf);
+ buf = outreg (SP_REGNUM, buf);
+#ifdef NPC_REGNUM
+ buf = outreg (NPC_REGNUM, buf);
+#endif
+#ifdef O7_REGNUM
+ buf = outreg (O7_REGNUM, buf);
+#endif
+
+ /* If the debugger hasn't used any thread features, don't burden it with
+ threads. If we didn't check this, GDB 4.13 and older would choke. */
+ if (cont_thread != 0)
+ {
+ if (old_thread_from_wait != thread_from_wait)
+ {
+ sprintf (buf, "thread:%x;", thread_from_wait);
+ buf += strlen (buf);
+ old_thread_from_wait = thread_from_wait;
+ }
+ }
+ }
+ /* For W and X, we're done. */
+ *buf++ = 0;
+}
+
+void
+decode_m_packet (from, mem_addr_ptr, len_ptr)
+ char *from;
+ unsigned int *mem_addr_ptr, *len_ptr;
+{
+ int i = 0, j = 0;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+
+ while ((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ for (j = 0; j < 4; j++)
+ {
+ if ((ch = from[i++]) == 0)
+ break;
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex (ch) & 0x0f;
+ }
+}
+
+void
+decode_M_packet (from, mem_addr_ptr, len_ptr, to)
+ char *from, *to;
+ unsigned int *mem_addr_ptr, *len_ptr;
+{
+ int i = 0, j = 0;
+ char ch;
+ *mem_addr_ptr = *len_ptr = 0;
+
+ while ((ch = from[i++]) != ',')
+ {
+ *mem_addr_ptr = *mem_addr_ptr << 4;
+ *mem_addr_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ while ((ch = from[i++]) != ':')
+ {
+ *len_ptr = *len_ptr << 4;
+ *len_ptr |= fromhex (ch) & 0x0f;
+ }
+
+ convert_ascii_to_int (&from[i++], to, *len_ptr);
+}
diff --git a/contrib/gdb/gdb/gdbserver/server.c b/contrib/gdb/gdb/gdbserver/server.c
new file mode 100644
index 0000000..a583c54
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/server.c
@@ -0,0 +1,249 @@
+/* Main code for remote server for GDB.
+ Copyright (C) 1989, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+
+int cont_thread;
+int general_thread;
+int thread_from_wait;
+int old_thread_from_wait;
+int extended_protocol;
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ char ch, status, own_buf[2000], mem_buf[2000];
+ int i = 0;
+ unsigned char signal;
+ unsigned int mem_addr, len;
+
+ if (setjmp(toplevel))
+ {
+ fprintf(stderr, "Exiting\n");
+ exit(1);
+ }
+
+ if (argc < 3)
+ error("Usage: gdbserver tty prog [args ...]");
+
+ inferior_pid = create_inferior (argv[2], &argv[2]);
+ fprintf (stderr, "Process %s created; pid = %d\n", argv[2], inferior_pid);
+
+ signal = mywait (&status); /* Wait till we are at 1st instr in prog */
+
+ /* We are now stopped at the first instruction of the target process */
+
+ while (1)
+ {
+ remote_open (argv[1]);
+
+restart:
+ setjmp(toplevel);
+ while (getpkt (own_buf) > 0)
+ {
+ unsigned char sig;
+ i = 0;
+ ch = own_buf[i++];
+ switch (ch)
+ {
+ case '!':
+ extended_protocol = 1;
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case '?':
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'H':
+ switch (own_buf[1])
+ {
+ case 'g':
+ general_thread = strtol (&own_buf[2], NULL, 16);
+ write_ok (own_buf);
+ fetch_inferior_registers (0);
+ break;
+ case 'c':
+ cont_thread = strtol (&own_buf[2], NULL, 16);
+ write_ok (own_buf);
+ break;
+ default:
+ /* Silently ignore it so that gdb can extend the protocol
+ without compatibility headaches. */
+ own_buf[0] = '\0';
+ break;
+ }
+ break;
+ case 'g':
+ convert_int_to_ascii (registers, own_buf, REGISTER_BYTES);
+ break;
+ case 'G':
+ convert_ascii_to_int (&own_buf[1], registers, REGISTER_BYTES);
+ store_inferior_registers (-1);
+ write_ok (own_buf);
+ break;
+ case 'm':
+ decode_m_packet (&own_buf[1], &mem_addr, &len);
+ read_inferior_memory (mem_addr, mem_buf, len);
+ convert_int_to_ascii (mem_buf, own_buf, len);
+ break;
+ case 'M':
+ decode_M_packet (&own_buf[1], &mem_addr, &len, mem_buf);
+ if (write_inferior_memory (mem_addr, mem_buf, len) == 0)
+ write_ok (own_buf);
+ else
+ write_enn (own_buf);
+ break;
+ case 'C':
+ convert_ascii_to_int (own_buf + 1, &sig, 1);
+ myresume (0, sig);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'S':
+ convert_ascii_to_int (own_buf + 1, &sig, 1);
+ myresume (1, sig);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'c':
+ myresume (0, 0);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 's':
+ myresume (1, 0);
+ signal = mywait (&status);
+ prepare_resume_reply (own_buf, status, signal);
+ break;
+ case 'k':
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ /* When using the extended protocol, we start up a new
+ debugging session. The traditional protocol will
+ exit instead. */
+ if (extended_protocol)
+ {
+ write_ok (own_buf);
+ fprintf (stderr, "GDBserver restarting\n");
+ inferior_pid = create_inferior (argv[2], &argv[2]);
+ fprintf (stderr, "Process %s created; pid = %d\n",
+ argv[2], inferior_pid);
+
+ /* Wait till we are at 1st instruction in prog. */
+ signal = mywait (&status);
+ goto restart;
+ break;
+ }
+ else
+ {
+ exit (0);
+ break;
+ }
+ case 'T':
+ if (mythread_alive (strtol (&own_buf[1], NULL, 16)))
+ write_ok (own_buf);
+ else
+ write_enn (own_buf);
+ break;
+ case 'R':
+ /* Restarting the inferior is only supported in the
+ extended protocol. */
+ if (extended_protocol)
+ {
+ kill_inferior ();
+ write_ok (own_buf);
+ fprintf (stderr, "GDBserver restarting\n");
+ inferior_pid = create_inferior (argv[2], &argv[2]);
+ fprintf (stderr, "Process %s created; pid = %d\n",
+ argv[2], inferior_pid);
+
+ /* Wait till we are at 1st instruction in prog. */
+ signal = mywait (&status);
+ goto restart;
+ break;
+ }
+ else
+ {
+ /* It is a request we don't understand. Respond with an
+ empty packet so that gdb knows that we don't support this
+ request. */
+ own_buf[0] = '\0';
+ break;
+ }
+ default:
+ /* It is a request we don't understand. Respond with an
+ empty packet so that gdb knows that we don't support this
+ request. */
+ own_buf[0] = '\0';
+ break;
+ }
+
+ putpkt (own_buf);
+
+ if (status == 'W')
+ fprintf (stderr,
+ "\nChild exited with status %d\n", sig);
+ if (status == 'X')
+ fprintf (stderr, "\nChild terminated with signal = 0x%x\n", sig);
+ if (status == 'W' || status == 'X')
+ {
+ if (extended_protocol)
+ {
+ fprintf (stderr, "Killing inferior\n");
+ kill_inferior ();
+ write_ok (own_buf);
+ fprintf (stderr, "GDBserver restarting\n");
+ inferior_pid = create_inferior (argv[2], &argv[2]);
+ fprintf (stderr, "Process %s created; pid = %d\n",
+ argv[2], inferior_pid);
+
+ /* Wait till we are at 1st instruction in prog. */
+ signal = mywait (&status);
+ goto restart;
+ break;
+ }
+ else
+ {
+ fprintf (stderr, "GDBserver exiting\n");
+ exit (0);
+ }
+ }
+ }
+
+ /* We come here when getpkt fails.
+
+ For the extended remote protocol we exit (and this is the only
+ way we gracefully exit!).
+
+ For the traditional remote protocol close the connection,
+ and re-open it at the top of the loop. */
+ if (extended_protocol)
+ {
+ remote_close ();
+ exit (0);
+ }
+ else
+ {
+ fprintf (stderr, "Remote side has terminated connection. GDBserver will reopen the connection.\n");
+
+ remote_close ();
+ }
+ }
+}
diff --git a/contrib/gdb/gdb/gdbserver/server.h b/contrib/gdb/gdb/gdbserver/server.h
new file mode 100644
index 0000000..6aeaa09
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/server.h
@@ -0,0 +1,50 @@
+/* Common definitions for remote server for GDB.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <setjmp.h>
+
+void read_inferior_memory ();
+unsigned char mywait ();
+void myresume();
+int mythread_alive ();
+int create_inferior ();
+
+extern char registers[];
+int inferior_pid;
+extern int cont_thread;
+extern int general_thread;
+extern int thread_from_wait;
+extern int old_thread_from_wait;
+
+int remote_send ();
+int putpkt ();
+int getpkt ();
+void remote_open ();
+void write_ok ();
+void write_enn ();
+void convert_ascii_to_int ();
+void convert_int_to_ascii ();
+void prepare_resume_reply ();
+void decode_m_packet ();
+void decode_M_packet ();
+
+jmp_buf toplevel;
+
+void perror_with_name ();
diff --git a/contrib/gdb/gdb/gdbserver/utils.c b/contrib/gdb/gdb/gdbserver/utils.c
new file mode 100644
index 0000000..032dbbf2
--- /dev/null
+++ b/contrib/gdb/gdb/gdbserver/utils.c
@@ -0,0 +1,113 @@
+/* General utility routines for the remote server for GDB.
+ Copyright (C) 1986, 1989, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "server.h"
+#include <stdio.h>
+
+/* Generally useful subroutines used throughout the program. */
+
+/* Print the system error message for errno, and also mention STRING
+ as the file name for which the error was encountered.
+ Then return to command level. */
+
+void
+perror_with_name (string)
+ char *string;
+{
+ extern int sys_nerr;
+ extern char *sys_errlist[];
+ extern int errno;
+ char *err;
+ char *combined;
+
+ if (errno < sys_nerr)
+ err = sys_errlist[errno];
+ else
+ err = "unknown error";
+
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ error ("%s.", combined);
+}
+
+/* Print an error message and return to command level.
+ STRING is the error message, used as a fprintf string,
+ and ARG is passed as an argument to it. */
+
+#ifdef ANSI_PROTOTYPES
+NORETURN void
+error (char *string, ...)
+#else
+void
+error (va_alist)
+ va_dcl
+#endif
+{
+ extern jmp_buf toplevel;
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ va_start (args);
+#endif
+ fflush (stdout);
+#ifdef ANSI_PROTOTYPES
+ vfprintf (stderr, string, args);
+#else
+ {
+ char *string1;
+
+ string1 = va_arg (args, char *);
+ vfprintf (stderr, string1, args);
+ }
+#endif
+ fprintf (stderr, "\n");
+ longjmp(toplevel, 1);
+}
+
+/* Print an error message and exit reporting failure.
+ This is for a error that we cannot continue from.
+ STRING and ARG are passed to fprintf. */
+
+/* VARARGS */
+NORETURN void
+#ifdef ANSI_PROTOTYPES
+fatal (char *string, ...)
+#else
+fatal (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ fprintf (stderr, "gdb: ");
+ vfprintf (stderr, string, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+ exit (1);
+}
diff --git a/contrib/gdb/gdb/gdbtypes.c b/contrib/gdb/gdb/gdbtypes.c
new file mode 100644
index 0000000..13a111f
--- /dev/null
+++ b/contrib/gdb/gdb/gdbtypes.c
@@ -0,0 +1,1683 @@
+/* Support routines for manipulating internal types for GDB.
+ Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "bfd.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "language.h"
+#include "target.h"
+#include "value.h"
+#include "demangle.h"
+#include "complaints.h"
+
+/* These variables point to the objects
+ representing the predefined C data types. */
+
+struct type *builtin_type_void;
+struct type *builtin_type_char;
+struct type *builtin_type_short;
+struct type *builtin_type_int;
+struct type *builtin_type_long;
+struct type *builtin_type_long_long;
+struct type *builtin_type_signed_char;
+struct type *builtin_type_unsigned_char;
+struct type *builtin_type_unsigned_short;
+struct type *builtin_type_unsigned_int;
+struct type *builtin_type_unsigned_long;
+struct type *builtin_type_unsigned_long_long;
+struct type *builtin_type_float;
+struct type *builtin_type_double;
+struct type *builtin_type_long_double;
+struct type *builtin_type_complex;
+struct type *builtin_type_double_complex;
+struct type *builtin_type_string;
+
+/* Alloc a new type structure and fill it with some defaults. If
+ OBJFILE is non-NULL, then allocate the space for the type structure
+ in that objfile's type_obstack. */
+
+struct type *
+alloc_type (objfile)
+ struct objfile *objfile;
+{
+ register struct type *type;
+
+ /* Alloc the structure and start off with all fields zeroed. */
+
+ if (objfile == NULL)
+ {
+ type = (struct type *) xmalloc (sizeof (struct type));
+ }
+ else
+ {
+ type = (struct type *) obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct type));
+ OBJSTAT (objfile, n_types++);
+ }
+ memset ((char *) type, 0, sizeof (struct type));
+
+ /* Initialize the fields that might not be zero. */
+
+ TYPE_CODE (type) = TYPE_CODE_UNDEF;
+ TYPE_OBJFILE (type) = objfile;
+ TYPE_VPTR_FIELDNO (type) = -1;
+
+ return (type);
+}
+
+/* Lookup a pointer to a type TYPE. TYPEPTR, if nonzero, points
+ to a pointer to memory where the pointer type should be stored.
+ If *TYPEPTR is zero, update it to point to the pointer type we return.
+ We allocate new memory if needed. */
+
+struct type *
+make_pointer_type (type, typeptr)
+ struct type *type;
+ struct type **typeptr;
+{
+ register struct type *ntype; /* New type */
+ struct objfile *objfile;
+
+ ntype = TYPE_POINTER_TYPE (type);
+
+ if (ntype)
+ if (typeptr == 0)
+ return ntype; /* Don't care about alloc, and have new type. */
+ else if (*typeptr == 0)
+ {
+ *typeptr = ntype; /* Tracking alloc, and we have new type. */
+ return ntype;
+ }
+
+ if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
+ {
+ ntype = alloc_type (TYPE_OBJFILE (type));
+ if (typeptr)
+ *typeptr = ntype;
+ }
+ else /* We have storage, but need to reset it. */
+ {
+ ntype = *typeptr;
+ objfile = TYPE_OBJFILE (ntype);
+ memset ((char *) ntype, 0, sizeof (struct type));
+ TYPE_OBJFILE (ntype) = objfile;
+ }
+
+ TYPE_TARGET_TYPE (ntype) = type;
+ TYPE_POINTER_TYPE (type) = ntype;
+
+ /* FIXME! Assume the machine has only one representation for pointers! */
+
+ TYPE_LENGTH (ntype) = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+ TYPE_CODE (ntype) = TYPE_CODE_PTR;
+
+ /* pointers are unsigned */
+ TYPE_FLAGS (ntype) |= TYPE_FLAG_UNSIGNED;
+
+ if (!TYPE_POINTER_TYPE (type)) /* Remember it, if don't have one. */
+ TYPE_POINTER_TYPE (type) = ntype;
+
+ return ntype;
+}
+
+/* Given a type TYPE, return a type of pointers to that type.
+ May need to construct such a type if this is the first use. */
+
+struct type *
+lookup_pointer_type (type)
+ struct type *type;
+{
+ return make_pointer_type (type, (struct type **)0);
+}
+
+/* Lookup a C++ `reference' to a type TYPE. TYPEPTR, if nonzero, points
+ to a pointer to memory where the reference type should be stored.
+ If *TYPEPTR is zero, update it to point to the reference type we return.
+ We allocate new memory if needed. */
+
+struct type *
+make_reference_type (type, typeptr)
+ struct type *type;
+ struct type **typeptr;
+{
+ register struct type *ntype; /* New type */
+ struct objfile *objfile;
+
+ ntype = TYPE_REFERENCE_TYPE (type);
+
+ if (ntype)
+ if (typeptr == 0)
+ return ntype; /* Don't care about alloc, and have new type. */
+ else if (*typeptr == 0)
+ {
+ *typeptr = ntype; /* Tracking alloc, and we have new type. */
+ return ntype;
+ }
+
+ if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
+ {
+ ntype = alloc_type (TYPE_OBJFILE (type));
+ if (typeptr)
+ *typeptr = ntype;
+ }
+ else /* We have storage, but need to reset it. */
+ {
+ ntype = *typeptr;
+ objfile = TYPE_OBJFILE (ntype);
+ memset ((char *) ntype, 0, sizeof (struct type));
+ TYPE_OBJFILE (ntype) = objfile;
+ }
+
+ TYPE_TARGET_TYPE (ntype) = type;
+ TYPE_REFERENCE_TYPE (type) = ntype;
+
+ /* FIXME! Assume the machine has only one representation for references,
+ and that it matches the (only) representation for pointers! */
+
+ TYPE_LENGTH (ntype) = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+ TYPE_CODE (ntype) = TYPE_CODE_REF;
+
+ if (!TYPE_REFERENCE_TYPE (type)) /* Remember it, if don't have one. */
+ TYPE_REFERENCE_TYPE (type) = ntype;
+
+ return ntype;
+}
+
+/* Same as above, but caller doesn't care about memory allocation details. */
+
+struct type *
+lookup_reference_type (type)
+ struct type *type;
+{
+ return make_reference_type (type, (struct type **)0);
+}
+
+/* Lookup a function type that returns type TYPE. TYPEPTR, if nonzero, points
+ to a pointer to memory where the function type should be stored.
+ If *TYPEPTR is zero, update it to point to the function type we return.
+ We allocate new memory if needed. */
+
+struct type *
+make_function_type (type, typeptr)
+ struct type *type;
+ struct type **typeptr;
+{
+ register struct type *ntype; /* New type */
+ struct objfile *objfile;
+
+ if (typeptr == 0 || *typeptr == 0) /* We'll need to allocate one. */
+ {
+ ntype = alloc_type (TYPE_OBJFILE (type));
+ if (typeptr)
+ *typeptr = ntype;
+ }
+ else /* We have storage, but need to reset it. */
+ {
+ ntype = *typeptr;
+ objfile = TYPE_OBJFILE (ntype);
+ memset ((char *) ntype, 0, sizeof (struct type));
+ TYPE_OBJFILE (ntype) = objfile;
+ }
+
+ TYPE_TARGET_TYPE (ntype) = type;
+
+ TYPE_LENGTH (ntype) = 1;
+ TYPE_CODE (ntype) = TYPE_CODE_FUNC;
+
+ return ntype;
+}
+
+
+/* Given a type TYPE, return a type of functions that return that type.
+ May need to construct such a type if this is the first use. */
+
+struct type *
+lookup_function_type (type)
+ struct type *type;
+{
+ return make_function_type (type, (struct type **)0);
+}
+
+/* Implement direct support for MEMBER_TYPE in GNU C++.
+ May need to construct such a type if this is the first use.
+ The TYPE is the type of the member. The DOMAIN is the type
+ of the aggregate that the member belongs to. */
+
+struct type *
+lookup_member_type (type, domain)
+ struct type *type;
+ struct type *domain;
+{
+ register struct type *mtype;
+
+ mtype = alloc_type (TYPE_OBJFILE (type));
+ smash_to_member_type (mtype, domain, type);
+ return (mtype);
+}
+
+/* Allocate a stub method whose return type is TYPE.
+ This apparently happens for speed of symbol reading, since parsing
+ out the arguments to the method is cpu-intensive, the way we are doing
+ it. So, we will fill in arguments later.
+ This always returns a fresh type. */
+
+struct type *
+allocate_stub_method (type)
+ struct type *type;
+{
+ struct type *mtype;
+
+ mtype = alloc_type (TYPE_OBJFILE (type));
+ TYPE_TARGET_TYPE (mtype) = type;
+ /* _DOMAIN_TYPE (mtype) = unknown yet */
+ /* _ARG_TYPES (mtype) = unknown yet */
+ TYPE_FLAGS (mtype) = TYPE_FLAG_STUB;
+ TYPE_CODE (mtype) = TYPE_CODE_METHOD;
+ TYPE_LENGTH (mtype) = 1;
+ return (mtype);
+}
+
+/* Create a range type using either a blank type supplied in RESULT_TYPE,
+ or creating a new type, inheriting the objfile from INDEX_TYPE.
+
+ Indices will be of type INDEX_TYPE, and will range from LOW_BOUND to
+ HIGH_BOUND, inclusive.
+
+ FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
+ sure it is TYPE_CODE_UNDEF before we bash it into a range type? */
+
+struct type *
+create_range_type (result_type, index_type, low_bound, high_bound)
+ struct type *result_type;
+ struct type *index_type;
+ int low_bound;
+ int high_bound;
+{
+ if (result_type == NULL)
+ {
+ result_type = alloc_type (TYPE_OBJFILE (index_type));
+ }
+ TYPE_CODE (result_type) = TYPE_CODE_RANGE;
+ TYPE_TARGET_TYPE (result_type) = index_type;
+ if (TYPE_FLAGS (index_type) & TYPE_FLAG_STUB)
+ TYPE_FLAGS (result_type) |= TYPE_FLAG_TARGET_STUB;
+ else
+ TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type));
+ TYPE_NFIELDS (result_type) = 2;
+ TYPE_FIELDS (result_type) = (struct field *)
+ TYPE_ALLOC (result_type, 2 * sizeof (struct field));
+ memset (TYPE_FIELDS (result_type), 0, 2 * sizeof (struct field));
+ TYPE_FIELD_BITPOS (result_type, 0) = low_bound;
+ TYPE_FIELD_BITPOS (result_type, 1) = high_bound;
+ TYPE_FIELD_TYPE (result_type, 0) = builtin_type_int; /* FIXME */
+ TYPE_FIELD_TYPE (result_type, 1) = builtin_type_int; /* FIXME */
+
+ return (result_type);
+}
+
+/* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type TYPE.
+ Return 1 of type is a range type, 0 if it is discrete (and bounds
+ will fit in LONGEST), or -1 otherwise. */
+
+int
+get_discrete_bounds (type, lowp, highp)
+ struct type *type;
+ LONGEST *lowp, *highp;
+{
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_RANGE:
+ *lowp = TYPE_LOW_BOUND (type);
+ *highp = TYPE_HIGH_BOUND (type);
+ return 1;
+ case TYPE_CODE_ENUM:
+ if (TYPE_NFIELDS (type) > 0)
+ {
+ /* The enums may not be sorted by value, so search all
+ entries */
+ int i;
+
+ *lowp = *highp = TYPE_FIELD_BITPOS (type, 0);
+ for (i = 0; i < TYPE_NFIELDS (type); i++)
+ {
+ if (TYPE_FIELD_BITPOS (type, i) < *lowp)
+ *lowp = TYPE_FIELD_BITPOS (type, i);
+ if (TYPE_FIELD_BITPOS (type, i) > *highp)
+ *highp = TYPE_FIELD_BITPOS (type, i);
+ }
+ }
+ else
+ {
+ *lowp = 0;
+ *highp = -1;
+ }
+ return 0;
+ case TYPE_CODE_BOOL:
+ *lowp = 0;
+ *highp = 1;
+ return 0;
+ case TYPE_CODE_INT:
+ if (TYPE_LENGTH (type) > sizeof (LONGEST)) /* Too big */
+ return -1;
+ if (!TYPE_UNSIGNED (type))
+ {
+ *lowp = - (1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1));
+ *highp = -*lowp - 1;
+ return 0;
+ }
+ /* ... fall through for unsigned ints ... */
+ case TYPE_CODE_CHAR:
+ *lowp = 0;
+ /* This round-about calculation is to avoid shifting by
+ TYPE_LENGTH (type) * TARGET_CHAR_BIT, which will not work
+ if TYPE_LENGTH (type) == sizeof (LONGEST). */
+ *highp = 1 << (TYPE_LENGTH (type) * TARGET_CHAR_BIT - 1);
+ *highp = (*highp - 1) | *highp;
+ return 0;
+ default:
+ return -1;
+ }
+}
+
+/* Create an array type using either a blank type supplied in RESULT_TYPE,
+ or creating a new type, inheriting the objfile from RANGE_TYPE.
+
+ Elements will be of type ELEMENT_TYPE, the indices will be of type
+ RANGE_TYPE.
+
+ FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
+ sure it is TYPE_CODE_UNDEF before we bash it into an array type? */
+
+struct type *
+create_array_type (result_type, element_type, range_type)
+ struct type *result_type;
+ struct type *element_type;
+ struct type *range_type;
+{
+ LONGEST low_bound, high_bound;
+
+ 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;
+ if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+ low_bound = high_bound = 0;
+ CHECK_TYPEDEF (element_type);
+ TYPE_LENGTH (result_type) =
+ TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+ TYPE_NFIELDS (result_type) = 1;
+ TYPE_FIELDS (result_type) =
+ (struct field *) TYPE_ALLOC (result_type, sizeof (struct field));
+ memset (TYPE_FIELDS (result_type), 0, sizeof (struct field));
+ TYPE_FIELD_TYPE (result_type, 0) = range_type;
+ TYPE_VPTR_FIELDNO (result_type) = -1;
+
+ return (result_type);
+}
+
+/* Create a string type using either a blank type supplied in RESULT_TYPE,
+ or creating a new type. String types are similar enough to array of
+ char types that we can use create_array_type to build the basic type
+ and then bash it into a string type.
+
+ For fixed length strings, the range type contains 0 as the lower
+ bound and the length of the string minus one as the upper bound.
+
+ FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
+ sure it is TYPE_CODE_UNDEF before we bash it into a string type? */
+
+struct type *
+create_string_type (result_type, range_type)
+ struct type *result_type;
+ struct type *range_type;
+{
+ result_type = create_array_type (result_type,
+ *current_language->string_char_type,
+ range_type);
+ TYPE_CODE (result_type) = TYPE_CODE_STRING;
+ return (result_type);
+}
+
+struct type *
+create_set_type (result_type, domain_type)
+ struct type *result_type;
+ struct type *domain_type;
+{
+ LONGEST low_bound, high_bound, bit_length;
+ if (result_type == NULL)
+ {
+ result_type = alloc_type (TYPE_OBJFILE (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));
+
+ if (! (TYPE_FLAGS (domain_type) & TYPE_FLAG_STUB))
+ {
+ if (get_discrete_bounds (domain_type, &low_bound, &high_bound) < 0)
+ low_bound = high_bound = 0;
+ bit_length = high_bound - low_bound + 1;
+ TYPE_LENGTH (result_type)
+ = (bit_length + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
+ }
+ TYPE_FIELD_TYPE (result_type, 0) = domain_type;
+ 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
+ include the offset (that's the value of the MEMBER itself), but does
+ include the structure type into which it points (for some reason).
+
+ When "smashing" the type, we preserve the objfile that the
+ old type pointed to, since we aren't changing where the type is actually
+ allocated. */
+
+void
+smash_to_member_type (type, domain, to_type)
+ struct type *type;
+ struct type *domain;
+ struct type *to_type;
+{
+ struct objfile *objfile;
+
+ objfile = TYPE_OBJFILE (type);
+
+ memset ((char *) type, 0, sizeof (struct type));
+ TYPE_OBJFILE (type) = objfile;
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_DOMAIN_TYPE (type) = domain;
+ TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
+ TYPE_CODE (type) = TYPE_CODE_MEMBER;
+}
+
+/* Smash TYPE to be a type of method of DOMAIN with type TO_TYPE.
+ METHOD just means `function that gets an extra "this" argument'.
+
+ When "smashing" the type, we preserve the objfile that the
+ old type pointed to, since we aren't changing where the type is actually
+ allocated. */
+
+void
+smash_to_method_type (type, domain, to_type, args)
+ struct type *type;
+ struct type *domain;
+ struct type *to_type;
+ struct type **args;
+{
+ struct objfile *objfile;
+
+ objfile = TYPE_OBJFILE (type);
+
+ memset ((char *) type, 0, sizeof (struct type));
+ TYPE_OBJFILE (type) = objfile;
+ TYPE_TARGET_TYPE (type) = to_type;
+ TYPE_DOMAIN_TYPE (type) = domain;
+ TYPE_ARG_TYPES (type) = args;
+ TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */
+ TYPE_CODE (type) = TYPE_CODE_METHOD;
+}
+
+/* Return a typename for a struct/union/enum type without "struct ",
+ "union ", or "enum ". If the type has a NULL name, return NULL. */
+
+char *
+type_name_no_tag (type)
+ register const struct type *type;
+{
+ if (TYPE_TAG_NAME (type) != NULL)
+ return TYPE_TAG_NAME (type);
+
+ /* Is there code which expects this to return the name if there is no
+ tag name? My guess is that this is mainly used for C++ in cases where
+ the two will always be the same. */
+ return TYPE_NAME (type);
+}
+
+/* Lookup a primitive type named NAME.
+ Return zero if NAME is not a primitive type.*/
+
+struct type *
+lookup_primitive_typename (name)
+ char *name;
+{
+ struct type ** const *p;
+
+ for (p = current_language -> la_builtin_type_vector; *p != NULL; p++)
+ {
+ if (STREQ ((**p) -> name, name))
+ {
+ return (**p);
+ }
+ }
+ return (NULL);
+}
+
+/* Lookup a typedef or primitive type named NAME,
+ visible in lexical block BLOCK.
+ If NOERR is nonzero, return zero if NAME is not suitably defined. */
+
+struct type *
+lookup_typename (name, block, noerr)
+ char *name;
+ struct block *block;
+ int noerr;
+{
+ register struct symbol *sym;
+ register struct type *tmp;
+
+ sym = lookup_symbol (name, block, VAR_NAMESPACE, 0, (struct symtab **) NULL);
+ if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ {
+ tmp = lookup_primitive_typename (name);
+ if (tmp)
+ {
+ return (tmp);
+ }
+ else if (!tmp && noerr)
+ {
+ return (NULL);
+ }
+ else
+ {
+ error ("No type named %s.", name);
+ }
+ }
+ return (SYMBOL_TYPE (sym));
+}
+
+struct type *
+lookup_unsigned_typename (name)
+ char *name;
+{
+ char *uns = alloca (strlen (name) + 10);
+
+ strcpy (uns, "unsigned ");
+ strcpy (uns + 9, name);
+ return (lookup_typename (uns, (struct block *) NULL, 0));
+}
+
+struct type *
+lookup_signed_typename (name)
+ char *name;
+{
+ struct type *t;
+ char *uns = alloca (strlen (name) + 8);
+
+ strcpy (uns, "signed ");
+ strcpy (uns + 7, name);
+ t = lookup_typename (uns, (struct block *) NULL, 1);
+ /* If we don't find "signed FOO" just try again with plain "FOO". */
+ if (t != NULL)
+ return t;
+ return lookup_typename (name, (struct block *) NULL, 0);
+}
+
+/* Lookup a structure type named "struct NAME",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_struct (name, block)
+ char *name;
+ struct block *block;
+{
+ register struct symbol *sym;
+
+ sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+
+ if (sym == NULL)
+ {
+ error ("No struct type named %s.", name);
+ }
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
+ {
+ error ("This context has class, union or enum %s, not a struct.", name);
+ }
+ return (SYMBOL_TYPE (sym));
+}
+
+/* Lookup a union type named "union NAME",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_union (name, block)
+ char *name;
+ struct block *block;
+{
+ register struct symbol *sym;
+
+ sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+
+ if (sym == NULL)
+ {
+ error ("No union type named %s.", name);
+ }
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_UNION)
+ {
+ error ("This context has class, struct or enum %s, not a union.", name);
+ }
+ return (SYMBOL_TYPE (sym));
+}
+
+/* Lookup an enum type named "enum NAME",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_enum (name, block)
+ char *name;
+ struct block *block;
+{
+ register struct symbol *sym;
+
+ sym = lookup_symbol (name, block, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+ if (sym == NULL)
+ {
+ error ("No enum type named %s.", name);
+ }
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_ENUM)
+ {
+ error ("This context has class, struct or union %s, not an enum.", name);
+ }
+ return (SYMBOL_TYPE (sym));
+}
+
+/* Lookup a template type named "template NAME<TYPE>",
+ visible in lexical block BLOCK. */
+
+struct type *
+lookup_template_type (name, type, block)
+ char *name;
+ struct type *type;
+ struct block *block;
+{
+ struct symbol *sym;
+ char *nam = (char*) alloca(strlen(name) + strlen(type->name) + 4);
+ strcpy (nam, name);
+ strcat (nam, "<");
+ strcat (nam, type->name);
+ strcat (nam, " >"); /* FIXME, extra space still introduced in gcc? */
+
+ sym = lookup_symbol (nam, block, VAR_NAMESPACE, 0, (struct symtab **)NULL);
+
+ if (sym == NULL)
+ {
+ error ("No template type named %s.", name);
+ }
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
+ {
+ error ("This context has class, union or enum %s, not a struct.", name);
+ }
+ return (SYMBOL_TYPE (sym));
+}
+
+/* Given a type TYPE, lookup the type of the component of type named NAME.
+
+ TYPE can be either a struct or union, or a pointer or reference to a struct or
+ union. If it is a pointer or reference, its target type is automatically used.
+ Thus '.' and '->' are interchangable, as specified for the definitions of the
+ expression element types STRUCTOP_STRUCT and STRUCTOP_PTR.
+
+ If NOERR is nonzero, return zero if NAME is not suitably defined.
+ If NAME is the name of a baseclass type, return that type. */
+
+struct type *
+lookup_struct_elt_type (type, name, noerr)
+ struct type *type;
+ char *name;
+ int noerr;
+{
+ int i;
+
+ for (;;)
+ {
+ CHECK_TYPEDEF (type);
+ if (TYPE_CODE (type) != TYPE_CODE_PTR
+ && TYPE_CODE (type) != TYPE_CODE_REF)
+ break;
+ type = TYPE_TARGET_TYPE (type);
+ }
+
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT &&
+ TYPE_CODE (type) != TYPE_CODE_UNION)
+ {
+ target_terminal_ours ();
+ gdb_flush (gdb_stdout);
+ fprintf_unfiltered (gdb_stderr, "Type ");
+ type_print (type, "", gdb_stderr, -1);
+ error (" is not a structure or union type.");
+ }
+
+#if 0
+ /* FIXME: This change put in by Michael seems incorrect for the case where
+ the structure tag name is the same as the member name. I.E. when doing
+ "ptype bell->bar" for "struct foo { int bar; int foo; } bell;"
+ Disabled by fnf. */
+ {
+ char *typename;
+
+ typename = type_name_no_tag (type);
+ if (typename != NULL && STREQ (typename, name))
+ return type;
+ }
+#endif
+
+ for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+ {
+ char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+ if (t_field_name && STREQ (t_field_name, name))
+ {
+ return TYPE_FIELD_TYPE (type, i);
+ }
+ }
+
+ /* OK, it's not in this class. Recursively check the baseclasses. */
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ struct type *t;
+
+ t = lookup_struct_elt_type (TYPE_BASECLASS (type, i), name, noerr);
+ if (t != NULL)
+ {
+ return t;
+ }
+ }
+
+ if (noerr)
+ {
+ return NULL;
+ }
+
+ target_terminal_ours ();
+ 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 */
+}
+
+/* If possible, make the vptr_fieldno and vptr_basetype fields of TYPE
+ valid. Callers should be aware that in some cases (for example,
+ the type or one of its baseclasses is a stub type and we are
+ debugging a .o file), this function will not be able to find the virtual
+ function table pointer, and vptr_fieldno will remain -1 and vptr_basetype
+ will remain NULL. */
+
+void
+fill_in_vptr_fieldno (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ {
+ int i;
+
+ /* We must start at zero in case the first (and only) baseclass is
+ virtual (and hence we cannot share the table pointer). */
+ for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+ {
+ fill_in_vptr_fieldno (TYPE_BASECLASS (type, i));
+ if (TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, i)) >= 0)
+ {
+ TYPE_VPTR_FIELDNO (type)
+ = TYPE_VPTR_FIELDNO (TYPE_BASECLASS (type, i));
+ TYPE_VPTR_BASETYPE (type)
+ = TYPE_VPTR_BASETYPE (TYPE_BASECLASS (type, i));
+ break;
+ }
+ }
+ }
+}
+
+/* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
+
+ 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. 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. */
+
+struct complaint stub_noname_complaint =
+ {"stub type has NULL name", 0, 0};
+
+struct type *
+check_typedef (type)
+ register struct type *type;
+{
+ struct type *orig_type = type;
+ while (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+ {
+ if (!TYPE_TARGET_TYPE (type))
+ {
+ char* name;
+ struct symbol *sym;
+
+ /* It is dangerous to call lookup_symbol if we are currently
+ reading a symtab. Infinite recursion is one danger. */
+ if (currently_reading_symtab)
+ return type;
+
+ name = type_name_no_tag (type);
+ /* FIXME: shouldn't we separately check the TYPE_NAME and the
+ TYPE_TAG_NAME, and look in STRUCT_NAMESPACE and/or VAR_NAMESPACE
+ as appropriate? (this code was written before TYPE_NAME and
+ TYPE_TAG_NAME were separate). */
+ if (name == NULL)
+ {
+ complain (&stub_noname_complaint);
+ return type;
+ }
+ sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+ if (sym)
+ TYPE_TARGET_TYPE (type) = SYMBOL_TYPE (sym);
+ else
+ TYPE_TARGET_TYPE (type) = alloc_type (NULL); /* TYPE_CODE_UNDEF */
+ }
+ type = TYPE_TARGET_TYPE (type);
+ }
+
+ if ((TYPE_FLAGS(type) & TYPE_FLAG_STUB) && ! currently_reading_symtab)
+ {
+ char* name = type_name_no_tag (type);
+ /* FIXME: shouldn't we separately check the TYPE_NAME and the
+ TYPE_TAG_NAME, and look in STRUCT_NAMESPACE and/or VAR_NAMESPACE
+ as appropriate? (this code was written before TYPE_NAME and
+ TYPE_TAG_NAME were separate). */
+ struct symbol *sym;
+ if (name == NULL)
+ {
+ complain (&stub_noname_complaint);
+ return type;
+ }
+ sym = lookup_symbol (name, 0, STRUCT_NAMESPACE, 0,
+ (struct symtab **) NULL);
+ if (sym)
+ {
+ memcpy ((char *)type,
+ (char *)SYMBOL_TYPE(sym),
+ sizeof (struct type));
+ }
+ }
+
+ if (TYPE_FLAGS (type) & TYPE_FLAG_TARGET_STUB)
+ {
+ struct type *range_type;
+ struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+ if (TYPE_FLAGS (target_type) & TYPE_FLAG_STUB)
+ { }
+ else if (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 (target_type));
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
+ {
+ TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_TARGET_STUB;
+ }
+ }
+ /* Cache TYPE_LENGTH for future use. */
+ TYPE_LENGTH (orig_type) = TYPE_LENGTH (type);
+ return type;
+}
+
+/* Ugly hack to convert method stubs into method types.
+
+ He ain't kiddin'. This demangles the name of the method into a string
+ including argument types, parses out each argument type, generates
+ a string casting a zero to that type, evaluates the string, and stuffs
+ the resulting type into an argtype vector!!! Then it knows the type
+ of the whole function (including argument types for overloading),
+ which info used to be in the stab's but was removed to hack back
+ the space required for them. */
+
+void
+check_stub_method (type, i, j)
+ struct type *type;
+ int i;
+ int j;
+{
+ struct fn_field *f;
+ char *mangled_name = gdb_mangle_name (type, i, j);
+ char *demangled_name = cplus_demangle (mangled_name,
+ DMGL_PARAMS | DMGL_ANSI);
+ char *argtypetext, *p;
+ int depth = 0, argcount = 1;
+ struct type **argtypes;
+ struct type *mtype;
+
+ /* Make sure we got back a function string that we can use. */
+ if (demangled_name)
+ p = strchr (demangled_name, '(');
+
+ if (demangled_name == NULL || p == NULL)
+ error ("Internal: Cannot demangle mangled name `%s'.", mangled_name);
+
+ /* Now, read in the parameters that define this type. */
+ p += 1;
+ argtypetext = p;
+ while (*p)
+ {
+ if (*p == '(')
+ {
+ depth += 1;
+ }
+ else if (*p == ')')
+ {
+ depth -= 1;
+ }
+ else if (*p == ',' && depth == 0)
+ {
+ argcount += 1;
+ }
+
+ p += 1;
+ }
+
+ /* We need two more slots: one for the THIS pointer, and one for the
+ NULL [...] or void [end of arglist]. */
+
+ 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;
+
+ if (*p != ')') /* () means no args, skip while */
+ {
+ depth = 0;
+ while (*p)
+ {
+ if (depth <= 0 && (*p == ',' || *p == ')'))
+ {
+ /* 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;
+ }
+
+ if (*p == '(')
+ {
+ depth += 1;
+ }
+ else if (*p == ')')
+ {
+ depth -= 1;
+ }
+
+ p += 1;
+ }
+ }
+
+ if (p[-2] != '.') /* Not '...' */
+ {
+ argtypes[argcount] = builtin_type_void; /* List terminator */
+ }
+ else
+ {
+ argtypes[argcount] = NULL; /* Ellist terminator */
+ }
+
+ free (demangled_name);
+
+ f = TYPE_FN_FIELDLIST1 (type, i);
+ TYPE_FN_FIELD_PHYSNAME (f, j) = mangled_name;
+
+ /* Now update the old "stub" type into a real type. */
+ mtype = TYPE_FN_FIELD_TYPE (f, j);
+ TYPE_DOMAIN_TYPE (mtype) = type;
+ TYPE_ARG_TYPES (mtype) = argtypes;
+ TYPE_FLAGS (mtype) &= ~TYPE_FLAG_STUB;
+ TYPE_FN_FIELD_STUB (f, j) = 0;
+}
+
+const struct cplus_struct_type cplus_struct_default;
+
+void
+allocate_cplus_struct_type (type)
+ struct type *type;
+{
+ if (!HAVE_CPLUS_STRUCT (type))
+ {
+ TYPE_CPLUS_SPECIFIC (type) = (struct cplus_struct_type *)
+ TYPE_ALLOC (type, sizeof (struct cplus_struct_type));
+ *(TYPE_CPLUS_SPECIFIC(type)) = cplus_struct_default;
+ }
+}
+
+/* Helper function to initialize the standard scalar types.
+
+ If NAME is non-NULL and OBJFILE is non-NULL, then we make a copy
+ of the string pointed to by name in the type_obstack for that objfile,
+ and initialize the type name to that copy. There are places (mipsread.c
+ in particular, where init_type is called with a NULL value for NAME). */
+
+struct type *
+init_type (code, length, flags, name, objfile)
+ enum type_code code;
+ int length;
+ int flags;
+ char *name;
+ struct objfile *objfile;
+{
+ register struct type *type;
+
+ type = alloc_type (objfile);
+ TYPE_CODE (type) = code;
+ TYPE_LENGTH (type) = length;
+ TYPE_FLAGS (type) |= flags;
+ if ((name != NULL) && (objfile != NULL))
+ {
+ TYPE_NAME (type) =
+ obsavestring (name, strlen (name), &objfile -> type_obstack);
+ }
+ else
+ {
+ TYPE_NAME (type) = name;
+ }
+
+ /* C++ fancies. */
+
+ if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+ {
+ INIT_CPLUS_SPECIFIC (type);
+ }
+ return (type);
+}
+
+/* Look up a fundamental type for the specified objfile.
+ May need to construct such a type if this is the first use.
+
+ Some object file formats (ELF, COFF, etc) do not define fundamental
+ types such as "int" or "double". Others (stabs for example), do
+ define fundamental types.
+
+ For the formats which don't provide fundamental types, gdb can create
+ such types, using defaults reasonable for the current language and
+ the current target machine.
+
+ NOTE: This routine is obsolescent. Each debugging format reader
+ should manage it's own fundamental types, either creating them from
+ suitable defaults or reading them from the debugging information,
+ whichever is appropriate. The DWARF reader has already been
+ fixed to do this. Once the other readers are fixed, this routine
+ will go away. Also note that fundamental types should be managed
+ on a compilation unit basis in a multi-language environment, not
+ on a linkage unit basis as is done here. */
+
+
+struct type *
+lookup_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type **typep;
+ register int nbytes;
+
+ if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
+ {
+ error ("internal error - invalid fundamental type id %d", typeid);
+ }
+
+ /* If this is the first time we need a fundamental type for this objfile
+ then we need to initialize the vector of type pointers. */
+
+ if (objfile -> fundamental_types == NULL)
+ {
+ nbytes = FT_NUM_MEMBERS * sizeof (struct type *);
+ objfile -> fundamental_types = (struct type **)
+ obstack_alloc (&objfile -> type_obstack, nbytes);
+ memset ((char *) objfile -> fundamental_types, 0, nbytes);
+ OBJSTAT (objfile, n_types += FT_NUM_MEMBERS);
+ }
+
+ /* Look for this particular type in the fundamental type vector. If one is
+ not found, create and install one appropriate for the current language. */
+
+ typep = objfile -> fundamental_types + typeid;
+ if (*typep == NULL)
+ {
+ *typep = create_fundamental_type (objfile, typeid);
+ }
+
+ return (*typep);
+}
+
+int
+can_dereference (t)
+ struct type *t;
+{
+ /* FIXME: Should we return true for references as well as pointers? */
+ CHECK_TYPEDEF (t);
+ return
+ (t != NULL
+ && TYPE_CODE (t) == TYPE_CODE_PTR
+ && TYPE_CODE (TYPE_TARGET_TYPE (t)) != TYPE_CODE_VOID);
+}
+
+/* Chill varying string and arrays are represented as follows:
+
+ struct { int __var_length; ELEMENT_TYPE[MAX_SIZE] __var_data};
+
+ Return true if TYPE is such a Chill varying type. */
+
+int
+chill_varying_type (type)
+ struct type *type;
+{
+ if (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ || TYPE_NFIELDS (type) != 2
+ || strcmp (TYPE_FIELD_NAME (type, 0), "__var_length") != 0)
+ return 0;
+ return 1;
+}
+
+#if MAINTENANCE_CMDS
+
+static void
+print_bit_vector (bits, nbits)
+ B_TYPE *bits;
+ int nbits;
+{
+ int bitno;
+
+ for (bitno = 0; bitno < nbits; bitno++)
+ {
+ if ((bitno % 8) == 0)
+ {
+ puts_filtered (" ");
+ }
+ if (B_TST (bits, bitno))
+ {
+ printf_filtered ("1");
+ }
+ else
+ {
+ printf_filtered ("0");
+ }
+ }
+}
+
+/* The args list is a strange beast. It is either terminated by a NULL
+ pointer for varargs functions, or by a pointer to a TYPE_CODE_VOID
+ type for normal fixed argcount functions. (FIXME someday)
+ Also note the first arg should be the "this" pointer, we may not want to
+ include it since we may get into a infinitely recursive situation. */
+
+static void
+print_arg_types (args, spaces)
+ struct type **args;
+ int spaces;
+{
+ if (args != NULL)
+ {
+ while (*args != NULL)
+ {
+ recursive_dump_type (*args, spaces + 2);
+ if ((*args++) -> code == TYPE_CODE_VOID)
+ {
+ break;
+ }
+ }
+ }
+}
+
+static void
+dump_fn_fieldlists (type, spaces)
+ struct type *type;
+ int spaces;
+{
+ int method_idx;
+ int overload_idx;
+ struct fn_field *f;
+
+ 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' (",
+ 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' (",
+ 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 ");
+ 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 ");
+ 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",
+ TYPE_FN_FIELD_VOLATILE (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_private %d\n",
+ TYPE_FN_FIELD_PRIVATE (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_protected %d\n",
+ TYPE_FN_FIELD_PROTECTED (f, overload_idx));
+ printfi_filtered (spaces + 8, "is_stub %d\n",
+ TYPE_FN_FIELD_STUB (f, overload_idx));
+ printfi_filtered (spaces + 8, "voffset %u\n",
+ TYPE_FN_FIELD_VOFFSET (f, overload_idx));
+ }
+ }
+}
+
+static void
+print_cplus_stuff (type, spaces)
+ struct type *type;
+ int spaces;
+{
+ printfi_filtered (spaces, "n_baseclasses %d\n",
+ TYPE_N_BASECLASSES (type));
+ printfi_filtered (spaces, "nfn_fields %d\n",
+ TYPE_NFN_FIELDS (type));
+ printfi_filtered (spaces, "nfn_fields_total %d\n",
+ TYPE_NFN_FIELDS_TOTAL (type));
+ if (TYPE_N_BASECLASSES (type) > 0)
+ {
+ 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");
+ }
+ if (TYPE_NFIELDS (type) > 0)
+ {
+ if (TYPE_FIELD_PRIVATE_BITS (type) != NULL)
+ {
+ 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 *",
+ 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");
+ }
+ }
+ if (TYPE_NFN_FIELDS (type) > 0)
+ {
+ dump_fn_fieldlists (type, spaces);
+ }
+}
+
+static struct obstack dont_print_type_obstack;
+
+void
+recursive_dump_type (type, spaces)
+ struct type *type;
+ int spaces;
+{
+ int idx;
+
+ if (spaces == 0)
+ obstack_begin (&dont_print_type_obstack, 0);
+
+ if (TYPE_NFIELDS (type) > 0
+ || (TYPE_CPLUS_SPECIFIC (type) && TYPE_NFN_FIELDS (type) > 0))
+ {
+ struct type **first_dont_print
+ = (struct type **)obstack_base (&dont_print_type_obstack);
+
+ int i = (struct type **)obstack_next_free (&dont_print_type_obstack)
+ - first_dont_print;
+
+ while (--i >= 0)
+ {
+ if (type == first_dont_print[i])
+ {
+ printfi_filtered (spaces, "type node ");
+ gdb_print_address (type, gdb_stdout);
+ printf_filtered (" <same as already seen type>\n");
+ return;
+ }
+ }
+
+ obstack_ptr_grow (&dont_print_type_obstack, 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) : "<NULL>");
+ gdb_print_address (TYPE_NAME (type), gdb_stdout);
+ printf_filtered (")\n");
+ if (TYPE_TAG_NAME (type) != NULL)
+ {
+ 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))
+ {
+ case TYPE_CODE_UNDEF:
+ printf_filtered ("(TYPE_CODE_UNDEF)");
+ break;
+ case TYPE_CODE_PTR:
+ printf_filtered ("(TYPE_CODE_PTR)");
+ break;
+ case TYPE_CODE_ARRAY:
+ printf_filtered ("(TYPE_CODE_ARRAY)");
+ break;
+ case TYPE_CODE_STRUCT:
+ printf_filtered ("(TYPE_CODE_STRUCT)");
+ break;
+ case TYPE_CODE_UNION:
+ printf_filtered ("(TYPE_CODE_UNION)");
+ break;
+ case TYPE_CODE_ENUM:
+ printf_filtered ("(TYPE_CODE_ENUM)");
+ break;
+ case TYPE_CODE_FUNC:
+ printf_filtered ("(TYPE_CODE_FUNC)");
+ break;
+ case TYPE_CODE_INT:
+ printf_filtered ("(TYPE_CODE_INT)");
+ break;
+ case TYPE_CODE_FLT:
+ printf_filtered ("(TYPE_CODE_FLT)");
+ break;
+ case TYPE_CODE_VOID:
+ printf_filtered ("(TYPE_CODE_VOID)");
+ break;
+ case TYPE_CODE_SET:
+ printf_filtered ("(TYPE_CODE_SET)");
+ break;
+ case TYPE_CODE_RANGE:
+ printf_filtered ("(TYPE_CODE_RANGE)");
+ break;
+ case TYPE_CODE_STRING:
+ printf_filtered ("(TYPE_CODE_STRING)");
+ break;
+ case TYPE_CODE_ERROR:
+ printf_filtered ("(TYPE_CODE_ERROR)");
+ break;
+ case TYPE_CODE_MEMBER:
+ printf_filtered ("(TYPE_CODE_MEMBER)");
+ break;
+ case TYPE_CODE_METHOD:
+ printf_filtered ("(TYPE_CODE_METHOD)");
+ break;
+ case TYPE_CODE_REF:
+ printf_filtered ("(TYPE_CODE_REF)");
+ break;
+ case TYPE_CODE_CHAR:
+ printf_filtered ("(TYPE_CODE_CHAR)");
+ break;
+ case TYPE_CODE_BOOL:
+ printf_filtered ("(TYPE_CODE_BOOL)");
+ break;
+ case TYPE_CODE_TYPEDEF:
+ printf_filtered ("(TYPE_CODE_TYPEDEF)");
+ break;
+ default:
+ printf_filtered ("(UNKNOWN TYPE CODE)");
+ break;
+ }
+ puts_filtered ("\n");
+ printfi_filtered (spaces, "length %d\n", TYPE_LENGTH (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 ");
+ 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, "flags 0x%x", TYPE_FLAGS (type));
+ if (TYPE_FLAGS (type) & TYPE_FLAG_UNSIGNED)
+ {
+ puts_filtered (" TYPE_FLAG_UNSIGNED");
+ }
+ if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+ {
+ puts_filtered (" TYPE_FLAG_STUB");
+ }
+ puts_filtered ("\n");
+ 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 ",
+ idx, TYPE_FIELD_BITPOS (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)
+ : "<NULL>");
+ 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 ");
+ 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);
+ }
+ printfi_filtered (spaces, "vptr_fieldno %d\n", TYPE_VPTR_FIELDNO (type));
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_FUNC:
+ 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 ");
+ gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout);
+ puts_filtered ("\n");
+ print_cplus_stuff (type, spaces);
+ break;
+
+ default:
+ /* 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 ");
+ gdb_print_address (TYPE_CPLUS_SPECIFIC (type), gdb_stdout);
+ if (TYPE_CPLUS_SPECIFIC (type) != NULL)
+ {
+ printf_filtered (" (unknown data form)");
+ }
+ printf_filtered ("\n");
+ break;
+
+ }
+ if (spaces == 0)
+ obstack_free (&dont_print_type_obstack, NULL);
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+void
+_initialize_gdbtypes ()
+{
+ builtin_type_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "void", (struct objfile *) NULL);
+ builtin_type_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "char", (struct objfile *) NULL);
+ builtin_type_signed_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "signed char", (struct objfile *) NULL);
+ builtin_type_unsigned_char =
+ init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned char", (struct objfile *) NULL);
+ builtin_type_short =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "short", (struct objfile *) NULL);
+ builtin_type_unsigned_short =
+ init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned short", (struct objfile *) NULL);
+ builtin_type_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "int", (struct objfile *) NULL);
+ builtin_type_unsigned_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ builtin_type_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long", (struct objfile *) NULL);
+ builtin_type_unsigned_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ builtin_type_long_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long long", (struct objfile *) NULL);
+ builtin_type_unsigned_long_long =
+ init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long long", (struct objfile *) NULL);
+ builtin_type_float =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "float", (struct objfile *) NULL);
+ builtin_type_double =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double", (struct objfile *) NULL);
+ builtin_type_long_double =
+ init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "long double", (struct objfile *) NULL);
+ builtin_type_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_complex) = builtin_type_float;
+ builtin_type_double_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (builtin_type_double_complex) = builtin_type_double;
+ builtin_type_string =
+ init_type (TYPE_CODE_STRING, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0,
+ "string", (struct objfile *) NULL);
+}
diff --git a/contrib/gdb/gdb/gdbtypes.h b/contrib/gdb/gdb/gdbtypes.h
new file mode 100644
index 0000000..59313d7
--- /dev/null
+++ b/contrib/gdb/gdb/gdbtypes.h
@@ -0,0 +1,789 @@
+/* Internal type definitions for GDB.
+ Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (GDBTYPES_H)
+#define GDBTYPES_H 1
+
+/* 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
+#define FT_CHAR 2
+#define FT_SIGNED_CHAR 3
+#define FT_UNSIGNED_CHAR 4
+#define FT_SHORT 5
+#define FT_SIGNED_SHORT 6
+#define FT_UNSIGNED_SHORT 7
+#define FT_INTEGER 8
+#define FT_SIGNED_INTEGER 9
+#define FT_UNSIGNED_INTEGER 10
+#define FT_LONG 11
+#define FT_SIGNED_LONG 12
+#define FT_UNSIGNED_LONG 13
+#define FT_LONG_LONG 14
+#define FT_SIGNED_LONG_LONG 15
+#define FT_UNSIGNED_LONG_LONG 16
+#define FT_FLOAT 17
+#define FT_DBL_PREC_FLOAT 18
+#define FT_EXT_PREC_FLOAT 19
+#define FT_COMPLEX 20
+#define FT_DBL_PREC_COMPLEX 21
+#define FT_EXT_PREC_COMPLEX 22
+#define FT_STRING 23
+#define FT_FIXED_DECIMAL 24
+#define FT_FLOAT_DECIMAL 25
+#define FT_BYTE 26
+#define FT_UNSIGNED_BYTE 27
+
+#define FT_NUM_MEMBERS 28 /* Highest FT_* above, plus one. */
+
+/* Some macros for char-based bitfields. */
+
+#define B_SET(a,x) ((a)[(x)>>3] |= (1 << ((x)&7)))
+#define B_CLR(a,x) ((a)[(x)>>3] &= ~(1 << ((x)&7)))
+#define B_TST(a,x) ((a)[(x)>>3] & (1 << ((x)&7)))
+#define B_TYPE unsigned char
+#define B_BYTES(x) ( 1 + ((x)>>3) )
+#define B_CLRALL(a,x) memset ((a), 0, B_BYTES(x))
+
+/* Different kinds of data types are distinguished by the `code' field. */
+
+enum type_code
+{
+ TYPE_CODE_UNDEF, /* Not used; catches errors */
+ TYPE_CODE_PTR, /* Pointer type */
+ TYPE_CODE_ARRAY, /* Array type with lower & upper bounds. */
+ TYPE_CODE_STRUCT, /* C struct or Pascal record */
+ TYPE_CODE_UNION, /* C union or Pascal variant part */
+ TYPE_CODE_ENUM, /* Enumeration type */
+ TYPE_CODE_FUNC, /* Function type */
+ TYPE_CODE_INT, /* Integer type */
+
+ /* Floating type. This is *NOT* a complex type. Beware, there are parts
+ of GDB which bogusly assume that TYPE_CODE_FLT can mean complex. */
+ TYPE_CODE_FLT,
+
+ /* 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) */
+
+ /* 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. */
+ TYPE_CODE_ERROR,
+
+ /* C++ */
+ TYPE_CODE_MEMBER, /* Member type */
+ TYPE_CODE_METHOD, /* Method type */
+ TYPE_CODE_REF, /* C++ Reference types */
+
+ TYPE_CODE_CHAR, /* *real* character 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,
+
+ /* Fortran */
+ TYPE_CODE_COMPLEX, /* Complex float */
+
+ TYPE_CODE_TYPEDEF
+};
+
+/* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an
+ 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. */
+
+/* Unsigned integer type. If this is not set for a TYPE_CODE_INT, the
+ type is signed. */
+
+#define TYPE_FLAG_UNSIGNED (1 << 0)
+
+/* 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_typedef.
+ Used for arrays and ranges, in which TYPE_LENGTH of the array/range
+ gets set based on the TYPE_LENGTH of the target type.
+ Also, set for TYPE_CODE_TYPEDEF. */
+
+#define TYPE_FLAG_TARGET_STUB (1 << 3)
+
+struct type
+{
+
+ /* Code for kind of type */
+
+ enum type_code code;
+
+ /* Name of this type, or NULL if none.
+
+ This is used for printing only, except by poorly designed C++ code.
+ For looking up a name, look for a symbol in the VAR_NAMESPACE. */
+
+ char *name;
+
+ /* Tag name for this type, or NULL if none. This means that the
+ name of the type consists of a keyword followed by the tag name.
+ Which keyword is determined by the type code ("struct" for
+ TYPE_CODE_STRUCT, etc.). As far as I know C/C++ are the only languages
+ with this feature.
+
+ This is used for printing only, except by poorly designed C++ code.
+ For looking up a name, look for a symbol in the STRUCT_NAMESPACE.
+ One more legitimate use is that if TYPE_FLAG_STUB is set, this is
+ the name to use to look for definitions in other files. */
+
+ char *tag_name;
+
+ /* Length of storage for a value of this type. Various places pass
+ this to memcpy and such, meaning it must be in units of
+ HOST_CHAR_BIT. Various other places expect they can calculate
+ addresses by adding it and such, meaning it must be in units of
+ TARGET_CHAR_BIT. For some DSP targets, in which HOST_CHAR_BIT
+ will (presumably) be 8 and TARGET_CHAR_BIT will be (say) 32, this
+ is a problem. One fix would be to make this field in bits
+ (requiring that it always be a multiple of HOST_CHAR_BIT and
+ TARGET_CHAR_BIT)--the other choice would be to make it
+ consistently in units of HOST_CHAR_BIT. */
+
+ unsigned length;
+
+ /* FIXME, these should probably be restricted to a Fortran-specific
+ field in some fashion. */
+#define BOUND_CANNOT_BE_DETERMINED 5
+#define BOUND_BY_REF_ON_STACK 4
+#define BOUND_BY_VALUE_ON_STACK 3
+#define BOUND_BY_REF_IN_REG 2
+#define BOUND_BY_VALUE_IN_REG 1
+#define BOUND_SIMPLE 0
+ int upper_bound_type;
+ int lower_bound_type;
+
+ /* Every type is now associated with a particular objfile, and the
+ type is allocated on the type_obstack for that objfile. One problem
+ however, is that there are times when gdb allocates new types while
+ it is not in the process of reading symbols from a particular objfile.
+ Fortunately, these happen when the type being created is a derived
+ type of an existing type, such as in lookup_pointer_type(). So
+ we can just allocate the new type using the same objfile as the
+ existing type, but to do this we need a backpointer to the objfile
+ from the existing type. Yes this is somewhat ugly, but without
+ major overhaul of the internal type system, it can't be avoided
+ for now. */
+
+ struct objfile *objfile;
+
+ /* For a pointer type, describes the type of object pointed to.
+ For an array type, describes the type of the elements.
+ For a function or method type, describes the type of the return value.
+ For a range type, describes the type of the full range.
+ For a complex type, describes the type of each coordinate.
+ Unused otherwise. */
+
+ struct type *target_type;
+
+ /* Type that is a pointer to this type.
+ NULL if no such pointer-to type is known yet.
+ The debugger may add the address of such a type
+ if it has to construct one later. */
+
+ struct type *pointer_type;
+
+ /* C++: also need a reference type. */
+
+ struct type *reference_type;
+
+ /* Flags about this type. */
+
+ short flags;
+
+ /* Number of fields described for this type */
+
+ short nfields;
+
+ /* For structure and union types, a description of each field.
+ For set and pascal array types, there is one "field",
+ whose type is the domain type of the set or array.
+ For range types, there are two "fields",
+ the minimum and maximum values (both inclusive).
+ For enum types, each possible value is described by one "field".
+ For a function type, a "field" for each parameter type.
+ For C++ classes, there is one field for each base class (if it is
+ a derived class) plus one field for each class data member. Member
+ functions are recorded elsewhere.
+
+ Using a pointer to a separate array of fields
+ allows all types to have the same size, which is useful
+ because we can allocate the space for a type before
+ we know what to put in it. */
+
+ struct field
+ {
+
+ /* Position of this field, counting in bits from start of
+ containing structure. For a function type, this is the
+ position in the argument list of this argument.
+ For a range bound or enum value, this is the value itself.
+ (FIXME: What about ranges larger than host int size?)
+ For BITS_BIG_ENDIAN=1 targets, it is the bit offset to the MSB.
+ For BITS_BIG_ENDIAN=0 targets, it is the bit offset to the LSB. */
+
+ int bitpos;
+
+ /* Size of this field, in bits, or zero if not packed.
+ For an unpacked field, the field's type's length
+ says how many bytes the field occupies. */
+ /* FIXME: This is abused by TYPE_FIELD_STATIC_PHYSNAME to contain
+ a pointer, so it has to be long. */
+
+ long bitsize;
+
+ /* In a struct or enum type, type of this field.
+ In a function type, type of this argument.
+ In an array type, the domain-type of the array. */
+
+ struct type *type;
+
+ /* Name of field, value or argument.
+ NULL for range bounds and array domains. */
+
+ char *name;
+
+ } *fields;
+
+ /* For types with virtual functions, VPTR_BASETYPE is the base class which
+ defined the virtual function table pointer.
+
+ For types that are pointer to member types, VPTR_BASETYPE
+ is the type that this pointer is a member of.
+
+ Unused otherwise. */
+
+ struct type *vptr_basetype;
+
+ /* Field number of the virtual function table pointer in
+ VPTR_BASETYPE. If -1, we were unable to find the virtual
+ function table pointer in initial symbol reading, and
+ fill_in_vptr_fieldno should be called to find it if possible.
+
+ Unused if this type does not have virtual functions. */
+
+ int vptr_fieldno;
+
+ /* Slot to point to additional language-specific fields of this type. */
+
+ union type_specific
+ {
+
+ /* ARG_TYPES is for TYPE_CODE_METHOD and TYPE_CODE_FUNC. */
+
+ struct type **arg_types;
+
+ /* CPLUS_STUFF is for TYPE_CODE_STRUCT. It is initialized to point to
+ cplus_struct_default, a default static instance of a struct
+ cplus_struct_type. */
+
+ struct cplus_struct_type *cplus_stuff;
+
+ } type_specific;
+};
+
+#define NULL_TYPE ((struct type *) 0)
+
+/* C++ language-specific information for TYPE_CODE_STRUCT and TYPE_CODE_UNION
+ nodes. */
+
+struct cplus_struct_type
+{
+ /* Number of base classes this type derives from. The baseclasses are
+ stored in the first N_BASECLASSES fields (i.e. the `fields' field of
+ the struct type). I think only the `type' field of such a field has
+ any meaning. */
+
+ short n_baseclasses;
+
+ /* Number of methods with unique names. All overloaded methods with
+ the same name count only once. */
+
+ short nfn_fields;
+
+ /* Number of methods described for this type, not including the
+ methods that it derives from. */
+
+ int nfn_fields_total;
+
+ /* For derived classes, the number of base classes is given by n_baseclasses
+ and virtual_field_bits is a bit vector containing one bit per base class.
+ If the base class is virtual, the corresponding bit will be set.
+ I.E, given:
+
+ class A{};
+ class B{};
+ class C : public B, public virtual A {};
+
+ B is a baseclass of C; A is a virtual baseclass for C.
+ This is a C++ 2.0 language feature. */
+
+ B_TYPE *virtual_field_bits;
+
+ /* For classes with private fields, the number of fields is given by
+ nfields and private_field_bits is a bit vector containing one bit
+ per field.
+ If the field is private, the corresponding bit will be set. */
+
+ B_TYPE *private_field_bits;
+
+ /* For classes with protected fields, the number of fields is given by
+ nfields and protected_field_bits is a bit vector containing one bit
+ per field.
+ If the field is private, the corresponding bit will be set. */
+
+ 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
+ has been renamed to make it distinct.
+
+ fn_fieldlists points to an array of nfn_fields of these. */
+
+ struct fn_fieldlist
+ {
+
+ /* The overloaded name. */
+
+ char *name;
+
+ /* The number of methods with this name. */
+
+ int length;
+
+ /* The list of methods. */
+
+ struct fn_field
+ {
+
+ /* If is_stub is clear, this is the mangled name which we can
+ look up to find the address of the method (FIXME: it would
+ be cleaner to have a pointer to the struct symbol here
+ instead). */
+
+ /* If is_stub is set, this is the portion of the mangled
+ name which specifies the arguments. For example, "ii",
+ if there are two int arguments, or "" if there are no
+ arguments. See gdb_mangle_name for the conversion from this
+ format to the one used if is_stub is clear. */
+
+ char *physname;
+
+ /* The return value of the method */
+
+ struct type *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. Should not contain
+ a `this' pointer for static member functions. */
+
+ struct type **args;
+
+ /* For virtual functions.
+ First baseclass that defines this virtual function. */
+
+ struct type *fcontext;
+
+ /* Attributes. */
+
+ unsigned int is_const : 1;
+ unsigned int is_volatile : 1;
+ unsigned int is_private : 1;
+ unsigned int is_protected : 1;
+
+ /* A stub method only has some fields valid (but they are enough
+ to reconstruct the rest of the fields). */
+ unsigned int is_stub : 1;
+
+ /* Unused. */
+ unsigned int dummy : 3;
+
+ /* Index into that baseclass's virtual function table,
+ minus 2; else if static: VOFFSET_STATIC; else: 0. */
+
+ unsigned int voffset : 24;
+
+# define VOFFSET_STATIC 1
+
+ } *fn_fields;
+
+ } *fn_fieldlists;
+
+};
+
+/* The default value of TYPE_CPLUS_SPECIFIC(T) points to the
+ this shared static structure. */
+
+extern const struct cplus_struct_type cplus_struct_default;
+
+extern void
+allocate_cplus_struct_type PARAMS ((struct type *));
+
+#define INIT_CPLUS_SPECIFIC(type) \
+ (TYPE_CPLUS_SPECIFIC(type)=(struct cplus_struct_type*)&cplus_struct_default)
+#define ALLOCATE_CPLUS_STRUCT_TYPE(type) allocate_cplus_struct_type (type)
+#define HAVE_CPLUS_STRUCT(type) \
+ (TYPE_CPLUS_SPECIFIC(type) != &cplus_struct_default)
+
+#define TYPE_NAME(thistype) (thistype)->name
+#define TYPE_TAG_NAME(type) ((type)->tag_name)
+#define TYPE_TARGET_TYPE(thistype) (thistype)->target_type
+#define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
+#define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
+/* Note that if thistype is a TYPEDEF type, you have to call check_typedef.
+ But check_typedef does set the TYPE_LENGTH of the TYPEDEF type,
+ so you only have to call check_typedef once. Since allocate_value
+ calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe. */
+#define TYPE_LENGTH(thistype) (thistype)->length
+#define TYPE_OBJFILE(thistype) (thistype)->objfile
+#define TYPE_FLAGS(thistype) (thistype)->flags
+#define TYPE_UNSIGNED(thistype) ((thistype)->flags & TYPE_FLAG_UNSIGNED)
+/* Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you wan the real
+ type, you need to do TYPE_CODE (check_type (this_type)). */
+#define TYPE_CODE(thistype) (thistype)->code
+#define TYPE_NFIELDS(thistype) (thistype)->nfields
+#define TYPE_FIELDS(thistype) (thistype)->fields
+
+#define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0)
+#define TYPE_LOW_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 0)
+#define TYPE_HIGH_BOUND(range_type) TYPE_FIELD_BITPOS (range_type, 1)
+
+/* Moto-specific stuff for FORTRAN arrays */
+
+#define TYPE_ARRAY_UPPER_BOUND_TYPE(thistype) (thistype)->upper_bound_type
+#define TYPE_ARRAY_LOWER_BOUND_TYPE(thistype) (thistype)->lower_bound_type
+
+#define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
+ (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),1))
+
+#define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \
+ (TYPE_FIELD_BITPOS((TYPE_FIELD_TYPE((arraytype),0)),0))
+
+/* C++ */
+
+#define TYPE_VPTR_BASETYPE(thistype) (thistype)->vptr_basetype
+#define TYPE_DOMAIN_TYPE(thistype) (thistype)->vptr_basetype
+#define TYPE_VPTR_FIELDNO(thistype) (thistype)->vptr_fieldno
+#define TYPE_FN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->fn_fields
+#define TYPE_NFN_FIELDS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields
+#define TYPE_NFN_FIELDS_TOTAL(thistype) TYPE_CPLUS_SPECIFIC(thistype)->nfn_fields_total
+#define TYPE_TYPE_SPECIFIC(thistype) (thistype)->type_specific
+#define TYPE_ARG_TYPES(thistype) (thistype)->type_specific.arg_types
+#define TYPE_CPLUS_SPECIFIC(thistype) (thistype)->type_specific.cplus_stuff
+#define TYPE_BASECLASS(thistype,index) (thistype)->fields[index].type
+#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
+#define TYPE_BASECLASS_NAME(thistype,index) (thistype)->fields[index].name
+#define TYPE_BASECLASS_BITPOS(thistype,index) (thistype)->fields[index].bitpos
+#define BASETYPE_VIA_PUBLIC(thistype, index) (!TYPE_FIELD_PRIVATE(thistype, index))
+#define BASETYPE_VIA_VIRTUAL(thistype, index) \
+ B_TST(TYPE_CPLUS_SPECIFIC(thistype)->virtual_field_bits, (index))
+
+#define TYPE_FIELD(thistype, n) (thistype)->fields[n]
+#define TYPE_FIELD_TYPE(thistype, n) (thistype)->fields[n].type
+#define TYPE_FIELD_NAME(thistype, n) (thistype)->fields[n].name
+#define TYPE_FIELD_VALUE(thistype, n) (* (int*) &(thistype)->fields[n].type)
+#define TYPE_FIELD_BITPOS(thistype, n) (thistype)->fields[n].bitpos
+#define TYPE_FIELD_BITSIZE(thistype, n) (thistype)->fields[n].bitsize
+#define TYPE_FIELD_PACKED(thistype, n) (thistype)->fields[n].bitsize
+
+#define TYPE_FIELD_PRIVATE_BITS(thistype) \
+ 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) \
+ (TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits == NULL ? 0 \
+ : B_TST(TYPE_CPLUS_SPECIFIC(thistype)->private_field_bits, (n)))
+#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))
+
+#define TYPE_FIELD_STATIC(thistype, n) ((thistype)->fields[n].bitpos == -1)
+#define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) ((char *)(thistype)->fields[n].bitsize)
+
+#define TYPE_FN_FIELDLISTS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists
+#define TYPE_FN_FIELDLIST(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n]
+#define TYPE_FN_FIELDLIST1(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].fn_fields
+#define TYPE_FN_FIELDLIST_NAME(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].name
+#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].length
+
+#define TYPE_FN_FIELD(thisfn, n) (thisfn)[n]
+#define TYPE_FN_FIELD_PHYSNAME(thisfn, n) (thisfn)[n].physname
+#define TYPE_FN_FIELD_TYPE(thisfn, n) (thisfn)[n].type
+#define TYPE_FN_FIELD_ARGS(thisfn, n) TYPE_ARG_TYPES ((thisfn)[n].type)
+#define TYPE_FN_FIELD_CONST(thisfn, n) ((thisfn)[n].is_const)
+#define TYPE_FN_FIELD_VOLATILE(thisfn, n) ((thisfn)[n].is_volatile)
+#define TYPE_FN_FIELD_PRIVATE(thisfn, n) ((thisfn)[n].is_private)
+#define TYPE_FN_FIELD_PROTECTED(thisfn, n) ((thisfn)[n].is_protected)
+#define TYPE_FN_FIELD_STUB(thisfn, n) ((thisfn)[n].is_stub)
+#define TYPE_FN_FIELD_FCONTEXT(thisfn, n) ((thisfn)[n].fcontext)
+#define TYPE_FN_FIELD_VOFFSET(thisfn, n) ((thisfn)[n].voffset-2)
+#define TYPE_FN_FIELD_VIRTUAL_P(thisfn, n) ((thisfn)[n].voffset > 1)
+#define TYPE_FN_FIELD_STATIC_P(thisfn, n) ((thisfn)[n].voffset == VOFFSET_STATIC)
+
+extern struct type *builtin_type_void;
+extern struct type *builtin_type_char;
+extern struct type *builtin_type_short;
+extern struct type *builtin_type_int;
+extern struct type *builtin_type_long;
+extern struct type *builtin_type_signed_char;
+extern struct type *builtin_type_unsigned_char;
+extern struct type *builtin_type_unsigned_short;
+extern struct type *builtin_type_unsigned_int;
+extern struct type *builtin_type_unsigned_long;
+extern struct type *builtin_type_float;
+extern struct type *builtin_type_double;
+extern struct type *builtin_type_long_double;
+extern struct type *builtin_type_complex;
+extern struct type *builtin_type_double_complex;
+extern struct type *builtin_type_string;
+
+/* This type represents a type that was unrecognized in symbol
+ read-in. */
+
+extern struct type *builtin_type_error;
+
+extern struct type *builtin_type_long_long;
+extern struct type *builtin_type_unsigned_long_long;
+
+/* Modula-2 types */
+
+extern struct type *builtin_type_m2_char;
+extern struct type *builtin_type_m2_int;
+extern struct type *builtin_type_m2_card;
+extern struct type *builtin_type_m2_real;
+extern struct type *builtin_type_m2_bool;
+
+/* Chill types */
+
+extern struct type *builtin_type_chill_bool;
+extern struct type *builtin_type_chill_char;
+extern struct type *builtin_type_chill_long;
+extern struct type *builtin_type_chill_ulong;
+extern struct type *builtin_type_chill_real;
+
+/* Fortran (F77) types */
+
+extern struct type *builtin_type_f_character;
+extern struct type *builtin_type_f_integer;
+extern struct type *builtin_type_f_logical;
+extern struct type *builtin_type_f_logical_s1;
+extern struct type *builtin_type_f_logical_s2;
+extern struct type *builtin_type_f_integer;
+extern struct type *builtin_type_f_integer_s2;
+extern struct type *builtin_type_f_real;
+extern struct type *builtin_type_f_real_s8;
+extern struct type *builtin_type_f_real_s16;
+extern struct type *builtin_type_f_complex_s8;
+extern struct type *builtin_type_f_complex_s16;
+extern struct type *builtin_type_f_complex_s32;
+extern struct type *builtin_type_f_void;
+
+/* Maximum and minimum values of built-in types */
+
+#define MAX_OF_TYPE(t) \
+ TYPE_UNSIGNED(t) ? UMAX_OF_SIZE(TYPE_LENGTH(t)) \
+ : MAX_OF_SIZE(TYPE_LENGTH(t))
+
+#define MIN_OF_TYPE(t) \
+ TYPE_UNSIGNED(t) ? UMIN_OF_SIZE(TYPE_LENGTH(t)) \
+ : MIN_OF_SIZE(TYPE_LENGTH(t))
+
+/* Allocate space for storing data associated with a particular type.
+ We ensure that the space is allocated using the same mechanism that
+ was used to allocate the space for the type structure itself. I.E.
+ if the type is on an objfile's type_obstack, then the space for data
+ associated with that type will also be allocated on the type_obstack.
+ If the type is not associated with any particular objfile (such as
+ builtin types), then the data space will be allocated with xmalloc,
+ the same as for the type structure. */
+
+#define TYPE_ALLOC(t,size) \
+ (TYPE_OBJFILE (t) != NULL \
+ ? obstack_alloc (&TYPE_OBJFILE (t) -> type_obstack, size) \
+ : xmalloc (size))
+
+extern struct type *
+alloc_type PARAMS ((struct objfile *));
+
+extern struct type *
+init_type PARAMS ((enum type_code, int, int, char *, struct objfile *));
+
+extern struct type *
+lookup_reference_type PARAMS ((struct type *));
+
+extern struct type *
+make_reference_type PARAMS ((struct type *, struct type **));
+
+extern struct type *
+lookup_member_type PARAMS ((struct type *, struct type *));
+
+extern void
+smash_to_method_type PARAMS ((struct type *, struct type *, struct type *,
+ struct type **));
+
+extern void
+smash_to_member_type PARAMS ((struct type *, struct type *, struct type *));
+
+extern struct type *
+allocate_stub_method PARAMS ((struct type *));
+
+extern char *
+type_name_no_tag PARAMS ((const struct type *));
+
+extern struct type *
+lookup_struct_elt_type PARAMS ((struct type *, char *, int));
+
+extern struct type *
+make_pointer_type PARAMS ((struct type *, struct type **));
+
+extern struct type *
+lookup_pointer_type PARAMS ((struct type *));
+
+extern struct type *
+make_function_type PARAMS ((struct type *, struct type **));
+
+extern struct type *
+lookup_function_type PARAMS ((struct type *));
+
+extern struct type *
+create_range_type PARAMS ((struct type *, struct type *, int, int));
+
+extern struct type *
+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 int chill_varying_type PARAMS ((struct type*));
+
+extern struct type *
+lookup_unsigned_typename PARAMS ((char *));
+
+extern struct type *
+lookup_signed_typename PARAMS ((char *));
+
+extern struct type *
+check_typedef PARAMS ((struct type *));
+
+#define CHECK_TYPEDEF(TYPE) (TYPE) = check_typedef (TYPE)
+
+extern void
+check_stub_method PARAMS ((struct type *, int, int));
+
+extern struct type *
+lookup_primitive_typename PARAMS ((char *));
+
+extern char *
+gdb_mangle_name PARAMS ((struct type *, int, int));
+
+extern struct type *
+builtin_type PARAMS ((char **));
+
+extern struct type *
+lookup_typename PARAMS ((char *, struct block *, int));
+
+extern struct type *
+lookup_template_type PARAMS ((char *, struct type *, struct block *));
+
+extern struct type *
+lookup_fundamental_type PARAMS ((struct objfile *, int));
+
+extern void
+fill_in_vptr_fieldno PARAMS ((struct type *));
+
+extern int get_discrete_bounds PARAMS ((struct type*, LONGEST*, LONGEST*));
+
+#if MAINTENANCE_CMDS
+extern void recursive_dump_type PARAMS ((struct type *, int));
+#endif
+
+/* printcmd.c */
+
+extern void
+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));
+#endif
+
+#endif /* GDBTYPES_H */
diff --git a/contrib/gdb/gdb/gnu-nat.c b/contrib/gdb/gdb/gnu-nat.c
new file mode 100644
index 0000000..2d9cbed
--- /dev/null
+++ b/contrib/gdb/gdb/gnu-nat.c
@@ -0,0 +1,2814 @@
+/* Interface GDB to the GNU Hurd
+ Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ Some code and ideas from m3-nat.c by Jukka Virtanen <jtv@hut.fi>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <signal.h>
+#include <assert.h>
+#include <setjmp.h>
+#include <limits.h>
+#include <sys/ptrace.h>
+
+/* We include this because we don't need the access macros and they conflict
+ with gdb's definitions (ick). This is very non standard! */
+#include <waitflags.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/notify.h>
+#include <mach_error.h>
+#include <mach/exception.h>
+#include <mach/vm_attributes.h>
+
+#include <hurd/process.h>
+#include <hurd/process_request.h>
+#include <hurd/msg.h>
+#include <hurd/msg_request.h>
+#include <hurd/signal.h>
+#include <hurd/interrupt.h>
+#include <hurd/sigpreempt.h>
+
+#include "defs.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "language.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+
+#include "gnu-nat.h"
+
+#include "exc_request_S.h"
+#include "notify_S.h"
+#include "process_reply_S.h"
+#include "msg_reply_S.h"
+
+#include "exc_request_U.h"
+#include "msg_U.h"
+
+static process_t proc_server = MACH_PORT_NULL;
+
+/* If we've sent a proc_wait_request to the proc server, the pid of the
+ process we asked about. We can only ever have one outstanding. */
+int proc_wait_pid = 0;
+
+/* The number of wait requests we've sent, and expect replies from. */
+int proc_waits_pending = 0;
+
+int gnu_debug_flag = 0;
+
+/* Forward decls */
+
+extern struct target_ops gnu_ops;
+
+struct inf *make_inf ();
+void inf_clear_wait (struct inf *inf);
+void inf_cleanup (struct inf *inf);
+void inf_startup (struct inf *inf, int pid, task_t task);
+int inf_update_suspends (struct inf *inf);
+void inf_set_task (struct inf *inf, task_t port);
+void inf_validate_procs (struct inf *inf);
+void inf_steal_exc_ports (struct inf *inf);
+void inf_restore_exc_ports (struct inf *inf);
+int inf_update_procs (struct inf *inf);
+struct proc *inf_tid_to_proc (struct inf *inf, int tid);
+inline void inf_set_threads_resume_sc (struct inf *inf, struct proc
+ *run_thread, int run_others);
+inline int inf_set_threads_resume_sc_for_signal_thread (struct inf *inf);
+inline void inf_suspend (struct inf *inf);
+inline void inf_resume (struct inf *inf);
+void inf_set_step_thread (struct inf *inf, struct proc *proc);
+void inf_detach (struct inf *inf);
+void inf_attach (struct inf *inf, int pid);
+void inf_signal (struct inf *inf, enum target_signal sig);
+
+#define inf_debug(_inf, msg, args...) \
+ do { struct inf *__inf = (_inf); \
+ debug ("{inf %d %p}: " msg, __inf->pid, __inf , ##args); } while (0)
+
+struct proc *make_proc (struct inf *inf, mach_port_t port, int tid);
+struct proc *_proc_free (struct proc *proc);
+int proc_update_sc (struct proc *proc);
+void proc_abort (struct proc *proc, int force);
+thread_state_t proc_get_state (struct proc *proc, int force);
+error_t proc_get_exception_port (struct proc *proc, mach_port_t *port);
+error_t proc_set_exception_port (struct proc *proc, mach_port_t port);
+static mach_port_t _proc_get_exc_port (struct proc *proc);
+void proc_steal_exc_port (struct proc *proc, mach_port_t exc_port);
+void proc_restore_exc_port (struct proc *proc);
+int proc_trace (struct proc *proc, int set);
+char *proc_string (struct proc *proc);
+
+/* Evaluate RPC_EXPR in a scope with the variables MSGPORT and REFPORT bound
+ to INF's msg port and task port respectively. If it has no msg port,
+ EIEIO is returned. INF must refer to a running process! */
+#define INF_MSGPORT_RPC(inf, rpc_expr) \
+ HURD_MSGPORT_RPC (proc_getmsgport (proc_server, inf->pid, &msgport), \
+ (refport = inf->task->port, 0), 0, \
+ msgport ? (rpc_expr) : EIEIO)
+
+/* Like INF_MSGPORT_RPC, but will also resume the signal thread to ensure
+ there's someone around to deal with the RPC (and resuspend things
+ afterwards). This effects INF's threads' resume_sc count. */
+#define INF_RESUME_MSGPORT_RPC(inf, rpc_expr) \
+ (inf_set_threads_resume_sc_for_signal_thread (inf) \
+ ? ({ error_t __e; \
+ inf_resume (inf); \
+ __e = INF_MSGPORT_RPC (inf, rpc_expr); \
+ inf_suspend (inf); \
+ __e; }) \
+ : EIEIO)
+
+#define MIG_SERVER_DIED EMIG_SERVER_DIED /* XXX */
+
+/* The state passed by an exception message. */
+struct exc_state
+{
+ int exception; /* The exception code */
+ int code, subcode;
+ mach_port_t handler; /* The real exception port to handle this. */
+ mach_port_t reply; /* The reply port from the exception call. */
+};
+
+/* The results of the last wait an inf did. */
+struct inf_wait
+{
+ struct target_waitstatus status; /* The status returned to gdb. */
+ struct exc_state exc; /* The exception that caused us to return. */
+ struct proc *thread; /* The thread in question. */
+ int suppress; /* Something trivial happened. */
+};
+
+/* The state of an inferior. */
+struct inf
+{
+ /* Fields describing the current inferior. */
+
+ struct proc *task; /* The mach task. */
+ struct proc *threads; /* A linked list of all threads in TASK. */
+
+ /* True if THREADS needn't be validated by querying the task. We assume that
+ we and the task in question are the only ones frobbing the thread list,
+ so as long as we don't let any code run, we don't have to worry about
+ THREADS changing. */
+ int threads_up_to_date;
+
+ pid_t pid; /* The real system PID. */
+
+ struct inf_wait wait; /* What to return from target_wait. */
+
+ /* One thread proc in INF may be in `single-stepping mode'. This is it. */
+ struct proc *step_thread;
+
+ /* The thread we think is the signal thread. */
+ struct proc *signal_thread;
+
+ mach_port_t event_port; /* Where we receive various msgs. */
+
+ /* True if we think at least one thread in the inferior could currently be
+ running. */
+ int running : 1;
+
+ /* True if the process has stopped (in the proc server sense). Note that
+ since a proc server `stop' leaves the signal thread running, the inf can
+ be RUNNING && STOPPED... */
+ int stopped : 1;
+
+ /* True if the inferior is traced. */
+ int traced : 1;
+
+ /* True if we shouldn't try waiting for the inferior, usually because we
+ can't for some reason. */
+ int no_wait : 1;
+
+ /* When starting a new inferior, we don't try to validate threads until all
+ the proper execs have been done. This is a count of how many execs we
+ expect to happen. */
+ unsigned pending_execs;
+
+ /* Fields describing global state */
+
+ /* The task suspend count used when gdb has control. This is normally 1 to
+ make things easier for us, but sometimes (like when attaching to vital
+ system servers) it may be desirable to let the task continue to run
+ (pausing individual threads as necessary). */
+ int pause_sc;
+
+ /* The initial values used for the run_sc and pause_sc of newly discovered
+ threads -- see the definition of those fields in struct proc. */
+ int default_thread_run_sc;
+ int default_thread_pause_sc;
+
+ /* True if the process should be traced when started/attached. Newly
+ started processes *must* be traced at first to exec them properly, but
+ if this is false, tracing is turned off as soon it has done so. */
+ int want_signals;
+
+ /* True if exceptions from the inferior process should be trapped. This
+ must be on to use breakpoints. */
+ int want_exceptions;
+};
+
+int __proc_pid (struct proc *proc)
+{
+ return proc->inf->pid;
+}
+
+/* Update PROC's real suspend count to match it's desired one. Returns true
+ if we think PROC is now in a runnable state. */
+int
+proc_update_sc (struct proc *proc)
+{
+ int running;
+ int err = 0;
+ int delta = proc->sc - proc->cur_sc;
+
+ if (delta)
+ proc_debug (proc, "sc: %d --> %d", proc->cur_sc, proc->sc);
+
+ if (proc->sc == 0 && proc->state_changed)
+ /* Since PROC may start running, we must write back any state changes. */
+ {
+ assert (proc_is_thread (proc));
+ proc_debug (proc, "storing back changed thread state");
+ err = thread_set_state (proc->port, THREAD_STATE_FLAVOR,
+ &proc->state, THREAD_STATE_SIZE);
+ if (! err)
+ proc->state_changed = 0;
+ }
+
+ if (delta > 0)
+ while (delta-- > 0 && !err)
+ if (proc_is_task (proc))
+ err = task_suspend (proc->port);
+ else
+ err = thread_suspend (proc->port);
+ else
+ while (delta++ < 0 && !err)
+ if (proc_is_task (proc))
+ err = task_resume (proc->port);
+ else
+ err = thread_resume (proc->port);
+
+ if (! err)
+ proc->cur_sc = proc->sc;
+
+ /* If we got an error, then the task/thread has disappeared. */
+ running = !err && proc->sc == 0;
+
+ proc_debug (proc, "is %s", err ? "dead" : running ? "running" : "suspended");
+ if (err)
+ proc_debug (proc, "err = %s", strerror (err));
+
+ if (running)
+ {
+ proc->aborted = 0;
+ proc->state_valid = proc->state_changed = 0;
+ proc->fetched_regs = 0;
+ }
+
+ return running;
+}
+
+/* Thread_abort is called on PROC if needed. PROC must be a thread proc.
+ If PROC is deemed `precious', then nothing is done unless FORCE is true.
+ In particular, a thread is precious if it's running (in which case forcing
+ it includes suspending it first), or if it has an exception pending. */
+void
+proc_abort (struct proc *proc, int force)
+{
+ assert (proc_is_thread (proc));
+
+ if (! proc->aborted)
+ {
+ struct inf *inf = proc->inf;
+ int running = (proc->cur_sc == 0 && inf->task->cur_sc == 0);
+
+ if (running && force)
+ {
+ proc->sc = 1;
+ inf_update_suspends (proc->inf);
+ running = 0;
+ warning ("Stopped %s.", proc_string (proc));
+ }
+ else if (proc == inf->wait.thread && inf->wait.exc.reply && !force)
+ /* An exception is pending on PROC, which don't mess with. */
+ running = 1;
+
+ if (! running)
+ /* We only abort the thread if it's not actually running. */
+ {
+ thread_abort (proc->port);
+ proc_debug (proc, "aborted");
+ proc->aborted = 1;
+ }
+ else
+ proc_debug (proc, "not aborting");
+ }
+}
+
+/* Make sure that the state field in PROC is up to date, and return a pointer
+ to it, or 0 if something is wrong. If WILL_MODIFY is true, makes sure
+ that the thread is stopped and aborted first, and sets the state_changed
+ field in PROC to true. */
+thread_state_t
+proc_get_state (struct proc *proc, int will_modify)
+{
+ int was_aborted = proc->aborted;
+
+ proc_debug (proc, "updating state info%s",
+ will_modify ? " (with intention to modify)" : "");
+
+ proc_abort (proc, will_modify);
+
+ if (! was_aborted && proc->aborted)
+ /* PROC's state may have changed since we last fetched it. */
+ proc->state_valid = 0;
+
+ if (! proc->state_valid)
+ {
+ mach_msg_type_number_t state_size = THREAD_STATE_SIZE;
+ error_t err =
+ thread_get_state (proc->port, THREAD_STATE_FLAVOR,
+ &proc->state, &state_size);
+ proc_debug (proc, "getting thread state");
+ proc->state_valid = !err;
+ }
+
+ if (proc->state_valid)
+ {
+ if (will_modify)
+ proc->state_changed = 1;
+ return &proc->state;
+ }
+ else
+ return 0;
+}
+
+error_t
+proc_get_exception_port (struct proc *proc, mach_port_t *port)
+{
+ if (proc_is_task (proc))
+ return task_get_exception_port (proc->port, port);
+ else
+ return thread_get_exception_port (proc->port, port);
+}
+
+error_t
+proc_set_exception_port (struct proc *proc, mach_port_t port)
+{
+ proc_debug (proc, "setting exception port: %d", port);
+ if (proc_is_task (proc))
+ return task_set_exception_port (proc->port, port);
+ else
+ return thread_set_exception_port (proc->port, port);
+}
+
+/* Get PROC's exception port, cleaning up a bit if proc has died. */
+static mach_port_t
+_proc_get_exc_port (struct proc *proc)
+{
+ mach_port_t exc_port;
+ error_t err = proc_get_exception_port (proc, &exc_port);
+
+ if (err)
+ /* PROC must be dead. */
+ {
+ if (proc->exc_port)
+ mach_port_deallocate (mach_task_self (), proc->exc_port);
+ proc->exc_port = MACH_PORT_NULL;
+ if (proc->saved_exc_port)
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+ proc->saved_exc_port = MACH_PORT_NULL;
+ }
+
+ return exc_port;
+}
+
+/* Replace PROC's exception port with EXC_PORT, unless it's already been
+ done. Stash away any existing exception port so we can restore it later. */
+void
+proc_steal_exc_port (struct proc *proc, mach_port_t exc_port)
+{
+ mach_port_t cur_exc_port = _proc_get_exc_port (proc);
+
+ if (cur_exc_port)
+ {
+ error_t err;
+
+ proc_debug (proc, "inserting exception port: %d", exc_port);
+
+ if (cur_exc_port != exc_port)
+ /* Put in our exception port. */
+ err = proc_set_exception_port (proc, exc_port);
+
+ if (err || cur_exc_port == proc->exc_port)
+ /* We previously set the exception port, and it's still set. So we
+ just keep the old saved port which is what the proc set. */
+ {
+ if (cur_exc_port)
+ mach_port_deallocate (mach_task_self (), cur_exc_port);
+ }
+ else
+ /* Keep a copy of PROC's old exception port so it can be restored. */
+ {
+ if (proc->saved_exc_port)
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+ proc->saved_exc_port = cur_exc_port;
+ }
+
+ proc_debug (proc, "saved exception port: %d", proc->saved_exc_port);
+
+ if (!err)
+ proc->exc_port = exc_port;
+ else
+ warning ("Error setting exception port for %s: %s",
+ proc_string (proc), strerror (err));
+ }
+}
+
+/* If we previously replaced PROC's exception port, put back what we found
+ there at the time, unless *our* exception port has since be overwritten,
+ in which case who knows what's going on. */
+void
+proc_restore_exc_port (struct proc *proc)
+{
+ mach_port_t cur_exc_port = _proc_get_exc_port (proc);
+
+ if (cur_exc_port)
+ {
+ error_t err = 0;
+
+ proc_debug (proc, "restoring real exception port");
+
+ if (proc->exc_port == cur_exc_port)
+ /* Our's is still there. */
+ err = proc_set_exception_port (proc, proc->saved_exc_port);
+
+ if (proc->saved_exc_port)
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+ proc->saved_exc_port = MACH_PORT_NULL;
+
+ if (!err)
+ proc->exc_port = MACH_PORT_NULL;
+ else
+ warning ("Error setting exception port for %s: %s",
+ proc_string (proc), strerror (err));
+ }
+}
+
+/* Turns hardware tracing in PROC on or off when SET is true or fals,
+ respectively. Returns true on success. */
+int
+proc_trace (struct proc *proc, int set)
+{
+ thread_state_t state = proc_get_state (proc, 1);
+
+ if (! state)
+ return 0; /* the thread must be dead. */
+
+ proc_debug (proc, "tracing %s", set ? "on" : "off");
+
+ if (set)
+ {
+ /* XXX We don't get the exception unless the thread has its own
+ exception port???? */
+ if (proc->exc_port == MACH_PORT_NULL)
+ proc_steal_exc_port (proc, proc->inf->event_port);
+ THREAD_STATE_SET_TRACED (state);
+ }
+ else
+ THREAD_STATE_CLEAR_TRACED (state);
+
+ return 1;
+}
+
+/* A variable from which to assign new TIDs. */
+static int next_thread_id = 1;
+
+/* Returns a new proc structure with the given fields. Also adds a
+ notification for PORT becoming dead to be sent to INF's notify port. */
+struct proc *
+make_proc (struct inf *inf, mach_port_t port, int tid)
+{
+ error_t err;
+ mach_port_t prev_port = MACH_PORT_NULL;
+ struct proc *proc = malloc (sizeof (struct proc));
+
+ proc->port = port;
+ proc->tid = tid;
+ proc->inf = inf;
+ proc->next = 0;
+ proc->saved_exc_port = MACH_PORT_NULL;
+ proc->exc_port = MACH_PORT_NULL;
+ proc->sc = 0;
+ proc->cur_sc = 0;
+ proc->run_sc = inf->default_thread_run_sc;
+ proc->pause_sc = inf->default_thread_pause_sc;
+ proc->resume_sc = proc->run_sc;
+ proc->aborted = 0;
+ proc->state_valid = 0;
+ proc->state_changed = 0;
+
+ proc_debug (proc, "is new");
+
+ /* Get notified when things die. */
+ err =
+ mach_port_request_notification (mach_task_self(), port,
+ MACH_NOTIFY_DEAD_NAME, 1,
+ inf->event_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &prev_port);
+ if (err)
+ warning ("Couldn't request notification for port %d: %s",
+ port, strerror (err));
+ else
+ {
+ proc_debug (proc, "notifications to: %d", inf->event_port);
+ if (prev_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), prev_port);
+ }
+
+ if (inf->want_exceptions)
+ if (proc_is_task (proc))
+ /* Make the task exception port point to us. */
+ proc_steal_exc_port (proc, inf->event_port);
+ else
+ /* Just clear thread exception ports -- they default to the task one. */
+ proc_steal_exc_port (proc, MACH_PORT_NULL);
+
+ return proc;
+}
+
+/* Frees PROC and any resources it uses, and returns the value of PROC's next
+ field. */
+struct proc *
+_proc_free (struct proc *proc)
+{
+ struct inf *inf = proc->inf;
+ struct proc *next = proc->next;
+
+ proc_debug (proc, "freeing...");
+
+ if (proc == inf->step_thread)
+ /* Turn off single stepping. */
+ inf_set_step_thread (inf, 0);
+ if (proc == inf->wait.thread)
+ inf_clear_wait (inf);
+ if (proc == inf->signal_thread)
+ inf->signal_thread = 0;
+
+ if (proc->port != MACH_PORT_NULL)
+ {
+ if (proc->exc_port != MACH_PORT_NULL)
+ /* Restore the original exception port. */
+ proc_restore_exc_port (proc);
+ if (proc->cur_sc != 0)
+ /* Resume the thread/task. */
+ {
+ proc->sc = 0;
+ proc_update_sc (proc);
+ }
+ mach_port_deallocate (mach_task_self (), proc->port);
+ }
+
+ free (proc);
+ return next;
+}
+
+struct inf *make_inf ()
+{
+ struct inf *inf = malloc (sizeof (struct inf));
+
+ if (!inf)
+ return 0;
+
+ inf->task = 0;
+ inf->threads = 0;
+ inf->threads_up_to_date = 0;
+ inf->pid = 0;
+ inf->wait.status.kind = TARGET_WAITKIND_SPURIOUS;
+ inf->wait.thread = 0;
+ inf->wait.exc.handler = MACH_PORT_NULL;
+ inf->wait.exc.reply = MACH_PORT_NULL;
+ inf->step_thread = 0;
+ inf->signal_thread = 0;
+ inf->event_port = MACH_PORT_NULL;
+ inf->stopped = 0;
+ inf->running = 0;
+ inf->traced = 0;
+ inf->no_wait = 0;
+ inf->pending_execs = 0;
+ inf->pause_sc = 1;
+ inf->default_thread_run_sc = 0;
+ inf->default_thread_pause_sc = 0;
+ inf->want_signals = 1; /* By default */
+ inf->want_exceptions = 1; /* By default */
+
+ return inf;
+}
+
+void
+inf_clear_wait (struct inf *inf)
+{
+ inf_debug (inf, "clearing wait");
+ inf->wait.status.kind = TARGET_WAITKIND_SPURIOUS;
+ inf->wait.thread = 0;
+ inf->wait.suppress = 0;
+ if (inf->wait.exc.handler != MACH_PORT_NULL)
+ {
+ mach_port_deallocate (mach_task_self (), inf->wait.exc.handler);
+ inf->wait.exc.handler = MACH_PORT_NULL;
+ }
+ if (inf->wait.exc.reply != MACH_PORT_NULL)
+ {
+ mach_port_deallocate (mach_task_self (), inf->wait.exc.reply);
+ inf->wait.exc.reply = MACH_PORT_NULL;
+ }
+}
+
+void
+inf_cleanup (struct inf *inf)
+{
+ inf_debug (inf, "cleanup");
+
+ inf_clear_wait (inf);
+
+ inf_set_task (inf, MACH_PORT_NULL);
+ inf->pid = 0;
+ inf->traced = 0;
+ inf->no_wait = 0;
+ inf->stopped = 0;
+ inf->running = 0;
+ inf->pending_execs = 0;
+
+ if (inf->event_port)
+ {
+ mach_port_destroy (mach_task_self (), inf->event_port);
+ inf->event_port = MACH_PORT_NULL;
+ }
+}
+
+void
+inf_startup (struct inf *inf, int pid, task_t task)
+{
+ error_t err;
+
+ inf_debug (inf, "startup: pid = %d, task = %d", pid, task);
+
+ inf_cleanup (inf);
+
+ /* Make the port on which we receive all events. */
+ err = mach_port_allocate (mach_task_self (),
+ MACH_PORT_RIGHT_RECEIVE, &inf->event_port);
+ if (err)
+ error ("Error allocating event port: %s", strerror (err));
+
+ /* Make a send right for it, so we can easily copy it for other people. */
+ mach_port_insert_right (mach_task_self (), inf->event_port,
+ inf->event_port, MACH_MSG_TYPE_MAKE_SEND);
+
+ if (inf->pause_sc)
+ task_suspend (task);
+
+ inf_set_task (inf, task);
+
+ if (inf->task)
+ {
+ inf->pid = pid;
+ if (inf->pause_sc)
+ inf->task->sc = inf->task->cur_sc = 1; /* Reflect task_suspend above */
+ }
+}
+
+void
+inf_set_task (struct inf *inf, mach_port_t port)
+{
+ struct proc *task = inf->task;
+
+ inf_debug (inf, "setting task: %d", port);
+
+ if (task && task->port != port)
+ {
+ inf->task = 0;
+ inf_validate_procs (inf); /* Trash all the threads. */
+ _proc_free (task); /* And the task. */
+ }
+
+ if (port != MACH_PORT_NULL)
+ {
+ inf->task = make_proc (inf, port, PROC_TID_TASK);
+ inf->threads_up_to_date = 0;
+ }
+}
+
+/* Validates INF's stopped field from the actual proc server state. */
+static void
+inf_validate_stopped (struct inf *inf)
+{
+ char *noise;
+ mach_msg_type_number_t noise_len = 0;
+ struct procinfo *pi;
+ mach_msg_type_number_t pi_len = 0;
+ error_t err =
+ proc_getprocinfo (proc_server, inf->pid, 0,
+ (procinfo_t *)&pi, &pi_len, &noise, &noise_len);
+
+ if (! err)
+ {
+ inf->stopped = !!(pi->state & PI_STOPPED);
+ vm_deallocate (mach_task_self (), (vm_address_t)pi, pi_len);
+ if (noise_len > 0)
+ vm_deallocate (mach_task_self (), (vm_address_t)noise, noise_len);
+ }
+}
+
+/* Validates INF's task suspend count. */
+static void
+inf_validate_task_sc (struct inf *inf)
+{
+ struct task_basic_info info;
+ mach_msg_type_number_t info_len = TASK_BASIC_INFO_COUNT;
+ error_t err = task_info (inf->task->port, TASK_BASIC_INFO, &info, &info_len);
+ if (! err)
+ {
+ if (inf->task->cur_sc < info.suspend_count)
+ warning ("Pid %d is suspended; continuing will clear existing suspend count.", inf->pid);
+ inf->task->cur_sc = info.suspend_count;
+ }
+}
+
+/* Turns tracing for INF on or off, depending on ON, unless it already is.
+ If INF is running, the resume_sc count of INF's threads will be modified,
+ and the signal thread will briefly be run to change the trace state. */
+void
+inf_set_traced (struct inf *inf, int on)
+{
+ if (on != inf->traced)
+ if (inf->task)
+ /* Make it take effect immediately. */
+ {
+ error_t (*f)(mach_port_t, mach_port_t, int) =
+ on ? msg_set_some_exec_flags : msg_clear_some_exec_flags;
+ error_t err =
+ INF_RESUME_MSGPORT_RPC (inf, (*f)(msgport, refport, EXEC_TRACED));
+ if (err == EIEIO)
+ warning ("Can't modify tracing state for pid %d: No signal thread",
+ inf->pid);
+ else if (err)
+ warning ("Can't modify tracing state for pid %d: %s",
+ inf->pid, strerror (err));
+ else
+ inf->traced = on;
+ }
+ else
+ inf->traced = on;
+}
+
+/* Makes all the real suspend count deltas of all the procs in INF match the
+ desired values. Careful to always do thread/task suspend counts in the
+ safe order. Returns true if at least one thread is thought to be running.*/
+int
+inf_update_suspends (struct inf *inf)
+{
+ struct proc *task = inf->task;
+ /* We don't have to update INF->threads even though we're iterating over it
+ because we'll change a thread only if it already has an existing proc
+ entry. */
+
+ inf_debug (inf, "updating suspend counts");
+
+ if (task)
+ {
+ struct proc *thread;
+ int task_running = (task->sc == 0), thread_running = 0;
+
+ if (task->sc > task->cur_sc)
+ /* The task is becoming _more_ suspended; do before any threads. */
+ task_running = proc_update_sc (task);
+
+ if (inf->pending_execs)
+ /* When we're waiting for an exec, things may be happening behind our
+ back, so be conservative. */
+ thread_running = 1;
+
+ /* Do all the thread suspend counts. */
+ for (thread = inf->threads; thread; thread = thread->next)
+ thread_running |= proc_update_sc (thread);
+
+ if (task->sc != task->cur_sc)
+ /* We didn't do the task first, because we wanted to wait for the
+ threads; do it now. */
+ task_running = proc_update_sc (task);
+
+ inf_debug (inf, "%srunning...",
+ (thread_running && task_running) ? "" : "not ");
+
+ inf->running = thread_running && task_running;
+
+ /* Once any thread has executed some code, we can't depend on the
+ threads list any more. */
+ if (inf->running)
+ inf->threads_up_to_date = 0;
+
+ return inf->running;
+ }
+
+ return 0;
+}
+
+/* Converts a GDB pid to a struct proc. */
+struct proc *
+inf_tid_to_thread (struct inf *inf, int tid)
+{
+ struct proc *thread = inf->threads;
+ while (thread)
+ if (thread->tid == tid)
+ return thread;
+ else
+ thread = thread->next;
+ return 0;
+}
+
+/* Converts a thread port to a struct proc. */
+struct proc *
+inf_port_to_thread (struct inf *inf, mach_port_t port)
+{
+ struct proc *thread = inf->threads;
+ while (thread)
+ if (thread->port == port)
+ return thread;
+ else
+ thread = thread->next;
+ return 0;
+}
+
+/* Make INF's list of threads be consistent with reality of TASK. */
+void
+inf_validate_procs (struct inf *inf)
+{
+ int i;
+ thread_array_t threads;
+ unsigned num_threads;
+ struct proc *task = inf->task;
+
+ inf->threads_up_to_date = !inf->running;
+
+ if (task)
+ {
+ error_t err = task_threads (task->port, &threads, &num_threads);
+ inf_debug (inf, "fetching threads");
+ if (err)
+ /* TASK must be dead. */
+ {
+ task->port = MACH_PORT_NULL;
+ _proc_free (task);
+ task = inf->task = 0;
+ }
+ }
+
+ if (!task)
+ {
+ num_threads = 0;
+ inf_debug (inf, "no task");
+ }
+
+ {
+ unsigned search_start = 0; /* Make things normally linear. */
+ /* Which thread in PROCS corresponds to each task thread, & the task. */
+ struct proc *matched[num_threads + 1];
+ /* The last thread in INF->threads, so we can add to the end. */
+ struct proc *last = 0;
+ /* The current thread we're considering. */
+ struct proc *thread = inf->threads;
+
+ bzero (matched, sizeof (matched));
+
+ while (thread)
+ {
+ unsigned left;
+
+ for (i = search_start, left = num_threads; left; i++, left--)
+ {
+ if (i >= num_threads)
+ i -= num_threads; /* I wrapped around. */
+ if (thread->port == threads[i])
+ /* We already know about this thread. */
+ {
+ matched[i] = thread;
+ last = thread;
+ thread = thread->next;
+ search_start++;
+ break;
+ }
+ }
+
+ if (! left)
+ {
+ proc_debug (thread, "died!");
+ thread->port = MACH_PORT_NULL;
+ thread = _proc_free (thread); /* THREAD is dead. */
+ (last ? last->next : inf->threads) = thread;
+ }
+ }
+
+ for (i = 0; i < num_threads; i++)
+ if (matched[i])
+ /* Throw away the duplicate send right. */
+ mach_port_deallocate (mach_task_self (), threads[i]);
+ else
+ /* THREADS[I] is a thread we don't know about yet! */
+ {
+ thread = make_proc (inf, threads[i], next_thread_id++);
+ (last ? last->next : inf->threads) = thread;
+ last = thread;
+ proc_debug (thread, "new thread: %d", threads[i]);
+ add_thread (thread->tid); /* Tell GDB's generic thread code. */
+ }
+
+ vm_deallocate(mach_task_self(),
+ (vm_address_t)threads, (num_threads * sizeof(thread_t)));
+ }
+}
+
+/* Makes sure that INF's thread list is synced with the actual process. */
+inline int
+inf_update_procs (struct inf *inf)
+{
+ if (! inf->task)
+ return 0;
+ if (! inf->threads_up_to_date)
+ inf_validate_procs (inf);
+ return !!inf->task;
+}
+
+/* Sets the resume_sc of each thread in inf. That of RUN_THREAD is set to 0,
+ and others are set to their run_sc if RUN_OTHERS is true, and otherwise
+ their pause_sc. */
+inline void
+inf_set_threads_resume_sc (struct inf *inf,
+ struct proc *run_thread, int run_others)
+{
+ struct proc *thread;
+ inf_update_procs (inf);
+ for (thread = inf->threads; thread; thread = thread->next)
+ if (thread == run_thread)
+ thread->resume_sc = 0;
+ else if (run_others)
+ thread->resume_sc = thread->run_sc;
+ else
+ thread->resume_sc = thread->pause_sc;
+}
+
+/* Cause INF to continue execution immediately; individual threads may still
+ be suspended (but their suspend counts will be updated). */
+inline void
+inf_resume (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_update_procs (inf);
+
+ for (thread = inf->threads; thread; thread = thread->next)
+ thread->sc = thread->resume_sc;
+
+ if (inf->task)
+ inf->task->sc = 0;
+
+ inf_update_suspends (inf);
+}
+
+/* Cause INF to stop execution immediately; individual threads may still
+ be running. */
+inline void
+inf_suspend (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_update_procs (inf);
+
+ for (thread = inf->threads; thread; thread = thread->next)
+ thread->sc = thread->pause_sc;
+
+ if (inf->task)
+ inf->task->sc = inf->pause_sc;
+
+ inf_update_suspends (inf);
+}
+
+/* INF has one thread PROC that is in single-stepping mode. This functions
+ changes it to be PROC, changing any old step_thread to be a normal one. A
+ PROC of 0 clears an any existing value. */
+void
+inf_set_step_thread (struct inf *inf, struct proc *thread)
+{
+ assert (!thread || proc_is_thread (thread));
+
+ if (thread)
+ inf_debug (inf, "setting step thread: %d/%d", inf->pid, thread->tid);
+ else
+ inf_debug (inf, "clearing step thread");
+
+ if (inf->step_thread != thread)
+ {
+ if (inf->step_thread && inf->step_thread->port != MACH_PORT_NULL)
+ if (! proc_trace (inf->step_thread, 0))
+ return;
+ if (thread && proc_trace (thread, 1))
+ inf->step_thread = thread;
+ else
+ inf->step_thread = 0;
+ }
+}
+
+/* Set up the thread resume_sc's so that only the signal thread is running
+ (plus whatever other thread are set to always run). Returns true if we
+ did so, or false if we can't find a signal thread. */
+inline int
+inf_set_threads_resume_sc_for_signal_thread (struct inf *inf)
+{
+ if (inf->signal_thread)
+ {
+ inf_set_threads_resume_sc (inf, inf->signal_thread, 0);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+static void
+inf_update_signal_thread (struct inf *inf)
+{
+ /* XXX for now we assume that if there's a msgport, the 2nd thread is
+ the signal thread. */
+ inf->signal_thread = inf->threads ? inf->threads->next : 0;
+}
+
+/* Detachs from INF's inferior task, letting it run once again... */
+void
+inf_detach (struct inf *inf)
+{
+ struct proc *task = inf->task;
+
+ inf_debug (inf, "detaching...");
+
+ inf_clear_wait (inf);
+ inf_set_step_thread (inf, 0);
+
+ if (task)
+ {
+ struct proc *thread;
+
+ inf_set_traced (inf, 0);
+ if (inf->stopped)
+ inf_signal (inf, TARGET_SIGNAL_0);
+
+ proc_restore_exc_port (task);
+ task->sc = 0;
+
+ for (thread = inf->threads; thread; thread = thread->next)
+ {
+ proc_restore_exc_port (thread);
+ thread->sc = 0;
+ }
+
+ inf_update_suspends (inf);
+ }
+
+ inf_cleanup (inf);
+}
+
+/* Attaches INF to the process with process id PID, returning it in a suspended
+ state suitable for debugging. */
+void
+inf_attach (struct inf *inf, int pid)
+{
+ error_t err;
+ task_t task;
+
+ inf_debug (inf, "attaching: %d", pid);
+
+ err = proc_pid2task (proc_server, pid, &task);
+ if (err)
+ error ("Error getting task for pid %d: %s", pid, strerror (err));
+
+ if (inf->pid)
+ inf_detach (inf);
+
+ inf_startup (inf, pid, task);
+}
+
+/* Makes sure that we've got our exception ports entrenched in the process. */
+void inf_steal_exc_ports (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_debug (inf, "stealing exception ports");
+
+ inf_set_step_thread (inf, 0); /* The step thread is special. */
+
+ proc_steal_exc_port (inf->task, inf->event_port);
+ for (thread = inf->threads; thread; thread = thread->next)
+ proc_steal_exc_port (thread, MACH_PORT_NULL);
+}
+
+/* Makes sure the process has its own exception ports. */
+void inf_restore_exc_ports (struct inf *inf)
+{
+ struct proc *thread;
+
+ inf_debug (inf, "restoring exception ports");
+
+ inf_set_step_thread (inf, 0); /* The step thread is special. */
+
+ proc_restore_exc_port (inf->task);
+ for (thread = inf->threads; thread; thread = thread->next)
+ proc_restore_exc_port (thread);
+}
+
+/* Deliver signal SIG to INF. If INF is stopped, delivering a signal, even
+ signal 0, will continue it. INF is assumed to be in a paused state, and
+ the resume_sc's of INF's threads may be affected. */
+void
+inf_signal (struct inf *inf, enum target_signal sig)
+{
+ error_t err = 0;
+ int host_sig = target_signal_to_host (sig);
+
+#define NAME target_signal_to_name (sig)
+
+ if (host_sig >= _NSIG)
+ /* A mach exception. Exceptions are encoded in the signal space by
+ putting them after _NSIG; this assumes they're positive (and not
+ extremely large)! */
+ {
+ struct inf_wait *w = &inf->wait;
+ if (w->status.kind == TARGET_WAITKIND_STOPPED
+ && w->status.value.sig == sig
+ && w->thread && !w->thread->aborted)
+ /* We're passing through the last exception we received. This is
+ kind of bogus, because exceptions are per-thread whereas gdb
+ treats signals as per-process. We just forward the exception to
+ the correct handler, even it's not for the same thread as TID --
+ i.e., we pretend it's global. */
+ {
+ struct exc_state *e = &w->exc;
+ inf_debug (inf, "passing through exception:"
+ " task = %d, thread = %d, exc = %d"
+ ", code = %d, subcode = %d",
+ w->thread->port, inf->task->port,
+ e->exception, e->code, e->subcode);
+ err =
+ exception_raise_request (e->handler,
+ e->reply, MACH_MSG_TYPE_MOVE_SEND_ONCE,
+ w->thread->port, inf->task->port,
+ e->exception, e->code, e->subcode);
+ }
+ else
+ warning ("Can't forward spontaneous exception (%s).", NAME);
+ }
+ else
+ /* A Unix signal. */
+ if (inf->stopped)
+ /* The process is stopped an expecting a signal. Just send off a
+ request and let it get handled when we resume everything. */
+ {
+ inf_debug (inf, "sending %s to stopped process", NAME);
+ err =
+ INF_MSGPORT_RPC (inf,
+ msg_sig_post_untraced_request (msgport,
+ inf->event_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ host_sig,
+ refport));
+ if (! err)
+ /* Posting an untraced signal automatically continues it.
+ We clear this here rather than when we get the reply
+ because we'd rather assume it's not stopped when it
+ actually is, than the reverse. */
+ inf->stopped = 0;
+ }
+ else
+ /* It's not expecting it. We have to let just the signal thread
+ run, and wait for it to get into a reasonable state before we
+ can continue the rest of the process. When we finally resume the
+ process the signal we request will be the very first thing that
+ happens. */
+ {
+ inf_debug (inf, "sending %s to unstopped process (so resuming signal thread)", NAME);
+ err =
+ INF_RESUME_MSGPORT_RPC (inf,
+ msg_sig_post_untraced (msgport,
+ host_sig, refport));
+ }
+
+ if (err == EIEIO)
+ /* Can't do too much... */
+ warning ("Can't deliver signal %s: No signal thread.", NAME);
+ else if (err)
+ warning ("Delivering signal %s: %s", NAME, strerror (err));
+
+#undef NAME
+}
+
+/* The inferior used for all gdb target ops. */
+struct inf *current_inferior = 0;
+
+/* The inferior being waited for by gnu_wait. Since GDB is decidely not
+ multi-threaded, we don't bother to lock this. */
+struct inf *waiting_inf;
+
+/* Wait for something to happen in the inferior, returning what in STATUS. */
+static int
+gnu_wait (int tid, struct target_waitstatus *status)
+{
+ struct msg {
+ mach_msg_header_t hdr;
+ mach_msg_type_t type;
+ int data[8000];
+ } msg;
+ error_t err;
+ struct proc *thread;
+ struct inf *inf = current_inferior;
+
+ waiting_inf = inf;
+
+ inf_debug (inf, "waiting for: %d", tid);
+
+ rewait:
+ if (proc_wait_pid != inf->pid && !inf->no_wait)
+ /* Always get information on events from the proc server. */
+ {
+ inf_debug (inf, "requesting wait on pid %d", inf->pid);
+
+ if (proc_wait_pid)
+ /* The proc server is single-threaded, and only allows a single
+ outstanding wait request, so we have to cancel the previous one. */
+ {
+ inf_debug (inf, "cancelling previous wait on pid %d", proc_wait_pid);
+ interrupt_operation (proc_server);
+ }
+
+ err =
+ proc_wait_request (proc_server, inf->event_port, inf->pid, WUNTRACED);
+ if (err)
+ warning ("wait request failed: %s", strerror (err));
+ else
+ {
+ inf_debug (inf, "waits pending: %d", proc_waits_pending);
+ proc_wait_pid = inf->pid;
+ /* Even if proc_waits_pending was > 0 before, we still won't get
+ any other replies, because it was either from a different INF,
+ or a different process attached to INF -- and the event port,
+ which is the wait reply port, changes when you switch processes.*/
+ proc_waits_pending = 1;
+ }
+ }
+
+ inf_clear_wait (inf);
+
+ /* What can happen? (1) Dead name notification; (2) Exceptions arrive;
+ (3) wait reply from the proc server. */
+
+ inf_debug (inf, "waiting for an event...");
+ err = _hurd_intr_rpc_mach_msg (&msg.hdr, MACH_RCV_MSG, 0,
+ sizeof (struct msg),
+ inf->event_port, MACH_PORT_NULL);
+
+ /* Re-suspend the task. */
+ inf_suspend (inf);
+
+ if (err == EINTR)
+ inf_debug (inf, "interrupted");
+ else if (err)
+ error ("Couldn't wait for an event: %s", strerror (err));
+ else
+ {
+ struct {
+ mach_msg_header_t hdr;
+ mach_msg_type_t err_type;
+ kern_return_t err;
+ char noise[200];
+ } reply;
+
+ inf_debug (inf, "event: msgid = %d", msg.hdr.msgh_id);
+
+ /* Handle what we got. */
+ if (! notify_server (&msg.hdr, &reply.hdr)
+ && ! exc_server (&msg.hdr, &reply.hdr)
+ && ! process_reply_server (&msg.hdr, &reply.hdr)
+ && ! msg_reply_server (&msg.hdr, &reply.hdr))
+ /* Whatever it is, it's something strange. */
+ error ("Got a strange event, msg id = %d.", msg.hdr.msgh_id);
+
+ if (reply.err)
+ error ("Handling event, msgid = %d: %s",
+ msg.hdr.msgh_id, strerror (reply.err));
+ }
+
+ if (inf->pending_execs)
+ /* We're waiting for the inferior to finish execing. */
+ {
+ struct inf_wait *w = &inf->wait;
+ enum target_waitkind kind = w->status.kind;
+
+ if (kind == TARGET_WAITKIND_SPURIOUS)
+ /* Since gdb is actually counting the number of times the inferior
+ stops, expecting one stop per exec, we only return major events
+ while execing. */
+ w->suppress = 1;
+ else if (kind == TARGET_WAITKIND_STOPPED
+ && w->status.value.sig == TARGET_SIGNAL_TRAP)
+ /* Ah hah! A SIGTRAP from the inferior while starting up probably
+ means we've succesfully completed an exec! */
+ if (--inf->pending_execs == 0)
+ /* We're done! */
+ {
+ prune_threads (1); /* Get rid of the old shell threads */
+ renumber_threads (0); /* Give our threads reasonable names. */
+ }
+ }
+
+ if (inf->wait.suppress)
+ /* Some totally spurious event happened that we don't consider
+ worth returning to gdb. Just keep waiting. */
+ {
+ inf_debug (inf, "suppressing return, rewaiting...");
+ inf_resume (inf);
+ goto rewait;
+ }
+
+ /* Pass back out our results. */
+ bcopy (&inf->wait.status, status, sizeof (*status));
+
+ thread = inf->wait.thread;
+ if (thread)
+ tid = thread->tid;
+ else
+ thread = inf_tid_to_thread (inf, tid);
+
+ if (!thread || thread->port == MACH_PORT_NULL)
+ /* TID is dead; try and find a new thread. */
+ if (inf_update_procs (inf) && inf->threads)
+ tid = inf->threads->tid; /* The first available thread. */
+ else
+ tid = -1;
+
+ if (thread && tid >= 0 && status->kind != TARGET_WAITKIND_SPURIOUS
+ && inf->pause_sc == 0 && thread->pause_sc == 0)
+ /* If something actually happened to THREAD, make sure we suspend it. */
+ {
+ thread->sc = 1;
+ inf_update_suspends (inf);
+ }
+
+ inf_debug (inf, "returning tid = %d, status = %s (%d)", tid,
+ status->kind == TARGET_WAITKIND_EXITED ? "EXITED"
+ : status->kind == TARGET_WAITKIND_STOPPED ? "STOPPED"
+ : status->kind == TARGET_WAITKIND_SIGNALLED ? "SIGNALLED"
+ : status->kind == TARGET_WAITKIND_LOADED ? "LOADED"
+ : status->kind == TARGET_WAITKIND_SPURIOUS ? "SPURIOUS"
+ : "?",
+ status->value.integer);
+
+ return tid;
+}
+
+/* The rpc handler called by exc_server. */
+error_t
+S_exception_raise_request (mach_port_t port, mach_port_t reply_port,
+ thread_t thread_port, task_t task_port,
+ int exception, int code, int subcode)
+{
+ struct inf *inf = waiting_inf;
+ struct proc *thread = inf_port_to_thread (inf, thread_port);
+
+ inf_debug (waiting_inf,
+ "thread = %d, task = %d, exc = %d, code = %d, subcode = %d",
+ thread_port, task_port, exception, code);
+
+ if (!thread)
+ /* We don't know about thread? */
+ {
+ inf_update_procs (inf);
+ thread = inf_port_to_thread (inf, thread_port);
+ if (!thread)
+ /* Give up, the generating thread is gone. */
+ return 0;
+ }
+
+ mach_port_deallocate (mach_task_self (), thread_port);
+ mach_port_deallocate (mach_task_self (), task_port);
+
+ if (! thread->aborted)
+ /* THREAD hasn't been aborted since this exception happened (abortion
+ clears any exception state), so it must be real. */
+ {
+ /* Store away the details; this will destroy any previous info. */
+ inf->wait.thread = thread;
+
+ inf->wait.status.kind = TARGET_WAITKIND_STOPPED;
+
+ if (exception == EXC_BREAKPOINT)
+ /* GDB likes to get SIGTRAP for breakpoints. */
+ {
+ inf->wait.status.value.sig = TARGET_SIGNAL_TRAP;
+ mach_port_deallocate (mach_task_self (), reply_port);
+ }
+ else
+ /* Record the exception so that we can forward it later. */
+ {
+ if (thread->exc_port == port)
+ inf->wait.exc.handler = thread->saved_exc_port;
+ else
+ {
+ inf->wait.exc.handler = inf->task->saved_exc_port;
+ assert (inf->task->exc_port == port);
+ }
+ if (inf->wait.exc.handler != MACH_PORT_NULL)
+ /* Add a reference to the exception handler. */
+ mach_port_mod_refs (mach_task_self (),
+ inf->wait.exc.handler, MACH_PORT_RIGHT_SEND,
+ 1);
+
+ inf->wait.exc.exception = exception;
+ inf->wait.exc.code = code;
+ inf->wait.exc.subcode = subcode;
+ inf->wait.exc.reply = reply_port;
+
+ /* Exceptions are encoded in the signal space by putting them after
+ _NSIG; this assumes they're positive (and not extremely large)! */
+ inf->wait.status.value.sig =
+ target_signal_from_host (_NSIG + exception);
+ }
+ }
+ else
+ /* A supppressed exception, which ignore. */
+ {
+ inf->wait.suppress = 1;
+ mach_port_deallocate (mach_task_self (), reply_port);
+ }
+
+ return 0;
+}
+
+/* Fill in INF's wait field after a task has died without giving us more
+ detailed information. */
+void
+inf_task_died_status (struct inf *inf)
+{
+ warning ("Pid %d died with unknown exit status, using SIGKILL.", inf->pid);
+ inf->wait.status.kind = TARGET_WAITKIND_SIGNALLED;
+ inf->wait.status.value.sig = TARGET_SIGNAL_KILL;
+}
+
+/* Notify server routines. The only real one is dead name notification. */
+
+error_t
+do_mach_notify_dead_name (mach_port_t notify, mach_port_t dead_port)
+{
+ struct inf *inf = waiting_inf;
+
+ inf_debug (waiting_inf, "port = %d", dead_port);
+
+ if (inf->task && inf->task->port == dead_port)
+ {
+ proc_debug (inf->task, "is dead");
+ inf->task->port = MACH_PORT_NULL;
+ if (proc_wait_pid == inf->pid)
+ /* We have a wait outstanding on the process, which will return more
+ detailed information, so delay until we get that. */
+ inf->wait.suppress = 1;
+ else
+ /* We never waited for the process (maybe it wasn't a child), so just
+ pretend it got a SIGKILL. */
+ inf_task_died_status (inf);
+ }
+ else
+ {
+ struct proc *thread = inf_port_to_thread (inf, dead_port);
+ if (thread)
+ {
+ proc_debug (thread, "is dead");
+ thread->port = MACH_PORT_NULL;
+ }
+ }
+
+ mach_port_deallocate (mach_task_self (), dead_port);
+ inf->threads_up_to_date = 0; /* Just in case */
+
+ return 0;
+}
+
+static error_t
+ill_rpc (char *fun)
+{
+ warning ("illegal rpc: %s", fun);
+ return 0;
+}
+
+error_t
+do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t count)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t name)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+do_mach_notify_send_once (mach_port_t notify)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+/* Process_reply server routines. We only use process_wait_reply. */
+
+error_t
+S_proc_wait_reply (mach_port_t reply, error_t err,
+ int status, rusage_t rusage, pid_t pid)
+{
+ struct inf *inf = waiting_inf;
+
+ inf_debug (inf, "err = %s, pid = %d, status = 0x%x",
+ err ? strerror (err) : "0", pid, status);
+
+ if (err && proc_wait_pid && (!inf->task || !inf->task->port))
+ /* Ack. The task has died, but the task-died notification code didn't
+ tell anyone because it thought a more detailed reply from the
+ procserver was forthcoming. However, we now learn that won't
+ happen... So we have to act like the task just died, and this time,
+ tell the world. */
+ inf_task_died_status (inf);
+
+ if (--proc_waits_pending == 0)
+ /* PROC_WAIT_PID represents the most recent wait. We will always get
+ replies in order because the proc server is single threaded. */
+ proc_wait_pid = 0;
+
+ inf_debug (inf, "waits pending now: %d", proc_waits_pending);
+
+ if (err)
+ {
+ if (err != EINTR)
+ {
+ warning ("Can't wait for pid %d: %s", inf->pid, strerror (err));
+ inf->no_wait = 1;
+
+ /* Since we can't see the inferior's signals, don't trap them. */
+ inf_set_traced (inf, 0);
+ }
+ }
+ else if (pid == inf->pid)
+ {
+ store_waitstatus (&inf->wait.status, status);
+ if (inf->wait.status.kind == TARGET_WAITKIND_STOPPED)
+ /* The process has sent us a signal, and stopped itself in a sane
+ state pending our actions. */
+ {
+ inf_debug (inf, "process has stopped itself");
+ inf->stopped = 1;
+
+ /* We recheck the task suspend count here because the crash server
+ messes with it in an unfriendly way, right before `stopping'. */
+ inf_validate_task_sc (inf);
+ }
+ }
+ else
+ inf->wait.suppress = 1; /* Something odd happened. Ignore. */
+
+ return 0;
+}
+
+error_t
+S_proc_setmsgport_reply (mach_port_t reply, error_t err,
+ mach_port_t old_msg_port)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+error_t
+S_proc_getmsgport_reply (mach_port_t reply, error_t err, mach_port_t msg_port)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+/* Msg_reply server routines. We only use msg_sig_post_untraced_reply. */
+
+error_t
+S_msg_sig_post_untraced_reply (mach_port_t reply, error_t err)
+{
+ struct inf *inf = waiting_inf;
+
+ if (err == EBUSY)
+ /* EBUSY is what we get when the crash server has grabbed control of the
+ process and doesn't like what signal we tried to send it. Just act
+ like the process stopped (using a signal of 0 should mean that the
+ *next* time the user continues, it will pass signal 0, which the crash
+ server should like). */
+ {
+ inf->wait.status.kind = TARGET_WAITKIND_STOPPED;
+ inf->wait.status.value.sig = TARGET_SIGNAL_0;
+ }
+ else if (err)
+ warning ("Signal delivery failed: %s", strerror (err));
+
+ if (err)
+ /* We only get this reply when we've posted a signal to a process which we
+ thought was stopped, and which we expected to continue after the signal.
+ Given that the signal has failed for some reason, it's reasonable to
+ assume it's still stopped. */
+ inf->stopped = 1;
+ else
+ inf->wait.suppress = 1;
+
+ return 0;
+}
+
+error_t
+S_msg_sig_post_reply (mach_port_t reply, error_t err)
+{
+ return ill_rpc (__FUNCTION__);
+}
+
+/* Returns the number of messages queued for the receive right PORT. */
+static mach_port_msgcount_t
+port_msgs_queued (mach_port_t port)
+{
+ struct mach_port_status status;
+ error_t err =
+ mach_port_get_receive_status (mach_task_self (), port, &status);
+
+ if (err)
+ return 0;
+ else
+ return status.mps_msgcount;
+}
+
+/* Resume execution of the inferior process.
+
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal.
+
+ TID STEP:
+ -1 true Single step the current thread allowing other threads to run.
+ -1 false Continue the current thread allowing other threads to run.
+ X true Single step the given thread, don't allow any others to run.
+ X false Continue the given thread, do not allow any others to run.
+ (Where X, of course, is anything except -1)
+
+ Note that a resume may not `take' if there are pending exceptions/&c
+ still unprocessed from the last resume we did (any given resume may result
+ in multiple events returned by wait).
+*/
+static void
+gnu_resume (int tid, int step, enum target_signal sig)
+{
+ struct proc *step_thread = 0;
+ struct inf *inf = current_inferior;
+
+ inf_debug (inf, "tid = %d, step = %d, sig = %d", tid, step, sig);
+
+ if (sig != TARGET_SIGNAL_0 || inf->stopped)
+ inf_signal (inf, sig);
+ else if (inf->wait.exc.reply != MACH_PORT_NULL)
+ /* We received an exception to which we have chosen not to forward, so
+ abort the faulting thread, which will perhaps retake it. */
+ {
+ proc_abort (inf->wait.thread, 1);
+ warning ("Aborting %s with unforwarded exception %s.",
+ proc_string (inf->wait.thread),
+ target_signal_to_name (inf->wait.status.value.sig));
+ }
+
+ if (port_msgs_queued (inf->event_port))
+ /* If there are still messages in our event queue, don't bother resuming
+ the process, as we're just going to stop it right away anyway. */
+ return;
+
+ if (tid < 0)
+ /* Allow all threads to run, except perhaps single-stepping one. */
+ {
+ inf_debug (inf, "running all threads; tid = %d", inferior_pid);
+ tid = inferior_pid; /* What to step. */
+ inf_set_threads_resume_sc (inf, 0, 1);
+ }
+ else
+ /* Just allow a single thread to run. */
+ {
+ struct proc *thread = inf_tid_to_thread (inf, tid);
+ assert (thread);
+
+ inf_debug (inf, "running one thread: %d/%d", inf->pid, thread->tid);
+ inf_set_threads_resume_sc (inf, thread, 0);
+ }
+
+ if (step)
+ {
+ step_thread = inf_tid_to_thread (inf, tid);
+ assert (step_thread);
+ inf_debug (inf, "stepping thread: %d/%d", inf->pid, step_thread->tid);
+ }
+ if (step_thread != inf->step_thread)
+ inf_set_step_thread (inf, step_thread);
+
+ inf_debug (inf, "here we go...");
+ inf_resume (inf);
+}
+
+static void
+gnu_kill_inferior ()
+{
+ struct proc *task = current_inferior->task;
+ if (task)
+ {
+ proc_debug (task, "terminating...");
+ task_terminate (task->port);
+ task->port = MACH_PORT_NULL;
+ inf_validate_procs (current_inferior); /* Clear out the thread list &c */
+ }
+ target_mourn_inferior ();
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+gnu_mourn_inferior ()
+{
+ inf_debug (current_inferior, "rip");
+ inf_detach (current_inferior);
+ unpush_target (&gnu_ops);
+ generic_mourn_inferior ();
+}
+
+/* Fork an inferior process, and start debugging it. */
+
+/* Set INFERIOR_PID to the first thread available in the child, if any. */
+static void
+pick_first_thread ()
+{
+ if (current_inferior->task && current_inferior->threads)
+ /* The first thread. */
+ inferior_pid = current_inferior->threads->tid;
+ else
+ /* What may be the next thread. */
+ inferior_pid = next_thread_id;
+}
+
+static struct inf *
+cur_inf ()
+{
+ if (! current_inferior)
+ current_inferior = make_inf ();
+ return current_inferior;
+}
+
+static void
+gnu_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ struct inf *inf = cur_inf ();
+
+ void trace_me ()
+ {
+ /* We're in the child; make this process stop as soon as it execs. */
+ inf_debug (inf, "tracing self");
+ ptrace (PTRACE_TRACEME, 0, 0, 0);
+ }
+ void attach_to_child (int pid)
+ {
+ /* Attach to the now stopped child, which is actually a shell... */
+ inf_debug (inf, "attaching to child: %d", pid);
+
+ inf_attach (inf, pid);
+ pick_first_thread ();
+
+ attach_flag = 0;
+ push_target (&gnu_ops);
+
+ inf->pending_execs = 2;
+ inf->traced = 1;
+
+ /* Now let the child run again, knowing that it will stop immediately
+ because of the ptrace. */
+ inf_resume (inf);
+
+ startup_inferior (pid, inf->pending_execs);
+ }
+
+ inf_debug (inf, "creating inferior");
+
+ fork_inferior (exec_file, allargs, env, trace_me, attach_to_child, NULL);
+
+ inf_update_signal_thread (inf);
+ inf_set_traced (inf, inf->want_signals);
+
+ /* Execing the process will have trashed our exception ports; steal them
+ back (or make sure they're restored if the user wants that). */
+ if (inf->want_exceptions)
+ inf_steal_exc_ports (inf);
+ else
+ inf_restore_exc_ports (inf);
+
+ /* Here we go! */
+ proceed ((CORE_ADDR) -1, 0, 0);
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach"
+ commands. */
+static int
+gnu_can_run ()
+{
+ return 1;
+}
+
+#ifdef ATTACH_DETACH
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+static void
+gnu_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int pid;
+ char *exec_file;
+ struct inf *inf = cur_inf ();
+
+ if (!args)
+ error_no_arg ("PID to attach");
+
+ pid = atoi (args);
+
+ if (pid == getpid()) /* Trying to masturbate? */
+ error ("I refuse to debug myself!");
+
+ if (from_tty)
+ {
+ exec_file = (char *) get_exec_file (0);
+
+ if (exec_file)
+ printf_unfiltered ("Attaching to program `%s', pid %d\n",
+ exec_file, pid);
+ else
+ printf_unfiltered ("Attaching to pid %d\n", pid);
+
+ gdb_flush (gdb_stdout);
+ }
+
+ inf_debug (inf, "attaching to pid: %d", pid);
+
+ inf_attach (inf, pid);
+ inf_update_procs (inf);
+
+ pick_first_thread ();
+
+ attach_flag = 1;
+ push_target (&gnu_ops);
+
+ inf_update_signal_thread (inf);
+ inf_set_traced (inf, inf->want_signals);
+
+ /* If the process was stopped before we attached, make it continue the next
+ time the user does a continue. */
+ inf_validate_stopped (inf);
+ inf_validate_task_sc (inf);
+}
+
+/* Take a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We'd better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via fork. */
+static void
+gnu_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (from_tty)
+ {
+ char *exec_file = get_exec_file (0);
+ if (exec_file)
+ printf_unfiltered ("Detaching from program `%s' pid %d\n",
+ exec_file, current_inferior->pid);
+ else
+ printf_unfiltered ("Detaching from pid %d\n", current_inferior->pid);
+ gdb_flush (gdb_stdout);
+ }
+
+ inf_detach (current_inferior);
+
+ inferior_pid = 0;
+
+ unpush_target (&gnu_ops); /* Pop out of handling an inferior */
+}
+#endif /* ATTACH_DETACH */
+
+static void
+gnu_terminal_init_inferior ()
+{
+ assert (current_inferior);
+ terminal_init_inferior_with_pgrp (current_inferior->pid);
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+gnu_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+static void
+gnu_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+static void
+gnu_stop ()
+{
+ error ("to_stop target function not implemented");
+}
+
+static int
+gnu_thread_alive (int tid)
+{
+ inf_update_procs (current_inferior);
+ return !!inf_tid_to_thread (current_inferior, tid);
+}
+
+/*
+ * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
+ * in gdb's address space.
+ *
+ * Return 0 on failure; number of bytes read otherwise.
+ */
+int
+gnu_read_inferior (task, addr, myaddr, length)
+ task_t task;
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ error_t err;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied;
+ int copy_count;
+
+ /* Get memory from inferior with page aligned addresses */
+ err = vm_read (task, low_address, aligned_length, &copied, &copy_count);
+ if (err)
+ return 0;
+
+ err = hurd_safe_copyin (myaddr, (void*)addr - low_address + copied, length);
+ if (err)
+ {
+ warning ("Read from inferior faulted: %s", strerror (err));
+ length = 0;
+ }
+
+ err = vm_deallocate (mach_task_self (), copied, copy_count);
+ if (err)
+ warning ("gnu_read_inferior vm_deallocate failed: %s", strerror (err));
+
+ return length;
+}
+
+#define CHK_GOTO_OUT(str,ret) \
+ do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
+
+struct vm_region_list {
+ struct vm_region_list *next;
+ vm_prot_t protection;
+ vm_address_t start;
+ vm_size_t length;
+};
+
+struct obstack region_obstack;
+
+/*
+ * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
+ * in gdb's address space.
+ */
+int
+gnu_write_inferior (task, addr, myaddr, length)
+ task_t task;
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ error_t err = 0;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied;
+ int copy_count;
+ int deallocate = 0;
+
+ char *errstr = "Bug in gnu_write_inferior";
+
+ struct vm_region_list *region_element;
+ struct vm_region_list *region_head = (struct vm_region_list *)NULL;
+
+ /* Get memory from inferior with page aligned addresses */
+ err = vm_read (task,
+ low_address,
+ aligned_length,
+ &copied,
+ &copy_count);
+ CHK_GOTO_OUT ("gnu_write_inferior vm_read failed", err);
+
+ deallocate++;
+
+ err = hurd_safe_copyout ((void*)addr - low_address + copied, myaddr, length);
+ CHK_GOTO_OUT ("Write to inferior faulted", err);
+
+ obstack_init (&region_obstack);
+
+ /* Do writes atomically.
+ * First check for holes and unwritable memory.
+ */
+ {
+ vm_size_t remaining_length = aligned_length;
+ vm_address_t region_address = low_address;
+
+ struct vm_region_list *scan;
+
+ while(region_address < low_address + aligned_length)
+ {
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ mach_port_t object_name;
+ vm_offset_t offset;
+ vm_size_t region_length = remaining_length;
+ vm_address_t old_address = region_address;
+
+ err = vm_region (task,
+ &region_address,
+ &region_length,
+ &protection,
+ &max_protection,
+ &inheritance,
+ &shared,
+ &object_name,
+ &offset);
+ CHK_GOTO_OUT ("vm_region failed", err);
+
+ /* Check for holes in memory */
+ if (old_address != region_address)
+ {
+ warning ("No memory at 0x%x. Nothing written",
+ old_address);
+ err = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ if (!(max_protection & VM_PROT_WRITE))
+ {
+ warning ("Memory at address 0x%x is unwritable. Nothing written",
+ old_address);
+ err = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ /* Chain the regions for later use */
+ region_element =
+ (struct vm_region_list *)
+ obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
+
+ region_element->protection = protection;
+ region_element->start = region_address;
+ region_element->length = region_length;
+
+ /* Chain the regions along with protections */
+ region_element->next = region_head;
+ region_head = region_element;
+
+ region_address += region_length;
+ remaining_length = remaining_length - region_length;
+ }
+
+ /* If things fail after this, we give up.
+ * Somebody is messing up inferior_task's mappings.
+ */
+
+ /* Enable writes to the chained vm regions */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ err = vm_protect (task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection | VM_PROT_WRITE);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", err);
+ }
+ }
+
+ err = vm_write (task,
+ low_address,
+ copied,
+ aligned_length);
+ CHK_GOTO_OUT ("vm_write failed", err);
+
+ /* Set up the original region protections, if they were changed */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ err = vm_protect (task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", err);
+ }
+ }
+ }
+
+ out:
+ if (deallocate)
+ {
+ obstack_free (&region_obstack, 0);
+
+ (void) vm_deallocate (mach_task_self (),
+ copied,
+ copy_count);
+ }
+
+ if (err != KERN_SUCCESS)
+ {
+ warning ("%s: %s", errstr, mach_error_string (err));
+ return 0;
+ }
+
+ return length;
+}
+
+/* Return 0 on failure, number of bytes handled otherwise. */
+static int
+gnu_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* IGNORED */
+{
+ int result;
+ task_t task =
+ current_inferior
+ ? (current_inferior->task ? current_inferior->task->port : 0)
+ : 0;
+
+ if (task == MACH_PORT_NULL)
+ return 0;
+ else
+ {
+ inf_debug (current_inferior, "%s %p[%d] %s %p",
+ write ? "writing" : "reading", memaddr, len,
+ write ? "<--" : "-->", myaddr);
+ if (write)
+ return gnu_write_inferior (task, memaddr, myaddr, len);
+ else
+ return gnu_read_inferior (task, memaddr, myaddr, len);
+ }
+}
+
+extern void gnu_store_registers (int regno);
+extern void gnu_fetch_registers (int regno);
+
+struct target_ops gnu_ops = {
+ "GNU", /* to_shortname */
+ "GNU Hurd process", /* to_longname */
+ "GNU Hurd process", /* to_doc */
+ gnu_open, /* to_open */
+ 0, /* to_close */
+ gnu_attach, /* to_attach */
+ gnu_detach, /* to_detach */
+ gnu_resume, /* to_resume */
+ gnu_wait, /* to_wait */
+ gnu_fetch_registers, /* to_fetch_registers */
+ gnu_store_registers, /* to_store_registers */
+ gnu_prepare_to_store, /* to_prepare_to_store */
+ gnu_xfer_memory, /* to_xfer_memory */
+ 0, /* to_files_info */
+ memory_insert_breakpoint, /* to_insert_breakpoint */
+ memory_remove_breakpoint, /* to_remove_breakpoint */
+ gnu_terminal_init_inferior, /* to_terminal_init */
+ terminal_inferior, /* to_terminal_inferior */
+ terminal_ours_for_output, /* to_terminal_ours_for_output */
+ terminal_ours, /* to_terminal_ours */
+ child_terminal_info, /* to_terminal_info */
+ gnu_kill_inferior, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+
+ gnu_create_inferior, /* to_create_inferior */
+ gnu_mourn_inferior, /* to_mourn_inferior */
+ gnu_can_run, /* to_can_run */
+ 0, /* to_notice_signals */
+ gnu_thread_alive, /* to_thread_alive */
+ gnu_stop, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+char *proc_string (struct proc *proc)
+{
+ static char tid_str[80];
+ if (proc_is_task (proc))
+ sprintf (tid_str, "process %d", proc->inf->pid);
+ else
+ sprintf (tid_str, "thread %d.%d",
+ proc->inf->pid,
+ pid_to_thread_id (proc->tid));
+ return tid_str;
+}
+
+char *
+gnu_target_pid_to_str (int tid)
+{
+ struct inf *inf = current_inferior;
+ struct proc *thread = inf_tid_to_thread (inf, tid);
+
+ if (thread)
+ return proc_string (thread);
+ else
+ {
+ static char tid_str[80];
+ sprintf (tid_str, "bogus thread id %d", tid);
+ return tid_str;
+ }
+}
+
+/* User task commands. */
+
+struct cmd_list_element *set_task_cmd_list = 0;
+struct cmd_list_element *show_task_cmd_list = 0;
+
+extern struct cmd_list_element *set_thread_default_cmd_list;
+extern struct cmd_list_element *show_thread_default_cmd_list;
+
+static int
+_parse_bool_arg (char *args, char *t_val, char *f_val, char *cmd_prefix)
+{
+ if (!args || strcmp (args, t_val) == 0)
+ return 1;
+ else if (strcmp (args, f_val) == 0)
+ return 0;
+ else
+ error ("Illegal argument for \"%s\" command, should be \"%s\" or \"%s\".",
+ cmd_prefix, t_val, f_val);
+}
+
+#define parse_bool_arg(args, cmd_prefix) \
+ _parse_bool_arg (args, "on", "off", cmd_prefix)
+
+static void
+check_empty (char *args, char *cmd_prefix)
+{
+ if (args)
+ error ("Garbage after \"%s\" command: `%s'", cmd_prefix, args);
+}
+
+/* Returns the alive thread named by INFERIOR_PID, or signals an error. */
+static struct proc *
+cur_thread ()
+{
+ struct inf *inf = cur_inf ();
+ struct proc *thread = inf_tid_to_thread (inf, inferior_pid);
+ if (!thread)
+ error ("No current thread.");
+ return thread;
+}
+
+static void
+set_task_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ int old_sc = inf->pause_sc;
+
+ inf->pause_sc = parse_bool_arg (args, "set task pause");
+
+ if (old_sc == 0 && inf->pause_sc != 0)
+ /* If the task is currently unsuspended, immediately suspend it,
+ otherwise wait until the next time it gets control. */
+ inf_suspend (inf);
+}
+
+static void
+show_task_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show task pause");
+ printf_unfiltered ("The inferior task %s suspended while gdb has control.\n",
+ inf->task
+ ? (inf->pause_sc == 0 ? "isn't" : "is")
+ : (inf->pause_sc == 0 ? "won't be" : "will be"));
+}
+
+static void
+set_thread_default_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ inf->default_thread_pause_sc =
+ parse_bool_arg (args, "set thread default pause") ? 0 : 1;
+}
+
+static void
+show_thread_default_pause_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ int sc = inf->default_thread_pause_sc;
+ check_empty (args, "show thread default pause");
+ printf_unfiltered ("New threads %s suspended while gdb has control%s.\n",
+ sc ? "are" : "aren't",
+ !sc && inf->pause_sc ? "(but the task is)" : "");
+}
+
+static void
+set_thread_default_run_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ inf->default_thread_run_sc =
+ parse_bool_arg (args, "set thread default run") ? 0 : 1;
+}
+
+static void
+show_thread_default_run_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show thread default run");
+ printf_unfiltered ("New threads %s allowed to run.\n",
+ inf->default_thread_run_sc == 0 ? "are" : "aren't");
+}
+
+/* Steal a send right called NAME in the inferior task, and make it PROC's
+ saved exception port. */
+static void
+steal_exc_port (struct proc *proc, mach_port_t name)
+{
+ error_t err;
+ mach_port_t port;
+ mach_msg_type_name_t port_type;
+
+ if (!proc || !proc->inf->task)
+ error ("No inferior task.");
+
+ err = mach_port_extract_right (proc->inf->task->port,
+ name, MACH_MSG_TYPE_COPY_SEND,
+ &port, &port_type);
+ if (err)
+ error ("Couldn't extract send right %d from inferior: %s",
+ name, strerror (err));
+
+ if (proc->saved_exc_port)
+ /* Get rid of our reference to the old one. */
+ mach_port_deallocate (mach_task_self (), proc->saved_exc_port);
+
+ proc->saved_exc_port = port;
+
+ if (! proc->exc_port)
+ /* If PROC is a thread, we may not have set its exception port before.
+ We can't use proc_steal_exc_port because it also sets saved_exc_port. */
+ {
+ proc->exc_port = proc->inf->event_port;
+ err = proc_set_exception_port (proc, proc->exc_port);
+ error ("Can't set exception port for %s: %s",
+ proc_string (proc), strerror (err));
+ }
+}
+
+static void
+set_task_exc_port_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ if (!args)
+ error ("No argument to \"set task exception-port\" command.");
+ steal_exc_port (inf->task, parse_and_eval_address (args));
+}
+
+static void
+set_signals_cmd (char *args, int from_tty)
+{
+ int trace;
+ struct inf *inf = cur_inf ();
+
+ inf->want_signals = parse_bool_arg (args, "set signals");
+
+ if (inf->task && inf->want_signals != inf->traced)
+ /* Make this take effect immediately in a running process. */
+ inf_set_traced (inf, inf->want_signals);
+}
+
+static void
+show_signals_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show signals");
+ printf_unfiltered ("The inferior process's signals %s intercepted.\n",
+ inf->task
+ ? (inf->traced ? "are" : "aren't")
+ : (inf->want_signals ? "will be" : "won't be"));
+}
+
+static void
+set_stopped_cmd (char *args, int from_tty)
+{
+ cur_inf ()->stopped = _parse_bool_arg (args, "yes", "no", "set stopped");
+}
+
+static void
+show_stopped_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show stopped");
+ if (! inf->task)
+ error ("No current process.");
+ printf_unfiltered ("The inferior process %s stopped.\n",
+ inf->stopped ? "is" : "isn't");
+}
+
+static void
+set_sig_thread_cmd (char *args, int from_tty)
+{
+ int tid;
+ struct inf *inf = cur_inf ();
+
+ if (!args || (! isdigit (*args) && strcmp (args, "none") != 0))
+ error ("Illegal argument to \"set signal-thread\" command.\n"
+ "Should be an integer thread ID, or `none'.");
+
+ if (strcmp (args, "none") == 0)
+ inf->signal_thread = 0;
+ else
+ {
+ int tid = thread_id_to_pid (atoi (args));
+ if (tid < 0)
+ error ("Thread ID %s not known. Use the \"info threads\" command to\n"
+ "see the IDs of currently known threads.", args);
+ inf->signal_thread = inf_tid_to_thread (inf, tid);
+ }
+}
+
+static void
+show_sig_thread_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show signal-thread");
+ if (! inf->task)
+ error ("No current process.");
+ if (inf->signal_thread)
+ printf_unfiltered ("The signal thread is %s.\n",
+ proc_string (inf->signal_thread));
+ else
+ printf_unfiltered ("There is no signal thread.\n");
+}
+
+static void
+set_exceptions_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ int val = parse_bool_arg (args, "set exceptions");
+
+ if (inf->task && inf->want_exceptions != val)
+ /* Make this take effect immediately in a running process. */
+ /* XXX */;
+
+ inf->want_exceptions = val;
+}
+
+static void
+show_exceptions_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+ check_empty (args, "show exceptions");
+ printf_unfiltered ("Exceptions in the inferior %s trapped.\n",
+ inf->task
+ ? (inf->want_exceptions ? "are" : "aren't")
+ : (inf->want_exceptions ? "will be" : "won't be"));
+}
+
+static void
+set_task_cmd (char *args, int from_tty)
+{
+ printf_unfiltered ("\"set task\" must be followed by the name of a task property.\n");
+}
+
+static void
+show_task_cmd (char *args, int from_tty)
+{
+ struct inf *inf = cur_inf ();
+
+ check_empty (args, "show task");
+
+ show_signals_cmd (0, from_tty);
+ show_exceptions_cmd (0, from_tty);
+ show_task_pause_cmd (0, from_tty);
+
+ if (inf->pause_sc == 0)
+ show_thread_default_pause_cmd (0, from_tty);
+ show_thread_default_run_cmd (0, from_tty);
+
+ if (inf->task)
+ {
+ show_stopped_cmd (0, from_tty);
+ show_sig_thread_cmd (0, from_tty);
+ }
+}
+
+static void add_task_commands ()
+{
+ add_cmd ("pause", class_run, set_thread_default_pause_cmd,
+ "Set whether the new threads are suspended while gdb has control.\n"
+ "This property normally has no effect because the whole task is\n"
+ "suspended, however, that may be disabled with \"set task pause off\".\n"
+ "The default value is \"off\".",
+ &set_thread_default_cmd_list);
+ add_cmd ("pause", no_class, show_thread_default_pause_cmd,
+ "Show whether new threads are suspended while gdb has control.",
+ &show_thread_default_cmd_list);
+ add_cmd ("run", class_run, set_thread_default_run_cmd,
+ "Set whether new threads are allowed to run (once gdb has noticed them).",
+ &set_thread_default_cmd_list);
+ add_cmd ("run", no_class, show_thread_default_run_cmd,
+ "Show whether new threads are allowed to run (once gdb has noticed
+them).",
+ &show_thread_default_cmd_list);
+
+ add_cmd ("signals", class_run, set_signals_cmd,
+ "Set whether the inferior process's signals will be intercepted.\n"
+ "Mach exceptions (such as breakpoint traps) are not affected.",
+ &setlist);
+ add_alias_cmd ("sigs", "signals", class_run, 1, &setlist);
+ add_cmd ("signals", no_class, show_signals_cmd,
+ "Show whether the inferior process's signals will be intercepted.",
+ &showlist);
+ add_alias_cmd ("sigs", "signals", no_class, 1, &showlist);
+
+ add_cmd ("signal-thread", class_run, set_sig_thread_cmd,
+ "Set the thread that gdb thinks is the libc signal thread.\n"
+ "This thread is run when delivering a signal to a non-stopped process.",
+ &setlist);
+ add_alias_cmd ("sigthread", "signal-thread", class_run, 1, &setlist);
+ add_cmd ("signal-thread", no_class, show_sig_thread_cmd,
+ "Set the thread that gdb thinks is the libc signal thread.",
+ &showlist);
+ add_alias_cmd ("sigthread", "signal-thread", no_class, 1, &showlist);
+
+ add_cmd ("stopped", class_run, set_stopped_cmd,
+ "Set whether gdb thinks the inferior process is stopped as with SIGSTOP.\n"
+ "Stopped process will be continued by sending them a signal.",
+ &setlist);
+ add_cmd ("stopped", no_class, show_signals_cmd,
+ "Show whether gdb thinks the inferior process is stopped as with SIGSTOP.",
+ &showlist);
+
+ add_cmd ("exceptions", class_run, set_exceptions_cmd,
+ "Set whether exceptions in the inferior process will be trapped.\n"
+ "When exceptions are turned off, neither breakpoints nor single-stepping\n"
+ "will work.",
+ &setlist);
+ /* Allow `set exc' despite conflict with `set exception-port'. */
+ add_alias_cmd ("exc", "exceptions", class_run, 1, &setlist);
+ add_cmd ("exceptions", no_class, show_exceptions_cmd,
+ "Show whether exceptions in the inferior process will be trapped.",
+ &showlist);
+
+
+
+ add_prefix_cmd ("task", no_class, set_task_cmd,
+ "Command prefix for setting task attributes.",
+ &set_task_cmd_list, "set task ", 0, &setlist);
+ add_prefix_cmd ("task", no_class, show_task_cmd,
+ "Command prefix for showing task attributes.",
+ &show_task_cmd_list, "show task ", 0, &showlist);
+
+ add_cmd ("pause", class_run, set_task_pause_cmd,
+ "Set whether the task is suspended while gdb has control.\n"
+ "A value of \"on\" takes effect immediately, otherwise nothing\n"
+ "happens until the next time the program is continued.\n"
+ "When setting this to \"off\", \"set thread default pause on\"\n"
+ "can be used to pause individual threads by default instead.",
+ &set_task_cmd_list);
+ add_cmd ("pause", no_class, show_task_pause_cmd,
+ "Show whether the task is suspended while gdb has control.",
+ &show_task_cmd_list);
+
+ add_cmd ("exception-port", no_class, set_task_exc_port_cmd,
+ "Set the task exception port to which we forward exceptions.\n"
+ "The argument should be the value of the send right in the task.",
+ &set_task_cmd_list);
+ add_alias_cmd ("excp", "exception-port", no_class, 1, &set_task_cmd_list);
+ add_alias_cmd ("exc-port", "exception-port", no_class, 1, &set_task_cmd_list);
+}
+
+/* User thread commands. */
+
+extern struct cmd_list_element *set_thread_cmd_list;
+extern struct cmd_list_element *show_thread_cmd_list;
+
+static void
+set_thread_pause_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ int old_sc = thread->pause_sc;
+ thread->pause_sc = parse_bool_arg (args, "set thread pause");
+ if (old_sc == 0 && thread->pause_sc != 0 && thread->inf->pause_sc == 0)
+ /* If the task is currently unsuspended, immediately suspend it,
+ otherwise wait until the next time it gets control. */
+ inf_suspend (thread->inf);
+}
+
+static void
+show_thread_pause_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ int sc = thread->pause_sc;
+ check_empty (args, "show task pause");
+ printf_unfiltered ("Thread %s %s suspended while gdb has control%s.\n",
+ proc_string (thread),
+ sc ? "is" : "isn't",
+ !sc && thread->inf->pause_sc ? "(but the task is)" : "");
+}
+
+static void
+set_thread_run_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ thread->run_sc = parse_bool_arg (args, "set thread run") ? 0 : 1;
+}
+
+static void
+show_thread_run_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ check_empty (args, "show thread run");
+ printf_unfiltered ("Thread %s allowed to run.",
+ proc_string (thread),
+ thread->run_sc == 0 ? "is" : "isn't");
+}
+
+static void
+set_thread_exc_port_cmd (char *args, int from_tty)
+{
+ struct proc *thread = cur_thread ();
+ if (!args)
+ error ("No argument to \"set thread exception-port\" command.");
+ steal_exc_port (thread, parse_and_eval_address (args));
+}
+
+static void
+set_thread_cmd (char *args, int from_tty)
+{
+ printf_unfiltered ("\"set thread\" must be followed by the name of a thread property.\n");
+}
+
+static void
+show_thread_cmd (char *args, int from_tty)
+{
+ check_empty (args, "show thread");
+ show_thread_run_cmd (0, from_tty);
+ show_thread_pause_cmd (0, from_tty);
+}
+
+add_thread_commands ()
+{
+ add_cmd ("pause", class_run, set_thread_pause_cmd,
+ "Set whether the current thread is suspended while gdb has control.\n"
+ "A value of \"on\" takes effect immediately, otherwise nothing\n"
+ "happens until the next time the program is continued. This\n"
+ "property normally has no effect because the whole task is suspended,\n"
+ "however, that may be disabled with \"set task pause off\".\n"
+ "The default value is \"off\".",
+ &set_thread_cmd_list);
+ add_cmd ("pause", no_class, show_thread_pause_cmd,
+ "Show whether the current thread is suspended while gdb has control.",
+ &show_thread_cmd_list);
+
+ add_cmd ("run", class_run, set_thread_run_cmd,
+ "Set whether the current thread is allowed to run.",
+ &set_thread_cmd_list);
+ add_cmd ("run", no_class, show_thread_run_cmd,
+ "Show whether the current thread is allowed to run.",
+ &show_thread_cmd_list);
+
+ add_cmd ("exception-port", no_class, set_thread_exc_port_cmd,
+ "Set the exception port to which we forward exceptions for the\n"
+ "current thread, overriding the task exception port.\n"
+ "The argument should be the value of the send right in the task.",
+ &set_thread_cmd_list);
+ add_alias_cmd ("excp", "exception-port", no_class, 1, &set_thread_cmd_list);
+ add_alias_cmd ("exc-port", "exception-port", no_class, 1, &set_thread_cmd_list);
+}
+
+void
+_initialize_gnu_nat ()
+{
+ proc_server = getproc ();
+
+ add_target (&gnu_ops);
+
+ add_task_commands ();
+ add_thread_commands ();
+
+#if MAINTENANCE_CMDS
+ add_set_cmd ("gnu-debug", class_maintenance,
+ var_boolean, (char *)&gnu_debug_flag,
+ "Set debugging output for the gnu backend.", &maintenancelist);
+#endif
+}
+
+#ifdef FLUSH_INFERIOR_CACHE
+
+/* When over-writing code on some machines the I-Cache must be flushed
+ explicitly, because it is not kept coherent by the lazy hardware.
+ This definitely includes breakpoints, for instance, or else we
+ end up looping in mysterious Bpt traps */
+
+void
+flush_inferior_icache(pc, amount)
+ CORE_ADDR pc;
+{
+ vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
+ error_t ret;
+
+ ret = vm_machine_attribute (current_inferior->task->port,
+ pc,
+ amount,
+ MATTR_CACHE,
+ &flush);
+ if (ret != KERN_SUCCESS)
+ warning ("Error flushing inferior's cache : %s", strerror (ret));
+}
+#endif FLUSH_INFERIOR_CACHE
diff --git a/contrib/gdb/gdb/gnu-nat.h b/contrib/gdb/gdb/gnu-nat.h
new file mode 100644
index 0000000..6f29b73
--- /dev/null
+++ b/contrib/gdb/gdb/gnu-nat.h
@@ -0,0 +1,91 @@
+/* Common things used by the various *gnu-nat.c files
+
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ The GNU Hurd is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */
+
+#ifndef __GNU_NAT_H__
+#define __GNU_NAT_H__
+
+#include <unistd.h>
+#include <mach.h>
+
+struct inf;
+
+extern struct inf *current_inferior;
+
+/* Converts a GDB pid to a struct proc. */
+struct proc *inf_tid_to_thread (struct inf *inf, int tid);
+
+/* A proc is either a thread, or the task (there can only be one task proc
+ because it always has the same TID, PROC_TID_TASK). */
+struct proc
+{
+ thread_t port; /* The task or thread port. */
+ int tid; /* The GDB pid (actually a thread id). */
+ int num; /* An id number for threads, to print. */
+
+ mach_port_t saved_exc_port; /* The task/thread's real exception port. */
+ mach_port_t exc_port; /* Our replacement, which for. */
+
+ int sc; /* Desired suspend count. */
+ int cur_sc; /* Implemented suspend count. */
+ int run_sc; /* Default sc when the program is running. */
+ int pause_sc; /* Default sc when gdb has control. */
+ int resume_sc; /* Sc resulting form the last resume. */
+
+ thread_state_data_t state; /* Registers, &c. */
+ int state_valid : 1; /* True if STATE is up to date. */
+ int state_changed : 1;
+
+ int aborted : 1; /* True if thread_abort has been called. */
+
+ /* Bit mask of registers fetched by gdb. This is used when we re-fetch
+ STATE after aborting the thread, to detect that gdb may have out-of-date
+ information. */
+ unsigned long fetched_regs;
+
+ struct inf *inf; /* Where we come from. */
+
+ struct proc *next;
+};
+
+/* The task has a thread entry with this TID. */
+#define PROC_TID_TASK (-1)
+
+#define proc_is_task(proc) ((proc)->tid == PROC_TID_TASK)
+#define proc_is_thread(proc) ((proc)->tid != PROC_TID_TASK)
+
+extern int __proc_pid (struct proc *proc);
+
+extern thread_state_t proc_get_state (struct proc *proc, int will_modify);
+
+#define proc_debug(_proc, msg, args...) \
+ do { struct proc *__proc = (_proc); \
+ debug ("{proc %d/%d %p}: " msg, \
+ __proc_pid (__proc), __proc->tid, __proc , ##args); } while (0)
+
+#if MAINTENANCE_CMDS
+extern int gnu_debug_flag;
+#define debug(msg, args...) \
+ do { if (gnu_debug_flag) \
+ fprintf (stderr, "%s: " msg "\r\n", __FUNCTION__ , ##args); } while (0)
+#else
+#define debug(msg, args...) (void)0
+#endif
+
+#endif /* __GNU_NAT_H__ */
diff --git a/contrib/gdb/gdb/gnu-regex.c b/contrib/gdb/gdb/gnu-regex.c
new file mode 100644
index 0000000..dec0cf1
--- /dev/null
+++ b/contrib/gdb/gdb/gnu-regex.c
@@ -0,0 +1,1759 @@
+/* Extended regular expression matching and search library.
+ Copyright (C) 1985, 1989 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* To test, compile with -Dtest.
+ This Dtestable feature turns this into a self-contained program
+ which reads a pattern, describes how it compiles,
+ then reads a string and searches for it. */
+
+#ifdef emacs
+
+/* The `emacs' switch turns on certain special matching commands
+ that make sense only in emacs. */
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+#else /* not emacs */
+
+#include "defs.h"
+#include "gdb_string.h"
+#undef malloc
+#define malloc xmalloc
+
+/*
+ * Define the syntax stuff, so we can do the \<...\> things.
+ */
+
+#ifndef Sword /* must be non-zero in some of the tests below... */
+#define Sword 1
+#endif
+
+#define SYNTAX(c) re_syntax_table[c]
+
+#ifdef SYNTAX_TABLE
+
+char *re_syntax_table;
+
+#else
+
+static char re_syntax_table[256];
+
+static void
+init_syntax_once ()
+{
+ register int c;
+ static int done = 0;
+
+ if (done)
+ return;
+
+ memset (re_syntax_table, '\0', sizeof re_syntax_table);
+
+ for (c = 'a'; c <= 'z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = 'A'; c <= 'Z'; c++)
+ re_syntax_table[c] = Sword;
+
+ for (c = '0'; c <= '9'; c++)
+ re_syntax_table[c] = Sword;
+
+ done = 1;
+}
+
+#endif /* SYNTAX_TABLE */
+#endif /* not emacs */
+
+#include "gnu-regex.h"
+
+/* Number of failure points to allocate space for initially,
+ when matching. If this number is exceeded, more space is allocated,
+ so it is not a hard limit. */
+
+#ifndef NFAILURES
+#define NFAILURES 80
+#endif /* NFAILURES */
+
+/* width of a byte in bits */
+
+#define BYTEWIDTH 8
+
+/* 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;
+
+/* Specify the precise syntax of regexp for compilation.
+ This provides for compatibility for various utilities
+ which historically have different, incompatible syntaxes.
+
+ The argument SYNTAX is a bit-mask containing the two bits
+ RE_NO_BK_PARENS and RE_NO_BK_VBAR. */
+
+int
+re_set_syntax (syntax)
+ int syntax;
+{
+ int ret;
+
+ ret = obscure_syntax;
+ obscure_syntax = syntax;
+ return ret;
+}
+
+/* re_compile_pattern takes a regular-expression string
+ and converts it into a buffer full of byte commands for matching.
+
+ PATTERN is the address of the pattern string
+ SIZE is the length of it.
+ BUFP is a struct re_pattern_buffer * which points to the info
+ on where to store the byte commands.
+ This structure contains a char * which points to the
+ actual space, which should have been obtained with malloc.
+ re_compile_pattern may use realloc to grow the buffer space.
+
+ The number of bytes of commands can be found out by looking in
+ the struct re_pattern_buffer that bufp pointed to,
+ after re_compile_pattern returns.
+*/
+
+#define PATPUSH(ch) (*b++ = (char) (ch))
+
+#define PATFETCH(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; \
+ if (translate) c = translate[c]; }
+
+#define PATFETCH_RAW(c) \
+ {if (p == pend) goto end_of_pattern; \
+ c = * (unsigned char *) p++; }
+
+#define PATUNFETCH p--
+
+/* 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 ();
+
+char *
+re_compile_pattern (pattern, size, bufp)
+ char *pattern;
+ int size;
+ struct re_pattern_buffer *bufp;
+{
+ register char *b = bufp->buffer;
+ register char *p = pattern;
+ char *pend = pattern + size;
+ register unsigned c, c1;
+ char *p1;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ /* address of the count-byte of the most recently inserted "exactn" command.
+ This makes it possible to tell whether a new exact-match character
+ can be added to that command or requires a new "exactn" command. */
+
+ char *pending_exact = 0;
+
+ /* address of the place where a forward-jump should go
+ to the end of the containing expression.
+ Each alternative of an "or", except the last, ends with a forward-jump
+ of this sort. */
+
+ char *fixup_jump = 0;
+
+ /* address of start of the most recently finished expression.
+ This tells postfix * where to find the start of its operand. */
+
+ char *laststart = 0;
+
+ /* In processing a repeat, 1 means zero matches is allowed */
+
+ char zero_times_ok;
+
+ /* In processing a repeat, 1 means many matches is allowed */
+
+ char many_times_ok;
+
+ /* address of beginning of regexp, or inside of last \( */
+
+ char *begalt = b;
+
+ /* Stack of information saved by \( and restored by \).
+ Four stack elements are pushed by each \(:
+ First, the value of b.
+ Second, the value of fixup_jump.
+ Third, the value of regnum.
+ Fourth, the value of begalt. */
+
+ int stackb[40];
+ int *stackp = stackb;
+ int *stacke = stackb + 40;
+ int *stackt;
+
+ /* Counts \('s as they are encountered. Remembered for the matching \),
+ where it becomes the "register number" to put in the stop_memory command */
+
+ int regnum = 1;
+
+ bufp->fastmap_accurate = 0;
+
+#ifndef emacs
+#ifndef SYNTAX_TABLE
+ /*
+ * Initialize the syntax table.
+ */
+ init_syntax_once();
+#endif
+#endif
+
+ if (bufp->allocated == 0)
+ {
+ bufp->allocated = 28;
+ if (bufp->buffer)
+ /* EXTEND_BUFFER loses when bufp->allocated is 0 */
+ bufp->buffer = (char *) realloc (bufp->buffer, 28);
+ else
+ /* Caller did not allocate a buffer. Do it for him */
+ bufp->buffer = (char *) malloc (28);
+ if (!bufp->buffer) goto memory_exhausted;
+ begalt = b = bufp->buffer;
+ }
+
+ while (p != pend)
+ {
+ if (b - bufp->buffer > bufp->allocated - 10)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ PATFETCH (c);
+
+ switch (c)
+ {
+ case '$':
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (! (obscure_syntax & RE_CONTEXT_INDEP_OPS) && p != pend)
+ goto normal_char;
+ /* Make operand of last vbar end before this `$'. */
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = 0;
+ PATPUSH (endline);
+ break;
+ }
+
+ /* $ means succeed if at end of line, but only in special contexts.
+ If randomly in the middle of a pattern, it is a normal character. */
+ if (p == pend || *p == '\n'
+ || (obscure_syntax & RE_CONTEXT_INDEP_OPS)
+ || (obscure_syntax & RE_NO_BK_PARENS
+ ? *p == ')'
+ : *p == '\\' && p[1] == ')')
+ || (obscure_syntax & RE_NO_BK_VBAR
+ ? *p == '|'
+ : *p == '\\' && p[1] == '|'))
+ {
+ PATPUSH (endline);
+ break;
+ }
+ goto normal_char;
+
+ case '^':
+ /* ^ means succeed if at beg of line, but only if no preceding pattern. */
+
+ if (laststart && p[-2] != '\n'
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ if (obscure_syntax & RE_TIGHT_VBAR)
+ {
+ if (p != pattern + 1
+ && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ PATPUSH (begline);
+ begalt = b;
+ }
+ else
+ PATPUSH (begline);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto normal_char;
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern, char not special. */
+ if (!laststart && ! (obscure_syntax & RE_CONTEXT_INDEP_OPS))
+ goto normal_char;
+ /* If there is a sequence of repetition chars,
+ collapse it down to equivalent to just one. */
+ zero_times_ok = 0;
+ many_times_ok = 0;
+ while (1)
+ {
+ zero_times_ok |= c != '+';
+ many_times_ok |= c != '?';
+ if (p == pend)
+ break;
+ PATFETCH (c);
+ if (c == '*')
+ ;
+ else if (!(obscure_syntax & RE_BK_PLUS_QM)
+ && (c == '+' || c == '?'))
+ ;
+ else if ((obscure_syntax & RE_BK_PLUS_QM)
+ && c == '\\')
+ {
+ int c1;
+ PATFETCH (c1);
+ if (!(c1 == '+' || c1 == '?'))
+ {
+ PATUNFETCH;
+ PATUNFETCH;
+ break;
+ }
+ c = c1;
+ }
+ else
+ {
+ PATUNFETCH;
+ break;
+ }
+ }
+
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
+
+ /* Now we know whether 0 matches is allowed,
+ and whether 2 or more matches is allowed. */
+ if (many_times_ok)
+ {
+ /* If more than one repetition is allowed,
+ put in a backward jump at the end. */
+ store_jump (b, maybe_finalize_jump, laststart - 3);
+ b += 3;
+ }
+ insert_jump (on_failure_jump, laststart, b + 3, b);
+ pending_exact = 0;
+ b += 3;
+ if (!zero_times_ok)
+ {
+ /* At least one repetition required: insert before the loop
+ a skip over the initial on-failure-jump instruction */
+ insert_jump (dummy_failure_jump, laststart, laststart + 6, b);
+ b += 3;
+ }
+ break;
+
+ case '.':
+ laststart = b;
+ PATPUSH (anychar);
+ break;
+
+ case '[':
+ while (b - bufp->buffer
+ > bufp->allocated - 3 - (1 << BYTEWIDTH) / BYTEWIDTH)
+ /* Note that EXTEND_BUFFER clobbers c */
+ EXTEND_BUFFER;
+
+ laststart = b;
+ if (*p == '^')
+ PATPUSH (charset_not), p++;
+ else
+ PATPUSH (charset);
+ p1 = p;
+
+ PATPUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Clear the whole map */
+ memset (b, '\0', (1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Read in characters and ranges, setting map bits */
+ while (1)
+ {
+ PATFETCH (c);
+ if (c == ']' && p != p1 + 1) break;
+ if (*p == '-' && p[1] != ']')
+ {
+ PATFETCH (c1);
+ PATFETCH (c1);
+ while (c <= c1)
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH), c++;
+ }
+ else
+ {
+ b[c / BYTEWIDTH] |= 1 << (c % BYTEWIDTH);
+ }
+ }
+ /* Discard any bitmap bytes that are all 0 at the end of the map.
+ Decrement the map-length byte too. */
+ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ b += b[-1];
+ break;
+
+ case '(':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_open;
+
+ case ')':
+ if (! (obscure_syntax & RE_NO_BK_PARENS))
+ goto normal_char;
+ else
+ goto handle_close;
+
+ case '\n':
+ if (! (obscure_syntax & RE_NEWLINE_OR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '|':
+ if (! (obscure_syntax & RE_NO_BK_VBAR))
+ goto normal_char;
+ else
+ goto handle_bar;
+
+ case '\\':
+ if (p == pend) goto invalid_pattern;
+ PATFETCH_RAW (c);
+ switch (c)
+ {
+ case '(':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_open:
+ if (stackp == stacke) goto nesting_too_deep;
+ if (regnum < RE_NREGS)
+ {
+ PATPUSH (start_memory);
+ PATPUSH (regnum);
+ }
+ *stackp++ = b - bufp->buffer;
+ *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0;
+ *stackp++ = regnum++;
+ *stackp++ = begalt - bufp->buffer;
+ fixup_jump = 0;
+ laststart = 0;
+ begalt = b;
+ break;
+
+ case ')':
+ if (obscure_syntax & RE_NO_BK_PARENS)
+ goto normal_backsl;
+ handle_close:
+ if (stackp == stackb) goto unmatched_close;
+ begalt = *--stackp + bufp->buffer;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ if (stackp[-1] < RE_NREGS)
+ {
+ PATPUSH (stop_memory);
+ PATPUSH (stackp[-1]);
+ }
+ stackp -= 2;
+ fixup_jump = 0;
+ if (*stackp)
+ fixup_jump = *stackp + bufp->buffer - 1;
+ laststart = *--stackp + bufp->buffer;
+ break;
+
+ case '|':
+ if (obscure_syntax & RE_NO_BK_VBAR)
+ goto normal_backsl;
+ handle_bar:
+ insert_jump (on_failure_jump, begalt, b + 6, b);
+ pending_exact = 0;
+ b += 3;
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+ fixup_jump = b;
+ b += 3;
+ laststart = 0;
+ begalt = b;
+ break;
+
+#ifdef emacs
+ case '=':
+ PATPUSH (at_dot);
+ break;
+
+ case 's':
+ laststart = b;
+ PATPUSH (syntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+
+ case 'S':
+ laststart = b;
+ PATPUSH (notsyntaxspec);
+ PATFETCH (c);
+ PATPUSH (syntax_spec_code[c]);
+ break;
+#endif /* emacs */
+
+ case 'w':
+ laststart = b;
+ PATPUSH (wordchar);
+ break;
+
+ case 'W':
+ laststart = b;
+ PATPUSH (notwordchar);
+ break;
+
+ case '<':
+ PATPUSH (wordbeg);
+ break;
+
+ case '>':
+ PATPUSH (wordend);
+ break;
+
+ case 'b':
+ PATPUSH (wordbound);
+ break;
+
+ case 'B':
+ PATPUSH (notwordbound);
+ break;
+
+ case '`':
+ PATPUSH (begbuf);
+ break;
+
+ case '\'':
+ PATPUSH (endbuf);
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c - '0';
+ if (c1 >= regnum)
+ goto normal_char;
+ for (stackt = stackp - 2; stackt > stackb; stackt -= 4)
+ if (*stackt == c1)
+ goto normal_char;
+ laststart = b;
+ PATPUSH (duplicate);
+ PATPUSH (c1);
+ break;
+
+ case '+':
+ case '?':
+ if (obscure_syntax & RE_BK_PLUS_QM)
+ goto handle_plus;
+
+ default:
+ normal_backsl:
+ /* You might think it would be useful for \ to mean
+ not to translate; but if we don't translate it
+ it will never match anything. */
+ if (translate) c = translate[c];
+ goto normal_char;
+ }
+ break;
+
+ default:
+ normal_char:
+ if (!pending_exact || pending_exact + *pending_exact + 1 != b
+ || *pending_exact == 0177 || *p == '*' || *p == '^'
+ || ((obscure_syntax & RE_BK_PLUS_QM)
+ ? *p == '\\' && (p[1] == '+' || p[1] == '?')
+ : (*p == '+' || *p == '?')))
+ {
+ laststart = b;
+ PATPUSH (exactn);
+ pending_exact = b;
+ PATPUSH (0);
+ }
+ PATPUSH (c);
+ (*pending_exact)++;
+ }
+ }
+
+ if (fixup_jump)
+ store_jump (fixup_jump, jump, b);
+
+ if (stackp != stackb) goto unmatched_open;
+
+ bufp->used = b - bufp->buffer;
+ return 0;
+
+ invalid_pattern:
+ return "Invalid regular expression";
+
+ unmatched_open:
+ return "Unmatched \\(";
+
+ unmatched_close:
+ return "Unmatched \\)";
+
+ end_of_pattern:
+ return "Premature end of regular expression";
+
+ nesting_too_deep:
+ return "Nesting too deep";
+
+ too_big:
+ return "Regular expression too big";
+
+ memory_exhausted:
+ return "Memory exhausted";
+}
+
+/* Store where `from' points a jump operation to jump to where `to' points.
+ `opcode' is the opcode to store. */
+
+static void
+store_jump (from, opcode, to)
+ char *from, *to;
+ char opcode;
+{
+ from[0] = opcode;
+ from[1] = (to - (from + 3)) & 0377;
+ from[2] = (to - (from + 3)) >> 8;
+}
+
+/* Open up space at char FROM, and insert there a jump to TO.
+ CURRENT_END gives te end of the storage no in use,
+ so we know how much data to copy up.
+ OP is the opcode of the jump to insert.
+
+ If you call this function, you must zero out pending_exact. */
+
+static void
+insert_jump (op, from, to, current_end)
+ char op;
+ char *from, *to, *current_end;
+{
+ register char *pto = current_end + 3;
+ register char *pfrom = current_end;
+ while (pfrom != from)
+ *--pto = *--pfrom;
+ store_jump (from, op, to);
+}
+
+/* Given a pattern, compute a fastmap from it.
+ The fastmap records which of the (1 << BYTEWIDTH) possible characters
+ can start a string that matches the pattern.
+ This fastmap is used by re_search to skip quickly over totally implausible text.
+
+ The caller must supply the address of a (1 << BYTEWIDTH)-byte data area
+ as bufp->fastmap.
+ The other components of bufp describe the pattern to be used. */
+
+void
+re_compile_fastmap (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ unsigned char *pattern = (unsigned char *) bufp->buffer;
+ int size = bufp->used;
+ register char *fastmap = bufp->fastmap;
+ register unsigned char *p = pattern;
+ register unsigned char *pend = pattern + size;
+ register int j;
+ unsigned char *translate = (unsigned char *) bufp->translate;
+
+ unsigned char *stackb[NFAILURES];
+ unsigned char **stackp = stackb;
+
+ memset (fastmap, '\0', (1 << BYTEWIDTH));
+ bufp->fastmap_accurate = 1;
+ bufp->can_be_null = 0;
+
+ while (p)
+ {
+ if (p == pend)
+ {
+ bufp->can_be_null = 1;
+ break;
+ }
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+ case exactn:
+ if (translate)
+ fastmap[translate[p[1]]] = 1;
+ else
+ fastmap[p[1]] = 1;
+ break;
+
+ case begline:
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ case begbuf:
+ case endbuf:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ continue;
+
+ case endline:
+ if (translate)
+ fastmap[translate['\n']] = 1;
+ else
+ fastmap['\n'] = 1;
+ if (bufp->can_be_null != 1)
+ bufp->can_be_null = 2;
+ break;
+
+ case finalize_jump:
+ case maybe_finalize_jump:
+ case jump:
+ case dummy_failure_jump:
+ bufp->can_be_null = 1;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (j > 0)
+ continue;
+ /* Jump backward reached implies we just went through
+ the body of a loop and matched nothing.
+ Opcode jumped to should be an on_failure_jump.
+ Just treat it like an ordinary jump.
+ For a * loop, it has pushed its failure point already;
+ if so, discard that as redundant. */
+ if ((enum regexpcode) *p != on_failure_jump)
+ continue;
+ p++;
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += j + 1; /* The 1 compensates for missing ++ above */
+ if (stackp != stackb && *stackp == p)
+ stackp--;
+ continue;
+
+ case on_failure_jump:
+ j = *p++ & 0377;
+ j += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *++stackp = p + j;
+ continue;
+
+ case start_memory:
+ case stop_memory:
+ p++;
+ continue;
+
+ case duplicate:
+ bufp->can_be_null = 1;
+ fastmap['\n'] = 1;
+ case anychar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (j != '\n')
+ fastmap[j] = 1;
+ if (bufp->can_be_null)
+ return;
+ /* Don't return; check the alternative paths
+ so we can set can_be_null if appropriate. */
+ break;
+
+ case wordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == Sword)
+ fastmap[j] = 1;
+ break;
+
+ case notwordchar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != Sword)
+ fastmap[j] = 1;
+ break;
+
+#ifdef emacs
+ case syntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) == (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+
+ case notsyntaxspec:
+ k = *p++;
+ for (j = 0; j < (1 << BYTEWIDTH); j++)
+ if (SYNTAX (j) != (enum syntaxcode) k)
+ fastmap[j] = 1;
+ break;
+#endif /* emacs */
+
+ case charset:
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+
+ case charset_not:
+ /* Chars beyond end of map must be allowed */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
+ {
+ if (translate)
+ fastmap[translate[j]] = 1;
+ else
+ fastmap[j] = 1;
+ }
+ break;
+ case unused:
+ case syntaxspec:
+ case notsyntaxspec:
+ default:
+ break;
+ }
+
+ /* Get here means we have successfully found the possible starting characters
+ of one path of the pattern. We need not follow this path any farther.
+ Instead, look at the next alternative remembered in the stack. */
+ if (stackp != stackb)
+ p = *stackp--;
+ else
+ break;
+ }
+}
+
+/* Like re_search_2, below, but only one string is specified. */
+
+int
+re_search (pbufp, string, size, startpos, range, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, startpos, range;
+ struct re_registers *regs;
+{
+ return re_search_2 (pbufp, 0, 0, string, size, startpos, range, regs, size);
+}
+
+/* Like re_match_2 but tries first a match starting at index STARTPOS,
+ then at STARTPOS + 1, and so on.
+ RANGE is the number of places to try before giving up.
+ If RANGE is negative, the starting positions tried are
+ STARTPOS, STARTPOS - 1, etc.
+ It is up to the caller to make sure that range is not so large
+ as to take the starting position outside of the input strings.
+
+The value returned is the position at which the match was found,
+ or -1 if no match was found,
+ or -2 if error (such as failure stack overflow). */
+
+int
+re_search_2 (pbufp, string1, size1, string2, size2, startpos, range, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ char *string1, *string2;
+ int size1, size2;
+ int startpos;
+ register int range;
+ struct re_registers *regs;
+ int mstop;
+{
+ register char *fastmap = pbufp->fastmap;
+ register unsigned char *translate = (unsigned char *) pbufp->translate;
+ int total = size1 + size2;
+ int val;
+
+ /* Update the fastmap now if not correct already */
+ if (fastmap && !pbufp->fastmap_accurate)
+ re_compile_fastmap (pbufp);
+
+ /* Don't waste time in a long search for a pattern
+ that says it is anchored. */
+ if (pbufp->used > 0 && (enum regexpcode) pbufp->buffer[0] == begbuf
+ && range > 0)
+ {
+ if (startpos > 0)
+ return -1;
+ else
+ range = 1;
+ }
+
+ while (1)
+ {
+ /* If a fastmap is supplied, skip quickly over characters
+ that cannot possibly be the start of a match.
+ Note, however, that if the pattern can possibly match
+ the null string, we must test it at each starting point
+ so that we take the first null string we get. */
+
+ if (fastmap && startpos < total && pbufp->can_be_null != 1)
+ {
+ if (range > 0)
+ {
+ register int lim = 0;
+ register unsigned char *p;
+ int irange = range;
+ if (startpos < size1 && startpos + range >= size1)
+ lim = range - (size1 - startpos);
+
+ p = ((unsigned char *)
+ &(startpos >= size1 ? string2 - size1 : string1)[startpos]);
+
+ if (translate)
+ {
+ while (range > lim && !fastmap[translate[*p++]])
+ range--;
+ }
+ else
+ {
+ while (range > lim && !fastmap[*p++])
+ range--;
+ }
+ startpos += irange - range;
+ }
+ else
+ {
+ register unsigned char c;
+ if (startpos >= size1)
+ c = string2[startpos - size1];
+ else
+ c = string1[startpos];
+ c &= 0xff;
+ if (translate ? !fastmap[translate[c]] : !fastmap[c])
+ goto advance;
+ }
+ }
+
+ if (range >= 0 && startpos == total
+ && fastmap && pbufp->can_be_null == 0)
+ return -1;
+
+ val = re_match_2 (pbufp, string1, size1, string2, size2, startpos, regs, mstop);
+ if (0 <= val)
+ {
+ if (val == -2)
+ return -2;
+ return startpos;
+ }
+
+#ifdef C_ALLOCA
+ alloca (0);
+#endif /* C_ALLOCA */
+
+ advance:
+ if (!range) break;
+ if (range > 0) range--, startpos++; else range++, startpos--;
+ }
+ return -1;
+}
+
+#ifndef emacs /* emacs never uses this */
+int
+re_match (pbufp, string, size, pos, regs)
+ struct re_pattern_buffer *pbufp;
+ char *string;
+ int size, pos;
+ struct re_registers *regs;
+{
+ return re_match_2 (pbufp, 0, 0, string, size, pos, regs, size);
+}
+#endif /* emacs */
+
+/* Maximum size of failure stack. Beyond this, overflow is an error. */
+
+int re_max_failures = 2000;
+
+static int memcmp_translate();
+/* Match the pattern described by PBUFP
+ against data which is the virtual concatenation of STRING1 and STRING2.
+ SIZE1 and SIZE2 are the sizes of the two data strings.
+ Start the match at position POS.
+ Do not consider matching past the position MSTOP.
+
+ If pbufp->fastmap is nonzero, then it had better be up to date.
+
+ The reason that the data to match are specified as two components
+ which are to be regarded as concatenated
+ is so this function can be used directly on the contents of an Emacs buffer.
+
+ -1 is returned if there is no match. -2 is returned if there is
+ an error (such as match stack overflow). Otherwise the value is the length
+ of the substring which was matched. */
+
+int
+re_match_2 (pbufp, string1, size1, string2, size2, pos, regs, mstop)
+ struct re_pattern_buffer *pbufp;
+ unsigned char *string1, *string2;
+ int size1, size2;
+ int pos;
+ struct re_registers *regs;
+ int mstop;
+{
+ register unsigned char *p = (unsigned char *) pbufp->buffer;
+ register unsigned char *pend = p + pbufp->used;
+ /* End of first string */
+ unsigned char *end1;
+ /* End of second string */
+ unsigned char *end2;
+ /* Pointer just past last char to consider matching */
+ unsigned char *end_match_1, *end_match_2;
+ register unsigned char *d, *dend;
+ register int mcnt;
+ unsigned char *translate = (unsigned char *) pbufp->translate;
+
+ /* Failure point stack. Each place that can handle a failure further down the line
+ pushes a failure point on this stack. It consists of two char *'s.
+ The first one pushed is where to resume scanning the pattern;
+ the second pushed is where to resume scanning the strings.
+ If the latter is zero, the failure point is a "dummy".
+ If a failure happens and the innermost failure point is dormant,
+ it discards that failure point and tries the next one. */
+
+ unsigned char *initial_stack[2 * NFAILURES];
+ unsigned char **stackb = initial_stack;
+ unsigned char **stackp = stackb, **stacke = &stackb[2 * NFAILURES];
+
+ /* Information on the "contents" of registers.
+ These are pointers into the input strings; they record
+ just what was matched (on this attempt) by some part of the pattern.
+ The start_memory command stores the start of a register's contents
+ and the stop_memory command stores the end.
+
+ At that point, regstart[regnum] points to the first character in the register,
+ regend[regnum] points to the first character beyond the end of the register,
+ regstart_seg1[regnum] is true iff regstart[regnum] points into string1,
+ and regend_seg1[regnum] is true iff regend[regnum] points into string1. */
+
+ unsigned char *regstart[RE_NREGS];
+ unsigned char *regend[RE_NREGS];
+ unsigned char regstart_seg1[RE_NREGS], regend_seg1[RE_NREGS];
+
+ /* Set up pointers to ends of strings.
+ Don't allow the second string to be empty unless both are empty. */
+ if (!size2)
+ {
+ string2 = string1;
+ size2 = size1;
+ string1 = 0;
+ size1 = 0;
+ }
+ end1 = string1 + size1;
+ end2 = string2 + size2;
+
+ /* Compute where to stop matching, within the two strings */
+ if (mstop <= size1)
+ {
+ end_match_1 = string1 + mstop;
+ end_match_2 = string2;
+ }
+ else
+ {
+ end_match_1 = end1;
+ end_match_2 = string2 + mstop - size1;
+ }
+
+ /* Initialize \) text positions to -1
+ to mark ones that no \( or \) has been seen for. */
+
+ for (mcnt = 0; mcnt < (int) (sizeof (regend) / sizeof (*regend)); mcnt++)
+ regend[mcnt] = (unsigned char *) -1;
+
+ /* `p' scans through the pattern as `d' scans through the data.
+ `dend' is the end of the input string that `d' points within.
+ `d' is advanced into the following input string whenever necessary,
+ but this happens before fetching;
+ therefore, at the beginning of the loop,
+ `d' can be pointing at the end of a string,
+ but it cannot equal string2. */
+
+ if (pos <= size1)
+ d = string1 + pos, dend = end_match_1;
+ else
+ d = string2 + pos - size1, dend = end_match_2;
+
+/* Write PREFETCH; just before fetching a character with *d. */
+#define PREFETCH \
+ while (d == dend) \
+ { if (dend == end_match_2) goto fail; /* end of string2 => failure */ \
+ d = string2; /* end of string1 => advance to string2. */ \
+ dend = end_match_2; }
+
+ /* This loop loops over pattern commands.
+ It exits by returning from the function if match is complete,
+ or it drops through if match fails at this starting point in the input data. */
+
+ while (1)
+ {
+ if (p == pend)
+ /* End of pattern means we have succeeded! */
+ {
+ /* If caller wants register contents data back, convert it to indices */
+ if (regs)
+ {
+ regs->start[0] = pos;
+ if (dend == end_match_1)
+ regs->end[0] = d - string1;
+ else
+ regs->end[0] = d - string2 + size1;
+ for (mcnt = 1; mcnt < RE_NREGS; mcnt++)
+ {
+ if (regend[mcnt] == (unsigned char *) -1)
+ {
+ regs->start[mcnt] = -1;
+ regs->end[mcnt] = -1;
+ continue;
+ }
+ if (regstart_seg1[mcnt])
+ regs->start[mcnt] = regstart[mcnt] - string1;
+ else
+ regs->start[mcnt] = regstart[mcnt] - string2 + size1;
+ if (regend_seg1[mcnt])
+ regs->end[mcnt] = regend[mcnt] - string1;
+ else
+ regs->end[mcnt] = regend[mcnt] - string2 + size1;
+ }
+ }
+ if (dend == end_match_1)
+ return (d - string1 - pos);
+ else
+ return d - string2 + size1 - pos;
+ }
+
+ /* Otherwise match next pattern command */
+#ifdef SWITCH_ENUM_BUG
+ switch ((int) ((enum regexpcode) *p++))
+#else
+ switch ((enum regexpcode) *p++)
+#endif
+ {
+
+ /* \( is represented by a start_memory, \) by a stop_memory.
+ Both of those commands contain a "register number" argument.
+ The text matched within the \( and \) is recorded under that number.
+ Then, \<digit> turns into a `duplicate' command which
+ is followed by the numeric value of <digit> as the register number. */
+
+ case start_memory:
+ regstart[*p] = d;
+ regstart_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case stop_memory:
+ regend[*p] = d;
+ regend_seg1[*p++] = (dend == end_match_1);
+ break;
+
+ case duplicate:
+ {
+ int regno = *p++; /* Get which register to match against */
+ register unsigned char *d2, *dend2;
+
+ d2 = regstart[regno];
+ dend2 = ((regstart_seg1[regno] == regend_seg1[regno])
+ ? regend[regno] : end_match_1);
+ while (1)
+ {
+ /* Advance to next segment in register contents, if necessary */
+ while (d2 == dend2)
+ {
+ if (dend2 == end_match_2) break;
+ if (dend2 == regend[regno]) break;
+ d2 = string2, dend2 = regend[regno]; /* end of string1 => advance to string2. */
+ }
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* Advance to next segment in data being matched, if necessary */
+ PREFETCH;
+
+ /* mcnt gets # consecutive chars to compare */
+ mcnt = dend - d;
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+ /* Compare that many; failure if mismatch, else skip them. */
+ if (translate ? memcmp_translate (d, d2, mcnt, translate) : memcmp (d, d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
+ }
+ }
+ break;
+
+ case anychar:
+ /* fetch a data character */
+ PREFETCH;
+ /* Match anything but a newline. */
+ if ((translate ? translate[*d++] : *d++) == '\n')
+ goto fail;
+ break;
+
+ case charset:
+ case charset_not:
+ {
+ /* Nonzero for charset_not */
+ int not = 0;
+ register int c;
+ if (*(p - 1) == (unsigned char) charset_not)
+ not = 1;
+
+ /* fetch a data character */
+ PREFETCH;
+
+ if (translate)
+ c = translate [*d];
+ else
+ c = *d;
+
+ if (c < *p * BYTEWIDTH
+ && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+
+ p += 1 + *p;
+
+ if (!not) goto fail;
+ d++;
+ break;
+ }
+
+ case begline:
+ if (d == string1 || d[-1] == '\n')
+ break;
+ goto fail;
+
+ case endline:
+ if (d == end2
+ || (d == end1 ? (size2 == 0 || *string2 == '\n') : *d == '\n'))
+ break;
+ goto fail;
+
+ /* "or" constructs ("|") are handled by starting each alternative
+ with an on_failure_jump that points to the start of the next alternative.
+ Each alternative except the last ends with a jump to the joining point.
+ (Actually, each jump except for the last one really jumps
+ to the following jump, because tensioning the jumps is a hassle.) */
+
+ /* The start of a stupid repeat has an on_failure_jump that points
+ past the end of the repeat text.
+ This makes a failure point so that, on failure to match a repetition,
+ matching restarts past as many repetitions have been found
+ with no way to fail and look for another one. */
+
+ /* A smart repeat is similar but loops back to the on_failure_jump
+ so that each repetition makes another failure point. */
+
+ case on_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx;
+ if (stacke - stackb > re_max_failures * 2)
+ return -2;
+ stackx = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ *stackp++ = mcnt + p;
+ *stackp++ = d;
+ break;
+
+ /* The end of a smart repeat has an maybe_finalize_jump back.
+ Change it either to a finalize_jump or an ordinary jump. */
+
+ case maybe_finalize_jump:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p++;
+ {
+ register unsigned char *p2 = p;
+ /* Compare what follows with the begining of the repeat.
+ If we can establish that there is nothing that they would
+ both match, we can change to finalize_jump */
+ while (p2 != pend
+ && (*p2 == (unsigned char) stop_memory
+ || *p2 == (unsigned char) start_memory))
+ p2++;
+ if (p2 == pend)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (*p2 == (unsigned char) exactn
+ || *p2 == (unsigned char) endline)
+ {
+ register int c = *p2 == (unsigned char) endline ? '\n' : p2[2];
+ register unsigned char *p1 = p + mcnt;
+ /* p1[0] ... p1[2] are an on_failure_jump.
+ Examine what follows that */
+ if (p1[3] == (unsigned char) exactn && p1[5] != c)
+ p[-3] = (unsigned char) finalize_jump;
+ else if (p1[3] == (unsigned char) charset
+ || p1[3] == (unsigned char) charset_not)
+ {
+ int not = p1[3] == (unsigned char) charset_not;
+ if (c < p1[4] * BYTEWIDTH
+ && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
+ not = !not;
+ /* not is 1 if c would match */
+ /* That means it is not safe to finalize */
+ if (!not)
+ p[-3] = (unsigned char) finalize_jump;
+ }
+ }
+ }
+ p -= 2;
+ if (p[-1] != (unsigned char) finalize_jump)
+ {
+ p[-1] = (unsigned char) jump;
+ goto nofinalize;
+ }
+
+ /* The end of a stupid repeat has a finalize-jump
+ back to the start, where another failure point will be made
+ which will point after all the repetitions found so far. */
+
+ case finalize_jump:
+ stackp -= 2;
+
+ case jump:
+ nofinalize:
+ mcnt = *p++ & 0377;
+ mcnt += SIGN_EXTEND_CHAR (*(char *)p) << 8;
+ p += mcnt + 1; /* The 1 compensates for missing ++ above */
+ break;
+
+ case dummy_failure_jump:
+ if (stackp == stacke)
+ {
+ unsigned char **stackx
+ = (unsigned char **) alloca (2 * (stacke - stackb)
+ * sizeof (char *));
+ memcpy (stackx, stackb, (stacke - stackb) * sizeof (char *));
+ stackp = stackx + (stackp - stackb);
+ stacke = stackx + 2 * (stacke - stackb);
+ stackb = stackx;
+ }
+ *stackp++ = 0;
+ *stackp++ = 0;
+ goto nofinalize;
+
+ case wordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ break;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ break;
+ goto fail;
+
+ case notwordbound:
+ if (d == string1 /* Points to first char */
+ || d == end2 /* Points to end */
+ || (d == end1 && size2 == 0)) /* Points to end */
+ goto fail;
+ if ((SYNTAX (d[-1]) == Sword)
+ != (SYNTAX (d == end1 ? *string2 : *d) == Sword))
+ goto fail;
+ break;
+
+ case wordbeg:
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (* (d == end1 ? string2 : d)) != Sword) /* Next char not a letter */
+ goto fail;
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ break;
+ goto fail;
+
+ case wordend:
+ if (d == string1 /* Points to first char */
+ || SYNTAX (d[-1]) != Sword) /* prev char not letter */
+ goto fail;
+ if (d == end2 /* Points to end */
+ || (d == end1 && size2 == 0) /* Points to end */
+ || SYNTAX (d == end1 ? *string2 : *d) != Sword) /* Next char not a letter */
+ break;
+ goto fail;
+
+#ifdef emacs
+ case before_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ <= point)
+ goto fail;
+ break;
+
+ case at_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ == point)
+ goto fail;
+ break;
+
+ case after_dot:
+ if (((d - string2 <= (unsigned) size2)
+ ? d - bf_p2 : d - bf_p1)
+ >= point)
+ goto fail;
+ break;
+
+ case wordchar:
+ mcnt = (int) Sword;
+ goto matchsyntax;
+
+ case syntaxspec:
+ mcnt = *p++;
+ matchsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail;
+ break;
+
+ case notwordchar:
+ mcnt = (int) Sword;
+ goto matchnotsyntax;
+
+ case notsyntaxspec:
+ mcnt = *p++;
+ matchnotsyntax:
+ PREFETCH;
+ if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail;
+ break;
+#else
+ case wordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) == 0) goto fail;
+ break;
+
+ case notwordchar:
+ PREFETCH;
+ if (SYNTAX (*d++) != 0) goto fail;
+ break;
+#endif /* not emacs */
+
+ case begbuf:
+ if (d == string1) /* Note, d cannot equal string2 */
+ break; /* unless string1 == string2. */
+ goto fail;
+
+ case endbuf:
+ if (d == end2 || (d == end1 && size2 == 0))
+ break;
+ goto fail;
+
+ case exactn:
+ /* Match the next few pattern characters exactly.
+ mcnt is how many characters to match. */
+ mcnt = *p++;
+ if (translate)
+ {
+ do
+ {
+ PREFETCH;
+ if (translate[*d++] != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ else
+ {
+ do
+ {
+ PREFETCH;
+ if (*d++ != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ break;
+ case unused:
+ case before_dot:
+ case at_dot:
+ case after_dot:
+ case syntaxspec:
+ case notsyntaxspec:
+ default:
+ break;
+ }
+ continue; /* Successfully matched one pattern command; keep matching */
+
+ /* Jump here if any matching operation fails. */
+ fail:
+ if (stackp != stackb)
+ /* A restart point is known. Restart there and pop it. */
+ {
+ if (!stackp[-2])
+ { /* If innermost failure point is dormant, flush it and keep looking */
+ stackp -= 2;
+ goto fail;
+ }
+ d = *--stackp;
+ p = *--stackp;
+ if (d >= string1 && d <= end1)
+ dend = end_match_1;
+ }
+ else break; /* Matching at this starting point really fails! */
+ }
+ return -1; /* Failure to match */
+}
+
+static int
+memcmp_translate (s1, s2, len, translate)
+ unsigned char *s1, *s2;
+ register int len;
+ unsigned char *translate;
+{
+ register unsigned char *p1 = s1, *p2 = s2;
+ while (len)
+ {
+ if (translate [*p1++] != translate [*p2++]) return 1;
+ len--;
+ }
+ return 0;
+}
+
+/* Entry points compatible with bsd4.2 regex library */
+
+#ifndef emacs
+
+static struct re_pattern_buffer re_comp_buf;
+
+char *
+re_comp (s)
+ const char *s;
+{
+ if (!s)
+ {
+ if (!re_comp_buf.buffer)
+ return "No previous regular expression";
+ return 0;
+ }
+
+ if (!re_comp_buf.buffer)
+ {
+ if (!(re_comp_buf.buffer = (char *) malloc (200)))
+ return "Memory exhausted";
+ re_comp_buf.allocated = 200;
+ if (!(re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH)))
+ return "Memory exhausted";
+ }
+ return re_compile_pattern (s, strlen (s), &re_comp_buf);
+}
+
+int
+re_exec (s)
+ char *s;
+{
+ int len = strlen (s);
+ return 0 <= re_search (&re_comp_buf, s, len, 0, len, 0);
+}
+
+#endif /* emacs */
+
+#ifdef test
+
+#include <stdio.h>
+
+/* Indexed by a character, gives the upper case equivalent of the character */
+
+static char upcase[0400] =
+ { 000, 001, 002, 003, 004, 005, 006, 007,
+ 010, 011, 012, 013, 014, 015, 016, 017,
+ 020, 021, 022, 023, 024, 025, 026, 027,
+ 030, 031, 032, 033, 034, 035, 036, 037,
+ 040, 041, 042, 043, 044, 045, 046, 047,
+ 050, 051, 052, 053, 054, 055, 056, 057,
+ 060, 061, 062, 063, 064, 065, 066, 067,
+ 070, 071, 072, 073, 074, 075, 076, 077,
+ 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
+ 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
+ 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
+ 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
+ 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
+ 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
+ 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
+ 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
+ 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
+ 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
+ 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
+ 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
+ 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
+ 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
+ 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
+ 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
+ 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
+ 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
+ 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
+ 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
+ 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
+ };
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char pat[80];
+ struct re_pattern_buffer buf;
+ int i;
+ char c;
+ char fastmap[(1 << BYTEWIDTH)];
+
+ /* Allow a command argument to specify the style of syntax. */
+ if (argc > 1)
+ obscure_syntax = atoi (argv[1]);
+
+ buf.allocated = 40;
+ buf.buffer = (char *) malloc (buf.allocated);
+ buf.fastmap = fastmap;
+ buf.translate = upcase;
+
+ while (1)
+ {
+ gets (pat);
+
+ if (*pat)
+ {
+ re_compile_pattern (pat, strlen(pat), &buf);
+
+ for (i = 0; i < buf.used; i++)
+ printchar (buf.buffer[i]);
+
+ putchar_unfiltered ('\n');
+
+ printf_unfiltered ("%d allocated, %d used.\n", buf.allocated, buf.used);
+
+ re_compile_fastmap (&buf);
+ printf_unfiltered ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (fastmap[i]) printchar (i);
+ putchar_unfiltered ('\n');
+ }
+
+ gets (pat); /* Now read the string to match against */
+
+ i = re_match (&buf, pat, strlen (pat), 0, 0);
+ printf_unfiltered ("Match value %d.\n", i);
+ }
+}
+
+#ifdef NOTDEF
+print_buf (bufp)
+ struct re_pattern_buffer *bufp;
+{
+ int i;
+
+ printf_unfiltered ("buf is :\n----------------\n");
+ for (i = 0; i < bufp->used; i++)
+ printchar (bufp->buffer[i]);
+
+ printf_unfiltered ("\n%d allocated, %d used.\n", bufp->allocated, bufp->used);
+
+ printf_unfiltered ("Allowed by fastmap: ");
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->fastmap[i])
+ printchar (i);
+ printf_unfiltered ("\nAllowed by translate: ");
+ if (bufp->translate)
+ for (i = 0; i < (1 << BYTEWIDTH); i++)
+ if (bufp->translate[i])
+ printchar (i);
+ 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
+
+printchar (c)
+ char c;
+{
+ if (c < 041 || c >= 0177)
+ {
+ putchar_unfiltered ('\\');
+ putchar_unfiltered (((c >> 6) & 3) + '0');
+ putchar_unfiltered (((c >> 3) & 7) + '0');
+ putchar_unfiltered ((c & 7) + '0');
+ }
+ else
+ putchar_unfiltered (c);
+}
+
+error (string)
+ char *string;
+{
+ puts_unfiltered (string);
+ exit (1);
+}
+
+#endif /* test */
diff --git a/contrib/gdb/gdb/gnu-regex.h b/contrib/gdb/gdb/gnu-regex.h
new file mode 100644
index 0000000..7b1a4af
--- /dev/null
+++ b/contrib/gdb/gdb/gnu-regex.h
@@ -0,0 +1,181 @@
+/* Definitions for data structures callers pass the regex library.
+ Copyright (C) 1985, 1989 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Define number of parens for which we record the beginnings and ends.
+ This affects how much space the `struct re_registers' type takes up. */
+#ifndef RE_NREGS
+#define RE_NREGS 10
+#endif
+
+/* These bits are used in the obscure_syntax variable to choose among
+ alternative regexp syntaxes. */
+
+/* 1 means plain parentheses serve as grouping, and backslash
+ parentheses are needed for literal searching.
+ 0 means backslash-parentheses are grouping, and plain parentheses
+ are for literal searching. */
+#define RE_NO_BK_PARENS 1
+
+/* 1 means plain | serves as the "or"-operator, and \| is a literal.
+ 0 means \| serves as the "or"-operator, and | is a literal. */
+#define RE_NO_BK_VBAR 2
+
+/* 0 means plain + or ? serves as an operator, and \+, \? are literals.
+ 1 means \+, \? are operators and plain +, ? are literals. */
+#define RE_BK_PLUS_QM 4
+
+/* 1 means | binds tighter than ^ or $.
+ 0 means the contrary. */
+#define RE_TIGHT_VBAR 8
+
+/* 1 means treat \n as an _OR operator
+ 0 means treat it as a normal character */
+#define RE_NEWLINE_OR 16
+
+/* 0 means that a special characters (such as *, ^, and $) always have
+ their special meaning regardless of the surrounding context.
+ 1 means that special characters may act as normal characters in some
+ contexts. Specifically, this applies to:
+ ^ - only special at the beginning, or after ( or |
+ $ - only special at the end, or before ) or |
+ *, +, ? - only special when not after the beginning, (, or | */
+#define RE_CONTEXT_INDEP_OPS 32
+
+/* Now define combinations of bits for the standard possibilities. */
+#define RE_SYNTAX_AWK (RE_NO_BK_PARENS | RE_NO_BK_VBAR | RE_CONTEXT_INDEP_OPS)
+#define RE_SYNTAX_EGREP (RE_SYNTAX_AWK | RE_NEWLINE_OR)
+#define RE_SYNTAX_GREP (RE_BK_PLUS_QM | RE_NEWLINE_OR)
+#define RE_SYNTAX_EMACS 0
+
+/* This data structure is used to represent a compiled pattern. */
+
+struct re_pattern_buffer
+ {
+ char *buffer; /* Space holding the compiled pattern commands. */
+ int allocated; /* Size of space that buffer points to */
+ int used; /* Length of portion of buffer actually occupied */
+ char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
+ /* re_search uses the fastmap, if there is one,
+ to skip quickly over totally implausible characters */
+ char *translate; /* Translate table to apply to all characters before comparing.
+ Or zero for no translation.
+ The translation is applied to a pattern when it is compiled
+ and to data when it is matched. */
+ char fastmap_accurate;
+ /* Set to zero when a new pattern is stored,
+ set to one when the fastmap is updated from it. */
+ char can_be_null; /* Set to one by compiling fastmap
+ if this pattern might match the null string.
+ It does not necessarily match the null string
+ in that case, but if this is zero, it cannot.
+ 2 as value means can match null string
+ but at end of range or before a character
+ listed in the fastmap. */
+ };
+
+/* Structure to store "register" contents data in.
+
+ Pass the address of such a structure as an argument to re_match, etc.,
+ if you want this information back.
+
+ start[i] and end[i] record the string matched by \( ... \) grouping i,
+ for i from 1 to RE_NREGS - 1.
+ start[0] and end[0] record the entire string matched. */
+
+struct re_registers
+ {
+ int start[RE_NREGS];
+ int end[RE_NREGS];
+ };
+
+/* These are the command codes that appear in compiled regular expressions, one per byte.
+ Some command codes are followed by argument bytes.
+ A command code can specify any interpretation whatever for its arguments.
+ Zero-bytes may appear in the compiled regular expression. */
+
+enum regexpcode
+ {
+ unused,
+ exactn, /* followed by one byte giving n, and then by n literal bytes */
+ begline, /* fails unless at beginning of line */
+ endline, /* fails unless at end of line */
+ jump, /* followed by two bytes giving relative address to jump to */
+ on_failure_jump, /* followed by two bytes giving relative address of place
+ to resume at in case of failure. */
+ finalize_jump, /* Throw away latest failure point and then jump to address. */
+ maybe_finalize_jump, /* Like jump but finalize if safe to do so.
+ This is used to jump back to the beginning
+ of a repeat. If the command that follows
+ this jump is clearly incompatible with the
+ one at the beginning of the repeat, such that
+ we can be sure that there is no use backtracking
+ out of repetitions already completed,
+ then we finalize. */
+ dummy_failure_jump, /* jump, and push a dummy failure point.
+ This failure point will be thrown away
+ if an attempt is made to use it for a failure.
+ A + construct makes this before the first repeat. */
+ anychar, /* matches any one character */
+ charset, /* matches any one char belonging to specified set.
+ First following byte is # bitmap bytes.
+ Then come bytes for a bit-map saying which chars are in.
+ Bits in each byte are ordered low-bit-first.
+ A character is in the set if its bit is 1.
+ A character too large to have a bit in the map
+ is automatically not in the set */
+ charset_not, /* similar but match any character that is NOT one of those specified */
+ start_memory, /* starts remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ stop_memory, /* stops remembering the text that is matched
+ and stores it in a memory register.
+ followed by one byte containing the register number.
+ Register numbers must be in the range 0 through NREGS. */
+ duplicate, /* match a duplicate of something remembered.
+ Followed by one byte containing the index of the memory register. */
+ before_dot, /* Succeeds if before dot */
+ at_dot, /* Succeeds if at dot */
+ after_dot, /* Succeeds if after dot */
+ begbuf, /* Succeeds if at beginning of buffer */
+ endbuf, /* Succeeds if at end of buffer */
+ wordchar, /* Matches any word-constituent character */
+ notwordchar, /* Matches any char that is not a word-constituent */
+ wordbeg, /* Succeeds if at word beginning */
+ wordend, /* Succeeds if at word end */
+ wordbound, /* Succeeds if at a word boundary */
+ notwordbound, /* Succeeds if not at a word boundary */
+ syntaxspec, /* Matches any character whose syntax is specified.
+ followed by a byte which contains a syntax code, Sword or such like */
+ notsyntaxspec /* Matches any character whose syntax differs from the specified. */
+ };
+
+extern char *re_compile_pattern ();
+/* Is this really advertised? */
+extern void re_compile_fastmap ();
+extern int re_search (), re_search_2 ();
+extern int re_match (), re_match_2 ();
+
+/* 4.2 bsd compatibility (yuck) */
+extern char *re_comp ();
+extern int re_exec ();
+
+#ifdef SYNTAX_TABLE
+extern char *re_syntax_table;
+#endif
+
+extern int re_set_syntax ();
diff --git a/contrib/gdb/gdb/go32-xdep.c b/contrib/gdb/gdb/go32-xdep.c
new file mode 100644
index 0000000..01c817a
--- /dev/null
+++ b/contrib/gdb/gdb/go32-xdep.c
@@ -0,0 +1,35 @@
+/* Host-dependent code for dos running GO32 for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+
+int
+sigsetmask (mask)
+ int mask;
+{
+ return 0;
+}
+
+void
+strlwr (str)
+ char *str;
+{
+ for (; *str; str++)
+ *str = tolower(*str);
+}
diff --git a/contrib/gdb/gdb/i386-stub.c b/contrib/gdb/gdb/i386-stub.c
new file mode 100644
index 0000000..ce53c48
--- /dev/null
+++ b/contrib/gdb/gdb/i386-stub.c
@@ -0,0 +1,915 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * Modified for 386 by Jim Kingdon, Cygnus Support.
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1.
+ *
+ * The external function exceptionHandler() is
+ * used to attach a specific handler to a specific 386 vector number.
+ * It should use the same privilege level it runs at. It should
+ * install it as an interrupt gate so that interrupts are masked
+ * while the handler runs.
+ * Also, need to assign exceptionHook and oldExceptionHook.
+ *
+ * Because gdb will sometimes write to the stack area to execute function
+ * calls, this program cannot rely on using the supervisor stack so it
+ * uses it's own stack area reserved in the int array remcomStack.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+typedef void (*ExceptionHook)(int); /* pointer to function with int parm */
+typedef void (*Function)(); /* pointer to a function */
+
+extern putDebugChar(); /* write a single character */
+extern getDebugChar(); /* read and return a single char */
+
+extern Function exceptionHandler(); /* assign an exception handler */
+extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 400
+
+static char initialized; /* boolean flag. != 0 means we've been initialized */
+
+int remote_debug;
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+
+void waitabit();
+
+static const char hexchars[]="0123456789abcdef";
+
+/* Number of bytes of registers. */
+#define NUMREGBYTES 64
+enum regnames {EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
+ PC /* also known as eip */,
+ PS /* also known as eflags */,
+ CS, SS, DS, ES, FS, GS};
+
+/*
+ * these should not be static cuz they can be used outside this module
+ */
+int registers[NUMREGBYTES/4];
+
+#define STACKSIZE 10000
+int remcomStack[STACKSIZE/sizeof(int)];
+static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+/*
+ * In many cases, the system will want to continue exception processing
+ * when a continue command is given.
+ * oldExceptionHook is a function to invoke in this case.
+ */
+
+static ExceptionHook oldExceptionHook;
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/* */
+
+extern void
+return_to_prog ();
+
+/* Restore the program's registers (including the stack pointer, which
+ means we get the right stack and don't have to worry about popping our
+ return address and any stack frames and so on) and return. */
+asm(".text");
+asm(".globl _return_to_prog");
+asm("_return_to_prog:");
+asm(" movw _registers+44, %ss");
+asm(" movl _registers+16, %esp");
+asm(" movl _registers+4, %ecx");
+asm(" movl _registers+8, %edx");
+asm(" movl _registers+12, %ebx");
+asm(" movl _registers+20, %ebp");
+asm(" movl _registers+24, %esi");
+asm(" movl _registers+28, %edi");
+asm(" movw _registers+48, %ds");
+asm(" movw _registers+52, %es");
+asm(" movw _registers+56, %fs");
+asm(" movw _registers+60, %gs");
+asm(" movl _registers+36, %eax");
+asm(" pushl %eax"); /* saved eflags */
+asm(" movl _registers+40, %eax");
+asm(" pushl %eax"); /* saved cs */
+asm(" movl _registers+32, %eax");
+asm(" pushl %eax"); /* saved eip */
+asm(" movl _registers, %eax");
+/* use iret to restore pc and flags together so
+ that trace flag works right. */
+asm(" iret");
+
+#define BREAKPOINT() asm(" int $3");
+
+/* Put the error code here just in case the user cares. */
+int gdb_i386errcode;
+/* Likewise, the vector number here (since GDB only gets the signal
+ number through the usual means, and that's not very specific). */
+int gdb_i386vector = -1;
+
+/* GDB stores segment registers in 32-bit words (that's just the way
+ m-i386v.h is written). So zero the appropriate areas in registers. */
+#define SAVE_REGISTERS1() \
+ asm ("movl %eax, _registers"); \
+ asm ("movl %ecx, _registers+4"); \
+ asm ("movl %edx, _registers+8"); \
+ asm ("movl %ebx, _registers+12"); \
+ asm ("movl %ebp, _registers+20"); \
+ asm ("movl %esi, _registers+24"); \
+ asm ("movl %edi, _registers+28"); \
+ asm ("movw $0, %ax"); \
+ asm ("movw %ds, _registers+48"); \
+ asm ("movw %ax, _registers+50"); \
+ asm ("movw %es, _registers+52"); \
+ asm ("movw %ax, _registers+54"); \
+ asm ("movw %fs, _registers+56"); \
+ asm ("movw %ax, _registers+58"); \
+ asm ("movw %gs, _registers+60"); \
+ asm ("movw %ax, _registers+62");
+#define SAVE_ERRCODE() \
+ asm ("popl %ebx"); \
+ asm ("movl %ebx, _gdb_i386errcode");
+#define SAVE_REGISTERS2() \
+ asm ("popl %ebx"); /* old eip */ \
+ asm ("movl %ebx, _registers+32"); \
+ asm ("popl %ebx"); /* old cs */ \
+ asm ("movl %ebx, _registers+40"); \
+ asm ("movw %ax, _registers+42"); \
+ asm ("popl %ebx"); /* old eflags */ \
+ asm ("movl %ebx, _registers+36"); \
+ /* Now that we've done the pops, we can save the stack pointer."); */ \
+ asm ("movw %ss, _registers+44"); \
+ asm ("movw %ax, _registers+46"); \
+ asm ("movl %esp, _registers+16");
+
+/* See if mem_fault_routine is set, if so just IRET to that address. */
+#define CHECK_FAULT() \
+ asm ("cmpl $0, _mem_fault_routine"); \
+ asm ("jne mem_fault");
+
+asm (".text");
+asm ("mem_fault:");
+/* OK to clobber temp registers; we're just going to end up in set_mem_err. */
+/* Pop error code from the stack and save it. */
+asm (" popl %eax");
+asm (" movl %eax, _gdb_i386errcode");
+
+asm (" popl %eax"); /* eip */
+/* We don't want to return there, we want to return to the function
+ pointed to by mem_fault_routine instead. */
+asm (" movl _mem_fault_routine, %eax");
+asm (" popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits). */
+asm (" popl %edx"); /* eflags */
+
+/* Remove this stack frame; when we do the iret, we will be going to
+ the start of a function, so we want the stack to look just like it
+ would after a "call" instruction. */
+asm (" leave");
+
+/* Push the stuff that iret wants. */
+asm (" pushl %edx"); /* eflags */
+asm (" pushl %ecx"); /* cs */
+asm (" pushl %eax"); /* eip */
+
+/* Zero mem_fault_routine. */
+asm (" movl $0, %eax");
+asm (" movl %eax, _mem_fault_routine");
+
+asm ("iret");
+
+#define CALL_HOOK() asm("call _remcomHandler");
+
+/* This function is called when a i386 exception occurs. It saves
+ * all the cpu regs in the _registers array, munges the stack a bit,
+ * and invokes an exception handler (remcom_handler).
+ *
+ * stack on entry: stack on exit:
+ * old eflags vector number
+ * old cs (zero-filled to 32 bits)
+ * old eip
+ *
+ */
+extern void _catchException3();
+asm(".text");
+asm(".globl __catchException3");
+asm("__catchException3:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $3");
+CALL_HOOK();
+
+/* Same thing for exception 1. */
+extern void _catchException1();
+asm(".text");
+asm(".globl __catchException1");
+asm("__catchException1:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $1");
+CALL_HOOK();
+
+/* Same thing for exception 0. */
+extern void _catchException0();
+asm(".text");
+asm(".globl __catchException0");
+asm("__catchException0:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $0");
+CALL_HOOK();
+
+/* Same thing for exception 4. */
+extern void _catchException4();
+asm(".text");
+asm(".globl __catchException4");
+asm("__catchException4:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $4");
+CALL_HOOK();
+
+/* Same thing for exception 5. */
+extern void _catchException5();
+asm(".text");
+asm(".globl __catchException5");
+asm("__catchException5:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $5");
+CALL_HOOK();
+
+/* Same thing for exception 6. */
+extern void _catchException6();
+asm(".text");
+asm(".globl __catchException6");
+asm("__catchException6:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $6");
+CALL_HOOK();
+
+/* Same thing for exception 7. */
+extern void _catchException7();
+asm(".text");
+asm(".globl __catchException7");
+asm("__catchException7:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $7");
+CALL_HOOK();
+
+/* Same thing for exception 8. */
+extern void _catchException8();
+asm(".text");
+asm(".globl __catchException8");
+asm("__catchException8:");
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $8");
+CALL_HOOK();
+
+/* Same thing for exception 9. */
+extern void _catchException9();
+asm(".text");
+asm(".globl __catchException9");
+asm("__catchException9:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $9");
+CALL_HOOK();
+
+/* Same thing for exception 10. */
+extern void _catchException10();
+asm(".text");
+asm(".globl __catchException10");
+asm("__catchException10:");
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $10");
+CALL_HOOK();
+
+/* Same thing for exception 12. */
+extern void _catchException12();
+asm(".text");
+asm(".globl __catchException12");
+asm("__catchException12:");
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $12");
+CALL_HOOK();
+
+/* Same thing for exception 16. */
+extern void _catchException16();
+asm(".text");
+asm(".globl __catchException16");
+asm("__catchException16:");
+SAVE_REGISTERS1();
+SAVE_REGISTERS2();
+asm ("pushl $16");
+CALL_HOOK();
+
+/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff. */
+
+/* Same thing for exception 13. */
+extern void _catchException13 ();
+asm (".text");
+asm (".globl __catchException13");
+asm ("__catchException13:");
+CHECK_FAULT();
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $13");
+CALL_HOOK();
+
+/* Same thing for exception 11. */
+extern void _catchException11 ();
+asm (".text");
+asm (".globl __catchException11");
+asm ("__catchException11:");
+CHECK_FAULT();
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $11");
+CALL_HOOK();
+
+/* Same thing for exception 14. */
+extern void _catchException14 ();
+asm (".text");
+asm (".globl __catchException14");
+asm ("__catchException14:");
+CHECK_FAULT();
+SAVE_REGISTERS1();
+SAVE_ERRCODE();
+SAVE_REGISTERS2();
+asm ("pushl $14");
+CALL_HOOK();
+
+/*
+ * remcomHandler is a front end for handle_exception. It moves the
+ * stack pointer into an area reserved for debugger use.
+ */
+asm("_remcomHandler:");
+asm(" popl %eax"); /* pop off return address */
+asm(" popl %eax"); /* get the exception number */
+asm(" movl _stackPtr, %esp"); /* move to remcom stack area */
+asm(" pushl %eax"); /* push exception onto stack */
+asm(" call _handle_exception"); /* this never returns */
+
+void _returnFromException()
+{
+ return_to_prog ();
+}
+
+int hex(ch)
+char ch;
+{
+ if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+ if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+ if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
+ return (-1);
+}
+
+
+/* scan for the sequence $<data>#<checksum> */
+void getpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ char ch;
+
+ do {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$');
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#') break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum += hex(getDebugChar() & 0x7f);
+ if ((remote_debug ) && (checksum != xmitcsum)) {
+ fprintf (stderr ,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum,xmitcsum,buffer);
+ }
+
+ if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */
+ else {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':') {
+ putDebugChar( buffer[0] );
+ putDebugChar( buffer[1] );
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ } while (checksum != xmitcsum);
+
+}
+
+/* send the packet in buffer. */
+
+
+void putpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ /* $<packet info>#<checksum>. */
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch=buffer[count]) {
+ if (! putDebugChar(ch)) return;
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum % 16]);
+
+ } while ((getDebugChar() & 0x7f) != '+');
+
+}
+
+char remcomInBuffer[BUFMAX];
+char remcomOutBuffer[BUFMAX];
+static short error;
+
+
+void debug_error(format, parm)
+char * format;
+char * parm;
+{
+ if (remote_debug) fprintf (stderr,format,parm);
+}
+
+/* Address of a routine to RTE to if we get a memory fault. */
+static void (*volatile mem_fault_routine)() = NULL;
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+static volatile int mem_err = 0;
+
+void
+set_mem_err ()
+{
+ mem_err = 1;
+}
+
+/* These are separate functions so that they are so short and sweet
+ that the compiler won't save any registers (if there is a fault
+ to mem_fault, they won't get restored, so there better not be any
+ saved). */
+int
+get_char (addr)
+ char *addr;
+{
+ return *addr;
+}
+
+void
+set_char (addr, val)
+ char *addr;
+ int val;
+{
+ *addr = val;
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+/* If MAY_FAULT is non-zero, then we should set mem_err in response to
+ a fault; if zero treat a fault like any other fault in the stub. */
+char* mem2hex(mem, buf, count, may_fault)
+char* mem;
+char* buf;
+int count;
+int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault)
+ mem_fault_routine = set_mem_err;
+ for (i=0;i<count;i++) {
+ ch = get_char (mem++);
+ if (may_fault && mem_err)
+ return (buf);
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ if (may_fault)
+ mem_fault_routine = NULL;
+ return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+char* hex2mem(buf, mem, count, may_fault)
+char* buf;
+char* mem;
+int count;
+int may_fault;
+{
+ int i;
+ unsigned char ch;
+
+ if (may_fault)
+ mem_fault_routine = set_mem_err;
+ for (i=0;i<count;i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ set_char (mem++, ch);
+ if (may_fault && mem_err)
+ return (mem);
+ }
+ if (may_fault)
+ mem_fault_routine = NULL;
+ return(mem);
+}
+
+/* this function takes the 386 exception vector and attempts to
+ translate this number into a unix compatible signal value */
+int computeSignal( exceptionVector )
+int exceptionVector;
+{
+ int sigval;
+ switch (exceptionVector) {
+ case 0 : sigval = 8; break; /* divide by zero */
+ case 1 : sigval = 5; break; /* debug exception */
+ case 3 : sigval = 5; break; /* breakpoint */
+ case 4 : sigval = 16; break; /* into instruction (overflow) */
+ case 5 : sigval = 16; break; /* bound instruction */
+ case 6 : sigval = 4; break; /* Invalid opcode */
+ case 7 : sigval = 8; break; /* coprocessor not available */
+ case 8 : sigval = 7; break; /* double fault */
+ case 9 : sigval = 11; break; /* coprocessor segment overrun */
+ case 10 : sigval = 11; break; /* Invalid TSS */
+ case 11 : sigval = 11; break; /* Segment not present */
+ case 12 : sigval = 11; break; /* stack exception */
+ case 13 : sigval = 11; break; /* general protection */
+ case 14 : sigval = 11; break; /* page fault */
+ case 16 : sigval = 7; break; /* coprocessor error */
+ default:
+ sigval = 7; /* "software generated"*/
+ }
+ return (sigval);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+int hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue >=0)
+ {
+ *intValue = (*intValue <<4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+void handle_exception(int exceptionVector)
+{
+ int sigval;
+ int addr, length;
+ char * ptr;
+ int newPC;
+
+ gdb_i386vector = exceptionVector;
+
+ if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
+ exceptionVector,
+ registers[ PS ],
+ registers[ PC ]);
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal( exceptionVector );
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+
+ putpacket(remcomOutBuffer);
+
+ while (1==1) {
+ error = 0;
+ remcomOutBuffer[0] = 0;
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0]) {
+ case '?' : remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+ break;
+ case 'd' : remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g' : /* return the value of the CPU registers */
+ mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES, 0);
+ break;
+ case 'G' : /* set the value of the CPU registers - return OK */
+ hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES, 0);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ case 'm' :
+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ {
+ ptr = 0;
+ mem_err = 0;
+ mem2hex((char*) addr, remcomOutBuffer, length, 1);
+ if (mem_err) {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ }
+ }
+
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E01");
+ debug_error("malformed read memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ case 'M' :
+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ if (*(ptr++) == ':')
+ {
+ mem_err = 0;
+ hex2mem(ptr, (char*) addr, length, 1);
+
+ if (mem_err) {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ } else {
+ strcpy(remcomOutBuffer,"OK");
+ }
+
+ ptr = 0;
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E02");
+ debug_error("malformed write memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ case 'c' :
+ case 's' :
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ registers[ PC ] = addr;
+
+ newPC = registers[ PC];
+
+ /* clear the trace bit */
+ registers[ PS ] &= 0xfffffeff;
+
+ /* set the trace bit if we're stepping */
+ if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x100;
+
+ /*
+ * If we found a match for the PC AND we are not returning
+ * as a result of a breakpoint (33),
+ * trace exception (9), nmi (31), jmp to
+ * the old exception handler as if this code never ran.
+ */
+#if 0
+ /* Don't really think we need this, except maybe for protection
+ exceptions. */
+ /*
+ * invoke the previous handler.
+ */
+ if (oldExceptionHook)
+ (*oldExceptionHook) (frame->exceptionVector);
+ newPC = registers[ PC ]; /* pc may have changed */
+#endif /* 0 */
+
+ _returnFromException(); /* this is a jump */
+
+ break;
+
+ /* kill the program */
+ case 'k' : /* do nothing */
+#if 0
+ /* Huh? This doesn't look like "nothing".
+ m68k-stub.c and sparc-stub.c don't have it. */
+ BREAKPOINT();
+#endif
+ break;
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+/* this function is used to set up exception handlers for tracing and
+ breakpoints */
+void set_debug_traps()
+{
+extern void remcomHandler();
+int exception;
+
+ stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+ exceptionHandler (0, _catchException0);
+ exceptionHandler (1, _catchException1);
+ exceptionHandler (3, _catchException3);
+ exceptionHandler (4, _catchException4);
+ exceptionHandler (5, _catchException5);
+ exceptionHandler (6, _catchException6);
+ exceptionHandler (7, _catchException7);
+ exceptionHandler (8, _catchException8);
+ exceptionHandler (9, _catchException9);
+ exceptionHandler (10, _catchException10);
+ exceptionHandler (11, _catchException11);
+ exceptionHandler (12, _catchException12);
+ exceptionHandler (13, _catchException13);
+ exceptionHandler (14, _catchException14);
+ exceptionHandler (16, _catchException16);
+
+ if (exceptionHook != remcomHandler)
+ {
+ oldExceptionHook = exceptionHook;
+ exceptionHook = remcomHandler;
+ }
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+ putDebugChar ('+');
+
+ initialized = 1;
+
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void breakpoint()
+{
+ if (initialized)
+#if 0
+ handle_exception(3);
+#else
+ BREAKPOINT();
+#endif
+ waitabit();
+}
+
+int waitlimit = 1000000;
+
+#if 0
+void
+bogon()
+{
+ waitabit();
+}
+#endif
+
+void
+waitabit()
+{
+ int i;
+ for (i = 0; i < waitlimit; i++) ;
+}
diff --git a/contrib/gdb/gdb/i386-tdep.c b/contrib/gdb/gdb/i386-tdep.c
new file mode 100644
index 0000000..47be4b3
--- /dev/null
+++ b/contrib/gdb/gdb/i386-tdep.c
@@ -0,0 +1,688 @@
+/* Intel 386 target-dependent stuff.
+ Copyright (C) 1988, 1989, 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "floatformat.h"
+#include "symtab.h"
+
+static long i386_get_frame_setup PARAMS ((CORE_ADDR));
+
+static void i386_follow_jump PARAMS ((void));
+
+static void codestream_read PARAMS ((unsigned char *, int));
+
+static void codestream_seek PARAMS ((CORE_ADDR));
+
+static unsigned char codestream_fill PARAMS ((int));
+
+/* Stdio style buffering was used to minimize calls to ptrace, but this
+ buffering did not take into account that the code section being accessed
+ may not be an even number of buffers long (even if the buffer is only
+ sizeof(int) long). In cases where the code section size happened to
+ be a non-integral number of buffers long, attempting to read the last
+ buffer would fail. Simply using target_read_memory and ignoring errors,
+ rather than read_memory, is not the correct solution, since legitimate
+ access errors would then be totally ignored. To properly handle this
+ situation and continue to use buffering would require that this code
+ be able to determine the minimum code section size granularity (not the
+ alignment of the section itself, since the actual failing case that
+ pointed out this problem had a section alignment of 4 but was not a
+ multiple of 4 bytes long), on a target by target basis, and then
+ adjust it's buffer size accordingly. This is messy, but potentially
+ feasible. It probably needs the bfd library's help and support. For
+ now, the buffer size is set to 1. (FIXME -fnf) */
+
+#define CODESTREAM_BUFSIZ 1 /* Was sizeof(int), see note above. */
+static CORE_ADDR codestream_next_addr;
+static CORE_ADDR codestream_addr;
+static unsigned char codestream_buf[CODESTREAM_BUFSIZ];
+static int codestream_off;
+static int codestream_cnt;
+
+#define codestream_tell() (codestream_addr + codestream_off)
+#define codestream_peek() (codestream_cnt == 0 ? \
+ codestream_fill(1): codestream_buf[codestream_off])
+#define codestream_get() (codestream_cnt-- == 0 ? \
+ codestream_fill(0) : codestream_buf[codestream_off++])
+
+static unsigned char
+codestream_fill (peek_flag)
+ int peek_flag;
+{
+ codestream_addr = codestream_next_addr;
+ codestream_next_addr += CODESTREAM_BUFSIZ;
+ codestream_off = 0;
+ codestream_cnt = CODESTREAM_BUFSIZ;
+ read_memory (codestream_addr, (char *) codestream_buf, CODESTREAM_BUFSIZ);
+
+ if (peek_flag)
+ return (codestream_peek());
+ else
+ return (codestream_get());
+}
+
+static void
+codestream_seek (place)
+ CORE_ADDR place;
+{
+ codestream_next_addr = place / CODESTREAM_BUFSIZ;
+ codestream_next_addr *= CODESTREAM_BUFSIZ;
+ codestream_cnt = 0;
+ codestream_fill (1);
+ while (codestream_tell() != place)
+ codestream_get ();
+}
+
+static void
+codestream_read (buf, count)
+ unsigned char *buf;
+ int count;
+{
+ unsigned char *p;
+ int i;
+ p = buf;
+ for (i = 0; i < count; i++)
+ *p++ = codestream_get ();
+}
+
+/* next instruction is a jump, move to target */
+
+static void
+i386_follow_jump ()
+{
+ unsigned char buf[4];
+ long delta;
+
+ int data16;
+ CORE_ADDR pos;
+
+ pos = codestream_tell ();
+
+ data16 = 0;
+ if (codestream_peek () == 0x66)
+ {
+ codestream_get ();
+ data16 = 1;
+ }
+
+ switch (codestream_get ())
+ {
+ case 0xe9:
+ /* relative jump: if data16 == 0, disp32, else disp16 */
+ if (data16)
+ {
+ codestream_read (buf, 2);
+ delta = extract_signed_integer (buf, 2);
+
+ /* include size of jmp inst (including the 0x66 prefix). */
+ pos += delta + 4;
+ }
+ else
+ {
+ codestream_read (buf, 4);
+ delta = extract_signed_integer (buf, 4);
+
+ pos += delta + 5;
+ }
+ break;
+ case 0xeb:
+ /* relative jump, disp8 (ignore data16) */
+ codestream_read (buf, 1);
+ /* Sign-extend it. */
+ delta = extract_signed_integer (buf, 1);
+
+ pos += delta + 2;
+ break;
+ }
+ codestream_seek (pos);
+}
+
+/*
+ * find & return amound a local space allocated, and advance codestream to
+ * first register push (if any)
+ *
+ * if entry sequence doesn't make sense, return -1, and leave
+ * codestream pointer random
+ */
+
+static long
+i386_get_frame_setup (pc)
+ CORE_ADDR pc;
+{
+ unsigned char op;
+
+ codestream_seek (pc);
+
+ i386_follow_jump ();
+
+ op = codestream_get ();
+
+ if (op == 0x58) /* popl %eax */
+ {
+ /*
+ * this function must start with
+ *
+ * popl %eax 0x58
+ * xchgl %eax, (%esp) 0x87 0x04 0x24
+ * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
+ *
+ * (the system 5 compiler puts out the second xchg
+ * inst, and the assembler doesn't try to optimize it,
+ * so the 'sib' form gets generated)
+ *
+ * this sequence is used to get the address of the return
+ * buffer for a function that returns a structure
+ */
+ int pos;
+ unsigned char buf[4];
+ static unsigned char proto1[3] = { 0x87,0x04,0x24 };
+ static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
+ pos = codestream_tell ();
+ codestream_read (buf, 4);
+ if (memcmp (buf, proto1, 3) == 0)
+ pos += 3;
+ else if (memcmp (buf, proto2, 4) == 0)
+ pos += 4;
+
+ codestream_seek (pos);
+ op = codestream_get (); /* update next opcode */
+ }
+
+ if (op == 0x55) /* pushl %ebp */
+ {
+ /* check for movl %esp, %ebp - can be written two ways */
+ switch (codestream_get ())
+ {
+ case 0x8b:
+ if (codestream_get () != 0xec)
+ return (-1);
+ break;
+ case 0x89:
+ if (codestream_get () != 0xe5)
+ return (-1);
+ break;
+ default:
+ return (-1);
+ }
+ /* check for stack adjustment
+ *
+ * subl $XXX, %esp
+ *
+ * note: you can't subtract a 16 bit immediate
+ * from a 32 bit reg, so we don't have to worry
+ * about a data16 prefix
+ */
+ op = codestream_peek ();
+ if (op == 0x83)
+ {
+ /* subl with 8 bit immed */
+ codestream_get ();
+ if (codestream_get () != 0xec)
+ /* Some instruction starting with 0x83 other than subl. */
+ {
+ codestream_seek (codestream_tell () - 2);
+ return 0;
+ }
+ /* subl with signed byte immediate
+ * (though it wouldn't make sense to be negative)
+ */
+ return (codestream_get());
+ }
+ else if (op == 0x81)
+ {
+ char buf[4];
+ /* Maybe it is subl with 32 bit immedediate. */
+ codestream_get();
+ if (codestream_get () != 0xec)
+ /* Some instruction starting with 0x81 other than subl. */
+ {
+ codestream_seek (codestream_tell () - 2);
+ return 0;
+ }
+ /* It is subl with 32 bit immediate. */
+ codestream_read ((unsigned char *)buf, 4);
+ return extract_signed_integer (buf, 4);
+ }
+ else
+ {
+ return (0);
+ }
+ }
+ else if (op == 0xc8)
+ {
+ char buf[2];
+ /* enter instruction: arg is 16 bit unsigned immed */
+ codestream_read ((unsigned char *)buf, 2);
+ codestream_get (); /* flush final byte of enter instruction */
+ return extract_unsigned_integer (buf, 2);
+ }
+ return (-1);
+}
+
+/* Return number of args passed to a frame.
+ Can return -1, meaning no way to tell. */
+
+int
+i386_frame_num_args (fi)
+ struct frame_info *fi;
+{
+#if 1
+ return -1;
+#else
+ /* This loses because not only might the compiler not be popping the
+ args right after the function call, it might be popping args from both
+ this call and a previous one, and we would say there are more args
+ than there really are. */
+
+ int retpc;
+ unsigned char op;
+ struct frame_info *pfi;
+
+ /* on the 386, the instruction following the call could be:
+ popl %ecx - one arg
+ addl $imm, %esp - imm/4 args; imm may be 8 or 32 bits
+ anything else - zero args */
+
+ int frameless;
+
+ FRAMELESS_FUNCTION_INVOCATION (fi, frameless);
+ if (frameless)
+ /* In the absence of a frame pointer, GDB doesn't get correct values
+ for nameless arguments. Return -1, so it doesn't print any
+ nameless arguments. */
+ return -1;
+
+ pfi = get_prev_frame_info (fi);
+ if (pfi == 0)
+ {
+ /* Note: this can happen if we are looking at the frame for
+ main, because FRAME_CHAIN_VALID won't let us go into
+ start. If we have debugging symbols, that's not really
+ a big deal; it just means it will only show as many arguments
+ to main as are declared. */
+ return -1;
+ }
+ else
+ {
+ retpc = pfi->pc;
+ op = read_memory_integer (retpc, 1);
+ if (op == 0x59)
+ /* pop %ecx */
+ return 1;
+ else if (op == 0x83)
+ {
+ op = read_memory_integer (retpc+1, 1);
+ if (op == 0xc4)
+ /* addl $<signed imm 8 bits>, %esp */
+ return (read_memory_integer (retpc+2,1)&0xff)/4;
+ else
+ return 0;
+ }
+ else if (op == 0x81)
+ { /* add with 32 bit immediate */
+ op = read_memory_integer (retpc+1, 1);
+ if (op == 0xc4)
+ /* addl $<imm 32>, %esp */
+ return read_memory_integer (retpc+2, 4) / 4;
+ else
+ return 0;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+#endif
+}
+
+/*
+ * parse the first few instructions of the function to see
+ * what registers were stored.
+ *
+ * We handle these cases:
+ *
+ * The startup sequence can be at the start of the function,
+ * or the function can start with a branch to startup code at the end.
+ *
+ * %ebp can be set up with either the 'enter' instruction, or
+ * 'pushl %ebp, movl %esp, %ebp' (enter is too slow to be useful,
+ * but was once used in the sys5 compiler)
+ *
+ * Local space is allocated just below the saved %ebp by either the
+ * 'enter' instruction, or by 'subl $<size>, %esp'. 'enter' has
+ * a 16 bit unsigned argument for space to allocate, and the
+ * 'addl' instruction could have either a signed byte, or
+ * 32 bit immediate.
+ *
+ * Next, the registers used by this function are pushed. In
+ * the sys5 compiler they will always be in the order: %edi, %esi, %ebx
+ * (and sometimes a harmless bug causes it to also save but not restore %eax);
+ * however, the code below is willing to see the pushes in any order,
+ * and will handle up to 8 of them.
+ *
+ * If the setup sequence is at the end of the function, then the
+ * next instruction will be a branch back to the start.
+ */
+
+void
+i386_frame_find_saved_regs (fip, fsrp)
+ struct frame_info *fip;
+ struct frame_saved_regs *fsrp;
+{
+ long locals;
+ unsigned char op;
+ CORE_ADDR dummy_bottom;
+ CORE_ADDR adr;
+ int i;
+
+ memset (fsrp, 0, sizeof *fsrp);
+
+ /* if frame is the end of a dummy, compute where the
+ * beginning would be
+ */
+ dummy_bottom = fip->frame - 4 - REGISTER_BYTES - CALL_DUMMY_LENGTH;
+
+ /* check if the PC is in the stack, in a dummy frame */
+ if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
+ {
+ /* all regs were saved by push_call_dummy () */
+ adr = fip->frame;
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ adr -= REGISTER_RAW_SIZE (i);
+ fsrp->regs[i] = adr;
+ }
+ return;
+ }
+
+ locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
+
+ if (locals >= 0)
+ {
+ adr = fip->frame - 4 - locals;
+ for (i = 0; i < 8; i++)
+ {
+ 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;
+ }
+ }
+
+ fsrp->regs[PC_REGNUM] = fip->frame + 4;
+ fsrp->regs[FP_REGNUM] = fip->frame;
+}
+
+/* return pc of first real instruction */
+
+int
+i386_skip_prologue (pc)
+ int 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);
+
+ /* found valid frame setup - codestream now points to
+ * start of push instructions for saving registers
+ */
+
+ /* skip over register saves */
+ for (i = 0; i < 8; i++)
+ {
+ op = codestream_peek ();
+ /* break if not pushl inst */
+ if (op < 0x50 || op > 0x57)
+ 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 ();
+
+ return (codestream_tell ());
+}
+
+void
+i386_push_dummy_frame ()
+{
+ CORE_ADDR sp = read_register (SP_REGNUM);
+ int regnum;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ sp = push_word (sp, read_register (PC_REGNUM));
+ sp = push_word (sp, read_register (FP_REGNUM));
+ write_register (FP_REGNUM, sp);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ read_register_gen (regnum, regbuf);
+ sp = push_bytes (sp, regbuf, REGISTER_RAW_SIZE (regnum));
+ }
+ write_register (SP_REGNUM, sp);
+}
+
+void
+i386_pop_frame ()
+{
+ struct frame_info *frame = get_current_frame ();
+ CORE_ADDR fp;
+ int regnum;
+ struct frame_saved_regs fsr;
+ char regbuf[MAX_REGISTER_RAW_SIZE];
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &fsr);
+ for (regnum = 0; regnum < NUM_REGS; regnum++)
+ {
+ CORE_ADDR adr;
+ adr = fsr.regs[regnum];
+ if (adr)
+ {
+ read_memory (adr, regbuf, REGISTER_RAW_SIZE (regnum));
+ write_register_bytes (REGISTER_BYTE (regnum), regbuf,
+ REGISTER_RAW_SIZE (regnum));
+ }
+ }
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
+ write_register (SP_REGNUM, fp + 8);
+ flush_cached_frames ();
+}
+
+#ifdef GET_LONGJMP_TARGET
+
+/* Figure out where the longjmp will land. Slurp the args out of the stack.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
+ This routine returns true on success. */
+
+int
+get_longjmp_target(pc)
+ CORE_ADDR *pc;
+{
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ CORE_ADDR sp, jb_addr;
+
+ sp = read_register (SP_REGNUM);
+
+ if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
+ buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ return 1;
+}
+
+#endif /* GET_LONGJMP_TARGET */
+
+void
+i386_extract_return_value(type, regbuf, valbuf)
+ struct type *type;
+ char regbuf[REGISTER_BYTES];
+ char *valbuf;
+{
+/* On AIX, floating point values are returned in floating point registers. */
+#ifdef I386_AIX_TARGET
+ if (TYPE_CODE_FLT == TYPE_CODE(type))
+ {
+ double d;
+ /* 387 %st(0), gcc uses this */
+ floatformat_to_double (&floatformat_i387_ext,
+ &regbuf[REGISTER_BYTE(FP0_REGNUM)],
+ &d);
+ store_floating (valbuf, TYPE_LENGTH (type), d);
+ }
+ else
+#endif /* I386_AIX_TARGET */
+ {
+ memcpy (valbuf, regbuf, TYPE_LENGTH (type));
+ }
+}
+
+#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)
+ struct frame_info *frame;
+{
+ CORE_ADDR saved_pc_offset = 4;
+ char *name = NULL;
+
+ find_pc_partial_function (frame->pc, &name, NULL, 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 */
+
+
+
+/* Stuff for WIN32 PE style DLL's but is pretty generic really. */
+
+CORE_ADDR
+skip_trampoline_code (pc, name)
+ CORE_ADDR pc;
+ char *name;
+{
+ if (pc && read_memory_unsigned_integer (pc, 2) == 0x25ff) /* jmp *(dest) */
+ {
+ unsigned long indirect = read_memory_unsigned_integer (pc+2, 4);
+ struct minimal_symbol *indsym =
+ indirect ? lookup_minimal_symbol_by_pc (indirect) : 0;
+ char *symname = indsym ? SYMBOL_NAME(indsym) : 0;
+
+ if (symname)
+ {
+ if (strncmp (symname,"__imp_", 6) == 0
+ || strncmp (symname,"_imp_", 5) == 0)
+ return name ? 1 : read_memory_unsigned_integer (indirect, 4);
+ }
+ }
+ return 0; /* not a trampoline */
+}
+
+void
+_initialize_i386_tdep ()
+{
+ tm_print_insn = print_insn_i386;
+}
diff --git a/contrib/gdb/gdb/i386aix-nat.c b/contrib/gdb/gdb/i386aix-nat.c
new file mode 100644
index 0000000..133109e
--- /dev/null
+++ b/contrib/gdb/gdb/i386aix-nat.c
@@ -0,0 +1,360 @@
+/* Intel 386 native support.
+ Copyright (C) 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include <stddef.h>
+#include <sys/ptrace.h>
+
+/* Does AIX define this in <errno.h>? */
+extern int errno;
+
+#ifndef NO_SYS_REG_H
+#include <sys/reg.h>
+#endif
+
+#include "floatformat.h"
+
+#include "target.h"
+
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ USP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+
+int
+i386_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+#if 0
+ /* this will be needed if fp registers are reinstated */
+ /* for now, you can look at them with 'info float'
+ * sys5 wont let you change them with ptrace anyway
+ */
+ if (regnum >= FP0_REGNUM && regnum <= FP7_REGNUM)
+ {
+ int ubase, fpstate;
+ struct user u;
+ ubase = blockend + 4 * (SS + 1) - KSTKSZ;
+ fpstate = ubase + ((char *)&u.u_fpstate - (char *)&u);
+ return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+ }
+ else
+#endif
+ return (blockend + 4 * regmap[regnum]);
+
+}
+
+/* The code below only work on the aix ps/2 (i386-ibm-aix) -
+ * mtranle@paris - Sat Apr 11 10:34:12 1992
+ */
+
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
+
+static
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = ((ep->status >> 11) & 7);
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> ((7 - fpreg) * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ i387_to_double ((char *)ep->regs[fpreg], (char *)&val);
+ printf_unfiltered (" %#g\n", val);
+ }
+}
+
+static struct env387 core_env387;
+
+void
+i386_float_info ()
+{
+ struct env387 fps;
+ int fpsaved = 0;
+ /* We need to reverse the order of the registers. Apparently AIX stores
+ the highest-numbered ones first. */
+ struct env387 fps_fixed;
+ int i;
+
+ if (inferior_pid)
+ {
+ char buf[10];
+ unsigned short status;
+
+ ptrace (PT_READ_FPR, inferior_pid, buf, offsetof(struct env387, status));
+ memcpy (&status, buf, sizeof (status));
+ fpsaved = status;
+ }
+ else
+ {
+ if ((fpsaved = core_env387.status) != 0)
+ memcpy(&fps, &core_env387, sizeof(fps));
+ }
+
+ if (fpsaved == 0)
+ {
+ printf_unfiltered ("no floating point status saved\n");
+ return;
+ }
+
+ if (inferior_pid)
+ {
+ int offset;
+ for (offset = 0; offset < sizeof(fps); offset += 10)
+ {
+ char buf[10];
+ ptrace (PT_READ_FPR, inferior_pid, buf, offset);
+ memcpy ((char *)&fps.control + offset, buf,
+ MIN(10, sizeof(fps) - offset));
+ }
+ }
+ fps_fixed = fps;
+ for (i = 0; i < 8; ++i)
+ memcpy (fps_fixed.regs[i], fps.regs[7 - i], 10);
+ print_387_status (0, &fps_fixed);
+}
+
+/* Fetch one register. */
+static void
+fetch_register (regno)
+ int regno;
+{
+ char buf[MAX_REGISTER_RAW_SIZE];
+ if (regno < FP0_REGNUM)
+ *(int *)buf = ptrace (PT_READ_GPR, inferior_pid,
+ PT_REG(regmap[regno]), 0, 0);
+ else
+ ptrace (PT_READ_FPR, inferior_pid, buf,
+ (regno - FP0_REGNUM)*10 + offsetof(struct env387, regs));
+ supply_register (regno, buf);
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ if (regno < 0)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ fetch_register (regno);
+ else
+ fetch_register (regno);
+}
+
+/* store one register */
+static void
+store_register (regno)
+ int regno;
+{
+ char buf[80];
+ extern char registers[];
+ errno = 0;
+ if (regno < FP0_REGNUM)
+ ptrace (PT_WRITE_GPR, inferior_pid, PT_REG(regmap[regno]),
+ *(int *) &registers[REGISTER_BYTE (regno)], 0);
+ else
+ ptrace (PT_WRITE_FPR, inferior_pid, &registers[REGISTER_BYTE (regno)],
+ (regno - FP0_REGNUM)*10 + offsetof(struct env387, regs));
+
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ if (regno < 0)
+ for (regno = 0; regno < NUM_REGS; regno++)
+ store_register (regno);
+ else
+ store_register (regno);
+}
+
+#ifndef CD_AX /* defined in sys/i386/coredump.h */
+# define CD_AX 0
+# define CD_BX 1
+# define CD_CX 2
+# define CD_DX 3
+# define CD_SI 4
+# define CD_DI 5
+# define CD_BP 6
+# define CD_SP 7
+# define CD_FL 8
+# define CD_IP 9
+# define CD_CS 10
+# define CD_DS 11
+# define CD_ES 12
+# define CD_FS 13
+# define CD_GS 14
+# define CD_SS 15
+#endif
+
+/*
+ * The order here in core_regmap[] has to be the same as in
+ * regmap[] above.
+ */
+static int core_regmap[] =
+{
+ CD_AX, CD_CX, CD_DX, CD_BX,
+ CD_SP, CD_BP, CD_SI, CD_DI,
+ CD_IP, CD_FL, CD_CS, CD_SS,
+ CD_DS, CD_ES, CD_FS, CD_GS,
+};
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned int reg_addr; /* ignored */
+{
+
+ if (which == 0)
+ {
+ /* Integer registers */
+
+#define cd_regs(n) ((int *)core_reg_sect)[n]
+#define regs(n) *((int *) &registers[REGISTER_BYTE (n)])
+
+ int i;
+ for (i = 0; i < FP0_REGNUM; i++)
+ regs(i) = cd_regs(core_regmap[i]);
+ }
+ else if (which == 2)
+ {
+ /* Floating point registers */
+
+ if (core_reg_size >= sizeof (core_env387))
+ memcpy (&core_env387, core_reg_sect, core_reg_size);
+ else
+ fprintf_unfiltered (gdb_stderr, "Couldn't read float regs from core file\n");
+ }
+}
+
+
+/* Register that we are able to handle i386aix core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns i386aix_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_i386aix ()
+{
+ add_core_fns (&i386aix_core_fns);
+}
diff --git a/contrib/gdb/gdb/i386b-nat.c b/contrib/gdb/gdb/i386b-nat.c
new file mode 100644
index 0000000..d273cab
--- /dev/null
+++ b/contrib/gdb/gdb/i386b-nat.c
@@ -0,0 +1,284 @@
+/* Native-dependent code for BSD Unix running on i386's, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+#ifdef FETCH_INFERIOR_REGISTERS
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+#include "inferior.h"
+
+void
+fetch_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+
+ ptrace (PT_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+ memcpy (&registers[REGISTER_BYTE (0)], &inferior_registers, 4*NUM_REGS);
+ registers_fetched ();
+}
+
+void
+store_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+
+ memcpy (&inferior_registers, &registers[REGISTER_BYTE (0)], 4*NUM_REGS);
+ ptrace (PT_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+}
+
+struct md_core {
+ struct reg intreg;
+ struct fpreg freg;
+};
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned int ignore;
+{
+ struct md_core *core_reg = (struct md_core *)core_reg_sect;
+
+ /* integer registers */
+ memcpy(&registers[REGISTER_BYTE (0)], &core_reg->intreg,
+ sizeof(struct reg));
+ /* floating point registers */
+ /* XXX */
+}
+
+#else
+
+#include <machine/reg.h>
+
+/* this table must line up with REGISTER_NAMES in tm-i386.h */
+/* symbols like 'tEAX' come from <machine/reg.h> */
+static int tregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ 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
+};
+#else /* No sEAX */
+
+/* FreeBSD has decided to collapse the s* and t* symbols. So if the s*
+ ones aren't around, use the t* ones for sregmap too. */
+
+static int sregmap[] =
+{
+ tEAX, tECX, tEDX, tEBX,
+ tESP, tEBP, tESI, tEDI,
+ tEIP, tEFLAGS, tCS, tSS
+};
+#endif /* No sEAX */
+
+/* blockend is the value of u.u_ar0, and points to the
+ place where ES is stored. */
+
+int
+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. */
+
+ if (blockend < 0x1fcc)
+ return (blockend + 4 * tregmap[regnum]);
+ else
+ return (blockend + 4 * sregmap[regnum]);
+}
+
+#endif /* !FETCH_INFERIOR_REGISTERS */
+
+#ifdef FLOAT_INFO
+#include "language.h" /* for local_hex_string */
+#include "floatformat.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <a.out.h>
+
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/uio.h>
+#define curpcb Xcurpcb /* XXX avoid leaking declaration from pcb.h */
+#include <sys/user.h>
+#undef curpcb
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/ptrace.h>
+
+extern void print_387_control_word (); /* i387-tdep.h */
+extern void print_387_status_word ();
+
+#define fpstate save87
+#define U_FPSTATE(u) u.u_pcb.pcb_savefpu
+
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
+
+static void
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("u: ");
+ print_387_status_word ((unsigned int)status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word ((unsigned int)ep->status);
+ }
+
+ print_387_control_word ((unsigned int)ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = (ep->status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ floatformat_to_double(&floatformat_i387_ext, (char *) ep->regs[fpreg],
+ &val);
+ printf_unfiltered (" %g\n", val);
+ }
+}
+
+i386_float_info ()
+{
+ struct user u; /* just for address computations */
+ int i;
+ /* fpstate defined in <sys/user.h> */
+ struct fpstate *fpstatep;
+ char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
+ unsigned int uaddr;
+ char fpvalid;
+ unsigned int rounded_addr;
+ unsigned int rounded_size;
+ /*extern int corechan;*/
+ int skip;
+ extern int inferior_pid;
+
+ uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+ if (inferior_pid)
+ {
+ int *ip;
+
+ rounded_addr = uaddr & -sizeof (int);
+ rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
+ sizeof (int) - 1) / sizeof (int);
+ skip = uaddr - rounded_addr;
+
+ ip = (int *)buf;
+ for (i = 0; i < rounded_size; i++)
+ {
+ *ip++ = ptrace (PT_READ_U, inferior_pid, (caddr_t)rounded_addr, 0);
+ rounded_addr += sizeof (int);
+ }
+ }
+ else
+ {
+ printf("float info: can't do a core file (yet)\n");
+ return;
+#if 0
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror_with_name ("seek on core file");
+ if (myread (corechan, buf, sizeof (struct fpstate)) < 0)
+ perror_with_name ("read from core file");
+ skip = 0;
+#endif
+ }
+
+ print_387_status (0, (struct env387 *)buf);
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#endif
diff --git a/contrib/gdb/gdb/i386gnu-nat.c b/contrib/gdb/gdb/i386gnu-nat.c
new file mode 100644
index 0000000..63c3bd0
--- /dev/null
+++ b/contrib/gdb/gdb/i386gnu-nat.c
@@ -0,0 +1,348 @@
+/* Low level interface to I386 running the GNU Hurd
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "floatformat.h"
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+#include "gnu-nat.h"
+
+/* Hmmm... Should this not be here?
+ * Now for i386_float_info() target_has_execution
+ */
+#include <target.h>
+
+/* @@@ Should move print_387_status() to i387-tdep.c */
+extern void print_387_control_word (); /* i387-tdep.h */
+extern void print_387_status_word ();
+
+/* Find offsets to thread states at compile time.
+ * If your compiler does not grok this, calculate offsets
+ * offsets yourself and use them (or get a compatible compiler :-)
+ */
+
+#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
+
+/* at reg_offset[i] is the offset to the i386_thread_state
+ * location where the gdb registers[i] is stored.
+ */
+
+static int reg_offset[] =
+{
+ REG_OFFSET(eax), REG_OFFSET(ecx), REG_OFFSET(edx), REG_OFFSET(ebx),
+ REG_OFFSET(uesp), REG_OFFSET(ebp), REG_OFFSET(esi), REG_OFFSET(edi),
+ REG_OFFSET(eip), REG_OFFSET(efl), REG_OFFSET(cs), REG_OFFSET(ss),
+ REG_OFFSET(ds), REG_OFFSET(es), REG_OFFSET(fs), REG_OFFSET(gs)
+};
+
+#define REG_ADDR(state,regnum) ((char *)(state)+reg_offset[regnum])
+
+/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
+ * Caller knows that the regs handled in one transaction are of same size.
+ */
+#define FETCH_REGS(state, regnum, count) \
+ memcpy (&registers[REGISTER_BYTE (regnum)], \
+ REG_ADDR (state, regnum), \
+ count * REGISTER_RAW_SIZE (regnum))
+
+/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
+#define STORE_REGS(state, regnum, count) \
+ memcpy (REG_ADDR (state, regnum), \
+ &registers[REGISTER_BYTE (regnum)], \
+ count * REGISTER_RAW_SIZE (regnum))
+
+/*
+ * Fetch inferiors registers for gdb.
+ * REG specifies which (as gdb views it) register, -1 for all.
+ */
+void
+gnu_fetch_registers (int reg)
+{
+ thread_state_t state;
+ struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
+
+ if (!thread)
+ error ("fetch inferior registers: %d: Invalid thread", inferior_pid);
+
+ state = proc_get_state (thread, 0);
+
+ if (! state)
+ warning ("Couldn't fetch register %s.", reg_names[reg]);
+ else if (reg >= 0)
+ {
+ proc_debug (thread, "fetching register: %s", reg_names[reg]);
+ supply_register (reg, REG_ADDR(state, reg));
+ thread->fetched_regs |= (1 << reg);
+ }
+ else
+ {
+ proc_debug (thread, "fetching all registers");
+ for (reg = 0; reg < NUM_REGS; reg++)
+ supply_register (reg, REG_ADDR(state, reg));
+ thread->fetched_regs = ~0;
+ }
+}
+
+/* Store our register values back into the inferior.
+ * If REG is -1, do this for all registers.
+ * Otherwise, REG specifies which register
+ *
+ * On mach3 all registers are always saved in one call.
+ */
+void
+gnu_store_registers (reg)
+ int reg;
+{
+ int was_aborted, was_valid;
+ thread_state_t state;
+ thread_state_data_t old_state;
+ struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
+
+ if (! thread)
+ error ("store inferior registers: %d: Invalid thread", inferior_pid);
+
+ proc_debug (thread, "storing register %s.", reg_names[reg]);
+
+ was_aborted = thread->aborted;
+ was_valid = thread->state_valid;
+ if (! was_aborted && was_valid)
+ bcopy (&thread->state, &old_state, sizeof (old_state));
+
+ state = proc_get_state (thread, 1);
+
+ if (! state)
+ warning ("Couldn't store register %s.", reg_names[reg]);
+ else
+ {
+ if (! was_aborted && was_valid)
+ /* See which registers have changed after aborting the thread. */
+ {
+ int check_reg;
+ for (check_reg = 0; check_reg < NUM_REGS; check_reg++)
+ if ((thread->fetched_regs & (1 << check_reg))
+ && bcmp (REG_ADDR (&old_state, check_reg),
+ REG_ADDR (state, check_reg),
+ REGISTER_RAW_SIZE (check_reg)))
+ /* Register CHECK_REG has changed! Ack! */
+ {
+ warning ("Register %s changed after thread was aborted.",
+ reg_names [check_reg]);
+ if (reg >= 0 && reg != check_reg)
+ /* Update gdb's copy of the register. */
+ supply_register (check_reg, REG_ADDR (state, check_reg));
+ else
+ warning ("... also writing this register! Suspicious...");
+ }
+ }
+
+ if (reg >= 0)
+ {
+ proc_debug (thread, "storing register: %s", reg_names[reg]);
+ STORE_REGS (state, reg, 1);
+ }
+ else
+ {
+ proc_debug (thread, "storing all registers");
+ for (reg = 0; reg < NUM_REGS; reg++)
+ STORE_REGS (state, reg, 1);
+ }
+ }
+}
+
+/* jtv@hut.fi: I copied and modified this 387 code from
+ * gdb/i386-xdep.c. Modifications for Mach 3.0.
+ *
+ * i387 status dumper. See also i387-tdep.c
+ */
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
+/* This routine is machine independent?
+ * Should move it to i387-tdep.c but you need to export struct env387
+ */
+static
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = (ep->status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ floatformat_to_double (&floatformat_i387_ext, (char *)ep->regs[fpreg],
+ &val);
+ printf_unfiltered (" %g\n", val);
+ }
+ if (ep->r0)
+ printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string(ep->r0));
+ if (ep->r1)
+ printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string(ep->r1));
+ if (ep->r2)
+ printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string(ep->r2));
+ if (ep->r3)
+ printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string(ep->r3));
+}
+
+/*
+ * values that go into fp_kind (from <i386/fpreg.h>)
+ */
+#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
+#define FP_SW 1 /* no fp chip, using software emulator */
+#define FP_HW 2 /* chip present bit */
+#define FP_287 2 /* 80287 chip present */
+#define FP_387 3 /* 80387 chip present */
+
+typedef struct fpstate {
+#if 1
+ unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
+#else
+ struct env387 state; /* Actually this */
+#endif
+ int status; /* Duplicate status */
+} *fpstate_t;
+
+/* Mach 3 specific routines.
+ */
+static int
+get_i387_state (fstate)
+ struct fpstate *fstate;
+{
+ error_t err;
+ thread_state_data_t state;
+ unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
+ struct i386_float_state *fsp;
+ struct proc *thread = inf_tid_to_thread (current_inferior, inferior_pid);
+
+ if (!thread)
+ error ("get_i387_state: Invalid thread");
+
+ proc_abort (thread, 0); /* Make sure THREAD's in a reasonable state. */
+
+ err = thread_get_state (thread->port, i386_FLOAT_STATE, state, &fsCnt);
+ if (err)
+ {
+ warning ("Can not get live floating point state: %s",
+ mach_error_string (err));
+ return 0;
+ }
+
+ fsp = (struct i386_float_state *)state;
+ /* The 387 chip (also 486 counts) or a software emulator? */
+ if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
+ return 0;
+
+ /* Clear the target then copy thread's float state there.
+ Make a copy of the status word, for some reason?
+ */
+ memset (fstate, 0, sizeof (struct fpstate));
+
+ fstate->status = fsp->exc_status;
+
+ memcpy (fstate->state, (char *)&fsp->hw_state, FP_STATE_BYTES);
+
+ return 1;
+}
+
+/*
+ * This is called by "info float" command
+ */
+void
+i386_mach3_float_info()
+{
+ char buf [sizeof (struct fpstate) + 2 * sizeof (int)];
+ int valid = 0;
+ fpstate_t fps;
+
+ if (target_has_execution)
+ valid = get_i387_state (buf);
+
+ if (!valid)
+ {
+ warning ("no floating point status saved");
+ return;
+ }
+
+ fps = (fpstate_t) buf;
+
+ print_387_status (fps->status, (struct env387 *)fps->state);
+}
diff --git a/contrib/gdb/gdb/i386ly-tdep.c b/contrib/gdb/gdb/i386ly-tdep.c
new file mode 100644
index 0000000..dcb4584
--- /dev/null
+++ b/contrib/gdb/gdb/i386ly-tdep.c
@@ -0,0 +1,42 @@
+/* Target-dependent code for Intel 386 running LynxOS.
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "target.h"
+
+/* Return the PC of the caller from the call frame. Assumes the subr prologue
+ has already been executed, and the frame pointer setup. If this is the
+ outermost frame, we check to see if we are in a system call by examining the
+ previous instruction. If so, then the return PC is actually at SP+4 because
+ system calls use a different calling sequence. */
+
+CORE_ADDR
+i386lynx_saved_pc_after_call (frame)
+ struct frame_info *frame;
+{
+ char opcode[7];
+ static const unsigned char call_inst[] = {0x9a, 0, 0, 0, 0, 8, 0}; /* lcall 0x8,0x0 */
+
+ read_memory (frame->pc - 7, opcode, 7);
+ if (memcmp (opcode, call_inst, 7) == 0)
+ return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
+
+ return read_memory_integer (read_register (SP_REGNUM), 4);
+}
diff --git a/contrib/gdb/gdb/i386m3-nat.c b/contrib/gdb/gdb/i386m3-nat.c
new file mode 100644
index 0000000..bbaa022
--- /dev/null
+++ b/contrib/gdb/gdb/i386m3-nat.c
@@ -0,0 +1,421 @@
+/* Low level interface to I386 running mach 3.0.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "floatformat.h"
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+/* Hmmm... Should this not be here?
+ * Now for i386_float_info() target_has_execution
+ */
+#include <target.h>
+
+/* This mess is duplicated in bfd/i386mach3.h
+ *
+ * This is an ugly way to hack around the incorrect
+ * definition of UPAGES in i386/machparam.h.
+ *
+ * The definition should specify the size reserved
+ * for "struct user" in core files in PAGES,
+ * but instead it gives it in 512-byte core-clicks
+ * for i386 and i860.
+ */
+#include <sys/param.h>
+#if UPAGES == 16
+#define UAREA_SIZE ctob(UPAGES)
+#elif UPAGES == 2
+#define UAREA_SIZE (NBPG*UPAGES)
+#else
+FIXME!! UPAGES is neither 2 nor 16
+#endif
+
+/* @@@ Should move print_387_status() to i387-tdep.c */
+extern void print_387_control_word (); /* i387-tdep.h */
+extern void print_387_status_word ();
+
+#define private static
+
+
+/* Find offsets to thread states at compile time.
+ * If your compiler does not grok this, calculate offsets
+ * offsets yourself and use them (or get a compatible compiler :-)
+ */
+
+#define REG_OFFSET(reg) (int)(&((struct i386_thread_state *)0)->reg)
+
+/* at reg_offset[i] is the offset to the i386_thread_state
+ * location where the gdb registers[i] is stored.
+ */
+
+static int reg_offset[] =
+{
+ REG_OFFSET(eax), REG_OFFSET(ecx), REG_OFFSET(edx), REG_OFFSET(ebx),
+ REG_OFFSET(uesp), REG_OFFSET(ebp), REG_OFFSET(esi), REG_OFFSET(edi),
+ REG_OFFSET(eip), REG_OFFSET(efl), REG_OFFSET(cs), REG_OFFSET(ss),
+ REG_OFFSET(ds), REG_OFFSET(es), REG_OFFSET(fs), REG_OFFSET(gs)
+};
+
+#define REG_ADDRESS(state,regnum) ((char *)(state)+reg_offset[regnum])
+
+/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
+ * Caller knows that the regs handled in one transaction are of same size.
+ */
+#define FETCH_REGS(state, regnum, count) \
+ memcpy (&registers[REGISTER_BYTE (regnum)], \
+ REG_ADDRESS (state, regnum), \
+ count*REGISTER_SIZE)
+
+/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
+#define STORE_REGS(state, regnum, count) \
+ memcpy (REG_ADDRESS (state, regnum), \
+ &registers[REGISTER_BYTE (regnum)], \
+ count*REGISTER_SIZE)
+
+/*
+ * Fetch inferiors registers for gdb.
+ * REGNO specifies which (as gdb views it) register, -1 for all.
+ */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = i386_THREAD_STATE_COUNT;
+ int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("fetch inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ ret = thread_get_state (current_thread,
+ i386_THREAD_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ warning ("fetch_inferior_registers: %s ",
+ mach_error_string (ret));
+#if 0
+ /* It may be more effective to store validate all of them,
+ * since we fetched them all anyway
+ */
+ else if (regno != -1)
+ supply_register (regno, (char *)state+reg_offset[regno]);
+#endif
+ else
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ supply_register (index, (char *)state+reg_offset[index]);
+ }
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
+
+/* Store our register values back into the inferior.
+ * If REGNO is -1, do this for all registers.
+ * Otherwise, REGNO specifies which register
+ *
+ * On mach3 all registers are always saved in one call.
+ */
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = i386_THREAD_STATE_COUNT;
+ register int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("store inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ /* Fetch the state of the current thread */
+ ret = thread_get_state (current_thread,
+ i386_THREAD_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("store_inferior_registers (get): %s",
+ mach_error_string (ret));
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+ return;
+ }
+
+ /* move gdb's registers to thread's state
+ *
+ * Since we save all registers anyway, save the ones
+ * that gdb thinks are valid (e.g. ignore the regno
+ * parameter)
+ */
+#if 0
+ if (regno != -1)
+ STORE_REGS (state, regno, 1);
+ else
+#endif
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ STORE_REGS (state, index, 1);
+ }
+
+ /* Write gdb's current view of register to the thread
+ */
+ ret = thread_set_state (current_thread,
+ i386_THREAD_STATE,
+ state,
+ i386_THREAD_STATE_COUNT);
+
+ if (ret != KERN_SUCCESS)
+ warning ("store_inferior_registers (set): %s",
+ mach_error_string (ret));
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
+
+
+
+/* Return the address in the core dump or inferior of register REGNO.
+ * BLOCKEND should be the address of the end of the UPAGES area read
+ * in memory, but it's not?
+ *
+ * Currently our UX server dumps the whole thread state to the
+ * core file. If your UX does something else, adapt the routine
+ * below to return the offset to the given register.
+ *
+ * Called by core-aout.c(fetch_core_registers)
+ */
+
+unsigned int
+register_addr (regno, blockend)
+ int regno;
+ int blockend;
+{
+ unsigned int addr;
+
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Invalid register number %d.", regno);
+
+ /* UAREA_SIZE == 8 kB in i386 */
+ addr = (unsigned int)REG_ADDRESS (UAREA_SIZE - sizeof(struct i386_thread_state), regno);
+
+ return addr;
+}
+
+/* jtv@hut.fi: I copied and modified this 387 code from
+ * gdb/i386-xdep.c. Modifications for Mach 3.0.
+ *
+ * i387 status dumper. See also i387-tdep.c
+ */
+struct env387
+{
+ unsigned short control;
+ unsigned short r0;
+ unsigned short status;
+ unsigned short r1;
+ unsigned short tag;
+ unsigned short r2;
+ unsigned long eip;
+ unsigned short code_seg;
+ unsigned short opcode;
+ unsigned long operand;
+ unsigned short operand_seg;
+ unsigned short r3;
+ unsigned char regs[8][10];
+};
+/* This routine is machine independent?
+ * Should move it to i387-tdep.c but you need to export struct env387
+ */
+private
+print_387_status (status, ep)
+ unsigned short status;
+ struct env387 *ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ bothstatus = ((status != 0) && (ep->status != 0));
+ if (status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("u: ");
+ print_387_status_word (status);
+ }
+
+ if (ep->status != 0)
+ {
+ if (bothstatus)
+ printf_unfiltered ("e: ");
+ print_387_status_word (ep->status);
+ }
+
+ print_387_control_word (ep->control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
+ printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
+ printf_unfiltered ("%s; ", local_hex_string(ep->eip));
+ printf_unfiltered ("operand %s", local_hex_string(ep->operand_seg));
+ printf_unfiltered (":%s\n", local_hex_string(ep->operand));
+
+ top = (ep->status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep->tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep->regs[fpreg][i]);
+
+ floatformat_to_double (&floatformat_i387_ext, (char *)ep->regs[fpreg],
+ &val);
+ printf_unfiltered (" %g\n", val);
+ }
+ if (ep->r0)
+ printf_unfiltered ("warning: reserved0 is %s\n", local_hex_string(ep->r0));
+ if (ep->r1)
+ printf_unfiltered ("warning: reserved1 is %s\n", local_hex_string(ep->r1));
+ if (ep->r2)
+ printf_unfiltered ("warning: reserved2 is %s\n", local_hex_string(ep->r2));
+ if (ep->r3)
+ printf_unfiltered ("warning: reserved3 is %s\n", local_hex_string(ep->r3));
+}
+
+/*
+ * values that go into fp_kind (from <i386/fpreg.h>)
+ */
+#define FP_NO 0 /* no fp chip, no emulator (no fp support) */
+#define FP_SW 1 /* no fp chip, using software emulator */
+#define FP_HW 2 /* chip present bit */
+#define FP_287 2 /* 80287 chip present */
+#define FP_387 3 /* 80387 chip present */
+
+typedef struct fpstate {
+#if 1
+ unsigned char state[FP_STATE_BYTES]; /* "hardware" state */
+#else
+ struct env387 state; /* Actually this */
+#endif
+ int status; /* Duplicate status */
+} *fpstate_t;
+
+/* Mach 3 specific routines.
+ */
+private boolean_t
+get_i387_state (fstate)
+ struct fpstate *fstate;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int fsCnt = i386_FLOAT_STATE_COUNT;
+ struct i386_float_state *fsp;
+
+ ret = thread_get_state (current_thread,
+ i386_FLOAT_STATE,
+ state,
+ &fsCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not get live floating point state: %s",
+ mach_error_string (ret));
+ return FALSE;
+ }
+
+ fsp = (struct i386_float_state *)state;
+ /* The 387 chip (also 486 counts) or a software emulator? */
+ if (!fsp->initialized || (fsp->fpkind != FP_387 && fsp->fpkind != FP_SW))
+ return FALSE;
+
+ /* Clear the target then copy thread's float state there.
+ Make a copy of the status word, for some reason?
+ */
+ memset (fstate, 0, sizeof (struct fpstate));
+
+ fstate->status = fsp->exc_status;
+
+ memcpy (fstate->state, (char *)&fsp->hw_state, FP_STATE_BYTES);
+
+ return TRUE;
+}
+
+private boolean_t
+get_i387_core_state (fstate)
+ struct fpstate *fstate;
+{
+ /* Not implemented yet. Core files do not contain float state. */
+ return FALSE;
+}
+
+/*
+ * This is called by "info float" command
+ */
+void
+i386_mach3_float_info()
+{
+ char buf [sizeof (struct fpstate) + 2 * sizeof (int)];
+ boolean_t valid = FALSE;
+ fpstate_t fps;
+
+ if (target_has_execution)
+ valid = get_i387_state (buf);
+#if 0
+ else if (WE HAVE CORE FILE) /* @@@@ Core files not supported */
+ valid = get_i387_core_state (buf);
+#endif
+
+ if (!valid)
+ {
+ warning ("no floating point status saved");
+ return;
+ }
+
+ fps = (fpstate_t) buf;
+
+ print_387_status (fps->status, (struct env387 *)fps->state);
+}
diff --git a/contrib/gdb/gdb/i386mach-nat.c b/contrib/gdb/gdb/i386mach-nat.c
new file mode 100644
index 0000000..1a5904a
--- /dev/null
+++ b/contrib/gdb/gdb/i386mach-nat.c
@@ -0,0 +1,163 @@
+/* Native dependent code for Mach 386's for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <sys/user.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include <sys/core.h>
+
+
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ registers_fetched ();
+
+ ptrace (PTRACE_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+
+ memcpy (registers, &inferior_registers, sizeof inferior_registers);
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ inferior_fp_registers.f_st,
+ sizeof inferior_fp_registers.f_st);
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &inferior_fp_registers.f_ctrl,
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ struct regs inferior_registers;
+ struct fp_state inferior_fp_registers;
+ extern char registers[];
+
+ memcpy (&inferior_registers, registers, 20 * 4);
+
+ memcpy (inferior_fp_registers.f_st,&registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof inferior_fp_registers.f_st);
+ memcpy (&inferior_fp_registers.f_ctrl,
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ sizeof inferior_fp_registers - sizeof inferior_fp_registers.f_st);
+
+#ifdef PTRACE_FP_BUG
+ if (regno == FP_REGNUM || regno == -1)
+ /* Storing the frame pointer requires a gross hack, in which an
+ instruction that moves eax into ebp gets single-stepped. */
+ {
+ int stack = inferior_registers.r_reg[SP_REGNUM];
+ int stuff = ptrace (PTRACE_PEEKDATA, inferior_pid,
+ (PTRACE_ARG3_TYPE) stack);
+ int reg = inferior_registers.r_reg[EAX];
+ inferior_registers.r_reg[EAX] =
+ inferior_registers.r_reg[FP_REGNUM];
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack, 0xc589);
+ ptrace (PTRACE_SINGLESTEP, inferior_pid, (PTRACE_ARG3_TYPE) stack, 0);
+ wait (0);
+ ptrace (PTRACE_POKEDATA, inferior_pid, (PTRACE_ARG3_TYPE) stack, stuff);
+ inferior_registers.r_reg[EAX] = reg;
+ }
+#endif
+ ptrace (PTRACE_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers);
+ ptrace (PTRACE_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers);
+}
+
+
+
+/* Work with core files, for GDB. */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned int reg_addr; /* Unused in this version */
+{
+ int val;
+ extern char registers[];
+
+ switch (which) {
+ case 0:
+ case 1:
+ memcpy (registers, core_reg_sect, core_reg_size);
+ break;
+
+ case 2:
+#ifdef FP0_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ core_reg_sect,
+ core_reg_size); /* FIXME, probably bogus */
+#endif
+#ifdef FPC_REGNUM
+ memcpy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &corestr.c_fpu.f_fpstatus.f_ctrl,
+ sizeof corestr.c_fpu.f_fpstatus -
+ sizeof corestr.c_fpu.f_fpstatus.f_st);
+#endif
+ break;
+ }
+}
+
+
+/* Register that we are able to handle i386mach core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns i386mach_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_i386mach ()
+{
+ add_core_fns (&i386mach_core_fns);
+}
diff --git a/contrib/gdb/gdb/i386v-nat.c b/contrib/gdb/gdb/i386v-nat.c
new file mode 100644
index 0000000..38468a9
--- /dev/null
+++ b/contrib/gdb/gdb/i386v-nat.c
@@ -0,0 +1,371 @@
+/* Intel 386 native support for SYSV systems (pre-SVR4).
+ Copyright (C) 1988, 1989, 1991, 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcore.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/user.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+#include <sys/debugreg.h>
+#endif
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#ifndef NO_SYS_REG_H
+#include <sys/reg.h>
+#endif
+
+#include "floatformat.h"
+
+#include "target.h"
+
+
+/* this table must line up with REGISTER_NAMES in tm-i386v.h */
+/* symbols like 'EAX' come from <sys/reg.h> */
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+/* blockend is the value of u.u_ar0, and points to the
+ * place where GS is stored
+ */
+
+int
+i386_register_u_addr (blockend, regnum)
+ int blockend;
+ int regnum;
+{
+ struct user u;
+ int fpstate;
+ int ubase;
+
+ ubase = blockend;
+ /* FIXME: Should have better way to test floating point range */
+ if (regnum >= FP0_REGNUM && regnum <= (FP0_REGNUM + 7))
+ {
+#ifdef KSTKSZ /* SCO, and others? */
+ ubase += 4 * (SS + 1) - KSTKSZ;
+ fpstate = ubase + ((char *)&u.u_fps.u_fpstate - (char *)&u);
+ return (fpstate + 0x1c + 10 * (regnum - FP0_REGNUM));
+#else
+ fpstate = ubase + ((char *)&u.i387.st_space - (char *)&u);
+ return (fpstate + 10 * (regnum - FP0_REGNUM));
+#endif
+ }
+ else
+ {
+ return (ubase + 4 * regmap[regnum]);
+ }
+
+}
+
+int
+kernel_u_size ()
+{
+ return (sizeof (struct user));
+}
+
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+#if !defined (offsetof)
+#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
+#endif
+
+/* Record the value of the debug control register. */
+static int debug_control_mirror;
+
+/* Record which address associates with which register. */
+static CORE_ADDR address_lookup[DR_LASTADDR - DR_FIRSTADDR + 1];
+
+static int
+i386_insert_aligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+ int));
+
+static int
+i386_insert_nonaligned_watchpoint PARAMS ((int, CORE_ADDR, CORE_ADDR, int,
+ int));
+
+/* Insert a watchpoint. */
+
+int
+i386_insert_watchpoint (pid, addr, len, rw)
+ int pid;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ return i386_insert_aligned_watchpoint (pid, addr, addr, len, rw);
+}
+
+static int
+i386_insert_aligned_watchpoint (pid, waddr, addr, len, rw)
+ int pid;
+ CORE_ADDR waddr;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ int i;
+ int read_write_bits, len_bits;
+ int free_debug_register;
+ int register_number;
+
+ /* Look for a free debug register. */
+ for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+ {
+ if (address_lookup[i - DR_FIRSTADDR] == 0)
+ break;
+ }
+
+ /* No more debug registers! */
+ if (i > DR_LASTADDR)
+ return -1;
+
+ read_write_bits = ((rw & 1) ? DR_RW_READ : 0) | ((rw & 2) ? DR_RW_WRITE : 0);
+
+ if (len == 1)
+ len_bits = DR_LEN_1;
+ else if (len == 2)
+ {
+ if (addr % 2)
+ return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+ len_bits = DR_LEN_2;
+ }
+
+ else if (len == 4)
+ {
+ if (addr % 4)
+ return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+ len_bits = DR_LEN_4;
+ }
+ else
+ return i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw);
+
+ free_debug_register = i;
+ register_number = free_debug_register - DR_FIRSTADDR;
+ debug_control_mirror |=
+ ((read_write_bits | len_bits)
+ << (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * register_number));
+ debug_control_mirror |=
+ (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+ debug_control_mirror |= DR_LOCAL_SLOWDOWN;
+ debug_control_mirror &= ~DR_CONTROL_RESERVED;
+
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+ debug_control_mirror);
+ ptrace (6, pid, offsetof (struct user, u_debugreg[free_debug_register]),
+ addr);
+
+ /* Record where we came from. */
+ address_lookup[register_number] = addr;
+ return 0;
+}
+
+static int
+i386_insert_nonaligned_watchpoint (pid, waddr, addr, len, rw)
+ int pid;
+ CORE_ADDR waddr;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ int align;
+ int size;
+ int rv;
+
+ static int size_try_array[16] = {
+ 1, 1, 1, 1, /* trying size one */
+ 2, 1, 2, 1, /* trying size two */
+ 2, 1, 2, 1, /* trying size three */
+ 4, 1, 2, 1 /* trying size four */
+ };
+
+ rv = 0;
+ while (len > 0)
+ {
+ align = addr % 4;
+ /* Four is the maximum length for 386. */
+ size = (len > 4) ? 3 : len - 1;
+ size = size_try_array[size * 4 + align];
+
+ rv = i386_insert_aligned_watchpoint (pid, waddr, addr, size, rw);
+ if (rv)
+ {
+ i386_remove_watchpoint (pid, waddr, size);
+ return rv;
+ }
+ addr += size;
+ len -= size;
+ }
+ return rv;
+}
+
+/* Remove a watchpoint. */
+
+int
+i386_remove_watchpoint (pid, addr, len)
+ int pid;
+ CORE_ADDR addr;
+ int len;
+{
+ int i;
+ int register_number;
+
+ for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+ {
+ register_number = i - DR_FIRSTADDR;
+ if (address_lookup[register_number] == addr)
+ {
+ debug_control_mirror &=
+ ~(1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * register_number));
+ address_lookup[register_number] = 0;
+ }
+ }
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_CONTROL]),
+ debug_control_mirror);
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+ return 0;
+}
+
+/* Check if stopped by a watchpoint. */
+
+CORE_ADDR
+i386_stopped_by_watchpoint (pid)
+ int pid;
+{
+ int i;
+ int status;
+
+ status = ptrace (3, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+ ptrace (6, pid, offsetof (struct user, u_debugreg[DR_STATUS]), 0);
+
+ for (i = DR_FIRSTADDR; i <= DR_LASTADDR; i++)
+ {
+ if (status & (1 << (i - DR_FIRSTADDR)))
+ return address_lookup[i - DR_FIRSTADDR];
+ }
+
+ return 0;
+}
+
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
+#if 0
+/* using FLOAT_INFO as is would be a problem. FLOAT_INFO is called
+ via a command xxx and eventually calls ptrace without ever having
+ traversed the target vector. This would be terribly impolite
+ behaviour for a sun4 hosted remote gdb.
+
+ A fix might be to move this code into the "info registers" command.
+ rich@cygnus.com 15 Sept 92. */
+i386_float_info ()
+{
+ struct user u; /* just for address computations */
+ int i;
+ /* fpstate defined in <sys/user.h> */
+ struct fpstate *fpstatep;
+ char buf[sizeof (struct fpstate) + 2 * sizeof (int)];
+ unsigned int uaddr;
+ char fpvalid = 0;
+ unsigned int rounded_addr;
+ unsigned int rounded_size;
+ extern int corechan;
+ int skip;
+
+ uaddr = (char *)&u.u_fpvalid - (char *)&u;
+ if (target_has_execution)
+ {
+ unsigned int data;
+ unsigned int mask;
+
+ rounded_addr = uaddr & -sizeof (int);
+ data = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
+ mask = 0xff << ((uaddr - rounded_addr) * 8);
+
+ fpvalid = ((data & mask) != 0);
+ }
+#if 0
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror ("seek on core file");
+ if (myread (corechan, &fpvalid, 1) < 0)
+ perror ("read on core file");
+
+ }
+#endif /* no core support yet */
+
+ if (fpvalid == 0)
+ {
+ printf_unfiltered ("no floating point status saved\n");
+ return;
+ }
+
+ uaddr = (char *)&U_FPSTATE(u) - (char *)&u;
+ if (target_has_execution)
+ {
+ int *ip;
+
+ rounded_addr = uaddr & -sizeof (int);
+ rounded_size = (((uaddr + sizeof (struct fpstate)) - uaddr) +
+ sizeof (int) - 1) / sizeof (int);
+ skip = uaddr - rounded_addr;
+
+ ip = (int *)buf;
+ for (i = 0; i < rounded_size; i++)
+ {
+ *ip++ = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) rounded_addr, 0);
+ rounded_addr += sizeof (int);
+ }
+ }
+#if 0
+ else
+ {
+ if (lseek (corechan, uaddr, 0) < 0)
+ perror_with_name ("seek on core file");
+ if (myread (corechan, buf, sizeof (struct fpstate)) < 0)
+ perror_with_name ("read from core file");
+ skip = 0;
+ }
+#endif /* 0 */
+
+ fpstatep = (struct fpstate *)(buf + skip);
+ print_387_status (fpstatep->status, (struct env387 *)fpstatep->state);
+}
+
+#endif /* never */
diff --git a/contrib/gdb/gdb/i386v4-nat.c b/contrib/gdb/gdb/i386v4-nat.c
new file mode 100644
index 0000000..98f7365
--- /dev/null
+++ b/contrib/gdb/gdb/i386v4-nat.c
@@ -0,0 +1,163 @@
+/* Native-dependent code for SVR4 Unix running on i386's, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+#ifdef HAVE_SYS_PROCFS_H
+
+#include <sys/procfs.h>
+
+/* The /proc interface divides the target machine's register set up into
+ two different sets, the general register set (gregset) and the floating
+ point register set (fpregset). For each set, there is an ioctl to get
+ the current register set and another ioctl to set the current values.
+
+ The actual structure passed through the ioctl interface is, of course,
+ naturally machine dependent, and is different for each set of registers.
+ For the i386 for example, the general register set is typically defined
+ by:
+
+ typedef int gregset_t[19]; (in <sys/regset.h>)
+
+ #define GS 0 (in <sys/reg.h>)
+ #define FS 1
+ ...
+ #define UESP 17
+ #define SS 18
+
+ and the floating point set by:
+
+ typedef struct fpregset
+ {
+ union
+ {
+ struct fpchip_state // fp extension state //
+ {
+ int state[27]; // 287/387 saved state //
+ int status; // status word saved at exception //
+ } fpchip_state;
+ struct fp_emul_space // for emulators //
+ {
+ char fp_emul[246];
+ char fp_epad[2];
+ } fp_emul_space;
+ int f_fpregs[62]; // union of the above //
+ } fp_reg_set;
+ long f_wregs[33]; // saved weitek state //
+ } fpregset_t;
+
+ These routines provide the packing and unpacking of gregset_t and
+ fpregset_t formatted data.
+
+ */
+
+#ifdef HAVE_GREGSET_T
+
+/* This is a duplicate of the table in i386-xdep.c. */
+
+static int regmap[] =
+{
+ EAX, ECX, EDX, EBX,
+ UESP, EBP, ESI, EDI,
+ EIP, EFL, CS, SS,
+ DS, ES, FS, GS,
+};
+
+
+/* FIXME: These routine absolutely depends upon (NUM_REGS - NUM_FREGS)
+ being less than or equal to the number of registers that can be stored
+ in a gregset_t. Note that with the current scheme there will typically
+ be more registers actually stored in a gregset_t that what we know
+ about. This is bogus and should be fixed. */
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern int regmap[];
+
+ for (regi = 0 ; regi < (NUM_REGS - NUM_FREGS) ; regi++)
+ {
+ supply_register (regi, (char *) (regp + regmap[regi]));
+ }
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+ extern int regmap[];
+
+ for (regi = 0 ; regi < (NUM_REGS - NUM_FREGS) ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ *(regp + regmap[regi]) = *(int *) &registers[REGISTER_BYTE (regi)];
+ }
+ }
+}
+
+#endif /* HAVE_GREGSET_T */
+
+#if defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T)
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+
+ /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *to;
+ char *from;
+ extern char registers[];
+
+ /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+}
+
+#endif /* defined (FP0_REGNUM) && defined (HAVE_FPREGSET_T) */
+
+#endif /* HAVE_SYS_PROCFS_H */
diff --git a/contrib/gdb/gdb/i387-tdep.c b/contrib/gdb/gdb/i387-tdep.c
new file mode 100644
index 0000000..6b69405
--- /dev/null
+++ b/contrib/gdb/gdb/i387-tdep.c
@@ -0,0 +1,107 @@
+/* Intel 387 floating point stuff.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcore.h"
+#include "floatformat.h"
+
+/* FIXME: Eliminate these routines when we have the time to change all
+ the callers. */
+
+void
+i387_to_double (from, to)
+ char *from;
+ char *to;
+{
+ floatformat_to_double (&floatformat_i387_ext, from, (double *)to);
+}
+
+void
+double_to_i387 (from, to)
+ char *from;
+ char *to;
+{
+ floatformat_from_double (&floatformat_i387_ext, (double *)from, to);
+}
+
+void
+print_387_control_word (control)
+ unsigned int control;
+{
+ printf_unfiltered ("control %s: ", local_hex_string(control));
+ printf_unfiltered ("compute to ");
+ switch ((control >> 8) & 3)
+ {
+ case 0: printf_unfiltered ("24 bits; "); break;
+ case 1: printf_unfiltered ("(bad); "); break;
+ case 2: printf_unfiltered ("53 bits; "); break;
+ case 3: printf_unfiltered ("64 bits; "); break;
+ }
+ printf_unfiltered ("round ");
+ switch ((control >> 10) & 3)
+ {
+ case 0: printf_unfiltered ("NEAREST; "); break;
+ case 1: printf_unfiltered ("DOWN; "); break;
+ case 2: printf_unfiltered ("UP; "); break;
+ case 3: printf_unfiltered ("CHOP; "); break;
+ }
+ if (control & 0x3f)
+ {
+ printf_unfiltered ("mask:");
+ if (control & 0x0001) printf_unfiltered (" INVALID");
+ if (control & 0x0002) printf_unfiltered (" DENORM");
+ if (control & 0x0004) printf_unfiltered (" DIVZ");
+ if (control & 0x0008) printf_unfiltered (" OVERF");
+ if (control & 0x0010) printf_unfiltered (" UNDERF");
+ if (control & 0x0020) printf_unfiltered (" LOS");
+ printf_unfiltered (";");
+ }
+ printf_unfiltered ("\n");
+ if (control & 0xe080) warning ("reserved bits on: %s\n",
+ local_hex_string(control & 0xe080));
+}
+
+void
+print_387_status_word (status)
+ unsigned int status;
+{
+ printf_unfiltered ("status %s: ", local_hex_string (status));
+ if (status & 0xff)
+ {
+ printf_unfiltered ("exceptions:");
+ if (status & 0x0001) printf_unfiltered (" INVALID");
+ if (status & 0x0002) printf_unfiltered (" DENORM");
+ if (status & 0x0004) printf_unfiltered (" DIVZ");
+ if (status & 0x0008) printf_unfiltered (" OVERF");
+ if (status & 0x0010) printf_unfiltered (" UNDERF");
+ if (status & 0x0020) printf_unfiltered (" LOS");
+ if (status & 0x0040) printf_unfiltered (" FPSTACK");
+ printf_unfiltered ("; ");
+ }
+ printf_unfiltered ("flags: %d%d%d%d; ",
+ (status & 0x4000) != 0,
+ (status & 0x0400) != 0,
+ (status & 0x0200) != 0,
+ (status & 0x0100) != 0);
+
+ printf_unfiltered ("top %d\n", (status >> 11) & 7);
+}
diff --git a/contrib/gdb/gdb/infcmd.c b/contrib/gdb/gdb/infcmd.c
new file mode 100644
index 0000000..bbadf92
--- /dev/null
+++ b/contrib/gdb/gdb/infcmd.c
@@ -0,0 +1,1375 @@
+/* Memory-access and commands for "inferior" process, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <signal.h>
+#include <sys/param.h>
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "language.h"
+
+static void continue_command PARAMS ((char *, int));
+
+static void until_next_command PARAMS ((int));
+
+static void until_command PARAMS ((char *, int));
+
+static void path_info PARAMS ((char *, int));
+
+static void path_command PARAMS ((char *, int));
+
+static void unset_command PARAMS ((char *, int));
+
+static void float_info PARAMS ((char *, int));
+
+static void detach_command PARAMS ((char *, int));
+
+static void nofp_registers_info PARAMS ((char *, int));
+
+static void all_registers_info PARAMS ((char *, int));
+
+static void registers_info PARAMS ((char *, int));
+
+static void do_registers_info PARAMS ((int, int));
+
+static void unset_environment_command PARAMS ((char *, int));
+
+static void set_environment_command PARAMS ((char *, int));
+
+static void environment_info PARAMS ((char *, int));
+
+static void program_info PARAMS ((char *, int));
+
+static void finish_command PARAMS ((char *, int));
+
+static void signal_command PARAMS ((char *, int));
+
+static void jump_command PARAMS ((char *, int));
+
+static void step_1 PARAMS ((int, int, char *));
+
+static void nexti_command PARAMS ((char *, int));
+
+static void stepi_command PARAMS ((char *, int));
+
+static void next_command PARAMS ((char *, int));
+
+static void step_command PARAMS ((char *, int));
+
+static void run_command PARAMS ((char *, int));
+
+#define ERROR_NO_INFERIOR \
+ if (!target_has_execution) error ("The program is not being run.");
+
+/* String containing arguments to give to the program, separated by spaces.
+ Empty string (pointer to '\0') means no args. */
+
+static char *inferior_args;
+
+/* File name for default use for standard in/out in the inferior. */
+
+char *inferior_io_terminal;
+
+/* Pid of our debugged inferior, or 0 if no inferior now.
+ Since various parts of infrun.c test this to see whether there is a program
+ being debugged it should be nonzero (currently 3 is used) for remote
+ debugging. */
+
+int inferior_pid;
+
+/* Last signal that the inferior received (why it stopped). */
+
+enum target_signal stop_signal;
+
+/* Address at which inferior stopped. */
+
+CORE_ADDR stop_pc;
+
+/* Chain containing status of breakpoint(s) that we have stopped at. */
+
+bpstat stop_bpstat;
+
+/* Flag indicating that a command has proceeded the inferior past the
+ current breakpoint. */
+
+int breakpoint_proceeded;
+
+/* Nonzero if stopped due to a step command. */
+
+int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine. */
+
+int stop_stack_dummy;
+
+/* Nonzero if stopped due to a random (unexpected) signal in inferior
+ process. */
+
+int stopped_by_random_signal;
+
+/* Range to single step within.
+ If this is nonzero, respond to a single-step signal
+ by continuing to step if the pc is in this range. */
+
+CORE_ADDR step_range_start; /* Inclusive */
+CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+ This is how we know when we step into a subroutine call,
+ and how to set the frame for the breakpoint used to step out. */
+
+CORE_ADDR step_frame_address;
+
+/* Our notion of the current stack pointer. */
+
+CORE_ADDR step_sp;
+
+/* 1 means step over all subroutine calls.
+ 0 means don't step over calls (used by stepi).
+ -1 means step over calls to undebuggable functions. */
+
+int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+ so don't print frame next time inferior stops
+ if it stops due to stepping. */
+
+int step_multi;
+
+/* Environment to use for running inferior,
+ in format described in environ.h. */
+
+struct environ *inferior_environ;
+
+
+/* ARGSUSED */
+void
+tty_command (file, from_tty)
+ char *file;
+ int from_tty;
+{
+ if (file == 0)
+ error_no_arg ("terminal name for running target process");
+
+ inferior_io_terminal = savestring (file, strlen (file));
+}
+
+static void
+run_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+
+ dont_repeat ();
+
+ if (inferior_pid)
+ {
+ if (
+ !query ("The program being debugged has been started already.\n\
+Start it from the beginning? "))
+ error ("Program not restarted.");
+ 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;
+ cmd = concat ("set args ", args, NULL);
+ make_cleanup (free, cmd);
+ execute_command (cmd, from_tty);
+ }
+
+ if (from_tty)
+ {
+ puts_filtered("Starting program: ");
+ if (exec_file)
+ puts_filtered(exec_file);
+ puts_filtered(" ");
+ puts_filtered(inferior_args);
+ puts_filtered("\n");
+ gdb_flush (gdb_stdout);
+ }
+
+ target_create_inferior (exec_file, inferior_args,
+ environ_vector (inferior_environ));
+}
+
+static void
+continue_command (proc_count_exp, from_tty)
+ char *proc_count_exp;
+ int from_tty;
+{
+ ERROR_NO_INFERIOR;
+
+ /* If have argument, set proceed count of breakpoint we stopped at. */
+
+ if (proc_count_exp != NULL)
+ {
+ bpstat bs = stop_bpstat;
+ int num = bpstat_num (&bs);
+ if (num == 0 && from_tty)
+ {
+ printf_filtered
+ ("Not stopped at any breakpoint; argument ignored.\n");
+ }
+ while (num != 0)
+ {
+ set_ignore_count (num,
+ parse_and_eval_address (proc_count_exp) - 1,
+ from_tty);
+ /* set_ignore_count prints a message ending with a period.
+ So print two spaces before "Continuing.". */
+ if (from_tty)
+ printf_filtered (" ");
+ num = bpstat_num (&bs);
+ }
+ }
+
+ if (from_tty)
+ printf_filtered ("Continuing.\n");
+
+ clear_proceed_status ();
+
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Step until outside of current statement. */
+
+/* ARGSUSED */
+static void
+step_command (count_string, from_tty)
+ char *count_string;
+ int from_tty;
+{
+ step_1 (0, 0, count_string);
+}
+
+/* Likewise, but skip over subroutine calls as if single instructions. */
+
+/* ARGSUSED */
+static void
+next_command (count_string, from_tty)
+ char *count_string;
+ int from_tty;
+{
+ step_1 (1, 0, count_string);
+}
+
+/* Likewise, but step only one instruction. */
+
+/* ARGSUSED */
+static void
+stepi_command (count_string, from_tty)
+ char *count_string;
+ int from_tty;
+{
+ step_1 (0, 1, count_string);
+}
+
+/* ARGSUSED */
+static void
+nexti_command (count_string, from_tty)
+ char *count_string;
+ int from_tty;
+{
+ step_1 (1, 1, count_string);
+}
+
+static void
+step_1 (skip_subroutines, single_inst, count_string)
+ int skip_subroutines;
+ int single_inst;
+ char *count_string;
+{
+ register int count = 1;
+ struct frame_info *frame;
+ struct cleanup *cleanups = 0;
+
+ ERROR_NO_INFERIOR;
+ count = count_string ? parse_and_eval_address (count_string) : 1;
+
+ if (!single_inst || skip_subroutines) /* leave si command alone */
+ {
+ enable_longjmp_breakpoint();
+ cleanups = make_cleanup(disable_longjmp_breakpoint, 0);
+ }
+
+ for (; count > 0; count--)
+ {
+ clear_proceed_status ();
+
+ frame = get_current_frame ();
+ if (!frame) /* Avoid coredump here. Why tho? */
+ error ("No current frame");
+ step_frame_address = FRAME_FP (frame);
+ step_sp = read_sp ();
+
+ if (! single_inst)
+ {
+ find_pc_line_pc_range (stop_pc, &step_range_start, &step_range_end);
+ if (step_range_end == 0)
+ {
+ char *name;
+ if (find_pc_partial_function (stop_pc, &name, &step_range_start,
+ &step_range_end) == 0)
+ error ("Cannot find bounds of current function");
+
+ target_terminal_ours ();
+ printf_filtered ("\
+Single stepping until exit from function %s, \n\
+which has no line number information.\n", name);
+ }
+ }
+ else
+ {
+ /* Say we are stepping, but stop after one insn whatever it does. */
+ step_range_start = step_range_end = 1;
+ if (!skip_subroutines)
+ /* It is stepi.
+ Don't step over function calls, not even to functions lacking
+ line numbers. */
+ step_over_calls = 0;
+ }
+
+ if (skip_subroutines)
+ step_over_calls = 1;
+
+ step_multi = (count > 1);
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+ if (! stop_step)
+ break;
+
+ /* FIXME: On nexti, this may have already been done (when we hit the
+ step resume break, I think). Probably this should be moved to
+ wait_for_inferior (near the top). */
+#if defined (SHIFT_INST_REGS)
+ SHIFT_INST_REGS();
+#endif
+ }
+
+ if (!single_inst || skip_subroutines)
+ do_cleanups(cleanups);
+}
+
+/* Continue program at specified address. */
+
+static void
+jump_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register CORE_ADDR addr;
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct symbol *fn;
+ struct symbol *sfn;
+
+ ERROR_NO_INFERIOR;
+
+ if (!arg)
+ error_no_arg ("starting address");
+
+ sals = decode_line_spec_1 (arg, 1);
+ if (sals.nelts != 1)
+ {
+ error ("Unreasonable jump request");
+ }
+
+ sal = sals.sals[0];
+ free ((PTR)sals.sals);
+
+ if (sal.symtab == 0 && sal.pc == 0)
+ error ("No source file has been specified.");
+
+ resolve_sal_pc (&sal); /* May error out */
+
+ /* See if we are trying to jump to another function. */
+ fn = get_frame_function (get_current_frame ());
+ sfn = find_pc_function (sal.pc);
+ if (fn != NULL && sfn != fn)
+ {
+ if (!query ("Line %d is not in `%s'. Jump anyway? ", sal.line,
+ SYMBOL_SOURCE_NAME (fn)))
+ {
+ error ("Not confirmed.");
+ /* NOTREACHED */
+ }
+ }
+
+ addr = sal.pc;
+
+ if (from_tty)
+ {
+ printf_filtered ("Continuing at ");
+ print_address_numeric (addr, 1, gdb_stdout);
+ printf_filtered (".\n");
+ }
+
+ clear_proceed_status ();
+ proceed (addr, TARGET_SIGNAL_0, 0);
+}
+
+/* Continue program giving it specified signal. */
+
+static void
+signal_command (signum_exp, from_tty)
+ char *signum_exp;
+ int from_tty;
+{
+ enum target_signal oursig;
+
+ dont_repeat (); /* Too dangerous. */
+ ERROR_NO_INFERIOR;
+
+ if (!signum_exp)
+ error_no_arg ("signal number");
+
+ /* 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. */
+ oursig = target_signal_from_name (signum_exp);
+
+ if (oursig == TARGET_SIGNAL_UNKNOWN)
+ {
+ /* No, try numeric. */
+ int num = parse_and_eval_address (signum_exp);
+
+ if (num == 0)
+ oursig = TARGET_SIGNAL_0;
+ else
+ oursig = target_signal_from_command (num);
+ }
+
+ if (from_tty)
+ {
+ if (oursig == TARGET_SIGNAL_0)
+ printf_filtered ("Continuing with no signal.\n");
+ else
+ printf_filtered ("Continuing with signal %s.\n",
+ target_signal_to_name (oursig));
+ }
+
+ clear_proceed_status ();
+ /* "signal 0" should not get stuck if we are stopped at a breakpoint.
+ FIXME: Neither should "signal foo" but when I tried passing
+ (CORE_ADDR)-1 unconditionally I got a testsuite failure which I haven't
+ tried to track down yet. */
+ proceed (oursig == TARGET_SIGNAL_0 ? (CORE_ADDR) -1 : stop_pc, oursig, 0);
+}
+
+/* Call breakpoint_auto_delete on the current contents of the bpstat
+ pointed to by arg (which is really a bpstat *). */
+void
+breakpoint_auto_delete_contents (arg)
+ PTR arg;
+{
+ breakpoint_auto_delete (*(bpstat *)arg);
+}
+
+/* Execute a "stack dummy", a piece of code stored in the stack
+ by the debugger to be executed in the inferior.
+
+ To call: first, do PUSH_DUMMY_FRAME.
+ Then push the contents of the dummy. It should end with a breakpoint insn.
+ Then call here, passing address at which to start the dummy.
+
+ The contents of all registers are saved before the dummy frame is popped
+ and copied into the buffer BUFFER.
+
+ The dummy's frame is automatically popped whenever that break is hit.
+ If that is the first time the program stops, run_stack_dummy
+ returns to its caller with that frame already gone and returns 0.
+ Otherwise, run_stack-dummy returns 1 (the frame will eventually be popped
+ when we do hit that breakpoint). */
+
+/* DEBUG HOOK: 4 => return instead of letting the stack dummy run. */
+
+static int stack_dummy_testing = 0;
+
+int
+run_stack_dummy (addr, buffer)
+ CORE_ADDR addr;
+ char buffer[REGISTER_BYTES];
+{
+ struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0);
+
+ /* Now proceed, having reached the desired place. */
+ clear_proceed_status ();
+ if (stack_dummy_testing & 4)
+ {
+ POP_FRAME;
+ return(0);
+ }
+#ifdef CALL_DUMMY_BREAKPOINT_OFFSET
+ {
+ struct breakpoint *bpt;
+ struct symtab_and_line sal;
+
+#if CALL_DUMMY_LOCATION != AT_ENTRY_POINT
+ sal.pc = addr - CALL_DUMMY_START_OFFSET + CALL_DUMMY_BREAKPOINT_OFFSET;
+#else
+ sal.pc = CALL_DUMMY_ADDRESS ();
+#endif
+ sal.symtab = NULL;
+ sal.line = 0;
+
+ /* Set up a FRAME for the dummy frame so we can pass it to
+ set_momentary_breakpoint. We need to give the breakpoint a
+ frame in case there is only one copy of the dummy (e.g.
+ CALL_DUMMY_LOCATION == AFTER_TEXT_END). */
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_fp (), sal.pc));
+
+ /* If defined, CALL_DUMMY_BREAKPOINT_OFFSET is where we need to put
+ a breakpoint instruction. If not, the call dummy already has the
+ breakpoint instruction in it.
+
+ addr is the address of the call dummy plus the CALL_DUMMY_START_OFFSET,
+ so we need to subtract the CALL_DUMMY_START_OFFSET. */
+ bpt = set_momentary_breakpoint (sal,
+ get_current_frame (),
+ bp_call_dummy);
+ bpt->disposition = del;
+
+ /* If all error()s out of proceed ended up calling normal_stop (and
+ perhaps they should; it already does in the special case of error
+ out of resume()), then we wouldn't need this. */
+ make_cleanup (breakpoint_auto_delete_contents, &stop_bpstat);
+ }
+#endif /* CALL_DUMMY_BREAKPOINT_OFFSET. */
+
+ proceed_to_finish = 1; /* We want stop_registers, please... */
+ proceed (addr, TARGET_SIGNAL_0, 0);
+
+ discard_cleanups (old_cleanups);
+
+ if (!stop_stack_dummy)
+ return 1;
+
+ /* On return, the stack dummy has been popped already. */
+
+ memcpy (buffer, stop_registers, sizeof stop_registers);
+ return 0;
+}
+
+/* Proceed until we reach a different source line with pc greater than
+ our current one or exit the function. We skip calls in both cases.
+
+ Note that eventually this command should probably be changed so
+ that only source lines are printed out when we hit the breakpoint
+ we set. This may involve changes to wait_for_inferior and the
+ proceed status code. */
+
+/* ARGSUSED */
+static void
+until_next_command (from_tty)
+ int from_tty;
+{
+ struct frame_info *frame;
+ CORE_ADDR pc;
+ struct symbol *func;
+ struct symtab_and_line sal;
+
+ clear_proceed_status ();
+
+ frame = get_current_frame ();
+
+ /* Step until either exited from this function or greater
+ than the current line (if in symbolic section) or pc (if
+ not). */
+
+ pc = read_pc ();
+ func = find_pc_function (pc);
+
+ if (!func)
+ {
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
+
+ if (msymbol == NULL)
+ error ("Execution is not within a known function.");
+
+ step_range_start = SYMBOL_VALUE_ADDRESS (msymbol);
+ step_range_end = pc;
+ }
+ else
+ {
+ sal = find_pc_line (pc, 0);
+
+ step_range_start = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
+ step_range_end = sal.end;
+ }
+
+ step_over_calls = 1;
+ step_frame_address = FRAME_FP (frame);
+ step_sp = read_sp ();
+
+ step_multi = 0; /* Only one call to proceed */
+
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+}
+
+static void
+until_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (!target_has_execution)
+ error ("The program is not running.");
+ if (arg)
+ until_break_command (arg, from_tty);
+ else
+ until_next_command (from_tty);
+}
+
+/* "finish": Set a temporary breakpoint at the place
+ the selected frame will return to, then continue. */
+
+static void
+finish_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtab_and_line sal;
+ register struct frame_info *frame;
+ register struct symbol *function;
+ struct breakpoint *breakpoint;
+ struct cleanup *old_chain;
+
+ if (arg)
+ error ("The \"finish\" command does not take any arguments.");
+ if (!target_has_execution)
+ error ("The program is not running.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+
+ frame = get_prev_frame (selected_frame);
+ if (frame == 0)
+ error ("\"finish\" not meaningful in the outermost frame.");
+
+ clear_proceed_status ();
+
+ sal = find_pc_line (frame->pc, 0);
+ sal.pc = frame->pc;
+
+ breakpoint = set_momentary_breakpoint (sal, frame, bp_finish);
+
+ old_chain = make_cleanup(delete_breakpoint, breakpoint);
+
+ /* Find the function we will return from. */
+
+ function = find_pc_function (selected_frame->pc);
+
+ /* Print info on the selected frame, including level number
+ but not source. */
+ if (from_tty)
+ {
+ printf_filtered ("Run till exit from ");
+ print_stack_frame (selected_frame, selected_frame_level, 0);
+ }
+
+ proceed_to_finish = 1; /* We want stop_registers, please... */
+ 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_ptr val;
+ CORE_ADDR funcaddr;
+
+ value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (function));
+ if (!value_type)
+ fatal ("internal: finish_command: function has no target type");
+
+ if (TYPE_CODE (value_type) == TYPE_CODE_VOID)
+ return;
+
+ funcaddr = BLOCK_START (SYMBOL_BLOCK_VALUE (function));
+
+ val = value_being_returned (value_type, stop_registers,
+ using_struct_return (value_of_variable (function, NULL),
+ funcaddr,
+ check_typedef (value_type),
+ BLOCK_GCC_COMPILED (SYMBOL_BLOCK_VALUE (function))));
+
+ printf_filtered ("Value returned is $%d = ", record_latest_value (val));
+ value_print (val, gdb_stdout, 0, Val_no_prettyprint);
+ printf_filtered ("\n");
+ }
+ do_cleanups(old_chain);
+}
+
+/* ARGSUSED */
+static void
+program_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ bpstat bs = stop_bpstat;
+ int num = bpstat_num (&bs);
+
+ if (!target_has_execution)
+ {
+ printf_filtered ("The program being debugged is not being run.\n");
+ return;
+ }
+
+ target_files_info ();
+ printf_filtered ("Program stopped at %s.\n",
+ local_hex_string((unsigned long) stop_pc));
+ if (stop_step)
+ printf_filtered ("It stopped after being stepped.\n");
+ else if (num != 0)
+ {
+ /* There may be several breakpoints in the same place, so this
+ isn't as strange as it seems. */
+ while (num != 0)
+ {
+ if (num < 0)
+ printf_filtered ("It stopped at a breakpoint that has since been deleted.\n");
+ else
+ printf_filtered ("It stopped at breakpoint %d.\n", num);
+ num = bpstat_num (&bs);
+ }
+ }
+ else if (stop_signal != TARGET_SIGNAL_0)
+ {
+ 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");
+}
+
+static void
+environment_info (var, from_tty)
+ char *var;
+ int from_tty;
+{
+ if (var)
+ {
+ register char *val = get_in_environ (inferior_environ, var);
+ if (val)
+ {
+ puts_filtered (var);
+ puts_filtered (" = ");
+ puts_filtered (val);
+ puts_filtered ("\n");
+ }
+ else
+ {
+ puts_filtered ("Environment variable \"");
+ puts_filtered (var);
+ puts_filtered ("\" not defined.\n");
+ }
+ }
+ else
+ {
+ register char **vector = environ_vector (inferior_environ);
+ while (*vector)
+ {
+ puts_filtered (*vector++);
+ puts_filtered ("\n");
+ }
+ }
+}
+
+static void
+set_environment_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register char *p, *val, *var;
+ int nullset = 0;
+
+ if (arg == 0)
+ error_no_arg ("environment variable and value");
+
+ /* Find seperation between variable name and value */
+ p = (char *) strchr (arg, '=');
+ val = (char *) strchr (arg, ' ');
+
+ if (p != 0 && val != 0)
+ {
+ /* We have both a space and an equals. If the space is before the
+ equals, walk forward over the spaces til we see a nonspace
+ (possibly the equals). */
+ if (p > val)
+ while (*val == ' ')
+ val++;
+
+ /* Now if the = is after the char following the spaces,
+ take the char following the spaces. */
+ if (p > val)
+ p = val - 1;
+ }
+ else if (val != 0 && p == 0)
+ p = val;
+
+ if (p == arg)
+ error_no_arg ("environment variable to set");
+
+ if (p == 0 || p[1] == 0)
+ {
+ nullset = 1;
+ if (p == 0)
+ p = arg + strlen (arg); /* So that savestring below will work */
+ }
+ else
+ {
+ /* Not setting variable value to null */
+ val = p + 1;
+ while (*val == ' ' || *val == '\t')
+ val++;
+ }
+
+ while (p != arg && (p[-1] == ' ' || p[-1] == '\t')) p--;
+
+ var = savestring (arg, p - arg);
+ if (nullset)
+ {
+ printf_filtered ("Setting environment variable \"%s\" to null value.\n", var);
+ set_in_environ (inferior_environ, var, "");
+ }
+ else
+ set_in_environ (inferior_environ, var, val);
+ free (var);
+}
+
+static void
+unset_environment_command (var, from_tty)
+ char *var;
+ int from_tty;
+{
+ if (var == 0)
+ {
+ /* If there is no argument, delete all environment variables.
+ Ask for confirmation if reading from the terminal. */
+ if (!from_tty || query ("Delete all environment variables? "))
+ {
+ free_environ (inferior_environ);
+ inferior_environ = make_environ ();
+ }
+ }
+ else
+ unset_in_environ (inferior_environ, var);
+}
+
+/* Handle the execution path (PATH variable) */
+
+static const char path_var_name[] = "PATH";
+
+/* ARGSUSED */
+static void
+path_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ puts_filtered ("Executable and object file path: ");
+ puts_filtered (get_in_environ (inferior_environ, path_var_name));
+ puts_filtered ("\n");
+}
+
+/* Add zero or more directories to the front of the execution path. */
+
+static void
+path_command (dirname, from_tty)
+ char *dirname;
+ int from_tty;
+{
+ char *exec_path;
+ char *env;
+ dont_repeat ();
+ env = get_in_environ (inferior_environ, path_var_name);
+ /* Can be null if path is not set */
+ if (!env)
+ env = "";
+ exec_path = strsave (env);
+ mod_path (dirname, &exec_path);
+ set_in_environ (inferior_environ, path_var_name, exec_path);
+ free (exec_path);
+ if (from_tty)
+ path_info ((char *)NULL, from_tty);
+}
+
+/* The array of register names. */
+
+char *reg_names[] = REGISTER_NAMES;
+
+/* Print out the machine register regnum. If regnum is -1,
+ print all registers (fpregs == 1) or all non-float registers
+ (fpregs == 0).
+
+ For most machines, having all_registers_info() print the
+ register(s) one per line is good enough. If a different format
+ is required, (eg, for MIPS or Pyramid 90x, which both have
+ lots of regs), or there is an existing convention for showing
+ all the registers, define the macro DO_REGISTERS_INFO(regnum, fp)
+ 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 < numregs; i++)
+ {
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
+
+ /* Decide between printing all regs, nonfloat regs, or specific reg. */
+ if (regnum == -1) {
+ if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (i)) == TYPE_CODE_FLT && !fpregs)
+ continue;
+ } else {
+ if (i != regnum)
+ continue;
+ }
+
+ /* If the register name is empty, it is undefined for this
+ processor, so don't display anything. */
+ if (reg_names[i] == NULL || *(reg_names[i]) == '\0')
+ continue;
+
+ fputs_filtered (reg_names[i], gdb_stdout);
+ print_spaces_filtered (15 - strlen (reg_names[i]), gdb_stdout);
+
+ /* Get the data in raw format. */
+ if (read_relative_register_raw_bytes (i, raw_buffer))
+ {
+ printf_filtered ("Invalid register contents\n");
+ continue;
+ }
+
+ /* 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)
+ {
+ register int j;
+
+#ifdef INVALID_FLOAT
+ if (INVALID_FLOAT (virtual_buffer, REGISTER_VIRTUAL_SIZE (i)))
+ printf_filtered ("<invalid float>");
+ else
+#endif
+ val_print (REGISTER_VIRTUAL_TYPE (i), virtual_buffer, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+
+ printf_filtered ("\t(raw 0x");
+ for (j = 0; j < REGISTER_RAW_SIZE (i); j++)
+ printf_filtered ("%02x", (unsigned char)raw_buffer[j]);
+ printf_filtered (")");
+ }
+
+/* FIXME! val_print probably can handle all of these cases now... */
+
+ /* Else if virtual format is too long for printf,
+ print in hex a byte at a time. */
+ else if (REGISTER_VIRTUAL_SIZE (i) > (int) sizeof (long))
+ {
+ register int j;
+ printf_filtered ("0x");
+ for (j = 0; j < REGISTER_VIRTUAL_SIZE (i); j++)
+ printf_filtered ("%02x", (unsigned char)virtual_buffer[j]);
+ }
+ /* Else print as integer in hex and in decimal. */
+ else
+ {
+ val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0,
+ gdb_stdout, 'x', 1, 0, Val_pretty_default);
+ printf_filtered ("\t");
+ val_print (REGISTER_VIRTUAL_TYPE (i), raw_buffer, 0,
+ gdb_stdout, 0, 1, 0, Val_pretty_default);
+ }
+
+ /* The SPARC wants to print even-numbered float regs as doubles
+ in addition to printing them as floats. */
+#ifdef PRINT_REGISTER_HOOK
+ PRINT_REGISTER_HOOK (i);
+#endif
+
+ printf_filtered ("\n");
+ }
+}
+#endif /* no DO_REGISTERS_INFO. */
+
+static void
+registers_info (addr_exp, fpregs)
+ char *addr_exp;
+ int fpregs;
+{
+ int regnum, numregs;
+ register char *end;
+
+ if (!target_has_registers)
+ error ("The program has no registers now.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+
+ if (!addr_exp)
+ {
+ DO_REGISTERS_INFO(-1, fpregs);
+ return;
+ }
+
+ do
+ {
+ if (addr_exp[0] == '$')
+ addr_exp++;
+ end = addr_exp;
+ while (*end != '\0' && *end != ' ' && *end != '\t')
+ ++end;
+ 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 >= numregs) /* Bad name, or bad number */
+ error ("%.*s: invalid register", end - addr_exp, addr_exp);
+
+found:
+ DO_REGISTERS_INFO(regnum, fpregs);
+
+ addr_exp = end;
+ while (*addr_exp == ' ' || *addr_exp == '\t')
+ ++addr_exp;
+ } while (*addr_exp != '\0');
+}
+
+static void
+all_registers_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+ registers_info (addr_exp, 1);
+}
+
+static void
+nofp_registers_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+ registers_info (addr_exp, 0);
+}
+
+/*
+ * TODO:
+ * Should save/restore the tty state since it might be that the
+ * program to be debugged was started on this tty and it wants
+ * the tty in some state other than what we want. If it's running
+ * on another terminal or without a terminal, then saving and
+ * restoring the tty state is a harmless no-op.
+ * This only needs to be done if we are attaching to a process.
+ */
+
+/*
+ attach_command --
+ takes a program started up outside of gdb and ``attaches'' to it.
+ This stops it cold in its tracks and allows us to start debugging it.
+ and wait for the trace-trap that results from attaching. */
+
+void
+attach_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int auto_solib_add;
+
+ dont_repeat (); /* Not for the faint of heart */
+
+ if (target_has_execution)
+ {
+ if (query ("A program is being debugged already. Kill it? "))
+ target_kill ();
+ else
+ error ("Not killed.");
+ }
+
+ target_attach (args, from_tty);
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* Set up execution context to know that we should return from
+ wait_for_inferior as soon as the target reports a stop. */
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+
+ /* No traps are generated when attaching to inferior under Mach 3
+ or GNU hurd. */
+#ifndef ATTACH_NO_WAIT
+ wait_for_inferior ();
+#endif
+
+#ifdef SOLIB_ADD
+ if (auto_solib_add)
+ {
+ /* Add shared library symbols from the newly attached process, if any. */
+ SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
+ re_enable_breakpoints_in_shlibs ();
+ }
+#endif
+
+ normal_stop ();
+}
+
+/*
+ * detach_command --
+ * takes a program previously attached to and detaches it.
+ * The program resumes execution and will no longer stop
+ * on signals, etc. We better not have left any breakpoints
+ * in the program or it'll die when it hits one. For this
+ * to work, it may be necessary for the process to have been
+ * previously attached. It *might* work if the program was
+ * started via the normal ptrace (PTRACE_TRACEME).
+ */
+
+static void
+detach_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat (); /* Not for the faint of heart */
+ target_detach (args, from_tty);
+}
+
+/* ARGSUSED */
+static void
+float_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+#ifdef FLOAT_INFO
+ FLOAT_INFO;
+#else
+ printf_filtered ("No floating point info available for this processor.\n");
+#endif
+}
+
+/* ARGSUSED */
+static void
+unset_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_filtered ("\"unset\" must be followed by the name of an unset subcommand.\n");
+ help_list (unsetlist, "unset ", -1, gdb_stdout);
+}
+
+void
+_initialize_infcmd ()
+{
+ struct cmd_list_element *c;
+
+ add_com ("tty", class_run, tty_command,
+ "Set terminal for future runs of program being debugged.");
+
+ add_show_from_set
+ (add_set_cmd ("args", class_run, var_string_noescape, (char *)&inferior_args,
+
+"Set arguments to give program being debugged when it is started.\n\
+Follow this command with any number of args, to be passed to the program.",
+ &setlist),
+ &showlist);
+
+ c = add_cmd
+ ("environment", no_class, environment_info,
+ "The environment to give the program, or one variable's value.\n\
+With an argument VAR, prints the value of environment variable VAR to\n\
+give the program being debugged. With no arguments, prints the entire\n\
+environment to be given to the program.", &showlist);
+ c->completer = noop_completer;
+
+ add_prefix_cmd ("unset", no_class, unset_command,
+ "Complement to certain \"set\" commands",
+ &unsetlist, "unset ", 0, &cmdlist);
+
+ c = add_cmd ("environment", class_run, unset_environment_command,
+ "Cancel environment variable VAR for the program.\n\
+This does not affect the program until the next \"run\" command.",
+ &unsetlist);
+ c->completer = noop_completer;
+
+ c = add_cmd ("environment", class_run, set_environment_command,
+ "Set environment variable value to give the program.\n\
+Arguments are VAR VALUE where VAR is variable name and VALUE is value.\n\
+VALUES of environment variables are uninterpreted strings.\n\
+This does not affect the program until the next \"run\" command.",
+ &setlist);
+ c->completer = noop_completer;
+
+ add_com ("path", class_files, path_command,
+ "Add directory DIR(s) to beginning of search path for object files.\n\
+$cwd in the path means the current working directory.\n\
+This path is equivalent to the $PATH shell variable. It is a list of\n\
+directories, separated by colons. These directories are searched to find\n\
+fully linked executable files and separately compiled object files as needed.");
+
+ c = add_cmd ("paths", no_class, path_info,
+ "Current search path for finding object files.\n\
+$cwd in the path means the current working directory.\n\
+This path is equivalent to the $PATH shell variable. It is a list of\n\
+directories, separated by colons. These directories are searched to find\n\
+fully linked executable files and separately compiled object files as needed.", &showlist);
+ c->completer = noop_completer;
+
+ add_com ("attach", class_run, attach_command,
+ "Attach to a process or file outside of GDB.\n\
+This command attaches to another target, of the same type as your last\n\
+`target' command (`info files' will show your target stack).\n\
+The command may take as argument a process id or a device file.\n\
+For a process id, you must have permission to send the process a signal,\n\
+and it must have the same effective uid as the debugger.\n\
+When using \"attach\", you should use the \"file\" command to specify\n\
+the program running in the process, and to load its symbol table.");
+
+ add_com ("detach", class_run, detach_command,
+ "Detach a process or file previously attached.\n\
+If a process, it is no longer traced, and it continues its execution. If you\n\
+were debugging a file, the file is closed and gdb no longer accesses it.");
+
+ add_com ("signal", class_run, signal_command,
+ "Continue program giving it signal specified by the argument.\n\
+An argument of \"0\" means continue program without giving it a signal.");
+
+ add_com ("stepi", class_run, stepi_command,
+ "Step one instruction exactly.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("si", "stepi", class_alias, 0);
+
+ add_com ("nexti", class_run, nexti_command,
+ "Step one instruction, but proceed through subroutine calls.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("ni", "nexti", class_alias, 0);
+
+ add_com ("finish", class_run, finish_command,
+ "Execute until selected stack frame returns.\n\
+Upon return, the value returned is printed and put in the value history.");
+
+ add_com ("next", class_run, next_command,
+ "Step program, proceeding through subroutine calls.\n\
+Like the \"step\" command as long as subroutine calls do not happen;\n\
+when they do, the call is treated as one instruction.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("n", "next", class_run, 1);
+
+ add_com ("step", class_run, step_command,
+ "Step program until it reaches a different source line.\n\
+Argument N means do this N times (or till program stops for another reason).");
+ add_com_alias ("s", "step", class_run, 1);
+
+ add_com ("until", class_run, until_command,
+ "Execute until the program reaches a source line greater than the current\n\
+or a specified line or address or function (same args as break command).\n\
+Execution will also stop upon exit from the current stack frame.");
+ add_com_alias ("u", "until", class_run, 1);
+
+ add_com ("jump", class_run, jump_command,
+ "Continue program being debugged at specified line or address.\n\
+Give as argument either LINENUM or *ADDR, where ADDR is an expression\n\
+for an address to start at.");
+
+ add_com ("continue", class_run, continue_command,
+ "Continue program being debugged, after signal or breakpoint.\n\
+If proceeding from breakpoint, a number N may be used as an argument,\n\
+which means to set the ignore count of that breakpoint to N - 1 (so that\n\
+the breakpoint won't break until the Nth time it is reached).");
+ add_com_alias ("c", "cont", class_run, 1);
+ add_com_alias ("fg", "cont", class_run, 1);
+
+ add_com ("run", class_run, run_command,
+ "Start debugged program. You may specify arguments to give it.\n\
+Args may include \"*\", or \"[...]\"; they are expanded using \"sh\".\n\
+Input and output redirection with \">\", \"<\", or \">>\" are also allowed.\n\n\
+With no arguments, uses arguments last specified (with \"run\" or \"set args\").\n\
+To cancel previous arguments and run with no arguments,\n\
+use \"set args\" without arguments.");
+ add_com_alias ("r", "run", class_run, 1);
+
+ add_info ("registers", nofp_registers_info,
+ "List of integer registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.");
+
+ add_info ("all-registers", all_registers_info,
+"List of all registers and their contents, for selected stack frame.\n\
+Register name as argument means describe only that register.");
+
+ add_info ("program", program_info,
+ "Execution status of the program.");
+
+ add_info ("float", float_info,
+ "Print the status of the floating point unit\n");
+
+ inferior_args = savestring ("", 1); /* Initially no args */
+ inferior_environ = make_environ ();
+ init_environ (inferior_environ);
+}
diff --git a/contrib/gdb/gdb/inferior.h b/contrib/gdb/gdb/inferior.h
new file mode 100644
index 0000000..e39f8b9
--- /dev/null
+++ b/contrib/gdb/gdb/inferior.h
@@ -0,0 +1,382 @@
+/* Variables that describe the inferior process running under GDB:
+ Where it is, why it stopped, and how to step it.
+ Copyright 1986, 1989, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (INFERIOR_H)
+#define INFERIOR_H 1
+
+/* For bpstat. */
+#include "breakpoint.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
+ "restore_inferior_status".
+ This pair of routines should be called around any transfer of
+ control to the inferior which you don't want showing up in your
+ control variables. */
+
+struct inferior_status {
+ enum target_signal stop_signal;
+ CORE_ADDR stop_pc;
+ bpstat stop_bpstat;
+ int stop_step;
+ int stop_stack_dummy;
+ int stopped_by_random_signal;
+ int trap_expected;
+ CORE_ADDR step_range_start;
+ CORE_ADDR step_range_end;
+ CORE_ADDR step_frame_address;
+ int step_over_calls;
+ CORE_ADDR step_resume_break_address;
+ int stop_after_trap;
+ int stop_soon_quietly;
+ CORE_ADDR selected_frame_address;
+ int selected_level;
+ char stop_registers[REGISTER_BYTES];
+
+ /* These are here because if call_function_by_hand has written some
+ registers and then decides to call error(), we better not have changed
+ any registers. */
+ char registers[REGISTER_BYTES];
+
+ int breakpoint_proceeded;
+ int restore_stack_info;
+ 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;
+
+/* Pid of our debugged inferior, or 0 if no inferior now. */
+
+extern int inferior_pid;
+
+/* Inferior environment. */
+
+extern struct environ *inferior_environ;
+
+/* Character array containing an image of the inferior programs' registers. */
+
+extern char registers[];
+
+/* Array of validity bits (one per register). Nonzero at position XXX_REGNUM
+ means that `registers' contains a valid copy of inferior register XXX. */
+
+extern char register_valid[NUM_REGS];
+
+extern void clear_proceed_status PARAMS ((void));
+
+extern void proceed PARAMS ((CORE_ADDR, enum target_signal, int));
+
+extern void kill_inferior PARAMS ((void));
+
+extern void generic_mourn_inferior PARAMS ((void));
+
+extern void terminal_ours PARAMS ((void));
+
+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));
+
+extern CORE_ADDR read_sp PARAMS ((void));
+
+extern void write_sp PARAMS ((CORE_ADDR));
+
+extern CORE_ADDR read_fp PARAMS ((void));
+
+extern void write_fp PARAMS ((CORE_ADDR));
+
+extern void wait_for_inferior PARAMS ((void));
+
+extern void init_wait_for_inferior PARAMS ((void));
+
+extern void close_exec_file PARAMS ((void));
+
+extern void 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, enum target_signal));
+
+/* From misc files */
+
+extern void store_inferior_registers PARAMS ((int));
+
+extern void fetch_inferior_registers PARAMS ((int));
+
+extern void solib_create_inferior_hook PARAMS ((void));
+
+extern void child_terminal_info PARAMS ((char *, int));
+
+extern void term_info PARAMS ((char *, int));
+
+extern void terminal_ours_for_output PARAMS ((void));
+
+extern void terminal_inferior PARAMS ((void));
+
+extern void terminal_init_inferior PARAMS ((void));
+
+/* From infptrace.c */
+
+extern int attach PARAMS ((int));
+
+void detach PARAMS ((int));
+
+extern void child_resume PARAMS ((int, int, enum target_signal));
+
+#ifndef PTRACE_ARG3_TYPE
+#define PTRACE_ARG3_TYPE int /* Correct definition for most systems. */
+#endif
+
+extern int call_ptrace PARAMS ((int, int, PTRACE_ARG3_TYPE, int));
+
+/* From procfs.c */
+
+extern int 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), char *));
+
+extern void startup_inferior PARAMS ((int));
+
+/* From inflow.c */
+
+extern void new_tty_prefork PARAMS ((char *));
+
+extern int gdb_has_a_terminal PARAMS ((void));
+
+/* From infrun.c */
+
+extern void start_remote PARAMS ((void));
+
+extern void normal_stop PARAMS ((void));
+
+extern int signal_stop_state PARAMS ((int));
+
+extern int signal_print_state PARAMS ((int));
+
+extern int signal_pass_state PARAMS ((int));
+
+/* From infcmd.c */
+
+extern void tty_command PARAMS ((char *, int));
+
+extern void attach_command PARAMS ((char *, int));
+
+/* Last signal that the inferior received (why it stopped). */
+
+extern enum target_signal stop_signal;
+
+/* Address at which inferior stopped. */
+
+extern CORE_ADDR stop_pc;
+
+/* Chain containing status of breakpoint(s) that we have stopped at. */
+
+extern bpstat stop_bpstat;
+
+/* Flag indicating that a command has proceeded the inferior past the
+ current breakpoint. */
+
+extern int breakpoint_proceeded;
+
+/* Nonzero if stopped due to a step command. */
+
+extern int stop_step;
+
+/* Nonzero if stopped due to completion of a stack dummy routine. */
+
+extern int stop_stack_dummy;
+
+/* Nonzero if program stopped due to a random (unexpected) signal in
+ inferior process. */
+
+extern int stopped_by_random_signal;
+
+/* Range to single step within.
+ If this is nonzero, respond to a single-step signal
+ by continuing to step if the pc is in this range.
+
+ If step_range_start and step_range_end are both 1, it means to step for
+ a single instruction (FIXME: it might clean up wait_for_inferior in a
+ minor way if this were changed to the address of the instruction and
+ that address plus one. But maybe not.). */
+
+extern CORE_ADDR step_range_start; /* Inclusive */
+extern CORE_ADDR step_range_end; /* Exclusive */
+
+/* Stack frame address as of when stepping command was issued.
+ This is how we know when we step into a subroutine call,
+ and how to set the frame for the breakpoint used to step out. */
+
+extern CORE_ADDR step_frame_address;
+
+/* Our notion of the current stack pointer. */
+
+extern CORE_ADDR step_sp;
+
+/* 1 means step over all subroutine calls.
+ -1 means step over calls to undebuggable functions. */
+
+extern int step_over_calls;
+
+/* If stepping, nonzero means step count is > 1
+ so don't print frame next time inferior stops
+ if it stops due to stepping. */
+
+extern int step_multi;
+
+/* Nonzero means expecting a trap and caller will handle it themselves.
+ It is used after attach, due to attaching to a process;
+ when running in the shell before the child program has been exec'd;
+ and when running some kinds of remote stuff (FIXME?). */
+
+extern int stop_soon_quietly;
+
+/* Nonzero if proceed is being used for a "finish" command or a similar
+ situation when stop_registers should be saved. */
+
+extern int proceed_to_finish;
+
+/* Save register contents here when about to pop a stack dummy frame,
+ if-and-only-if proceed_to_finish is set.
+ Thus this contains the return value from the called function (assuming
+ values are returned in a register). */
+
+extern char stop_registers[REGISTER_BYTES];
+
+/* Nonzero if the child process in inferior_pid was attached rather
+ than forked. */
+
+extern int attach_flag;
+
+/* Sigtramp is a routine that the kernel calls (which then calls the
+ signal handler). On most machines it is a library routine that
+ is linked into the executable.
+
+ This macro, given a program counter value and the name of the
+ function in which that PC resides (which can be null if the
+ name is not known), returns nonzero if the PC and name show
+ that we are in sigtramp.
+
+ On most machines just see if the name is sigtramp (and if we have
+ no name, assume we are not in sigtramp). */
+#if !defined (IN_SIGTRAMP)
+# if defined (SIGTRAMP_START)
+# define IN_SIGTRAMP(pc, name) \
+ ((pc) >= SIGTRAMP_START \
+ && (pc) < SIGTRAMP_END \
+ )
+# else
+# define IN_SIGTRAMP(pc, name) \
+ (name && STREQ ("_sigtramp", name))
+# endif
+#endif
+
+/* Possible values for CALL_DUMMY_LOCATION. */
+#define ON_STACK 1
+#define BEFORE_TEXT_END 2
+#define AFTER_TEXT_END 3
+#define AT_ENTRY_POINT 4
+
+#if !defined (CALL_DUMMY_LOCATION)
+#define CALL_DUMMY_LOCATION ON_STACK
+#endif /* No CALL_DUMMY_LOCATION. */
+
+/* Are we in a call dummy? The code below which allows DECR_PC_AFTER_BREAK
+ below is for infrun.c, which may give the macro a pc without that
+ subtracted out. */
+#if !defined (PC_IN_CALL_DUMMY)
+#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
+extern CORE_ADDR text_end;
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= text_end - CALL_DUMMY_LENGTH \
+ && (pc) <= text_end + DECR_PC_AFTER_BREAK)
+#endif /* Before text_end. */
+
+#if CALL_DUMMY_LOCATION == AFTER_TEXT_END
+extern CORE_ADDR text_end;
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= text_end \
+ && (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK)
+#endif /* After text_end. */
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and
+ top of the stack frame which we are checking, where "bottom" and
+ "top" refer to some section of memory which contains the code for
+ the call dummy. Calls to this macro assume that the contents of
+ SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively,
+ are the things to pass.
+
+ This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't
+ have that meaning, but the 29k doesn't use ON_STACK. This could be
+ fixed by generalizing this scheme, perhaps by passing in a frame
+ and adding a few fields, at least on machines which need them for
+ PC_IN_CALL_DUMMY.
+
+ Something simpler, like checking for the stack segment, doesn't work,
+ since various programs (threads implementations, gcc nested function
+ stubs, etc) may either allocate stack frames in another segment, or
+ allocate other kinds of code on the stack. */
+
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((sp) INNER_THAN (pc) && (frame_address != 0) && (pc) INNER_THAN (frame_address))
+#endif /* On stack. */
+
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
+ ((pc) >= CALL_DUMMY_ADDRESS () \
+ && (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK))
+#endif /* At entry point. */
+#endif /* No PC_IN_CALL_DUMMY. */
+
+#endif /* !defined (INFERIOR_H) */
diff --git a/contrib/gdb/gdb/inflow.c b/contrib/gdb/gdb/inflow.c
new file mode 100644
index 0000000..62daa65
--- /dev/null
+++ b/contrib/gdb/gdb/inflow.c
@@ -0,0 +1,718 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "command.h"
+#include "signals.h"
+#include "serial.h"
+#include "terminal.h"
+#include "target.h"
+#include "thread.h"
+
+#include "gdb_string.h"
+#include <signal.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_TERMIOS
+#define PROCESS_GROUP_TYPE pid_t
+#endif
+
+#ifdef HAVE_SGTTY
+#ifdef SHORT_PGRP
+/* This is only used for the ultra. Does it have pid_t? */
+#define PROCESS_GROUP_TYPE short
+#else
+#define PROCESS_GROUP_TYPE int
+#endif
+#endif /* sgtty */
+
+static void
+kill_command PARAMS ((char *, int));
+
+static void
+terminal_ours_1 PARAMS ((int));
+
+/* Record terminal status separately for debugger and inferior. */
+
+static serial_t stdin_serial;
+
+/* TTY state for the inferior. We save it whenever the inferior stops, and
+ restore it when it resumes. */
+static serial_ttystate inferior_ttystate;
+
+/* Our own tty state, which we restore every time we need to deal with the
+ terminal. We only set it once, when GDB first starts. The settings of
+ flags which readline saves and restores and unimportant. */
+static serial_ttystate our_ttystate;
+
+/* fcntl flags for us and the inferior. Saved and restored just like
+ {our,inferior}_ttystate. */
+static int tflags_inferior;
+static int tflags_ours;
+
+#ifdef PROCESS_GROUP_TYPE
+/* Process group for us and the inferior. Saved and restored just like
+ {our,inferior}_ttystate. */
+PROCESS_GROUP_TYPE our_process_group;
+PROCESS_GROUP_TYPE inferior_process_group;
+#endif
+
+/* While the inferior is running, we want SIGINT and SIGQUIT to go to the
+ inferior only. If we have job control, that takes care of it. If not,
+ we save our handlers in these two variables and set SIGINT and SIGQUIT
+ to SIG_IGN. */
+static void (*sigint_ours) ();
+static void (*sigquit_ours) ();
+
+/* The name of the tty (from the `tty' command) that we gave to the inferior
+ when it was last started. */
+
+static char *inferior_thisrun_terminal;
+
+/* Nonzero if our terminal settings are in effect. Zero if the
+ inferior's settings are in effect. Ignored if !gdb_has_a_terminal
+ (). */
+
+static int terminal_is_ours;
+
+enum {yes, no, have_not_checked} gdb_has_a_terminal_flag = have_not_checked;
+
+/* Does GDB have a terminal (on stdin)? */
+int
+gdb_has_a_terminal ()
+{
+ switch (gdb_has_a_terminal_flag)
+ {
+ case yes:
+ return 1;
+ case no:
+ return 0;
+ case have_not_checked:
+ /* Get all the current tty settings (including whether we have a tty at
+ all!). Can't do this in _initialize_inflow because SERIAL_FDOPEN
+ won't work until the serial_ops_list is initialized. */
+
+#ifdef F_GETFL
+ tflags_ours = fcntl (0, F_GETFL, 0);
+#endif
+
+ gdb_has_a_terminal_flag = no;
+ stdin_serial = SERIAL_FDOPEN (0);
+ if (stdin_serial != NULL)
+ {
+ our_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
+
+ if (our_ttystate != NULL)
+ {
+ gdb_has_a_terminal_flag = yes;
+#ifdef HAVE_TERMIOS
+ our_process_group = tcgetpgrp (0);
+#endif
+#ifdef HAVE_SGTTY
+ ioctl (0, TIOCGPGRP, &our_process_group);
+#endif
+ }
+ }
+
+ return gdb_has_a_terminal_flag == yes;
+ default:
+ /* "Can't happen". */
+ return 0;
+ }
+}
+
+/* Macro for printing errors from ioctl operations */
+
+#define OOPSY(what) \
+ if (result == -1) \
+ fprintf_unfiltered(gdb_stderr, "[%s failed in terminal_inferior: %s]\n", \
+ what, strerror (errno))
+
+static void terminal_ours_1 PARAMS ((int));
+
+/* Initialize the terminal settings we record for the inferior,
+ before we actually run the inferior. */
+
+void
+terminal_init_inferior ()
+{
+ if (gdb_has_a_terminal ())
+ {
+ /* We could just as well copy our_ttystate (if we felt like adding
+ a new function SERIAL_COPY_TTY_STATE). */
+ if (inferior_ttystate)
+ 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
+ before the program runs, as it needs to be), we install the new
+ process group. */
+ terminal_is_ours = 1;
+ }
+}
+
+/* Put the inferior's terminal settings into effect.
+ This is preparation for starting or resuming the inferior. */
+
+void
+terminal_inferior ()
+{
+ if (gdb_has_a_terminal () && terminal_is_ours
+ && inferior_thisrun_terminal == 0)
+ {
+ int result;
+
+#ifdef F_GETFL
+ /* Is there a reason this is being done twice? It happens both
+ places we use F_SETFL, so I'm inclined to think perhaps there
+ is some reason, however perverse. Perhaps not though... */
+ result = fcntl (0, F_SETFL, tflags_inferior);
+ result = fcntl (0, F_SETFL, tflags_inferior);
+ OOPSY ("fcntl F_SETFL");
+#endif
+
+ /* Because we were careful to not change in or out of raw mode in
+ terminal_ours, we will not change in our out of raw mode with
+ this call, so we don't flush any input. */
+ result = SERIAL_SET_TTY_STATE (stdin_serial, inferior_ttystate);
+ OOPSY ("setting tty state");
+
+ if (!job_control)
+ {
+ sigint_ours = (void (*) ()) signal (SIGINT, SIG_IGN);
+ sigquit_ours = (void (*) ()) signal (SIGQUIT, SIG_IGN);
+ }
+
+ /* If attach_flag is set, we don't know whether we are sharing a
+ terminal with the inferior or not. (attaching a process
+ without a terminal is one case where we do not; attaching a
+ process which we ran from the same shell as GDB via `&' is
+ one case where we do, I think (but perhaps this is not
+ `sharing' in the sense that we need to save and restore tty
+ state)). I don't know if there is any way to tell whether we
+ are sharing a terminal. So what we do is to go through all
+ the saving and restoring of the tty state, but ignore errors
+ setting the process group, which will happen if we are not
+ sharing a terminal). */
+
+ if (job_control)
+ {
+#ifdef HAVE_TERMIOS
+ result = tcsetpgrp (0, inferior_process_group);
+ if (!attach_flag)
+ OOPSY ("tcsetpgrp");
+#endif
+
+#ifdef HAVE_SGTTY
+ result = ioctl (0, TIOCSPGRP, &inferior_process_group);
+ if (!attach_flag)
+ OOPSY ("TIOCSPGRP");
+#endif
+ }
+
+ }
+ terminal_is_ours = 0;
+}
+
+/* Put some of our terminal settings into effect,
+ enough to get proper results from our output,
+ but do not change into or out of RAW mode
+ so that no input is discarded.
+
+ After doing this, either terminal_ours or terminal_inferior
+ should be called to get back to a normal state of affairs. */
+
+void
+terminal_ours_for_output ()
+{
+ terminal_ours_1 (1);
+}
+
+/* Put our terminal settings into effect.
+ First record the inferior's terminal settings
+ so they can be restored properly later. */
+
+void
+terminal_ours ()
+{
+ terminal_ours_1 (0);
+}
+
+/* output_only is not used, and should not be used unless we introduce
+ separate terminal_is_ours and terminal_is_ours_for_output
+ flags. */
+
+static void
+terminal_ours_1 (output_only)
+ int output_only;
+{
+ /* Checking inferior_thisrun_terminal is necessary so that
+ if GDB is running in the background, it won't block trying
+ to do the ioctl()'s below. Checking gdb_has_a_terminal
+ avoids attempting all the ioctl's when running in batch. */
+ if (inferior_thisrun_terminal != 0 || gdb_has_a_terminal () == 0)
+ return;
+
+ if (!terminal_is_ours)
+ {
+ /* Ignore this signal since it will happen when we try to set the
+ pgrp. */
+ void (*osigttou) ();
+ int result;
+
+ terminal_is_ours = 1;
+
+#ifdef SIGTTOU
+ if (job_control)
+ osigttou = (void (*) ()) signal (SIGTTOU, SIG_IGN);
+#endif
+
+ if (inferior_ttystate)
+ free (inferior_ttystate);
+ inferior_ttystate = SERIAL_GET_TTY_STATE (stdin_serial);
+#ifdef HAVE_TERMIOS
+ inferior_process_group = tcgetpgrp (0);
+#endif
+#ifdef HAVE_SGTTY
+ ioctl (0, TIOCGPGRP, &inferior_process_group);
+#endif
+
+ /* 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.
+ 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
+ regardless of output_only, because we don't have separate
+ 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);
+
+ if (job_control)
+ {
+#ifdef HAVE_TERMIOS
+ result = tcsetpgrp (0, our_process_group);
+#if 0
+ /* This fails on Ultrix with EINVAL if you run the testsuite
+ in the background with nohup, and then log out. GDB never
+ used to check for an error here, so perhaps there are other
+ such situations as well. */
+ if (result == -1)
+ fprintf_unfiltered (gdb_stderr, "[tcsetpgrp failed in terminal_ours: %s]\n",
+ strerror (errno));
+#endif
+#endif /* termios */
+
+#ifdef HAVE_SGTTY
+ result = ioctl (0, TIOCSPGRP, &our_process_group);
+#endif
+ }
+
+#ifdef SIGTTOU
+ if (job_control)
+ signal (SIGTTOU, osigttou);
+#endif
+
+ if (!job_control)
+ {
+ signal (SIGINT, sigint_ours);
+ signal (SIGQUIT, sigquit_ours);
+ }
+
+#ifdef F_GETFL
+ tflags_inferior = fcntl (0, F_GETFL, 0);
+
+ /* Is there a reason this is being done twice? It happens both
+ places we use F_SETFL, so I'm inclined to think perhaps there
+ is some reason, however perverse. Perhaps not though... */
+ result = fcntl (0, F_SETFL, tflags_ours);
+ result = fcntl (0, F_SETFL, tflags_ours);
+#endif
+
+ result = result; /* lint */
+ }
+}
+
+/* ARGSUSED */
+void
+term_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ target_terminal_info (arg, from_tty);
+}
+
+/* ARGSUSED */
+void
+child_terminal_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (!gdb_has_a_terminal ())
+ {
+ printf_filtered ("This GDB does not control a terminal.\n");
+ return;
+ }
+
+ printf_filtered ("Inferior's terminal status (currently saved by GDB):\n");
+
+ /* First the fcntl flags. */
+ {
+ int flags;
+
+ flags = tflags_inferior;
+
+ printf_filtered ("File descriptor flags = ");
+
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+ /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
+ switch (flags & (O_ACCMODE))
+ {
+ case O_RDONLY: printf_filtered ("O_RDONLY"); break;
+ case O_WRONLY: printf_filtered ("O_WRONLY"); break;
+ case O_RDWR: printf_filtered ("O_RDWR"); break;
+ }
+ flags &= ~(O_ACCMODE);
+
+#ifdef O_NONBLOCK
+ if (flags & O_NONBLOCK)
+ printf_filtered (" | O_NONBLOCK");
+ flags &= ~O_NONBLOCK;
+#endif
+
+#if defined (O_NDELAY)
+ /* If O_NDELAY and O_NONBLOCK are defined to the same thing, we will
+ print it as O_NONBLOCK, which is good cause that is what POSIX
+ has, and the flag will already be cleared by the time we get here. */
+ if (flags & O_NDELAY)
+ printf_filtered (" | O_NDELAY");
+ flags &= ~O_NDELAY;
+#endif
+
+ if (flags & O_APPEND)
+ printf_filtered (" | O_APPEND");
+ flags &= ~O_APPEND;
+
+#if defined (O_BINARY)
+ if (flags & O_BINARY)
+ printf_filtered (" | O_BINARY");
+ flags &= ~O_BINARY;
+#endif
+
+ if (flags)
+ printf_filtered (" | 0x%x", flags);
+ printf_filtered ("\n");
+ }
+
+#ifdef PROCESS_GROUP_TYPE
+ printf_filtered ("Process group = %d\n", inferior_process_group);
+#endif
+
+ SERIAL_PRINT_TTY_STATE (stdin_serial, inferior_ttystate);
+}
+
+/* NEW_TTY_PREFORK is called before forking a new child process,
+ so we can record the state of ttys in the child to be formed.
+ TTYNAME is null if we are to share the terminal with gdb;
+ or points to a string containing the name of the desired tty.
+
+ NEW_TTY is called in new child processes under Unix, which will
+ become debugger target processes. This actually switches to
+ the terminal specified in the NEW_TTY_PREFORK call. */
+
+void
+new_tty_prefork (ttyname)
+ char *ttyname;
+{
+ /* Save the name for later, for determining whether we and the child
+ are sharing a tty. */
+ inferior_thisrun_terminal = ttyname;
+}
+
+void
+new_tty ()
+{
+ register int tty;
+
+ if (inferior_thisrun_terminal == 0)
+ return;
+#if !defined(__GO32__) && !defined(__WIN32__)
+#ifdef TIOCNOTTY
+ /* Disconnect the child process from our controlling terminal. On some
+ systems (SVR4 for example), this may cause a SIGTTOU, so temporarily
+ ignore SIGTTOU. */
+ tty = open("/dev/tty", O_RDWR);
+ if (tty > 0)
+ {
+ void (*osigttou) ();
+
+ osigttou = (void (*)()) signal(SIGTTOU, SIG_IGN);
+ ioctl(tty, TIOCNOTTY, 0);
+ close(tty);
+ signal(SIGTTOU, osigttou);
+ }
+#endif
+
+ /* Now open the specified new terminal. */
+
+#ifdef USE_O_NOCTTY
+ tty = open(inferior_thisrun_terminal, O_RDWR | O_NOCTTY);
+#else
+ tty = open(inferior_thisrun_terminal, O_RDWR);
+#endif
+ if (tty == -1)
+ {
+ print_sys_errmsg (inferior_thisrun_terminal, errno);
+ _exit(1);
+ }
+
+ /* Avoid use of dup2; doesn't exist on all systems. */
+ if (tty != 0)
+ { close (0); dup (tty); }
+ if (tty != 1)
+ { close (1); dup (tty); }
+ if (tty != 2)
+ { close (2); dup (tty); }
+ if (tty > 2)
+ close(tty);
+#endif /* !go32 && !win32*/
+}
+
+/* Kill the inferior process. Make us have no inferior. */
+
+/* ARGSUSED */
+static void
+kill_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ /* FIXME: This should not really be inferior_pid (or target_has_execution).
+ It should be a distinct flag that indicates that a target is active, cuz
+ some targets don't have processes! */
+
+ if (inferior_pid == 0)
+ error ("The program is not being run.");
+ if (!query ("Kill the program being debugged? "))
+ error ("Not confirmed.");
+ target_kill ();
+
+ init_thread_list(); /* Destroy thread info */
+
+ /* Killing off the inferior can leave us with a core file. If so,
+ print the state we are left in. */
+ if (target_has_stack) {
+ printf_filtered ("In %s,\n", target_longname);
+ if (selected_frame == NULL)
+ fputs_filtered ("No selected stack frame.\n", gdb_stdout);
+ else
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+ }
+}
+
+/* Call set_sigint_trap when you need to pass a signal on to an attached
+ process when handling SIGINT */
+
+/* ARGSUSED */
+static void
+pass_signal (signo)
+ int signo;
+{
+ kill (inferior_pid, SIGINT);
+}
+
+static void (*osig)();
+
+void
+set_sigint_trap()
+{
+ if (attach_flag || inferior_thisrun_terminal)
+ {
+ osig = (void (*) ()) signal (SIGINT, pass_signal);
+ }
+}
+
+void
+clear_sigint_trap()
+{
+ if (attach_flag || inferior_thisrun_terminal)
+ {
+ signal (SIGINT, osig);
+ }
+}
+
+#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN)
+static void (*old_sigio) ();
+
+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
+ setpgid or setpgrp might not exist on a system without job control.
+ It might be considered misplaced (on the other hand, process groups and
+ job control are closely related to ttys).
+
+ For a more clean implementation, in libiberty, put a setpgid which merely
+ calls setpgrp and a setpgrp which does nothing (any system with job control
+ will have one or the other). */
+int
+gdb_setpgid ()
+{
+ int retval = 0;
+
+ if (job_control)
+ {
+#if defined (NEED_POSIX_SETPGID) || (defined (HAVE_TERMIOS) && defined (HAVE_SETPGID))
+ /* setpgid (0, 0) is supposed to work and mean the same thing as
+ this, but on Ultrix 4.2A it fails with EPERM (and
+ setpgid (getpid (), getpid ()) succeeds). */
+ retval = setpgid (getpid (), getpid ());
+#else
+#if defined (TIOCGPGRP)
+#if defined(USG) && !defined(SETPGRP_ARGS)
+ retval = setpgrp ();
+#else
+ retval = setpgrp (getpid (), getpid ());
+#endif /* USG */
+#endif /* TIOCGPGRP. */
+#endif /* NEED_POSIX_SETPGID */
+ }
+ return retval;
+}
+
+void
+_initialize_inflow ()
+{
+ add_info ("terminal", term_info,
+ "Print inferior's saved terminal status.");
+
+ add_com ("kill", class_run, kill_command,
+ "Kill execution of program being debugged.");
+
+ inferior_pid = 0;
+
+ terminal_is_ours = 1;
+
+ /* OK, figure out whether we have job control. If neither termios nor
+ sgtty (i.e. termio or go32), leave job_control 0. */
+
+#if defined (HAVE_TERMIOS)
+ /* Do all systems with termios have the POSIX way of identifying job
+ control? I hope so. */
+#ifdef _POSIX_JOB_CONTROL
+ job_control = 1;
+#else
+#ifdef _SC_JOB_CONTROL
+ job_control = sysconf (_SC_JOB_CONTROL);
+#else
+ job_control = 0; /* have to assume the worst */
+#endif /* _SC_JOB_CONTROL */
+#endif /* _POSIX_JOB_CONTROL */
+#endif /* HAVE_TERMIOS */
+
+#ifdef HAVE_SGTTY
+#ifdef TIOCGPGRP
+ job_control = 1;
+#else
+ job_control = 0;
+#endif /* TIOCGPGRP */
+#endif /* sgtty */
+}
diff --git a/contrib/gdb/gdb/infptrace.c b/contrib/gdb/gdb/infptrace.c
new file mode 100644
index 0000000..28210e4
--- /dev/null
+++ b/contrib/gdb/gdb/infptrace.c
@@ -0,0 +1,534 @@
+/* Low level Unix child interface to ptrace, for GDB when running under Unix.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdb_string.h"
+#include "wait.h"
+#include "command.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+
+#ifndef NO_PTRACE_H
+#ifdef PTRACE_IN_WRONG_PLACE
+#include <ptrace.h>
+#else
+#include <sys/ptrace.h>
+#endif
+#endif /* NO_PTRACE_H */
+
+#if !defined (PT_READ_I)
+#define PT_READ_I 1 /* Read word from text space */
+#endif
+#if !defined (PT_READ_D)
+#define PT_READ_D 2 /* Read word from data space */
+#endif
+#if !defined (PT_READ_U)
+#define PT_READ_U 3 /* Read word from kernel user struct */
+#endif
+#if !defined (PT_WRITE_I)
+#define PT_WRITE_I 4 /* Write word to text space */
+#endif
+#if !defined (PT_WRITE_D)
+#define PT_WRITE_D 5 /* Write word to data space */
+#endif
+#if !defined (PT_WRITE_U)
+#define PT_WRITE_U 6 /* Write word to kernel user struct */
+#endif
+#if !defined (PT_CONTINUE)
+#define PT_CONTINUE 7 /* Continue after signal */
+#endif
+#if !defined (PT_STEP)
+#define PT_STEP 9 /* Set flag for single stepping */
+#endif
+#if !defined (PT_KILL)
+#define PT_KILL 8 /* Send child a SIGKILL signal */
+#endif
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+#ifndef PT_DETACH
+#define PT_DETACH PTRACE_DETACH
+#endif
+
+#include "gdbcore.h"
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#if 0
+/* Don't think this is used anymore. On the sequent (not sure whether it's
+ dynix or ptx or both), it is included unconditionally by sys/user.h and
+ not protected against multiple inclusion. */
+#include "gdb_stat.h"
+#endif
+
+#if !defined (FETCH_INFERIOR_REGISTERS)
+#include <sys/user.h> /* Probably need to poke the user structure */
+#if defined (KERNEL_U_ADDR_BSD)
+#include <a.out.h> /* For struct nlist */
+#endif /* KERNEL_U_ADDR_BSD. */
+#endif /* !FETCH_INFERIOR_REGISTERS */
+
+
+/* This function simply calls ptrace with the given arguments.
+ It exists so that all calls to ptrace are isolated in this
+ machine-dependent file. */
+int
+call_ptrace (request, pid, addr, data)
+ int request, pid;
+ PTRACE_ARG3_TYPE addr;
+ int data;
+{
+ return ptrace (request, pid, addr, data
+#if defined (FIVE_ARG_PTRACE)
+ /* Deal with HPUX 8.0 braindamage. We never use the
+ calls which require the fifth argument. */
+ , 0
+#endif
+ );
+}
+
+#if defined (DEBUG_PTRACE) || defined (FIVE_ARG_PTRACE)
+/* For the rest of the file, use an extra level of indirection */
+/* This lets us breakpoint usefully on call_ptrace. */
+#define ptrace call_ptrace
+#endif
+
+void
+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. 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. */
+
+void
+child_resume (pid, step, signal)
+ int pid;
+ int step;
+ 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
+ it was. (If GDB wanted it to start some other way, we have already
+ written a new PC value to the child.)
+
+ If this system does not support PT_STEP, a higher level function will
+ have called single_step() to transmute the step request into a
+ continue request (by setting breakpoints on all possible successor
+ instructions), so we don't have to worry about that here. */
+
+ if (step)
+ ptrace (PT_STEP, pid, (PTRACE_ARG3_TYPE) 1,
+ target_signal_to_host (signal));
+ else
+ 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
+/* Start debugging the process whose number is PID. */
+int
+attach (pid)
+ int pid;
+{
+ errno = 0;
+ ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0);
+ if (errno)
+ perror_with_name ("ptrace");
+ attach_flag = 1;
+ return pid;
+}
+
+/* Stop debugging the process whose number is PID
+ and continue it with signal number SIGNAL.
+ SIGNAL = 0 means just continue it. */
+
+void
+detach (signal)
+ int signal;
+{
+ errno = 0;
+ ptrace (PT_DETACH, inferior_pid, (PTRACE_ARG3_TYPE) 1, signal);
+ if (errno)
+ perror_with_name ("ptrace");
+ attach_flag = 0;
+}
+#endif /* ATTACH_DETACH */
+
+/* Default the type of the ptrace transfer to int. */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+/* 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) && !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";
+ names[1].n_un.n_name = NULL;
+ if (nlist ("/vmunix", names) == 0)
+ 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)
+#endif
+
+/* U_REGS_OFFSET is the offset of the registers within the u area. */
+#if !defined (U_REGS_OFFSET)
+#define U_REGS_OFFSET \
+ ptrace (PT_READ_U, inferior_pid, \
+ (PTRACE_ARG3_TYPE) (offsetof (struct user, u_ar0)), 0) \
+ - KERNEL_U_ADDR
+#endif
+
+/* Registers we shouldn't try to fetch. */
+#if !defined (CANNOT_FETCH_REGISTER)
+#define CANNOT_FETCH_REGISTER(regno) 0
+#endif
+
+/* Fetch one register. */
+
+static void
+fetch_register (regno)
+ int regno;
+{
+ /* 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;
+
+ /* Offset of registers within the u area. */
+ unsigned int offset;
+
+ if (CANNOT_FETCH_REGISTER (regno))
+ {
+ memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
+ supply_register (regno, buf);
+ return;
+ }
+
+ offset = U_REGS_OFFSET;
+
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ *(PTRACE_XFER_TYPE *) &buf[i] = ptrace (PT_READ_U, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (PTRACE_XFER_TYPE);
+ if (errno != 0)
+ {
+ sprintf (mess, "reading register %s (#%d)", reg_names[regno], regno);
+ perror_with_name (mess);
+ }
+ }
+ supply_register (regno, buf);
+}
+
+
+/* Fetch all registers, or just one, from the child process. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int numregs;
+
+ if (regno == -1)
+ {
+ numregs = ARCH_NUM_REGS;
+ for (regno = 0; regno < numregs; regno++)
+ fetch_register (regno);
+ }
+ else
+ fetch_register (regno);
+}
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ /* This isn't really an address. But ptrace thinks of it as one. */
+ CORE_ADDR regaddr;
+ char buf[80];
+ register int i, numregs;
+
+ unsigned int offset = U_REGS_OFFSET;
+
+ if (regno >= 0)
+ {
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(PTRACE_XFER_TYPE);
+ }
+ }
+ else
+ {
+ numregs = ARCH_NUM_REGS;
+ for (regno = 0; regno < numregs; regno++)
+ {
+ if (CANNOT_STORE_REGISTER (regno))
+ continue;
+ regaddr = register_addr (regno, offset);
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof(PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_U, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ *(PTRACE_XFER_TYPE *) &registers[REGISTER_BYTE (regno) + i]);
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d(%d)", regno, i);
+ perror_with_name (buf);
+ }
+ regaddr += sizeof(PTRACE_XFER_TYPE);
+ }
+ }
+ }
+}
+#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
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. Copy to inferior if
+ WRITE is nonzero.
+
+ Returns the length copied, which is either the LEN argument or zero.
+ This xfer function does not do partial moves, since child_ops
+ doesn't allow memory operations to cross below us in the target stack
+ anyway. */
+
+int
+child_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (PTRACE_XFER_TYPE);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+ / sizeof (PTRACE_XFER_TYPE);
+ /* Allocate buffer of that many longwords. */
+ register PTRACE_XFER_TYPE *buffer
+ = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = ptrace (PT_READ_I, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ 0);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = ptrace (PT_READ_I, inferior_pid,
+ ((PTRACE_ARG3_TYPE)
+ (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE))),
+ 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ myaddr,
+ len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WRITE_D, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ buffer[i]);
+ if (errno)
+ {
+ /* Using the appropriate one (I or D) is necessary for
+ Gould NP1, at least. */
+ errno = 0;
+ ptrace (PT_WRITE_I, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ buffer[i]);
+ }
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ buffer[i] = ptrace (PT_READ_I, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr,
+ (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ len);
+ }
+ return len;
+}
+
+
+static void
+udot_info ()
+{
+ int udot_off; /* Offset into user struct */
+ int udot_val; /* Value from user struct at udot_off */
+ char mess[128]; /* For messages */
+
+ if (!target_has_execution)
+ {
+ error ("The program is not being run.");
+ }
+
+#if !defined (KERNEL_U_SIZE)
+
+ /* Adding support for this command is easy. Typically you just add a
+ routine, called "kernel_u_size" that returns the size of the user
+ struct, to the appropriate *-nat.c file and then add to the native
+ config file "#define KERNEL_U_SIZE kernel_u_size()" */
+ error ("Don't know how large ``struct user'' is in this version of gdb.");
+
+#else
+
+ for (udot_off = 0; udot_off < KERNEL_U_SIZE; udot_off += sizeof (udot_val))
+ {
+ if ((udot_off % 24) == 0)
+ {
+ if (udot_off > 0)
+ {
+ printf_filtered ("\n");
+ }
+ printf_filtered ("%04x:", udot_off);
+ }
+ udot_val = ptrace (PT_READ_U, inferior_pid, (PTRACE_ARG3_TYPE) udot_off, 0);
+ if (errno != 0)
+ {
+ sprintf (mess, "\nreading user struct at offset 0x%x", udot_off);
+ perror_with_name (mess);
+ }
+ /* Avoid using nonportable (?) "*" in print specs */
+ printf_filtered (sizeof (int) == 4 ? " 0x%08x" : " 0x%16x", udot_val);
+ }
+ printf_filtered ("\n");
+
+#endif
+}
+#endif /* !defined (CHILD_XFER_MEMORY). */
+
+
+void
+_initialize_infptrace ()
+{
+#if !defined (CHILD_XFER_MEMORY)
+ add_info ("udot", udot_info,
+ "Print contents of kernel ``struct user'' for current child.");
+#endif
+}
diff --git a/contrib/gdb/gdb/infrun.c b/contrib/gdb/gdb/infrun.c
new file mode 100644
index 0000000..90dbd8e
--- /dev/null
+++ b/contrib/gdb/gdb/infrun.c
@@ -0,0 +1,2224 @@
+/* Target-struct-independent code to start (run) and stop an inferior process.
+ Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "breakpoint.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "thread.h"
+#include "annotate.h"
+
+#include <signal.h>
+
+/* unistd.h is needed to #define X_OK */
+#ifdef USG
+#include <unistd.h>
+#else
+#include <sys/file.h>
+#endif
+
+/* Prototypes for local functions */
+
+static void signals_info PARAMS ((char *, int));
+
+static void handle_command PARAMS ((char *, int));
+
+static void sig_print_info PARAMS ((enum target_signal));
+
+static void sig_print_header PARAMS ((void));
+
+static void resume_cleanups PARAMS ((int));
+
+static int hook_stop_stub PARAMS ((char *));
+
+/* GET_LONGJMP_TARGET returns the PC at which longjmp() will resume the
+ program. It needs to examine the jmp_buf argument and extract the PC
+ from it. The return value is non-zero on success, zero otherwise. */
+
+#ifndef GET_LONGJMP_TARGET
+#define GET_LONGJMP_TARGET(PC_ADDR) 0
+#endif
+
+
+/* Some machines have trampoline code that sits between function callers
+ and the actual functions themselves. If this machine doesn't have
+ such things, disable their processing. */
+
+#ifndef SKIP_TRAMPOLINE_CODE
+#define SKIP_TRAMPOLINE_CODE(pc) 0
+#endif
+
+/* Dynamic function trampolines are similar to solib trampolines in that they
+ are between the caller and the callee. The difference is that when you
+ enter a dynamic trampoline, you can't determine the callee's address. Some
+ (usually complex) code needs to run in the dynamic trampoline to figure out
+ the callee's address. This macro is usually called twice. First, when we
+ enter the trampoline (looks like a normal function call at that point). It
+ should return the PC of a point within the trampoline where the callee's
+ address is known. Second, when we hit the breakpoint, this routine returns
+ the callee's address. At that point, things proceed as per a step resume
+ breakpoint. */
+
+#ifndef DYNAMIC_TRAMPOLINE_NEXTPC
+#define DYNAMIC_TRAMPOLINE_NEXTPC(pc) 0
+#endif
+
+/* For SVR4 shared libraries, each call goes through a small piece of
+ trampoline code in the ".plt" section. IN_SOLIB_CALL_TRAMPOLINE evaluates
+ to nonzero if we are current stopped in one of these. */
+
+#ifndef IN_SOLIB_CALL_TRAMPOLINE
+#define IN_SOLIB_CALL_TRAMPOLINE(pc,name) 0
+#endif
+
+/* In some shared library schemes, the return path from a shared library
+ call may need to go through a trampoline too. */
+
+#ifndef IN_SOLIB_RETURN_TRAMPOLINE
+#define IN_SOLIB_RETURN_TRAMPOLINE(pc,name) 0
+#endif
+
+/* On some systems, the PC may be left pointing at an instruction that won't
+ actually be executed. This is usually indicated by a bit in the PSW. If
+ we find ourselves in such a state, then we step the target beyond the
+ nullified instruction before returning control to the user so as to avoid
+ confusion. */
+
+#ifndef INSTRUCTION_NULLIFIED
+#define INSTRUCTION_NULLIFIED 0
+#endif
+
+/* Tables of how to react to signals; the user sets them. */
+
+static unsigned char *signal_stop;
+static unsigned char *signal_print;
+static unsigned char *signal_program;
+
+#define SET_SIGS(nsigs,sigs,flags) \
+ do { \
+ int signum = (nsigs); \
+ while (signum-- > 0) \
+ if ((sigs)[signum]) \
+ (flags)[signum] = 1; \
+ } while (0)
+
+#define UNSET_SIGS(nsigs,sigs,flags) \
+ do { \
+ int signum = (nsigs); \
+ while (signum-- > 0) \
+ if ((sigs)[signum]) \
+ (flags)[signum] = 0; \
+ } while (0)
+
+
+/* Command list pointer for the "stop" placeholder. */
+
+static struct cmd_list_element *stop_command;
+
+/* Nonzero if breakpoints are now inserted in the inferior. */
+
+static int breakpoints_inserted;
+
+/* Function inferior was in as of last step command. */
+
+static struct symbol *step_start_function;
+
+/* Nonzero if we are expecting a trace trap and should proceed from it. */
+
+static int trap_expected;
+
+/* Nonzero if we want to give control to the user when we're notified
+ of shared library events by the dynamic linker. */
+static int stop_on_solib_events;
+
+#ifdef HP_OS_BUG
+/* Nonzero if the next time we try to continue the inferior, it will
+ step one instruction and generate a spurious trace trap.
+ This is used to compensate for a bug in HP-UX. */
+
+static int trap_expected_after_continue;
+#endif
+
+/* Nonzero means expecting a trace trap
+ and should stop the inferior and return silently when it happens. */
+
+int stop_after_trap;
+
+/* Nonzero means expecting a trap and caller will handle it themselves.
+ It is used after attach, due to attaching to a process;
+ when running in the shell before the child program has been exec'd;
+ and when running some kinds of remote stuff (FIXME?). */
+
+int stop_soon_quietly;
+
+/* Nonzero if proceed is being used for a "finish" command or a similar
+ situation when stop_registers should be saved. */
+
+int proceed_to_finish;
+
+/* Save register contents here when about to pop a stack dummy frame,
+ if-and-only-if proceed_to_finish is set.
+ Thus this contains the return value from the called function (assuming
+ values are returned in a register). */
+
+char stop_registers[REGISTER_BYTES];
+
+/* Nonzero if program stopped due to error trying to insert breakpoints. */
+
+static int breakpoints_failed;
+
+/* Nonzero after stop if current stack frame should be printed. */
+
+static int stop_print_frame;
+
+#ifdef NO_SINGLE_STEP
+extern int one_stepped; /* From machine dependent code */
+extern void single_step (); /* Same. */
+#endif /* NO_SINGLE_STEP */
+
+extern void write_pc_pid PARAMS ((CORE_ADDR, int));
+
+
+/* Things to clean up if we QUIT out of resume (). */
+/* ARGSUSED */
+static void
+resume_cleanups (arg)
+ int arg;
+{
+ normal_stop ();
+}
+
+/* Resume the inferior, but allow a QUIT. This is useful if the user
+ wants to interrupt some lengthy single-stepping operation
+ (for child processes, the SIGINT goes to the inferior, and so
+ we get a SIGINT random_signal, but for remote debugging and perhaps
+ other targets, that's not true).
+
+ STEP nonzero if we should step (zero to continue instead).
+ SIG is the signal to give the inferior (zero for none). */
+void
+resume (step, sig)
+ int step;
+ enum target_signal sig;
+{
+ struct cleanup *old_cleanups = make_cleanup (resume_cleanups, 0);
+ QUIT;
+
+#ifdef CANNOT_STEP_BREAKPOINT
+ /* Most targets can step a breakpoint instruction, thus executing it
+ normally. But if this one cannot, just continue and we will hit
+ it anyway. */
+ if (step && breakpoints_inserted && breakpoint_here_p (read_pc ()))
+ step = 0;
+#endif
+
+#ifdef NO_SINGLE_STEP
+ if (step) {
+ single_step(sig); /* Do it the hard way, w/temp breakpoints */
+ step = 0; /* ...and don't ask hardware to do it. */
+ }
+#endif
+
+ /* Handle any optimized stores to the inferior NOW... */
+#ifdef DO_DEFERRED_STORES
+ DO_DEFERRED_STORES;
+#endif
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ target_resume (-1, step, sig);
+ discard_cleanups (old_cleanups);
+}
+
+
+/* Clear out all variables saying what to do when inferior is continued.
+ First do this, then set the ones you want, then call `proceed'. */
+
+void
+clear_proceed_status ()
+{
+ trap_expected = 0;
+ step_range_start = 0;
+ step_range_end = 0;
+ step_frame_address = 0;
+ step_over_calls = -1;
+ stop_after_trap = 0;
+ stop_soon_quietly = 0;
+ proceed_to_finish = 0;
+ breakpoint_proceeded = 1; /* We're about to proceed... */
+
+ /* Discard any remaining commands or status from previous stop. */
+ bpstat_clear (&stop_bpstat);
+}
+
+/* Basic routine for continuing the program in various fashions.
+
+ ADDR is the address to resume at, or -1 for resume where stopped.
+ SIGGNAL is the signal to give it, or 0 for none,
+ or -1 for act according to how it stopped.
+ STEP is nonzero if should trap after one instruction.
+ -1 means return after that and print nothing.
+ You should probably set various step_... variables
+ before calling here, if you are stepping.
+
+ You should call clear_proceed_status before calling proceed. */
+
+void
+proceed (addr, siggnal, step)
+ CORE_ADDR addr;
+ enum target_signal siggnal;
+ int step;
+{
+ int oneproc = 0;
+
+ if (step > 0)
+ step_start_function = find_pc_function (read_pc ());
+ if (step < 0)
+ stop_after_trap = 1;
+
+ if (addr == (CORE_ADDR)-1)
+ {
+ /* If there is a breakpoint at the address we will resume at,
+ step one instruction before inserting breakpoints
+ so that we do not stop right away. */
+
+ 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 */
+
+#ifdef HP_OS_BUG
+ if (trap_expected_after_continue)
+ {
+ /* If (step == 0), a trap will be automatically generated after
+ the first instruction is executed. Force step one
+ instruction to clear this condition. This should not occur
+ if step is nonzero, but it is harmless in that case. */
+ oneproc = 1;
+ trap_expected_after_continue = 0;
+ }
+#endif /* HP_OS_BUG */
+
+ if (oneproc)
+ /* We will get a trace trap after one instruction.
+ Continue it automatically and insert breakpoints then. */
+ trap_expected = 1;
+ else
+ {
+ int temp = insert_breakpoints ();
+ if (temp)
+ {
+ print_sys_errmsg ("ptrace", temp);
+ error ("Cannot insert breakpoints.\n\
+The same program may be running in another process.");
+ }
+ breakpoints_inserted = 1;
+ }
+
+ 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 (!signal_program[stop_signal])
+ stop_signal = TARGET_SIGNAL_0;
+
+ annotate_starting ();
+
+ /* Make sure that output from GDB appears before output from the
+ inferior. */
+ gdb_flush (gdb_stdout);
+
+ /* Resume inferior. */
+ resume (oneproc || step || bpstat_should_step (), stop_signal);
+
+ /* Wait for it to stop (if not standalone)
+ and in any case decode why it stopped, and act accordingly. */
+
+ wait_for_inferior ();
+ normal_stop ();
+}
+
+/* Record the pc and sp of the program the last time it stopped.
+ These are just used internally by wait_for_inferior, but need
+ to be preserved over calls to it and cleared when the inferior
+ is started. */
+static CORE_ADDR prev_pc;
+static CORE_ADDR prev_func_start;
+static char *prev_func_name;
+
+
+/* Start remote-debugging of a machine over a serial link. */
+
+void
+start_remote ()
+{
+ init_thread_list ();
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ trap_expected = 0;
+ wait_for_inferior ();
+ normal_stop ();
+}
+
+/* Initialize static vars when a new inferior begins. */
+
+void
+init_wait_for_inferior ()
+{
+ /* These are meaningless until the first time through wait_for_inferior. */
+ prev_pc = 0;
+ prev_func_start = 0;
+ prev_func_name = NULL;
+
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 0;
+#endif
+ breakpoints_inserted = 0;
+ breakpoint_init_inferior ();
+
+ /* Don't confuse first call to proceed(). */
+ stop_signal = TARGET_SIGNAL_0;
+}
+
+static void
+delete_breakpoint_current_contents (arg)
+ PTR arg;
+{
+ struct breakpoint **breakpointp = (struct breakpoint **)arg;
+ if (*breakpointp != NULL)
+ delete_breakpoint (*breakpointp);
+}
+
+/* Wait for control to return from inferior to debugger.
+ If inferior gets a signal, we may decide to start it up again
+ instead of returning. That is why there is a loop in this function.
+ When this function actually returns it means the inferior
+ should be left stopped and GDB should read more commands. */
+
+void
+wait_for_inferior ()
+{
+ struct cleanup *old_cleanups;
+ struct target_waitstatus w;
+ int another_trap;
+ int random_signal;
+ CORE_ADDR stop_func_start;
+ CORE_ADDR stop_func_end;
+ char *stop_func_name;
+#if 0
+ CORE_ADDR prologue_pc = 0;
+#endif
+ CORE_ADDR 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;
+ int update_step_sp = 0;
+
+ 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() \
+ ((through_sigtramp_breakpoint == NULL \
+ && !handling_longjmp \
+ && ((step_range_end && step_resume_breakpoint == NULL) \
+ || trap_expected)) \
+ || bpstat_should_step ())
+
+ while (1)
+ {
+ /* 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 ();
+
+ if (target_wait_hook)
+ pid = target_wait_hook (-1, &w);
+ else
+ pid = target_wait (-1, &w);
+
+#ifdef HAVE_NONSTEPPABLE_WATCHPOINT
+ have_waited:
+#endif
+
+ flush_cached_frames ();
+
+ /* If it's a new process, add it to the thread database */
+
+ 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 */
+ annotate_exited (w.value.integer);
+ if (w.value.integer)
+ printf_filtered ("\nProgram exited with code 0%o.\n",
+ (unsigned int)w.value.integer);
+ else
+ printf_filtered ("\nProgram exited normally.\n");
+
+ /* Record the exit code in the convenience variable $_exitcode, so
+ that the user can inspect this again later. */
+ set_internalvar (lookup_internalvar ("_exitcode"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) w.value.integer));
+ gdb_flush (gdb_stdout);
+ target_mourn_inferior ();
+#ifdef NO_SINGLE_STEP
+ one_stepped = 0;
+#endif
+ stop_print_frame = 0;
+ goto stop_stepping;
+
+ case TARGET_WAITKIND_SIGNALLED:
+ stop_print_frame = 0;
+ stop_signal = w.value.sig;
+ target_terminal_ours (); /* Must do this before mourn anyway */
+ annotate_signalled ();
+
+ /* This looks pretty bogus to me. Doesn't TARGET_WAITKIND_SIGNALLED
+ mean it is already dead? This has been here since GDB 2.8, so
+ perhaps it means rms didn't understand unix waitstatuses?
+ For the moment I'm just kludging around this in remote.c
+ rather than trying to change it here --kingdon, 5 Dec 1994. */
+ target_kill (); /* kill mourns as well */
+
+ printf_filtered ("\nProgram terminated with signal ");
+ 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");
+ 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 = w.value.sig;
+
+ 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))
+ {
+ 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_pid (stop_pc - DECR_PC_AFTER_BREAK, pid);
+
+ remove_breakpoints ();
+ target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
+ /* FIXME: What if a signal arrives instead of the single-step
+ happening? */
+
+ if (target_wait_hook)
+ target_wait_hook (pid, &w);
+ else
+ target_wait (pid, &w);
+ insert_breakpoints ();
+
+ /* We need to restart all the threads now. */
+ target_resume (-1, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+ }
+ else
+ random_signal = 1;
+
+ /* 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 it's a random signal for a non-current thread, notify user
+ if he's expressed an interest. */
+
+ 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;
+ }
+
+ /* It's a SIGTRAP or a signal we're interested in. Switch threads,
+ and fall into the rest of wait_for_inferior(). */
+
+ /* Save infrun state for the old thread. */
+ save_infrun_state (inferior_pid, prev_pc,
+ prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint,
+ step_range_start, step_range_end,
+ step_frame_address, handling_longjmp,
+ another_trap);
+
+ inferior_pid = pid;
+
+ /* Load infrun state for the new thread. */
+ load_infrun_state (inferior_pid, &prev_pc,
+ &prev_func_start, &prev_func_name,
+ &trap_expected, &step_resume_breakpoint,
+ &through_sigtramp_breakpoint,
+ &step_range_start, &step_range_end,
+ &step_frame_address, &handling_longjmp,
+ &another_trap);
+ printf_filtered ("[Switching to %s]\n", target_pid_to_str (pid));
+
+ flush_cached_frames ();
+ }
+
+#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 (INSTRUCTION_NULLIFIED)
+ {
+ resume (1, 0);
+ continue;
+ }
+
+#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))
+ {
+/* At this point, we are stopped at an instruction which has attempted to write
+ to a piece of memory under control of a watchpoint. The instruction hasn't
+ actually executed yet. If we were to evaluate the watchpoint expression
+ now, we would get the old value, and therefore no change would seem to have
+ occurred.
+
+ In order to make watchpoints work `right', we really need to complete the
+ memory write, and then evaluate the watchpoint expression. The following
+ code does that by removing the watchpoint (actually, all watchpoints and
+ breakpoints), single-stepping the target, re-inserting watchpoints, and then
+ falling through to let normal single-step processing handle proceed. Since
+ this includes evaluating watchpoints, things will come to a stop in the
+ correct manner. */
+
+ write_pc (stop_pc - DECR_PC_AFTER_BREAK);
+
+ remove_breakpoints ();
+ target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
+
+ if (target_wait_hook)
+ target_wait_hook (pid, &w);
+ else
+ target_wait (pid, &w);
+ insert_breakpoints ();
+ /* FIXME-maybe: is this cleaner than setting a flag? Does it
+ handle things like signals arriving and other things happening
+ in combination correctly? */
+ goto have_waited;
+ }
+#endif
+
+#ifdef HAVE_CONTINUABLE_WATCHPOINT
+ /* It may be possible to simply continue after a watchpoint. */
+ STOPPED_BY_WATCHPOINT (w);
+#endif
+
+ stop_func_start = 0;
+ stop_func_name = 0;
+ /* 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,
+ &stop_func_end);
+ stop_func_start += FUNCTION_START_OFFSET;
+ another_trap = 0;
+ bpstat_clear (&stop_bpstat);
+ stop_step = 0;
+ stop_stack_dummy = 0;
+ stop_print_frame = 1;
+ random_signal = 0;
+ stopped_by_random_signal = 0;
+ breakpoints_failed = 0;
+
+ /* Look at the cause of the stop, and decide what to do.
+ The alternatives are:
+ 1) break; to really stop and return to the debugger,
+ 2) drop through to start up again
+ (set another_trap to 1 to single step once)
+ 3) set random_signal to 1, and the decision between 1 and 2
+ will be made according to the signal handling tables. */
+
+ /* First, distinguish signals caused by the debugger from signals
+ that have to do with the program's own actions.
+ Note that breakpoint insns may cause SIGTRAP or SIGILL
+ or SIGEMT, depending on the operating system version.
+ Here we detect when a SIGILL or SIGEMT is really a breakpoint
+ and change it to SIGTRAP. */
+
+ if (stop_signal == TARGET_SIGNAL_TRAP
+ || (breakpoints_inserted &&
+ (stop_signal == TARGET_SIGNAL_ILL
+ || stop_signal == TARGET_SIGNAL_EMT
+ ))
+ || stop_soon_quietly)
+ {
+ if (stop_signal == TARGET_SIGNAL_TRAP && stop_after_trap)
+ {
+ stop_print_frame = 0;
+ break;
+ }
+ if (stop_soon_quietly)
+ break;
+
+ /* Don't even think about breakpoints
+ if just proceeded over a breakpoint.
+
+ However, if we are trying to proceed over a 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 == TARGET_SIGNAL_TRAP && trap_expected
+ && through_sigtramp_breakpoint == NULL)
+ bpstat_clear (&stop_bpstat);
+ else
+ {
+ /* See if there is a breakpoint at the current PC. */
+ stop_bpstat = bpstat_stop_status
+ (&stop_pc,
+#if DECR_PC_AFTER_BREAK
+ /* Notice the case of stepping through a jump
+ that lands just after a breakpoint.
+ Don't confuse that with hitting the breakpoint.
+ What we check for is that 1) stepping is going on
+ and 2) the pc before the last insn does not match
+ the address of the breakpoint before the current pc. */
+ (prev_pc != stop_pc - DECR_PC_AFTER_BREAK
+ && CURRENTLY_STEPPING ())
+#else /* DECR_PC_AFTER_BREAK zero */
+ 0
+#endif /* DECR_PC_AFTER_BREAK zero */
+ );
+ /* Following in case break condition called a
+ function. */
+ stop_print_frame = 1;
+ }
+
+ if (stop_signal == TARGET_SIGNAL_TRAP)
+ random_signal
+ = !(bpstat_explains_signal (stop_bpstat)
+ || trap_expected
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+ FRAME_FP (get_current_frame ()))
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+ || (step_range_end && step_resume_breakpoint == NULL));
+ else
+ {
+ random_signal
+ = !(bpstat_explains_signal (stop_bpstat)
+ /* End of a stack dummy. Some systems (e.g. Sony
+ news) give another signal besides SIGTRAP,
+ so check here as well as above. */
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ || PC_IN_CALL_DUMMY (stop_pc, read_sp (),
+ FRAME_FP (get_current_frame ()))
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+ );
+ if (!random_signal)
+ stop_signal = TARGET_SIGNAL_TRAP;
+ }
+ }
+ else
+ random_signal = 1;
+
+ /* For the program's own signals, act according to
+ the signal handling tables. */
+
+ if (random_signal)
+ {
+ /* Signal not for debugging purposes. */
+ int printed = 0;
+
+ stopped_by_random_signal = 1;
+
+ if (signal_print[stop_signal])
+ {
+ printed = 1;
+ target_terminal_ours_for_output ();
+ annotate_signal ();
+ printf_filtered ("\nProgram received signal ");
+ 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 (signal_stop[stop_signal])
+ break;
+ /* If not going to stop, give terminal back
+ if we took it away. */
+ else 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;
+
+ /* I'm not sure whether this needs to be check_sigtramp2 or
+ whether it could/should be keep_going. */
+ goto check_sigtramp2;
+ }
+
+ /* Handle cases caused by hitting a breakpoint. */
+ {
+ CORE_ADDR jmp_buf_pc;
+ struct bpstat_what what;
+
+ what = bpstat_what (stop_bpstat);
+
+ if (what.call_dummy)
+ {
+ stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 1;
+#endif
+ }
+
+ switch (what.main_action)
+ {
+ case BPSTAT_WHAT_SET_LONGJMP_RESUME:
+ /* If we hit the breakpoint at longjmp, disable it for the
+ duration of this command. Then, install a temporary
+ breakpoint at the target of the jmp_buf. */
+ disable_longjmp_breakpoint();
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ if (!GET_LONGJMP_TARGET(&jmp_buf_pc)) goto keep_going;
+
+ /* Need to blow away step-resume breakpoint, as it
+ interferes with us */
+ if (step_resume_breakpoint != NULL)
+ {
+ delete_breakpoint (step_resume_breakpoint);
+ step_resume_breakpoint = NULL;
+ }
+ /* 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
+ /* FIXME - Need to implement nested temporary breakpoints */
+ if (step_over_calls > 0)
+ set_longjmp_resume_breakpoint(jmp_buf_pc,
+ get_current_frame());
+ else
+#endif /* 0 */
+ set_longjmp_resume_breakpoint(jmp_buf_pc, NULL);
+ handling_longjmp = 1; /* FIXME */
+ goto keep_going;
+
+ case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME:
+ case BPSTAT_WHAT_CLEAR_LONGJMP_RESUME_SINGLE:
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+#if 0
+ /* FIXME - Need to implement nested temporary breakpoints */
+ if (step_over_calls
+ && (FRAME_FP (get_current_frame ())
+ INNER_THAN step_frame_address))
+ {
+ another_trap = 1;
+ goto keep_going;
+ }
+#endif /* 0 */
+ disable_longjmp_breakpoint();
+ handling_longjmp = 0; /* FIXME */
+ if (what.main_action == BPSTAT_WHAT_CLEAR_LONGJMP_RESUME)
+ break;
+ /* else fallthrough */
+
+ case BPSTAT_WHAT_SINGLE:
+ if (breakpoints_inserted)
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ another_trap = 1;
+ /* Still need to check other stuff, at least the case
+ where we are stepping and step out of the right range. */
+ break;
+
+ case BPSTAT_WHAT_STOP_NOISY:
+ stop_print_frame = 1;
+
+ /* 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 and
+ through_sigtramp_breakpoint via the cleanup chain, so
+ no need to worry about it here. */
+
+ goto stop_stepping;
+
+ case BPSTAT_WHAT_STEP_RESUME:
+ delete_breakpoint (step_resume_breakpoint);
+ step_resume_breakpoint = NULL;
+ break;
+
+ case BPSTAT_WHAT_THROUGH_SIGTRAMP:
+ if (through_sigtramp_breakpoint)
+ 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;
+
+#ifdef SOLIB_ADD
+ case BPSTAT_WHAT_CHECK_SHLIBS:
+ {
+ extern int auto_solib_add;
+
+ /* Remove breakpoints, we eventually want to step over the
+ shlib event breakpoint, and SOLIB_ADD might adjust
+ breakpoint addresses via breakpoint_re_set. */
+ if (breakpoints_inserted)
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+
+ /* Check for any newly added shared libraries if we're
+ supposed to be adding them automatically. */
+ if (auto_solib_add)
+ {
+ /* Switch terminal for any messages produced by
+ breakpoint_re_set. */
+ target_terminal_ours_for_output ();
+ SOLIB_ADD (NULL, 0, NULL);
+ re_enable_breakpoints_in_shlibs ();
+ target_terminal_inferior ();
+ }
+
+ /* If requested, stop when the dynamic linker notifies
+ gdb of events. This allows the user to get control
+ and place breakpoints in initializer routines for
+ dynamically loaded objects (among other things). */
+ if (stop_on_solib_events)
+ {
+ stop_print_frame = 0;
+ goto stop_stepping;
+ }
+ else
+ {
+ /* We want to step over this breakpoint, then keep going. */
+ another_trap = 1;
+ break;
+ }
+ }
+#endif
+
+ case BPSTAT_WHAT_LAST:
+ /* Not a real code, but listed here to shut up gcc -Wall. */
+
+ case BPSTAT_WHAT_KEEP_CHECKING:
+ break;
+ }
+ }
+
+ /* We come here if we hit a breakpoint but should not
+ stop for it. Possibly we also were stepping
+ and should stop for that. So fall through and
+ test for stepping. But, if not stepping,
+ do not stop. */
+
+#ifndef CALL_DUMMY_BREAKPOINT_OFFSET
+ /* This is the old way of detecting the end of the stack dummy.
+ An architecture which defines CALL_DUMMY_BREAKPOINT_OFFSET gets
+ handled above. As soon as we can test it on all of them, all
+ architectures should define it. */
+
+ /* If this is the breakpoint at the end of a stack dummy,
+ just stop silently, unless the user was doing an si/ni, in which
+ case she'd better know what she's doing. */
+
+ if (PC_IN_CALL_DUMMY (stop_pc, read_sp (), FRAME_FP (get_current_frame ()))
+ && !step_range_end)
+ {
+ stop_print_frame = 0;
+ stop_stack_dummy = 1;
+#ifdef HP_OS_BUG
+ trap_expected_after_continue = 1;
+#endif
+ break;
+ }
+#endif /* No CALL_DUMMY_BREAKPOINT_OFFSET. */
+
+ if (step_resume_breakpoint)
+ /* Having a step-resume breakpoint overrides anything
+ else having to do with stepping commands until
+ that breakpoint is reached. */
+ /* 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)
+ /* Likewise if we aren't even stepping. */
+ /* I'm not sure whether this needs to be check_sigtramp2 or
+ whether it could/should be keep_going. */
+ goto check_sigtramp2;
+
+ /* If stepping through a line, keep going if still within it. */
+ if (stop_pc >= step_range_start
+ && stop_pc < step_range_end
+#if 0
+/* I haven't a clue what might trigger this clause, and it seems wrong anyway,
+ so I've disabled it until someone complains. -Stu 10/24/95 */
+
+ /* The step range might include the start of the
+ function, so if we are at the start of the
+ step range and either the stack or frame pointers
+ just changed, we've stepped outside */
+ && !(stop_pc == step_range_start
+ && FRAME_FP (get_current_frame ())
+ && (read_sp () INNER_THAN step_sp
+ || FRAME_FP (get_current_frame ()) != step_frame_address))
+#endif
+)
+ {
+ /* We might be doing a BPSTAT_WHAT_SINGLE and getting a signal.
+ So definately need to check for sigtramp here. */
+ goto check_sigtramp2;
+ }
+
+ /* We stepped out of the stepping range. */
+
+ /* We can't update step_sp every time through the loop, because
+ reading the stack pointer would slow down stepping too much.
+ But we can update it every time we leave the step range. */
+ update_step_sp = 1;
+
+ /* Did we just take a signal? */
+ 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). */
+
+ /* 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
+ step_frame_address; I don't think anyone thought to try it. */
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+ }
+
+ /* If this is stepi or nexti, make sure that the stepping range
+ gets us past that instruction. */
+ if (step_range_end == 1)
+ /* FIXME: Does this run afoul of the code below which, if
+ we step into the middle of a line, resets the stepping
+ range? */
+ step_range_end = (step_range_start = prev_pc) + 1;
+
+ remove_breakpoints_on_following_step = 1;
+ goto keep_going;
+ }
+
+#if 0
+ /* I disabled this test because it was too complicated and slow. The
+ SKIP_PROLOGUE was especially slow, because it caused unnecessary
+ prologue examination on various architectures. The code in the #else
+ clause has been tested on the Sparc, Mips, PA, and Power
+ architectures, so it's pretty likely to be correct. -Stu 10/24/95 */
+
+ /* See if we left the step range due to a subroutine call that
+ we should proceed to the end of. */
+
+ if (stop_func_start)
+ {
+ struct symtab *s;
+
+ /* Do this after the IN_SIGTRAMP check; it might give
+ an error. */
+ prologue_pc = stop_func_start;
+
+ /* 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
+ enough that stop_func_start == prev_func_start even though
+ they are really two functions, we will treat some calls as
+ jumps. */
+ stop_func_start != prev_func_start
+
+ /* Might be a recursive call if either we have a prologue
+ or the call instruction itself saves the PC on the stack. */
+ || prologue_pc != stop_func_start
+ || read_sp () != step_sp)
+ && (/* PC is completely out of bounds of any known objfiles. Treat
+ like a subroutine call. */
+ ! stop_func_start
+
+ /* If we do a call, we will be at the start of a function... */
+ || stop_pc == stop_func_start
+
+ /* ...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
+
+ /* ...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
+ have the above checks with stop_func_start (and now that
+ find_pc_partial_function is pickier). */
+ || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
+
+ /* If none of the above apply, it is a jump within a function,
+ or a return from a subroutine. The other case is longjmp,
+ which can no longer happen here as long as the
+ handling_longjmp stuff is working. */
+ ))
+#else
+ /* This test is a much more streamlined, (but hopefully correct)
+ replacement for the code above. It's been tested on the Sparc,
+ Mips, PA, and Power architectures with good results. */
+
+ if (stop_pc == stop_func_start /* Quick test */
+ || in_prologue (stop_pc, stop_func_start)
+ || IN_SOLIB_CALL_TRAMPOLINE (stop_pc, stop_func_name)
+ || stop_func_start == 0)
+#endif
+
+ {
+ /* It's a subroutine call. */
+
+ if (step_over_calls == 0)
+ {
+ /* I presume that step_over_calls is only 0 when we're
+ supposed to be stepping at the assembly language level
+ ("stepi"). Just stop. */
+ stop_step = 1;
+ break;
+ }
+
+ if (step_over_calls > 0)
+ /* We're doing a "next". */
+ goto step_over_function;
+
+ /* If we are in a function call trampoline (a stub between
+ the calling routine and the real function), locate the real
+ function. That's what tells us (a) whether we want to step
+ into it at all, and (b) what prologue we want to run to
+ the end of, if we do step into it. */
+ tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
+ if (tmp != 0)
+ stop_func_start = tmp;
+ else
+ {
+ tmp = DYNAMIC_TRAMPOLINE_NEXTPC (stop_pc);
+ if (tmp)
+ {
+ struct symtab_and_line xxx;
+
+ xxx.pc = tmp;
+ xxx.symtab = NULL;
+ xxx.line = 0;
+ step_resume_breakpoint =
+ set_momentary_breakpoint (xxx, NULL, bp_step_resume);
+ insert_breakpoints ();
+ goto keep_going;
+ }
+ }
+
+ /* If we have line number information for the function we
+ are thinking of stepping into, step into it.
+
+ If there are several symtabs at that PC (e.g. with include
+ files), just want to know whether *any* of them have line
+ numbers. find_pc_line handles this. */
+ {
+ struct symtab_and_line tmp_sal;
+
+ tmp_sal = find_pc_line (stop_func_start, 0);
+ if (tmp_sal.line != 0)
+ goto step_into_function;
+ }
+
+step_over_function:
+ /* A subroutine call has happened. */
+ {
+ /* Set a special breakpoint after the return */
+ struct symtab_and_line sr_sal;
+ sr_sal.pc =
+ ADDR_BITS_REMOVE
+ (SAVED_PC_AFTER_CALL (get_current_frame ()));
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, get_current_frame (),
+ bp_step_resume);
+ step_resume_breakpoint->frame = step_frame_address;
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+ }
+ goto keep_going;
+
+step_into_function:
+ /* Subroutine call with source code we should not step over.
+ Do step to the first line of code in it. */
+ {
+ 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 (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 && sal.end < stop_func_end)
+ stop_func_start = sal.end;
+#endif
+
+ if (stop_func_start == stop_pc)
+ {
+ /* We are already there: stop now. */
+ stop_step = 1;
+ break;
+ }
+ else
+ /* Put the step-breakpoint there and go until there. */
+ {
+ struct symtab_and_line sr_sal;
+
+ sr_sal.pc = stop_func_start;
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ /* Do not specify what the fp should be when we stop
+ since on some machines the prologue
+ is where the new fp value is established. */
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+
+ /* And make sure stepping stops right away then. */
+ step_range_end = step_range_start;
+ }
+ goto keep_going;
+ }
+
+ /* We've wandered out of the step range. */
+
+ sal = find_pc_line(stop_pc, 0);
+
+ if (step_range_end == 1)
+ {
+ /* It is stepi or nexti. We always want to stop stepping after
+ one instruction. */
+ stop_step = 1;
+ break;
+ }
+
+ /* If we're in the return path from a shared library trampoline,
+ we want to proceed through the trampoline when stepping. */
+ if (IN_SOLIB_RETURN_TRAMPOLINE(stop_pc, stop_func_name))
+ {
+ CORE_ADDR tmp;
+
+ /* Determine where this trampoline returns. */
+ tmp = SKIP_TRAMPOLINE_CODE (stop_pc);
+
+ /* Only proceed through if we know where it's going. */
+ if (tmp)
+ {
+ /* And put the step-breakpoint there and go until there. */
+ struct symtab_and_line sr_sal;
+
+ sr_sal.pc = tmp;
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ /* Do not specify what the fp should be when we stop
+ since on some machines the prologue
+ is where the new fp value is established. */
+ step_resume_breakpoint =
+ set_momentary_breakpoint (sr_sal, NULL, bp_step_resume);
+ if (breakpoints_inserted)
+ insert_breakpoints ();
+
+ /* Restart without fiddling with the step ranges or
+ other state. */
+ goto keep_going;
+ }
+ }
+
+ if (sal.line == 0)
+ {
+ /* We have no line number information. That means to stop
+ stepping (does this always happen right after one instruction,
+ when we do "s" in a function with no line numbers,
+ or can this happen as a result of a return or longjmp?). */
+ stop_step = 1;
+ break;
+ }
+
+ 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.
+ That is said to make things like for (;;) statements work
+ better. */
+ stop_step = 1;
+ break;
+ }
+
+ /* We aren't done stepping.
+
+ Optimize by setting the stepping range to the line.
+ (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;
+
+ check_sigtramp2:
+ if (trap_expected
+ && IN_SIGTRAMP (stop_pc, stop_func_name)
+ && !IN_SIGTRAMP (prev_pc, prev_func_name))
+ {
+ /* What has happened here is that we have just stepped the inferior
+ with a signal (because it is a signal which shouldn't make
+ us stop), thus stepping into sigtramp.
+
+ So we need to set a step_resume_break_address breakpoint
+ and continue until we hit it, and then step. FIXME: This should
+ be more enduring than a step_resume breakpoint; we should know
+ that we will later need to keep going rather than re-hitting
+ the breakpoint here (see testsuite/gdb.t06/signals.exp where
+ it says "exceedingly difficult"). */
+ struct symtab_and_line sr_sal;
+
+ sr_sal.pc = prev_pc;
+ sr_sal.symtab = NULL;
+ sr_sal.line = 0;
+ /* 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 ();
+
+ remove_breakpoints_on_following_step = 1;
+ another_trap = 1;
+ }
+
+ keep_going:
+ /* Come to this label when you need to resume the inferior.
+ It's really much cleaner to do a goto than a maze of if-else
+ conditions. */
+
+ /* Save the pc before execution, to compare with pc after stop. */
+ prev_pc = read_pc (); /* Might have been DECR_AFTER_BREAK */
+ prev_func_start = stop_func_start; /* Ok, since if DECR_PC_AFTER
+ BREAK is defined, the
+ original pc would not have
+ been at the start of a
+ function. */
+ prev_func_name = stop_func_name;
+
+ if (update_step_sp)
+ step_sp = read_sp ();
+ update_step_sp = 0;
+
+ /* If we did not do break;, it means we should keep
+ running the inferior and not return to debugger. */
+
+ 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
+ haven't yet gotten our trap. Simply continue. */
+ resume (CURRENTLY_STEPPING (), stop_signal);
+ }
+ else
+ {
+ /* Either the trap was not expected, but we are continuing
+ anyway (the user asked that this signal be passed to the
+ child)
+ -- or --
+ The signal was SIGTRAP, e.g. it was our signal, but we
+ decided we should resume from it.
+
+ We're going to run this baby now!
+
+ Insert breakpoints now, unless we are trying
+ 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
+ && through_sigtramp_breakpoint == NULL
+ && remove_breakpoints_on_following_step)
+ {
+ remove_breakpoints_on_following_step = 0;
+ remove_breakpoints ();
+ breakpoints_inserted = 0;
+ }
+ else if (!breakpoints_inserted &&
+ (through_sigtramp_breakpoint != NULL || !another_trap))
+ {
+ breakpoints_failed = insert_breakpoints ();
+ if (breakpoints_failed)
+ break;
+ breakpoints_inserted = 1;
+ }
+
+ trap_expected = another_trap;
+
+ 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,
+ that we shouldn't rewrite the regs when we were stopped by a
+ random signal from the inferior process. */
+ /* FIXME: Shouldn't this be based on the valid bit of the SXIP?
+ (this is only used on the 88k). */
+
+ if (!bpstat_explains_signal (stop_bpstat)
+ && (stop_signal != TARGET_SIGNAL_CHLD)
+ && !stopped_by_random_signal)
+ SHIFT_INST_REGS();
+#endif /* SHIFT_INST_REGS */
+
+ resume (CURRENTLY_STEPPING (), stop_signal);
+ }
+ }
+
+ stop_stepping:
+ if (target_has_execution)
+ {
+ /* Assuming the inferior still exists, set these up for next
+ time, just like we did above if we didn't break out of the
+ loop. */
+ prev_pc = read_pc ();
+ prev_func_start = stop_func_start;
+ prev_func_name = stop_func_name;
+ }
+ do_cleanups (old_cleanups);
+}
+
+/* Here to return control to GDB when the inferior stops for real.
+ Print appropriate messages, remove breakpoints, give terminal our modes.
+
+ STOP_PRINT_FRAME nonzero means print the executing frame
+ (pc, function, args, file, line number and line text).
+ BREAKPOINTS_FAILED nonzero means stop was due to error
+ attempting to insert breakpoints. */
+
+void
+normal_stop ()
+{
+ /* Make sure that the current_frame's pc is correct. This
+ is a correction for setting up the frame info before doing
+ DECR_PC_AFTER_BREAK */
+ if (target_has_execution && get_current_frame())
+ (get_current_frame ())->pc = read_pc ();
+
+ if (breakpoints_failed)
+ {
+ target_terminal_ours_for_output ();
+ print_sys_errmsg ("ptrace", breakpoints_failed);
+ printf_filtered ("Stopped; cannot insert breakpoints.\n\
+The same program may be running in another process.\n");
+ }
+
+ if (target_has_execution && breakpoints_inserted)
+ if (remove_breakpoints ())
+ {
+ target_terminal_ours_for_output ();
+ printf_filtered ("Cannot remove breakpoints because program is no longer writable.\n\
+It might be running in another process.\n\
+Further execution is probably impossible.\n");
+ }
+
+ breakpoints_inserted = 0;
+
+ /* Delete the breakpoint we stopped at, if it wants to be deleted.
+ Delete any breakpoint that is to be deleted at the next stop. */
+
+ breakpoint_auto_delete (stop_bpstat);
+
+ /* If an auto-display called a function and that got a signal,
+ delete that auto-display to avoid an infinite recursion. */
+
+ if (stopped_by_random_signal)
+ disable_current_display ();
+
+ if (step_multi && stop_step)
+ goto done;
+
+ target_terminal_ours ();
+
+ if (stop_bpstat
+ && stop_bpstat->breakpoint_at
+ && stop_bpstat->breakpoint_at->type == bp_shlib_event)
+ printf_filtered ("Stopped due to shared library event\n");
+
+ /* Look up the hook_stop and run it if it exists. */
+
+ if (stop_command->hook)
+ {
+ catch_errors (hook_stop_stub, (char *)stop_command->hook,
+ "Error while running hook_stop:\n", RETURN_MASK_ALL);
+ }
+
+ if (!target_has_stack)
+ 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
+ we have changed functions or hit a breakpoint. Print source line
+ if we have one. */
+ if (!stop_stack_dummy)
+ {
+ select_frame (get_current_frame (), 0);
+
+ if (stop_print_frame)
+ {
+ int source_only;
+
+ source_only = bpstat_print (stop_bpstat);
+ source_only = source_only ||
+ ( stop_step
+ && step_frame_address == FRAME_FP (get_current_frame ())
+ && step_start_function == find_pc_function (stop_pc));
+
+ print_stack_frame (selected_frame, -1, source_only? -1: 1);
+
+ /* Display the auto-display expressions. */
+ do_displays ();
+ }
+ }
+
+ /* Save the function value return registers, if we care.
+ We might be about to restore their previous contents. */
+ if (proceed_to_finish)
+ read_register_bytes (0, stop_registers, REGISTER_BYTES);
+
+ if (stop_stack_dummy)
+ {
+ /* Pop the empty frame that contains the stack dummy.
+ 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
+hook_stop_stub (cmd)
+ char *cmd;
+{
+ execute_user_command ((struct cmd_list_element *)cmd, 0);
+ return (0);
+}
+
+int signal_stop_state (signo)
+ int signo;
+{
+ return signal_stop[signo];
+}
+
+int signal_print_state (signo)
+ int signo;
+{
+ return signal_print[signo];
+}
+
+int signal_pass_state (signo)
+ int signo;
+{
+ return signal_program[signo];
+}
+
+static void
+sig_print_header ()
+{
+ printf_filtered ("\
+Signal Stop\tPrint\tPass to program\tDescription\n");
+}
+
+static void
+sig_print_info (oursig)
+ enum target_signal oursig;
+{
+ 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. */
+
+static void
+handle_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ int digits, wordlen;
+ int sigfirst, signum, siglast;
+ enum target_signal oursig;
+ int allsigs;
+ int nsigs;
+ unsigned char *sigs;
+ struct cleanup *old_chain;
+
+ if (args == NULL)
+ {
+ error_no_arg ("signal to handle");
+ }
+
+ /* Allocate and zero an array of flags for which signals to handle. */
+
+ nsigs = (int)TARGET_SIGNAL_LAST;
+ sigs = (unsigned char *) alloca (nsigs);
+ memset (sigs, 0, nsigs);
+
+ /* Break the command line up into args. */
+
+ argv = buildargv (args);
+ if (argv == NULL)
+ {
+ nomem (0);
+ }
+ old_chain = make_cleanup (freeargv, (char *) argv);
+
+ /* 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 <LOW>-<HIGH>. */
+
+ while (*argv != NULL)
+ {
+ wordlen = strlen (*argv);
+ for (digits = 0; isdigit ((*argv)[digits]); digits++) {;}
+ allsigs = 0;
+ sigfirst = siglast = -1;
+
+ if (wordlen >= 1 && !strncmp (*argv, "all", wordlen))
+ {
+ /* Apply action to all signals except those used by the
+ debugger. Silently skip those. */
+ allsigs = 1;
+ sigfirst = 0;
+ siglast = nsigs - 1;
+ }
+ else if (wordlen >= 1 && !strncmp (*argv, "stop", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_stop);
+ SET_SIGS (nsigs, sigs, signal_print);
+ }
+ else if (wordlen >= 1 && !strncmp (*argv, "ignore", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_program);
+ }
+ else if (wordlen >= 2 && !strncmp (*argv, "print", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_print);
+ }
+ else if (wordlen >= 2 && !strncmp (*argv, "pass", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_program);
+ }
+ else if (wordlen >= 3 && !strncmp (*argv, "nostop", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_stop);
+ }
+ else if (wordlen >= 3 && !strncmp (*argv, "noignore", wordlen))
+ {
+ SET_SIGS (nsigs, sigs, signal_program);
+ }
+ else if (wordlen >= 4 && !strncmp (*argv, "noprint", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_print);
+ UNSET_SIGS (nsigs, sigs, signal_stop);
+ }
+ else if (wordlen >= 4 && !strncmp (*argv, "nopass", wordlen))
+ {
+ UNSET_SIGS (nsigs, sigs, signal_program);
+ }
+ 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 = (int) target_signal_from_command (atoi (*argv));
+ if ((*argv)[digits] == '-')
+ {
+ siglast =
+ (int) target_signal_from_command (atoi ((*argv) + digits + 1));
+ }
+ if (sigfirst > siglast)
+ {
+ /* Bet he didn't figure we'd think of this case... */
+ signum = sigfirst;
+ sigfirst = siglast;
+ siglast = signum;
+ }
+ }
+ else
+ {
+ 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
+ which signals to apply actions to. */
+
+ for (signum = sigfirst; signum >= 0 && signum <= siglast; signum++)
+ {
+ switch ((enum target_signal)signum)
+ {
+ case TARGET_SIGNAL_TRAP:
+ case TARGET_SIGNAL_INT:
+ if (!allsigs && !sigs[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_unfiltered ("Not confirmed, unchanged.\n");
+ gdb_flush (gdb_stdout);
+ }
+ }
+ break;
+ case TARGET_SIGNAL_0:
+ case TARGET_SIGNAL_DEFAULT:
+ case TARGET_SIGNAL_UNKNOWN:
+ /* Make sure that "all" doesn't print these. */
+ break;
+ default:
+ sigs[signum] = 1;
+ break;
+ }
+ }
+
+ argv++;
+ }
+
+ target_notice_signals(inferior_pid);
+
+ if (from_tty)
+ {
+ /* Show the results. */
+ sig_print_header ();
+ for (signum = 0; signum < nsigs; signum++)
+ {
+ if (sigs[signum])
+ {
+ sig_print_info (signum);
+ }
+ }
+ }
+
+ do_cleanups (old_chain);
+}
+
+/* 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;
+{
+ enum target_signal oursig;
+ sig_print_header ();
+
+ if (signum_exp)
+ {
+ /* First see if this is a symbol name. */
+ oursig = target_signal_from_name (signum_exp);
+ if (oursig == TARGET_SIGNAL_UNKNOWN)
+ {
+ /* No, try numeric. */
+ oursig =
+ target_signal_from_command (parse_and_eval_address (signum_exp));
+ }
+ sig_print_info (oursig);
+ return;
+ }
+
+ printf_filtered ("\n");
+ /* 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;
+
+ 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");
+}
+
+/* Save all of the information associated with the inferior<==>gdb
+ connection. INF_STATUS is a pointer to a "struct inferior_status"
+ (defined in inferior.h). */
+
+void
+save_inferior_status (inf_status, restore_stack_info)
+ struct inferior_status *inf_status;
+ int restore_stack_info;
+{
+ inf_status->stop_signal = stop_signal;
+ inf_status->stop_pc = stop_pc;
+ inf_status->stop_step = stop_step;
+ inf_status->stop_stack_dummy = stop_stack_dummy;
+ inf_status->stopped_by_random_signal = stopped_by_random_signal;
+ inf_status->trap_expected = trap_expected;
+ inf_status->step_range_start = step_range_start;
+ inf_status->step_range_end = step_range_end;
+ inf_status->step_frame_address = step_frame_address;
+ inf_status->step_over_calls = step_over_calls;
+ inf_status->stop_after_trap = stop_after_trap;
+ inf_status->stop_soon_quietly = stop_soon_quietly;
+ /* Save original bpstat chain here; replace it with copy of chain.
+ If caller's caller is walking the chain, they'll be happier if we
+ hand them back the original chain when restore_i_s is called. */
+ inf_status->stop_bpstat = stop_bpstat;
+ stop_bpstat = bpstat_copy (stop_bpstat);
+ inf_status->breakpoint_proceeded = breakpoint_proceeded;
+ inf_status->restore_stack_info = restore_stack_info;
+ inf_status->proceed_to_finish = proceed_to_finish;
+
+ memcpy (inf_status->stop_registers, stop_registers, REGISTER_BYTES);
+
+ read_register_bytes (0, inf_status->registers, REGISTER_BYTES);
+
+ record_selected_frame (&(inf_status->selected_frame_address),
+ &(inf_status->selected_level));
+ return;
+}
+
+struct restore_selected_frame_args {
+ CORE_ADDR frame_address;
+ int level;
+};
+
+static int restore_selected_frame PARAMS ((char *));
+
+/* Restore the selected frame. args is really a struct
+ restore_selected_frame_args * (declared as char * for catch_errors)
+ telling us what frame to restore. Returns 1 for success, or 0 for
+ failure. An error message will have been printed on error. */
+
+static int
+restore_selected_frame (args)
+ char *args;
+{
+ struct restore_selected_frame_args *fr =
+ (struct restore_selected_frame_args *) args;
+ struct frame_info *frame;
+ int level = fr->level;
+
+ frame = find_relative_frame (get_current_frame (), &level);
+
+ /* If inf_status->selected_frame_address is NULL, there was no
+ previously selected frame. */
+ if (frame == NULL ||
+ FRAME_FP (frame) != fr->frame_address ||
+ level != 0)
+ {
+ warning ("Unable to restore previously selected frame.\n");
+ return 0;
+ }
+ select_frame (frame, fr->level);
+ return(1);
+}
+
+void
+restore_inferior_status (inf_status)
+ struct inferior_status *inf_status;
+{
+ stop_signal = inf_status->stop_signal;
+ stop_pc = inf_status->stop_pc;
+ stop_step = inf_status->stop_step;
+ stop_stack_dummy = inf_status->stop_stack_dummy;
+ stopped_by_random_signal = inf_status->stopped_by_random_signal;
+ trap_expected = inf_status->trap_expected;
+ step_range_start = inf_status->step_range_start;
+ step_range_end = inf_status->step_range_end;
+ step_frame_address = inf_status->step_frame_address;
+ step_over_calls = inf_status->step_over_calls;
+ stop_after_trap = inf_status->stop_after_trap;
+ stop_soon_quietly = inf_status->stop_soon_quietly;
+ bpstat_clear (&stop_bpstat);
+ stop_bpstat = inf_status->stop_bpstat;
+ breakpoint_proceeded = inf_status->breakpoint_proceeded;
+ proceed_to_finish = inf_status->proceed_to_finish;
+
+ memcpy (stop_registers, inf_status->stop_registers, REGISTER_BYTES);
+
+ /* The inferior can be gone if the user types "print exit(0)"
+ (and perhaps other times). */
+ if (target_has_execution)
+ write_register_bytes (0, inf_status->registers, REGISTER_BYTES);
+
+ /* The inferior can be gone if the user types "print exit(0)"
+ (and perhaps other times). */
+
+ /* FIXME: If we are being called after stopping in a function which
+ is called from gdb, we should not be trying to restore the
+ selected frame; it just prints a spurious error message (The
+ message is useful, however, in detecting bugs in gdb (like if gdb
+ clobbers the stack)). In fact, should we be restoring the
+ inferior status at all in that case? . */
+
+ if (target_has_stack && inf_status->restore_stack_info)
+ {
+ struct restore_selected_frame_args fr;
+ fr.level = inf_status->selected_level;
+ fr.frame_address = inf_status->selected_frame_address;
+ /* The point of catch_errors is that if the stack is clobbered,
+ walking the stack might encounter a garbage pointer and error()
+ trying to dereference it. */
+ if (catch_errors (restore_selected_frame, &fr,
+ "Unable to restore previously selected frame:\n",
+ RETURN_MASK_ERROR) == 0)
+ /* Error in restoring the selected frame. Select the innermost
+ frame. */
+ select_frame (get_current_frame (), 0);
+ }
+}
+
+
+void
+_initialize_infrun ()
+{
+ register int i;
+ register int numsigs;
+
+ add_info ("signals", signals_info,
+ "What debugger does when program gets various signals.\n\
+Specify a signal as argument to print info on that signal only.");
+ add_info_alias ("handle", "signals", 0);
+
+ add_com ("handle", class_run, handle_command,
+ concat ("Specify how to handle a signal.\n\
+Args are signals and actions to apply to those signals.\n\
+Symbolic signals (e.g. SIGSEGV) are recommended but numeric signals\n\
+from 1-15 are allowed for compatibility with old versions of GDB.\n\
+Numeric ranges may be specified with the form LOW-HIGH (e.g. 1-5).\n\
+The special arg \"all\" is recognized to mean all signals except those\n\
+used by the debugger, typically SIGTRAP and SIGINT.\n",
+"Recognized actions include \"stop\", \"nostop\", \"print\", \"noprint\",\n\
+\"pass\", \"nopass\", \"ignore\", or \"noignore\".\n\
+Stop means reenter debugger if this signal happens (implies print).\n\
+Print means print a message if this signal happens.\n\
+Pass means let program see this signal; otherwise program doesn't know.\n\
+Ignore is a synonym for nopass and noignore is a synonym for pass.\n\
+Pass and Stop may be combined.", NULL));
+
+ stop_command = add_cmd ("stop", class_obscure, not_just_help_class_command,
+ "There is no `stop' command, but you can set a hook on `stop'.\n\
+This allows you to set a list of commands to be run each time execution\n\
+of the program stops.", &cmdlist);
+
+ 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);
+ for (i = 0; i < numsigs; i++)
+ {
+ signal_stop[i] = 1;
+ signal_print[i] = 1;
+ signal_program[i] = 1;
+ }
+
+ /* Signals caused by debugger's own actions
+ should not be given to the program afterwards. */
+ signal_program[TARGET_SIGNAL_TRAP] = 0;
+ signal_program[TARGET_SIGNAL_INT] = 0;
+
+ /* Signals that are not errors should not normally enter the debugger. */
+ 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;
+
+#ifdef SOLIB_ADD
+ add_show_from_set
+ (add_set_cmd ("stop-on-solib-events", class_support, var_zinteger,
+ (char *) &stop_on_solib_events,
+ "Set stopping for shared library events.\n\
+If nonzero, gdb will give control to the user when the dynamic linker\n\
+notifies gdb of shared library events. The most common event of interest\n\
+to the user would be loading/unloading of a new library.\n",
+ &setlist),
+ &showlist);
+#endif
+}
diff --git a/contrib/gdb/gdb/inftarg.c b/contrib/gdb/gdb/inftarg.c
new file mode 100644
index 0000000..6e0e50a
--- /dev/null
+++ b/contrib/gdb/gdb/inftarg.c
@@ -0,0 +1,390 @@
+/* Target-vector operations for controlling Unix child processes, for GDB.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h" /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "command.h"
+#include <signal.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+static void
+child_prepare_to_store PARAMS ((void));
+
+#ifndef CHILD_WAIT
+static int child_wait PARAMS ((int, struct target_waitstatus *));
+#endif /* CHILD_WAIT */
+
+static void child_open PARAMS ((char *, int));
+
+static void
+child_files_info PARAMS ((struct target_ops *));
+
+static void
+child_detach PARAMS ((char *, int));
+
+static void
+child_attach PARAMS ((char *, int));
+
+static void
+ptrace_me PARAMS ((void));
+
+static void
+ptrace_him PARAMS ((int));
+
+static void child_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+child_mourn_inferior PARAMS ((void));
+
+static int
+child_can_run PARAMS ((void));
+
+static int child_thread_alive PARAMS ((int));
+
+extern char **environ;
+
+/* Forward declaration */
+extern struct target_ops child_ops;
+
+static int
+proc_wait (pid, status)
+ int pid;
+ int *status;
+{
+#ifndef __GO32__
+ return wait (status);
+#endif
+}
+
+#ifndef CHILD_WAIT
+
+/* Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status through argument pointer OURSTATUS. */
+
+static int
+child_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int save_errno;
+ int status;
+
+ do {
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ set_sigio_trap ();
+
+ pid = proc_wait (inferior_pid, &status);
+ save_errno = errno;
+
+ clear_sigio_trap ();
+
+ clear_sigint_trap();
+
+ if (pid == -1)
+ {
+ if (save_errno == EINTR)
+ continue;
+ fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+ /* 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 */
+
+#ifndef CHILD_THREAD_ALIVE
+
+/* Check to see if the given thread is alive.
+
+ FIXME: Is kill() ever the right way to do this? I doubt it, but
+ for now we're going to try and be compatable with the old thread
+ code. */
+static int
+child_thread_alive (pid)
+ int pid;
+{
+ return (kill (pid, 0) != -1);
+}
+
+#endif
+
+/* Attach to process PID, then initialize for debugging it. */
+
+static void
+child_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+#ifndef ATTACH_DETACH
+ error ("Can't attach to a process on this machine.");
+#else
+ {
+ char *exec_file;
+ int pid;
+
+ pid = atoi (args);
+
+ if (pid == getpid()) /* Trying to masturbate? */
+ error ("I refuse to debug myself!");
+
+ if (from_tty)
+ {
+ exec_file = (char *) get_exec_file (0);
+
+ 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));
+
+ gdb_flush (gdb_stdout);
+ }
+
+ attach (pid);
+ inferior_pid = pid;
+ push_target (&child_ops);
+ }
+#endif /* ATTACH_DETACH */
+}
+
+
+/* Take a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We'd better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via the normal ptrace (PTRACE_TRACEME). */
+
+static void
+child_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+#ifdef ATTACH_DETACH
+ {
+ 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.");
+#endif
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+child_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+child_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_unfiltered ("\tUsing the running image of %s %s.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+/* ARGSUSED */
+static void
+child_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+/* Stub function which causes the inferior that runs it, to be ptrace-able
+ by its parent process. */
+
+static void
+ptrace_me ()
+{
+ /* "Trace me, Dr. Memory!" */
+ call_ptrace (0, 0, (PTRACE_ARG3_TYPE) 0, 0);
+}
+
+/* Stub function which causes the GDB that runs it, to start ptrace-ing
+ the child process. */
+
+static void
+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.
+ 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(). */
+
+static void
+child_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ 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, TARGET_SIGNAL_0, 0);
+}
+
+static void
+child_mourn_inferior ()
+{
+ unpush_target (&child_ops);
+ proc_remove_foreign (inferior_pid);
+ generic_mourn_inferior ();
+}
+
+static int
+child_can_run ()
+{
+ return(1);
+}
+
+/* Send a SIGINT to the process group. This acts just like the user typed a
+ ^C on the controlling terminal.
+
+ XXX - This may not be correct for all systems. Some may want to use
+ killpg() instead of kill (-pgrp). */
+
+void
+child_stop ()
+{
+ extern pid_t inferior_process_group;
+
+ kill (-inferior_process_group, SIGINT);
+}
+
+struct target_ops child_ops = {
+ "child", /* to_shortname */
+ "Unix child process", /* to_longname */
+ "Unix child process (started by the \"run\" command).", /* to_doc */
+ child_open, /* to_open */
+ 0, /* to_close */
+ child_attach, /* to_attach */
+ child_detach, /* to_detach */
+ child_resume, /* to_resume */
+ child_wait, /* to_wait */
+ fetch_inferior_registers, /* to_fetch_registers */
+ store_inferior_registers, /* to_store_registers */
+ child_prepare_to_store, /* to_prepare_to_store */
+ child_xfer_memory, /* to_xfer_memory */
+ child_files_info, /* to_files_info */
+ memory_insert_breakpoint, /* to_insert_breakpoint */
+ memory_remove_breakpoint, /* to_remove_breakpoint */
+ terminal_init_inferior, /* to_terminal_init */
+ terminal_inferior, /* to_terminal_inferior */
+ terminal_ours_for_output, /* to_terminal_ours_for_output */
+ terminal_ours, /* to_terminal_ours */
+ child_terminal_info, /* to_terminal_info */
+ kill_inferior, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ child_create_inferior, /* to_create_inferior */
+ child_mourn_inferior, /* to_mourn_inferior */
+ child_can_run, /* to_can_run */
+ 0, /* to_notice_signals */
+ child_thread_alive, /* to_thread_alive */
+ child_stop, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* to_sections */
+ 0, /* to_sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_inftarg ()
+{
+#ifdef HAVE_OPTIONAL_PROC_FS
+ char procname[32];
+ int fd;
+
+ /* If we have an optional /proc filesystem (e.g. under OSF/1),
+ don't add ptrace support if we can access the running GDB via /proc. */
+#ifndef PROC_NAME_FMT
+#define PROC_NAME_FMT "/proc/%05d"
+#endif
+ sprintf (procname, PROC_NAME_FMT, getpid ());
+ if ((fd = open (procname, O_RDONLY)) >= 0)
+ {
+ close (fd);
+ return;
+ }
+#endif
+
+ add_target (&child_ops);
+}
diff --git a/contrib/gdb/gdb/irix4-nat.c b/contrib/gdb/gdb/irix4-nat.c
new file mode 100644
index 0000000..8cd9b4c
--- /dev/null
+++ b/contrib/gdb/gdb/irix4-nat.c
@@ -0,0 +1,192 @@
+/* Native support for the SGI Iris running IRIX version 4, for GDB.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1995
+ Free Software Foundation, Inc.
+ Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+ and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+ Implemented for Irix 4.x by Garrett A. Wollman.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+
+#include <sys/time.h>
+#include <sys/procfs.h>
+#include <setjmp.h> /* For JB_XXX. */
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 4
+
+typedef unsigned int greg_t; /* why isn't this defined? */
+
+/*
+ * See the comment in m68k-tdep.c regarding the utility of these functions.
+ */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *)(gregsetp->gp_regs);
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ /* FIXME: somewhere, there should be a #define for the meaning
+ of this magic number 32; we should use that. */
+ for(regi = 0; regi < 32; regi++)
+ supply_register (regi, (char *)(regp + regi));
+
+ supply_register (PC_REGNUM, (char *)&(gregsetp->gp_pc));
+ supply_register (HI_REGNUM, (char *)&(gregsetp->gp_mdhi));
+ supply_register (LO_REGNUM, (char *)&(gregsetp->gp_mdlo));
+ supply_register (CAUSE_REGNUM, (char *)&(gregsetp->gp_cause));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (BADVADDR_REGNUM, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *)(gregsetp->gp_regs);
+
+ /* same FIXME as above wrt 32*/
+ for (regi = 0; regi < 32; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(greg_t *) &registers[REGISTER_BYTE (regi)];
+
+ if ((regno == -1) || (regno == PC_REGNUM))
+ gregsetp->gp_pc = *(greg_t *) &registers[REGISTER_BYTE (PC_REGNUM)];
+
+ if ((regno == -1) || (regno == CAUSE_REGNUM))
+ gregsetp->gp_cause = *(greg_t *) &registers[REGISTER_BYTE (CAUSE_REGNUM)];
+
+ if ((regno == -1) || (regno == HI_REGNUM))
+ gregsetp->gp_mdhi = *(greg_t *) &registers[REGISTER_BYTE (HI_REGNUM)];
+
+ if ((regno == -1) || (regno == LO_REGNUM))
+ gregsetp->gp_mdlo = *(greg_t *) &registers[REGISTER_BYTE (LO_REGNUM)];
+}
+
+/*
+ * Now we do the same thing for floating-point registers.
+ * We don't bother to condition on FP0_REGNUM since any
+ * reasonable MIPS configuration has an R3010 in it.
+ *
+ * Again, see the comments in m68k-tdep.c.
+ */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regi = 0; regi < 32; regi++)
+ supply_register (FP0_REGNUM + regi,
+ (char *)&fpregsetp->fp_r.fp_regs[regi]);
+
+ supply_register (FCRCS_REGNUM, (char *)&fpregsetp->fp_csr);
+
+ /* FIXME: how can we supply FCRIR_REGNUM? SGI doesn't tell us. */
+ supply_register (FCRIR_REGNUM, zerobuf);
+}
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *from, *to;
+
+ for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
+ memcpy(to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+
+ if ((regno == -1) || (regno == FCRCS_REGNUM))
+ fpregsetp->fp_csr = *(unsigned *) &registers[REGISTER_BYTE(FCRCS_REGNUM)];
+}
+
+
+/* Figure out where the longjmp will land.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
+ This routine returns true on success. */
+
+int
+get_longjmp_target (pc)
+ CORE_ADDR *pc;
+{
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ CORE_ADDR jb_addr;
+
+ jb_addr = read_register (A0_REGNUM);
+
+ if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ return 1;
+}
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which; /* Unused */
+ unsigned int reg_addr; /* Unused */
+{
+ if (core_reg_size != REGISTER_BYTES)
+ {
+ warning ("wrong size gregset struct in core file");
+ return;
+ }
+
+ memcpy ((char *)registers, core_reg_sect, core_reg_size);
+}
+
+
+/* Register that we are able to handle irix4 core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns irix4_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_irix4 ()
+{
+ add_core_fns (&irix4_core_fns);
+}
diff --git a/contrib/gdb/gdb/irix5-nat.c b/contrib/gdb/gdb/irix5-nat.c
new file mode 100644
index 0000000..fc4c8cb
--- /dev/null
+++ b/contrib/gdb/gdb/irix5-nat.c
@@ -0,0 +1,1067 @@
+/* Native support for the SGI Iris running IRIX version 5, for GDB.
+ Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+ Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
+ and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
+ Implemented for Irix 4.x by Garrett A. Wollman.
+ Modified for Irix 5.x by Ian Lance Taylor.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+
+#include "gdb_string.h"
+#include <sys/time.h>
+#include <sys/procfs.h>
+#include <setjmp.h> /* For JB_XXX. */
+
+/* Size of elements in jmpbuf */
+
+#define JB_ELEMENT_SIZE 4
+
+/*
+ * See the comment in m68k-tdep.c regarding the utility of these functions.
+ *
+ * These definitions are from the MIPS SVR4 ABI, so they may work for
+ * any MIPS SVR4 target.
+ */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = &(*gregsetp)[0];
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for(regi = 0; regi <= CTX_RA; regi++)
+ supply_register (regi, (char *)(regp + regi));
+
+ supply_register (PC_REGNUM, (char *)(regp + CTX_EPC));
+ supply_register (HI_REGNUM, (char *)(regp + CTX_MDHI));
+ supply_register (LO_REGNUM, (char *)(regp + CTX_MDLO));
+ supply_register (CAUSE_REGNUM, (char *)(regp + CTX_CAUSE));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (BADVADDR_REGNUM, zerobuf);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = &(*gregsetp)[0];
+
+ for (regi = 0; regi <= CTX_RA; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(greg_t *) &registers[REGISTER_BYTE (regi)];
+
+ if ((regno == -1) || (regno == PC_REGNUM))
+ *(regp + CTX_EPC) = *(greg_t *) &registers[REGISTER_BYTE (PC_REGNUM)];
+
+ if ((regno == -1) || (regno == CAUSE_REGNUM))
+ *(regp + CTX_CAUSE) = *(greg_t *) &registers[REGISTER_BYTE (CAUSE_REGNUM)];
+
+ if ((regno == -1) || (regno == HI_REGNUM))
+ *(regp + CTX_MDHI) = *(greg_t *) &registers[REGISTER_BYTE (HI_REGNUM)];
+
+ if ((regno == -1) || (regno == LO_REGNUM))
+ *(regp + CTX_MDLO) = *(greg_t *) &registers[REGISTER_BYTE (LO_REGNUM)];
+}
+
+/*
+ * Now we do the same thing for floating-point registers.
+ * We don't bother to condition on FP0_REGNUM since any
+ * reasonable MIPS configuration has an R3010 in it.
+ *
+ * Again, see the comments in m68k-tdep.c.
+ */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ register int regi;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+
+ for (regi = 0; regi < 32; regi++)
+ supply_register (FP0_REGNUM + regi,
+ (char *)&fpregsetp->fp_r.fp_regs[regi]);
+
+ supply_register (FCRCS_REGNUM, (char *)&fpregsetp->fp_csr);
+
+ /* FIXME: how can we supply FCRIR_REGNUM? SGI doesn't tell us. */
+ supply_register (FCRIR_REGNUM, zerobuf);
+}
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *from, *to;
+
+ for (regi = FP0_REGNUM; regi < FP0_REGNUM + 32; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &(fpregsetp->fp_r.fp_regs[regi - FP0_REGNUM]);
+ memcpy(to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+
+ if ((regno == -1) || (regno == FCRCS_REGNUM))
+ fpregsetp->fp_csr = *(unsigned *) &registers[REGISTER_BYTE(FCRCS_REGNUM)];
+}
+
+
+/* Figure out where the longjmp will land.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
+ This routine returns true on success. */
+
+int
+get_longjmp_target (pc)
+ CORE_ADDR *pc;
+{
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ CORE_ADDR jb_addr;
+
+ jb_addr = read_register (A0_REGNUM);
+
+ if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ return 1;
+}
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which; /* Unused */
+ unsigned int reg_addr; /* Unused */
+{
+ if (core_reg_size != REGISTER_BYTES)
+ {
+ warning ("wrong size gregset struct in core file");
+ return;
+ }
+
+ memcpy ((char *)registers, core_reg_sect, core_reg_size);
+}
+
+/* Irix 5 uses what appears to be a unique form of shared library
+ support. This is a copy of solib.c modified for Irix 5. */
+
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/param.h>
+#include <fcntl.h>
+
+/* <obj.h> includes <sym.h> and <symconst.h>, which causes conflicts
+ with our versions of those files included by tm-mips.h. Prevent
+ <obj.h> from including them with some appropriate defines. */
+#define __SYM_H__
+#define __SYMCONST_H__
+#include <obj.h>
+
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "command.h"
+#include "frame.h"
+#include "gnu-regex.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcmd.h"
+
+/* The symbol which starts off the list of shared libraries. */
+#define DEBUG_BASE "__rld_obj_head"
+
+/* How to get the loaded address of a shared library. */
+#define LM_ADDR(so) ((so)->lm.o_praw)
+
+char shadow_contents[BREAKPOINT_MAX]; /* Stash old bkpt addr contents */
+
+struct so_list {
+ struct so_list *next; /* next structure in linked list */
+ struct obj_list ll;
+ struct obj lm; /* copy of link map from inferior */
+ struct obj_list *lladdr; /* addr in inferior lm was read from */
+ CORE_ADDR lmend; /* upper addr bound of mapped object */
+ char symbols_loaded; /* flag: symbols read in yet? */
+ char from_tty; /* flag: print msgs? */
+ struct objfile *objfile; /* objfile for loaded lib */
+ struct section_table *sections;
+ struct section_table *sections_end;
+ struct section_table *textsection;
+ bfd *abfd;
+};
+
+static struct so_list *so_list_head; /* List of known shared objects */
+static CORE_ADDR debug_base; /* Base of dynamic linker structures */
+static CORE_ADDR breakpoint_addr; /* Address where end bkpt is set */
+
+/* Local function prototypes */
+
+static void
+sharedlibrary_command PARAMS ((char *, int));
+
+static int
+enable_break PARAMS ((void));
+
+static int
+disable_break PARAMS ((void));
+
+static void
+info_sharedlibrary_command PARAMS ((char *, int));
+
+static int
+symbol_add_stub PARAMS ((char *));
+
+static struct so_list *
+find_solib PARAMS ((struct so_list *));
+
+static struct obj_list *
+first_link_map_member PARAMS ((void));
+
+static CORE_ADDR
+locate_base PARAMS ((void));
+
+static void
+solib_map_sections PARAMS ((struct so_list *));
+
+/*
+
+LOCAL FUNCTION
+
+ solib_map_sections -- open bfd and build sections for shared lib
+
+SYNOPSIS
+
+ static void solib_map_sections (struct so_list *so)
+
+DESCRIPTION
+
+ Given a pointer to one of the shared objects in our list
+ of mapped objects, use the recorded name to open a bfd
+ descriptor for the object, build a section table, and then
+ relocate all the section addresses by the base address at
+ which the shared object was mapped.
+
+FIXMES
+
+ In most (all?) cases the shared object file name recorded in the
+ dynamic linkage tables will be a fully qualified pathname. For
+ cases where it isn't, do we really mimic the systems search
+ mechanism correctly in the below code (particularly the tilde
+ expansion stuff?).
+ */
+
+static void
+solib_map_sections (so)
+ struct so_list *so;
+{
+ char *filename;
+ char *scratch_pathname;
+ int scratch_chan;
+ struct section_table *p;
+ struct cleanup *old_chain;
+ bfd *abfd;
+ CORE_ADDR offset;
+
+ filename = tilde_expand (so -> lm.o_path);
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &scratch_pathname);
+ if (scratch_chan < 0)
+ {
+ scratch_chan = openp (getenv ("LD_LIBRARY_PATH"), 1, filename,
+ O_RDONLY, 0, &scratch_pathname);
+ }
+ if (scratch_chan < 0)
+ {
+ perror_with_name (filename);
+ }
+ /* Leave scratch_pathname allocated. abfd->name will point to it. */
+
+ abfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+ if (!abfd)
+ {
+ close (scratch_chan);
+ error ("Could not open `%s' as an executable file: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+ /* Leave bfd open, core_xfer_memory and "info files" need it. */
+ so -> abfd = abfd;
+ abfd -> cacheable = true;
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+ if (build_section_table (abfd, &so -> sections, &so -> sections_end))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ bfd_get_filename (exec_bfd), bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* Irix 5 shared objects are pre-linked to particular addresses
+ although the dynamic linker may have to relocate them if the
+ address ranges of the libraries used by the main program clash.
+ The offset is the difference between the address where the object
+ is mapped and the binding address of the shared library. */
+ offset = (CORE_ADDR) LM_ADDR (so) - so -> lm.o_base_address;
+
+ for (p = so -> sections; p < so -> sections_end; p++)
+ {
+ /* Relocate the section binding addresses as recorded in the shared
+ object's file by the offset to get the address to which the
+ object was actually mapped. */
+ p -> addr += offset;
+ p -> endaddr += offset;
+ so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
+ if (STREQ (p -> the_bfd_section -> name, ".text"))
+ {
+ so -> textsection = p;
+ }
+ }
+
+ /* Free the file names, close the file now. */
+ do_cleanups (old_chain);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ locate_base -- locate the base address of dynamic linker structs
+
+SYNOPSIS
+
+ CORE_ADDR locate_base (void)
+
+DESCRIPTION
+
+ For both the SunOS and SVR4 shared library implementations, if the
+ inferior executable has been linked dynamically, there is a single
+ address somewhere in the inferior's data space which is the key to
+ locating all of the dynamic linker's runtime structures. This
+ address is the value of the symbol defined by the macro DEBUG_BASE.
+ The job of this function is to find and return that address, or to
+ return 0 if there is no such address (the executable is statically
+ linked for example).
+
+ For SunOS, the job is almost trivial, since the dynamic linker and
+ all of it's structures are statically linked to the executable at
+ link time. Thus the symbol for the address we are looking for has
+ already been added to the minimal symbol table for the executable's
+ objfile at the time the symbol file's symbols were read, and all we
+ have to do is look it up there. Note that we explicitly do NOT want
+ to find the copies in the shared library.
+
+ The SVR4 version is much more complicated because the dynamic linker
+ and it's structures are located in the shared C library, which gets
+ run as the executable's "interpreter" by the kernel. We have to go
+ to a lot more work to discover the address of DEBUG_BASE. Because
+ of this complexity, we cache the value we find and return that value
+ on subsequent invocations. Note there is no copy in the executable
+ symbol tables.
+
+ Irix 5 is basically like SunOS.
+
+ Note that we can assume nothing about the process state at the time
+ we need to find this address. We may be stopped on the first instruc-
+ tion of the interpreter (C shared library), the first instruction of
+ the executable itself, or somewhere else entirely (if we attached
+ to the process for example).
+
+ */
+
+static CORE_ADDR
+locate_base ()
+{
+ struct minimal_symbol *msymbol;
+ CORE_ADDR address = 0;
+
+ msymbol = lookup_minimal_symbol (DEBUG_BASE, NULL, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ address = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+ return (address);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ first_link_map_member -- locate first member in dynamic linker's map
+
+SYNOPSIS
+
+ static struct link_map *first_link_map_member (void)
+
+DESCRIPTION
+
+ Read in a copy of the first member in the inferior's dynamic
+ link map from the inferior's dynamic linker structures, and return
+ a pointer to the copy in our address space.
+*/
+
+static struct obj_list *
+first_link_map_member ()
+{
+ struct obj_list *lm;
+ struct obj_list s;
+
+ read_memory (debug_base, (char *) &lm, sizeof (struct obj_list *));
+
+ if (lm == NULL)
+ return NULL;
+
+ /* The first entry in the list is the object file we are debugging,
+ so skip it. */
+ read_memory ((CORE_ADDR) lm, (char *) &s, sizeof (struct obj_list));
+
+ return s.next;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ find_solib -- step through list of shared objects
+
+SYNOPSIS
+
+ struct so_list *find_solib (struct so_list *so_list_ptr)
+
+DESCRIPTION
+
+ This module contains the routine which finds the names of any
+ loaded "images" in the current process. The argument in must be
+ NULL on the first call, and then the returned value must be passed
+ in on subsequent calls. This provides the capability to "step" down
+ the list of loaded objects. On the last object, a NULL value is
+ returned.
+ */
+
+static struct so_list *
+find_solib (so_list_ptr)
+ struct so_list *so_list_ptr; /* Last lm or NULL for first one */
+{
+ struct so_list *so_list_next = NULL;
+ struct obj_list *lm = NULL;
+ struct so_list *new;
+
+ if (so_list_ptr == NULL)
+ {
+ /* We are setting up for a new scan through the loaded images. */
+ if ((so_list_next = so_list_head) == NULL)
+ {
+ /* We have not already read in the dynamic linking structures
+ from the inferior, lookup the address of the base structure. */
+ debug_base = locate_base ();
+ if (debug_base != 0)
+ {
+ /* Read the base structure in and find the address of the first
+ link map list member. */
+ lm = first_link_map_member ();
+ }
+ }
+ }
+ else
+ {
+ /* We have been called before, and are in the process of walking
+ the shared library list. Advance to the next shared object. */
+ if ((lm = so_list_ptr->ll.next) == NULL)
+ {
+ /* We have hit the end of the list, so check to see if any were
+ added, but be quiet if we can't read from the target any more. */
+ int status = target_read_memory ((CORE_ADDR) so_list_ptr -> lladdr,
+ (char *) &(so_list_ptr -> ll),
+ sizeof (struct obj_list));
+ if (status == 0)
+ {
+ lm = so_list_ptr->ll.next;
+ }
+ else
+ {
+ lm = NULL;
+ }
+ }
+ so_list_next = so_list_ptr -> next;
+ }
+ if ((so_list_next == NULL) && (lm != NULL))
+ {
+ int errcode;
+ char *buffer;
+
+ /* Get next link map structure from inferior image and build a local
+ abbreviated load_map structure */
+ new = (struct so_list *) xmalloc (sizeof (struct so_list));
+ memset ((char *) new, 0, sizeof (struct so_list));
+ new -> lladdr = lm;
+ /* Add the new node as the next node in the list, or as the root
+ node if this is the first one. */
+ if (so_list_ptr != NULL)
+ {
+ so_list_ptr -> next = new;
+ }
+ else
+ {
+ so_list_head = new;
+ }
+ so_list_next = new;
+ read_memory ((CORE_ADDR) lm, (char *) &(new -> ll),
+ sizeof (struct obj_list));
+ read_memory ((CORE_ADDR) new->ll.data, (char *) &(new -> lm),
+ sizeof (struct obj));
+ target_read_string ((CORE_ADDR)new->lm.o_path, &buffer,
+ INT_MAX, &errcode);
+ if (errcode != 0)
+ memory_error (errcode, (CORE_ADDR)new->lm.o_path);
+ new->lm.o_path = buffer;
+ solib_map_sections (new);
+ }
+ return (so_list_next);
+}
+
+/* A small stub to get us past the arg-passing pinhole of catch_errors. */
+
+static int
+symbol_add_stub (arg)
+ char *arg;
+{
+ register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+
+ so -> objfile = symbol_file_add (so -> lm.o_path, so -> from_tty,
+ (unsigned int) so -> textsection -> addr,
+ 0, 0, 0);
+ return (1);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_add -- add a shared library file to the symtab and section list
+
+SYNOPSIS
+
+ void solib_add (char *arg_string, int from_tty,
+ struct target_ops *target)
+
+DESCRIPTION
+
+*/
+
+void
+solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+
+ /* Last shared library that we read. */
+ struct so_list *so_last = NULL;
+
+ char *re_err;
+ int count;
+ int old;
+
+ if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+ {
+ error ("Invalid regexp: %s", re_err);
+ }
+
+ /* Add the shared library sections to the section table of the
+ specified target, if any. */
+ if (target)
+ {
+ /* Count how many new section_table entries there are. */
+ so = NULL;
+ count = 0;
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> lm.o_path[0])
+ {
+ count += so -> sections_end - so -> sections;
+ }
+ }
+
+ if (count)
+ {
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ /* Reallocate the target's section table including the new size. */
+ if (target -> to_sections)
+ {
+ old = target -> to_sections_end - target -> to_sections;
+ target -> to_sections = (struct section_table *)
+ xrealloc ((char *)target -> to_sections,
+ (sizeof (struct section_table)) * (count + old));
+ }
+ else
+ {
+ old = 0;
+ target -> to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table)) * count);
+ }
+ target -> to_sections_end = target -> to_sections + (count + old);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* Add these section table entries to the target's table. */
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> lm.o_path[0])
+ {
+ count = so -> sections_end - so -> sections;
+ memcpy ((char *) (target -> to_sections + old),
+ so -> sections,
+ (sizeof (struct section_table)) * count);
+ old += count;
+ }
+ }
+ }
+ }
+
+ /* Now add the symbol files. */
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> lm.o_path[0] && re_exec (so -> lm.o_path))
+ {
+ so -> from_tty = from_tty;
+ if (so -> symbols_loaded)
+ {
+ if (from_tty)
+ {
+ printf_unfiltered ("Symbols already loaded for %s\n", so -> lm.o_path);
+ }
+ }
+ else if (catch_errors
+ (symbol_add_stub, (char *) so,
+ "Error while reading shared library symbols:\n",
+ RETURN_MASK_ALL))
+ {
+ so_last = so;
+ so -> symbols_loaded = 1;
+ }
+ }
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (so_last)
+ reinit_frame_cache ();
+}
+
+/*
+
+LOCAL FUNCTION
+
+ info_sharedlibrary_command -- code for "info sharedlibrary"
+
+SYNOPSIS
+
+ static void info_sharedlibrary_command ()
+
+DESCRIPTION
+
+ Walk through the shared library list and print information
+ about each attached library.
+*/
+
+static void
+info_sharedlibrary_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+ int header_done = 0;
+
+ if (exec_bfd == NULL)
+ {
+ printf_unfiltered ("No exec file.\n");
+ return;
+ }
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> lm.o_path[0])
+ {
+ if (!header_done)
+ {
+ printf_unfiltered("%-12s%-12s%-12s%s\n", "From", "To", "Syms Read",
+ "Shared Object Library");
+ header_done++;
+ }
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom ((unsigned long) LM_ADDR (so),
+ "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom ((unsigned long) so -> lmend,
+ "08l"));
+ printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
+ printf_unfiltered ("%s\n", so -> lm.o_path);
+ }
+ }
+ if (so_list_head == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_address -- check to see if an address is in a shared lib
+
+SYNOPSIS
+
+ char *solib_address (CORE_ADDR address)
+
+DESCRIPTION
+
+ Provides a hook for other gdb routines to discover whether or
+ not a particular address is within the mapped address space of
+ a shared library. Any address between the base mapping address
+ and the first address beyond the end of the last mapping, is
+ considered to be within the shared library address space, for
+ our purposes.
+
+ For example, this routine is called at one point to disable
+ breakpoints which are in shared libraries that are not currently
+ mapped in.
+ */
+
+char *
+solib_address (address)
+ CORE_ADDR address;
+{
+ register struct so_list *so = 0; /* link map state variable */
+
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> lm.o_path[0])
+ {
+ if ((address >= (CORE_ADDR) LM_ADDR (so)) &&
+ (address < (CORE_ADDR) so -> lmend))
+ return (so->lm.o_path);
+ }
+ }
+ return (0);
+}
+
+/* Called by free_all_symtabs */
+
+void
+clear_solib()
+{
+ struct so_list *next;
+ char *bfd_filename;
+
+ while (so_list_head)
+ {
+ if (so_list_head -> sections)
+ {
+ free ((PTR)so_list_head -> sections);
+ }
+ if (so_list_head -> abfd)
+ {
+ bfd_filename = bfd_get_filename (so_list_head -> abfd);
+ if (!bfd_close (so_list_head -> abfd))
+ warning ("cannot close \"%s\": %s",
+ bfd_filename, bfd_errmsg (bfd_get_error ()));
+ }
+ else
+ /* This happens for the executable on SVR4. */
+ bfd_filename = NULL;
+
+ next = so_list_head -> next;
+ if (bfd_filename)
+ free ((PTR)bfd_filename);
+ free (so_list_head->lm.o_path);
+ free ((PTR)so_list_head);
+ so_list_head = next;
+ }
+ debug_base = 0;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ disable_break -- remove the "mapping changed" breakpoint
+
+SYNOPSIS
+
+ static int disable_break ()
+
+DESCRIPTION
+
+ Removes the breakpoint that gets hit when the dynamic linker
+ completes a mapping change.
+
+*/
+
+static int
+disable_break ()
+{
+ int status = 1;
+
+
+ /* Note that breakpoint address and original contents are in our address
+ space, so we just need to write the original contents back. */
+
+ if (memory_remove_breakpoint (breakpoint_addr, shadow_contents) != 0)
+ {
+ status = 0;
+ }
+
+ /* For the SVR4 version, we always know the breakpoint address. For the
+ SunOS version we don't know it until the above code is executed.
+ Grumble if we are stopped anywhere besides the breakpoint address. */
+
+ if (stop_pc != breakpoint_addr)
+ {
+ warning ("stopped at unknown breakpoint while handling shared libraries");
+ }
+
+ return (status);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ enable_break -- arrange for dynamic linker to hit breakpoint
+
+SYNOPSIS
+
+ int enable_break (void)
+
+DESCRIPTION
+
+ This functions inserts a breakpoint at the entry point of the
+ main executable, where all shared libraries are mapped in.
+*/
+
+static int
+enable_break ()
+{
+ if (symfile_objfile != NULL
+ && target_insert_breakpoint (symfile_objfile->ei.entry_point,
+ shadow_contents) == 0)
+ {
+ breakpoint_addr = symfile_objfile->ei.entry_point;
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_create_inferior_hook -- shared library startup support
+
+SYNOPSIS
+
+ void solib_create_inferior_hook()
+
+DESCRIPTION
+
+ When gdb starts up the inferior, it nurses it along (through the
+ shell) until it is ready to execute it's first instruction. At this
+ point, this function gets called via expansion of the macro
+ SOLIB_CREATE_INFERIOR_HOOK.
+
+ For SunOS executables, this first instruction is typically the
+ one at "_start", or a similar text label, regardless of whether
+ the executable is statically or dynamically linked. The runtime
+ startup code takes care of dynamically linking in any shared
+ libraries, once gdb allows the inferior to continue.
+
+ For SVR4 executables, this first instruction is either the first
+ instruction in the dynamic linker (for dynamically linked
+ executables) or the instruction at "start" for statically linked
+ executables. For dynamically linked executables, the system
+ first exec's /lib/libc.so.N, which contains the dynamic linker,
+ and starts it running. The dynamic linker maps in any needed
+ shared libraries, maps in the actual user executable, and then
+ jumps to "start" in the user executable.
+
+ For both SunOS shared libraries, and SVR4 shared libraries, we
+ can arrange to cooperate with the dynamic linker to discover the
+ names of shared libraries that are dynamically linked, and the
+ base addresses to which they are linked.
+
+ This function is responsible for discovering those names and
+ addresses, and saving sufficient information about them to allow
+ their symbols to be read at a later time.
+
+FIXME
+
+ Between enable_break() and disable_break(), this code does not
+ properly handle hitting breakpoints which the user might have
+ set in the startup code or in the dynamic linker itself. Proper
+ handling will probably have to wait until the implementation is
+ changed to use the "breakpoint handler function" method.
+
+ Also, what if child has exit()ed? Must exit loop somehow.
+ */
+
+void
+solib_create_inferior_hook()
+{
+ if (!enable_break ())
+ {
+ warning ("shared library handler failed to enable breakpoint");
+ return;
+ }
+
+ /* Now run the target. It will eventually hit the breakpoint, at
+ which point all of the libraries will have been mapped in and we
+ can go groveling around in the dynamic linker structures to find
+ out what we need to know about them. */
+
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ stop_signal = 0;
+ do
+ {
+ target_resume (-1, 0, stop_signal);
+ wait_for_inferior ();
+ }
+ while (stop_signal != SIGTRAP);
+
+ /* We are now either at the "mapping complete" breakpoint (or somewhere
+ else, a condition we aren't prepared to deal with anyway), so adjust
+ the PC as necessary after a breakpoint, disable the breakpoint, and
+ add any shared libraries that were mapped in. */
+
+ if (DECR_PC_AFTER_BREAK)
+ {
+ stop_pc -= DECR_PC_AFTER_BREAK;
+ write_register (PC_REGNUM, stop_pc);
+ }
+
+ if (!disable_break ())
+ {
+ warning ("shared library handler failed to disable breakpoint");
+ }
+
+ /* solib_add will call reinit_frame_cache.
+ But we are stopped in the startup code and we might not have symbols
+ for the startup code, so heuristic_proc_start could be called
+ and will put out an annoying warning.
+ Delaying the resetting of stop_soon_quietly until after symbol loading
+ suppresses the warning. */
+ if (auto_solib_add)
+ solib_add ((char *) 0, 0, (struct target_ops *) 0);
+ stop_soon_quietly = 0;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ sharedlibrary_command -- handle command to explicitly add library
+
+SYNOPSIS
+
+ static void sharedlibrary_command (char *args, int from_tty)
+
+DESCRIPTION
+
+*/
+
+static void
+sharedlibrary_command (args, from_tty)
+char *args;
+int from_tty;
+{
+ dont_repeat ();
+ solib_add (args, from_tty, (struct target_ops *) 0);
+}
+
+void
+_initialize_solib()
+{
+ add_com ("sharedlibrary", class_files, sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", info_sharedlibrary_command,
+ "Status of loaded shared object libraries.");
+
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded. Otherwise, symbols\n\
+must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+}
+
+
+/* Register that we are able to handle irix5 core file formats.
+ This really is bfd_target_unknown_flavour */
+
+static struct core_fns irix5_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_irix5 ()
+{
+ add_core_fns (&irix5_core_fns);
+}
diff --git a/contrib/gdb/gdb/isi-xdep.c b/contrib/gdb/gdb/isi-xdep.c
new file mode 100644
index 0000000..8773c83
--- /dev/null
+++ b/contrib/gdb/gdb/isi-xdep.c
@@ -0,0 +1,20 @@
+/* Copyright (C) 1993 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <machine/reg.h>
+int rloc[] = {
+ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, FP, SP, PS, PC
+};
diff --git a/contrib/gdb/gdb/kdb-start.c b/contrib/gdb/gdb/kdb-start.c
new file mode 100644
index 0000000..bec558f
--- /dev/null
+++ b/contrib/gdb/gdb/kdb-start.c
@@ -0,0 +1,35 @@
+/* Main loop for the standalone kernel debugger, for GDB, the GNU Debugger.
+ Copyright 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+static char *args[] = {"kdb", "kdb-symbols", 0};
+
+static char *environment[] = {0};
+
+char **environ;
+
+start ()
+{
+ INIT_STACK (kdb_stack_beg, kdb_stack_end);
+
+ environ = environment;
+
+ main (2, args, environment);
+}
diff --git a/contrib/gdb/gdb/language.c b/contrib/gdb/gdb/language.c
new file mode 100644
index 0000000..51ce181
--- /dev/null
+++ b/contrib/gdb/gdb/language.c
@@ -0,0 +1,1400 @@
+/* Multiple source language support for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Contributed by the Department of Computer Science at the State University
+ of New York at Buffalo.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file contains functions that return things that are specific
+ to languages. Each function should examine current_language if necessary,
+ and return the appropriate result. */
+
+/* FIXME: Most of these would be better organized as macros which
+ return data out of a "language-specific" struct pointer that is set
+ whenever the working language changes. That would be a lot faster. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "gdb_string.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "expression.h"
+#include "language.h"
+#include "target.h"
+#include "parser-defs.h"
+
+static void
+show_language_command PARAMS ((char *, int));
+
+static void
+set_language_command PARAMS ((char *, int));
+
+static void
+show_type_command PARAMS ((char *, int));
+
+static void
+set_type_command PARAMS ((char *, int));
+
+static void
+show_range_command PARAMS ((char *, int));
+
+static void
+set_range_command PARAMS ((char *, int));
+
+static void
+set_range_str PARAMS ((void));
+
+static void
+set_type_str PARAMS ((void));
+
+static void
+set_lang_str PARAMS ((void));
+
+static void
+unk_lang_error PARAMS ((char *));
+
+static int
+unk_lang_parser PARAMS ((void));
+
+static void
+show_check PARAMS ((char *, int));
+
+static void
+set_check PARAMS ((char *, int));
+
+static void
+set_type_range PARAMS ((void));
+
+/* Forward declaration */
+extern const struct language_defn unknown_language_defn;
+extern char *warning_pre_print;
+
+/* The current (default at startup) state of type and range checking.
+ (If the modes are set to "auto", though, these are changed based
+ on the default language at startup, and then again based on the
+ language of the first source file. */
+
+enum range_mode range_mode = range_mode_auto;
+enum range_check range_check = range_check_off;
+enum type_mode type_mode = type_mode_auto;
+enum type_check type_check = type_check_off;
+
+/* The current language and language_mode (see language.h) */
+
+const struct language_defn *current_language = &unknown_language_defn;
+enum language_mode language_mode = language_mode_auto;
+
+/* The language that the user expects to be typing in (the language
+ of main(), or the last language we notified them about, or C). */
+
+const struct language_defn *expected_language;
+
+/* The list of supported languages. The list itself is malloc'd. */
+
+static const struct language_defn **languages;
+static unsigned languages_size;
+static unsigned languages_allocsize;
+#define DEFAULT_ALLOCSIZE 4
+
+/* The "set language/type/range" commands all put stuff in these
+ buffers. This is to make them work as set/show commands. The
+ user's string is copied here, then the set_* commands look at
+ them and update them to something that looks nice when it is
+ printed out. */
+
+static char *language;
+static char *type;
+static char *range;
+
+/* Warning issued when current_language and the language of the current
+ frame do not match. */
+char lang_frame_mismatch_warn[] =
+ "Warning: the current language does not match this frame.";
+
+
+/* This page contains the functions corresponding to GDB commands
+ and their helpers. */
+
+/* Show command. Display a warning if the language set
+ does not match the frame. */
+static void
+show_language_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ enum language flang; /* The language of the current frame */
+
+ flang = get_frame_language();
+ if (flang != language_unknown &&
+ language_mode == language_mode_manual &&
+ current_language->la_language != flang)
+ printf_filtered("%s\n",lang_frame_mismatch_warn);
+}
+
+/* Set command. Change the current working language. */
+static void
+set_language_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ int i;
+ enum language flang;
+ char *err_lang;
+
+ if (!language || !language[0])
+ {
+ printf_unfiltered("The currently understood settings are:\n\n");
+ printf_unfiltered ("local or auto Automatic setting based on source file\n");
+
+ for (i = 0; i < languages_size; ++i)
+ {
+ /* Already dealt with these above. */
+ if (languages[i]->la_language == language_unknown
+ || languages[i]->la_language == language_auto)
+ continue;
+
+ /* FIXME for now assume that the human-readable name is just
+ a capitalization of the internal name. */
+ printf_unfiltered ("%-16s Use the %c%s language\n",
+ languages[i]->la_name,
+ /* Capitalize first letter of language
+ name. */
+ toupper (languages[i]->la_name[0]),
+ languages[i]->la_name + 1);
+ }
+ /* Restore the silly string. */
+ set_language(current_language->la_language);
+ return;
+ }
+
+ /* Search the list of languages for a match. */
+ for (i = 0; i < languages_size; i++) {
+ if (STREQ (languages[i]->la_name, language)) {
+ /* Found it! Go into manual mode, and use this language. */
+ if (languages[i]->la_language == language_auto) {
+ /* Enter auto mode. Set to the current frame's language, if known. */
+ language_mode = language_mode_auto;
+ flang = get_frame_language();
+ if (flang!=language_unknown)
+ set_language(flang);
+ expected_language = current_language;
+ return;
+ } else {
+ /* Enter manual mode. Set the specified language. */
+ language_mode = language_mode_manual;
+ current_language = languages[i];
+ set_type_range ();
+ set_lang_str();
+ expected_language = current_language;
+ return;
+ }
+ }
+ }
+
+ /* Reset the language (esp. the global string "language") to the
+ correct values. */
+ err_lang=savestring(language,strlen(language));
+ make_cleanup (free, err_lang); /* Free it after error */
+ set_language(current_language->la_language);
+ error ("Unknown language `%s'.",err_lang);
+}
+
+/* Show command. Display a warning if the type setting does
+ not match the current language. */
+static void
+show_type_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (type_check != current_language->la_type_check)
+ printf_unfiltered(
+"Warning: the current type check setting does not match the language.\n");
+}
+
+/* Set command. Change the setting for type checking. */
+static void
+set_type_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (STREQ(type,"on"))
+ {
+ type_check = type_check_on;
+ type_mode = type_mode_manual;
+ }
+ else if (STREQ(type,"warn"))
+ {
+ type_check = type_check_warn;
+ type_mode = type_mode_manual;
+ }
+ else if (STREQ(type,"off"))
+ {
+ type_check = type_check_off;
+ type_mode = type_mode_manual;
+ }
+ else if (STREQ(type,"auto"))
+ {
+ type_mode = type_mode_auto;
+ set_type_range();
+ /* Avoid hitting the set_type_str call below. We
+ did it in set_type_range. */
+ return;
+ }
+ set_type_str();
+ show_type_command((char *)NULL, from_tty);
+}
+
+/* Show command. Display a warning if the range setting does
+ not match the current language. */
+static void
+show_range_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+
+ if (range_check != current_language->la_range_check)
+ printf_unfiltered(
+"Warning: the current range check setting does not match the language.\n");
+}
+
+/* Set command. Change the setting for range checking. */
+static void
+set_range_command(ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (STREQ(range,"on"))
+ {
+ range_check = range_check_on;
+ range_mode = range_mode_manual;
+ }
+ else if (STREQ(range,"warn"))
+ {
+ range_check = range_check_warn;
+ range_mode = range_mode_manual;
+ }
+ else if (STREQ(range,"off"))
+ {
+ range_check = range_check_off;
+ range_mode = range_mode_manual;
+ }
+ else if (STREQ(range,"auto"))
+ {
+ range_mode = range_mode_auto;
+ set_type_range();
+ /* Avoid hitting the set_range_str call below. We
+ did it in set_type_range. */
+ return;
+ }
+ set_range_str();
+ show_range_command((char *)0, from_tty);
+}
+
+/* Set the status of range and type checking based on
+ the current modes and the current language.
+ If SHOW is non-zero, then print out the current language,
+ type and range checking status. */
+static void
+set_type_range()
+{
+
+ if (range_mode == range_mode_auto)
+ range_check = current_language->la_range_check;
+
+ if (type_mode == type_mode_auto)
+ type_check = current_language->la_type_check;
+
+ set_type_str();
+ set_range_str();
+}
+
+/* Set current language to (enum language) LANG. */
+
+void
+set_language(lang)
+ enum language lang;
+{
+ int i;
+
+ for (i = 0; i < languages_size; i++) {
+ if (languages[i]->la_language == lang) {
+ current_language = languages[i];
+ set_type_range ();
+ set_lang_str();
+ break;
+ }
+ }
+}
+
+/* This page contains functions that update the global vars
+ language, type and range. */
+static void
+set_lang_str()
+{
+ char *prefix = "";
+
+ free (language);
+ if (language_mode == language_mode_auto)
+ prefix = "auto; currently ";
+
+ language = concat(prefix, current_language->la_name, NULL);
+}
+
+static void
+set_type_str()
+{
+ char *tmp, *prefix = "";
+
+ free (type);
+ if (type_mode==type_mode_auto)
+ prefix = "auto; currently ";
+
+ switch(type_check)
+ {
+ case type_check_on:
+ tmp = "on";
+ break;
+ case type_check_off:
+ tmp = "off";
+ break;
+ case type_check_warn:
+ tmp = "warn";
+ break;
+ default:
+ error ("Unrecognized type check setting.");
+ }
+
+ type = concat(prefix,tmp,NULL);
+}
+
+static void
+set_range_str()
+{
+ char *tmp, *pref = "";
+
+ free (range);
+ if (range_mode==range_mode_auto)
+ pref = "auto; currently ";
+
+ switch(range_check)
+ {
+ case range_check_on:
+ tmp = "on";
+ break;
+ case range_check_off:
+ tmp = "off";
+ break;
+ case range_check_warn:
+ tmp = "warn";
+ break;
+ default:
+ error ("Unrecognized range check setting.");
+ }
+
+ range = concat(pref,tmp,NULL);
+}
+
+
+/* Print out the current language settings: language, range and
+ type checking. If QUIETLY, print only what has changed. */
+
+void
+language_info (quietly)
+ int quietly;
+{
+ if (quietly && expected_language == current_language)
+ return;
+
+ expected_language = current_language;
+ printf_unfiltered("Current language: %s\n",language);
+ show_language_command((char *)0, 1);
+
+ if (!quietly)
+ {
+ printf_unfiltered("Type checking: %s\n",type);
+ show_type_command((char *)0, 1);
+ printf_unfiltered("Range checking: %s\n",range);
+ show_range_command((char *)0, 1);
+ }
+}
+
+/* Return the result of a binary operation. */
+
+#if 0 /* Currently unused */
+
+struct type *
+binop_result_type (v1, v2)
+ value_ptr v1, v2;
+{
+ int size,uns;
+ struct type *t1 = check_typedef (VALUE_TYPE (v1));
+ struct type *t2 = check_typedef (VALUE_TYPE (v2));
+
+ int l1 = TYPE_LENGTH (t1);
+ int l2 = TYPE_LENGTH (t2);
+
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ if (TYPE_CODE (t1)==TYPE_CODE_FLT)
+ return TYPE_CODE(t2) == TYPE_CODE_FLT && l2 > l1 ?
+ VALUE_TYPE(v2) : VALUE_TYPE(v1);
+ else if (TYPE_CODE(t2)==TYPE_CODE_FLT)
+ return TYPE_CODE(t1)) == TYPE_CODE_FLT && l1 > l2 ?
+ VALUE_TYPE(v1) : VALUE_TYPE(v2);
+ else if (TYPE_UNSIGNED(t1) && l1 > l2)
+ return VALUE_TYPE(v1);
+ else if (TYPE_UNSIGNED(t2) && l2 > l1)
+ return VALUE_TYPE(v2);
+ else /* Both are signed. Result is the longer type */
+ return l1 > l2 ? VALUE_TYPE(v1) : VALUE_TYPE(v2);
+ break;
+ case language_m2:
+ /* If we are doing type-checking, l1 should equal l2, so this is
+ not needed. */
+ return l1 > l2 ? VALUE_TYPE(v1) : VALUE_TYPE(v2);
+ break;
+ case language_chill:
+ error ("Missing Chill support in function binop_result_check.");/*FIXME*/
+ }
+ abort();
+ return (struct type *)0; /* For lint */
+}
+
+#endif /* 0 */
+
+
+/* This page contains functions that return format strings for
+ printf for printing out numbers in different formats */
+
+/* Returns the appropriate printf format for hexadecimal
+ numbers. */
+char *
+local_hex_format_custom(pre)
+ char *pre;
+{
+ static char form[50];
+
+ strcpy (form, local_hex_format_prefix ());
+ strcat (form, "%");
+ strcat (form, pre);
+ strcat (form, local_hex_format_specifier ());
+ strcat (form, local_hex_format_suffix ());
+ return form;
+}
+
+/* Converts a number to hexadecimal and stores it in a static
+ string. Returns a pointer to this string. */
+char *
+local_hex_string (num)
+ unsigned long num;
+{
+ static char res[50];
+
+ sprintf (res, local_hex_format(), num);
+ return res;
+}
+
+/* Converts a number to custom hexadecimal and stores it in a static
+ string. Returns a pointer to this string. */
+char *
+local_hex_string_custom(num,pre)
+ unsigned long num;
+ char *pre;
+{
+ static char res[50];
+
+ sprintf (res, local_hex_format_custom(pre), num);
+ return res;
+}
+
+/* Returns the appropriate printf format for octal
+ numbers. */
+char *
+local_octal_format_custom(pre)
+ char *pre;
+{
+ static char form[50];
+
+ strcpy (form, local_octal_format_prefix ());
+ strcat (form, "%");
+ strcat (form, pre);
+ strcat (form, local_octal_format_specifier ());
+ strcat (form, local_octal_format_suffix ());
+ return form;
+}
+
+/* Returns the appropriate printf format for decimal numbers. */
+char *
+local_decimal_format_custom(pre)
+ char *pre;
+{
+ static char form[50];
+
+ strcpy (form, local_decimal_format_prefix ());
+ strcat (form, "%");
+ strcat (form, pre);
+ strcat (form, local_decimal_format_specifier ());
+ strcat (form, local_decimal_format_suffix ());
+ return form;
+}
+
+#if 0
+/* This page contains functions that are used in type/range checking.
+ They all return zero if the type/range check fails.
+
+ It is hoped that these will make extending GDB to parse different
+ languages a little easier. These are primarily used in eval.c when
+ evaluating expressions and making sure that their types are correct.
+ Instead of having a mess of conjucted/disjuncted expressions in an "if",
+ the ideas of type can be wrapped up in the following functions.
+
+ Note that some of them are not currently dependent upon which language
+ is currently being parsed. For example, floats are the same in
+ C and Modula-2 (ie. the only floating point type has TYPE_CODE of
+ TYPE_CODE_FLT), while booleans are different. */
+
+/* Returns non-zero if its argument is a simple type. This is the same for
+ both Modula-2 and for C. In the C case, TYPE_CODE_CHAR will never occur,
+ and thus will never cause the failure of the test. */
+int
+simple_type(type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type)) {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_BOOL:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Returns non-zero if its argument is of an ordered type.
+ An ordered type is one in which the elements can be tested for the
+ properties of "greater than", "less than", etc, or for which the
+ operations "increment" or "decrement" make sense. */
+int
+ordered_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type)) {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_ENUM:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_RANGE:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Returns non-zero if the two types are the same */
+int
+same_type (arg1, arg2)
+ struct type *arg1, *arg2;
+{
+ CHECK_TYPEDEF (type);
+ if (structured_type(arg1) ? !structured_type(arg2) : structured_type(arg2))
+ /* One is structured and one isn't */
+ return 0;
+ else if (structured_type(arg1) && structured_type(arg2))
+ return arg1 == arg2;
+ else if (numeric_type(arg1) && numeric_type(arg2))
+ return (TYPE_CODE(arg2) == TYPE_CODE(arg1)) &&
+ (TYPE_UNSIGNED(arg1) == TYPE_UNSIGNED(arg2))
+ ? 1 : 0;
+ else
+ return arg1==arg2;
+}
+
+/* Returns non-zero if the type is integral */
+int
+integral_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ return (TYPE_CODE(type) != TYPE_CODE_INT) &&
+ (TYPE_CODE(type) != TYPE_CODE_ENUM) ? 0 : 1;
+ case language_m2:
+ return TYPE_CODE(type) != TYPE_CODE_INT ? 0 : 1;
+ case language_chill:
+ error ("Missing Chill support in function integral_type."); /*FIXME*/
+ default:
+ error ("Language not supported.");
+ }
+}
+
+/* Returns non-zero if the value is numeric */
+int
+numeric_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type)) {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_FLT:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Returns non-zero if the value is a character type */
+int
+character_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ switch(current_language->la_language)
+ {
+ case language_chill:
+ case language_m2:
+ return TYPE_CODE(type) != TYPE_CODE_CHAR ? 0 : 1;
+
+ case language_c:
+ case language_cplus:
+ return (TYPE_CODE(type) == TYPE_CODE_INT) &&
+ TYPE_LENGTH(type) == sizeof(char)
+ ? 1 : 0;
+ default:
+ return (0);
+ }
+}
+
+/* Returns non-zero if the value is a string type */
+int
+string_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ switch(current_language->la_language)
+ {
+ case language_chill:
+ case language_m2:
+ return TYPE_CODE(type) != TYPE_CODE_STRING ? 0 : 1;
+
+ case language_c:
+ case language_cplus:
+ /* C does not have distinct string type. */
+ return (0);
+ default:
+ return (0);
+ }
+}
+
+/* Returns non-zero if the value is a boolean type */
+int
+boolean_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ 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:
+ break;
+ }
+ return 0;
+}
+
+/* Returns non-zero if the value is a floating-point type */
+int
+float_type (type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ return TYPE_CODE(type) == TYPE_CODE_FLT;
+}
+
+/* Returns non-zero if the value is a pointer type */
+int
+pointer_type(type)
+ struct type *type;
+{
+ return TYPE_CODE(type) == TYPE_CODE_PTR ||
+ TYPE_CODE(type) == TYPE_CODE_REF;
+}
+
+/* Returns non-zero if the value is a structured type */
+int
+structured_type(type)
+ struct type *type;
+{
+ CHECK_TYPEDEF (type);
+ switch(current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ return (TYPE_CODE(type) == TYPE_CODE_STRUCT) ||
+ (TYPE_CODE(type) == TYPE_CODE_UNION) ||
+ (TYPE_CODE(type) == TYPE_CODE_ARRAY);
+ case language_m2:
+ return (TYPE_CODE(type) == TYPE_CODE_STRUCT) ||
+ (TYPE_CODE(type) == TYPE_CODE_SET) ||
+ (TYPE_CODE(type) == TYPE_CODE_ARRAY);
+ case language_chill:
+ error ("Missing Chill support in function structured_type."); /*FIXME*/
+ default:
+ return (0);
+ }
+}
+#endif
+
+struct type *
+lang_bool_type ()
+{
+ struct symbol *sym;
+ struct type *type;
+ switch(current_language->la_language)
+ {
+ case language_chill:
+ return builtin_type_chill_bool;
+ case language_fortran:
+ sym = lookup_symbol ("logical", NULL, VAR_NAMESPACE, NULL, NULL);
+ if (sym)
+ {
+ type = SYMBOL_TYPE (sym);
+ if (type && TYPE_CODE (type) == TYPE_CODE_BOOL)
+ return type;
+ }
+ return builtin_type_f_logical_s2;
+ case language_cplus:
+ sym = lookup_symbol ("bool", NULL, VAR_NAMESPACE, NULL, NULL);
+ if (sym)
+ {
+ type = SYMBOL_TYPE (sym);
+ if (type && TYPE_CODE (type) == TYPE_CODE_BOOL)
+ return type;
+ }
+ /* ... else fall through ... */
+ default:
+ return builtin_type_int;
+ }
+}
+
+/* This page contains functions that return info about
+ (struct value) values used in GDB. */
+
+/* Returns non-zero if the value VAL represents a true value. */
+int
+value_true (val)
+ value_ptr val;
+{
+ /* 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
+ the values ARG1 and ARG2. */
+
+#if 0 /* Currently unused */
+
+void
+binop_type_check(arg1,arg2,op)
+ value_ptr arg1,arg2;
+ int op;
+{
+ struct type *t1, *t2;
+
+ /* If we're not checking types, always return success. */
+ if (!STRICT_TYPE)
+ return;
+
+ t1=VALUE_TYPE(arg1);
+ if (arg2 != NULL)
+ t2=VALUE_TYPE(arg2);
+ else
+ t2=NULL;
+
+ switch(op)
+ {
+ case BINOP_ADD:
+ case BINOP_SUB:
+ if ((numeric_type(t1) && pointer_type(t2)) ||
+ (pointer_type(t1) && numeric_type(t2)))
+ {
+ warning ("combining pointer and integer.\n");
+ break;
+ }
+ case BINOP_MUL:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ if (!numeric_type(t1) || !numeric_type(t2))
+ type_op_error ("Arguments to %s must be numbers.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_LOGICAL_AND:
+ case BINOP_LOGICAL_OR:
+ if (!boolean_type(t1) || !boolean_type(t2))
+ type_op_error ("Arguments to %s must be of boolean type.",op);
+ break;
+
+ case BINOP_EQUAL:
+ if ((pointer_type(t1) && !(pointer_type(t2) || integral_type(t2))) ||
+ (pointer_type(t2) && !(pointer_type(t1) || integral_type(t1))))
+ type_op_error ("A pointer can only be compared to an integer or pointer.",op);
+ else if ((pointer_type(t1) && integral_type(t2)) ||
+ (integral_type(t1) && pointer_type(t2)))
+ {
+ warning ("combining integer and pointer.\n");
+ break;
+ }
+ else if (!simple_type(t1) || !simple_type(t2))
+ type_op_error ("Arguments to %s must be of simple type.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_REM:
+ case BINOP_MOD:
+ if (!integral_type(t1) || !integral_type(t2))
+ type_op_error ("Arguments to %s must be of integral type.",op);
+ break;
+
+ case BINOP_LESS:
+ case BINOP_GTR:
+ case BINOP_LEQ:
+ case BINOP_GEQ:
+ if (!ordered_type(t1) || !ordered_type(t2))
+ type_op_error ("Arguments to %s must be of ordered type.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_ASSIGN:
+ if (pointer_type(t1) && !integral_type(t2))
+ type_op_error ("A pointer can only be assigned an integer.",op);
+ else if (pointer_type(t1) && integral_type(t2))
+ {
+ warning ("combining integer and pointer.");
+ break;
+ }
+ else if (!simple_type(t1) || !simple_type(t2))
+ type_op_error ("Arguments to %s must be of simple type.",op);
+ else if (!same_type(t1,t2))
+ type_op_error ("Arguments to %s must be of the same type.",op);
+ break;
+
+ case BINOP_CONCAT:
+ /* FIXME: Needs to handle bitstrings as well. */
+ if (!(string_type(t1) || character_type(t1) || integral_type(t1))
+ || !(string_type(t2) || character_type(t2) || integral_type(t2)))
+ type_op_error ("Arguments to %s must be strings or characters.", op);
+ break;
+
+ /* Unary checks -- arg2 is null */
+
+ case UNOP_LOGICAL_NOT:
+ if (!boolean_type(t1))
+ type_op_error ("Argument to %s must be of boolean type.",op);
+ break;
+
+ case UNOP_PLUS:
+ case UNOP_NEG:
+ if (!numeric_type(t1))
+ type_op_error ("Argument to %s must be of numeric type.",op);
+ break;
+
+ case UNOP_IND:
+ if (integral_type(t1))
+ {
+ warning ("combining pointer and integer.\n");
+ break;
+ }
+ else if (!pointer_type(t1))
+ type_op_error ("Argument to %s must be a pointer.",op);
+ break;
+
+ case UNOP_PREINCREMENT:
+ case UNOP_POSTINCREMENT:
+ case UNOP_PREDECREMENT:
+ case UNOP_POSTDECREMENT:
+ if (!ordered_type(t1))
+ type_op_error ("Argument to %s must be of an ordered type.",op);
+ break;
+
+ default:
+ /* Ok. The following operators have different meanings in
+ different languages. */
+ switch(current_language->la_language)
+ {
+#ifdef _LANG_c
+ case language_c:
+ case language_cplus:
+ switch(op)
+ {
+ case BINOP_DIV:
+ if (!numeric_type(t1) || !numeric_type(t2))
+ type_op_error ("Arguments to %s must be numbers.",op);
+ break;
+ }
+ break;
+#endif
+
+#ifdef _LANG_m2
+ case language_m2:
+ switch(op)
+ {
+ case BINOP_DIV:
+ if (!float_type(t1) || !float_type(t2))
+ type_op_error ("Arguments to %s must be floating point numbers.",op);
+ break;
+ case BINOP_INTDIV:
+ if (!integral_type(t1) || !integral_type(t2))
+ type_op_error ("Arguments to %s must be of integral type.",op);
+ break;
+ }
+#endif
+
+#ifdef _LANG_chill
+ case language_chill:
+ error ("Missing Chill support in function binop_type_check.");/*FIXME*/
+#endif
+
+ }
+ }
+}
+
+#endif /* 0 */
+
+
+/* This page contains functions for the printing out of
+ error messages that occur during type- and range-
+ checking. */
+
+/* Prints the format string FMT with the operator as a string
+ corresponding to the opcode OP. If FATAL is non-zero, then
+ this is an error and error () is called. Otherwise, it is
+ a warning and printf() is called. */
+void
+op_error (fmt,op,fatal)
+ char *fmt;
+ enum exp_opcode op;
+ int fatal;
+{
+ if (fatal)
+ error (fmt,op_string(op));
+ else
+ {
+ warning (fmt,op_string(op));
+ }
+}
+
+/* These are called when a language fails a type- or range-check.
+ The first argument should be a printf()-style format string, and
+ the rest of the arguments should be its arguments. If
+ [type|range]_check is [type|range]_check_on, then return_to_top_level()
+ is called in the style of error (). Otherwise, the message is prefixed
+ by the value of warning_pre_print and we do not return to the top level. */
+
+void
+#ifdef ANSI_PROTOTYPES
+type_error (char *string, ...)
+#else
+type_error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+
+ if (type_check == type_check_warn)
+ fprintf_filtered (gdb_stderr, warning_pre_print);
+ else
+ error_begin ();
+
+ 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);
+}
+
+void
+#ifdef ANSI_PROTOTYPES
+range_error (char *string, ...)
+#else
+range_error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+
+ if (range_check == range_check_warn)
+ fprintf_filtered (gdb_stderr, warning_pre_print);
+ else
+ error_begin ();
+
+ 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);
+}
+
+
+/* This page contains miscellaneous functions */
+
+/* Return the language struct for a given language enum. */
+
+const struct language_defn *
+language_def(lang)
+ enum language lang;
+{
+ int i;
+
+ for (i = 0; i < languages_size; i++) {
+ if (languages[i]->la_language == lang) {
+ return languages[i];
+ }
+ }
+ return NULL;
+}
+
+/* Return the language as a string */
+char *
+language_str(lang)
+ enum language lang;
+{
+ int i;
+
+ for (i = 0; i < languages_size; i++) {
+ if (languages[i]->la_language == lang) {
+ return languages[i]->la_name;
+ }
+ }
+ return "Unknown";
+}
+
+static void
+set_check (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ printf_unfiltered(
+"\"set check\" must be followed by the name of a check subcommand.\n");
+ help_list(setchecklist, "set check ", -1, gdb_stdout);
+}
+
+static void
+show_check (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ cmd_show_list(showchecklist, from_tty, "");
+}
+
+/* Add a language to the set of known languages. */
+
+void
+add_language (lang)
+ const struct language_defn *lang;
+{
+ if (lang->la_magic != LANG_MAGIC)
+ {
+ fprintf_unfiltered(gdb_stderr, "Magic number of %s language struct wrong\n",
+ lang->la_name);
+ abort();
+ }
+
+ if (!languages)
+ {
+ languages_allocsize = DEFAULT_ALLOCSIZE;
+ languages = (const struct language_defn **) xmalloc
+ (languages_allocsize * sizeof (*languages));
+ }
+ if (languages_size >= languages_allocsize)
+ {
+ languages_allocsize *= 2;
+ languages = (const struct language_defn **) xrealloc ((char *) languages,
+ languages_allocsize * sizeof (*languages));
+ }
+ languages[languages_size++] = lang;
+}
+
+/* Define the language that is no language. */
+
+static int
+unk_lang_parser ()
+{
+ return 1;
+}
+
+static void
+unk_lang_error (msg)
+ char *msg;
+{
+ error ("Attempted to parse an expression with unknown language");
+}
+
+static void
+unk_lang_printchar (c, stream)
+ register int c;
+ GDB_FILE *stream;
+{
+ error ("internal error - unimplemented function unk_lang_printchar called.");
+}
+
+static void
+unk_lang_printstr (stream, string, length, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ error ("internal error - unimplemented function unk_lang_printstr called.");
+}
+
+static struct type *
+unk_lang_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ error ("internal error - unimplemented function unk_lang_create_fundamental_type called.");
+}
+
+void
+unk_lang_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ error ("internal error - unimplemented function unk_lang_print_type called.");
+}
+
+int
+unk_lang_val_print (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;
+{
+ 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}
+};
+
+const struct language_defn unknown_language_defn = {
+ "unknown",
+ language_unknown,
+ &unknown_builtin_types[0],
+ range_check_off,
+ type_check_off,
+ unk_lang_parser,
+ unk_lang_error,
+ evaluate_subexp_standard,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ 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 */
+ unk_lang_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ unk_op_print_tab, /* expression operators for printing */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+/* These two structs define fake entries for the "local" and "auto" options. */
+const struct language_defn auto_language_defn = {
+ "auto",
+ language_auto,
+ &unknown_builtin_types[0],
+ range_check_off,
+ type_check_off,
+ unk_lang_parser,
+ unk_lang_error,
+ evaluate_subexp_standard,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ 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 */
+ unk_lang_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ unk_op_print_tab, /* expression operators for printing */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+const struct language_defn local_language_defn = {
+ "local",
+ language_auto,
+ &unknown_builtin_types[0],
+ range_check_off,
+ type_check_off,
+ unk_lang_parser,
+ unk_lang_error,
+ evaluate_subexp_standard,
+ unk_lang_printchar, /* Print character constant */
+ unk_lang_printstr,
+ 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 */
+ unk_lang_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"0%lo", "0", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0x%lx", "0x", "x", ""}, /* Hex format info */
+ unk_op_print_tab, /* expression operators for printing */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+/* Initialize the language routines */
+
+void
+_initialize_language()
+{
+ struct cmd_list_element *set, *show;
+
+ /* GDB commands for language specific stuff */
+
+ set = add_set_cmd ("language", class_support, var_string_noescape,
+ (char *)&language,
+ "Set the current source language.",
+ &setlist);
+ show = add_show_from_set (set, &showlist);
+ set->function.cfunc = set_language_command;
+ show->function.cfunc = show_language_command;
+
+ add_prefix_cmd ("check", no_class, set_check,
+ "Set the status of the type/range checker",
+ &setchecklist, "set check ", 0, &setlist);
+ add_alias_cmd ("c", "check", no_class, 1, &setlist);
+ add_alias_cmd ("ch", "check", no_class, 1, &setlist);
+
+ add_prefix_cmd ("check", no_class, show_check,
+ "Show the status of the type/range checker",
+ &showchecklist, "show check ", 0, &showlist);
+ add_alias_cmd ("c", "check", no_class, 1, &showlist);
+ add_alias_cmd ("ch", "check", no_class, 1, &showlist);
+
+ set = add_set_cmd ("type", class_support, var_string_noescape,
+ (char *)&type,
+ "Set type checking. (on/warn/off/auto)",
+ &setchecklist);
+ show = add_show_from_set (set, &showchecklist);
+ set->function.cfunc = set_type_command;
+ show->function.cfunc = show_type_command;
+
+ set = add_set_cmd ("range", class_support, var_string_noescape,
+ (char *)&range,
+ "Set range checking. (on/warn/off/auto)",
+ &setchecklist);
+ show = add_show_from_set (set, &showchecklist);
+ set->function.cfunc = set_range_command;
+ show->function.cfunc = show_range_command;
+
+ add_language (&unknown_language_defn);
+ add_language (&local_language_defn);
+ add_language (&auto_language_defn);
+
+ language = savestring ("auto",strlen("auto"));
+ range = savestring ("auto",strlen("auto"));
+ type = savestring ("auto",strlen("auto"));
+
+ /* Have the above take effect */
+
+ set_language_command (language, 0);
+ set_type_command (NULL, 0);
+ set_range_command (NULL, 0);
+}
diff --git a/contrib/gdb/gdb/language.h b/contrib/gdb/gdb/language.h
new file mode 100644
index 0000000..941943b
--- /dev/null
+++ b/contrib/gdb/gdb/language.h
@@ -0,0 +1,431 @@
+/* Source-language-related definitions for GDB.
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ Contributed by the Department of Computer Science at the State University
+ of New York at Buffalo.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (LANGUAGE_H)
+#define LANGUAGE_H 1
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+struct objfile;
+struct expression;
+/* enum exp_opcode; ANSI's `wisdom' didn't include forward enum decls. */
+#endif
+
+/* This used to be included to configure GDB for one or more specific
+ languages. Now it is shortcutted to configure for all of them. FIXME. */
+/* #include "lang_def.h" */
+#define _LANG_c
+#define _LANG_m2
+#define _LANG_chill
+#define _LANG_fortran
+
+#define MAX_FORTRAN_DIMS 7 /* Maximum number of F77 array dims */
+
+/* range_mode ==
+ range_mode_auto: range_check set automatically to default of language.
+ range_mode_manual: range_check set manually by user. */
+
+extern enum range_mode {range_mode_auto, range_mode_manual} range_mode;
+
+/* range_check ==
+ range_check_on: Ranges are checked in GDB expressions, producing errors.
+ range_check_warn: Ranges are checked, producing warnings.
+ range_check_off: Ranges are not checked in GDB expressions. */
+
+extern enum range_check
+ {range_check_off, range_check_warn, range_check_on} range_check;
+
+/* type_mode ==
+ type_mode_auto: type_check set automatically to default of language
+ type_mode_manual: type_check set manually by user. */
+
+extern enum type_mode {type_mode_auto, type_mode_manual} type_mode;
+
+/* type_check ==
+ type_check_on: Types are checked in GDB expressions, producing errors.
+ type_check_warn: Types are checked, producing warnings.
+ type_check_off: Types are not checked in GDB expressions. */
+
+extern enum type_check
+ {type_check_off, type_check_warn, type_check_on} type_check;
+
+/* Information for doing language dependent formatting of printed values. */
+
+struct language_format_info
+{
+ /* The format that can be passed directly to standard C printf functions
+ to generate a completely formatted value in the format appropriate for
+ the language. */
+
+ char *la_format;
+
+ /* The prefix to be used when directly printing a value, or constructing
+ a standard C printf format. This generally is everything up to the
+ conversion specification (the part introduced by the '%' character
+ and terminated by the conversion specifier character). */
+
+ char *la_format_prefix;
+
+ /* The conversion specifier. This is generally everything after the
+ field width and precision, typically only a single character such
+ as 'o' for octal format or 'x' for hexadecimal format. */
+
+ char *la_format_specifier;
+
+ /* The suffix to be used when directly printing a value, or constructing
+ a standard C printf format. This generally is everything after the
+ conversion specification (the part introduced by the '%' character
+ and terminated by the conversion specifier character). */
+
+ char *la_format_suffix; /* Suffix for custom format string */
+};
+
+/* Structure tying together assorted information about a language. */
+
+struct language_defn
+{
+ /* Name of the language */
+
+ char *la_name;
+
+ /* its symtab language-enum (defs.h) */
+
+ enum language la_language;
+
+ /* 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;
+
+ /* Default range checking */
+
+ enum range_check la_range_check;
+
+ /* Default type checking */
+
+ enum type_check la_type_check;
+
+ /* Parser function. */
+
+ int (*la_parser) PARAMS((void));
+
+ /* Parser error function */
+
+ void (*la_error) PARAMS ((char *));
+
+ /* Evaluate an expression. */
+ struct value * (*evaluate_exp) PARAMS ((struct type*, struct expression *,
+ int *, enum noside));
+
+ void (*la_printchar) PARAMS ((int, GDB_FILE *));
+
+ 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 *, GDB_FILE *, int, int));
+
+ /* Print a value using syntax appropriate for this language. */
+
+ int (*la_val_print) PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *,
+ int, int, int, enum val_prettyprint));
+
+ /* Print a top-level value using syntax appropriate for this language. */
+
+ int (*la_value_print) PARAMS ((struct value *, GDB_FILE *,
+ int, enum val_prettyprint));
+
+ /* Base 2 (binary) formats. */
+
+ struct language_format_info la_binary_format;
+
+ /* Base 8 (octal) formats. */
+
+ struct language_format_info la_octal_format;
+
+ /* Base 10 (decimal) formats */
+
+ struct language_format_info la_decimal_format;
+
+ /* Base 16 (hexadecimal) formats */
+
+ struct language_format_info la_hex_format;
+
+ /* Table for printing expressions */
+
+ const struct op_print *la_op_print_tab;
+
+ /* Zero if the language has first-class arrays. True if there are no
+ array values, and array objects decay to pointers, as in C. */
+
+ char c_style_arrays;
+
+ /* Index to use for extracting the first element of a string. */
+ char string_lower_bound;
+
+ /* Type of elements of strings. */
+ struct type **string_char_type;
+
+ /* Add fields above this point, so the magic number is always last. */
+ /* Magic number for compat checking */
+
+ long la_magic;
+
+};
+
+#define LANG_MAGIC 910823L
+
+/* Pointer to the language_defn for our current language. This pointer
+ always points to *some* valid struct; it can be used without checking
+ it for validity.
+
+ The current language affects expression parsing and evaluation
+ (FIXME: it might be cleaner to make the evaluation-related stuff
+ separate exp_opcodes for each different set of semantics. We
+ should at least think this through more clearly with respect to
+ what happens if the language is changed between parsing and
+ evaluation) and printing of things like types and arrays. It does
+ *not* affect symbol-reading-- each source file in a symbol-file has
+ its own language and we should keep track of that regardless of the
+ language when symbols are read. If we want some manual setting for
+ the language of symbol files (e.g. detecting when ".c" files are
+ C++), it should be a seprate setting from the current_language. */
+
+extern const struct language_defn *current_language;
+
+/* Pointer to the language_defn expected by the user, e.g. the language
+ of main(), or the language we last mentioned in a message, or C. */
+
+extern const struct language_defn *expected_language;
+
+/* language_mode ==
+ language_mode_auto: current_language automatically set upon selection
+ of scope (e.g. stack frame)
+ language_mode_manual: current_language set only by user. */
+
+extern enum language_mode
+ {language_mode_auto, language_mode_manual} language_mode;
+
+/* These macros define the behaviour of the expression
+ evaluator. */
+
+/* Should we strictly type check expressions? */
+#define STRICT_TYPE (type_check != type_check_off)
+
+/* Should we range check values against the domain of their type? */
+#define RANGE_CHECK (range_check != range_check_off)
+
+/* "cast" really means conversion */
+/* FIXME -- should be a setting in language_defn */
+#define CAST_IS_CONVERSION (current_language->la_language == language_c || \
+ current_language->la_language == language_cplus)
+
+extern void
+language_info PARAMS ((int));
+
+extern void
+set_language PARAMS ((enum language));
+
+
+/* This page contains functions that return things that are
+ specific to languages. Each of these functions is based on
+ the current setting of working_lang, which the user sets
+ with the "set language" command. */
+
+#define create_fundamental_type(objfile,typeid) \
+ (current_language->la_fund_type(objfile, typeid))
+
+#define LA_PRINT_TYPE(type,varstring,stream,show,level) \
+ (current_language->la_print_type(type,varstring,stream,show,level))
+
+#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
+ overwritten by the next call. Takes printf options like "08" or "l"
+ (to produce e.g. %08x or %lx). */
+
+#define local_binary_format() \
+ (current_language->la_binary_format.la_format)
+#define local_binary_format_prefix() \
+ (current_language->la_binary_format.la_format_prefix)
+#define local_binary_format_specifier() \
+ (current_language->la_binary_format.la_format_specifier)
+#define local_binary_format_suffix() \
+ (current_language->la_binary_format.la_format_suffix)
+
+#define local_octal_format() \
+ (current_language->la_octal_format.la_format)
+#define local_octal_format_prefix() \
+ (current_language->la_octal_format.la_format_prefix)
+#define local_octal_format_specifier() \
+ (current_language->la_octal_format.la_format_specifier)
+#define local_octal_format_suffix() \
+ (current_language->la_octal_format.la_format_suffix)
+
+#define local_decimal_format() \
+ (current_language->la_decimal_format.la_format)
+#define local_decimal_format_prefix() \
+ (current_language->la_decimal_format.la_format_prefix)
+#define local_decimal_format_specifier() \
+ (current_language->la_decimal_format.la_format_specifier)
+#define local_decimal_format_suffix() \
+ (current_language->la_decimal_format.la_format_suffix)
+
+#define local_hex_format() \
+ (current_language->la_hex_format.la_format)
+#define local_hex_format_prefix() \
+ (current_language->la_hex_format.la_format_prefix)
+#define local_hex_format_specifier() \
+ (current_language->la_hex_format.la_format_specifier)
+#define local_hex_format_suffix() \
+ (current_language->la_hex_format.la_format_suffix)
+
+#define LA_PRINT_CHAR(ch, stream) \
+ (current_language->la_printchar(ch, stream))
+#define LA_PRINT_STRING(stream, string, length, force_ellipses) \
+ (current_language->la_printstr(stream, string, length, force_ellipses))
+
+/* Test a character to decide whether it can be printed in literal form
+ or needs to be printed in another representation. For example,
+ in C the literal form of the character with octal value 141 is 'a'
+ and the "other representation" is '\141'. The "other representation"
+ is program language dependent. */
+
+#define PRINT_LITERAL_FORM(c) \
+ ((c)>=0x20 && ((c)<0x7F || (c)>=0xA0) && (!sevenbit_strings || (c)<0x80))
+
+/* Return a format string for printf that will print a number in one of
+ the local (language-specific) formats. Result is static and is
+ overwritten by the next call. Takes printf options like "08" or "l"
+ (to produce e.g. %08x or %lx). */
+
+extern char *
+local_decimal_format_custom PARAMS ((char *)); /* language.c */
+
+extern char *
+local_octal_format_custom PARAMS ((char *)); /* language.c */
+
+extern char *
+local_hex_format_custom PARAMS ((char *)); /* language.c */
+
+/* Return a string that contains a number formatted in one of the local
+ (language-specific) formats. Result is static and is overwritten by
+ the next call. Takes printf options like "08" or "l". */
+
+extern char *
+local_hex_string PARAMS ((unsigned long)); /* language.c */
+
+extern char *
+local_hex_string_custom PARAMS ((unsigned long, char *)); /* language.c */
+
+/* Type predicates */
+
+extern int
+simple_type PARAMS ((struct type *));
+
+extern int
+ordered_type PARAMS ((struct type *));
+
+extern int
+same_type PARAMS ((struct type *, struct type *));
+
+extern int
+integral_type PARAMS ((struct type *));
+
+extern int
+numeric_type PARAMS ((struct type *));
+
+extern int
+character_type PARAMS ((struct type *));
+
+extern int
+boolean_type PARAMS ((struct type *));
+
+extern int
+float_type PARAMS ((struct type *));
+
+extern int
+pointer_type PARAMS ((struct type *));
+
+extern int
+structured_type PARAMS ((struct type *));
+
+/* Checks Binary and Unary operations for semantic type correctness */
+/* FIXME: Does not appear to be used */
+#define unop_type_check(v,o) binop_type_check((v),NULL,(o))
+
+extern void
+binop_type_check PARAMS ((struct value *, struct value *, int));
+
+/* Error messages */
+
+extern void
+op_error PARAMS ((char *fmt, enum exp_opcode, int));
+
+#define type_op_error(f,o) \
+ op_error((f),(o),type_check==type_check_on ? 1 : 0)
+#define range_op_error(f,o) \
+ op_error((f),(o),range_check==range_check_on ? 1 : 0)
+
+extern void
+type_error PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+void
+range_error PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+
+/* Data: Does this value represent "truth" to the current language? */
+
+extern int
+value_true PARAMS ((struct value *));
+
+extern struct type * lang_bool_type PARAMS ((void));
+
+/* The type used for Boolean values in the current language. */
+#define LA_BOOL_TYPE lang_bool_type ()
+
+/* Misc: The string representing a particular enum language. */
+
+extern const struct language_defn *
+language_def PARAMS ((enum language));
+
+extern char *
+language_str PARAMS ((enum language));
+
+/* Add a language to the set known by GDB (at initialization time). */
+
+extern void
+add_language PARAMS ((const struct language_defn *));
+
+extern enum language
+get_frame_language PARAMS ((void)); /* In stack.c */
+
+#endif /* defined (LANGUAGE_H) */
diff --git a/contrib/gdb/gdb/lynx-nat.c b/contrib/gdb/gdb/lynx-nat.c
new file mode 100644
index 0000000..78716e0
--- /dev/null
+++ b/contrib/gdb/gdb/lynx-nat.c
@@ -0,0 +1,838 @@
+/* Native-dependent code for LynxOS.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "gdbcore.h"
+
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <sys/fpp.h>
+
+static unsigned long registers_addr PARAMS ((int pid));
+
+#define X(ENTRY)(offsetof(struct econtext, ENTRY))
+
+#ifdef I386
+/* Mappings from tm-i386v.h */
+
+static int regmap[] =
+{
+ X(eax),
+ X(ecx),
+ X(edx),
+ X(ebx),
+ X(esp), /* sp */
+ X(ebp), /* fp */
+ X(esi),
+ X(edi),
+ X(eip), /* pc */
+ X(flags), /* ps */
+ X(cs),
+ X(ss),
+ X(ds),
+ X(es),
+ X(ecode), /* Lynx doesn't give us either fs or gs, so */
+ X(fault), /* we just substitute these two in the hopes
+ that they are useful. */
+};
+#endif /* I386 */
+
+#ifdef M68K
+/* Mappings from tm-m68k.h */
+
+static int regmap[] =
+{
+ X(regs[0]), /* d0 */
+ X(regs[1]), /* d1 */
+ X(regs[2]), /* d2 */
+ X(regs[3]), /* d3 */
+ X(regs[4]), /* d4 */
+ X(regs[5]), /* d5 */
+ X(regs[6]), /* d6 */
+ X(regs[7]), /* d7 */
+ X(regs[8]), /* a0 */
+ X(regs[9]), /* a1 */
+ X(regs[10]), /* a2 */
+ X(regs[11]), /* a3 */
+ X(regs[12]), /* a4 */
+ X(regs[13]), /* a5 */
+ X(regs[14]), /* fp */
+ offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */
+ X(status), /* ps */
+ X(pc),
+
+ X(fregs[0*3]), /* fp0 */
+ X(fregs[1*3]), /* fp1 */
+ X(fregs[2*3]), /* fp2 */
+ X(fregs[3*3]), /* fp3 */
+ X(fregs[4*3]), /* fp4 */
+ X(fregs[5*3]), /* fp5 */
+ X(fregs[6*3]), /* fp6 */
+ X(fregs[7*3]), /* fp7 */
+
+ X(fcregs[0]), /* fpcontrol */
+ X(fcregs[1]), /* fpstatus */
+ X(fcregs[2]), /* fpiaddr */
+ X(ssw), /* fpcode */
+ X(fault), /* fpflags */
+};
+#endif /* M68K */
+
+#ifdef SPARC
+/* Mappings from tm-sparc.h */
+
+#define FX(ENTRY)(offsetof(struct fcontext, ENTRY))
+
+static int regmap[] =
+{
+ -1, /* g0 */
+ X(g1),
+ X(g2),
+ X(g3),
+ X(g4),
+ -1, /* g5->g7 aren't saved by Lynx */
+ -1,
+ -1,
+
+ X(o[0]),
+ X(o[1]),
+ X(o[2]),
+ X(o[3]),
+ X(o[4]),
+ X(o[5]),
+ X(o[6]), /* sp */
+ X(o[7]), /* ra */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* l0 -> l7 */
+
+ -1,-1,-1,-1,-1,-1,-1,-1, /* i0 -> i7 */
+
+ FX(f.fregs[0]), /* f0 */
+ FX(f.fregs[1]),
+ FX(f.fregs[2]),
+ FX(f.fregs[3]),
+ FX(f.fregs[4]),
+ FX(f.fregs[5]),
+ FX(f.fregs[6]),
+ FX(f.fregs[7]),
+ FX(f.fregs[8]),
+ FX(f.fregs[9]),
+ FX(f.fregs[10]),
+ FX(f.fregs[11]),
+ FX(f.fregs[12]),
+ FX(f.fregs[13]),
+ FX(f.fregs[14]),
+ FX(f.fregs[15]),
+ FX(f.fregs[16]),
+ FX(f.fregs[17]),
+ FX(f.fregs[18]),
+ FX(f.fregs[19]),
+ FX(f.fregs[20]),
+ FX(f.fregs[21]),
+ FX(f.fregs[22]),
+ FX(f.fregs[23]),
+ FX(f.fregs[24]),
+ FX(f.fregs[25]),
+ FX(f.fregs[26]),
+ FX(f.fregs[27]),
+ FX(f.fregs[28]),
+ FX(f.fregs[29]),
+ FX(f.fregs[30]),
+ FX(f.fregs[31]),
+
+ X(y),
+ X(psr),
+ X(wim),
+ X(tbr),
+ X(pc),
+ X(npc),
+ FX(fsr), /* fpsr */
+ -1, /* cpsr */
+};
+#endif /* SPARC */
+
+#ifdef rs6000
+
+static int regmap[] =
+{
+ X(iregs[0]), /* r0 */
+ X(iregs[1]),
+ X(iregs[2]),
+ X(iregs[3]),
+ X(iregs[4]),
+ X(iregs[5]),
+ X(iregs[6]),
+ X(iregs[7]),
+ X(iregs[8]),
+ X(iregs[9]),
+ X(iregs[10]),
+ X(iregs[11]),
+ X(iregs[12]),
+ X(iregs[13]),
+ X(iregs[14]),
+ X(iregs[15]),
+ X(iregs[16]),
+ X(iregs[17]),
+ X(iregs[18]),
+ X(iregs[19]),
+ X(iregs[20]),
+ X(iregs[21]),
+ X(iregs[22]),
+ X(iregs[23]),
+ X(iregs[24]),
+ X(iregs[25]),
+ X(iregs[26]),
+ X(iregs[27]),
+ X(iregs[28]),
+ X(iregs[29]),
+ X(iregs[30]),
+ X(iregs[31]),
+
+ X(fregs[0]), /* f0 */
+ X(fregs[1]),
+ X(fregs[2]),
+ X(fregs[3]),
+ X(fregs[4]),
+ X(fregs[5]),
+ X(fregs[6]),
+ X(fregs[7]),
+ X(fregs[8]),
+ X(fregs[9]),
+ X(fregs[10]),
+ X(fregs[11]),
+ X(fregs[12]),
+ X(fregs[13]),
+ X(fregs[14]),
+ X(fregs[15]),
+ X(fregs[16]),
+ X(fregs[17]),
+ X(fregs[18]),
+ X(fregs[19]),
+ X(fregs[20]),
+ X(fregs[21]),
+ X(fregs[22]),
+ X(fregs[23]),
+ X(fregs[24]),
+ X(fregs[25]),
+ X(fregs[26]),
+ X(fregs[27]),
+ X(fregs[28]),
+ X(fregs[29]),
+ X(fregs[30]),
+ X(fregs[31]),
+
+ X(srr0), /* IAR (PC) */
+ X(srr1), /* MSR (PS) */
+ X(cr), /* CR */
+ X(lr), /* LR */
+ X(ctr), /* CTR */
+ X(xer), /* XER */
+ X(mq) /* MQ */
+};
+
+#endif /* rs6000 */
+
+#ifdef SPARC
+
+/* This routine handles some oddball cases for Sparc registers and LynxOS.
+ In partucular, it causes refs to G0, g5->7, and all fp regs to return zero.
+ It also handles knows where to find the I & L regs on the stack. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int whatregs = 0;
+
+#define WHATREGS_FLOAT 1
+#define WHATREGS_GEN 2
+#define WHATREGS_STACK 4
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_GETREGS)");
+
+ memset (buf, 0, REGISTER_RAW_SIZE (G0_REGNUM));
+ supply_register (G0_REGNUM, buf);
+ supply_register (TBR_REGNUM, (char *)&ec.tbr);
+
+ memcpy (&registers[REGISTER_BYTE (G1_REGNUM)], &ec.g1,
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+ for (i = G1_REGNUM; i <= G1_REGNUM + 3; i++)
+ register_valid[i] = 1;
+
+ supply_register (PS_REGNUM, (char *)&ec.psr);
+ supply_register (Y_REGNUM, (char *)&ec.y);
+ supply_register (PC_REGNUM, (char *)&ec.pc);
+ supply_register (NPC_REGNUM, (char *)&ec.npc);
+ supply_register (WIM_REGNUM, (char *)&ec.wim);
+
+ memcpy (&registers[REGISTER_BYTE (O0_REGNUM)], ec.o,
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+ for (i = O0_REGNUM; i <= O0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ CORE_ADDR sp;
+ int i;
+
+ sp = read_register (SP_REGNUM);
+
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE(I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 0);
+ for (i = I0_REGNUM; i <= I7_REGNUM; i++)
+ register_valid[i] = 1;
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE(L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 0);
+ for (i = L0_REGNUM; i <= L0_REGNUM + 7; i++)
+ register_valid[i] = 1;
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+ int i;
+
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_GETFPREGS)");
+
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], fc.f.fregs,
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+ for (i = FP0_REGNUM; i <= FP0_REGNUM + 31; i++)
+ register_valid[i] = 1;
+
+ supply_register (FPS_REGNUM, (char *)&fc.fsr);
+ }
+}
+
+/* This routine handles storing of the I & L regs for the Sparc. The trick
+ here is that they actually live on the stack. The really tricky part is
+ that when changing the stack pointer, the I & L regs must be written to
+ where the new SP points, otherwise the regs will be incorrect when the
+ process is started up again. We assume that the I & L regs are valid at
+ this point. */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ int whatregs = 0;
+
+ if (regno == -1)
+ whatregs = WHATREGS_FLOAT | WHATREGS_GEN | WHATREGS_STACK;
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ whatregs = WHATREGS_STACK;
+ else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ whatregs = WHATREGS_FLOAT;
+ else if (regno == SP_REGNUM)
+ whatregs = WHATREGS_STACK | WHATREGS_GEN;
+ else
+ whatregs = WHATREGS_GEN;
+
+ if (whatregs & WHATREGS_GEN)
+ {
+ struct econtext ec; /* general regs */
+ int retval;
+
+ ec.tbr = read_register (TBR_REGNUM);
+ memcpy (&ec.g1, &registers[REGISTER_BYTE (G1_REGNUM)],
+ 4 * REGISTER_RAW_SIZE (G1_REGNUM));
+
+ ec.psr = read_register (PS_REGNUM);
+ ec.y = read_register (Y_REGNUM);
+ ec.pc = read_register (PC_REGNUM);
+ ec.npc = read_register (NPC_REGNUM);
+ ec.wim = read_register (WIM_REGNUM);
+
+ memcpy (ec.o, &registers[REGISTER_BYTE (O0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (O0_REGNUM));
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETREGS, inferior_pid, (PTRACE_ARG3_TYPE) &ec,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_SETREGS)");
+ }
+
+ if (whatregs & WHATREGS_STACK)
+ {
+ int regoffset;
+ CORE_ADDR sp;
+
+ sp = read_register (SP_REGNUM);
+
+ if (regno == -1 || regno == SP_REGNUM)
+ {
+ if (!register_valid[L0_REGNUM+5])
+ abort();
+ target_xfer_memory (sp + FRAME_SAVED_I0,
+ &registers[REGISTER_BYTE (I0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (I0_REGNUM), 1);
+
+ target_xfer_memory (sp + FRAME_SAVED_L0,
+ &registers[REGISTER_BYTE (L0_REGNUM)],
+ 8 * REGISTER_RAW_SIZE (L0_REGNUM), 1);
+ }
+ else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+ {
+ if (!register_valid[regno])
+ abort();
+ if (regno >= L0_REGNUM && regno <= L0_REGNUM + 7)
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM)
+ + FRAME_SAVED_L0;
+ else
+ regoffset = REGISTER_BYTE (regno) - REGISTER_BYTE (I0_REGNUM)
+ + FRAME_SAVED_I0;
+ target_xfer_memory (sp + regoffset, &registers[REGISTER_BYTE (regno)],
+ REGISTER_RAW_SIZE (regno), 1);
+ }
+ }
+
+ if (whatregs & WHATREGS_FLOAT)
+ {
+ struct fcontext fc; /* fp regs */
+ int retval;
+
+/* We read fcontext first so that we can get good values for fq_t... */
+ errno = 0;
+ retval = ptrace (PTRACE_GETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_GETFPREGS)");
+
+ memcpy (fc.f.fregs, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ 32 * REGISTER_RAW_SIZE (FP0_REGNUM));
+
+ fc.fsr = read_register (FPS_REGNUM);
+
+ errno = 0;
+ retval = ptrace (PTRACE_SETFPREGS, inferior_pid, (PTRACE_ARG3_TYPE) &fc,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_SETFPREGS)");
+ }
+}
+#endif /* SPARC */
+
+#if defined (I386) || defined (M68K) || defined (rs6000)
+
+/* Return the offset relative to the start of the per-thread data to the
+ saved context block. */
+
+static unsigned long
+registers_addr(pid)
+ int pid;
+{
+ CORE_ADDR stblock;
+ int ecpoff = offsetof(st_t, ecp);
+ CORE_ADDR ecp;
+
+ errno = 0;
+ stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE)0,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_THREADUSER)");
+
+ ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE)ecpoff,
+ 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_PEEKTHREAD)");
+
+ return ecp - stblock;
+}
+
+/* Fetch one or more registers from the inferior. REGNO == -1 to get
+ them all. We actually fetch more than requested, when convenient,
+ marking them as valid so we won't fetch them again. */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int reglo, reghi;
+ int i;
+ unsigned long ecp;
+
+ if (regno == -1)
+ {
+ reglo = 0;
+ reghi = NUM_REGS - 1;
+ }
+ else
+ reglo = reghi = regno;
+
+ ecp = registers_addr (inferior_pid);
+
+ for (regno = reglo; regno <= reghi; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ int ptrace_fun = PTRACE_PEEKTHREAD;
+
+#ifdef M68K
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD;
+#endif
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ unsigned int reg;
+
+ errno = 0;
+ reg = ptrace (ptrace_fun, inferior_pid,
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_PEEKUSP)");
+
+ *(int *)&buf[i] = reg;
+ }
+ supply_register (regno, buf);
+ }
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+/* Registers we shouldn't try to store. */
+#if !defined (CANNOT_STORE_REGISTER)
+#define CANNOT_STORE_REGISTER(regno) 0
+#endif
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ int reglo, reghi;
+ int i;
+ unsigned long ecp;
+
+ if (regno == -1)
+ {
+ reglo = 0;
+ reghi = NUM_REGS - 1;
+ }
+ else
+ reglo = reghi = regno;
+
+ ecp = registers_addr (inferior_pid);
+
+ for (regno = reglo; regno <= reghi; regno++)
+ {
+ int ptrace_fun = PTRACE_POKEUSER;
+
+ if (CANNOT_STORE_REGISTER (regno))
+ continue;
+
+#ifdef M68K
+ ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER;
+#endif
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ unsigned int reg;
+
+ reg = *(unsigned int *)&registers[REGISTER_BYTE (regno) + i];
+
+ errno = 0;
+ ptrace (ptrace_fun, inferior_pid,
+ (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg);
+ if (errno)
+ perror_with_name ("ptrace(PTRACE_POKEUSP)");
+ }
+ }
+}
+#endif /* defined (I386) || defined (M68K) || defined (rs6000) */
+
+/* Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status through argument pointer OURSTATUS. */
+
+int
+child_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int save_errno;
+ int thread;
+ union wait status;
+
+ while (1)
+ {
+ int sig;
+
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ pid = wait (&status);
+
+ save_errno = errno;
+
+ clear_sigint_trap();
+
+ if (pid == -1)
+ {
+ if (save_errno == EINTR)
+ continue;
+ fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+ /* Claim it exited with unknown signal. */
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ return -1;
+ }
+
+ if (pid != PIDGET (inferior_pid)) /* Some other process?!? */
+ continue;
+
+ thread = status.w_tid; /* Get thread id from status */
+
+ /* Initial thread value can only be acquired via wait, so we have to
+ resort to this hack. */
+
+ if (TIDGET (inferior_pid) == 0 && thread != 0)
+ {
+ inferior_pid = BUILDPID (inferior_pid, thread);
+ add_thread (inferior_pid);
+ }
+
+ pid = BUILDPID (pid, thread);
+
+ /* We've become a single threaded process again. */
+ if (thread == 0)
+ inferior_pid = pid;
+
+ /* Check for thread creation. */
+ if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == SIGTRAP
+ && !in_thread_list (pid))
+ {
+ int realsig;
+
+ realsig = ptrace (PTRACE_GETTRACESIG, pid, (PTRACE_ARG3_TYPE)0, 0);
+
+ if (realsig == SIGNEWTHREAD)
+ {
+ /* It's a new thread notification. Nothing to do here since
+ the machine independent code in wait_for_inferior will
+ add the thread to the thread list and restart the thread
+ when pid != inferior_pid and pid is not in the thread
+ list. We don't even want to much with realsig -- the
+ code in wait_for_inferior expects SIGTRAP. */
+ ;
+ }
+ else
+ error ("Signal for unknown thread was not SIGNEWTHREAD");
+ }
+
+ /* Check for thread termination. */
+ else if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == SIGTRAP
+ && in_thread_list (pid))
+ {
+ int realsig;
+
+ realsig = ptrace (PTRACE_GETTRACESIG, pid, (PTRACE_ARG3_TYPE)0, 0);
+
+ if (realsig == SIGTHREADEXIT)
+ {
+ ptrace (PTRACE_CONT, PIDGET (pid), (PTRACE_ARG3_TYPE)0, 0);
+ continue;
+ }
+ }
+
+#ifdef SPARC
+ /* SPARC Lynx uses an byte reversed wait status; we must use the
+ host macros to access it. These lines just a copy of
+ store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS
+ because target.c can't include the Lynx <sys/wait.h>. */
+ if (WIFEXITED (status))
+ {
+ ourstatus->kind = TARGET_WAITKIND_EXITED;
+ ourstatus->value.integer = WEXITSTATUS (status);
+ }
+ else if (!WIFSTOPPED (status))
+ {
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig =
+ target_signal_from_host (WTERMSIG (status));
+ }
+ else
+ {
+ ourstatus->kind = TARGET_WAITKIND_STOPPED;
+ ourstatus->value.sig =
+ target_signal_from_host (WSTOPSIG (status));
+ }
+#else
+ store_waitstatus (ourstatus, status.w_status);
+#endif
+
+ return pid;
+ }
+}
+
+/* Return nonzero if the given thread is still alive. */
+int
+child_thread_alive (pid)
+ int pid;
+{
+ /* Arggh. Apparently pthread_kill only works for threads within
+ the process that calls pthread_kill.
+
+ We want to avoid the lynx signal extensions as they simply don't
+ map well to the generic gdb interface we want to keep.
+
+ All we want to do is determine if a particular thread is alive;
+ it appears as if we can just make a harmless thread specific
+ ptrace call to do that. */
+ return (ptrace (PTRACE_THREADUSER, pid, 0, 0) != -1);
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+child_resume (pid, step, signal)
+ int pid;
+ int step;
+ enum target_signal signal;
+{
+ int func;
+
+ errno = 0;
+
+ /* If pid == -1, then we want to step/continue all threads, else
+ we only want to step/continue a single thread. */
+ if (pid == -1)
+ {
+ pid = inferior_pid;
+ func = step ? PTRACE_SINGLESTEP : PTRACE_CONT;
+ }
+ else
+ func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE;
+
+
+ /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
+ it was. (If GDB wanted it to start some other way, we have already
+ written a new PC value to the child.)
+
+ If this system does not support PT_STEP, a higher level function will
+ have called single_step() to transmute the step request into a
+ continue request (by setting breakpoints on all possible successor
+ instructions), so we don't have to worry about that here. */
+
+ ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal));
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+/* Convert a Lynx process ID to a string. Returns the string in a static
+ buffer. */
+
+char *
+lynx_pid_to_str (pid)
+ int pid;
+{
+ static char buf[40];
+
+ sprintf (buf, "process %d thread %d", PIDGET (pid), TIDGET (pid));
+
+ return buf;
+}
+
+/* Extract the register values out of the core file and store
+ them where `read_register' will find them.
+
+ CORE_REG_SECT points to the register values themselves, read into memory.
+ CORE_REG_SIZE is the size of that area.
+ WHICH says which set of registers we are handling (0 = int, 2 = float
+ on machines where they are discontiguous).
+ REG_ADDR is the offset from u.u_ar0 to the register values relative to
+ core_reg_sect. This is used with old-fashioned core files to
+ locate the registers in a large upage-plus-stack ".reg" section.
+ Original upage address X is at location core_reg_sect+x+reg_addr.
+ */
+
+static void
+fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned reg_addr;
+{
+ struct st_entry s;
+ unsigned int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ if (regmap[regno] != -1)
+ supply_register (regno, core_reg_sect + offsetof (st_t, ec)
+ + regmap[regno]);
+
+#ifdef SPARC
+/* Fetching this register causes all of the I & L regs to be read from the
+ stack and validated. */
+
+ fetch_inferior_registers (I0_REGNUM);
+#endif
+}
+
+
+/* Register that we are able to handle lynx core file formats.
+ FIXME: is this really bfd_target_unknown_flavour? */
+
+static struct core_fns lynx_core_fns =
+{
+ bfd_target_unknown_flavour,
+ fetch_core_registers,
+ NULL
+};
+
+void
+_initialize_core_lynx ()
+{
+ add_core_fns (&lynx_core_fns);
+}
diff --git a/contrib/gdb/gdb/m2-exp.tab.c b/contrib/gdb/gdb/m2-exp.tab.c
new file mode 100644
index 0000000..0ad36c3
--- /dev/null
+++ b/contrib/gdb/gdb/m2-exp.tab.c
@@ -0,0 +1,2095 @@
+
+/* A Bison parser, made from ./m2-exp.y with Bison version GNU Bison version 1.24
+ */
+
+#define YYBISON 1 /* Identify Bison output. */
+
+#define INT 258
+#define HEX 259
+#define ERROR 260
+#define UINT 261
+#define M2_TRUE 262
+#define M2_FALSE 263
+#define CHAR 264
+#define FLOAT 265
+#define STRING 266
+#define NAME 267
+#define BLOCKNAME 268
+#define IDENT 269
+#define VARNAME 270
+#define TYPENAME 271
+#define SIZE 272
+#define CAP 273
+#define ORD 274
+#define HIGH 275
+#define ABS 276
+#define MIN_FUNC 277
+#define MAX_FUNC 278
+#define FLOAT_FUNC 279
+#define VAL 280
+#define CHR 281
+#define ODD 282
+#define TRUNC 283
+#define INC 284
+#define DEC 285
+#define INCL 286
+#define EXCL 287
+#define COLONCOLON 288
+#define INTERNAL_VAR 289
+#define ABOVE_COMMA 290
+#define ASSIGN 291
+#define LEQ 292
+#define GEQ 293
+#define NOTEQUAL 294
+#define IN 295
+#define OROR 296
+#define LOGICAL_AND 297
+#define DIV 298
+#define MOD 299
+#define UNARY 300
+#define DOT 301
+#define NOT 302
+#define QID 303
+
+#line 40 "./m2-exp.y"
+
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "expression.h"
+#include "language.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "m2-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth m2_maxdepth
+#define yyparse m2_parse
+#define yylex m2_lex
+#define yyerror m2_error
+#define yylval m2_lval
+#define yychar m2_char
+#define yydebug m2_debug
+#define yypact m2_pact
+#define yyr1 m2_r1
+#define yyr2 m2_r2
+#define yydef m2_def
+#define yychk m2_chk
+#define yypgo m2_pgo
+#define yyact m2_act
+#define yyexca m2_exca
+#define yyerrflag m2_errflag
+#define yynerrs m2_nerrs
+#define yyps m2_ps
+#define yypv m2_pv
+#define yys m2_s
+#define yy_yys m2_yys
+#define yystate m2_state
+#define yytmp m2_tmp
+#define yyv m2_v
+#define yy_yyv m2_yyv
+#define yyval m2_val
+#define yylloc m2_lloc
+#define yyreds m2_reds /* With YYDEBUG defined */
+#define yytoks m2_toks /* With YYDEBUG defined */
+#define yylhs m2_yylhs
+#define yylen m2_yylen
+#define yydefred m2_yydefred
+#define yydgoto m2_yydgoto
+#define yysindex m2_yysindex
+#define yyrindex m2_yyrindex
+#define yygindex m2_yygindex
+#define yytable m2_yytable
+#define yycheck m2_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+#if 0
+static char *
+make_qualname PARAMS ((char *, char *));
+#endif
+
+static int
+parse_number PARAMS ((int));
+
+/* The sign of the number being parsed. */
+static int number_sign = 1;
+
+/* The block that the module specified by the qualifer on an identifer is
+ contained in, */
+#if 0
+static struct block *modblock=0;
+#endif
+
+
+#line 135 "./m2-exp.y"
+typedef union
+ {
+ LONGEST lval;
+ unsigned LONGEST ulval;
+ DOUBLEST dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ } YYSTYPE;
+
+#ifndef YYLTYPE
+typedef
+ struct yyltype
+ {
+ int timestamp;
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ char *text;
+ }
+ yyltype;
+
+#define YYLTYPE yyltype
+#endif
+
+#include <stdio.h>
+
+#ifndef __cplusplus
+#ifndef __STDC__
+#define const
+#endif
+#endif
+
+
+
+#define YYFINAL 181
+#define YYFLAG -32768
+#define YYNTBASE 68
+
+#define YYTRANSLATE(x) ((unsigned)(x) <= 303 ? yytranslate[x] : 82)
+
+static const char yytranslate[] = { 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 44, 2, 2, 48, 2, 60,
+ 64, 52, 50, 35, 51, 2, 53, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 38,
+ 42, 39, 2, 49, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 59, 2, 67, 57, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 65, 2, 66, 62, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 36,
+ 37, 40, 41, 43, 45, 46, 47, 54, 55, 56,
+ 58, 61, 63
+};
+
+#if YYDEBUG != 0
+static const short yyprhs[] = { 0,
+ 0, 2, 4, 6, 9, 10, 14, 17, 20, 22,
+ 24, 29, 34, 39, 44, 49, 54, 59, 66, 71,
+ 76, 81, 84, 89, 96, 101, 108, 112, 114, 118,
+ 125, 132, 136, 141, 142, 148, 149, 155, 156, 158,
+ 162, 164, 168, 173, 178, 182, 186, 190, 194, 198,
+ 202, 206, 210, 214, 218, 222, 226, 230, 234, 238,
+ 242, 246, 250, 252, 254, 256, 258, 260, 262, 264,
+ 269, 271, 273, 275, 279, 281, 283, 287, 289
+};
+
+static const short yyrhs[] = { 70,
+ 0, 69, 0, 81, 0, 70, 57, 0, 0, 51,
+ 71, 70, 0, 50, 70, 0, 72, 70, 0, 61,
+ 0, 62, 0, 18, 60, 70, 64, 0, 19, 60,
+ 70, 64, 0, 21, 60, 70, 64, 0, 20, 60,
+ 70, 64, 0, 22, 60, 81, 64, 0, 23, 60,
+ 81, 64, 0, 24, 60, 70, 64, 0, 25, 60,
+ 81, 35, 70, 64, 0, 26, 60, 70, 64, 0,
+ 27, 60, 70, 64, 0, 28, 60, 70, 64, 0,
+ 17, 70, 0, 29, 60, 70, 64, 0, 29, 60,
+ 70, 35, 70, 64, 0, 30, 60, 70, 64, 0,
+ 30, 60, 70, 35, 70, 64, 0, 70, 58, 12,
+ 0, 73, 0, 70, 45, 73, 0, 31, 60, 70,
+ 35, 70, 64, 0, 32, 60, 70, 35, 70, 64,
+ 0, 65, 76, 66, 0, 81, 65, 76, 66, 0,
+ 0, 70, 59, 74, 77, 67, 0, 0, 70, 60,
+ 75, 76, 64, 0, 0, 70, 0, 76, 35, 70,
+ 0, 70, 0, 77, 35, 70, 0, 65, 81, 66,
+ 70, 0, 81, 60, 70, 64, 0, 60, 70, 64,
+ 0, 70, 49, 70, 0, 70, 52, 70, 0, 70,
+ 53, 70, 0, 70, 54, 70, 0, 70, 55, 70,
+ 0, 70, 50, 70, 0, 70, 51, 70, 0, 70,
+ 42, 70, 0, 70, 43, 70, 0, 70, 44, 70,
+ 0, 70, 40, 70, 0, 70, 41, 70, 0, 70,
+ 38, 70, 0, 70, 39, 70, 0, 70, 47, 70,
+ 0, 70, 46, 70, 0, 70, 37, 70, 0, 7,
+ 0, 8, 0, 3, 0, 6, 0, 9, 0, 10,
+ 0, 80, 0, 17, 60, 81, 64, 0, 11, 0,
+ 79, 0, 13, 0, 78, 33, 13, 0, 79, 0,
+ 34, 0, 78, 33, 12, 0, 12, 0, 16, 0
+};
+
+#endif
+
+#if YYDEBUG != 0
+static const short yyrline[] = { 0,
+ 204, 205, 208, 217, 220, 222, 227, 231, 235, 236,
+ 239, 243, 247, 251, 255, 261, 267, 271, 277, 281,
+ 285, 289, 294, 298, 304, 308, 314, 320, 323, 327,
+ 331, 334, 336, 342, 347, 353, 357, 363, 366, 370,
+ 375, 380, 385, 391, 397, 405, 409, 413, 417, 421,
+ 425, 429, 433, 437, 439, 443, 447, 451, 455, 459,
+ 463, 467, 474, 480, 486, 493, 502, 510, 517, 520,
+ 527, 534, 538, 547, 559, 567, 571, 587, 638
+};
+
+static const char * const yytname[] = { "$","error","$undefined.","INT","HEX",
+"ERROR","UINT","M2_TRUE","M2_FALSE","CHAR","FLOAT","STRING","NAME","BLOCKNAME",
+"IDENT","VARNAME","TYPENAME","SIZE","CAP","ORD","HIGH","ABS","MIN_FUNC","MAX_FUNC",
+"FLOAT_FUNC","VAL","CHR","ODD","TRUNC","INC","DEC","INCL","EXCL","COLONCOLON",
+"INTERNAL_VAR","','","ABOVE_COMMA","ASSIGN","'<'","'>'","LEQ","GEQ","'='","NOTEQUAL",
+"'#'","IN","OROR","LOGICAL_AND","'&'","'@'","'+'","'-'","'*'","'/'","DIV","MOD",
+"UNARY","'^'","DOT","'['","'('","NOT","'~'","QID","')'","'{'","'}'","']'","start",
+"type_exp","exp","@1","not_exp","set","@2","@3","arglist","non_empty_arglist",
+"block","fblock","variable","type",""
+};
+#endif
+
+static const short yyr1[] = { 0,
+ 68, 68, 69, 70, 71, 70, 70, 70, 72, 72,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 73, 73, 74, 70, 75, 70, 76, 76, 76,
+ 77, 77, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 78, 79, 79, 80, 80, 80, 80, 81
+};
+
+static const short yyr2[] = { 0,
+ 1, 1, 1, 2, 0, 3, 2, 2, 1, 1,
+ 4, 4, 4, 4, 4, 4, 4, 6, 4, 4,
+ 4, 2, 4, 6, 4, 6, 3, 1, 3, 6,
+ 6, 3, 4, 0, 5, 0, 5, 0, 1, 3,
+ 1, 3, 4, 4, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 1, 1, 1, 1, 1, 1, 1, 4,
+ 1, 1, 1, 3, 1, 1, 3, 1, 1
+};
+
+static const short yydefact[] = { 0,
+ 65, 66, 63, 64, 67, 68, 71, 78, 73, 79,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 76, 0, 5, 0,
+ 9, 10, 38, 2, 1, 0, 28, 0, 75, 69,
+ 3, 0, 22, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
+ 0, 0, 39, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 34, 36, 8, 0, 0,
+ 38, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 6, 45, 0,
+ 32, 0, 62, 58, 59, 56, 57, 53, 54, 55,
+ 38, 29, 0, 61, 60, 46, 51, 52, 47, 48,
+ 49, 50, 27, 0, 38, 77, 74, 0, 0, 70,
+ 11, 12, 14, 13, 15, 16, 17, 0, 19, 20,
+ 21, 0, 23, 0, 25, 0, 0, 40, 43, 41,
+ 0, 0, 44, 33, 0, 0, 0, 0, 0, 0,
+ 35, 37, 18, 24, 26, 30, 31, 42, 0, 0,
+ 0
+};
+
+static const short yydefgoto[] = { 179,
+ 34, 63, 61, 36, 37, 134, 135, 64, 161, 38,
+ 39, 40, 44
+};
+
+static const short yypact[] = { 155,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
+ 215, -27, -22, -20, -19, 14, 24, 26, 27, 28,
+ 29, 31, 32, 33, 35, 36,-32768, 155,-32768, 155,
+-32768,-32768, 155,-32768, 742, 155,-32768, -6, -4,-32768,
+ -34, 155, 5, -34, 155, 155, 155, 155, 44, 44,
+ 155, 44, 155, 155, 155, 155, 155, 155, 155, 5,
+ 155, 272, 742, -31, -41, 155, 155, 155, 155, 155,
+ 155, 155, 155, -15, 155, 155, 155, 155, 155, 155,
+ 155, 155, 155,-32768, 85,-32768,-32768, 5, -5, 155,
+ 155, -21, 300, 328, 356, 384, 34, 39, 412, 64,
+ 440, 468, 496, 78, 244, 692, 718, 5,-32768, 155,
+-32768, 155, 766, -37, -37, -37, -37, -37, -37, -37,
+ 155,-32768, 40, 141, 201, 777, 786, 786, 5, 5,
+ 5, 5,-32768, 155, 155,-32768,-32768, 524, -29,-32768,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768, 155,-32768,-32768,
+-32768, 155,-32768, 155,-32768, 155, 155, 742, 5, 742,
+ -33, -32,-32768,-32768, 552, 580, 608, 636, 664, 155,
+-32768,-32768,-32768,-32768,-32768,-32768,-32768, 742, 100, 106,
+-32768
+};
+
+static const short yypgoto[] = {-32768,
+-32768, 0,-32768,-32768, 37,-32768,-32768, -86,-32768,-32768,
+-32768,-32768, 52
+};
+
+
+#define YYLAST 846
+
+
+static const short yytable[] = { 35,
+ 10, 170, 110, 110, 139, 110, 136, 137, 75, 76,
+ 43, 77, 78, 79, 80, 81, 82, 83, 90, 84,
+ 85, 86, 87, 91, 112, 90, 89, 60, -72, 62,
+ 91, 172, 45, 171, 111, 88, 164, 46, 90, 47,
+ 48, 62, 140, 91, 93, 94, 95, 96, 162, 121,
+ 99, 41, 101, 102, 103, 104, 105, 106, 107, 10,
+ 108, 84, 85, 86, 87, 113, 114, 115, 116, 117,
+ 118, 119, 120, 49, 124, 125, 126, 127, 128, 129,
+ 130, 131, 132, 50, 65, 51, 52, 53, 54, 138,
+ 55, 56, 57, 92, 58, 59, 133, 145, 148, 180,
+ 97, 98, 146, 100, 91, 181, 0, 0, 0, 158,
+ 122, 159, 152, 0, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 123, 77, 78, 79, 80,
+ 81, 82, 83, 160, 84, 85, 86, 87, 0, 0,
+ 0, 153, 0, 0, 0, 0, 0, 165, 0, 0,
+ 0, 166, 0, 167, 0, 168, 169, 1, 0, 0,
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 178,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 76, 27, 77,
+ 78, 79, 80, 81, 82, 83, 0, 84, 85, 86,
+ 87, 0, 0, 0, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 30, 31, 32, 1, 0, 33,
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 0,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 0, 27, 77,
+ 78, 79, 80, 81, 82, 83, 0, 84, 85, 86,
+ 87, 0, 0, 0, 28, 29, 0, 0, 0, 0,
+ 0, 0, 0, 0, 42, 31, 32, 0, 154, 33,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 0, 77, 78, 79, 80, 81, 82, 83, 0,
+ 84, 85, 86, 87, 0, 0, 0, 155, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 0,
+ 77, 78, 79, 80, 81, 82, 83, 0, 84, 85,
+ 86, 87, 0, 0, 0, 109, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 0, 77, 78,
+ 79, 80, 81, 82, 83, 0, 84, 85, 86, 87,
+ 0, 0, 0, 141, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 0, 77, 78, 79, 80,
+ 81, 82, 83, 0, 84, 85, 86, 87, 0, 0,
+ 0, 142, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 0, 77, 78, 79, 80, 81, 82,
+ 83, 0, 84, 85, 86, 87, 0, 0, 0, 143,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 0, 77, 78, 79, 80, 81, 82, 83, 0,
+ 84, 85, 86, 87, 0, 0, 0, 144, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 0,
+ 77, 78, 79, 80, 81, 82, 83, 0, 84, 85,
+ 86, 87, 0, 0, 0, 147, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 0, 77, 78,
+ 79, 80, 81, 82, 83, 0, 84, 85, 86, 87,
+ 0, 0, 0, 149, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 0, 77, 78, 79, 80,
+ 81, 82, 83, 0, 84, 85, 86, 87, 0, 0,
+ 0, 150, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 0, 77, 78, 79, 80, 81, 82,
+ 83, 0, 84, 85, 86, 87, 0, 0, 0, 151,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 0, 77, 78, 79, 80, 81, 82, 83, 0,
+ 84, 85, 86, 87, 0, 0, 0, 163, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 0,
+ 77, 78, 79, 80, 81, 82, 83, 0, 84, 85,
+ 86, 87, 0, 0, 0, 173, 66, 67, 68, 69,
+ 70, 71, 72, 73, 74, 75, 76, 0, 77, 78,
+ 79, 80, 81, 82, 83, 0, 84, 85, 86, 87,
+ 0, 0, 0, 174, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 0, 77, 78, 79, 80,
+ 81, 82, 83, 0, 84, 85, 86, 87, 0, 0,
+ 0, 175, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 0, 77, 78, 79, 80, 81, 82,
+ 83, 0, 84, 85, 86, 87, 0, 0, 0, 176,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 76, 0, 77, 78, 79, 80, 81, 82, 83, 0,
+ 84, 85, 86, 87, 0, 0, 156, 177, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 0,
+ 77, 78, 79, 80, 81, 82, 83, 0, 84, 85,
+ 86, 87, 157, 0, 66, 67, 68, 69, 70, 71,
+ 72, 73, 74, 75, 76, 0, 77, 78, 79, 80,
+ 81, 82, 83, 0, 84, 85, 86, 87, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 0,
+ 77, 78, 79, 80, 81, 82, 83, 0, 84, 85,
+ 86, 87,-32768, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 0, 77, 78, 79, 80, 81, 82,
+ 83, 0, 84, 85, 86, 87, 78, 79, 80, 81,
+ 82, 83, 0, 84, 85, 86, 87, 80, 81, 82,
+ 83, 0, 84, 85, 86, 87
+};
+
+static const short yycheck[] = { 0,
+ 16, 35, 35, 35, 91, 35, 12, 13, 46, 47,
+ 11, 49, 50, 51, 52, 53, 54, 55, 60, 57,
+ 58, 59, 60, 65, 66, 60, 33, 28, 33, 30,
+ 65, 64, 60, 67, 66, 36, 66, 60, 60, 60,
+ 60, 42, 64, 65, 45, 46, 47, 48, 135, 65,
+ 51, 0, 53, 54, 55, 56, 57, 58, 59, 16,
+ 61, 57, 58, 59, 60, 66, 67, 68, 69, 70,
+ 71, 72, 73, 60, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 60, 33, 60, 60, 60, 60, 90,
+ 60, 60, 60, 42, 60, 60, 12, 64, 35, 0,
+ 49, 50, 64, 52, 65, 0, -1, -1, -1, 110,
+ 74, 112, 35, -1, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 74, 49, 50, 51, 52,
+ 53, 54, 55, 134, 57, 58, 59, 60, -1, -1,
+ -1, 64, -1, -1, -1, -1, -1, 148, -1, -1,
+ -1, 152, -1, 154, -1, 156, 157, 3, -1, -1,
+ 6, 7, 8, 9, 10, 11, 12, 13, -1, 170,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 47, 34, 49,
+ 50, 51, 52, 53, 54, 55, -1, 57, 58, 59,
+ 60, -1, -1, -1, 50, 51, -1, -1, -1, -1,
+ -1, -1, -1, -1, 60, 61, 62, 3, -1, 65,
+ 6, 7, 8, 9, 10, 11, 12, 13, -1, -1,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, -1, 34, 49,
+ 50, 51, 52, 53, 54, 55, -1, 57, 58, 59,
+ 60, -1, -1, -1, 50, 51, -1, -1, -1, -1,
+ -1, -1, -1, -1, 60, 61, 62, -1, 35, 65,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, -1, 49, 50, 51, 52, 53, 54, 55, -1,
+ 57, 58, 59, 60, -1, -1, -1, 64, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, 50, 51, 52, 53, 54, 55, -1, 57, 58,
+ 59, 60, -1, -1, -1, 64, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, -1, 49, 50,
+ 51, 52, 53, 54, 55, -1, 57, 58, 59, 60,
+ -1, -1, -1, 64, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, -1, 49, 50, 51, 52,
+ 53, 54, 55, -1, 57, 58, 59, 60, -1, -1,
+ -1, 64, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, -1, 49, 50, 51, 52, 53, 54,
+ 55, -1, 57, 58, 59, 60, -1, -1, -1, 64,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, -1, 49, 50, 51, 52, 53, 54, 55, -1,
+ 57, 58, 59, 60, -1, -1, -1, 64, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, 50, 51, 52, 53, 54, 55, -1, 57, 58,
+ 59, 60, -1, -1, -1, 64, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, -1, 49, 50,
+ 51, 52, 53, 54, 55, -1, 57, 58, 59, 60,
+ -1, -1, -1, 64, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, -1, 49, 50, 51, 52,
+ 53, 54, 55, -1, 57, 58, 59, 60, -1, -1,
+ -1, 64, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, -1, 49, 50, 51, 52, 53, 54,
+ 55, -1, 57, 58, 59, 60, -1, -1, -1, 64,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, -1, 49, 50, 51, 52, 53, 54, 55, -1,
+ 57, 58, 59, 60, -1, -1, -1, 64, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, 50, 51, 52, 53, 54, 55, -1, 57, 58,
+ 59, 60, -1, -1, -1, 64, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, -1, 49, 50,
+ 51, 52, 53, 54, 55, -1, 57, 58, 59, 60,
+ -1, -1, -1, 64, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, -1, 49, 50, 51, 52,
+ 53, 54, 55, -1, 57, 58, 59, 60, -1, -1,
+ -1, 64, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, -1, 49, 50, 51, 52, 53, 54,
+ 55, -1, 57, 58, 59, 60, -1, -1, -1, 64,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
+ 47, -1, 49, 50, 51, 52, 53, 54, 55, -1,
+ 57, 58, 59, 60, -1, -1, 35, 64, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, 50, 51, 52, 53, 54, 55, -1, 57, 58,
+ 59, 60, 35, -1, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, -1, 49, 50, 51, 52,
+ 53, 54, 55, -1, 57, 58, 59, 60, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, -1,
+ 49, 50, 51, 52, 53, 54, 55, -1, 57, 58,
+ 59, 60, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, -1, 49, 50, 51, 52, 53, 54,
+ 55, -1, 57, 58, 59, 60, 50, 51, 52, 53,
+ 54, 55, -1, 57, 58, 59, 60, 52, 53, 54,
+ 55, -1, 57, 58, 59, 60
+};
+/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
+#line 3 "/usr/unsupported/share/bison.simple"
+
+/* Skeleton output parser for bison,
+ Copyright (C) 1984, 1989, 1990 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
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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. */
+
+/* As a special exception, when this file is copied by Bison into a
+ Bison output file, you may use that output file without restriction.
+ This special exception was added by the Free Software Foundation
+ in version 1.24 of Bison. */
+
+#ifndef alloca
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not GNU C. */
+#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
+#include <alloca.h>
+#else /* not sparc */
+#if defined (MSDOS) && !defined (__TURBOC__)
+#else /* not MSDOS, or __TURBOC__ */
+#if defined(_AIX)
+ #pragma alloca
+#else /* not MSDOS, __TURBOC__, or _AIX */
+#ifdef __hpux
+#ifdef __cplusplus
+extern "C" {
+void *alloca (unsigned int);
+};
+#else /* not __cplusplus */
+void *alloca ();
+#endif /* not __cplusplus */
+#endif /* __hpux */
+#endif /* not _AIX */
+#endif /* not MSDOS, or __TURBOC__ */
+#endif /* not sparc. */
+#endif /* not GNU C. */
+#endif /* alloca not defined. */
+
+/* This is the parser code that is written into each bison parser
+ when the %semantic_parser declaration is not specified in the grammar.
+ It was written by Richard Stallman by simplifying the hairy parser
+ used when %semantic_parser is specified. */
+
+/* Note: there must be only one dollar sign in this file.
+ It is replaced by the list of actions, each action
+ as one case of the switch. */
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY -2
+#define YYEOF 0
+#define YYACCEPT return(0)
+#define YYABORT return(1)
+#define YYERROR goto yyerrlab1
+/* Like YYERROR except do call yyerror.
+ This remains here temporarily to ease the
+ transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+#define YYFAIL goto yyerrlab
+#define YYRECOVERING() (!!yyerrstatus)
+#define YYBACKUP(token, value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { yychar = (token), yylval = (value); \
+ yychar1 = YYTRANSLATE (yychar); \
+ YYPOPSTACK; \
+ goto yybackup; \
+ } \
+ else \
+ { yyerror ("syntax error: cannot back up"); YYERROR; } \
+while (0)
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+#ifndef YYPURE
+#define YYLEX yylex()
+#endif
+
+#ifdef YYPURE
+#ifdef YYLSP_NEEDED
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval, &yylloc)
+#endif
+#else /* not YYLSP_NEEDED */
+#ifdef YYLEX_PARAM
+#define YYLEX yylex(&yylval, YYLEX_PARAM)
+#else
+#define YYLEX yylex(&yylval)
+#endif
+#endif /* not YYLSP_NEEDED */
+#endif
+
+/* If nonreentrant, generate the variables here */
+
+#ifndef YYPURE
+
+int yychar; /* the lookahead symbol */
+YYSTYPE yylval; /* the semantic value of the */
+ /* lookahead symbol */
+
+#ifdef YYLSP_NEEDED
+YYLTYPE yylloc; /* location data for the lookahead */
+ /* symbol */
+#endif
+
+int yynerrs; /* number of parse errors so far */
+#endif /* not YYPURE */
+
+#if YYDEBUG != 0
+int yydebug; /* nonzero means print parse trace */
+/* Since this is uninitialized, it does not stop multiple parsers
+ from coexisting. */
+#endif
+
+/* YYINITDEPTH indicates the initial size of the parser's stacks */
+
+#ifndef YYINITDEPTH
+#define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH is the maximum size the stacks can grow to
+ (effective only if the built-in stack extension method is used). */
+
+#if YYMAXDEPTH == 0
+#undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 10000
+#endif
+
+/* Prevent warning if -Wstrict-prototypes. */
+#ifdef __GNUC__
+int yyparse (void);
+#endif
+
+#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
+#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
+#else /* not GNU C or C++ */
+#ifndef __cplusplus
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (from, to, count)
+ char *from;
+ char *to;
+ int count;
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#else /* __cplusplus */
+
+/* This is the most reliable way to avoid incompatibilities
+ in available built-in functions on various systems. */
+static void
+__yy_memcpy (char *from, char *to, int count)
+{
+ register char *f = from;
+ register char *t = to;
+ register int i = count;
+
+ while (i-- > 0)
+ *t++ = *f++;
+}
+
+#endif
+#endif
+
+#line 192 "/usr/unsupported/share/bison.simple"
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+ into yyparse. The argument should have type void *.
+ It should actually point to an object.
+ Grammar actions can access the variable by casting it
+ to the proper pointer type. */
+
+#ifdef YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+#else
+#define YYPARSE_PARAM
+#define YYPARSE_PARAM_DECL
+#endif
+
+int
+yyparse(YYPARSE_PARAM)
+ YYPARSE_PARAM_DECL
+{
+ register int yystate;
+ register int yyn;
+ register short *yyssp;
+ register YYSTYPE *yyvsp;
+ int yyerrstatus; /* number of tokens to shift before error messages enabled */
+ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
+
+ short yyssa[YYINITDEPTH]; /* the state stack */
+ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
+
+ short *yyss = yyssa; /* refer to the stacks thru separate pointers */
+ YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to xreallocate them elsewhere */
+
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+
+#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
+#else
+#define YYPOPSTACK (yyvsp--, yyssp--)
+#endif
+
+ int yystacksize = YYINITDEPTH;
+
+#ifdef YYPURE
+ int yychar;
+ YYSTYPE yylval;
+ int yynerrs;
+#ifdef YYLSP_NEEDED
+ YYLTYPE yylloc;
+#endif
+#endif
+
+ YYSTYPE yyval; /* the variable used to return */
+ /* semantic values from the action */
+ /* routines */
+
+ int yylen;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Starting parse\n");
+#endif
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss - 1;
+ yyvsp = yyvs;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls;
+#endif
+
+/* Push a new state, which is found in yystate . */
+/* In all cases, when you get here, the value and location stacks
+ have just been pushed. so pushing a state here evens the stacks. */
+yynewstate:
+
+ *++yyssp = yystate;
+
+ if (yyssp >= yyss + yystacksize - 1)
+ {
+ /* Give user a chance to xreallocate the stack */
+ /* Use copies of these so that the &'s don't force the real ones into memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ short *yyss1 = yyss;
+#ifdef YYLSP_NEEDED
+ YYLTYPE *yyls1 = yyls;
+#endif
+
+ /* Get the current used size of the three stacks, in elements. */
+ int size = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ /* Each stack pointer address is followed by the size of
+ the data in use in that stack, in bytes. */
+#ifdef YYLSP_NEEDED
+ /* This used to be a conditional around just the two extra args,
+ but that might be undefined if yyoverflow is a macro. */
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yyls1, size * sizeof (*yylsp),
+ &yystacksize);
+#else
+ yyoverflow("parser stack overflow",
+ &yyss1, size * sizeof (*yyssp),
+ &yyvs1, size * sizeof (*yyvsp),
+ &yystacksize);
+#endif
+
+ yyss = yyss1; yyvs = yyvs1;
+#ifdef YYLSP_NEEDED
+ yyls = yyls1;
+#endif
+#else /* no yyoverflow */
+ /* Extend the stack our own way. */
+ if (yystacksize >= YYMAXDEPTH)
+ {
+ yyerror("parser stack overflow");
+ return 2;
+ }
+ yystacksize *= 2;
+ if (yystacksize > YYMAXDEPTH)
+ yystacksize = YYMAXDEPTH;
+ yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
+ __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
+ yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
+ __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
+#ifdef YYLSP_NEEDED
+ yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
+ __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
+#endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + size - 1;
+ yyvsp = yyvs + size - 1;
+#ifdef YYLSP_NEEDED
+ yylsp = yyls + size - 1;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Stack size increased to %d\n", yystacksize);
+#endif
+
+ if (yyssp >= yyss + yystacksize - 1)
+ YYABORT;
+ }
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Entering state %d\n", yystate);
+#endif
+
+ goto yybackup;
+ yybackup:
+
+/* Do appropriate processing given the current state. */
+/* Read a lookahead token if we need one and don't already have one. */
+/* yyresume: */
+
+ /* First try to decide what to do without reference to lookahead token. */
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* yychar is either YYEMPTY or YYEOF
+ or a valid token in external form. */
+
+ if (yychar == YYEMPTY)
+ {
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Reading a token: ");
+#endif
+ yychar = YYLEX;
+ }
+
+ /* Convert token to internal form (in yychar1) for indexing tables with */
+
+ if (yychar <= 0) /* This means end of input. */
+ {
+ yychar1 = 0;
+ yychar = YYEOF; /* Don't call YYLEX any more */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Now at end of input.\n");
+#endif
+ }
+ else
+ {
+ yychar1 = YYTRANSLATE(yychar);
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
+ /* Give the individual parser a way to print the precise meaning
+ of a token, for further debugging info. */
+#ifdef YYPRINT
+ YYPRINT (stderr, yychar, yylval);
+#endif
+ fprintf (stderr, ")\n");
+ }
+#endif
+ }
+
+ yyn += yychar1;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+ goto yydefault;
+
+ yyn = yytable[yyn];
+
+ /* yyn is what to do for this token type in this state.
+ Negative => reduce, -yyn is rule number.
+ Positive => shift, yyn is new state.
+ New state is final state => don't bother to shift,
+ just return success.
+ 0, or most negative number => error. */
+
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrlab;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Shift the lookahead token. */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
+#endif
+
+ /* Discard the token being shifted unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ /* count tokens shifted since error; after three, turn off error status. */
+ if (yyerrstatus) yyerrstatus--;
+
+ yystate = yyn;
+ goto yynewstate;
+
+/* Do the default action for the current state. */
+yydefault:
+
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+
+/* Do a reduction. yyn is the number of a rule to reduce with. */
+yyreduce:
+ yylen = yyr2[yyn];
+ if (yylen > 0)
+ yyval = yyvsp[1-yylen]; /* implement default value of the action */
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ int i;
+
+ fprintf (stderr, "Reducing via rule %d (line %d), ",
+ yyn, yyrline[yyn]);
+
+ /* Print the symbols being reduced, and their result. */
+ for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
+ fprintf (stderr, "%s ", yytname[yyrhs[i]]);
+ fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+ }
+#endif
+
+
+ switch (yyn) {
+
+case 3:
+#line 209 "./m2-exp.y"
+{ write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type(yyvsp[0].tval);
+ write_exp_elt_opcode(OP_TYPE);
+ ;
+ break;}
+case 4:
+#line 218 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_IND); ;
+ break;}
+case 5:
+#line 221 "./m2-exp.y"
+{ number_sign = -1; ;
+ break;}
+case 6:
+#line 223 "./m2-exp.y"
+{ number_sign = 1;
+ write_exp_elt_opcode (UNOP_NEG); ;
+ break;}
+case 7:
+#line 228 "./m2-exp.y"
+{ write_exp_elt_opcode(UNOP_PLUS); ;
+ break;}
+case 8:
+#line 232 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); ;
+ break;}
+case 11:
+#line 240 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_CAP); ;
+ break;}
+case 12:
+#line 244 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_ORD); ;
+ break;}
+case 13:
+#line 248 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_ABS); ;
+ break;}
+case 14:
+#line 252 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_HIGH); ;
+ break;}
+case 15:
+#line 256 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_MIN);
+ write_exp_elt_type (yyvsp[-1].tval);
+ write_exp_elt_opcode (UNOP_MIN); ;
+ break;}
+case 16:
+#line 262 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_MAX);
+ write_exp_elt_type (yyvsp[-1].tval);
+ write_exp_elt_opcode (UNOP_MIN); ;
+ break;}
+case 17:
+#line 268 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_FLOAT); ;
+ break;}
+case 18:
+#line 272 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_VAL);
+ write_exp_elt_type (yyvsp[-3].tval);
+ write_exp_elt_opcode (BINOP_VAL); ;
+ break;}
+case 19:
+#line 278 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_CHR); ;
+ break;}
+case 20:
+#line 282 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_ODD); ;
+ break;}
+case 21:
+#line 286 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_TRUNC); ;
+ break;}
+case 22:
+#line 290 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_SIZEOF); ;
+ break;}
+case 23:
+#line 295 "./m2-exp.y"
+{ write_exp_elt_opcode(UNOP_PREINCREMENT); ;
+ break;}
+case 24:
+#line 299 "./m2-exp.y"
+{ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode(BINOP_ADD);
+ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY); ;
+ break;}
+case 25:
+#line 305 "./m2-exp.y"
+{ write_exp_elt_opcode(UNOP_PREDECREMENT);;
+ break;}
+case 26:
+#line 309 "./m2-exp.y"
+{ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode(BINOP_SUB);
+ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY); ;
+ break;}
+case 27:
+#line 315 "./m2-exp.y"
+{ write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); ;
+ break;}
+case 29:
+#line 324 "./m2-exp.y"
+{ error("Sets are not implemented.");;
+ break;}
+case 30:
+#line 328 "./m2-exp.y"
+{ error("Sets are not implemented.");;
+ break;}
+case 31:
+#line 332 "./m2-exp.y"
+{ error("Sets are not implemented.");;
+ break;}
+case 32:
+#line 335 "./m2-exp.y"
+{ error("Sets are not implemented.");;
+ break;}
+case 33:
+#line 337 "./m2-exp.y"
+{ error("Sets are not implemented.");;
+ break;}
+case 34:
+#line 346 "./m2-exp.y"
+{ start_arglist(); ;
+ break;}
+case 35:
+#line 348 "./m2-exp.y"
+{ write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst ((LONGEST) end_arglist());
+ write_exp_elt_opcode (MULTI_SUBSCRIPT); ;
+ break;}
+case 36:
+#line 356 "./m2-exp.y"
+{ start_arglist (); ;
+ break;}
+case 37:
+#line 358 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); ;
+ break;}
+case 39:
+#line 367 "./m2-exp.y"
+{ arglist_len = 1; ;
+ break;}
+case 40:
+#line 371 "./m2-exp.y"
+{ arglist_len++; ;
+ break;}
+case 41:
+#line 376 "./m2-exp.y"
+{ arglist_len = 1; ;
+ break;}
+case 42:
+#line 381 "./m2-exp.y"
+{ arglist_len++; ;
+ break;}
+case 43:
+#line 386 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_elt_type (yyvsp[-2].tval);
+ write_exp_elt_opcode (UNOP_MEMVAL); ;
+ break;}
+case 44:
+#line 392 "./m2-exp.y"
+{ write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type (yyvsp[-3].tval);
+ write_exp_elt_opcode (UNOP_CAST); ;
+ break;}
+case 45:
+#line 398 "./m2-exp.y"
+{ ;
+ break;}
+case 46:
+#line 406 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_REPEAT); ;
+ break;}
+case 47:
+#line 410 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_MUL); ;
+ break;}
+case 48:
+#line 414 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_DIV); ;
+ break;}
+case 49:
+#line 418 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_INTDIV); ;
+ break;}
+case 50:
+#line 422 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_REM); ;
+ break;}
+case 51:
+#line 426 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_ADD); ;
+ break;}
+case 52:
+#line 430 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_SUB); ;
+ break;}
+case 53:
+#line 434 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_EQUAL); ;
+ break;}
+case 54:
+#line 438 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_NOTEQUAL); ;
+ break;}
+case 55:
+#line 440 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_NOTEQUAL); ;
+ break;}
+case 56:
+#line 444 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_LEQ); ;
+ break;}
+case 57:
+#line 448 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_GEQ); ;
+ break;}
+case 58:
+#line 452 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_LESS); ;
+ break;}
+case 59:
+#line 456 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_GTR); ;
+ break;}
+case 60:
+#line 460 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_AND); ;
+ break;}
+case 61:
+#line 464 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_OR); ;
+ break;}
+case 62:
+#line 468 "./m2-exp.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN); ;
+ break;}
+case 63:
+#line 475 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].ulval);
+ write_exp_elt_opcode (OP_BOOL); ;
+ break;}
+case 64:
+#line 481 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].ulval);
+ write_exp_elt_opcode (OP_BOOL); ;
+ break;}
+case 65:
+#line 487 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_int);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 66:
+#line 494 "./m2-exp.y"
+{
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_card);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].ulval);
+ write_exp_elt_opcode (OP_LONG);
+ ;
+ break;}
+case 67:
+#line 503 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_char);
+ write_exp_elt_longcst ((LONGEST) yyvsp[0].ulval);
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 68:
+#line 511 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_m2_real);
+ write_exp_elt_dblcst (yyvsp[0].dval);
+ write_exp_elt_opcode (OP_DOUBLE); ;
+ break;}
+case 70:
+#line 521 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH (yyvsp[-1].tval));
+ write_exp_elt_opcode (OP_LONG); ;
+ break;}
+case 71:
+#line 528 "./m2-exp.y"
+{ write_exp_elt_opcode (OP_M2_STRING);
+ write_exp_string (yyvsp[0].sval);
+ write_exp_elt_opcode (OP_M2_STRING); ;
+ break;}
+case 72:
+#line 535 "./m2-exp.y"
+{ yyval.bval = SYMBOL_BLOCK_VALUE(yyvsp[0].sym); ;
+ break;}
+case 73:
+#line 539 "./m2-exp.y"
+{ struct symbol *sym
+ = lookup_symbol (copy_name (yyvsp[0].sval), expression_context_block,
+ VAR_NAMESPACE, 0, NULL);
+ yyval.sym = sym;;
+ break;}
+case 74:
+#line 548 "./m2-exp.y"
+{ struct symbol *tem
+ = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+ VAR_NAMESPACE, 0, NULL);
+ if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+ error ("No function \"%s\" in specified context.",
+ copy_name (yyvsp[0].sval));
+ yyval.sym = tem;
+ ;
+ break;}
+case 75:
+#line 560 "./m2-exp.y"
+{ write_exp_elt_opcode(OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (yyvsp[0].sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); ;
+ break;}
+case 77:
+#line 572 "./m2-exp.y"
+{ struct symbol *sym;
+ sym = lookup_symbol (copy_name (yyvsp[0].sval), yyvsp[-2].bval,
+ VAR_NAMESPACE, 0, NULL);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name (yyvsp[0].sval));
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* block_found is set by lookup_symbol. */
+ write_exp_elt_block (block_found);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); ;
+ break;}
+case 78:
+#line 588 "./m2-exp.y"
+{ struct symbol *sym;
+ int is_a_field_of_this;
+
+ sym = lookup_symbol (copy_name (yyvsp[0].sval),
+ expression_context_block,
+ VAR_NAMESPACE,
+ &is_a_field_of_this,
+ NULL);
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name (yyvsp[0].sval);
+
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol
+ (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name (yyvsp[0].sval));
+ }
+ ;
+ break;}
+case 79:
+#line 639 "./m2-exp.y"
+{ yyval.tval = lookup_typename (copy_name (yyvsp[0].sval),
+ expression_context_block, 0); ;
+ break;}
+}
+ /* the action file gets copied in in place of this dollarsign */
+#line 487 "/usr/unsupported/share/bison.simple"
+
+ yyvsp -= yylen;
+ yyssp -= yylen;
+#ifdef YYLSP_NEEDED
+ yylsp -= yylen;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+ *++yyvsp = yyval;
+
+#ifdef YYLSP_NEEDED
+ yylsp++;
+ if (yylen == 0)
+ {
+ yylsp->first_line = yylloc.first_line;
+ yylsp->first_column = yylloc.first_column;
+ yylsp->last_line = (yylsp-1)->last_line;
+ yylsp->last_column = (yylsp-1)->last_column;
+ yylsp->text = 0;
+ }
+ else
+ {
+ yylsp->last_line = (yylsp+yylen-1)->last_line;
+ yylsp->last_column = (yylsp+yylen-1)->last_column;
+ }
+#endif
+
+ /* Now "shift" the result of the reduction.
+ Determine what state that goes to,
+ based on the state we popped back to
+ and the rule number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+ if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTBASE];
+
+ goto yynewstate;
+
+yyerrlab: /* here on detecting error */
+
+ if (! yyerrstatus)
+ /* If not already recovering from an error, report this error. */
+ {
+ ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+ yyn = yypact[yystate];
+
+ if (yyn > YYFLAG && yyn < YYLAST)
+ {
+ int size = 0;
+ char *msg;
+ int x, count;
+
+ count = 0;
+ /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ size += strlen(yytname[x]) + 15, count++;
+ msg = (char *) xmalloc(size + 15);
+ if (msg != 0)
+ {
+ strcpy(msg, "parse error");
+
+ if (count < 5)
+ {
+ count = 0;
+ for (x = (yyn < 0 ? -yyn : 0);
+ x < (sizeof(yytname) / sizeof(char *)); x++)
+ if (yycheck[x + yyn] == x)
+ {
+ strcat(msg, count == 0 ? ", expecting `" : " or `");
+ strcat(msg, yytname[x]);
+ strcat(msg, "'");
+ count++;
+ }
+ }
+ yyerror(msg);
+ free(msg);
+ }
+ else
+ yyerror ("parse error; also virtual memory exceeded");
+ }
+ else
+#endif /* YYERROR_VERBOSE */
+ yyerror("parse error");
+ }
+
+ goto yyerrlab1;
+yyerrlab1: /* here on error raised explicitly by an action */
+
+ if (yyerrstatus == 3)
+ {
+ /* if just tried and failed to reuse lookahead token after an error, discard it. */
+
+ /* return failure if at end of input */
+ if (yychar == YYEOF)
+ YYABORT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
+#endif
+
+ yychar = YYEMPTY;
+ }
+
+ /* Else will try to reuse lookahead token
+ after shifting the error token. */
+
+ yyerrstatus = 3; /* Each real token shifted decrements this */
+
+ goto yyerrhandle;
+
+yyerrdefault: /* current state does not do anything special for the error token. */
+
+#if 0
+ /* This is wrong; only states that explicitly want error tokens
+ should shift them. */
+ yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
+ if (yyn) goto yydefault;
+#endif
+
+yyerrpop: /* pop the current state because it cannot handle the error token */
+
+ if (yyssp == yyss) YYABORT;
+ yyvsp--;
+ yystate = *--yyssp;
+#ifdef YYLSP_NEEDED
+ yylsp--;
+#endif
+
+#if YYDEBUG != 0
+ if (yydebug)
+ {
+ short *ssp1 = yyss - 1;
+ fprintf (stderr, "Error: state stack now");
+ while (ssp1 != yyssp)
+ fprintf (stderr, " %d", *++ssp1);
+ fprintf (stderr, "\n");
+ }
+#endif
+
+yyerrhandle:
+
+ yyn = yypact[yystate];
+ if (yyn == YYFLAG)
+ goto yyerrdefault;
+
+ yyn += YYTERROR;
+ if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+ goto yyerrdefault;
+
+ yyn = yytable[yyn];
+ if (yyn < 0)
+ {
+ if (yyn == YYFLAG)
+ goto yyerrpop;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+ else if (yyn == 0)
+ goto yyerrpop;
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+#if YYDEBUG != 0
+ if (yydebug)
+ fprintf(stderr, "Shifting error token, ");
+#endif
+
+ *++yyvsp = yylval;
+#ifdef YYLSP_NEEDED
+ *++yylsp = yylloc;
+#endif
+
+ yystate = yyn;
+ goto yynewstate;
+}
+#line 644 "./m2-exp.y"
+
+
+#if 0 /* FIXME! */
+int
+overflow(a,b)
+ long a,b;
+{
+ return (MAX_OF_TYPE(builtin_type_m2_int) - b) < a;
+}
+
+int
+uoverflow(a,b)
+ unsigned long a,b;
+{
+ return (MAX_OF_TYPE(builtin_type_m2_card) - b) < a;
+}
+#endif /* FIXME */
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (olen)
+ int olen;
+{
+ register char *p = lexptr;
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ register int c,i,ischar=0;
+ register int base = input_radix;
+ register int len = olen;
+ int unsigned_p = number_sign == 1 ? 1 : 0;
+
+ if(p[len-1] == 'H')
+ {
+ base = 16;
+ len--;
+ }
+ else if(p[len-1] == 'C' || p[len-1] == 'B')
+ {
+ base = 8;
+ ischar = p[len-1] == 'C';
+ len--;
+ }
+
+ /* Scan the number */
+ for (c = 0; c < len; c++)
+ {
+ if (p[c] == '.' && base == 10)
+ {
+ /* It's a float since it contains a point. */
+ yylval.dval = atof (p);
+ lexptr += len;
+ return FLOAT;
+ }
+ if (p[c] == '.' && base != 10)
+ error("Floating point numbers must be base 10.");
+ if (base == 10 && (p[c] < '0' || p[c] > '9'))
+ error("Invalid digit \'%c\' in number.",p[c]);
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ n *= base;
+ if( base == 8 && (c == '8' || c == '9'))
+ error("Invalid digit \'%c\' in octal number.",c);
+ if (c >= '0' && c <= '9')
+ i = c - '0';
+ else
+ {
+ if (base == 16 && c >= 'A' && c <= 'F')
+ i = c - 'A' + 10;
+ else
+ return ERROR;
+ }
+ n+=i;
+ if(i >= base)
+ return ERROR;
+ if(!unsigned_p && number_sign == 1 && (prevn >= n))
+ unsigned_p=1; /* Try something unsigned */
+ /* Don't do the range check if n==i and i==0, since that special
+ case will give an overflow error. */
+ if(RANGE_CHECK && n!=i && i)
+ {
+ if((unsigned_p && (unsigned)prevn >= (unsigned)n) ||
+ ((!unsigned_p && number_sign==-1) && -prevn <= -n))
+ range_error("Overflow on numeric constant.");
+ }
+ prevn=n;
+ }
+
+ lexptr = p;
+ if(*p == 'B' || *p == 'C' || *p == 'H')
+ lexptr++; /* Advance past B,C or H */
+
+ if (ischar)
+ {
+ yylval.ulval = n;
+ return CHAR;
+ }
+ else if ( unsigned_p && number_sign == 1)
+ {
+ yylval.ulval = n;
+ return UINT;
+ }
+ else if((unsigned_p && (n<0))) {
+ range_error("Overflow on numeric constant -- number too large.");
+ /* But, this can return if range_check == range_warn. */
+ }
+ yylval.lval = n;
+ return INT;
+}
+
+
+/* Some tokens */
+
+static struct
+{
+ char name[2];
+ int token;
+} tokentab2[] =
+{
+ { {'<', '>'}, NOTEQUAL },
+ { {':', '='}, ASSIGN },
+ { {'<', '='}, LEQ },
+ { {'>', '='}, GEQ },
+ { {':', ':'}, COLONCOLON },
+
+};
+
+/* Some specific keywords */
+
+struct keyword {
+ char keyw[10];
+ int token;
+};
+
+static struct keyword keytab[] =
+{
+ {"OR" , OROR },
+ {"IN", IN },/* Note space after IN */
+ {"AND", LOGICAL_AND},
+ {"ABS", ABS },
+ {"CHR", CHR },
+ {"DEC", DEC },
+ {"NOT", NOT },
+ {"DIV", DIV },
+ {"INC", INC },
+ {"MAX", MAX_FUNC },
+ {"MIN", MIN_FUNC },
+ {"MOD", MOD },
+ {"ODD", ODD },
+ {"CAP", CAP },
+ {"ORD", ORD },
+ {"VAL", VAL },
+ {"EXCL", EXCL },
+ {"HIGH", HIGH },
+ {"INCL", INCL },
+ {"SIZE", SIZE },
+ {"FLOAT", FLOAT_FUNC },
+ {"TRUNC", TRUNC },
+};
+
+
+/* Read one token, getting characters through lexptr. */
+
+/* This is where we will check to make sure that the language and the operators used are
+ compatible */
+
+static int
+yylex ()
+{
+ register int c;
+ register int namelen;
+ register int i;
+ register char *tokstart;
+ register char quote;
+
+ retry:
+
+ tokstart = lexptr;
+
+
+ /* See if it is a special token of length 2 */
+ for( i = 0 ; i < (int) (sizeof tokentab2 / sizeof tokentab2[0]) ; i++)
+ if(STREQN(tokentab2[i].name, tokstart, 2))
+ {
+ lexptr += 2;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] >= '0' && lexptr[1] <= '9')
+ break; /* Falls into number code. */
+ else
+ {
+ lexptr++;
+ return DOT;
+ }
+
+/* These are character tokens that appear as-is in the YACC grammar */
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '^':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '=':
+ case '{':
+ case '}':
+ case '#':
+ case '@':
+ case '~':
+ case '&':
+ lexptr++;
+ return c;
+
+ case '\'' :
+ case '"':
+ quote = c;
+ for (namelen = 1; (c = tokstart[namelen]) != quote && c != '\0'; namelen++)
+ if (c == '\\')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ c = tokstart[++namelen];
+ }
+ }
+ if(c != quote)
+ error("Unterminated string or character constant.");
+ yylval.sval.ptr = tokstart + 1;
+ yylval.sval.length = namelen - 1;
+ lexptr += namelen + 1;
+
+ if(namelen == 2) /* Single character */
+ {
+ yylval.ulval = tokstart[1];
+ return CHAR;
+ }
+ else
+ return STRING;
+ }
+
+ /* Is it a number? */
+ /* Note: We have already dealt with the case of the token '.'.
+ See case '.' above. */
+ if ((c >= '0' && c <= '9'))
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0;
+ register char *p = tokstart;
+ int toktype;
+
+ for (++p ;; ++p)
+ {
+ if (!got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ else if ((*p < '0' || *p > '9') &&
+ (*p < 'A' || *p > 'F') &&
+ (*p != 'H')) /* Modula-2 hexadecimal number */
+ break;
+ }
+ toktype = parse_number (p - tokstart);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen])
+ ;
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ lexptr += namelen;
+
+ /* Lookup special keywords */
+ for(i = 0 ; i < (int) (sizeof(keytab) / sizeof(keytab[0])) ; i++)
+ if(namelen == strlen(keytab[i].keyw) && STREQN(tokstart,keytab[i].keyw,namelen))
+ return keytab[i].token;
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return INTERNAL_VAR;
+ }
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+
+
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+
+ if (lookup_partial_symtab (tmp))
+ return BLOCKNAME;
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, 0, NULL);
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ return BLOCKNAME;
+ if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1))
+ return TYPENAME;
+
+ if(sym)
+ {
+ switch(sym->aclass)
+ {
+ case LOC_STATIC:
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ case LOC_OPTIMIZED_OUT:
+ return NAME;
+
+ case LOC_TYPEDEF:
+ return TYPENAME;
+
+ case LOC_BLOCK:
+ return BLOCKNAME;
+
+ case LOC_UNDEF:
+ error("internal: Undefined class in m2lex()");
+
+ case LOC_LABEL:
+ case LOC_UNRESOLVED:
+ error("internal: Unforseen case in m2lex()");
+ }
+ }
+ else
+ {
+ /* Built-in BOOLEAN type. This is sort of a hack. */
+ if(STREQN(tokstart,"TRUE",4))
+ {
+ yylval.ulval = 1;
+ return M2_TRUE;
+ }
+ else if(STREQN(tokstart,"FALSE",5))
+ {
+ yylval.ulval = 0;
+ return M2_FALSE;
+ }
+ }
+
+ /* Must be another type of name... */
+ return NAME;
+ }
+}
+
+#if 0 /* Unused */
+static char *
+make_qualname(mod,ident)
+ char *mod, *ident;
+{
+ char *new = xmalloc(strlen(mod)+strlen(ident)+2);
+
+ strcpy(new,mod);
+ strcat(new,".");
+ strcat(new,ident);
+ return new;
+}
+#endif /* 0 */
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/contrib/gdb/gdb/m2-exp.y b/contrib/gdb/gdb/m2-exp.y
new file mode 100644
index 0000000..08a11ce
--- /dev/null
+++ b/contrib/gdb/gdb/m2-exp.y
@@ -0,0 +1,1094 @@
+/* YACC grammar for Modula-2 expressions, for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+ Generated from expread.y (now c-exp.y) and contributed by the Department
+ of Computer Science at the State University of New York at Buffalo, 1991.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Parse a Modula-2 expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result.
+
+ Note that malloc's and realloc's in this file are transformed to
+ xmalloc and xrealloc respectively by the same sed command in the
+ makefile that remaps any other malloc/realloc inserted by the parser
+ generator. Doing this with #defines and trying to control the interaction
+ with include files (<malloc.h> and <stdlib.h> for example) just became
+ too messy, particularly when such includes can be inserted at random
+ times by the parser generator. */
+
+%{
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "expression.h"
+#include "language.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "m2-lang.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+ as well as gratuitiously global symbol names, so we can have multiple
+ yacc generated parsers in gdb. Note that these are only the variables
+ produced by yacc. If other parser generators (bison, byacc, etc) produce
+ additional global names that conflict at link time, then those parser
+ generators need to be fixed instead of adding those names to this list. */
+
+#define yymaxdepth m2_maxdepth
+#define yyparse m2_parse
+#define yylex m2_lex
+#define yyerror m2_error
+#define yylval m2_lval
+#define yychar m2_char
+#define yydebug m2_debug
+#define yypact m2_pact
+#define yyr1 m2_r1
+#define yyr2 m2_r2
+#define yydef m2_def
+#define yychk m2_chk
+#define yypgo m2_pgo
+#define yyact m2_act
+#define yyexca m2_exca
+#define yyerrflag m2_errflag
+#define yynerrs m2_nerrs
+#define yyps m2_ps
+#define yypv m2_pv
+#define yys m2_s
+#define yy_yys m2_yys
+#define yystate m2_state
+#define yytmp m2_tmp
+#define yyv m2_v
+#define yy_yyv m2_yyv
+#define yyval m2_val
+#define yylloc m2_lloc
+#define yyreds m2_reds /* With YYDEBUG defined */
+#define yytoks m2_toks /* With YYDEBUG defined */
+#define yylhs m2_yylhs
+#define yylen m2_yylen
+#define yydefred m2_yydefred
+#define yydgoto m2_yydgoto
+#define yysindex m2_yysindex
+#define yyrindex m2_yyrindex
+#define yygindex m2_yygindex
+#define yytable m2_yytable
+#define yycheck m2_yycheck
+
+#ifndef YYDEBUG
+#define YYDEBUG 0 /* Default to no yydebug support */
+#endif
+
+int
+yyparse PARAMS ((void));
+
+static int
+yylex PARAMS ((void));
+
+void
+yyerror PARAMS ((char *));
+
+#if 0
+static char *
+make_qualname PARAMS ((char *, char *));
+#endif
+
+static int
+parse_number PARAMS ((int));
+
+/* The sign of the number being parsed. */
+static int number_sign = 1;
+
+/* The block that the module specified by the qualifer on an identifer is
+ contained in, */
+#if 0
+static struct block *modblock=0;
+#endif
+
+%}
+
+/* Although the yacc "value" of an expression is not used,
+ since the result is stored in the structure being created,
+ other node types do have values. */
+
+%union
+ {
+ LONGEST lval;
+ unsigned LONGEST ulval;
+ DOUBLEST dval;
+ struct symbol *sym;
+ struct type *tval;
+ struct stoken sval;
+ int voidval;
+ struct block *bval;
+ enum exp_opcode opcode;
+ struct internalvar *ivar;
+
+ struct type **tvec;
+ int *ivec;
+ }
+
+%type <voidval> exp type_exp start set
+%type <voidval> variable
+%type <tval> type
+%type <bval> block
+%type <sym> fblock
+
+%token <lval> INT HEX ERROR
+%token <ulval> UINT M2_TRUE M2_FALSE CHAR
+%token <dval> FLOAT
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+ and both convey their data as strings.
+ But a TYPENAME is a string that happens to be defined as a typedef
+ or builtin type name (such as int or char)
+ and a NAME is any other symbol.
+
+ Contexts where this distinction is not important can use the
+ nonterminal "name", which matches either NAME or TYPENAME. */
+
+%token <sval> STRING
+%token <sval> NAME BLOCKNAME IDENT VARNAME
+%token <sval> TYPENAME
+
+%token SIZE CAP ORD HIGH ABS MIN_FUNC MAX_FUNC FLOAT_FUNC VAL CHR ODD TRUNC
+%token INC DEC INCL EXCL
+
+/* The GDB scope operator */
+%token COLONCOLON
+
+%token <voidval> INTERNAL_VAR
+
+/* M2 tokens */
+%left ','
+%left ABOVE_COMMA
+%nonassoc ASSIGN
+%left '<' '>' LEQ GEQ '=' NOTEQUAL '#' IN
+%left OROR
+%left LOGICAL_AND '&'
+%left '@'
+%left '+' '-'
+%left '*' '/' DIV MOD
+%right UNARY
+%right '^' DOT '[' '('
+%right NOT '~'
+%left COLONCOLON QID
+/* This is not an actual token ; it is used for precedence.
+%right QID
+*/
+
+
+%%
+
+start : exp
+ | type_exp
+ ;
+
+type_exp: type
+ { write_exp_elt_opcode(OP_TYPE);
+ write_exp_elt_type($1);
+ write_exp_elt_opcode(OP_TYPE);
+ }
+ ;
+
+/* Expressions */
+
+exp : exp '^' %prec UNARY
+ { write_exp_elt_opcode (UNOP_IND); }
+
+exp : '-'
+ { number_sign = -1; }
+ exp %prec UNARY
+ { number_sign = 1;
+ write_exp_elt_opcode (UNOP_NEG); }
+ ;
+
+exp : '+' exp %prec UNARY
+ { write_exp_elt_opcode(UNOP_PLUS); }
+ ;
+
+exp : not_exp exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+ ;
+
+not_exp : NOT
+ | '~'
+ ;
+
+exp : CAP '(' exp ')'
+ { write_exp_elt_opcode (UNOP_CAP); }
+ ;
+
+exp : ORD '(' exp ')'
+ { write_exp_elt_opcode (UNOP_ORD); }
+ ;
+
+exp : ABS '(' exp ')'
+ { write_exp_elt_opcode (UNOP_ABS); }
+ ;
+
+exp : HIGH '(' exp ')'
+ { write_exp_elt_opcode (UNOP_HIGH); }
+ ;
+
+exp : MIN_FUNC '(' type ')'
+ { write_exp_elt_opcode (UNOP_MIN);
+ write_exp_elt_type ($3);
+ write_exp_elt_opcode (UNOP_MIN); }
+ ;
+
+exp : MAX_FUNC '(' type ')'
+ { write_exp_elt_opcode (UNOP_MAX);
+ write_exp_elt_type ($3);
+ write_exp_elt_opcode (UNOP_MIN); }
+ ;
+
+exp : FLOAT_FUNC '(' exp ')'
+ { write_exp_elt_opcode (UNOP_FLOAT); }
+ ;
+
+exp : VAL '(' type ',' exp ')'
+ { write_exp_elt_opcode (BINOP_VAL);
+ write_exp_elt_type ($3);
+ write_exp_elt_opcode (BINOP_VAL); }
+ ;
+
+exp : CHR '(' exp ')'
+ { write_exp_elt_opcode (UNOP_CHR); }
+ ;
+
+exp : ODD '(' exp ')'
+ { write_exp_elt_opcode (UNOP_ODD); }
+ ;
+
+exp : TRUNC '(' exp ')'
+ { write_exp_elt_opcode (UNOP_TRUNC); }
+ ;
+
+exp : SIZE exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_SIZEOF); }
+ ;
+
+
+exp : INC '(' exp ')'
+ { write_exp_elt_opcode(UNOP_PREINCREMENT); }
+ ;
+
+exp : INC '(' exp ',' exp ')'
+ { write_exp_elt_opcode(BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode(BINOP_ADD);
+ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : DEC '(' exp ')'
+ { write_exp_elt_opcode(UNOP_PREDECREMENT);}
+ ;
+
+exp : DEC '(' exp ',' exp ')'
+ { write_exp_elt_opcode(BINOP_ASSIGN_MODIFY);
+ write_exp_elt_opcode(BINOP_SUB);
+ write_exp_elt_opcode(BINOP_ASSIGN_MODIFY); }
+ ;
+
+exp : exp DOT NAME
+ { write_exp_elt_opcode (STRUCTOP_STRUCT);
+ write_exp_string ($3);
+ write_exp_elt_opcode (STRUCTOP_STRUCT); }
+ ;
+
+exp : set
+ ;
+
+exp : exp IN set
+ { error("Sets are not implemented.");}
+ ;
+
+exp : INCL '(' exp ',' exp ')'
+ { error("Sets are not implemented.");}
+ ;
+
+exp : EXCL '(' exp ',' exp ')'
+ { error("Sets are not implemented.");}
+
+set : '{' arglist '}'
+ { error("Sets are not implemented.");}
+ | type '{' arglist '}'
+ { error("Sets are not implemented.");}
+ ;
+
+
+/* Modula-2 array subscript notation [a,b,c...] */
+exp : exp '['
+ /* This function just saves the number of arguments
+ that follow in the list. It is *not* specific to
+ function types */
+ { start_arglist(); }
+ non_empty_arglist ']' %prec DOT
+ { write_exp_elt_opcode (MULTI_SUBSCRIPT);
+ write_exp_elt_longcst ((LONGEST) end_arglist());
+ write_exp_elt_opcode (MULTI_SUBSCRIPT); }
+ ;
+
+exp : exp '('
+ /* This is to save the value of arglist_len
+ being accumulated by an outer function call. */
+ { start_arglist (); }
+ arglist ')' %prec DOT
+ { write_exp_elt_opcode (OP_FUNCALL);
+ write_exp_elt_longcst ((LONGEST) end_arglist ());
+ write_exp_elt_opcode (OP_FUNCALL); }
+ ;
+
+arglist :
+ ;
+
+arglist : exp
+ { arglist_len = 1; }
+ ;
+
+arglist : arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+non_empty_arglist
+ : exp
+ { arglist_len = 1; }
+ ;
+
+non_empty_arglist
+ : non_empty_arglist ',' exp %prec ABOVE_COMMA
+ { arglist_len++; }
+ ;
+
+/* GDB construct */
+exp : '{' type '}' exp %prec UNARY
+ { write_exp_elt_opcode (UNOP_MEMVAL);
+ write_exp_elt_type ($2);
+ write_exp_elt_opcode (UNOP_MEMVAL); }
+ ;
+
+exp : type '(' exp ')' %prec UNARY
+ { write_exp_elt_opcode (UNOP_CAST);
+ write_exp_elt_type ($1);
+ write_exp_elt_opcode (UNOP_CAST); }
+ ;
+
+exp : '(' exp ')'
+ { }
+ ;
+
+/* Binary operators in order of decreasing precedence. Note that some
+ of these operators are overloaded! (ie. sets) */
+
+/* GDB construct */
+exp : exp '@' exp
+ { write_exp_elt_opcode (BINOP_REPEAT); }
+ ;
+
+exp : exp '*' exp
+ { write_exp_elt_opcode (BINOP_MUL); }
+ ;
+
+exp : exp '/' exp
+ { write_exp_elt_opcode (BINOP_DIV); }
+ ;
+
+exp : exp DIV exp
+ { write_exp_elt_opcode (BINOP_INTDIV); }
+ ;
+
+exp : exp MOD exp
+ { write_exp_elt_opcode (BINOP_REM); }
+ ;
+
+exp : exp '+' exp
+ { write_exp_elt_opcode (BINOP_ADD); }
+ ;
+
+exp : exp '-' exp
+ { write_exp_elt_opcode (BINOP_SUB); }
+ ;
+
+exp : exp '=' exp
+ { write_exp_elt_opcode (BINOP_EQUAL); }
+ ;
+
+exp : exp NOTEQUAL exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ | exp '#' exp
+ { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+ ;
+
+exp : exp LEQ exp
+ { write_exp_elt_opcode (BINOP_LEQ); }
+ ;
+
+exp : exp GEQ exp
+ { write_exp_elt_opcode (BINOP_GEQ); }
+ ;
+
+exp : exp '<' exp
+ { write_exp_elt_opcode (BINOP_LESS); }
+ ;
+
+exp : exp '>' exp
+ { write_exp_elt_opcode (BINOP_GTR); }
+ ;
+
+exp : exp LOGICAL_AND exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+ ;
+
+exp : exp OROR exp
+ { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+ ;
+
+exp : exp ASSIGN exp
+ { write_exp_elt_opcode (BINOP_ASSIGN); }
+ ;
+
+
+/* Constants */
+
+exp : M2_TRUE
+ { write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL); }
+ ;
+
+exp : M2_FALSE
+ { write_exp_elt_opcode (OP_BOOL);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_BOOL); }
+ ;
+
+exp : INT
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_int);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : UINT
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_card);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG);
+ }
+ ;
+
+exp : CHAR
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_m2_char);
+ write_exp_elt_longcst ((LONGEST) $1);
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+
+exp : FLOAT
+ { write_exp_elt_opcode (OP_DOUBLE);
+ write_exp_elt_type (builtin_type_m2_real);
+ write_exp_elt_dblcst ($1);
+ write_exp_elt_opcode (OP_DOUBLE); }
+ ;
+
+exp : variable
+ ;
+
+exp : SIZE '(' type ')' %prec UNARY
+ { write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_int);
+ write_exp_elt_longcst ((LONGEST) TYPE_LENGTH ($3));
+ write_exp_elt_opcode (OP_LONG); }
+ ;
+
+exp : STRING
+ { write_exp_elt_opcode (OP_M2_STRING);
+ write_exp_string ($1);
+ write_exp_elt_opcode (OP_M2_STRING); }
+ ;
+
+/* This will be used for extensions later. Like adding modules. */
+block : fblock
+ { $$ = SYMBOL_BLOCK_VALUE($1); }
+ ;
+
+fblock : BLOCKNAME
+ { struct symbol *sym
+ = lookup_symbol (copy_name ($1), expression_context_block,
+ VAR_NAMESPACE, 0, NULL);
+ $$ = sym;}
+ ;
+
+
+/* GDB scope operator */
+fblock : block COLONCOLON BLOCKNAME
+ { struct symbol *tem
+ = lookup_symbol (copy_name ($3), $1,
+ VAR_NAMESPACE, 0, NULL);
+ if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK)
+ error ("No function \"%s\" in specified context.",
+ copy_name ($3));
+ $$ = tem;
+ }
+ ;
+
+/* Useful for assigning to PROCEDURE variables */
+variable: fblock
+ { write_exp_elt_opcode(OP_VAR_VALUE);
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym ($1);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+/* GDB internal ($foo) variable */
+variable: INTERNAL_VAR
+ ;
+
+/* GDB scope operator */
+variable: block COLONCOLON NAME
+ { struct symbol *sym;
+ sym = lookup_symbol (copy_name ($3), $1,
+ VAR_NAMESPACE, 0, NULL);
+ if (sym == 0)
+ error ("No symbol \"%s\" in specified context.",
+ copy_name ($3));
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* block_found is set by lookup_symbol. */
+ write_exp_elt_block (block_found);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE); }
+ ;
+
+/* Base case for variables. */
+variable: NAME
+ { struct symbol *sym;
+ int is_a_field_of_this;
+
+ sym = lookup_symbol (copy_name ($1),
+ expression_context_block,
+ VAR_NAMESPACE,
+ &is_a_field_of_this,
+ NULL);
+ if (sym)
+ {
+ if (symbol_read_needs_frame (sym))
+ {
+ if (innermost_block == 0 ||
+ contained_in (block_found,
+ innermost_block))
+ innermost_block = block_found;
+ }
+
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ /* We want to use the selected frame, not
+ another more inner frame which happens to
+ be in the same block. */
+ write_exp_elt_block (NULL);
+ write_exp_elt_sym (sym);
+ write_exp_elt_opcode (OP_VAR_VALUE);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol;
+ register char *arg = copy_name ($1);
+
+ msymbol =
+ lookup_minimal_symbol (arg, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ write_exp_msymbol
+ (msymbol,
+ lookup_function_type (builtin_type_int),
+ builtin_type_int);
+ }
+ else if (!have_full_symbols () && !have_partial_symbols ())
+ error ("No symbol table is loaded. Use the \"symbol-file\" command.");
+ else
+ error ("No symbol \"%s\" in current context.",
+ copy_name ($1));
+ }
+ }
+ ;
+
+type
+ : TYPENAME
+ { $$ = lookup_typename (copy_name ($1),
+ expression_context_block, 0); }
+
+ ;
+
+%%
+
+#if 0 /* FIXME! */
+int
+overflow(a,b)
+ long a,b;
+{
+ return (MAX_OF_TYPE(builtin_type_m2_int) - b) < a;
+}
+
+int
+uoverflow(a,b)
+ unsigned long a,b;
+{
+ return (MAX_OF_TYPE(builtin_type_m2_card) - b) < a;
+}
+#endif /* FIXME */
+
+/* Take care of parsing a number (anything that starts with a digit).
+ Set yylval and return the token type; update lexptr.
+ LEN is the number of characters in it. */
+
+/*** Needs some error checking for the float case ***/
+
+static int
+parse_number (olen)
+ int olen;
+{
+ register char *p = lexptr;
+ register LONGEST n = 0;
+ register LONGEST prevn = 0;
+ register int c,i,ischar=0;
+ register int base = input_radix;
+ register int len = olen;
+ int unsigned_p = number_sign == 1 ? 1 : 0;
+
+ if(p[len-1] == 'H')
+ {
+ base = 16;
+ len--;
+ }
+ else if(p[len-1] == 'C' || p[len-1] == 'B')
+ {
+ base = 8;
+ ischar = p[len-1] == 'C';
+ len--;
+ }
+
+ /* Scan the number */
+ for (c = 0; c < len; c++)
+ {
+ if (p[c] == '.' && base == 10)
+ {
+ /* It's a float since it contains a point. */
+ yylval.dval = atof (p);
+ lexptr += len;
+ return FLOAT;
+ }
+ if (p[c] == '.' && base != 10)
+ error("Floating point numbers must be base 10.");
+ if (base == 10 && (p[c] < '0' || p[c] > '9'))
+ error("Invalid digit \'%c\' in number.",p[c]);
+ }
+
+ while (len-- > 0)
+ {
+ c = *p++;
+ n *= base;
+ if( base == 8 && (c == '8' || c == '9'))
+ error("Invalid digit \'%c\' in octal number.",c);
+ if (c >= '0' && c <= '9')
+ i = c - '0';
+ else
+ {
+ if (base == 16 && c >= 'A' && c <= 'F')
+ i = c - 'A' + 10;
+ else
+ return ERROR;
+ }
+ n+=i;
+ if(i >= base)
+ return ERROR;
+ if(!unsigned_p && number_sign == 1 && (prevn >= n))
+ unsigned_p=1; /* Try something unsigned */
+ /* Don't do the range check if n==i and i==0, since that special
+ case will give an overflow error. */
+ if(RANGE_CHECK && n!=i && i)
+ {
+ if((unsigned_p && (unsigned)prevn >= (unsigned)n) ||
+ ((!unsigned_p && number_sign==-1) && -prevn <= -n))
+ range_error("Overflow on numeric constant.");
+ }
+ prevn=n;
+ }
+
+ lexptr = p;
+ if(*p == 'B' || *p == 'C' || *p == 'H')
+ lexptr++; /* Advance past B,C or H */
+
+ if (ischar)
+ {
+ yylval.ulval = n;
+ return CHAR;
+ }
+ else if ( unsigned_p && number_sign == 1)
+ {
+ yylval.ulval = n;
+ return UINT;
+ }
+ else if((unsigned_p && (n<0))) {
+ range_error("Overflow on numeric constant -- number too large.");
+ /* But, this can return if range_check == range_warn. */
+ }
+ yylval.lval = n;
+ return INT;
+}
+
+
+/* Some tokens */
+
+static struct
+{
+ char name[2];
+ int token;
+} tokentab2[] =
+{
+ { {'<', '>'}, NOTEQUAL },
+ { {':', '='}, ASSIGN },
+ { {'<', '='}, LEQ },
+ { {'>', '='}, GEQ },
+ { {':', ':'}, COLONCOLON },
+
+};
+
+/* Some specific keywords */
+
+struct keyword {
+ char keyw[10];
+ int token;
+};
+
+static struct keyword keytab[] =
+{
+ {"OR" , OROR },
+ {"IN", IN },/* Note space after IN */
+ {"AND", LOGICAL_AND},
+ {"ABS", ABS },
+ {"CHR", CHR },
+ {"DEC", DEC },
+ {"NOT", NOT },
+ {"DIV", DIV },
+ {"INC", INC },
+ {"MAX", MAX_FUNC },
+ {"MIN", MIN_FUNC },
+ {"MOD", MOD },
+ {"ODD", ODD },
+ {"CAP", CAP },
+ {"ORD", ORD },
+ {"VAL", VAL },
+ {"EXCL", EXCL },
+ {"HIGH", HIGH },
+ {"INCL", INCL },
+ {"SIZE", SIZE },
+ {"FLOAT", FLOAT_FUNC },
+ {"TRUNC", TRUNC },
+};
+
+
+/* Read one token, getting characters through lexptr. */
+
+/* This is where we will check to make sure that the language and the operators used are
+ compatible */
+
+static int
+yylex ()
+{
+ register int c;
+ register int namelen;
+ register int i;
+ register char *tokstart;
+ register char quote;
+
+ retry:
+
+ tokstart = lexptr;
+
+
+ /* See if it is a special token of length 2 */
+ for( i = 0 ; i < (int) (sizeof tokentab2 / sizeof tokentab2[0]) ; i++)
+ if(STREQN(tokentab2[i].name, tokstart, 2))
+ {
+ lexptr += 2;
+ return tokentab2[i].token;
+ }
+
+ switch (c = *tokstart)
+ {
+ case 0:
+ return 0;
+
+ case ' ':
+ case '\t':
+ case '\n':
+ lexptr++;
+ goto retry;
+
+ case '(':
+ paren_depth++;
+ lexptr++;
+ return c;
+
+ case ')':
+ if (paren_depth == 0)
+ return 0;
+ paren_depth--;
+ lexptr++;
+ return c;
+
+ case ',':
+ if (comma_terminates && paren_depth == 0)
+ return 0;
+ lexptr++;
+ return c;
+
+ case '.':
+ /* Might be a floating point number. */
+ if (lexptr[1] >= '0' && lexptr[1] <= '9')
+ break; /* Falls into number code. */
+ else
+ {
+ lexptr++;
+ return DOT;
+ }
+
+/* These are character tokens that appear as-is in the YACC grammar */
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '^':
+ case '<':
+ case '>':
+ case '[':
+ case ']':
+ case '=':
+ case '{':
+ case '}':
+ case '#':
+ case '@':
+ case '~':
+ case '&':
+ lexptr++;
+ return c;
+
+ case '\'' :
+ case '"':
+ quote = c;
+ for (namelen = 1; (c = tokstart[namelen]) != quote && c != '\0'; namelen++)
+ if (c == '\\')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ {
+ c = tokstart[++namelen];
+ if (c >= '0' && c <= '9')
+ c = tokstart[++namelen];
+ }
+ }
+ if(c != quote)
+ error("Unterminated string or character constant.");
+ yylval.sval.ptr = tokstart + 1;
+ yylval.sval.length = namelen - 1;
+ lexptr += namelen + 1;
+
+ if(namelen == 2) /* Single character */
+ {
+ yylval.ulval = tokstart[1];
+ return CHAR;
+ }
+ else
+ return STRING;
+ }
+
+ /* Is it a number? */
+ /* Note: We have already dealt with the case of the token '.'.
+ See case '.' above. */
+ if ((c >= '0' && c <= '9'))
+ {
+ /* It's a number. */
+ int got_dot = 0, got_e = 0;
+ register char *p = tokstart;
+ int toktype;
+
+ for (++p ;; ++p)
+ {
+ if (!got_e && (*p == 'e' || *p == 'E'))
+ got_dot = got_e = 1;
+ else if (!got_dot && *p == '.')
+ got_dot = 1;
+ else if (got_e && (p[-1] == 'e' || p[-1] == 'E')
+ && (*p == '-' || *p == '+'))
+ /* This is the sign of the exponent, not the end of the
+ number. */
+ continue;
+ else if ((*p < '0' || *p > '9') &&
+ (*p < 'A' || *p > 'F') &&
+ (*p != 'H')) /* Modula-2 hexadecimal number */
+ break;
+ }
+ toktype = parse_number (p - tokstart);
+ if (toktype == ERROR)
+ {
+ char *err_copy = (char *) alloca (p - tokstart + 1);
+
+ memcpy (err_copy, tokstart, p - tokstart);
+ err_copy[p - tokstart] = 0;
+ error ("Invalid number \"%s\".", err_copy);
+ }
+ lexptr = p;
+ return toktype;
+ }
+
+ if (!(c == '_' || c == '$'
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')))
+ /* We must have come across a bad character (e.g. ';'). */
+ error ("Invalid character '%c' in expression.", c);
+
+ /* It's a name. See how long it is. */
+ namelen = 0;
+ for (c = tokstart[namelen];
+ (c == '_' || c == '$' || (c >= '0' && c <= '9')
+ || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
+ c = tokstart[++namelen])
+ ;
+
+ /* The token "if" terminates the expression and is NOT
+ removed from the input stream. */
+ if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f')
+ {
+ return 0;
+ }
+
+ lexptr += namelen;
+
+ /* Lookup special keywords */
+ for(i = 0 ; i < (int) (sizeof(keytab) / sizeof(keytab[0])) ; i++)
+ if(namelen == strlen(keytab[i].keyw) && STREQN(tokstart,keytab[i].keyw,namelen))
+ return keytab[i].token;
+
+ yylval.sval.ptr = tokstart;
+ yylval.sval.length = namelen;
+
+ if (*tokstart == '$')
+ {
+ write_dollar_variable (yylval.sval);
+ return INTERNAL_VAR;
+ }
+
+ /* Use token-type BLOCKNAME for symbols that happen to be defined as
+ functions. If this is not so, then ...
+ Use token-type TYPENAME for symbols that happen to be defined
+ currently as names of types; NAME for other symbols.
+ The caller is not constrained to care about the distinction. */
+ {
+
+
+ char *tmp = copy_name (yylval.sval);
+ struct symbol *sym;
+
+ if (lookup_partial_symtab (tmp))
+ return BLOCKNAME;
+ sym = lookup_symbol (tmp, expression_context_block,
+ VAR_NAMESPACE, 0, NULL);
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ return BLOCKNAME;
+ if (lookup_typename (copy_name (yylval.sval), expression_context_block, 1))
+ return TYPENAME;
+
+ if(sym)
+ {
+ switch(sym->aclass)
+ {
+ case LOC_STATIC:
+ case LOC_REGISTER:
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG:
+ case LOC_BASEREG_ARG:
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ case LOC_OPTIMIZED_OUT:
+ return NAME;
+
+ case LOC_TYPEDEF:
+ return TYPENAME;
+
+ case LOC_BLOCK:
+ return BLOCKNAME;
+
+ case LOC_UNDEF:
+ error("internal: Undefined class in m2lex()");
+
+ case LOC_LABEL:
+ case LOC_UNRESOLVED:
+ error("internal: Unforseen case in m2lex()");
+ }
+ }
+ else
+ {
+ /* Built-in BOOLEAN type. This is sort of a hack. */
+ if(STREQN(tokstart,"TRUE",4))
+ {
+ yylval.ulval = 1;
+ return M2_TRUE;
+ }
+ else if(STREQN(tokstart,"FALSE",5))
+ {
+ yylval.ulval = 0;
+ return M2_FALSE;
+ }
+ }
+
+ /* Must be another type of name... */
+ return NAME;
+ }
+}
+
+#if 0 /* Unused */
+static char *
+make_qualname(mod,ident)
+ char *mod, *ident;
+{
+ char *new = malloc(strlen(mod)+strlen(ident)+2);
+
+ strcpy(new,mod);
+ strcat(new,".");
+ strcat(new,ident);
+ return new;
+}
+#endif /* 0 */
+
+void
+yyerror (msg)
+ char *msg;
+{
+ error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
diff --git a/contrib/gdb/gdb/m2-lang.c b/contrib/gdb/gdb/m2-lang.c
new file mode 100644
index 0000000..7502033
--- /dev/null
+++ b/contrib/gdb/gdb/m2-lang.c
@@ -0,0 +1,465 @@
+/* Modula 2 language support routines for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#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
+ characters and strings is language specific.
+ FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true Modula version.
+ */
+
+static void
+emit_char (c, stream, quoter)
+ register int c;
+ GDB_FILE *stream;
+ int quoter;
+{
+
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if (PRINT_LITERAL_FORM (c))
+ {
+ if (c == '\\' || c == quoter)
+ {
+ fputs_filtered ("\\", stream);
+ }
+ fprintf_filtered (stream, "%c", c);
+ }
+ else
+ {
+ switch (c)
+ {
+ case '\n':
+ fputs_filtered ("\\n", stream);
+ break;
+ case '\b':
+ fputs_filtered ("\\b", stream);
+ break;
+ case '\t':
+ fputs_filtered ("\\t", stream);
+ break;
+ case '\f':
+ fputs_filtered ("\\f", stream);
+ break;
+ case '\r':
+ fputs_filtered ("\\r", stream);
+ break;
+ case '\033':
+ fputs_filtered ("\\e", stream);
+ break;
+ case '\007':
+ fputs_filtered ("\\a", stream);
+ break;
+ default:
+ fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
+ break;
+ }
+ }
+}
+
+/* FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true Modula version. */
+
+static void
+m2_printchar (c, stream)
+ int c;
+ GDB_FILE *stream;
+{
+ fputs_filtered ("'", stream);
+ emit_char (c, stream, '\'');
+ fputs_filtered ("'", stream);
+}
+
+/* Print the character string STRING, printing at most LENGTH characters.
+ Printing stops early if the number hits print_max; repeat counts
+ are printed as appropriate. Print ellipses at the end if we
+ had to stop before printing LENGTH characters, or if FORCE_ELLIPSES.
+ FIXME: This is a copy of the same function from c-exp.y. It should
+ be replaced with a true Modula version. */
+
+static void
+m2_printstr (stream, string, length, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ register unsigned int i;
+ unsigned int things_printed = 0;
+ int in_quotes = 0;
+ int need_comma = 0;
+ extern int inspect_it;
+ extern int repeat_count_threshold;
+ extern int print_max;
+
+ if (length == 0)
+ {
+ fputs_filtered ("\"\"", gdb_stdout);
+ return;
+ }
+
+ for (i = 0; i < length && things_printed < print_max; ++i)
+ {
+ /* Position of the character we are examining
+ to see whether it is repeated. */
+ unsigned int rep1;
+ /* Number of repetitions we have detected so far. */
+ unsigned int reps;
+
+ QUIT;
+
+ if (need_comma)
+ {
+ fputs_filtered (", ", stream);
+ need_comma = 0;
+ }
+
+ rep1 = i + 1;
+ reps = 1;
+ while (rep1 < length && string[rep1] == string[i])
+ {
+ ++rep1;
+ ++reps;
+ }
+
+ if (reps > repeat_count_threshold)
+ {
+ if (in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\\", ", stream);
+ else
+ fputs_filtered ("\", ", stream);
+ in_quotes = 0;
+ }
+ m2_printchar (string[i], stream);
+ fprintf_filtered (stream, " <repeats %u times>", reps);
+ i = rep1 - 1;
+ things_printed += repeat_count_threshold;
+ need_comma = 1;
+ }
+ else
+ {
+ if (!in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\\"", stream);
+ else
+ fputs_filtered ("\"", stream);
+ in_quotes = 1;
+ }
+ emit_char (string[i], stream, '"');
+ ++things_printed;
+ }
+ }
+
+ /* Terminate the quotes if necessary. */
+ if (in_quotes)
+ {
+ if (inspect_it)
+ fputs_filtered ("\\\"", stream);
+ else
+ fputs_filtered ("\"", stream);
+ }
+
+ if (force_ellipses || i < length)
+ fputs_filtered ("...", stream);
+}
+
+/* FIXME: This is a copy of c_create_fundamental_type(), before
+ all the non-C types were stripped from it. Needs to be fixed
+ by an experienced Modula programmer. */
+
+static struct type *
+m2_create_fundamental_type (objfile, typeid)
+ struct objfile *objfile;
+ int typeid;
+{
+ register struct type *type = NULL;
+
+ switch (typeid)
+ {
+ default:
+ /* FIXME: For now, if we are asked to produce a type not in this
+ language, create the equivalent of a C integer type with the
+ name "<?type?>". When all the dust settles from the type
+ reconstruction work, this should probably become an error. */
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "<?type?>", objfile);
+ warning ("internal error: no Modula fundamental type %d", typeid);
+ break;
+ case FT_VOID:
+ type = init_type (TYPE_CODE_VOID,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "void", objfile);
+ break;
+ case FT_BOOLEAN:
+ type = init_type (TYPE_CODE_BOOL,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "boolean", objfile);
+ break;
+ case FT_STRING:
+ type = init_type (TYPE_CODE_STRING,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "string", objfile);
+ break;
+ case FT_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "char", objfile);
+ break;
+ case FT_SIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "signed char", objfile);
+ break;
+ case FT_UNSIGNED_CHAR:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
+ break;
+ case FT_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile);
+ break;
+ case FT_SIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ 0, "short", objfile); /* FIXME-fnf */
+ break;
+ case FT_UNSIGNED_SHORT:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
+ break;
+ case FT_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", objfile);
+ break;
+ case FT_SIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_INTEGER:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
+ break;
+ case FT_FIXED_DECIMAL:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "fixed decimal", objfile);
+ break;
+ case FT_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile);
+ break;
+ case FT_SIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long", objfile); /* FIXME -fnf */
+ break;
+ case FT_UNSIGNED_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
+ break;
+ case FT_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "long long", objfile);
+ break;
+ case FT_SIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "signed long long", objfile);
+ break;
+ case FT_UNSIGNED_LONG_LONG:
+ type = init_type (TYPE_CODE_INT,
+ TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
+ break;
+ case FT_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "float", objfile);
+ break;
+ case FT_DBL_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "double", objfile);
+ break;
+ case FT_FLOAT_DECIMAL:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "floating decimal", objfile);
+ break;
+ case FT_EXT_PREC_FLOAT:
+ type = init_type (TYPE_CODE_FLT,
+ TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "long double", objfile);
+ break;
+ case FT_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0, "complex", objfile);
+ TYPE_TARGET_TYPE (type)
+ = m2_create_fundamental_type (objfile, FT_FLOAT);
+ break;
+ case FT_DBL_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "double complex", objfile);
+ TYPE_TARGET_TYPE (type)
+ = m2_create_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ break;
+ case FT_EXT_PREC_COMPLEX:
+ type = init_type (TYPE_CODE_COMPLEX,
+ 2 * TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "long double complex", objfile);
+ TYPE_TARGET_TYPE (type)
+ = m2_create_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+ break;
+ }
+ return (type);
+}
+
+
+/* Table of operators and their precedences for printing expressions. */
+
+static const struct op_print m2_op_print_tab[] = {
+ {"+", BINOP_ADD, PREC_ADD, 0},
+ {"+", UNOP_PLUS, PREC_PREFIX, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"DIV", BINOP_INTDIV, PREC_MUL, 0},
+ {"MOD", BINOP_REM, PREC_MUL, 0},
+ {":=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"OR", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"AND", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"NOT", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"=", BINOP_EQUAL, PREC_EQUAL, 0},
+ {"<>", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+ {"<=", BINOP_LEQ, PREC_ORDER, 0},
+ {">=", BINOP_GEQ, PREC_ORDER, 0},
+ {">", BINOP_GTR, PREC_ORDER, 0},
+ {"<", BINOP_LESS, PREC_ORDER, 0},
+ {"^", UNOP_IND, PREC_PREFIX, 0},
+ {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+ {"CAP", UNOP_CAP, PREC_BUILTIN_FUNCTION, 0},
+ {"CHR", UNOP_CHR, PREC_BUILTIN_FUNCTION, 0},
+ {"ORD", UNOP_ORD, PREC_BUILTIN_FUNCTION, 0},
+ {"FLOAT",UNOP_FLOAT, PREC_BUILTIN_FUNCTION, 0},
+ {"HIGH", UNOP_HIGH, PREC_BUILTIN_FUNCTION, 0},
+ {"MAX", UNOP_MAX, PREC_BUILTIN_FUNCTION, 0},
+ {"MIN", UNOP_MIN, PREC_BUILTIN_FUNCTION, 0},
+ {"ODD", UNOP_ODD, PREC_BUILTIN_FUNCTION, 0},
+ {"TRUNC", UNOP_TRUNC, PREC_BUILTIN_FUNCTION, 0},
+ {NULL, 0, 0, 0}
+};
+
+/* The built-in types of Modula-2. */
+
+struct type *builtin_type_m2_char;
+struct type *builtin_type_m2_int;
+struct type *builtin_type_m2_card;
+struct type *builtin_type_m2_real;
+struct type *builtin_type_m2_bool;
+
+struct type ** const (m2_builtin_types[]) =
+{
+ &builtin_type_m2_char,
+ &builtin_type_m2_int,
+ &builtin_type_m2_card,
+ &builtin_type_m2_real,
+ &builtin_type_m2_bool,
+ 0
+};
+
+const struct language_defn m2_language_defn = {
+ "modula-2",
+ language_m2,
+ m2_builtin_types,
+ range_check_on,
+ type_check_on,
+ m2_parse, /* parser */
+ m2_error, /* parser error function */
+ evaluate_subexp_standard,
+ m2_printchar, /* Print character constant */
+ m2_printstr, /* function to print string constant */
+ 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 */
+ c_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"%loB", "", "o", "B"}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"0%lXH", "0", "X", "H"}, /* Hex format info */
+ m2_op_print_tab, /* expression operators for printing */
+ 0, /* arrays are first-class (not c-style) */
+ 0, /* String lower bound */
+ &builtin_type_m2_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+/* Initialization for Modula-2 */
+
+void
+_initialize_m2_language ()
+{
+ /* Modula-2 "pervasive" types. NOTE: these can be redefined!!! */
+ builtin_type_m2_int =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "INTEGER", (struct objfile *) NULL);
+ builtin_type_m2_card =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "CARDINAL", (struct objfile *) NULL);
+ builtin_type_m2_real =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "REAL", (struct objfile *) NULL);
+ builtin_type_m2_char =
+ init_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "CHAR", (struct objfile *) NULL);
+ builtin_type_m2_bool =
+ init_type (TYPE_CODE_BOOL, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED,
+ "BOOLEAN", (struct objfile *) NULL);
+
+ add_language (&m2_language_defn);
+}
diff --git a/contrib/gdb/gdb/m2-lang.h b/contrib/gdb/gdb/m2-lang.h
new file mode 100644
index 0000000..36bcfc3
--- /dev/null
+++ b/contrib/gdb/gdb/m2-lang.h
@@ -0,0 +1,31 @@
+/* Modula 2 language support definitions for GDB, the GNU debugger.
+ Copyright 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+extern int
+m2_parse PARAMS ((void)); /* Defined in m2-exp.y */
+
+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 *, GDB_FILE *, int, int));
+
+extern int
+m2_val_print PARAMS ((struct type *, char *, CORE_ADDR, GDB_FILE *, int, int,
+ int, enum val_prettyprint));
diff --git a/contrib/gdb/gdb/m2-typeprint.c b/contrib/gdb/gdb/m2-typeprint.c
new file mode 100644
index 0000000..317f401
--- /dev/null
+++ b/contrib/gdb/gdb/m2-typeprint.c
@@ -0,0 +1,49 @@
+/* Support for printing Modula 2 types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "m2-lang.h"
+
+#include "gdb_string.h"
+#include <errno.h>
+
+void
+m2_print_type (type, varstring, stream, show, level)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+ int level;
+{
+ 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/contrib/gdb/gdb/m2-valprint.c b/contrib/gdb/gdb/m2-valprint.c
new file mode 100644
index 0000000..28ea3b1
--- /dev/null
+++ b/contrib/gdb/gdb/m2-valprint.c
@@ -0,0 +1,45 @@
+/* Support for printing Modula 2 values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "valprint.h"
+
+/* FIXME: For now, just explicitly declare c_val_print and use it instead */
+
+int
+m2_val_print (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;
+{
+ extern 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/contrib/gdb/gdb/m3-nat.c b/contrib/gdb/gdb/m3-nat.c
new file mode 100644
index 0000000..1ea1769
--- /dev/null
+++ b/contrib/gdb/gdb/m3-nat.c
@@ -0,0 +1,4640 @@
+/* Interface GDB to Mach 3.0 operating systems.
+ (Most) Mach 3.0 related routines live in this file.
+
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Author: Jukka Virtanen <jtv@hut.fi>
+ * Computing Centre
+ * Helsinki University of Technology
+ * Finland
+ *
+ * Thanks to my friends who helped with ideas and testing:
+ *
+ * Johannes Helander, Antti Louko, Tero Mononen,
+ * jvh@cs.hut.fi alo@hut.fi tmo@cs.hut.fi
+ *
+ * Tero Kivinen and Eamonn McManus
+ * kivinen@cs.hut.fi emcmanus@gr.osf.org
+ *
+ */
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <servers/netname.h>
+#include <servers/machid.h>
+#include <mach/message.h>
+#include <mach/notify.h>
+#include <mach_error.h>
+#include <mach/exception.h>
+#include <mach/vm_attributes.h>
+
+#include "defs.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "value.h"
+#include "language.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+
+#if 0
+#include <servers/machid_lib.h>
+#else
+#define MACH_TYPE_TASK 1
+#define MACH_TYPE_THREAD 2
+#endif
+
+/* Included only for signal names and NSIG
+ *
+ * note: There are many problems in signal handling with
+ * gdb in Mach 3.0 in general.
+ */
+#include <signal.h>
+#define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
+
+#include <cthreads.h>
+
+/* This is what a cproc looks like. This is here partly because
+ cthread_internals.h is not a header we can just #include, partly with
+ an eye towards perhaps getting this to work with cross-debugging
+ someday. Best solution is if CMU publishes a real interface to this
+ stuff. */
+#define CPROC_NEXT_OFFSET 0
+#define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
+#define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
+#define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
+#define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
+#define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
+#define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
+#define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
+#define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
+#define CPROC_REPLY_SIZE (sizeof (mach_port_t))
+#define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
+#define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
+#define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
+#define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
+#define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
+#define CPROC_WIRED_SIZE (sizeof (mach_port_t))
+#define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
+#define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
+#define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
+#define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
+#define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
+#define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
+#define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
+
+/* Values for the state field in the cproc. */
+#define CPROC_RUNNING 0
+#define CPROC_SWITCHING 1
+#define CPROC_BLOCKED 2
+#define CPROC_CONDWAIT 4
+
+/* For cproc and kernel thread mapping */
+typedef struct gdb_thread {
+ mach_port_t name;
+ CORE_ADDR sp;
+ CORE_ADDR pc;
+ CORE_ADDR fp;
+ boolean_t in_emulator;
+ int slotid;
+
+ /* This is for the mthreads list. It points to the cproc list.
+ Perhaps the two lists should be merged (or perhaps it was a mistake
+ to make them both use a struct gdb_thread). */
+ struct gdb_thread *cproc;
+
+ /* These are for the cproc list, which is linked through the next field
+ of the struct gdb_thread. */
+ char raw_cproc[CPROC_SIZE];
+ /* The cthread which is pointed to by the incarnation field from the
+ cproc. This points to the copy we've read into GDB. */
+ cthread_t cthread;
+ /* Point back to the mthreads list. */
+ int reverse_map;
+ struct gdb_thread *next;
+} *gdb_thread_t;
+
+/*
+ * Actions for Mach exceptions.
+ *
+ * sigmap field maps the exception to corresponding Unix signal.
+ *
+ * I do not know how to map the exception to unix signal
+ * if SIG_UNKNOWN is specified.
+ */
+
+struct exception_list {
+ char *name;
+ boolean_t forward;
+ boolean_t print;
+ int sigmap;
+} exception_map[] = {
+ {"not_mach3_exception", FALSE, TRUE, SIG_UNKNOWN},
+ {"EXC_BAD_ACCESS", FALSE, TRUE, SIGSEGV},
+ {"EXC_BAD_INSTRUCTION", FALSE, TRUE, SIGILL},
+ {"EXC_ARITHMETIC", FALSE, TRUE, SIGFPE},
+ {"EXC_EMULATION", FALSE, TRUE, SIGEMT}, /* ??? */
+ {"EXC_SOFTWARE", FALSE, TRUE, SIG_UNKNOWN},
+ {"EXC_BREAKPOINT", FALSE, FALSE, SIGTRAP}
+};
+
+/* Mach exception table size */
+int max_exception = sizeof(exception_map)/sizeof(struct exception_list) - 1;
+
+#define MAX_EXCEPTION max_exception
+
+WAITTYPE wait_status;
+
+/* If you define this, intercepted bsd server calls will be
+ * dumped while waiting the inferior to EXEC the correct
+ * program
+ */
+/* #define DUMP_SYSCALL /* debugging interceptor */
+
+/* xx_debug() outputs messages if this is nonzero.
+ * If > 1, DUMP_SYSCALL will dump message contents.
+ */
+int debug_level = 0;
+
+/* "Temporary" debug stuff */
+void
+xx_debug (fmt, a,b,c)
+char *fmt;
+int a,b,c;
+{
+ if (debug_level)
+ warning (fmt, a, b, c);
+}
+
+/* This is in libmach.a */
+extern mach_port_t name_server_port;
+
+/* Set in catch_exception_raise */
+int stop_exception, stop_code, stop_subcode;
+int stopped_in_exception;
+
+/* Thread that was the active thread when we stopped */
+thread_t stop_thread = MACH_PORT_NULL;
+
+char *hostname = "";
+
+/* Set when task is attached or created */
+boolean_t emulator_present = FALSE;
+
+task_t inferior_task;
+thread_t current_thread;
+
+/* Exception ports for inferior task */
+mach_port_t inferior_exception_port = MACH_PORT_NULL;
+mach_port_t inferior_old_exception_port = MACH_PORT_NULL;
+
+/* task exceptions and notifications */
+mach_port_t inferior_wait_port_set = MACH_PORT_NULL;
+mach_port_t our_notify_port = MACH_PORT_NULL;
+
+/* This is "inferior_wait_port_set" when not single stepping, and
+ * "singlestepped_thread_port" when we are single stepping.
+ *
+ * This is protected by a cleanup function: discard_single_step()
+ */
+mach_port_t currently_waiting_for = MACH_PORT_NULL;
+
+/* A port for external messages to gdb.
+ * External in the meaning that they do not come
+ * from the inferior_task, but rather from external
+ * tasks.
+ *
+ * As a debugging feature:
+ * A debugger debugging another debugger can stop the
+ * inferior debugger by the following command sequence
+ * (without running external programs)
+ *
+ * (top-gdb) set stop_inferior_gdb ()
+ * (top-gdb) continue
+ */
+mach_port_t our_message_port = MACH_PORT_NULL;
+
+/* For single stepping */
+mach_port_t thread_exception_port = MACH_PORT_NULL;
+mach_port_t thread_saved_exception_port = MACH_PORT_NULL;
+mach_port_t singlestepped_thread_port = MACH_PORT_NULL;
+
+/* For machid calls */
+mach_port_t mid_server = MACH_PORT_NULL;
+mach_port_t mid_auth = MACH_PORT_NULL;
+
+/* If gdb thinks the inferior task is not suspended, it
+ * must take suspend/abort the threads when it reads the state.
+ */
+int must_suspend_thread = 0;
+
+/* When single stepping, we switch the port that mach_really_wait() listens to.
+ * This cleanup is a guard to prevent the port set from being left to
+ * the singlestepped_thread_port when error() is called.
+ * This is nonzero only when we are single stepping.
+ */
+#define NULL_CLEANUP (struct cleanup *)0
+struct cleanup *cleanup_step = NULL_CLEANUP;
+
+
+extern struct target_ops m3_ops;
+static void m3_kill_inferior ();
+
+#if 0
+#define MACH_TYPE_EXCEPTION_PORT -1
+#endif
+
+/* Chain of ports to remember requested notifications. */
+
+struct port_chain {
+ struct port_chain *next;
+ mach_port_t port;
+ int type;
+ int mid; /* Now only valid with MACH_TYPE_THREAD and */
+ /* MACH_TYPE_THREAD */
+};
+typedef struct port_chain *port_chain_t;
+
+/* Room for chain nodes comes from pchain_obstack */
+struct obstack pchain_obstack;
+struct obstack *port_chain_obstack = &pchain_obstack;
+
+/* For thread handling */
+struct obstack Cproc_obstack;
+struct obstack *cproc_obstack = &Cproc_obstack;
+
+/* the list of notified ports */
+port_chain_t notify_chain = (port_chain_t) NULL;
+
+port_chain_t
+port_chain_insert (list, name, type)
+ port_chain_t list;
+ mach_port_t name;
+ int type;
+{
+ kern_return_t ret;
+ port_chain_t new;
+ int mid;
+
+ if (! MACH_PORT_VALID (name))
+ return list;
+
+ if (type == MACH_TYPE_TASK || type == MACH_TYPE_THREAD)
+ {
+ if (! MACH_PORT_VALID (mid_server))
+ {
+ warning ("Machid server port invalid, can not map port 0x%x to MID",
+ name);
+ mid = name;
+ }
+ else
+ {
+ ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not map name (0x%x) to MID with machid", name);
+ mid = name;
+ }
+ }
+ }
+ else
+ abort ();
+
+ new = (port_chain_t) obstack_alloc (port_chain_obstack,
+ sizeof (struct port_chain));
+ new->next = list;
+ new->port = name;
+ new->type = type;
+ new->mid = mid;
+
+ return new;
+}
+
+port_chain_t
+port_chain_delete (list, elem)
+ port_chain_t list;
+ mach_port_t elem;
+{
+ if (list)
+ if (list->port == elem)
+ list = list->next;
+ else
+ while (list->next)
+ {
+ if (list->next->port == elem)
+ list->next = list->next->next; /* GCd with obstack_free() */
+ else
+ list = list->next;
+ }
+ return list;
+}
+
+void
+port_chain_destroy (ostack)
+ struct obstack *ostack;
+{
+ obstack_free (ostack, 0);
+ obstack_init (ostack);
+}
+
+port_chain_t
+port_chain_member (list, elem)
+ port_chain_t list;
+ mach_port_t elem;
+{
+ while (list)
+ {
+ if (list->port == elem)
+ return list;
+ list = list->next;
+ }
+ return (port_chain_t) NULL;
+}
+
+int
+map_port_name_to_mid (name, type)
+mach_port_t name;
+int type;
+{
+ port_chain_t elem;
+
+ if (!MACH_PORT_VALID (name))
+ return -1;
+
+ elem = port_chain_member (notify_chain, name);
+
+ if (elem && (elem->type == type))
+ return elem->mid;
+
+ if (elem)
+ return -1;
+
+ if (! MACH_PORT_VALID (mid_server))
+ {
+ warning ("Machid server port invalid, can not map port 0x%x to mid",
+ name);
+ return -1;
+ }
+ else
+ {
+ int mid;
+ kern_return_t ret;
+
+ ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not map name (0x%x) to mid with machid", name);
+ return -1;
+ }
+ return mid;
+ }
+}
+
+/* Guard for currently_waiting_for and singlestepped_thread_port */
+static void
+discard_single_step (thread)
+ thread_t thread;
+{
+ currently_waiting_for = inferior_wait_port_set;
+
+ cleanup_step = NULL_CLEANUP;
+ if (MACH_PORT_VALID (thread) && MACH_PORT_VALID (singlestepped_thread_port))
+ setup_single_step (thread, FALSE);
+}
+
+setup_single_step (thread, start_step)
+ thread_t thread;
+ boolean_t start_step;
+{
+ kern_return_t ret;
+
+ if (! MACH_PORT_VALID (thread))
+ error ("Invalid thread supplied to setup_single_step");
+ else
+ {
+ mach_port_t teport;
+
+ /* Get the current thread exception port */
+ ret = thread_get_exception_port (thread, &teport);
+ CHK ("Getting thread's exception port", ret);
+
+ if (start_step)
+ {
+ if (MACH_PORT_VALID (singlestepped_thread_port))
+ {
+ warning ("Singlestepped_thread_port (0x%x) is still valid?",
+ singlestepped_thread_port);
+ singlestepped_thread_port = MACH_PORT_NULL;
+ }
+
+ /* If we are already stepping this thread */
+ if (MACH_PORT_VALID (teport) && teport == thread_exception_port)
+ {
+ ret = mach_port_deallocate (mach_task_self (), teport);
+ CHK ("Could not deallocate thread exception port", ret);
+ }
+ else
+ {
+ ret = thread_set_exception_port (thread, thread_exception_port);
+ CHK ("Setting exception port for thread", ret);
+#if 0
+ /* Insert thread exception port to wait port set */
+ ret = mach_port_move_member (mach_task_self(),
+ thread_exception_port,
+ inferior_wait_port_set);
+ CHK ("Moving thread exception port to inferior_wait_port_set",
+ ret);
+#endif
+ thread_saved_exception_port = teport;
+ }
+
+ thread_trace (thread, TRUE);
+
+ singlestepped_thread_port = thread_exception_port;
+ currently_waiting_for = singlestepped_thread_port;
+ cleanup_step = make_cleanup (discard_single_step, thread);
+ }
+ else
+ {
+ if (! MACH_PORT_VALID (teport))
+ error ("Single stepped thread had an invalid exception port?");
+
+ if (teport != thread_exception_port)
+ error ("Single stepped thread had an unknown exception port?");
+
+ ret = mach_port_deallocate (mach_task_self (), teport);
+ CHK ("Couldn't deallocate thread exception port", ret);
+#if 0
+ /* Remove thread exception port from wait port set */
+ ret = mach_port_move_member (mach_task_self(),
+ thread_exception_port,
+ MACH_PORT_NULL);
+ CHK ("Removing thread exception port from inferior_wait_port_set",
+ ret);
+#endif
+ /* Restore thread's old exception port */
+ ret = thread_set_exception_port (thread,
+ thread_saved_exception_port);
+ CHK ("Restoring stepped thread's exception port", ret);
+
+ if (MACH_PORT_VALID (thread_saved_exception_port))
+ (void) mach_port_deallocate (mach_task_self (),
+ thread_saved_exception_port);
+
+ thread_trace (thread, FALSE);
+
+ singlestepped_thread_port = MACH_PORT_NULL;
+ currently_waiting_for = inferior_wait_port_set;
+ if (cleanup_step)
+ discard_cleanups (cleanup_step);
+ }
+ }
+}
+
+static
+request_notify (name, variant, type)
+ mach_port_t name;
+ mach_msg_id_t variant;
+ int type;
+{
+ kern_return_t ret;
+ mach_port_t previous_port_dummy = MACH_PORT_NULL;
+
+ if (! MACH_PORT_VALID (name))
+ return;
+
+ if (port_chain_member (notify_chain, name))
+ return;
+
+ ret = mach_port_request_notification (mach_task_self(),
+ name,
+ variant,
+ 1,
+ our_notify_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &previous_port_dummy);
+ CHK ("Serious: request_notify failed", ret);
+
+ (void) mach_port_deallocate (mach_task_self (),
+ previous_port_dummy);
+
+ notify_chain = port_chain_insert (notify_chain, name, type);
+}
+
+reverse_msg_bits(msgp, type)
+ mach_msg_header_t *msgp;
+ int type;
+{
+ int rbits,lbits;
+ rbits = MACH_MSGH_BITS_REMOTE(msgp->msgh_bits);
+ lbits = type;
+ msgp->msgh_bits =
+ (msgp->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
+ MACH_MSGH_BITS(lbits,rbits);
+}
+
+/* On the third day He said:
+
+ Let this be global
+ and then it was global.
+
+ When creating the inferior fork, the
+ child code in inflow.c sets the name of the
+ bootstrap_port in its address space to this
+ variable.
+
+ The name is transferred to our address space
+ with mach3_read_inferior().
+
+ Thou shalt not do this with
+ task_get_bootstrap_port() in this task, since
+ the name in the inferior task is different than
+ the one we get.
+
+ For blessed are the meek, as they shall inherit
+ the address space.
+ */
+mach_port_t original_server_port_name = MACH_PORT_NULL;
+
+
+/* Called from inferior after FORK but before EXEC */
+static void
+m3_trace_me ()
+{
+ kern_return_t ret;
+
+ /* Get the NAME of the bootstrap port in this task
+ so that GDB can read it */
+ ret = task_get_bootstrap_port (mach_task_self (),
+ &original_server_port_name);
+ if (ret != KERN_SUCCESS)
+ abort ();
+ ret = mach_port_deallocate (mach_task_self (),
+ original_server_port_name);
+ if (ret != KERN_SUCCESS)
+ abort ();
+
+ /* Suspend this task to let the parent change my ports.
+ Resumed by the debugger */
+ ret = task_suspend (mach_task_self ());
+ if (ret != KERN_SUCCESS)
+ abort ();
+}
+
+/*
+ * Intercept system calls to Unix server.
+ * After EXEC_COUNTER calls to exec(), return.
+ *
+ * Pre-assertion: Child is suspended. (Not verified)
+ * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
+ */
+
+void
+intercept_exec_calls (exec_counter)
+ int exec_counter;
+{
+ int terminal_initted = 0;
+
+ struct syscall_msg_t {
+ mach_msg_header_t header;
+ mach_msg_type_t type;
+ char room[ 2000 ]; /* Enuff space */
+ };
+
+ struct syscall_msg_t syscall_in, syscall_out;
+
+ mach_port_t fake_server;
+ mach_port_t original_server_send;
+ mach_port_t original_exec_reply;
+ mach_port_t exec_reply;
+ mach_port_t exec_reply_send;
+ mach_msg_type_name_t acquired;
+ mach_port_t emulator_server_port_name;
+ struct task_basic_info info;
+ mach_msg_type_number_t info_count;
+
+ kern_return_t ret;
+
+ if (exec_counter <= 0)
+ return; /* We are already set up in the correct program */
+
+ ret = mach_port_allocate(mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &fake_server);
+ CHK("create inferior_fake_server port failed", ret);
+
+ /* Wait for inferior_task to suspend itself */
+ while(1)
+ {
+ info_count = sizeof (info);
+ ret = task_info (inferior_task,
+ TASK_BASIC_INFO,
+ (task_info_t)&info,
+ &info_count);
+ CHK ("Task info", ret);
+
+ if (info.suspend_count)
+ break;
+
+ /* Note that the definition of the parameter was undefined
+ * at the time of this writing, so I just use an `ad hoc' value.
+ */
+ (void) swtch_pri (42); /* Universal Priority Value */
+ }
+
+ /* Read the inferior's bootstrap port name */
+ if (!mach3_read_inferior (&original_server_port_name,
+ &original_server_port_name,
+ sizeof (original_server_port_name)))
+ error ("Can't read inferior task bootstrap port name");
+
+ /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
+ /* Should get refs, and set them back when restoring */
+ /* Steal the original bsd server send right from inferior */
+ ret = mach_port_extract_right (inferior_task,
+ original_server_port_name,
+ MACH_MSG_TYPE_MOVE_SEND,
+ &original_server_send,
+ &acquired);
+ CHK("mach_port_extract_right (bsd server send)",ret);
+
+ if (acquired != MACH_MSG_TYPE_PORT_SEND)
+ error("Incorrect right extracted, send right to bsd server excpected");
+
+ ret = mach_port_insert_right (inferior_task,
+ original_server_port_name,
+ fake_server,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK("mach_port_insert_right (fake server send)",ret);
+
+ xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
+ fake_server,
+ original_server_port_name, original_server_send);
+
+ /* A receive right to the reply generated by unix server exec() request */
+ ret = mach_port_allocate(mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &exec_reply);
+ CHK("create intercepted_reply_port port failed", ret);
+
+ /* Pass this send right to Unix server so it replies to us after exec() */
+ ret = mach_port_extract_right (mach_task_self (),
+ exec_reply,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &exec_reply_send,
+ &acquired);
+ CHK("mach_port_extract_right (exec_reply)",ret);
+
+ if (acquired != MACH_MSG_TYPE_PORT_SEND_ONCE)
+ error("Incorrect right extracted, send once excpected for exec reply");
+
+ ret = mach_port_move_member(mach_task_self(),
+ fake_server,
+ inferior_wait_port_set);
+ CHK ("Moving fake syscall port to inferior_wait_port_set", ret);
+
+ xx_debug ("syscall fake server set up, resuming inferior\n");
+
+ ret = task_resume (inferior_task);
+ CHK("task_resume (startup)", ret);
+
+ /* Read requests from the inferior.
+ Pass directly through everything else except exec() calls.
+ */
+ while(exec_counter > 0)
+ {
+ ret = mach_msg (&syscall_in.header, /* header */
+ MACH_RCV_MSG, /* options */
+ 0, /* send size */
+ sizeof (struct syscall_msg_t), /* receive size */
+ inferior_wait_port_set, /* receive_name */
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ CHK("mach_msg (intercepted sycall)", ret);
+
+#ifdef DUMP_SYSCALL
+ print_msg (&syscall_in.header);
+#endif
+
+ /* ASSERT : msgh_local_port == fake_server */
+
+ if (notify_server (&syscall_in.header, &syscall_out.header))
+ error ("received a notify while intercepting syscalls");
+
+ if (syscall_in.header.msgh_id == MIG_EXEC_SYSCALL_ID)
+ {
+ xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter);
+ if (exec_counter == 1)
+ {
+ original_exec_reply = syscall_in.header.msgh_remote_port;
+ syscall_in.header.msgh_remote_port = exec_reply_send;
+ }
+
+ if (!terminal_initted)
+ {
+ /* Now that the child has exec'd we know it has already set its
+ process group. On POSIX systems, tcsetpgrp will fail with
+ EPERM if we try it before the child's setpgid. */
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ terminal_initted = 1;
+ }
+
+ exec_counter--;
+ }
+
+ syscall_in.header.msgh_local_port = syscall_in.header.msgh_remote_port;
+ syscall_in.header.msgh_remote_port = original_server_send;
+
+ reverse_msg_bits(&syscall_in.header, MACH_MSG_TYPE_COPY_SEND);
+
+ ret = mach_msg_send (&syscall_in.header);
+ CHK ("Forwarded syscall", ret);
+ }
+
+ ret = mach_port_move_member(mach_task_self(),
+ fake_server,
+ MACH_PORT_NULL);
+ CHK ("Moving fake syscall out of inferior_wait_port_set", ret);
+
+ ret = mach_port_move_member(mach_task_self(),
+ exec_reply,
+ inferior_wait_port_set);
+ CHK ("Moving exec_reply to inferior_wait_port_set", ret);
+
+ ret = mach_msg (&syscall_in.header, /* header */
+ MACH_RCV_MSG, /* options */
+ 0, /* send size */
+ sizeof (struct syscall_msg_t), /* receive size */
+ inferior_wait_port_set, /* receive_name */
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ CHK("mach_msg (exec reply)", ret);
+
+ ret = task_suspend (inferior_task);
+ CHK ("Suspending inferior after last exec", ret);
+
+ must_suspend_thread = 0;
+
+ xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
+
+#ifdef DUMP_SYSCALL
+ print_msg (&syscall_in.header);
+#endif
+
+ /* Message should appear as if it came from the unix server */
+ syscall_in.header.msgh_local_port = MACH_PORT_NULL;
+
+ /* and go to the inferior task original reply port */
+ syscall_in.header.msgh_remote_port = original_exec_reply;
+
+ reverse_msg_bits(&syscall_in.header, MACH_MSG_TYPE_MOVE_SEND_ONCE);
+
+ ret = mach_msg_send (&syscall_in.header);
+ CHK ("Forwarding exec reply to inferior", ret);
+
+ /* Garbage collect */
+ ret = mach_port_deallocate (inferior_task,
+ original_server_port_name);
+ CHK ("deallocating fake server send right", ret);
+
+ ret = mach_port_insert_right (inferior_task,
+ original_server_port_name,
+ original_server_send,
+ MACH_MSG_TYPE_MOVE_SEND);
+ CHK ("Restoring the original bsd server send right", ret);
+
+ ret = mach_port_destroy (mach_task_self (),
+ fake_server);
+ fake_server = MACH_PORT_DEAD;
+ CHK("mach_port_destroy (fake_server)", ret);
+
+ ret = mach_port_destroy (mach_task_self (),
+ exec_reply);
+ exec_reply = MACH_PORT_DEAD;
+ CHK("mach_port_destroy (exec_reply)", ret);
+
+ xx_debug ("Done with exec call interception\n");
+}
+
+void
+consume_send_rights (thread_list, thread_count)
+ thread_array_t thread_list;
+ int thread_count;
+{
+ int index;
+
+ if (!thread_count)
+ return;
+
+ for (index = 0; index < thread_count; index++)
+ {
+ /* Since thread kill command kills threads, don't check ret */
+ (void) mach_port_deallocate (mach_task_self (),
+ thread_list [ index ]);
+ }
+}
+
+/* suspend/abort/resume a thread. */
+setup_thread (thread, what)
+ mach_port_t thread;
+ int what;
+{
+ kern_return_t ret;
+
+ if (what)
+ {
+ ret = thread_suspend (thread);
+ CHK ("setup_thread thread_suspend", ret);
+
+ ret = thread_abort (thread);
+ CHK ("setup_thread thread_abort", ret);
+ }
+ else
+ {
+ ret = thread_resume (thread);
+ CHK ("setup_thread thread_resume", ret);
+ }
+}
+
+int
+map_slot_to_mid (slot, threads, thread_count)
+ int slot;
+ thread_array_t threads;
+ int thread_count;
+{
+ kern_return_t ret;
+ int deallocate = 0;
+ int index;
+ int mid;
+
+ if (! threads)
+ {
+ deallocate++;
+ ret = task_threads (inferior_task, &threads, &thread_count);
+ CHK ("Can not select a thread from a dead task", ret);
+ }
+
+ if (slot < 0 || slot >= thread_count)
+ {
+ if (deallocate)
+ {
+ consume_send_rights (threads, thread_count);
+ (void) vm_deallocate (mach_task_self(), (vm_address_t)threads,
+ (thread_count * sizeof(mach_port_t)));
+ }
+ if (slot < 0)
+ error ("invalid slot number");
+ else
+ return -(slot+1);
+ }
+
+ mid = map_port_name_to_mid (threads [slot], MACH_TYPE_THREAD);
+
+ if (deallocate)
+ {
+ consume_send_rights (threads, thread_count);
+ (void) vm_deallocate (mach_task_self(), (vm_address_t)threads,
+ (thread_count * sizeof(mach_port_t)));
+ }
+
+ return mid;
+}
+
+static int
+parse_thread_id (arg, thread_count, slots)
+ char *arg;
+ int thread_count;
+ int slots;
+{
+ kern_return_t ret;
+ int mid;
+ int slot;
+ int index;
+
+ if (arg == 0)
+ return 0;
+
+ while (*arg && (*arg == ' ' || *arg == '\t'))
+ arg++;
+
+ if (! *arg)
+ return 0;
+
+ /* Currently parse MID and @SLOTNUMBER */
+ if (*arg != '@')
+ {
+ mid = atoi (arg);
+ if (mid <= 0)
+ error ("valid thread mid expected");
+ return mid;
+ }
+
+ arg++;
+ slot = atoi (arg);
+
+ if (slot < 0)
+ error ("invalid slot number");
+
+ /* If you want slot numbers to remain slot numbers, set slots.
+ *
+ * Well, since 0 is reserved, return the ordinal number
+ * of the thread rather than the slot number. Awk, this
+ * counts as a kludge.
+ */
+ if (slots)
+ return -(slot+1);
+
+ if (thread_count && slot >= thread_count)
+ return -(slot+1);
+
+ mid = map_slot_to_mid (slot);
+
+ return mid;
+}
+
+/* THREAD_ID 0 is special; it selects the first kernel
+ * thread from the list (i.e. SLOTNUMBER 0)
+ * This is used when starting the program with 'run' or when attaching.
+ *
+ * If FLAG is 0 the context is not changed, and the registers, frame, etc
+ * will continue to describe the old thread.
+ *
+ * If FLAG is nonzero, really select the thread.
+ * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
+ *
+ */
+kern_return_t
+select_thread (task, thread_id, flag)
+ mach_port_t task;
+ int thread_id;
+ int flag;
+{
+ thread_array_t thread_list;
+ int thread_count;
+ kern_return_t ret;
+ int index;
+ thread_t new_thread = MACH_PORT_NULL;
+
+ if (thread_id < 0)
+ error ("Can't select cprocs without kernel thread");
+
+ ret = task_threads (task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Can not select a thread from a dead task");
+ m3_kill_inferior ();
+ return KERN_FAILURE;
+ }
+
+ if (thread_count == 0)
+ {
+ /* The task can not do anything anymore, but it still
+ * exists as a container for memory and ports.
+ */
+ registers_changed ();
+ warning ("Task %d has no threads",
+ map_port_name_to_mid (task, MACH_TYPE_TASK));
+ current_thread = MACH_PORT_NULL;
+ (void) vm_deallocate(mach_task_self(),
+ (vm_address_t) thread_list,
+ (thread_count * sizeof(mach_port_t)));
+ return KERN_FAILURE;
+ }
+
+ if (! thread_id || flag == 2)
+ {
+ /* First thread or a slotnumber */
+ if (! thread_id)
+ new_thread = thread_list[0];
+ else
+ {
+ if (thread_id < thread_count)
+ new_thread = thread_list[ thread_id ];
+ else
+ {
+ (void) vm_deallocate(mach_task_self(),
+ (vm_address_t) thread_list,
+ (thread_count * sizeof(mach_port_t)));
+ error ("No such thread slot number : %d", thread_id);
+ }
+ }
+ }
+ else
+ {
+ for (index = 0; index < thread_count; index++)
+ if (thread_id == map_port_name_to_mid (thread_list [index],
+ MACH_TYPE_THREAD))
+ {
+ new_thread = thread_list [index];
+ index = -1;
+ break;
+ }
+
+ if (index != -1)
+ error ("No thread with mid %d", thread_id);
+ }
+
+ /* Notify when the selected thread dies */
+ request_notify (new_thread, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_THREAD);
+
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t) thread_list,
+ (thread_count * sizeof(mach_port_t)));
+ CHK ("vm_deallocate", ret);
+
+ if (! flag)
+ current_thread = new_thread;
+ else
+ {
+#if 0
+ if (MACH_PORT_VALID (current_thread))
+ {
+ /* Store the gdb's view of the thread we are deselecting
+ *
+ * @@ I think gdb updates registers immediately when they are
+ * changed, so don't do this.
+ */
+ ret = thread_abort (current_thread);
+ CHK ("Could not abort system calls when saving state of old thread",
+ ret);
+ target_prepare_to_store ();
+ target_store_registers (-1);
+ }
+#endif
+
+ registers_changed ();
+
+ current_thread = new_thread;
+
+ ret = thread_abort (current_thread);
+ CHK ("Could not abort system calls when selecting a thread", ret);
+
+ stop_pc = read_pc();
+ flush_cached_frames ();
+
+ select_frame (get_current_frame (), 0);
+ }
+
+ return KERN_SUCCESS;
+}
+
+/*
+ * Switch to use thread named NEW_THREAD.
+ * Return it's MID
+ */
+int
+switch_to_thread (new_thread)
+ thread_t new_thread;
+{
+ thread_t saved_thread = current_thread;
+ int mid;
+
+ mid = map_port_name_to_mid (new_thread,
+ MACH_TYPE_THREAD);
+ if (mid == -1)
+ warning ("Can't map thread name 0x%x to mid", new_thread);
+ else if (select_thread (inferior_task, mid, 1) != KERN_SUCCESS)
+ {
+ if (current_thread)
+ current_thread = saved_thread;
+ error ("Could not select thread %d", mid);
+ }
+
+ return mid;
+}
+
+/* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
+ * Note that the registers are not yet valid in the inferior task.
+ */
+static void
+m3_trace_him (pid)
+ int pid;
+{
+ kern_return_t ret;
+
+ push_target (&m3_ops);
+
+ inferior_task = task_by_pid (pid);
+
+ if (! MACH_PORT_VALID (inferior_task))
+ error ("Can not map Unix pid %d to Mach task", pid);
+
+ /* Clean up previous notifications and create new ones */
+ setup_notify_port (1);
+
+ /* When notification appears, the inferior task has died */
+ request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
+
+ emulator_present = have_emulator_p (inferior_task);
+
+ /* By default, select the first thread,
+ * If task has no threads, gives a warning
+ * Does not fetch registers, since they are not yet valid.
+ */
+ select_thread (inferior_task, 0, 0);
+
+ inferior_exception_port = MACH_PORT_NULL;
+
+ setup_exception_port ();
+
+ xx_debug ("Now the debugged task is created\n");
+
+ /* One trap to exec the shell, one to exec the program being debugged. */
+ intercept_exec_calls (2);
+}
+
+setup_exception_port ()
+{
+ kern_return_t ret;
+
+ ret = mach_port_allocate (mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &inferior_exception_port);
+ CHK("mach_port_allocate",ret);
+
+ /* add send right */
+ ret = mach_port_insert_right (mach_task_self (),
+ inferior_exception_port,
+ inferior_exception_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK("mach_port_insert_right",ret);
+
+ ret = mach_port_move_member (mach_task_self(),
+ inferior_exception_port,
+ inferior_wait_port_set);
+ CHK("mach_port_move_member",ret);
+
+ ret = task_get_special_port (inferior_task,
+ TASK_EXCEPTION_PORT,
+ &inferior_old_exception_port);
+ CHK ("task_get_special_port(old exc)",ret);
+
+ ret = task_set_special_port (inferior_task,
+ TASK_EXCEPTION_PORT,
+ inferior_exception_port);
+ CHK("task_set_special_port",ret);
+
+ ret = mach_port_deallocate (mach_task_self (),
+ inferior_exception_port);
+ CHK("mack_port_deallocate",ret);
+
+#if 0
+ /* When notify appears, the inferior_task's exception
+ * port has been destroyed.
+ *
+ * Not used, since the dead_name_notification already
+ * appears when task dies.
+ *
+ */
+ request_notify (inferior_exception_port,
+ MACH_NOTIFY_NO_SENDERS,
+ MACH_TYPE_EXCEPTION_PORT);
+#endif
+}
+
+/* Nonzero if gdb is waiting for a message */
+int mach_really_waiting;
+
+/* Wait for the inferior to stop for some reason.
+ - Loop on notifications until inferior_task dies.
+ - Loop on exceptions until stopped_in_exception comes true.
+ (e.g. we receive a single step trace trap)
+ - a message arrives to gdb's message port
+
+ There is no other way to exit this loop.
+
+ Returns the inferior_pid for rest of gdb.
+ Side effects: Set *OURSTATUS. */
+int
+mach_really_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ kern_return_t ret;
+ int w;
+
+ struct msg {
+ mach_msg_header_t header;
+ mach_msg_type_t foo;
+ int data[8000];
+ } in_msg, out_msg;
+
+ /* Either notify (death), exception or message can stop the inferior */
+ stopped_in_exception = FALSE;
+
+ while (1)
+ {
+ QUIT;
+
+ stop_exception = stop_code = stop_subcode = -1;
+ stop_thread = MACH_PORT_NULL;
+
+ mach_really_waiting = 1;
+ ret = mach_msg (&in_msg.header, /* header */
+ MACH_RCV_MSG, /* options */
+ 0, /* send size */
+ sizeof (struct msg), /* receive size */
+ currently_waiting_for, /* receive name */
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ mach_really_waiting = 0;
+ CHK("mach_msg (receive)", ret);
+
+ /* Check if we received a notify of the childs' death */
+ if (notify_server (&in_msg.header, &out_msg.header))
+ {
+ /* If inferior_task is null then the inferior has
+ gone away and we want to return to command level.
+ Otherwise it was just an informative message and we
+ need to look to see if there are any more. */
+ if (inferior_task != MACH_PORT_NULL)
+ continue;
+ else
+ {
+ /* Collect Unix exit status for gdb */
+
+ wait3(&w, WNOHANG, 0);
+
+ /* This mess is here to check that the rest of
+ * gdb knows that the inferior died. It also
+ * tries to hack around the fact that Mach 3.0 (mk69)
+ * unix server (ux28) does not always know what
+ * has happened to it's children when mach-magic
+ * is applied on them.
+ */
+ if ((!WIFEXITED(w) && WIFSTOPPED(w)) ||
+ (WIFEXITED(w) && WEXITSTATUS(w) > 0377))
+ {
+ WSETEXIT(w, 0);
+ warning ("Using exit value 0 for terminated task");
+ }
+ else if (!WIFEXITED(w))
+ {
+ int sig = WTERMSIG(w);
+
+ /* Signals cause problems. Warn the user. */
+ if (sig != SIGKILL) /* Bad luck if garbage matches this */
+ warning ("The terminating signal stuff may be nonsense");
+ else if (sig > NSIG)
+ {
+ WSETEXIT(w, 0);
+ warning ("Using exit value 0 for terminated task");
+ }
+ }
+ store_waitstatus (ourstatus, w);
+ return inferior_pid;
+ }
+ }
+
+ /* Hmm. Check for exception, as it was not a notification.
+ exc_server() does an upcall to catch_exception_raise()
+ if this rpc is an exception. Further actions are decided
+ there.
+ */
+ if (! exc_server (&in_msg.header, &out_msg.header))
+ {
+
+ /* Not an exception, check for message.
+ *
+ * Messages don't come from the inferior, or if they
+ * do they better be asynchronous or it will hang.
+ */
+ if (gdb_message_server (&in_msg.header))
+ continue;
+
+ error ("Unrecognized message received in mach_really_wait");
+ }
+
+ /* Send the reply of the exception rpc to the suspended task */
+ ret = mach_msg_send (&out_msg.header);
+ CHK ("mach_msg_send (exc reply)", ret);
+
+ if (stopped_in_exception)
+ {
+ /* Get unix state. May be changed in mach3_exception_actions() */
+ wait3(&w, WNOHANG, 0);
+
+ mach3_exception_actions (&w, FALSE, "Task");
+
+ store_waitstatus (ourstatus, w);
+ return inferior_pid;
+ }
+ }
+}
+
+/* Called by macro DO_QUIT() in utils.c(quit).
+ * This is called just before calling error() to return to command level
+ */
+void
+mach3_quit ()
+{
+ int mid;
+ kern_return_t ret;
+
+ if (mach_really_waiting)
+ {
+ ret = task_suspend (inferior_task);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Could not suspend task for interrupt: %s",
+ mach_error_string (ret));
+ mach_really_waiting = 0;
+ return;
+ }
+ }
+
+ must_suspend_thread = 0;
+ mach_really_waiting = 0;
+
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+ if (mid == -1)
+ {
+ warning ("Selecting first existing kernel thread");
+ mid = 0;
+ }
+
+ current_thread = MACH_PORT_NULL; /* Force setup */
+ select_thread (inferior_task, mid, 1);
+
+ return;
+}
+
+#if 0
+/* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
+
+/* If ^C is typed when we are waiting for a message
+ * and your Unix server is able to notice that we
+ * should quit now.
+ *
+ * Called by REQUEST_QUIT() from utils.c(request_quit)
+ */
+void
+mach3_request_quit ()
+{
+ if (mach_really_waiting)
+ immediate_quit = 1;
+}
+#endif
+
+/*
+ * Gdb message server.
+ * Currently implemented is the STOP message, that causes
+ * gdb to return to the command level like ^C had been typed from terminal.
+ */
+int
+gdb_message_server (InP)
+ mach_msg_header_t *InP;
+{
+ kern_return_t ret;
+ int mid;
+
+ if (InP->msgh_local_port == our_message_port)
+ {
+ /* A message coming to our_message_port. Check validity */
+ switch (InP->msgh_id) {
+
+ case GDB_MESSAGE_ID_STOP:
+ ret = task_suspend (inferior_task);
+ if (ret != KERN_SUCCESS)
+ warning ("Could not suspend task for stop message: %s",
+ mach_error_string (ret));
+
+ /* QUIT in mach_really_wait() loop. */
+ request_quit (0);
+ break;
+
+ default:
+ warning ("Invalid message id %d received, ignored.",
+ InP->msgh_id);
+ break;
+ }
+
+ return 1;
+ }
+
+ /* Message not handled by this server */
+ return 0;
+}
+
+/* NOTE: This is not an RPC call. It is a simpleroutine.
+ *
+ * This is not called from this gdb code.
+ *
+ * It may be called by another debugger to cause this
+ * debugger to enter command level:
+ *
+ * (gdb) set stop_inferior_gdb ()
+ * (gdb) continue
+ *
+ * External program "stop-gdb" implements this also.
+ */
+void
+stop_inferior_gdb ()
+{
+ kern_return_t ret;
+
+ /* Code generated by mig, with minor cleanups :-)
+ *
+ * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
+ */
+
+ typedef struct {
+ mach_msg_header_t Head;
+ } Request;
+
+ Request Mess;
+
+ register Request *InP = &Mess;
+
+ InP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
+
+ /* msgh_size passed as argument */
+ InP->Head.msgh_remote_port = our_message_port;
+ InP->Head.msgh_local_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = GDB_MESSAGE_ID_STOP;
+
+ ret = mach_msg (&InP->Head,
+ MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
+ sizeof(Request),
+ 0,
+ MACH_PORT_NULL,
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+}
+
+#ifdef THREAD_ALLOWED_TO_BREAK
+/*
+ * Return 1 if the MID specifies the thread that caused the
+ * last exception.
+ * Since catch_exception_raise() selects the thread causing
+ * the last exception to current_thread, we just check that
+ * it is selected and the last exception was a breakpoint.
+ */
+int
+mach_thread_for_breakpoint (mid)
+ int mid;
+{
+ int cmid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+
+ if (mid < 0)
+ {
+ mid = map_slot_to_mid (-(mid+1), 0, 0);
+ if (mid < 0)
+ return 0; /* Don't stop, no such slot */
+ }
+
+ if (! mid || cmid == -1)
+ return 1; /* stop */
+
+ return cmid == mid && stop_exception == EXC_BREAKPOINT;
+}
+#endif /* THREAD_ALLOWED_TO_BREAK */
+
+#ifdef THREAD_PARSE_ID
+/*
+ * Map a thread id string (MID or a @SLOTNUMBER)
+ * to a thread-id.
+ *
+ * 0 matches all threads.
+ * Otherwise the meaning is defined only in this file.
+ * (mach_thread_for_breakpoint uses it)
+ *
+ * @@ This allows non-existent MIDs to be specified.
+ * It now also allows non-existent slots to be
+ * specified. (Slot numbers stored are negative,
+ * and the magnitude is one greater than the actual
+ * slot index. (Since 0 is reserved))
+ */
+int
+mach_thread_parse_id (arg)
+ char *arg;
+{
+ int mid;
+ if (arg == 0)
+ error ("thread id excpected");
+ mid = parse_thread_id (arg, 0, 1);
+
+ return mid;
+}
+#endif /* THREAD_PARSE_ID */
+
+#ifdef THREAD_OUTPUT_ID
+char *
+mach_thread_output_id (mid)
+ int mid;
+{
+ static char foobar [20];
+
+ if (mid > 0)
+ sprintf (foobar, "mid %d", mid);
+ else if (mid < 0)
+ sprintf (foobar, "@%d", -(mid+1));
+ else
+ sprintf (foobar, "*any thread*");
+
+ return foobar;
+}
+#endif /* THREAD_OUTPUT_ID */
+
+/* Called with hook PREPARE_TO_PROCEED() from infrun.c.
+ *
+ * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
+ *
+ * if SELECT_IT is nonzero, reselect the thread that was active when
+ * we stopped at a breakpoint.
+ *
+ */
+
+mach3_prepare_to_proceed (select_it)
+ int select_it;
+{
+ if (stop_thread &&
+ stop_thread != current_thread &&
+ stop_exception == EXC_BREAKPOINT)
+ {
+ int mid;
+
+ if (! select_it)
+ return 1;
+
+ mid = switch_to_thread (stop_thread);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+/* this stuff here is an upcall via libmach/excServer.c
+ and mach_really_wait which does the actual upcall.
+
+ The code will pass the exception to the inferior if:
+
+ - The task that signaled is not the inferior task
+ (e.g. when debugging another debugger)
+
+ - The user has explicitely requested to pass on the exceptions.
+ (e.g to the default unix exception handler, which maps
+ exceptions to signals, or the user has her own exception handler)
+
+ - If the thread that signaled is being single-stepped and it
+ has set it's own exception port and the exception is not
+ EXC_BREAKPOINT. (Maybe this is not desirable?)
+ */
+
+kern_return_t
+catch_exception_raise (port, thread, task, exception, code, subcode)
+ mach_port_t port;
+ thread_t thread;
+ task_t task;
+ int exception, code, subcode;
+{
+ kern_return_t ret;
+ boolean_t signal_thread;
+ int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
+
+ if (! MACH_PORT_VALID (thread))
+ {
+ /* If the exception was sent and thread dies before we
+ receive it, THREAD will be MACH_PORT_DEAD
+ */
+
+ current_thread = thread = MACH_PORT_NULL;
+ error ("Received exception from nonexistent thread");
+ }
+
+ /* Check if the task died in transit.
+ * @@ Isn't the thread also invalid in such case?
+ */
+ if (! MACH_PORT_VALID (task))
+ {
+ current_thread = thread = MACH_PORT_NULL;
+ error ("Received exception from nonexistent task");
+ }
+
+ if (exception < 0 || exception > MAX_EXCEPTION)
+ fatal ("catch_exception_raise: unknown exception code %d thread %d",
+ exception,
+ mid);
+
+ if (! MACH_PORT_VALID (inferior_task))
+ error ("got an exception, but inferior_task is null or dead");
+
+ stop_exception = exception;
+ stop_code = code;
+ stop_subcode = subcode;
+ stop_thread = thread;
+
+ signal_thread = exception != EXC_BREAKPOINT &&
+ port == singlestepped_thread_port &&
+ MACH_PORT_VALID (thread_saved_exception_port);
+
+ /* If it was not our inferior or if we want to forward
+ * the exception to the inferior's handler, do it here
+ *
+ * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
+ */
+ if (task != inferior_task ||
+ signal_thread ||
+ exception_map [exception].forward)
+ {
+ mach_port_t eport = inferior_old_exception_port;
+
+ if (signal_thread)
+ {
+ /*
+ GDB now forwards the exeption to thread's original handler,
+ since the user propably knows what he is doing.
+ Give a message, though.
+ */
+
+ mach3_exception_actions ((WAITTYPE *)NULL, TRUE, "Thread");
+ eport = thread_saved_exception_port;
+ }
+
+ /* Send the exception to the original handler */
+ ret = exception_raise (eport,
+ thread,
+ task,
+ exception,
+ code,
+ subcode);
+
+ (void) mach_port_deallocate (mach_task_self (), task);
+ (void) mach_port_deallocate (mach_task_self (), thread);
+
+ /* If we come here, we don't want to trace any more, since we
+ * will never stop for tracing anyway.
+ */
+ discard_single_step (thread);
+
+ /* Do not stop the inferior */
+ return ret;
+ }
+
+ /* Now gdb handles the exception */
+ stopped_in_exception = TRUE;
+
+ ret = task_suspend (task);
+ CHK ("Error suspending inferior after exception", ret);
+
+ must_suspend_thread = 0;
+
+ if (current_thread != thread)
+ {
+ if (MACH_PORT_VALID (singlestepped_thread_port))
+ /* Cleanup discards single stepping */
+ error ("Exception from thread %d while singlestepping thread %d",
+ mid,
+ map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
+
+ /* Then select the thread that caused the exception */
+ if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
+ error ("Could not select thread %d causing exception", mid);
+ else
+ warning ("Gdb selected thread %d", mid);
+ }
+
+ /* If we receive an exception that is not breakpoint
+ * exception, we interrupt the single step and return to
+ * debugger. Trace condition is cleared.
+ */
+ if (MACH_PORT_VALID (singlestepped_thread_port))
+ {
+ if (stop_exception != EXC_BREAKPOINT)
+ warning ("Single step interrupted by exception");
+ else if (port == singlestepped_thread_port)
+ {
+ /* Single step exception occurred, remove trace bit
+ * and return to gdb.
+ */
+ if (! MACH_PORT_VALID (current_thread))
+ error ("Single stepped thread is not valid");
+
+ /* Resume threads, but leave the task suspended */
+ resume_all_threads (0);
+ }
+ else
+ warning ("Breakpoint while single stepping?");
+
+ discard_single_step (current_thread);
+ }
+
+ (void) mach_port_deallocate (mach_task_self (), task);
+ (void) mach_port_deallocate (mach_task_self (), thread);
+
+ return KERN_SUCCESS;
+}
+
+int
+port_valid (port, mask)
+ mach_port_t port;
+ int mask;
+{
+ kern_return_t ret;
+ mach_port_type_t type;
+
+ ret = mach_port_type (mach_task_self (),
+ port,
+ &type);
+ if (ret != KERN_SUCCESS || (type & mask) != mask)
+ return 0;
+ return 1;
+}
+
+/* @@ No vm read cache implemented yet */
+boolean_t vm_read_cache_valid = FALSE;
+
+/*
+ * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
+ * in gdb's address space.
+ *
+ * Return 0 on failure; number of bytes read otherwise.
+ */
+int
+mach3_read_inferior (addr, myaddr, length)
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ kern_return_t ret;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied_memory;
+ int copy_count;
+
+ /* Get memory from inferior with page aligned addresses */
+ ret = vm_read (inferior_task,
+ low_address,
+ aligned_length,
+ &copied_memory,
+ &copy_count);
+ if (ret != KERN_SUCCESS)
+ {
+ /* the problem is that the inferior might be killed for whatever reason
+ * before we go to mach_really_wait. This is one place that ought to
+ * catch many of those errors.
+ * @@ A better fix would be to make all external events to GDB
+ * to arrive via a SINGLE port set. (Including user input!)
+ */
+
+ if (! port_valid (inferior_task, MACH_PORT_TYPE_SEND))
+ {
+ m3_kill_inferior ();
+ error ("Inferior killed (task port invalid)");
+ }
+ else
+ {
+#ifdef OSF
+ extern int errno;
+ /* valprint.c gives nicer format if this does not
+ screw it. Eamonn seems to like this, so I enable
+ it if OSF is defined...
+ */
+ warning ("[read inferior %x failed: %s]",
+ addr, mach_error_string (ret));
+ errno = 0;
+#endif
+ return 0;
+ }
+ }
+
+ memcpy (myaddr, (char *)addr - low_address + copied_memory, length);
+
+ ret = vm_deallocate (mach_task_self (),
+ copied_memory,
+ copy_count);
+ CHK("mach3_read_inferior vm_deallocate failed", ret);
+
+ return length;
+}
+
+#ifdef __STDC__
+#define CHK_GOTO_OUT(str,ret) \
+ do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
+#else
+#define CHK_GOTO_OUT(str,ret) \
+ do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
+#endif
+
+struct vm_region_list {
+ struct vm_region_list *next;
+ vm_prot_t protection;
+ vm_address_t start;
+ vm_size_t length;
+};
+
+struct obstack region_obstack;
+
+/*
+ * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
+ * in gdb's address space.
+ */
+int
+mach3_write_inferior (addr, myaddr, length)
+ CORE_ADDR addr;
+ char *myaddr;
+ int length;
+{
+ kern_return_t ret;
+ vm_address_t low_address = (vm_address_t) trunc_page (addr);
+ vm_size_t aligned_length =
+ (vm_size_t) round_page (addr+length) - low_address;
+ pointer_t copied_memory;
+ int copy_count;
+ int deallocate = 0;
+
+ char *errstr = "Bug in mach3_write_inferior";
+
+ struct vm_region_list *region_element;
+ struct vm_region_list *region_head = (struct vm_region_list *)NULL;
+
+ /* Get memory from inferior with page aligned addresses */
+ ret = vm_read (inferior_task,
+ low_address,
+ aligned_length,
+ &copied_memory,
+ &copy_count);
+ CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
+
+ deallocate++;
+
+ memcpy ((char *)addr - low_address + copied_memory, myaddr, length);
+
+ obstack_init (&region_obstack);
+
+ /* Do writes atomically.
+ * First check for holes and unwritable memory.
+ */
+ {
+ vm_size_t remaining_length = aligned_length;
+ vm_address_t region_address = low_address;
+
+ struct vm_region_list *scan;
+
+ while(region_address < low_address + aligned_length)
+ {
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+ vm_inherit_t inheritance;
+ boolean_t shared;
+ mach_port_t object_name;
+ vm_offset_t offset;
+ vm_size_t region_length = remaining_length;
+ vm_address_t old_address = region_address;
+
+ ret = vm_region (inferior_task,
+ &region_address,
+ &region_length,
+ &protection,
+ &max_protection,
+ &inheritance,
+ &shared,
+ &object_name,
+ &offset);
+ CHK_GOTO_OUT ("vm_region failed", ret);
+
+ /* Check for holes in memory */
+ if (old_address != region_address)
+ {
+ warning ("No memory at 0x%x. Nothing written",
+ old_address);
+ ret = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ if (!(max_protection & VM_PROT_WRITE))
+ {
+ warning ("Memory at address 0x%x is unwritable. Nothing written",
+ old_address);
+ ret = KERN_SUCCESS;
+ length = 0;
+ goto out;
+ }
+
+ /* Chain the regions for later use */
+ region_element =
+ (struct vm_region_list *)
+ obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
+
+ region_element->protection = protection;
+ region_element->start = region_address;
+ region_element->length = region_length;
+
+ /* Chain the regions along with protections */
+ region_element->next = region_head;
+ region_head = region_element;
+
+ region_address += region_length;
+ remaining_length = remaining_length - region_length;
+ }
+
+ /* If things fail after this, we give up.
+ * Somebody is messing up inferior_task's mappings.
+ */
+
+ /* Enable writes to the chained vm regions */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ ret = vm_protect (inferior_task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection | VM_PROT_WRITE);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
+ }
+ }
+
+ ret = vm_write (inferior_task,
+ low_address,
+ copied_memory,
+ aligned_length);
+ CHK_GOTO_OUT ("vm_write failed", ret);
+
+ /* Set up the original region protections, if they were changed */
+ for (scan = region_head; scan; scan = scan->next)
+ {
+ boolean_t protection_changed = FALSE;
+
+ if (!(scan->protection & VM_PROT_WRITE))
+ {
+ ret = vm_protect (inferior_task,
+ scan->start,
+ scan->length,
+ FALSE,
+ scan->protection);
+ CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
+ }
+ }
+ }
+
+ out:
+ if (deallocate)
+ {
+ obstack_free (&region_obstack, 0);
+
+ (void) vm_deallocate (mach_task_self (),
+ copied_memory,
+ copy_count);
+ }
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("%s %s", errstr, mach_error_string (ret));
+ return 0;
+ }
+
+ return length;
+}
+
+/* Return 0 on failure, number of bytes handled otherwise. */
+static int
+m3_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* IGNORED */
+{
+ int result;
+
+ if (write)
+ result = mach3_write_inferior (memaddr, myaddr, len);
+ else
+ result = mach3_read_inferior (memaddr, myaddr, len);
+
+ return result;
+}
+
+
+static char *
+translate_state(state)
+int state;
+{
+ switch (state) {
+ case TH_STATE_RUNNING: return("R");
+ case TH_STATE_STOPPED: return("S");
+ case TH_STATE_WAITING: return("W");
+ case TH_STATE_UNINTERRUPTIBLE: return("U");
+ case TH_STATE_HALTED: return("H");
+ default: return("?");
+ }
+}
+
+static char *
+translate_cstate (state)
+ int state;
+{
+ switch (state)
+ {
+ case CPROC_RUNNING: return "R";
+ case CPROC_SWITCHING: return "S";
+ case CPROC_BLOCKED: return "B";
+ case CPROC_CONDWAIT: return "C";
+ case CPROC_CONDWAIT|CPROC_SWITCHING: return "CS";
+ default: return "?";
+ }
+}
+
+/* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
+
+mach_port_t /* no mach_port_name_t found in include files. */
+map_inferior_port_name (inferior_name, type)
+ mach_port_t inferior_name;
+ mach_msg_type_name_t type;
+{
+ kern_return_t ret;
+ mach_msg_type_name_t acquired;
+ mach_port_t iport;
+
+ ret = mach_port_extract_right (inferior_task,
+ inferior_name,
+ type,
+ &iport,
+ &acquired);
+ CHK("mach_port_extract_right (map_inferior_port_name)", ret);
+
+ if (acquired != MACH_MSG_TYPE_PORT_SEND)
+ error("Incorrect right extracted, (map_inferior_port_name)");
+
+ ret = mach_port_deallocate (mach_task_self (),
+ iport);
+ CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
+
+ return iport;
+}
+
+/*
+ * Naming convention:
+ * Always return user defined name if found.
+ * _K == A kernel thread with no matching CPROC
+ * _C == A cproc with no current cthread
+ * _t == A cthread with no user defined name
+ *
+ * The digits that follow the _names are the SLOT number of the
+ * kernel thread if there is such a thing, otherwise just a negation
+ * of the sequential number of such cprocs.
+ */
+
+static char buf[7];
+
+static char *
+get_thread_name (one_cproc, id)
+ gdb_thread_t one_cproc;
+ int id;
+{
+ if (one_cproc)
+ if (one_cproc->cthread == NULL)
+ {
+ /* cproc not mapped to any cthread */
+ sprintf(buf, "_C%d", id);
+ }
+ else if (! one_cproc->cthread->name)
+ {
+ /* cproc and cthread, but no name */
+ sprintf(buf, "_t%d", id);
+ }
+ else
+ return (char *)(one_cproc->cthread->name);
+ else
+ {
+ if (id < 0)
+ warning ("Inconsistency in thread name id %d", id);
+
+ /* Kernel thread without cproc */
+ sprintf(buf, "_K%d", id);
+ }
+
+ return buf;
+}
+
+int
+fetch_thread_info (task, mthreads_out)
+ mach_port_t task;
+ gdb_thread_t *mthreads_out; /* out */
+{
+ kern_return_t ret;
+ thread_array_t th_table;
+ int th_count;
+ gdb_thread_t mthreads = NULL;
+ int index;
+
+ ret = task_threads (task, &th_table, &th_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Error getting inferior's thread list:%s",
+ mach_error_string(ret));
+ m3_kill_inferior ();
+ return -1;
+ }
+
+ mthreads = (gdb_thread_t)
+ obstack_alloc
+ (cproc_obstack,
+ th_count * sizeof (struct gdb_thread));
+
+ for (index = 0; index < th_count; index++)
+ {
+ thread_t saved_thread = MACH_PORT_NULL;
+ int mid;
+
+ if (must_suspend_thread)
+ setup_thread (th_table[ index ], 1);
+
+ if (th_table[index] != current_thread)
+ {
+ saved_thread = current_thread;
+
+ mid = switch_to_thread (th_table[ index ]);
+ }
+
+ mthreads[index].name = th_table[index];
+ mthreads[index].cproc = NULL; /* map_cprocs_to_kernel_threads() */
+ mthreads[index].in_emulator = FALSE;
+ mthreads[index].slotid = index;
+
+ mthreads[index].sp = read_register (SP_REGNUM);
+ mthreads[index].fp = read_register (FP_REGNUM);
+ mthreads[index].pc = read_pc ();
+
+ if (MACH_PORT_VALID (saved_thread))
+ mid = switch_to_thread (saved_thread);
+
+ if (must_suspend_thread)
+ setup_thread (th_table[ index ], 0);
+ }
+
+ consume_send_rights (th_table, th_count);
+ ret = vm_deallocate (mach_task_self(), (vm_address_t)th_table,
+ (th_count * sizeof(mach_port_t)));
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Error trying to deallocate thread list : %s",
+ mach_error_string (ret));
+ }
+
+ *mthreads_out = mthreads;
+
+ return th_count;
+}
+
+
+/*
+ * Current emulator always saves the USP on top of
+ * emulator stack below struct emul_stack_top stuff.
+ */
+CORE_ADDR
+fetch_usp_from_emulator_stack (sp)
+ CORE_ADDR sp;
+{
+ CORE_ADDR stack_pointer;
+
+ sp = (sp & ~(EMULATOR_STACK_SIZE-1)) +
+ EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
+
+ if (mach3_read_inferior (sp,
+ &stack_pointer,
+ sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
+ {
+ warning ("Can't read user sp from emulator stack address 0x%x", sp);
+ return 0;
+ }
+
+ return stack_pointer;
+}
+
+#ifdef MK67
+
+/* get_emulation_vector() interface was changed after mk67 */
+#define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
+
+#endif /* MK67 */
+
+/* Check if the emulator exists at task's address space.
+ */
+boolean_t
+have_emulator_p (task)
+ task_t task;
+{
+ kern_return_t ret;
+#ifndef EMUL_VECTOR_COUNT
+ vm_offset_t *emulation_vector;
+ int n;
+#else
+ vm_offset_t emulation_vector[ EMUL_VECTOR_COUNT ];
+ int n = EMUL_VECTOR_COUNT;
+#endif
+ int i;
+ int vector_start;
+
+ ret = task_get_emulation_vector (task,
+ &vector_start,
+#ifndef EMUL_VECTOR_COUNT
+ &emulation_vector,
+#else
+ emulation_vector,
+#endif
+ &n);
+ CHK("task_get_emulation_vector", ret);
+ xx_debug ("%d vectors from %d at 0x%08x\n",
+ n, vector_start, emulation_vector);
+
+ for(i = 0; i < n; i++)
+ {
+ vm_offset_t entry = emulation_vector [i];
+
+ if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
+ return TRUE;
+ else if (entry)
+ {
+ static boolean_t informed = FALSE;
+ if (!informed)
+ {
+ warning("Emulation vector address 0x08%x outside emulator space",
+ entry);
+ informed = TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/* Map cprocs to kernel threads and vice versa. */
+
+void
+map_cprocs_to_kernel_threads (cprocs, mthreads, thread_count)
+ gdb_thread_t cprocs;
+ gdb_thread_t mthreads;
+ int thread_count;
+{
+ int index;
+ gdb_thread_t scan;
+ boolean_t all_mapped = TRUE;
+ LONGEST stack_base;
+ LONGEST stack_size;
+
+ for (scan = cprocs; scan; scan = scan->next)
+ {
+ /* Default to: no kernel thread for this cproc */
+ scan->reverse_map = -1;
+
+ /* Check if the cproc is found by its stack */
+ for (index = 0; index < thread_count; index++)
+ {
+ stack_base =
+ extract_signed_integer (scan->raw_cproc + CPROC_BASE_OFFSET,
+ CPROC_BASE_SIZE);
+ stack_size =
+ extract_signed_integer (scan->raw_cproc + CPROC_SIZE_OFFSET,
+ CPROC_SIZE_SIZE);
+ if ((mthreads + index)->sp > stack_base &&
+ (mthreads + index)->sp <= stack_base + stack_size)
+ {
+ (mthreads + index)->cproc = scan;
+ scan->reverse_map = index;
+ break;
+ }
+ }
+ all_mapped &= (scan->reverse_map != -1);
+ }
+
+ /* Check for threads that are currently in the emulator.
+ * If so, they have a different stack, and the still unmapped
+ * cprocs may well get mapped to these threads.
+ *
+ * If:
+ * - cproc stack does not match any kernel thread stack pointer
+ * - there is at least one extra kernel thread
+ * that has no cproc mapped above.
+ * - some kernel thread stack pointer points to emulator space
+ * then we find the user stack pointer saved in the emulator
+ * stack, and try to map that to the cprocs.
+ *
+ * Also set in_emulator for kernel threads.
+ */
+
+ if (emulator_present)
+ {
+ for (index = 0; index < thread_count; index++)
+ {
+ CORE_ADDR emul_sp;
+ CORE_ADDR usp;
+
+ gdb_thread_t mthread = (mthreads+index);
+ emul_sp = mthread->sp;
+
+ if (mthread->cproc == NULL &&
+ EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
+ {
+ mthread->in_emulator = emulator_present;
+
+ if (!all_mapped && cprocs)
+ {
+ usp = fetch_usp_from_emulator_stack (emul_sp);
+
+ /* @@ Could be more accurate */
+ if (! usp)
+ error ("Zero stack pointer read from emulator?");
+
+ /* Try to match this stack pointer to the cprocs that
+ * don't yet have a kernel thread.
+ */
+ for (scan = cprocs; scan; scan = scan->next)
+ {
+
+ /* Check is this unmapped CPROC stack contains
+ * the user stack pointer saved in the
+ * emulator.
+ */
+ if (scan->reverse_map == -1)
+ {
+ stack_base =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_BASE_OFFSET,
+ CPROC_BASE_SIZE);
+ stack_size =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_SIZE_OFFSET,
+ CPROC_SIZE_SIZE);
+ if (usp > stack_base &&
+ usp <= stack_base + stack_size)
+ {
+ mthread->cproc = scan;
+ scan->reverse_map = index;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Format of the thread_list command
+ *
+ * slot mid sel name emul ks susp cstate wired address
+ */
+#define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
+
+#define TL_HEADER "\n@ MID Name KState CState Where\n"
+
+void
+print_tl_address (stream, pc)
+ GDB_FILE *stream;
+ CORE_ADDR pc;
+{
+ if (! lookup_minimal_symbol_by_pc (pc))
+ fprintf_filtered (stream, local_hex_format(), pc);
+ else
+ {
+ extern int addressprint;
+ extern int asm_demangle;
+
+ int store = addressprint;
+ addressprint = 0;
+ print_address_symbolic (pc, stream, asm_demangle, "");
+ addressprint = store;
+ }
+}
+
+/* For thread names, but also for gdb_message_port external name */
+#define MAX_NAME_LEN 50
+
+/* Returns the address of variable NAME or 0 if not found */
+CORE_ADDR
+lookup_address_of_variable (name)
+ char *name;
+{
+ struct symbol *sym;
+ CORE_ADDR symaddr = 0;
+ struct minimal_symbol *msymbol;
+
+ sym = lookup_symbol (name,
+ (struct block *)NULL,
+ VAR_NAMESPACE,
+ (int *)NULL,
+ (struct symtab **)NULL);
+
+ if (sym)
+ symaddr = SYMBOL_VALUE (sym);
+
+ if (! symaddr)
+ {
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+
+ if (msymbol && msymbol->type == mst_data)
+ symaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+
+ return symaddr;
+}
+
+static gdb_thread_t
+get_cprocs()
+{
+ gdb_thread_t cproc_head;
+ gdb_thread_t cproc_copy;
+ CORE_ADDR their_cprocs;
+ char *buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+ char *name;
+ cthread_t cthread;
+ CORE_ADDR symaddr;
+
+ symaddr = lookup_address_of_variable ("cproc_list");
+
+ if (! symaddr)
+ {
+ /* cproc_list is not in a file compiled with debugging
+ symbols, but don't give up yet */
+
+ symaddr = lookup_address_of_variable ("cprocs");
+
+ if (symaddr)
+ {
+ static int informed = 0;
+ if (!informed)
+ {
+ informed++;
+ warning ("Your program is loaded with an old threads library.");
+ warning ("GDB does not know the old form of threads");
+ warning ("so things may not work.");
+ }
+ }
+ }
+
+ /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
+ if (! symaddr)
+ return NULL;
+
+ /* Get the address of the first cproc in the task */
+ if (!mach3_read_inferior (symaddr,
+ buf,
+ TARGET_PTR_BIT / HOST_CHAR_BIT))
+ error ("Can't read cproc master list at address (0x%x).", symaddr);
+ their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
+
+ /* Scan the CPROCs in the task.
+ CPROCs are chained with LIST field, not NEXT field, which
+ chains mutexes, condition variables and queues */
+
+ cproc_head = NULL;
+
+ while (their_cprocs != (CORE_ADDR)0)
+ {
+ CORE_ADDR cproc_copy_incarnation;
+ cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
+ sizeof (struct gdb_thread));
+
+ if (!mach3_read_inferior (their_cprocs,
+ &cproc_copy->raw_cproc[0],
+ CPROC_SIZE))
+ error("Can't read next cproc at 0x%x.", their_cprocs);
+
+ their_cprocs =
+ extract_address (cproc_copy->raw_cproc + CPROC_LIST_OFFSET,
+ CPROC_LIST_SIZE);
+ cproc_copy_incarnation =
+ extract_address (cproc_copy->raw_cproc + CPROC_INCARNATION_OFFSET,
+ CPROC_INCARNATION_SIZE);
+
+ if (cproc_copy_incarnation == (CORE_ADDR)0)
+ cproc_copy->cthread = NULL;
+ else
+ {
+ /* This CPROC has an attached CTHREAD. Get its name */
+ cthread = (cthread_t)obstack_alloc (cproc_obstack,
+ sizeof(struct cthread));
+
+ if (!mach3_read_inferior (cproc_copy_incarnation,
+ cthread,
+ sizeof(struct cthread)))
+ error("Can't read next thread at 0x%x.",
+ cproc_copy_incarnation);
+
+ cproc_copy->cthread = cthread;
+
+ if (cthread->name)
+ {
+ name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
+
+ if (!mach3_read_inferior(cthread->name, name, MAX_NAME_LEN))
+ error("Can't read next thread's name at 0x%x.", cthread->name);
+
+ cthread->name = name;
+ }
+ }
+
+ /* insert in front */
+ cproc_copy->next = cproc_head;
+ cproc_head = cproc_copy;
+ }
+ return cproc_head;
+}
+
+#ifndef FETCH_CPROC_STATE
+/*
+ * Check if your machine does not grok the way this routine
+ * fetches the FP,PC and SP of a cproc that is not
+ * currently attached to any kernel thread (e.g. its cproc.context
+ * field points to the place in stack where the context
+ * is saved).
+ *
+ * If it doesn't, define your own routine.
+ */
+#define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
+
+int
+mach3_cproc_state (mthread)
+ gdb_thread_t mthread;
+{
+ int context;
+
+ if (! mthread || !mthread->cproc)
+ return -1;
+
+ context = extract_signed_integer
+ (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
+ CPROC_CONTEXT_SIZE);
+ if (context == 0)
+ return -1;
+
+ mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
+
+ if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
+ &mthread->pc,
+ sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
+ {
+ warning ("Can't read cproc pc from inferior");
+ return -1;
+ }
+
+ if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
+ &mthread->fp,
+ sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
+ {
+ warning ("Can't read cproc fp from inferior");
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* FETCH_CPROC_STATE */
+
+
+void
+thread_list_command()
+{
+ thread_basic_info_data_t ths;
+ int thread_count;
+ gdb_thread_t cprocs;
+ gdb_thread_t scan;
+ int index;
+ char *name;
+ char selected;
+ char *wired;
+ int infoCnt;
+ kern_return_t ret;
+ mach_port_t mid_or_port;
+ gdb_thread_t their_threads;
+ gdb_thread_t kthread;
+
+ int neworder = 1;
+
+ char *fmt = "There are %d kernel threads in task %d.\n";
+
+ int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
+
+ MACH_ERROR_NO_INFERIOR;
+
+ thread_count = fetch_thread_info (inferior_task,
+ &their_threads);
+ if (thread_count == -1)
+ return;
+
+ if (thread_count == 1)
+ fmt = "There is %d kernel thread in task %d.\n";
+
+ printf_filtered (fmt, thread_count, tmid);
+
+ puts_filtered (TL_HEADER);
+
+ cprocs = get_cprocs();
+
+ map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
+
+ for (scan = cprocs; scan; scan = scan->next)
+ {
+ int mid;
+ char buf[10];
+ char slot[3];
+ int cproc_state =
+ extract_signed_integer
+ (scan->raw_cproc + CPROC_STATE_OFFSET, CPROC_STATE_SIZE);
+
+ selected = ' ';
+
+ /* a wired cproc? */
+ wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
+ CPROC_WIRED_SIZE)
+ ? "wired" : "");
+
+ if (scan->reverse_map != -1)
+ kthread = (their_threads + scan->reverse_map);
+ else
+ kthread = NULL;
+
+ if (kthread)
+ {
+ /* These cprocs have a kernel thread */
+
+ mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
+
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ ret = thread_info (kthread->name,
+ THREAD_BASIC_INFO,
+ (thread_info_t)&ths,
+ &infoCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Unable to get basic info on thread %d : %s",
+ mid,
+ mach_error_string (ret));
+ continue;
+ }
+
+ /* Who is the first to have more than 100 threads */
+ sprintf (slot, "%d", kthread->slotid%100);
+
+ if (kthread->name == current_thread)
+ selected = '*';
+
+ if (ths.suspend_count)
+ sprintf (buf, "%d", ths.suspend_count);
+ else
+ buf[0] = '\000';
+
+#if 0
+ if (ths.flags & TH_FLAGS_SWAPPED)
+ strcat (buf, "S");
+#endif
+
+ if (ths.flags & TH_FLAGS_IDLE)
+ strcat (buf, "I");
+
+ printf_filtered (TL_FORMAT,
+ slot,
+ mid,
+ selected,
+ get_thread_name (scan, kthread->slotid),
+ kthread->in_emulator ? "E" : "",
+ translate_state (ths.run_state),
+ buf,
+ translate_cstate (cproc_state),
+ wired);
+ print_tl_address (gdb_stdout, kthread->pc);
+ }
+ else
+ {
+ /* These cprocs don't have a kernel thread.
+ * find out the calling frame with
+ * FETCH_CPROC_STATE.
+ */
+
+ struct gdb_thread state;
+
+#if 0
+ /* jtv -> emcmanus: why do you want this here? */
+ if (scan->incarnation == NULL)
+ continue; /* EMcM */
+#endif
+
+ printf_filtered (TL_FORMAT,
+ "-",
+ -neworder, /* Pseudo MID */
+ selected,
+ get_thread_name (scan, -neworder),
+ "",
+ "-", /* kernel state */
+ "",
+ translate_cstate (cproc_state),
+ "");
+ state.cproc = scan;
+
+ if (FETCH_CPROC_STATE (&state) == -1)
+ puts_filtered ("???");
+ else
+ print_tl_address (gdb_stdout, state.pc);
+
+ neworder++;
+ }
+ puts_filtered ("\n");
+ }
+
+ /* Scan for kernel threads without cprocs */
+ for (index = 0; index < thread_count; index++)
+ {
+ if (! their_threads[index].cproc)
+ {
+ int mid;
+
+ char buf[10];
+ char slot[3];
+
+ mach_port_t name = their_threads[index].name;
+
+ mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
+
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ ret = thread_info(name,
+ THREAD_BASIC_INFO,
+ (thread_info_t)&ths,
+ &infoCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Unable to get basic info on thread %d : %s",
+ mid,
+ mach_error_string (ret));
+ continue;
+ }
+
+ sprintf (slot, "%d", index%100);
+
+ if (name == current_thread)
+ selected = '*';
+ else
+ selected = ' ';
+
+ if (ths.suspend_count)
+ sprintf (buf, "%d", ths.suspend_count);
+ else
+ buf[0] = '\000';
+
+#if 0
+ if (ths.flags & TH_FLAGS_SWAPPED)
+ strcat (buf, "S");
+#endif
+
+ if (ths.flags & TH_FLAGS_IDLE)
+ strcat (buf, "I");
+
+ printf_filtered (TL_FORMAT,
+ slot,
+ mid,
+ selected,
+ get_thread_name (NULL, index),
+ their_threads[index].in_emulator ? "E" : "",
+ translate_state (ths.run_state),
+ buf,
+ "", /* No cproc state */
+ ""); /* Can't be wired */
+ print_tl_address (gdb_stdout, their_threads[index].pc);
+ puts_filtered ("\n");
+ }
+ }
+
+ obstack_free (cproc_obstack, 0);
+ obstack_init (cproc_obstack);
+}
+
+void
+thread_select_command(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid;
+ thread_array_t thread_list;
+ int thread_count;
+ kern_return_t ret;
+ int is_slot = 0;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!args)
+ error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
+
+ while (*args == ' ' || *args == '\t')
+ args++;
+
+ if (*args == '@')
+ {
+ is_slot++;
+ args++;
+ }
+
+ mid = atoi(args);
+
+ if (mid == 0)
+ if (!is_slot || *args != '0') /* Rudimentary checks */
+ error ("You must select threads by MID or @SLOTNUMBER");
+
+ if (select_thread (inferior_task, mid, is_slot?2:1) != KERN_SUCCESS)
+ return;
+
+ if (from_tty)
+ printf_filtered ("Thread %d selected\n",
+ is_slot ? map_port_name_to_mid (current_thread,
+ MACH_TYPE_THREAD) : mid);
+}
+
+thread_trace (thread, set)
+mach_port_t thread;
+boolean_t set;
+{
+ int flavor = TRACE_FLAVOR;
+ unsigned int stateCnt = TRACE_FLAVOR_SIZE;
+ kern_return_t ret;
+ thread_state_data_t state;
+
+ if (! MACH_PORT_VALID (thread))
+ {
+ warning ("thread_trace: invalid thread");
+ return;
+ }
+
+ if (must_suspend_thread)
+ setup_thread (thread, 1);
+
+ ret = thread_get_state(thread, flavor, state, &stateCnt);
+ CHK ("thread_trace: error reading thread state", ret);
+
+ if (set)
+ {
+ TRACE_SET (thread, state);
+ }
+ else
+ {
+ if (! TRACE_CLEAR (thread, state))
+ {
+ if (must_suspend_thread)
+ setup_thread (thread, 0);
+ return;
+ }
+ }
+
+ ret = thread_set_state(thread, flavor, state, stateCnt);
+ CHK ("thread_trace: error writing thread state", ret);
+ if (must_suspend_thread)
+ setup_thread (thread, 0);
+}
+
+#ifdef FLUSH_INFERIOR_CACHE
+
+/* When over-writing code on some machines the I-Cache must be flushed
+ explicitly, because it is not kept coherent by the lazy hardware.
+ This definitely includes breakpoints, for instance, or else we
+ end up looping in mysterious Bpt traps */
+
+flush_inferior_icache(pc, amount)
+ CORE_ADDR pc;
+{
+ vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
+ kern_return_t ret;
+
+ ret = vm_machine_attribute (inferior_task,
+ pc,
+ amount,
+ MATTR_CACHE,
+ &flush);
+ if (ret != KERN_SUCCESS)
+ warning ("Error flushing inferior's cache : %s",
+ mach_error_string (ret));
+}
+#endif FLUSH_INFERIOR_CACHE
+
+
+static
+suspend_all_threads (from_tty)
+ int from_tty;
+{
+ kern_return_t ret;
+ thread_array_t thread_list;
+ int thread_count, index;
+ int infoCnt;
+ thread_basic_info_data_t th_info;
+
+
+ ret = task_threads (inferior_task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("Could not suspend inferior threads.");
+ m3_kill_inferior ();
+ return_to_top_level (RETURN_ERROR);
+ }
+
+ for (index = 0; index < thread_count; index++)
+ {
+ int mid;
+
+ mid = map_port_name_to_mid (thread_list[ index ],
+ MACH_TYPE_THREAD);
+
+ ret = thread_suspend(thread_list[ index ]);
+
+ if (ret != KERN_SUCCESS)
+ warning ("Error trying to suspend thread %d : %s",
+ mid, mach_error_string (ret));
+
+ if (from_tty)
+ {
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+ ret = thread_info (thread_list[ index ],
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("suspend can't get thread info", ret);
+
+ warning ("Thread %d suspend count is %d",
+ mid, th_info.suspend_count);
+ }
+ }
+
+ consume_send_rights (thread_list, thread_count);
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t)thread_list,
+ (thread_count * sizeof(int)));
+ CHK ("Error trying to deallocate thread list", ret);
+}
+
+void
+thread_suspend_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ kern_return_t ret;
+ int mid;
+ mach_port_t saved_thread;
+ int infoCnt;
+ thread_basic_info_data_t th_info;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!strcasecmp (args, "all")) {
+ suspend_all_threads (from_tty);
+ return;
+ }
+
+ saved_thread = current_thread;
+
+ mid = parse_thread_id (args, 0, 0);
+
+ if (mid < 0)
+ error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
+
+ if (mid == 0)
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+ else
+ if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
+ {
+ if (current_thread)
+ current_thread = saved_thread;
+ error ("Could not select thread %d", mid);
+ }
+
+ ret = thread_suspend (current_thread);
+ if (ret != KERN_SUCCESS)
+ warning ("thread_suspend failed : %s",
+ mach_error_string (ret));
+
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+ ret = thread_info (current_thread,
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("suspend can't get thread info", ret);
+
+ warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
+
+ current_thread = saved_thread;
+}
+
+resume_all_threads (from_tty)
+ int from_tty;
+{
+ kern_return_t ret;
+ thread_array_t thread_list;
+ int thread_count, index;
+ int mid;
+ int infoCnt;
+ thread_basic_info_data_t th_info;
+
+ ret = task_threads (inferior_task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ m3_kill_inferior ();
+ error("task_threads", mach_error_string( ret));
+ }
+
+ for (index = 0; index < thread_count; index++)
+ {
+ infoCnt = THREAD_BASIC_INFO_COUNT;
+ ret = thread_info (thread_list [ index ],
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("resume_all can't get thread info", ret);
+
+ mid = map_port_name_to_mid (thread_list[ index ],
+ MACH_TYPE_THREAD);
+
+ if (! th_info.suspend_count)
+ {
+ if (mid != -1 && from_tty)
+ warning ("Thread %d is not suspended", mid);
+ continue;
+ }
+
+ ret = thread_resume (thread_list[ index ]);
+
+ if (ret != KERN_SUCCESS)
+ warning ("Error trying to resume thread %d : %s",
+ mid, mach_error_string (ret));
+ else if (mid != -1 && from_tty)
+ warning ("Thread %d suspend count is %d",
+ mid, --th_info.suspend_count);
+ }
+
+ consume_send_rights (thread_list, thread_count);
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t)thread_list,
+ (thread_count * sizeof(int)));
+ CHK("Error trying to deallocate thread list", ret);
+}
+
+void
+thread_resume_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid;
+ mach_port_t saved_thread;
+ kern_return_t ret;
+ thread_basic_info_data_t th_info;
+ int infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!strcasecmp (args, "all")) {
+ resume_all_threads (from_tty);
+ return;
+ }
+
+ saved_thread = current_thread;
+
+ mid = parse_thread_id (args, 0, 0);
+
+ if (mid < 0)
+ error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
+
+ if (mid == 0)
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+ else
+ if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
+ {
+ if (current_thread)
+ current_thread = saved_thread;
+ return_to_top_level (RETURN_ERROR);
+ }
+
+ ret = thread_info (current_thread,
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("resume can't get thread info", ret);
+
+ if (! th_info.suspend_count)
+ {
+ warning ("Thread %d is not suspended", mid);
+ goto out;
+ }
+
+ ret = thread_resume (current_thread);
+ if (ret != KERN_SUCCESS)
+ warning ("thread_resume failed : %s",
+ mach_error_string (ret));
+ else
+ {
+ th_info.suspend_count--;
+ warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
+ }
+
+ out:
+ current_thread = saved_thread;
+}
+
+void
+thread_kill_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid;
+ kern_return_t ret;
+ int thread_count;
+ thread_array_t thread_table;
+ int index;
+ mach_port_t thread_to_kill = MACH_PORT_NULL;
+
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (!args)
+ error_no_arg ("thread mid to kill from the inferior task");
+
+ mid = parse_thread_id (args, 0, 0);
+
+ if (mid < 0)
+ error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
+
+ if (mid)
+ {
+ ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
+ CHK ("thread_kill_command: machid_mach_port map failed", ret);
+ }
+ else
+ mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
+
+ /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
+ ret = task_threads (inferior_task, &thread_table, &thread_count);
+ CHK ("Error getting inferior's thread list", ret);
+
+ if (thread_to_kill == current_thread)
+ {
+ ret = thread_terminate (thread_to_kill);
+ CHK ("Thread could not be terminated", ret);
+
+ if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
+ warning ("Last thread was killed, use \"kill\" command to kill task");
+ }
+ else
+ for (index = 0; index < thread_count; index++)
+ if (thread_table [ index ] == thread_to_kill)
+ {
+ ret = thread_terminate (thread_to_kill);
+ CHK ("Thread could not be terminated", ret);
+ }
+
+ if (thread_count > 1)
+ consume_send_rights (thread_table, thread_count);
+
+ ret = vm_deallocate (mach_task_self(), (vm_address_t)thread_table,
+ (thread_count * sizeof(mach_port_t)));
+ CHK ("Error trying to deallocate thread list", ret);
+
+ warning ("Thread %d killed", mid);
+}
+
+
+/* Task specific commands; add more if you like */
+
+void
+task_resume_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ kern_return_t ret;
+ task_basic_info_data_t ta_info;
+ int infoCnt = TASK_BASIC_INFO_COUNT;
+ int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
+
+ MACH_ERROR_NO_INFERIOR;
+
+ /* Would be trivial to change, but is it desirable? */
+ if (args)
+ error ("Currently gdb can resume only it's inferior task");
+
+ ret = task_info (inferior_task,
+ TASK_BASIC_INFO,
+ (task_info_t) &ta_info,
+ &infoCnt);
+ CHK ("task_resume_command: task_info failed", ret);
+
+ if (ta_info.suspend_count == 0)
+ error ("Inferior task %d is not suspended", mid);
+ else if (ta_info.suspend_count == 1 &&
+ from_tty &&
+ !query ("Suspend count is now 1. Do you know what you are doing? "))
+ error ("Task not resumed");
+
+ ret = task_resume (inferior_task);
+ CHK ("task_resume_command: task_resume", ret);
+
+ if (ta_info.suspend_count == 1)
+ {
+ warning ("Inferior task %d is no longer suspended", mid);
+ must_suspend_thread = 1;
+ /* @@ This is not complete: Registers change all the time when not
+ suspended! */
+ registers_changed ();
+ }
+ else
+ warning ("Inferior task %d suspend count is now %d",
+ mid, ta_info.suspend_count-1);
+}
+
+
+void
+task_suspend_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ kern_return_t ret;
+ task_basic_info_data_t ta_info;
+ int infoCnt = TASK_BASIC_INFO_COUNT;
+ int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
+
+ MACH_ERROR_NO_INFERIOR;
+
+ /* Would be trivial to change, but is it desirable? */
+ if (args)
+ error ("Currently gdb can suspend only it's inferior task");
+
+ ret = task_suspend (inferior_task);
+ CHK ("task_suspend_command: task_suspend", ret);
+
+ must_suspend_thread = 0;
+
+ ret = task_info (inferior_task,
+ TASK_BASIC_INFO,
+ (task_info_t) &ta_info,
+ &infoCnt);
+ CHK ("task_suspend_command: task_info failed", ret);
+
+ warning ("Inferior task %d suspend count is now %d",
+ mid, ta_info.suspend_count);
+}
+
+static char *
+get_size (bytes)
+ int bytes;
+{
+ static char size [ 30 ];
+ int zz = bytes/1024;
+
+ if (zz / 1024)
+ sprintf (size, "%-2.1f M", ((float)bytes)/(1024.0*1024.0));
+ else
+ sprintf (size, "%d K", zz);
+
+ return size;
+}
+
+/* Does this require the target task to be suspended?? I don't think so. */
+void
+task_info_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int mid = -5;
+ mach_port_t task;
+ kern_return_t ret;
+ task_basic_info_data_t ta_info;
+ int infoCnt = TASK_BASIC_INFO_COUNT;
+ int page_size = round_page(1);
+ int thread_count = 0;
+
+ if (MACH_PORT_VALID (inferior_task))
+ mid = map_port_name_to_mid (inferior_task,
+ MACH_TYPE_TASK);
+
+ task = inferior_task;
+
+ if (args)
+ {
+ int tmid = atoi (args);
+
+ if (tmid <= 0)
+ error ("Invalid mid %d for task info", tmid);
+
+ if (tmid != mid)
+ {
+ mid = tmid;
+ ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
+ CHK ("task_info_command: machid_mach_port map failed", ret);
+ }
+ }
+
+ if (mid < 0)
+ error ("You have to give the task MID as an argument");
+
+ ret = task_info (task,
+ TASK_BASIC_INFO,
+ (task_info_t) &ta_info,
+ &infoCnt);
+ CHK ("task_info_command: task_info failed", ret);
+
+ printf_filtered ("\nTask info for task %d:\n\n", mid);
+ printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
+ printf_filtered (" Base priority : %d\n", ta_info.base_priority);
+ printf_filtered (" Virtual size : %s\n", get_size (ta_info.virtual_size));
+ printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
+
+ {
+ thread_array_t thread_list;
+
+ ret = task_threads (task, &thread_list, &thread_count);
+ CHK ("task_info_command: task_threads", ret);
+
+ printf_filtered (" Thread count : %d\n", thread_count);
+
+ consume_send_rights (thread_list, thread_count);
+ ret = vm_deallocate(mach_task_self(),
+ (vm_address_t)thread_list,
+ (thread_count * sizeof(int)));
+ CHK("Error trying to deallocate thread list", ret);
+ }
+ if (have_emulator_p (task))
+ printf_filtered (" Emulator at : 0x%x..0x%x\n",
+ EMULATOR_BASE, EMULATOR_END);
+ else
+ printf_filtered (" No emulator.\n");
+
+ if (thread_count && task == inferior_task)
+ printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
+}
+
+/* You may either FORWARD the exception to the inferior, or KEEP
+ * it and return to GDB command level.
+ *
+ * exception mid [ forward | keep ]
+ */
+
+static void
+exception_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *scan = args;
+ int exception;
+ int len;
+
+ if (!args)
+ error_no_arg ("exception number action");
+
+ while (*scan == ' ' || *scan == '\t') scan++;
+
+ if ('0' <= *scan && *scan <= '9')
+ while ('0' <= *scan && *scan <= '9')
+ scan++;
+ else
+ error ("exception number action");
+
+ exception = atoi (args);
+ if (exception <= 0 || exception > MAX_EXCEPTION)
+ error ("Allowed exception numbers are in range 1..%d",
+ MAX_EXCEPTION);
+
+ if (*scan != ' ' && *scan != '\t')
+ error ("exception number must be followed by a space");
+ else
+ while (*scan == ' ' || *scan == '\t') scan++;
+
+ args = scan;
+ len = 0;
+ while (*scan)
+ {
+ len++;
+ scan++;
+ }
+
+ if (!len)
+ error("exception number action");
+
+ if (!strncasecmp (args, "forward", len))
+ exception_map[ exception ].forward = TRUE;
+ else if (!strncasecmp (args, "keep", len))
+ exception_map[ exception ].forward = FALSE;
+ else
+ error ("exception action is either \"keep\" or \"forward\"");
+}
+
+static void
+print_exception_info (exception)
+ int exception;
+{
+ boolean_t forward = exception_map[ exception ].forward;
+
+ printf_filtered ("%s\t(%d): ", exception_map[ exception ].name,
+ exception);
+ if (!forward)
+ if (exception_map[ exception ].sigmap != SIG_UNKNOWN)
+ printf_filtered ("keep and handle as signal %d\n",
+ exception_map[ exception ].sigmap);
+ else
+ printf_filtered ("keep and handle as unknown signal %d\n",
+ exception_map[ exception ].sigmap);
+ else
+ printf_filtered ("forward exception to inferior\n");
+}
+
+void
+exception_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int exception;
+
+ if (!args)
+ for (exception = 1; exception <= MAX_EXCEPTION; exception++)
+ print_exception_info (exception);
+ else
+ {
+ exception = atoi (args);
+
+ if (exception <= 0 || exception > MAX_EXCEPTION)
+ error ("Invalid exception number, values from 1 to %d allowed",
+ MAX_EXCEPTION);
+ print_exception_info (exception);
+ }
+}
+
+/* Check for actions for mach exceptions.
+ */
+mach3_exception_actions (w, force_print_only, who)
+ WAITTYPE *w;
+ boolean_t force_print_only;
+ char *who;
+{
+ boolean_t force_print = FALSE;
+
+
+ if (force_print_only ||
+ exception_map[stop_exception].sigmap == SIG_UNKNOWN)
+ force_print = TRUE;
+ else
+ WSETSTOP (*w, exception_map[stop_exception].sigmap);
+
+ if (exception_map[stop_exception].print || force_print)
+ {
+ target_terminal_ours ();
+
+ printf_filtered ("\n%s received %s exception : ",
+ who,
+ exception_map[stop_exception].name);
+
+ wrap_here (" ");
+
+ switch(stop_exception) {
+ case EXC_BAD_ACCESS:
+ printf_filtered ("referencing address 0x%x : %s\n",
+ stop_subcode,
+ mach_error_string (stop_code));
+ break;
+ case EXC_BAD_INSTRUCTION:
+ printf_filtered
+ ("illegal or undefined instruction. code %d subcode %d\n",
+ stop_code, stop_subcode);
+ break;
+ case EXC_ARITHMETIC:
+ printf_filtered ("code %d\n", stop_code);
+ break;
+ case EXC_EMULATION:
+ printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
+ break;
+ case EXC_SOFTWARE:
+ printf_filtered ("%s specific, code 0x%x\n",
+ stop_code < 0xffff ? "hardware" : "os emulation",
+ stop_code);
+ break;
+ case EXC_BREAKPOINT:
+ printf_filtered ("type %d (machine dependent)\n",
+ stop_code);
+ break;
+ default:
+ fatal ("Unknown exception");
+ }
+ }
+}
+
+setup_notify_port (create_new)
+ int create_new;
+{
+ kern_return_t ret;
+
+ if (MACH_PORT_VALID (our_notify_port))
+ {
+ ret = mach_port_destroy (mach_task_self (), our_notify_port);
+ CHK ("Could not destroy our_notify_port", ret);
+ }
+
+ our_notify_port = MACH_PORT_NULL;
+ notify_chain = (port_chain_t) NULL;
+ port_chain_destroy (port_chain_obstack);
+
+ if (create_new)
+ {
+ ret = mach_port_allocate (mach_task_self(),
+ MACH_PORT_RIGHT_RECEIVE,
+ &our_notify_port);
+ if (ret != KERN_SUCCESS)
+ fatal("Creating notify port %s", mach_error_string(ret));
+
+ ret = mach_port_move_member(mach_task_self(),
+ our_notify_port,
+ inferior_wait_port_set);
+ if (ret != KERN_SUCCESS)
+ fatal("initial move member %s",mach_error_string(ret));
+ }
+}
+
+/*
+ * Register our message port to the net name server
+ *
+ * Currently used only by the external stop-gdb program
+ * since ^C does not work if you would like to enter
+ * gdb command level while debugging your program.
+ *
+ * NOTE: If the message port is sometimes used for other
+ * purposes also, the NAME must not be a guessable one.
+ * Then, there should be a way to change it.
+ */
+
+char registered_name[ MAX_NAME_LEN ];
+
+void
+message_port_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (registered_name[0])
+ printf_filtered ("gdb's message port name: '%s'\n",
+ registered_name);
+ else
+ printf_filtered ("gdb's message port is not currently registered\n");
+}
+
+void
+gdb_register_port (name, port)
+ char *name;
+ mach_port_t port;
+{
+ kern_return_t ret;
+ static int already_signed = 0;
+ int len;
+
+ if (! MACH_PORT_VALID (port) || !name || !*name)
+ {
+ warning ("Invalid registration request");
+ return;
+ }
+
+ if (! already_signed)
+ {
+ ret = mach_port_insert_right (mach_task_self (),
+ our_message_port,
+ our_message_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK ("Failed to create a signature to our_message_port", ret);
+ already_signed = 1;
+ }
+ else if (already_signed > 1)
+ {
+ ret = netname_check_out (name_server_port,
+ registered_name,
+ our_message_port);
+ CHK ("Failed to check out gdb's message port", ret);
+ registered_name[0] = '\000';
+ already_signed = 1;
+ }
+
+ ret = netname_check_in (name_server_port, /* Name server port */
+ name, /* Name of service */
+ our_message_port, /* Signature */
+ port); /* Creates a new send right */
+ CHK("Failed to check in the port", ret);
+
+ len = 0;
+ while(len < MAX_NAME_LEN && *(name+len))
+ {
+ registered_name[len] = *(name+len);
+ len++;
+ }
+ registered_name[len] = '\000';
+ already_signed = 2;
+}
+
+struct cmd_list_element *cmd_thread_list;
+struct cmd_list_element *cmd_task_list;
+
+/*ARGSUSED*/
+static void
+thread_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
+ help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
+}
+
+/*ARGSUSED*/
+static void
+task_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
+ help_list (cmd_task_list, "task ", -1, gdb_stdout);
+}
+
+add_mach_specific_commands ()
+{
+ /* Thread handling commands */
+
+ /* FIXME: Move our thread support into the generic thread.c stuff so we
+ can share that code. */
+ add_prefix_cmd ("mthread", class_stack, thread_command,
+ "Generic command for handling Mach threads in the debugged task.",
+ &cmd_thread_list, "thread ", 0, &cmdlist);
+
+ add_com_alias ("th", "mthread", class_stack, 1);
+
+ add_cmd ("select", class_stack, thread_select_command,
+ "Select and print MID of the selected thread",
+ &cmd_thread_list);
+ add_cmd ("list", class_stack, thread_list_command,
+ "List info of task's threads. Selected thread is marked with '*'",
+ &cmd_thread_list);
+ add_cmd ("suspend", class_run, thread_suspend_command,
+ "Suspend one or all of the threads in the selected task.",
+ &cmd_thread_list);
+ add_cmd ("resume", class_run, thread_resume_command,
+ "Resume one or all of the threads in the selected task.",
+ &cmd_thread_list);
+ add_cmd ("kill", class_run, thread_kill_command,
+ "Kill the specified thread MID from inferior task.",
+ &cmd_thread_list);
+#if 0
+ /* The rest of this support (condition_thread) was not merged. It probably
+ should not be merged in this form, but instead added to the generic GDB
+ thread support. */
+ add_cmd ("break", class_breakpoint, condition_thread,
+ "Breakpoint N will only be effective for thread MID or @SLOT\n\
+ If MID/@SLOT is omitted allow all threads to break at breakpoint",
+ &cmd_thread_list);
+#endif
+ /* Thread command shorthands (for backward compatibility) */
+ add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
+ add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist);
+
+ /* task handling commands */
+
+ add_prefix_cmd ("task", class_stack, task_command,
+ "Generic command for handling debugged task.",
+ &cmd_task_list, "task ", 0, &cmdlist);
+
+ add_com_alias ("ta", "task", class_stack, 1);
+
+ add_cmd ("suspend", class_run, task_suspend_command,
+ "Suspend the inferior task.",
+ &cmd_task_list);
+ add_cmd ("resume", class_run, task_resume_command,
+ "Resume the inferior task.",
+ &cmd_task_list);
+ add_cmd ("info", no_class, task_info_command,
+ "Print information about the specified task.",
+ &cmd_task_list);
+
+ /* Print my message port name */
+
+ add_info ("message-port", message_port_info,
+ "Returns the name of gdb's message port in the netnameserver");
+
+ /* Exception commands */
+
+ add_info ("exceptions", exception_info,
+ "What debugger does when program gets various exceptions.\n\
+Specify an exception number as argument to print info on that\n\
+exception only.");
+
+ add_com ("exception", class_run, exception_command,
+ "Specify how to handle an exception.\n\
+Args are exception number followed by \"forward\" or \"keep\".\n\
+`Forward' means forward the exception to the program's normal exception\n\
+handler.\n\
+`Keep' means reenter debugger if this exception happens, and GDB maps\n\
+the exception to some signal (see info exception)\n\
+Normally \"keep\" is used to return to GDB on exception.");
+}
+
+kern_return_t
+do_mach_notify_dead_name (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{
+ kern_return_t kr = KERN_SUCCESS;
+
+ /* Find the thing that notified */
+ port_chain_t element = port_chain_member (notify_chain, name);
+
+ /* Take name of from unreceived dead name notification list */
+ notify_chain = port_chain_delete (notify_chain, name);
+
+ if (! element)
+ error ("Received a dead name notify from unchained port (0x%x)", name);
+
+ switch (element->type) {
+
+ case MACH_TYPE_THREAD:
+ target_terminal_ours_for_output ();
+ if (name == current_thread)
+ {
+ printf_filtered ("\nCurrent thread %d died", element->mid);
+ current_thread = MACH_PORT_NULL;
+ }
+ else
+ printf_filtered ("\nThread %d died", element->mid);
+
+ break;
+
+ case MACH_TYPE_TASK:
+ target_terminal_ours_for_output ();
+ if (name != inferior_task)
+ printf_filtered ("Task %d died, but it was not the selected task",
+ element->mid);
+ else
+ {
+ printf_filtered ("Current task %d died", element->mid);
+
+ mach_port_destroy (mach_task_self(), name);
+ inferior_task = MACH_PORT_NULL;
+
+ if (notify_chain)
+ warning ("There were still unreceived dead_name_notifications???");
+
+ /* Destroy the old notifications */
+ setup_notify_port (0);
+
+ }
+ break;
+
+ default:
+ error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
+ name, element->type, element->mid);
+ break;
+ }
+
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{
+ warning ("do_mach_notify_msg_accepted : notify %x, name %x",
+ notify, name);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_no_senders (notify, mscount)
+ mach_port_t notify;
+ mach_port_mscount_t mscount;
+{
+ warning ("do_mach_notify_no_senders : notify %x, mscount %x",
+ notify, mscount);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_port_deleted (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{
+ warning ("do_mach_notify_port_deleted : notify %x, name %x",
+ notify, name);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_port_destroyed (notify, rights)
+ mach_port_t notify;
+ mach_port_t rights;
+{
+ warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
+ notify, rights);
+ return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_send_once (notify)
+ mach_port_t notify;
+{
+#ifdef DUMP_SYSCALL
+ /* MANY of these are generated. */
+ warning ("do_mach_notify_send_once : notify %x",
+ notify);
+#endif
+ return KERN_SUCCESS;
+}
+
+/* Kills the inferior. It's gone when you call this */
+static void
+kill_inferior_fast ()
+{
+ WAITTYPE w;
+
+ if (inferior_pid == 0 || inferior_pid == 1)
+ return;
+
+ /* kill() it, since the Unix server does not otherwise notice when
+ * killed with task_terminate().
+ */
+ if (inferior_pid > 0)
+ kill (inferior_pid, SIGKILL);
+
+ /* It's propably terminate already */
+ (void) task_terminate (inferior_task);
+
+ inferior_task = MACH_PORT_NULL;
+ current_thread = MACH_PORT_NULL;
+
+ wait3 (&w, WNOHANG, 0);
+
+ setup_notify_port (0);
+}
+
+static void
+m3_kill_inferior ()
+{
+ kill_inferior_fast ();
+ target_mourn_inferior ();
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+m3_mourn_inferior ()
+{
+ unpush_target (&m3_ops);
+ generic_mourn_inferior ();
+}
+
+
+/* Fork an inferior process, and start debugging it. */
+
+static void
+m3_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL);
+ /* We are at the first instruction we care about. */
+ /* Pedal to the metal... */
+ proceed ((CORE_ADDR) -1, 0, 0);
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach"
+ commands. */
+static int
+m3_can_run ()
+{
+ return 1;
+}
+
+/* Mach 3.0 does not need ptrace for anything
+ * Make sure nobody uses it on mach.
+ */
+ptrace (a,b,c,d)
+int a,b,c,d;
+{
+ error ("Lose, Lose! Somebody called ptrace\n");
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+m3_resume (pid, step, signal)
+ int pid;
+ int step;
+ enum target_signal signal;
+{
+ kern_return_t ret;
+
+ if (step)
+ {
+ thread_basic_info_data_t th_info;
+ unsigned int infoCnt = THREAD_BASIC_INFO_COUNT;
+
+ /* There is no point in single stepping when current_thread
+ * is dead.
+ */
+ if (! MACH_PORT_VALID (current_thread))
+ error ("No thread selected; can not single step");
+
+ /* If current_thread is suspended, tracing it would never return.
+ */
+ ret = thread_info (current_thread,
+ THREAD_BASIC_INFO,
+ (thread_info_t) &th_info,
+ &infoCnt);
+ CHK ("child_resume: can't get thread info", ret);
+
+ if (th_info.suspend_count)
+ error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
+ }
+
+ vm_read_cache_valid = FALSE;
+
+ if (signal && inferior_pid > 0) /* Do not signal, if attached by MID */
+ kill (inferior_pid, target_signal_to_host (signal));
+
+ if (step)
+ {
+ suspend_all_threads (0);
+
+ setup_single_step (current_thread, TRUE);
+
+ ret = thread_resume (current_thread);
+ CHK ("thread_resume", ret);
+ }
+
+ ret = task_resume (inferior_task);
+ if (ret == KERN_FAILURE)
+ warning ("Task was not suspended");
+ else
+ CHK ("Resuming task", ret);
+
+ /* HACK HACK This is needed by the multiserver system HACK HACK */
+ while ((ret = task_resume(inferior_task)) == KERN_SUCCESS)
+ /* make sure it really runs */;
+ /* HACK HACK This is needed by the multiserver system HACK HACK */
+}
+
+#ifdef ATTACH_DETACH
+
+/* Start debugging the process with the given task */
+void
+task_attach (tid)
+ task_t tid;
+{
+ kern_return_t ret;
+ inferior_task = tid;
+
+ ret = task_suspend (inferior_task);
+ CHK("task_attach: task_suspend", ret);
+
+ must_suspend_thread = 0;
+
+ setup_notify_port (1);
+
+ request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
+
+ setup_exception_port ();
+
+ emulator_present = have_emulator_p (inferior_task);
+
+ attach_flag = 1;
+}
+
+/* Well, we can call error also here and leave the
+ * target stack inconsistent. Sigh.
+ * Fix this sometime (the only way to fail here is that
+ * the task has no threads at all, which is rare, but
+ * possible; or if the target task has died, which is also
+ * possible, but unlikely, since it has been suspended.
+ * (Someone must have killed it))
+ */
+void
+attach_to_thread ()
+{
+ if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
+ error ("Could not select any threads to attach to");
+}
+
+mid_attach (mid)
+ int mid;
+{
+ kern_return_t ret;
+
+ ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
+ CHK("mid_attach: machid_mach_port", ret);
+
+ task_attach (inferior_task);
+
+ return mid;
+}
+
+/*
+ * Start debugging the process whose unix process-id is PID.
+ * A negative "pid" value is legal and signifies a mach_id not a unix pid.
+ *
+ * Prevent (possible unwanted) dangerous operations by enabled users
+ * like "atta 0" or "atta foo" (equal to the previous :-) and
+ * "atta pidself". Anyway, the latter is allowed by specifying a MID.
+ */
+static int
+m3_do_attach (pid)
+ int pid;
+{
+ kern_return_t ret;
+
+ if (pid == 0)
+ error("MID=0, Debugging the master unix server does not compute");
+
+ /* Foo. This assumes gdb has a unix pid */
+ if (pid == getpid())
+ error ("I will debug myself only by mid. (Gdb would suspend itself!)");
+
+ if (pid < 0)
+ {
+ mid_attach (-(pid));
+
+ /* inferior_pid will be NEGATIVE! */
+ inferior_pid = pid;
+
+ return inferior_pid;
+ }
+
+ inferior_task = task_by_pid (pid);
+ if (! MACH_PORT_VALID (inferior_task))
+ error("Cannot map Unix pid %d to Mach task port", pid);
+
+ task_attach (inferior_task);
+
+ inferior_pid = pid;
+
+ return inferior_pid;
+}
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+static void
+m3_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+ int pid;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ pid = atoi (args);
+
+ if (pid == getpid()) /* Trying to masturbate? */
+ error ("I refuse to debug myself!");
+
+ if (from_tty)
+ {
+ exec_file = (char *) get_exec_file (0);
+
+ 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));
+
+ gdb_flush (gdb_stdout);
+ }
+
+ m3_do_attach (pid);
+ inferior_pid = pid;
+ push_target (&m3_ops);
+}
+
+void
+deallocate_inferior_ports ()
+{
+ kern_return_t ret;
+ thread_array_t thread_list;
+ int thread_count, index;
+
+ if (!MACH_PORT_VALID (inferior_task))
+ return;
+
+ ret = task_threads (inferior_task, &thread_list, &thread_count);
+ if (ret != KERN_SUCCESS)
+ {
+ warning ("deallocate_inferior_ports: task_threads",
+ mach_error_string(ret));
+ return;
+ }
+
+ /* Get rid of send rights to task threads */
+ for (index = 0; index < thread_count; index++)
+ {
+ int rights;
+ ret = mach_port_get_refs (mach_task_self (),
+ thread_list[index],
+ MACH_PORT_RIGHT_SEND,
+ &rights);
+ CHK("deallocate_inferior_ports: get refs", ret);
+
+ if (rights > 0)
+ {
+ ret = mach_port_mod_refs (mach_task_self (),
+ thread_list[index],
+ MACH_PORT_RIGHT_SEND,
+ -rights);
+ CHK("deallocate_inferior_ports: mod refs", ret);
+ }
+ }
+
+ ret = mach_port_mod_refs (mach_task_self (),
+ inferior_exception_port,
+ MACH_PORT_RIGHT_RECEIVE,
+ -1);
+ CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
+
+ ret = mach_port_deallocate (mach_task_self (),
+ inferior_task);
+ CHK ("deallocate_task_port: deallocating inferior_task", ret);
+
+ current_thread = MACH_PORT_NULL;
+ inferior_task = MACH_PORT_NULL;
+}
+
+/* Stop debugging the process whose number is PID
+ and continue it with signal number SIGNAL.
+ SIGNAL = 0 means just continue it. */
+
+static void
+m3_do_detach (signal)
+ int signal;
+{
+ kern_return_t ret;
+
+ MACH_ERROR_NO_INFERIOR;
+
+ if (current_thread != MACH_PORT_NULL)
+ {
+ /* Store the gdb's view of the thread we are deselecting
+ * before we detach.
+ * @@ I am really not sure if this is ever needeed.
+ */
+ target_prepare_to_store ();
+ target_store_registers (-1);
+ }
+
+ ret = task_set_special_port (inferior_task,
+ TASK_EXCEPTION_PORT,
+ inferior_old_exception_port);
+ CHK ("task_set_special_port", ret);
+
+ /* Discard all requested notifications */
+ setup_notify_port (0);
+
+ if (remove_breakpoints ())
+ warning ("Could not remove breakpoints when detaching");
+
+ if (signal && inferior_pid > 0)
+ kill (inferior_pid, signal);
+
+ /* the task might be dead by now */
+ (void) task_resume (inferior_task);
+
+ deallocate_inferior_ports ();
+
+ attach_flag = 0;
+}
+
+/* Take a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We'd better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via fork. */
+
+static void
+m3_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ 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);
+
+ m3_do_detach (siggnal);
+ inferior_pid = 0;
+ unpush_target (&m3_ops); /* Pop out of handling an inferior */
+}
+#endif /* ATTACH_DETACH */
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+m3_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+m3_files_info (ignore)
+ struct target_ops *ignore;
+{
+ /* FIXME: should print MID and all that crap. */
+ printf_unfiltered ("\tUsing the running image of %s %s.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+static void
+m3_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+#ifdef DUMP_SYSCALL
+#ifdef __STDC__
+#define STR(x) #x
+#else
+#define STR(x) "x"
+#endif
+
+char *bsd1_names[] = {
+ "execve",
+ "fork",
+ "take_signal",
+ "sigreturn",
+ "getrusage",
+ "chdir",
+ "chroot",
+ "open",
+ "creat",
+ "mknod",
+ "link",
+ "symlink",
+ "unlink",
+ "access",
+ "stat",
+ "readlink",
+ "chmod",
+ "chown",
+ "utimes",
+ "truncate",
+ "rename",
+ "mkdir",
+ "rmdir",
+ "xutimes",
+ "mount",
+ "umount",
+ "acct",
+ "setquota",
+ "write_short",
+ "write_long",
+ "send_short",
+ "send_long",
+ "sendto_short",
+ "sendto_long",
+ "select",
+ "task_by_pid",
+ "recvfrom_short",
+ "recvfrom_long",
+ "setgroups",
+ "setrlimit",
+ "sigvec",
+ "sigstack",
+ "settimeofday",
+ "adjtime",
+ "setitimer",
+ "sethostname",
+ "bind",
+ "accept",
+ "connect",
+ "setsockopt",
+ "getsockopt",
+ "getsockname",
+ "getpeername",
+ "init_process",
+ "table_set",
+ "table_get",
+ "pioctl",
+ "emulator_error",
+ "readwrite",
+ "share_wakeup",
+ 0,
+ "maprw_request_it",
+ "maprw_release_it",
+ "maprw_remap",
+ "pid_by_task",
+};
+
+int bsd1_nnames = sizeof(bsd1_names)/sizeof(bsd1_names[0]);
+
+char*
+name_str(name,buf)
+
+int name;
+char *buf;
+
+{
+ switch (name) {
+ case MACH_MSG_TYPE_BOOLEAN:
+ return "boolean";
+ case MACH_MSG_TYPE_INTEGER_16:
+ return "short";
+ case MACH_MSG_TYPE_INTEGER_32:
+ return "long";
+ case MACH_MSG_TYPE_CHAR:
+ return "char";
+ case MACH_MSG_TYPE_BYTE:
+ return "byte";
+ case MACH_MSG_TYPE_REAL:
+ return "real";
+ case MACH_MSG_TYPE_STRING:
+ return "string";
+ default:
+ sprintf(buf,"%d",name);
+ return buf;
+ }
+}
+
+char *
+id_str(id,buf)
+
+int id;
+char *buf;
+
+{
+ char *p;
+ if (id >= 101000 && id < 101000+bsd1_nnames) {
+ if (p = bsd1_names[id-101000])
+ return p;
+ }
+ if (id == 102000)
+ return "psignal_retry";
+ if (id == 100000)
+ return "syscall";
+ sprintf(buf,"%d",id);
+ return buf;
+}
+
+print_msg(mp)
+mach_msg_header_t *mp;
+{
+ char *fmt_x = "%20s : 0x%08x\n";
+ char *fmt_d = "%20s : %10d\n";
+ char *fmt_s = "%20s : %s\n";
+ char buf[100];
+
+ puts_filtered ("\n");
+#define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
+ pr(fmt_x,(*mp),msgh_bits);
+ pr(fmt_d,(*mp),msgh_size);
+ pr(fmt_x,(*mp),msgh_remote_port);
+ pr(fmt_x,(*mp),msgh_local_port);
+ pr(fmt_d,(*mp),msgh_kind);
+ printf_filtered(fmt_s,STR(msgh_id),id_str(mp->msgh_id,buf));
+
+ if (debug_level > 1)
+ {
+ char *p,*ep,*dp;
+ int plen;
+ p = (char*)mp;
+ ep = p+mp->msgh_size;
+ p += sizeof(*mp);
+ for(; p < ep; p += plen) {
+ mach_msg_type_t *tp;
+ mach_msg_type_long_t *tlp;
+ int name,size,number;
+ tp = (mach_msg_type_t*)p;
+ if (tp->msgt_longform) {
+ tlp = (mach_msg_type_long_t*)tp;
+ name = tlp->msgtl_name;
+ size = tlp->msgtl_size;
+ number = tlp->msgtl_number;
+ plen = sizeof(*tlp);
+ } else {
+ name = tp->msgt_name;
+ size = tp->msgt_size;
+ number = tp->msgt_number;
+ plen = sizeof(*tp);
+ }
+ printf_filtered("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
+ name_str(name,buf),size,number,tp->msgt_inline,
+ tp->msgt_longform, tp->msgt_deallocate);
+ dp = p+plen;
+ if (tp->msgt_inline) {
+ int l;
+ l = size*number/8;
+ l = (l+sizeof(long)-1)&~((sizeof(long))-1);
+ plen += l;
+ print_data(dp,size,number);
+ } else {
+ plen += sizeof(int*);
+ }
+ printf_filtered("plen=%d\n",plen);
+ }
+ }
+}
+
+print_data(p,size,number)
+
+char *p;
+
+{
+ int *ip;
+ short *sp;
+ int i;
+
+ switch (size) {
+ case 8:
+ for(i = 0; i < number; i++) {
+ printf_filtered(" %02x",p[i]);
+ }
+ break;
+ case 16:
+ sp = (short*)p;
+ for(i = 0; i < number; i++) {
+ printf_filtered(" %04x",sp[i]);
+ }
+ break;
+ case 32:
+ ip = (int*)p;
+ for(i = 0; i < number; i++) {
+ printf_filtered(" %08x",ip[i]);
+ }
+ break;
+ }
+ puts_filtered("\n");
+}
+#endif DUMP_SYSCALL
+
+static void
+m3_stop ()
+{
+ error ("to_stop target function not implemented");
+}
+
+struct target_ops m3_ops = {
+ "mach", /* to_shortname */
+ "Mach child process", /* to_longname */
+ "Mach child process (started by the \"run\" command).", /* to_doc */
+ m3_open, /* to_open */
+ 0, /* to_close */
+ m3_attach, /* to_attach */
+ m3_detach, /* to_detach */
+ m3_resume, /* to_resume */
+ mach_really_wait, /* to_wait */
+ fetch_inferior_registers, /* to_fetch_registers */
+ store_inferior_registers, /* to_store_registers */
+ m3_prepare_to_store, /* to_prepare_to_store */
+ m3_xfer_memory, /* to_xfer_memory */
+ m3_files_info, /* to_files_info */
+ memory_insert_breakpoint, /* to_insert_breakpoint */
+ memory_remove_breakpoint, /* to_remove_breakpoint */
+ terminal_init_inferior, /* to_terminal_init */
+ terminal_inferior, /* to_terminal_inferior */
+ terminal_ours_for_output, /* to_terminal_ours_for_output */
+ terminal_ours, /* to_terminal_ours */
+ child_terminal_info, /* to_terminal_info */
+ m3_kill_inferior, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+
+ m3_create_inferior, /* to_create_inferior */
+ m3_mourn_inferior, /* to_mourn_inferior */
+ m3_can_run, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ m3_stop, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_m3_nat ()
+{
+ kern_return_t ret;
+
+ add_target (&m3_ops);
+
+ ret = mach_port_allocate(mach_task_self(),
+ MACH_PORT_RIGHT_PORT_SET,
+ &inferior_wait_port_set);
+ if (ret != KERN_SUCCESS)
+ fatal("initial port set %s",mach_error_string(ret));
+
+ /* mach_really_wait now waits for this */
+ currently_waiting_for = inferior_wait_port_set;
+
+ ret = netname_look_up(name_server_port, hostname, "MachID", &mid_server);
+ if (ret != KERN_SUCCESS)
+ {
+ mid_server = MACH_PORT_NULL;
+
+ warning ("initialize machid: netname_lookup_up(MachID) : %s",
+ mach_error_string(ret));
+ warning ("Some (most?) features disabled...");
+ }
+
+ mid_auth = mach_privileged_host_port();
+ if (mid_auth == MACH_PORT_NULL)
+ mid_auth = mach_task_self();
+
+ obstack_init (port_chain_obstack);
+
+ ret = mach_port_allocate (mach_task_self (),
+ MACH_PORT_RIGHT_RECEIVE,
+ &thread_exception_port);
+ CHK ("Creating thread_exception_port for single stepping", ret);
+
+ ret = mach_port_insert_right (mach_task_self (),
+ thread_exception_port,
+ thread_exception_port,
+ MACH_MSG_TYPE_MAKE_SEND);
+ CHK ("Inserting send right to thread_exception_port", ret);
+
+ /* Allocate message port */
+ ret = mach_port_allocate (mach_task_self (),
+ MACH_PORT_RIGHT_RECEIVE,
+ &our_message_port);
+ if (ret != KERN_SUCCESS)
+ warning ("Creating message port %s", mach_error_string (ret));
+ else
+ {
+ char buf[ MAX_NAME_LEN ];
+ ret = mach_port_move_member(mach_task_self (),
+ our_message_port,
+ inferior_wait_port_set);
+ if (ret != KERN_SUCCESS)
+ warning ("message move member %s", mach_error_string (ret));
+
+
+ /* @@@@ No way to change message port name currently */
+ /* Foo. This assumes gdb has a unix pid */
+ sprintf (buf, "gdb-%d", getpid ());
+ gdb_register_port (buf, our_message_port);
+ }
+
+ /* Heap for thread commands */
+ obstack_init (cproc_obstack);
+
+ add_mach_specific_commands ();
+}
diff --git a/contrib/gdb/gdb/m68k-stub.c b/contrib/gdb/gdb/m68k-stub.c
new file mode 100644
index 0000000..009cba3
--- /dev/null
+++ b/contrib/gdb/gdb/m68k-stub.c
@@ -0,0 +1,1014 @@
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
+ *
+ * Module name: remcom.c $
+ * Revision: 1.34 $
+ * Date: 91/03/09 12:29:49 $
+ * Contributor: Lake Stevens Instrument Division$
+ *
+ * Description: low level support for gdb debugger. $
+ *
+ * Considerations: only works on target hardware $
+ *
+ * Written by: Glenn Engel $
+ * ModuleState: Experimental $
+ *
+ * NOTES: See Below $
+ *
+ * To enable debugger support, two things need to happen. One, a
+ * call to set_debug_traps() is necessary in order to allow any breakpoints
+ * or error conditions to be properly intercepted and reported to gdb.
+ * Two, a breakpoint needs to be generated to begin communication. This
+ * is most easily accomplished by a call to breakpoint(). Breakpoint()
+ * simulates a breakpoint by executing a trap #1. The breakpoint instruction
+ * is hardwired to trap #1 because not to do so is a compatibility problem--
+ * there either should be a standard breakpoint instruction, or the protocol
+ * should be extended to provide some means to communicate which breakpoint
+ * instruction is in use (or have the stub insert the breakpoint).
+ *
+ * Some explanation is probably necessary to explain how exceptions are
+ * handled. When an exception is encountered the 68000 pushes the current
+ * program counter and status register onto the supervisor stack and then
+ * transfers execution to a location specified in it's vector table.
+ * The handlers for the exception vectors are hardwired to jmp to an address
+ * given by the relation: (exception - 256) * 6. These are decending
+ * addresses starting from -6, -12, -18, ... By allowing 6 bytes for
+ * each entry, a jsr, jmp, bsr, ... can be used to enter the exception
+ * handler. Using a jsr to handle an exception has an added benefit of
+ * allowing a single handler to service several exceptions and use the
+ * return address as the key differentiation. The vector number can be
+ * computed from the return address by [ exception = (addr + 1530) / 6 ].
+ * The sole purpose of the routine _catchException is to compute the
+ * exception number and push it on the stack in place of the return address.
+ * The external function exceptionHandler() is
+ * used to attach a specific handler to a specific m68k exception.
+ * For 68020 machines, the ability to have a return address around just
+ * so the vector can be determined is not necessary because the '020 pushes an
+ * extra word onto the stack containing the vector offset
+ *
+ * Because gdb will sometimes write to the stack area to execute function
+ * calls, this program cannot rely on using the supervisor stack so it
+ * uses it's own stack area reserved in the int array remcomStack.
+ *
+ *************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <setjmp.h>
+
+/************************************************************************
+ *
+ * external low-level support routines
+ */
+typedef void (*ExceptionHook)(int); /* pointer to function with int parm */
+typedef void (*Function)(); /* pointer to a function */
+
+extern putDebugChar(); /* write a single character */
+extern getDebugChar(); /* read and return a single char */
+
+extern Function exceptionHandler(); /* assign an exception handler */
+extern ExceptionHook exceptionHook; /* hook variable for errors/exceptions */
+
+/************************/
+/* FORWARD DECLARATIONS */
+/************************/
+static void
+initializeRemcomErrorFrame ();
+
+/************************************************************************/
+/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/
+/* at least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX 400
+
+static char initialized; /* boolean flag. != 0 means we've been initialized */
+
+int remote_debug;
+/* debug > 0 prints ill-formed commands in valid packets & checksum errors */
+
+static const char hexchars[]="0123456789abcdef";
+
+/* there are 180 bytes of registers on a 68020 w/68881 */
+/* many of the fpa registers are 12 byte (96 bit) registers */
+#define NUMREGBYTES 180
+enum regnames {D0,D1,D2,D3,D4,D5,D6,D7,
+ A0,A1,A2,A3,A4,A5,A6,A7,
+ PS,PC,
+ FP0,FP1,FP2,FP3,FP4,FP5,FP6,FP7,
+ FPCONTROL,FPSTATUS,FPIADDR
+ };
+
+
+/* We keep a whole frame cache here. "Why?", I hear you cry, "doesn't
+ GDB handle that sort of thing?" Well, yes, I believe the only
+ reason for this cache is to save and restore floating point state
+ (fsave/frestore). A cleaner way to do this would be to make the
+ fsave data part of the registers which GDB deals with like any
+ other registers. This should not be a performance problem if the
+ ability to read individual registers is added to the protocol. */
+
+typedef struct FrameStruct
+{
+ struct FrameStruct *previous;
+ int exceptionPC; /* pc value when this frame created */
+ int exceptionVector; /* cpu vector causing exception */
+ short frameSize; /* size of cpu frame in words */
+ short sr; /* for 68000, this not always sr */
+ int pc;
+ short format;
+ int fsaveHeader;
+ int morejunk[0]; /* exception frame, fp save... */
+} Frame;
+
+#define FRAMESIZE 500
+int gdbFrameStack[FRAMESIZE];
+static Frame *lastFrame;
+
+/*
+ * these should not be static cuz they can be used outside this module
+ */
+int registers[NUMREGBYTES/4];
+int superStack;
+
+#define STACKSIZE 10000
+int remcomStack[STACKSIZE/sizeof(int)];
+static int* stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+/*
+ * In many cases, the system will want to continue exception processing
+ * when a continue command is given.
+ * oldExceptionHook is a function to invoke in this case.
+ */
+
+static ExceptionHook oldExceptionHook;
+
+#ifdef mc68020
+/* the size of the exception stack on the 68020 varies with the type of
+ * exception. The following table is the number of WORDS used
+ * for each exception format.
+ */
+const short exceptionSize[] = { 4,4,6,4,4,4,4,4,29,10,16,46,12,4,4,4 };
+#endif
+
+#ifdef mc68332
+static const short exceptionSize[] = { 4,4,6,4,4,4,4,4,4,4,4,4,16,4,4,4 };
+#endif
+
+/************* jump buffer used for setjmp/longjmp **************************/
+jmp_buf remcomEnv;
+
+/*************************** ASSEMBLY CODE MACROS *************************/
+/* */
+
+#ifdef __HAVE_68881__
+/* do an fsave, then remember the address to begin a restore from */
+#define SAVE_FP_REGS() asm(" fsave a0@-"); \
+ asm(" fmovemx fp0-fp7,_registers+72"); \
+ asm(" fmoveml fpcr/fpsr/fpi,_registers+168");
+#define RESTORE_FP_REGS() \
+asm(" \n\
+ fmoveml _registers+168,fpcr/fpsr/fpi \n\
+ fmovemx _registers+72,fp0-fp7 \n\
+ cmpl #-1,a0@ | skip frestore flag set ? \n\
+ beq skip_frestore \n\
+ frestore a0@+ \n\
+skip_frestore: \n\
+");
+
+#else
+#define SAVE_FP_REGS()
+#define RESTORE_FP_REGS()
+#endif /* __HAVE_68881__ */
+
+void return_to_super();
+void return_to_user();
+
+asm("
+.text
+.globl _return_to_super
+_return_to_super:
+ movel _registers+60,sp /* get new stack pointer */
+ movel _lastFrame,a0 /* get last frame info */
+ bra return_to_any
+
+.globl _return_to_user
+_return_to_user:
+ movel _registers+60,a0 /* get usp */
+ movel a0,usp /* set usp */
+ movel _superStack,sp /* get original stack pointer */
+
+return_to_any:
+ movel _lastFrame,a0 /* get last frame info */
+ movel a0@+,_lastFrame /* link in previous frame */
+ addql #8,a0 /* skip over pc, vector#*/
+ movew a0@+,d0 /* get # of words in cpu frame */
+ addw d0,a0 /* point to end of data */
+ addw d0,a0 /* point to end of data */
+ movel a0,a1
+#
+# copy the stack frame
+ subql #1,d0
+copyUserLoop:
+ movew a1@-,sp@-
+ dbf d0,copyUserLoop
+");
+ RESTORE_FP_REGS()
+ asm(" moveml _registers,d0-d7/a0-a6");
+ asm(" rte"); /* pop and go! */
+
+#define DISABLE_INTERRUPTS() asm(" oriw #0x0700,sr");
+#define BREAKPOINT() asm(" trap #1");
+
+/* this function is called immediately when a level 7 interrupt occurs */
+/* if the previous interrupt level was 7 then we're already servicing */
+/* this interrupt and an rte is in order to return to the debugger. */
+/* For the 68000, the offset for sr is 6 due to the jsr return address */
+asm("
+.text
+.globl __debug_level7
+__debug_level7:
+ movew d0,sp@-");
+#if defined (mc68020) || defined (mc68332)
+asm(" movew sp@(2),d0");
+#else
+asm(" movew sp@(6),d0");
+#endif
+asm(" andiw #0x700,d0
+ cmpiw #0x700,d0
+ beq _already7
+ movew sp@+,d0
+ bra __catchException
+_already7:
+ movew sp@+,d0");
+#if !defined (mc68020) && !defined (mc68332)
+asm(" lea sp@(4),sp"); /* pull off 68000 return address */
+#endif
+asm(" rte");
+
+extern void _catchException ();
+
+#if defined (mc68020) || defined (mc68332)
+/* This function is called when a 68020 exception occurs. It saves
+ * all the cpu and fpcp regs in the _registers array, creates a frame on a
+ * linked list of frames which has the cpu and fpcp stack frames needed
+ * to properly restore the context of these processors, and invokes
+ * an exception handler (remcom_handler).
+ *
+ * stack on entry: stack on exit:
+ * N bytes of junk exception # MSWord
+ * Exception Format Word exception # MSWord
+ * Program counter LSWord
+ * Program counter MSWord
+ * Status Register
+ *
+ *
+ */
+asm("
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+ moveml d0-d7/a0-a6,_registers /* save registers */
+ movel _lastFrame,a0 /* last frame pointer */
+");
+SAVE_FP_REGS();
+asm("
+ lea _registers,a5 /* get address of registers */
+ movew sp@,d1 /* get status register */
+ movew d1,a5@(66) /* save sr */
+ movel sp@(2),a4 /* save pc in a4 for later use */
+ movel a4,a5@(68) /* save pc in _regisers[] */
+
+#
+# figure out how many bytes in the stack frame
+ movew sp@(6),d0 /* get '020 exception format */
+ movew d0,d2 /* make a copy of format word */
+ andiw #0xf000,d0 /* mask off format type */
+ rolw #5,d0 /* rotate into the low byte *2 */
+ lea _exceptionSize,a1
+ addw d0,a1 /* index into the table */
+ movew a1@,d0 /* get number of words in frame */
+ movew d0,d3 /* save it */
+ subw d0,a0 /* adjust save pointer */
+ subw d0,a0 /* adjust save pointer(bytes) */
+ movel a0,a1 /* copy save pointer */
+ subql #1,d0 /* predecrement loop counter */
+#
+# copy the frame
+saveFrameLoop:
+ movew sp@+,a1@+
+ dbf d0,saveFrameLoop
+#
+# now that the stack has been clenaed,
+# save the a7 in use at time of exception
+ movel sp,_superStack /* save supervisor sp */
+ andiw #0x2000,d1 /* were we in supervisor mode ? */
+ beq userMode
+ movel a7,a5@(60) /* save a7 */
+ bra a7saveDone
+userMode:
+ movel usp,a1
+ movel a1,a5@(60) /* save user stack pointer */
+a7saveDone:
+
+#
+# save size of frame
+ movew d3,a0@-
+
+#
+# compute exception number
+ andl #0xfff,d2 /* mask off vector offset */
+ lsrw #2,d2 /* divide by 4 to get vect num */
+ movel d2,a0@- /* save it */
+#
+# save pc causing exception
+ movel a4,a0@-
+#
+# save old frame link and set the new value
+ movel _lastFrame,a1 /* last frame pointer */
+ movel a1,a0@- /* save pointer to prev frame */
+ movel a0,_lastFrame
+
+ movel d2,sp@- /* push exception num */
+ movel _exceptionHook,a0 /* get address of handler */
+ jbsr a0@ /* and call it */
+ clrl sp@ /* replace exception num parm with frame ptr */
+ jbsr __returnFromException /* jbsr, but never returns */
+");
+#else /* mc68000 */
+/* This function is called when an exception occurs. It translates the
+ * return address found on the stack into an exception vector # which
+ * is then handled by either handle_exception or a system handler.
+ * _catchException provides a front end for both.
+ *
+ * stack on entry: stack on exit:
+ * Program counter MSWord exception # MSWord
+ * Program counter LSWord exception # MSWord
+ * Status Register
+ * Return Address MSWord
+ * Return Address LSWord
+ */
+asm("
+.text
+.globl __catchException
+__catchException:");
+DISABLE_INTERRUPTS();
+asm("
+ moveml d0-d7/a0-a6,_registers /* save registers */
+ movel _lastFrame,a0 /* last frame pointer */
+");
+SAVE_FP_REGS();
+asm("
+ lea _registers,a5 /* get address of registers */
+ movel sp@+,d2 /* pop return address */
+ addl #1530,d2 /* convert return addr to */
+ divs #6,d2 /* exception number */
+ extl d2
+
+ moveql #3,d3 /* assume a three word frame */
+
+ cmpiw #3,d2 /* bus error or address error ? */
+ bgt normal /* if >3 then normal error */
+ movel sp@+,a0@- /* copy error info to frame buff*/
+ movel sp@+,a0@- /* these are never used */
+ moveql #7,d3 /* this is a 7 word frame */
+
+normal:
+ movew sp@+,d1 /* pop status register */
+ movel sp@+,a4 /* pop program counter */
+ movew d1,a5@(66) /* save sr */
+ movel a4,a5@(68) /* save pc in _regisers[] */
+ movel a4,a0@- /* copy pc to frame buffer */
+ movew d1,a0@- /* copy sr to frame buffer */
+
+ movel sp,_superStack /* save supervisor sp */
+
+ andiw #0x2000,d1 /* were we in supervisor mode ? */
+ beq userMode
+ movel a7,a5@(60) /* save a7 */
+ bra saveDone
+userMode:
+ movel usp,a1 /* save user stack pointer */
+ movel a1,a5@(60) /* save user stack pointer */
+saveDone:
+
+ movew d3,a0@- /* push frame size in words */
+ movel d2,a0@- /* push vector number */
+ movel a4,a0@- /* push exception pc */
+
+#
+# save old frame link and set the new value
+ movel _lastFrame,a1 /* last frame pointer */
+ movel a1,a0@- /* save pointer to prev frame */
+ movel a0,_lastFrame
+
+ movel d2,sp@- /* push exception num */
+ movel _exceptionHook,a0 /* get address of handler */
+ jbsr a0@ /* and call it */
+ clrl sp@ /* replace exception num parm with frame ptr */
+ jbsr __returnFromException /* jbsr, but never returns */
+");
+#endif
+
+
+/*
+ * remcomHandler is a front end for handle_exception. It moves the
+ * stack pointer into an area reserved for debugger use in case the
+ * breakpoint happened in supervisor mode.
+ */
+asm("_remcomHandler:");
+asm(" addl #4,sp"); /* pop off return address */
+asm(" movel sp@+,d0"); /* get the exception number */
+asm(" movel _stackPtr,sp"); /* move to remcom stack area */
+asm(" movel d0,sp@-"); /* push exception onto stack */
+asm(" jbsr _handle_exception"); /* this never returns */
+asm(" rts"); /* return */
+
+void _returnFromException( Frame *frame )
+{
+ /* if no passed in frame, use the last one */
+ if (! frame)
+ {
+ frame = lastFrame;
+ frame->frameSize = 4;
+ frame->format = 0;
+ frame->fsaveHeader = -1; /* restore regs, but we dont have fsave info*/
+ }
+
+#if !defined (mc68020) && !defined (mc68332)
+ /* a 68000 cannot use the internal info pushed onto a bus error
+ * or address error frame when doing an RTE so don't put this info
+ * onto the stack or the stack will creep every time this happens.
+ */
+ frame->frameSize=3;
+#endif
+
+ /* throw away any frames in the list after this frame */
+ lastFrame = frame;
+
+ frame->sr = registers[(int) PS];
+ frame->pc = registers[(int) PC];
+
+ if (registers[(int) PS] & 0x2000)
+ {
+ /* return to supervisor mode... */
+ return_to_super();
+ }
+ else
+ { /* return to user mode */
+ return_to_user();
+ }
+}
+
+int hex(ch)
+char ch;
+{
+ if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
+ if ((ch >= '0') && (ch <= '9')) return (ch-'0');
+ if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
+ return (-1);
+}
+
+
+/* scan for the sequence $<data>#<checksum> */
+void getpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ char ch;
+
+ do {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = (getDebugChar() & 0x7f)) != '$');
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX) {
+ ch = getDebugChar() & 0x7f;
+ if (ch == '#') break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#') {
+ xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+ xmitcsum += hex(getDebugChar() & 0x7f);
+ if ((remote_debug ) && (checksum != xmitcsum)) {
+ fprintf (stderr,"bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum,xmitcsum,buffer);
+ }
+
+ if (checksum != xmitcsum) putDebugChar('-'); /* failed checksum */
+ else {
+ putDebugChar('+'); /* successful transfer */
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':') {
+ putDebugChar( buffer[0] );
+ putDebugChar( buffer[1] );
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++) buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ } while (checksum != xmitcsum);
+
+}
+
+/* send the packet in buffer. The host get's one chance to read it.
+ This routine does not wait for a positive acknowledge. */
+
+
+void putpacket(buffer)
+char * buffer;
+{
+ unsigned char checksum;
+ int count;
+ char ch;
+
+ /* $<packet info>#<checksum>. */
+ do {
+ putDebugChar('$');
+ checksum = 0;
+ count = 0;
+
+ while (ch=buffer[count]) {
+ if (! putDebugChar(ch)) return;
+ checksum += ch;
+ count += 1;
+ }
+
+ putDebugChar('#');
+ putDebugChar(hexchars[checksum >> 4]);
+ putDebugChar(hexchars[checksum % 16]);
+
+ } while (1 == 0); /* (getDebugChar() != '+'); */
+
+}
+
+char remcomInBuffer[BUFMAX];
+char remcomOutBuffer[BUFMAX];
+static short error;
+
+
+void debug_error(format, parm)
+char * format;
+char * parm;
+{
+ if (remote_debug) fprintf (stderr,format,parm);
+}
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+char* mem2hex(mem, buf, count)
+char* mem;
+char* buf;
+int count;
+{
+ int i;
+ unsigned char ch;
+ for (i=0;i<count;i++) {
+ ch = *mem++;
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+char* hex2mem(buf, mem, count)
+char* buf;
+char* mem;
+int count;
+{
+ int i;
+ unsigned char ch;
+ for (i=0;i<count;i++) {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ *mem++ = ch;
+ }
+ return(mem);
+}
+
+/* a bus error has occurred, perform a longjmp
+ to return execution and allow handling of the error */
+
+void handle_buserror()
+{
+ longjmp(remcomEnv,1);
+}
+
+/* this function takes the 68000 exception number and attempts to
+ translate this number into a unix compatible signal value */
+int computeSignal( exceptionVector )
+int exceptionVector;
+{
+ int sigval;
+ switch (exceptionVector) {
+ case 2 : sigval = 10; break; /* bus error */
+ case 3 : sigval = 10; break; /* address error */
+ case 4 : sigval = 4; break; /* illegal instruction */
+ case 5 : sigval = 8; break; /* zero divide */
+ case 6 : sigval = 8; break; /* chk instruction */
+ case 7 : sigval = 8; break; /* trapv instruction */
+ case 8 : sigval = 11; break; /* privilege violation */
+ case 9 : sigval = 5; break; /* trace trap */
+ case 10: sigval = 4; break; /* line 1010 emulator */
+ case 11: sigval = 4; break; /* line 1111 emulator */
+
+ /* Coprocessor protocol violation. Using a standard MMU or FPU
+ this cannot be triggered by software. Call it a SIGBUS. */
+ case 13: sigval = 10; break;
+
+ case 31: sigval = 2; break; /* interrupt */
+ case 33: sigval = 5; break; /* breakpoint */
+
+ /* This is a trap #8 instruction. Apparently it is someone's software
+ convention for some sort of SIGFPE condition. Whose? How many
+ people are being screwed by having this code the way it is?
+ Is there a clean solution? */
+ case 40: sigval = 8; break; /* floating point err */
+
+ case 48: sigval = 8; break; /* floating point err */
+ case 49: sigval = 8; break; /* floating point err */
+ case 50: sigval = 8; break; /* zero divide */
+ case 51: sigval = 8; break; /* underflow */
+ case 52: sigval = 8; break; /* operand error */
+ case 53: sigval = 8; break; /* overflow */
+ case 54: sigval = 8; break; /* NAN */
+ default:
+ sigval = 7; /* "software generated"*/
+ }
+ return (sigval);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+int hexToInt(char **ptr, int *intValue)
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue >=0)
+ {
+ *intValue = (*intValue <<4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/*
+ * This function does all command procesing for interfacing to gdb.
+ */
+void handle_exception(int exceptionVector)
+{
+ int sigval;
+ int addr, length;
+ char * ptr;
+ int newPC;
+ Frame *frame;
+
+ if (remote_debug) printf("vector=%d, sr=0x%x, pc=0x%x\n",
+ exceptionVector,
+ registers[ PS ],
+ registers[ PC ]);
+
+ /* reply to host that an exception has occurred */
+ sigval = computeSignal( exceptionVector );
+ remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+
+ putpacket(remcomOutBuffer);
+
+ while (1==1) {
+ error = 0;
+ remcomOutBuffer[0] = 0;
+ getpacket(remcomInBuffer);
+ switch (remcomInBuffer[0]) {
+ case '?' : remcomOutBuffer[0] = 'S';
+ remcomOutBuffer[1] = hexchars[sigval >> 4];
+ remcomOutBuffer[2] = hexchars[sigval % 16];
+ remcomOutBuffer[3] = 0;
+ break;
+ case 'd' : remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g' : /* return the value of the CPU registers */
+ mem2hex((char*) registers, remcomOutBuffer, NUMREGBYTES);
+ break;
+ case 'G' : /* set the value of the CPU registers - return OK */
+ hex2mem(&remcomInBuffer[1], (char*) registers, NUMREGBYTES);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ case 'm' :
+ if (setjmp(remcomEnv) == 0)
+ {
+ exceptionHandler(2,handle_buserror);
+
+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ {
+ ptr = 0;
+ mem2hex((char*) addr, remcomOutBuffer, length);
+ }
+
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E01");
+ debug_error("malformed read memory command: %s",remcomInBuffer);
+ }
+ }
+ else {
+ exceptionHandler(2,_catchException);
+ strcpy(remcomOutBuffer,"E03");
+ debug_error("bus error");
+ }
+
+ /* restore handler for bus error */
+ exceptionHandler(2,_catchException);
+ break;
+
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ case 'M' :
+ if (setjmp(remcomEnv) == 0) {
+ exceptionHandler(2,handle_buserror);
+
+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ if (*(ptr++) == ':')
+ {
+ hex2mem(ptr, (char*) addr, length);
+ ptr = 0;
+ strcpy(remcomOutBuffer,"OK");
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E02");
+ debug_error("malformed write memory command: %s",remcomInBuffer);
+ }
+ }
+ else {
+ exceptionHandler(2,_catchException);
+ strcpy(remcomOutBuffer,"E03");
+ debug_error("bus error");
+ }
+
+ /* restore handler for bus error */
+ exceptionHandler(2,_catchException);
+ break;
+
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ case 'c' :
+ case 's' :
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ registers[ PC ] = addr;
+
+ newPC = registers[ PC];
+
+ /* clear the trace bit */
+ registers[ PS ] &= 0x7fff;
+
+ /* set the trace bit if we're stepping */
+ if (remcomInBuffer[0] == 's') registers[ PS ] |= 0x8000;
+
+ /*
+ * look for newPC in the linked list of exception frames.
+ * if it is found, use the old frame it. otherwise,
+ * fake up a dummy frame in returnFromException().
+ */
+ if (remote_debug) printf("new pc = 0x%x\n",newPC);
+ frame = lastFrame;
+ while (frame)
+ {
+ if (remote_debug)
+ printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+ frame,frame->exceptionPC,
+ frame->exceptionVector);
+ if (frame->exceptionPC == newPC) break; /* bingo! a match */
+ /*
+ * for a breakpoint instruction, the saved pc may
+ * be off by two due to re-executing the instruction
+ * replaced by the trap instruction. Check for this.
+ */
+ if ((frame->exceptionVector == 33) &&
+ (frame->exceptionPC == (newPC+2))) break;
+ if (frame == frame->previous)
+ {
+ frame = 0; /* no match found */
+ break;
+ }
+ frame = frame->previous;
+ }
+
+ /*
+ * If we found a match for the PC AND we are not returning
+ * as a result of a breakpoint (33),
+ * trace exception (9), nmi (31), jmp to
+ * the old exception handler as if this code never ran.
+ */
+ if (frame)
+ {
+ if ((frame->exceptionVector != 9) &&
+ (frame->exceptionVector != 31) &&
+ (frame->exceptionVector != 33))
+ {
+ /*
+ * invoke the previous handler.
+ */
+ if (oldExceptionHook)
+ (*oldExceptionHook) (frame->exceptionVector);
+ newPC = registers[ PC ]; /* pc may have changed */
+ if (newPC != frame->exceptionPC)
+ {
+ if (remote_debug)
+ printf("frame at 0x%x has pc=0x%x, except#=%d\n",
+ frame,frame->exceptionPC,
+ frame->exceptionVector);
+ /* re-use the last frame, we're skipping it (longjump?)*/
+ frame = (Frame *) 0;
+ _returnFromException( frame ); /* this is a jump */
+ }
+ }
+ }
+
+ /* if we couldn't find a frame, create one */
+ if (frame == 0)
+ {
+ frame = lastFrame -1 ;
+
+ /* by using a bunch of print commands with breakpoints,
+ it's possible for the frame stack to creep down. If it creeps
+ too far, give up and reset it to the top. Normal use should
+ not see this happen.
+ */
+ if ((unsigned int) (frame-2) < (unsigned int) &gdbFrameStack)
+ {
+ initializeRemcomErrorFrame();
+ frame = lastFrame;
+ }
+ frame->previous = lastFrame;
+ lastFrame = frame;
+ frame = 0; /* null so _return... will properly initialize it */
+ }
+
+ _returnFromException( frame ); /* this is a jump */
+
+ break;
+
+ /* kill the program */
+ case 'k' : /* do nothing */
+ break;
+ } /* switch */
+
+ /* reply to the request */
+ putpacket(remcomOutBuffer);
+ }
+}
+
+
+void
+initializeRemcomErrorFrame()
+{
+ lastFrame = ((Frame *) &gdbFrameStack[FRAMESIZE-1]) - 1;
+ lastFrame->previous = lastFrame;
+}
+
+/* this function is used to set up exception handlers for tracing and
+ breakpoints */
+void set_debug_traps()
+{
+ extern void _debug_level7();
+ extern void remcomHandler();
+ int exception;
+
+ initializeRemcomErrorFrame();
+ stackPtr = &remcomStack[STACKSIZE/sizeof(int) - 1];
+
+ for (exception = 2; exception <= 23; exception++)
+ exceptionHandler(exception,_catchException);
+
+ /* level 7 interrupt */
+ exceptionHandler(31,_debug_level7);
+
+ /* breakpoint exception (trap #1) */
+ exceptionHandler(33,_catchException);
+
+ /* This is a trap #8 instruction. Apparently it is someone's software
+ convention for some sort of SIGFPE condition. Whose? How many
+ people are being screwed by having this code the way it is?
+ Is there a clean solution? */
+ exceptionHandler(40,_catchException);
+
+ /* 48 to 54 are floating point coprocessor errors */
+ for (exception = 48; exception <= 54; exception++)
+ exceptionHandler(exception,_catchException);
+
+ if (oldExceptionHook != remcomHandler)
+ {
+ oldExceptionHook = exceptionHook;
+ exceptionHook = remcomHandler;
+ }
+
+ initialized = 1;
+
+}
+
+/* This function will generate a breakpoint exception. It is used at the
+ beginning of a program to sync up with a debugger and can be used
+ otherwise as a quick means to stop program execution and "break" into
+ the debugger. */
+
+void breakpoint()
+{
+ if (initialized) BREAKPOINT();
+}
+
diff --git a/contrib/gdb/gdb/m68k-tdep.c b/contrib/gdb/gdb/m68k-tdep.c
new file mode 100644
index 0000000..f5cc3b0
--- /dev/null
+++ b/contrib/gdb/gdb/m68k-tdep.c
@@ -0,0 +1,514 @@
+/* Target dependent code for the Motorola 68000 series.
+ Copyright (C) 1990, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "symtab.h"
+
+
+/* Push an empty stack frame, to record the current PC, etc. */
+
+void
+m68k_push_dummy_frame ()
+{
+ register CORE_ADDR sp = read_register (SP_REGNUM);
+ register int regnum;
+ char raw_buffer[12];
+
+ sp = push_word (sp, read_register (PC_REGNUM));
+ sp = push_word (sp, read_register (FP_REGNUM));
+ write_register (FP_REGNUM, sp);
+
+ /* Always save the floating-point registers, whether they exist on
+ this target or not. */
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--)
+ {
+ read_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
+ sp = push_bytes (sp, raw_buffer, 12);
+ }
+
+ for (regnum = FP_REGNUM - 1; regnum >= 0; regnum--)
+ {
+ sp = push_word (sp, read_register (regnum));
+ }
+ sp = push_word (sp, read_register (PS_REGNUM));
+ write_register (SP_REGNUM, sp);
+}
+
+/* Discard from the stack the innermost frame,
+ restoring all saved registers. */
+
+void
+m68k_pop_frame ()
+{
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR fp;
+ register int regnum;
+ struct frame_saved_regs fsr;
+ struct frame_info *fi;
+ char raw_buffer[12];
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &fsr);
+ for (regnum = FP0_REGNUM + 7 ; regnum >= FP0_REGNUM ; regnum--)
+ {
+ if (fsr.regs[regnum])
+ {
+ read_memory (fsr.regs[regnum], raw_buffer, 12);
+ write_register_bytes (REGISTER_BYTE (regnum), raw_buffer, 12);
+ }
+ }
+ for (regnum = FP_REGNUM - 1 ; regnum >= 0 ; regnum--)
+ {
+ if (fsr.regs[regnum])
+ {
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+ }
+ }
+ if (fsr.regs[PS_REGNUM])
+ {
+ write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4));
+ }
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+ write_register (PC_REGNUM, read_memory_integer (fp + 4, 4));
+ write_register (SP_REGNUM, fp + 8);
+ flush_cached_frames ();
+}
+
+
+/* Given an ip value corresponding to the start of a function,
+ return the ip of the first instruction after the function
+ prologue. This is the generic m68k support. Machines which
+ require something different can override the SKIP_PROLOGUE
+ macro to point elsewhere.
+
+ Some instructions which typically may appear in a function
+ prologue include:
+
+ A link instruction, word form:
+
+ link.w %a6,&0 4e56 XXXX
+
+ A link instruction, long form:
+
+ link.l %fp,&F%1 480e XXXX XXXX
+
+ A movm instruction to preserve integer regs:
+
+ movm.l &M%1,(4,%sp) 48ef XXXX XXXX
+
+ A fmovm instruction to preserve float regs:
+
+ fmovm &FPM%1,(FPO%1,%sp) f237 XXXX XXXX XXXX XXXX
+
+ Some profiling setup code (FIXME, not recognized yet):
+
+ lea.l (.L3,%pc),%a1 43fb XXXX XXXX XXXX
+ bsr _mcount 61ff XXXX XXXX
+
+ */
+
+#define P_LINK_L 0x480e
+#define P_LINK_W 0x4e56
+#define P_MOV_L 0x207c
+#define P_JSR 0x4eb9
+#define P_BSR 0x61ff
+#define P_LEA_L 0x43fb
+#define P_MOVM_L 0x48ef
+#define P_FMOVM 0xf237
+#define P_TRAP 0x4e40
+
+CORE_ADDR
+m68k_skip_prologue (ip)
+CORE_ADDR ip;
+{
+ register CORE_ADDR limit;
+ struct symtab_and_line sal;
+ register int op;
+
+ /* Find out if there is a known limit for the extent of the prologue.
+ If so, ensure we don't go past it. If not, assume "infinity". */
+
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end) ? sal.end : (CORE_ADDR) ~0;
+
+ while (ip < limit)
+ {
+ op = read_memory_integer (ip, 2);
+ op &= 0xFFFF;
+
+ if (op == P_LINK_W)
+ {
+ ip += 4; /* Skip link.w */
+ }
+ else if (op == 0x4856)
+ ip += 2; /* Skip pea %fp */
+ else if (op == 0x2c4f)
+ ip += 2; /* Skip move.l %sp, %fp */
+ else if (op == P_LINK_L)
+ {
+ ip += 6; /* Skip link.l */
+ }
+ else if (op == P_MOVM_L)
+ {
+ ip += 6; /* Skip movm.l */
+ }
+ else if (op == P_FMOVM)
+ {
+ ip += 10; /* Skip fmovm */
+ }
+ else
+ {
+ break; /* Found unknown code, bail out. */
+ }
+ }
+ return (ip);
+}
+
+void
+m68k_find_saved_regs (frame_info, saved_regs)
+ struct frame_info *frame_info;
+ struct frame_saved_regs *saved_regs;
+{
+ register int regnum;
+ register int regmask;
+ register CORE_ADDR next_addr;
+ register CORE_ADDR pc;
+
+ /* First possible address for a pc in a call dummy for this frame. */
+ CORE_ADDR possible_call_dummy_start =
+ (frame_info)->frame - CALL_DUMMY_LENGTH - FP_REGNUM*4 - 4 - 8*12;
+
+ int nextinsn;
+ memset (saved_regs, 0, sizeof (*saved_regs));
+ if ((frame_info)->pc >= possible_call_dummy_start
+ && (frame_info)->pc <= (frame_info)->frame)
+ {
+
+ /* It is a call dummy. We could just stop now, since we know
+ what the call dummy saves and where. But this code proceeds
+ to parse the "prologue" which is part of the call dummy.
+ This is needlessly complex and confusing. FIXME. */
+
+ next_addr = (frame_info)->frame;
+ pc = possible_call_dummy_start;
+ }
+ else
+ {
+ pc = get_pc_function_start ((frame_info)->pc);
+
+ if (0x4856 == read_memory_integer (pc, 2)
+ && 0x2c4f == read_memory_integer (pc + 2, 2))
+ {
+ /*
+ pea %fp
+ move.l %sp, %fp */
+
+ pc += 4;
+ next_addr = frame_info->frame;
+ }
+ else if (044016 == read_memory_integer (pc, 2))
+ /* link.l %fp */
+ /* Find the address above the saved
+ regs using the amount of storage from the link instruction. */
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 4), pc+=4;
+ else if (047126 == read_memory_integer (pc, 2))
+ /* link.w %fp */
+ /* Find the address above the saved
+ regs using the amount of storage from the link instruction. */
+ next_addr = (frame_info)->frame + read_memory_integer (pc += 2, 2), pc+=2;
+ else goto lose;
+
+ /* If have an addal #-n, sp next, adjust next_addr. */
+ if ((0177777 & read_memory_integer (pc, 2)) == 0157774)
+ next_addr += read_memory_integer (pc += 2, 4), pc += 4;
+ }
+ regmask = read_memory_integer (pc + 2, 2);
+
+ /* Here can come an fmovem. Check for it. */
+ nextinsn = 0xffff & read_memory_integer (pc, 2);
+ if (0xf227 == nextinsn
+ && (regmask & 0xff00) == 0xe000)
+ { pc += 4; /* Regmask's low bit is for register fp7, the first pushed */
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr -= 12);
+ regmask = read_memory_integer (pc + 2, 2); }
+
+ /* next should be a moveml to (sp) or -(sp) or a movl r,-(sp) */
+ if (0044327 == read_memory_integer (pc, 2))
+ { pc += 4; /* Regmask's low bit is for register 0, the first written */
+ for (regnum = 0; regnum < 16; regnum++, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr += 4) - 4; }
+ else if (0044347 == read_memory_integer (pc, 2))
+ {
+ pc += 4; /* Regmask's low bit is for register 15, the first pushed */
+ for (regnum = 15; regnum >= 0; regnum--, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr -= 4);
+ }
+ else if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
+ {
+ regnum = 0xf & read_memory_integer (pc, 2); pc += 2;
+ saved_regs->regs[regnum] = (next_addr -= 4);
+ /* gcc, at least, may use a pair of movel instructions when saving
+ exactly 2 registers. */
+ if (0x2f00 == (0xfff0 & read_memory_integer (pc, 2)))
+ {
+ regnum = 0xf & read_memory_integer (pc, 2);
+ pc += 2;
+ saved_regs->regs[regnum] = (next_addr -= 4);
+ }
+ }
+
+ /* fmovemx to index of sp may follow. */
+ regmask = read_memory_integer (pc + 2, 2);
+ nextinsn = 0xffff & read_memory_integer (pc, 2);
+ if (0xf236 == nextinsn
+ && (regmask & 0xff00) == 0xf000)
+ { pc += 10; /* Regmask's low bit is for register fp0, the first written */
+ for (regnum = FP0_REGNUM + 7; regnum >= FP0_REGNUM; regnum--, regmask >>= 1)
+ if (regmask & 1)
+ saved_regs->regs[regnum] = (next_addr += 12) - 12;
+ regmask = read_memory_integer (pc + 2, 2); }
+
+ /* clrw -(sp); movw ccr,-(sp) may follow. */
+ if (0x426742e7 == read_memory_integer (pc, 4))
+ saved_regs->regs[PS_REGNUM] = (next_addr -= 4);
+ lose: ;
+ saved_regs->regs[SP_REGNUM] = (frame_info)->frame + 8;
+ saved_regs->regs[FP_REGNUM] = (frame_info)->frame;
+ saved_regs->regs[PC_REGNUM] = (frame_info)->frame + 4;
+#ifdef SIG_SP_FP_OFFSET
+ /* Adjust saved SP_REGNUM for fake _sigtramp frames. */
+ if (frame_info->signal_handler_caller && frame_info->next)
+ saved_regs->regs[SP_REGNUM] = frame_info->next->frame + SIG_SP_FP_OFFSET;
+#endif
+}
+
+
+#ifdef USE_PROC_FS /* Target dependent support for /proc */
+
+#include <sys/procfs.h>
+
+/* The /proc interface divides the target machine's register set up into
+ two different sets, the general register set (gregset) and the floating
+ point register set (fpregset). For each set, there is an ioctl to get
+ the current register set and another ioctl to set the current values.
+
+ The actual structure passed through the ioctl interface is, of course,
+ naturally machine dependent, and is different for each set of registers.
+ For the m68k for example, the general register set is typically defined
+ by:
+
+ typedef int gregset_t[18];
+
+ #define R_D0 0
+ ...
+ #define R_PS 17
+
+ and the floating point set by:
+
+ typedef struct fpregset {
+ int f_pcr;
+ int f_psr;
+ int f_fpiaddr;
+ int f_fpregs[8][3]; (8 regs, 96 bits each)
+ } fpregset_t;
+
+ These routines provide the packing and unpacking of gregset_t and
+ fpregset_t formatted data.
+
+ */
+
+/* Atari SVR4 has R_SR but not R_PS */
+
+#if !defined (R_PS) && defined (R_SR)
+#define R_PS R_SR
+#endif
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi = 0 ; regi < R_PC ; regi++)
+ {
+ supply_register (regi, (char *) (regp + regi));
+ }
+ supply_register (PS_REGNUM, (char *) (regp + R_PS));
+ supply_register (PC_REGNUM, (char *) (regp + R_PC));
+}
+
+void
+fill_gregset (gregsetp, regno)
+gregset_t *gregsetp;
+int regno;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+
+ for (regi = 0 ; regi < R_PC ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ *(regp + regi) = *(int *) &registers[REGISTER_BYTE (regi)];
+ }
+ }
+ if ((regno == -1) || (regno == PS_REGNUM))
+ {
+ *(regp + R_PS) = *(int *) &registers[REGISTER_BYTE (PS_REGNUM)];
+ }
+ if ((regno == -1) || (regno == PC_REGNUM))
+ {
+ *(regp + R_PC) = *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+ }
+}
+
+#if defined (FP0_REGNUM)
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+fpregset_t *fpregsetp;
+{
+ register int regi;
+ char *from;
+
+ for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
+ {
+ from = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
+ supply_register (regi, from);
+ }
+ supply_register (FPC_REGNUM, (char *) &(fpregsetp -> f_pcr));
+ supply_register (FPS_REGNUM, (char *) &(fpregsetp -> f_psr));
+ supply_register (FPI_REGNUM, (char *) &(fpregsetp -> f_fpiaddr));
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+
+void
+fill_fpregset (fpregsetp, regno)
+fpregset_t *fpregsetp;
+int regno;
+{
+ int regi;
+ char *to;
+ char *from;
+ extern char registers[];
+
+ for (regi = FP0_REGNUM ; regi < FPC_REGNUM ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ from = (char *) &registers[REGISTER_BYTE (regi)];
+ to = (char *) &(fpregsetp -> f_fpregs[regi-FP0_REGNUM][0]);
+ memcpy (to, from, REGISTER_RAW_SIZE (regi));
+ }
+ }
+ if ((regno == -1) || (regno == FPC_REGNUM))
+ {
+ fpregsetp -> f_pcr = *(int *) &registers[REGISTER_BYTE (FPC_REGNUM)];
+ }
+ if ((regno == -1) || (regno == FPS_REGNUM))
+ {
+ fpregsetp -> f_psr = *(int *) &registers[REGISTER_BYTE (FPS_REGNUM)];
+ }
+ if ((regno == -1) || (regno == FPI_REGNUM))
+ {
+ fpregsetp -> f_fpiaddr = *(int *) &registers[REGISTER_BYTE (FPI_REGNUM)];
+ }
+}
+
+#endif /* defined (FP0_REGNUM) */
+
+#endif /* USE_PROC_FS */
+
+#ifdef GET_LONGJMP_TARGET
+/* Figure out where the longjmp will land. Slurp the args out of the stack.
+ We expect the first arg to be a pointer to the jmp_buf structure from which
+ we extract the pc (JB_PC) that we will land at. The pc is copied into PC.
+ This routine returns true on success. */
+
+int
+get_longjmp_target(pc)
+ CORE_ADDR *pc;
+{
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ CORE_ADDR sp, jb_addr;
+
+ sp = read_register(SP_REGNUM);
+
+ if (target_read_memory (sp + SP_ARG0, /* Offset of first arg on stack */
+ buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ jb_addr = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
+ TARGET_PTR_BIT / TARGET_CHAR_BIT))
+ return 0;
+
+ *pc = extract_address (buf, TARGET_PTR_BIT / TARGET_CHAR_BIT);
+
+ return 1;
+}
+#endif /* GET_LONGJMP_TARGET */
+
+/* Immediately after a function call, return the saved pc before the frame
+ is setup. For sun3's, we check for the common case of being inside of a
+ system call, and if so, we know that Sun pushes the call # on the stack
+ prior to doing the trap. */
+
+CORE_ADDR
+m68k_saved_pc_after_call(frame)
+ struct frame_info *frame;
+{
+#ifdef SYSCALL_TRAP
+ int op;
+
+ op = read_memory_integer (frame->pc - SYSCALL_TRAP_OFFSET, 2);
+
+ if (op == SYSCALL_TRAP)
+ return read_memory_integer (read_register (SP_REGNUM) + 4, 4);
+ else
+#endif /* SYSCALL_TRAP */
+ return read_memory_integer (read_register (SP_REGNUM), 4);
+}
+
+void
+_initialize_m68k_tdep ()
+{
+ tm_print_insn = print_insn_m68k;
+}
diff --git a/contrib/gdb/gdb/m68knbsd-nat.c b/contrib/gdb/gdb/m68knbsd-nat.c
new file mode 100644
index 0000000..7f98147
--- /dev/null
+++ b/contrib/gdb/gdb/m68knbsd-nat.c
@@ -0,0 +1,86 @@
+/* Native-dependent code for Motorola m68k's running NetBSD, for GDB.
+ Copyright 1988, 1989, 1991, 1992, 1994, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <machine/reg.h>
+#include <machine/frame.h>
+
+#include "defs.h"
+#include "inferior.h"
+
+void
+fetch_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+ struct fpreg inferior_fp_registers;
+
+ ptrace (PT_GETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+ memcpy (&registers[REGISTER_BYTE (0)], &inferior_registers,
+ sizeof(inferior_registers));
+
+ ptrace (PT_GETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
+ memcpy (&registers[REGISTER_BYTE (FP0_REGNUM)], &inferior_fp_registers,
+ sizeof(inferior_fp_registers));
+
+ registers_fetched ();
+}
+
+void
+store_inferior_registers(regno)
+ int regno;
+{
+ struct reg inferior_registers;
+ struct fpreg inferior_fp_registers;
+
+ memcpy (&inferior_registers, &registers[REGISTER_BYTE (0)],
+ sizeof(inferior_registers));
+ ptrace (PT_SETREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_registers, 0);
+
+ memcpy (&inferior_fp_registers, &registers[REGISTER_BYTE (FP0_REGNUM)],
+ sizeof(inferior_fp_registers));
+ ptrace (PT_SETFPREGS, inferior_pid,
+ (PTRACE_ARG3_TYPE) &inferior_fp_registers, 0);
+}
+
+struct md_core {
+ struct reg intreg;
+ struct fpreg freg;
+};
+
+void
+fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
+ char *core_reg_sect;
+ unsigned core_reg_size;
+ int which;
+ unsigned int ignore;
+{
+ struct md_core *core_reg = (struct md_core *)core_reg_sect;
+
+ /* Integer registers */
+ memcpy(&registers[REGISTER_BYTE (0)],
+ &core_reg->intreg, sizeof(struct reg));
+ /* Floating point registers */
+ memcpy(&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &core_reg->freg, sizeof(struct fpreg));
+}
diff --git a/contrib/gdb/gdb/m88k-nat.c b/contrib/gdb/gdb/m88k-nat.c
new file mode 100644
index 0000000..19e9392
--- /dev/null
+++ b/contrib/gdb/gdb/m88k-nat.c
@@ -0,0 +1,285 @@
+/* Native-dependent Motorola 88xxx support for GDB, the GNU Debugger.
+ Copyright 1988, 1990, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include "gdbcore.h"
+#include <sys/user.h>
+
+#ifndef USER /* added to support BCS ptrace_user */
+#define USER ptrace_user
+#endif
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+#include "symtab.h"
+#include "setjmp.h"
+#include "value.h"
+
+#ifdef DELTA88
+#include <sys/ptrace.h>
+
+/* define offsets to the pc instruction offsets in ptrace_user struct */
+#define SXIP_OFFSET ((char *)&u.pt_sigframe.sig_sxip - (char *)&u)
+#define SNIP_OFFSET ((char *)&u.pt_sigframe.sig_snip - (char *)&u)
+#define SFIP_OFFSET ((char *)&u.pt_sigframe.sig_sfip - (char *)&u)
+#else
+/* define offsets to the pc instruction offsets in ptrace_user struct */
+#define SXIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sxip - (char *)&u)
+#define SNIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_snip - (char *)&u)
+#define SFIP_OFFSET ((char *)&u.pt_sigframe.dg_sigframe.sc_sfip - (char *)&u)
+#endif
+
+extern int have_symbol_file_p();
+
+extern jmp_buf stack_jmp;
+
+extern int errno;
+extern char registers[REGISTER_BYTES];
+
+void
+fetch_inferior_registers (regno)
+ int regno; /* Original value discarded */
+{
+ register unsigned int regaddr;
+ char buf[MAX_REGISTER_RAW_SIZE];
+ register int i;
+
+ struct USER u;
+ unsigned int offset;
+
+ offset = (char *) &u.pt_r0 - (char *) &u;
+ regaddr = offset; /* byte offset to r0;*/
+
+/* offset = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) offset, 0) - KERNEL_U_ADDR; */
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ /*regaddr = register_addr (regno, offset);*/
+ /* 88k enhancement */
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
+ {
+ *(int *) &buf[i] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, 0);
+ regaddr += sizeof (int);
+ }
+ supply_register (regno, buf);
+ }
+ /* now load up registers 36 - 38; special pc registers */
+ *(int *) &buf[0] = ptrace (3,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET ,0);
+ supply_register (SXIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,0);
+ supply_register (SNIP_REGNUM, buf);
+ *(int *) &buf[0] = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,0);
+ supply_register (SFIP_REGNUM, buf);
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ struct USER u;
+
+ unsigned int offset = (char *) &u.pt_r0 - (char *) &u;
+
+ regaddr = offset;
+
+ /* Don't try to deal with EXIP_REGNUM or ENIP_REGNUM, because I think either
+ svr3 doesn't run on an 88110, or the kernel isolates the different (not
+ completely sure this is true, but seems to be. */
+ if (regno >= 0)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ if (regno < PC_REGNUM)
+ {
+ regaddr = offset + regno * sizeof (int);
+ errno = 0;
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ else if (regno == SXIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET, read_register(regno));
+ else if (regno == SNIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET, read_register(regno));
+ else if (regno == SFIP_REGNUM)
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET, read_register(regno));
+ else
+ printf_unfiltered ("Bad register number for store_inferior routine\n");
+ }
+ else
+ {
+ for (regno = 0; regno < PC_REGNUM; regno++)
+ {
+ /* regaddr = register_addr (regno, offset); */
+ errno = 0;
+ regaddr = offset + regno * sizeof (int);
+ ptrace (6, inferior_pid,
+ (PTRACE_ARG3_TYPE) regaddr, read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SXIP_OFFSET,read_register(SXIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SNIP_OFFSET,read_register(SNIP_REGNUM));
+ ptrace (6,inferior_pid,
+ (PTRACE_ARG3_TYPE) SFIP_OFFSET,read_register(SFIP_REGNUM));
+ }
+}
+
+
+/* blockend is the address of the end of the user structure */
+m88k_register_u_addr (blockend, regnum)
+{
+ struct USER u;
+ int ustart = blockend - sizeof (struct USER);
+ switch (regnum)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ case 20:
+ case 21:
+ case 22:
+ case 23:
+ case 24:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 29:
+ case 30:
+ case 31:
+ return (ustart + ((int) &u.pt_r0 - (int) &u) + REGISTER_SIZE * regnum);
+ case PSR_REGNUM: return (ustart + ((int) &u.pt_psr - (int) &u));
+ case FPSR_REGNUM: return (ustart + ((int) &u.pt_fpsr - (int) &u));
+ case FPCR_REGNUM: return (ustart + ((int) &u.pt_fpcr - (int) &u));
+ case SXIP_REGNUM: return (ustart + SXIP_OFFSET);
+ case SNIP_REGNUM: return (ustart + SNIP_OFFSET);
+ case SFIP_REGNUM: return (ustart + SFIP_OFFSET);
+ default:
+ if (regnum < NUM_REGS)
+ /* The register is one of those which is not defined...
+ give it zero */
+ return (ustart + ((int) &u.pt_r0 - (int) &u));
+ else
+ return (blockend + REGISTER_SIZE * regnum);
+ }
+}
+
+#ifdef USE_PROC_FS
+
+#include <sys/procfs.h>
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ register int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+
+ for (regi=0; regi <= SP_REGNUM; regi++)
+ supply_register (regi, (char *) (regp + regi));
+
+ supply_register (SXIP_REGNUM, (char *) (regp + R_XIP));
+ supply_register (SNIP_REGNUM, (char *) (regp + R_NIP));
+ supply_register (SFIP_REGNUM, (char *) (regp + R_FIP));
+ supply_register (PSR_REGNUM, (char *) (regp + R_PSR));
+ supply_register (FPSR_REGNUM, (char *) (regp + R_FPSR));
+ supply_register (FPCR_REGNUM, (char *) (regp + R_FPCR));
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ register greg_t *regp = (greg_t *) gregsetp;
+ extern char registers[];
+
+ for (regi = 0 ; regi <= R_R31 ; regi++)
+ if ((regno == -1) || (regno == regi))
+ *(regp + regi) = *(int *) &registers[REGISTER_BYTE(regi)];
+
+ if ((regno == -1) || (regno == SXIP_REGNUM))
+ *(regp + R_XIP) = *(int *) &registers[REGISTER_BYTE(SXIP_REGNUM)];
+ if ((regno == -1) || (regno == SNIP_REGNUM))
+ *(regp + R_NIP) = *(int *) &registers[REGISTER_BYTE(SNIP_REGNUM)];
+ if ((regno == -1) || (regno == SFIP_REGNUM))
+ *(regp + R_FIP) = *(int *) &registers[REGISTER_BYTE(SFIP_REGNUM)];
+ if ((regno == -1) || (regno == PSR_REGNUM))
+ *(regp + R_PSR) = *(int *) &registers[REGISTER_BYTE(PSR_REGNUM)];
+ if ((regno == -1) || (regno == FPSR_REGNUM))
+ *(regp + R_FPSR) = *(int *) &registers[REGISTER_BYTE(FPSR_REGNUM)];
+ if ((regno == -1) || (regno == FPCR_REGNUM))
+ *(regp + R_FPCR) = *(int *) &registers[REGISTER_BYTE(FPCR_REGNUM)];
+}
+
+#endif /* USE_PROC_FS */
diff --git a/contrib/gdb/gdb/m88k-tdep.c b/contrib/gdb/gdb/m88k-tdep.c
new file mode 100644
index 0000000..a21bd96
--- /dev/null
+++ b/contrib/gdb/gdb/m88k-tdep.c
@@ -0,0 +1,616 @@
+/* Target-machine dependent code for Motorola 88000 series, for GDB.
+ Copyright 1988, 1990, 1991, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "symtab.h"
+#include "setjmp.h"
+#include "value.h"
+
+/* Size of an instruction */
+#define BYTES_PER_88K_INSN 4
+
+void frame_find_saved_regs ();
+
+/* Is this target an m88110? Otherwise assume m88100. This has
+ relevance for the ways in which we screw with instruction pointers. */
+
+int target_is_m88110 = 0;
+
+/* Given a GDB frame, determine the address of the calling function's frame.
+ This will be used to create a new GDB frame struct, and then
+ INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+
+ For us, the frame address is its stack pointer value, so we look up
+ the function prologue to determine the caller's sp value, and return it. */
+
+CORE_ADDR
+frame_chain (thisframe)
+ struct frame_info *thisframe;
+{
+
+ frame_find_saved_regs (thisframe, (struct frame_saved_regs *) 0);
+ /* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
+ the ADDRESS, of SP_REGNUM. It also depends on the cache of
+ frame_find_saved_regs results. */
+ if (thisframe->fsr->regs[SP_REGNUM])
+ return thisframe->fsr->regs[SP_REGNUM];
+ else
+ return thisframe->frame; /* Leaf fn -- next frame up has same SP. */
+}
+
+int
+frameless_function_invocation (frame)
+ struct frame_info *frame;
+{
+
+ frame_find_saved_regs (frame, (struct frame_saved_regs *) 0);
+ /* NOTE: this depends on frame_find_saved_regs returning the VALUE, not
+ the ADDRESS, of SP_REGNUM. It also depends on the cache of
+ frame_find_saved_regs results. */
+ if (frame->fsr->regs[SP_REGNUM])
+ return 0; /* Frameful -- return addr saved somewhere */
+ else
+ return 1; /* Frameless -- no saved return address */
+}
+
+void
+init_extra_frame_info (fromleaf, frame)
+ int fromleaf;
+ struct frame_info *frame;
+{
+ frame->fsr = 0; /* Not yet allocated */
+ frame->args_pointer = 0; /* Unknown */
+ frame->locals_pointer = 0; /* Unknown */
+}
+
+/* Examine an m88k function prologue, recording the addresses at which
+ registers are saved explicitly by the prologue code, and returning
+ the address of the first instruction after the prologue (but not
+ after the instruction at address LIMIT, as explained below).
+
+ LIMIT places an upper bound on addresses of the instructions to be
+ examined. If the prologue code scan reaches LIMIT, the scan is
+ aborted and LIMIT is returned. This is used, when examining the
+ prologue for the current frame, to keep examine_prologue () from
+ claiming that a given register has been saved when in fact the
+ instruction that saves it has not yet been executed. LIMIT is used
+ at other times to stop the scan when we hit code after the true
+ function prologue (e.g. for the first source line) which might
+ otherwise be mistaken for function prologue.
+
+ The format of the function prologue matched by this routine is
+ derived from examination of the source to gcc 1.95, particularly
+ the routine output_prologue () in config/out-m88k.c.
+
+ subu r31,r31,n # stack pointer update
+
+ (st rn,r31,offset)? # save incoming regs
+ (st.d rn,r31,offset)?
+
+ (addu r30,r31,n)? # frame pointer update
+
+ (pic sequence)? # PIC code prologue
+
+ (or rn,rm,0)? # Move parameters to other regs
+*/
+
+/* Macros for extracting fields from instructions. */
+
+#define BITMASK(pos, width) (((0x1 << (width)) - 1) << (pos))
+#define EXTRACT_FIELD(val, pos, width) ((val) >> (pos) & BITMASK (0, width))
+#define SUBU_OFFSET(x) ((unsigned)(x & 0xFFFF))
+#define ST_OFFSET(x) ((unsigned)((x) & 0xFFFF))
+#define ST_SRC(x) EXTRACT_FIELD ((x), 21, 5)
+#define ADDU_OFFSET(x) ((unsigned)(x & 0xFFFF))
+
+/*
+ * prologue_insn_tbl is a table of instructions which may comprise a
+ * function prologue. Associated with each table entry (corresponding
+ * to a single instruction or group of instructions), is an action.
+ * This action is used by examine_prologue (below) to determine
+ * the state of certain machine registers and where the stack frame lives.
+ */
+
+enum prologue_insn_action {
+ PIA_SKIP, /* don't care what the instruction does */
+ PIA_NOTE_ST, /* note register stored and where */
+ PIA_NOTE_STD, /* note pair of registers stored and where */
+ PIA_NOTE_SP_ADJUSTMENT, /* note stack pointer adjustment */
+ PIA_NOTE_FP_ASSIGNMENT, /* note frame pointer assignment */
+ PIA_NOTE_PROLOGUE_END, /* no more prologue */
+};
+
+struct prologue_insns {
+ unsigned long insn;
+ unsigned long mask;
+ enum prologue_insn_action action;
+};
+
+struct prologue_insns prologue_insn_tbl[] = {
+ /* Various register move instructions */
+ { 0x58000000, 0xf800ffff, PIA_SKIP }, /* or/or.u with immed of 0 */
+ { 0xf4005800, 0xfc1fffe0, PIA_SKIP }, /* or rd, r0, rs */
+ { 0xf4005800, 0xfc00ffff, PIA_SKIP }, /* or rd, rs, r0 */
+
+ /* Stack pointer setup: "subu sp, sp, n" where n is a multiple of 8 */
+ { 0x67ff0000, 0xffff0007, PIA_NOTE_SP_ADJUSTMENT },
+
+ /* Frame pointer assignment: "addu r30, r31, n" */
+ { 0x63df0000, 0xffff0000, PIA_NOTE_FP_ASSIGNMENT },
+
+ /* Store to stack instructions; either "st rx, sp, n" or "st.d rx, sp, n" */
+ { 0x241f0000, 0xfc1f0000, PIA_NOTE_ST }, /* st rx, sp, n */
+ { 0x201f0000, 0xfc1f0000, PIA_NOTE_STD }, /* st.d rs, sp, n */
+
+ /* Instructions needed for setting up r25 for pic code. */
+ { 0x5f200000, 0xffff0000, PIA_SKIP }, /* or.u r25, r0, offset_high */
+ { 0xcc000002, 0xffffffff, PIA_SKIP }, /* bsr.n Lab */
+ { 0x5b390000, 0xffff0000, PIA_SKIP }, /* or r25, r25, offset_low */
+ { 0xf7396001, 0xffffffff, PIA_SKIP }, /* Lab: addu r25, r25, r1 */
+
+ /* Various branch or jump instructions which have a delay slot -- these
+ do not form part of the prologue, but the instruction in the delay
+ slot might be a store instruction which should be noted. */
+ { 0xc4000000, 0xe4000000, PIA_NOTE_PROLOGUE_END },
+ /* br.n, bsr.n, bb0.n, or bb1.n */
+ { 0xec000000, 0xfc000000, PIA_NOTE_PROLOGUE_END }, /* bcnd.n */
+ { 0xf400c400, 0xfffff7e0, PIA_NOTE_PROLOGUE_END } /* jmp.n or jsr.n */
+
+};
+
+
+/* Fetch the instruction at ADDR, returning 0 if ADDR is beyond LIM or
+ is not the address of a valid instruction, the address of the next
+ instruction beyond ADDR otherwise. *PWORD1 receives the first word
+ of the instruction. */
+
+#define NEXT_PROLOGUE_INSN(addr, lim, pword1) \
+ (((addr) < (lim)) ? next_insn (addr, pword1) : 0)
+
+/* Read the m88k instruction at 'memaddr' and return the address of
+ the next instruction after that, or 0 if 'memaddr' is not the
+ address of a valid instruction. The instruction
+ is stored at 'pword1'. */
+
+CORE_ADDR
+next_insn (memaddr, pword1)
+ unsigned long *pword1;
+ CORE_ADDR memaddr;
+{
+ *pword1 = read_memory_integer (memaddr, BYTES_PER_88K_INSN);
+ return memaddr + BYTES_PER_88K_INSN;
+}
+
+/* Read a register from frames called by us (or from the hardware regs). */
+
+static int
+read_next_frame_reg(frame, regno)
+ struct frame_info *frame;
+ int regno;
+{
+ for (; frame; frame = frame->next) {
+ if (regno == SP_REGNUM)
+ return FRAME_FP (frame);
+ else if (frame->fsr->regs[regno])
+ return read_memory_integer(frame->fsr->regs[regno], 4);
+ }
+ return read_register(regno);
+}
+
+/* Examine the prologue of a function. `ip' points to the first instruction.
+ `limit' is the limit of the prologue (e.g. the addr of the first
+ linenumber, or perhaps the program counter if we're stepping through).
+ `frame_sp' is the stack pointer value in use in this frame.
+ `fsr' is a pointer to a frame_saved_regs structure into which we put
+ info about the registers saved by this frame.
+ `fi' is a struct frame_info pointer; we fill in various fields in it
+ to reflect the offsets of the arg pointer and the locals pointer. */
+
+static CORE_ADDR
+examine_prologue (ip, limit, frame_sp, fsr, fi)
+ register CORE_ADDR ip;
+ register CORE_ADDR limit;
+ CORE_ADDR frame_sp;
+ struct frame_saved_regs *fsr;
+ struct frame_info *fi;
+{
+ register CORE_ADDR next_ip;
+ register int src;
+ unsigned int insn;
+ int size, offset;
+ char must_adjust[32]; /* If set, must adjust offsets in fsr */
+ int sp_offset = -1; /* -1 means not set (valid must be mult of 8) */
+ int fp_offset = -1; /* -1 means not set */
+ CORE_ADDR frame_fp;
+ CORE_ADDR prologue_end = 0;
+
+ memset (must_adjust, '\0', sizeof (must_adjust));
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
+
+ while (next_ip)
+ {
+ struct prologue_insns *pip;
+
+ for (pip=prologue_insn_tbl; (insn & pip->mask) != pip->insn; )
+ if (++pip >= prologue_insn_tbl + sizeof prologue_insn_tbl)
+ goto end_of_prologue_found; /* not a prologue insn */
+
+ switch (pip->action)
+ {
+ case PIA_NOTE_ST:
+ case PIA_NOTE_STD:
+ if (sp_offset != -1) {
+ src = ST_SRC (insn);
+ offset = ST_OFFSET (insn);
+ must_adjust[src] = 1;
+ fsr->regs[src++] = offset; /* Will be adjusted later */
+ if (pip->action == PIA_NOTE_STD && src < 32)
+ {
+ offset += 4;
+ must_adjust[src] = 1;
+ fsr->regs[src++] = offset;
+ }
+ }
+ else
+ goto end_of_prologue_found;
+ break;
+ case PIA_NOTE_SP_ADJUSTMENT:
+ if (sp_offset == -1)
+ sp_offset = -SUBU_OFFSET (insn);
+ else
+ goto end_of_prologue_found;
+ break;
+ case PIA_NOTE_FP_ASSIGNMENT:
+ if (fp_offset == -1)
+ fp_offset = ADDU_OFFSET (insn);
+ else
+ goto end_of_prologue_found;
+ break;
+ case PIA_NOTE_PROLOGUE_END:
+ if (!prologue_end)
+ prologue_end = ip;
+ break;
+ case PIA_SKIP:
+ default :
+ /* Do nothing */
+ break;
+ }
+
+ ip = next_ip;
+ next_ip = NEXT_PROLOGUE_INSN (ip, limit, &insn);
+ }
+
+end_of_prologue_found:
+
+ if (prologue_end)
+ ip = prologue_end;
+
+ /* We're done with the prologue. If we don't care about the stack
+ frame itself, just return. (Note that fsr->regs has been trashed,
+ but the one caller who calls with fi==0 passes a dummy there.) */
+
+ if (fi == 0)
+ return ip;
+
+ /*
+ OK, now we have:
+
+ sp_offset original (before any alloca calls) displacement of SP
+ (will be negative).
+
+ fp_offset displacement from original SP to the FP for this frame
+ or -1.
+
+ fsr->regs[0..31] displacement from original SP to the stack
+ location where reg[0..31] is stored.
+
+ must_adjust[0..31] set if corresponding offset was set.
+
+ If alloca has been called between the function prologue and the current
+ IP, then the current SP (frame_sp) will not be the original SP as set by
+ the function prologue. If the current SP is not the original SP, then the
+ compiler will have allocated an FP for this frame, fp_offset will be set,
+ and we can use it to calculate the original SP.
+
+ Then, we figure out where the arguments and locals are, and relocate the
+ offsets in fsr->regs to absolute addresses. */
+
+ if (fp_offset != -1) {
+ /* We have a frame pointer, so get it, and base our calc's on it. */
+ frame_fp = (CORE_ADDR) read_next_frame_reg (fi->next, ACTUAL_FP_REGNUM);
+ frame_sp = frame_fp - fp_offset;
+ } else {
+ /* We have no frame pointer, therefore frame_sp is still the same value
+ as set by prologue. But where is the frame itself? */
+ if (must_adjust[SRP_REGNUM]) {
+ /* Function header saved SRP (r1), the return address. Frame starts
+ 4 bytes down from where it was saved. */
+ frame_fp = frame_sp + fsr->regs[SRP_REGNUM] - 4;
+ fi->locals_pointer = frame_fp;
+ } else {
+ /* Function header didn't save SRP (r1), so we are in a leaf fn or
+ are otherwise confused. */
+ frame_fp = -1;
+ }
+ }
+
+ /* The locals are relative to the FP (whether it exists as an allocated
+ register, or just as an assumed offset from the SP) */
+ fi->locals_pointer = frame_fp;
+
+ /* The arguments are just above the SP as it was before we adjusted it
+ on entry. */
+ fi->args_pointer = frame_sp - sp_offset;
+
+ /* Now that we know the SP value used by the prologue, we know where
+ it saved all the registers. */
+ for (src = 0; src < 32; src++)
+ if (must_adjust[src])
+ fsr->regs[src] += frame_sp;
+
+ /* The saved value of the SP is always known. */
+ /* (we hope...) */
+ if (fsr->regs[SP_REGNUM] != 0
+ && fsr->regs[SP_REGNUM] != frame_sp - sp_offset)
+ fprintf_unfiltered(gdb_stderr, "Bad saved SP value %x != %x, offset %x!\n",
+ fsr->regs[SP_REGNUM],
+ frame_sp - sp_offset, sp_offset);
+
+ fsr->regs[SP_REGNUM] = frame_sp - sp_offset;
+
+ return (ip);
+}
+
+/* Given an ip value corresponding to the start of a function,
+ return the ip of the first instruction after the function
+ prologue. */
+
+CORE_ADDR
+skip_prologue (ip)
+ CORE_ADDR (ip);
+{
+ struct frame_saved_regs saved_regs_dummy;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end) ? sal.end : 0xffffffff;
+
+ return (examine_prologue (ip, limit, (CORE_ADDR) 0, &saved_regs_dummy,
+ (struct frame_info *)0 ));
+}
+
+/* Put here the code to store, into a struct frame_saved_regs,
+ the addresses of the saved registers of frame described by FRAME_INFO.
+ This includes special registers such as pc and fp saved in special
+ ways in the stack frame. sp is even more special:
+ the address we return for it IS the sp for the next frame.
+
+ We cache the result of doing this in the frame_cache_obstack, since
+ it is fairly expensive. */
+
+void
+frame_find_saved_regs (fi, fsr)
+ struct frame_info *fi;
+ struct frame_saved_regs *fsr;
+{
+ register struct frame_saved_regs *cache_fsr;
+ extern struct obstack frame_cache_obstack;
+ CORE_ADDR ip;
+ struct symtab_and_line sal;
+ CORE_ADDR limit;
+
+ if (!fi->fsr)
+ {
+ cache_fsr = (struct frame_saved_regs *)
+ obstack_alloc (&frame_cache_obstack,
+ sizeof (struct frame_saved_regs));
+ memset (cache_fsr, '\0', sizeof (struct frame_saved_regs));
+ fi->fsr = cache_fsr;
+
+ /* Find the start and end of the function prologue. If the PC
+ is in the function prologue, we only consider the part that
+ has executed already. In the case where the PC is not in
+ the function prologue, we set limit to two instructions beyond
+ where the prologue ends in case if any of the prologue instructions
+ were moved into a delay slot of a branch instruction. */
+
+ ip = get_pc_function_start (fi->pc);
+ sal = find_pc_line (ip, 0);
+ limit = (sal.end && sal.end < fi->pc) ? sal.end + 2 * BYTES_PER_88K_INSN
+ : fi->pc;
+
+ /* This will fill in fields in *fi as well as in cache_fsr. */
+#ifdef SIGTRAMP_FRAME_FIXUP
+ if (fi->signal_handler_caller)
+ SIGTRAMP_FRAME_FIXUP(fi->frame);
+#endif
+ examine_prologue (ip, limit, fi->frame, cache_fsr, fi);
+#ifdef SIGTRAMP_SP_FIXUP
+ if (fi->signal_handler_caller && fi->fsr->regs[SP_REGNUM])
+ SIGTRAMP_SP_FIXUP(fi->fsr->regs[SP_REGNUM]);
+#endif
+ }
+
+ if (fsr)
+ *fsr = *fi->fsr;
+}
+
+/* Return the address of the locals block for the frame
+ described by FI. Returns 0 if the address is unknown.
+ NOTE! Frame locals are referred to by negative offsets from the
+ argument pointer, so this is the same as frame_args_address(). */
+
+CORE_ADDR
+frame_locals_address (fi)
+ struct frame_info *fi;
+{
+ struct frame_saved_regs fsr;
+
+ if (fi->args_pointer) /* Cached value is likely there. */
+ return fi->args_pointer;
+
+ /* Nope, generate it. */
+
+ get_frame_saved_regs (fi, &fsr);
+
+ return fi->args_pointer;
+}
+
+/* Return the address of the argument block for the frame
+ described by FI. Returns 0 if the address is unknown. */
+
+CORE_ADDR
+frame_args_address (fi)
+ struct frame_info *fi;
+{
+ struct frame_saved_regs fsr;
+
+ if (fi->args_pointer) /* Cached value is likely there. */
+ return fi->args_pointer;
+
+ /* Nope, generate it. */
+
+ get_frame_saved_regs (fi, &fsr);
+
+ return fi->args_pointer;
+}
+
+/* Return the saved PC from this frame.
+
+ If the frame has a memory copy of SRP_REGNUM, use that. If not,
+ just use the register SRP_REGNUM itself. */
+
+CORE_ADDR
+frame_saved_pc (frame)
+ struct frame_info *frame;
+{
+ return read_next_frame_reg(frame, SRP_REGNUM);
+}
+
+
+#define DUMMY_FRAME_SIZE 192
+
+static void
+write_word (sp, word)
+ CORE_ADDR sp;
+ unsigned LONGEST word;
+{
+ register int len = REGISTER_SIZE;
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ store_unsigned_integer (buffer, len, word);
+ write_memory (sp, buffer, len);
+}
+
+void
+m88k_push_dummy_frame()
+{
+ register CORE_ADDR sp = read_register (SP_REGNUM);
+ register int rn;
+ int offset;
+
+ sp -= DUMMY_FRAME_SIZE; /* allocate a bunch of space */
+
+ for (rn = 0, offset = 0; rn <= SP_REGNUM; rn++, offset+=4)
+ write_word (sp+offset, read_register(rn));
+
+ write_word (sp+offset, read_register (SXIP_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (SNIP_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (SFIP_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (PSR_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (FPSR_REGNUM));
+ offset += 4;
+
+ write_word (sp+offset, read_register (FPCR_REGNUM));
+ offset += 4;
+
+ write_register (SP_REGNUM, sp);
+ write_register (ACTUAL_FP_REGNUM, sp);
+}
+
+void
+pop_frame ()
+{
+ register struct frame_info *frame = get_current_frame ();
+ register CORE_ADDR fp;
+ register int regnum;
+ struct frame_saved_regs fsr;
+
+ fp = FRAME_FP (frame);
+ get_frame_saved_regs (frame, &fsr);
+
+ if (PC_IN_CALL_DUMMY (read_pc (), read_register (SP_REGNUM), FRAME_FP (fi)))
+ {
+ /* FIXME: I think get_frame_saved_regs should be handling this so
+ that we can deal with the saved registers properly (e.g. frame
+ 1 is a call dummy, the user types "frame 2" and then "print $ps"). */
+ register CORE_ADDR sp = read_register (ACTUAL_FP_REGNUM);
+ int offset;
+
+ for (regnum = 0, offset = 0; regnum <= SP_REGNUM; regnum++, offset+=4)
+ (void) write_register (regnum, read_memory_integer (sp+offset, 4));
+
+ write_register (SXIP_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (SNIP_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (SFIP_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (PSR_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (FPSR_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ write_register (FPCR_REGNUM, read_memory_integer (sp+offset, 4));
+ offset += 4;
+
+ }
+ else
+ {
+ for (regnum = FP_REGNUM ; regnum > 0 ; regnum--)
+ if (fsr.regs[regnum])
+ write_register (regnum,
+ read_memory_integer (fsr.regs[regnum], 4));
+ write_pc (frame_saved_pc (frame));
+ }
+ reinit_frame_cache ();
+}
+
+void
+_initialize_m88k_tdep ()
+{
+ tm_print_insn = print_insn_m88k;
+}
diff --git a/contrib/gdb/gdb/main.c b/contrib/gdb/gdb/main.c
new file mode 100644
index 0000000..c440217
--- /dev/null
+++ b/contrib/gdb/gdb/main.c
@@ -0,0 +1,627 @@
+/* Top level stuff for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <setjmp.h>
+#include "top.h"
+#include "target.h"
+#include "inferior.h"
+#include "call-cmds.h"
+
+#include "getopt.h"
+
+#include <sys/types.h>
+#include "gdb_stat.h"
+#include <ctype.h>
+
+#include "gdb_string.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+
+/* Temporary variable for SET_TOP_LEVEL. */
+
+static int top_level_val;
+
+/* Do a setjmp on error_return and quit_return. catch_errors is
+ generally a cleaner way to do this, but main() would look pretty
+ ugly if it had to use catch_errors each time. */
+
+#define SET_TOP_LEVEL() \
+ (((top_level_val = setjmp (error_return)) \
+ ? (PTR) 0 : (PTR) memcpy (quit_return, error_return, sizeof (jmp_buf))) \
+ , top_level_val)
+
+/* If nonzero, display time usage both at startup and for each command. */
+
+int display_time;
+
+/* If nonzero, display space usage both at startup and for each command. */
+
+int display_space;
+
+extern void gdb_init PARAMS ((void));
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int count;
+ static int quiet = 0;
+ static int batch = 0;
+
+ /* Pointers to various arguments from command line. */
+ char *symarg = NULL;
+ char *execarg = NULL;
+ char *corearg = NULL;
+ char *cdarg = NULL;
+ char *ttyarg = NULL;
+
+ /* These are static so that we can take their address in an initializer. */
+ static int print_help;
+ static int print_version;
+
+ /* Pointers to all arguments of --command option. */
+ char **cmdarg;
+ /* Allocated size of cmdarg. */
+ int cmdsize;
+ /* Number of elements of cmdarg used. */
+ int ncmd;
+
+ /* Indices of all arguments of --directory option. */
+ char **dirarg;
+ /* Allocated size. */
+ int dirsize;
+ /* Number of elements used. */
+ int ndir;
+
+ struct stat homebuf, cwdbuf;
+ char *homedir, *homeinit;
+
+ register int i;
+
+ long time_at_startup = get_run_time ();
+
+ START_PROGRESS (argv[0], 0);
+
+#ifdef MPW
+ /* Do all Mac-specific setup. */
+ mac_init ();
+#endif /* MPW */
+
+ /* This needs to happen before the first use of malloc. */
+ init_malloc ((PTR) NULL);
+
+#if defined (ALIGN_STACK_ON_STARTUP)
+ i = (int) &count & 0x3;
+ if (i != 0)
+ alloca (4 - i);
+#endif
+
+ /* If error() is called from initialization code, just exit */
+ if (SET_TOP_LEVEL ()) {
+ exit(1);
+ }
+
+ cmdsize = 1;
+ cmdarg = (char **) xmalloc (cmdsize * sizeof (*cmdarg));
+ ncmd = 0;
+ dirsize = 1;
+ dirarg = (char **) xmalloc (dirsize * sizeof (*dirarg));
+ ndir = 0;
+
+ quit_flag = 0;
+ line = (char *) xmalloc (linesize);
+ line[0] = '\0'; /* Terminate saved (now empty) cmd line */
+ instream = stdin;
+
+ getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
+ current_directory = gdb_dirbuf;
+
+ /* Parse arguments and options. */
+#ifndef WINGDB
+ {
+ int c;
+ /* When var field is 0, use flag field to record the equivalent
+ short option (or arbitrary numbers starting at 10 for those
+ with no equivalent). */
+ static struct option long_options[] =
+ {
+ {"readnow", no_argument, &readnow_symbol_files, 1},
+ {"r", no_argument, &readnow_symbol_files, 1},
+ {"mapped", no_argument, &mapped_symbol_files, 1},
+ {"m", no_argument, &mapped_symbol_files, 1},
+ {"quiet", no_argument, &quiet, 1},
+ {"q", no_argument, &quiet, 1},
+ {"silent", no_argument, &quiet, 1},
+ {"nx", no_argument, &inhibit_gdbinit, 1},
+ {"n", no_argument, &inhibit_gdbinit, 1},
+ {"batch", no_argument, &batch, 1},
+ {"epoch", no_argument, &epoch_interface, 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'},
+ {"s", required_argument, 0, 's'},
+ {"exec", required_argument, 0, 'e'},
+ {"e", required_argument, 0, 'e'},
+ {"core", required_argument, 0, 'c'},
+ {"c", required_argument, 0, 'c'},
+ {"command", required_argument, 0, 'x'},
+ {"version", no_argument, &print_version, 1},
+ {"x", required_argument, 0, 'x'},
+ {"directory", required_argument, 0, 'd'},
+ {"cd", required_argument, 0, 11},
+ {"tty", required_argument, 0, 't'},
+ {"baud", required_argument, 0, 'b'},
+ {"b", required_argument, 0, 'b'},
+ {"nw", no_argument, &use_windows, 0},
+ {"nowindows", no_argument, &use_windows, 0},
+ {"w", no_argument, &use_windows, 1},
+ {"windows", no_argument, &use_windows, 1},
+ {"statistics", no_argument, 0, 13},
+/* Allow machine descriptions to add more options... */
+#ifdef ADDITIONAL_OPTIONS
+ ADDITIONAL_OPTIONS
+#endif
+ {0, no_argument, 0, 0}
+ };
+
+ while (1)
+ {
+ int option_index;
+
+ c = getopt_long_only (argc, argv, "",
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ /* Long option that takes an argument. */
+ if (c == 0 && long_options[option_index].flag == 0)
+ c = long_options[option_index].val;
+
+ switch (c)
+ {
+ case 0:
+ /* Long option that just sets a flag. */
+ break;
+ case 10:
+ symarg = optarg;
+ execarg = optarg;
+ break;
+ case 11:
+ cdarg = optarg;
+ break;
+ case 12:
+ /* FIXME: what if the syntax is wrong (e.g. not digits)? */
+ annotation_level = atoi (optarg);
+ break;
+ case 13:
+ /* Enable the display of both time and space usage. */
+ display_time = 1;
+ display_space = 1;
+ break;
+ case 'f':
+ annotation_level = 1;
+/* We have probably been invoked from emacs. Disable window interface. */
+ use_windows = 0;
+ break;
+ case 's':
+ symarg = optarg;
+ break;
+ case 'e':
+ execarg = optarg;
+ break;
+ case 'c':
+ corearg = optarg;
+ break;
+ case 'x':
+ cmdarg[ncmd++] = optarg;
+ if (ncmd >= cmdsize)
+ {
+ cmdsize *= 2;
+ cmdarg = (char **) xrealloc ((char *)cmdarg,
+ cmdsize * sizeof (*cmdarg));
+ }
+ break;
+ case 'd':
+ dirarg[ndir++] = optarg;
+ if (ndir >= dirsize)
+ {
+ dirsize *= 2;
+ dirarg = (char **) xrealloc ((char *)dirarg,
+ dirsize * sizeof (*dirarg));
+ }
+ break;
+ case 't':
+ ttyarg = optarg;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'b':
+ {
+ int i;
+ char *p;
+
+ i = strtol (optarg, &p, 0);
+ if (i == 0 && p == 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 ADDITIONAL_OPTION_CASES
+ ADDITIONAL_OPTION_CASES
+#endif
+ case '?':
+ fprintf_unfiltered (gdb_stderr,
+ "Use `%s --help' for a complete list of options.\n",
+ argv[0]);
+ exit (1);
+ }
+ }
+
+ /* If --help or --version, disable window interface. */
+ if (print_help || print_version)
+ use_windows = 0;
+
+ /* OK, that's all the options. The other arguments are filenames. */
+ count = 0;
+ for (; optind < argc; optind++)
+ switch (++count)
+ {
+ case 1:
+ symarg = argv[optind];
+ execarg = argv[optind];
+ break;
+ case 2:
+ corearg = argv[optind];
+ break;
+ case 3:
+ fprintf_unfiltered (gdb_stderr,
+ "Excess command line arguments ignored. (%s%s)\n",
+ argv[optind], (optind == argc - 1) ? "" : " ...");
+ break;
+ }
+ if (batch)
+ quiet = 1;
+ }
+
+#endif
+ gdb_init ();
+
+ /* Do these (and anything which might call wrap_here or *_filtered)
+ after initialize_all_files. */
+ if (print_version)
+ {
+ print_gdb_version (gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("\n");
+ exit (0);
+ }
+
+ if (print_help)
+ {
+ /* --version is intentionally not documented here, because we
+ are printing the version here, and the help is long enough
+ already. */
+
+ 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_unfiltered ("\
+This is the GNU debugger. Usage:\n\
+ gdb [options] [executable-file [core-file or process-id]]\n\
+Options:\n\
+ --help Print this message.\n\
+ --quiet Do not print version number on startup.\n\
+ --fullname Output information used by emacs-GDB interface.\n\
+ --epoch Output information used by epoch emacs-GDB interface.\n\
+", gdb_stdout);
+ fputs_unfiltered ("\
+ --batch Exit after processing options.\n\
+ --nx Do not read .gdbinit file.\n\
+ --tty=TTY Use TTY for input/output by the program being debugged.\n\
+ --cd=DIR Change current directory to DIR.\n\
+ --directory=DIR Search for source files in DIR.\n\
+", gdb_stdout);
+ fputs_unfiltered ("\
+ --command=FILE Execute GDB commands from FILE.\n\
+ --symbols=SYMFILE Read symbols from SYMFILE.\n\
+ --exec=EXECFILE Use EXECFILE as the executable.\n\
+ --se=FILE Use FILE as symbol file and executable file.\n\
+", gdb_stdout);
+ fputs_unfiltered ("\
+ --core=COREFILE Analyze the core dump COREFILE.\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\
+ --nw Do not use a window interface.\n\
+", gdb_stdout);
+#ifdef ADDITIONAL_OPTION_HELP
+ fputs_unfiltered (ADDITIONAL_OPTION_HELP, gdb_stdout);
+#endif
+ 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", gdb_stdout);
+ exit (0);
+ }
+
+ if (!quiet)
+ {
+ /* 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 (gdb_stdout);
+ if (symarg)
+ printf_filtered ("..");
+ wrap_here("");
+ gdb_flush (gdb_stdout); /* Force to screen during slow operations */
+ }
+
+ error_pre_print = "\n\n";
+ quit_pre_print = error_pre_print;
+
+ /* We may get more than one warning, don't double space all of them... */
+ warning_pre_print = "\nwarning: ";
+
+ /* 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
+ debugging or what directory you are in. */
+ homedir = getenv ("HOME");
+ if (homedir)
+ {
+ homeinit = (char *) alloca (strlen (getenv ("HOME")) +
+ strlen (gdbinit) + 10);
+ strcpy (homeinit, getenv ("HOME"));
+ strcat (homeinit, "/");
+ strcat (homeinit, gdbinit);
+
+ if (!inhibit_gdbinit && access (homeinit, R_OK) == 0)
+ {
+ if (!SET_TOP_LEVEL ())
+ source_command (homeinit, 0);
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ /* Do stats; no need to do them elsewhere since we'll only
+ need them if homedir is set. Make sure that they are
+ zero in case one of them fails (this guarantees that they
+ won't match if either exists). */
+
+ memset (&homebuf, 0, sizeof (struct stat));
+ memset (&cwdbuf, 0, sizeof (struct stat));
+
+ stat (homeinit, &homebuf);
+ stat (gdbinit, &cwdbuf); /* We'll only need this if
+ homedir was set. */
+ }
+
+ /* Now perform all the actions indicated by the arguments. */
+ if (cdarg != NULL)
+ {
+ if (!SET_TOP_LEVEL ())
+ {
+ cd_command (cdarg, 0);
+ }
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ for (i = 0; i < ndir; i++)
+ if (!SET_TOP_LEVEL ())
+ directory_command (dirarg[i], 0);
+ free ((PTR)dirarg);
+ do_cleanups (ALL_CLEANUPS);
+
+ if (execarg != NULL
+ && symarg != NULL
+ && STREQ (execarg, symarg))
+ {
+ /* The exec file and the symbol-file are the same. If we can't open
+ it, better only print one error message. */
+ if (!SET_TOP_LEVEL ())
+ {
+ exec_file_command (execarg, !batch);
+ symbol_file_command (symarg, 0);
+ }
+ }
+ else
+ {
+ if (execarg != NULL)
+ if (!SET_TOP_LEVEL ())
+ exec_file_command (execarg, !batch);
+ if (symarg != NULL)
+ if (!SET_TOP_LEVEL ())
+ symbol_file_command (symarg, 0);
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ /* After the symbol file has been read, print a newline to get us
+ beyond the copyright line... But errors should still set off
+ the error message with a (single) blank line. */
+ if (!quiet)
+ printf_filtered ("\n");
+ error_pre_print = "\n";
+ quit_pre_print = error_pre_print;
+ warning_pre_print = "\nwarning: ";
+
+ if (corearg != NULL)
+ if (!SET_TOP_LEVEL ())
+ core_file_command (corearg, !batch);
+ else if (isdigit (corearg[0]) && !SET_TOP_LEVEL ())
+ attach_command (corearg, !batch);
+ do_cleanups (ALL_CLEANUPS);
+
+ if (ttyarg != NULL)
+ if (!SET_TOP_LEVEL ())
+ tty_command (ttyarg, !batch);
+ do_cleanups (ALL_CLEANUPS);
+
+#ifdef ADDITIONAL_OPTION_HANDLER
+ ADDITIONAL_OPTION_HANDLER;
+#endif
+
+ /* Error messages should no longer be distinguished with extra output. */
+ error_pre_print = NULL;
+ quit_pre_print = NULL;
+ warning_pre_print = "warning: ";
+
+ /* Read the .gdbinit file in the current directory, *if* it isn't
+ the same as the $HOME/.gdbinit file (it should exist, also). */
+
+ if (!homedir
+ || memcmp ((char *) &homebuf, (char *) &cwdbuf, sizeof (struct stat)))
+ if (!inhibit_gdbinit && access (gdbinit, R_OK) == 0)
+ {
+ if (!SET_TOP_LEVEL ())
+ source_command (gdbinit, 0);
+ }
+ do_cleanups (ALL_CLEANUPS);
+
+ for (i = 0; i < ncmd; i++)
+ {
+ if (!SET_TOP_LEVEL ())
+ {
+ if (cmdarg[i][0] == '-' && cmdarg[i][1] == '\0')
+ read_command_file (stdin);
+ else
+ source_command (cmdarg[i], !batch);
+ do_cleanups (ALL_CLEANUPS);
+ }
+ }
+ free ((PTR)cmdarg);
+
+ /* Read in the old history after all the command files have been read. */
+ init_history();
+
+ if (batch)
+ {
+ /* We have hit the end of the batch file. */
+ exit (0);
+ }
+
+ /* Do any host- or target-specific hacks. This is used for i960 targets
+ to force the user to set a nindy target and spec its parameters. */
+
+#ifdef BEFORE_MAIN_LOOP_HOOK
+ BEFORE_MAIN_LOOP_HOOK;
+#endif
+
+ END_PROGRESS (argv[0]);
+
+ /* Show time and/or space usage. */
+
+ if (display_time)
+ {
+ long init_time = get_run_time () - time_at_startup;
+
+ printf_unfiltered ("Startup time: %ld.%06ld\n",
+ init_time / 1000000, init_time % 1000000);
+ }
+
+ if (display_space)
+ {
+#ifdef HAVE_SBRK
+ extern char **environ;
+ char *lim = (char *) sbrk (0);
+
+ printf_unfiltered ("Startup size: data size %ld\n",
+ (long) (lim - (char *) &environ));
+#endif
+ }
+
+ /* The default command loop.
+ The WIN32 Gui calls this main to set up gdb's state, and
+ has its own command loop. */
+#if !defined (WINGDB)
+ while (1)
+ {
+ if (!SET_TOP_LEVEL ())
+ {
+ do_cleanups (ALL_CLEANUPS); /* Do complete cleanup */
+ /* GUIs generally have their own command loop, mainloop, or whatever.
+ This is a good place to gain control because many error
+ conditions will end up here via longjmp(). */
+ if (command_loop_hook)
+ command_loop_hook ();
+ else
+ command_loop ();
+ quit_command ((char *)0, instream == stdin);
+ }
+ }
+
+ /* No exit -- exit is through quit_command. */
+#endif
+
+}
+
+void
+init_proc ()
+{
+}
+
+void
+proc_remove_foreign (pid)
+ int pid;
+{
+}
+
+void
+fputs_unfiltered (linebuffer, stream)
+ const char *linebuffer;
+ FILE *stream;
+{
+ if (fputs_unfiltered_hook)
+ {
+ /* FIXME: I think we should only be doing this for stdout or stderr.
+ Either that or we should be passing stream to the hook so it can
+ deal with it. If that is cleaned up, this function can go back
+ into utils.c and the fputs_unfiltered_hook can replace the current
+ ability to avoid this function by not linking with main.c. */
+ fputs_unfiltered_hook (linebuffer, stream);
+ return;
+ }
+
+ fputs (linebuffer, stream);
+}
diff --git a/contrib/gdb/gdb/maint.c b/contrib/gdb/gdb/maint.c
new file mode 100644
index 0000000..9ce342c
--- /dev/null
+++ b/contrib/gdb/gdb/maint.c
@@ -0,0 +1,370 @@
+/* Support for GDB maintenance commands.
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+
+#if MAINTENANCE_CMDS /* Entire rest of file goes away if not including maint cmds */
+
+#include <signal.h>
+#include "command.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "demangle.h"
+#include "gdbcore.h"
+#include "expression.h" /* For language.h */
+#include "language.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+static void maintenance_command PARAMS ((char *, int));
+
+static void maintenance_dump_me PARAMS ((char *, int));
+
+static void maintenance_demangle PARAMS ((char *, int));
+
+static void maintenance_time_display PARAMS ((char *, int));
+
+static void maintenance_space_display PARAMS ((char *, int));
+
+/* Set this to the maximum number of seconds to wait instead of waiting forever
+ in target_wait(). If this timer times out, then it generates an error and
+ the command is aborted. This replaces most of the need for timeouts in the
+ GDB test suite, and makes it possible to distinguish between a hung target
+ and one with slow communications. */
+
+int watchdog = 0;
+
+/*
+
+LOCAL FUNCTION
+
+ maintenance_command -- access the maintenance subcommands
+
+SYNOPSIS
+
+ void maintenance_command (char *args, int from_tty)
+
+DESCRIPTION
+
+*/
+
+static void
+maintenance_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered ("\"maintenance\" must be followed by the name of a maintenance command.\n");
+ help_list (maintenancelist, "maintenance ", -1, gdb_stdout);
+}
+
+
+/* ARGSUSED */
+static void
+maintenance_dump_me (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (query ("Should GDB dump core? "))
+ {
+ signal (SIGQUIT, SIG_DFL);
+ kill (getpid (), SIGQUIT);
+ }
+}
+
+/* Someday we should allow demangling for things other than just
+ explicit strings. For example, we might want to be able to
+ specify the address of a string in either GDB's process space
+ or the debuggee's process space, and have gdb fetch and demangle
+ that string. If we have a char* pointer "ptr" that points to
+ a string, we might want to be able to given just the name and
+ have GDB demangle and print what it points to, etc. (FIXME) */
+
+static void
+maintenance_demangle (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *demangled;
+
+ if (args == NULL || *args == '\0')
+ {
+ printf_unfiltered ("\"maintenance demangle\" takes an argument to demangle.\n");
+ }
+ else
+ {
+ demangled = cplus_demangle (args, DMGL_ANSI | DMGL_PARAMS);
+ if (demangled != NULL)
+ {
+ printf_unfiltered ("%s\n", demangled);
+ free (demangled);
+ }
+ else
+ {
+ printf_unfiltered ("Can't demangle \"%s\"\n", args);
+ }
+ }
+}
+
+static void
+maintenance_time_display (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int display_time;
+
+ if (args == NULL || *args == '\0')
+ printf_unfiltered ("\"maintenance time\" takes a numeric argument.\n");
+ else
+ display_time = strtol (args, NULL, 10);
+}
+
+static void
+maintenance_space_display (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int display_space;
+
+ if (args == NULL || *args == '\0')
+ printf_unfiltered ("\"maintenance space\" takes a numeric argument.\n");
+ else
+ display_space = strtol (args, NULL, 10);
+}
+
+/* The "maintenance info" command is defined as a prefix, with allow_unknown 0.
+ Therefore, its own definition is called only for "maintenance info" with
+ no args. */
+
+/* ARGSUSED */
+static void
+maintenance_info_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ 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
+print_section_table (abfd, asect, ignore)
+ bfd *abfd;
+ asection *asect;
+ PTR ignore;
+{
+ flagword flags;
+
+ 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"));
+ printf_filtered ("->%s",
+ local_hex_string_custom
+ ((unsigned long) (bfd_section_vma (abfd, asect)
+ + bfd_section_size (abfd, asect)),
+ "08l"));
+ printf_filtered (" at %s",
+ local_hex_string_custom
+ ((unsigned long) asect->filepos, "08l"));
+ printf_filtered (": %s", bfd_section_name (abfd, asect));
+
+ if (flags & SEC_ALLOC)
+ printf_filtered (" ALLOC");
+ if (flags & SEC_LOAD)
+ printf_filtered (" LOAD");
+ if (flags & SEC_RELOC)
+ printf_filtered (" RELOC");
+ if (flags & SEC_READONLY)
+ printf_filtered (" READONLY");
+ if (flags & SEC_CODE)
+ printf_filtered (" CODE");
+ if (flags & SEC_DATA)
+ printf_filtered (" DATA");
+ if (flags & SEC_ROM)
+ printf_filtered (" ROM");
+ if (flags & SEC_CONSTRUCTOR)
+ printf_filtered (" CONSTRUCTOR");
+ if (flags & SEC_HAS_CONTENTS)
+ printf_filtered (" HAS_CONTENTS");
+ if (flags & SEC_NEVER_LOAD)
+ printf_filtered (" NEVER_LOAD");
+ if (flags & SEC_COFF_SHARED_LIBRARY)
+ printf_filtered (" COFF_SHARED_LIBRARY");
+ if (flags & SEC_IS_COMMON)
+ printf_filtered (" IS_COMMON");
+
+ printf_filtered ("\n");
+}
+
+/* ARGSUSED */
+static void
+maintenance_info_sections (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (exec_bfd)
+ {
+ printf_filtered ("Exec file:\n");
+ printf_filtered (" `%s', ", bfd_get_filename(exec_bfd));
+ wrap_here (" ");
+ printf_filtered ("file type %s.\n", bfd_get_target(exec_bfd));
+ bfd_map_over_sections(exec_bfd, print_section_table, 0);
+ }
+
+ if (core_bfd)
+ {
+ printf_filtered ("Core file:\n");
+ printf_filtered (" `%s', ", bfd_get_filename(core_bfd));
+ wrap_here (" ");
+ printf_filtered ("file type %s.\n", bfd_get_target(core_bfd));
+ bfd_map_over_sections(core_bfd, print_section_table, 0);
+ }
+}
+
+/* ARGSUSED */
+void
+maintenance_print_statistics (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ print_objfile_statistics ();
+ print_symbol_bcache_statistics ();
+}
+
+/* The "maintenance print" command is defined as a prefix, with allow_unknown
+ 0. Therefore, its own definition is called only for "maintenance print"
+ with no args. */
+
+/* ARGSUSED */
+static void
+maintenance_print_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf_unfiltered ("\"maintenance print\" must be followed by the name of a print command.\n");
+ help_list (maintenanceprintlist, "maintenance print ", -1, gdb_stdout);
+}
+
+#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\
+a human readable form, to cause GDB to deliberately dump core,\n\
+to test internal functions such as the C++ demangler, etc.",
+ &maintenancelist, "maintenance ", 0,
+ &cmdlist);
+
+ add_com_alias ("mt", "maintenance", class_maintenance, 1);
+
+ add_prefix_cmd ("info", class_maintenance, maintenance_info_command,
+ "Commands for showing internal info about the program being debugged.",
+ &maintenanceinfolist, "maintenance info ", 0,
+ &maintenancelist);
+
+ add_cmd ("sections", class_maintenance, maintenance_info_sections,
+ "List the BFD sections of the exec and core files.",
+ &maintenanceinfolist);
+
+ add_prefix_cmd ("print", class_maintenance, maintenance_print_command,
+ "Maintenance command for printing GDB internal state.",
+ &maintenanceprintlist, "maintenance print ", 0,
+ &maintenancelist);
+
+ add_cmd ("dump-me", class_maintenance, maintenance_dump_me,
+ "Get fatal error; make debugger dump its core.\n\
+GDB sets it's handling of SIGQUIT back to SIG_DFL and then sends\n\
+itself a SIGQUIT signal.",
+ &maintenancelist);
+
+ add_cmd ("demangle", class_maintenance, maintenance_demangle,
+ "Demangle a C++ mangled name.\n\
+Call internal GDB demangler routine to demangle a C++ link name\n\
+and prints the result.",
+ &maintenancelist);
+
+ add_cmd ("time", class_maintenance, maintenance_time_display,
+ "Set the display of time usage.\n\
+If nonzero, will cause the execution time for each command to be\n\
+displayed, following the command's output.",
+ &maintenancelist);
+
+ add_cmd ("space", class_maintenance, maintenance_space_display,
+ "Set the display of space usage.\n\
+If nonzero, will cause the execution space for each command to be\n\
+displayed, following the command's output.",
+ &maintenancelist);
+
+ add_cmd ("type", class_maintenance, maintenance_print_type,
+ "Print a type chain for a given symbol.\n\
+For each node in a type chain, print the raw data for each member of\n\
+the type structure, and the interpretation of the data.",
+ &maintenanceprintlist);
+
+ add_cmd ("symbols", class_maintenance, maintenance_print_symbols,
+ "Print dump of current symbol definitions.\n\
+Entries in the full symbol table are dumped to file OUTFILE.\n\
+If a SOURCE file is specified, dump only that file's symbols.",
+ &maintenanceprintlist);
+
+ add_cmd ("msymbols", class_maintenance, maintenance_print_msymbols,
+ "Print dump of current minimal symbol definitions.\n\
+Entries in the minimal symbol table are dumped to file OUTFILE.\n\
+If a SOURCE file is specified, dump only that file's minimal symbols.",
+ &maintenanceprintlist);
+
+ add_cmd ("psymbols", class_maintenance, maintenance_print_psymbols,
+ "Print dump of current partial symbol definitions.\n\
+Entries in the partial symbol table are dumped to file OUTFILE.\n\
+If a SOURCE file is specified, dump only that file's partial symbols.",
+ &maintenanceprintlist);
+
+ add_cmd ("objfiles", class_maintenance, maintenance_print_objfiles,
+ "Print dump of current object file definitions.",
+ &maintenanceprintlist);
+
+ add_cmd ("statistics", class_maintenance, maintenance_print_statistics,
+ "Print statistics about internal gdb state.",
+ &maintenanceprintlist);
+
+ add_cmd ("check-symtabs", class_maintenance, maintenance_check_symtabs,
+ "Check consistency of psymtabs and symtabs.",
+ &maintenancelist);
+
+ add_show_from_set (
+ add_set_cmd ("watchdog", class_maintenance, var_zinteger, (char *)&watchdog,
+ "Set watchdog timer.\n\
+When non-zero, this timeout is used instead of waiting forever for a target to\n\
+finish a low-level step or continue operation. If the specified amount of time\n\
+passes without a response from the target, an error occurs.", &setlist),
+ &showlist);
+#endif /* MAINTENANCE_CMDS */
+}
diff --git a/contrib/gdb/gdb/mdebugread.c b/contrib/gdb/gdb/mdebugread.c
new file mode 100644
index 0000000..3fe4f96
--- /dev/null
+++ b/contrib/gdb/gdb/mdebugread.c
@@ -0,0 +1,4368 @@
+/* Read a symbol table in ECOFF format (Third-Eye).
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+ Original version contributed by Alessandro Forin (af@cs.cmu.edu) at
+ CMU. Major work by Per Bothner, John Gilmore and Ian Lance Taylor
+ at Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module provides the function mdebug_build_psymtabs. It reads
+ ECOFF debugging information into partial symbol tables. The
+ debugging information is read from two structures. A struct
+ ecoff_debug_swap includes the sizes of each ECOFF structure and
+ swapping routines; these are fixed for a particular target. A
+ struct ecoff_debug_info points to the debugging information for a
+ particular object file.
+
+ 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. */
+
+#include "defs.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"
+#include "demangle.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 <sys/types.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include "gdb_stat.h"
+#include "gdb_string.h"
+
+#include "gdb-stabs.h"
+
+#include "bfd.h"
+
+#include "coff/ecoff.h" /* COFF-like aspects of ecoff files */
+
+#include "libaout.h" /* Private BFD a.out information. */
+#include "aout/aout64.h"
+#include "aout/stab_gnu.h" /* STABS 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
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc
+{
+ /* Index of the FDR that this psymtab represents. */
+ int fdr_idx;
+ /* The BFD that the psymtab was created from. */
+ bfd *cur_bfd;
+ const struct ecoff_debug_swap *debug_swap;
+ struct ecoff_debug_info *debug_info;
+ struct mdebug_pending **pending_list;
+ /* Pointer to external symbols for this file. */
+ EXTR *extern_tab;
+ /* Size of extern_tab. */
+ int extern_count;
+ enum language pst_language;
+};
+
+#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)
+#define DEBUG_SWAP(p) (PST_PRIVATE(p)->debug_swap)
+#define DEBUG_INFO(p) (PST_PRIVATE(p)->debug_info)
+#define PENDING_LIST(p) (PST_PRIVATE(p)->pending_list)
+
+/* Things we import explicitly from other modules */
+
+extern int info_verbose;
+
+/* Various complaints about symbol reading that don't abort the process */
+
+static struct complaint bad_file_number_complaint =
+{"bad file number %d", 0, 0};
+
+static struct complaint index_complaint =
+{"bad aux index at symbol %s", 0, 0};
+
+static struct complaint aux_index_complaint =
+{"bad proc end in aux found from symbol %s", 0, 0};
+
+static struct complaint block_index_complaint =
+{"bad aux index at block symbol %s", 0, 0};
+
+static struct complaint unknown_ext_complaint =
+{"unknown external symbol %s", 0, 0};
+
+static struct complaint unknown_sym_complaint =
+{"unknown local symbol %s", 0, 0};
+
+static struct complaint unknown_st_complaint =
+{"with type %d", 0, 0};
+
+static struct complaint block_overflow_complaint =
+{"block containing %s overfilled", 0, 0};
+
+static struct complaint basic_type_complaint =
+{"cannot map ECOFF basic type 0x%x for %s", 0, 0};
+
+static struct complaint unknown_type_qual_complaint =
+{"unknown type qualifier 0x%x", 0, 0};
+
+static struct complaint array_index_type_complaint =
+{"illegal array index type for %s, assuming int", 0, 0};
+
+static struct complaint bad_tag_guess_complaint =
+{"guessed tag type of %s incorrectly", 0, 0};
+
+static struct complaint block_member_complaint =
+{"declaration block contains unhandled symbol type %d", 0, 0};
+
+static struct complaint stEnd_complaint =
+{"stEnd with storage class %d not handled", 0, 0};
+
+static struct complaint unknown_mdebug_symtype_complaint =
+{"unknown symbol type 0x%x", 0, 0};
+
+static struct complaint stab_unknown_complaint =
+{"unknown stabs symbol %s", 0, 0};
+
+static struct complaint pdr_for_nonsymbol_complaint =
+{"PDR for %s, but no symbol", 0, 0};
+
+static struct complaint pdr_static_symbol_complaint =
+{"can't handle PDR for static proc at 0x%lx", 0, 0};
+
+static struct complaint bad_setjmp_pdr_complaint =
+{"fixing bad setjmp PDR from libc", 0, 0};
+
+static struct complaint bad_fbitfield_complaint =
+{"can't handle TIR fBitfield for %s", 0, 0};
+
+static struct complaint bad_continued_complaint =
+{"illegal TIR continued for %s", 0, 0};
+
+static struct complaint bad_rfd_entry_complaint =
+{"bad rfd entry for %s: file %d, index %d", 0, 0};
+
+static struct complaint unexpected_type_code_complaint =
+{"unexpected type code for %s", 0, 0};
+
+static struct complaint unable_to_cross_ref_complaint =
+{"unable to cross ref btTypedef for %s", 0, 0};
+
+static struct complaint bad_indirect_xref_complaint =
+{"unable to cross ref btIndirect for %s", 0, 0};
+
+static struct complaint illegal_forward_tq0_complaint =
+{"illegal tq0 in forward typedef for %s", 0, 0};
+
+static struct complaint illegal_forward_bt_complaint =
+{"illegal bt %d in forward typedef for %s", 0, 0};
+
+static struct complaint bad_linetable_guess_complaint =
+{"guessed size of linetable for %s incorrectly", 0, 0};
+
+static struct complaint bad_ext_ifd_complaint =
+{"bad ifd for external symbol: %d (max %d)", 0, 0};
+
+static struct complaint bad_ext_iss_complaint =
+{"bad iss for external symbol: %ld (max %ld)", 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;
+
+/* How to parse debugging information for CUR_BFD. */
+
+static const struct ecoff_debug_swap *debug_swap;
+
+/* Pointers to debugging information for CUR_BFD. */
+
+static struct ecoff_debug_info *debug_info;
+
+/* 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;
+
+/* Types corresponding to mdebug format bt* basic types. */
+
+static struct type *mdebug_type_void;
+static struct type *mdebug_type_char;
+static struct type *mdebug_type_short;
+static struct type *mdebug_type_int_32;
+#define mdebug_type_int mdebug_type_int_32
+static struct type *mdebug_type_int_64;
+static struct type *mdebug_type_long_32;
+static struct type *mdebug_type_long_64;
+static struct type *mdebug_type_long_long_64;
+static struct type *mdebug_type_unsigned_char;
+static struct type *mdebug_type_unsigned_short;
+static struct type *mdebug_type_unsigned_int_32;
+static struct type *mdebug_type_unsigned_int_64;
+static struct type *mdebug_type_unsigned_long_32;
+static struct type *mdebug_type_unsigned_long_64;
+static struct type *mdebug_type_unsigned_long_long_64;
+static struct type *mdebug_type_adr_32;
+static struct type *mdebug_type_adr_64;
+static struct type *mdebug_type_float;
+static struct type *mdebug_type_double;
+static struct type *mdebug_type_complex;
+static struct type *mdebug_type_double_complex;
+static struct type *mdebug_type_fixed_dec;
+static struct type *mdebug_type_float_dec;
+static struct type *mdebug_type_string;
+
+/* Types for symbols from files compiled without debugging info. */
+
+static struct type *nodebug_func_symbol_type;
+static struct type *nodebug_var_symbol_type;
+
+/* Nonzero if we have seen ecoff debugging info for a file. */
+
+static int found_ecoff_debugging_info;
+
+/* Forward declarations */
+
+static int
+upgrade_type PARAMS ((int, struct type **, int, union aux_ext *, int, char *));
+
+static void
+parse_partial_symbols PARAMS ((struct objfile *,
+ struct section_offsets *));
+
+static FDR
+*get_rfd PARAMS ((int, int));
+
+static int
+has_opaque_xref PARAMS ((FDR *, SYMR *));
+
+static int
+cross_ref PARAMS ((int, union aux_ext *, struct type **, enum type_code,
+ char **, int, char *));
+
+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, struct section_offsets *));
+
+static struct type *
+parse_type PARAMS ((int, union aux_ext *, unsigned int, int *, int, char *));
+
+static struct symbol *
+mylookup_symbol PARAMS ((char *, struct block *, namespace_enum,
+ enum address_class));
+
+static struct block *
+shrink_block PARAMS ((struct block *, struct symtab *));
+
+static PTR
+xzalloc PARAMS ((unsigned int));
+
+static void
+sort_blocks PARAMS ((struct symtab *));
+
+static int
+compare_blocks PARAMS ((const void *, const void *));
+
+static struct partial_symtab *
+new_psymtab PARAMS ((char *, struct objfile *, struct section_offsets *));
+
+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 void
+handle_psymbol_enumerators PARAMS ((struct objfile *, FDR *, int, CORE_ADDR));
+
+static char *
+mdebug_next_symbol_text PARAMS ((struct objfile *));
+
+/* Address bounds for the signal trampoline in inferior, if any */
+
+CORE_ADDR sigtramp_address, sigtramp_end;
+
+/* 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
+mdebug_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+
+ if (!pst)
+ return;
+
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ gdb_flush (gdb_stdout);
+ }
+
+ next_symbol_text_func = mdebug_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");
+}
+
+/* File-level interface functions */
+
+/* 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 = debug_info->fdr;
+ f = fdrs + cf;
+ /* Object files do not have the RFD table, all refs are absolute */
+ if (f->rfdBase == 0)
+ return fdrs + rf;
+ (*debug_swap->swap_rfd_in) (cur_bfd,
+ ((char *) debug_info->external_rfd
+ + ((f->rfdBase + rf)
+ * debug_swap->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 "<stripped file>";
+ if (f->rss == 0)
+ return "<NFY>";
+ return debug_info->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. */
+
+void
+mdebug_build_psymtabs (objfile, swap, info, section_offsets)
+ struct objfile *objfile;
+ const struct ecoff_debug_swap *swap;
+ struct ecoff_debug_info *info;
+ struct section_offsets *section_offsets;
+{
+ cur_bfd = objfile->obfd;
+ debug_swap = swap;
+ debug_info = info;
+
+ /* Make sure all the FDR information is swapped in. */
+ if (info->fdr == (FDR *) NULL)
+ {
+ char *fdr_src;
+ char *fdr_end;
+ FDR *fdr_ptr;
+
+ info->fdr = (FDR *) obstack_alloc (&objfile->psymbol_obstack,
+ (info->symbolic_header.ifdMax
+ * sizeof (FDR)));
+ fdr_src = info->external_fdr;
+ fdr_end = (fdr_src
+ + info->symbolic_header.ifdMax * swap->external_fdr_size);
+ fdr_ptr = info->fdr;
+ for (; fdr_src < fdr_end; fdr_src += swap->external_fdr_size, fdr_ptr++)
+ (*swap->swap_fdr_in) (objfile->obfd, fdr_src, fdr_ptr);
+ }
+
+ 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_unfiltered ("\n%s not compiled with -g, debugging support is limited.\n",
+ objfile->name);
+ printf_unfiltered ("You should compile with -g2 or -g3 for best debugging support.\n");
+ gdb_flush (gdb_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. */
+
+ /* What are we parsing. stFile, or stBlock are for files and
+ blocks. stProc or stStaticProc means we have seen the start of a
+ procedure, but not the start of the block within in. When we see
+ the start of that block, we change it to stNil, without pushing a
+ new block, i.e. stNil means both a procedure and a block. */
+
+ int blocktype;
+
+ 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 mdebug_pending
+{
+ struct mdebug_pending *next; /* link */
+ char *s; /* the unswapped symbol */
+ struct type *t; /* its partial type descriptor */
+};
+
+
+/* The pending information is kept for an entire object file, and used
+ to be in the sym_private field. I took it out when I split
+ mdebugread from mipsread, because this might not be the only type
+ of symbols read from an object file. Instead, we allocate the
+ pending information table when we create the partial symbols, and
+ we store a pointer to the single table in each psymtab. */
+
+static struct mdebug_pending **pending_list;
+
+/* Check whether we already saw symbol SH in file FH */
+
+static struct mdebug_pending *
+is_pending_symbol (fh, sh)
+ FDR *fh;
+ char *sh;
+{
+ int f_idx = fh - debug_info->fdr;
+ register struct mdebug_pending *p;
+
+ /* 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 - debug_info->fdr;
+ struct mdebug_pending *p = is_pending_symbol (fh, sh);
+
+ /* Make sure we do not make duplicates */
+ if (!p)
+ {
+ p = ((struct mdebug_pending *)
+ obstack_alloc (&current_objfile->psymbol_obstack,
+ sizeof (struct mdebug_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, section_offsets)
+ SYMR *sh;
+ union aux_ext *ax;
+ char *ext_sh;
+ int bigend;
+ struct section_offsets *section_offsets;
+{
+ const bfd_size_type external_sym_size = debug_swap->external_sym_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *)) =
+ debug_swap->swap_sym_in;
+ char *name;
+ struct symbol *s;
+ struct block *b;
+ struct mdebug_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 = debug_info->ssext + sh->iss;
+ else
+ name = debug_info->ss + cur_fdr->issBase + sh->iss;
+
+ switch (sh->sc)
+ {
+ case scText:
+ /* Do not relocate relative values.
+ The value of a stEnd symbol is the displacement from the
+ corresponding start symbol value.
+ The value of a stBlock symbol is the displacement from the
+ procedure address. */
+ if (sh->st != stEnd && sh->st != stBlock)
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ sh->value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
+ 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 || sh->sc == scSCommon)
+ {
+ /* 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 if file is compiled without debugging info. */
+ if (sh->sc == scUndefined || sh->sc == scNil || sh->index == indexNil)
+ SYMBOL_TYPE (s) = nodebug_var_symbol_type;
+ 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++;
+ found_ecoff_debugging_info = 1;
+ top_stack->numargs++;
+
+ /* Special GNU C++ name. */
+ if (is_cplus_marker (name[0]) && 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);
+ 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) = mdebug_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 = mdebug_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);
+ /* Irix 5 sometimes has duplicate names for the same
+ function. We want to add such names up at the global
+ level, not as a nested function. */
+ else if (sh->value == top_stack->procadr)
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ }
+ add_symbol (s, b);
+
+ /* Make a type for the procedure itself */
+ SYMBOL_TYPE (s) = lookup_function_type (t);
+
+ /* 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 && sh->sc != scSCommon)
+ 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:
+ found_ecoff_debugging_info = 1;
+ 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.
+ Alpha cc -migrate enums are recognized by a zero
+ index and a zero symbol value. */
+ if (tsym.index == indexNil
+ || (tsym.index == 0 && sh->value == 0))
+ type_code = TYPE_CODE_ENUM;
+ else
+ {
+ (*debug_swap->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 *) debug_info->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;
+
+ case stIndirect:
+ /* Irix5 cc puts out a stIndirect 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 mdebug_pending *) NULL)
+ {
+ t = new_type (NULL);
+ add_pending (cur_fdr, ext_sh, t);
+ }
+ else
+ t = pend->t;
+
+ /* Do not set the tag name if it is a compiler generated tag name
+ (.Fxx or .xxfake or empty) for unnamed struct/union/enums.
+ Alpha cc puts out an sh->iss of zero for those. */
+ if (sh->iss == 0 || name[0] == '.' || name[0] == '\0')
+ TYPE_TAG_NAME (t) = NULL;
+ else
+ TYPE_TAG_NAME (t) = obconcat (&current_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)
+ {
+ int unsigned_enum = 1;
+
+ /* This is a non-empty enum. */
+
+ /* DEC c89 has the number of enumerators in the sh.value field,
+ not the type length, so we have to compensate for that
+ incompatibility quirk.
+ This might do the wrong thing for an enum with one or two
+ enumerators and gcc -gcoff -fshort-enums, but these cases
+ are hopefully rare enough.
+ Alpha cc -migrate has a sh.value field of zero, we adjust
+ that too. */
+ if (TYPE_LENGTH (t) == TYPE_NFIELDS (t)
+ || TYPE_LENGTH (t) == 0)
+ TYPE_LENGTH (t) = TARGET_INT_BIT / HOST_CHAR_BIT;
+ 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 = debug_info->ss + cur_fdr->issBase + tsym.iss;
+ f->bitsize = 0;
+
+ enum_sym = ((struct symbol *)
+ obstack_alloc (&current_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;
+ if (SYMBOL_VALUE (enum_sym) < 0)
+ unsigned_enum = 0;
+ add_symbol (enum_sym, top_stack->cur_block);
+
+ /* Skip the stMembers that we've handled. */
+ count++;
+ f++;
+ }
+ if (unsigned_enum)
+ TYPE_FLAGS (t) |= TYPE_FLAG_UNSIGNED;
+ }
+ /* 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;
+
+ /* gcc puts out an empty struct for an opaque struct definitions,
+ do not create a symbol for it either. */
+ if (TYPE_NFIELDS (t) == 0)
+ {
+ TYPE_FLAGS (t) |= TYPE_FLAG_STUB;
+ break;
+ }
+
+ s = new_symbol (name);
+ SYMBOL_NAMESPACE (s) = STRUCT_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_TYPEDEF;
+ SYMBOL_VALUE (s) = 0;
+ SYMBOL_TYPE (s) = t;
+ 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:
+ found_ecoff_debugging_info = 1;
+ /* beginnning of (code) block. Value of symbol
+ is the displacement from procedure start */
+ push_parse_stack ();
+
+ /* Do not start a new block if this is the outermost block of a
+ procedure. This allows the LOC_BLOCK symbol to point to the
+ block with the local variables, so funcname::var works. */
+ if (top_stack->blocktype == stProc
+ || top_stack->blocktype == stStaticProc)
+ {
+ top_stack->blocktype = stNil;
+ break;
+ }
+
+ 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 || sh->sc == scSCommon)
+ {
+ /* 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;
+ struct type *ftype = top_stack->cur_type;
+ 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) = mdebug_type_void;
+ e = ((struct mips_extra_func_info *)
+ obstack_alloc (&current_objfile->symbol_obstack,
+ sizeof (struct mips_extra_func_info)));
+ memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
+ SYMBOL_VALUE (s) = (long) e;
+ e->numargs = top_stack->numargs;
+ e->pdr.framereg = -1;
+ 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);
+ }
+ }
+
+ if (TYPE_NFIELDS (ftype) <= 0)
+ {
+ /* No parameter type information is recorded with the function's
+ type. Set that from the type of the parameter symbols. */
+ int nparams = top_stack->numargs;
+ int iparams;
+ struct symbol *sym;
+
+ if (nparams > 0)
+ {
+ TYPE_NFIELDS (ftype) = nparams;
+ TYPE_FIELDS (ftype) = (struct field *)
+ TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+
+ for (i = iparams = 0; iparams < nparams; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ TYPE_FIELD_TYPE (ftype, iparams) = SYMBOL_TYPE (sym);
+ iparams++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ 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 == stNil)
+ {
+ /* End of outermost block. Pop parse stack and ignore. The
+ following stEnd of stProc will take care of the block. */
+ ;
+ }
+ 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 stIndirect: /* forward declaration on Irix5 */
+ /* Forward declarations from Irix5 cc are handled by cross_ref,
+ skip them. */
+ break;
+
+ case stTypedef: /* type definition */
+ found_ecoff_debugging_info = 1;
+
+ /* 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 mdebug_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 and Irix5 cc. */
+
+ /* However if the typedef cross references to an opaque aggregate, it
+ is safe to omit it from the symbol table. */
+
+ if (has_opaque_xref (cur_fdr, sh))
+ break;
+ 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_mdebug_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[] =
+ {
+ &mdebug_type_void, /* btNil */
+ &mdebug_type_adr_32, /* btAdr */
+ &mdebug_type_char, /* btChar */
+ &mdebug_type_unsigned_char, /* btUChar */
+ &mdebug_type_short, /* btShort */
+ &mdebug_type_unsigned_short, /* btUShort */
+ &mdebug_type_int_32, /* btInt */
+ &mdebug_type_unsigned_int_32, /* btUInt */
+ &mdebug_type_long_32, /* btLong */
+ &mdebug_type_unsigned_long_32, /* btULong */
+ &mdebug_type_float, /* btFloat */
+ &mdebug_type_double, /* btDouble */
+ 0, /* btStruct */
+ 0, /* btUnion */
+ 0, /* btEnum */
+ 0, /* btTypedef */
+ 0, /* btRange */
+ 0, /* btSet */
+ &mdebug_type_complex, /* btComplex */
+ &mdebug_type_double_complex, /* btDComplex */
+ 0, /* btIndirect */
+ &mdebug_type_fixed_dec, /* btFixedDec */
+ &mdebug_type_float_dec, /* btFloatDec */
+ &mdebug_type_string, /* btString */
+ 0, /* btBit */
+ 0, /* btPicture */
+ &mdebug_type_void, /* btVoid */
+ 0, /* DEC C++: Pointer to member */
+ 0, /* DEC C++: Virtual function table */
+ 0, /* DEC C++: Class (Record) */
+ &mdebug_type_long_64, /* btLong64 */
+ &mdebug_type_unsigned_long_64, /* btULong64 */
+ &mdebug_type_long_long_64, /* btLongLong64 */
+ &mdebug_type_unsigned_long_long_64, /* btULongLong64 */
+ &mdebug_type_adr_64, /* btAdr64 */
+ &mdebug_type_int_64, /* btInt64 */
+ &mdebug_type_unsigned_int_64, /* btUInt64 */
+ };
+
+ TIR t[1];
+ struct type *tp = 0;
+ enum type_code type_code = TYPE_CODE_UNDEF;
+
+ /* Handle undefined types, they have indexNil. */
+ if (aux_index == indexNil)
+ return mdebug_type_int;
+
+ /* Handle corrupt aux indices. */
+ if (aux_index >= (debug_info->fdr + fd)->caux)
+ {
+ complain (&index_complaint, sym_name);
+ return mdebug_type_int;
+ }
+ ax += aux_index;
+
+ /* Use aux as a type information record, map its basic type. */
+ (*debug_swap->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 mdebug_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 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 btIndirect:
+ /* alpha cc -migrate uses this for typedefs. The true type will
+ be obtained by crossreferencing below. */
+ type_code = TYPE_CODE_ERROR;
+ 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 mdebug_type_int;
+ }
+ }
+
+ /* Move on to next aux */
+ ax++;
+
+ if (t->fBitfield)
+ {
+ int width = AUX_GET_WIDTH (bigend, ax);
+
+ /* Inhibit core dumps with some cfront generated objects that
+ corrupt the TIR. */
+ if (bs == (int *)NULL)
+ {
+ /* Alpha cc -migrate encodes char and unsigned char types
+ as short and unsigned short types with a field width of 8.
+ Enum types also have a field width which we ignore for now. */
+ if (t->bt == btShort && width == 8)
+ tp = mdebug_type_char;
+ else if (t->bt == btUShort && width == 8)
+ tp = mdebug_type_unsigned_char;
+ else if (t->bt == btEnum)
+ ;
+ else
+ complain (&bad_fbitfield_complaint, sym_name);
+ }
+ else
+ *bs = width;
+ ax++;
+ }
+
+ /* A btIndirect entry cross references to an aux entry containing
+ the type. */
+ if (t->bt == btIndirect)
+ {
+ RNDXR rn[1];
+ int rf;
+ FDR *xref_fh;
+ int xref_fd;
+
+ (*debug_swap->swap_rndx_in) (bigend, &ax->a_rndx, rn);
+ ax++;
+ if (rn->rfd == 0xfff)
+ {
+ rf = AUX_GET_ISYM (bigend, ax);
+ ax++;
+ }
+ else
+ rf = rn->rfd;
+
+ if (rf == -1)
+ {
+ complain (&bad_indirect_xref_complaint, sym_name);
+ return mdebug_type_int;
+ }
+ xref_fh = get_rfd (fd, rf);
+ xref_fd = xref_fh - debug_info->fdr;
+ tp = parse_type (xref_fd, debug_info->external_aux + xref_fh->iauxBase,
+ rn->index, (int *) NULL, xref_fh->fBigendian, sym_name);
+ }
+
+ /* 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);
+
+ /* DEC c89 produces cross references to qualified aggregate types,
+ dereference them. */
+ while (TYPE_CODE (tp) == TYPE_CODE_PTR
+ || TYPE_CODE (tp) == TYPE_CODE_ARRAY)
+ tp = tp->target_type;
+
+ /* 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),
+ &current_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: We are not doing any guessing on range types. */
+ if (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),
+ &current_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 = mdebug_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"),
+ &current_objfile->type_obstack);
+ TYPE_FIELD_BITPOS (tp, 0) = AUX_GET_DNLOW (bigend, ax);
+ ax++;
+ TYPE_FIELD_NAME (tp, 1) = obsavestring ("High", strlen ("High"),
+ &current_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;
+
+ (*debug_swap->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) */
+ (*debug_swap->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 (fh - debug_info->fdr,
+ debug_info->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 = mdebug_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. */
+
+ /* TYPE_FLAG_TARGET_STUB now takes care of the zero TYPE_LENGTH
+ problem. */
+ if (TYPE_LENGTH (*tpp) == 0)
+ {
+ TYPE_FLAGS (t) |= TYPE_FLAG_TARGET_STUB;
+ }
+
+ *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 *, CORE_ADDR,
+ struct partial_symtab *));
+
+static void
+parse_procedure (pr, search_symtab, lowest_pdr_addr, pst)
+ PDR *pr;
+ struct symtab *search_symtab;
+ CORE_ADDR lowest_pdr_addr;
+ struct partial_symtab *pst;
+{
+ 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. */
+ /* FIXME-32x64. assuming pr->adr fits in long. */
+ complain (&pdr_static_symbol_complaint, (unsigned long) pr->adr);
+ return;
+ }
+ else
+ {
+ /* external */
+ EXTR she;
+
+ (*debug_swap->swap_ext_in) (cur_bfd,
+ ((char *) debug_info->external_ext
+ + (pr->isym
+ * debug_swap->external_ext_size)),
+ &she);
+ sh_name = debug_info->ssext + she.asym.iss;
+ }
+ }
+ else
+ {
+ /* Full symbols */
+ SYMR sh;
+
+ (*debug_swap->swap_sym_in) (cur_bfd,
+ ((char *) debug_info->external_sym
+ + ((cur_fdr->isymBase + pr->isym)
+ * debug_swap->external_sym_size)),
+ &sh);
+ sh_name = debug_info->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 (mdebug_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 += pst->textlow - lowest_pdr_addr;
+
+ /* 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;
+ }
+ }
+
+ /* It would be reasonable that functions that have been compiled
+ without debugging info have a btNil type for their return value,
+ and functions that are void and are compiled with debugging info
+ have btVoid.
+ gcc and DEC f77 put out btNil types for both cases, so btNil is mapped
+ to TYPE_CODE_VOID in parse_type to get the `compiled with debugging info'
+ case right.
+ The glevel field in cur_fdr could be used to determine the presence
+ of debugging info, but GCC doesn't always pass the -g switch settings
+ to the assembler and GAS doesn't set the glevel field from the -g switch
+ settings.
+ To work around these problems, the return value type of a TYPE_CODE_VOID
+ function is adjusted accordingly if no debugging info was found in the
+ compilation unit. */
+
+ if (processing_gcc_compilation == 0
+ && found_ecoff_debugging_info == 0
+ && TYPE_CODE (TYPE_TARGET_TYPE (SYMBOL_TYPE (s))) == TYPE_CODE_VOID)
+ SYMBOL_TYPE (s) = nodebug_func_symbol_type;
+}
+
+/* Relocate the extra function info pointed to by the symbol table. */
+
+void
+ecoff_relocate_efi (sym, delta)
+ struct symbol *sym;
+ CORE_ADDR delta;
+{
+ struct mips_extra_func_info *e;
+
+ e = (struct mips_extra_func_info *) SYMBOL_VALUE (sym);
+
+ e->pdr.adr += delta;
+}
+
+/* Parse the external symbol ES. Just call parse_symbol() after
+ making sure we know where the aux are for it.
+ 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 PARAMS ((EXTR *, int, struct section_offsets *));
+
+static void
+parse_external (es, bigend, section_offsets)
+ EXTR *es;
+ int bigend;
+ struct section_offsets *section_offsets;
+{
+ union aux_ext *ax;
+
+ if (es->ifd != ifdNil)
+ {
+ cur_fd = es->ifd;
+ cur_fdr = debug_info->fdr + cur_fd;
+ ax = debug_info->external_aux + cur_fdr->iauxBase;
+ }
+ else
+ {
+ cur_fdr = debug_info->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, debug_info->ssext + es->asym.iss,
+ fdr_name (cur_fdr));
+ return;
+ }
+
+ switch (es->asym.st)
+ {
+ case stProc:
+ case stStaticProc:
+ /* There is no need to parse the external procedure symbols.
+ If they are from objects compiled without -g, their index will
+ be indexNil, and the symbol definition from the minimal symbol
+ is preferrable (yielding a function returning int instead of int).
+ If the index points to a local procedure symbol, the local
+ symbol already provides the correct type.
+ Note that the index of the external procedure symbol points
+ to the local procedure symbol in the local symbol table, and
+ _not_ to the auxiliary symbol info. */
+ break;
+ case stGlobal:
+ case stLabel:
+ /* Global common symbols are resolved by the runtime loader,
+ ignore them. */
+ if (es->asym.sc == scCommon || es->asym.sc == scSCommon)
+ break;
+
+ /* Note that the case of a symbol with indexNil must be handled
+ anyways by parse_symbol(). */
+ parse_symbol (&es->asym, ax, (char *) NULL, bigend, section_offsets);
+ 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 PARAMS ((FDR *, PDR *, struct linetable *, int,
+ struct partial_symtab *, CORE_ADDR));
+
+static void
+parse_lines (fh, pr, lt, maxlines, pst, lowest_pdr_addr)
+ FDR *fh;
+ PDR *pr;
+ struct linetable *lt;
+ int maxlines;
+ struct partial_symtab *pst;
+ CORE_ADDR lowest_pdr_addr;
+{
+ unsigned char *base;
+ int j, k;
+ int delta, count, lineno = 0;
+
+ if (fh->cbLine == 0)
+ return;
+
+ /* Scan by procedure descriptors */
+ k = 0;
+ for (j = 0; j < fh->cpd; j++, pr++)
+ {
+ CORE_ADDR l;
+ CORE_ADDR 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 = debug_info->line + fh->cbLineOffset;
+ if (j != (fh->cpd - 1))
+ halt = base + pr[1].cbLineOffset;
+ else
+ halt = base + fh->cbLine;
+ base += pr->cbLineOffset;
+
+ adr = pst->textlow + pr->adr - lowest_pdr_addr;
+
+ 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 bfd_size_type external_sym_size = debug_swap->external_sym_size;
+ const bfd_size_type external_rfd_size = debug_swap->external_rfd_size;
+ const bfd_size_type external_ext_size = debug_swap->external_ext_size;
+ void (* const swap_ext_in) PARAMS ((bfd *, PTR, EXTR *))
+ = debug_swap->swap_ext_in;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = debug_swap->swap_sym_in;
+ void (* const swap_rfd_in) PARAMS ((bfd *, PTR, RFDT *))
+ = debug_swap->swap_rfd_in;
+ int f_idx, s_idx;
+ HDRR *hdr = &debug_info->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;
+ asection *text_sect;
+ int relocatable = 0;
+
+ /* Irix 5.2 shared libraries have a fh->adr field of zero, but
+ the shared libraries are prelinked at a high memory address.
+ We have to adjust the start address of the object file for this case,
+ by setting it to the start address of the first procedure in the file.
+ But we should do no adjustments if we are debugging a .o file, where
+ the text section (and fh->adr) really starts at zero. */
+ text_sect = bfd_get_section_by_name (cur_bfd, ".text");
+ if (text_sect != NULL
+ && (bfd_get_section_flags (cur_bfd, text_sect) & SEC_RELOC))
+ relocatable = 1;
+
+ 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 = mdebug_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, section_offsets);
+ fdr_to_pst[-1].pst = pst;
+ FDR_IDX (pst) = -1;
+ }
+
+ /* Allocate the global pending list. */
+ pending_list =
+ ((struct mdebug_pending **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ hdr->ifdMax * sizeof (struct mdebug_pending *)));
+ memset ((PTR) pending_list, 0,
+ hdr->ifdMax * sizeof (struct mdebug_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 *) debug_info->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++)
+ {
+ /* See calls to complain below. */
+ if (ext_in->ifd >= -1
+ && ext_in->ifd < hdr->ifdMax
+ && ext_in->asym.iss >= 0
+ && ext_in->asym.iss < hdr->issExtMax)
+ 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;
+ CORE_ADDR svalue = ext_in->asym.value;
+
+ /* The Irix 5 native tools seem to sometimes generate bogus
+ external symbols. */
+ if (ext_in->ifd < -1 || ext_in->ifd >= hdr->ifdMax)
+ {
+ complain (&bad_ext_ifd_complaint, ext_in->ifd, hdr->ifdMax);
+ continue;
+ }
+ if (ext_in->asym.iss < 0 || ext_in->asym.iss >= hdr->issExtMax)
+ {
+ complain (&bad_ext_iss_complaint, ext_in->asym.iss,
+ hdr->issExtMax);
+ continue;
+ }
+
+ 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 = debug_info->ssext + ext_in->asym.iss;
+ switch (ext_in->asym.st)
+ {
+ case stProc:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case stStaticProc:
+ ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case stGlobal:
+ if (ext_in->asym.sc == scCommon || ext_in->asym.sc == scSCommon)
+ {
+ /* The value of a common symbol is its size, not its address.
+ Ignore it. */
+ continue;
+ }
+ else if (ext_in->asym.sc == scData
+ || ext_in->asym.sc == scSData
+ || ext_in->asym.sc == scRData
+ || ext_in->asym.sc == scPData
+ || ext_in->asym.sc == scXData)
+ {
+ ms_type = mst_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
+ else
+ {
+ ms_type = mst_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ }
+ break;
+ case stLabel:
+ if (ext_in->asym.sc == scAbs)
+ ms_type = mst_abs;
+ else if (ext_in->asym.sc == scText
+ || ext_in->asym.sc == scInit
+ || ext_in->asym.sc == scFini)
+ {
+ ms_type = mst_file_text;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
+ else if (ext_in->asym.sc == scData
+ || ext_in->asym.sc == scSData
+ || ext_in->asym.sc == scRData
+ || ext_in->asym.sc == scPData
+ || ext_in->asym.sc == scXData)
+ {
+ ms_type = mst_file_data;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ }
+ else
+ {
+ ms_type = mst_file_bss;
+ svalue += ANOFFSET (section_offsets, SECT_OFF_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, svalue, ms_type, objfile);
+ }
+
+ /* 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;
+ CORE_ADDR textlow;
+
+ cur_fdr = fh = debug_info->fdr + f_idx;
+
+ if (fh->csym == 0)
+ {
+ fdr_to_pst[f_idx].pst = NULL;
+ continue;
+ }
+
+ /* Determine the start address for this object file from the
+ file header and relocate it, except for Irix 5.2 zero fh->adr. */
+ if (fh->cpd)
+ {
+ textlow = fh->adr;
+ if (relocatable || textlow != 0)
+ textlow += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ }
+ else
+ textlow = 0;
+ pst = start_psymtab_common (objfile, section_offsets,
+ fdr_name (fh),
+ textlow,
+ 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;
+ DEBUG_SWAP (pst) = debug_swap;
+ DEBUG_INFO (pst) = debug_info;
+ PENDING_LIST (pst) = pending_list;
+
+ /* The way to turn this into a symtab is to call... */
+ pst->read_symtab = mdebug_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 *) debug_info->external_sym
+ + (fh->isymBase + 1) * external_sym_size),
+ &sh);
+ if (STREQ (debug_info->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 *) debug_info->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;
+ long isym;
+
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ if (sh.st == stStaticProc)
+ {
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_text,
+ NULL,
+ SECT_OFF_TEXT,
+ objfile);
+ }
+ procaddr = sh.value;
+
+ isym = AUX_GET_ISYM (fh->fBigendian,
+ (debug_info->external_aux
+ + fh->iauxBase
+ + sh.index));
+ (*swap_sym_in) (cur_bfd,
+ ((char *) debug_info->external_sym
+ + ((fh->isymBase + isym - 1)
+ * external_sym_size)),
+ &sh);
+ if (sh.st == stEnd)
+ {
+ long high = procaddr + sh.value;
+
+ /* Kludge for Irix 5.2 zero fh->adr. */
+ if (!relocatable
+ && (pst->textlow == 0 || procaddr < pst->textlow))
+ pst->textlow = procaddr;
+ if (high > pst->texthigh)
+ pst->texthigh = high;
+ }
+ }
+ else if (sh.st == stStatic)
+ {
+ switch (sh.sc)
+ {
+ case scUndefined:
+ case scNil:
+ case scAbs:
+ break;
+
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_data,
+ NULL,
+ SECT_OFF_DATA,
+ objfile);
+ break;
+
+ default:
+ namestring = debug_info->ss + fh->issBase + sh.iss;
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ prim_record_minimal_symbol_and_info (namestring,
+ sh.value,
+ mst_file_bss,
+ NULL,
+ SECT_OFF_BSS,
+ objfile);
+ break;
+ }
+ }
+ continue;
+ }
+#define SET_NAMESTRING() \
+ namestring = debug_info->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 *) debug_info->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 = debug_info->ss + fh->issBase + sh.iss;
+
+ switch (sh.sc)
+ {
+ case scText:
+ /* The value of a stEnd symbol is the displacement from the
+ corresponding start symbol value, do not relocate it. */
+ if (sh.st != stEnd)
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ sh.value += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
+ switch (sh.st)
+ {
+ long high;
+ long procaddr;
+ int new_sdx;
+
+ case stStaticProc:
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_text, NULL,
+ SECT_OFF_TEXT, objfile);
+
+ /* FALLTHROUGH */
+
+ case stProc:
+ /* Usually there is a local and a global stProc symbol
+ for a function. This means that the function name
+ has already been entered into the mimimal symbol table
+ while processing the global symbols in pass 2 above.
+ One notable exception is the PROGRAM name from
+ f77 compiled executables, it is only put out as
+ local stProc symbol, and a global MAIN__ stProc symbol
+ points to it. It doesn't matter though, as gdb is
+ still able to find the PROGRAM name via the partial
+ symbol table, and the MAIN__ symbol via the minimal
+ symbol table. */
+ if (sh.st == stProc)
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols,
+ sh.value, 0, psymtab_language, objfile);
+ else
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols,
+ sh.value, 0, 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,
+ (debug_info->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 *) debug_info->external_sym
+ + ((fh->isymBase + cur_sdx - 1)
+ * external_sym_size)),
+ &sh);
+ if (sh.st != stEnd)
+ continue;
+
+ /* Kludge for Irix 5.2 zero fh->adr. */
+ if (!relocatable
+ && (pst->textlow == 0 || procaddr < pst->textlow))
+ pst->textlow = procaddr;
+
+ 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
+ || sh.sc == scPData
+ || sh.sc == scXData)
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_data, NULL,
+ SECT_OFF_DATA,
+ objfile);
+ else
+ prim_record_minimal_symbol_and_info (name, sh.value,
+ mst_file_bss, NULL,
+ SECT_OFF_BSS,
+ objfile);
+ class = LOC_STATIC;
+ break;
+
+ case stIndirect:/* Irix5 forward declaration */
+ /* Skip forward declarations from Irix5 cc */
+ goto skip;
+
+ case stTypedef:/* Typedef */
+ /* Skip typedefs for forward declarations and opaque
+ structs from alpha and mips cc. */
+ if (sh.iss == 0 || has_opaque_xref (fh, &sh))
+ goto skip;
+ class = LOC_TYPEDEF;
+ break;
+
+ case stConstant: /* Constant decl */
+ class = LOC_CONST;
+ break;
+
+ case stUnion:
+ case stStruct:
+ case stEnum:
+ case stBlock: /* { }, str, un, enum*/
+ /* Do not create a partial symbol for cc unnamed aggregates
+ and gcc empty aggregates. */
+ if ((sh.sc == scInfo
+ || sh.sc == scCommon || sh.sc == scSCommon)
+ && sh.iss != 0
+ && sh.index != cur_sdx + 2)
+ {
+ add_psymbol_to_list (name, strlen (name),
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ sh.value, 0,
+ psymtab_language, objfile);
+ }
+ handle_psymbol_enumerators (objfile, fh, sh.st, sh.value);
+
+ /* 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,
+ 0, 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;
+ CORE_ADDR svalue;
+
+ 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;
+
+ svalue = psh->value;
+ switch (psh->sc)
+ {
+ case scText:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ break;
+ case scData:
+ case scSData:
+ case scRData:
+ case scPData:
+ case scXData:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ break;
+ case scBss:
+ case scSBss:
+ svalue += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ break;
+ }
+
+ switch (psh->st)
+ {
+ case stNil:
+ /* These are generated for static symbols in .o files,
+ ignore them. */
+ continue;
+ case stProc:
+ case stStaticProc:
+ /* External procedure symbols have been entered
+ into the minimal symbol table in pass 2 above.
+ Ignore them, as parse_external will ignore them too. */
+ continue;
+ case stLabel:
+ class = LOC_LABEL;
+ break;
+ default:
+ complain (&unknown_ext_complaint,
+ debug_info->ssext + psh->iss);
+ /* Fall through, pretend it's global. */
+ case stGlobal:
+ /* Global common symbols are resolved by the runtime loader,
+ ignore them. */
+ if (psh->sc == scCommon || psh->sc == scSCommon)
+ continue;
+
+ class = LOC_STATIC;
+ break;
+ }
+ name = debug_info->ssext + psh->iss;
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, class,
+ &objfile->global_psymbols,
+ 0, svalue,
+ 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);
+ includes_used = 0;
+ dependencies_used = 0;
+
+ 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;
+ }
+
+ /* The objfile has its functions reordered if this partial symbol
+ table overlaps any other partial symbol table.
+ We cannot assume a reordered objfile if a partial symbol table
+ is contained within another partial symbol table, as partial symbol
+ tables for include files with executable code are contained
+ within the partial symbol table for the including source file,
+ and we do not want to flag the objfile reordered for these cases.
+
+ This strategy works well for Irix-5.2 shared libraries, but we
+ might have to use a more elaborate (and slower) algorithm for
+ other cases. */
+ save_pst = fdr_to_pst[f_idx].pst;
+ if (save_pst != NULL
+ && save_pst->textlow != 0
+ && !(objfile->flags & OBJF_REORDERED))
+ {
+ ALL_OBJFILE_PSYMTABS (objfile, pst)
+ {
+ if (save_pst != pst
+ && save_pst->textlow >= pst->textlow
+ && save_pst->textlow < pst->texthigh
+ && save_pst->texthigh > pst->texthigh)
+ {
+ objfile->flags |= OBJF_REORDERED;
+ break;
+ }
+ }
+ }
+ }
+
+ /* Now scan the FDRs for dependencies */
+ for (f_idx = 0; f_idx < hdr->ifdMax; f_idx++)
+ {
+ fh = f_idx + debug_info->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 *) debug_info->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;
+ }
+ }
+
+ /* Remove the dummy psymtab created for -O3 images above, if it is
+ still empty, to enable the detection of stripped executables. */
+ if (objfile->psymtabs->next == NULL
+ && objfile->psymtabs->number_of_dependencies == 0
+ && objfile->psymtabs->n_global_syms == 0
+ && objfile->psymtabs->n_static_syms == 0)
+ objfile->psymtabs = NULL;
+ do_cleanups (old_chain);
+}
+
+/* If the current psymbol has an enumerated type, we need to add
+ all the the enum constants to the partial symbol table. */
+
+static void
+handle_psymbol_enumerators (objfile, fh, stype, svalue)
+ struct objfile *objfile;
+ FDR *fh;
+ int stype;
+ CORE_ADDR svalue;
+{
+ const bfd_size_type external_sym_size = debug_swap->external_sym_size;
+ void (* const swap_sym_in) PARAMS ((bfd *, PTR, SYMR *))
+ = debug_swap->swap_sym_in;
+ char *ext_sym = ((char *) debug_info->external_sym
+ + ((fh->isymBase + cur_sdx + 1) * external_sym_size));
+ SYMR sh;
+ TIR tir;
+
+ switch (stype)
+ {
+ case stEnum:
+ break;
+
+ case stBlock:
+ /* It is an enumerated type if the next symbol entry is a stMember
+ and its auxiliary index is indexNil or its auxiliary entry
+ is a plain btNil or btVoid.
+ Alpha cc -migrate enums are recognized by a zero index and
+ a zero symbol value. */
+ (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+ if (sh.st != stMember)
+ return;
+
+ if (sh.index == indexNil
+ || (sh.index == 0 && svalue == 0))
+ break;
+ (*debug_swap->swap_tir_in) (fh->fBigendian,
+ &(debug_info->external_aux
+ + fh->iauxBase + sh.index)->a_ti,
+ &tir);
+ if ((tir.bt != btNil && tir.bt != btVoid) || tir.tq0 != tqNil)
+ return;
+ break;
+
+ default:
+ return;
+ }
+
+ for (;;)
+ {
+ char *name;
+
+ (*swap_sym_in) (cur_bfd, ext_sym, &sh);
+ if (sh.st != stMember)
+ break;
+ name = debug_info->ss + cur_fdr->issBase + sh.iss;
+
+ /* Note that the value doesn't matter for enum constants
+ in psymtabs, just in symtabs. */
+ add_psymbol_to_list (name, strlen (name),
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ 0, psymtab_language, objfile);
+ ext_sym += external_sym_size;
+ }
+}
+
+static char *
+mdebug_next_symbol_text (objfile)
+ struct objfile *objfile; /* argument objfile is currently unused */
+{
+ SYMR sh;
+
+ cur_sdx++;
+ (*debug_swap->swap_sym_in) (cur_bfd,
+ ((char *) debug_info->external_sym
+ + ((cur_fdr->isymBase + cur_sdx)
+ * debug_swap->external_sym_size)),
+ &sh);
+ return debug_info->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;
+{
+ bfd_size_type external_sym_size;
+ bfd_size_type external_pdr_size;
+ void (*swap_sym_in) PARAMS ((bfd *, PTR, SYMR *));
+ void (*swap_pdr_in) PARAMS ((bfd *, PTR, PDR *));
+ int i;
+ struct symtab *st;
+ FDR *fh;
+ struct linetable *lines;
+ CORE_ADDR lowest_pdr_addr = 0;
+
+ 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 (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...",
+ pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_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);
+ debug_swap = DEBUG_SWAP (pst);
+ debug_info = DEBUG_INFO (pst);
+ pending_list = PENDING_LIST (pst);
+ external_sym_size = debug_swap->external_sym_size;
+ external_pdr_size = debug_swap->external_pdr_size;
+ swap_sym_in = debug_swap->swap_sym_in;
+ swap_pdr_in = debug_swap->swap_pdr_in;
+ current_objfile = pst->objfile;
+ cur_fd = FDR_IDX (pst);
+ fh = ((cur_fd == -1)
+ ? (FDR *) NULL
+ : debug_info->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 *) debug_info->external_sym
+ + (fh->isymBase + 1) * external_sym_size),
+ &sh);
+ if (STREQ (debug_info->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)
+ {
+
+ /* 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 *) debug_info->external_sym)
+ + (fh->isymBase + cur_sdx) * external_sym_size),
+ &sh);
+ name = debug_info->ss + fh->issBase + sh.iss;
+ valu = sh.value;
+ if (ECOFF_IS_STAB (&sh))
+ {
+ int type_code = ECOFF_UNMARK_STAB (sh.index);
+
+ /* We should never get non N_STAB symbols here, but they
+ should be harmless, so keep process_one_symbol from
+ complaining about them. */
+ if (type_code & N_STAB)
+ {
+ 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 (&current_objfile->symbol_obstack,
+ sizeof (struct mips_extra_func_info)));
+ struct symbol *s = new_symbol (MIPS_EFI_SYMBOL_NAME);
+
+ memset ((PTR) e, 0, sizeof (struct mips_extra_func_info));
+ SYMBOL_NAMESPACE (s) = LABEL_NAMESPACE;
+ SYMBOL_CLASS (s) = LOC_CONST;
+ SYMBOL_TYPE (s) = mdebug_type_void;
+ SYMBOL_VALUE (s) = (long) e;
+ e->pdr.framereg = -1;
+ add_symbol_to_list (s, &local_symbols);
+ }
+ }
+ else if (sh.st == stLabel)
+ {
+ if (sh.index == indexNil)
+ {
+ /* This is what the gcc2_compiled and __gnu_compiled_*
+ show up as. So don't complain. */
+ ;
+ }
+ else
+ {
+ /* Handle encoded stab line number. */
+ valu += ANOFFSET (pst->section_offsets, SECT_OFF_TEXT);
+ record_line (current_subfile, sh.index, valu);
+ }
+ }
+ else if (sh.st == stProc || sh.st == stStaticProc
+ || sh.st == stStatic || sh.st == stEnd)
+ /* These are generated by gcc-2.x, do not complain */
+ ;
+ else
+ complain (&stab_unknown_complaint, name);
+ }
+ st = end_symtab (pst->texthigh, 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);
+
+ /* There used to be a call to sort_blocks here, but this should not
+ be necessary for stabs symtabs. And as sort_blocks modifies the
+ start address of the GLOBAL_BLOCK to the FIRST_LOCAL_BLOCK,
+ it did the wrong thing if the first procedure in a file was
+ generated via asm statements. */
+
+ /* Fill in procedure info next. */
+ 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 *) debug_info->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);
+
+ /* Determine lowest PDR address, the PDRs are not always
+ sorted. */
+ if (pdr_in == pr_block)
+ lowest_pdr_addr = pdr_in->adr;
+ else if (pdr_in->adr < lowest_pdr_addr)
+ lowest_pdr_addr = pdr_in->adr;
+ }
+
+ pdr_in = pr_block;
+ pdr_in_end = pdr_in + fh->cpd;
+ for (; pdr_in < pdr_in_end; pdr_in++)
+ parse_procedure (pdr_in, st, lowest_pdr_addr, pst);
+
+ do_cleanups (old_chain);
+ }
+ }
+ else
+ {
+ /* This symbol table contains ordinary ecoff entries. */
+
+ 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) = pst->textlow;
+ 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;
+ found_ecoff_debugging_info = 0;
+
+ if (fh)
+ {
+ char *sym_ptr;
+ char *sym_end;
+
+ /* Parse local symbols first */
+ sym_ptr = ((char *) debug_info->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,
+ debug_info->external_aux + fh->iauxBase,
+ sym_ptr, fh->fBigendian, pst->section_offsets);
+ 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 *) debug_info->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);
+
+ /* Determine lowest PDR address, the PDRs are not always
+ sorted. */
+ if (pdr_in == pr_block)
+ lowest_pdr_addr = pdr_in->adr;
+ else if (pdr_in->adr < lowest_pdr_addr)
+ lowest_pdr_addr = pdr_in->adr;
+ }
+
+ parse_lines (fh, pr_block, lines, maxlines, pst, lowest_pdr_addr);
+ 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, lowest_pdr_addr, pst);
+
+ 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
+ = (debug_info->symbolic_header.isymMax
+ + debug_info->symbolic_header.ipdMax
+ + debug_info->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, fh->fBigendian, pst->section_offsets);
+
+ /* 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 ();
+
+ st->primary = 1;
+
+ /* 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. */
+
+/* Return 1 if the symbol pointed to by SH has a cross reference
+ to an opaque aggregate type, else 0. */
+
+static int
+has_opaque_xref (fh, sh)
+ FDR *fh;
+ SYMR *sh;
+{
+ TIR tir;
+ union aux_ext *ax;
+ RNDXR rn[1];
+ unsigned int rf;
+
+ if (sh->index == indexNil)
+ return 0;
+
+ ax = debug_info->external_aux + fh->iauxBase + sh->index;
+ (*debug_swap->swap_tir_in) (fh->fBigendian, &ax->a_ti, &tir);
+ if (tir.bt != btStruct && tir.bt != btUnion && tir.bt != btEnum)
+ return 0;
+
+ ax++;
+ (*debug_swap->swap_rndx_in) (fh->fBigendian, &ax->a_rndx, rn);
+ if (rn->rfd == 0xfff)
+ rf = AUX_GET_ISYM (fh->fBigendian, ax + 1);
+ else
+ rf = rn->rfd;
+ if (rf != -1)
+ return 0;
+ return 1;
+}
+
+/* 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 mdebug_pending *pend;
+
+ *tpp = (struct type *)NULL;
+
+ (*debug_swap->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_typedef will
+ resolve them if the struct gets defined in another compilation unit. */
+ if (rf == -1)
+ {
+ *pname = "<undefined>";
+ *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 = "<undefined>";
+ return result;
+ }
+
+ /* Find the relative file descriptor and the symbol in it. */
+ fh = get_rfd (fd, rf);
+ xref_fd = fh - debug_info->fdr;
+
+ if (rn->index >= fh->csym)
+ {
+ /* File indirect entry is corrupt. */
+ *pname = "<illegal>";
+ 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 *) debug_info->external_sym
+ + ((fh->isymBase + rn->index)
+ * debug_swap->external_sym_size));
+ (*debug_swap->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 != stIndirect
+ && sh.st != stStruct && sh.st != stUnion
+ && sh.st != stEnum))
+ && (sh.st != stBlock || (sh.sc != scCommon && sh.sc != scSCommon)))
+ {
+ /* File indirect entry is corrupt. */
+ *pname = "<illegal>";
+ complain (&bad_rfd_entry_complaint,
+ sym_name, xref_fd, rn->index);
+ return result;
+ }
+
+ *pname = debug_info->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) || sh.st == stIndirect)
+ {
+ 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/typedefs which
+ are defined later in this file or in another file in the same
+ compilation unit. Irix5 cc uses a stIndirect symbol for this.
+ 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. */
+
+ (*debug_swap->swap_tir_in) (bigend,
+ &(debug_info->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 = "<undefined>";
+ break;
+
+ case btStruct:
+ case btUnion:
+ case btEnum:
+ cross_ref (xref_fd,
+ (debug_info->external_aux
+ + fh->iauxBase + sh.index + 1),
+ tpp, type_code, pname,
+ fh->fBigendian, sym_name);
+ break;
+
+ case btTypedef:
+ /* Follow a forward 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. 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,
+ debug_info->external_aux + fh->iauxBase,
+ sh.index,
+ (int *)NULL,
+ fh->fBigendian,
+ debug_info->ss + fh->issBase + sh.iss);
+ add_pending (fh, esh, *tpp);
+ 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,
+ debug_info->external_aux + fh->iauxBase,
+ sh.index,
+ (int *)NULL,
+ fh->fBigendian,
+ debug_info->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;
+ namespace_enum 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;
+{
+ /* DEC c89 sometimes produces zero linenos which confuse gdb.
+ Change them to something sensible. */
+ if (lineno == 0)
+ lineno = 1;
+ 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, section_offsets)
+ char *name;
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ struct partial_symtab *psymtab;
+
+ psymtab = allocate_psymtab (name, objfile);
+ psymtab->section_offsets = section_offsets;
+
+ /* 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;
+ DEBUG_SWAP (psymtab) = debug_swap;
+ DEBUG_INFO (psymtab) = debug_info;
+ PENDING_LIST (psymtab) = pending_list;
+
+ /* The way to turn this into a symtab is to call... */
+ psymtab->read_symtab = mdebug_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 (&current_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, &current_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;
+}
+
+/* Read ECOFF debugging information from a BFD section. This is
+ called from elfread.c. It parses the section into a
+ ecoff_debug_info struct, and then lets the rest of the file handle
+ it as normal. */
+
+void
+elfmdebug_build_psymtabs (objfile, swap, sec, section_offsets)
+ struct objfile *objfile;
+ const struct ecoff_debug_swap *swap;
+ asection *sec;
+ struct section_offsets *section_offsets;
+{
+ bfd *abfd = objfile->obfd;
+ struct ecoff_debug_info *info;
+
+ info = ((struct ecoff_debug_info *)
+ obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct ecoff_debug_info)));
+
+ if (!(*swap->read_debug_info) (abfd, sec, info))
+ error ("Error reading ECOFF debugging information: %s",
+ bfd_errmsg (bfd_get_error ()));
+
+ mdebug_build_psymtabs (objfile, swap, info, section_offsets);
+}
+
+
+/* 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. */
+
+/* FIXME: This function is called only by mips-tdep.c. It needs to be
+ here because it calls functions defined in this file, but perhaps
+ this could be handled in a better way. */
+
+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)) = mdebug_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 */
+ e->pdr.frameoffset = 32;
+ e->pdr.framereg = SP_REGNUM;
+ /* Note that setting pcreg is no longer strictly necessary as
+ mips_frame_saved_pc is now aware of signal handler frames. */
+ e->pdr.pcreg = PC_REGNUM;
+ e->pdr.regmask = -2;
+ /* Offset to saved r31, in the sigtramp case the saved registers
+ are above the frame in the sigcontext.
+ We have 4 alignment bytes, 12 bytes for onstack, mask and pc,
+ 32 * 4 bytes for the general registers, 12 bytes for mdhi, mdlo, ownedfp
+ and 32 * 4 bytes for the floating point registers. */
+ e->pdr.regoffset = 4 + 12 + 31 * 4;
+ e->pdr.fregmask = -1;
+ /* Offset to saved f30 (first saved *double* register). */
+ e->pdr.fregoffset = 4 + 12 + 32 * 4 + 12 + 30 * 4;
+ 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) = mdebug_type_void;
+ current_objfile = NULL;
+ }
+
+ BLOCK_SYM (b, BLOCK_NSYMS (b)++) = s;
+}
+
+void
+_initialize_mdebugread ()
+{
+ mdebug_type_void =
+ init_type (TYPE_CODE_VOID, 1,
+ 0,
+ "void", (struct objfile *) NULL);
+ mdebug_type_char =
+ init_type (TYPE_CODE_INT, 1,
+ 0,
+ "char", (struct objfile *) NULL);
+ mdebug_type_unsigned_char =
+ init_type (TYPE_CODE_INT, 1,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned char", (struct objfile *) NULL);
+ mdebug_type_short =
+ init_type (TYPE_CODE_INT, 2,
+ 0,
+ "short", (struct objfile *) NULL);
+ mdebug_type_unsigned_short =
+ init_type (TYPE_CODE_INT, 2,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned short", (struct objfile *) NULL);
+ mdebug_type_int_32 =
+ init_type (TYPE_CODE_INT, 4,
+ 0,
+ "int", (struct objfile *) NULL);
+ mdebug_type_unsigned_int_32 =
+ init_type (TYPE_CODE_INT, 4,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ mdebug_type_int_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "int", (struct objfile *) NULL);
+ mdebug_type_unsigned_int_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned int", (struct objfile *) NULL);
+ mdebug_type_long_32 =
+ init_type (TYPE_CODE_INT, 4,
+ 0,
+ "long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_32 =
+ init_type (TYPE_CODE_INT, 4,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ mdebug_type_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long", (struct objfile *) NULL);
+ mdebug_type_long_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ 0,
+ "long long", (struct objfile *) NULL);
+ mdebug_type_unsigned_long_long_64 =
+ init_type (TYPE_CODE_INT, 8,
+ TYPE_FLAG_UNSIGNED,
+ "unsigned long long", (struct objfile *) NULL);
+ mdebug_type_adr_32 =
+ init_type (TYPE_CODE_PTR, 4,
+ TYPE_FLAG_UNSIGNED,
+ "adr_32", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_adr_32) = mdebug_type_void;
+ mdebug_type_adr_64 =
+ init_type (TYPE_CODE_PTR, 8,
+ TYPE_FLAG_UNSIGNED,
+ "adr_64", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_adr_64) = mdebug_type_void;
+ mdebug_type_float =
+ init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "float", (struct objfile *) NULL);
+ mdebug_type_double =
+ init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double", (struct objfile *) NULL);
+ mdebug_type_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+ 0,
+ "complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_complex) = mdebug_type_float;
+ mdebug_type_double_complex =
+ init_type (TYPE_CODE_COMPLEX, 2 * TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0,
+ "double complex", (struct objfile *) NULL);
+ TYPE_TARGET_TYPE (mdebug_type_double_complex) = mdebug_type_double;
+
+ /* Is a "string" the way btString means it the same as TYPE_CODE_STRING?
+ FIXME. */
+ mdebug_type_string =
+ init_type (TYPE_CODE_STRING,
+ TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+ 0, "string",
+ (struct objfile *) NULL);
+
+ /* We use TYPE_CODE_INT to print these as integers. Does this do any
+ good? Would we be better off with TYPE_CODE_ERROR? Should
+ TYPE_CODE_ERROR print things in hex if it knows the size? */
+ mdebug_type_fixed_dec =
+ init_type (TYPE_CODE_INT,
+ TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "fixed decimal",
+ (struct objfile *) NULL);
+
+ mdebug_type_float_dec =
+ init_type (TYPE_CODE_ERROR,
+ TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+ 0, "floating decimal",
+ (struct objfile *) NULL);
+
+ nodebug_func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0,
+ "<function, no debug info>", NULL);
+ TYPE_TARGET_TYPE (nodebug_func_symbol_type) = mdebug_type_int;
+ nodebug_var_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<variable, no debug info>", NULL);
+}
diff --git a/contrib/gdb/gdb/mem-break.c b/contrib/gdb/gdb/mem-break.c
new file mode 100644
index 0000000..f31e2fb
--- /dev/null
+++ b/contrib/gdb/gdb/mem-break.c
@@ -0,0 +1,121 @@
+/* Simulate breakpoints by patching locations in the target system, for GDB.
+ Copyright 1990, 1991, 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by John Gilmore.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+/* Either BREAKPOINT should be defined, or both of LITTLE_BREAKPOINT,
+ BIG_BREAKPOINT should be defined. */
+
+#if defined (BREAKPOINT) || (defined (LITTLE_BREAKPOINT) && defined (BIG_BREAKPOINT))
+
+/* This file is only useful if BREAKPOINT is set. If not, we punt. */
+
+#include "symtab.h"
+#include "breakpoint.h"
+#include "inferior.h"
+#include "target.h"
+
+/* If the target isn't bi-endian, just pretend it is. */
+#if defined(BREAKPOINT) && !defined (LITTLE_BREAKPOINT) && !defined (BIG_BREAKPOINT)
+#define LITTLE_BREAKPOINT BREAKPOINT
+#define BIG_BREAKPOINT BREAKPOINT
+#endif
+
+/* This is the sequence of bytes we insert for a breakpoint. On some
+ machines, breakpoints are handled by the target environment and we
+ don't have to worry about them here. */
+
+static unsigned char big_break_insn[] = BIG_BREAKPOINT;
+static unsigned char little_break_insn[] = LITTLE_BREAKPOINT;
+
+/* FIXME: We assume big and little breakpoints are the same size. */
+#define BREAKPOINT_LEN (sizeof (big_break_insn))
+
+/* Insert a breakpoint on targets that don't have any better breakpoint
+ support. We read the contents of the target location and stash it,
+ then overwrite it with a breakpoint instruction. ADDR is the target
+ location in the target machine. CONTENTS_CACHE is a pointer to
+ memory allocated for saving the target contents. It is guaranteed
+ by the caller to be long enough to save BREAKPOINT_LEN bytes (this
+ is accomplished via BREAKPOINT_MAX). */
+
+int
+memory_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int val;
+
+ val = target_read_memory (addr, contents_cache, BREAKPOINT_LEN);
+
+ if (val == 0)
+ {
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = target_write_memory (addr, (char *)big_break_insn,
+ BREAKPOINT_LEN);
+ else
+ val = target_write_memory (addr, (char *)little_break_insn,
+ BREAKPOINT_LEN);
+ }
+
+ return val;
+}
+
+
+int
+memory_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ return target_write_memory (addr, contents_cache, BREAKPOINT_LEN);
+}
+
+
+/* FIXME: This is a hack and should depend on the debugging target.
+ See comment in breakpoint.c where this is used. */
+
+int memory_breakpoint_size = BREAKPOINT_LEN;
+
+
+#else /* BREAKPOINT */
+
+char nogo[] = "Breakpoints not implemented for this target.";
+
+int
+memory_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ error (nogo);
+ return 0; /* lint */
+}
+
+int
+memory_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ error (nogo);
+ return 0; /* lint */
+}
+
+int memory_breakpoint_size = -1;
+
+#endif /* BREAKPOINT */
diff --git a/contrib/gdb/gdb/minimon.h b/contrib/gdb/gdb/minimon.h
new file mode 100644
index 0000000..f60c417
--- /dev/null
+++ b/contrib/gdb/gdb/minimon.h
@@ -0,0 +1,562 @@
+/* Definitions and macros for support of AMD's remote debugger, MiniMON.
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Some basic types. FIXME, this should be done by declaring bitfield
+ * sizes in the structs. We can't portably depend on a "long int" being
+ * 32 bits, etc.
+ */
+typedef long int INT32; /* 32 bit integer */
+typedef unsigned long int UINT32; /* 32 bit integer (unsigned) */
+typedef unsigned long int ADDR32; /* 32 bit address */
+typedef unsigned long int INST32; /* 32 bit instruction */
+typedef long int BOOLEAN; /* Boolean value (32 bit) */
+typedef unsigned char BYTE; /* byte (8 bit) */
+typedef short int INT16; /* 16 bit integer */
+typedef unsigned short int UINT16; /* 16 bit integer (unsigned) */
+
+/****************************************************************************/
+/************************* Message Information ******************************/
+/****************************************************************************/
+
+/*
+ * Error codes
+ */
+
+/* General errors */
+#define EMUSAGE 1 /* Bad args / flags */
+#define EMFAIL 2 /* Unrecoverable error */
+#define EMBADADDR 3 /* Illegal address */
+#define EMBADREG 4 /* Illegal register */
+#define EMSYNTAX 5 /* Illegal command syntax */
+#define EMACCESS 6 /* Could not access memory */
+#define EMALLOC 7 /* Could not allocate memory */
+#define EMTARGET 8 /* Unknown target type */
+#define EMHINIT 9 /* Could not initialize host */
+#define EMCOMM 10 /* Could not open communication channel */
+
+/* Message errors */
+#define EMBADMSG 11 /* Unknown message type */
+#define EMMSG2BIG 12 /* Message to large for buffer */
+#define EMNOSEND 13 /* Could not send message */
+#define EMNORECV 14 /* Could not receive message */
+
+#define EMRESET 15 /* Could not RESET target */
+#define EMCONFIG 16 /* Could not get target CONFIG */
+#define EMSTATUS 17 /* Could not get target STATUS */
+#define EMREAD 18 /* Could not READ target memory */
+#define EMWRITE 19 /* Could not WRITE target memory */
+#define EMBKPTSET 20 /* Could not set breakpoint */
+#define EMBKPTRM 21 /* Could not remove breakpoint */
+#define EMBKPTSTAT 22 /* Could not get breakpoint status */
+#define EMBKPTNONE 23 /* All breakpoints in use */
+#define EMBKPTUSED 24 /* Breakpoints already in use */
+#define EMCOPY 25 /* Could not COPY target memory */
+#define EMFILL 26 /* Could not FILL target memory */
+#define EMINIT 27 /* Could not initialize target memory */
+#define EMGO 28 /* Could not start execution */
+#define EMSTEP 29 /* Could not single step */
+#define EMBREAK 30 /* Could not BREAK */
+#define EMHIF 31 /* Could not perform HIF service */
+#define EMCHANNEL0 32 /* Could not read CHANNEL0 */
+#define EMCHANNEL1 33 /* Could not write CHANNEL1 */
+
+/* COFF file loader errors */
+#define EMOPEN 34 /* Could not open COFF file */
+#define EMHDR 35 /* Could not read COFF header */
+#define EMMAGIC 36 /* Bad magic number */
+#define EMAOUT 37 /* Could not read COFF a.out header */
+#define EMSCNHDR 38 /* Could not read COFF section header */
+#define EMSCN 39 /* Could not read COFF section */
+#define EMCLOSE 40 /* Could not close COFF file */
+
+/* Log file errors */
+#define EMLOGOPEN 41 /* Could not open log file */
+#define EMLOGREAD 42 /* Could not read log file */
+#define EMLOGWRITE 43 /* Could not write to log file */
+#define EMLOGCLOSE 44 /* Could not close log file */
+
+/* Command file errors */
+#define EMCMDOPEN 45 /* Could not open command file */
+#define EMCMDREAD 46 /* Could not read command file */
+#define EMCMDWRITE 47 /* Could not write to command file */
+#define EMCMDCLOSE 48 /* Could not close comand file */
+
+#define EMTIMEOUT 49 /* Host timed out waiting for a message */
+#define EMCOMMTYPE 50 /* A '-t' flag must be specified */
+#define EMCOMMERR 51 /* Communication error */
+#define EMBAUD 52 /* Invalid baud rate specified */
+/*
+ * Memory Spaces
+ */
+#define LOCAL_REG 0 /* Local processor register */
+#define GLOBAL_REG 1 /* Global processor register */
+#define SPECIAL_REG 2 /* Special processor register */
+#define TLB_REG 3 /* Translation Lookaside Buffer */
+#define COPROC_REG 4 /* Coprocessor register */
+#define I_MEM 5 /* Instruction Memory */
+#define D_MEM 6 /* Data Memory */
+#define I_ROM 7 /* Instruction ROM */
+#define D_ROM 8 /* Data ROM */
+#define I_O 9 /* Input/Output */
+#define I_CACHE 10 /* Instruction Cache */
+#define D_CACHE 11 /* Data Cache */
+
+/* To supress warnings for zero length array definitions */
+#define DUMMY 1
+
+/*
+** Host to target definitions
+*/
+
+#define RESET 0
+#define CONFIG_REQ 1
+#define STATUS_REQ 2
+#define READ_REQ 3
+#define WRITE_REQ 4
+#define BKPT_SET 5
+#define BKPT_RM 6
+#define BKPT_STAT 7
+#define COPY 8
+#define FILL 9
+#define INIT 10
+#define GO 11
+#define STEP 12
+#define BREAK 13
+
+#define HIF_CALL_RTN 64
+#define CHANNEL0 65
+#define CHANNEL1_ACK 66
+
+
+/*
+** Target to host definitions
+*/
+
+#define RESET_ACK 32
+#define CONFIG 33
+#define STATUS 34
+#define READ_ACK 35
+#define WRITE_ACK 36
+#define BKPT_SET_ACK 37
+#define BKPT_RM_ACK 38
+#define BKPT_STAT_ACK 39
+#define COPY_ACK 40
+#define FILL_ACK 41
+#define INIT_ACK 42
+#define HALT 43
+
+#define ERROR 63
+
+#define HIF_CALL 96
+#define CHANNEL0_ACK 97
+#define CHANNEL1 98
+
+
+/* A "generic" message */
+struct generic_msg_t {
+ INT32 code; /* generic */
+ INT32 length;
+ BYTE byte[DUMMY];
+};
+
+
+/* A "generic" message (with an INT32 array) */
+struct generic_int32_msg_t {
+ INT32 code; /* generic */
+ INT32 length;
+ INT32 int32[DUMMY];
+};
+
+
+/*
+** Host to target messages
+*/
+
+struct reset_msg_t {
+ INT32 code; /* 0 */
+ INT32 length;
+};
+
+
+struct config_req_msg_t {
+ INT32 code; /* 1 */
+ INT32 length;
+};
+
+
+struct status_req_msg_t {
+ INT32 code; /* 2 */
+ INT32 length;
+};
+
+
+struct read_req_msg_t {
+ INT32 code; /* 3 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+};
+
+
+struct write_req_msg_t {
+ INT32 code; /* 4 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ BYTE data[DUMMY];
+};
+
+
+struct write_r_msg_t {
+ INT32 code; /* 4 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ INT32 data[DUMMY];
+};
+
+
+struct bkpt_set_msg_t {
+ INT32 code; /* 5 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 bkpt_addr;
+ INT32 pass_count;
+ INT32 bkpt_type;
+};
+
+
+struct bkpt_rm_msg_t {
+ INT32 code; /* 6 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 bkpt_addr;
+};
+
+
+struct bkpt_stat_msg_t {
+ INT32 code; /* 7 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 bkpt_addr;
+};
+
+
+struct copy_msg_t {
+ INT32 code; /* 8 */
+ INT32 length;
+ INT32 source_space;
+ ADDR32 source_addr;
+ INT32 dest_space;
+ ADDR32 dest_addr;
+ INT32 byte_count;
+};
+
+
+struct fill_msg_t {
+ INT32 code; /* 9 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 start_addr;
+ INT32 fill_count;
+ INT32 byte_count;
+ BYTE fill_data[DUMMY];
+};
+
+
+struct init_msg_t {
+ INT32 code; /* 10 */
+ INT32 length;
+ ADDR32 text_start;
+ ADDR32 text_end;
+ ADDR32 data_start;
+ ADDR32 data_end;
+ ADDR32 entry_point;
+ INT32 mem_stack_size;
+ INT32 reg_stack_size;
+ ADDR32 arg_start;
+ INT32 os_control;
+};
+
+
+struct go_msg_t {
+ INT32 code; /* 11 */
+ INT32 length;
+};
+
+
+struct step_msg_t {
+ INT32 code; /* 12 */
+ INT32 length;
+ INT32 count;
+};
+
+
+struct break_msg_t {
+ INT32 code; /* 13 */
+ INT32 length;
+};
+
+
+struct hif_call_rtn_msg_t {
+ INT32 code; /* 64 */
+ INT32 length;
+ INT32 service_number;
+ INT32 gr121;
+ INT32 gr96;
+ INT32 gr97;
+};
+
+
+struct channel0_msg_t {
+ INT32 code; /* 65 */
+ INT32 length;
+ BYTE data;
+};
+
+
+struct channel1_ack_msg_t {
+ INT32 code; /* 66 */
+ INT32 length;
+};
+
+
+/*
+** Target to host messages
+*/
+
+
+struct reset_ack_msg_t {
+ INT32 code; /* 32 */
+ INT32 length;
+};
+
+
+struct config_msg_t {
+ INT32 code; /* 33 */
+ INT32 length;
+ INT32 processor_id;
+ INT32 version;
+ ADDR32 I_mem_start;
+ INT32 I_mem_size;
+ ADDR32 D_mem_start;
+ INT32 D_mem_size;
+ ADDR32 ROM_start;
+ INT32 ROM_size;
+ INT32 max_msg_size;
+ INT32 max_bkpts;
+ INT32 coprocessor;
+ INT32 reserved;
+};
+
+
+struct status_msg_t {
+ INT32 code; /* 34 */
+ INT32 length;
+ INT32 msgs_sent;
+ INT32 msgs_received;
+ INT32 errors;
+ INT32 bkpts_hit;
+ INT32 bkpts_free;
+ INT32 traps;
+ INT32 fills;
+ INT32 spills;
+ INT32 cycles;
+ INT32 reserved;
+};
+
+
+struct read_ack_msg_t {
+ INT32 code; /* 35 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ BYTE data[DUMMY];
+};
+
+struct read_r_ack_msg_t {
+ INT32 code; /* 35 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+ INT32 data[DUMMY];
+};
+
+
+struct write_ack_msg_t {
+ INT32 code; /* 36 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 byte_count;
+};
+
+
+struct bkpt_set_ack_msg_t {
+ INT32 code; /* 37 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 pass_count;
+ INT32 bkpt_type;
+};
+
+
+struct bkpt_rm_ack_msg_t {
+ INT32 code; /* 38 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+};
+
+
+struct bkpt_stat_ack_msg_t {
+ INT32 code; /* 39 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 address;
+ INT32 pass_count;
+ INT32 bkpt_type;
+};
+
+
+struct copy_ack_msg_t {
+ INT32 code; /* 40 */
+ INT32 length;
+ INT32 source_space;
+ ADDR32 source_addr;
+ INT32 dest_space;
+ ADDR32 dest_addr;
+ INT32 byte_count;
+};
+
+
+struct fill_ack_msg_t {
+ INT32 code; /* 41 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 start_addr;
+ INT32 fill_count;
+ INT32 byte_count;
+};
+
+
+struct init_ack_msg_t {
+ INT32 code; /* 42 */
+ INT32 length;
+};
+
+
+struct halt_msg_t {
+ INT32 code; /* 43 */
+ INT32 length;
+ INT32 memory_space;
+ ADDR32 pc0;
+ ADDR32 pc1;
+ INT32 trap_number;
+};
+
+
+struct error_msg_t {
+ INT32 code; /* 63 */
+ INT32 length;
+ INT32 error_code;
+ INT32 memory_space;
+ ADDR32 address;
+};
+
+
+struct hif_call_msg_t {
+ INT32 code; /* 96 */
+ INT32 length;
+ INT32 service_number;
+ INT32 lr2;
+ INT32 lr3;
+ INT32 lr4;
+};
+
+
+struct channel0_ack_msg_t {
+ INT32 code; /* 97 */
+ INT32 length;
+};
+
+
+struct channel1_msg_t {
+ INT32 code; /* 98 */
+ INT32 length;
+ BYTE data[DUMMY];
+};
+
+
+
+/*
+** Union all of the message types together
+*/
+
+union msg_t {
+ struct generic_msg_t generic_msg;
+ struct generic_int32_msg_t generic_int32_msg;
+
+ struct reset_msg_t reset_msg;
+ struct config_req_msg_t config_req_msg;
+ struct status_req_msg_t status_req_msg;
+ struct read_req_msg_t read_req_msg;
+ struct write_req_msg_t write_req_msg;
+ struct write_r_msg_t write_r_msg;
+ struct bkpt_set_msg_t bkpt_set_msg;
+ struct bkpt_rm_msg_t bkpt_rm_msg;
+ struct bkpt_stat_msg_t bkpt_stat_msg;
+ struct copy_msg_t copy_msg;
+ struct fill_msg_t fill_msg;
+ struct init_msg_t init_msg;
+ struct go_msg_t go_msg;
+ struct step_msg_t step_msg;
+ struct break_msg_t break_msg;
+
+ struct hif_call_rtn_msg_t hif_call_rtn_msg;
+ struct channel0_msg_t channel0_msg;
+ struct channel1_ack_msg_t channel1_ack_msg;
+
+ struct reset_ack_msg_t reset_ack_msg;
+ struct config_msg_t config_msg;
+ struct status_msg_t status_msg;
+ struct read_ack_msg_t read_ack_msg;
+ struct read_r_ack_msg_t read_r_ack_msg;
+ struct write_ack_msg_t write_ack_msg;
+ struct bkpt_set_ack_msg_t bkpt_set_ack_msg;
+ struct bkpt_rm_ack_msg_t bkpt_rm_ack_msg;
+ struct bkpt_stat_ack_msg_t bkpt_stat_ack_msg;
+ struct copy_ack_msg_t copy_ack_msg;
+ struct fill_ack_msg_t fill_ack_msg;
+ struct init_ack_msg_t init_ack_msg;
+ struct halt_msg_t halt_msg;
+
+ struct error_msg_t error_msg;
+
+ struct hif_call_msg_t hif_call_msg;
+ struct channel0_ack_msg_t channel0_ack_msg;
+ struct channel1_msg_t channel1_msg;
+};
diff --git a/contrib/gdb/gdb/minsyms.c b/contrib/gdb/gdb/minsyms.c
new file mode 100644
index 0000000..6c22d6c
--- /dev/null
+++ b/contrib/gdb/gdb/minsyms.c
@@ -0,0 +1,855 @@
+/* GDB routines for manipulating the minimal symbol tables.
+ Copyright 1992, 1993, 1994, 1996, 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file contains support routines for creating, manipulating, and
+ destroying minimal symbol tables.
+
+ Minimal symbol tables are used to hold some very basic information about
+ all defined global symbols (text, data, bss, abs, etc). The only two
+ required pieces of information are the symbol's name and the address
+ associated with that symbol.
+
+ In many cases, even if a file was compiled with no special options for
+ debugging at all, as long as was not stripped it will contain sufficient
+ information to build useful minimal symbol tables using this structure.
+
+ Even when a file contains enough debugging information to build a full
+ symbol table, these minimal symbols are still useful for quickly mapping
+ between names and addresses, and vice versa. They are also sometimes used
+ to figure out what full symbol table entries need to be read in. */
+
+
+#include "defs.h"
+#include "gdb_string.h"
+#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
+ symbol obstack. */
+
+#define BUNCH_SIZE 127
+
+struct msym_bunch
+{
+ struct msym_bunch *next;
+ struct minimal_symbol contents[BUNCH_SIZE];
+};
+
+/* Bunch currently being filled up.
+ The next field points to chain of filled bunches. */
+
+static struct msym_bunch *msym_bunch;
+
+/* Number of slots filled in current bunch. */
+
+static int msym_bunch_index;
+
+/* Total number of minimal symbols recorded so far for the objfile. */
+
+static int msym_count;
+
+/* Prototypes for local functions. */
+
+static int
+compare_minimal_symbols PARAMS ((const void *, const void *));
+
+static int
+compact_minimal_symbols PARAMS ((struct minimal_symbol *, int));
+
+/* Look through all the current minimal symbol tables and find the
+ first minimal symbol that matches NAME. If OBJF is non-NULL, limit
+ the search to that objfile. If SFILE is non-NULL, limit the search
+ to that source file. Returns a pointer to the minimal symbol that
+ matches, or NULL if no match is found.
+
+ Note: One instance where there may be duplicate minimal symbols with
+ the same name is when the symbol tables for a shared library and the
+ symbol tables for an executable contain global symbols with the same
+ names (the dynamic linker deals with the duplication). */
+
+struct minimal_symbol *
+lookup_minimal_symbol (name, sfile, objf)
+ register const char *name;
+ const char *sfile;
+ struct objfile *objf;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *found_symbol = NULL;
+ struct minimal_symbol *found_file_symbol = NULL;
+ struct minimal_symbol *trampoline_symbol = NULL;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile != NULL)
+ {
+ char *p = strrchr (sfile, '/');
+ if (p != NULL)
+ sfile = p + 1;
+ }
+#endif
+
+ for (objfile = object_files;
+ objfile != NULL && found_symbol == NULL;
+ objfile = objfile -> next)
+ {
+ if (objf == NULL || objf == objfile)
+ {
+ for (msymbol = objfile -> msymbols;
+ msymbol != NULL && SYMBOL_NAME (msymbol) != NULL &&
+ found_symbol == NULL;
+ msymbol++)
+ {
+ if (SYMBOL_MATCHES_NAME (msymbol, name))
+ {
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_file_text:
+ case mst_file_data:
+ case mst_file_bss:
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile == NULL || STREQ (msymbol->filename, sfile))
+ found_file_symbol = msymbol;
+#else
+ /* We have neither the ability nor the need to
+ deal with the SFILE parameter. If we find
+ more than one symbol, just return the latest
+ one (the user can't expect useful behavior in
+ that case). */
+ found_file_symbol = msymbol;
+#endif
+ break;
+
+ case mst_solib_trampoline:
+
+ /* If a trampoline symbol is found, we prefer to
+ keep looking for the *real* symbol. If the
+ actual symbol is not found, then we'll use the
+ trampoline entry. */
+ if (trampoline_symbol == NULL)
+ trampoline_symbol = msymbol;
+ break;
+
+ case mst_unknown:
+ default:
+ found_symbol = msymbol;
+ break;
+ }
+ }
+ }
+ }
+ }
+ /* External symbols are best. */
+ if (found_symbol)
+ return found_symbol;
+
+ /* File-local symbols are next best. */
+ if (found_file_symbol)
+ return found_file_symbol;
+
+ /* Symbols for shared library trampolines are next best. */
+ if (trampoline_symbol)
+ return trampoline_symbol;
+
+ return NULL;
+}
+
+/* Look through all the current minimal symbol tables and find the
+ first minimal symbol that matches NAME and of text type.
+ If OBJF is non-NULL, limit
+ the search to that objfile. If SFILE is non-NULL, limit the search
+ to that source file. Returns a pointer to the minimal symbol that
+ matches, or NULL if no match is found.
+*/
+
+struct minimal_symbol *
+lookup_minimal_symbol_text (name, sfile, objf)
+ register const char *name;
+ const char *sfile;
+ struct objfile *objf;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *found_symbol = NULL;
+ struct minimal_symbol *found_file_symbol = NULL;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile != NULL)
+ {
+ char *p = strrchr (sfile, '/');
+ if (p != NULL)
+ sfile = p + 1;
+ }
+#endif
+
+ for (objfile = object_files;
+ objfile != NULL && found_symbol == NULL;
+ objfile = objfile -> next)
+ {
+ if (objf == NULL || objf == objfile)
+ {
+ for (msymbol = objfile -> msymbols;
+ msymbol != NULL && SYMBOL_NAME (msymbol) != NULL &&
+ found_symbol == NULL;
+ msymbol++)
+ {
+ if (SYMBOL_MATCHES_NAME (msymbol, name) &&
+ (MSYMBOL_TYPE (msymbol) == mst_text ||
+ MSYMBOL_TYPE (msymbol) == mst_file_text))
+ {
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_file_text:
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile == NULL || STREQ (msymbol->filename, sfile))
+ found_file_symbol = msymbol;
+#else
+ /* We have neither the ability nor the need to
+ deal with the SFILE parameter. If we find
+ more than one symbol, just return the latest
+ one (the user can't expect useful behavior in
+ that case). */
+ found_file_symbol = msymbol;
+#endif
+ break;
+ default:
+ found_symbol = msymbol;
+ break;
+ }
+ }
+ }
+ }
+ }
+ /* External symbols are best. */
+ if (found_symbol)
+ return found_symbol;
+
+ /* File-local symbols are next best. */
+ if (found_file_symbol)
+ return found_file_symbol;
+
+ return NULL;
+}
+
+/* Look through all the current minimal symbol tables and find the
+ first minimal symbol that matches NAME and of solib trampoline type.
+ If OBJF is non-NULL, limit
+ the search to that objfile. If SFILE is non-NULL, limit the search
+ to that source file. Returns a pointer to the minimal symbol that
+ matches, or NULL if no match is found.
+*/
+
+struct minimal_symbol *
+lookup_minimal_symbol_solib_trampoline (name, sfile, objf)
+ register const char *name;
+ const char *sfile;
+ struct objfile *objf;
+{
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ struct minimal_symbol *found_symbol = NULL;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (sfile != NULL)
+ {
+ char *p = strrchr (sfile, '/');
+ if (p != NULL)
+ sfile = p + 1;
+ }
+#endif
+
+ for (objfile = object_files;
+ objfile != NULL && found_symbol == NULL;
+ objfile = objfile -> next)
+ {
+ if (objf == NULL || objf == objfile)
+ {
+ for (msymbol = objfile -> msymbols;
+ msymbol != NULL && SYMBOL_NAME (msymbol) != NULL &&
+ found_symbol == NULL;
+ msymbol++)
+ {
+ if (SYMBOL_MATCHES_NAME (msymbol, name) &&
+ MSYMBOL_TYPE (msymbol) == mst_solib_trampoline)
+ return msymbol;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+/* Search through the minimal symbol table for each objfile and find the
+ symbol whose address is the largest address that is still less than or
+ equal to PC. Returns a pointer to the minimal symbol if such a symbol
+ is found, or NULL if PC is not in a suitable range. Note that we need
+ to look through ALL the minimal symbol tables before deciding on the
+ symbol that comes closest to the specified PC. This is because objfiles
+ can overlap, for example objfile A has .text at 0x100 and .data at 0x40000
+ and objfile B has .text at 0x234 and .data at 0x40048. */
+
+struct minimal_symbol *
+lookup_minimal_symbol_by_pc (pc)
+ register CORE_ADDR pc;
+{
+ register int lo;
+ register int hi;
+ register int new;
+ register struct objfile *objfile;
+ register struct minimal_symbol *msymbol;
+ register struct minimal_symbol *best_symbol = NULL;
+
+ for (objfile = object_files;
+ objfile != NULL;
+ objfile = objfile -> next)
+ {
+ /* If this objfile has a minimal symbol table, go search it using
+ a binary search. Note that a minimal symbol table always consists
+ of at least two symbols, a "real" symbol and the terminating
+ "null symbol". If there are no real symbols, then there is no
+ minimal symbol table at all. */
+
+ if ((msymbol = objfile -> msymbols) != NULL)
+ {
+ lo = 0;
+ hi = objfile -> minimal_symbol_count - 1;
+
+ /* This code assumes that the minimal symbols are sorted by
+ ascending address values. If the pc value is greater than or
+ equal to the first symbol's address, then some symbol in this
+ minimal symbol table is a suitable candidate for being the
+ "best" symbol. This includes the last real symbol, for cases
+ where the pc value is larger than any address in this vector.
+
+ By iterating until the address associated with the current
+ hi index (the endpoint of the test interval) is less than
+ or equal to the desired pc value, we accomplish two things:
+ (1) the case where the pc value is larger than any minimal
+ symbol address is trivially solved, (2) the address associated
+ with the hi index is always the one we want when the interation
+ terminates. In essence, we are iterating the test interval
+ down until the pc value is pushed out of it from the high end.
+
+ Warning: this code is trickier than it would appear at first. */
+
+ /* Should also requires that pc is <= end of objfile. FIXME! */
+ if (pc >= SYMBOL_VALUE_ADDRESS (&msymbol[lo]))
+ {
+ while (SYMBOL_VALUE_ADDRESS (&msymbol[hi]) > pc)
+ {
+ /* pc is still strictly less than highest address */
+ /* Note "new" will always be >= lo */
+ new = (lo + hi) / 2;
+ if ((SYMBOL_VALUE_ADDRESS (&msymbol[new]) >= pc) ||
+ (lo == new))
+ {
+ hi = new;
+ }
+ else
+ {
+ lo = new;
+ }
+ }
+
+ /* If we have multiple symbols at the same address, we want
+ hi to point to the last one. That way we can find the
+ right symbol if it has an index greater than hi. */
+ while (hi < objfile -> minimal_symbol_count - 1
+ && (SYMBOL_VALUE_ADDRESS (&msymbol[hi])
+ == SYMBOL_VALUE_ADDRESS (&msymbol[hi+1])))
+ hi++;
+
+ /* The minimal symbol indexed by hi now is the best one in this
+ objfile's minimal symbol table. See if it is the best one
+ overall. */
+
+ /* Skip any absolute symbols. This is apparently what adb
+ and dbx do, and is needed for the CM-5. There are two
+ known possible problems: (1) on ELF, apparently end, edata,
+ etc. are absolute. Not sure ignoring them here is a big
+ deal, but if we want to use them, the fix would go in
+ elfread.c. (2) I think shared library entry points on the
+ NeXT are absolute. If we want special handling for this
+ it probably should be triggered by a special
+ mst_abs_or_lib or some such. */
+ while (hi >= 0
+ && msymbol[hi].type == mst_abs)
+ --hi;
+
+ if (hi >= 0
+ && ((best_symbol == NULL) ||
+ (SYMBOL_VALUE_ADDRESS (best_symbol) <
+ SYMBOL_VALUE_ADDRESS (&msymbol[hi]))))
+ {
+ best_symbol = &msymbol[hi];
+ }
+ }
+ }
+ }
+ return (best_symbol);
+}
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+CORE_ADDR
+find_stab_function_addr (namestring, pst, objfile)
+ char *namestring;
+ struct partial_symtab *pst;
+ struct objfile *objfile;
+{
+ struct minimal_symbol *msym;
+ char *p;
+ int n;
+
+ p = strchr (namestring, ':');
+ if (p == NULL)
+ p = namestring;
+ n = p - namestring;
+ p = alloca (n + 1);
+ strncpy (p, namestring, n);
+ p[n] = 0;
+
+ msym = lookup_minimal_symbol (p, pst->filename, objfile);
+ return msym == NULL ? 0 : SYMBOL_VALUE_ADDRESS (msym);
+}
+#endif /* SOFUN_ADDRESS_MAYBE_MISSING */
+
+
+/* Return leading symbol character for a BFD. If BFD is NULL,
+ return the leading symbol character from the main objfile. */
+
+static int get_symbol_leading_char PARAMS ((bfd *));
+
+static int
+get_symbol_leading_char (abfd)
+ bfd * abfd;
+{
+ if (abfd != NULL)
+ return bfd_get_symbol_leading_char (abfd);
+ if (symfile_objfile != NULL && symfile_objfile->obfd != NULL)
+ return bfd_get_symbol_leading_char (symfile_objfile->obfd);
+ return 0;
+}
+
+/* Prepare to start collecting minimal symbols. Note that presetting
+ msym_bunch_index to BUNCH_SIZE causes the first call to save a minimal
+ symbol to allocate the memory for the first bunch. */
+
+void
+init_minimal_symbol_collection ()
+{
+ msym_count = 0;
+ msym_bunch = NULL;
+ msym_bunch_index = BUNCH_SIZE;
+}
+
+void
+prim_record_minimal_symbol (name, address, ms_type, objfile)
+ const char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ struct objfile *objfile;
+{
+ int section;
+
+ switch (ms_type)
+ {
+ 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;
+ }
+
+ prim_record_minimal_symbol_and_info (name, address, ms_type,
+ NULL, section, objfile);
+}
+
+/* Record a minimal symbol in the msym bunches. Returns the symbol
+ newly created. */
+struct minimal_symbol *
+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 (NULL);
+
+ {
+ const char *tempstring = name;
+ if (tempstring[0] == get_symbol_leading_char (objfile->obfd))
+ ++tempstring;
+ if (STREQN (tempstring, "__gnu_compiled", 14))
+ return (NULL);
+ }
+ }
+
+ if (msym_bunch_index == BUNCH_SIZE)
+ {
+ new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch));
+ msym_bunch_index = 0;
+ new -> next = msym_bunch;
+ msym_bunch = new;
+ }
+ 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) = section;
+
+ MSYMBOL_TYPE (msymbol) = ms_type;
+ /* FIXME: This info, if it remains, needs its own field. */
+ MSYMBOL_INFO (msymbol) = info; /* FIXME! */
+ msym_bunch_index++;
+ msym_count++;
+ OBJSTAT (objfile, n_minsyms++);
+ return msymbol;
+}
+
+/* Compare two minimal symbols by address and return a signed result based
+ on unsigned comparisons, so that we sort into unsigned numeric order. */
+
+static int
+compare_minimal_symbols (fn1p, fn2p)
+ const PTR fn1p;
+ const PTR fn2p;
+{
+ register const struct minimal_symbol *fn1;
+ register const struct minimal_symbol *fn2;
+
+ fn1 = (const struct minimal_symbol *) fn1p;
+ fn2 = (const struct minimal_symbol *) fn2p;
+
+ if (SYMBOL_VALUE_ADDRESS (fn1) < SYMBOL_VALUE_ADDRESS (fn2))
+ {
+ return (-1);
+ }
+ else if (SYMBOL_VALUE_ADDRESS (fn1) > SYMBOL_VALUE_ADDRESS (fn2))
+ {
+ return (1);
+ }
+ else
+ {
+ return (0);
+ }
+}
+
+/* Discard the currently collected minimal symbols, if any. If we wish
+ to save them for later use, we must have already copied them somewhere
+ else before calling this function.
+
+ FIXME: We could allocate the minimal symbol bunches on their own
+ obstack and then simply blow the obstack away when we are done with
+ it. Is it worth the extra trouble though? */
+
+/* ARGSUSED */
+void
+discard_minimal_symbols (foo)
+ int foo;
+{
+ register struct msym_bunch *next;
+
+ while (msym_bunch != NULL)
+ {
+ next = msym_bunch -> next;
+ free ((PTR)msym_bunch);
+ msym_bunch = next;
+ }
+}
+
+/* Compact duplicate entries out of a minimal symbol table by walking
+ through the table and compacting out entries with duplicate addresses
+ and matching names. Return the number of entries remaining.
+
+ On entry, the table resides between msymbol[0] and msymbol[mcount].
+ On exit, it resides between msymbol[0] and msymbol[result_count].
+
+ When files contain multiple sources of symbol information, it is
+ possible for the minimal symbol table to contain many duplicate entries.
+ As an example, SVR4 systems use ELF formatted object files, which
+ usually contain at least two different types of symbol tables (a
+ standard ELF one and a smaller dynamic linking table), as well as
+ DWARF debugging information for files compiled with -g.
+
+ Without compacting, the minimal symbol table for gdb itself contains
+ over a 1000 duplicates, about a third of the total table size. Aside
+ from the potential trap of not noticing that two successive entries
+ identify the same location, this duplication impacts the time required
+ to linearly scan the table, which is done in a number of places. So we
+ just do one linear scan here and toss out the duplicates.
+
+ Note that we are not concerned here about recovering the space that
+ is potentially freed up, because the strings themselves are allocated
+ on the symbol_obstack, and will get automatically freed when the symbol
+ table is freed. The caller can free up the unused minimal symbols at
+ the end of the compacted region if their allocation strategy allows it.
+
+ Also note we only go up to the next to last entry within the loop
+ and then copy the last entry explicitly after the loop terminates.
+
+ Since the different sources of information for each symbol may
+ have different levels of "completeness", we may have duplicates
+ that have one entry with type "mst_unknown" and the other with a
+ known type. So if the one we are leaving alone has type mst_unknown,
+ overwrite its type with the type from the one we are compacting out. */
+
+static int
+compact_minimal_symbols (msymbol, mcount)
+ struct minimal_symbol *msymbol;
+ int mcount;
+{
+ struct minimal_symbol *copyfrom;
+ struct minimal_symbol *copyto;
+
+ if (mcount > 0)
+ {
+ copyfrom = copyto = msymbol;
+ while (copyfrom < msymbol + mcount - 1)
+ {
+ if (SYMBOL_VALUE_ADDRESS (copyfrom) ==
+ SYMBOL_VALUE_ADDRESS ((copyfrom + 1)) &&
+ (STREQ (SYMBOL_NAME (copyfrom), SYMBOL_NAME ((copyfrom + 1)))))
+ {
+ if (MSYMBOL_TYPE((copyfrom + 1)) == mst_unknown)
+ {
+ MSYMBOL_TYPE ((copyfrom + 1)) = MSYMBOL_TYPE (copyfrom);
+ }
+ copyfrom++;
+ }
+ else
+ {
+ *copyto++ = *copyfrom++;
+ }
+ }
+ *copyto++ = *copyfrom++;
+ mcount = copyto - msymbol;
+ }
+ return (mcount);
+}
+
+/* Add the minimal symbols in the existing bunches to the objfile's official
+ minimal symbol table. In most cases there is no minimal symbol table yet
+ for this objfile, and the existing bunches are used to create one. Once
+ in a while (for shared libraries for example), we add symbols (e.g. common
+ symbols) to an existing objfile.
+
+ Because of the way minimal symbols are collected, we generally have no way
+ of knowing what source language applies to any particular minimal symbol.
+ Specifically, we have no way of knowing if the minimal symbol comes from a
+ C++ compilation unit or not. So for the sake of supporting cached
+ demangled C++ names, we have no choice but to try and demangle each new one
+ that comes in. If the demangling succeeds, then we assume it is a C++
+ symbol and set the symbol's language and demangled name fields
+ appropriately. Note that in order to avoid unnecessary demanglings, and
+ allocating obstack space that subsequently can't be freed for the demangled
+ names, we mark all newly added symbols with language_auto. After
+ compaction of the minimal symbols, we go back and scan the entire minimal
+ symbol table looking for these new symbols. For each new symbol we attempt
+ to demangle it, and if successful, record it as a language_cplus symbol
+ and cache the demangled form on the symbol obstack. Symbols which don't
+ demangle are marked as language_unknown symbols, which inhibits future
+ attempts to demangle them if we later add more minimal symbols. */
+
+void
+install_minimal_symbols (objfile)
+ struct objfile *objfile;
+{
+ register int bindex;
+ register int mcount;
+ register struct msym_bunch *bunch;
+ register struct minimal_symbol *msymbols;
+ int alloc_count;
+ register char leading_char;
+
+ if (msym_count > 0)
+ {
+ /* Allocate enough space in the obstack, into which we will gather the
+ bunches of new and existing minimal symbols, sort them, and then
+ compact out the duplicate entries. Once we have a final table,
+ we will give back the excess space. */
+
+ alloc_count = msym_count + objfile->minimal_symbol_count + 1;
+ obstack_blank (&objfile->symbol_obstack,
+ alloc_count * sizeof (struct minimal_symbol));
+ msymbols = (struct minimal_symbol *)
+ obstack_base (&objfile->symbol_obstack);
+
+ /* Copy in the existing minimal symbols, if there are any. */
+
+ if (objfile->minimal_symbol_count)
+ memcpy ((char *)msymbols, (char *)objfile->msymbols,
+ objfile->minimal_symbol_count * sizeof (struct minimal_symbol));
+
+ /* Walk through the list of minimal symbol bunches, adding each symbol
+ to the new contiguous array of symbols. Note that we start with the
+ current, possibly partially filled bunch (thus we use the current
+ msym_bunch_index for the first bunch we copy over), and thereafter
+ each bunch is full. */
+
+ mcount = objfile->minimal_symbol_count;
+ leading_char = get_symbol_leading_char (objfile->obfd);
+
+ for (bunch = msym_bunch; bunch != NULL; bunch = bunch -> next)
+ {
+ for (bindex = 0; bindex < msym_bunch_index; bindex++, mcount++)
+ {
+ msymbols[mcount] = bunch -> contents[bindex];
+ SYMBOL_LANGUAGE (&msymbols[mcount]) = language_auto;
+ if (SYMBOL_NAME (&msymbols[mcount])[0] == leading_char)
+ {
+ SYMBOL_NAME(&msymbols[mcount])++;
+ }
+ }
+ msym_bunch_index = BUNCH_SIZE;
+ }
+
+ /* Sort the minimal symbols by address. */
+
+ qsort (msymbols, mcount, sizeof (struct minimal_symbol),
+ compare_minimal_symbols);
+
+ /* Compact out any duplicates, and free up whatever space we are
+ no longer using. */
+
+ mcount = compact_minimal_symbols (msymbols, mcount);
+
+ obstack_blank (&objfile->symbol_obstack,
+ (mcount + 1 - alloc_count) * sizeof (struct minimal_symbol));
+ msymbols = (struct minimal_symbol *)
+ obstack_finish (&objfile->symbol_obstack);
+
+ /* We also terminate the minimal symbol table with a "null symbol",
+ which is *not* included in the size of the table. This makes it
+ easier to find the end of the table when we are handed a pointer
+ to some symbol in the middle of it. Zero out the fields in the
+ "null symbol" allocated at the end of the array. Note that the
+ symbol count does *not* include this null symbol, which is why it
+ is indexed by mcount and not mcount-1. */
+
+ SYMBOL_NAME (&msymbols[mcount]) = NULL;
+ SYMBOL_VALUE_ADDRESS (&msymbols[mcount]) = 0;
+ MSYMBOL_INFO (&msymbols[mcount]) = NULL;
+ MSYMBOL_TYPE (&msymbols[mcount]) = mst_unknown;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (&msymbols[mcount], language_unknown);
+
+ /* Attach the minimal symbol table to the specified objfile.
+ The strings themselves are also located in the symbol_obstack
+ of this objfile. */
+
+ objfile -> minimal_symbol_count = mcount;
+ objfile -> msymbols = msymbols;
+
+ /* Now walk through all the minimal symbols, selecting the newly added
+ ones and attempting to cache their C++ demangled names. */
+
+ for ( ; mcount-- > 0 ; msymbols++)
+ {
+ SYMBOL_INIT_DEMANGLED_NAME (msymbols, &objfile->symbol_obstack);
+ }
+ }
+}
+
+/* Sort all the minimal symbols in OBJFILE. */
+
+void
+msymbols_sort (objfile)
+ struct objfile *objfile;
+{
+ qsort (objfile->msymbols, objfile->minimal_symbol_count,
+ sizeof (struct minimal_symbol), compare_minimal_symbols);
+}
+
+/* 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/contrib/gdb/gdb/mipsread.c b/contrib/gdb/gdb/mipsread.c
new file mode 100644
index 0000000..e02e4b1
--- /dev/null
+++ b/contrib/gdb/gdb/mipsread.c
@@ -0,0 +1,477 @@
+/* Read a symbol table in MIPS' format (Third-Eye).
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ 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.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Read symbols from an ECOFF file. Most of the work is done in
+ mdebugread.c. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "bfd.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+
+#include "coff/sym.h"
+#include "coff/internal.h"
+#include "coff/ecoff.h"
+#include "libcoff.h" /* Private BFD COFF information. */
+#include "libecoff.h" /* Private BFD ECOFF information. */
+#include "elf/common.h"
+#include "elf/mips.h"
+
+static void
+mipscoff_new_init PARAMS ((struct objfile *));
+
+static void
+mipscoff_symfile_init PARAMS ((struct objfile *));
+
+static void
+mipscoff_symfile_read PARAMS ((struct objfile *, struct section_offsets *,
+ int));
+
+static void
+mipscoff_symfile_finish PARAMS ((struct objfile *));
+
+static struct section_offsets *
+mipscoff_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static void
+read_alphacoff_dynamic_symtab PARAMS ((struct section_offsets *,
+ struct objfile *objfile));
+
+/* 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). */
+
+extern CORE_ADDR sigtramp_address;
+
+static void
+mipscoff_new_init (ignore)
+ struct objfile *ignore;
+{
+ sigtramp_address = 0;
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+/* Initialize to read a symbol file (nothing to do). */
+
+static void
+mipscoff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+}
+
+/* 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 ();
+ back_to = make_cleanup (discard_minimal_symbols, 0);
+
+ /* Now that the executable file is positioned at symbol table,
+ process it and define symbols accordingly. */
+
+ 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 alpha coff dynamic symbols. */
+
+ read_alphacoff_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 the entry_file bounds are still unknown after processing the
+ partial symbols, then try to set them from the minimal symbols
+ surrounding the entry_point. */
+
+ if (mainline
+ && objfile->ei.entry_point != INVALID_ENTRY_POINT
+ && objfile->ei.entry_file_lowpc == INVALID_ENTRY_LOWPC)
+ {
+ struct minimal_symbol *m;
+
+ m = lookup_minimal_symbol_by_pc (objfile->ei.entry_point);
+ if (m && SYMBOL_NAME (m + 1))
+ {
+ objfile->ei.entry_file_lowpc = SYMBOL_VALUE_ADDRESS (m);
+ objfile->ei.entry_file_highpc = SYMBOL_VALUE_ADDRESS (m + 1);
+ }
+ }
+
+ do_cleanups (back_to);
+}
+
+/* Perform any local cleanups required when we are done with a
+ particular objfile. */
+
+static void
+mipscoff_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+}
+
+/* Fake up identical offsets for all sections. */
+
+static struct section_offsets *
+mipscoff_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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)))));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = 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)
+ {
+ if (dt_mips_local_gotno < 0)
+ dt_mips_local_gotno
+ = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp->d_un.d_val);
+ }
+ else if (dyn_tag == DT_MIPS_GOTSYM)
+ {
+ if (dt_mips_gotsym < 0)
+ 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 =
+{
+ 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 */
+ mipscoff_symfile_finish, /* sym_finish: finished with file, cleanup */
+ mipscoff_symfile_offsets, /* sym_offsets: dummy FIXME til implem sym reloc */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_mipsread ()
+{
+ add_symtab_fns (&ecoff_sym_fns);
+}
diff --git a/contrib/gdb/gdb/mon960-rom.c b/contrib/gdb/gdb/mon960-rom.c
new file mode 100644
index 0000000..5a79923
--- /dev/null
+++ b/contrib/gdb/gdb/mon960-rom.c
@@ -0,0 +1,270 @@
+/* Remote target glue for the Intel 960 ROM monitor.
+ Copyright 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+#include "srec.h"
+#include "xmodem.h"
+
+#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
+#define HAVE_SGTTY
+#endif
+
+#ifdef HAVE_SGTTY
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/types.h> /* Needed by file.h on Sys V */
+#include <sys/file.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+#define USE_GENERIC_LOAD
+
+int quiet = 0; /* 1 => stifle unnecessary messages */
+serial_t mon960_serial;
+char *mon960_ttyname; /* name of tty to talk to mon960 on, or null */
+static struct monitor_ops mon960_cmds;
+
+#ifdef USE_GENERIC_LOAD
+extern void generic_load PARAMS ((char* filename, int from_tty));
+#endif
+static void mon960_open PARAMS ((char *args, int from_tty));
+
+#ifdef USE_GENERIC_LOAD
+static void
+mon960_load_gen (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ extern int inferior_pid;
+ generic_load (filename, from_tty);
+ /* Finally, make the PC point at the start address */
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+}
+
+#else
+static void
+mon960_load (desc, file, hashmark)
+ serial_t desc;
+ char *file;
+ int hashmark;
+{
+ bfd *abfd;
+ asection *s;
+ char *buffer;
+ int i;
+
+ buffer = alloca (XMODEM_PACKETSIZE);
+ abfd = bfd_openr (file, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", file);
+ return;
+ }
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+ for (s = abfd->sections; s; s = s->next)
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type section_size;
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
+ s->vma + s->_raw_size);
+ gdb_flush (gdb_stdout);
+ monitor_printf (mon960_cmds.load, s->vma);
+ if (mon960_cmds.loadresp)
+ monitor_expect (mon960_cmds.loadresp, NULL, 0);
+ xmodem_init_xfer (desc);
+ section_size = bfd_section_size (abfd, s);
+ for (i = 0; i < section_size; i += XMODEM_DATASIZE)
+ {
+ int numbytes;
+ numbytes = min (XMODEM_DATASIZE, section_size - i);
+ bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i,
+ numbytes);
+ xmodem_send_packet (desc, buffer, numbytes, hashmark);
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+ } /* Per-packet (or S-record) loop */
+ xmodem_finish_xfer (desc);
+ monitor_expect_prompt (NULL, 0);
+ putchar_unfiltered ('\n');
+ } /* Loadable sections */
+ if (hashmark)
+ putchar_unfiltered ('\n');
+}
+#endif
+
+/* This array of registers need to match the indexes used by GDB.
+ This exists because the various ROM monitors use different strings
+ than does GDB, and don't necessarily support all the registers
+ either. So, typing "info reg sp" becomes a "r30". */
+
+/* these correspond to the offsets from tm-* files from config directories */
+/* g0-g14, fp, pfp, sp, rip,r3-15, pc, ac, tc, fp0-3 */
+/* NOTE: "ip" is documented as "ir" in the Mon960 UG. */
+/* NOTE: "ir" can't be accessed... but there's an ip and rip. */
+static char *mon960_regnames[NUM_REGS] = {
+ /* 0 */ "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", \
+ /* 8 */ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",\
+ /* 16 */ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", \
+ /* 24 */ "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", \
+ /* 32 */ "pc", "ac", "tc", "ip", "fp0", "fp1", "fp2", "fp3",\
+ };
+
+/* Define the monitor command strings. Since these are passed directly
+ through to a printf style function, we may include formatting
+ strings. We also need a CR or LF on the end. */
+
+static struct target_ops mon960_ops;
+
+/* need to pause the monitor for timing reasons, so slow it down */
+static char *mon960_inits[] = {"\n\r\r\r\r\r\r\r\r\r\r\r\r\r\r\n\r\n\r\n", NULL}; /* Exits sub-command mode & download cmds */
+
+static struct monitor_ops mon960_cmds =
+{
+ MO_CLR_BREAK_USES_ADDR
+ | MO_NO_ECHO_ON_OPEN
+ | MO_SEND_BREAK_ON_STOP
+ | MO_GETMEM_READ_SINGLE, /* flags */
+ mon960_inits, /* Init strings */
+ "go\n\r", /* continue command */
+ "st\n\r", /* single step */
+ "\n\r", /* break interrupts the program */
+ NULL, /* set a breakpoint */
+ /* can't use "br" because only 2 hw bps are supported */
+ NULL, /* clear a breakpoint - "de" is for hw bps */
+ NULL, /* clear all breakpoints */
+ NULL, /* fill (start end val) */
+ /* can't use "fi" because it takes words, not bytes */
+ {
+ /* can't use "mb", "md" or "mo" because they require interaction */
+ NULL, /* setmem.cmdb (addr, value) */
+ "md %x %x\n\r", /* setmem.cmdw (addr, value) */
+ NULL, /* setmem.cmdl (addr, value) */
+ NULL, /* setmem.cmdll (addr, value) */
+ NULL, /* setmem.resp_delim */
+ NULL, /* setmem.term */
+ NULL, /* setmem.term_cmd */
+ },
+ {
+ /* since the parsing of multiple bytes is difficult due to
+ interspersed addresses, we'll only read 1 value at a time,
+ even tho these can handle a count */
+ "db %x\n\r", /* getmem.cmdb (addr, #bytes) */
+ "ds %x\n\r", /* getmem.cmdw (addr, #swords) */
+ "di %x\n\r", /* getmem.cmdl (addr, #words) */
+ "dd %x\n\r", /* getmem.cmdll (addr, #dwords) */
+ " : ", /* getmem.resp_delim */
+ NULL, /* getmem.term */
+ NULL, /* getmem.term_cmd */
+ },
+ {
+ "md %s %x\n\r", /* setreg.cmd (name, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL /* setreg.term_cmd */
+ },
+ {
+ "di %s\n\r", /* getreg.cmd (name) */
+ " : ", /* getreg.resp_delim */
+ NULL, /* getreg.term */
+ NULL, /* getreg.term_cmd */
+ },
+ "re\n\r", /* dump_registers */
+ "\\(\\w+\\)=\\([0-9a-fA-F]+\\)", /* register_pattern */
+ NULL, /* supply_register */
+#ifdef USE_GENERIC_LOAD
+ NULL, /* load_routine (defaults to SRECs) */
+ NULL, /* download command */
+ NULL, /* load response */
+#else
+ mon960_load, /* load_routine (defaults to SRECs) */
+ "do\n\r", /* download command */
+ "Downloading\n\r", /* load response */
+#endif
+ "=>", /* monitor command prompt */
+ "\n\r", /* end-of-command delimitor */
+ NULL, /* optional command terminator */
+ &mon960_ops, /* target operations */
+ SERIAL_1_STOPBITS, /* number of stop bits */
+ mon960_regnames, /* registers names */
+ MONITOR_OPS_MAGIC /* magic */
+};
+
+/* invoked from monitor.c - opens the serial port */
+static void
+mon960_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *serial_port_name = args;
+ if (args)
+ {
+ char *cursor = serial_port_name = strsave (args);
+
+ while (*cursor && *cursor != ' ')
+ cursor++;
+
+ if (*cursor)
+ *cursor++ = 0;
+
+ while (*cursor == ' ')
+ cursor++;
+
+ }
+ monitor_open (serial_port_name, &mon960_cmds, from_tty);
+}
+
+
+void
+_initialize_mon960 ()
+{
+ init_monitor_ops (&mon960_ops);
+
+ mon960_ops.to_shortname = "mon960"; /* for the target command */
+ mon960_ops.to_longname = "Intel 960 rom monitor";
+#ifdef USE_GENERIC_LOAD
+ mon960_ops.to_load = mon960_load_gen; /* FIXME - should go back and try "do" */
+#endif
+ /* use SW breaks; target only supports 2 HW breakpoints */
+ mon960_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ mon960_ops.to_remove_breakpoint = memory_remove_breakpoint;
+
+ mon960_ops.to_doc =
+ "Debug on an Intel 960 eval board running the Mon960 rom monitor.\n"
+ "Specify the serial device it is connected to (e.g. /dev/ttya).";
+
+ mon960_ops.to_open = mon960_open;
+ add_target (&mon960_ops);
+}
+
diff --git a/contrib/gdb/gdb/monitor.c b/contrib/gdb/gdb/monitor.c
new file mode 100644
index 0000000..db8913c
--- /dev/null
+++ b/contrib/gdb/gdb/monitor.c
@@ -0,0 +1,1541 @@
+/* Remote debugging interface for boot monitors, for GDB.
+ Copyright 1990, 1991, 1992, 1993, 1995, 1996
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
+ Resurrected from the ashes by Stu Grossman.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file was derived from various remote-* modules. It is a collection
+ of generic support functions so GDB can talk directly to a ROM based
+ monitor. This saves use from having to hack an exception based handler
+ into existance, and makes for quick porting.
+
+ This module talks to a debug monitor called 'MONITOR', which
+ We communicate with MONITOR via either a direct serial line, or a TCP
+ (or possibly TELNET) stream to a terminal multiplexor,
+ which in turn talks to the target board. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <signal.h>
+#include <ctype.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+#include "command.h"
+#include "serial.h"
+#include "monitor.h"
+#include "gdbcmd.h"
+#include "inferior.h"
+#include "gnu-regex.h"
+#include "dcache.h"
+#include "srec.h"
+
+static int readchar PARAMS ((int timeout));
+
+static void monitor_command PARAMS ((char *args, int fromtty));
+
+static void monitor_fetch_register PARAMS ((int regno));
+static void monitor_store_register PARAMS ((int regno));
+
+static void monitor_detach PARAMS ((char *args, int from_tty));
+static void monitor_resume PARAMS ((int pid, int step, enum target_signal sig));
+static void monitor_interrupt PARAMS ((int signo));
+static void monitor_interrupt_twice PARAMS ((int signo));
+static void monitor_interrupt_query PARAMS ((void));
+static void monitor_wait_cleanup PARAMS ((int old_timeout));
+
+static int monitor_wait PARAMS ((int pid, struct target_waitstatus *status));
+static void monitor_fetch_registers PARAMS ((int regno));
+static void monitor_store_registers PARAMS ((int regno));
+static void monitor_prepare_to_store PARAMS ((void));
+static int monitor_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, int write, struct target_ops *target));
+static void monitor_files_info PARAMS ((struct target_ops *ops));
+static int monitor_insert_breakpoint PARAMS ((CORE_ADDR addr, char *shadow));
+static int monitor_remove_breakpoint PARAMS ((CORE_ADDR addr, char *shadow));
+static void monitor_kill PARAMS ((void));
+static void monitor_load PARAMS ((char *file, int from_tty));
+static void monitor_mourn_inferior PARAMS ((void));
+static void monitor_stop PARAMS ((void));
+static void monitor_debug PARAMS ((char *prefix, char *string, char *suffix));
+
+static int monitor_read_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
+static int monitor_write_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
+
+static int monitor_expect_regexp PARAMS ((struct re_pattern_buffer *pat,
+ char *buf, int buflen));
+static int from_hex PARAMS ((int a));
+static unsigned long get_hex_word PARAMS ((void));
+
+static struct monitor_ops *current_monitor;
+
+static int hashmark; /* flag set by "set hash" */
+
+static int timeout = 30;
+
+static int in_monitor_wait = 0; /* Non-zero means we are in monitor_wait() */
+
+static void (*ofunc)(); /* Old SIGINT signal handler */
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so
+ that monitor_open knows that we don't have a file open when the
+ program starts. */
+
+static serial_t monitor_desc = NULL;
+
+/* Pointer to regexp pattern matching data */
+
+static struct re_pattern_buffer register_pattern;
+static char register_fastmap[256];
+
+static struct re_pattern_buffer getmem_resp_delim_pattern;
+static char getmem_resp_delim_fastmap[256];
+
+static int dump_reg_flag; /* Non-zero means do a dump_registers cmd when
+ monitor_wait wakes up. */
+
+static DCACHE *remote_dcache;
+
+/* monitor_debug is like fputs_unfiltered, except it prints special
+ characters in printable fashion. */
+
+static void
+monitor_debug (prefix, string, suffix)
+ char *prefix;
+ char *string;
+ char *suffix;
+{
+ int ch;
+
+ /* print prefix and suffix after each line */
+ static int new_line=1;
+ if (new_line==1) { /* print prefix if last char was a newline */
+ fputs_unfiltered (prefix, gdb_stderr);
+ new_line=0;
+ }
+ if (strchr(string,'\n')) /* save state for next call */
+ new_line=1;
+
+ while ((ch = *string++) != '\0')
+ {
+ switch (ch) {
+ default:
+ if (isprint (ch))
+ fputc_unfiltered (ch, gdb_stderr);
+
+ else
+ fprintf_unfiltered (gdb_stderr, "\\%03o", ch);
+
+ break;
+
+ case '\\': fputs_unfiltered ("\\\\", gdb_stderr); break;
+ case '\b': fputs_unfiltered ("\\b", gdb_stderr); break;
+ case '\f': fputs_unfiltered ("\\f", gdb_stderr); break;
+ case '\n': fputs_unfiltered ("\\n", gdb_stderr); break;
+ case '\r': fputs_unfiltered ("\\r", gdb_stderr); break;
+ case '\t': fputs_unfiltered ("\\t", gdb_stderr); break;
+ case '\v': fputs_unfiltered ("\\v", gdb_stderr); break;
+ }
+ }
+
+ if (new_line==1) { /* print suffix if last char was a newline */
+ fputs_unfiltered (suffix, gdb_stderr);
+ fputs_unfiltered ("\n", gdb_stderr);
+ }
+}
+
+/* monitor_printf_noecho -- Send data to monitor, but don't expect an echo.
+ Works just like printf. */
+
+void
+#ifdef ANSI_PROTOTYPES
+monitor_printf_noecho (char *pattern, ...)
+#else
+monitor_printf_noecho (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char sndbuf[2000];
+ int len;
+
+#if ANSI_PROTOTYPES
+ va_start (args, pattern);
+#else
+ char *pattern;
+ va_start (args);
+ pattern = va_arg (args, char *);
+#endif
+
+ vsprintf (sndbuf, pattern, args);
+
+ if (remote_debug > 0)
+ monitor_debug ("sent -->", sndbuf, "<--");
+
+ len = strlen (sndbuf);
+
+ if (len + 1 > sizeof sndbuf)
+ abort ();
+
+ if (SERIAL_WRITE(monitor_desc, sndbuf, len))
+ fprintf_unfiltered (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+}
+
+/* monitor_printf -- Send data to monitor and check the echo. Works just like
+ printf. */
+
+void
+#ifdef ANSI_PROTOTYPES
+monitor_printf (char *pattern, ...)
+#else
+monitor_printf (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char sndbuf[2000];
+ int len;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, pattern);
+#else
+ char *pattern;
+ va_start (args);
+ pattern = va_arg (args, char *);
+#endif
+
+ vsprintf (sndbuf, pattern, args);
+
+ if (remote_debug > 0)
+ monitor_debug ("sent -->", sndbuf, "<--");
+
+ len = strlen (sndbuf);
+
+ if (len + 1 > sizeof sndbuf)
+ abort ();
+
+ if (SERIAL_WRITE(monitor_desc, sndbuf, len))
+ fprintf_unfiltered (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+
+ /* We used to expect that the next immediate output was the characters we
+ just output, but sometimes some extra junk appeared before the characters
+ we expected, like an extra prompt, or a portmaster sending telnet negotiations.
+ So, just start searching for what we sent, and skip anything unknown. */
+ monitor_expect (sndbuf, (char *)0, 0);
+}
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+
+static int
+readchar (timeout)
+ int timeout;
+{
+ int c;
+ static enum { last_random, last_nl, last_cr, last_crnl } state = last_random;
+ int looping;
+
+ do
+ {
+ looping = 0;
+ c = SERIAL_READCHAR (monitor_desc, timeout);
+
+ if (c >= 0)
+ {
+ c &= 0x7f;
+ if (remote_debug > 0)
+ {
+ char buf[2];
+ buf[0] = c;
+ buf[1] = '\0';
+ monitor_debug ("read -->", buf, "<--");
+ }
+ }
+
+ /* Canonicialize \n\r combinations into one \r */
+ if ((current_monitor->flags & MO_HANDLE_NL) != 0)
+ {
+ if ((c == '\r' && state == last_nl)
+ || (c == '\n' && state == last_cr))
+ {
+ state = last_crnl;
+ looping = 1;
+ }
+ else if (c == '\r')
+ state = last_cr;
+ else if (c != '\n')
+ state = last_random;
+ else
+ {
+ state = last_nl;
+ c = '\r';
+ }
+ }
+ }
+ while (looping);
+
+ if (c >= 0)
+ return c;
+
+ if (c == SERIAL_TIMEOUT)
+#ifdef MAINTENANCE_CMDS
+ if (in_monitor_wait) /* Watchdog went off */
+ {
+ target_mourn_inferior ();
+ error ("Watchdog has expired. Target detached.\n");
+ }
+ else
+#endif
+ error ("Timeout reading from remote system.");
+
+ perror_with_name ("remote-monitor");
+}
+
+/* Scan input from the remote system, until STRING is found. If BUF is non-
+ zero, then collect input until we have collected either STRING or BUFLEN-1
+ chars. In either case we terminate BUF with a 0. If input overflows BUF
+ because STRING can't be found, return -1, else return number of chars in BUF
+ (minus the terminating NUL). Note that in the non-overflow case, STRING
+ will be at the end of BUF. */
+
+int
+monitor_expect (string, buf, buflen)
+ char *string;
+ char *buf;
+ int buflen;
+{
+ char *p = string;
+ int obuflen = buflen;
+ int c;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ if (buf)
+ {
+ if (buflen < 2)
+ {
+ *buf = '\000';
+ immediate_quit = 0;
+ return -1;
+ }
+
+ c = readchar (timeout);
+ if (c == '\000')
+ continue;
+ *buf++ = c;
+ buflen--;
+ }
+ else
+ c = readchar (timeout);
+
+ /* Don't expect any ^C sent to be echoed */
+
+ if (*p == '\003' || c == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+
+ if (buf)
+ {
+ *buf++ = '\000';
+ return obuflen - buflen;
+ }
+ else
+ return 0;
+ }
+ }
+ else
+ {
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+/* Search for a regexp. */
+
+static int
+monitor_expect_regexp (pat, buf, buflen)
+ struct re_pattern_buffer *pat;
+ char *buf;
+ int buflen;
+{
+ char *mybuf;
+ char *p;
+
+ if (buf)
+ mybuf = buf;
+ else
+ {
+ mybuf = alloca (1024);
+ buflen = 1024;
+ }
+
+ p = mybuf;
+ while (1)
+ {
+ int retval;
+
+ if (p - mybuf >= buflen)
+ { /* Buffer about to overflow */
+
+/* On overflow, we copy the upper half of the buffer to the lower half. Not
+ great, but it usually works... */
+
+ memcpy (mybuf, mybuf + buflen / 2, buflen / 2);
+ p = mybuf + buflen / 2;
+ }
+
+ *p++ = readchar (timeout);
+
+ retval = re_search (pat, mybuf, p - mybuf, 0, p - mybuf, NULL);
+ if (retval >= 0)
+ return 1;
+ }
+}
+
+/* Keep discarding input until we see the MONITOR prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an monitor_expect_prompt(). Exception: monitor_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a monitor_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+
+int
+monitor_expect_prompt (buf, buflen)
+ char *buf;
+ int buflen;
+{
+ return monitor_expect (PROMPT, buf, buflen);
+}
+
+/* Get N 32-bit words from remote, each preceded by a space, and put
+ them in registers starting at REGNO. */
+
+static unsigned long
+get_hex_word ()
+{
+ unsigned long val;
+ int i;
+ int ch;
+
+ do
+ ch = readchar (timeout);
+ while (isspace(ch));
+
+ val = from_hex (ch);
+
+ for (i = 7; i >= 1; i--)
+ {
+ ch = readchar (timeout);
+ if (!isxdigit (ch))
+ break;
+ val = (val << 4) | from_hex (ch);
+ }
+
+ return val;
+}
+
+static void
+compile_pattern (pattern, compiled_pattern, fastmap)
+ char *pattern;
+ struct re_pattern_buffer *compiled_pattern;
+ char *fastmap;
+{
+ int tmp;
+ char *val;
+
+ compiled_pattern->fastmap = fastmap;
+
+ tmp = re_set_syntax (RE_SYNTAX_EMACS);
+ val = re_compile_pattern (pattern,
+ strlen (pattern),
+ compiled_pattern);
+ re_set_syntax (tmp);
+
+ if (val)
+ error ("compile_pattern: Can't compile pattern string `%s': %s!", pattern, val);
+
+ if (fastmap)
+ re_compile_fastmap (compiled_pattern);
+}
+
+/* Open a connection to a remote debugger. NAME is the filename used
+ for communication. */
+
+static char *dev_name;
+static struct target_ops *targ_ops;
+
+void
+monitor_open (args, mon_ops, from_tty)
+ char *args;
+ struct monitor_ops *mon_ops;
+ int from_tty;
+{
+ char *name;
+ int i;
+ char **p;
+
+ if (mon_ops->magic != MONITOR_OPS_MAGIC)
+ error ("Magic number of monitor_ops struct wrong.");
+
+ targ_ops = mon_ops->target;
+ name = targ_ops->to_shortname;
+
+ if (!args)
+ error ("Use `target %s DEVICE-NAME' to use a serial port, or \n\
+`target %s HOST-NAME:PORT-NUMBER' to use a network connection.", name, name);
+
+ target_preopen (from_tty);
+
+ /* Setup pattern for register dump */
+
+ if (mon_ops->register_pattern)
+ compile_pattern (mon_ops->register_pattern, &register_pattern,
+ register_fastmap);
+
+ if (mon_ops->getmem.resp_delim)
+ compile_pattern (mon_ops->getmem.resp_delim, &getmem_resp_delim_pattern,
+ getmem_resp_delim_fastmap);
+
+ unpush_target (targ_ops);
+
+ if (dev_name)
+ free (dev_name);
+ dev_name = strsave (args);
+
+ monitor_desc = SERIAL_OPEN (dev_name);
+
+ if (!monitor_desc)
+ perror_with_name (dev_name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (monitor_desc, baud_rate))
+ {
+ SERIAL_CLOSE (monitor_desc);
+ perror_with_name (dev_name);
+ }
+ }
+
+ SERIAL_RAW (monitor_desc);
+
+ SERIAL_FLUSH_INPUT (monitor_desc);
+
+ /* some systems only work with 2 stop bits */
+
+ SERIAL_SETSTOPBITS (monitor_desc, mon_ops->stopbits);
+
+ current_monitor = mon_ops;
+
+ /* See if we can wake up the monitor. First, try sending a stop sequence,
+ then send the init strings. Last, remove all breakpoints. */
+
+ if (current_monitor->stop)
+ {
+ monitor_stop ();
+ if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
+ {
+ monitor_expect_prompt (NULL, 0);
+ }
+ }
+
+ /* wake up the monitor and see if it's alive */
+ for (p = mon_ops->init; *p != NULL; p++)
+ {
+ /* Some of the characters we send may not be echoed,
+ but we hope to get a prompt at the end of it all. */
+
+ if ((current_monitor->flags & MO_NO_ECHO_ON_OPEN) == 0)
+ monitor_printf(*p);
+ else
+ monitor_printf_noecho (*p);
+ monitor_expect_prompt (NULL, 0);
+ }
+
+ SERIAL_FLUSH_INPUT (monitor_desc);
+
+ /* Remove all breakpoints */
+
+ if (mon_ops->clr_all_break)
+ {
+ monitor_printf (mon_ops->clr_all_break);
+ monitor_expect_prompt (NULL, 0);
+ }
+
+ if (from_tty)
+ printf_unfiltered ("Remote target %s connected to %s\n", name, dev_name);
+
+ push_target (targ_ops);
+
+ inferior_pid = 42000; /* Make run command think we are busy... */
+
+ /* Give monitor_wait something to read */
+
+ monitor_printf (current_monitor->line_term);
+
+ remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory);
+
+ start_remote ();
+}
+
+/* Close out all files and local state before this target loses
+ control. */
+
+void
+monitor_close (quitting)
+ int quitting;
+{
+ if (monitor_desc)
+ SERIAL_CLOSE (monitor_desc);
+ monitor_desc = NULL;
+}
+
+/* Terminate the open connection to the remote debugger. Use this
+ when you want to detach and do something else with your gdb. */
+
+static void
+monitor_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ pop_target (); /* calls monitor_close to do the real work */
+ if (from_tty)
+ printf_unfiltered ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Convert VALSTR into the target byte-ordered value of REGNO and store it. */
+
+char *
+monitor_supply_register (regno, valstr)
+ int regno;
+ char *valstr;
+{
+ unsigned LONGEST val;
+ unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
+ char *p;
+
+ val = strtoul (valstr, &p, 16);
+
+ if (val == 0 && valstr == p)
+ error ("monitor_supply_register (%d): bad value from monitor: %s.",
+ regno, valstr);
+
+ /* supply register stores in target byte order, so swap here */
+
+ store_unsigned_integer (regbuf, REGISTER_RAW_SIZE (regno), val);
+
+ supply_register (regno, regbuf);
+
+ return p;
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+monitor_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ dcache_flush (remote_dcache);
+ if (step)
+ monitor_printf (STEP_CMD);
+ else
+ {
+ monitor_printf (CONT_CMD);
+ if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT)
+ dump_reg_flag = 1;
+ }
+}
+
+/* Parse the output of a register dump command. A monitor specific
+ regexp is used to extract individual register descriptions of the
+ form REG=VAL. Each description is split up into a name and a value
+ string which are passed down to monitor specific code. */
+
+static char *
+parse_register_dump (buf, len)
+ char *buf;
+ int len;
+{
+ while (1)
+ {
+ int regnamelen, vallen;
+ char *regname, *val;
+ /* Element 0 points to start of register name, and element 1
+ points to the start of the register value. */
+ struct re_registers register_strings;
+
+ if (re_search (&register_pattern, buf, len, 0, len,
+ &register_strings) == -1)
+ break;
+
+ regnamelen = register_strings.end[1] - register_strings.start[1];
+ regname = buf + register_strings.start[1];
+ vallen = register_strings.end[2] - register_strings.start[2];
+ val = buf + register_strings.start[2];
+
+ current_monitor->supply_register (regname, regnamelen, val, vallen);
+
+ buf += register_strings.end[0];
+ len -= register_strings.end[0];
+ }
+}
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void
+monitor_interrupt (signo)
+ int signo;
+{
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, monitor_interrupt_twice);
+
+ if (remote_debug)
+ printf_unfiltered ("monitor_interrupt called\n");
+
+ target_stop ();
+}
+
+/* The user typed ^C twice. */
+
+static void
+monitor_interrupt_twice (signo)
+ int signo;
+{
+ signal (signo, ofunc);
+
+ monitor_interrupt_query ();
+
+ signal (signo, monitor_interrupt);
+}
+
+/* Ask the user what to do when an interrupt is received. */
+
+static void
+monitor_interrupt_query ()
+{
+ target_terminal_ours ();
+
+ if (query ("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? "))
+ {
+ target_mourn_inferior ();
+ return_to_top_level (RETURN_QUIT);
+ }
+
+ target_terminal_inferior ();
+}
+
+static void
+monitor_wait_cleanup (old_timeout)
+ int old_timeout;
+{
+ timeout = old_timeout;
+ signal (SIGINT, ofunc);
+ in_monitor_wait = 0;
+}
+
+/* Wait until the remote machine stops, then return, storing status in
+ status just as `wait' would. */
+
+static int
+monitor_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+ char buf[1024];
+ int resp_len;
+ struct cleanup *old_chain;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ old_chain = make_cleanup (monitor_wait_cleanup, old_timeout);
+
+#ifdef MAINTENANCE_CMDS
+ in_monitor_wait = 1;
+ timeout = watchdog > 0 ? watchdog : -1;
+#else
+ timeout = -1; /* Don't time out -- user program is running. */
+#endif
+
+ ofunc = (void (*)()) signal (SIGINT, monitor_interrupt);
+
+ do
+ {
+ resp_len = monitor_expect_prompt (buf, sizeof (buf));
+
+ if (resp_len <= 0)
+ fprintf_unfiltered (gdb_stderr, "monitor_wait: excessive response from monitor: %s.", buf);
+ }
+ while (resp_len < 0);
+
+ signal (SIGINT, ofunc);
+
+ timeout = old_timeout;
+
+ if (dump_reg_flag && current_monitor->dump_registers)
+ {
+ dump_reg_flag = 0;
+
+ monitor_printf (current_monitor->dump_registers);
+ resp_len = monitor_expect_prompt (buf, sizeof (buf));
+ }
+
+ if (current_monitor->register_pattern)
+ parse_register_dump (buf, resp_len);
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ discard_cleanups (old_chain);
+
+ in_monitor_wait = 0;
+
+ return inferior_pid;
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1. Returns
+ errno value. */
+
+static void
+monitor_fetch_register (regno)
+ int regno;
+{
+ char *name;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
+ char regbuf[MAX_REGISTER_RAW_SIZE * 2 + 1];
+ int i;
+
+ name = REGNAMES (regno);
+
+ if (!name)
+ {
+ supply_register (regno, zerobuf);
+ return;
+ }
+
+ /* send the register examine command */
+
+ monitor_printf (current_monitor->getreg.cmd, name);
+
+ /* If RESP_DELIM is specified, we search for that as a leading
+ delimiter for the register value. Otherwise, we just start
+ searching from the start of the buf. */
+
+ if (current_monitor->getreg.resp_delim)
+ monitor_expect (current_monitor->getreg.resp_delim, NULL, 0);
+
+ /* Read upto the maximum number of hex digits for this register, skipping
+ spaces, but stop reading if something else is seen. Some monitors
+ like to drop leading zeros. */
+
+ for (i = 0; i < REGISTER_RAW_SIZE (regno) * 2; i++)
+ {
+ int c;
+ c = readchar (timeout);
+ while (c == ' ')
+ c = readchar (timeout);
+
+ if (!isxdigit (c))
+ break;
+
+ regbuf[i] = c;
+ }
+
+ regbuf[i] = '\000'; /* terminate the number */
+
+ /* If TERM is present, we wait for that to show up. Also, (if TERM
+ is present), we will send TERM_CMD if that is present. In any
+ case, we collect all of the output into buf, and then wait for
+ the normal prompt. */
+
+ if (current_monitor->getreg.term)
+ {
+ monitor_expect (current_monitor->getreg.term, NULL, 0); /* get response */
+
+ if (current_monitor->getreg.term_cmd)
+ {
+ monitor_printf (current_monitor->getreg.term_cmd);
+ monitor_expect_prompt (NULL, 0);
+ }
+ }
+ else
+ monitor_expect_prompt (NULL, 0); /* get response */
+
+ monitor_supply_register (regno, regbuf);
+}
+
+/* Read the remote registers into the block regs. */
+
+static void monitor_dump_regs ()
+{
+ if (current_monitor->dump_registers)
+ {
+ char buf[200];
+ int resp_len;
+
+ monitor_printf (current_monitor->dump_registers);
+ resp_len = monitor_expect_prompt (buf, sizeof (buf));
+ parse_register_dump (buf, resp_len);
+ }
+ else
+ abort(); /* Need some way to read registers */
+}
+
+static void
+monitor_fetch_registers (regno)
+ int regno;
+{
+ if (current_monitor->getreg.cmd)
+ {
+ if (regno >= 0)
+ {
+ monitor_fetch_register (regno);
+ return;
+ }
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ monitor_fetch_register (regno);
+ }
+ else {
+ monitor_dump_regs ();
+ }
+}
+
+/* Store register REGNO, or all if REGNO == 0. Return errno value. */
+
+static void
+monitor_store_register (regno)
+ int regno;
+{
+ char *name;
+ unsigned LONGEST val;
+
+ name = REGNAMES (regno);
+ if (!name)
+ return;
+
+ val = read_register (regno);
+
+ /* send the register deposit command */
+
+ monitor_printf (current_monitor->setreg.cmd, name, val);
+
+/* It's possible that there are actually some monitors out there that
+ will prompt you when you set a register. In that case, you may
+ need to add some code here to deal with TERM and TERM_CMD (see
+ monitor_fetch_register to get an idea of what's needed...) */
+
+ monitor_expect_prompt (NULL, 0);
+}
+
+/* Store the remote registers. */
+
+static void
+monitor_store_registers (regno)
+ int regno;
+{
+ if (regno >= 0)
+ {
+ monitor_store_register (regno);
+ return;
+ }
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ monitor_store_register (regno);
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+monitor_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+monitor_files_info (ops)
+ struct target_ops *ops;
+{
+ printf_unfiltered ("\tAttached to %s at %d baud.\n", dev_name, baud_rate);
+}
+
+static int
+monitor_write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ unsigned LONGEST val;
+ char *cmd;
+ int i;
+
+ /* Use memory fill command for leading 0 bytes. */
+
+ if (current_monitor->fill)
+ {
+ for (i = 0; i < len; i++)
+ if (myaddr[i] != 0)
+ break;
+
+ if (i > 4) /* More than 4 zeros is worth doing */
+ {
+ if (current_monitor->flags & MO_FILL_USES_ADDR)
+ monitor_printf (current_monitor->fill, memaddr, memaddr + i, 0);
+ else
+ monitor_printf (current_monitor->fill, memaddr, i, 0);
+
+ monitor_expect_prompt (NULL, 0);
+
+ return i;
+ }
+ }
+
+ if ((memaddr & 0x7) == 0 && len >= 8 && current_monitor->setmem.cmdll)
+ {
+ len = 8;
+ cmd = current_monitor->setmem.cmdll;
+ }
+ else if ((memaddr & 0x3) == 0 && len >= 4 && current_monitor->setmem.cmdl)
+ {
+ len = 4;
+ cmd = current_monitor->setmem.cmdl;
+ }
+ else if ((memaddr & 0x1) == 0 && len >= 2 && current_monitor->setmem.cmdw)
+ {
+ len = 2;
+ cmd = current_monitor->setmem.cmdw;
+ }
+ else
+ {
+ len = 1;
+ cmd = current_monitor->setmem.cmdb;
+ }
+
+ val = extract_unsigned_integer (myaddr, len);
+
+ monitor_printf (cmd, memaddr, val);
+
+ monitor_expect_prompt (NULL, 0);
+
+ return len;
+}
+
+/* This is an alternate form of monitor_read_memory which is used for monitors
+ which can only read a single byte/word/etc. at a time. */
+
+static int
+monitor_read_memory_single (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ unsigned LONGEST val;
+ char membuf[sizeof(LONGEST) * 2 + 1];
+ char *p;
+ char *cmd;
+ int i;
+
+ if ((memaddr & 0x7) == 0 && len >= 8 && current_monitor->getmem.cmdll)
+ {
+ len = 8;
+ cmd = current_monitor->getmem.cmdll;
+ }
+ else if ((memaddr & 0x3) == 0 && len >= 4 && current_monitor->getmem.cmdl)
+ {
+ len = 4;
+ cmd = current_monitor->getmem.cmdl;
+ }
+ else if ((memaddr & 0x1) == 0 && len >= 2 && current_monitor->getmem.cmdw)
+ {
+ len = 2;
+ cmd = current_monitor->getmem.cmdw;
+ }
+ else
+ {
+ len = 1;
+ cmd = current_monitor->getmem.cmdb;
+ }
+
+/* Send the examine command. */
+
+ monitor_printf (cmd, memaddr);
+
+/* If RESP_DELIM is specified, we search for that as a leading delimiter for
+ the register value. Otherwise, we just start searching from the start of
+ the buf. */
+
+ if (current_monitor->getmem.resp_delim)
+ monitor_expect_regexp (&getmem_resp_delim_pattern, NULL, 0);
+
+/* Now, read the appropriate number of hex digits for this loc, skipping
+ spaces. */
+
+ for (i = 0; i < len * 2; i++)
+ {
+ int c;
+
+ while (1)
+ {
+ c = readchar (timeout);
+ if (isxdigit (c))
+ break;
+ if (c == ' ')
+ continue;
+
+ error ("monitor_read_memory_single (0x%x): bad response from monitor: %.*s%c.",
+ memaddr, i, membuf, c);
+ }
+
+ membuf[i] = c;
+ }
+
+ membuf[i] = '\000'; /* terminate the number */
+
+/* If TERM is present, we wait for that to show up. Also, (if TERM is
+ present), we will send TERM_CMD if that is present. In any case, we collect
+ all of the output into buf, and then wait for the normal prompt. */
+
+ if (current_monitor->getmem.term)
+ {
+ monitor_expect (current_monitor->getmem.term, NULL, 0); /* get response */
+
+ if (current_monitor->getmem.term_cmd)
+ {
+ monitor_printf (current_monitor->getmem.term_cmd);
+ monitor_expect_prompt (NULL, 0);
+ }
+ }
+ else
+ monitor_expect_prompt (NULL, 0); /* get response */
+
+ p = membuf;
+ val = strtoul (membuf, &p, 16);
+
+ if (val == 0 && membuf == p)
+ error ("monitor_read_memory_single (0x%x): bad value from monitor: %s.",
+ memaddr, membuf);
+
+ /* supply register stores in target byte order, so swap here */
+
+ store_unsigned_integer (myaddr, len, val);
+
+ return len;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's memory
+ at MEMADDR. Returns length moved. Currently, we only do one byte at a
+ time. */
+
+static int
+monitor_read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ unsigned LONGEST val;
+ unsigned char regbuf[MAX_REGISTER_RAW_SIZE];
+ char buf[512];
+ char *p, *p1;
+ char *name;
+ int resp_len;
+ int i;
+
+ if (current_monitor->flags & MO_GETMEM_READ_SINGLE)
+ return monitor_read_memory_single (memaddr, myaddr, len);
+
+ len = min (len, 16);
+
+/* See if xfer would cross a 16 byte boundary. If so, clip it. */
+ if (((memaddr ^ (memaddr + len - 1)) & ~0xf) != 0)
+ len = ((memaddr + len) & ~0xf) - memaddr;
+
+ /* send the memory examine command */
+
+ if (current_monitor->flags & MO_GETMEM_NEEDS_RANGE)
+ monitor_printf (current_monitor->getmem.cmdb, memaddr, memaddr + len - 1);
+ else
+ monitor_printf (current_monitor->getmem.cmdb, memaddr, len);
+
+/* If TERM is present, we wait for that to show up. Also, (if TERM is
+ present), we will send TERM_CMD if that is present. In any case, we collect
+ all of the output into buf, and then wait for the normal prompt. */
+
+ if (current_monitor->getmem.term)
+ {
+ resp_len = monitor_expect (current_monitor->getmem.term, buf, sizeof buf); /* get response */
+
+ if (resp_len <= 0)
+ error ("monitor_read_memory (0x%x): excessive response from monitor: %.*s.",
+ memaddr, resp_len, buf);
+
+ if (current_monitor->getmem.term_cmd)
+ {
+ SERIAL_WRITE (monitor_desc, current_monitor->getmem.term_cmd,
+ strlen (current_monitor->getmem.term_cmd));
+ monitor_expect_prompt (NULL, 0);
+ }
+ }
+ else
+ resp_len = monitor_expect_prompt (buf, sizeof buf); /* get response */
+
+ p = buf;
+
+ /* If RESP_DELIM is specified, we search for that as a leading delimiter for
+ the values. Otherwise, we just start searching from the start of the buf.
+ */
+
+ if (current_monitor->getmem.resp_delim)
+ {
+ int retval, tmp;
+ struct re_registers resp_strings;
+
+ tmp = strlen (p);
+ retval = re_search (&getmem_resp_delim_pattern, p, tmp, 0, tmp,
+ &resp_strings);
+
+ if (retval < 0)
+ error ("monitor_read_memory (0x%x): bad response from monitor: %.*s.",
+ memaddr, resp_len, buf);
+
+ p += resp_strings.end[0];
+#if 0
+ p = strstr (p, current_monitor->getmem.resp_delim);
+ if (!p)
+ error ("monitor_read_memory (0x%x): bad response from monitor: %.*s.",
+ memaddr, resp_len, buf);
+ p += strlen (current_monitor->getmem.resp_delim);
+#endif
+ }
+
+ for (i = len; i > 0; i--)
+ {
+ /* Skip non-hex chars, but bomb on end of string and newlines */
+
+ while (1)
+ {
+ if (isxdigit (*p))
+ break;
+ if (*p == '\000' || *p == '\n' || *p == '\r')
+ error ("monitor_read_memory (0x%x): badly terminated response from monitor: %.*s", memaddr, resp_len, buf);
+ p++;
+ }
+
+ val = strtoul (p, &p1, 16);
+
+ if (val == 0 && p == p1)
+ error ("monitor_read_memory (0x%x): bad value from monitor: %.*s.", memaddr,
+ resp_len, buf);
+
+ *myaddr++ = val;
+
+ if (i == 1)
+ break;
+
+ p = p1;
+ }
+
+ return len;
+}
+
+static int
+monitor_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, write);
+}
+
+static void
+monitor_kill ()
+{
+ return; /* ignore attempts to kill target system */
+}
+
+/* All we actually do is set the PC to the start address of exec_bfd, and start
+ the program at that point. */
+
+static void
+monitor_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ if (args && (*args != '\000'))
+ error ("Args are not supported by the monitor.");
+
+ clear_proceed_status ();
+ proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0);
+}
+
+/* Clean up when a program exits.
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+monitor_mourn_inferior ()
+{
+ unpush_target (targ_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define NUM_MONITOR_BREAKPOINTS 8
+
+static CORE_ADDR breakaddr[NUM_MONITOR_BREAKPOINTS] = {0};
+
+/* Tell the monitor to add a breakpoint. */
+
+static int
+monitor_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+ static unsigned char break_insn[] = BREAKPOINT;
+
+ for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
+ {
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+ monitor_read_memory (addr, shadow, sizeof (break_insn));
+ monitor_printf (SET_BREAK_CMD, addr);
+ monitor_expect_prompt (NULL, 0);
+ return 0;
+ }
+ }
+
+ error ("Too many breakpoints (> %d) for monitor.", NUM_MONITOR_BREAKPOINTS);
+}
+
+/* Tell the monitor to remove a breakpoint. */
+
+static int
+monitor_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ for (i = 0; i < NUM_MONITOR_BREAKPOINTS; i++)
+ {
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+ /* some monitors remove breakpoints based on the address */
+ if (current_monitor->flags & MO_CLR_BREAK_USES_ADDR)
+ monitor_printf (CLR_BREAK_CMD, addr);
+ else
+ monitor_printf (CLR_BREAK_CMD, i);
+ monitor_expect_prompt (NULL, 0);
+ return 0;
+ }
+ }
+ fprintf_unfiltered (stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+/* monitor_load -- download a file. */
+
+static void
+monitor_load (file, from_tty)
+ char *file;
+ int from_tty;
+{
+ dcache_flush (remote_dcache);
+
+ if (current_monitor->load_routine)
+ current_monitor->load_routine (monitor_desc, file, hashmark);
+ else
+ { /* The default is ascii S-records */
+ monitor_printf (LOAD_CMD); /* tell the monitor to load */
+ if (current_monitor->loadresp)
+ monitor_expect (current_monitor->loadresp, NULL, 0);
+
+ load_srec (monitor_desc, file, 32, SREC_ALL, hashmark);
+
+ monitor_expect_prompt (NULL, 0);
+ }
+
+/* Finally, make the PC point at the start address */
+
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+}
+
+static void
+monitor_stop ()
+{
+ if ((current_monitor->flags & MO_SEND_BREAK_ON_STOP) != 0)
+ SERIAL_SEND_BREAK (monitor_desc);
+ if (current_monitor->stop)
+ monitor_printf_noecho (current_monitor->stop);
+}
+
+/* Put a command string, in args, out to MONITOR. Output from MONITOR
+ is placed on the users terminal until the prompt is seen. FIXME: We
+ read the characters ourseleves here cause of a nasty echo. */
+
+static void
+monitor_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *p;
+ int resp_len;
+ char buf[1000];
+
+ if (monitor_desc == NULL)
+ error ("monitor target not open.");
+
+ p = PROMPT;
+
+ /* Send the command. Note that if no args were supplied, then we're
+ just sending the monitor a newline, which is sometimes useful. */
+
+ monitor_printf ("%s\r", (args ? args : ""));
+
+ resp_len = monitor_expect_prompt (buf, sizeof buf);
+
+ fputs_unfiltered (buf, gdb_stdout); /* Output the response */
+}
+
+/* Convert hex digit A to a number. */
+
+static int
+from_hex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+
+ error ("Reply contains invalid hex digit 0x%x", a);
+}
+
+static struct target_ops monitor_ops =
+{
+ NULL, /* to_shortname */
+ NULL, /* to_longname */
+ NULL, /* to_doc */
+ NULL, /* to_open */
+ monitor_close, /* to_close */
+ NULL, /* to_attach */
+ monitor_detach, /* to_detach */
+ monitor_resume, /* to_resume */
+ monitor_wait, /* to_wait */
+ monitor_fetch_registers, /* to_fetch_registers */
+ monitor_store_registers, /* to_store_registers */
+ monitor_prepare_to_store, /* to_prepare_to_store */
+ monitor_xfer_memory, /* to_xfer_memory */
+ monitor_files_info, /* to_files_info */
+ monitor_insert_breakpoint, /* to_insert_breakpoint */
+ monitor_remove_breakpoint, /* to_remove_breakpoint */
+ 0, /* to_terminal_init */
+ 0, /* to_terminal_inferior */
+ 0, /* to_terminal_ours_for_output */
+ 0, /* to_terminal_ours */
+ 0, /* to_terminal_info */
+ monitor_kill, /* to_kill */
+ monitor_load, /* to_load */
+ 0, /* to_lookup_symbol */
+ monitor_create_inferior, /* to_create_inferior */
+ monitor_mourn_inferior, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ monitor_stop, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+/* Init the target_ops structure pointed at by OPS */
+
+void
+init_monitor_ops (ops)
+ struct target_ops *ops;
+{
+ memcpy (ops, &monitor_ops, sizeof monitor_ops);
+}
+
+/* Define additional commands that are usually only used by monitors. */
+
+void
+_initialize_remote_monitors ()
+{
+ add_show_from_set (add_set_cmd ("hash", no_class, var_boolean,
+ (char *)&hashmark,
+ "Set display of activity while downloading a file.\n\
+When enabled, a hashmark \'#\' is displayed.",
+ &setlist),
+ &showlist);
+
+ add_com ("monitor", class_obscure, monitor_command,
+ "Send a command to the debug monitor.");
+}
diff --git a/contrib/gdb/gdb/monitor.h b/contrib/gdb/gdb/monitor.h
new file mode 100644
index 0000000..daad1ca
--- /dev/null
+++ b/contrib/gdb/gdb/monitor.h
@@ -0,0 +1,177 @@
+/* Remote debugging interface ROM monitors.
+ * Copyright 1990, 1991, 1992, 1996 Free Software Foundation, Inc.
+ * Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
+ *
+ * This file is part of GDB.
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "serial.h"
+
+/* This structure describes the strings necessary to give small command
+ sequences to the monitor, and parse the response.
+
+ CMD is the actual command typed at the monitor. Usually this has embedded
+ sequences ala printf, which are substituted with the arguments appropriate
+ to that type of command. Ie: to examine a register, we substitute the
+ register name for the first arg. To modify memory, we substitute the memory
+ location and the new contents for the first and second args, etc...
+
+ RESP_DELIM used to home in on the response string, and is used to
+ disambiguate the answer within the pile of text returned by the monitor.
+ This should be a unique string that immediately precedes the answer. Ie: if
+ your monitor prints out `PC: 00000001= ' in response to asking for the PC,
+ you should use `: ' as the RESP_DELIM. RESP_DELIM may be NULL if the res-
+ ponse is going to be ignored, or has no particular leading text.
+
+ TERM is the string that the monitor outputs to indicate that it is idle, and
+ waiting for input. This is usually a prompt of some sort. In the previous
+ example, it would be `= '. It is important that TERM really means that the
+ monitor is idle, otherwise GDB may try to type at it when it isn't ready for
+ input. This is a problem because many monitors cannot deal with type-ahead.
+ TERM may be NULL if the normal prompt is output.
+
+ TERM_CMD is used to quit out of the subcommand mode and get back to the main
+ prompt. TERM_CMD may be NULL if it isn't necessary. It will also be
+ ignored if TERM is NULL.
+*/
+
+struct memrw_cmd
+{
+ char *cmdb; /* Command to send for byte read/write */
+ char *cmdw; /* Command for word (16 bit) read/write */
+ char *cmdl; /* Command for long (32 bit) read/write */
+ char *cmdll; /* Command for long long (64 bit) read/write */
+ char *resp_delim; /* String just prior to the desired value */
+ char *term; /* Terminating string to search for */
+ char *term_cmd; /* String to get out of sub-mode (if necessary) */
+};
+
+struct regrw_cmd
+{
+ char *cmd; /* Command to send for reg read/write */
+ char *resp_delim; /* String (actually a regexp if getmem) just
+ prior to the desired value */
+ char *term; /* Terminating string to search for */
+ char *term_cmd; /* String to get out of sub-mode (if necessary) */
+};
+
+struct monitor_ops
+{
+ int flags; /* See below */
+ char **init; /* List of init commands. NULL terminated. */
+ char *cont; /* continue command */
+ char *step; /* single step */
+ char *stop; /* Interrupt program string */
+ char *set_break; /* set a breakpoint */
+ char *clr_break; /* clear a breakpoint */
+ char *clr_all_break; /* Clear all breakpoints */
+ char *fill; /* Memory fill cmd (addr len val) */
+ struct memrw_cmd setmem; /* set memory to a value */
+ struct memrw_cmd getmem; /* display memory */
+ struct regrw_cmd setreg; /* set a register */
+ struct regrw_cmd getreg; /* get a register */
+ /* Some commands can dump a bunch of registers
+ at once. This comes as a set of REG=VAL
+ pairs. This should be called for each pair
+ of registers that we can parse to supply
+ GDB with the value of a register. */
+ char *dump_registers; /* Command to dump all regs at once */
+ char *register_pattern; /* Pattern that picks out register from reg dump */
+ void (*supply_register) PARAMS ((char *name, int namelen, char *val, int vallen));
+ void (*load_routine) PARAMS ((serial_t desc, char *file, int hashmark)); /* Download routine */
+ char *load; /* load command */
+ char *loadresp; /* Response to load command */
+ char *prompt; /* monitor command prompt */
+ char *line_term; /* end-of-command delimitor */
+ char *cmd_end; /* optional command terminator */
+ struct target_ops *target; /* target operations */
+ int stopbits; /* number of stop bits */
+ char **regnames; /* array of register names in ascii */
+ int magic; /* Check value */
+};
+
+#define MONITOR_OPS_MAGIC 600925
+
+/* Flag defintions */
+
+#define MO_CLR_BREAK_USES_ADDR 0x1 /* If set, then clear breakpoint command
+ uses address, otherwise it uses an index
+ returned by the monitor. */
+#define MO_FILL_USES_ADDR 0x2 /* If set, then memory fill command uses
+ STARTADDR, ENDADDR+1, VALUE as args, else it
+ uses STARTADDR, LENGTH, VALUE as args. */
+#define MO_NEED_REGDUMP_AFTER_CONT 0x4 /* If set, then monitor doesn't auto-
+ matically supply register dump when
+ coming back after a continue. */
+#define MO_GETMEM_NEEDS_RANGE 0x8 /* getmem needs start addr and end addr */
+#define MO_GETMEM_READ_SINGLE 0x10 /* getmem can only read one loc at a time */
+#define MO_HANDLE_NL 0x20 /* handle \r\n combinations */
+
+#define MO_NO_ECHO_ON_OPEN 0x40 /* don't expect echos in monitor_open */
+
+#define MO_SEND_BREAK_ON_STOP 0x80 /* If set, send break to stop monitor */
+
+extern struct monitor_ops *current_monitor;
+
+#define LOADTYPES (current_monitor->loadtypes)
+#define LOADPROTOS (current_monitor->loadprotos)
+#define INIT_CMD (current_monitor->init)
+#define CONT_CMD (current_monitor->cont)
+#define STEP_CMD (current_monitor->step)
+#define SET_BREAK_CMD (current_monitor->set_break)
+#define CLR_BREAK_CMD (current_monitor->clr_break)
+#define SET_MEM (current_monitor->setmem)
+#define GET_MEM (current_monitor->getmem)
+#define LOAD_CMD (current_monitor->load)
+#define GET_REG (current_monitor->regget)
+#define SET_REG (current_monitor->regset)
+#define CMD_END (current_monitor->cmd_end)
+#define CMD_DELIM (current_monitor->cmd_delim)
+#define PROMPT (current_monitor->prompt)
+#define TARGET_OPS (current_monitor->target)
+#define TARGET_NAME (current_monitor->target->to_shortname)
+#define BAUDRATES (current_monitor->baudrates)
+#define STOPBITS (current_monitor->stopbits)
+#define REGNAMES(x) (current_monitor->regnames[x])
+#define ROMCMD(x) (x.cmd)
+#define ROMDELIM(x) (x.delim)
+#define ROMRES(x) (x.result)
+
+#define push_monitor(x) current_monitor = x;
+
+#define SREC_SIZE 160
+
+/*
+ * FIXME: These are to temporarily maintain compatability with the
+ * old monitor structure till remote-mon.c is fixed to work
+ * like the *-rom.c files.
+ */
+#define MEM_PROMPT (current_monitor->loadtypes)
+#define MEM_SET_CMD (current_monitor->setmem)
+#define MEM_DIS_CMD (current_monitor->getmem)
+#define REG_DELIM (current_monitor->regset.delim)
+
+extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops, int from_tty));
+extern void monitor_close PARAMS ((int quitting));
+extern char *monitor_supply_register PARAMS ((int regno, char *valstr));
+extern int monitor_expect PARAMS ((char *prompt, char *buf, int buflen));
+extern int monitor_expect_prompt PARAMS ((char *buf, int buflen));
+extern void monitor_printf PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+extern void monitor_printf_noecho PARAMS ((char *, ...))
+ ATTR_FORMAT(printf, 1, 2);
+extern void init_monitor_ops PARAMS ((struct target_ops *));
diff --git a/contrib/gdb/gdb/mpw-config.in b/contrib/gdb/gdb/mpw-config.in
new file mode 100644
index 0000000..47e7186
--- /dev/null
+++ b/contrib/gdb/gdb/mpw-config.in
@@ -0,0 +1,82 @@
+# Configuration fragment for GDB.
+
+If "{host_canonical}" =~ /m68k-apple-mpw/
+ forward-include "{srcdir}"config:m68k:xm-mpw.h xm.h
+ Set siow_lib '"{Libraries}"SIOW.o'
+
+Else If "{host_canonical}" =~ /powerpc-apple-mpw/
+ forward-include "{srcdir}"config:powerpc:xm-mpw.h xm.h
+ Set siow_lib '"{PPCLibraries}"PPCSIOW.o'
+
+End If
+
+Set xdepfiles '"{o}"mac-xdep.c.o'
+
+Set enable_cflags ""
+
+# Make a copy of this file and give it a different name, so it
+# won't be confused with GDB's serial.h.
+
+Duplicate -y "{CIncludes}"Serial.h MacSerial.h
+
+Echo "/* dummy */" >termio.h
+
+If "{target_canonical}" =~ /m68k-apple-macos/
+ forward-include "{srcdir}"config:m68k:tm-mac.h tm.h
+ forward-include "{srcdir}"config:m68k:tm-m68k.h 'm68k/tm-m68k.h'
+ Set tdepfiles '"{o}"m68k-tdep.c.o'
+
+Else If "{target_canonical}" =~ /powerpc-apple-macos/
+ forward-include "{srcdir}"config:powerpc:tm-macos.h tm.h
+ forward-include "{srcdir}"config:rs6000:tm-rs6000.h 'rs6000/tm-rs6000.h'
+ Set tdepfiles '"{o}"rs6000-tdep.c.o "{o}"xcoffread.c.o'
+
+Else If "{target_canonical}" =~ /i386-unknown-go32/
+ forward-include "{srcdir}"config:i386:tm-i386v.h tm.h
+ Set tdepfiles '"{o}"i386-tdep.c.o'
+
+Else If "{target_canonical}" =~ /mips-idt-ecoff/
+ forward-include "{srcdir}"config:mips:tm-embed.h tm.h
+ forward-include "{srcdir}"config:mips:tm-bigmips.h 'mips/tm-bigmips.h'
+ forward-include "{srcdir}"config:mips:tm-mips.h 'mips/tm-mips.h'
+ Set tdepfiles '"{o}"mips-tdep.c.o "{o}"remote-mips.c.o'
+
+
+Else If "{target_canonical}" =~ /sh-hitachi-hms/
+ forward-include "{srcdir}"config:sh:tm-sh.h tm.h
+ Set tdepfiles '"{o}"sh-tdep.c.o'
+
+End If
+
+If "{target_canonical}" =~ /m68k-apple-macos/
+ forward-include "{srcdir}"config:m68k:nm-macos.h nm.h
+ Set natdepfiles '"{o}"mac-nat.c.o'
+
+Else If "{target_canonical}" =~ /powerpc-apple-macos/
+ forward-include "{srcdir}"config:powerpc:nm-macos.h nm.h
+ Set natdepfiles '"{o}"mac-nat.c.o'
+
+Else
+ forward-include "{srcdir}"config:nm-empty.h nm.h
+ Set natdepfiles ' '
+
+End If
+
+Echo '# From mpw-config.in' > "{o}"mk.tmp
+Echo "TDEPFILES = " {tdepfiles} >> "{o}"mk.tmp
+Echo "XDEPFILES = " {xdepfiles} >> "{o}"mk.tmp
+Echo "NATDEPFILES = " {natdepfiles} >> "{o}"mk.tmp
+Echo "XM_ADD_FILES = " >> "{o}"mk.tmp
+Echo "TM_ADD_FILES = " >> "{o}"mk.tmp
+Echo "NAT_ADD_FILES = " >> "{o}"mk.tmp
+Echo "XM_CDEPS = " >> "{o}"mk.tmp
+Echo "TM_CDEPS = " >> "{o}"mk.tmp
+Echo "NAT_CDEPS = " >> "{o}"mk.tmp
+Echo "SIOW_LIB = " {siow_lib} >> "{o}"mk.tmp
+Echo "ENABLE_CFLAGS = " {enable_cflags} >> "{o}"mk.tmp
+Echo '# End from mpw-config.in' >> "{o}"mk.tmp
+
+Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new
+Echo '#include "mpw.h"' >> "{o}"config.new
+
+MoveIfChange "{o}"config.new "{o}"config.h
diff --git a/contrib/gdb/gdb/mpw-make.sed b/contrib/gdb/gdb/mpw-make.sed
new file mode 100644
index 0000000..9cfaaa3
--- /dev/null
+++ b/contrib/gdb/gdb/mpw-make.sed
@@ -0,0 +1,167 @@
+# Sed commands that finish translating the GDB Unix Makefile to MPW syntax.
+
+/^host_alias =/s/^/#/
+/^target_alias =/s/^/#/
+
+/^host_makefile_frag@$/d
+/^target_makefile_frag@$/d
+
+/@ENABLE_CFLAGS@/s/@ENABLE_CFLAGS@/{ENABLE_CFLAGS}/g
+/^ENABLE_CFLAGS=/s/^/#/
+
+# Edit all the symbolic definitions pointing to various libraries and such.
+
+/^INCLUDE_DIR = /s/"{srcdir}":include/"{topsrcdir}"include:/
+
+/^MMALLOC_DIR = /s/::mmalloc/mmalloc:/
+/^MMALLOC_SRC = /s/"{srcdir}"/"{topsrcdir}"/
+/^MMALLOC =/s/=.*$/=/
+/#MMALLOC_DISABLE/s/^#//
+
+/^BFD_DIR = /s/::bfd/bfd:/
+/^BFD = /s/{BFD_DIR}:libbfd/{BFD_DIR}libbfd/
+/^BFD_SRC = /s/"{srcdir}"/"{topsrcdir}"/
+
+/^READLINE_DIR = /s/::readline/readline:/
+/^READLINE =/s/=.*$/=/
+/^READLINE_SRC = /s/"{srcdir}"/"{topsrcdir}"/
+
+/^INCLUDE_CFLAGS = /s/$/ -i "{topsrcdir}"include:mpw: -i ::extra-include:/
+
+/^SER_HARDWIRE =/s/ser-unix/ser-mac/
+
+/^TERMCAP =/s/ =.*$/ =/
+
+/@DEFS@/s/@DEFS@//g
+
+/@YACC@/s/@YACC@/byacc/g
+
+/@ENABLE_OBS@/s/@ENABLE_OBS@//g
+
+/@ENABLE_CLIBS@/s/@ENABLE_CLIBS@//g
+
+/@LIBS@/s/@LIBS@//g
+
+/INCLUDE_DIR/s/"{s}"{INCLUDE_DIR}/{INCLUDE_DIR}/g
+/INCLUDE_DIR/s/{INCLUDE_DIR}:/{INCLUDE_DIR}/g
+/INCLUDE_DIR/s/"{INCLUDE_DIR}":/"{INCLUDE_DIR}"/g
+
+/{BFD_DIR}/s/"{BFD_DIR}":/"{BFD_DIR}"/g
+/{BFD_DIR}/s/\([ ]\){BFD_DIR}/\1::{BFD_DIR}/g
+/{BFD_DIR}/s/\([ ]\)"{BFD_DIR}"/\1::"{BFD_DIR}"/g
+
+/{BFD_SRC}/s/"{s}"{BFD_SRC}/{BFD_SRC}/g
+/{BFD_SRC}/s/{BFD_SRC}:/{BFD_SRC}/g
+
+/{READLINE_SRC}/s/"{s}"{READLINE_SRC}/{READLINE_SRC}/g
+
+/^readline_headers =/,/^$/c\
+readline_headers =\
+
+
+/{MMALLOC_CHECK}/s/{MMALLOC_CHECK}//g
+
+# This isn't really useful, and seems to cause nonsensical complaints.
+/{ALLDEPFILES}/s/{ALLDEPFILES}//g
+
+/^copying.c \\Option-f /,/^$/d
+
+# Fix the syntax of bits of C code that go into version.c.
+/char /s/'char .Option-x/'char */
+
+/version/s/"{s}"version\.c/"{o}"version.c/g
+/version/s/^version\.c/"{o}"version.c/
+/config/s/"{s}"config\.h/"{o}"config.h/g
+/config/s/^config\.h/"{o}"config.h/
+/xm/s/"{s}"xm\.h/"{o}"xm.h/g
+/xm/s/^xm\.h/"{o}"xm.h/
+/tm/s/"{s}"tm\.h/"{o}"tm.h/g
+/tm/s/^tm\.h/"{o}"tm.h/
+/nm/s/"{s}"nm\.h/"{o}"nm.h/g
+/nm/s/^nm\.h/"{o}"nm.h/
+
+/exp.tab.c/s/"{s}"\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/g
+/exp.tab.c/s/^\([a-z0-9]*\)-exp\.tab\.c/"{o}"\1-exp.tab.c/
+
+/y.tab/s/"{s}"y.tab\.c/"{o}"y.tab.c/g
+/y.tab/s/^y.tab\.c/"{o}"y.tab.c/
+
+/init/s/"{s}"init\.c-tmp/"{o}"init.c-tmp/g
+/init/s/^init\.c-tmp/"{o}"init.c-tmp/
+/init/s/"{s}"init\.c/"{o}"init.c/g
+/init/s/^init\.c/"{o}"init.c/
+
+/"{o}"version.c \\Option-f Makefile/,/^$/c\
+"{o}"version.c \\Option-f Makefile\
+ echo -n 'char *version = "' >"{o}"version.c\
+ echo -n "{VERSION}" >>"{o}"version.c\
+ echo '";' >>"{o}"version.c\
+ echo -n 'char *host_name = "' >>"{o}"version.c\
+ echo -n "{host_alias}" >>"{o}"version.c\
+ echo '";' >>"{o}"version.c\
+ echo -n 'char *target_name = "' >>"{o}"version.c\
+ echo -n "{target_alias}" >>"{o}"version.c\
+ echo '";' >>"{o}"version.c\
+
+
+# Open-brace in a command causes much confusion; replace with the
+# result from a script.
+/initialize_all_files ()/c\
+ Echo -n 'void initialize_all_files () ' >> "{o}"init.c-tmp\
+ open-brace >> "{o}"init.c-tmp
+
+# Replace the whole sed bit for init.c; it's simpler that way...
+/filename=`echo $i | sed/,/esac/c\
+ set filename "`Echo {i} | sed \\Option-d\
+ -e '/^Onindy.c.o/d' \\Option-d\
+ -e '/^nindy.c.o/d' \\Option-d\
+ -e '/ttyflush.c.o/d' \\Option-d\
+ -e '/xdr_ld.c.o/d' \\Option-d\
+ -e '/xdr_ptrace.c.o/d' \\Option-d\
+ -e '/xdr_rdb.c.o/d' \\Option-d\
+ -e '/udr.c.o/d' \\Option-d\
+ -e '/udip2soc.c.o/d' \\Option-d\
+ -e '/udi2go32.c.o/d' \\Option-d\
+ -e '/version.c.o/d' \\Option-d\
+ -e '/[a-z0-9A-Z_]*-exp.tab.c.o/d' \\Option-d\
+ -e 's/\\.c\\.o/.c/' \\Option-d\
+ -e 's/^://'`"\
+ If "{filename}" != ""\
+ sed <"{s}""{filename}" >>"{o}"init.c-tmp -n \\Option-d\
+ -e '/^_initialize_[a-z_0-9A-Z]* *(/s/^\\([a-z_0-9A-Z]*\\).*/ {extern void \\1 (); \\1 ();}/p'\
+ End If
+
+# Fix the main compile/link command.
+/{CC_LD} {INTERNAL_LDFLAGS} -o gdb/,/"{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES}/c\
+ {CC_LD} {INTERNAL_LDFLAGS} -o gdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {LOADLIBES} {EXTRALIBS}\
+ {MAKEPEF} gdb{PROG_EXT} -o gdb {MAKEPEF_TOOL_FLAGS} {MAKEPEF_FLAGS}\
+ {REZ} "{s}"mac-gdb.r -o gdb -append -d PROG_NAME='"'gdb'"' -d VERSION_STRING='"'{version}'"'\
+
+/^install \\Option-f /,/^$/c\
+install \\Option-f all install-only\
+\
+install-only \\Option-f \
+ Duplicate -y gdb "{bindir}"gdb\
+ If "`Exists SiowGDB`" != ""\
+ Duplicate -y SiowGDB "{bindir}"SiowGDB\
+ End If\
+
+
+# Don't do any recursive subdir stuff.
+/ subdir_do/s/{MAKE}/null-command/
+
+# Edit out actions that only confuse MPW Make.
+/^config.status \\Option-f/,/^$/d
+/^Makefile \\Option-f/,/^$/d
+
+/^"{o}"config.h \\Option-f/s/^/#/
+
+# Add an action to build SIOWgdb.
+$a\
+SIOWgdb \\Option-f {OBS} {TSOBS} {ADD_DEPS} {CDEPS} "{o}"init.c.o\
+ Delete -i -y SIOWgdb\
+ {CC_LD} {INTERNAL_LDFLAGS} -t 'APPL' -c 'gdb ' -o SIOWgdb{PROG_EXT} "{o}"init.c.o {OBS} {TSOBS} {ADD_FILES} {CLIBS} {SIOW_LIB} {LOADLIBES} {EXTRALIBS}\
+ {MAKEPEF} SIOWgdb{PROG_EXT} -o SIOWgdb -ft 'APPL' -fc 'gdb ' {MAKEPEF_FLAGS} \
+ {REZ} -o SIOWgdb "{RIncludes}"siow.r -append -d __kPrefSize=5000 -d __kMinSize=2000 -d APPNAME='"'SIOWgdb'"' \
+ {REZ} "{s}"mac-gdb.r -o SIOWgdb -append -d VERSION_STRING='"'{version}'"'\
+
diff --git a/contrib/gdb/gdb/msg.defs b/contrib/gdb/gdb/msg.defs
new file mode 100644
index 0000000..7c9fcd1
--- /dev/null
+++ b/contrib/gdb/gdb/msg.defs
@@ -0,0 +1 @@
+#include <hurd/msg.defs>
diff --git a/contrib/gdb/gdb/msg_reply.defs b/contrib/gdb/gdb/msg_reply.defs
new file mode 100644
index 0000000..049bfa8
--- /dev/null
+++ b/contrib/gdb/gdb/msg_reply.defs
@@ -0,0 +1 @@
+#include <hurd/msg_reply.defs>
diff --git a/contrib/gdb/gdb/news-xdep.c b/contrib/gdb/gdb/news-xdep.c
new file mode 100644
index 0000000..7f57aeb
--- /dev/null
+++ b/contrib/gdb/gdb/news-xdep.c
@@ -0,0 +1,65 @@
+/* Low level interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __GNUC__
+/* Bad implement execle(3). It's depend for "/bin/cc".
+
+ main()
+ {
+ printf("execle:\n");
+ execle(FILE, ARGS, envp);
+ exit(1);
+ }
+
+ GCC:
+ link a6,#0
+ pea LC5 ; call printf
+ jbsr _printf
+ ; ; (not popd stack)
+ pea _envp ; call execle
+ clrl sp@-
+ pea LC4
+ pea LC4
+ pea LC4
+ pea LC3
+ pea LC6
+ jbsr _execle
+ addw #32,sp ; delayed pop !!
+
+ /bin/cc:
+ link.l fp,#L23
+ movem.l #L24,(sp)
+ pea L26 ; call printf
+ jbsr _printf
+ addq.l #4,sp ; <--- popd stack !!
+ pea _envp ; call execle
+ clr.l -(sp)
+ pea L32
+
+ */
+
+execle(name, args)
+ char *name, *args;
+{
+ register char **env = &args;
+ while (*env++)
+ ;
+ execve(name, (char **)&args, (char **)*env);
+}
+#endif
diff --git a/contrib/gdb/gdb/nindy-tdep.c b/contrib/gdb/gdb/nindy-tdep.c
new file mode 100644
index 0000000..76f04e4
--- /dev/null
+++ b/contrib/gdb/gdb/nindy-tdep.c
@@ -0,0 +1,73 @@
+/* Target-machine dependent code for the NINDY monitor running on the Intel 960
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ Contributed by Intel Corporation.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Miscellaneous NINDY-dependent routines.
+ Some replace macros normally defined in "tm.h". */
+
+#include "defs.h"
+#include "symtab.h"
+#include "frame.h"
+
+/* 'start_frame' is a variable in the NINDY runtime startup routine
+ that contains the frame pointer of the 'start' routine (the routine
+ that calls 'main'). By reading its contents out of remote memory,
+ we can tell where the frame chain ends: backtraces should halt before
+ they display this frame. */
+
+int
+nindy_frame_chain_valid (chain, curframe)
+ unsigned int chain;
+ struct frame_info *curframe;
+{
+ struct symbol *sym;
+ struct minimal_symbol *msymbol;
+
+ /* crtnindy.o is an assembler module that is assumed to be linked
+ * first in an i80960 executable. It contains the true entry point;
+ * it performs startup up initialization and then calls 'main'.
+ *
+ * 'sf' is the name of a variable in crtnindy.o that is set
+ * during startup to the address of the first frame.
+ *
+ * 'a' is the address of that variable in 80960 memory.
+ */
+ static char sf[] = "start_frame";
+ CORE_ADDR a;
+
+
+ chain &= ~0x3f; /* Zero low 6 bits because previous frame pointers
+ contain return status info in them. */
+ if ( chain == 0 ){
+ return 0;
+ }
+
+ sym = lookup_symbol(sf, 0, VAR_NAMESPACE, (int *)NULL,
+ (struct symtab **)NULL);
+ if ( sym != 0 ){
+ a = SYMBOL_VALUE (sym);
+ } else {
+ msymbol = lookup_minimal_symbol (sf, NULL, NULL);
+ if (msymbol == NULL)
+ return 0;
+ a = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+
+ return ( chain != read_memory_integer(a,4) );
+}
diff --git a/contrib/gdb/gdb/nlm/Makefile.in b/contrib/gdb/gdb/nlm/Makefile.in
new file mode 100644
index 0000000..c17bcff
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/Makefile.in
@@ -0,0 +1,173 @@
+#Copyright 1989, 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+# This file is part of GDB.
+
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+host_alias = @host_alias@
+target_alias = @target_alias@
+program_transform_name = @program_transform_name@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+tooldir = $(libdir)/$(target_alias)
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+docdir = $(datadir)/doc
+
+SHELL = /bin/sh
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+CC_FOR_TARGET = ` \
+ if [ -f ../../gcc/xgcc ] ; then \
+ echo ../../gcc/xgcc -B../../gcc/; \
+ else \
+ t='$(program_transform_name)'; echo gcc | sed -e '' $$t; \
+ fi`
+
+NLMCONV_FOR_TARGET = ` \
+ if [ -f ../../binutils/nlmconv ] ; then \
+ echo ../../binutils/nlmconv; \
+ else \
+ t='$(program_transform_name)'; echo nlmconv | sed -e '' $$t; \
+ fi`
+
+# All the includes used for CFLAGS and for lint.
+INCLUDE_CFLAGS = -I. -I${srcdir}
+
+# CFLAGS is specifically reserved for setting from the command line
+# when running make. I.E. "make CFLAGS=-Wmissing-prototypes".
+CFLAGS = -g
+# INTERNAL_CFLAGS is the aggregate of all other *CFLAGS macros.
+INTERNAL_CFLAGS = ${CFLAGS} ${INCLUDE_CFLAGS} ${USER_CFLAGS}
+LDFLAGS = $(CFLAGS)
+
+# Perhaps should come from parent Makefile
+VERSION = gdbserve-4.12
+DIST=gdb
+
+# target-dependent makefile fragment come in here.
+@target_makefile_frag@
+# End target-dependent makefile fragment
+
+# All source files that go into linking GDB remote server.
+
+DEPFILES = $(GDBSERVE_DEPFILES)
+
+SOURCES = $(ALLDEPFILES)
+TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
+
+# Prevent Sun make from putting in the machine type. Setting
+# TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
+.c.o:
+ ${CC_FOR_TARGET} -c ${INTERNAL_CFLAGS} $<
+
+.S.o:
+ ${CC_FOR_TARGET} -c ${INTERNAL_CFLAGS} $<
+
+all: gdbserve.nlm
+
+# Traditionally "install" depends on "all". But it may be useful
+# not to; for example, if the user has made some trivial change to a
+# source file and doesn't care about rebuilding or just wants to save the
+# time it takes for make to check that all is up to date.
+# install-only is intended to address that need.
+install: all install-only
+install-only:
+ $(INSTALL) gdbserve.nlm $(bindir)/gdbserve.nlm
+
+uninstall: force
+ rm -f $(bindir)/gdbserve.nlm
+
+installcheck:
+check:
+info dvi:
+install-info:
+clean-info:
+
+gdbserve.nlm: gdbserve.O $(srcdir)/gdbserve.def
+ ${NLMCONV_FOR_TARGET} -T $(srcdir)/gdbserve.def
+
+gdbserve.O: prelude.o gdbserve.o $(TDEPFILES)
+ ${CC_FOR_TARGET} $(LDFLAGS) -r -o gdbserve.O prelude.o gdbserve.o ${TDEPFILES}
+
+# Put the proper machine-specific files first, so M-. on a machine
+# specific routine gets the one for the correct machine.
+# The xyzzy stuff below deals with empty DEPFILES
+TAGS: ${TAGFILES}
+ etags `find ${srcdir}/../config -name $(TM_FILE) -print` \
+ `find ${srcdir}/../config -name ${XM_FILE} -print` \
+ `find ${srcdir}/../config -name ${NAT_FILE} -print` \
+ `for i in yzzy ${DEPFILES}; do \
+ if [ x$$i != xyzzy ]; then \
+ echo ${srcdir}/$$i | sed -e 's/\.o$$/\.c/' ; \
+ fi; \
+ done` \
+ ${TAGFILES}
+tags: TAGS
+
+clean:
+ rm -f *.o ${ADD_FILES} *~
+ rm -f gdbserve.O gdbserve.nlm core make.log
+
+distclean: clean TAGS
+ rm -f config.log config.cache config.status
+ rm -f Makefile
+
+maintainer-clean realclean: clean
+ rm -f TAGS
+ rm -f config.log config.cache config.status
+ rm -f Makefile
+
+Makefile: Makefile.in config.status @target_makefile_frag_path@
+ $(SHELL) config.status
+
+config.status: configure
+ $(SHELL) config.status --recheck
+
+force:
+
+# GNU Make has an annoying habit of putting *all* the Makefile variables
+# into the environment, unless you include this target as a circumvention.
+# Rumor is that this will be fixed (and this target can be removed)
+# in GNU Make 4.0.
+.NOEXPORT:
+
+# GNU Make 3.63 has a different problem: it keeps tacking command line
+# overrides onto the definition of $(MAKE). This variable setting
+# will remove them.
+MAKEOVERRIDES=
+
+# This is the end of "Makefile.in".
diff --git a/contrib/gdb/gdb/nlm/configure b/contrib/gdb/gdb/nlm/configure
new file mode 100644
index 0000000..0b62dc1
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/configure
@@ -0,0 +1,864 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.3
+# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Initialize some other variables.
+subdirs=
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -build | --build | --buil | --bui | --bu | --b)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=PREFIX install architecture-dependent files in PREFIX
+ [same as prefix]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+--enable and --with options recognized:$ac_help
+EOF
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.3"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=gdbserve.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5'
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+ac_aux_dir=
+for ac_dir in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in `cd $srcdir;pwd`/../.. $srcdir/`cd $srcdir;pwd`/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Do some error checking and defaulting for the host and target type.
+# The inputs are:
+# configure --host=HOST --target=TARGET --build=BUILD NONOPT
+#
+# The rules are:
+# 1. You are not allowed to specify --host, --target, and nonopt at the
+# same time.
+# 2. Host defaults to nonopt.
+# 3. If nonopt is not specified, then host defaults to the current host,
+# as determined by config.guess.
+# 4. Target and build default to nonopt.
+# 5. If nonopt is not specified, then target and build default to host.
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+case $host---$target---$nonopt in
+NONE---*---* | *---NONE---* | *---*---NONE) ;;
+*) { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } ;;
+esac
+
+
+# Make sure we can run config.sub.
+if $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`$ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`$ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+echo $ac_n "checking target system type""... $ac_c" 1>&6
+
+target_alias=$target
+case "$target_alias" in
+NONE)
+ case $nonopt in
+ NONE) target_alias=$host_alias ;;
+ *) target_alias=$nonopt ;;
+ esac ;;
+esac
+
+target=`$ac_config_sub $target_alias`
+target_cpu=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+target_vendor=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+target_os=`echo $target | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$target" 1>&6
+
+echo $ac_n "checking build system type""... $ac_c" 1>&6
+
+build_alias=$build
+case "$build_alias" in
+NONE)
+ case $nonopt in
+ NONE) build_alias=$host_alias ;;
+ *) build_alias=$nonopt ;;
+ esac ;;
+esac
+
+build=`$ac_config_sub $build_alias`
+build_cpu=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'`
+build_vendor=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'`
+build_os=`echo $build | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'`
+echo "$ac_t""$build" 1>&6
+
+test "$host_alias" != "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $.
+ echo 's,\\,\\\\,g; s,\$,$$,g' > conftestsed
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ for ac_prog in ginstall installbsd scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ # OSF/1 installbsd also uses dspmsg, but is usable.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_ifs"
+ # As a last resort, use the slow shell script.
+ test -z "$ac_cv_path_install" && ac_cv_path_install="$ac_install_sh"
+fi
+ INSTALL="$ac_cv_path_install"
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+case "${target_cpu}" in
+alpha) gdb_target_cpu=alpha ;;
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[345]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+np1) gdb_target_cpu=gould ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+esac
+
+target_makefile_frag=${srcdir}/../config/${gdb_target_cpu}/gdbserve.mt
+if ! -f ${target_makefile_frag} ; then
+ { echo "configure: error: "*** GDBSERVE does not support target ${target}"" 1>&2; exit 1; }
+fi
+
+target_makefile_frag_path=$target_makefile_frag
+
+
+
+cpufile=`sed -n '
+s/CPU_FILE *= *\(^ *\)/\1/p
+' ${target_makefile_frag}
+
+files=
+links=
+rm -f cpu.h
+if "${cpufile}" != "" ; then
+ files="${files} ${cpufile}.h"
+ links="${links} cpu.h"
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+ >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.3"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@target@%$target%g
+s%@target_alias@%$target_alias%g
+s%@target_cpu@%$target_cpu%g
+s%@target_vendor@%$target_vendor%g
+s%@target_os@%$target_os%g
+s%@build@%$build%g
+s%@build_alias@%$build_alias%g
+s%@build_cpu@%$build_cpu%g
+s%@build_vendor@%$build_vendor%g
+s%@build_os@%$build_os%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@target_makefile_frag_path@%$target_makefile_frag_path%g
+/@target_makefile_frag@/r $target_makefile_frag
+s%@target_makefile_frag@%%g
+
+CEOF
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust relative srcdir, etc. for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+fi; done
+rm -f conftest.subs
+
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+ac_sources="$files"
+ac_dests="$links"
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+srcdir=$ac_given_srcdir
+while test -n "$ac_sources"; do
+ set $ac_dests; ac_dest=$1; shift; ac_dests=$*
+ set $ac_sources; ac_source=$1; shift; ac_sources=$*
+
+ echo "linking $srcdir/$ac_source to $ac_dest"
+
+ if test ! -r $srcdir/$ac_source; then
+ { echo "configure: error: $srcdir/$ac_source: File not found" 1>&2; exit 1; }
+ fi
+ rm -f $ac_dest
+
+ # Make relative symlinks.
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dest_dir=`echo $ac_dest|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dest_dir" != "$ac_dest" && test "$ac_dest_dir" != .; then
+ # The dest file is in a subdirectory.
+ test ! -d "$ac_dest_dir" && mkdir "$ac_dest_dir"
+ ac_dest_dir_suffix="/`echo $ac_dest_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dest_dir_suffix.
+ ac_dots=`echo $ac_dest_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dest_dir_suffix= ac_dots=
+ fi
+
+ case "$srcdir" in
+ [/$]*) ac_rel_source="$srcdir/$ac_source" ;;
+ *) ac_rel_source="$ac_dots$srcdir/$ac_source" ;;
+ esac
+
+ # Make a symlink if possible; otherwise try a hard link.
+ if ln -s $ac_rel_source $ac_dest 2>/dev/null ||
+ ln $srcdir/$ac_source $ac_dest; then :
+ else
+ { echo "configure: error: can not link $ac_dest to $srcdir/$ac_source" 1>&2; exit 1; }
+ fi
+done
+
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
diff --git a/contrib/gdb/gdb/nlm/configure.in b/contrib/gdb/gdb/nlm/configure.in
new file mode 100644
index 0000000..f70be82
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/configure.in
@@ -0,0 +1,55 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.3)dnl
+AC_INIT(gdbserve.c)
+
+AC_CONFIG_AUX_DIR(`cd $srcdir;pwd`/../..)
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
+
+AC_PROG_INSTALL
+
+# Map target cpu into the config cpu subdirectory name.
+# The default is $target_cpu.
+changequote(,)dnl
+case "${target_cpu}" in
+alpha) gdb_target_cpu=alpha ;;
+c[12]) gdb_target_cpu=convex ;;
+hppa*) gdb_target_cpu=pa ;;
+i[345]86) gdb_target_cpu=i386 ;;
+m68*) gdb_target_cpu=m68k ;;
+np1) gdb_target_cpu=gould ;;
+pn) gdb_target_cpu=gould ;;
+pyramid) gdb_target_cpu=pyr ;;
+sparc*) gdb_target_cpu=sparc ;;
+*) gdb_target_cpu=$target_cpu ;;
+esac
+changequote([,])dnl
+
+target_makefile_frag=${srcdir}/../config/${gdb_target_cpu}/gdbserve.mt
+if [ ! -f ${target_makefile_frag} ]; then
+ AC_MSG_ERROR("*** GDBSERVE does not support target ${target}")
+fi
+
+dnl We have to assign the same value to other variables because autoconf
+dnl doesn't provide a mechanism to substitute a replacement keyword with
+dnl arbitrary data or pathnames.
+dnl
+target_makefile_frag_path=$target_makefile_frag
+AC_SUBST(target_makefile_frag_path)
+AC_SUBST_FILE(target_makefile_frag)
+
+cpufile=`sed -n '
+s/CPU_FILE[ ]*=[ ]*\([^ ]*\)/\1/p
+' ${target_makefile_frag}
+
+files=
+links=
+rm -f cpu.h
+if [ "${cpufile}" != "" ]; then
+ files="${files} ${cpufile}.h"
+ links="${links} cpu.h"
+fi
+
+AC_LINK_FILES($files, $links)
+AC_OUTPUT(Makefile)
+
diff --git a/contrib/gdb/gdb/nlm/gdbserve.c b/contrib/gdb/gdb/nlm/gdbserve.c
new file mode 100644
index 0000000..62adf3a
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/gdbserve.c
@@ -0,0 +1,1056 @@
+/* gdbserve.c -- NLM debugging stub for Novell NetWare.
+
+ This is originally based on an m68k software stub written by Glenn
+ Engel at HP, but has changed quite a bit. It was modified for the
+ i386 by Jim Kingdon, Cygnus Support. It was modified to run under
+ NetWare by Ian Lance Taylor, Cygnus Support.
+
+ This code is intended to produce an NLM (a NetWare Loadable Module)
+ to run under Novell NetWare. To create the NLM, compile this code
+ into an object file using the NLM SDK on any i386 host, and use the
+ nlmconv program (available in the GNU binutils) to transform the
+ resulting object file into an NLM. */
+
+/****************************************************************************
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ HP offers the following for use in the public domain. HP makes no
+ warranty with regard to the software or it's performance and the
+ user accepts the software "AS IS" with all faults.
+
+ HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
+ TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+****************************************************************************/
+
+/****************************************************************************
+ *
+ * The following gdb commands are supported:
+ *
+ * command function Return value
+ *
+ * g return the value of the CPU registers hex data or ENN
+ * G set the value of the CPU registers OK or ENN
+ *
+ * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN
+ * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN
+ *
+ * c Resume at current address SNN ( signal NN)
+ * cAA..AA Continue at address AA..AA SNN
+ *
+ * s Step one instruction SNN
+ * sAA..AA Step one instruction from AA..AA SNN
+ *
+ * k kill
+ *
+ * ? What was the last sigval ? SNN (signal NN)
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum. A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer. '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host: Reply:
+ * $m0,10#2a +$00010203040506070809101112131415#42
+ *
+ ****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+
+#ifdef __i386__
+#include <dfs.h>
+#include <conio.h>
+#include <advanced.h>
+#include <debugapi.h>
+#include <process.h>
+#else
+#include <nwtypes.h>
+#include <nwdfs.h>
+#include <nwconio.h>
+#include <nwadv.h>
+#include <nwdbgapi.h>
+#include <nwthread.h>
+#endif
+
+#include <aio.h>
+#include "cpu.h"
+
+
+/****************************************************/
+/* This information is from Novell. It is not in any of the standard
+ NetWare header files. */
+
+struct DBG_LoadDefinitionStructure
+{
+ void *reserved1[4];
+ LONG reserved5;
+ LONG LDCodeImageOffset;
+ LONG LDCodeImageLength;
+ LONG LDDataImageOffset;
+ LONG LDDataImageLength;
+ LONG LDUninitializedDataLength;
+ LONG LDCustomDataOffset;
+ LONG LDCustomDataSize;
+ LONG reserved6[2];
+ LONG (*LDInitializationProcedure)(void);
+};
+
+#define LO_NORMAL 0x0000
+#define LO_STARTUP 0x0001
+#define LO_PROTECT 0x0002
+#define LO_DEBUG 0x0004
+#define LO_AUTO_LOAD 0x0008
+
+/* Loader returned error codes */
+#define LOAD_COULD_NOT_FIND_FILE 1
+#define LOAD_ERROR_READING_FILE 2
+#define LOAD_NOT_NLM_FILE_FORMAT 3
+#define LOAD_WRONG_NLM_FILE_VERSION 4
+#define LOAD_REENTRANT_INITIALIZE_FAILURE 5
+#define LOAD_CAN_NOT_LOAD_MULTIPLE_COPIES 6
+#define LOAD_ALREADY_IN_PROGRESS 7
+#define LOAD_NOT_ENOUGH_MEMORY 8
+#define LOAD_INITIALIZE_FAILURE 9
+#define LOAD_INCONSISTENT_FILE_FORMAT 10
+#define LOAD_CAN_NOT_LOAD_AT_STARTUP 11
+#define LOAD_AUTO_LOAD_MODULES_NOT_LOADED 12
+#define LOAD_UNRESOLVED_EXTERNAL 13
+#define LOAD_PUBLIC_ALREADY_DEFINED 14
+/****************************************************/
+
+/* The main thread ID. */
+static int mainthread;
+
+/* An error message for the main thread to print. */
+static char *error_message;
+
+/* The AIO port handle. */
+static int AIOhandle;
+
+/* BUFMAX defines the maximum number of characters in inbound/outbound
+ buffers. At least NUMREGBYTES*2 are needed for register packets */
+#define BUFMAX (REGISTER_BYTES * 2 + 16)
+
+/* remote_debug > 0 prints ill-formed commands in valid packets and
+ checksum errors. */
+static int remote_debug = 1;
+
+static const char hexchars[] = "0123456789abcdef";
+
+unsigned char breakpoint_insn[] = BREAKPOINT;
+
+char *mem2hex (void *mem, char *buf, int count, int may_fault);
+char *hex2mem (char *buf, void *mem, int count, int may_fault);
+extern void set_step_traps (struct StackFrame *);
+extern void clear_step_traps (struct StackFrame *);
+
+static int __main() {};
+
+/* Read a character from the serial port. This must busy wait, but
+ that's OK because we will be the only thread running anyhow. */
+
+static int
+getDebugChar ()
+{
+ int err;
+ LONG got;
+ unsigned char ret;
+
+ do
+ {
+ err = AIOReadData (AIOhandle, (char *) &ret, 1, &got);
+ if (err != 0)
+ {
+ error_message = "AIOReadData failed";
+ ResumeThread (mainthread);
+ return -1;
+ }
+ }
+ while (got == 0);
+
+ return ret;
+}
+
+/* Write a character to the serial port. Returns 0 on failure,
+ non-zero on success. */
+
+static int
+putDebugChar (c)
+ unsigned char c;
+{
+ int err;
+ LONG put;
+
+ put = 0;
+ while (put < 1)
+ {
+ err = AIOWriteData (AIOhandle, (char *) &c, 1, &put);
+ if (err != 0)
+ ConsolePrintf ("AIOWriteData: err = %d, put = %d\r\n", err, put);
+ }
+ return 1;
+}
+
+/* Turn a hex character into a number. */
+
+static int
+hex (ch)
+ char ch;
+{
+ if ((ch >= 'a') && (ch <= 'f'))
+ return (ch-'a'+10);
+ if ((ch >= '0') && (ch <= '9'))
+ return (ch-'0');
+ if ((ch >= 'A') && (ch <= 'F'))
+ return (ch-'A'+10);
+ return (-1);
+}
+
+/* Scan for the sequence $<data>#<checksum>. Returns 0 on failure,
+ non-zero on success. */
+
+static int
+getpacket (buffer)
+ char * buffer;
+{
+ unsigned char checksum;
+ unsigned char xmitcsum;
+ int i;
+ int count;
+ int ch;
+
+ do
+ {
+ /* wait around for the start character, ignore all other characters */
+ while ((ch = getDebugChar()) != '$')
+ if (ch == -1)
+ return 0;
+ checksum = 0;
+ xmitcsum = -1;
+
+ count = 0;
+
+ /* now, read until a # or end of buffer is found */
+ while (count < BUFMAX)
+ {
+ ch = getDebugChar();
+ if (ch == -1)
+ return 0;
+ if (ch == '#')
+ break;
+ checksum = checksum + ch;
+ buffer[count] = ch;
+ count = count + 1;
+ }
+ buffer[count] = 0;
+
+ if (ch == '#')
+ {
+ ch = getDebugChar ();
+ if (ch == -1)
+ return 0;
+ xmitcsum = hex(ch) << 4;
+ ch = getDebugChar ();
+ if (ch == -1)
+ return 0;
+ xmitcsum += hex(ch);
+
+ if (checksum != xmitcsum)
+ {
+ if (remote_debug)
+ ConsolePrintf ("bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n",
+ checksum,xmitcsum,buffer);
+ /* failed checksum */
+ if (! putDebugChar('-'))
+ return 0;
+ return 1;
+ }
+ else
+ {
+ /* successful transfer */
+ if (! putDebugChar('+'))
+ return 0;
+ /* if a sequence char is present, reply the sequence ID */
+ if (buffer[2] == ':')
+ {
+ if (! putDebugChar (buffer[0])
+ || ! putDebugChar (buffer[1]))
+ return 0;
+ /* remove sequence chars from buffer */
+ count = strlen(buffer);
+ for (i=3; i <= count; i++)
+ buffer[i-3] = buffer[i];
+ }
+ }
+ }
+ }
+ while (checksum != xmitcsum);
+
+ if (remote_debug)
+ ConsolePrintf ("Received packet \"%s\"\r\n", buffer);
+
+ return 1;
+}
+
+/* Send the packet in buffer. Returns 0 on failure, non-zero on
+ success. */
+
+static int
+putpacket (buffer)
+ char * buffer;
+{
+ unsigned char checksum;
+ int count;
+ int ch;
+
+ if (remote_debug)
+ ConsolePrintf ("Sending packet \"%s\"\r\n", buffer);
+
+ /* $<packet info>#<checksum>. */
+ do
+ {
+ if (! putDebugChar('$'))
+ return 0;
+ checksum = 0;
+ count = 0;
+
+ while (ch=buffer[count])
+ {
+ if (! putDebugChar(ch))
+ return 0;
+ checksum += ch;
+ count += 1;
+ }
+
+ if (! putDebugChar('#')
+ || ! putDebugChar(hexchars[checksum >> 4])
+ || ! putDebugChar(hexchars[checksum % 16]))
+ return 0;
+
+ ch = getDebugChar ();
+ if (ch == -1)
+ return 0;
+ }
+ while (ch != '+');
+
+ return 1;
+}
+
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+static short error;
+
+static void
+debug_error (format, parm)
+ char *format;
+ char *parm;
+{
+ if (remote_debug)
+ {
+ ConsolePrintf (format, parm);
+ ConsolePrintf ("\n");
+ }
+}
+
+/* This is set if we could get a memory access fault. */
+static int mem_may_fault;
+
+/* Indicate to caller of mem2hex or hex2mem that there has been an
+ error. */
+volatile int mem_err = 0;
+
+#ifndef ALTERNATE_MEM_FUNCS
+/* These are separate functions so that they are so short and sweet
+ that the compiler won't save any registers (if there is a fault
+ to mem_fault, they won't get restored, so there better not be any
+ saved). */
+
+int
+get_char (addr)
+ char *addr;
+{
+ return *addr;
+}
+
+void
+set_char (addr, val)
+ char *addr;
+ int val;
+{
+ *addr = val;
+}
+#endif /* ALTERNATE_MEM_FUNCS */
+
+/* convert the memory pointed to by mem into hex, placing result in buf */
+/* return a pointer to the last char put in buf (null) */
+/* If MAY_FAULT is non-zero, then we should set mem_err in response to
+ a fault; if zero treat a fault like any other fault in the stub. */
+
+char *
+mem2hex (mem, buf, count, may_fault)
+ void *mem;
+ char *buf;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+ char *ptr = mem;
+
+ mem_may_fault = may_fault;
+ for (i = 0; i < count; i++)
+ {
+ ch = get_char (ptr++);
+ if (may_fault && mem_err)
+ return (buf);
+ *buf++ = hexchars[ch >> 4];
+ *buf++ = hexchars[ch % 16];
+ }
+ *buf = 0;
+ mem_may_fault = 0;
+ return(buf);
+}
+
+/* convert the hex array pointed to by buf into binary to be placed in mem */
+/* return a pointer to the character AFTER the last byte written */
+
+char *
+hex2mem (buf, mem, count, may_fault)
+ char *buf;
+ void *mem;
+ int count;
+ int may_fault;
+{
+ int i;
+ unsigned char ch;
+ char *ptr = mem;
+
+ mem_may_fault = may_fault;
+ for (i=0;i<count;i++)
+ {
+ ch = hex(*buf++) << 4;
+ ch = ch + hex(*buf++);
+ set_char (ptr++, ch);
+ if (may_fault && mem_err)
+ return (ptr);
+ }
+ mem_may_fault = 0;
+ return(mem);
+}
+
+/* This function takes the 386 exception vector and attempts to
+ translate this number into a unix compatible signal value. */
+
+int
+computeSignal (exceptionVector)
+ int exceptionVector;
+{
+ int sigval;
+ switch (exceptionVector)
+ {
+ case 0 : sigval = 8; break; /* divide by zero */
+ case 1 : sigval = 5; break; /* debug exception */
+ case 3 : sigval = 5; break; /* breakpoint */
+ case 4 : sigval = 16; break; /* into instruction (overflow) */
+ case 5 : sigval = 16; break; /* bound instruction */
+ case 6 : sigval = 4; break; /* Invalid opcode */
+ case 7 : sigval = 8; break; /* coprocessor not available */
+ case 8 : sigval = 7; break; /* double fault */
+ case 9 : sigval = 11; break; /* coprocessor segment overrun */
+ case 10 : sigval = 11; break; /* Invalid TSS */
+ case 11 : sigval = 11; break; /* Segment not present */
+ case 12 : sigval = 11; break; /* stack exception */
+ case 13 : sigval = 11; break; /* general protection */
+ case 14 : sigval = 11; break; /* page fault */
+ case 16 : sigval = 7; break; /* coprocessor error */
+ default:
+ sigval = 7; /* "software generated"*/
+ }
+ return (sigval);
+}
+
+/**********************************************/
+/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
+/* RETURN NUMBER OF CHARS PROCESSED */
+/**********************************************/
+static int
+hexToInt(ptr, intValue)
+ char **ptr;
+ int *intValue;
+{
+ int numChars = 0;
+ int hexValue;
+
+ *intValue = 0;
+
+ while (**ptr)
+ {
+ hexValue = hex(**ptr);
+ if (hexValue >=0)
+ {
+ *intValue = (*intValue <<4) | hexValue;
+ numChars ++;
+ }
+ else
+ break;
+
+ (*ptr)++;
+ }
+
+ return (numChars);
+}
+
+/* This function does all command processing for interfacing to gdb.
+ It is called whenever an exception occurs in the module being
+ debugged. */
+
+static LONG
+handle_exception (frame)
+ struct StackFrame *frame;
+{
+ int addr, length;
+ char *ptr;
+ static struct DBG_LoadDefinitionStructure *ldinfo = 0;
+ static unsigned char first_insn[BREAKPOINT_SIZE]; /* The first instruction in the program. */
+
+#if 0
+ /* According to some documentation from Novell, the bell sometimes
+ may be ringing at this point. This can be stopped on Netware 4
+ systems by calling the undocumented StopBell() function. */
+
+ StopBell ();
+#endif
+
+ if (remote_debug)
+ {
+ ConsolePrintf ("vector=%d: %s, pc=%08x, thread=%08x\r\n",
+ frame->ExceptionNumber,
+ frame->ExceptionDescription,
+ frame->ExceptionPC,
+ GetThreadID ());
+ }
+
+ switch (frame->ExceptionNumber)
+ {
+ case START_NLM_EVENT:
+ /* If the NLM just started, we record the module load information
+ and the thread ID, and set a breakpoint at the first instruction
+ in the program. */
+
+ ldinfo = ((struct DBG_LoadDefinitionStructure *)
+ frame->ExceptionErrorCode);
+ memcpy (first_insn, ldinfo->LDInitializationProcedure,
+ BREAKPOINT_SIZE);
+ memcpy (ldinfo->LDInitializationProcedure, breakpoint_insn,
+ BREAKPOINT_SIZE);
+ flush_i_cache ();
+ return RETURN_TO_PROGRAM;
+
+ case ENTER_DEBUGGER_EVENT:
+ case KEYBOARD_BREAK_EVENT:
+ /* Pass some events on to the next debugger, in case it will handle
+ them. */
+ return RETURN_TO_NEXT_DEBUGGER;
+
+ case 3: /* Breakpoint */
+ /* After we've reached the initial breakpoint, reset it. */
+ if (frame->ExceptionPC - DECR_PC_AFTER_BREAK == (LONG) ldinfo->LDInitializationProcedure
+ && memcmp (ldinfo->LDInitializationProcedure, breakpoint_insn,
+ BREAKPOINT_SIZE) == 0)
+ {
+ memcpy (ldinfo->LDInitializationProcedure, first_insn,
+ BREAKPOINT_SIZE);
+ frame->ExceptionPC -= DECR_PC_AFTER_BREAK;
+ flush_i_cache ();
+ }
+ /* Normal breakpoints end up here */
+ do_status (remcomOutBuffer, frame);
+ break;
+
+ default:
+ /* At the moment, we don't care about most of the unusual NetWare
+ exceptions. */
+ if (frame->ExceptionNumber > 31)
+ return RETURN_TO_PROGRAM;
+
+ /* Most machine level exceptions end up here */
+ do_status (remcomOutBuffer, frame);
+ break;
+
+ case 11: /* Segment not present */
+ case 13: /* General protection */
+ case 14: /* Page fault */
+ /* If we get a GP fault, and mem_may_fault is set, and the
+ instruction pointer is near set_char or get_char, then we caused
+ the fault ourselves accessing an illegal memory location. */
+ if (mem_may_fault
+ && ((frame->ExceptionPC >= (long) &set_char
+ && frame->ExceptionPC < (long) &set_char + 50)
+ || (frame->ExceptionPC >= (long) &get_char
+ && frame->ExceptionPC < (long) &get_char + 50)))
+ {
+ mem_err = 1;
+ /* Point the instruction pointer at an assembly language stub
+ which just returns from the function. */
+
+ frame->ExceptionPC += 4; /* Skip the load or store */
+
+ /* Keep going. This will act as though it returned from
+ set_char or get_char. The calling routine will check
+ mem_err, and do the right thing. */
+ return RETURN_TO_PROGRAM;
+ }
+ /* Random mem fault, report it */
+ do_status (remcomOutBuffer, frame);
+ break;
+
+ case TERMINATE_NLM_EVENT:
+ /* There is no way to get the exit status. */
+ sprintf (remcomOutBuffer, "W%02x", 0);
+ break; /* We generate our own status */
+ }
+
+ /* FIXME: How do we know that this exception has anything to do with
+ the program we are debugging? We can check whether the PC is in
+ the range of the module we are debugging, but that doesn't help
+ much since an error could occur in a library routine. */
+
+ clear_step_traps (frame);
+
+ if (! putpacket(remcomOutBuffer))
+ return RETURN_TO_NEXT_DEBUGGER;
+
+ if (frame->ExceptionNumber == TERMINATE_NLM_EVENT)
+ {
+ ResumeThread (mainthread);
+ return RETURN_TO_PROGRAM;
+ }
+
+ while (1)
+ {
+ error = 0;
+ remcomOutBuffer[0] = 0;
+ if (! getpacket (remcomInBuffer))
+ return RETURN_TO_NEXT_DEBUGGER;
+ switch (remcomInBuffer[0])
+ {
+ case '?':
+ do_status (remcomOutBuffer, frame);
+ break;
+ case 'd':
+ remote_debug = !(remote_debug); /* toggle debug flag */
+ break;
+ case 'g':
+ /* return the value of the CPU registers */
+ frame_to_registers (frame, remcomOutBuffer);
+ break;
+ case 'G':
+ /* set the value of the CPU registers - return OK */
+ registers_to_frame (&remcomInBuffer[1], frame);
+ strcpy(remcomOutBuffer,"OK");
+ break;
+
+ case 'm':
+ /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */
+ /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ {
+ ptr = 0;
+ mem_err = 0;
+ mem2hex((char*) addr, remcomOutBuffer, length, 1);
+ if (mem_err)
+ {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ }
+ }
+
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E01");
+ debug_error("malformed read memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ case 'M':
+ /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
+ /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ if (*(ptr++) == ',')
+ if (hexToInt(&ptr,&length))
+ if (*(ptr++) == ':')
+ {
+ mem_err = 0;
+ hex2mem(ptr, (char*) addr, length, 1);
+
+ if (mem_err)
+ {
+ strcpy (remcomOutBuffer, "E03");
+ debug_error ("memory fault");
+ }
+ else
+ {
+ strcpy(remcomOutBuffer,"OK");
+ }
+
+ ptr = 0;
+ }
+ if (ptr)
+ {
+ strcpy(remcomOutBuffer,"E02");
+ debug_error("malformed write memory command: %s",remcomInBuffer);
+ }
+ break;
+
+ case 'c':
+ case 's':
+ /* cAA..AA Continue at address AA..AA(optional) */
+ /* sAA..AA Step one instruction from AA..AA(optional) */
+ /* try to read optional parameter, pc unchanged if no parm */
+ ptr = &remcomInBuffer[1];
+ if (hexToInt(&ptr,&addr))
+ {
+/* registers[PC_REGNUM].lo = addr;*/
+ fprintf (stderr, "Setting PC to 0x%x\n", addr);
+ while (1);
+ }
+
+ if (remcomInBuffer[0] == 's')
+ set_step_traps (frame);
+
+ flush_i_cache ();
+ return RETURN_TO_PROGRAM;
+
+ case 'k':
+ /* kill the program */
+ KillMe (ldinfo);
+ ResumeThread (mainthread);
+ return RETURN_TO_PROGRAM;
+
+ case 'q': /* Query message */
+ if (strcmp (&remcomInBuffer[1], "Offsets") == 0)
+ {
+ sprintf (remcomOutBuffer, "Text=%x;Data=%x;Bss=%x",
+ ldinfo->LDCodeImageOffset,
+ ldinfo->LDDataImageOffset,
+ ldinfo->LDDataImageOffset + ldinfo->LDDataImageLength);
+ }
+ else
+ sprintf (remcomOutBuffer, "E04, Unknown query %s", &remcomInBuffer[1]);
+ break;
+ }
+
+ /* reply to the request */
+ if (! putpacket(remcomOutBuffer))
+ return RETURN_TO_NEXT_DEBUGGER;
+ }
+}
+
+char *progname;
+
+struct bitRate {
+ BYTE bitRate;
+ const char *bitRateString;
+};
+
+struct bitRate bitRateTable[] =
+{
+ { AIO_BAUD_50 , "50" },
+ { AIO_BAUD_75 , "75" },
+ { AIO_BAUD_110 , "110" },
+ { AIO_BAUD_134p5 , "134.5" },
+ { AIO_BAUD_150 , "150" },
+ { AIO_BAUD_300 , "300" },
+ { AIO_BAUD_600 , "600" },
+ { AIO_BAUD_1200 , "1200" },
+ { AIO_BAUD_1800 , "1800" },
+ { AIO_BAUD_2000 , "2000" },
+ { AIO_BAUD_2400 , "2400" },
+ { AIO_BAUD_3600 , "3600" },
+ { AIO_BAUD_4800 , "4800" },
+ { AIO_BAUD_7200 , "7200" },
+ { AIO_BAUD_9600 , "9600" },
+ { AIO_BAUD_19200 , "19200" },
+ { AIO_BAUD_38400 , "38400" },
+ { AIO_BAUD_57600 , "57600" },
+ { AIO_BAUD_115200, "115200" },
+ { -1, NULL }
+};
+
+char dataBitsTable[] = "5678";
+
+char *stopBitsTable[] = { "1", "1.5", "2" };
+
+char parity[] = "NOEMS";
+
+/* Start up. The main thread opens the named serial I/O port, loads
+ the named NLM module and then goes to sleep. The serial I/O port
+ is named as a board number and a port number. It would be more DOS
+ like to provide a menu of available serial ports, but I don't want
+ to have to figure out how to do that. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int hardware, board, port;
+ BYTE bitRate;
+ BYTE dataBits;
+ BYTE stopBits;
+ BYTE parityMode;
+ LONG err;
+ struct debuggerStructure s;
+ int cmdindx;
+ char *cmdlin;
+ int i;
+
+ /* set progname */
+ progname = "gdbserve";
+
+ /* set default serial line */
+ hardware = -1;
+ board = 0;
+ port = 0;
+
+ /* set default serial line characteristics */
+ bitRate = AIO_BAUD_9600;
+ dataBits = AIO_DATA_BITS_8;
+ stopBits = AIO_STOP_BITS_1;
+ parityMode = AIO_PARITY_NONE;
+
+ cmdindx = 0;
+ for (argc--, argv++; *argv; argc--, argv++)
+ {
+ char *bp;
+ char *ep;
+
+ if (strnicmp(*argv, "BAUD=", 5) == 0)
+ {
+ struct bitRate *brp;
+
+ bp = *argv + 5;
+ for (brp = bitRateTable; brp->bitRate != (BYTE) -1; brp++)
+ {
+ if (strcmp(brp->bitRateString, bp) == 0)
+ {
+ bitRate = brp->bitRate;
+ break;
+ }
+ }
+
+ if (brp->bitRateString == NULL)
+ {
+ fprintf(stderr, "%s: %s: unknown or unsupported bit rate",
+ progname, bp);
+ exit (1);
+ }
+ }
+ else if (strnicmp(*argv, "BOARD=", 6) == 0)
+ {
+ bp = *argv + 6;
+ board = strtol (bp, &ep, 0);
+ if (ep == bp || *ep != '\0')
+ {
+ fprintf (stderr, "%s: %s: expected integer argument\n",
+ progname, bp);
+ exit(1);
+ }
+ }
+#if 1 /* FIXME: this option has been depricated */
+ else if (strnicmp(*argv, "NODE=", 5) == 0)
+ {
+ bp = *argv + 5;
+ board = strtol (bp, &ep, 0);
+ if (ep == bp || *ep != '\0')
+ {
+ fprintf (stderr, "%s: %s: expected integer argument\n",
+ progname, bp);
+ exit(1);
+ }
+ }
+#endif
+ else if (strnicmp(*argv, "PORT=", 5) == 0)
+ {
+ bp = *argv + 5;
+ port = strtol (bp, &ep, 0);
+ if (ep == bp || *ep != '\0')
+ {
+ fprintf (stderr, "%s: %s: expected integer argument\n",
+ progname, bp);
+ exit(1);
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ cmdindx++;
+ }
+
+ if (argc == 0)
+ {
+ fprintf (stderr,
+ "Usage: load %s [options] program [arguments]\n", progname);
+ exit (1);
+ }
+
+ err = AIOAcquirePort (&hardware, &board, &port, &AIOhandle);
+ if (err != AIO_SUCCESS)
+ {
+ switch (err)
+ {
+ case AIO_PORT_NOT_AVAILABLE:
+ fprintf (stderr, "Port not available\n");
+ break;
+
+ case AIO_BOARD_NUMBER_INVALID:
+ case AIO_PORT_NUMBER_INVALID:
+ fprintf (stderr, "No such port\n");
+ break;
+
+ default:
+ fprintf (stderr, "Could not open port: %d\n", err);
+ break;
+ }
+
+ exit (1);
+ }
+
+ err = AIOConfigurePort (AIOhandle, bitRate, dataBits, stopBits, parityMode,
+ AIO_HARDWARE_FLOW_CONTROL_OFF);
+
+ if (err == AIO_QUALIFIED_SUCCESS)
+ {
+ AIOPORTCONFIG portConfig;
+
+ fprintf (stderr, "Port configuration changed!\n");
+
+ portConfig.returnLength = sizeof(portConfig);
+ AIOGetPortConfiguration (AIOhandle, &portConfig, NULL);
+
+ fprintf (stderr,
+ " Bit Rate: %s, Data Bits: %c, Stop Bits: %s, Parity: %c,\
+ Flow:%s\n",
+ bitRateTable[portConfig.bitRate].bitRateString,
+ dataBitsTable[portConfig.dataBits],
+ stopBitsTable[portConfig.stopBits],
+ parity[portConfig.parityMode],
+ portConfig.flowCtrlMode ? "ON" : "OFF");
+ }
+ else if (err != AIO_SUCCESS)
+ {
+ fprintf (stderr, "Could not configure port: %d\n", err);
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ if (AIOSetExternalControl(AIOhandle, AIO_EXTERNAL_CONTROL,
+ (AIO_EXTCTRL_DTR | AIO_EXTCTRL_RTS))
+ != AIO_SUCCESS)
+ {
+ LONG extStatus, chgdExtStatus;
+
+ fprintf (stderr, "Could not set desired port controls!\n");
+ AIOGetExternalStatus (AIOhandle, &extStatus, &chgdExtStatus);
+ fprintf (stderr, "Port controls now: %d, %d\n", extStatus,
+ chgdExtStatus);
+ }
+
+ /* Register ourselves as an alternate debugger. */
+ memset (&s, 0, sizeof s);
+ s.DDSResourceTag = ((struct ResourceTagStructure *)
+ AllocateResourceTag (GetNLMHandle (),
+ (BYTE *)"gdbserver",
+ DebuggerSignature));
+ if (s.DDSResourceTag == 0)
+ {
+ fprintf (stderr, "AllocateResourceTag failed\n");
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+ s.DDSdebuggerEntry = handle_exception;
+ s.DDSFlags = TSS_FRAME_BIT;
+
+ err = RegisterDebuggerRTag (&s, AT_FIRST);
+ if (err != 0)
+ {
+ fprintf (stderr, "RegisterDebuggerRTag failed\n");
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ /* Get the command line we were invoked with, and advance it past
+ our name and the board and port arguments. */
+ cmdlin = getcmd ((char *) NULL);
+ for (i = 0; i < cmdindx; i++)
+ {
+ while (! isspace (*cmdlin))
+ ++cmdlin;
+ while (isspace (*cmdlin))
+ ++cmdlin;
+ }
+
+ /* In case GDB is started before us, ack any packets (presumably
+ "$?#xx") sitting there. */
+ if (! putDebugChar ('+'))
+ {
+ fprintf (stderr, "putDebugChar failed\n");
+ UnRegisterDebugger (&s);
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ mainthread = GetThreadID ();
+
+ if (remote_debug > 0)
+ ConsolePrintf ("About to call LoadModule with \"%s\" %08x\r\n",
+ cmdlin, __GetScreenID (GetCurrentScreen()));
+
+ /* Start up the module to be debugged. */
+ err = LoadModule ((struct ScreenStruct *) __GetScreenID (GetCurrentScreen()),
+ (BYTE *)cmdlin, LO_DEBUG);
+ if (err != 0)
+ {
+ fprintf (stderr, "LoadModule failed: %d\n", err);
+ UnRegisterDebugger (&s);
+ AIOReleasePort (AIOhandle);
+ exit (1);
+ }
+
+ /* Wait for the debugger to wake us up. */
+ if (remote_debug > 0)
+ ConsolePrintf ("Suspending main thread (%08x)\r\n", mainthread);
+ SuspendThread (mainthread);
+ if (remote_debug > 0)
+ ConsolePrintf ("Resuming main thread (%08x)\r\n", mainthread);
+
+ /* If we are woken up, print an optional error message, deregister
+ ourselves and exit. */
+ if (error_message != NULL)
+ fprintf (stderr, "%s\n", error_message);
+ UnRegisterDebugger (&s);
+ AIOReleasePort (AIOhandle);
+ exit (0);
+}
diff --git a/contrib/gdb/gdb/nlm/gdbserve.def b/contrib/gdb/gdb/nlm/gdbserve.def
new file mode 100644
index 0000000..588028d
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/gdbserve.def
@@ -0,0 +1,42 @@
+description "GDB debugger stub"
+version 1,2
+debug
+module clib
+screenname "System Console"
+input gdbserve.O
+output gdbserve.nlm
+start _Prelude
+exit _Stop
+import
+ AllocateResourceTag
+ ConsolePrintf
+ GetCurrentScreen
+ GetNLMHandle
+ GetThreadID
+ KillMe
+ LoadModule
+ ReadByteAltDebugger
+ RegisterDebuggerRTag
+ ResumeThread
+ SuspendThread
+ UnRegisterDebugger
+ WriteByteAltDebugger
+ _GetCLibNLMLibHandle
+ _NWRegisterNLMLibraryUser
+ _SetupArgv
+ _StartNLM
+ _TerminateNLM
+ __GetScreenID
+ __get_errno_ptr
+ exit
+ fprintf
+ getcmd
+ memcmp
+ memcpy
+ memset
+ sprintf
+ strcmp
+ strcpy
+ strlen
+ strnicmp
+ strtol
diff --git a/contrib/gdb/gdb/nlm/i386.c b/contrib/gdb/gdb/nlm/i386.c
new file mode 100644
index 0000000..560198e
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/i386.c
@@ -0,0 +1,108 @@
+#include <dfs.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <conio.h>
+#include <advanced.h>
+#include <debugapi.h>
+#include <process.h>
+#include <errno.h>
+#include "i386.h"
+
+extern char *mem2hex (void *mem, char *buf, int count, int may_fault);
+extern char *hex2mem (char *buf, void *mem, int count, int may_fault);
+extern int computeSignal (int exceptionVector);
+
+void
+flush_i_cache()
+{
+}
+
+/* Get the registers out of the frame information. */
+
+void
+frame_to_registers (frame, regs)
+ struct StackFrame *frame;
+ char *regs;
+{
+ /* Copy EAX -> EDI */
+ mem2hex (&frame->ExceptionEAX, &regs[0 * 4 * 2], 4 * 8, 0);
+
+ /* Copy EIP & PS */
+ mem2hex (&frame->ExceptionPC, &regs[8 * 4 * 2], 4 * 2, 0);
+
+ /* Copy CS, SS, DS */
+ mem2hex (&frame->ExceptionCS, &regs[10 * 4 * 2], 4 * 3, 0);
+
+ /* Copy ES */
+ mem2hex (&frame->ExceptionES, &regs[13 * 4 * 2], 4 * 1, 0);
+
+ /* Copy FS & GS */
+ mem2hex (&frame->ExceptionFS, &regs[14 * 4 * 2], 4 * 2, 0);
+}
+
+/* Put the registers back into the frame information. */
+
+void
+registers_to_frame (regs, frame)
+ char *regs;
+ struct StackFrame *frame;
+{
+ /* Copy EAX -> EDI */
+ hex2mem (&regs[0 * 4 * 2], &frame->ExceptionEAX, 4 * 8, 0);
+
+ /* Copy EIP & PS */
+ hex2mem (&regs[8 * 4 * 2], &frame->ExceptionPC, 4 * 2, 0);
+
+ /* Copy CS, SS, DS */
+ hex2mem (&regs[10 * 4 * 2], &frame->ExceptionCS, 4 * 3, 0);
+
+ /* Copy ES */
+ hex2mem (&regs[13 * 4 * 2], &frame->ExceptionES, 4 * 1, 0);
+
+ /* Copy FS & GS */
+ hex2mem (&regs[14 * 4 * 2], &frame->ExceptionFS, 4 * 2, 0);
+}
+
+void
+set_step_traps (frame)
+ struct StackFrame *frame;
+{
+ frame->ExceptionSystemFlags |= 0x100;
+}
+
+void
+clear_step_traps (frame)
+ struct StackFrame *frame;
+{
+ frame->ExceptionSystemFlags &= ~0x100;
+}
+
+void
+do_status (ptr, frame)
+ char *ptr;
+ struct StackFrame *frame;
+{
+ int sigval;
+
+ sigval = computeSignal (frame->ExceptionNumber);
+
+ sprintf (ptr, "T%02x", sigval);
+ ptr += 3;
+
+ sprintf (ptr, "%02x:", PC_REGNUM);
+ ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", SP_REGNUM);
+ ptr = mem2hex (&frame->ExceptionESP, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", FP_REGNUM);
+ ptr = mem2hex (&frame->ExceptionEBP, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ *ptr = '\000';
+}
diff --git a/contrib/gdb/gdb/nlm/i386.h b/contrib/gdb/gdb/nlm/i386.h
new file mode 100644
index 0000000..155702b
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/i386.h
@@ -0,0 +1,13 @@
+/* Register values. All of these values *MUST* agree with tm.h */
+#define SP_REGNUM 4 /* Contains address of top of stack */
+#define PC_REGNUM 8 /* Contains program counter */
+#define FP_REGNUM 5 /* Virtual frame pointer */
+#define NUM_REGS 16 /* Number of machine registers */
+#define REGISTER_BYTES (NUM_REGS * 4) /* Total size of registers array */
+
+#define ExceptionPC ExceptionEIP
+#define DECR_PC_AFTER_BREAK 1 /* int 3 leaves PC pointing after insn */
+#define BREAKPOINT {0xcc}
+#define BREAKPOINT_SIZE (sizeof breakpoint_insn)
+
+#define StackFrame T_TSS_StackFrame
diff --git a/contrib/gdb/gdb/nlm/ppc.c b/contrib/gdb/gdb/nlm/ppc.c
new file mode 100644
index 0000000..e68397b
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/ppc.c
@@ -0,0 +1,257 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+
+#include <nwtypes.h>
+#include <nwdfs.h>
+#include <nwconio.h>
+#include <nwadv.h>
+#include <nwdbgapi.h>
+#include <nwthread.h>
+#include "ppc.h"
+
+extern char *mem2hex (void *mem, char *buf, int count, int may_fault);
+extern char *hex2mem (char *buf, void *mem, int count, int may_fault);
+extern int computeSignal (int exceptionVector);
+
+void
+flush_i_cache (void)
+{
+}
+
+/* Get the registers out of the frame information. */
+
+void
+frame_to_registers (frame, regs)
+ struct StackFrame *frame;
+ char *regs;
+{
+ mem2hex (&frame->ExceptionState.CsavedRegs, &regs[GP0_REGNUM * 4 * 2], 4 * 32, 0);
+
+ mem2hex (&frame->ExceptionState.CSavedFPRegs, &regs[FP0_REGNUM * 4 * 2], 4 * 32, 0);
+
+ mem2hex (&frame->ExceptionPC, &regs[PC_REGNUM * 4 * 2], 4 * 1, 0);
+
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, &regs[CR_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, &regs[LR_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, &regs[CTR_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, &regs[XER_REGNUM * 4 * 2], 4 * 1, 0);
+ mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, &regs[MQ_REGNUM * 4 * 2], 4 * 1, 0);
+}
+
+/* Put the registers back into the frame information. */
+
+void
+registers_to_frame (regs, frame)
+ char *regs;
+ struct StackFrame *frame;
+{
+ hex2mem (&regs[GP0_REGNUM * 4 * 2], &frame->ExceptionState.CsavedRegs, 4 * 32, 0);
+
+ hex2mem (&regs[FP0_REGNUM * 4 * 2], &frame->ExceptionState.CSavedFPRegs, 4 * 32, 0);
+
+ hex2mem (&regs[PC_REGNUM * 4 * 2], &frame->ExceptionPC, 4 * 1, 0);
+
+ hex2mem (&regs[CR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, 4 * 1, 0);
+ hex2mem (&regs[LR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, 4 * 1, 0);
+ hex2mem (&regs[CTR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, 4 * 1, 0);
+ hex2mem (&regs[XER_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, 4 * 1, 0);
+ hex2mem (&regs[MQ_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, 4 * 1, 0);
+}
+
+
+extern volatile int mem_err;
+
+#ifdef ALTERNATE_MEM_FUNCS
+extern int ReadByteAltDebugger (char* addr, char *theByte);
+extern int WriteByteAltDebugger (char* addr, char theByte);
+int
+get_char (addr)
+ char *addr;
+{
+ char c;
+
+ if (!ReadByteAltDebugger (addr, &c))
+ mem_err = 1;
+
+ return c;
+}
+
+void
+set_char (addr, val)
+ char *addr;
+ int val;
+{
+ if (!WriteByteAltDebugger (addr, val))
+ mem_err = 1;
+}
+#endif
+
+int
+mem_write (dst, src, len)
+ char *dst, *src;
+ int len;
+{
+ while (len-- && !mem_err)
+ set_char (dst++, *src++);
+
+ return mem_err;
+}
+
+union inst
+{
+ LONG l;
+
+ struct
+ {
+ union
+ {
+ struct /* Unconditional branch */
+ {
+ unsigned opcode : 6; /* 18 */
+ signed li : 24;
+ unsigned aa : 1;
+ unsigned lk : 1;
+ } b;
+ struct /* Conditional branch */
+ {
+ unsigned opcode : 6; /* 16 */
+ unsigned bo : 5;
+ unsigned bi : 5;
+ signed bd : 14;
+ unsigned aa : 1;
+ unsigned lk : 1;
+ } bc;
+ struct /* Conditional branch to ctr or lr reg */
+ {
+ unsigned opcode : 6; /* 19 */
+ unsigned bo : 5;
+ unsigned bi : 5;
+ unsigned type : 15; /* 528 = ctr, 16 = lr */
+ unsigned lk : 1;
+ } bclr;
+ } variant;
+ } inst;
+};
+
+static LONG saved_inst;
+static LONG *saved_inst_pc = 0;
+static LONG saved_target_inst;
+static LONG *saved_target_inst_pc = 0;
+
+void
+set_step_traps (frame)
+ struct StackFrame *frame;
+{
+ union inst inst;
+ LONG *target;
+ int opcode;
+ int ra, rb;
+ LONG *pc = (LONG *)frame->ExceptionPC;
+
+ inst.l = *pc++;
+
+ opcode = inst.inst.variant.b.opcode;
+
+ target = pc;
+
+ switch (opcode)
+ {
+ case 18: /* Unconditional branch */
+
+ if (inst.inst.variant.b.aa) /* Absolute? */
+ target = 0;
+ target += inst.inst.variant.b.li;
+
+ break;
+ case 16: /* Conditional branch */
+
+ if (!inst.inst.variant.bc.aa) /* Absolute? */
+ target = 0;
+ target += inst.inst.variant.bc.bd;
+
+ break;
+ case 19: /* Cond. branch via ctr or lr reg */
+ switch (inst.inst.variant.bclr.type)
+ {
+ case 528: /* ctr */
+ target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR;
+ break;
+ case 16: /* lr */
+ target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR;
+ break;
+ }
+ break;
+ }
+
+ saved_inst = *pc;
+ mem_write (pc, breakpoint_insn, BREAKPOINT_SIZE);
+ saved_inst_pc = pc;
+
+ if (target != pc)
+ {
+ saved_target_inst = *target;
+ mem_write (target, breakpoint_insn, BREAKPOINT_SIZE);
+ saved_target_inst_pc = target;
+ }
+}
+
+/* Remove step breakpoints. Returns non-zero if pc was at a step breakpoint,
+ zero otherwise. This routine works even if there were no step breakpoints
+ set. */
+
+int
+clear_step_traps (frame)
+ struct StackFrame *frame;
+{
+ int retcode;
+ LONG *pc = (LONG *)frame->ExceptionPC;
+
+ if (saved_inst_pc == pc || saved_target_inst_pc == pc)
+ retcode = 1;
+ else
+ retcode = 0;
+
+ if (saved_inst_pc)
+ {
+ mem_write (saved_inst_pc, saved_inst, BREAKPOINT_SIZE);
+ saved_inst_pc = 0;
+ }
+
+ if (saved_target_inst_pc)
+ {
+ mem_write (saved_target_inst_pc, saved_target_inst, BREAKPOINT_SIZE);
+ saved_target_inst_pc = 0;
+ }
+
+ return retcode;
+}
+
+void
+do_status (ptr, frame)
+ char *ptr;
+ struct StackFrame *frame;
+{
+ int sigval;
+
+ sigval = computeSignal (frame->ExceptionNumber);
+
+ sprintf (ptr, "T%02x", sigval);
+ ptr += 3;
+
+ sprintf (ptr, "%02x:", PC_REGNUM);
+ ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", SP_REGNUM);
+ ptr = mem2hex (&frame->ExceptionState.CsavedRegs[SP_REGNUM], ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ sprintf (ptr, "%02x:", LR_REGNUM);
+ ptr = mem2hex (&frame->ExceptionState.CsavedRegs[LR_REGNUM], ptr + 3, 4, 0);
+ *ptr++ = ';';
+
+ *ptr = '\000';
+}
diff --git a/contrib/gdb/gdb/nlm/ppc.h b/contrib/gdb/gdb/nlm/ppc.h
new file mode 100644
index 0000000..84cee6b
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/ppc.h
@@ -0,0 +1,165 @@
+typedef long Long;
+
+/* The following enum is used to access the special registers in
+ the saved machine state. */
+
+typedef enum
+{
+ kDc_SavedPC = 0, /* really SRR0 */
+ kDc_SavedMSR = 1, /* really SRR1 */
+ kDc_SavedCR = 2,
+ kDc_SavedLR = 3,
+ kDc_SavedDSISR = 4,
+ kDc_SavedDAR = 5,
+ kDc_SavedXER = 6,
+ kDc_SavedCTR = 7,
+ kDc_SavedSDR1 = 8,
+ kDc_SavedRTCU = 9,
+ kDc_SavedRTCL = 10,
+ kDc_SavedDEC = 11,
+ kDc_SavedSR00 = 12, /* The Segement Registers are consecutive */
+ kDc_SavedSR01 = 13, /* kDc_SavedSR00 + n is supported */
+ kDc_SavedSR02 = 14,
+ kDc_SavedSR03 = 15,
+ kDc_SavedSR04 = 16,
+ kDc_SavedSR05 = 17,
+ kDc_SavedSR06 = 18,
+ kDc_SavedSR07 = 19,
+ kDc_SavedSR08 = 20,
+ kDc_SavedSR09 = 21,
+ kDc_SavedSR10 = 22,
+ kDc_SavedSR11 = 23,
+ kDc_SavedSR12 = 24,
+ kDc_SavedSR13 = 25,
+ kDc_SavedSR14 = 26,
+ kDc_SavedSR15 = 27,
+ kDc_SavedFPSCR = 29,
+ kDc_SavedMQ = 30,
+ kDc_SavedBAT0U = 31,
+ kDc_SavedBAT0L = 32,
+ kDc_SavedBAT1U = 33,
+ kDc_SavedBAT1L = 34,
+ kDc_SavedBAT2U = 35,
+ kDc_SavedBAT2L = 36,
+ kDc_SavedBAT3U = 37,
+ kDc_SavedBAT3L = 38,
+
+ kNumberSpecialRegisters = 39
+} Dc_SavedRegisterName;
+
+/* Access to floating points is not very easy. This allows the number to be
+ accessed both as a floating number and as a pair of Longs. */
+
+typedef union
+{
+ double asfloat; /* access the variable as a floating number */
+ struct
+ {
+ Long high;
+ Long low;
+ }
+ asLONG; /* access the variable as two Longs */
+} FloatingPoints;
+
+/* The following is the standard record for Saving a machine state */
+
+struct SavedMachineState
+{
+ FloatingPoints CSavedFPRegs[32]; /* The floating point registers [0->31] */
+ /* ***32bit assumption*** */
+ Long CsavedRegs[32]; /* space to save the General Registers */
+ /* These are saved 0->31 */
+ Long CexReason;
+ Long SavedDomainID;
+ union
+ { /* must be 8-byte aligned, so doubleFPSCR is 8-byte aligned */
+ struct
+ {
+ Long CsavedSRR0; /* Index 0 - The saved PC */
+ Long CsavedSRR1; /* 1 saved MSR */
+ Long CsavedCR; /* 2 */
+ Long CsavedLR; /* 3 */
+ Long CsavedDSISR; /* 4 */
+ Long CsavedDAR; /* 5 */
+
+ Long CsavedXER; /* 6 */
+ Long CsavedCTR; /* 7 */
+ Long CsavedSDR1; /* 8 */
+ Long CsavedRTCU; /* 9 */
+ Long CsavedRTCL; /* 10 */
+ Long CsavedDEC; /* 11 */
+ Long CsavedSR0; /* 12 */
+ Long CsavedSR1; /* 13 */
+ Long CsavedSR2; /* 14 */
+ Long CsavedSR3; /* 15 */
+ Long CsavedSR4; /* 16 */
+ Long CsavedSR5; /* 17 */
+ Long CsavedSR6; /* 18 */
+ Long CsavedSR7; /* 19 */
+ Long CsavedSR8; /* 20 */
+ Long CsavedSR9; /* 21 */
+ Long CsavedSR10; /* 22 */
+ Long CsavedSR11; /* 23 */
+ Long CsavedSR12; /* 24 */
+ Long CsavedSR13; /* 25 */
+ Long CsavedSR14; /* 26 */
+ Long CsavedSR15; /* 27 */
+ /* CdoubleFPSCR must be double word aligned */
+ Long CdoubleFPSCR; /* 28 this is the upper part of the store and has
+ no meaning */
+ Long CsavedFPSCR; /* 29 */
+ Long CsavedMQ; /* 30 */
+ Long CsavedBAT0U; /* 31 */
+ Long CsavedBAT0L; /* 32 */
+ Long CsavedBAT1U; /* 33 */
+ Long CsavedBAT1L; /* 34 */
+ Long CsavedBAT2U; /* 35 */
+ Long CsavedBAT2L; /* 36 */
+ Long CsavedBAT3U; /* 37 */
+ Long CsavedBAT3L; /* 38 */
+ }
+ SpecialRegistersEnumerated;
+
+ Long SpecialRegistersIndexed[kNumberSpecialRegisters];
+ } u;
+
+ Long Padding[3]; /* Needed for quad-word alignment */
+};
+
+struct StackFrame
+{
+ LONG *ExceptionDomainID;
+ /*ProcessorStructure*/ int *ExceptionProcessorID;
+ BYTE *ExceptionDescription;
+ LONG ExceptionFlags;
+ LONG ExceptionErrorCode;
+ LONG ExceptionNumber;
+ struct SavedMachineState ExceptionState;
+};
+
+/* Register values. All of these values *MUST* agree with tm.h */
+#define GP0_REGNUM 0 /* GPR register 0 */
+#define SP_REGNUM 1 /* Contains address of top of stack */
+#define FP0_REGNUM 32 /* FPR (Floating point) register 0 */
+#define PC_REGNUM 64 /* Contains program counter */
+#define PS_REGNUM 65 /* Processor (or machine) status (%msr) */
+#define CR_REGNUM 66 /* Condition register */
+#define LR_REGNUM 67 /* Link register */
+#define CTR_REGNUM 68 /* Count register */
+#define XER_REGNUM 69 /* Fixed point exception registers */
+#define MQ_REGNUM 70 /* Multiply/quotient register */
+#define NUM_REGS 71 /* Number of machine registers */
+#define REGISTER_BYTES (420) /* Total size of registers array */
+
+#define ExceptionPC ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR0
+#define DECR_PC_AFTER_BREAK 0 /* PPCs get this right! */
+#define BREAKPOINT {0x7d, 0x82, 0x10, 0x08}
+extern unsigned char breakpoint_insn[];
+#define BREAKPOINT_SIZE 4
+
+#if 0
+#define ALTERNATE_MEM_FUNCS /* We need our own get_char/set_char */
+#endif
+
+extern int get_char (char *addr);
+extern void set_char (char *addr, int val);
diff --git a/contrib/gdb/gdb/nlm/prelude.c b/contrib/gdb/gdb/nlm/prelude.c
new file mode 100644
index 0000000..37e12c8
--- /dev/null
+++ b/contrib/gdb/gdb/nlm/prelude.c
@@ -0,0 +1,67 @@
+/*===========================================================================
+= Novell Standard C Library for NetWare Loadable Modules
+=
+= Unpublished Copyright (C) 1993 by Novell, Inc. All rights reserved.
+=
+= No part of this file may be duplicated, revised, translated, localized or
+= modified in any manner or compiled, linked or uploaded or downloaded to or
+= from any computer system without the prior written consent of Novell, Inc.
+==============================================================================
+= The object produced by compiling this file is for use by the client of this
+= library and is not linked in; Prelude.Obj is therefore one of the files to
+= be distributed with CLib.NLM and its headers.
+==============================================================================
+*/
+
+#include <stddef.h>
+#if defined(__netware__) && defined(__i386__)
+#define TERMINATE_BY_UNLOAD 5
+#else
+#include <nwpre.h>
+#endif
+/*#include "libhooks.h"*/
+
+extern int main (int, char **);
+
+static int NLMID;
+
+
+void _Stop( void )
+{
+ _TerminateNLM(NLMID, NULL, TERMINATE_BY_UNLOAD);
+}
+
+int _cstart_( void )
+{
+ return _SetupArgv(main);
+}
+
+int _Prelude
+(
+ int NLMHandle,
+ int initErrorScreenID,
+ char *commandLine,
+ char *loadDirectoryPath,
+ int uninitializedDataLength,
+ int NLMFileHandle,
+ int (*readRoutineP)(),
+ int customDataOffset,
+ int customDataSize
+)
+{
+ int rc;
+
+ rc = _StartNLM(NLMHandle,
+ initErrorScreenID,
+ commandLine,
+ loadDirectoryPath,
+ uninitializedDataLength,
+ NLMFileHandle,
+ readRoutineP,
+ customDataOffset,
+ customDataSize,
+ &NLMID,
+ _cstart_);
+
+ return rc;
+}
diff --git a/contrib/gdb/gdb/nlmread.c b/contrib/gdb/gdb/nlmread.c
new file mode 100644
index 0000000..b61dc97
--- /dev/null
+++ b/contrib/gdb/gdb/nlmread.c
@@ -0,0 +1,308 @@
+/* Read NLM (NetWare Loadable Module) format executable files for GDB.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support (fnf@cygnus.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#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 *));
+
+static void
+nlm_symfile_init PARAMS ((struct objfile *));
+
+static void
+nlm_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+nlm_symfile_finish PARAMS ((struct objfile *));
+
+static void
+nlm_symtab_read PARAMS ((bfd *, CORE_ADDR, struct objfile *));
+
+static struct section_offsets *
+nlm_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
+ struct objfile *));
+
+
+/* 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).
+
+ We reinitialize buildsym, since gdb will be able to read stabs from an NLM
+ file at some point in the near future. */
+
+static void
+nlm_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+
+/* NLM specific initialization routine for reading symbols.
+
+ It is passed a pointer to a struct sym_fns which contains, among other
+ things, the BFD for the file whose symbols are being read, and a slot for
+ a pointer to "private data" which we can fill with goodies.
+
+ For now at least, we have nothing in particular to do, so this function is
+ just a stub. */
+
+static void
+nlm_symfile_init (ignore)
+ struct objfile *ignore;
+{
+}
+
+static void
+record_minimal_symbol (name, address, ms_type, objfile)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ struct objfile *objfile;
+{
+ name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
+ prim_record_minimal_symbol (name, address, ms_type, objfile);
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ nlm_symtab_read -- read the symbol table of an NLM file
+
+SYNOPSIS
+
+ void nlm_symtab_read (bfd *abfd, CORE_ADDR addr,
+ struct objfile *objfile)
+
+DESCRIPTION
+
+ Given an open bfd, a base address to relocate symbols to, and a
+ flag that specifies whether or not this bfd is for an executable
+ or not (may be shared library for example), add all the global
+ function and data symbols to the minimal symbol table.
+*/
+
+static void
+nlm_symtab_read (abfd, addr, objfile)
+ bfd *abfd;
+ CORE_ADDR addr;
+ struct objfile *objfile;
+{
+ long storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ long number_of_symbols;
+ long i;
+ struct cleanup *back_to;
+ CORE_ADDR symaddr;
+ enum minimal_symbol_type ms_type;
+
+ 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*/ 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;
+
+ /* 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 -> flags & SEC_CODE)
+ ms_type = mst_text;
+ else if (sym -> section -> flags & SEC_DATA)
+ ms_type = mst_data;
+ else
+ ms_type = mst_unknown;
+
+ record_minimal_symbol ((char *) sym -> name, symaddr, ms_type,
+ objfile);
+ }
+ }
+ do_cleanups (back_to);
+ }
+}
+
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to nlm_symfile_init, which
+ currently does nothing.
+
+ SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
+ in each section. We simplify it down to a single offset for all
+ symbols. FIXME.
+
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file).
+
+ This function 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.
+
+ Note that NLM files have two sets of information that is potentially
+ useful for building gdb's minimal symbol table. The first is a list
+ of the publically exported symbols, and is currently used to build
+ bfd's canonical symbol table. The second is an optional native debugging
+ format which contains additional symbols (and possibly duplicates of
+ the publically exported symbols). The optional native debugging format
+ is not currently used. */
+
+static void
+nlm_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int 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);
+
+ /* FIXME, should take a section_offsets param, not just an offset. */
+
+ offset = ANOFFSET (section_offsets, 0);
+
+ /* Process the NLM export records, which become the bfd's canonical symbol
+ table. */
+
+ 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. */
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ 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. */
+
+static void
+nlm_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_private != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_private);
+ }
+}
+
+/* NLM specific parsing routine for section offsets.
+ FIXME: This may or may not be necessary. All the symbol readers seem
+ to have similar code. See if it can be generalized and moved elsewhere. */
+
+static
+struct section_offsets *
+nlm_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ {
+ ANOFFSET (section_offsets, i) = addr;
+ }
+
+ return (section_offsets);
+}
+
+
+/* Register that we are able to handle NLM file format. */
+
+static struct sym_fns nlm_sym_fns =
+{
+ 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 */
+ nlm_symfile_finish, /* sym_finish: finished with file, cleanup */
+ nlm_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_nlmread ()
+{
+ add_symtab_fns (&nlm_sym_fns);
+}
diff --git a/contrib/gdb/gdb/notify.defs b/contrib/gdb/gdb/notify.defs
new file mode 100644
index 0000000..2014be5
--- /dev/null
+++ b/contrib/gdb/gdb/notify.defs
@@ -0,0 +1 @@
+#include <mach/notify.defs>
diff --git a/contrib/gdb/gdb/ns32k-tdep.c b/contrib/gdb/gdb/ns32k-tdep.c
new file mode 100644
index 0000000..58a0860
--- /dev/null
+++ b/contrib/gdb/gdb/ns32k-tdep.c
@@ -0,0 +1,27 @@
+/* Print NS 32000 instructions for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1991, 1992, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+void
+_initialize_ns32k_tdep ()
+{
+ tm_print_insn = print_insn_ns32k;
+}
diff --git a/contrib/gdb/gdb/ns32km3-nat.c b/contrib/gdb/gdb/ns32km3-nat.c
new file mode 100644
index 0000000..89696ba
--- /dev/null
+++ b/contrib/gdb/gdb/ns32km3-nat.c
@@ -0,0 +1,181 @@
+/* Low level interface to ns532 running mach 3.0.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+
+#include <stdio.h>
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach/exception.h>
+#include <mach_error.h>
+
+#define private static
+
+
+/* Find offsets to thread states at compile time.
+ * If your compiler does not grok this, calculate offsets
+ * offsets yourself and use them (or get a compatible compiler :-)
+ */
+
+#define REG_N_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->ts.reg)
+#define REG_F_OFFSET(reg) (int)(&((struct ns532_combined_state *)0)->fs.reg)
+
+/* at reg_offset[i] is the offset to the ns532_combined_state
+ * location where the gdb registers[i] is stored.
+ */
+
+static int reg_offset[] =
+{
+ REG_N_OFFSET(r0), REG_N_OFFSET(r1), REG_N_OFFSET(r2), REG_N_OFFSET(r3),
+ REG_N_OFFSET(r4), REG_N_OFFSET(r5), REG_N_OFFSET(r6), REG_N_OFFSET(r7),
+ REG_F_OFFSET(l0a), REG_F_OFFSET(l1a),REG_F_OFFSET(l2a),REG_F_OFFSET(l3a),
+ REG_F_OFFSET(l4a), REG_F_OFFSET(l5a),REG_F_OFFSET(l6a),REG_F_OFFSET(l7a),
+ REG_N_OFFSET(sp), REG_N_OFFSET(fp), REG_N_OFFSET(pc), REG_N_OFFSET(psr),
+ REG_F_OFFSET(fsr),
+ REG_F_OFFSET(l0a), REG_F_OFFSET(l2a),REG_F_OFFSET(l4a),REG_F_OFFSET(l6a)
+ /* @@@ 532 has more double length floating point regs, not accessed currently */
+};
+
+/* Fetch COUNT contiguous registers from thread STATE starting from REGNUM
+ * Caller knows that the regs handled in one transaction are of same size.
+ */
+#define FETCH_REGS(state, regnum, count) \
+ memcpy (&registers[REGISTER_BYTE (regnum)], \
+ (char *)state+reg_offset[ regnum ], \
+ count*REGISTER_SIZE)
+
+/* Store COUNT contiguous registers to thread STATE starting from REGNUM */
+#define STORE_REGS(state, regnum, count) \
+ memcpy ((char *)state+reg_offset[ regnum ], \
+ &registers[REGISTER_BYTE (regnum)], \
+ count*REGISTER_SIZE)
+
+/*
+ * Fetch inferiors registers for gdb.
+ * REGNO specifies which (as gdb views it) register, -1 for all.
+ */
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = NS532_COMBINED_STATE_COUNT;
+ int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("fetch inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ ret = thread_get_state (current_thread,
+ NS532_COMBINED_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ message ("fetch_inferior_registers: %s ",
+ mach_error_string (ret));
+#if 0
+ /* It may be more effective to store validate all of them,
+ * since we fetched them all anyway
+ */
+ else if (regno != -1)
+ supply_register (regno, (char *)state+reg_offset[regno]);
+#endif
+ else
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ supply_register (index, (char *)state+reg_offset[index]);
+ }
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
+
+/* Store our register values back into the inferior.
+ * If REGNO is -1, do this for all registers.
+ * Otherwise, REGNO specifies which register
+ *
+ * On mach3 all registers are always saved in one call.
+ */
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ kern_return_t ret;
+ thread_state_data_t state;
+ unsigned int stateCnt = NS532_COMBINED_STATE_COUNT;
+ register int index;
+
+ if (! MACH_PORT_VALID (current_thread))
+ error ("store inferior registers: Invalid thread");
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 1);
+
+ /* Fetch the state of the current thread */
+ ret = thread_get_state (current_thread,
+ NS532_COMBINED_STATE,
+ state,
+ &stateCnt);
+
+ if (ret != KERN_SUCCESS)
+ {
+ message ("store_inferior_registers (get): %s",
+ mach_error_string (ret));
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+ return;
+ }
+
+ /* move gdb's registers to thread's state
+ *
+ * Since we save all registers anyway, save the ones
+ * that gdb thinks are valid (e.g. ignore the regno
+ * parameter)
+ */
+#if 0
+ if (regno != -1)
+ STORE_REGS (state, regno, 1);
+ else
+#endif
+ {
+ for (index = 0; index < NUM_REGS; index++)
+ STORE_REGS (state, index, 1);
+ }
+
+ /* Write gdb's current view of register to the thread
+ */
+ ret = thread_set_state (current_thread,
+ NS532_COMBINED_STATE,
+ state,
+ NS532_COMBINED_STATE_COUNT);
+
+ if (ret != KERN_SUCCESS)
+ message ("store_inferior_registers (set): %s",
+ mach_error_string (ret));
+
+ if (must_suspend_thread)
+ setup_thread (current_thread, 0);
+}
diff --git a/contrib/gdb/gdb/objfiles.c b/contrib/gdb/gdb/objfiles.c
new file mode 100644
index 0000000..97b05dc
--- /dev/null
+++ b/contrib/gdb/gdb/objfiles.c
@@ -0,0 +1,911 @@
+/* GDB routines for manipulating objfiles.
+ Copyright 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file contains support routines for creating, manipulating, and
+ destroying objfile structures. */
+
+#include "defs.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "target.h"
+
+#include <sys/types.h>
+#include "gdb_stat.h"
+#include <fcntl.h>
+#include "obstack.h"
+#include "gdb_string.h"
+
+/* Prototypes for local functions */
+
+#if !defined(NO_MMALLOC) && defined(HAVE_MMAP)
+
+static int
+open_existing_mapped_file PARAMS ((char *, long, int));
+
+static int
+open_mapped_file PARAMS ((char *filename, long mtime, int mapped));
+
+static CORE_ADDR
+map_to_address PARAMS ((void));
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+/* Externally visible variables that are owned by this module.
+ See declarations in objfile.h for more info. */
+
+struct objfile *object_files; /* Linked list of all objfiles */
+struct objfile *current_objfile; /* For symbol file being read in */
+struct objfile *symfile_objfile; /* Main symbol table loaded from */
+struct objfile *rt_common_objfile; /* For runtime common symbols */
+
+int mapped_symbol_files; /* Try to use mapped symbol files */
+
+/* Locate all mappable sections of a BFD file.
+ objfile_p_char is a char * to get it through
+ bfd_map_over_sections; we cast it back to its proper type. */
+
+static void
+add_to_objfile_sections (abfd, asect, objfile_p_char)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR objfile_p_char;
+{
+ struct objfile *objfile = (struct objfile *) objfile_p_char;
+ struct obj_section section;
+ flagword aflag;
+
+ aflag = bfd_get_section_flags (abfd, asect);
+ if (!(aflag & SEC_ALLOC))
+ return;
+ if (0 == bfd_section_size (abfd, asect))
+ return;
+ section.offset = 0;
+ section.objfile = objfile;
+ 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, (char *) &section, sizeof(section));
+ objfile->sections_end = (struct obj_section *) (((unsigned long) objfile->sections_end) + 1);
+}
+
+/* Builds a section table for OBJFILE.
+ Returns 0 if OK, 1 on error (in which case bfd_error contains the
+ error). */
+
+int
+build_objfile_section_table (objfile)
+ struct objfile *objfile;
+{
+ /* 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);
+ objfile->sections = (struct obj_section *)
+ obstack_finish (&objfile->psymbol_obstack);
+ objfile->sections_end = objfile->sections + (unsigned long) objfile->sections_end;
+ return(0);
+}
+
+/* Given a pointer to an initialized bfd (ABFD) and a flag that indicates
+ whether or not an objfile is to be mapped (MAPPED), allocate a new objfile
+ struct, fill it in as best we can, link it into the list of all known
+ objfiles, and return a pointer to the new objfile struct. */
+
+struct objfile *
+allocate_objfile (abfd, mapped)
+ bfd *abfd;
+ int mapped;
+{
+ struct objfile *objfile = NULL;
+ struct objfile *last_one = NULL;
+
+ 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. */
+
+ int fd;
+
+ 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_cache.cache, xmmalloc);
+ obstack_freefun (&objfile -> psymbol_cache.cache, mfree);
+ 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_cache.cache,
+ 0, 0, xmmalloc, mfree,
+ objfile -> md);
+ 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)
+ {
+ warning ("mapped symbol tables are not supported on this machine; missing or broken mmap().");
+
+ /* Turn off the global flag so we don't try to do mapped symbol tables
+ any more, which shuts up gdb unless the user specifically gives the
+ "mapped" keyword again. */
+
+ mapped_symbol_files = 0;
+ }
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+ /* If we don't support mapped symbol files, didn't ask for the file to be
+ mapped, or failed to open the mapped file for some reason, then revert
+ back to an unmapped objfile. */
+
+ if (objfile == NULL)
+ {
+ objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
+ memset (objfile, 0, sizeof (struct objfile));
+ objfile -> md = NULL;
+ obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0,
+ xmalloc, free);
+ 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);
+ }
+
+ /* Update the per-objfile information that comes from the bfd, ensuring
+ that any data that is reference is saved in the per-objfile data
+ region. */
+
+ objfile -> obfd = abfd;
+ if (objfile -> name != NULL)
+ {
+ mfree (objfile -> md, objfile -> name);
+ }
+ objfile -> name = mstrsave (objfile -> md, bfd_get_filename (abfd));
+ objfile -> mtime = bfd_get_mtime (abfd);
+
+ /* Build section table. */
+
+ if (build_objfile_section_table (objfile))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ objfile -> name, bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* Add this file onto the tail of the linked list of other such files. */
+
+ objfile -> next = NULL;
+ if (object_files == NULL)
+ object_files = objfile;
+ else
+ {
+ for (last_one = object_files;
+ last_one -> next;
+ last_one = last_one -> next);
+ last_one -> next = objfile;
+ }
+ return (objfile);
+}
+
+/* Put OBJFILE at the front of the list. */
+
+void
+objfile_to_front (objfile)
+ struct objfile *objfile;
+{
+ struct objfile **objp;
+ for (objp = &object_files; *objp != NULL; objp = &((*objp)->next))
+ {
+ if (*objp == objfile)
+ {
+ /* Unhook it from where it is. */
+ *objp = objfile->next;
+ /* Put it in the front. */
+ objfile->next = object_files;
+ object_files = objfile;
+ break;
+ }
+ }
+}
+
+/* Unlink OBJFILE from the list of known objfiles, if it is found in the
+ list.
+
+ It is not a bug, or error, to call this function if OBJFILE is not known
+ to be in the current list. This is done in the case of mapped objfiles,
+ for example, just to ensure that the mapped objfile doesn't appear twice
+ in the list. Since the list is threaded, linking in a mapped objfile
+ twice would create a circular list.
+
+ If OBJFILE turns out to be in the list, we zap it's NEXT pointer after
+ unlinking it, just to ensure that we have completely severed any linkages
+ between the OBJFILE and the list. */
+
+void
+unlink_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct objfile** objpp;
+
+ for (objpp = &object_files; *objpp != NULL; objpp = &((*objpp) -> next))
+ {
+ if (*objpp == objfile)
+ {
+ *objpp = (*objpp) -> next;
+ objfile -> next = NULL;
+ break;
+ }
+ }
+}
+
+
+/* Destroy an objfile and all the symtabs and psymtabs under it. Note
+ that as much as possible is allocated on the symbol_obstack and
+ psymbol_obstack, so that the memory can be efficiently freed.
+
+ Things which we do NOT free because they are not in malloc'd memory
+ or not in memory specific to the objfile include:
+
+ objfile -> sf
+
+ FIXME: If the objfile is using reusable symbol information (via mmalloc),
+ then we need to take into account the fact that more than one process
+ may be using the symbol information at the same time (when mmalloc is
+ extended to support cooperative locking). When more than one process
+ is using the mapped symbol info, we need to be more careful about when
+ we free objects in the reusable area. */
+
+void
+free_objfile (objfile)
+ struct objfile *objfile;
+{
+ /* 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
+ these routines is responsible for doing the correct thing, either
+ freeing things which are valid only during this particular gdb
+ execution, or leaving them to be reused during the next one. */
+
+ if (objfile -> sf != NULL)
+ {
+ (*objfile -> sf -> sym_finish) (objfile);
+ }
+
+ /* We always close the bfd. */
+
+ if (objfile -> obfd != NULL)
+ {
+ char *name = bfd_get_filename (objfile->obfd);
+ if (!bfd_close (objfile -> obfd))
+ warning ("cannot close \"%s\": %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ free (name);
+ }
+
+ /* Remove it from the chain of all objfiles. */
+
+ unlink_objfile (objfile);
+
+ /* If we are going to free the runtime common objfile, mark it
+ as unallocated. */
+
+ if (objfile == rt_common_objfile)
+ rt_common_objfile = NULL;
+
+ /* Before the symbol table code was redone to make it easier to
+ selectively load and remove information particular to a specific
+ linkage unit, gdb used to do these things whenever the monolithic
+ symbol table was blown away. How much still needs to be done
+ is unknown, but we play it safe for now and keep each action until
+ it is shown to be no longer needed. */
+
+#if defined (CLEAR_SOLIB)
+ CLEAR_SOLIB ();
+ /* CLEAR_SOLIB closes the bfd's for any shared libraries. But
+ the to_sections for a core file might refer to those bfd's. So
+ detach any core file. */
+ {
+ struct target_ops *t = find_core_target ();
+ if (t != NULL)
+ (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
+ non-reusable case, or detach from the mapped file for the reusable
+ case. Note that the mmalloc_detach or the mfree is the last thing
+ we can do with this objfile. */
+
+#if !defined(NO_MMALLOC) && defined(HAVE_MMAP)
+
+ if (objfile -> flags & OBJF_MAPPED)
+ {
+ /* 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;
+ close (mmfd);
+ }
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+ /* If we still have an objfile, then either we don't support reusable
+ objfiles or this one was not reusable. So free it normally. */
+
+ if (objfile != NULL)
+ {
+ if (objfile -> name != NULL)
+ {
+ mfree (objfile -> md, objfile -> name);
+ }
+ if (objfile->global_psymbols.list)
+ mfree (objfile->md, objfile->global_psymbols.list);
+ if (objfile->static_psymbols.list)
+ mfree (objfile->md, objfile->static_psymbols.list);
+ /* Free the obstacks for non-reusable objfiles */
+ obstack_free (&objfile -> psymbol_cache.cache, 0);
+ obstack_free (&objfile -> psymbol_obstack, 0);
+ obstack_free (&objfile -> symbol_obstack, 0);
+ obstack_free (&objfile -> type_obstack, 0);
+ mfree (objfile -> md, objfile);
+ objfile = NULL;
+ }
+}
+
+
+/* Free all the object files at once and clean up their users. */
+
+void
+free_all_objfiles ()
+{
+ struct objfile *objfile, *temp;
+
+ ALL_OBJFILES_SAFE (objfile, temp)
+ {
+ free_objfile (objfile);
+ }
+ clear_symtab_users ();
+}
+
+/* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS
+ entries in new_offsets. */
+void
+objfile_relocate (objfile, new_offsets)
+ struct objfile *objfile;
+ struct section_offsets *new_offsets;
+{
+ struct section_offsets *delta = (struct section_offsets *) alloca
+ (sizeof (struct section_offsets)
+ + objfile->num_sections * sizeof (delta->offsets));
+
+ {
+ int i;
+ int something_changed = 0;
+ for (i = 0; i < objfile->num_sections; ++i)
+ {
+ ANOFFSET (delta, i) =
+ ANOFFSET (new_offsets, i) - ANOFFSET (objfile->section_offsets, i);
+ if (ANOFFSET (delta, i) != 0)
+ something_changed = 1;
+ }
+ if (!something_changed)
+ return;
+ }
+
+ /* OK, get all the symtabs. */
+ {
+ struct symtab *s;
+
+ ALL_OBJFILE_SYMTABS (objfile, s)
+ {
+ struct linetable *l;
+ struct blockvector *bv;
+ int i;
+
+ /* First the line table. */
+ l = LINETABLE (s);
+ if (l)
+ {
+ for (i = 0; i < l->nitems; ++i)
+ l->item[i].pc += ANOFFSET (delta, s->block_line_section);
+ }
+
+ /* Don't relocate a shared blockvector more than once. */
+ if (!s->primary)
+ continue;
+
+ bv = BLOCKVECTOR (s);
+ for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); ++i)
+ {
+ struct block *b;
+ int j;
+
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ BLOCK_START (b) += ANOFFSET (delta, s->block_line_section);
+ BLOCK_END (b) += ANOFFSET (delta, s->block_line_section);
+
+ for (j = 0; j < BLOCK_NSYMS (b); ++j)
+ {
+ struct symbol *sym = BLOCK_SYM (b, j);
+ /* The RS6000 code from which this was taken skipped
+ any symbols in STRUCT_NAMESPACE or UNDEF_NAMESPACE.
+ But I'm leaving out that test, on the theory that
+ they can't possibly pass the tests below. */
+ if ((SYMBOL_CLASS (sym) == LOC_LABEL
+ || SYMBOL_CLASS (sym) == LOC_STATIC)
+ && SYMBOL_SECTION (sym) >= 0)
+ {
+ 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
+ }
+ }
+ }
+ }
+
+ {
+ struct partial_symtab *p;
+
+ ALL_OBJFILE_PSYMTABS (objfile, p)
+ {
+ p->textlow += ANOFFSET (delta, SECT_OFF_TEXT);
+ p->texthigh += ANOFFSET (delta, SECT_OFF_TEXT);
+ }
+ }
+
+ {
+ struct partial_symbol **psym;
+
+ for (psym = objfile->global_psymbols.list;
+ psym < objfile->global_psymbols.next;
+ psym++)
+ if (SYMBOL_SECTION (*psym) >= 0)
+ SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta, SYMBOL_SECTION (*psym));
+ for (psym = objfile->static_psymbols.list;
+ psym < objfile->static_psymbols.next;
+ psym++)
+ if (SYMBOL_SECTION (*psym) >= 0)
+ SYMBOL_VALUE_ADDRESS (*psym) += ANOFFSET (delta, SYMBOL_SECTION (*psym));
+ }
+
+ {
+ struct minimal_symbol *msym;
+ ALL_OBJFILE_MSYMBOLS (objfile, msym)
+ if (SYMBOL_SECTION (msym) >= 0)
+ SYMBOL_VALUE_ADDRESS (msym) += ANOFFSET (delta, SYMBOL_SECTION (msym));
+ }
+ /* Relocating different sections by different amounts may cause the symbols
+ to be out of order. */
+ msymbols_sort (objfile);
+
+ {
+ int i;
+ for (i = 0; i < objfile->num_sections; ++i)
+ ANOFFSET (objfile->section_offsets, i) = ANOFFSET (new_offsets, i);
+ }
+
+ {
+ struct obj_section *s;
+ bfd *abfd;
+
+ abfd = objfile->obfd;
+
+ for (s = objfile->sections;
+ s < 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
+ symbols available. This function returns zero if none are currently
+ available, nonzero otherwise. */
+
+int
+have_partial_symbols ()
+{
+ struct objfile *ofp;
+
+ ALL_OBJFILES (ofp)
+ {
+ if (ofp -> psymtabs != NULL)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Many places in gdb want to test just to see if we have any full
+ symbols available. This function returns zero if none are currently
+ available, nonzero otherwise. */
+
+int
+have_full_symbols ()
+{
+ struct objfile *ofp;
+
+ ALL_OBJFILES (ofp)
+ {
+ if (ofp -> symtabs != NULL)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Many places in gdb want to test just to see if we have any minimal
+ symbols available. This function returns zero if none are currently
+ available, nonzero otherwise. */
+
+int
+have_minimal_symbols ()
+{
+ struct objfile *ofp;
+
+ ALL_OBJFILES (ofp)
+ {
+ if (ofp -> msymbols != NULL)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#if !defined(NO_MMALLOC) && defined(HAVE_MMAP)
+
+/* Given the name of a mapped symbol file in SYMSFILENAME, and the timestamp
+ of the corresponding symbol file in MTIME, try to open an existing file
+ with the name SYMSFILENAME and verify it is more recent than the base
+ file by checking it's timestamp against MTIME.
+
+ If SYMSFILENAME does not exist (or can't be stat'd), simply returns -1.
+
+ If SYMSFILENAME does exist, but is out of date, we check to see if the
+ user has specified creation of a mapped file. If so, we don't issue
+ any warning message because we will be creating a new mapped file anyway,
+ overwriting the old one. If not, then we issue a warning message so that
+ the user will know why we aren't using this existing mapped symbol file.
+ In either case, we return -1.
+
+ If SYMSFILENAME does exist and is not out of date, but can't be opened for
+ some reason, then prints an appropriate system error message and returns -1.
+
+ Otherwise, returns the open file descriptor. */
+
+static int
+open_existing_mapped_file (symsfilename, mtime, mapped)
+ char *symsfilename;
+ long mtime;
+ int mapped;
+{
+ int fd = -1;
+ struct stat sbuf;
+
+ if (stat (symsfilename, &sbuf) == 0)
+ {
+ if (sbuf.st_mtime < mtime)
+ {
+ if (!mapped)
+ {
+ warning ("mapped symbol file `%s' is out of date, ignored it",
+ symsfilename);
+ }
+ }
+ else if ((fd = open (symsfilename, O_RDWR)) < 0)
+ {
+ if (error_pre_print)
+ {
+ printf_unfiltered (error_pre_print);
+ }
+ print_sys_errmsg (symsfilename, errno);
+ }
+ }
+ return (fd);
+}
+
+/* Look for a mapped symbol file that corresponds to FILENAME and is more
+ recent than MTIME. If MAPPED is nonzero, the user has asked that gdb
+ use a mapped symbol file for this file, so create a new one if one does
+ not currently exist.
+
+ If found, then return an open file descriptor for the file, otherwise
+ return -1.
+
+ This routine is responsible for implementing the policy that generates
+ the name of the mapped symbol file from the name of a file containing
+ symbols that gdb would like to read. Currently this policy is to append
+ ".syms" to the name of the file.
+
+ This routine is also responsible for implementing the policy that
+ determines where the mapped symbol file is found (the search path).
+ This policy is that when reading an existing mapped file, a file of
+ the correct name in the current directory takes precedence over a
+ file of the correct name in the same directory as the symbol file.
+ When creating a new mapped file, it is always created in the current
+ directory. This helps to minimize the chances of a user unknowingly
+ creating big mapped files in places like /bin and /usr/local/bin, and
+ allows a local copy to override a manually installed global copy (in
+ /bin for example). */
+
+static int
+open_mapped_file (filename, mtime, mapped)
+ char *filename;
+ long mtime;
+ int mapped;
+{
+ int fd;
+ char *symsfilename;
+
+ /* First try to open an existing file in the current directory, and
+ then try the directory where the symbol file is located. */
+
+ symsfilename = concat ("./", basename (filename), ".syms", (char *) NULL);
+ if ((fd = open_existing_mapped_file (symsfilename, mtime, mapped)) < 0)
+ {
+ free (symsfilename);
+ symsfilename = concat (filename, ".syms", (char *) NULL);
+ fd = open_existing_mapped_file (symsfilename, mtime, mapped);
+ }
+
+ /* If we don't have an open file by now, then either the file does not
+ already exist, or the base file has changed since it was created. In
+ either case, if the user has specified use of a mapped file, then
+ create a new mapped file, truncating any existing one. If we can't
+ create one, print a system error message saying why we can't.
+
+ By default the file is rw for everyone, with the user's umask taking
+ care of turning off the permissions the user wants off. */
+
+ if ((fd < 0) && mapped)
+ {
+ free (symsfilename);
+ symsfilename = concat ("./", basename (filename), ".syms",
+ (char *) NULL);
+ if ((fd = open (symsfilename, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
+ {
+ if (error_pre_print)
+ {
+ printf_unfiltered (error_pre_print);
+ }
+ print_sys_errmsg (symsfilename, errno);
+ }
+ }
+
+ free (symsfilename);
+ return (fd);
+}
+
+/* Return the base address at which we would like the next objfile's
+ mapped data to start.
+
+ For now, we use the kludge that the configuration specifies a base
+ address to which it is safe to map the first mmalloc heap, and an
+ increment to add to this address for each successive heap. There are
+ a lot of issues to deal with here to make this work reasonably, including:
+
+ Avoid memory collisions with existing mapped address spaces
+
+ Reclaim address spaces when their mmalloc heaps are unmapped
+
+ When mmalloc heaps are shared between processes they have to be
+ mapped at the same addresses in each
+
+ Once created, a mmalloc heap that is to be mapped back in must be
+ mapped at the original address. I.E. each objfile will expect to
+ be remapped at it's original address. This becomes a problem if
+ the desired address is already in use.
+
+ etc, etc, etc.
+
+ */
+
+
+static CORE_ADDR
+map_to_address ()
+{
+
+#if defined(MMAP_BASE_ADDRESS) && defined (MMAP_INCREMENT)
+
+ static CORE_ADDR next = MMAP_BASE_ADDRESS;
+ CORE_ADDR mapto = next;
+
+ next += MMAP_INCREMENT;
+ return (mapto);
+
+#else
+
+ warning ("need to recompile gdb with MMAP_BASE_ADDRESS and MMAP_INCREMENT defined");
+ return (0);
+
+#endif
+
+}
+
+#endif /* !defined(NO_MMALLOC) && defined(HAVE_MMAP) */
+
+/* Returns a section whose range includes PC or NULL if none found. */
+
+struct obj_section *
+find_pc_section(pc)
+ CORE_ADDR pc;
+{
+ struct obj_section *s;
+ struct objfile *objfile;
+
+ ALL_OBJFILES (objfile)
+ for (s = objfile->sections; s < objfile->sections_end; ++s)
+ if (s->addr <= pc
+ && pc < s->endaddr)
+ return(s);
+
+ 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/contrib/gdb/gdb/objfiles.h b/contrib/gdb/gdb/objfiles.h
new file mode 100644
index 0000000..b98b708
--- /dev/null
+++ b/contrib/gdb/gdb/objfiles.h
@@ -0,0 +1,502 @@
+/* Definitions for symbol file management in GDB.
+ Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (OBJFILES_H)
+#define OBJFILES_H
+
+/* 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 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
+ and is run by the kernel first when an exec is done of a user executable
+ that is dynamically linked. The dynamic linker within the shared C library
+ then maps in the various program segments in the user executable and jumps
+ to the user executable's recorded entry point, as if the call had been made
+ directly by the kernel.
+
+ The traditional gdb method of using this info is to use the recorded entry
+ point to set the variables entry_file_lowpc and entry_file_highpc from
+ the debugging information, where these values are the starting address
+ (inclusive) and ending address (exclusive) of the instruction space in the
+ 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.
+
+ 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
+ containing the process entry point, since it has no predecessor frame,
+ and the frame for the function containing the user code entry point
+ (the main() function), since all the predecessor frames are for the
+ process startup code. Since we have no guarantee that the linked
+ in startup modules have any debugging information that gdb can use,
+ we need to avoid following frame pointers back into frames that might
+ have been built in the startup code, as we might get hopelessly
+ confused. However, we almost always have debugging information
+ available for main().
+
+ These variables are used to save the range of PC values which are valid
+ within the main() function and within the function containing the process
+ entry point. If we always consider the frame for main() as the outermost
+ frame when debugging user code, and the frame for the process entry
+ point function as the outermost frame when debugging startup code, then
+ all we have to do is have FRAME_CHAIN_VALID return false whenever a
+ frame's current PC is within the range specified by these variables.
+ In essence, we set "ceilings" in the frame chain beyond which we will
+ not proceed when following the frame chain back up the stack.
+
+ A nice side effect is that we can still debug startup code without
+ running off the end of the frame chain, assuming that we have usable
+ debugging information in the startup modules, and if we choose to not
+ use the block at main, or can't find it for some reason, everything
+ still works as before. And if we have no startup code debugging
+ information but we do have usable information for main(), backtraces
+ from user code don't go wandering off into the startup code.
+
+ To use this method, define your FRAME_CHAIN_VALID macro like:
+
+ #define FRAME_CHAIN_VALID(chain, thisframe) \
+ (chain != 0 \
+ && !(inside_main_func ((thisframe)->pc)) \
+ && !(inside_entry_func ((thisframe)->pc)))
+
+ and add initializations of the four scope controlling variables inside
+ the object file / debugging information processing modules. */
+
+struct entry_info
+{
+
+ /* The value we should use for this objects entry point.
+ The illegal/unknown value needs to be something other than 0, ~0
+ for instance, which is much less likely than 0. */
+
+ 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. */
+
+ CORE_ADDR entry_func_lowpc;
+ CORE_ADDR entry_func_highpc;
+
+ /* Start (inclusive) and end (exclusive) of object file containing the
+ entry point. */
+
+ CORE_ADDR entry_file_lowpc;
+ CORE_ADDR entry_file_highpc;
+
+ /* Start (inclusive) and end (exclusive) of the user code main() function. */
+
+ 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.
+
+ It is strange that we have both this notion of "sections"
+ and the one used by section_offsets. Section as used
+ here, (currently at least) means a BFD section, and the sections
+ are set up from the BFD sections in allocate_objfile.
+
+ The sections in section_offsets have their meaning determined by
+ the symbol format, and they are set up by the sym_offsets function
+ for that symbol file format.
+
+ I'm not sure this could or should be changed, however. */
+
+struct obj_section {
+ CORE_ADDR addr; /* lowest address in section */
+ CORE_ADDR endaddr; /* 1+highest address in section */
+
+ /* This field is being used for nefarious purposes by syms_from_objfile.
+ It is said to be redundant with section_offsets; it's not really being
+ used that way, however, it's some sort of hack I don't understand
+ and am not going to try to eliminate (yet, anyway). FIXME.
+
+ It was documented as "offset between (end)addr and actual memory
+ addresses", but that's not true; addr & endaddr are actual memory
+ addresses. */
+ CORE_ADDR offset;
+
+ sec_ptr the_bfd_section; /* BFD section pointer */
+
+ /* Objfile this section is part of. */
+ struct objfile *objfile;
+};
+
+/* The "objstats" structure provides a place for gdb to record some
+ interesting information about its internal state at runtime, on a
+ per objfile basis, such as information about the number of symbols
+ read, size of string table (if any), etc. */
+
+#if MAINTENANCE_CMDS
+
+struct objstats {
+ int n_minsyms; /* Number of minimal symbols read */
+ int n_psyms; /* Number of partial symbols read */
+ int n_syms; /* Number of full symbols read */
+ int n_stabs; /* Number of ".stabs" read (if applicable) */
+ int n_types; /* Number of types */
+ int sz_strtab; /* Size of stringtable, (if applicable) */
+};
+
+#define OBJSTAT(objfile, expr) (objfile -> stats.expr)
+#define OBJSTATS struct objstats stats
+extern void print_objfile_statistics PARAMS ((void));
+extern void print_symbol_bcache_statistics PARAMS ((void));
+
+#else
+
+#define OBJSTAT(objfile, expr) /* Nothing */
+#define OBJSTATS /* Nothing */
+
+#endif /* MAINTENANCE_CMDS */
+
+/* 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
+{
+
+ /* All struct objfile's are chained together by their next pointers.
+ The global variable "object_files" points to the first link in this
+ chain.
+
+ FIXME: There is a problem here if the objfile is reusable, and if
+ multiple users are to be supported. The problem is that the objfile
+ list is linked through a member of the objfile struct itself, which
+ is only valid for one gdb process. The list implementation needs to
+ be changed to something like:
+
+ struct list {struct list *next; struct objfile *objfile};
+
+ where the list structure is completely maintained separately within
+ each gdb process. */
+
+ struct objfile *next;
+
+ /* The object file's name. Malloc'd; free it if you free this struct. */
+
+ char *name;
+
+ /* Some flag bits for this objfile. */
+
+ unsigned short flags;
+
+ /* Each objfile points to a linked list of symtabs derived from this file,
+ one symtab structure for each compilation unit (source file). Each link
+ in the symtab list contains a backpointer to this objfile. */
+
+ struct symtab *symtabs;
+
+ /* Each objfile points to a linked list of partial symtabs derived from
+ this file, one partial symtab structure for each compilation unit
+ (source file). */
+
+ struct partial_symtab *psymtabs;
+
+ /* List of freed partial symtabs, available for re-use */
+
+ struct partial_symtab *free_psymtabs;
+
+ /* The object file's BFD. Can be null if the objfile contains only
+ minimal symbols, e.g. the run time common symbols for SunOS4. */
+
+ bfd *obfd;
+
+ /* The modification timestamp of the object file, as of the last time
+ we read its symbols. */
+
+ long mtime;
+
+ /* Obstacks to hold objects that should be freed when we load a new symbol
+ table from this object file. */
+
+ struct obstack psymbol_obstack; /* Partial symbols */
+ struct obstack symbol_obstack; /* Full symbols */
+ struct obstack type_obstack; /* Types */
+
+ /* A byte cache where we can stash arbitrary "chunks" of bytes that
+ will not change. */
+
+ struct bcache psymbol_cache; /* Byte cache for partial syms */
+
+ /* Vectors of all partial symbols read in from file. The actual data
+ is stored in the psymbol_obstack. */
+
+ struct psymbol_allocation_list global_psymbols;
+ struct psymbol_allocation_list static_psymbols;
+
+ /* Each file contains a pointer to an array of minimal symbols for all
+ global symbols that are defined within the file. The array is terminated
+ by a "null symbol", one that has a NULL pointer for the name and a zero
+ value for the address. This makes it easy to walk through the array
+ when passed a pointer to somewhere in the middle of it. There is also
+ a count of the number of symbols, which does not include the terminating
+ null symbol. The array itself, as well as all the data that it points
+ to, should be allocated on the symbol_obstack for this file. */
+
+ struct minimal_symbol *msymbols;
+ int minimal_symbol_count;
+
+ /* For object file formats which don't specify fundamental types, gdb
+ can create such types. For now, it maintains a vector of pointers
+ to these internally created fundamental types on a per objfile basis,
+ however it really should ultimately keep them on a per-compilation-unit
+ basis, to account for linkage-units that consist of a number of
+ compilation units that may have different fundamental types, such as
+ linking C modules with ADA modules, or linking C modules that are
+ compiled with 32-bit ints with C modules that are compiled with 64-bit
+ ints (not inherently evil with a smarter linker). */
+
+ struct type **fundamental_types;
+
+ /* The mmalloc() malloc-descriptor for this objfile if we are using
+ the memory mapped malloc() package to manage storage for this objfile's
+ data. NULL if we are not. */
+
+ PTR md;
+
+ /* The file descriptor that was used to obtain the mmalloc descriptor
+ for this objfile. If we call mmalloc_detach with the malloc descriptor
+ we should then close this file descriptor. */
+
+ int mmfd;
+
+ /* Structure which keeps track of functions that manipulate objfile's
+ of the same type as this objfile. I.E. the function to read partial
+ symbols for example. Note that this structure is in statically
+ allocated memory, and is shared by all objfiles that use the
+ object module reader of this type. */
+
+ struct sym_fns *sf;
+
+ /* The per-objfile information about the entry point, the scope (file/func)
+ containing the entry point, and the scope of the user's main() func. */
+
+ struct entry_info ei;
+
+ /* Information about stabs. Will be filled in with a dbx_symfile_info
+ struct by those readers that need it. */
+
+ PTR sym_stab_info;
+
+ /* Hook for information for use by the symbol reader (currently used
+ for information shared by sym_init and sym_read). It is
+ typically a pointer to malloc'd memory. The symbol reader's finish
+ function is responsible for freeing the memory thusly allocated. */
+
+ PTR sym_private;
+
+ /* Hook for target-architecture-specific information. This must
+ point to memory allocated on one of the obstacks in this objfile,
+ so that it gets freed automatically when reading a new object
+ file. */
+
+ PTR obj_private;
+
+ /* Set of relocation offsets to apply to each section.
+ Currently on the psymbol_obstack (which makes no sense, but I'm
+ not sure it's harming anything).
+
+ These offsets indicate that all symbols (including partial and
+ minimal symbols) which have been read have been relocated by this
+ much. Symbols which are yet to be read need to be relocated by
+ it. */
+
+ struct section_offsets *section_offsets;
+ int num_sections;
+
+ /* set of section begin and end addresses used to map pc addresses
+ into sections. Currently on the psymbol_obstack (which makes no
+ sense, but I'm not sure it's harming anything). */
+
+ struct obj_section
+ *sections,
+ *sections_end;
+
+ /* two auxiliary fields, used to hold the fp of separate symbol files */
+ FILE *auxf1, *auxf2;
+
+ /* Place to stash various statistics about this objfile */
+ OBJSTATS;
+};
+
+/* 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 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
+ dumped to a gdb state file and subsequently reloaded at a later time. */
+
+#define OBJF_MAPPED (1 << 0) /* Objfile data is mmap'd */
+
+/* When using mapped/remapped predigested gdb symbol information, we need
+ a flag that indicates that we have previously done an initial symbol
+ table read from this particular objfile. We can't just look for the
+ absence of any of the three symbol tables (msymbols, psymtab, symtab)
+ because if the file has no symbols for example, none of these will
+ exist. */
+
+#define OBJF_SYMS (1 << 1) /* Have tried to read symbols */
+
+/* When an object file has its functions reordered (currently Irix-5.2
+ shared libraries exhibit this behaviour), we will need an expensive
+ algorithm to locate a partial symtab or symtab via an address.
+ To avoid this penalty for normal object files, we use this flag,
+ whose setting is determined upon symbol table read in. */
+
+#define OBJF_REORDERED (2 << 1) /* Functions are reordered */
+
+/* The object file that the main symbol table was loaded from (e.g. the
+ argument to the "symbol-file" or "file" command). */
+
+extern struct objfile *symfile_objfile;
+
+/* The object file that contains the runtime common minimal symbols
+ for SunOS4. Note that this objfile has no associated BFD. */
+
+extern struct objfile *rt_common_objfile;
+
+/* When we need to allocate a new type, we need to know which type_obstack
+ to allocate the type on, since there is one for each objfile. The places
+ where types are allocated are deeply buried in function call hierarchies
+ which know nothing about objfiles, so rather than trying to pass a
+ particular objfile down to them, we just do an end run around them and
+ set current_objfile to be whatever objfile we expect to be using at the
+ time types are being allocated. For instance, when we start reading
+ symbols for a particular objfile, we set current_objfile to point to that
+ objfile, and when we are done, we set it back to NULL, to ensure that we
+ never put a type someplace other than where we are expecting to put it.
+ FIXME: Maybe we should review the entire type handling system and
+ see if there is a better way to avoid this problem. */
+
+extern struct objfile *current_objfile;
+
+/* All known objfiles are kept in a linked list. This points to the
+ root of this list. */
+
+extern struct objfile *object_files;
+
+/* Declarations for functions defined in objfiles.c */
+
+extern struct objfile *
+allocate_objfile PARAMS ((bfd *, int));
+
+extern int
+build_objfile_section_table PARAMS ((struct objfile *));
+
+extern void objfile_to_front PARAMS ((struct objfile *));
+
+extern void
+unlink_objfile PARAMS ((struct objfile *));
+
+extern void
+free_objfile PARAMS ((struct objfile *));
+
+extern void
+free_all_objfiles PARAMS ((void));
+
+extern void
+objfile_relocate PARAMS ((struct objfile *, struct section_offsets *));
+
+extern int
+have_partial_symbols PARAMS ((void));
+
+extern int
+have_full_symbols PARAMS ((void));
+
+/* Functions for dealing with the minimal symbol table, really a misc
+ address<->symbol mapping for things we don't have debug symbols for. */
+
+extern int
+have_minimal_symbols PARAMS ((void));
+
+extern struct obj_section *
+find_pc_section PARAMS((CORE_ADDR pc));
+
+/* Traverse all object files. ALL_OBJFILES_SAFE works even if you delete
+ the objfile during the traversal. */
+
+#define ALL_OBJFILES(obj) \
+ for ((obj) = object_files; (obj) != NULL; (obj) = (obj)->next)
+
+#define ALL_OBJFILES_SAFE(obj,nxt) \
+ for ((obj) = object_files; \
+ (obj) != NULL? ((nxt)=(obj)->next,1) :0; \
+ (obj) = (nxt))
+
+/* Traverse all symtabs in one objfile. */
+
+#define ALL_OBJFILE_SYMTABS(objfile, s) \
+ for ((s) = (objfile) -> symtabs; (s) != NULL; (s) = (s) -> next)
+
+/* Traverse all psymtabs in one objfile. */
+
+#define ALL_OBJFILE_PSYMTABS(objfile, p) \
+ for ((p) = (objfile) -> psymtabs; (p) != NULL; (p) = (p) -> next)
+
+/* Traverse all minimal symbols in one objfile. */
+
+#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) \
+ ALL_OBJFILES (objfile) \
+ ALL_OBJFILE_SYMTABS (objfile, s)
+
+/* Traverse all psymtabs in all objfiles. */
+
+#define ALL_PSYMTABS(objfile, p) \
+ ALL_OBJFILES (objfile) \
+ ALL_OBJFILE_PSYMTABS (objfile, p)
+
+/* Traverse all minimal symbols in all objfiles. */
+
+#define ALL_MSYMBOLS(objfile, m) \
+ ALL_OBJFILES (objfile) \
+ if ((objfile)->msymbols) \
+ ALL_OBJFILE_MSYMBOLS (objfile, m)
+
+#endif /* !defined (OBJFILES_H) */
diff --git a/contrib/gdb/gdb/op50-rom.c b/contrib/gdb/gdb/op50-rom.c
new file mode 100644
index 0000000..f8cb7fa
--- /dev/null
+++ b/contrib/gdb/gdb/op50-rom.c
@@ -0,0 +1,146 @@
+/* Remote target glue for the Oki op50n based eval board.
+
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void op50n_open PARAMS ((char *args, int from_tty));
+
+/*
+ * this array of registers need to match the indexes used by GDB. The
+ * whole reason this exists is cause the various ROM monitors use
+ * different strings than GDB does, and doesn't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *op50n_regnames[NUM_REGS] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+ "cr11", "p", NULL, NULL, NULL, "cr15", "cr19", "cr20",
+ "cr21", "cr22", NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "cr0", "cr8", "cr9", "cr10","cr12",
+ "cr13", "cr24", "cr25", "cr26",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops op50n_ops;
+
+static char *op50n_inits[] = {".\r", NULL};
+
+static struct monitor_ops op50n_cmds =
+{
+ MO_CLR_BREAK_USES_ADDR /*| MO_GETMEM_READ_SINGLE*/, /* flags */
+ op50n_inits, /* Init strings */
+ "g\r", /* continue command */
+ "t\r", /* single step */
+ "\003.\r", /* Interrupt char */
+ "b %x\r", /* set a breakpoint */
+ "b %x,0\r", /* clear breakpoint at addr */
+ "bx\r", /* clear all breakpoints */
+ "fx %x s%x %x\r", /* memory fill cmd (addr, len, val) */
+ {
+ "sx %x %x\r", /* setmem.cmdb (addr, value) */
+ "sh %x %x\r", /* setmem.cmdw (addr, value) */
+ "s %x %x\r", /* setmem.cmdl (addr, value) */
+ NULL, /* setmem.cmdll (addr, value) */
+ NULL, /* setmem.resp_delim */
+ NULL, /* setmem.term */
+ NULL, /* setmem.term_cmd */
+ },
+#if 0
+ {
+ "sx %x\r", /* getmem.cmdb (addr, len) */
+ "sh %x\r", /* getmem.cmdw (addr, len) */
+ "s %x\r", /* getmem.cmdl (addr, len) */
+ NULL, /* getmem.cmdll (addr, len) */
+ " : ", /* getmem.resp_delim */
+ " ", /* getmem.term */
+ ".\r", /* getmem.term_cmd */
+ },
+#else
+ {
+ "dx %x s%x\r", /* getmem.cmdb (addr, len) */
+ NULL, /* getmem.cmdw (addr, len) */
+ NULL, /* getmem.cmdl (addr, len) */
+ NULL, /* getmem.cmdll (addr, len) */
+ " : ", /* getmem.resp_delim */
+ NULL, /* getmem.term */
+ NULL, /* getmem.term_cmd */
+ },
+#endif
+ {
+ "x %s %x\r", /* setreg.cmd (name, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL, /* setreg.term_cmd */
+ },
+ {
+ "x %s\r", /* getreg.cmd (name) */
+ "=", /* getreg.resp_delim */
+ " ", /* getreg.term */
+ ".\r", /* getreg.term_cmd */
+ },
+ NULL, /* dump_registers */
+ NULL, /* register_pattern */
+ NULL, /* supply_register */
+ NULL, /* load routine */
+ "r 0\r", /* download command */
+ NULL, /* load response */
+ "\n#", /* monitor command prompt */
+ "\r", /* end-of-command delimitor */
+ NULL, /* optional command terminator */
+ &op50n_ops, /* target operations */
+ SERIAL_1_STOPBITS, /* number of stop bits */
+ op50n_regnames, /* register names */
+ MONITOR_OPS_MAGIC /* magic */
+ };
+
+static void
+op50n_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &op50n_cmds, from_tty);
+}
+
+void
+_initialize_op50n ()
+{
+ init_monitor_ops (&op50n_ops);
+
+ op50n_ops.to_shortname = "op50n";
+ op50n_ops.to_longname = "Oki's debug monitor for the Op50n Eval board";
+ op50n_ops.to_doc = "Debug on a Oki OP50N eval board.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ op50n_ops.to_open = op50n_open;
+
+ add_target (&op50n_ops);
+}
diff --git a/contrib/gdb/gdb/os9kread.c b/contrib/gdb/gdb/os9kread.c
new file mode 100644
index 0000000..f80cb1b
--- /dev/null
+++ b/contrib/gdb/gdb/os9kread.c
@@ -0,0 +1,1659 @@
+/* Read os9/os9k symbol tables and convert to internal format, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module provides three functions: os9k_symfile_init,
+ which initializes to read a symbol file; os9k_new_init, which
+ discards existing cached information when all symbols are being
+ discarded; and os9k_symfile_read, which reads a symbol table
+ from a file.
+
+ os9k_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. os9k_psymtab_to_symtab() is the function that does this */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <stdio.h>
+
+#if defined(USG) || defined(__CYGNUSCLIB__)
+#include <sys/types.h>
+#include <fcntl.h>
+#endif
+
+#include "obstack.h"
+#include <sys/param.h>
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#include "gdb_stat.h"
+#include <ctype.h>
+#include "symtab.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "target.h"
+#include "gdbcore.h" /* for bfd stuff */
+#include "libaout.h" /* FIXME Secret internal BFD stuff for a.out */
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "gdb-stabs.h"
+#include "demangle.h"
+#include "language.h" /* Needed inside partial-stab.h */
+#include "complaints.h"
+#include "os9k.h"
+#include "stabsread.h"
+
+/* 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 dbxread this structure contains the offset within the file symbol table
+ of first local symbol for this file, and count of the section
+ of the symbol table devoted to this file's symbols (actually, the section
+ bracketed may contain more than just this file's symbols). It also contains
+ further information needed to locate the symbols if they are in an ELF file.
+
+ If ldsymcnt is 0, the only reason for this thing's existence is the
+ dependency list. Nothing else will happen when it is read in. */
+
+#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
+#define LDSYMCNT(p) (((struct symloc *)((p)->read_symtab_private))->ldsymnum)
+
+struct symloc {
+ int ldsymoff;
+ int ldsymnum;
+};
+
+/* Remember what we deduced to be the source language of this psymtab. */
+static enum language psymtab_language = language_unknown;
+
+/* keep partial symbol table file nested depth */
+static int psymfile_depth = 0;
+
+/* keep symbol table file nested depth */
+static int symfile_depth = 0;
+
+/* Nonzero means give verbose info on gdb action. From main.c. */
+extern int info_verbose;
+
+extern int previous_stab_code;
+
+/* Name of last function encountered. Used in Solaris to approximate
+ object file boundaries. */
+static char *last_function_name;
+
+/* Complaints about the symbols we have encountered. */
+extern struct complaint lbrac_complaint;
+
+extern struct complaint unknown_symtype_complaint;
+
+extern struct complaint unknown_symchar_complaint;
+
+extern struct complaint lbrac_rbrac_complaint;
+
+extern struct complaint repeated_header_complaint;
+
+extern struct complaint repeated_header_name_complaint;
+
+#if 0
+static struct complaint lbrac_unmatched_complaint =
+ {"unmatched Increment Block Entry before symtab pos %d", 0, 0};
+
+static struct complaint lbrac_mismatch_complaint =
+ {"IBE/IDE symbol mismatch at symtab pos %d", 0, 0};
+#endif
+
+/* Local function prototypes */
+static void
+os9k_read_ofile_symtab PARAMS ((struct partial_symtab *));
+
+static void
+os9k_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+static void
+os9k_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static void
+read_os9k_psymtab PARAMS ((struct section_offsets *, struct objfile *,
+ CORE_ADDR, int));
+
+static int
+fill_sym PARAMS ((FILE *, bfd *));
+
+static void
+os9k_symfile_init PARAMS ((struct objfile *));
+
+static void
+os9k_new_init PARAMS ((struct objfile *));
+
+static void
+os9k_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+os9k_symfile_finish PARAMS ((struct objfile *));
+
+static void
+os9k_process_one_symbol PARAMS ((int, int, CORE_ADDR, char *,
+ struct section_offsets *, struct objfile *));
+
+static struct partial_symtab *
+os9k_start_psymtab PARAMS ((struct objfile *, struct section_offsets *, char *,
+ CORE_ADDR, int, int, struct partial_symbol **,
+ struct partial_symbol **));
+
+static struct partial_symtab *
+os9k_end_psymtab PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
+ struct partial_symtab **, int));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR, int, struct objfile *,
+ struct section_offsets *));
+
+#define HANDLE_RBRAC(val) \
+ if ((val) > pst->texthigh) pst->texthigh = (val);
+
+#define SWAP_STBHDR(hdrp, abfd) \
+ { \
+ (hdrp)->fmtno = bfd_get_16(abfd, (unsigned char *)&(hdrp)->fmtno); \
+ (hdrp)->crc = bfd_get_32(abfd, (unsigned char *)&(hdrp)->crc); \
+ (hdrp)->offset = bfd_get_32(abfd, (unsigned char *)&(hdrp)->offset); \
+ (hdrp)->nsym = bfd_get_32(abfd, (unsigned char *)&(hdrp)->nsym); \
+ }
+#define SWAP_STBSYM(symp, abfd) \
+ { \
+ (symp)->value = bfd_get_32(abfd, (unsigned char *)&(symp)->value); \
+ (symp)->type = bfd_get_16(abfd, (unsigned char *)&(symp)->type); \
+ (symp)->stroff = bfd_get_32(abfd, (unsigned char *)&(symp)->stroff); \
+ }
+#define N_DATA 0
+#define N_BSS 1
+#define N_RDATA 2
+#define N_IDATA 3
+#define N_TEXT 4
+#define N_ABS 6
+
+static void
+record_minimal_symbol (name, address, type, objfile, section_offsets)
+ char *name;
+ CORE_ADDR address;
+ int type;
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ enum minimal_symbol_type ms_type;
+
+ switch (type)
+ {
+ case N_TEXT:
+ ms_type = mst_text;
+ address += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ break;
+ case N_DATA:
+ ms_type = mst_data;
+ break;
+ case N_BSS:
+ ms_type = mst_bss;
+ break;
+ case N_RDATA:
+ ms_type = mst_bss;
+ break;
+ case N_IDATA:
+ ms_type = mst_data;
+ break;
+ case N_ABS:
+ ms_type = mst_abs;
+ break;
+ default:
+ ms_type = mst_unknown; break;
+ }
+
+ prim_record_minimal_symbol
+ (obsavestring (name, strlen(name), &objfile->symbol_obstack),
+ address, ms_type, objfile);
+}
+
+/* read and process .stb file and store in minimal symbol table */
+typedef char mhhdr[80];
+struct stbhdr {
+ mhhdr comhdr;
+ char * name;
+ short fmtno;
+ int crc;
+ int offset;
+ int nsym;
+ char *pad;
+};
+struct stbsymbol {
+ int value;
+ short type;
+ int stroff;
+};
+#define STBSYMSIZE 10
+
+static void
+read_minimal_symbols(objfile, section_offsets)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+FILE *fp;
+bfd *abfd;
+struct stbhdr hdr;
+struct stbsymbol sym;
+int ch, i, j, off;
+char buf[64], buf1[128];
+
+ fp = objfile->auxf1;
+ if (fp == NULL) return;
+ abfd = objfile->obfd;
+ fread(&hdr.comhdr[0], sizeof(mhhdr), 1, fp);
+ i = 0;
+ ch = getc(fp);
+ while (ch != -1) {
+ buf[i] = (char)ch;
+ i++;
+ if (ch == 0) break;
+ ch = getc(fp);
+ };
+ if (i%2) ch=getc(fp);
+ hdr.name = &buf[0];
+
+ fread(&hdr.fmtno, sizeof(hdr.fmtno), 1, fp);
+ fread(&hdr.crc, sizeof(hdr.crc), 1, fp);
+ fread(&hdr.offset, sizeof(hdr.offset), 1, fp);
+ fread(&hdr.nsym, sizeof(hdr.nsym), 1, fp);
+ SWAP_STBHDR(&hdr, abfd);
+
+ /* read symbols */
+ init_minimal_symbol_collection();
+ off = hdr.offset;
+ for (i = hdr.nsym; i > 0; i--) {
+ fseek(fp, (long)off, 0);
+ fread(&sym.value, sizeof(sym.value), 1, fp);
+ fread(&sym.type, sizeof(sym.type), 1, fp);
+ fread(&sym.stroff, sizeof(sym.stroff), 1, fp);
+ SWAP_STBSYM (&sym, abfd);
+ fseek(fp, (long)sym.stroff, 0);
+ j = 0;
+ ch = getc(fp);
+ while (ch != -1) {
+ buf1[j] = (char)ch;
+ j++;
+ if (ch == 0) break;
+ ch = getc(fp);
+ };
+ record_minimal_symbol(buf1, sym.value, sym.type&7, objfile, section_offsets);
+ off += STBSYMSIZE;
+ };
+ install_minimal_symbols (objfile);
+ return;
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to os9k_symfile_init, which
+ put all the relevant info into a "struct os9k_symfile_info",
+ hung off the objfile structure.
+
+ SECTION_OFFSETS contains offsets relative to which the symbols in the
+ various sections are (depending where the sections were actually loaded).
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file). */
+
+static void
+os9k_symfile_read (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline; /* FIXME comments above */
+{
+ bfd *sym_bfd;
+ struct cleanup *back_to;
+
+ sym_bfd = objfile->obfd;
+ /* If we are reinitializing, or if we have never loaded syms yet, init */
+ if (mainline || objfile->global_psymbols.size == 0 ||
+ objfile->static_psymbols.size == 0)
+ init_psymbol_list (objfile, DBX_SYMCOUNT (objfile));
+
+ pending_blocks = 0;
+ back_to = make_cleanup (really_free_pendings, 0);
+
+ make_cleanup (discard_minimal_symbols, 0);
+ read_minimal_symbols (objfile, section_offsets);
+
+ /* Now that the symbol table data of the executable file are all in core,
+ process them and define symbols accordingly. */
+ read_os9k_psymtab (section_offsets, objfile,
+ DBX_TEXT_ADDR (objfile),
+ DBX_TEXT_SIZE (objfile));
+
+ do_cleanups (back_to);
+}
+
+/* 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 void
+os9k_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+ psymfile_depth = 0;
+/*
+ init_header_files ();
+*/
+}
+
+/* os9k_symfile_init ()
+ It is passed a struct objfile which contains, among other things,
+ the BFD for the file whose symbols are being read, and a slot for a pointer
+ to "private data" which we fill with goodies.
+
+ Since BFD doesn't know how to read debug symbols in a format-independent
+ way (and may never do so...), we have to do it ourselves. We will never
+ be called unless this is an a.out (or very similar) file.
+ FIXME, there should be a cleaner peephole into the BFD environment here. */
+
+static void
+os9k_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ bfd *sym_bfd = objfile->obfd;
+ char *name = bfd_get_filename (sym_bfd);
+ char dbgname[512], stbname[512];
+ FILE *symfile = 0;
+ FILE *minfile = 0;
+ asection *text_sect;
+
+ strcpy(dbgname, name);
+ strcat(dbgname, ".dbg");
+ strcpy(stbname, name);
+ strcat(stbname, ".stb");
+
+ if ((symfile = fopen(dbgname, "r")) == NULL) {
+ warning("Symbol file %s not found", dbgname);
+ }
+ objfile->auxf2 = symfile;
+
+ if ((minfile = fopen(stbname, "r")) == NULL) {
+ warning("Symbol file %s not found", stbname);
+ }
+ objfile->auxf1 = minfile;
+
+ /* Allocate struct to keep track of the symfile */
+ objfile->sym_stab_info = (PTR)
+ xmmalloc (objfile -> md, sizeof (struct dbx_symfile_info));
+ DBX_SYMFILE_INFO (objfile)->stab_section_info = NULL;
+
+ text_sect = bfd_get_section_by_name (sym_bfd, ".text");
+ if (!text_sect)
+ error ("Can't find .text section in file");
+ DBX_TEXT_ADDR (objfile) = bfd_section_vma (sym_bfd, text_sect);
+ DBX_TEXT_SIZE (objfile) = bfd_section_size (sym_bfd, text_sect);
+
+ DBX_SYMBOL_SIZE (objfile) = 0; /* variable size symbol */
+ DBX_SYMCOUNT (objfile) = 0; /* used to be bfd_get_symcount(sym_bfd) */
+ DBX_SYMTAB_OFFSET (objfile) = 0; /* used to be SYMBOL_TABLE_OFFSET */
+}
+
+/* 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. */
+
+static void
+os9k_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile->sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile->sym_stab_info);
+ }
+/*
+ free_header_files ();
+*/
+}
+
+
+struct st_dbghdr {
+ int sync;
+ short rev;
+ int crc;
+ short os;
+ short cpu;
+};
+#define SYNC (int)0xefbefeca
+
+#define SWAP_DBGHDR(hdrp, abfd) \
+ { \
+ (hdrp)->sync = bfd_get_32(abfd, (unsigned char *)&(hdrp)->sync); \
+ (hdrp)->rev = bfd_get_16(abfd, (unsigned char *)&(hdrp)->rev); \
+ (hdrp)->crc = bfd_get_32(abfd, (unsigned char *)&(hdrp)->crc); \
+ (hdrp)->os = bfd_get_16(abfd, (unsigned char *)&(hdrp)->os); \
+ (hdrp)->cpu = bfd_get_16(abfd, (unsigned char *)&(hdrp)->cpu); \
+ }
+
+#define N_SYM_CMPLR 0
+#define N_SYM_SLINE 1
+#define N_SYM_SYM 2
+#define N_SYM_LBRAC 3
+#define N_SYM_RBRAC 4
+#define N_SYM_SE 5
+
+struct internal_symstruct {
+ short n_type;
+ short n_desc;
+ long n_value;
+ char * n_strx;
+};
+static struct internal_symstruct symbol;
+static struct internal_symstruct *symbuf = &symbol;
+static char strbuf[4096];
+static struct st_dbghdr dbghdr;
+static short cmplrid;
+
+#define VER_PRE_ULTRAC ((short)4)
+#define VER_ULTRAC ((short)5)
+
+static int
+fill_sym (dbg_file, abfd)
+ FILE *dbg_file;
+ bfd *abfd;
+{
+short si, nmask;
+long li;
+int ii;
+char *p;
+
+ int nbytes = fread(&si, sizeof(si), 1, dbg_file);
+ if (nbytes == 0)
+ return 0;
+ if (nbytes < 0)
+ perror_with_name ("reading .dbg file.");
+ symbuf->n_desc = 0;
+ symbuf->n_value = 0;
+ symbuf->n_strx = NULL;
+ symbuf->n_type = bfd_get_16 (abfd, (unsigned char *)&si);
+ symbuf->n_type = 0xf & symbuf->n_type;
+ switch (symbuf->n_type)
+ {
+ case N_SYM_CMPLR:
+ fread(&si, sizeof(si), 1, dbg_file);
+ symbuf->n_desc = bfd_get_16(abfd, (unsigned char *)&si);
+ cmplrid = symbuf->n_desc & 0xff;
+ break;
+ case N_SYM_SLINE:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ fread(&li, sizeof(li), 1, dbg_file);
+ li = bfd_get_32(abfd, (unsigned char *)&li);
+ symbuf->n_strx = (char *)(li >> 12);
+ symbuf->n_desc = li & 0xfff;
+ break;
+ case N_SYM_SYM:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ si = 0;
+ do {
+ ii = getc(dbg_file);
+ strbuf[si++] = (char) ii;
+ } while (ii != 0 || si % 2 != 0);
+ symbuf->n_strx = strbuf;
+ p = (char *) strchr (strbuf, ':');
+ if (!p) break;
+ if ((p[1] == 'F' || p[1] == 'f') && cmplrid == VER_PRE_ULTRAC)
+ {
+ fread(&si, sizeof(si), 1, dbg_file);
+ nmask = bfd_get_16(abfd, (unsigned char *)&si);
+ for (ii=0; ii<nmask; ii++)
+ fread(&si, sizeof(si), 1, dbg_file);
+ }
+ break;
+ case N_SYM_LBRAC:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ break;
+ case N_SYM_RBRAC:
+ fread(&li, sizeof(li), 1, dbg_file);
+ symbuf->n_value = bfd_get_32(abfd, (unsigned char *)&li);
+ break;
+ case N_SYM_SE:
+ break;
+ }
+ return 1;
+}
+
+/* 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.
+ SYMFILE_NAME is the name of the file we are reading from
+ and SECTION_OFFSETS is the set of offsets for the various sections
+ of the file (a set of zeros if the mainline program). */
+
+static void
+read_os9k_psymtab (section_offsets, objfile, text_addr, text_size)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+ CORE_ADDR text_addr;
+ int text_size;
+{
+ register struct internal_symstruct *bufp = 0; /* =0 avoids gcc -Wall glitch*/
+ register char *namestring;
+ int past_first_source_file = 0;
+ CORE_ADDR last_o_file_start = 0;
+#if 0
+ struct cleanup *back_to;
+#endif
+ bfd *abfd;
+ FILE *fp;
+
+ /* End of the text segment of the executable file. */
+ static CORE_ADDR end_of_text_addr;
+
+ /* Current partial symtab */
+ static struct partial_symtab *pst = 0;
+
+ /* List of current psymtab's include files */
+ char **psymtab_include_list;
+ int includes_allocated;
+ int includes_used;
+
+ /* Index within current psymtab dependency list */
+ struct partial_symtab **dependency_list;
+ int dependencies_used, dependencies_allocated;
+
+ includes_allocated = 30;
+ includes_used = 0;
+ psymtab_include_list = (char **) alloca (includes_allocated *
+ sizeof (char *));
+
+ dependencies_allocated = 30;
+ dependencies_used = 0;
+ dependency_list =
+ (struct partial_symtab **) alloca (dependencies_allocated *
+ sizeof (struct partial_symtab *));
+
+ 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
+
+ abfd = objfile->obfd;
+ fp = objfile->auxf2;
+ if (!fp) return;
+
+ fread(&dbghdr.sync, sizeof(dbghdr.sync), 1, fp);
+ fread(&dbghdr.rev, sizeof(dbghdr.rev), 1, fp);
+ fread(&dbghdr.crc, sizeof(dbghdr.crc), 1, fp);
+ fread(&dbghdr.os, sizeof(dbghdr.os), 1, fp);
+ fread(&dbghdr.cpu, sizeof(dbghdr.cpu), 1, fp);
+ SWAP_DBGHDR(&dbghdr, abfd);
+
+ symnum = 0;
+ while(1)
+ {
+ int ret;
+ long cursymoffset;
+
+ /* Get the symbol for this run and pull out some info */
+ QUIT; /* allow this to be interruptable */
+ cursymoffset = ftell(objfile->auxf2);
+ ret = fill_sym(objfile->auxf2, abfd);
+ if (ret <= 0) break;
+ else symnum++;
+ bufp = symbuf;
+
+ /* Special case to speed up readin. */
+ if (bufp->n_type == (short)N_SYM_SLINE) continue;
+
+#define CUR_SYMBOL_VALUE bufp->n_value
+ /* partial-stab.h */
+
+ switch (bufp->n_type)
+ {
+ char *p;
+
+ case N_SYM_CMPLR:
+ continue;
+
+ case N_SYM_SE:
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ if (psymfile_depth == 1 && pst)
+ {
+ os9k_end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum, CUR_SYMBOL_VALUE,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ psymfile_depth--;
+ continue;
+
+ case N_SYM_SYM: /* Typedef or automatic variable. */
+ namestring = bufp->n_strx;
+ p = (char *) strchr (namestring, ':');
+ if (!p)
+ continue; /* Not a debugging symbol. */
+
+ /* Main processing section for debugging symbols which
+ the initial read through the symbol tables needs to worry
+ about. If we reach this point, the symbol which we are
+ considering is definitely one we are interested in.
+ p must also contain the (valid) index into the namestring
+ which indicates the debugging type symbol. */
+
+ switch (p[1])
+ {
+ case 'S' :
+ {
+ unsigned long valu;
+ enum language tmp_language;
+ char *str, *p;
+ int n;
+
+ valu = CUR_SYMBOL_VALUE;
+ if (valu)
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ past_first_source_file = 1;
+
+ p = strchr(namestring, ':');
+ if (p) n = p-namestring;
+ else n = strlen(namestring);
+ str = alloca(n+1);
+ strncpy(str, namestring, n);
+ str[n] = '\0';
+
+ if (psymfile_depth == 0) {
+ if (!pst)
+ pst = os9k_start_psymtab (objfile, section_offsets,
+ str, valu,
+ cursymoffset,
+ symnum-1,
+ objfile -> global_psymbols.next,
+ objfile -> static_psymbols.next);
+ } else { /* this is a include file */
+ tmp_language = deduce_language_from_filename (str);
+ if (tmp_language != language_unknown
+ && (tmp_language != language_c
+ || psymtab_language != language_cplus))
+ psymtab_language = tmp_language;
+
+/*
+ if (pst && STREQ (str, pst->filename))
+ continue;
+ {
+ register int i;
+ for (i = 0; i < includes_used; i++)
+ if (STREQ (str, psymtab_include_list[i]))
+ {
+ i = -1;
+ break;
+ }
+ if (i == -1)
+ continue;
+ }
+*/
+
+ psymtab_include_list[includes_used++] = str;
+ 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 *));
+ }
+
+ }
+ psymfile_depth++;
+ continue;
+ }
+
+ case 'v':
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+ case 'V':
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+
+ case 'T':
+ if (p != namestring) /* a name is there, not just :T... */
+ {
+ add_psymbol_to_list (namestring, p - namestring,
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0,
+ psymtab_language, objfile);
+ if (p[2] == 't')
+ {
+ /* Also a typedef with the same name. */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0, psymtab_language,
+ 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, 0, psymtab_language,
+ objfile);
+ }
+ }
+ goto check_enum;
+ case 't':
+ if (p != namestring) /* a name is there, not just :T... */
+ {
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0,
+ psymtab_language, objfile);
+ }
+ check_enum:
+ /* If this is an enumerated type, we need to
+ add all the enum constants to the partial symbol
+ table. This does not cover enums without names, e.g.
+ "enum {a, b} c;" in C, but fortunately those are
+ rare. There is no way for GDB to find those from the
+ enum type without spending too much time on it. Thus
+ to solve this problem, the compiler needs to put out the
+ enum in a nameless type. GCC2 does this. */
+
+ /* We are looking for something of the form
+ <name> ":" ("t" | "T") [<number> "="] "e" <size>
+ {<constant> ":" <value> ","} ";". */
+
+ /* Skip over the colon and the 't' or 'T'. */
+ p += 2;
+ /* This type may be given a number. Also, numbers can come
+ in pairs like (0,26). Skip over it. */
+ while ((*p >= '0' && *p <= '9')
+ || *p == '(' || *p == ',' || *p == ')'
+ || *p == '=')
+ p++;
+
+ if (*p++ == 'e')
+ {
+ /* We have found an enumerated type. skip size */
+ while (*p >= '0' && *p <= '9') p++;
+ /* According to comments in read_enum_type
+ a comma could end it instead of a semicolon.
+ I don't know where that happens.
+ Accept either. */
+ while (*p && *p != ';' && *p != ',')
+ {
+ char *q;
+
+ /* Check for and handle cretinous dbx symbol name
+ continuation!
+ if (*p == '\\')
+ p = next_symbol_text (objfile);
+ */
+
+ /* Point to the character after the name
+ of the enum constant. */
+ for (q = p; *q && *q != ':'; q++)
+ ;
+ /* Note that the value doesn't matter for
+ enum constants in psymtabs, just in symtabs. */
+ add_psymbol_to_list (p, q - p,
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ 0, psymtab_language, objfile);
+ /* Point past the name. */
+ p = q;
+ /* Skip over the value. */
+ while (*p && *p != ',')
+ p++;
+ /* Advance past the comma. */
+ if (*p)
+ p++;
+ }
+ }
+ continue;
+ case 'c':
+ /* Constant, e.g. from "const" in Pascal. */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'f':
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ if (pst && pst->textlow == 0)
+ pst->textlow = CUR_SYMBOL_VALUE;
+
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'F':
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+ if (pst && pst->textlow == 0)
+ pst->textlow = CUR_SYMBOL_VALUE;
+
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'p':
+ case 'l':
+ case 's':
+ continue;
+
+ 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]);
+ continue;
+ }
+
+ case N_SYM_RBRAC:
+ CUR_SYMBOL_VALUE += ANOFFSET(section_offsets, SECT_OFF_TEXT);
+#ifdef HANDLE_RBRAC
+ HANDLE_RBRAC(CUR_SYMBOL_VALUE);
+ continue;
+#endif
+ case N_SYM_LBRAC:
+ continue;
+
+ default:
+ /* 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) bufp->n_type));
+ continue;
+ }
+ }
+
+ DBX_SYMCOUNT (objfile) = symnum;
+
+ /* If there's stuff to be cleaned up, clean it up. */
+ if (DBX_SYMCOUNT (objfile) > 0
+/*FIXME, does this have a bug at start address 0? */
+ && last_o_file_start
+ && objfile -> ei.entry_point < bufp->n_value
+ && objfile -> ei.entry_point >= last_o_file_start)
+ {
+ objfile -> ei.entry_file_lowpc = last_o_file_start;
+ objfile -> ei.entry_file_highpc = bufp->n_value;
+ }
+
+ if (pst)
+ {
+ os9k_end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum, end_of_text_addr,
+ dependency_list, dependencies_used);
+ }
+/*
+ do_cleanups (back_to);
+*/
+}
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+
+static struct partial_symtab *
+os9k_start_psymtab (objfile, section_offsets,
+ filename, textlow, ldsymoff,ldsymcnt, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ CORE_ADDR textlow;
+ int ldsymoff;
+ int ldsymcnt;
+ struct partial_symbol **global_syms;
+ struct partial_symbol **static_syms;
+{
+ struct partial_symtab *result =
+ start_psymtab_common(objfile, section_offsets,
+ filename, textlow, global_syms, static_syms);
+
+ result->read_symtab_private = (char *)
+ obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct symloc));
+
+ LDSYMOFF(result) = ldsymoff;
+ LDSYMCNT(result) = ldsymcnt;
+ result->read_symtab = os9k_psymtab_to_symtab;
+
+ /* Deduce the source language from the filename for this psymtab. */
+ psymtab_language = deduce_language_from_filename (filename);
+ return result;
+}
+
+/* Close off the current usage of PST.
+ Returns PST or NULL if the partial symtab was empty and thrown away.
+ FIXME: List variables and peculiarities of same. */
+
+static struct partial_symtab *
+os9k_end_psymtab (pst, include_list, num_includes, capping_symbol_cnt,
+ capping_text, dependency_list, number_dependencies)
+ struct partial_symtab *pst;
+ char **include_list;
+ int num_includes;
+ int capping_symbol_cnt;
+ 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_cnt != -1)
+ LDSYMCNT(pst) = capping_symbol_cnt - LDSYMCNT(pst);
+
+ /* 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.
+ The first trick is in partial-stab.h: if we see a static
+ or global function, and the textlow for the current pst
+ is still 0, then we use that function's address for
+ the textlow of the pst.
+
+ Now, to fill in texthigh, we remember the last function seen
+ in the .o file (also in partial-stab.h). Also, there's a hack in
+ bfd/elf.c and gdb/elfread.c to pass the ELF st_size field
+ to here via the misc_info field. Therefore, we can fill in
+ a reliable texthigh by taking the address plus size of the
+ last function in the file.
+
+ Unfortunately, that does not cover the case where the last function
+ in the file is static. See the paragraph below for more comments
+ on this situation.
+
+ Finally, if we have a valid textlow for the current file, we run
+ down the partial_symtab_list filling in previous texthighs that
+ are still unknown. */
+
+ if (pst->texthigh == 0 && last_function_name) {
+ char *p;
+ int n;
+ struct minimal_symbol *minsym;
+
+ p = strchr (last_function_name, ':');
+ if (p == NULL)
+ p = last_function_name;
+ n = p - last_function_name;
+ p = alloca (n + 1);
+ strncpy (p, last_function_name, n);
+ p[n] = 0;
+
+ minsym = lookup_minimal_symbol (p, NULL, objfile);
+
+ if (minsym) {
+ pst->texthigh = SYMBOL_VALUE_ADDRESS(minsym)+(long)MSYMBOL_INFO(minsym);
+ } else {
+ /* This file ends with a static function, and it's
+ difficult to imagine how hard it would be to track down
+ the elf symbol. Luckily, most of the time no one will notice,
+ since the next file will likely be compiled with -g, so
+ the code below will copy the first fuction's start address
+ back to our texthigh variable. (Also, if this file is the
+ last one in a dynamically linked program, texthigh already
+ has the right value.) If the next file isn't compiled
+ with -g, then the last function in this file winds up owning
+ all of the text space up to the next -g file, or the end (minus
+ shared libraries). This only matters for single stepping,
+ and even then it will still work, except that it will single
+ step through all of the covered functions, instead of setting
+ breakpoints around them as it usualy does. This makes it
+ pretty slow, but at least it doesn't fail.
+
+ We can fix this with a fairly big change to bfd, but we need
+ to coordinate better with Cygnus if we want to do that. FIXME. */
+ }
+ last_function_name = NULL;
+ }
+
+ /* this test will be true if the last .o file is only data */
+ if (pst->textlow == 0)
+ pst->textlow = pst->texthigh;
+
+ /* If we know our own starting text address, then walk through all other
+ psymtabs for this objfile, and if any didn't know their ending text
+ address, set it to our starting address. Take care to not set our
+ own ending address to our starting address, nor to set addresses on
+ `dependency' files that have both textlow and texthigh zero. */
+ if (pst->textlow) {
+ ALL_OBJFILE_PSYMTABS (objfile, p1) {
+ if (p1->texthigh == 0 && p1->textlow != 0 && p1 != pst) {
+ p1->texthigh = pst->textlow;
+ /* if this file has only data, then make textlow match texthigh */
+ if (p1->textlow == 0)
+ p1->textlow = p1->texthigh;
+ }
+ }
+ }
+
+ /* End of kludge for patching Solaris textlow and texthigh. */
+
+ pst->n_global_syms =
+ objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset);
+ pst->n_static_syms =
+ objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset);
+
+ pst->number_of_dependencies = number_dependencies;
+ if (number_dependencies)
+ {
+ pst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ number_dependencies * sizeof (struct partial_symtab *));
+ memcpy (pst->dependencies, dependency_list,
+ number_dependencies * sizeof (struct partial_symtab *));
+ }
+ else
+ pst->dependencies = 0;
+
+ for (i = 0; i < num_includes; i++)
+ {
+ struct partial_symtab *subpst =
+ allocate_psymtab (include_list[i], objfile);
+
+ subpst->section_offsets = pst->section_offsets;
+ subpst->read_symtab_private =
+ (char *) obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct symloc));
+ LDSYMOFF(subpst) =
+ LDSYMCNT(subpst) =
+ subpst->textlow =
+ subpst->texthigh = 0;
+
+ /* We could save slight bits of space by only making one of these,
+ shared by the entire set of include files. FIXME-someday. */
+ subpst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct partial_symtab *));
+ subpst->dependencies[0] = pst;
+ subpst->number_of_dependencies = 1;
+
+ subpst->globals_offset =
+ subpst->n_global_syms =
+ subpst->statics_offset =
+ subpst->n_static_syms = 0;
+
+ subpst->readin = 0;
+ subpst->symtab = 0;
+ subpst->read_symtab = pst->read_symtab;
+ }
+
+ sort_pst_symbols (pst);
+
+ /* If there is already a psymtab or symtab for a file of this name,
+ remove it.
+ (If there is a symtab, more drastic things also happen.)
+ This happens in VxWorks. */
+ 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;
+
+ /* 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;
+
+ /* Next, put it on a free list for recycling */
+ pst->next = pst->objfile->free_psymtabs;
+ pst->objfile->free_psymtabs = pst;
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *)NULL;
+ }
+ return pst;
+}
+
+static void
+os9k_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ /* Read in all partial symtabs on which this one is dependent */
+ for (i = 0; i < pst->number_of_dependencies; i++)
+ if (!pst->dependencies[i]->readin)
+ {
+ /* Inform about additional files that need to be read in. */
+ if (info_verbose)
+ {
+ fputs_filtered (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ os9k_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ if (LDSYMCNT(pst)) /* Otherwise it's a dummy */
+ {
+ /* Init stuff necessary for reading in symbols */
+ stabsread_init ();
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+
+ /* Read in this file's symbols */
+ os9k_read_ofile_symtab (pst);
+ sort_symtab_syms (pst->symtab);
+ do_cleanups (old_chain);
+ }
+
+ pst->readin = 1;
+}
+
+/* Read in all of the symbols for a given psymtab for real.
+ Be verbose about it if the user wants that. */
+
+static void
+os9k_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ bfd *sym_bfd;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ if (LDSYMCNT(pst) || pst->number_of_dependencies)
+ {
+ /* Print the message now, before reading the string table,
+ to avoid disconcerting pauses. */
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ gdb_flush (gdb_stdout);
+ }
+
+ sym_bfd = pst->objfile->obfd;
+ os9k_psymtab_to_symtab_1 (pst);
+
+ /* 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);
+
+ /* Finish up the debug error message. */
+ if (info_verbose)
+ printf_filtered ("done.\n");
+ }
+}
+
+/* Read in a defined section of a specific object file's symbols. */
+static void
+os9k_read_ofile_symtab (pst)
+ struct partial_symtab *pst;
+{
+ register struct internal_symstruct *bufp;
+ unsigned char type;
+ unsigned max_symnum;
+ register bfd *abfd;
+ struct objfile *objfile;
+ int sym_offset; /* Offset to start of symbols to read */
+ CORE_ADDR text_offset; /* Start of text segment for symbols */
+ int text_size; /* Size of text segment for symbols */
+ struct section_offsets *section_offsets;
+ FILE *dbg_file;
+
+ objfile = pst->objfile;
+ sym_offset = LDSYMOFF(pst);
+ max_symnum = LDSYMCNT(pst);
+ text_offset = pst->textlow;
+ text_size = pst->texthigh - pst->textlow;
+ section_offsets = pst->section_offsets;
+
+ current_objfile = objfile;
+ subfile_stack = NULL;
+ last_source_file = NULL;
+
+ abfd = objfile->obfd;
+ dbg_file = objfile->auxf2;
+
+#if 0
+ /* It is necessary to actually read one symbol *before* the start
+ of this symtab's symbols, because the GCC_COMPILED_FLAG_SYMBOL
+ occurs before the N_SO symbol.
+ Detecting this in read_dbx_symtab
+ would slow down initial readin, so we look for it here instead. */
+ if (!processing_acc_compilation && sym_offset >= (int)symbol_size)
+ {
+ fseek (objefile->auxf2, sym_offset, SEEK_CUR);
+ fill_sym(objfile->auxf2, abfd);
+ bufp = symbuf;
+
+ processing_gcc_compilation = 0;
+ if (bufp->n_type == N_TEXT)
+ {
+ if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 1;
+ else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 2;
+ }
+
+ /* Try to select a C++ demangling based on the compilation unit
+ producer. */
+
+ if (processing_gcc_compilation)
+ {
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ }
+ }
+ else
+ {
+ /* The N_SO starting this symtab is the first symbol, so we
+ better not check the symbol before it. I'm not this can
+ happen, but it doesn't hurt to check for it. */
+ bfd_seek (symfile_bfd, sym_offset, SEEK_CUR);
+ processing_gcc_compilation = 0;
+ }
+#endif /* 0 */
+
+ fseek(dbg_file, (long)sym_offset, 0);
+/*
+ if (bufp->n_type != (unsigned char)N_SYM_SYM)
+ error("First symbol in segment of executable not a source symbol");
+*/
+
+ for (symnum = 0; symnum < max_symnum; symnum++)
+ {
+ QUIT; /* Allow this to be interruptable */
+ fill_sym(dbg_file, abfd);
+ bufp = symbuf;
+ type = bufp->n_type;
+
+ os9k_process_one_symbol ((int)type, (int)bufp->n_desc,
+ (CORE_ADDR)bufp->n_value, bufp->n_strx, section_offsets, objfile);
+
+ /* We skip checking for a new .o or -l file; that should never
+ happen in this routine. */
+#if 0
+ else if (type == N_TEXT)
+ {
+ /* I don't think this code will ever be executed, because
+ the GCC_COMPILED_FLAG_SYMBOL usually is right before
+ the N_SO symbol which starts this source file.
+ However, there is no reason not to accept
+ the GCC_COMPILED_FLAG_SYMBOL anywhere. */
+
+ if (STREQ (namestring, GCC_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 1;
+ else if (STREQ (namestring, GCC2_COMPILED_FLAG_SYMBOL))
+ processing_gcc_compilation = 2;
+
+ if (AUTO_DEMANGLING)
+ {
+ set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+ }
+ }
+ else if (type & N_EXT || type == (unsigned char)N_TEXT
+ || type == (unsigned char)N_NBTEXT
+ ) {
+ /* Global symbol: see if we came across a dbx defintion for
+ a corresponding symbol. If so, store the value. Remove
+ syms from the chain when their values are stored, but
+ search the whole chain, as there may be several syms from
+ different files with the same name. */
+ /* This is probably not true. Since the files will be read
+ in one at a time, each reference to a global symbol will
+ be satisfied in each file as it appears. So we skip this
+ section. */
+ ;
+ }
+#endif /* 0 */
+ }
+
+ current_objfile = NULL;
+
+ /* In a Solaris elf file, this variable, which comes from the
+ value of the N_SO symbol, will still be 0. Luckily, text_offset,
+ which comes from pst->textlow is correct. */
+ if (last_source_start_addr == 0)
+ last_source_start_addr = text_offset;
+ pst->symtab = end_symtab (text_offset + text_size, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+}
+
+
+/* This handles a single symbol from the symbol-file, building symbols
+ into a GDB symtab. It takes these arguments and an implicit argument.
+
+ TYPE is the type field of the ".stab" symbol entry.
+ DESC is the desc field of the ".stab" entry.
+ VALU is the value field of the ".stab" entry.
+ NAME is the symbol name, in our address space.
+ SECTION_OFFSETS is a set of amounts by which the sections of this object
+ file were relocated when it was loaded into memory.
+ All symbols that refer
+ to memory locations need to be offset by these amounts.
+ OBJFILE is the object file from which we are reading symbols.
+ It is used in end_symtab. */
+
+static void
+os9k_process_one_symbol (type, desc, valu, name, section_offsets, objfile)
+ int type, desc;
+ CORE_ADDR valu;
+ char *name;
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ register struct context_stack *new;
+ /* The stab type used for the definition of the last function.
+ N_STSYM or N_GSYM for SunOS4 acc; N_FUN for other compilers. */
+ static int function_stab_type = 0;
+
+#if 0
+ /* Something is wrong if we see real data before
+ seeing a source file name. */
+ if (last_source_file == NULL && type != (unsigned char)N_SO)
+ {
+ /* Ignore any symbols which appear before an N_SO symbol. Currently
+ no one puts symbols there, but we should deal gracefully with the
+ case. A complain()t might be in order (if !IGNORE_SYMBOL (type)),
+ but this should not be an error (). */
+ return;
+ }
+#endif /* 0 */
+
+ switch (type)
+ {
+ case N_SYM_LBRAC:
+ /* On most machines, the block addresses are relative to the
+ N_SO, the linker did not relocate them (sigh). */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ new = push_context (desc, valu);
+ break;
+
+ case N_SYM_RBRAC:
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ new = pop_context();
+
+#if !defined (OS9K_VARIABLES_INSIDE_BLOCK)
+#define OS9K_VARIABLES_INSIDE_BLOCK(desc, gcc_p) 1
+#endif
+
+ if (!OS9K_VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+ local_symbols = new->locals;
+
+ if (context_stack_depth > 1)
+ {
+ /* 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)
+ {
+ /* 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);
+ }
+ }
+ else
+ {
+ if (context_stack_depth == 0)
+ {
+ within_function = 0;
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr, valu, objfile);
+ }
+ else
+ {
+ /* attach local_symbols to the end of new->locals */
+ if (!new->locals) new->locals = local_symbols;
+ else {
+ struct pending *p;
+
+ p = new->locals;
+ while (p->next) p = p->next;
+ p->next = local_symbols;
+ }
+ }
+ }
+
+ if (OS9K_VARIABLES_INSIDE_BLOCK(desc, processing_gcc_compilation))
+ /* Now pop locals of block just finished. */
+ local_symbols = new->locals;
+ break;
+
+
+ case N_SYM_SLINE:
+ /* This type of "symbol" really just records
+ one line-number -- core-address correspondence.
+ Enter it in the line list for this symbol table. */
+ /* Relocate for dynamic loading and for ELF acc fn-relative syms. */
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ /* FIXME: loses if sizeof (char *) > sizeof (int) */
+ record_line (current_subfile, (int)name, valu);
+ break;
+
+ /* The following symbol types need to have the appropriate offset added
+ to their value; then we process symbol definitions in the name. */
+ case N_SYM_SYM:
+
+ if (name)
+ {
+ char deftype;
+ char *dirn, *n;
+ char *p = strchr (name, ':');
+ if (p == NULL)
+ deftype = '\0';
+ else
+ deftype = p[1];
+
+
+ switch (deftype)
+ {
+ case 'S':
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ n = strrchr(name, '/');
+ if (n != NULL) {
+ *n = '\0';
+ n++;
+ dirn = name;
+ } else {
+ n = name;
+ dirn = NULL;
+ }
+ *p = '\0';
+ if (symfile_depth++ == 0) {
+ if (last_source_file) {
+ end_symtab (valu, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ }
+ start_stabs ();
+ os9k_stabs = 1;
+ start_symtab (n, dirn, valu);
+ } else {
+ push_subfile();
+ start_subfile (n, dirn!=NULL ? dirn : current_subfile->dirname);
+ }
+ break;
+
+ case 'f':
+ case 'F':
+ valu += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ function_stab_type = type;
+
+ within_function = 1;
+ new = push_context (0, valu);
+ new->name = define_symbol (valu, name, desc, type, objfile);
+ break;
+
+ case 'V':
+ case 'v':
+ valu += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ define_symbol (valu, name, desc, type, objfile);
+ break;
+
+ default:
+ define_symbol (valu, name, desc, type, objfile);
+ break;
+ }
+ }
+ break;
+
+ case N_SYM_SE:
+ if (--symfile_depth != 0)
+ start_subfile(pop_subfile(), current_subfile->dirname);
+ break;
+
+ default:
+ complain (&unknown_symtype_complaint,
+ local_hex_string((unsigned long) type));
+ /* FALLTHROUGH */
+ break;
+
+ case N_SYM_CMPLR:
+ break;
+ }
+ previous_stab_code = type;
+}
+
+/* Parse the user's idea of an offset for dynamic linking, into our idea
+ of how to represent it for fast symbol reading. */
+
+static struct section_offsets *
+os9k_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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));
+
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+
+ return section_offsets;
+}
+
+static struct sym_fns os9k_sym_fns =
+{
+ bfd_target_os9k_flavour,
+ os9k_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ os9k_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ os9k_symfile_read, /* sym_read: read a symbol file into symtab */
+ os9k_symfile_finish, /* sym_finish: finished with file, cleanup */
+ os9k_symfile_offsets, /* sym_offsets: parse user's offsets to internal form*/
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_os9kread ()
+{
+ add_symtab_fns(&os9k_sym_fns);
+}
diff --git a/contrib/gdb/gdb/osfsolib.c b/contrib/gdb/gdb/osfsolib.c
new file mode 100644
index 0000000..85afa24
--- /dev/null
+++ b/contrib/gdb/gdb/osfsolib.c
@@ -0,0 +1,955 @@
+/* Handle OSF/1 shared libraries for GDB, the GNU Debugger.
+ Copyright 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* FIXME: Most of this code could be merged with solib.c by using
+ next_link_map_member and xfer_link_map_member in solib.c. */
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <signal.h>
+#include "gdb_string.h"
+#include <fcntl.h>
+
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "target.h"
+#include "frame.h"
+#include "gnu-regex.h"
+#include "inferior.h"
+#include "language.h"
+#include "gdbcmd.h"
+
+#define MAX_PATH_SIZE 1024 /* FIXME: Should be dynamic */
+
+/* When handling shared libraries, GDB has to find out the pathnames
+ of all shared libraries that are currently loaded (to read in their
+ symbols) and where the shared libraries are loaded in memory
+ (to relocate them properly from their prelinked addresses to the
+ current load address).
+
+ Under OSF/1 there are two possibilities to get at this information:
+ 1) Peek around in the runtime loader structures.
+ These are not documented, and they are not defined in the system
+ header files. The definitions below were obtained by experimentation,
+ but they seem stable enough.
+ 2) Use the undocumented libxproc.a library, which contains the
+ equivalent ldr_* routines.
+ This approach is somewhat cleaner, but it requires that the GDB
+ executable is dynamically linked. In addition it requires a
+ NAT_CLIBS= -lxproc -Wl,-expect_unresolved,ldr_process_context
+ linker specification for GDB and all applications that are using
+ libgdb.
+ We will use the peeking approach until it becomes unwieldy. */
+
+#ifndef USE_LDR_ROUTINES
+
+/* Definition of runtime loader structures, found by experimentation. */
+#define RLD_CONTEXT_ADDRESS 0x3ffc0000000
+
+typedef struct
+{
+ CORE_ADDR next;
+ CORE_ADDR previous;
+ CORE_ADDR unknown1;
+ char *module_name;
+ CORE_ADDR modinfo_addr;
+ long module_id;
+ CORE_ADDR unknown2;
+ CORE_ADDR unknown3;
+ long region_count;
+ CORE_ADDR regioninfo_addr;
+} ldr_module_info_t;
+
+typedef struct
+{
+ long unknown1;
+ CORE_ADDR regionname_addr;
+ long protection;
+ CORE_ADDR vaddr;
+ CORE_ADDR mapaddr;
+ long size;
+ long unknown2[5];
+} ldr_region_info_t;
+
+typedef struct
+{
+ CORE_ADDR unknown1;
+ CORE_ADDR unknown2;
+ CORE_ADDR head;
+ CORE_ADDR tail;
+} ldr_context_t;
+
+static ldr_context_t ldr_context;
+
+#else
+
+#include <loader.h>
+static ldr_process_t fake_ldr_process;
+
+/* Called by ldr_* routines to read memory from the current target. */
+
+static int ldr_read_memory PARAMS ((CORE_ADDR, char *, int, int));
+
+static int
+ldr_read_memory (memaddr, myaddr, len, readstring)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int readstring;
+{
+ int result;
+ char *buffer;
+
+ if (readstring)
+ {
+ target_read_string (memaddr, &buffer, len, &result);
+ if (result == 0)
+ strcpy (myaddr, buffer);
+ free (buffer);
+ }
+ else
+ result = target_read_memory (memaddr, myaddr, len);
+
+ if (result != 0)
+ result = -result;
+ return result;
+}
+
+#endif
+
+/* Define our own link_map structure.
+ This will help to share code with solib.c. */
+
+struct link_map {
+ CORE_ADDR l_offset; /* prelink to load address offset */
+ char *l_name; /* full name of loaded object */
+ ldr_module_info_t module_info; /* corresponding module info */
+};
+
+#define LM_OFFSET(so) ((so) -> lm.l_offset)
+#define LM_NAME(so) ((so) -> lm.l_name)
+
+struct so_list {
+ struct so_list *next; /* next structure in linked list */
+ struct link_map lm; /* copy of link map from inferior */
+ struct link_map *lmaddr; /* addr in inferior lm was read from */
+ CORE_ADDR lmend; /* upper addr bound of mapped object */
+ char so_name[MAX_PATH_SIZE]; /* shared object lib name (FIXME) */
+ char symbols_loaded; /* flag: symbols read in yet? */
+ char from_tty; /* flag: print msgs? */
+ struct objfile *objfile; /* objfile for loaded lib */
+ struct section_table *sections;
+ struct section_table *sections_end;
+ struct section_table *textsection;
+ bfd *abfd;
+};
+
+static struct so_list *so_list_head; /* List of known shared objects */
+
+extern int
+fdmatch PARAMS ((int, int)); /* In libiberty */
+
+/* Local function prototypes */
+
+static void
+sharedlibrary_command PARAMS ((char *, int));
+
+static void
+info_sharedlibrary_command PARAMS ((char *, int));
+
+static int
+symbol_add_stub PARAMS ((char *));
+
+static struct so_list *
+find_solib PARAMS ((struct so_list *));
+
+static struct link_map *
+first_link_map_member PARAMS ((void));
+
+static struct link_map *
+next_link_map_member PARAMS ((struct so_list *));
+
+static void
+xfer_link_map_member PARAMS ((struct so_list *, struct link_map *));
+
+static void
+solib_map_sections PARAMS ((struct so_list *));
+
+/*
+
+LOCAL FUNCTION
+
+ solib_map_sections -- open bfd and build sections for shared lib
+
+SYNOPSIS
+
+ static void solib_map_sections (struct so_list *so)
+
+DESCRIPTION
+
+ Given a pointer to one of the shared objects in our list
+ of mapped objects, use the recorded name to open a bfd
+ descriptor for the object, build a section table, and then
+ relocate all the section addresses by the base address at
+ which the shared object was mapped.
+
+FIXMES
+
+ In most (all?) cases the shared object file name recorded in the
+ dynamic linkage tables will be a fully qualified pathname. For
+ cases where it isn't, do we really mimic the systems search
+ mechanism correctly in the below code (particularly the tilde
+ expansion stuff?).
+ */
+
+static void
+solib_map_sections (so)
+ struct so_list *so;
+{
+ char *filename;
+ char *scratch_pathname;
+ int scratch_chan;
+ struct section_table *p;
+ struct cleanup *old_chain;
+ bfd *abfd;
+
+ filename = tilde_expand (so -> so_name);
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
+ &scratch_pathname);
+ if (scratch_chan < 0)
+ {
+ scratch_chan = openp (getenv ("LD_LIBRARY_PATH"), 1, filename,
+ O_RDONLY, 0, &scratch_pathname);
+ }
+ if (scratch_chan < 0)
+ {
+ perror_with_name (filename);
+ }
+ /* Leave scratch_pathname allocated. bfd->name will point to it. */
+
+ abfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+ if (!abfd)
+ {
+ close (scratch_chan);
+ error ("Could not open `%s' as an executable file: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+ /* Leave bfd open, core_xfer_memory and "info files" need it. */
+ so -> abfd = abfd;
+ abfd -> cacheable = true;
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+ if (build_section_table (abfd, &so -> sections, &so -> sections_end))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ bfd_get_filename (exec_bfd), bfd_errmsg (bfd_get_error ()));
+ }
+
+ for (p = so -> sections; p < so -> sections_end; p++)
+ {
+ /* Relocate the section binding addresses as recorded in the shared
+ object's file by the offset to get the address to which the
+ object was actually mapped. */
+ p -> addr += LM_OFFSET (so);
+ p -> endaddr += LM_OFFSET (so);
+ so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
+ if (STREQ (p -> the_bfd_section -> name, ".text"))
+ {
+ so -> textsection = p;
+ }
+ }
+
+ /* Free the file names, close the file now. */
+ do_cleanups (old_chain);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ first_link_map_member -- locate first member in dynamic linker's map
+
+SYNOPSIS
+
+ static struct link_map *first_link_map_member (void)
+
+DESCRIPTION
+
+ Read in a copy of the first member in the inferior's dynamic
+ link map from the inferior's dynamic linker structures, and return
+ a pointer to the copy in our address space.
+*/
+
+static struct link_map *
+first_link_map_member ()
+{
+ struct link_map *lm = NULL;
+ static struct link_map first_lm;
+
+#ifdef USE_LDR_ROUTINES
+ ldr_module_t mod_id = LDR_NULL_MODULE;
+ size_t retsize;
+
+ fake_ldr_process = ldr_core_process ();
+ ldr_set_core_reader (ldr_read_memory);
+ ldr_xdetach (fake_ldr_process);
+ if (ldr_xattach (fake_ldr_process) != 0
+ || ldr_next_module(fake_ldr_process, &mod_id) != 0
+ || mod_id == LDR_NULL_MODULE
+ || ldr_inq_module(fake_ldr_process, mod_id,
+ &first_lm.module_info, sizeof(ldr_module_info_t),
+ &retsize) != 0)
+ return lm;
+#else
+ CORE_ADDR ldr_context_addr;
+
+ if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
+ (char *) &ldr_context_addr,
+ sizeof (CORE_ADDR)) != 0
+ || target_read_memory (ldr_context_addr,
+ (char *) &ldr_context,
+ sizeof (ldr_context_t)) != 0
+ || target_read_memory ((CORE_ADDR) ldr_context.head,
+ (char *) &first_lm.module_info,
+ sizeof (ldr_module_info_t)) != 0)
+ return lm;
+#endif
+
+ lm = &first_lm;
+
+ /* The first entry is for the main program and should be skipped. */
+ lm->l_name = NULL;
+
+ return lm;
+}
+
+static struct link_map *
+next_link_map_member (so_list_ptr)
+ struct so_list *so_list_ptr;
+{
+ struct link_map *lm = NULL;
+ static struct link_map next_lm;
+#ifdef USE_LDR_ROUTINES
+ ldr_module_t mod_id = so_list_ptr->lm.module_info.lmi_modid;
+ size_t retsize;
+
+ if (ldr_next_module(fake_ldr_process, &mod_id) != 0
+ || mod_id == LDR_NULL_MODULE
+ || ldr_inq_module(fake_ldr_process, mod_id,
+ &next_lm.module_info, sizeof(ldr_module_info_t),
+ &retsize) != 0)
+ return lm;
+
+ lm = &next_lm;
+ lm->l_name = lm->module_info.lmi_name;
+#else
+ CORE_ADDR ldr_context_addr;
+
+ /* Reread context in case ldr_context.tail was updated. */
+
+ if (target_read_memory ((CORE_ADDR) RLD_CONTEXT_ADDRESS,
+ (char *) &ldr_context_addr,
+ sizeof (CORE_ADDR)) != 0
+ || target_read_memory (ldr_context_addr,
+ (char *) &ldr_context,
+ sizeof (ldr_context_t)) != 0
+ || so_list_ptr->lm.module_info.modinfo_addr == ldr_context.tail
+ || target_read_memory (so_list_ptr->lm.module_info.next,
+ (char *) &next_lm.module_info,
+ sizeof (ldr_module_info_t)) != 0)
+ return lm;
+
+ lm = &next_lm;
+ lm->l_name = lm->module_info.module_name;
+#endif
+ return lm;
+}
+
+static void
+xfer_link_map_member (so_list_ptr, lm)
+ struct so_list *so_list_ptr;
+ struct link_map *lm;
+{
+ int i;
+ so_list_ptr->lm = *lm;
+
+ /* OSF/1 shared libraries are pre-linked to particular addresses,
+ but the runtime loader may have to relocate them if the
+ address ranges of the libraries used by the target executable clash,
+ or if the target executable is linked with the -taso option.
+ The offset is the difference between the address where the shared
+ library is mapped and the pre-linked address of the shared library.
+
+ FIXME: GDB is currently unable to relocate the shared library
+ sections by different offsets. If sections are relocated by
+ different offsets, put out a warning and use the offset of the
+ first section for all remaining sections. */
+ LM_OFFSET (so_list_ptr) = 0;
+
+ /* There is one entry that has no name (for the inferior executable)
+ since it is not a shared object. */
+ if (LM_NAME (so_list_ptr) != 0)
+ {
+
+#ifdef USE_LDR_ROUTINES
+ int len = strlen (LM_NAME (so_list_ptr) + 1);
+
+ if (len > MAX_PATH_SIZE)
+ len = MAX_PATH_SIZE;
+ strncpy (so_list_ptr->so_name, LM_NAME (so_list_ptr), MAX_PATH_SIZE);
+ so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
+
+ for (i = 0; i < lm->module_info.lmi_nregion; i++)
+ {
+ ldr_region_info_t region_info;
+ size_t retsize;
+ CORE_ADDR region_offset;
+
+ if (ldr_inq_region (fake_ldr_process, lm->module_info.lmi_modid,
+ i, &region_info, sizeof (region_info),
+ &retsize) != 0)
+ break;
+ region_offset = (CORE_ADDR) region_info.lri_mapaddr
+ - (CORE_ADDR) region_info.lri_vaddr;
+ if (i == 0)
+ LM_OFFSET (so_list_ptr) = region_offset;
+ else if (LM_OFFSET (so_list_ptr) != region_offset)
+ warning ("cannot handle shared library relocation for %s (%s)",
+ so_list_ptr->so_name, region_info.lri_name);
+ }
+#else
+ int errcode;
+ char *buffer;
+ target_read_string ((CORE_ADDR) LM_NAME (so_list_ptr), &buffer,
+ MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+ error ("xfer_link_map_member: Can't read pathname for load map: %s\n",
+ safe_strerror (errcode));
+ strncpy (so_list_ptr->so_name, buffer, MAX_PATH_SIZE - 1);
+ free (buffer);
+ so_list_ptr->so_name[MAX_PATH_SIZE - 1] = '\0';
+
+ for (i = 0; i < lm->module_info.region_count; i++)
+ {
+ ldr_region_info_t region_info;
+ CORE_ADDR region_offset;
+
+ if (target_read_memory (lm->module_info.regioninfo_addr
+ + i * sizeof (region_info),
+ (char *) &region_info,
+ sizeof (region_info)) != 0)
+ break;
+ region_offset = region_info.mapaddr - region_info.vaddr;
+ if (i == 0)
+ LM_OFFSET (so_list_ptr) = region_offset;
+ else if (LM_OFFSET (so_list_ptr) != region_offset)
+ {
+ char *region_name;
+ target_read_string (region_info.regionname_addr, &buffer,
+ MAX_PATH_SIZE - 1, &errcode);
+ if (errcode == 0)
+ region_name = buffer;
+ else
+ region_name = "??";
+ warning ("cannot handle shared library relocation for %s (%s)",
+ so_list_ptr->so_name, region_name);
+ free (buffer);
+ }
+ }
+#endif
+
+ solib_map_sections (so_list_ptr);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ find_solib -- step through list of shared objects
+
+SYNOPSIS
+
+ struct so_list *find_solib (struct so_list *so_list_ptr)
+
+DESCRIPTION
+
+ This module contains the routine which finds the names of any
+ loaded "images" in the current process. The argument in must be
+ NULL on the first call, and then the returned value must be passed
+ in on subsequent calls. This provides the capability to "step" down
+ the list of loaded objects. On the last object, a NULL value is
+ returned.
+
+ The arg and return value are "struct link_map" pointers, as defined
+ in <link.h>.
+ */
+
+static struct so_list *
+find_solib (so_list_ptr)
+ struct so_list *so_list_ptr; /* Last lm or NULL for first one */
+{
+ struct so_list *so_list_next = NULL;
+ struct link_map *lm = NULL;
+ struct so_list *new;
+
+ if (so_list_ptr == NULL)
+ {
+ /* We are setting up for a new scan through the loaded images. */
+ if ((so_list_next = so_list_head) == NULL)
+ {
+ /* Find the first link map list member. */
+ lm = first_link_map_member ();
+ }
+ }
+ else
+ {
+ /* We have been called before, and are in the process of walking
+ the shared library list. Advance to the next shared object. */
+ lm = next_link_map_member (so_list_ptr);
+ so_list_next = so_list_ptr -> next;
+ }
+ if ((so_list_next == NULL) && (lm != NULL))
+ {
+ /* Get next link map structure from inferior image and build a local
+ abbreviated load_map structure */
+ new = (struct so_list *) xmalloc (sizeof (struct so_list));
+ memset ((char *) new, 0, sizeof (struct so_list));
+ new -> lmaddr = lm;
+ /* Add the new node as the next node in the list, or as the root
+ node if this is the first one. */
+ if (so_list_ptr != NULL)
+ {
+ so_list_ptr -> next = new;
+ }
+ else
+ {
+ so_list_head = new;
+ }
+ so_list_next = new;
+ xfer_link_map_member (new, lm);
+ }
+ return (so_list_next);
+}
+
+/* A small stub to get us past the arg-passing pinhole of catch_errors. */
+
+static int
+symbol_add_stub (arg)
+ char *arg;
+{
+ register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+
+ so -> objfile = symbol_file_add (so -> so_name, so -> from_tty,
+ so -> textsection -> addr,
+ 0, 0, 0);
+ return (1);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_add -- add a shared library file to the symtab and section list
+
+SYNOPSIS
+
+ void solib_add (char *arg_string, int from_tty,
+ struct target_ops *target)
+
+DESCRIPTION
+
+*/
+
+void
+solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+
+ /* Last shared library that we read. */
+ struct so_list *so_last = NULL;
+
+ char *re_err;
+ int count;
+ int old;
+
+ if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+ {
+ error ("Invalid regexp: %s", re_err);
+ }
+
+
+ /* Add the shared library sections to the section table of the
+ specified target, if any. */
+ if (target)
+ {
+ /* Count how many new section_table entries there are. */
+ so = NULL;
+ count = 0;
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ count += so -> sections_end - so -> sections;
+ }
+ }
+
+ if (count)
+ {
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ /* Reallocate the target's section table including the new size. */
+ if (target -> to_sections)
+ {
+ old = target -> to_sections_end - target -> to_sections;
+ target -> to_sections = (struct section_table *)
+ xrealloc ((char *)target -> to_sections,
+ (sizeof (struct section_table)) * (count + old));
+ }
+ else
+ {
+ old = 0;
+ target -> to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table)) * count);
+ }
+ target -> to_sections_end = target -> to_sections + (count + old);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* Add these section table entries to the target's table. */
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ count = so -> sections_end - so -> sections;
+ memcpy ((char *) (target -> to_sections + old),
+ so -> sections,
+ (sizeof (struct section_table)) * count);
+ old += count;
+ }
+ }
+ }
+ }
+
+ /* Now add the symbol files. */
+ so = NULL;
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0] && re_exec (so -> so_name))
+ {
+ so -> from_tty = from_tty;
+ if (so -> symbols_loaded)
+ {
+ if (from_tty)
+ {
+ printf_unfiltered ("Symbols already loaded for %s\n", so -> so_name);
+ }
+ }
+ else if (catch_errors
+ (symbol_add_stub, (char *) so,
+ "Error while reading shared library symbols:\n",
+ RETURN_MASK_ALL))
+ {
+ so_last = so;
+ so -> symbols_loaded = 1;
+ }
+ }
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (so_last)
+ reinit_frame_cache ();
+}
+
+/*
+
+LOCAL FUNCTION
+
+ info_sharedlibrary_command -- code for "info sharedlibrary"
+
+SYNOPSIS
+
+ static void info_sharedlibrary_command ()
+
+DESCRIPTION
+
+ Walk through the shared library list and print information
+ about each attached library.
+*/
+
+static void
+info_sharedlibrary_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+ int header_done = 0;
+
+ if (exec_bfd == NULL)
+ {
+ printf_unfiltered ("No exec file.\n");
+ return;
+ }
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ unsigned long txt_start = 0;
+ unsigned long txt_end = 0;
+
+ if (!header_done)
+ {
+ printf_unfiltered("%-20s%-20s%-12s%s\n", "From", "To", "Syms Read",
+ "Shared Object Library");
+ header_done++;
+ }
+ if (so -> textsection)
+ {
+ txt_start = (unsigned long) so -> textsection -> addr;
+ txt_end = (unsigned long) so -> textsection -> endaddr;
+ }
+ printf_unfiltered ("%-20s", local_hex_string_custom (txt_start, "08l"));
+ printf_unfiltered ("%-20s", local_hex_string_custom (txt_end, "08l"));
+ printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
+ printf_unfiltered ("%s\n", so -> so_name);
+ }
+ }
+ if (so_list_head == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_address -- check to see if an address is in a shared lib
+
+SYNOPSIS
+
+ char *solib_address (CORE_ADDR address)
+
+DESCRIPTION
+
+ Provides a hook for other gdb routines to discover whether or
+ not a particular address is within the mapped address space of
+ a shared library. Any address between the base mapping address
+ and the first address beyond the end of the last mapping, is
+ considered to be within the shared library address space, for
+ our purposes.
+
+ For example, this routine is called at one point to disable
+ breakpoints which are in shared libraries that are not currently
+ mapped in.
+ */
+
+char *
+solib_address (address)
+ CORE_ADDR address;
+{
+ register struct so_list *so = 0; /* link map state variable */
+
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0] && so -> textsection)
+ {
+ if ((address >= (CORE_ADDR) so -> textsection -> addr) &&
+ (address < (CORE_ADDR) so -> textsection -> endaddr))
+ return (so->so_name);
+ }
+ }
+ return (0);
+}
+
+/* Called by free_all_symtabs */
+
+void
+clear_solib()
+{
+ struct so_list *next;
+ char *bfd_filename;
+
+ while (so_list_head)
+ {
+ if (so_list_head -> sections)
+ {
+ free ((PTR)so_list_head -> sections);
+ }
+ if (so_list_head -> abfd)
+ {
+ bfd_filename = bfd_get_filename (so_list_head -> abfd);
+ if (!bfd_close (so_list_head -> abfd))
+ warning ("cannot close \"%s\": %s",
+ bfd_filename, bfd_errmsg (bfd_get_error ()));
+ }
+ else
+ /* This happens for the executable on SVR4. */
+ bfd_filename = NULL;
+
+ next = so_list_head -> next;
+ if (bfd_filename)
+ free ((PTR)bfd_filename);
+ free ((PTR)so_list_head);
+ so_list_head = next;
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_create_inferior_hook -- shared library startup support
+
+SYNOPSIS
+
+ void solib_create_inferior_hook()
+
+DESCRIPTION
+
+ When gdb starts up the inferior, it nurses it along (through the
+ shell) until it is ready to execute it's first instruction. At this
+ point, this function gets called via expansion of the macro
+ SOLIB_CREATE_INFERIOR_HOOK.
+ For a statically bound executable, this first instruction is the
+ one at "_start", or a similar text label. No further processing is
+ needed in that case.
+ For a dynamically bound executable, this first instruction is somewhere
+ in the rld, and the actual user executable is not yet mapped in.
+ We continue the inferior again, rld then maps in the actual user
+ executable and any needed shared libraries and then sends
+ itself a SIGTRAP.
+ At that point we discover the names of all shared libraries and
+ read their symbols in.
+
+FIXME
+
+ This code does not properly handle hitting breakpoints which the
+ user might have set in the rld itself. Proper handling would have
+ to check if the SIGTRAP happened due to a kill call.
+
+ Also, what if child has exit()ed? Must exit loop somehow.
+ */
+
+void
+solib_create_inferior_hook()
+{
+
+ /* Nothing to do for statically bound executables. */
+
+ if (symfile_objfile == NULL
+ || symfile_objfile->obfd == NULL
+ || ((bfd_get_file_flags (symfile_objfile->obfd) & DYNAMIC) == 0))
+ return;
+
+ /* Now run the target. It will eventually get a SIGTRAP, at
+ which point all of the libraries will have been mapped in and we
+ can go groveling around in the rld structures to find
+ out what we need to know about them. */
+
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ stop_signal = TARGET_SIGNAL_0;
+ do
+ {
+ target_resume (-1, 0, stop_signal);
+ wait_for_inferior ();
+ }
+ while (stop_signal != TARGET_SIGNAL_TRAP);
+
+ /* solib_add will call reinit_frame_cache.
+ But we are stopped in the runtime loader and we do not have symbols
+ for the runtime loader. So heuristic_proc_start will be called
+ and will put out an annoying warning.
+ Delaying the resetting of stop_soon_quietly until after symbol loading
+ suppresses the warning. */
+ if (auto_solib_add)
+ solib_add ((char *) 0, 0, (struct target_ops *) 0);
+ stop_soon_quietly = 0;
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ sharedlibrary_command -- handle command to explicitly add library
+
+SYNOPSIS
+
+ static void sharedlibrary_command (char *args, int from_tty)
+
+DESCRIPTION
+
+*/
+
+static void
+sharedlibrary_command (args, from_tty)
+char *args;
+int from_tty;
+{
+ dont_repeat ();
+ solib_add (args, from_tty, (struct target_ops *) 0);
+}
+
+void
+_initialize_solib()
+{
+ add_com ("sharedlibrary", class_files, sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", info_sharedlibrary_command,
+ "Status of loaded shared object libraries.");
+
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded. Otherwise, symbols\n\
+must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+}
diff --git a/contrib/gdb/gdb/parse.c b/contrib/gdb/gdb/parse.c
new file mode 100644
index 0000000..92f9465
--- /dev/null
+++ b/contrib/gdb/gdb/parse.c
@@ -0,0 +1,1013 @@
+/* Parse expressions for GDB.
+ 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.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Parse an expression from text in a string,
+ and return the result as a struct expression pointer.
+ That structure contains arithmetic operations in reverse polish,
+ with constants represented by operations that are followed by special data.
+ See expression.h for the details of the format.
+ What is important here is that it can be built up sequentially
+ during the process of parsing; the lower levels of the tree always
+ come first in the result. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "frame.h"
+#include "expression.h"
+#include "value.h"
+#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));
+
+static void
+prefixify_expression PARAMS ((struct expression *));
+
+static int
+length_of_subexp PARAMS ((struct expression *, int));
+
+static void
+prefixify_subexp PARAMS ((struct expression *, struct expression *, int, int));
+
+/* Data structure for saving values of arglist_len for function calls whose
+ arguments contain other function calls. */
+
+struct funcall
+ {
+ struct funcall *next;
+ int arglist_len;
+ };
+
+static struct funcall *funcall_chain;
+
+/* Assign machine-independent names to certain registers
+ (unless overridden by the REGISTER_NAMES table) */
+
+#ifdef NO_STD_REGS
+unsigned num_std_regs = 0;
+struct std_regs std_regs[1];
+#else
+struct std_regs std_regs[] = {
+
+#ifdef PC_REGNUM
+ { "pc", PC_REGNUM },
+#endif
+#ifdef FP_REGNUM
+ { "fp", FP_REGNUM },
+#endif
+#ifdef SP_REGNUM
+ { "sp", SP_REGNUM },
+#endif
+#ifdef PS_REGNUM
+ { "ps", PS_REGNUM },
+#endif
+
+};
+
+unsigned num_std_regs = (sizeof std_regs / sizeof std_regs[0]);
+
+#endif
+
+
+/* Begin counting arguments for a function call,
+ saving the data about any containing call. */
+
+void
+start_arglist ()
+{
+ register struct funcall *new;
+
+ new = (struct funcall *) xmalloc (sizeof (struct funcall));
+ new->next = funcall_chain;
+ new->arglist_len = arglist_len;
+ arglist_len = 0;
+ funcall_chain = new;
+}
+
+/* Return the number of arguments in a function call just terminated,
+ and restore the data for the containing function call. */
+
+int
+end_arglist ()
+{
+ register int val = arglist_len;
+ register struct funcall *call = funcall_chain;
+ funcall_chain = call->next;
+ arglist_len = call->arglist_len;
+ free ((PTR)call);
+ return val;
+}
+
+/* Free everything in the funcall chain.
+ Used when there is an error inside parsing. */
+
+static void
+free_funcalls ()
+{
+ register struct funcall *call, *next;
+
+ for (call = funcall_chain; call; call = next)
+ {
+ next = call->next;
+ free ((PTR)call);
+ }
+}
+
+/* This page contains the functions for adding data to the struct expression
+ being constructed. */
+
+/* Add one element to the end of the expression. */
+
+/* To avoid a bug in the Sun 4 compiler, we pass things that can fit into
+ a register through here */
+
+void
+write_exp_elt (expelt)
+ union exp_element expelt;
+{
+ if (expout_ptr >= expout_size)
+ {
+ expout_size *= 2;
+ expout = (struct expression *)
+ xrealloc ((char *) expout, sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size));
+ }
+ expout->elts[expout_ptr++] = expelt;
+}
+
+void
+write_exp_elt_opcode (expelt)
+ enum exp_opcode expelt;
+{
+ union exp_element tmp;
+
+ tmp.opcode = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_sym (expelt)
+ struct symbol *expelt;
+{
+ union exp_element tmp;
+
+ tmp.symbol = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_block (b)
+ struct block *b;
+{
+ union exp_element tmp;
+ tmp.block = b;
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_longcst (expelt)
+ LONGEST expelt;
+{
+ union exp_element tmp;
+
+ tmp.longconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_dblcst (expelt)
+ DOUBLEST expelt;
+{
+ union exp_element tmp;
+
+ tmp.doubleconst = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_type (expelt)
+ struct type *expelt;
+{
+ union exp_element tmp;
+
+ tmp.type = expelt;
+
+ write_exp_elt (tmp);
+}
+
+void
+write_exp_elt_intern (expelt)
+ struct internalvar *expelt;
+{
+ union exp_element tmp;
+
+ tmp.internalvar = expelt;
+
+ write_exp_elt (tmp);
+}
+
+/* Add a string constant to the end of the expression.
+
+ String constants are stored by first writing an expression element
+ that contains the length of the string, then stuffing the string
+ constant itself into however many expression elements are needed
+ to hold it, and then writing another expression element that contains
+ the length of the string. I.E. an expression element at each end of
+ the string records the string length, so you can skip over the
+ expression elements containing the actual string bytes from either
+ end of the string. Note that this also allows gdb to handle
+ strings with embedded null bytes, as is required for some languages.
+
+ Don't be fooled by the fact that the string is null byte terminated,
+ this is strictly for the convenience of debugging gdb itself. Gdb
+ Gdb does not depend up the string being null terminated, since the
+ actual length is recorded in expression elements at each end of the
+ string. The null byte is taken into consideration when computing how
+ many expression elements are required to hold the string constant, of
+ course. */
+
+
+void
+write_exp_string (str)
+ struct stoken str;
+{
+ register int len = str.length;
+ register int lenelt;
+ register char *strdata;
+
+ /* Compute the number of expression elements required to hold the string
+ (including a null byte terminator), along with one expression element
+ at each end to record the actual string length (not including the
+ null byte terminator). */
+
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len + 1);
+
+ /* Ensure that we have enough available expression elements to store
+ everything. */
+
+ if ((expout_ptr + lenelt) >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
+ expout = (struct expression *)
+ xrealloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ /* Write the leading length expression element (which advances the current
+ expression element index), then write the string constant followed by a
+ terminating null byte, and then write the trailing length expression
+ element. */
+
+ write_exp_elt_longcst ((LONGEST) len);
+ strdata = (char *) &expout->elts[expout_ptr];
+ memcpy (strdata, str.ptr, len);
+ *(strdata + len) = '\0';
+ expout_ptr += lenelt - 2;
+ write_exp_elt_longcst ((LONGEST) len);
+}
+
+/* Add a bitstring constant to the end of the expression.
+
+ Bitstring constants are stored by first writing an expression element
+ that contains the length of the bitstring (in bits), then stuffing the
+ bitstring constant itself into however many expression elements are
+ needed to hold it, and then writing another expression element that
+ contains the length of the bitstring. I.E. an expression element at
+ each end of the bitstring records the bitstring length, so you can skip
+ over the expression elements containing the actual bitstring bytes from
+ either end of the bitstring. */
+
+void
+write_exp_bitstring (str)
+ struct stoken str;
+{
+ register int bits = str.length; /* length in bits */
+ register int len = (bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ register int lenelt;
+ register char *strdata;
+
+ /* Compute the number of expression elements required to hold the bitstring,
+ along with one expression element at each end to record the actual
+ bitstring length in bits. */
+
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len);
+
+ /* Ensure that we have enough available expression elements to store
+ everything. */
+
+ if ((expout_ptr + lenelt) >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
+ expout = (struct expression *)
+ xrealloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ /* Write the leading length expression element (which advances the current
+ expression element index), then write the bitstring constant, and then
+ write the trailing length expression element. */
+
+ write_exp_elt_longcst ((LONGEST) bits);
+ strdata = (char *) &expout->elts[expout_ptr];
+ memcpy (strdata, str.ptr, len);
+ expout_ptr += lenelt - 2;
+ write_exp_elt_longcst ((LONGEST) bits);
+}
+
+/* Add the appropriate elements for a minimal symbol to the end of
+ the expression. The rationale behind passing in text_symbol_type and
+ data_symbol_type was so that Modula-2 could pass in WORD for
+ data_symbol_type. Perhaps it still is useful to have those types vary
+ based on the language, but they no longer have names like "int", so
+ the initial rationale is gone. */
+
+static struct type *msym_text_symbol_type;
+static struct type *msym_data_symbol_type;
+static struct type *msym_unknown_symbol_type;
+
+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 (lookup_pointer_type (builtin_type_void));
+ 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 (msym_text_symbol_type);
+ break;
+
+ case mst_data:
+ case mst_file_data:
+ case mst_bss:
+ case mst_file_bss:
+ write_exp_elt_type (msym_data_symbol_type);
+ break;
+
+ default:
+ write_exp_elt_type (msym_unknown_symbol_type);
+ break;
+ }
+ write_exp_elt_opcode (UNOP_MEMVAL);
+}
+
+/* Recognize tokens that start with '$'. These include:
+
+ $regname A native register name or a "standard
+ register name".
+
+ $variable A convenience variable with a name chosen
+ by the user.
+
+ $digits Value history with index <digits>, starting
+ from the first value which has index 1.
+
+ $$digits Value history with index <digits> relative
+ to the last value. I.E. $$0 is the last
+ value, $$1 is the one previous to that, $$2
+ is the one previous to $$1, etc.
+
+ $ | $0 | $$0 The last value in the value history.
+
+ $$ An abbreviation for the second to the last
+ value in the value history, I.E. $$1
+
+ */
+
+void
+write_dollar_variable (str)
+ struct stoken str;
+{
+ /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+ and $$digits (equivalent to $<-digits> if you could type that). */
+
+ int negate = 0;
+ int i = 1;
+ /* Double dollar means negate the number and add -1 as well.
+ Thus $$ alone means -1. */
+ if (str.length >= 2 && str.ptr[1] == '$')
+ {
+ negate = 1;
+ i = 2;
+ }
+ if (i == str.length)
+ {
+ /* Just dollars (one or two) */
+ i = - negate;
+ goto handle_last;
+ }
+ /* Is the rest of the token digits? */
+ for (; i < str.length; i++)
+ if (!(str.ptr[i] >= '0' && str.ptr[i] <= '9'))
+ break;
+ if (i == str.length)
+ {
+ i = atoi (str.ptr + 1 + negate);
+ if (negate)
+ i = - i;
+ goto handle_last;
+ }
+
+ /* Handle tokens that refer to machine registers:
+ $ followed by a register name. */
+ for (i = 0; i < NUM_REGS; i++)
+ if (str.length - 1 == strlen (reg_names[i])
+ && STREQN (str.ptr + 1, reg_names[i], str.length - 1))
+ {
+ goto handle_register;
+ }
+ for (i = 0; i < num_std_regs; i++)
+ if (str.length - 1 == strlen (std_regs[i].name)
+ && STREQN (str.ptr + 1, std_regs[i].name, str.length - 1))
+ {
+ i = std_regs[i].regnum;
+ goto handle_register;
+ }
+
+ /* Any other names starting in $ are debugger internal variables. */
+
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ write_exp_elt_intern (lookup_internalvar (copy_name (str) + 1));
+ write_exp_elt_opcode (OP_INTERNALVAR);
+ return;
+ handle_last:
+ write_exp_elt_opcode (OP_LAST);
+ write_exp_elt_longcst ((LONGEST) i);
+ write_exp_elt_opcode (OP_LAST);
+ return;
+ handle_register:
+ write_exp_elt_opcode (OP_REGISTER);
+ write_exp_elt_longcst (i);
+ write_exp_elt_opcode (OP_REGISTER);
+ return;
+}
+
+/* Return a null-terminated temporary copy of the name
+ of a string token. */
+
+char *
+copy_name (token)
+ struct stoken token;
+{
+ memcpy (namecopy, token.ptr, token.length);
+ namecopy[token.length] = 0;
+ return namecopy;
+}
+
+/* Reverse an expression from suffix form (in which it is constructed)
+ to prefix form (in which we can conveniently print or execute it). */
+
+static void
+prefixify_expression (expr)
+ register struct expression *expr;
+{
+ register int len =
+ sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts);
+ register struct expression *temp;
+ register int inpos = expr->nelts, outpos = 0;
+
+ temp = (struct expression *) alloca (len);
+
+ /* Copy the original expression into temp. */
+ memcpy (temp, expr, len);
+
+ prefixify_subexp (temp, expr, inpos, outpos);
+}
+
+/* Return the number of exp_elements in the subexpression of EXPR
+ whose last exp_element is at index ENDPOS - 1 in EXPR. */
+
+static int
+length_of_subexp (expr, endpos)
+ register struct expression *expr;
+ register int endpos;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+
+ if (endpos < 1)
+ error ("?error in length_of_subexp");
+
+ i = (int) expr->elts[endpos - 1].opcode;
+
+ switch (i)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ case OP_VAR_VALUE:
+ oplen = 4;
+ break;
+
+ case OP_TYPE:
+ case OP_BOOL:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_COMPLEX:
+ oplen = 1;
+ args = 2;
+ break;
+
+ case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
+ oplen = 3;
+ args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
+ break;
+
+ case UNOP_MAX:
+ case UNOP_MIN:
+ oplen = 3;
+ break;
+
+ case BINOP_VAL:
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case UNOP_ABS:
+ case UNOP_CAP:
+ case UNOP_CHR:
+ case UNOP_FLOAT:
+ case UNOP_HIGH:
+ case UNOP_ODD:
+ case UNOP_ORD:
+ case UNOP_TRUNC:
+ oplen = 1;
+ args = 1;
+ break;
+
+ case OP_LABELED:
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ args = 1;
+ /* fall through */
+ case OP_M2_STRING:
+ case OP_STRING:
+ case OP_NAME:
+ case OP_EXPRSTRING:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_BITSTRING:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = (oplen + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen);
+ break;
+
+ case OP_ARRAY:
+ oplen = 4;
+ args = longest_to_int (expr->elts[endpos - 2].longconst);
+ args -= longest_to_int (expr->elts[endpos - 3].longconst);
+ args += 1;
+ break;
+
+ case TERNOP_COND:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ args = 3;
+ break;
+
+ /* Modula-2 */
+ case MULTI_SUBSCRIPT:
+ oplen = 3;
+ args = 1 + longest_to_int (expr->elts[endpos- 2].longconst);
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + (i < (int) BINOP_END);
+ }
+
+ while (args > 0)
+ {
+ oplen += length_of_subexp (expr, endpos - oplen);
+ args--;
+ }
+
+ return oplen;
+}
+
+/* Copy the subexpression ending just before index INEND in INEXPR
+ into OUTEXPR, starting at index OUTBEG.
+ In the process, convert it from suffix to prefix form. */
+
+static void
+prefixify_subexp (inexpr, outexpr, inend, outbeg)
+ register struct expression *inexpr;
+ struct expression *outexpr;
+ register int inend;
+ int outbeg;
+{
+ register int oplen = 1;
+ register int args = 0;
+ register int i;
+ int *arglens;
+ enum exp_opcode opcode;
+
+ /* Compute how long the last operation is (in OPLEN),
+ and also how many preceding subexpressions serve as
+ arguments for it (in ARGS). */
+
+ opcode = inexpr->elts[inend - 1].opcode;
+ switch (opcode)
+ {
+ /* C++ */
+ case OP_SCOPE:
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_LONG:
+ case OP_DOUBLE:
+ case OP_VAR_VALUE:
+ oplen = 4;
+ break;
+
+ case OP_TYPE:
+ case OP_BOOL:
+ case OP_LAST:
+ case OP_REGISTER:
+ case OP_INTERNALVAR:
+ oplen = 3;
+ break;
+
+ case OP_COMPLEX:
+ oplen = 1;
+ args = 2;
+ break;
+
+ case OP_FUNCALL:
+ case OP_F77_UNDETERMINED_ARGLIST:
+ oplen = 3;
+ args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
+ break;
+
+ case UNOP_MIN:
+ case UNOP_MAX:
+ oplen = 3;
+ break;
+
+ case UNOP_CAST:
+ case UNOP_MEMVAL:
+ oplen = 3;
+ args = 1;
+ break;
+
+ case UNOP_ABS:
+ case UNOP_CAP:
+ case UNOP_CHR:
+ case UNOP_FLOAT:
+ case UNOP_HIGH:
+ case UNOP_ODD:
+ case UNOP_ORD:
+ case UNOP_TRUNC:
+ oplen=1;
+ args=1;
+ break;
+
+ case STRUCTOP_STRUCT:
+ case STRUCTOP_PTR:
+ case OP_LABELED:
+ args = 1;
+ /* fall through */
+ case OP_M2_STRING:
+ case OP_STRING:
+ case OP_NAME:
+ case OP_EXPRSTRING:
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_BITSTRING:
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = (oplen + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen);
+ break;
+
+ case OP_ARRAY:
+ oplen = 4;
+ args = longest_to_int (inexpr->elts[inend - 2].longconst);
+ args -= longest_to_int (inexpr->elts[inend - 3].longconst);
+ args += 1;
+ break;
+
+ case TERNOP_COND:
+ case TERNOP_SLICE:
+ case TERNOP_SLICE_COUNT:
+ args = 3;
+ break;
+
+ case BINOP_ASSIGN_MODIFY:
+ oplen = 3;
+ args = 2;
+ break;
+
+ /* Modula-2 */
+ case MULTI_SUBSCRIPT:
+ oplen = 3;
+ args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
+ break;
+
+ /* C++ */
+ case OP_THIS:
+ oplen = 2;
+ break;
+
+ default:
+ args = 1 + ((int) opcode < (int) BINOP_END);
+ }
+
+ /* Copy the final operator itself, from the end of the input
+ to the beginning of the output. */
+ inend -= oplen;
+ memcpy (&outexpr->elts[outbeg], &inexpr->elts[inend],
+ EXP_ELEM_TO_BYTES (oplen));
+ outbeg += oplen;
+
+ /* Find the lengths of the arg subexpressions. */
+ arglens = (int *) alloca (args * sizeof (int));
+ for (i = args - 1; i >= 0; i--)
+ {
+ oplen = length_of_subexp (inexpr, inend);
+ arglens[i] = oplen;
+ inend -= oplen;
+ }
+
+ /* Now copy each subexpression, preserving the order of
+ the subexpressions, but prefixifying each one.
+ In this loop, inend starts at the beginning of
+ the expression this level is working on
+ and marches forward over the arguments.
+ outbeg does similarly in the output. */
+ for (i = 0; i < args; i++)
+ {
+ oplen = arglens[i];
+ inend += oplen;
+ prefixify_subexp (inexpr, outexpr, inend, outbeg);
+ outbeg += oplen;
+ }
+}
+
+/* This page contains the two entry points to this file. */
+
+/* Read an expression from the string *STRINGPTR points to,
+ parse it, and return a pointer to a struct expression that we malloc.
+ Use block BLOCK as the lexical context for variable names;
+ if BLOCK is zero, use the block of the selected stack frame.
+ Meanwhile, advance *STRINGPTR to point after the expression,
+ at the first nonwhite character that is not part of the expression
+ (possibly a null character).
+
+ If COMMA is nonzero, stop if a comma is reached. */
+
+struct expression *
+parse_exp_1 (stringptr, block, comma)
+ char **stringptr;
+ struct block *block;
+ int comma;
+{
+ struct cleanup *old_chain;
+
+ lexptr = *stringptr;
+
+ paren_depth = 0;
+ type_stack_depth = 0;
+
+ comma_terminates = comma;
+
+ if (lexptr == 0 || *lexptr == 0)
+ error_no_arg ("expression to compute");
+
+ old_chain = make_cleanup (free_funcalls, 0);
+ funcall_chain = 0;
+
+ expression_context_block = block ? block : get_selected_block ();
+
+ namecopy = (char *) alloca (strlen (lexptr) + 1);
+ expout_size = 10;
+ expout_ptr = 0;
+ expout = (struct expression *)
+ xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
+ expout->language_defn = current_language;
+ make_cleanup (free_current_contents, &expout);
+
+ if (current_language->la_parser ())
+ current_language->la_error (NULL);
+
+ discard_cleanups (old_chain);
+
+ /* Record the actual number of expression elements, and then
+ reallocate the expression memory so that we free up any
+ excess elements. */
+
+ expout->nelts = expout_ptr;
+ expout = (struct expression *)
+ xrealloc ((char *) expout,
+ sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_ptr));;
+
+ /* Convert expression from postfix form as generated by yacc
+ parser, to a prefix form. */
+
+ DUMP_EXPRESSION (expout, gdb_stdout, "before conversion to prefix form");
+ prefixify_expression (expout);
+ DUMP_EXPRESSION (expout, gdb_stdout, "after conversion to prefix form");
+
+ *stringptr = lexptr;
+ return expout;
+}
+
+/* Parse STRING as an expression, and complain if this fails
+ to use up all of the contents of STRING. */
+
+struct expression *
+parse_expression (string)
+ char *string;
+{
+ register struct expression *exp;
+ exp = parse_exp_1 (&string, 0, 0);
+ if (*string)
+ error ("Junk after end of expression.");
+ return exp;
+}
+
+/* Stuff for maintaining a stack of types. Currently just used by C, but
+ probably useful for any language which declares its types "backwards". */
+
+void
+push_type (tp)
+ enum type_pieces tp;
+{
+ if (type_stack_depth == type_stack_size)
+ {
+ type_stack_size *= 2;
+ type_stack = (union type_stack_elt *)
+ xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
+ }
+ type_stack[type_stack_depth++].piece = tp;
+}
+
+void
+push_type_int (n)
+ int n;
+{
+ if (type_stack_depth == type_stack_size)
+ {
+ type_stack_size *= 2;
+ type_stack = (union type_stack_elt *)
+ xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
+ }
+ type_stack[type_stack_depth++].int_val = n;
+}
+
+enum type_pieces
+pop_type ()
+{
+ if (type_stack_depth)
+ return type_stack[--type_stack_depth].piece;
+ return tp_end;
+}
+
+int
+pop_type_int ()
+{
+ if (type_stack_depth)
+ return type_stack[--type_stack_depth].int_val;
+ /* "Can't happen". */
+ return 0;
+}
+
+/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
+ as modified by all the stuff on the stack. */
+struct type *
+follow_types (follow_type)
+ struct type *follow_type;
+{
+ int done = 0;
+ int array_size;
+ struct type *range_type;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = pop_type_int ();
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_int, 0,
+ array_size >= 0 ? array_size - 1 : 0);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ if (array_size < 0)
+ TYPE_ARRAY_UPPER_BOUND_TYPE(follow_type)
+ = BOUND_CANNOT_BE_DETERMINED;
+ break;
+ case tp_function:
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ return follow_type;
+}
+
+void
+_initialize_parse ()
+{
+ type_stack_size = 80;
+ type_stack_depth = 0;
+ type_stack = (union type_stack_elt *)
+ xmalloc (type_stack_size * sizeof (*type_stack));
+
+ msym_text_symbol_type =
+ init_type (TYPE_CODE_FUNC, 1, 0, "<text variable, no debug info>", NULL);
+ TYPE_TARGET_TYPE (msym_text_symbol_type) = builtin_type_int;
+ msym_data_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<data variable, no debug info>", NULL);
+ msym_unknown_symbol_type =
+ init_type (TYPE_CODE_INT, 1, 0,
+ "<variable (not text or data), no debug info>",
+ NULL);
+}
diff --git a/contrib/gdb/gdb/parser-defs.h b/contrib/gdb/gdb/parser-defs.h
new file mode 100644
index 0000000..60c12e6
--- /dev/null
+++ b/contrib/gdb/gdb/parser-defs.h
@@ -0,0 +1,191 @@
+/* Parser definitions for GDB.
+ Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+ Modified from expread.y by the Department of Computer Science at the
+ State University of New York at Buffalo.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (PARSER_DEFS_H)
+#define PARSER_DEFS_H 1
+
+struct std_regs {
+ char *name;
+ int regnum;
+};
+
+extern struct std_regs std_regs[];
+extern unsigned num_std_regs;
+
+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. */
+
+extern struct block *expression_context_block;
+
+/* The innermost context required by the stack and register variables
+ we've encountered so far. */
+extern struct block *innermost_block;
+
+/* 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. */
+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. */
+
+struct stoken
+ {
+ /* Pointer to first byte of char-string or first bit of bit-string */
+ char *ptr;
+ /* Length of string in bytes for char-string or bits for bit-string */
+ int length;
+ };
+
+struct ttype
+ {
+ struct stoken stoken;
+ struct type *type;
+ };
+
+struct symtoken
+ {
+ struct stoken stoken;
+ struct symbol *sym;
+ int is_a_field_of_this;
+ };
+
+/* For parsing of complicated types.
+ An array should be preceded in the list by the size of the array. */
+enum type_pieces
+ {tp_end = -1, tp_pointer, tp_reference, tp_array, tp_function};
+/* The stack can contain either an enum type_pieces or an int. */
+union type_stack_elt {
+ enum type_pieces piece;
+ int int_val;
+};
+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_opcode PARAMS ((enum exp_opcode));
+
+extern void write_exp_elt_sym PARAMS ((struct symbol *));
+
+extern void write_exp_elt_longcst PARAMS ((LONGEST));
+
+extern void write_exp_elt_dblcst PARAMS ((DOUBLEST));
+
+extern void write_exp_elt_type PARAMS ((struct type *));
+
+extern void write_exp_elt_intern PARAMS ((struct internalvar *));
+
+extern void write_exp_string 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 write_dollar_variable PARAMS ((struct stoken str));
+
+extern void
+start_arglist PARAMS ((void));
+
+extern int
+end_arglist PARAMS ((void));
+
+extern char *
+copy_name PARAMS ((struct stoken));
+
+extern void
+push_type PARAMS ((enum type_pieces));
+
+extern void
+push_type_int PARAMS ((int));
+
+extern enum type_pieces
+pop_type PARAMS ((void));
+
+extern int
+pop_type_int PARAMS ((void));
+
+extern struct type *follow_types PARAMS ((struct type *));
+
+/* During parsing of a C expression, the pointer to the next character
+ is in this variable. */
+
+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.
+
+ When it is necessary to pass a name to a function that expects
+ a null-terminated string, the substring is copied out
+ into a block of storage that namecopy points to.
+
+ namecopy is allocated once, guaranteed big enough, for each parsing. */
+
+extern char *namecopy;
+
+/* Current depth in parentheses within the expression. */
+
+extern int paren_depth;
+
+/* Nonzero means stop parsing on first comma (if not within parentheses). */
+
+extern int comma_terminates;
+
+/* These codes indicate operator precedences for expression printing,
+ least tightly binding first. */
+/* Adding 1 to a precedence value is done for binary operators,
+ on the operand which is more tightly bound, so that operators
+ of equal precedence within that operand will get parentheses. */
+/* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
+ they are used as the "surrounding precedence" to force
+ various kinds of things to be parenthesized. */
+enum precedence
+{ PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_LOGICAL_OR,
+ PREC_LOGICAL_AND, PREC_BITWISE_IOR, PREC_BITWISE_AND, PREC_BITWISE_XOR,
+ PREC_EQUAL, PREC_ORDER, PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
+ PREC_HYPER, PREC_PREFIX, PREC_SUFFIX, PREC_BUILTIN_FUNCTION };
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+
+struct op_print
+{
+ char *string;
+ enum exp_opcode opcode;
+ /* Precedence of operator. These values are used only by comparisons. */
+ enum precedence precedence;
+
+ /* For a binary operator: 1 iff right associate.
+ For a unary operator: 1 iff postfix. */
+ int right_assoc;
+};
+
+#endif /* PARSER_DEFS_H */
diff --git a/contrib/gdb/gdb/partial-stab.h b/contrib/gdb/gdb/partial-stab.h
new file mode 100644
index 0000000..d006809
--- /dev/null
+++ b/contrib/gdb/gdb/partial-stab.h
@@ -0,0 +1,774 @@
+/* Shared code to pre-read a stab (dbx-style), when building a psymtab.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The following need to be defined:
+ SET_NAMESTRING() --Set namestring to name of symbol.
+ CUR_SYMBOL_TYPE --Type code of current symbol.
+ CUR_SYMBOL_VALUE --Value field of current symbol. May be adjusted here.
+ namestring - variable pointing to the name of the stab.
+ section_offsets - variable pointing to the section offsets.
+ pst - the partial symbol table being built.
+
+ psymtab_include_list, includes_used, includes_allocated - list of include
+ file names (N_SOL) seen so far.
+ dependency_list, dependencies_used, dependencies_allocated - list of
+ N_EXCL stabs seen so far.
+
+ END_PSYMTAB -- end a partial symbol table.
+ START_PSYMTAB -- start a partial symbol table.
+ */
+
+/* End of macro definitions, now let's handle them symbols! */
+
+ switch (CUR_SYMBOL_TYPE)
+ {
+ char *p;
+ /*
+ * Standard, external, non-debugger, symbols
+ */
+
+ case N_TEXT | N_EXT:
+ case N_NBTEXT | N_EXT:
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ goto record_it;
+
+ case N_DATA | N_EXT:
+ case N_NBDATA | N_EXT:
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ goto record_it;
+
+ case N_BSS:
+ case N_BSS | N_EXT:
+ case N_NBBSS | N_EXT:
+ case N_SETV | N_EXT: /* FIXME, is this in BSS? */
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_BSS);
+ goto record_it;
+
+ case N_ABS | N_EXT:
+ record_it:
+#ifdef DBXREAD_ONLY
+ SET_NAMESTRING();
+
+ bss_ext_symbol:
+ record_minimal_symbol (namestring, CUR_SYMBOL_VALUE,
+ CUR_SYMBOL_TYPE, objfile); /* Always */
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ /* Standard, local, non-debugger, symbols */
+
+ case N_NBTEXT:
+
+ /* We need to be able to deal with both N_FN or N_TEXT,
+ because we have no way of knowing whether the sys-supplied ld
+ or GNU ld was used to make the executable. Sequents throw
+ in another wrinkle -- they renumbered N_FN. */
+
+ case N_FN:
+ case N_FN_SEQ:
+ case N_TEXT:
+#ifdef DBXREAD_ONLY
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+ SET_NAMESTRING();
+ if ((namestring[0] == '-' && namestring[1] == 'l')
+ || (namestring [(nsl = strlen (namestring)) - 1] == 'o'
+ && namestring [nsl - 2] == '.'))
+ {
+ if (objfile -> ei.entry_point < CUR_SYMBOL_VALUE &&
+ objfile -> ei.entry_point >= last_o_file_start)
+ {
+ objfile -> ei.entry_file_lowpc = last_o_file_start;
+ objfile -> ei.entry_file_highpc = CUR_SYMBOL_VALUE;
+ }
+ if (past_first_source_file && pst
+ /* The gould NP1 uses low values for .o and -l symbols
+ which are not the address. */
+ && CUR_SYMBOL_VALUE >= pst->textlow)
+ {
+ END_PSYMTAB (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size,
+ CUR_SYMBOL_VALUE > pst->texthigh
+ ? CUR_SYMBOL_VALUE : pst->texthigh,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ else
+ past_first_source_file = 1;
+ last_o_file_start = CUR_SYMBOL_VALUE;
+ }
+ else
+ goto record_it;
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ case N_DATA:
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ goto record_it;
+
+ case N_UNDF | N_EXT:
+#ifdef DBXREAD_ONLY
+ if (CUR_SYMBOL_VALUE != 0) {
+ /* This is a "Fortran COMMON" symbol. See if the target
+ environment knows where it has been relocated to. */
+
+ CORE_ADDR reladdr;
+
+ SET_NAMESTRING();
+ if (target_lookup_symbol (namestring, &reladdr)) {
+ continue; /* Error in lookup; ignore symbol for now. */
+ }
+ CUR_SYMBOL_TYPE ^= (N_BSS^N_UNDF); /* Define it as a bss-symbol */
+ CUR_SYMBOL_VALUE = reladdr;
+ goto bss_ext_symbol;
+ }
+#endif /* DBXREAD_ONLY */
+ continue; /* Just undefined, not COMMON */
+
+ case N_UNDF:
+#ifdef DBXREAD_ONLY
+ if (processing_acc_compilation && bufp->n_strx == 1) {
+ /* Deal with relative offsets in the string table
+ used in ELF+STAB under Solaris. If we want to use the
+ n_strx field, which contains the name of the file,
+ we must adjust file_string_table_offset *before* calling
+ SET_NAMESTRING(). */
+ past_first_source_file = 1;
+ file_string_table_offset = next_file_string_table_offset;
+ next_file_string_table_offset =
+ file_string_table_offset + bufp->n_value;
+ if (next_file_string_table_offset < file_string_table_offset)
+ error ("string table offset backs up at %d", symnum);
+ /* FIXME -- replace error() with complaint. */
+ continue;
+ }
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ /* Lots of symbol types we can just ignore. */
+
+ case N_ABS:
+ case N_NBDATA:
+ case N_NBBSS:
+ continue;
+
+ /* Keep going . . .*/
+
+ /*
+ * Special symbol types for GNU
+ */
+ case N_INDR:
+ case N_INDR | N_EXT:
+ 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:
+ case N_SETV:
+ continue;
+
+ /*
+ * Debugger symbols
+ */
+
+ case N_SO: {
+ unsigned long valu;
+ static int prev_so_symnum = -10;
+ static int first_so_symnum;
+ char *p;
+
+ valu = CUR_SYMBOL_VALUE + ANOFFSET (section_offsets, SECT_OFF_TEXT);
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* A zero value is probably an indication for the SunPRO 3.0
+ compiler. end_psymtab explicitly tests for zero, so
+ don't relocate it. */
+ if (CUR_SYMBOL_VALUE == 0)
+ valu = 0;
+#endif
+
+ past_first_source_file = 1;
+
+ if (prev_so_symnum != symnum - 1)
+ { /* Here if prev stab wasn't N_SO */
+ first_so_symnum = symnum;
+
+ if (pst)
+ {
+ END_PSYMTAB (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size,
+ valu > pst->texthigh ? valu : pst->texthigh,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ }
+
+ prev_so_symnum = symnum;
+
+ /* End the current partial symtab and start a new one */
+
+ SET_NAMESTRING();
+
+ /* Null name means end of .o file. Don't start a new one. */
+ if (*namestring == '\000')
+ continue;
+
+ /* Some compilers (including gcc) emit a pair of initial N_SOs.
+ The first one is a directory name; the second the file name.
+ If pst exists, is empty, and has a filename ending in '/',
+ we assume the previous N_SO was a directory name. */
+
+ p = strrchr (namestring, '/');
+ if (p && *(p+1) == '\000')
+ continue; /* Simply ignore directory name SOs */
+
+ /* Some other compilers (C++ ones in particular) emit useless
+ SOs for non-existant .c files. We ignore all subsequent SOs that
+ immediately follow the first. */
+
+ if (!pst)
+ pst = START_PSYMTAB (objfile, section_offsets,
+ namestring, valu,
+ first_so_symnum * symbol_size,
+ objfile -> global_psymbols.next,
+ objfile -> static_psymbols.next);
+ continue;
+ }
+
+ case N_BINCL:
+ {
+#ifdef DBXREAD_ONLY
+ 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();
+
+ 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;
+
+ 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:
+ {
+ 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;
+ {
+ register int i;
+ for (i = 0; i < includes_used; i++)
+ if (STREQ (namestring, psymtab_include_list[i]))
+ {
+ i = -1;
+ break;
+ }
+ if (i == -1)
+ 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 " */
+ case N_ROSYM: /* Read-only data seg var -- static. */
+ case N_NBSTS: /* Gould nobase. */
+ case N_NBLCS: /* symbols. */
+ case N_FUN:
+ case N_GSYM: /* Global (extern) variable; can be
+ data or bss (sigh FIXME). */
+
+ /* Following may probably be ignored; I'll leave them here
+ for now (until I do Pascal and Modula 2 extensions). */
+
+ case N_PC: /* I may or may not need this; I
+ suspect not. */
+ case N_M2C: /* I suspect that I can ignore this here. */
+ case N_SCOPE: /* Same. */
+
+ SET_NAMESTRING();
+
+#ifdef DBXREAD_ONLY
+ /* See if this is an end of function stab. */
+ if (CUR_SYMBOL_TYPE == N_FUN && ! strcmp (namestring, ""))
+ {
+ unsigned long valu;
+
+ /* It's value is the size (in bytes) of the function for
+ function relative stabs, or the address of the function's
+ end for old style stabs. */
+ valu = CUR_SYMBOL_VALUE + last_function_start;
+ if (pst->texthigh == 0 || valu > pst->texthigh)
+ pst->texthigh = valu;
+ break;
+ }
+#endif
+
+ p = (char *) strchr (namestring, ':');
+ if (!p)
+ continue; /* Not a debugging symbol. */
+
+
+
+ /* Main processing section for debugging symbols which
+ the initial read through the symbol tables needs to worry
+ about. If we reach this point, the symbol which we are
+ considering is definitely one we are interested in.
+ p must also contain the (valid) index into the namestring
+ which indicates the debugging type symbol. */
+
+ switch (p[1])
+ {
+ case 'S':
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+#ifdef STATIC_TRANSFORM_NAME
+ namestring = STATIC_TRANSFORM_NAME (namestring);
+#endif
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+ case 'G':
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_DATA);
+ /* The addresses in these entries are reported to be
+ wrong. See the code that reads 'G's for symtabs. */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, CUR_SYMBOL_VALUE,
+ psymtab_language, objfile);
+ continue;
+
+ case 'T':
+ if (p != namestring) /* a name is there, not just :T... */
+ {
+ add_psymbol_to_list (namestring, p - namestring,
+ STRUCT_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0,
+ psymtab_language, objfile);
+ if (p[2] == 't')
+ {
+ /* Also a typedef with the same name. */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0,
+ psymtab_language, 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, 0,
+ psymtab_language, objfile);
+ }
+ }
+ goto check_enum;
+ case 't':
+ if (p != namestring) /* a name is there, not just :T... */
+ {
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_TYPEDEF,
+ &objfile->static_psymbols,
+ CUR_SYMBOL_VALUE, 0,
+ psymtab_language, objfile);
+ }
+ check_enum:
+ /* If this is an enumerated type, we need to
+ add all the enum constants to the partial symbol
+ table. This does not cover enums without names, e.g.
+ "enum {a, b} c;" in C, but fortunately those are
+ rare. There is no way for GDB to find those from the
+ enum type without spending too much time on it. Thus
+ to solve this problem, the compiler needs to put out the
+ enum in a nameless type. GCC2 does this. */
+
+ /* We are looking for something of the form
+ <name> ":" ("t" | "T") [<number> "="] "e"
+ {<constant> ":" <value> ","} ";". */
+
+ /* Skip over the colon and the 't' or 'T'. */
+ p += 2;
+ /* This type may be given a number. Also, numbers can come
+ in pairs like (0,26). Skip over it. */
+ while ((*p >= '0' && *p <= '9')
+ || *p == '(' || *p == ',' || *p == ')'
+ || *p == '=')
+ p++;
+
+ if (*p++ == 'e')
+ {
+ /* The aix4 compiler emits extra crud before the members. */
+ if (*p == '-')
+ {
+ /* Skip over the type (?). */
+ while (*p != ':')
+ p++;
+
+ /* Skip over the colon. */
+ p++;
+ }
+
+ /* We have found an enumerated type. */
+ /* According to comments in read_enum_type
+ a comma could end it instead of a semicolon.
+ I don't know where that happens.
+ Accept either. */
+ while (*p && *p != ';' && *p != ',')
+ {
+ char *q;
+
+ /* Check for and handle cretinous dbx symbol name
+ continuation! */
+ if (*p == '\\' || (*p == '?' && p[1] == '\0'))
+ p = next_symbol_text (objfile);
+
+ /* Point to the character after the name
+ of the enum constant. */
+ for (q = p; *q && *q != ':'; q++)
+ ;
+ /* Note that the value doesn't matter for
+ enum constants in psymtabs, just in symtabs. */
+ add_psymbol_to_list (p, q - p,
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, 0,
+ 0, psymtab_language, objfile);
+ /* Point past the name. */
+ p = q;
+ /* Skip over the value. */
+ while (*p && *p != ',')
+ p++;
+ /* Advance past the comma. */
+ if (*p)
+ p++;
+ }
+ }
+ continue;
+ case 'c':
+ /* Constant, e.g. from "const" in Pascal. */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_CONST,
+ &objfile->static_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ case 'f':
+ CUR_SYMBOL_VALUE += ANOFFSET (section_offsets, SECT_OFF_TEXT);
+#ifdef DBXREAD_ONLY
+ /* Keep track of the start of the last function so we
+ can handle end of function symbols. */
+ last_function_start = CUR_SYMBOL_VALUE;
+ /* Kludges for ELF/STABS with Sun ACC */
+ last_function_name = namestring;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* 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 =
+ find_stab_function_addr (namestring, pst, objfile);
+#endif
+#if 0
+ if (startup_file_end == 0)
+ startup_file_end = CUR_SYMBOL_VALUE;
+#endif
+ /* End kludge. */
+
+ /* In reordered executables this function may lie outside
+ the bounds created by N_SO symbols. If that's the case
+ use the address of this function as the low bound for
+ the partial symbol table. */
+ if (pst->textlow == 0
+ || (CUR_SYMBOL_VALUE < pst->textlow
+ && CUR_SYMBOL_VALUE
+ != ANOFFSET (section_offsets, SECT_OFF_TEXT)))
+ pst->textlow = CUR_SYMBOL_VALUE;
+#endif /* DBXREAD_ONLY */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->static_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ /* Global functions were ignored here, but now they
+ 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
+ /* Keep track of the start of the last function so we
+ can handle end of function symbols. */
+ last_function_start = CUR_SYMBOL_VALUE;
+ /* Kludges for ELF/STABS with Sun ACC */
+ last_function_name = namestring;
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* 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 =
+ find_stab_function_addr (namestring, pst, objfile);
+#endif
+#if 0
+ if (startup_file_end == 0)
+ startup_file_end = CUR_SYMBOL_VALUE;
+#endif
+ /* End kludge. */
+ /* In reordered executables this function may lie outside
+ the bounds created by N_SO symbols. If that's the case
+ use the address of this function as the low bound for
+ the partial symbol table. */
+ if (pst->textlow == 0
+ || (CUR_SYMBOL_VALUE < pst->textlow
+ && CUR_SYMBOL_VALUE
+ != ANOFFSET (section_offsets, SECT_OFF_TEXT)))
+ pst->textlow = CUR_SYMBOL_VALUE;
+#endif /* DBXREAD_ONLY */
+ add_psymbol_to_list (namestring, p - namestring,
+ VAR_NAMESPACE, LOC_BLOCK,
+ &objfile->global_psymbols, CUR_SYMBOL_VALUE,
+ 0, psymtab_language, objfile);
+ continue;
+
+ /* Two things show up here (hopefully); static symbols of
+ local scope (static used inside braces) or extensions
+ of structure symbols. We can ignore both. */
+ case 'V':
+ case '(':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ continue;
+
+ 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;
+ }
+
+ case N_EXCL:
+#ifdef DBXREAD_ONLY
+
+ SET_NAMESTRING();
+
+ /* Find the corresponding bincl and mark that psymtab on the
+ psymtab dependency list */
+ {
+ struct partial_symtab *needed_pst =
+ find_corresponding_bincl_psymtab (namestring, CUR_SYMBOL_VALUE);
+
+ /* If this include file was defined earlier in this file,
+ leave it alone. */
+ if (needed_pst == pst) continue;
+
+ if (needed_pst)
+ {
+ int i;
+ int found = 0;
+
+ for (i = 0; i < dependencies_used; i++)
+ if (dependency_list[i] == needed_pst)
+ {
+ found = 1;
+ break;
+ }
+
+ /* If it's already in the list, skip the rest. */
+ if (found) continue;
+
+ dependency_list[dependencies_used++] = needed_pst;
+ if (dependencies_used >= dependencies_allocated)
+ {
+ struct partial_symtab **orig = dependency_list;
+ dependency_list =
+ (struct partial_symtab **)
+ alloca ((dependencies_allocated *= 2)
+ * sizeof (struct partial_symtab *));
+ memcpy ((PTR)dependency_list, (PTR)orig,
+ (dependencies_used
+ * sizeof (struct partial_symtab *)));
+#ifdef DEBUG_INFO
+ fprintf_unfiltered (gdb_stderr, "Had to reallocate dependency list.\n");
+ fprintf_unfiltered (gdb_stderr, "New dependencies allocated: %d\n",
+ dependencies_allocated);
+#endif
+ }
+ }
+ }
+#endif /* DBXREAD_ONLY */
+ continue;
+
+ case N_ENDM:
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Solaris 2 end of module, finish current partial symbol table.
+ END_PSYMTAB will set pst->texthigh to the proper value, which
+ is necessary if a module compiled without debugging info
+ follows this module. */
+ if (pst)
+ {
+ END_PSYMTAB (pst, psymtab_include_list, includes_used,
+ symnum * symbol_size,
+ (CORE_ADDR) 0,
+ dependency_list, dependencies_used);
+ pst = (struct partial_symtab *) 0;
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+#endif
+ continue;
+
+ case N_RBRAC:
+#ifdef HANDLE_RBRAC
+ HANDLE_RBRAC(CUR_SYMBOL_VALUE);
+ continue;
+#endif
+ case N_EINCL:
+ case N_DSLINE:
+ case N_BSLINE:
+ case N_SSYM: /* Claim: Structure or union element.
+ Hopefully, I can ignore this. */
+ case N_ENTRY: /* Alternate entry point; can ignore. */
+ case N_MAIN: /* Can definitely ignore this. */
+ case N_CATCH: /* These are GNU C++ extensions */
+ case N_EHDECL: /* that can safely be ignored here. */
+ case N_LENG:
+ case N_BCOMM:
+ case N_ECOMM:
+ case N_ECOML:
+ case N_FNAME:
+ case N_SLINE:
+ case N_RSYM:
+ case N_PSYM:
+ case N_LBRAC:
+ case N_NSYMS: /* Ultrix 4.0: symbol count */
+ case N_DEFD: /* GNU Modula-2 */
+
+ case N_OBJ: /* useless types from Solaris */
+ case N_OPT:
+ /* These symbols aren't interesting; don't worry about them */
+
+ continue;
+
+ default:
+ /* 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 (CUR_SYMBOL_TYPE));
+ continue;
+ }
diff --git a/contrib/gdb/gdb/ppcbug-rom.c b/contrib/gdb/gdb/ppcbug-rom.c
new file mode 100644
index 0000000..6c7432b
--- /dev/null
+++ b/contrib/gdb/gdb/ppcbug-rom.c
@@ -0,0 +1,233 @@
+/* Remote debugging interface for PPCbug (PowerPC) Rom monitor
+ for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+ Written by Stu Grossman of Cygnus Support
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void ppcbug_open PARAMS ((char *args, int from_tty));
+
+static void
+ppcbug_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno = 0, base = 0;
+
+ if (regnamelen < 2 || regnamelen > 4)
+ return;
+
+ switch (regname[0])
+ {
+ case 'R':
+ if (regname[1] < '0' || regname[1] > '9')
+ return;
+ if (regnamelen == 2)
+ regno = regname[1] - '0';
+ else if (regnamelen == 3 && regname[2] >= '0' && regname[2] <= '9')
+ regno = (regname[1] - '0') * 10 + (regname[2] - '0');
+ else
+ return;
+ break;
+ case 'F':
+ if (regname[1] != 'R' || regname[2] < '0' || regname[2] > '9')
+ return;
+ if (regnamelen == 3)
+ regno = 32 + regname[2] - '0';
+ else if (regnamelen == 4 && regname[3] >= '0' && regname[3] <= '9')
+ regno = 32 + (regname[2] - '0') * 10 + (regname[3] - '0');
+ else
+ return;
+ break;
+ case 'I':
+ if (regnamelen != 2 || regname[1] != 'P')
+ return;
+ regno = 64;
+ break;
+ case 'M':
+ if (regnamelen != 3 || regname[1] != 'S' || regname[2] != 'R')
+ return;
+ regno = 65;
+ break;
+ case 'C':
+ if (regnamelen != 2 || regname[1] != 'R')
+ return;
+ regno = 66;
+ break;
+ case 'S':
+ if (regnamelen != 4 || regname[1] != 'P' || regname[2] != 'R')
+ return;
+ else if (regname[3] == '8')
+ regno = 67;
+ else if (regname[3] == '9')
+ regno = 68;
+ else if (regname[3] == '1')
+ regno = 69;
+ else if (regname[3] == '0')
+ regno = 70;
+ else
+ return;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes an "A7".
+ */
+
+static char *ppcbug_regnames[NUM_REGS] =
+{
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+ "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
+ "fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
+ "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
+ "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
+
+/* pc ps cnd lr cnt xer mq */
+ "ip", "msr", "cr", "spr8", "spr9", "spr1", "spr0"
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops ppcbug_ops0;
+static struct target_ops ppcbug_ops1;
+
+static char *ppcbug_inits[] = {"\r", NULL};
+
+#define PPC_CMDS(LOAD_CMD, OPS) \
+{ \
+ MO_CLR_BREAK_USES_ADDR | MO_HANDLE_NL, \
+ ppcbug_inits, /* Init strings */ \
+ "g\r", /* continue command */ \
+ "t\r", /* single step */ \
+ NULL, /* interrupt command */ \
+ "br %x\r", /* set a breakpoint */ \
+ "nobr %x\r", /* clear a breakpoint */ \
+ "nobr\r", /* clear all breakpoints */ \
+ "bf %x:%x %x;b\r", /* fill (start count val) */ \
+ { \
+ "ms %x %02x\r", /* setmem.cmdb (addr, value) */ \
+ "ms %x %04x\r", /* setmem.cmdw (addr, value) */ \
+ "ms %x %08x\r", /* setmem.cmdl (addr, value) */ \
+ NULL, /* setmem.cmdll (addr, value) */ \
+ NULL, /* setreg.resp_delim */ \
+ NULL, /* setreg.term */ \
+ NULL, /* setreg.term_cmd */ \
+ }, \
+ { \
+ "md %x:%x;b\r", /* getmem.cmdb (addr, len) */ \
+ "md %x:%x;b\r", /* getmem.cmdw (addr, len) */ \
+ "md %x:%x;b\r", /* getmem.cmdl (addr, len) */ \
+ NULL, /* getmem.cmdll (addr, len) */ \
+ " ", /* getmem.resp_delim */ \
+ NULL, /* getmem.term */ \
+ NULL, /* getmem.term_cmd */ \
+ }, \
+ { \
+ "rs %s %x\r", /* setreg.cmd (name, value) */ \
+ NULL, /* setreg.resp_delim */ \
+ NULL, /* setreg.term */ \
+ NULL /* setreg.term_cmd */ \
+ }, \
+ { \
+ "rs %s\r", /* getreg.cmd (name) */ \
+ "=", /* getreg.resp_delim */ \
+ NULL, /* getreg.term */ \
+ NULL /* getreg.term_cmd */ \
+ }, \
+ "rd\r", /* dump_registers */ \
+ "\\(\\w+\\) +=\\([0-9a-fA-F]+\\b\\)", /* register_pattern */ \
+ ppcbug_supply_register, /* supply_register */ \
+ NULL, /* load_routine (defaults to SRECs) */ \
+ LOAD_CMD, /* download command */ \
+ NULL, /* load response */ \
+ "PPC1-Bug>", /* monitor command prompt */ \
+ "\r", /* end-of-line terminator */ \
+ NULL, /* optional command terminator */ \
+ &OPS, /* target operations */ \
+ SERIAL_1_STOPBITS, /* number of stop bits */ \
+ ppcbug_regnames, /* registers names */ \
+ MONITOR_OPS_MAGIC /* magic */ \
+}
+
+
+static struct monitor_ops ppcbug_cmds0 = PPC_CMDS("lo 0\r", ppcbug_ops0);
+static struct monitor_ops ppcbug_cmds1 = PPC_CMDS("lo 1\r", ppcbug_ops1);
+
+static void
+ppcbug_open0(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &ppcbug_cmds0, from_tty);
+}
+
+static void
+ppcbug_open1(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &ppcbug_cmds1, from_tty);
+}
+
+void
+_initialize_ppcbug_rom ()
+{
+ init_monitor_ops (&ppcbug_ops0);
+
+ ppcbug_ops0.to_shortname = "ppcbug";
+ ppcbug_ops0.to_longname = "PowerPC PPCBug monitor on port 0";
+ ppcbug_ops0.to_doc = "Debug via the PowerPC PPCBug monitor using port 0.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ ppcbug_ops0.to_open = ppcbug_open0;
+
+ add_target (&ppcbug_ops0);
+
+ init_monitor_ops (&ppcbug_ops1);
+
+ ppcbug_ops1.to_shortname = "ppcbug1";
+ ppcbug_ops1.to_longname = "PowerPC PPCBug monitor on port 1";
+ ppcbug_ops1.to_doc = "Debug via the PowerPC PPCBug monitor using port 1.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ ppcbug_ops1.to_open = ppcbug_open1;
+
+ add_target (&ppcbug_ops1);
+}
diff --git a/contrib/gdb/gdb/printcmd.c b/contrib/gdb/gdb/printcmd.c
new file mode 100644
index 0000000..29f0572
--- /dev/null
+++ b/contrib/gdb/gdb/printcmd.c
@@ -0,0 +1,2248 @@
+/* Print values for GNU debugger GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "frame.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "language.h"
+#include "expression.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#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 " */
+
+struct format_data
+{
+ int count;
+ char format;
+ char size;
+};
+
+/* Last specified output format. */
+
+static char last_format = 'x';
+
+/* Last specified examination size. 'b', 'h', 'w' or `q'. */
+
+static char last_size = 'w';
+
+/* Default address to examine next. */
+
+static CORE_ADDR next_address;
+
+/* Last address examined. */
+
+static CORE_ADDR last_examine_address;
+
+/* Contents of last address examined.
+ This is not valid past the end of the `x' command! */
+
+static value_ptr last_examine_value;
+
+/* Largest offset between a symbolic value and an address, that will be
+ printed as `0x1234 <symbol+offset>'. */
+
+static unsigned int max_symbolic_offset = UINT_MAX;
+
+/* Append the source filename and linenumber of the symbol when
+ printing a symbolic value as `<symbol at filename:linenum>' if set. */
+static int print_symbol_filename = 0;
+
+/* Number of auto-display expression currently being displayed.
+ So that we can disable it if we get an error or a signal within it.
+ -1 when not doing one. */
+
+int current_display_number;
+
+/* Flag to low-level print routines that this value is being printed
+ in an epoch window. We'd like to pass this as a parameter, but
+ every routine would need to take it. Perhaps we can encapsulate
+ this in the I/O stream once we have GNU stdio. */
+
+int inspect_it = 0;
+
+struct display
+{
+ /* Chain link to next auto-display item. */
+ struct display *next;
+ /* Expression to be evaluated and displayed. */
+ struct expression *exp;
+ /* Item number of this auto-display item. */
+ int number;
+ /* Display format specified. */
+ struct format_data format;
+ /* Innermost block required by this expression when evaluated */
+ struct block *block;
+ /* Status of this display (enabled or disabled) */
+ enum enable status;
+};
+
+/* Chain of expressions whose values should be displayed
+ automatically each time the program stops. */
+
+static struct display *display_chain;
+
+static int display_number;
+
+/* Pointer to the target-dependent disassembly function. */
+
+int (*tm_print_insn) PARAMS ((bfd_vma, disassemble_info *));
+
+/* Prototypes for local functions. */
+
+static void delete_display PARAMS ((int));
+
+static void enable_display PARAMS ((char *, int));
+
+static void disable_display_command PARAMS ((char *, int));
+
+static void disassemble_command PARAMS ((char *, int));
+
+static void printf_command PARAMS ((char *, int));
+
+static void print_frame_nameless_args PARAMS ((struct frame_info *, long,
+ int, int, GDB_FILE *));
+
+static void display_info PARAMS ((char *, int));
+
+static void do_one_display PARAMS ((struct display *));
+
+static void undisplay_command PARAMS ((char *, int));
+
+static void free_display PARAMS ((struct display *));
+
+static void display_command PARAMS ((char *, int));
+
+static void x_command PARAMS ((char *, int));
+
+static void address_info PARAMS ((char *, int));
+
+static void set_command PARAMS ((char *, int));
+
+static void output_command PARAMS ((char *, int));
+
+static void call_command PARAMS ((char *, int));
+
+static void inspect_command PARAMS ((char *, int));
+
+static void print_command PARAMS ((char *, int));
+
+static void print_command_1 PARAMS ((char *, int, int));
+
+static void validate_format PARAMS ((struct format_data, char *));
+
+static void do_examine PARAMS ((struct format_data, CORE_ADDR));
+
+static void print_formatted PARAMS ((value_ptr, int, int));
+
+static struct format_data decode_format PARAMS ((char **, int, int));
+
+static int print_insn PARAMS ((CORE_ADDR, GDB_FILE *));
+
+
+/* Decode a format specification. *STRING_PTR should point to it.
+ OFORMAT and OSIZE are used as defaults for the format and size
+ if none are given in the format specification.
+ If OSIZE is zero, then the size field of the returned value
+ should be set only if a size is explicitly specified by the
+ user.
+ The structure returned describes all the data
+ found in the specification. In addition, *STRING_PTR is advanced
+ past the specification and past all whitespace following it. */
+
+static struct format_data
+decode_format (string_ptr, oformat, osize)
+ char **string_ptr;
+ int oformat;
+ int osize;
+{
+ struct format_data val;
+ register char *p = *string_ptr;
+
+ val.format = '?';
+ val.size = '?';
+ val.count = 1;
+
+ if (*p >= '0' && *p <= '9')
+ val.count = atoi (p);
+ while (*p >= '0' && *p <= '9') p++;
+
+ /* Now process size or format letters that follow. */
+
+ while (1)
+ {
+ if (*p == 'b' || *p == 'h' || *p == 'w' || *p == 'g')
+ val.size = *p++;
+ else if (*p >= 'a' && *p <= 'z')
+ val.format = *p++;
+ else
+ break;
+ }
+
+ while (*p == ' ' || *p == '\t') p++;
+ *string_ptr = p;
+
+ /* Set defaults for format and size if not specified. */
+ if (val.format == '?')
+ {
+ if (val.size == '?')
+ {
+ /* Neither has been specified. */
+ val.format = oformat;
+ val.size = osize;
+ }
+ else
+ /* If a size is specified, any format makes a reasonable
+ default except 'i'. */
+ val.format = oformat == 'i' ? 'x' : oformat;
+ }
+ else if (val.size == '?')
+ switch (val.format)
+ {
+ case 'a':
+ case 's':
+ /* 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. */
+ if (osize == 'w' || osize == 'g')
+ val.size = osize;
+ else
+ /* Default it to giantword if the last used size is not
+ appropriate. */
+ val.size = osize ? 'g' : osize;
+ break;
+ case 'c':
+ /* Characters default to one byte. */
+ val.size = osize ? 'b' : osize;
+ break;
+ default:
+ /* The default is the size most recently specified. */
+ val.size = osize;
+ }
+
+ return val;
+}
+
+/* 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.
+ This is used to pad hex numbers so they line up. */
+
+static void
+print_formatted (val, format, size)
+ register value_ptr val;
+ register int format;
+ int size;
+{
+ struct type *type = check_typedef (VALUE_TYPE (val));
+ int len = TYPE_LENGTH (type);
+
+ if (VALUE_LVAL (val) == lval_memory)
+ next_address = VALUE_ADDRESS (val) + len;
+
+ switch (format)
+ {
+ case 's':
+ next_address = VALUE_ADDRESS (val)
+ + val_print_string (VALUE_ADDRESS (val), 0, gdb_stdout);
+ break;
+
+ case 'i':
+ /* The old comment says
+ "Force output out, print_insn not using _filtered".
+ I'm not completely sure what that means, I suspect most print_insn
+ now do use _filtered, so I guess it's obsolete. */
+ /* We often wrap here if there are long symbolic names. */
+ wrap_here (" ");
+ next_address = VALUE_ADDRESS (val)
+ + print_insn (VALUE_ADDRESS (val), gdb_stdout);
+ break;
+
+ default:
+ if (format == 0
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY
+ || TYPE_CODE (type) == TYPE_CODE_STRING
+ || TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION)
+ value_print (val, gdb_stdout, format, Val_pretty_default);
+ else
+ print_scalar_formatted (VALUE_CONTENTS (val), type,
+ format, size, gdb_stdout);
+ }
+}
+
+/* Print a scalar of data of type TYPE, pointed to in GDB by VALADDR,
+ according to letters FORMAT and SIZE on STREAM.
+ FORMAT may not be zero. Formats s and i are not supported at this level.
+
+ This is how the elements of an array or structure are printed
+ with a format. */
+
+void
+print_scalar_formatted (valaddr, type, format, size, stream)
+ char *valaddr;
+ struct type *type;
+ int format;
+ int size;
+ GDB_FILE *stream;
+{
+ LONGEST val_long;
+ unsigned int len = TYPE_LENGTH (type);
+
+ if (len > sizeof (LONGEST)
+ && (format == 't'
+ || format == 'c'
+ || format == 'o'
+ || format == 'u'
+ || format == 'd'
+ || format == 'x'))
+ {
+ if (! TYPE_UNSIGNED (type)
+ || ! extract_long_unsigned_integer (valaddr, len, &val_long))
+ {
+ /* We can't print it normally, but we can print it in hex.
+ Printing it in the wrong radix is more useful than saying
+ "use /x, you dummy". */
+ /* FIXME: we could also do octal or binary if that was the
+ desired format. */
+ /* FIXME: we should be using the size field to give us a
+ minimum field width to print. */
+ val_print_type_code_int (type, valaddr, stream);
+ return;
+ }
+
+ /* If we get here, extract_long_unsigned_integer set val_long. */
+ }
+ else 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
+ (if shorts are 16 bits) instead of 4294967295). */
+ if (format != 'd')
+ {
+ if (len < sizeof (LONGEST))
+ val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1;
+ }
+
+ switch (format)
+ {
+ case 'x':
+ if (!size)
+ {
+ /* no size specified, like in print. Print varying # of digits. */
+ print_longest (stream, 'x', 1, val_long);
+ }
+ else
+ switch (size)
+ {
+ case 'b':
+ case 'h':
+ case 'w':
+ case 'g':
+ print_longest (stream, size, 1, val_long);
+ break;
+ default:
+ error ("Undefined output size \"%c\".", size);
+ }
+ break;
+
+ case 'd':
+ print_longest (stream, 'd', 1, val_long);
+ break;
+
+ case 'u':
+ print_longest (stream, 'u', 0, val_long);
+ break;
+
+ case 'o':
+ if (val_long)
+ print_longest (stream, 'o', 1, val_long);
+ else
+ fprintf_filtered (stream, "0");
+ break;
+
+ case 'a':
+ print_address (unpack_pointer (type, valaddr), stream);
+ break;
+
+ case 'c':
+ value_print (value_from_longest (builtin_type_char, val_long), stream, 0,
+ Val_pretty_default);
+ break;
+
+ case 'f':
+ if (len == sizeof (float))
+ type = builtin_type_float;
+ else if (len == sizeof (double))
+ type = builtin_type_double;
+ print_floating (valaddr, type, stream);
+ break;
+
+ case 0:
+ abort ();
+
+ case 't':
+ /* Binary; 't' stands for "two". */
+ {
+ char bits[8*(sizeof val_long) + 1];
+ char *cp = bits;
+ int width;
+
+ if (!size)
+ width = 8*(sizeof val_long);
+ else
+ switch (size)
+ {
+ case 'b':
+ width = 8;
+ break;
+ case 'h':
+ width = 16;
+ break;
+ case 'w':
+ width = 32;
+ break;
+ case 'g':
+ width = 64;
+ break;
+ default:
+ error ("Undefined output size \"%c\".", size);
+ }
+
+ bits[width] = '\0';
+ while (width-- > 0)
+ {
+ bits[width] = (val_long & 1) ? '1' : '0';
+ val_long >>= 1;
+ }
+ if (!size)
+ {
+ while (*cp && *cp == '0')
+ cp++;
+ if (*cp == '\0')
+ cp--;
+ }
+ fprintf_filtered (stream, local_binary_format_prefix());
+ fprintf_filtered (stream, cp);
+ fprintf_filtered (stream, local_binary_format_suffix());
+ }
+ break;
+
+ default:
+ error ("Undefined output format \"%c\".", format);
+ }
+}
+
+/* Specify default address for `x' command.
+ `info lines' uses this. */
+
+void
+set_next_address (addr)
+ CORE_ADDR addr;
+{
+ next_address = addr;
+
+ /* Make address available to the user as $_. */
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_longest (lookup_pointer_type (builtin_type_void),
+ (LONGEST) addr));
+}
+
+/* Optionally print address ADDR symbolically as <SYMBOL+OFFSET> 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. */
+
+void
+print_address_symbolic (addr, stream, do_demangle, leadin)
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+ int do_demangle;
+ char *leadin;
+{
+ 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 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 (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
+ CORE_ADDR. But when we detect unsigned wraparound in the
+ CORE_ADDR math, we ignore this test and print the offset,
+ because addr+max_symbolic_offset has wrapped through the end
+ of the address space back to the beginning, giving bogus comparison. */
+ if (addr > name_location + max_symbolic_offset
+ && name_location + max_symbolic_offset > name_location)
+ return;
+
+ fputs_filtered (leadin, stream);
+ fputs_filtered ("<", stream);
+ fputs_filtered (name, stream);
+ if (addr != name_location)
+ fprintf_filtered (stream, "+%u", (unsigned int)(addr - name_location));
+
+ /* 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. */
+ print_longest (stream, 'x', use_local, (unsigned LONGEST) addr);
+}
+
+/* Print address ADDR symbolically on STREAM.
+ First print it as a number. Then perhaps print
+ <SYMBOL + OFFSET> after the number. */
+
+void
+print_address (addr, stream)
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+{
+ print_address_numeric (addr, 1, stream);
+ print_address_symbolic (addr, stream, asm_demangle, " ");
+}
+
+/* Print address ADDR symbolically on STREAM. Parameter DEMANGLE
+ controls whether to print the symbolic name "raw" or demangled.
+ Global setting "addressprint" controls whether to print hex address
+ or not. */
+
+void
+print_address_demangle (addr, stream, do_demangle)
+ CORE_ADDR addr;
+ GDB_FILE *stream;
+ int 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, "");
+ }
+}
+
+
+/* These are the types that $__ will get after an examine command of one
+ of these sizes. */
+
+static struct type *examine_b_type;
+static struct type *examine_h_type;
+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 gdb_stdout. */
+
+static void
+do_examine (fmt, addr)
+ struct format_data fmt;
+ CORE_ADDR addr;
+{
+ register char format = 0;
+ register char size;
+ register int count = 1;
+ struct type *val_type = NULL;
+ register int i;
+ register int maxelts;
+
+ format = fmt.format;
+ size = fmt.size;
+ count = fmt.count;
+ next_address = addr;
+
+ /* String or instruction format implies fetch single bytes
+ regardless of the specified size. */
+ if (format == 's' || format == 'i')
+ size = 'b';
+
+ if (size == 'b')
+ val_type = examine_b_type;
+ else if (size == 'h')
+ val_type = examine_h_type;
+ else if (size == 'w')
+ val_type = examine_w_type;
+ else if (size == 'g')
+ val_type = examine_g_type;
+
+ maxelts = 8;
+ if (size == 'w')
+ maxelts = 4;
+ if (size == 'g')
+ maxelts = 2;
+ if (format == 's' || format == 'i')
+ maxelts = 1;
+
+ /* Print as many objects as specified in COUNT, at most maxelts per line,
+ with the address of the next one at the start of each line. */
+
+ while (count > 0)
+ {
+ QUIT;
+ print_address (next_address, gdb_stdout);
+ printf_filtered (":");
+ for (i = maxelts;
+ i > 0 && count > 0;
+ i--, count--)
+ {
+ printf_filtered ("\t");
+ /* Note that print_formatted sets next_address for the next
+ object. */
+ last_examine_address = next_address;
+ last_examine_value = value_at (val_type, next_address);
+ print_formatted (last_examine_value, format, size);
+ }
+ printf_filtered ("\n");
+ gdb_flush (gdb_stdout);
+ }
+}
+
+static void
+validate_format (fmt, cmdname)
+ struct format_data fmt;
+ char *cmdname;
+{
+ if (fmt.size != 0)
+ error ("Size letters are meaningless in \"%s\" command.", cmdname);
+ if (fmt.count != 1)
+ error ("Item count other than 1 is meaningless in \"%s\" command.",
+ cmdname);
+ if (fmt.format == 'i' || fmt.format == 's')
+ error ("Format letter \"%c\" is meaningless in \"%s\" command.",
+ fmt.format, cmdname);
+}
+
+/* Evaluate string EXP as an expression in the current language and
+ print the resulting value. EXP may contain a format specifier as the
+ first argument ("/x myvar" for example, to print myvar in hex).
+ */
+
+static void
+print_command_1 (exp, inspect, voidprint)
+ char *exp;
+ int inspect;
+ int voidprint;
+{
+ struct expression *expr;
+ register struct cleanup *old_chain = 0;
+ register char format = 0;
+ register value_ptr val;
+ struct format_data fmt;
+ int cleanup = 0;
+
+ /* Pass inspect flag to the rest of the print routines in a global (sigh). */
+ inspect_it = inspect;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, last_format, 0);
+ validate_format (fmt, "print");
+ last_format = format = fmt.format;
+ }
+ else
+ {
+ fmt.count = 1;
+ fmt.format = 0;
+ fmt.size = 0;
+ }
+
+ if (exp && *exp)
+ {
+ extern int objectprint;
+ struct type *type;
+ expr = parse_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ cleanup = 1;
+ val = evaluate_expression (expr);
+
+ /* C++: figure out what type we actually want to print it as. */
+ type = VALUE_TYPE (val);
+
+ if (objectprint
+ && ( TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF)
+ && ( TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_UNION))
+ {
+ value_ptr v;
+
+ v = value_from_vtable_info (val, TYPE_TARGET_TYPE (type));
+ if (v != 0)
+ {
+ val = v;
+ type = VALUE_TYPE (val);
+ }
+ }
+ }
+ else
+ val = access_value_history (0);
+
+ if (voidprint || (val && VALUE_TYPE (val) &&
+ TYPE_CODE (VALUE_TYPE (val)) != TYPE_CODE_VOID))
+ {
+ 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_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_unfiltered("\") )\030");
+ }
+
+ if (cleanup)
+ do_cleanups (old_chain);
+ inspect_it = 0; /* Reset print routines to normal */
+}
+
+/* ARGSUSED */
+static void
+print_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ print_command_1 (exp, 0, 1);
+}
+
+/* Same as print, except in epoch, it gets its own window */
+/* ARGSUSED */
+static void
+inspect_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ extern int epoch_interface;
+
+ print_command_1 (exp, epoch_interface, 1);
+}
+
+/* Same as print, except it doesn't print void results. */
+/* ARGSUSED */
+static void
+call_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ print_command_1 (exp, 0, 0);
+}
+
+/* ARGSUSED */
+static void
+output_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct expression *expr;
+ register struct cleanup *old_chain;
+ register char format = 0;
+ register value_ptr val;
+ struct format_data fmt;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, 0, 0);
+ validate_format (fmt, "output");
+ format = fmt.format;
+ }
+
+ expr = parse_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+
+ val = evaluate_expression (expr);
+
+ annotate_value_begin (VALUE_TYPE (val));
+
+ print_formatted (val, format, fmt.size);
+
+ annotate_value_end ();
+
+ do_cleanups (old_chain);
+}
+
+/* ARGSUSED */
+static void
+set_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct expression *expr = parse_expression (exp);
+ register struct cleanup *old_chain
+ = make_cleanup (free_current_contents, &expr);
+ evaluate_expression (expr);
+ do_cleanups (old_chain);
+}
+
+/* ARGSUSED */
+static void
+address_info (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ register struct symbol *sym;
+ register struct minimal_symbol *msymbol;
+ register long val;
+ register long basereg;
+ int is_a_field_of_this; /* C++: lookup_symbol sets this to nonzero
+ if exp is a field of `this'. */
+
+ if (exp == 0)
+ error ("Argument required.");
+
+ sym = lookup_symbol (exp, get_selected_block (), VAR_NAMESPACE,
+ &is_a_field_of_this, (struct symtab **)NULL);
+ if (sym == NULL)
+ {
+ if (is_a_field_of_this)
+ {
+ 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, NULL, NULL);
+
+ if (msymbol != NULL)
+ {
+ 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_filtered ("Symbol \"");
+ fprintf_symbol_filtered (gdb_stdout, SYMBOL_NAME (sym),
+ current_language->la_language, DMGL_ANSI);
+ printf_filtered ("\" is ");
+ val = SYMBOL_VALUE (sym);
+ basereg = SYMBOL_BASEREG (sym);
+
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_CONST:
+ case LOC_CONST_BYTES:
+ printf_filtered ("constant");
+ break;
+
+ case LOC_LABEL:
+ printf_filtered ("a label at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
+ break;
+
+ case LOC_REGISTER:
+ printf_filtered ("a variable in register %s", reg_names[val]);
+ break;
+
+ case LOC_STATIC:
+ printf_filtered ("static storage at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (sym), 1, gdb_stdout);
+ break;
+
+ case LOC_REGPARM:
+ printf_filtered ("an argument in register %s", reg_names[val]);
+ break;
+
+ case LOC_REGPARM_ADDR:
+ printf_filtered ("address of an argument in register %s", reg_names[val]);
+ break;
+
+ case LOC_ARG:
+ printf_filtered ("an argument at offset %ld", val);
+ break;
+
+ case LOC_LOCAL_ARG:
+ printf_filtered ("an argument at frame offset %ld", val);
+ break;
+
+ case LOC_LOCAL:
+ printf_filtered ("a local variable at frame offset %ld", val);
+ break;
+
+ case LOC_REF_ARG:
+ printf_filtered ("a reference argument at offset %ld", val);
+ break;
+
+ case LOC_BASEREG:
+ printf_filtered ("a variable at offset %ld from register %s",
+ val, reg_names[basereg]);
+ break;
+
+ case LOC_BASEREG_ARG:
+ printf_filtered ("an argument at offset %ld from register %s",
+ val, reg_names[basereg]);
+ break;
+
+ case LOC_TYPEDEF:
+ printf_filtered ("a typedef");
+ break;
+
+ case LOC_BLOCK:
+ printf_filtered ("a function at address ");
+ print_address_numeric (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), 1,
+ gdb_stdout);
+ break;
+
+ case LOC_UNRESOLVED:
+ {
+ struct minimal_symbol *msym;
+
+ msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, NULL);
+ if (msym == NULL)
+ printf_filtered ("unresolved");
+ else
+ {
+ printf_filtered ("static storage at address ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (msym), 1, gdb_stdout);
+ }
+ }
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ printf_filtered ("optimized out");
+ break;
+
+ default:
+ printf_filtered ("of unknown (botched) type");
+ break;
+ }
+ printf_filtered (".\n");
+}
+
+static void
+x_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct expression *expr;
+ struct format_data fmt;
+ struct cleanup *old_chain;
+ struct value *val;
+
+ fmt.format = last_format;
+ fmt.size = last_size;
+ fmt.count = 1;
+
+ if (exp && *exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, last_format, last_size);
+ }
+
+ /* If we have an expression, evaluate it and use it as the address. */
+
+ if (exp != 0 && *exp != 0)
+ {
+ expr = parse_expression (exp);
+ /* Cause expression not to be there any more
+ if this command is repeated with Newline.
+ But don't clobber a user-defined command's definition. */
+ if (from_tty)
+ *exp = 0;
+ old_chain = make_cleanup (free_current_contents, &expr);
+ val = evaluate_expression (expr);
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_REF)
+ val = value_ind (val);
+ /* In rvalue contexts, such as this, functions are coerced into
+ pointers to functions. This makes "x/i main" work. */
+ if (/* last_format == 'i'
+ && */ TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FUNC
+ && VALUE_LVAL (val) == lval_memory)
+ next_address = VALUE_ADDRESS (val);
+ else
+ next_address = value_as_pointer (val);
+ do_cleanups (old_chain);
+ }
+
+ do_examine (fmt, next_address);
+
+ /* If the examine succeeds, we remember its size and format for next time. */
+ last_size = fmt.size;
+ last_format = fmt.format;
+
+ /* Set a couple of internal variables if appropriate. */
+ if (last_examine_value)
+ {
+ /* Make last address examined available to the user as $_. Use
+ the correct pointer type. */
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_longest (
+ lookup_pointer_type (VALUE_TYPE (last_examine_value)),
+ (LONGEST) last_examine_address));
+
+ /* Make contents of last address examined available to the user as $__.*/
+ set_internalvar (lookup_internalvar ("__"), last_examine_value);
+ }
+}
+
+
+/* Add an expression to the auto-display chain.
+ Specify the expression. */
+
+static void
+display_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ struct format_data fmt;
+ register struct expression *expr;
+ register struct display *new;
+
+ if (exp == 0)
+ {
+ do_displays ();
+ return;
+ }
+
+ if (*exp == '/')
+ {
+ exp++;
+ fmt = decode_format (&exp, 0, 0);
+ if (fmt.size && fmt.format == 0)
+ fmt.format = 'x';
+ if (fmt.format == 'i' || fmt.format == 's')
+ fmt.size = 'b';
+ }
+ else
+ {
+ fmt.format = 0;
+ fmt.size = 0;
+ fmt.count = 0;
+ }
+
+ innermost_block = 0;
+ expr = parse_expression (exp);
+
+ new = (struct display *) xmalloc (sizeof (struct display));
+
+ new->exp = expr;
+ new->block = innermost_block;
+ new->next = display_chain;
+ new->number = ++display_number;
+ new->format = fmt;
+ new->status = enabled;
+ display_chain = new;
+
+ if (from_tty && target_has_execution)
+ do_one_display (new);
+
+ dont_repeat ();
+}
+
+static void
+free_display (d)
+ struct display *d;
+{
+ free ((PTR)d->exp);
+ free ((PTR)d);
+}
+
+/* Clear out the display_chain.
+ Done when new symtabs are loaded, since this invalidates
+ the types stored in many expressions. */
+
+void
+clear_displays ()
+{
+ register struct display *d;
+
+ while ((d = display_chain) != NULL)
+ {
+ free ((PTR)d->exp);
+ display_chain = d->next;
+ free ((PTR)d);
+ }
+}
+
+/* Delete the auto-display number NUM. */
+
+static void
+delete_display (num)
+ int num;
+{
+ register struct display *d1, *d;
+
+ if (!display_chain)
+ error ("No display number %d.", num);
+
+ if (display_chain->number == num)
+ {
+ d1 = display_chain;
+ display_chain = d1->next;
+ free_display (d1);
+ }
+ else
+ for (d = display_chain; ; d = d->next)
+ {
+ if (d->next == 0)
+ error ("No display number %d.", num);
+ if (d->next->number == num)
+ {
+ d1 = d->next;
+ d->next = d1->next;
+ free_display (d1);
+ break;
+ }
+ }
+}
+
+/* Delete some values from the auto-display chain.
+ Specify the element numbers. */
+
+static void
+undisplay_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ register char *p1;
+ register int num;
+
+ if (args == 0)
+ {
+ if (query ("Delete all auto-display expressions? "))
+ clear_displays ();
+ dont_repeat ();
+ return;
+ }
+
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9') p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ num = atoi (p);
+
+ delete_display (num);
+
+ p = p1;
+ while (*p == ' ' || *p == '\t') p++;
+ }
+ dont_repeat ();
+}
+
+/* Display a single auto-display.
+ Do nothing if the display cannot be printed in the current context,
+ or if the display is disabled. */
+
+static void
+do_one_display (d)
+ struct display *d;
+{
+ int within_current_scope;
+
+ if (d->status == disabled)
+ return;
+
+ if (d->block)
+ within_current_scope = contained_in (get_selected_block (), d->block);
+ else
+ within_current_scope = 1;
+ if (!within_current_scope)
+ return;
+
+ current_display_number = 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);
+ printf_filtered ("%c", d->format.format);
+ if (d->format.format != 'i' && d->format.format != 's')
+ printf_filtered ("%c", d->format.size);
+ printf_filtered (" ");
+
+ annotate_display_expression ();
+
+ print_expression (d->exp, gdb_stdout);
+ annotate_display_expression_end ();
+
+ if (d->format.count != 1)
+ printf_filtered ("\n");
+ else
+ printf_filtered (" ");
+
+ 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);
+
+ 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");
+ }
+
+ annotate_display_end ();
+
+ gdb_flush (gdb_stdout);
+ current_display_number = -1;
+}
+
+/* Display all of the values on the auto-display chain which can be
+ evaluated in the current scope. */
+
+void
+do_displays ()
+{
+ register struct display *d;
+
+ for (d = display_chain; d; d = d->next)
+ do_one_display (d);
+}
+
+/* Delete the auto-display which we were in the process of displaying.
+ This is done when there is an error or a signal. */
+
+void
+disable_display (num)
+ int num;
+{
+ register struct display *d;
+
+ for (d = display_chain; d; d = d->next)
+ if (d->number == num)
+ {
+ d->status = disabled;
+ return;
+ }
+ printf_unfiltered ("No display number %d.\n", num);
+}
+
+void
+disable_current_display ()
+{
+ if (current_display_number >= 0)
+ {
+ disable_display (current_display_number);
+ fprintf_unfiltered (gdb_stderr, "Disabling display %d to avoid infinite recursion.\n",
+ current_display_number);
+ }
+ current_display_number = -1;
+}
+
+static void
+display_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct display *d;
+
+ if (!display_chain)
+ printf_unfiltered ("There are no auto-display expressions now.\n");
+ else
+ printf_filtered ("Auto-display expressions now in effect:\n\
+Num Enb Expression\n");
+
+ for (d = display_chain; d; d = d->next)
+ {
+ printf_filtered ("%d: %c ", d->number, "ny"[(int)d->status]);
+ if (d->format.size)
+ printf_filtered ("/%d%c%c ", d->format.count, d->format.size,
+ d->format.format);
+ else if (d->format.format)
+ printf_filtered ("/%c ", d->format.format);
+ 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");
+ gdb_flush (gdb_stdout);
+ }
+}
+
+static void
+enable_display (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ register char *p1;
+ register int num;
+ register struct display *d;
+
+ if (p == 0)
+ {
+ for (d = display_chain; d; d = d->next)
+ d->status = enabled;
+ }
+ else
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9')
+ p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ num = atoi (p);
+
+ for (d = display_chain; d; d = d->next)
+ if (d->number == num)
+ {
+ d->status = enabled;
+ goto win;
+ }
+ printf_unfiltered ("No display number %d.\n", num);
+ win:
+ p = p1;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ }
+}
+
+/* ARGSUSED */
+static void
+disable_display_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ register char *p = args;
+ register char *p1;
+ register struct display *d;
+
+ if (p == 0)
+ {
+ for (d = display_chain; d; d = d->next)
+ d->status = disabled;
+ }
+ else
+ while (*p)
+ {
+ p1 = p;
+ while (*p1 >= '0' && *p1 <= '9')
+ p1++;
+ if (*p1 && *p1 != ' ' && *p1 != '\t')
+ error ("Arguments must be display numbers.");
+
+ disable_display (atoi (p));
+
+ p = p1;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ }
+}
+
+
+/* Print the value in stack frame FRAME of a variable
+ specified by a struct symbol. */
+
+void
+print_variable_value (var, frame, stream)
+ struct symbol *var;
+ struct frame_info *frame;
+ GDB_FILE *stream;
+{
+ value_ptr val = read_var_value (var, frame);
+
+ value_print (val, stream, 0, Val_pretty_default);
+}
+
+/* Print the arguments of a stack frame, given the function FUNC
+ running in that frame (as a symbol), the info on the frame,
+ and the number of args according to the stack frame (or -1 if unknown). */
+
+/* References here and elsewhere to "number of args according to the
+ stack frame" appear in all cases to refer to "number of ints of args
+ according to the stack frame". At least for VAX, i386, isi. */
+
+void
+print_frame_args (func, fi, num, stream)
+ struct symbol *func;
+ struct frame_info *fi;
+ int num;
+ GDB_FILE *stream;
+{
+ struct block *b = NULL;
+ int nsyms = 0;
+ int first = 1;
+ register int i;
+ register struct symbol *sym;
+ 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. */
+ long highest_offset = -1;
+ int arg_size;
+ /* Number of ints of arguments that we have printed so far. */
+ int args_printed = 0;
+
+ if (func)
+ {
+ b = SYMBOL_BLOCK_VALUE (func);
+ nsyms = BLOCK_NSYMS (b);
+ }
+
+ for (i = 0; i < nsyms; i++)
+ {
+ QUIT;
+ sym = BLOCK_SYM (b, i);
+
+ /* Keep track of the highest stack argument offset seen, and
+ skip over any kinds of symbols we don't care about. */
+
+ switch (SYMBOL_CLASS (sym)) {
+ case LOC_ARG:
+ case LOC_REF_ARG:
+ {
+ long current_offset = SYMBOL_VALUE (sym);
+ arg_size = TYPE_LENGTH (SYMBOL_TYPE (sym));
+
+ /* Compute address of next argument by adding the size of
+ this argument and rounding to an int boundary. */
+ current_offset
+ = ((current_offset + arg_size + sizeof (int) - 1)
+ & ~(sizeof (int) - 1));
+
+ /* If this is the highest offset seen yet, set highest_offset. */
+ if (highest_offset == -1
+ || (current_offset > highest_offset))
+ highest_offset = current_offset;
+
+ /* Add the number of ints we're about to print to args_printed. */
+ args_printed += (arg_size + sizeof (int) - 1) / sizeof (int);
+ }
+
+ /* We care about types of symbols, but don't need to keep track of
+ stack offsets in them. */
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_LOCAL_ARG:
+ case LOC_BASEREG_ARG:
+ break;
+
+ /* Other types of symbols we just skip over. */
+ default:
+ continue;
+ }
+
+ /* We have to look up the symbol because arguments can have
+ two entries (one a parameter, one a local) and the one we
+ want is the local, which lookup_symbol will find for us.
+ This includes gcc1 (not gcc2) on the sparc when passing a
+ small structure and gcc2 when the argument type is float
+ 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). */
+ /* 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))
+ {
+ 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
+ want to print their addresses. Print ??? for args whose address
+ we do not know. We pass 2 as "recurse" to val_print because our
+ standard indentation here is 4 spaces, and val_print indents
+ 2 for each recurse. */
+ val = read_var_value (sym, 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;
+ }
+
+ /* Don't print nameless args in situations where we don't know
+ enough about the stack to find them. */
+ if (num != -1)
+ {
+ long start;
+
+ if (highest_offset == -1)
+ start = FRAME_ARGS_SKIP;
+ else
+ start = highest_offset;
+
+ print_frame_nameless_args (fi, start, num - args_printed,
+ first, stream);
+ }
+}
+
+/* Print nameless args on STREAM.
+ FI is the frameinfo for this frame, START is the offset
+ of the first nameless arg, and NUM is the number of nameless args to
+ print. FIRST is nonzero if this is the first argument (not just
+ the first nameless arg). */
+
+static void
+print_frame_nameless_args (fi, start, num, first, stream)
+ struct frame_info *fi;
+ long start;
+ int num;
+ int first;
+ GDB_FILE *stream;
+{
+ int i;
+ CORE_ADDR argsaddr;
+ long arg_value;
+
+ for (i = 0; i < num; i++)
+ {
+ QUIT;
+#ifdef NAMELESS_ARG_VALUE
+ NAMELESS_ARG_VALUE (fi, start, &arg_value);
+#else
+ argsaddr = FRAME_ARGS_ADDRESS (fi);
+ if (!argsaddr)
+ return;
+
+ arg_value = read_memory_integer (argsaddr + start, sizeof (int));
+#endif
+
+ if (!first)
+ fprintf_filtered (stream, ", ");
+
+#ifdef PRINT_NAMELESS_INTEGER
+ PRINT_NAMELESS_INTEGER (stream, arg_value);
+#else
+#ifdef PRINT_TYPELESS_INTEGER
+ PRINT_TYPELESS_INTEGER (stream, builtin_type_int, (LONGEST) arg_value);
+#else
+ fprintf_filtered (stream, "%ld", arg_value);
+#endif /* PRINT_TYPELESS_INTEGER */
+#endif /* PRINT_NAMELESS_INTEGER */
+ first = 0;
+ start += sizeof (int);
+ }
+}
+
+/* ARGSUSED */
+static void
+printf_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ register char *f;
+ register char *s = arg;
+ char *string;
+ value_ptr *val_args;
+ char *substrings;
+ char *current_substring;
+ int nargs = 0;
+ int allocated_args = 20;
+ struct cleanup *old_cleanups;
+
+ val_args = (value_ptr *) xmalloc (allocated_args * sizeof (value_ptr));
+ old_cleanups = make_cleanup (free_current_contents, &val_args);
+
+ if (s == 0)
+ error_no_arg ("format-control string and values to print");
+
+ /* Skip white space before format string */
+ while (*s == ' ' || *s == '\t') s++;
+
+ /* A format string should follow, enveloped in double quotes */
+ if (*s++ != '"')
+ error ("Bad format string, missing '\"'.");
+
+ /* Parse the format-control string and copy it into the string STRING,
+ processing some kinds of escape sequence. */
+
+ f = string = (char *) alloca (strlen (s) + 1);
+
+ while (*s != '"')
+ {
+ int c = *s++;
+ switch (c)
+ {
+ case '\0':
+ error ("Bad format string, non-terminated '\"'.");
+
+ case '\\':
+ switch (c = *s++)
+ {
+ 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 'v':
+ *f++ = '\v';
+ break;
+ case '"':
+ *f++ = '"';
+ break;
+ default:
+ /* ??? TODO: handle other escape sequences */
+ error ("Unrecognized escape character \\%c in format string.",
+ c);
+ }
+ break;
+
+ default:
+ *f++ = c;
+ }
+ }
+
+ /* Skip over " and following space and comma. */
+ s++;
+ *f++ = '\0';
+ while (*s == ' ' || *s == '\t') s++;
+
+ if (*s != ',' && *s != 0)
+ error ("Invalid argument syntax");
+
+ if (*s == ',') s++;
+ while (*s == ' ' || *s == '\t') s++;
+
+ /* Need extra space for the '\0's. Doubling the size is sufficient. */
+ substrings = alloca (strlen (string) * 2);
+ current_substring = substrings;
+
+ {
+ /* Now scan the string for %-specs and see what kinds of args they want.
+ 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;
+ enum argclass this_argclass;
+ char *last_arg;
+ int nargs_wanted;
+ int lcount;
+ int i;
+
+ argclass = (enum argclass *) alloca (strlen (s) * sizeof *argclass);
+ nargs_wanted = 0;
+ f = string;
+ last_arg = string;
+ while (*f)
+ if (*f++ == '%')
+ {
+ lcount = 0;
+ while (strchr ("0123456789.hlL-+ #", *f))
+ {
+ if (*f == 'l' || *f == 'L')
+ lcount++;
+ f++;
+ }
+ switch (*f)
+ {
+ case 's':
+ this_argclass = string_arg;
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ this_argclass = double_arg;
+ break;
+
+ case '*':
+ error ("`*' not supported for precision or width in printf");
+
+ case 'n':
+ error ("Format specifier `n' not supported in printf");
+
+ case '%':
+ this_argclass = no_arg;
+ break;
+
+ default:
+ if (lcount > 1)
+ this_argclass = long_long_arg;
+ else
+ this_argclass = int_arg;
+ break;
+ }
+ f++;
+ if (this_argclass != no_arg)
+ {
+ strncpy (current_substring, last_arg, f - last_arg);
+ current_substring += f - last_arg;
+ *current_substring++ = '\0';
+ last_arg = f;
+ argclass[nargs_wanted++] = this_argclass;
+ }
+ }
+
+ /* Now, parse all arguments and evaluate them.
+ Store the VALUEs in VAL_ARGS. */
+
+ while (*s != '\0')
+ {
+ char *s1;
+ if (nargs == allocated_args)
+ 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);
+
+ /* If format string wants a float, unchecked-convert the value to
+ floating point of the same size */
+
+ if (argclass[nargs] == double_arg)
+ {
+ struct type *type = VALUE_TYPE (val_args[nargs]);
+ if (TYPE_LENGTH (type) == sizeof (float))
+ VALUE_TYPE (val_args[nargs]) = builtin_type_float;
+ if (TYPE_LENGTH (type) == sizeof (double))
+ VALUE_TYPE (val_args[nargs]) = builtin_type_double;
+ }
+ nargs++;
+ s = s1;
+ if (*s == ',')
+ s++;
+ }
+
+ if (nargs != nargs_wanted)
+ error ("Wrong number of arguments for specified format-string");
+
+ /* Now actually print them. */
+ current_substring = substrings;
+ for (i = 0; i < nargs; i++)
+ {
+ switch (argclass[i])
+ {
+ case string_arg:
+ {
+ char *str;
+ CORE_ADDR tem;
+ int j;
+ tem = value_as_pointer (val_args[i]);
+
+ /* This is a %s argument. Find the length of the string. */
+ for (j = 0; ; j++)
+ {
+ char c;
+ QUIT;
+ read_memory (tem + j, &c, 1);
+ if (c == 0)
+ break;
+ }
+
+ /* Copy the string contents into a string inside GDB. */
+ str = (char *) alloca (j + 1);
+ read_memory (tem, str, j);
+ str[j] = 0;
+
+ printf_filtered (current_substring, str);
+ }
+ break;
+ case double_arg:
+ {
+ double val = value_as_double (val_args[i]);
+ 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]);
+ printf_filtered (current_substring, val);
+ break;
+ }
+#else
+ error ("long long not supported in printf");
+#endif
+ case int_arg:
+ {
+ /* FIXME: there should be separate int_arg and long_arg. */
+ long val = value_as_long (val_args[i]);
+ printf_filtered (current_substring, val);
+ break;
+ }
+ default:
+ error ("internal error in printf_command");
+ }
+ /* Skip to the next substring. */
+ current_substring += strlen (current_substring) + 1;
+ }
+ /* Print the portion of the format string after the last argument. */
+ printf_filtered (last_arg);
+ }
+ do_cleanups (old_cleanups);
+}
+
+/* Dump a specified section of assembly code. With no command line
+ arguments, this command will dump the assembly code for the
+ function surrounding the pc value in the selected frame. With one
+ argument, it will dump the assembly code surrounding that pc value.
+ Two arguments are interpeted as bounds within which to dump
+ assembly. */
+
+/* ARGSUSED */
+static void
+disassemble_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ CORE_ADDR low, high;
+ char *name;
+ CORE_ADDR pc;
+ char *space_index;
+
+ name = NULL;
+ if (!arg)
+ {
+ if (!selected_frame)
+ error ("No frame selected.\n");
+
+ pc = get_frame_pc (selected_frame);
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains program counter for selected frame.\n");
+ }
+ else if (!(space_index = (char *) strchr (arg, ' ')))
+ {
+ /* One argument. */
+ pc = parse_and_eval_address (arg);
+ if (find_pc_partial_function (pc, &name, &low, &high) == 0)
+ error ("No function contains specified address.\n");
+ }
+ else
+ {
+ /* Two arguments. */
+ *space_index = '\0';
+ low = parse_and_eval_address (arg);
+ high = parse_and_eval_address (space_index + 1);
+ }
+
+ printf_filtered ("Dump of assembler code ");
+ if (name != NULL)
+ {
+ printf_filtered ("for function %s:\n", name);
+ }
+ else
+ {
+ 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, gdb_stdout);
+ printf_filtered (":\t");
+ /* 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");
+ gdb_flush (gdb_stdout);
+}
+
+/* Print the instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+static int
+print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ GDB_FILE *stream;
+{
+ disassemble_info info;
+
+ INIT_DISASSEMBLE_INFO (info, stream, (fprintf_ftype)fprintf_filtered);
+ info.read_memory_func = dis_asm_read_memory;
+ info.memory_error_func = dis_asm_memory_error;
+ info.print_address_func = dis_asm_print_address;
+
+ /* If there's no disassembler, something is very wrong. */
+ if (tm_print_insn == NULL)
+ abort ();
+
+ return (*tm_print_insn) (memaddr, &info);
+}
+
+
+void
+_initialize_printcmd ()
+{
+ current_display_number = -1;
+
+ add_info ("address", address_info,
+ "Describe where variable VAR is stored.");
+
+ add_com ("x", class_vars, x_command,
+ concat ("Examine memory: x/FMT ADDRESS.\n\
+ADDRESS is an expression for the memory address to examine.\n\
+FMT is a repeat count followed by a format letter and a size letter.\n\
+Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n\
+ t(binary), f(float), a(address), i(instruction), c(char) and s(string).\n",
+"Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n\
+The specified number of objects of the specified size are printed\n\
+according to the format.\n\n\
+Defaults for format and size letters are those previously used.\n\
+Default count is 1. Default address is following last thing printed\n\
+with this command or \"print\".", NULL));
+
+ add_com ("disassemble", class_vars, disassemble_command,
+ "Disassemble a specified section of memory.\n\
+Default is the function surrounding the pc of the selected frame.\n\
+With a single argument, the function surrounding that address is dumped.\n\
+Two arguments are taken as a range of memory to dump.");
+
+#if 0
+ add_com ("whereis", class_vars, whereis_command,
+ "Print line number and file of definition of variable.");
+#endif
+
+ add_info ("display", display_info,
+ "Expressions to display when program stops, with code numbers.");
+
+ add_cmd ("undisplay", class_vars, undisplay_command,
+ "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+\"delete display\" has the same effect as this command.\n\
+Do \"info display\" to see current list of code numbers.",
+ &cmdlist);
+
+ add_com ("display", class_vars, display_command,
+ "Print value of expression EXP each time the program stops.\n\
+/FMT may be used before EXP as in the \"print\" command.\n\
+/FMT \"i\" or \"s\" or including a size-letter is allowed,\n\
+as in the \"x\" command, and then EXP is used to get the address to examine\n\
+and examining is done as in the \"x\" command.\n\n\
+With no argument, display all currently requested auto-display expressions.\n\
+Use \"undisplay\" to cancel display requests previously made."
+);
+
+ add_cmd ("display", class_vars, enable_display,
+ "Enable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to resume displaying.\n\
+No argument means enable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &enablelist);
+
+ add_cmd ("display", class_vars, disable_display_command,
+ "Disable some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means disable all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &disablelist);
+
+ add_cmd ("display", class_vars, undisplay_command,
+ "Cancel some expressions to be displayed when program stops.\n\
+Arguments are the code numbers of the expressions to stop displaying.\n\
+No argument means cancel all automatic-display expressions.\n\
+Do \"info display\" to see current list of code numbers.", &deletelist);
+
+ add_com ("printf", class_vars, printf_command,
+ "printf \"printf format string\", arg1, arg2, arg3, ..., argn\n\
+This is useful for formatted output in user-defined commands.");
+
+ add_com ("output", class_vars, output_command,
+ "Like \"print\" but don't put in value history and don't print newline.\n\
+This is useful in user-defined commands.");
+
+ add_prefix_cmd ("set", class_vars, set_command,
+concat ("Evaluate expression EXP and assign result to variable VAR, using assignment\n\
+syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
+example). VAR may be a debugger \"convenience\" variable (names starting\n\
+with $), a register (a few standard names starting with $), or an actual\n\
+variable in the program being debugged. EXP is any valid expression.\n",
+"Use \"set variable\" for variables with names identical to set subcommands.\n\
+\nWith a subcommand, this command modifies parts of the gdb environment.\n\
+You can see these environment settings with the \"show\" command.", NULL),
+ &setlist, "set ", 1, &cmdlist);
+
+ /* "call" is the same as "set", but handy for dbx users to call fns. */
+ add_com ("call", class_vars, call_command,
+ "Call a function in the program.\n\
+The argument is the function name and arguments, in the notation of the\n\
+current working language. The result is printed and saved in the value\n\
+history, if it is not void.");
+
+ add_cmd ("variable", class_vars, set_command,
+"Evaluate expression EXP and assign result to variable VAR, using assignment\n\
+syntax appropriate for the current language (VAR = EXP or VAR := EXP for\n\
+example). VAR may be a debugger \"convenience\" variable (names starting\n\
+with $), a register (a few standard names starting with $), or an actual\n\
+variable in the program being debugged. EXP is any valid expression.\n\
+This may usually be abbreviated to simply \"set\".",
+ &setlist);
+
+ add_com ("print", class_vars, print_command,
+ concat ("Print value of expression EXP.\n\
+Variables accessible are those of the lexical environment of the selected\n\
+stack frame, plus all those whose scope is global or an entire file.\n\
+\n\
+$NUM gets previous value number NUM. $ and $$ are the last two values.\n\
+$$NUM refers to NUM'th value back from the last one.\n\
+Names starting with $ refer to registers (with the values they would have\n",
+"if the program were to return to the stack frame now selected, restoring\n\
+all registers saved by frames farther in) or else to debugger\n\
+\"convenience\" variables (any such name not a known register).\n\
+Use assignment expressions to give values to convenience variables.\n",
+ "\n\
+{TYPE}ADREXP refers to a datum of data type TYPE, located at address ADREXP.\n\
+@ is a binary operator for treating consecutive data objects\n\
+anywhere in memory as an array. FOO@NUM gives an array whose first\n\
+element is FOO, whose second element is stored in the space following\n\
+where FOO is stored, etc. FOO must be an expression whose value\n\
+resides in memory.\n",
+ "\n\
+EXP may be preceded with /FMT, where FMT is a format letter\n\
+but no count or size letter (see \"x\" command).", NULL));
+ add_com_alias ("p", "print", class_vars, 1);
+
+ add_com ("inspect", class_vars, inspect_command,
+"Same as \"print\" command, except that if you are running in the epoch\n\
+environment, the value is printed in its own window.");
+
+ add_show_from_set (
+ add_set_cmd ("max-symbolic-offset", no_class, var_uinteger,
+ (char *)&max_symbolic_offset,
+ "Set the largest offset that will be printed in <symbol+1234> form.",
+ &setprintlist),
+ &showprintlist);
+ add_show_from_set (
+ add_set_cmd ("symbol-filename", no_class, var_boolean,
+ (char *)&print_symbol_filename,
+ "Set printing of source filename and line number with <symbol>.",
+ &setprintlist),
+ &showprintlist);
+
+ examine_b_type = init_type (TYPE_CODE_INT, 1, 0, "examine_b_type", NULL);
+ examine_h_type = init_type (TYPE_CODE_INT, 2, 0, "examine_h_type", NULL);
+ examine_w_type = init_type (TYPE_CODE_INT, 4, 0, "examine_w_type", NULL);
+ examine_g_type = init_type (TYPE_CODE_INT, 8, 0, "examine_g_type", NULL);
+}
diff --git a/contrib/gdb/gdb/process_reply.defs b/contrib/gdb/gdb/process_reply.defs
new file mode 100644
index 0000000..824b5c6
--- /dev/null
+++ b/contrib/gdb/gdb/process_reply.defs
@@ -0,0 +1 @@
+#include <hurd/process_reply.defs>
diff --git a/contrib/gdb/gdb/procfs.c b/contrib/gdb/gdb/procfs.c
new file mode 100644
index 0000000..edc062b
--- /dev/null
+++ b/contrib/gdb/gdb/procfs.c
@@ -0,0 +1,3815 @@
+/* Machine independent support for SVR4 /proc (process file system) for GDB.
+ Copyright 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* N O T E S
+
+For information on the details of using /proc consult section proc(4)
+in the UNIX System V Release 4 System Administrator's Reference Manual.
+
+The general register and floating point register sets are manipulated by
+separate ioctl's. This file makes the assumption that if FP0_REGNUM is
+defined, then support for the floating point register set is desired,
+regardless of whether or not the actual target has floating point hardware.
+
+ */
+
+
+#include "defs.h"
+
+#include <sys/types.h>
+#include <time.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
+#include <sys/procfs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "gdb_string.h"
+#include <stropts.h>
+#include <poll.h>
+#include <unistd.h>
+#include "gdb_stat.h"
+
+#include "inferior.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcore.h"
+#include "thread.h"
+
+#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */
+
+#ifndef PROC_NAME_FMT
+#define PROC_NAME_FMT "/proc/%05d"
+#endif
+
+extern struct target_ops procfs_ops; /* Forward declaration */
+
+#if 1 /* FIXME: Gross and ugly hack to resolve coredep.c global */
+CORE_ADDR kernel_u_addr;
+#endif
+
+#ifdef BROKEN_SIGINFO_H /* Workaround broken SGS <sys/siginfo.h> */
+#undef si_pid
+#define si_pid _data._proc.pid
+#undef si_uid
+#define si_uid _data._proc._pdata._kill.uid
+#endif /* BROKEN_SIGINFO_H */
+
+/* All access to the inferior, either one started by gdb or one that has
+ been attached to, is controlled by an instance of a procinfo structure,
+ defined below. Since gdb currently only handles one inferior at a time,
+ the procinfo structure for the inferior is statically allocated and
+ only one exists at any given time. There is a separate procinfo
+ structure for use by the "info proc" command, so that we can print
+ useful information about any random process without interfering with
+ the inferior's procinfo information. */
+
+struct procinfo {
+ struct procinfo *next;
+ int pid; /* Process ID of inferior */
+ int fd; /* File descriptor for /proc entry */
+ char *pathname; /* Pathname to /proc entry */
+ int had_event; /* poll/select says something happened */
+ int was_stopped; /* Nonzero if was stopped prior to attach */
+ int nopass_next_sigstop; /* Don't pass a sigstop on next resume */
+ prrun_t prrun; /* Control state when it is run */
+ prstatus_t prstatus; /* Current process status info */
+ gregset_t gregset; /* General register set */
+ fpregset_t fpregset; /* Floating point register set */
+ fltset_t fltset; /* Current traced hardware fault set */
+ sigset_t trace; /* Current traced signal set */
+ sysset_t exitset; /* Current traced system call exit set */
+ sysset_t entryset; /* Current traced system call entry set */
+ fltset_t saved_fltset; /* Saved traced hardware fault set */
+ sigset_t saved_trace; /* Saved traced signal set */
+ sigset_t saved_sighold; /* Saved held signal set */
+ sysset_t saved_exitset; /* Saved traced system call exit set */
+ sysset_t saved_entryset; /* Saved traced system call entry set */
+};
+
+/* List of inferior process information */
+static struct procinfo *procinfo_list = NULL;
+
+static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
+
+static int num_poll_list = 0; /* Number of entries in poll_list */
+
+static int last_resume_pid = -1; /* Last pid used with procfs_resume */
+
+/* Much of the information used in the /proc interface, particularly for
+ printing status information, is kept as tables of structures of the
+ following form. These tables can be used to map numeric values to
+ their symbolic names and to a string that describes their specific use. */
+
+struct trans {
+ int value; /* The numeric value */
+ char *name; /* The equivalent symbolic value */
+ char *desc; /* Short description of value */
+};
+
+/* Translate bits in the pr_flags member of the prstatus structure, into the
+ names and desc information. */
+
+static struct trans pr_flag_table[] =
+{
+#if defined (PR_STOPPED)
+ { PR_STOPPED, "PR_STOPPED", "Process is stopped" },
+#endif
+#if defined (PR_ISTOP)
+ { PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest" },
+#endif
+#if defined (PR_DSTOP)
+ { PR_DSTOP, "PR_DSTOP", "A stop directive is in effect" },
+#endif
+#if defined (PR_ASLEEP)
+ { PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call" },
+#endif
+#if defined (PR_FORK)
+ { PR_FORK, "PR_FORK", "Inherit-on-fork is in effect" },
+#endif
+#if defined (PR_RLC)
+ { PR_RLC, "PR_RLC", "Run-on-last-close is in effect" },
+#endif
+#if defined (PR_PTRACE)
+ { PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace" },
+#endif
+#if defined (PR_PCINVAL)
+ { PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address" },
+#endif
+#if defined (PR_ISSYS)
+ { PR_ISSYS, "PR_ISSYS", "Is a system process" },
+#endif
+#if defined (PR_STEP)
+ { PR_STEP, "PR_STEP", "Process has single step pending" },
+#endif
+#if defined (PR_KLC)
+ { PR_KLC, "PR_KLC", "Kill-on-last-close is in effect" },
+#endif
+#if defined (PR_ASYNC)
+ { PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect" },
+#endif
+#if defined (PR_PCOMPAT)
+ { PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
+#endif
+ { 0, NULL, NULL }
+};
+
+/* Translate values in the pr_why field of the prstatus struct. */
+
+static struct trans pr_why_table[] =
+{
+#if defined (PR_REQUESTED)
+ { PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP" },
+#endif
+#if defined (PR_SIGNALLED)
+ { PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
+#endif
+#if defined (PR_FAULTED)
+ { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
+#endif
+#if defined (PR_SYSENTRY)
+ { PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" },
+#endif
+#if defined (PR_SYSEXIT)
+ { PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call" },
+#endif
+#if defined (PR_JOBCONTROL)
+ { PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
+#endif
+#if defined (PR_SUSPENDED)
+ { PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
+#endif
+ { 0, NULL, NULL }
+};
+
+/* Hardware fault translation table. */
+
+static struct trans faults_table[] =
+{
+#if defined (FLTILL)
+ { FLTILL, "FLTILL", "Illegal instruction" },
+#endif
+#if defined (FLTPRIV)
+ { FLTPRIV, "FLTPRIV", "Privileged instruction" },
+#endif
+#if defined (FLTBPT)
+ { FLTBPT, "FLTBPT", "Breakpoint trap" },
+#endif
+#if defined (FLTTRACE)
+ { FLTTRACE, "FLTTRACE", "Trace trap" },
+#endif
+#if defined (FLTACCESS)
+ { FLTACCESS, "FLTACCESS", "Memory access fault" },
+#endif
+#if defined (FLTBOUNDS)
+ { FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation" },
+#endif
+#if defined (FLTIOVF)
+ { FLTIOVF, "FLTIOVF", "Integer overflow" },
+#endif
+#if defined (FLTIZDIV)
+ { FLTIZDIV, "FLTIZDIV", "Integer zero divide" },
+#endif
+#if defined (FLTFPE)
+ { FLTFPE, "FLTFPE", "Floating-point exception" },
+#endif
+#if defined (FLTSTACK)
+ { FLTSTACK, "FLTSTACK", "Unrecoverable stack fault" },
+#endif
+#if defined (FLTPAGE)
+ { FLTPAGE, "FLTPAGE", "Recoverable page fault" },
+#endif
+ { 0, NULL, NULL }
+};
+
+/* Translation table for signal generation information. See UNIX System
+ V Release 4 Programmer's Reference Manual, siginfo(5). */
+
+static struct sigcode {
+ int signo;
+ int code;
+ char *codename;
+ char *desc;
+} siginfo_table[] = {
+#if defined (SIGILL) && defined (ILL_ILLOPC)
+ { SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode" },
+#endif
+#if defined (SIGILL) && defined (ILL_ILLOPN)
+ { SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand", },
+#endif
+#if defined (SIGILL) && defined (ILL_ILLADR)
+ { SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode" },
+#endif
+#if defined (SIGILL) && defined (ILL_ILLTRP)
+ { SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap" },
+#endif
+#if defined (SIGILL) && defined (ILL_PRVOPC)
+ { SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode" },
+#endif
+#if defined (SIGILL) && defined (ILL_PRVREG)
+ { SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register" },
+#endif
+#if defined (SIGILL) && defined (ILL_COPROC)
+ { SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error" },
+#endif
+#if defined (SIGILL) && defined (ILL_BADSTK)
+ { SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error" },
+#endif
+#if defined (SIGFPE) && defined (FPE_INTDIV)
+ { SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero" },
+#endif
+#if defined (SIGFPE) && defined (FPE_INTOVF)
+ { SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTDIV)
+ { SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTOVF)
+ { SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTUND)
+ { SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTRES)
+ { SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTINV)
+ { SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation" },
+#endif
+#if defined (SIGFPE) && defined (FPE_FLTSUB)
+ { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range" },
+#endif
+#if defined (SIGSEGV) && defined (SEGV_MAPERR)
+ { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object" },
+#endif
+#if defined (SIGSEGV) && defined (SEGV_ACCERR)
+ { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object" },
+#endif
+#if defined (SIGBUS) && defined (BUS_ADRALN)
+ { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment" },
+#endif
+#if defined (SIGBUS) && defined (BUS_ADRERR)
+ { SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address" },
+#endif
+#if defined (SIGBUS) && defined (BUS_OBJERR)
+ { SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error" },
+#endif
+#if defined (SIGTRAP) && defined (TRAP_BRKPT)
+ { SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint" },
+#endif
+#if defined (SIGTRAP) && defined (TRAP_TRACE)
+ { SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap" },
+#endif
+#if defined (SIGCLD) && defined (CLD_EXITED)
+ { SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited" },
+#endif
+#if defined (SIGCLD) && defined (CLD_KILLED)
+ { SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed" },
+#endif
+#if defined (SIGCLD) && defined (CLD_DUMPED)
+ { SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally" },
+#endif
+#if defined (SIGCLD) && defined (CLD_TRAPPED)
+ { SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped" },
+#endif
+#if defined (SIGCLD) && defined (CLD_STOPPED)
+ { SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped" },
+#endif
+#if defined (SIGCLD) && defined (CLD_CONTINUED)
+ { SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_IN)
+ { SIGPOLL, POLL_IN, "POLL_IN", "Input input available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_OUT)
+ { SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_MSG)
+ { SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_ERR)
+ { SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_PRI)
+ { SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available" },
+#endif
+#if defined (SIGPOLL) && defined (POLL_HUP)
+ { SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected" },
+#endif
+ { 0, 0, NULL, NULL }
+};
+
+static char *syscall_table[MAX_SYSCALLS];
+
+/* Prototypes for local functions */
+
+static void set_proc_siginfo PARAMS ((struct procinfo *, int));
+
+static void init_syscall_table PARAMS ((void));
+
+static char *syscallname PARAMS ((int));
+
+static char *signalname PARAMS ((int));
+
+static char *errnoname PARAMS ((int));
+
+static int proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
+
+static int open_proc_file PARAMS ((int, struct procinfo *, int));
+
+static void close_proc_file PARAMS ((struct procinfo *));
+
+static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
+
+static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *)) ATTR_NORETURN;
+
+static void info_proc PARAMS ((char *, int));
+
+static void info_proc_flags PARAMS ((struct procinfo *, int));
+
+static void info_proc_stop PARAMS ((struct procinfo *, int));
+
+static void info_proc_siginfo PARAMS ((struct procinfo *, int));
+
+static void info_proc_syscalls PARAMS ((struct procinfo *, int));
+
+static void info_proc_mappings PARAMS ((struct procinfo *, int));
+
+static void info_proc_signals PARAMS ((struct procinfo *, int));
+
+static void info_proc_faults PARAMS ((struct procinfo *, int));
+
+static char *mappingflags PARAMS ((long));
+
+static char *lookupname PARAMS ((struct trans *, unsigned int, char *));
+
+static char *lookupdesc PARAMS ((struct trans *, unsigned int));
+
+static int do_attach PARAMS ((int pid));
+
+static void do_detach PARAMS ((int siggnal));
+
+static void procfs_create_inferior PARAMS ((char *, char *, char **));
+
+static void procfs_notice_signals PARAMS ((int pid));
+
+static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
+
+/* External function prototypes that can't be easily included in any
+ header file because the args are typedefs in system include files. */
+
+extern void supply_gregset PARAMS ((gregset_t *));
+
+extern void fill_gregset PARAMS ((gregset_t *, int));
+
+extern void supply_fpregset PARAMS ((fpregset_t *));
+
+extern void fill_fpregset PARAMS ((fpregset_t *, int));
+
+/*
+
+LOCAL FUNCTION
+
+ find_procinfo -- convert a process id to a struct procinfo
+
+SYNOPSIS
+
+ static struct procinfo * find_procinfo (pid_t pid, int okfail);
+
+DESCRIPTION
+
+ Given a process id, look it up in the procinfo chain. Returns
+ a struct procinfo *. If can't find pid, then call error(),
+ unless okfail is set, in which case, return NULL;
+ */
+
+static struct procinfo *
+find_procinfo (pid, okfail)
+ pid_t pid;
+ int okfail;
+{
+ struct procinfo *procinfo;
+
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ if (procinfo->pid == pid)
+ return procinfo;
+
+ if (okfail)
+ return NULL;
+
+ error ("procfs (find_procinfo): Couldn't locate pid %d", pid);
+}
+
+/*
+
+LOCAL MACRO
+
+ current_procinfo -- convert inferior_pid to a struct procinfo
+
+SYNOPSIS
+
+ static struct procinfo * current_procinfo;
+
+DESCRIPTION
+
+ Looks up inferior_pid in the procinfo chain. Always returns a
+ struct procinfo *. If process can't be found, we error() out.
+ */
+
+#define current_procinfo find_procinfo (inferior_pid, 0)
+
+/*
+
+LOCAL FUNCTION
+
+ add_fd -- Add the fd to the poll/select list
+
+SYNOPSIS
+
+ static void add_fd (struct procinfo *);
+
+DESCRIPTION
+
+ Add the fd of the supplied procinfo to the list of fds used for
+ poll/select operations.
+ */
+
+static void
+add_fd (pi)
+ struct procinfo *pi;
+{
+ if (num_poll_list <= 0)
+ poll_list = (struct pollfd *) xmalloc (sizeof (struct pollfd));
+ else
+ poll_list = (struct pollfd *) xrealloc (poll_list,
+ (num_poll_list + 1)
+ * sizeof (struct pollfd));
+ poll_list[num_poll_list].fd = pi->fd;
+ poll_list[num_poll_list].events = POLLPRI;
+
+ num_poll_list++;
+}
+
+static void
+remove_fd (pi)
+ struct procinfo *pi;
+{
+ int i;
+
+ for (i = 0; i < num_poll_list; i++)
+ {
+ if (poll_list[i].fd == pi->fd)
+ {
+ if (i != num_poll_list - 1)
+ memcpy (poll_list, poll_list + i + 1,
+ (num_poll_list - i - 1) * sizeof (struct pollfd));
+
+ num_poll_list--;
+
+ if (num_poll_list == 0)
+ free (poll_list);
+ else
+ poll_list = (struct pollfd *) xrealloc (poll_list,
+ num_poll_list
+ * sizeof (struct pollfd));
+ return;
+ }
+ }
+}
+
+#define LOSING_POLL unixware_sux
+
+static struct procinfo *
+wait_fd ()
+{
+ struct procinfo *pi;
+ int num_fds;
+ int i;
+
+ set_sigint_trap (); /* Causes SIGINT to be passed on to the
+ attached process. */
+ set_sigio_trap ();
+
+#ifndef LOSING_POLL
+ num_fds = poll (poll_list, num_poll_list, -1);
+#else
+ pi = current_procinfo;
+
+ while (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
+ {
+ if (errno == ENOENT)
+ {
+ /* Process exited. */
+ pi->prstatus.pr_flags = 0;
+ break;
+ }
+ else if (errno != EINTR)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCWSTOP failed");
+ }
+ }
+ pi->had_event = 1;
+#endif
+
+ clear_sigint_trap ();
+ clear_sigio_trap ();
+
+#ifndef LOSING_POLL
+
+ if (num_fds <= 0)
+ {
+ print_sys_errmsg ("poll failed\n", errno);
+ error ("Poll failed, returned %d", num_fds);
+ }
+
+ for (i = 0; i < num_poll_list && num_fds > 0; i++)
+ {
+ if ((poll_list[i].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)
+ continue;
+ for (pi = procinfo_list; pi; pi = pi->next)
+ {
+ if (poll_list[i].fd == pi->fd)
+ {
+ if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSTATUS failed");
+ }
+ num_fds--;
+ pi->had_event = 1;
+ break;
+ }
+ }
+ if (!pi)
+ error ("procfs_wait: Couldn't find procinfo for fd %d\n",
+ poll_list[i].fd);
+ }
+#endif /* LOSING_POLL */
+
+ return pi;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ lookupdesc -- translate a value to a summary desc string
+
+SYNOPSIS
+
+ static char *lookupdesc (struct trans *transp, unsigned int val);
+
+DESCRIPTION
+
+ Given a pointer to a translation table and a value to be translated,
+ lookup the desc string and return it.
+ */
+
+static char *
+lookupdesc (transp, val)
+ struct trans *transp;
+ unsigned int val;
+{
+ char *desc;
+
+ for (desc = NULL; transp -> name != NULL; transp++)
+ {
+ if (transp -> value == val)
+ {
+ desc = transp -> desc;
+ break;
+ }
+ }
+
+ /* Didn't find a translation for the specified value, set a default one. */
+
+ if (desc == NULL)
+ {
+ desc = "Unknown";
+ }
+ return (desc);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ lookupname -- translate a value to symbolic name
+
+SYNOPSIS
+
+ static char *lookupname (struct trans *transp, unsigned int val,
+ char *prefix);
+
+DESCRIPTION
+
+ Given a pointer to a translation table, a value to be translated,
+ and a default prefix to return if the value can't be translated,
+ match the value with one of the translation table entries and
+ return a pointer to the symbolic name.
+
+ If no match is found it just returns the value as a printable string,
+ with the given prefix. The previous such value, if any, is freed
+ at this time.
+ */
+
+static char *
+lookupname (transp, val, prefix)
+ struct trans *transp;
+ unsigned int val;
+ char *prefix;
+{
+ static char *locbuf;
+ char *name;
+
+ for (name = NULL; transp -> name != NULL; transp++)
+ {
+ if (transp -> value == val)
+ {
+ name = transp -> name;
+ break;
+ }
+ }
+
+ /* Didn't find a translation for the specified value, build a default
+ one using the specified prefix and return it. The lifetime of
+ the value is only until the next one is needed. */
+
+ if (name == NULL)
+ {
+ if (locbuf != NULL)
+ {
+ free (locbuf);
+ }
+ locbuf = xmalloc (strlen (prefix) + 16);
+ sprintf (locbuf, "%s %u", prefix, val);
+ name = locbuf;
+ }
+ return (name);
+}
+
+static char *
+sigcodename (sip)
+ siginfo_t *sip;
+{
+ struct sigcode *scp;
+ char *name = NULL;
+ static char locbuf[32];
+
+ for (scp = siginfo_table; scp -> codename != NULL; scp++)
+ {
+ if ((scp -> signo == sip -> si_signo) &&
+ (scp -> code == sip -> si_code))
+ {
+ name = scp -> codename;
+ break;
+ }
+ }
+ if (name == NULL)
+ {
+ sprintf (locbuf, "sigcode %u", sip -> si_signo);
+ name = locbuf;
+ }
+ return (name);
+}
+
+static char *
+sigcodedesc (sip)
+ siginfo_t *sip;
+{
+ struct sigcode *scp;
+ char *desc = NULL;
+
+ for (scp = siginfo_table; scp -> codename != NULL; scp++)
+ {
+ if ((scp -> signo == sip -> si_signo) &&
+ (scp -> code == sip -> si_code))
+ {
+ desc = scp -> desc;
+ break;
+ }
+ }
+ if (desc == NULL)
+ {
+ desc = "Unrecognized signal or trap use";
+ }
+ return (desc);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ syscallname - translate a system call number into a system call name
+
+SYNOPSIS
+
+ char *syscallname (int syscallnum)
+
+DESCRIPTION
+
+ Given a system call number, translate it into the printable name
+ of a system call, or into "syscall <num>" if it is an unknown
+ number.
+ */
+
+static char *
+syscallname (syscallnum)
+ int syscallnum;
+{
+ static char locbuf[32];
+ char *rtnval;
+
+ if (syscallnum >= 0 && syscallnum < MAX_SYSCALLS)
+ {
+ rtnval = syscall_table[syscallnum];
+ }
+ else
+ {
+ sprintf (locbuf, "syscall %u", syscallnum);
+ rtnval = locbuf;
+ }
+ return (rtnval);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ init_syscall_table - initialize syscall translation table
+
+SYNOPSIS
+
+ void init_syscall_table (void)
+
+DESCRIPTION
+
+ Dynamically initialize the translation table to convert system
+ call numbers into printable system call names. Done once per
+ gdb run, on initialization.
+
+NOTES
+
+ This is awfully ugly, but preprocessor tricks to make it prettier
+ tend to be nonportable.
+ */
+
+static void
+init_syscall_table ()
+{
+#if defined (SYS_exit)
+ syscall_table[SYS_exit] = "exit";
+#endif
+#if defined (SYS_fork)
+ syscall_table[SYS_fork] = "fork";
+#endif
+#if defined (SYS_read)
+ syscall_table[SYS_read] = "read";
+#endif
+#if defined (SYS_write)
+ syscall_table[SYS_write] = "write";
+#endif
+#if defined (SYS_open)
+ syscall_table[SYS_open] = "open";
+#endif
+#if defined (SYS_close)
+ syscall_table[SYS_close] = "close";
+#endif
+#if defined (SYS_wait)
+ syscall_table[SYS_wait] = "wait";
+#endif
+#if defined (SYS_creat)
+ syscall_table[SYS_creat] = "creat";
+#endif
+#if defined (SYS_link)
+ syscall_table[SYS_link] = "link";
+#endif
+#if defined (SYS_unlink)
+ syscall_table[SYS_unlink] = "unlink";
+#endif
+#if defined (SYS_exec)
+ syscall_table[SYS_exec] = "exec";
+#endif
+#if defined (SYS_execv)
+ syscall_table[SYS_execv] = "execv";
+#endif
+#if defined (SYS_execve)
+ syscall_table[SYS_execve] = "execve";
+#endif
+#if defined (SYS_chdir)
+ syscall_table[SYS_chdir] = "chdir";
+#endif
+#if defined (SYS_time)
+ syscall_table[SYS_time] = "time";
+#endif
+#if defined (SYS_mknod)
+ syscall_table[SYS_mknod] = "mknod";
+#endif
+#if defined (SYS_chmod)
+ syscall_table[SYS_chmod] = "chmod";
+#endif
+#if defined (SYS_chown)
+ syscall_table[SYS_chown] = "chown";
+#endif
+#if defined (SYS_brk)
+ syscall_table[SYS_brk] = "brk";
+#endif
+#if defined (SYS_stat)
+ syscall_table[SYS_stat] = "stat";
+#endif
+#if defined (SYS_lseek)
+ syscall_table[SYS_lseek] = "lseek";
+#endif
+#if defined (SYS_getpid)
+ syscall_table[SYS_getpid] = "getpid";
+#endif
+#if defined (SYS_mount)
+ syscall_table[SYS_mount] = "mount";
+#endif
+#if defined (SYS_umount)
+ syscall_table[SYS_umount] = "umount";
+#endif
+#if defined (SYS_setuid)
+ syscall_table[SYS_setuid] = "setuid";
+#endif
+#if defined (SYS_getuid)
+ syscall_table[SYS_getuid] = "getuid";
+#endif
+#if defined (SYS_stime)
+ syscall_table[SYS_stime] = "stime";
+#endif
+#if defined (SYS_ptrace)
+ syscall_table[SYS_ptrace] = "ptrace";
+#endif
+#if defined (SYS_alarm)
+ syscall_table[SYS_alarm] = "alarm";
+#endif
+#if defined (SYS_fstat)
+ syscall_table[SYS_fstat] = "fstat";
+#endif
+#if defined (SYS_pause)
+ syscall_table[SYS_pause] = "pause";
+#endif
+#if defined (SYS_utime)
+ syscall_table[SYS_utime] = "utime";
+#endif
+#if defined (SYS_stty)
+ syscall_table[SYS_stty] = "stty";
+#endif
+#if defined (SYS_gtty)
+ syscall_table[SYS_gtty] = "gtty";
+#endif
+#if defined (SYS_access)
+ syscall_table[SYS_access] = "access";
+#endif
+#if defined (SYS_nice)
+ syscall_table[SYS_nice] = "nice";
+#endif
+#if defined (SYS_statfs)
+ syscall_table[SYS_statfs] = "statfs";
+#endif
+#if defined (SYS_sync)
+ syscall_table[SYS_sync] = "sync";
+#endif
+#if defined (SYS_kill)
+ syscall_table[SYS_kill] = "kill";
+#endif
+#if defined (SYS_fstatfs)
+ syscall_table[SYS_fstatfs] = "fstatfs";
+#endif
+#if defined (SYS_pgrpsys)
+ syscall_table[SYS_pgrpsys] = "pgrpsys";
+#endif
+#if defined (SYS_xenix)
+ syscall_table[SYS_xenix] = "xenix";
+#endif
+#if defined (SYS_dup)
+ syscall_table[SYS_dup] = "dup";
+#endif
+#if defined (SYS_pipe)
+ syscall_table[SYS_pipe] = "pipe";
+#endif
+#if defined (SYS_times)
+ syscall_table[SYS_times] = "times";
+#endif
+#if defined (SYS_profil)
+ syscall_table[SYS_profil] = "profil";
+#endif
+#if defined (SYS_plock)
+ syscall_table[SYS_plock] = "plock";
+#endif
+#if defined (SYS_setgid)
+ syscall_table[SYS_setgid] = "setgid";
+#endif
+#if defined (SYS_getgid)
+ syscall_table[SYS_getgid] = "getgid";
+#endif
+#if defined (SYS_signal)
+ syscall_table[SYS_signal] = "signal";
+#endif
+#if defined (SYS_msgsys)
+ syscall_table[SYS_msgsys] = "msgsys";
+#endif
+#if defined (SYS_sys3b)
+ syscall_table[SYS_sys3b] = "sys3b";
+#endif
+#if defined (SYS_acct)
+ syscall_table[SYS_acct] = "acct";
+#endif
+#if defined (SYS_shmsys)
+ syscall_table[SYS_shmsys] = "shmsys";
+#endif
+#if defined (SYS_semsys)
+ syscall_table[SYS_semsys] = "semsys";
+#endif
+#if defined (SYS_ioctl)
+ syscall_table[SYS_ioctl] = "ioctl";
+#endif
+#if defined (SYS_uadmin)
+ syscall_table[SYS_uadmin] = "uadmin";
+#endif
+#if defined (SYS_utssys)
+ syscall_table[SYS_utssys] = "utssys";
+#endif
+#if defined (SYS_fsync)
+ syscall_table[SYS_fsync] = "fsync";
+#endif
+#if defined (SYS_umask)
+ syscall_table[SYS_umask] = "umask";
+#endif
+#if defined (SYS_chroot)
+ syscall_table[SYS_chroot] = "chroot";
+#endif
+#if defined (SYS_fcntl)
+ syscall_table[SYS_fcntl] = "fcntl";
+#endif
+#if defined (SYS_ulimit)
+ syscall_table[SYS_ulimit] = "ulimit";
+#endif
+#if defined (SYS_rfsys)
+ syscall_table[SYS_rfsys] = "rfsys";
+#endif
+#if defined (SYS_rmdir)
+ syscall_table[SYS_rmdir] = "rmdir";
+#endif
+#if defined (SYS_mkdir)
+ syscall_table[SYS_mkdir] = "mkdir";
+#endif
+#if defined (SYS_getdents)
+ syscall_table[SYS_getdents] = "getdents";
+#endif
+#if defined (SYS_sysfs)
+ syscall_table[SYS_sysfs] = "sysfs";
+#endif
+#if defined (SYS_getmsg)
+ syscall_table[SYS_getmsg] = "getmsg";
+#endif
+#if defined (SYS_putmsg)
+ syscall_table[SYS_putmsg] = "putmsg";
+#endif
+#if defined (SYS_poll)
+ syscall_table[SYS_poll] = "poll";
+#endif
+#if defined (SYS_lstat)
+ syscall_table[SYS_lstat] = "lstat";
+#endif
+#if defined (SYS_symlink)
+ syscall_table[SYS_symlink] = "symlink";
+#endif
+#if defined (SYS_readlink)
+ syscall_table[SYS_readlink] = "readlink";
+#endif
+#if defined (SYS_setgroups)
+ syscall_table[SYS_setgroups] = "setgroups";
+#endif
+#if defined (SYS_getgroups)
+ syscall_table[SYS_getgroups] = "getgroups";
+#endif
+#if defined (SYS_fchmod)
+ syscall_table[SYS_fchmod] = "fchmod";
+#endif
+#if defined (SYS_fchown)
+ syscall_table[SYS_fchown] = "fchown";
+#endif
+#if defined (SYS_sigprocmask)
+ syscall_table[SYS_sigprocmask] = "sigprocmask";
+#endif
+#if defined (SYS_sigsuspend)
+ syscall_table[SYS_sigsuspend] = "sigsuspend";
+#endif
+#if defined (SYS_sigaltstack)
+ syscall_table[SYS_sigaltstack] = "sigaltstack";
+#endif
+#if defined (SYS_sigaction)
+ syscall_table[SYS_sigaction] = "sigaction";
+#endif
+#if defined (SYS_sigpending)
+ syscall_table[SYS_sigpending] = "sigpending";
+#endif
+#if defined (SYS_context)
+ syscall_table[SYS_context] = "context";
+#endif
+#if defined (SYS_evsys)
+ syscall_table[SYS_evsys] = "evsys";
+#endif
+#if defined (SYS_evtrapret)
+ syscall_table[SYS_evtrapret] = "evtrapret";
+#endif
+#if defined (SYS_statvfs)
+ syscall_table[SYS_statvfs] = "statvfs";
+#endif
+#if defined (SYS_fstatvfs)
+ syscall_table[SYS_fstatvfs] = "fstatvfs";
+#endif
+#if defined (SYS_nfssys)
+ syscall_table[SYS_nfssys] = "nfssys";
+#endif
+#if defined (SYS_waitsys)
+ syscall_table[SYS_waitsys] = "waitsys";
+#endif
+#if defined (SYS_sigsendsys)
+ syscall_table[SYS_sigsendsys] = "sigsendsys";
+#endif
+#if defined (SYS_hrtsys)
+ syscall_table[SYS_hrtsys] = "hrtsys";
+#endif
+#if defined (SYS_acancel)
+ syscall_table[SYS_acancel] = "acancel";
+#endif
+#if defined (SYS_async)
+ syscall_table[SYS_async] = "async";
+#endif
+#if defined (SYS_priocntlsys)
+ syscall_table[SYS_priocntlsys] = "priocntlsys";
+#endif
+#if defined (SYS_pathconf)
+ syscall_table[SYS_pathconf] = "pathconf";
+#endif
+#if defined (SYS_mincore)
+ syscall_table[SYS_mincore] = "mincore";
+#endif
+#if defined (SYS_mmap)
+ syscall_table[SYS_mmap] = "mmap";
+#endif
+#if defined (SYS_mprotect)
+ syscall_table[SYS_mprotect] = "mprotect";
+#endif
+#if defined (SYS_munmap)
+ syscall_table[SYS_munmap] = "munmap";
+#endif
+#if defined (SYS_fpathconf)
+ syscall_table[SYS_fpathconf] = "fpathconf";
+#endif
+#if defined (SYS_vfork)
+ syscall_table[SYS_vfork] = "vfork";
+#endif
+#if defined (SYS_fchdir)
+ syscall_table[SYS_fchdir] = "fchdir";
+#endif
+#if defined (SYS_readv)
+ syscall_table[SYS_readv] = "readv";
+#endif
+#if defined (SYS_writev)
+ syscall_table[SYS_writev] = "writev";
+#endif
+#if defined (SYS_xstat)
+ syscall_table[SYS_xstat] = "xstat";
+#endif
+#if defined (SYS_lxstat)
+ syscall_table[SYS_lxstat] = "lxstat";
+#endif
+#if defined (SYS_fxstat)
+ syscall_table[SYS_fxstat] = "fxstat";
+#endif
+#if defined (SYS_xmknod)
+ syscall_table[SYS_xmknod] = "xmknod";
+#endif
+#if defined (SYS_clocal)
+ syscall_table[SYS_clocal] = "clocal";
+#endif
+#if defined (SYS_setrlimit)
+ syscall_table[SYS_setrlimit] = "setrlimit";
+#endif
+#if defined (SYS_getrlimit)
+ syscall_table[SYS_getrlimit] = "getrlimit";
+#endif
+#if defined (SYS_lchown)
+ syscall_table[SYS_lchown] = "lchown";
+#endif
+#if defined (SYS_memcntl)
+ syscall_table[SYS_memcntl] = "memcntl";
+#endif
+#if defined (SYS_getpmsg)
+ syscall_table[SYS_getpmsg] = "getpmsg";
+#endif
+#if defined (SYS_putpmsg)
+ syscall_table[SYS_putpmsg] = "putpmsg";
+#endif
+#if defined (SYS_rename)
+ syscall_table[SYS_rename] = "rename";
+#endif
+#if defined (SYS_uname)
+ syscall_table[SYS_uname] = "uname";
+#endif
+#if defined (SYS_setegid)
+ syscall_table[SYS_setegid] = "setegid";
+#endif
+#if defined (SYS_sysconfig)
+ syscall_table[SYS_sysconfig] = "sysconfig";
+#endif
+#if defined (SYS_adjtime)
+ syscall_table[SYS_adjtime] = "adjtime";
+#endif
+#if defined (SYS_systeminfo)
+ syscall_table[SYS_systeminfo] = "systeminfo";
+#endif
+#if defined (SYS_seteuid)
+ syscall_table[SYS_seteuid] = "seteuid";
+#endif
+#if defined (SYS_sproc)
+ syscall_table[SYS_sproc] = "sproc";
+#endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_kill_inferior - kill any currently inferior
+
+SYNOPSIS
+
+ void procfs_kill_inferior (void)
+
+DESCRIPTION
+
+ Kill any current inferior.
+
+NOTES
+
+ Kills even attached inferiors. Presumably the user has already
+ been prompted that the inferior is an attached one rather than
+ one started by gdb. (FIXME?)
+
+*/
+
+static void
+procfs_kill_inferior ()
+{
+ target_mourn_inferior ();
+}
+
+/*
+
+LOCAL FUNCTION
+
+ unconditionally_kill_inferior - terminate the inferior
+
+SYNOPSIS
+
+ static void unconditionally_kill_inferior (struct procinfo *)
+
+DESCRIPTION
+
+ Kill the specified inferior.
+
+NOTE
+
+ A possibly useful enhancement would be to first try sending
+ the inferior a terminate signal, politely asking it to commit
+ suicide, before we murder it (we could call that
+ politely_kill_inferior()).
+
+*/
+
+static void
+unconditionally_kill_inferior (pi)
+ struct procinfo *pi;
+{
+ int signo;
+ int ppid;
+
+ ppid = pi->prstatus.pr_ppid;
+
+ signo = SIGKILL;
+
+#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
+ /* Alpha OSF/1-3.x procfs needs a clear of the current signal
+ before the PIOCKILL, otherwise it might generate a corrupted core
+ file for the inferior. */
+ ioctl (pi->fd, PIOCSSIG, NULL);
+#endif
+#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL
+ /* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal
+ to kill the inferior, otherwise it might remain stopped with a
+ pending SIGKILL.
+ We do not check the result of the PIOCSSIG, the inferior might have
+ died already. */
+ {
+ struct siginfo newsiginfo;
+
+ memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+ newsiginfo.si_signo = signo;
+ newsiginfo.si_code = 0;
+ newsiginfo.si_errno = 0;
+ newsiginfo.si_pid = getpid ();
+ newsiginfo.si_uid = getuid ();
+ ioctl (pi->fd, PIOCSSIG, &newsiginfo);
+ }
+#else
+ ioctl (pi->fd, PIOCKILL, &signo);
+#endif
+
+ close_proc_file (pi);
+
+/* Only wait() for our direct children. Our grandchildren zombies are killed
+ by the death of their parents. */
+
+ if (ppid == getpid())
+ wait ((int *) 0);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_xfer_memory -- copy data to or from inferior memory space
+
+SYNOPSIS
+
+ int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
+ int dowrite, struct target_ops target)
+
+DESCRIPTION
+
+ Copy LEN bytes to/from inferior's memory starting at MEMADDR
+ from/to debugger memory starting at MYADDR. Copy from inferior
+ if DOWRITE is zero or to inferior if DOWRITE is nonzero.
+
+ Returns the length copied, which is either the LEN argument or
+ zero. This xfer function does not do partial moves, since procfs_ops
+ doesn't allow memory operations to cross below us in the target stack
+ anyway.
+
+NOTES
+
+ The /proc interface makes this an almost trivial task.
+ */
+
+static int
+procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int dowrite;
+ struct target_ops *target; /* ignored */
+{
+ int nbytes = 0;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (lseek(pi->fd, (off_t) memaddr, 0) == (off_t) memaddr)
+ {
+ if (dowrite)
+ {
+ nbytes = write (pi->fd, myaddr, len);
+ }
+ else
+ {
+ nbytes = read (pi->fd, myaddr, len);
+ }
+ if (nbytes < 0)
+ {
+ nbytes = 0;
+ }
+ }
+ return (nbytes);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_store_registers -- copy register values back to inferior
+
+SYNOPSIS
+
+ void procfs_store_registers (int regno)
+
+DESCRIPTION
+
+ Store our current register values back into the inferior. If
+ REGNO is -1 then store all the register, otherwise store just
+ the value specified by REGNO.
+
+NOTES
+
+ If we are storing only a single register, we first have to get all
+ the current values from the process, overwrite the desired register
+ in the gregset with the one we want from gdb's registers, and then
+ send the whole set back to the process. For writing all the
+ registers, all we have to do is generate the gregset and send it to
+ the process.
+
+ Also note that the process has to be stopped on an event of interest
+ for this to work, which basically means that it has to have been
+ run under the control of one of the other /proc ioctl calls and not
+ ptrace. Since we don't use ptrace anyway, we don't worry about this
+ fine point, but it is worth noting for future reference.
+
+ Gdb is confused about what this function is supposed to return.
+ Some versions return a value, others return nothing. Some are
+ declared to return a value and actually return nothing. Gdb ignores
+ anything returned. (FIXME)
+
+ */
+
+static void
+procfs_store_registers (regno)
+ int regno;
+{
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (regno != -1)
+ {
+ ioctl (pi->fd, PIOCGREG, &pi->gregset);
+ }
+ fill_gregset (&pi->gregset, regno);
+ ioctl (pi->fd, PIOCSREG, &pi->gregset);
+
+#if defined (FP0_REGNUM)
+
+ /* Now repeat everything using the floating point register set, if the
+ target has floating point hardware. Since we ignore the returned value,
+ we'll never know whether it worked or not anyway. */
+
+ if (regno != -1)
+ {
+ ioctl (pi->fd, PIOCGFPREG, &pi->fpregset);
+ }
+ fill_fpregset (&pi->fpregset, regno);
+ ioctl (pi->fd, PIOCSFPREG, &pi->fpregset);
+
+#endif /* FP0_REGNUM */
+
+}
+
+/*
+
+LOCAL FUNCTION
+
+ create_procinfo - initialize access to a /proc entry
+
+SYNOPSIS
+
+ struct procinfo * create_procinfo (int pid)
+
+DESCRIPTION
+
+ Allocate a procinfo structure, open the /proc file and then set up the
+ set of signals and faults that are to be traced. Returns a pointer to
+ the new procinfo structure.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static struct procinfo *
+create_procinfo (pid)
+ int pid;
+{
+ struct procinfo *pi;
+
+ pi = find_procinfo (pid, 1);
+ if (pi != NULL)
+ return pi; /* All done! It already exists */
+
+ pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+
+ if (!open_proc_file (pid, pi, O_RDWR))
+ proc_init_failed (pi, "can't open process file");
+
+ /* Add new process to process info list */
+
+ pi->next = procinfo_list;
+ procinfo_list = pi;
+
+ add_fd (pi); /* Add to list for poll/select */
+
+ memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
+ prfillset (&pi->prrun.pr_trace);
+ procfs_notice_signals (pid);
+ prfillset (&pi->prrun.pr_fault);
+ prdelset (&pi->prrun.pr_fault, FLTPAGE);
+
+#ifdef PROCFS_DONT_TRACE_FAULTS
+ premptyset (&pi->prrun.pr_fault);
+#endif
+
+ if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
+ proc_init_failed (pi, "PIOCWSTOP failed");
+
+ if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
+ proc_init_failed (pi, "PIOCSFAULT failed");
+
+ return pi;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_init_inferior - initialize target vector and access to a
+ /proc entry
+
+SYNOPSIS
+
+ void procfs_init_inferior (int pid)
+
+DESCRIPTION
+
+ When gdb starts an inferior, this function is called in the parent
+ process immediately after the fork. It waits for the child to stop
+ on the return from the exec system call (the child itself takes care
+ of ensuring that this is set up), then sets up the set of signals
+ and faults that are to be traced.
+
+NOTES
+
+ If proc_init_failed ever gets called, control returns to the command
+ processing loop via the standard error handling code.
+
+ */
+
+static void
+procfs_init_inferior (pid)
+ int pid;
+{
+ push_target (&procfs_ops);
+
+ create_procinfo (pid);
+ add_thread (pid); /* Setup initial thread */
+
+#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
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ procfs_notice_signals
+
+SYNOPSIS
+
+ static void procfs_notice_signals (int pid);
+
+DESCRIPTION
+
+ When the user changes the state of gdb's signal handling via the
+ "handle" command, this function gets called to see if any change
+ in the /proc interface is required. It is also called internally
+ by other /proc interface functions to initialize the state of
+ the traced signal set.
+
+ One thing it does is that signals for which the state is "nostop",
+ "noprint", and "pass", have their trace bits reset in the pr_trace
+ field, so that they are no longer traced. This allows them to be
+ delivered directly to the inferior without the debugger ever being
+ involved.
+ */
+
+static void
+procfs_notice_signals (pid)
+ int pid;
+{
+ int signo;
+ struct procinfo *pi;
+
+ pi = find_procinfo (pid, 0);
+
+ for (signo = 0; signo < NSIG; signo++)
+ {
+ if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
+ signal_print_state (target_signal_from_host (signo)) == 0 &&
+ signal_pass_state (target_signal_from_host (signo)) == 1)
+ {
+ prdelset (&pi->prrun.pr_trace, signo);
+ }
+ else
+ {
+ praddset (&pi->prrun.pr_trace, signo);
+ }
+ }
+ if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))
+ {
+ print_sys_errmsg ("PIOCSTRACE failed", errno);
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ proc_set_exec_trap -- arrange for exec'd child to halt at startup
+
+SYNOPSIS
+
+ void proc_set_exec_trap (void)
+
+DESCRIPTION
+
+ This function is called in the child process when starting up
+ an inferior, prior to doing the exec of the actual inferior.
+ It sets the child process's exitset to make exit from the exec
+ system call an event of interest to stop on, and then simply
+ returns. The child does the exec, the system call returns, and
+ the child stops at the first instruction, ready for the gdb
+ parent process to take control of it.
+
+NOTE
+
+ We need to use all local variables since the child may be sharing
+ it's data space with the parent, if vfork was used rather than
+ fork.
+
+ Also note that we want to turn off the inherit-on-fork flag in
+ the child process so that any grand-children start with all
+ tracing flags cleared.
+ */
+
+static void
+proc_set_exec_trap ()
+{
+ sysset_t exitset;
+ sysset_t entryset;
+ auto char procname[32];
+ int fd;
+
+ sprintf (procname, PROC_NAME_FMT, getpid ());
+ if ((fd = open (procname, O_RDWR)) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ premptyset (&exitset);
+ premptyset (&entryset);
+
+#ifdef PIOCSSPCACT
+ /* Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace
+ exits from exec system calls because of the user level loader. */
+ {
+ int prfs_flags;
+
+ if (ioctl (fd, PIOCGSPCACT, &prfs_flags) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ prfs_flags |= PRFS_STOPEXEC;
+ if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ }
+#else
+ /* GW: Rationale...
+ Not all systems with /proc have all the exec* syscalls with the same
+ names. On the SGI, for example, there is no SYS_exec, but there
+ *is* a SYS_execv. So, we try to account for that. */
+
+#ifdef SYS_exec
+ praddset (&exitset, SYS_exec);
+#endif
+#ifdef SYS_execve
+ praddset (&exitset, SYS_execve);
+#endif
+#ifdef SYS_execv
+ praddset (&exitset, SYS_execv);
+#endif
+
+ if (ioctl (fd, PIOCSEXIT, &exitset) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+#endif
+
+ praddset (&entryset, SYS_exit);
+
+ if (ioctl (fd, PIOCSENTRY, &entryset) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (126);
+ }
+
+ /* Turn off inherit-on-fork flag so that all grand-children of gdb
+ start with tracing flags cleared. */
+
+#if defined (PIOCRESET) /* New method */
+ {
+ long pr_flags;
+ pr_flags = PR_FORK;
+ ioctl (fd, PIOCRESET, &pr_flags);
+ }
+#else
+#if defined (PIOCRFORK) /* Original method */
+ ioctl (fd, PIOCRFORK, NULL);
+#endif
+#endif
+
+ /* Turn on run-on-last-close flag so that this process will not hang
+ if GDB goes away for some reason. */
+
+#if defined (PIOCSET) /* New method */
+ {
+ long pr_flags;
+ pr_flags = PR_RLC;
+ (void) ioctl (fd, PIOCSET, &pr_flags);
+ }
+#else
+#if defined (PIOCSRLC) /* Original method */
+ (void) ioctl (fd, PIOCSRLC, 0);
+#endif
+#endif
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ proc_iterate_over_mappings -- call function for every mapped space
+
+SYNOPSIS
+
+ int proc_iterate_over_mappings (int (*func)())
+
+DESCRIPTION
+
+ Given a pointer to a function, call that function for every
+ mapped address space, passing it an open file descriptor for
+ the file corresponding to that mapped address space (if any)
+ and the base address of the mapped space. Quit when we hit
+ the end of the mappings or the function returns nonzero.
+ */
+
+int
+proc_iterate_over_mappings (func)
+ int (*func) PARAMS ((int, CORE_ADDR));
+{
+ int nmap;
+ int fd;
+ int funcstat = 0;
+ struct prmap *prmaps;
+ struct prmap *prmap;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (ioctl (pi->fd, PIOCNMAP, &nmap) == 0)
+ {
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (ioctl (pi->fd, PIOCMAP, prmaps) == 0)
+ {
+ for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
+ {
+ fd = proc_address_to_fd (pi, (CORE_ADDR) prmap -> pr_vaddr, 0);
+ funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
+ close (fd);
+ }
+ }
+ }
+ return (funcstat);
+}
+
+#if 0 /* Currently unused */
+/*
+
+GLOBAL FUNCTION
+
+ proc_base_address -- find base address for segment containing address
+
+SYNOPSIS
+
+ CORE_ADDR proc_base_address (CORE_ADDR addr)
+
+DESCRIPTION
+
+ Given an address of a location in the inferior, find and return
+ the base address of the mapped segment containing that address.
+
+ This is used for example, by the shared library support code,
+ where we have the pc value for some location in the shared library
+ where we are stopped, and need to know the base address of the
+ segment containing that address.
+*/
+
+CORE_ADDR
+proc_base_address (addr)
+ CORE_ADDR addr;
+{
+ int nmap;
+ struct prmap *prmaps;
+ struct prmap *prmap;
+ CORE_ADDR baseaddr = 0;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (ioctl (pi->fd, PIOCNMAP, &nmap) == 0)
+ {
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (ioctl (pi->fd, PIOCMAP, prmaps) == 0)
+ {
+ for (prmap = prmaps; prmap -> pr_size; ++prmap)
+ {
+ if ((prmap -> pr_vaddr <= (caddr_t) addr) &&
+ (prmap -> pr_vaddr + prmap -> pr_size > (caddr_t) addr))
+ {
+ baseaddr = (CORE_ADDR) prmap -> pr_vaddr;
+ break;
+ }
+ }
+ }
+ }
+ return (baseaddr);
+}
+
+#endif /* 0 */
+
+/*
+
+LOCAL FUNCTION
+
+ proc_address_to_fd -- return open fd for file mapped to address
+
+SYNOPSIS
+
+ int proc_address_to_fd (struct procinfo *pi, CORE_ADDR addr, complain)
+
+DESCRIPTION
+
+ Given an address in the current inferior's address space, use the
+ /proc interface to find an open file descriptor for the file that
+ this address was mapped in from. Return -1 if there is no current
+ inferior. Print a warning message if there is an inferior but
+ the address corresponds to no file (IE a bogus address).
+
+*/
+
+static int
+proc_address_to_fd (pi, addr, complain)
+ struct procinfo *pi;
+ CORE_ADDR addr;
+ int complain;
+{
+ int fd = -1;
+
+ if ((fd = ioctl (pi->fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
+ {
+ if (complain)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ warning ("can't find mapped file for address 0x%x", addr);
+ }
+ }
+ return (fd);
+}
+
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+static void
+procfs_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *exec_file;
+ int pid;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ pid = atoi (args);
+
+ if (pid == getpid()) /* Trying to masturbate? */
+ error ("I refuse to debug myself!");
+
+ if (from_tty)
+ {
+ exec_file = (char *) get_exec_file (0);
+
+ 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));
+
+ gdb_flush (gdb_stdout);
+ }
+
+ do_attach (pid);
+ inferior_pid = pid;
+ push_target (&procfs_ops);
+}
+
+
+/* Take a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We'd better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via the normal ptrace (PTRACE_TRACEME). */
+
+static void
+procfs_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ 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);
+
+ do_detach (siggnal);
+ inferior_pid = 0;
+ unpush_target (&procfs_ops); /* Pop out of handling an inferior */
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+procfs_prepare_to_store ()
+{
+#ifdef CHILD_PREPARE_TO_STORE
+ CHILD_PREPARE_TO_STORE ();
+#endif
+}
+
+/* Print status information about what we're accessing. */
+
+static void
+procfs_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_unfiltered ("\tUsing the running image of %s %s via /proc.\n",
+ attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
+}
+
+/* ARGSUSED */
+static void
+procfs_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a Unix child process.");
+}
+
+/*
+
+LOCAL FUNCTION
+
+ do_attach -- attach to an already existing process
+
+SYNOPSIS
+
+ int do_attach (int pid)
+
+DESCRIPTION
+
+ Attach to an already existing process with the specified process
+ id. If the process is not already stopped, query whether to
+ stop it or not.
+
+NOTES
+
+ The option of stopping at attach time is specific to the /proc
+ versions of gdb. Versions using ptrace force the attachee
+ to stop. (I have changed this version to do so, too. All you
+ have to do is "continue" to make it go on. -- gnu@cygnus.com)
+
+*/
+
+static int
+do_attach (pid)
+ int pid;
+{
+ int result;
+ struct procinfo *pi;
+
+ pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+
+ if (!open_proc_file (pid, pi, O_RDWR))
+ {
+ free (pi);
+ perror_with_name (pi->pathname);
+ /* NOTREACHED */
+ }
+
+ /* Add new process to process info list */
+
+ pi->next = procinfo_list;
+ procinfo_list = pi;
+
+ add_fd (pi); /* Add to list for poll/select */
+
+ /* Get current status of process and if it is not already stopped,
+ then stop it. Remember whether or not it was stopped when we first
+ examined it. */
+
+ if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
+ error ("PIOCSTATUS failed");
+ }
+ if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ {
+ pi->was_stopped = 1;
+ }
+ else
+ {
+ pi->was_stopped = 0;
+ if (1 || query ("Process is currently running, stop it? "))
+ {
+ /* Make it run again when we close it. */
+#if defined (PIOCSET) /* New method */
+ {
+ long pr_flags;
+ pr_flags = PR_RLC;
+ result = ioctl (pi->fd, PIOCSET, &pr_flags);
+ }
+#else
+#if defined (PIOCSRLC) /* Original method */
+ result = ioctl (pi->fd, PIOCSRLC, 0);
+#endif
+#endif
+ if (result < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
+ error ("PIOCSRLC or PIOCSET failed");
+ }
+ if (ioctl (pi->fd, PIOCSTOP, &pi->prstatus) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ close_proc_file (pi);
+ error ("PIOCSTOP failed");
+ }
+ pi->nopass_next_sigstop = 1;
+ }
+ else
+ {
+ printf_unfiltered ("Ok, gdb will wait for %s to stop.\n", target_pid_to_str (pid));
+ }
+ }
+
+ /* Remember some things about the inferior that we will, or might, change
+ so that we can restore them when we detach. */
+
+ ioctl (pi->fd, PIOCGTRACE, &pi->saved_trace);
+ ioctl (pi->fd, PIOCGHOLD, &pi->saved_sighold);
+ ioctl (pi->fd, PIOCGFAULT, &pi->saved_fltset);
+ ioctl (pi->fd, PIOCGENTRY, &pi->saved_entryset);
+ ioctl (pi->fd, PIOCGEXIT, &pi->saved_exitset);
+
+ /* Set up trace and fault sets, as gdb expects them. */
+
+ memset (&pi->prrun, 0, sizeof (pi->prrun));
+ prfillset (&pi->prrun.pr_trace);
+ procfs_notice_signals (pid);
+ prfillset (&pi->prrun.pr_fault);
+ prdelset (&pi->prrun.pr_fault, FLTPAGE);
+
+#ifdef PROCFS_DONT_TRACE_FAULTS
+ premptyset (&pi->prrun.pr_fault);
+#endif
+
+ if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault))
+ {
+ print_sys_errmsg ("PIOCSFAULT failed", errno);
+ }
+ if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))
+ {
+ print_sys_errmsg ("PIOCSTRACE failed", errno);
+ }
+ attach_flag = 1;
+ return (pid);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ do_detach -- detach from an attached-to process
+
+SYNOPSIS
+
+ void do_detach (int signal)
+
+DESCRIPTION
+
+ Detach from the current attachee.
+
+ If signal is non-zero, the attachee is started running again and sent
+ the specified signal.
+
+ If signal is zero and the attachee was not already stopped when we
+ attached to it, then we make it runnable again when we detach.
+
+ Otherwise, we query whether or not to make the attachee runnable
+ again, since we may simply want to leave it in the state it was in
+ when we attached.
+
+ We report any problems, but do not consider them errors, since we
+ MUST detach even if some things don't seem to go right. This may not
+ be the ideal situation. (FIXME).
+ */
+
+static void
+do_detach (signal)
+ int signal;
+{
+ int result;
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (signal)
+ {
+ set_proc_siginfo (pi, signal);
+ }
+ if (ioctl (pi->fd, PIOCSEXIT, &pi->saved_exitset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSEXIT failed.\n");
+ }
+ if (ioctl (pi->fd, PIOCSENTRY, &pi->saved_entryset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSENTRY failed.\n");
+ }
+ if (ioctl (pi->fd, PIOCSTRACE, &pi->saved_trace) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSTRACE failed.\n");
+ }
+ if (ioctl (pi->fd, PIOCSHOLD, &pi->saved_sighold) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOSCHOLD failed.\n");
+ }
+ if (ioctl (pi->fd, PIOCSFAULT, &pi->saved_fltset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSFAULT failed.\n");
+ }
+ if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSTATUS failed.\n");
+ }
+ else
+ {
+ if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+ {
+ if (signal || !pi->was_stopped ||
+ query ("Was stopped when attached, make it runnable again? "))
+ {
+ /* Clear any pending signal if we want to detach without
+ a signal. */
+ if (signal == 0)
+ set_proc_siginfo (pi, signal);
+
+ /* Clear any fault that might have stopped it. */
+ if (ioctl (pi->fd, PIOCCFAULT, 0))
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCCFAULT failed.\n");
+ }
+
+ /* Make it run again when we close it. */
+#if defined (PIOCSET) /* New method */
+ {
+ long pr_flags;
+ pr_flags = PR_RLC;
+ result = ioctl (pi->fd, PIOCSET, &pr_flags);
+ }
+#else
+#if defined (PIOCSRLC) /* Original method */
+ result = ioctl (pi->fd, PIOCSRLC, 0);
+#endif
+#endif
+ if (result)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ printf_unfiltered ("PIOCSRLC or PIOCSET failed.\n");
+ }
+ }
+ }
+ }
+ close_proc_file (pi);
+ attach_flag = 0;
+}
+
+/* emulate wait() as much as possible.
+ Wait for child to do something. Return pid of child, or -1 in case
+ of error; store status in *OURSTATUS.
+
+ Not sure why we can't
+ just use wait(), but it seems to have problems when applied to a
+ process being controlled with the /proc interface.
+
+ We have a race problem here with no obvious solution. We need to let
+ the inferior run until it stops on an event of interest, which means
+ that we need to use the PIOCWSTOP ioctl. However, we cannot use this
+ ioctl if the process is already stopped on something that is not an
+ event of interest, or the call will hang indefinitely. Thus we first
+ use PIOCSTATUS to see if the process is not stopped. If not, then we
+ use PIOCWSTOP. But during the window between the two, if the process
+ stops for any reason that is not an event of interest (such as a job
+ control signal) then gdb will hang. One possible workaround is to set
+ an alarm to wake up every minute of so and check to see if the process
+ is still running, and if so, then reissue the PIOCWSTOP. But this is
+ a real kludge, so has not been implemented. FIXME: investigate
+ alternatives.
+
+ FIXME: Investigate why wait() seems to have problems with programs
+ being control by /proc routines. */
+
+static int
+procfs_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ short what;
+ short why;
+ int statval = 0;
+ int checkerr = 0;
+ int rtnval = -1;
+ struct procinfo *pi;
+
+ if (pid != -1) /* Non-specific process? */
+ pi = NULL;
+ else
+ for (pi = procinfo_list; pi; pi = pi->next)
+ if (pi->had_event)
+ break;
+
+ if (!pi)
+ {
+ wait_again:
+
+ pi = wait_fd ();
+ }
+
+ if (pid != -1)
+ for (pi = procinfo_list; pi; pi = pi->next)
+ if (pi->pid == pid && pi->had_event)
+ break;
+
+ if (!pi && !checkerr)
+ goto wait_again;
+
+ if (!checkerr && !(pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
+ {
+ if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
+ {
+ checkerr++;
+ }
+ }
+ if (checkerr)
+ {
+ if (errno == ENOENT)
+ {
+ rtnval = wait (&statval);
+ if (rtnval != inferior_pid)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCWSTOP, wait failed, returned %d", rtnval);
+ /* NOTREACHED */
+ }
+ }
+ else
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSTATUS or PIOCWSTOP failed.");
+ /* NOTREACHED */
+ }
+ }
+ else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ {
+ rtnval = pi->prstatus.pr_pid;
+ why = pi->prstatus.pr_why;
+ what = pi->prstatus.pr_what;
+
+ switch (why)
+ {
+ case PR_SIGNALLED:
+ statval = (what << 8) | 0177;
+ break;
+ case PR_SYSENTRY:
+ if (what != SYS_exit)
+ error ("PR_SYSENTRY, unknown system call %d", what);
+
+ pi->prrun.pr_flags = PRCFAULT;
+
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+
+ rtnval = wait (&statval);
+
+ break;
+ case PR_SYSEXIT:
+ switch (what)
+ {
+#ifdef SYS_exec
+ case SYS_exec:
+#endif
+#ifdef SYS_execve
+ case SYS_execve:
+#endif
+#ifdef SYS_execv
+ case SYS_execv:
+#endif
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+#ifdef SYS_sproc
+ case SYS_sproc:
+/* We've just detected the completion of an sproc system call. Now we need to
+ setup a procinfo struct for this thread, and notify the thread system of the
+ new arrival. */
+
+/* If sproc failed, then nothing interesting happened. Continue the process and
+ go back to sleep. */
+
+ if (pi->prstatus.pr_errno != 0)
+ {
+ pi->prrun.pr_flags &= PRSTEP;
+ pi->prrun.pr_flags |= PRCFAULT;
+
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+
+ goto wait_again;
+ }
+
+/* At this point, the new thread is stopped at it's first instruction, and
+ the parent is stopped at the exit from sproc. */
+
+/* Notify the caller of the arrival of a new thread. */
+ create_procinfo (pi->prstatus.pr_rval1);
+
+ rtnval = pi->prstatus.pr_rval1;
+ statval = (SIGTRAP << 8) | 0177;
+
+ break;
+ case SYS_fork:
+#ifdef SYS_vfork
+ case SYS_vfork:
+#endif
+/* At this point, we've detected the completion of a fork (or vfork) call in
+ our child. The grandchild is also stopped because we set inherit-on-fork
+ earlier. (Note that nobody has the grandchilds' /proc file open at this
+ point.) We will release the grandchild from the debugger by opening it's
+ /proc file and then closing it. Since run-on-last-close is set, the
+ grandchild continues on its' merry way. */
+
+ {
+ struct procinfo *pitemp;
+
+ pitemp = create_procinfo (pi->prstatus.pr_rval1);
+ if (pitemp)
+ close_proc_file (pitemp);
+
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+ }
+ goto wait_again;
+#endif /* SYS_sproc */
+
+ default:
+ error ("PIOCSTATUS (PR_SYSEXIT): Unknown system call %d", what);
+ }
+ break;
+ case PR_REQUESTED:
+ statval = (SIGSTOP << 8) | 0177;
+ break;
+ case PR_JOBCONTROL:
+ statval = (what << 8) | 0177;
+ break;
+ case PR_FAULTED:
+ switch (what)
+ {
+#ifdef FLTWATCH
+ case FLTWATCH:
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+#endif
+#ifdef FLTKWATCH
+ case FLTKWATCH:
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+#endif
+#ifndef FAULTED_USE_SIGINFO
+ /* Irix, contrary to the documentation, fills in 0 for si_signo.
+ Solaris fills in si_signo. I'm not sure about others. */
+ case FLTPRIV:
+ case FLTILL:
+ statval = (SIGILL << 8) | 0177;
+ break;
+ case FLTBPT:
+ case FLTTRACE:
+ statval = (SIGTRAP << 8) | 0177;
+ break;
+ case FLTSTACK:
+ case FLTACCESS:
+ case FLTBOUNDS:
+ statval = (SIGSEGV << 8) | 0177;
+ break;
+ case FLTIOVF:
+ case FLTIZDIV:
+ case FLTFPE:
+ statval = (SIGFPE << 8) | 0177;
+ break;
+ case FLTPAGE: /* Recoverable page fault */
+#endif /* not FAULTED_USE_SIGINFO */
+ default:
+ /* Use the signal which the kernel assigns. This is better than
+ trying to second-guess it from the fault. In fact, I suspect
+ that FLTACCESS can be either SIGSEGV or SIGBUS. */
+ statval = ((pi->prstatus.pr_info.si_signo) << 8) | 0177;
+ break;
+ }
+ break;
+ default:
+ error ("PIOCWSTOP, unknown why %d, what %d", why, what);
+ }
+/* Stop all the other threads when any of them stops. */
+
+ {
+ struct procinfo *procinfo;
+
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ {
+ if (!procinfo->had_event)
+ if (ioctl (procinfo->fd, PIOCSTOP, &procinfo->prstatus) < 0)
+ {
+ print_sys_errmsg (procinfo->pathname, errno);
+ error ("PIOCSTOP failed");
+ }
+ }
+ }
+ }
+ else
+ {
+ error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
+ pi->prstatus.pr_flags);
+ }
+
+ store_waitstatus (ourstatus, statval);
+
+ if (rtnval == -1) /* No more children to wait for */
+ {
+ fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing.\n");
+ /* Claim it exited with unknown signal. */
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ return rtnval;
+ }
+
+ pi->had_event = 0; /* Indicate that we've seen this one */
+ return (rtnval);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ set_proc_siginfo - set a process's current signal info
+
+SYNOPSIS
+
+ void set_proc_siginfo (struct procinfo *pip, int signo);
+
+DESCRIPTION
+
+ Given a pointer to a process info struct in PIP and a signal number
+ in SIGNO, set the process's current signal and its associated signal
+ information. The signal will be delivered to the process immediately
+ after execution is resumed, even if it is being held. In addition,
+ this particular delivery will not cause another PR_SIGNALLED stop
+ even if the signal is being traced.
+
+ If we are not delivering the same signal that the prstatus siginfo
+ struct contains information about, then synthesize a siginfo struct
+ to match the signal we are doing to deliver, make it of the type
+ "generated by a user process", and send this synthesized copy. When
+ used to set the inferior's signal state, this will be required if we
+ are not currently stopped because of a traced signal, or if we decide
+ to continue with a different signal.
+
+ Note that when continuing the inferior from a stop due to receipt
+ of a traced signal, we either have set PRCSIG to clear the existing
+ signal, or we have to call this function to do a PIOCSSIG with either
+ the existing siginfo struct from pr_info, or one we have synthesized
+ appropriately for the signal we want to deliver. Otherwise if the
+ signal is still being traced, the inferior will immediately stop
+ again.
+
+ See siginfo(5) for more details.
+*/
+
+static void
+set_proc_siginfo (pip, signo)
+ struct procinfo *pip;
+ int signo;
+{
+ struct siginfo newsiginfo;
+ struct siginfo *sip;
+
+#ifdef PROCFS_DONT_PIOCSSIG_CURSIG
+ /* With Alpha OSF/1 procfs, the kernel gets really confused if it
+ receives a PIOCSSIG with a signal identical to the current signal,
+ it messes up the current signal. Work around the kernel bug. */
+ if (signo == pip -> prstatus.pr_cursig)
+ return;
+#endif
+
+ if (signo == pip -> prstatus.pr_info.si_signo)
+ {
+ sip = &pip -> prstatus.pr_info;
+ }
+ else
+ {
+ memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+ sip = &newsiginfo;
+ sip -> si_signo = signo;
+ sip -> si_code = 0;
+ sip -> si_errno = 0;
+ sip -> si_pid = getpid ();
+ sip -> si_uid = getuid ();
+ }
+ if (ioctl (pip -> fd, PIOCSSIG, sip) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ warning ("PIOCSSIG failed");
+ }
+}
+
+/* Resume execution of process PID. If STEP is nozero, then
+ just single step it. If SIGNAL is nonzero, restart it with that
+ signal activated. */
+
+static void
+procfs_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
+{
+ int signal_to_pass;
+ struct procinfo *pi, *procinfo;
+
+ pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+
+ errno = 0;
+ pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
+
+#if 0
+ /* It should not be necessary. If the user explicitly changes the value,
+ value_assign calls write_register_bytes, which writes it. */
+/* It may not be absolutely necessary to specify the PC value for
+ restarting, but to be safe we use the value that gdb considers
+ to be current. One case where this might be necessary is if the
+ user explicitly changes the PC value that gdb considers to be
+ current. FIXME: Investigate if this is necessary or not. */
+
+#ifdef PRSVADDR_BROKEN
+/* Can't do this under Solaris running on a Sparc, as there seems to be no
+ place to put nPC. In fact, if you use this, nPC seems to be set to some
+ random garbage. We have to rely on the fact that PC and nPC have been
+ written previously via PIOCSREG during a register flush. */
+
+ pi->prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
+ pi->prrun.pr_flags != PRSVADDR;
+#endif
+#endif
+
+ if (signo == TARGET_SIGNAL_STOP && pi->nopass_next_sigstop)
+ /* When attaching to a child process, if we forced it to stop with
+ a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
+ Upon resuming the first time after such a stop, we explicitly
+ inhibit sending it another SIGSTOP, which would be the normal
+ result of default signal handling. One potential drawback to
+ this is that we will also ignore any attempt to by the user
+ to explicitly continue after the attach with a SIGSTOP. Ultimately
+ this problem should be dealt with by making the routines that
+ deal with the inferior a little smarter, and possibly even allow
+ an inferior to continue running at the same time as gdb. (FIXME?) */
+ signal_to_pass = 0;
+ else if (signo == TARGET_SIGNAL_TSTP
+ && pi->prstatus.pr_cursig == SIGTSTP
+ && pi->prstatus.pr_action.sa_handler == SIG_DFL)
+
+ /* We are about to pass the inferior a SIGTSTP whose action is
+ SIG_DFL. The SIG_DFL action for a SIGTSTP is to stop
+ (notifying the parent via wait()), and then keep going from the
+ same place when the parent is ready for you to keep going. So
+ under the debugger, it should do nothing (as if the program had
+ been stopped and then later resumed. Under ptrace, this
+ happens for us, but under /proc, the system obligingly stops
+ the process, and wait_for_inferior would have no way of
+ distinguishing that type of stop (which indicates that we
+ should just start it again), with a stop due to the pr_trace
+ field of the prrun_t struct.
+
+ Note that if the SIGTSTP is being caught, we *do* need to pass it,
+ because the handler needs to get executed. */
+ signal_to_pass = 0;
+ else
+ signal_to_pass = target_signal_to_host (signo);
+
+ if (signal_to_pass)
+ {
+ set_proc_siginfo (pi, signal_to_pass);
+ }
+ else
+ {
+ pi->prrun.pr_flags |= PRCSIG;
+ }
+ pi->nopass_next_sigstop = 0;
+ if (step)
+ {
+ pi->prrun.pr_flags |= PRSTEP;
+ }
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ {
+ perror_with_name (pi->pathname);
+ /* NOTREACHED */
+ }
+
+ pi->had_event = 0;
+
+ /* Continue all the other threads that haven't had an event of
+ interest. */
+
+ if (pid == -1)
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ {
+ if (pi != procinfo && !procinfo->had_event)
+ {
+ procinfo->prrun.pr_flags &= PRSTEP;
+ procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
+ ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);
+ if (ioctl (procinfo->fd, PIOCRUN, &procinfo->prrun) < 0)
+ {
+ if (ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus) < 0)
+ {
+ fprintf_unfiltered(gdb_stderr, "PIOCSTATUS failed, errno=%d\n", errno);
+ }
+ print_sys_errmsg (procinfo->pathname, errno);
+ error ("PIOCRUN failed");
+ }
+ ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);
+ }
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_fetch_registers -- fetch current registers from inferior
+
+SYNOPSIS
+
+ void procfs_fetch_registers (int regno)
+
+DESCRIPTION
+
+ Read the current values of the inferior's registers, both the
+ general register set and floating point registers (if supported)
+ and update gdb's idea of their current values.
+
+*/
+
+static void
+procfs_fetch_registers (regno)
+ int regno;
+{
+ struct procinfo *pi;
+
+ pi = current_procinfo;
+
+ if (ioctl (pi->fd, PIOCGREG, &pi->gregset) != -1)
+ {
+ supply_gregset (&pi->gregset);
+ }
+#if defined (FP0_REGNUM)
+ if (ioctl (pi->fd, PIOCGFPREG, &pi->fpregset) != -1)
+ {
+ supply_fpregset (&pi->fpregset);
+ }
+#endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+ proc_init_failed - called whenever /proc access initialization
+fails
+
+SYNOPSIS
+
+ static void proc_init_failed (struct procinfo *pi, char *why)
+
+DESCRIPTION
+
+ This function is called whenever initialization of access to a /proc
+ entry fails. It prints a suitable error message, does some cleanup,
+ and then invokes the standard error processing routine which dumps
+ us back into the command loop.
+ */
+
+static void
+proc_init_failed (pi, why)
+ struct procinfo *pi;
+ char *why;
+{
+ print_sys_errmsg (pi->pathname, errno);
+ kill (pi->pid, SIGKILL);
+ close_proc_file (pi);
+ error (why);
+ /* NOTREACHED */
+}
+
+/*
+
+LOCAL FUNCTION
+
+ close_proc_file - close any currently open /proc entry
+
+SYNOPSIS
+
+ static void close_proc_file (struct procinfo *pip)
+
+DESCRIPTION
+
+ Close any currently open /proc entry and mark the process information
+ entry as invalid. In order to ensure that we don't try to reuse any
+ stale information, the pid, fd, and pathnames are explicitly
+ invalidated, which may be overkill.
+
+ */
+
+static void
+close_proc_file (pip)
+ struct procinfo *pip;
+{
+ struct procinfo *procinfo;
+
+ remove_fd (pip); /* Remove fd from poll/select list */
+
+ close (pip -> fd);
+
+ free (pip -> pathname);
+
+ /* Unlink pip from the procinfo chain. Note pip might not be on the list. */
+
+ if (procinfo_list == pip)
+ procinfo_list = pip->next;
+ else
+ for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
+ if (procinfo->next == pip)
+ procinfo->next = pip->next;
+
+ free (pip);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ open_proc_file - open a /proc entry for a given process id
+
+SYNOPSIS
+
+ static int open_proc_file (int pid, struct procinfo *pip, int mode)
+
+DESCRIPTION
+
+ Given a process id and a mode, close the existing open /proc
+ entry (if any) and open one for the new process id, in the
+ specified mode. Once it is open, then mark the local process
+ information structure as valid, which guarantees that the pid,
+ fd, and pathname fields match an open /proc entry. Returns
+ zero if the open fails, nonzero otherwise.
+
+ Note that the pathname is left intact, even when the open fails,
+ so that callers can use it to construct meaningful error messages
+ rather than just "file open failed".
+ */
+
+static int
+open_proc_file (pid, pip, mode)
+ int pid;
+ struct procinfo *pip;
+ int mode;
+{
+ pip -> next = NULL;
+ pip -> had_event = 0;
+ pip -> pathname = xmalloc (32);
+ pip -> pid = pid;
+
+ sprintf (pip -> pathname, PROC_NAME_FMT, pid);
+ if ((pip -> fd = open (pip -> pathname, mode)) < 0)
+ return 0;
+
+ return 1;
+}
+
+static char *
+mappingflags (flags)
+ long flags;
+{
+ static char asciiflags[8];
+
+ strcpy (asciiflags, "-------");
+#if defined (MA_PHYS)
+ if (flags & MA_PHYS) asciiflags[0] = 'd';
+#endif
+ if (flags & MA_STACK) asciiflags[1] = 's';
+ if (flags & MA_BREAK) asciiflags[2] = 'b';
+ if (flags & MA_SHARED) asciiflags[3] = 's';
+ if (flags & MA_READ) asciiflags[4] = 'r';
+ if (flags & MA_WRITE) asciiflags[5] = 'w';
+ if (flags & MA_EXEC) asciiflags[6] = 'x';
+ return (asciiflags);
+}
+
+static void
+info_proc_flags (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct trans *transp;
+
+ printf_filtered ("%-32s", "Process status flags:");
+ if (!summary)
+ {
+ printf_filtered ("\n\n");
+ }
+ for (transp = pr_flag_table; transp -> name != NULL; transp++)
+ {
+ if (pip -> prstatus.pr_flags & transp -> value)
+ {
+ if (summary)
+ {
+ printf_filtered ("%s ", transp -> name);
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc);
+ }
+ }
+ }
+ printf_filtered ("\n");
+}
+
+static void
+info_proc_stop (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct trans *transp;
+ int why;
+ int what;
+
+ why = pip -> prstatus.pr_why;
+ what = pip -> prstatus.pr_what;
+
+ if (pip -> prstatus.pr_flags & PR_STOPPED)
+ {
+ printf_filtered ("%-32s", "Reason for stopping:");
+ if (!summary)
+ {
+ printf_filtered ("\n\n");
+ }
+ for (transp = pr_why_table; transp -> name != NULL; transp++)
+ {
+ if (why == transp -> value)
+ {
+ if (summary)
+ {
+ printf_filtered ("%s ", transp -> name);
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n",
+ transp -> name, transp -> desc);
+ }
+ break;
+ }
+ }
+
+ /* Use the pr_why field to determine what the pr_what field means, and
+ print more information. */
+
+ switch (why)
+ {
+ case PR_REQUESTED:
+ /* pr_what is unused for this case */
+ break;
+ case PR_JOBCONTROL:
+ case PR_SIGNALLED:
+ if (summary)
+ {
+ printf_filtered ("%s ", signalname (what));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", signalname (what),
+ safe_strsignal (what));
+ }
+ break;
+ case PR_SYSENTRY:
+ if (summary)
+ {
+ printf_filtered ("%s ", syscallname (what));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", syscallname (what),
+ "Entered this system call");
+ }
+ break;
+ case PR_SYSEXIT:
+ if (summary)
+ {
+ printf_filtered ("%s ", syscallname (what));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", syscallname (what),
+ "Returned from this system call");
+ }
+ break;
+ case PR_FAULTED:
+ if (summary)
+ {
+ printf_filtered ("%s ",
+ lookupname (faults_table, what, "fault"));
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n",
+ lookupname (faults_table, what, "fault"),
+ lookupdesc (faults_table, what));
+ }
+ break;
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_siginfo (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct siginfo *sip;
+
+ if ((pip -> prstatus.pr_flags & PR_STOPPED) &&
+ (pip -> prstatus.pr_why == PR_SIGNALLED ||
+ pip -> prstatus.pr_why == PR_FAULTED))
+ {
+ printf_filtered ("%-32s", "Additional signal/fault info:");
+ sip = &pip -> prstatus.pr_info;
+ if (summary)
+ {
+ printf_filtered ("%s ", signalname (sip -> si_signo));
+ if (sip -> si_errno > 0)
+ {
+ printf_filtered ("%s ", errnoname (sip -> si_errno));
+ }
+ if (sip -> si_code <= 0)
+ {
+ printf_filtered ("sent by %s, uid %d ",
+ target_pid_to_str (sip -> si_pid),
+ sip -> si_uid);
+ }
+ else
+ {
+ printf_filtered ("%s ", sigcodename (sip));
+ if ((sip -> si_signo == SIGILL) ||
+ (sip -> si_signo == SIGFPE) ||
+ (sip -> si_signo == SIGSEGV) ||
+ (sip -> si_signo == SIGBUS))
+ {
+ printf_filtered ("addr=%#lx ",
+ (unsigned long) sip -> si_addr);
+ }
+ else if ((sip -> si_signo == SIGCHLD))
+ {
+ printf_filtered ("child %s, status %u ",
+ target_pid_to_str (sip -> si_pid),
+ sip -> si_status);
+ }
+ else if ((sip -> si_signo == SIGPOLL))
+ {
+ printf_filtered ("band %u ", sip -> si_band);
+ }
+ }
+ }
+ else
+ {
+ printf_filtered ("\n\n");
+ printf_filtered ("\t%-16s %s.\n", signalname (sip -> si_signo),
+ safe_strsignal (sip -> si_signo));
+ if (sip -> si_errno > 0)
+ {
+ printf_filtered ("\t%-16s %s.\n",
+ errnoname (sip -> si_errno),
+ safe_strerror (sip -> si_errno));
+ }
+ if (sip -> si_code <= 0)
+ {
+ printf_filtered ("\t%-16u %s\n", sip -> si_pid, /* XXX need target_pid_to_str() */
+ "PID of process sending signal");
+ printf_filtered ("\t%-16u %s\n", sip -> si_uid,
+ "UID of process sending signal");
+ }
+ else
+ {
+ printf_filtered ("\t%-16s %s.\n", sigcodename (sip),
+ sigcodedesc (sip));
+ if ((sip -> si_signo == SIGILL) ||
+ (sip -> si_signo == SIGFPE))
+ {
+ printf_filtered ("\t%#-16lx %s.\n",
+ (unsigned long) sip -> si_addr,
+ "Address of faulting instruction");
+ }
+ else if ((sip -> si_signo == SIGSEGV) ||
+ (sip -> si_signo == SIGBUS))
+ {
+ printf_filtered ("\t%#-16lx %s.\n",
+ (unsigned long) sip -> si_addr,
+ "Address of faulting memory reference");
+ }
+ else if ((sip -> si_signo == SIGCHLD))
+ {
+ printf_filtered ("\t%-16u %s.\n", sip -> si_pid, /* XXX need target_pid_to_str() */
+ "Child process ID");
+ printf_filtered ("\t%-16u %s.\n", sip -> si_status,
+ "Child process exit value or signal");
+ }
+ else if ((sip -> si_signo == SIGPOLL))
+ {
+ printf_filtered ("\t%-16u %s.\n", sip -> si_band,
+ "Band event for POLL_{IN,OUT,MSG}");
+ }
+ }
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_syscalls (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ int syscallnum;
+
+ if (!summary)
+ {
+
+#if 0 /* FIXME: Needs to use gdb-wide configured info about system calls. */
+ if (pip -> prstatus.pr_flags & PR_ASLEEP)
+ {
+ int syscallnum = pip -> prstatus.pr_reg[R_D0];
+ if (summary)
+ {
+ printf_filtered ("%-32s", "Sleeping in system call:");
+ printf_filtered ("%s", syscallname (syscallnum));
+ }
+ else
+ {
+ printf_filtered ("Sleeping in system call '%s'.\n",
+ syscallname (syscallnum));
+ }
+ }
+#endif
+
+ if (ioctl (pip -> fd, PIOCGENTRY, &pip -> entryset) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGENTRY failed");
+ }
+
+ if (ioctl (pip -> fd, PIOCGEXIT, &pip -> exitset) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGEXIT failed");
+ }
+
+ printf_filtered ("System call tracing information:\n\n");
+
+ printf_filtered ("\t%-12s %-8s %-8s\n",
+ "System call",
+ "Entry",
+ "Exit");
+ for (syscallnum = 0; syscallnum < MAX_SYSCALLS; syscallnum++)
+ {
+ QUIT;
+ if (syscall_table[syscallnum] != NULL)
+ {
+ printf_filtered ("\t%-12s ", syscall_table[syscallnum]);
+ printf_filtered ("%-8s ",
+ prismember (&pip -> entryset, syscallnum)
+ ? "on" : "off");
+ printf_filtered ("%-8s ",
+ prismember (&pip -> exitset, syscallnum)
+ ? "on" : "off");
+ printf_filtered ("\n");
+ }
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static char *
+signalname (signo)
+ int signo;
+{
+ const char *name;
+ static char locbuf[32];
+
+ name = strsigno (signo);
+ if (name == NULL)
+ {
+ sprintf (locbuf, "Signal %d", signo);
+ }
+ else
+ {
+ sprintf (locbuf, "%s (%d)", name, signo);
+ }
+ return (locbuf);
+}
+
+static char *
+errnoname (errnum)
+ int errnum;
+{
+ const char *name;
+ static char locbuf[32];
+
+ name = strerrno (errnum);
+ if (name == NULL)
+ {
+ sprintf (locbuf, "Errno %d", errnum);
+ }
+ else
+ {
+ sprintf (locbuf, "%s (%d)", name, errnum);
+ }
+ return (locbuf);
+}
+
+static void
+info_proc_signals (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ int signo;
+
+ if (!summary)
+ {
+ if (ioctl (pip -> fd, PIOCGTRACE, &pip -> trace) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGTRACE failed");
+ }
+
+ printf_filtered ("Disposition of signals:\n\n");
+ printf_filtered ("\t%-15s %-8s %-8s %-8s %s\n\n",
+ "Signal", "Trace", "Hold", "Pending", "Description");
+ for (signo = 0; signo < NSIG; signo++)
+ {
+ QUIT;
+ printf_filtered ("\t%-15s ", signalname (signo));
+ printf_filtered ("%-8s ",
+ prismember (&pip -> trace, signo)
+ ? "on" : "off");
+ printf_filtered ("%-8s ",
+ prismember (&pip -> prstatus.pr_sighold, signo)
+ ? "on" : "off");
+
+#ifdef PROCFS_SIGPEND_OFFSET
+ /* Alpha OSF/1 numbers the pending signals from 1. */
+ printf_filtered ("%-8s ",
+ (signo ? prismember (&pip -> prstatus.pr_sigpend,
+ signo - 1)
+ : 0)
+ ? "yes" : "no");
+#else
+ printf_filtered ("%-8s ",
+ prismember (&pip -> prstatus.pr_sigpend, signo)
+ ? "yes" : "no");
+#endif
+ printf_filtered (" %s\n", safe_strsignal (signo));
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_faults (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ struct trans *transp;
+
+ if (!summary)
+ {
+ if (ioctl (pip -> fd, PIOCGFAULT, &pip -> fltset) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCGFAULT failed");
+ }
+
+ printf_filtered ("Current traced hardware fault set:\n\n");
+ printf_filtered ("\t%-12s %-8s\n", "Fault", "Trace");
+
+ for (transp = faults_table; transp -> name != NULL; transp++)
+ {
+ QUIT;
+ printf_filtered ("\t%-12s ", transp -> name);
+ printf_filtered ("%-8s", prismember (&pip -> fltset, transp -> value)
+ ? "on" : "off");
+ printf_filtered ("\n");
+ }
+ printf_filtered ("\n");
+ }
+}
+
+static void
+info_proc_mappings (pip, summary)
+ struct procinfo *pip;
+ int summary;
+{
+ int nmap;
+ struct prmap *prmaps;
+ struct prmap *prmap;
+
+ if (!summary)
+ {
+ printf_filtered ("Mapped address spaces:\n\n");
+#ifdef BFD_HOST_64_BIT
+ printf_filtered (" %18s %18s %10s %10s %7s\n",
+#else
+ printf_filtered ("\t%10s %10s %10s %10s %7s\n",
+#endif
+ "Start Addr",
+ " End Addr",
+ " Size",
+ " Offset",
+ "Flags");
+ if (ioctl (pip -> fd, PIOCNMAP, &nmap) == 0)
+ {
+ prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
+ if (ioctl (pip -> fd, PIOCMAP, prmaps) == 0)
+ {
+ for (prmap = prmaps; prmap -> pr_size; ++prmap)
+ {
+#ifdef BFD_HOST_64_BIT
+ printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n",
+#else
+ printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
+#endif
+ (unsigned long)prmap -> pr_vaddr,
+ (unsigned long)prmap -> pr_vaddr
+ + prmap -> pr_size - 1,
+ prmap -> pr_size,
+ prmap -> pr_off,
+ mappingflags (prmap -> pr_mflags));
+ }
+ }
+ }
+ printf_filtered ("\n");
+ }
+}
+
+/*
+
+LOCAL FUNCTION
+
+ info_proc -- implement the "info proc" command
+
+SYNOPSIS
+
+ void info_proc (char *args, int from_tty)
+
+DESCRIPTION
+
+ Implement gdb's "info proc" command by using the /proc interface
+ to print status information about any currently running process.
+
+ Examples of the use of "info proc" are:
+
+ info proc (prints summary info for current inferior)
+ info proc 123 (prints summary info for process with pid 123)
+ info proc mappings (prints address mappings)
+ info proc times (prints process/children times)
+ info proc id (prints pid, ppid, gid, sid, etc)
+ FIXME: i proc id not implemented.
+ info proc status (prints general process state info)
+ FIXME: i proc status not implemented.
+ info proc signals (prints info about signal handling)
+ info proc all (prints all info)
+
+ */
+
+static void
+info_proc (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int pid;
+ struct procinfo *pip;
+ struct cleanup *old_chain;
+ char **argv;
+ int argsize;
+ int summary = 1;
+ int flags = 0;
+ int syscalls = 0;
+ int signals = 0;
+ int faults = 0;
+ int mappings = 0;
+ int times = 0;
+ int id = 0;
+ int status = 0;
+ int all = 0;
+
+ old_chain = make_cleanup (null_cleanup, 0);
+
+ /* Default to using the current inferior if no pid specified. Note
+ that inferior_pid may be 0, hence we set okerr. */
+
+ pip = find_procinfo (inferior_pid, 1);
+
+ if (args != NULL)
+ {
+ if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ make_cleanup (freeargv, (char *) argv);
+
+ while (*argv != NULL)
+ {
+ argsize = strlen (*argv);
+ if (argsize >= 1 && strncmp (*argv, "all", argsize) == 0)
+ {
+ summary = 0;
+ all = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "faults", argsize) == 0)
+ {
+ summary = 0;
+ faults = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "flags", argsize) == 0)
+ {
+ summary = 0;
+ flags = 1;
+ }
+ else if (argsize >= 1 && strncmp (*argv, "id", argsize) == 0)
+ {
+ summary = 0;
+ id = 1;
+ }
+ else if (argsize >= 1 && strncmp (*argv, "mappings", argsize) == 0)
+ {
+ summary = 0;
+ mappings = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "signals", argsize) == 0)
+ {
+ summary = 0;
+ signals = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "status", argsize) == 0)
+ {
+ summary = 0;
+ status = 1;
+ }
+ else if (argsize >= 2 && strncmp (*argv, "syscalls", argsize) == 0)
+ {
+ summary = 0;
+ syscalls = 1;
+ }
+ else if (argsize >= 1 && strncmp (*argv, "times", argsize) == 0)
+ {
+ summary = 0;
+ times = 1;
+ }
+ else if ((pid = atoi (*argv)) > 0)
+ {
+ pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
+ memset (pip, 0, sizeof (*pip));
+
+ pip->pid = pid;
+ if (!open_proc_file (pid, pip, O_RDONLY))
+ {
+ perror_with_name (pip -> pathname);
+ /* NOTREACHED */
+ }
+ make_cleanup (close_proc_file, pip);
+ }
+ else if (**argv != '\000')
+ {
+ error ("Unrecognized or ambiguous keyword `%s'.", *argv);
+ }
+ argv++;
+ }
+ }
+
+ /* If we don't have a valid open process at this point, then we have no
+ inferior or didn't specify a specific pid. */
+
+ if (!pip)
+ {
+ error ("\
+No process. Start debugging a program or specify an explicit process ID.");
+ }
+ if (ioctl (pip -> fd, PIOCSTATUS, &(pip -> prstatus)) < 0)
+ {
+ print_sys_errmsg (pip -> pathname, errno);
+ error ("PIOCSTATUS failed");
+ }
+
+ /* Print verbose information of the requested type(s), or just a summary
+ of the information for all types. */
+
+ printf_filtered ("\nInformation for %s:\n\n", pip -> pathname);
+ if (summary || all || flags)
+ {
+ info_proc_flags (pip, summary);
+ }
+ if (summary || all)
+ {
+ info_proc_stop (pip, summary);
+ }
+ if (summary || all || signals || faults)
+ {
+ info_proc_siginfo (pip, summary);
+ }
+ if (summary || all || syscalls)
+ {
+ info_proc_syscalls (pip, summary);
+ }
+ if (summary || all || mappings)
+ {
+ info_proc_mappings (pip, summary);
+ }
+ if (summary || all || signals)
+ {
+ info_proc_signals (pip, summary);
+ }
+ if (summary || all || faults)
+ {
+ info_proc_faults (pip, summary);
+ }
+ printf_filtered ("\n");
+
+ /* All done, deal with closing any temporary process info structure,
+ freeing temporary memory , etc. */
+
+ do_cleanups (old_chain);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ procfs_set_sproc_trap -- arrange for child to stop on sproc().
+
+SYNOPSIS
+
+ void procfs_set_sproc_trap (struct procinfo *)
+
+DESCRIPTION
+
+ This function sets up a trap on sproc system call exits so that we can
+ detect the arrival of a new thread. We are called with the new thread
+ stopped prior to it's first instruction.
+
+ Also note that we turn on the inherit-on-fork flag in the child process
+ so that any grand-children start with all tracing flags set.
+ */
+
+#ifdef SYS_sproc
+
+static void
+procfs_set_sproc_trap (pi)
+ struct procinfo *pi;
+{
+ sysset_t exitset;
+
+ if (ioctl (pi->fd, PIOCGEXIT, &exitset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCGEXIT failed");
+ }
+
+ praddset (&exitset, SYS_sproc);
+
+ /* We trap on fork() and vfork() in order to disable debugging in our grand-
+ children and descendant processes. At this time, GDB can only handle
+ threads (multiple processes, one address space). forks (and execs) result
+ in the creation of multiple address spaces, which GDB can't handle yet. */
+
+ praddset (&exitset, SYS_fork);
+#ifdef SYS_vfork
+ praddset (&exitset, SYS_vfork);
+#endif
+
+ if (ioctl (pi->fd, PIOCSEXIT, &exitset) < 0)
+ {
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSEXIT failed");
+ }
+
+ /* Turn on inherit-on-fork flag so that all grand-children of gdb start with
+ tracing flags set. */
+
+#ifdef PIOCSET /* New method */
+ {
+ long pr_flags;
+ pr_flags = PR_FORK;
+ ioctl (pi->fd, PIOCSET, &pr_flags);
+ }
+#else
+#ifdef PIOCSFORK /* Original method */
+ ioctl (pi->fd, PIOCSFORK, NULL);
+#endif
+#endif
+}
+#endif /* SYS_sproc */
+
+/* Fork an inferior process, and start debugging it with /proc. */
+
+static void
+procfs_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ char *shell_file = getenv ("SHELL");
+ char *tryname;
+ if (shell_file != NULL && strchr (shell_file, '/') == NULL)
+ {
+
+ /* We will be looking down the PATH to find shell_file. If we
+ just do this the normal way (via execlp, which operates by
+ attempting an exec for each element of the PATH until it
+ finds one which succeeds), then there will be an exec for
+ each failed attempt, each of which will cause a PR_SYSEXIT
+ stop, and we won't know how to distinguish the PR_SYSEXIT's
+ for these failed execs with the ones for successful execs
+ (whether the exec has succeeded is stored at that time in the
+ carry bit or some such architecture-specific and
+ non-ABI-specified place).
+
+ So I can't think of anything better than to search the PATH
+ now. This has several disadvantages: (1) There is a race
+ condition; if we find a file now and it is deleted before we
+ exec it, we lose, even if the deletion leaves a valid file
+ further down in the PATH, (2) there is no way to know exactly
+ what an executable (in the sense of "capable of being
+ exec'd") file is. Using access() loses because it may lose
+ if the caller is the superuser; failing to use it loses if
+ there are ACLs or some such. */
+
+ char *p;
+ char *p1;
+ /* FIXME-maybe: might want "set path" command so user can change what
+ path is used from within GDB. */
+ char *path = getenv ("PATH");
+ int len;
+ struct stat statbuf;
+
+ if (path == NULL)
+ path = "/bin:/usr/bin";
+
+ tryname = alloca (strlen (path) + strlen (shell_file) + 2);
+ for (p = path; p != NULL; p = p1 ? p1 + 1: NULL)
+ {
+ p1 = strchr (p, ':');
+ if (p1 != NULL)
+ len = p1 - p;
+ else
+ len = strlen (p);
+ strncpy (tryname, p, len);
+ tryname[len] = '\0';
+ strcat (tryname, "/");
+ strcat (tryname, shell_file);
+ if (access (tryname, X_OK) < 0)
+ continue;
+ if (stat (tryname, &statbuf) < 0)
+ continue;
+ if (!S_ISREG (statbuf.st_mode))
+ /* We certainly need to reject directories. I'm not quite
+ as sure about FIFOs, sockets, etc., but I kind of doubt
+ that people want to exec() these things. */
+ continue;
+ break;
+ }
+ if (p == NULL)
+ /* Not found. This must be an error rather than merely passing
+ the file to execlp(), because execlp() would try all the
+ exec()s, causing GDB to get confused. */
+ error ("Can't find shell %s in PATH", shell_file);
+
+ shell_file = tryname;
+ }
+
+ fork_inferior (exec_file, allargs, env,
+ proc_set_exec_trap, procfs_init_inferior, shell_file);
+
+ /* We are at the first instruction we care about. */
+ /* Pedal to the metal... */
+
+ /* Setup traps on exit from sproc() */
+
+#ifdef SYS_sproc
+ procfs_set_sproc_trap (current_procinfo);
+#endif
+
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+procfs_mourn_inferior ()
+{
+ struct procinfo *pi;
+ struct procinfo *next_pi;
+
+ for (pi = procinfo_list; pi; pi = next_pi)
+ {
+ next_pi = pi->next;
+ unconditionally_kill_inferior (pi);
+ }
+
+ unpush_target (&procfs_ops);
+ generic_mourn_inferior ();
+}
+
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
+static int
+procfs_can_run ()
+{
+ return(1);
+}
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Insert a watchpoint */
+int
+procfs_set_watchpoint(pid, addr, len, rw)
+ int pid;
+ CORE_ADDR addr;
+ int len;
+ int rw;
+{
+ struct procinfo *pi;
+ prwatch_t wpt;
+
+ pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+ wpt.pr_vaddr = (caddr_t)addr;
+ wpt.pr_size = len;
+ wpt.pr_wflags = ((rw & 1) ? MA_READ : 0) | ((rw & 2) ? MA_WRITE : 0);
+ if (ioctl (pi->fd, PIOCSWATCH, &wpt) < 0)
+ {
+ if (errno == E2BIG)
+ return -1;
+ /* Currently it sometimes happens that the same watchpoint gets
+ deleted twice - don't die in this case (FIXME please) */
+ if (errno == ESRCH && len == 0)
+ return 0;
+ print_sys_errmsg (pi->pathname, errno);
+ error ("PIOCSWATCH failed");
+ }
+ return 0;
+}
+
+int
+procfs_stopped_by_watchpoint(pid)
+ int pid;
+{
+ struct procinfo *pi;
+ short what;
+ short why;
+
+ pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
+ if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
+ {
+ why = pi->prstatus.pr_why;
+ what = pi->prstatus.pr_what;
+ if (why == PR_FAULTED
+#if defined (FLTWATCH) && defined (FLTKWATCH)
+ && (what == FLTWATCH || what == FLTKWATCH)
+#else
+#ifdef FLTWATCH
+ && (what == FLTWATCH)
+#endif
+#ifdef FLTKWATCH
+ && (what == FLTKWATCH)
+#endif
+#endif
+ )
+ return what;
+ }
+ return 0;
+}
+#endif
+
+/* Send a SIGINT to the process group. This acts just like the user typed a
+ ^C on the controlling terminal.
+
+ XXX - This may not be correct for all systems. Some may want to use
+ killpg() instead of kill (-pgrp). */
+
+void
+procfs_stop ()
+{
+ extern pid_t inferior_process_group;
+
+ kill (-inferior_process_group, SIGINT);
+}
+
+
+struct target_ops procfs_ops = {
+ "procfs", /* to_shortname */
+ "Unix /proc child process", /* to_longname */
+ "Unix /proc child process (started by the \"run\" command).", /* to_doc */
+ procfs_open, /* to_open */
+ 0, /* to_close */
+ procfs_attach, /* to_attach */
+ procfs_detach, /* to_detach */
+ procfs_resume, /* to_resume */
+ procfs_wait, /* to_wait */
+ procfs_fetch_registers, /* to_fetch_registers */
+ procfs_store_registers, /* to_store_registers */
+ procfs_prepare_to_store, /* to_prepare_to_store */
+ procfs_xfer_memory, /* to_xfer_memory */
+ procfs_files_info, /* to_files_info */
+ memory_insert_breakpoint, /* to_insert_breakpoint */
+ memory_remove_breakpoint, /* to_remove_breakpoint */
+ terminal_init_inferior, /* to_terminal_init */
+ terminal_inferior, /* to_terminal_inferior */
+ terminal_ours_for_output, /* to_terminal_ours_for_output */
+ terminal_ours, /* to_terminal_ours */
+ child_terminal_info, /* to_terminal_info */
+ procfs_kill_inferior, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ procfs_create_inferior, /* to_create_inferior */
+ procfs_mourn_inferior, /* to_mourn_inferior */
+ procfs_can_run, /* to_can_run */
+ procfs_notice_signals, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ procfs_stop, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_procfs ()
+{
+#ifdef HAVE_OPTIONAL_PROC_FS
+ char procname[32];
+ int fd;
+
+ /* If we have an optional /proc filesystem (e.g. under OSF/1),
+ don't add procfs support if we cannot access the running
+ GDB via /proc. */
+ sprintf (procname, PROC_NAME_FMT, getpid ());
+ if ((fd = open (procname, O_RDONLY)) < 0)
+ return;
+ close (fd);
+#endif
+
+ add_target (&procfs_ops);
+
+ add_info ("proc", info_proc,
+"Show process status information using /proc entry.\n\
+Specify process id or use current inferior by default.\n\
+Specify keywords for detailed information; default is summary.\n\
+Keywords are: `all', `faults', `flags', `id', `mappings', `signals',\n\
+`status', `syscalls', and `times'.\n\
+Unambiguous abbreviations may be used.");
+
+ init_syscall_table ();
+}
diff --git a/contrib/gdb/gdb/ptx4-nat.c b/contrib/gdb/gdb/ptx4-nat.c
new file mode 100644
index 0000000..564b799
--- /dev/null
+++ b/contrib/gdb/gdb/ptx4-nat.c
@@ -0,0 +1,209 @@
+/* Native-dependent code for ptx 4.0
+ Copyright 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include <sys/procfs.h>
+#include <sys/ptrace.h>
+#include <sys/param.h>
+#include <fcntl.h>
+
+/* Given a pointer to a general register set in /proc format (gregset_t *),
+ unpack the register contents and supply them as gdb's idea of the current
+ register values. */
+
+void
+supply_gregset (gregsetp)
+ gregset_t *gregsetp;
+{
+ supply_register(EAX_REGNUM, (char *)&(*gregsetp)[EAX]);
+ supply_register(EDX_REGNUM, (char *)&(*gregsetp)[EDX]);
+ supply_register(ECX_REGNUM, (char *)&(*gregsetp)[ECX]);
+ supply_register(EBX_REGNUM, (char *)&(*gregsetp)[EBX]);
+ supply_register(ESI_REGNUM, (char *)&(*gregsetp)[ESI]);
+ supply_register(EDI_REGNUM, (char *)&(*gregsetp)[EDI]);
+ supply_register(ESP_REGNUM, (char *)&(*gregsetp)[UESP]);
+ supply_register(EBP_REGNUM, (char *)&(*gregsetp)[EBP]);
+ supply_register(EIP_REGNUM, (char *)&(*gregsetp)[EIP]);
+ supply_register(EFLAGS_REGNUM, (char *)&(*gregsetp)[EFL]);
+}
+
+void
+fill_gregset (gregsetp, regno)
+ gregset_t *gregsetp;
+ int regno;
+{
+ int regi;
+ extern char registers[];
+
+ for (regi = 0 ; regi < NUM_REGS ; regi++)
+ {
+ if ((regno == -1) || (regno == regi))
+ {
+ (*gregsetp)[regi] = *(greg_t *)&registers[REGISTER_BYTE (regi)];
+ }
+ }
+}
+
+#if defined (FP0_REGNUM)
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), unpack the register contents and supply them as gdb's
+ idea of the current floating point register values. */
+
+void
+supply_fpregset (fpregsetp)
+ fpregset_t *fpregsetp;
+{
+ supply_fpu_registers((struct fpusave *)&fpregsetp->fp_reg_set);
+ supply_fpa_registers((struct fpasave *)&fpregsetp->f_wregs);
+}
+
+/* Given a pointer to a floating point register set in /proc format
+ (fpregset_t *), update the register specified by REGNO from gdb's idea
+ of the current floating point register set. If REGNO is -1, update
+ them all. */
+
+void
+fill_fpregset (fpregsetp, regno)
+ fpregset_t *fpregsetp;
+ int regno;
+{
+ int regi;
+ char *to;
+ char *from;
+ extern char registers[];
+
+ /* FIXME: see m68k-tdep.c for an example, for the m68k. */
+}
+
+#endif /* defined (FP0_REGNUM) */
+
+/*
+ * This doesn't quite do the same thing as the procfs.c version, but give
+ * it the same name so we don't have to put an ifdef in solib.c.
+ */
+/* this could use elf_interpreter() from elfread.c */
+int
+proc_iterate_over_mappings(func)
+ int (*func) PARAMS ((int, CORE_ADDR));
+{
+ vaddr_t curseg, memptr;
+ pt_vseg_t pv;
+ int rv, cmperr;
+ sec_ptr interp_sec;
+ char *interp_content;
+ int interp_fd, funcstat;
+ unsigned int size;
+ char buf1[NBPG], buf2[NBPG];
+
+ /*
+ * The following is really vile. We can get the name of the
+ * shared library from the exec_bfd, and we can get a list of
+ * each virtual memory segment, but there is no simple way to
+ * find the mapped segment from the shared library (ala
+ * procfs's PIOCOPENMEM). As a pretty nasty kludge, we
+ * compare the virtual memory segment to the contents of the
+ * .interp file. If they match, we assume that we've got the
+ * right one.
+ */
+
+ /*
+ * TODO: for attach, use XPT_OPENT to get the executable, in
+ * case we're attached without knowning the executable's
+ * filename.
+ */
+
+#ifdef VERBOSE_DEBUG
+ printf("proc_iter\n");
+#endif
+ interp_sec = bfd_get_section_by_name(exec_bfd, ".interp");
+ if (!interp_sec) {
+ return 0;
+ }
+
+ size = bfd_section_size(exec_bfd, interp_sec);
+ interp_content = alloca(size);
+ if (0 == bfd_get_section_contents(exec_bfd, interp_sec,
+ interp_content, (file_ptr)0, size)) {
+ return 0;
+ }
+
+#ifdef VERBOSE_DEBUG
+ printf("proc_iter: \"%s\"\n", interp_content);
+#endif
+ interp_fd = open(interp_content, O_RDONLY, 0);
+ if (-1 == interp_fd) {
+ return 0;
+ }
+
+ curseg = 0;
+ while (1) {
+ rv = ptrace(PT_NEXT_VSEG, inferior_pid, &pv, curseg);
+#ifdef VERBOSE_DEBUG
+ printf("PT_NEXT_VSEG: rv %d errno %d\n", rv, errno);
+#endif
+ if (-1 == rv)
+ break;
+ if (0 == rv)
+ break;
+#ifdef VERBOSE_DEBUG
+ printf("pv.pv_start 0x%x pv_size 0x%x pv_prot 0x%x\n",
+ pv.pv_start, pv.pv_size, pv.pv_prot);
+#endif
+ curseg = pv.pv_start + pv.pv_size;
+
+ rv = lseek(interp_fd, 0, SEEK_SET);
+ if (-1 == rv) {
+ perror("lseek");
+ close(interp_fd);
+ return 0;
+ }
+ for (memptr = pv.pv_start; memptr < pv.pv_start + pv.pv_size;
+ memptr += NBPG) {
+#ifdef VERBOSE_DEBUG
+ printf("memptr 0x%x\n", memptr);
+#endif
+ rv = read(interp_fd, buf1, NBPG);
+ if (-1 == rv) {
+ perror("read");
+ close(interp_fd);
+ return 0;
+ }
+ rv = ptrace(PT_RDATA_PAGE, inferior_pid, buf2,
+ memptr);
+ if (-1 == rv) {
+ perror("ptrace");
+ close(interp_fd);
+ return 0;
+ }
+ cmperr = memcmp(buf1, buf2, NBPG);
+ if (cmperr)
+ break;
+ }
+ if (0 == cmperr) {
+ /* this is it */
+ funcstat = (*func)(interp_fd, pv.pv_start);
+ break;
+ }
+ }
+ close(interp_fd);
+ return 0;
+}
diff --git a/contrib/gdb/gdb/pyr-tdep.c b/contrib/gdb/gdb/pyr-tdep.c
new file mode 100644
index 0000000..b9abc0f
--- /dev/null
+++ b/contrib/gdb/gdb/pyr-tdep.c
@@ -0,0 +1,452 @@
+/* Pyramid target-dependent code for GDB.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+
+/*** Prettier register printing. ***/
+
+/* Print registers in the same format as pyramid's dbx, adb, sdb. */
+pyr_print_registers(reg_buf, regnum)
+ long *reg_buf[];
+{
+ register int regno;
+ int usp, ksp;
+ struct user u;
+
+ for (regno = 0; regno < 16; regno++) {
+ printf_unfiltered/*_filtered*/ ("%6.6s: %8x %6.6s: %8x %6s: %8x %6s: %8x\n",
+ reg_names[regno], reg_buf[regno],
+ reg_names[regno+16], reg_buf[regno+16],
+ reg_names[regno+32], reg_buf[regno+32],
+ reg_names[regno+48], reg_buf[regno+48]);
+ }
+ usp = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_usp) -
+ ((char *)&u), 0);
+ ksp = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) ((char *)&u.u_pcb.pcb_ksp) -
+ ((char *)&u), 0);
+ printf_unfiltered/*_filtered*/ ("\n%6.6s: %8x %6.6s: %8x (%08x) %6.6s %8x\n",
+ reg_names[CSP_REGNUM],reg_buf[CSP_REGNUM],
+ reg_names[KSP_REGNUM], reg_buf[KSP_REGNUM], ksp,
+ "usp", usp);
+}
+
+/* Print the register regnum, or all registers if regnum is -1.
+ fpregs is currently ignored. */
+
+pyr_do_registers_info (regnum, fpregs)
+ int regnum;
+ int fpregs;
+{
+ /* On a pyr, we know a virtual register can always fit in an long.
+ Here (and elsewhere) we take advantage of that. Yuk. */
+ long raw_regs[MAX_REGISTER_RAW_SIZE*NUM_REGS];
+ register int i;
+
+ for (i = 0 ; i < 64 ; i++) {
+ read_relative_register_raw_bytes(i, raw_regs+i);
+ }
+ if (regnum == -1)
+ pyr_print_registers (raw_regs, regnum);
+ else
+ for (i = 0; i < NUM_REGS; i++)
+ if (i == regnum) {
+ long val = raw_regs[i];
+
+ fputs_filtered (reg_names[i], stdout);
+ printf_filtered(":");
+ print_spaces_filtered (6 - strlen (reg_names[i]), stdout);
+ if (val == 0)
+ printf_filtered ("0");
+ else
+ printf_filtered ("%s %d", local_hex_string_custom(val,"08"), val);
+ printf_filtered("\n");
+ }
+}
+
+/*** Debugging editions of various macros from m-pyr.h ****/
+
+CORE_ADDR frame_locals_address (frame)
+ struct frame_info *frame;
+{
+ register int addr = find_saved_register (frame,CFP_REGNUM);
+ register int result = read_memory_integer (addr, 4);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ fprintf_unfiltered (stderr,
+ "\t[[..frame_locals:%8x, %s= %x @%x fcfp= %x foo= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+ frame->frame,
+ reg_names[CFP_REGNUM],
+ result, addr,
+ frame->frame_cfp, (CFP_REGNUM),
+
+
+ read_register(13), read_register(29), read_register(61),
+ find_saved_register(frame, 61));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+ or at least CFP_REGNUM relative to FRAME (ie, result).
+ There seems to be a bug in the way the innermost frame is set up. */
+
+ return ((frame->next) ? result: frame->frame_cfp);
+}
+
+CORE_ADDR frame_args_addr (frame)
+ struct frame_info *frame;
+{
+ register int addr = find_saved_register (frame,CFP_REGNUM);
+ register int result = read_memory_integer (addr, 4);
+
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ fprintf_unfiltered (stderr,
+ "\t[[..frame_args:%8x, %s= %x @%x fcfp= %x r_r= %x\n\t gr13=%x pr13=%x tr13=%x @%x]]\n",
+ frame->frame,
+ reg_names[CFP_REGNUM],
+ result, addr,
+ frame->frame_cfp, read_register(CFP_REGNUM),
+
+ read_register(13), read_register(29), read_register(61),
+ find_saved_register(frame, 61));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ /* FIXME: I thought read_register (CFP_REGNUM) should be the right answer;
+ or at least CFP_REGNUM relative to FRAME (ie, result).
+ There seems to be a bug in the way the innermost frame is set up. */
+ return ((frame->next) ? result: frame->frame_cfp);
+}
+
+#include "symtab.h"
+#include "opcode/pyr.h"
+#include "gdbcore.h"
+
+
+/* A couple of functions used for debugging frame-handling on
+ Pyramids. (The Pyramid-dependent handling of register values for
+ windowed registers is known to be buggy.)
+
+ When debugging, these functions can supplant the normal definitions of some
+ of the macros in tm-pyramid.h The quantity of information produced
+ when these functions are used makes the gdb unusable as a
+ debugger for user programs. */
+
+extern unsigned pyr_saved_pc(), pyr_frame_chain();
+
+CORE_ADDR pyr_frame_chain(frame)
+ CORE_ADDR frame;
+{
+ int foo=frame - CONTROL_STACK_FRAME_SIZE;
+ /* printf_unfiltered ("...following chain from %x: got %x\n", frame, foo);*/
+ return foo;
+}
+
+CORE_ADDR pyr_saved_pc(frame)
+ CORE_ADDR frame;
+{
+ int foo=0;
+ foo = read_memory_integer (((CORE_ADDR)(frame))+60, 4);
+ printf_unfiltered ("..reading pc from frame 0x%0x+%d regs: got %0x\n",
+ frame, 60/4, foo);
+ return foo;
+}
+
+/* Pyramid instructions are never longer than this many bytes. */
+#define MAXLEN 24
+
+/* Number of elements in the opcode table. */
+/*const*/ static int nopcodes = (sizeof (pyr_opcodes) / sizeof( pyr_opcodes[0]));
+#define NOPCODES (nopcodes)
+
+/* Let's be byte-independent so we can use this as a cross-assembler. */
+
+#define NEXTLONG(p) \
+ (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
+
+/* Print one instruction at address MEMADDR in debugged memory,
+ on STREAM. Returns length of the instruction, in bytes. */
+
+int
+pyr_print_insn (memaddr, stream)
+ CORE_ADDR memaddr;
+ FILE *stream;
+{
+ unsigned char buffer[MAXLEN];
+ register int i, nargs, insn_size =4;
+ register unsigned char *p;
+ register char *d;
+ register int insn_opcode, operand_mode;
+ register int index_multiplier, index_reg_regno, op_1_regno, op_2_regno ;
+ long insn; /* first word of the insn, not broken down. */
+ pyr_insn_format insn_decode; /* the same, broken out into op{code,erands} */
+ long extra_1, extra_2;
+
+ read_memory (memaddr, buffer, MAXLEN);
+ insn_decode = *((pyr_insn_format *) buffer);
+ insn = * ((int *) buffer);
+ insn_opcode = insn_decode.operator;
+ operand_mode = insn_decode.mode;
+ index_multiplier = insn_decode.index_scale;
+ index_reg_regno = insn_decode.index_reg;
+ op_1_regno = insn_decode.operand_1;
+ op_2_regno = insn_decode.operand_2;
+
+
+ if (*((int *)buffer) == 0x0) {
+ /* "halt" looks just like an invalid "jump" to the insn decoder,
+ so is dealt with as a special case */
+ fprintf_unfiltered (stream, "halt");
+ return (4);
+ }
+
+ for (i = 0; i < NOPCODES; i++)
+ if (pyr_opcodes[i].datum.code == insn_opcode)
+ break;
+
+ if (i == NOPCODES)
+ /* FIXME: Handle unrecognised instructions better. */
+ fprintf_unfiltered (stream, "???\t#%08x\t(op=%x mode =%x)",
+ insn, insn_decode.operator, insn_decode.mode);
+ else
+ {
+ /* Print the mnemonic for the instruction. Pyramid insn operands
+ are so regular that we can deal with almost all of them
+ separately.
+ Unconditional branches are an exception: they are encoded as
+ conditional branches (branch if false condition, I think)
+ with no condition specified. The average user will not be
+ aware of this. To maintain their illusion that an
+ unconditional branch insn exists, we will have to FIXME to
+ treat the insn mnemnonic of all branch instructions here as a
+ special case: check the operands of branch insn and print an
+ appropriate mnemonic. */
+
+ fprintf_unfiltered (stream, "%s\t", pyr_opcodes[i].name);
+
+ /* Print the operands of the insn (as specified in
+ insn.operand_mode).
+ Branch operands of branches are a special case: they are a word
+ offset, not a byte offset. */
+
+ if (insn_decode.operator == 0x01 || insn_decode.operator == 0x02) {
+ register int bit_codes=(insn >> 16)&0xf;
+ register int i;
+ register int displacement = (insn & 0x0000ffff) << 2;
+
+ static char cc_bit_names[] = "cvzn"; /* z,n,c,v: strange order? */
+
+ /* Is bfc and no bits specified an unconditional branch?*/
+ for (i=0;i<4;i++) {
+ if ((bit_codes) & 0x1)
+ fputc_unfiltered (cc_bit_names[i], stream);
+ bit_codes >>= 1;
+ }
+
+ fprintf_unfiltered (stream, ",%0x",
+ displacement + memaddr);
+ return (insn_size);
+ }
+
+ switch (operand_mode) {
+ case 0:
+ fprintf_unfiltered (stream, "%s,%s",
+ reg_names [op_1_regno],
+ reg_names [op_2_regno]);
+ break;
+
+ case 1:
+ fprintf_unfiltered (stream, " 0x%0x,%s",
+ op_1_regno,
+ reg_names [op_2_regno]);
+ break;
+
+ case 2:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream, " $0x%0x,%s",
+ extra_1,
+ reg_names [op_2_regno]);
+ break;
+ case 3:
+ fprintf_unfiltered (stream, " (%s),%s",
+ reg_names [op_1_regno],
+ reg_names [op_2_regno]);
+ break;
+
+ case 4:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream, " 0x%0x(%s),%s",
+ extra_1,
+ reg_names [op_1_regno],
+ reg_names [op_2_regno]);
+ break;
+
+ /* S1 destination mode */
+ case 5:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%s,(%s)[%s*%1d]" : "%s,(%s)"),
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 6:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+ : " $%#0x,(%s)"),
+ op_1_regno,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 7:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? " $%#0x,(%s)[%s*%1d]"
+ : " $%#0x,(%s)"),
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 8:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? " (%s),(%s)[%s*%1d]" : " (%s),(%s)"),
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 9:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno)
+ ? "%#0x(%s),(%s)[%s*%1d]"
+ : "%#0x(%s),(%s)"),
+ extra_1,
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ /* S2 destination mode */
+ case 10:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%s,%#0x(%s)[%s*%1d]" : "%s,%#0x(%s)"),
+ reg_names [op_1_regno],
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+ case 11:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ?
+ " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+ op_1_regno,
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+ case 12:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ read_memory (memaddr+8, buffer, MAXLEN);
+ insn_size += 4;
+ extra_2 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ?
+ " $%#0x,%#0x(%s)[%s*%1d]" : " $%#0x,%#0x(%s)"),
+ extra_1,
+ extra_2,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ case 13:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno)
+ ? " (%s),%#0x(%s)[%s*%1d]"
+ : " (%s),%#0x(%s)"),
+ reg_names [op_1_regno],
+ extra_1,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+ case 14:
+ read_memory (memaddr+4, buffer, MAXLEN);
+ insn_size += 4;
+ extra_1 = * ((int *) buffer);
+ read_memory (memaddr+8, buffer, MAXLEN);
+ insn_size += 4;
+ extra_2 = * ((int *) buffer);
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%#0x(%s),%#0x(%s)[%s*%1d]"
+ : "%#0x(%s),%#0x(%s) "),
+ extra_1,
+ reg_names [op_1_regno],
+ extra_2,
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ break;
+
+ default:
+ fprintf_unfiltered (stream,
+ ((index_reg_regno) ? "%s,%s [%s*%1d]" : "%s,%s"),
+ reg_names [op_1_regno],
+ reg_names [op_2_regno],
+ reg_names [index_reg_regno],
+ index_multiplier);
+ fprintf_unfiltered (stream,
+ "\t\t# unknown mode in %08x",
+ insn);
+ break;
+ } /* switch */
+ }
+
+ {
+ return insn_size;
+ }
+ abort ();
+}
diff --git a/contrib/gdb/gdb/pyr-xdep.c b/contrib/gdb/gdb/pyr-xdep.c
new file mode 100644
index 0000000..e205b50
--- /dev/null
+++ b/contrib/gdb/gdb/pyr-xdep.c
@@ -0,0 +1,370 @@
+/* Low level Pyramid interface to ptrace, for GDB when running under Unix.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+/* #include <fcntl.h> Can we live without this? */
+
+#include "gdbcore.h"
+#include <sys/user.h> /* After a.out.h */
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ register int datum;
+ register unsigned int regaddr;
+ int reg_buf[NUM_REGS+1];
+ struct user u;
+ register int skipped_frames = 0;
+
+ registers_fetched ();
+
+ for (regno = 0; regno < 64; regno++) {
+ reg_buf[regno] = ptrace (3, inferior_pid, (PTRACE_ARG3_TYPE) regno, 0);
+
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered ("Fetching register %s, got %0x\n",
+ reg_names[regno],
+ reg_buf[regno]);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+ if (reg_buf[regno] == -1 && errno == EIO) {
+ printf_unfiltered("fetch_interior_registers: fetching register %s\n",
+ reg_names[regno]);
+ errno = 0;
+ }
+ supply_register (regno, reg_buf+regno);
+ }
+ /* that leaves regs 64, 65, and 66 */
+ datum = ptrace (3, inferior_pid,
+ (PTRACE_ARG3_TYPE) (((char *)&u.u_pcb.pcb_csp) -
+ ((char *)&u)), 0);
+
+
+
+ /* FIXME: Find the Current Frame Pointer (CFP). CFP is a global
+ register (ie, NOT windowed), that gets saved in a frame iff
+ the code for that frame has a prologue (ie, "adsf N"). If
+ there is a prologue, the adsf insn saves the old cfp in
+ pr13, cfp is set to sp, and N bytes of locals are allocated
+ (sp is decremented by n).
+ This makes finding CFP hard. I guess the right way to do it
+ is:
+ - If this is the innermost frame, believe ptrace() or
+ the core area.
+ - Otherwise:
+ Find the first insn of the current frame.
+ - find the saved pc;
+ - find the call insn that saved it;
+ - figure out where the call is to;
+ - if the first insn is an adsf, we got a frame
+ pointer. */
+
+
+ /* Normal processors have separate stack pointers for user and
+ kernel mode. Getting the last user mode frame on such
+ machines is easy: the kernel context of the ptrace()'d
+ process is on the kernel stack, and the USP points to what
+ we want. But Pyramids only have a single cfp for both user and
+ kernel mode. And processes being ptrace()'d have some
+ kernel-context control frames on their stack.
+ To avoid tracing back into the kernel context of an inferior,
+ we skip 0 or more contiguous control frames where the pc is
+ in the kernel. */
+
+ while (1) {
+ register int inferior_saved_pc;
+ inferior_saved_pc = ptrace (1, inferior_pid,
+ (PTRACE_ARG3_TYPE) (datum+((32+15)*4)), 0);
+ if (inferior_saved_pc > 0) break;
+#if defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered("skipping kernel frame %08x, pc=%08x\n", datum,
+ inferior_saved_pc);
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+ skipped_frames++;
+ datum -= CONTROL_STACK_FRAME_SIZE;
+ }
+
+ reg_buf[CSP_REGNUM] = datum;
+ supply_register(CSP_REGNUM, reg_buf+CSP_REGNUM);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ if (skipped_frames) {
+ fprintf_unfiltered (stderr,
+ "skipped %d frames from %x to %x; cfp was %x, now %x\n",
+ skipped_frames, reg_buf[CSP_REGNUM]);
+ }
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+}
+
+/* Store our register values back into the inferior.
+ If REGNO is -1, do this for all registers.
+ Otherwise, REGNO specifies which register (so we can save time). */
+
+void
+store_inferior_registers (regno)
+ int regno;
+{
+ register unsigned int regaddr;
+ char buf[80];
+
+ if (regno >= 0)
+ {
+ if ((0 <= regno) && (regno < 64)) {
+ /*regaddr = register_addr (regno, offset);*/
+ regaddr = regno;
+ errno = 0;
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing register number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+ }
+ else
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ /*regaddr = register_addr (regno, offset);*/
+ regaddr = regno;
+ errno = 0;
+ ptrace (6, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+ read_register (regno));
+ if (errno != 0)
+ {
+ sprintf (buf, "writing all regs, number %d", regno);
+ perror_with_name (buf);
+ }
+ }
+}
+
+/*** Extensions to core and dump files, for GDB. */
+
+extern unsigned int last_frame_offset;
+
+#ifdef PYRAMID_CORE
+
+/* Can't make definitions here static, since corefile.c needs them
+ to do bounds checking on the core-file areas. O well. */
+
+/* have two stacks: one for data, one for register windows. */
+extern CORE_ADDR reg_stack_start;
+extern CORE_ADDR reg_stack_end;
+
+/* need this so we can find the global registers: they never get saved. */
+CORE_ADDR global_reg_offset;
+static CORE_ADDR last_frame_address;
+CORE_ADDR last_frame_offset;
+
+
+/* Address in core file of start of register window stack area.
+ Don't know if is this any of meaningful, useful or necessary. */
+extern int reg_stack_offset;
+
+#endif /* PYRAMID_CORE */
+
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+#ifdef PYRAMID_CORE
+ reg_stack_start = CONTROL_STACK_ADDR;
+ reg_stack_end = CONTROL_STACK_ADDR; /* this isn't strictly true...*/
+#endif /* PYRAMID_CORE */
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct user u;
+
+ unsigned int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name ("Not a core file: reading upage");
+ if (val != sizeof u)
+ error ("Not a core file: could only read %d bytes", val);
+ data_start = exec_data_start;
+
+ data_end = data_start + NBPG * u.u_dsize;
+ data_offset = NBPG * UPAGES;
+ stack_offset = NBPG * (UPAGES + u.u_dsize);
+
+ /* find registers in core file */
+#ifdef PYRAMID_PTRACE
+ stack_start = stack_end - NBPG * u.u_ussize;
+ reg_stack_offset = stack_offset + (NBPG *u.u_ussize);
+ reg_stack_end = reg_stack_start + NBPG * u.u_cssize;
+
+ last_frame_address = ((int) u.u_pcb.pcb_csp);
+ last_frame_offset = reg_stack_offset + last_frame_address
+ - CONTROL_STACK_ADDR ;
+ global_reg_offset = (char *)&u - (char *)&u.u_pcb.pcb_gr0 ;
+
+ /* skip any control-stack frames that were executed in the
+ kernel. */
+
+ while (1) {
+ char buf[4];
+ val = lseek (corechan, last_frame_offset+(47*4), 0);
+ if (val < 0)
+ perror_with_name (filename);
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+
+ if (*(int *)buf >= 0)
+ break;
+ printf_unfiltered ("skipping frame %s\n", local_hex_string (last_frame_address));
+ last_frame_offset -= CONTROL_STACK_FRAME_SIZE;
+ last_frame_address -= CONTROL_STACK_FRAME_SIZE;
+ }
+ reg_offset = last_frame_offset;
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered ("Control stack pointer = %s\n",
+ local_hex_string (u.u_pcb.pcb_csp));
+ printf_unfiltered ("offset to control stack %d outermost frame %d (%s)\n",
+ reg_stack_offset, reg_offset, local_hex_string (last_frame_address));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+
+#else /* not PYRAMID_CORE */
+ stack_start = stack_end - NBPG * u.u_ssize;
+ reg_offset = (int) u.u_ar0 - KERNEL_U_ADDR;
+#endif /* not PYRAMID_CORE */
+
+#ifdef __not_on_pyr_yet
+ /* Some machines put an absolute address in here and some put
+ the offset in the upage of the regs. */
+ reg_offset = (int) u.u_ar0;
+ if (reg_offset > NBPG * UPAGES)
+ reg_offset -= KERNEL_U_ADDR;
+#endif
+
+ /* I don't know where to find this info.
+ So, for now, mark it as not available. */
+ N_SET_MAGIC (core_aouthdr, 0);
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < 64; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0
+ || (val = myread (corechan, buf, sizeof buf)) < 0)
+ {
+ char * buffer = (char *) alloca (strlen (reg_names[regno])
+ + 30);
+ strcpy (buffer, "Reading register ");
+ strcat (buffer, reg_names[regno]);
+
+ perror_with_name (buffer);
+ }
+
+ if (val < 0)
+ perror_with_name (filename);
+#ifdef PYRAMID_CONTROL_FRAME_DEBUGGING
+ printf_unfiltered ("[reg %s(%d), offset in file %s=0x%0x, addr =0x%0x, =%0x]\n",
+ reg_names[regno], regno, filename,
+ register_addr(regno, reg_offset),
+ regno * 4 + last_frame_address,
+ *((int *)buf));
+#endif /* PYRAMID_CONTROL_FRAME_DEBUGGING */
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename, NULL);
+ }
+
+#if 1 || defined(PYRAMID_CONTROL_FRAME_DEBUGGING)
+ printf_unfiltered ("Providing CSP (%s) as nominal address of current frame.\n",
+ local_hex_string(last_frame_address));
+#endif PYRAMID_CONTROL_FRAME_DEBUGGING
+ /* FIXME: Which of the following is correct? */
+#if 0
+ set_current_frame ( create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+#else
+ set_current_frame ( create_new_frame (last_frame_address,
+ read_pc ()));
+#endif
+
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_unfiltered ("No core file now.\n");
+}
diff --git a/contrib/gdb/gdb/remote-adapt.c b/contrib/gdb/gdb/remote-adapt.c
new file mode 100644
index 0000000..8fcb1f7
--- /dev/null
+++ b/contrib/gdb/gdb/remote-adapt.c
@@ -0,0 +1,1359 @@
+/* Remote debugging interface for AMD 290*0 Adapt Monitor Version 2.1d18.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by David Wood at New York University (wood@lab.ultra.nyu.edu).
+ Adapted from work done at Cygnus Support in remote-eb.c.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but is for an esoteric situation--
+ having a 29k board attached to an Adapt inline monitor.
+ The monitor is connected via serial line to a unix machine
+ running gdb.
+
+ 3/91 - developed on Sun3 OS 4.1, by David Wood
+ o - I can't get binary coff to load.
+ o - I can't get 19200 baud rate to work.
+ 7/91 o - Freeze mode tracing can be done on a 29050. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+
+/* External data declarations */
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+/* Forward data declarations */
+extern struct target_ops adapt_ops; /* Forward declaration */
+
+/* Forward function declarations */
+static void adapt_fetch_registers ();
+static void adapt_store_registers ();
+static void adapt_close ();
+static int adapt_clear_breakpoints();
+
+#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
+#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
+
+/* Can't seem to get binary coff working */
+#define ASCII_COFF /* Adapt will be downloaded with ascii coff */
+
+/* FIXME: Replace with `set remotedebug'. */
+#define LOG_FILE "adapt.log"
+#if defined (LOG_FILE)
+FILE *log_file=NULL;
+#endif
+
+static int timeout = 5;
+static char *dev_name;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ adapt_open knows that we don't have a file open when the program
+ starts. */
+int adapt_desc = -1;
+
+/* stream which is fdopen'd from adapt_desc. Only valid when
+ adapt_desc != -1. */
+FILE *adapt_stream;
+
+#define ON 1
+#define OFF 0
+static void
+rawmode(desc, turnon)
+int desc;
+int turnon;
+{
+ TERMINAL sg;
+
+ if (desc < 0)
+ return;
+
+ ioctl (desc, TIOCGETP, &sg);
+
+ if (turnon) {
+#ifdef HAVE_TERMIO
+ sg.c_lflag &= ~(ICANON);
+#else
+ sg.sg_flags |= RAW;
+#endif
+ } else {
+#ifdef HAVE_TERMIO
+ sg.c_lflag |= ICANON;
+#else
+ sg.sg_flags &= ~(RAW);
+#endif
+ }
+ ioctl (desc, TIOCSETP, &sg);
+}
+
+/* Suck up all the input from the adapt */
+slurp_input()
+{
+ char buf[8];
+
+#ifdef HAVE_TERMIO
+ /* termio does the timeout for us. */
+ while (read (adapt_desc, buf, 8) > 0);
+#else
+ alarm (timeout);
+ while (read (adapt_desc, buf, 8) > 0);
+ alarm (0);
+#endif
+}
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+static int
+readchar ()
+{
+ char buf;
+
+ buf = '\0';
+#ifdef HAVE_TERMIO
+ /* termio does the timeout for us. */
+ read (adapt_desc, &buf, 1);
+#else
+ alarm (timeout);
+ if (read (adapt_desc, &buf, 1) < 0)
+ {
+ if (errno == EINTR)
+ error ("Timeout reading from remote system.");
+ else
+ perror_with_name ("remote");
+ }
+ alarm (0);
+#endif
+
+ if (buf == '\0')
+ error ("Timeout reading from remote system.");
+#if defined (LOG_FILE)
+ putc (buf & 0x7f, log_file);
+#endif
+ return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+
+ fflush(adapt_stream);
+ immediate_quit = 1;
+ while (1)
+ {
+ if (readchar() == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ p = string;
+ }
+}
+
+/* Keep discarding input until we see the adapt prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: adapt_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a adapt_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt ()
+{
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush (log_file);
+#endif
+ fflush(adapt_stream);
+ expect ("\n# ");
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from adapt_desc and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Read a 32-bit hex word from the adapt, preceded by a space */
+static long
+get_hex_word()
+{
+ long val;
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ return val;
+}
+/* Get N 32-bit hex words from remote, each preceded by a space
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ while (n--) {
+ val = get_hex_word();
+ supply_register(regno++,(char *) &val);
+ }
+}
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+# ifndef volatile
+# define volatile /**/
+# endif
+#endif
+volatile int n_alarms;
+
+void
+adapt_timer ()
+{
+#if 0
+ if (kiodebug)
+ printf ("adapt_timer called\n");
+#endif
+ n_alarms++;
+}
+#endif
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to adapt_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+void
+adapt_kill(arg,from_tty)
+char *arg;
+int from_tty;
+{
+ fprintf (adapt_stream, "K");
+ fprintf (adapt_stream, "\r");
+ expect_prompt ();
+}
+/*
+ * Download a file specified in 'args', to the adapt.
+ * FIXME: Assumes the file to download is a binary coff file.
+ */
+static void
+adapt_load(args,fromtty)
+char *args;
+int fromtty;
+{
+ FILE *fp;
+ int n;
+ char buffer[1024];
+
+ if (!adapt_stream) {
+ printf_filtered("Adapt not open. Use 'target' command to open adapt\n");
+ return;
+ }
+
+ /* OK, now read in the file. Y=read, C=COFF, T=dTe port
+ 0=start address. */
+
+#ifdef ASCII_COFF /* Ascii coff */
+ fprintf (adapt_stream, "YA T,0\r");
+ fflush(adapt_stream); /* Just in case */
+ /* FIXME: should check args for only 1 argument */
+ sprintf(buffer,"cat %s | btoa > /tmp/#adapt-btoa",args);
+ system(buffer);
+ fp = fopen("/tmp/#adapt-btoa","r");
+ rawmode(adapt_desc,OFF);
+ while (n=fread(buffer,1,1024,fp)) {
+ do { n -= write(adapt_desc,buffer,n); } while (n>0);
+ if (n<0) { perror("writing ascii coff"); break; }
+ }
+ fclose(fp);
+ rawmode(adapt_desc,ON);
+ system("rm /tmp/#adapt-btoa");
+#else /* Binary coff - can't get it to work .*/
+ fprintf (adapt_stream, "YC T,0\r");
+ fflush(adapt_stream); /* Just in case */
+ if (!(fp = fopen(args,"r"))) {
+ printf_filtered("Can't open %s\n",args);
+ return;
+ }
+ while (n=fread(buffer,1,512,fp)) {
+ do { n -= write(adapt_desc,buffer,n); } while (n>0);
+ if (n<0) { perror("writing ascii coff"); break; }
+ }
+ fclose(fp);
+#endif
+ expect_prompt (); /* Skip garbage that comes out */
+ fprintf (adapt_stream, "\r");
+ expect_prompt ();
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+void
+adapt_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote adapt process.");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ if (adapt_stream) {
+ adapt_kill(NULL,NULL);
+ adapt_clear_breakpoints();
+ init_wait_for_inferior ();
+ /* Clear the input because what the adapt sends back is different
+ * depending on whether it was running or not.
+ */
+ slurp_input(); /* After this there should be a prompt */
+ fprintf(adapt_stream,"\r");
+ expect_prompt();
+ printf_filtered("Do you want to download '%s' (y/n)? [y] : ",prog_name);
+ {
+ char buffer[10];
+ gets(buffer);
+ if (*buffer != 'n') {
+ adapt_load(prog_name,0);
+ }
+ }
+
+#ifdef NOTDEF
+ /* Set the PC and wait for a go/cont */
+ fprintf (adapt_stream, "G %x,N\r",entry_pt);
+ printf_filtered("Now use the 'continue' command to start.\n");
+ expect_prompt ();
+#else
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+ proceed(entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+#endif
+
+ } else {
+ printf_filtered("Adapt not open yet.\n");
+ }
+}
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+static struct {int rate, damn_b;} baudtab[] = {
+ {0, B0},
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+static int damn_b (rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+ return B38400; /* Random */
+}
+
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication, then a space,
+ then the baud rate.
+ */
+
+static int baudrate = 9600;
+static void
+adapt_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ TERMINAL sg;
+ unsigned int prl;
+ char *p;
+
+ /* Find the first whitespace character, it separates dev_name from
+ prog_name. */
+ if (name == 0)
+ goto erroid;
+
+ for (p = name;
+ *p != '\0' && !isspace (*p); p++)
+ ;
+ if (*p == '\0')
+erroid:
+ error ("\
+Please include the name of the device for the serial port,\n\
+the baud rate, and the name of the program to run on the remote system.");
+ dev_name = (char*)xmalloc(p - name + 1);
+ strncpy (dev_name, name, p - name);
+ dev_name[p - name] = '\0';
+
+ /* Skip over the whitespace after dev_name */
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (1 != sscanf (p, "%d ", &baudrate))
+ goto erroid;
+
+ /* Skip the number and then the spaces */
+ for (; isdigit (*p); p++)
+ /*EMPTY*/;
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (p, strlen (p));
+
+ adapt_close (0);
+
+ adapt_desc = open (dev_name, O_RDWR);
+ if (adapt_desc < 0)
+ perror_with_name (dev_name);
+ ioctl (adapt_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+ sg.c_cc[VMIN] = 0; /* read with timeout. */
+ sg.c_cc[VTIME] = timeout * 10;
+ sg.c_lflag &= ~(ICANON | ECHO);
+ sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+ sg.sg_ispeed = damn_b (baudrate);
+ sg.sg_ospeed = damn_b (baudrate);
+ sg.sg_flags |= RAW | ANYP;
+ sg.sg_flags &= ~ECHO;
+#endif
+
+ ioctl (adapt_desc, TIOCSETP, &sg);
+ adapt_stream = fdopen (adapt_desc, "r+");
+
+ push_target (&adapt_ops);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+ /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+ the read. */
+ if (siginterrupt (SIGALRM, 1) != 0)
+ perror ("adapt_open: error in siginterrupt");
+#endif
+
+ /* Set up read timeout timer. */
+ if ((void (*)) signal (SIGALRM, adapt_timer) == (void (*)) -1)
+ perror ("adapt_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+
+ /* Put this port into NORMAL mode, send the 'normal' character */
+ write(adapt_desc, "", 1); /* Control A */
+ write(adapt_desc, "\r", 1);
+ expect_prompt ();
+
+ /* Hello? Are you there? */
+ write (adapt_desc, "\r", 1);
+
+ expect_prompt ();
+
+ /* Clear any break points */
+ adapt_clear_breakpoints();
+
+ /* Print out some stuff, letting the user now what's going on */
+ printf_filtered("Connected to an Adapt via %s.\n", dev_name);
+ /* FIXME: can this restriction be removed? */
+ printf_filtered("Remote debugging using virtual addresses works only\n");
+ printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n");
+ if (processor_type != a29k_freeze_mode) {
+ fprintf_filtered(stderr,
+ "Freeze-mode debugging not available, and can only be done on an A29050.\n");
+ }
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+adapt_close (quitting)
+ int quitting;
+{
+
+ /* Clear any break points */
+ adapt_clear_breakpoints();
+
+ /* Put this port back into REMOTE mode */
+ if (adapt_stream) {
+ fflush(adapt_stream);
+ sleep(1); /* Let any output make it all the way back */
+ write(adapt_desc, "R\r", 2);
+ }
+
+ /* Due to a bug in Unix, fclose closes not only the stdio stream,
+ but also the file descriptor. So we don't actually close
+ adapt_desc. */
+ if (adapt_stream)
+ fclose (adapt_stream); /* This also closes adapt_desc */
+ if (adapt_desc >= 0)
+ /* close (adapt_desc); */
+
+ /* Do not try to close adapt_desc again, later in the program. */
+ adapt_stream = NULL;
+ adapt_desc = -1;
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror (log_file))
+ printf_filtered ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf_filtered ("Error closing log file.\n");
+ log_file = NULL;
+ }
+#endif
+}
+
+/* Attach to the target that is already loaded and possibly running */
+static void
+adapt_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+
+ if (from_tty)
+ printf_filtered ("Attaching to remote program %s.\n", prog_name);
+
+ /* Send the adapt a kill. It is ok if it is not already running */
+ fprintf(adapt_stream, "K\r"); fflush(adapt_stream);
+ expect_prompt(); /* Slurp the echo */
+}
+
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+void
+adapt_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+
+ if (adapt_stream) { /* Send it on its way (tell it to continue) */
+ adapt_clear_breakpoints();
+ fprintf(adapt_stream,"G\r");
+ }
+
+ pop_target(); /* calls adapt_close to do the real work */
+ if (from_tty)
+ printf_filtered ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+void
+adapt_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (step)
+ {
+ write (adapt_desc, "t 1,s\r", 6);
+ /* Wait for the echo. */
+ expect ("t 1,s\r\n");
+ /* Then comes a line containing the instruction we stepped to. */
+ expect ("@");
+ /* Then we get the prompt. */
+ expect_prompt ();
+
+ /* Force the next adapt_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type
+ "continue" to see any. FIXME, this should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ {
+ write (adapt_desc, "G\r", 2);
+ /* Swallow the echo. */
+ expect_prompt();
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+int
+adapt_wait (status)
+ struct target_waitstatus *status;
+{
+ /* Strings to look for. '?' means match any single character.
+ Note that with the algorithm we use, the initial character
+ of the string cannot recur in the string, or we will not
+ find some cases of the string in the input. */
+
+ static char bpt[] = "@";
+ /* It would be tempting to look for "\n[__exit + 0x8]\n"
+ but that requires loading symbols with "yc i" and even if
+ we did do that we don't know that the file has symbols. */
+ static char exitmsg[] = "@????????I JMPTI GR121,LR0";
+ char *bp = bpt;
+ char *ep = exitmsg;
+
+ /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
+ char swallowed[50];
+ /* Current position in swallowed. */
+ char *swallowed_p = swallowed;
+
+ int ch;
+ int ch_handled;
+ int old_timeout = timeout;
+ int old_immediate_quit = immediate_quit;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ if (need_artificial_trap != 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ return 0;
+ }
+
+ timeout = 0; /* Don't time out -- user program is running. */
+ immediate_quit = 1; /* Helps ability to QUIT */
+ while (1) {
+ QUIT; /* Let user quit and leave process running */
+ ch_handled = 0;
+ ch = readchar ();
+ if (ch == *bp) {
+ bp++;
+ if (*bp == '\0')
+ break;
+ ch_handled = 1;
+
+ *swallowed_p++ = ch;
+ } else
+ bp = bpt;
+ if (ch == *ep || *ep == '?') {
+ ep++;
+ if (*ep == '\0')
+ break;
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+ ch_handled = 1;
+ } else
+ ep = exitmsg;
+ if (!ch_handled) {
+ char *p;
+ /* Print out any characters which have been swallowed. */
+ for (p = swallowed; p < swallowed_p; ++p)
+ putc (*p, stdout);
+ swallowed_p = swallowed;
+ putc (ch, stdout);
+ }
+ }
+ expect_prompt ();
+ if (*bp== '\0')
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+ timeout = old_timeout;
+ immediate_quit = old_immediate_quit;
+ return 0;
+}
+
+/* Return the name of register number REGNO
+ in the form input and output by adapt.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[80];
+ if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32 )
+ sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ sprintf (buf, "GR%03d", regno - GR64_REGNUM + 64);
+#endif
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ sprintf (buf, "LR%03d", regno - LR0_REGNUM);
+ else if (regno == Q_REGNUM)
+ strcpy (buf, "SR131");
+ else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
+ sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
+ else if (regno == ALU_REGNUM)
+ strcpy (buf, "SR132");
+ else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
+ sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
+ else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM) {
+ /* When a 29050 is in freeze-mode, read shadow pcs instead */
+ if ((regno >= NPC_REGNUM && regno <= PC2_REGNUM) && USE_SHADOW_PC)
+ sprintf (buf, "SR%03d", regno - NPC_REGNUM + 20);
+ else
+ sprintf (buf, "SR%03d", regno - VAB_REGNUM);
+ }
+ else if (regno == GR1_REGNUM)
+ strcpy (buf, "GR001");
+ return buf;
+}
+
+/* Read the remote registers. */
+
+static void
+adapt_fetch_registers ()
+{
+ int reg_index;
+ int regnum_index;
+ char tempbuf[10];
+ int sreg_buf[16];
+ int i,j;
+
+/*
+ * Global registers
+ */
+#if defined(GR64_REGNUM)
+ write (adapt_desc, "dw gr64,gr95\r", 13);
+ for (reg_index = 64, regnum_index = GR64_REGNUM;
+ reg_index < 96;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "GR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+#endif
+ write (adapt_desc, "dw gr96,gr127\r", 14);
+ for (reg_index = 96, regnum_index = GR96_REGNUM;
+ reg_index < 128;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "GR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+
+/*
+ * Local registers
+ */
+ for (i = 0; i < 128; i += 32)
+ {
+ /* The PC has a tendency to hang if we get these
+ all in one fell swoop ("dw lr0,lr127"). */
+ sprintf (tempbuf, "dw lr%d\r", i);
+ write (adapt_desc, tempbuf, strlen (tempbuf));
+ for (reg_index = i, regnum_index = LR0_REGNUM + i;
+ reg_index < i + 32;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "LR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+ }
+
+/*
+ * Special registers
+ */
+ sprintf (tempbuf, "dw sr0\r");
+ write (adapt_desc, tempbuf, strlen (tempbuf));
+ for (i=0 ; i<4 ; i++) { /* SR0 - SR14 */
+ sprintf (tempbuf, "SR%3d",i*4);
+ expect(tempbuf);
+ for (j=0 ; j < (i==3 ? 3 : 4) ; j++)
+ sreg_buf[i*4 + j] = get_hex_word();
+ }
+ expect_prompt();
+ /*
+ * Read the pcs individually if we are in freeze mode.
+ * See get_reg_name(), it translates the register names for the pcs to
+ * the names of the shadow pcs.
+ */
+ if (USE_SHADOW_PC) {
+ sreg_buf[10] = read_register(NPC_REGNUM); /* pc0 */
+ sreg_buf[11] = read_register(PC_REGNUM); /* pc1 */
+ sreg_buf[12] = read_register(PC2_REGNUM); /* pc2 */
+ }
+ for (i=0 ; i<14 ; i++) /* Supply vab -> lru */
+ supply_register(VAB_REGNUM+i, (char *) &sreg_buf[i]);
+ sprintf (tempbuf, "dw sr128\r");
+ write (adapt_desc, tempbuf, strlen (tempbuf));
+ for (i=0 ; i<2 ; i++) { /* SR128 - SR135 */
+ sprintf (tempbuf, "SR%3d",128 + i*4);
+ expect(tempbuf);
+ for (j=0 ; j<4 ; j++)
+ sreg_buf[i*4 + j] = get_hex_word();
+ }
+ expect_prompt();
+ supply_register(IPC_REGNUM,(char *) &sreg_buf[0]);
+ supply_register(IPA_REGNUM,(char *) &sreg_buf[1]);
+ supply_register(IPB_REGNUM,(char *) &sreg_buf[2]);
+ supply_register(Q_REGNUM, (char *) &sreg_buf[3]);
+ /* Skip ALU */
+ supply_register(BP_REGNUM, (char *) &sreg_buf[5]);
+ supply_register(FC_REGNUM, (char *) &sreg_buf[6]);
+ supply_register(CR_REGNUM, (char *) &sreg_buf[7]);
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, (char *) &val);
+ supply_register (INTE_REGNUM, (char *) &val);
+ supply_register (FPS_REGNUM, (char *) &val);
+ supply_register (EXO_REGNUM, (char *) &val);
+ }
+
+ write (adapt_desc, "dw gr1,gr1\r", 11);
+ expect ("GR001 ");
+ get_hex_regs (1, GR1_REGNUM);
+ expect_prompt ();
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ */
+static void
+adapt_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ adapt_fetch_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (adapt_stream, "dw %s,%s\r", name, name);
+ expect (name);
+ expect (" ");
+ get_hex_regs (1, regno);
+ expect_prompt ();
+ }
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+adapt_store_registers ()
+{
+ int i, j;
+
+ fprintf (adapt_stream, "s gr1,%x\r", read_register (GR1_REGNUM));
+ expect_prompt ();
+
+#if defined(GR64_REGNUM)
+ for (j = 0; j < 32; j += 16)
+ {
+ fprintf (adapt_stream, "s gr%d,", j + 64);
+ for (i = 0; i < 15; ++i)
+ fprintf (adapt_stream, "%x,", read_register (GR64_REGNUM + j + i));
+ fprintf (adapt_stream, "%x\r", read_register (GR64_REGNUM + j + 15));
+ expect_prompt ();
+ }
+#endif
+ for (j = 0; j < 32; j += 16)
+ {
+ fprintf (adapt_stream, "s gr%d,", j + 96);
+ for (i = 0; i < 15; ++i)
+ fprintf (adapt_stream, "%x,", read_register (GR96_REGNUM + j + i));
+ fprintf (adapt_stream, "%x\r", read_register (GR96_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ for (j = 0; j < 128; j += 16)
+ {
+ fprintf (adapt_stream, "s lr%d,", j);
+ for (i = 0; i < 15; ++i)
+ fprintf (adapt_stream, "%x,", read_register (LR0_REGNUM + j + i));
+ fprintf (adapt_stream, "%x\r", read_register (LR0_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ fprintf (adapt_stream, "s sr128,%x,%x,%x\r", read_register (IPC_REGNUM),
+ read_register (IPA_REGNUM), read_register (IPB_REGNUM));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr133,%x,%x,%x\r", read_register (BP_REGNUM),
+ read_register (FC_REGNUM), read_register (CR_REGNUM));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr131,%x\r", read_register (Q_REGNUM));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr0,");
+ for (i=0 ; i<7 ; ++i)
+ fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
+ expect_prompt ();
+ fprintf (adapt_stream, "s sr7,");
+ for (i=7; i<14 ; ++i)
+ fprintf (adapt_stream, "%x,", read_register (VAB_REGNUM + i));
+ expect_prompt ();
+}
+
+/* Store register REGNO, or all if REGNO == -1.
+ Return errno value. */
+void
+adapt_store_register (regno)
+ int regno;
+{
+ /* printf("adapt_store_register() called.\n"); fflush(stdout); /* */
+ if (regno == -1)
+ adapt_store_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (adapt_stream, "s %s,%x\r", name, read_register (regno));
+ /* Setting GR1 changes the numbers of all the locals, so
+ invalidate the register cache. Do this *after* calling
+ read_register, because we want read_register to return the
+ value that write_register has just stuffed into the registers
+ array, not the value of the register fetched from the
+ inferior. */
+ if (regno == GR1_REGNUM)
+ registers_changed ();
+ expect_prompt ();
+ }
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+void
+adapt_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static CORE_ADDR
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(KERNEL_DEBUGGING)
+ /* Check for a virtual address in the kernel */
+ /* Assume physical address of ublock is in paddr_u register */
+ if (addr >= UVADDR) {
+ /* PADDR_U register holds the physical address of the ublock */
+ CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
+ return(i + addr - (CORE_ADDR)UVADDR);
+ } else {
+ return(addr);
+ }
+#else
+ return(addr);
+#endif
+}
+
+
+/* FIXME! Merge these two. */
+int
+adapt_xfer_inferior_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+
+ memaddr = translate_addr(memaddr);
+
+ if (write)
+ return adapt_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return adapt_read_inferior_memory (memaddr, myaddr, len);
+}
+
+void
+adapt_files_info ()
+{
+ printf_filtered("\tAttached to %s at %d baud and running program %s\n",
+ dev_name, baudrate, prog_name);
+ printf_filtered("\ton an %s processor.\n", processor_name[processor_type]);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns errno value.
+ * sb/sh instructions don't work on unaligned addresses, when TU=1.
+ */
+int
+adapt_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+ unsigned int cps;
+
+ /* Turn TU bit off so we can do 'sb' commands */
+ cps = read_register(CPS_REGNUM);
+ if (cps & 0x00000800)
+ write_register(CPS_REGNUM,cps&~(0x00000800));
+
+ for (i = 0; i < len; i++)
+ {
+ if ((i % 16) == 0)
+ fprintf (adapt_stream, "sb %x,", memaddr + i);
+ if ((i % 16) == 15 || i == len - 1)
+ {
+ fprintf (adapt_stream, "%x\r", ((unsigned char *)myaddr)[i]);
+ expect_prompt ();
+ }
+ else
+ fprintf (adapt_stream, "%x,", ((unsigned char *)myaddr)[i]);
+ }
+ /* Restore the old value of cps if the TU bit was on */
+ if (cps & 0x00000800)
+ write_register(CPS_REGNUM,cps);
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns errno value. */
+int
+adapt_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ adapt_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len to memaddr and gets 0. */
+ /* However, something like
+ adapt_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+
+ if (((memaddr - 1) + len) < memaddr)
+ return EIO;
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+
+ fprintf (adapt_stream, "db %x,%x\r", startaddr,
+ (startaddr - 1) + len_this_pass);
+
+#ifdef NOTDEF /* Why do this */
+ expect ("\n");
+ /* Look for 8 hex digits. */
+ i = 0;
+ while (1)
+ {
+ if (isxdigit (readchar ()))
+ ++i;
+ else
+ {
+ expect_prompt ();
+ error ("Hex digit expected from remote system.");
+ }
+ if (i >= 8)
+ break;
+ }
+#endif /* NOTDEF */
+
+ expect (" ");
+
+ for (i = 0; i < len_this_pass; i++)
+ get_hex_byte (&myaddr[count++]);
+
+ expect_prompt ();
+
+ startaddr += len_this_pass;
+ }
+ return count;
+}
+
+#define MAX_BREAKS 8
+static int num_brkpts=0;
+static int
+adapt_insert_breakpoint(addr, save)
+CORE_ADDR addr;
+char *save; /* Throw away, let adapt save instructions */
+{
+ if (num_brkpts < MAX_BREAKS) {
+ num_brkpts++;
+ fprintf (adapt_stream, "B %x", addr);
+ fprintf (adapt_stream, "\r");
+ expect_prompt ();
+ return(0); /* Success */
+ } else {
+ fprintf_filtered(stderr,
+ "Too many break points, break point not installed\n");
+ return(1); /* Failure */
+ }
+
+}
+static int
+adapt_remove_breakpoint(addr, save)
+CORE_ADDR addr;
+char *save; /* Throw away, let adapt save instructions */
+{
+ if (num_brkpts > 0) {
+ num_brkpts--;
+ fprintf (adapt_stream, "BR %x", addr);
+ fprintf (adapt_stream, "\r");
+ fflush (adapt_stream);
+ expect_prompt ();
+ }
+ return(0);
+}
+
+/* Clear the adapts notion of what the break points are */
+static int
+adapt_clear_breakpoints()
+{
+ if (adapt_stream) {
+ fprintf (adapt_stream, "BR"); /* Clear all break points */
+ fprintf (adapt_stream, "\r");
+ fflush(adapt_stream);
+ expect_prompt ();
+ }
+ num_brkpts = 0;
+}
+static void
+adapt_mourn()
+{
+ adapt_clear_breakpoints();
+ pop_target (); /* Pop back to no-child state */
+ generic_mourn_inferior ();
+}
+
+/* Display everthing we read in from the adapt until we match/see the
+ * specified string
+ */
+static int
+display_until(str)
+char *str;
+{
+ int i=0,j,c;
+
+ while (c=readchar()) {
+ if (c==str[i]) {
+ i++;
+ if (i == strlen(str)) return;
+ } else {
+ if (i) {
+ for (j=0 ; j<i ; j++) /* Put everthing we matched */
+ putchar(str[j]);
+ i=0;
+ }
+ putchar(c);
+ }
+ }
+
+}
+
+
+/* Put a command string, in args, out to the adapt. The adapt is assumed to
+ be in raw mode, all writing/reading done through adapt_desc.
+ Ouput from the adapt is placed on the users terminal until the
+ prompt from the adapt is seen.
+ FIXME: Can't handle commands that take input. */
+
+void
+adapt_com (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ if (!adapt_stream) {
+ printf_filtered("Adapt not open. Use the 'target' command to open.\n");
+ return;
+ }
+
+ /* Clear all input so only command relative output is displayed */
+ slurp_input();
+
+ switch(islower(args[0]) ? toupper(args[0]) : args[0]) {
+ default:
+ printf_filtered("Unknown/Unimplemented adapt command '%s'\n",args);
+ break;
+ case 'G': /* Go, begin execution */
+ write(adapt_desc,args,strlen(args));
+ write(adapt_desc,"\r",1);
+ expect_prompt();
+ break;
+ case 'B': /* Break points, B or BR */
+ case 'C': /* Check current 29k status (running/halted) */
+ case 'D': /* Display data/registers */
+ case 'I': /* Input from i/o space */
+ case 'J': /* Jam an instruction */
+ case 'K': /* Kill, stop execution */
+ case 'L': /* Disassemble */
+ case 'O': /* Output to i/o space */
+ case 'T': /* Trace */
+ case 'P': /* Pulse an input line */
+ case 'X': /* Examine special purpose registers */
+ case 'Z': /* Display trace buffer */
+ write(adapt_desc,args,strlen(args));
+ write(adapt_desc,"\r",1);
+ expect(args); /* Don't display the command */
+ display_until("# ");
+ break;
+ /* Begin commands that take input in the form 'c x,y[,z...]' */
+ case 'S': /* Set memory or register */
+ if (strchr(args,',')) { /* Assume it is properly formatted */
+ write(adapt_desc,args,strlen(args));
+ write(adapt_desc,"\r",1);
+ expect_prompt();
+ }
+ break;
+ }
+}
+
+/* Define the target subroutine names */
+
+struct target_ops adapt_ops = {
+ "adapt", "Remote AMD `Adapt' target",
+ "Remote debug an AMD 290*0 using an `Adapt' monitor via RS232",
+ adapt_open, adapt_close,
+ adapt_attach, adapt_detach, adapt_resume, adapt_wait,
+ adapt_fetch_register, adapt_store_register,
+ adapt_prepare_to_store,
+ adapt_xfer_inferior_memory,
+ adapt_files_info,
+ adapt_insert_breakpoint, adapt_remove_breakpoint, /* Breakpoints */
+ 0, 0, 0, 0, 0, /* Terminal handling */
+ adapt_kill, /* FIXME, kill */
+ adapt_load,
+ 0, /* lookup_symbol */
+ adapt_create_inferior, /* create_inferior */
+ adapt_mourn, /* mourn_inferior FIXME */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_stop */
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ 0,0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_adapt ()
+{
+ add_target (&adapt_ops);
+ add_com ("adapt <command>", class_obscure, adapt_com,
+ "Send a command to the AMD Adapt remote monitor.");
+}
diff --git a/contrib/gdb/gdb/remote-array.c b/contrib/gdb/gdb/remote-array.c
new file mode 100644
index 0000000..0ed84ca
--- /dev/null
+++ b/contrib/gdb/gdb/remote-array.c
@@ -0,0 +1,1465 @@
+/* Remote debugging interface for Array Tech RAID controller..
+ Copyright 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Rob Savoye for Cygnus.
+
+ This module talks to a debug monitor called 'MONITOR', which
+ We communicate with MONITOR via either a direct serial line, or a TCP
+ (or possibly TELNET) stream to a terminal multiplexor,
+ which in turn talks to the target board.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <signal.h>
+#include <sys/types.h>
+#include "gdb_string.h"
+#include "command.h"
+#include "serial.h"
+#include "monitor.h"
+#include "remote-utils.h"
+
+extern int baud_rate;
+
+#define ARRAY_PROMPT ">> "
+
+#define SWAP_TARGET_AND_HOST(buffer,len) \
+ do \
+ { \
+ if (TARGET_BYTE_ORDER != HOST_BYTE_ORDER) \
+ { \
+ char tmp; \
+ char *p = (char *)(buffer); \
+ char *q = ((char *)(buffer)) + len - 1; \
+ for (; p < q; p++, q--) \
+ { \
+ tmp = *q; \
+ *q = *p; \
+ *p = tmp; \
+ } \
+ } \
+ } \
+ while (0)
+
+static void debuglogs PARAMS((int, char *, ...));
+static void array_open();
+static void array_close();
+static void array_detach();
+static void array_attach();
+static void array_resume();
+static void array_fetch_register();
+static void array_store_register();
+static void array_fetch_registers();
+static void array_store_registers();
+static void array_prepare_to_store();
+static void array_files_info();
+static void array_kill();
+static void array_create_inferior();
+static void array_mourn_inferior();
+static void make_gdb_packet();
+static int array_xfer_memory();
+static int array_wait();
+static int array_insert_breakpoint();
+static int array_remove_breakpoint();
+static int tohex();
+static int to_hex();
+static int from_hex();
+static int array_send_packet();
+static int array_get_packet();
+static unsigned long ascii2hexword();
+static char *hexword2ascii();
+
+extern char *version;
+
+#define LOG_FILE "monitor.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 30;
+/* 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
+
+/*
+ * Descriptor for I/O to remote machine. Initialize it to NULL so that
+ * array_open knows that we don't have a file open when the program starts.
+ */
+serial_t array_desc = NULL;
+
+/*
+ * this array of registers need to match the indexes used by GDB. The
+ * whole reason this exists is cause the various ROM monitors use
+ * different strings than GDB does, and doesn't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+extern char *tmp_mips_processor_type;
+extern int mips_set_processor_type();
+
+static struct target_ops array_ops = {
+ "array", /* to_shortname */
+ /* to_longname */
+ "Debug using the standard GDB remote protocol for the Array Tech target.",
+ /* to_doc */
+ "Debug using the standard GDB remote protocol for the Array Tech target.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",
+ array_open, /* to_open */
+ array_close, /* to_close */
+ NULL, /* to_attach */
+ array_detach, /* to_detach */
+ array_resume, /* to_resume */
+ array_wait, /* to_wait */
+ array_fetch_registers, /* to_fetch_registers */
+ array_store_registers, /* to_store_registers */
+ array_prepare_to_store, /* to_prepare_to_store */
+ array_xfer_memory, /* to_xfer_memory */
+ array_files_info, /* to_files_info */
+ array_insert_breakpoint, /* to_insert_breakpoint */
+ array_remove_breakpoint, /* to_remove_breakpoint */
+ 0, /* to_terminal_init */
+ 0, /* to_terminal_inferior */
+ 0, /* to_terminal_ours_for_output */
+ 0, /* to_terminal_ours */
+ 0, /* to_terminal_info */
+ array_kill, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ array_create_inferior, /* to_create_inferior */
+ array_mourn_inferior, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+/*
+ * printf_monitor -- send data to monitor. Works just like printf.
+ */
+static void
+#ifdef ANSI_PROTOTYPES
+printf_monitor(char *pattern, ...)
+#else
+printf_monitor(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char buf[PBUFSIZ];
+ int i;
+
+#ifdef ANSI_PROTOTYPES
+ va_start(args, pattern);
+#else
+ char *pattern;
+ va_start(args);
+ pattern = va_arg(args, char *);
+#endif
+
+ vsprintf(buf, pattern, args);
+
+ debuglogs (1, "printf_monitor(), Sending: \"%s\".", buf);
+
+ if (strlen(buf) > PBUFSIZ)
+ error ("printf_monitor(): string too long");
+ if (SERIAL_WRITE(array_desc, buf, strlen(buf)))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+}
+/*
+ * write_monitor -- send raw data to monitor.
+ */
+static void
+write_monitor(data, len)
+ char data[];
+ int len;
+{
+ if (SERIAL_WRITE(array_desc, data, len))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+
+ *(data + len+1) = '\0';
+ debuglogs (1, "write_monitor(), Sending: \"%s\".", data);
+
+}
+
+/*
+ * debuglogs -- deal with debugging info to multiple sources. This takes
+ * two real args, the first one is the level to be compared against
+ * the sr_get_debug() value, the second arg is a printf buffer and args
+ * to be formatted and printed. A CR is added after each string is printed.
+ */
+static void
+#ifdef ANSI_PROTOTYPES
+debuglogs(int level, char *pattern, ...)
+#else
+debuglogs(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char *p;
+ unsigned char buf[PBUFSIZ];
+ char newbuf[PBUFSIZ];
+ int i;
+
+#ifdef ANSI_PROTOTYPES
+ va_start(args, pattern);
+#else
+ char *pattern;
+ int level;
+ va_start(args);
+ level = va_arg(args, int); /* get the debug level */
+ pattern = va_arg(args, char *); /* get the printf style pattern */
+#endif
+
+ if ((level <0) || (level > 100)) {
+ error ("Bad argument passed to debuglogs(), needs debug level");
+ return;
+ }
+
+ vsprintf(buf, pattern, args); /* format the string */
+
+ /* convert some characters so it'll look right in the log */
+ p = newbuf;
+ for (i = 0 ; buf[i] != '\0'; i++) {
+ if (i > PBUFSIZ)
+ error ("Debug message too long");
+ switch (buf[i]) {
+ case '\n': /* newlines */
+ *p++ = '\\';
+ *p++ = 'n';
+ continue;
+ case '\r': /* carriage returns */
+ *p++ = '\\';
+ *p++ = 'r';
+ continue;
+ case '\033': /* escape */
+ *p++ = '\\';
+ *p++ = 'e';
+ continue;
+ case '\t': /* tab */
+ *p++ = '\\';
+ *p++ = 't';
+ continue;
+ case '\b': /* backspace */
+ *p++ = '\\';
+ *p++ = 'b';
+ continue;
+ default: /* no change */
+ *p++ = buf[i];
+ }
+
+ if (buf[i] < 26) { /* modify control characters */
+ *p++ = '^';
+ *p++ = buf[i] + 'A';
+ continue;
+ }
+ if (buf[i] >= 128) { /* modify control characters */
+ *p++ = '!';
+ *p++ = buf[i] + 'A';
+ continue;
+ }
+ }
+ *p = '\0'; /* terminate the string */
+
+ if (sr_get_debug() > level)
+ printf_unfiltered ("%s\n", newbuf);
+
+#ifdef LOG_FILE /* write to the monitor log */
+ if (log_file != 0x0) {
+ fputs (newbuf, log_file);
+ fputc ('\n', log_file);
+ fflush (log_file);
+ }
+#endif
+}
+
+/* readchar -- read a character from the remote system, doing all the fancy
+ * timeout stuff.
+ */
+static int
+readchar(timeout)
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR(array_desc, abs(timeout));
+
+ if (sr_get_debug() > 5) {
+ putchar(c & 0x7f);
+ debuglogs (5, "readchar: timeout = %d\n", timeout);
+ }
+
+#ifdef LOG_FILE
+ if (isascii (c))
+ putc(c & 0x7f, log_file);
+#endif
+
+ if (c >= 0)
+ return c & 0x7f;
+
+ if (c == SERIAL_TIMEOUT) {
+ if (timeout <= 0)
+ return c; /* Polls shouldn't generate timeout errors */
+ error("Timeout reading from remote system.");
+#ifdef LOG_FILE
+ fputs ("ERROR: Timeout reading from remote system", log_file);
+#endif
+ }
+ perror_with_name("readchar");
+}
+
+/*
+ * expect -- scan input from the remote system, until STRING is found.
+ * If DISCARD is non-zero, then discard non-matching input, else print
+ * it out. Let the user break out immediately.
+ */
+static void
+expect (string, discard)
+ char *string;
+ int discard;
+{
+ char *p = string;
+ int c;
+
+
+ debuglogs (1, "Expecting \"%s\".", string);
+
+ immediate_quit = 1;
+ while (1) {
+ c = readchar(timeout);
+ if (!isascii (c))
+ continue;
+ if (c == *p++) {
+ if (*p == '\0') {
+ immediate_quit = 0;
+ debuglogs (4, "Matched");
+ return;
+ }
+ } else {
+ if (!discard) {
+ fputc_unfiltered (c, gdb_stdout);
+ }
+ p = string;
+ }
+ }
+}
+
+/* Keep discarding input until we see the MONITOR array_cmds->prompt.
+
+ The convention for dealing with the expect_prompt is that you
+ o give your command
+ o *then* wait for the expect_prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: array_resume does not
+ wait for the expect_prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a array_wait which does wait for the expect_prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt(discard)
+ int discard;
+{
+ expect (ARRAY_PROMPT, discard);
+}
+
+/*
+ * junk -- ignore junk characters. Returns a 1 if junk, 0 otherwise
+ */
+static int
+junk(ch)
+ char ch;
+{
+ switch (ch) {
+ case '\0':
+ case ' ':
+ case '-':
+ case '\t':
+ case '\r':
+ case '\n':
+ if (sr_get_debug() > 5)
+ debuglogs (5, "Ignoring \'%c\'.", ch);
+ return 1;
+ default:
+ if (sr_get_debug() > 5)
+ debuglogs (5, "Accepting \'%c\'.", ch);
+ return 0;
+ }
+}
+
+/*
+ * get_hex_digit -- Get a hex digit from the remote system & return its value.
+ * If ignore is nonzero, ignore spaces, newline & tabs.
+ */
+static int
+get_hex_digit(ignore)
+ int ignore;
+{
+ static int ch;
+ while (1) {
+ ch = readchar(timeout);
+ if (junk(ch))
+ continue;
+ if (sr_get_debug() > 4) {
+ debuglogs (4, "get_hex_digit() got a 0x%x(%c)", ch, ch);
+ } else {
+#ifdef LOG_FILE /* write to the monitor log */
+ if (log_file != 0x0) {
+ fputs ("get_hex_digit() got a 0x", log_file);
+ fputc (ch, log_file);
+ fputc ('\n', log_file);
+ fflush (log_file);
+ }
+#endif
+ }
+
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore)
+ ;
+ else {
+ expect_prompt(1);
+ debuglogs (4, "Invalid hex digit from remote system. (0x%x)", ch);
+ error("Invalid hex digit from remote system. (0x%x)", ch);
+ }
+ }
+}
+
+/* get_hex_byte -- Get a byte from monitor and put it in *BYT.
+ * Accept any number leading spaces.
+ */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ debuglogs (4, "get_hex_byte() -- Read first nibble 0x%x", val);
+
+ val |= get_hex_digit (0);
+ debuglogs (4, "get_hex_byte() -- Read second nibble 0x%x", val);
+ *byt = val;
+
+ debuglogs (4, "get_hex_byte() -- Read a 0x%x", val);
+}
+
+/*
+ * get_hex_word -- Get N 32-bit words from remote, each preceded by a space,
+ * and put them in registers starting at REGNO.
+ */
+static int
+get_hex_word ()
+{
+ long val, newval;
+ int i;
+
+ val = 0;
+
+#if 0
+ if (HOST_BYTE_ORDER == BIG_ENDIAN) {
+#endif
+ for (i = 0; i < 8; i++)
+ val = (val << 4) + get_hex_digit (i == 0);
+#if 0
+ } else {
+ for (i = 7; i >= 0; i--)
+ val = (val << 4) + get_hex_digit (i == 0);
+ }
+#endif
+
+ debuglogs (4, "get_hex_word() got a 0x%x for a %s host.", val, (HOST_BYTE_ORDER == BIG_ENDIAN) ? "big endian" : "little endian");
+
+ return val;
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+array_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error("Can't pass arguments to remote MONITOR process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/*
+ * array_open -- open a connection to a remote debugger.
+ * NAME is the filename used for communication.
+ */
+static int baudrate = 9600;
+static char dev_name[100];
+
+static void
+array_open(args, name, from_tty)
+ char *args;
+ char *name;
+ int from_tty;
+{
+ char packet[PBUFSIZ];
+
+ if (args == NULL)
+ error ("Use `target %s DEVICE-NAME' to use a serial port, or \n\
+`target %s HOST-NAME:PORT-NUMBER' to use a network connection.", name, name);
+
+/* if (is_open) */
+ array_close(0);
+
+ target_preopen (from_tty);
+ unpush_target (&array_ops);
+
+ tmp_mips_processor_type = "lsi33k"; /* change the default from r3051 */
+ mips_set_processor_type_command ("lsi33k", 0);
+
+ strcpy(dev_name, args);
+ array_desc = SERIAL_OPEN(dev_name);
+
+ if (array_desc == NULL)
+ perror_with_name(dev_name);
+
+ if (baud_rate != -1) {
+ if (SERIAL_SETBAUDRATE (array_desc, baud_rate)) {
+ SERIAL_CLOSE (array_desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW(array_desc);
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+ fprintf_filtered (log_file, "GDB %s (%s", version);
+ fprintf_filtered (log_file, " --target %s)\n", array_ops.to_shortname);
+ fprintf_filtered (log_file, "Remote target %s connected to %s\n\n", array_ops.to_shortname, dev_name);
+#endif
+
+ /* see if the target is alive. For a ROM monitor, we can just try to force the
+ expect_prompt to print a few times. For the GDB remote protocol, the application
+ being debugged is sitting at a breakpoint and waiting for GDB to initialize
+ the connection. We force it to give us an empty packet to see if it's alive.
+ */
+ debuglogs (3, "Trying to ACK the target's debug stub");
+ /* unless your are on the new hardware, the old board won't initialize
+ because the '@' doesn't flush output like it does on the new ROMS.
+ */
+ printf_monitor ("@"); /* ask for the last signal */
+ expect_prompt(1); /* See if we get a expect_prompt */
+#ifdef TEST_ARRAY /* skip packet for testing */
+ make_gdb_packet (packet, "?"); /* ask for a bogus packet */
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ printf_monitor ("@\n"); /* force it to flush stdout */
+ expect_prompt(1); /* See if we get a expect_prompt */
+#endif
+ push_target (&array_ops);
+ if (from_tty)
+ printf("Remote target %s connected to %s\n", array_ops.to_shortname, dev_name);
+}
+
+/*
+ * array_close -- Close out all files and local state before this
+ * target loses control.
+ */
+
+static void
+array_close (quitting)
+ int quitting;
+{
+ SERIAL_CLOSE(array_desc);
+ array_desc = NULL;
+
+ debuglogs (1, "array_close (quitting=%d)", quitting);
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror(log_file))
+ printf_filtered ("Error writing log file.\n");
+ if (fclose(log_file) != 0)
+ printf_filtered ("Error closing log file.\n");
+ }
+#endif
+}
+
+/*
+ * array_detach -- terminate the open connection to the remote
+ * debugger. Use this when you want to detach and do something
+ * else with your gdb.
+ */
+static void
+array_detach (from_tty)
+ int from_tty;
+{
+
+ debuglogs (1, "array_detach ()");
+
+ pop_target(); /* calls array_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/*
+ * array_attach -- attach GDB to the target.
+ */
+static void
+array_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (from_tty)
+ printf ("Starting remote %s debugging\n", target_shortname);
+
+ debuglogs (1, "array_attach (args=%s)", args);
+
+ printf_monitor ("go %x\n");
+ /* swallow the echo. */
+ expect ("go %x\n", 1);
+}
+
+/*
+ * array_resume -- Tell the remote machine to resume.
+ */
+static void
+array_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ debuglogs (1, "array_resume (step=%d, sig=%d)", step, sig);
+
+ if (step) {
+ printf_monitor ("s\n");
+ } else {
+ printf_monitor ("go\n");
+ }
+}
+
+#define TMPBUFSIZ 5
+
+/*
+ * array_wait -- Wait until the remote machine stops, then return,
+ * storing status in status just as `wait' would.
+ */
+static int
+array_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+ int result, i;
+ char c;
+ serial_t tty_desc;
+ serial_ttystate ttystate;
+
+ debuglogs(1, "array_wait (), printing extraneous text.");
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = 0; /* Don't time out -- user program is running. */
+
+#if !defined(__GO32__) && !defined(__MSDOS__) && !defined(__WIN32__)
+ tty_desc = SERIAL_FDOPEN (0);
+ ttystate = SERIAL_GET_TTY_STATE (tty_desc);
+ SERIAL_RAW (tty_desc);
+
+ i = 0;
+ /* poll on the serial port and the keyboard. */
+ while (1) {
+ c = readchar(timeout);
+ if (c > 0) {
+ if (c == *(ARRAY_PROMPT + i)) {
+ if (++i >= strlen (ARRAY_PROMPT)) { /* matched the prompt */
+ debuglogs (4, "array_wait(), got the expect_prompt.");
+ break;
+ }
+ } else { /* not the prompt */
+ i = 0;
+ }
+ fputc_unfiltered (c, gdb_stdout);
+ fflush (stdout);
+ }
+ c = SERIAL_READCHAR(tty_desc, timeout);
+ if (c > 0) {
+ SERIAL_WRITE(array_desc, &c, 1);
+ /* do this so it looks like there's keyboard echo */
+ if (c == 3) /* exit on Control-C */
+ break;
+#if 0
+ fputc_unfiltered (c, gdb_stdout);
+ fflush (stdout);
+#endif
+ }
+ }
+ SERIAL_SET_TTY_STATE (tty_desc, ttystate);
+#else
+ expect_prompt(1);
+ debuglogs (4, "array_wait(), got the expect_prompt.");
+#endif
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ timeout = old_timeout;
+
+ return 0;
+}
+
+/*
+ * array_fetch_registers -- read the remote registers into the
+ * block regs.
+ */
+static void
+array_fetch_registers (ignored)
+ int ignored;
+{
+ int regno, i;
+ char *p;
+ unsigned char packet[PBUFSIZ];
+ char regs[REGISTER_BYTES];
+
+ debuglogs (1, "array_fetch_registers (ignored=%d)\n", ignored);
+
+ memset (packet, 0, PBUFSIZ);
+ /* Unimplemented registers read as all bits zero. */
+ memset (regs, 0, REGISTER_BYTES);
+ make_gdb_packet (packet, "g");
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ if (array_get_packet (packet) == 0)
+ error ("Couldn't receive packet\n");
+ /* FIXME: read bytes from packet */
+ debuglogs (4, "array_fetch_registers: Got a \"%s\" back\n", packet);
+ for (regno = 0; regno <= PC_REGNUM+4; regno++) {
+ /* supply register stores in target byte order, so swap here */
+ /* FIXME: convert from ASCII hex to raw bytes */
+ i = ascii2hexword (packet + (regno * 8));
+ debuglogs (5, "Adding register %d = %x\n", regno, i);
+ SWAP_TARGET_AND_HOST (&i, 4);
+ supply_register (regno, (char *)&i);
+ }
+}
+
+/*
+ * This is unused by targets like this one that use a
+ * protocol based on GDB's remote protocol.
+ */
+static void
+array_fetch_register (ignored)
+ int ignored;
+{
+ array_fetch_registers ();
+}
+
+/*
+ * Get all the registers from the targets. They come back in a large array.
+ */
+static void
+array_store_registers (ignored)
+ int ignored;
+{
+ int regno;
+ unsigned long i;
+ char packet[PBUFSIZ];
+ char buf[PBUFSIZ];
+ char num[9];
+
+ debuglogs (1, "array_store_registers()");
+
+ memset (packet, 0, PBUFSIZ);
+ memset (buf, 0, PBUFSIZ);
+ buf[0] = 'G';
+
+ /* Unimplemented registers read as all bits zero. */
+ /* FIXME: read bytes from packet */
+ for (regno = 0; regno < 41; regno++) { /* FIXME */
+ /* supply register stores in target byte order, so swap here */
+ /* FIXME: convert from ASCII hex to raw bytes */
+ i = (unsigned long)read_register (regno);
+ hexword2ascii (num, i);
+ strcpy (buf+(regno * 8)+1, num);
+ }
+ *(buf + (regno * 8) + 2) = 0;
+ make_gdb_packet (packet, buf);
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ if (array_get_packet (packet) == 0)
+ error ("Couldn't receive packet\n");
+
+ registers_changed ();
+}
+
+/*
+ * This is unused by targets like this one that use a
+ * protocol based on GDB's remote protocol.
+ */
+static void
+array_store_register (ignored)
+ int ignored;
+{
+ array_store_registers ();
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+array_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+array_files_info ()
+{
+ printf ("\tAttached to %s at %d baud.\n",
+ dev_name, baudrate);
+}
+
+/*
+ * array_write_inferior_memory -- Copy LEN bytes of data from debugger
+ * memory at MYADDR to inferior's memory at MEMADDR. Returns length moved.
+ */
+static int
+array_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ unsigned long i;
+ int j;
+ char packet[PBUFSIZ];
+ char buf[PBUFSIZ];
+ char num[9];
+ char *p;
+
+ debuglogs (1, "array_write_inferior_memory (memaddr=0x%x, myaddr=0x%x, len=%d)", memaddr, myaddr, len);
+ memset (buf, '\0', PBUFSIZ); /* this also sets the string terminator */
+ p = buf;
+
+ *p++ = 'M'; /* The command to write memory */
+ hexword2ascii (num, memaddr); /* convert the address */
+ strcpy (p, num); /* copy the address */
+ p += 8;
+ *p++ = ','; /* add comma delimeter */
+ hexword2ascii (num, len); /* Get the length as a 4 digit number */
+ *p++ = num[4];
+ *p++ = num[5];
+ *p++ = num[6];
+ *p++ = num[7];
+ *p++ = ':'; /* add the colon delimeter */
+ for (j = 0; j < len; j++) { /* copy the data in after converting it */
+ *p++ = tohex ((myaddr[j] >> 4) & 0xf);
+ *p++ = tohex (myaddr[j] & 0xf);
+ }
+
+ make_gdb_packet (packet, buf);
+ if (array_send_packet (packet) == 0)
+ error ("Couldn't transmit packet\n");
+ if (array_get_packet (packet) == 0)
+ error ("Couldn't receive packet\n");
+
+ return len;
+}
+
+/*
+ * array_read_inferior_memory -- read LEN bytes from inferior memory
+ * at MEMADDR. Put the result at debugger address MYADDR. Returns
+ * length moved.
+ */
+static int
+array_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int j;
+ char buf[20];
+ char packet[PBUFSIZ];
+ int count; /* Number of bytes read so far. */
+ unsigned long startaddr; /* Starting address of this pass. */
+ int len_this_pass; /* Number of bytes to read in this pass. */
+
+ debuglogs (1, "array_read_inferior_memory (memaddr=0x%x, myaddr=0x%x, len=%d)", memaddr, myaddr, len);
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ array_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len To memaddr and gets 0. */
+ /* However, something like
+ array_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+
+ for (count = 0, startaddr = memaddr; count < len; startaddr += len_this_pass)
+ {
+ /* Try to align to 16 byte boundry (why?) */
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ {
+ len_this_pass -= startaddr % 16;
+ }
+ /* Only transfer bytes we need */
+ if (len_this_pass > (len - count))
+ {
+ len_this_pass = (len - count);
+ }
+ /* Fetch the bytes */
+ debuglogs (3, "read %d bytes from inferior address %x", len_this_pass,
+ startaddr);
+ sprintf (buf, "m%08x,%04x", startaddr, len_this_pass);
+ make_gdb_packet (packet, buf);
+ if (array_send_packet (packet) == 0)
+ {
+ error ("Couldn't transmit packet\n");
+ }
+ if (array_get_packet (packet) == 0)
+ {
+ error ("Couldn't receive packet\n");
+ }
+ if (*packet == 0)
+ {
+ error ("Got no data in the GDB packet\n");
+ }
+ /* Pick packet apart and xfer bytes to myaddr */
+ debuglogs (4, "array_read_inferior_memory: Got a \"%s\" back\n", packet);
+ for (j = 0; j < len_this_pass ; j++)
+ {
+ /* extract the byte values */
+ myaddr[count++] = from_hex (*(packet+(j*2))) * 16 + from_hex (*(packet+(j*2)+1));
+ debuglogs (5, "myaddr[%d] set to %x\n", count-1, myaddr[count-1]);
+ }
+ }
+ return (count);
+}
+
+/* FIXME-someday! merge these two. */
+static int
+array_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return array_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return array_read_inferior_memory (memaddr, myaddr, len);
+}
+
+static void
+array_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+array_mourn_inferior ()
+{
+ remove_breakpoints ();
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define MAX_ARRAY_BREAKPOINTS 16
+
+extern int memory_breakpoint_size;
+static CORE_ADDR breakaddr[MAX_ARRAY_BREAKPOINTS] = {0};
+
+/*
+ * array_insert_breakpoint -- add a breakpoint
+ */
+static int
+array_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ debuglogs (1, "array_insert_breakpoint() addr = 0x%x", addr);
+
+ for (i = 0; i <= MAX_ARRAY_BREAKPOINTS; i++) {
+ if (breakaddr[i] == 0) {
+ breakaddr[i] = addr;
+ if (sr_get_debug() > 4)
+ printf ("Breakpoint at %x\n", addr);
+ array_read_inferior_memory(addr, shadow, memory_breakpoint_size);
+ printf_monitor("b 0x%x\n", addr);
+ expect_prompt(1);
+ return 0;
+ }
+ }
+
+ fprintf(stderr, "Too many breakpoints (> 16) for monitor\n");
+ return 1;
+}
+
+/*
+ * _remove_breakpoint -- Tell the monitor to remove a breakpoint
+ */
+static int
+array_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ debuglogs (1, "array_remove_breakpoint() addr = 0x%x", addr);
+
+ for (i = 0; i < MAX_ARRAY_BREAKPOINTS; i++) {
+ if (breakaddr[i] == addr) {
+ breakaddr[i] = 0;
+ /* some monitors remove breakpoints based on the address */
+ printf_monitor("bd %x\n", i);
+ expect_prompt(1);
+ return 0;
+ }
+ }
+ fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+static void
+array_stop ()
+{
+ debuglogs (1, "array_stop()");
+ printf_monitor("\003");
+ expect_prompt(1);
+}
+
+/*
+ * array_command -- put a command string, in args, out to MONITOR.
+ * Output from MONITOR is placed on the users terminal until the
+ * expect_prompt is seen. FIXME
+ */
+static void
+monitor_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ debuglogs (1, "monitor_command (args=%s)", args);
+
+ if (array_desc == NULL)
+ error("monitor target not open.");
+
+ if (!args)
+ error("Missing command.");
+
+ printf_monitor ("%s\n", args);
+ expect_prompt(0);
+}
+
+/*
+ * make_gdb_packet -- make a GDB packet. The data is always ASCII.
+ * A debug packet whose contents are <data>
+ * is encapsulated for transmission in the form:
+ *
+ * $ <data> # CSUM1 CSUM2
+ *
+ * <data> must be ASCII alphanumeric and cannot include characters
+ * '$' or '#'. If <data> 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 <data>, the most significant nibble is sent first.
+ * the hex digits 0-9,a-f are used.
+ *
+ */
+static void
+make_gdb_packet (buf, data)
+ char *buf, *data;
+{
+ int i;
+ unsigned char csum = 0;
+ int cnt;
+ char *p;
+
+ debuglogs (3, "make_gdb_packet(%s)\n", data);
+ cnt = strlen (data);
+ if (cnt > PBUFSIZ)
+ error ("make_gdb_packet(): to much data\n");
+
+ /* start with the packet header */
+ p = buf;
+ *p++ = '$';
+
+ /* calculate the checksum */
+ for (i = 0; i < cnt; i++) {
+ csum += data[i];
+ *p++ = data[i];
+ }
+
+ /* terminate the data with a '#' */
+ *p++ = '#';
+
+ /* add the checksum as two ascii digits */
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+ *p = 0x0; /* Null terminator on string */
+}
+
+/*
+ * array_send_packet -- send a GDB packet to the target with error handling. We
+ * get a '+' (ACK) back if the packet is received and the checksum
+ * matches. Otherwise a '-' (NAK) is returned. It returns a 1 for a
+ * successful transmition, or a 0 for a failure.
+ */
+static int
+array_send_packet (packet)
+ char *packet;
+{
+ int c, retries, i;
+ char junk[PBUFSIZ];
+
+ retries = 0;
+
+#if 0
+ /* scan the packet to make sure it only contains valid characters.
+ this may sound silly, but sometimes a garbled packet will hang
+ the target board. We scan the whole thing, then print the error
+ message.
+ */
+ for (i = 0; i < strlen(packet); i++) {
+ debuglogs (5, "array_send_packet(): Scanning \'%c\'\n", packet[i]);
+ /* legit hex numbers or command */
+ if ((isxdigit(packet[i])) || (isalpha(packet[i])))
+ continue;
+ switch (packet[i]) {
+ case '+': /* ACK */
+ case '-': /* NAK */
+ case '#': /* end of packet */
+ case '$': /* start of packet */
+ continue;
+ default: /* bogus character */
+ retries++;
+ debuglogs (4, "array_send_packet(): Found a non-ascii digit \'%c\' in the packet.\n", packet[i]);
+ }
+ }
+#endif
+
+ if (retries > 0)
+ error ("Can't send packet, found %d non-ascii characters", retries);
+
+ /* ok, try to send the packet */
+ retries = 0;
+ while (retries++ <= 10) {
+ printf_monitor ("%s", packet);
+
+ /* read until either a timeout occurs (-2) or '+' is read */
+ while (retries <= 10) {
+ c = readchar (-timeout);
+ debuglogs (3, "Reading a GDB protocol packet... Got a '%c'\n", c);
+ switch (c) {
+ case '+':
+ debuglogs (3, "Got Ack\n");
+ return 1;
+ case SERIAL_TIMEOUT:
+ debuglogs (3, "Timed out reading serial port\n");
+ printf_monitor("@"); /* resync with the monitor */
+ expect_prompt(1); /* See if we get a expect_prompt */
+ break; /* Retransmit buffer */
+ case '-':
+ debuglogs (3, "Got NAK\n");
+ printf_monitor("@"); /* resync with the monitor */
+ expect_prompt(1); /* See if we get a expect_prompt */
+ break;
+ case '$':
+ /* it's probably an old response, or the echo of our command.
+ * just gobble up the packet and ignore it.
+ */
+ debuglogs (3, "Got a junk packet\n");
+ i = 0;
+ do {
+ c = readchar (timeout);
+ junk[i++] = c;
+ } while (c != '#');
+ c = readchar (timeout);
+ junk[i++] = c;
+ c = readchar (timeout);
+ junk[i++] = c;
+ junk[i++] = '\0';
+ debuglogs (3, "Reading a junk packet, got a \"%s\"\n", junk);
+ continue; /* Now, go look for next packet */
+ default:
+ continue;
+ }
+ retries++;
+ debuglogs (3, "Retransmitting packet \"%s\"\n", packet);
+ break; /* Here to retransmit */
+ }
+ } /* outer while */
+ return 0;
+}
+
+/*
+ * array_get_packet -- get a GDB packet from the target. Basically we read till we
+ * see a '#', then check the checksum. It returns a 1 if it's gotten a
+ * packet, or a 0 it the packet wasn't transmitted correctly.
+ */
+static int
+array_get_packet (packet)
+ char *packet;
+{
+ int c;
+ int retries;
+ unsigned char csum;
+ unsigned char pktcsum;
+ char *bp;
+
+ csum = 0;
+ bp = packet;
+
+ memset (packet, 1, PBUFSIZ);
+ retries = 0;
+ while (retries <= 10) {
+ do {
+ c = readchar (timeout);
+ if (c == SERIAL_TIMEOUT) {
+ debuglogs (3, "array_get_packet: got time out from serial port.\n");
+ }
+ debuglogs (3, "Waiting for a '$', got a %c\n", c);
+ } while (c != '$');
+
+ retries = 0;
+ while (retries <= 10) {
+ c = readchar (timeout);
+ debuglogs (3, "array_get_packet: got a '%c'\n", c);
+ switch (c) {
+ case SERIAL_TIMEOUT:
+ debuglogs (3, "Timeout in mid-packet, retrying\n");
+ return 0;
+ case '$':
+ debuglogs (3, "Saw new packet start in middle of old one\n");
+ return 0; /* Start a new packet, count retries */
+ case '#':
+ *bp = '\0';
+ pktcsum = from_hex (readchar (timeout)) << 4;
+ pktcsum |= from_hex (readchar (timeout));
+ if (csum == 0)
+ debuglogs (3, "\nGDB packet checksum zero, must be a bogus packet\n");
+ if (csum == pktcsum) {
+ debuglogs (3, "\nGDB packet checksum correct, packet data is \"%s\",\n", packet);
+ printf_monitor ("@");
+ expect_prompt (1);
+ return 1;
+ }
+ debuglogs (3, "Bad checksum, sentsum=0x%x, csum=0x%x\n", pktcsum, csum);
+ return 0;
+ case '*': /* Run length encoding */
+ debuglogs (5, "Run length encoding in packet\n");
+ csum += c;
+ c = readchar (timeout);
+ csum += c;
+ c = c - ' ' + 3; /* Compute repeat count */
+
+ if (c > 0 && c < 255 && bp + c - 1 < packet + PBUFSIZ - 1) {
+ memset (bp, *(bp - 1), c);
+ bp += c;
+ continue;
+ }
+ *bp = '\0';
+ printf_filtered ("Repeat count %d too large for buffer.\n", c);
+ return 0;
+
+ default:
+ if ((!isxdigit(c)) && (!ispunct(c)))
+ debuglogs (4, "Got a non-ascii digit \'%c\'.\\n", c);
+ if (bp < packet + PBUFSIZ - 1) {
+ *bp++ = c;
+ csum += c;
+ continue;
+ }
+
+ *bp = '\0';
+ puts_filtered ("Remote packet too long.\n");
+ return 0;
+ }
+ }
+ }
+}
+
+/*
+ * ascii2hexword -- convert an ascii number represented by 8 digits to a hex value.
+ */
+static unsigned long
+ascii2hexword (mem)
+ unsigned char *mem;
+{
+ unsigned long val;
+ int i;
+ char buf[9];
+
+ val = 0;
+ for (i = 0; i < 8; i++) {
+ val <<= 4;
+ if (mem[i] >= 'A' && mem[i] <= 'F')
+ val = val + mem[i] - 'A' + 10;
+ if (mem[i] >= 'a' && mem[i] <= 'f')
+ val = val + mem[i] - 'a' + 10;
+ if (mem[i] >= '0' && mem[i] <= '9')
+ val = val + mem[i] - '0';
+ buf[i] = mem[i];
+ }
+ buf[8] = '\0';
+ debuglogs (4, "ascii2hexword() got a 0x%x from %s(%x).\n", val, buf, mem);
+ return val;
+}
+
+/*
+ * ascii2hexword -- convert a hex value to an ascii number represented by 8
+ * digits.
+ */
+static char*
+hexword2ascii (mem, num)
+ unsigned char *mem;
+ unsigned long num;
+{
+ int i;
+ unsigned char ch;
+
+ debuglogs (4, "hexword2ascii() converting %x ", num);
+ for (i = 7; i >= 0; i--) {
+ mem[i] = tohex ((num >> 4) & 0xf);
+ mem[i] = tohex (num & 0xf);
+ num = num >> 4;
+ }
+ mem[8] = '\0';
+ debuglogs (4, "\tto a %s", mem);
+}
+
+/* Convert hex digit A to a number. */
+static int
+from_hex (a)
+ int a;
+{
+ if (a == 0)
+ return 0;
+
+ debuglogs (4, "from_hex got a 0x%x(%c)\n",a,a);
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+ else {
+ error ("Reply contains invalid hex digit 0x%x", a);
+ }
+}
+
+/* Convert number NIB to a hex digit. */
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0'+nib;
+ else
+ return 'a'+nib-10;
+}
+
+/*
+ * _initialize_remote_monitors -- setup a few addtitional commands that
+ * are usually only used by monitors.
+ */
+void
+_initialize_remote_monitors ()
+{
+ /* generic monitor command */
+ add_com ("monitor", class_obscure, monitor_command,
+ "Send a command to the debug monitor.");
+
+}
+
+/*
+ * _initialize_array -- do any special init stuff for the target.
+ */
+void
+_initialize_array ()
+{
+ add_target (&array_ops);
+}
diff --git a/contrib/gdb/gdb/remote-bug.c b/contrib/gdb/gdb/remote-bug.c
new file mode 100644
index 0000000..cd3b798
--- /dev/null
+++ b/contrib/gdb/gdb/remote-bug.c
@@ -0,0 +1,1053 @@
+/* Remote debugging interface for Motorola's MVME187BUG monitor, an embedded
+ monitor for the m88k.
+
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by K. Richard Pixley.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+
+#include "gdb_string.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+
+#include "terminal.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+
+#include "remote-utils.h"
+
+extern int sleep();
+
+/* External data declarations */
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+/* Forward data declarations */
+extern struct target_ops bug_ops; /* Forward declaration */
+
+/* Forward function declarations */
+static int bug_clear_breakpoints PARAMS((void));
+
+static int bug_read_memory PARAMS((CORE_ADDR memaddr,
+ unsigned char *myaddr,
+ int len));
+
+static int bug_write_memory PARAMS((CORE_ADDR memaddr,
+ unsigned char *myaddr,
+ int len));
+
+/* This variable is somewhat arbitrary. It's here so that it can be
+ set from within a running gdb. */
+
+static int srec_max_retries = 3;
+
+/* Each S-record download to the target consists of an S0 header
+ record, some number of S3 data records, and one S7 termination
+ record. I call this download a "frame". Srec_frame says how many
+ bytes will be represented in each frame. */
+
+#define SREC_SIZE 160
+static int srec_frame = SREC_SIZE;
+
+/* This variable determines how many bytes will be represented in each
+ S3 s-record. */
+
+static int srec_bytes = 40;
+
+/* At one point it appeared to me as though the bug monitor could not
+ really be expected to receive two sequential characters at 9600
+ baud reliably. Echo-pacing is an attempt to force data across the
+ line even in this condition. Specifically, in echo-pace mode, each
+ character is sent one at a time and we look for the echo before
+ sending the next. This is excruciatingly slow. */
+
+static int srec_echo_pace = 0;
+
+/* How long to wait after an srec for a possible error message.
+ Similar to the above, I tried sleeping after sending each S3 record
+ in hopes that I might actually see error messages from the bug
+ monitor. This might actually work if we were to use sleep
+ intervals smaller than 1 second. */
+
+static int srec_sleep = 0;
+
+/* Every srec_noise records, flub the checksum. This is a debugging
+ feature. Set the variable to something other than 1 in order to
+ inject *deliberate* checksum errors. One might do this if one
+ wanted to test error handling and recovery. */
+
+static int srec_noise = 0;
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to bug_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+/*
+ * Download a file specified in 'args', to the bug.
+ */
+
+static void
+bug_load (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ bfd *abfd;
+ asection *s;
+ char buffer[1024];
+
+ sr_check_open ();
+
+ dcache_flush (gr_get_dcache());
+ inferior_pid = 0;
+ abfd = bfd_openr (args, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", args);
+ return;
+ }
+
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+
+ s = abfd->sections;
+ while (s != (asection *) NULL)
+ {
+ srec_frame = SREC_SIZE;
+ if (s->flags & SEC_LOAD)
+ {
+ int i;
+
+ char *buffer = xmalloc (srec_frame);
+
+ 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; i += srec_frame)
+ {
+ if (srec_frame > s->_raw_size - i)
+ srec_frame = s->_raw_size - i;
+
+ bfd_get_section_contents (abfd, s, buffer, i, srec_frame);
+ bug_write_memory (s->vma + i, buffer, srec_frame);
+ printf_filtered ("*");
+ fflush (stdout);
+ }
+ printf_filtered ("\n");
+ free (buffer);
+ }
+ s = s->next;
+ }
+ sprintf (buffer, "rs ip %lx", (unsigned long) abfd->start_address);
+ sr_write_cr (buffer);
+ gr_expect_prompt ();
+}
+
+#if 0
+static char *
+get_word (p)
+ char **p;
+{
+ char *s = *p;
+ char *word;
+ char *copy;
+ size_t len;
+
+ while (isspace (*s))
+ s++;
+
+ word = s;
+
+ len = 0;
+
+ while (*s && !isspace (*s))
+ {
+ s++;
+ len++;
+
+ }
+ copy = xmalloc (len + 1);
+ memcpy (copy, word, len);
+ copy[len] = 0;
+ *p = s;
+ return copy;
+}
+#endif
+
+static struct gr_settings bug_settings = {
+ NULL, /* dcache */
+ "Bug>", /* prompt */
+ &bug_ops, /* ops */
+ bug_clear_breakpoints, /* clear_all_breakpoints */
+ bug_read_memory, /* readfunc */
+ bug_write_memory, /* writefunc */
+ gr_generic_checkin, /* checkin */
+};
+
+static char *cpu_check_strings[] = {
+ "=",
+ "Invalid Register",
+};
+
+static void
+bug_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args == NULL)
+ args = "";
+
+ gr_open(args, from_tty, &bug_settings);
+ /* decide *now* whether we are on an 88100 or an 88110 */
+ sr_write_cr("rs cr06");
+ sr_expect("rs cr06");
+
+ switch (gr_multi_scan(cpu_check_strings, 0))
+ {
+ case 0: /* this is an m88100 */
+ target_is_m88110 = 0;
+ break;
+ case 1: /* this is an m88110 */
+ target_is_m88110 = 1;
+ break;
+ default:
+ abort();
+ }
+}
+
+/* Tell the remote machine to resume. */
+
+void
+bug_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ dcache_flush (gr_get_dcache());
+
+ if (step)
+ {
+ sr_write_cr("t");
+
+ /* Force the next bug_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type
+ "continue" to see any. FIXME, this should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ sr_write_cr ("g");
+
+ return;
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static char *wait_strings[] = {
+ "At Breakpoint",
+ "Exception: Data Access Fault (Local Bus Timeout)",
+ "\r8???-Bug>",
+ "\r197-Bug>",
+ NULL,
+};
+
+int
+bug_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = sr_get_timeout();
+ int old_immediate_quit = immediate_quit;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ /* read off leftovers from resume so that the rest can be passed
+ back out as stdout. */
+ if (need_artificial_trap == 0)
+ {
+ sr_expect("Effective address: ");
+ (void) sr_get_hex_word();
+ sr_expect ("\r\n");
+ }
+
+ sr_set_timeout(-1); /* Don't time out -- user program is running. */
+ immediate_quit = 1; /* Helps ability to QUIT */
+
+ switch (gr_multi_scan(wait_strings, need_artificial_trap == 0))
+ {
+ case 0: /* breakpoint case */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ /* user output from the target can be discarded here. (?) */
+ gr_expect_prompt();
+ break;
+
+ case 1: /* bus error */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_BUS;
+ /* user output from the target can be discarded here. (?) */
+ gr_expect_prompt();
+ break;
+
+ case 2: /* normal case */
+ case 3:
+ if (need_artificial_trap != 0)
+ {
+ /* stepping */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ break;
+ }
+ else
+ {
+ /* exit case */
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ break;
+ }
+
+ case -1: /* trouble */
+ default:
+ fprintf_filtered (stderr,
+ "Trouble reading target during wait\n");
+ break;
+ }
+
+ sr_set_timeout(old_timeout);
+ immediate_quit = old_immediate_quit;
+ return 0;
+}
+
+/* Return the name of register number REGNO
+ in the form input and output by bug.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char *rn[] = {
+ "r00", "r01", "r02", "r03", "r04", "r05", "r06", "r07",
+ "r08", "r09", "r10", "r11", "r12", "r13", "r14", "r15",
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+
+ /* these get confusing because we omit a few and switch some ordering around. */
+
+ "cr01", /* 32 = psr */
+ "fcr62", /* 33 = fpsr*/
+ "fcr63", /* 34 = fpcr */
+ "ip", /* this is something of a cheat. */
+ /* 35 = sxip */
+ "cr05", /* 36 = snip */
+ "cr06", /* 37 = sfip */
+
+ "x00", "x01", "x02", "x03", "x04", "x05", "x06", "x07",
+ "x08", "x09", "x10", "x11", "x12", "x13", "x14", "x15",
+ "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
+ "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31",
+ };
+
+ return rn[regno];
+}
+
+#if 0 /* not currently used */
+/* Read from remote while the input matches STRING. Return zero on
+ success, -1 on failure. */
+
+static int
+bug_scan (s)
+ char *s;
+{
+ int c;
+
+ while (*s)
+ {
+ c = sr_readchar();
+ if (c != *s++)
+ {
+ fflush(stdout);
+ printf("\nNext character is '%c' - %d and s is \"%s\".\n", c, c, --s);
+ return(-1);
+ }
+ }
+
+ return(0);
+}
+#endif /* never */
+
+static int
+bug_srec_write_cr (s)
+ char *s;
+{
+ char *p = s;
+
+ if (srec_echo_pace)
+ for (p = s; *p; ++p)
+ {
+ if (sr_get_debug() > 0)
+ printf ("%c", *p);
+
+ do
+ SERIAL_WRITE(sr_get_desc(), p, 1);
+ while (sr_pollchar() != *p);
+ }
+ else
+ {
+ sr_write_cr (s);
+/* return(bug_scan (s) || bug_scan ("\n")); */
+ }
+
+ return(0);
+}
+
+/* Store register REGNO, or all if REGNO == -1. */
+
+static void
+bug_fetch_register(regno)
+ int regno;
+{
+ sr_check_open();
+
+ if (regno == -1)
+ {
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i)
+ bug_fetch_register(i);
+ }
+ else if (target_is_m88110 && regno == SFIP_REGNUM)
+ {
+ /* m88110 has no sfip. */
+ long l = 0;
+ supply_register(regno, (char *) &l);
+ }
+ else if (regno < XFP_REGNUM)
+ {
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ sr_write ("rs ", 3);
+ sr_write_cr (get_reg_name(regno));
+ sr_expect ("=");
+ store_unsigned_integer (buffer, REGISTER_RAW_SIZE (regno),
+ sr_get_hex_word());
+ gr_expect_prompt ();
+ supply_register (regno, buffer);
+ }
+ else
+ {
+ /* Float register so we need to parse a strange data format. */
+ long p;
+ unsigned char fpreg_buf[10];
+
+ sr_write("rs ", 3);
+ sr_write(get_reg_name(regno), strlen(get_reg_name(regno)));
+ sr_write_cr(";d");
+ sr_expect("rs");
+ sr_expect(get_reg_name(regno));
+ sr_expect(";d");
+ sr_expect("=");
+
+ /* sign */
+ p = sr_get_hex_digit(1);
+ fpreg_buf[0] = p << 7;
+
+ /* exponent */
+ sr_expect("_");
+ p = sr_get_hex_digit(1);
+ fpreg_buf[0] += (p << 4);
+ fpreg_buf[0] += sr_get_hex_digit(1);
+
+ fpreg_buf[1] = sr_get_hex_digit(1) << 4;
+
+ /* fraction */
+ sr_expect("_");
+ fpreg_buf[1] += sr_get_hex_digit(1);
+
+ fpreg_buf[2] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[3] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[4] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[5] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[6] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[7] = (sr_get_hex_digit(1) << 4) + sr_get_hex_digit(1);
+ fpreg_buf[8] = 0;
+ fpreg_buf[9] = 0;
+
+ gr_expect_prompt();
+ supply_register(regno, fpreg_buf);
+ }
+
+ return;
+}
+
+/* Store register REGNO, or all if REGNO == -1. */
+
+static void
+bug_store_register (regno)
+ int regno;
+{
+ char buffer[1024];
+ sr_check_open();
+
+ if (regno == -1)
+ {
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i)
+ bug_store_register(i);
+ }
+ else
+ {
+ char *regname;
+
+ regname = get_reg_name(regno);
+
+ if (target_is_m88110 && regno == SFIP_REGNUM)
+ return;
+ else if (regno < XFP_REGNUM)
+ sprintf(buffer, "rs %s %08x",
+ regname,
+ read_register(regno));
+ else
+ {
+ unsigned char *fpreg_buf =
+ (unsigned char *)&registers[REGISTER_BYTE(regno)];
+
+ sprintf(buffer, "rs %s %1x_%02x%1x_%1x%02x%02x%02x%02x%02x%02x;d",
+ regname,
+ /* sign */
+ (fpreg_buf[0] >> 7) & 0xf,
+ /* exponent */
+ fpreg_buf[0] & 0x7f,
+ (fpreg_buf[1] >> 8) & 0xf,
+ /* fraction */
+ fpreg_buf[1] & 0xf,
+ fpreg_buf[2],
+ fpreg_buf[3],
+ fpreg_buf[4],
+ fpreg_buf[5],
+ fpreg_buf[6],
+ fpreg_buf[7]);
+ }
+
+ sr_write_cr(buffer);
+ gr_expect_prompt();
+ }
+
+ return;
+}
+
+int
+bug_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ register int i;
+
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr;
+
+ /* Round ending address up; get number of longwords that makes. */
+ register int count;
+
+ /* Allocate buffer of that many longwords. */
+ register int *buffer;
+
+ addr = memaddr & -sizeof (int);
+ count = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+
+ buffer = (int *) alloca (count * sizeof (int));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int) sizeof (int))
+ {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = gr_fetch_word (addr);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = gr_fetch_word (addr + (count - 1) * sizeof (int));
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ gr_store_word (addr, buffer[i]);
+ if (errno)
+ {
+
+ return 0;
+ }
+
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ buffer[i] = gr_fetch_word (addr);
+ if (errno)
+ {
+ return 0;
+ }
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+ }
+
+ return len;
+}
+
+static void
+start_load()
+{
+ char *command;
+
+ command = (srec_echo_pace ? "lo 0 ;x" : "lo 0");
+
+ sr_write_cr (command);
+ sr_expect (command);
+ sr_expect ("\r\n");
+ bug_srec_write_cr ("S0030000FC");
+ return;
+}
+
+/* This is an extremely vulnerable and fragile function. I've made
+ considerable attempts to make this deterministic, but I've
+ certainly forgotten something. The trouble is that S-records are
+ only a partial file format, not a protocol. Worse, apparently the
+ m88k bug monitor does not run in real time while receiving
+ S-records. Hence, we must pay excruciating attention to when and
+ where error messages are returned, and what has actually been sent.
+
+ Each call represents a chunk of memory to be sent to the target.
+ We break that chunk into an S0 header record, some number of S3
+ data records each containing srec_bytes, and an S7 termination
+ record. */
+
+static char *srecord_strings[] = {
+ "S-RECORD",
+ "-Bug>",
+ NULL,
+};
+
+static int
+bug_write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int done;
+ int checksum;
+ int x;
+ int retries;
+ char *buffer = alloca ((srec_bytes + 8) << 1);
+
+ retries = 0;
+
+ do
+ {
+ done = 0;
+
+ if (retries > srec_max_retries)
+ return(-1);
+
+ if (retries > 0)
+ {
+ if (sr_get_debug() > 0)
+ printf("\n<retrying...>\n");
+
+ /* This gr_expect_prompt call is extremely important. Without
+ it, we will tend to resend our packet so fast that it
+ will arrive before the bug monitor is ready to receive
+ it. This would lead to a very ugly resend loop. */
+
+ gr_expect_prompt();
+ }
+
+ start_load();
+
+ while (done < len)
+ {
+ int thisgo;
+ int idx;
+ char *buf = buffer;
+ CORE_ADDR address;
+
+ checksum = 0;
+ thisgo = len - done;
+ if (thisgo > srec_bytes)
+ thisgo = srec_bytes;
+
+ address = memaddr + done;
+ sprintf (buf, "S3%02X%08X", thisgo + 4 + 1, address);
+ buf += 12;
+
+ checksum += (thisgo + 4 + 1
+ + (address & 0xff)
+ + ((address >> 8) & 0xff)
+ + ((address >> 16) & 0xff)
+ + ((address >> 24) & 0xff));
+
+ for (idx = 0; idx < thisgo; idx++)
+ {
+ sprintf (buf, "%02X", myaddr[idx + done]);
+ checksum += myaddr[idx + done];
+ buf += 2;
+ }
+
+ if (srec_noise > 0)
+ {
+ /* FIXME-NOW: insert a deliberate error every now and then.
+ This is intended for testing/debugging the error handling
+ stuff. */
+ static int counter = 0;
+ if (++counter > srec_noise)
+ {
+ counter = 0;
+ ++checksum;
+ }
+ }
+
+ sprintf(buf, "%02X", ~checksum & 0xff);
+ bug_srec_write_cr (buffer);
+
+ if (srec_sleep != 0)
+ sleep(srec_sleep);
+
+ /* This pollchar is probably redundant to the gr_multi_scan
+ below. Trouble is, we can't be sure when or where an
+ error message will appear. Apparently, when running at
+ full speed from a typical sun4, error messages tend to
+ appear to arrive only *after* the s7 record. */
+
+ if ((x = sr_pollchar()) != 0)
+ {
+ if (sr_get_debug() > 0)
+ printf("\n<retrying...>\n");
+
+ ++retries;
+
+ /* flush any remaining input and verify that we are back
+ at the prompt level. */
+ gr_expect_prompt();
+ /* start all over again. */
+ start_load();
+ done = 0;
+ continue;
+ }
+
+ done += thisgo;
+ }
+
+ bug_srec_write_cr("S7060000000000F9");
+ ++retries;
+
+ /* Having finished the load, we need to figure out whether we
+ had any errors. */
+ } while (gr_multi_scan(srecord_strings, 0) == 0);;
+
+ return(0);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns errno value.
+ * sb/sh instructions don't work on unaligned addresses, when TU=1.
+ */
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns errno value. */
+static int
+bug_read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ char request[100];
+ char *buffer;
+ char *p;
+ char type;
+ char size;
+ unsigned char c;
+ unsigned int inaddr;
+ unsigned int checksum;
+
+ sprintf(request, "du 0 %x:&%d", memaddr, len);
+ sr_write_cr(request);
+
+ p = buffer = alloca(len);
+
+ /* scan up through the header */
+ sr_expect("S0030000FC");
+
+ while (p < buffer + len)
+ {
+ /* scan off any white space. */
+ while (sr_readchar() != 'S') ;;
+
+ /* what kind of s-rec? */
+ type = sr_readchar();
+
+ /* scan record size */
+ sr_get_hex_byte(&size);
+ checksum = size;
+ --size;
+ inaddr = 0;
+
+ switch (type)
+ {
+ case '7':
+ case '8':
+ case '9':
+ goto done;
+
+ case '3':
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ /* intentional fall through */
+ case '2':
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ /* intentional fall through */
+ case '1':
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ sr_get_hex_byte(&c);
+ inaddr = (inaddr << 8) + c;
+ checksum += c;
+ --size;
+ break;
+
+ default:
+ /* bonk */
+ error("reading s-records.");
+ }
+
+ if (inaddr < memaddr
+ || (memaddr + len) < (inaddr + size))
+ error("srec out of memory range.");
+
+ if (p != buffer + inaddr - memaddr)
+ error("srec out of sequence.");
+
+ for (; size; --size, ++p)
+ {
+ sr_get_hex_byte(p);
+ checksum += *p;
+ }
+
+ sr_get_hex_byte(&c);
+ if (c != (~checksum & 0xff))
+ error("bad s-rec checksum");
+ }
+
+ done:
+ gr_expect_prompt();
+ if (p != buffer + len)
+ return(1);
+
+ memcpy(myaddr, buffer, len);
+ return(0);
+}
+
+#define MAX_BREAKS 16
+static int num_brkpts = 0;
+static int
+bug_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let bug save instructions */
+{
+ sr_check_open ();
+
+ if (num_brkpts < MAX_BREAKS)
+ {
+ char buffer[100];
+
+ num_brkpts++;
+ sprintf (buffer, "br %x", addr);
+ sr_write_cr (buffer);
+ gr_expect_prompt ();
+ return(0);
+ }
+ else
+ {
+ fprintf_filtered (stderr,
+ "Too many break points, break point not installed\n");
+ return(1);
+ }
+
+}
+static int
+bug_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let bug save instructions */
+{
+ if (num_brkpts > 0)
+ {
+ char buffer[100];
+
+ num_brkpts--;
+ sprintf (buffer, "nobr %x", addr);
+ sr_write_cr (buffer);
+ gr_expect_prompt ();
+
+ }
+ return (0);
+}
+
+/* Clear the bugs notion of what the break points are */
+static int
+bug_clear_breakpoints ()
+{
+
+ if (sr_is_open())
+ {
+ sr_write_cr ("nobr");
+ sr_expect("nobr");
+ gr_expect_prompt ();
+ }
+ num_brkpts = 0;
+ return(0);
+}
+
+struct target_ops bug_ops =
+{
+ "bug", "Remote BUG monitor",
+ "Use the mvme187 board running the BUG monitor connected by a serial line.",
+
+ bug_open, gr_close,
+ 0, gr_detach, bug_resume, bug_wait, /* attach */
+ bug_fetch_register, bug_store_register,
+ gr_prepare_to_store,
+ bug_xfer_memory,
+ gr_files_info,
+ bug_insert_breakpoint, bug_remove_breakpoint, /* Breakpoints */
+ 0, 0, 0, 0, 0, /* Terminal handling */
+ gr_kill, /* FIXME, kill */
+ bug_load,
+ 0, /* lookup_symbol */
+ gr_create_inferior, /* create_inferior */
+ gr_mourn, /* mourn_inferior FIXME */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_bug ()
+{
+ add_target (&bug_ops);
+
+ add_show_from_set
+ (add_set_cmd ("srec-bytes", class_support, var_uinteger,
+ (char *) &srec_bytes,
+ "\
+Set the number of bytes represented in each S-record.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("srec-max-retries", class_support, var_uinteger,
+ (char *) &srec_max_retries,
+ "\
+Set the number of retries for shipping S-records.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+
+#if 0
+ /* This needs to set SREC_SIZE, not srec_frame which gets changed at the
+ end of a download. But do we need the option at all? */
+ add_show_from_set
+ (add_set_cmd ("srec-frame", class_support, var_uinteger,
+ (char *) &srec_frame,
+ "\
+Set the number of bytes in an S-record frame.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+#endif /* 0 */
+
+ add_show_from_set
+ (add_set_cmd ("srec-noise", class_support, var_zinteger,
+ (char *) &srec_noise,
+ "\
+Set number of S-record to send before deliberately flubbing a checksum.\n\
+Zero means flub none at all. This affects the communication protocol\n\
+with the remote target.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("srec-sleep", class_support, var_zinteger,
+ (char *) &srec_sleep,
+ "\
+Set number of seconds to sleep after an S-record for a possible error message to arrive.\n\
+This affects the communication protocol with the remote target.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("srec-echo-pace", class_support, var_boolean,
+ (char *) &srec_echo_pace,
+ "\
+Set echo-verification.\n\
+When on, use verification by echo when downloading S-records. This is\n\
+much slower, but generally more reliable.",
+ &setlist),
+ &showlist);
+}
diff --git a/contrib/gdb/gdb/remote-e7000.c b/contrib/gdb/gdb/remote-e7000.c
new file mode 100644
index 0000000..d188913
--- /dev/null
+++ b/contrib/gdb/gdb/remote-e7000.c
@@ -0,0 +1,2066 @@
+/* Remote debugging interface for Hitachi E7000 ICE, for GDB
+ Copyright 1993, 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ Written by Steve Chamberlain for Cygnus Support.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The E7000 is an in-circuit emulator for the Hitachi H8/300-H and
+ Hitachi-SH processor. It has serial port and a lan port.
+
+ The monitor command set makes it difficult to load large ammounts of
+ data over the lan without using ftp - so try not to issue load
+ commands when communicating over ethernet; use the ftpload command.
+
+ The monitor pauses for a second when dumping srecords to the serial
+ line too, so we use a slower per byte mechanism but without the
+ startup overhead. Even so, it's pretty slow... */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "value.h"
+#include "command.h"
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+#include "serial.h"
+#include "remote-utils.h"
+#include "symfile.h"
+#include <sys/time.h>
+
+#if 0
+#define HARD_BREAKPOINTS
+#define BC_BREAKPOINTS 0
+#endif
+
+#define CTRLC 0x03
+#define ENQ 0x05
+#define ACK 0x06
+#define CTRLZ 0x1a
+
+extern void notice_quit PARAMS ((void));
+
+/* Local function declarations. */
+
+static void e7000_close PARAMS ((int));
+
+static void e7000_fetch_register PARAMS ((int));
+
+static void e7000_store_register PARAMS ((int));
+
+static void e7000_command PARAMS ((char *, int));
+
+static void e7000_login_command PARAMS ((char *, int));
+
+static void e7000_ftp_command PARAMS ((char *, int));
+
+static void e7000_drain_command PARAMS ((char *, int));
+
+static void expect PARAMS ((char *));
+
+static void expect_full_prompt PARAMS ((void));
+
+static void expect_prompt PARAMS ((void));
+
+/* Variables. */
+
+static serial_t e7000_desc;
+
+/* Nonzero if using the tcp serial driver. */
+
+static int using_tcp;
+
+/* Nonzero if using the pc isa card. */
+
+static int using_pc;
+
+extern struct target_ops e7000_ops; /* Forward declaration */
+
+char *ENQSTRING = "\005";
+
+/* Nonzero if some routine (as opposed to the user) wants echoing.
+ FIXME: Do this reentrantly with an extra parameter. */
+
+static int echo;
+
+static int ctrl_c;
+
+static int timeout = 5;
+
+/* Send data to e7000debug. */
+
+static void
+puts_e7000debug (buf)
+ char *buf;
+{
+ if (!e7000_desc)
+ error ("Use \"target e7000 ...\" first.");
+
+ if (remote_debug)
+ printf("Sending %s\n", buf);
+
+ if (SERIAL_WRITE (e7000_desc, buf, strlen (buf)))
+ fprintf (stderr, "SERIAL_WRITE failed: %s\n", safe_strerror (errno));
+
+ /* And expect to see it echoed, unless using the pc interface */
+#if 0
+ if (!using_pc)
+#endif
+ expect (buf);
+}
+
+static void
+putchar_e7000 (x)
+ int x;
+{
+ char b[1];
+
+ b[0] = x;
+ SERIAL_WRITE (e7000_desc, b, 1);
+}
+
+static void
+write_e7000 (s)
+ char *s;
+{
+ SERIAL_WRITE (e7000_desc, s, strlen (s));
+}
+
+static int
+normal (x)
+ int x;
+{
+ if (x == '\n')
+ return '\r';
+ return x;
+}
+
+/* Read a character from the remote system, doing all the fancy timeout
+ stuff. */
+
+static int
+readchar (timeout)
+ int timeout;
+{
+ int c;
+
+ do
+ {
+ c = SERIAL_READCHAR (e7000_desc, timeout);
+ }
+ while (c > 127);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return -1;
+ echo = 0;
+ error ("Timeout reading from remote system.");
+ }
+ if (remote_debug)
+ {
+ putchar (c);
+ fflush (stdout);
+ }
+
+ return normal (c);
+}
+
+#if 0
+char *
+tl (x)
+{
+ static char b[8][10];
+ static int p;
+
+ p++;
+ p &= 7;
+ if (x >= ' ')
+ {
+ b[p][0] = x;
+ b[p][1] = 0;
+ }
+ else
+ {
+ sprintf(b[p], "<%d>", x);
+ }
+
+ return b[p];
+}
+#endif
+
+/* Scan input from the remote system, until STRING is found. If
+ DISCARD is non-zero, then discard non-matching input, else print it
+ out. Let the user break out immediately. */
+
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+ int c;
+ int nl = 0;
+
+ while (1)
+ {
+ c = readchar (timeout);
+ notice_quit ();
+ if (quit_flag == 1)
+ {
+ if (ctrl_c)
+ {
+ putchar_e7000(CTRLC);
+ --ctrl_c;
+ }
+ else
+ {
+ quit ();
+ }
+ }
+
+ if (c == SERIAL_ERROR)
+ {
+ error ("Serial communication error");
+ }
+ if (echo || remote_debug)
+ {
+ if (c == '\r' || c == '\n')
+ {
+ if (!nl)
+ putchar ('\n');
+ nl = 1;
+ }
+ else
+ {
+ nl = 0;
+ putchar (c);
+ }
+ fflush (stdout);
+ }
+ if (normal (c) == normal (*p++))
+ {
+ if (*p == '\0')
+ return;
+ }
+ else
+ {
+ p = string;
+
+ if (normal (c) == normal (string[0]))
+ p++;
+ }
+ }
+}
+
+/* Keep discarding input until we see the e7000 prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line will
+ be an expect_prompt(). Exception: e7000_resume does not wait for
+ the prompt, because the terminal is being handed over to the
+ inferior. However, the next thing which happens after that is a
+ e7000_wait which does wait for the prompt. Note that this includes
+ abnormal exit, e.g. error(). This is necessary to prevent getting
+ into states from which we can't recover. */
+
+static void
+expect_prompt ()
+{
+ expect (":");
+}
+
+static void
+expect_full_prompt ()
+{
+ expect ("\r:");
+}
+
+static int
+convert_hex_digit (ch)
+ int ch;
+{
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ return -1;
+}
+
+static int
+get_hex (start)
+ int *start;
+{
+ int value = convert_hex_digit (*start);
+ int try;
+
+ *start = readchar (timeout);
+ while ((try = convert_hex_digit (*start)) >= 0)
+ {
+ value <<= 4;
+ value += try;
+ *start = readchar (timeout);
+ }
+ return value;
+}
+
+#if 0
+/* Get N 32-bit words from remote, each preceded by a space, and put
+ them in registers starting at REGNO. */
+
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ supply_register (regno++, (char *) &val);
+ }
+}
+#endif
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+
+static void
+e7000_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote E7000DEBUG process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+#ifdef CREATE_INFERIOR_HOOK
+ CREATE_INFERIOR_HOOK (0); /* No process-ID */
+#endif
+
+ /* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed ((CORE_ADDR) entry_pt, -1, 0); /* Let 'er rip... */
+}
+
+/* Open a connection to a remote debugger. NAME is the filename used
+ for communication. */
+
+static int baudrate = 9600;
+static char dev_name[100];
+
+static char *machine = "";
+static char *user = "";
+static char *passwd = "";
+static char *dir = "";
+
+/* Grab the next token and buy some space for it */
+
+static char *
+next (ptr)
+ char **ptr;
+{
+ char *p = *ptr;
+ char *s;
+ char *r;
+ int l = 0;
+
+ while (*p && *p == ' ')
+ p++;
+ s = p;
+ while (*p && (*p != ' ' && *p != '\t'))
+ {
+ l++;
+ p++;
+ }
+ r = xmalloc (l + 1);
+ memcpy (r, s, l);
+ r[l] = 0;
+ *ptr = p;
+ return r;
+}
+
+static void
+e7000_login_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ {
+ machine = next (&args);
+ user = next (&args);
+ passwd = next (&args);
+ dir = next (&args);
+ if (from_tty)
+ {
+ printf ("Set info to %s %s %s %s\n", machine, user, passwd, dir);
+ }
+ }
+ else
+ {
+ error ("Syntax is ftplogin <machine> <user> <passwd> <directory>");
+ }
+}
+
+/* Start an ftp transfer from the E7000 to a host */
+
+static void
+e7000_ftp_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ /* FIXME: arbitrary limit on machine names and such. */
+ char buf[200];
+
+ int oldtimeout = timeout;
+ timeout = 10;
+
+ sprintf (buf, "ftp %s\r", machine);
+ puts_e7000debug (buf);
+ expect (" Username : ");
+ sprintf (buf, "%s\r", user);
+ puts_e7000debug (buf);
+ expect (" Password : ");
+ write_e7000 (passwd);
+ write_e7000 ("\r");
+ expect ("success\r");
+ expect ("FTP>");
+ sprintf (buf, "cd %s\r", dir);
+ puts_e7000debug (buf);
+ expect ("FTP>");
+ sprintf (buf, "ll 0;s:%s\r", args);
+ puts_e7000debug (buf);
+ expect ("FTP>");
+ puts_e7000debug ("bye\r");
+ expect (":");
+ timeout = oldtimeout;
+}
+
+static void
+e7000_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int n;
+ int loop;
+ char junk[100];
+ int sync;
+ target_preopen (from_tty);
+
+ n = 0;
+ if (args && strcasecmp (args, "pc") == 0)
+ {
+ strcpy (dev_name, args);
+ }
+ else
+ {
+ if (args)
+ {
+ n = sscanf (args, " %s %d %s", dev_name, &baudrate, junk);
+ }
+
+ if (n != 1 && n != 2)
+ {
+ error ("Bad arguments. Usage:\ttarget e7000 <device> <speed>\n\
+or \t\ttarget e7000 <host>[:<port>]\n\
+or \t\ttarget e7000 pc\n");
+ }
+
+#ifndef __GO32__
+ if (n == 1 && strchr (dev_name, ':') == 0)
+ {
+ /* Default to normal telnet port */
+ strcat (dev_name, ":23");
+ }
+#endif
+ }
+
+ push_target (&e7000_ops);
+
+ e7000_desc = SERIAL_OPEN (dev_name);
+
+ if (!e7000_desc)
+ perror_with_name (dev_name);
+
+ using_tcp = strcmp (e7000_desc->ops->name, "tcp") == 0;
+ using_pc = strcmp (e7000_desc->ops->name, "pc") == 0;
+
+ SERIAL_SETBAUDRATE (e7000_desc, baudrate);
+ SERIAL_RAW (e7000_desc);
+
+ /* Hello? Are you there? */
+ sync = 0;
+ loop = 0;
+ putchar_e7000 (CTRLC);
+ while (!sync)
+ {
+ int c;
+
+ if (from_tty)
+ printf_unfiltered ("[waiting for e7000...]\n");
+
+ write_e7000 ("\r");
+ c = SERIAL_READCHAR (e7000_desc, 1);
+ while (c != SERIAL_TIMEOUT)
+ {
+ /* Dont echo cr's */
+ if (from_tty && c != '\r')
+ {
+ putchar (c);
+ fflush (stdout);
+ }
+ if (c == ':')
+ sync = 1;
+
+ if (loop++ == 20)
+ {
+ putchar_e7000 (CTRLC);
+ loop = 0;
+ }
+
+ QUIT ;
+
+
+ if (quit_flag)
+ {
+ putchar_e7000 (CTRLC);
+ quit_flag = 0;
+ }
+ c = SERIAL_READCHAR (e7000_desc, 1);
+ }
+ }
+ puts_e7000debug ("\r");
+
+ expect_prompt ();
+
+ puts_e7000debug ("b -\r");
+
+ expect_prompt ();
+
+ if (from_tty)
+ printf_filtered ("Remote target %s connected to %s\n", target_shortname,
+ dev_name);
+
+#ifdef GDB_TARGET_IS_H8300
+ h8300hmode = 1;
+#endif
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+e7000_close (quitting)
+ int quitting;
+{
+ if (e7000_desc)
+ {
+ SERIAL_CLOSE (e7000_desc);
+ e7000_desc = 0;
+ }
+}
+
+/* Terminate the open connection to the remote debugger. Use this
+ when you want to detach and do something else with your gdb. */
+
+static void
+e7000_detach (from_tty)
+ int from_tty;
+{
+ pop_target (); /* calls e7000_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+e7000_resume (pid, step, sig)
+ int pid, step, sig;
+{
+ if (step)
+ puts_e7000debug ("S\r");
+ else
+ puts_e7000debug ("G\r");
+}
+
+/* Read the remote registers into the block REGS.
+
+ For the H8/300 a register dump looks like:
+
+ PC=00021A CCR=80:I*******
+ ER0 - ER3 0000000A 0000002E 0000002E 00000000
+ ER4 - ER7 00000000 00000000 00000000 00FFEFF6
+ 000218 MOV.B R1L,R2L
+ STEP NORMAL END or
+ BREAK POINT
+ */
+
+#ifdef GDB_TARGET_IS_H8300
+
+char *want = "PC=%p CCR=%c\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7\n";
+
+char *want_nopc = "%p CCR=%c\n\
+ ER0 - ER3 %0 %1 %2 %3\n\
+ ER4 - ER7 %4 %5 %6 %7";
+
+#endif
+
+#ifdef GDB_TARGET_IS_SH
+
+char *want = "PC=%16 SR=%22\n\
+PR=%17 GBR=%18 VBR=%19\n\
+MACH=%20 MACL=%21\n\
+R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+R8-15 %8 %9 %10 %11 %12 %13 %14 %15\n";
+
+char *want_nopc = "%16 SR=%22\n\
+ PR=%17 GBR=%18 VBR=%19\n\
+ MACH=%20 MACL=%21\n\
+ R0-7 %0 %1 %2 %3 %4 %5 %6 %7\n\
+ R8-15 %8 %9 %10 %11 %12 %13 %14 %15";
+
+#endif
+
+static int
+gch ()
+{
+ int c = readchar (timeout);
+
+ if (remote_debug)
+ {
+ if (c >= ' ')
+ printf ("%c", c);
+ else if (c == '\n')
+ printf ("\n");
+ }
+ return c;
+}
+
+static unsigned int
+gbyte ()
+{
+ int high = convert_hex_digit (gch ());
+ int low = convert_hex_digit (gch ());
+
+ return (high << 4) + low;
+}
+
+void
+fetch_regs_from_dump (nextchar, want)
+ int (*nextchar)();
+ char *want;
+{
+ int regno;
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ int thischar = nextchar ();
+
+ while (*want)
+ {
+ switch (*want)
+ {
+ case '\n':
+ /* Skip to end of line and then eat all new line type stuff */
+ while (thischar != '\n' && thischar != '\r')
+ thischar = nextchar ();
+ while (thischar == '\n' || thischar == '\r')
+ thischar = nextchar ();
+ want++;
+ break;
+
+ case ' ':
+ while (thischar == ' '
+ || thischar == '\t'
+ || thischar == '\r'
+ || thischar == '\n')
+ thischar = nextchar ();
+ want++;
+ break;
+
+ default:
+ if (*want == thischar)
+ {
+ want++;
+ if (*want)
+ thischar = nextchar ();
+
+ }
+ else if (thischar == ' ' || thischar == '\n' || thischar == '\r')
+ {
+ thischar = nextchar ();
+ }
+ else {
+ error ("out of sync in fetch registers wanted <%s>, got <%c 0x%x>",
+ want, thischar, thischar);
+ }
+
+ break;
+ case '%':
+ /* Got a register command */
+ want++;
+ switch (*want)
+ {
+#ifdef PC_REGNUM
+ case 'p':
+ regno = PC_REGNUM;
+ want++;
+ break;
+#endif
+#ifdef CCR_REGNUM
+ case 'c':
+ regno = CCR_REGNUM;
+ want++;
+ break;
+#endif
+#ifdef SP_REGNUM
+ case 's':
+ regno = SP_REGNUM;
+ want++;
+ break;
+#endif
+#ifdef FP_REGNUM
+ case 'f':
+ regno = FP_REGNUM;
+ want++;
+ break;
+#endif
+
+ default:
+ if (isdigit (want[0]))
+ {
+ if (isdigit (want[1]))
+ {
+ regno = (want[0] - '0') * 10 + want[1] - '0';
+ want += 2;
+ }
+ else
+ {
+ regno = want[0] - '0';
+ want++;
+ }
+ }
+
+ else
+ abort ();
+ }
+ store_signed_integer (buf,
+ REGISTER_RAW_SIZE(regno),
+ (LONGEST) get_hex (&thischar, nextchar));
+ supply_register (regno, buf);
+ break;
+ }
+ }
+}
+
+static void
+e7000_fetch_registers ()
+{
+ int regno;
+
+ puts_e7000debug ("R\r");
+ fetch_regs_from_dump (gch, want);
+
+ /* And supply the extra ones the simulator uses */
+ for (regno = NUM_REALREGS; regno < NUM_REGS; regno++)
+ {
+ int buf = 0;
+
+ supply_register (regno, (char *) (&buf));
+ }
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1. Returns
+ errno value. */
+
+static void
+e7000_fetch_register (regno)
+ int regno;
+{
+ e7000_fetch_registers ();
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+e7000_store_registers ()
+{
+ int regno;
+
+ for (regno = 0; regno < NUM_REALREGS; regno++)
+ e7000_store_register (regno);
+
+ registers_changed ();
+}
+
+/* Store register REGNO, or all if REGNO == 0. Return errno value. */
+
+static void
+e7000_store_register (regno)
+ int regno;
+{
+ char buf[200];
+
+ if (regno == -1)
+ {
+ e7000_store_registers ();
+ return;
+ }
+
+#ifdef GDB_TARGET_IS_H8300
+ if (regno <= 7)
+ {
+ sprintf (buf, ".ER%d %x\r", regno, read_register (regno));
+ puts_e7000debug (buf);
+ }
+ else if (regno == PC_REGNUM)
+ {
+ sprintf (buf, ".PC %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
+ else if (regno == CCR_REGNUM)
+ {
+ sprintf (buf, ".CCR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ }
+#endif /* GDB_TARGET_IS_H8300 */
+
+#ifdef GDB_TARGET_IS_SH
+ switch (regno)
+ {
+ default:
+ sprintf (buf, ".R%d %x\r", regno, read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case PC_REGNUM:
+ sprintf (buf, ".PC %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case SR_REGNUM:
+ sprintf (buf, ".SR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case PR_REGNUM:
+ sprintf (buf, ".PR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case GBR_REGNUM:
+ sprintf (buf, ".GBR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case VBR_REGNUM:
+ sprintf (buf, ".VBR %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case MACH_REGNUM:
+ sprintf (buf, ".MACH %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+
+ case MACL_REGNUM:
+ sprintf (buf, ".MACL %x\r", read_register (regno));
+ puts_e7000debug (buf);
+ break;
+ }
+
+#endif /* GDB_TARGET_IS_SH */
+
+ expect_prompt ();
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+e7000_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+e7000_files_info ()
+{
+ printf ("\tAttached to %s at %d baud.\n", dev_name, baudrate);
+}
+
+static int
+stickbyte (where, what)
+ char *where;
+ unsigned int what;
+{
+ static CONST char digs[] = "0123456789ABCDEF";
+
+ where[0] = digs[(what >> 4) & 0xf];
+ where[1] = digs[(what & 0xf) & 0xf];
+
+ return what;
+}
+
+/* Write a small ammount of memory. */
+
+static int
+write_small (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+ char buf[200];
+
+ for (i = 0; i < len; i++)
+ {
+ if (((memaddr + i) & 3) == 0 && (i + 3 < len))
+ {
+ /* Can be done with a long word */
+ sprintf (buf, "m %x %x%02x%02x%02x;l\r",
+ memaddr + i,
+ myaddr[i], myaddr[i + 1], myaddr[i + 2], myaddr[i + 3]);
+ puts_e7000debug (buf);
+ i += 3;
+ }
+ else
+ {
+ sprintf (buf, "m %x %x\r", memaddr + i, myaddr[i]);
+ puts_e7000debug (buf);
+ }
+ }
+
+ expect_prompt ();
+
+ return len;
+}
+
+/* Write a large ammount of memory, this only works with the serial
+ mode enabled. Command is sent as
+
+ il ;s:s\r ->
+ <- il ;s:s\r
+ <- ENQ
+ ACK ->
+ <- LO s\r
+ Srecords...
+ ^Z ->
+ <- ENQ
+ ACK ->
+ <- :
+ */
+
+static int
+write_large (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+#define maxstride 128
+ int stride;
+
+ puts_e7000debug ("IL ;S:FK\r");
+ expect (ENQSTRING);
+ putchar_e7000 (ACK);
+ expect ("LO FK\r");
+
+ for (i = 0; i < len; i += stride)
+ {
+ char compose[maxstride * 2 + 50];
+ int address = i + memaddr;
+ int j;
+ int check_sum;
+ int where = 0;
+ int alen;
+
+ stride = len - i;
+ if (stride > maxstride)
+ stride = maxstride;
+
+ compose[where++] = 'S';
+ check_sum = 0;
+ if (address >= 0xffffff)
+ alen = 4;
+ else if (address >= 0xffff)
+ alen = 3;
+ else
+ alen = 2;
+ /* Insert type. */
+ compose[where++] = alen - 1 + '0';
+ /* Insert length. */
+ check_sum += stickbyte (compose + where, alen + stride + 1);
+ where += 2;
+ while (alen > 0)
+ {
+ alen--;
+ check_sum += stickbyte (compose + where, address >> (8 * (alen)));
+ where += 2;
+ }
+
+ for (j = 0; j < stride; j++)
+ {
+ check_sum += stickbyte (compose + where, myaddr[i + j]);
+ where += 2;
+ }
+ stickbyte (compose + where, ~check_sum);
+ where += 2;
+ compose[where++] = '\r';
+ compose[where++] = '\n';
+ compose[where++] = 0;
+
+ SERIAL_WRITE (e7000_desc, compose, where);
+ j = SERIAL_READCHAR (e7000_desc, 0);
+ if (j == SERIAL_TIMEOUT)
+ {
+ /* This is ok - nothing there */
+ }
+ else if (j == ENQ)
+ {
+ /* Hmm, it's trying to tell us something */
+ expect (":");
+ error ("Error writing memory");
+ }
+ else
+ {
+ printf ("@%d}@", j);
+ while ((j = SERIAL_READCHAR(e7000_desc,0)) > 0)
+ {
+ printf ("@{%d}@",j);
+ }
+ }
+ }
+
+ /* Send the trailer record */
+ write_e7000 ("S70500000000FA\r");
+ putchar_e7000 (CTRLZ);
+ expect (ENQSTRING);
+ putchar_e7000 (ACK);
+ expect (":");
+
+ return len;
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's
+ memory at MEMADDR. Returns length moved.
+
+ Can't use the Srecord load over ethernet, so don't use fast method
+ then. */
+
+static int
+e7000_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ if (len < 16 || using_tcp || using_pc)
+ return write_small (memaddr, myaddr, len);
+ else
+ return write_large (memaddr, myaddr, len);
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved.
+
+ Small transactions we send
+ m <addr>;l
+ and receive
+ 00000000 12345678 ?
+ */
+
+static int
+e7000_read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int count;
+ int c;
+ int i;
+ char buf[200];
+ /* Starting address of this pass. */
+
+/* printf("READ INF %x %x %d\n", memaddr, myaddr, len);*/
+ if (((memaddr - 1) + len) < memaddr)
+ {
+ errno = EIO;
+ return 0;
+ }
+
+ sprintf (buf, "m %x;l\r", memaddr);
+ puts_e7000debug (buf);
+
+ for (count = 0; count < len; count += 4)
+ {
+ /* Suck away the address */
+ c = gch ();
+ while (c != ' ')
+ c = gch ();
+ c = gch ();
+ if (c == '*')
+ { /* Some kind of error */
+ expect_prompt();
+ return -1;
+ }
+ while (c != ' ')
+ c = gch ();
+
+ /* Now read in the data */
+ for (i = 0; i < 4; i++)
+ {
+ int b = gbyte();
+ if (count + i < len) {
+ myaddr[count + i] = b;
+ }
+ }
+
+ /* Skip the trailing ? and send a . to end and a cr for more */
+ gch ();
+ gch ();
+ if (count + 4 >= len)
+ puts_e7000debug(".\r");
+ else
+ puts_e7000debug("\r");
+
+ }
+ expect_prompt();
+ return len;
+}
+
+
+#if 0
+/*
+ For large transfers we used to send
+
+
+ d <addr> <endaddr>\r
+
+ and receive
+ <ADDR> < D A T A > < ASCII CODE >
+ 000000 5F FD FD FF DF 7F DF FF 01 00 01 00 02 00 08 04 "_..............."
+ 000010 FF D7 FF 7F D7 F1 7F FF 00 05 00 00 08 00 40 00 "..............@."
+ 000020 7F FD FF F7 7F FF FF F7 00 00 00 00 00 00 00 00 "................"
+
+ A cost in chars for each transaction of 80 + 5*n-bytes.
+
+ Large transactions could be done with the srecord load code, but
+ there is a pause for a second before dumping starts, which slows the
+ average rate down!
+*/
+
+static int
+e7000_read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int count;
+ int c;
+ char buf[200];
+
+ /* Starting address of this pass. */
+
+ if (((memaddr - 1) + len) < memaddr)
+ {
+ errno = EIO;
+ return 0;
+ }
+
+ sprintf (buf, "d %x %x\r", memaddr, memaddr + len - 1);
+ puts_e7000debug (buf);
+
+ count = 0;
+ c = gch ();
+
+ /* First skip the command */
+ while (c == '\n')
+ c = gch ();
+
+ while (c == ' ')
+ c = gch ();
+ if (c == '*')
+ {
+ expect ("\r");
+ return -1;
+ }
+
+ /* Skip the title line */
+ while (c != '\n')
+ c = gch ();
+ c = gch ();
+ while (count < len)
+ {
+ /* Skip the address */
+ while (c <= ' ')
+ c = gch ();
+
+ get_hex (&c);
+
+ /* read in the bytes on the line */
+ while (c != '"' && count < len)
+ {
+ if (c == ' ')
+ c = gch ();
+ else
+ {
+ myaddr[count++] = get_hex (&c);
+ }
+ }
+
+ while (c != '\n')
+ c = gch ();
+ }
+
+ while (c != ':')
+ c = gch ();
+
+ return len;
+}
+
+static int
+fast_but_for_the_pause_e7000_read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int loop;
+ int c;
+ char buf[200];
+
+ if (((memaddr - 1) + len) < memaddr)
+ {
+ errno = EIO;
+ return 0;
+ }
+
+ sprintf (buf, "is %x@%x:s\r", memaddr, len);
+ puts_e7000debug (buf);
+ gch ();
+ c = gch ();
+ if (c != ENQ)
+ {
+ /* Got an error */
+ error ("Memory read error");
+ }
+ putchar_e7000 (ACK);
+ expect ("SV s");
+ loop = 1;
+ while (loop)
+ {
+ int type;
+ int length;
+ int addr;
+ int i;
+
+ c = gch ();
+ switch (c)
+ {
+ case ENQ: /* ENQ, at the end */
+ loop = 0;
+ break;
+ case 'S':
+ /* Start of an Srecord */
+ type = gch ();
+ length = gbyte ();
+ switch (type)
+ {
+ case '7': /* Termination record, ignore */
+ case '0':
+ case '8':
+ case '9':
+ /* Header record - ignore it */
+ while (length--)
+ {
+ gbyte ();
+ }
+ break;
+ case '1':
+ case '2':
+ case '3':
+ {
+ int alen;
+
+ alen = type - '0' + 1;
+ addr = 0;
+ while (alen--)
+ {
+ addr = (addr << 8) + gbyte ();
+ length--;
+ }
+
+ for (i = 0; i < length - 1; i++)
+ myaddr[i + addr - memaddr] = gbyte ();
+
+ gbyte (); /* Ignore checksum */
+ }
+ }
+ }
+ }
+
+ putchar_e7000 (ACK);
+ expect ("TOP ADDRESS =");
+ expect ("END ADDRESS =");
+ expect (":");
+
+ return len;
+}
+
+#endif
+
+static int
+e7000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return e7000_write_inferior_memory( memaddr, myaddr, len);
+ else
+ return e7000_read_inferior_memory( memaddr, myaddr, len);
+}
+
+static void
+e7000_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+}
+
+static void
+e7000_load (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct cleanup *old_chain;
+ asection *section;
+ bfd *pbfd;
+ bfd_vma entry;
+ int i;
+#define WRITESIZE 0x1000
+ char buf[2 + 4 + 4 + WRITESIZE]; /* `DT' + <addr> + <len> + <data> */
+ char *filename;
+ int quiet;
+ int nostart;
+ time_t start_time, end_time; /* Start and end times of download */
+ unsigned long data_count; /* Number of bytes transferred to memory */
+
+ if (!strchr (dev_name, ':'))
+ {
+ generic_load (args, from_tty);
+ return;
+ }
+
+ buf[0] = 'D';
+ buf[1] = 'T';
+ quiet = 0;
+ nostart = 0;
+ filename = NULL;
+
+ while (*args != '\000')
+ {
+ char *arg;
+
+ while (isspace (*args)) args++;
+
+ arg = args;
+
+ while ((*args != '\000') && !isspace (*args)) args++;
+
+ if (*args != '\000')
+ *args++ = '\000';
+
+ if (*arg != '-')
+ filename = arg;
+ else if (strncmp (arg, "-quiet", strlen (arg)) == 0)
+ quiet = 1;
+ else if (strncmp (arg, "-nostart", strlen (arg)) == 0)
+ nostart = 1;
+ else
+ error ("unknown option `%s'", arg);
+ }
+
+ if (!filename)
+ filename = get_exec_file (1);
+
+ pbfd = bfd_openr (filename, gnutarget);
+ if (pbfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ old_chain = make_cleanup (bfd_close, pbfd);
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("\"%s\" is not an object file: %s", filename,
+ bfd_errmsg (bfd_get_error ()));
+
+ start_time = time (NULL);
+ data_count = 0;
+
+ puts_e7000debug ("mw\r");
+
+ expect ("\nOK");
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
+ {
+ bfd_vma section_address;
+ bfd_size_type section_size;
+ file_ptr fptr;
+
+ section_address = bfd_get_section_vma (pbfd, section);
+ section_size = bfd_get_section_size_before_reloc (section);
+
+ if (!quiet)
+ printf_filtered ("[Loading section %s at 0x%x (%d bytes)]\n",
+ bfd_get_section_name (pbfd, section),
+ section_address,
+ section_size);
+
+ fptr = 0;
+
+ data_count += section_size;
+
+ while (section_size > 0)
+ {
+ int count;
+ static char inds[] = "|/-\\";
+ static int k = 0;
+
+ QUIT;
+
+ count = min (section_size, WRITESIZE);
+
+ buf[2] = section_address >> 24;
+ buf[3] = section_address >> 16;
+ buf[4] = section_address >> 8;
+ buf[5] = section_address;
+
+ buf[6] = count >> 24;
+ buf[7] = count >> 16;
+ buf[8] = count >> 8;
+ buf[9] = count;
+
+ bfd_get_section_contents (pbfd, section, buf + 10, fptr, count);
+
+ if (SERIAL_WRITE (e7000_desc, buf, count + 10))
+ fprintf_unfiltered (gdb_stderr,
+ "e7000_load: SERIAL_WRITE failed: %s\n",
+ safe_strerror(errno));
+
+ expect ("OK");
+
+ if (!quiet)
+ {
+ printf_unfiltered ("\r%c", inds[k++ % 4]);
+ gdb_flush (gdb_stdout);
+ }
+
+ section_address += count;
+ fptr += count;
+ section_size -= count;
+ }
+ }
+ }
+
+ write_e7000 ("ED");
+
+ expect_prompt ();
+
+ end_time = time (NULL);
+
+/* Finally, make the PC point at the start address */
+
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+
+ if (!nostart)
+ {
+ entry = bfd_get_start_address (pbfd);
+
+ if (!quiet)
+ printf_unfiltered ("[Starting %s at 0x%x]\n", filename, entry);
+
+/* start_routine (entry);*/
+ }
+
+ printf_filtered ("Transfer rate: %d bits/sec.\n",
+ (data_count * 8)/(end_time - start_time));
+
+ do_cleanups (old_chain);
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+e7000_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&e7000_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#ifdef HARD_BREAKPOINTS
+#define MAX_E7000DEBUG_BREAKPOINTS (BC_BREAKPOINTS ? 5 : 200)
+#else
+#define MAX_E7000DEBUG_BREAKPOINTS 200
+#endif
+
+extern int memory_breakpoint_size;
+
+static CORE_ADDR breakaddr[MAX_E7000DEBUG_BREAKPOINTS] = {0};
+
+static int
+e7000_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ unsigned char *shadow;
+{
+ int i;
+ char buf[200];
+ static char nop[2] = NOP;
+
+ for (i = 0; i <= MAX_E7000DEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+ /* Save old contents, and insert a nop in the space */
+#ifdef HARD_BREAKPOINTS
+ if (BC_BREAKPOINTS)
+ {
+ sprintf (buf, "BC%d A=%x\r", i+1, addr);
+ puts_e7000debug (buf);
+ }
+ else
+ {
+ sprintf (buf, "B %x\r", addr);
+ puts_e7000debug (buf);
+ }
+#else
+#if 0
+ e7000_read_inferior_memory (addr, shadow, 2);
+ e7000_write_inferior_memory (addr, nop, 2);
+#endif
+
+ sprintf (buf, "B %x\r", addr);
+ puts_e7000debug (buf);
+#endif
+ expect_prompt ();
+ return 0;
+ }
+
+ error ("Too many breakpoints ( > %d) for the E7000\n",
+ MAX_E7000DEBUG_BREAKPOINTS);
+ return 1;
+}
+
+static int
+e7000_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ unsigned char *shadow;
+{
+ int i;
+ char buf[200];
+
+ for (i = 0; i < MAX_E7000DEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+#ifdef HARD_BREAKPOINTS
+ if (BC_BREAKPOINTS)
+ {
+ sprintf (buf, "BC%d - \r", i+1);
+ puts_e7000debug (buf);
+ }
+ else
+ {
+ sprintf (buf, "B - %x\r", addr);
+ puts_e7000debug (buf);
+ }
+ expect_prompt ();
+#else
+ sprintf (buf, "B - %x\r", addr);
+ puts_e7000debug (buf);
+ expect_prompt ();
+
+#if 0
+ /* Replace the insn under the break */
+ e7000_write_inferior_memory (addr, shadow, 2);
+#endif
+#endif
+
+ return 0;
+ }
+
+ warning ("Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+/* Put a command string, in args, out to STDBUG. Output from STDBUG
+ is placed on the users terminal until the prompt is seen. */
+
+static void
+e7000_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ /* FIXME: arbitrary limit on length of args. */
+ char buf[200];
+
+ echo = 0;
+
+ if (!e7000_desc)
+ error ("e7000 target not open.");
+ if (!args)
+ {
+ puts_e7000debug ("\r");
+ }
+ else
+ {
+ sprintf (buf, "%s\r", args);
+ puts_e7000debug (buf);
+ }
+
+ echo++;
+ ctrl_c = 2;
+ expect_full_prompt ();
+ echo--;
+ ctrl_c = 0;
+ printf_unfiltered ("\n");
+
+ /* Who knows what the command did... */
+ registers_changed ();
+}
+
+
+static void
+e7000_drain_command (args, fromtty)
+ char *args;
+ int fromtty;
+
+{
+ int c;
+
+ puts_e7000debug("end\r");
+ putchar_e7000 (CTRLC);
+
+ while ((c = SERIAL_READCHAR (e7000_desc, 1) != SERIAL_TIMEOUT))
+ {
+ if (quit_flag)
+ {
+ putchar_e7000(CTRLC);
+ quit_flag = 0;
+ }
+ if (c > ' ' && c < 127)
+ printf ("%c", c & 0xff);
+ else
+ printf ("<%x>", c & 0xff);
+ }
+}
+
+#define NITEMS 7
+
+static int
+why_stop ()
+{
+ static char *strings[NITEMS] = {
+ "STEP NORMAL",
+ "BREAK POINT",
+ "BREAK KEY",
+ "BREAK CONDI",
+ "CYCLE ACCESS",
+ "ILLEGAL INSTRUCTION",
+ "WRITE PROTECT",
+ };
+ char *p[NITEMS];
+ int c;
+ int i;
+
+ for (i = 0; i < NITEMS; ++i)
+ p[i] = strings[i];
+
+ c = gch ();
+ while (1)
+ {
+ for (i = 0; i < NITEMS; i++)
+ {
+ if (c == *(p[i]))
+ {
+ p[i]++;
+ if (*(p[i]) == 0)
+ {
+ /* found one of the choices */
+ return i;
+ }
+ }
+ else
+ p[i] = strings[i];
+ }
+
+ c = gch ();
+ }
+}
+
+/* Suck characters, if a string match, then return the strings index
+ otherwise echo them. */
+
+int
+expect_n (strings)
+char **strings;
+{
+ char *(ptr[10]);
+ int n;
+ int c;
+ char saveaway[100];
+ char *buffer = saveaway;
+ /* Count number of expect strings */
+
+ for (n = 0; strings[n]; n++)
+ {
+ ptr[n] = strings[n];
+ }
+
+ while (1)
+ {
+ int i;
+ int gotone = 0;
+
+ c = SERIAL_READCHAR (e7000_desc, 1);
+ if (c == SERIAL_TIMEOUT)
+ {
+ printf_unfiltered ("[waiting for e7000...]\n");
+ }
+#ifdef __GO32__
+ if (kbhit ())
+ {
+ int k = getkey();
+
+ if (k == 1)
+ quit_flag = 1;
+ }
+#endif
+ if (quit_flag)
+ {
+ putchar_e7000 (CTRLC); /* interrupt the running program */
+ quit_flag = 0;
+ }
+
+ for (i = 0; i < n; i++)
+ {
+ if (c == ptr[i][0])
+ {
+ ptr[i]++;
+ if (ptr[i][0] == 0)
+ {
+ /* Gone all the way */
+ return i;
+ }
+ gotone = 1;
+ }
+ else
+ {
+ ptr[i] = strings[i];
+ }
+ }
+
+ if (gotone)
+ {
+ /* Save it up incase we find that there was no match */
+ *buffer ++ = c;
+ }
+ else
+ {
+ if (buffer != saveaway)
+ {
+ *buffer++ = 0;
+ printf ("%s", buffer);
+ buffer = saveaway;
+ }
+ if (c != SERIAL_TIMEOUT)
+ {
+ putchar (c);
+ fflush (stdout);
+ }
+ }
+ }
+}
+
+/* We subtract two from the pc here rather than use
+ DECR_PC_AFTER_BREAK since the e7000 doesn't always add two to the
+ pc, and the simulators never do. */
+
+static void
+sub2_from_pc ()
+{
+ char buf[4];
+ char buf2[200];
+
+ store_signed_integer (buf,
+ REGISTER_RAW_SIZE(PC_REGNUM),
+ read_register (PC_REGNUM) -2);
+ supply_register (PC_REGNUM, buf);
+ sprintf (buf2, ".PC %x\r", read_register (PC_REGNUM));
+ puts_e7000debug (buf2);
+}
+
+#define WAS_SLEEP 0
+#define WAS_INT 1
+#define WAS_RUNNING 2
+#define WAS_OTHER 3
+
+static char *estrings[] = {
+ "** SLEEP",
+ "BREAK !",
+ "** PC",
+ "PC",
+ NULL
+};
+
+/* Wait until the remote machine stops, then return, storing status in
+ STATUS just as `wait' would. */
+
+static int
+e7000_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int stop_reason;
+ int regno;
+ int running_count = 0;
+ int had_sleep = 0;
+ int loop = 1;
+
+ /* Then echo chars until PC= string seen */
+ gch (); /* Drop cr */
+ gch (); /* and space */
+
+ while (loop)
+ {
+ switch (expect_n (estrings))
+ {
+ case WAS_OTHER:
+ /* how did this happen ? */
+ loop = 0;
+ break;
+ case WAS_SLEEP:
+ had_sleep = 1;
+ putchar_e7000 (CTRLC);
+ loop = 0;
+ break;
+ case WAS_INT:
+ loop = 0;
+ break;
+ case WAS_RUNNING:
+ running_count++;
+ if (running_count == 20)
+ {
+ printf_unfiltered ("[running...]\n");
+ running_count = 0;
+ }
+ break;
+ default:
+ /* error? */
+ break;
+ }
+ }
+
+ /* Skip till the PC= */
+ expect ("=");
+ fetch_regs_from_dump (gch, want_nopc);
+
+ /* And supply the extra ones the simulator uses */
+ for (regno = NUM_REALREGS; regno < NUM_REGS; regno++)
+ {
+ int buf = 0;
+ supply_register (regno, (char *) &buf);
+ }
+
+ stop_reason = why_stop ();
+ expect_full_prompt ();
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ switch (stop_reason)
+ {
+ case 1: /* Breakpoint */
+ write_pc (read_pc ()); /* PC is always off by 2 for breakpoints */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 0: /* Single step */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 2: /* Interrupt */
+ if (had_sleep)
+ {
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ sub2_from_pc ();
+ }
+ else
+ {
+ status->value.sig = TARGET_SIGNAL_INT;
+ }
+ break;
+ case 3:
+ break;
+ case 4:
+ printf_unfiltered ("a cycle address error?\n");
+ status->value.sig = TARGET_SIGNAL_UNKNOWN;
+ break;
+ case 5:
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 6:
+ status->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+ case 7: /* Anything else (NITEMS + 1) */
+ printf_unfiltered ("a write protect error?\n");
+ status->value.sig = TARGET_SIGNAL_UNKNOWN;
+ break;
+ default:
+ /* Get the user's attention - this should never happen. */
+ abort ();
+ }
+
+ return 0;
+}
+
+/* Define the target subroutine names. */
+
+struct target_ops e7000_ops =
+{
+ "e7000",
+ "Remote Hitachi e7000 target",
+ "Use a remote Hitachi e7000 ICE connected by a serial line,\n\
+or a network connection.\n\
+Arguments are the name of the device for the serial line,\n\
+the speed to connect at in bits per second.\n\
+eg\n\
+target e7000 /dev/ttya 9600\n\
+target e7000 foobar",
+ e7000_open, /* to_open */
+ e7000_close, /* to_close */
+ 0, /* to_attach */
+ e7000_detach, /* to_detach */
+ e7000_resume, /* to_resume */
+ e7000_wait, /* to_wait */
+ e7000_fetch_register, /* to_fetch_registers */
+ e7000_store_register, /* to_store_registers */
+ e7000_prepare_to_store, /* to_prepare_to_store */
+ e7000_xfer_inferior_memory, /* to_xfer_memory */
+ e7000_files_info, /* to_files_info */
+ e7000_insert_breakpoint, /* to_insert_breakpoint */
+ e7000_remove_breakpoint, /* to_remove_breakpoint */
+ 0, /* to_terminal_init */
+ 0, /* to_terminal_inferior */
+ 0, /* to_terminal_ours_for_output */
+ 0, /* to_terminal_ours */
+ 0, /* to_terminal_info */
+ e7000_kill, /* to_kill */
+ e7000_load, /* to_load */
+ 0, /* to_lookup_symbol */
+ e7000_create_inferior, /* to_create_inferior */
+ e7000_mourn_inferior, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* next (unused) */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* to_sections */
+ 0, /* to_sections_end */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_e7000 ()
+{
+ add_target (&e7000_ops);
+
+ add_com ("e7000 <command>", class_obscure, e7000_command,
+ "Send a command to the e7000 monitor.");
+
+ add_com ("ftplogin <machine> <name> <passwd> <dir>", class_obscure, e7000_login_command,
+ "Login to machine and change to directory.");
+
+ add_com ("ftpload <file>", class_obscure, e7000_ftp_command,
+ "Fetch and load a file from previously described place.");
+
+ add_com ("drain", class_obscure, e7000_drain_command,
+ "Drain pending e7000 text buffers.");
+}
diff --git a/contrib/gdb/gdb/remote-eb.c b/contrib/gdb/gdb/remote-eb.c
new file mode 100644
index 0000000..baa4d24
--- /dev/null
+++ b/contrib/gdb/gdb/remote-eb.c
@@ -0,0 +1,1009 @@
+/* Remote debugging interface for AMD 29000 EBMON on IBM PC, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but is for an esoteric situation--
+ having a a29k board in a PC hooked up to a unix machine with
+ a serial line, and running ctty com1 on the PC, through which
+ the unix machine can run ebmon. Not to mention that the PC
+ has PC/NFS, so it can access the same executables that gdb can,
+ over the net in real time. */
+
+#include "defs.h"
+#include "gdb_string.h"
+
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+
+extern struct target_ops eb_ops; /* Forward declaration */
+
+static void eb_close();
+
+#define LOG_FILE "eb.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 24;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ eb_open knows that we don't have a file open when the program
+ starts. */
+int eb_desc = -1;
+
+/* stream which is fdopen'd from eb_desc. Only valid when
+ eb_desc != -1. */
+FILE *eb_stream;
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+static int
+readchar ()
+{
+ char buf;
+
+ buf = '\0';
+#ifdef HAVE_TERMIO
+ /* termio does the timeout for us. */
+ read (eb_desc, &buf, 1);
+#else
+ alarm (timeout);
+ if (read (eb_desc, &buf, 1) < 0)
+ {
+ if (errno == EINTR)
+ error ("Timeout reading from remote system.");
+ else
+ perror_with_name ("remote");
+ }
+ alarm (0);
+#endif
+
+ if (buf == '\0')
+ error ("Timeout reading from remote system.");
+#if defined (LOG_FILE)
+ putc (buf & 0x7f, log_file);
+#endif
+ return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ if (readchar() == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ p = string;
+ }
+}
+
+/* Keep discarding input until we see the ebmon prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: eb_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a eb_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt ()
+{
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush (log_file);
+#endif
+ expect ("\n# ");
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from eb_desc and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ supply_register (regno++, (char *) &val);
+ }
+}
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+#define volatile /**/
+#endif
+volatile int n_alarms;
+
+void
+eb_timer ()
+{
+#if 0
+ if (kiodebug)
+ printf ("eb_timer called\n");
+#endif
+ n_alarms++;
+}
+#endif
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+/* Nonzero if we have loaded the file ("yc") and not yet issued a "gi"
+ command. "gi" is supposed to happen exactly once for each "yc". */
+static int need_gi = 0;
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to eb_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+eb_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote EBMON process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ {
+ /* OK, now read in the file. Y=read, C=COFF, D=no symbols
+ 0=start address, %s=filename. */
+
+ fprintf (eb_stream, "YC D,0:%s", prog_name);
+
+ if (args != NULL)
+ fprintf(eb_stream, " %s", args);
+
+ fprintf (eb_stream, "\n");
+ fflush (eb_stream);
+
+ expect_prompt ();
+
+ need_gi = 1;
+ }
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0); /* Let 'er rip... */
+}
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+struct {int rate, damn_b;} baudtab[] = {
+ {0, B0},
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+int damn_b (rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+ return B38400; /* Random */
+}
+
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication, then a space,
+ then the name of the program as we should name it to EBMON. */
+
+static int baudrate = 9600;
+static char *dev_name;
+void
+eb_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ TERMINAL sg;
+
+ char *p;
+
+ target_preopen (from_tty);
+
+ /* Find the first whitespace character, it separates dev_name from
+ prog_name. */
+ if (name == 0)
+ goto erroid;
+
+ for (p = name;
+ *p != '\0' && !isspace (*p); p++)
+ ;
+ if (*p == '\0')
+erroid:
+ error ("\
+Please include the name of the device for the serial port,\n\
+the baud rate, and the name of the program to run on the remote system.");
+ dev_name = alloca (p - name + 1);
+ strncpy (dev_name, name, p - name);
+ dev_name[p - name] = '\0';
+
+ /* Skip over the whitespace after dev_name */
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (1 != sscanf (p, "%d ", &baudrate))
+ goto erroid;
+
+ /* Skip the number and then the spaces */
+ for (; isdigit (*p); p++)
+ /*EMPTY*/;
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (p, strlen (p));
+
+ eb_close (0);
+
+ eb_desc = open (dev_name, O_RDWR);
+ if (eb_desc < 0)
+ perror_with_name (dev_name);
+ ioctl (eb_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+ sg.c_cc[VMIN] = 0; /* read with timeout. */
+ sg.c_cc[VTIME] = timeout * 10;
+ sg.c_lflag &= ~(ICANON | ECHO);
+ sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+ sg.sg_ispeed = damn_b (baudrate);
+ sg.sg_ospeed = damn_b (baudrate);
+ sg.sg_flags |= RAW | ANYP;
+ sg.sg_flags &= ~ECHO;
+#endif
+
+ ioctl (eb_desc, TIOCSETP, &sg);
+ eb_stream = fdopen (eb_desc, "r+");
+
+ push_target (&eb_ops);
+ if (from_tty)
+ printf ("Remote %s debugging %s using %s\n", target_shortname,
+ prog_name, dev_name);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+ /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+ the read. */
+ if (siginterrupt (SIGALRM, 1) != 0)
+ perror ("eb_open: error in siginterrupt");
+#endif
+
+ /* Set up read timeout timer. */
+ if ((void (*)) signal (SIGALRM, eb_timer) == (void (*)) -1)
+ perror ("eb_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+
+ /* Hello? Are you there? */
+ write (eb_desc, "\n", 1);
+
+ expect_prompt ();
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+eb_close (quitting)
+ int quitting;
+{
+
+ /* Due to a bug in Unix, fclose closes not only the stdio stream,
+ but also the file descriptor. So we don't actually close
+ eb_desc. */
+ if (eb_stream)
+ fclose (eb_stream); /* This also closes eb_desc */
+ if (eb_desc >= 0)
+ /* close (eb_desc); */
+
+ /* Do not try to close eb_desc again, later in the program. */
+ eb_stream = NULL;
+ eb_desc = -1;
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror (log_file))
+ printf ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf ("Error closing log file.\n");
+ }
+#endif
+}
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+void
+eb_detach (from_tty)
+ int from_tty;
+{
+ pop_target(); /* calls eb_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+void
+eb_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (step)
+ {
+ write (eb_desc, "t 1,s\n", 6);
+ /* Wait for the echo. */
+ expect ("t 1,s\r");
+ /* Then comes a line containing the instruction we stepped to. */
+ expect ("\n@");
+ /* Then we get the prompt. */
+ expect_prompt ();
+
+ /* Force the next eb_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type
+ "continue" to see any. This should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ {
+ if (need_gi)
+ {
+ need_gi = 0;
+ write (eb_desc, "gi\n", 3);
+
+ /* Swallow the echo of "gi". */
+ expect ("gi\r");
+ }
+ else
+ {
+ write (eb_desc, "GR\n", 3);
+ /* Swallow the echo. */
+ expect ("GR\r");
+ }
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+int
+eb_wait (status)
+ struct target_waitstatus *status;
+{
+ /* Strings to look for. '?' means match any single character.
+ Note that with the algorithm we use, the initial character
+ of the string cannot recur in the string, or we will not
+ find some cases of the string in the input. */
+
+ static char bpt[] = "Invalid interrupt taken - #0x50 - ";
+ /* It would be tempting to look for "\n[__exit + 0x8]\n"
+ but that requires loading symbols with "yc i" and even if
+ we did do that we don't know that the file has symbols. */
+ static char exitmsg[] = "\n@????????I JMPTI GR121,LR0";
+ char *bp = bpt;
+ char *ep = exitmsg;
+
+ /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
+ char swallowed[50];
+ /* Current position in swallowed. */
+ char *swallowed_p = swallowed;
+
+ int ch;
+ int ch_handled;
+
+ int old_timeout = timeout;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ if (need_artificial_trap != 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ return 0;
+ }
+
+ timeout = 0; /* Don't time out -- user program is running. */
+ while (1)
+ {
+ ch_handled = 0;
+ ch = readchar ();
+ if (ch == *bp)
+ {
+ bp++;
+ if (*bp == '\0')
+ break;
+ ch_handled = 1;
+
+ *swallowed_p++ = ch;
+ }
+ else
+ bp = bpt;
+
+ if (ch == *ep || *ep == '?')
+ {
+ ep++;
+ if (*ep == '\0')
+ break;
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+ ch_handled = 1;
+ }
+ else
+ ep = exitmsg;
+
+ if (!ch_handled)
+ {
+ char *p;
+
+ /* Print out any characters which have been swallowed. */
+ for (p = swallowed; p < swallowed_p; ++p)
+ putc (*p, stdout);
+ swallowed_p = swallowed;
+
+ putc (ch, stdout);
+ }
+ }
+ expect_prompt ();
+ if (*bp== '\0')
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+ timeout = old_timeout;
+
+ return 0;
+}
+
+/* Return the name of register number REGNO
+ in the form input and output by EBMON.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[80];
+ if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ sprintf (buf, "GR%03d", regno - GR96_REGNUM + 96);
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ sprintf (buf, "LR%03d", regno - LR0_REGNUM);
+ else if (regno == Q_REGNUM)
+ strcpy (buf, "SR131");
+ else if (regno >= BP_REGNUM && regno <= CR_REGNUM)
+ sprintf (buf, "SR%03d", regno - BP_REGNUM + 133);
+ else if (regno == ALU_REGNUM)
+ strcpy (buf, "SR132");
+ else if (regno >= IPC_REGNUM && regno <= IPB_REGNUM)
+ sprintf (buf, "SR%03d", regno - IPC_REGNUM + 128);
+ else if (regno >= VAB_REGNUM && regno <= LRU_REGNUM)
+ sprintf (buf, "SR%03d", regno - VAB_REGNUM);
+ else if (regno == GR1_REGNUM)
+ strcpy (buf, "GR001");
+ return buf;
+}
+
+/* Read the remote registers into the block REGS. */
+
+static void
+eb_fetch_registers ()
+{
+ int reg_index;
+ int regnum_index;
+ char tempbuf[10];
+ int i;
+
+#if 0
+ /* This should not be necessary, because one is supposed to read the
+ registers only when the inferior is stopped (at least with
+ ptrace() and why not make it the same for remote?). */
+ /* ^A is the "normal character" used to make sure we are talking to EBMON
+ and not to the program being debugged. */
+ write (eb_desc, "\001\n");
+ expect_prompt ();
+#endif
+
+ write (eb_desc, "dw gr96,gr127\n", 14);
+ for (reg_index = 96, regnum_index = GR96_REGNUM;
+ reg_index < 128;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "GR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+
+ for (i = 0; i < 128; i += 32)
+ {
+ /* The PC has a tendency to hang if we get these
+ all in one fell swoop ("dw lr0,lr127"). */
+ sprintf (tempbuf, "dw lr%d\n", i);
+ write (eb_desc, tempbuf, strlen (tempbuf));
+ for (reg_index = i, regnum_index = LR0_REGNUM + i;
+ reg_index < i + 32;
+ reg_index += 4, regnum_index += 4)
+ {
+ sprintf (tempbuf, "LR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (4, regnum_index);
+ expect ("\n");
+ }
+ }
+
+ write (eb_desc, "dw sr133,sr133\n", 15);
+ expect ("SR133 ");
+ get_hex_regs (1, BP_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr134,sr134\n", 15);
+ expect ("SR134 ");
+ get_hex_regs (1, FC_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr135,sr135\n", 15);
+ expect ("SR135 ");
+ get_hex_regs (1, CR_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr131,sr131\n", 15);
+ expect ("SR131 ");
+ get_hex_regs (1, Q_REGNUM);
+ expect ("\n");
+
+ write (eb_desc, "dw sr0,sr14\n", 12);
+ for (reg_index = 0, regnum_index = VAB_REGNUM;
+ regnum_index <= LRU_REGNUM;
+ regnum_index += 4, reg_index += 4)
+ {
+ sprintf (tempbuf, "SR%03d ", reg_index);
+ expect (tempbuf);
+ get_hex_regs (reg_index == 12 ? 3 : 4, regnum_index);
+ expect ("\n");
+ }
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, (char *) &val);
+ supply_register (INTE_REGNUM, (char *) &val);
+ supply_register (FPS_REGNUM, (char *) &val);
+ supply_register (EXO_REGNUM, (char *) &val);
+ }
+
+ write (eb_desc, "dw gr1,gr1\n", 11);
+ expect ("GR001 ");
+ get_hex_regs (1, GR1_REGNUM);
+ expect_prompt ();
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ Returns errno value. */
+void
+eb_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ eb_fetch_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (eb_stream, "dw %s,%s\n", name, name);
+ expect (name);
+ expect (" ");
+ get_hex_regs (1, regno);
+ expect_prompt ();
+ }
+ return;
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+eb_store_registers ()
+{
+ int i, j;
+ fprintf (eb_stream, "s gr1,%x\n", read_register (GR1_REGNUM));
+ expect_prompt ();
+
+ for (j = 0; j < 32; j += 16)
+ {
+ fprintf (eb_stream, "s gr%d,", j + 96);
+ for (i = 0; i < 15; ++i)
+ fprintf (eb_stream, "%x,", read_register (GR96_REGNUM + j + i));
+ fprintf (eb_stream, "%x\n", read_register (GR96_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ for (j = 0; j < 128; j += 16)
+ {
+ fprintf (eb_stream, "s lr%d,", j);
+ for (i = 0; i < 15; ++i)
+ fprintf (eb_stream, "%x,", read_register (LR0_REGNUM + j + i));
+ fprintf (eb_stream, "%x\n", read_register (LR0_REGNUM + j + 15));
+ expect_prompt ();
+ }
+
+ fprintf (eb_stream, "s sr133,%x,%x,%x\n", read_register (BP_REGNUM),
+ read_register (FC_REGNUM), read_register (CR_REGNUM));
+ expect_prompt ();
+ fprintf (eb_stream, "s sr131,%x\n", read_register (Q_REGNUM));
+ expect_prompt ();
+ fprintf (eb_stream, "s sr0,");
+ for (i = 0; i < 11; ++i)
+ fprintf (eb_stream, "%x,", read_register (VAB_REGNUM + i));
+ fprintf (eb_stream, "%x\n", read_register (VAB_REGNUM + 11));
+ expect_prompt ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+ Return errno value. */
+void
+eb_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ eb_store_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ fprintf (eb_stream, "s %s,%x\n", name, read_register (regno));
+ /* Setting GR1 changes the numbers of all the locals, so
+ invalidate the register cache. Do this *after* calling
+ read_register, because we want read_register to return the
+ value that write_register has just stuffed into the registers
+ array, not the value of the register fetched from the
+ inferior. */
+ if (regno == GR1_REGNUM)
+ registers_changed ();
+ expect_prompt ();
+ }
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+void
+eb_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+
+/* FIXME-someday! Merge these two. */
+int
+eb_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return eb_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return eb_read_inferior_memory (memaddr, myaddr, len);
+}
+
+void
+eb_files_info ()
+{
+ printf ("\tAttached to %s at %d baud and running program %s.\n",
+ dev_name, baudrate, prog_name);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns length moved. */
+int
+eb_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ if ((i % 16) == 0)
+ fprintf (eb_stream, "sb %x,", memaddr + i);
+ if ((i % 16) == 15 || i == len - 1)
+ {
+ fprintf (eb_stream, "%x\n", ((unsigned char *)myaddr)[i]);
+ expect_prompt ();
+ }
+ else
+ fprintf (eb_stream, "%x,", ((unsigned char *)myaddr)[i]);
+ }
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved. */
+int
+eb_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ eb_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len to memaddr and gets 0. */
+ /* However, something like
+ eb_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+
+ fprintf (eb_stream, "db %x,%x\n", startaddr,
+ (startaddr - 1) + len_this_pass);
+ expect ("\n");
+
+ /* Look for 8 hex digits. */
+ i = 0;
+ while (1)
+ {
+ if (isxdigit (readchar ()))
+ ++i;
+ else
+ {
+ expect_prompt ();
+ error ("Hex digit expected from remote system.");
+ }
+ if (i >= 8)
+ break;
+ }
+
+ expect (" ");
+
+ for (i = 0; i < len_this_pass; i++)
+ get_hex_byte (&myaddr[count++]);
+
+ expect_prompt ();
+
+ startaddr += len_this_pass;
+ }
+ return len;
+}
+
+static void
+eb_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+void
+eb_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&eb_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+/* Define the target subroutine names */
+
+struct target_ops eb_ops = {
+ "amd-eb", "Remote serial AMD EBMON target",
+ "Use a remote computer running EBMON connected by a serial line.\n\
+Arguments are the name of the device for the serial line,\n\
+the speed to connect at in bits per second, and the filename of the\n\
+executable as it exists on the remote computer. For example,\n\
+ target amd-eb /dev/ttya 9600 demo",
+ eb_open, eb_close,
+ 0, eb_detach, eb_resume, eb_wait,
+ eb_fetch_register, eb_store_register,
+ eb_prepare_to_store,
+ eb_xfer_inferior_memory, eb_files_info,
+ 0, 0, /* Breakpoints */
+ 0, 0, 0, 0, 0, /* Terminal handling */
+ eb_kill,
+ generic_load, /* load */
+ 0, /* lookup_symbol */
+ eb_create_inferior,
+ eb_mourn_inferior,
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_stop */
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_eb ()
+{
+ add_target (&eb_ops);
+}
diff --git a/contrib/gdb/gdb/remote-es.c b/contrib/gdb/gdb/remote-es.c
new file mode 100644
index 0000000..b4e60ef
--- /dev/null
+++ b/contrib/gdb/gdb/remote-es.c
@@ -0,0 +1,2152 @@
+/* Memory-access and commands for remote es1800 processes, for GDB.
+ Copyright (C) 1988, 1992 Free Software Foundation, Inc.
+
+ This file is added to GDB to make it possible to do debugging via an
+ ES-1800 emulator. The code was originally written by Johan Holmberg
+ TT/SJ Ericsson Telecom AB and later modified by Johan Henriksson
+ TT/SJ. It was modified for gdb 4.0 by TX/DK Jan Nordenand by TX/DKG
+ Harald Johansen.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* Emulator communication protocol.
+ All values are encoded in ascii hex digits.
+
+ Request
+Command
+Reply
+ read registers:
+DR<cr>
+ - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - -- 6 - - 7 -
+D = XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
+A = XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
+ PC = XXXXXX SSP = XXXXXX USP = XXXXXX SR = XXXXXXXX
+ >
+Each byte of register data is described by two hex digits.
+
+ write regs
+D0=XXXXXXXX<cr>
+ >D1=XXXXXXXX<cr>
+ >D2=XXXXXXXX<cr>
+ >D3=XXXXXXXX<cr>
+ >D4=XXXXXXXX<cr>
+ >D5=XXXXXXXX<cr>
+ >D6=XXXXXXXX<cr>
+ >D7=XXXXXXXX<cr>
+ >A0=XXXXXXXX<cr>
+ >A1=XXXXXXXX<cr>
+ >A2=XXXXXXXX<cr>
+ >A3=XXXXXXXX<cr>
+ >A4=XXXXXXXX<cr>
+ >A5=XXXXXXXX<cr>
+ >A6=XXXXXXXX<cr>
+ >A7=XXXXXXXX<cr>
+ >SR=XXXXXXXX<cr>
+ >PC=XXXXXX<cr>
+ >
+Each byte of register data is described by two hex digits.
+
+ read mem
+@.BAA..AA
+$FFFFFFXX
+ >
+AA..AA is address, XXXXXXX is the contents
+
+ write mem
+ @.BAA..AA=$XXXXXXXX
+ >
+AA..AA is address, XXXXXXXX is data
+
+ cont
+PC=$AA..AA
+ >RBK
+R>
+AA..AA is address to resume. If AA..AA is omitted, resume at same address.
+
+ step
+PC=$AA..AA
+ >STP
+R>
+AA..AA is address to resume. If AA..AA is omitted, resume at same address.
+
+ kill req
+STP
+ >
+*/
+
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <errno.h>
+#include <ctype.h>
+#include "gdb_string.h"
+#include <setjmp.h>
+#include <fcntl.h>
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "command.h"
+#include "remote-utils.h"
+#include "gdbcore.h"
+#include "serial.h"
+
+/* Prototypes for local functions */
+
+static void
+es1800_child_detach PARAMS ((char *, int));
+
+static void
+es1800_child_open PARAMS ((char *, int));
+
+static void
+es1800_transparent PARAMS ((char *, int));
+
+static void
+es1800_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+es1800_load PARAMS ((char *, int));
+
+static void
+es1800_kill PARAMS ((void));
+
+static int
+verify_break PARAMS ((int));
+
+static int
+es1800_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static int
+es1800_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+static void
+es1800_files_info PARAMS ((struct target_ops *));
+
+static int
+es1800_xfer_inferior_memory PARAMS ((CORE_ADDR, char *, int, int,
+ struct target_ops *));
+
+static void
+es1800_prepare_to_store PARAMS ((void));
+
+static int es1800_wait PARAMS ((int, struct target_waitstatus *));
+
+static void es1800_resume PARAMS ((int, int, enum target_signal));
+
+static void
+es1800_detach PARAMS ((char *, int));
+
+static void
+es1800_attach PARAMS ((char *, int));
+
+static int
+damn_b PARAMS ((char *));
+
+static void
+es1800_open PARAMS ((char *, int));
+
+static void
+es1800_timer PARAMS ((void));
+
+static void
+es1800_reset PARAMS ((char *));
+
+static void
+es1800_request_quit PARAMS ((void));
+
+static int
+readchar PARAMS ((void));
+
+static void
+expect PARAMS ((char *, int));
+
+static void
+expect_prompt PARAMS ((void));
+
+static void
+download PARAMS ((FILE *, int, int));
+
+#if 0
+static void
+bfd_copy PARAMS ((bfd *, bfd *));
+#endif
+
+static void
+get_break_addr PARAMS ((int, CORE_ADDR *));
+
+static int
+fromhex PARAMS ((int));
+
+static int
+tohex PARAMS ((int));
+
+static void
+es1800_close PARAMS ((int));
+
+static void
+es1800_fetch_registers PARAMS ((void));
+
+static void
+es1800_fetch_register PARAMS ((int));
+
+static void
+es1800_store_register PARAMS ((int));
+
+static void
+es1800_read_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static void
+es1800_write_bytes PARAMS ((CORE_ADDR, char *, int));
+
+static void
+send_with_reply PARAMS ((char *, char *, int));
+
+static void
+send_command PARAMS ((char *));
+
+static void
+send PARAMS ((char *));
+
+static void
+getmessage PARAMS ((char *, int));
+
+static void
+es1800_mourn_inferior PARAMS ((void));
+
+static void
+es1800_create_break_insn PARAMS ((char *, int));
+
+static void
+es1800_init_break PARAMS ((char *, int));
+
+/* Local variables */
+
+/* FIXME: Convert this to use "set remotedebug" instead. */
+#define LOG_FILE "es1800.log"
+#if defined (LOG_FILE)
+static FILE *log_file;
+#endif
+
+extern struct target_ops es1800_ops; /* Forward decl */
+extern struct target_ops es1800_child_ops; /* Forward decl */
+
+static int kiodebug;
+static int timeout = 100;
+static char *savename; /* Name of i/o device used */
+static serial_ttystate es1800_saved_ttystate;
+static int es1800_fc_save; /* Save fcntl state */
+
+/* indicates that the emulator uses 32-bit data-adress (68020-mode)
+ instead of 24-bit (68000 -mode) */
+
+static int m68020;
+
+#define MODE (m68020 ? "M68020" : "M68000" )
+#define ES1800_BREAK_VEC (0xf)
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so that
+ es1800_open knows that we don't have a file open when the program
+ starts. */
+
+static serial_t es1800_desc = NULL;
+
+#define PBUFSIZ 1000
+#define HDRLEN sizeof("@.BAAAAAAAA=$VV\r")
+
+/* Maximum number of bytes to read/write at once. The value here
+ is chosen to fill up a packet. */
+
+#define MAXBUFBYTES ((PBUFSIZ-150)*16/75 )
+
+static int es1800_break_vec = 0;
+static char es1800_break_insn[2];
+static long es1800_break_address;
+static void (*old_sigint)(); /* Old signal-handler for sigint */
+static jmp_buf interrupt;
+
+/* Local signalhandler to allow breaking tranfers or program run.
+ Rely on global variables: old_sigint(), interrupt */
+
+static void
+es1800_request_quit ()
+{
+ /* restore original signalhandler */
+ signal (SIGINT, old_sigint);
+ longjmp (interrupt, 1);
+}
+
+
+/* Reset emulator.
+ Sending reset character(octal 32) to emulator.
+ quit - return to '(esgdb)' prompt or continue */
+
+static void
+es1800_reset (quit)
+ char *quit;
+{
+ char buf[80];
+
+ if (quit)
+ {
+ printf ("\nResetting emulator... ");
+ }
+ strcpy (buf, "\032");
+ send (buf);
+ expect_prompt ();
+ if (quit)
+ {
+ error ("done\n");
+ }
+}
+
+
+/* Open a connection to a remote debugger and push the new target
+ onto the stack. Check if the emulator is responding and find out
+ what kind of processor the emulator is connected to.
+ Initiate the breakpoint handling in the emulator.
+
+ name - the filename used for communication (ex. '/dev/tta')
+ from_tty - says whether to be verbose or not */
+
+static void
+es1800_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ char buf[PBUFSIZ];
+ char *p;
+ int i, fcflag;
+
+ m68020 = 0;
+
+ if (!name) /* no device name given in target command */
+ {
+ error_no_arg ("serial port device name");
+ }
+
+ target_preopen (from_tty);
+ es1800_close (0);
+
+ /* open the device and configure it for communication */
+
+#ifndef DEBUG_STDIN
+
+ es1800_desc = SERIAL_OPEN (name);
+ if (es1800_desc == NULL)
+ {
+ perror_with_name (name);
+ }
+ savename = savestring (name, strlen (name));
+
+ es1800_saved_ttystate = SERIAL_GET_TTY_STATE (es1800_desc);
+
+ if ((fcflag = fcntl (es1800_desc->fd, F_GETFL, 0)) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+ es1800_fc_save = fcflag;
+
+ fcflag = (fcflag & (FREAD | FWRITE)); /* mask out any funny stuff */
+ if (fcntl (es1800_desc->fd, F_SETFL, fcflag) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (es1800_desc, baud_rate))
+ {
+ SERIAL_CLOSE (es1800_desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW (es1800_desc);
+
+ /* If there is something sitting in the buffer we might take it as a
+ response to a command, which would be bad. */
+ SERIAL_FLUSH_INPUT (es1800_desc);
+
+#endif /* DEBUG_STDIN */
+
+ push_target (&es1800_ops); /* Switch to using remote target now */
+ if (from_tty)
+ {
+ printf ("Remote ES1800 debugging using %s\n", name);
+ }
+
+#if defined (LOG_FILE)
+
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ {
+ perror_with_name (LOG_FILE);
+ }
+
+#endif /* LOG_FILE */
+
+ /* Hello? Are you there?, also check mode */
+
+ /* send_with_reply( "DB 0 TO 1", buf, sizeof(buf)); */
+ /* for (p = buf, i = 0; *p++ =='0';) */ /* count the number of zeros */
+ /* i++; */
+
+ send ("\032");
+ getmessage (buf, sizeof (buf)); /* send reset character */
+
+ if (from_tty)
+ {
+ printf ("Checking mode.... ");
+ }
+ /* m68020 = (i==8); */ /* if eight zeros then we are in m68020 mode */
+
+ /* What kind of processor am i talking to ?*/
+ p = buf;
+ while (*p++ != '\n') {;}
+ while (*p++ != '\n') {;}
+ while (*p++ != '\n') {;}
+ for (i = 0; i < 20; i++, p++) {;}
+ m68020 = !strncmp (p, "68020", 5);
+ if (from_tty)
+ {
+ printf ("You are in %s(%c%c%c%c%c)-mode\n", MODE, p[0], p[1], p[2],
+ p[3], p[4]);
+ }
+
+ /* if no init_break statement is present in .gdb file we have to check
+ whether to download a breakpoint routine or not */
+
+#if 0
+ if ((es1800_break_vec == 0) || (verify_break (es1800_break_vec) != 0)
+ && query ("No breakpoint routine in ES 1800 emulator!\nDownload a breakpoint routine to the emulator? "))
+ {
+ CORE_ADDR memaddress;
+ printf ("Give the start address of the breakpoint routine: ");
+ scanf ("%li", &memaddress);
+ es1800_init_break ((es1800_break_vec ? es1800_break_vec :
+ ES1800_BREAK_VEC), memaddress);
+ }
+#endif
+
+}
+
+/* Close out all files and local state before this target loses control.
+ quitting - are we quitting gdb now? */
+
+static void
+es1800_close (quitting)
+ int quitting;
+{
+ if (es1800_desc != NULL)
+ {
+ printf ("\nClosing connection to emulator...\n");
+ if (SERIAL_SET_TTY_STATE (es1800_desc, es1800_saved_ttystate) < 0)
+ print_sys_errmsg ("warning: unable to restore tty state", errno);
+ fcntl (es1800_desc->fd, F_SETFL, es1800_fc_save);
+ SERIAL_CLOSE (es1800_desc);
+ es1800_desc = NULL;
+ }
+ if (savename != NULL)
+ {
+ free (savename);
+ }
+ savename = NULL;
+
+#if defined (LOG_FILE)
+
+ if (log_file != NULL)
+ {
+ if (ferror (log_file))
+ {
+ printf ("Error writing log file.\n");
+ }
+ if (fclose (log_file) != 0)
+ {
+ printf ("Error closing log file.\n");
+ }
+ log_file = NULL;
+ }
+
+#endif /* LOG_FILE */
+
+}
+
+/* Attaches to a process on the target side
+ proc_id - the id of the process to be attached.
+ from_tty - says whether to be verbose or not */
+
+static void
+es1800_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ error ("Cannot attach to pid %s, this feature is not implemented yet.",
+ args);
+}
+
+
+/* Takes a program previously attached to and detaches it.
+ We better not have left any breakpoints
+ in the program or it'll die when it hits one.
+ Close the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb.
+
+ args - arguments given to the 'detach' command
+ from_tty - says whether to be verbose or not */
+
+static void
+es1800_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ {
+ error ("Argument given to \"detach\" when remotely debugging.");
+ }
+ pop_target ();
+ if (from_tty)
+ {
+ printf ("Ending es1800 remote debugging.\n");
+ }
+}
+
+
+/* Tell the remote machine to resume.
+ step - single-step or run free
+ siggnal - the signal value to be given to the target (0 = no signal) */
+
+static void
+es1800_resume (pid, step, siggnal)
+ int pid;
+ int step;
+ enum target_signal siggnal;
+{
+ char buf[PBUFSIZ];
+
+ if (siggnal)
+ {
+ error ("Can't send signals to a remote system.");
+ }
+ if (step)
+ {
+ strcpy (buf,"STP\r");
+ send (buf);
+ }
+ else
+ {
+ send_command ("RBK");
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would.
+ status - */
+
+static int
+es1800_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ unsigned char buf[PBUFSIZ];
+ int old_timeout = timeout;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = 0; /* Don't time out -- user program is running. */
+ if (!setjmp (interrupt))
+ {
+ old_sigint = signal (SIGINT, es1800_request_quit);
+ while (1)
+ {
+ getmessage (buf, sizeof(buf));
+ if (strncmp ( buf, "\r\n* BREAK *", 11) == 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ send_command ("STP"); /* Restore stack and PC and such */
+ if (m68020)
+ {
+ send_command ("STP");
+ }
+ break;
+ }
+ if (strncmp (buf, "STP\r\n ", 6) == 0)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ }
+ if (buf[strlen (buf) - 2] == 'R')
+ {
+ printf ("Unexpected emulator reply: \n%s\n", buf);
+ }
+ else
+ {
+ printf ("Unexpected stop: \n%s\n", buf);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_QUIT;
+ break;
+ }
+ }
+ }
+ else
+ {
+ fflush (stdin);
+ printf ("\nStopping emulator...");
+ if (!setjmp (interrupt))
+ {
+ old_sigint = signal (SIGINT, es1800_request_quit);
+ send_command ("STP");
+ printf (" emulator stopped\n");
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_INT;
+ }
+ else
+ {
+ fflush (stdin);
+ es1800_reset ((char*) 1);
+ }
+ }
+ signal (SIGINT, old_sigint);
+ timeout = old_timeout;
+ return (0);
+}
+
+
+/* Fetch register values from remote machine.
+ regno - the register to be fetched (fetch all registers if -1) */
+
+static void
+es1800_fetch_register (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ int k;
+ int r;
+ char *p;
+ static char regtab[18][4] =
+ {
+ "D0 ", "D1 ", "D2 ", "D3 ", "D4 ", "D5 ", "D6 ", "D7 ",
+ "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ", "A6 ", "SSP",
+ "SR ", "PC "
+ };
+
+ if ((regno < 15) || (regno == 16) || (regno == 17))
+ {
+ r = regno * 4;
+ send_with_reply (regtab[regno], buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if ((p[k*2 + 1] == 0) || (p[k*2 + 2] == 0))
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = (fromhex (p[k*2 + 1]) * 16) + fromhex (p[k*2 + 2]);
+ }
+ }
+ else
+ {
+ es1800_fetch_registers ();
+ }
+}
+
+/* Read the remote registers into REGISTERS.
+ Always fetches all registers. */
+
+static void
+es1800_fetch_registers ()
+{
+ char buf[PBUFSIZ];
+ char SR_buf[PBUFSIZ];
+ int i;
+ int k;
+ int r;
+ char *p;
+
+ send_with_reply ("DR", buf, sizeof (buf));
+
+ /* Reply is edited to a string that describes registers byte by byte,
+ each byte encoded as two hex characters. */
+
+ p = buf;
+ r = 0;
+
+ /* parsing row one - D0-D7-registers */
+
+ while (*p++ != '\n') {;}
+ for (i = 4; i < 70; i += (i == 39 ? 3 : 1))
+ {
+ for (k = 0; k < 4; k++)
+ {
+ if (p[i+0] == 0 || p[i+1] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = (fromhex (p[i+0]) * 16) + fromhex (p[i+1]);
+ i += 2;
+ }
+ }
+ p += i;
+
+ /* parsing row two - A0-A6-registers */
+
+ while (*p++ != '\n') {;}
+ for (i = 4; i < 61; i += (i == 39 ? 3 : 1))
+ {
+ for (k = 0; k < 4; k++)
+ {
+ if (p[i+0] == 0 || p[i+1] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = (fromhex (p[i+0])) * 16 + fromhex (p[i+1]);
+ i += 2;
+ }
+ }
+ p += i;
+
+ while (*p++ != '\n') {;}
+
+ /* fetch SSP-, SR- and PC-registers */
+
+ /* first - check STATUS-word and decide which stackpointer to use */
+
+ send_with_reply ("SR", SR_buf, sizeof (SR_buf));
+ p = SR_buf;
+ p += 5;
+
+ if (m68020)
+ {
+ if (*p == '3') /* use masterstackpointer MSP */
+ {
+ send_with_reply ("MSP", buf, sizeof (buf));
+ }
+ else if (*p == '2') /* use interruptstackpointer ISP */
+ {
+ send_with_reply ("ISP", buf, sizeof (buf));
+ }
+ else /* use userstackpointer USP */
+ {
+ send_with_reply ("USP", buf, sizeof (buf));
+ }
+ p = buf;
+ for (k = 0; k<4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+
+ p = SR_buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] =
+ fromhex (SR_buf[k*2+1]) * 16 + fromhex (SR_buf[k*2+2]);
+ }
+ send_with_reply ("PC", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k<4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+ }
+ else /* 68000-mode */
+ {
+ if (*p == '2') /* use supervisorstackpointer SSP */
+ {
+ send_with_reply ("SSP", buf, sizeof (buf));
+ }
+ else /* use userstackpointer USP */
+ {
+ send_with_reply ("USP", buf, sizeof (buf));
+ }
+
+ /* fetch STACKPOINTER */
+
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2 + 1] == 0 || p[k*2 + 2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+
+ /* fetch STATUS */
+
+ p = SR_buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] =
+ fromhex (SR_buf[k*2+1]) * 16 + fromhex (SR_buf[k*2+2]);
+ }
+
+ /* fetch PC */
+
+ send_with_reply ("PC", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if (p[k*2+1] == 0 || p[k*2+2] == 0)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ registers[r++] = fromhex (buf[k*2+1]) * 16 + fromhex (buf[k*2+2]);
+ }
+ }
+}
+
+/* Store register value, located in REGISTER, on the target processor.
+ regno - the register-number of the register to store
+ (-1 means store them all)
+ FIXME: Return errno value. */
+
+static void
+es1800_store_register(regno)
+ int regno;
+{
+
+ static char regtab[18][4] =
+ {
+ "D0 ", "D1 ", "D2 ", "D3 ", "D4 ", "D5 ", "D6 ", "D7 ",
+ "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ", "A6 ", "SSP",
+ "SR ", "PC "
+ };
+
+ char buf[PBUFSIZ];
+ char SR_buf[PBUFSIZ];
+ char stack_pointer[4];
+ char *p;
+ int i;
+ int j;
+ int k;
+ unsigned char *r;
+
+ r = (unsigned char *) registers;
+
+ if (regno == -1) /* write all registers */
+ {
+ j = 0;
+ k = 18;
+ }
+ else /* write one register */
+ {
+ j = regno;
+ k = regno+1;
+ r += regno * 4;
+ }
+
+ if ((regno == -1) || (regno == 15))
+ {
+ /* fetch current status */
+ send_with_reply ("SR", SR_buf, sizeof (SR_buf));
+ p = SR_buf;
+ p += 5;
+ if (m68020)
+ {
+ if (*p == '3') /* use masterstackpointer MSP */
+ {
+ strcpy (stack_pointer,"MSP");
+ }
+ else
+ {
+ if (*p == '2') /* use interruptstackpointer ISP */
+ {
+ strcpy (stack_pointer,"ISP");
+ }
+ else
+ {
+ strcpy (stack_pointer,"USP"); /* use userstackpointer USP */
+ }
+ }
+ }
+ else /* 68000-mode */
+ {
+ if (*p == '2') /* use supervisorstackpointer SSP */
+ {
+ strcpy (stack_pointer,"SSP");
+ }
+ else
+ {
+ strcpy (stack_pointer,"USP");/* use userstackpointer USP */
+ }
+ }
+ strcpy (regtab[15],stack_pointer);
+ }
+
+ for (i = j; i<k; i++)
+ {
+ buf[0] = regtab[i][0];
+ buf[1] = regtab[i][1];
+ buf[2] = regtab[i][2];
+ buf[3] = '=';
+ buf[4] = '$';
+ buf[5] = tohex ((*r >> 4) & 0x0f);
+ buf[6] = tohex (*r++ & 0x0f);
+ buf[7] = tohex ((*r >> 4) & 0x0f);
+ buf[8] = tohex (*r++ & 0x0f);
+ buf[9] = tohex ((*r >> 4) & 0x0f);
+ buf[10] = tohex (*r++ & 0x0f);
+ buf[11] = tohex ((*r >> 4) & 0x0f);
+ buf[12] = tohex (*r++ & 0x0f);
+ buf[13] = 0;
+
+ send_with_reply (buf, buf, sizeof (buf)); /* FIXME, reply not used? */
+ }
+}
+
+
+/* Prepare to store registers. */
+
+static void
+es1800_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+/* Convert hex digit A to a number. */
+
+static int
+fromhex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ {
+ return a - '0';
+ }
+ else if (a >= 'a' && a <= 'f')
+ {
+ return a - 'a' + 10;
+ }
+ else if (a >= 'A' && a <= 'F')
+ {
+ return a - 'A' + 10;
+ }
+ else
+ {
+ error ("Reply contains invalid hex digit");
+ }
+ return (-1);
+}
+
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ {
+ return ('0' + nib);
+ }
+ else
+ {
+ return ('A' + nib - 10);
+ }
+}
+
+/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+ to or from debugger address MYADDR. Write to inferior if WRITE is
+ nonzero. Returns length of data written or read; 0 for error.
+
+ memaddr - the target's address
+ myaddr - gdb's address
+ len - number of bytes
+ write - write if != 0 otherwise read */
+
+static int
+es1800_xfer_inferior_memory (memaddr, myaddr, len, write, tops)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *tops; /* Unused */
+{
+ int origlen = len;
+ int xfersize;
+
+ while (len > 0)
+ {
+ xfersize = len > MAXBUFBYTES ? MAXBUFBYTES : len;
+ if (write)
+ {
+ es1800_write_bytes (memaddr, myaddr, xfersize);
+ }
+ else
+ {
+ es1800_read_bytes (memaddr, myaddr, xfersize);
+ }
+ memaddr += xfersize;
+ myaddr += xfersize;
+ len -= xfersize;
+ }
+ return (origlen); /* no error possible */
+}
+
+
+/* Write memory data directly to the emulator.
+ This does not inform the data cache; the data cache uses this.
+ MEMADDR is the address in the remote memory space.
+ MYADDR is the address of the buffer in our space.
+ LEN is the number of bytes.
+
+ memaddr - the target's address
+ myaddr - gdb's address
+ len - number of bytes */
+
+static void
+es1800_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ p = myaddr;
+ for (i = 0; i < len; i++)
+ {
+ sprintf (buf, "@.B$%x=$%x", memaddr+i, (*p++) & 0xff);
+ send_with_reply (buf, buf, sizeof (buf)); /* FIXME send_command? */
+ }
+}
+
+
+/* Read memory data directly from the emulator.
+ This does not use the data cache; the data cache uses this.
+
+ memaddr - the target's address
+ myaddr - gdb's address
+ len - number of bytes */
+
+static void
+es1800_read_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ static int DB_tab[16] = {8,11,14,17,20,23,26,29,34,37,40,43,46,49,52,55};
+ char buf[PBUFSIZ];
+ int i;
+ int low_addr;
+ char *p;
+ char *b;
+
+ if (len > PBUFSIZ / 2 - 1)
+ {
+ abort ();
+ }
+
+ if (len == 1) /* The emulator does not like expressions like: */
+ {
+ len = 2; /* DB.B $20018 TO $20018 */
+ }
+
+ /* Reply describes registers byte by byte, each byte encoded as two hex
+ characters. */
+
+ sprintf (buf, "DB.B $%x TO $%x", memaddr, memaddr+len-1);
+ send_with_reply (buf, buf, sizeof (buf));
+ b = buf;
+ low_addr = memaddr&0x0f;
+ for (i = low_addr; i < low_addr + len; i++)
+ {
+ if ((!(i % 16)) && i)
+ { /* if (i = 16,32,48) */
+ while (*p++!='\n') {;}
+ b = p;
+ }
+ p = b + DB_tab[i%16] + (m68020 ? 2 : 0);
+ if (p[0] == 32 || p[1] == 32)
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ myaddr[i-low_addr] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ }
+}
+
+/* Information about the current target */
+
+static void
+es1800_files_info (tops)
+ struct target_ops *tops; /* Unused */
+{
+ printf ("ES1800 Attached to %s at %d baud in %s mode\n", savename, 19200,
+ MODE);
+}
+
+
+/* We read the contents of the target location and stash it,
+ then overwrite it with a breakpoint instruction.
+
+ addr - is the target location in the target machine.
+ contents_cache - is a pointer to memory allocated for saving the target contents.
+ It is guaranteed by the caller to be long enough to save sizeof
+ BREAKPOINT bytes.
+
+ FIXME: This size is target_arch dependent and should be available in
+ the target_arch transfer vector, if we ever have one... */
+
+static int
+es1800_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int val;
+
+ val = target_read_memory (addr, contents_cache, sizeof (es1800_break_insn));
+
+ if (val == 0)
+ {
+ val = target_write_memory (addr, es1800_break_insn,
+ sizeof (es1800_break_insn));
+ }
+
+ return (val);
+}
+
+
+/* Write back the stashed instruction
+
+ addr - is the target location in the target machine.
+ contents_cache - is a pointer to memory allocated for saving the target contents.
+ It is guaranteed by the caller to be long enough to save sizeof
+ BREAKPOINT bytes. */
+
+static int
+es1800_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+
+ return (target_write_memory (addr, contents_cache,
+ sizeof (es1800_break_insn)));
+}
+
+/* create_break_insn ()
+ Primitive datastructures containing the es1800 breakpoint instruction */
+
+static void
+es1800_create_break_insn (ins, vec)
+ char *ins;
+ int vec;
+{
+ if (vec == 15)
+ {
+ ins[0] = 0x4e;
+ ins[1] = 0x4f;
+ }
+}
+
+
+/* verify_break ()
+ Seach for breakpoint routine in emulator memory.
+ returns non-zero on failure
+ vec - trap vector used for breakpoints */
+
+static int
+verify_break (vec)
+ int vec;
+{
+ CORE_ADDR memaddress;
+ char buf[8];
+ char *instr = "NqNqNqNs"; /* breakpoint routine */
+ int status;
+
+ get_break_addr (vec, &memaddress);
+
+ if (memaddress)
+ {
+ status = target_read_memory (memaddress, buf, 8);
+ if (status != 0)
+ {
+ memory_error (status, memaddress);
+ }
+ return (STRCMP (instr, buf));
+ }
+ return (-1);
+}
+
+
+/* get_break_addr ()
+ find address of breakpint routine
+ vec - trap vector used for breakpoints
+ addrp - store the address here */
+
+static void
+get_break_addr (vec, addrp)
+ int vec;
+ CORE_ADDR *addrp;
+{
+ CORE_ADDR memaddress = 0;
+ int status;
+ int k;
+ char buf[PBUFSIZ];
+ char base_addr[4];
+ char *p;
+
+ if (m68020)
+ {
+ send_with_reply ("VBR ", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if ((p[k*2 + 1] == 0) || (p[k*2 + 2] == 0))
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ base_addr[k] = (fromhex (p[k*2 + 1]) * 16) + fromhex (p[k*2 + 2]);
+ }
+ /* base addr of exception vector table */
+ memaddress = *((CORE_ADDR *) base_addr);
+ }
+
+ memaddress += (vec + 32) * 4; /* address of trap vector */
+ status = target_read_memory (memaddress, (char *) addrp, 4);
+ if (status != 0)
+ {
+ memory_error (status, memaddress);
+ }
+}
+
+
+/* Kill an inferior process */
+
+static void
+es1800_kill ()
+{
+ if (inferior_pid != 0)
+ {
+ inferior_pid = 0;
+ es1800_mourn_inferior ();
+ }
+}
+
+
+/* Load a file to the ES1800 emulator.
+ Converts the file from a.out format into Extended Tekhex format
+ before the file is loaded.
+ Also loads the trap routine, and sets the ES1800 breakpoint on it
+ filename - the a.out to be loaded
+ from_tty - says whether to be verbose or not
+ FIXME Uses emulator overlay memory for trap routine */
+
+static void
+es1800_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+
+ FILE *instream;
+ char loadname[15];
+ char buf[160];
+ struct cleanup *old_chain;
+ int es1800_load_format = 5;
+
+ if (es1800_desc == NULL)
+ {
+ printf ("No emulator attached, type emulator-command first\n");
+ return;
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ switch (es1800_load_format)
+ {
+ case 2: /* Extended Tekhex */
+ if (from_tty)
+ {
+ printf ("Converting \"%s\" to Extended Tekhex Format\n", filename);
+ }
+ sprintf (buf, "tekhex %s", filename);
+ system (buf);
+ sprintf (loadname, "out.hex");
+ break;
+
+ case 5: /* Motorola S-rec */
+ if (from_tty)
+ {
+ printf ("Converting \"%s\" to Motorola S-record format\n",
+ filename);
+ }
+ /* in the future the source code in copy (part of binutils-1.93) will
+ be included in this file */
+ sprintf (buf,
+ "copy -s \"a.out-sunos-big\" -d \"srec\" %s /tmp/out.hex",
+ filename);
+ system (buf);
+ sprintf (loadname, "/tmp/out.hex");
+ break;
+
+ default:
+ error ("Downloading format not defined\n");
+ }
+
+ breakpoint_init_inferior ();
+ inferior_pid = 0;
+ if (from_tty)
+ {
+ printf ("Downloading \"%s\" to the ES 1800\n",filename);
+ }
+ if ((instream = fopen (loadname, "r")) == NULL)
+ {
+ perror_with_name ("fopen:");
+ }
+
+ old_chain = make_cleanup (fclose, instream);
+ immediate_quit++;
+
+ es1800_reset (0);
+
+ download (instream, from_tty, es1800_load_format);
+
+ /* if breakpoint routine is not present anymore we have to check
+ whether to download a new breakpoint routine or not */
+
+ if ((verify_break (es1800_break_vec) != 0)
+ && query ("No breakpoint routine in ES 1800 emulator!\nDownload a breakpoint routine to the emulator? "))
+ {
+ char buf[128];
+ printf ("Using break vector 0x%x\n", es1800_break_vec);
+ sprintf (buf, "0x%x ", es1800_break_vec);
+ printf ("Give the start address of the breakpoint routine: ");
+ fgets (buf + strlen (buf), sizeof (buf) - strlen (buf), stdin);
+ es1800_init_break (buf, 0);
+ }
+
+ do_cleanups (old_chain);
+ expect_prompt ();
+ readchar (); /* FIXME I am getting a ^G = 7 after the prompt */
+ printf ("\n");
+
+ if (fclose (instream) == EOF)
+ {
+ ;
+ }
+
+ if (es1800_load_format != 2)
+ {
+ sprintf (buf, "/usr/bin/rm %s", loadname);
+ system (buf);
+ }
+
+ symbol_file_command (filename, from_tty); /* reading symbol table */
+ immediate_quit--;
+}
+
+#if 0
+
+#define NUMCPYBYTES 20
+
+static void
+bfd_copy (from_bfd, to_bfd)
+ bfd *from_bfd;
+ bfd *to_bfd;
+{
+ asection *p, *new;
+ int i;
+ char buf[NUMCPYBYTES];
+
+ for (p = from_bfd->sections; p != NULL; p = p->next)
+ {
+ printf (" Copying section %s. Size = %x.\n", p->name, p->_cooked_size);
+ printf (" vma = %x, offset = %x, output_sec = %x\n",
+ p->vma, p->output_offset, p->output_section);
+ new = bfd_make_section (to_bfd, p->name);
+ if (p->_cooked_size &&
+ !bfd_set_section_size (to_bfd, new, p->_cooked_size))
+ {
+ error ("Wrong BFD size!\n");
+ }
+ if (!bfd_set_section_flags (to_bfd, new, p->flags))
+ {
+ error ("bfd_set_section_flags");
+ }
+ new->vma = p->vma;
+
+ for (i = 0; (i + NUMCPYBYTES) < p->_cooked_size ; i += NUMCPYBYTES)
+ {
+ if (!bfd_get_section_contents (from_bfd, p, (PTR) buf, (file_ptr) i,
+ (bfd_size_type) NUMCPYBYTES))
+ {
+ error ("bfd_get_section_contents\n");
+ }
+ if (!bfd_set_section_contents (to_bfd, new, (PTR) buf, (file_ptr) i,
+ (bfd_size_type) NUMCPYBYTES))
+ {
+ error ("bfd_set_section_contents\n");
+ }
+ }
+ bfd_get_section_contents (from_bfd, p, (PTR) buf, (file_ptr) i,
+ (bfd_size_type) (p->_cooked_size - i));
+ bfd_set_section_contents (to_bfd, new, (PTR) buf,(file_ptr) i,
+ (bfd_size_type) (p->_cooked_size - i));
+ }
+}
+
+#endif
+
+/* Start an process on the es1800 and set inferior_pid to the new
+ process' pid.
+ execfile - the file to run
+ args - arguments passed to the program
+ env - the environment vector to pass */
+
+static void
+es1800_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+ int pid;
+#if 0
+ struct expression *expr;
+ register struct cleanup *old_chain = 0;
+ register value val;
+#endif
+
+ if (args && *args)
+ {
+ error ("Can't pass arguments to remote ES1800 process");
+ }
+
+#if 0
+ if (query ("Use 'start' as entry point? "))
+ {
+ expr = parse_c_expression ("start");
+ old_chain = make_cleanup (free_current_contents, &expr);
+ val = evaluate_expression (expr);
+ entry_pt = (val->location).address;
+ }
+ else
+ {
+ printf ("Enter the program's entry point (in hexadecimal): ");
+ scanf ("%x", &entry_pt);
+ }
+#endif
+
+ if (execfile == 0 || exec_bfd == 0)
+ {
+ error ("No exec file specified");
+ }
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ pid = 42;
+
+ /* Now that we have a child process, make it our target. */
+
+ push_target (&es1800_child_ops);
+
+ /* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ inferior_pid = pid; /* Needed for wait_for_inferior below */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+
+ target_terminal_inferior ();
+
+ /* remote_start (args); */
+ /* trap_expected = 0; */
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR) entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+
+}
+
+
+/* The process has died, clean up. */
+
+static void
+es1800_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&es1800_child_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+/* ES1800-protocol specific routines */
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately.
+ string - the string to expect
+ nowait - break out if string not the emulator's first respond otherwise
+ read until string is found (== 0) */
+
+static void
+expect (string, nowait)
+ char *string;
+ int nowait;
+{
+ char c;
+ char *p = string;
+
+ immediate_quit++;
+ while (1)
+ {
+ c = readchar ();
+ if (isalpha (c))
+ {
+ c = toupper (c);
+ }
+ if (c == toupper (*p))
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit--;
+ return;
+ }
+ }
+ else if (!nowait)
+ {
+ p = string;
+ }
+ else
+ {
+ printf ("\'%s\' expected\n" , string);
+ printf ("char %d is %d", p - string, c);
+ error ("\n" );
+ }
+ }
+}
+
+/* Keep discarding input until we see the prompt. */
+
+static void
+expect_prompt ()
+{
+ expect (">", 0);
+}
+
+
+/* Read one character */
+
+#ifdef DEBUG_STDIN
+
+/* read from stdin */
+
+static int
+readchar ()
+{
+ char buf[1];
+
+ buf[0] = '\0';
+ printf ("readchar, give one character\n");
+ read (0, buf, 1);
+
+#if defined (LOG_FILE)
+ putc (buf[0] & 0x7f, log_file);
+#endif
+
+ return (buf[0] & 0x7f);
+}
+
+#else /* !DEBUG_STDIN */
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+
+static int
+readchar ()
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (es1800_desc, timeout);
+
+ /* FIXME: doing an error() here will probably cause trouble, at least if from
+ es1800_wait. */
+ if (ch == SERIAL_TIMEOUT)
+ error ("Timeout reading from remote system.");
+ else if (ch == SERIAL_ERROR)
+ perror_with_name ("remote read");
+
+#if defined (LOG_FILE)
+ putc (ch & 0x7f, log_file);
+ fflush (log_file);
+#endif
+
+ return (ch);
+}
+
+#endif /* DEBUG_STDIN */
+
+
+/* Send a command to the emulator and save the reply.
+ Report an error if we get an error reply.
+ string - the es1800 command
+ buf - containing the emulator reply on return
+ len - size of buf */
+
+static void
+send_with_reply (string, buf, len)
+ char *string, *buf;
+ int len;
+{
+ send (string);
+ SERIAL_WRITE (es1800_desc, "\r", 1);
+
+#ifndef DEBUG_STDIN
+ expect (string, 1);
+ expect ("\r\n", 0);
+#endif
+
+ getmessage (buf, len);
+}
+
+
+/* Send the command in STR to the emulator adding \r. check
+ the echo for consistency.
+ string - the es1800 command */
+
+static void
+send_command (string)
+ char *string;
+{
+ send (string);
+ SERIAL_WRITE (es1800_desc, "\r", 1);
+
+#ifndef DEBUG_STDIN
+ expect (string, 0);
+ expect_prompt ();
+#endif
+
+}
+
+/* Send a string
+ string - the es1800 command */
+
+static void
+send (string)
+ char *string;
+{
+ if (kiodebug)
+ {
+ fprintf (stderr, "Sending: %s\n", string);
+ }
+ SERIAL_WRITE (es1800_desc, string, strlen (string));
+}
+
+
+/* Read a message from the emulator and store it in BUF.
+ buf - containing the emulator reply on return
+ len - size of buf */
+
+static void
+getmessage (buf, len)
+ char *buf;
+ int len;
+{
+ char *bp;
+ int c;
+ int prompt_found = 0;
+ extern kiodebug;
+
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush (log_file);
+#endif
+
+ bp = buf;
+ c = readchar ();
+ do
+ {
+ if (c)
+ {
+ if (len-- < 2) /* char and terminaling NULL */
+ {
+ error ("input buffer overrun\n");
+ }
+ *bp++ = c;
+ }
+ c = readchar ();
+ if ((c == '>') && (*(bp - 1) == ' '))
+ {
+ prompt_found = 1;
+ }
+ }
+ while (!prompt_found);
+ *bp = 0;
+
+ if (kiodebug)
+ {
+ fprintf (stderr,"message received :%s\n", buf);
+ }
+}
+
+static void
+download (instream, from_tty, format)
+FILE *instream;
+ int from_tty;
+ int format;
+{
+ char c;
+ char buf[160];
+ int i = 0;
+
+ send_command ("SET #2,$1A"); /* reset char = ^Z */
+ send_command ("SET #3,$11,$13"); /* XON XOFF */
+ if (format == 2)
+ {
+ send_command ("SET #26,#2");
+ }
+ else
+ {
+ send_command ("SET #26,#5"); /* Format=Extended Tekhex */
+ }
+ send_command ("DFB = $10");
+ send_command ("PUR");
+ send_command ("CES");
+ send ("DNL\r");
+ expect ("DNL", 1);
+ if (from_tty)
+ {
+ printf (" 0 records loaded...\r");
+ }
+ while (fgets (buf, 160, instream))
+ {
+ send (buf);
+ if (from_tty)
+ {
+ printf ("%5d\b\b\b\b\b",++i);
+ fflush (stdout);
+ }
+ if ((c = readchar ()) != 006)
+ {
+ error ("expected ACK");
+ }
+ }
+ if (from_tty)
+ {
+ printf ("- All");
+ }
+}
+
+/* Additional commands */
+
+#if defined (TIOCGETP) && defined (FNDELAY) && defined (EWOULDBLOCK)
+#define PROVIDE_TRANSPARENT
+#endif
+
+#ifdef PROVIDE_TRANSPARENT
+/* Talk directly to the emulator
+ FIXME, uses busy wait, and is SUNOS (or at least BSD) specific */
+
+/*ARGSUSED*/
+static void
+es1800_transparent (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int console;
+ struct sgttyb modebl;
+ int fcflag;
+ int cc;
+ struct sgttyb console_mode_save;
+ int console_fc_save;
+ int es1800_fc_save;
+ int inputcnt = 80;
+ char inputbuf[80];
+ int consolecnt = 0;
+ char consolebuf[80];
+ int es1800_cnt = 0;
+ char es1800_buf[80];
+ int i;
+
+ dont_repeat ();
+ if (es1800_desc == NULL)
+ {
+ printf ("No emulator attached, type emulator-command first\n");
+ return;
+ }
+
+ printf ("\n");
+ printf ("You are now communicating directly with the ES 1800 emulator.\n");
+ printf ("To leave this mode (transparent mode), press ^E.\n");
+ printf ("\n");
+ printf (" >");
+ fflush (stdout);
+
+ if ((console = open ("/dev/tty", O_RDWR)) == -1)
+ {
+ perror_with_name ("/dev/tty:");
+ }
+
+ if ((fcflag = fcntl (console, F_GETFL, 0)) == -1)
+ {
+ perror_with_name ("fcntl console");
+ }
+
+ console_fc_save = fcflag;
+ fcflag = fcflag | FNDELAY;
+
+ if (fcntl (console, F_SETFL, fcflag) == -1)
+ {
+ perror_with_name ("fcntl console");
+ }
+
+ if (ioctl (console, TIOCGETP, &modebl))
+ {
+ perror_with_name ("ioctl console");
+ }
+
+ console_mode_save = modebl;
+ modebl.sg_flags = RAW;
+
+ if (ioctl (console, TIOCSETP, &modebl))
+ {
+ perror_with_name ("ioctl console");
+ }
+
+ if ((fcflag = fcntl (es1800_desc->fd, F_GETFL, 0)) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+
+ es1800_fc_save = fcflag;
+ fcflag = fcflag | FNDELAY;
+
+ if (fcntl (es1800_desc->fd, F_SETFL, fcflag) == -1)
+ {
+ perror_with_name ("fcntl serial");
+ }
+
+ while (1)
+ {
+ cc = read (console, inputbuf, inputcnt);
+ if (cc != -1)
+ {
+ if ((*inputbuf & 0x7f) == 0x05)
+ {
+ break;
+ }
+ for (i = 0; i < cc; )
+ {
+ es1800_buf[es1800_cnt++] = inputbuf[i++];
+ }
+ if ((cc = SERIAL_WRITE (es1800_desc, es1800_buf, es1800_cnt)) == -1)
+ {
+ perror_with_name ("FEL! write:");
+ }
+ es1800_cnt -= cc;
+ if (es1800_cnt && cc)
+ {
+ for (i = 0; i < es1800_cnt; i++)
+ {
+ es1800_buf[i] = es1800_buf[cc+i];
+ }
+ }
+ }
+ else if (errno != EWOULDBLOCK)
+ {
+ perror_with_name ("FEL! read:");
+ }
+
+ cc = read (es1800_desc->fd,inputbuf,inputcnt);
+ if (cc != -1)
+ {
+ for (i = 0; i < cc; )
+ {
+ consolebuf[consolecnt++] = inputbuf[i++];
+ }
+ if ((cc = write (console,consolebuf,consolecnt)) == -1)
+ {
+ perror_with_name ("FEL! write:");
+ }
+ consolecnt -= cc;
+ if (consolecnt && cc)
+ {
+ for (i = 0; i < consolecnt; i++)
+ {
+ consolebuf[i] = consolebuf[cc+i];
+ }
+ }
+ }
+ else if (errno != EWOULDBLOCK)
+ {
+ perror_with_name ("FEL! read:");
+ }
+ }
+
+ console_fc_save = console_fc_save & !FNDELAY;
+ if (fcntl (console, F_SETFL, console_fc_save) == -1)
+ {
+ perror_with_name ("FEL! fcntl");
+ }
+
+ if (ioctl (console, TIOCSETP, &console_mode_save))
+ {
+ perror_with_name ("FEL! ioctl");
+ }
+
+ close (console);
+
+ if (fcntl (es1800_desc->fd, F_SETFL, es1800_fc_save) == -1)
+ {
+ perror_with_name ("FEL! fcntl");
+ }
+
+ printf ("\n");
+
+}
+#endif /* PROVIDE_TRANSPARENT */
+
+static void
+es1800_init_break (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ CORE_ADDR memaddress = 0;
+ char buf[PBUFSIZ];
+ char base_addr[4];
+ char *space_index;
+ char *p;
+ int k;
+
+ if (args == NULL)
+ {
+ error_no_arg ("a trap vector");
+ }
+
+ if (!(space_index = strchr (args, ' ')))
+ {
+ error ("Two arguments needed (trap vector and address of break routine).\n");
+ }
+
+ *space_index = '\0';
+
+ es1800_break_vec = strtol (args, (char **) NULL, 0);
+ es1800_break_address = parse_and_eval_address (space_index + 1);
+
+ es1800_create_break_insn (es1800_break_insn, es1800_break_vec);
+
+ if (m68020)
+ {
+ send_with_reply ("VBR ", buf, sizeof (buf));
+ p = buf;
+ for (k = 0; k < 4; k++)
+ {
+ if ((p[k*2 + 1] == 0) || (p[k*2 + 2] == 0))
+ {
+ error ("Emulator reply is too short: %s", buf);
+ }
+ base_addr[k] = (fromhex (p[k*2 + 1]) * 16) + fromhex (p[k*2 + 2]);
+ }
+ /* base addr of exception vector table */
+ memaddress = *((CORE_ADDR *) base_addr);
+ }
+
+ memaddress += (es1800_break_vec + 32) * 4; /* address of trap vector */
+
+ sprintf (buf, "@.L%lx=$%lx", memaddress, es1800_break_address);
+ send_command (buf); /* set the address of the break routine in the */
+ /* trap vector */
+
+ sprintf (buf, "@.L%lx=$4E714E71", es1800_break_address); /* NOP; NOP */
+ send_command (buf);
+ sprintf (buf, "@.L%lx=$4E714E73", es1800_break_address + 4); /* NOP; RTE */
+ send_command (buf);
+
+ sprintf (buf, "AC2=$%lx", es1800_break_address + 4);
+ /* breakpoint at es1800-break_address */
+ send_command (buf);
+ send_command ("WHEN AC2 THEN BRK"); /* ie in exception routine */
+
+ if (from_tty)
+ {
+ printf ("Breakpoint (trap $%x) routine at address: %lx\n",
+ es1800_break_vec, es1800_break_address);
+ }
+}
+
+static void
+es1800_child_open (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a child process.");
+}
+
+static void
+es1800_child_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ {
+ error ("Argument given to \"detach\" when remotely debugging.");
+ }
+
+ pop_target ();
+ if (from_tty)
+ {
+ printf ("Ending debugging the process %d.\n", inferior_pid);
+ }
+}
+
+
+/* Define the target subroutine names */
+
+struct target_ops es1800_ops =
+{
+ "es1800", /* to_shortname */
+ /* to_longname */
+ "Remote serial target in ES1800-emulator protocol",
+ /* to_doc */
+ "Remote debugging on the es1800 emulator via a serial line.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",
+ es1800_open, /* to_open */
+ es1800_close, /* to_close */
+ es1800_attach, /* to_attach */
+ es1800_detach, /* to_detach */
+ es1800_resume, /* to_resume */
+ NULL, /* to_wait */
+ NULL, /* to_fetch_registers */
+ NULL, /* to_store_registers */
+ es1800_prepare_to_store, /* to_prepare_to_store */
+ es1800_xfer_inferior_memory, /* to_xfer_memory */
+ es1800_files_info, /* to_files_info */
+ es1800_insert_breakpoint, /* to_insert_breakpoint */
+ es1800_remove_breakpoint, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ NULL, /* to_kill */
+ es1800_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ es1800_create_inferior, /* to_create_inferior */
+ NULL, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ core_stratum, /* to_stratum */
+ 0, /* to_next */
+ 0, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 0, /* to_has_stack */
+ 0, /* to_has_registers */
+ 0, /* to_has_execution */
+ NULL, /* to_sections */
+ NULL, /* to_sections_end */
+ OPS_MAGIC /* to_magic (always last) */
+};
+
+/* Define the target subroutine names */
+
+struct target_ops es1800_child_ops =
+{
+ "es1800_process", /* to_shortname */
+ /* to_longname */
+ "Remote serial target in ES1800-emulator protocol",
+ /* to_doc */
+ "Remote debugging on the es1800 emulator via a serial line.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",
+ es1800_child_open, /* to_open */
+ NULL, /* to_close */
+ es1800_attach, /* to_attach */
+ es1800_child_detach, /* to_detach */
+ es1800_resume, /* to_resume */
+ es1800_wait, /* to_wait */
+ es1800_fetch_register, /* to_fetch_registers */
+ es1800_store_register, /* to_store_registers */
+ es1800_prepare_to_store, /* to_prepare_to_store */
+ es1800_xfer_inferior_memory, /* to_xfer_memory */
+ es1800_files_info, /* to_files_info */
+ es1800_insert_breakpoint, /* to_insert_breakpoint */
+ es1800_remove_breakpoint, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ es1800_kill, /* to_kill */
+ es1800_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ es1800_create_inferior, /* to_create_inferior */
+ es1800_mourn_inferior, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ 0, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* to_sections */
+ NULL, /* to_sections_end */
+ OPS_MAGIC /* to_magic (always last) */
+};
+
+void
+_initialize_es1800 ()
+{
+ add_target (&es1800_ops);
+ add_target (&es1800_child_ops);
+#ifdef PROVIDE_TRANSPARENT
+ add_com ("transparent", class_support, es1800_transparent,
+ "Start transparent communication with the ES 1800 emulator.");
+#endif /* PROVIDE_TRANSPARENT */
+ add_com ("init_break", class_support, es1800_init_break,
+ "Download break routine and initialize break facility on ES 1800");
+}
diff --git a/contrib/gdb/gdb/remote-est.c b/contrib/gdb/gdb/remote-est.c
new file mode 100644
index 0000000..cfa9731
--- /dev/null
+++ b/contrib/gdb/gdb/remote-est.c
@@ -0,0 +1,174 @@
+/* Remote debugging interface for EST-300 ICE, for GDB
+ Copyright 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+ Written by Steve Chamberlain for Cygnus Support.
+ Re-written by Stu Grossman of Cygnus Support
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void est_open PARAMS ((char *args, int from_tty));
+
+static void
+est_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+
+ switch (regname[0])
+ {
+ case 'S':
+ if (regname[1] != 'R')
+ return;
+ regno = PS_REGNUM;
+ break;
+ case 'P':
+ if (regname[1] != 'C')
+ return;
+ regno = PC_REGNUM;
+ break;
+ case 'D':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + D0_REGNUM;
+ break;
+ case 'A':
+ if (regname[1] < '0' || regname[1] > '7')
+ return;
+ regno = regname[1] - '0' + A0_REGNUM;
+ break;
+ default:
+ return;
+ }
+
+ monitor_supply_register (regno, val);
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *est_regnames[NUM_REGS] =
+{
+ "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
+ "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
+ "SR", "PC",
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops est_ops;
+
+static char *est_inits[] = {"he\r", /* Resets the prompt, and clears repeated cmds */
+ NULL};
+
+static struct monitor_ops est_cmds =
+{
+ MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_NEED_REGDUMP_AFTER_CONT,
+ est_inits, /* Init strings */
+ "go\r", /* continue command */
+ "sidr\r", /* single step */
+ "\003", /* ^C interrupts the program */
+ "sb %x\r", /* set a breakpoint */
+ "rb %x\r", /* clear a breakpoint */
+ "rb\r", /* clear all breakpoints */
+ "bfb %x %x %x\r", /* fill (start end val) */
+ {
+ "smb %x %x\r", /* setmem.cmdb (addr, value) */
+ "smw %x %x\r", /* setmem.cmdw (addr, value) */
+ "sml %x %x\r", /* setmem.cmdl (addr, value) */
+ NULL, /* setmem.cmdll (addr, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL, /* setreg.term_cmd */
+ },
+ {
+ "dmb %x %x\r", /* getmem.cmdb (addr, len) */
+ "dmw %x %x\r", /* getmem.cmdw (addr, len) */
+ "dml %x %x\r", /* getmem.cmdl (addr, len) */
+ NULL, /* getmem.cmdll (addr, len) */
+ ": ", /* getmem.resp_delim */
+ NULL, /* getmem.term */
+ NULL, /* getmem.term_cmd */
+ },
+ {
+ "sr %s %x\r", /* setreg.cmd (name, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL /* setreg.term_cmd */
+ },
+ {
+ "dr %s\r", /* getreg.cmd (name) */
+ " = ", /* getreg.resp_delim */
+ NULL, /* getreg.term */
+ NULL /* getreg.term_cmd */
+ },
+ "dr\r", /* dump_registers */
+ "\\(\\w+\\) = \\([0-9a-fA-F]+\\)", /* register_pattern */
+ est_supply_register, /* supply_register */
+ NULL, /* load_routine (defaults to SRECs) */
+ "dl\r", /* download command */
+ "+", /* load response */
+ ">BKM>", /* monitor command prompt */
+ "\r", /* end-of-line terminator */
+ NULL, /* optional command terminator */
+ &est_ops, /* target operations */
+ SERIAL_1_STOPBITS, /* number of stop bits */
+ est_regnames, /* registers names */
+ MONITOR_OPS_MAGIC /* magic */
+ };
+
+static void
+est_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &est_cmds, from_tty);
+}
+
+void
+_initialize_est ()
+{
+ init_monitor_ops (&est_ops);
+
+ est_ops.to_shortname = "est";
+ est_ops.to_longname = "EST background debug monitor";
+ est_ops.to_doc = "Debug via the EST BDM.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ est_ops.to_open = est_open;
+
+ add_target (&est_ops);
+}
diff --git a/contrib/gdb/gdb/remote-hms.c b/contrib/gdb/gdb/remote-hms.c
new file mode 100644
index 0000000..2f43e20
--- /dev/null
+++ b/contrib/gdb/gdb/remote-hms.c
@@ -0,0 +1,1463 @@
+/* Remote debugging interface for Hitachi HMS Monitor Version 1.0
+ Copyright 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Steve Chamberlain
+ (sac@cygnus.com).
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "monitor.h"
+#include "serial.h"
+
+static void hms_open PARAMS ((char *args, int from_tty));
+
+static void
+hms_supply_register (regname, regnamelen, val, vallen)
+ char *regname;
+ int regnamelen;
+ char *val;
+ int vallen;
+{
+ int regno;
+
+ if (regnamelen != 2)
+ return;
+ if (regname[0] != 'P')
+ return;
+ /* We scan off all the registers in one go */
+
+ val = monitor_supply_register (PC_REGNUM, val);
+ /* Skip the ccr string */
+ while (*val != '=' && *val)
+ val++;
+
+ val = monitor_supply_register (CCR_REGNUM, val + 1);
+
+ /* Skip up to rest of regs */
+ while (*val != '=' && *val)
+ val++;
+
+ for (regno = 0; regno < 7; regno++)
+ {
+ val = monitor_supply_register (regno, val + 1);
+ }
+}
+
+/*
+ * This array of registers needs to match the indexes used by GDB. The
+ * whole reason this exists is because the various ROM monitors use
+ * different names than GDB does, and don't support all the
+ * registers either. So, typing "info reg sp" becomes a "r30".
+ */
+
+static char *hms_regnames[NUM_REGS] =
+{
+ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "CCR", "PC"
+};
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+
+static struct target_ops hms_ops;
+
+static char *hms_inits[] =
+{"\003", /* Resets the prompt, and clears repeated cmds */
+ NULL};
+
+static struct monitor_ops hms_cmds =
+{
+ MO_CLR_BREAK_USES_ADDR | MO_FILL_USES_ADDR | MO_GETMEM_NEEDS_RANGE,
+ hms_inits, /* Init strings */
+ "g\r", /* continue command */
+ "s\r", /* single step */
+ "\003", /* ^C interrupts the program */
+ "b %x\r", /* set a breakpoint */
+ "b - %x\r", /* clear a breakpoint */
+ "b -\r", /* clear all breakpoints */
+ "f %x %x %x\r", /* fill (start end val) */
+ {
+ "m.b %x=%x\r", /* setmem.cmdb (addr, value) */
+ "m.w %x=%x\r", /* setmem.cmdw (addr, value) */
+ NULL, /* setmem.cmdl (addr, value) */
+ NULL, /* setmem.cmdll (addr, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL, /* setreg.term_cmd */
+ },
+ {
+ "m.b %x %x\r", /* getmem.cmdb (addr, addr) */
+ "m.w %x %x\r", /* getmem.cmdw (addr, addr) */
+ NULL, /* getmem.cmdl (addr, addr) */
+ NULL, /* getmem.cmdll (addr, addr) */
+ ": ", /* getmem.resp_delim */
+ ">", /* getmem.term */
+ "\003", /* getmem.term_cmd */
+ },
+ {
+ "r %s=%x\r", /* setreg.cmd (name, value) */
+ NULL, /* setreg.resp_delim */
+ NULL, /* setreg.term */
+ NULL /* setreg.term_cmd */
+ },
+ {
+ "r %s\r", /* getreg.cmd (name) */
+ " (", /* getreg.resp_delim */
+ ":", /* getreg.term */
+ "\003", /* getreg.term_cmd */
+ },
+ "r\r", /* dump_registers */
+ "\\(\\w+\\)=\\([0-9a-fA-F]+\\)", /* register_pattern */
+ hms_supply_register, /* supply_register */
+ NULL, /* load_routine (defaults to SRECs) */
+ "tl\r", /* download command */
+ NULL, /* load response */
+ ">", /* monitor command prompt */
+ "\r", /* end-of-command delimitor */
+ NULL, /* optional command terminator */
+ &hms_ops, /* target operations */
+ SERIAL_1_STOPBITS, /* number of stop bits */
+ hms_regnames, /* registers names */
+ MONITOR_OPS_MAGIC /* magic */
+};
+
+static void
+hms_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ monitor_open (args, &hms_cmds, from_tty);
+}
+
+int write_dos_tick_delay;
+
+void
+_initialize_remote_hms ()
+{
+ init_monitor_ops (&hms_ops);
+
+ hms_ops.to_shortname = "hms";
+ hms_ops.to_longname = "Hitachi Microsystems H8/300 debug monitor";
+ hms_ops.to_doc = "Debug via the HMS monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).";
+ hms_ops.to_open = hms_open;
+ /* By trial and error I've found that this delay doesn't break things */
+ write_dos_tick_delay = 1;
+ add_target (&hms_ops);
+}
+
+
+#if 0
+/* This is kept here because we used to support the H8/500 in this module,
+ and I haven't done the H8/500 yet */
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "serial.h"
+#include "remote-utils.h"
+/* External data declarations */
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+/* Forward data declarations */
+extern struct target_ops hms_ops; /* Forward declaration */
+
+/* Forward function declarations */
+static void hms_fetch_registers ();
+static int hms_store_registers ();
+static void hms_close ();
+static int hms_clear_breakpoints ();
+
+extern struct target_ops hms_ops;
+static void hms_drain ();
+static void add_commands ();
+static void remove_commands ();
+
+static int quiet = 1; /* FIXME - can be removed after Dec '94 */
+
+
+
+/***********************************************************************
+ * I/O stuff stolen from remote-eb.c
+ ***********************************************************************/
+
+static int timeout = 2;
+
+static const char *dev_name;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ hms_open knows that we don't have a file open when the program
+ starts. */
+
+static int before = 0xdead;
+static int is_open = 0;
+static int after = 0xdead;
+int
+check_open ()
+{
+ if (before != 0xdead
+ || after != 0xdead)
+ printf ("OUTCH! \n");
+ if (!is_open)
+ {
+ error ("remote device not open");
+ }
+}
+
+#define ON 1
+#define OFF 0
+
+/* Read a character from the remote system, doing all the fancy
+ timeout stuff. */
+static int
+readchar ()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (desc, timeout);
+
+ if (buf == SERIAL_TIMEOUT)
+ {
+ hms_write (".\r\n", 3);
+ error ("Timeout reading from remote system.");
+ }
+ if (buf == SERIAL_ERROR)
+ {
+ error ("Serial port error!");
+ }
+
+ if (!quiet || remote_debug)
+ printf_unfiltered ("%c", buf);
+
+ return buf & 0x7f;
+}
+
+static void
+flush ()
+{
+ while (1)
+ {
+ int b = SERIAL_READCHAR (desc, 0);
+ if (b == SERIAL_TIMEOUT)
+ return;
+ }
+}
+
+static int
+readchar_nofail ()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (desc, timeout);
+ if (buf == SERIAL_TIMEOUT)
+ buf = 0;
+ if (!quiet || remote_debug)
+ printf_unfiltered ("%c", buf);
+
+ return buf & 0x7f;
+
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+static void
+expect (string)
+ char *string;
+{
+ char *p = string;
+ char c;
+ immediate_quit = 1;
+ while (1)
+ {
+ c = readchar ();
+ if (c == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ {
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+/* Keep discarding input until we see the hms prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: hms_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a hms_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt ()
+{
+ expect ("HMS>");
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+
+ while (1)
+ {
+ ch = readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from hms_desc and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Read a 32-bit hex word from the hms, preceded by a space */
+static long
+get_hex_word ()
+{
+ long val;
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ return val;
+}
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to hms_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+static int need_artificial_trap = 0;
+
+void
+hms_kill (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+void
+hms_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+ char buffer[100];
+
+ if (args && *args)
+ error ("Can't pass arguments to remote hms process.");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+ check_open ();
+
+ hms_kill (NULL, NULL);
+ hms_clear_breakpoints ();
+ init_wait_for_inferior ();
+ hms_write_cr ("");
+ expect_prompt ();
+
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication, then a space,
+ then the baud rate.
+ */
+
+static char *
+find_end_of_word (s)
+ char *s;
+{
+ while (*s && !isspace (*s))
+ s++;
+ return s;
+}
+
+static char *
+get_word (p)
+ char **p;
+{
+ char *s = *p;
+ char *word;
+ char *copy;
+ size_t len;
+
+ while (isspace (*s))
+ s++;
+
+ word = s;
+
+ len = 0;
+
+ while (*s && !isspace (*s))
+ {
+ s++;
+ len++;
+
+ }
+ copy = xmalloc (len + 1);
+ memcpy (copy, word, len);
+ copy[len] = 0;
+ *p = s;
+ return copy;
+}
+
+static int baudrate = 9600;
+
+static int
+is_baudrate_right ()
+{
+ int ok;
+
+ /* Put this port into NORMAL mode, send the 'normal' character */
+
+ hms_write ("\001", 1); /* Control A */
+ hms_write ("\r\n", 2); /* Cr */
+
+ while (1)
+ {
+ ok = SERIAL_READCHAR (desc, timeout);
+ if (ok < 0)
+ break;
+ }
+
+ hms_write ("r", 1);
+
+ if (readchar_nofail () == 'r')
+ return 1;
+
+ /* Not the right baudrate, or the board's not on */
+ return 0;
+}
+static void
+set_rate ()
+{
+ if (!SERIAL_SETBAUDRATE (desc, baudrate))
+ error ("Can't set baudrate");
+}
+
+
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+hms_close (quitting)
+ int quitting;
+{
+ /* Clear any break points */
+ remove_commands ();
+ hms_clear_breakpoints ();
+ sleep (1); /* Let any output make it all the way back */
+ if (is_open)
+ {
+ SERIAL_WRITE (desc, "R\r\n", 3);
+ SERIAL_CLOSE (desc);
+ }
+ is_open = 0;
+}
+
+/* Terminate the open connection to the remote debugger. Use this
+ when you want to detach and do something else with your gdb. */ void
+hms_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (is_open)
+ {
+ hms_clear_breakpoints ();
+ }
+
+ pop_target (); /* calls hms_close to do the real work
+ */
+ if (from_tty)
+ printf_filtered ("Ending remote %s debugging\n",
+ target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+void
+hms_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal
+ sig;
+{
+ if (step)
+ {
+ hms_write_cr ("s");
+ expect ("Step>");
+
+ /* Force the next hms_wait to return a trap. Not doing anything
+ about I/O from the target means that the user has to type "continue"
+ to see any. FIXME, this should be fixed. */
+ need_artificial_trap = 1;
+ }
+ else
+ {
+ hms_write_cr ("g");
+ expect ("g");
+ }
+}
+
+/* Wait until the remote machine stops, then return, storing status in
+ STATUS just as `wait' would. */
+
+int
+hms_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ /* Strings to look for. '?' means match any single character. Note
+ that with the algorithm we use, the initial character of the string
+ cannot recur in the string, or we will not find some cases of the
+ string in the input. */
+
+ static char bpt[] = "At breakpoint:";
+
+ /* It would be tempting to look for "\n[__exit + 0x8]\n" but that
+ requires loading symbols with "yc i" and even if we did do that we
+ don't know that the file has symbols. */
+ static char exitmsg[] = "HMS>";
+ char *bp = bpt;
+ char *ep = exitmsg;
+
+ /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars.
+ */
+ char swallowed[50];
+
+ /* Current position in swallowed. */
+ char *swallowed_p = swallowed;
+
+ int ch;
+ int ch_handled;
+ int old_timeout = timeout;
+ int
+ old_immediate_quit = immediate_quit;
+ int swallowed_cr = 0;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ if (need_artificial_trap != 0)
+ {
+ status->kind =
+ TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ need_artificial_trap--;
+ return 0;
+ }
+
+ timeout = 5; /* Don't time out for a while - user program is running.
+ */
+ immediate_quit = 1; /* Helps ability to QUIT */
+ while (1)
+ {
+ QUIT; /* Let user quit and leave process running */
+ ch_handled = 0;
+ ch = readchar ();
+ if (ch == *bp)
+ {
+ bp++;
+ if (*bp == '\0')
+ break;
+ ch_handled = 1;
+
+ *swallowed_p++ = ch;
+ }
+ else
+ {
+ bp = bpt;
+ }
+ if
+ (ch == *ep || *ep == '?')
+ {
+ ep++;
+ if (*ep == '\0')
+ break;
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+ ch_handled =
+ 1;
+ }
+ else
+ {
+ ep = exitmsg;
+ }
+
+ if (!ch_handled)
+ {
+ char *p;
+
+ /* Print out any characters which have been swallowed. */
+ for (p = swallowed; p < swallowed_p; ++p)
+ putchar_unfiltered (*p);
+ swallowed_p = swallowed;
+
+ if ((ch != '\r' && ch != '\n') || swallowed_cr > 10)
+ {
+ putchar_unfiltered (ch);
+ swallowed_cr = 10;
+ }
+ swallowed_cr++;
+
+ }
+ }
+ if (*bp == '\0')
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ expect_prompt ();
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer =
+ TARGET_SIGNAL_STOP;
+ }
+
+ timeout = old_timeout;
+ immediate_quit = old_immediate_quit;
+ return
+ 0;
+}
+
+/* Return the name of register number REGNO in the form input and
+ output by hms.
+
+ Returns a pointer to a static buffer containing the answer. */
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char *rn[] =
+ REGISTER_NAMES;
+
+ return rn[regno];
+}
+
+/* Read the remote registers. */
+
+static int
+gethex (length, start, ok)
+ unsigned int length;
+ char *start;
+ int *ok;
+{
+ int result = 0;
+
+ while (length--)
+ {
+ result <<= 4;
+ if (*start >= 'a' && *start <= 'f')
+ {
+ result += *start - 'a' + 10;
+ }
+ else if (*start >= 'A' &&
+ *start <= 'F')
+ {
+ result += *start - 'A' + 10;
+ }
+ else if
+ (*start >= '0' && *start <= '9')
+ {
+ result += *start - '0';
+ }
+ else
+ *ok = 0;
+ start++;
+
+ }
+ return result;
+}
+static int
+timed_read (buf, n, timeout)
+ char
+ *buf;
+
+{
+ int i;
+ char c;
+
+ i = 0;
+ while (i < n)
+ {
+ c = readchar ();
+
+ if (c == 0)
+ return i;
+ buf[i] = c;
+ i++;
+
+ }
+ return i;
+}
+
+hms_write (a, l)
+ char *a;
+{
+ int i;
+
+ SERIAL_WRITE (desc, a, l);
+
+ if (!quiet || remote_debug)
+ {
+ printf_unfiltered ("<");
+ for (i = 0; i < l; i++)
+ {
+ printf_unfiltered ("%c", a[i]);
+ }
+ printf_unfiltered (">");
+ }
+}
+
+hms_write_cr (s)
+ char *s;
+{
+ hms_write (s, strlen (s));
+ hms_write ("\r\n", 2);
+}
+
+#ifdef GDB_TARGET_IS_H8500
+
+/* H8/500 monitor reg dump looks like:
+
+ HMS>r
+ PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00
+ R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE
+ HMS>
+
+
+ */
+
+supply_val (n, size, ptr, segptr)
+ int n;
+ int size;
+ char *ptr;
+ char *segptr;
+{
+ int ok;
+ char raw[4];
+ switch (size)
+ {
+ case 2:
+ raw[0] = gethex (2, ptr, &ok);
+ raw[1] = gethex (2, ptr + 2, &ok);
+ supply_register (n, raw);
+ break;
+ case 1:
+ raw[0] = gethex (2, ptr, &ok);
+ supply_register (n, raw);
+ break;
+ case 4:
+ {
+ int v = gethex (4, ptr, &ok);
+ v |= gethex (2, segptr, &ok) << 16;
+ raw[0] = 0;
+ raw[1] = (v >> 16) & 0xff;
+ raw[2] = (v >> 8) & 0xff;
+ raw[3] = (v >> 0) & 0xff;
+ supply_register (n, raw);
+ }
+ }
+
+}
+static void
+hms_fetch_register (dummy)
+ int dummy;
+{
+#define REGREPLY_SIZE 108
+ char linebuf[REGREPLY_SIZE + 1];
+ int i;
+ int s;
+ int gottok;
+
+ LONGEST reg[NUM_REGS];
+ check_open ();
+
+ do
+ {
+
+ hms_write_cr ("r");
+ expect ("r");
+ s = timed_read (linebuf + 1, REGREPLY_SIZE, 1);
+
+ linebuf[REGREPLY_SIZE] = 0;
+ gottok = 0;
+ if (linebuf[3] == 'P' &&
+ linebuf[4] == 'C' &&
+ linebuf[5] == ':' &&
+ linebuf[105] == 'H' &&
+ linebuf[106] == 'M' &&
+ linebuf[107] == 'S')
+ {
+
+ /*
+ 012
+ r**
+ -------1---------2---------3---------4---------5-----
+ 345678901234567890123456789012345678901234567890123456
+ PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00**
+ ---6---------7---------8---------9--------10----
+ 789012345678901234567890123456789012345678901234
+ R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE**
+
+ 56789
+ HMS>
+ */
+ gottok = 1;
+
+
+ supply_val (PC_REGNUM, 4, linebuf + 6, linebuf + 29);
+
+ supply_val (CCR_REGNUM, 2, linebuf + 14);
+ supply_val (SEG_C_REGNUM, 1, linebuf + 29);
+ supply_val (SEG_D_REGNUM, 1, linebuf + 35);
+ supply_val (SEG_E_REGNUM, 1, linebuf + 41);
+ supply_val (SEG_T_REGNUM, 1, linebuf + 47);
+ for (i = 0; i < 8; i++)
+ {
+ static int sr[8] =
+ {35, 35, 35, 35,
+ 41, 41, 47, 47};
+
+ char raw[4];
+ char *src = linebuf + 64 + 5 * i;
+ char *segsrc = linebuf + sr[i];
+ supply_val (R0_REGNUM + i, 2, src);
+ supply_val (PR0_REGNUM + i, 4, src, segsrc);
+ }
+ }
+ if (!gottok)
+ {
+ hms_write_cr ("");
+ expect ("HMS>");
+ }
+ }
+ while (!gottok);
+}
+#endif
+
+#ifdef GDB_TARGET_IS_H8300
+static void
+hms_fetch_register (dummy)
+ int dummy;
+{
+#define REGREPLY_SIZE 79
+ char linebuf[REGREPLY_SIZE + 1];
+ int i;
+ int s;
+ int gottok;
+
+ unsigned LONGEST reg[NUM_REGS];
+
+ check_open ();
+
+ do
+ {
+ hms_write_cr ("r");
+
+ s = timed_read (linebuf, 1, 1);
+
+ while (linebuf[0] != 'r')
+ s = timed_read (linebuf, 1, 1);
+
+ s = timed_read (linebuf + 1, REGREPLY_SIZE - 1, 1);
+
+ linebuf[REGREPLY_SIZE] = 0;
+ gottok = 0;
+ if (linebuf[0] == 'r' &&
+ linebuf[3] == 'P' &&
+ linebuf[4] == 'C' &&
+ linebuf[5] == '=' &&
+ linebuf[75] == 'H' &&
+ linebuf[76] == 'M' &&
+ linebuf[77] == 'S')
+ {
+ /*
+ PC=XXXX CCR=XX:XXXXXXXX R0-R7= XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
+ 5436789012345678901234567890123456789012345678901234567890123456789012
+ 0 1 2 3 4 5 6
+ */
+ gottok = 1;
+
+ reg[PC_REGNUM] = gethex (4, linebuf + 6, &gottok);
+ reg[CCR_REGNUM] = gethex (2, linebuf + 15, &gottok);
+ for (i = 0; i < 8; i++)
+ {
+ reg[i] = gethex (4, linebuf + 34 + 5 * i, &gottok);
+ }
+ }
+ }
+ while (!gottok);
+ for (i = 0; i < NUM_REGS; i++)
+ {
+ char swapped[2];
+
+ swapped[1] = reg[i];
+ swapped[0] = (reg[i]) >> 8;
+
+ supply_register (i, swapped);
+ }
+}
+#endif
+/* Store register REGNO, or all if REGNO == -1.
+ Return errno value. */
+static void
+hms_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ hms_store_register (regno);
+ }
+ }
+ else
+ {
+ char *name = get_reg_name (regno);
+ char buffer[100];
+ /* Some regs dont really exist */
+ if (!(name[0] == 'p' && name[1] == 'r')
+ && !(name[0] == 'c' && name[1] == 'y')
+ && !(name[0] == 't' && name[1] == 'i')
+ && !(name[0] == 'i' && name[1] == 'n'))
+ {
+ sprintf (buffer, "r %s=%x", name, read_register (regno));
+ hms_write_cr (buffer);
+ expect_prompt ();
+ }
+ }
+}
+
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+void
+hms_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static CORE_ADDR
+translate_addr (addr)
+ CORE_ADDR addr;
+{
+
+ return (addr);
+
+}
+
+
+int
+hms_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+
+ return len;
+}
+
+int
+hms_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ bfd_vma addr;
+ int done;
+ int todo;
+ char buffer[100];
+ done = 0;
+ hms_write_cr (".");
+ expect_prompt ();
+ while (done < len)
+ {
+ char *ptr = buffer;
+ int thisgo;
+ int idx;
+
+ thisgo = len - done;
+ if (thisgo > 20)
+ thisgo = 20;
+
+ sprintf (ptr, "M.B %4x =", memaddr + done);
+ ptr += 10;
+ for (idx = 0; idx < thisgo; idx++)
+ {
+ sprintf (ptr, "%2x ", myaddr[idx + done]);
+ ptr += 3;
+ }
+ hms_write_cr (buffer);
+ expect_prompt ();
+ done += thisgo;
+ }
+}
+
+void
+hms_files_info ()
+{
+ char *file = "nothing";
+
+ if (exec_bfd)
+ file = bfd_get_filename (exec_bfd);
+
+ if (exec_bfd)
+#ifdef __GO32__
+ printf_filtered ("\tAttached to DOS asynctsr and running program %s\n", file);
+#else
+ printf_filtered ("\tAttached to %s at %d baud and running program %s\n", dev_name, baudrate, file);
+#endif
+ printf_filtered ("\ton an H8/300 processor.\n");
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns errno value.
+ * sb/sh instructions don't work on unaligned addresses, when TU=1.
+ */
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns errno value. */
+int
+hms_read_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ /* Align to nearest low 16 bits */
+ int i;
+
+ CORE_ADDR start = memaddr;
+ CORE_ADDR end = memaddr + len - 1;
+
+ int ok = 1;
+
+ /*
+ AAAA: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX '................'
+ 012345678901234567890123456789012345678901234567890123456789012345
+ 0 1 2 3 4 5 6
+ */
+ char buffer[66];
+
+ if (memaddr & 0xf)
+ abort ();
+ if (len != 16)
+ abort ();
+
+ sprintf (buffer, "m %4x %4x", start & 0xffff, end & 0xffff);
+
+ flush ();
+ hms_write_cr (buffer);
+ /* drop the echo and newline */
+ for (i = 0; i < 13; i++)
+ readchar ();
+
+ /* Grab the lines as they come out and fill the area */
+ /* Skip over cr */
+ while (1)
+ {
+ int p;
+ int i;
+ int addr;
+ size_t idx;
+
+ char byte[16];
+
+ buffer[0] = readchar ();
+ while (buffer[0] == '\r'
+ || buffer[0] == '\n')
+ buffer[0] = readchar ();
+
+ if (buffer[0] == 'M')
+ break;
+
+ for (i = 1; i < 50; i++)
+ {
+ buffer[i] = readchar ();
+ }
+ /* sometimes we loose characters in the ascii representation of the
+ data. I don't know where. So just scan for the end of line */
+ i = readchar ();
+ while (i != '\n' && i != '\r')
+ i = readchar ();
+
+ /* Now parse the line */
+
+ addr = gethex (4, buffer, &ok);
+ idx = 6;
+ for (p = 0; p < 16; p += 2)
+ {
+ byte[p] = gethex (2, buffer + idx, &ok);
+ byte[p + 1] = gethex (2, buffer + idx + 2, &ok);
+ idx += 5;
+ }
+
+ for (p = 0; p < 16; p++)
+ {
+ if (addr + p >= memaddr &&
+ addr + p < memaddr + len)
+ {
+ myaddr[(addr + p) - memaddr] = byte[p];
+
+ }
+
+ }
+ }
+#ifdef GDB_TARGET_IS_H8500
+ expect ("ore>");
+#endif
+#ifdef GDB_TARGET_IS_H8300
+ expect ("emory>");
+#endif
+ hms_write_cr (".");
+
+ expect_prompt ();
+ return len;
+}
+
+
+
+#define MAX_BREAKS 16
+static int num_brkpts = 0;
+static int
+hms_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let hms save instructions */
+{
+ check_open ();
+
+ if (num_brkpts < MAX_BREAKS)
+ {
+ char buffer[100];
+
+ num_brkpts++;
+ sprintf (buffer, "b %x", addr & 0xffff);
+ hms_write_cr (buffer);
+ expect_prompt ();
+ return (0);
+ }
+ else
+ {
+ fprintf_filtered (gdb_stderr,
+ "Too many break points, break point not installed\n");
+ return (1);
+ }
+
+}
+static int
+hms_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save; /* Throw away, let hms save instructions */
+{
+ if (num_brkpts > 0)
+ {
+ char buffer[100];
+
+ num_brkpts--;
+ sprintf (buffer, "b - %x", addr & 0xffff);
+ hms_write_cr (buffer);
+ expect_prompt ();
+
+ }
+ return (0);
+}
+
+/* Clear the hmss notion of what the break points are */
+static int
+hms_clear_breakpoints ()
+{
+
+ if (is_open)
+ {
+ hms_write_cr ("b -");
+ expect_prompt ();
+ }
+ num_brkpts = 0;
+}
+static void
+hms_mourn ()
+{
+ hms_clear_breakpoints ();
+ unpush_target (&hms_ops);
+ generic_mourn_inferior ();
+}
+
+/* Put a command string, in args, out to the hms. The hms is assumed to
+ be in raw mode, all writing/reading done through desc.
+ Ouput from the hms is placed on the users terminal until the
+ prompt from the hms is seen.
+ FIXME: Can't handle commands that take input. */
+
+void
+hms_com (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ check_open ();
+
+ if (!args)
+ return;
+
+ /* Clear all input so only command relative output is displayed */
+
+ hms_write_cr (args);
+/* hms_write ("\030", 1); */
+ expect_prompt ();
+}
+
+static void
+hms_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ unsigned int prl;
+ char *p;
+
+ if (name == 0)
+ {
+ name = "";
+ }
+ if (is_open)
+ hms_close (0);
+ dev_name = strdup (name);
+
+ if (!(desc = SERIAL_OPEN (dev_name)))
+ perror_with_name ((char *) dev_name);
+
+ SERIAL_RAW (desc);
+ is_open = 1;
+ push_target (&hms_ops);
+ dcache_ptr = dcache_init (hms_read_inferior_memory,
+ hms_write_inferior_memory);
+ remote_dcache = 1;
+ /* Hello? Are you there? */
+ SERIAL_WRITE (desc, "\r\n", 2);
+ expect_prompt ();
+
+ /* Clear any break points */
+ hms_clear_breakpoints ();
+
+ printf_filtered ("Connected to remote board running HMS monitor.\n");
+ add_commands ();
+/* hms_drain (); */
+}
+
+/* Define the target subroutine names */
+
+struct target_ops hms_ops =
+{
+ "hms", "Remote HMS monitor",
+ "Use the H8 evaluation board running the HMS monitor connected\n\
+by a serial line.",
+
+ hms_open, hms_close,
+ 0, hms_detach, hms_resume, hms_wait, /* attach */
+ hms_fetch_register, hms_store_register,
+ hms_prepare_to_store,
+ hms_xfer_inferior_memory,
+ hms_files_info,
+ hms_insert_breakpoint, hms_remove_breakpoint, /* Breakpoints */
+ 0, 0, 0, 0, 0, /* Terminal handling */
+ hms_kill, /* FIXME, kill */
+ generic_load,
+ 0, /* lookup_symbol */
+ hms_create_inferior, /* create_inferior */
+ hms_mourn, /* mourn_inferior FIXME */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+hms_quiet () /* FIXME - this routine can be removed after Dec '94 */
+{
+ quiet = !quiet;
+ if (quiet)
+ printf_filtered ("Snoop disabled\n");
+ else
+ printf_filtered ("Snoop enabled\n");
+
+ printf_filtered ("`snoop' is obsolete, please use `set remotedebug'.\n");
+}
+
+hms_device (s)
+ char *s;
+{
+ if (s)
+ {
+ dev_name = get_word (&s);
+ }
+}
+
+static
+hms_speed (s)
+ char *s;
+{
+ check_open ();
+
+ if (s)
+ {
+ char buffer[100];
+ int newrate = atoi (s);
+ int which = 0;
+
+ if (SERIAL_SETBAUDRATE (desc, newrate))
+ error ("Can't use %d baud\n", newrate);
+
+ printf_filtered ("Checking target is in sync\n");
+
+ printf_filtered ("Sending commands to set target to %d\n",
+ baudrate);
+
+ sprintf (buffer, "tm %d. N 8 1", baudrate);
+ hms_write_cr (buffer);
+ }
+}
+
+/***********************************************************************/
+
+static void
+hms_drain (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ int c;
+ while (1)
+ {
+ c = SERIAL_READCHAR (desc, 1);
+ if (c == SERIAL_TIMEOUT)
+ break;
+ if (c == SERIAL_ERROR)
+ break;
+ if (c > ' ' && c < 127)
+ printf ("%c", c & 0xff);
+ else
+ printf ("<%x>", c & 0xff);
+ }
+}
+
+static void
+add_commands ()
+{
+
+ add_com ("hms_drain", class_obscure, hms_drain,
+ "Drain pending hms text buffers.");
+}
+
+static void
+remove_commands ()
+{
+ extern struct cmd_list_element *cmdlist;
+ delete_cmd ("hms-drain", &cmdlist);
+}
+
+
+void
+_initialize_remote_hms ()
+{
+ add_target (&hms_ops);
+
+ add_com ("hms <command>", class_obscure, hms_com,
+ "Send a command to the HMS monitor.");
+
+ /* FIXME - hms_quiet and `snoop' can be removed after Dec '94 */
+ add_com ("snoop", class_obscure, hms_quiet,
+ "Show what commands are going to the monitor (OBSOLETE - see 'set remotedebug')");
+
+ add_com ("device", class_obscure, hms_device,
+ "Set the terminal line for HMS communications");
+
+ add_com ("speed", class_obscure, hms_speed,
+ "Set the terminal line speed for HMS communications");
+
+ dev_name = NULL;
+}
+#endif
+
diff --git a/contrib/gdb/gdb/remote-mips.c b/contrib/gdb/gdb/remote-mips.c
new file mode 100644
index 0000000..176e1be
--- /dev/null
+++ b/contrib/gdb/gdb/remote-mips.c
@@ -0,0 +1,2997 @@
+/* Remote debugging interface for MIPS remote debugging protocol.
+ Copyright 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Ian Lance Taylor
+ <ian@cygnus.com>.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "wait.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "serial.h"
+#include "target.h"
+#include "remote-utils.h"
+
+#include <signal.h>
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+extern char *mips_read_processor_type PARAMS ((void));
+
+extern void mips_set_processor_type_command PARAMS ((char *, int));
+
+
+/* Prototypes for local functions. */
+
+static int mips_readchar PARAMS ((int timeout));
+
+static int mips_receive_header PARAMS ((unsigned char *hdr, int *pgarbage,
+ int ch, int timeout));
+
+static int mips_receive_trailer PARAMS ((unsigned char *trlr, int *pgarbage,
+ int *pch, int timeout));
+
+static int mips_cksum PARAMS ((const unsigned char *hdr,
+ const unsigned char *data,
+ int len));
+
+static void mips_send_packet PARAMS ((const char *s, int get_ack));
+
+static void mips_send_command PARAMS ((const char *cmd, int prompt));
+
+static int mips_receive_packet PARAMS ((char *buff, int throw_error,
+ int timeout));
+
+static int mips_request PARAMS ((int cmd, unsigned int addr,
+ unsigned int data, int *perr, int timeout,
+ char *buff));
+
+static void mips_initialize PARAMS ((void));
+
+static void mips_open PARAMS ((char *name, int from_tty));
+
+static void pmon_open PARAMS ((char *name, int from_tty));
+
+static void mips_close PARAMS ((int quitting));
+
+static void mips_detach PARAMS ((char *args, int from_tty));
+
+static void mips_resume PARAMS ((int pid, int step,
+ enum target_signal siggnal));
+
+static int mips_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static int pmon_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static int mips_map_regno PARAMS ((int regno));
+
+static void mips_fetch_registers PARAMS ((int regno));
+
+static void mips_prepare_to_store PARAMS ((void));
+
+static void mips_store_registers PARAMS ((int regno));
+
+static int mips_fetch_word PARAMS ((CORE_ADDR addr));
+
+static int mips_store_word PARAMS ((CORE_ADDR addr, int value,
+ char *old_contents));
+
+static int mips_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
+ int write, struct target_ops *ignore));
+
+static void mips_files_info PARAMS ((struct target_ops *ignore));
+
+static void mips_create_inferior PARAMS ((char *execfile, char *args,
+ char **env));
+
+static void mips_mourn_inferior PARAMS ((void));
+
+static int pmon_makeb64 PARAMS ((unsigned long v, char *p, int n, int *chksum));
+
+static int pmon_zeroset PARAMS ((int recsize, char **buff, int *amount,
+ unsigned int *chksum));
+
+static int pmon_checkset PARAMS ((int recsize, char **buff, int *value));
+
+static void pmon_make_fastrec PARAMS ((char **outbuf, unsigned char *inbuf,
+ int *inptr, int inamount, int *recsize,
+ unsigned int *csum, unsigned int *zerofill));
+
+static int pmon_check_ack PARAMS ((void));
+
+static void pmon_load_fast PARAMS ((char *file));
+
+static void mips_load PARAMS ((char *file, int from_tty));
+
+static int mips_make_srec PARAMS ((char *buffer, int type, CORE_ADDR memaddr,
+ unsigned char *myaddr, int len));
+
+static int common_breakpoint PARAMS ((int cmd, CORE_ADDR addr, CORE_ADDR mask,
+ char *flags));
+
+static void common_open PARAMS ((struct target_ops *ops, char *name,
+ int from_tty));
+/* Forward declarations. */
+extern struct target_ops mips_ops;
+extern struct target_ops pmon_ops;
+
+/* The MIPS remote debugging interface is built on top of a simple
+ packet protocol. Each packet is organized as follows:
+
+ SYN The first character is always a SYN (ASCII 026, or ^V). SYN
+ may not appear anywhere else in the packet. Any time a SYN is
+ seen, a new packet should be assumed to have begun.
+
+ TYPE_LEN
+ This byte contains the upper five bits of the logical length
+ of the data section, plus a single bit indicating whether this
+ is a data packet or an acknowledgement. The documentation
+ indicates that this bit is 1 for a data packet, but the actual
+ board uses 1 for an acknowledgement. The value of the byte is
+ 0x40 + (ack ? 0x20 : 0) + (len >> 6)
+ (we always have 0 <= len < 1024). Acknowledgement packets do
+ not carry data, and must have a data length of 0.
+
+ LEN1 This byte contains the lower six bits of the logical length of
+ the data section. The value is
+ 0x40 + (len & 0x3f)
+
+ SEQ This byte contains the six bit sequence number of the packet.
+ The value is
+ 0x40 + seq
+ An acknowlegment packet contains the sequence number of the
+ packet being acknowledged plus 1 modulo 64. Data packets are
+ transmitted in sequence. There may only be one outstanding
+ unacknowledged data packet at a time. The sequence numbers
+ are independent in each direction. If an acknowledgement for
+ the previous packet is received (i.e., an acknowledgement with
+ the sequence number of the packet just sent) the packet just
+ sent should be retransmitted. If no acknowledgement is
+ received within a timeout period, the packet should be
+ retransmitted. This has an unfortunate failure condition on a
+ high-latency line, as a delayed acknowledgement may lead to an
+ endless series of duplicate packets.
+
+ DATA The actual data bytes follow. The following characters are
+ escaped inline with DLE (ASCII 020, or ^P):
+ SYN (026) DLE S
+ DLE (020) DLE D
+ ^C (003) DLE C
+ ^S (023) DLE s
+ ^Q (021) DLE q
+ The additional DLE characters are not counted in the logical
+ length stored in the TYPE_LEN and LEN1 bytes.
+
+ CSUM1
+ CSUM2
+ CSUM3
+ These bytes contain an 18 bit checksum of the complete
+ contents of the packet excluding the SEQ byte and the
+ CSUM[123] bytes. The checksum is simply the twos complement
+ addition of all the bytes treated as unsigned characters. The
+ values of the checksum bytes are:
+ CSUM1: 0x40 + ((cksum >> 12) & 0x3f)
+ CSUM2: 0x40 + ((cksum >> 6) & 0x3f)
+ CSUM3: 0x40 + (cksum & 0x3f)
+
+ It happens that the MIPS remote debugging protocol always
+ communicates with ASCII strings. Because of this, this
+ implementation doesn't bother to handle the DLE quoting mechanism,
+ since it will never be required. */
+
+/* The SYN character which starts each packet. */
+#define SYN '\026'
+
+/* The 0x40 used to offset each packet (this value ensures that all of
+ the header and trailer bytes, other than SYN, are printable ASCII
+ characters). */
+#define HDR_OFFSET 0x40
+
+/* The indices of the bytes in the packet header. */
+#define HDR_INDX_SYN 0
+#define HDR_INDX_TYPE_LEN 1
+#define HDR_INDX_LEN1 2
+#define HDR_INDX_SEQ 3
+#define HDR_LENGTH 4
+
+/* The data/ack bit in the TYPE_LEN header byte. */
+#define TYPE_LEN_DA_BIT 0x20
+#define TYPE_LEN_DATA 0
+#define TYPE_LEN_ACK TYPE_LEN_DA_BIT
+
+/* How to compute the header bytes. */
+#define HDR_SET_SYN(data, len, seq) (SYN)
+#define HDR_SET_TYPE_LEN(data, len, seq) \
+ (HDR_OFFSET \
+ + ((data) ? TYPE_LEN_DATA : TYPE_LEN_ACK) \
+ + (((len) >> 6) & 0x1f))
+#define HDR_SET_LEN1(data, len, seq) (HDR_OFFSET + ((len) & 0x3f))
+#define HDR_SET_SEQ(data, len, seq) (HDR_OFFSET + (seq))
+
+/* Check that a header byte is reasonable. */
+#define HDR_CHECK(ch) (((ch) & HDR_OFFSET) == HDR_OFFSET)
+
+/* Get data from the header. These macros evaluate their argument
+ multiple times. */
+#define HDR_IS_DATA(hdr) \
+ (((hdr)[HDR_INDX_TYPE_LEN] & TYPE_LEN_DA_BIT) == TYPE_LEN_DATA)
+#define HDR_GET_LEN(hdr) \
+ ((((hdr)[HDR_INDX_TYPE_LEN] & 0x1f) << 6) + (((hdr)[HDR_INDX_LEN1] & 0x3f)))
+#define HDR_GET_SEQ(hdr) ((hdr)[HDR_INDX_SEQ] & 0x3f)
+
+/* The maximum data length. */
+#define DATA_MAXLEN 1023
+
+/* The trailer offset. */
+#define TRLR_OFFSET HDR_OFFSET
+
+/* The indices of the bytes in the packet trailer. */
+#define TRLR_INDX_CSUM1 0
+#define TRLR_INDX_CSUM2 1
+#define TRLR_INDX_CSUM3 2
+#define TRLR_LENGTH 3
+
+/* How to compute the trailer bytes. */
+#define TRLR_SET_CSUM1(cksum) (TRLR_OFFSET + (((cksum) >> 12) & 0x3f))
+#define TRLR_SET_CSUM2(cksum) (TRLR_OFFSET + (((cksum) >> 6) & 0x3f))
+#define TRLR_SET_CSUM3(cksum) (TRLR_OFFSET + (((cksum) ) & 0x3f))
+
+/* Check that a trailer byte is reasonable. */
+#define TRLR_CHECK(ch) (((ch) & TRLR_OFFSET) == TRLR_OFFSET)
+
+/* Get data from the trailer. This evaluates its argument multiple
+ times. */
+#define TRLR_GET_CKSUM(trlr) \
+ ((((trlr)[TRLR_INDX_CSUM1] & 0x3f) << 12) \
+ + (((trlr)[TRLR_INDX_CSUM2] & 0x3f) << 6) \
+ + ((trlr)[TRLR_INDX_CSUM3] & 0x3f))
+
+/* The sequence number modulos. */
+#define SEQ_MODULOS (64)
+
+enum mips_monitor_type {
+ /* IDT/SIM monitor being used: */
+ MON_IDT,
+ /* PMON monitor being used: */
+ MON_PMON,
+ /* Last and unused value, for sizing vectors, etc. */
+ MON_LAST
+};
+static enum mips_monitor_type mips_monitor = MON_LAST;
+
+/* The default monitor prompt text: */
+static char *mips_monitor_prompt = TARGET_MONITOR_PROMPT;
+/* For the Cogent PMON world this is still not ideal. The default
+ prompt is "PMON> ", unfortunately the user can change the prompt
+ and the new prompt will survive over a power-cycle (EEPROM). This
+ means that the code should really force the monitor prompt to a
+ known value as the very first action, and that the
+ "mips_monitor_prompt" support is not needed... since the prompt
+ could be explicitly set to TARGET_MONITOR_PROMPT (even though it
+ may be the prompt for a different monitor). However, this will
+ require changing the mips_initialize reset sequence. (TODO) */
+
+/* Set to 1 if the target is open. */
+static int mips_is_open;
+
+/* Currently active target description (if mips_is_open == 1) */
+static struct target_ops *current_ops;
+
+/* Set to 1 while the connection is being initialized. */
+static int mips_initializing;
+
+/* The next sequence number to send. */
+static unsigned int mips_send_seq;
+
+/* The next sequence number we expect to receive. */
+static unsigned int mips_receive_seq;
+
+/* The time to wait before retransmitting a packet, in seconds. */
+static int mips_retransmit_wait = 3;
+
+/* The number of times to try retransmitting a packet before giving up. */
+static int mips_send_retries = 10;
+
+/* The number of garbage characters to accept when looking for an
+ SYN for the next packet. */
+static int mips_syn_garbage = 1050;
+
+/* The time to wait for a packet, in seconds. */
+static int mips_receive_wait = 5;
+
+/* Set if we have sent a packet to the board but have not yet received
+ a reply. */
+static int mips_need_reply = 0;
+
+/* Handle used to access serial I/O stream. */
+static serial_t mips_desc;
+
+/* Counts the number of times the user tried to interrupt the target (usually
+ via ^C. */
+static int interrupt_count;
+
+/* If non-zero, means that the target is running. */
+static int mips_wait_flag = 0;
+
+/* If non-zero, monitor supports breakpoint commands. */
+static monitor_supports_breakpoints = 0;
+
+/* Data cache header. */
+
+static DCACHE *mips_dcache;
+
+/* Non-zero means that we've just hit a read or write watchpoint */
+static int hit_watchpoint;
+
+/* Handle low-level error that we can't recover from. Note that just
+ error()ing out from target_wait or some such low-level place will cause
+ all hell to break loose--the rest of GDB will tend to get left in an
+ inconsistent state. */
+
+static NORETURN void
+#ifdef ANSI_PROTOTYPES
+mips_error (char *string, ...)
+#else
+mips_error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+
+ target_terminal_ours ();
+ wrap_here(""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+ if (error_pre_print)
+ fprintf_filtered (gdb_stderr, error_pre_print);
+ vfprintf_filtered (gdb_stderr, string, args);
+ fprintf_filtered (gdb_stderr, "\n");
+ va_end (args);
+ gdb_flush (gdb_stderr);
+
+ /* Clean up in such a way that mips_close won't try to talk to the
+ board (it almost surely won't work since we weren't able to talk to
+ it). */
+ mips_is_open = 0;
+ SERIAL_CLOSE (mips_desc);
+
+ printf_unfiltered ("Ending remote MIPS debugging.\n");
+ target_mourn_inferior ();
+
+ return_to_top_level (RETURN_ERROR);
+}
+
+/* Wait until STRING shows up in mips_desc. Returns 1 if successful, else 0 if
+ timed out. */
+
+int
+mips_expect (string)
+ char *string;
+{
+ char *p = string;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ int c;
+
+/* Must use SERIAL_READCHAR here cuz mips_readchar would get confused if we
+ were waiting for the mips_monitor_prompt... */
+
+ c = SERIAL_READCHAR (mips_desc, 2);
+
+ if (c == SERIAL_TIMEOUT)
+ return 0;
+
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return 1;
+ }
+ }
+ else
+ {
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+/* Read the required number of characters into the given buffer (which
+ is assumed to be large enough). The only failure is a timeout. */
+int
+mips_getstring (string, n)
+ char *string;
+ int n;
+{
+ char *p = string;
+ int c;
+
+ immediate_quit = 1;
+ while (n > 0)
+ {
+ c = SERIAL_READCHAR (mips_desc, 2);
+
+ if (c == SERIAL_TIMEOUT) {
+ fprintf_unfiltered (stderr, "Failed to read %d characters from target (TIMEOUT)\n", n);
+ return 0;
+ }
+
+ *p++ = c;
+ n--;
+ }
+
+ return 1;
+}
+
+/* Read a character from the remote, aborting on error. Returns
+ SERIAL_TIMEOUT on timeout (since that's what SERIAL_READCHAR
+ returns). FIXME: If we see the string mips_monitor_prompt from
+ the board, then we are debugging on the main console port, and we
+ have somehow dropped out of remote debugging mode. In this case,
+ we automatically go back in to remote debugging mode. This is a
+ hack, put in because I can't find any way for a program running on
+ the remote board to terminate without also ending remote debugging
+ mode. I assume users won't have any trouble with this; for one
+ thing, the IDT documentation generally assumes that the remote
+ debugging port is not the console port. This is, however, very
+ convenient for DejaGnu when you only have one connected serial
+ port. */
+
+static int
+mips_readchar (timeout)
+ int timeout;
+{
+ int ch;
+ static int state = 0;
+ static int mips_monitor_prompt_len = -1;
+
+ /* NASTY, since we assume that the prompt does not change after the
+ first mips_readchar call: */
+ if (mips_monitor_prompt_len = -1)
+ mips_monitor_prompt_len = strlen(mips_monitor_prompt);
+
+#ifdef MAINTENANCE_CMDS
+ {
+ int i;
+
+ i = timeout;
+ if (i == -1 && watchdog > 0)
+ i = watchdog;
+ }
+#endif
+
+ if (state == mips_monitor_prompt_len)
+ timeout = 1;
+ ch = SERIAL_READCHAR (mips_desc, timeout);
+#ifdef MAINTENANCE_CMDS
+ if (ch == SERIAL_TIMEOUT && timeout == -1) /* Watchdog went off */
+ {
+ target_mourn_inferior ();
+ error ("Watchdog has expired. Target detached.\n");
+ }
+#endif
+ if (ch == SERIAL_EOF)
+ mips_error ("End of file from remote");
+ if (ch == SERIAL_ERROR)
+ mips_error ("Error reading from remote: %s", safe_strerror (errno));
+ if (remote_debug > 1)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (ch != SERIAL_TIMEOUT)
+ printf_unfiltered ("Read '%c' %d 0x%x\n", ch, ch, ch);
+ else
+ printf_unfiltered ("Timed out in read\n");
+ }
+
+ /* If we have seen mips_monitor_prompt and we either time out, or
+ we see a @ (which was echoed from a packet we sent), reset the
+ board as described above. The first character in a packet after
+ the SYN (which is not echoed) is always an @ unless the packet is
+ more than 64 characters long, which ours never are. */
+ if ((ch == SERIAL_TIMEOUT || ch == '@')
+ && state == mips_monitor_prompt_len
+ && ! mips_initializing)
+ {
+ if (remote_debug > 0)
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Reinitializing MIPS debugging mode\n");
+
+ mips_need_reply = 0;
+ mips_initialize ();
+
+ state = 0;
+
+ /* At this point, about the only thing we can do is abort the command
+ in progress and get back to command level as quickly as possible. */
+
+ error ("Remote board reset, debug protocol re-initialized.");
+ }
+
+ if (ch == mips_monitor_prompt[state])
+ ++state;
+ else
+ state = 0;
+
+ return ch;
+}
+
+/* Get a packet header, putting the data in the supplied buffer.
+ PGARBAGE is a pointer to the number of garbage characters received
+ so far. CH is the last character received. Returns 0 for success,
+ or -1 for timeout. */
+
+static int
+mips_receive_header (hdr, pgarbage, ch, timeout)
+ unsigned char *hdr;
+ int *pgarbage;
+ int ch;
+ int timeout;
+{
+ int i;
+
+ while (1)
+ {
+ /* Wait for a SYN. mips_syn_garbage is intended to prevent
+ sitting here indefinitely if the board sends us one garbage
+ character per second. ch may already have a value from the
+ last time through the loop. */
+ while (ch != SYN)
+ {
+ ch = mips_readchar (timeout);
+ if (ch == SERIAL_TIMEOUT)
+ return -1;
+ if (ch != SYN)
+ {
+ /* Printing the character here lets the user of gdb see
+ what the program is outputting, if the debugging is
+ being done on the console port. Don't use _filtered;
+ we can't deal with a QUIT out of target_wait. */
+ if (! mips_initializing || remote_debug > 0)
+ {
+ /* Note that the host's idea of newline may not
+ correspond to the target's idea, so recognize
+ newline by its actual ASCII code, but write it
+ out using the \n notation. */
+ if (ch < 0x20 && ch != '\012')
+ {
+ putchar_unfiltered ('^');
+ putchar_unfiltered (ch + 0x40);
+ }
+ else if (ch == '\012')
+ putchar_unfiltered ('\n');
+ else
+ putchar_unfiltered (ch);
+ gdb_flush (gdb_stdout);
+ }
+
+ ++*pgarbage;
+ if (mips_syn_garbage > 0
+ && *pgarbage > mips_syn_garbage)
+ mips_error ("Debug protocol failure: more than %d characters before a sync.",
+ mips_syn_garbage);
+ }
+ }
+
+ /* Get the packet header following the SYN. */
+ for (i = 1; i < HDR_LENGTH; i++)
+ {
+ ch = mips_readchar (timeout);
+ if (ch == SERIAL_TIMEOUT)
+ return -1;
+ /* Make sure this is a header byte. */
+ if (ch == SYN || ! HDR_CHECK (ch))
+ break;
+
+ hdr[i] = ch;
+ }
+
+ /* If we got the complete header, we can return. Otherwise we
+ loop around and keep looking for SYN. */
+ if (i >= HDR_LENGTH)
+ return 0;
+ }
+}
+
+/* Get a packet header, putting the data in the supplied buffer.
+ PGARBAGE is a pointer to the number of garbage characters received
+ so far. The last character read is returned in *PCH. Returns 0
+ for success, -1 for timeout, -2 for error. */
+
+static int
+mips_receive_trailer (trlr, pgarbage, pch, timeout)
+ unsigned char *trlr;
+ int *pgarbage;
+ int *pch;
+ int timeout;
+{
+ int i;
+ int ch;
+
+ for (i = 0; i < TRLR_LENGTH; i++)
+ {
+ ch = mips_readchar (timeout);
+ *pch = ch;
+ if (ch == SERIAL_TIMEOUT)
+ return -1;
+ if (! TRLR_CHECK (ch))
+ return -2;
+ trlr[i] = ch;
+ }
+ return 0;
+}
+
+/* Get the checksum of a packet. HDR points to the packet header.
+ DATA points to the packet data. LEN is the length of DATA. */
+
+static int
+mips_cksum (hdr, data, len)
+ const unsigned char *hdr;
+ const unsigned char *data;
+ int len;
+{
+ register const unsigned char *p;
+ register int c;
+ register int cksum;
+
+ cksum = 0;
+
+ /* The initial SYN is not included in the checksum. */
+ c = HDR_LENGTH - 1;
+ p = hdr + 1;
+ while (c-- != 0)
+ cksum += *p++;
+
+ c = len;
+ p = data;
+ while (c-- != 0)
+ cksum += *p++;
+
+ return cksum;
+}
+
+/* Send a packet containing the given ASCII string. */
+
+static void
+mips_send_packet (s, get_ack)
+ const char *s;
+ int get_ack;
+{
+ unsigned int len;
+ unsigned char *packet;
+ register int cksum;
+ int try;
+
+ len = strlen (s);
+ if (len > DATA_MAXLEN)
+ mips_error ("MIPS protocol data packet too long: %s", s);
+
+ packet = (unsigned char *) alloca (HDR_LENGTH + len + TRLR_LENGTH + 1);
+
+ packet[HDR_INDX_SYN] = HDR_SET_SYN (1, len, mips_send_seq);
+ packet[HDR_INDX_TYPE_LEN] = HDR_SET_TYPE_LEN (1, len, mips_send_seq);
+ packet[HDR_INDX_LEN1] = HDR_SET_LEN1 (1, len, mips_send_seq);
+ packet[HDR_INDX_SEQ] = HDR_SET_SEQ (1, len, mips_send_seq);
+
+ memcpy (packet + HDR_LENGTH, s, len);
+
+ cksum = mips_cksum (packet, packet + HDR_LENGTH, len);
+ packet[HDR_LENGTH + len + TRLR_INDX_CSUM1] = TRLR_SET_CSUM1 (cksum);
+ packet[HDR_LENGTH + len + TRLR_INDX_CSUM2] = TRLR_SET_CSUM2 (cksum);
+ packet[HDR_LENGTH + len + TRLR_INDX_CSUM3] = TRLR_SET_CSUM3 (cksum);
+
+ /* Increment the sequence number. This will set mips_send_seq to
+ the sequence number we expect in the acknowledgement. */
+ mips_send_seq = (mips_send_seq + 1) % SEQ_MODULOS;
+
+ /* We can only have one outstanding data packet, so we just wait for
+ the acknowledgement here. Keep retransmitting the packet until
+ we get one, or until we've tried too many times. */
+ for (try = 0; try < mips_send_retries; try++)
+ {
+ int garbage;
+ int ch;
+
+ if (remote_debug > 0)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ packet[HDR_LENGTH + len + TRLR_LENGTH] = '\0';
+ printf_unfiltered ("Writing \"%s\"\n", packet + 1);
+ }
+
+ if (SERIAL_WRITE (mips_desc, packet,
+ HDR_LENGTH + len + TRLR_LENGTH) != 0)
+ mips_error ("write to target failed: %s", safe_strerror (errno));
+
+ if (! get_ack)
+ return;
+
+ garbage = 0;
+ ch = 0;
+ while (1)
+ {
+ unsigned char hdr[HDR_LENGTH + 1];
+ unsigned char trlr[TRLR_LENGTH + 1];
+ int err;
+ int seq;
+
+ /* Get the packet header. If we time out, resend the data
+ packet. */
+ err = mips_receive_header (hdr, &garbage, ch, mips_retransmit_wait);
+ if (err != 0)
+ break;
+
+ ch = 0;
+
+ /* If we get a data packet, assume it is a duplicate and
+ ignore it. FIXME: If the acknowledgement is lost, this
+ data packet may be the packet the remote sends after the
+ acknowledgement. */
+ if (HDR_IS_DATA (hdr)) {
+ int i;
+
+ /* Ignore any errors raised whilst attempting to ignore
+ packet. */
+
+ len = HDR_GET_LEN (hdr);
+
+ for (i = 0; i < len; i++)
+ {
+ int rch;
+
+ rch = mips_readchar (2);
+ if (rch == SYN)
+ {
+ ch = SYN;
+ break;
+ }
+ if (rch == SERIAL_TIMEOUT)
+ break;
+ /* ignore the character */
+ }
+
+ if (i == len)
+ (void) mips_receive_trailer (trlr, &garbage, &ch, 2);
+
+ /* We don't bother checking the checksum, or providing an
+ ACK to the packet. */
+ continue;
+ }
+
+ /* If the length is not 0, this is a garbled packet. */
+ if (HDR_GET_LEN (hdr) != 0)
+ continue;
+
+ /* Get the packet trailer. */
+ err = mips_receive_trailer (trlr, &garbage, &ch,
+ mips_retransmit_wait);
+
+ /* If we timed out, resend the data packet. */
+ if (err == -1)
+ break;
+
+ /* If we got a bad character, reread the header. */
+ if (err != 0)
+ continue;
+
+ /* If the checksum does not match the trailer checksum, this
+ is a bad packet; ignore it. */
+ if (mips_cksum (hdr, (unsigned char *) NULL, 0)
+ != TRLR_GET_CKSUM (trlr))
+ continue;
+
+ if (remote_debug > 0)
+ {
+ hdr[HDR_LENGTH] = '\0';
+ trlr[TRLR_LENGTH] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Got ack %d \"%s%s\"\n",
+ HDR_GET_SEQ (hdr), hdr + 1, trlr);
+ }
+
+ /* If this ack is for the current packet, we're done. */
+ seq = HDR_GET_SEQ (hdr);
+ if (seq == mips_send_seq)
+ return;
+
+ /* If this ack is for the last packet, resend the current
+ packet. */
+ if ((seq + 1) % SEQ_MODULOS == mips_send_seq)
+ break;
+
+ /* Otherwise this is a bad ack; ignore it. Increment the
+ garbage count to ensure that we do not stay in this loop
+ forever. */
+ ++garbage;
+ }
+ }
+
+ mips_error ("Remote did not acknowledge packet");
+}
+
+/* Receive and acknowledge a packet, returning the data in BUFF (which
+ should be DATA_MAXLEN + 1 bytes). The protocol documentation
+ implies that only the sender retransmits packets, so this code just
+ waits silently for a packet. It returns the length of the received
+ packet. If THROW_ERROR is nonzero, call error() on errors. If not,
+ don't print an error message and return -1. */
+
+static int
+mips_receive_packet (buff, throw_error, timeout)
+ char *buff;
+ int throw_error;
+ int timeout;
+{
+ int ch;
+ int garbage;
+ int len;
+ unsigned char ack[HDR_LENGTH + TRLR_LENGTH + 1];
+ int cksum;
+
+ ch = 0;
+ garbage = 0;
+ while (1)
+ {
+ unsigned char hdr[HDR_LENGTH];
+ unsigned char trlr[TRLR_LENGTH];
+ int i;
+ int err;
+
+ if (mips_receive_header (hdr, &garbage, ch, timeout) != 0)
+ {
+ if (throw_error)
+ mips_error ("Timed out waiting for remote packet");
+ else
+ return -1;
+ }
+
+ ch = 0;
+
+ /* An acknowledgement is probably a duplicate; ignore it. */
+ if (! HDR_IS_DATA (hdr))
+ {
+ len = HDR_GET_LEN (hdr);
+ /* Check if the length is valid for an ACK, we may aswell
+ try and read the remainder of the packet: */
+ if (len == 0)
+ {
+ /* Ignore the error condition, since we are going to
+ ignore the packet anyway. */
+ (void) mips_receive_trailer (trlr, &garbage, &ch, timeout);
+ }
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Ignoring unexpected ACK\n");
+ continue;
+ }
+
+ len = HDR_GET_LEN (hdr);
+ for (i = 0; i < len; i++)
+ {
+ int rch;
+
+ rch = mips_readchar (timeout);
+ if (rch == SYN)
+ {
+ ch = SYN;
+ break;
+ }
+ if (rch == SERIAL_TIMEOUT)
+ {
+ if (throw_error)
+ mips_error ("Timed out waiting for remote packet");
+ else
+ return -1;
+ }
+ buff[i] = rch;
+ }
+
+ if (i < len)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Got new SYN after %d chars (wanted %d)\n",
+ i, len);
+ continue;
+ }
+
+ err = mips_receive_trailer (trlr, &garbage, &ch, timeout);
+ if (err == -1)
+ {
+ if (throw_error)
+ mips_error ("Timed out waiting for packet");
+ else
+ return -1;
+ }
+ if (err == -2)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Got SYN when wanted trailer\n");
+ continue;
+ }
+
+ /* If this is the wrong sequence number, ignore it. */
+ if (HDR_GET_SEQ (hdr) != mips_receive_seq)
+ {
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ if (remote_debug > 0)
+ printf_unfiltered ("Ignoring sequence number %d (want %d)\n",
+ HDR_GET_SEQ (hdr), mips_receive_seq);
+ continue;
+ }
+
+ if (mips_cksum (hdr, buff, len) == TRLR_GET_CKSUM (trlr))
+ break;
+
+ if (remote_debug > 0)
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Bad checksum; data %d, trailer %d\n",
+ mips_cksum (hdr, buff, len),
+ TRLR_GET_CKSUM (trlr));
+
+ /* The checksum failed. Send an acknowledgement for the
+ previous packet to tell the remote to resend the packet. */
+ ack[HDR_INDX_SYN] = HDR_SET_SYN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_TYPE_LEN] = HDR_SET_TYPE_LEN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_LEN1] = HDR_SET_LEN1 (0, 0, mips_receive_seq);
+ ack[HDR_INDX_SEQ] = HDR_SET_SEQ (0, 0, mips_receive_seq);
+
+ cksum = mips_cksum (ack, (unsigned char *) NULL, 0);
+
+ ack[HDR_LENGTH + TRLR_INDX_CSUM1] = TRLR_SET_CSUM1 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM2] = TRLR_SET_CSUM2 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM3] = TRLR_SET_CSUM3 (cksum);
+
+ if (remote_debug > 0)
+ {
+ ack[HDR_LENGTH + TRLR_LENGTH] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Writing ack %d \"%s\"\n", mips_receive_seq,
+ ack + 1);
+ }
+
+ if (SERIAL_WRITE (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0)
+ {
+ if (throw_error)
+ mips_error ("write to target failed: %s", safe_strerror (errno));
+ else
+ return -1;
+ }
+ }
+
+ if (remote_debug > 0)
+ {
+ buff[len] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Got packet \"%s\"\n", buff);
+ }
+
+ /* We got the packet. Send an acknowledgement. */
+ mips_receive_seq = (mips_receive_seq + 1) % SEQ_MODULOS;
+
+ ack[HDR_INDX_SYN] = HDR_SET_SYN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_TYPE_LEN] = HDR_SET_TYPE_LEN (0, 0, mips_receive_seq);
+ ack[HDR_INDX_LEN1] = HDR_SET_LEN1 (0, 0, mips_receive_seq);
+ ack[HDR_INDX_SEQ] = HDR_SET_SEQ (0, 0, mips_receive_seq);
+
+ cksum = mips_cksum (ack, (unsigned char *) NULL, 0);
+
+ ack[HDR_LENGTH + TRLR_INDX_CSUM1] = TRLR_SET_CSUM1 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM2] = TRLR_SET_CSUM2 (cksum);
+ ack[HDR_LENGTH + TRLR_INDX_CSUM3] = TRLR_SET_CSUM3 (cksum);
+
+ if (remote_debug > 0)
+ {
+ ack[HDR_LENGTH + TRLR_LENGTH] = '\0';
+ /* Don't use _filtered; we can't deal with a QUIT out of
+ target_wait, and I think this might be called from there. */
+ printf_unfiltered ("Writing ack %d \"%s\"\n", mips_receive_seq,
+ ack + 1);
+ }
+
+ if (SERIAL_WRITE (mips_desc, ack, HDR_LENGTH + TRLR_LENGTH) != 0)
+ {
+ if (throw_error)
+ mips_error ("write to target failed: %s", safe_strerror (errno));
+ else
+ return -1;
+ }
+
+ return len;
+}
+
+/* Optionally send a request to the remote system and optionally wait
+ for the reply. This implements the remote debugging protocol,
+ which is built on top of the packet protocol defined above. Each
+ request has an ADDR argument and a DATA argument. The following
+ requests are defined:
+
+ \0 don't send a request; just wait for a reply
+ i read word from instruction space at ADDR
+ d read word from data space at ADDR
+ I write DATA to instruction space at ADDR
+ D write DATA to data space at ADDR
+ r read register number ADDR
+ R set register number ADDR to value DATA
+ c continue execution (if ADDR != 1, set pc to ADDR)
+ s single step (if ADDR != 1, set pc to ADDR)
+
+ The read requests return the value requested. The write requests
+ return the previous value in the changed location. The execution
+ requests return a UNIX wait value (the approximate signal which
+ caused execution to stop is in the upper eight bits).
+
+ If PERR is not NULL, this function waits for a reply. If an error
+ occurs, it sets *PERR to 1 and sets errno according to what the
+ target board reports. */
+
+static int
+mips_request (cmd, addr, data, perr, timeout, buff)
+ int cmd;
+ unsigned int addr;
+ unsigned int data;
+ int *perr;
+ int timeout;
+ char *buff;
+{
+ char myBuff[DATA_MAXLEN + 1];
+ int len;
+ int rpid;
+ char rcmd;
+ int rerrflg;
+ int rresponse;
+
+ if (buff == (char *) NULL)
+ buff = myBuff;
+
+ if (cmd != '\0')
+ {
+ if (mips_need_reply)
+ fatal ("mips_request: Trying to send command before reply");
+ sprintf (buff, "0x0 %c 0x%x 0x%x", cmd, addr, data);
+ mips_send_packet (buff, 1);
+ mips_need_reply = 1;
+ }
+
+ if (perr == (int *) NULL)
+ return 0;
+
+ if (! mips_need_reply)
+ fatal ("mips_request: Trying to get reply before command");
+
+ mips_need_reply = 0;
+
+ len = mips_receive_packet (buff, 1, timeout);
+ buff[len] = '\0';
+
+ if (sscanf (buff, "0x%x %c 0x%x 0x%x",
+ &rpid, &rcmd, &rerrflg, &rresponse) != 4
+ || (cmd != '\0' && rcmd != cmd))
+ mips_error ("Bad response from remote board");
+
+ if (rerrflg != 0)
+ {
+ *perr = 1;
+
+ /* FIXME: This will returns MIPS errno numbers, which may or may
+ not be the same as errno values used on other systems. If
+ they stick to common errno values, they will be the same, but
+ if they don't, they must be translated. */
+ errno = rresponse;
+
+ return 0;
+ }
+
+ *perr = 0;
+ return rresponse;
+}
+
+static void
+mips_initialize_cleanups (arg)
+ PTR arg;
+{
+ mips_initializing = 0;
+}
+
+static void
+mips_send_command (cmd, prompt)
+ const char *cmd;
+ int prompt;
+{
+ SERIAL_WRITE (mips_desc, cmd, strlen(cmd));
+ mips_expect (cmd);
+ mips_expect ("\012");
+ if (prompt)
+ mips_expect (mips_monitor_prompt);
+}
+
+/* Enter remote (dbx) debug mode: */
+static void
+mips_enter_debug ()
+{
+ /* Reset the sequence numbers, ready for the new debug sequence: */
+ mips_send_seq = 0;
+ mips_receive_seq = 0;
+
+ if (mips_monitor == MON_PMON)
+ mips_send_command ("debug\015", 0);
+ else /* assume IDT monitor by default */
+ mips_send_command ("db tty0\015", 0);
+
+ SERIAL_WRITE (mips_desc, "\015", sizeof "\015" - 1);
+
+ /* We don't need to absorb any spurious characters here, since the
+ mips_receive_header will eat up a reasonable number of characters
+ whilst looking for the SYN, however this avoids the "garbage"
+ being displayed to the user. */
+ if (mips_monitor == MON_PMON)
+ mips_expect ("\015");
+
+ {
+ char buff[DATA_MAXLEN + 1];
+ if (mips_receive_packet (buff, 1, 3) < 0)
+ mips_error ("Failed to initialize (didn't receive packet).");
+ }
+}
+
+/* Exit remote (dbx) debug mode, returning to the monitor prompt: */
+static int
+mips_exit_debug ()
+{
+ int err;
+
+ mips_request ('x', (unsigned int) 0, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+
+ if (mips_monitor == MON_PMON && !mips_expect ("Exiting remote debug mode"))
+ return -1;
+
+ if (!mips_expect ("\015\012"))
+ return -1;
+
+ if (!mips_expect (mips_monitor_prompt))
+ return -1;
+
+ return 0;
+}
+
+/* Initialize a new connection to the MIPS board, and make sure we are
+ really connected. */
+
+static void
+mips_initialize ()
+{
+ int err;
+ struct cleanup *old_cleanups = make_cleanup (mips_initialize_cleanups, NULL);
+ int j;
+
+ /* What is this code doing here? I don't see any way it can happen, and
+ it might mean mips_initializing didn't get cleared properly.
+ So I'll make it a warning. */
+
+ if (mips_initializing)
+ {
+ warning ("internal error: mips_initialize called twice");
+ return;
+ }
+
+ mips_wait_flag = 0;
+ mips_initializing = 1;
+
+ /* At this point, the packit protocol isn't responding. We'll try getting
+ into the monitor, and restarting the protocol. */
+
+ /* Force the system into the monitor. After this we *should* be at
+ the mips_monitor_prompt. */
+ if (mips_monitor == MON_PMON)
+ j = 0; /* start by checking if we are already at the prompt */
+ else
+ j = 1; /* start by sending a break */
+ for (; j <= 4; j++)
+ {
+ switch (j)
+ {
+ case 0: /* First, try sending a CR */
+ SERIAL_FLUSH_INPUT (mips_desc);
+ SERIAL_WRITE (mips_desc, "\015", 1);
+ break;
+ case 1: /* First, try sending a break */
+ SERIAL_SEND_BREAK (mips_desc);
+ break;
+ case 2: /* Then, try a ^C */
+ SERIAL_WRITE (mips_desc, "\003", 1);
+ break;
+ case 3: /* Then, try escaping from download */
+ {
+ if (mips_monitor == MON_PMON)
+ {
+ char tbuff[7];
+
+ /* We shouldn't need to send multiple termination
+ sequences, since the target performs line (or
+ block) reads, and then processes those
+ packets. In-case we were downloading a large packet
+ we flush the output buffer before inserting a
+ termination sequence. */
+ SERIAL_FLUSH_OUTPUT (mips_desc);
+ sprintf (tbuff, "\015/E/E\015");
+ SERIAL_WRITE (mips_desc, tbuff, 6);
+ }
+ else
+ {
+ char srec[10];
+ int i;
+
+ /* We are possibly in binary download mode, having
+ aborted in the middle of an S-record. ^C won't
+ work because of binary mode. The only reliable way
+ out is to send enough termination packets (8 bytes)
+ to fill up and then overflow the largest size
+ S-record (255 bytes in this case). This amounts to
+ 256/8 + 1 packets.
+ */
+
+ mips_make_srec (srec, '7', 0, NULL, 0);
+
+ for (i = 1; i <= 33; i++)
+ {
+ SERIAL_WRITE (mips_desc, srec, 8);
+
+ if (SERIAL_READCHAR (mips_desc, 0) >= 0)
+ break; /* Break immediatly if we get something from
+ the board. */
+ }
+ }
+ }
+ break;
+ case 4:
+ mips_error ("Failed to initialize.");
+ }
+
+ if (mips_expect (mips_monitor_prompt))
+ break;
+ }
+
+ if (mips_monitor == MON_PMON)
+ {
+ /* Ensure the correct target state: */
+ mips_send_command ("set regsize 64\015", -1);
+ mips_send_command ("set hostport tty0\015", -1);
+ mips_send_command ("set brkcmd \"\"\015", -1);
+ /* Delete all the current breakpoints: */
+ mips_send_command ("db *\015", -1);
+ /* NOTE: PMON does not have breakpoint support through the
+ "debug" mode, only at the monitor command-line. */
+ }
+
+ mips_enter_debug ();
+
+ /* Clear all breakpoints: */
+ if (common_breakpoint ('b', -1, 0, NULL))
+ monitor_supports_breakpoints = 0;
+ else
+ monitor_supports_breakpoints = 1;
+
+ do_cleanups (old_cleanups);
+
+ /* If this doesn't call error, we have connected; we don't care if
+ the request itself succeeds or fails. */
+
+ mips_request ('r', (unsigned int) 0, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+ set_current_frame (create_new_frame (read_fp (), read_pc ()));
+ select_frame (get_current_frame (), 0);
+}
+
+/* Open a connection to the remote board. */
+static void
+common_open (ops, name, from_tty)
+ struct target_ops *ops;
+ char *name;
+ int from_tty;
+{
+ char *ptype;
+
+ if (name == 0)
+ error (
+"To open a MIPS remote debugging connection, you need to specify what serial\n\
+device is attached to the target board (e.g., /dev/ttya).");
+
+ target_preopen (from_tty);
+
+ if (mips_is_open)
+ unpush_target (current_ops);
+
+ mips_desc = SERIAL_OPEN (name);
+ if (mips_desc == (serial_t) NULL)
+ perror_with_name (name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (mips_desc, baud_rate))
+ {
+ SERIAL_CLOSE (mips_desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW (mips_desc);
+
+ current_ops = ops;
+ mips_is_open = 1;
+
+ mips_initialize ();
+
+ if (from_tty)
+ printf_unfiltered ("Remote MIPS debugging using %s\n", name);
+
+ /* Switch to using remote target now. */
+ push_target (ops);
+
+ /* FIXME: Should we call start_remote here? */
+
+ /* Try to figure out the processor model if possible. */
+ ptype = mips_read_processor_type ();
+ if (ptype)
+ mips_set_processor_type_command (strsave (ptype), 0);
+
+/* This is really the job of start_remote however, that makes an assumption
+ that the target is about to print out a status message of some sort. That
+ doesn't happen here (in fact, it may not be possible to get the monitor to
+ send the appropriate packet). */
+
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc ();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, -1, 1);
+}
+
+static void
+mips_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ mips_monitor = MON_IDT;
+ common_open (&mips_ops, name, from_tty);
+}
+
+static void
+pmon_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ /* The PMON monitor has a prompt different from the default
+ "TARGET_MONITOR_PROMPT": */
+ mips_monitor_prompt = "PMON> ";
+ mips_monitor = MON_PMON;
+ common_open (&pmon_ops, name, from_tty);
+}
+
+
+/* Close a connection to the remote board. */
+
+static void
+mips_close (quitting)
+ int quitting;
+{
+ if (mips_is_open)
+ {
+ int err;
+
+ mips_is_open = 0;
+
+ /* Get the board out of remote debugging mode. */
+ (void) mips_exit_debug ();
+
+ SERIAL_CLOSE (mips_desc);
+ }
+}
+
+/* Detach from the remote board. */
+
+static void
+mips_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ pop_target ();
+
+ mips_close (1);
+
+ if (from_tty)
+ printf_unfiltered ("Ending remote MIPS debugging.\n");
+}
+
+/* Tell the target board to resume. This does not wait for a reply
+ from the board. */
+
+static void
+mips_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+
+
+ mips_request (step ? 's' : 'c',
+ (unsigned int) 1,
+ (unsigned int) siggnal,
+ (int *) NULL,
+ mips_receive_wait, NULL);
+}
+
+/* Return the signal corresponding to SIG, where SIG is the number which
+ the MIPS protocol uses for the signal. */
+enum target_signal
+mips_signal_from_protocol (sig)
+ int sig;
+{
+ /* We allow a few more signals than the IDT board actually returns, on
+ the theory that there is at least *some* hope that perhaps the numbering
+ for these signals is widely agreed upon. */
+ if (sig <= 0
+ || sig > 31)
+ return TARGET_SIGNAL_UNKNOWN;
+
+ /* Don't want to use target_signal_from_host because we are converting
+ from MIPS signal numbers, not host ones. Our internal numbers
+ match the MIPS numbers for the signals the board can return, which
+ are: SIGINT, SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP. */
+ return (enum target_signal) sig;
+}
+
+/* Wait until the remote stops, and return a wait status. */
+
+static int
+mips_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int rstatus;
+ int err;
+ char buff[DATA_MAXLEN];
+ int rpc, rfp, rsp;
+ char flags[20];
+ int nfields;
+
+ interrupt_count = 0;
+ hit_watchpoint = 0;
+
+ /* If we have not sent a single step or continue command, then the
+ board is waiting for us to do something. Return a status
+ indicating that it is stopped. */
+ if (! mips_need_reply)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ return 0;
+ }
+
+ /* No timeout; we sit here as long as the program continues to execute. */
+ mips_wait_flag = 1;
+ rstatus = mips_request ('\000', (unsigned int) 0, (unsigned int) 0, &err, -1,
+ buff);
+ mips_wait_flag = 0;
+ if (err)
+ mips_error ("Remote failure: %s", safe_strerror (errno));
+
+ nfields = sscanf (buff, "0x%*x %*c 0x%*x 0x%*x 0x%x 0x%x 0x%x 0x%*x %s",
+ &rpc, &rfp, &rsp, flags);
+
+ /* See if we got back extended status. If so, pick out the pc, fp, sp, etc... */
+
+ if (nfields == 7 || nfields == 9)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rpc);
+ supply_register (PC_REGNUM, buf);
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rfp);
+ supply_register (30, buf); /* This register they are avoiding and so it is unnamed */
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (SP_REGNUM), rsp);
+ supply_register (SP_REGNUM, buf);
+
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (FP_REGNUM), 0);
+ supply_register (FP_REGNUM, buf);
+
+ if (nfields == 9)
+ {
+ int i;
+
+ for (i = 0; i <= 2; i++)
+ if (flags[i] == 'r' || flags[i] == 'w')
+ hit_watchpoint = 1;
+ else if (flags[i] == '\000')
+ break;
+ }
+ }
+
+ /* Translate a MIPS waitstatus. We use constants here rather than WTERMSIG
+ and so on, because the constants we want here are determined by the
+ MIPS protocol and have nothing to do with what host we are running on. */
+ if ((rstatus & 0377) == 0)
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = (((rstatus) >> 8) & 0377);
+ }
+ else if ((rstatus & 0377) == 0177)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = mips_signal_from_protocol (((rstatus) >> 8) & 0377);
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ status->value.sig = mips_signal_from_protocol (rstatus & 0177);
+ }
+
+ return 0;
+}
+
+static int
+pmon_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int rstatus;
+ int err;
+ char buff[DATA_MAXLEN];
+
+ interrupt_count = 0;
+ hit_watchpoint = 0;
+
+ /* If we have not sent a single step or continue command, then the
+ board is waiting for us to do something. Return a status
+ indicating that it is stopped. */
+ if (! mips_need_reply)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ return 0;
+ }
+
+ /* Sit, polling the serial until the target decides to talk to
+ us. NOTE: the timeout value we use is used not just for the
+ first character, but for all the characters. */
+ mips_wait_flag = 1;
+ rstatus = mips_request ('\000', (unsigned int) 0, (unsigned int) 0, &err, -1,
+ buff);
+ mips_wait_flag = 0;
+ if (err)
+ mips_error ("Remote failure: %s", safe_strerror (errno));
+
+ /* NOTE: The following (sig) numbers are defined by PMON:
+ SPP_SIGTRAP 5 breakpoint
+ SPP_SIGINT 2
+ SPP_SIGSEGV 11
+ SPP_SIGBUS 10
+ SPP_SIGILL 4
+ SPP_SIGFPE 8
+ SPP_SIGTERM 15 */
+
+ /* On returning from a continue, the PMON monitor seems to start
+ echoing back the messages we send prior to sending back the
+ ACK. The code can cope with this, but to try and avoid the
+ unnecessary serial traffic, and "spurious" characters displayed
+ to the user, we cheat and reset the debug protocol. The problems
+ seems to be caused by a check on the number of arguments, and the
+ command length, within the monitor causing it to echo the command
+ as a bad packet. */
+ mips_exit_debug ();
+ mips_enter_debug ();
+
+ /* Translate a MIPS waitstatus. We use constants here rather than WTERMSIG
+ and so on, because the constants we want here are determined by the
+ MIPS protocol and have nothing to do with what host we are running on. */
+ if ((rstatus & 0377) == 0)
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = (((rstatus) >> 8) & 0377);
+ }
+ else if ((rstatus & 0377) == 0177)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = mips_signal_from_protocol (((rstatus) >> 8) & 0377);
+ }
+ else
+ {
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ status->value.sig = mips_signal_from_protocol (rstatus & 0177);
+ }
+
+ return 0;
+}
+
+/* We have to map between the register numbers used by gdb and the
+ register numbers used by the debugging protocol. This function
+ assumes that we are using tm-mips.h. */
+
+#define REGNO_OFFSET 96
+
+static int
+mips_map_regno (regno)
+ int regno;
+{
+ if (regno < 32)
+ return regno;
+ if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+ return regno - FP0_REGNUM + 32;
+ switch (regno)
+ {
+ case PC_REGNUM:
+ return REGNO_OFFSET + 0;
+ case CAUSE_REGNUM:
+ return REGNO_OFFSET + 1;
+ case HI_REGNUM:
+ return REGNO_OFFSET + 2;
+ case LO_REGNUM:
+ return REGNO_OFFSET + 3;
+ case FCRCS_REGNUM:
+ return REGNO_OFFSET + 4;
+ case FCRIR_REGNUM:
+ return REGNO_OFFSET + 5;
+ default:
+ /* FIXME: Is there a way to get the status register? */
+ return 0;
+ }
+}
+
+/* Fetch the remote registers. */
+
+static void
+mips_fetch_registers (regno)
+ int regno;
+{
+ unsigned LONGEST val;
+ int err;
+
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ mips_fetch_registers (regno);
+ return;
+ }
+
+ if (regno == FP_REGNUM || regno == ZERO_REGNUM)
+ /* FP_REGNUM on the mips is a hack which is just supposed to read
+ zero (see also mips-nat.c). */
+ val = 0;
+ else
+ {
+#if 0 /* Unfortunately the PMON version in the Vr4300 board has been
+ compiled without the 64bit register access commands. This
+ means we cannot get hold of the full register width. */
+ if (mips_monitor == MON_PMON)
+ val = mips_request ('t', (unsigned int) mips_map_regno (regno),
+ (unsigned int) 0, &err, mips_receive_wait, NULL);
+ else
+#endif
+ val = mips_request ('r', (unsigned int) mips_map_regno (regno),
+ (unsigned int) 0, &err, mips_receive_wait, NULL);
+ if (err)
+ mips_error ("Can't read register %d: %s", regno,
+ safe_strerror (errno));
+ }
+
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ /* We got the number the register holds, but gdb expects to see a
+ value in the target byte ordering. */
+ store_unsigned_integer (buf, REGISTER_RAW_SIZE (regno), val);
+ supply_register (regno, buf);
+ }
+}
+
+/* Prepare to store registers. The MIPS protocol can store individual
+ registers, so this function doesn't have to do anything. */
+
+static void
+mips_prepare_to_store ()
+{
+}
+
+/* Store remote register(s). */
+
+static void
+mips_store_registers (regno)
+ int regno;
+{
+ int err;
+
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ mips_store_registers (regno);
+ return;
+ }
+
+ mips_request ('R', (unsigned int) mips_map_regno (regno),
+ (unsigned int) read_register (regno),
+ &err, mips_receive_wait, NULL);
+ if (err)
+ mips_error ("Can't write register %d: %s", regno, safe_strerror (errno));
+}
+
+/* Fetch a word from the target board. */
+
+static int
+mips_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ int val;
+ int err;
+
+ val = mips_request ('d', (unsigned int) addr, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+ if (err)
+ {
+ /* Data space failed; try instruction space. */
+ val = mips_request ('i', (unsigned int) addr, (unsigned int) 0, &err,
+ mips_receive_wait, NULL);
+ if (err)
+ mips_error ("Can't read address 0x%x: %s", addr, safe_strerror (errno));
+ }
+ return val;
+}
+
+/* Store a word to the target board. Returns errno code or zero for
+ success. If OLD_CONTENTS is non-NULL, put the old contents of that
+ memory location there. */
+
+static int
+mips_store_word (addr, val, old_contents)
+ CORE_ADDR addr;
+ int val;
+ char *old_contents;
+{
+ int err;
+ unsigned int oldcontents;
+
+ oldcontents = mips_request ('D', (unsigned int) addr, (unsigned int) val,
+ &err,
+ mips_receive_wait, NULL);
+ if (err)
+ {
+ /* Data space failed; try instruction space. */
+ oldcontents = mips_request ('I', (unsigned int) addr,
+ (unsigned int) val, &err,
+ mips_receive_wait, NULL);
+ if (err)
+ return errno;
+ }
+ if (old_contents != NULL)
+ store_unsigned_integer (old_contents, 4, oldcontents);
+ return 0;
+}
+
+/* Read or write LEN bytes from inferior memory at MEMADDR,
+ transferring to or from debugger address MYADDR. Write to inferior
+ if SHOULD_WRITE is nonzero. Returns length of data written or
+ read; 0 for error. Note that protocol gives us the correct value
+ for a longword, since it transfers values in ASCII. We want the
+ byte values, so we have to swap the longword values. */
+
+static int
+mips_xfer_memory (memaddr, myaddr, len, write, ignore)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *ignore;
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr &~ 3;
+ /* Round ending address up; get number of longwords that makes. */
+ register int count = (((memaddr + len) - addr) + 3) / 4;
+ /* Allocate buffer of that many longwords. */
+ register char *buffer = alloca (count * 4);
+
+ int status;
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing data. */
+ if (addr != memaddr || len < 4)
+ {
+ /* Need part of initial word -- fetch it. */
+ store_unsigned_integer (&buffer[0], 4, mips_fetch_word (addr));
+ }
+
+ if (count > 1)
+ {
+ /* Need part of last word -- fetch it. FIXME: we do this even
+ if we don't need it. */
+ store_unsigned_integer (&buffer[(count - 1) * 4], 4,
+ mips_fetch_word (addr + (count - 1) * 4));
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & 3), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += 4)
+ {
+ status = mips_store_word (addr,
+ extract_unsigned_integer (&buffer[i*4], 4),
+ NULL);
+ /* Report each kilobyte (we download 32-bit words at a time) */
+ if (i % 256 == 255)
+ {
+ printf_unfiltered ("*");
+ fflush (stdout);
+ }
+ if (status)
+ {
+ errno = status;
+ return 0;
+ }
+ /* FIXME: Do we want a QUIT here? */
+ }
+ if (count >= 256)
+ printf_unfiltered ("\n");
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += 4)
+ {
+ store_unsigned_integer (&buffer[i*4], 4, mips_fetch_word (addr));
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, buffer + (memaddr & 3), len);
+ }
+ return len;
+}
+
+/* Print info on this target. */
+
+static void
+mips_files_info (ignore)
+ struct target_ops *ignore;
+{
+ printf_unfiltered ("Debugging a MIPS board over a serial line.\n");
+}
+
+/* Kill the process running on the board. This will actually only
+ work if we are doing remote debugging over the console input. I
+ think that if IDT/sim had the remote debug interrupt enabled on the
+ right port, we could interrupt the process with a break signal. */
+
+static void
+mips_kill ()
+{
+ if (!mips_wait_flag)
+ return;
+
+ interrupt_count++;
+
+ if (interrupt_count >= 2)
+ {
+ interrupt_count = 0;
+
+ target_terminal_ours ();
+
+ if (query ("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? "))
+ {
+ /* Clean up in such a way that mips_close won't try to talk to the
+ board (it almost surely won't work since we weren't able to talk to
+ it). */
+ mips_wait_flag = 0;
+ mips_is_open = 0;
+ SERIAL_CLOSE (mips_desc);
+
+ printf_unfiltered ("Ending remote MIPS debugging.\n");
+ target_mourn_inferior ();
+
+ return_to_top_level (RETURN_QUIT);
+ }
+
+ target_terminal_inferior ();
+ }
+
+ if (remote_debug > 0)
+ printf_unfiltered ("Sending break\n");
+
+ SERIAL_SEND_BREAK (mips_desc);
+
+#if 0
+ if (mips_is_open)
+ {
+ char cc;
+
+ /* Send a ^C. */
+ cc = '\003';
+ SERIAL_WRITE (mips_desc, &cc, 1);
+ sleep (1);
+ target_mourn_inferior ();
+ }
+#endif
+}
+
+/* Start running on the target board. */
+
+static void
+mips_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ CORE_ADDR entry_pt;
+
+ if (args && *args)
+ {
+ warning ("\
+Can't pass arguments to remote MIPS board; arguments ignored.");
+ /* And don't try to use them on the next "run" command. */
+ execute_command ("set args", 0);
+ }
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No executable file specified");
+
+ entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
+
+ init_wait_for_inferior ();
+
+ /* FIXME: Should we set inferior_pid here? */
+
+ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Clean up after a process. Actually nothing to do. */
+
+static void
+mips_mourn_inferior ()
+{
+ if (current_ops != NULL)
+ unpush_target (current_ops);
+ generic_mourn_inferior ();
+}
+
+/* We can write a breakpoint and read the shadow contents in one
+ operation. */
+
+/* The IDT board uses an unusual breakpoint value, and sometimes gets
+ confused when it sees the usual MIPS breakpoint instruction. */
+
+#define BREAK_INSN (0x00000a0d)
+#define BREAK_INSN_SIZE (4)
+
+/* Insert a breakpoint on targets that don't have any better breakpoint
+ support. We read the contents of the target location and stash it,
+ then overwrite it with a breakpoint instruction. ADDR is the target
+ location in the target machine. CONTENTS_CACHE is a pointer to
+ memory allocated for saving the target contents. It is guaranteed
+ by the caller to be long enough to save sizeof BREAKPOINT bytes (this
+ is accomplished via BREAKPOINT_MAX). */
+
+static int
+mips_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int status;
+
+ if (monitor_supports_breakpoints)
+ return common_breakpoint ('B', addr, 0x3, "f");
+
+ return mips_store_word (addr, BREAK_INSN, contents_cache);
+}
+
+static int
+mips_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (monitor_supports_breakpoints)
+ return common_breakpoint ('b', addr, 0, NULL);
+
+ return target_write_memory (addr, contents_cache, BREAK_INSN_SIZE);
+}
+
+#if 0 /* currently not used */
+/* PMON does not currently provide support for the debug mode 'b'
+ commands to manipulate breakpoints. However, if we wanted to use
+ the monitor breakpoints (rather than the GDB BREAK_INSN version)
+ then this code performs the work needed to leave debug mode,
+ set/clear the breakpoint, and then return to debug mode. */
+
+#define PMON_MAX_BP (33) /* 32 SW, 1 HW */
+static CORE_ADDR mips_pmon_bp_info[PMON_MAX_BP];
+/* NOTE: The code relies on this vector being zero-initialised by the system */
+
+static int
+pmon_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int status;
+
+ if (monitor_supports_breakpoints)
+ {
+ char tbuff[12]; /* space for breakpoint command */
+ int bpnum;
+ CORE_ADDR bpaddr;
+
+ /* PMON does not support debug level breakpoint set/remove: */
+ if (mips_exit_debug ())
+ mips_error ("Failed to exit debug mode");
+
+ sprintf (tbuff, "b %08x\015", addr);
+ mips_send_command (tbuff, 0);
+
+ mips_expect ("Bpt ");
+
+ if (!mips_getstring (tbuff, 2))
+ return 1;
+ tbuff[2] = '\0'; /* terminate the string */
+ if (sscanf (tbuff, "%d", &bpnum) != 1)
+ {
+ fprintf_unfiltered (stderr, "Invalid decimal breakpoint number from target: %s\n", tbuff);
+ return 1;
+ }
+
+ mips_expect (" = ");
+
+ /* Lead in the hex number we are expecting: */
+ tbuff[0] = '0';
+ tbuff[1] = 'x';
+
+ if (!mips_getstring (&tbuff[2], 8))
+ return 1;
+ tbuff[10] = '\0'; /* terminate the string */
+
+ if (sscanf (tbuff, "0x%08x", &bpaddr) != 1)
+ {
+ fprintf_unfiltered (stderr, "Invalid hex address from target: %s\n", tbuff);
+ return 1;
+ }
+
+ if (bpnum >= PMON_MAX_BP)
+ {
+ fprintf_unfiltered (stderr, "Error: Returned breakpoint number %d outside acceptable range (0..%d)\n",
+ bpnum, PMON_MAX_BP - 1);
+ return 1;
+ }
+
+ if (bpaddr != addr)
+ fprintf_unfiltered (stderr, "Warning: Breakpoint addresses do not match: 0x%x != 0x%x\n", addr, bpaddr);
+
+ mips_pmon_bp_info[bpnum] = bpaddr;
+
+ mips_expect ("\015\012");
+ mips_expect (mips_monitor_prompt);
+
+ mips_enter_debug ();
+
+ return 0;
+ }
+
+ return mips_store_word (addr, BREAK_INSN, contents_cache);
+}
+
+static int
+pmon_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (monitor_supports_breakpoints)
+ {
+ int bpnum;
+ char tbuff[7]; /* enough for delete breakpoint command */
+
+ for (bpnum = 0; bpnum < PMON_MAX_BP; bpnum++)
+ if (mips_pmon_bp_info[bpnum] == addr)
+ break;
+
+ if (bpnum >= PMON_MAX_BP)
+ {
+ fprintf_unfiltered (stderr, "pmon_remove_breakpoint: Failed to find breakpoint at address 0x%x\n", addr);
+ return 1;
+ }
+
+ if (mips_exit_debug ())
+ mips_error ("Failed to exit debug mode");
+
+ sprintf (tbuff, "db %02d\015", bpnum);
+
+ mips_send_command (tbuff, -1);
+ /* NOTE: If the breakpoint does not exist then a "Bpt <dd> not
+ set" message will be returned. */
+
+ mips_enter_debug ();
+
+ return 0;
+ }
+
+ return target_write_memory (addr, contents_cache, BREAK_INSN_SIZE);
+}
+#endif
+
+/* Compute a don't care mask for the region bounding ADDR and ADDR + LEN - 1.
+ This is used for memory ref breakpoints. */
+
+static unsigned long
+calculate_mask (addr, len)
+ CORE_ADDR addr;
+ int len;
+{
+ unsigned long mask;
+ int i;
+
+ mask = addr ^ (addr + len - 1);
+
+ for (i = 32; i >= 0; i--)
+ if (mask == 0)
+ break;
+ else
+ mask >>= 1;
+
+ mask = (unsigned long) 0xffffffff >> i;
+
+ return mask;
+}
+
+/* Set a data watchpoint. ADDR and LEN should be obvious. TYPE is either 1
+ for a read watchpoint, or 2 for a read/write watchpoint. */
+
+int
+remote_mips_set_watchpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ int type;
+{
+ CORE_ADDR first_addr;
+ unsigned long mask;
+ char *flags;
+
+ mask = calculate_mask (addr, len);
+
+ first_addr = addr & ~mask;
+
+ switch (type)
+ {
+ case 0: /* write */
+ flags = "w";
+ break;
+ case 1: /* read */
+ flags = "r";
+ break;
+ case 2: /* read/write */
+ flags = "rw";
+ break;
+ default:
+ abort ();
+ }
+
+ if (common_breakpoint ('B', first_addr, mask, flags))
+ return -1;
+
+ return 0;
+}
+
+int
+remote_mips_remove_watchpoint (addr, len, type)
+ CORE_ADDR addr;
+ int len;
+ int type;
+{
+ CORE_ADDR first_addr;
+ unsigned long mask;
+
+ mask = calculate_mask (addr, len);
+
+ first_addr = addr & ~mask;
+
+ if (common_breakpoint ('b', first_addr, 0, NULL))
+ return -1;
+
+ return 0;
+}
+
+int
+remote_mips_stopped_by_watchpoint ()
+{
+ return hit_watchpoint;
+}
+
+/* This routine generates the a breakpoint command of the form:
+
+ 0x0 <CMD> <ADDR> <MASK> <FLAGS>
+
+ Where <CMD> is one of: `B' to set, or `b' to clear a breakpoint. <ADDR> is
+ the address of the breakpoint. <MASK> is a don't care mask for addresses.
+ <FLAGS> is any combination of `r', `w', or `f' for read/write/or fetch. */
+
+static int
+common_breakpoint (cmd, addr, mask, flags)
+ int cmd;
+ CORE_ADDR addr;
+ CORE_ADDR mask;
+ char *flags;
+{
+ int len;
+ char buf[DATA_MAXLEN + 1];
+ char rcmd;
+ int rpid, rerrflg, rresponse;
+ int nfields;
+
+ if (flags)
+ sprintf (buf, "0x0 %c 0x%x 0x%x %s", cmd, addr, mask, flags);
+ else
+ sprintf (buf, "0x0 %c 0x%x", cmd, addr);
+
+ mips_send_packet (buf, 1);
+
+ len = mips_receive_packet (buf, 1, mips_receive_wait);
+ buf[len] = '\0';
+
+ nfields = sscanf (buf, "0x%x %c 0x%x 0x%x", &rpid, &rcmd, &rerrflg, &rresponse);
+
+ if (nfields != 4
+ || rcmd != cmd)
+ mips_error ("common_breakpoint: Bad response from remote board: %s", buf);
+
+ if (rerrflg != 0)
+ {
+ if (rresponse != EINVAL)
+ fprintf_unfiltered (stderr, "common_breakpoint (0x%x): Got error: 0x%x\n",
+ addr, rresponse);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+send_srec (srec, len, addr)
+ char *srec;
+ int len;
+ CORE_ADDR addr;
+{
+ while (1)
+ {
+ int ch;
+
+ SERIAL_WRITE (mips_desc, srec, len);
+
+ ch = mips_readchar (2);
+
+ switch (ch)
+ {
+ case SERIAL_TIMEOUT:
+ error ("Timeout during download.");
+ break;
+ case 0x6: /* ACK */
+ return;
+ case 0x15: /* NACK */
+ fprintf_unfiltered (gdb_stderr, "Download got a NACK at byte %d! Retrying.\n", addr);
+ continue;
+ default:
+ error ("Download got unexpected ack char: 0x%x, retrying.\n", ch);
+ }
+ }
+}
+
+/* Download a binary file by converting it to S records. */
+
+static void
+mips_load_srec (args)
+ char *args;
+{
+ bfd *abfd;
+ asection *s;
+ char *buffer, srec[1024];
+ int i;
+ int srec_frame = 200;
+ int reclen;
+ static int hashmark = 1;
+
+ buffer = alloca (srec_frame * 2 + 256);
+
+ abfd = bfd_openr (args, 0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n", args);
+ return;
+ }
+
+ if (bfd_check_format (abfd, bfd_object) == 0)
+ {
+ printf_filtered ("File is not an object file\n");
+ return;
+ }
+
+/* This actually causes a download in the IDT binary format: */
+#define LOAD_CMD "load -b -s tty0\015"
+ mips_send_command (LOAD_CMD, 0);
+
+ for (s = abfd->sections; s; s = s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ int numbytes;
+
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
+ s->vma + s->_raw_size);
+ gdb_flush (gdb_stdout);
+
+ for (i = 0; i < s->_raw_size; i += numbytes)
+ {
+ numbytes = min (srec_frame, s->_raw_size - i);
+
+ bfd_get_section_contents (abfd, s, buffer, i, numbytes);
+
+ reclen = mips_make_srec (srec, '3', s->vma + i, buffer, numbytes);
+ send_srec (srec, reclen, s->vma + i);
+
+ if (hashmark)
+ {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+
+ } /* Per-packet (or S-record) loop */
+
+ putchar_unfiltered ('\n');
+ } /* Loadable sections */
+ }
+ if (hashmark)
+ putchar_unfiltered ('\n');
+
+ /* Write a type 7 terminator record. no data for a type 7, and there
+ is no data, so len is 0. */
+
+ reclen = mips_make_srec (srec, '7', abfd->start_address, NULL, 0);
+
+ send_srec (srec, reclen, abfd->start_address);
+
+ SERIAL_FLUSH_INPUT (mips_desc);
+}
+
+/*
+ * mips_make_srec -- make an srecord. This writes each line, one at a
+ * time, each with it's own header and trailer line.
+ * An srecord looks like this:
+ *
+ * byte count-+ address
+ * start ---+ | | data +- checksum
+ * | | | |
+ * S01000006F6B692D746573742E73726563E4
+ * S315000448600000000000000000FC00005900000000E9
+ * S31A0004000023C1400037DE00F023604000377B009020825000348D
+ * S30B0004485A0000000000004E
+ * S70500040000F6
+ *
+ * S<type><length><address><data><checksum>
+ *
+ * Where
+ * - length
+ * is the number of bytes following upto the checksum. Note that
+ * this is not the number of chars following, since it takes two
+ * chars to represent a byte.
+ * - type
+ * is one of:
+ * 0) header record
+ * 1) two byte address data record
+ * 2) three byte address data record
+ * 3) four byte address data record
+ * 7) four byte address termination record
+ * 8) three byte address termination record
+ * 9) two byte address termination record
+ *
+ * - address
+ * is the start address of the data following, or in the case of
+ * a termination record, the start address of the image
+ * - data
+ * is the data.
+ * - checksum
+ * is the sum of all the raw byte data in the record, from the length
+ * upwards, modulo 256 and subtracted from 255.
+ *
+ * This routine returns the length of the S-record.
+ *
+ */
+
+static int
+mips_make_srec (buf, type, memaddr, myaddr, len)
+ char *buf;
+ int type;
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ unsigned char checksum;
+ int i;
+
+ /* Create the header for the srec. addr_size is the number of bytes in the address,
+ and 1 is the number of bytes in the count. */
+
+ buf[0] = 'S';
+ buf[1] = type;
+ buf[2] = len + 4 + 1; /* len + 4 byte address + 1 byte checksum */
+ /* This assumes S3 style downloads (4byte addresses). There should
+ probably be a check, or the code changed to make it more
+ explicit. */
+ buf[3] = memaddr >> 24;
+ buf[4] = memaddr >> 16;
+ buf[5] = memaddr >> 8;
+ buf[6] = memaddr;
+ memcpy (&buf[7], myaddr, len);
+
+ /* Note that the checksum is calculated on the raw data, not the
+ hexified data. It includes the length, address and the data
+ portions of the packet. */
+ checksum = 0;
+ buf += 2; /* Point at length byte */
+ for (i = 0; i < len + 4 + 1; i++)
+ checksum += *buf++;
+
+ *buf = ~checksum;
+
+ return len + 8;
+}
+
+/* The following manifest controls whether we enable the simple flow
+ control support provided by the monitor. If enabled the code will
+ wait for an affirmative ACK between transmitting packets. */
+#define DOETXACK (1)
+
+/* The PMON fast-download uses an encoded packet format constructed of
+ 3byte data packets (encoded as 4 printable ASCII characters), and
+ escape sequences (preceded by a '/'):
+
+ 'K' clear checksum
+ 'C' compare checksum (12bit value, not included in checksum calculation)
+ 'S' define symbol name (for addr) terminated with "," and padded to 4char boundary
+ 'Z' zero fill multiple of 3bytes
+ 'B' byte (12bit encoded value, of 8bit data)
+ 'A' address (36bit encoded value)
+ 'E' define entry as original address, and exit load
+
+ The packets are processed in 4 character chunks, so the escape
+ sequences that do not have any data (or variable length data)
+ should be padded to a 4 character boundary. The decoder will give
+ an error if the complete message block size is not a multiple of
+ 4bytes (size of record).
+
+ The encoding of numbers is done in 6bit fields. The 6bit value is
+ used to index into this string to get the specific character
+ encoding for the value: */
+static char encoding[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.";
+
+/* Convert the number of bits required into an encoded number, 6bits
+ at a time (range 0..63). Keep a checksum if required (passed
+ pointer non-NULL). The function returns the number of encoded
+ characters written into the buffer. */
+static int
+pmon_makeb64 (v, p, n, chksum)
+ unsigned long v;
+ char *p;
+ int n;
+ int *chksum;
+{
+ int count = (n / 6);
+
+ if ((n % 12) != 0) {
+ fprintf_unfiltered(stderr,"Fast encoding bitcount must be a multiple of 12bits: %dbit%s\n",n,(n == 1)?"":"s");
+ return(0);
+ }
+ if (n > 36) {
+ fprintf_unfiltered(stderr,"Fast encoding cannot process more than 36bits at the moment: %dbits\n",n);
+ return(0);
+ }
+
+ /* Deal with the checksum: */
+ if (chksum != NULL) {
+ switch (n) {
+ case 36: *chksum += ((v >> 24) & 0xFFF);
+ case 24: *chksum += ((v >> 12) & 0xFFF);
+ case 12: *chksum += ((v >> 0) & 0xFFF);
+ }
+ }
+
+ do {
+ n -= 6;
+ *p++ = encoding[(v >> n) & 0x3F];
+ } while (n > 0);
+
+ return(count);
+}
+
+/* Shorthand function (that could be in-lined) to output the zero-fill
+ escape sequence into the data stream. */
+static int
+pmon_zeroset (recsize, buff, amount, chksum)
+ int recsize;
+ char **buff;
+ int *amount;
+ unsigned int *chksum;
+{
+ int count;
+
+ sprintf(*buff,"/Z");
+ count = pmon_makeb64 (*amount, (*buff + 2), 12, chksum);
+ *buff += (count + 2);
+ *amount = 0;
+ return(recsize + count + 2);
+}
+
+static int
+pmon_checkset (recsize, buff, value)
+ int recsize;
+ char **buff;
+ int *value;
+{
+ int count;
+
+ /* Add the checksum (without updating the value): */
+ sprintf (*buff, "/C");
+ count = pmon_makeb64 (*value, (*buff + 2), 12, NULL);
+ *buff += (count + 2);
+ sprintf (*buff, "\015");
+ *buff += 2; /* include zero terminator */
+ /* Forcing a checksum validation clears the sum: */
+ *value = 0;
+ return(recsize + count + 3);
+}
+
+/* Amount of padding we leave after at the end of the output buffer,
+ for the checksum and line termination characters: */
+#define CHECKSIZE (4 + 4 + 4 + 2)
+/* zero-fill, checksum, transfer end and line termination space. */
+
+/* The amount of binary data loaded from the object file in a single
+ operation: */
+#define BINCHUNK (1024)
+
+/* Maximum line of data accepted by the monitor: */
+#define MAXRECSIZE (550)
+/* NOTE: This constant depends on the monitor being used. This value
+ is for PMON 5.x on the Cogent Vr4300 board. */
+
+static void
+pmon_make_fastrec (outbuf, inbuf, inptr, inamount, recsize, csum, zerofill)
+ char **outbuf;
+ unsigned char *inbuf;
+ int *inptr;
+ int inamount;
+ int *recsize;
+ unsigned int *csum;
+ unsigned int *zerofill;
+{
+ int count = 0;
+ char *p = *outbuf;
+
+ /* This is a simple check to ensure that our data will fit within
+ the maximum allowable record size. Each record output is 4bytes
+ in length. We must allow space for a pending zero fill command,
+ the record, and a checksum record. */
+ while ((*recsize < (MAXRECSIZE - CHECKSIZE)) && ((inamount - *inptr) > 0)) {
+ /* Process the binary data: */
+ if ((inamount - *inptr) < 3) {
+ if (*zerofill != 0)
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ sprintf (p, "/B");
+ count = pmon_makeb64 (inbuf[*inptr], &p[2], 12, csum);
+ p += (2 + count);
+ *recsize += (2 + count);
+ (*inptr)++;
+ } else {
+ unsigned int value = ((inbuf[*inptr + 0] << 16) | (inbuf[*inptr + 1] << 8) | inbuf[*inptr + 2]);
+ /* Simple check for zero data. TODO: A better check would be
+ to check the last, and then the middle byte for being zero
+ (if the first byte is not). We could then check for
+ following runs of zeros, and if above a certain size it is
+ worth the 4 or 8 character hit of the byte insertions used
+ to pad to the start of the zeroes. NOTE: This also depends
+ on the alignment at the end of the zero run. */
+ if (value == 0x00000000) {
+ (*zerofill)++;
+ if (*zerofill == 0xFFF) /* 12bit counter */
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ }else {
+ if (*zerofill != 0)
+ *recsize = pmon_zeroset (*recsize, &p, zerofill, csum);
+ count = pmon_makeb64 (value, p, 24, csum);
+ p += count;
+ *recsize += count;
+ }
+ *inptr += 3;
+ }
+ }
+
+ *outbuf = p;
+ return;
+}
+
+#if defined(DOETXACK)
+static int
+pmon_check_ack()
+{
+ int c = SERIAL_READCHAR (mips_desc, 2);
+ if ((c == SERIAL_TIMEOUT) || (c != 0x06)) {
+ fprintf_unfiltered (gdb_stderr, "Failed to receive valid ACK\n");
+ return(-1); /* terminate the download */
+ }
+ return(0);
+}
+#endif /* DOETXACK */
+
+static void
+pmon_load_fast (file)
+ char *file;
+{
+ bfd *abfd;
+ asection *s;
+ unsigned char *binbuf;
+ char *buffer;
+ int reclen;
+ unsigned int csum = 0;
+ static int hashmark = 1;
+ int bintotal = 0;
+ int final;
+ int finished = 0;
+
+ buffer = (char *)xmalloc(MAXRECSIZE + 1);
+ binbuf = (unsigned char *)xmalloc(BINCHUNK);
+
+ abfd = bfd_openr(file,0);
+ if (!abfd)
+ {
+ printf_filtered ("Unable to open file %s\n",file);
+ return;
+ }
+
+ if (bfd_check_format(abfd,bfd_object) == 0)
+ {
+ printf_filtered("File is not an object file\n");
+ return;
+ }
+
+ /* Setup the required download state: */
+ mips_send_command ("set dlproto etxack\015", -1);
+ mips_send_command ("set dlecho off\015", -1);
+ /* NOTE: We get a "cannot set variable" message if the variable is
+ already defined to have the argument we give. The code doesn't
+ care, since it just scans to the next prompt anyway. */
+ /* Start the download: */
+ mips_send_command (LOAD_CMD, 0);
+ mips_expect ("Downloading from tty0, ^C to abort\015\012");
+
+ /* Zero the checksum */
+ sprintf(buffer,"/Kxx\015");
+ reclen = strlen(buffer);
+ SERIAL_WRITE (mips_desc, buffer, reclen);
+
+#if defined(DOETXACK)
+ finished = pmon_check_ack();
+#endif /* DOETXACK */
+
+ for (s = abfd->sections; s && !finished; s = s->next)
+ if (s->flags & SEC_LOAD) /* only deal with loadable sections */
+ {
+ bintotal += s->_raw_size;
+ final = (s->vma + s->_raw_size);
+
+ printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
+ s->vma + s->_raw_size);
+ gdb_flush (gdb_stdout);
+
+ /* Output the starting address */
+ sprintf(buffer,"/A");
+ reclen = pmon_makeb64(s->vma,&buffer[2],36,&csum);
+ buffer[2 + reclen] = '\015';
+ buffer[3 + reclen] = '\0';
+ reclen += 3; /* for the initial escape code and carriage return */
+ SERIAL_WRITE (mips_desc, buffer, reclen);
+#if defined(DOETXACK)
+ finished = pmon_check_ack();
+#endif /* DOETXACK */
+
+ if (!finished)
+ {
+ int binamount;
+ unsigned int zerofill = 0;
+ char *bp = buffer;
+ int i;
+
+ reclen = 0;
+
+ for (i = 0; ((i < s->_raw_size) && !finished); i += binamount) {
+ int binptr = 0;
+
+ binamount = min (BINCHUNK, s->_raw_size - i);
+
+ bfd_get_section_contents (abfd, s, binbuf, i, binamount);
+
+ /* This keeps a rolling checksum, until we decide to output
+ the line: */
+ for (; ((binamount - binptr) > 0);) {
+ pmon_make_fastrec (&bp, binbuf, &binptr, binamount, &reclen, &csum, &zerofill);
+ if (reclen >= (MAXRECSIZE - CHECKSIZE)) {
+ reclen = pmon_checkset (reclen, &bp, &csum);
+ SERIAL_WRITE (mips_desc, buffer, reclen);
+#if defined(DOETXACK)
+ finished = pmon_check_ack();
+ if (finished) {
+ zerofill = 0; /* do not transmit pending zerofills */
+ break;
+ }
+#endif /* DOETXACK */
+
+ if (hashmark) {
+ putchar_unfiltered ('#');
+ gdb_flush (gdb_stdout);
+ }
+
+ bp = buffer;
+ reclen = 0; /* buffer processed */
+ }
+ }
+ }
+
+ /* Ensure no out-standing zerofill requests: */
+ if (zerofill != 0)
+ reclen = pmon_zeroset (reclen, &bp, &zerofill, &csum);
+
+ /* and then flush the line: */
+ if (reclen > 0) {
+ reclen = pmon_checkset (reclen, &bp, &csum);
+ /* Currently pmon_checkset outputs the line terminator by
+ default, so we write out the buffer so far: */
+ SERIAL_WRITE (mips_desc, buffer, reclen);
+#if defined(DOETXACK)
+ finished = pmon_check_ack();
+#endif /* DOETXACK */
+ }
+ }
+
+ if (hashmark)
+ putchar_unfiltered ('\n');
+ }
+
+ /* Terminate the transfer. We know that we have an empty output
+ buffer at this point. */
+ sprintf (buffer, "/E/E\015"); /* include dummy padding characters */
+ reclen = strlen (buffer);
+ SERIAL_WRITE (mips_desc, buffer, reclen);
+
+ if (finished) { /* Ignore the termination message: */
+ SERIAL_FLUSH_INPUT (mips_desc);
+ } else { /* Deal with termination message: */
+ char hexnumber[9]; /* includes '\0' space */
+ mips_expect ("Entry Address = ");
+ sprintf(hexnumber,"%x",final);
+ mips_expect (hexnumber);
+#if defined(DOETXACK)
+ mips_expect ("\015\012\006\015\012total = 0x");
+#else /* normal termination */
+ mips_expect ("\015\012\015\012total = 0x");
+#endif /* !DOETXACK */
+ sprintf(hexnumber,"%x",bintotal);
+ mips_expect (hexnumber);
+ mips_expect (" bytes\015\012");
+ }
+
+ return;
+}
+
+/* mips_load -- download a file. */
+
+static void
+mips_load (file, from_tty)
+ char *file;
+ int from_tty;
+{
+ /* Get the board out of remote debugging mode. */
+ if (mips_exit_debug ())
+ error ("mips_load: Couldn't get into monitor mode.");
+
+ if (mips_monitor == MON_PMON)
+ pmon_load_fast (file);
+ else
+ mips_load_srec (file);
+
+ mips_initialize ();
+
+/* Finally, make the PC point at the start address */
+
+ if (exec_bfd)
+ write_pc (bfd_get_start_address (exec_bfd));
+
+ inferior_pid = 0; /* No process now */
+
+/* This is necessary because many things were based on the PC at the time that
+ we attached to the monitor, which is no longer valid now that we have loaded
+ new code (and just changed the PC). Another way to do this might be to call
+ normal_stop, except that the stack may not be valid, and things would get
+ horribly confused... */
+
+ clear_symtab_users ();
+}
+
+/* The target vector. */
+
+struct target_ops mips_ops =
+{
+ "mips", /* to_shortname */
+ "Remote MIPS debugging over serial line", /* to_longname */
+ "\
+Debug a board using the MIPS remote debugging protocol over a serial line.\n\
+The argument is the device it is connected to or, if it contains a colon,\n\
+HOST:PORT to access a board over a network", /* to_doc */
+ mips_open, /* to_open */
+ mips_close, /* to_close */
+ NULL, /* to_attach */
+ mips_detach, /* to_detach */
+ mips_resume, /* to_resume */
+ mips_wait, /* to_wait */
+ mips_fetch_registers, /* to_fetch_registers */
+ mips_store_registers, /* to_store_registers */
+ mips_prepare_to_store, /* to_prepare_to_store */
+ mips_xfer_memory, /* to_xfer_memory */
+ mips_files_info, /* to_files_info */
+ mips_insert_breakpoint, /* to_insert_breakpoint */
+ mips_remove_breakpoint, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ mips_kill, /* to_kill */
+ mips_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ mips_create_inferior, /* to_create_inferior */
+ mips_mourn_inferior, /* to_mourn_inferior */
+ NULL, /* to_can_run */
+ NULL, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+/* An alternative target vector: */
+struct target_ops pmon_ops =
+{
+ "pmon", /* to_shortname */
+ "Remote MIPS debugging over serial line", /* to_longname */
+ "\
+Debug a board using the PMON MIPS remote debugging protocol over a serial\n\
+line. The argument is the device it is connected to or, if it contains a\n\
+colon, HOST:PORT to access a board over a network", /* to_doc */
+ pmon_open, /* to_open */
+ mips_close, /* to_close */
+ NULL, /* to_attach */
+ mips_detach, /* to_detach */
+ mips_resume, /* to_resume */
+ pmon_wait, /* to_wait */
+ mips_fetch_registers, /* to_fetch_registers */
+ mips_store_registers, /* to_store_registers */
+ mips_prepare_to_store, /* to_prepare_to_store */
+ mips_xfer_memory, /* to_xfer_memory */
+ mips_files_info, /* to_files_info */
+ mips_insert_breakpoint, /* to_insert_breakpoint */
+ mips_remove_breakpoint, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ mips_kill, /* to_kill */
+ mips_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ mips_create_inferior, /* to_create_inferior */
+ mips_mourn_inferior, /* to_mourn_inferior */
+ NULL, /* to_can_run */
+ NULL, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_remote_mips ()
+{
+ add_target (&mips_ops);
+ add_target (&pmon_ops);
+
+ add_show_from_set (
+ add_set_cmd ("timeout", no_class, var_zinteger,
+ (char *) &mips_receive_wait,
+ "Set timeout in seconds for remote MIPS serial I/O.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("retransmit-timeout", no_class, var_zinteger,
+ (char *) &mips_retransmit_wait,
+ "Set retransmit timeout in seconds for remote MIPS serial I/O.\n\
+This is the number of seconds to wait for an acknowledgement to a packet\n\
+before resending the packet.", &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("syn-garbage-limit", no_class, var_zinteger,
+ (char *) &mips_syn_garbage,
+"Set the maximum number of characters to ignore when scanning for a SYN.\n\
+This is the maximum number of characters GDB will ignore when trying to\n\
+synchronize with the remote system. A value of -1 means that there is no limit\n\
+(Note that these characters are printed out even though they are ignored.)",
+ &setlist),
+ &showlist);
+}
diff --git a/contrib/gdb/gdb/remote-mm.c b/contrib/gdb/gdb/remote-mm.c
new file mode 100644
index 0000000..101d964
--- /dev/null
+++ b/contrib/gdb/gdb/remote-mm.c
@@ -0,0 +1,1627 @@
+/* Remote debugging interface for Am290*0 running MiniMON monitor, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Originally written by Daniel Mann at AMD.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but ecpects MiniMON to be running on the Am29000
+ target hardware.
+ - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
+ file to gdb 3.95. I was unable to get this working on sun3os4
+ with termio, only with sgtty. Because we are only attempting to
+ use this module to debug our kernel, which is already loaded when
+ gdb is started up, I did not code up the file downloading facilities.
+ As a result this module has only the stubs to download files.
+ You should get tagged at compile time if you need to make any
+ changes/additions. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "gdb_string.h"
+#include "terminal.h"
+#include "minimon.h"
+#include "target.h"
+
+/* Offset of member MEMBER in a struct of type TYPE. */
+#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
+
+#define DRAIN_INPUT() (msg_recv_serial((union msg_t*)0))
+
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+static void mm_resume();
+static void mm_fetch_registers ();
+static int fetch_register ();
+static void mm_store_registers ();
+static int store_register ();
+static int regnum_to_srnum();
+static void mm_close ();
+static char* msg_str();
+static char* error_msg_str();
+static int expect_msg();
+static void init_target_mm();
+static int mm_memory_space();
+
+#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
+#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
+
+/* FIXME: Replace with `set remotedebug'. */
+#define LLOG_FILE "minimon.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+/*
+ * Size of message buffers. I couldn't get memory reads to work when
+ * the byte_count was larger than 512 (it may be a baud rate problem).
+ */
+#define BUFER_SIZE 512
+/*
+ * Size of data area in message buffer on the TARGET (remote system).
+ */
+#define MAXDATA_T (target_config.max_msg_size - \
+ offsetof(struct write_r_msg_t,data[0]))
+/*
+ * Size of data area in message buffer on the HOST (gdb).
+ */
+#define MAXDATA_H (BUFER_SIZE - offsetof(struct write_r_msg_t,data[0]))
+/*
+ * Defined as the minimum size of data areas of the two message buffers
+ */
+#define MAXDATA (MAXDATA_H < MAXDATA_T ? MAXDATA_H : MAXDATA_T)
+
+static char out_buf[BUFER_SIZE];
+static char in_buf[BUFER_SIZE];
+
+int msg_recv_serial();
+int msg_send_serial();
+
+#define MAX_RETRIES 5000
+extern struct target_ops mm_ops; /* Forward declaration */
+struct config_msg_t target_config; /* HIF needs this */
+union msg_t *out_msg_buf = (union msg_t*)out_buf;
+union msg_t *in_msg_buf = (union msg_t*)in_buf;
+
+static int timeout = 5;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ mm_open knows that we don't have a file open when the program
+ starts. */
+int mm_desc = -1;
+
+/* stream which is fdopen'd from mm_desc. Only valid when
+ mm_desc != -1. */
+FILE *mm_stream;
+
+/* Called when SIGALRM signal sent due to alarm() timeout. */
+#ifndef HAVE_TERMIO
+
+#ifndef __STDC__
+# ifndef volatile
+# define volatile /**/
+# endif
+#endif
+volatile int n_alarms;
+
+static void
+mm_timer ()
+{
+#if 0
+ if (kiodebug)
+ printf ("mm_timer called\n");
+#endif
+ n_alarms++;
+}
+#endif /* HAVE_TERMIO */
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+
+/* Number of SIGTRAPs we need to simulate. That is, the next
+ NEED_ARTIFICIAL_TRAP calls to mm_wait should just return
+ SIGTRAP without actually waiting for anything. */
+
+/**************************************************** REMOTE_CREATE_INFERIOR */
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+mm_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+#define MAX_TOKENS 25
+#define BUFFER_SIZE 256
+ int token_count;
+ int result;
+ char *token[MAX_TOKENS];
+ char cmd_line[BUFFER_SIZE];
+
+ if (args && *args)
+ error ("Can't pass arguments to remote mm process (yet).");
+
+ if (execfile == 0 /* || exec_bfd == 0 */ )
+ error ("No exec file specified");
+
+ if (!mm_stream) {
+ printf("Minimon not open yet.\n");
+ return;
+ }
+
+ /* On ultra3 (NYU) we assume the kernel is already running so there is
+ no file to download.
+ FIXME: Fixed required here -> load your program, possibly with mm_load().
+ */
+ printf_filtered ("\n\
+Assuming you are at NYU debuging a kernel, i.e., no need to download.\n\n");
+
+ /* We will get a task spawn event immediately. */
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+ normal_stop ();
+}
+/**************************************************** REMOTE_MOURN_INFERIOR */
+static void
+mm_mourn()
+{
+ pop_target (); /* Pop back to no-child state */
+ generic_mourn_inferior ();
+}
+
+/********************************************************************** damn_b
+*/
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+static struct {int rate, damn_b;} baudtab[] = {
+ {0, B0},
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+static int damn_b (rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate) return baudtab[i].damn_b;
+ return B38400; /* Random */
+}
+
+
+/***************************************************************** REMOTE_OPEN
+** Open a connection to remote minimon.
+ NAME is the filename used for communication, then a space,
+ then the baud rate.
+ 'target adapt /dev/ttya 9600 [prognam]' for example.
+ */
+
+static char *dev_name;
+int baudrate = 9600;
+static void
+mm_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ TERMINAL sg;
+ unsigned int prl;
+ char *p;
+
+ /* Find the first whitespace character, it separates dev_name from
+ prog_name. */
+ for (p = name;
+ p && *p && !isspace (*p); p++)
+ ;
+ if (p == 0 || *p == '\0')
+erroid:
+ error ("Usage : <command> <serial-device> <baud-rate> [progname]");
+ dev_name = (char*)xmalloc (p - name + 1);
+ strncpy (dev_name, name, p - name);
+ dev_name[p - name] = '\0';
+
+ /* Skip over the whitespace after dev_name */
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (1 != sscanf (p, "%d ", &baudrate))
+ goto erroid;
+
+ /* Skip the number and then the spaces */
+ for (; isdigit (*p); p++)
+ /*EMPTY*/;
+ for (; isspace (*p); p++)
+ /*EMPTY*/;
+
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (p, strlen (p));
+
+
+ if (mm_desc >= 0)
+ close (mm_desc);
+
+ mm_desc = open (dev_name, O_RDWR);
+ if (mm_desc < 0)
+ perror_with_name (dev_name);
+ ioctl (mm_desc, TIOCGETP, &sg);
+#ifdef HAVE_TERMIO
+ sg.c_cc[VMIN] = 0; /* read with timeout. */
+ sg.c_cc[VTIME] = timeout * 10;
+ sg.c_lflag &= ~(ICANON | ECHO);
+ sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
+#else
+ sg.sg_ispeed = damn_b (baudrate);
+ sg.sg_ospeed = damn_b (baudrate);
+ sg.sg_flags |= RAW;
+ sg.sg_flags |= ANYP;
+ sg.sg_flags &= ~ECHO;
+#endif
+
+
+ ioctl (mm_desc, TIOCSETP, &sg);
+ mm_stream = fdopen (mm_desc, "r+");
+
+ push_target (&mm_ops);
+
+#ifndef HAVE_TERMIO
+#ifndef NO_SIGINTERRUPT
+ /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
+ the read. */
+ if (siginterrupt (SIGALRM, 1) != 0)
+ perror ("mm_open: error in siginterrupt");
+#endif
+
+ /* Set up read timeout timer. */
+ if ((void (*)) signal (SIGALRM, mm_timer) == (void (*)) -1)
+ perror ("mm_open: error in signal");
+#endif
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+ /*
+ ** Initialize target configuration structure (global)
+ */
+ DRAIN_INPUT();
+ out_msg_buf->config_req_msg.code = CONFIG_REQ;
+ out_msg_buf->config_req_msg.length = 4*0;
+ msg_send_serial(out_msg_buf); /* send config request message */
+
+ expect_msg(CONFIG,in_msg_buf,1);
+
+ a29k_get_processor_type ();
+
+ /* Print out some stuff, letting the user now what's going on */
+ printf_filtered("Connected to MiniMon via %s.\n", dev_name);
+ /* FIXME: can this restriction be removed? */
+ printf_filtered("Remote debugging using virtual addresses works only\n");
+ printf_filtered("\twhen virtual addresses map 1:1 to physical addresses.\n")
+;
+ if (processor_type != a29k_freeze_mode) {
+ fprintf_filtered(stderr,
+ "Freeze-mode debugging not available, and can only be done on an A29050.\n");
+ }
+
+ target_config.code = CONFIG;
+ target_config.length = 0;
+ target_config.processor_id = in_msg_buf->config_msg.processor_id;
+ target_config.version = in_msg_buf->config_msg.version;
+ target_config.I_mem_start = in_msg_buf->config_msg.I_mem_start;
+ target_config.I_mem_size = in_msg_buf->config_msg.I_mem_size;
+ target_config.D_mem_start = in_msg_buf->config_msg.D_mem_start;
+ target_config.D_mem_size = in_msg_buf->config_msg.D_mem_size;
+ target_config.ROM_start = in_msg_buf->config_msg.ROM_start;
+ target_config.ROM_size = in_msg_buf->config_msg.ROM_size;
+ target_config.max_msg_size = in_msg_buf->config_msg.max_msg_size;
+ target_config.max_bkpts = in_msg_buf->config_msg.max_bkpts;
+ target_config.coprocessor = in_msg_buf->config_msg.coprocessor;
+ target_config.reserved = in_msg_buf->config_msg.reserved;
+ if (from_tty) {
+ printf("Connected to MiniMON :\n");
+ printf(" Debugcore version %d.%d\n",
+ 0x0f & (target_config.version >> 4),
+ 0x0f & (target_config.version ) );
+ printf(" Configuration version %d.%d\n",
+ 0x0f & (target_config.version >> 12),
+ 0x0f & (target_config.version >> 8) );
+ printf(" Message system version %d.%d\n",
+ 0x0f & (target_config.version >> 20),
+ 0x0f & (target_config.version >> 16) );
+ printf(" Communication driver version %d.%d\n",
+ 0x0f & (target_config.version >> 28),
+ 0x0f & (target_config.version >> 24) );
+ }
+
+ /* Leave the target running...
+ * The above message stopped the target in the dbg core (MiniMon),
+ * so restart the target out of MiniMon,
+ */
+ out_msg_buf->go_msg.code = GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ /* No message to expect after a GO */
+}
+
+/**************************************************************** REMOTE_CLOSE
+** Close the open connection to the minimon debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+mm_close (quitting) /*FIXME: how is quitting used */
+ int quitting;
+{
+ if (mm_desc < 0)
+ error ("Can't close remote connection: not debugging remotely.");
+
+ /* We should never get here if there isn't something valid in
+ mm_desc and mm_stream.
+
+ Due to a bug in Unix, fclose closes not only the stdio stream,
+ but also the file descriptor. So we don't actually close
+ mm_desc. */
+ DRAIN_INPUT();
+ fclose (mm_stream);
+ /* close (mm_desc); */
+
+ /* Do not try to close mm_desc again, later in the program. */
+ mm_stream = NULL;
+ mm_desc = -1;
+
+#if defined (LOG_FILE)
+ if (ferror (log_file))
+ printf ("Error writing log file.\n");
+ if (fclose (log_file) != 0)
+ printf ("Error closing log file.\n");
+#endif
+
+ printf ("Ending remote debugging\n");
+}
+
+/************************************************************* REMOTE_ATACH */
+/* Attach to a program that is already loaded and running
+ * Upon exiting the process's execution is stopped.
+ */
+static void
+mm_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+
+ if (!mm_stream)
+ error ("MiniMon not opened yet, use the 'target minimon' command.\n");
+
+ if (from_tty)
+ printf ("Attaching to remote program %s...\n", prog_name);
+
+ /* Make sure the target is currently running, it is supposed to be. */
+ /* FIXME: is it ok to send MiniMon a BREAK if it is already stopped in
+ * the dbg core. If so, we don't need to send this GO.
+ */
+ out_msg_buf->go_msg.code = GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ sleep(2); /* At the worst it will stop, receive a message, continue */
+
+ /* Send the mm a break. */
+ out_msg_buf->break_msg.code = BREAK;
+ out_msg_buf->break_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+}
+/********************************************************** REMOTE_DETACH */
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. Leave remote process running (with no breakpoints set). */
+static void
+mm_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+ remove_breakpoints(); /* Just in case there were any left in */
+ out_msg_buf->go_msg.code = GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ pop_target(); /* calls mm_close to do the real work */
+}
+
+
+/*************************************************************** REMOTE_RESUME
+** Tell the remote machine to resume. */
+
+static void
+mm_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (sig != TARGET_SIGNAL_0)
+ warning ("Can't send signals to a remote MiniMon system.");
+
+ if (step) {
+ out_msg_buf->step_msg.code= STEP;
+ out_msg_buf->step_msg.length = 1*4;
+ out_msg_buf->step_msg.count = 1; /* step 1 instruction */
+ msg_send_serial(out_msg_buf);
+ } else {
+ out_msg_buf->go_msg.code= GO;
+ out_msg_buf->go_msg.length = 0;
+ msg_send_serial(out_msg_buf);
+ }
+}
+
+/***************************************************************** REMOTE_WAIT
+** Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static int
+mm_wait (status)
+ struct target_waitstatus *status;
+{
+ int i, result;
+ int old_timeout = timeout;
+ int old_immediate_quit = immediate_quit;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+/* wait for message to arrive. It should be:
+ - A HIF service request.
+ - A HIF exit service request.
+ - A CHANNEL0_ACK.
+ - A CHANNEL1 request.
+ - a debugcore HALT message.
+ HIF services must be responded too, and while-looping continued.
+ If the target stops executing, mm_wait() should return.
+*/
+ timeout = 0; /* Wait indefinetly for a message */
+ immediate_quit = 1; /* Helps ability to QUIT */
+ while(1)
+ {
+ while(msg_recv_serial(in_msg_buf)) {
+ QUIT; /* Let user quit if they want */
+ }
+ switch (in_msg_buf->halt_msg.code)
+ {
+ case HIF_CALL:
+ i = in_msg_buf->hif_call_rtn_msg.service_number;
+ result=service_HIF(in_msg_buf);
+ if(i == 1) /* EXIT */
+ goto exit;
+ if(result)
+ printf("Warning: failure during HIF service %d\n", i);
+ break;
+ case CHANNEL0_ACK:
+ service_HIF(in_msg_buf);
+ break;
+ case CHANNEL1:
+ i=in_msg_buf->channel1_msg.length;
+ in_msg_buf->channel1_msg.data[i] = '\0';
+ printf("%s", in_msg_buf->channel1_msg.data);
+ gdb_flush(stdout);
+ /* Send CHANNEL1_ACK message */
+ out_msg_buf->channel1_ack_msg.code = CHANNEL1_ACK;
+ out_msg_buf->channel1_ack_msg.length = 0;
+ result = msg_send_serial(out_msg_buf);
+ break;
+ case HALT:
+ goto halted;
+ default:
+ goto halted;
+ }
+ }
+halted:
+ /* FIXME, these printfs should not be here. This is a source level
+ debugger, guys! */
+ if (in_msg_buf->halt_msg.trap_number== 0)
+ { printf("Am290*0 received vector number %d (break point)\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 1)
+ {
+ printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_BUS;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 3
+ || in_msg_buf->halt_msg.trap_number== 4)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_FPE;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 5)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ }
+ else if (in_msg_buf->halt_msg.trap_number >= 6
+ && in_msg_buf->halt_msg.trap_number <= 11)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_SEGV;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 12
+ || in_msg_buf->halt_msg.trap_number== 13)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 14)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ALRM;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 15)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else if (in_msg_buf->halt_msg.trap_number >= 16
+ && in_msg_buf->halt_msg.trap_number <= 21)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_INT;
+ }
+ else if (in_msg_buf->halt_msg.trap_number== 22)
+ { printf("Am290*0 received vector number %d\n",
+ in_msg_buf->halt_msg.trap_number);
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ } /* BREAK message was sent */
+ else if (in_msg_buf->halt_msg.trap_number== 75)
+ {
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ }
+ else
+exit:
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+
+ timeout = old_timeout; /* Restore original timeout value */
+ immediate_quit = old_immediate_quit;
+ return 0;
+}
+
+/******************************************************* REMOTE_FETCH_REGISTERS
+ * Read a remote register 'regno'.
+ * If regno==-1 then read all the registers.
+ */
+static void
+mm_fetch_registers (regno)
+int regno;
+{
+ INT32 *data_p;
+
+ if (regno >= 0) {
+ fetch_register(regno);
+ return;
+ }
+
+/* Gr1/rsp */
+ out_msg_buf->read_req_msg.byte_count = 4*1;
+ out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 1;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+ supply_register (GR1_REGNUM , data_p);
+
+#if defined(GR64_REGNUM) /* Read gr64-127 */
+/* Global Registers gr64-gr95 */
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.length = 4*3;
+ out_msg_buf->read_req_msg.byte_count = 4*32;
+ out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 64;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=GR64_REGNUM; regno<GR64_REGNUM+32; regno++) {
+ supply_register (regno, data_p++);
+ }
+#endif /* GR64_REGNUM */
+
+/* Global Registers gr96-gr127 */
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.length = 4*3;
+ out_msg_buf->read_req_msg.byte_count = 4 * 32;
+ out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 96;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=GR96_REGNUM; regno<GR96_REGNUM+32; regno++) {
+ supply_register (regno, data_p++);
+ }
+
+/* Local Registers */
+ out_msg_buf->read_req_msg.byte_count = 4 * (128);
+ out_msg_buf->read_req_msg.memory_space = LOCAL_REG;
+ out_msg_buf->read_req_msg.address = 0;
+ msg_send_serial(out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=LR0_REGNUM; regno<LR0_REGNUM+128; regno++) {
+ supply_register (regno, data_p++);
+ }
+
+/* Protected Special Registers */
+ out_msg_buf->read_req_msg.byte_count = 4*15;
+ out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->read_req_msg.address = 0;
+ msg_send_serial( out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=0; regno<=14; regno++) {
+ supply_register (SR_REGNUM(regno), data_p++);
+ }
+ if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
+ fetch_register(NPC_REGNUM);
+ fetch_register(PC_REGNUM);
+ fetch_register(PC2_REGNUM);
+ }
+
+/* Unprotected Special Registers */
+ out_msg_buf->read_req_msg.byte_count = 4*8;
+ out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->read_req_msg.address = 128;
+ msg_send_serial( out_msg_buf);
+ expect_msg(READ_ACK,in_msg_buf,1);
+ data_p = &(in_msg_buf->read_r_ack_msg.data[0]);
+
+ for (regno=128; regno<=135; regno++) {
+ supply_register (SR_REGNUM(regno), data_p++);
+ }
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, &val);
+ supply_register (INTE_REGNUM, &val);
+ supply_register (FPS_REGNUM, &val);
+ supply_register (EXO_REGNUM, &val);
+ }
+}
+
+
+/****************************************************** REMOTE_STORE_REGISTERS
+ * Store register regno into the target.
+ * If regno==-1 then store all the registers.
+ * Result is 0 for success, -1 for failure.
+ */
+
+static void
+mm_store_registers (regno)
+int regno;
+{
+ int result;
+
+ if (regno >= 0) {
+ store_register(regno);
+ return;
+ }
+
+ result = 0;
+
+ out_msg_buf->write_r_msg.code= WRITE_REQ;
+
+/* Gr1/rsp */
+ out_msg_buf->write_r_msg.byte_count = 4*1;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_r_msg.address = 1;
+ out_msg_buf->write_r_msg.data[0] = read_register (GR1_REGNUM);
+
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+#if defined(GR64_REGNUM)
+/* Global registers gr64-gr95 */
+ out_msg_buf->write_r_msg.byte_count = 4* (32);
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 64;
+
+ for (regno=GR64_REGNUM ; regno<GR64_REGNUM+32 ; regno++)
+ {
+ out_msg_buf->write_r_msg.data[regno-GR64_REGNUM] = read_register (regno);
+ }
+ msg_send_serial(out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+#endif /* GR64_REGNUM */
+
+/* Global registers gr96-gr127 */
+ out_msg_buf->write_r_msg.byte_count = 4* (32);
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 96;
+ for (regno=GR96_REGNUM ; regno<GR96_REGNUM+32 ; regno++)
+ {
+ out_msg_buf->write_r_msg.data[regno-GR96_REGNUM] = read_register (regno);
+ }
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+/* Local Registers */
+ out_msg_buf->write_r_msg.memory_space = LOCAL_REG;
+ out_msg_buf->write_r_msg.byte_count = 4*128;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 0;
+
+ for (regno = LR0_REGNUM ; regno < LR0_REGNUM+128 ; regno++)
+ {
+ out_msg_buf->write_r_msg.data[regno-LR0_REGNUM] = read_register (regno);
+ }
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+/* Protected Special Registers */
+ /* VAB through TMR */
+ out_msg_buf->write_r_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->write_r_msg.byte_count = 4* 10;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 0;
+ for (regno = 0 ; regno<=9 ; regno++) /* VAB through TMR */
+ out_msg_buf->write_r_msg.data[regno] = read_register (SR_REGNUM(regno));
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+ /* PC0, PC1, PC2 possibly as shadow registers */
+ out_msg_buf->write_r_msg.byte_count = 4* 3;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ for (regno=10 ; regno<=12 ; regno++) /* LRU and MMU */
+ out_msg_buf->write_r_msg.data[regno-10] = read_register (SR_REGNUM(regno));
+ if (USE_SHADOW_PC)
+ out_msg_buf->write_r_msg.address = 20; /* SPC0 */
+ else
+ out_msg_buf->write_r_msg.address = 10; /* PC0 */
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+ /* LRU and MMU */
+ out_msg_buf->write_r_msg.byte_count = 4* 2;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 13;
+ for (regno=13 ; regno<=14 ; regno++) /* LRU and MMU */
+ out_msg_buf->write_r_msg.data[regno-13] = read_register (SR_REGNUM(regno));
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+/* Unprotected Special Registers */
+ out_msg_buf->write_r_msg.byte_count = 4*8;
+ out_msg_buf->write_r_msg.length = 3*4 + out_msg_buf->write_r_msg.byte_count;
+ out_msg_buf->write_r_msg.address = 128;
+ for (regno = 128 ; regno<=135 ; regno++)
+ out_msg_buf->write_r_msg.data[regno-128] = read_register(SR_REGNUM(regno));
+ msg_send_serial( out_msg_buf);
+ if (!expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = -1;
+ }
+
+ registers_changed ();
+}
+
+/*************************************************** REMOTE_PREPARE_TO_STORE */
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+mm_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+/******************************************************* REMOTE_XFER_MEMORY */
+static CORE_ADDR
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(KERNEL_DEBUGGING)
+ /* Check for a virtual address in the kernel */
+ /* Assume physical address of ublock is in paddr_u register */
+ /* FIXME: doesn't work for user virtual addresses */
+ if (addr >= UVADDR) {
+ /* PADDR_U register holds the physical address of the ublock */
+ CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
+ return(i + addr - (CORE_ADDR)UVADDR);
+ } else {
+ return(addr);
+ }
+#else
+ return(addr);
+#endif
+}
+
+/******************************************************* REMOTE_FILES_INFO */
+static void
+mm_files_info ()
+{
+ printf ("\tAttached to %s at %d baud and running program %s.\n",
+ dev_name, baudrate, prog_name);
+}
+
+/************************************************* REMOTE_INSERT_BREAKPOINT */
+static int
+mm_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ out_msg_buf->bkpt_set_msg.code = BKPT_SET;
+ out_msg_buf->bkpt_set_msg.length = 4*4;
+ out_msg_buf->bkpt_set_msg.memory_space = I_MEM;
+ out_msg_buf->bkpt_set_msg.bkpt_addr = (ADDR32) addr;
+ out_msg_buf->bkpt_set_msg.pass_count = 1;
+ out_msg_buf->bkpt_set_msg.bkpt_type = -1; /* use illop for 29000 */
+ msg_send_serial( out_msg_buf);
+ if (expect_msg(BKPT_SET_ACK,in_msg_buf,1)) {
+ return 0; /* Success */
+ } else {
+ return 1; /* Failure */
+ }
+}
+
+/************************************************* REMOTE_DELETE_BREAKPOINT */
+static int
+mm_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ out_msg_buf->bkpt_rm_msg.code = BKPT_RM;
+ out_msg_buf->bkpt_rm_msg.length = 4*3;
+ out_msg_buf->bkpt_rm_msg.memory_space = I_MEM;
+ out_msg_buf->bkpt_rm_msg.bkpt_addr = (ADDR32) addr;
+ msg_send_serial( out_msg_buf);
+ if (expect_msg(BKPT_RM_ACK,in_msg_buf,1)) {
+ return 0; /* Success */
+ } else {
+ return 1; /* Failure */
+ }
+}
+
+
+/******************************************************* REMOTE_KILL */
+static void
+mm_kill(arg,from_tty)
+char *arg;
+int from_tty;
+{
+ char buf[4];
+
+#if defined(KERNEL_DEBUGGING)
+ /* We don't ever kill the kernel */
+ if (from_tty) {
+ printf("Kernel not killed, but left in current state.\n");
+ printf("Use detach to leave kernel running.\n");
+ }
+#else
+ out_msg_buf->break_msg.code = BREAK;
+ out_msg_buf->bkpt_set_msg.length = 4*0;
+ expect_msg(HALT,in_msg_buf,from_tty);
+ if (from_tty) {
+ printf("Target has been stopped.");
+ printf("Would you like to do a hardware reset (y/n) [n] ");
+ fgets(buf,3,stdin);
+ if (buf[0] == 'y') {
+ out_msg_buf->reset_msg.code = RESET;
+ out_msg_buf->bkpt_set_msg.length = 4*0;
+ expect_msg(RESET_ACK,in_msg_buf,from_tty);
+ printf("Target has been reset.");
+ }
+ }
+ pop_target();
+#endif
+}
+
+
+
+/***************************************************************************/
+/*
+ * Load a program into the target.
+ */
+static void
+mm_load(arg_string,from_tty)
+char *arg_string;
+int from_tty;
+{
+ dont_repeat ();
+
+#if defined(KERNEL_DEBUGGING)
+ printf("The kernel had better be loaded already! Loading not done.\n");
+#else
+ if (arg_string == 0)
+ error ("The load command takes a file name");
+
+ arg_string = tilde_expand (arg_string);
+ make_cleanup (free, arg_string);
+ QUIT;
+ immediate_quit++;
+ error("File loading is not yet supported for MiniMon.");
+ /* FIXME, code to load your file here... */
+ /* You may need to do an init_target_mm() */
+ /* init_target_mm(?,?,?,?,?,?,?,?); */
+ immediate_quit--;
+ /* symbol_file_add (arg_string, from_tty, text_addr, 0, 0); */
+#endif
+
+}
+
+/************************************************ REMOTE_WRITE_INFERIOR_MEMORY
+** Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns number of bytes written. */
+static int
+mm_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i,nwritten;
+
+ out_msg_buf->write_req_msg.code= WRITE_REQ;
+ out_msg_buf->write_req_msg.memory_space = mm_memory_space(memaddr);
+
+ nwritten=0;
+ while (nwritten < len) {
+ int num_to_write = len - nwritten;
+ if (num_to_write > MAXDATA) num_to_write = MAXDATA;
+ for (i=0 ; i < num_to_write ; i++)
+ out_msg_buf->write_req_msg.data[i] = myaddr[i+nwritten];
+ out_msg_buf->write_req_msg.byte_count = num_to_write;
+ out_msg_buf->write_req_msg.length = 3*4 + num_to_write;
+ out_msg_buf->write_req_msg.address = memaddr + nwritten;
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ nwritten += in_msg_buf->write_ack_msg.byte_count;
+ } else {
+ break;
+ }
+ }
+ return(nwritten);
+}
+
+/************************************************* REMOTE_READ_INFERIOR_MEMORY
+** Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns number of bytes read. */
+static int
+mm_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i,nread;
+
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.memory_space = mm_memory_space(memaddr);
+
+ nread=0;
+ while (nread < len) {
+ int num_to_read = (len - nread);
+ if (num_to_read > MAXDATA) num_to_read = MAXDATA;
+ out_msg_buf->read_req_msg.byte_count = num_to_read;
+ out_msg_buf->read_req_msg.length = 3*4 + num_to_read;
+ out_msg_buf->read_req_msg.address = memaddr + nread;
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(READ_ACK,in_msg_buf,1)) {
+ for (i=0 ; i<in_msg_buf->read_ack_msg.byte_count ; i++)
+ myaddr[i+nread] = in_msg_buf->read_ack_msg.data[i];
+ nread += in_msg_buf->read_ack_msg.byte_count;
+ } else {
+ break;
+ }
+ }
+ return(nread);
+}
+
+/* FIXME! Merge these two. */
+static int
+mm_xfer_inferior_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+
+ memaddr = translate_addr(memaddr);
+
+ if (write)
+ return mm_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return mm_read_inferior_memory (memaddr, myaddr, len);
+}
+
+
+/********************************************************** MSG_SEND_SERIAL
+** This function is used to send a message over the
+** serial line.
+**
+** If the message is successfully sent, a zero is
+** returned. If the message was not sendable, a -1
+** is returned. This function blocks. That is, it
+** does not return until the message is completely
+** sent, or until an error is encountered.
+**
+*/
+
+int
+msg_send_serial(msg_ptr)
+ union msg_t *msg_ptr;
+{
+ INT32 message_size;
+ int byte_count;
+ int result;
+ char c;
+
+ /* Send message header */
+ byte_count = 0;
+ message_size = msg_ptr->generic_msg.length + (2 * sizeof(INT32));
+ do {
+ c = *((char *)msg_ptr+byte_count);
+ result = write(mm_desc, &c, 1);
+ if (result == 1) {
+ byte_count = byte_count + 1;
+ }
+ } while ((byte_count < message_size) );
+
+ return(0);
+} /* end msg_send_serial() */
+
+/********************************************************** MSG_RECV_SERIAL
+** This function is used to receive a message over a
+** serial line.
+**
+** If the message is waiting in the buffer, a zero is
+** returned and the buffer pointed to by msg_ptr is filled
+** in. If no message was available, a -1 is returned.
+** If timeout==0, wait indefinetly for a character.
+**
+*/
+
+int
+msg_recv_serial(msg_ptr)
+union msg_t *msg_ptr;
+{
+ static INT32 length=0;
+ static INT32 byte_count=0;
+ int result;
+ char c;
+ if(msg_ptr == 0) /* re-sync request */
+ { length=0;
+ byte_count=0;
+#ifdef HAVE_TERMIO
+ /* The timeout here is the prevailing timeout set with VTIME */
+ ->"timeout==0 semantics not supported"
+ read(mm_desc, in_buf, BUFER_SIZE);
+#else
+ alarm (1);
+ read(mm_desc, in_buf, BUFER_SIZE);
+ alarm (0);
+#endif
+ return(0);
+ }
+ /* Receive message */
+#ifdef HAVE_TERMIO
+/* Timeout==0, help support the mm_wait() routine */
+ ->"timeout==0 semantics not supported (and its nice if they are)"
+ result = read(mm_desc, &c, 1);
+#else
+ alarm(timeout);
+ result = read(mm_desc, &c, 1);
+ alarm (0);
+#endif
+ if ( result < 0) {
+ if (errno == EINTR) {
+ error ("Timeout reading from remote system.");
+ } else
+ perror_with_name ("remote");
+ } else if (result == 1) {
+ *((char *)msg_ptr+byte_count) = c;
+ byte_count = byte_count + 1;
+ }
+
+ /* Message header received. Save message length. */
+ if (byte_count == (2 * sizeof(INT32)))
+ length = msg_ptr->generic_msg.length;
+
+ if (byte_count >= (length + (2 * sizeof(INT32)))) {
+ /* Message received */
+ byte_count = 0;
+ return(0);
+ } else
+ return (-1);
+
+} /* end msg_recv_serial() */
+
+/********************************************************************* KBD_RAW
+** This function is used to put the keyboard in "raw"
+** mode for BSD Unix. The original status is saved
+** so that it may be restored later.
+*/
+TERMINAL kbd_tbuf;
+
+int
+kbd_raw() {
+ int result;
+ TERMINAL tbuf;
+
+ /* Get keyboard termio (to save to restore original modes) */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCGETA, &kbd_tbuf);
+#else
+ result = ioctl(0, TIOCGETP, &kbd_tbuf);
+#endif
+ if (result == -1)
+ return (errno);
+
+ /* Get keyboard TERMINAL (for modification) */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCGETA, &tbuf);
+#else
+ result = ioctl(0, TIOCGETP, &tbuf);
+#endif
+ if (result == -1)
+ return (errno);
+
+ /* Set up new parameters */
+#ifdef HAVE_TERMIO
+ tbuf.c_iflag = tbuf.c_iflag &
+ ~(INLCR | ICRNL | IUCLC | ISTRIP | IXON | BRKINT);
+ tbuf.c_lflag = tbuf.c_lflag & ~(ICANON | ISIG | ECHO);
+ tbuf.c_cc[4] = 0; /* MIN */
+ tbuf.c_cc[5] = 0; /* TIME */
+#else
+ /* FIXME: not sure if this is correct (matches HAVE_TERMIO). */
+ tbuf.sg_flags |= RAW;
+ tbuf.sg_flags |= ANYP;
+ tbuf.sg_flags &= ~ECHO;
+#endif
+
+ /* Set keyboard termio to new mode (RAW) */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCSETAF, &tbuf);
+#else
+ result = ioctl(0, TIOCSETP, &tbuf);
+#endif
+ if (result == -1)
+ return (errno);
+
+ return (0);
+} /* end kbd_raw() */
+
+
+
+/***************************************************************** KBD_RESTORE
+** This function is used to put the keyboard back in the
+** mode it was in before kbk_raw was called. Note that
+** kbk_raw() must have been called at least once before
+** kbd_restore() is called.
+*/
+
+int
+kbd_restore() {
+ int result;
+
+ /* Set keyboard termio to original mode */
+#ifdef HAVE_TERMIO
+ result = ioctl(0, TCSETAF, &kbd_tbuf);
+#else
+ result = ioctl(0, TIOCGETP, &kbd_tbuf);
+#endif
+
+ if (result == -1)
+ return (errno);
+
+ return(0);
+} /* end kbd_cooked() */
+
+
+/*****************************************************************************/
+/* Fetch a single register indicatated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static int
+fetch_register (regno)
+ int regno;
+{
+ int result;
+ out_msg_buf->read_req_msg.code= READ_REQ;
+ out_msg_buf->read_req_msg.length = 4*3;
+ out_msg_buf->read_req_msg.byte_count = 4;
+
+ if (regno == GR1_REGNUM)
+ { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = 1;
+ }
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = (regno - GR96_REGNUM) + 96;
+ }
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ { out_msg_buf->read_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->read_req_msg.address = (regno - GR64_REGNUM) + 64;
+ }
+#endif /* GR64_REGNUM */
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ { out_msg_buf->read_req_msg.memory_space = LOCAL_REG;
+ out_msg_buf->read_req_msg.address = (regno - LR0_REGNUM);
+ }
+ else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
+ { int val = -1;
+ supply_register(160 + (regno - FPE_REGNUM),&val);
+ return 0; /* Pretend Success */
+ }
+ else
+ { out_msg_buf->read_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->read_req_msg.address = regnum_to_srnum(regno);
+ }
+
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(READ_ACK,in_msg_buf,1)) {
+ supply_register (regno, &(in_msg_buf->read_r_ack_msg.data[0]));
+ result = 0;
+ } else {
+ result = -1;
+ }
+ return result;
+}
+/*****************************************************************************/
+/* Store a single register indicated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static int
+store_register (regno)
+ int regno;
+{
+ int result;
+
+ out_msg_buf->write_req_msg.code= WRITE_REQ;
+ out_msg_buf->write_req_msg.length = 4*4;
+ out_msg_buf->write_req_msg.byte_count = 4;
+ out_msg_buf->write_r_msg.data[0] = read_register (regno);
+
+ if (regno == GR1_REGNUM)
+ { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_req_msg.address = 1;
+ /* Setting GR1 changes the numbers of all the locals, so invalidate the
+ * register cache. Do this *after* calling read_register, because we want
+ * read_register to return the value that write_register has just stuffed
+ * into the registers array, not the value of the register fetched from
+ * the inferior.
+ */
+ registers_changed ();
+ }
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_req_msg.address = (regno - GR64_REGNUM) + 64;
+ }
+#endif /* GR64_REGNUM */
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ { out_msg_buf->write_req_msg.memory_space = GLOBAL_REG;
+ out_msg_buf->write_req_msg.address = (regno - GR96_REGNUM) + 96;
+ }
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ { out_msg_buf->write_req_msg.memory_space = LOCAL_REG;
+ out_msg_buf->write_req_msg.address = (regno - LR0_REGNUM);
+ }
+ else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
+ {
+ return 0; /* Pretend Success */
+ }
+ else /* An unprotected or protected special register */
+ { out_msg_buf->write_req_msg.memory_space = SPECIAL_REG;
+ out_msg_buf->write_req_msg.address = regnum_to_srnum(regno);
+ }
+
+ msg_send_serial(out_msg_buf);
+
+ if (expect_msg(WRITE_ACK,in_msg_buf,1)) {
+ result = 0;
+ } else {
+ result = -1;
+ }
+ return result;
+}
+/****************************************************************************/
+/*
+ * Convert a gdb special register number to a 29000 special register number.
+ */
+static int
+regnum_to_srnum(regno)
+int regno;
+{
+ switch(regno) {
+ case VAB_REGNUM: return(0);
+ case OPS_REGNUM: return(1);
+ case CPS_REGNUM: return(2);
+ case CFG_REGNUM: return(3);
+ case CHA_REGNUM: return(4);
+ case CHD_REGNUM: return(5);
+ case CHC_REGNUM: return(6);
+ case RBP_REGNUM: return(7);
+ case TMC_REGNUM: return(8);
+ case TMR_REGNUM: return(9);
+ case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
+ case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
+ case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
+ case MMU_REGNUM: return(13);
+ case LRU_REGNUM: return(14);
+ case IPC_REGNUM: return(128);
+ case IPA_REGNUM: return(129);
+ case IPB_REGNUM: return(130);
+ case Q_REGNUM: return(131);
+ case ALU_REGNUM: return(132);
+ case BP_REGNUM: return(133);
+ case FC_REGNUM: return(134);
+ case CR_REGNUM: return(135);
+ case FPE_REGNUM: return(160);
+ case INTE_REGNUM: return(161);
+ case FPS_REGNUM: return(162);
+ case EXO_REGNUM:return(164);
+ default:
+ return(255); /* Failure ? */
+ }
+}
+/****************************************************************************/
+/*
+ * Initialize the target debugger (minimon only).
+ */
+static void
+init_target_mm(tstart,tend,dstart,dend,entry,ms_size,rs_size,arg_start)
+ADDR32 tstart,tend,dstart,dend,entry;
+INT32 ms_size,rs_size;
+ADDR32 arg_start;
+{
+ out_msg_buf->init_msg.code = INIT;
+ out_msg_buf->init_msg.length= sizeof(struct init_msg_t)-2*sizeof(INT32);
+ out_msg_buf->init_msg.text_start = tstart;
+ out_msg_buf->init_msg.text_end = tend;
+ out_msg_buf->init_msg.data_start = dstart;
+ out_msg_buf->init_msg.data_end = dend;
+ out_msg_buf->init_msg.entry_point = entry;
+ out_msg_buf->init_msg.mem_stack_size = ms_size;
+ out_msg_buf->init_msg.reg_stack_size = rs_size;
+ out_msg_buf->init_msg.arg_start = arg_start;
+ msg_send_serial(out_msg_buf);
+ expect_msg(INIT_ACK,in_msg_buf,1);
+}
+/****************************************************************************/
+/*
+ * Return a pointer to a string representing the given message code.
+ * Not all messages are represented here, only the ones that we expect
+ * to be called with.
+ */
+static char*
+msg_str(code)
+INT32 code;
+{
+ static char cbuf[32];
+
+ switch (code) {
+ case BKPT_SET_ACK: sprintf(cbuf,"%s (%d)","BKPT_SET_ACK",code); break;
+ case BKPT_RM_ACK: sprintf(cbuf,"%s (%d)","BKPT_RM_ACK",code); break;
+ case INIT_ACK: sprintf(cbuf,"%s (%d)","INIT_ACK",code); break;
+ case READ_ACK: sprintf(cbuf,"%s (%d)","READ_ACK",code); break;
+ case WRITE_ACK: sprintf(cbuf,"%s (%d)","WRITE_ACK",code); break;
+ case ERROR: sprintf(cbuf,"%s (%d)","ERROR",code); break;
+ case HALT: sprintf(cbuf,"%s (%d)","HALT",code); break;
+ default: sprintf(cbuf,"UNKNOWN (%d)",code); break;
+ }
+ return(cbuf);
+}
+/****************************************************************************/
+/*
+ * Selected (not all of them) error codes that we might get.
+ */
+static char*
+error_msg_str(code)
+INT32 code;
+{
+ static char cbuf[50];
+
+ switch (code) {
+ case EMFAIL: return("EMFAIL: unrecoverable error");
+ case EMBADADDR: return("EMBADADDR: Illegal address");
+ case EMBADREG: return("EMBADREG: Illegal register ");
+ case EMACCESS: return("EMACCESS: Could not access memory");
+ case EMBADMSG: return("EMBADMSG: Unknown message type");
+ case EMMSG2BIG: return("EMMSG2BIG: Message to large");
+ case EMNOSEND: return("EMNOSEND: Could not send message");
+ case EMNORECV: return("EMNORECV: Could not recv message");
+ case EMRESET: return("EMRESET: Could not RESET target");
+ case EMCONFIG: return("EMCONFIG: Could not get target CONFIG");
+ case EMSTATUS: return("EMSTATUS: Could not get target STATUS");
+ case EMREAD: return("EMREAD: Could not READ target memory");
+ case EMWRITE: return("EMWRITE: Could not WRITE target memory");
+ case EMBKPTSET: return("EMBKPTSET: Could not set breakpoint");
+ case EMBKPTRM: return("EMBKPTRM: Could not remove breakpoint");
+ case EMBKPTSTAT:return("EMBKPTSTAT: Could not get breakpoint status");
+ case EMBKPTNONE:return("EMBKPTNONE: All breakpoints in use");
+ case EMBKPTUSED:return("EMBKPTUSED: Breakpoints already in use");
+ case EMINIT: return("EMINIT: Could not init target memory");
+ case EMGO: return("EMGO: Could not start execution");
+ case EMSTEP: return("EMSTEP: Could not single step");
+ case EMBREAK: return("EMBREAK: Could not BREAK");
+ case EMCOMMERR: return("EMCOMMERR: Communication error");
+ default: sprintf(cbuf,"error number %d",code); break;
+ } /* end switch */
+
+ return (cbuf);
+}
+/****************************************************************************/
+/*
+ * Receive a message and expect it to be of type msgcode.
+ * Returns 0/1 on failure/success.
+ */
+static int
+expect_msg(msgcode,msg_buf,from_tty)
+INT32 msgcode; /* Msg code we expect */
+union msg_t *msg_buf; /* Where to put the message received */
+int from_tty; /* Print message on error if non-zero */
+{
+ int retries=0;
+ while(msg_recv_serial(msg_buf) && (retries++<MAX_RETRIES));
+ if (retries >= MAX_RETRIES) {
+ printf("Expected msg %s, ",msg_str(msgcode));
+ printf("no message received!\n");
+ return(0); /* Failure */
+ }
+
+ if (msg_buf->generic_msg.code != msgcode) {
+ if (from_tty) {
+ printf("Expected msg %s, ",msg_str(msgcode));
+ printf("got msg %s\n",msg_str(msg_buf->generic_msg.code));
+ if (msg_buf->generic_msg.code == ERROR)
+ printf("%s\n",error_msg_str(msg_buf->error_msg.error_code));
+ }
+ return(0); /* Failure */
+ }
+ return(1); /* Success */
+}
+/****************************************************************************/
+/*
+ * Determine the MiniMon memory space qualifier based on the addr.
+ * FIXME: Can't distinguis I_ROM/D_ROM.
+ * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
+ */
+static int
+mm_memory_space(addr)
+CORE_ADDR *addr;
+{
+ ADDR32 tstart = target_config.I_mem_start;
+ ADDR32 tend = tstart + target_config.I_mem_size;
+ ADDR32 dstart = target_config.D_mem_start;
+ ADDR32 dend = tstart + target_config.D_mem_size;
+ ADDR32 rstart = target_config.ROM_start;
+ ADDR32 rend = tstart + target_config.ROM_size;
+
+ if (((ADDR32)addr >= tstart) && ((ADDR32)addr < tend)) {
+ return I_MEM;
+ } else if (((ADDR32)addr >= dstart) && ((ADDR32)addr < dend)) {
+ return D_MEM;
+ } else if (((ADDR32)addr >= rstart) && ((ADDR32)addr < rend)) {
+ /* FIXME: how do we determine between D_ROM and I_ROM */
+ return D_ROM;
+ } else /* FIXME: what do me do now? */
+ return D_MEM; /* Hmmm! */
+}
+
+/****************************************************************************/
+/*
+ * Define the target subroutine names
+ */
+struct target_ops mm_ops = {
+ "minimon", "Remote AMD/Minimon target",
+ "Remote debug an AMD 290*0 using the MiniMon dbg core on the target",
+ mm_open, mm_close,
+ mm_attach, mm_detach, mm_resume, mm_wait,
+ mm_fetch_registers, mm_store_registers,
+ mm_prepare_to_store,
+ mm_xfer_inferior_memory,
+ mm_files_info,
+ mm_insert_breakpoint, mm_remove_breakpoint, /* Breakpoints */
+ 0, 0, 0, 0, 0, /* Terminal handling */
+ mm_kill, /* FIXME, kill */
+ mm_load,
+ 0, /* lookup_symbol */
+ mm_create_inferior, /* create_inferior */
+ mm_mourn, /* mourn_inferior FIXME */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_stop */
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ 0,0, /* sections, sections_end */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_mm()
+{
+ add_target (&mm_ops);
+}
+
+#ifdef NO_HIF_SUPPORT
+service_HIF(msg)
+union msg_t *msg;
+{
+ return(0); /* Emulate a failure */
+}
+#endif
diff --git a/contrib/gdb/gdb/remote-nindy.c b/contrib/gdb/gdb/remote-nindy.c
new file mode 100644
index 0000000..a3417f0
--- /dev/null
+++ b/contrib/gdb/gdb/remote-nindy.c
@@ -0,0 +1,820 @@
+/* Memory-access and commands for remote NINDY process, for GDB.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Contributed by Intel Corporation. Modified from remote.c by Chris Benenati.
+
+GDB is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY. No author or distributor accepts responsibility to anyone
+for the consequences of using it or for whether it serves any
+particular purpose or works at all, unless he says so in writing.
+Refer to the GDB General Public License for full details.
+
+Everyone is granted permission to copy, modify and redistribute GDB,
+but only under the conditions described in the GDB General Public
+License. A copy of this license is supposed to have been given to you
+along with GDB so you can know your rights and responsibilities. It
+should be in a file named COPYING. Among other things, the copyright
+notice and this notice must be preserved on all copies.
+
+In other words, go ahead and share GDB, but don't try to stop
+anyone else from sharing it farther. Help stamp out software hoarding!
+*/
+
+/*
+Except for the data cache routines, this file bears little resemblence
+to remote.c. A new (although similar) protocol has been specified, and
+portions of the code are entirely dependent on having an i80960 with a
+NINDY ROM monitor at the other end of the line.
+*/
+
+/*****************************************************************************
+ *
+ * REMOTE COMMUNICATION PROTOCOL BETWEEN GDB960 AND THE NINDY ROM MONITOR.
+ *
+ *
+ * MODES OF OPERATION
+ * ----- -- ---------
+ *
+ * As far as NINDY is concerned, GDB is always in one of two modes: command
+ * mode or passthrough mode.
+ *
+ * In command mode (the default) pre-defined packets containing requests
+ * are sent by GDB to NINDY. NINDY never talks except in reponse to a request.
+ *
+ * Once the the user program is started, GDB enters passthrough mode, to give
+ * the user program access to the terminal. GDB remains in this mode until
+ * NINDY indicates that the program has stopped.
+ *
+ *
+ * PASSTHROUGH MODE
+ * ----------- ----
+ *
+ * GDB writes all input received from the keyboard directly to NINDY, and writes
+ * all characters received from NINDY directly to the monitor.
+ *
+ * Keyboard input is neither buffered nor echoed to the monitor.
+ *
+ * GDB remains in passthrough mode until NINDY sends a single ^P character,
+ * to indicate that the user process has stopped.
+ *
+ * Note:
+ * GDB assumes NINDY performs a 'flushreg' when the user program stops.
+ *
+ *
+ * COMMAND MODE
+ * ------- ----
+ *
+ * All info (except for message ack and nak) is transferred between gdb
+ * and the remote processor in messages of the following format:
+ *
+ * <info>#<checksum>
+ *
+ * where
+ * # is a literal character
+ *
+ * <info> ASCII information; all numeric information is in the
+ * form of hex digits ('0'-'9' and lowercase 'a'-'f').
+ *
+ * <checksum>
+ * is a pair of ASCII hex digits representing an 8-bit
+ * checksum formed by adding together each of the
+ * characters in <info>.
+ *
+ * The receiver of a message always sends a single character to the sender
+ * to indicate that the checksum was good ('+') or bad ('-'); the sender
+ * re-transmits the entire message over until a '+' is received.
+ *
+ * In response to a command NINDY always sends back either data or
+ * a result code of the form "Xnn", where "nn" are hex digits and "X00"
+ * means no errors. (Exceptions: the "s" and "c" commands don't respond.)
+ *
+ * SEE THE HEADER OF THE FILE "gdb.c" IN THE NINDY MONITOR SOURCE CODE FOR A
+ * FULL DESCRIPTION OF LEGAL COMMANDS.
+ *
+ * SEE THE FILE "stop.h" IN THE NINDY MONITOR SOURCE CODE FOR A LIST
+ * OF STOP CODES.
+ *
+ ***************************************************************************/
+
+#include "defs.h"
+#include <signal.h>
+#include <sys/types.h>
+#include <setjmp.h>
+
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "floatformat.h"
+
+#include "wait.h"
+#include <sys/file.h>
+#include <ctype.h>
+#include "serial.h"
+#include "nindy-share/env.h"
+#include "nindy-share/stop.h"
+
+#include "dcache.h"
+#include "remote-utils.h"
+
+static DCACHE *nindy_dcache;
+
+extern int unlink();
+extern char *getenv();
+extern char *mktemp();
+
+extern void generic_mourn_inferior ();
+
+extern struct target_ops nindy_ops;
+extern GDB_FILE *instream;
+
+extern char ninStopWhy ();
+extern int ninMemGet ();
+extern int ninMemPut ();
+
+int nindy_initial_brk; /* nonzero if want to send an initial BREAK to nindy */
+int nindy_old_protocol; /* nonzero if want to use old protocol */
+char *nindy_ttyname; /* name of tty to talk to nindy on, or null */
+
+#define DLE '\020' /* Character NINDY sends to indicate user program has
+ * halted. */
+#define TRUE 1
+#define FALSE 0
+
+/* From nindy-share/nindy.c. */
+extern serial_t nindy_serial;
+
+static int have_regs = 0; /* 1 iff regs read since i960 last halted */
+static int regs_changed = 0; /* 1 iff regs were modified since last read */
+
+extern char *exists();
+
+static void
+nindy_fetch_registers PARAMS ((int));
+
+static void
+nindy_store_registers PARAMS ((int));
+
+static char *savename;
+
+static void
+nindy_close (quitting)
+ int quitting;
+{
+ if (nindy_serial != NULL)
+ SERIAL_CLOSE (nindy_serial);
+ nindy_serial = NULL;
+
+ if (savename)
+ free (savename);
+ savename = 0;
+}
+
+/* Open a connection to a remote debugger.
+ FIXME, there should be "set" commands for the options that are
+ now specified with gdb command-line options (old_protocol,
+ and initial_brk). */
+void
+nindy_open (name, from_tty)
+ char *name; /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
+ int from_tty;
+{
+ char baudrate[1024];
+
+ if (!name)
+ error_no_arg ("serial port device name");
+
+ target_preopen (from_tty);
+
+ nindy_close (0);
+
+ have_regs = regs_changed = 0;
+ nindy_dcache = dcache_init(ninMemGet, ninMemPut);
+
+ /* Allow user to interrupt the following -- we could hang if there's
+ no NINDY at the other end of the remote tty. */
+ immediate_quit++;
+ /* If baud_rate is -1, then ninConnect will not recognize the baud rate
+ and will deal with the situation in a (more or less) reasonable
+ fashion. */
+ sprintf(baudrate, "%d", baud_rate);
+ ninConnect(name, baudrate,
+ nindy_initial_brk, !from_tty, nindy_old_protocol);
+ immediate_quit--;
+
+ if (nindy_serial == NULL)
+ {
+ perror_with_name (name);
+ }
+
+ savename = savestring (name, strlen (name));
+ push_target (&nindy_ops);
+ target_fetch_registers(-1);
+}
+
+/* User-initiated quit of nindy operations. */
+
+static void
+nindy_detach (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ if (name)
+ error ("Too many arguments");
+ pop_target ();
+}
+
+static void
+nindy_files_info ()
+{
+ /* FIXME: this lies about the baud rate if we autobauded. */
+ printf_unfiltered("\tAttached to %s at %d bits per second%s%s.\n", savename,
+ baud_rate,
+ nindy_old_protocol? " in old protocol": "",
+ nindy_initial_brk? " with initial break": "");
+}
+
+/* Return the number of characters in the buffer before
+ the first DLE character. */
+
+static
+int
+non_dle( buf, n )
+ char *buf; /* Character buffer; NOT '\0'-terminated */
+ int n; /* Number of characters in buffer */
+{
+ int i;
+
+ for ( i = 0; i < n; i++ ){
+ if ( buf[i] == DLE ){
+ break;
+ }
+ }
+ return i;
+}
+
+/* Tell the remote machine to resume. */
+
+void
+nindy_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ if (siggnal != TARGET_SIGNAL_0 && siggnal != stop_signal)
+ warning ("Can't send signals to remote NINDY targets.");
+
+ dcache_flush(nindy_dcache);
+ if ( regs_changed )
+ {
+ nindy_store_registers (-1);
+ regs_changed = 0;
+ }
+ have_regs = 0;
+ ninGo( step );
+}
+
+/* FIXME, we can probably use the normal terminal_inferior stuff here.
+ We have to do terminal_inferior and then set up the passthrough
+ settings initially. Thereafter, terminal_ours and terminal_inferior
+ will automatically swap the settings around for us. */
+
+struct clean_up_tty_args {
+ serial_ttystate state;
+ serial_t serial;
+};
+static struct clean_up_tty_args tty_args;
+
+static void
+clean_up_tty (ptrarg)
+ PTR ptrarg;
+{
+ struct clean_up_tty_args *args = (struct clean_up_tty_args *) ptrarg;
+ SERIAL_SET_TTY_STATE (args->serial, args->state);
+ free (args->state);
+ warning ("\n\nYou may need to reset the 80960 and/or reload your program.\n");
+}
+
+/* Recover from ^Z or ^C while remote process is running */
+static void (*old_ctrlc)();
+#ifdef SIGTSTP
+static void (*old_ctrlz)();
+#endif
+
+static void
+clean_up_int()
+{
+ SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
+ free (tty_args.state);
+
+ signal(SIGINT, old_ctrlc);
+#ifdef SIGTSTP
+ signal(SIGTSTP, old_ctrlz);
+#endif
+ error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
+}
+
+/* Wait until the remote machine stops. While waiting, operate in passthrough
+ * mode; i.e., pass everything NINDY sends to gdb_stdout, and everything from
+ * stdin to NINDY.
+ *
+ * Return to caller, storing status in 'status' just as `wait' would.
+ */
+
+static int
+nindy_wait( pid, status )
+ int pid;
+ struct target_waitstatus *status;
+{
+ fd_set fds;
+ int c;
+ char buf[2];
+ int i, n;
+ unsigned char stop_exit;
+ unsigned char stop_code;
+ struct cleanup *old_cleanups;
+ long ip_value, fp_value, sp_value; /* Reg values from stop */
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
+
+ /* Save current tty attributes, and restore them when done. */
+ tty_args.serial = SERIAL_FDOPEN (0);
+ tty_args.state = SERIAL_GET_TTY_STATE (tty_args.serial);
+ old_ctrlc = signal( SIGINT, clean_up_int );
+#ifdef SIGTSTP
+ old_ctrlz = signal( SIGTSTP, clean_up_int );
+#endif
+
+ old_cleanups = make_cleanup (clean_up_tty, &tty_args);
+
+ /* Pass input from keyboard to NINDY as it arrives. NINDY will interpret
+ <CR> and perform echo. */
+ /* This used to set CBREAK and clear ECHO and CRMOD. I hope this is close
+ enough. */
+ SERIAL_RAW (tty_args.serial);
+
+ while (1)
+ {
+ /* Input on remote */
+ c = SERIAL_READCHAR (nindy_serial, -1);
+ if (c == SERIAL_ERROR)
+ {
+ error ("Cannot read from serial line");
+ }
+ else if (c == 0x1b) /* ESC */
+ {
+ c = SERIAL_READCHAR (nindy_serial, -1);
+ c &= ~0x40;
+ }
+ else if (c != 0x10) /* DLE */
+ /* Write out any characters preceding DLE */
+ {
+ buf[0] = (char)c;
+ write (1, buf, 1);
+ }
+ else
+ {
+ stop_exit = ninStopWhy(&stop_code,
+ &ip_value, &fp_value, &sp_value);
+ if (!stop_exit && (stop_code == STOP_SRQ))
+ {
+ immediate_quit++;
+ ninSrq();
+ immediate_quit--;
+ }
+ else
+ {
+ /* Get out of loop */
+ supply_register (IP_REGNUM,
+ (char *)&ip_value);
+ supply_register (FP_REGNUM,
+ (char *)&fp_value);
+ supply_register (SP_REGNUM,
+ (char *)&sp_value);
+ break;
+ }
+ }
+ }
+
+ SERIAL_SET_TTY_STATE (tty_args.serial, tty_args.state);
+ free (tty_args.state);
+ discard_cleanups (old_cleanups);
+
+ if (stop_exit)
+ {
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = stop_code;
+ }
+ else
+ {
+ /* nindy has some special stop code need to be handled */
+ if (stop_code == STOP_GDB_BPT)
+ stop_code = TRACE_STEP;
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = i960_fault_to_signal (stop_code);
+ }
+ return inferior_pid;
+}
+
+/* Read the remote registers into the block REGS. */
+
+/* This is the block that ninRegsGet and ninRegsPut handles. */
+struct nindy_regs {
+ char local_regs[16 * 4];
+ char global_regs[16 * 4];
+ char pcw_acw[2 * 4];
+ char ip[4];
+ char tcw[4];
+ char fp_as_double[4 * 8];
+};
+
+static void
+nindy_fetch_registers(regno)
+ int regno;
+{
+ struct nindy_regs nindy_regs;
+ int regnum, inv;
+ double dub;
+
+ immediate_quit++;
+ ninRegsGet( (char *) &nindy_regs );
+ immediate_quit--;
+
+ memcpy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs, 16*4);
+ memcpy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
+ memcpy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw, 2*4);
+ memcpy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip, 1*4);
+ memcpy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw, 1*4);
+ for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
+ dub = unpack_double (builtin_type_double,
+ &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
+ &inv);
+ /* dub now in host byte order */
+ floatformat_from_double (&floatformat_i960_ext, &dub,
+ &registers[REGISTER_BYTE (regnum)]);
+ }
+
+ registers_fetched ();
+}
+
+static void
+nindy_prepare_to_store()
+{
+ /* Fetch all regs if they aren't already here. */
+ read_register_bytes (0, NULL, REGISTER_BYTES);
+}
+
+static void
+nindy_store_registers(regno)
+ int regno;
+{
+ struct nindy_regs nindy_regs;
+ int regnum;
+ double dub;
+
+ memcpy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
+ memcpy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
+ memcpy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
+ memcpy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
+ memcpy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
+ for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++)
+ {
+ floatformat_to_double (&floatformat_i960_ext,
+ &registers[REGISTER_BYTE (regnum)], &dub);
+ store_floating (&nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
+ REGISTER_VIRTUAL_SIZE (regnum),
+ dub);
+ }
+
+ immediate_quit++;
+ ninRegsPut( (char *) &nindy_regs );
+ immediate_quit--;
+}
+
+/* Read a word from remote address ADDR and return it.
+ * This goes through the data cache.
+ */
+int
+nindy_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ return dcache_fetch (nindy_dcache, addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+void
+nindy_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (nindy_dcache, addr, word);
+}
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. Copy to inferior if
+ WRITE is nonzero. Returns the length copied.
+
+ This is stolen almost directly from infptrace.c's child_xfer_memory,
+ which also deals with a word-oriented memory interface. Sometime,
+ FIXME, rewrite this to not use the word-oriented routines. */
+
+int
+nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (int);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
+ /* Allocate buffer of that many longwords. */
+ register int *buffer = (int *) alloca (count * sizeof (int));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int)sizeof (int)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = nindy_fetch_word (addr);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = nindy_fetch_word (addr + (count - 1) * sizeof (int));
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ nindy_store_word (addr, buffer[i]);
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (int))
+ {
+ errno = 0;
+ buffer[i] = nindy_fetch_word (addr);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
+ }
+ return len;
+}
+
+static void
+nindy_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+ int pid;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote NINDY process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ pid = 42;
+
+ /* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ inferior_pid = pid; /* Needed for wait_for_inferior below */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+static void
+reset_command(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (nindy_serial == NULL)
+ {
+ error( "No target system to reset -- use 'target nindy' command.");
+ }
+ if ( query("Really reset the target system?",0,0) )
+ {
+ SERIAL_SEND_BREAK (nindy_serial);
+ tty_flush (nindy_serial);
+ }
+}
+
+void
+nindy_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+void
+nindy_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&nindy_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+/* Pass the args the way catch_errors wants them. */
+static int
+nindy_open_stub (arg)
+ char *arg;
+{
+ nindy_open (arg, 1);
+ return 1;
+}
+
+static void
+nindy_load( filename, from_tty )
+ char *filename;
+ int from_tty;
+{
+ asection *s;
+ /* Can't do unix style forking on a VMS system, so we'll use bfd to do
+ all the work for us
+ */
+
+ bfd *file = bfd_openr(filename,0);
+ if (!file)
+ {
+ perror_with_name(filename);
+ return;
+ }
+
+ if (!bfd_check_format(file, bfd_object))
+ {
+ error("can't prove it's an object file\n");
+ return;
+ }
+
+ for ( s = file->sections; s; s=s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ char *buffer = xmalloc(s->_raw_size);
+ bfd_get_section_contents(file, s, buffer, 0, s->_raw_size);
+ printf("Loading section %s, size %x vma %x\n",
+ s->name,
+ s->_raw_size,
+ s->vma);
+ ninMemPut(s->vma, buffer, s->_raw_size);
+ free(buffer);
+ }
+ }
+ bfd_close(file);
+}
+
+static int
+load_stub (arg)
+ char *arg;
+{
+ target_load (arg, 1);
+ return 1;
+}
+
+/* This routine is run as a hook, just before the main command loop is
+ entered. If gdb is configured for the i960, but has not had its
+ nindy target specified yet, this will loop prompting the user to do so.
+
+ Unlike the loop provided by Intel, we actually let the user get out
+ of this with a RETURN. This is useful when e.g. simply examining
+ an i960 object file on the host system. */
+
+void
+nindy_before_main_loop ()
+{
+ char ttyname[100];
+ char *p, *p2;
+
+ while (target_stack->target_ops != &nindy_ops) /* What is this crap??? */
+ { /* remote tty not specified yet */
+ if ( instream == stdin ){
+ printf_unfiltered("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit: ");
+ gdb_flush( gdb_stdout );
+ }
+ fgets( ttyname, sizeof(ttyname)-1, stdin );
+
+ /* Strip leading and trailing whitespace */
+ for ( p = ttyname; isspace(*p); p++ ){
+ ;
+ }
+ if ( *p == '\0' ){
+ return; /* User just hit spaces or return, wants out */
+ }
+ for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
+ ;
+ }
+ *p2= '\0';
+ if ( STREQ("quit",p) ){
+ exit(1);
+ }
+
+ if (catch_errors (nindy_open_stub, p, "", RETURN_MASK_ALL))
+ {
+ /* Now that we have a tty open for talking to the remote machine,
+ download the executable file if one was specified. */
+ if (exec_bfd)
+ {
+ catch_errors (load_stub, bfd_get_filename (exec_bfd), "",
+ RETURN_MASK_ALL);
+ }
+ }
+ }
+}
+
+/* Define the target subroutine names */
+
+struct target_ops nindy_ops = {
+ "nindy", "Remote serial target in i960 NINDY-specific protocol",
+ "Use a remote i960 system running NINDY connected by a serial line.\n\
+Specify the name of the device the serial line is connected to.\n\
+The speed (baud rate), whether to use the old NINDY protocol,\n\
+and whether to send a break on startup, are controlled by options\n\
+specified when you started GDB.",
+ nindy_open, nindy_close,
+ 0,
+ nindy_detach,
+ nindy_resume,
+ nindy_wait,
+ nindy_fetch_registers, nindy_store_registers,
+ nindy_prepare_to_store,
+ nindy_xfer_inferior_memory, nindy_files_info,
+ memory_insert_breakpoint,
+ memory_remove_breakpoint,
+ 0, 0, 0, 0, 0, /* Terminal crud */
+ nindy_kill,
+ nindy_load,
+ 0, /* lookup_symbol */
+ nindy_create_inferior,
+ nindy_mourn_inferior,
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, 0, /* next */
+ 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_nindy ()
+{
+ add_target (&nindy_ops);
+ add_com ("reset", class_obscure, reset_command,
+ "Send a 'break' to the remote target system.\n\
+Only useful if the target has been equipped with a circuit\n\
+to perform a hard reset when a break is detected.");
+}
diff --git a/contrib/gdb/gdb/remote-nrom.c b/contrib/gdb/gdb/remote-nrom.c
new file mode 100644
index 0000000..d67791b
--- /dev/null
+++ b/contrib/gdb/gdb/remote-nrom.c
@@ -0,0 +1,332 @@
+/* Remote debugging with the XLNT Designs, Inc (XDI) NetROM.
+ Copyright 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+ Contributed by:
+ Roger Moyers
+ XLNT Designs, Inc.
+ 15050 Avenue of Science, Suite 106
+ San Diego, CA 92128
+ (619)487-9320
+ roger@xlnt.com
+ Adapted from work done at Cygnus Support in remote-nindy.c,
+ later merged in by Stan Shebs at Cygnus.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "serial.h"
+#include "target.h"
+
+/* Default ports used to talk with the NetROM. */
+
+#define DEFAULT_NETROM_LOAD_PORT 1236
+#define DEFAULT_NETROM_CONTROL_PORT 1237
+
+static void nrom_close PARAMS ((int quitting));
+
+/* New commands. */
+
+static void nrom_passthru PARAMS ((char *, int));
+
+/* We talk to the NetROM over these sockets. */
+
+static serial_t load_desc = NULL;
+static serial_t ctrl_desc = NULL;
+
+static int load_port = DEFAULT_NETROM_LOAD_PORT;
+static int control_port = DEFAULT_NETROM_CONTROL_PORT;
+
+static char nrom_hostname[100];
+
+/* Forward data declaration. */
+
+extern struct target_ops nrom_ops;
+
+/* Scan input from the remote system, until STRING is found. Print chars that
+ don't match. */
+
+static int
+expect (string)
+ char *string;
+{
+ char *p = string;
+ int c;
+
+ immediate_quit = 1;
+
+ while (1)
+ {
+ c = SERIAL_READCHAR (ctrl_desc, 5);
+
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+
+ return 0;
+ }
+ }
+ else
+ {
+ fputc_unfiltered (c, gdb_stdout);
+ p = string;
+ if (c == *p)
+ p++;
+ }
+ }
+}
+
+static void
+nrom_kill ()
+{
+ nrom_close (0);
+}
+
+static serial_t
+open_socket (name, port)
+ char *name;
+ int port;
+{
+ char sockname[100];
+ serial_t desc;
+
+ sprintf (sockname, "%s:%d", name, port);
+ desc = SERIAL_OPEN (sockname);
+ if (!desc)
+ perror_with_name (sockname);
+
+ return desc;
+}
+
+static void
+load_cleanup ()
+{
+ SERIAL_CLOSE (load_desc);
+ load_desc = NULL;
+}
+
+/* Download a file specified in ARGS to the netROM. */
+
+static void
+nrom_load (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ int fd, rd_amt, fsize;
+ bfd *pbfd;
+ asection *section;
+ char *downloadstring = "download 0\n";
+ struct cleanup *old_chain;
+
+ /* Tell the netrom to get ready to download. */
+ if (SERIAL_WRITE (ctrl_desc, downloadstring, strlen (downloadstring)))
+ error ("nrom_load: control_send() of `%s' failed", downloadstring);
+
+ expect ("Waiting for a connection...\n");
+
+ load_desc = open_socket (nrom_hostname, load_port);
+
+ old_chain = make_cleanup (load_cleanup, 0);
+
+ pbfd = bfd_openr (args, 0);
+
+ if (pbfd)
+ {
+ make_cleanup (bfd_close, pbfd);
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("\"%s\": not in executable format: %s",
+ args, bfd_errmsg (bfd_get_error ()));
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
+ {
+ bfd_vma section_address;
+ unsigned long section_size;
+ const char *section_name;
+
+ section_name = bfd_get_section_name (pbfd, section);
+ section_address = bfd_get_section_vma (pbfd, section);
+ section_size = bfd_section_size (pbfd, section);
+
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD)
+ {
+ file_ptr fptr;
+
+ printf_filtered ("[Loading section %s at %x (%d bytes)]\n",
+ section_name, section_address,
+ section_size);
+
+ fptr = 0;
+
+ while (section_size > 0)
+ {
+ char buffer[1024];
+ int count;
+
+ count = min (section_size, 1024);
+
+ bfd_get_section_contents (pbfd, section, buffer, fptr,
+ count);
+
+ SERIAL_WRITE (load_desc, buffer, count);
+ section_address += count;
+ fptr += count;
+ section_size -= count;
+ }
+ }
+ else /* BSS and such */
+ {
+ printf_filtered ("[section %s: not loading]\n",
+ section_name);
+ }
+ }
+ }
+ }
+ else
+ error ("\"%s\": Could not open", args);
+
+ do_cleanups (old_chain);
+}
+
+/* Open a connection to the remote NetROM devices. */
+
+static void
+nrom_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ int errn;
+
+ if (!name || strchr (name, '/') || strchr (name, ':'))
+ error (
+"To open a NetROM connection, you must specify the hostname\n\
+or IP address of the NetROM device you wish to use.");
+
+ strcpy (nrom_hostname, name);
+
+ target_preopen (from_tty);
+
+ unpush_target (&nrom_ops);
+
+ ctrl_desc = open_socket (nrom_hostname, control_port);
+
+ push_target (&nrom_ops);
+
+ if (from_tty)
+ printf_filtered ("Connected to NetROM device \"%s\"\n", nrom_hostname);
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+nrom_close (quitting)
+ int quitting;
+{
+ if (load_desc)
+ SERIAL_CLOSE (load_desc);
+ if (ctrl_desc)
+ SERIAL_CLOSE (ctrl_desc);
+}
+
+/* Pass arguments directly to the NetROM. */
+
+static void
+nrom_passthru (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ char buf[1024];
+
+ sprintf (buf, "%s\n", args);
+ if (SERIAL_WRITE (ctrl_desc, buf, strlen (buf)))
+ error ("nrom_reset: control_send() of `%s'failed", args);
+}
+
+static void
+nrom_mourn()
+{
+ unpush_target (&nrom_ops);
+ generic_mourn_inferior ();
+}
+
+/* Define the target vector. */
+
+struct target_ops nrom_ops = {
+ "nrom", /* to_shortname */
+ "Remote XDI `NetROM' target", /* to_longname */
+ "Remote debug using a NetROM over Ethernet", /* to_doc */
+ nrom_open, /* to_open */
+ nrom_close, /* to_close */
+ NULL, /* to_attach */
+ NULL, /* to_detach */
+ NULL, /* to_resume */
+ NULL, /* to_wait */
+ NULL, /* to_fetch_registers */
+ NULL, /* to_store_registers */
+ NULL, /* to_prepare_to_store */
+ NULL, /* to_xfer_memory */
+ NULL, /* to_files_info */
+ NULL, /* to_insert_breakpoint */
+ NULL, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ nrom_kill, /* to_kill */
+ nrom_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ NULL, /* to_create_inferior */
+ nrom_mourn, /* to_mourn_inferior */
+ NULL, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ download_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 0, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_remote_nrom ()
+{
+ add_target (&nrom_ops);
+
+ add_show_from_set (
+ add_set_cmd ("nrom_load_port", no_class, var_zinteger, (char *)&load_port,
+ "Set the port to use for NetROM downloads\n", &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("nrom_control_port", no_class, var_zinteger, (char *)&control_port,
+ "Set the port to use for NetROM debugger services\n", &setlist),
+ &showlist);
+
+ add_cmd ("nrom", no_class, nrom_passthru,
+ "Pass arguments as command to NetROM",
+ &cmdlist);
+}
diff --git a/contrib/gdb/gdb/remote-os9k.c b/contrib/gdb/gdb/remote-os9k.c
new file mode 100644
index 0000000..fda5272
--- /dev/null
+++ b/contrib/gdb/gdb/remote-os9k.c
@@ -0,0 +1,1230 @@
+/* Remote debugging interface for boot monitors, for GDB.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file was derived from remote-eb.c, which did a similar job, but for
+ an AMD-29K running EBMON. That file was in turn derived from remote.c
+ as mentioned in the following comment (left in for comic relief):
+
+ "This is like remote.c but is for a different situation--
+ having a PC running os9000 hook up with a unix machine with
+ a serial line, and running ctty com2 on the PC. os9000 has a debug
+ monitor called ROMBUG running. Not to mention that the PC
+ has PC/NFS, so it can access the same executables that gdb can,
+ over the net in real time."
+
+ In reality, this module talks to a debug monitor called 'ROMBUG', which
+ We communicate with ROMBUG via a direct serial line, the network version
+ of ROMBUG is not available yet.
+*/
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+#include "command.h"
+#include "serial.h"
+#include "monitor.h"
+#include "remote-utils.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+
+struct monitor_ops *current_monitor;
+struct cmd_list_element *showlist;
+extern struct target_ops rombug_ops; /* Forward declaration */
+extern struct monitor_ops rombug_cmds; /* Forward declaration */
+extern struct cmd_list_element *setlist;
+extern struct cmd_list_element *unsetlist;
+extern int attach_flag;
+
+static void rombug_close();
+static void rombug_fetch_register();
+static void rombug_fetch_registers();
+static void rombug_store_register();
+#if 0
+static int sr_get_debug(); /* flag set by "set remotedebug" */
+#endif
+static int hashmark; /* flag set by "set hash" */
+static int rombug_is_open = 0;
+
+/* FIXME: Replace with sr_get_debug (). */
+#define LOG_FILE "monitor.log"
+FILE *log_file;
+static int monitor_log = 0;
+static int tty_xon = 0;
+static int tty_xoff = 0;
+
+static int timeout = 10;
+static int is_trace_mode = 0;
+/* Descriptor for I/O to remote machine. Initialize it to NULL*/
+static serial_t monitor_desc = NULL;
+
+static CORE_ADDR bufaddr = 0;
+static int buflen = 0;
+static char readbuf[16];
+
+/* Send data to monitor. Works just like printf. */
+static void
+#ifdef ANSI_PROTOTYPES
+printf_monitor(char *pattern, ...)
+#else
+printf_monitor(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char buf[200];
+ int i;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, pattern);
+#else
+ char *pattern;
+ va_start(args);
+ pattern = va_arg(args, char *);
+#endif
+
+ vsprintf(buf, pattern, args);
+ va_end(args);
+
+ if (SERIAL_WRITE(monitor_desc, buf, strlen(buf)))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+}
+
+/* Read a character from the remote system, doing all the fancy timeout stuff*/
+static int
+readchar(timeout)
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR(monitor_desc, timeout);
+
+ if (sr_get_debug())
+ putchar(c & 0x7f);
+
+ if (monitor_log && isascii(c))
+ putc(c & 0x7f, log_file);
+
+ if (c >= 0)
+ return c & 0x7f;
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return c; /* Polls shouldn't generate timeout errors */
+
+ error("Timeout reading from remote system.");
+ }
+
+ perror_with_name("remote-monitor");
+}
+
+/* Scan input from the remote system, until STRING is found. If DISCARD is
+ non-zero, then discard non-matching input, else print it out.
+ Let the user break out immediately. */
+static void
+expect(string, discard)
+ char *string;
+ int discard;
+{
+ char *p = string;
+ int c;
+
+ if (sr_get_debug())
+ printf ("Expecting \"%s\"\n", string);
+
+ immediate_quit = 1;
+ while (1)
+ {
+ c = readchar(timeout);
+ if (!isascii (c))
+ continue;
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ if (sr_get_debug())
+ printf ("\nMatched\n");
+ return;
+ }
+ }
+ else
+ {
+ if (!discard)
+ {
+ fwrite(string, 1, (p - 1) - string, stdout);
+ putchar((char)c);
+ fflush(stdout);
+ }
+ p = string;
+ }
+ }
+}
+
+/* Keep discarding input until we see the ROMBUG prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: rombug_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a rombug_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt(discard)
+ int discard;
+{
+ if (monitor_log)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush(log_file);
+
+ if (is_trace_mode) {
+ expect("trace", discard);
+ } else {
+ expect (PROMPT, discard);
+ }
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit(ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar(timeout);
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt(1);
+ error("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from monitor and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+ unsigned char b;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 4; j++)
+ {
+ get_hex_byte (&b);
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = (val << 8) + b;
+ else
+ val = val + (b << (j*8));
+ }
+ supply_register (regno++, (char *) &val);
+ }
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+rombug_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error("Can't pass arguments to remote ROMBUG process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+ if (monitor_log)
+ fputs ("\nIn Create_inferior()", log_file);
+
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ init_wait_for_inferior ();
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static char dev_name[100];
+
+static void
+rombug_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args == NULL)
+ error ("Use `target RomBug DEVICE-NAME' to use a serial port, or \n\
+`target RomBug HOST-NAME:PORT-NUMBER' to use a network connection.");
+
+ target_preopen(from_tty);
+
+ if (rombug_is_open)
+ unpush_target(&rombug_ops);
+
+ strcpy(dev_name, args);
+ monitor_desc = SERIAL_OPEN(dev_name);
+ if (monitor_desc == NULL)
+ perror_with_name(dev_name);
+
+ /* if baud rate is set by 'set remotebaud' */
+ if (SERIAL_SETBAUDRATE (monitor_desc, sr_get_baud_rate()))
+ {
+ SERIAL_CLOSE (monitor_desc);
+ perror_with_name ("RomBug");
+ }
+ SERIAL_RAW(monitor_desc);
+ if (tty_xon || tty_xoff)
+ {
+ struct hardware_ttystate { struct termios t;} *tty_s;
+
+ tty_s =(struct hardware_ttystate *)SERIAL_GET_TTY_STATE(monitor_desc);
+ if (tty_xon) tty_s->t.c_iflag |= IXON;
+ if (tty_xoff) tty_s->t.c_iflag |= IXOFF;
+ SERIAL_SET_TTY_STATE(monitor_desc, (serial_ttystate) tty_s);
+ }
+
+ rombug_is_open = 1;
+
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+
+ push_monitor (&rombug_cmds);
+ printf_monitor("\r"); /* CR wakes up monitor */
+ expect_prompt(1);
+ push_target (&rombug_ops);
+ attach_flag = 1;
+
+ if (from_tty)
+ printf("Remote %s connected to %s\n", target_shortname,
+ dev_name);
+
+ rombug_fetch_registers();
+
+ printf_monitor ("ov e \r");
+ expect_prompt(1);
+ bufaddr = 0;
+ buflen = 0;
+}
+
+/*
+ * Close out all files and local state before this target loses control.
+ */
+
+static void
+rombug_close (quitting)
+ int quitting;
+{
+ if (rombug_is_open) {
+ SERIAL_CLOSE(monitor_desc);
+ monitor_desc = NULL;
+ rombug_is_open = 0;
+ }
+
+ if (log_file) {
+ if (ferror(log_file))
+ fprintf(stderr, "Error writing log file.\n");
+ if (fclose(log_file) != 0)
+ fprintf(stderr, "Error closing log file.\n");
+ log_file = 0;
+ }
+}
+
+int
+rombug_link(mod_name, text_reloc)
+ char *mod_name;
+ CORE_ADDR *text_reloc;
+{
+ int i, j;
+ unsigned long val;
+ unsigned char b;
+
+ printf_monitor("l %s \r", mod_name);
+ expect_prompt(1);
+ printf_monitor(".r \r");
+ expect(REG_DELIM, 1);
+ for (i=0; i <= 7; i++)
+ {
+ val = 0;
+ for (j = 0; j < 4; j++)
+ {
+ get_hex_byte(&b);
+ val = (val << 8) + b;
+ }
+ }
+ expect_prompt(1);
+ *text_reloc = val;
+ return 1;
+}
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+rombug_detach (from_tty)
+ int from_tty;
+{
+ if (attach_flag) {
+ printf_monitor (GO_CMD);
+ attach_flag = 0;
+ }
+ pop_target(); /* calls rombug_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/*
+ * Tell the remote machine to resume.
+ */
+static void
+rombug_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (monitor_log)
+ fprintf (log_file, "\nIn Resume (step=%d, sig=%d)\n", step, sig);
+
+ if (step)
+ {
+ is_trace_mode = 1;
+ printf_monitor (STEP_CMD);
+ /* wait for the echo. **
+ expect (STEP_CMD, 1);
+ */
+ }
+ else
+ {
+ printf_monitor (GO_CMD);
+ /* swallow the echo. **
+ expect (GO_CMD, 1);
+ */
+ }
+ bufaddr = 0;
+ buflen= 0;
+}
+
+/*
+ * Wait until the remote machine stops, then return,
+ * storing status in status just as `wait' would.
+ */
+
+static int
+rombug_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+ struct section_offsets *offs;
+ CORE_ADDR addr, pc;
+ struct obj_section *obj_sec;
+
+ if (monitor_log)
+ fputs ("\nIn wait ()", log_file);
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = -1; /* Don't time out -- user program is running. */
+ expect ("eax:", 0); /* output any message before register display */
+ expect_prompt(1); /* Wait for prompt, outputting extraneous text */
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ timeout = old_timeout;
+ rombug_fetch_registers();
+ bufaddr = 0;
+ buflen = 0;
+ pc = read_register(PC_REGNUM);
+ addr = read_register(DATABASE_REG);
+ obj_sec = find_pc_section (pc);
+ if (obj_sec != NULL)
+ {
+ if (obj_sec->objfile != symfile_objfile)
+ new_symfile_objfile(obj_sec->objfile, 1, 0);
+ 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_DATA) = addr;
+ ANOFFSET (offs, SECT_OFF_BSS) = addr;
+
+ objfile_relocate(symfile_objfile, offs);
+ }
+
+ return 0;
+}
+
+/* Return the name of register number regno in the form input and output by
+ monitor. Currently, register_names just happens to contain exactly what
+ monitor wants. Lets take advantage of that just as long as possible! */
+
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[50];
+ char *p;
+ char *b;
+
+ b = buf;
+
+ if (regno < 0)
+ return ("");
+/*
+ for (p = reg_names[regno]; *p; p++)
+ *b++ = toupper(*p);
+ *b = '\000';
+*/
+ p = (char *)reg_names[regno];
+ return p;
+/*
+ return buf;
+*/
+}
+
+/* read the remote registers into the block regs. */
+
+static void
+rombug_fetch_registers ()
+{
+ int regno, j, i;
+ long val;
+ unsigned char b;
+
+ printf_monitor (GET_REG);
+ expect("eax:", 1);
+ expect("\n", 1);
+ get_hex_regs(1, 0);
+ get_hex_regs(1, 3);
+ get_hex_regs(1, 1);
+ get_hex_regs(1, 2);
+ get_hex_regs(1, 6);
+ get_hex_regs(1, 7);
+ get_hex_regs(1, 5);
+ get_hex_regs(1, 4);
+ for (regno = 8; regno <= 15; regno++)
+ {
+ expect(REG_DELIM, 1);
+ if (regno >= 8 && regno <= 13)
+ {
+ val = 0;
+ for (j = 0; j < 2; j++)
+ {
+ get_hex_byte (&b);
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = (val << 8) + b;
+ else
+ val = val + (b << (j*8));
+ }
+
+ if (regno == 8) i = 10;
+ if (regno >= 9 && regno <= 12) i = regno + 3;
+ if (regno == 13) i = 11;
+ supply_register (i, (char *) &val);
+ }
+ else if (regno == 14)
+ {
+ get_hex_regs(1, PC_REGNUM);
+ }
+ else if (regno == 15)
+ {
+ get_hex_regs(1, 9);
+ }
+ else
+ {
+ val = 0;
+ supply_register(regno, (char *) &val);
+ }
+ }
+ is_trace_mode = 0;
+ expect_prompt (1);
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ Returns errno value. */
+static void
+rombug_fetch_register (regno)
+ int regno;
+{
+ int val, j;
+ unsigned char b;
+
+ if (monitor_log) {
+ fprintf (log_file, "\nIn Fetch Register (reg=%s)\n", get_reg_name (regno));
+ fflush (log_file);
+ }
+
+ if (regno < 0)
+ {
+ rombug_fetch_registers ();
+ }
+ else
+ {
+ char *name = get_reg_name (regno);
+ printf_monitor (GET_REG);
+ if (regno >= 10 && regno <= 15)
+ {
+ expect ("\n", 1);
+ expect ("\n", 1);
+ expect (name, 1);
+ expect (REG_DELIM, 1);
+ val = 0;
+ for (j = 0; j < 2; j++)
+ {
+ get_hex_byte (&b);
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ val = (val << 8) + b;
+ else
+ val = val + (b << (j*8));
+ }
+ supply_register (regno, (char *) &val);
+ }
+ else if (regno == 8 || regno == 9)
+ {
+ expect ("\n", 1);
+ expect ("\n", 1);
+ expect ("\n", 1);
+ expect (name, 1);
+ expect (REG_DELIM, 1);
+ get_hex_regs (1, regno);
+ }
+ else
+ {
+ expect (name, 1);
+ expect (REG_DELIM, 1);
+ expect("\n", 1);
+ get_hex_regs(1, 0);
+ get_hex_regs(1, 3);
+ get_hex_regs(1, 1);
+ get_hex_regs(1, 2);
+ get_hex_regs(1, 6);
+ get_hex_regs(1, 7);
+ get_hex_regs(1, 5);
+ get_hex_regs(1, 4);
+ }
+ expect_prompt (1);
+ }
+ return;
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+rombug_store_registers ()
+{
+ int regno;
+
+ for (regno = 0; regno <= PC_REGNUM; regno++)
+ rombug_store_register(regno);
+
+ registers_changed ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+ return errno value. */
+static void
+rombug_store_register (regno)
+ int regno;
+{
+char *name;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Store_register (regno=%d)\n", regno);
+
+ if (regno == -1)
+ rombug_store_registers ();
+ else
+ {
+ if (sr_get_debug())
+ printf ("Setting register %s to 0x%x\n", get_reg_name (regno), read_register (regno));
+
+ name = get_reg_name(regno);
+ if (name == 0) return;
+ printf_monitor (SET_REG, name, read_register (regno));
+
+ is_trace_mode = 0;
+ expect_prompt (1);
+ }
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+rombug_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+rombug_files_info ()
+{
+ printf ("\tAttached to %s at %d baud.\n",
+ dev_name, sr_get_baud_rate());
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns length moved. */
+static int
+rombug_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+ char buf[10];
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Write_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
+
+ printf_monitor (MEM_SET_CMD, memaddr);
+ for (i = 0; i < len; i++)
+ {
+ expect (CMD_DELIM, 1);
+ printf_monitor ("%x \r", myaddr[i]);
+ if (sr_get_debug())
+ printf ("\nSet 0x%x to 0x%x\n", memaddr + i, myaddr[i]);
+ }
+ expect (CMD_DELIM, 1);
+ if (CMD_END)
+ printf_monitor (CMD_END);
+ is_trace_mode = 0;
+ expect_prompt (1);
+
+ bufaddr = 0;
+ buflen = 0;
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved. */
+static int
+rombug_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i, j;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Read_inferior_memory (memaddr=%x, len=%d)\n", memaddr, len);
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ rombug_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len To memaddr and gets 0. */
+ /* However, something like
+ rombug_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+ if (bufaddr <= memaddr && (memaddr+len) <= (bufaddr+buflen))
+ {
+ memcpy(myaddr, &readbuf[memaddr-bufaddr], len);
+ return len;
+ }
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+ if (sr_get_debug())
+ printf ("\nDisplay %d bytes at %x\n", len_this_pass, startaddr);
+
+ printf_monitor (MEM_DIS_CMD, startaddr, 8);
+ expect ("- ", 1);
+ for (i = 0; i < 16; i++)
+ {
+ get_hex_byte (&readbuf[i]);
+ }
+ bufaddr = startaddr;
+ buflen = 16;
+ memcpy(&myaddr[count], readbuf, len_this_pass);
+ count += len_this_pass;
+ startaddr += len_this_pass;
+ expect(CMD_DELIM, 1);
+ }
+ if (CMD_END)
+ printf_monitor (CMD_END);
+ is_trace_mode = 0;
+ expect_prompt (1);
+
+ return len;
+}
+
+/* FIXME-someday! merge these two. */
+static int
+rombug_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return rombug_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return rombug_read_inferior_memory (memaddr, myaddr, len);
+}
+
+static void
+rombug_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+rombug_mourn_inferior ()
+{
+ remove_breakpoints ();
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define MAX_MONITOR_BREAKPOINTS 16
+
+extern int memory_breakpoint_size;
+static CORE_ADDR breakaddr[MAX_MONITOR_BREAKPOINTS] = {0};
+
+static int
+rombug_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Insert_breakpoint (addr=%x)\n", addr);
+
+ for (i = 0; i <= MAX_MONITOR_BREAKPOINTS; i++)
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+ if (sr_get_debug())
+ printf ("Breakpoint at %x\n", addr);
+ rombug_read_inferior_memory(addr, shadow, memory_breakpoint_size);
+ printf_monitor(SET_BREAK_CMD, addr);
+ is_trace_mode = 0;
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Too many breakpoints (> 16) for monitor\n");
+ return 1;
+}
+
+/*
+ * _remove_breakpoint -- Tell the monitor to remove a breakpoint
+ */
+static int
+rombug_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn Remove_breakpoint (addr=%x)\n", addr);
+
+ for (i = 0; i < MAX_MONITOR_BREAKPOINTS; i++)
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+ printf_monitor(CLR_BREAK_CMD, addr);
+ is_trace_mode = 0;
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+/* Load a file. This is usually an srecord, which is ascii. No
+ protocol, just sent line by line. */
+
+#define DOWNLOAD_LINE_SIZE 100
+static void
+rombug_load (arg)
+ char *arg;
+{
+/* this part comment out for os9* */
+#if 0
+ FILE *download;
+ char buf[DOWNLOAD_LINE_SIZE];
+ int i, bytes_read;
+
+ if (sr_get_debug())
+ printf ("Loading %s to monitor\n", arg);
+
+ download = fopen (arg, "r");
+ if (download == NULL)
+ {
+ error (sprintf (buf, "%s Does not exist", arg));
+ return;
+ }
+
+ printf_monitor (LOAD_CMD);
+/* expect ("Waiting for S-records from host... ", 1); */
+
+ while (!feof (download))
+ {
+ bytes_read = fread (buf, sizeof (char), DOWNLOAD_LINE_SIZE, download);
+ if (hashmark)
+ {
+ putchar ('.');
+ fflush (stdout);
+ }
+
+ if (SERIAL_WRITE(monitor_desc, buf, bytes_read)) {
+ fprintf(stderr, "SERIAL_WRITE failed: (while downloading) %s\n", safe_strerror(errno));
+ break;
+ }
+ i = 0;
+ while (i++ <=200000) {} ; /* Ugly HACK, probably needs flow control */
+ if (bytes_read < DOWNLOAD_LINE_SIZE)
+ {
+ if (!feof (download))
+ error ("Only read %d bytes\n", bytes_read);
+ break;
+ }
+ }
+
+ if (hashmark)
+ {
+ putchar ('\n');
+ }
+ if (!feof (download))
+ error ("Never got EOF while downloading");
+ fclose (download);
+#endif 0
+}
+
+/* Put a command string, in args, out to MONITOR.
+ Output from MONITOR is placed on the users terminal until the prompt
+ is seen. */
+
+static void
+rombug_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ if (monitor_desc == NULL)
+ error("monitor target not open.");
+
+ if (monitor_log)
+ fprintf (log_file, "\nIn command (args=%s)\n", args);
+
+ if (!args)
+ error("Missing command.");
+
+ printf_monitor("%s\r", args);
+ expect_prompt(0);
+}
+
+#if 0
+/* Connect the user directly to MONITOR. This command acts just like the
+ 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
+
+static struct ttystate ttystate;
+
+static void
+cleanup_tty()
+{ printf("\r\n[Exiting connect mode]\r\n");
+ /*SERIAL_RESTORE(0, &ttystate);*/
+}
+
+static void
+connect_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ fd_set readfds;
+ int numfds;
+ int c;
+ char cur_esc = 0;
+
+ dont_repeat();
+
+ if (monitor_desc == NULL)
+ error("monitor target not open.");
+
+ if (args)
+ fprintf("This command takes no args. They have been ignored.\n");
+
+ printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
+
+ serial_raw(0, &ttystate);
+
+ make_cleanup(cleanup_tty, 0);
+
+ FD_ZERO(&readfds);
+
+ while (1)
+ {
+ do
+ {
+ FD_SET(0, &readfds);
+ FD_SET(monitor_desc, &readfds);
+ numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
+ }
+ while (numfds == 0);
+
+ if (numfds < 0)
+ perror_with_name("select");
+
+ if (FD_ISSET(0, &readfds))
+ { /* tty input, send to monitor */
+ c = getchar();
+ if (c < 0)
+ perror_with_name("connect");
+
+ printf_monitor("%c", c);
+ switch (cur_esc)
+ {
+ case 0:
+ if (c == '\r')
+ cur_esc = c;
+ break;
+ case '\r':
+ if (c == '~')
+ cur_esc = c;
+ else
+ cur_esc = 0;
+ break;
+ case '~':
+ if (c == '.' || c == '\004')
+ return;
+ else
+ cur_esc = 0;
+ }
+ }
+
+ if (FD_ISSET(monitor_desc, &readfds))
+ {
+ while (1)
+ {
+ c = readchar(0);
+ if (c < 0)
+ break;
+ putchar(c);
+ }
+ fflush(stdout);
+ }
+ }
+}
+#endif
+
+/*
+ * Define the monitor command strings. Since these are passed directly
+ * through to a printf style function, we need can include formatting
+ * strings. We also need a CR or LF on the end.
+ */
+struct monitor_ops rombug_cmds = {
+ "g \r", /* execute or usually GO command */
+ "g \r", /* continue command */
+ "t \r", /* single step */
+ "b %x\r", /* set a breakpoint */
+ "k %x\r", /* clear a breakpoint */
+ "c %x\r", /* set memory to a value */
+ "d %x %d\r", /* display memory */
+ "$%08X", /* prompt memory commands use */
+ ".%s %x\r", /* set a register */
+ ":", /* delimiter between registers */
+ ". \r", /* read a register */
+ "mf \r", /* download command */
+ "RomBug: ", /* monitor command prompt */
+ ": ", /* end-of-command delimitor */
+ ".\r" /* optional command terminator */
+};
+
+struct target_ops rombug_ops = {
+ "rombug",
+ "Microware's ROMBUG debug monitor",
+ "Use a remote computer running the ROMBUG debug monitor.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).",
+ rombug_open,
+ rombug_close,
+ 0,
+ rombug_detach,
+ rombug_resume,
+ rombug_wait,
+ rombug_fetch_register,
+ rombug_store_register,
+ rombug_prepare_to_store,
+ rombug_xfer_inferior_memory,
+ rombug_files_info,
+ rombug_insert_breakpoint,
+ rombug_remove_breakpoint, /* Breakpoints */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* Terminal handling */
+ rombug_kill,
+ rombug_load, /* load */
+ rombug_link, /* lookup_symbol */
+ rombug_create_inferior,
+ rombug_mourn_inferior,
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_stop */
+ process_stratum,
+ 0, /* next */
+ 1,
+ 1,
+ 1,
+ 1,
+ 1, /* has execution */
+ 0,
+ 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_os9k ()
+{
+ add_target (&rombug_ops);
+
+ add_show_from_set (
+ add_set_cmd ("hash", no_class, var_boolean, (char *)&hashmark,
+ "Set display of activity while downloading a file.\nWhen enabled, a period \'.\' is displayed.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("timeout", no_class, var_zinteger,
+ (char *) &timeout,
+ "Set timeout in seconds for remote MIPS serial I/O.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotelog", no_class, var_zinteger,
+ (char *) &monitor_log,
+ "Set monitor activity log on(=1) or off(=0).",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotexon", no_class, var_zinteger,
+ (char *) &tty_xon,
+ "Set remote tty line XON control",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("remotexoff", no_class, var_zinteger,
+ (char *) &tty_xoff,
+ "Set remote tty line XOFF control",
+ &setlist),
+ &showlist);
+
+ add_com ("rombug <command>", class_obscure, rombug_command,
+ "Send a command to the debug monitor.");
+#if 0
+ add_com ("connect", class_obscure, connect_command,
+ "Connect the terminal directly up to a serial based command monitor.\nUse <CR>~. or <CR>~^D to break out.");
+#endif
+}
diff --git a/contrib/gdb/gdb/remote-pa.c b/contrib/gdb/gdb/remote-pa.c
new file mode 100644
index 0000000..1121e15
--- /dev/null
+++ b/contrib/gdb/gdb/remote-pa.c
@@ -0,0 +1,1540 @@
+/* Remote target communications for serial-line targets in custom GDB protocol
+ Copyright 1988, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Remote communication protocol.
+
+ A debug packet whose contents are <data>
+ is encapsulated for transmission in the form:
+
+ $ <data> # CSUM1 CSUM2
+
+ <data> must be ASCII alphanumeric and cannot include characters
+ '$' or '#'. If <data> 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 <data>, the most significant nibble is sent first.
+ the hex digits 0-9,a-f are used.
+
+ Receiver responds with:
+
+ + - if CSUM is correct and ready for next packet
+ - - if CSUM is incorrect
+
+ <data> is as follows:
+ All values are encoded in ascii hex digits.
+
+ Request Packet
+
+ read registers g
+ reply XX....X Each byte of register data
+ is described by two hex digits.
+ Registers are in the internal order
+ for GDB, and the bytes in a register
+ are in the same order the machine uses.
+ or ENN for an error.
+
+ write regs GXX..XX Each byte of register data
+ is described by two hex digits.
+ 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
+ if able to read only part of the data.
+ or ENN NN is errno
+
+ write mem MAA..AA,LLLL:XX..XX
+ AA..AA is address,
+ LLLL is number of bytes,
+ XX..XX is data
+ reply OK for success
+ ENN for an error (this includes the case
+ where only part of the data was
+ written).
+
+ cont cAA..AA AA..AA is address to resume
+ If AA..AA is omitted,
+ resume at same address.
+
+ step sAA..AA AA..AA is address to resume
+ If AA..AA is omitted,
+ resume at same address.
+
+ last signal ? Reply the current reason for stopping.
+ This is the same reply as is generated
+ for step or cont : SAA where AA is the
+ signal number.
+
+ There is no immediate reply to step or cont.
+ The reply comes when the machine stops.
+ It is SAA AA is the "signal number"
+
+ or... TAAn...:r...;n:r...;n...:r...;
+ AA = signal number
+ n... = register number
+ r... = register contents
+ or... WAA The process exited, and AA is
+ the exit status. This is only
+ applicable for certains sorts of
+ targets.
+ kill request k
+
+ toggle debug d toggle debug flag (see 386 & 68k stubs)
+ reset r reset -- see sparc stub.
+ reserved <other> On other requests, the stub should
+ ignore the request and send an empty
+ response ($#<checksum>). This way
+ 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 character is an ASCII encoding giving a repeat count which
+ stands for that many repititions of the character preceding the '*'.
+ The encoding is n+29, yielding a printable character where n >=3
+ (which is where rle starts to win). Don't use an n > 126.
+
+ So
+ "0* " means the same as "0000". */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+#include "terminal.h"
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "remote-utils.h"
+#include "dcache.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+#include "serial.h"
+
+/* Prototypes for local functions */
+
+static int
+remote_write_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+static int
+remote_read_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len));
+
+static void
+remote_files_info PARAMS ((struct target_ops *ignore));
+
+static int
+remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
+ int should_write, struct target_ops *target));
+
+static void
+remote_prepare_to_store PARAMS ((void));
+
+static void
+remote_fetch_registers PARAMS ((int regno));
+
+static void
+remote_resume PARAMS ((int pid, int step, enum target_signal siggnal));
+
+static int
+remote_start_remote PARAMS ((char *dummy));
+
+static void
+remote_open PARAMS ((char *name, int from_tty));
+
+static void
+remote_close PARAMS ((int quitting));
+
+static void
+remote_store_registers PARAMS ((int regno));
+
+static void
+getpkt PARAMS ((char *buf, int forever));
+
+static void
+putpkt PARAMS ((char *buf));
+
+static void
+remote_send PARAMS ((char *buf));
+
+static int
+readchar PARAMS ((int timeout));
+
+static int
+remote_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static int
+tohex PARAMS ((int nib));
+
+static int
+fromhex PARAMS ((int a));
+
+static void
+remote_detach PARAMS ((char *args, int from_tty));
+
+static void
+remote_interrupt PARAMS ((int signo));
+
+static void
+remote_interrupt_twice PARAMS ((int signo));
+
+static void
+interrupt_query PARAMS ((void));
+
+static void
+hppro_load PARAMS ((char *name, int from_tty));
+
+extern struct target_ops remote_ops; /* Forward decl */
+
+/* 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 remote_timeout = 2;
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so that
+ remote_open knows that we don't have a file open when the program
+ starts. */
+extern serial_t remote_desc;
+
+/* 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
+#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;
+
+/* sets the download protocol, choices are srec, generic, boot */
+char *loadtype;
+static char *loadtype_str;
+static void set_loadtype_command
+PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+hppro_load (file, from_tty)
+ char *file;
+ int from_tty;
+{
+ puts ("Loading... HA!");
+}
+
+
+/* Clean up connection to a remote debugger. */
+
+/* ARGSUSED */
+static void
+remote_close (quitting)
+ int quitting;
+{
+ if (remote_desc)
+ SERIAL_CLOSE (remote_desc);
+ 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);
+}
+
+#define INBUFSIZE 10
+
+void
+boot_board()
+{
+ char c;
+ char buf[INBUFSIZE];
+ char *ptr;
+
+ /* See if we can connect to the boot ROM command line */
+ ptr = buf;
+ while (1) {
+ SERIAL_WRITE (remote_desc, "\r\n", 2);
+ c = readchar (2);
+ if ((sr_get_debug() > 2) && (isascii(c)))
+ putchar (c);
+ if (c == SERIAL_TIMEOUT) {
+ if (sr_get_debug())
+ puts_filtered ("Timed out.\n");
+ break;
+ }
+ if (c == '&') {
+ if (sr_get_debug() > 2)
+ puts ("Got ACK from stub");
+ break;
+ }
+ if (c == '>') {
+ if (sr_get_debug() > 2)
+ puts ("Got prompt from ROM monitor");
+ break;
+ }
+ }
+
+}
+
+/* Stub for catch_errors. */
+static int
+remote_start_remote (dummy)
+ char *dummy;
+{
+ int timeout;
+
+ immediate_quit = 1; /* Allow user to interrupt it */
+
+ /* Ack any packet which the remote side has already sent. */
+
+ if (sr_get_debug())
+ puts ("Trying a '+' to ACK the target.");
+
+ SERIAL_WRITE (remote_desc, "+", 1);
+
+#if 0
+ boot_board();
+
+ get_offsets (); /* Get text, data & bss offsets */
+#endif
+
+ putpkt ("?"); /* initiate a query from remote machine */
+ immediate_quit = 0;
+
+ start_remote (); /* Initialize gdb process mechanisms */
+
+ return 1;
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static DCACHE *remote_dcache;
+
+static void
+remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ if (name == 0)
+ error (
+"To open a remote debug connection, you need to specify what serial\n\
+device is attached to the remote system (e.g. /dev/ttya).");
+
+ target_preopen (from_tty);
+
+ unpush_target (&remote_ops);
+
+ remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
+
+ remote_desc = SERIAL_OPEN (name);
+ if (!remote_desc)
+ perror_with_name (name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (remote_desc, baud_rate))
+ {
+ SERIAL_CLOSE (remote_desc);
+ perror_with_name (name);
+ }
+ }
+
+ SERIAL_RAW (remote_desc);
+
+ /* If there is something sitting in the buffer we might take it as a
+ response to a command, which would be bad. */
+ SERIAL_FLUSH_INPUT (remote_desc);
+
+ if (from_tty)
+ {
+ puts_filtered ("Remote debugging using ");
+ puts_filtered (name);
+ puts_filtered ("\n");
+ }
+ 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;
+
+ /* Without this, some commands which require an active target (such as kill)
+ won't work. This variable serves (at least) double duty as both the pid
+ of the target process (if it has such), and as a flag indicating that a
+ target is active. These functions should be split out into seperate
+ variables, especially since GDB will someday have a notion of debugging
+ several processes. */
+
+ inferior_pid = 42000;
+
+ /* 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). */
+ if (!catch_errors (remote_start_remote, (char *)0,
+ "Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
+ pop_target();
+}
+
+/* remote_detach()
+ takes a program previously attached to and detaches it.
+ We better not have left any breakpoints
+ in the program or it'll die when it hits one.
+ Close the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+
+static void
+remote_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ pop_target ();
+ if (from_tty)
+ puts_filtered ("Ending remote debugging.\n");
+}
+
+/* Convert hex digit A to a number. */
+
+static int
+fromhex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else
+ error ("Reply contains invalid hex digit");
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0'+nib;
+ else
+ return 'a'+nib-10;
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+remote_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ char buf[PBUFSIZ];
+
+ if (siggnal)
+ {
+ target_terminal_ours_for_output ();
+ printf_filtered
+ ("Can't send signals to a remote system. %s not sent.\n",
+ target_signal_to_name (siggnal)); target_terminal_inferior ();
+ }
+
+ dcache_flush (remote_dcache);
+
+ strcpy (buf, step ? "s": "c");
+
+ putpkt (buf);
+}
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void
+remote_interrupt (signo)
+ int signo;
+{
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, remote_interrupt_twice);
+
+ if (remote_debug)
+ printf_unfiltered ("remote_interrupt called\n");
+
+ SERIAL_WRITE (remote_desc, "\003", 1); /* Send a ^C */
+}
+
+static void (*ofunc)();
+
+/* The user typed ^C twice. */
+static void
+remote_interrupt_twice (signo)
+ int signo;
+{
+ signal (signo, ofunc);
+
+ interrupt_query ();
+
+ signal (signo, remote_interrupt);
+}
+
+/* Ask the user what to do when an interrupt is received. */
+
+static void
+interrupt_query ()
+{
+ target_terminal_ours ();
+
+ if (query ("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? "))
+ {
+ target_mourn_inferior ();
+ return_to_top_level (RETURN_QUIT);
+ }
+
+ target_terminal_inferior ();
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would.
+ Returns "pid" (though it's not clear what, if anything, that
+ means in the case of this target). */
+
+static int
+remote_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ unsigned char buf[PBUFSIZ];
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ while (1)
+ {
+ unsigned char *p;
+
+ ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
+ getpkt ((char *) buf, 1);
+ signal (SIGINT, ofunc);
+
+ switch (buf[0])
+ {
+ 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
+ */
+
+ p = &buf[3]; /* after Txx */
+
+ while (*p)
+ {
+ unsigned char *p1;
+
+ regno = strtol (p, (char **) &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);
+ }
+ }
+ /* 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 inferior_pid;
+ case 'W': /* Target exited */
+ {
+ /* The remote process exited. */
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+ return inferior_pid;
+ }
+ case 'O': /* Console output */
+ fputs_filtered (buf + 1, gdb_stdout);
+ continue;
+ default:
+ warning ("Invalid remote reply: %s", buf);
+ continue;
+ }
+ }
+ return inferior_pid;
+}
+
+/* Number of bytes of registers this stub implements. */
+static int register_bytes_found;
+
+/* Read the remote registers into the block REGS. */
+/* Currently we just read all the registers, so we don't use regno. */
+/* ARGSUSED */
+static void
+remote_fetch_registers (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+ char regs[REGISTER_BYTES];
+
+ sprintf (buf, "g");
+ remote_send (buf);
+
+ /* Unimplemented registers read as all bits zero. */
+ memset (regs, 0, REGISTER_BYTES);
+
+ /* We can get out of synch in various cases. If the first character
+ in the buffer is not a hex character, assume that has happened
+ and try to fetch another packet to read. */
+ while ((buf[0] < '0' || buf[0] > '9')
+ && (buf[0] < 'a' || buf[0] > 'f'))
+ {
+ if (remote_debug)
+ printf_unfiltered ("Bad register packet; fetching a new packet\n");
+ getpkt (buf, 0);
+ }
+
+ /* Reply describes registers byte by byte, each byte encoded as two
+ hex characters. Suck them all up, then supply them to the
+ register cacheing/storage mechanism. */
+
+ p = buf;
+ for (i = 0; i < REGISTER_BYTES; i++)
+ {
+ if (p[0] == 0)
+ break;
+ if (p[1] == 0)
+ {
+ warning ("Remote reply is of odd length: %s", buf);
+ /* Don't change register_bytes_found in this case, and don't
+ print a second warning. */
+ goto supply_them;
+ }
+ regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+
+ if (i != register_bytes_found)
+ {
+ register_bytes_found = i;
+#ifdef REGISTER_BYTES_OK
+ if (!REGISTER_BYTES_OK (i))
+ warning ("Remote reply is too short: %s", buf);
+#endif
+ }
+
+ supply_them:
+ for (i = 0; i < NUM_REGS; i++)
+ supply_register (i, &regs[REGISTER_BYTE(i)]);
+}
+
+/* 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 ()
+{
+ /* Make sure the entire registers array is valid. */
+ read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
+}
+
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. FIXME: ignores errors. */
+
+static void
+remote_store_registers (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ 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 = &registers[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. */
+
+ p = buf + 1;
+ /* remote_prepare_to_store insures that register_bytes_found gets set. */
+ for (i = 0; i < register_bytes_found; i++)
+ {
+ *p++ = tohex ((registers[i] >> 4) & 0xf);
+ *p++ = tohex (registers[i] & 0xf);
+ }
+ *p = '\0';
+
+ remote_send (buf);
+}
+
+#if 0
+
+/* Use of the data cache is disabled because it loses for looking at
+ and changing hardware I/O ports and the like. Accepting `volatile'
+ would perhaps be one way to fix it. Another idea would be to use the
+ executable file for the text segment (for all SEC_CODE sections?
+ For all SEC_READONLY sections?). This has problems if you want to
+ actually see what the memory contains (e.g. self-modifying code,
+ clobbered memory, user downloaded the wrong thing). */
+
+/* Read a word from remote address ADDR and return it.
+ This goes through the data cache. */
+
+static int
+remote_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ return dcache_fetch (remote_dcache, addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+static void
+remote_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (remote_dcache, addr, word);
+}
+#endif /* 0 */
+
+/* Write memory data directly to the remote machine.
+ This does not inform the data cache; the data cache uses this.
+ MEMADDR is the address in the remote memory space.
+ MYADDR is the address of the buffer in our space.
+ LEN is the number of bytes.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+static int
+remote_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ /* 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. */
+
+ p = buf + strlen (buf);
+ for (i = 0; i < len; i++)
+ {
+ *p++ = tohex ((myaddr[i] >> 4) & 0xf);
+ *p++ = tohex (myaddr[i] & 0xf);
+ }
+ *p = '\0';
+
+ putpkt (buf);
+ getpkt (buf, 0);
+
+ 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 return EIO. */
+ errno = EIO;
+ return 0;
+ }
+ return len;
+}
+
+/* Read memory data directly from the remote machine.
+ This does not use the data cache; the data cache uses this.
+ MEMADDR is the address in the remote memory space.
+ MYADDR is the address of the buffer in our space.
+ LEN is the number of bytes.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+static int
+remote_read_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ if (len > PBUFSIZ / 2 - 1)
+ abort ();
+
+ /* 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);
+
+ 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 return EIO. */
+ errno = EIO;
+ return 0;
+ }
+
+ /* Reply describes memory byte by byte,
+ each byte encoded as two hex characters. */
+
+ p = buf;
+ for (i = 0; i < len; i++)
+ {
+ if (p[0] == 0 || p[1] == 0)
+ /* Reply is short. This means that we were able to read only part
+ of what we wanted to. */
+ break;
+ myaddr[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+ return i;
+}
+
+/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+ to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
+ nonzero. Returns length of data written or read; 0 for error. */
+
+/* ARGSUSED */
+static int
+remote_xfer_memory(memaddr, myaddr, len, should_write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+ struct target_ops *target; /* ignored */
+{
+ int xfersize;
+ int bytes_xferred;
+ int total_xferred = 0;
+
+ while (len > 0)
+ {
+ if (len > MAXBUFBYTES)
+ xfersize = MAXBUFBYTES;
+ else
+ xfersize = len;
+
+ if (should_write)
+ bytes_xferred = remote_write_bytes (memaddr, myaddr, xfersize);
+ else
+ bytes_xferred = remote_read_bytes (memaddr, myaddr, xfersize);
+
+ /* If we get an error, we are done xferring. */
+ if (bytes_xferred == 0)
+ break;
+
+ memaddr += bytes_xferred;
+ myaddr += bytes_xferred;
+ len -= bytes_xferred;
+ total_xferred += bytes_xferred;
+ }
+ 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;
+{
+ puts_filtered ("Debugging a target over a serial line.\n");
+}
+
+/* Stuff for dealing with the packets which are part of this protocol.
+ See comment at top of file for details. */
+
+/* Read a single character from the remote end, masking it down to 7 bits. */
+
+static int
+readchar (timeout)
+ int timeout;
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (remote_desc, timeout);
+
+ 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,
+ and read the reply into BUF.
+ Report an error if we get an error reply. */
+
+static void
+remote_send (buf)
+ char *buf;
+{
+
+ putpkt (buf);
+ getpkt (buf, 0);
+
+ if (buf[0] == 'E')
+ error ("Remote failure reply: %s", buf);
+}
+
+/* Send a packet to the remote machine, with error checking.
+ The data of the packet is in BUF. */
+static void
+putpkt (buf)
+ char *buf;
+{
+ int i;
+ unsigned char csum = 0;
+ char buf2[PBUFSIZ];
+ int cnt = strlen (buf);
+ int ch;
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ if (cnt > sizeof(buf2) - 5) /* Prosanity check */
+ abort();
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ /* Send it over and over until we get a positive ack. */
+
+ while (1)
+ {
+ int started_error_output = 0;
+
+ if (remote_debug)
+ {
+ *p = '\0';
+ printf_unfiltered ("Sending packet: %s...", buf2);
+ gdb_flush(gdb_stdout);
+ }
+ if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
+ perror_with_name ("putpkt: write failed");
+
+ /* read until either a timeout occurs (-2) or '+' is read */
+ while (1)
+ {
+ ch = readchar (remote_timeout);
+
+ if (remote_debug)
+ {
+ switch (ch)
+ {
+ case '+':
+ case SERIAL_TIMEOUT:
+ case '$':
+ if (started_error_output)
+ {
+ putchar_unfiltered ('\n');
+ started_error_output = 0;
+ }
+ }
+ }
+
+ switch (ch)
+ {
+ case '+':
+ if (remote_debug)
+ printf_unfiltered("Got Ack\n");
+ return;
+ case SERIAL_TIMEOUT:
+ break; /* Retransmit buffer */
+ 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)
+ {
+ if (!started_error_output)
+ {
+ started_error_output = 1;
+ printf_unfiltered ("putpkt: Junk: ");
+ }
+ putchar_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;
+ pktcsum |= 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 */
+ csum += c;
+ 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;
+ }
+ }
+}
+
+/* Read a packet from the remote machine, with error checking,
+ and store it in BUF. BUF is expected to be of size PBUFSIZ.
+ If FOREVER, wait forever rather than timing out; this is used
+ while the target is executing user code. */
+
+static void
+getpkt (buf, forever)
+ char *buf;
+ int forever;
+{
+ char *bp;
+ int c;
+ int tries;
+ int timeout;
+ int val;
+
+ if (forever)
+ timeout = -1;
+ else
+ timeout = remote_timeout;
+
+#define MAX_TRIES 10
+
+ for (tries = 1; tries <= MAX_TRIES; tries++)
+ {
+ /* 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. */
+
+ /* 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. */
+
+ do
+ {
+ c = readchar (timeout);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (remote_debug)
+ puts_filtered ("Timed out.\n");
+ goto retry;
+ }
+ }
+ while (c != '$');
+
+ /* 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. */
+retry:
+ SERIAL_WRITE (remote_desc, "-", 1);
+ }
+
+ /* 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);
+}
+
+static void
+remote_kill ()
+{
+ putpkt ("k");
+ /* Don't wait for it to die. I'm not really sure it matters whether
+ we do or not. For the existing stubs, kill is a noop. */
+ target_mourn_inferior ();
+}
+
+static void
+remote_mourn ()
+{
+ unpush_target (&remote_ops);
+ generic_mourn_inferior ();
+}
+
+#ifdef REMOTE_BREAKPOINT
+
+/* On some machines, e.g. 68k, we may use a different breakpoint instruction
+ than other targets. */
+static unsigned char break_insn[] = REMOTE_BREAKPOINT;
+
+#else /* No REMOTE_BREAKPOINT. */
+
+/* Same old breakpoint instruction. This code does nothing different
+ than mem-break.c. */
+static unsigned char break_insn[] = BREAKPOINT;
+
+#endif /* No REMOTE_BREAKPOINT. */
+
+/* Insert a breakpoint on targets that don't have any better breakpoint
+ support. We read the contents of the target location and stash it,
+ then overwrite it with a breakpoint instruction. ADDR is the target
+ location in the target machine. CONTENTS_CACHE is a pointer to
+ memory allocated for saving the target contents. It is guaranteed
+ by the caller to be long enough to save sizeof BREAKPOINT bytes (this
+ is accomplished via BREAKPOINT_MAX). */
+
+static int
+remote_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int val;
+
+ val = target_read_memory (addr, contents_cache, sizeof break_insn);
+
+ if (val == 0)
+ val = target_write_memory (addr, (char *)break_insn, sizeof break_insn);
+
+ return val;
+}
+
+static int
+remote_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ return target_write_memory (addr, contents_cache, sizeof break_insn);
+}
+
+/* Define the target subroutine names */
+
+struct target_ops remote_hppro_ops = {
+ "hppro", /* to_shortname */
+ "Remote serial target for HP-PRO targets", /* to_longname */
+ "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
+This is for targets that supports the HP-PRO standard.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya) or telnet port.", /* to_doc */
+ remote_open, /* to_open */
+ remote_close, /* to_close */
+ NULL, /* to_attach */
+ remote_detach, /* to_detach */
+ remote_resume, /* to_resume */
+ remote_wait, /* to_wait */
+ remote_fetch_registers, /* to_fetch_registers */
+ remote_store_registers, /* to_store_registers */
+ remote_prepare_to_store, /* to_prepare_to_store */
+ remote_xfer_memory, /* to_xfer_memory */
+ remote_files_info, /* to_files_info */
+
+ remote_insert_breakpoint, /* to_insert_breakpoint */
+ remote_remove_breakpoint, /* to_remove_breakpoint */
+
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ remote_kill, /* to_kill */
+ hppro_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ NULL, /* to_create_inferior */
+ remote_mourn, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_remote_hppro ()
+{
+ struct cmd_list_element *c;
+ add_target (&remote_hppro_ops);
+
+ /* this sets the type of download protocol */
+ c = add_set_cmd ("loadtype", no_class, var_string, (char *)&loadtype_str,
+ "Set the type of the remote load protocol.\n", &setlist);
+ c->function.sfunc = set_loadtype_command;
+ add_show_from_set (c, &showlist);
+ loadtype_str = savestring ("generic", 8);
+
+ /* this adds a command to boot the board */
+ add_com ("boot", class_support, boot_board,
+ "Boot the damn target board.\n");
+}
+
+static void
+set_loadtype_command (ignore, from_tty, c)
+ char *ignore;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ loadtype_str = savestring (*(char **) c->var, strlen (*(char **) c->var));
+}
+
diff --git a/contrib/gdb/gdb/remote-rdp.c b/contrib/gdb/gdb/remote-rdp.c
new file mode 100644
index 0000000..3cc4c4e
--- /dev/null
+++ b/contrib/gdb/gdb/remote-rdp.c
@@ -0,0 +1,1247 @@
+/* Remote debugging for the ARM RDP interface.
+ Copyright 1994, 1995 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+ */
+
+
+/*
+ Much of this file (in particular the SWI stuff) is based on code by
+ David Taylor (djt1000@uk.ac.cam.hermes).
+
+ I hacked on and simplified it by removing a lot of sexy features he
+ had added, and some of the (unix specific) workarounds he'd done
+ for other GDB problems - which if they still exist should be fixed
+ in GDB, not in a remote-foo thing . I also made it conform more to
+ the doc I have; which may be wrong.
+
+ Steve Chamberlain (sac@cygnus.com).
+ */
+
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include "callback.h"
+#include "command.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <ctype.h>
+#include <fcntl.h>
+#include "symfile.h"
+#include "remote-utils.h"
+#include "gdb_string.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+
+extern struct target_ops remote_rdp_ops;
+static serial_t io;
+static host_callback *callback = &default_callback;
+
+struct
+ {
+ int step_info;
+ int break_info;
+ int model_info;
+ int target_info;
+ int can_step;
+ char command_line[10];
+ int rdi_level;
+ int rdi_stopped_status;
+ }
+ds;
+
+
+
+/* Definitions for the RDP protocol. */
+
+#define RDP_MOUTHFULL (1<<6)
+#define FPU_COPRO_NUMBER 1
+
+#define RDP_OPEN 0
+#define RDP_OPEN_TYPE_COLD 0
+#define RDP_OPEN_TYPE_WARM 1
+#define RDP_OPEN_TYPE_BAUDRATE 2
+
+#define RDP_OPEN_BAUDRATE_9600 1
+#define RDP_OPEN_BAUDRATE_19200 2
+#define RDP_OPEN_BAUDRATE_38400 3
+
+#define RDP_OPEN_TYPE_RETURN_SEX (1<<3)
+
+#define RDP_CLOSE 1
+
+#define RDP_MEM_READ 2
+
+#define RDP_MEM_WRITE 3
+
+#define RDP_CPU_READ 4
+#define RDP_CPU_WRITE 5
+#define RDP_CPU_READWRITE_MODE_CURRENT 255
+#define RDP_CPU_READWRITE_MASK_PC (1<<16)
+#define RDP_CPU_READWRITE_MASK_CPSR (1<<17)
+#define RDP_CPU_READWRITE_MASK_SPSR (1<<18)
+
+#define RDP_COPRO_READ 6
+#define RDP_COPRO_WRITE 7
+#define RDP_FPU_READWRITE_MASK_FPS (1<<8)
+
+#define RDP_SET_BREAK 0xa
+#define RDP_SET_BREAK_TYPE_PC_EQUAL 0
+#define RDP_SET_BREAK_TYPE_GET_HANDLE (0x10)
+
+#define RDP_CLEAR_BREAK 0xb
+
+#define RDP_EXEC 0x10
+#define RDP_EXEC_TYPE_SYNC 0
+
+#define RDP_STEP 0x11
+
+#define RDP_INFO 0x12
+#define RDP_INFO_ABOUT_STEP 2
+#define RDP_INFO_ABOUT_STEP_GT_1 1
+#define RDP_INFO_ABOUT_STEP_TO_JMP 2
+#define RDP_INFO_ABOUT_STEP_1 4
+#define RDP_INFO_ABOUT_TARGET 0
+#define RDP_INFO_ABOUT_BREAK 1
+#define RDP_INFO_ABOUT_BREAK_COMP 1
+#define RDP_INFO_ABOUT_BREAK_RANGE 2
+#define RDP_INFO_ABOUT_BREAK_BYTE_READ 4
+#define RDP_INFO_ABOUT_BREAK_HALFWORD_READ 8
+#define RDP_INFO_ABOUT_BREAK_WORD_READ (1<<4)
+#define RDP_INFO_ABOUT_BREAK_BYTE_WRITE (1<<5)
+#define RDP_INFO_ABOUT_BREAK_HALFWORD_WRITE (1<<6)
+#define RDP_INFO_ABOUT_BREAK_WORD_WRITE (1<<7)
+#define RDP_INFO_ABOUT_BREAK_MASK (1<<8)
+#define RDP_INFO_ABOUT_BREAK_THREAD_BREAK (1<<9)
+#define RDP_INFO_ABOUT_BREAK_THREAD_WATCH (1<<10)
+#define RDP_INFO_ABOUT_BREAK_COND (1<<11)
+
+#define RDP_RESET 0x7f
+
+/* Returns from RDP */
+#define RDP_RES_STOPPED 0x20
+#define RDP_RES_SWI 0x21
+#define RDP_RES_FATAL 0x5e
+#define RDP_RES_VALUE 0x5f
+#define RDP_RES_VALUE_LITTLE_ENDIAN 240
+#define RDP_RES_VALUE_BIG_ENDIAN 241
+#define RDP_RES_RESET 0x7f
+#define RDP_RES_AT_BREAKPOINT 143
+#define RDP_RES_IDUNNO 0xe6
+#define RDP_OSOpReply 0x13
+#define RDP_OSOpWord 2
+#define RDP_OSOpNothing 0
+
+static int timeout = 2;
+
+static int
+remote_rdp_xfer_inferior_memory PARAMS ((CORE_ADDR memaddr,
+ char *myaddr,
+ int len,
+ int write,
+ struct target_ops * target));
+
+
+/* Stuff for talking to the serial layer. */
+
+static unsigned char
+get_byte ()
+{
+ int c = SERIAL_READCHAR (io, timeout);
+
+ if (remote_debug)
+ printf ("[%02x]\n", c);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return (unsigned char) c;
+
+ error ("Timeout reading from remote_system");
+ }
+
+ return c;
+}
+
+/* Note that the target always speaks little-endian to us,
+ even if it's a big endian machine. */
+static unsigned int
+get_word ()
+{
+ unsigned int val = 0;
+ unsigned int c;
+ int n;
+ for (n = 0; n < 4; n++)
+ {
+ c = get_byte ();
+ val |= c << (n * 8);
+ }
+ return val;
+}
+
+static void
+put_byte (val)
+ char val;
+{
+ if (remote_debug)
+ printf ("(%02x)\n", val);
+ SERIAL_WRITE (io, &val, 1);
+}
+
+static void
+put_word (val)
+ int val;
+{
+ /* We always send in little endian */
+ unsigned char b[4];
+ b[0] = val;
+ b[1] = val >> 8;
+ b[2] = val >> 16;
+ b[3] = val >> 24;
+
+ if (remote_debug)
+ printf ("(%04x)", val);
+
+ SERIAL_WRITE (io, b, 4);
+}
+
+
+
+/* Stuff for talking to the RDP layer. */
+
+/* This is a bit more fancy that need be so that it syncs even in nasty cases.
+
+ I'be been unable to make it reliably sync up with the change
+ baudrate open command. It likes to sit and say it's been reset,
+ with no more action. So I took all that code out. I'd rather sync
+ reliably at 9600 than wait forever for a possible 19200 connection.
+
+ */
+static void
+rdp_init (cold, tty)
+ int cold;
+ int tty;
+{
+ int sync = 0;
+ int type = cold ? RDP_OPEN_TYPE_COLD : RDP_OPEN_TYPE_WARM;
+ int baudtry = 9600;
+
+ time_t now = time (0);
+ time_t stop_time = now + 10; /* Try and sync for 10 seconds, then give up */
+
+
+ while (time (0) < stop_time && !sync)
+ {
+ int restype;
+ QUIT;
+
+ SERIAL_FLUSH_INPUT (io);
+ SERIAL_FLUSH_OUTPUT (io);
+
+ if (tty)
+ printf_unfiltered ("Trying to connect at %d baud.\n", baudtry);
+ put_byte (RDP_OPEN);
+
+ put_byte (type | RDP_OPEN_TYPE_RETURN_SEX);
+ put_word (0);
+
+ while (!sync && (restype = SERIAL_READCHAR (io, 1)) > 0)
+ {
+ if (remote_debug)
+ printf_unfiltered ("[%02x]\n", restype);
+
+ switch (restype)
+ {
+ case SERIAL_TIMEOUT:
+ break;
+ case RDP_RESET:
+ while ((restype = SERIAL_READCHAR (io, 1)) == RDP_RESET)
+ ;
+ while ((restype = SERIAL_READCHAR (io, 1)) > 0)
+ {
+ printf_unfiltered ("%c", isgraph (restype) ? restype : ' ');
+ }
+ while ((restype = SERIAL_READCHAR (io, 1)) > 0)
+ ;
+ if (tty)
+ {
+ printf_unfiltered ("\nThe board has sent notification that it was reset.\n");
+ printf_unfiltered ("Waiting for it to settle down...\n");
+ }
+ sleep (3);
+ if (tty)
+ printf_unfiltered ("\nTrying again.\n");
+ break;
+ default:
+ break;
+ case RDP_RES_VALUE:
+ {
+ int resval = SERIAL_READCHAR (io, 1);
+ switch (resval)
+ {
+ case SERIAL_TIMEOUT:
+ break;
+ case RDP_RES_VALUE_LITTLE_ENDIAN:
+ target_byte_order = LITTLE_ENDIAN;
+ sync = 1;
+ break;
+ case RDP_RES_VALUE_BIG_ENDIAN:
+ target_byte_order = BIG_ENDIAN;
+ sync = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (!sync)
+ {
+ error ("Couldn't reset the board, try pressing the reset button");
+ }
+}
+
+
+#ifdef ANSI_PROTOTYPES
+void
+send_rdp (char *template,...)
+#else
+void
+send_rdp (char *template, va_alist)
+ va_dcl
+#endif
+{
+ char buf[200];
+ char *dst = buf;
+ va_list alist;
+#ifdef ANSI_PROTOTYPES
+ va_start (alist, template);
+#else
+ va_start (alist);
+#endif
+
+ while (*template)
+ {
+ unsigned int val;
+ int *pi;
+ int *pstat;
+ char *pc;
+ int i;
+ switch (*template++)
+ {
+ case 'b':
+ val = va_arg (alist, int);
+ *dst++ = val;
+ break;
+ case 'w':
+ val = va_arg (alist, int);
+ *dst++ = val;
+ *dst++ = val >> 8;
+ *dst++ = val >> 16;
+ *dst++ = val >> 24;
+ break;
+ case 'S':
+ val = get_byte ();
+ if (val != RDP_RES_VALUE)
+ {
+ printf_unfiltered ("got bad res value of %d, %x\n", val, val);
+ }
+ break;
+ case 'V':
+ pstat = va_arg (alist, int *);
+ pi = va_arg (alist, int *);
+
+ *pstat = get_byte ();
+ /* Check the result was zero, if not read the syndrome */
+ if (*pstat)
+ {
+ *pi = get_word ();
+ }
+ break;
+ case 'Z':
+ /* Check the result code, error if not zero */
+ if (get_byte ())
+ error ("Command garbled");
+ break;
+ case 'W':
+ /* Read a word from the target */
+ pi = va_arg (alist, int *);
+ *pi = get_word ();
+ break;
+ case 'P':
+ /* Read in some bytes from the target. */
+ pc = va_arg (alist, char *);
+ val = va_arg (alist, int);
+ for (i = 0; i < val; i++)
+ {
+ pc[i] = get_byte ();
+ }
+ break;
+ case 'p':
+ /* send what's being pointed at */
+ pc = va_arg (alist, char *);
+ val = va_arg (alist, int);
+ dst = buf;
+ SERIAL_WRITE (io, pc, val);
+ break;
+ case '-':
+ /* Send whats in the queue */
+ if (dst != buf)
+ {
+ SERIAL_WRITE (io, buf, dst - buf);
+ dst = buf;
+ }
+ break;
+ case 'B':
+ pi = va_arg (alist, int *);
+ *pi = get_byte ();
+ break;
+ default:
+ abort ();
+ }
+ }
+ va_end (args);
+
+ if (dst != buf)
+ abort ();
+}
+
+
+static int
+rdp_write (memaddr, buf, len)
+ CORE_ADDR memaddr;
+ char *buf;
+ int len;
+{
+ int res;
+ int val;
+
+ send_rdp ("bww-p-SV", RDP_MEM_WRITE, memaddr, len, buf, len, &res, &val);
+
+ if (res)
+ {
+ return val;
+ }
+ return len;
+}
+
+
+static int
+rdp_read (memaddr, buf, len)
+ CORE_ADDR memaddr;
+ char *buf;
+ int len;
+{
+ int res;
+ int val;
+ send_rdp ("bww-S-P-V",
+ RDP_MEM_READ, memaddr, len,
+ buf, len,
+ &res, &val);
+ if (res)
+ {
+ return val;
+ }
+ return len;
+}
+
+static void
+rdp_fetch_one_register (mask, buf)
+ int mask;
+ char *buf;
+{
+ int val;
+ send_rdp ("bbw-SWZ", RDP_CPU_READ, RDP_CPU_READWRITE_MODE_CURRENT, mask, &val);
+ store_signed_integer (buf, 4, val);
+}
+
+static void
+rdp_fetch_one_fpu_register (mask, buf)
+ int mask;
+ char *buf;
+{
+#if 0
+ /* !!! Since the PIE board doesn't work as documented,
+ and it doesn't have FPU hardware anyway and since it
+ slows everything down, I've disabled this. */
+ int val;
+ if (mask == RDP_FPU_READWRITE_MASK_FPS)
+ {
+ /* this guy is only a word */
+ send_rdp ("bbw-SWZ", RDP_COPRO_READ, FPU_COPRO_NUMBER, mask, &val);
+ store_signed_integer (buf, 4, val);
+ }
+ else
+ {
+ /* There are 12 bytes long
+ !! fixme about endianness
+ */
+ int dummy; /* I've seen these come back as four words !! */
+ send_rdp ("bbw-SWWWWZ", RDP_COPRO_READ, FPU_COPRO_NUMBER, mask, buf + 0, buf + 4, buf + 8, &dummy);
+ }
+#endif
+ memset (buf, 0, MAX_REGISTER_RAW_SIZE);
+}
+
+
+static void
+rdp_store_one_register (mask, buf)
+ int mask;
+ char *buf;
+{
+ int val = extract_unsigned_integer (buf, 4);
+
+ send_rdp ("bbww-SZ",
+ RDP_CPU_WRITE, RDP_CPU_READWRITE_MODE_CURRENT, mask, val);
+}
+
+
+static void
+rdp_store_one_fpu_register (mask, buf)
+ int mask;
+ char *buf;
+{
+#if 0
+ /* See comment in fetch_one_fpu_register */
+ if (mask == RDP_FPU_READWRITE_MASK_FPS)
+ {
+ int val = extract_unsigned_integer (buf, 4);
+ /* this guy is only a word */
+ send_rdp ("bbww-SZ", RDP_COPRO_WRITE,
+ FPU_COPRO_NUMBER,
+ mask, val);
+ }
+ else
+ {
+ /* There are 12 bytes long
+ !! fixme about endianness
+ */
+ int dummy = 0;
+ /* I've seen these come as four words, not the three advertized !! */
+ printf ("Sending mask %x\n", mask);
+ send_rdp ("bbwwwww-SZ",
+ RDP_COPRO_WRITE,
+ FPU_COPRO_NUMBER,
+ mask,
+ *(int *) (buf + 0),
+ *(int *) (buf + 4),
+ *(int *) (buf + 8),
+ 0);
+
+ printf ("done mask %x\n", mask);
+ }
+#endif
+}
+
+
+/* Convert between GDB requests and the RDP layer. */
+
+static void
+remote_rdp_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ remote_rdp_fetch_register (regno);
+ }
+ else
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+ if (regno < 15)
+ rdp_fetch_one_register (1 << regno, buf);
+ else if (regno == PC_REGNUM)
+ rdp_fetch_one_register (RDP_CPU_READWRITE_MASK_PC, buf);
+ else if (regno == PS_REGNUM)
+ rdp_fetch_one_register (RDP_CPU_READWRITE_MASK_CPSR, buf);
+ else if (regno == FPS_REGNUM)
+ rdp_fetch_one_fpu_register (RDP_FPU_READWRITE_MASK_FPS, buf);
+ else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
+ rdp_fetch_one_fpu_register (1 << (regno - F0_REGNUM), buf);
+ else
+ {
+ printf ("Help me with fetch reg %d\n", regno);
+ }
+ supply_register (regno, buf);
+ }
+}
+
+
+static void
+remote_rdp_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ remote_rdp_store_register (regno);
+ }
+ else
+ {
+ char tmp[MAX_REGISTER_RAW_SIZE];
+ read_register_gen (regno, tmp);
+ if (regno < 15)
+ rdp_store_one_register (1 << regno, tmp);
+ else if (regno == PC_REGNUM)
+ rdp_store_one_register (RDP_CPU_READWRITE_MASK_PC, tmp);
+ else if (regno == PS_REGNUM)
+ rdp_store_one_register (RDP_CPU_READWRITE_MASK_CPSR, tmp);
+ else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
+ rdp_store_one_fpu_register (1 << (regno - F0_REGNUM), tmp);
+ else
+ {
+ printf ("Help me with reg %d\n", regno);
+ }
+ }
+}
+
+static void
+remote_rdp_kill ()
+{
+ callback->shutdown (callback);
+}
+
+
+static void
+rdp_info ()
+{
+ send_rdp ("bw-S-W-Z", RDP_INFO, RDP_INFO_ABOUT_STEP,
+ &ds.step_info);
+ send_rdp ("bw-S-W-Z", RDP_INFO, RDP_INFO_ABOUT_BREAK,
+ &ds.break_info);
+ send_rdp ("bw-S-WW-Z", RDP_INFO, RDP_INFO_ABOUT_TARGET,
+ &ds.target_info,
+ &ds.model_info);
+
+ ds.can_step = ds.step_info & RDP_INFO_ABOUT_STEP_1;
+
+ ds.rdi_level = (ds.target_info >> 5) & 3;
+}
+
+
+static void
+rdp_execute_start ()
+{
+ /* Start it off, but don't wait for it */
+ send_rdp ("bb-", RDP_EXEC, RDP_EXEC_TYPE_SYNC);
+}
+
+
+
+#define a_byte 1
+#define a_word 2
+#define a_string 3
+
+
+typedef struct
+{
+ CORE_ADDR n;
+ const char *s;
+}
+argsin;
+
+#define ABYTE 1
+#define AWORD 2
+#define ASTRING 3
+#define ADDRLEN 4
+
+#define SWI_WriteC 0x0
+#define SWI_Write0 0x2
+#define SWI_ReadC 0x4
+#define SWI_CLI 0x5
+#define SWI_GetEnv 0x10
+#define SWI_Exit 0x11
+#define SWI_EnterOS 0x16
+
+#define SWI_GetErrno 0x60
+#define SWI_Clock 0x61
+
+#define SWI_Time 0x63
+#define SWI_Remove 0x64
+#define SWI_Rename 0x65
+#define SWI_Open 0x66
+
+#define SWI_Close 0x68
+#define SWI_Write 0x69
+#define SWI_Read 0x6a
+#define SWI_Seek 0x6b
+#define SWI_Flen 0x6c
+
+#define SWI_IsTTY 0x6e
+#define SWI_TmpNam 0x6f
+#define SWI_InstallHandler 0x70
+#define SWI_GenerateError 0x71
+
+
+static int
+exec_swi (swi, args)
+ int swi;
+ argsin *args;
+{
+ int i;
+ char c;
+ switch (swi)
+ {
+ case SWI_WriteC:
+ callback->write_stdout (callback, &c, 1);
+ return 0;
+ case SWI_Write0:
+ for (i = 0; i < args->n; i++)
+ callback->write_stdout (callback, args->s, strlen (args->s));
+ return 0;
+ case SWI_ReadC:
+ callback->read_stdin (callback, &c, 1);
+ args->n = c;
+ return 1;
+ case SWI_CLI:
+ args->n = callback->system (callback, args->s);
+ return 1;
+ case SWI_GetErrno:
+ args->n = callback->get_errno (callback);
+ return 1;
+ case SWI_Time:
+ args->n = callback->time (callback, NULL);
+ return 1;
+ case SWI_Remove:
+ args->n = callback->unlink (callback, args->s);
+ return 1;
+ case SWI_Rename:
+ args->n = callback->rename (callback, args[0].s, args[1].s);
+ return 1;
+ case SWI_Open:
+ i = 0;
+
+#ifdef O_BINARY
+ if (args[1].n & 1)
+ i |= O_BINARY;
+#endif
+ if (args[1].n & 2)
+ i |= O_RDWR;
+
+ if (args[1].n & 4)
+ {
+ i |= O_CREAT;
+ }
+
+ if (args[1].n & 8)
+ i |= O_APPEND;
+
+ args->n = callback->open (callback, args->s, i);
+ return 1;
+
+ case SWI_Close:
+ args->n = callback->close (callback, args->n);
+ return 1;
+
+ case SWI_Write:
+ args->n = callback->write (callback, args[0].n, args[1].s, args[1].n);
+ return 1;
+ case SWI_Read:
+ {
+ char *copy = alloca (args[2].n);
+ int done = callback->read (callback, args[0].n, copy, args[2].n);
+ if (done > 0)
+ remote_rdp_xfer_inferior_memory (args[0].n, copy, done, 1, 0);
+ args->n -= done;
+ return 1;
+ }
+
+ case SWI_Seek:
+ args->n = callback->lseek (callback, args[0].n, args[1].n, 0) >= 0;
+ return 1;
+ case SWI_Flen:
+ {
+ long old = callback->lseek (callback, args->n, 1, 1);
+ args->n = callback->lseek (callback, args->n, 2, 0);
+ callback->lseek (callback, args->n, old, 0);
+ return 1;
+ }
+
+ case SWI_IsTTY:
+ args->n = callback->isatty (callback, args->n);
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+
+static void
+handle_swi ()
+{
+ argsin args[3];
+ char *buf;
+ int len;
+ int count = 0;
+
+ int swino = get_word ();
+ int type = get_byte ();
+ while (type != 0)
+ {
+ switch (type & 0x3)
+ {
+ case ABYTE:
+ args[count].n = get_byte ();
+ break;
+
+ case AWORD:
+ args[count].n = get_word ();
+ break;
+
+ case ASTRING:
+ /* If the word is under 32 bytes it will be sent otherwise
+ an address to it is passed. Also: Special case of 255 */
+
+ len = get_byte ();
+ if (len > 32)
+ {
+ if (len == 255)
+ {
+ len = get_word ();
+ }
+ buf = alloca (len);
+ remote_rdp_xfer_inferior_memory (get_word (),
+ buf,
+ len,
+ 0,
+ 0);
+ }
+ else
+ {
+ int i;
+ buf = alloca (len + 1);
+ for (i = 0; i < len; i++)
+ buf[i] = get_byte ();
+ buf[i] = 0;
+ }
+ args[count].n = len;
+ args[count].s = buf;
+ break;
+
+ default:
+ error ("Unimplented SWI argument");
+ }
+
+ type = type >> 2;
+ count++;
+ }
+
+ if (exec_swi (swino, args))
+ {
+ /* We have two options here reply with either a byte or a word
+ which is stored in args[0].n. There is no harm in replying with
+ a word all the time, so thats what I do! */
+ send_rdp ("bbw-", RDP_OSOpReply, RDP_OSOpWord, args[0].n);
+ }
+ else
+ {
+ send_rdp ("bb-", RDP_OSOpReply, RDP_OSOpNothing);
+ }
+}
+
+static void
+rdp_execute_finish ()
+{
+ int running = 1;
+
+ while (running)
+ {
+ int res;
+ res = SERIAL_READCHAR (io, 1);
+ while (res == SERIAL_TIMEOUT)
+ {
+ QUIT;
+ printf_filtered ("Waiting for target..\n");
+ res = SERIAL_READCHAR (io, 1);
+ }
+
+ switch (res)
+ {
+ case RDP_RES_SWI:
+ handle_swi ();
+ break;
+ case RDP_RES_VALUE:
+ send_rdp ("B", &ds.rdi_stopped_status);
+ running = 0;
+ break;
+ case RDP_RESET:
+ printf_filtered ("Target reset\n");
+ running = 0;
+ break;
+ default:
+ printf_filtered ("Ignoring %x\n", res);
+ break;
+ }
+ }
+}
+
+
+static void
+rdp_execute ()
+{
+ rdp_execute_start ();
+ rdp_execute_finish ();
+}
+
+static int
+remote_rdp_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int res;
+ if (ds.rdi_level > 0)
+ {
+ send_rdp ("bwb-SWB",
+ RDP_SET_BREAK,
+ addr,
+ RDP_SET_BREAK_TYPE_PC_EQUAL | RDP_SET_BREAK_TYPE_GET_HANDLE,
+ save,
+ &res);
+ }
+ else
+ {
+ send_rdp ("bwb-SB",
+ RDP_SET_BREAK,
+ addr,
+ RDP_SET_BREAK_TYPE_PC_EQUAL,
+ &res);
+ }
+ return res;
+}
+
+static int
+remote_rdp_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int res;
+ if (ds.rdi_level > 0)
+ {
+ send_rdp ("b-p-S-B",
+ RDP_CLEAR_BREAK,
+ save, 4,
+ &res);
+ }
+ else
+ {
+ send_rdp ("bw-S-B",
+ RDP_CLEAR_BREAK,
+ addr,
+ &res);
+ }
+ return res;
+}
+
+static void
+rdp_step ()
+{
+ if (ds.can_step && 0)
+ {
+ /* The pie board can't do steps so I can't test this, and
+ the other code will always work. */
+ int status;
+ send_rdp ("bbw-S-B",
+ RDP_STEP, 0, 1,
+ &status);
+ }
+ else
+ {
+ char handle[4];
+ CORE_ADDR pc = read_register (PC_REGNUM);
+ pc = arm_get_next_pc (pc);
+ remote_rdp_insert_breakpoint (pc, &handle);
+ rdp_execute ();
+ remote_rdp_remove_breakpoint (pc, &handle);
+ }
+}
+
+static void
+remote_rdp_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (!args)
+ error_no_arg ("serial port device name");
+
+ baud_rate = 9600;
+
+ target_preopen (from_tty);
+
+ io = SERIAL_OPEN (args);
+
+ if (!io)
+ perror_with_name (args);
+
+ SERIAL_RAW (io);
+
+ rdp_init (1, from_tty);
+
+
+ if (from_tty)
+ {
+ printf_unfiltered ("Remote RDP debugging using %s at %d baud\n", args, baud_rate);
+ }
+
+ rdp_info ();
+
+ push_target (&remote_rdp_ops);
+
+ callback->init (callback);
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc ();
+ set_current_frame (create_new_frame (read_fp (), stop_pc));
+ select_frame (get_current_frame (), 0);
+ print_stack_frame (selected_frame, -1, 1);
+}
+
+
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+remote_rdp_close (quitting)
+ int quitting;
+{
+ callback->shutdown (callback);
+ if (io)
+ SERIAL_CLOSE (io);
+ io = 0;
+}
+
+
+/* Resume execution of the target process. 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. */
+
+static void
+remote_rdp_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ if (step)
+ rdp_step ();
+ else
+ rdp_execute ();
+}
+
+/* Wait for inferior process to do something. Return pid of child,
+ or -1 in case of error; store status through argument pointer STATUS,
+ just as `wait' would. */
+
+static int
+remote_rdp_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ switch (ds.rdi_stopped_status)
+ {
+ default:
+ case RDP_RES_RESET:
+ case RDP_RES_SWI:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = read_register (0);
+ break;
+ case RDP_RES_AT_BREAKPOINT:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+#if 0
+ case rdp_signalled:
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = target_signal_from_host (sigrc);
+ break;
+#endif
+ }
+
+ return inferior_pid;
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+remote_rdp_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static int
+remote_rdp_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ /* I infer from D Taylor's code that there's a limit on the amount
+ we can transfer in one chunk.. */
+ int done = 0;
+ while (done < len)
+ {
+ int justdone;
+ int thisbite = len - done;
+ if (thisbite > RDP_MOUTHFULL)
+ thisbite = RDP_MOUTHFULL;
+
+ QUIT;
+
+ if (write)
+ {
+ justdone = rdp_write (memaddr + done, myaddr + done, thisbite);
+ }
+ else
+ {
+ justdone = rdp_read (memaddr + done, myaddr + done, thisbite);
+ }
+
+ done += justdone;
+
+ if (justdone != thisbite)
+ break;
+ }
+ return done;
+}
+
+
+
+struct yn
+{
+ const char *name;
+ int bit;
+};
+static struct yn stepinfo[] =
+{
+ {"Step more than one instruction", RDP_INFO_ABOUT_STEP_GT_1},
+ {"Step to jump", RDP_INFO_ABOUT_STEP_TO_JMP},
+ {"Step one instruction", RDP_INFO_ABOUT_STEP_1},
+ {0}
+};
+
+static struct yn breakinfo[] =
+{
+ {"comparison breakpoints supported", RDP_INFO_ABOUT_BREAK_COMP},
+ {"range breakpoints supported", RDP_INFO_ABOUT_BREAK_RANGE},
+ {"watchpoints for byte reads supported", RDP_INFO_ABOUT_BREAK_BYTE_READ},
+ {"watchpoints for half-word reads supported", RDP_INFO_ABOUT_BREAK_HALFWORD_READ},
+ {"watchpoints for word reads supported", RDP_INFO_ABOUT_BREAK_WORD_READ},
+ {"watchpoints for byte writes supported", RDP_INFO_ABOUT_BREAK_BYTE_WRITE},
+ {"watchpoints for half-word writes supported", RDP_INFO_ABOUT_BREAK_HALFWORD_WRITE},
+ {"watchpoints for word writes supported", RDP_INFO_ABOUT_BREAK_WORD_WRITE},
+ {"mask break/watch-points supported", RDP_INFO_ABOUT_BREAK_MASK},
+{"thread-specific breakpoints supported", RDP_INFO_ABOUT_BREAK_THREAD_BREAK},
+{"thread-specific watchpoints supported", RDP_INFO_ABOUT_BREAK_THREAD_WATCH},
+ {"conditional breakpoints supported", RDP_INFO_ABOUT_BREAK_COND},
+ {0}
+};
+
+
+static void
+dump_bits (t, info)
+ struct yn *t;
+ int info;
+{
+ while (t->name)
+ {
+ printf_unfiltered (" %-45s : %s\n", t->name, (info & t->bit) ? "Yes" : "No");
+ t++;
+ }
+}
+
+static void
+remote_rdp_files_info (target)
+ struct target_ops *target;
+{
+ printf_filtered ("Target capabilities:\n");
+ dump_bits (stepinfo, ds.step_info);
+ dump_bits (breakinfo, ds.break_info);
+ printf_unfiltered ("target level RDI %x\n", (ds.target_info >> 5) & 3);
+}
+
+
+/* Define the target subroutine names */
+
+struct target_ops remote_rdp_ops =
+{
+ "rdp", /* to_shortname */
+ /* to_longname */
+ "Remote Target using the RDProtocol",
+ /* to_doc */
+ "Use a remote ARM system which uses the ARM Remote Debugging Protocol",
+ remote_rdp_open, /* to_open */
+ remote_rdp_close, /* to_close */
+ NULL, /* to_attach */
+ NULL, /* to_detach */
+ remote_rdp_resume, /* to_resume */
+ remote_rdp_wait, /* to_wait */
+ remote_rdp_fetch_register, /* to_fetch_registers */
+ remote_rdp_store_register, /* to_store_registers */
+ remote_rdp_prepare_to_store, /* to_prepare_to_store */
+ remote_rdp_xfer_inferior_memory, /* to_xfer_memory */
+ remote_rdp_files_info, /* to_files_info */
+ remote_rdp_insert_breakpoint, /* to_insert_breakpoint */
+ remote_rdp_remove_breakpoint, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ remote_rdp_kill, /* to_kill */
+ generic_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ NULL, /* to_create_inferior */
+ generic_mourn_inferior, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC, /* to_magic */
+};
+
+void
+_initialize_remote_rdp ()
+{
+ add_target (&remote_rdp_ops);
+}
diff --git a/contrib/gdb/gdb/remote-sim.c b/contrib/gdb/gdb/remote-sim.c
new file mode 100644
index 0000000..d0f0f50
--- /dev/null
+++ b/contrib/gdb/gdb/remote-sim.c
@@ -0,0 +1,468 @@
+/* Generic remote debugging interface for simulators.
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+ Steve Chamberlain (sac@cygnus.com).
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include "gdb_string.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include "terminal.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "remote-sim.h"
+#include "remote-utils.h"
+#include "callback.h"
+
+/* Naming convention:
+
+ sim_* are the interface to the simulator (see remote-sim.h).
+ sim_callback_* are the stuff which the simulator can see inside GDB.
+ gdbsim_* are stuff which is internal to gdb. */
+
+/* Forward data declarations */
+extern struct target_ops gdbsim_ops;
+
+static int program_loaded = 0;
+
+static void
+dump_mem (buf, len)
+ char *buf;
+ int len;
+{
+ if (len <= 8)
+ {
+ if (len == 8 || len == 4)
+ {
+ long l[2];
+ memcpy (l, buf, len);
+ printf_filtered ("\t0x%x", l[0]);
+ printf_filtered (len == 8 ? " 0x%x\n" : "\n", l[1]);
+ }
+ else
+ {
+ int i;
+ printf_filtered ("\t");
+ for (i = 0; i < len; i++)
+ printf_filtered ("0x%x ", buf[i]);
+ printf_filtered ("\n");
+ }
+ }
+}
+
+static void
+gdbsim_fetch_register (regno)
+int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ gdbsim_fetch_register (regno);
+ }
+ else
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ sim_fetch_register (regno, buf);
+ supply_register (regno, buf);
+ if (sr_get_debug ())
+ {
+ printf_filtered ("gdbsim_fetch_register: %d", regno);
+ /* FIXME: We could print something more intelligible. */
+ dump_mem (buf, REGISTER_RAW_SIZE (regno));
+ }
+ }
+}
+
+
+static void
+gdbsim_store_register (regno)
+int regno;
+{
+ if (regno == -1)
+ {
+ for (regno = 0; regno < NUM_REGS; regno++)
+ gdbsim_store_register (regno);
+ }
+ else
+ {
+ /* FIXME: Until read_register() returns LONGEST, we have this. */
+ char tmp[MAX_REGISTER_RAW_SIZE];
+ read_register_gen (regno, tmp);
+ sim_store_register (regno, tmp);
+ if (sr_get_debug ())
+ {
+ printf_filtered ("gdbsim_store_register: %d", regno);
+ /* FIXME: We could print something more intelligible. */
+ dump_mem (tmp, REGISTER_RAW_SIZE (regno));
+ }
+ }
+}
+
+/* Kill the running program. This may involve closing any open files
+ and releasing other resources acquired by the simulated program. */
+
+static void
+gdbsim_kill ()
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_kill\n");
+
+ sim_kill (); /* close fd's, remove mappings */
+ inferior_pid = 0;
+}
+
+/* Load an executable file into the target process. This is expected to
+ not only bring new code into the target process, but also to update
+ GDB's symbol tables to match. */
+
+static void
+gdbsim_load (prog, fromtty)
+ char *prog;
+ int fromtty;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_load: prog \"%s\"\n", prog);
+
+ inferior_pid = 0;
+
+ /* This must be done before calling gr_load_image. */
+ program_loaded = 1;
+
+ if (sim_load (prog, fromtty) != 0)
+ generic_load (prog, fromtty);
+}
+
+
+/* Start an inferior process and set 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().
+ On VxWorks and various standalone systems, we ignore exec_file. */
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+
+static void
+gdbsim_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ int len;
+ char *arg_buf,**argv;
+ CORE_ADDR entry_pt;
+
+ if (! program_loaded)
+ error ("No program loaded.");
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_create_inferior: exec_file \"%s\", args \"%s\"\n",
+ exec_file, args);
+
+ if (exec_file == 0 || exec_bfd == 0)
+ error ("No exec file specified.");
+
+ entry_pt = (CORE_ADDR) bfd_get_start_address (exec_bfd);
+
+ gdbsim_kill (NULL, NULL);
+ remove_breakpoints ();
+ init_wait_for_inferior ();
+
+ len = 5 + strlen (exec_file) + 1 + strlen (args) + 1 + /*slop*/ 10;
+ arg_buf = (char *) alloca (len);
+ arg_buf[0] = '\0';
+ strcat (arg_buf, exec_file);
+ strcat (arg_buf, " ");
+ strcat (arg_buf, args);
+ argv = buildargv (arg_buf);
+ make_cleanup (freeargv, (char *) argv);
+ sim_create_inferior (entry_pt, argv, env);
+
+ inferior_pid = 42;
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+ proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* The open routine takes the rest of the parameters from the command,
+ and (if successful) pushes a new target onto the stack.
+ Targets should supply this routine, if only to provide an error message. */
+/* Called when selecting the simulator. EG: (gdb) target sim name. */
+
+static void
+gdbsim_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_open: args \"%s\"\n", args ? args : "(null)");
+
+ sim_set_callbacks (&default_callback);
+ default_callback.init (&default_callback);
+
+ sim_open (args);
+
+ push_target (&gdbsim_ops);
+ target_fetch_registers (-1);
+ printf_filtered ("Connected to the simulator.\n");
+}
+
+/* Does whatever cleanup is required for a target that we are no longer
+ going to be calling. Argument says whether we are quitting gdb and
+ should not get hung in case of errors, or whether we want a clean
+ termination even if it takes a while. This routine is automatically
+ always called just before a routine is popped off the target stack.
+ Closing file descriptors and freeing memory are typical things it should
+ do. */
+/* Close out all files and local state before this target loses control. */
+
+static void
+gdbsim_close (quitting)
+ int quitting;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_close: quitting %d\n", quitting);
+
+ program_loaded = 0;
+
+ sim_close (quitting);
+}
+
+/* Takes a program previously attached to and detaches it.
+ The program may resume execution (some targets do, some don't) and will
+ no longer stop on signals, etc. We better not have left any breakpoints
+ in the program or it'll die when it hits one. ARGS is arguments
+ typed by the user (e.g. a signal to send the process). FROM_TTY
+ says whether to be verbose or not. */
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else with your gdb. */
+
+static void
+gdbsim_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_detach: args \"%s\"\n", args);
+
+ pop_target (); /* calls gdbsim_close to do the real work */
+ if (from_tty)
+ printf_filtered ("Ending simulator %s debugging\n", target_shortname);
+}
+
+/* Resume execution of the target process. 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. */
+
+static void
+gdbsim_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_resume: step %d, signal %d\n", step, siggnal);
+
+ sim_resume (step, target_signal_to_host (siggnal));
+}
+
+/* Wait for inferior process to do something. Return pid of child,
+ or -1 in case of error; store status through argument pointer STATUS,
+ just as `wait' would. */
+
+static int
+gdbsim_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int sigrc;
+ enum sim_stop reason;
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_wait\n");
+
+ sim_stop_reason (&reason, &sigrc);
+ switch (reason)
+ {
+ case sim_exited:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = sigrc;
+ break;
+ case sim_stopped:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = target_signal_from_host (sigrc);
+ break;
+ case sim_signalled:
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ /* The signal in sigrc is a host signal. That probably
+ should be fixed. */
+ status->value.sig = target_signal_from_host (sigrc);
+ break;
+ }
+
+ return inferior_pid;
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+gdbsim_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static int
+gdbsim_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (! program_loaded)
+ error ("No program loaded.");
+
+ if (sr_get_debug ())
+ {
+ printf_filtered ("gdbsim_xfer_inferior_memory: myaddr 0x%x, memaddr 0x%x, len %d, write %d\n",
+ myaddr, memaddr, len, write);
+ if (sr_get_debug () && write)
+ dump_mem(myaddr, len);
+ }
+
+ if (write)
+ {
+ len = sim_write (memaddr, myaddr, len);
+ }
+ else
+ {
+ len = sim_read (memaddr, myaddr, len);
+ if (sr_get_debug () && len > 0)
+ dump_mem(myaddr, len);
+ }
+ return len;
+}
+
+static void
+gdbsim_files_info (target)
+ struct target_ops *target;
+{
+ char *file = "nothing";
+
+ if (exec_bfd)
+ file = bfd_get_filename (exec_bfd);
+
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_files_info: file \"%s\"\n", file);
+
+ if (exec_bfd)
+ {
+ printf_filtered ("\tAttached to %s running program %s\n",
+ target_shortname, file);
+ sim_info (0);
+ }
+}
+
+/* Clear the simulator's notion of what the break points are. */
+
+static void
+gdbsim_mourn_inferior ()
+{
+ if (sr_get_debug ())
+ printf_filtered ("gdbsim_mourn_inferior:\n");
+
+ remove_breakpoints ();
+ generic_mourn_inferior ();
+}
+
+/* Put a command string, in args, out to MONITOR. Output from MONITOR
+ is placed on the users terminal until the prompt is seen. FIXME: We
+ read the characters ourseleves here cause of a nasty echo. */
+
+static void
+simulator_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ sim_do_command (args);
+}
+
+/* Define the target subroutine names */
+
+struct target_ops gdbsim_ops = {
+ "sim", /* to_shortname */
+ "simulator", /* to_longname */
+ "Use the compiled-in simulator.", /* to_doc */
+ gdbsim_open, /* to_open */
+ gdbsim_close, /* to_close */
+ NULL, /* to_attach */
+ gdbsim_detach, /* to_detach */
+ gdbsim_resume, /* to_resume */
+ gdbsim_wait, /* to_wait */
+ gdbsim_fetch_register, /* to_fetch_registers */
+ gdbsim_store_register, /* to_store_registers */
+ gdbsim_prepare_to_store, /* to_prepare_to_store */
+ gdbsim_xfer_inferior_memory, /* to_xfer_memory */
+ gdbsim_files_info, /* to_files_info */
+ memory_insert_breakpoint, /* to_insert_breakpoint */
+ memory_remove_breakpoint, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ gdbsim_kill, /* to_kill */
+ gdbsim_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ gdbsim_create_inferior, /* to_create_inferior */
+ gdbsim_mourn_inferior, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC, /* to_magic */
+};
+
+void
+_initialize_remote_sim ()
+{
+ add_target (&gdbsim_ops);
+
+ add_com ("sim <command>", class_obscure, simulator_command,
+ "Send a command to the simulator.");
+}
diff --git a/contrib/gdb/gdb/remote-sim.h b/contrib/gdb/gdb/remote-sim.h
new file mode 100644
index 0000000..8c106a2
--- /dev/null
+++ b/contrib/gdb/gdb/remote-sim.h
@@ -0,0 +1,142 @@
+/* This file defines the interface between the simulator and gdb.
+ Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (REMOTE_SIM_H)
+#define REMOTE_SIM_H 1
+
+#include "callback.h"
+/* This file is used when building stand-alone simulators, so isolate this
+ file from gdb. */
+
+/* Pick up CORE_ADDR_TYPE if defined (from gdb), otherwise use same value as
+ gdb does (unsigned int - from defs.h). */
+
+#ifndef CORE_ADDR_TYPE
+typedef unsigned int SIM_ADDR;
+#else
+typedef CORE_ADDR_TYPE SIM_ADDR;
+#endif
+
+/* Callbacks.
+ The simulator may use the following callbacks (gdb routines) which the
+ standalone program must provide.
+
+ void printf_filtered (char *msg, ...);
+ void error /-* noreturn *-/ (char *msg, ...);
+ void *xmalloc (long size);
+ int sim_callback_write_stdout (char *, int len);
+
+ The new way of doing I/O is to use the pointer provided by GDB
+ via the sim_set_callbacks call, look in callbacks.c to see what
+ can be done.
+*/
+
+/* Main simulator entry points ...
+
+ All functions that can get an error must call the gdb routine `error',
+ they can only return upon success. */
+
+/* Initialize the simulator. This function is called when the simulator
+ is selected from the command line. ARGS is passed from the command line
+ and can be used to select whatever run time options the simulator provides.
+ ARGS is the raw character string and must be parsed by the simulator,
+ which is trivial to do with the buildargv function in libiberty.
+ It is ok to do nothing. */
+
+void sim_open PARAMS ((char *args));
+
+/* Terminate usage of the simulator. This may involve freeing target memory
+ and closing any open files and mmap'd areas. You cannot assume sim_kill
+ has already been called.
+ QUITTING is non-zero if we cannot hang on errors. */
+
+void sim_close PARAMS ((int quitting));
+
+/* Load program PROG into the simulator.
+ Return non-zero if you wish the caller to handle it
+ (it is done this way because most simulators can use gr_load_image,
+ but defining it as a callback seems awkward). */
+
+int sim_load PARAMS ((char *prog, int from_tty));
+
+/* Prepare to run the simulated program.
+ START_ADDRESS is, yes, you guessed it, the start address of the program.
+ ARGV and ENV are NULL terminated lists of pointers.
+ Gdb will set the start address via sim_store_register as well, but
+ standalone versions of existing simulators are not set up to cleanly call
+ sim_store_register, so the START_ADDRESS argument is there as a
+ workaround. */
+
+void sim_create_inferior PARAMS ((SIM_ADDR start_address,
+ char **argv, char **env));
+
+/* Kill the running program.
+ This may involve closing any open files and deleting any mmap'd areas. */
+
+void sim_kill PARAMS ((void));
+
+/* Read LENGTH bytes of the simulated program's memory and store in BUF.
+ Result is number of bytes read, or zero if error. */
+
+int sim_read PARAMS ((SIM_ADDR mem, unsigned char *buf, int length));
+
+/* Store LENGTH bytes from BUF in the simulated program's memory.
+ Result is number of bytes write, or zero if error. */
+
+int sim_write PARAMS ((SIM_ADDR mem, unsigned char *buf, int length));
+
+/* Fetch register REGNO and store the raw value in BUF. */
+
+void sim_fetch_register PARAMS ((int regno, unsigned char *buf));
+
+/* Store register REGNO from BUF (in raw format). */
+
+void sim_store_register PARAMS ((int regno, unsigned char *buf));
+
+/* Print some interesting information about the simulator.
+ VERBOSE is non-zero for the wordy version. */
+
+void sim_info PARAMS ((int verbose));
+
+/* Fetch why the program stopped.
+ SIGRC will contain either the argument to exit() or the signal number. */
+
+enum sim_stop { sim_exited, sim_stopped, sim_signalled };
+
+void sim_stop_reason PARAMS ((enum sim_stop *reason, int *sigrc));
+
+/* Run (or resume) the program. */
+
+void sim_resume PARAMS ((int step, int siggnal));
+
+/* Passthru for other commands that the simulator might support. */
+
+void sim_do_command PARAMS ((char *cmd));
+
+
+/* Callbacks for the simulator to use. */
+
+int sim_callback_write_stdout PARAMS ((char *, int));
+
+/* Provide simulator with a standard host_callback_struct. */
+
+void sim_set_callbacks PARAMS ((struct host_callback_struct *));
+
+
+#endif /* !defined (REMOTE_SIM_H) */
diff --git a/contrib/gdb/gdb/remote-st.c b/contrib/gdb/gdb/remote-st.c
new file mode 100644
index 0000000..117501d
--- /dev/null
+++ b/contrib/gdb/gdb/remote-st.c
@@ -0,0 +1,847 @@
+/* Remote debugging interface for Tandem ST2000 phone switch, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Jim Kingdon for Cygnus.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file was derived from remote-eb.c, which did a similar job, but for
+ an AMD-29K running EBMON. That file was in turn derived from remote.c
+ as mentioned in the following comment (left in for comic relief):
+
+ "This is like remote.c but is for an esoteric situation--
+ having an a29k board in a PC hooked up to a unix machine with
+ a serial line, and running ctty com1 on the PC, through which
+ the unix machine can run ebmon. Not to mention that the PC
+ has PC/NFS, so it can access the same executables that gdb can,
+ over the net in real time."
+
+ In reality, this module talks to a debug monitor called 'STDEBUG', which
+ runs in a phone switch. We communicate with STDEBUG via either a direct
+ serial line, or a TCP (or possibly TELNET) stream to a terminal multiplexor,
+ which in turn talks to the phone switch. */
+
+#include "defs.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "wait.h"
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/types.h>
+#include "serial.h"
+
+extern struct target_ops st2000_ops; /* Forward declaration */
+
+static void st2000_close();
+static void st2000_fetch_register();
+static void st2000_store_register();
+
+#define LOG_FILE "st2000.log"
+#if defined (LOG_FILE)
+FILE *log_file;
+#endif
+
+static int timeout = 24;
+
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ st2000_open knows that we don't have a file open when the program
+ starts. */
+
+static serial_t st2000_desc;
+
+/* Send data to stdebug. Works just like printf. */
+
+static void
+#ifdef ANSI_PROTOTYPES
+printf_stdebug(char *pattern, ...)
+#else
+printf_stdebug(va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char buf[200];
+
+#ifdef ANSI_PROTOTYPES
+ va_start(args, pattern);
+#else
+ char *pattern;
+ va_start(args);
+ pattern = va_arg(args, char *);
+#endif
+
+ vsprintf(buf, pattern, args);
+ va_end(args);
+
+ if (SERIAL_WRITE(st2000_desc, buf, strlen(buf)))
+ fprintf(stderr, "SERIAL_WRITE failed: %s\n", safe_strerror(errno));
+}
+
+/* Read a character from the remote system, doing all the fancy timeout
+ stuff. */
+
+static int
+readchar(timeout)
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR(st2000_desc, timeout);
+
+#ifdef LOG_FILE
+ putc(c & 0x7f, log_file);
+#endif
+
+ if (c >= 0)
+ return c & 0x7f;
+
+ if (c == SERIAL_TIMEOUT)
+ {
+ if (timeout == 0)
+ return c; /* Polls shouldn't generate timeout errors */
+
+ error("Timeout reading from remote system.");
+ }
+
+ perror_with_name("remote-st2000");
+}
+
+/* Scan input from the remote system, until STRING is found. If DISCARD is
+ non-zero, then discard non-matching input, else print it out.
+ Let the user break out immediately. */
+static void
+expect(string, discard)
+ char *string;
+ int discard;
+{
+ char *p = string;
+ int c;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ c = readchar(timeout);
+ if (c == *p++)
+ {
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ {
+ if (!discard)
+ {
+ fwrite(string, 1, (p - 1) - string, stdout);
+ putchar((char)c);
+ fflush(stdout);
+ }
+ p = string;
+ }
+ }
+}
+
+/* Keep discarding input until we see the STDEBUG prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an expect_prompt(). Exception: st2000_resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a st2000_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+static void
+expect_prompt(discard)
+ int discard;
+{
+#if defined (LOG_FILE)
+ /* This is a convenient place to do this. The idea is to do it often
+ enough that we never lose much data if we terminate abnormally. */
+ fflush(log_file);
+#endif
+ expect ("dbug> ", discard);
+}
+
+/* Get a hex digit from the remote system & return its value.
+ If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+static int
+get_hex_digit(ignore_space)
+ int ignore_space;
+{
+ int ch;
+ while (1)
+ {
+ ch = readchar(timeout);
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch == ' ' && ignore_space)
+ ;
+ else
+ {
+ expect_prompt(1);
+ error("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from stdebug and put it in *BYT. Accept any number
+ leading spaces. */
+static void
+get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = get_hex_digit (1) << 4;
+ val |= get_hex_digit (0);
+ *byt = val;
+}
+
+/* Get N 32-bit words from remote, each preceded by a space,
+ and put them in registers starting at REGNO. */
+static void
+get_hex_regs (n, regno)
+ int n;
+ int regno;
+{
+ long val;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + get_hex_digit (j == 0);
+ supply_register (regno++, (char *) &val);
+ }
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+static void
+st2000_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error("Can't pass arguments to remote STDEBUG process");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+
+/* The "process" (board) is already stopped awaiting our commands, and
+ the program is already downloaded. We just set its PC and go. */
+
+ clear_proceed_status ();
+
+ /* Tell wait_for_inferior that we've started a new process. */
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ /* Let 'er rip... */
+ proceed ((CORE_ADDR)entry_pt, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static int baudrate = 9600;
+static char dev_name[100];
+
+static void
+st2000_open(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int n;
+ char junk[100];
+
+ target_preopen(from_tty);
+
+ n = sscanf(args, " %s %d %s", dev_name, &baudrate, junk);
+
+ if (n != 2)
+ error("Bad arguments. Usage: target st2000 <device> <speed>\n\
+or target st2000 <host> <port>\n");
+
+ st2000_close(0);
+
+ st2000_desc = SERIAL_OPEN(dev_name);
+
+ if (!st2000_desc)
+ perror_with_name(dev_name);
+
+ SERIAL_SETBAUDRATE(st2000_desc, baudrate);
+
+ SERIAL_RAW(st2000_desc);
+
+ push_target(&st2000_ops);
+
+#if defined (LOG_FILE)
+ log_file = fopen (LOG_FILE, "w");
+ if (log_file == NULL)
+ perror_with_name (LOG_FILE);
+#endif
+
+ /* Hello? Are you there? */
+ printf_stdebug("\003"); /* ^C wakes up dbug */
+
+ expect_prompt(1);
+
+ if (from_tty)
+ printf("Remote %s connected to %s\n", target_shortname,
+ dev_name);
+}
+
+/* Close out all files and local state before this target loses control. */
+
+static void
+st2000_close (quitting)
+ int quitting;
+{
+ SERIAL_CLOSE(st2000_desc);
+
+#if defined (LOG_FILE)
+ if (log_file) {
+ if (ferror(log_file))
+ fprintf(stderr, "Error writing log file.\n");
+ if (fclose(log_file) != 0)
+ fprintf(stderr, "Error closing log file.\n");
+ }
+#endif
+}
+
+/* Terminate the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+st2000_detach (from_tty)
+ int from_tty;
+{
+ pop_target(); /* calls st2000_close to do the real work */
+ if (from_tty)
+ printf ("Ending remote %s debugging\n", target_shortname);
+}
+
+/* Tell the remote machine to resume. */
+
+static void
+st2000_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ if (step)
+ {
+ printf_stdebug ("ST\r");
+ /* Wait for the echo. */
+ expect ("ST\r", 1);
+ }
+ else
+ {
+ printf_stdebug ("GO\r");
+ /* Swallow the echo. */
+ expect ("GO\r", 1);
+ }
+}
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static int
+st2000_wait (status)
+ struct target_waitstatus *status;
+{
+ int old_timeout = timeout;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ timeout = 0; /* Don't time out -- user program is running. */
+
+ expect_prompt(0); /* Wait for prompt, outputting extraneous text */
+
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+
+ timeout = old_timeout;
+
+ return 0;
+}
+
+/* Return the name of register number REGNO in the form input and output by
+ STDEBUG. Currently, REGISTER_NAMES just happens to contain exactly what
+ STDEBUG wants. Lets take advantage of that just as long as possible! */
+
+static char *
+get_reg_name (regno)
+ int regno;
+{
+ static char buf[50];
+ const char *p;
+ char *b;
+
+ b = buf;
+
+ for (p = reg_names[regno]; *p; p++)
+ *b++ = toupper(*p);
+ *b = '\000';
+
+ return buf;
+}
+
+/* Read the remote registers into the block REGS. */
+
+static void
+st2000_fetch_registers ()
+{
+ int regno;
+
+ /* Yeah yeah, I know this is horribly inefficient. But it isn't done
+ very often... I'll clean it up later. */
+
+ for (regno = 0; regno <= PC_REGNUM; regno++)
+ st2000_fetch_register(regno);
+}
+
+/* Fetch register REGNO, or all registers if REGNO is -1.
+ Returns errno value. */
+static void
+st2000_fetch_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ st2000_fetch_registers ();
+ else
+ {
+ char *name = get_reg_name (regno);
+ printf_stdebug ("DR %s\r", name);
+ expect (name, 1);
+ expect (" : ", 1);
+ get_hex_regs (1, regno);
+ expect_prompt (1);
+ }
+ return;
+}
+
+/* Store the remote registers from the contents of the block REGS. */
+
+static void
+st2000_store_registers ()
+{
+ int regno;
+
+ for (regno = 0; regno <= PC_REGNUM; regno++)
+ st2000_store_register(regno);
+
+ registers_changed ();
+}
+
+/* Store register REGNO, or all if REGNO == 0.
+ Return errno value. */
+static void
+st2000_store_register (regno)
+ int regno;
+{
+ if (regno == -1)
+ st2000_store_registers ();
+ else
+ {
+ printf_stdebug ("PR %s %x\r", get_reg_name (regno),
+ read_register (regno));
+
+ expect_prompt (1);
+ }
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+st2000_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+static void
+st2000_files_info ()
+{
+ printf ("\tAttached to %s at %d baud.\n",
+ dev_name, baudrate);
+}
+
+/* Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns length moved. */
+static int
+st2000_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ unsigned char *myaddr;
+ int len;
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]);
+ expect_prompt (1);
+ }
+ return len;
+}
+
+/* Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns length moved. */
+static int
+st2000_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int i;
+
+ /* Number of bytes read so far. */
+ int count;
+
+ /* Starting address of this pass. */
+ unsigned long startaddr;
+
+ /* Number of bytes to read in this pass. */
+ int len_this_pass;
+
+ /* Note that this code works correctly if startaddr is just less
+ than UINT_MAX (well, really CORE_ADDR_MAX if there was such a
+ thing). That is, something like
+ st2000_read_bytes (CORE_ADDR_MAX - 4, foo, 4)
+ works--it never adds len to memaddr and gets 0. */
+ /* However, something like
+ st2000_read_bytes (CORE_ADDR_MAX - 3, foo, 4)
+ doesn't need to work. Detect it and give up if there's an attempt
+ to do that. */
+ if (((memaddr - 1) + len) < memaddr) {
+ errno = EIO;
+ return 0;
+ }
+
+ startaddr = memaddr;
+ count = 0;
+ while (count < len)
+ {
+ len_this_pass = 16;
+ if ((startaddr % 16) != 0)
+ len_this_pass -= startaddr % 16;
+ if (len_this_pass > (len - count))
+ len_this_pass = (len - count);
+
+ printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass);
+ expect (": ", 1);
+
+ for (i = 0; i < len_this_pass; i++)
+ get_hex_byte (&myaddr[count++]);
+
+ expect_prompt (1);
+
+ startaddr += len_this_pass;
+ }
+ return len;
+}
+
+/* FIXME-someday! Merge these two. */
+static int
+st2000_xfer_inferior_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ if (write)
+ return st2000_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return st2000_read_inferior_memory (memaddr, myaddr, len);
+}
+
+static void
+st2000_kill (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ return; /* Ignore attempts to kill target system */
+}
+
+/* Clean up when a program exits.
+
+ The program actually lives on in the remote processor's RAM, and may be
+ run again without a download. Don't leave it full of breakpoint
+ instructions. */
+
+static void
+st2000_mourn_inferior ()
+{
+ remove_breakpoints ();
+ unpush_target (&st2000_ops);
+ generic_mourn_inferior (); /* Do all the proper things now */
+}
+
+#define MAX_STDEBUG_BREAKPOINTS 16
+
+extern int memory_breakpoint_size;
+static CORE_ADDR breakaddr[MAX_STDEBUG_BREAKPOINTS] = {0};
+
+static int
+st2000_insert_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ for (i = 0; i <= MAX_STDEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == 0)
+ {
+ breakaddr[i] = addr;
+
+ st2000_read_inferior_memory(addr, shadow, memory_breakpoint_size);
+ printf_stdebug("BR %x H\r", addr);
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Too many breakpoints (> 16) for STDBUG\n");
+ return 1;
+}
+
+static int
+st2000_remove_breakpoint (addr, shadow)
+ CORE_ADDR addr;
+ char *shadow;
+{
+ int i;
+
+ for (i = 0; i < MAX_STDEBUG_BREAKPOINTS; i++)
+ if (breakaddr[i] == addr)
+ {
+ breakaddr[i] = 0;
+
+ printf_stdebug("CB %d\r", i);
+ expect_prompt(1);
+ return 0;
+ }
+
+ fprintf(stderr, "Can't find breakpoint associated with 0x%x\n", addr);
+ return 1;
+}
+
+
+/* Put a command string, in args, out to STDBUG. Output from STDBUG is placed
+ on the users terminal until the prompt is seen. */
+
+static void
+st2000_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ if (!st2000_desc)
+ error("st2000 target not open.");
+
+ if (!args)
+ error("Missing command.");
+
+ printf_stdebug("%s\r", args);
+ expect_prompt(0);
+}
+
+/* Connect the user directly to STDBUG. This command acts just like the
+ 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
+
+/*static struct ttystate ttystate;*/
+
+static void
+cleanup_tty()
+{
+ printf("\r\n[Exiting connect mode]\r\n");
+/* SERIAL_RESTORE(0, &ttystate);*/
+}
+
+#if 0
+/* This all should now be in serial.c */
+
+static void
+connect_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ fd_set readfds;
+ int numfds;
+ int c;
+ char cur_esc = 0;
+
+ dont_repeat();
+
+ if (st2000_desc < 0)
+ error("st2000 target not open.");
+
+ if (args)
+ fprintf("This command takes no args. They have been ignored.\n");
+
+ printf("[Entering connect mode. Use ~. or ~^D to escape]\n");
+
+ serial_raw(0, &ttystate);
+
+ make_cleanup(cleanup_tty, 0);
+
+ FD_ZERO(&readfds);
+
+ while (1)
+ {
+ do
+ {
+ FD_SET(0, &readfds);
+ FD_SET(st2000_desc, &readfds);
+ numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
+ }
+ while (numfds == 0);
+
+ if (numfds < 0)
+ perror_with_name("select");
+
+ if (FD_ISSET(0, &readfds))
+ { /* tty input, send to stdebug */
+ c = getchar();
+ if (c < 0)
+ perror_with_name("connect");
+
+ printf_stdebug("%c", c);
+ switch (cur_esc)
+ {
+ case 0:
+ if (c == '\r')
+ cur_esc = c;
+ break;
+ case '\r':
+ if (c == '~')
+ cur_esc = c;
+ else
+ cur_esc = 0;
+ break;
+ case '~':
+ if (c == '.' || c == '\004')
+ return;
+ else
+ cur_esc = 0;
+ }
+ }
+
+ if (FD_ISSET(st2000_desc, &readfds))
+ {
+ while (1)
+ {
+ c = readchar(0);
+ if (c < 0)
+ break;
+ putchar(c);
+ }
+ fflush(stdout);
+ }
+ }
+}
+#endif /* 0 */
+
+/* Define the target subroutine names */
+
+struct target_ops st2000_ops = {
+ "st2000",
+ "Remote serial Tandem ST2000 target",
+ "Use a remote computer running STDEBUG connected by a serial line,\n\
+or a network connection.\n\
+Arguments are the name of the device for the serial line,\n\
+the speed to connect at in bits per second.",
+ st2000_open,
+ st2000_close,
+ 0,
+ st2000_detach,
+ st2000_resume,
+ st2000_wait,
+ st2000_fetch_register,
+ st2000_store_register,
+ st2000_prepare_to_store,
+ st2000_xfer_inferior_memory,
+ st2000_files_info,
+ st2000_insert_breakpoint,
+ st2000_remove_breakpoint, /* Breakpoints */
+ 0,
+ 0,
+ 0,
+ 0,
+ 0, /* Terminal handling */
+ st2000_kill,
+ 0, /* load */
+ 0, /* lookup_symbol */
+ st2000_create_inferior,
+ st2000_mourn_inferior,
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_stop */
+ process_stratum,
+ 0, /* next */
+ 1,
+ 1,
+ 1,
+ 1,
+ 1, /* all mem, mem, stack, regs, exec */
+ 0,
+ 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_st2000 ()
+{
+ add_target (&st2000_ops);
+ add_com ("st2000 <command>", class_obscure, st2000_command,
+ "Send a command to the STDBUG monitor.");
+ add_com ("connect", class_obscure, connect_command,
+ "Connect the terminal directly up to the STDBUG command monitor.\n\
+Use <CR>~. or <CR>~^D to break out.");
+}
diff --git a/contrib/gdb/gdb/remote-udi.c b/contrib/gdb/gdb/remote-udi.c
new file mode 100644
index 0000000..9512023
--- /dev/null
+++ b/contrib/gdb/gdb/remote-udi.c
@@ -0,0 +1,1689 @@
+/* Remote debugging interface for AMD 29k interfaced via UDI, for GDB.
+ Copyright 1990, 1992, 1995 Free Software Foundation, Inc.
+ Written by Daniel Mann. Contributed by AMD.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This is like remote.c but uses the Universal Debug Interface (UDI) to
+ talk to the target hardware (or simulator). UDI is a TCP/IP based
+ protocol; for hardware that doesn't run TCP, an interface adapter
+ daemon talks UDI on one side, and talks to the hardware (typically
+ over a serial port) on the other side.
+
+ - Originally written by Daniel Mann at AMD for MiniMON and gdb 3.91.6.
+ - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
+ file to gdb 3.95. I was unable to get this working on sun3os4
+ with termio, only with sgtty.
+ - Daniel Mann at AMD took the 3.95 adaptions above and replaced
+ MiniMON interface with UDI-p interface. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "value.h"
+#include <ctype.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include "gdb_string.h"
+#include "terminal.h"
+#include "target.h"
+#include "29k-share/udi/udiproc.h"
+#include "gdbcmd.h"
+#include "bfd.h"
+#include "gdbcore.h" /* For download function */
+
+/* access the register store directly, without going through
+ the normal handler functions. This avoids an extra data copy. */
+
+extern int stop_soon_quietly; /* for wait_for_inferior */
+extern struct value *call_function_by_hand();
+static void udi_resume PARAMS ((int pid, int step, enum target_signal sig));
+static void udi_fetch_registers PARAMS ((int regno));
+static void udi_load PARAMS ((char *args, int from_tty));
+static void fetch_register PARAMS ((int regno));
+static void udi_store_registers PARAMS ((int regno));
+static int store_register PARAMS ((int regno));
+static int regnum_to_srnum PARAMS ((int regno));
+static void udi_close PARAMS ((int quitting));
+static CPUSpace udi_memory_space PARAMS ((CORE_ADDR addr));
+static int udi_write_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len));
+static int udi_read_inferior_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len));
+static void download PARAMS ((char *load_arg_string, int from_tty));
+char CoffFileName[100] = "";
+
+#define FREEZE_MODE (read_register(CPS_REGNUM) & 0x400)
+#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
+
+static int timeout = 5;
+extern struct target_ops udi_ops; /* Forward declaration */
+
+/* Special register enumeration.
+*/
+
+/******************************************************************* UDI DATA*/
+#define MAXDATA 2*1024 /* max UDI[read/write] byte size */
+/* Descriptor for I/O to remote machine. Initialize it to -1 so that
+ udi_open knows that we don't have a file open when the program
+ starts. */
+
+UDISessionId udi_session_id = -1;
+static char *udi_config_id;
+
+CPUOffset IMemStart = 0;
+CPUSizeT IMemSize = 0;
+CPUOffset DMemStart = 0;
+CPUSizeT DMemSize = 0;
+CPUOffset RMemStart = 0;
+CPUSizeT RMemSize = 0;
+UDIUInt32 CPUPRL;
+UDIUInt32 CoProcPRL;
+
+UDIMemoryRange address_ranges[2]; /* Text and data */
+UDIResource entry = {0, 0}; /* Entry point */
+CPUSizeT stack_sizes[2]; /* Regular and memory stacks */
+
+#define SBUF_MAX 1024 /* maximum size of string handling buffer */
+char sbuf[SBUF_MAX];
+
+typedef struct bkpt_entry_str
+{
+ UDIResource Addr;
+ UDIUInt32 PassCount;
+ UDIBreakType Type;
+ unsigned int BreakId;
+} bkpt_entry_t;
+#define BKPT_TABLE_SIZE 40
+static bkpt_entry_t bkpt_table[BKPT_TABLE_SIZE];
+extern char dfe_errmsg[]; /* error string */
+
+/* malloc'd name of the program on the remote system. */
+static char *prog_name = NULL;
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+
+static void
+udi_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ char *args1;
+
+ if (execfile)
+ {
+ if (prog_name != NULL)
+ free (prog_name);
+ prog_name = savestring (execfile, strlen (execfile));
+ }
+ else if (entry.Offset)
+ execfile = "";
+ else
+ error ("No image loaded into target.");
+
+ if (udi_session_id < 0)
+ {
+ /* If the TIP is not open, open it. */
+ if (UDIConnect (udi_config_id, &udi_session_id))
+ error("UDIConnect() failed: %s\n", dfe_errmsg);
+ /* We will need to download the program. */
+ entry.Offset = 0;
+ }
+
+ inferior_pid = 40000;
+
+ if (!entry.Offset)
+ download(execfile, 0);
+
+ args1 = alloca (strlen(execfile) + strlen(args) + 2);
+
+ if (execfile[0] == '\0')
+
+ /* It is empty. We need to quote it somehow, or else the target
+ will think there is no argument being passed here. According
+ to the UDI spec it is quoted "according to TIP OS rules" which
+ I guess means quoting it like the Unix shell should work
+ (sounds pretty bogus to me...). In fact it doesn't work (with
+ isstip anyway), but passing in two quotes as the argument seems
+ like a reasonable enough behavior anyway (I guess). */
+
+ strcpy (args1, "''");
+ else
+ strcpy (args1, execfile);
+ strcat (args1, " ");
+ strcat (args1, args);
+
+ UDIInitializeProcess (address_ranges, /* ProcessMemory[] */
+ (UDIInt)2, /* NumberOfRanges */
+ entry, /* EntryPoint */
+ stack_sizes, /* *StackSizes */
+ (UDIInt)2, /* NumberOfStacks */
+ args1); /* ArgString */
+
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+static void
+udi_mourn()
+{
+#if 0
+ /* Requiring "target udi" each time you run is a major pain. I suspect
+ this was just blindy copied from remote.c, in which "target" and
+ "run" are combined. Having a udi target without an inferior seems
+ to work between "target udi" and "run", so why not now? */
+ pop_target (); /* Pop back to no-child state */
+#endif
+ /* But if we're going to want to run it again, we better remove the
+ breakpoints... */
+ remove_breakpoints ();
+ generic_mourn_inferior ();
+}
+
+/******************************************************************** UDI_OPEN
+** Open a connection to remote TIP.
+ NAME is the socket domain used for communication with the TIP,
+ then a space and the socket name or TIP-host name.
+ '<udi_udi_config_id>' for example.
+ */
+
+/* XXX - need cleanups for udiconnect for various failures!!! */
+
+static void
+udi_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ unsigned int prl;
+ char *p;
+ int cnt;
+ UDIMemoryRange KnownMemory[10];
+ UDIUInt32 ChipVersions[10];
+ UDIInt NumberOfRanges = 10;
+ UDIInt NumberOfChips = 10;
+ UDIPId PId;
+ UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
+
+ target_preopen(from_tty);
+
+ entry.Offset = 0;
+
+ for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
+ bkpt_table[cnt].Type = 0;
+
+ if (udi_config_id)
+ free (udi_config_id);
+
+ if (!name)
+ error("Usage: target udi config_id, where config_id appears in udi_soc file");
+
+ udi_config_id = strdup (strtok (name, " \t"));
+
+ if (UDIConnect (udi_config_id, &udi_session_id))
+ /* FIXME: Should set udi_session_id to -1 here. */
+ error("UDIConnect() failed: %s\n", dfe_errmsg);
+
+ push_target (&udi_ops);
+
+ /*
+ ** Initialize target configuration structure (global)
+ */
+ if (UDIGetTargetConfig (KnownMemory, &NumberOfRanges,
+ ChipVersions, &NumberOfChips))
+ error ("UDIGetTargetConfig() failed");
+ if (NumberOfChips > 2)
+ fprintf_unfiltered(gdb_stderr,"Target has more than one processor\n");
+ for (cnt=0; cnt < NumberOfRanges; cnt++)
+ {
+ switch(KnownMemory[cnt].Space)
+ {
+ default:
+ fprintf_unfiltered(gdb_stderr, "UDIGetTargetConfig() unknown memory space\n");
+ break;
+ case UDI29KCP_S:
+ break;
+ case UDI29KIROMSpace:
+ RMemStart = KnownMemory[cnt].Offset;
+ RMemSize = KnownMemory[cnt].Size;
+ break;
+ case UDI29KIRAMSpace:
+ IMemStart = KnownMemory[cnt].Offset;
+ IMemSize = KnownMemory[cnt].Size;
+ break;
+ case UDI29KDRAMSpace:
+ DMemStart = KnownMemory[cnt].Offset;
+ DMemSize = KnownMemory[cnt].Size;
+ break;
+ }
+ }
+
+ a29k_get_processor_type ();
+
+ if (UDICreateProcess (&PId))
+ fprintf_unfiltered(gdb_stderr, "UDICreateProcess() failed\n");
+
+ /* Print out some stuff, letting the user now what's going on */
+ if (UDICapabilities (&TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
+ &TIPIPCId, sbuf))
+ error ("UDICapabilities() failed");
+ if (from_tty)
+ {
+ printf_filtered ("Connected via UDI socket,\n\
+ DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
+ (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
+ (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
+ (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
+ sbuf);
+ }
+}
+
+/******************************************************************* UDI_CLOSE
+ Close the open connection to the TIP process.
+ Use this when you want to detach and do something else
+ with your gdb. */
+static void
+udi_close (quitting) /*FIXME: how is quitting used */
+ int quitting;
+{
+ if (udi_session_id < 0)
+ return;
+
+ /* We should never get here if there isn't something valid in
+ udi_session_id. */
+
+ if (UDIDisconnect (udi_session_id, UDITerminateSession))
+ {
+ if (quitting)
+ warning ("UDIDisconnect() failed in udi_close");
+ else
+ error ("UDIDisconnect() failed in udi_close");
+ }
+
+ /* Do not try to close udi_session_id again, later in the program. */
+ udi_session_id = -1;
+ inferior_pid = 0;
+
+ printf_filtered (" Ending remote debugging\n");
+}
+
+/**************************************************************** UDI_ATACH */
+/* Attach to a program that is already loaded and running
+ * Upon exiting the process's execution is stopped.
+ */
+static void
+udi_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ UDIResource From;
+ UDIInt32 PC_adds;
+ UDICount Count = 1;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+
+ if (args == NULL)
+ error_no_arg ("program to attach");
+
+ if (udi_session_id < 0)
+ error ("UDI connection not opened yet, use the 'target udi' command.\n");
+
+ if (from_tty)
+ printf_unfiltered ("Attaching to remote program %s...\n", prog_name);
+
+ UDIStop();
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = 11;
+ if (err = UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
+ error ("UDIRead failed in udi_attach");
+ printf_unfiltered ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
+}
+/************************************************************* UDI_DETACH */
+/* Terminate the open connection to the TIP process.
+ Use this when you want to detach and do something else
+ with your gdb. Leave remote process running (with no breakpoints set). */
+static void
+udi_detach (args,from_tty)
+ char *args;
+ int from_tty;
+{
+
+ remove_breakpoints(); /* Just in case there were any left in */
+
+ if (UDIDisconnect (udi_session_id, UDIContinueSession))
+ error ("UDIDisconnect() failed in udi_detach");
+
+ /* Don't try to UDIDisconnect it again in udi_close, which is called from
+ pop_target. */
+ udi_session_id = -1;
+ inferior_pid = 0;
+
+ pop_target();
+
+ if (from_tty)
+ printf_unfiltered ("Detaching from TIP\n");
+}
+
+
+/****************************************************************** UDI_RESUME
+** Tell the remote machine to resume. */
+
+static void
+udi_resume (pid, step, sig)
+ int pid, step;
+ enum target_signal sig;
+{
+ UDIError tip_error;
+ UDIUInt32 Steps = 1;
+ UDIStepType StepType = UDIStepNatural;
+ UDIRange Range;
+
+ if (step) /* step 1 instruction */
+ {
+ tip_error = UDIStep (Steps, StepType, Range);
+ if (!tip_error)
+ return;
+
+ fprintf_unfiltered (gdb_stderr, "UDIStep() error = %d\n", tip_error);
+ error ("failed in udi_resume");
+ }
+
+ if (UDIExecute())
+ error ("UDIExecute() failed in udi_resume");
+}
+
+/******************************************************************** UDI_WAIT
+** Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would. */
+
+static int
+udi_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ UDIInt32 MaxTime;
+ UDIPId PId;
+ UDIInt32 StopReason;
+ UDISizeT CountDone;
+ int old_timeout = timeout;
+ int old_immediate_quit = immediate_quit;
+ int i;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+/* wait for message to arrive. It should be:
+ If the target stops executing, udi_wait() should return.
+*/
+ timeout = 0; /* Wait indefinetly for a message */
+ immediate_quit = 1; /* Helps ability to QUIT */
+
+ while(1)
+ {
+ i = 0;
+ MaxTime = UDIWaitForever;
+ UDIWait(MaxTime, &PId, &StopReason);
+ QUIT; /* Let user quit if they want */
+
+ switch (StopReason & UDIGrossState)
+ {
+ case UDIStdoutReady:
+ if (UDIGetStdout (sbuf, (UDISizeT)SBUF_MAX, &CountDone))
+ /* This is said to happen if the program tries to output
+ a whole bunch of output (more than SBUF_MAX, I would
+ guess). It doesn't seem to happen with the simulator. */
+ warning ("UDIGetStdout() failed in udi_wait");
+ fwrite (sbuf, 1, CountDone, gdb_stdout);
+ gdb_flush(gdb_stdout);
+ continue;
+
+ case UDIStderrReady:
+ UDIGetStderr (sbuf, (UDISizeT)SBUF_MAX, &CountDone);
+ fwrite (sbuf, 1, CountDone, gdb_stderr);
+ gdb_flush(gdb_stderr);
+ continue;
+
+ case UDIStdinNeeded:
+ {
+ int ch;
+ i = 0;
+ do
+ {
+ ch = getchar ();
+ if (ch == EOF)
+ break;
+ sbuf[i++] = ch;
+ } while (i < SBUF_MAX && ch != '\n');
+ UDIPutStdin (sbuf, (UDISizeT)i, &CountDone);
+ continue;
+ }
+
+ case UDIRunning:
+ /* In spite of the fact that we told UDIWait to wait forever, it will
+ return spuriously sometimes. */
+ case UDIStdinModeX:
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ switch (StopReason & UDIGrossState)
+ {
+ case UDITrapped:
+ printf_unfiltered("Am290*0 received vector number %d\n", StopReason >> 24);
+
+ switch ((StopReason >> 8 ) & 0xff)
+ {
+ case 0: /* Illegal opcode */
+ printf_unfiltered(" (break point)\n");
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 1: /* Unaligned Access */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_BUS;
+ break;
+ case 3:
+ case 4:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_FPE;
+ break;
+ case 5: /* Protection Violation */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* Why not SEGV? What is a Protection Violation? */
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 6:
+ case 7:
+ case 8: /* User Instruction Mapping Miss */
+ case 9: /* User Data Mapping Miss */
+ case 10: /* Supervisor Instruction Mapping Miss */
+ case 11: /* Supervisor Data Mapping Miss */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_SEGV;
+ break;
+ case 12:
+ case 13:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 14: /* Timer */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_ALRM;
+ break;
+ case 15: /* Trace */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case 16: /* INTR0 */
+ case 17: /* INTR1 */
+ case 18: /* INTR2 */
+ case 19: /* INTR3/Internal */
+ case 20: /* TRAP0 */
+ case 21: /* TRAP1 */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_INT;
+ break;
+ case 22: /* Floating-Point Exception */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ /* Why not FPE? */
+ status->value.sig = TARGET_SIGNAL_ILL;
+ break;
+ case 77: /* assert 77 */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ default:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+ break;
+ case UDINotExecuting:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TERM;
+ break;
+ case UDIStopped:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TSTP;
+ break;
+ case UDIWarned:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_URG;
+ break;
+ case UDIStepped:
+ case UDIBreak:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case UDIWaiting:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_STOP;
+ break;
+ case UDIHalted:
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_KILL;
+ break;
+ case UDIExited:
+ default:
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+ }
+
+ timeout = old_timeout; /* Restore original timeout value */
+ immediate_quit = old_immediate_quit;
+ return inferior_pid;
+}
+
+#if 0
+/* Handy for debugging */
+udi_pc()
+{
+ UDIResource From;
+ UDIUInt32 *To;
+ UDICount Count;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+ int pc[2];
+ unsigned long myregs[256];
+ int i;
+
+ From.Space = UDI29KPC;
+ From.Offset = 0;
+ To = (UDIUInt32 *)pc;
+ Count = 2;
+
+ err = UDIRead(From, To, Count, Size, &CountDone, HostEndian);
+
+ printf_unfiltered ("err = %d, CountDone = %d, pc[0] = 0x%x, pc[1] = 0x%x\n",
+ err, CountDone, pc[0], pc[1]);
+
+ udi_fetch_registers(-1);
+
+ printf_unfiltered("other pc1 = 0x%x, pc0 = 0x%x\n", *(int *)&registers[4 * PC_REGNUM],
+ *(int *)&registers[4 * NPC_REGNUM]);
+
+ /* Now, read all the registers globally */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 0;
+ err = UDIRead(From, myregs, 256, 4, &CountDone, HostEndian);
+
+ printf ("err = %d, CountDone = %d\n", err, CountDone);
+
+ printf("\n");
+
+ for (i = 0; i < 256; i += 2)
+ printf("%d:\t%#10x\t%11d\t%#10x\t%11d\n", i, myregs[i], myregs[i],
+ myregs[i+1], myregs[i+1]);
+ printf("\n");
+
+ return pc[0];
+}
+#endif
+
+/********************************************************** UDI_FETCH_REGISTERS
+ * Read a remote register 'regno'.
+ * If regno==-1 then read all the registers.
+ */
+static void
+udi_fetch_registers (regno)
+int regno;
+{
+ UDIResource From;
+ UDIUInt32 *To;
+ UDICount Count;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+ int i;
+
+ if (regno >= 0) {
+ fetch_register(regno);
+ return;
+ }
+
+/* Gr1/rsp */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 1;
+ To = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
+ Count = 1;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ register_valid[GR1_REGNUM] = 1;
+
+#if defined(GR64_REGNUM) /* Read gr64-127 */
+
+/* Global Registers gr64-gr95 */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 64;
+ To = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
+ Count = 32;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = GR64_REGNUM; i < GR64_REGNUM + 32; i++)
+ register_valid[i] = 1;
+
+#endif /* GR64_REGNUM */
+
+/* Global Registers gr96-gr127 */
+
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 96;
+ To = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
+ Count = 32;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = GR96_REGNUM; i < GR96_REGNUM + 32; i++)
+ register_valid[i] = 1;
+
+/* Local Registers */
+
+ From.Space = UDI29KLocalRegs;
+ From.Offset = 0;
+ To = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
+ Count = 128;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = LR0_REGNUM; i < LR0_REGNUM + 128; i++)
+ register_valid[i] = 1;
+
+/* Protected Special Registers */
+
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = 0;
+ To = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
+ Count = 15;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = SR_REGNUM(0); i < SR_REGNUM(0) + 15; i++)
+ register_valid[i] = 1;
+
+ if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
+ fetch_register(NPC_REGNUM);
+ fetch_register(PC_REGNUM);
+ fetch_register(PC2_REGNUM);
+
+/* Unprotected Special Registers sr128-sr135 */
+
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = 128;
+ To = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
+ Count = 135-128 + 1;
+ if (err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ for (i = SR_REGNUM(128); i < SR_REGNUM(128) + 135-128+1; i++)
+ register_valid[i] = 1;
+ }
+
+ if (remote_debug)
+ {
+ printf_unfiltered("Fetching all registers\n");
+ printf_unfiltered("Fetching PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n",
+ read_register(NPC_REGNUM), read_register(PC_REGNUM),
+ read_register(PC2_REGNUM));
+ }
+
+ /* There doesn't seem to be any way to get these. */
+ {
+ int val = -1;
+ supply_register (FPE_REGNUM, (char *) &val);
+ supply_register (INTE_REGNUM, (char *) &val);
+ supply_register (FPS_REGNUM, (char *) &val);
+ supply_register (EXO_REGNUM, (char *) &val);
+ }
+}
+
+
+/********************************************************* UDI_STORE_REGISTERS
+** Store register regno into the target.
+ * If regno==-1 then store all the registers.
+ */
+
+static void
+udi_store_registers (regno)
+int regno;
+{
+ UDIUInt32 *From;
+ UDIResource To;
+ UDICount Count;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+
+ if (regno >= 0)
+ {
+ store_register(regno);
+ return;
+ }
+
+ if (remote_debug)
+ {
+ printf_unfiltered("Storing all registers\n");
+ printf_unfiltered("PC0 = 0x%x, PC1 = 0x%x, PC2 = 0x%x\n", read_register(NPC_REGNUM),
+ read_register(PC_REGNUM), read_register(PC2_REGNUM));
+ }
+
+/* Gr1/rsp */
+
+ From = (UDIUInt32 *)&registers[4 * GR1_REGNUM];
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 1;
+ Count = 1;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+#if defined(GR64_REGNUM)
+
+/* Global registers gr64-gr95 */
+
+ From = (UDIUInt32 *)&registers[4 * GR64_REGNUM];
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 64;
+ Count = 32;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+#endif /* GR64_REGNUM */
+
+/* Global registers gr96-gr127 */
+
+ From = (UDIUInt32 *)&registers[4 * GR96_REGNUM];
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 96;
+ Count = 32;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* Local Registers */
+
+ From = (UDIUInt32 *)&registers[4 * LR0_REGNUM];
+ To.Space = UDI29KLocalRegs;
+ To.Offset = 0;
+ Count = 128;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+
+/* Protected Special Registers */ /* VAB through TMR */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(0)];
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = 0;
+ Count = 10;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* PC0, PC1, PC2 possibly as shadow registers */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(10)];
+ To.Space = UDI29KSpecialRegs;
+ Count = 3;
+ if (USE_SHADOW_PC)
+ To.Offset = 20; /* SPC0 */
+ else
+ To.Offset = 10; /* PC0 */
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* PC1 via UDI29KPC */
+
+ From = (UDIUInt32 *)&registers[4 * PC_REGNUM];
+ To.Space = UDI29KPC;
+ To.Offset = 0; /* PC1 */
+ Count = 1;
+ if (UDIWrite (From, To, Count, Size, &CountDone, HostEndian))
+ error ("UDIWrite() failed in udi_store_regisetrs");
+
+ /* LRU and MMU */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(13)];
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = 13;
+ Count = 2;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+/* Unprotected Special Registers */
+
+ From = (UDIUInt32 *)&registers[4 * SR_REGNUM(128)];
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = 128;
+ Count = 135-128 +1;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ error("UDIWrite() failed in udi_store_regisetrs");
+
+ registers_changed ();
+}
+
+/****************************************************** UDI_PREPARE_TO_STORE */
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+static void
+udi_prepare_to_store ()
+{
+ /* Do nothing, since we can store individual regs */
+}
+
+/********************************************************** TRANSLATE_ADDR */
+static CORE_ADDR
+translate_addr(addr)
+CORE_ADDR addr;
+{
+#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
+ /* Check for a virtual address in the kernel */
+ /* Assume physical address of ublock is in paddr_u register */
+ /* FIXME: doesn't work for user virtual addresses */
+ if (addr >= UVADDR) {
+ /* PADDR_U register holds the physical address of the ublock */
+ CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
+ return(i + addr - (CORE_ADDR)UVADDR);
+ } else {
+ return(addr);
+ }
+#else
+ return(addr);
+#endif
+}
+/************************************************* UDI_XFER_INFERIOR_MEMORY */
+/* FIXME! Merge these two. */
+static int
+udi_xfer_inferior_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+
+ memaddr = translate_addr(memaddr);
+
+ if (write)
+ return udi_write_inferior_memory (memaddr, myaddr, len);
+ else
+ return udi_read_inferior_memory (memaddr, myaddr, len);
+}
+
+/********************************************************** UDI_FILES_INFO */
+static void
+udi_files_info ()
+{
+ printf_unfiltered ("\tAttached to UDI socket to %s", udi_config_id);
+ if (prog_name != NULL)
+ printf_unfiltered ("and running program %s", prog_name);
+ printf_unfiltered (".\n");
+}
+
+/**************************************************** UDI_INSERT_BREAKPOINT */
+static int
+udi_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int cnt;
+ UDIError err;
+
+ for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
+ if (bkpt_table[cnt].Type == 0) /* Find first free slot */
+ break;
+
+ if(cnt >= BKPT_TABLE_SIZE)
+ error("Too many breakpoints set");
+
+ bkpt_table[cnt].Addr.Offset = addr;
+ bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
+ bkpt_table[cnt].PassCount = 1;
+ bkpt_table[cnt].Type = UDIBreakFlagExecute;
+
+ err = UDISetBreakpoint(bkpt_table[cnt].Addr,
+ bkpt_table[cnt].PassCount,
+ bkpt_table[cnt].Type,
+ &bkpt_table[cnt].BreakId);
+
+ if (err == 0) return 0; /* Success */
+
+ bkpt_table[cnt].Type = 0;
+ error("UDISetBreakpoint returned error code %d\n", err);
+}
+
+/**************************************************** UDI_REMOVE_BREAKPOINT */
+static int
+udi_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int cnt;
+ UDIError err;
+
+ for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
+ if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
+ break;
+
+ if(cnt >= BKPT_TABLE_SIZE)
+ error("Can't find breakpoint in table");
+
+ bkpt_table[cnt].Type = 0;
+
+ err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
+ if (err == 0) return 0; /* Success */
+
+ error("UDIClearBreakpoint returned error code %d\n", err);
+}
+
+static void
+udi_kill(arg,from_tty)
+ char *arg;
+ int from_tty;
+{
+
+#if 0
+/*
+UDIStop does not really work as advertised. It causes the TIP to close it's
+connection, which usually results in GDB dying with a SIGPIPE. For now, we
+just invoke udi_close, which seems to get things right.
+*/
+ UDIStop();
+
+ udi_session_id = -1;
+ inferior_pid = 0;
+
+ if (from_tty)
+ printf_unfiltered("Target has been stopped.");
+#endif /* 0 */
+#if 0
+ udi_close(0);
+ pop_target();
+#endif /* 0 */
+
+ /* Keep the target around, e.g. so "run" can do the right thing when
+ we are already debugging something. */
+
+ if (UDIDisconnect (udi_session_id, UDITerminateSession))
+ {
+ warning ("UDIDisconnect() failed");
+ }
+
+ /* Do not try to close udi_session_id again, later in the program. */
+ udi_session_id = -1;
+ inferior_pid = 0;
+}
+
+/*
+ Load a program into the target. Args are: `program {options}'. The options
+ are used to control loading of the program, and are NOT passed onto the
+ loaded code as arguments. (You need to use the `run' command to do that.)
+
+ The options are:
+ -ms %d Set mem stack size to %d
+ -rs %d Set regular stack size to %d
+ -i send init info (default)
+ -noi don't send init info
+ -[tT] Load Text section
+ -[dD] Load Data section
+ -[bB] Load BSS section
+ -[lL] Load Lit section
+ */
+
+static void
+download(load_arg_string, from_tty)
+ char *load_arg_string;
+ int from_tty;
+{
+#define DEFAULT_MEM_STACK_SIZE 0x6000
+#define DEFAULT_REG_STACK_SIZE 0x2000
+
+ char *token;
+ char *filename;
+ asection *section;
+ bfd *pbfd;
+ UDIError err;
+ int load_text = 1, load_data = 1, load_bss = 1, load_lit = 1;
+
+ address_ranges[0].Space = UDI29KIRAMSpace;
+ address_ranges[0].Offset = 0xffffffff;
+ address_ranges[0].Size = 0;
+
+ address_ranges[1].Space = UDI29KDRAMSpace;
+ address_ranges[1].Offset = 0xffffffff;
+ address_ranges[1].Size = 0;
+
+ stack_sizes[0] = DEFAULT_REG_STACK_SIZE;
+ stack_sizes[1] = DEFAULT_MEM_STACK_SIZE;
+
+ dont_repeat ();
+
+ filename = strtok(load_arg_string, " \t");
+ if (!filename)
+ error ("Must specify at least a file name with the load command");
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ while (token = strtok (NULL, " \t"))
+ {
+ if (token[0] == '-')
+ {
+ token++;
+
+ if (STREQ (token, "ms"))
+ stack_sizes[1] = atol (strtok (NULL, " \t"));
+ else if (STREQ (token, "rs"))
+ stack_sizes[0] = atol (strtok (NULL, " \t"));
+ else
+ {
+ load_text = load_data = load_bss = load_lit = 0;
+
+ while (*token)
+ {
+ switch (*token++)
+ {
+ case 't':
+ case 'T':
+ load_text = 1;
+ break;
+ case 'd':
+ case 'D':
+ load_data = 1;
+ break;
+ case 'b':
+ case 'B':
+ load_bss = 1;
+ break;
+ case 'l':
+ case 'L':
+ load_lit = 1;
+ break;
+ default:
+ error ("Unknown UDI load option -%s", token-1);
+ }
+ }
+ }
+ }
+ }
+
+ pbfd = bfd_openr (filename, gnutarget);
+
+ if (!pbfd)
+ /* FIXME: should be using bfd_errmsg, not assuming it was
+ bfd_error_system_call. */
+ perror_with_name (filename);
+
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ make_cleanup (bfd_close, pbfd);
+
+ QUIT;
+ immediate_quit++;
+
+ if (!bfd_check_format (pbfd, bfd_object))
+ error ("It doesn't seem to be an object file");
+
+ for (section = pbfd->sections; section; section = section->next)
+ {
+ if (bfd_get_section_flags (pbfd, section) & SEC_ALLOC)
+ {
+ UDIResource To;
+ UDICount Count;
+ unsigned long section_size, section_end;
+ const char *section_name;
+
+ section_name = bfd_get_section_name (pbfd, section);
+ if (STREQ (section_name, ".text") && !load_text)
+ continue;
+ else if (STREQ (section_name, ".data") && !load_data)
+ continue;
+ else if (STREQ (section_name, ".bss") && !load_bss)
+ continue;
+ else if (STREQ (section_name, ".lit") && !load_lit)
+ continue;
+
+ To.Offset = bfd_get_section_vma (pbfd, section);
+ section_size = bfd_section_size (pbfd, section);
+ section_end = To.Offset + section_size;
+
+ if (section_size == 0)
+ /* This is needed at least in the BSS case, where the code
+ below starts writing before it even checks the size. */
+ continue;
+
+ printf_unfiltered("[Loading section %s at %x (%d bytes)]\n",
+ section_name,
+ To.Offset,
+ section_size);
+
+ if (bfd_get_section_flags (pbfd, section) & SEC_CODE)
+ {
+ To.Space = UDI29KIRAMSpace;
+
+ address_ranges[0].Offset = min (address_ranges[0].Offset,
+ To.Offset);
+ address_ranges[0].Size = max (address_ranges[0].Size,
+ section_end
+ - address_ranges[0].Offset);
+ }
+ else
+ {
+ To.Space = UDI29KDRAMSpace;
+
+ address_ranges[1].Offset = min (address_ranges[1].Offset,
+ To.Offset);
+ address_ranges[1].Size = max (address_ranges[1].Size,
+ section_end
+ - address_ranges[1].Offset);
+ }
+
+ if (bfd_get_section_flags (pbfd, section) & SEC_LOAD) /* Text, data or lit */
+ {
+ file_ptr fptr;
+
+ fptr = 0;
+
+ while (section_size > 0)
+ {
+ char buffer[1024];
+
+ Count = min (section_size, 1024);
+
+ bfd_get_section_contents (pbfd, section, buffer, fptr,
+ Count);
+
+ err = UDIWrite ((UDIHostMemPtr)buffer, /* From */
+ To, /* To */
+ Count, /* Count */
+ (UDISizeT)1, /* Size */
+ &Count, /* CountDone */
+ (UDIBool)0); /* HostEndian */
+ if (err)
+ error ("UDIWrite failed, error = %d", err);
+
+ To.Offset += Count;
+ fptr += Count;
+ section_size -= Count;
+ }
+ }
+ else /* BSS */
+ {
+ UDIResource From;
+ unsigned long zero = 0;
+
+ /* Write a zero byte at the vma */
+ /* FIXME: Broken for sections of 1-3 bytes (we test for
+ zero above). */
+ err = UDIWrite ((UDIHostMemPtr)&zero, /* From */
+ To, /* To */
+ (UDICount)1, /* Count */
+ (UDISizeT)4, /* Size */
+ &Count, /* CountDone */
+ (UDIBool)0); /* HostEndian */
+ if (err)
+ error ("UDIWrite failed, error = %d", err);
+
+ From = To;
+ To.Offset+=4;
+
+ /* Now, duplicate it for the length of the BSS */
+ err = UDICopy (From, /* From */
+ To, /* To */
+ (UDICount)(section_size/4 - 1), /* Count */
+ (UDISizeT)4, /* Size */
+ &Count, /* CountDone */
+ (UDIBool)1); /* Direction */
+ if (err)
+ {
+ char message[100];
+ int xerr;
+
+ xerr = UDIGetErrorMsg(err, 100, message, &Count);
+ if (!xerr)
+ fprintf_unfiltered (gdb_stderr, "Error is %s\n", message);
+ else
+ fprintf_unfiltered (gdb_stderr, "xerr is %d\n", xerr);
+ error ("UDICopy failed, error = %d", err);
+ }
+ }
+
+ }
+ }
+
+ entry.Space = UDI29KIRAMSpace;
+ entry.Offset = bfd_get_start_address (pbfd);
+
+ immediate_quit--;
+}
+
+/* Function to download an image into the remote target. */
+
+static void
+udi_load (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ download (args, from_tty);
+
+ /* As a convenience, pick up any symbol info that is in the program
+ being loaded. Note that we assume that the program is the``mainline'';
+ if this is not always true, then this code will need to be augmented. */
+ symbol_file_add (strtok (args, " \t"), from_tty, 0, 1, 0, 0);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+/*************************************************** UDI_WRITE_INFERIOR_MEMORY
+** Copy LEN bytes of data from debugger memory at MYADDR
+ to inferior's memory at MEMADDR. Returns number of bytes written. */
+static int
+udi_write_inferior_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int nwritten = 0;
+ UDIUInt32 *From;
+ UDIResource To;
+ UDICount Count;
+ UDISizeT Size = 1;
+ UDICount CountDone = 0;
+ UDIBool HostEndian = 0;
+
+ To.Space = udi_memory_space(memaddr);
+ From = (UDIUInt32*)myaddr;
+
+ while (nwritten < len)
+ { Count = len - nwritten;
+ if (Count > MAXDATA) Count = MAXDATA;
+ To.Offset = memaddr + nwritten;
+ if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
+ { error("UDIWrite() failed in udi_write_inferior_memory");
+ break;
+ }
+ else
+ { nwritten += CountDone;
+ From += CountDone;
+ }
+ }
+ return(nwritten);
+}
+
+/**************************************************** UDI_READ_INFERIOR_MEMORY
+** Read LEN bytes from inferior memory at MEMADDR. Put the result
+ at debugger address MYADDR. Returns number of bytes read. */
+static int
+udi_read_inferior_memory(memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ int nread = 0;
+ UDIResource From;
+ UDIUInt32 *To;
+ UDICount Count;
+ UDISizeT Size = 1;
+ UDICount CountDone = 0;
+ UDIBool HostEndian = 0;
+ UDIError err;
+
+ From.Space = udi_memory_space(memaddr);
+ To = (UDIUInt32*)myaddr;
+
+ while (nread < len)
+ { Count = len - nread;
+ if (Count > MAXDATA) Count = MAXDATA;
+ From.Offset = memaddr + nread;
+ if(err = UDIRead(From, To, Count, Size, &CountDone, HostEndian))
+ { error("UDIRead() failed in udi_read_inferior_memory");
+ break;
+ }
+ else
+ { nread += CountDone;
+ To += CountDone;
+ }
+ }
+ return(nread);
+}
+
+/********************************************************************* WARNING
+*/
+udi_warning(num)
+int num;
+{
+ error ("ERROR while loading program into remote TIP: $d\n", num);
+}
+
+
+/*****************************************************************************/
+/* Fetch a single register indicatated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static void
+fetch_register (regno)
+ int regno;
+{
+ UDIResource From;
+ UDIUInt32 To;
+ UDICount Count = 1;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+ UDIError err;
+ int result;
+
+ if (regno == GR1_REGNUM)
+ {
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = 1;
+ }
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ {
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = (regno - GR96_REGNUM) + 96;;
+ }
+
+#if defined(GR64_REGNUM)
+
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ {
+ From.Space = UDI29KGlobalRegs;
+ From.Offset = (regno - GR64_REGNUM) + 64;
+ }
+
+#endif /* GR64_REGNUM */
+
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ {
+ From.Space = UDI29KLocalRegs;
+ From.Offset = (regno - LR0_REGNUM);
+ }
+ else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
+ {
+ int val = -1;
+ /*supply_register(160 + (regno - FPE_REGNUM),(char *) &val);*/
+ supply_register(regno, (char *) &val);
+ return; /* Pretend Success */
+ }
+ else
+ {
+ From.Space = UDI29KSpecialRegs;
+ From.Offset = regnum_to_srnum(regno);
+ }
+
+ if (err = UDIRead(From, &To, Count, Size, &CountDone, HostEndian))
+ error("UDIRead() failed in udi_fetch_registers");
+
+ supply_register(regno, (char *) &To);
+
+ if (remote_debug)
+ printf_unfiltered("Fetching register %s = 0x%x\n", reg_names[regno], To);
+}
+/*****************************************************************************/
+/* Store a single register indicated by 'regno'.
+ * Returns 0/-1 on success/failure.
+ */
+static int
+store_register (regno)
+ int regno;
+{
+ int result;
+ UDIUInt32 From;
+ UDIResource To;
+ UDICount Count = 1;
+ UDISizeT Size = 4;
+ UDICount CountDone;
+ UDIBool HostEndian = 0;
+
+ From = read_register (regno); /* get data value */
+
+ if (remote_debug)
+ printf_unfiltered("Storing register %s = 0x%x\n", reg_names[regno], From);
+
+ if (regno == GR1_REGNUM)
+ {
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = 1;
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ /* Setting GR1 changes the numbers of all the locals, so invalidate the
+ * register cache. Do this *after* calling read_register, because we want
+ * read_register to return the value that write_register has just stuffed
+ * into the registers array, not the value of the register fetched from
+ * the inferior.
+ */
+ registers_changed ();
+ }
+#if defined(GR64_REGNUM)
+ else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
+ {
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = (regno - GR64_REGNUM) + 64;
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+#endif /* GR64_REGNUM */
+ else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
+ {
+ To.Space = UDI29KGlobalRegs;
+ To.Offset = (regno - GR96_REGNUM) + 96;
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+ else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
+ {
+ To.Space = UDI29KLocalRegs;
+ To.Offset = (regno - LR0_REGNUM);
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+ else if (regno >= FPE_REGNUM && regno <= EXO_REGNUM)
+ return 0; /* Pretend Success */
+ else if (regno == PC_REGNUM)
+ {
+ /* PC1 via UDI29KPC */
+
+ To.Space = UDI29KPC;
+ To.Offset = 0; /* PC1 */
+ result = UDIWrite (&From, To, Count, Size, &CountDone, HostEndian);
+
+ /* Writing to this loc actually changes the values of pc0 & pc1 */
+
+ register_valid[PC_REGNUM] = 0; /* pc1 */
+ register_valid[NPC_REGNUM] = 0; /* pc0 */
+ }
+ else /* An unprotected or protected special register */
+ {
+ To.Space = UDI29KSpecialRegs;
+ To.Offset = regnum_to_srnum(regno);
+ result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
+ }
+
+ if (result != 0)
+ error("UDIWrite() failed in store_registers");
+
+ return 0;
+}
+/********************************************************** REGNUM_TO_SRNUM */
+/*
+ * Convert a gdb special register number to a 29000 special register number.
+ */
+static int
+regnum_to_srnum(regno)
+int regno;
+{
+ switch(regno) {
+ case VAB_REGNUM: return(0);
+ case OPS_REGNUM: return(1);
+ case CPS_REGNUM: return(2);
+ case CFG_REGNUM: return(3);
+ case CHA_REGNUM: return(4);
+ case CHD_REGNUM: return(5);
+ case CHC_REGNUM: return(6);
+ case RBP_REGNUM: return(7);
+ case TMC_REGNUM: return(8);
+ case TMR_REGNUM: return(9);
+ case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
+ case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
+ case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
+ case MMU_REGNUM: return(13);
+ case LRU_REGNUM: return(14);
+ case IPC_REGNUM: return(128);
+ case IPA_REGNUM: return(129);
+ case IPB_REGNUM: return(130);
+ case Q_REGNUM: return(131);
+ case ALU_REGNUM: return(132);
+ case BP_REGNUM: return(133);
+ case FC_REGNUM: return(134);
+ case CR_REGNUM: return(135);
+ case FPE_REGNUM: return(160);
+ case INTE_REGNUM: return(161);
+ case FPS_REGNUM: return(162);
+ case EXO_REGNUM:return(164);
+ default:
+ return(255); /* Failure ? */
+ }
+}
+/****************************************************************************/
+/*
+ * Determine the Target memory space qualifier based on the addr.
+ * FIXME: Can't distinguis I_ROM/D_ROM.
+ * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
+ */
+static CPUSpace
+udi_memory_space(addr)
+CORE_ADDR addr;
+{
+ UDIUInt32 tstart = IMemStart;
+ UDIUInt32 tend = tstart + IMemSize;
+ UDIUInt32 dstart = DMemStart;
+ UDIUInt32 dend = tstart + DMemSize;
+ UDIUInt32 rstart = RMemStart;
+ UDIUInt32 rend = tstart + RMemSize;
+
+ if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
+ return UDI29KIRAMSpace;
+ } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
+ return UDI29KDRAMSpace;
+ } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
+ /* FIXME: how do we determine between D_ROM and I_ROM */
+ return UDI29KIROMSpace;
+ } else /* FIXME: what do me do now? */
+ return UDI29KDRAMSpace; /* Hmmm! */
+}
+/*********************************************************************** STUBS
+*/
+
+void convert16() {;}
+void convert32() {;}
+GDB_FILE * EchoFile = 0; /* used for debugging */
+int QuietMode = 0; /* used for debugging */
+
+#ifdef NO_HIF_SUPPORT
+service_HIF(msg)
+ union msg_t *msg;
+{
+ return(0); /* Emulate a failure */
+}
+#endif
+
+/* Target_ops vector. Not static because there does not seem to be
+ any portable way to do a forward declaration of a static variable.
+ The RS/6000 doesn't like "extern" followed by "static"; SunOS
+ /bin/cc doesn't like "static" twice. */
+
+struct target_ops udi_ops = {
+ "udi",
+ "Remote UDI connected TIP",
+ "Remote debug an AMD 29k using UDI socket connection to TIP process.\n\
+Arguments are\n\
+`configuration-id AF_INET hostname port-number'\n\
+ To connect via the network, where hostname and port-number specify the\n\
+ host and port where you can connect via UDI.\n\
+ configuration-id is unused.\n\
+\n\
+`configuration-id AF_UNIX socket-name tip-program'\n\
+ To connect using a local connection to the \"tip.exe\" program which is\n\
+ supplied by AMD. If socket-name specifies an AF_UNIX socket then the\n\
+ tip program must already be started; connect to it using that socket.\n\
+ If not, start up tip-program, which should be the name of the tip\n\
+ program. If appropriate, the PATH environment variable is searched.\n\
+ configuration-id is unused.\n\
+\n\
+`configuration-id'\n\
+ Look up the configuration in ./udi_soc or /etc/udi_soc, which\n\
+ are files containing lines in the above formats. configuration-id is\n\
+ used to pick which line of the file to use.",
+ udi_open,
+ udi_close,
+ udi_attach,
+ udi_detach,
+ udi_resume,
+ udi_wait,
+ udi_fetch_registers,
+ udi_store_registers,
+ udi_prepare_to_store,
+ udi_xfer_inferior_memory,
+ udi_files_info,
+ udi_insert_breakpoint,
+ udi_remove_breakpoint,
+ 0, /* termial_init */
+ 0, /* terminal_inferior */
+ 0, /* terminal_ours_for_output */
+ 0, /* terminal_ours */
+ 0, /* terminal_info */
+ udi_kill, /* FIXME, kill */
+ udi_load, /* to_load */
+ 0, /* lookup_symbol */
+ udi_create_inferior,
+ udi_mourn, /* mourn_inferior FIXME */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum,
+ 0, /* next */
+ 1, /* has_all_memory */
+ 1, /* has_memory */
+ 1, /* has_stack */
+ 1, /* has_registers */
+ 1, /* has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+void
+_initialize_remote_udi ()
+{
+ add_target (&udi_ops);
+}
diff --git a/contrib/gdb/gdb/remote-utils.c b/contrib/gdb/gdb/remote-utils.c
new file mode 100644
index 0000000..cbbdeaf
--- /dev/null
+++ b/contrib/gdb/gdb/remote-utils.c
@@ -0,0 +1,646 @@
+/* Generic support for remote debugging interfaces.
+
+ Copyright 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file actually contains two distinct logical "packages". They
+ are packaged together in this one file because they are typically
+ used together.
+
+ The first package is an addition to the serial package. The
+ addition provides reading and writing with debugging output and
+ timeouts based on user settable variables. These routines are
+ intended to support serial port based remote backends. These
+ functions are prefixed with sr_.
+
+ The second package is a collection of more or less generic
+ functions for use by remote backends. They support user settable
+ variables for debugging, retries, and the like.
+
+ Todo:
+
+ * a pass through mode a la kermit or telnet.
+ * autobaud.
+ * ask remote to change his baud rate.
+ */
+
+#include <ctype.h>
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "serial.h"
+#include "gdbcore.h" /* for exec_bfd */
+#include "inferior.h" /* for generic_mourn_inferior */
+#include "remote-utils.h"
+
+struct _sr_settings sr_settings = {
+ 4, /* timeout:
+ remote-hms.c had 2
+ remote-bug.c had "with a timeout of 2, we time out waiting for
+ the prompt after an s-record dump."
+
+ remote.c had (2): 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.
+*/
+
+ 10, /* retries */
+ NULL, /* device */
+ NULL, /* descriptor */
+};
+
+struct gr_settings *gr_settings = NULL;
+
+static void
+usage(proto, junk)
+ char *proto;
+ char *junk;
+{
+ if (junk != NULL)
+ fprintf_unfiltered(gdb_stderr, "Unrecognized arguments: `%s'.\n", junk);
+
+ error ("Usage: target %s [DEVICE [SPEED [DEBUG]]]\n\
+where DEVICE is the name of a device or HOST:PORT", proto, proto);
+
+ return;
+}
+
+#define CHECKDONE(p, q) \
+{ \
+ if (q == p) \
+ { \
+ if (*p == '\0') \
+ return; \
+ else \
+ usage(proto, p); \
+ } \
+}
+
+void
+sr_scan_args(proto, args)
+ char *proto;
+ char *args;
+{
+ int n;
+ char *p, *q;
+
+ /* if no args, then nothing to do. */
+ if (args == NULL || *args == '\0')
+ return;
+
+ /* scan off white space. */
+ for (p = args; isspace(*p); ++p) ;;
+
+ /* find end of device name. */
+ for (q = p; *q != '\0' && !isspace(*q); ++q) ;;
+
+ /* check for missing or empty device name. */
+ CHECKDONE(p, q);
+ sr_set_device(savestring(p, q - p));
+
+ /* look for baud rate. */
+ n = strtol(q, &p, 10);
+
+ /* check for missing or empty baud rate. */
+ CHECKDONE(p, q);
+ baud_rate = n;
+
+ /* look for debug value. */
+ n = strtol(p, &q, 10);
+
+ /* check for missing or empty debug value. */
+ CHECKDONE(p, q);
+ sr_set_debug(n);
+
+ /* scan off remaining white space. */
+ for (p = q; isspace(*p); ++p) ;;
+
+ /* if not end of string, then there's unrecognized junk. */
+ if (*p != '\0')
+ usage(proto, p);
+
+ return;
+}
+
+void
+gr_generic_checkin()
+{
+ sr_write_cr("");
+ gr_expect_prompt();
+}
+
+void
+gr_open(args, from_tty, gr)
+ char *args;
+ int from_tty;
+ struct gr_settings *gr;
+{
+ target_preopen(from_tty);
+ sr_scan_args(gr->ops->to_shortname, args);
+ unpush_target(gr->ops);
+
+ gr_settings = gr;
+
+ gr_set_dcache(dcache_init(gr->readfunc, gr->writefunc));
+
+ 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 (baud_rate != -1)
+ {
+ 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());
+
+ /* If there is something sitting in the buffer we might take it as a
+ response to a command, which would be bad. */
+ SERIAL_FLUSH_INPUT (sr_get_desc ());
+
+ /* default retries */
+ if (sr_get_retries() == 0)
+ sr_set_retries(1);
+
+ /* default clear breakpoint function */
+ if (gr_settings->clear_all_breakpoints == NULL)
+ gr_settings->clear_all_breakpoints = remove_breakpoints;
+
+ if (from_tty)
+ {
+ 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();
+ gr_clear_all_breakpoints ();
+ return;
+}
+
+/* Read a character from the remote system masking it down to 7 bits
+ and doing all the fancy timeout stuff. */
+
+int
+sr_readchar ()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (sr_get_desc(), sr_get_timeout());
+
+ if (buf == SERIAL_TIMEOUT)
+ error ("Timeout reading from remote system.");
+
+ if (sr_get_debug() > 0)
+ printf_unfiltered ("%c", buf);
+
+ return buf & 0x7f;
+}
+
+int
+sr_pollchar()
+{
+ int buf;
+
+ buf = SERIAL_READCHAR (sr_get_desc(), 0);
+ if (buf == SERIAL_TIMEOUT)
+ buf = 0;
+ if (sr_get_debug() > 0)
+ if (buf)
+ printf_unfiltered ("%c", buf);
+ else
+ printf_unfiltered ("<empty character poll>");
+
+ return buf & 0x7f;
+}
+
+/* Keep discarding input from the remote system, until STRING is found.
+ Let the user break out immediately. */
+void
+sr_expect (string)
+ char *string;
+{
+ char *p = string;
+
+ immediate_quit = 1;
+ while (1)
+ {
+ if (sr_readchar () == *p)
+ {
+ p++;
+ if (*p == '\0')
+ {
+ immediate_quit = 0;
+ return;
+ }
+ }
+ else
+ p = string;
+ }
+}
+
+void
+sr_write (a, l)
+ char *a;
+ int l;
+{
+ int i;
+
+ if (SERIAL_WRITE (sr_get_desc(), a, l) != 0)
+ perror_with_name ("sr_write: Error writing to remote");
+
+ if (sr_get_debug() > 0)
+ for (i = 0; i < l; i++)
+ printf_unfiltered ("%c", a[i]);
+
+ return;
+}
+
+void
+sr_write_cr (s)
+ char *s;
+{
+ sr_write (s, strlen (s));
+ sr_write ("\r", 1);
+ return;
+}
+
+int
+sr_timed_read (buf, n)
+ char *buf;
+ int n;
+{
+ int i;
+ char c;
+
+ i = 0;
+ while (i < n)
+ {
+ c = sr_readchar ();
+
+ if (c == 0)
+ return i;
+ buf[i] = c;
+ i++;
+
+ }
+ return i;
+}
+
+/* Get a hex digit from the remote system & return its value. If
+ ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
+
+int
+sr_get_hex_digit (ignore_space)
+ int ignore_space;
+{
+ int ch;
+
+ while (1)
+ {
+ ch = sr_readchar ();
+ if (ch >= '0' && ch <= '9')
+ return ch - '0';
+ else if (ch >= 'A' && ch <= 'F')
+ return ch - 'A' + 10;
+ else if (ch >= 'a' && ch <= 'f')
+ return ch - 'a' + 10;
+ else if (ch != ' ' || !ignore_space)
+ {
+ gr_expect_prompt ();
+ error ("Invalid hex digit from remote system.");
+ }
+ }
+}
+
+/* Get a byte from the remote and put it in *BYT. Accept any number
+ leading spaces. */
+void
+sr_get_hex_byte (byt)
+ char *byt;
+{
+ int val;
+
+ val = sr_get_hex_digit (1) << 4;
+ val |= sr_get_hex_digit (0);
+ *byt = val;
+}
+
+/* Read a 32-bit hex word from the remote, preceded by a space */
+long
+sr_get_hex_word ()
+{
+ long val;
+ int j;
+
+ val = 0;
+ for (j = 0; j < 8; j++)
+ val = (val << 4) + sr_get_hex_digit (j == 0);
+ return val;
+}
+
+/* Put a command string, in args, out to the remote. The remote is assumed to
+ be in raw mode, all writing/reading done through desc.
+ Ouput from the remote is placed on the users terminal until the
+ prompt from the remote is seen.
+ FIXME: Can't handle commands that take input. */
+
+void
+sr_com (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ sr_check_open ();
+
+ if (!args)
+ return;
+
+ /* Clear all input so only command relative output is displayed */
+
+ sr_write_cr (args);
+ sr_write ("\030", 1);
+ registers_changed ();
+ gr_expect_prompt ();
+}
+
+void
+gr_close(quitting)
+ int quitting;
+{
+ gr_clear_all_breakpoints();
+
+ if (sr_is_open())
+ {
+ SERIAL_CLOSE (sr_get_desc());
+ sr_set_desc(NULL);
+ }
+
+ return;
+}
+
+/* gr_detach()
+ takes a program previously attached to and detaches it.
+ We better not have left any breakpoints
+ in the program or it'll die when it hits one.
+ Close the open connection to the remote debugger.
+ Use this when you want to detach and do something else
+ with your gdb. */
+
+void
+gr_detach(args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ if (sr_is_open())
+ gr_clear_all_breakpoints ();
+
+ pop_target ();
+ if (from_tty)
+ puts_filtered ("Ending remote debugging.\n");
+
+ return;
+}
+
+void
+gr_files_info (ops)
+ struct target_ops *ops;
+{
+#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)
+ {
+ printf_filtered ("\tand running program %s\n",
+ bfd_get_filename (exec_bfd));
+ }
+ printf_filtered ("\tusing the %s protocol.\n", ops->to_shortname);
+}
+
+void
+gr_mourn ()
+{
+ gr_clear_all_breakpoints ();
+ unpush_target (gr_get_ops());
+ generic_mourn_inferior ();
+}
+
+void
+gr_kill ()
+{
+ return;
+}
+
+/* This is called not only when we first attach, but also when the
+ user types "run" after having attached. */
+void
+gr_create_inferior (execfile, args, env)
+ char *execfile;
+ char *args;
+ char **env;
+{
+ int entry_pt;
+
+ if (args && *args)
+ error ("Can't pass arguments to remote process.");
+
+ if (execfile == 0 || exec_bfd == 0)
+ error ("No exec file specified");
+
+ entry_pt = (int) bfd_get_start_address (exec_bfd);
+ sr_check_open ();
+
+ gr_kill ();
+ gr_clear_all_breakpoints ();
+
+ init_wait_for_inferior ();
+ gr_checkin();
+
+ insert_breakpoints (); /* Needed to get correct instruction in cache */
+ proceed (entry_pt, -1, 0);
+}
+
+/* Given a null terminated list of strings LIST, read the input until we find one of
+ them. Return the index of the string found or -1 on error. '?' means match
+ any single character. Note that with the algorithm we use, the initial
+ character of the string cannot recur in the string, or we will not find some
+ cases of the string in the input. If PASSTHROUGH is non-zero, then
+ pass non-matching data on. */
+
+int
+gr_multi_scan (list, passthrough)
+ char *list[];
+ int passthrough;
+{
+ char *swallowed = NULL; /* holding area */
+ char *swallowed_p = swallowed; /* Current position in swallowed. */
+ int ch;
+ int ch_handled;
+ int i;
+ int string_count;
+ int max_length;
+ char **plist;
+
+ /* Look through the strings. Count them. Find the largest one so we can
+ allocate a holding area. */
+
+ for (max_length = string_count = i = 0;
+ list[i] != NULL;
+ ++i, ++string_count)
+ {
+ int length = strlen(list[i]);
+
+ if (length > max_length)
+ max_length = length;
+ }
+
+ /* if we have no strings, then something is wrong. */
+ if (string_count == 0)
+ return(-1);
+
+ /* otherwise, we will need a holding area big enough to hold almost two
+ copies of our largest string. */
+ swallowed_p = swallowed = alloca(max_length << 1);
+
+ /* and a list of pointers to current scan points. */
+ plist = (char **) alloca (string_count * sizeof(*plist));
+
+ /* and initialize */
+ for (i = 0; i < string_count; ++i)
+ plist[i] = list[i];
+
+ for (ch = sr_readchar(); /* loop forever */ ; ch = sr_readchar())
+ {
+ QUIT; /* Let user quit and leave process running */
+ ch_handled = 0;
+
+ for (i = 0; i < string_count; ++i)
+ {
+ if (ch == *plist[i] || *plist[i] == '?')
+ {
+ ++plist[i];
+ if (*plist[i] == '\0')
+ return(i);
+
+ if (!ch_handled)
+ *swallowed_p++ = ch;
+
+ ch_handled = 1;
+ }
+ else
+ plist[i] = list[i];
+ }
+
+ if (!ch_handled)
+ {
+ char *p;
+
+ /* Print out any characters which have been swallowed. */
+ if (passthrough)
+ {
+ for (p = swallowed; p < swallowed_p; ++p)
+ fputc_unfiltered (*p, gdb_stdout);
+
+ fputc_unfiltered (ch, gdb_stdout);
+ }
+
+ swallowed_p = swallowed;
+ }
+ }
+#if 0
+ /* Never reached. */
+ return(-1);
+#endif
+}
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that registers contains all the registers from the program being
+ debugged. */
+
+void
+gr_prepare_to_store ()
+{
+ /* Do nothing, since we assume we can store individual regs */
+}
+
+/* Read a word from remote address ADDR and return it.
+ * This goes through the data cache.
+ */
+int
+gr_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ return dcache_fetch (gr_get_dcache(), addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+void
+gr_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (gr_get_dcache(), addr, word);
+}
+
+void
+_initialize_sr_support ()
+{
+/* FIXME-now: if target is open... */
+ add_show_from_set (add_set_cmd ("remotedevice", no_class,
+ var_filename, (char *)&sr_settings.device,
+ "Set device for remote serial I/O.\n\
+This device is used as the serial port when debugging using remote\n\
+targets.", &setlist),
+ &showlist);
+
+ add_com ("remote <command>", class_obscure, sr_com,
+ "Send a command to the remote monitor.");
+
+}
diff --git a/contrib/gdb/gdb/remote-utils.h b/contrib/gdb/gdb/remote-utils.h
new file mode 100644
index 0000000..d4fcd0e
--- /dev/null
+++ b/contrib/gdb/gdb/remote-utils.h
@@ -0,0 +1,142 @@
+/* Generic support for remote debugging interfaces.
+
+ Copyright 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef REMOTE_UTILS_H
+#define REMOTE_UTILS_H
+
+#include "serial.h"
+#include "target.h"
+#include "dcache.h"
+
+/* Stuff that should be shared (and handled consistently) among the various
+ remote targets. */
+
+struct _sr_settings {
+ unsigned int timeout;
+
+ int retries;
+
+ char *device;
+ serial_t desc;
+
+};
+
+extern struct _sr_settings sr_settings;
+
+/* get and set debug value. */
+#define sr_get_debug() (remote_debug)
+#define sr_set_debug(newval) (remote_debug = (newval))
+
+/* get and set timeout. */
+#define sr_get_timeout() (sr_settings.timeout)
+#define sr_set_timeout(newval) (sr_settings.timeout = (newval))
+
+/* get and set device. */
+#define sr_get_device() (sr_settings.device)
+#define sr_set_device(newval) \
+{ \
+ if (sr_settings.device) free(sr_settings.device); \
+ sr_settings.device = (newval); \
+}
+
+/* get and set descriptor value. */
+#define sr_get_desc() (sr_settings.desc)
+#define sr_set_desc(newval) (sr_settings.desc = (newval))
+
+/* get and set retries. */
+#define sr_get_retries() (sr_settings.retries)
+#define sr_set_retries(newval) (sr_settings.retries = (newval))
+
+#define sr_is_open() (sr_settings.desc != NULL)
+
+#define sr_check_open() { if (!sr_is_open()) \
+ error ("Remote device not open"); }
+
+struct gr_settings {
+ /* This is our data cache. */
+ DCACHE *dcache;
+ char *prompt;
+ struct target_ops *ops;
+ int (*clear_all_breakpoints)PARAMS((void));
+ memxferfunc readfunc;
+ memxferfunc writefunc;
+ void (*checkin)PARAMS((void));
+};
+
+extern struct gr_settings *gr_settings;
+
+/* get and set dcache. */
+#define gr_get_dcache() (gr_settings->dcache)
+#define gr_set_dcache(newval) (gr_settings->dcache = (newval))
+
+/* get and set prompt. */
+#define gr_get_prompt() (gr_settings->prompt)
+#define gr_set_prompt(newval) (gr_settings->prompt = (newval))
+
+/* get and set ops. */
+#define gr_get_ops() (gr_settings->ops)
+#define gr_set_ops(newval) (gr_settings->ops = (newval))
+
+#define gr_clear_all_breakpoints() ((gr_settings->clear_all_breakpoints)())
+#define gr_checkin() ((gr_settings->checkin)())
+
+/* Keep discarding input until we see the prompt.
+
+ The convention for dealing with the prompt is that you
+ o give your command
+ o *then* wait for the prompt.
+
+ Thus the last thing that a procedure does with the serial line
+ will be an gr_expect_prompt(). Exception: resume does not
+ wait for the prompt, because the terminal is being handed over
+ to the inferior. However, the next thing which happens after that
+ is a bug_wait which does wait for the prompt.
+ Note that this includes abnormal exit, e.g. error(). This is
+ necessary to prevent getting into states from which we can't
+ recover. */
+
+#define gr_expect_prompt() sr_expect(gr_get_prompt())
+
+int gr_fetch_word PARAMS((CORE_ADDR addr));
+int gr_multi_scan PARAMS((char *list[], int passthrough));
+int sr_get_hex_digit PARAMS((int ignore_space));
+int sr_pollchar PARAMS((void));
+int sr_readchar PARAMS((void));
+int sr_timed_read PARAMS((char *buf, int n));
+long sr_get_hex_word PARAMS((void));
+void gr_close PARAMS((int quitting));
+void gr_create_inferior PARAMS((char *execfile, char *args, char **env));
+void gr_detach PARAMS((char *args, int from_tty));
+void gr_files_info PARAMS((struct target_ops *ops));
+void gr_generic_checkin PARAMS((void));
+void gr_kill PARAMS((void));
+void gr_mourn PARAMS((void));
+void gr_prepare_to_store PARAMS((void));
+void gr_store_word PARAMS((CORE_ADDR addr, int word));
+void sr_expect PARAMS((char *string));
+void sr_get_hex_byte PARAMS((char *byt));
+void sr_scan_args PARAMS((char *proto, char *args));
+void sr_write PARAMS((char *a, int l));
+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/contrib/gdb/gdb/remote-vx.c b/contrib/gdb/gdb/remote-vx.c
new file mode 100644
index 0000000..13b6c29
--- /dev/null
+++ b/contrib/gdb/gdb/remote-vx.c
@@ -0,0 +1,1488 @@
+/* Memory-access and commands for remote VxWorks processes, for GDB.
+ Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
+ Contributed by Wind River Systems and Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "complaints.h"
+#include "gdbcmd.h"
+#include "bfd.h" /* Required by objfiles.h. */
+#include "symfile.h" /* Required by objfiles.h. */
+#include "objfiles.h"
+#include "gdb-stabs.h"
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#define malloc bogon_malloc /* Sun claims "char *malloc()" not void * */
+#define free bogon_free /* Sun claims "int free()" not void */
+#define realloc bogon_realloc /* Sun claims "char *realloc()", not void * */
+#include <rpc/rpc.h>
+#undef malloc
+#undef free
+#undef realloc
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+#include <symtab.h>
+
+/* Maximum number of bytes to transfer in a single
+ PTRACE_{READ,WRITE}DATA request. */
+#define VX_MEMXFER_MAX 4096
+
+extern void vx_read_register ();
+extern void vx_write_register ();
+extern void symbol_file_command ();
+extern int stop_soon_quietly; /* for wait_for_inferior */
+
+static int net_step ();
+static int net_ptrace_clnt_call (); /* Forward decl */
+static enum clnt_stat net_clnt_call (); /* Forward decl */
+extern struct target_ops vx_ops, vx_run_ops; /* Forward declaration */
+
+/* Saved name of target host and called function for "info files".
+ Both malloc'd. */
+
+static char *vx_host;
+static char *vx_running; /* Called function */
+
+/* Nonzero means target that is being debugged remotely has a floating
+ point processor. */
+
+int target_has_fp;
+
+/* Default error message when the network is forking up. */
+
+static const char rpcerr[] = "network target debugging: rpc error";
+
+CLIENT *pClient; /* client used in net debugging */
+static int ptraceSock = RPC_ANYSOCK;
+
+enum clnt_stat net_clnt_call();
+static void parse_args ();
+
+static struct timeval rpcTimeout = { 10, 0 };
+
+static char *skip_white_space ();
+static char *find_white_space ();
+
+/* Tell the VxWorks target system to download a file.
+ The load addresses of the text, data, and bss segments are
+ stored in *pTextAddr, *pDataAddr, and *pBssAddr (respectively).
+ Returns 0 for success, -1 for failure. */
+
+static int
+net_load (filename, pTextAddr, pDataAddr, pBssAddr)
+ char *filename;
+ CORE_ADDR *pTextAddr;
+ CORE_ADDR *pDataAddr;
+ CORE_ADDR *pBssAddr;
+{
+ enum clnt_stat status;
+ struct ldfile ldstruct;
+ struct timeval load_timeout;
+
+ memset ((char *) &ldstruct, '\0', sizeof (ldstruct));
+
+ /* We invoke clnt_call () here directly, instead of through
+ net_clnt_call (), because we need to set a large timeout value.
+ The load on the target side can take quite a while, easily
+ more than 10 seconds. The user can kill this call by typing
+ CTRL-C if there really is a problem with the load.
+
+ Do not change the tv_sec value without checking -- select() imposes
+ a limit of 10**8 on it for no good reason that I can see... */
+
+ load_timeout.tv_sec = 99999999; /* A large number, effectively inf. */
+ load_timeout.tv_usec = 0;
+
+ status = clnt_call (pClient, VX_LOAD, xdr_wrapstring, &filename, xdr_ldfile,
+ &ldstruct, load_timeout);
+
+ if (status == RPC_SUCCESS)
+ {
+ if (*ldstruct.name == 0) /* load failed on VxWorks side */
+ return -1;
+ *pTextAddr = ldstruct.txt_addr;
+ *pDataAddr = ldstruct.data_addr;
+ *pBssAddr = ldstruct.bss_addr;
+ return 0;
+ }
+ else
+ return -1;
+}
+
+/* returns 0 if successful, errno if RPC failed or VxWorks complains. */
+
+static int
+net_break (addr, procnum)
+ int addr;
+ u_long procnum;
+{
+ enum clnt_stat status;
+ int break_status;
+ Rptrace ptrace_in; /* XXX This is stupid. It doesn't need to be a ptrace
+ structure. How about something smaller? */
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ break_status = 0;
+
+ ptrace_in.addr = addr;
+ ptrace_in.pid = inferior_pid;
+
+ status = net_clnt_call (procnum, xdr_rptrace, &ptrace_in, xdr_int,
+ &break_status);
+
+ if (status != RPC_SUCCESS)
+ return errno;
+
+ if (break_status == -1)
+ return ENOMEM;
+ return break_status; /* probably (FIXME) zero */
+}
+
+/* returns 0 if successful, errno otherwise */
+
+static int
+vx_insert_breakpoint (addr)
+ int addr;
+{
+ return net_break (addr, VX_BREAK_ADD);
+}
+
+/* returns 0 if successful, errno otherwise */
+
+static int
+vx_remove_breakpoint (addr)
+ int addr;
+{
+ return net_break (addr, VX_BREAK_DELETE);
+}
+
+/* Start an inferior 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.
+ Returns process id. Errors reported with error().
+ On VxWorks, we ignore exec_file. */
+
+static void
+vx_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ enum clnt_stat status;
+ arg_array passArgs;
+ TASK_START taskStart;
+
+ memset ((char *) &passArgs, '\0', sizeof (passArgs));
+ memset ((char *) &taskStart, '\0', sizeof (taskStart));
+
+ /* parse arguments, put them in passArgs */
+
+ parse_args (args, &passArgs);
+
+ if (passArgs.arg_array_len == 0)
+ error ("You must specify a function name to run, and arguments if any");
+
+ status = net_clnt_call (PROCESS_START, xdr_arg_array, &passArgs,
+ xdr_TASK_START, &taskStart);
+
+ if ((status != RPC_SUCCESS) || (taskStart.status == -1))
+ error ("Can't create process on remote target machine");
+
+ /* Save the name of the running function */
+ vx_running = savestring (passArgs.arg_array_val[0],
+ strlen (passArgs.arg_array_val[0]));
+
+ push_target (&vx_run_ops);
+ inferior_pid = taskStart.pid;
+
+ /* We will get a trace trap after one instruction.
+ Insert breakpoints and continue. */
+
+ init_wait_for_inferior ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+ target_terminal_inferior ();
+
+ stop_soon_quietly = 1;
+ wait_for_inferior (); /* Get the task spawn event */
+ stop_soon_quietly = 0;
+
+ /* insert_step_breakpoint (); FIXME, do we need this? */
+ proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
+}
+
+/* Fill ARGSTRUCT in argc/argv form with the arguments from the
+ argument string ARGSTRING. */
+
+static void
+parse_args (arg_string, arg_struct)
+ register char *arg_string;
+ arg_array *arg_struct;
+{
+ register int arg_count = 0; /* number of arguments */
+ register int arg_index = 0;
+ register char *p0;
+
+ memset ((char *) arg_struct, '\0', sizeof (arg_array));
+
+ /* first count how many arguments there are */
+
+ p0 = arg_string;
+ while (*p0 != '\0')
+ {
+ if (*(p0 = skip_white_space (p0)) == '\0')
+ break;
+ p0 = find_white_space (p0);
+ arg_count++;
+ }
+
+ arg_struct->arg_array_len = arg_count;
+ arg_struct->arg_array_val = (char **) xmalloc ((arg_count + 1)
+ * sizeof (char *));
+
+ /* now copy argument strings into arg_struct. */
+
+ while (*(arg_string = skip_white_space (arg_string)))
+ {
+ p0 = find_white_space (arg_string);
+ arg_struct->arg_array_val[arg_index++] = savestring (arg_string,
+ p0 - arg_string);
+ arg_string = p0;
+ }
+
+ arg_struct->arg_array_val[arg_count] = NULL;
+}
+
+/* Advance a string pointer across whitespace and return a pointer
+ to the first non-white character. */
+
+static char *
+skip_white_space (p)
+ register char *p;
+{
+ while (*p == ' ' || *p == '\t')
+ p++;
+ return p;
+}
+
+/* Search for the first unquoted whitespace character in a string.
+ Returns a pointer to the character, or to the null terminator
+ if no whitespace is found. */
+
+static char *
+find_white_space (p)
+ register char *p;
+{
+ register int c;
+
+ while ((c = *p) != ' ' && c != '\t' && c)
+ {
+ if (c == '\'' || c == '"')
+ {
+ while (*++p != c && *p)
+ {
+ if (*p == '\\')
+ p++;
+ }
+ if (!*p)
+ break;
+ }
+ p++;
+ }
+ return p;
+}
+
+/* Poll the VxWorks target system for an event related
+ to the debugged task.
+ Returns -1 if remote wait failed, task status otherwise. */
+
+static int
+net_wait (pEvent)
+ RDB_EVENT *pEvent;
+{
+ int pid;
+ enum clnt_stat status;
+
+ memset ((char *) pEvent, '\0', sizeof (RDB_EVENT));
+
+ pid = inferior_pid;
+ status = net_clnt_call (PROCESS_WAIT, xdr_int, &pid, xdr_RDB_EVENT,
+ pEvent);
+
+ /* return (status == RPC_SUCCESS)? pEvent->status: -1; */
+ if (status == RPC_SUCCESS)
+ return ((pEvent->status) ? 1 : 0);
+ else if (status == RPC_TIMEDOUT)
+ return (1);
+ else
+ return (-1);
+}
+
+/* Suspend the remote task.
+ Returns -1 if suspend fails on target system, 0 otherwise. */
+
+static int
+net_quit ()
+{
+ int pid;
+ int quit_status;
+ enum clnt_stat status;
+
+ quit_status = 0;
+
+ /* don't let rdbTask suspend itself by passing a pid of 0 */
+
+ if ((pid = inferior_pid) == 0)
+ return -1;
+
+ status = net_clnt_call (VX_TASK_SUSPEND, xdr_int, &pid, xdr_int,
+ &quit_status);
+
+ return (status == RPC_SUCCESS)? quit_status: -1;
+}
+
+/* Read a register or registers from the remote system. */
+
+void
+net_read_registers (reg_buf, len, procnum)
+ char *reg_buf;
+ int len;
+ u_long procnum;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ C_bytes out_data;
+ char message[100];
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ /* Initialize RPC input argument structure. */
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_in.info.ttype = NOINFO;
+
+ /* Initialize RPC return value structure. */
+
+ out_data.bytes = reg_buf;
+ out_data.len = len;
+ ptrace_out.info.more_data = (caddr_t) &out_data;
+
+ /* Call RPC; take an error exit if appropriate. */
+
+ status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ sprintf (message, "reading %s registers", (procnum == PTRACE_GETREGS)
+ ? "general-purpose"
+ : "floating-point");
+ perror_with_name (message);
+ }
+}
+
+/* Write register values to a VxWorks target. REG_BUF points to a buffer
+ containing the raw register values, LEN is the length of REG_BUF in
+ bytes, and PROCNUM is the RPC procedure number (PTRACE_SETREGS or
+ PTRACE_SETFPREGS). An error exit is taken if the RPC call fails or
+ if an error status is returned by the remote debug server. This is
+ a utility routine used by vx_write_register (). */
+
+void
+net_write_registers (reg_buf, len, procnum)
+ char *reg_buf;
+ int len;
+ u_long procnum;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ C_bytes in_data;
+ char message[100];
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ /* Initialize RPC input argument structure. */
+
+ in_data.bytes = reg_buf;
+ in_data.len = len;
+
+ ptrace_in.pid = inferior_pid;
+ ptrace_in.info.ttype = DATA;
+ ptrace_in.info.more_data = (caddr_t) &in_data;
+
+ /* Call RPC; take an error exit if appropriate. */
+
+ status = net_ptrace_clnt_call (procnum, &ptrace_in, &ptrace_out);
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ sprintf (message, "writing %s registers", (procnum == PTRACE_SETREGS)
+ ? "general-purpose"
+ : "floating-point");
+ perror_with_name (message);
+ }
+}
+
+/* Prepare to store registers. Since we will store all of them,
+ read out their current values now. */
+
+static void
+vx_prepare_to_store ()
+{
+ /* Fetch all registers, if any of them are not yet fetched. */
+ read_register_bytes (0, NULL, REGISTER_BYTES);
+}
+
+/* Copy LEN bytes to or from remote inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. WRITE is true if writing to the
+ inferior.
+ Result is the number of bytes written or read (zero if error). The
+ protocol allows us to return a negative count, indicating that we can't
+ handle the current address but can handle one N bytes further, but
+ vxworks doesn't give us that information. */
+
+static int
+vx_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ C_bytes data;
+ enum ptracereq request;
+ int nleft, nxfer;
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ ptrace_in.pid = inferior_pid; /* XXX pid unnecessary for READDATA */
+ ptrace_in.addr = (int) memaddr; /* Where from */
+ ptrace_in.data = len; /* How many bytes */
+
+ if (write)
+ {
+ ptrace_in.info.ttype = DATA;
+ ptrace_in.info.more_data = (caddr_t) &data;
+
+ data.bytes = (caddr_t) myaddr; /* Where from */
+ data.len = len; /* How many bytes (again, for XDR) */
+ request = PTRACE_WRITEDATA;
+ }
+ else
+ {
+ ptrace_out.info.more_data = (caddr_t) &data;
+ request = PTRACE_READDATA;
+ }
+ /* Loop until the entire request has been satisfied, transferring
+ at most VX_MEMXFER_MAX bytes per iteration. Break from the loop
+ if an error status is returned by the remote debug server. */
+
+ nleft = len;
+ status = 0;
+
+ while (nleft > 0 && status == 0)
+ {
+ nxfer = min (nleft, VX_MEMXFER_MAX);
+
+ ptrace_in.addr = (int) memaddr;
+ ptrace_in.data = nxfer;
+ data.bytes = (caddr_t) myaddr;
+ data.len = nxfer;
+
+ /* Request a block from the remote debug server; if RPC fails,
+ report an error and return to debugger command level. */
+
+ if (net_ptrace_clnt_call (request, &ptrace_in, &ptrace_out))
+ error (rpcerr);
+
+ status = ptrace_out.status;
+ if (status == 0)
+ {
+ memaddr += nxfer;
+ myaddr += nxfer;
+ nleft -= nxfer;
+ }
+ else
+ {
+ /* A target-side error has ocurred. Set errno to the error
+ code chosen by the target so that a later perror () will
+ say something meaningful. */
+
+ errno = ptrace_out.errno;
+ }
+ }
+
+ /* Return the number of bytes transferred. */
+
+ return (len - nleft);
+}
+
+static void
+vx_files_info ()
+{
+ printf_unfiltered ("\tAttached to host `%s'", vx_host);
+ printf_unfiltered (", which has %sfloating point", target_has_fp? "": "no ");
+ printf_unfiltered (".\n");
+}
+
+static void
+vx_run_files_info ()
+{
+ printf_unfiltered ("\tRunning %s VxWorks process %s",
+ vx_running ? "child" : "attached",
+ local_hex_string (inferior_pid));
+ if (vx_running)
+ printf_unfiltered (", function `%s'", vx_running);
+ printf_unfiltered(".\n");
+}
+
+static void
+vx_resume (pid, step, siggnal)
+ int pid;
+ int step;
+ enum target_signal siggnal;
+{
+ int status;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ CORE_ADDR cont_addr;
+
+ if (pid == -1)
+ pid = inferior_pid;
+
+ if (siggnal != 0 && siggnal != stop_signal)
+ error ("Cannot send signals to VxWorks processes");
+
+ /* Set CONT_ADDR to the address at which we are continuing,
+ or to 1 if we are continuing from where the program stopped.
+ This conforms to traditional ptrace () usage, but at the same
+ time has special meaning for the VxWorks remote debug server.
+ If the address is not 1, the server knows that the target
+ program is jumping to a new address, which requires special
+ handling if there is a breakpoint at the new address. */
+
+ cont_addr = read_register (PC_REGNUM);
+ if (cont_addr == stop_pc)
+ cont_addr = 1;
+
+ memset ((char *) &ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *) &ptrace_out, '\0', sizeof (ptrace_out));
+
+ ptrace_in.pid = pid;
+ ptrace_in.addr = cont_addr; /* Target side insists on this, or it panics. */
+
+ if (step)
+ status = net_step();
+ else
+ status = net_ptrace_clnt_call (PTRACE_CONT, &ptrace_in, &ptrace_out);
+
+ if (status)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Resuming remote process");
+ }
+}
+
+static void
+vx_mourn_inferior ()
+{
+ pop_target (); /* Pop back to no-child state */
+ generic_mourn_inferior ();
+}
+
+
+static void vx_add_symbols PARAMS ((char *, int, CORE_ADDR, CORE_ADDR,
+ CORE_ADDR));
+
+struct find_sect_args {
+ CORE_ADDR text_start;
+ CORE_ADDR data_start;
+ CORE_ADDR bss_start;
+};
+
+static void find_sect PARAMS ((bfd *, asection *, void *));
+
+static void
+find_sect (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ struct find_sect_args *args = (struct find_sect_args *)obj;
+
+ if (bfd_get_section_flags (abfd, sect) & (SEC_CODE & SEC_READONLY))
+ args->text_start = bfd_get_section_vma (abfd, sect);
+ else if (bfd_get_section_flags (abfd, sect) & SEC_ALLOC)
+ {
+ if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
+ {
+ /* Exclude .ctor and .dtor sections which have SEC_CODE set but not
+ SEC_DATA. */
+ if (bfd_get_section_flags (abfd, sect) & SEC_DATA)
+ args->data_start = bfd_get_section_vma (abfd, sect);
+ }
+ else
+ args->bss_start = bfd_get_section_vma (abfd, sect);
+ }
+}
+
+static void
+vx_add_symbols (name, from_tty, text_addr, data_addr, bss_addr)
+ char *name;
+ int from_tty;
+ CORE_ADDR text_addr;
+ CORE_ADDR data_addr;
+ CORE_ADDR bss_addr;
+{
+ struct section_offsets *offs;
+ struct objfile *objfile;
+ struct find_sect_args ss;
+
+ /* It might be nice to suppress the breakpoint_re_set which happens here
+ because we are going to do one again after the objfile_relocate. */
+ objfile = symbol_file_add (name, from_tty, 0, 0, 0, 0);
+
+ /* This is a (slightly cheesy) way of superceding the old symbols. A less
+ cheesy way would be to find the objfile with the same name and
+ free_objfile it. */
+ objfile_to_front (objfile);
+
+ offs = (struct section_offsets *)
+ alloca (sizeof (struct section_offsets)
+ + objfile->num_sections * sizeof (offs->offsets));
+ memcpy (offs, objfile->section_offsets,
+ sizeof (struct section_offsets)
+ + objfile->num_sections * sizeof (offs->offsets));
+
+ ss.text_start = 0;
+ ss.data_start = 0;
+ ss.bss_start = 0;
+ bfd_map_over_sections (objfile->obfd, find_sect, &ss);
+
+ /* Both COFF and b.out frontends use these SECT_OFF_* values. */
+ ANOFFSET (offs, SECT_OFF_TEXT) = text_addr - ss.text_start;
+ ANOFFSET (offs, SECT_OFF_DATA) = data_addr - ss.data_start;
+ ANOFFSET (offs, SECT_OFF_BSS) = bss_addr - ss.bss_start;
+ objfile_relocate (objfile, offs);
+
+ /* Need to do this *after* things are relocated. */
+ breakpoint_re_set ();
+}
+
+/* This function allows the addition of incrementally linked object files. */
+
+static void
+vx_load_command (arg_string, from_tty)
+ char *arg_string;
+ int from_tty;
+{
+ CORE_ADDR text_addr;
+ CORE_ADDR data_addr;
+ CORE_ADDR bss_addr;
+
+ if (arg_string == 0)
+ error ("The load command takes a file name");
+
+ arg_string = tilde_expand (arg_string);
+ make_cleanup (free, arg_string);
+
+ dont_repeat ();
+
+ /* Refuse to load the module if a debugged task is running. Doing so
+ can have a number of unpleasant consequences to the running task. */
+
+ if (inferior_pid != 0 && target_has_execution)
+ {
+ if (query ("You may not load a module while the target task is running.\n\
+Kill the target task? "))
+ target_kill ();
+ else
+ error ("Load cancelled.");
+ }
+
+ QUIT;
+ immediate_quit++;
+ if (net_load (arg_string, &text_addr, &data_addr, &bss_addr) == -1)
+ error ("Load failed on target machine");
+ immediate_quit--;
+
+ vx_add_symbols (arg_string, from_tty, text_addr, data_addr, bss_addr);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+/* Single step the target program at the source or machine level.
+ Takes an error exit if rpc fails.
+ Returns -1 if remote single-step operation fails, else 0. */
+
+static int
+net_step ()
+{
+ enum clnt_stat status;
+ int step_status;
+ SOURCE_STEP source_step;
+
+ source_step.taskId = inferior_pid;
+
+ if (step_range_end)
+ {
+ source_step.startAddr = step_range_start;
+ source_step.endAddr = step_range_end;
+ }
+ else
+ {
+ source_step.startAddr = 0;
+ source_step.endAddr = 0;
+ }
+
+ status = net_clnt_call (VX_SOURCE_STEP, xdr_SOURCE_STEP, &source_step,
+ xdr_int, &step_status);
+
+ if (status == RPC_SUCCESS)
+ return step_status;
+ else
+ error (rpcerr);
+}
+
+/* Emulate ptrace using RPC calls to the VxWorks target system.
+ Returns nonzero (-1) if RPC status to VxWorks is bad, 0 otherwise. */
+
+static int
+net_ptrace_clnt_call (request, pPtraceIn, pPtraceOut)
+ enum ptracereq request;
+ Rptrace *pPtraceIn;
+ Ptrace_return *pPtraceOut;
+{
+ enum clnt_stat status;
+
+ status = net_clnt_call (request, xdr_rptrace, pPtraceIn, xdr_ptrace_return,
+ pPtraceOut);
+
+ if (status != RPC_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+/* Query the target for the name of the file from which VxWorks was
+ booted. pBootFile is the address of a pointer to the buffer to
+ receive the file name; if the pointer pointed to by pBootFile is
+ NULL, memory for the buffer will be allocated by XDR.
+ Returns -1 if rpc failed, 0 otherwise. */
+
+static int
+net_get_boot_file (pBootFile)
+ char **pBootFile;
+{
+ enum clnt_stat status;
+
+ status = net_clnt_call (VX_BOOT_FILE_INQ, xdr_void, (char *) 0,
+ xdr_wrapstring, pBootFile);
+ return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Fetch a list of loaded object modules from the VxWorks target.
+ Returns -1 if rpc failed, 0 otherwise
+ There's no way to check if the returned loadTable is correct.
+ VxWorks doesn't check it. */
+
+static int
+net_get_symbols (pLoadTable)
+ ldtabl *pLoadTable; /* return pointer to ldtabl here */
+{
+ enum clnt_stat status;
+
+ memset ((char *) pLoadTable, '\0', sizeof (struct ldtabl));
+
+ status = net_clnt_call (VX_STATE_INQ, xdr_void, 0, xdr_ldtabl, pLoadTable);
+ return (status == RPC_SUCCESS) ? 0 : -1;
+}
+
+/* Look up a symbol in the VxWorks target's symbol table.
+ Returns status of symbol read on target side (0=success, -1=fail)
+ Returns -1 and complain()s if rpc fails. */
+
+struct complaint cant_contact_target =
+ {"Lost contact with VxWorks target", 0, 0};
+
+static int
+vx_lookup_symbol (name, pAddr)
+ char *name; /* symbol name */
+ CORE_ADDR *pAddr;
+{
+ enum clnt_stat status;
+ SYMBOL_ADDR symbolAddr;
+
+ *pAddr = 0;
+ memset ((char *) &symbolAddr, '\0', sizeof (symbolAddr));
+
+ status = net_clnt_call (VX_SYMBOL_INQ, xdr_wrapstring, &name,
+ xdr_SYMBOL_ADDR, &symbolAddr);
+ if (status != RPC_SUCCESS)
+ {
+ complain (&cant_contact_target);
+ return -1;
+ }
+
+ *pAddr = symbolAddr.addr;
+ return symbolAddr.status;
+}
+
+/* Check to see if the VxWorks target has a floating point coprocessor.
+ Returns 1 if target has floating point processor, 0 otherwise.
+ Calls error() if rpc fails. */
+
+static int
+net_check_for_fp ()
+{
+ enum clnt_stat status;
+ bool_t fp = 0; /* true if fp processor is present on target board */
+
+ status = net_clnt_call (VX_FP_INQUIRE, xdr_void, 0, xdr_bool, &fp);
+ if (status != RPC_SUCCESS)
+ error (rpcerr);
+
+ return (int) fp;
+}
+
+/* Establish an RPC connection with the VxWorks target system.
+ Calls error () if unable to establish connection. */
+
+static void
+net_connect (host)
+ char *host;
+{
+ struct sockaddr_in destAddr;
+ struct hostent *destHost;
+ unsigned long addr;
+
+ /* Get the internet address for the given host. Allow a numeric
+ IP address or a hostname. */
+
+ addr = inet_addr (host);
+ if (addr == -1)
+ {
+ destHost = (struct hostent *) gethostbyname (host);
+ if (destHost == NULL)
+ /* FIXME: Probably should include hostname here in quotes.
+ For example if the user types "target vxworks vx960 " it should
+ say "Invalid host `vx960 '." not just "Invalid hostname". */
+ error ("Invalid hostname. Couldn't find remote host address.");
+ addr = * (unsigned long *) destHost->h_addr;
+ }
+
+ memset (&destAddr, '\0', sizeof (destAddr));
+
+ destAddr.sin_addr.s_addr = addr;
+ destAddr.sin_family = AF_INET;
+ destAddr.sin_port = 0; /* set to actual port that remote
+ ptrace is listening on. */
+
+ /* Create a tcp client transport on which to issue
+ calls to the remote ptrace server. */
+
+ ptraceSock = RPC_ANYSOCK;
+ pClient = clnttcp_create (&destAddr, RDBPROG, RDBVERS, &ptraceSock, 0, 0);
+ /* FIXME, here is where we deal with different version numbers of the
+ proto */
+
+ if (pClient == NULL)
+ {
+ clnt_pcreateerror ("\tnet_connect");
+ error ("Couldn't connect to remote target.");
+ }
+}
+
+/* Sleep for the specified number of milliseconds
+ * (assumed to be less than 1000).
+ * If select () is interrupted, returns immediately;
+ * takes an error exit if select () fails for some other reason.
+ */
+
+static void
+sleep_ms (ms)
+ long ms;
+{
+ struct timeval select_timeout;
+ int status;
+
+ select_timeout.tv_sec = 0;
+ select_timeout.tv_usec = ms * 1000;
+
+ status = select (0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0,
+ &select_timeout);
+
+ if (status < 0 && errno != EINTR)
+ perror_with_name ("select");
+}
+
+static int
+vx_wait (pid_to_wait_for, status)
+ int pid_to_wait_for;
+ struct target_waitstatus *status;
+{
+ register int pid;
+ RDB_EVENT rdbEvent;
+ int quit_failed;
+
+ do
+ {
+ /* If CTRL-C is hit during this loop,
+ suspend the inferior process. */
+
+ quit_failed = 0;
+ if (quit_flag)
+ {
+ quit_failed = (net_quit () == -1);
+ quit_flag = 0;
+ }
+
+ /* If a net_quit () or net_wait () call has failed,
+ allow the user to break the connection with the target.
+ We can't simply error () out of this loop, since the
+ data structures representing the state of the inferior
+ are in an inconsistent state. */
+
+ if (quit_failed || net_wait (&rdbEvent) == -1)
+ {
+ terminal_ours ();
+ if (query ("Can't %s. Disconnect from target system? ",
+ (quit_failed) ? "suspend remote task"
+ : "get status of remote task"))
+ {
+ target_mourn_inferior();
+ error ("Use the \"target\" command to reconnect.");
+ }
+ else
+ {
+ terminal_inferior ();
+ continue;
+ }
+ }
+
+ pid = rdbEvent.taskId;
+ if (pid == 0)
+ {
+ sleep_ms (200); /* FIXME Don't kill the network too badly */
+ }
+ else if (pid != inferior_pid)
+ fatal ("Bad pid for debugged task: %s\n",
+ local_hex_string((unsigned long) pid));
+ } while (pid == 0);
+
+ /* The mostly likely kind. */
+ status->kind = TARGET_WAITKIND_STOPPED;
+
+ switch (rdbEvent.eventType)
+ {
+ case EVENT_EXIT:
+ status->kind = TARGET_WAITKIND_EXITED;
+ /* FIXME is it possible to distinguish between a
+ normal vs abnormal exit in VxWorks? */
+ status->value.integer = 0;
+ break;
+
+ case EVENT_START:
+ /* Task was just started. */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+
+ case EVENT_STOP:
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ /* XXX was it stopped by a signal? act accordingly */
+ break;
+
+ case EVENT_BREAK: /* Breakpoint was hit. */
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+
+ case EVENT_SUSPEND: /* Task was suspended, probably by ^C. */
+ status->value.sig = TARGET_SIGNAL_INT;
+ break;
+
+ case EVENT_BUS_ERR: /* Task made evil nasty reference. */
+ status->value.sig = TARGET_SIGNAL_BUS;
+ break;
+
+ case EVENT_ZERO_DIV: /* Division by zero */
+ status->value.sig = TARGET_SIGNAL_FPE;
+ break;
+
+ case EVENT_SIGNAL:
+#ifdef I80960
+ status->value.sig = i960_fault_to_signal (rdbEvent.sigType);
+#else
+ /* Back in the old days, before enum target_signal, this code used
+ to add NSIG to the signal number and claim that PRINT_RANDOM_SIGNAL
+ would take care of it. But PRINT_RANDOM_SIGNAL has never been
+ defined except on the i960, so I don't really know what we are
+ supposed to do on other architectures. */
+ status->value.sig = TARGET_SIGNAL_UNKNOWN;
+#endif
+ break;
+ } /* switch */
+ return pid;
+}
+
+static int
+symbol_stub (arg)
+ char *arg;
+{
+ symbol_file_command (arg, 0);
+ return 1;
+}
+
+static int
+add_symbol_stub (arg)
+ char *arg;
+{
+ struct ldfile *pLoadFile = (struct ldfile *)arg;
+
+ printf_unfiltered("\t%s: ", pLoadFile->name);
+ vx_add_symbols (pLoadFile->name, 0, pLoadFile->txt_addr,
+ pLoadFile->data_addr, pLoadFile->bss_addr);
+ printf_unfiltered ("ok\n");
+ return 1;
+}
+/* Target command for VxWorks target systems.
+
+ Used in vxgdb. Takes the name of a remote target machine
+ running vxWorks and connects to it to initialize remote network
+ debugging. */
+
+static void
+vx_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ extern int close ();
+ char *bootFile;
+ extern char *source_path;
+ struct ldtabl loadTable;
+ struct ldfile *pLoadFile;
+ int i;
+ extern CLIENT *pClient;
+ int symbols_added = 0;
+
+ if (!args)
+ error_no_arg ("target machine name");
+
+ target_preopen (from_tty);
+
+ unpush_target (&vx_ops);
+ printf_unfiltered ("Attaching remote machine across net...\n");
+ gdb_flush (gdb_stdout);
+
+ /* Allow the user to kill the connect attempt by typing ^C.
+ Wait until the call to target_has_fp () completes before
+ disallowing an immediate quit, since even if net_connect ()
+ is successful, the remote debug server might be hung. */
+
+ immediate_quit++;
+
+ net_connect (args);
+ target_has_fp = net_check_for_fp ();
+ printf_filtered ("Connected to %s.\n", args);
+
+ immediate_quit--;
+
+ push_target (&vx_ops);
+
+ /* Save a copy of the target host's name. */
+ vx_host = savestring (args, strlen (args));
+
+ /* Find out the name of the file from which the target was booted
+ and load its symbol table. */
+
+ printf_filtered ("Looking in Unix path for all loaded modules:\n");
+ bootFile = NULL;
+ if (!net_get_boot_file (&bootFile))
+ {
+ if (*bootFile)
+ {
+ printf_filtered ("\t%s: ", bootFile);
+ /* This assumes that the kernel is never relocated. Hope that is an
+ accurate assumption. */
+ if (catch_errors
+ (symbol_stub,
+ bootFile,
+ "Error while reading symbols from boot file:\n",
+ RETURN_MASK_ALL))
+ puts_filtered ("ok\n");
+ }
+ else if (from_tty)
+ printf_unfiltered ("VxWorks kernel symbols not loaded.\n");
+ }
+ else
+ error ("Can't retrieve boot file name from target machine.");
+
+ clnt_freeres (pClient, xdr_wrapstring, &bootFile);
+
+ if (net_get_symbols (&loadTable) != 0)
+ error ("Can't read loaded modules from target machine");
+
+ i = 0-1;
+ while (++i < loadTable.tbl_size)
+ {
+ QUIT; /* FIXME, avoids clnt_freeres below: mem leak */
+ pLoadFile = &loadTable.tbl_ent [i];
+#ifdef WRS_ORIG
+ {
+ register int desc;
+ struct cleanup *old_chain;
+ char *fullname = NULL;
+
+ desc = openp (source_path, 0, pLoadFile->name, O_RDONLY, 0, &fullname);
+ if (desc < 0)
+ perror_with_name (pLoadFile->name);
+ old_chain = make_cleanup (close, desc);
+ add_file_at_addr (fullname, desc, pLoadFile->txt_addr, pLoadFile->data_addr,
+ pLoadFile->bss_addr);
+ do_cleanups (old_chain);
+ }
+#else
+ /* FIXME: Is there something better to search than the PATH? (probably
+ not the source path, since source might be in different directories
+ than objects. */
+
+ if (catch_errors (add_symbol_stub, (char *)pLoadFile, (char *)0,
+ RETURN_MASK_ALL))
+ symbols_added = 1;
+#endif
+ }
+ printf_filtered ("Done.\n");
+
+ clnt_freeres (pClient, xdr_ldtabl, &loadTable);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (symbols_added)
+ reinit_frame_cache ();
+}
+
+/* Takes a task started up outside of gdb and ``attaches'' to it.
+ This stops it cold in its tracks and allows us to start tracing it. */
+
+static void
+vx_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ unsigned long pid;
+ char *cptr = 0;
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int status;
+
+ if (!args)
+ error_no_arg ("process-id to attach");
+
+ pid = strtoul (args, &cptr, 0);
+ if ((cptr == args) || (*cptr != '\0'))
+ error ("Invalid process-id -- give a single number in decimal or 0xhex");
+
+ if (from_tty)
+ printf_unfiltered ("Attaching pid %s.\n",
+ local_hex_string((unsigned long) pid));
+
+ memset ((char *)&ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
+ ptrace_in.pid = pid;
+
+ status = net_ptrace_clnt_call (PTRACE_ATTACH, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Attaching remote process");
+ }
+
+ /* It worked... */
+ push_target (&vx_run_ops);
+ /* The unsigned long pid will get turned into a signed int here,
+ but it doesn't seem to matter. inferior_pid must be signed
+ in order for other parts of GDB to work correctly. */
+ inferior_pid = pid;
+ vx_running = 0;
+#if defined (START_INFERIOR_HOOK)
+ START_INFERIOR_HOOK ();
+#endif
+
+ mark_breakpoints_out ();
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+
+ target_terminal_init ();
+
+ /* Install inferior's terminal modes. */
+
+ target_terminal_inferior ();
+
+ /* We will get a task spawn event immediately. */
+
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ wait_for_inferior ();
+ stop_soon_quietly = 0;
+ normal_stop ();
+}
+
+
+/* detach_command --
+ takes a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via the normal ptrace (PTRACE_TRACEME). */
+
+static void
+vx_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int signal = 0;
+ int status;
+
+ if (args)
+ error ("Argument given to VxWorks \"detach\".");
+
+ if (from_tty)
+ printf_unfiltered ("Detaching pid %s.\n",
+ local_hex_string((unsigned long) inferior_pid));
+
+ if (args) /* FIXME, should be possible to leave suspended */
+ signal = atoi (args);
+
+ memset ((char *)&ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
+ ptrace_in.pid = inferior_pid;
+
+ status = net_ptrace_clnt_call (PTRACE_DETACH, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ error (rpcerr);
+ if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Detaching VxWorks process");
+ }
+
+ inferior_pid = 0;
+ pop_target (); /* go back to non-executing VxWorks connection */
+}
+
+/* vx_kill -- takes a running task and wipes it out. */
+
+static void
+vx_kill ()
+{
+ Rptrace ptrace_in;
+ Ptrace_return ptrace_out;
+ int status;
+
+ printf_unfiltered ("Killing pid %s.\n", local_hex_string((unsigned long) inferior_pid));
+
+ memset ((char *)&ptrace_in, '\0', sizeof (ptrace_in));
+ memset ((char *)&ptrace_out, '\0', sizeof (ptrace_out));
+ ptrace_in.pid = inferior_pid;
+
+ status = net_ptrace_clnt_call (PTRACE_KILL, &ptrace_in, &ptrace_out);
+ if (status == -1)
+ warning (rpcerr);
+ else if (ptrace_out.status == -1)
+ {
+ errno = ptrace_out.errno;
+ perror_with_name ("Killing VxWorks process");
+ }
+
+ /* If it gives good status, the process is *gone*, no events remain.
+ If the kill failed, assume the process is gone anyhow. */
+ inferior_pid = 0;
+ pop_target (); /* go back to non-executing VxWorks connection */
+}
+
+/* Clean up from the VxWorks process target as it goes away. */
+
+static void
+vx_proc_close (quitting)
+ int quitting;
+{
+ inferior_pid = 0; /* No longer have a process. */
+ if (vx_running)
+ free (vx_running);
+ vx_running = 0;
+}
+
+/* Make an RPC call to the VxWorks target.
+ Returns RPC status. */
+
+static enum clnt_stat
+net_clnt_call (procNum, inProc, in, outProc, out)
+ enum ptracereq procNum;
+ xdrproc_t inProc;
+ char *in;
+ xdrproc_t outProc;
+ char *out;
+{
+ enum clnt_stat status;
+
+ status = clnt_call (pClient, procNum, inProc, in, outProc, out, rpcTimeout);
+
+ if (status != RPC_SUCCESS)
+ clnt_perrno (status);
+
+ return status;
+}
+
+/* Clean up before losing control. */
+
+static void
+vx_close (quitting)
+ int quitting;
+{
+ if (pClient)
+ clnt_destroy (pClient); /* The net connection */
+ pClient = 0;
+
+ if (vx_host)
+ free (vx_host); /* The hostname */
+ vx_host = 0;
+}
+
+/* A vxprocess target should be started via "run" not "target". */
+/*ARGSUSED*/
+static void
+vx_proc_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ error ("Use the \"run\" command to start a VxWorks process.");
+}
+
+/* Target ops structure for accessing memory and such over the net */
+
+struct target_ops vx_ops = {
+ "vxworks", "VxWorks target memory via RPC over TCP/IP",
+ "Use VxWorks target memory. \n\
+Specify the name of the machine to connect to.",
+ vx_open, vx_close, vx_attach, 0, /* vx_detach, */
+ 0, 0, /* resume, wait */
+ 0, 0, /* read_reg, write_reg */
+ 0, /* prep_to_store, */
+ vx_xfer_memory, vx_files_info,
+ 0, 0, /* insert_breakpoint, remove_breakpoint */
+ 0, 0, 0, 0, 0, /* terminal stuff */
+ 0, /* vx_kill, */
+ vx_load_command,
+ vx_lookup_symbol,
+ vx_create_inferior, 0, /* mourn_inferior */
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* thread_alive */
+ 0, /* to_stop */
+ core_stratum, 0, /* next */
+ 1, 1, 0, 0, 0, /* all mem, mem, stack, regs, exec */
+ 0, 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+
+/* Target ops structure for accessing VxWorks child processes over the net */
+
+struct target_ops vx_run_ops = {
+ "vxprocess", "VxWorks process",
+ "VxWorks process, started by the \"run\" command.",
+ vx_proc_open, vx_proc_close, 0, vx_detach, /* vx_attach */
+ vx_resume, vx_wait,
+ vx_read_register, vx_write_register,
+ vx_prepare_to_store,
+ vx_xfer_memory, vx_run_files_info,
+ vx_insert_breakpoint, vx_remove_breakpoint,
+ 0, 0, 0, 0, 0, /* terminal stuff */
+ vx_kill,
+ vx_load_command,
+ vx_lookup_symbol,
+ 0, vx_mourn_inferior,
+ 0, /* can_run */
+ 0, /* notice_signals */
+ 0, /* thread_alive */
+ 0, /* to_stop */
+ process_stratum, 0, /* next */
+ 0, /* all_mem--off to avoid spurious msg in "i files" */
+ 1, 1, 1, 1, /* mem, stack, regs, exec */
+ 0, 0, /* Section pointers */
+ OPS_MAGIC, /* Always the last thing */
+};
+/* ==> Remember when reading at end of file, there are two "ops" structs here. */
+
+void
+_initialize_vx ()
+{
+ add_show_from_set
+ (add_set_cmd ("vxworks-timeout", class_support, var_uinteger,
+ (char *) &rpcTimeout.tv_sec,
+ "Set seconds to wait for rpc calls to return.\n\
+Set the number of seconds to wait for rpc calls to return.", &setlist),
+ &showlist);
+
+ add_target (&vx_ops);
+ add_target (&vx_run_ops);
+}
diff --git a/contrib/gdb/gdb/remote-vx29k.c b/contrib/gdb/gdb/remote-vx29k.c
new file mode 100644
index 0000000..02554aa
--- /dev/null
+++ b/contrib/gdb/gdb/remote-vx29k.c
@@ -0,0 +1,188 @@
+/* Am29k-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char am29k_greg_packet[AM29K_GREG_PLEN];
+ char am29k_fpreg_packet[AM29K_FPREG_PLEN];
+
+ /* Get general-purpose registers. When copying values into
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ net_read_registers (am29k_greg_packet, AM29K_GREG_PLEN, PTRACE_GETREGS);
+
+ /* Now copy the register values into registers[].
+ Note that this code depends on the ordering of the REGNUMs
+ as defined in "tm-29k.h". */
+
+ bcopy (&am29k_greg_packet[AM29K_R_GR96],
+ &registers[REGISTER_BYTE (GR96_REGNUM)], 160 * AM29K_GREG_SIZE);
+ bcopy (&am29k_greg_packet[AM29K_R_VAB],
+ &registers[REGISTER_BYTE (VAB_REGNUM)], 15 * AM29K_GREG_SIZE);
+ registers[REGISTER_BYTE (INTE_REGNUM)] = am29k_greg_packet[AM29K_R_INTE];
+ bcopy (&am29k_greg_packet[AM29K_R_RSP],
+ &registers[REGISTER_BYTE (GR1_REGNUM)], 5 * AM29K_GREG_SIZE);
+
+ /* PAD For now, don't care about exop register */
+
+ memset (&registers[REGISTER_BYTE (EXO_REGNUM)], '\0', AM29K_GREG_SIZE);
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (am29k_fpreg_packet, AM29K_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+ registers[REGISTER_BYTE (FPE_REGNUM)] = am29k_fpreg_packet[AM29K_R_FPE];
+ registers[REGISTER_BYTE (FPS_REGNUM)] = am29k_fpreg_packet[AM29K_R_FPS];
+
+ /* PAD For now, don't care about registers (?) AI0 to q */
+
+ memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
+ }
+ else
+ {
+ memset (&registers[REGISTER_BYTE (FPE_REGNUM)], '\0', AM29K_FPREG_SIZE);
+ memset (&registers[REGISTER_BYTE (FPS_REGNUM)], '\0', AM29K_FPREG_SIZE);
+
+ /* PAD For now, don't care about registers (?) AI0 to q */
+
+ memset (&registers[REGISTER_BYTE (161)], '\0', 21 * AM29K_FPREG_SIZE);
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char am29k_greg_packet[AM29K_GREG_PLEN];
+ char am29k_fpreg_packet[AM29K_FPREG_PLEN];
+
+ /* Store general purpose registers. When copying values from
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ bcopy (&registers[REGISTER_BYTE (GR96_REGNUM)],
+ &am29k_greg_packet[AM29K_R_GR96], 160 * AM29K_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (VAB_REGNUM)],
+ &am29k_greg_packet[AM29K_R_VAB], 15 * AM29K_GREG_SIZE);
+ am29k_greg_packet[AM29K_R_INTE] = registers[REGISTER_BYTE (INTE_REGNUM)];
+ bcopy (&registers[REGISTER_BYTE (GR1_REGNUM)],
+ &am29k_greg_packet[AM29K_R_RSP], 5 * AM29K_GREG_SIZE);
+
+ net_write_registers (am29k_greg_packet, AM29K_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ am29k_fpreg_packet[AM29K_R_FPE] = registers[REGISTER_BYTE (FPE_REGNUM)];
+ am29k_fpreg_packet[AM29K_R_FPS] = registers[REGISTER_BYTE (FPS_REGNUM)];
+
+ net_write_registers (am29k_fpreg_packet, AM29K_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
+
+/* VxWorks zeroes fp when the task is initialized; we use this
+ to terminate the frame chain. Chain means here the nominal address of
+ a frame, that is, the return address (lr0) address in the stack. To
+ obtain the frame pointer (lr1) contents, we must add 4 bytes.
+ Note : may be we should modify init_frame_info() to get the frame pointer
+ and store it into the frame_info struct rather than reading its
+ contents when FRAME_CHAIN_VALID is invoked. */
+
+int
+get_fp_contents (chain, thisframe)
+ CORE_ADDR chain;
+ struct frame_info *thisframe; /* not used here */
+{
+ int fp_contents;
+
+ read_memory ((CORE_ADDR)(chain + 4), (char *) &fp_contents, 4);
+ return (fp_contents != 0);
+}
+
diff --git a/contrib/gdb/gdb/remote-vx68.c b/contrib/gdb/gdb/remote-vx68.c
new file mode 100644
index 0000000..c6ceda1
--- /dev/null
+++ b/contrib/gdb/gdb/remote-vx68.c
@@ -0,0 +1,158 @@
+/* 68k-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+
+#ifdef _AIX
+#undef malloc
+#endif
+
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char mc68k_greg_packet[MC68K_GREG_PLEN];
+ char mc68k_fpreg_packet[MC68K_FPREG_PLEN];
+
+ /* Get general-purpose registers. */
+
+ net_read_registers (mc68k_greg_packet, MC68K_GREG_PLEN, PTRACE_GETREGS);
+
+ bcopy (&mc68k_greg_packet[MC68K_R_D0], registers, 16 * MC68K_GREG_SIZE);
+ bcopy (&mc68k_greg_packet[MC68K_R_SR], &registers[REGISTER_BYTE (PS_REGNUM)],
+ MC68K_GREG_SIZE);
+ bcopy (&mc68k_greg_packet[MC68K_R_PC], &registers[REGISTER_BYTE (PC_REGNUM)],
+ MC68K_GREG_SIZE);
+
+ /* Get floating-point registers, if the target system has them.
+ Otherwise, zero them. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (mc68k_fpreg_packet, MC68K_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+
+ bcopy (&mc68k_fpreg_packet[MC68K_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ MC68K_FPREG_SIZE * 8);
+ bcopy (&mc68k_fpreg_packet[MC68K_R_FPCR],
+ &registers[REGISTER_BYTE (FPC_REGNUM)],
+ MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
+ }
+ else
+ {
+ bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ MC68K_FPREG_SIZE * 8);
+ bzero (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char mc68k_greg_packet[MC68K_GREG_PLEN];
+ char mc68k_fpreg_packet[MC68K_FPREG_PLEN];
+
+ /* Store general-purpose registers. */
+
+ bcopy (registers, &mc68k_greg_packet[MC68K_R_D0], 16 * MC68K_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PS_REGNUM)],
+ &mc68k_greg_packet[MC68K_R_SR], MC68K_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &mc68k_greg_packet[MC68K_R_PC], MC68K_GREG_SIZE);
+
+ net_write_registers (mc68k_greg_packet, MC68K_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &mc68k_fpreg_packet[MC68K_R_FP0],
+ MC68K_FPREG_SIZE * 8);
+ bcopy (&registers[REGISTER_BYTE (FPC_REGNUM)],
+ &mc68k_fpreg_packet[MC68K_R_FPCR],
+ MC68K_FPREG_PLEN - (MC68K_FPREG_SIZE * 8));
+
+ net_write_registers (mc68k_fpreg_packet, MC68K_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
diff --git a/contrib/gdb/gdb/remote-vx960.c b/contrib/gdb/gdb/remote-vx960.c
new file mode 100644
index 0000000..bb4fbee
--- /dev/null
+++ b/contrib/gdb/gdb/remote-vx960.c
@@ -0,0 +1,163 @@
+/* i80960-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* 960 floating point format descriptor, from "i960-tdep.c." */
+
+extern struct ext_format ext_format_i960;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char i960_greg_packet[I960_GREG_PLEN];
+ char i960_fpreg_packet[I960_FPREG_PLEN];
+
+ /* Get general-purpose registers. When copying values into
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ net_read_registers (i960_greg_packet, I960_GREG_PLEN, PTRACE_GETREGS);
+
+ bcopy (&i960_greg_packet[I960_R_R0],
+ &registers[REGISTER_BYTE (R0_REGNUM)], 16 * I960_GREG_SIZE);
+ bcopy (&i960_greg_packet[I960_R_G0],
+ &registers[REGISTER_BYTE (G0_REGNUM)], 16 * I960_GREG_SIZE);
+ bcopy (&i960_greg_packet[I960_R_PCW],
+ &registers[REGISTER_BYTE (PCW_REGNUM)], sizeof (int));
+ bcopy (&i960_greg_packet[I960_R_ACW],
+ &registers[REGISTER_BYTE (ACW_REGNUM)], sizeof (int));
+ bcopy (&i960_greg_packet[I960_R_TCW],
+ &registers[REGISTER_BYTE (TCW_REGNUM)], sizeof (int));
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (i960_fpreg_packet, I960_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+ bcopy (&i960_fpreg_packet[I960_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+ }
+ else
+ bzero (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char i960_greg_packet[I960_GREG_PLEN];
+ char i960_fpreg_packet[I960_FPREG_PLEN];
+
+ /* Store floating-point registers. When copying values from
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ bcopy (&registers[REGISTER_BYTE (R0_REGNUM)],
+ &i960_greg_packet[I960_R_R0], 16 * I960_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
+ &i960_greg_packet[I960_R_G0], 16 * I960_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)],
+ &i960_greg_packet[I960_R_PCW], sizeof (int));
+ bcopy (&registers[REGISTER_BYTE (ACW_REGNUM)],
+ &i960_greg_packet[I960_R_ACW], sizeof (int));
+ bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)],
+ &i960_greg_packet[I960_R_TCW], sizeof (int));
+
+ net_write_registers (i960_greg_packet, I960_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &i960_fpreg_packet[I960_R_FP0],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 4);
+
+ net_write_registers (i960_fpreg_packet, I960_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
+
diff --git a/contrib/gdb/gdb/remote-vxmips.c b/contrib/gdb/gdb/remote-vxmips.c
new file mode 100644
index 0000000..c65ac01
--- /dev/null
+++ b/contrib/gdb/gdb/remote-vxmips.c
@@ -0,0 +1,201 @@
+/* MIPS-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char mips_greg_packet[MIPS_GREG_PLEN];
+ char mips_fpreg_packet[MIPS_FPREG_PLEN];
+
+ /* Get general-purpose registers. */
+
+ net_read_registers (mips_greg_packet, MIPS_GREG_PLEN, PTRACE_GETREGS);
+
+ /* this code copies the registers obtained by RPC
+ stored in a structure(s) like this :
+
+ Register(s) Offset(s)
+ gp 0-31 0x00
+ hi 0x80
+ lo 0x84
+ sr 0x88
+ pc 0x8c
+
+ into a stucture like this:
+
+ 0x00 GP 0-31
+ 0x80 SR
+ 0x84 LO
+ 0x88 HI
+ 0x8C BAD --- Not available currently
+ 0x90 CAUSE --- Not available currently
+ 0x94 PC
+ 0x98 FP 0-31
+ 0x118 FCSR
+ 0x11C FIR --- Not available currently
+ 0x120 FP --- Not available currently
+
+ structure is 0x124 (292) bytes in length */
+
+ /* Copy the general registers. */
+
+ bcopy (&mips_greg_packet[MIPS_R_GP0], &registers[0], 32 * MIPS_GREG_SIZE);
+
+ /* Copy SR, LO, HI, and PC. */
+
+ bcopy (&mips_greg_packet[MIPS_R_SR],
+ &registers[REGISTER_BYTE (PS_REGNUM)], MIPS_GREG_SIZE);
+ bcopy (&mips_greg_packet[MIPS_R_LO],
+ &registers[REGISTER_BYTE (LO_REGNUM)], MIPS_GREG_SIZE);
+ bcopy (&mips_greg_packet[MIPS_R_HI],
+ &registers[REGISTER_BYTE (HI_REGNUM)], MIPS_GREG_SIZE);
+ bcopy (&mips_greg_packet[MIPS_R_PC],
+ &registers[REGISTER_BYTE (PC_REGNUM)], MIPS_GREG_SIZE);
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (mips_fpreg_packet, MIPS_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+
+ /* Copy the floating point registers. */
+
+ bcopy (&mips_fpreg_packet[MIPS_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+
+ /* Copy the floating point control/status register (fpcsr). */
+
+ bcopy (&mips_fpreg_packet[MIPS_R_FPCSR],
+ &registers[REGISTER_BYTE (FCRCS_REGNUM)],
+ REGISTER_RAW_SIZE (FCRCS_REGNUM));
+ }
+ else
+ {
+ bzero ((char *) &registers[REGISTER_BYTE (FP0_REGNUM)],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+ bzero ((char *) &registers[REGISTER_BYTE (FCRCS_REGNUM)],
+ REGISTER_RAW_SIZE (FCRCS_REGNUM));
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+vx_write_register (regno)
+ int regno;
+{
+ char mips_greg_packet[MIPS_GREG_PLEN];
+ char mips_fpreg_packet[MIPS_FPREG_PLEN];
+
+ /* Store general registers. */
+
+ bcopy (&registers[0], &mips_greg_packet[MIPS_R_GP0], 32 * MIPS_GREG_SIZE);
+
+ /* Copy SR, LO, HI, and PC. */
+
+ bcopy (&registers[REGISTER_BYTE (PS_REGNUM)],
+ &mips_greg_packet[MIPS_R_SR], MIPS_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (LO_REGNUM)],
+ &mips_greg_packet[MIPS_R_LO], MIPS_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (HI_REGNUM)],
+ &mips_greg_packet[MIPS_R_HI], MIPS_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (PC_REGNUM)],
+ &mips_greg_packet[MIPS_R_PC], MIPS_GREG_SIZE);
+
+ net_write_registers (mips_greg_packet, MIPS_GREG_PLEN, PTRACE_SETREGS);
+
+ /* Store floating point registers if the target has them. */
+
+ if (target_has_fp)
+ {
+ /* Copy the floating point data registers. */
+
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &mips_fpreg_packet[MIPS_R_FP0],
+ REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+
+ /* Copy the floating point control/status register (fpcsr). */
+
+ bcopy (&registers[REGISTER_BYTE (FCRCS_REGNUM)],
+ &mips_fpreg_packet[MIPS_R_FPCSR],
+ REGISTER_RAW_SIZE (FCRCS_REGNUM));
+
+ net_write_registers (mips_fpreg_packet, MIPS_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
diff --git a/contrib/gdb/gdb/remote-vxsparc.c b/contrib/gdb/gdb/remote-vxsparc.c
new file mode 100644
index 0000000..0682542
--- /dev/null
+++ b/contrib/gdb/gdb/remote-vxsparc.c
@@ -0,0 +1,196 @@
+/* sparc-dependent portions of the RPC protocol
+ used with a VxWorks target
+
+Contributed by Wind River Systems.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include "defs.h"
+
+#include "vx-share/regPacket.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+#include "target.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "symtab.h"
+#include "symfile.h" /* for struct complaint */
+
+#include "gdb_string.h"
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#ifdef _AIX /* IBM claims "void *malloc()" not char * */
+#define malloc bogon_malloc
+#endif
+
+#include <rpc/rpc.h>
+#include <sys/time.h> /* UTek's <rpc/rpc.h> doesn't #incl this */
+#include <netdb.h>
+#include "vx-share/ptrace.h"
+#include "vx-share/xdr_ptrace.h"
+#include "vx-share/xdr_ld.h"
+#include "vx-share/xdr_rdb.h"
+#include "vx-share/dbgRpcLib.h"
+
+/* get rid of value.h if possible */
+#include <value.h>
+#include <symtab.h>
+
+/* Flag set if target has fpu */
+
+extern int target_has_fp;
+
+/* sparc floating point format descriptor, from "sparc-tdep.c." */
+
+extern struct ext_format ext_format_sparc;
+
+/* Generic register read/write routines in remote-vx.c. */
+
+extern void net_read_registers ();
+extern void net_write_registers ();
+
+/* Read a register or registers from the VxWorks target.
+ REGNO is the register to read, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_read_register (regno)
+ int regno;
+{
+ char sparc_greg_packet[SPARC_GREG_PLEN];
+ char sparc_fpreg_packet[SPARC_FPREG_PLEN];
+ CORE_ADDR sp;
+
+ /* Get general-purpose registers. When copying values into
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ net_read_registers (sparc_greg_packet, SPARC_GREG_PLEN, PTRACE_GETREGS);
+
+ /* Now copy the register values into registers[].
+ Note that this code depends on the ordering of the REGNUMs
+ as defined in "tm-sparc.h". */
+
+ bcopy (&sparc_greg_packet[SPARC_R_G0],
+ &registers[REGISTER_BYTE (G0_REGNUM)], 32 * SPARC_GREG_SIZE);
+ bcopy (&sparc_greg_packet[SPARC_R_Y],
+ &registers[REGISTER_BYTE (Y_REGNUM)], 6 * SPARC_GREG_SIZE);
+
+ /* Now write the local and in registers to the register window
+ spill area in the frame. VxWorks does not do this for the
+ active frame automatically; it greatly simplifies debugging
+ (FRAME_FIND_SAVED_REGS, in particular, depends on this). */
+
+ sp = extract_address (&registers[REGISTER_BYTE (SP_REGNUM)],
+ REGISTER_RAW_SIZE (CORE_ADDR));
+ write_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM));
+
+ /* If the target has floating point registers, fetch them.
+ Otherwise, zero the floating point register values in
+ registers[] for good measure, even though we might not
+ need to. */
+
+ if (target_has_fp)
+ {
+ net_read_registers (sparc_fpreg_packet, SPARC_FPREG_PLEN,
+ PTRACE_GETFPREGS);
+ bcopy (&sparc_fpreg_packet[SPARC_R_FP0],
+ &registers[REGISTER_BYTE (FP0_REGNUM)], 32 * SPARC_FPREG_SIZE);
+ bcopy (&sparc_fpreg_packet[SPARC_R_FSR],
+ &registers[REGISTER_BYTE (FPS_REGNUM)], 1 * SPARC_FPREG_SIZE);
+ }
+ else
+ {
+ bzero (&registers[REGISTER_BYTE (FP0_REGNUM)], 32 * SPARC_FPREG_SIZE);
+ bzero (&registers[REGISTER_BYTE (FPS_REGNUM)], 1 * SPARC_FPREG_SIZE);
+ }
+
+ /* Mark the register cache valid. */
+
+ registers_fetched ();
+}
+
+/* Store a register or registers into the VxWorks target.
+ REGNO is the register to store, or -1 for all; currently,
+ it is ignored. FIXME look at regno to improve efficiency. */
+
+void
+vx_write_register (regno)
+ int regno;
+{
+ char sparc_greg_packet[SPARC_GREG_PLEN];
+ char sparc_fpreg_packet[SPARC_FPREG_PLEN];
+ int in_gp_regs;
+ int in_fp_regs;
+ CORE_ADDR sp;
+
+ /* Store general purpose registers. When copying values from
+ registers [], don't assume that a location in registers []
+ is properly aligned for the target data type. */
+
+ in_gp_regs = 1;
+ in_fp_regs = 1;
+ if (regno >= 0)
+ {
+ if ((G0_REGNUM <= regno && regno <= I7_REGNUM)
+ || (Y_REGNUM <= regno && regno <= NPC_REGNUM))
+ in_fp_regs = 0;
+ else
+ in_gp_regs = 0;
+ }
+ if (in_gp_regs)
+ {
+ bcopy (&registers[REGISTER_BYTE (G0_REGNUM)],
+ &sparc_greg_packet[SPARC_R_G0], 32 * SPARC_GREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (Y_REGNUM)],
+ &sparc_greg_packet[SPARC_R_Y], 6 * SPARC_GREG_SIZE);
+
+ net_write_registers (sparc_greg_packet, SPARC_GREG_PLEN, PTRACE_SETREGS);
+
+ /* If this is a local or in register, or we're storing all
+ registers, update the register window spill area. */
+
+ if (regno < 0 || (L0_REGNUM <= regno && regno <= I7_REGNUM))
+ {
+ sp = extract_address (&registers[REGISTER_BYTE (SP_REGNUM)],
+ REGISTER_RAW_SIZE (CORE_ADDR));
+ write_memory (sp, &registers[REGISTER_BYTE (L0_REGNUM)],
+ 16 * REGISTER_RAW_SIZE (L0_REGNUM));
+ }
+ }
+
+ /* Store floating point registers if the target has them. */
+
+ if (in_fp_regs && target_has_fp)
+ {
+ bcopy (&registers[REGISTER_BYTE (FP0_REGNUM)],
+ &sparc_fpreg_packet[SPARC_R_FP0], 32 * SPARC_FPREG_SIZE);
+ bcopy (&registers[REGISTER_BYTE (FPS_REGNUM)],
+ &sparc_fpreg_packet[SPARC_R_FSR], 1 * SPARC_FPREG_SIZE);
+
+ net_write_registers (sparc_fpreg_packet, SPARC_FPREG_PLEN,
+ PTRACE_SETFPREGS);
+ }
+}
diff --git a/contrib/gdb/gdb/remote.c b/contrib/gdb/gdb/remote.c
new file mode 100644
index 0000000..5356e5e
--- /dev/null
+++ b/contrib/gdb/gdb/remote.c
@@ -0,0 +1,1839 @@
+/* Remote target communications for serial-line targets in custom GDB protocol
+ Copyright 1988, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Remote communication protocol.
+
+ A debug packet whose contents are <data>
+ is encapsulated for transmission in the form:
+
+ $ <data> # CSUM1 CSUM2
+
+ <data> must be ASCII alphanumeric and cannot include characters
+ '$' or '#'. If <data> 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 <data>, the most significant nibble is sent first.
+ the hex digits 0-9,a-f are used.
+
+ Receiver responds with:
+
+ + - if CSUM is correct and ready for next packet
+ - - if CSUM is incorrect
+
+ <data> is as follows:
+ Most values are encoded in ascii hex digits. Signal numbers are according
+ to the numbering in target.h.
+
+ Request Packet
+
+ set thread Hct... Set thread for subsequent operations.
+ c = 'c' for thread used in step and
+ continue; t... can be -1 for all
+ threads.
+ c = 'g' for thread used in other
+ operations. If zero, pick a thread,
+ any thread.
+ reply OK for success
+ ENN for an error.
+
+ read registers g
+ reply XX....X Each byte of register data
+ is described by two hex digits.
+ Registers are in the internal order
+ for GDB, and the bytes in a register
+ are in the same order the machine uses.
+ or ENN for an error.
+
+ write regs GXX..XX Each byte of register data
+ is described by two hex digits.
+ 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
+ if able to read only part of the data.
+ or ENN NN is errno
+
+ write mem MAA..AA,LLLL:XX..XX
+ AA..AA is address,
+ LLLL is number of bytes,
+ XX..XX is data
+ reply OK for success
+ ENN for an error (this includes the case
+ where only part of the data was
+ written).
+
+ continue cAA..AA AA..AA is address to resume
+ If AA..AA is omitted,
+ resume at same address.
+
+ step sAA..AA AA..AA is address to resume
+ If AA..AA is omitted,
+ resume at same address.
+
+ continue with Csig;AA Continue with signal sig (hex signal
+ signal number).
+
+ step with Ssig;AA Like 'C' but step not continue.
+ signal
+
+ last signal ? Reply the current reason for stopping.
+ This is the same reply as is generated
+ for step or cont : SAA where AA is the
+ signal number.
+
+ detach D Reply OK.
+
+ There is no immediate reply to step or cont.
+ The reply comes when the machine stops.
+ It is SAA AA is the signal number.
+
+ or... TAAn...:r...;n...:r...;n...:r...;
+ AA = signal number
+ n... = register number (hex)
+ r... = register contents
+ n... = `thread'
+ r... = thread process ID. This is
+ a hex integer.
+ n... = other string not starting
+ with valid hex digit.
+ gdb should ignore this n,r pair
+ and go on to the next. This way
+ we can extend the protocol.
+ or... WAA The process exited, and AA is
+ the exit status. This is only
+ applicable for certains sorts of
+ targets.
+ or... XAA The process terminated with signal
+ AA.
+ or... OXX..XX XX..XX is hex encoding of ASCII data. This
+ can happen at any time while the program is
+ running and the debugger should
+ continue to wait for 'W', 'T', etc.
+
+ thread alive TXX Find out if the thread XX is alive.
+ reply OK thread is still alive
+ ENN thread is dead
+
+ remote restart RXX Restart the remote server
+
+ extended ops ! Use the extended remote protocol.
+ Sticky -- only needs to be set once.
+
+ kill request k
+
+ toggle debug d toggle debug flag (see 386 & 68k stubs)
+ reset r reset -- see sparc stub.
+ reserved <other> On other requests, the stub should
+ ignore the request and send an empty
+ response ($#<checksum>). This way
+ 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
+
+ Responses can be run-length encoded to save space. A '*' means that
+ the next character is an ASCII encoding giving a repeat count which
+ stands for that many repititions of the character preceding the '*'.
+ The encoding is n+29, yielding a printable character where n >=3
+ (which is where rle starts to win). Don't use an n > 126.
+
+ So
+ "0* " means the same as "0000". */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include <fcntl.h>
+#include "frame.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "target.h"
+#include "wait.h"
+/*#include "terminal.h"*/
+#include "gdbcmd.h"
+#include "objfiles.h"
+#include "gdb-stabs.h"
+#include "thread.h"
+
+#include "dcache.h"
+
+#ifdef USG
+#include <sys/types.h>
+#endif
+
+#include <signal.h>
+#include "serial.h"
+
+/* Prototypes for local functions */
+
+static int remote_write_bytes PARAMS ((CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static int remote_read_bytes PARAMS ((CORE_ADDR memaddr,
+ char *myaddr, int len));
+
+static void remote_files_info PARAMS ((struct target_ops *ignore));
+
+static int remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, int should_write,
+ struct target_ops *target));
+
+static void remote_prepare_to_store PARAMS ((void));
+
+static void remote_fetch_registers PARAMS ((int regno));
+
+static void remote_resume PARAMS ((int pid, int step,
+ enum target_signal siggnal));
+
+static int remote_start_remote PARAMS ((char *dummy));
+
+static void remote_open PARAMS ((char *name, int from_tty));
+
+static void extended_remote_open PARAMS ((char *name, int from_tty));
+
+static void remote_open_1 PARAMS ((char *, int, struct target_ops *));
+
+static void remote_close PARAMS ((int quitting));
+
+static void remote_store_registers PARAMS ((int regno));
+
+static void remote_mourn PARAMS ((void));
+
+static void extended_remote_restart PARAMS ((void));
+
+static void extended_remote_mourn PARAMS ((void));
+
+static void extended_remote_create_inferior PARAMS ((char *, char *, char **));
+
+static void remote_mourn_1 PARAMS ((struct target_ops *));
+
+static void getpkt PARAMS ((char *buf, int forever));
+
+static int putpkt PARAMS ((char *buf));
+
+static void remote_send PARAMS ((char *buf));
+
+static int readchar PARAMS ((int timeout));
+
+static int remote_wait PARAMS ((int pid, struct target_waitstatus *status));
+
+static void remote_kill PARAMS ((void));
+
+static int tohex PARAMS ((int nib));
+
+static int fromhex PARAMS ((int a));
+
+static void remote_detach PARAMS ((char *args, int from_tty));
+
+static void remote_interrupt PARAMS ((int signo));
+
+static void remote_interrupt_twice PARAMS ((int signo));
+
+static void interrupt_query PARAMS ((void));
+
+extern struct target_ops remote_ops; /* Forward decl */
+extern struct target_ops extended_remote_ops; /* Forward decl */
+
+/* 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 remote_timeout = 2;
+
+/* This variable chooses whether to send a ^C or a break when the user
+ requests program interruption. Although ^C is usually what remote
+ systems expect, and that is the default here, sometimes a break is
+ preferable instead. */
+
+static int remote_break;
+
+/* Descriptor for I/O to remote machine. Initialize it to NULL so that
+ remote_open knows that we don't have a file open when the program
+ starts. */
+serial_t remote_desc = NULL;
+
+/* 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
+#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;
+
+
+/* These are the threads which we last sent to the remote system. -1 for all
+ or -2 for not sent yet. */
+int general_thread;
+int cont_thread;
+
+static void
+set_thread (th, gen)
+ int th;
+ int gen;
+{
+ char buf[PBUFSIZ];
+ int state = gen ? general_thread : cont_thread;
+ if (state == th)
+ return;
+ buf[0] = 'H';
+ buf[1] = gen ? 'g' : 'c';
+ if (th == 42000)
+ {
+ buf[2] = '0';
+ buf[3] = '\0';
+ }
+ else if (th < 0)
+ sprintf (&buf[2], "-%x", -th);
+ else
+ sprintf (&buf[2], "%x", th);
+ putpkt (buf);
+ getpkt (buf, 0);
+ if (gen)
+ general_thread = th;
+ else
+ cont_thread = th;
+}
+
+/* Return nonzero if the thread TH is still alive on the remote system. */
+
+static int
+remote_thread_alive (th)
+ int th;
+{
+ char buf[PBUFSIZ];
+
+ buf[0] = 'T';
+ if (th < 0)
+ sprintf (&buf[1], "-%x", -th);
+ else
+ sprintf (&buf[1], "%x", th);
+ putpkt (buf);
+ getpkt (buf, 0);
+ return (buf[0] == 'O' && buf[1] == 'K');
+}
+
+/* Restart the remote side; this is an extended protocol operation. */
+
+static void
+extended_remote_restart ()
+{
+ char buf[PBUFSIZ];
+
+ /* Send the restart command; for reasons I don't understand the
+ remote side really expects a number after the "R". */
+ buf[0] = 'R';
+ sprintf (&buf[1], "%x", 0);
+ putpkt (buf);
+
+ /* Now query for status so this looks just like we restarted
+ gdbserver from scratch. */
+ putpkt ("?");
+ getpkt (buf, 0);
+}
+
+/* Clean up connection to a remote debugger. */
+
+/* ARGSUSED */
+static void
+remote_close (quitting)
+ int quitting;
+{
+ if (remote_desc)
+ SERIAL_CLOSE (remote_desc);
+ remote_desc = NULL;
+}
+
+/* Query the remote side for the text, data and bss offsets. */
+
+static void
+get_offsets ()
+{
+ 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));
+
+ 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
+remote_start_remote (dummy)
+ char *dummy;
+{
+ immediate_quit = 1; /* Allow user to interrupt it */
+
+ /* Ack any packet which the remote side has already sent. */
+ SERIAL_WRITE (remote_desc, "+", 1);
+
+ /* Let the stub know that we want it to return the thread. */
+ set_thread (-1, 0);
+
+ 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;
+}
+
+/* Open a connection to a remote debugger.
+ NAME is the filename used for communication. */
+
+static void
+remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ remote_open_1 (name, from_tty, &remote_ops);
+}
+
+/* Open a connection to a remote debugger using the extended
+ remote gdb protocol. NAME is the filename used for communication. */
+
+static void
+extended_remote_open (name, from_tty)
+ char *name;
+ int from_tty;
+{
+ char buf[PBUFSIZ];
+
+ /* Do the basic remote open stuff. */
+ remote_open_1 (name, from_tty, &extended_remote_ops);
+
+ /* Now tell the remote that we're using the extended protocol. */
+ putpkt ("!");
+ getpkt (buf, 0);
+
+}
+
+/* Generic code for opening a connection to a remote target. */
+static DCACHE *remote_dcache;
+
+static void
+remote_open_1 (name, from_tty, target)
+ char *name;
+ int from_tty;
+ struct target_ops *target;
+{
+ if (name == 0)
+ error ("To open a remote debug connection, you need to specify what serial\n\
+device is attached to the remote system (e.g. /dev/ttya).");
+
+ target_preopen (from_tty);
+
+ unpush_target (target);
+
+ remote_dcache = dcache_init (remote_read_bytes, remote_write_bytes);
+
+ remote_desc = SERIAL_OPEN (name);
+ if (!remote_desc)
+ perror_with_name (name);
+
+ if (baud_rate != -1)
+ {
+ if (SERIAL_SETBAUDRATE (remote_desc, baud_rate))
+ {
+ SERIAL_CLOSE (remote_desc);
+ perror_with_name (name);
+ }
+ }
+
+
+ SERIAL_RAW (remote_desc);
+
+ /* If there is something sitting in the buffer we might take it as a
+ response to a command, which would be bad. */
+ SERIAL_FLUSH_INPUT (remote_desc);
+
+ if (from_tty)
+ {
+ puts_filtered ("Remote debugging using ");
+ puts_filtered (name);
+ puts_filtered ("\n");
+ }
+ push_target (target); /* 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;
+
+ general_thread = -2;
+ cont_thread = -2;
+
+ /* Without this, some commands which require an active target (such as kill)
+ won't work. This variable serves (at least) double duty as both the pid
+ of the target process (if it has such), and as a flag indicating that a
+ target is active. These functions should be split out into seperate
+ variables, especially since GDB will someday have a notion of debugging
+ several processes. */
+
+ inferior_pid = 42000;
+ /* 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). */
+ if (!catch_errors (remote_start_remote, (char *)0,
+ "Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
+ pop_target();
+}
+
+/* This takes a program previously attached to and detaches it. After
+ this is done, GDB can be used to debug some other program. We
+ better not have left any breakpoints in the target program or it'll
+ die when it hits one. */
+
+static void
+remote_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char buf[PBUFSIZ];
+
+ if (args)
+ error ("Argument given to \"detach\" when remotely debugging.");
+
+ /* Tell the remote target to detach. */
+ strcpy (buf, "D");
+ remote_send (buf);
+
+ pop_target ();
+ if (from_tty)
+ puts_filtered ("Ending remote debugging.\n");
+}
+
+/* Convert hex digit A to a number. */
+
+static int
+fromhex (a)
+ int a;
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else
+ error ("Reply contains invalid hex digit %d", a);
+}
+
+/* Convert number NIB to a hex digit. */
+
+static int
+tohex (nib)
+ int nib;
+{
+ if (nib < 10)
+ return '0'+nib;
+ else
+ return 'a'+nib-10;
+}
+
+/* Tell the remote machine to resume. */
+
+static enum target_signal last_sent_signal = TARGET_SIGNAL_0;
+int last_sent_step;
+
+static void
+remote_resume (pid, step, siggnal)
+ int pid, step;
+ enum target_signal siggnal;
+{
+ char buf[PBUFSIZ];
+
+ if (pid == -1)
+ set_thread (inferior_pid, 0);
+ else
+ set_thread (pid, 0);
+
+ dcache_flush (remote_dcache);
+
+ last_sent_signal = siggnal;
+ last_sent_step = step;
+
+ if (siggnal != TARGET_SIGNAL_0)
+ {
+ buf[0] = step ? 'S' : 'C';
+ buf[1] = tohex (((int)siggnal >> 4) & 0xf);
+ buf[2] = tohex ((int)siggnal & 0xf);
+ buf[3] = '\0';
+ }
+ else
+ strcpy (buf, step ? "s": "c");
+
+ putpkt (buf);
+}
+
+/* Send ^C to target to halt it. Target will respond, and send us a
+ packet. */
+
+static void
+remote_interrupt (signo)
+ int signo;
+{
+ /* If this doesn't work, try more severe steps. */
+ signal (signo, remote_interrupt_twice);
+
+ if (remote_debug)
+ printf_unfiltered ("remote_interrupt called\n");
+
+ /* Send a break or a ^C, depending on user preference. */
+ if (remote_break)
+ SERIAL_SEND_BREAK (remote_desc);
+ else
+ SERIAL_WRITE (remote_desc, "\003", 1);
+}
+
+static void (*ofunc)();
+
+/* The user typed ^C twice. */
+static void
+remote_interrupt_twice (signo)
+ int signo;
+{
+ signal (signo, ofunc);
+
+ interrupt_query ();
+
+ signal (signo, remote_interrupt);
+}
+
+/* Ask the user what to do when an interrupt is received. */
+
+static void
+interrupt_query ()
+{
+ target_terminal_ours ();
+
+ if (query ("Interrupted while waiting for the program.\n\
+Give up (and stop debugging it)? "))
+ {
+ target_mourn_inferior ();
+ return_to_top_level (RETURN_QUIT);
+ }
+
+ target_terminal_inferior ();
+}
+
+/* If nonzero, ignore the next kill. */
+int kill_kludge;
+
+/* Wait until the remote machine stops, then return,
+ storing status in STATUS just as `wait' would.
+ Returns "pid" (though it's not clear what, if anything, that
+ means in the case of this target). */
+
+static int
+remote_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ unsigned char buf[PBUFSIZ];
+ int thread_num = -1;
+
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = 0;
+
+ while (1)
+ {
+ unsigned char *p;
+
+ ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
+ getpkt ((char *) buf, 1);
+ signal (SIGINT, ofunc);
+
+ switch (buf[0])
+ {
+ 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
+ */
+
+ p = &buf[3]; /* after Txx */
+
+ while (*p)
+ {
+ unsigned char *p1;
+ char *p_temp;
+
+ regno = strtol ((const char *) p, &p_temp, 16); /* Read the register number */
+ p1 = (unsigned char *)p_temp;
+
+ if (p1 == p)
+ {
+ p1 = (unsigned char *) strchr ((const char *) p, ':');
+ if (p1 == NULL)
+ warning ("Malformed packet (missing colon): %s\n\
+Packet: '%s'\n",
+ p, buf);
+ if (strncmp ((const char *) p, "thread", p1 - p) == 0)
+ {
+ thread_num = strtol ((const char *) ++p1, &p_temp, 16);
+ p = (unsigned char *)p_temp;
+ }
+ }
+ else
+ {
+ p = p1;
+
+ if (*p++ != ':')
+ warning ("Malformed packet (missing colon): %s\n\
+Packet: '%s'\n",
+ p, buf);
+
+ if (regno >= NUM_REGS)
+ warning ("Remote sent bad register number %ld: %s\n\
+Packet: '%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;
+ }
+ supply_register (regno, regs);
+ }
+
+ if (*p++ != ';')
+ warning ("Remote register badly formatted: %s", buf);
+ }
+ }
+ /* 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])));
+
+ goto got_status;
+ case 'W': /* Target exited */
+ {
+ /* The remote process exited. */
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = (fromhex (buf[1]) << 4) + fromhex (buf[2]);
+ goto got_status;
+ }
+ case 'X':
+ status->kind = TARGET_WAITKIND_SIGNALLED;
+ status->value.sig = (enum target_signal)
+ (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+ kill_kludge = 1;
+
+ goto got_status;
+ case 'O': /* Console output */
+ for (p = buf + 1; *p; p +=2)
+ {
+ char tb[2];
+ char c = fromhex (p[0]) * 16 + fromhex (p[1]);
+ tb[0] = c;
+ tb[1] = 0;
+ if (target_output_hook)
+ target_output_hook (tb);
+ else
+ fputs_filtered (tb, gdb_stdout);
+ }
+ continue;
+ case '\0':
+ if (last_sent_signal != TARGET_SIGNAL_0)
+ {
+ /* Zero length reply means that we tried 'S' or 'C' and
+ the remote system doesn't support it. */
+ target_terminal_ours_for_output ();
+ printf_filtered
+ ("Can't send signals to this remote system. %s not sent.\n",
+ target_signal_to_name (last_sent_signal));
+ last_sent_signal = TARGET_SIGNAL_0;
+ target_terminal_inferior ();
+
+ strcpy ((char *) buf, last_sent_step ? "s" : "c");
+ putpkt ((char *) buf);
+ continue;
+ }
+ /* else fallthrough */
+ default:
+ warning ("Invalid remote reply: %s", buf);
+ continue;
+ }
+ }
+ got_status:
+ if (thread_num != -1)
+ {
+ /* Initial thread value can only be acquired via wait, so deal with
+ this marker which is used before the first thread value is
+ acquired. */
+ if (inferior_pid == 42000)
+ {
+ inferior_pid = thread_num;
+ add_thread (inferior_pid);
+ }
+ return thread_num;
+ }
+ return inferior_pid;
+}
+
+/* Number of bytes of registers this stub implements. */
+static int register_bytes_found;
+
+/* Read the remote registers into the block REGS. */
+/* Currently we just read all the registers, so we don't use regno. */
+/* ARGSUSED */
+static void
+remote_fetch_registers (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+ char regs[REGISTER_BYTES];
+
+ set_thread (inferior_pid, 1);
+
+ sprintf (buf, "g");
+ remote_send (buf);
+
+ /* Unimplemented registers read as all bits zero. */
+ memset (regs, 0, REGISTER_BYTES);
+
+ /* We can get out of synch in various cases. If the first character
+ in the buffer is not a hex character, assume that has happened
+ and try to fetch another packet to read. */
+ while ((buf[0] < '0' || buf[0] > '9')
+ && (buf[0] < 'a' || buf[0] > 'f'))
+ {
+ if (remote_debug)
+ printf_unfiltered ("Bad register packet; fetching a new packet\n");
+ getpkt (buf, 0);
+ }
+
+ /* Reply describes registers byte by byte, each byte encoded as two
+ hex characters. Suck them all up, then supply them to the
+ register cacheing/storage mechanism. */
+
+ p = buf;
+ for (i = 0; i < REGISTER_BYTES; i++)
+ {
+ if (p[0] == 0)
+ break;
+ if (p[1] == 0)
+ {
+ warning ("Remote reply is of odd length: %s", buf);
+ /* Don't change register_bytes_found in this case, and don't
+ print a second warning. */
+ goto supply_them;
+ }
+ regs[i] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+
+ if (i != register_bytes_found)
+ {
+ register_bytes_found = i;
+#ifdef REGISTER_BYTES_OK
+ if (!REGISTER_BYTES_OK (i))
+ warning ("Remote reply is too short: %s", buf);
+#endif
+ }
+
+ supply_them:
+ for (i = 0; i < NUM_REGS; i++)
+ supply_register (i, &regs[REGISTER_BYTE(i)]);
+}
+
+/* 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 ()
+{
+ /* Make sure the entire registers array is valid. */
+ read_register_bytes (0, (char *)NULL, REGISTER_BYTES);
+}
+
+/* Store register REGNO, or all registers if REGNO == -1, from the contents
+ of REGISTERS. FIXME: ignores errors. */
+
+static void
+remote_store_registers (regno)
+ int regno;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+
+ set_thread (inferior_pid, 1);
+
+ if (regno >= 0 && stub_supports_P)
+ {
+ /* Try storing a single register. */
+ char *regp;
+
+ sprintf (buf, "P%x=", regno);
+ p = buf + strlen (buf);
+ regp = &registers[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. */
+
+ p = buf + 1;
+ /* remote_prepare_to_store insures that register_bytes_found gets set. */
+ for (i = 0; i < register_bytes_found; i++)
+ {
+ *p++ = tohex ((registers[i] >> 4) & 0xf);
+ *p++ = tohex (registers[i] & 0xf);
+ }
+ *p = '\0';
+
+ remote_send (buf);
+}
+
+/*
+ Use of the data cache *used* to be disabled because it loses for looking at
+ and changing hardware I/O ports and the like. Accepting `volatile'
+ would perhaps be one way to fix it. Another idea would be to use the
+ executable file for the text segment (for all SEC_CODE sections?
+ For all SEC_READONLY sections?). This has problems if you want to
+ actually see what the memory contains (e.g. self-modifying code,
+ clobbered memory, user downloaded the wrong thing).
+
+ Because it speeds so much up, it's now enabled, if you're playing
+ with registers you turn it of (set remotecache 0)
+*/
+
+/* Read a word from remote address ADDR and return it.
+ This goes through the data cache. */
+
+#if 0 /* unused? */
+static int
+remote_fetch_word (addr)
+ CORE_ADDR addr;
+{
+ return dcache_fetch (remote_dcache, addr);
+}
+
+/* Write a word WORD into remote address ADDR.
+ This goes through the data cache. */
+
+static void
+remote_store_word (addr, word)
+ CORE_ADDR addr;
+ int word;
+{
+ dcache_poke (remote_dcache, addr, word);
+}
+#endif /* 0 (unused?) */
+
+
+/* Write memory data directly to the remote machine.
+ This does not inform the data cache; the data cache uses this.
+ MEMADDR is the address in the remote memory space.
+ MYADDR is the address of the buffer in our space.
+ LEN is the number of bytes.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+static int
+remote_write_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+ int done;
+ /* Chop the transfer down if necessary */
+
+ done = 0;
+ while (done < len)
+ {
+ int todo = len - done;
+ int cando = PBUFSIZ /2 - 32; /* number of bytes that will fit. */
+ if (todo > cando)
+ todo = cando;
+
+ /* 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 + done, todo);
+
+ /* We send target system values byte by byte, in increasing byte addresses,
+ each byte encoded as two hex characters. */
+
+ p = buf + strlen (buf);
+ for (i = 0; i < todo; i++)
+ {
+ *p++ = tohex ((myaddr[i + done] >> 4) & 0xf);
+ *p++ = tohex (myaddr[i + done] & 0xf);
+ }
+ *p = '\0';
+
+ putpkt (buf);
+ getpkt (buf, 0);
+
+ 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 return EIO. */
+ errno = EIO;
+ return 0;
+ }
+ done += todo;
+ }
+ return len;
+}
+
+/* Read memory data directly from the remote machine.
+ This does not use the data cache; the data cache uses this.
+ MEMADDR is the address in the remote memory space.
+ MYADDR is the address of the buffer in our space.
+ LEN is the number of bytes.
+
+ Returns number of bytes transferred, or 0 for error. */
+
+static int
+remote_read_bytes (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ char buf[PBUFSIZ];
+ int i;
+ char *p;
+ int done;
+ /* Chop transfer down if neccessary */
+
+#if 0
+ /* FIXME: This is wrong for larger packets */
+ if (len > PBUFSIZ / 2 - 1)
+ abort ();
+#endif
+ done = 0;
+ while (done < len)
+ {
+ int todo = len - done;
+ int cando = PBUFSIZ / 2 - 32; /* number of bytes that will fit. */
+ if (todo > cando)
+ todo = cando;
+
+ /* 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 + done, todo);
+ putpkt (buf);
+ getpkt (buf, 0);
+
+ 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 return EIO. */
+ errno = EIO;
+ return 0;
+ }
+
+ /* Reply describes memory byte by byte,
+ each byte encoded as two hex characters. */
+
+ p = buf;
+ for (i = 0; i < todo; i++)
+ {
+ if (p[0] == 0 || p[1] == 0)
+ /* Reply is short. This means that we were able to read only part
+ of what we wanted to. */
+ return i + done;
+ myaddr[i + done] = fromhex (p[0]) * 16 + fromhex (p[1]);
+ p += 2;
+ }
+ done += todo;
+ }
+ return len;
+}
+
+/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
+ to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
+ nonzero. Returns length of data written or read; 0 for error. */
+
+/* ARGSUSED */
+static int
+remote_xfer_memory(memaddr, myaddr, len, should_write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int should_write;
+ struct target_ops *target; /* ignored */
+{
+ return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, should_write);
+}
+
+
+#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;
+{
+ puts_filtered ("Debugging a target over a serial line.\n");
+}
+
+/* Stuff for dealing with the packets which are part of this protocol.
+ See comment at top of file for details. */
+
+/* Read a single character from the remote end, masking it down to 7 bits. */
+
+static int
+readchar (timeout)
+ int timeout;
+{
+ int ch;
+
+ ch = SERIAL_READCHAR (remote_desc, timeout);
+
+ 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,
+ and read the reply into BUF.
+ Report an error if we get an error reply. */
+
+static void
+remote_send (buf)
+ char *buf;
+{
+ putpkt (buf);
+ getpkt (buf, 0);
+
+ if (buf[0] == 'E')
+ error ("Remote failure reply: %s", buf);
+}
+
+/* Send a packet to the remote machine, with error checking.
+ The data of the packet is in BUF. */
+
+static int
+putpkt (buf)
+ char *buf;
+{
+ int i;
+ unsigned char csum = 0;
+ char buf2[PBUFSIZ];
+ int cnt = strlen (buf);
+ int ch;
+ int tcount = 0;
+ char *p;
+
+ /* Copy the packet into buffer BUF2, encapsulating it
+ and giving it a checksum. */
+
+ if (cnt > (int) sizeof (buf2) - 5) /* Prosanity check */
+ abort();
+
+ p = buf2;
+ *p++ = '$';
+
+ for (i = 0; i < cnt; i++)
+ {
+ csum += buf[i];
+ *p++ = buf[i];
+ }
+ *p++ = '#';
+ *p++ = tohex ((csum >> 4) & 0xf);
+ *p++ = tohex (csum & 0xf);
+
+ /* Send it over and over until we get a positive ack. */
+
+ while (1)
+ {
+ int started_error_output = 0;
+
+ if (remote_debug)
+ {
+ *p = '\0';
+ printf_unfiltered ("Sending packet: %s...", buf2);
+ gdb_flush(gdb_stdout);
+ }
+ if (SERIAL_WRITE (remote_desc, buf2, p - buf2))
+ perror_with_name ("putpkt: write failed");
+
+ /* read until either a timeout occurs (-2) or '+' is read */
+ while (1)
+ {
+ ch = readchar (remote_timeout);
+
+ if (remote_debug)
+ {
+ switch (ch)
+ {
+ case '+':
+ case SERIAL_TIMEOUT:
+ case '$':
+ if (started_error_output)
+ {
+ putchar_unfiltered ('\n');
+ started_error_output = 0;
+ }
+ }
+ }
+
+ switch (ch)
+ {
+ case '+':
+ if (remote_debug)
+ printf_unfiltered("Ack\n");
+ return 1;
+ case SERIAL_TIMEOUT:
+ tcount ++;
+ if (tcount > 3)
+ return 0;
+ break; /* Retransmit buffer */
+ case '$':
+ {
+ 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)
+ {
+ if (!started_error_output)
+ {
+ started_error_output = 1;
+ printf_unfiltered ("putpkt: Junk: ");
+ }
+ putchar_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;
+ pktcsum |= fromhex (readchar (remote_timeout));
+
+ if (csum == pktcsum)
+ return 1;
+
+ if (remote_debug)
+ {
+ 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 */
+ csum += c;
+ c = readchar (remote_timeout);
+ csum += c;
+ c = c - ' ' + 3; /* Compute repeat count */
+
+
+ if (c > 0 && c < 255 && 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;
+ }
+ }
+}
+
+/* Read a packet from the remote machine, with error checking,
+ and store it in BUF. BUF is expected to be of size PBUFSIZ.
+ If FOREVER, wait forever rather than timing out; this is used
+ while the target is executing user code. */
+
+static void
+getpkt (buf, forever)
+ char *buf;
+ int forever;
+{
+ int c;
+ int tries;
+ int timeout;
+ int val;
+
+ strcpy (buf,"timeout");
+
+ if (forever)
+ {
+#ifdef MAINTENANCE_CMDS
+ timeout = watchdog > 0 ? watchdog : -1;
+#else
+ timeout = -1;
+#endif
+ }
+
+ else
+ timeout = remote_timeout;
+
+#define MAX_TRIES 3
+
+ for (tries = 1; tries <= MAX_TRIES; tries++)
+ {
+ /* 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. */
+
+ /* 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. */
+
+ do
+ {
+ c = readchar (timeout);
+
+ if (c == SERIAL_TIMEOUT)
+ {
+#ifdef MAINTENANCE_CMDS
+ if (forever) /* Watchdog went off. Kill the target. */
+ {
+ target_mourn_inferior ();
+ error ("Watchdog has expired. Target detached.\n");
+ }
+#endif
+ if (remote_debug)
+ puts_filtered ("Timed out.\n");
+ goto retry;
+ }
+ }
+ while (c != '$');
+
+ /* 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. */
+ retry:
+ SERIAL_WRITE (remote_desc, "-", 1);
+ }
+
+ /* 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);
+}
+
+static void
+remote_kill ()
+{
+ /* For some mysterious reason, wait_for_inferior calls kill instead of
+ mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */
+ if (kill_kludge)
+ {
+ kill_kludge = 0;
+ target_mourn_inferior ();
+ return;
+ }
+
+ /* Use catch_errors so the user can quit from gdb even when we aren't on
+ speaking terms with the remote system. */
+ catch_errors (putpkt, "k", "", RETURN_MASK_ERROR);
+
+ /* Don't wait for it to die. I'm not really sure it matters whether
+ we do or not. For the existing stubs, kill is a noop. */
+ target_mourn_inferior ();
+}
+
+static void
+remote_mourn ()
+{
+ remote_mourn_1 (&remote_ops);
+}
+
+static void
+extended_remote_mourn ()
+{
+ /* We do _not_ want to mourn the target like this; this will
+ remove the extended remote target from the target stack,
+ and the next time the user says "run" it'll fail.
+
+ FIXME: What is the right thing to do here? */
+#if 0
+ remote_mourn_1 (&extended_remote_ops);
+#endif
+}
+
+/* Worker function for remote_mourn. */
+static void
+remote_mourn_1 (target)
+ struct target_ops *target;
+{
+ unpush_target (target);
+ generic_mourn_inferior ();
+}
+
+/* In the extended protocol we want to be able to do things like
+ "run" and have them basically work as expected. So we need
+ a special create_inferior function.
+
+ FIXME: One day add support for changing the exec file
+ we're debugging, arguments and an environment. */
+
+static void
+extended_remote_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ /* Rip out the breakpoints; we'll reinsert them after restarting
+ the remote server. */
+ remove_breakpoints ();
+
+ /* Now restart the remote server. */
+ extended_remote_restart ();
+
+ /* Now put the breakpoints back in. This way we're safe if the
+ restart function works via a unix fork on the remote side. */
+ insert_breakpoints ();
+
+ /* Clean up from the last time we were running. */
+ clear_proceed_status ();
+
+ /* Let the remote process run. */
+ proceed (-1, TARGET_SIGNAL_0, 0);
+}
+
+
+#ifdef REMOTE_BREAKPOINT
+
+/* On some machines, e.g. 68k, we may use a different breakpoint instruction
+ than other targets. */
+static unsigned char break_insn[] = REMOTE_BREAKPOINT;
+
+#else /* No REMOTE_BREAKPOINT. */
+
+/* Same old breakpoint instruction. This code does nothing different
+ than mem-break.c. */
+static unsigned char break_insn[] = BREAKPOINT;
+
+#endif /* No REMOTE_BREAKPOINT. */
+
+/* Insert a breakpoint on targets that don't have any better breakpoint
+ support. We read the contents of the target location and stash it,
+ then overwrite it with a breakpoint instruction. ADDR is the target
+ location in the target machine. CONTENTS_CACHE is a pointer to
+ memory allocated for saving the target contents. It is guaranteed
+ by the caller to be long enough to save sizeof BREAKPOINT bytes (this
+ is accomplished via BREAKPOINT_MAX). */
+
+static int
+remote_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ int val;
+
+ val = target_read_memory (addr, contents_cache, sizeof break_insn);
+
+ if (val == 0)
+ val = target_write_memory (addr, (char *)break_insn, sizeof break_insn);
+
+ return val;
+}
+
+static int
+remote_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ return target_write_memory (addr, contents_cache, sizeof break_insn);
+}
+
+/* Define the target subroutine names */
+
+struct target_ops remote_ops = {
+ "remote", /* to_shortname */
+ "Remote serial target in gdb-specific protocol", /* to_longname */
+ "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */
+ remote_open, /* to_open */
+ remote_close, /* to_close */
+ NULL, /* to_attach */
+ remote_detach, /* to_detach */
+ remote_resume, /* to_resume */
+ remote_wait, /* to_wait */
+ remote_fetch_registers, /* to_fetch_registers */
+ remote_store_registers, /* to_store_registers */
+ remote_prepare_to_store, /* to_prepare_to_store */
+ remote_xfer_memory, /* to_xfer_memory */
+ remote_files_info, /* to_files_info */
+ remote_insert_breakpoint, /* to_insert_breakpoint */
+ remote_remove_breakpoint, /* to_remove_breakpoint */
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ remote_kill, /* to_kill */
+ generic_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ NULL, /* to_create_inferior */
+ remote_mourn, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ remote_thread_alive, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+struct target_ops extended_remote_ops = {
+ "extended-remote", /* to_shortname */
+ "Extended remote serial target in gdb-specific protocol",/* to_longname */
+ "Use a remote computer via a serial line, using a gdb-specific protocol.\n\
+Specify the serial device it is connected to (e.g. /dev/ttya).", /* to_doc */
+ extended_remote_open, /* to_open */
+ remote_close, /* to_close */
+ NULL, /* to_attach */
+ remote_detach, /* to_detach */
+ remote_resume, /* to_resume */
+ remote_wait, /* to_wait */
+ remote_fetch_registers, /* to_fetch_registers */
+ remote_store_registers, /* to_store_registers */
+ remote_prepare_to_store, /* to_prepare_to_store */
+ remote_xfer_memory, /* to_xfer_memory */
+ remote_files_info, /* to_files_info */
+
+ remote_insert_breakpoint, /* to_insert_breakpoint */
+ remote_remove_breakpoint, /* to_remove_breakpoint */
+
+ NULL, /* to_terminal_init */
+ NULL, /* to_terminal_inferior */
+ NULL, /* to_terminal_ours_for_output */
+ NULL, /* to_terminal_ours */
+ NULL, /* to_terminal_info */
+ remote_kill, /* to_kill */
+ generic_load, /* to_load */
+ NULL, /* to_lookup_symbol */
+ extended_remote_create_inferior,/* to_create_inferior */
+ extended_remote_mourn, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ remote_thread_alive, /* to_thread_alive */
+ 0, /* to_stop */
+ process_stratum, /* to_stratum */
+ NULL, /* to_next */
+ 1, /* to_has_all_memory */
+ 1, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ NULL, /* sections */
+ NULL, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_remote ()
+{
+ add_target (&remote_ops);
+ add_target (&extended_remote_ops);
+
+ add_show_from_set (add_set_cmd ("remotetimeout", no_class,
+ var_integer, (char *)&remote_timeout,
+ "Set timeout value for remote read.\n", &setlist),
+ &showlist);
+
+ add_show_from_set (add_set_cmd ("remotebreak", no_class,
+ var_integer, (char *)&remote_break,
+ "Set whether to send break if interrupted.\n", &setlist),
+ &showlist);
+}
diff --git a/contrib/gdb/gdb/reply_mig_hack.awk b/contrib/gdb/gdb/reply_mig_hack.awk
new file mode 100644
index 0000000..310a40c
--- /dev/null
+++ b/contrib/gdb/gdb/reply_mig_hack.awk
@@ -0,0 +1,123 @@
+# Reply server mig-output massager
+#
+# Copyright (C) 1995 Free Software Foundation, Inc.
+#
+# Written by Miles Bader <miles@gnu.ai.mit.edu>
+#
+# 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 the Free Software Foundation; either version 2, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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.
+#
+# This awk script hacks the output of mig-generated reply server code
+# so that it allows replies with just the error-code in them (as this is
+# how mig returns errors).
+#
+# It is highly, highly, dependent on the exact format of mig output. Ick.
+#
+
+BEGIN { parse_phase = 0; }
+
+/^}/ { parse_phase = 0; }
+
+parse_phase == 0 && /^mig_internal void _X[a-zA-Z0-9_]*_reply/ {
+ # The start of a mig server routine. Reset everything. Note that we only
+ # mess with rpcs that have the suffix `_reply'.
+ num_args = 0;
+ num_checks = 0;
+ parse_phase = 1;
+ print; next;
+}
+
+parse_phase == 1 && /^[\t ]*typedef struct/ {
+ # The first structure in the server routine should describe the arguments
+ parse_phase = 2;
+ print; next;
+}
+
+parse_phase == 2 {
+ # The message header field in the args structure, which skip.
+ parse_phase = 3;
+ print; next;
+}
+
+parse_phase == 3 && /}/ {
+ # The args structure is over.
+ if (num_args > 1)
+ parse_phase = 5;
+ else
+ # There's no extra args that could screw up the normal mechanism for
+ # error returns, so we don't have to insert any new code.
+ parse_phase = 0;
+ print; next;
+}
+
+parse_phase == 3 {
+ # The type field for an argument.
+ arg_type_code_name[num_args] = $2;
+ sub (/;$/, "", arg_type_code_name[num_args]) # Get rid of the semi-colon
+ parse_phase = 4;
+ print; next;
+}
+
+parse_phase == 4 {
+ # The value field for an argument.
+ arg_name[num_args] = $2;
+ sub (/;$/, "", arg_name[num_args]) # Get rid of the semi-colon
+ arg_type[num_args] = $1;
+ num_args++;
+ parse_phase = 3;
+ print; next;
+}
+
+parse_phase == 5 && /^[ \t]*static const mach_msg_type_t/ {
+ # The type check structure for an argument.
+ arg_check_name[num_checks] = $4;
+ num_checks++;
+ print; next;
+}
+
+parse_phase == 5 && /^[ \t]*mig_external kern_return_t/ {
+ # The declaration of the user server function for this rpc.
+ user_function_name = $3;
+ print; next;
+}
+
+parse_phase == 5 && /^#if[ \t]TypeCheck/ {
+ # The first args type checking statement; we need to insert our chunk of
+ # code that bypasses all the type checks if this is an error return, after
+ # which we're done until we get to the next function. Handily, the size
+ # of mig's Reply structure is also the size of the alternate Request
+ # structure that we want to check for.
+ print "\tif (In0P->Head.msgh_size == sizeof (Reply)";
+ print "\t && ! (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)";
+ print "\t && *(int *)&In0P->" arg_type_code_name[0] " == *(int *)&" arg_check_name[0];
+ print "\t && In0P->" arg_name[0] " != 0)";
+ print "\t /* Error return, only the error code argument is passed. */";
+ print "\t {";
+ # Force the function into a type that only takes the first two args, via
+ # the temp variable SFUN (is there another way to correctly do this cast?).
+ # This is possibly bogus, but easier than supplying bogus values for all
+ # the other args (we can't just pass 0 for them, as they might not be scalar).
+ printf ("\t kern_return_t (*sfun)(mach_port_t");
+ for (i = 0; i < num_args; i++)
+ printf (", %s", arg_type[i]);
+ printf (") = %s;\n", user_function_name);
+ print "\t OutP->RetCode = (*(kern_return_t (*)(mach_port_t, kern_return_t))sfun) (In0P->Head.msgh_request_port, In0P->" arg_name[0] ");";
+ print "\t return;";
+ print "\t }";
+ print "";
+ parse_phase = 0;
+ print; next;
+}
+
+{ print; }
diff --git a/contrib/gdb/gdb/saber.suppress b/contrib/gdb/gdb/saber.suppress
new file mode 100644
index 0000000..6dda1c5
--- /dev/null
+++ b/contrib/gdb/gdb/saber.suppress
@@ -0,0 +1,451 @@
+
+
+/* Options for project */
+unsetopt ansi
+setopt auto_compile
+unsetopt auto_reload
+setopt auto_replace
+unsetopt batch_load
+unsetopt batch_run
+unsetopt cc_prog
+setopt ccargs -g
+unsetopt create_file
+unsetopt debug_child
+unsetopt echo
+setopt edit_jobs 5
+unsetopt eight_bit
+setopt line_edit
+setopt line_meta
+setopt lint_load 2
+setopt lint_run 2
+setopt list_action
+setopt load_flags -I. -g -I.. -I../vx-share
+unsetopt long_not_int
+unsetopt make_args
+setopt make_hfiles
+unsetopt make_offset
+unsetopt make_prog
+setopt make_symbol #
+setopt mem_config 16384
+unsetopt mem_trace
+setopt num_proc 1
+unsetopt page_cmds
+setopt page_list 19
+unsetopt page_load
+unsetopt path
+setopt proto_path . /s2/saber_dir30/sun4-40/proto /s2/saber_dir30/sun4-40/../common/proto
+unsetopt preprocessor
+setopt program_name a.out
+unsetopt print_custom
+setopt print_pointer
+setopt print_string 20
+unsetopt save_memory
+setopt sbrk_size 1048576
+setopt src_err 3
+setopt src_step 1
+setopt src_stop 3
+setopt sys_load_flags -L/lib -L/usr/lib -L/usr/local/lib -I/usr/include -Dunix -Dsun -Dsparc
+unsetopt tab_stop
+unsetopt terse_suppress
+unsetopt terse_where
+setopt unset_value 191
+unsetopt win_fork_nodup
+setopt win_no_raise
+unsetopt win_message_list
+unsetopt win_project_list
+/* Suppressions for project */
+suppress 6 in read_huge_number
+/* Over/underflow <plus> */
+suppress 8 in read_huge_number
+/* Over/underflow <multiply> */
+suppress 22
+/* Pointer subtraction */
+suppress 22 in free_all_psymtabs
+/* Pointer subtraction */
+suppress 22 in free_all_symtabs
+/* Pointer subtraction */
+suppress 56 in print_string
+/* Information lost <function> */
+suppress 65 "../bfd/bfd.c":379
+/* Too many function arguments */
+suppress 65 on printf_filtered
+/* Too many function arguments */
+suppress 65 on fprintf_filtered
+/* Too many function arguments */
+suppress 65 on vfprintf_filtered
+/* Too many function arguments */
+suppress 65 on query
+/* Too many function arguments */
+suppress 65 on fatal_dump_core
+/* Too many function arguments */
+suppress 65 on fatal
+/* Too many function arguments */
+suppress 65 on error
+/* Too many function arguments */
+suppress 65 on noprocess
+/* Too many function arguments */
+suppress 65
+/* Too many function arguments */
+suppress 66 on say
+/* Too few function arguments */
+suppress 66 on printf_filtered
+/* Too few function arguments */
+suppress 66 on fprintf_filtered
+/* Too few function arguments */
+suppress 66 on vfprintf_filtered
+/* Too few function arguments */
+suppress 66 on query
+/* Too few function arguments */
+suppress 66 on fatal_dump_core
+/* Too few function arguments */
+suppress 66 on fatal
+/* Too few function arguments */
+suppress 66 on error
+/* Too few function arguments */
+suppress 67 on printf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on fprintf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on vfprintf_filtered
+/* Signed/unsigned argument mismatch */
+suppress 67 on query
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal_dump_core
+/* Signed/unsigned argument mismatch */
+suppress 67 on fatal
+/* Signed/unsigned argument mismatch */
+suppress 67 on error
+/* Signed/unsigned argument mismatch */
+suppress 67
+/* Signed/unsigned argument mismatch */
+suppress 68 on bfd_get_section_contents
+/* Benign argument mismatch */
+suppress 68 on _do_getblong
+/* Benign argument mismatch */
+suppress 68 on supply_register
+/* Benign argument mismatch */
+suppress 68 on target_write_memory
+/* Benign argument mismatch */
+suppress 68 on write_register_bytes
+/* Benign argument mismatch */
+suppress 68 on read_register_bytes
+/* Benign argument mismatch */
+suppress 68 on read_memory
+/* Benign argument mismatch */
+suppress 68 on say
+/* Benign argument mismatch */
+suppress 68 on printf_filtered
+/* Benign argument mismatch */
+suppress 68 on fprintf_filtered
+/* Benign argument mismatch */
+suppress 68 on vfprintf_filtered
+/* Benign argument mismatch */
+suppress 68 on query
+/* Benign argument mismatch */
+suppress 68 on fatal_dump_core
+/* Benign argument mismatch */
+suppress 68 on fatal
+/* Benign argument mismatch */
+suppress 68 on error
+/* Benign argument mismatch */
+suppress 68 in find_solib
+/* Benign argument mismatch */
+suppress 68 on child_wait
+/* Benign argument mismatch */
+suppress 68 on xrealloc
+/* Benign argument mismatch */
+suppress 68 on myread
+/* Benign argument mismatch */
+suppress 68 in do_cleanups
+/* Benign argument mismatch */
+suppress 68 on make_cleanup
+/* Benign argument mismatch */
+suppress 68 on target_read_memory
+/* Benign argument mismatch */
+suppress 69 on printf_filtered
+/* Serious argument mismatch */
+suppress 69 on fprintf_filtered
+/* Serious argument mismatch */
+suppress 69 on vfprintf_filtered
+/* Serious argument mismatch */
+suppress 69 on query
+/* Serious argument mismatch */
+suppress 69 on fatal_dump_core
+/* Serious argument mismatch */
+suppress 69 on fatal
+/* Serious argument mismatch */
+suppress 69 on error
+/* Serious argument mismatch */
+suppress 70 on printf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on fprintf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on vfprintf_filtered
+/* Passing illegal enumeration value */
+suppress 70 on query
+/* Passing illegal enumeration value */
+suppress 70 on fatal_dump_core
+/* Passing illegal enumeration value */
+suppress 70 on fatal
+/* Passing illegal enumeration value */
+suppress 70 on error
+/* Passing illegal enumeration value */
+suppress 80 on first_link_map_member
+/* Returning invalid pointer */
+suppress 110 in printf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in fprintf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in vfprintf_filtered
+/* Signed/unsigned memory retrieval */
+suppress 110 in query
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal_dump_core
+/* Signed/unsigned memory retrieval */
+suppress 110 in fatal
+/* Signed/unsigned memory retrieval */
+suppress 110 in error
+/* Signed/unsigned memory retrieval */
+suppress 112 in printf_filtered
+/* Memory retrieval */
+suppress 112 in fprintf_filtered
+/* Memory retrieval */
+suppress 112 in vfprintf_filtered
+/* Memory retrieval */
+suppress 112 in query
+/* Memory retrieval */
+suppress 112 in fatal_dump_core
+/* Memory retrieval */
+suppress 112 in fatal
+/* Memory retrieval */
+suppress 112 in error
+/* Memory retrieval */
+suppress 112
+/* Memory retrieval */
+suppress 112 ../symtab.c
+/* Memory retrieval */
+suppress 112 in child_xfer_memory
+/* Memory retrieval */
+suppress 165 in frame_saved_pc
+/* Dereference */
+suppress 165 in get_prev_frame_info
+/* Dereference */
+suppress 167 in get_prev_frame_info
+/* Selection */
+suppress 167 in frame_saved_pc
+/* Selection */
+suppress 442 in try_baudrate
+/* Escape has null value */
+suppress 529 in read_range_type
+/* Statement not reached */
+suppress 529 in process_one_symbol
+/* Statement not reached */
+suppress 529 in unpack_double
+/* Statement not reached */
+suppress 529 in wait_for_inferior
+/* Statement not reached */
+suppress 529 in do_registers_info
+/* Statement not reached */
+suppress 529 in value_from_register
+/* Statement not reached */
+suppress 529 in solib_create_inferior_hook
+/* Constant in conditional */
+suppress 530
+/* Empty body of statement */
+suppress 546 in net_quit
+/* Function exits through bottom */
+suppress 546 in net_wait
+/* Function exits through bottom */
+suppress 546 in vx_remove_breakpoint
+/* Function exits through bottom */
+suppress 546 in vx_insert_breakpoint
+/* Function exits through bottom */
+suppress 546 in value_less
+/* Function exits through bottom */
+suppress 546 in value_equal
+/* Function exits through bottom */
+suppress 546 in unpack_long
+/* Function exits through bottom */
+suppress 558 in solib_create_inferior_hook
+/* Constant in conditional */
+suppress 558 in read_range_type
+/* Constant in conditional */
+suppress 558 in process_one_symbol
+/* Constant in conditional */
+suppress 558 in read_dbx_symtab
+/* Constant in conditional */
+suppress 558 in vx_write_register
+/* Constant in conditional */
+suppress 558 in vx_read_register
+/* Constant in conditional */
+suppress 558 in unpack_double
+/* Constant in conditional */
+suppress 558 in wait_for_inferior
+/* Constant in conditional */
+suppress 558 in do_registers_info
+/* Constant in conditional */
+suppress 558 in value_from_register
+/* Constant in conditional */
+suppress 558 in add_enum_psymbol
+/* Constant in conditional */
+suppress 558 in add_partial_symbol
+/* Constant in conditional */
+suppress 558 mfree.c
+/* Constant in conditional */
+suppress 558 mmalloc.c
+/* Constant in conditional */
+suppress 558 mrealloc.c
+/* Constant in conditional */
+suppress 560 in solib_address
+/* Assignment within conditional */
+suppress 560 in solib_info
+/* Assignment within conditional */
+suppress 560 in solib_add
+/* Assignment within conditional */
+suppress 560 in read_type
+/* Assignment within conditional */
+suppress 560 in type_print_base
+/* Assignment within conditional */
+suppress 560 in type_print_derivation_info
+/* Assignment within conditional */
+suppress 560 in block_depth
+/* Assignment within conditional */
+suppress 560 in select_source_symtab
+/* Assignment within conditional */
+suppress 560 in clear_value_history
+/* Assignment within conditional */
+suppress 560 in clear_displays
+/* Assignment within conditional */
+suppress 560 in initialize_main
+/* Assignment within conditional */
+suppress 560 in echo_command
+/* Assignment within conditional */
+suppress 560 in unset_in_environ
+/* Assignment within conditional */
+suppress 560 in set_in_environ
+/* Assignment within conditional */
+suppress 560 in get_in_environ
+/* Assignment within conditional */
+suppress 560 in do_setshow_command
+/* Assignment within conditional */
+suppress 560 in breakpoint_1
+/* Assignment within conditional */
+suppress 590 on sig
+/* Unused formal parameter */
+suppress 590 in nindy_create_inferior
+/* Unused formal parameter */
+suppress 590 in add_to_section_table
+/* Unused formal parameter */
+suppress 590 in vx_create_inferior
+/* Unused formal parameter */
+suppress 590 in host_convert_from_virtual
+/* Unused formal parameter */
+suppress 590 in host_convert_to_virtual
+/* Unused formal parameter */
+suppress 590 on siggnal
+/* Unused formal parameter */
+suppress 590 in init_sig
+/* Unused formal parameter */
+suppress 590 in nindy_resume
+/* Unused formal parameter */
+suppress 590 in set_history_size_command
+/* Unused formal parameter */
+suppress 590 in not_just_help_class_command
+/* Unused formal parameter */
+suppress 590 on regno
+/* Unused formal parameter */
+suppress 590 on from_tty
+/* Unused formal parameter */
+suppress 590 on args
+/* Unused formal parameter */
+suppress 590 in process_symbol_pair
+/* Unused formal parameter */
+suppress 591 in print_scalar_formatted
+/* Unused automatic variable */
+suppress 592 on rcsid
+/* Unused static */
+suppress 594 in call_function_by_hand
+/* Set but not used */
+suppress 594 in record_latest_value
+/* Set but not used */
+suppress 594 in bpstat_stop_status
+/* Set but not used */
+suppress 595 in coffstrip
+/* Used before set */
+suppress 652 ../include/bfd.h
+/* Declaration has no effect */
+suppress 652 /usr/include/machine/reg.h
+/* Declaration has no effect */
+suppress 652 /usr/include/sun4/reg.h
+/* Declaration has no effect */
+suppress 68 on complain
+/* Benign type mismatch */
+suppress 3 in read_range_type
+/* Over/underflow unary minus */
+suppress 442 ../bfd/archive.c
+/* \0 in string */
+suppress 558 ../bfd/b.out.c
+/* Conditional if always true */
+suppress 558 ../bfd/coffswap.c
+/* Conditional if always true -- bfd_h_put_x */
+suppress 529 ../bfd/coffswap.c
+/* Stmt unreach -- bfd_h_put_x */
+suppress 590 ../bfd/ecoff.c
+/* Formal parameter not used */
+suppress 590 on ignore
+/* Formal param not used */
+suppress 590 on ignore_exec_bfd
+/* Formal param not used */
+suppress 590 on ignore_core_bfd
+/* Formal param not used */
+suppress 590 on ignore_input_section
+/* Formal param not used */
+suppress 590 on ignore_newsect
+/* Formal param not used */
+suppress 590 on ignore_abfd
+/* Formal param not used */
+suppress 590 on ignore_symbol
+/* Formal param not used */
+suppress 590 on ignore_symbols
+/* Formal param not used */
+suppress 590 on signo
+/* Formal param not used */
+suppress 652
+/* The declaration has no effect */
+suppress 442 in ../bfd/archive.c
+/* Escape sequence in string literal has null value */
+
+/* Signals caught and ignored */
+catch HUP
+catch QUIT
+catch ILL
+catch TRAP
+catch IOT
+catch EMT
+catch FPE
+catch KILL
+catch BUS
+catch SEGV
+catch SYS
+catch PIPE
+catch TERM
+catch URG
+catch STOP
+catch TSTP
+catch TTIN
+catch TTOU
+catch IO
+catch XCPU
+catch XFSZ
+catch VTALRM
+catch PROF
+catch LOST
+catch USR1
+catch USR2
+ignore INT
+ignore ALRM
+ignore CONT
+ignore CHLD
+ignore WINCH
+
+/* Status of project */
diff --git a/contrib/gdb/gdb/scm-exp.c b/contrib/gdb/gdb/scm-exp.c
new file mode 100644
index 0000000..8df6803
--- /dev/null
+++ b/contrib/gdb/gdb/scm-exp.c
@@ -0,0 +1,414 @@
+/* Scheme/Guile language support routines for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "value.h"
+#include "c-lang.h"
+#include "scm-lang.h"
+#include "scm-tags.h"
+
+#define USE_EXPRSTRING 0
+
+static void scm_lreadr PARAMS ((int));
+
+LONGEST
+scm_istr2int(str, len, radix)
+ char *str;
+ int len;
+ int radix;
+{
+ int j;
+ int i = 0;
+ LONGEST inum = 0;
+ int c;
+ int sign = 0;
+
+ if (0 >= len) return SCM_BOOL_F; /* zero scm_length */
+ switch (str[0])
+ { /* leading sign */
+ case '-':
+ case '+':
+ sign = str[0];
+ if (++i==len)
+ return SCM_BOOL_F; /* bad if lone `+' or `-' */
+ }
+ do {
+ switch (c = str[i++]) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c = c - '0';
+ goto accumulate;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ c = c-'A'+10;
+ goto accumulate;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ c = c-'a'+10;
+ accumulate:
+ if (c >= radix) return SCM_BOOL_F; /* bad digit for radix */
+ inum *= radix;
+ inum += c;
+ break;
+ default:
+ return SCM_BOOL_F; /* not a digit */
+ }
+ } while (i < len);
+ if (sign == '-')
+ inum = -inum;
+ return SCM_MAKINUM (inum);
+}
+
+LONGEST
+scm_istring2number(str, len, radix)
+ char *str;
+ int len;
+ int radix;
+{
+ int i = 0;
+ char ex = 0;
+ char ex_p = 0, rx_p = 0; /* Only allow 1 exactness and 1 radix prefix */
+ SCM res;
+ if (len==1)
+ if (*str=='+' || *str=='-') /* Catches lone `+' and `-' for speed */
+ return SCM_BOOL_F;
+
+ while ((len-i) >= 2 && str[i]=='#' && ++i)
+ switch (str[i++]) {
+ case 'b': case 'B': if (rx_p++) return SCM_BOOL_F; radix = 2; break;
+ case 'o': case 'O': if (rx_p++) return SCM_BOOL_F; radix = 8; break;
+ case 'd': case 'D': if (rx_p++) return SCM_BOOL_F; radix = 10; break;
+ case 'x': case 'X': if (rx_p++) return SCM_BOOL_F; radix = 16; break;
+ case 'i': case 'I': if (ex_p++) return SCM_BOOL_F; ex = 2; break;
+ case 'e': case 'E': if (ex_p++) return SCM_BOOL_F; ex = 1; break;
+ default: return SCM_BOOL_F;
+ }
+
+ switch (ex) {
+ case 1:
+ return scm_istr2int(&str[i], len-i, radix);
+ case 0:
+ return scm_istr2int(&str[i], len-i, radix);
+#if 0
+ if NFALSEP(res) return res;
+#ifdef FLOATS
+ case 2: return scm_istr2flo(&str[i], len-i, radix);
+#endif
+#endif
+ }
+ return SCM_BOOL_F;
+}
+
+static void
+scm_read_token (c, weird)
+ int c;
+ int weird;
+{
+ while (1)
+ {
+ c = *lexptr++;
+ switch (c)
+ {
+ case '[':
+ case ']':
+ case '(':
+ case ')':
+ case '\"':
+ case ';':
+ case ' ': case '\t': case '\r': case '\f':
+ case '\n':
+ if (weird)
+ goto default_case;
+ case '\0': /* End of line */
+ eof_case:
+ --lexptr;
+ return;
+ case '\\':
+ if (!weird)
+ goto default_case;
+ else
+ {
+ c = *lexptr++;
+ if (c == '\0')
+ goto eof_case;
+ else
+ goto default_case;
+ }
+ case '}':
+ if (!weird)
+ goto default_case;
+
+ c = *lexptr++;
+ if (c == '#')
+ return;
+ else
+ {
+ --lexptr;
+ c = '}';
+ goto default_case;
+ }
+
+ default:
+ default_case:
+ ;
+ }
+ }
+}
+
+static int
+scm_skip_ws ()
+{
+ register int c;
+ while (1)
+ switch ((c = *lexptr++))
+ {
+ case '\0':
+ goteof:
+ return c;
+ case ';':
+ lp:
+ switch ((c = *lexptr++))
+ {
+ case '\0':
+ goto goteof;
+ default:
+ goto lp;
+ case '\n':
+ break;
+ }
+ case ' ': case '\t': case '\r': case '\f': case '\n':
+ break;
+ default:
+ return c;
+ }
+}
+
+static void
+scm_lreadparen (skipping)
+ int skipping;
+{
+ for (;;)
+ {
+ int c = scm_skip_ws ();
+ if (')' == c || ']' == c)
+ return;
+ --lexptr;
+ if (c == '\0')
+ error ("missing close paren");
+ scm_lreadr (skipping);
+ }
+}
+
+static void
+scm_lreadr (skipping)
+ int skipping;
+{
+ int c, j;
+ struct stoken str;
+ LONGEST svalue;
+ tryagain:
+ c = *lexptr++;
+ switch (c)
+ {
+ case '\0':
+ lexptr--;
+ return;
+ case '[':
+ case '(':
+ scm_lreadparen (skipping);
+ return;
+ case ']':
+ case ')':
+ error ("unexpected #\\%c", c);
+ goto tryagain;
+ case '\'':
+ case '`':
+ str.ptr = lexptr - 1;
+ scm_lreadr (skipping);
+ if (!skipping)
+ {
+ value_ptr val = scm_evaluate_string (str.ptr, lexptr - str.ptr);
+ if (!is_scmvalue_type (VALUE_TYPE (val)))
+ error ("quoted scm form yields non-SCM value");
+ svalue = extract_signed_integer (VALUE_CONTENTS (val),
+ TYPE_LENGTH (VALUE_TYPE (val)));
+ goto handle_immediate;
+ }
+ return;
+ case ',':
+ c = *lexptr++;
+ if ('@' != c)
+ lexptr--;
+ scm_lreadr (skipping);
+ return;
+ case '#':
+ c = *lexptr++;
+ switch (c)
+ {
+ case '[':
+ case '(':
+ scm_lreadparen (skipping);
+ return;
+ case 't': case 'T':
+ svalue = SCM_BOOL_T;
+ goto handle_immediate;
+ case 'f': case 'F':
+ svalue = SCM_BOOL_F;
+ goto handle_immediate;
+ case 'b': case 'B':
+ case 'o': case 'O':
+ case 'd': case 'D':
+ case 'x': case 'X':
+ case 'i': case 'I':
+ case 'e': case 'E':
+ lexptr--;
+ c = '#';
+ goto num;
+ case '*': /* bitvector */
+ scm_read_token (c, 0);
+ return;
+ case '{':
+ scm_read_token (c, 1);
+ return;
+ case '\\': /* character */
+ c = *lexptr++;
+ scm_read_token (c, 0);
+ return;
+ case '|':
+ j = 1; /* here j is the comment nesting depth */
+ lp:
+ c = *lexptr++;
+ lpc:
+ switch (c)
+ {
+ case '\0':
+ error ("unbalanced comment");
+ default:
+ goto lp;
+ case '|':
+ if ('#' != (c = *lexptr++))
+ goto lpc;
+ if (--j)
+ goto lp;
+ break;
+ case '#':
+ if ('|' != (c = *lexptr++))
+ goto lpc;
+ ++j;
+ goto lp;
+ }
+ goto tryagain;
+ case '.':
+ default:
+ callshrp:
+ scm_lreadr (skipping);
+ return;
+ }
+ case '\"':
+ while ('\"' != (c = *lexptr++))
+ {
+ if (c == '\\')
+ switch (c = *lexptr++)
+ {
+ case '\0':
+ error ("non-terminated string literal");
+ case '\n':
+ continue;
+ case '0':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case 'a':
+ case 'v':
+ break;
+ }
+ }
+ return;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ case '.':
+ case '-':
+ case '+':
+ num:
+ {
+ str.ptr = lexptr-1;
+ scm_read_token (c, 0);
+ if (!skipping)
+ {
+ svalue = scm_istring2number (str.ptr, lexptr - str.ptr, 10);
+ if (svalue != SCM_BOOL_F)
+ goto handle_immediate;
+ goto tok;
+ }
+ }
+ return;
+ case ':':
+ scm_read_token ('-', 0);
+ return;
+ do_symbol:
+ default:
+ str.ptr = lexptr-1;
+ scm_read_token (c, 0);
+ tok:
+ if (!skipping)
+ {
+ str.length = lexptr - str.ptr;
+ if (str.ptr[0] == '$')
+ {
+ write_dollar_variable (str);
+ return;
+ }
+ write_exp_elt_opcode (OP_NAME);
+ write_exp_string (str);
+ write_exp_elt_opcode (OP_NAME);
+ }
+ return;
+ }
+ handle_immediate:
+ if (!skipping)
+ {
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (builtin_type_scm);
+ write_exp_elt_longcst (svalue);
+ write_exp_elt_opcode (OP_LONG);
+ }
+}
+
+int
+scm_parse ()
+{
+ char* start;
+ struct stoken str;
+ while (*lexptr == ' ')
+ lexptr++;
+ start = lexptr;
+ scm_lreadr (USE_EXPRSTRING);
+#if USE_EXPRSTRING
+ str.length = lexptr - start;
+ str.ptr = start;
+ write_exp_elt_opcode (OP_EXPRSTRING);
+ write_exp_string (str);
+ write_exp_elt_opcode (OP_EXPRSTRING);
+#endif
+ return 0;
+}
diff --git a/contrib/gdb/gdb/scm-lang.c b/contrib/gdb/gdb/scm-lang.c
new file mode 100644
index 0000000..b054dcf
--- /dev/null
+++ b/contrib/gdb/gdb/scm-lang.c
@@ -0,0 +1,268 @@
+/* Scheme/Guile language support routines for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "value.h"
+#include "c-lang.h"
+#include "scm-lang.h"
+#include "scm-tags.h"
+#include "gdb_string.h"
+
+extern struct type ** const (c_builtin_types[]);
+extern value_ptr value_allocate_space_in_inferior PARAMS ((int));
+extern value_ptr find_function_in_inferior PARAMS ((char*));
+
+struct type *builtin_type_scm;
+
+void
+scm_printchar (c, stream)
+ int c;
+ GDB_FILE *stream;
+{
+ fprintf_filtered (stream, "#\\%c", c);
+}
+
+static void
+scm_printstr (stream, string, length, force_ellipses)
+ GDB_FILE *stream;
+ char *string;
+ unsigned int length;
+ int force_ellipses;
+{
+ fprintf_filtered (stream, "\"%s\"", string);
+}
+
+int
+is_scmvalue_type (type)
+ struct type *type;
+{
+ if (TYPE_CODE (type) == TYPE_CODE_INT
+ && TYPE_NAME (type) && strcmp (TYPE_NAME (type), "SCM") == 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/* Get the INDEX'th SCM value, assuming SVALUE is the address
+ of the 0'th one. */
+
+LONGEST
+scm_get_field (svalue, index)
+ LONGEST svalue;
+ int index;
+{
+ value_ptr val;
+ char buffer[20];
+ read_memory (SCM2PTR (svalue) + index * TYPE_LENGTH (builtin_type_scm),
+ buffer, TYPE_LENGTH (builtin_type_scm));
+ return extract_signed_integer (buffer, TYPE_LENGTH (builtin_type_scm));
+}
+
+/* Unpack a value of type TYPE in buffer VALADDR as an integer
+ (if CONTEXT == TYPE_CODE_IN), a pointer (CONTEXT == TYPE_CODE_PTR),
+ or Boolean (CONTEXT == TYPE_CODE_BOOL). */
+
+LONGEST
+scm_unpack (type, valaddr, context)
+ struct type *type;
+ char *valaddr;
+ enum type_code context;
+{
+ if (is_scmvalue_type (type))
+ {
+ LONGEST svalue = extract_signed_integer (valaddr, TYPE_LENGTH (type));
+ if (context == TYPE_CODE_BOOL)
+ {
+ if (svalue == SCM_BOOL_F)
+ return 0;
+ else
+ return 1;
+ }
+ switch (7 & svalue)
+ {
+ case 2: case 6: /* fixnum */
+ return svalue >> 2;
+ case 4: /* other immediate value */
+ if (SCM_ICHRP (svalue)) /* character */
+ return SCM_ICHR (svalue);
+ else if (SCM_IFLAGP (svalue))
+ {
+ switch (svalue)
+ {
+#ifndef SICP
+ case SCM_EOL:
+#endif
+ case SCM_BOOL_F:
+ return 0;
+ case SCM_BOOL_T:
+ return 1;
+ }
+ }
+ error ("Value can't be converted to integer.");
+ default:
+ return svalue;
+ }
+ }
+ else
+ return unpack_long (type, valaddr);
+}
+
+/* True if we're correctly in Guile's eval.c (the evaluator and apply). */
+
+static int
+in_eval_c ()
+{
+ if (current_source_symtab && current_source_symtab->filename)
+ {
+ char *filename = current_source_symtab->filename;
+ int len = strlen (filename);
+ if (len >= 6 && strcmp (filename + len - 6, "eval.c") == 0)
+ return 1;
+ }
+ return 0;
+}
+
+/* Lookup a value for the variable named STR.
+ First lookup in Scheme context (using the scm_lookup_cstr inferior
+ function), then try lookup_symbol for compiled variables. */
+
+value_ptr
+scm_lookup_name (str)
+ char *str;
+{
+ value_ptr args[3];
+ int len = strlen (str);
+ value_ptr symval, func, val;
+ struct symbol *sym;
+ args[0] = value_allocate_space_in_inferior (len);
+ args[1] = value_from_longest (builtin_type_int, len);
+ write_memory (value_as_long (args[0]), str, len);
+
+ if (in_eval_c ()
+ && (sym = lookup_symbol ("env",
+ expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL)) != NULL)
+ args[2] = value_of_variable (sym, expression_context_block);
+ else
+ /* FIXME in this case, we should try lookup_symbol first */
+ args[2] = value_from_longest (builtin_type_scm, SCM_EOL);
+
+ func = find_function_in_inferior ("scm_lookup_cstr");
+ val = call_function_by_hand (func, 3, args);
+ if (!value_logical_not (val))
+ return value_ind (val);
+
+ sym = lookup_symbol (str,
+ expression_context_block,
+ VAR_NAMESPACE, (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym)
+ return value_of_variable (sym, NULL);
+ error ("No symbol \"%s\" in current context.");
+}
+
+value_ptr
+scm_evaluate_string (str, len)
+ char *str; int len;
+{
+ value_ptr func;
+ value_ptr addr = value_allocate_space_in_inferior (len + 1);
+ LONGEST iaddr = value_as_long (addr);
+ write_memory (iaddr, str, len);
+ /* FIXME - should find and pass env */
+ write_memory (iaddr + len, "", 1);
+ func = find_function_in_inferior ("scm_evstr");
+ return call_function_by_hand (func, 1, &addr);
+}
+
+static value_ptr
+evaluate_subexp_scm (expect_type, exp, pos, noside)
+ struct type *expect_type;
+ register struct expression *exp;
+ register int *pos;
+ enum noside noside;
+{
+ enum exp_opcode op = exp->elts[*pos].opcode;
+ int len, pc; char *str;
+ switch (op)
+ {
+ case OP_NAME:
+ pc = (*pos)++;
+ len = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ str = &exp->elts[pc + 2].string;
+ return scm_lookup_name (str);
+ case OP_EXPRSTRING:
+ pc = (*pos)++;
+ len = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+ str = &exp->elts[pc + 2].string;
+ return scm_evaluate_string (str, len);
+ default: ;
+ }
+ return evaluate_subexp_standard (expect_type, exp, pos, noside);
+ nosideret:
+ return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+const struct language_defn scm_language_defn = {
+ "scheme", /* Language name */
+ language_scm,
+ c_builtin_types,
+ range_check_off,
+ type_check_off,
+ scm_parse,
+ c_error,
+ evaluate_subexp_scm,
+ scm_printchar, /* Print a character constant */
+ scm_printstr, /* Function to print string constant */
+ NULL, /* Create fundamental type in this language */
+ c_print_type, /* Print a type using appropriate syntax */
+ scm_val_print, /* Print a value using appropriate syntax */
+ scm_value_print, /* Print a top-level value */
+ {"", "", "", ""}, /* Binary format info */
+ {"#o%lo", "#o", "o", ""}, /* Octal format info */
+ {"%ld", "", "d", ""}, /* Decimal format info */
+ {"#x%lX", "#X", "X", ""}, /* Hex format info */
+ NULL, /* expression operators for printing */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ &builtin_type_char, /* Type of string elements */
+ LANG_MAGIC
+};
+
+void
+_initialize_scheme_language ()
+{
+ add_language (&scm_language_defn);
+ builtin_type_scm = init_type (TYPE_CODE_INT,
+ TARGET_LONG_BIT / TARGET_CHAR_BIT,
+ 0, "SCM", (struct objfile *) NULL);
+}
diff --git a/contrib/gdb/gdb/scm-lang.h b/contrib/gdb/gdb/scm-lang.h
new file mode 100644
index 0000000..f990d77
--- /dev/null
+++ b/contrib/gdb/gdb/scm-lang.h
@@ -0,0 +1,50 @@
+#define SICP
+#include "scm-tags.h"
+#undef SCM_NCELLP
+#define SCM_NCELLP(x) ((SCM_SIZE-1) & (int)(x))
+#define SCM_ITAG8_DATA(X) ((X)>>8)
+#define SCM_ICHR(x) ((unsigned char)SCM_ITAG8_DATA(x))
+#define SCM_ICHRP(x) (SCM_ITAG8(x) == scm_tc8_char)
+#define scm_tc8_char 0xf4
+#define SCM_IFLAGP(n) ((0x87 & (int)(n))==4)
+#define SCM_ISYMNUM(n) ((int)((n)>>9))
+#define SCM_ISYMCHARS(n) (scm_isymnames[SCM_ISYMNUM(n)])
+#define SCM_ILOCP(n) ((0xff & (int)(n))==0xfc)
+#define SCM_ITAG8(X) ((int)(X) & 0xff)
+#define SCM_TYP7(x) (0x7f & (int)SCM_CAR(x))
+#define SCM_LENGTH(x) (((unsigned long)SCM_CAR(x))>>8)
+#define SCM_NCONSP(x) (1 & (int)SCM_CAR(x))
+#define SCM_NECONSP(x) (SCM_NCONSP(x) && (1 != SCM_TYP3(x)))
+#define SCM_CAR(x) scm_get_field (x, 0)
+#define SCM_CDR(x) scm_get_field (x, 1)
+#define SCM_VELTS(x) ((SCM *)SCM_CDR(x))
+#define SCM_CLOSCAR(x) (SCM_CAR(x)-scm_tc3_closure)
+#define SCM_CODE(x) SCM_CAR(SCM_CLOSCAR (x))
+#define SCM_MAKINUM(x) (((x)<<2)+2L)
+
+#ifdef __STDC__ /* Forward decls for prototypes */
+struct value;
+#endif
+
+extern int scm_value_print PARAMS ((struct value *, GDB_FILE*,
+ int, enum val_prettyprint));
+
+extern int scm_val_print PARAMS ((struct type*, char*, CORE_ADDR, GDB_FILE*,
+ int, int, int, enum val_prettyprint));
+
+extern LONGEST scm_get_field PARAMS ((LONGEST, int));
+
+extern int scm_scmval_print PARAMS ((LONGEST, GDB_FILE *,
+ int, int, int, enum val_prettyprint));
+
+extern int is_scmvalue_type PARAMS ((struct type*));
+
+extern void scm_printchar PARAMS ((int, GDB_FILE*));
+
+extern struct value * scm_evaluate_string PARAMS ((char*, int));
+
+extern struct type *builtin_type_scm;
+
+extern int scm_parse ();
+
+extern LONGEST scm_unpack PARAMS ((struct type *, char *, enum type_code));
diff --git a/contrib/gdb/gdb/scm-tags.h b/contrib/gdb/gdb/scm-tags.h
new file mode 100644
index 0000000..a3b736b
--- /dev/null
+++ b/contrib/gdb/gdb/scm-tags.h
@@ -0,0 +1,385 @@
+/* This is a minimally edited version of Guile's tags.h. */
+/* classes: h_files */
+
+#ifndef TAGSH
+#define TAGSH
+/* Copyright (C) 1995 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
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE. If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way. To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+
+/** This file defines the format of SCM values and cons pairs.
+ ** It is here that tag bits are assigned for various purposes.
+ **/
+
+
+/* Three Bit Tags
+ *
+ * 000 -- a non-immediate value. Points into the pair heap.
+ *
+ * 001 -- a gloc (i.e., a resolved global variable in a CAR in a code graph)
+ * or the CAR of an object handle (i.e., the tagged pointer to the
+ * vtable part of a user-defined object).
+ *
+ * If X has this tag, the value at CDAR(X - 1) distinguishes
+ * glocs from object handles. The distinction only needs
+ * to be made in a few places. Only a few parts of the code know
+ * about glocs. In most cases, when a value in the CAR of a pair
+ * has the tag 001, it means that the pair is an object handle.
+ *
+ * 010 -- the tag for immediate, exact integers.
+ *
+ * 011 -- in the CAR of a pair, this tag indicates that the pair is a closure.
+ * The remaining bits of the CAR are a pointer into the pair heap
+ * to the code graph for the closure.
+ *
+ * 1xy -- an extension tag which means that there is a five or six bit
+ * tag to the left of the low three bits. See the nice diagrams
+ * in ../doc/code.doc if you want to know what the bits mean.
+ */
+
+
+
+
+
+#define scm_tc3_cons 0
+#define scm_tc3_cons_gloc 1
+#define scm_tc3_closure 3
+
+#define scm_tc7_ssymbol 5
+#define scm_tc7_msymbol 7
+#define scm_tc7_string 13
+#define scm_tc7_bvect 15
+#define scm_tc7_vector 21
+#define scm_tc7_lvector 23
+#define scm_tc7_ivect 29
+#define scm_tc7_uvect 31
+/* spare 37 39 */
+#define scm_tc7_fvect 45
+#define scm_tc7_dvect 47
+#define scm_tc7_cvect 53
+#define scm_tc7_port 55
+#define scm_tc7_contin 61
+#define scm_tc7_cclo 63
+/* spare 69 71 77 79 */
+#define scm_tc7_subr_0 85
+#define scm_tc7_subr_1 87
+#define scm_tc7_cxr 93
+#define scm_tc7_subr_3 95
+#define scm_tc7_subr_2 101
+#define scm_tc7_asubr 103
+#define scm_tc7_subr_1o 109
+#define scm_tc7_subr_2o 111
+#define scm_tc7_lsubr_2 117
+#define scm_tc7_lsubr 119
+#define scm_tc7_rpsubr 125
+
+#define scm_tc7_smob 127
+#define scm_tc_free_cell 127
+
+#define scm_tc16_flo 0x017f
+#define scm_tc_flo 0x017fL
+
+#define SCM_REAL_PART (1L<<16)
+#define SCM_IMAG_PART (2L<<16)
+#define scm_tc_dblr (scm_tc16_flo|REAL_PART)
+#define scm_tc_dblc (scm_tc16_flo|REAL_PART|IMAG_PART)
+
+#define scm_tc16_bigpos 0x027f
+#define scm_tc16_bigneg 0x037f
+
+#define scm_tc16_fport (scm_tc7_port + 0*256L)
+#define scm_tc16_pipe (scm_tc7_port + 1*256L)
+#define scm_tc16_strport (scm_tc7_port + 2*256L)
+#define scm_tc16_sfport (scm_tc7_port + 3*256L)
+
+
+
+/* For cons pairs with immediate values in the CAR */
+#define scm_tcs_cons_imcar 2:case 4:case 6:case 10:\
+ case 12:case 14:case 18:case 20:\
+ case 22:case 26:case 28:case 30:\
+ case 34:case 36:case 38:case 42:\
+ case 44:case 46:case 50:case 52:\
+ case 54:case 58:case 60:case 62:\
+ case 66:case 68:case 70:case 74:\
+ case 76:case 78:case 82:case 84:\
+ case 86:case 90:case 92:case 94:\
+ case 98:case 100:case 102:case 106:\
+ case 108:case 110:case 114:case 116:\
+ case 118:case 122:case 124:case 126
+
+/* For cons pairs with non-immediate values in the CAR */
+#define scm_tcs_cons_nimcar 0:case 8:case 16:case 24:\
+ case 32:case 40:case 48:case 56:\
+ case 64:case 72:case 80:case 88:\
+ case 96:case 104:case 112:case 120
+
+/* A CONS_GLOC occurs in code. It's CAR is a pointer to the
+ * CDR of a variable. The low order bits of the CAR are 001.
+ * The CDR of the gloc is the code continuation.
+ */
+#define scm_tcs_cons_gloc 1:case 9:case 17:case 25:\
+ case 33:case 41:case 49:case 57:\
+ case 65:case 73:case 81:case 89:\
+ case 97:case 105:case 113:case 121
+
+#define scm_tcs_closures 3:case 11:case 19:case 27:\
+ case 35:case 43:case 51:case 59:\
+ case 67:case 75:case 83:case 91:\
+ case 99:case 107:case 115:case 123
+
+#define scm_tcs_subrs scm_tc7_asubr:case scm_tc7_subr_0:case scm_tc7_subr_1:case scm_tc7_cxr:\
+ case scm_tc7_subr_3:case scm_tc7_subr_2:case scm_tc7_rpsubr:case scm_tc7_subr_1o:\
+ case scm_tc7_subr_2o:case scm_tc7_lsubr_2:case scm_tc7_lsubr
+
+#define scm_tcs_symbols scm_tc7_ssymbol:case scm_tc7_msymbol
+
+#define scm_tcs_bignums tc16_bigpos:case tc16_bigneg
+
+
+
+/* References to objects are of type SCM. Values may be non-immediate
+ * (pointers) or immediate (encoded, immutable, scalar values that fit
+ * in an SCM variable).
+ */
+
+typedef long SCM;
+
+/* Cray machines have pointers that are incremented once for each word,
+ * rather than each byte, the 3 most significant bits encode the byte
+ * within the word. The following macros deal with this by storing the
+ * native Cray pointers like the ones that looks like scm expects. This
+ * is done for any pointers that might appear in the car of a scm_cell, pointers
+ * to scm_vector elts, functions, &c are not munged.
+ */
+#ifdef _UNICOS
+# define SCM2PTR(x) ((int)(x) >> 3)
+# define PTR2SCM(x) (((SCM)(x)) << 3)
+# define SCM_POINTERS_MUNGED
+#else
+# define SCM2PTR(x) (x)
+# define PTR2SCM(x) ((SCM)(x))
+#endif /* def _UNICOS */
+
+
+
+/* Immediate? Predicates
+ */
+#define SCM_IMP(x) (6 & (int)(x))
+#define SCM_NIMP(x) (!SCM_IMP(x))
+
+
+
+enum scm_tags
+{
+ scm_tc8_char = 0xf4
+};
+
+#define SCM_ITAG8(X) ((int)(X) & 0xff)
+#define SCM_MAKE_ITAG8(X, TAG) (((X)<<8) + TAG)
+#define SCM_ITAG8_DATA(X) ((X)>>8)
+
+
+
+/* Local Environment Structure
+ */
+#define SCM_ILOCP(n) ((0xff & (int)(n))==0xfc)
+#define SCM_ILOC00 (0x000000fcL)
+#define SCM_IDINC (0x00100000L)
+#define SCM_ICDR (0x00080000L)
+#define SCM_IFRINC (0x00000100L)
+#define SCM_IDSTMSK (-SCM_IDINC)
+#define SCM_IFRAME(n) ((int)((SCM_ICDR-SCM_IFRINC)>>8) & ((int)(n)>>8))
+#define SCM_IDIST(n) (((unsigned long)(n))>>20)
+#define SCM_ICDRP(n) (SCM_ICDR & (n))
+
+
+/* Immediate Symbols, Special Symbols, Flags (various constants).
+ */
+
+/* ISYMP tests for ISPCSYM and ISYM */
+#define SCM_ISYMP(n) ((0x187 & (int)(n))==4)
+
+/* IFLAGP tests for ISPCSYM, ISYM and IFLAG */
+#define SCM_IFLAGP(n) ((0x87 & (int)(n))==4)
+#define SCM_ISYMNUM(n) ((int)((n)>>9))
+#define SCM_ISYMCHARS(n) (scm_isymnames[SCM_ISYMNUM(n)])
+#define SCM_MAKSPCSYM(n) (((n)<<9)+((n)<<3)+4L)
+#define SCM_MAKISYM(n) (((n)<<9)+0x74L)
+#define SCM_MAKIFLAG(n) (((n)<<9)+0x174L)
+
+/* This table must agree with the declarations
+ * in repl.c: {Names of immediate symbols}.
+ *
+ * These are used only in eval but their values
+ * have to be allocated here.
+ *
+ */
+
+#define SCM_IM_AND SCM_MAKSPCSYM(0)
+#define SCM_IM_BEGIN SCM_MAKSPCSYM(1)
+#define SCM_IM_CASE SCM_MAKSPCSYM(2)
+#define SCM_IM_COND SCM_MAKSPCSYM(3)
+#define SCM_IM_DO SCM_MAKSPCSYM(4)
+#define SCM_IM_IF SCM_MAKSPCSYM(5)
+#define SCM_IM_LAMBDA SCM_MAKSPCSYM(6)
+#define SCM_IM_LET SCM_MAKSPCSYM(7)
+#define SCM_IM_LETSTAR SCM_MAKSPCSYM(8)
+#define SCM_IM_LETREC SCM_MAKSPCSYM(9)
+#define SCM_IM_OR SCM_MAKSPCSYM(10)
+#define SCM_IM_QUOTE SCM_MAKSPCSYM(11)
+#define SCM_IM_SET SCM_MAKSPCSYM(12)
+#define SCM_IM_DEFINE SCM_MAKSPCSYM(13)
+#define SCM_IM_APPLY SCM_MAKISYM(14)
+#define SCM_IM_CONT SCM_MAKISYM(15)
+#define SCM_NUM_ISYMS 16
+
+/* Important immediates
+ */
+
+#define SCM_BOOL_F SCM_MAKIFLAG(SCM_NUM_ISYMS+0)
+#define SCM_BOOL_T SCM_MAKIFLAG(SCM_NUM_ISYMS+1)
+#define SCM_UNDEFINED SCM_MAKIFLAG(SCM_NUM_ISYMS+2)
+#define SCM_EOF_VAL SCM_MAKIFLAG(SCM_NUM_ISYMS+3)
+
+#ifdef SICP
+#define SCM_EOL SCM_BOOL_F
+#else
+#define SCM_EOL SCM_MAKIFLAG(SCM_NUM_ISYMS+4)
+#endif
+
+#define SCM_UNSPECIFIED SCM_MAKIFLAG(SCM_NUM_ISYMS+5)
+
+
+
+/* Heap Pairs and the Empty List Predicates
+ */
+#define SCM_NULLP(x) (SCM_EOL == (x))
+#define SCM_NNULLP(x) (SCM_EOL != (x))
+#define SCM_CELLP(x) (!SCM_NCELLP(x))
+#define SCM_NCELLP(x) ((sizeof(scm_cell)-1) & (int)(x))
+
+
+
+#define SCM_UNBNDP(x) (SCM_UNDEFINED==(x))
+
+
+
+/* Testing and Changing GC Marks in Various Standard Positions
+ */
+#define SCM_GCMARKP(x) (1 & (int)SCM_CDR(x))
+#define SCM_GC8MARKP(x) (0x80 & (int)SCM_CAR(x))
+#define SCM_SETGCMARK(x) (SCM_CDR(x) |= 1)
+#define SCM_CLRGCMARK(x) (SCM_CDR(x) &= ~1L)
+#define SCM_SETGC8MARK(x) (SCM_CAR(x) |= 0x80)
+#define SCM_CLRGC8MARK(x) (SCM_CAR(x) &= ~0x80L)
+
+
+/* Extracting Tag Bits, With or Without GC Safety and Optional Bits
+ */
+#define SCM_TYP3(x) (7 & (int)SCM_CAR(x))
+#define SCM_TYP7(x) (0x7f & (int)SCM_CAR(x))
+#define SCM_TYP7S(x) (0x7d & (int)SCM_CAR(x))
+#define SCM_TYP16(x) (0xffff & (int)SCM_CAR(x))
+#define SCM_TYP16S(x) (0xfeff & (int)SCM_CAR(x))
+#define SCM_GCTYP16(x) (0xff7f & (int)SCM_CAR(x))
+
+
+/* Two slightly extensible types: smobs and ptobs.
+ *
+ */
+#define SCM_SMOBNUM(x) (0x0ff & (CAR(x)>>8));
+#define SCM_PTOBNUM(x) (0x0ff & (CAR(x)>>8));
+
+
+
+
+#define SCM_DIRP(x) (SCM_NIMP(x) && (TYP16(x)==(scm_tc16_dir)))
+#define SCM_OPDIRP(x) (SCM_NIMP(x) && (CAR(x)==(scm_tc16_dir | OPN)))
+
+
+
+/* Lvectors
+ */
+#define SCM_LVECTORP(x) (TYP7(x)==tc7_lvector)
+
+
+#if 0
+
+/* Sockets
+ */
+#define tc_socket (tc7_port | OPN)
+#define SCM_SOCKP(x) (((0x7f | OPN | RDNG | WRTNG) & CAR(x))==(tc_socket))
+#define SCM_SOCKTYP(x) (CAR(x)>>24)
+
+
+
+extern int scm_tc16_key_vector;
+#define SCM_KEYVECP(X) (scm_tc16_key_vector == TYP16 (X))
+#define SCM_KEYVECLEN(OBJ) (((unsigned long)CAR (obj)) >> 16)
+
+
+#define SCM_MALLOCDATA(obj) ((char *)CDR(obj))
+#define SCM_MALLOCLEN(obj) (((unsigned long)CAR (obj)) >> 16)
+#define SCM_WORDDATA(obj) (CDR (obj))
+
+
+#define SCM_BYTECODEP(X) ((TYP7 (X) == tc7_cclo) && (CCLO_SUBR (X) == rb_proc))
+#define SCM_BYTECODE_CONSTANTS(X) (VELTS(X)[1])
+#define SCM_BYTECODE_CODE(X) (VELTS(X)[2])
+#define SCM_BYTECODE_NAME(X) (VELTS(X)[3])
+#define SCM_BYTECODE_BCODE(X) (VELTS(X)[4])
+#define SCM_BYTECODE_ELTS 5
+
+
+#define SCM_FREEP(x) (CAR(x)==tc_free_cell)
+#define SCM_NFREEP(x) (!FREEP(x))
+
+#endif /* 0*/
+
+#ifdef __STDC__
+
+#else /* STDC */
+
+#endif /* STDC */
+
+
+#endif /* TAGSH */
diff --git a/contrib/gdb/gdb/scm-valprint.c b/contrib/gdb/gdb/scm-valprint.c
new file mode 100644
index 0000000..8544870
--- /dev/null
+++ b/contrib/gdb/gdb/scm-valprint.c
@@ -0,0 +1,404 @@
+/* Scheme/Guile language support routines for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "value.h"
+#include "scm-lang.h"
+#include "valprint.h"
+
+/* Prints the SCM value VALUE by invoking the inferior, if appropraite.
+ Returns >= 0 on succes; retunr -1 if the inferior cannot/should not
+ print VALUE. */
+
+int
+scm_inferior_print (value, stream, format, deref_ref, recurse, pretty)
+ LONGEST value;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ return -1;
+}
+
+/* {Names of immediate symbols}
+ * This table must agree with the declarations in scm.h: {Immediate Symbols}.*/
+
+static char *scm_isymnames[] =
+{
+ /* This table must agree with the declarations */
+ "and",
+ "begin",
+ "case",
+ "cond",
+ "do",
+ "if",
+ "lambda",
+ "let",
+ "let*",
+ "letrec",
+ "or",
+ "quote",
+ "set!",
+ "define",
+#if 0
+ "literal-variable-ref",
+ "literal-variable-set!",
+#endif
+ "apply",
+ "call-with-current-continuation",
+
+ /* user visible ISYMS */
+ /* other keywords */
+ /* Flags */
+
+ "#f",
+ "#t",
+ "#<undefined>",
+ "#<eof>",
+ "()",
+ "#<unspecified>"
+};
+
+static int
+scm_scmlist_print (svalue, stream, format, deref_ref, recurse, pretty)
+ LONGEST svalue;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ unsigned int more = print_max;
+ if (recurse > 6)
+ {
+ fputs_filtered ("...", stream);
+ return 0;
+ }
+ scm_scmval_print (SCM_CAR (svalue), stream, format,
+ deref_ref, recurse + 1, pretty);
+ svalue = SCM_CDR (svalue);
+ for (; SCM_NIMP (svalue); svalue = SCM_CDR (svalue))
+ {
+ if (SCM_NECONSP (svalue))
+ break;
+ fputs_filtered (" ", stream);
+ if (--more == 0)
+ {
+ fputs_filtered ("...", stream);
+ return;
+ }
+ scm_scmval_print (SCM_CAR (svalue), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ if (SCM_NNULLP (svalue))
+ {
+ fputs_filtered (" . ", stream);
+ scm_scmval_print (svalue, stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+}
+
+static void
+scm_ipruk (hdr, ptr, stream)
+ char *hdr;
+ LONGEST ptr;
+ GDB_FILE *stream;
+{
+ fprintf_filtered (stream, "#<unknown-%s", hdr);
+#define SCM_SIZE TYPE_LENGTH (builtin_type_scm)
+ if (SCM_CELLP (ptr))
+ fprintf_filtered (stream, " (0x%lx . 0x%lx) @",
+ (long) SCM_CAR (ptr), (long) SCM_CDR (ptr));
+ fprintf_filtered (stream, " 0x%x>", ptr);
+}
+
+int
+scm_scmval_print (svalue, stream, format, deref_ref, recurse, pretty)
+ LONGEST svalue;
+ GDB_FILE *stream;
+ int format;
+ int deref_ref;
+ int recurse;
+ enum val_prettyprint pretty;
+{
+ taloop:
+ switch (7 & svalue)
+ {
+ case 2:
+ case 6:
+ print_longest (stream, format ? format : 'd', 1, svalue >> 2);
+ break;
+ case 4:
+ if (SCM_ICHRP (svalue))
+ {
+ svalue = SCM_ICHR (svalue);
+ scm_printchar (svalue, stream);
+ break;
+ }
+ else if (SCM_IFLAGP (svalue)
+ && (SCM_ISYMNUM (svalue)
+ < (sizeof scm_isymnames / sizeof (char *))))
+ {
+ fputs_filtered (SCM_ISYMCHARS (svalue), stream);
+ break;
+ }
+ else if (SCM_ILOCP (svalue))
+ {
+ fprintf_filtered (stream, "#@%ld%c%ld",
+ (long) SCM_IFRAME (svalue),
+ SCM_ICDRP (svalue) ? '-' : '+',
+ (long) SCM_IDIST (svalue));
+ break;
+ }
+ else
+ goto idef;
+ break;
+ case 1:
+ /* gloc */
+ svalue = SCM_CAR (svalue - 1);
+ goto taloop;
+ default:
+ idef:
+ scm_ipruk ("immediate", svalue, stream);
+ break;
+ case 0:
+
+ switch (SCM_TYP7 (svalue))
+ {
+ case scm_tcs_cons_gloc:
+ if (SCM_CDR (SCM_CAR (svalue) - 1L) == 0)
+ {
+ SCM name;
+ fputs_filtered ("#<latte ", stream);
+#if 1
+ fputs_filtered ("???", stream);
+#else
+ name = ((SCM n*)(STRUCT_TYPE( exp)))[struct_i_name];
+ scm_lfwrite (CHARS (name),
+ (sizet) sizeof (char),
+ (sizet) LENGTH (name),
+ port);
+#endif
+ fprintf_filtered (stream, " #X%lX>", svalue);
+ break;
+ }
+ case scm_tcs_cons_imcar:
+ case scm_tcs_cons_nimcar:
+ fputs_filtered ("(", stream);
+ scm_scmlist_print (svalue, stream, format,
+ deref_ref, recurse + 1, pretty);
+ fputs_filtered (")", stream);
+ break;
+ case scm_tcs_closures:
+ fputs_filtered ("#<CLOSURE ", stream);
+ scm_scmlist_print (SCM_CODE (svalue), stream, format,
+ deref_ref, recurse + 1, pretty);
+ fputs_filtered (">", stream);
+ break;
+ case scm_tc7_string:
+ {
+ int len = SCM_LENGTH (svalue);
+ CORE_ADDR addr = (CORE_ADDR) SCM_CDR (svalue);
+ int i;
+ int done = 0;
+ int buf_size;
+ char buffer[64];
+ int truncate = print_max && len > (int) print_max;
+ if (truncate)
+ len = print_max;
+ fputs_filtered ("\"", stream);
+ for (; done < len; done += buf_size)
+ {
+ buf_size = min (len - done, 64);
+ read_memory (addr + done, buffer, buf_size);
+
+ for (i = 0; i < buf_size; ++i)
+ switch (buffer[i])
+ {
+ case '\"':
+ case '\\':
+ fputs_filtered ("\\", stream);
+ default:
+ fprintf_filtered (stream, "%c", buffer[i]);
+ }
+ }
+ fputs_filtered (truncate ? "...\"" : "\"", stream);
+ break;
+ }
+ break;
+ case scm_tcs_symbols:
+ {
+ int len = SCM_LENGTH (svalue);
+
+ char * str = (char*) alloca (len);
+ read_memory (SCM_CDR (svalue), str, len + 1);
+ /* Should handle weird characters FIXME */
+ str[len] = '\0';
+ fputs_filtered (str, stream);
+ break;
+ }
+ case scm_tc7_vector:
+ {
+ int len = SCM_LENGTH (svalue);
+ int i;
+ LONGEST elements = SCM_CDR(svalue);
+ fputs_filtered ("#(", stream);
+ for (i = 0; i < len; ++i)
+ {
+ if (i > 0)
+ fputs_filtered (" ", stream);
+ scm_scmval_print (scm_get_field (elements, i), stream, format,
+ deref_ref, recurse + 1, pretty);
+ }
+ fputs_filtered (")", stream);
+ }
+ break;
+#if 0
+ case tc7_lvector:
+ {
+ SCM result;
+ SCM hook;
+ hook = scm_get_lvector_hook (exp, LV_PRINT_FN);
+ if (hook == BOOL_F)
+ {
+ scm_puts ("#<locked-vector ", port);
+ scm_intprint(CDR(exp), 16, port);
+ scm_puts (">", port);
+ }
+ else
+ {
+ result
+ = scm_apply (hook,
+ scm_listify (exp, port, (writing ? BOOL_T : BOOL_F),
+ SCM_UNDEFINED),
+ EOL);
+ if (result == BOOL_F)
+ goto punk;
+ }
+ break;
+ }
+ break;
+ case tc7_bvect:
+ case tc7_ivect:
+ case tc7_uvect:
+ case tc7_fvect:
+ case tc7_dvect:
+ case tc7_cvect:
+ scm_raprin1 (exp, port, writing);
+ break;
+#endif
+ case scm_tcs_subrs:
+ {
+ int index = SCM_CAR (svalue) >> 8;
+#if 1
+ char str[20];
+ sprintf (str, "#%d", index);
+#else
+ char *str = index ? SCM_CHARS (scm_heap_org+index) : "";
+#define SCM_CHARS(x) ((char *)(SCM_CDR(x)))
+ char *str = CHARS (SNAME (exp));
+#endif
+ fprintf_filtered (stream, "#<primitive-procedure %s>",
+ str);
+ }
+ break;
+#if 0
+#ifdef CCLO
+ case tc7_cclo:
+ scm_puts ("#<compiled-closure ", port);
+ scm_iprin1 (CCLO_SUBR (exp), port, writing);
+ scm_putc ('>', port);
+ break;
+#endif
+ case tc7_contin:
+ fprintf_filtered (stream, "#<continuation %d @ #X%lx >",
+ LENGTH (svalue),
+ (long) CHARS (svalue));
+ break;
+ case tc7_port:
+ i = PTOBNUM (exp);
+ if (i < scm_numptob && scm_ptobs[i].print && (scm_ptobs[i].print) (exp, port, writing))
+ break;
+ goto punk;
+ case tc7_smob:
+ i = SMOBNUM (exp);
+ if (i < scm_numsmob && scm_smobs[i].print
+ && (scm_smobs[i].print) (exp, port, writing))
+ break;
+ goto punk;
+#endif
+ default:
+ punk:scm_ipruk ("type", svalue, stream);
+ }
+ break;
+ }
+}
+
+int
+scm_val_print (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;
+{
+ if (is_scmvalue_type (type))
+ {
+ LONGEST svalue = extract_signed_integer (valaddr, TYPE_LENGTH (type));
+ if (scm_inferior_print (svalue, stream, format,
+ deref_ref, recurse, pretty) >= 0)
+ {
+ }
+ else
+ {
+ scm_scmval_print (svalue, stream, format,
+ deref_ref, recurse, pretty);
+ }
+
+ gdb_flush (stream);
+ return (0);
+ }
+ else
+ {
+ return c_val_print (type, valaddr, address, stream, format,
+ deref_ref, recurse, pretty);
+ }
+}
+
+int
+scm_value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ return (val_print (VALUE_TYPE (val), VALUE_CONTENTS (val),
+ VALUE_ADDRESS (val), stream, format, 1, 0, pretty));
+}
diff --git a/contrib/gdb/gdb/ser-e7kpc.c b/contrib/gdb/gdb/ser-e7kpc.c
new file mode 100644
index 0000000..9faf7dd
--- /dev/null
+++ b/contrib/gdb/gdb/ser-e7kpc.c
@@ -0,0 +1,420 @@
+/* Remote serial interface using Hitachi E7000 PC ISA card in a PC
+
+ Copyright 1994 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __GO32__
+#include "defs.h"
+#include "serial.h"
+#include <sys/dos.h>
+
+
+
+static int e7000pc_open PARAMS ((serial_t scb, const char *name));
+static void e7000pc_raw PARAMS ((serial_t scb));
+static int e7000pc_readchar PARAMS ((serial_t scb, int timeout));
+static int e7000pc_setbaudrate PARAMS ((serial_t scb, int rate));
+static int e7000pc_write PARAMS ((serial_t scb, const char *str, int len));
+static void e7000pc_close PARAMS ((serial_t scb));
+static serial_ttystate e7000pc_get_tty_state PARAMS ((serial_t scb));
+static int e7000pc_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static char *aptr PARAMS ((short p));
+
+static int dos_async_init PARAMS ((int port));
+static void dos_async_tx PARAMS ((const char c));
+static int dos_async_rx PARAMS (());
+
+
+
+#define OFF_DPD 0x0000
+#define OFF_DDP 0x1000
+#define OFF_CPD 0x2000
+#define OFF_CDP 0x2400
+#define OFF_FA 0x3000
+#define OFF_FB 0x3002
+#define OFF_FC 0x3004
+#define OFF_IRQTOD 0x3008
+#define OFF_IRQTOP 0x300a
+#define OFF_READY 0x300c
+#define OFF_PON 0x300e
+
+#define IDLE 0x0000
+#define CMD_CI 0x4349
+#define CMD_CO 0x434f
+#define CMD_LO 0x4c4f
+#define CMD_LS 0x4c53
+#define CMD_SV 0x5356
+#define CMD_SS 0x5353
+#define CMD_OK 0x4f4b
+#define CMD_ER 0x4552
+#define CMD_NF 0x4e46
+#define CMD_AB 0x4142
+#define CMD_ED 0x4544
+#define CMD_CE 0x4345
+
+static unsigned long fa;
+static unsigned long irqtod;
+static unsigned long ready;
+static unsigned long fb;
+static unsigned long cpd ;
+static unsigned long cdp ;
+static unsigned long ready;
+static unsigned long pon;
+static unsigned long irqtop;
+static unsigned long board_at;
+
+#define SET_BYTE(x,y) { char _buf = y;dosmemput(&_buf,1, x);}
+#define SET_WORD(x,y) { short _buf = y;dosmemput(&_buf,2, x);}
+#define GET_BYTE(x) ( dosmemget(x,1,&bb), bb)
+#define GET_WORD(x) ( dosmemget(x,2,&sb), sb)
+
+static unsigned char bb;
+static unsigned short sb;
+
+
+static struct sw
+{
+ int sw;
+ int addr;
+} sigs[] = {
+ {0x14, 0xd0000},
+ {0x15, 0xd4000},
+ {0x16, 0xd8000},
+ {0x17, 0xdc000},
+ 0};
+
+static int
+e7000pc_init ()
+{
+ /* Look around in memory for the board's signature */
+
+ int try;
+
+ for (try = 0; sigs[try].sw; try++)
+
+ {
+ int val;
+ board_at = sigs[try].addr;
+ fa = board_at + OFF_FA;
+ fb = board_at + OFF_FB;
+ cpd = board_at + OFF_CPD;
+ cdp = board_at + OFF_CDP;
+ ready =board_at + OFF_READY;
+ pon = board_at + OFF_PON;
+ irqtop = board_at + OFF_IRQTOP;
+ irqtod = board_at + OFF_IRQTOD;
+
+ val = GET_WORD (ready);
+
+ if (val == (0xaaa0 | sigs[try].sw))
+ {
+ if (GET_BYTE (pon) & 0xf)
+ {
+ SET_BYTE(fa, 0);
+ SET_BYTE (fb, 0);
+
+ SET_BYTE (irqtop, 1); /* Disable interrupts from e7000 */
+ SET_WORD (ready, 1);
+ printf_filtered ("\nConnected to the E7000PC at address 0x%x\n",
+ sigs[try].addr);
+ return 1;
+ }
+ error ("The E7000 PC board is working, but the E7000 is turned off.\n");
+ return 0;
+ }
+ }
+
+ error ("GDB cannot connect to the E7000 PC board, check that it is installed\n\
+and that the switch settings are correct. Some other DOS programs can \n\
+stop the board from working. Try starting from a very minimal boot, \n\
+perhaps you need to disable EMM386 over the region where the board has\n\
+its I/O space, remove other unneeded cards, etc etc\n");
+ return 0;
+
+}
+
+static int pbuf_size;
+static int pbuf_index;
+
+static
+int
+e7000_get ()
+{
+ static char pbuf[1000];
+ char tmp[1000];
+ int x;
+ if (pbuf_index < pbuf_size)
+ {
+ x = pbuf[pbuf_index++];
+ }
+ else if ((GET_BYTE (fb) & 1))
+ {
+ int i;
+ pbuf_size = GET_WORD(cdp + 2);
+
+ dosmemget (cdp + 8, pbuf_size + 1, tmp);
+
+ /* Tell the E7000 we've eaten */
+ SET_BYTE(fb,0);
+ /* Swap it around */
+ for (i = 0; i < pbuf_size; i++)
+ {
+ pbuf[i] = tmp[i^1];
+ }
+ pbuf_index = 0;
+ x = pbuf[pbuf_index++];
+ }
+ else
+ {
+ x = -1;
+ }
+ return x;
+}
+
+static int
+dosasync_read (fd, buf, len, timeout)
+ int fd;
+ char *buf;
+ int len;
+ int timeout;
+
+{
+ long now;
+ long then;
+ int i = 0;
+ int p;
+
+ /* Then look for some more if we're still hungry */
+ time (&now);
+ then = now + timeout;
+ while (i < len)
+ {
+ int ch = e7000_get();
+
+ /* While there's room in the buffer, and we've already
+ read the stuff in, suck it over */
+ if (ch != -1)
+ {
+ buf[i++] = ch;
+ while (i < len && pbuf_index < pbuf_size )
+ {
+ ch = e7000_get();
+ if (ch == -1)
+ break;
+ buf[i++] = ch;
+ }
+ }
+
+ time (&now);
+
+ if (timeout == 0)
+ return i;
+ if (now >= then && timeout > 0)
+ {
+ return i;
+ }
+ }
+ return len;
+}
+
+
+static int
+dosasync_write (fd, buf, len)
+ int fd;
+ const char *buf;
+ int len;
+{
+ int i;
+ char dummy[1000];
+
+
+ /* Construct copy locally */
+ ((short *)dummy)[0] = CMD_CI;
+ ((short *)dummy)[1] = len;
+ ((short *)dummy)[2] = 0;
+ ((short *)dummy)[3] = 0;
+ for (i = 0; i < len ; i++)
+ {
+ dummy[8 + i ^ 1] = buf[i];
+ }
+
+ /* Wait for the card to get ready */
+ while ((GET_BYTE(fa) & 1) != 0)
+ ;
+
+ /* Blast onto the ISA card */
+ dosmemput (dummy, 8 + len + 1, cpd);
+
+ SET_BYTE(fa, 1);
+ SET_BYTE(irqtod, 1); /* Interrupt the E7000 */
+
+ return len;
+}
+
+static int
+e7000pc_open (scb, name)
+ serial_t scb;
+ const char *name;
+{
+ if (strncasecmp (name, "pc", 2) != 0)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ scb->fd = e7000pc_init ();
+
+ if (!scb->fd)
+ return -1;
+
+ return 0;
+}
+
+static int
+e7000pc_noop (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+e7000pc_raw (scb)
+ serial_t scb;
+{
+ /* Always in raw mode */
+}
+
+static int
+e7000pc_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ char buf;
+
+ top:
+
+ if (dosasync_read (scb->fd, &buf, 1, timeout))
+ {
+ if (buf == 0) goto top;
+ return buf;
+ }
+ else
+ return SERIAL_TIMEOUT;
+}
+
+struct e7000pc_ttystate {
+ int dummy;
+};
+
+/* e7000pc_{get set}_tty_state() are both dummys to fill out the function
+ vector. Someday, they may do something real... */
+
+static serial_ttystate
+e7000pc_get_tty_state (scb)
+ serial_t scb;
+{
+ struct e7000pc_ttystate *state;
+
+ state = (struct e7000pc_ttystate *) xmalloc (sizeof *state);
+
+ return (serial_ttystate) state;
+}
+
+static int
+e7000pc_set_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ return 0;
+}
+
+static int
+e7000pc_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ return 0;
+}
+
+static void
+e7000pc_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print. */
+ return;
+}
+
+static int
+e7000pc_setbaudrate (scb, rate)
+ serial_t scb;
+ int rate;
+{
+ return 0;
+}
+
+static int
+e7000pc_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ dosasync_write (scb->fd, str, len);
+
+ return 0;
+}
+
+static void
+e7000pc_close (scb)
+ serial_t scb;
+{
+}
+
+static struct serial_ops e7000pc_ops =
+{
+ "pc",
+ 0,
+ e7000pc_open,
+ e7000pc_close,
+ e7000pc_readchar,
+ e7000pc_write,
+ e7000pc_noop, /* flush output */
+ e7000pc_noop, /* flush input */
+ e7000pc_noop, /* send break -- currently used only for nindy */
+ e7000pc_raw,
+ e7000pc_get_tty_state,
+ e7000pc_set_tty_state,
+ e7000pc_print_tty_state,
+ e7000pc_noflush_set_tty_state,
+ e7000pc_setbaudrate,
+};
+
+void
+_initialize_ser_e7000pc ()
+{
+ serial_add_interface (&e7000pc_ops);
+}
+#else
+
+void
+_initialize_ser_e7000pc ()
+{
+
+}
+#endif
diff --git a/contrib/gdb/gdb/ser-go32.c b/contrib/gdb/gdb/ser-go32.c
new file mode 100644
index 0000000..4af25f1
--- /dev/null
+++ b/contrib/gdb/gdb/ser-go32.c
@@ -0,0 +1,957 @@
+/* Remote serial interface for local (hardwired) serial ports for
+ GO32. Copyright 1992, 1993 Free Software Foundation, Inc.
+
+ Contributed by Nigel Stephens, Algorithmics Ltd. (nigel@algor.co.uk).
+
+ This version uses DPMI interrupts to handle buffered i/o
+ without the separate "asynctsr" program.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "serial.h"
+
+
+/*
+ * NS16550 UART registers
+ */
+
+#define COM1ADDR 0x3f8
+#define COM2ADDR 0x2f8
+#define COM3ADDR 0x3e8
+#define COM4ADDR 0x3e0
+
+#define com_data 0 /* data register (R/W) */
+#define com_dlbl 0 /* divisor latch low (W) */
+#define com_ier 1 /* interrupt enable (W) */
+#define com_dlbh 1 /* divisor latch high (W) */
+#define com_iir 2 /* interrupt identification (R) */
+#define com_fifo 2 /* FIFO control (W) */
+#define com_lctl 3 /* line control register (R/W) */
+#define com_cfcr 3 /* line control register (R/W) */
+#define com_mcr 4 /* modem control register (R/W) */
+#define com_lsr 5 /* line status register (R/W) */
+#define com_msr 6 /* modem status register (R/W) */
+
+/*
+ * Constants for computing 16 bit baud rate divisor (lower byte
+ * in com_dlbl, upper in com_dlbh) from 1.8432MHz crystal. Divisor is
+ * 1.8432 MHz / (16 * X) for X bps. If the baud rate can't be set
+ * to within +- (desired_rate*SPEED_TOLERANCE/1000) bps, we fail.
+ */
+#define COMTICK (1843200/16)
+#define SPEED_TOLERANCE 30 /* thousandths; real == desired +- 3.0% */
+
+/* interrupt enable register */
+#define IER_ERXRDY 0x1 /* int on rx ready */
+#define IER_ETXRDY 0x2 /* int on tx ready */
+#define IER_ERLS 0x4 /* int on line status change */
+#define IER_EMSC 0x8 /* int on modem status change */
+
+/* interrupt identification register */
+#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+#define IIR_IMASK 0xf /* interrupt cause mask */
+#define IIR_NOPEND 0x1 /* nothing pending */
+#define IIR_RLS 0x6 /* receive line status */
+#define IIR_RXRDY 0x4 /* receive ready */
+#define IIR_RXTOUT 0xc /* receive timeout */
+#define IIR_TXRDY 0x2 /* transmit ready */
+#define IIR_MLSC 0x0 /* modem status */
+
+
+/* fifo control register */
+#define FIFO_ENABLE 0x01 /* enable fifo */
+#define FIFO_RCV_RST 0x02 /* reset receive fifo */
+#define FIFO_XMT_RST 0x04 /* reset transmit fifo */
+#define FIFO_DMA_MODE 0x08 /* enable dma mode */
+#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */
+#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */
+#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */
+#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */
+
+/* character format control register */
+#define CFCR_DLAB 0x80 /* divisor latch */
+#define CFCR_SBREAK 0x40 /* send break */
+#define CFCR_PZERO 0x30 /* zero parity */
+#define CFCR_PONE 0x20 /* one parity */
+#define CFCR_PEVEN 0x10 /* even parity */
+#define CFCR_PODD 0x00 /* odd parity */
+#define CFCR_PENAB 0x08 /* parity enable */
+#define CFCR_STOPB 0x04 /* 2 stop bits */
+#define CFCR_8BITS 0x03 /* 8 data bits */
+#define CFCR_7BITS 0x02 /* 7 data bits */
+#define CFCR_6BITS 0x01 /* 6 data bits */
+#define CFCR_5BITS 0x00 /* 5 data bits */
+
+/* modem control register */
+#define MCR_LOOPBACK 0x10 /* loopback */
+#define MCR_IENABLE 0x08 /* output 2 = int enable */
+#define MCR_DRS 0x04 /* output 1 = xxx */
+#define MCR_RTS 0x02 /* enable RTS */
+#define MCR_DTR 0x01 /* enable DTR */
+
+/* line status register */
+#define LSR_RCV_FIFO 0x80 /* error in receive fifo */
+#define LSR_TSRE 0x40 /* transmitter empty */
+#define LSR_TXRDY 0x20 /* transmitter ready */
+#define LSR_BI 0x10 /* break detected */
+#define LSR_FE 0x08 /* framing error */
+#define LSR_PE 0x04 /* parity error */
+#define LSR_OE 0x02 /* overrun error */
+#define LSR_RXRDY 0x01 /* receiver ready */
+#define LSR_RCV_MASK 0x1f
+
+/* modem status register */
+#define MSR_DCD 0x80
+#define MSR_RI 0x40
+#define MSR_DSR 0x20
+#define MSR_CTS 0x10
+#define MSR_DDCD 0x08
+#define MSR_TERI 0x04
+#define MSR_DDSR 0x02
+#define MSR_DCTS 0x01
+
+#include <sys/dos.h>
+#include <sys/go32.h>
+#include <sys/dpmi.h>
+
+/* DPMI Communication */
+static union REGS dpmi_regs;
+static struct SREGS dpmi_sregs;
+
+/* 16550 rx fifo trigger point */
+#define FIFO_TRIGGER FIFO_TRIGGER_4
+
+/* input buffer size */
+#define CBSIZE 4096
+
+/* return raw 18Hz clock count */
+extern long rawclock (void);
+
+#define RAWHZ 18
+
+#ifdef DOS_STATS
+#define CNT_RX 16
+#define CNT_TX 17
+#define CNT_STRAY 18
+#define CNT_ORUN 19
+#define NCNT 20
+
+static int intrcnt;
+static int cnts[NCNT];
+static char *cntnames[NCNT] = {
+ /* h/w interrupt counts. */
+ "mlsc", "nopend", "txrdy", "?3",
+ "rxrdy", "?5", "rls", "?7",
+ "?8", "?9", "?a", "?b",
+ "rxtout", "?d", "?e", "?f",
+ /* s/w counts. */
+ "rxcnt", "txcnt", "stray", "swoflo"
+};
+
+#define COUNT(x) cnts[x]++
+#else
+#define COUNT(x)
+#endif
+
+/* Main interrupt controller port addresses. */
+#define ICU_BASE 0x20
+#define ICU_OCW2 (ICU_BASE + 0)
+#define ICU_MASK (ICU_BASE + 1)
+
+/* Original interrupt controller mask register. */
+unsigned char icu_oldmask;
+
+/* Maximum of 8 interrupts (we don't handle the slave icu yet). */
+#define NINTR 8
+
+static struct intrupt
+{
+ char inuse;
+ struct dos_ttystate *port;
+ _go32_dpmi_seginfo old_rmhandler;
+ _go32_dpmi_seginfo old_pmhandler;
+ _go32_dpmi_seginfo new_rmhandler;
+ _go32_dpmi_seginfo new_pmhandler;
+ _go32_dpmi_registers regs;
+} intrupts[NINTR];
+
+
+static struct dos_ttystate
+{
+ int base;
+ int irq;
+ int refcnt;
+ struct intrupt *intrupt;
+ int fifo;
+ int baudrate;
+ unsigned char cbuf[CBSIZE];
+ unsigned int first;
+ unsigned int count;
+ int txbusy;
+ unsigned char old_mcr;
+ int ferr;
+ int perr;
+ int oflo;
+ int msr;
+} ports[4] = {
+ {COM1ADDR, 4},
+ {COM2ADDR, 3},
+ {COM3ADDR, 4},
+ {COM4ADDR, 3}
+};
+
+static int dos_open PARAMS ((serial_t scb, const char *name));
+static void dos_raw PARAMS ((serial_t scb));
+static int dos_readchar PARAMS ((serial_t scb, int timeout));
+static int dos_setbaudrate PARAMS ((serial_t scb, int rate));
+static int dos_write PARAMS ((serial_t scb, const char *str, int len));
+static void dos_close PARAMS ((serial_t scb));
+static serial_ttystate dos_get_tty_state PARAMS ((serial_t scb));
+static int dos_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static int dos_baudconv PARAMS ((int rate));
+
+#define inb(p,a) inportb((p)->base + (a))
+#define outb(p,a,v) outportb((p)->base + (a), (v))
+#define disable() asm volatile ("cli");
+#define enable() asm volatile ("sti");
+
+
+static int
+dos_getc (port)
+ volatile struct dos_ttystate *port;
+{
+ int c;
+
+ if (port->count == 0)
+ return -1;
+
+ c = port->cbuf[port->first];
+ disable ();
+ port->first = (port->first + 1) & (CBSIZE - 1);
+ port->count--;
+ enable ();
+ return c;
+}
+
+
+static int
+dos_putc (c, port)
+ int c;
+ struct dos_ttystate *port;
+{
+ if (port->count >= CBSIZE - 1)
+ return -1;
+ port->cbuf[(port->first + port->count) & (CBSIZE - 1)] = c;
+ port->count++;
+ return 0;
+}
+
+
+
+static void
+dos_comisr (irq)
+ int irq;
+{
+ struct dos_ttystate *port;
+ unsigned char iir, lsr, c;
+
+ disable (); /* Paranoia */
+ outportb (ICU_OCW2, 0x20); /* End-Of-Interrupt */
+#ifdef DOS_STATS
+ ++intrcnt;
+#endif
+
+ port = intrupts[irq].port;
+ if (!port)
+ {
+ COUNT (CNT_STRAY);
+ return; /* not open */
+ }
+
+ while (1)
+ {
+ iir = inb (port, com_iir) & IIR_IMASK;
+ switch (iir)
+ {
+
+ case IIR_RLS:
+ lsr = inb (port, com_lsr);
+ goto rx;
+
+ case IIR_RXTOUT:
+ case IIR_RXRDY:
+ lsr = 0;
+
+ rx:
+ do
+ {
+ c = inb (port, com_data);
+ if (lsr & (LSR_BI | LSR_FE | LSR_PE | LSR_OE))
+ {
+ if (lsr & (LSR_BI | LSR_FE))
+ port->ferr++;
+ else if (lsr & LSR_PE)
+ port->perr++;
+ if (lsr & LSR_OE)
+ port->oflo++;
+ }
+
+ if (dos_putc (c, port) < 0)
+ {
+ COUNT (CNT_ORUN);
+ }
+ else
+ {
+ COUNT (CNT_RX);
+ }
+ }
+ while ((lsr = inb (port, com_lsr)) & LSR_RXRDY);
+ break;
+
+ case IIR_MLSC:
+ /* could be used to flowcontrol Tx */
+ port->msr = inb (port, com_msr);
+ break;
+
+ case IIR_TXRDY:
+ port->txbusy = 0;
+ break;
+
+ case IIR_NOPEND:
+ /* no more pending interrupts, all done */
+ return;
+
+ default:
+ /* unexpected interrupt, ignore */
+ break;
+ }
+ COUNT (iir);
+ }
+}
+
+#ifdef __STDC__
+#define ISRNAME(x) dos_comisr##x
+#else
+#define ISRNAME(x) dos_comisr/**/x
+#endif
+#define ISR(x) static void ISRNAME(x)() {dos_comisr(x);}
+
+ISR(0) ISR(1) ISR(2) ISR(3)
+ISR(4) ISR(5) ISR(6) ISR(7)
+
+typedef void (*isr_t)();
+
+static isr_t isrs[NINTR] = {
+ ISRNAME(0), ISRNAME(1), ISRNAME(2), ISRNAME(3),
+ ISRNAME(4), ISRNAME(5), ISRNAME(6), ISRNAME(7)
+};
+
+
+
+static struct intrupt *
+dos_hookirq (irq)
+ unsigned int irq;
+{
+ struct intrupt *intr;
+ unsigned int vec;
+ isr_t isr;
+
+ if (irq >= NINTR)
+ return 0;
+
+ intr = &intrupts[irq];
+ if (intr->inuse)
+ return 0;
+
+ vec = 0x08 + irq;
+ isr = isrs[irq];
+
+ /* setup real mode handler */
+ _go32_dpmi_get_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
+
+ intr->new_rmhandler.pm_selector = _go32_my_cs();
+ intr->new_rmhandler.pm_offset = (u_long)isr;
+ if (_go32_dpmi_allocate_real_mode_callback_iret (&intr->new_rmhandler,
+ &intr->regs))
+ {
+ return 0;
+ }
+
+ if (_go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->new_rmhandler))
+ {
+ return 0;
+ }
+
+ /* setup protected mode handler */
+ _go32_dpmi_get_protected_mode_interrupt_vector(vec, &intr->old_pmhandler);
+
+ intr->new_pmhandler.pm_selector = _go32_my_cs();
+ intr->new_pmhandler.pm_offset = (u_long)isr;
+ _go32_dpmi_allocate_iret_wrapper (&intr->new_pmhandler);
+
+ if (_go32_dpmi_set_protected_mode_interrupt_vector(vec, &intr->new_pmhandler))
+ {
+ return 0;
+ }
+
+ /* setup interrupt controller mask */
+ disable ();
+ outportb (ICU_MASK, inportb (ICU_MASK) & ~(1 << irq));
+ enable ();
+
+ intr->inuse = 1;
+ return intr;
+}
+
+
+static void
+dos_unhookirq (intr)
+ struct intrupt *intr;
+{
+ unsigned int irq, vec;
+ unsigned char mask;
+
+ irq = intr - intrupts;
+ vec = 0x08 + irq;
+
+ /* restore old interrupt mask bit */
+ mask = 1 << irq;
+ disable ();
+ outportb (ICU_MASK, inportb (ICU_MASK) | (mask & icu_oldmask));
+ enable ();
+
+ /* remove real mode handler */
+ _go32_dpmi_set_real_mode_interrupt_vector (vec, &intr->old_rmhandler);
+ _go32_dpmi_free_real_mode_callback (&intr->new_rmhandler);
+
+ /* remove protected mode handler */
+ _go32_dpmi_set_protected_mode_interrupt_vector (vec, &intr->old_pmhandler);
+ _go32_dpmi_free_iret_wrapper (&intr->new_pmhandler);
+ intr->inuse = 0;
+}
+
+
+
+static int
+dos_open (scb, name)
+ serial_t scb;
+ const char *name;
+{
+ struct dos_ttystate *port;
+ int fd, i;
+
+ if (strncasecmp (name, "/dev/", 5) == 0)
+ name += 5;
+ else if (strncasecmp (name, "\\dev\\", 5) == 0)
+ name += 5;
+
+ if (strlen (name) != 4 || strncasecmp (name, "com", 3) != 0)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (name[3] < '1' || name[3] > '4')
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ fd = name[3] - '1';
+ port = &ports[fd];
+ if (port->refcnt++ > 0)
+ {
+ /* Device already opened another user. Just point at it. */
+ scb->fd = fd;
+ return 0;
+ }
+
+ /* force access to ID reg */
+ outb(port, com_cfcr, 0);
+ outb(port, com_iir, 0);
+ for (i = 0; i < 17; i++) {
+ if ((inb(port, com_iir) & 0x38) == 0)
+ goto ok;
+ (void) inb(port, com_data); /* clear recv */
+ }
+ errno = ENODEV;
+ return -1;
+
+ok:
+ /* disable all interrupts in chip */
+ outb(port, com_ier, 0);
+
+ /* tentatively enable 16550 fifo, and see if it responds */
+ outb(port, com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER);
+ sleep(1);
+ port->fifo = ((inb(port, com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK);
+
+ /* clear pending status reports. */
+ (void) inb(port, com_lsr);
+ (void) inb(port, com_msr);
+
+ /* enable external interrupt gate (to avoid floating IRQ) */
+ outb(port, com_mcr, MCR_IENABLE);
+
+ /* hook up interrupt handler and initialise icu */
+ port->intrupt = dos_hookirq (port->irq);
+ if (!port->intrupt)
+ {
+ outb(port, com_mcr, 0);
+ outb(port, com_fifo, 0);
+ errno = ENODEV;
+ return -1;
+ }
+
+ disable ();
+
+ /* record port */
+ port->intrupt->port = port;
+ scb->fd = fd;
+
+ /* clear rx buffer, tx busy flag and overflow count */
+ port->first = port->count = 0;
+ port->txbusy = 0;
+ port->oflo = 0;
+
+ /* set default baud rate and mode: 9600,8,n,1 */
+ i = dos_baudconv (port->baudrate = 9600);
+ outb(port, com_cfcr, CFCR_DLAB);
+ outb(port, com_dlbl, i & 0xff);
+ outb(port, com_dlbh, i >> 8);
+ outb(port, com_cfcr, CFCR_8BITS);
+
+ /* enable all interrupts */
+ outb(port, com_ier, IER_ETXRDY | IER_ERXRDY | IER_ERLS | IER_EMSC);
+
+ /* enable DTR & RTS */
+ outb(port, com_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
+
+ enable ();
+
+ return 0;
+}
+
+
+static void
+dos_close (scb)
+ serial_t scb;
+{
+ struct dos_ttystate *port;
+ struct intrupt *intrupt;
+
+ if (!scb)
+ return;
+
+ port = &ports[scb->fd];
+
+ if (port->refcnt-- > 1)
+ return;
+
+ if (!(intrupt = port->intrupt))
+ return;
+
+ /* disable interrupts, fifo, flow control */
+ disable ();
+ port->intrupt = 0;
+ intrupt->port = 0;
+ outb(port, com_fifo, 0);
+ outb(port, com_ier, 0);
+ enable ();
+
+ /* unhook handler, and disable interrupt gate */
+ dos_unhookirq (intrupt);
+ outb(port, com_mcr, 0);
+
+ /* Check for overflow errors */
+ if (port->oflo)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Serial input overruns occurred.\n");
+ fprintf_unfiltered (gdb_stderr, "This system %s handle %d baud.\n",
+ port->fifo ? "cannot" : "needs a 16550 to",
+ port->baudrate);
+ }
+}
+
+
+
+static int
+dos_noop (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+dos_raw (scb)
+ serial_t scb;
+{
+ /* Always in raw mode */
+}
+
+static int
+dos_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ long then;
+ int c;
+
+ then = rawclock() + (timeout * RAWHZ);
+ while ((c = dos_getc (port)) < 0)
+ {
+ if (timeout >= 0 && (rawclock () - then) >= 0)
+ return SERIAL_TIMEOUT;
+ notice_quit ();
+ }
+
+ return c;
+}
+
+
+static serial_ttystate
+dos_get_tty_state (scb)
+ serial_t scb;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ struct dos_ttystate *state;
+
+ state = (struct dos_ttystate *) xmalloc (sizeof *state);
+ *state = *port;
+ return (serial_ttystate) state;
+}
+
+static int
+dos_set_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct dos_ttystate *state;
+
+ state = (struct dos_ttystate *) ttystate;
+ dos_setbaudrate (scb, state->baudrate);
+ return 0;
+}
+
+static int
+dos_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ struct dos_ttystate *state;
+
+ state = (struct dos_ttystate *) new_ttystate;
+ dos_setbaudrate (scb, state->baudrate);
+ return 0;
+}
+
+static int
+dos_flush_input (scb)
+ serial_t scb;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ disable();
+ port->first = port->count = 0;
+ if (port->fifo)
+ outb(port, com_fifo, FIFO_ENABLE|FIFO_RCV_RST|FIFO_TRIGGER);
+ enable();
+}
+
+static void
+dos_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print */
+ return;
+}
+
+static int
+dos_baudconv (rate)
+ int rate;
+{
+ long x, err;
+
+ if (rate <= 0)
+ return -1;
+
+#define divrnd(n, q) (((n) * 2 / (q) + 1) / 2) /* divide and round off */
+ x = divrnd(COMTICK, rate);
+ if (x <= 0)
+ return -1;
+
+ err = divrnd(1000 * COMTICK, x * rate) - 1000;
+ if (err < 0)
+ err = -err;
+ if (err > SPEED_TOLERANCE)
+ return -1;
+#undef divrnd
+ return x;
+}
+
+
+static int
+dos_setbaudrate (scb, rate)
+ serial_t scb;
+ int rate;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+
+ if (port->baudrate != rate)
+ {
+ int x;
+ unsigned char cfcr;
+
+ x = dos_baudconv (rate);
+ if (x <= 0)
+ {
+ fprintf_unfiltered (gdb_stderr, "%d: impossible baudrate\n", rate);
+ errno = EINVAL;
+ return -1;
+ }
+
+ disable ();
+ cfcr = inb (port, com_cfcr);
+
+ outb(port, com_cfcr, CFCR_DLAB);
+ outb(port, com_dlbl, x & 0xff);
+ outb(port, com_dlbh, x >> 8);
+ outb(port, com_cfcr, cfcr);
+ port->baudrate = rate;
+ enable ();
+ }
+
+ return 0;
+}
+
+static int
+dos_setstopbits (scb, num)
+ serial_t scb;
+ int num;
+{
+ struct dos_ttystate *port = &ports[scb->fd];
+ unsigned char cfcr;
+
+ disable ();
+ cfcr = inb (port, com_cfcr);
+
+ switch (num)
+ {
+ case SERIAL_1_STOPBITS:
+ outb (port, com_cfcr, cfcr & ~CFCR_STOPB);
+ break;
+ case SERIAL_1_AND_A_HALF_STOPBITS:
+ case SERIAL_2_STOPBITS:
+ outb (port, com_cfcr, cfcr | CFCR_STOPB);
+ break;
+ default:
+ enable ();
+ return 1;
+ }
+ enable ();
+
+ return 0;
+}
+
+static int
+dos_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ volatile struct dos_ttystate *port = &ports[scb->fd];
+ int fifosize = port->fifo ? 16 : 1;
+ long then;
+ int cnt;
+
+ while (len > 0)
+ {
+ /* send the data, fifosize bytes at a time */
+ cnt = fifosize > len ? len : fifosize;
+ port->txbusy = 1;
+ outportsb (port->base + com_data, str, cnt);
+ str += cnt;
+ len -= cnt;
+#ifdef DOS_STATS
+ cnts[CNT_TX] += cnt;
+#endif
+ /* wait for transmission to complete (max 1 sec) */
+ then = rawclock() + RAWHZ;
+ while (port->txbusy)
+ {
+ if ((rawclock () - then) >= 0)
+ {
+ errno = EIO;
+ return SERIAL_ERROR;
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int
+dos_sendbreak (scb)
+ serial_t scb;
+{
+ volatile struct dos_ttystate *port = &ports[scb->fd];
+ unsigned char cfcr;
+ long then;
+
+ cfcr = inb(port, com_cfcr);
+ outb(port, com_cfcr, cfcr | CFCR_SBREAK);
+
+ /* 0.25 sec delay */
+ then = rawclock () + RAWHZ / 4;
+ while ((rawclock () - then) < 0)
+ continue;
+
+ outb(port, com_cfcr, cfcr);
+ return 0;
+}
+
+
+static struct serial_ops dos_ops =
+{
+ "hardwire",
+ 0,
+ dos_open,
+ dos_close,
+ dos_readchar,
+ dos_write,
+ dos_noop, /* flush output */
+ dos_flush_input,
+ dos_sendbreak,
+ dos_raw,
+ dos_get_tty_state,
+ dos_set_tty_state,
+ dos_print_tty_state,
+ dos_noflush_set_tty_state,
+ dos_setbaudrate,
+ dos_setstopbits,
+};
+
+
+static void
+dos_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct dos_ttystate *port;
+ int i;
+
+ for (port = ports; port < &ports[4]; port++)
+ {
+ if (port->baudrate == 0)
+ continue;
+ printf_filtered ("Port:\tCOM%d (%sactive)\n", port - ports + 1,
+ port->intrupt ? "" : "not ");
+ printf_filtered ("Addr:\t0x%03x (irq %d)\n", port->base, port->irq);
+ printf_filtered ("16550:\t%s\n", port->fifo ? "yes" : "no");
+ printf_filtered ("Speed:\t%d baud\n", port->baudrate);
+ printf_filtered ("Errs:\tframing %d parity %d overflow %d\n\n",
+ port->ferr, port->perr, port->oflo);
+ }
+
+#ifdef DOS_STATS
+ printf_filtered ("\nTotal interrupts: %d\n", intrcnt);
+ for (i = 0; i < NCNT; i++)
+ if (cnts[i])
+ printf_filtered ("%s:\t%d\n", cntnames[i], cnts[i]);
+#endif
+}
+
+
+void
+_initialize_ser_dos ()
+{
+ struct cmd_list_element *c;
+
+ serial_add_interface (&dos_ops);
+
+ /* Save original interrupt mask register. */
+ icu_oldmask = inportb (ICU_MASK);
+
+ /* Mark fixed motherboard irqs as inuse. */
+ intrupts[0].inuse = /* timer tick */
+ intrupts[1].inuse = /* keyboard */
+ intrupts[2].inuse = 1; /* slave icu */
+
+ add_show_from_set (
+ add_set_cmd ("com1base", class_obscure, var_zinteger,
+ (char *) &ports[0].base,
+ "Set COM1 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com1irq", class_obscure, var_zinteger,
+ (char *) &ports[0].irq,
+ "Set COM1 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com2base", class_obscure, var_zinteger,
+ (char *) &ports[1].base,
+ "Set COM2 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com2irq", class_obscure, var_zinteger,
+ (char *) &ports[1].irq,
+ "Set COM2 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com3base", class_obscure, var_zinteger,
+ (char *) &ports[2].base,
+ "Set COM3 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com3irq", class_obscure, var_zinteger,
+ (char *) &ports[2].irq,
+ "Set COM3 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com4base", class_obscure, var_zinteger,
+ (char *) &ports[3].base,
+ "Set COM4 base i/o port address.",
+ &setlist),
+ &showlist);
+
+ add_show_from_set (
+ add_set_cmd ("com4irq", class_obscure, var_zinteger,
+ (char *) &ports[3].irq,
+ "Set COM4 interrupt request.",
+ &setlist),
+ &showlist);
+
+ add_info ("serial", dos_info,
+ "Print DOS serial port status.");
+}
diff --git a/contrib/gdb/gdb/ser-mac.c b/contrib/gdb/gdb/ser-mac.c
new file mode 100644
index 0000000..e27a9dd0
--- /dev/null
+++ b/contrib/gdb/gdb/ser-mac.c
@@ -0,0 +1,361 @@
+/* Remote serial interface for local (hardwired) serial ports for Macintosh.
+ Copyright 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by Stan Shebs.
+
+ This file is part of GDB.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+
+#include <Types.h>
+#include <Devices.h>
+/* This is the regular Mac Serial.h, but copied to a different name
+ so as not to get confused with the GDB serial.h above. */
+#include "MacSerial.h"
+
+/* This is unused for now. We just return a placeholder. */
+
+struct mac_ttystate
+ {
+ int bogus;
+ };
+
+static int mac_open PARAMS ((serial_t scb, const char *name));
+static void mac_raw PARAMS ((serial_t scb));
+static int mac_readchar PARAMS ((serial_t scb, int timeout));
+static int mac_setbaudrate PARAMS ((serial_t scb, int rate));
+static int mac_write PARAMS ((serial_t scb, const char *str, int len));
+static void mac_close PARAMS ((serial_t scb));
+static serial_ttystate mac_get_tty_state PARAMS ((serial_t scb));
+static int mac_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+static char *aptr PARAMS ((short p));
+
+short input_refnum;
+short output_refnum;
+
+char *mac_input_buffer;
+char *mac_output_buffer;
+
+static int
+mac_open (scb, name)
+ serial_t scb;
+ const char *name;
+{
+ OSErr err;
+
+ /* Alloc buffer space first - that way any allocation failures are
+ intercepted before the serial driver gets involved. */
+ if (mac_input_buffer == NULL)
+ mac_input_buffer = (char *) xmalloc (4096);
+ /* Match on a name and open a port. */
+ if (strcmp (name, "modem") == 0)
+ {
+ err = OpenDriver ("\p.AIn", &input_refnum);
+ if (err != 0)
+ {
+ return (-1);
+ }
+ err = OpenDriver ("\p.AOut", &output_refnum);
+ if (err != 0)
+ {
+ CloseDriver (input_refnum);
+ return (-1);
+ }
+ }
+ else if (strcmp (name, "printer") == 0)
+ {
+ err = OpenDriver ("\p.BIn", &input_refnum);
+ if (err != 0)
+ {
+ return (-1);
+ }
+ err = OpenDriver ("\p.BOut", &output_refnum);
+ if (err != 0)
+ {
+ CloseDriver (input_refnum);
+ return (-1);
+ }
+ /* fake */
+ scb->fd = 1;
+ return 0;
+ }
+ else
+ {
+ error ("You must specify a valid serial port name; your choices are `modem' or `printer'.");
+ errno = ENOENT;
+ return (-1);
+ }
+ /* We got something open. */
+ if (1 /* using custom buffer */)
+ SerSetBuf (input_refnum, mac_input_buffer, 4096);
+ /* Set to a GDB-preferred state. */
+ SerReset (input_refnum, stop10|noParity|data8|baud9600);
+ SerReset (output_refnum, stop10|noParity|data8|baud9600);
+ {
+ CntrlParam cb;
+ struct SerShk *handshake;
+
+ cb.ioCRefNum = output_refnum;
+ cb.csCode = 14;
+ handshake = (struct SerShk *) &cb.csParam[0];
+ handshake->fXOn = 0;
+ handshake->fCTS = 0;
+ handshake->xOn = 0;
+ handshake->xOff = 0;
+ handshake->errs = 0;
+ handshake->evts = 0;
+ handshake->fInX = 0;
+ handshake->fDTR = 0;
+ err = PBControl ((ParmBlkPtr) &cb, 0);
+ if (err < 0)
+ return (-1);
+ }
+ /* fake */
+ scb->fd = 1;
+ return 0;
+}
+
+static int
+mac_noop (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+mac_raw (scb)
+ serial_t scb;
+{
+ /* Always effectively in raw mode. */
+}
+
+/* Read a character with user-specified timeout. TIMEOUT is number of seconds
+ to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
+ char if successful. Returns -2 if timeout expired, EOF if line dropped
+ dead, or -3 for any other error (see errno in that case). */
+
+static int
+mac_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int status, n;
+ /* time_t */ unsigned long start_time, now;
+ OSErr err;
+ CntrlParam cb;
+ IOParam pb;
+
+ if (scb->bufcnt-- > 0)
+ return *scb->bufp++;
+
+ time (&start_time);
+
+ while (1)
+ {
+ cb.ioCRefNum = input_refnum;
+ cb.csCode = 2;
+ err = PBStatus ((ParmBlkPtr) &cb, 0);
+ if (err < 0)
+ return SERIAL_ERROR;
+ n = *((long *) &cb.csParam[0]);
+ if (n > 0)
+ {
+ pb.ioRefNum = input_refnum;
+ pb.ioBuffer = (Ptr) (scb->buf);
+ pb.ioReqCount = (n > 64 ? 64 : n);
+ err = PBRead ((ParmBlkPtr) &pb, 0);
+ if (err < 0)
+ return SERIAL_ERROR;
+ scb->bufcnt = pb.ioReqCount;
+ scb->bufcnt--;
+ scb->bufp = scb->buf;
+ return *scb->bufp++;
+ }
+ else if (timeout == 0)
+ return SERIAL_TIMEOUT;
+ else if (timeout == -1)
+ ;
+ else
+ {
+ time (&now);
+ if (now > start_time + timeout)
+ return SERIAL_TIMEOUT;
+ }
+ PROGRESS (1);
+ }
+}
+
+/* mac_{get set}_tty_state() are both dummys to fill out the function
+ vector. Someday, they may do something real... */
+
+static serial_ttystate
+mac_get_tty_state (scb)
+ serial_t scb;
+{
+ struct mac_ttystate *state;
+
+ state = (struct mac_ttystate *) xmalloc (sizeof *state);
+
+ return (serial_ttystate) state;
+}
+
+static int
+mac_set_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ return 0;
+}
+
+static int
+mac_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ return 0;
+}
+
+static void
+mac_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print. */
+ return;
+}
+
+/* If there is a tricky formula to relate real baud rates
+ to what the serial driver wants, we should use it. Until
+ we get one, this table will have to do. */
+
+static struct {
+ int real_rate;
+ int bits;
+} mac_baud_rate_table[] = {
+ { 57600, baud57600 },
+ { 38400, 1 },
+ { 19200, baud19200 },
+ { 9600, baud9600 },
+ { 7200, baud7200 },
+ { 4800, baud4800 },
+ { 3600, baud3600 },
+ { 2400, baud2400 },
+ { 1800, baud1800 },
+ { 1200, baud1200 },
+ { 600, baud600 },
+ { 300, baud300 },
+ { 0, 0 }
+};
+
+static int
+mac_set_baud_rate (scb, rate)
+ serial_t scb;
+ int rate;
+{
+ int i, bits;
+
+ for (i = 0; mac_baud_rate_table[i].real_rate != 0; ++i)
+ {
+ if (mac_baud_rate_table[i].real_rate == rate)
+ {
+ bits = mac_baud_rate_table[i].bits;
+ break;
+ }
+ }
+ SerReset (input_refnum, stop10|noParity|data8|bits);
+ SerReset (output_refnum, stop10|noParity|data8|bits);
+}
+
+static int
+mac_set_stop_bits (scb, num)
+ serial_t scb;
+ int num;
+{
+ return 0;
+}
+
+int first_mac_write = 0;
+
+static int
+mac_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ OSErr err;
+ IOParam pb;
+
+ if (first_mac_write++ < 4)
+ {
+ sleep (1);
+ }
+ pb.ioRefNum = output_refnum;
+ pb.ioBuffer = (Ptr) str;
+ pb.ioReqCount = len;
+ err = PBWrite ((ParmBlkPtr) &pb, 0);
+ if (err < 0)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+static void
+mac_close (serial_t scb)
+{
+ if (input_refnum)
+ {
+ if (1 /* custom buffer */)
+ SerSetBuf (input_refnum, mac_input_buffer, 0);
+ CloseDriver (input_refnum);
+ input_refnum = 0;
+ }
+ if (output_refnum)
+ {
+ if (0 /* custom buffer */)
+ SetSetBuf (input_refnum, mac_output_buffer, 0);
+ CloseDriver (output_refnum);
+ output_refnum = 0;
+ }
+}
+
+static struct serial_ops mac_ops =
+{
+ "hardwire",
+ 0,
+ mac_open,
+ mac_close,
+ mac_readchar,
+ mac_write,
+ mac_noop, /* flush output */
+ mac_noop, /* flush input */
+ mac_noop, /* send break -- currently only for nindy */
+ mac_raw,
+ mac_get_tty_state,
+ mac_set_tty_state,
+ mac_print_tty_state,
+ mac_noflush_set_tty_state,
+ mac_set_baud_rate,
+ mac_set_stop_bits,
+};
+
+void
+_initialize_ser_mac ()
+{
+ serial_add_interface (&mac_ops);
+}
diff --git a/contrib/gdb/gdb/ser-tcp.c b/contrib/gdb/gdb/ser-tcp.c
new file mode 100644
index 0000000..388293f
--- /dev/null
+++ b/contrib/gdb/gdb/ser-tcp.c
@@ -0,0 +1,343 @@
+/* Serial interface for raw TCP connections on Un*x like systems
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include "signals.h"
+#include "gdb_string.h"
+
+struct tcp_ttystate
+{
+ int bogus;
+};
+
+static int tcp_open PARAMS ((serial_t scb, const char *name));
+static void tcp_raw PARAMS ((serial_t scb));
+static int wait_for PARAMS ((serial_t scb, int timeout));
+static int tcp_readchar PARAMS ((serial_t scb, int timeout));
+static int tcp_setbaudrate PARAMS ((serial_t scb, int rate));
+static int tcp_setstopbits PARAMS ((serial_t scb, int num));
+static int tcp_write PARAMS ((serial_t scb, const char *str, int len));
+/* FIXME: static void tcp_restore PARAMS ((serial_t scb)); */
+static void tcp_close PARAMS ((serial_t scb));
+static serial_ttystate tcp_get_tty_state PARAMS ((serial_t scb));
+static int tcp_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+
+/* Open up a raw tcp socket */
+
+static int
+tcp_open(scb, name)
+ serial_t scb;
+ const char *name;
+{
+ char *port_str;
+ int port;
+ struct hostent *hostent;
+ struct sockaddr_in sockaddr;
+ int tmp;
+ char hostname[100];
+ struct protoent *protoent;
+ int i;
+
+ port_str = strchr (name, ':');
+
+ if (!port_str)
+ error ("tcp_open: No colon in host name!"); /* Shouldn't ever happen */
+
+ tmp = min (port_str - name, (int) sizeof hostname - 1);
+ strncpy (hostname, name, tmp); /* Don't want colon */
+ hostname[tmp] = '\000'; /* Tie off host name */
+ port = atoi (port_str + 1);
+
+ hostent = gethostbyname (hostname);
+
+ if (!hostent)
+ {
+ fprintf_unfiltered (gdb_stderr, "%s: unknown host\n", hostname);
+ errno = ENOENT;
+ return -1;
+ }
+
+ for (i = 1; i <= 15; i++)
+ {
+ scb->fd = socket (PF_INET, SOCK_STREAM, 0);
+ if (scb->fd < 0)
+ return -1;
+
+ /* Allow rapid reuse of this port. */
+ tmp = 1;
+ setsockopt (scb->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&tmp, sizeof(tmp));
+
+ /* Enable TCP keep alive process. */
+ tmp = 1;
+ setsockopt (scb->fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&tmp, sizeof(tmp));
+
+ sockaddr.sin_family = PF_INET;
+ sockaddr.sin_port = htons(port);
+ memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
+ sizeof (struct in_addr));
+
+ if (!connect (scb->fd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)))
+ break;
+
+ close (scb->fd);
+ scb->fd = -1;
+
+/* We retry for ECONNREFUSED because that is often a temporary condition, which
+ happens when the server is being restarted. */
+
+ if (errno != ECONNREFUSED)
+ return -1;
+
+ sleep (1);
+ }
+
+ protoent = getprotobyname ("tcp");
+ if (!protoent)
+ return -1;
+
+ tmp = 1;
+ if (setsockopt (scb->fd, protoent->p_proto, TCP_NODELAY,
+ (char *)&tmp, sizeof(tmp)))
+ return -1;
+
+ signal(SIGPIPE, SIG_IGN); /* If we don't do this, then GDB simply exits
+ when the remote side dies. */
+
+ return 0;
+}
+
+static serial_ttystate
+tcp_get_tty_state(scb)
+ serial_t scb;
+{
+ struct tcp_ttystate *state;
+
+ state = (struct tcp_ttystate *)xmalloc(sizeof *state);
+
+ return (serial_ttystate)state;
+}
+
+static int
+tcp_set_tty_state(scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct tcp_ttystate *state;
+
+ state = (struct tcp_ttystate *)ttystate;
+
+ return 0;
+}
+
+static int
+tcp_return_0 (scb)
+ serial_t scb;
+{
+ return 0;
+}
+
+static void
+tcp_raw(scb)
+ serial_t scb;
+{
+ return; /* Always in raw mode */
+}
+
+/* Wait for input on scb, with timeout seconds. Returns 0 on success,
+ otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
+
+ For termio{s}, we actually just setup VTIME if necessary, and let the
+ timeout occur in the read() in tcp_read().
+ */
+
+static int
+wait_for(scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int numfds;
+ struct timeval tv;
+ fd_set readfds, exceptfds;
+
+ FD_ZERO (&readfds);
+ FD_ZERO (&exceptfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_SET(scb->fd, &readfds);
+ FD_SET(scb->fd, &exceptfds);
+
+ while (1)
+ {
+ if (timeout >= 0)
+ numfds = select(scb->fd+1, &readfds, 0, &exceptfds, &tv);
+ else
+ numfds = select(scb->fd+1, &readfds, 0, &exceptfds, 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;
+ }
+}
+
+/* Read a character with user-specified timeout. TIMEOUT is number of seconds
+ to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
+ char if successful. Returns -2 if timeout expired, EOF if line dropped
+ dead, or -3 for any other error (see errno in that case). */
+
+static int
+tcp_readchar(scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int status;
+
+ if (scb->bufcnt-- > 0)
+ return *scb->bufp++;
+
+ status = wait_for(scb, timeout);
+
+ if (status < 0)
+ return status;
+
+ while (1)
+ {
+ scb->bufcnt = read(scb->fd, scb->buf, BUFSIZ);
+ if (scb->bufcnt != -1 || errno != EINTR)
+ break;
+ }
+
+ 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 */
+
+ scb->bufcnt--;
+ scb->bufp = scb->buf;
+ return *scb->bufp++;
+}
+
+static int
+tcp_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ return 0;
+}
+
+static void
+tcp_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ /* Nothing to print. */
+ return;
+}
+
+static int
+tcp_setbaudrate(scb, rate)
+ serial_t scb;
+ int rate;
+{
+ return 0; /* Never fails! */
+}
+
+static int
+tcp_setstopbits(scb, num)
+ serial_t scb;
+ int num;
+{
+ return 0; /* Never fails! */
+}
+
+static int
+tcp_write(scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ int cc;
+
+ while (len > 0)
+ {
+ cc = write(scb->fd, str, len);
+
+ if (cc < 0)
+ return 1;
+ len -= cc;
+ str += cc;
+ }
+ return 0;
+}
+
+static void
+tcp_close(scb)
+ serial_t scb;
+{
+ if (scb->fd < 0)
+ return;
+
+ close(scb->fd);
+ scb->fd = -1;
+}
+
+static struct serial_ops tcp_ops =
+{
+ "tcp",
+ 0,
+ tcp_open,
+ tcp_close,
+ tcp_readchar,
+ tcp_write,
+ tcp_return_0, /* flush output */
+ tcp_return_0, /* flush input */
+ tcp_return_0, /* send break */
+ tcp_raw,
+ tcp_get_tty_state,
+ tcp_set_tty_state,
+ tcp_print_tty_state,
+ tcp_noflush_set_tty_state,
+ tcp_setbaudrate,
+ tcp_setstopbits,
+};
+
+void
+_initialize_ser_tcp ()
+{
+ serial_add_interface (&tcp_ops);
+}
diff --git a/contrib/gdb/gdb/ser-unix.c b/contrib/gdb/gdb/ser-unix.c
new file mode 100644
index 0000000..a4a00e5
--- /dev/null
+++ b/contrib/gdb/gdb/ser-unix.c
@@ -0,0 +1,730 @@
+/* Serial interface for local (hardwired) serial ports on Un*x like systems
+ Copyright 1992, 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include <fcntl.h>
+#include <sys/types.h>
+#include "terminal.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_TERMIOS
+
+struct hardwire_ttystate
+{
+ struct termios termios;
+};
+#endif /* termios */
+
+#ifdef HAVE_TERMIO
+
+/* It is believed that all systems which have added job control to SVR3
+ (e.g. sco) have also added termios. Even if not, trying to figure out
+ all the variations (TIOCGPGRP vs. TCGETPGRP, etc.) would be pretty
+ bewildering. So we don't attempt it. */
+
+struct hardwire_ttystate
+{
+ struct termio termio;
+};
+#endif /* termio */
+
+#ifdef HAVE_SGTTY
+/* Needed for the code which uses select(). We would include <sys/select.h>
+ too if it existed on all systems. */
+#include <sys/time.h>
+
+struct hardwire_ttystate
+{
+ struct sgttyb sgttyb;
+ struct tchars tc;
+ struct ltchars ltc;
+ /* Line discipline flags. */
+ int lmode;
+};
+#endif /* sgtty */
+
+static int hardwire_open PARAMS ((serial_t scb, const char *name));
+static void hardwire_raw PARAMS ((serial_t scb));
+static int wait_for PARAMS ((serial_t scb, int timeout));
+static int hardwire_readchar PARAMS ((serial_t scb, int timeout));
+static int rate_to_code PARAMS ((int rate));
+static int hardwire_setbaudrate PARAMS ((serial_t scb, int rate));
+static int hardwire_write PARAMS ((serial_t scb, const char *str, int len));
+/* FIXME: static void hardwire_restore PARAMS ((serial_t scb)); */
+static void hardwire_close PARAMS ((serial_t scb));
+static int get_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
+static int set_tty_state PARAMS ((serial_t scb, struct hardwire_ttystate *state));
+static serial_ttystate hardwire_get_tty_state PARAMS ((serial_t scb));
+static int hardwire_set_tty_state PARAMS ((serial_t scb, serial_ttystate state));
+
+/* Open up a real live device for serial I/O */
+
+static int
+hardwire_open(scb, name)
+ serial_t scb;
+ const char *name;
+{
+ scb->fd = open (name, O_RDWR);
+ if (scb->fd < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+get_tty_state(scb, state)
+ serial_t scb;
+ struct hardwire_ttystate *state;
+{
+#ifdef HAVE_TERMIOS
+ extern int errno;
+
+ if (tcgetattr(scb->fd, &state->termios) < 0)
+ return -1;
+
+ return 0;
+#endif
+
+#ifdef HAVE_TERMIO
+ if (ioctl (scb->fd, TCGETA, &state->termio) < 0)
+ return -1;
+ return 0;
+#endif
+
+#ifdef HAVE_SGTTY
+ if (ioctl (scb->fd, TIOCGETP, &state->sgttyb) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCGETC, &state->tc) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCGLTC, &state->ltc) < 0)
+ return -1;
+ if (ioctl (scb->fd, TIOCLGET, &state->lmode) < 0)
+ return -1;
+
+ return 0;
+#endif
+}
+
+static int
+set_tty_state(scb, state)
+ serial_t scb;
+ struct hardwire_ttystate *state;
+{
+#ifdef HAVE_TERMIOS
+ if (tcsetattr(scb->fd, TCSANOW, &state->termios) < 0)
+ return -1;
+
+ return 0;
+#endif
+
+#ifdef HAVE_TERMIO
+ if (ioctl (scb->fd, TCSETA, &state->termio) < 0)
+ return -1;
+ return 0;
+#endif
+
+#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
+}
+
+static serial_ttystate
+hardwire_get_tty_state(scb)
+ serial_t scb;
+{
+ struct hardwire_ttystate *state;
+
+ state = (struct hardwire_ttystate *)xmalloc(sizeof *state);
+
+ if (get_tty_state(scb, state))
+ return NULL;
+
+ return (serial_ttystate)state;
+}
+
+static int
+hardwire_set_tty_state(scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct hardwire_ttystate *state;
+
+ state = (struct hardwire_ttystate *)ttystate;
+
+ return set_tty_state(scb, state);
+}
+
+static int
+hardwire_noflush_set_tty_state (scb, new_ttystate, old_ttystate)
+ serial_t scb;
+ serial_ttystate new_ttystate;
+ serial_ttystate old_ttystate;
+{
+ struct hardwire_ttystate new_state;
+#ifdef HAVE_SGTTY
+ struct hardwire_ttystate *state = (struct hardwire_ttystate *) old_ttystate;
+#endif
+
+ new_state = *(struct hardwire_ttystate *)new_ttystate;
+
+ /* 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)
+ new_state.sgttyb.sg_flags |= RAW;
+ else
+ new_state.sgttyb.sg_flags &= ~RAW;
+
+ /* I'm not sure whether this is necessary; the manpage just mentions
+ RAW not CBREAK. */
+ if (state->sgttyb.sg_flags & CBREAK)
+ new_state.sgttyb.sg_flags |= CBREAK;
+ else
+ new_state.sgttyb.sg_flags &= ~CBREAK;
+#endif
+
+ return set_tty_state (scb, &new_state);
+}
+
+static void
+hardwire_print_tty_state (scb, ttystate)
+ serial_t scb;
+ serial_ttystate ttystate;
+{
+ struct hardwire_ttystate *state = (struct hardwire_ttystate *) ttystate;
+ int i;
+
+#ifdef HAVE_TERMIOS
+ printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ state->termios.c_iflag, state->termios.c_oflag);
+ printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x\n",
+ state->termios.c_cflag, state->termios.c_lflag);
+#if 0
+ /* This not in POSIX, and is not really documented by those systems
+ which have it (at least not Sun). */
+ printf_filtered ("c_line = 0x%x.\n", state->termios.c_line);
+#endif
+ printf_filtered ("c_cc: ");
+ for (i = 0; i < NCCS; i += 1)
+ printf_filtered ("0x%x ", state->termios.c_cc[i]);
+ printf_filtered ("\n");
+#endif
+
+#ifdef HAVE_TERMIO
+ printf_filtered ("c_iflag = 0x%x, c_oflag = 0x%x,\n",
+ state->termio.c_iflag, state->termio.c_oflag);
+ printf_filtered ("c_cflag = 0x%x, c_lflag = 0x%x, c_line = 0x%x.\n",
+ state->termio.c_cflag, state->termio.c_lflag,
+ state->termio.c_line);
+ printf_filtered ("c_cc: ");
+ for (i = 0; i < NCC; i += 1)
+ printf_filtered ("0x%x ", state->termio.c_cc[i]);
+ printf_filtered ("\n");
+#endif
+
+#ifdef HAVE_SGTTY
+ printf_filtered ("sgttyb.sg_flags = 0x%x.\n", state->sgttyb.sg_flags);
+
+ printf_filtered ("tchars: ");
+ for (i = 0; i < (int)sizeof (struct tchars); i++)
+ printf_filtered ("0x%x ", ((unsigned char *)&state->tc)[i]);
+ printf_filtered ("\n");
+
+ printf_filtered ("ltchars: ");
+ for (i = 0; i < (int)sizeof (struct ltchars); i++)
+ printf_filtered ("0x%x ", ((unsigned char *)&state->ltc)[i]);
+ printf_filtered ("\n");
+
+ printf_filtered ("lmode: 0x%x\n", state->lmode);
+#endif
+}
+
+static int
+hardwire_flush_output (scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ return tcflush (scb->fd, TCOFLUSH);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCFLSH, 1);
+#endif
+
+#ifdef HAVE_SGTTY
+ /* This flushes both input and output, but we can't do better. */
+ return ioctl (scb->fd, TIOCFLUSH, 0);
+#endif
+}
+
+static int
+hardwire_flush_input (scb)
+ serial_t scb;
+{
+ scb->bufcnt = 0;
+ scb->bufp = scb->buf;
+
+#ifdef HAVE_TERMIOS
+ return tcflush (scb->fd, TCIFLUSH);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCFLSH, 0);
+#endif
+
+#ifdef HAVE_SGTTY
+ /* This flushes both input and output, but we can't do better. */
+ return ioctl (scb->fd, TIOCFLUSH, 0);
+#endif
+}
+
+static int
+hardwire_send_break (scb)
+ serial_t scb;
+{
+#ifdef HAVE_TERMIOS
+ return tcsendbreak (scb->fd, 0);
+#endif
+
+#ifdef HAVE_TERMIO
+ return ioctl (scb->fd, TCSBRK, 0);
+#endif
+
+#ifdef HAVE_SGTTY
+ {
+ int status;
+ struct timeval timeout;
+
+ status = ioctl (scb->fd, TIOCSBRK, 0);
+
+ /* Can't use usleep; it doesn't exist in BSD 4.2. */
+ /* Note that if this select() is interrupted by a signal it will not wait
+ the full length of time. I think that is OK. */
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 250000;
+ select (0, 0, 0, 0, &timeout);
+ status = ioctl (scb->fd, TIOCCBRK, 0);
+ return status;
+ }
+#endif
+}
+
+static void
+hardwire_raw(scb)
+ serial_t scb;
+{
+ struct hardwire_ttystate state;
+
+ if (get_tty_state(scb, &state))
+ 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 |= CLOCAL | CS8;
+ state.termios.c_cc[VMIN] = 0;
+ state.termios.c_cc[VTIME] = 0;
+#endif
+
+#ifdef HAVE_TERMIO
+ state.termio.c_iflag = 0;
+ state.termio.c_oflag = 0;
+ state.termio.c_lflag = 0;
+ state.termio.c_cflag &= ~(CSIZE|PARENB);
+ state.termio.c_cflag |= CLOCAL | CS8;
+ state.termio.c_cc[VMIN] = 0;
+ state.termio.c_cc[VTIME] = 0;
+#endif
+
+#ifdef HAVE_SGTTY
+ state.sgttyb.sg_flags |= RAW | ANYP;
+ state.sgttyb.sg_flags &= ~(CBREAK | ECHO);
+#endif
+
+ scb->current_timeout = 0;
+
+ if (set_tty_state (scb, &state))
+ 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,
+ otherwise SERIAL_TIMEOUT or SERIAL_ERROR.
+
+ For termio{s}, we actually just setup VTIME if necessary, and let the
+ timeout occur in the read() in hardwire_read().
+ */
+
+static int
+wait_for(scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ scb->timeout_remaining = 0;
+
+#ifdef HAVE_SGTTY
+ {
+ struct timeval tv;
+ fd_set readfds;
+
+ FD_ZERO (&readfds);
+
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
+
+ FD_SET(scb->fd, &readfds);
+
+ 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;
+ 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_unfiltered(gdb_stderr, "get_tty_state failed: %s\n", safe_strerror(errno));
+
+#ifdef HAVE_TERMIOS
+ 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
+ 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
+
+ if (set_tty_state (scb, &state))
+ fprintf_unfiltered(gdb_stderr, "set_tty_state failed: %s\n", safe_strerror(errno));
+
+ return 0;
+ }
+#endif /* HAVE_TERMIO || HAVE_TERMIOS */
+}
+
+/* Read a character with user-specified timeout. TIMEOUT is number of seconds
+ to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
+ char if successful. Returns SERIAL_TIMEOUT if timeout expired, EOF if line
+ dropped dead, or SERIAL_ERROR for any other error (see errno in that case). */
+
+static int
+hardwire_readchar(scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int status;
+
+ if (scb->bufcnt-- > 0)
+ return *scb->bufp++;
+
+ while (1)
+ {
+ status = wait_for (scb, timeout);
+
+ if (status < 0)
+ return status;
+
+ scb->bufcnt = read (scb->fd, scb->buf, BUFSIZ);
+
+ 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++;
+ }
+}
+
+#ifndef B19200
+#define B19200 EXTA
+#endif
+
+#ifndef B38400
+#define B38400 EXTB
+#endif
+
+/* Translate baud rates from integers to damn B_codes. Unix should
+ have outgrown this crap years ago, but even POSIX wouldn't buck it. */
+
+static struct
+{
+ int rate;
+ int code;
+}
+baudtab[] =
+{
+ {50, B50},
+ {75, B75},
+ {110, B110},
+ {134, B134},
+ {150, B150},
+ {200, B200},
+ {300, B300},
+ {600, B600},
+ {1200, B1200},
+ {1800, B1800},
+ {2400, B2400},
+ {4800, B4800},
+ {9600, B9600},
+ {19200, B19200},
+ {38400, B38400},
+ {-1, -1},
+};
+
+static int
+rate_to_code(rate)
+ int rate;
+{
+ int i;
+
+ for (i = 0; baudtab[i].rate != -1; i++)
+ if (rate == baudtab[i].rate)
+ return baudtab[i].code;
+
+ return -1;
+}
+
+static int
+hardwire_setbaudrate(scb, rate)
+ serial_t scb;
+ int rate;
+{
+ struct hardwire_ttystate state;
+
+ if (get_tty_state(scb, &state))
+ return -1;
+
+#ifdef HAVE_TERMIOS
+ cfsetospeed (&state.termios, rate_to_code (rate));
+ cfsetispeed (&state.termios, rate_to_code (rate));
+#endif
+
+#ifdef HAVE_TERMIO
+#ifndef CIBAUD
+#define CIBAUD CBAUD
+#endif
+
+ state.termio.c_cflag &= ~(CBAUD | CIBAUD);
+ state.termio.c_cflag |= rate_to_code (rate);
+#endif
+
+#ifdef HAVE_SGTTY
+ state.sgttyb.sg_ispeed = rate_to_code (rate);
+ state.sgttyb.sg_ospeed = rate_to_code (rate);
+#endif
+
+ return set_tty_state (scb, &state);
+}
+
+static int
+hardwire_setstopbits(scb, num)
+ serial_t scb;
+ int num;
+{
+ struct hardwire_ttystate state;
+ int newbit;
+
+ if (get_tty_state(scb, &state))
+ return -1;
+
+ switch (num)
+ {
+ case SERIAL_1_STOPBITS:
+ newbit = 0;
+ break;
+ case SERIAL_1_AND_A_HALF_STOPBITS:
+ case SERIAL_2_STOPBITS:
+ newbit = 1;
+ break;
+ default:
+ return 1;
+ }
+
+#ifdef HAVE_TERMIOS
+ if (!newbit)
+ state.termios.c_cflag &= ~CSTOPB;
+ else
+ state.termios.c_cflag |= CSTOPB; /* two bits */
+#endif
+
+#ifdef HAVE_TERMIO
+ if (!newbit)
+ state.termio.c_cflag &= ~CSTOPB;
+ else
+ state.termio.c_cflag |= CSTOPB; /* two bits */
+#endif
+
+#ifdef HAVE_SGTTY
+ return 0; /* sgtty doesn't support this */
+#endif
+
+ return set_tty_state (scb, &state);
+}
+
+static int
+hardwire_write(scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ int cc;
+
+ while (len > 0)
+ {
+ cc = write(scb->fd, str, len);
+
+ if (cc < 0)
+ return 1;
+ len -= cc;
+ str += cc;
+ }
+ return 0;
+}
+
+static void
+hardwire_close(scb)
+ serial_t scb;
+{
+ if (scb->fd < 0)
+ return;
+
+ close(scb->fd);
+ scb->fd = -1;
+}
+
+static struct serial_ops hardwire_ops =
+{
+ "hardwire",
+ 0,
+ hardwire_open,
+ hardwire_close,
+ hardwire_readchar,
+ hardwire_write,
+ hardwire_flush_output,
+ hardwire_flush_input,
+ hardwire_send_break,
+ hardwire_raw,
+ hardwire_get_tty_state,
+ hardwire_set_tty_state,
+ hardwire_print_tty_state,
+ hardwire_noflush_set_tty_state,
+ hardwire_setbaudrate,
+ hardwire_setstopbits,
+};
+
+void
+_initialize_ser_hardwire ()
+{
+ serial_add_interface (&hardwire_ops);
+}
diff --git a/contrib/gdb/gdb/serial.c b/contrib/gdb/gdb/serial.c
new file mode 100644
index 0000000..18c6cde
--- /dev/null
+++ b/contrib/gdb/gdb/serial.c
@@ -0,0 +1,484 @@
+/* Generic serial interface routines
+ Copyright 1992, 1993, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <ctype.h>
+#include "serial.h"
+#include "gdb_string.h"
+#include "gdbcmd.h"
+
+/* Linked list of serial I/O handlers */
+
+static struct serial_ops *serial_ops_list = NULL;
+
+/* This is the last serial stream opened. Used by connect command. */
+
+static serial_t last_serial_opened = NULL;
+
+/* Pointer to list of scb's. */
+
+static serial_t scb_base;
+
+/* Non-NULL gives filename which contains a recording of the remote session,
+ suitable for playback by gdbserver. */
+
+char *serial_logfile = NULL;
+FILE *serial_logfp = NULL;
+
+
+static int serial_reading = 0;
+static int serial_writing = 0;
+
+void
+serial_log_command (cmd)
+ const char *cmd;
+{
+ if (serial_reading || serial_writing)
+ {
+ fputc_unfiltered ('\n', serial_logfp);
+ serial_reading = 0;
+ serial_writing = 0;
+ }
+ fprintf_unfiltered (serial_logfp, "c %s\n", cmd);
+ /* Make sure that the log file is as up-to-date as possible,
+ in case we are getting ready to dump core or something. */
+ fflush (serial_logfp);
+}
+
+static void
+serial_logchar (ch)
+ int ch;
+{
+ switch (ch)
+ {
+ case '\\': fputs_unfiltered ("\\\\", serial_logfp); break;
+ case '\b': fputs_unfiltered ("\\b", serial_logfp); break;
+ case '\f': fputs_unfiltered ("\\f", serial_logfp); break;
+ case '\n': fputs_unfiltered ("\\n", serial_logfp); break;
+ case '\r': fputs_unfiltered ("\\r", serial_logfp); break;
+ case '\t': fputs_unfiltered ("\\t", serial_logfp); break;
+ case '\v': fputs_unfiltered ("\\v", serial_logfp); break;
+ default: fprintf_unfiltered (serial_logfp, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); break;
+ }
+}
+
+int
+serial_write (scb, str, len)
+ serial_t scb;
+ const char *str;
+ int len;
+{
+ int count;
+
+ if (serial_logfp != NULL)
+ {
+ if (serial_reading)
+ {
+ fputc_unfiltered ('\n', serial_logfp);
+ serial_reading = 0;
+ }
+ if (!serial_writing)
+ {
+ serial_logchar ('w');
+ serial_logchar (' ');
+ serial_writing = 1;
+ }
+ for (count = 0; count < len; count++)
+ {
+ serial_logchar (str[count]);
+ }
+ /* Make sure that the log file is as up-to-date as possible,
+ in case we are getting ready to dump core or something. */
+ fflush (serial_logfp);
+ }
+ return (scb -> ops -> write (scb, str, len));
+}
+
+int
+serial_readchar (scb, timeout)
+ serial_t scb;
+ int timeout;
+{
+ int ch;
+
+ ch = scb -> ops -> readchar (scb, timeout);
+ if (serial_logfp != NULL)
+ {
+ if (serial_writing)
+ {
+ fputc_unfiltered ('\n', serial_logfp);
+ serial_writing = 0;
+ }
+ if (!serial_reading)
+ {
+ serial_logchar ('r');
+ serial_logchar (' ');
+ serial_reading = 1;
+ }
+ serial_logchar (ch);
+ /* Make sure that the log file is as up-to-date as possible,
+ in case we are getting ready to dump core or something. */
+ fflush (serial_logfp);
+ }
+ return (ch);
+}
+
+static struct serial_ops *
+serial_interface_lookup (name)
+ char *name;
+{
+ struct serial_ops *ops;
+
+ for (ops = serial_ops_list; ops; ops = ops->next)
+ if (strcmp (name, ops->name) == 0)
+ return ops;
+
+ return NULL;
+}
+
+void
+serial_add_interface(optable)
+ struct serial_ops *optable;
+{
+ optable->next = serial_ops_list;
+ serial_ops_list = optable;
+}
+
+/* Open up a device or a network socket, depending upon the syntax of NAME. */
+
+serial_t
+serial_open (name)
+ const char *name;
+{
+ serial_t scb;
+ struct serial_ops *ops;
+
+ for (scb = scb_base; scb; scb = scb->next)
+ if (scb->name && strcmp (scb->name, name) == 0)
+ {
+ scb->refcnt++;
+ return scb;
+ }
+
+ if (strcmp (name, "pc") == 0)
+ ops = serial_interface_lookup ("pc");
+ else if (strchr (name, ':'))
+ ops = serial_interface_lookup ("tcp");
+ else if (strncmp (name, "lpt", 3) == 0)
+ ops = serial_interface_lookup ("parallel");
+ else
+ ops = serial_interface_lookup ("hardwire");
+
+ if (!ops)
+ return NULL;
+
+ scb = (serial_t)xmalloc (sizeof (struct _serial_t));
+
+ scb->ops = ops;
+
+ scb->bufcnt = 0;
+ scb->bufp = scb->buf;
+
+ if (scb->ops->open(scb, name))
+ {
+ free (scb);
+ return NULL;
+ }
+
+ scb->name = strsave (name);
+ scb->next = scb_base;
+ scb->refcnt = 1;
+ scb_base = scb;
+
+ last_serial_opened = scb;
+
+ if (serial_logfile != NULL)
+ {
+ serial_logfp = fopen (serial_logfile, "w");
+ if (serial_logfp == NULL)
+ {
+ perror_with_name (serial_logfile);
+ }
+ }
+
+ return scb;
+}
+
+serial_t
+serial_fdopen (fd)
+ const int fd;
+{
+ serial_t scb;
+ struct serial_ops *ops;
+
+ for (scb = scb_base; scb; scb = scb->next)
+ if (scb->fd == fd)
+ {
+ scb->refcnt++;
+ return scb;
+ }
+
+ ops = serial_interface_lookup ("hardwire");
+
+ if (!ops)
+ return NULL;
+
+ scb = (serial_t)xmalloc (sizeof (struct _serial_t));
+
+ scb->ops = ops;
+
+ scb->bufcnt = 0;
+ scb->bufp = scb->buf;
+
+ scb->fd = fd;
+
+ scb->name = NULL;
+ scb->next = scb_base;
+ scb->refcnt = 1;
+ scb_base = scb;
+
+ last_serial_opened = scb;
+
+ return scb;
+}
+
+void
+serial_close(scb, really_close)
+ serial_t scb;
+ int really_close;
+{
+ serial_t tmp_scb;
+
+ last_serial_opened = NULL;
+
+ if (serial_logfp)
+ {
+ if (serial_reading || serial_writing)
+ {
+ fputc_unfiltered ('\n', serial_logfp);
+ serial_reading = 0;
+ serial_writing = 0;
+ }
+ fclose (serial_logfp);
+ serial_logfp = NULL;
+ }
+
+/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
+ should fix your code instead. */
+
+ if (!scb)
+ return;
+
+ scb->refcnt--;
+ if (scb->refcnt > 0)
+ return;
+
+ if (really_close)
+ scb->ops->close (scb);
+
+ if (scb->name)
+ free (scb->name);
+
+ if (scb_base == scb)
+ scb_base = scb_base->next;
+ else
+ for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
+ {
+ if (tmp_scb->next != scb)
+ continue;
+
+ tmp_scb->next = tmp_scb->next->next;
+ break;
+ }
+
+ free(scb);
+}
+
+#if 0
+/*
+The connect command is #if 0 because I hadn't thought of an elegant
+way to wait for I/O on two serial_t's simultaneously. Two solutions
+came to mind:
+
+ 1) Fork, and have have one fork handle the to user direction,
+ and have the other hand the to target direction. This
+ obviously won't cut it for MSDOS.
+
+ 2) Use something like select. This assumes that stdin and
+ the target side can both be waited on via the same
+ mechanism. This may not be true for DOS, if GDB is
+ talking to the target via a TCP socket.
+-grossman, 8 Jun 93
+*/
+
+/* Connect the user directly to the remote system. This command acts just like
+ the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
+
+static serial_t tty_desc; /* Controlling terminal */
+
+static void
+cleanup_tty(ttystate)
+ serial_ttystate ttystate;
+{
+ printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
+ SERIAL_SET_TTY_STATE (tty_desc, ttystate);
+ free (ttystate);
+ SERIAL_CLOSE (tty_desc);
+}
+
+static void
+connect_command (args, fromtty)
+ char *args;
+ int fromtty;
+{
+ int c;
+ char cur_esc = 0;
+ serial_ttystate ttystate;
+ serial_t port_desc; /* TTY port */
+
+ dont_repeat();
+
+ if (args)
+ fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
+
+ printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
+
+ tty_desc = SERIAL_FDOPEN (0);
+ port_desc = last_serial_opened;
+
+ ttystate = SERIAL_GET_TTY_STATE (tty_desc);
+
+ SERIAL_RAW (tty_desc);
+ SERIAL_RAW (port_desc);
+
+ make_cleanup (cleanup_tty, ttystate);
+
+ while (1)
+ {
+ int mask;
+
+ mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
+
+ if (mask & 2)
+ { /* tty input */
+ char cx;
+
+ while (1)
+ {
+ c = SERIAL_READCHAR(tty_desc, 0);
+
+ if (c == SERIAL_TIMEOUT)
+ break;
+
+ if (c < 0)
+ perror_with_name("connect");
+
+ cx = c;
+ SERIAL_WRITE(port_desc, &cx, 1);
+
+ switch (cur_esc)
+ {
+ case 0:
+ if (c == '\r')
+ cur_esc = c;
+ break;
+ case '\r':
+ if (c == '~')
+ cur_esc = c;
+ else
+ cur_esc = 0;
+ break;
+ case '~':
+ if (c == '.' || c == '\004')
+ return;
+ else
+ cur_esc = 0;
+ }
+ }
+ }
+
+ if (mask & 1)
+ { /* Port input */
+ char cx;
+
+ while (1)
+ {
+ c = SERIAL_READCHAR(port_desc, 0);
+
+ if (c == SERIAL_TIMEOUT)
+ break;
+
+ if (c < 0)
+ perror_with_name("connect");
+
+ cx = c;
+
+ SERIAL_WRITE(tty_desc, &cx, 1);
+ }
+ }
+ }
+}
+#endif /* 0 */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+serial_printf (serial_t desc, const char *format, ...)
+#else
+serial_printf (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char *buf;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ serial_t desc;
+ char *format;
+
+ va_start (args);
+ desc = va_arg (args, serial_t);
+ format = va_arg (args, char *);
+#endif
+
+ vasprintf (&buf, format, args);
+ SERIAL_WRITE (desc, buf, strlen (buf));
+
+ free (buf);
+ va_end (args);
+}
+
+void
+_initialize_serial ()
+{
+#if 0
+ add_com ("connect", class_obscure, connect_command,
+ "Connect the terminal directly up to the command monitor.\n\
+Use <CR>~. or <CR>~^D to break out.");
+#endif /* 0 */
+
+ add_show_from_set (add_set_cmd ("remotelogfile", no_class,
+ var_filename, (char *)&serial_logfile,
+ "Set filename for remote session recording.\n\
+This file is used to record the remote session for future playback\n\
+by gdbserver.", &setlist),
+ &showlist);
+
+}
diff --git a/contrib/gdb/gdb/serial.h b/contrib/gdb/gdb/serial.h
new file mode 100644
index 0000000..8abcb3d
--- /dev/null
+++ b/contrib/gdb/gdb/serial.h
@@ -0,0 +1,182 @@
+/* Remote serial support interface definitions for GDB, the GNU Debugger.
+ Copyright 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef SERIAL_H
+#define SERIAL_H
+
+/* Terminal state pointer. This is specific to each type of interface. */
+
+typedef PTR serial_ttystate;
+
+struct _serial_t
+{
+ int fd; /* File descriptor */
+ struct serial_ops *ops; /* Function vector */
+ serial_ttystate ttystate; /* Not used (yet) */
+ int bufcnt; /* Amount of data in receive buffer */
+ 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;
+ char *name; /* The name of the device or host */
+ struct _serial_t *next; /* Pointer to the next serial_t */
+ int refcnt; /* Number of pointers to this block */
+};
+
+typedef struct _serial_t *serial_t;
+
+struct serial_ops {
+ char *name;
+ struct serial_ops *next;
+ int (*open) PARAMS ((serial_t, const char *name));
+ void (*close) PARAMS ((serial_t));
+ int (*readchar) PARAMS ((serial_t, int timeout));
+ int (*write) PARAMS ((serial_t, const char *str, int len));
+ int (*flush_output) PARAMS ((serial_t));
+ int (*flush_input) PARAMS ((serial_t));
+ int (*send_break) PARAMS ((serial_t));
+ void (*go_raw) PARAMS ((serial_t));
+ serial_ttystate (*get_tty_state) PARAMS ((serial_t));
+ int (*set_tty_state) PARAMS ((serial_t, serial_ttystate));
+ void (*print_tty_state) PARAMS ((serial_t, serial_ttystate));
+ int (*noflush_set_tty_state)
+ PARAMS ((serial_t, serial_ttystate, serial_ttystate));
+ int (*setbaudrate) PARAMS ((serial_t, int rate));
+ int (*setstopbits) PARAMS ((serial_t, int num));
+};
+
+/* Add a new serial interface to the interface list */
+
+void serial_add_interface PARAMS ((struct serial_ops *optable));
+
+serial_t serial_open PARAMS ((const char *name));
+
+serial_t serial_fdopen PARAMS ((const int fd));
+
+/* For most routines, if a failure is indicated, then errno should be
+ examined. */
+
+/* Try to open NAME. Returns a new serial_t on success, NULL on failure.
+ */
+
+#define SERIAL_OPEN(NAME) serial_open(NAME)
+
+/* Open a new serial stream using a file handle. */
+
+#define SERIAL_FDOPEN(FD) serial_fdopen(FD)
+
+/* Flush pending output. Might also flush input (if this system can't flush
+ only output). */
+
+#define SERIAL_FLUSH_OUTPUT(SERIAL_T) \
+ ((SERIAL_T)->ops->flush_output((SERIAL_T)))
+
+/* Flush pending input. Might also flush output (if this system can't flush
+ only input). */
+
+#define SERIAL_FLUSH_INPUT(SERIAL_T)\
+ ((*(SERIAL_T)->ops->flush_input) ((SERIAL_T)))
+
+/* Send a break between 0.25 and 0.5 seconds long. */
+
+#define SERIAL_SEND_BREAK(SERIAL_T) \
+ ((*(SERIAL_T)->ops->send_break) (SERIAL_T))
+
+/* Turn the port into raw mode. */
+
+#define SERIAL_RAW(SERIAL_T) (SERIAL_T)->ops->go_raw((SERIAL_T))
+
+/* Return a pointer to a newly malloc'd ttystate containing the state
+ of the tty. */
+#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.
+ 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. */
+#define SERIAL_PRINT_TTY_STATE(SERIAL_T, TTYSTATE) \
+ ((*((SERIAL_T)->ops->print_tty_state)) ((SERIAL_T), (TTYSTATE)))
+
+/* Set the tty state to NEW_TTYSTATE, where OLD_TTYSTATE is the
+ current state (generally obtained from a recent call to
+ SERIAL_GET_TTY_STATE), but be careful not to discard any input.
+ This means that we never switch in or out of raw mode, even
+ if NEW_TTYSTATE specifies a switch. */
+#define SERIAL_NOFLUSH_SET_TTY_STATE(SERIAL_T, NEW_TTYSTATE, OLD_TTYSTATE) \
+ ((*((SERIAL_T)->ops->noflush_set_tty_state)) \
+ ((SERIAL_T), (NEW_TTYSTATE), (OLD_TTYSTATE)))
+
+/* Read one char from the serial device with TIMEOUT seconds to wait
+ or -1 to wait forever. Use timeout of 0 to effect a poll. Returns
+ char if ok, else one of the following codes. Note that all error
+ codes are guaranteed to be < 0. */
+
+#define SERIAL_ERROR -1 /* General error, see errno for details */
+#define SERIAL_TIMEOUT -2
+#define SERIAL_EOF -3
+
+extern int serial_readchar PARAMS ((serial_t scb, int timeout));
+
+#define SERIAL_READCHAR(SERIAL_T, TIMEOUT) serial_readchar (SERIAL_T, TIMEOUT)
+
+/* Set the baudrate to the decimal value supplied. Returns 0 for success,
+ -1 for failure. */
+
+#define SERIAL_SETBAUDRATE(SERIAL_T, RATE) ((SERIAL_T)->ops->setbaudrate((SERIAL_T), RATE))
+
+/* Set the number of stop bits to the value specified. Returns 0 for success,
+ -1 for failure. */
+
+#define SERIAL_1_STOPBITS 1
+#define SERIAL_1_AND_A_HALF_STOPBITS 2 /* 1.5 bits, snicker... */
+#define SERIAL_2_STOPBITS 3
+
+#define SERIAL_SETSTOPBITS(SERIAL_T, NUM) ((SERIAL_T)->ops->setstopbits((SERIAL_T), NUM))
+
+/* Write LEN chars from STRING to the port SERIAL_T. Returns 0 for
+ success, non-zero for failure. */
+
+extern int serial_write PARAMS ((serial_t scb, const char *str, int len));
+
+#define SERIAL_WRITE(SERIAL_T, STRING,LEN) serial_write (SERIAL_T, STRING, LEN)
+
+/* Push out all buffers, close the device and destroy SERIAL_T. */
+
+extern void serial_close PARAMS ((serial_t, int));
+
+#define SERIAL_CLOSE(SERIAL_T) serial_close(SERIAL_T, 1)
+
+/* Push out all buffers and destroy SERIAL_T without closing the device. */
+
+#define SERIAL_UN_FDOPEN(SERIAL_T) serial_close(SERIAL_T, 0)
+
+extern void serial_printf PARAMS ((serial_t desc, const char *, ...))
+ ATTR_FORMAT(printf, 2, 3);
+
+/* File in which to record the remote debugging session */
+
+extern char *serial_logfile;
+extern FILE *serial_logfp;
+
+#endif /* SERIAL_H */
diff --git a/contrib/gdb/gdb/signals.h b/contrib/gdb/gdb/signals.h
new file mode 100644
index 0000000..a1348b6
--- /dev/null
+++ b/contrib/gdb/gdb/signals.h
@@ -0,0 +1,27 @@
+/* Signal handler definitions for GDB, the GNU Debugger.
+ Copyright (C) 1986, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is almost the same as including <signal.h> except that it
+ eliminates certain signal names when job control is not supported,
+ (or, on some systems, when job control is there but doesn't work
+ the way GDB expects it to work). */
+/* This has been superceded by the job_control variable in serial.h. */
+
+#include <signal.h>
diff --git a/contrib/gdb/gdb/solib.c b/contrib/gdb/gdb/solib.c
new file mode 100644
index 0000000..3a20b55
--- /dev/null
+++ b/contrib/gdb/gdb/solib.c
@@ -0,0 +1,1714 @@
+/* Handle SunOS and SVR4 shared libraries for GDB, the GNU Debugger.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+
+/* This file is only compilable if link.h is available. */
+
+#ifdef HAVE_LINK_H
+
+#include <sys/types.h>
+#include <signal.h>
+#include "gdb_string.h"
+#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#ifndef SVR4_SHARED_LIBS
+ /* SunOS shared libs need the nlist structure. */
+#include <a.out.h>
+#else
+#include "elf/external.h"
+#endif
+
+#include <link.h>
+
+#include "symtab.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "target.h"
+#include "frame.h"
+#include "gnu-regex.h"
+#include "inferior.h"
+#include "environ.h"
+#include "language.h"
+#include "gdbcmd.h"
+
+#define MAX_PATH_SIZE 512 /* FIXME: Should be dynamic */
+
+/* On SVR4 systems, a list of symbols in the dynamic linker where
+ GDB can try to place a breakpoint to monitor shared library
+ events.
+
+ If none of these symbols are found, or other errors occur, then
+ SVR4 systems will fall back to using a symbol as the "startup
+ mapping complete" breakpoint address. */
+
+#ifdef SVR4_SHARED_LIBS
+static char *solib_break_names[] = {
+ "r_debug_state",
+ "_r_debug_state",
+ "_dl_debug_state",
+ NULL
+};
+#endif
+
+#define BKPT_AT_SYMBOL 1
+
+#if defined (BKPT_AT_SYMBOL) && defined (SVR4_SHARED_LIBS)
+static char *bkpt_names[] = {
+#ifdef SOLIB_BKPT_NAME
+ SOLIB_BKPT_NAME, /* Prefer configured name if it exists. */
+#endif
+ "_start",
+ "main",
+ NULL
+};
+#endif
+
+/* Symbols which are used to locate the base of the link map structures. */
+
+#ifndef SVR4_SHARED_LIBS
+static char *debug_base_symbols[] = {
+ "_DYNAMIC",
+ "_DYNAMIC__MGC",
+ NULL
+};
+#endif
+
+static char *main_name_list[] = {
+ "main_$main",
+ NULL
+};
+
+/* local data declarations */
+
+#ifndef SVR4_SHARED_LIBS
+
+#define LM_ADDR(so) ((so) -> lm.lm_addr)
+#define LM_NEXT(so) ((so) -> lm.lm_next)
+#define LM_NAME(so) ((so) -> lm.lm_name)
+/* Test for first link map entry; first entry is a shared library. */
+#define IGNORE_FIRST_LINK_MAP_ENTRY(x) (0)
+static struct link_dynamic dynamic_copy;
+static struct link_dynamic_2 ld_2_copy;
+static struct ld_debug debug_copy;
+static CORE_ADDR debug_addr;
+static CORE_ADDR flag_addr;
+
+#else /* SVR4_SHARED_LIBS */
+
+#define LM_ADDR(so) ((so) -> lm.l_addr)
+#define LM_NEXT(so) ((so) -> lm.l_next)
+#define LM_NAME(so) ((so) -> lm.l_name)
+/* Test for first link map entry; first entry is the exec-file. */
+#define IGNORE_FIRST_LINK_MAP_ENTRY(x) ((x).l_prev == NULL)
+static struct r_debug debug_copy;
+char shadow_contents[BREAKPOINT_MAX]; /* Stash old bkpt addr contents */
+
+#endif /* !SVR4_SHARED_LIBS */
+
+struct so_list {
+ struct so_list *next; /* next structure in linked list */
+ struct link_map lm; /* copy of link map from inferior */
+ struct link_map *lmaddr; /* addr in inferior lm was read from */
+ CORE_ADDR lmend; /* upper addr bound of mapped object */
+ char so_name[MAX_PATH_SIZE]; /* shared object lib name (FIXME) */
+ char symbols_loaded; /* flag: symbols read in yet? */
+ char from_tty; /* flag: print msgs? */
+ struct objfile *objfile; /* objfile for loaded lib */
+ struct section_table *sections;
+ struct section_table *sections_end;
+ struct section_table *textsection;
+ bfd *abfd;
+};
+
+static struct so_list *so_list_head; /* List of known shared objects */
+static CORE_ADDR debug_base; /* Base of dynamic linker structures */
+static CORE_ADDR breakpoint_addr; /* Address where end bkpt is set */
+
+extern int
+fdmatch PARAMS ((int, int)); /* In libiberty */
+
+/* Local function prototypes */
+
+static void
+special_symbol_handling PARAMS ((struct so_list *));
+
+static void
+sharedlibrary_command PARAMS ((char *, int));
+
+static int
+enable_break PARAMS ((void));
+
+static void
+info_sharedlibrary_command PARAMS ((char *, int));
+
+static int
+symbol_add_stub PARAMS ((char *));
+
+static struct so_list *
+find_solib PARAMS ((struct so_list *));
+
+static struct link_map *
+first_link_map_member PARAMS ((void));
+
+static CORE_ADDR
+locate_base PARAMS ((void));
+
+static void
+solib_map_sections PARAMS ((struct so_list *));
+
+#ifdef SVR4_SHARED_LIBS
+
+static CORE_ADDR
+elf_locate_base PARAMS ((void));
+
+#else
+
+static int
+disable_break PARAMS ((void));
+
+static void
+allocate_rt_common_objfile PARAMS ((void));
+
+static void
+solib_add_common_symbols PARAMS ((struct rtc_symb *));
+
+#endif
+
+/*
+
+LOCAL FUNCTION
+
+ solib_map_sections -- open bfd and build sections for shared lib
+
+SYNOPSIS
+
+ static void solib_map_sections (struct so_list *so)
+
+DESCRIPTION
+
+ Given a pointer to one of the shared objects in our list
+ of mapped objects, use the recorded name to open a bfd
+ descriptor for the object, build a section table, and then
+ relocate all the section addresses by the base address at
+ which the shared object was mapped.
+
+FIXMES
+
+ In most (all?) cases the shared object file name recorded in the
+ dynamic linkage tables will be a fully qualified pathname. For
+ cases where it isn't, do we really mimic the systems search
+ mechanism correctly in the below code (particularly the tilde
+ expansion stuff?).
+ */
+
+static void
+solib_map_sections (so)
+ struct so_list *so;
+{
+ char *filename;
+ char *scratch_pathname;
+ int scratch_chan;
+ struct section_table *p;
+ struct cleanup *old_chain;
+ bfd *abfd;
+
+ filename = tilde_expand (so -> so_name);
+ old_chain = make_cleanup (free, filename);
+
+ scratch_chan = openp (get_in_environ (inferior_environ, "PATH"),
+ 1, filename, O_RDONLY, 0, &scratch_pathname);
+ if (scratch_chan < 0)
+ {
+ scratch_chan = openp (get_in_environ
+ (inferior_environ, "LD_LIBRARY_PATH"),
+ 1, filename, O_RDONLY, 0, &scratch_pathname);
+ }
+ if (scratch_chan < 0)
+ {
+ perror_with_name (filename);
+ }
+ /* Leave scratch_pathname allocated. abfd->name will point to it. */
+
+ abfd = bfd_fdopenr (scratch_pathname, gnutarget, scratch_chan);
+ if (!abfd)
+ {
+ close (scratch_chan);
+ error ("Could not open `%s' as an executable file: %s",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+ /* Leave bfd open, core_xfer_memory and "info files" need it. */
+ so -> abfd = abfd;
+ abfd -> cacheable = true;
+
+ /* copy full path name into so_name, so that later symbol_file_add can find
+ it */
+ if (strlen (scratch_pathname) >= MAX_PATH_SIZE)
+ error ("Full path name length of shared library exceeds MAX_PATH_SIZE in so_list structure.");
+ strcpy (so->so_name, scratch_pathname);
+
+ if (!bfd_check_format (abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ scratch_pathname, bfd_errmsg (bfd_get_error ()));
+ }
+ if (build_section_table (abfd, &so -> sections, &so -> sections_end))
+ {
+ error ("Can't find the file sections in `%s': %s",
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+ }
+
+ for (p = so -> sections; p < so -> sections_end; p++)
+ {
+ /* Relocate the section binding addresses as recorded in the shared
+ object's file by the base address to which the object was actually
+ mapped. */
+ p -> addr += (CORE_ADDR) LM_ADDR (so);
+ p -> endaddr += (CORE_ADDR) LM_ADDR (so);
+ so -> lmend = (CORE_ADDR) max (p -> endaddr, so -> lmend);
+ if (STREQ (p -> the_bfd_section -> name, ".text"))
+ {
+ so -> textsection = p;
+ }
+ }
+
+ /* Free the file names, close the file now. */
+ do_cleanups (old_chain);
+}
+
+#ifndef SVR4_SHARED_LIBS
+
+/* Allocate the runtime common object file. */
+
+static void
+allocate_rt_common_objfile ()
+{
+ struct objfile *objfile;
+ struct objfile *last_one;
+
+ objfile = (struct objfile *) xmalloc (sizeof (struct objfile));
+ memset (objfile, 0, sizeof (struct objfile));
+ objfile -> md = NULL;
+ obstack_specify_allocation (&objfile -> psymbol_cache.cache, 0, 0,
+ xmalloc, free);
+ 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);
+ objfile -> name = mstrsave (objfile -> md, "rt_common");
+
+ /* Add this file onto the tail of the linked list of other such files. */
+
+ objfile -> next = NULL;
+ if (object_files == NULL)
+ object_files = objfile;
+ else
+ {
+ for (last_one = object_files;
+ last_one -> next;
+ last_one = last_one -> next);
+ last_one -> next = objfile;
+ }
+
+ rt_common_objfile = objfile;
+}
+
+/* Read all dynamically loaded common symbol definitions from the inferior
+ and put them into the minimal symbol table for the runtime common
+ objfile. */
+
+static void
+solib_add_common_symbols (rtc_symp)
+ struct rtc_symb *rtc_symp;
+{
+ struct rtc_symb inferior_rtc_symb;
+ struct nlist inferior_rtc_nlist;
+ int len;
+ char *name;
+ char *origname;
+
+ /* Remove any runtime common symbols from previous runs. */
+
+ if (rt_common_objfile != NULL && rt_common_objfile -> minimal_symbol_count)
+ {
+ obstack_free (&rt_common_objfile -> symbol_obstack, 0);
+ obstack_specify_allocation (&rt_common_objfile -> symbol_obstack, 0, 0,
+ xmalloc, free);
+ rt_common_objfile -> minimal_symbol_count = 0;
+ rt_common_objfile -> msymbols = NULL;
+ }
+
+ init_minimal_symbol_collection ();
+ make_cleanup (discard_minimal_symbols, 0);
+
+ while (rtc_symp)
+ {
+ read_memory ((CORE_ADDR) rtc_symp,
+ (char *) &inferior_rtc_symb,
+ sizeof (inferior_rtc_symb));
+ read_memory ((CORE_ADDR) inferior_rtc_symb.rtc_sp,
+ (char *) &inferior_rtc_nlist,
+ sizeof(inferior_rtc_nlist));
+ if (inferior_rtc_nlist.n_type == N_COMM)
+ {
+ /* FIXME: The length of the symbol name is not available, but in the
+ current implementation the common symbol is allocated immediately
+ behind the name of the symbol. */
+ len = inferior_rtc_nlist.n_value - inferior_rtc_nlist.n_un.n_strx;
+
+ origname = name = xmalloc (len);
+ read_memory ((CORE_ADDR) inferior_rtc_nlist.n_un.n_name, name, len);
+
+ /* Allocate the runtime common objfile if necessary. */
+ if (rt_common_objfile == NULL)
+ allocate_rt_common_objfile ();
+
+ name = obsavestring (name, strlen (name),
+ &rt_common_objfile -> symbol_obstack);
+ prim_record_minimal_symbol (name, inferior_rtc_nlist.n_value,
+ mst_bss, rt_common_objfile);
+ free (origname);
+ }
+ rtc_symp = inferior_rtc_symb.rtc_next;
+ }
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for the runtime common objfile. */
+
+ install_minimal_symbols (rt_common_objfile);
+}
+
+#endif /* SVR4_SHARED_LIBS */
+
+
+#ifdef SVR4_SHARED_LIBS
+
+static CORE_ADDR
+bfd_lookup_symbol PARAMS ((bfd *, char *));
+
+/*
+
+LOCAL FUNCTION
+
+ bfd_lookup_symbol -- lookup the value for a specific symbol
+
+SYNOPSIS
+
+ CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
+
+DESCRIPTION
+
+ An expensive way to lookup the value of a single symbol for
+ bfd's that are only temporary anyway. This is used by the
+ shared library support to find the address of the debugger
+ interface structures in the shared library.
+
+ Note that 0 is specifically allowed as an error return (no
+ such symbol).
+*/
+
+static CORE_ADDR
+bfd_lookup_symbol (abfd, symname)
+ bfd *abfd;
+ char *symname;
+{
+ unsigned int storage_needed;
+ asymbol *sym;
+ asymbol **symbol_table;
+ unsigned int number_of_symbols;
+ unsigned int i;
+ struct cleanup *back_to;
+ CORE_ADDR symaddr = 0;
+
+ storage_needed = bfd_get_symtab_upper_bound (abfd);
+
+ if (storage_needed > 0)
+ {
+ symbol_table = (asymbol **) xmalloc (storage_needed);
+ back_to = make_cleanup (free, (PTR)symbol_table);
+ number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table);
+
+ for (i = 0; i < number_of_symbols; i++)
+ {
+ sym = *symbol_table++;
+ if (STREQ (sym -> name, symname))
+ {
+ /* Bfd symbols are section relative. */
+ symaddr = sym -> value + sym -> section -> vma;
+ break;
+ }
+ }
+ do_cleanups (back_to);
+ }
+ return (symaddr);
+}
+
+#ifdef HANDLE_SVR4_EXEC_EMULATORS
+
+/*
+ Solaris BCP (the part of Solaris which allows it to run SunOS4
+ a.out files) throws in another wrinkle. Solaris does not fill
+ in the usual a.out link map structures when running BCP programs,
+ the only way to get at them is via groping around in the dynamic
+ linker.
+ The dynamic linker and it's structures are located in the shared
+ C library, which gets run as the executable's "interpreter" by
+ the kernel.
+
+ Note that we can assume nothing about the process state at the time
+ we need to find these structures. We may be stopped on the first
+ instruction of the interpreter (C shared library), the first
+ instruction of the executable itself, or somewhere else entirely
+ (if we attached to the process for example).
+*/
+
+static char *debug_base_symbols[] = {
+ "r_debug", /* Solaris 2.3 */
+ "_r_debug", /* Solaris 2.1, 2.2 */
+ NULL
+};
+
+static int
+look_for_base PARAMS ((int, CORE_ADDR));
+
+/*
+
+LOCAL FUNCTION
+
+ look_for_base -- examine file for each mapped address segment
+
+SYNOPSYS
+
+ static int look_for_base (int fd, CORE_ADDR baseaddr)
+
+DESCRIPTION
+
+ This function is passed to proc_iterate_over_mappings, which
+ causes it to get called once for each mapped address space, with
+ an open file descriptor for the file mapped to that space, and the
+ base address of that mapped space.
+
+ Our job is to find the debug base symbol in the file that this
+ fd is open on, if it exists, and if so, initialize the dynamic
+ linker structure base address debug_base.
+
+ Note that this is a computationally expensive proposition, since
+ we basically have to open a bfd on every call, so we specifically
+ avoid opening the exec file.
+ */
+
+static int
+look_for_base (fd, baseaddr)
+ int fd;
+ CORE_ADDR baseaddr;
+{
+ bfd *interp_bfd;
+ CORE_ADDR address = 0;
+ char **symbolp;
+
+ /* If the fd is -1, then there is no file that corresponds to this
+ mapped memory segment, so skip it. Also, if the fd corresponds
+ to the exec file, skip it as well. */
+
+ if (fd == -1
+ || (exec_bfd != NULL
+ && fdmatch (fileno ((GDB_FILE *)(exec_bfd -> iostream)), fd)))
+ {
+ return (0);
+ }
+
+ /* Try to open whatever random file this fd corresponds to. Note that
+ we have no way currently to find the filename. Don't gripe about
+ any problems we might have, just fail. */
+
+ if ((interp_bfd = bfd_fdopenr ("unnamed", gnutarget, fd)) == NULL)
+ {
+ return (0);
+ }
+ if (!bfd_check_format (interp_bfd, bfd_object))
+ {
+ /* FIXME-leak: on failure, might not free all memory associated with
+ interp_bfd. */
+ bfd_close (interp_bfd);
+ return (0);
+ }
+
+ /* Now try to find our debug base symbol in this file, which we at
+ least know to be a valid ELF executable or shared library. */
+
+ for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++)
+ {
+ address = bfd_lookup_symbol (interp_bfd, *symbolp);
+ if (address != 0)
+ {
+ break;
+ }
+ }
+ if (address == 0)
+ {
+ /* FIXME-leak: on failure, might not free all memory associated with
+ interp_bfd. */
+ bfd_close (interp_bfd);
+ return (0);
+ }
+
+ /* Eureka! We found the symbol. But now we may need to relocate it
+ by the base address. If the symbol's value is less than the base
+ address of the shared library, then it hasn't yet been relocated
+ by the dynamic linker, and we have to do it ourself. FIXME: Note
+ that we make the assumption that the first segment that corresponds
+ to the shared library has the base address to which the library
+ was relocated. */
+
+ if (address < baseaddr)
+ {
+ address += baseaddr;
+ }
+ debug_base = address;
+ /* FIXME-leak: on failure, might not free all memory associated with
+ interp_bfd. */
+ bfd_close (interp_bfd);
+ return (1);
+}
+#endif /* HANDLE_SVR4_EXEC_EMULATORS */
+
+/*
+
+LOCAL FUNCTION
+
+ elf_locate_base -- locate the base address of dynamic linker structs
+ for SVR4 elf targets.
+
+SYNOPSIS
+
+ CORE_ADDR elf_locate_base (void)
+
+DESCRIPTION
+
+ For SVR4 elf targets the address of the dynamic linker's runtime
+ structure is contained within the dynamic info section in the
+ executable file. The dynamic section is also mapped into the
+ inferior address space. Because the runtime loader fills in the
+ real address before starting the inferior, we have to read in the
+ dynamic info section from the inferior address space.
+ If there are any errors while trying to find the address, we
+ silently return 0, otherwise the found address is returned.
+
+ */
+
+static CORE_ADDR
+elf_locate_base ()
+{
+ sec_ptr dyninfo_sect;
+ int dyninfo_sect_size;
+ CORE_ADDR dyninfo_addr;
+ char *buf;
+ char *bufend;
+
+ /* Find the start address of the .dynamic section. */
+ dyninfo_sect = bfd_get_section_by_name (exec_bfd, ".dynamic");
+ if (dyninfo_sect == NULL)
+ return 0;
+ dyninfo_addr = bfd_section_vma (exec_bfd, dyninfo_sect);
+
+ /* Read in .dynamic section, silently ignore errors. */
+ dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
+ buf = alloca (dyninfo_sect_size);
+ if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
+ return 0;
+
+ /* Find the DT_DEBUG entry in the the .dynamic section.
+ For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
+ no DT_DEBUG entries. */
+ /* FIXME: In lack of a 64 bit ELF ABI the following code assumes
+ a 32 bit ELF ABI target. */
+ for (bufend = buf + dyninfo_sect_size;
+ buf < bufend;
+ buf += sizeof (Elf32_External_Dyn))
+ {
+ Elf32_External_Dyn *x_dynp = (Elf32_External_Dyn *)buf;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr;
+
+ dyn_tag = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
+ if (dyn_tag == DT_NULL)
+ break;
+ else if (dyn_tag == DT_DEBUG)
+ {
+ dyn_ptr = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
+ return dyn_ptr;
+ }
+#ifdef DT_MIPS_RLD_MAP
+ else if (dyn_tag == DT_MIPS_RLD_MAP)
+ {
+ char pbuf[TARGET_PTR_BIT / HOST_CHAR_BIT];
+
+ /* DT_MIPS_RLD_MAP contains a pointer to the address
+ of the dynamic link structure. */
+ dyn_ptr = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr);
+ if (target_read_memory (dyn_ptr, pbuf, sizeof (pbuf)))
+ return 0;
+ return extract_unsigned_integer (pbuf, sizeof (pbuf));
+ }
+#endif
+ }
+
+ /* DT_DEBUG entry not found. */
+ return 0;
+}
+
+#endif /* SVR4_SHARED_LIBS */
+
+/*
+
+LOCAL FUNCTION
+
+ locate_base -- locate the base address of dynamic linker structs
+
+SYNOPSIS
+
+ CORE_ADDR locate_base (void)
+
+DESCRIPTION
+
+ For both the SunOS and SVR4 shared library implementations, if the
+ inferior executable has been linked dynamically, there is a single
+ address somewhere in the inferior's data space which is the key to
+ locating all of the dynamic linker's runtime structures. This
+ address is the value of the debug base symbol. The job of this
+ function is to find and return that address, or to return 0 if there
+ is no such address (the executable is statically linked for example).
+
+ For SunOS, the job is almost trivial, since the dynamic linker and
+ all of it's structures are statically linked to the executable at
+ link time. Thus the symbol for the address we are looking for has
+ already been added to the minimal symbol table for the executable's
+ objfile at the time the symbol file's symbols were read, and all we
+ have to do is look it up there. Note that we explicitly do NOT want
+ to find the copies in the shared library.
+
+ The SVR4 version is a bit more complicated because the address
+ is contained somewhere in the dynamic info section. We have to go
+ to a lot more work to discover the address of the debug base symbol.
+ Because of this complexity, we cache the value we find and return that
+ value on subsequent invocations. Note there is no copy in the
+ executable symbol tables.
+
+ */
+
+static CORE_ADDR
+locate_base ()
+{
+
+#ifndef SVR4_SHARED_LIBS
+
+ struct minimal_symbol *msymbol;
+ CORE_ADDR address = 0;
+ char **symbolp;
+
+ /* For SunOS, we want to limit the search for the debug base symbol to the
+ executable being debugged, since there is a duplicate named symbol in the
+ shared library. We don't want the shared library versions. */
+
+ for (symbolp = debug_base_symbols; *symbolp != NULL; symbolp++)
+ {
+ msymbol = lookup_minimal_symbol (*symbolp, NULL, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ address = SYMBOL_VALUE_ADDRESS (msymbol);
+ return (address);
+ }
+ }
+ return (0);
+
+#else /* SVR4_SHARED_LIBS */
+
+ /* Check to see if we have a currently valid address, and if so, avoid
+ doing all this work again and just return the cached address. If
+ we have no cached address, try to locate it in the dynamic info
+ section for ELF executables. */
+
+ if (debug_base == 0)
+ {
+ if (exec_bfd != NULL
+ && bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
+ debug_base = elf_locate_base ();
+#ifdef HANDLE_SVR4_EXEC_EMULATORS
+ /* Try it the hard way for emulated executables. */
+ else if (inferior_pid != 0)
+ proc_iterate_over_mappings (look_for_base);
+#endif
+ }
+ return (debug_base);
+
+#endif /* !SVR4_SHARED_LIBS */
+
+}
+
+/*
+
+LOCAL FUNCTION
+
+ first_link_map_member -- locate first member in dynamic linker's map
+
+SYNOPSIS
+
+ static struct link_map *first_link_map_member (void)
+
+DESCRIPTION
+
+ Read in a copy of the first member in the inferior's dynamic
+ link map from the inferior's dynamic linker structures, and return
+ a pointer to the copy in our address space.
+*/
+
+static struct link_map *
+first_link_map_member ()
+{
+ struct link_map *lm = NULL;
+
+#ifndef SVR4_SHARED_LIBS
+
+ read_memory (debug_base, (char *) &dynamic_copy, sizeof (dynamic_copy));
+ if (dynamic_copy.ld_version >= 2)
+ {
+ /* It is a version that we can deal with, so read in the secondary
+ structure and find the address of the link map list from it. */
+ read_memory ((CORE_ADDR) dynamic_copy.ld_un.ld_2, (char *) &ld_2_copy,
+ sizeof (struct link_dynamic_2));
+ lm = ld_2_copy.ld_loaded;
+ }
+
+#else /* SVR4_SHARED_LIBS */
+
+ read_memory (debug_base, (char *) &debug_copy, sizeof (struct r_debug));
+ /* FIXME: Perhaps we should validate the info somehow, perhaps by
+ checking r_version for a known version number, or r_state for
+ RT_CONSISTENT. */
+ lm = debug_copy.r_map;
+
+#endif /* !SVR4_SHARED_LIBS */
+
+ return (lm);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ find_solib -- step through list of shared objects
+
+SYNOPSIS
+
+ struct so_list *find_solib (struct so_list *so_list_ptr)
+
+DESCRIPTION
+
+ This module contains the routine which finds the names of any
+ loaded "images" in the current process. The argument in must be
+ NULL on the first call, and then the returned value must be passed
+ in on subsequent calls. This provides the capability to "step" down
+ the list of loaded objects. On the last object, a NULL value is
+ returned.
+
+ The arg and return value are "struct link_map" pointers, as defined
+ in <link.h>.
+ */
+
+static struct so_list *
+find_solib (so_list_ptr)
+ struct so_list *so_list_ptr; /* Last lm or NULL for first one */
+{
+ struct so_list *so_list_next = NULL;
+ struct link_map *lm = NULL;
+ struct so_list *new;
+
+ if (so_list_ptr == NULL)
+ {
+ /* We are setting up for a new scan through the loaded images. */
+ if ((so_list_next = so_list_head) == NULL)
+ {
+ /* We have not already read in the dynamic linking structures
+ from the inferior, lookup the address of the base structure. */
+ debug_base = locate_base ();
+ if (debug_base != 0)
+ {
+ /* Read the base structure in and find the address of the first
+ link map list member. */
+ lm = first_link_map_member ();
+ }
+ }
+ }
+ else
+ {
+ /* We have been called before, and are in the process of walking
+ the shared library list. Advance to the next shared object. */
+ if ((lm = LM_NEXT (so_list_ptr)) == NULL)
+ {
+ /* We have hit the end of the list, so check to see if any were
+ added, but be quiet if we can't read from the target any more. */
+ int status = target_read_memory ((CORE_ADDR) so_list_ptr -> lmaddr,
+ (char *) &(so_list_ptr -> lm),
+ sizeof (struct link_map));
+ if (status == 0)
+ {
+ lm = LM_NEXT (so_list_ptr);
+ }
+ else
+ {
+ lm = NULL;
+ }
+ }
+ so_list_next = so_list_ptr -> next;
+ }
+ if ((so_list_next == NULL) && (lm != NULL))
+ {
+ /* Get next link map structure from inferior image and build a local
+ abbreviated load_map structure */
+ new = (struct so_list *) xmalloc (sizeof (struct so_list));
+ memset ((char *) new, 0, sizeof (struct so_list));
+ new -> lmaddr = lm;
+ /* Add the new node as the next node in the list, or as the root
+ node if this is the first one. */
+ if (so_list_ptr != NULL)
+ {
+ so_list_ptr -> next = new;
+ }
+ else
+ {
+ so_list_head = new;
+ }
+ so_list_next = new;
+ read_memory ((CORE_ADDR) lm, (char *) &(new -> lm),
+ sizeof (struct link_map));
+ /* For SVR4 versions, the first entry in the link map is for the
+ inferior executable, so we must ignore it. For some versions of
+ SVR4, it has no name. For others (Solaris 2.3 for example), it
+ does have a name, so we can no longer use a missing name to
+ decide when to ignore it. */
+ if (!IGNORE_FIRST_LINK_MAP_ENTRY (new -> lm))
+ {
+ int errcode;
+ char *buffer;
+ target_read_string ((CORE_ADDR) LM_NAME (new), &buffer,
+ MAX_PATH_SIZE - 1, &errcode);
+ if (errcode != 0)
+ error ("find_solib: Can't read pathname for load map: %s\n",
+ safe_strerror (errcode));
+ strncpy (new -> so_name, buffer, MAX_PATH_SIZE - 1);
+ new -> so_name[MAX_PATH_SIZE - 1] = '\0';
+ free (buffer);
+ solib_map_sections (new);
+ }
+ }
+ return (so_list_next);
+}
+
+/* A small stub to get us past the arg-passing pinhole of catch_errors. */
+
+static int
+symbol_add_stub (arg)
+ char *arg;
+{
+ register struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
+
+ so -> objfile =
+ symbol_file_add (so -> so_name, so -> from_tty,
+ (so->textsection == NULL
+ ? 0
+ : (unsigned int) so -> textsection -> addr),
+ 0, 0, 0);
+ return (1);
+}
+
+/* This function will check the so name to see if matches the main list.
+ In some system the main object is in the list, which we want to exclude */
+
+static int match_main (soname)
+ char *soname;
+{
+ char **mainp;
+
+ for (mainp = main_name_list; *mainp != NULL; mainp++)
+ {
+ if (strcmp (soname, *mainp) == 0)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_add -- add a shared library file to the symtab and section list
+
+SYNOPSIS
+
+ void solib_add (char *arg_string, int from_tty,
+ struct target_ops *target)
+
+DESCRIPTION
+
+*/
+
+void
+solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+
+ /* Last shared library that we read. */
+ struct so_list *so_last = NULL;
+
+ char *re_err;
+ int count;
+ int old;
+
+ if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+ {
+ error ("Invalid regexp: %s", re_err);
+ }
+
+ /* Add the shared library sections to the section table of the
+ specified target, if any. */
+ if (target)
+ {
+ /* Count how many new section_table entries there are. */
+ so = NULL;
+ count = 0;
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0] && !match_main (so -> so_name))
+ {
+ count += so -> sections_end - so -> sections;
+ }
+ }
+
+ if (count)
+ {
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ /* Reallocate the target's section table including the new size. */
+ if (target -> to_sections)
+ {
+ old = target -> to_sections_end - target -> to_sections;
+ target -> to_sections = (struct section_table *)
+ xrealloc ((char *)target -> to_sections,
+ (sizeof (struct section_table)) * (count + old));
+ }
+ else
+ {
+ old = 0;
+ target -> to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table)) * count);
+ }
+ target -> to_sections_end = target -> to_sections + (count + old);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* Add these section table entries to the target's table. */
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ count = so -> sections_end - so -> sections;
+ memcpy ((char *) (target -> to_sections + old),
+ so -> sections,
+ (sizeof (struct section_table)) * count);
+ old += count;
+ }
+ }
+ }
+ }
+
+ /* Now add the symbol files. */
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0] && re_exec (so -> so_name) &&
+ !match_main (so -> so_name))
+ {
+ so -> from_tty = from_tty;
+ if (so -> symbols_loaded)
+ {
+ if (from_tty)
+ {
+ printf_unfiltered ("Symbols already loaded for %s\n", so -> so_name);
+ }
+ }
+ else if (catch_errors
+ (symbol_add_stub, (char *) so,
+ "Error while reading shared library symbols:\n",
+ RETURN_MASK_ALL))
+ {
+ so_last = so;
+ so -> symbols_loaded = 1;
+ }
+ }
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ if (so_last)
+ reinit_frame_cache ();
+
+ if (so_last)
+ special_symbol_handling (so_last);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ info_sharedlibrary_command -- code for "info sharedlibrary"
+
+SYNOPSIS
+
+ static void info_sharedlibrary_command ()
+
+DESCRIPTION
+
+ Walk through the shared library list and print information
+ about each attached library.
+*/
+
+static void
+info_sharedlibrary_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct so_list *so = NULL; /* link map state variable */
+ int header_done = 0;
+
+ if (exec_bfd == NULL)
+ {
+ printf_unfiltered ("No exec file.\n");
+ return;
+ }
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ if (!header_done)
+ {
+ printf_unfiltered("%-12s%-12s%-12s%s\n", "From", "To", "Syms Read",
+ "Shared Object Library");
+ header_done++;
+ }
+ /* FIXME-32x64: need print_address_numeric with field width or
+ some such. */
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom ((unsigned long) LM_ADDR (so),
+ "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom ((unsigned long) so -> lmend,
+ "08l"));
+ printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No");
+ printf_unfiltered ("%s\n", so -> so_name);
+ }
+ }
+ if (so_list_head == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ }
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_address -- check to see if an address is in a shared lib
+
+SYNOPSIS
+
+ char * solib_address (CORE_ADDR address)
+
+DESCRIPTION
+
+ Provides a hook for other gdb routines to discover whether or
+ not a particular address is within the mapped address space of
+ a shared library. Any address between the base mapping address
+ and the first address beyond the end of the last mapping, is
+ considered to be within the shared library address space, for
+ our purposes.
+
+ For example, this routine is called at one point to disable
+ breakpoints which are in shared libraries that are not currently
+ mapped in.
+ */
+
+char *
+solib_address (address)
+ CORE_ADDR address;
+{
+ register struct so_list *so = 0; /* link map state variable */
+
+ while ((so = find_solib (so)) != NULL)
+ {
+ if (so -> so_name[0])
+ {
+ if ((address >= (CORE_ADDR) LM_ADDR (so)) &&
+ (address < (CORE_ADDR) so -> lmend))
+ return (so->so_name);
+ }
+ }
+ return (0);
+}
+
+/* Called by free_all_symtabs */
+
+void
+clear_solib()
+{
+ struct so_list *next;
+ char *bfd_filename;
+
+ while (so_list_head)
+ {
+ if (so_list_head -> sections)
+ {
+ free ((PTR)so_list_head -> sections);
+ }
+ if (so_list_head -> abfd)
+ {
+ bfd_filename = bfd_get_filename (so_list_head -> abfd);
+ if (!bfd_close (so_list_head -> abfd))
+ warning ("cannot close \"%s\": %s",
+ bfd_filename, bfd_errmsg (bfd_get_error ()));
+ }
+ else
+ /* This happens for the executable on SVR4. */
+ bfd_filename = NULL;
+
+ next = so_list_head -> next;
+ if (bfd_filename)
+ free ((PTR)bfd_filename);
+ free ((PTR)so_list_head);
+ so_list_head = next;
+ }
+ debug_base = 0;
+}
+
+/*
+
+LOCAL FUNCTION
+
+ disable_break -- remove the "mapping changed" breakpoint
+
+SYNOPSIS
+
+ static int disable_break ()
+
+DESCRIPTION
+
+ Removes the breakpoint that gets hit when the dynamic linker
+ completes a mapping change.
+
+*/
+
+#ifndef SVR4_SHARED_LIBS
+
+static int
+disable_break ()
+{
+ int status = 1;
+
+#ifndef SVR4_SHARED_LIBS
+
+ int in_debugger = 0;
+
+ /* Read the debugger structure from the inferior to retrieve the
+ address of the breakpoint and the original contents of the
+ breakpoint address. Remove the breakpoint by writing the original
+ contents back. */
+
+ read_memory (debug_addr, (char *) &debug_copy, sizeof (debug_copy));
+
+ /* Set `in_debugger' to zero now. */
+
+ write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
+
+ breakpoint_addr = (CORE_ADDR) debug_copy.ldd_bp_addr;
+ write_memory (breakpoint_addr, (char *) &debug_copy.ldd_bp_inst,
+ sizeof (debug_copy.ldd_bp_inst));
+
+#else /* SVR4_SHARED_LIBS */
+
+ /* Note that breakpoint address and original contents are in our address
+ space, so we just need to write the original contents back. */
+
+ if (memory_remove_breakpoint (breakpoint_addr, shadow_contents) != 0)
+ {
+ status = 0;
+ }
+
+#endif /* !SVR4_SHARED_LIBS */
+
+ /* For the SVR4 version, we always know the breakpoint address. For the
+ SunOS version we don't know it until the above code is executed.
+ Grumble if we are stopped anywhere besides the breakpoint address. */
+
+ if (stop_pc != breakpoint_addr)
+ {
+ warning ("stopped at unknown breakpoint while handling shared libraries");
+ }
+
+ return (status);
+}
+
+#endif /* #ifdef SVR4_SHARED_LIBS */
+
+/*
+
+LOCAL FUNCTION
+
+ enable_break -- arrange for dynamic linker to hit breakpoint
+
+SYNOPSIS
+
+ int enable_break (void)
+
+DESCRIPTION
+
+ Both the SunOS and the SVR4 dynamic linkers have, as part of their
+ debugger interface, support for arranging for the inferior to hit
+ a breakpoint after mapping in the shared libraries. This function
+ enables that breakpoint.
+
+ For SunOS, there is a special flag location (in_debugger) which we
+ set to 1. When the dynamic linker sees this flag set, it will set
+ a breakpoint at a location known only to itself, after saving the
+ original contents of that place and the breakpoint address itself,
+ in it's own internal structures. When we resume the inferior, it
+ will eventually take a SIGTRAP when it runs into the breakpoint.
+ We handle this (in a different place) by restoring the contents of
+ the breakpointed location (which is only known after it stops),
+ chasing around to locate the shared libraries that have been
+ loaded, then resuming.
+
+ For SVR4, the debugger interface structure contains a member (r_brk)
+ which is statically initialized at the time the shared library is
+ built, to the offset of a function (_r_debug_state) which is guaran-
+ teed to be called once before mapping in a library, and again when
+ the mapping is complete. At the time we are examining this member,
+ it contains only the unrelocated offset of the function, so we have
+ to do our own relocation. Later, when the dynamic linker actually
+ runs, it relocates r_brk to be the actual address of _r_debug_state().
+
+ The debugger interface structure also contains an enumeration which
+ is set to either RT_ADD or RT_DELETE prior to changing the mapping,
+ depending upon whether or not the library is being mapped or unmapped,
+ and then set to RT_CONSISTENT after the library is mapped/unmapped.
+*/
+
+static int
+enable_break ()
+{
+ int success = 0;
+
+#ifndef SVR4_SHARED_LIBS
+
+ int j;
+ int in_debugger;
+
+ /* Get link_dynamic structure */
+
+ j = target_read_memory (debug_base, (char *) &dynamic_copy,
+ sizeof (dynamic_copy));
+ if (j)
+ {
+ /* unreadable */
+ return (0);
+ }
+
+ /* Calc address of debugger interface structure */
+
+ debug_addr = (CORE_ADDR) dynamic_copy.ldd;
+
+ /* Calc address of `in_debugger' member of debugger interface structure */
+
+ flag_addr = debug_addr + (CORE_ADDR) ((char *) &debug_copy.ldd_in_debugger -
+ (char *) &debug_copy);
+
+ /* Write a value of 1 to this member. */
+
+ in_debugger = 1;
+ write_memory (flag_addr, (char *) &in_debugger, sizeof (in_debugger));
+ success = 1;
+
+#else /* SVR4_SHARED_LIBS */
+
+#ifdef BKPT_AT_SYMBOL
+
+ struct minimal_symbol *msymbol;
+ char **bkpt_namep;
+ asection *interp_sect;
+
+ /* First, remove all the solib event breakpoints. Their addresses
+ may have changed since the last time we ran the program. */
+ remove_solib_event_breakpoints ();
+
+#ifdef SVR4_SHARED_LIBS
+ /* Find the .interp section; if not found, warn the user and drop
+ into the old breakpoint at symbol code. */
+ interp_sect = bfd_get_section_by_name (exec_bfd, ".interp");
+ if (interp_sect)
+ {
+ unsigned int interp_sect_size;
+ char *buf;
+ CORE_ADDR load_addr;
+ bfd *tmp_bfd;
+ CORE_ADDR sym_addr = 0;
+
+ /* Read the contents of the .interp section into a local buffer;
+ the contents specify the dynamic linker this program uses. */
+ interp_sect_size = bfd_section_size (exec_bfd, interp_sect);
+ buf = alloca (interp_sect_size);
+ bfd_get_section_contents (exec_bfd, interp_sect,
+ buf, 0, interp_sect_size);
+
+ /* Now we need to figure out where the dynamic linker was
+ loaded so that we can load its symbols and place a breakpoint
+ in the dynamic linker itself.
+
+ This address is stored on the stack. However, I've been unable
+ to find any magic formula to find it for Solaris (appears to
+ be trivial on Linux). Therefore, we have to try an alternate
+ mechanism to find the dynamic linker's base address. */
+ tmp_bfd = bfd_openr (buf, gnutarget);
+ if (tmp_bfd == NULL)
+ goto bkpt_at_symbol;
+
+ /* Make sure the dynamic linker's really a useful object. */
+ if (!bfd_check_format (tmp_bfd, bfd_object))
+ {
+ warning ("Unable to grok dynamic linker %s as an object file", buf);
+ bfd_close (tmp_bfd);
+ goto bkpt_at_symbol;
+ }
+
+ /* We find the dynamic linker's base address by examining the
+ current pc (which point at the entry point for the dynamic
+ linker) and subtracting the offset of the entry point. */
+ load_addr = read_pc () - tmp_bfd->start_address;
+
+ /* Now try to set a breakpoint in the dynamic linker. */
+ for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
+ {
+ sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep);
+ if (sym_addr != 0)
+ break;
+ }
+
+ /* We're done with the temporary bfd. */
+ bfd_close (tmp_bfd);
+
+ if (sym_addr != 0)
+ {
+ create_solib_event_breakpoint (load_addr + sym_addr);
+ return 1;
+ }
+
+ /* For whatever reason we couldn't set a breakpoint in the dynamic
+ linker. Warn and drop into the old code. */
+bkpt_at_symbol:
+ warning ("Unable to find dynamic linker breakpoint function.");
+ warning ("GDB will be unable to debug shared library initializers");
+ warning ("and track explicitly loaded dynamic code.");
+ }
+#endif
+
+ /* Scan through the list of symbols, trying to look up the symbol and
+ set a breakpoint there. Terminate loop when we/if we succeed. */
+
+ breakpoint_addr = 0;
+ for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
+ {
+ msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
+ if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ {
+ create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+ return 1;
+ }
+ }
+
+ /* Nothing good happened. */
+ return 0;
+
+#endif /* BKPT_AT_SYMBOL */
+
+#endif /* !SVR4_SHARED_LIBS */
+
+ return (success);
+}
+
+/*
+
+GLOBAL FUNCTION
+
+ solib_create_inferior_hook -- shared library startup support
+
+SYNOPSIS
+
+ void solib_create_inferior_hook()
+
+DESCRIPTION
+
+ When gdb starts up the inferior, it nurses it along (through the
+ shell) until it is ready to execute it's first instruction. At this
+ point, this function gets called via expansion of the macro
+ SOLIB_CREATE_INFERIOR_HOOK.
+
+ For SunOS executables, this first instruction is typically the
+ one at "_start", or a similar text label, regardless of whether
+ the executable is statically or dynamically linked. The runtime
+ startup code takes care of dynamically linking in any shared
+ libraries, once gdb allows the inferior to continue.
+
+ For SVR4 executables, this first instruction is either the first
+ instruction in the dynamic linker (for dynamically linked
+ executables) or the instruction at "start" for statically linked
+ executables. For dynamically linked executables, the system
+ first exec's /lib/libc.so.N, which contains the dynamic linker,
+ and starts it running. The dynamic linker maps in any needed
+ shared libraries, maps in the actual user executable, and then
+ jumps to "start" in the user executable.
+
+ For both SunOS shared libraries, and SVR4 shared libraries, we
+ can arrange to cooperate with the dynamic linker to discover the
+ names of shared libraries that are dynamically linked, and the
+ base addresses to which they are linked.
+
+ This function is responsible for discovering those names and
+ addresses, and saving sufficient information about them to allow
+ their symbols to be read at a later time.
+
+FIXME
+
+ Between enable_break() and disable_break(), this code does not
+ properly handle hitting breakpoints which the user might have
+ set in the startup code or in the dynamic linker itself. Proper
+ handling will probably have to wait until the implementation is
+ changed to use the "breakpoint handler function" method.
+
+ Also, what if child has exit()ed? Must exit loop somehow.
+ */
+
+void
+solib_create_inferior_hook()
+{
+ /* If we are using the BKPT_AT_SYMBOL code, then we don't need the base
+ yet. In fact, in the case of a SunOS4 executable being run on
+ Solaris, we can't get it yet. find_solib will get it when it needs
+ it. */
+#if !(defined (SVR4_SHARED_LIBS) && defined (BKPT_AT_SYMBOL))
+ if ((debug_base = locate_base ()) == 0)
+ {
+ /* Can't find the symbol or the executable is statically linked. */
+ return;
+ }
+#endif
+
+ if (!enable_break ())
+ {
+ warning ("shared library handler failed to enable breakpoint");
+ return;
+ }
+
+#ifndef SVR4_SHARED_LIBS
+ /* Only SunOS needs the loop below, other systems should be using the
+ special shared library breakpoints and the shared library breakpoint
+ service routine.
+
+ Now run the target. It will eventually hit the breakpoint, at
+ which point all of the libraries will have been mapped in and we
+ can go groveling around in the dynamic linker structures to find
+ out what we need to know about them. */
+
+ clear_proceed_status ();
+ stop_soon_quietly = 1;
+ stop_signal = TARGET_SIGNAL_0;
+ do
+ {
+ target_resume (-1, 0, stop_signal);
+ wait_for_inferior ();
+ }
+ while (stop_signal != TARGET_SIGNAL_TRAP);
+ stop_soon_quietly = 0;
+
+ /* We are now either at the "mapping complete" breakpoint (or somewhere
+ else, a condition we aren't prepared to deal with anyway), so adjust
+ the PC as necessary after a breakpoint, disable the breakpoint, and
+ add any shared libraries that were mapped in. */
+
+ if (DECR_PC_AFTER_BREAK)
+ {
+ stop_pc -= DECR_PC_AFTER_BREAK;
+ write_register (PC_REGNUM, stop_pc);
+ }
+
+ if (!disable_break ())
+ {
+ warning ("shared library handler failed to disable breakpoint");
+ }
+
+ if (auto_solib_add)
+ solib_add ((char *) 0, 0, (struct target_ops *) 0);
+#endif
+}
+
+/*
+
+LOCAL FUNCTION
+
+ special_symbol_handling -- additional shared library symbol handling
+
+SYNOPSIS
+
+ void special_symbol_handling (struct so_list *so)
+
+DESCRIPTION
+
+ Once the symbols from a shared object have been loaded in the usual
+ way, we are called to do any system specific symbol handling that
+ is needed.
+
+ For SunOS4, this consists of grunging around in the dynamic
+ linkers structures to find symbol definitions for "common" symbols
+ and adding them to the minimal symbol table for the runtime common
+ objfile.
+
+*/
+
+static void
+special_symbol_handling (so)
+struct so_list *so;
+{
+#ifndef SVR4_SHARED_LIBS
+ int j;
+
+ if (debug_addr == 0)
+ {
+ /* Get link_dynamic structure */
+
+ j = target_read_memory (debug_base, (char *) &dynamic_copy,
+ sizeof (dynamic_copy));
+ if (j)
+ {
+ /* unreadable */
+ return;
+ }
+
+ /* Calc address of debugger interface structure */
+ /* FIXME, this needs work for cross-debugging of core files
+ (byteorder, size, alignment, etc). */
+
+ debug_addr = (CORE_ADDR) dynamic_copy.ldd;
+ }
+
+ /* Read the debugger structure from the inferior, just to make sure
+ we have a current copy. */
+
+ j = target_read_memory (debug_addr, (char *) &debug_copy,
+ sizeof (debug_copy));
+ if (j)
+ return; /* unreadable */
+
+ /* Get common symbol definitions for the loaded object. */
+
+ if (debug_copy.ldd_cp)
+ {
+ solib_add_common_symbols (debug_copy.ldd_cp);
+ }
+
+#endif /* !SVR4_SHARED_LIBS */
+}
+
+
+/*
+
+LOCAL FUNCTION
+
+ sharedlibrary_command -- handle command to explicitly add library
+
+SYNOPSIS
+
+ static void sharedlibrary_command (char *args, int from_tty)
+
+DESCRIPTION
+
+*/
+
+static void
+sharedlibrary_command (args, from_tty)
+char *args;
+int from_tty;
+{
+ dont_repeat ();
+ solib_add (args, from_tty, (struct target_ops *) 0);
+}
+
+#endif /* HAVE_LINK_H */
+
+void
+_initialize_solib()
+{
+#ifdef HAVE_LINK_H
+
+ add_com ("sharedlibrary", class_files, sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", info_sharedlibrary_command,
+ "Status of loaded shared object libraries.");
+
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading of shared library symbols.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded. Otherwise, symbols\n\
+must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+
+#endif /* HAVE_LINK_H */
+}
diff --git a/contrib/gdb/gdb/solib.h b/contrib/gdb/gdb/solib.h
new file mode 100644
index 0000000..959e59e
--- /dev/null
+++ b/contrib/gdb/gdb/solib.h
@@ -0,0 +1,60 @@
+/* Shared library declarations for GDB, the GNU Debugger.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct target_ops;
+#endif
+
+/* Called when we free all symtabs, to free the shared library information
+ as well. */
+
+#define CLEAR_SOLIB clear_solib
+
+extern void
+clear_solib PARAMS ((void));
+
+/* Called to add symbols from a shared library to gdb's symbol table. */
+
+#define SOLIB_ADD(filename, from_tty, targ) \
+ solib_add (filename, from_tty, targ)
+
+extern void
+solib_add PARAMS ((char *, int, struct target_ops *));
+
+/* Function to be called when the inferior starts up, to discover the names
+ of shared libraries that are dynamically linked, the base addresses to
+ which they are linked, and sufficient information to read in their symbols
+ at a later time. */
+
+#define SOLIB_CREATE_INFERIOR_HOOK(PID) solib_create_inferior_hook()
+
+extern void
+solib_create_inferior_hook PARAMS((void)); /* solib.c */
+
+/* If we can't set a breakpoint, and it's in a shared library, just
+ disable it. */
+
+#define DISABLE_UNSETTABLE_BREAK(addr) (solib_address(addr) != NULL)
+
+extern char *
+solib_address PARAMS ((CORE_ADDR)); /* solib.c */
+
+/* If ADDR lies in a shared library, return its name. */
+
+#define PC_SOLIB(addr) solib_address (addr)
diff --git a/contrib/gdb/gdb/somread.c b/contrib/gdb/gdb/somread.c
new file mode 100644
index 0000000..ab8d531
--- /dev/null
+++ b/contrib/gdb/gdb/somread.c
@@ -0,0 +1,470 @@
+/* Read HP PA/Risc object files for GDB.
+ Copyright 1991, 1992, 1996 Free Software Foundation, Inc.
+ Written by Fred Fish at Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "bfd.h"
+#include "som.h"
+#include "libhppa.h"
+#include <syms.h>
+#include "symtab.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "gdb-stabs.h"
+#include "complaints.h"
+#include "gdb_string.h"
+#include "demangle.h"
+#include <sys/file.h>
+
+/* Various things we might complain about... */
+
+static void
+som_symfile_init PARAMS ((struct objfile *));
+
+static void
+som_new_init PARAMS ((struct objfile *));
+
+static void
+som_symfile_read PARAMS ((struct objfile *, struct section_offsets *, int));
+
+static void
+som_symfile_finish PARAMS ((struct objfile *));
+
+static void
+som_symtab_read PARAMS ((bfd *, struct objfile *,
+ struct section_offsets *));
+
+static struct section_offsets *
+som_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static void
+record_minimal_symbol PARAMS ((char *, CORE_ADDR,
+ enum minimal_symbol_type,
+ struct objfile *));
+
+static void
+record_minimal_symbol (name, address, ms_type, objfile)
+ char *name;
+ CORE_ADDR address;
+ enum minimal_symbol_type ms_type;
+ struct objfile *objfile;
+{
+ name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
+ prim_record_minimal_symbol (name, address, ms_type, objfile);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ som_symtab_read -- read the symbol table of a SOM file
+
+SYNOPSIS
+
+ void som_symtab_read (bfd *abfd, struct objfile *objfile,
+ struct section_offsets *section_offsets)
+
+DESCRIPTION
+
+ Given an open bfd, a base address to relocate symbols to, and a
+ flag that specifies whether or not this bfd is for an executable
+ or not (may be shared library for example), add all the global
+ function and data symbols to the minimal symbol table.
+*/
+
+static void
+som_symtab_read (abfd, objfile, section_offsets)
+ bfd *abfd;
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+{
+ unsigned int number_of_symbols;
+ int val, dynamic;
+ char *stringtab;
+ asection *shlib_info;
+ struct symbol_dictionary_record *buf, *bufp, *endbufp;
+ char *symname;
+ CONST int symsize = sizeof (struct symbol_dictionary_record);
+ CORE_ADDR text_offset, data_offset;
+
+
+ text_offset = ANOFFSET (section_offsets, 0);
+ data_offset = ANOFFSET (section_offsets, 1);
+
+ number_of_symbols = bfd_get_symcount (abfd);
+
+ buf = alloca (symsize * number_of_symbols);
+ bfd_seek (abfd, obj_som_sym_filepos (abfd), SEEK_SET);
+ val = bfd_read (buf, symsize * number_of_symbols, 1, abfd);
+ if (val != symsize * number_of_symbols)
+ error ("Couldn't read symbol dictionary!");
+
+ stringtab = alloca (obj_som_stringtab_size (abfd));
+ bfd_seek (abfd, obj_som_str_filepos (abfd), SEEK_SET);
+ val = bfd_read (stringtab, obj_som_stringtab_size (abfd), 1, abfd);
+ if (val != obj_som_stringtab_size (abfd))
+ error ("Can't read in HP string table.");
+
+ /* We need to determine if objfile is a dynamic executable (so we
+ can do the right thing for ST_ENTRY vs ST_CODE symbols).
+
+ There's nothing in the header which easily allows us to do
+ this. The only reliable way I know of is to check for the
+ existance of a $SHLIB_INFO$ section with a non-zero size. */
+ shlib_info = bfd_get_section_by_name (objfile->obfd, "$SHLIB_INFO$");
+ if (shlib_info)
+ dynamic = (bfd_section_size (objfile->obfd, shlib_info) != 0);
+ else
+ dynamic = 0;
+
+ endbufp = buf + number_of_symbols;
+ for (bufp = buf; bufp < endbufp; ++bufp)
+ {
+ enum minimal_symbol_type ms_type;
+
+ QUIT;
+
+ switch (bufp->symbol_scope)
+ {
+ case SS_UNIVERSAL:
+ case SS_EXTERNAL:
+ switch (bufp->symbol_type)
+ {
+ case ST_SYM_EXT:
+ case ST_ARG_EXT:
+ continue;
+
+ case ST_CODE:
+ case ST_PRI_PROG:
+ case ST_SEC_PROG:
+ case ST_MILLICODE:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_ENTRY:
+ symname = bufp->name.n_strx + stringtab;
+ /* For a dynamic executable, ST_ENTRY symbols are
+ the stubs, while the ST_CODE symbol is the real
+ function. */
+ if (dynamic)
+ ms_type = mst_solib_trampoline;
+ else
+ ms_type = mst_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_STUB:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_solib_trampoline;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_DATA:
+ symname = bufp->name.n_strx + stringtab;
+ bufp->symbol_value += data_offset;
+ ms_type = mst_data;
+ break;
+ default:
+ continue;
+ }
+ break;
+
+#if 0
+ /* SS_GLOBAL and SS_LOCAL are two names for the same thing (!). */
+ case SS_GLOBAL:
+#endif
+ case SS_LOCAL:
+ switch (bufp->symbol_type)
+ {
+ case ST_SYM_EXT:
+ case ST_ARG_EXT:
+ continue;
+
+ case ST_CODE:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_file_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+
+ check_strange_names:
+ /* Utah GCC 2.5, FSF GCC 2.6 and later generate correct local
+ label prefixes for stabs, constant data, etc. So we need
+ only filter out L$ symbols which are left in due to
+ limitations in how GAS generates SOM relocations.
+
+ When linking in the HPUX C-library the HP linker has
+ the nasty habit of placing section symbols from the literal
+ subspaces in the middle of the program's text. Filter
+ those out as best we can. Check for first and last character
+ being '$'.
+
+ And finally, the newer HP compilers emit crud like $PIC_foo$N
+ in some circumstance (PIC code I guess). It's also claimed
+ that they emit D$ symbols too. What stupidity. */
+ if ((symname[0] == 'L' && symname[1] == '$')
+ || (symname[0] == '$' && symname[strlen(symname) - 1] == '$')
+ || (symname[0] == 'D' && symname[1] == '$')
+ || (strncmp (symname, "$PIC", 4) == 0))
+ continue;
+ break;
+
+ case ST_PRI_PROG:
+ case ST_SEC_PROG:
+ case ST_MILLICODE:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_file_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_ENTRY:
+ symname = bufp->name.n_strx + stringtab;
+ /* For a dynamic executable, ST_ENTRY symbols are
+ the stubs, while the ST_CODE symbol is the real
+ function. */
+ if (dynamic)
+ ms_type = mst_solib_trampoline;
+ else
+ ms_type = mst_file_text;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+ case ST_STUB:
+ symname = bufp->name.n_strx + stringtab;
+ ms_type = mst_solib_trampoline;
+ bufp->symbol_value += text_offset;
+#ifdef SMASH_TEXT_ADDRESS
+ SMASH_TEXT_ADDRESS (bufp->symbol_value);
+#endif
+ break;
+
+
+ case ST_DATA:
+ symname = bufp->name.n_strx + stringtab;
+ bufp->symbol_value += data_offset;
+ ms_type = mst_file_data;
+ goto check_strange_names;
+
+ default:
+ continue;
+ }
+ break;
+
+ /* This can happen for common symbols when -E is passed to the
+ final link. No idea _why_ that would make the linker force
+ common symbols to have an SS_UNSAT scope, but it does. */
+ case SS_UNSAT:
+ switch (bufp->symbol_type)
+ {
+ case ST_STORAGE:
+ symname = bufp->name.n_strx + stringtab;
+ bufp->symbol_value += data_offset;
+ ms_type = mst_data;
+ break;
+
+ default:
+ continue;
+ }
+ break;
+
+ default:
+ continue;
+ }
+
+ if (bufp->name.n_strx > obj_som_stringtab_size (abfd))
+ error ("Invalid symbol data; bad HP string table offset: %d",
+ bufp->name.n_strx);
+
+ record_minimal_symbol (symname,
+ bufp->symbol_value, ms_type,
+ objfile);
+ }
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to som_symfile_init, which
+ currently does nothing.
+
+ SECTION_OFFSETS is a set of offsets to apply to relocate the symbols
+ in each section. This is ignored, as it isn't needed for SOM.
+
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file).
+
+ This function 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.
+
+ We look for sections with specific names, to tell us what debug
+ format to look for: FIXME!!!
+
+ somstab_build_psymtabs() handles STABS symbols.
+
+ Note that SOM files have a "minimal" symbol table, which is vaguely
+ reminiscent of a COFF symbol table, but has only the minimal information
+ necessary for linking. We process this also, and use the information to
+ build gdb's minimal symbol table. This gives us some minimal debugging
+ capability even for files compiled without -g. */
+
+static void
+som_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 ();
+ back_to = make_cleanup (discard_minimal_symbols, 0);
+
+ /* Process the normal SOM symbol table first. */
+
+ som_symtab_read (abfd, objfile, section_offsets);
+
+ /* Now read information from the stabs debug sections. */
+ stabsect_build_psymtabs (objfile, section_offsets, mainline,
+ "$GDB_SYMBOLS$", "$GDB_STRINGS$", "$TEXT$");
+
+ /* Now read the native debug information. */
+ hpread_build_psymtabs (objfile, section_offsets, mainline);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+ install_minimal_symbols (objfile);
+
+ /* Force hppa-tdep.c to re-read the unwind descriptors. */
+ objfile->obj_private = NULL;
+ do_cleanups (back_to);
+}
+
+/* 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).
+
+ We reinitialize buildsym, since we may be reading stabs from a SOM file. */
+
+static void
+som_new_init (ignore)
+ struct objfile *ignore;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+/* 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. */
+
+static void
+som_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_stab_info != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_stab_info);
+ }
+ hpread_symfile_finish (objfile);
+}
+
+/* SOM specific initialization routine for reading symbols. */
+
+static void
+som_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ /* SOM objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+ hpread_symfile_init (objfile);
+}
+
+/* SOM specific parsing routine for section offsets.
+
+ Plain and simple for now. */
+
+static struct section_offsets *
+som_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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));
+
+ /* First see if we're a shared library. If so, get the section
+ offsets from the library, else get them from addr. */
+ if (!som_solib_section_offsets (objfile, section_offsets))
+ {
+ for (i = 0; i < SECT_OFF_MAX; i++)
+ ANOFFSET (section_offsets, i) = addr;
+ }
+
+ return section_offsets;
+}
+
+/* Register that we are able to handle SOM object file formats. */
+
+static struct sym_fns som_sym_fns =
+{
+ bfd_target_som_flavour,
+ som_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ som_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ som_symfile_read, /* sym_read: read a symbol file into symtab */
+ som_symfile_finish, /* sym_finish: finished with file, cleanup */
+ som_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_somread ()
+{
+ add_symtab_fns (&som_sym_fns);
+}
diff --git a/contrib/gdb/gdb/somsolib.c b/contrib/gdb/gdb/somsolib.c
new file mode 100644
index 0000000..1c32837
--- /dev/null
+++ b/contrib/gdb/gdb/somsolib.c
@@ -0,0 +1,820 @@
+/* Handle HP SOM shared libraries for GDB, the GNU Debugger.
+ Copyright 1993, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Written by the Center for Software Science at the Univerity of Utah
+and by Cygnus Support. */
+
+
+#include "defs.h"
+
+#include "frame.h"
+#include "bfd.h"
+#include "som.h"
+#include "libhppa.h"
+#include "gdbcore.h"
+#include "symtab.h"
+#include "breakpoint.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "inferior.h"
+#include "gdb-stabs.h"
+#include "gdbcmd.h"
+
+/* TODO:
+
+ * Most of this code should work for hp300 shared libraries. Does
+ anyone care enough to weed out any SOM-isms.
+
+ * Support for hpux8 dynamic linker. */
+
+/* The basic structure which describes a dynamically loaded object. This
+ data structure is private to the dynamic linker and isn't found in
+ any HPUX include file. */
+
+struct som_solib_mapped_entry
+{
+ /* The name of the library. */
+ char *name;
+
+ /* Version of this structure (it is expected to change again in hpux10). */
+ unsigned char struct_version;
+
+ /* Binding mode for this library. */
+ unsigned char bind_mode;
+
+ /* Version of this library. */
+ short library_version;
+
+ /* Start of text address, link-time text location, end of text address. */
+ CORE_ADDR text_addr;
+ CORE_ADDR text_link_addr;
+ CORE_ADDR text_end;
+
+ /* Start of data, start of bss and end of data. */
+ CORE_ADDR data_start;
+ CORE_ADDR bss_start;
+ CORE_ADDR data_end;
+
+ /* Value of linkage pointer (%r19). */
+ CORE_ADDR got_value;
+
+ /* Next entry. */
+ struct som_solib_mapped_entry *next;
+
+ /* There are other fields, but I don't have information as to what is
+ contained in them. */
+};
+
+/* A structure to keep track of all the known shared objects. */
+struct so_list
+{
+ struct som_solib_mapped_entry som_solib;
+ struct objfile *objfile;
+ bfd *abfd;
+ struct section_table *sections;
+ struct section_table *sections_end;
+ struct so_list *next;
+};
+
+static struct so_list *so_list_head;
+
+static void som_sharedlibrary_info_command PARAMS ((char *, int));
+
+/* Add symbols from shared libraries into the symtab list. */
+
+void
+som_solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ struct minimal_symbol *msymbol;
+ struct so_list *so_list_tail;
+ CORE_ADDR addr;
+ asection *shlib_info;
+ int status;
+ unsigned int dld_flags;
+ char buf[4], *re_err;
+
+ /* First validate our arguments. */
+ if ((re_err = re_comp (arg_string ? arg_string : ".")) != NULL)
+ {
+ error ("Invalid regexp: %s", re_err);
+ }
+
+ /* If we're debugging a core file, or have attached to a running
+ process, then som_solib_create_inferior_hook will not have been
+ called.
+
+ We need to first determine if we're dealing with a dynamically
+ linked executable. If not, then return without an error or warning.
+
+ We also need to examine __dld_flags to determine if the shared library
+ list is valid and to determine if the libraries have been privately
+ mapped. */
+ if (symfile_objfile == NULL)
+ return;
+
+ /* First see if the objfile was dynamically linked. */
+ shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+ if (!shlib_info)
+ return;
+
+ /* It's got a $SHLIB_INFO$ section, make sure it's not empty. */
+ if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
+ return;
+
+ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+ if (msymbol == NULL)
+ {
+ error ("Unable to find __dld_flags symbol in object file.\n");
+ return;
+ }
+
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ /* Read the current contents. */
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to read __dld_flags\n");
+ return;
+ }
+ dld_flags = extract_unsigned_integer (buf, 4);
+
+ /* __dld_list may not be valid. If it's not valid tell the user. */
+ if ((dld_flags & 4) == 0)
+ {
+ error ("__dld_list is not valid according to __dld_flags.\n");
+ return;
+ }
+
+ /* If the libraries were not mapped private, warn the user. */
+ if ((dld_flags & 1) == 0)
+ warning ("The shared libraries were not privately mapped; setting a\nbreakpoint in a shared library will not work until you rerun the program.\n");
+
+ msymbol = lookup_minimal_symbol ("__dld_list", NULL, NULL);
+ if (!msymbol)
+ {
+ /* Older crt0.o files (hpux8) don't have __dld_list as a symbol,
+ but the data is still available if you know where to look. */
+ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+ if (!msymbol)
+ {
+ error ("Unable to find dynamic library list.\n");
+ return;
+ }
+ addr = SYMBOL_VALUE_ADDRESS (msymbol) - 8;
+ }
+ else
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to find dynamic library list.\n");
+ return;
+ }
+
+ addr = extract_unsigned_integer (buf, 4);
+
+ /* If addr is zero, then we're using an old dynamic loader which
+ doesn't maintain __dld_list. We'll have to use a completely
+ different approach to get shared library information. */
+ if (addr == 0)
+ goto old_dld;
+
+ /* Using the information in __dld_list is the preferred method
+ to get at shared library information. It doesn't depend on
+ any functions in /usr/lib/end.o and has a chance of working
+ with hpux10 when it is released. */
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to find dynamic library list.\n");
+ return;
+ }
+
+ /* addr now holds the address of the first entry in the dynamic
+ library list. */
+ addr = extract_unsigned_integer (buf, 4);
+
+ /* Now that we have a pointer to the dynamic library list, walk
+ through it and add the symbols for each library. */
+
+ so_list_tail = so_list_head;
+ /* Find the end of the list of shared objects. */
+ while (so_list_tail && so_list_tail->next)
+ so_list_tail = so_list_tail->next;
+
+ while (1)
+ {
+ CORE_ADDR name_addr, text_addr;
+ unsigned int name_len;
+ char *name;
+ struct so_list *new_so;
+ struct so_list *so_list = so_list_head;
+ struct section_table *p;
+ struct stat statbuf;
+
+ if (addr == 0)
+ break;
+
+ /* Get a pointer to the name of this library. */
+ status = target_read_memory (addr, buf, 4);
+ if (status != 0)
+ goto err;
+
+ name_addr = extract_unsigned_integer (buf, 4);
+ name_len = 0;
+ while (1)
+ {
+ target_read_memory (name_addr + name_len, buf, 1);
+ if (status != 0)
+ goto err;
+
+ name_len++;
+ if (*buf == '\0')
+ break;
+ }
+ name = alloca (name_len);
+ status = target_read_memory (name_addr, name, name_len);
+ if (status != 0)
+ goto err;
+
+ /* See if we've already loaded something with this name. */
+ while (so_list)
+ {
+ if (!strcmp (so_list->som_solib.name, name))
+ break;
+ so_list = so_list->next;
+ }
+
+ /* See if the file exists. If not, give a warning, but don't
+ die. */
+ status = stat (name, &statbuf);
+ if (status == -1)
+ {
+ warning ("Can't find file %s referenced in dld_list.", name);
+
+ status = target_read_memory (addr + 36, buf, 4);
+ if (status != 0)
+ goto err;
+
+ addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
+ continue;
+ }
+
+ /* If we've already loaded this one or it's the main program, skip it. */
+ if (so_list || !strcmp (name, symfile_objfile->name))
+ {
+ status = target_read_memory (addr + 36, buf, 4);
+ if (status != 0)
+ goto err;
+
+ addr = (CORE_ADDR) extract_unsigned_integer (buf, 4);
+ continue;
+ }
+
+ name = obsavestring (name, name_len - 1,
+ &symfile_objfile->symbol_obstack);
+
+ status = target_read_memory (addr + 8, buf, 4);
+ if (status != 0)
+ goto err;
+
+ text_addr = extract_unsigned_integer (buf, 4);
+
+
+ new_so = (struct so_list *) xmalloc (sizeof (struct so_list));
+ memset ((char *)new_so, 0, sizeof (struct so_list));
+ if (so_list_head == NULL)
+ {
+ so_list_head = new_so;
+ so_list_tail = new_so;
+ }
+ else
+ {
+ so_list_tail->next = new_so;
+ so_list_tail = new_so;
+ }
+
+ /* Fill in all the entries in GDB's shared library list. */
+ new_so->som_solib.name = name;
+ status = target_read_memory (addr + 4, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.struct_version = extract_unsigned_integer (buf + 3, 1);
+ new_so->som_solib.bind_mode = extract_unsigned_integer (buf + 2, 1);
+ new_so->som_solib.library_version = extract_unsigned_integer (buf, 2);
+ new_so->som_solib.text_addr = text_addr;
+
+ status = target_read_memory (addr + 12, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.text_link_addr = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 16, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.text_end = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 20, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.data_start = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 24, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.bss_start = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 28, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.data_end = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 32, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.got_value = extract_unsigned_integer (buf, 4);
+
+ status = target_read_memory (addr + 36, buf, 4);
+ if (status != 0)
+ goto err;
+
+ new_so->som_solib.next = (void *)extract_unsigned_integer (buf, 4);
+ addr = (CORE_ADDR)new_so->som_solib.next;
+
+ new_so->objfile = symbol_file_add (name, from_tty, text_addr, 0, 0, 0);
+ new_so->abfd = new_so->objfile->obfd;
+
+ if (!bfd_check_format (new_so->abfd, bfd_object))
+ {
+ error ("\"%s\": not in executable format: %s.",
+ name, bfd_errmsg (bfd_get_error ()));
+ }
+
+ /* Now we need to build a section table for this library since
+ we might be debugging a core file from a dynamically linked
+ executable in which the libraries were not privately mapped. */
+ if (build_section_table (new_so->abfd,
+ &new_so->sections,
+ &new_so->sections_end))
+ {
+ error ("Unable to build section table for shared library\n.");
+ return;
+ }
+
+ /* Relocate all the sections based on where they got loaded. */
+ for (p = new_so->sections; p < new_so->sections_end; p++)
+ {
+ if (p->the_bfd_section->flags & SEC_CODE)
+ {
+ p->addr += text_addr - new_so->som_solib.text_link_addr;
+ p->endaddr += text_addr - new_so->som_solib.text_link_addr;
+ }
+ else if (p->the_bfd_section->flags & SEC_DATA)
+ {
+ p->addr += new_so->som_solib.data_start;
+ p->endaddr += new_so->som_solib.data_start;
+ }
+ }
+
+ /* Now see if we need to map in the text and data for this shared
+ library (for example debugging a core file which does not use
+ private shared libraries.).
+
+ Carefully peek at the first text address in the library. If the
+ read succeeds, then the libraries were privately mapped and were
+ included in the core dump file.
+
+ If the peek failed, then the libraries were not privately mapped
+ and are not in the core file, we'll have to read them in ourselves. */
+ status = target_read_memory (text_addr, buf, 4);
+ if (status != 0)
+ {
+ int old, new;
+ int update_coreops;
+
+ /* We must update the to_sections field in the core_ops structure
+ here, otherwise we dereference a potential dangling pointer
+ for each call to target_read/write_memory within this routine. */
+ update_coreops = core_ops.to_sections == target->to_sections;
+
+ new = new_so->sections_end - new_so->sections;
+ /* Add sections from the shared library to the core target. */
+ if (target->to_sections)
+ {
+ old = target->to_sections_end - target->to_sections;
+ target->to_sections = (struct section_table *)
+ xrealloc ((char *)target->to_sections,
+ ((sizeof (struct section_table)) * (old + new)));
+ }
+ else
+ {
+ old = 0;
+ target->to_sections = (struct section_table *)
+ xmalloc ((sizeof (struct section_table)) * new);
+ }
+ target->to_sections_end = (target->to_sections + old + new);
+
+ /* Update the to_sections field in the core_ops structure
+ if needed. */
+ if (update_coreops)
+ {
+ core_ops.to_sections = target->to_sections;
+ core_ops.to_sections_end = target->to_sections_end;
+ }
+
+ /* Copy over the old data before it gets clobbered. */
+ memcpy ((char *)(target->to_sections + old),
+ new_so->sections,
+ ((sizeof (struct section_table)) * new));
+ }
+ }
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+ return;
+
+old_dld:
+ error ("Debugging dynamic executables loaded via the hpux8 dld.sl is not supported.\n");
+ return;
+
+err:
+ error ("Error while reading dynamic library list.\n");
+ return;
+}
+
+
+/* This hook gets called just before the first instruction in the
+ inferior process is executed.
+
+ This is our opportunity to set magic flags in the inferior so
+ that GDB can be notified when a shared library is mapped in and
+ to tell the dynamic linker that a private copy of the library is
+ needed (so GDB can set breakpoints in the library).
+
+ __dld_flags is the location of the magic flags; as of this implementation
+ there are 3 flags of interest:
+
+ bit 0 when set indicates that private copies of the libraries are needed
+ bit 1 when set indicates that the callback hook routine is valid
+ bit 2 when set indicates that the dynamic linker should maintain the
+ __dld_list structure when loading/unloading libraries.
+
+ Note that shared libraries are not mapped in at this time, so we have
+ run the inferior until the libraries are mapped in. Typically this
+ means running until the "_start" is called. */
+
+void
+som_solib_create_inferior_hook()
+{
+ struct minimal_symbol *msymbol;
+ unsigned int dld_flags, status, have_endo;
+ asection *shlib_info;
+ char shadow_contents[BREAKPOINT_MAX], buf[4];
+ struct objfile *objfile;
+ CORE_ADDR anaddr;
+
+ /* First, remove all the solib event breakpoints. Their addresses
+ may have changed since the last time we ran the program. */
+ remove_solib_event_breakpoints ();
+
+ if (symfile_objfile == NULL)
+ return;
+
+ /* First see if the objfile was dynamically linked. */
+ shlib_info = bfd_get_section_by_name (symfile_objfile->obfd, "$SHLIB_INFO$");
+ if (!shlib_info)
+ return;
+
+ /* It's got a $SHLIB_INFO$ section, make sure it's not empty. */
+ if (bfd_section_size (symfile_objfile->obfd, shlib_info) == 0)
+ return;
+
+ have_endo = 0;
+ /* Slam the pid of the process into __d_pid; failing is only a warning! */
+ msymbol = lookup_minimal_symbol ("__d_pid", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find __d_pid symbol in object file.");
+ warning ("Suggest linking with /usr/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ store_unsigned_integer (buf, 4, inferior_pid);
+ status = target_write_memory (anaddr, buf, 4);
+ if (status != 0)
+ {
+ warning ("Unable to write __d_pid");
+ warning ("Suggest linking with /usr/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+
+ /* Get the value of _DLD_HOOK (an export stub) and put it in __dld_hook;
+ This will force the dynamic linker to call __d_trap when significant
+ events occur. */
+ msymbol = lookup_minimal_symbol ("_DLD_HOOK", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find _DLD_HOOK symbol in object file.");
+ warning ("Suggest linking with /usr/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ /* Grrr, this might not be an export symbol! We have to find the
+ export stub. */
+ ALL_OBJFILES (objfile)
+ {
+ struct unwind_table_entry *u;
+ extern struct unwind_table_entry *find_unwind_entry PARAMS ((CORE_ADDR pc));
+
+ /* What a crock. */
+ msymbol = lookup_minimal_symbol_solib_trampoline (SYMBOL_NAME (msymbol),
+ NULL, objfile);
+ /* Found a symbol with the right name. */
+ if (msymbol)
+ {
+ struct unwind_table_entry *u;
+ /* It must be a shared library trampoline. */
+ if (SYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+ continue;
+
+ /* It must also be an export stub. */
+ u = find_unwind_entry (SYMBOL_VALUE (msymbol));
+ if (!u || u->stub_type != EXPORT)
+ continue;
+
+ /* OK. Looks like the correct import stub. */
+ anaddr = SYMBOL_VALUE (msymbol);
+ break;
+ }
+ }
+ store_unsigned_integer (buf, 4, anaddr);
+
+ msymbol = lookup_minimal_symbol ("__dld_hook", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find __dld_hook symbol in object file.");
+ warning ("Suggest linking with /usr/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ status = target_write_memory (anaddr, buf, 4);
+
+ /* Now set a shlib_event breakpoint at __d_trap so we can track
+ significant shared library events. */
+ msymbol = lookup_minimal_symbol ("__d_trap", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ warning ("Unable to find __dld_d_trap symbol in object file.");
+ warning ("Suggest linking with /usr/lib/end.o.");
+ warning ("GDB will be unable to track shl_load/shl_unload calls");
+ goto keep_going;
+ }
+ create_solib_event_breakpoint (SYMBOL_VALUE_ADDRESS (msymbol));
+
+ /* We have all the support usually found in end.o, so we can track
+ shl_load and shl_unload calls. */
+ have_endo = 1;
+
+keep_going:
+
+ /* Get the address of __dld_flags, if no such symbol exists, then we can
+ not debug the shared code. */
+ msymbol = lookup_minimal_symbol ("__dld_flags", NULL, NULL);
+ if (msymbol == NULL)
+ {
+ error ("Unable to find __dld_flags symbol in object file.\n");
+ goto keep_going;
+ return;
+ }
+
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+ /* Read the current contents. */
+ status = target_read_memory (anaddr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to read __dld_flags\n");
+ return;
+ }
+ dld_flags = extract_unsigned_integer (buf, 4);
+
+ /* Turn on the flags we care about. */
+ dld_flags |= (0x5 | (have_endo << 1));
+ store_unsigned_integer (buf, 4, dld_flags);
+ status = target_write_memory (anaddr, buf, 4);
+ if (status != 0)
+ {
+ error ("Unable to write __dld_flags\n");
+ return;
+ }
+
+ /* Now find the address of _start and set a breakpoint there.
+ We still need this code for two reasons:
+
+ * Not all sites have /usr/lib/end.o, so it's not always
+ possible to track the dynamic linker's events.
+
+ * At this time no events are triggered for shared libraries
+ loaded at startup time (what a crock). */
+
+ msymbol = lookup_minimal_symbol ("_start", NULL, symfile_objfile);
+ if (msymbol == NULL)
+ {
+ error ("Unable to find _start symbol in object file.\n");
+ return;
+ }
+
+ anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ /* Make the breakpoint at "_start" a shared library event breakpoint. */
+ create_solib_event_breakpoint (anaddr);
+
+ /* Wipe out all knowledge of old shared libraries since their
+ mapping can change from one exec to another! */
+ while (so_list_head)
+ {
+ struct so_list *temp;
+
+ free_objfile (so_list_head->objfile);
+ temp = so_list_head;
+ free (so_list_head);
+ so_list_head = temp->next;
+ }
+ clear_symtab_users ();
+}
+
+/* Return the GOT value for the shared library in which ADDR belongs. If
+ ADDR isn't in any known shared library, return zero. */
+
+CORE_ADDR
+som_solib_get_got_by_pc (addr)
+ CORE_ADDR addr;
+{
+ struct so_list *so_list = so_list_head;
+ CORE_ADDR got_value = 0;
+
+ while (so_list)
+ {
+ if (so_list->som_solib.text_addr <= addr
+ && so_list->som_solib.text_end > addr)
+ {
+ got_value = so_list->som_solib.got_value;
+ break;
+ }
+ so_list = so_list->next;
+ }
+ return got_value;
+}
+
+int
+som_solib_section_offsets (objfile, offsets)
+ struct objfile *objfile;
+ struct section_offsets *offsets;
+{
+ struct so_list *so_list = so_list_head;
+
+ while (so_list)
+ {
+ /* Oh what a pain! We need the offsets before so_list->objfile
+ is valid. The BFDs will never match. Make a best guess. */
+ if (strstr (objfile->name, so_list->som_solib.name))
+ {
+ asection *private_section;
+
+ /* The text offset is easy. */
+ ANOFFSET (offsets, SECT_OFF_TEXT)
+ = (so_list->som_solib.text_addr
+ - so_list->som_solib.text_link_addr);
+ ANOFFSET (offsets, SECT_OFF_RODATA)
+ = ANOFFSET (offsets, SECT_OFF_TEXT);
+
+ /* We should look at presumed_dp in the SOM header, but
+ that's not easily available. This should be OK though. */
+ private_section = bfd_get_section_by_name (objfile->obfd,
+ "$PRIVATE$");
+ if (!private_section)
+ {
+ warning ("Unable to find $PRIVATE$ in shared library!");
+ ANOFFSET (offsets, SECT_OFF_DATA) = 0;
+ ANOFFSET (offsets, SECT_OFF_BSS) = 0;
+ return 1;
+ }
+ ANOFFSET (offsets, SECT_OFF_DATA)
+ = (so_list->som_solib.data_start - private_section->vma);
+ ANOFFSET (offsets, SECT_OFF_BSS)
+ = ANOFFSET (offsets, SECT_OFF_DATA);
+ return 1;
+ }
+ so_list = so_list->next;
+ }
+ return 0;
+}
+
+/* Dump information about all the currently loaded shared libraries. */
+
+static void
+som_sharedlibrary_info_command (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ struct so_list *so_list = so_list_head;
+
+ if (exec_bfd == NULL)
+ {
+ printf_unfiltered ("no exec file.\n");
+ return;
+ }
+
+ if (so_list == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ return;
+ }
+
+ printf_unfiltered ("Shared Object Libraries\n");
+ printf_unfiltered (" %-12s%-12s%-12s%-12s%-12s%-12s\n",
+ " flags", " tstart", " tend", " dstart", " dend", " dlt");
+ while (so_list)
+ {
+ unsigned int flags;
+
+ flags = so_list->som_solib.struct_version << 24;
+ flags |= so_list->som_solib.bind_mode << 16;
+ flags |= so_list->som_solib.library_version;
+ printf_unfiltered ("%s\n", so_list->som_solib.name);
+ printf_unfiltered (" %-12s", local_hex_string_custom (flags, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.text_addr, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.text_end, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.data_start, "08l"));
+ printf_unfiltered ("%-12s",
+ local_hex_string_custom (so_list->som_solib.data_end, "08l"));
+ printf_unfiltered ("%-12s\n",
+ local_hex_string_custom (so_list->som_solib.got_value, "08l"));
+ so_list = so_list->next;
+ }
+}
+
+static void
+som_solib_sharedlibrary_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+ som_solib_add (args, from_tty, (struct target_ops *) 0);
+}
+
+void
+_initialize_som_solib ()
+{
+ add_com ("sharedlibrary", class_files, som_solib_sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", som_sharedlibrary_info_command,
+ "Status of loaded shared object libraries.");
+ add_show_from_set
+ (add_set_cmd ("auto-solib-add", class_support, var_zinteger,
+ (char *) &auto_solib_add,
+ "Set autoloading of shared library symbols at startup.\n\
+If nonzero, symbols from all shared object libraries will be loaded\n\
+automatically when the inferior begins execution or when the dynamic linker\n\
+informs gdb that a new library has been loaded. Otherwise, symbols\n\
+must be loaded manually, using `sharedlibrary'.",
+ &setlist),
+ &showlist);
+
+}
diff --git a/contrib/gdb/gdb/somsolib.h b/contrib/gdb/gdb/somsolib.h
new file mode 100644
index 0000000..6fe0200
--- /dev/null
+++ b/contrib/gdb/gdb/somsolib.h
@@ -0,0 +1,51 @@
+/* HP SOM Shared library declarations for GDB, the GNU Debugger.
+ Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Written by the Center for Software Science at the Univerity of Utah
+and by Cygnus Support. */
+
+#ifdef __STDC__ /* Forward decl's for prototypes */
+struct target_ops;
+struct objfile;
+struct section_offsets;
+#endif
+
+/* Called to add symbols from a shared library to gdb's symbol table. */
+
+#define SOLIB_ADD(filename, from_tty, targ) \
+ som_solib_add (filename, from_tty, targ)
+
+extern void
+som_solib_add PARAMS ((char *, int, struct target_ops *));
+
+extern CORE_ADDR
+som_solib_get_got_by_pc PARAMS ((CORE_ADDR));
+
+extern int
+som_solib_section_offsets PARAMS ((struct objfile *, struct section_offsets *));
+
+/* Function to be called when the inferior starts up, to discover the names
+ of shared libraries that are dynamically linked, the base addresses to
+ which they are linked, and sufficient information to read in their symbols
+ at a later time. */
+
+#define SOLIB_CREATE_INFERIOR_HOOK(PID) som_solib_create_inferior_hook()
+
+extern void
+som_solib_create_inferior_hook PARAMS((void));
diff --git a/contrib/gdb/gdb/source.c b/contrib/gdb/gdb/source.c
new file mode 100644
index 0000000..5e7af03
--- /dev/null
+++ b/contrib/gdb/gdb/source.c
@@ -0,0 +1,1506 @@
+/* List lines of source files for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "expression.h"
+#include "language.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "frame.h"
+#include "value.h"
+
+#include <sys/types.h>
+#include "gdb_string.h"
+#include <sys/param.h>
+#include "gdb_stat.h"
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include "gdbcore.h"
+#include "gnu-regex.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "annotate.h"
+#include "gdbtypes.h"
+
+/* Prototypes for local functions. */
+
+static int open_source_file PARAMS ((struct symtab *));
+
+static int get_filename_and_charpos PARAMS ((struct symtab *, char **));
+
+static void reverse_search_command PARAMS ((char *, int));
+
+static void forward_search_command PARAMS ((char *, int));
+
+static void line_info PARAMS ((char *, int));
+
+static void list_command PARAMS ((char *, int));
+
+static void ambiguous_line_spec PARAMS ((struct symtabs_and_lines *));
+
+static void source_info PARAMS ((char *, int));
+
+static void show_directories PARAMS ((char *, int));
+
+static void find_source_lines PARAMS ((struct symtab *, int));
+
+/* If we use this declaration, it breaks because of fucking ANSI "const" stuff
+ on some systems. We just have to not declare it at all, have it default
+ to int, and possibly botch on a few systems. Thanks, ANSIholes... */
+/* extern char *strstr(); */
+
+/* Path of directories to search for source files.
+ Same format as the PATH environment variable's value. */
+
+char *source_path;
+
+/* Symtab of default file for listing lines of. */
+
+struct symtab *current_source_symtab;
+
+/* Default next line to list. */
+
+int current_source_line;
+
+/* Default number of lines to print with commands like "list".
+ This is based on guessing how many long (i.e. more than chars_per_line
+ characters) lines there will be. To be completely correct, "list"
+ and friends should be rewritten to count characters and see where
+ things are wrapping, but that would be a fair amount of work. */
+
+int lines_to_list = 10;
+
+/* Line number of last line printed. Default for various commands.
+ current_source_line is usually, but not always, the same as this. */
+
+static int last_line_listed;
+
+/* First line number listed by last listing command. */
+
+static int first_line_listed;
+
+
+/* Set the source file default for the "list" command to be S.
+
+ If S is NULL, and we don't have a default, find one. This
+ should only be called when the user actually tries to use the
+ default, since we produce an error if we can't find a reasonable
+ default. Also, since this can cause symbols to be read, doing it
+ before we need to would make things slower than necessary. */
+
+void
+select_source_symtab (s)
+ register struct symtab *s;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ struct partial_symtab *ps;
+ struct partial_symtab *cs_pst = 0;
+ struct objfile *ofp;
+
+ if (s)
+ {
+ current_source_symtab = s;
+ current_source_line = 1;
+ return;
+ }
+
+ if (current_source_symtab)
+ return;
+
+ /* Make the default place to list be the function `main'
+ if one exists. */
+ if (lookup_symbol ("main", 0, VAR_NAMESPACE, 0, NULL))
+ {
+ sals = decode_line_spec ("main", 1);
+ sal = sals.sals[0];
+ free (sals.sals);
+ current_source_symtab = sal.symtab;
+ current_source_line = max (sal.line - (lines_to_list - 1), 1);
+ if (current_source_symtab)
+ return;
+ }
+
+ /* All right; find the last file in the symtab list (ignoring .h's). */
+
+ current_source_line = 1;
+
+ for (ofp = object_files; ofp != NULL; ofp = ofp -> next)
+ {
+ for (s = ofp -> symtabs; s; s = s->next)
+ {
+ char *name = s -> filename;
+ int len = strlen (name);
+ if (! (len > 2 && (STREQ (&name[len - 2], ".h"))))
+ {
+ current_source_symtab = s;
+ }
+ }
+ }
+ if (current_source_symtab)
+ return;
+
+ /* Howabout the partial symbol tables? */
+
+ for (ofp = object_files; ofp != NULL; ofp = ofp -> next)
+ {
+ for (ps = ofp -> psymtabs; ps != NULL; ps = ps -> next)
+ {
+ char *name = ps -> filename;
+ int len = strlen (name);
+ if (! (len > 2 && (STREQ (&name[len - 2], ".h"))))
+ {
+ cs_pst = ps;
+ }
+ }
+ }
+ if (cs_pst)
+ {
+ if (cs_pst -> readin)
+ {
+ fatal ("Internal: select_source_symtab: readin pst found and no symtabs.");
+ }
+ else
+ {
+ current_source_symtab = PSYMTAB_TO_SYMTAB (cs_pst);
+ }
+ }
+
+ error ("Can't find a default source file");
+}
+
+static void
+show_directories (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ puts_filtered ("Source directories searched: ");
+ puts_filtered (source_path);
+ puts_filtered ("\n");
+}
+
+/* Forget what we learned about line positions in source files, and
+ which directories contain them; must check again now since files
+ may be found in a different directory now. */
+
+void
+forget_cached_source_info ()
+{
+ 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)
+ {
+ if (s -> line_charpos != NULL)
+ {
+ mfree (objfile -> md, s -> line_charpos);
+ s -> line_charpos = NULL;
+ }
+ if (s -> fullname != NULL)
+ {
+ mfree (objfile -> md, s -> fullname);
+ s -> fullname = NULL;
+ }
+ }
+ }
+}
+
+void
+init_source_path ()
+{
+ char buf[20];
+
+ sprintf (buf, "$cdir%c$cwd", DIRNAME_SEPARATOR);
+ source_path = strsave (buf);
+ forget_cached_source_info ();
+}
+
+/* Add zero or more directories to the front of the source path. */
+
+void
+directory_command (dirname, from_tty)
+ char *dirname;
+ int from_tty;
+{
+ dont_repeat ();
+ /* FIXME, this goes to "delete dir"... */
+ if (dirname == 0)
+ {
+ if (query ("Reinitialize source path to empty? "))
+ {
+ free (source_path);
+ init_source_path ();
+ }
+ }
+ else
+ mod_path (dirname, &source_path);
+ if (from_tty)
+ show_directories ((char *)0, from_tty);
+ forget_cached_source_info ();
+}
+
+/* Add zero or more directories to the front of an arbitrary path. */
+
+void
+mod_path (dirname, which_path)
+ char *dirname;
+ char **which_path;
+{
+ char *old = *which_path;
+ int prefix = 0;
+
+ if (dirname == 0)
+ return;
+
+ dirname = strsave (dirname);
+ make_cleanup (free, dirname);
+
+ do
+ {
+ char *name = dirname;
+ register char *p;
+ struct stat st;
+
+ {
+ char *separator = strchr (name, DIRNAME_SEPARATOR);
+ char *space = strchr (name, ' ');
+ char *tab = strchr (name, '\t');
+
+ if (separator == 0 && space == 0 && tab == 0)
+ p = dirname = name + strlen (name);
+ else
+ {
+ p = 0;
+ if (separator != 0 && (p == 0 || separator < p))
+ p = separator;
+ if (space != 0 && (p == 0 || space < p))
+ p = space;
+ if (tab != 0 && (p == 0 || tab < p))
+ p = tab;
+ dirname = p + 1;
+ while (*dirname == DIRNAME_SEPARATOR
+ || *dirname == ' '
+ || *dirname == '\t')
+ ++dirname;
+ }
+ }
+
+#ifndef WIN32
+ /* On win32 h:\ is different to h: */
+ if (SLASH_P (p[-1]))
+ /* Sigh. "foo/" => "foo" */
+ --p;
+#endif
+ *p = '\0';
+
+ while (p[-1] == '.')
+ {
+ if (p - name == 1)
+ {
+ /* "." => getwd (). */
+ name = current_directory;
+ goto append;
+ }
+ else if (SLASH_P (p[-2]))
+ {
+ if (p - name == 2)
+ {
+ /* "/." => "/". */
+ *--p = '\0';
+ goto append;
+ }
+ else
+ {
+ /* "...foo/." => "...foo". */
+ p -= 2;
+ *p = '\0';
+ continue;
+ }
+ }
+ else
+ break;
+ }
+
+ if (name[0] == '~')
+ name = tilde_expand (name);
+ else if (!ROOTED_P (name) && name[0] != '$')
+ name = concat (current_directory, SLASH_STRING, name, NULL);
+ else
+ name = savestring (name, p - name);
+ make_cleanup (free, name);
+
+ /* Unless it's a variable, check existence. */
+ if (name[0] != '$') {
+ /* These are warnings, not errors, since we don't want a
+ non-existent directory in a .gdbinit file to stop processing
+ of the .gdbinit file.
+
+ Whether they get added to the path is more debatable. Current
+ answer is yes, in case the user wants to go make the directory
+ or whatever. If the directory continues to not exist/not be
+ a directory/etc, then having them in the path should be
+ harmless. */
+ if (stat (name, &st) < 0)
+ {
+ int save_errno = errno;
+ fprintf_unfiltered (gdb_stderr, "Warning: ");
+ print_sys_errmsg (name, save_errno);
+ }
+ else if ((st.st_mode & S_IFMT) != S_IFDIR)
+ warning ("%s is not a directory.", name);
+ }
+
+ append:
+ {
+ register unsigned int len = strlen (name);
+
+ p = *which_path;
+ while (1)
+ {
+ if (!strncmp (p, name, len)
+ && (p[len] == '\0' || p[len] == DIRNAME_SEPARATOR))
+ {
+ /* Found it in the search path, remove old copy */
+ if (p > *which_path)
+ p--; /* Back over leading separator */
+ if (prefix > p - *which_path)
+ goto skip_dup; /* Same dir twice in one cmd */
+ strcpy (p, &p[len+1]); /* Copy from next \0 or : */
+ }
+ p = strchr (p, DIRNAME_SEPARATOR);
+ if (p != 0)
+ ++p;
+ else
+ break;
+ }
+ 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)
+ {
+ char *temp, c;
+
+ c = old[prefix];
+ old[prefix] = '\0';
+ temp = concat (old, tinybuf, name, NULL);
+ old[prefix] = c;
+ *which_path = concat (temp, "", &old[prefix], NULL);
+ prefix = strlen (temp);
+ free (temp);
+ }
+ else
+ {
+ *which_path = concat (name, (old[0] ? tinybuf : old), old, NULL);
+ prefix = strlen (name);
+ }
+ free (old);
+ old = *which_path;
+ }
+ }
+ skip_dup: ;
+ } while (*dirname != '\0');
+}
+
+
+static void
+source_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct symtab *s = current_source_symtab;
+
+ if (!s)
+ {
+ printf_filtered("No current source file.\n");
+ return;
+ }
+ printf_filtered ("Current source file is %s\n", s->filename);
+ if (s->dirname)
+ printf_filtered ("Compilation directory is %s\n", s->dirname);
+ if (s->fullname)
+ printf_filtered ("Located in %s\n", s->fullname);
+ if (s->nlines)
+ printf_filtered ("Contains %d line%s.\n", s->nlines,
+ s->nlines == 1 ? "" : "s");
+
+ printf_filtered("Source language is %s.\n", language_str (s->language));
+}
+
+
+
+/* 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.
+ (ie pretend the first element of PATH is "."). This also indicates
+ that a slash in STRING disables searching of the path (this is
+ so that "exec-file ./foo" or "symbol-file ./foo" insures that you
+ get that particular version of foo or an error message).
+
+ If FILENAMED_OPENED is non-null, set it to a newly allocated string naming
+ the actual file opened (this string will always start with a "/". We
+ have to take special pains to avoid doubling the "/" between the directory
+ and the file, sigh! Emacs gets confuzzed by this when we print the
+ source file name!!!
+
+ If a file is found, return the descriptor.
+ Otherwise, return -1, with errno set for the last name we tried to open. */
+
+/* >>>> This should only allow files of certain types,
+ >>>> eg executable, non-directory */
+int
+openp (path, try_cwd_first, string, mode, prot, filename_opened)
+ char *path;
+ int try_cwd_first;
+ char *string;
+ int mode;
+ int prot;
+ char **filename_opened;
+{
+ register int fd;
+ register char *filename;
+ register char *p, *p1;
+ register int len;
+ int alloclen;
+
+ if (!path)
+ path = ".";
+
+#ifdef WIN32
+ mode |= O_BINARY;
+#endif
+
+ if (try_cwd_first || SLASH_P (string[0]))
+ {
+ int i;
+ filename = string;
+ fd = open (filename, mode, prot);
+ if (fd >= 0)
+ goto done;
+ for (i = 0; string[i]; i++)
+ if (SLASH_P (string[i]))
+ goto done;
+ }
+
+ /* ./foo => foo */
+ while (string[0] == '.' && SLASH_P (string[1]))
+ string += 2;
+
+ alloclen = strlen (path) + strlen (string) + 2;
+ filename = (char *) alloca (alloclen);
+ fd = -1;
+ for (p = path; p; p = p1 ? p1 + 1 : 0)
+ {
+ p1 = (char *) strchr (p, DIRNAME_SEPARATOR);
+ if (p1)
+ len = p1 - p;
+ else
+ len = strlen (p);
+
+ if (len == 4 && p[0] == '$' && p[1] == 'c'
+ && p[2] == 'w' && p[3] == 'd') {
+ /* Name is $cwd -- insert current directory name instead. */
+ int newlen;
+
+ /* First, realloc the filename buffer if too short. */
+ len = strlen (current_directory);
+ newlen = len + strlen (string) + 2;
+ if (newlen > alloclen) {
+ alloclen = newlen;
+ filename = (char *) alloca (alloclen);
+ }
+ strcpy (filename, current_directory);
+ } else {
+ /* Normal file name in path -- just use it. */
+ strncpy (filename, p, len);
+ filename[len] = 0;
+ }
+
+ /* Remove trailing slashes */
+ while (len > 0 && SLASH_P (filename[len-1]))
+ filename[--len] = 0;
+
+ strcat (filename+len, SLASH_STRING);
+ strcat (filename, string);
+
+ fd = open (filename, mode);
+ if (fd >= 0) break;
+ }
+
+ done:
+ if (filename_opened)
+ {
+ if (fd < 0)
+ *filename_opened = (char *) 0;
+ else if (ROOTED_P (filename))
+ *filename_opened = savestring (filename, strlen (filename));
+ else
+ {
+ /* Beware the // my son, the Emacs barfs, the botch that catch... */
+
+ *filename_opened = concat (current_directory,
+ SLASH_CHAR
+ == current_directory[strlen(current_directory)-1]
+ ? "": SLASH_STRING,
+ filename, NULL);
+ }
+ }
+#ifdef MPW
+ /* This is a debugging hack that can go away when all combinations
+ of Mac and Unix names are handled reasonably. */
+ {
+ extern int debug_openp;
+
+ if (debug_openp)
+ {
+ printf("openp on %s, path %s mode %d prot %d\n returned %d",
+ string, path, mode, prot, fd);
+ if (*filename_opened)
+ printf(" (filename is %s)", *filename_opened);
+ printf("\n");
+ }
+ }
+#endif /* MPW */
+
+ return fd;
+}
+
+/* Open a source file given a symtab S. Returns a file descriptor or
+ negative number for error. */
+
+static int
+open_source_file (s)
+ struct symtab *s;
+{
+ char *path = source_path;
+ char *p;
+ int result;
+ char *fullname;
+
+ /* Quick way out if we already know its full name */
+ if (s->fullname)
+ {
+ result = open (s->fullname, O_RDONLY);
+ if (result >= 0)
+ return result;
+ /* Didn't work -- free old one, try again. */
+ mfree (s->objfile->md, s->fullname);
+ s->fullname = NULL;
+ }
+
+ if (s->dirname != NULL)
+ {
+ /* Replace a path entry of $cdir with the compilation directory name */
+#define cdir_len 5
+ /* 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] == DIRNAME_SEPARATOR)
+ && (p[cdir_len] == DIRNAME_SEPARATOR || p[cdir_len] == '\0'))
+ {
+ int len;
+
+ path = (char *)
+ alloca (strlen (source_path) + 1 + strlen (s->dirname) + 1);
+ len = p - source_path;
+ strncpy (path, source_path, len); /* Before $cdir */
+ strcpy (path + len, s->dirname); /* new stuff */
+ strcat (path + len, source_path + len + cdir_len); /* After $cdir */
+ }
+ }
+
+ result = openp (path, 0, s->filename, O_RDONLY, 0, &s->fullname);
+ if (result < 0)
+ {
+ /* 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);
+ }
+#ifdef MPW
+ if (result < 0)
+ {
+ /* Didn't work. Try using just the MPW basename. */
+ p = (char *) mpw_basename (s->filename);
+ if (p != s->filename)
+ result = openp (path, 0, p, O_RDONLY, 0, &s->fullname);
+ }
+ if (result < 0)
+ {
+ /* Didn't work. Try using the mixed Unix/MPW basename. */
+ p = (char *) mpw_mixed_basename (s->filename);
+ if (p != s->filename)
+ result = openp (path, 0, p, O_RDONLY, 0, &s->fullname);
+ }
+#endif /* MPW */
+
+ if (result >= 0)
+ {
+ fullname = s->fullname;
+ s->fullname = mstrsave (s->objfile->md, s->fullname);
+ free (fullname);
+ }
+ return result;
+}
+
+/* Return the path to the source file associated with symtab. Returns NULL
+ if no symtab. */
+
+char *
+symtab_to_filename (s)
+ struct symtab *s;
+{
+ int fd;
+
+ if (!s)
+ return NULL;
+
+ /* If we've seen the file before, just return fullname. */
+
+ if (s->fullname)
+ return s->fullname;
+
+ /* Try opening the file to setup fullname */
+
+ fd = open_source_file (s);
+ if (fd < 0)
+ return s->filename; /* File not found. Just use short name */
+
+ /* Found the file. Cleanup and return the full name */
+
+ close (fd);
+ return s->fullname;
+}
+
+
+/* Create and initialize the table S->line_charpos that records
+ the positions of the lines in the source file, which is assumed
+ to be open on descriptor DESC.
+ All set S->nlines to the number of such lines. */
+
+static void
+find_source_lines (s, desc)
+ struct symtab *s;
+ int desc;
+{
+ struct stat st;
+ register char *data, *p, *end;
+ int nlines = 0;
+ int lines_allocated = 1000;
+ int *line_charpos;
+ long exec_mtime;
+ int size;
+
+ line_charpos = (int *) xmmalloc (s -> objfile -> md,
+ lines_allocated * sizeof (int));
+ if (fstat (desc, &st) < 0)
+ 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");
+ }
+
+#ifdef LSEEK_NOT_LINEAR
+ {
+ char c;
+
+ /* Have to read it byte by byte to find out where the chars live */
+
+ line_charpos[0] = lseek (desc, 0, SEEK_CUR);
+ 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++] = lseek (desc, 0, SEEK_CUR);
+ }
+ }
+ }
+#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,
+ nlines * sizeof (int));
+
+}
+
+/* Return the character position of a line LINE in symtab S.
+ Return 0 if anything is invalid. */
+
+#if 0 /* Currently unused */
+
+int
+source_line_charpos (s, line)
+ struct symtab *s;
+ int line;
+{
+ if (!s) return 0;
+ if (!s->line_charpos || line <= 0) return 0;
+ if (line > s->nlines)
+ line = s->nlines;
+ return s->line_charpos[line - 1];
+}
+
+/* Return the line number of character position POS in symtab S. */
+
+int
+source_charpos_line (s, chr)
+ register struct symtab *s;
+ register int chr;
+{
+ register int line = 0;
+ register int *lnp;
+
+ if (s == 0 || s->line_charpos == 0) return 0;
+ lnp = s->line_charpos;
+ /* Files are usually short, so sequential search is Ok */
+ while (line < s->nlines && *lnp <= chr)
+ {
+ line++;
+ lnp++;
+ }
+ if (line >= s->nlines)
+ line = s->nlines;
+ return line;
+}
+
+#endif /* 0 */
+
+
+/* Get full pathname and line number positions for a symtab.
+ Return nonzero if line numbers may have changed.
+ Set *FULLNAME to actual name of the file as found by `openp',
+ or to 0 if the file is not found. */
+
+static int
+get_filename_and_charpos (s, fullname)
+ struct symtab *s;
+ char **fullname;
+{
+ register int desc, linenums_changed = 0;
+
+ desc = open_source_file (s);
+ if (desc < 0)
+ {
+ if (fullname)
+ *fullname = NULL;
+ return 0;
+ }
+ if (fullname)
+ *fullname = s->fullname;
+ if (s->line_charpos == 0) linenums_changed = 1;
+ if (linenums_changed) find_source_lines (s, desc);
+ close (desc);
+ return linenums_changed;
+}
+
+/* Print text describing the full name of the source file S
+ and the line number LINE and its corresponding character position.
+ The text starts with two Ctrl-z so that the Emacs-GDB interface
+ can easily find it.
+
+ MID_STATEMENT is nonzero if the PC is not at the beginning of that line.
+
+ Return 1 if successful, 0 if could not find the file. */
+
+int
+identify_source_line (s, line, mid_statement, pc)
+ struct symtab *s;
+ int line;
+ int mid_statement;
+ CORE_ADDR pc;
+{
+ if (s->line_charpos == 0)
+ get_filename_and_charpos (s, (char **)NULL);
+ if (s->fullname == 0)
+ return 0;
+ if (line > s->nlines)
+ /* Don't index off the end of the line_charpos array. */
+ return 0;
+ 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;
+ current_source_symtab = s;
+ return 1;
+}
+
+/* Print source lines from the file of symtab S,
+ starting with line number LINE and stopping before line number STOPLINE. */
+
+void
+print_source_lines (s, line, stopline, noerror)
+ struct symtab *s;
+ int line, stopline;
+ int noerror;
+{
+ register int c;
+ register int desc;
+ register FILE *stream;
+ int nlines = stopline - line;
+
+ /* Regardless of whether we can open the file, set current_source_symtab. */
+ current_source_symtab = s;
+ current_source_line = line;
+ first_line_listed = line;
+
+ desc = open_source_file (s);
+ if (desc < 0)
+ {
+ if (! noerror) {
+ char *name = alloca (strlen (s->filename) + 100);
+ sprintf (name, "%s:%d", s->filename, line);
+ print_sys_errmsg (name, errno);
+ }
+ return;
+ }
+
+ if (s->line_charpos == 0)
+ find_source_lines (s, desc);
+
+ if (line < 1 || line > s->nlines)
+ {
+ close (desc);
+ error ("Line number %d out of range; %s has %d lines.",
+ line, s->filename, s->nlines);
+ }
+
+ if (lseek (desc, s->line_charpos[line - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (s->filename);
+ }
+
+ stream = fdopen (desc, FOPEN_RT);
+ clearerr (stream);
+
+ while (nlines-- > 0)
+ {
+ c = fgetc (stream);
+ if (c == EOF) break;
+ last_line_listed = current_source_line;
+ printf_filtered ("%d\t", current_source_line++);
+ do
+ {
+ if (c < 040 && c != '\t' && c != '\n' && c != '\r')
+ printf_filtered ("^%c", c + 0100);
+ else if (c == 0177)
+ printf_filtered ("^?");
+ else
+ printf_filtered ("%c", c);
+ } while (c != '\n' && (c = fgetc (stream)) >= 0);
+ }
+
+ fclose (stream);
+}
+
+
+
+/* Print a list of files and line numbers which a user may choose from
+ in order to list a function which was specified ambiguously (as with
+ `list classname::overloadedfuncname', for example). The vector in
+ SALS provides the filenames and line numbers. */
+
+static void
+ambiguous_line_spec (sals)
+ struct symtabs_and_lines *sals;
+{
+ int i;
+
+ for (i = 0; i < sals->nelts; ++i)
+ printf_filtered("file: \"%s\", line number: %d\n",
+ sals->sals[i].symtab->filename, sals->sals[i].line);
+}
+
+static void
+list_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtabs_and_lines sals, sals_end;
+ struct symtab_and_line sal, sal_end;
+ struct symbol *sym;
+ char *arg1;
+ int no_end = 1;
+ int dummy_end = 0;
+ int dummy_beg = 0;
+ int linenum_beg = 0;
+ char *p;
+
+ if (!have_full_symbols () && !have_partial_symbols())
+ error ("No symbol table is loaded. Use the \"file\" command.");
+
+ /* Pull in a current source symtab if necessary */
+ if (current_source_symtab == 0 &&
+ (arg == 0 || arg[0] == '+' || arg[0] == '-'))
+ select_source_symtab (0);
+
+ /* "l" or "l +" lists next ten lines. */
+
+ if (arg == 0 || STREQ (arg, "+"))
+ {
+ if (current_source_symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ print_source_lines (current_source_symtab, current_source_line,
+ current_source_line + lines_to_list, 0);
+ return;
+ }
+
+ /* "l -" lists previous ten lines, the ones before the ten just listed. */
+ if (STREQ (arg, "-"))
+ {
+ if (current_source_symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ print_source_lines (current_source_symtab,
+ max (first_line_listed - lines_to_list, 1),
+ first_line_listed, 0);
+ return;
+ }
+
+ /* Now if there is only one argument, decode it in SAL
+ and set NO_END.
+ If there are two arguments, decode them in SAL and SAL_END
+ and clear NO_END; however, if one of the arguments is blank,
+ set DUMMY_BEG or DUMMY_END to record that fact. */
+
+ arg1 = arg;
+ if (*arg1 == ',')
+ dummy_beg = 1;
+ else
+ {
+ sals = decode_line_1 (&arg1, 0, 0, 0, 0);
+
+ if (! sals.nelts) return; /* C++ */
+ if (sals.nelts > 1)
+ {
+ ambiguous_line_spec (&sals);
+ free (sals.sals);
+ return;
+ }
+
+ sal = sals.sals[0];
+ free (sals.sals);
+ }
+
+ /* Record whether the BEG arg is all digits. */
+
+ for (p = arg; p != arg1 && *p >= '0' && *p <= '9'; p++);
+ linenum_beg = (p == arg1);
+
+ while (*arg1 == ' ' || *arg1 == '\t')
+ arg1++;
+ if (*arg1 == ',')
+ {
+ no_end = 0;
+ arg1++;
+ while (*arg1 == ' ' || *arg1 == '\t')
+ arg1++;
+ if (*arg1 == 0)
+ dummy_end = 1;
+ else
+ {
+ if (dummy_beg)
+ sals_end = decode_line_1 (&arg1, 0, 0, 0, 0);
+ else
+ sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0);
+ if (sals_end.nelts == 0)
+ return;
+ if (sals_end.nelts > 1)
+ {
+ ambiguous_line_spec (&sals_end);
+ free (sals_end.sals);
+ return;
+ }
+ sal_end = sals_end.sals[0];
+ free (sals_end.sals);
+ }
+ }
+
+ if (*arg1)
+ error ("Junk at end of line specification.");
+
+ if (!no_end && !dummy_beg && !dummy_end
+ && sal.symtab != sal_end.symtab)
+ error ("Specified start and end are in different files.");
+ if (dummy_beg && dummy_end)
+ error ("Two empty args do not say what lines to list.");
+
+ /* if line was specified by address,
+ first print exactly which line, and which file.
+ In this case, sal.symtab == 0 means address is outside
+ of all known source files, not that user failed to give a filename. */
+ 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)
+ {
+ 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
+ {
+ 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,
+ and it does not imply a symtab, it must be an undebuggable symbol
+ which means no source code. */
+
+ if (! linenum_beg && sal.symtab == 0)
+ error ("No line number known for %s.", arg);
+
+ /* If this command is repeated with RET,
+ turn it into the no-arg variant. */
+
+ if (from_tty)
+ *arg = 0;
+
+ if (dummy_beg && sal_end.symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ if (dummy_beg)
+ print_source_lines (sal_end.symtab,
+ max (sal_end.line - (lines_to_list - 1), 1),
+ sal_end.line + 1, 0);
+ else if (sal.symtab == 0)
+ error ("No default source file yet. Do \"help list\".");
+ else if (no_end)
+ print_source_lines (sal.symtab,
+ max (sal.line - (lines_to_list / 2), 1),
+ sal.line + (lines_to_list / 2), 0);
+ else
+ print_source_lines (sal.symtab, sal.line,
+ (dummy_end
+ ? sal.line + lines_to_list
+ : sal_end.line + 1),
+ 0);
+}
+
+/* Print info on range of pc's in a specified line. */
+
+static void
+line_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct symtabs_and_lines sals;
+ struct symtab_and_line sal;
+ CORE_ADDR start_pc, end_pc;
+ int i;
+
+ if (arg == 0)
+ {
+ sal.symtab = current_source_symtab;
+ sal.line = last_line_listed;
+ sal.pc = 0;
+ sals.nelts = 1;
+ sals.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ sals.sals[0] = sal;
+ }
+ else
+ {
+ sals = decode_line_spec_1 (arg, 0);
+
+ dont_repeat ();
+ }
+
+ /* C++ More than one line may have been specified, as when the user
+ specifies an overloaded function name. Print info on them all. */
+ for (i = 0; i < sals.nelts; i++)
+ {
+ sal = sals.sals[i];
+
+ if (sal.symtab == 0)
+ {
+ printf_filtered ("No line number information available");
+ if (sal.pc != 0)
+ {
+ /* This is useful for "info line *0x7f34". If we can't tell the
+ user about a source line, at least let them have the symbolic
+ address. */
+ printf_filtered (" for address ");
+ wrap_here (" ");
+ print_address (sal.pc, gdb_stdout);
+ }
+ else
+ printf_filtered (".");
+ printf_filtered ("\n");
+ }
+ else if (sal.line > 0
+ && find_line_pc_range (sal, &start_pc, &end_pc))
+ {
+ if (start_pc == end_pc)
+ {
+ printf_filtered ("Line %d of \"%s\"",
+ sal.line, sal.symtab->filename);
+ wrap_here (" ");
+ printf_filtered (" is at address ");
+ print_address (start_pc, gdb_stdout);
+ wrap_here (" ");
+ printf_filtered (" but contains no code.\n");
+ }
+ else
+ {
+ printf_filtered ("Line %d of \"%s\"",
+ sal.line, sal.symtab->filename);
+ wrap_here (" ");
+ printf_filtered (" starts at address ");
+ print_address (start_pc, gdb_stdout);
+ wrap_here (" ");
+ printf_filtered (" and ends at ");
+ print_address (end_pc, gdb_stdout);
+ printf_filtered (".\n");
+ }
+
+ /* x/i should display this line's code. */
+ set_next_address (start_pc);
+
+ /* Repeating "info line" should do the following line. */
+ last_line_listed = sal.line + 1;
+
+ /* If this is the only line, show the source code. If it could
+ not find the file, don't do anything special. */
+ if (annotation_level && sals.nelts == 1)
+ identify_source_line (sal.symtab, sal.line, 0, start_pc);
+ }
+ else
+ /* Is there any case in which we get here, and have an address
+ which the user would want to see? If we have debugging symbols
+ and no line numbers? */
+ printf_filtered ("Line number %d is out of range for \"%s\".\n",
+ sal.line, sal.symtab->filename);
+ }
+ free (sals.sals);
+}
+
+/* Commands to search the source file for a regexp. */
+
+/* ARGSUSED */
+static void
+forward_search_command (regex, from_tty)
+ char *regex;
+ int from_tty;
+{
+ register int c;
+ register int desc;
+ register FILE *stream;
+ int line = last_line_listed + 1;
+ char *msg;
+
+ msg = (char *) re_comp (regex);
+ if (msg)
+ error (msg);
+
+ if (current_source_symtab == 0)
+ select_source_symtab (0);
+
+ /* Search from last_line_listed+1 in current_source_symtab */
+
+ desc = open_source_file (current_source_symtab);
+ if (desc < 0)
+ perror_with_name (current_source_symtab->filename);
+
+ if (current_source_symtab->line_charpos == 0)
+ find_source_lines (current_source_symtab, desc);
+
+ if (line < 1 || line > current_source_symtab->nlines)
+ {
+ close (desc);
+ error ("Expression not found");
+ }
+
+ if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (current_source_symtab->filename);
+ }
+
+ stream = fdopen (desc, FOPEN_RT);
+ clearerr (stream);
+ while (1) {
+ static char *buf = NULL;
+ register char *p;
+ int cursize, newsize;
+
+ cursize = 256;
+ buf = xmalloc (cursize);
+ p = buf;
+
+ c = getc (stream);
+ if (c == EOF)
+ break;
+ do {
+ *p++ = c;
+ if (p - buf == cursize)
+ {
+ newsize = cursize + cursize / 2;
+ buf = xrealloc (buf, newsize);
+ p = buf + cursize;
+ cursize = newsize;
+ }
+ } while (c != '\n' && (c = getc (stream)) >= 0);
+
+ /* we now have a source line in buf, null terminate and match */
+ *p = 0;
+ if (re_exec (buf) > 0)
+ {
+ /* Match! */
+ fclose (stream);
+ print_source_lines (current_source_symtab, line, line+1, 0);
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) line));
+ current_source_line = max (line - lines_to_list / 2, 1);
+ return;
+ }
+ line++;
+ }
+
+ printf_filtered ("Expression not found\n");
+ fclose (stream);
+}
+
+/* ARGSUSED */
+static void
+reverse_search_command (regex, from_tty)
+ char *regex;
+ int from_tty;
+{
+ register int c;
+ register int desc;
+ register FILE *stream;
+ int line = last_line_listed - 1;
+ char *msg;
+
+ msg = (char *) re_comp (regex);
+ if (msg)
+ error (msg);
+
+ if (current_source_symtab == 0)
+ select_source_symtab (0);
+
+ /* Search from last_line_listed-1 in current_source_symtab */
+
+ desc = open_source_file (current_source_symtab);
+ if (desc < 0)
+ perror_with_name (current_source_symtab->filename);
+
+ if (current_source_symtab->line_charpos == 0)
+ find_source_lines (current_source_symtab, desc);
+
+ if (line < 1 || line > current_source_symtab->nlines)
+ {
+ close (desc);
+ error ("Expression not found");
+ }
+
+ if (lseek (desc, current_source_symtab->line_charpos[line - 1], 0) < 0)
+ {
+ close (desc);
+ perror_with_name (current_source_symtab->filename);
+ }
+
+ stream = fdopen (desc, FOPEN_RT);
+ clearerr (stream);
+ while (line > 1)
+ {
+/* FIXME!!! We walk right off the end of buf if we get a long line!!! */
+ char buf[4096]; /* Should be reasonable??? */
+ register char *p = buf;
+
+ c = getc (stream);
+ if (c == EOF)
+ break;
+ do {
+ *p++ = c;
+ } while (c != '\n' && (c = getc (stream)) >= 0);
+
+ /* We now have a source line in buf; null terminate and match. */
+ *p = 0;
+ if (re_exec (buf) > 0)
+ {
+ /* Match! */
+ fclose (stream);
+ print_source_lines (current_source_symtab,
+ line, line+1, 0);
+ set_internalvar (lookup_internalvar ("_"),
+ value_from_longest (builtin_type_int,
+ (LONGEST) line));
+ current_source_line = max (line - lines_to_list / 2, 1);
+ return;
+ }
+ line--;
+ if (fseek (stream, current_source_symtab->line_charpos[line - 1], 0) < 0)
+ {
+ fclose (stream);
+ perror_with_name (current_source_symtab->filename);
+ }
+ }
+
+ printf_filtered ("Expression not found\n");
+ fclose (stream);
+ return;
+}
+
+void
+_initialize_source ()
+{
+ struct cmd_list_element *c;
+ current_source_symtab = 0;
+ init_source_path ();
+
+ /* The intention is to use POSIX Basic Regular Expressions.
+ Always use the GNU regex routine for consistency across all hosts.
+ Our current GNU regex.c does not have all the POSIX features, so this is
+ just an approximation. */
+ re_set_syntax (RE_SYNTAX_GREP);
+
+ c = add_cmd ("directory", class_files, directory_command,
+ "Add directory DIR to beginning of search path for source files.\n\
+Forget cached info on source file locations and line positions.\n\
+DIR can also be $cwd for the current working directory, or $cdir for the\n\
+directory in which the source file was compiled into object code.\n\
+With no argument, reset the search path to $cdir:$cwd, the default.",
+ &cmdlist);
+ c->completer = filename_completer;
+
+ add_cmd ("directories", no_class, show_directories,
+ "Current search path for finding source files.\n\
+$cwd in the path means the current working directory.\n\
+$cdir in the path means the compilation directory of the source file.",
+ &showlist);
+
+ add_info ("source", source_info,
+ "Information about the current source file.");
+
+ add_info ("line", line_info,
+ concat ("Core addresses of the code for a source line.\n\
+Line can be specified as\n\
+ LINENUM, to list around that line in current file,\n\
+ FILE:LINENUM, to list around that line in that file,\n\
+ FUNCTION, to list around beginning of that function,\n\
+ FILE:FUNCTION, to distinguish among like-named static functions.\n\
+", "\
+Default is to describe the last source line that was listed.\n\n\
+This sets the default address for \"x\" to the line's first instruction\n\
+so that \"x/i\" suffices to start examining the machine code.\n\
+The address is also stored as the value of \"$_\".", NULL));
+
+ add_com ("forward-search", class_files, forward_search_command,
+ "Search for regular expression (see regex(3)) from last line listed.\n\
+The matching line number is also stored as the value of \"$_\".");
+ add_com_alias ("search", "forward-search", class_files, 0);
+
+ add_com ("reverse-search", class_files, reverse_search_command,
+ "Search backward for regular expression (see regex(3)) from last line listed.\n\
+The matching line number is also stored as the value of \"$_\".");
+
+ add_com ("list", class_files, list_command,
+ concat ("List specified function or line.\n\
+With no argument, lists ten more lines after or around previous listing.\n\
+\"list -\" lists the ten lines before a previous ten-line listing.\n\
+One argument specifies a line, and ten lines are listed around that line.\n\
+Two arguments with comma between specify starting and ending lines to list.\n\
+", "\
+Lines can be specified in these ways:\n\
+ LINENUM, to list around that line in current file,\n\
+ FILE:LINENUM, to list around that line in that file,\n\
+ FUNCTION, to list around beginning of that function,\n\
+ FILE:FUNCTION, to distinguish among like-named static functions.\n\
+ *ADDRESS, to list around the line containing that address.\n\
+With two args if one is empty it stands for ten lines away from the other arg.", NULL));
+
+ add_com_alias ("l", "list", class_files, 1);
+
+ add_show_from_set
+ (add_set_cmd ("listsize", class_support, var_uinteger,
+ (char *)&lines_to_list,
+ "Set number of source lines gdb will list by default.",
+ &setlist),
+ &showlist);
+}
diff --git a/contrib/gdb/gdb/srec.h b/contrib/gdb/gdb/srec.h
new file mode 100644
index 0000000..1446bda
--- /dev/null
+++ b/contrib/gdb/gdb/srec.h
@@ -0,0 +1,35 @@
+/* S-record download support for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+void load_srec PARAMS ((serial_t desc, const char *file, int maxrecsize,
+ int flags, int hashmark));
+
+/* S-record capability flags */
+
+/* Which record types are supported */
+#define SREC_2_BYTE_ADDR 0x00000001
+#define SREC_3_BYTE_ADDR 0x00000002
+#define SREC_4_BYTE_ADDR 0x00000004
+#define SREC_TERM_SHIFT 3
+
+#define SREC_ALL (SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR \
+ | ((SREC_2_BYTE_ADDR | SREC_3_BYTE_ADDR | SREC_4_BYTE_ADDR) \
+ << SREC_TERM_SHIFT))
+
+#define SREC_BINARY 0x00000040 /* Supports binary form of S-records */
diff --git a/contrib/gdb/gdb/stabsread.c b/contrib/gdb/gdb/stabsread.c
new file mode 100644
index 0000000..80fbd77
--- /dev/null
+++ b/contrib/gdb/gdb/stabsread.c
@@ -0,0 +1,4017 @@
+/* Support routines for decoding "stabs" debugging information format.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Support routines for reading and decoding debugging information in
+ the "stabs" format. This format is used with many systems that use
+ the a.out object file format, as well as some systems that use
+ COFF or ELF where the stabs data is placed in a special section.
+ Avoid placing any object file format specific code in this file. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "bfd.h"
+#include "obstack.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#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"
+#include "language.h"
+
+#include <ctype.h>
+
+/* Ask stabsread.h to define the vars it normally declares `extern'. */
+#define EXTERN /**/
+#include "stabsread.h" /* Our own declarations */
+#undef EXTERN
+
+/* The routines that read and process a complete stabs for a C struct or
+ C++ class pass lists of data member fields and lists of member function
+ fields in an instance of a field_info structure, as defined below.
+ This is part of some reorganization of low level C++ support and is
+ expected to eventually go away... (FIXME) */
+
+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
+ {
+ struct next_fnfieldlist *next;
+ struct fn_fieldlist fn_fieldlist;
+ } *fnlist;
+};
+
+static struct type *
+dbx_alloc_type PARAMS ((int [2], struct objfile *));
+
+static long read_huge_number PARAMS ((char **, int, int *));
+
+static struct type *error_type PARAMS ((char **, struct objfile *));
+
+static void
+patch_block_stabs PARAMS ((struct pending *, struct pending_stabs *,
+ struct objfile *));
+
+static void
+fix_common_block PARAMS ((struct symbol *, int));
+
+static int
+read_type_number PARAMS ((char **, int *));
+
+static struct type *
+read_range_type PARAMS ((char **, int [2], struct objfile *));
+
+static struct type *
+read_sun_builtin_type PARAMS ((char **, int [2], struct objfile *));
+
+static struct type *
+read_sun_floating_type PARAMS ((char **, int [2], struct objfile *));
+
+static struct type *
+read_enum_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type *
+rs6000_builtin_type PARAMS ((int));
+
+static int
+read_member_functions PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+read_struct_fields PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+read_baseclasses PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+read_tilde_fields PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static int
+attach_fn_fields_to_type PARAMS ((struct field_info *, struct type *));
+
+static int
+attach_fields_to_type PARAMS ((struct field_info *, struct type *,
+ struct objfile *));
+
+static struct type *
+read_struct_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type *
+read_array_type PARAMS ((char **, struct type *, struct objfile *));
+
+static struct type **
+read_args PARAMS ((char **, int, struct objfile *));
+
+static int
+read_cpp_abbrev PARAMS ((struct field_info *, char **, struct type *,
+ struct objfile *));
+
+static const char vptr_name[] = { '_','v','p','t','r',CPLUS_MARKER,'\0' };
+static const char vb_name[] = { '_','v','b',CPLUS_MARKER,'\0' };
+
+/* 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
+
+struct complaint invalid_cpp_abbrev_complaint =
+ {"invalid C++ abbreviation `%s'", 0, 0};
+
+struct complaint invalid_cpp_type_complaint =
+ {"C++ abbreviated type name unknown at symtab pos %d", 0, 0};
+
+struct complaint member_fn_complaint =
+ {"member function type missing, got '%c'", 0, 0};
+
+struct complaint const_vol_complaint =
+ {"const/volatile indicator missing, got '%c'", 0, 0};
+
+struct complaint error_type_complaint =
+ {"debug info mismatch between compiler and debugger", 0, 0};
+
+struct complaint invalid_member_complaint =
+ {"invalid (minimal) member type data format at symtab pos %d.", 0, 0};
+
+struct complaint range_type_base_complaint =
+ {"base type %d of range type is not defined", 0, 0};
+
+struct complaint reg_value_complaint =
+ {"register number %d too large (max %d) in symbol %s", 0, 0};
+
+struct complaint vtbl_notfound_complaint =
+ {"virtual function table pointer not found when defining class `%s'", 0, 0};
+
+struct complaint unrecognized_cplus_name_complaint =
+ {"Unknown C++ symbol name `%s'", 0, 0};
+
+struct complaint rs6000_builtin_complaint =
+ {"Unknown builtin type %d", 0, 0};
+
+struct complaint unresolved_sym_chain_complaint =
+ {"%s: common block `%s' from global_sym_chain unresolved", 0, 0};
+
+struct complaint stabs_general_complaint =
+ {"%s", 0, 0};
+
+/* Make a list of forward references which haven't been defined. */
+
+static struct type **undef_types;
+static int undef_types_allocated;
+static int undef_types_length;
+static struct symbol *current_symbol = NULL;
+
+/* Check for and handle cretinous stabs symbol name continuation! */
+#define STABS_CONTINUE(pp,objfile) \
+ do { \
+ if (**(pp) == '\\' || (**(pp) == '?' && (*(pp))[1] == '\0')) \
+ *(pp) = next_symbol_text (objfile); \
+ } 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; i<sizeof(os9k_type_vector)/sizeof(struct type **); i++)
+ tv[i] = (os9k_type_vector[i] == 0 ? 0 : *(os9k_type_vector[i]));
+}
+
+/* Look up a dbx type-number pair. Return the address of the slot
+ where the type for that number-pair is stored.
+ The number-pair is in TYPENUMS.
+
+ This can be used for finding the type associated with that pair
+ or for associating a new type with the pair. */
+
+struct type **
+dbx_lookup_type (typenums)
+ int typenums[2];
+{
+ register int filenum = typenums[0];
+ register int index = typenums[1];
+ unsigned old_len;
+ register int real_filenum;
+ register struct header_file *f;
+ int f_orig_length;
+
+ if (filenum == -1) /* -1,-1 is for temporary types. */
+ return 0;
+
+ if (filenum < 0 || filenum >= n_this_object_header_files)
+ {
+ static struct complaint msg = {"\
+Invalid symbol data: type number (%d,%d) out of range at symtab pos %d.",
+ 0, 0};
+ complain (&msg, filenum, index, symnum);
+ goto error_return;
+ }
+
+ if (filenum == 0)
+ {
+ if (index < 0)
+ {
+ /* Caller wants address of address of type. We think
+ that negative (rs6k builtin) types will never appear as
+ "lvalues", (nor should they), so we stuff the real type
+ pointer into a temp, and return its address. If referenced,
+ this will do the right thing. */
+ static struct type *temp_type;
+
+ temp_type = rs6000_builtin_type(index);
+ return &temp_type;
+ }
+
+ /* Type is defined outside of header files.
+ Find it in this object file's type vector. */
+ if (index >= type_vector_length)
+ {
+ old_len = type_vector_length;
+ if (old_len == 0)
+ {
+ type_vector_length = INITIAL_TYPE_VECTOR_LENGTH;
+ type_vector = (struct type **)
+ xmalloc (type_vector_length * sizeof (struct type *));
+ }
+ while (index >= type_vector_length)
+ {
+ type_vector_length *= 2;
+ }
+ type_vector = (struct type **)
+ xrealloc ((char *) type_vector,
+ (type_vector_length * sizeof (struct type *)));
+ memset (&type_vector[old_len], 0,
+ (type_vector_length - old_len) * sizeof (struct type *));
+
+ if (os9k_stabs)
+ /* Deal with OS9000 fundamental types. */
+ os9k_init_type_vector (type_vector);
+ }
+ return (&type_vector[index]);
+ }
+ else
+ {
+ real_filenum = this_object_header_files[filenum];
+
+ if (real_filenum >= n_header_files)
+ {
+ struct type *temp_type;
+ struct type **temp_type_p;
+
+ warning ("GDB internal error: bad real_filenum");
+
+ error_return:
+ temp_type = init_type (TYPE_CODE_ERROR, 0, 0, NULL, NULL);
+ temp_type_p = (struct type **) xmalloc (sizeof (struct type *));
+ *temp_type_p = temp_type;
+ return temp_type_p;
+ }
+
+ f = &header_files[real_filenum];
+
+ f_orig_length = f->length;
+ if (index >= f_orig_length)
+ {
+ while (index >= f->length)
+ {
+ f->length *= 2;
+ }
+ f->vector = (struct type **)
+ xrealloc ((char *) f->vector, f->length * sizeof (struct type *));
+ memset (&f->vector[f_orig_length], 0,
+ (f->length - f_orig_length) * sizeof (struct type *));
+ }
+ return (&f->vector[index]);
+ }
+}
+
+/* Make sure there is a type allocated for type numbers TYPENUMS
+ and return the type object.
+ This can create an empty (zeroed) type object.
+ TYPENUMS may be (-1, -1) to return a new type object that is not
+ put into the type vector, and so may not be referred to by number. */
+
+static struct type *
+dbx_alloc_type (typenums, objfile)
+ int typenums[2];
+ struct objfile *objfile;
+{
+ register struct type **type_addr;
+
+ if (typenums[0] == -1)
+ {
+ return (alloc_type (objfile));
+ }
+
+ type_addr = dbx_lookup_type (typenums);
+
+ /* If we are referring to a type not known at all yet,
+ allocate an empty type for it.
+ We will fill it in later if we find out how. */
+ if (*type_addr == 0)
+ {
+ *type_addr = alloc_type (objfile);
+ }
+
+ return (*type_addr);
+}
+
+/* for all the stabs in a given stab vector, build appropriate types
+ and fix their symbols in given symbol vector. */
+
+static void
+patch_block_stabs (symbols, stabs, objfile)
+ struct pending *symbols;
+ struct pending_stabs *stabs;
+ struct objfile *objfile;
+{
+ int ii;
+ char *name;
+ char *pp;
+ struct symbol *sym;
+
+ if (stabs)
+ {
+
+ /* for all the stab entries, find their corresponding symbols and
+ patch their types! */
+
+ for (ii = 0; ii < stabs->count; ++ii)
+ {
+ name = stabs->stab[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. */
+ sym = (struct symbol *)
+ obstack_alloc (&objfile->symbol_obstack,
+ sizeof (struct symbol));
+
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ SYMBOL_NAME (sym) =
+ obstack_copy0 (&objfile->symbol_obstack, name, pp - name);
+ pp += 2;
+ if (*(pp-1) == 'F' || *(pp-1) == 'f')
+ {
+ /* I don't think the linker does this with functions,
+ so as far as I know this is never executed.
+ But it doesn't hurt to check. */
+ SYMBOL_TYPE (sym) =
+ lookup_function_type (read_type (&pp, objfile));
+ }
+ else
+ {
+ SYMBOL_TYPE (sym) = read_type (&pp, objfile);
+ }
+ add_symbol_to_list (sym, &global_symbols);
+ }
+ else
+ {
+ pp += 2;
+ if (*(pp-1) == 'F' || *(pp-1) == 'f')
+ {
+ SYMBOL_TYPE (sym) =
+ lookup_function_type (read_type (&pp, objfile));
+ }
+ else
+ {
+ SYMBOL_TYPE (sym) = read_type (&pp, objfile);
+ }
+ }
+ }
+ }
+}
+
+
+/* Read a number by which a type is referred to in dbx data,
+ or perhaps read a pair (FILENUM, TYPENUM) in parentheses.
+ Just a single number N is equivalent to (0,N).
+ Return the two numbers by storing them in the vector TYPENUMS.
+ TYPENUMS will then be used as an argument to dbx_lookup_type.
+
+ Returns 0 for success, -1 for error. */
+
+static int
+read_type_number (pp, typenums)
+ register char **pp;
+ register int *typenums;
+{
+ int nbits;
+ if (**pp == '(')
+ {
+ (*pp)++;
+ typenums[0] = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0) return -1;
+ typenums[1] = read_huge_number (pp, ')', &nbits);
+ if (nbits != 0) return -1;
+ }
+ else
+ {
+ typenums[0] = 0;
+ typenums[1] = read_huge_number (pp, 0, &nbits);
+ if (nbits != 0) return -1;
+ }
+ return 0;
+}
+
+
+#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)
+ CORE_ADDR valu;
+ char *string;
+ int desc;
+ int type;
+ struct objfile *objfile;
+{
+ register struct symbol *sym;
+ char *p = (char *) strchr (string, ':');
+ int deftype;
+ int synonym = 0;
+ register int i;
+
+ /* We would like to eliminate nameless symbols, but keep their types.
+ E.g. stab entry ":t10=*2" should produce a type 10, which is a pointer
+ to type 2, but, should not create a symbol to address that type. Since
+ the symbol will be nameless, there is no way any user can refer to it. */
+
+ int nameless;
+
+ /* Ignore syms with empty names. */
+ if (string[0] == 0)
+ return 0;
+
+ /* Ignore old-style symbols from cc -go */
+ 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] == ':')));
+
+ current_symbol = sym = (struct symbol *)
+ 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
+ number of bytes occupied by a type or object, which we ignore. */
+ SYMBOL_LINE(sym) = desc;
+ }
+ else
+ {
+ SYMBOL_LINE(sym) = 0; /* unknown */
+ }
+
+ if (is_cplus_marker (string[0]))
+ {
+ /* Special GNU C++ names. */
+ switch (string[1])
+ {
+ case 't':
+ SYMBOL_NAME (sym) = obsavestring ("this", strlen ("this"),
+ &objfile -> symbol_obstack);
+ break;
+
+ case 'v': /* $vtbl_ptr_type */
+ /* Was: SYMBOL_NAME (sym) = "vptr"; */
+ goto normal;
+
+ case 'e':
+ SYMBOL_NAME (sym) = obsavestring ("eh_throw", strlen ("eh_throw"),
+ &objfile -> symbol_obstack);
+ break;
+
+ case '_':
+ /* This was an anonymous type that was never fixed up. */
+ goto normal;
+
+#ifdef STATIC_TRANSFORM_NAME
+ case 'X':
+ /* SunPRO (3.0 at least) static variable encoding. */
+ goto normal;
+#endif
+
+ default:
+ complain (&unrecognized_cplus_name_complaint, string);
+ goto normal; /* Do *something* with it */
+ }
+ }
+ else
+ {
+ normal:
+ SYMBOL_LANGUAGE (sym) = current_subfile -> language;
+ SYMBOL_NAME (sym) = (char *)
+ obstack_alloc (&objfile -> symbol_obstack, ((p - string) + 1));
+ /* Open-coded memcpy--saves function call time. */
+ /* FIXME: Does it really? Try replacing with simple strcpy and
+ try it on an executable with a large symbol table. */
+ /* FIXME: considering that gcc can open code memcpy anyway, I
+ doubt it. xoxorich. */
+ {
+ register char *p1 = string;
+ register char *p2 = SYMBOL_NAME (sym);
+ while (p1 != p)
+ {
+ *p2++ = *p1++;
+ }
+ *p2++ = '\0';
+ }
+
+ /* If this symbol is from a C++ compilation, then attempt to cache the
+ demangled form for future reference. This is a typical time versus
+ space tradeoff, that was decided in favor of time because it sped up
+ C++ symbol lookups by a factor of about 20. */
+
+ SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
+ }
+ p++;
+
+ /* Determine the type of name being defined. */
+#if 0
+ /* Getting GDB to correctly skip the symbol on an undefined symbol
+ descriptor and not ever dump core is a very dodgy proposition if
+ we do things this way. I say the acorn RISC machine can just
+ fix their compiler. */
+ /* The Acorn RISC machine's compiler can put out locals that don't
+ start with "234=" or "(3,4)=", so assume anything other than the
+ deftypes we know how to handle is a local. */
+ if (!strchr ("cfFGpPrStTvVXCR", *p))
+#else
+ if (isdigit (*p) || *p == '(' || *p == '-')
+#endif
+ deftype = 'l';
+ else
+ deftype = *p++;
+
+ switch (deftype)
+ {
+ case 'c':
+ /* c is a special case, not followed by a type-number.
+ SYMBOL:c=iVALUE for an integer constant symbol.
+ SYMBOL:c=rVALUE for a floating constant symbol.
+ SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ if (*p != '=')
+ {
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = error_type (&p, objfile);
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ return sym;
+ }
+ ++p;
+ switch (*p++)
+ {
+ case 'r':
+ {
+ 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?
+
+ Also, what should the name of this type be? Should we
+ be using 'S' constants (see stabs.texinfo) instead? */
+
+ SYMBOL_TYPE (sym) = lookup_fundamental_type (objfile,
+ FT_DBL_PREC_FLOAT);
+ dbl_valu = (char *)
+ 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;
+ }
+ break;
+ case 'i':
+ {
+ /* Defining integer constants this way is kind of silly,
+ since 'e' constants allows the compiler to give not
+ only the value, but the type as well. C has at least
+ int, long, unsigned int, and long long as constant
+ types; other languages probably should have at least
+ unsigned as well as signed constants. */
+
+ /* We just need one int constant type for all objfiles.
+ It doesn't depend on languages or anything (arguably its
+ name should be a language-specific name for a type of
+ that size, but I'm inclined to say that if the compiler
+ wants a nice name for the type, it can use 'e'). */
+ static struct type *int_const_type;
+
+ /* Yes, this is as long as a *host* int. That is because we
+ use atoi. */
+ if (int_const_type == NULL)
+ int_const_type =
+ init_type (TYPE_CODE_INT,
+ sizeof (int) * HOST_CHAR_BIT / TARGET_CHAR_BIT, 0,
+ "integer constant",
+ (struct objfile *)NULL);
+ SYMBOL_TYPE (sym) = int_const_type;
+ SYMBOL_VALUE (sym) = atoi (p);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ }
+ break;
+ case 'e':
+ /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
+ can be represented as integral.
+ e.g. "b:c=e6,0" for "const b = blob1"
+ (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
+ {
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ if (*p != ',')
+ {
+ SYMBOL_TYPE (sym) = error_type (&p, objfile);
+ break;
+ }
+ ++p;
+
+ /* If the value is too big to fit in an int (perhaps because
+ it is unsigned), or something like that, we silently get
+ a bogus value. The type and everything else about it is
+ correct. Ideally, we should be using whatever we have
+ available for parsing unsigned and long long values,
+ however. */
+ SYMBOL_VALUE (sym) = atoi (p);
+ }
+ break;
+ default:
+ {
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_TYPE (sym) = error_type (&p, objfile);
+ }
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ return sym;
+
+ case 'C':
+ /* The name of a caught exception. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_LABEL;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE_ADDRESS (sym) = valu;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'f':
+ /* A static function definition. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ /* fall into process_function_types. */
+
+ process_function_types:
+ /* Function result types are described as the result type in stabs.
+ We need to convert this to the function-returning-type-X type
+ in GDB. E.g. "int" is converted to "function returning int". */
+ if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_FUNC)
+ SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+ /* fall into process_prototype_types */
+
+ process_prototype_types:
+ /* Sun acc puts declared types of arguments here. We don't care
+ about their actual types (FIXME -- we should remember the whole
+ function prototype), but the list may define some new types
+ that we have to remember, so we must scan it now. */
+ while (*p == ';') {
+ p++;
+ read_type (&p, objfile);
+ }
+ break;
+
+ case 'F':
+ /* A global function definition. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &global_symbols);
+ goto process_function_types;
+
+ case 'G':
+ /* For a class G (global) symbol, it appears that the
+ value is not correct. It is necessary to search for the
+ corresponding linker definition to find the value.
+ These definitions appear at the end of the namelist. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ i = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+ global_sym_chain[i] = sym;
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &global_symbols);
+ break;
+
+ /* 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;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'p':
+ if (*p == 'F')
+ /* pF is a two-letter code that means a function parameter in Fortran.
+ The type-number specifies the type of the return value.
+ Translate it into a pointer-to-function type. */
+ {
+ p++;
+ SYMBOL_TYPE (sym)
+ = lookup_pointer_type
+ (lookup_function_type (read_type (&p, objfile)));
+ }
+ else
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ /* Normally this is a parameter, a LOC_ARG. On the i960, it
+ can also be a LOC_LOCAL_ARG depending on symbol type. */
+#ifndef DBX_PARM_SYMBOL_CLASS
+#define DBX_PARM_SYMBOL_CLASS(type) LOC_ARG
+#endif
+
+ SYMBOL_CLASS (sym) = DBX_PARM_SYMBOL_CLASS (type);
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+
+ if (TARGET_BYTE_ORDER != BIG_ENDIAN)
+ {
+ /* On little-endian machines, this crud is never necessary,
+ and, if the extra bytes contain garbage, is harmful. */
+ break;
+ }
+
+ /* If it's gcc-compiled, if it says `short', believe it. */
+ if (processing_gcc_compilation || BELIEVE_PCC_PROMOTION)
+ break;
+
+#if !BELIEVE_PCC_PROMOTION
+ {
+ /* This is the signed type which arguments get promoted to. */
+ static struct type *pcc_promotion_type;
+ /* This is the unsigned type which arguments get promoted to. */
+ static struct type *pcc_unsigned_promotion_type;
+
+ /* Call it "int" because this is mainly C lossage. */
+ if (pcc_promotion_type == NULL)
+ pcc_promotion_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "int", NULL);
+
+ if (pcc_unsigned_promotion_type == NULL)
+ pcc_unsigned_promotion_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, "unsigned int", NULL);
+
+#if defined(BELIEVE_PCC_PROMOTION_TYPE)
+ /* 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).
+
+ My guess is that this correction, as opposed to changing
+ the parameter to an 'int' (as done below, for PCC
+ on most machines), is the right thing to do
+ on all machines, but I don't want to risk breaking
+ something that already works. On most PCC machines,
+ 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 little practical difference between an int and a short
+ (except perhaps what happens when the GDB user types
+ "print short_arg = 0x10000;").
+
+ Hacked for SunOS 4.1 by gnu@cygnus.com. In 4.1, the compiler
+ actually produces the correct address (we don't need to fix it
+ up). I made this code adapt so that it will offset the symbol
+ if it was pointing at an int-aligned location and not
+ otherwise. This way you can use the same gdb for 4.0.x and
+ 4.1 systems.
+
+ If the parameter is shorter than an int, and is integral
+ (e.g. char, short, or unsigned equivalent), and is claimed to
+ be passed on an integer boundary, don't believe it! Offset the
+ parameter's address to the tail-end of that integer. */
+
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (pcc_promotion_type)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT
+ && 0 == SYMBOL_VALUE (sym) % TYPE_LENGTH (pcc_promotion_type))
+ {
+ SYMBOL_VALUE (sym) += TYPE_LENGTH (pcc_promotion_type)
+ - TYPE_LENGTH (SYMBOL_TYPE (sym));
+ }
+ break;
+
+#else /* no BELIEVE_PCC_PROMOTION_TYPE. */
+
+ /* If PCC says a parameter is a short or a char,
+ it is really an int. */
+ if (TYPE_LENGTH (SYMBOL_TYPE (sym)) < TYPE_LENGTH (pcc_promotion_type)
+ && TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_INT)
+ {
+ SYMBOL_TYPE (sym) =
+ TYPE_UNSIGNED (SYMBOL_TYPE (sym))
+ ? pcc_unsigned_promotion_type
+ : pcc_promotion_type;
+ }
+ break;
+
+#endif /* no BELIEVE_PCC_PROMOTION_TYPE. */
+ }
+#endif /* !BELIEVE_PCC_PROMOTION. */
+
+ case 'P':
+ /* acc seems to use P to declare the prototypes of functions that
+ are referenced by this file. gdb is not prepared to deal
+ with this extra information. FIXME, it ought to. */
+ if (type == N_FUN)
+ {
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ goto process_prototype_types;
+ }
+ /*FALLTHROUGH*/
+
+ case 'R':
+ /* Parameter which is in a register. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_REGPARM;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (&reg_value_complaint, SYMBOL_VALUE (sym), NUM_REGS,
+ SYMBOL_SOURCE_NAME (sym));
+ SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'r':
+ /* Register variable (either global or local). */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_REGISTER;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (&reg_value_complaint, SYMBOL_VALUE (sym), NUM_REGS,
+ SYMBOL_SOURCE_NAME (sym));
+ SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (within_function)
+ {
+ /* 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. 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) 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
+#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
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_SET
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_BITSTRING)
+#endif
+ )
+ {
+ struct symbol *prev_sym;
+ prev_sym = local_symbols->symbol[local_symbols->nsyms - 1];
+ 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;
+ }
+ }
+ add_symbol_to_list (sym, &local_symbols);
+ }
+ else
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 'S':
+ /* Static symbol at top level of file */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = valu;
+#ifdef STATIC_TRANSFORM_NAME
+ if (SYMBOL_NAME (sym)[0] == '$')
+ {
+ struct minimal_symbol *msym;
+ msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
+ if (msym != NULL)
+ {
+ SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
+ }
+ }
+#endif
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 't':
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ /* For a nameless type, we don't want a create a symbol, thus we
+ did not use `sym'. Return without further processing. */
+ if (nameless) return NULL;
+
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ /* C++ vagaries: we may have a type which is derived from
+ a base type which did not have its name defined when the
+ derived class was output. We fill in the derived class's
+ base part member's name here in that case. */
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) != NULL)
+ if ((TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT
+ || TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_UNION)
+ && TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)))
+ {
+ int j;
+ for (j = TYPE_N_BASECLASSES (SYMBOL_TYPE (sym)) - 1; j >= 0; j--)
+ if (TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), j) == 0)
+ TYPE_BASECLASS_NAME (SYMBOL_TYPE (sym), j) =
+ type_name_no_tag (TYPE_BASECLASS (SYMBOL_TYPE (sym), j));
+ }
+
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == NULL)
+ {
+ /* 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
+ 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; PCC and GCC (at
+ least through version 2.4) both output variables of
+ either type char * or caddr_t with the type number
+ defined in the 't' 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)) = SYMBOL_NAME (sym);
+ }
+
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+
+ case 'T':
+ /* Struct, union, or enum tag. For GNU C++, this can be be followed
+ by 't' which means we are typedef'ing it as well. */
+ synonym = *p == 't';
+
+ if (synonym)
+ p++;
+ /* 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;
+
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+
+ /* For a nameless type, we don't want a create a symbol, thus we
+ did not use `sym'. Return without further processing. */
+ if (nameless) return NULL;
+
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
+ if (TYPE_TAG_NAME (SYMBOL_TYPE (sym)) == 0)
+ TYPE_TAG_NAME (SYMBOL_TYPE (sym))
+ = obconcat (&objfile -> type_obstack, "", "", SYMBOL_NAME (sym));
+ add_symbol_to_list (sym, &file_symbols);
+
+ if (synonym)
+ {
+ /* Clone the sym and then modify it. */
+ register struct symbol *typedef_sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ *typedef_sym = *sym;
+ SYMBOL_CLASS (typedef_sym) = LOC_TYPEDEF;
+ SYMBOL_VALUE (typedef_sym) = valu;
+ SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+ TYPE_NAME (SYMBOL_TYPE (sym))
+ = obconcat (&objfile -> type_obstack, "", "", SYMBOL_NAME (sym));
+ add_symbol_to_list (typedef_sym, &file_symbols);
+ }
+ break;
+
+ case 'V':
+ /* Static symbol of local scope */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_VALUE_ADDRESS (sym) = valu;
+#ifdef STATIC_TRANSFORM_NAME
+ if (SYMBOL_NAME (sym)[0] == '$')
+ {
+ struct minimal_symbol *msym;
+ msym = lookup_minimal_symbol (SYMBOL_NAME (sym), NULL, objfile);
+ if (msym != NULL)
+ {
+ SYMBOL_NAME (sym) = STATIC_TRANSFORM_NAME (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msym);
+ }
+ }
+#endif
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ if (os9k_stabs)
+ add_symbol_to_list (sym, &global_symbols);
+ else
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'v':
+ /* Reference parameter */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'a':
+ /* Reference parameter which is in a register. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_REGPARM_ADDR;
+ SYMBOL_VALUE (sym) = STAB_REG_TO_REGNUM (valu);
+ if (SYMBOL_VALUE (sym) >= NUM_REGS)
+ {
+ complain (&reg_value_complaint, SYMBOL_VALUE (sym), NUM_REGS,
+ SYMBOL_SOURCE_NAME (sym));
+ SYMBOL_VALUE (sym) = SP_REGNUM; /* Known safe, though useless */
+ }
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ case 'X':
+ /* This is used by Sun FORTRAN for "function result value".
+ Sun claims ("dbx and dbxtool interfaces", 2nd ed)
+ that Pascal uses it too, but when I tried it Pascal used
+ "x:3" (local symbol) instead. */
+ SYMBOL_TYPE (sym) = read_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_LOCAL;
+ SYMBOL_VALUE (sym) = valu;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &local_symbols);
+ break;
+
+ default:
+ SYMBOL_TYPE (sym) = error_type (&p, objfile);
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_VALUE (sym) = 0;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ add_symbol_to_list (sym, &file_symbols);
+ break;
+ }
+
+ /* When passing structures to a function, some systems sometimes pass
+ the address in a register, not the structure itself. */
+
+ if (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)
+ || (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_BITSTRING)
+ || (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_SET)))
+ {
+ /* If REG_STRUCT_HAS_ADDR yields non-zero we have to
+ convert LOC_REGPARM to LOC_REGPARM_ADDR for structures and unions. */
+ if (SYMBOL_CLASS (sym) == LOC_REGPARM)
+ 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). */
+ else if (SYMBOL_CLASS (sym) == LOC_ARG)
+ SYMBOL_CLASS (sym) = LOC_REF_ARG;
+ }
+
+ return sym;
+}
+
+
+/* Skip rest of this symbol and return an error type.
+
+ General notes on error recovery: error_type always skips to the
+ end of the symbol (modulo cretinous dbx symbol name continuation).
+ Thus code like this:
+
+ if (*(*pp)++ != ';')
+ return error_type (pp, objfile);
+
+ is wrong because if *pp starts out pointing at '\0' (typically as the
+ result of an earlier error), it will be incremented to point to the
+ start of the next symbol, which might produce strange results, at least
+ if you run off the end of the string table. Instead use
+
+ if (**pp != ';')
+ return error_type (pp, objfile);
+ ++*pp;
+
+ or
+
+ if (**pp != ';')
+ foo = error_type (pp, objfile);
+ else
+ ++*pp;
+
+ And in case it isn't obvious, the point of all this hair is so the compiler
+ can define new types and new syntaxes, and old versions of the
+ debugger will be able to read the new symbol tables. */
+
+static struct type *
+error_type (pp, objfile)
+ char **pp;
+ struct objfile *objfile;
+{
+ complain (&error_type_complaint);
+ while (1)
+ {
+ /* Skip to end of symbol. */
+ while (**pp != '\0')
+ {
+ (*pp)++;
+ }
+
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if ((*pp)[-1] == '\\' || (*pp)[-1] == '?')
+ {
+ *pp = next_symbol_text (objfile);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return (builtin_type_error);
+}
+
+
+/* Read type information or a type definition; return the type. Even
+ though this routine accepts either type information or a type
+ definition, the distinction is relevant--some parts of stabsread.c
+ assume that type information starts with a digit, '-', or '(' in
+ deciding whether to call read_type. */
+
+struct type *
+read_type (pp, objfile)
+ register char **pp;
+ struct objfile *objfile;
+{
+ register struct type *type = 0;
+ struct type *type1;
+ int typenums[2];
+ int xtypenums[2];
+ char type_descriptor;
+
+ /* Size in bits of type if specified by a type attribute, or -1 if
+ 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". */
+ if ((**pp >= '0' && **pp <= '9')
+ || **pp == '('
+ || **pp == '-')
+ {
+ if (read_type_number (pp, typenums) != 0)
+ return error_type (pp, objfile);
+
+ /* Type is not being defined here. Either it already exists,
+ or this is a forward reference to it. dbx_alloc_type handles
+ both cases. */
+ if (**pp != '=')
+ return dbx_alloc_type (typenums, objfile);
+
+ /* Type is being defined here. */
+ /* Skip the '='. */
+ ++(*pp);
+
+ while (**pp == '@')
+ {
+ char *p = *pp + 1;
+ /* It might be a type attribute or a member type. */
+ if (isdigit (*p) || *p == '(' || *p == '-')
+ /* Member type. */
+ break;
+ else
+ {
+ /* Type attributes. */
+ char *attr = p;
+
+ /* Skip to the semicolon. */
+ while (*p != ';' && *p != '\0')
+ ++p;
+ *pp = p;
+ if (*p == '\0')
+ return error_type (pp, objfile);
+ else
+ /* Skip the semicolon. */
+ ++*pp;
+
+ switch (*attr)
+ {
+ case 's':
+ type_size = atoi (attr + 1);
+ 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. */
+ break;
+ }
+ }
+ }
+ /* Skip the type descriptor, we get it below with (*pp)[-1]. */
+ ++(*pp);
+ }
+ else
+ {
+ /* 'typenums=' not present, type is anonymous. Read and return
+ the definition, but don't put it in the type vector. */
+ typenums[0] = typenums[1] = -1;
+ (*pp)++;
+ }
+
+ type_descriptor = (*pp)[-1];
+ switch (type_descriptor)
+ {
+ case 'x':
+ {
+ enum type_code code;
+
+ /* Used to index through file_symbols. */
+ struct pending *ppt;
+ int i;
+
+ /* Name including "struct", etc. */
+ char *type_name;
+
+ {
+ char *from, *to, *p, *q1, *q2;
+
+ /* Set the type code according to the following letter. */
+ switch ((*pp)[0])
+ {
+ case 's':
+ code = TYPE_CODE_STRUCT;
+ break;
+ case 'u':
+ code = TYPE_CODE_UNION;
+ break;
+ case 'e':
+ code = TYPE_CODE_ENUM;
+ break;
+ default:
+ {
+ /* 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;
+ }
+ }
+
+ q1 = strchr(*pp, '<');
+ p = strchr(*pp, ':');
+ if (p == NULL)
+ return error_type (pp, objfile);
+ 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, objfile);
+ }
+ to = type_name =
+ (char *)obstack_alloc (&objfile->type_obstack, p - *pp + 1);
+
+ /* Copy the name. */
+ from = *pp + 1;
+ while (from < p)
+ *to++ = *from++;
+ *to = '\0';
+
+ /* 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 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++)
+ {
+ struct symbol *sym = ppt->symbol[i];
+
+ if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+ && (TYPE_CODE (SYMBOL_TYPE (sym)) == code)
+ && STREQ (SYMBOL_NAME (sym), type_name))
+ {
+ obstack_free (&objfile -> type_obstack, type_name);
+ type = SYMBOL_TYPE (sym);
+ 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
+ fill in the rest of the fields when we get the full
+ type. */
+ type = dbx_alloc_type (typenums, objfile);
+ TYPE_CODE (type) = code;
+ TYPE_TAG_NAME (type) = type_name;
+ INIT_CPLUS_SPECIFIC(type);
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+
+ add_undefined_type (type);
+ return type;
+ }
+
+ case '-': /* RS/6000 built-in type */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '(':
+
+ {
+ char *pp_saved;
+
+ (*pp)--;
+ pp_saved = *pp;
+
+ /* Peek ahead at the number to detect void. */
+ if (read_type_number (pp, xtypenums) != 0)
+ return error_type (pp, objfile);
+
+ 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;
+
+ /* 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 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);
+ if (SYMBOL_LINE (current_symbol) == 0)
+ {
+ *type = *xtype;
+ /* 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;
+ }
+ else
+ {
+ TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
+ TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
+ TYPE_TARGET_TYPE (type) = xtype;
+ }
+ }
+ 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
+ and making the typenums point to the new one. This is because there
+ may already be pointers to the existing type (if it had been
+ forward-referenced), and we must change it to a pointer, function,
+ reference, or whatever, *in-place*. */
+
+ case '*':
+ type1 = read_type (pp, objfile);
+ type = make_pointer_type (type1, dbx_lookup_type (typenums));
+ break;
+
+ case '&': /* Reference to another type */
+ type1 = read_type (pp, objfile);
+ type = make_reference_type (type1, dbx_lookup_type (typenums));
+ 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 '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, objfile);
+ type = read_type (pp, objfile);
+ /* FIXME! For now, we ignore const and volatile qualifiers. */
+ break;
+
+ 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, objfile);
+ type = read_type (pp, objfile);
+ /* FIXME! For now, we ignore const and volatile qualifiers. */
+ break;
+
+/* FIXME -- we should be doing smash_to_XXX types here. */
+ case '@': /* Member (class & variable) type */
+ {
+ struct type *domain = read_type (pp, objfile);
+ struct type *memtype;
+
+ if (**pp != ',')
+ /* Invalid member type data format. */
+ return error_type (pp, objfile);
+ ++*pp;
+
+ memtype = read_type (pp, objfile);
+ type = dbx_alloc_type (typenums, objfile);
+ smash_to_member_type (type, domain, memtype);
+ }
+ break;
+
+ case '#': /* Method (class & fn) type */
+ if ((*pp)[0] == '#')
+ {
+ /* We'll get the parameter types from the name. */
+ struct type *return_type;
+
+ (*pp)++;
+ return_type = read_type (pp, objfile);
+ if (*(*pp)++ != ';')
+ complain (&invalid_member_complaint, symnum);
+ type = allocate_stub_method (return_type);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ }
+ else
+ {
+ struct type *domain = read_type (pp, objfile);
+ struct type *return_type;
+ struct type **args;
+
+ if (**pp != ',')
+ /* Invalid member type data format. */
+ return error_type (pp, objfile);
+ else
+ ++(*pp);
+
+ return_type = read_type (pp, objfile);
+ args = read_args (pp, ';', objfile);
+ type = dbx_alloc_type (typenums, objfile);
+ smash_to_method_type (type, domain, return_type, args);
+ }
+ break;
+
+ case 'r': /* Range type */
+ type = read_range_type (pp, typenums, objfile);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ 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 */
+ type = read_sun_floating_type (pp, typenums, objfile);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 'e': /* Enumeration type */
+ type = dbx_alloc_type (typenums, objfile);
+ type = read_enum_type (pp, type, objfile);
+ if (typenums[0] != -1)
+ *dbx_lookup_type (typenums) = type;
+ break;
+
+ case 's': /* Struct type */
+ case 'u': /* Union type */
+ type = dbx_alloc_type (typenums, objfile);
+ switch (type_descriptor)
+ {
+ case 's':
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ break;
+ case 'u':
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ break;
+ }
+ type = read_struct_type (pp, type, objfile);
+ break;
+
+ case 'a': /* Array type */
+ if (**pp != 'r')
+ return error_type (pp, objfile);
+ ++*pp;
+
+ 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:
+ --*pp; /* Go back to the symbol in error */
+ /* Particularly important if it was \0! */
+ return error_type (pp, objfile);
+ }
+
+ if (type == 0)
+ {
+ warning ("GDB internal error, type is NULL in stabsread.c\n");
+ return error_type (pp, objfile);
+ }
+
+ /* Size specified in a type attribute overrides any other size. */
+ if (type_size != -1)
+ TYPE_LENGTH (type) = (type_size + TARGET_CHAR_BIT - 1) / TARGET_CHAR_BIT;
+
+ return type;
+}
+
+/* RS/6000 xlc/dbx combination uses a set of builtin types, starting from -1.
+ Return the proper type node for a given builtin type number. */
+
+static struct type *
+rs6000_builtin_type (typenum)
+ int typenum;
+{
+ /* We recognize types numbered from -NUMBER_RECOGNIZED to -1. */
+#define NUMBER_RECOGNIZED 34
+ /* This includes an empty slot for type number -0. */
+ static struct type *negative_types[NUMBER_RECOGNIZED + 1];
+ struct type *rettype = NULL;
+
+ if (typenum >= 0 || typenum < -NUMBER_RECOGNIZED)
+ {
+ complain (&rs6000_builtin_complaint, typenum);
+ return builtin_type_error;
+ }
+ if (negative_types[-typenum] != NULL)
+ return negative_types[-typenum];
+
+#if TARGET_CHAR_BIT != 8
+ #error This code wrong for TARGET_CHAR_BIT not 8
+ /* These definitions all assume that TARGET_CHAR_BIT is 8. I think
+ that if that ever becomes not true, the correct fix will be to
+ make the size in the struct type to be in bits, not in units of
+ TARGET_CHAR_BIT. */
+#endif
+
+ switch (-typenum)
+ {
+ case 1:
+ /* The size of this and all the other types are fixed, defined
+ by the debugging format. If there is a type called "int" which
+ is other than 32 bits, then it should use a new negative type
+ number (or avoid negative type numbers for that case).
+ See stabs.texinfo. */
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "int", NULL);
+ break;
+ case 2:
+ rettype = init_type (TYPE_CODE_INT, 1, 0, "char", NULL);
+ break;
+ case 3:
+ rettype = init_type (TYPE_CODE_INT, 2, 0, "short", NULL);
+ break;
+ case 4:
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "long", NULL);
+ break;
+ case 5:
+ rettype = init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED,
+ "unsigned char", NULL);
+ break;
+ case 6:
+ rettype = init_type (TYPE_CODE_INT, 1, 0, "signed char", NULL);
+ break;
+ case 7:
+ rettype = init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED,
+ "unsigned short", NULL);
+ break;
+ case 8:
+ rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
+ "unsigned int", NULL);
+ break;
+ case 9:
+ rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
+ "unsigned", NULL);
+ case 10:
+ rettype = init_type (TYPE_CODE_INT, 4, TYPE_FLAG_UNSIGNED,
+ "unsigned long", NULL);
+ break;
+ case 11:
+ rettype = init_type (TYPE_CODE_VOID, 1, 0, "void", NULL);
+ break;
+ case 12:
+ /* IEEE single precision (32 bit). */
+ rettype = init_type (TYPE_CODE_FLT, 4, 0, "float", NULL);
+ break;
+ case 13:
+ /* IEEE double precision (64 bit). */
+ rettype = init_type (TYPE_CODE_FLT, 8, 0, "double", NULL);
+ break;
+ case 14:
+ /* This is an IEEE double on the RS/6000, and different machines with
+ different sizes for "long double" should use different negative
+ type numbers. See stabs.texinfo. */
+ rettype = init_type (TYPE_CODE_FLT, 8, 0, "long double", NULL);
+ break;
+ case 15:
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "integer", NULL);
+ break;
+ case 16:
+ rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
+ "boolean", NULL);
+ break;
+ case 17:
+ rettype = init_type (TYPE_CODE_FLT, 4, 0, "short real", NULL);
+ break;
+ case 18:
+ rettype = init_type (TYPE_CODE_FLT, 8, 0, "real", NULL);
+ break;
+ case 19:
+ rettype = init_type (TYPE_CODE_ERROR, 0, 0, "stringptr", NULL);
+ break;
+ case 20:
+ rettype = init_type (TYPE_CODE_CHAR, 1, TYPE_FLAG_UNSIGNED,
+ "character", NULL);
+ break;
+ case 21:
+ rettype = init_type (TYPE_CODE_BOOL, 1, TYPE_FLAG_UNSIGNED,
+ "logical*1", NULL);
+ break;
+ case 22:
+ rettype = init_type (TYPE_CODE_BOOL, 2, TYPE_FLAG_UNSIGNED,
+ "logical*2", NULL);
+ break;
+ case 23:
+ rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
+ "logical*4", NULL);
+ break;
+ case 24:
+ rettype = init_type (TYPE_CODE_BOOL, 4, TYPE_FLAG_UNSIGNED,
+ "logical", NULL);
+ break;
+ case 25:
+ /* Complex type consisting of two IEEE single precision values. */
+ rettype = init_type (TYPE_CODE_ERROR, 8, 0, "complex", NULL);
+ break;
+ case 26:
+ /* Complex type consisting of two IEEE double precision values. */
+ rettype = init_type (TYPE_CODE_ERROR, 16, 0, "double complex", NULL);
+ break;
+ case 27:
+ rettype = init_type (TYPE_CODE_INT, 1, 0, "integer*1", NULL);
+ break;
+ case 28:
+ rettype = init_type (TYPE_CODE_INT, 2, 0, "integer*2", NULL);
+ break;
+ case 29:
+ rettype = init_type (TYPE_CODE_INT, 4, 0, "integer*4", NULL);
+ break;
+ case 30:
+ rettype = init_type (TYPE_CODE_CHAR, 2, 0, "wchar", NULL);
+ break;
+ case 31:
+ rettype = init_type (TYPE_CODE_INT, 8, 0, "long long", NULL);
+ break;
+ case 32:
+ rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
+ "unsigned long long", NULL);
+ break;
+ case 33:
+ rettype = init_type (TYPE_CODE_INT, 8, TYPE_FLAG_UNSIGNED,
+ "logical*8", NULL);
+ break;
+ case 34:
+ rettype = init_type (TYPE_CODE_INT, 8, 0, "integer*8", NULL);
+ break;
+ }
+ negative_types[-typenum] = rettype;
+ return rettype;
+}
+
+/* This page contains subroutines of read_type. */
+
+#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:
+
+ NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ;
+
+ An example with two member functions is:
+
+ afunc1::20=##15;:i;2A.;afunc2::20:i;2A.;
+
+ For the case of overloaded operators, the format is op$::*.funcs, where
+ $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
+ name (such as `+=') and `.' marks the end of the operator name.
+
+ Returns 1 for success, 0 for failure. */
+
+static int
+read_member_functions (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ int nfn_fields = 0;
+ int length = 0;
+ /* Total number of member functions defined in this class. If the class
+ defines two `f' functions, and one `g' function, then this will have
+ the value 3. */
+ int total_length = 0;
+ int i;
+ struct next_fnfield
+ {
+ struct next_fnfield *next;
+ struct fn_field fn_field;
+ } *sublist;
+ struct type *look_ahead_type;
+ struct next_fnfieldlist *new_fnlist;
+ struct next_fnfield *new_sublist;
+ char *main_fn_name;
+ register char *p;
+
+ /* Process each list until we find something that is not a member function
+ or find the end of the functions. */
+
+ while (**pp != ';')
+ {
+ /* We should be positioned at the start of the function name.
+ Scan forward to find the first ':' and if it is not the
+ first of a "::" delimiter, then this is not a member function. */
+ p = *pp;
+ while (*p != ':')
+ {
+ p++;
+ }
+ if (p[1] != ':')
+ {
+ break;
+ }
+
+ sublist = NULL;
+ look_ahead_type = NULL;
+ length = 0;
+
+ new_fnlist = (struct next_fnfieldlist *)
+ xmalloc (sizeof (struct next_fnfieldlist));
+ make_cleanup (free, new_fnlist);
+ memset (new_fnlist, 0, sizeof (struct next_fnfieldlist));
+
+ if ((*pp)[0] == 'o' && (*pp)[1] == 'p' && is_cplus_marker ((*pp)[2]))
+ {
+ /* This is a completely wierd case. In order to stuff in the
+ names that might contain colons (the usual name delimiter),
+ Mike Tiemann defined a different name format which is
+ signalled if the identifier is "op$". In that case, the
+ format is "op$::XXXX." where XXXX is the name. This is
+ used for names like "+" or "=". YUUUUUUUK! FIXME! */
+ /* This lets the user type "break operator+".
+ We could just put in "+" as the name, but that wouldn't
+ work for "*". */
+ static char opname[32] = {'o', 'p', CPLUS_MARKER};
+ char *o = opname + 3;
+
+ /* Skip past '::'. */
+ *pp = p + 2;
+
+ STABS_CONTINUE (pp, objfile);
+ p = *pp;
+ while (*p != '.')
+ {
+ *o++ = *p++;
+ }
+ main_fn_name = savestring (opname, o - opname);
+ /* Skip past '.' */
+ *pp = p + 1;
+ }
+ else
+ {
+ main_fn_name = savestring (*pp, p - *pp);
+ /* Skip past '::'. */
+ *pp = p + 2;
+ }
+ new_fnlist -> fn_fieldlist.name = main_fn_name;
+
+ do
+ {
+ new_sublist =
+ (struct next_fnfield *) xmalloc (sizeof (struct next_fnfield));
+ make_cleanup (free, new_sublist);
+ memset (new_sublist, 0, sizeof (struct next_fnfield));
+
+ /* Check for and handle cretinous dbx symbol name continuation! */
+ if (look_ahead_type == NULL)
+ {
+ /* Normal case. */
+ STABS_CONTINUE (pp, objfile);
+
+ new_sublist -> fn_field.type = read_type (pp, objfile);
+ if (**pp != ':')
+ {
+ /* Invalid symtab info for member function. */
+ return 0;
+ }
+ }
+ else
+ {
+ /* g++ version 1 kludge */
+ new_sublist -> fn_field.type = look_ahead_type;
+ look_ahead_type = NULL;
+ }
+
+ (*pp)++;
+ p = *pp;
+ while (*p != ';')
+ {
+ p++;
+ }
+
+ /* If this is just a stub, then we don't have the real name here. */
+
+ if (TYPE_FLAGS (new_sublist -> fn_field.type) & TYPE_FLAG_STUB)
+ {
+ if (!TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type))
+ TYPE_DOMAIN_TYPE (new_sublist -> fn_field.type) = type;
+ new_sublist -> fn_field.is_stub = 1;
+ }
+ new_sublist -> fn_field.physname = savestring (*pp, p - *pp);
+ *pp = p + 1;
+
+ /* Set this member function's visibility fields. */
+ switch (*(*pp)++)
+ {
+ case VISIBILITY_PRIVATE:
+ new_sublist -> fn_field.is_private = 1;
+ break;
+ case VISIBILITY_PROTECTED:
+ new_sublist -> fn_field.is_protected = 1;
+ break;
+ }
+
+ STABS_CONTINUE (pp, objfile);
+ switch (**pp)
+ {
+ case 'A': /* Normal functions. */
+ new_sublist -> fn_field.is_const = 0;
+ new_sublist -> fn_field.is_volatile = 0;
+ (*pp)++;
+ break;
+ case 'B': /* `const' member functions. */
+ new_sublist -> fn_field.is_const = 1;
+ new_sublist -> fn_field.is_volatile = 0;
+ (*pp)++;
+ break;
+ case 'C': /* `volatile' member function. */
+ new_sublist -> fn_field.is_const = 0;
+ new_sublist -> fn_field.is_volatile = 1;
+ (*pp)++;
+ break;
+ case 'D': /* `const volatile' member function. */
+ new_sublist -> fn_field.is_const = 1;
+ new_sublist -> fn_field.is_volatile = 1;
+ (*pp)++;
+ break;
+ case '*': /* File compiled with g++ version 1 -- no info */
+ case '?':
+ case '.':
+ break;
+ default:
+ complain (&const_vol_complaint, **pp);
+ break;
+ }
+
+ switch (*(*pp)++)
+ {
+ case '*':
+ {
+ int nbits;
+ /* virtual member function, followed by index.
+ The sign bit is set to distinguish pointers-to-methods
+ from virtual function indicies. Since the array is
+ in words, the quantity must be shifted left by 1
+ on 16 bit machine, and by 2 on 32 bit machine, forcing
+ the sign bit out, and usable as a valid index into
+ the array. Remove the sign bit here. */
+ new_sublist -> fn_field.voffset =
+ (0x7fffffff & read_huge_number (pp, ';', &nbits)) + 2;
+ if (nbits != 0)
+ return 0;
+
+ STABS_CONTINUE (pp, objfile);
+ if (**pp == ';' || **pp == '\0')
+ {
+ /* Must be g++ version 1. */
+ new_sublist -> fn_field.fcontext = 0;
+ }
+ else
+ {
+ /* Figure out from whence this virtual function came.
+ It may belong to virtual function table of
+ one of its baseclasses. */
+ look_ahead_type = read_type (pp, objfile);
+ if (**pp == ':')
+ {
+ /* g++ version 1 overloaded methods. */
+ }
+ else
+ {
+ new_sublist -> fn_field.fcontext = look_ahead_type;
+ if (**pp != ';')
+ {
+ return 0;
+ }
+ else
+ {
+ ++*pp;
+ }
+ look_ahead_type = NULL;
+ }
+ }
+ break;
+ }
+ case '?':
+ /* static member function. */
+ new_sublist -> fn_field.voffset = VOFFSET_STATIC;
+ if (strncmp (new_sublist -> fn_field.physname,
+ main_fn_name, strlen (main_fn_name)))
+ {
+ new_sublist -> fn_field.is_stub = 1;
+ }
+ break;
+
+ default:
+ /* error */
+ complain (&member_fn_complaint, (*pp)[-1]);
+ /* Fall through into normal member function. */
+
+ case '.':
+ /* normal member function. */
+ new_sublist -> fn_field.voffset = 0;
+ new_sublist -> fn_field.fcontext = 0;
+ break;
+ }
+
+ new_sublist -> next = sublist;
+ sublist = new_sublist;
+ length++;
+ STABS_CONTINUE (pp, objfile);
+ }
+ while (**pp != ';' && **pp != '\0');
+
+ (*pp)++;
+
+ new_fnlist -> fn_fieldlist.fn_fields = (struct fn_field *)
+ obstack_alloc (&objfile -> type_obstack,
+ sizeof (struct fn_field) * length);
+ memset (new_fnlist -> fn_fieldlist.fn_fields, 0,
+ sizeof (struct fn_field) * length);
+ for (i = length; (i--, sublist); sublist = sublist -> next)
+ {
+ new_fnlist -> fn_fieldlist.fn_fields[i] = sublist -> fn_field;
+ }
+
+ new_fnlist -> fn_fieldlist.length = length;
+ new_fnlist -> next = fip -> fnlist;
+ fip -> fnlist = new_fnlist;
+ nfn_fields++;
+ total_length += length;
+ STABS_CONTINUE (pp, objfile);
+ }
+
+ if (nfn_fields)
+ {
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
+ TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * nfn_fields);
+ memset (TYPE_FN_FIELDLISTS (type), 0,
+ sizeof (struct fn_fieldlist) * nfn_fields);
+ TYPE_NFN_FIELDS (type) = nfn_fields;
+ TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+ }
+
+ return 1;
+}
+
+/* Special GNU C++ name.
+
+ Returns 1 for success, 0 for failure. "failure" means that we can't
+ keep parsing and it's time for error_type(). */
+
+static int
+read_cpp_abbrev (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ register char *p;
+ char *name;
+ char cpp_abbrev;
+ struct type *context;
+
+ p = *pp;
+ if (*++p == 'v')
+ {
+ name = NULL;
+ cpp_abbrev = *++p;
+
+ *pp = p + 1;
+
+ /* At this point, *pp points to something like "22:23=*22...",
+ where the type number before the ':' is the "context" and
+ everything after is a regular type definition. Lookup the
+ type, find it's name, and construct the field name. */
+
+ context = read_type (pp, objfile);
+
+ switch (cpp_abbrev)
+ {
+ case 'f': /* $vf -- a virtual function table pointer */
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack, vptr_name, "", "");
+ break;
+
+ case 'b': /* $vb -- a virtual bsomethingorother */
+ name = type_name_no_tag (context);
+ if (name == NULL)
+ {
+ complain (&invalid_cpp_type_complaint, symnum);
+ name = "FOO";
+ }
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack, vb_name, name, "");
+ break;
+
+ default:
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ fip->list->field.name =
+ obconcat (&objfile->type_obstack,
+ "INVALID_CPLUSPLUS_ABBREV", "", "");
+ break;
+ }
+
+ /* At this point, *pp points to the ':'. Skip it and read the
+ field type. */
+
+ p = ++(*pp);
+ if (p[-1] != ':')
+ {
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ return 0;
+ }
+ fip->list->field.type = read_type (pp, objfile);
+ if (**pp == ',')
+ (*pp)++; /* Skip the comma. */
+ else
+ return 0;
+
+ {
+ int nbits;
+ fip->list->field.bitpos = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return 0;
+ }
+ /* This field is unpacked. */
+ fip->list->field.bitsize = 0;
+ fip->list->visibility = VISIBILITY_PRIVATE;
+ }
+ else
+ {
+ complain (&invalid_cpp_abbrev_complaint, *pp);
+ /* We have no idea what syntax an unrecognized abbrev would have, so
+ better return 0. If we returned 1, we would need to at least advance
+ *pp to avoid an infinite loop. */
+ return 0;
+ }
+ return 1;
+}
+
+static void
+read_one_struct_field (fip, pp, p, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ char *p;
+ struct type *type;
+ struct objfile *objfile;
+{
+ /* The following is code to work around cfront generated stabs.
+ The stabs contains full mangled name for each field.
+ We try to demangle the name and extract the field name out of it.
+ */
+ if (ARM_DEMANGLING && current_subfile->language == language_cplus)
+ {
+ char save_p;
+ char *dem, *dem_p;
+ save_p = *p;
+ *p = '\0';
+ dem = cplus_demangle (*pp, DMGL_ANSI | DMGL_PARAMS);
+ if (dem != NULL)
+ {
+ dem_p = strrchr (dem, ':');
+ if (dem_p != 0 && *(dem_p-1)==':')
+ dem_p++;
+ fip->list->field.name =
+ obsavestring (dem_p, strlen(dem_p), &objfile -> type_obstack);
+ }
+ else
+ {
+ fip->list->field.name =
+ obsavestring (*pp, p - *pp, &objfile -> type_obstack);
+ }
+ *p = save_p;
+ }
+ /* end of code for cfront work around */
+
+ else
+ 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)++;
+ }
+ else
+ {
+ /* normal dbx-style format, no explicit visibility */
+ fip -> list -> visibility = VISIBILITY_PUBLIC;
+ }
+
+ fip -> list -> field.type = read_type (pp, objfile);
+ if (**pp == ':')
+ {
+ p = ++(*pp);
+#if 0
+ /* Possible future hook for nested types. */
+ if (**pp == '!')
+ {
+ fip -> list -> field.bitpos = (long)-2; /* nested type */
+ p = ++(*pp);
+ }
+ else
+#endif
+ {
+ /* Static class member. */
+ fip -> list -> field.bitpos = (long) -1;
+ }
+ while (*p != ';')
+ {
+ p++;
+ }
+ fip -> list -> field.bitsize = (long) savestring (*pp, p - *pp);
+ *pp = p + 1;
+ return;
+ }
+ else if (**pp != ',')
+ {
+ /* Bad structure-type format. */
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+
+ (*pp)++; /* Skip the comma. */
+
+ {
+ int nbits;
+ fip -> list -> field.bitpos = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ {
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+ fip -> list -> field.bitsize = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ {
+ complain (&stabs_general_complaint, "bad structure-type format");
+ return;
+ }
+ }
+
+ if (fip -> list -> field.bitpos == 0 && fip -> list -> field.bitsize == 0)
+ {
+ /* 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 "<no value>" 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-> visibility = VISIBILITY_IGNORE;
+ }
+ else
+ {
+ /* 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_BOOL
+ && TYPE_CODE (fip -> list -> field.type) != TYPE_CODE_ENUM)
+ {
+ fip -> list -> field.bitsize = 0;
+ }
+ if ((fip -> list -> field.bitsize
+ == TARGET_CHAR_BIT * TYPE_LENGTH (fip -> list -> field.type)
+ || (TYPE_CODE (fip -> list -> field.type) == TYPE_CODE_ENUM
+ && (fip -> list -> field.bitsize
+ == TARGET_INT_BIT)
+ )
+ )
+ &&
+ fip -> list -> field.bitpos % 8 == 0)
+ {
+ fip -> list -> field.bitsize = 0;
+ }
+ }
+}
+
+
+/* Read struct or class data fields. They have the form:
+
+ NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
+
+ At the end, we see a semicolon instead of a field.
+
+ In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
+ a static field.
+
+ The optional VISIBILITY is one of:
+
+ '/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;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ register char *p;
+ struct nextfield *new;
+
+ /* We better set p right now, in case there are no fields at all... */
+
+ p = *pp;
+
+ /* Read each data member type until we find the terminating ';' at the end of
+ the data member list, or break for some other reason such as finding the
+ start of the member function list. */
+
+ while (**pp != ';')
+ {
+ if (os9k_stabs && **pp == ',') break;
+ STABS_CONTINUE (pp, objfile);
+ /* Get space to record the next field's data. */
+ new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (free, new);
+ memset (new, 0, sizeof (struct nextfield));
+ new -> next = fip -> list;
+ fip -> list = new;
+
+ /* 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 (is_cplus_marker (p[0]) && p[1] != '_')
+ {
+ if (!read_cpp_abbrev (fip, pp, type, objfile))
+ return 0;
+ continue;
+ }
+
+ /* Look for the ':' that separates the field name from the field
+ values. Data members are delimited by a single ':', while member
+ functions are delimited by a pair of ':'s. When we hit the member
+ functions (if any), terminate scan loop and return. */
+
+ while (*p != ':' && *p != '\0')
+ {
+ p++;
+ }
+ if (*p == '\0')
+ return 0;
+
+ /* Check to see if we have hit the member functions yet. */
+ if (p[1] == ':')
+ {
+ break;
+ }
+ read_one_struct_field (fip, pp, p, type, objfile);
+ }
+ 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. */
+ fip -> list = fip -> list -> next;
+ }
+ return 1;
+}
+
+/* The stabs for C++ derived classes contain baseclass information which
+ is marked by a '!' character after the total size. This function is
+ called when we encounter the baseclass marker, and slurps up all the
+ baseclass information.
+
+ Immediately following the '!' marker is the number of base classes that
+ the class is derived from, followed by information for each base class.
+ For each base class, there are two visibility specifiers, a bit offset
+ to the base class information within the derived class, a reference to
+ the type for the base class, and a terminating semicolon.
+
+ A typical example, with two base classes, would be "!2,020,19;0264,21;".
+ ^^ ^ ^ ^ ^ ^ ^
+ Baseclass information marker __________________|| | | | | | |
+ Number of baseclasses __________________________| | | | | | |
+ Visibility specifiers (2) ________________________| | | | | |
+ Offset in bits from start of class _________________| | | | |
+ Type number for base class ___________________________| | | |
+ Visibility specifiers (2) _______________________________| | |
+ Offset in bits from start of class ________________________| |
+ Type number of base class ____________________________________|
+
+ Return 1 for success, 0 for (error-type-inducing) failure. */
+
+static int
+read_baseclasses (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ int i;
+ struct nextfield *new;
+
+ if (**pp != '!')
+ {
+ return 1;
+ }
+ else
+ {
+ /* Skip the '!' baseclass information marker. */
+ (*pp)++;
+ }
+
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+ {
+ int nbits;
+ TYPE_N_BASECLASSES (type) = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ return 0;
+ }
+
+#if 0
+ /* Some stupid compilers have trouble with the following, so break
+ it up into simpler expressions. */
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *)
+ TYPE_ALLOC (type, B_BYTES (TYPE_N_BASECLASSES (type)));
+#else
+ {
+ int num_bytes = B_BYTES (TYPE_N_BASECLASSES (type));
+ char *pointer;
+
+ pointer = (char *) TYPE_ALLOC (type, num_bytes);
+ TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
+ }
+#endif /* 0 */
+
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), TYPE_N_BASECLASSES (type));
+
+ for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+ {
+ new = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+ make_cleanup (free, new);
+ memset (new, 0, sizeof (struct nextfield));
+ new -> next = fip -> list;
+ fip -> list = new;
+ new -> field.bitsize = 0; /* this should be an unpacked field! */
+
+ STABS_CONTINUE (pp, objfile);
+ switch (**pp)
+ {
+ case '0':
+ /* Nothing to do. */
+ break;
+ case '1':
+ SET_TYPE_FIELD_VIRTUAL (type, i);
+ break;
+ default:
+ /* 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)
+ {
+ case VISIBILITY_PRIVATE:
+ case VISIBILITY_PROTECTED:
+ case VISIBILITY_PUBLIC:
+ break;
+ default:
+ /* 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;
+ }
+ }
+
+ {
+ int nbits;
+
+ /* The remaining value is the bit offset of the portion of the object
+ corresponding to this baseclass. Always zero in the absence of
+ multiple inheritance. */
+
+ new -> field.bitpos = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ return 0;
+ }
+
+ /* The last piece of baseclass information is the type of the
+ base class. Read it, and remember it's type name as this
+ field's name. */
+
+ new -> field.type = read_type (pp, objfile);
+ new -> field.name = type_name_no_tag (new -> field.type);
+
+ /* skip trailing ';' and bump count of number of fields seen */
+ if (**pp == ';')
+ (*pp)++;
+ else
+ return 0;
+ }
+ return 1;
+}
+
+/* The tail end of stabs for C++ classes that contain a virtual function
+ pointer contains a tilde, a %, and a type number.
+ The type number refers to the base class (possibly this class itself) which
+ contains the vtable pointer for the current class.
+
+ This function is called when we have parsed all the method declarations,
+ so we can look for the vptr base class info. */
+
+static int
+read_tilde_fields (fip, pp, type, objfile)
+ struct field_info *fip;
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ register char *p;
+
+ STABS_CONTINUE (pp, objfile);
+
+ /* If we are positioned at a ';', then skip it. */
+ if (**pp == ';')
+ {
+ (*pp)++;
+ }
+
+ if (**pp == '~')
+ {
+ (*pp)++;
+
+ if (**pp == '=' || **pp == '+' || **pp == '-')
+ {
+ /* Obsolete flags that used to indicate the presence
+ of constructors and/or destructors. */
+ (*pp)++;
+ }
+
+ /* Read either a '%' or the final ';'. */
+ if (*(*pp)++ == '%')
+ {
+ /* The next number is the type number of the base class
+ (possibly our own class) which supplies the vtable for
+ this class. Parse it out, and search that class to find
+ its vtable pointer, and install those into TYPE_VPTR_BASETYPE
+ and TYPE_VPTR_FIELDNO. */
+
+ struct type *t;
+ int i;
+
+ t = read_type (pp, objfile);
+ p = (*pp)++;
+ while (*p != '\0' && *p != ';')
+ {
+ p++;
+ }
+ if (*p == '\0')
+ {
+ /* Premature end of symbol. */
+ return 0;
+ }
+
+ TYPE_VPTR_BASETYPE (type) = t;
+ if (type == t) /* Our own class provides vtbl ptr */
+ {
+ for (i = TYPE_NFIELDS (t) - 1;
+ i >= TYPE_N_BASECLASSES (t);
+ --i)
+ {
+ if (! strncmp (TYPE_FIELD_NAME (t, i), vptr_name,
+ sizeof (vptr_name) - 1))
+ {
+ TYPE_VPTR_FIELDNO (type) = i;
+ goto gotit;
+ }
+ }
+ /* Virtual function table field not found. */
+ complain (&vtbl_notfound_complaint, TYPE_NAME (type));
+ return 0;
+ }
+ else
+ {
+ TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
+ }
+
+ gotit:
+ *pp = p + 1;
+ }
+ }
+ return 1;
+}
+
+static int
+attach_fn_fields_to_type (fip, type)
+ struct field_info *fip;
+ register struct type *type;
+{
+ register int n;
+
+ for (n = TYPE_NFN_FIELDS (type);
+ fip -> fnlist != NULL;
+ fip -> fnlist = fip -> fnlist -> next)
+ {
+ --n; /* Circumvent Sun3 compiler bug */
+ TYPE_FN_FIELDLISTS (type)[n] = fip -> fnlist -> fn_fieldlist;
+ }
+ return 1;
+}
+
+/* Create the vector of fields, and record how big it is.
+ We need this info to record proper virtual function table information
+ for this class's virtual functions. */
+
+static int
+attach_fields_to_type (fip, type, objfile)
+ struct field_info *fip;
+ register struct type *type;
+ struct objfile *objfile;
+{
+ register int nfields = 0;
+ register int non_public_fields = 0;
+ register struct nextfield *scan;
+
+ /* Count up the number of fields that we have, as well as taking note of
+ whether or not there are any non-public fields, which requires us to
+ allocate and build the private_field_bits and protected_field_bits
+ bitfields. */
+
+ for (scan = fip -> list; scan != NULL; scan = scan -> next)
+ {
+ nfields++;
+ if (scan -> visibility != VISIBILITY_PUBLIC)
+ {
+ non_public_fields++;
+ }
+ }
+
+ /* Now we know how many fields there are, and whether or not there are any
+ non-public fields. Record the field count, allocate space for the
+ array of fields, and create blank visibility bitfields if necessary. */
+
+ TYPE_NFIELDS (type) = nfields;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nfields);
+ memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+
+ if (non_public_fields)
+ {
+ ALLOCATE_CPLUS_STRUCT_TYPE (type);
+
+ TYPE_FIELD_PRIVATE_BITS (type) =
+ (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+ B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+
+ 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
+ of the list, adding to the tail of the field array, so that they end
+ up in the same order in the array in which they were added to the list. */
+
+ while (nfields-- > 0)
+ {
+ TYPE_FIELD (type, nfields) = fip -> list -> field;
+ switch (fip -> list -> visibility)
+ {
+ case VISIBILITY_PRIVATE:
+ SET_TYPE_FIELD_PRIVATE (type, nfields);
+ break;
+
+ case VISIBILITY_PROTECTED:
+ SET_TYPE_FIELD_PROTECTED (type, nfields);
+ break;
+
+ case VISIBILITY_IGNORE:
+ SET_TYPE_FIELD_IGNORE (type, nfields);
+ break;
+
+ case VISIBILITY_PUBLIC:
+ break;
+
+ default:
+ /* 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;
+ }
+ return 1;
+}
+
+/* Read the description of a structure (or union type) and return an object
+ describing the type.
+
+ PP points to a character pointer that points to the next unconsumed token
+ in the the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
+ *PP will point to "4a:1,0,32;;".
+
+ TYPE points to an incomplete type that needs to be filled in.
+
+ OBJFILE points to the current objfile from which the stabs information is
+ being read. (Note that it is redundant in that TYPE also contains a pointer
+ to this same objfile, so it might be a good idea to eliminate it. FIXME).
+ */
+
+static struct type *
+read_struct_type (pp, type, objfile)
+ char **pp;
+ struct type *type;
+ struct objfile *objfile;
+{
+ struct cleanup *back_to;
+ struct field_info fi;
+
+ fi.list = NULL;
+ fi.fnlist = NULL;
+
+ back_to = make_cleanup (null_cleanup, 0);
+
+ INIT_CPLUS_SPECIFIC (type);
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+
+ /* First comes the total size in bytes. */
+
+ {
+ int nbits;
+ TYPE_LENGTH (type) = read_huge_number (pp, 0, &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+ }
+
+ /* Now read the baseclasses, if any, read the regular C struct or C++
+ class member fields, attach the fields to the type, read the C++
+ member functions, attach them to the type, and then read any tilde
+ field (baseclass specifier for the class holding the main vtable). */
+
+ if (!read_baseclasses (&fi, pp, type, objfile)
+ || !read_struct_fields (&fi, pp, type, objfile)
+ || !attach_fields_to_type (&fi, type, objfile)
+ || !read_member_functions (&fi, pp, type, objfile)
+ || !attach_fn_fields_to_type (&fi, type)
+ || !read_tilde_fields (&fi, pp, type, objfile))
+ {
+ type = error_type (pp, objfile);
+ }
+
+ do_cleanups (back_to);
+ return (type);
+}
+
+/* Read a definition of an array type,
+ and create and return a suitable type object.
+ Also creates a range type which represents the bounds of that
+ array. */
+
+static struct type *
+read_array_type (pp, type, objfile)
+ register char **pp;
+ register struct type *type;
+ struct objfile *objfile;
+{
+ struct type *index_type, *element_type, *range_type;
+ int lower, upper;
+ int adjustable = 0;
+ int nbits;
+
+ /* Format of an array type:
+ "ar<index type>;lower;upper;<array_contents_type>".
+ OS9000: "arlower,upper;<array_contents_type>".
+
+ Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
+ for these, produce a type like float[][]. */
+
+ 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, objfile);
+ ++*pp;
+ }
+
+ if (!(**pp >= '0' && **pp <= '9') && **pp != '-')
+ {
+ (*pp)++;
+ adjustable = 1;
+ }
+ lower = read_huge_number (pp, os9k_stabs ? ',' : ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ if (!(**pp >= '0' && **pp <= '9') && **pp != '-')
+ {
+ (*pp)++;
+ adjustable = 1;
+ }
+ upper = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ element_type = read_type (pp, objfile);
+
+ if (adjustable)
+ {
+ lower = 0;
+ upper = -1;
+ }
+
+ range_type =
+ create_range_type ((struct type *) NULL, index_type, lower, upper);
+ type = create_array_type (type, element_type, range_type);
+
+ return type;
+}
+
+
+/* Read a definition of an enumeration type,
+ and create and return a suitable type object.
+ Also defines the symbols that represent the values of the type. */
+
+static struct type *
+read_enum_type (pp, type, objfile)
+ register char **pp;
+ register struct type *type;
+ struct objfile *objfile;
+{
+ register char *p;
+ char *name;
+ register long n;
+ register struct symbol *sym;
+ int nsyms = 0;
+ struct pending **symlist;
+ struct pending *osyms, *syms;
+ int o_nsyms;
+ int nbits;
+ int unsigned_enum = 1;
+
+#if 0
+ /* FIXME! The stabs produced by Sun CC merrily define things that ought
+ to be file-scope, between N_FN entries, using N_LSYM. What's a mother
+ to do? For now, force all enum values to file scope. */
+ if (within_function)
+ symlist = &local_symbols;
+ else
+#endif
+ symlist = &file_symbols;
+ 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, objfile);
+ }
+
+ /* The aix4 compiler emits an extra field before the enum members;
+ my guess is it's a type of some sort. Just ignore it. */
+ if (**pp == '-')
+ {
+ /* Skip over the type. */
+ while (**pp != ':')
+ (*pp)++;
+
+ /* Skip over the colon. */
+ (*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 != ',')
+ {
+ STABS_CONTINUE (pp, objfile);
+ p = *pp;
+ while (*p != ':') p++;
+ name = obsavestring (*pp, p - *pp, &objfile -> symbol_obstack);
+ *pp = p + 1;
+ n = read_huge_number (pp, ',', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = name;
+ SYMBOL_LANGUAGE (sym) = current_subfile -> language;
+ SYMBOL_CLASS (sym) = LOC_CONST;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_VALUE (sym) = n;
+ if (n < 0)
+ unsigned_enum = 0;
+ add_symbol_to_list (sym, symlist);
+ nsyms++;
+ }
+
+ if (**pp == ';')
+ (*pp)++; /* Skip the semicolon. */
+
+ /* Now fill in the fields of the type-structure. */
+
+ TYPE_LENGTH (type) = TARGET_INT_BIT / HOST_CHAR_BIT;
+ TYPE_CODE (type) = TYPE_CODE_ENUM;
+ TYPE_FLAGS (type) &= ~TYPE_FLAG_STUB;
+ if (unsigned_enum)
+ TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+ TYPE_NFIELDS (type) = nsyms;
+ TYPE_FIELDS (type) = (struct field *)
+ TYPE_ALLOC (type, sizeof (struct field) * nsyms);
+ memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nsyms);
+
+ /* Find the symbols for the values and put them into the type.
+ The symbols can be found in the symlist that we put them on
+ to cause them to be defined. osyms contains the old value
+ of that symlist; everything up to there was defined by us. */
+ /* Note that we preserve the order of the enum constants, so
+ that in something like "enum {FOO, LAST_THING=FOO}" we print
+ FOO, not LAST_THING. */
+
+ for (syms = *symlist, n = nsyms - 1; syms; syms = syms->next)
+ {
+ int last = syms == osyms ? o_nsyms : 0;
+ int j = syms->nsyms;
+ for (; --j >= last; --n)
+ {
+ struct symbol *xsym = syms->symbol[j];
+ SYMBOL_TYPE (xsym) = type;
+ TYPE_FIELD_NAME (type, n) = SYMBOL_NAME (xsym);
+ TYPE_FIELD_VALUE (type, n) = 0;
+ TYPE_FIELD_BITPOS (type, n) = SYMBOL_VALUE (xsym);
+ TYPE_FIELD_BITSIZE (type, n) = 0;
+ }
+ if (syms == osyms)
+ break;
+ }
+
+ return type;
+}
+
+/* Sun's ACC uses a somewhat saner method for specifying the builtin
+ typedefs in every file (for int, long, etc):
+
+ type = b <signed> <width>; <offset>; <nbits>
+ signed = u or s. Possible c in addition to u or s (for char?).
+ offset = offset from high order bit to start bit of type.
+ width is # bytes in object of this type, nbits is # bits in type.
+
+ The width/offset stuff appears to be for small objects stored in
+ larger ones (e.g. `shorts' in `int' registers). We ignore it for now,
+ FIXME. */
+
+static struct type *
+read_sun_builtin_type (pp, typenums, objfile)
+ char **pp;
+ int typenums[2];
+ struct objfile *objfile;
+{
+ int type_bits;
+ int nbits;
+ int signed_type;
+
+ switch (**pp)
+ {
+ case 's':
+ signed_type = 1;
+ break;
+ case 'u':
+ signed_type = 0;
+ break;
+ default:
+ return error_type (pp, objfile);
+ }
+ (*pp)++;
+
+ /* For some odd reason, all forms of char put a c here. This is strange
+ because no other type has this honor. We can safely ignore this because
+ we actually determine 'char'acterness by the number of bits specified in
+ the descriptor. */
+
+ if (**pp == 'c')
+ (*pp)++;
+
+ /* The first number appears to be the number of bytes occupied
+ by this type, except that unsigned short is 4 instead of 2.
+ Since this information is redundant with the third number,
+ we will ignore it. */
+ read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ /* The second number is always 0, so ignore it too. */
+ read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ /* The third number is the number of bits for this type. */
+ type_bits = read_huge_number (pp, 0, &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+ /* 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 (type_bits == 0)
+ 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 *
+read_sun_floating_type (pp, typenums, objfile)
+ char **pp;
+ int typenums[2];
+ struct objfile *objfile;
+{
+ int nbits;
+ int details;
+ int nbytes;
+
+ /* The first number has more details about the type, for example
+ FN_COMPLEX. */
+ details = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ /* The second number is the number of bytes occupied by this type */
+ nbytes = read_huge_number (pp, ';', &nbits);
+ if (nbits != 0)
+ return error_type (pp, objfile);
+
+ if (details == NF_COMPLEX || details == NF_COMPLEX16
+ || details == NF_COMPLEX32)
+ /* This is a type we can't handle, but we do know the size.
+ We also will be able to give it a name. */
+ return init_type (TYPE_CODE_ERROR, nbytes, 0, NULL, objfile);
+
+ return init_type (TYPE_CODE_FLT, nbytes, 0, NULL, objfile);
+}
+
+/* Read a number from the string pointed to by *PP.
+ The value of *PP is advanced over the number.
+ If END is nonzero, the character that ends the
+ number must match END, or an error happens;
+ and that character is skipped if it does match.
+ If END is zero, *PP is left pointing to that character.
+
+ If the number fits in a long, set *BITS to 0 and return the value.
+ If not, set *BITS to be the number of bits in the number and return 0.
+
+ If encounter garbage, set *BITS to -1 and return 0. */
+
+static long
+read_huge_number (pp, end, bits)
+ char **pp;
+ int end;
+ int *bits;
+{
+ char *p = *pp;
+ int sign = 1;
+ long n = 0;
+ int radix = 10;
+ char overflow = 0;
+ int nbits = 0;
+ int c;
+ long upper_limit;
+
+ if (*p == '-')
+ {
+ sign = -1;
+ p++;
+ }
+
+ /* Leading zero means octal. GCC uses this to output values larger
+ than an int (because that would be hard in decimal). */
+ if (*p == '0')
+ {
+ radix = 8;
+ p++;
+ }
+
+ 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)
+ {
+ n *= radix;
+ n += c - '0'; /* FIXME this overflows anyway */
+ }
+ else
+ overflow = 1;
+
+ /* This depends on large values being output in octal, which is
+ what GCC does. */
+ if (radix == 8)
+ {
+ if (nbits == 0)
+ {
+ if (c == '0')
+ /* Ignore leading zeroes. */
+ ;
+ else if (c == '1')
+ nbits = 1;
+ else if (c == '2' || c == '3')
+ nbits = 2;
+ else
+ nbits = 3;
+ }
+ else
+ nbits += 3;
+ }
+ }
+ if (end)
+ {
+ if (c && c != end)
+ {
+ if (bits != NULL)
+ *bits = -1;
+ return 0;
+ }
+ }
+ else
+ --p;
+
+ *pp = p;
+ if (overflow)
+ {
+ if (nbits == 0)
+ {
+ /* Large decimal constants are an error (because it is hard to
+ count how many bits are in them). */
+ if (bits != NULL)
+ *bits = -1;
+ return 0;
+ }
+
+ /* -0x7f is the same as 0x80. So deal with it by adding one to
+ the number of bits. */
+ if (sign == -1)
+ ++nbits;
+ if (bits)
+ *bits = nbits;
+ }
+ else
+ {
+ if (bits)
+ *bits = 0;
+ return n * sign;
+ }
+ /* It's *BITS which has the interesting information. */
+ return 0;
+}
+
+static struct type *
+read_range_type (pp, typenums, objfile)
+ char **pp;
+ int typenums[2];
+ struct objfile *objfile;
+{
+ char *orig_pp = *pp;
+ int rangenums[2];
+ long n2, n3;
+ int n2bits, n3bits;
+ int self_subrange;
+ struct type *result_type;
+ struct type *index_type = NULL;
+
+ /* First comes a type we are a subrange of.
+ In C it is usually 0, 1 or the type being defined. */
+ if (read_type_number (pp, rangenums) != 0)
+ return error_type (pp, objfile);
+ self_subrange = (rangenums[0] == typenums[0] &&
+ rangenums[1] == typenums[1]);
+
+ if (**pp == '=')
+ {
+ *pp = orig_pp;
+ index_type = read_type (pp, objfile);
+ }
+
+ /* A semicolon should now follow; skip it. */
+ if (**pp == ';')
+ (*pp)++;
+
+ /* The remaining two operands are usually lower and upper bounds
+ of the range. But in some special cases they mean something else. */
+ n2 = read_huge_number (pp, ';', &n2bits);
+ n3 = read_huge_number (pp, ';', &n3bits);
+
+ if (n2bits == -1 || n3bits == -1)
+ return error_type (pp, objfile);
+
+ if (index_type)
+ goto handle_true_range;
+
+ /* If limits are huge, must be large integral type. */
+ if (n2bits != 0 || n3bits != 0)
+ {
+ char got_signed = 0;
+ char got_unsigned = 0;
+ /* Number of bits in the type. */
+ int nbits = 0;
+
+ /* Range from 0 to <large number> is an unsigned large integral type. */
+ if ((n2bits == 0 && n2 == 0) && n3bits != 0)
+ {
+ got_unsigned = 1;
+ nbits = n3bits;
+ }
+ /* Range from <large number> to <large number>-1 is a large signed
+ integral type. Take care of the case where <large number> doesn't
+ fit in a long but <large number>-1 does. */
+ else if ((n2bits != 0 && n3bits != 0 && n2bits == n3bits + 1)
+ || (n2bits != 0 && n3bits == 0
+ && (n2bits == sizeof (long) * HOST_CHAR_BIT)
+ && n3 == LONG_MAX))
+ {
+ got_signed = 1;
+ nbits = n2bits;
+ }
+
+ if (got_signed || got_unsigned)
+ {
+ return init_type (TYPE_CODE_INT, nbits / TARGET_CHAR_BIT,
+ got_unsigned ? TYPE_FLAG_UNSIGNED : 0, NULL,
+ objfile);
+ }
+ else
+ return error_type (pp, 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, 1, 0, NULL, objfile);
+
+ /* If n3 is zero and n2 is positive, we want a floating type,
+ and n2 is the width in bytes.
+
+ Fortran programs appear to use this for complex types also,
+ and they give no way to distinguish between double and single-complex!
+
+ GDB does not have complex types.
+
+ Just return the complex as a float of that size. It won't work right
+ for the complex values, but at least it makes the file loadable. */
+
+ if (n3 == 0 && n2 > 0)
+ {
+ return init_type (TYPE_CODE_FLT, n2, 0, NULL, objfile);
+ }
+
+ /* If the upper bound is -1, it must really be an unsigned int. */
+
+ else if (n2 == 0 && n3 == -1)
+ {
+ /* It is unsigned int or unsigned long. */
+ /* GCC 2.3.3 uses this for long long too, but that is just a GDB 3.5
+ compatibility hack. */
+ return init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ TYPE_FLAG_UNSIGNED, NULL, objfile);
+ }
+
+ /* Special case: char is defined (Who knows why) as a subrange of
+ itself with range 0-127. */
+ else if (self_subrange && n2 == 0 && n3 == 127)
+ return init_type (TYPE_CODE_INT, 1, 0, NULL, objfile);
+
+ else if (current_symbol && SYMBOL_LANGUAGE (current_symbol) == language_chill
+ && !self_subrange)
+ goto handle_true_range;
+
+ /* We used to do this only for subrange of self or subrange of int. */
+ else if (n2 == 0)
+ {
+ if (n3 < 0)
+ /* n3 actually gives the size. */
+ return init_type (TYPE_CODE_INT, - n3, TYPE_FLAG_UNSIGNED,
+ NULL, objfile);
+ if (n3 == 0xff)
+ return init_type (TYPE_CODE_INT, 1, TYPE_FLAG_UNSIGNED, NULL, objfile);
+ if (n3 == 0xffff)
+ return init_type (TYPE_CODE_INT, 2, TYPE_FLAG_UNSIGNED, NULL, objfile);
+
+ /* -1 is used for the upper bound of (4 byte) "unsigned int" and
+ "unsigned long", and we already checked for that,
+ so don't need to test for it here. */
+ }
+ /* I think this is for Convex "long long". Since I don't know whether
+ Convex sets self_subrange, I also accept that particular size regardless
+ of self_subrange. */
+ else if (n3 == 0 && n2 < 0
+ && (self_subrange
+ || n2 == - TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT))
+ return init_type (TYPE_CODE_INT, - n2, 0, NULL, objfile);
+ else if (n2 == -n3 -1)
+ {
+ if (n3 == 0x7f)
+ return init_type (TYPE_CODE_INT, 1, 0, NULL, objfile);
+ if (n3 == 0x7fff)
+ return init_type (TYPE_CODE_INT, 2, 0, NULL, objfile);
+ if (n3 == 0x7fffffff)
+ return init_type (TYPE_CODE_INT, 4, 0, NULL, objfile);
+ }
+
+ /* We have a real range type on our hands. Allocate space and
+ return a real pointer. */
+ handle_true_range:
+
+ if (self_subrange)
+ index_type = builtin_type_int;
+ else
+ index_type = *dbx_lookup_type (rangenums);
+ if (index_type == NULL)
+ {
+ /* Does this actually ever happen? Is that why we are worrying
+ about dealing with it rather than just calling error_type? */
+
+ static struct type *range_type_index;
+
+ complain (&range_type_base_complaint, rangenums[1]);
+ if (range_type_index == NULL)
+ range_type_index =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+ 0, "range type index type", NULL);
+ index_type = range_type_index;
+ }
+
+ result_type = create_range_type ((struct type *) NULL, index_type, n2, n3);
+ return (result_type);
+}
+
+/* Read in an argument list. This is a list of types, separated by commas
+ and terminated with END. Return the list of types read in, or (struct type
+ **)-1 if there is an error. */
+
+static struct type **
+read_args (pp, end, objfile)
+ char **pp;
+ int end;
+ struct objfile *objfile;
+{
+ /* FIXME! Remove this arbitrary limit! */
+ struct type *types[1024], **rval; /* allow for fns of 1023 parameters */
+ int n = 0;
+
+ while (**pp != end)
+ {
+ if (**pp != ',')
+ /* Invalid argument list: no ','. */
+ return (struct type **)-1;
+ (*pp)++;
+ STABS_CONTINUE (pp, objfile);
+ types[n++] = read_type (pp, objfile);
+ }
+ (*pp)++; /* get past `end' (the ':' character) */
+
+ if (n == 1)
+ {
+ rval = (struct type **) xmalloc (2 * sizeof (struct type *));
+ }
+ else if (TYPE_CODE (types[n-1]) != TYPE_CODE_VOID)
+ {
+ rval = (struct type **) xmalloc ((n + 1) * sizeof (struct type *));
+ memset (rval + n, 0, sizeof (struct type *));
+ }
+ else
+ {
+ rval = (struct type **) xmalloc (n * sizeof (struct type *));
+ }
+ memcpy (rval, types, n * sizeof (struct type *));
+ return rval;
+}
+
+/* Common block handling. */
+
+/* List of symbols declared since the last BCOMM. This list is a tail
+ of local_symbols. When ECOMM is seen, the symbols on the list
+ are noted so their proper addresses can be filled in later,
+ using the common block base address gotten from the assembler
+ stabs. */
+
+static struct pending *common_block;
+static int common_block_i;
+
+/* Name of the current common block. We get it from the BCOMM instead of the
+ ECOMM to match IBM documentation (even though IBM puts the name both places
+ like everyone else). */
+static char *common_block_name;
+
+/* Process a N_BCOMM symbol. The storage for NAME is not guaranteed
+ to remain after this function returns. */
+
+void
+common_block_start (name, objfile)
+ char *name;
+ struct objfile *objfile;
+{
+ if (common_block_name != NULL)
+ {
+ static struct complaint msg = {
+ "Invalid symbol data: common block within common block",
+ 0, 0};
+ complain (&msg);
+ }
+ common_block = local_symbols;
+ common_block_i = local_symbols ? local_symbols->nsyms : 0;
+ common_block_name = obsavestring (name, strlen (name),
+ &objfile -> symbol_obstack);
+}
+
+/* Process a N_ECOMM symbol. */
+
+void
+common_block_end (objfile)
+ struct objfile *objfile;
+{
+ /* Symbols declared since the BCOMM are to have the common block
+ start address added in when we know it. common_block and
+ common_block_i point to the first symbol after the BCOMM in
+ the local_symbols list; copy the list and hang it off the
+ symbol for the common block name for later fixup. */
+ int i;
+ struct symbol *sym;
+ struct pending *new = 0;
+ struct pending *next;
+ int j;
+
+ if (common_block_name == NULL)
+ {
+ static struct complaint msg = {"ECOMM symbol unmatched by BCOMM", 0, 0};
+ complain (&msg);
+ return;
+ }
+
+ sym = (struct symbol *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+ memset (sym, 0, sizeof (struct symbol));
+ SYMBOL_NAME (sym) = common_block_name;
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+
+ /* Now we copy all the symbols which have been defined since the BCOMM. */
+
+ /* Copy all the struct pendings before common_block. */
+ for (next = local_symbols;
+ next != NULL && next != common_block;
+ next = next->next)
+ {
+ for (j = 0; j < next->nsyms; j++)
+ add_symbol_to_list (next->symbol[j], &new);
+ }
+
+ /* Copy however much of COMMON_BLOCK we need. If COMMON_BLOCK is
+ NULL, it means copy all the local symbols (which we already did
+ above). */
+
+ if (common_block != NULL)
+ for (j = common_block_i; j < common_block->nsyms; j++)
+ add_symbol_to_list (common_block->symbol[j], &new);
+
+ SYMBOL_TYPE (sym) = (struct type *) new;
+
+ /* Should we be putting local_symbols back to what it was?
+ Does it matter? */
+
+ i = hashname (SYMBOL_NAME (sym));
+ SYMBOL_VALUE_CHAIN (sym) = global_sym_chain[i];
+ global_sym_chain[i] = sym;
+ common_block_name = NULL;
+}
+
+/* Add a common block's start address to the offset of each symbol
+ declared to be in it (by being between a BCOMM/ECOMM pair that uses
+ the common block name). */
+
+static void
+fix_common_block (sym, valu)
+ struct symbol *sym;
+ int valu;
+{
+ struct pending *next = (struct pending *) SYMBOL_TYPE (sym);
+ for ( ; next; next = next->next)
+ {
+ register int j;
+ for (j = next->nsyms - 1; j >= 0; j--)
+ SYMBOL_VALUE_ADDRESS (next->symbol[j]) += valu;
+ }
+}
+
+
+
+/* What about types defined as forward references inside of a small lexical
+ scope? */
+/* Add a type to the list of undefined types to be checked through
+ once this file has been read in. */
+
+void
+add_undefined_type (type)
+ struct type *type;
+{
+ if (undef_types_length == undef_types_allocated)
+ {
+ undef_types_allocated *= 2;
+ undef_types = (struct type **)
+ xrealloc ((char *) undef_types,
+ undef_types_allocated * sizeof (struct type *));
+ }
+ undef_types[undef_types_length++] = type;
+}
+
+/* Go through each undefined type, see if it's still undefined, and fix it
+ up if possible. We have two kinds of undefined types:
+
+ TYPE_CODE_ARRAY: Array whose target type wasn't defined yet.
+ Fix: update array length using the element bounds
+ and the target type's length.
+ TYPE_CODE_STRUCT, TYPE_CODE_UNION: Structure whose fields were not
+ yet defined at the time a pointer to it was made.
+ Fix: Do a full lookup on the struct/union tag. */
+void
+cleanup_undefined_types ()
+{
+ struct type **type;
+
+ for (type = undef_types; type < undef_types + undef_types_length; type++)
+ {
+ switch (TYPE_CODE (*type))
+ {
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_ENUM:
+ {
+ /* Check if it has been defined since. Need to do this here
+ as well as in check_typedef 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;
+ int i;
+ /* Name of the type, without "struct" or "union" */
+ char *typename = TYPE_TAG_NAME (*type);
+
+ if (typename == NULL)
+ {
+ static struct complaint msg = {"need a type name", 0, 0};
+ complain (&msg);
+ break;
+ }
+ for (ppt = file_symbols; ppt; ppt = ppt->next)
+ {
+ for (i = 0; i < ppt->nsyms; i++)
+ {
+ struct symbol *sym = ppt->symbol[i];
+
+ if (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ && SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE
+ && (TYPE_CODE (SYMBOL_TYPE (sym)) ==
+ TYPE_CODE (*type))
+ && STREQ (SYMBOL_NAME (sym), typename))
+ {
+ memcpy (*type, SYMBOL_TYPE (sym),
+ sizeof (struct type));
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ {
+ static struct complaint msg = {"\
+GDB internal error. cleanup_undefined_types with bad type %d.", 0, 0};
+ complain (&msg, TYPE_CODE (*type));
+ }
+ break;
+ }
+ }
+
+ undef_types_length = 0;
+}
+
+/* Scan through all of the global symbols defined in the object file,
+ assigning values to the debugging symbols that need to be assigned
+ to. Get these symbols from the minimal symbol table. */
+
+void
+scan_file_globals (objfile)
+ struct objfile *objfile;
+{
+ int hash;
+ struct minimal_symbol *msymbol;
+ struct symbol *sym, *prev;
+
+ /* Avoid expensive loop through all minimal symbols if there are
+ no unresolved symbols. */
+ for (hash = 0; hash < HASHSIZE; hash++)
+ {
+ if (global_sym_chain[hash])
+ break;
+ }
+ if (hash >= HASHSIZE)
+ return;
+
+ for (msymbol = objfile -> msymbols;
+ msymbol && SYMBOL_NAME (msymbol) != NULL;
+ msymbol++)
+ {
+ QUIT;
+
+ /* Skip static symbols. */
+ switch (MSYMBOL_TYPE (msymbol))
+ {
+ case mst_file_text:
+ case mst_file_data:
+ case mst_file_bss:
+ continue;
+ default:
+ break;
+ }
+
+ prev = NULL;
+
+ /* Get the hash index and check all the symbols
+ under that hash index. */
+
+ hash = hashname (SYMBOL_NAME (msymbol));
+
+ for (sym = global_sym_chain[hash]; sym;)
+ {
+ if (SYMBOL_NAME (msymbol)[0] == SYMBOL_NAME (sym)[0] &&
+ STREQ(SYMBOL_NAME (msymbol) + 1, SYMBOL_NAME (sym) + 1))
+ {
+ /* Splice this symbol out of the hash chain and
+ assign the value we have to it. */
+ if (prev)
+ {
+ SYMBOL_VALUE_CHAIN (prev) = SYMBOL_VALUE_CHAIN (sym);
+ }
+ else
+ {
+ global_sym_chain[hash] = SYMBOL_VALUE_CHAIN (sym);
+ }
+
+ /* Check to see whether we need to fix up a common block. */
+ /* Note: this code might be executed several times for
+ the same symbol if there are multiple references. */
+
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ fix_common_block (sym, SYMBOL_VALUE_ADDRESS (msymbol));
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (sym) = SYMBOL_VALUE_ADDRESS (msymbol);
+ }
+
+ SYMBOL_SECTION (sym) = SYMBOL_SECTION (msymbol);
+
+ if (prev)
+ {
+ sym = SYMBOL_VALUE_CHAIN (prev);
+ }
+ else
+ {
+ sym = global_sym_chain[hash];
+ }
+ }
+ else
+ {
+ prev = sym;
+ sym = SYMBOL_VALUE_CHAIN (sym);
+ }
+ }
+ }
+
+ /* Change the storage class of any remaining unresolved globals to
+ LOC_UNRESOLVED and remove them from the chain. */
+ for (hash = 0; hash < HASHSIZE; hash++)
+ {
+ sym = global_sym_chain[hash];
+ while (sym)
+ {
+ prev = sym;
+ sym = SYMBOL_VALUE_CHAIN (sym);
+
+ /* Change the symbol address from the misleading chain value
+ to address zero. */
+ SYMBOL_VALUE_ADDRESS (prev) = 0;
+
+ /* Complain about unresolved common block symbols. */
+ if (SYMBOL_CLASS (prev) == LOC_STATIC)
+ SYMBOL_CLASS (prev) = LOC_UNRESOLVED;
+ else
+ complain (&unresolved_sym_chain_complaint,
+ objfile->name, SYMBOL_NAME (prev));
+ }
+ }
+ memset (global_sym_chain, 0, sizeof (global_sym_chain));
+}
+
+/* Initialize anything that needs initializing when starting to read
+ a fresh piece of a symbol file, e.g. reading in the stuff corresponding
+ to a psymtab. */
+
+void
+stabsread_init ()
+{
+}
+
+/* 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). */
+
+void
+stabsread_new_init ()
+{
+ /* Empty the hash table of global syms looking for values. */
+ memset (global_sym_chain, 0, sizeof (global_sym_chain));
+}
+
+/* Initialize anything that needs initializing at the same time as
+ start_symtab() is called. */
+
+void start_stabs ()
+{
+ global_stabs = NULL; /* AIX COFF */
+ /* Leave FILENUM of 0 free for builtin types and this file's types. */
+ n_this_object_header_files = 1;
+ type_vector_length = 0;
+ type_vector = (struct type **) 0;
+
+ /* FIXME: If common_block_name is not already NULL, we should complain(). */
+ common_block_name = NULL;
+
+ os9k_stabs = 0;
+}
+
+/* Call after end_symtab() */
+
+void end_stabs ()
+{
+ if (type_vector)
+ {
+ free ((char *) type_vector);
+ }
+ type_vector = 0;
+ type_vector_length = 0;
+ previous_stab_code = 0;
+}
+
+void
+finish_global_stabs (objfile)
+ struct objfile *objfile;
+{
+ if (global_stabs)
+ {
+ patch_block_stabs (global_symbols, global_stabs, objfile);
+ free ((PTR) global_stabs);
+ global_stabs = NULL;
+ }
+}
+
+/* Initializer for this module */
+
+void
+_initialize_stabsread ()
+{
+ undef_types_allocated = 20;
+ undef_types_length = 0;
+ undef_types = (struct type **)
+ xmalloc (undef_types_allocated * sizeof (struct type *));
+}
diff --git a/contrib/gdb/gdb/stabsread.h b/contrib/gdb/gdb/stabsread.h
new file mode 100644
index 0000000..b348738
--- /dev/null
+++ b/contrib/gdb/gdb/stabsread.h
@@ -0,0 +1,225 @@
+/* Include file for stabs debugging format support functions.
+ Copyright 1986-1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Definitions, prototypes, etc for stabs debugging format support
+ functions.
+
+ Variables declared in this file can be defined by #define-ing
+ the name EXTERN to null. It is used to declare variables that
+ are normally extern, but which get defined in a single module
+ using this technique. */
+
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
+/* Convert stab register number (from `r' declaration) to a gdb REGNUM. */
+
+#ifndef STAB_REG_TO_REGNUM
+#define STAB_REG_TO_REGNUM(VALUE) (VALUE)
+#endif
+
+/* Hash table of global symbols whose values are not known yet.
+ They are chained thru the SYMBOL_VALUE_CHAIN, since we don't
+ 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, and
+ the such LOC_BLOCK symbols use their fields in nonstandard ways. */
+
+EXTERN struct symbol *global_sym_chain[HASHSIZE];
+
+extern void common_block_start PARAMS ((char *, struct objfile *));
+extern void common_block_end PARAMS ((struct objfile *));
+
+/* Kludge for xcoffread.c */
+
+struct pending_stabs
+{
+ int count;
+ int length;
+ char *stab[1];
+};
+
+EXTERN struct pending_stabs *global_stabs;
+
+/* The type code that process_one_symbol saw on its previous invocation.
+ Used to detect pairs of N_SO symbols. */
+
+EXTERN int previous_stab_code;
+
+/* Support for Sun changes to dbx symbol format */
+
+/* For each identified header file, we have a table of types defined
+ in that header file.
+
+ header_files maps header file names to their type tables.
+ It is a vector of n_header_files elements.
+ Each element describes one header file.
+ It contains a vector of types.
+
+ Sometimes it can happen that the same header file produces
+ different results when included in different places.
+ This can result from conditionals or from different
+ things done before including the file.
+ When this happens, there are multiple entries for the file in this table,
+ one entry for each distinct set of results.
+ The entries are distinguished by the INSTANCE field.
+ The INSTANCE field appears in the N_BINCL and N_EXCL symbol table and is
+ used to match header-file references to their corresponding data. */
+
+struct header_file
+{
+
+ /* Name of header file */
+
+ char *name;
+
+ /* Numeric code distinguishing instances of one header file that produced
+ different results when included. It comes from the N_BINCL or N_EXCL. */
+
+ int instance;
+
+ /* Pointer to vector of types */
+
+ struct type **vector;
+
+ /* Allocated length (# elts) of that vector */
+
+ int length;
+
+};
+
+EXTERN struct header_file *header_files;
+
+EXTERN int n_header_files;
+
+EXTERN int n_allocated_header_files;
+
+/* Within each object file, various header files are assigned numbers.
+ A type is defined or referred to with a pair of numbers
+ (FILENUM,TYPENUM) where FILENUM is the number of the header file
+ and TYPENUM is the number within that header file.
+ TYPENUM is the index within the vector of types for that header file.
+
+ FILENUM == 1 is special; it refers to the main source of the object file,
+ and not to any header file. FILENUM != 1 is interpreted by looking it up
+ in the following table, which contains indices in header_files. */
+
+EXTERN int *this_object_header_files;
+
+EXTERN int n_this_object_header_files;
+
+EXTERN int n_allocated_this_object_header_files;
+
+extern struct complaint unknown_symtype_complaint;
+extern struct complaint unknown_symchar_complaint;
+
+extern struct type *
+read_type PARAMS ((char **, struct objfile *));
+
+extern void
+cleanup_undefined_types PARAMS ((void));
+
+extern struct type **
+dbx_lookup_type PARAMS ((int [2]));
+
+extern long
+read_number PARAMS ((char **, int));
+
+extern void
+add_undefined_type PARAMS ((struct type *));
+
+extern struct symbol *
+define_symbol PARAMS ((CORE_ADDR, char *, int, int, struct objfile *));
+
+extern void
+stabsread_init PARAMS ((void));
+
+extern void
+stabsread_new_init PARAMS ((void));
+
+extern void
+start_stabs PARAMS ((void));
+
+extern void
+end_stabs PARAMS ((void));
+
+extern void
+finish_global_stabs PARAMS ((struct objfile *objfile));
+
+EXTERN int os9k_stabs;
+
+/* COFF files can have multiple .stab sections, if they are linked
+ using --split-by-reloc. This linked list is used to pass the
+ information into the functions in dbxread.c. */
+struct stab_section_list
+{
+ /* Next in list. */
+ struct stab_section_list *next;
+
+ /* Stab section. */
+ asection *section;
+};
+
+/* Functions exported by dbxread.c. These are not in stabsread.c because
+ they are only used by some stabs readers. */
+
+extern struct partial_symtab *
+start_psymtab PARAMS ((struct objfile *, struct section_offsets *, char *,
+ CORE_ADDR, int, struct partial_symbol **,
+ struct partial_symbol **));
+
+extern struct partial_symtab *
+end_psymtab PARAMS ((struct partial_symtab *, char **, int, int, CORE_ADDR,
+ struct partial_symtab **, int));
+
+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 coffstab_build_psymtabs
+ PARAMS ((struct objfile *objfile,
+ struct section_offsets *section_offsets,
+ int mainline,
+ CORE_ADDR textaddr, unsigned int textsize,
+ struct stab_section_list *stabs,
+ 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/contrib/gdb/gdb/stack.c b/contrib/gdb/gdb/stack.c
new file mode 100644
index 0000000..be52e98
--- /dev/null
+++ b/contrib/gdb/gdb/stack.c
@@ -0,0 +1,1502 @@
+/* Print and select stack frames for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "value.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "language.h"
+#include "frame.h"
+#include "gdbcmd.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "breakpoint.h"
+#include "demangle.h"
+#include "inferior.h"
+#include "annotate.h"
+#include "symfile.h"
+#include "objfiles.h"
+
+static void return_command PARAMS ((char *, int));
+
+static void down_command PARAMS ((char *, int));
+
+static void down_silently_command PARAMS ((char *, int));
+
+static void up_command PARAMS ((char *, int));
+
+static void up_silently_command PARAMS ((char *, int));
+
+static void frame_command PARAMS ((char *, int));
+
+static void select_frame_command PARAMS ((char *, int));
+
+static void args_info PARAMS ((char *, int));
+
+static void print_frame_arg_vars PARAMS ((struct frame_info *, GDB_FILE *));
+
+static void catch_info PARAMS ((char *, int));
+
+static void locals_info PARAMS ((char *, int));
+
+static void print_frame_label_vars PARAMS ((struct frame_info *, int,
+ GDB_FILE *));
+
+static void print_frame_local_vars PARAMS ((struct frame_info *, GDB_FILE *));
+
+static int print_block_frame_labels PARAMS ((struct block *, int *,
+ GDB_FILE *));
+
+static int print_block_frame_locals PARAMS ((struct block *,
+ struct frame_info *,
+ GDB_FILE *));
+
+static void backtrace_command PARAMS ((char *, int));
+
+static struct frame_info *parse_frame_specification PARAMS ((char *));
+
+static void frame_info PARAMS ((char *, int));
+
+extern int addressprint; /* Print addresses, or stay symbolic only? */
+extern int info_verbose; /* Verbosity of symbol reading msgs */
+extern int lines_to_list; /* # of lines "list" command shows by default */
+
+/* The "selected" stack frame is used by default for local and arg access.
+ May be zero, for no selected frame. */
+
+struct frame_info *selected_frame;
+
+/* Level of the selected frame:
+ 0 for innermost, 1 for its caller, ...
+ or -1 for frame specified by address with no defined level. */
+
+int selected_frame_level;
+
+/* 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 annotation_level = 0;
+
+
+struct print_stack_frame_args {
+ struct frame_info *fi;
+ int level;
+ int source;
+ int args;
+};
+
+static int print_stack_frame_stub PARAMS ((char *));
+
+/* Pass the args the way catch_errors wants them. */
+static int
+print_stack_frame_stub (args)
+ char *args;
+{
+ struct print_stack_frame_args *p = (struct print_stack_frame_args *)args;
+
+ print_frame_info (p->fi, p->level, p->source, p->args);
+ return 0;
+}
+
+/* Print a stack frame briefly. FRAME_INFI should be the frame info
+ and LEVEL should be its level in the stack (or -1 for level not defined).
+ This prints the level, the function executing, the arguments,
+ and the file name and line number.
+ If the pc is not at the beginning of the source line,
+ the actual pc is printed at the beginning.
+
+ If SOURCE is 1, print the source line as well.
+ If SOURCE is -1, print ONLY the source line. */
+
+void
+print_stack_frame (fi, level, source)
+ struct frame_info *fi;
+ int level;
+ int source;
+{
+ struct print_stack_frame_args args;
+
+ args.fi = fi;
+ args.level = level;
+ args.source = source;
+ args.args = 1;
+
+ catch_errors (print_stack_frame_stub, (char *)&args, "", RETURN_MASK_ALL);
+}
+
+struct print_args_args {
+ struct symbol *func;
+ struct frame_info *fi;
+};
+
+static int print_args_stub PARAMS ((char *));
+
+/* Pass the args the way catch_errors wants them. */
+
+static int
+print_args_stub (args)
+ char *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, 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;
+ register int level;
+ int source;
+ int args;
+{
+ struct symtab_and_line sal;
+ 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);
+ sp = extract_address (buf, REGISTER_RAW_SIZE (SP_REGNUM));
+
+ /* This is not a perfect test, because if a function alloca's some
+ memory, puts some code there, and then jumps into it, then the test
+ 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 ("<function called from gdb>\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 ("<signal handler called>\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 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
+ && !frame_in_dummy (fi->next));
+
+ func = find_pc_function (fi->pc);
+ if (func)
+ {
+ /* In certain pathological cases, the symtabs give the wrong
+ function (when we are in the first function in a file which
+ is compiled without debugging symbols, the previous function
+ is compiled with debugging symbols, and the "foo.o" symbol
+ that is supposed to tell us where the file with debugging symbols
+ ends has been truncated by ar because it is longer than 15
+ characters). This also occurs if the user uses asm() to create
+ a function but not stabs for it (in a file compiled -g).
+
+ So look in the minimal symbol tables as well, and if it comes
+ up with a larger address for the function use that instead.
+ I don't think this can ever cause any problems; there shouldn't
+ be any minimal symbols in the middle of a function; if this is
+ ever changed many parts of GDB will need to be changed (and we'll
+ create a find_pc_minimal_function or some such). */
+
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL
+ && (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;
+ funname = SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ else
+ {
+ funname = SYMBOL_NAME (func);
+ funlang = SYMBOL_LANGUAGE (func);
+ }
+ }
+ else
+ {
+ if (find_pc_section (fi->pc))
+ {
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL)
+ {
+ funname = SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ }
+ }
+
+ 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)
+ {
+ 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 (" ");
+ annotate_frame_args ();
+ fputs_filtered (" (", gdb_stdout);
+ if (args)
+ {
+ struct print_args_args args;
+ args.fi = fi;
+ args.func = func;
+ catch_errors (print_args_stub, (char *)&args, "", RETURN_MASK_ALL);
+ QUIT;
+ }
+ printf_filtered (")");
+ if (sal.symtab && sal.symtab->filename)
+ {
+ annotate_frame_source_begin ();
+ wrap_here (" ");
+ 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)
+ {
+ annotate_frame_where ();
+ wrap_here (" ");
+ printf_filtered (" from %s", PC_LOAD_SEGMENT (fi->pc));
+ }
+#endif
+#ifdef PC_SOLIB
+ if (!funname)
+ {
+ char *lib = PC_SOLIB (fi->pc);
+ if (lib)
+ {
+ annotate_frame_where ();
+ wrap_here (" ");
+ printf_filtered (" from %s", lib);
+ }
+ }
+#endif
+ printf_filtered ("\n");
+ }
+
+ if ((source != 0) && sal.symtab)
+ {
+ int done = 0;
+ int mid_statement = source < 0 && fi->pc != sal.pc;
+ if (annotation_level)
+ done = identify_source_line (sal.symtab, sal.line, mid_statement,
+ fi->pc);
+ if (!done)
+ {
+ if (addressprint && mid_statement)
+ {
+ print_address_numeric (fi->pc, 1, gdb_stdout);
+ printf_filtered ("\t");
+ }
+ if (print_frame_info_listing_hook)
+ print_frame_info_listing_hook (sal.symtab, sal.line, sal.line + 1, 0);
+ else
+ print_source_lines (sal.symtab, sal.line, sal.line + 1, 0);
+ }
+ current_source_line = max (sal.line - lines_to_list/2, 1);
+ }
+ if (source != 0)
+ set_default_breakpoint (1, fi->pc, sal.symtab, sal.line);
+
+ annotate_frame_end ();
+
+ gdb_flush (gdb_stdout);
+}
+
+/* Read a frame specification in whatever the appropriate format is.
+ Call error() if the specification is in any way invalid (i.e.
+ this function never returns NULL). */
+
+static struct frame_info *
+parse_frame_specification (frame_exp)
+ char *frame_exp;
+{
+ int numargs = 0;
+#define MAXARGS 4
+ CORE_ADDR args[MAXARGS];
+
+ if (frame_exp)
+ {
+ char *addr_string, *p;
+ struct cleanup *tmp_cleanup;
+
+ while (*frame_exp == ' ') frame_exp++;
+
+ while (*frame_exp)
+ {
+ if (numargs > MAXARGS)
+ error ("Too many args in frame specification");
+ /* Parse an argument. */
+ for (p = frame_exp; *p && *p != ' '; p++)
+ ;
+ addr_string = savestring(frame_exp, p - frame_exp);
+
+ {
+ tmp_cleanup = make_cleanup (free, addr_string);
+ args[numargs++] = parse_and_eval_address (addr_string);
+ do_cleanups (tmp_cleanup);
+ }
+
+ /* Skip spaces, move to possible next arg. */
+ while (*p == ' ') p++;
+ frame_exp = p;
+ }
+ }
+
+ switch (numargs)
+ {
+ case 0:
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ return selected_frame;
+ /* NOTREACHED */
+ case 1:
+ {
+ int level = args[0];
+ struct frame_info *fid =
+ find_relative_frame (get_current_frame (), &level);
+ struct frame_info *tfid;
+
+ if (level == 0)
+ /* 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. */
+
+ for (fid = get_current_frame ();
+ fid && fid->frame != args[0];
+ fid = get_prev_frame (fid))
+ ;
+
+ if (fid)
+ while ((tfid = get_prev_frame (fid)) &&
+ (tfid->frame == args[0]))
+ fid = tfid;
+
+ /* We couldn't identify the frame as an existing frame, but
+ perhaps we can create one with a single argument. */
+ }
+
+ default:
+#ifdef SETUP_ARBITRARY_FRAME
+ return SETUP_ARBITRARY_FRAME (numargs, args);
+#else
+ /* Usual case. Do it here rather than have everyone supply
+ a SETUP_ARBITRARY_FRAME that does this. */
+ if (numargs == 1)
+ return create_new_frame (args[0], 0);
+ error ("Too many args in frame specification");
+#endif
+ /* NOTREACHED */
+ }
+ /* NOTREACHED */
+}
+
+/* FRAME_ARGS_ADDRESS_CORRECT is just like FRAME_ARGS_ADDRESS except
+ that if it is unsure about the answer, it returns 0
+ instead of guessing (this happens on the VAX and i960, for example).
+
+ On most machines, we never have to guess about the args address,
+ so FRAME_ARGS_ADDRESS{,_CORRECT} are the same. */
+#if !defined (FRAME_ARGS_ADDRESS_CORRECT)
+#define FRAME_ARGS_ADDRESS_CORRECT FRAME_ARGS_ADDRESS
+#endif
+
+/* Print verbosely the selected frame or the frame at address ADDR.
+ This means absolutely all information in the frame is printed. */
+
+static void
+frame_info (addr_exp, from_tty)
+ char *addr_exp;
+ int from_tty;
+{
+ struct frame_info *fi;
+ struct frame_saved_regs fsr;
+ struct symtab_and_line sal;
+ struct symbol *func;
+ struct symtab *s;
+ struct frame_info *calling_frame_info;
+ int i, count, numregs;
+ char *funname = 0;
+ enum language funlang = language_unknown;
+
+ if (!target_has_stack)
+ error ("No stack.");
+
+ fi = parse_frame_specification (addr_exp);
+ if (fi == NULL)
+ error ("Invalid frame specified.");
+
+ sal = find_pc_line (fi->pc,
+ fi->next != NULL
+ && !fi->next->signal_handler_caller
+ && !frame_in_dummy (fi->next));
+ func = get_frame_function (fi);
+ s = find_pc_symtab(fi->pc);
+ if (func)
+ {
+ funname = SYMBOL_NAME (func);
+ funlang = SYMBOL_LANGUAGE (func);
+ }
+ else
+ {
+ register struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (fi->pc);
+ if (msymbol != NULL)
+ {
+ funname = SYMBOL_NAME (msymbol);
+ funlang = SYMBOL_LANGUAGE (msymbol);
+ }
+ }
+ calling_frame_info = get_prev_frame (fi);
+
+ if (!addr_exp && selected_frame_level >= 0)
+ {
+ printf_filtered ("Stack level %d, frame at ", selected_frame_level);
+ print_address_numeric (fi->frame, 1, gdb_stdout);
+ printf_filtered (":\n");
+ }
+ else
+ {
+ printf_filtered ("Stack frame at ");
+ print_address_numeric (fi->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 (gdb_stdout, funname, funlang,
+ DMGL_ANSI | DMGL_PARAMS);
+ }
+ wrap_here (" ");
+ if (sal.symtab)
+ printf_filtered (" (%s:%d)", sal.symtab->filename, sal.line);
+ puts_filtered ("; ");
+ wrap_here (" ");
+ printf_filtered ("saved %s ", reg_names[PC_REGNUM]);
+ print_address_numeric (FRAME_SAVED_PC (fi), 1, gdb_stdout);
+ printf_filtered ("\n");
+
+ {
+ int frameless = 0;
+#ifdef FRAMELESS_FUNCTION_INVOCATION
+ FRAMELESS_FUNCTION_INVOCATION (fi, frameless);
+#endif
+ if (frameless)
+ printf_filtered (" (FRAMELESS),");
+ }
+
+ if (calling_frame_info)
+ {
+ printf_filtered (" called by frame at ");
+ print_address_numeric (calling_frame_info->frame, 1, gdb_stdout);
+ }
+ if (fi->next && calling_frame_info)
+ puts_filtered (",");
+ wrap_here (" ");
+ if (fi->next)
+ {
+ printf_filtered (" caller of frame at ");
+ print_address_numeric (fi->next->frame, 1, gdb_stdout);
+ }
+ if (fi->next || calling_frame_info)
+ puts_filtered ("\n");
+ if (s)
+ printf_filtered (" source language %s.\n", language_str (s->language));
+
+#ifdef PRINT_EXTRA_FRAME_INFO
+ PRINT_EXTRA_FRAME_INFO (fi);
+#endif
+
+ {
+ /* Address of the argument list for this frame, or 0. */
+ CORE_ADDR arg_list = FRAME_ARGS_ADDRESS_CORRECT (fi);
+ /* Number of args for this frame, or -1 if unknown. */
+ int numargs;
+
+ if (arg_list == 0)
+ printf_filtered (" Arglist at unknown address.\n");
+ else
+ {
+ printf_filtered (" Arglist at ");
+ print_address_numeric (arg_list, 1, gdb_stdout);
+ printf_filtered (",");
+
+ FRAME_NUM_ARGS (numargs, fi);
+ if (numargs < 0)
+ puts_filtered (" args: ");
+ else if (numargs == 0)
+ puts_filtered (" no args.");
+ else if (numargs == 1)
+ puts_filtered (" 1 arg: ");
+ else
+ printf_filtered (" %d args: ", numargs);
+ print_frame_args (func, fi, numargs, gdb_stdout);
+ puts_filtered ("\n");
+ }
+ }
+ {
+ /* Address of the local variables for this frame, or 0. */
+ CORE_ADDR arg_list = FRAME_LOCALS_ADDRESS (fi);
+
+ if (arg_list == 0)
+ printf_filtered (" Locals at unknown address,");
+ else
+ {
+ 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 ");
+ print_address_numeric (fsr.regs[SP_REGNUM], 1, gdb_stdout);
+ printf_filtered ("\n");
+ count = 0;
+ numregs = ARCH_NUM_REGS;
+ for (i = 0; i < numregs; i++)
+ if (fsr.regs[i] && i != SP_REGNUM)
+ {
+ if (count == 0)
+ puts_filtered (" Saved registers:\n ");
+ else
+ puts_filtered (",");
+ wrap_here (" ");
+ 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. */
+ /* We could get some information about saved registers by calling
+ get_saved_register on each register. Which info goes with which frame
+ is necessarily lost, however, and I suspect that the users don't care
+ whether they get the info. */
+ puts_filtered ("\n");
+#endif /* Have FRAME_FIND_SAVED_REGS. */
+}
+
+#if 0
+/* Set a limit on the number of frames printed by default in a
+ backtrace. */
+
+static int backtrace_limit;
+
+static void
+set_backtrace_limit_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ int count = parse_and_eval_address (count_exp);
+
+ if (count < 0)
+ error ("Negative argument not meaningful as backtrace limit.");
+
+ backtrace_limit = count;
+}
+
+static void
+backtrace_limit_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (arg)
+ error ("\"Info backtrace-limit\" takes no arguments.");
+
+ printf_unfiltered ("Backtrace limit: %d.\n", backtrace_limit);
+}
+#endif
+
+/* Print briefly all stack frames or just the innermost COUNT frames. */
+
+static void
+backtrace_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ struct frame_info *fi;
+ register int count;
+ register int i;
+ register struct frame_info *trailing;
+ register int trailing_level;
+
+ if (!target_has_stack)
+ error ("No stack.");
+
+ /* The following code must do two things. First, it must
+ set the variable TRAILING to the frame from which we should start
+ printing. Second, it must set the variable count to the number
+ of frames which we should print, or -1 if all of them. */
+ trailing = get_current_frame ();
+ trailing_level = 0;
+ if (count_exp)
+ {
+ count = parse_and_eval_address (count_exp);
+ if (count < 0)
+ {
+ struct frame_info *current;
+
+ count = -count;
+
+ current = trailing;
+ while (current && count--)
+ {
+ QUIT;
+ current = get_prev_frame (current);
+ }
+
+ /* Will stop when CURRENT reaches the top of the stack. TRAILING
+ will be COUNT below it. */
+ while (current)
+ {
+ QUIT;
+ trailing = get_prev_frame (trailing);
+ current = get_prev_frame (current);
+ trailing_level++;
+ }
+
+ count = -1;
+ }
+ }
+ else
+ count = -1;
+
+ if (info_verbose)
+ {
+ struct partial_symtab *ps;
+
+ /* Read in symbols for all of the frames. Need to do this in
+ a separate pass so that "Reading in symbols for xxx" messages
+ don't screw up the appearance of the backtrace. Also
+ if people have strong opinions against reading symbols for
+ backtrace this may have to be an option. */
+ i = count;
+ for (fi = trailing;
+ fi != NULL && i--;
+ fi = get_prev_frame (fi))
+ {
+ QUIT;
+ ps = find_pc_psymtab (fi->pc);
+ if (ps)
+ PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in */
+ }
+ }
+
+ for (i = 0, fi = trailing;
+ fi && count--;
+ i++, fi = get_prev_frame (fi))
+ {
+ QUIT;
+
+ /* Don't use print_stack_frame; if an error() occurs it probably
+ means further attempts to backtrace would fail (on the other
+ hand, perhaps the code does or could be fixed to make sure
+ the frame->prev field gets set to NULL in that case). */
+ print_frame_info (fi, trailing_level + i, 0, 1);
+ }
+
+ /* If we've stopped before the end, mention that. */
+ if (fi && from_tty)
+ printf_filtered ("(More stack frames follow...)\n");
+}
+
+/* Print the local variables of a block B active in FRAME.
+ Return 1 if any variables were printed; 0 otherwise. */
+
+static int
+print_block_frame_locals (b, fi, stream)
+ struct block *b;
+ register struct frame_info *fi;
+ register GDB_FILE *stream;
+{
+ int nsyms;
+ register int i;
+ register struct symbol *sym;
+ register int values_printed = 0;
+
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ 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, fi, stream);
+ fprintf_filtered (stream, "\n");
+ break;
+
+ default:
+ /* Ignore symbols which are not locals. */
+ break;
+ }
+ }
+ return values_printed;
+}
+
+/* Same, but print labels. */
+
+static int
+print_block_frame_labels (b, have_default, stream)
+ struct block *b;
+ int *have_default;
+ register GDB_FILE *stream;
+{
+ int nsyms;
+ register int i;
+ register struct symbol *sym;
+ register int values_printed = 0;
+
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ if (STREQ (SYMBOL_NAME (sym), "default"))
+ {
+ if (*have_default)
+ continue;
+ *have_default = 1;
+ }
+ if (SYMBOL_CLASS (sym) == LOC_LABEL)
+ {
+ struct symtab_and_line sal;
+ sal = find_pc_line (SYMBOL_VALUE_ADDRESS (sym), 0);
+ values_printed = 1;
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream);
+ if (addressprint)
+ {
+ 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);
+ }
+ }
+ return values_printed;
+}
+
+/* Print on STREAM all the local variables in frame FRAME,
+ including all the blocks active in that frame
+ at its current pc.
+
+ Returns 1 if the job was done,
+ or 0 if nothing was printed because we have no info
+ on the function running in FRAME. */
+
+static void
+print_frame_local_vars (fi, stream)
+ register struct frame_info *fi;
+ register GDB_FILE *stream;
+{
+ register struct block *block = get_frame_block (fi);
+ register int values_printed = 0;
+
+ if (block == 0)
+ {
+ fprintf_filtered (stream, "No symbol table info available.\n");
+ return;
+ }
+
+ while (block != 0)
+ {
+ if (print_block_frame_locals (block, fi, stream))
+ values_printed = 1;
+ /* After handling the function's top-level block, stop.
+ Don't continue to its superblock, the block of
+ per-file symbols. */
+ if (BLOCK_FUNCTION (block))
+ break;
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ if (!values_printed)
+ {
+ fprintf_filtered (stream, "No locals.\n");
+ }
+}
+
+/* Same, but print labels. */
+
+static void
+print_frame_label_vars (fi, this_level_only, stream)
+ register struct frame_info *fi;
+ int this_level_only;
+ register GDB_FILE *stream;
+{
+ register struct blockvector *bl;
+ register struct block *block = get_frame_block (fi);
+ register int values_printed = 0;
+ int index, have_default = 0;
+ char *blocks_printed;
+ CORE_ADDR pc = fi->pc;
+
+ if (block == 0)
+ {
+ fprintf_filtered (stream, "No symbol table info available.\n");
+ return;
+ }
+
+ bl = blockvector_for_pc (BLOCK_END (block) - 4, &index);
+ blocks_printed = (char *) alloca (BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+ memset (blocks_printed, 0, BLOCKVECTOR_NBLOCKS (bl) * sizeof (char));
+
+ while (block != 0)
+ {
+ CORE_ADDR end = BLOCK_END (block) - 4;
+ int last_index;
+
+ if (bl != blockvector_for_pc (end, &index))
+ error ("blockvector blotch");
+ if (BLOCKVECTOR_BLOCK (bl, index) != block)
+ error ("blockvector botch");
+ last_index = BLOCKVECTOR_NBLOCKS (bl);
+ index += 1;
+
+ /* Don't print out blocks that have gone by. */
+ while (index < last_index
+ && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < pc)
+ index++;
+
+ while (index < last_index
+ && BLOCK_END (BLOCKVECTOR_BLOCK (bl, index)) < end)
+ {
+ if (blocks_printed[index] == 0)
+ {
+ if (print_block_frame_labels (BLOCKVECTOR_BLOCK (bl, index), &have_default, stream))
+ values_printed = 1;
+ blocks_printed[index] = 1;
+ }
+ index++;
+ }
+ if (have_default)
+ return;
+ if (values_printed && this_level_only)
+ return;
+
+ /* After handling the function's top-level block, stop.
+ Don't continue to its superblock, the block of
+ per-file symbols. */
+ if (BLOCK_FUNCTION (block))
+ break;
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ if (!values_printed && !this_level_only)
+ {
+ fprintf_filtered (stream, "No catches.\n");
+ }
+}
+
+/* ARGSUSED */
+static void
+locals_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_local_vars (selected_frame, gdb_stdout);
+}
+
+static void
+catch_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_label_vars (selected_frame, 0, gdb_stdout);
+}
+
+static void
+print_frame_arg_vars (fi, stream)
+ register struct frame_info *fi;
+ register GDB_FILE *stream;
+{
+ struct symbol *func = get_frame_function (fi);
+ register struct block *b;
+ int nsyms;
+ register int i;
+ register struct symbol *sym, *sym2;
+ register int values_printed = 0;
+
+ if (func == 0)
+ {
+ fprintf_filtered (stream, "No symbol table info available.\n");
+ return;
+ }
+
+ b = SYMBOL_BLOCK_VALUE (func);
+ nsyms = BLOCK_NSYMS (b);
+
+ for (i = 0; i < nsyms; i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ switch (SYMBOL_CLASS (sym))
+ {
+ case LOC_ARG:
+ case LOC_LOCAL_ARG:
+ case LOC_REF_ARG:
+ case LOC_REGPARM:
+ case LOC_REGPARM_ADDR:
+ case LOC_BASEREG_ARG:
+ values_printed = 1;
+ fputs_filtered (SYMBOL_SOURCE_NAME (sym), stream);
+ fputs_filtered (" = ", stream);
+
+ /* We have to look up the symbol because arguments can have
+ two entries (one a parameter, one a local) and the one we
+ want is the local, which lookup_symbol will find for us.
+ This includes gcc1 (not gcc2) on the sparc when passing a
+ small structure and gcc2 when the argument type is float
+ 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. */
+
+ sym2 = lookup_symbol (SYMBOL_NAME (sym),
+ b, VAR_NAMESPACE, (int *)NULL, (struct symtab **)NULL);
+ print_variable_value (sym2, fi, stream);
+ fprintf_filtered (stream, "\n");
+ break;
+
+ default:
+ /* Don't worry about things which aren't arguments. */
+ break;
+ }
+ }
+
+ if (!values_printed)
+ {
+ fprintf_filtered (stream, "No arguments.\n");
+ }
+}
+
+static void
+args_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ if (!selected_frame)
+ error ("No frame selected.");
+ print_frame_arg_vars (selected_frame, gdb_stdout);
+}
+
+/* Select frame FI, and note that its stack level is LEVEL.
+ LEVEL may be -1 if an actual level number is not known. */
+
+void
+select_frame (fi, level)
+ struct frame_info *fi;
+ int level;
+{
+ register struct symtab *s;
+
+ selected_frame = fi;
+ selected_frame_level = level;
+
+ /* Ensure that symbols for this frame are read in. Also, determine the
+ source language of this frame, and switch to it if desired. */
+ if (fi)
+ {
+ s = find_pc_symtab (fi->pc);
+ if (s
+ && s->language != current_language->la_language
+ && s->language != language_unknown
+ && language_mode == language_mode_auto) {
+ set_language(s->language);
+ }
+ }
+}
+
+/* Store the selected frame and its level into *FRAMEP and *LEVELP.
+ If there is no selected frame, *FRAMEP is set to NULL. */
+
+void
+record_selected_frame (frameaddrp, levelp)
+ CORE_ADDR *frameaddrp;
+ int *levelp;
+{
+ *frameaddrp = selected_frame ? selected_frame->frame : 0;
+ *levelp = selected_frame_level;
+}
+
+/* Return the symbol-block in which the selected frame is executing.
+ Can return zero under various legitimate circumstances. */
+
+struct block *
+get_selected_block ()
+{
+ if (!target_has_stack)
+ return 0;
+
+ if (!selected_frame)
+ return get_current_block ();
+ return get_frame_block (selected_frame);
+}
+
+/* Find a frame a certain number of levels away from FRAME.
+ LEVEL_OFFSET_PTR points to an int containing the number of levels.
+ Positive means go to earlier frames (up); negative, the reverse.
+ The int that contains the number of levels is counted toward
+ zero as the frames for those levels are found.
+ If the top or bottom frame is reached, that frame is returned,
+ but the final value of *LEVEL_OFFSET_PTR is nonzero and indicates
+ how much farther the original request asked to go. */
+
+struct frame_info *
+find_relative_frame (frame, level_offset_ptr)
+ register struct frame_info *frame;
+ register int *level_offset_ptr;
+{
+ register struct frame_info *prev;
+ register struct frame_info *frame1;
+
+ /* Going up is simple: just do get_prev_frame enough times
+ or until initial frame is reached. */
+ while (*level_offset_ptr > 0)
+ {
+ prev = get_prev_frame (frame);
+ if (prev == 0)
+ break;
+ (*level_offset_ptr)--;
+ frame = prev;
+ }
+ /* Going down is just as simple. */
+ if (*level_offset_ptr < 0)
+ {
+ while (*level_offset_ptr < 0) {
+ frame1 = get_next_frame (frame);
+ if (!frame1)
+ break;
+ frame = frame1;
+ (*level_offset_ptr)++;
+ }
+ }
+ return frame;
+}
+
+/* The "select_frame" command. With no arg, NOP.
+ With arg LEVEL_EXP, select the frame at level LEVEL if it is a
+ valid level. Otherwise, treat level_exp as an address expression
+ and select it. See parse_frame_specification for more info on proper
+ frame expressions. */
+
+/* ARGSUSED */
+static void
+select_frame_command (level_exp, from_tty)
+ char *level_exp;
+ int from_tty;
+{
+ register struct frame_info *frame, *frame1;
+ unsigned int level = 0;
+
+ if (!target_has_stack)
+ error ("No stack.");
+
+ frame = parse_frame_specification (level_exp);
+
+ /* Try to figure out what level this frame is. But if there is
+ no current stack, don't error out -- let the user set one. */
+ frame1 = 0;
+ if (get_current_frame()) {
+ for (frame1 = get_prev_frame (0);
+ frame1 && frame1 != frame;
+ frame1 = get_prev_frame (frame1))
+ level++;
+ }
+
+ if (!frame1)
+ level = 0;
+
+ select_frame (frame, level);
+}
+
+/* The "frame" command. With no arg, print selected frame briefly.
+ With arg, behaves like select_frame and then prints the selected
+ frame. */
+
+static void
+frame_command (level_exp, from_tty)
+ char *level_exp;
+ int from_tty;
+{
+ select_frame_command (level_exp, from_tty);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* Select the frame up one or COUNT stack levels
+ from the previously selected frame, and print it briefly. */
+
+/* ARGSUSED */
+static void
+up_silently_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ register struct frame_info *fi;
+ int count = 1, count1;
+ if (count_exp)
+ count = parse_and_eval_address (count_exp);
+ count1 = count;
+
+ if (target_has_stack == 0 || selected_frame == 0)
+ error ("No stack.");
+
+ fi = find_relative_frame (selected_frame, &count1);
+ if (count1 != 0 && count_exp == 0)
+ error ("Initial frame selected; you cannot go up.");
+ select_frame (fi, selected_frame_level + count - count1);
+}
+
+static void
+up_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ up_silently_command (count_exp, from_tty);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+/* Select the frame down one or COUNT stack levels
+ from the previously selected frame, and print it briefly. */
+
+/* ARGSUSED */
+static void
+down_silently_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ register struct frame_info *frame;
+ int count = -1, count1;
+ if (count_exp)
+ count = - parse_and_eval_address (count_exp);
+ count1 = count;
+
+ if (target_has_stack == 0 || selected_frame == 0)
+ error ("No stack.");
+
+ frame = find_relative_frame (selected_frame, &count1);
+ if (count1 != 0 && count_exp == 0)
+ {
+
+ /* 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);
+}
+
+
+static void
+down_command (count_exp, from_tty)
+ char *count_exp;
+ int from_tty;
+{
+ down_silently_command (count_exp, from_tty);
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+static void
+return_command (retval_exp, from_tty)
+ char *retval_exp;
+ int from_tty;
+{
+ struct symbol *thisfun;
+ CORE_ADDR selected_frame_addr;
+ CORE_ADDR selected_frame_pc;
+ struct frame_info *frame;
+ value_ptr return_value = NULL;
+
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ thisfun = get_frame_function (selected_frame);
+ selected_frame_addr = FRAME_FP (selected_frame);
+ selected_frame_pc = selected_frame->pc;
+
+ /* Compute the return value (if any -- possibly getting errors here). */
+
+ if (retval_exp)
+ {
+ struct type *return_type = NULL;
+
+ return_value = parse_and_eval (retval_exp);
+
+ /* Cast return value to the return type of the function. */
+ if (thisfun != NULL)
+ return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun));
+ if (return_type == NULL)
+ return_type = builtin_type_int;
+ return_value = value_cast (return_type, return_value);
+
+ /* Make sure we have fully evaluated it, since
+ it might live in the stack frame we're about to pop. */
+ if (VALUE_LAZY (return_value))
+ value_fetch_lazy (return_value);
+ }
+
+ /* If interactive, require confirmation. */
+
+ if (from_tty)
+ {
+ if (thisfun != 0)
+ {
+ if (!query ("Make %s return now? ", SYMBOL_SOURCE_NAME (thisfun)))
+ {
+ error ("Not confirmed.");
+ /* NOTREACHED */
+ }
+ }
+ else
+ if (!query ("Make selected stack frame return now? "))
+ error ("Not confirmed.");
+ }
+
+ /* Do the real work. Pop until the specified frame is current. We
+ use this method because the selected_frame is not valid after
+ a POP_FRAME. The pc comparison makes this work even if the
+ selected frame shares its fp with another frame. */
+
+ while (selected_frame_addr != (frame = get_current_frame())->frame
+ || selected_frame_pc != frame->pc)
+ POP_FRAME;
+
+ /* Then pop that frame. */
+
+ POP_FRAME;
+
+ /* Compute the return value (if any) and store in the place
+ for return values. */
+
+ if (retval_exp)
+ set_return_value (return_value);
+
+ /* If interactive, print the frame that is now current. */
+
+ if (from_tty)
+ frame_command ("0", 1);
+ else
+ select_frame_command ("0", 0);
+}
+
+/* Gets the language of the current frame. */
+
+enum language
+get_frame_language()
+{
+ register struct symtab *s;
+ enum language flang; /* The language of the current frame */
+
+ if (selected_frame)
+ {
+ s = find_pc_symtab(selected_frame->pc);
+ if (s)
+ flang = s->language;
+ else
+ flang = language_unknown;
+ }
+ else
+ flang = language_unknown;
+
+ return flang;
+}
+
+void
+_initialize_stack ()
+{
+#if 0
+ backtrace_limit = 30;
+#endif
+
+ add_com ("return", class_stack, return_command,
+ "Make selected stack frame return to its caller.\n\
+Control remains in the debugger, but when you continue\n\
+execution will resume in the frame above the one now selected.\n\
+If an argument is given, it is an expression for the value to return.");
+
+ add_com ("up", class_stack, up_command,
+ "Select and print stack frame that called this one.\n\
+An argument says how many frames up to go.");
+ add_com ("up-silently", class_support, up_silently_command,
+ "Same as the `up' command, but does not print anything.\n\
+This is useful in command scripts.");
+
+ add_com ("down", class_stack, down_command,
+ "Select and print stack frame called by this one.\n\
+An argument says how many frames down to go.");
+ add_com_alias ("do", "down", class_stack, 1);
+ add_com_alias ("dow", "down", class_stack, 1);
+ add_com ("down-silently", class_support, down_silently_command,
+ "Same as the `down' command, but does not print anything.\n\
+This is useful in command scripts.");
+
+ add_com ("frame", class_stack, frame_command,
+ "Select and print a stack frame.\n\
+With no argument, print the selected stack frame. (See also \"info frame\").\n\
+An argument specifies the frame to select.\n\
+It can be a stack frame number or the address of the frame.\n\
+With argument, nothing is printed if input is coming from\n\
+a command file or a user-defined command.");
+
+ add_com_alias ("f", "frame", class_stack, 1);
+
+ add_com ("select-frame", class_stack, select_frame_command,
+ "Select a stack frame without printing anything.\n\
+An argument specifies the frame to select.\n\
+It can be a stack frame number or the address of the frame.\n");
+
+ add_com ("backtrace", class_stack, backtrace_command,
+ "Print backtrace of all stack frames, or innermost COUNT frames.\n\
+With a negative argument, print outermost -COUNT frames.");
+ add_com_alias ("bt", "backtrace", class_stack, 0);
+ add_com_alias ("where", "backtrace", class_alias, 0);
+ add_info ("stack", backtrace_command,
+ "Backtrace of the stack, or innermost COUNT frames.");
+ add_info_alias ("s", "stack", 1);
+ add_info ("frame", frame_info,
+ "All about selected stack frame, or frame at ADDR.");
+ add_info_alias ("f", "frame", 1);
+ add_info ("locals", locals_info,
+ "Local variables of current stack frame.");
+ add_info ("args", args_info,
+ "Argument variables of current stack frame.");
+ add_info ("catch", catch_info,
+ "Exceptions that can be caught in the current stack frame.");
+
+#if 0
+ add_cmd ("backtrace-limit", class_stack, set_backtrace_limit_command,
+ "Specify maximum number of frames for \"backtrace\" to print by default.",
+ &setlist);
+ add_info ("backtrace-limit", backtrace_limit_info,
+ "The maximum number of frames for \"backtrace\" to print by default.");
+#endif
+}
diff --git a/contrib/gdb/gdb/standalone.c b/contrib/gdb/gdb/standalone.c
new file mode 100644
index 0000000..13fc476
--- /dev/null
+++ b/contrib/gdb/gdb/standalone.c
@@ -0,0 +1,593 @@
+/* Interface to bare machine for GDB running as kernel debugger.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include "gdb_stat.h"
+
+#if defined (SIGTSTP) && defined (SIGIO)
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif /* SIGTSTP and SIGIO defined (must be 4.2) */
+
+#include "defs.h"
+#include "signals.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "wait.h"
+
+
+/* Random system calls, mostly no-ops to prevent link problems */
+
+ioctl (desc, code, arg)
+{}
+
+int (* signal ()) ()
+{}
+
+kill ()
+{}
+
+getpid ()
+{
+ return 0;
+}
+
+sigsetmask ()
+{}
+
+chdir ()
+{}
+
+char *
+getcwd (buf, len)
+ char *buf;
+ unsigned int len;
+{
+ buf[0] = '/';
+ buf[1] = 0;
+ return buf;
+}
+
+/* Used to check for existence of .gdbinit. Say no. */
+
+access ()
+{
+ return -1;
+}
+
+exit ()
+{
+ error ("Fatal error; restarting.");
+}
+
+/* Reading "files". The contents of some files are written into kdb's
+ data area before it is run. These files are used to contain the
+ symbol table for kdb to load, and the source files (in case the
+ kdb user wants to print them). The symbols are stored in a file
+ named "kdb-symbols" in a.out format (except that all the text and
+ data have been stripped to save room).
+
+ The files are stored in the following format:
+ int number of bytes of data for this file, including these four.
+ char[] name of the file, ending with a null.
+ padding to multiple of 4 boundary.
+ char[] file contents. The length can be deduced from what was
+ specified before. There is no terminating null here.
+
+ If the int at the front is zero, it means there are no more files.
+
+ Opening a file in kdb returns a nonzero value to indicate success,
+ but the value does not matter. Only one file can be open, and only
+ for reading. All the primitives for input from the file know
+ which file is open and ignore what is specified for the descriptor
+ or for the stdio stream.
+
+ Input with fgetc can be done either on the file that is open
+ or on stdin (which reads from the terminal through tty_input () */
+
+/* Address of data for the files stored in format described above. */
+char *files_start;
+
+/* The file stream currently open: */
+
+char *sourcebeg; /* beginning of contents */
+int sourcesize; /* size of contents */
+char *sourceptr; /* current read pointer */
+int sourceleft; /* number of bytes to eof */
+
+/* "descriptor" for the file now open.
+ Incremented at each close.
+ If specified descriptor does not match this,
+ it means the program is trying to use a closed descriptor.
+ We report an error for that. */
+
+int sourcedesc;
+
+open (filename, modes)
+ char *filename;
+ int modes;
+{
+ register char *next;
+
+ if (modes)
+ {
+ errno = EROFS;
+ return -1;
+ }
+
+ if (sourceptr)
+ {
+ errno = EMFILE;
+ return -1;
+ }
+
+ for (next = files_start; * (int *) next; next += * (int *) next)
+ {
+ if (!STRCMP (next + 4, filename))
+ {
+ sourcebeg = next + 4 + strlen (next + 4) + 1;
+ sourcebeg = (char *) (((int) sourcebeg + 3) & (-4));
+ sourceptr = sourcebeg;
+ sourcesize = next + * (int *) next - sourceptr;
+ sourceleft = sourcesize;
+ return sourcedesc;
+ }
+ }
+ return 0;
+}
+
+close (desc)
+ int desc;
+{
+ sourceptr = 0;
+ sourcedesc++;
+ /* Don't let sourcedesc get big enough to be confused with stdin. */
+ if (sourcedesc == 100)
+ sourcedesc = 5;
+}
+
+FILE *
+fopen (filename, modes)
+ char *filename;
+ char *modes;
+{
+ return (FILE *) open (filename, *modes == 'w');
+}
+
+FILE *
+fdopen (desc)
+ int desc;
+{
+ return (FILE *) desc;
+}
+
+fclose (desc)
+ int desc;
+{
+ close (desc);
+}
+
+fstat (desc, statbuf)
+ struct stat *statbuf;
+{
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+ statbuf->st_size = sourcesize;
+}
+
+myread (desc, destptr, size, filename)
+ int desc;
+ char *destptr;
+ int size;
+ char *filename;
+{
+ int len = min (sourceleft, size);
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ memcpy (destptr, sourceptr, len);
+ sourceleft -= len;
+ return len;
+}
+
+int
+fread (bufp, numelts, eltsize, stream)
+{
+ register int elts = min (numelts, sourceleft / eltsize);
+ register int len = elts * eltsize;
+
+ if (stream != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ memcpy (bufp, sourceptr, len);
+ sourceleft -= len;
+ return elts;
+}
+
+int
+fgetc (desc)
+ int desc;
+{
+
+ if (desc == (int) stdin)
+ return tty_input ();
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (sourceleft-- <= 0)
+ return EOF;
+ return *sourceptr++;
+}
+
+lseek (desc, pos)
+ int desc;
+ int pos;
+{
+
+ if (desc != sourcedesc)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ if (pos < 0 || pos > sourcesize)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ sourceptr = sourcebeg + pos;
+ sourceleft = sourcesize - pos;
+}
+
+/* Output in kdb can go only to the terminal, so the stream
+ specified may be ignored. */
+
+printf (a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+ char buffer[1024];
+ sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ display_string (buffer);
+}
+
+fprintf (ign, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+{
+ char buffer[1024];
+ sprintf (buffer, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+ display_string (buffer);
+}
+
+fwrite (buf, numelts, size, stream)
+ register char *buf;
+ int numelts, size;
+{
+ register int i = numelts * size;
+ while (i-- > 0)
+ fputc (*buf++, stream);
+}
+
+fputc (c, ign)
+{
+ char buf[2];
+ buf[0] = c;
+ buf[1] = 0;
+ display_string (buf);
+}
+
+/* sprintf refers to this, but loading this from the
+ library would cause fflush to be loaded from it too.
+ In fact there should be no need to call this (I hope). */
+
+_flsbuf ()
+{
+ error ("_flsbuf was actually called.");
+}
+
+fflush (ign)
+{
+}
+
+/* Entries into core and inflow, needed only to make things link ok. */
+
+exec_file_command ()
+{}
+
+core_file_command ()
+{}
+
+char *
+get_exec_file (err)
+ int err;
+{
+ /* Makes one printout look reasonable; value does not matter otherwise. */
+ return "run";
+}
+
+/* Nonzero if there is a core file. */
+
+have_core_file_p ()
+{
+ return 0;
+}
+
+kill_command ()
+{
+ inferior_pid = 0;
+}
+
+terminal_inferior ()
+{}
+
+terminal_ours ()
+{}
+
+terminal_init_inferior ()
+{}
+
+write_inferior_register ()
+{}
+
+read_inferior_register ()
+{}
+
+read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ memcpy (myaddr, memaddr, len);
+}
+
+/* Always return 0 indicating success. */
+
+write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ memcpy (memaddr, myaddr, len);
+ return 0;
+}
+
+static REGISTER_TYPE saved_regs[NUM_REGS];
+
+REGISTER_TYPE
+read_register (regno)
+ int regno;
+{
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Register number %d out of range.", regno);
+ return saved_regs[regno];
+}
+
+void
+write_register (regno, value)
+ int regno;
+ REGISTER_TYPE value;
+{
+ if (regno < 0 || regno >= NUM_REGS)
+ error ("Register number %d out of range.", regno);
+ saved_regs[regno] = value;
+}
+
+/* System calls needed in relation to running the "inferior". */
+
+vfork ()
+{
+ /* Just appear to "succeed". Say the inferior's pid is 1. */
+ return 1;
+}
+
+/* These are called by code that normally runs in the inferior
+ that has just been forked. That code never runs, when standalone,
+ and these definitions are so it will link without errors. */
+
+ptrace ()
+{}
+
+setpgrp ()
+{}
+
+execle ()
+{}
+
+_exit ()
+{}
+
+/* Malloc calls these. */
+
+malloc_warning (str)
+ char *str;
+{
+ printf ("\n%s.\n\n", str);
+}
+
+char *next_free;
+char *memory_limit;
+
+char *
+sbrk (amount)
+ int amount;
+{
+ if (next_free + amount > memory_limit)
+ return (char *) -1;
+ next_free += amount;
+ return next_free - amount;
+}
+
+/* Various ways malloc might ask where end of memory is. */
+
+char *
+ulimit ()
+{
+ return memory_limit;
+}
+
+int
+vlimit ()
+{
+ return memory_limit - next_free;
+}
+
+getrlimit (addr)
+ struct rlimit *addr;
+{
+ addr->rlim_cur = memory_limit - next_free;
+}
+
+/* Context switching to and from program being debugged. */
+
+/* GDB calls here to run the user program.
+ The frame pointer for this function is saved in
+ gdb_stack by save_frame_pointer; then we restore
+ all of the user program's registers, including PC and PS. */
+
+static int fault_code;
+static REGISTER_TYPE gdb_stack;
+
+resume ()
+{
+ REGISTER_TYPE restore[NUM_REGS];
+
+ PUSH_FRAME_PTR;
+ save_frame_pointer ();
+
+ memcpy (restore, saved_regs, sizeof restore);
+ POP_REGISTERS;
+ /* Control does not drop through here! */
+}
+
+save_frame_pointer (val)
+ CORE_ADDR val;
+{
+ gdb_stack = val;
+}
+
+/* Fault handlers call here, running in the user program stack.
+ They must first push a fault code,
+ old PC, old PS, and any other info about the fault.
+ The exact format is machine-dependent and is known only
+ in the definition of PUSH_REGISTERS. */
+
+fault ()
+{
+ /* Transfer all registers and fault code to the stack
+ in canonical order: registers in order of GDB register number,
+ followed by fault code. */
+ PUSH_REGISTERS;
+
+ /* Transfer them to saved_regs and fault_code. */
+ save_registers ();
+
+ restore_gdb ();
+ /* Control does not reach here */
+}
+
+restore_gdb ()
+{
+ CORE_ADDR new_fp = gdb_stack;
+ /* Switch to GDB's stack */
+ POP_FRAME_PTR;
+ /* Return from the function `resume'. */
+}
+
+/* Assuming register contents and fault code have been pushed on the stack as
+ arguments to this function, copy them into the standard place
+ for the program's registers while GDB is running. */
+
+save_registers (firstreg)
+ int firstreg;
+{
+ memcpy (saved_regs, &firstreg, sizeof saved_regs);
+ fault_code = (&firstreg)[NUM_REGS];
+}
+
+/* Store into the structure such as `wait' would return
+ the information on why the program faulted,
+ converted into a machine-independent signal number. */
+
+static int fault_table[] = FAULT_TABLE;
+
+int
+wait (w)
+ WAITTYPE *w;
+{
+ WSETSTOP (*w, fault_table[fault_code / FAULT_CODE_UNITS]);
+ return inferior_pid;
+}
+
+/* Allocate a big space in which files for kdb to read will be stored.
+ Whatever is left is where malloc can allocate storage.
+
+ Initialize it, so that there will be space in the executable file
+ for it. Then the files can be put into kdb by writing them into
+ kdb's executable file. */
+
+/* The default size is as much space as we expect to be available
+ for kdb to use! */
+
+#ifndef HEAP_SIZE
+#define HEAP_SIZE 400000
+#endif
+
+char heap[HEAP_SIZE] = {0};
+
+#ifndef STACK_SIZE
+#define STACK_SIZE 100000
+#endif
+
+int kdb_stack_beg[STACK_SIZE / sizeof (int)];
+int kdb_stack_end;
+
+_initialize_standalone ()
+{
+ register char *next;
+
+ /* Find start of data on files. */
+
+ files_start = heap;
+
+ /* Find the end of the data on files. */
+
+ for (next = files_start; * (int *) next; next += * (int *) next) {}
+
+ /* That is where free storage starts for sbrk to give out. */
+ next_free = next;
+
+ memory_limit = heap + sizeof heap;
+}
+
diff --git a/contrib/gdb/gdb/stop-gdb.c b/contrib/gdb/gdb/stop-gdb.c
new file mode 100644
index 0000000..8f22bf9
--- /dev/null
+++ b/contrib/gdb/gdb/stop-gdb.c
@@ -0,0 +1,110 @@
+/* A client to make GDB return to command level in Mach 3.
+ Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Authors: Jukka Virtanen <jtv@hut.fi> and Peter Stout <pds@cs.cmu.edu>.
+
+ A simple client to make GDB (versions 4.4 and later) on Mach 3 return
+ to the command level when it is waiting for the inferior to stop.
+
+ Actions: Lookup the send right to the GDB message port from the
+ NetMsgServer.
+
+ Send an asynchronous message with msgh_id
+ GDB_MESSAGE_ID_STOP to that port.
+ */
+
+#include <stdio.h>
+
+#include "defs.h"
+
+#include <mach.h>
+#include <mach/message.h>
+#include <mach_error.h>
+#include <servers/netname.h>
+#include <servers/netname_defs.h>
+
+void
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ kern_return_t kr;
+ mach_msg_header_t msg;
+ mach_port_t gdb_port;
+ char *host;
+ char *name;
+
+ if (argc == 1)
+ argv[argc++] = GDB_DEF_NAME;
+
+ if (argc != 2)
+ {
+ fprintf (stderr, "Usage : %s <GDB name>\n", argv[0]);
+ exit (1);
+ }
+
+ /* Allow the user to specify a remote host. */
+ host = strchr (argv[1], '@');
+ if (host)
+ *(host++) = '\0';
+ else
+ host = (char *) "";
+
+ name = malloc (strlen (argv[1]) + sizeof(GDB_NAME_PREFIX));
+ if (name == NULL)
+ {
+ fprintf (stderr, "Unable to allocate memory for name.");
+ exit (1);
+ }
+
+ strcpy (name, GDB_NAME_PREFIX);
+ strcat (name, argv[1]);
+
+ /* Look up the GDB service port. For convenience, add the
+ GDB_NAME_PREFIX the argument before looking up the name.
+ For backwards compatibility, do it without. */
+
+ kr = netname_look_up (name_server_port, host, name, &gdb_port);
+ if (kr == NETNAME_NOT_CHECKED_IN)
+ kr = netname_look_up (name_server_port, host, argv[1], &gdb_port);
+ if (kr != KERN_SUCCESS)
+ {
+ fprintf (stderr, "Unable to lookup the GDB service port: %s.\n",
+ mach_error_string(kr));
+ exit(1);
+ }
+
+ /* Code generated by mig stub generator, with minor cleanups :-)
+
+ simpleroutine stop_inferior(gdb_port : mach_port_t); */
+
+ msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
+ msg.msgh_remote_port = gdb_port;
+ msg.msgh_local_port = MACH_PORT_NULL;
+ msg.msgh_size = sizeof(msg);
+ msg.msgh_seqno = 0;
+ msg.msgh_id = GDB_MESSAGE_ID_STOP;
+
+ kr = mach_msg_send (&msg);
+ if (kr != KERN_SUCCESS)
+ fprintf (stderr, "Message not sent, return code %d : %s\n", kr,
+ mach_error_string (kr));
+
+ exit (kr != KERN_SUCCESS);
+}
diff --git a/contrib/gdb/gdb/stuff.c b/contrib/gdb/gdb/stuff.c
new file mode 100644
index 0000000..eedbeab
--- /dev/null
+++ b/contrib/gdb/gdb/stuff.c
@@ -0,0 +1,174 @@
+/* Program to stuff files into a specially prepared space in kdb.
+ Copyright (C) 1986, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written 13-Mar-86 by David Bridgham. */
+
+#include <stdio.h>
+#include <a.out.h>
+#include <sys/types.h>
+#include "gdb_stat.h"
+#include <sys/file.h>
+#include <varargs.h>
+
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ register char *cp;
+ char *outfile;
+ register int i;
+ int offset;
+ int out_fd, in_fd;
+ struct stat stat_buf;
+ int size, pad;
+ char buf[1024];
+ static char zeros[4] = {0};
+
+ if (argc < 4)
+ err("Not enough arguments\nUsage: %s -o kdb file1 file2 ...\n",
+ argv[0]);
+
+ outfile = 0;
+ for (i = 1; i < argc; i++)
+ {
+ if (STREQ (argv[i], "-o"))
+ outfile = argv[++i];
+ }
+ if (outfile == 0)
+ err("Output file not specified\n");
+
+ offset = get_offset (outfile, "_heap");
+
+ out_fd = open (outfile, O_WRONLY);
+ if (out_fd < 0)
+ err ("Error opening %s for write: %s\n", outfile, strerror (errno));
+ if (lseek (out_fd, offset, 0) < 0)
+ err ("Error seeking to heap in %s: %s\n", outfile, strerror (errno));
+
+ /* For each file listed on the command line, write it into the
+ * 'heap' of the output file. Make sure to skip the arguments
+ * that name the output file. */
+ for (i = 1; i < argc; i++)
+ {
+ if (STREQ (argv[i], "-o"))
+ continue;
+ if ((in_fd = open (argv[i], O_RDONLY)) < 0)
+ err ("Error opening %s for read: %s\n", argv[i],
+ strerror (errno));
+ if (fstat (in_fd, &stat_buf) < 0)
+ err ("Error stat'ing %s: %s\n", argv[i], strerror (errno));
+ size = strlen (argv[i]);
+ pad = 4 - (size & 3);
+ size += pad + stat_buf.st_size + sizeof (int);
+ write (out_fd, &size, sizeof (int));
+ write (out_fd, argv[i], strlen (argv[i]));
+ write (out_fd, zeros, pad);
+ while ((size = read (in_fd, buf, sizeof (buf))) > 0)
+ write (out_fd, buf, size);
+ close (in_fd);
+ }
+ size = 0;
+ write (out_fd, &size, sizeof (int));
+ close (out_fd);
+ return (0);
+}
+
+/* Read symbol table from file and returns the offset into the file
+ * where symbol sym_name is located. If error, print message and
+ * exit. */
+get_offset (file, sym_name)
+ char *file;
+ char *sym_name;
+{
+ int f;
+ struct exec file_hdr;
+ struct nlist *symbol_table;
+ int size;
+ char *strings;
+
+ f = open (file, O_RDONLY);
+ if (f < 0)
+ err ("Error opening %s: %s\n", file, strerror (errno));
+ if (read (f, &file_hdr, sizeof (file_hdr)) < 0)
+ err ("Error reading exec structure: %s\n", strerror (errno));
+ if (N_BADMAG (file_hdr))
+ err ("File %s not an a.out file\n", file);
+
+ /* read in symbol table */
+ if ((symbol_table = (struct nlist *)malloc (file_hdr.a_syms)) == 0)
+ err ("Couldn't allocate space for symbol table\n");
+ if (lseek (f, N_SYMOFF (file_hdr), 0) == -1)
+ err ("lseek error: %s\n", strerror (errno));
+ if (read (f, symbol_table, file_hdr.a_syms) == -1)
+ err ("Error reading symbol table from %s: %s\n", file,
+ strerror (errno));
+
+ /* read in string table */
+ if (read (f, &size, 4) == -1)
+ err ("reading string table size: %s\n", strerror (errno));
+ if ((strings = (char *)malloc (size)) == 0)
+ err ("Couldn't allocate memory for string table\n");
+ if (read (f, strings, size - 4) == -1)
+ err ("reading string table: %s\n", strerror (errno));
+
+ /* Find the core address at which the first byte of kdb text segment
+ should be loaded into core when kdb is run. */
+ origin = find_symbol ("_etext", symbol_table, file_hdr.a_syms, strings)
+ - file_hdr.a_text;
+ /* Find the core address at which the heap will appear. */
+ coreaddr = find_symbol (sym_name, symbol_table, file_hdr.a_syms, strings);
+ /* Return address in file of the heap data space. */
+ return (N_TXTOFF (file_hdr) + core_addr - origin);
+}
+
+find_symbol (sym_name, symbol_table, length, strings)
+ char *sym_name;
+ struct nlist *symbol_table;
+ int length;
+ char *strings;
+{
+ register struct nlist *sym;
+
+ /* Find symbol in question */
+ for (sym = symbol_table;
+ sym != (struct nlist *)((char *)symbol_table + length);
+ sym++)
+ {
+ if ((sym->n_type & N_TYPE) != N_DATA) continue;
+ if (sym->n_un.n_strx == 0) continue;
+ if (STREQ (sym_name, strings + sym->n_un.n_strx - 4))
+ return sym->n_value;
+ }
+ err ("Data symbol %s not found in %s\n", sym_name, file);
+}
+
+/* VARARGS */
+void
+err (va_alist)
+ va_dcl
+{
+ va_list args;
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+ vfprintf (gdb_stderr, string, args);
+ va_end (args);
+ exit (-1);
+}
diff --git a/contrib/gdb/gdb/symfile.c b/contrib/gdb/gdb/symfile.c
new file mode 100644
index 0000000..62c4f61
--- /dev/null
+++ b/contrib/gdb/gdb/symfile.c
@@ -0,0 +1,1774 @@
+/* Generic symbol file reading for the GNU debugger, GDB.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+ Contributed by Cygnus Support, using pieces from other GDB modules.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "target.h"
+#include "value.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcmd.h"
+#include "breakpoint.h"
+#include "language.h"
+#include "complaints.h"
+#include "demangle.h"
+#include "inferior.h" /* for write_pc */
+
+#include "obstack.h"
+#include <assert.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+#include <time.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* Global variables owned by this file */
+int readnow_symbol_files; /* Read full symbols immediately */
+
+struct complaint oldsyms_complaint = {
+ "Replacing old symbols for `%s'", 0, 0
+};
+
+struct complaint empty_symtab_complaint = {
+ "Empty symbol table found for `%s'", 0, 0
+};
+
+/* External variables and functions referenced. */
+
+extern int info_verbose;
+
+/* Functions this file defines */
+
+static void
+set_initial_language PARAMS ((void));
+
+static void
+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 *));
+
+static int
+compare_psymbols PARAMS ((const void *, const void *));
+
+static int
+compare_symbols PARAMS ((const void *, const void *));
+
+static bfd *
+symfile_bfd_open PARAMS ((char *));
+
+static void
+find_sym_fns PARAMS ((struct objfile *));
+
+/* List of all available sym_fns. On gdb startup, each object file reader
+ calls add_symtab_fns() to register information on each format it is
+ prepared to read. */
+
+static struct sym_fns *symtab_fns = NULL;
+
+/* Flag for whether user will be reloading symbols multiple times.
+ Defaults to ON for VxWorks, otherwise OFF. */
+
+#ifdef SYMBOL_RELOADING_DEFAULT
+int symbol_reloading = SYMBOL_RELOADING_DEFAULT;
+#else
+int symbol_reloading = 0;
+#endif
+
+/* If true, then shared library symbols will be added automatically
+ when the inferior is created, new libraries are loaded, or when
+ attaching to the inferior. This is almost always what users
+ will want to have happen; but for very large programs, the startup
+ time will be excessive, and so if this is a problem, the user can
+ clear this flag and then add the shared library symbols as needed.
+ Note that there is a potential for confusion, since if the shared
+ library symbols are not loaded, commands like "info fun" will *not*
+ report all the functions that are actually present. */
+
+int auto_solib_add = 1;
+
+
+/* Since this function is called from within qsort, in an ANSI environment
+ it must conform to the prototype for qsort, which specifies that the
+ comparison function takes two "void *" pointers. */
+
+static int
+compare_symbols (s1p, s2p)
+ const PTR s1p;
+ const PTR s2p;
+{
+ register struct symbol **s1, **s2;
+
+ s1 = (struct symbol **) s1p;
+ s2 = (struct symbol **) s2p;
+
+ return (STRCMP (SYMBOL_NAME (*s1), SYMBOL_NAME (*s2)));
+}
+
+/*
+
+LOCAL FUNCTION
+
+ compare_psymbols -- compare two partial symbols by name
+
+DESCRIPTION
+
+ Given pointers to pointers to two partial symbol table entries,
+ compare them by name and return -N, 0, or +N (ala strcmp).
+ Typically used by sorting routines like qsort().
+
+NOTES
+
+ Does direct compare of first two characters before punting
+ and passing to strcmp for longer compares. Note that the
+ original version had a bug whereby two null strings or two
+ identically named one character strings would return the
+ comparison of memory following the null byte.
+
+ */
+
+static int
+compare_psymbols (s1p, s2p)
+ const PTR s1p;
+ const PTR s2p;
+{
+ register char *st1 = SYMBOL_NAME (*(struct partial_symbol **) s1p);
+ register char *st2 = SYMBOL_NAME (*(struct partial_symbol **) s2p);
+
+ if ((st1[0] - st2[0]) || !st1[0])
+ {
+ return (st1[0] - st2[0]);
+ }
+ else if ((st1[1] - st2[1]) || !st1[1])
+ {
+ return (st1[1] - st2[1]);
+ }
+ else
+ {
+ return (STRCMP (st1 + 2, st2 + 2));
+ }
+}
+
+void
+sort_pst_symbols (pst)
+ struct partial_symtab *pst;
+{
+ /* Sort the global list; don't sort the static list */
+
+ qsort (pst -> objfile -> global_psymbols.list + pst -> globals_offset,
+ pst -> n_global_syms, sizeof (struct partial_symbol *),
+ compare_psymbols);
+}
+
+/* Call sort_block_syms to sort alphabetically the symbols of one block. */
+
+void
+sort_block_syms (b)
+ register struct block *b;
+{
+ qsort (&BLOCK_SYM (b, 0), BLOCK_NSYMS (b),
+ sizeof (struct symbol *), compare_symbols);
+}
+
+/* Call sort_symtab_syms to sort alphabetically
+ the symbols of each block of one symtab. */
+
+void
+sort_symtab_syms (s)
+ register struct symtab *s;
+{
+ register struct blockvector *bv;
+ int nbl;
+ int i;
+ register struct block *b;
+
+ if (s == 0)
+ return;
+ bv = BLOCKVECTOR (s);
+ nbl = BLOCKVECTOR_NBLOCKS (bv);
+ for (i = 0; i < nbl; i++)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ if (BLOCK_SHOULD_SORT (b))
+ sort_block_syms (b);
+ }
+}
+
+/* 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. */
+
+char *
+obsavestring (ptr, size, obstackp)
+ char *ptr;
+ int size;
+ struct obstack *obstackp;
+{
+ register char *p = (char *) obstack_alloc (obstackp, size + 1);
+ /* Open-coded memcpy--saves function call time.
+ These strings are usually short. */
+ {
+ register char *p1 = ptr;
+ register char *p2 = p;
+ char *end = ptr + size;
+ while (p1 != end)
+ *p2++ = *p1++;
+ }
+ p[size] = 0;
+ return p;
+}
+
+/* Concatenate strings S1, S2 and S3; return the new string.
+ Space is found in the symbol_obstack. */
+
+char *
+obconcat (obstackp, s1, s2, s3)
+ struct obstack *obstackp;
+ const char *s1, *s2, *s3;
+{
+ register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
+ register char *val = (char *) obstack_alloc (obstackp, len);
+ strcpy (val, s1);
+ strcat (val, s2);
+ strcat (val, s3);
+ return val;
+}
+
+/* True if we are nested inside psymtab_to_symtab. */
+
+int currently_reading_symtab = 0;
+
+static void
+decrement_reading_symtab (dummy)
+ void *dummy;
+{
+ currently_reading_symtab--;
+}
+
+/* Get the symbol table that corresponds to a partial_symtab.
+ This is fast after the first time you do it. In fact, there
+ is an even faster macro PSYMTAB_TO_SYMTAB that does the fast
+ case inline. */
+
+struct symtab *
+psymtab_to_symtab (pst)
+ register struct partial_symtab *pst;
+{
+ /* If it's been looked up before, return it. */
+ if (pst->symtab)
+ return pst->symtab;
+
+ /* If it has not yet been read in, read it. */
+ if (!pst->readin)
+ {
+ struct cleanup *back_to = make_cleanup (decrement_reading_symtab, NULL);
+ currently_reading_symtab++;
+ (*pst->read_symtab) (pst);
+ do_cleanups (back_to);
+ }
+
+ return pst->symtab;
+}
+
+/* Initialize entry point information for this objfile. */
+
+void
+init_entry_point_info (objfile)
+ struct objfile *objfile;
+{
+ /* Save startup file's range of PC addresses to help blockframe.c
+ decide where the bottom of the stack is. */
+
+ if (bfd_get_file_flags (objfile -> obfd) & EXEC_P)
+ {
+ /* Executable file -- record its entry point so we'll recognize
+ the startup file because it contains the entry point. */
+ objfile -> ei.entry_point = bfd_get_start_address (objfile -> obfd);
+ }
+ else
+ {
+ /* Examination of non-executable.o files. Short-circuit this stuff. */
+ objfile -> ei.entry_point = INVALID_ENTRY_POINT;
+ }
+ objfile -> ei.entry_file_lowpc = INVALID_ENTRY_LOWPC;
+ objfile -> ei.entry_file_highpc = INVALID_ENTRY_HIGHPC;
+ objfile -> ei.entry_func_lowpc = INVALID_ENTRY_LOWPC;
+ objfile -> ei.entry_func_highpc = INVALID_ENTRY_HIGHPC;
+ objfile -> ei.main_func_lowpc = INVALID_ENTRY_LOWPC;
+ objfile -> ei.main_func_highpc = INVALID_ENTRY_HIGHPC;
+}
+
+/* Get current entry point address. */
+
+CORE_ADDR
+entry_point_address()
+{
+ return symfile_objfile ? symfile_objfile->ei.entry_point : 0;
+}
+
+/* Remember the lowest-addressed loadable section we've seen.
+ This function is called via bfd_map_over_sections.
+
+ In case of equal vmas, the section with the largest size becomes the
+ lowest-addressed loadable section.
+
+ If the vmas and sizes are equal, the last section is considered the
+ lowest-addressed loadable section. */
+
+void
+find_lowest_section (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ asection **lowest = (asection **)obj;
+
+ if (0 == (bfd_get_section_flags (abfd, sect) & SEC_LOAD))
+ return;
+ if (!*lowest)
+ *lowest = sect; /* First loadable section */
+ else if (bfd_section_vma (abfd, *lowest) > bfd_section_vma (abfd, sect))
+ *lowest = sect; /* A lower loadable section */
+ else if (bfd_section_vma (abfd, *lowest) == bfd_section_vma (abfd, sect)
+ && (bfd_section_size (abfd, (*lowest))
+ <= bfd_section_size (abfd, sect)))
+ *lowest = sect;
+}
+
+/* Process a symbol file, as either the main file or as a dynamically
+ loaded file.
+
+ NAME is the file name (which will be tilde-expanded and made
+ absolute herein) (but we don't free or modify NAME itself).
+ FROM_TTY says how verbose to be. MAINLINE specifies whether this
+ is the main symbol file, or whether it's an extra symbol file such
+ as dynamically loaded code. If !mainline, ADDR is the address
+ where the text segment was loaded. If VERBO, the caller has printed
+ a verbose message about the symbol reading (and complaints can be
+ more terse about it). */
+
+void
+syms_from_objfile (objfile, addr, mainline, verbo)
+ struct objfile *objfile;
+ CORE_ADDR addr;
+ int mainline;
+ int verbo;
+{
+ struct section_offsets *section_offsets;
+ asection *lowest_sect;
+ struct cleanup *old_chain;
+
+ init_entry_point_info (objfile);
+ find_sym_fns (objfile);
+
+ /* Make sure that partially constructed symbol tables will be cleaned up
+ if an error occurs during symbol reading. */
+ old_chain = make_cleanup (free_objfile, objfile);
+
+ if (mainline)
+ {
+ /* We will modify the main symbol table, make sure that all its users
+ will be cleaned up if an error occurs during symbol reading. */
+ make_cleanup (clear_symtab_users, 0);
+
+ /* Since no error yet, throw away the old symbol table. */
+
+ if (symfile_objfile != NULL)
+ {
+ free_objfile (symfile_objfile);
+ 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);
+ }
+
+ /* Convert addr into an offset rather than an absolute address.
+ We find the lowest address of a loaded segment in the objfile,
+ and assume that <addr> is where that got loaded. Due to historical
+ precedent, we warn if that doesn't happen to be a text segment. */
+
+ if (mainline)
+ {
+ addr = 0; /* No offset from objfile addresses. */
+ }
+ else
+ {
+ lowest_sect = bfd_get_section_by_name (objfile->obfd, ".text");
+ if (lowest_sect == NULL)
+ bfd_map_over_sections (objfile->obfd, find_lowest_section,
+ (PTR) &lowest_sect);
+
+ if (lowest_sect == NULL)
+ warning ("no loadable sections found in added symbol-file %s",
+ objfile->name);
+ else if ((bfd_get_section_flags (objfile->obfd, lowest_sect) & SEC_CODE)
+ == 0)
+ /* 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),
+ (unsigned long) bfd_section_vma (objfile->obfd, lowest_sect));
+
+ if (lowest_sect)
+ addr -= bfd_section_vma (objfile->obfd, lowest_sect);
+ }
+
+ /* Initialize symbol reading routines for this objfile, allow complaints to
+ appear for this new file, and record how verbose to be, then do the
+ initial symbol reading for this file. */
+
+ (*objfile -> sf -> sym_init) (objfile);
+ clear_complaints (1, verbo);
+
+ section_offsets = (*objfile -> sf -> sym_offsets) (objfile, addr);
+ objfile->section_offsets = section_offsets;
+
+#ifndef IBM6000_TARGET
+ /* This is a SVR4/SunOS specific hack, I think. In any event, it
+ screws RS/6000. sym_offsets should be doing this sort of thing,
+ because it knows the mapping between bfd sections and
+ section_offsets. */
+ /* This is a hack. As far as I can tell, section offsets are not
+ target dependent. They are all set to addr with a couple of
+ exceptions. The exceptions are sysvr4 shared libraries, whose
+ offsets are kept in solib structures anyway and rs6000 xcoff
+ which handles shared libraries in a completely unique way.
+
+ Section offsets are built similarly, except that they are built
+ by adding addr in all cases because there is no clear mapping
+ from section_offsets into actual sections. Note that solib.c
+ has a different algorythm for finding section offsets.
+
+ These should probably all be collapsed into some target
+ independent form of shared library support. FIXME. */
+
+ if (addr)
+ {
+ struct obj_section *s;
+
+ for (s = objfile->sections; s < objfile->sections_end; ++s)
+ {
+ s->addr -= s->offset;
+ s->addr += addr;
+ s->endaddr -= s->offset;
+ s->endaddr += addr;
+ s->offset += addr;
+ }
+ }
+#endif /* not IBM6000_TARGET */
+
+ (*objfile -> sf -> sym_read) (objfile, section_offsets, mainline);
+
+ 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;
+
+ /* Mark the objfile has having had initial symbol read attempted. Note
+ that this does not mean we found any symbols... */
+
+ objfile -> flags |= OBJF_SYMS;
+
+ /* Discard cleanups as symbol reading was successful. */
+
+ discard_cleanups (old_chain);
+
+/* Call this after reading in a new symbol table to give target dependant code
+ a crack at the new symbols. For instance, this could be used to update the
+ values of target-specific symbols GDB needs to keep track of (such as
+ _sigtramp, or whatever). */
+
+ TARGET_SYMFILE_POSTREAD (objfile);
+}
+
+/* Perform required actions after either reading in the initial
+ symbols for a new objfile, or mapping in the symbols from a reusable
+ objfile. */
+
+void
+new_symfile_objfile (objfile, mainline, verbo)
+ struct objfile *objfile;
+ int mainline;
+ int verbo;
+{
+
+ /* If this is the main symbol file we have to clean up all users of the
+ old main symbol file. Otherwise it is sufficient to fixup all the
+ breakpoints that may have been redefined by this symbol file. */
+ if (mainline)
+ {
+ /* OK, make it the "real" symbol file. */
+ symfile_objfile = objfile;
+
+ clear_symtab_users ();
+ }
+ else
+ {
+ breakpoint_re_set ();
+ }
+
+ /* We're done reading the symbol file; finish off complaints. */
+ clear_complaints (0, verbo);
+}
+
+/* Process a symbol file, as either the main file or as a dynamically
+ loaded file.
+
+ NAME is the file name (which will be tilde-expanded and made
+ absolute herein) (but we don't free or modify NAME itself).
+ FROM_TTY says how verbose to be. MAINLINE specifies whether this
+ is the main symbol file, or whether it's an extra symbol file such
+ as dynamically loaded code. If !mainline, ADDR is the address
+ where the text segment was loaded.
+
+ Upon success, returns a pointer to the objfile that was added.
+ Upon failure, jumps back to command level (never returns). */
+
+struct objfile *
+symbol_file_add (name, from_tty, addr, mainline, mapped, readnow)
+ char *name;
+ int from_tty;
+ CORE_ADDR addr;
+ int mainline;
+ int mapped;
+ int readnow;
+{
+ struct objfile *objfile;
+ struct partial_symtab *psymtab;
+ bfd *abfd;
+
+ /* Open a bfd for the file, and give user a chance to burp if we'd be
+ interactively wiping out any existing symbols. */
+
+ abfd = symfile_bfd_open (name);
+
+ if ((have_full_symbols () || have_partial_symbols ())
+ && mainline
+ && from_tty
+ && !query ("Load new symbol table from \"%s\"? ", name))
+ error ("Not confirmed.");
+
+ objfile = allocate_objfile (abfd, mapped);
+
+ /* If the objfile uses a mapped symbol file, and we have a psymtab for
+ it, then skip reading any symbols at this time. */
+
+ if ((objfile -> flags & OBJF_MAPPED) && (objfile -> flags & OBJF_SYMS))
+ {
+ /* We mapped in an existing symbol table file that already has had
+ initial symbol reading performed, so we can skip that part. Notify
+ the user that instead of reading the symbols, they have been mapped.
+ */
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("Mapped symbols for %s...", name);
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ }
+ init_entry_point_info (objfile);
+ find_sym_fns (objfile);
+ }
+ else
+ {
+ /* We either created a new mapped symbol table, mapped an existing
+ symbol table file which has not had initial symbol reading
+ performed, or need to read an unmapped symbol table. */
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("Reading symbols from %s...", name);
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ }
+ syms_from_objfile (objfile, addr, mainline, from_tty);
+ }
+
+ /* We now have at least a partial symbol table. Check to see if the
+ user requested that all symbols be read on initial access via either
+ the gdb startup command line or on a per symbol file basis. Expand
+ all partial symbol tables for this objfile if so. */
+
+ if (readnow || readnow_symbol_files)
+ {
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("expanding to full symbols...");
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ }
+
+ for (psymtab = objfile -> psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab -> next)
+ {
+ psymtab_to_symtab (psymtab);
+ }
+ }
+
+ if (from_tty || info_verbose)
+ {
+ printf_filtered ("done.\n");
+ gdb_flush (gdb_stdout);
+ }
+
+ new_symfile_objfile (objfile, mainline, from_tty);
+
+ return (objfile);
+}
+
+/* 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)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ char *name = NULL;
+ CORE_ADDR text_relocation = 0; /* text_relocation */
+ struct cleanup *cleanups;
+ int mapped = 0;
+ int readnow = 0;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ if ((have_full_symbols () || have_partial_symbols ())
+ && from_tty
+ && !query ("Discard symbol table from `%s'? ",
+ symfile_objfile -> name))
+ error ("Not confirmed.");
+ free_all_objfiles ();
+ symfile_objfile = NULL;
+ if (from_tty)
+ {
+ printf_unfiltered ("No symbol file now.\n");
+ }
+ }
+ else
+ {
+ if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, (char *) argv);
+ while (*argv != NULL)
+ {
+ if (STREQ (*argv, "-mapped"))
+ {
+ mapped = 1;
+ }
+ else if (STREQ (*argv, "-readnow"))
+ {
+ readnow = 1;
+ }
+ else if (**argv == '-')
+ {
+ error ("unknown option `%s'", *argv);
+ }
+ else
+ {
+ 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);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+
+ set_initial_language ();
+ }
+ argv++;
+ }
+
+ if (name == NULL)
+ {
+ error ("no symbol file name was specified");
+ }
+ do_cleanups (cleanups);
+ }
+}
+
+/* Set the initial language.
+
+ A better solution would be to record the language in the psymtab when reading
+ partial symbols, and then use it (if known) to set the language. This would
+ be a win for formats that encode the language in an easily discoverable place,
+ such as DWARF. For stabs, we can jump through hoops looking for specially
+ named symbols or try to intuit the language from the specific type of stabs
+ we find, but we can't do that until later when we read in full symbols.
+ FIXME. */
+
+static void
+set_initial_language ()
+{
+ struct partial_symtab *pst;
+ enum language lang = language_unknown;
+
+ pst = find_main_psymtab ();
+ if (pst != NULL)
+ {
+ if (pst -> filename != NULL)
+ {
+ lang = deduce_language_from_filename (pst -> filename);
+ }
+ if (lang == language_unknown)
+ {
+ /* Make C the default language */
+ lang = language_c;
+ }
+ set_language (lang);
+ expected_language = current_language; /* Don't warn the user */
+ }
+}
+
+/* Open file specified by NAME and hand it off to BFD for preliminary
+ analysis. Result is a newly initialized bfd *, which includes a newly
+ malloc'd` copy of NAME (tilde-expanded and made absolute).
+ In case of trouble, error() is called. */
+
+static bfd *
+symfile_bfd_open (name)
+ char *name;
+{
+ bfd *sym_bfd;
+ int desc;
+ char *absolute_name;
+
+ name = tilde_expand (name); /* Returns 1st new malloc'd copy */
+
+ /* Look down path for it, allocate 2nd new malloc'd copy. */
+ desc = openp (getenv ("PATH"), 1, name, O_RDONLY | O_BINARY, 0, &absolute_name);
+ if (desc < 0)
+ {
+ make_cleanup (free, name);
+ perror_with_name (name);
+ }
+ free (name); /* Free 1st new malloc'd copy */
+ name = absolute_name; /* Keep 2nd malloc'd copy in bfd */
+ /* It'll be freed in free_objfile(). */
+
+ sym_bfd = bfd_fdopenr (name, gnutarget, desc);
+ if (!sym_bfd)
+ {
+ close (desc);
+ make_cleanup (free, name);
+ error ("\"%s\": can't open to read symbols: %s.", name,
+ bfd_errmsg (bfd_get_error ()));
+ }
+ sym_bfd->cacheable = true;
+
+ if (!bfd_check_format (sym_bfd, bfd_object))
+ {
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ bfd_close (sym_bfd); /* This also closes desc */
+ make_cleanup (free, name);
+ error ("\"%s\": can't read symbols: %s.", name,
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ return (sym_bfd);
+}
+
+/* Link a new symtab_fns into the global symtab_fns list. Called on gdb
+ startup by the _initialize routine in each object file format reader,
+ to register information about each format the the reader is prepared
+ to handle. */
+
+void
+add_symtab_fns (sf)
+ struct sym_fns *sf;
+{
+ sf->next = symtab_fns;
+ symtab_fns = sf;
+}
+
+
+/* Initialize to read symbols from the symbol file sym_bfd. It either
+ returns or calls error(). The result is an initialized struct sym_fns
+ in the objfile structure, that contains cached information about the
+ symbol file. */
+
+static void
+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 and PowerMac. See xcoffread.c. */
+ if (STREQ (our_target, "aixcoff-rs6000") ||
+ STREQ (our_target, "xcoff-powermac"))
+ 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 (our_flavour == sf -> sym_flavour)
+ {
+ objfile -> sf = sf;
+ return;
+ }
+ }
+ error ("I'm sorry, Dave, I can't do that. Symbol format `%s' unknown.",
+ bfd_get_target (objfile -> obfd));
+}
+
+/* This function runs the load command of our current target. */
+
+static void
+load_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (arg == NULL)
+ arg = get_exec_file (1);
+ target_load (arg, from_tty);
+}
+
+/* This version of "load" should be usable for any target. Currently
+ it is just used for remote targets, not inftarg.c or core files,
+ on the theory that only in that case is it useful.
+
+ Avoiding xmodem and the like seems like a win (a) because we don't have
+ to worry about finding it, and (b) On VMS, fork() is very slow and so
+ we don't want to run a subprocess. On the other hand, I'm not sure how
+ performance compares. */
+void
+generic_load (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ struct cleanup *old_cleanups;
+ asection *s;
+ bfd *loadfile_bfd;
+ time_t start_time, end_time; /* Start and end times of download */
+ unsigned long data_count; /* Number of bytes transferred to memory */
+
+ loadfile_bfd = bfd_openr (filename, gnutarget);
+ if (loadfile_bfd == NULL)
+ {
+ perror_with_name (filename);
+ return;
+ }
+ /* FIXME: should be checking for errors from bfd_close (for one thing,
+ on error it does not free all the storage associated with the
+ bfd). */
+ old_cleanups = make_cleanup (bfd_close, loadfile_bfd);
+
+ if (!bfd_check_format (loadfile_bfd, bfd_object))
+ {
+ error ("\"%s\" is not an object file: %s", filename,
+ bfd_errmsg (bfd_get_error ()));
+ }
+
+ start_time = time (NULL);
+
+ for (s = loadfile_bfd->sections; s; s = s->next)
+ {
+ if (s->flags & SEC_LOAD)
+ {
+ bfd_size_type size;
+
+ size = bfd_get_section_size_before_reloc (s);
+ if (size > 0)
+ {
+ char *buffer;
+ struct cleanup *old_chain;
+ bfd_vma vma;
+
+ data_count += size;
+
+ buffer = xmalloc (size);
+ old_chain = make_cleanup (free, buffer);
+
+ vma = bfd_get_section_vma (loadfile_bfd, s);
+
+ /* 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 ",
+ bfd_get_section_name (loadfile_bfd, s),
+ (unsigned long) size);
+ print_address_numeric (vma, 1, gdb_stdout);
+ printf_filtered ("\n");
+
+ bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
+
+ target_write_memory (vma, buffer, size);
+
+ do_cleanups (old_chain);
+ }
+ }
+ }
+
+ end_time = time (NULL);
+
+ /* We were doing this in remote-mips.c, I suspect it is right
+ for other targets too. */
+ write_pc (loadfile_bfd->start_address);
+
+ /* FIXME: are we supposed to call symbol_file_add or not? According to
+ a comment from remote-mips.c (where a call to symbol_file_add was
+ commented out), making the call confuses GDB if more than one file is
+ loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c
+ does. */
+
+ if (end_time != start_time)
+ printf_filtered ("Transfer rate: %d bits/sec.\n",
+ (data_count * 8)/(end_time - start_time));
+
+ do_cleanups (old_cleanups);
+}
+
+/* This function allows the addition of incrementally linked object files.
+ It does not modify any state in the target, only in the debugger. */
+
+/* ARGSUSED */
+static void
+add_symbol_file_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char *name = NULL;
+ CORE_ADDR text_addr;
+ char *arg;
+ int readnow = 0;
+ int mapped = 0;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("add-symbol-file takes a file name and an address");
+ }
+
+ /* Make a copy of the string that we can safely write into. */
+
+ args = strdup (args);
+ make_cleanup (free, args);
+
+ /* Pick off any -option args and the file name. */
+
+ while ((*args != '\000') && (name == NULL))
+ {
+ while (isspace (*args)) {args++;}
+ arg = args;
+ while ((*args != '\000') && !isspace (*args)) {args++;}
+ if (*args != '\000')
+ {
+ *args++ = '\000';
+ }
+ if (*arg != '-')
+ {
+ name = arg;
+ }
+ else if (STREQ (arg, "-mapped"))
+ {
+ mapped = 1;
+ }
+ else if (STREQ (arg, "-readnow"))
+ {
+ readnow = 1;
+ }
+ else
+ {
+ error ("unknown option `%s'", arg);
+ }
+ }
+
+ /* After picking off any options and the file name, args should be
+ left pointing at the remainder of the command line, which should
+ be the address expression to evaluate. */
+
+ if (name == NULL)
+ {
+ error ("add-symbol-file takes a file name");
+ }
+ name = tilde_expand (name);
+ make_cleanup (free, name);
+
+ 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.");
+
+ symbol_file_add (name, 0, text_addr, 0, mapped, readnow);
+
+ /* Getting new symbols may change our opinion about what is
+ frameless. */
+ reinit_frame_cache ();
+}
+
+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 ()
+{
+ struct objfile *objfile;
+ long new_modtime;
+ int reread_one = 0;
+ struct stat new_statbuf;
+ int res;
+
+ /* With the addition of shared libraries, this should be modified,
+ the load time should be saved in the partial symbol tables, since
+ different tables may come from different source files. FIXME.
+ This routine should then walk down each partial symbol table
+ and see if the symbol table that it originates from has been changed */
+
+ for (objfile = object_files; objfile; objfile = objfile->next) {
+ if (objfile->obfd) {
+#ifdef IBM6000_TARGET
+ /* If this object is from a shared library, then you should
+ stat on the library name, not member name. */
+
+ if (objfile->obfd->my_archive)
+ res = stat (objfile->obfd->my_archive->filename, &new_statbuf);
+ else
+#endif
+ res = stat (objfile->name, &new_statbuf);
+ if (res != 0) {
+ /* FIXME, should use print_sys_errmsg but it's not filtered. */
+ printf_filtered ("`%s' has disappeared; keeping its symbols.\n",
+ objfile->name);
+ continue;
+ }
+ new_modtime = new_statbuf.st_mtime;
+ if (new_modtime != objfile->mtime)
+ {
+ struct cleanup *old_cleanups;
+ struct section_offsets *offsets;
+ int num_offsets;
+ int section_offsets_size;
+ char *obfd_filename;
+
+ 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. */
+ obfd_filename = bfd_get_filename (objfile->obfd);
+ if (!bfd_close (objfile->obfd))
+ error ("Can't close BFD for %s: %s", objfile->name,
+ bfd_errmsg (bfd_get_error ()));
+ objfile->obfd = bfd_openr (obfd_filename, 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);
+ memset (&objfile -> global_psymbols, 0,
+ sizeof (objfile -> global_psymbols));
+ if (objfile->static_psymbols.list)
+ mfree (objfile->md, objfile->static_psymbols.list);
+ memset (&objfile -> static_psymbols, 0,
+ sizeof (objfile -> static_psymbols));
+
+ /* Free the obstacks for non-reusable objfiles */
+ obstack_free (&objfile -> psymbol_cache.cache, 0);
+ memset (&objfile -> psymbol_cache, 0,
+ sizeof (objfile -> psymbol_cache));
+ 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_cache.cache, 0, 0,
+ xmalloc, free);
+ 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;
+
+ /* Call this after reading in a new symbol table to give target
+ dependant code a crack at the new symbols. For instance, this
+ could be used to update the values of target-specific symbols GDB
+ needs to keep track of (such as _sigtramp, or whatever). */
+
+ TARGET_SYMFILE_POSTREAD (objfile);
+ }
+ }
+ }
+
+ if (reread_one)
+ clear_symtab_users ();
+}
+
+
+enum language
+deduce_language_from_filename (filename)
+ char *filename;
+{
+ char *c;
+
+ if (0 == filename)
+ ; /* Get default */
+ else if (0 == (c = strrchr (filename, '.')))
+ ; /* Get default. */
+ else if (STREQ (c, ".c"))
+ return language_c;
+ else if (STREQ (c, ".cc") || STREQ (c, ".C") || STREQ (c, ".cxx")
+ || STREQ (c, ".cpp") || STREQ (c, ".cp") || STREQ (c, ".c++"))
+ return language_cplus;
+ else if (STREQ (c, ".ch") || STREQ (c, ".c186") || STREQ (c, ".c286"))
+ return language_chill;
+ else if (STREQ (c, ".f") || STREQ (c, ".F"))
+ return language_fortran;
+ else if (STREQ (c, ".mod"))
+ return language_m2;
+ else if (STREQ (c, ".s") || STREQ (c, ".S"))
+ return language_asm;
+
+ return language_unknown; /* default */
+}
+
+/* allocate_symtab:
+
+ Allocate and partly initialize a new symbol table. Return a pointer
+ to it. error() if no space.
+
+ Caller must set these fields:
+ LINETABLE(symtab)
+ symtab->blockvector
+ symtab->dirname
+ symtab->free_code
+ symtab->free_ptr
+ initialize any EXTRA_SYMTAB_INFO
+ possibly free_named_symtabs (symtab->filename);
+ */
+
+struct symtab *
+allocate_symtab (filename, objfile)
+ char *filename;
+ struct objfile *objfile;
+{
+ register struct symtab *symtab;
+
+ symtab = (struct symtab *)
+ obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symtab));
+ memset (symtab, 0, sizeof (*symtab));
+ symtab -> filename = obsavestring (filename, strlen (filename),
+ &objfile -> symbol_obstack);
+ symtab -> fullname = NULL;
+ symtab -> language = deduce_language_from_filename (filename);
+
+ /* Hook it to the objfile it comes from */
+
+ symtab -> objfile = objfile;
+ symtab -> next = objfile -> symtabs;
+ objfile -> symtabs = symtab;
+
+#ifdef INIT_EXTRA_SYMTAB_INFO
+ INIT_EXTRA_SYMTAB_INFO (symtab);
+#endif
+
+ return (symtab);
+}
+
+struct partial_symtab *
+allocate_psymtab (filename, objfile)
+ char *filename;
+ struct objfile *objfile;
+{
+ struct partial_symtab *psymtab;
+
+ if (objfile -> free_psymtabs)
+ {
+ psymtab = objfile -> free_psymtabs;
+ objfile -> free_psymtabs = psymtab -> next;
+ }
+ else
+ psymtab = (struct partial_symtab *)
+ obstack_alloc (&objfile -> psymbol_obstack,
+ sizeof (struct partial_symtab));
+
+ memset (psymtab, 0, sizeof (struct partial_symtab));
+ psymtab -> filename = obsavestring (filename, strlen (filename),
+ &objfile -> psymbol_obstack);
+ psymtab -> symtab = NULL;
+
+ /* Hook it to the objfile it comes from */
+
+ psymtab -> objfile = objfile;
+ psymtab -> next = objfile -> psymtabs;
+ objfile -> psymtabs = psymtab;
+
+ return (psymtab);
+}
+
+
+/* Reset all data structures in gdb which may contain references to symbol
+ table date. */
+
+void
+clear_symtab_users ()
+{
+ /* Someday, we should do better than this, by only blowing away
+ the things that really need to be blown. */
+ clear_value_history ();
+ clear_displays ();
+ clear_internalvars ();
+ breakpoint_re_set ();
+ set_default_breakpoint (0, 0, 0, 0);
+ current_source_symtab = 0;
+ current_source_line = 0;
+ clear_pc_function_cache ();
+}
+
+/* clear_symtab_users_once:
+
+ This function is run after symbol reading, or from a cleanup.
+ If an old symbol table was obsoleted, the old symbol table
+ has been blown away, but the other GDB data structures that may
+ reference it have not yet been cleared or re-directed. (The old
+ symtab was zapped, and the cleanup queued, in free_named_symtab()
+ below.)
+
+ This function can be queued N times as a cleanup, or called
+ directly; it will do all the work the first time, and then will be a
+ no-op until the next time it is queued. This works by bumping a
+ counter at queueing time. Much later when the cleanup is run, or at
+ the end of symbol processing (in case the cleanup is discarded), if
+ the queued count is greater than the "done-count", we do the work
+ and set the done-count to the queued count. If the queued count is
+ less than or equal to the done-count, we just ignore the call. This
+ is needed because reading a single .o file will often replace many
+ symtabs (one per .h file, for example), and we don't want to reset
+ the breakpoints N times in the user's face.
+
+ The reason we both queue a cleanup, and call it directly after symbol
+ reading, is because the cleanup protects us in case of errors, but is
+ discarded if symbol reading is successful. */
+
+#if 0
+/* FIXME: As free_named_symtabs is currently a big noop this function
+ is no longer needed. */
+static void
+clear_symtab_users_once PARAMS ((void));
+
+static int clear_symtab_users_queued;
+static int clear_symtab_users_done;
+
+static void
+clear_symtab_users_once ()
+{
+ /* Enforce once-per-`do_cleanups'-semantics */
+ if (clear_symtab_users_queued <= clear_symtab_users_done)
+ return;
+ clear_symtab_users_done = clear_symtab_users_queued;
+
+ clear_symtab_users ();
+}
+#endif
+
+/* Delete the specified psymtab, and any others that reference it. */
+
+static void
+cashier_psymtab (pst)
+ struct partial_symtab *pst;
+{
+ struct partial_symtab *ps, *pprev = NULL;
+ int i;
+
+ /* Find its previous psymtab in the chain */
+ for (ps = pst->objfile->psymtabs; ps; ps = ps->next) {
+ if (ps == pst)
+ break;
+ pprev = ps;
+ }
+
+ if (ps) {
+ /* Unhook it from the chain. */
+ if (ps == pst->objfile->psymtabs)
+ pst->objfile->psymtabs = ps->next;
+ else
+ pprev->next = ps->next;
+
+ /* FIXME, we can't conveniently deallocate the entries in the
+ partial_symbol lists (global_psymbols/static_psymbols) that
+ this psymtab points to. These just take up space until all
+ the psymtabs are reclaimed. Ditto the dependencies list and
+ filename, which are all in the psymbol_obstack. */
+
+ /* We need to cashier any psymtab that has this one as a dependency... */
+again:
+ for (ps = pst->objfile->psymtabs; ps; ps = ps->next) {
+ for (i = 0; i < ps->number_of_dependencies; i++) {
+ if (ps->dependencies[i] == pst) {
+ cashier_psymtab (ps);
+ goto again; /* Must restart, chain has been munged. */
+ }
+ }
+ }
+ }
+}
+
+/* If a symtab or psymtab for filename NAME is found, free it along
+ with any dependent breakpoints, displays, etc.
+ Used when loading new versions of object modules with the "add-file"
+ command. This is only called on the top-level symtab or psymtab's name;
+ it is not called for subsidiary files such as .h files.
+
+ Return value is 1 if we blew away the environment, 0 if not.
+ FIXME. The return valu appears to never be used.
+
+ FIXME. I think this is not the best way to do this. We should
+ work on being gentler to the environment while still cleaning up
+ all stray pointers into the freed symtab. */
+
+int
+free_named_symtabs (name)
+ char *name;
+{
+#if 0
+ /* FIXME: With the new method of each objfile having it's own
+ psymtab list, this function needs serious rethinking. In particular,
+ why was it ever necessary to toss psymtabs with specific compilation
+ unit filenames, as opposed to all psymtabs from a particular symbol
+ file? -- fnf
+ Well, the answer is that some systems permit reloading of particular
+ compilation units. We want to blow away any old info about these
+ compilation units, regardless of which objfiles they arrived in. --gnu. */
+
+ register struct symtab *s;
+ register struct symtab *prev;
+ register struct partial_symtab *ps;
+ struct blockvector *bv;
+ int blewit = 0;
+
+ /* We only wack things if the symbol-reload switch is set. */
+ if (!symbol_reloading)
+ return 0;
+
+ /* Some symbol formats have trouble providing file names... */
+ if (name == 0 || *name == '\0')
+ return 0;
+
+ /* Look for a psymtab with the specified name. */
+
+again2:
+ for (ps = partial_symtab_list; ps; ps = ps->next) {
+ if (STREQ (name, ps->filename)) {
+ cashier_psymtab (ps); /* Blow it away...and its little dog, too. */
+ goto again2; /* Must restart, chain has been munged */
+ }
+ }
+
+ /* Look for a symtab with the specified name. */
+
+ for (s = symtab_list; s; s = s->next)
+ {
+ if (STREQ (name, s->filename))
+ break;
+ prev = s;
+ }
+
+ if (s)
+ {
+ if (s == symtab_list)
+ symtab_list = s->next;
+ else
+ prev->next = s->next;
+
+ /* For now, queue a delete for all breakpoints, displays, etc., whether
+ or not they depend on the symtab being freed. This should be
+ changed so that only those data structures affected are deleted. */
+
+ /* But don't delete anything if the symtab is empty.
+ This test is necessary due to a bug in "dbxread.c" that
+ causes empty symtabs to be created for N_SO symbols that
+ contain the pathname of the object file. (This problem
+ has been fixed in GDB 3.9x). */
+
+ bv = BLOCKVECTOR (s);
+ if (BLOCKVECTOR_NBLOCKS (bv) > 2
+ || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK))
+ || BLOCK_NSYMS (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)))
+ {
+ complain (&oldsyms_complaint, name);
+
+ clear_symtab_users_queued++;
+ make_cleanup (clear_symtab_users_once, 0);
+ blewit = 1;
+ } else {
+ complain (&empty_symtab_complaint, name);
+ }
+
+ free_symtab (s);
+ }
+ else
+ {
+ /* It is still possible that some breakpoints will be affected
+ even though no symtab was found, since the file might have
+ been compiled without debugging, and hence not be associated
+ with a symtab. In order to handle this correctly, we would need
+ to keep a list of text address ranges for undebuggable files.
+ For now, we do nothing, since this is a fairly obscure case. */
+ ;
+ }
+
+ /* FIXME, what about the minimal symbol table? */
+ return blewit;
+#else
+ return (0);
+#endif
+}
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+
+struct partial_symtab *
+start_psymtab_common (objfile, section_offsets,
+ filename, textlow, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ CORE_ADDR textlow;
+ struct partial_symbol **global_syms;
+ struct partial_symbol **static_syms;
+{
+ struct partial_symtab *psymtab;
+
+ psymtab = allocate_psymtab (filename, objfile);
+ psymtab -> section_offsets = section_offsets;
+ psymtab -> textlow = textlow;
+ psymtab -> texthigh = psymtab -> textlow; /* default */
+ psymtab -> globals_offset = global_syms - objfile -> global_psymbols.list;
+ psymtab -> statics_offset = static_syms - objfile -> static_psymbols.list;
+ return (psymtab);
+}
+
+/* Add a symbol with a long value to a psymtab.
+ Since one arg is a struct, we pass in a ptr and deref it (sigh). */
+
+void
+add_psymbol_to_list (name, namelength, namespace, class, list, val, coreaddr,
+ language, objfile)
+ char *name;
+ int namelength;
+ namespace_enum namespace;
+ enum address_class class;
+ struct psymbol_allocation_list *list;
+ long val; /* Value as a long */
+ CORE_ADDR coreaddr; /* Value as a CORE_ADDR */
+ enum language language;
+ struct objfile *objfile;
+{
+ register struct partial_symbol *psym;
+ char *buf = alloca (namelength + 1);
+ /* psymbol is static so that there will be no uninitialized gaps in the
+ structure which might contain random data, causing cache misses in
+ bcache. */
+ static struct partial_symbol psymbol;
+
+ /* Create local copy of the partial symbol */
+ memcpy (buf, name, namelength);
+ buf[namelength] = '\0';
+ SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache);
+ /* val and coreaddr are mutually exclusive, one of them *will* be zero */
+ if (val != 0)
+ {
+ SYMBOL_VALUE (&psymbol) = val;
+ }
+ else
+ {
+ SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr;
+ }
+ SYMBOL_SECTION (&psymbol) = 0;
+ SYMBOL_LANGUAGE (&psymbol) = language;
+ PSYMBOL_NAMESPACE (&psymbol) = namespace;
+ PSYMBOL_CLASS (&psymbol) = class;
+ SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language);
+
+ /* Stash the partial symbol away in the cache */
+ psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache);
+
+ /* Save pointer to partial symbol in psymtab, growing symtab if needed. */
+ if (list->next >= list->list + list->size)
+ {
+ extend_psymbol_list (list, objfile);
+ }
+ *list->next++ = psym;
+ OBJSTAT (objfile, n_psyms++);
+}
+
+/* Initialize storage for partial symbols. */
+
+void
+init_psymbol_list (objfile, total_symbols)
+ struct objfile *objfile;
+ int total_symbols;
+{
+ /* Free any previously allocated psymbol lists. */
+
+ if (objfile -> global_psymbols.list)
+ {
+ mfree (objfile -> md, (PTR)objfile -> global_psymbols.list);
+ }
+ if (objfile -> static_psymbols.list)
+ {
+ mfree (objfile -> md, (PTR)objfile -> static_psymbols.list);
+ }
+
+ /* Current best guess is that approximately a twentieth
+ of the total symbols (in a debugging file) are global or static
+ oriented symbols */
+
+ objfile -> global_psymbols.size = total_symbols / 10;
+ objfile -> static_psymbols.size = total_symbols / 10;
+ objfile -> global_psymbols.next =
+ objfile -> global_psymbols.list = (struct partial_symbol **)
+ xmmalloc (objfile -> md, objfile -> global_psymbols.size
+ * sizeof (struct partial_symbol *));
+ objfile -> static_psymbols.next =
+ objfile -> static_psymbols.list = (struct partial_symbol **)
+ xmmalloc (objfile -> md, objfile -> static_psymbols.size
+ * sizeof (struct partial_symbol *));
+}
+
+void
+_initialize_symfile ()
+{
+ struct cmd_list_element *c;
+
+ c = add_cmd ("symbol-file", class_files, symbol_file_command,
+ "Load symbol table from executable file FILE.\n\
+The `file' command can also load symbol tables, as well as setting the file\n\
+to execute.", &cmdlist);
+ c->completer = filename_completer;
+
+ c = add_cmd ("add-symbol-file", class_files, add_symbol_file_command,
+ "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);
+ c->completer = filename_completer;
+
+ add_show_from_set
+ (add_set_cmd ("symbol-reloading", class_support, var_boolean,
+ (char *)&symbol_reloading,
+ "Set dynamic symbol table reloading multiple times in one run.",
+ &setlist),
+ &showlist);
+
+}
diff --git a/contrib/gdb/gdb/symfile.h b/contrib/gdb/gdb/symfile.h
new file mode 100644
index 0000000..d173f4e
--- /dev/null
+++ b/contrib/gdb/gdb/symfile.h
@@ -0,0 +1,211 @@
+/* Definitions for reading symbol files into GDB.
+ Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (SYMFILE_H)
+#define SYMFILE_H
+
+/* This file requires that you first include "bfd.h". */
+
+/* Partial symbols are stored in the psymbol_cache and pointers to them
+ are kept in a dynamically grown array that is obtained from malloc and
+ grown as necessary via realloc. Each objfile typically has two of these,
+ one for global symbols and one for static symbols. Although this adds
+ a level of indirection for storing or accessing the partial symbols,
+ it allows us to throw away duplicate psymbols and set all pointers
+ to the single saved instance. */
+
+struct psymbol_allocation_list {
+ struct partial_symbol **list; /* Pointer to first partial symbol pointer*/
+ struct partial_symbol **next; /* Pointer to next avail storage for pointer */
+ int size; /* Number of symbols */
+};
+
+/* Structure to keep track of symbol reading functions for various
+ object file types. */
+
+struct sym_fns {
+
+ /* BFD flavour that we handle, or (as a special kludge, see xcoffread.c,
+ (enum bfd_flavour)-1 for xcoff). */
+
+ 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
+ program. */
+
+ void (*sym_new_init) PARAMS ((struct objfile *));
+
+ /* Reads any initial information from a symbol file, and initializes the
+ struct sym_fns SF in preparation for sym_read(). It is called every
+ time we read a symbol file for any reason. */
+
+ void (*sym_init) PARAMS ((struct objfile *));
+
+ /* sym_read (objfile, addr, mainline)
+ Reads a symbol file into a psymtab (or possibly a symtab).
+ OBJFILE is the objfile struct for the file we are reading.
+ SECTION_OFFSETS
+ are the offset between the file's specified section addresses and
+ their true addresses in memory.
+ MAINLINE is 1 if this is the
+ main symbol table being read, and 0 if a secondary
+ symbol file (e.g. shared library or dynamically loaded file)
+ is being read. */
+
+ void (*sym_read) PARAMS ((struct objfile *, struct section_offsets *, int));
+
+ /* Called when we are finished with an objfile. Should do all cleanup
+ that is specific to the object file format for the particular objfile. */
+
+ void (*sym_finish) PARAMS ((struct objfile *));
+
+ /* This function produces a file-dependent section_offsets structure,
+ allocated in the objfile's storage, and based on the parameter.
+ The parameter is currently a CORE_ADDR (FIXME!) for backward compatibility
+ with the higher levels of GDB. It should probably be changed to
+ a string, where NULL means the default, and others are parsed in a file
+ dependent way. The result of this function is handed in to sym_read. */
+
+ struct section_offsets *(*sym_offsets) PARAMS ((struct objfile *, CORE_ADDR));
+
+ /* Finds the next struct sym_fns. They are allocated and initialized
+ in whatever module implements the functions pointed to; an
+ initializer calls add_symtab_fns to add them to the global chain. */
+
+ struct sym_fns *next;
+
+};
+
+extern void
+extend_psymbol_list PARAMS ((struct psymbol_allocation_list *,
+ struct objfile *));
+
+/* Add any kind of symbol to a psymbol_allocation_list. */
+
+/* #include "demangle.h" */
+
+extern void
+add_psymbol_to_list PARAMS ((char *, int, namespace_enum, enum address_class,
+ struct psymbol_allocation_list *, long, CORE_ADDR,
+ enum language, struct objfile *));
+
+extern void init_psymbol_list PARAMS ((struct objfile *, int));
+
+extern void
+sort_pst_symbols PARAMS ((struct partial_symtab *));
+
+extern struct symtab *
+allocate_symtab PARAMS ((char *, struct objfile *));
+
+extern int
+free_named_symtabs PARAMS ((char *));
+
+extern void
+fill_in_vptr_fieldno PARAMS ((struct type *));
+
+extern void
+add_symtab_fns PARAMS ((struct sym_fns *));
+
+extern void
+init_entry_point_info PARAMS ((struct objfile *));
+
+extern void
+syms_from_objfile PARAMS ((struct objfile *, CORE_ADDR, int, int));
+
+extern void
+new_symfile_objfile PARAMS ((struct objfile *, int, int));
+
+extern struct partial_symtab *
+start_psymtab_common PARAMS ((struct objfile *, struct section_offsets *,
+ char *, CORE_ADDR,
+ struct partial_symbol **,
+ struct partial_symbol **));
+
+/* Sorting your symbols for fast lookup or alphabetical printing. */
+
+extern void
+sort_block_syms PARAMS ((struct block *));
+
+extern void
+sort_symtab_syms PARAMS ((struct symtab *));
+
+/* 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. */
+
+extern char *
+obsavestring PARAMS ((char *, int, struct obstack *));
+
+/* Concatenate strings S1, S2 and S3; return the new string.
+ Space is found in the symbol_obstack. */
+
+extern char *
+obconcat PARAMS ((struct obstack *obstackp, const char *, const char *,
+ const char *));
+
+ /* Variables */
+
+/* whether to auto load solibs at startup time: 0/1. */
+
+extern int auto_solib_add;
+
+/* From symfile.c */
+
+extern struct partial_symtab *
+allocate_psymtab PARAMS ((char *, struct objfile *));
+
+extern void find_lowest_section PARAMS ((bfd *, asection *, PTR));
+
+/* Remote targets may wish to use this as their load function. */
+extern void generic_load PARAMS ((char *name, int from_tty));
+
+/* From dwarfread.c */
+
+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 *));
+
+#endif /* !defined(SYMFILE_H) */
diff --git a/contrib/gdb/gdb/symm-nat.c b/contrib/gdb/gdb/symm-nat.c
new file mode 100644
index 0000000..0461066
--- /dev/null
+++ b/contrib/gdb/gdb/symm-nat.c
@@ -0,0 +1,846 @@
+/* Sequent Symmetry host interface, for GDB when running under Unix.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* FIXME, some 387-specific items of use taken from i387-tdep.c -- ought to be
+ merged back in. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+
+/* FIXME: What is the _INKERNEL define for? */
+#define _INKERNEL
+#include <signal.h>
+#undef _INKERNEL
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include "gdb_stat.h"
+#ifdef _SEQUENT_
+#include <sys/ptrace.h>
+#else
+/* Dynix has only machine/ptrace.h, which is already included by sys/user.h */
+/* Dynix has no mptrace call */
+#define mptrace ptrace
+#endif
+#include "gdbcore.h"
+#include <fcntl.h>
+#include <sgtty.h>
+#define TERMINAL struct sgttyb
+
+#include "gdbcore.h"
+
+void
+store_inferior_registers(regno)
+int regno;
+{
+ struct pt_regset regs;
+ int i;
+ extern char registers[];
+
+ /* FIXME: Fetching the registers is a kludge to initialize all elements
+ in the fpu and fpa status. This works for normal debugging, but
+ might cause problems when calling functions in the inferior.
+ At least fpu_control and fpa_pcr (probably more) should be added
+ to the registers array to solve this properly. */
+ mptrace (XPT_RREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+
+ regs.pr_eax = *(int *)&registers[REGISTER_BYTE(0)];
+ regs.pr_ebx = *(int *)&registers[REGISTER_BYTE(5)];
+ regs.pr_ecx = *(int *)&registers[REGISTER_BYTE(2)];
+ regs.pr_edx = *(int *)&registers[REGISTER_BYTE(1)];
+ regs.pr_esi = *(int *)&registers[REGISTER_BYTE(6)];
+ regs.pr_edi = *(int *)&registers[REGISTER_BYTE(7)];
+ regs.pr_esp = *(int *)&registers[REGISTER_BYTE(14)];
+ regs.pr_ebp = *(int *)&registers[REGISTER_BYTE(15)];
+ regs.pr_eip = *(int *)&registers[REGISTER_BYTE(16)];
+ regs.pr_flags = *(int *)&registers[REGISTER_BYTE(17)];
+ for (i = 0; i < 31; i++)
+ {
+ regs.pr_fpa.fpa_regs[i] =
+ *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)];
+ }
+ memcpy (regs.pr_fpu.fpu_stack[0], &registers[REGISTER_BYTE(ST0_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[1], &registers[REGISTER_BYTE(ST1_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[2], &registers[REGISTER_BYTE(ST2_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[3], &registers[REGISTER_BYTE(ST3_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[4], &registers[REGISTER_BYTE(ST4_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[5], &registers[REGISTER_BYTE(ST5_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[6], &registers[REGISTER_BYTE(ST6_REGNUM)], 10);
+ memcpy (regs.pr_fpu.fpu_stack[7], &registers[REGISTER_BYTE(ST7_REGNUM)], 10);
+ mptrace (XPT_WREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+}
+
+void
+fetch_inferior_registers (regno)
+ int regno;
+{
+ int i;
+ struct pt_regset regs;
+ extern char registers[];
+
+ registers_fetched ();
+
+ mptrace (XPT_RREGS, inferior_pid, (PTRACE_ARG3_TYPE) &regs, 0);
+ *(int *)&registers[REGISTER_BYTE(EAX_REGNUM)] = regs.pr_eax;
+ *(int *)&registers[REGISTER_BYTE(EBX_REGNUM)] = regs.pr_ebx;
+ *(int *)&registers[REGISTER_BYTE(ECX_REGNUM)] = regs.pr_ecx;
+ *(int *)&registers[REGISTER_BYTE(EDX_REGNUM)] = regs.pr_edx;
+ *(int *)&registers[REGISTER_BYTE(ESI_REGNUM)] = regs.pr_esi;
+ *(int *)&registers[REGISTER_BYTE(EDI_REGNUM)] = regs.pr_edi;
+ *(int *)&registers[REGISTER_BYTE(EBP_REGNUM)] = regs.pr_ebp;
+ *(int *)&registers[REGISTER_BYTE(ESP_REGNUM)] = regs.pr_esp;
+ *(int *)&registers[REGISTER_BYTE(EIP_REGNUM)] = regs.pr_eip;
+ *(int *)&registers[REGISTER_BYTE(EFLAGS_REGNUM)] = regs.pr_flags;
+ for (i = 0; i < FPA_NREGS; i++)
+ {
+ *(int *)&registers[REGISTER_BYTE(FP1_REGNUM+i)] =
+ regs.pr_fpa.fpa_regs[i];
+ }
+ memcpy (&registers[REGISTER_BYTE(ST0_REGNUM)], regs.pr_fpu.fpu_stack[0], 10);
+ memcpy (&registers[REGISTER_BYTE(ST1_REGNUM)], regs.pr_fpu.fpu_stack[1], 10);
+ memcpy (&registers[REGISTER_BYTE(ST2_REGNUM)], regs.pr_fpu.fpu_stack[2], 10);
+ memcpy (&registers[REGISTER_BYTE(ST3_REGNUM)], regs.pr_fpu.fpu_stack[3], 10);
+ memcpy (&registers[REGISTER_BYTE(ST4_REGNUM)], regs.pr_fpu.fpu_stack[4], 10);
+ memcpy (&registers[REGISTER_BYTE(ST5_REGNUM)], regs.pr_fpu.fpu_stack[5], 10);
+ memcpy (&registers[REGISTER_BYTE(ST6_REGNUM)], regs.pr_fpu.fpu_stack[6], 10);
+ memcpy (&registers[REGISTER_BYTE(ST7_REGNUM)], regs.pr_fpu.fpu_stack[7], 10);
+}
+
+/* FIXME: This should be merged with i387-tdep.c as well. */
+static
+print_fpu_status(ep)
+struct pt_regset ep;
+{
+ int i;
+ int bothstatus;
+ int top;
+ int fpreg;
+ unsigned char *p;
+
+ printf_unfiltered("80387:");
+ if (ep.pr_fpu.fpu_ip == 0) {
+ printf_unfiltered(" not in use.\n");
+ return;
+ } else {
+ printf_unfiltered("\n");
+ }
+ if (ep.pr_fpu.fpu_status != 0) {
+ print_387_status_word (ep.pr_fpu.fpu_status);
+ }
+ print_387_control_word (ep.pr_fpu.fpu_control);
+ printf_unfiltered ("last exception: ");
+ printf_unfiltered ("opcode 0x%x; ", ep.pr_fpu.fpu_rsvd4);
+ printf_unfiltered ("pc 0x%x:0x%x; ", ep.pr_fpu.fpu_cs, ep.pr_fpu.fpu_ip);
+ printf_unfiltered ("operand 0x%x:0x%x\n", ep.pr_fpu.fpu_data_offset, ep.pr_fpu.fpu_op_sel);
+
+ top = (ep.pr_fpu.fpu_status >> 11) & 7;
+
+ printf_unfiltered ("regno tag msb lsb value\n");
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ double val;
+
+ printf_unfiltered ("%s %d: ", fpreg == top ? "=>" : " ", fpreg);
+
+ switch ((ep.pr_fpu.fpu_tag >> (fpreg * 2)) & 3)
+ {
+ case 0: printf_unfiltered ("valid "); break;
+ case 1: printf_unfiltered ("zero "); break;
+ case 2: printf_unfiltered ("trap "); break;
+ case 3: printf_unfiltered ("empty "); break;
+ }
+ for (i = 9; i >= 0; i--)
+ printf_unfiltered ("%02x", ep.pr_fpu.fpu_stack[fpreg][i]);
+
+ i387_to_double ((char *)ep.pr_fpu.fpu_stack[fpreg], (char *)&val);
+ printf_unfiltered (" %g\n", val);
+ }
+ if (ep.pr_fpu.fpu_rsvd1)
+ warning ("rsvd1 is 0x%x\n", ep.pr_fpu.fpu_rsvd1);
+ if (ep.pr_fpu.fpu_rsvd2)
+ warning ("rsvd2 is 0x%x\n", ep.pr_fpu.fpu_rsvd2);
+ if (ep.pr_fpu.fpu_rsvd3)
+ warning ("rsvd3 is 0x%x\n", ep.pr_fpu.fpu_rsvd3);
+ if (ep.pr_fpu.fpu_rsvd5)
+ warning ("rsvd5 is 0x%x\n", ep.pr_fpu.fpu_rsvd5);
+}
+
+
+print_1167_control_word(pcr)
+unsigned int pcr;
+
+{
+ int pcr_tmp;
+
+ pcr_tmp = pcr & FPA_PCR_MODE;
+ printf_unfiltered("\tMODE= %#x; RND= %#x ", pcr_tmp, pcr_tmp & 12);
+ switch (pcr_tmp & 12) {
+ case 0:
+ printf_unfiltered("RN (Nearest Value)");
+ break;
+ case 1:
+ printf_unfiltered("RZ (Zero)");
+ break;
+ case 2:
+ printf_unfiltered("RP (Positive Infinity)");
+ break;
+ case 3:
+ printf_unfiltered("RM (Negative Infinity)");
+ break;
+ }
+ printf_unfiltered("; IRND= %d ", pcr_tmp & 2);
+ if (0 == pcr_tmp & 2) {
+ printf_unfiltered("(same as RND)\n");
+ } else {
+ printf_unfiltered("(toward zero)\n");
+ }
+ pcr_tmp = pcr & FPA_PCR_EM;
+ printf_unfiltered("\tEM= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_EM_DM) printf_unfiltered(" DM");
+ if (pcr_tmp & FPA_PCR_EM_UOM) printf_unfiltered(" UOM");
+ if (pcr_tmp & FPA_PCR_EM_PM) printf_unfiltered(" PM");
+ if (pcr_tmp & FPA_PCR_EM_UM) printf_unfiltered(" UM");
+ if (pcr_tmp & FPA_PCR_EM_OM) printf_unfiltered(" OM");
+ if (pcr_tmp & FPA_PCR_EM_ZM) printf_unfiltered(" ZM");
+ if (pcr_tmp & FPA_PCR_EM_IM) printf_unfiltered(" IM");
+ printf_unfiltered("\n");
+ pcr_tmp = FPA_PCR_CC;
+ printf_unfiltered("\tCC= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_20MHZ) printf_unfiltered(" 20MHZ");
+ if (pcr_tmp & FPA_PCR_CC_Z) printf_unfiltered(" Z");
+ if (pcr_tmp & FPA_PCR_CC_C2) printf_unfiltered(" C2");
+
+ /* Dynix defines FPA_PCR_CC_C0 to 0x100 and ptx defines
+ FPA_PCR_CC_C1 to 0x100. Use whichever is defined and assume
+ the OS knows what it is doing. */
+#ifdef FPA_PCR_CC_C1
+ if (pcr_tmp & FPA_PCR_CC_C1) printf_unfiltered(" C1");
+#else
+ if (pcr_tmp & FPA_PCR_CC_C0) printf_unfiltered(" C0");
+#endif
+
+ switch (pcr_tmp)
+ {
+ case FPA_PCR_CC_Z:
+ printf_unfiltered(" (Equal)");
+ break;
+#ifdef FPA_PCR_CC_C1
+ case FPA_PCR_CC_C1:
+#else
+ case FPA_PCR_CC_C0:
+#endif
+ printf_unfiltered(" (Less than)");
+ break;
+ case 0:
+ printf_unfiltered(" (Greater than)");
+ break;
+ case FPA_PCR_CC_Z |
+#ifdef FPA_PCR_CC_C1
+ FPA_PCR_CC_C1
+#else
+ FPA_PCR_CC_C0
+#endif
+ | FPA_PCR_CC_C2:
+ printf_unfiltered(" (Unordered)");
+ break;
+ default:
+ printf_unfiltered(" (Undefined)");
+ break;
+ }
+ printf_unfiltered("\n");
+ pcr_tmp = pcr & FPA_PCR_AE;
+ printf_unfiltered("\tAE= %#x", pcr_tmp);
+ if (pcr_tmp & FPA_PCR_AE_DE) printf_unfiltered(" DE");
+ if (pcr_tmp & FPA_PCR_AE_UOE) printf_unfiltered(" UOE");
+ if (pcr_tmp & FPA_PCR_AE_PE) printf_unfiltered(" PE");
+ if (pcr_tmp & FPA_PCR_AE_UE) printf_unfiltered(" UE");
+ if (pcr_tmp & FPA_PCR_AE_OE) printf_unfiltered(" OE");
+ if (pcr_tmp & FPA_PCR_AE_ZE) printf_unfiltered(" ZE");
+ if (pcr_tmp & FPA_PCR_AE_EE) printf_unfiltered(" EE");
+ if (pcr_tmp & FPA_PCR_AE_IE) printf_unfiltered(" IE");
+ printf_unfiltered("\n");
+}
+
+print_1167_regs(regs)
+long regs[FPA_NREGS];
+
+{
+ int i;
+
+ union {
+ double d;
+ long l[2];
+ } xd;
+ union {
+ float f;
+ long l;
+ } xf;
+
+
+ for (i = 0; i < FPA_NREGS; i++) {
+ xf.l = regs[i];
+ printf_unfiltered("%%fp%d: raw= %#x, single= %f", i+1, regs[i], xf.f);
+ if (!(i & 1)) {
+ printf_unfiltered("\n");
+ } else {
+ xd.l[1] = regs[i];
+ xd.l[0] = regs[i+1];
+ printf_unfiltered(", double= %f\n", xd.d);
+ }
+ }
+}
+
+print_fpa_status(ep)
+struct pt_regset ep;
+
+{
+
+ printf_unfiltered("WTL 1167:");
+ if (ep.pr_fpa.fpa_pcr !=0) {
+ printf_unfiltered("\n");
+ print_1167_control_word(ep.pr_fpa.fpa_pcr);
+ print_1167_regs(ep.pr_fpa.fpa_regs);
+ } else {
+ printf_unfiltered(" not in use.\n");
+ }
+}
+
+#if 0 /* disabled because it doesn't go through the target vector. */
+i386_float_info ()
+{
+ char ubuf[UPAGES*NBPG];
+ struct pt_regset regset;
+
+ if (have_inferior_p())
+ {
+ PTRACE_READ_REGS (inferior_pid, (PTRACE_ARG3_TYPE) &regset);
+ }
+ else
+ {
+ int corechan = bfd_cache_lookup (core_bfd);
+ if (lseek (corechan, 0, 0) < 0)
+ {
+ perror ("seek on core file");
+ }
+ if (myread (corechan, ubuf, UPAGES*NBPG) < 0)
+ {
+ perror ("read on core file");
+ }
+ /* only interested in the floating point registers */
+ regset.pr_fpu = ((struct user *) ubuf)->u_fpusave;
+ regset.pr_fpa = ((struct user *) ubuf)->u_fpasave;
+ }
+ print_fpu_status(regset);
+ print_fpa_status(regset);
+}
+#endif
+
+static volatile int got_sigchld;
+
+/*ARGSUSED*/
+/* This will eventually be more interesting. */
+void
+sigchld_handler(signo)
+ int signo;
+{
+ got_sigchld++;
+}
+
+/*
+ * Signals for which the default action does not cause the process
+ * to die. See <sys/signal.h> for where this came from (alas, we
+ * can't use those macros directly)
+ */
+#ifndef sigmask
+#define sigmask(s) (1 << ((s) - 1))
+#endif
+#define SIGNALS_DFL_SAFE sigmask(SIGSTOP) | sigmask(SIGTSTP) | \
+ sigmask(SIGTTIN) | sigmask(SIGTTOU) | sigmask(SIGCHLD) | \
+ sigmask(SIGCONT) | sigmask(SIGWINCH) | sigmask(SIGPWR) | \
+ sigmask(SIGURG) | sigmask(SIGPOLL)
+
+#ifdef ATTACH_DETACH
+/*
+ * Thanks to XPT_MPDEBUGGER, we have to mange child_wait().
+ */
+int
+child_wait(pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int save_errno, rv, xvaloff, saoff, sa_hand;
+ struct pt_stop pt;
+ struct user u;
+ sigset_t set;
+ /* Host signal number for a signal which the inferior terminates with, or
+ 0 if it hasn't terminated due to a signal. */
+ static int death_by_signal = 0;
+#ifdef SVR4_SHARED_LIBS /* use this to distinguish ptx 2 vs ptx 4 */
+ prstatus_t pstatus;
+#endif
+
+ do {
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ save_errno = errno;
+
+ got_sigchld = 0;
+
+ sigemptyset(&set);
+
+ while (got_sigchld == 0) {
+ sigsuspend(&set);
+ }
+
+ clear_sigint_trap();
+
+ rv = mptrace(XPT_STOPSTAT, 0, (char *)&pt, 0);
+ if (-1 == rv) {
+ printf("XPT_STOPSTAT: errno %d\n", errno); /* DEBUG */
+ continue;
+ }
+
+ pid = pt.ps_pid;
+
+ if (pid != inferior_pid) {
+ /* NOTE: the mystery fork in csh/tcsh needs to be ignored.
+ * We should not return new children for the initial run
+ * of a process until it has done the exec.
+ */
+ /* inferior probably forked; send it on its way */
+ rv = mptrace(XPT_UNDEBUG, pid, 0, 0);
+ if (-1 == rv) {
+ printf("child_wait: XPT_UNDEBUG: pid %d: %s\n", pid,
+ safe_strerror(errno));
+ }
+ continue;
+ }
+ /* FIXME: Do we deal with fork notification correctly? */
+ switch (pt.ps_reason) {
+ case PTS_FORK:
+ /* multi proc: treat like PTS_EXEC */
+ /*
+ * Pretend this didn't happen, since gdb isn't set up
+ * to deal with stops on fork.
+ */
+ rv = ptrace(PT_CONTSIG, pid, 1, 0);
+ if (-1 == rv) {
+ printf("PTS_FORK: PT_CONTSIG: error %d\n", errno);
+ }
+ continue;
+ case PTS_EXEC:
+ /*
+ * Pretend this is a SIGTRAP.
+ */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = TARGET_SIGNAL_TRAP;
+ break;
+ case PTS_EXIT:
+ /*
+ * Note: we stop before the exit actually occurs. Extract
+ * the exit code from the uarea. If we're stopped in the
+ * exit() system call, the exit code will be in
+ * u.u_ap[0]. An exit due to an uncaught signal will have
+ * something else in here, see the comment in the default:
+ * case, below. Finally,let the process exit.
+ */
+ if (death_by_signal)
+ {
+ status->kind = TARGET_WAITKIND_SIGNALED;
+ status->value.sig = target_signal_from_host (death_by_signal);
+ death_by_signal = 0;
+ break;
+ }
+ xvaloff = (unsigned long)&u.u_ap[0] - (unsigned long)&u;
+ errno = 0;
+ rv = ptrace(PT_RUSER, pid, (char *)xvaloff, 0);
+ status->kind = TARGET_WAITKIND_EXITED;
+ status->value.integer = rv;
+ /*
+ * addr & data to mptrace() don't matter here, since
+ * the process is already dead.
+ */
+ rv = mptrace(XPT_UNDEBUG, pid, 0, 0);
+ if (-1 == rv) {
+ printf("child_wait: PTS_EXIT: XPT_UNDEBUG: pid %d error %d\n", pid,
+ errno);
+ }
+ break;
+ case PTS_WATCHPT_HIT:
+ fatal("PTS_WATCHPT_HIT\n");
+ break;
+ default:
+ /* stopped by signal */
+ status->kind = TARGET_WAITKIND_STOPPED;
+ status->value.sig = target_signal_from_host (pt.ps_reason);
+ death_by_signal = 0;
+
+ if (0 == (SIGNALS_DFL_SAFE & sigmask(pt.ps_reason))) {
+ break;
+ }
+ /* else default action of signal is to die */
+#ifdef SVR4_SHARED_LIBS
+ rv = ptrace(PT_GET_PRSTATUS, pid, (char *)&pstatus, 0);
+ if (-1 == rv)
+ error("child_wait: signal %d PT_GET_PRSTATUS: %s\n",
+ pt.ps_reason, safe_strerror(errno));
+ if (pstatus.pr_cursig != pt.ps_reason) {
+ printf("pstatus signal %d, pt signal %d\n",
+ pstatus.pr_cursig, pt.ps_reason);
+ }
+ sa_hand = (int)pstatus.pr_action.sa_handler;
+#else
+ saoff = (unsigned long)&u.u_sa[0] - (unsigned long)&u;
+ saoff += sizeof(struct sigaction) * (pt.ps_reason - 1);
+ errno = 0;
+ sa_hand = ptrace(PT_RUSER, pid, (char *)saoff, 0);
+ if (errno)
+ error("child_wait: signal %d: RUSER: %s\n",
+ pt.ps_reason, safe_strerror(errno));
+#endif
+ if ((int)SIG_DFL == sa_hand) {
+ /* we will be dying */
+ death_by_signal = pt.ps_reason;
+ }
+ break;
+ }
+
+ } while (pid != inferior_pid); /* Some other child died or stopped */
+
+ return pid;
+}
+#else /* !ATTACH_DETACH */
+/*
+ * Simple child_wait() based on inftarg.c child_wait() for use until
+ * the MPDEBUGGER child_wait() works properly. This will go away when
+ * that is fixed.
+ */
+child_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int save_errno;
+ int status;
+
+ do {
+ pid = wait (&status);
+ save_errno = errno;
+
+ if (pid == -1)
+ {
+ if (save_errno == EINTR)
+ continue;
+ fprintf (stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+ 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 /* ATTACH_DETACH */
+
+
+
+/* This function simply calls ptrace with the given arguments.
+ It exists so that all calls to ptrace are isolated in this
+ machine-dependent file. */
+int
+call_ptrace (request, pid, addr, data)
+ int request, pid;
+ PTRACE_ARG3_TYPE addr;
+ int data;
+{
+ return ptrace (request, pid, addr, data);
+}
+
+int
+call_mptrace(request, pid, addr, data)
+ int request, pid;
+ PTRACE_ARG3_TYPE addr;
+ int data;
+{
+ return mptrace(request, pid, addr, data);
+}
+
+#if defined (DEBUG_PTRACE)
+/* For the rest of the file, use an extra level of indirection */
+/* This lets us breakpoint usefully on call_ptrace. */
+#define ptrace call_ptrace
+#define mptrace call_mptrace
+#endif
+
+void
+kill_inferior ()
+{
+ if (inferior_pid == 0)
+ return;
+
+ /* For MPDEBUGGER, don't use PT_KILL, since the child will stop
+ again with a PTS_EXIT. Just hit him with SIGKILL (so he stops)
+ and detach. */
+
+ kill (inferior_pid, SIGKILL);
+#ifdef ATTACH_DETACH
+ detach(SIGKILL);
+#else /* ATTACH_DETACH */
+ ptrace(PT_KILL, inferior_pid, 0, 0);
+ wait((int *)NULL);
+#endif /* ATTACH_DETACH */
+ target_mourn_inferior ();
+}
+
+/* Resume execution of the inferior process.
+ If STEP is nonzero, single-step it.
+ If SIGNAL is nonzero, give it that signal. */
+
+void
+child_resume (pid, step, signal)
+ int pid;
+ int step;
+ enum target_signal signal;
+{
+ errno = 0;
+
+ if (pid == -1)
+ pid = inferior_pid;
+
+ /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where
+ it was. (If GDB wanted it to start some other way, we have already
+ written a new PC value to the child.)
+
+ If this system does not support PT_SSTEP, a higher level function will
+ have called single_step() to transmute the step request into a
+ continue request (by setting breakpoints on all possible successor
+ instructions), so we don't have to worry about that here. */
+
+ if (step)
+ ptrace (PT_SSTEP, pid, (PTRACE_ARG3_TYPE) 1, signal);
+ else
+ ptrace (PT_CONTSIG, pid, (PTRACE_ARG3_TYPE) 1, signal);
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+
+#ifdef ATTACH_DETACH
+/* Start debugging the process whose number is PID. */
+int
+attach (pid)
+ int pid;
+{
+ sigset_t set;
+ int rv;
+
+ rv = mptrace(XPT_DEBUG, pid, 0, 0);
+ if (-1 == rv) {
+ error("mptrace(XPT_DEBUG): %s", safe_strerror(errno));
+ }
+ rv = mptrace(XPT_SIGNAL, pid, 0, SIGSTOP);
+ if (-1 == rv) {
+ error("mptrace(XPT_SIGNAL): %s", safe_strerror(errno));
+ }
+ attach_flag = 1;
+ return pid;
+}
+
+void
+detach (signo)
+ int signo;
+{
+ int rv;
+
+ rv = mptrace(XPT_UNDEBUG, inferior_pid, 1, signo);
+ if (-1 == rv) {
+ error("mptrace(XPT_UNDEBUG): %s", safe_strerror(errno));
+ }
+ attach_flag = 0;
+}
+
+#endif /* ATTACH_DETACH */
+
+/* Default the type of the ptrace transfer to int. */
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+
+/* 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
+ not write the data that I specified. I cannot understand where
+ it got the data that it actually did write. */
+
+/* Copy LEN bytes to or from inferior's memory starting at MEMADDR
+ to debugger memory starting at MYADDR. Copy to inferior if
+ WRITE is nonzero.
+
+ Returns the length copied, which is either the LEN argument or zero.
+ This xfer function does not do partial moves, since child_ops
+ doesn't allow memory operations to cross below us in the target stack
+ anyway. */
+
+int
+child_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target; /* ignored */
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & - sizeof (PTRACE_XFER_TYPE);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+ / sizeof (PTRACE_XFER_TYPE);
+ /* Allocate buffer of that many longwords. */
+ register PTRACE_XFER_TYPE *buffer
+ = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+
+ if (write)
+ {
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ if (addr != memaddr || len < (int) sizeof (PTRACE_XFER_TYPE)) {
+ /* Need part of initial word -- fetch it. */
+ buffer[0] = ptrace (PT_RTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ 0);
+ }
+
+ if (count > 1) /* FIXME, avoid if even boundary */
+ {
+ buffer[count - 1]
+ = ptrace (PT_RTEXT, inferior_pid,
+ ((PTRACE_ARG3_TYPE)
+ (addr + (count - 1) * sizeof (PTRACE_XFER_TYPE))),
+ 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ myaddr,
+ len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ ptrace (PT_WDATA, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ buffer[i]);
+ if (errno)
+ {
+ /* Using the appropriate one (I or D) is necessary for
+ Gould NP1, at least. */
+ errno = 0;
+ ptrace (PT_WTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr,
+ buffer[i]);
+ }
+ if (errno)
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
+ {
+ errno = 0;
+ buffer[i] = ptrace (PT_RTEXT, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0);
+ if (errno)
+ return 0;
+ QUIT;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr,
+ (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ len);
+ }
+ return len;
+}
+
+
+void
+_initialize_symm_nat ()
+{
+#ifdef ATTACH_DETACH
+/*
+ * the MPDEBUGGER is necessary for process tree debugging and attach
+ * to work, but it alters the behavior of debugged processes, so other
+ * things (at least child_wait()) will have to change to accomodate
+ * that.
+ *
+ * Note that attach is not implemented in dynix 3, and not in ptx
+ * until version 2.1 of the OS.
+ */
+ int rv;
+ sigset_t set;
+ struct sigaction sact;
+
+ rv = mptrace(XPT_MPDEBUGGER, 0, 0, 0);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): mptrace(XPT_MPDEBUGGER): %s",
+ safe_strerror(errno));
+ }
+
+ /*
+ * Under MPDEBUGGER, we get SIGCLHD when a traced process does
+ * anything of interest.
+ */
+
+ /*
+ * Block SIGCHLD. We leave it blocked all the time, and then
+ * call sigsuspend() in child_wait() to wait for the child
+ * to do something. None of these ought to fail, but check anyway.
+ */
+ sigemptyset(&set);
+ rv = sigaddset(&set, SIGCHLD);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): sigaddset(SIGCHLD): %s",
+ safe_strerror(errno));
+ }
+ rv = sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): sigprocmask(SIG_BLOCK): %s",
+ safe_strerror(errno));
+ }
+
+ sact.sa_handler = sigchld_handler;
+ sigemptyset(&sact.sa_mask);
+ sact.sa_flags = SA_NOCLDWAIT; /* keep the zombies away */
+ rv = sigaction(SIGCHLD, &sact, (struct sigaction *)NULL);
+ if (-1 == rv) {
+ fatal("_initialize_symm_nat(): sigaction(SIGCHLD): %s",
+ safe_strerror(errno));
+ }
+#endif
+}
diff --git a/contrib/gdb/gdb/symm-tdep.c b/contrib/gdb/gdb/symm-tdep.c
new file mode 100644
index 0000000..aaf73e9
--- /dev/null
+++ b/contrib/gdb/gdb/symm-tdep.c
@@ -0,0 +1,93 @@
+/* Sequent Symmetry target interface, for GDB.
+ Copyright (C) 1986, 1987, 1989, 1991, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* many 387-specific items of use taken from i386-dep.c */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+#include "symtab.h"
+
+#include <signal.h>
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/dir.h>
+#include <sys/ioctl.h>
+#include "gdb_stat.h"
+#include "gdbcore.h"
+#include <fcntl.h>
+
+void
+symmetry_extract_return_value(type, regbuf, valbuf)
+ struct type *type;
+ char *regbuf;
+ char *valbuf;
+{
+ union {
+ double d;
+ int l[2];
+ } xd;
+ struct minimal_symbol *msymbol;
+ float f;
+
+ if (TYPE_CODE_FLT == TYPE_CODE(type)) {
+ msymbol = lookup_minimal_symbol ("1167_flt", NULL, NULL);
+ if (msymbol != NULL) {
+ /* found "1167_flt" means 1167, %fp2-%fp3 */
+ /* float & double; 19= %fp2, 20= %fp3 */
+ /* no single precision on 1167 */
+ xd.l[1] = *((int *)&regbuf[REGISTER_BYTE(19)]);
+ xd.l[0] = *((int *)&regbuf[REGISTER_BYTE(20)]);
+ switch (TYPE_LENGTH(type)) {
+ case 4:
+ /* FIXME: broken for cross-debugging. */
+ f = (float) xd.d;
+ memcpy (valbuf, &f, TYPE_LENGTH(type));
+ break;
+ case 8:
+ /* FIXME: broken for cross-debugging. */
+ memcpy (valbuf, &xd.d, TYPE_LENGTH(type));
+ break;
+ default:
+ error("Unknown floating point size");
+ break;
+ }
+ } else {
+ /* 387 %st(0), gcc uses this */
+ i387_to_double(((int *)&regbuf[REGISTER_BYTE(3)]),
+ &xd.d);
+ switch (TYPE_LENGTH(type)) {
+ case 4: /* float */
+ f = (float) xd.d;
+ /* FIXME: broken for cross-debugging. */
+ memcpy (valbuf, &f, 4);
+ break;
+ case 8: /* double */
+ /* FIXME: broken for cross-debugging. */
+ memcpy (valbuf, &xd.d, 8);
+ break;
+ default:
+ error("Unknown floating point size");
+ break;
+ }
+ }
+ } else {
+ memcpy (valbuf, regbuf, TYPE_LENGTH (type));
+ }
+}
diff --git a/contrib/gdb/gdb/symmisc.c b/contrib/gdb/gdb/symmisc.c
new file mode 100644
index 0000000..db58cdd
--- /dev/null
+++ b/contrib/gdb/gdb/symmisc.c
@@ -0,0 +1,1053 @@
+/* Do various things to symbol tables (other than lookup), for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "breakpoint.h"
+#include "command.h"
+#include "obstack.h"
+#include "language.h"
+#include "bcache.h"
+
+#include "gdb_string.h"
+
+#ifndef DEV_TTY
+#define DEV_TTY "/dev/tty"
+#endif
+
+/* Unfortunately for debugging, stderr is usually a macro. This is painful
+ when calling functions that take FILE *'s from the debugger.
+ So we make a variable which has the same value and which is accessible when
+ debugging GDB with itself. Because stdin et al need not be constants,
+ we initialize them in the _initialize_symmisc function at the bottom
+ of the file. */
+FILE *std_in;
+FILE *std_out;
+FILE *std_err;
+
+/* Prototypes for local functions */
+
+static void
+dump_symtab PARAMS ((struct objfile *, struct symtab *, GDB_FILE *));
+
+static void
+dump_psymtab PARAMS ((struct objfile *, struct partial_symtab *, GDB_FILE *));
+
+static void
+dump_msymbols PARAMS ((struct objfile *, GDB_FILE *));
+
+static void
+dump_objfile PARAMS ((struct objfile *));
+
+static int
+block_depth PARAMS ((struct block *));
+
+static void
+print_partial_symbols PARAMS ((struct partial_symbol **, int, char *, GDB_FILE *));
+
+struct print_symbol_args {
+ struct symbol *symbol;
+ int depth;
+ GDB_FILE *outfile;
+};
+
+static int print_symbol PARAMS ((char *));
+
+static void
+free_symtab_block PARAMS ((struct objfile *, struct block *));
+
+
+/* Free a struct block <- B and all the symbols defined in that block. */
+
+static void
+free_symtab_block (objfile, b)
+ struct objfile *objfile;
+ struct block *b;
+{
+ register int i, n;
+ n = BLOCK_NSYMS (b);
+ for (i = 0; i < n; i++)
+ {
+ mfree (objfile -> md, SYMBOL_NAME (BLOCK_SYM (b, i)));
+ mfree (objfile -> md, (PTR) BLOCK_SYM (b, i));
+ }
+ mfree (objfile -> md, (PTR) b);
+}
+
+/* Free all the storage associated with the struct symtab <- S.
+ Note that some symtabs have contents malloc'ed structure by structure,
+ while some have contents that all live inside one big block of memory,
+ and some share the contents of another symbol table and so you should
+ not free the contents on their behalf (except sometimes the linetable,
+ which maybe per symtab even when the rest is not).
+ It is s->free_code that says which alternative to use. */
+
+void
+free_symtab (s)
+ register struct symtab *s;
+{
+ register int i, n;
+ register struct blockvector *bv;
+
+ switch (s->free_code)
+ {
+ case free_nothing:
+ /* All the contents are part of a big block of memory (an obstack),
+ and some other symtab is in charge of freeing that block.
+ Therefore, do nothing. */
+ break;
+
+ case free_contents:
+ /* Here all the contents were malloc'ed structure by structure
+ and must be freed that way. */
+ /* First free the blocks (and their symbols. */
+ bv = BLOCKVECTOR (s);
+ n = BLOCKVECTOR_NBLOCKS (bv);
+ for (i = 0; i < n; i++)
+ free_symtab_block (s -> objfile, BLOCKVECTOR_BLOCK (bv, i));
+ /* Free the blockvector itself. */
+ mfree (s -> objfile -> md, (PTR) bv);
+ /* Also free the linetable. */
+
+ case free_linetable:
+ /* Everything will be freed either by our `free_ptr'
+ or by some other symtab, except for our linetable.
+ Free that now. */
+ if (LINETABLE (s))
+ mfree (s -> objfile -> md, (PTR) LINETABLE (s));
+ break;
+ }
+
+ /* If there is a single block of memory to free, free it. */
+ if (s -> free_ptr != NULL)
+ mfree (s -> objfile -> md, s -> free_ptr);
+
+ /* Free source-related stuff */
+ if (s -> line_charpos != NULL)
+ mfree (s -> objfile -> md, (PTR) s -> line_charpos);
+ if (s -> fullname != NULL)
+ mfree (s -> objfile -> md, s -> fullname);
+ mfree (s -> objfile -> md, (PTR) s);
+}
+
+#if MAINTENANCE_CMDS
+
+void
+print_symbol_bcache_statistics ()
+{
+ struct objfile *objfile;
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ {
+ printf_filtered ("Byte cache statistics for '%s':\n", objfile -> name);
+ print_bcache_statistics (&objfile -> psymbol_cache, "partial symbol cache");
+ }
+ immediate_quit--;
+}
+
+void
+print_objfile_statistics ()
+{
+ struct objfile *objfile;
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ {
+ printf_filtered ("Statistics for '%s':\n", objfile -> name);
+ if (OBJSTAT (objfile, n_stabs) > 0)
+ printf_filtered (" Number of \"stab\" symbols read: %d\n",
+ OBJSTAT (objfile, n_stabs));
+ if (OBJSTAT (objfile, n_minsyms) > 0)
+ printf_filtered (" Number of \"minimal symbols read: %d\n",
+ OBJSTAT (objfile, n_minsyms));
+ if (OBJSTAT (objfile, n_psyms) > 0)
+ printf_filtered (" Number of \"partial symbols read: %d\n",
+ OBJSTAT (objfile, n_psyms));
+ if (OBJSTAT (objfile, n_syms) > 0)
+ printf_filtered (" Number of \"full symbols read: %d\n",
+ OBJSTAT (objfile, n_syms));
+ if (OBJSTAT (objfile, n_types) > 0)
+ printf_filtered (" Number of \"types defined: %d\n",
+ OBJSTAT (objfile, n_types));
+ if (OBJSTAT (objfile, sz_strtab) > 0)
+ printf_filtered (" Space used by a.out string tables: %d\n",
+ OBJSTAT (objfile, sz_strtab));
+ printf_filtered (" Total memory used for psymbol obstack: %d\n",
+ obstack_memory_used (&objfile -> psymbol_obstack));
+ printf_filtered (" Total memory used for psymbol cache: %d\n",
+ obstack_memory_used (&objfile -> psymbol_cache.cache));
+ printf_filtered (" Total memory used for symbol obstack: %d\n",
+ obstack_memory_used (&objfile -> symbol_obstack));
+ printf_filtered (" Total memory used for type obstack: %d\n",
+ obstack_memory_used (&objfile -> type_obstack));
+ }
+ immediate_quit--;
+}
+
+static void
+dump_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct symtab *symtab;
+ struct partial_symtab *psymtab;
+
+ printf_filtered ("\nObject file %s: ", objfile -> name);
+ 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)
+ {
+ printf_filtered ("Psymtabs:\n");
+ for (psymtab = objfile -> psymtabs;
+ psymtab != NULL;
+ psymtab = psymtab -> next)
+ {
+ printf_filtered ("%s at ",
+ psymtab -> filename);
+ gdb_print_address (psymtab, gdb_stdout);
+ printf_filtered (", ");
+ if (psymtab -> objfile != objfile)
+ {
+ printf_filtered ("NOT ON CHAIN! ");
+ }
+ wrap_here (" ");
+ }
+ printf_filtered ("\n\n");
+ }
+
+ if (objfile -> symtabs)
+ {
+ printf_filtered ("Symtabs:\n");
+ for (symtab = objfile -> symtabs;
+ symtab != NULL;
+ symtab = symtab->next)
+ {
+ printf_filtered ("%s at ", symtab -> filename);
+ gdb_print_address (symtab, gdb_stdout);
+ printf_filtered (", ");
+ if (symtab -> objfile != objfile)
+ {
+ printf_filtered ("NOT ON CHAIN! ");
+ }
+ wrap_here (" ");
+ }
+ printf_filtered ("\n\n");
+ }
+}
+
+/* Print minimal symbols from this objfile. */
+
+static void
+dump_msymbols (objfile, outfile)
+ struct objfile *objfile;
+ GDB_FILE *outfile;
+{
+ struct minimal_symbol *msymbol;
+ int index;
+ char ms_type;
+
+ fprintf_filtered (outfile, "\nObject file %s:\n\n", objfile -> name);
+ if (objfile -> minimal_symbol_count == 0)
+ {
+ fprintf_filtered (outfile, "No minimal symbols found.\n");
+ return;
+ }
+ for (index = 0, msymbol = objfile -> msymbols;
+ SYMBOL_NAME (msymbol) != NULL; msymbol++, index++)
+ {
+ switch (msymbol -> type)
+ {
+ case mst_unknown:
+ ms_type = 'u';
+ break;
+ case mst_text:
+ ms_type = 'T';
+ break;
+ case mst_solib_trampoline:
+ ms_type = 'S';
+ break;
+ case mst_data:
+ ms_type = 'D';
+ break;
+ case mst_bss:
+ ms_type = 'B';
+ break;
+ case mst_abs:
+ ms_type = 'A';
+ break;
+ case mst_file_text:
+ ms_type = 't';
+ break;
+ case mst_file_data:
+ ms_type = 'd';
+ break;
+ case mst_file_bss:
+ ms_type = 'b';
+ break;
+ default:
+ ms_type = '?';
+ break;
+ }
+ fprintf_filtered (outfile, "[%2d] %c %#10lx %s", index, ms_type,
+ SYMBOL_VALUE_ADDRESS (msymbol), SYMBOL_NAME (msymbol));
+ if (SYMBOL_DEMANGLED_NAME (msymbol) != NULL)
+ {
+ fprintf_filtered (outfile, " %s", SYMBOL_DEMANGLED_NAME (msymbol));
+ }
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ if (msymbol->filename)
+ fprintf_filtered (outfile, " %s", msymbol->filename);
+#endif
+ fputs_filtered ("\n", outfile);
+ }
+ if (objfile -> minimal_symbol_count != index)
+ {
+ warning ("internal error: minimal symbol count %d != %d",
+ objfile -> minimal_symbol_count, index);
+ }
+ fprintf_filtered (outfile, "\n");
+}
+
+static void
+dump_psymtab (objfile, psymtab, outfile)
+ struct objfile *objfile;
+ struct partial_symtab *psymtab;
+ GDB_FILE *outfile;
+{
+ int i;
+
+ fprintf_filtered (outfile, "\nPartial symtab for source file %s ",
+ psymtab -> filename);
+ 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 ");
+ gdb_print_address (psymtab->symtab, outfile);
+ fprintf_filtered (outfile, " by function at ");
+ gdb_print_address ((PTR)psymtab->read_symtab, outfile);
+ fprintf_filtered (outfile, ")\n");
+ }
+
+ 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 ");
+ 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 ", i);
+ gdb_print_address (psymtab -> dependencies[i], outfile);
+ fprintf_filtered (outfile, " %s\n",
+ psymtab -> dependencies[i] -> filename);
+ }
+ if (psymtab -> n_global_syms > 0)
+ {
+ print_partial_symbols (objfile -> global_psymbols.list
+ + psymtab -> globals_offset,
+ psymtab -> n_global_syms, "Global", outfile);
+ }
+ if (psymtab -> n_static_syms > 0)
+ {
+ print_partial_symbols (objfile -> static_psymbols.list
+ + psymtab -> statics_offset,
+ psymtab -> n_static_syms, "Static", outfile);
+ }
+ fprintf_filtered (outfile, "\n");
+}
+
+static void
+dump_symtab (objfile, symtab, outfile)
+ struct objfile *objfile;
+ struct symtab *symtab;
+ GDB_FILE *outfile;
+{
+ register int i, j;
+ int len, blen;
+ register struct linetable *l;
+ struct blockvector *bv;
+ register struct block *b;
+ int depth;
+
+ 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_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_filtered (outfile, "\nBlockvector:\n\n");
+ bv = BLOCKVECTOR (symtab);
+ len = BLOCKVECTOR_NBLOCKS (bv);
+ for (i = 0; i < len; i++)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ depth = block_depth (b) * 2;
+ print_spaces (depth, outfile);
+ 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_filtered (outfile, " (under ");
+ gdb_print_address (BLOCK_SUPERBLOCK (b), outfile);
+ fprintf_filtered (outfile, ")");
+ }
+ if (BLOCK_FUNCTION (b))
+ {
+ fprintf_filtered (outfile, " %s", SYMBOL_NAME (BLOCK_FUNCTION (b)));
+ if (SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)) != NULL)
+ {
+ fprintf_filtered (outfile, " %s",
+ SYMBOL_DEMANGLED_NAME (BLOCK_FUNCTION (b)));
+ }
+ }
+ if (BLOCK_GCC_COMPILED(b))
+ fprintf_filtered (outfile, " gcc%d compiled", BLOCK_GCC_COMPILED(b));
+ fprintf_filtered (outfile, "\n");
+ blen = BLOCK_NSYMS (b);
+ for (j = 0; j < blen; j++)
+ {
+ struct print_symbol_args s;
+ s.symbol = BLOCK_SYM (b, j);
+ s.depth = depth + 1;
+ s.outfile = outfile;
+ catch_errors (print_symbol, &s, "Error printing symbol:\n",
+ RETURN_MASK_ALL);
+ }
+ }
+ fprintf_filtered (outfile, "\n");
+}
+
+void
+maintenance_print_symbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ GDB_FILE *outfile;
+ struct cleanup *cleanups;
+ char *symname = NULL;
+ char *filename = DEV_TTY;
+ struct objfile *objfile;
+ struct symtab *s;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("\
+Arguments missing: an output file name and an optional symbol file name");
+ }
+ else if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, (char *) argv);
+
+ if (argv[0] != NULL)
+ {
+ filename = argv[0];
+ /* If a second arg is supplied, it is a source file name to match on */
+ if (argv[1] != NULL)
+ {
+ symname = argv[1];
+ }
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ outfile = gdb_fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup (fclose, (char *) outfile);
+
+ immediate_quit++;
+ ALL_SYMTABS (objfile, s)
+ if (symname == NULL || (STREQ (symname, s -> filename)))
+ dump_symtab (objfile, s, outfile);
+ immediate_quit--;
+ do_cleanups (cleanups);
+}
+
+/* Print symbol ARGS->SYMBOL on ARGS->OUTFILE. ARGS->DEPTH says how
+ far to indent. ARGS is really a struct print_symbol_args *, but is
+ declared as char * to get it past catch_errors. Returns 0 for error,
+ 1 for success. */
+
+static int
+print_symbol (args)
+ char *args;
+{
+ struct symbol *symbol = ((struct print_symbol_args *)args)->symbol;
+ int depth = ((struct print_symbol_args *)args)->depth;
+ GDB_FILE *outfile = ((struct print_symbol_args *)args)->outfile;
+
+ print_spaces (depth, outfile);
+ if (SYMBOL_NAMESPACE (symbol) == LABEL_NAMESPACE)
+ {
+ 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)
+ {
+ if (TYPE_TAG_NAME (SYMBOL_TYPE (symbol)))
+ {
+ LA_PRINT_TYPE (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+ }
+ else
+ {
+ fprintf_filtered (outfile, "%s %s = ",
+ (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_ENUM
+ ? "enum"
+ : (TYPE_CODE (SYMBOL_TYPE (symbol)) == TYPE_CODE_STRUCT
+ ? "struct" : "union")),
+ SYMBOL_NAME (symbol));
+ LA_PRINT_TYPE (SYMBOL_TYPE (symbol), "", outfile, 1, depth);
+ }
+ fprintf_filtered (outfile, ";\n");
+ }
+ else
+ {
+ if (SYMBOL_CLASS (symbol) == LOC_TYPEDEF)
+ fprintf_filtered (outfile, "typedef ");
+ if (SYMBOL_TYPE (symbol))
+ {
+ /* Print details of types, except for enums where it's clutter. */
+ LA_PRINT_TYPE (SYMBOL_TYPE (symbol), SYMBOL_SOURCE_NAME (symbol),
+ outfile,
+ TYPE_CODE (SYMBOL_TYPE (symbol)) != TYPE_CODE_ENUM,
+ depth);
+ fprintf_filtered (outfile, "; ");
+ }
+ else
+ fprintf_filtered (outfile, "%s ", SYMBOL_SOURCE_NAME (symbol));
+
+ switch (SYMBOL_CLASS (symbol))
+ {
+ case LOC_CONST:
+ fprintf_filtered (outfile, "const %ld (0x%lx),",
+ SYMBOL_VALUE (symbol),
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_CONST_BYTES:
+ {
+ unsigned i;
+ struct type *type = check_typedef (SYMBOL_TYPE (symbol));
+ fprintf_filtered (outfile, "const %u hex bytes:",
+ TYPE_LENGTH (type));
+ for (i = 0; i < TYPE_LENGTH (type); i++)
+ fprintf_filtered (outfile, " %02x",
+ (unsigned)SYMBOL_VALUE_BYTES (symbol) [i]);
+ fprintf_filtered (outfile, ",");
+ }
+ break;
+
+ case LOC_STATIC:
+ fprintf_filtered (outfile, "static at ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1,outfile);
+ fprintf_filtered (outfile, ",");
+ break;
+
+ case LOC_REGISTER:
+ fprintf_filtered (outfile, "register %ld,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_ARG:
+ fprintf_filtered (outfile, "arg at offset 0x%lx,",
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_LOCAL_ARG:
+ fprintf_filtered (outfile, "arg at offset 0x%lx from fp,",
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REF_ARG:
+ fprintf_filtered (outfile, "reference arg at 0x%lx,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REGPARM:
+ fprintf_filtered (outfile, "parameter register %ld,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_REGPARM_ADDR:
+ fprintf_filtered (outfile, "address parameter register %ld,", SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_LOCAL:
+ fprintf_filtered (outfile, "local at offset 0x%lx,",
+ SYMBOL_VALUE (symbol));
+ break;
+
+ case LOC_BASEREG:
+ fprintf_filtered (outfile, "local at 0x%lx from register %d",
+ SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol));
+ break;
+
+ case LOC_BASEREG_ARG:
+ fprintf_filtered (outfile, "arg at 0x%lx from register %d,",
+ SYMBOL_VALUE (symbol), SYMBOL_BASEREG (symbol));
+ break;
+
+ case LOC_TYPEDEF:
+ break;
+
+ case LOC_LABEL:
+ fprintf_filtered (outfile, "label at ");
+ print_address_numeric (SYMBOL_VALUE_ADDRESS (symbol), 1, outfile);
+ break;
+
+ case LOC_BLOCK:
+ 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_UNRESOLVED:
+ fprintf_filtered (outfile, "unresolved");
+ break;
+
+ case LOC_OPTIMIZED_OUT:
+ fprintf_filtered (outfile, "optimized out");
+ break;
+
+ default:
+ fprintf_filtered (outfile, "botched symbol class %x",
+ SYMBOL_CLASS (symbol));
+ break;
+ }
+ }
+ fprintf_filtered (outfile, "\n");
+ return 1;
+}
+
+void
+maintenance_print_psymbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ GDB_FILE *outfile;
+ struct cleanup *cleanups;
+ char *symname = NULL;
+ char *filename = DEV_TTY;
+ struct objfile *objfile;
+ struct partial_symtab *ps;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("print-psymbols takes an output file name and optional symbol file name");
+ }
+ else if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, (char *) argv);
+
+ if (argv[0] != NULL)
+ {
+ filename = argv[0];
+ /* If a second arg is supplied, it is a source file name to match on */
+ if (argv[1] != NULL)
+ {
+ symname = argv[1];
+ }
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ outfile = gdb_fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup (fclose, outfile);
+
+ immediate_quit++;
+ ALL_PSYMTABS (objfile, ps)
+ if (symname == NULL || (STREQ (symname, ps -> filename)))
+ dump_psymtab (objfile, ps, outfile);
+ immediate_quit--;
+ do_cleanups (cleanups);
+}
+
+static void
+print_partial_symbols (p, count, what, outfile)
+ struct partial_symbol **p;
+ int count;
+ char *what;
+ GDB_FILE *outfile;
+{
+ fprintf_filtered (outfile, " %s partial symbols:\n", what);
+ while (count-- > 0)
+ {
+ fprintf_filtered (outfile, " `%s'", SYMBOL_NAME(*p));
+ if (SYMBOL_DEMANGLED_NAME (*p) != NULL)
+ {
+ fprintf_filtered (outfile, " `%s'", SYMBOL_DEMANGLED_NAME (*p));
+ }
+ fputs_filtered (", ", outfile);
+ switch (SYMBOL_NAMESPACE (*p))
+ {
+ case UNDEF_NAMESPACE:
+ fputs_filtered ("undefined namespace, ", outfile);
+ break;
+ case VAR_NAMESPACE:
+ /* This is the usual thing -- don't print it */
+ break;
+ case STRUCT_NAMESPACE:
+ fputs_filtered ("struct namespace, ", outfile);
+ break;
+ case LABEL_NAMESPACE:
+ fputs_filtered ("label namespace, ", outfile);
+ break;
+ default:
+ fputs_filtered ("<invalid namespace>, ", outfile);
+ break;
+ }
+ switch (SYMBOL_CLASS (*p))
+ {
+ case LOC_UNDEF:
+ fputs_filtered ("undefined", outfile);
+ break;
+ case LOC_CONST:
+ fputs_filtered ("constant int", outfile);
+ break;
+ case LOC_STATIC:
+ fputs_filtered ("static", outfile);
+ break;
+ case LOC_REGISTER:
+ fputs_filtered ("register", outfile);
+ break;
+ case LOC_ARG:
+ fputs_filtered ("pass by value", outfile);
+ break;
+ case LOC_REF_ARG:
+ fputs_filtered ("pass by reference", outfile);
+ break;
+ case LOC_REGPARM:
+ fputs_filtered ("register parameter", outfile);
+ break;
+ case LOC_REGPARM_ADDR:
+ fputs_filtered ("register address parameter", outfile);
+ break;
+ case LOC_LOCAL:
+ fputs_filtered ("stack parameter", outfile);
+ break;
+ case LOC_TYPEDEF:
+ fputs_filtered ("type", outfile);
+ break;
+ case LOC_LABEL:
+ fputs_filtered ("label", outfile);
+ break;
+ case LOC_BLOCK:
+ fputs_filtered ("function", outfile);
+ break;
+ case LOC_CONST_BYTES:
+ fputs_filtered ("constant bytes", outfile);
+ break;
+ case LOC_LOCAL_ARG:
+ fputs_filtered ("shuffled arg", outfile);
+ break;
+ case LOC_UNRESOLVED:
+ fputs_filtered ("unresolved", outfile);
+ break;
+ case LOC_OPTIMIZED_OUT:
+ fputs_filtered ("optimized out", outfile);
+ break;
+ default:
+ fputs_filtered ("<invalid location>", 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++;
+ }
+}
+
+void
+maintenance_print_msymbols (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ char **argv;
+ GDB_FILE *outfile;
+ struct cleanup *cleanups;
+ char *filename = DEV_TTY;
+ char *symname = NULL;
+ struct objfile *objfile;
+
+ dont_repeat ();
+
+ if (args == NULL)
+ {
+ error ("print-msymbols takes an output file name and optional symbol file name");
+ }
+ else if ((argv = buildargv (args)) == NULL)
+ {
+ nomem (0);
+ }
+ cleanups = make_cleanup (freeargv, argv);
+
+ if (argv[0] != NULL)
+ {
+ filename = argv[0];
+ /* If a second arg is supplied, it is a source file name to match on */
+ if (argv[1] != NULL)
+ {
+ symname = argv[1];
+ }
+ }
+
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ outfile = gdb_fopen (filename, FOPEN_WT);
+ if (outfile == 0)
+ perror_with_name (filename);
+ make_cleanup (fclose, outfile);
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ if (symname == NULL || (STREQ (symname, objfile -> name)))
+ dump_msymbols (objfile, outfile);
+ immediate_quit--;
+ fprintf_filtered (outfile, "\n\n");
+ do_cleanups (cleanups);
+}
+
+void
+maintenance_print_objfiles (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ struct objfile *objfile;
+
+ dont_repeat ();
+
+ immediate_quit++;
+ ALL_OBJFILES (objfile)
+ dump_objfile (objfile);
+ 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. */
+
+static int
+block_depth (block)
+ struct block *block;
+{
+ register int i = 0;
+ while ((block = BLOCK_SUPERBLOCK (block)) != NULL)
+ {
+ i++;
+ }
+ return i;
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+
+/* Increase the space allocated for LISTP, which is probably
+ global_psymbols or static_psymbols. This space will eventually
+ be freed in free_objfile(). */
+
+void
+extend_psymbol_list (listp, objfile)
+ register struct psymbol_allocation_list *listp;
+ struct objfile *objfile;
+{
+ int new_size;
+ if (listp->size == 0)
+ {
+ new_size = 255;
+ listp->list = (struct partial_symbol **)
+ xmmalloc (objfile -> md, new_size * sizeof (struct partial_symbol *));
+ }
+ else
+ {
+ new_size = listp->size * 2;
+ listp->list = (struct partial_symbol **)
+ xmrealloc (objfile -> md, (char *) listp->list,
+ new_size * sizeof (struct partial_symbol *));
+ }
+ /* Next assumes we only went one over. Should be good if
+ program works correctly */
+ listp->next = listp->list + listp->size;
+ listp->size = new_size;
+}
+
+
+/* Do early runtime initializations. */
+void
+_initialize_symmisc ()
+{
+ std_in = stdin;
+ std_out = stdout;
+ std_err = stderr;
+}
diff --git a/contrib/gdb/gdb/symtab.c b/contrib/gdb/gdb/symtab.c
new file mode 100644
index 0000000..41605bc
--- /dev/null
+++ b/contrib/gdb/gdb/symtab.c
@@ -0,0 +1,3346 @@
+/* Symbol table lookup for the GNU debugger, GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "target.h"
+#include "value.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "gdbcmd.h"
+#include "call-cmds.h"
+#include "gnu-regex.h"
+#include "expression.h"
+#include "language.h"
+#include "demangle.h"
+
+#include "obstack.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include "gdb_string.h"
+#include "gdb_stat.h"
+#include <ctype.h>
+
+/* Prototypes for local functions */
+
+extern int
+find_methods PARAMS ((struct type *, char *, struct symbol **));
+
+static void
+completion_list_add_name PARAMS ((char *, char *, int, char *, char *));
+
+static void
+build_canonical_line_spec PARAMS ((struct symtab_and_line *, char *, char ***));
+
+static struct symtabs_and_lines
+decode_line_2 PARAMS ((struct symbol *[], int, int, char ***));
+
+static void
+rbreak_command PARAMS ((char *, int));
+
+static void
+types_info PARAMS ((char *, int));
+
+static void
+functions_info PARAMS ((char *, int));
+
+static void
+variables_info PARAMS ((char *, int));
+
+static void
+sources_info PARAMS ((char *, int));
+
+static void
+list_symbols PARAMS ((char *, int, int, int));
+
+static void
+output_source_filename PARAMS ((char *, int *));
+
+static char *
+operator_chars PARAMS ((char *, char **));
+
+static int find_line_common PARAMS ((struct linetable *, int, int *));
+
+static struct partial_symbol *
+lookup_partial_symbol PARAMS ((struct partial_symtab *, const char *,
+ int, namespace_enum));
+
+static struct symtab *
+lookup_symtab_1 PARAMS ((char *));
+
+/* */
+
+/* The single non-language-specific builtin type */
+struct type *builtin_type_error;
+
+/* Block in which the most recently searched-for symbol was found.
+ Might be better to make this a parameter to lookup_symbol and
+ value_of_this. */
+
+const struct block *block_found;
+
+char no_symtab_msg[] = "No symbol table is loaded. Use the \"file\" command.";
+
+/* While the C++ support is still in flux, issue a possibly helpful hint on
+ using the new command completion feature on single quoted demangled C++
+ symbols. Remove when loose ends are cleaned up. FIXME -fnf */
+
+void
+cplusplus_hint (name)
+ char *name;
+{
+ while (*name == '\'')
+ name++;
+ printf_filtered ("Hint: try '%s<TAB> or '%s<ESC-?>\n", name, name);
+ printf_filtered ("(Note leading single quote.)\n");
+}
+
+/* Check for a symtab of a specific name; first in symtabs, then in
+ psymtabs. *If* there is no '/' in the name, a match after a '/'
+ in the symtab filename will also work. */
+
+static struct symtab *
+lookup_symtab_1 (name)
+ char *name;
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register char *slash;
+ register struct objfile *objfile;
+
+ got_symtab:
+
+ /* First, search for an exact match */
+
+ ALL_SYMTABS (objfile, s)
+ if (STREQ (name, s->filename))
+ return s;
+
+ slash = strchr (name, '/');
+
+ /* Now, search for a matching tail (only if name doesn't have any dirs) */
+
+ if (!slash)
+ ALL_SYMTABS (objfile, s)
+ {
+ char *p = s -> filename;
+ char *tail = strrchr (p, '/');
+
+ if (tail)
+ p = tail + 1;
+
+ if (STREQ (p, name))
+ return s;
+ }
+
+ /* Same search rules as above apply here, but now we look thru the
+ psymtabs. */
+
+ ps = lookup_partial_symtab (name);
+ if (!ps)
+ return (NULL);
+
+ if (ps -> readin)
+ error ("Internal: readin %s pst for `%s' found when no symtab found.",
+ ps -> filename, name);
+
+ s = PSYMTAB_TO_SYMTAB (ps);
+
+ if (s)
+ return s;
+
+ /* At this point, we have located the psymtab for this file, but
+ the conversion to a symtab has failed. This usually happens
+ when we are looking up an include file. In this case,
+ PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has
+ been created. So, we need to run through the symtabs again in
+ order to find the file.
+ XXX - This is a crock, and should be fixed inside of the the
+ symbol parsing routines. */
+ goto got_symtab;
+}
+
+/* Lookup the symbol table of a source file named NAME. Try a couple
+ of variations if the first lookup doesn't work. */
+
+struct symtab *
+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
+ the GDB manual. */
+
+ copy = (char *) alloca (strlen (name) + 3);
+ strcpy (copy, name);
+ strcat (copy, ".c");
+ s = lookup_symtab_1 (copy);
+ if (s) return s;
+#endif /* 0 */
+
+ /* We didn't find anything; die. */
+ return 0;
+}
+
+/* Lookup the partial symbol table of a source file named NAME.
+ *If* there is no '/' in the name, a match after a '/'
+ in the psymtab filename will also work. */
+
+struct partial_symtab *
+lookup_partial_symtab (name)
+char *name;
+{
+ register struct partial_symtab *pst;
+ register struct objfile *objfile;
+
+ ALL_PSYMTABS (objfile, pst)
+ {
+ if (STREQ (name, pst -> filename))
+ {
+ return (pst);
+ }
+ }
+
+ /* Now, search for a matching tail (only if name doesn't have any dirs) */
+
+ if (!strchr (name, '/'))
+ ALL_PSYMTABS (objfile, pst)
+ {
+ char *p = pst -> filename;
+ char *tail = strrchr (p, '/');
+
+ if (tail)
+ p = tail + 1;
+
+ if (STREQ (p, name))
+ return (pst);
+ }
+
+ return (NULL);
+}
+
+/* Demangle a GDB method stub type.
+ Note that this function is g++ specific. */
+
+char *
+gdb_mangle_name (type, i, j)
+ struct type *type;
+ int i, j;
+{
+ int mangled_name_len;
+ char *mangled_name;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ struct fn_field *method = &f[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. */
+ char *const_prefix = method->is_const ? "C" : "";
+ char *volatile_prefix = method->is_volatile ? "V" : "";
+ char buf[20];
+ int len = (newname == NULL ? 0 : strlen (newname));
+
+ 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);
+
+ if (is_destructor || is_full_physname_constructor)
+ {
+ mangled_name = (char*) xmalloc(strlen(physname)+1);
+ strcpy(mangled_name, physname);
+ return mangled_name;
+ }
+
+ if (len == 0)
+ {
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ if (strcmp(buf, "__") == 0)
+ buf[0] = '\0';
+ }
+ else if (newname != NULL && strchr (newname, '<') != NULL)
+ {
+ /* Template methods are fully mangled. */
+ sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
+ newname = NULL;
+ len = 0;
+ }
+ else
+ {
+ sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+ }
+ mangled_name_len = ((is_constructor ? 0 : strlen (field_name))
+ + strlen (buf) + len
+ + strlen (physname)
+ + 1);
+
+ /* Only needed for GNU-mangled names. ANSI-mangled names
+ work with the normal mechanisms. */
+ if (OPNAME_PREFIX_P (field_name))
+ {
+ const char *opname = cplus_mangle_opname (field_name + 3, 0);
+ if (opname == NULL)
+ error ("No mangling for \"%s\"", field_name);
+ mangled_name_len += strlen (opname);
+ mangled_name = (char *)xmalloc (mangled_name_len);
+
+ strncpy (mangled_name, field_name, 3);
+ mangled_name[3] = '\0';
+ strcat (mangled_name, opname);
+ }
+ else
+ {
+ mangled_name = (char *)xmalloc (mangled_name_len);
+ if (is_constructor)
+ mangled_name[0] = '\0';
+ else
+ strcpy (mangled_name, field_name);
+ }
+ strcat (mangled_name, buf);
+ /* If the class doesn't have a name, i.e. newname NULL, then we just
+ mangle it using 0 for the length of the class. Thus it gets mangled
+ as something starting with `::' rather than `classname::'. */
+ if (newname != NULL)
+ strcat (mangled_name, newname);
+
+ strcat (mangled_name, physname);
+ return (mangled_name);
+}
+
+
+/* Find which partial symtab on contains PC. Return 0 if none. */
+
+struct partial_symtab *
+find_pc_psymtab (pc)
+ register CORE_ADDR pc;
+{
+ register struct partial_symtab *pst;
+ register struct objfile *objfile;
+
+ ALL_PSYMTABS (objfile, pst)
+ {
+ if (pc >= pst->textlow && pc < pst->texthigh)
+ {
+ struct minimal_symbol *msymbol;
+ struct partial_symtab *tpst;
+
+ /* An objfile that has its functions reordered might have
+ many partial symbol tables containing the PC, but
+ we want the partial symbol table that contains the
+ function containing the PC. */
+ if (!(objfile->flags & OBJF_REORDERED))
+ return (pst);
+
+ msymbol = lookup_minimal_symbol_by_pc (pc);
+ if (msymbol == NULL)
+ return (pst);
+
+ for (tpst = pst; tpst != NULL; tpst = tpst->next)
+ {
+ if (pc >= tpst->textlow && pc < tpst->texthigh)
+ {
+ struct partial_symbol *p;
+
+ p = find_pc_psymbol (tpst, pc);
+ if (p != NULL
+ && SYMBOL_VALUE_ADDRESS(p)
+ == SYMBOL_VALUE_ADDRESS (msymbol))
+ return (tpst);
+ }
+ }
+ return (pst);
+ }
+ }
+ return (NULL);
+}
+
+/* Find which partial symbol within a psymtab contains PC. Return 0
+ if none. Check all psymtabs if PSYMTAB is 0. */
+struct partial_symbol *
+find_pc_psymbol (psymtab, pc)
+ struct partial_symtab *psymtab;
+ CORE_ADDR pc;
+{
+ struct partial_symbol *best = NULL, *p, **pp;
+ CORE_ADDR best_pc;
+
+ if (!psymtab)
+ psymtab = find_pc_psymtab (pc);
+ if (!psymtab)
+ return 0;
+
+ 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 (pp = psymtab->objfile->global_psymbols.list + psymtab->globals_offset;
+ (pp - (psymtab->objfile->global_psymbols.list + psymtab->globals_offset)
+ < psymtab->n_global_syms);
+ pp++)
+ {
+ p = *pp;
+ 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 (pp = psymtab->objfile->static_psymbols.list + psymtab->statics_offset;
+ (pp - (psymtab->objfile->static_psymbols.list + psymtab->statics_offset)
+ < psymtab->n_static_syms);
+ pp++)
+ {
+ p = *pp;
+ 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;
+ }
+ }
+ if (best_pc == psymtab->textlow - 1)
+ return 0;
+ return best;
+}
+
+
+/* Find the definition for a specified symbol name NAME
+ in namespace NAMESPACE, visible from lexical block BLOCK.
+ Returns the struct symbol pointer, or zero if no symbol is found.
+ If SYMTAB is non-NULL, store the symbol table in which the
+ symbol was found there, or NULL if not found.
+ C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
+ NAME is a field of the current implied argument `this'. If so set
+ *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero.
+ 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;
+ register const struct block *block;
+ const namespace_enum namespace;
+ int *is_a_field_of_this;
+ struct symtab **symtab;
+{
+ register struct symbol *sym;
+ register struct symtab *s = NULL;
+ register struct partial_symtab *ps;
+ struct blockvector *bv;
+ register struct objfile *objfile;
+ register struct block *b;
+ register struct minimal_symbol *msymbol;
+
+ /* Search specified block and its superiors. */
+
+ while (block != 0)
+ {
+ sym = lookup_block_symbol (block, name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ {
+ /* Search the list of symtabs for one which contains the
+ address of the start of this block. */
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ if (BLOCK_START (b) <= BLOCK_START (block)
+ && BLOCK_END (b) > BLOCK_START (block))
+ goto found;
+ }
+found:
+ *symtab = s;
+ }
+
+ return (sym);
+ }
+ block = BLOCK_SUPERBLOCK (block);
+ }
+
+ /* FIXME: this code is never executed--block is always NULL at this
+ point. What is it trying to do, anyway? We already should have
+ checked the STATIC_BLOCK above (it is the superblock of top-level
+ blocks). Why is VAR_NAMESPACE special-cased? */
+ /* Don't need to mess with the psymtabs; if we have a block,
+ that file is read in. If we don't, then we deal later with
+ all the psymtab stuff that needs checking. */
+ if (namespace == VAR_NAMESPACE && block != NULL)
+ {
+ struct block *b;
+ /* Find the right symtab. */
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ if (BLOCK_START (b) <= BLOCK_START (block)
+ && BLOCK_END (b) > BLOCK_START (block))
+ {
+ sym = lookup_block_symbol (b, name, VAR_NAMESPACE);
+ if (sym)
+ {
+ block_found = b;
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+ }
+ }
+
+
+ /* C++: If requested to do so by the caller,
+ check to see if NAME is a field of `this'. */
+ if (is_a_field_of_this)
+ {
+ struct value *v = value_of_this (0);
+
+ *is_a_field_of_this = 0;
+ if (v && check_field (v, name))
+ {
+ *is_a_field_of_this = 1;
+ if (symtab != NULL)
+ *symtab = NULL;
+ return 0;
+ }
+ }
+
+ /* Now search all global blocks. Do the symtab's first, then
+ check the psymtab's */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+
+ /* Check for the possibility of the symbol being a function or
+ a mangled variable that is stored in one of the minimal symbol tables.
+ Eventually, all global symbols might be resolved in this way. */
+
+ if (namespace == VAR_NAMESPACE)
+ {
+ msymbol = lookup_minimal_symbol (name, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol));
+ if (s != NULL)
+ {
+ /* This is a function which has a symtab for its address. */
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
+ namespace);
+ /* We kept static functions in minimal symbol table as well as
+ in static scope. We want to find them in the symbol table. */
+ if (!sym) {
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, SYMBOL_NAME (msymbol),
+ namespace);
+ }
+
+ /* sym == 0 if symbol was found in the minimal symbol table
+ but not in the symtab.
+ Return 0 to use the msymbol definition of "foo_".
+
+ This happens for Fortran "foo_" symbols,
+ which are "foo" in the symtab.
+
+ This can also happen if "asm" is used to make a
+ regular symbol but not a debugging symbol, e.g.
+ asm(".globl _main");
+ asm("_main:");
+ */
+
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ else if (MSYMBOL_TYPE (msymbol) != mst_text
+ && MSYMBOL_TYPE (msymbol) != mst_file_text
+ && !STREQ (name, SYMBOL_NAME (msymbol)))
+ {
+ /* This is a mangled variable, look it up by its
+ mangled name. */
+ return lookup_symbol (SYMBOL_NAME (msymbol), block,
+ namespace, is_a_field_of_this, symtab);
+ }
+ /* There are no debug symbols for this file, or we are looking
+ for an unmangled variable.
+ Try to find a matching static symbol below. */
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, 1, namespace))
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ error ("Internal: global symbol `%s' found in %s psymtab but not in symtab", name, ps->filename);
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+
+ /* Now search all per-file blocks.
+ Not strictly correct, but more useful than an error.
+ Do the symtabs first, then check the psymtabs */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (sym)
+ {
+ block_found = block;
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin && lookup_partial_symbol (ps, name, 0, namespace))
+ {
+ s = PSYMTAB_TO_SYMTAB(ps);
+ bv = BLOCKVECTOR (s);
+ block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ sym = lookup_block_symbol (block, name, namespace);
+ if (!sym)
+ error ("Internal: static symbol `%s' found in %s psymtab but not in symtab", name, ps->filename);
+ if (symtab != NULL)
+ *symtab = s;
+ return sym;
+ }
+ }
+
+ if (symtab != NULL)
+ *symtab = NULL;
+ return 0;
+}
+
+/* Look, in partial_symtab PST, for symbol NAME. Check the global
+ symbols if GLOBAL, the static symbols if not */
+
+static struct partial_symbol *
+lookup_partial_symbol (pst, name, global, namespace)
+ struct partial_symtab *pst;
+ const char *name;
+ int global;
+ namespace_enum namespace;
+{
+ struct partial_symbol **start, **psym;
+ struct partial_symbol **top, **bottom, **center;
+ int length = (global ? pst->n_global_syms : pst->n_static_syms);
+ int do_linear_search = 1;
+
+ if (length == 0)
+ {
+ return (NULL);
+ }
+
+ start = (global ?
+ pst->objfile->global_psymbols.list + pst->globals_offset :
+ pst->objfile->static_psymbols.list + pst->statics_offset );
+
+ if (global) /* This means we can use a binary search. */
+ {
+ do_linear_search = 0;
+
+ /* Binary search. This search is guaranteed to end with center
+ pointing at the earliest partial symbol with the correct
+ name. At that point *all* partial symbols with that name
+ will be checked against the correct namespace. */
+
+ bottom = start;
+ top = start + length - 1;
+ while (top > bottom)
+ {
+ center = bottom + (top - bottom) / 2;
+ if (!(center < top))
+ abort ();
+ if (!do_linear_search && SYMBOL_LANGUAGE (*center) == language_cplus)
+ {
+ do_linear_search = 1;
+ }
+ if (STRCMP (SYMBOL_NAME (*center), name) >= 0)
+ {
+ top = center;
+ }
+ else
+ {
+ bottom = center + 1;
+ }
+ }
+ if (!(top == bottom))
+ abort ();
+ while (STREQ (SYMBOL_NAME (*top), name))
+ {
+ if (SYMBOL_NAMESPACE (*top) == namespace)
+ {
+ return (*top);
+ }
+ top ++;
+ }
+ }
+
+ /* Can't use a binary search or else we found during the binary search that
+ we should also do a linear search. */
+
+ if (do_linear_search)
+ {
+ for (psym = start; psym < start + length; psym++)
+ {
+ if (namespace == SYMBOL_NAMESPACE (*psym))
+ {
+ if (SYMBOL_MATCHES_NAME (*psym, name))
+ {
+ return (*psym);
+ }
+ }
+ }
+ }
+
+ return (NULL);
+}
+
+/* Find the psymtab containing main(). */
+/* FIXME: What about languages without main() or specially linked
+ executables that have no main() ? */
+
+struct partial_symtab *
+find_main_psymtab ()
+{
+ register struct partial_symtab *pst;
+ register struct objfile *objfile;
+
+ ALL_PSYMTABS (objfile, pst)
+ {
+ if (lookup_partial_symbol (pst, "main", 1, VAR_NAMESPACE))
+ {
+ return (pst);
+ }
+ }
+ return (NULL);
+}
+
+/* Search BLOCK for symbol NAME in NAMESPACE.
+
+ Note that if NAME is the demangled form of a C++ symbol, we will fail
+ to find a match during the binary search of the non-encoded names, but
+ for now we don't worry about the slight inefficiency of looking for
+ a match we'll never find, since it will go pretty quick. Once the
+ binary search terminates, we drop through and do a straight linear
+ search on the symbols. Each symbol which is marked as being a C++
+ symbol (language_cplus set) has both the encoded and non-encoded names
+ tested for a match. */
+
+struct symbol *
+lookup_block_symbol (block, name, namespace)
+ register const struct block *block;
+ const char *name;
+ const namespace_enum namespace;
+{
+ register int bot, top, inc;
+ register struct symbol *sym;
+ register struct symbol *sym_found = NULL;
+ register int do_linear_search = 1;
+
+ /* If the blocks's symbols were sorted, start with a binary search. */
+
+ if (BLOCK_SHOULD_SORT (block))
+ {
+ /* Reset the linear search flag so if the binary search fails, we
+ won't do the linear search once unless we find some reason to
+ do so, such as finding a C++ symbol during the binary search.
+ Note that for C++ modules, ALL the symbols in a block should
+ end up marked as C++ symbols. */
+
+ do_linear_search = 0;
+ top = BLOCK_NSYMS (block);
+ bot = 0;
+
+ /* Advance BOT to not far before the first symbol whose name is NAME. */
+
+ while (1)
+ {
+ inc = (top - bot + 1);
+ /* No need to keep binary searching for the last few bits worth. */
+ if (inc < 4)
+ {
+ break;
+ }
+ inc = (inc >> 1) + bot;
+ sym = BLOCK_SYM (block, inc);
+ if (!do_linear_search && SYMBOL_LANGUAGE (sym) == language_cplus)
+ {
+ do_linear_search = 1;
+ }
+ if (SYMBOL_NAME (sym)[0] < name[0])
+ {
+ bot = inc;
+ }
+ else if (SYMBOL_NAME (sym)[0] > name[0])
+ {
+ top = inc;
+ }
+ else if (STRCMP (SYMBOL_NAME (sym), name) < 0)
+ {
+ bot = inc;
+ }
+ else
+ {
+ top = inc;
+ }
+ }
+
+ /* Now scan forward until we run out of symbols, find one whose
+ name is greater than NAME, or find one we want. If there is
+ more than one symbol with the right name and namespace, we
+ return the first one; I believe it is now impossible for us
+ to encounter two symbols with the same name and namespace
+ here, because blocks containing argument symbols are no
+ longer sorted. */
+
+ top = BLOCK_NSYMS (block);
+ while (bot < top)
+ {
+ sym = BLOCK_SYM (block, bot);
+ inc = SYMBOL_NAME (sym)[0] - name[0];
+ if (inc == 0)
+ {
+ inc = STRCMP (SYMBOL_NAME (sym), name);
+ }
+ if (inc == 0 && SYMBOL_NAMESPACE (sym) == namespace)
+ {
+ return (sym);
+ }
+ if (inc > 0)
+ {
+ break;
+ }
+ bot++;
+ }
+ }
+
+ /* Here if block isn't sorted, or we fail to find a match during the
+ binary search above. If during the binary search above, we find a
+ symbol which is a C++ symbol, then we have re-enabled the linear
+ search flag which was reset when starting the binary search.
+
+ This loop is equivalent to the loop above, but hacked greatly for speed.
+
+ Note that parameter symbols do not always show up last in the
+ list; this loop makes sure to take anything else other than
+ parameter symbols first; it only uses parameter symbols as a
+ last resort. Note that this only takes up extra computation
+ time on a match. */
+
+ if (do_linear_search)
+ {
+ top = BLOCK_NSYMS (block);
+ bot = 0;
+ while (bot < top)
+ {
+ sym = BLOCK_SYM (block, bot);
+ if (SYMBOL_NAMESPACE (sym) == namespace &&
+ SYMBOL_MATCHES_NAME (sym, name))
+ {
+ sym_found = sym;
+ if (SYMBOL_CLASS (sym) != LOC_ARG &&
+ SYMBOL_CLASS (sym) != LOC_LOCAL_ARG &&
+ SYMBOL_CLASS (sym) != LOC_REF_ARG &&
+ SYMBOL_CLASS (sym) != LOC_REGPARM &&
+ SYMBOL_CLASS (sym) != LOC_REGPARM_ADDR &&
+ SYMBOL_CLASS (sym) != LOC_BASEREG_ARG)
+ {
+ break;
+ }
+ }
+ bot++;
+ }
+ }
+ return (sym_found); /* Will be NULL if not found. */
+}
+
+
+/* Return the symbol for the function which contains a specified
+ lexical block, described by a struct block BL. */
+
+struct symbol *
+block_function (bl)
+ struct block *bl;
+{
+ while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0)
+ bl = BLOCK_SUPERBLOCK (bl);
+
+ return BLOCK_FUNCTION (bl);
+}
+
+/* Find the symtab associated with PC. Look through the psymtabs and read in
+ another symtab if necessary. */
+
+struct symtab *
+find_pc_symtab (pc)
+ register CORE_ADDR pc;
+{
+ register struct block *b;
+ struct blockvector *bv;
+ register struct symtab *s = NULL;
+ register struct symtab *best_s = NULL;
+ register struct partial_symtab *ps;
+ register struct objfile *objfile;
+ int distance = 0;
+
+ /* Search all symtabs for the one whose file contains our address, and which
+ is the smallest of all the ones containing the address. This is designed
+ to deal with a case like symtab a is at 0x1000-0x2000 and 0x3000-0x4000
+ and symtab b is at 0x2000-0x3000. So the GLOBAL_BLOCK for a is from
+ 0x1000-0x4000, but for address 0x2345 we want to return symtab b.
+
+ This happens for native ecoff format, where code from included files
+ gets its own symtab. The symtab for the included file should have
+ been read in already via the dependency mechanism.
+ It might be swifter to create several symtabs with the same name
+ like xcoff does (I'm not sure).
+
+ It also happens for objfiles that have their functions reordered.
+ For these, the symtab we are looking for is not necessarily read in. */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ bv = BLOCKVECTOR (s);
+ b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+ if (BLOCK_START (b) <= pc
+ && BLOCK_END (b) > pc
+ && (distance == 0
+ || BLOCK_END (b) - BLOCK_START (b) < distance))
+ {
+ /* For an objfile that has its functions reordered,
+ find_pc_psymtab will find the proper partial symbol table
+ and we simply return its corresponding symtab. */
+ if ((objfile->flags & OBJF_REORDERED) && objfile->psymtabs)
+ {
+ ps = find_pc_psymtab (pc);
+ if (ps)
+ s = PSYMTAB_TO_SYMTAB (ps);
+ else
+ s = NULL;
+ return (s);
+ }
+ distance = BLOCK_END (b) - BLOCK_START (b);
+ best_s = s;
+ }
+ }
+
+ if (best_s != NULL)
+ return(best_s);
+
+ s = NULL;
+ ps = find_pc_psymtab (pc);
+ if (ps)
+ {
+ if (ps->readin)
+ /* 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);
+ s = PSYMTAB_TO_SYMTAB (ps);
+ }
+ 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,
+ and a pc range for the entire source line.
+ The value's .pc field is NOT the specified pc.
+ NOTCURRENT nonzero means, if specified pc is on a line boundary,
+ use the line that ends there. Otherwise, in that case, the line
+ that begins there is used. */
+
+/* The big complication here is that a line may start in one file, and end just
+ before the start of another file. This usually occurs when you #include
+ code in the middle of a subroutine. To properly find the end of a line's PC
+ range, we must search all symtabs associated with this compilation unit, and
+ find the one whose first PC is closer than that of the next line in this
+ symtab. */
+
+/* If it's worth the effort, we could be using a binary search. */
+
+struct symtab_and_line
+find_pc_line (pc, notcurrent)
+ CORE_ADDR pc;
+ int notcurrent;
+{
+ struct symtab *s;
+ register struct linetable *l;
+ register int len;
+ register int i;
+ register struct linetable_entry *item;
+ struct symtab_and_line val;
+ struct blockvector *bv;
+
+ /* Info on best line seen so far, and where it starts, and its file. */
+
+ struct linetable_entry *best = NULL;
+ CORE_ADDR best_end = 0;
+ struct symtab *best_symtab = 0;
+
+ /* Store here the first line number
+ of a file which contains the line at the smallest pc after PC.
+ If we don't find a line whose range contains PC,
+ we will use a line one less than this,
+ with a range from the start of that file to the first line's pc. */
+ struct linetable_entry *alt = NULL;
+ struct symtab *alt_symtab = 0;
+
+ /* Info on best line seen in this file. */
+
+ struct linetable_entry *prev;
+
+ /* If this pc is not from the current frame,
+ it is the address of the end of a call instruction.
+ Quite likely that is the start of the following statement.
+ But what we want is the statement containing the instruction.
+ Fudge the pc to make sure we get that. */
+
+ if (notcurrent) pc -= 1;
+
+ s = find_pc_symtab (pc);
+ if (!s)
+ {
+ val.symtab = 0;
+ val.line = 0;
+ val.pc = pc;
+ val.end = 0;
+ return val;
+ }
+
+ bv = BLOCKVECTOR (s);
+
+ /* Look at all the symtabs that share this blockvector.
+ They all have the same apriori range, that we found was right;
+ but they have different line tables. */
+
+ for (; s && BLOCKVECTOR (s) == bv; s = s->next)
+ {
+ /* Find the best line in this symtab. */
+ l = LINETABLE (s);
+ if (!l)
+ continue;
+ len = l->nitems;
+ if (len <= 0)
+ {
+ /* I think len can be zero if the symtab lacks line numbers
+ (e.g. gcc -g1). (Either that or the LINETABLE is NULL;
+ I'm not sure which, and maybe it depends on the symbol
+ reader). */
+ continue;
+ }
+
+ prev = NULL;
+ item = l->item; /* Get first line info */
+
+ /* Is this file's first line closer than the first lines of other files?
+ If so, record this file, and its first line, as best alternate. */
+ if (item->pc > pc && (!alt || item->pc < alt->pc))
+ {
+ alt = item;
+ alt_symtab = s;
+ }
+
+ for (i = 0; i < len; i++, item++)
+ {
+ /* Return the last line that did not start after PC. */
+ if (item->pc > pc)
+ break;
+
+ prev = item;
+ }
+
+ /* At this point, prev points at the line whose start addr is <= pc, and
+ item points at the next line. If we ran off the end of the linetable
+ (pc >= start of the last line), then prev == item. If pc < start of
+ the first line, prev will not be set. */
+
+ /* Is this file's best line closer than the best in the other files?
+ If so, record this file, and its best line, as best so far. */
+
+ if (prev && (!best || prev->pc > best->pc))
+ {
+ best = prev;
+ best_symtab = s;
+ /* If another line is in the linetable, and its PC is closer
+ than the best_end we currently have, take it as best_end. */
+ if (i < len && (best_end == 0 || best_end > item->pc))
+ best_end = item->pc;
+ }
+ }
+
+ if (!best_symtab)
+ {
+ if (!alt_symtab)
+ { /* If we didn't find any line # info, just
+ return zeros. */
+ val.symtab = 0;
+ val.line = 0;
+ val.pc = pc;
+ val.end = 0;
+ }
+ else
+ {
+ val.symtab = alt_symtab;
+ val.line = alt->line - 1;
+
+ /* Don't return line 0, that means that we didn't find the line. */
+ if (val.line == 0) ++val.line;
+
+ val.pc = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
+ val.end = alt->pc;
+ }
+ }
+ else
+ {
+ val.symtab = best_symtab;
+ val.line = best->line;
+ val.pc = best->pc;
+ if (best_end && (!alt || best_end < alt->pc))
+ val.end = best_end;
+ else if (alt)
+ val.end = alt->pc;
+ else
+ val.end = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
+ }
+ return val;
+}
+
+static int find_line_symtab PARAMS ((struct symtab *, int, struct linetable **,
+ int *, int *));
+
+/* Find line number LINE in any symtab whose name is the same as
+ SYMTAB.
+
+ If found, return 1, set *LINETABLE to the linetable in which it was
+ found, set *INDEX to the index in the linetable of the best entry
+ found, and set *EXACT_MATCH nonzero if the value returned is an
+ exact match.
+
+ If not found, return 0. */
+
+static int
+find_line_symtab (symtab, line, linetable, index, exact_match)
+ struct symtab *symtab;
+ int line;
+ struct linetable **linetable;
+ int *index;
+ int *exact_match;
+{
+ int exact;
+
+ /* BEST_INDEX and BEST_LINETABLE identify the smallest linenumber > LINE
+ so far seen. */
+
+ int best_index;
+ struct linetable *best_linetable;
+
+ /* First try looking it up in the given symtab. */
+ best_linetable = LINETABLE (symtab);
+ best_index = find_line_common (best_linetable, line, &exact);
+ if (best_index < 0 || !exact)
+ {
+ /* Didn't find an exact match. So we better keep looking for
+ another symtab with the same name. In the case of xcoff,
+ multiple csects for one source file (produced by IBM's FORTRAN
+ compiler) produce multiple symtabs (this is unavoidable
+ assuming csects can be at arbitrary places in memory and that
+ the GLOBAL_BLOCK of a symtab has a begin and end address). */
+
+ /* BEST is the smallest linenumber > LINE so far seen,
+ or 0 if none has been seen so far.
+ BEST_INDEX and BEST_LINETABLE identify the item for it. */
+ int best;
+
+ struct objfile *objfile;
+ struct symtab *s;
+
+ if (best_index >= 0)
+ best = best_linetable->item[best_index].line;
+ else
+ best = 0;
+
+ ALL_SYMTABS (objfile, s)
+ {
+ struct linetable *l;
+ int ind;
+
+ if (!STREQ (symtab->filename, s->filename))
+ continue;
+ l = LINETABLE (s);
+ ind = find_line_common (l, line, &exact);
+ if (ind >= 0)
+ {
+ if (exact)
+ {
+ best_index = ind;
+ best_linetable = l;
+ goto done;
+ }
+ if (best == 0 || l->item[ind].line < best)
+ {
+ best = l->item[ind].line;
+ best_index = ind;
+ best_linetable = l;
+ }
+ }
+ }
+ }
+ done:
+ if (best_index < 0)
+ return 0;
+
+ if (index)
+ *index = best_index;
+ if (linetable)
+ *linetable = best_linetable;
+ if (exact_match)
+ *exact_match = exact;
+ return 1;
+}
+
+/* Find the PC value for a given source file and line number.
+ Returns zero for invalid line number.
+ The source file is specified with a struct symtab. */
+
+CORE_ADDR
+find_line_pc (symtab, line)
+ struct symtab *symtab;
+ int line;
+{
+ struct linetable *l;
+ int ind;
+
+ if (symtab == 0)
+ return 0;
+ if (find_line_symtab (symtab, line, &l, &ind, NULL))
+ return l->item[ind].pc;
+ else
+ return 0;
+}
+
+/* Find the range of pc values in a line.
+ Store the starting pc of the line into *STARTPTR
+ and the ending pc (start of next line) into *ENDPTR.
+ Returns 1 to indicate success.
+ Returns 0 if could not find the specified line. */
+
+int
+find_line_pc_range (sal, startptr, endptr)
+ struct symtab_and_line sal;
+ CORE_ADDR *startptr, *endptr;
+{
+ CORE_ADDR startaddr;
+ struct symtab_and_line found_sal;
+
+ startaddr = sal.pc;
+ if (startaddr == 0)
+ {
+ startaddr = find_line_pc (sal.symtab, sal.line);
+ }
+ if (startaddr == 0)
+ return 0;
+
+ /* 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". */
+
+ 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
+ table for the pc of the nearest line whose number is >= the specified one.
+ Return -1 if none is found. The value is >= 0 if it is an index.
+
+ Set *EXACT_MATCH nonzero if the value returned is an exact match. */
+
+static int
+find_line_common (l, lineno, exact_match)
+ register struct linetable *l;
+ register int lineno;
+ int *exact_match;
+{
+ register int i;
+ register int len;
+
+ /* BEST is the smallest linenumber > LINENO so far seen,
+ or 0 if none has been seen so far.
+ BEST_INDEX identifies the item for it. */
+
+ int best_index = -1;
+ int best = 0;
+
+ if (lineno <= 0)
+ return -1;
+ if (l == 0)
+ return -1;
+
+ len = l->nitems;
+ for (i = 0; i < len; i++)
+ {
+ register struct linetable_entry *item = &(l->item[i]);
+
+ if (item->line == lineno)
+ {
+ /* Return the first (lowest address) entry which matches. */
+ *exact_match = 1;
+ return i;
+ }
+
+ if (item->line > lineno && (best == 0 || item->line < best))
+ {
+ best = item->line;
+ best_index = i;
+ }
+ }
+
+ /* If we got here, we didn't get an exact match. */
+
+ *exact_match = 0;
+ return best_index;
+}
+
+int
+find_pc_line_pc_range (pc, startptr, endptr)
+ CORE_ADDR pc;
+ CORE_ADDR *startptr, *endptr;
+{
+ struct symtab_and_line sal;
+ sal = find_pc_line (pc, 0);
+ *startptr = sal.pc;
+ *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
+ beginning of the substring of the operator text.
+ Otherwise, return "". */
+static char *
+operator_chars (p, end)
+ char *p;
+ char **end;
+{
+ *end = "";
+ if (strncmp (p, "operator", 8))
+ return *end;
+ p += 8;
+
+ /* Don't get faked out by `operator' being part of a longer
+ identifier. */
+ if (isalpha(*p) || *p == '_' || *p == '$' || *p == '\0')
+ return *end;
+
+ /* Allow some whitespace between `operator' and the operator symbol. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* Recognize 'operator TYPENAME'. */
+
+ if (isalpha(*p) || *p == '_' || *p == '$')
+ {
+ register char *q = p+1;
+ while (isalnum(*q) || *q == '_' || *q == '$')
+ q++;
+ *end = q;
+ return p;
+ }
+
+ switch (*p)
+ {
+ case '!':
+ case '=':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ if (p[1] == '=')
+ *end = p+2;
+ else
+ *end = p+1;
+ return p;
+ case '<':
+ case '>':
+ case '+':
+ case '-':
+ case '&':
+ case '|':
+ if (p[1] == '=' || p[1] == p[0])
+ *end = p+2;
+ else
+ *end = p+1;
+ return p;
+ case '~':
+ case ',':
+ *end = p+1;
+ return p;
+ case '(':
+ if (p[1] != ')')
+ error ("`operator ()' must be specified without whitespace in `()'");
+ *end = p+2;
+ return p;
+ case '?':
+ if (p[1] != ':')
+ error ("`operator ?:' must be specified without whitespace in `?:'");
+ *end = p+2;
+ return p;
+ case '[':
+ if (p[1] != ']')
+ error ("`operator []' must be specified without whitespace in `[]'");
+ *end = p+2;
+ return p;
+ default:
+ error ("`operator %s' not supported", p);
+ break;
+ }
+ *end = "";
+ return *end;
+}
+
+/* Return the number of methods described for TYPE, including the
+ methods from types it derives from. This can't be done in the symbol
+ reader because the type of the baseclass might still be stubbed
+ when the definition of the derived class is parsed. */
+
+static int total_number_of_methods PARAMS ((struct type *type));
+
+static int
+total_number_of_methods (type)
+ struct type *type;
+{
+ int n;
+ int count;
+
+ CHECK_TYPEDEF (type);
+ count = TYPE_NFN_FIELDS_TOTAL (type);
+
+ for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
+ count += total_number_of_methods (TYPE_BASECLASS (type, n));
+
+ return count;
+}
+
+/* Recursive helper function for decode_line_1.
+ Look for methods named NAME in type T.
+ Return number of matches.
+ Put matches in SYM_ARR, which should have been allocated with
+ a size of total_number_of_methods (T) * sizeof (struct symbol *).
+ Note that this function is g++ specific. */
+
+int
+find_methods (t, name, sym_arr)
+ struct type *t;
+ char *name;
+ struct symbol **sym_arr;
+{
+ int i1 = 0;
+ int ibase;
+ struct symbol *sym_class;
+ char *class_name = type_name_no_tag (t);
+ /* Ignore this class if it doesn't have a name. This is ugly, but
+ unless we figure out how to get the physname without the name of
+ the class, then the loop can't do any good. */
+ if (class_name
+ && (sym_class = lookup_symbol (class_name,
+ (struct block *)NULL,
+ STRUCT_NAMESPACE,
+ (int *)NULL,
+ (struct symtab **)NULL)))
+ {
+ int method_counter;
+ /* FIXME: Shouldn't this just be CHECK_TYPEDEF (t)? */
+ t = SYMBOL_TYPE (sym_class);
+ for (method_counter = TYPE_NFN_FIELDS (t) - 1;
+ method_counter >= 0;
+ --method_counter)
+ {
+ 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;
+ field_counter >= 0;
+ --field_counter)
+ {
+ char *phys_name;
+ if (TYPE_FN_FIELD_STUB (f, field_counter))
+ check_stub_method (t, method_counter, field_counter);
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+ /* Destructor is handled by caller, dont add it to the list */
+ if (DESTRUCTOR_PREFIX_P (phys_name))
+ continue;
+
+ /* FIXME: Why are we looking this up in the
+ SYMBOL_BLOCK_VALUE (sym_class)? It is intended as a hook
+ for nested types? If so, it should probably hook to the
+ type, not the symbol. mipsread.c is the only symbol
+ reader which sets the SYMBOL_BLOCK_VALUE for types, and
+ this is not documented in symtab.h. -26Aug93. */
+
+ sym_arr[i1] = lookup_symbol (phys_name,
+ SYMBOL_BLOCK_VALUE (sym_class),
+ VAR_NAMESPACE,
+ (int *) NULL,
+ (struct symtab **) NULL);
+ if (sym_arr[i1]) i1++;
+ else
+ {
+ 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);
+ }
+ }
+ }
+ }
+
+ /* Only search baseclasses if there is no match yet, since names in
+ derived classes override those in baseclasses.
+
+ FIXME: The above is not true; it is only true of member functions
+ if they have the same number of arguments (??? - section 13.1 of the
+ ARM says the function members are not in the same scope but doesn't
+ really spell out the rules in a way I understand. In any case, if
+ the number of arguments differ this is a case in which we can overload
+ rather than hiding without any problem, and gcc 2.4.5 does overload
+ rather than hiding in this case). */
+
+ if (i1)
+ return i1;
+ for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
+ i1 += find_methods(TYPE_BASECLASS(t, ibase), name,
+ sym_arr + i1);
+ return i1;
+}
+
+/* Helper function for decode_line_1.
+ Build a canonical line spec in CANONICAL if it is non-NULL and if
+ the SAL has a symtab.
+ If SYMNAME is non-NULL the canonical line spec is `filename:symname'.
+ If SYMNAME is NULL the line number from SAL is used and the canonical
+ line spec is `filename:linenum'. */
+
+static void
+build_canonical_line_spec (sal, symname, canonical)
+ struct symtab_and_line *sal;
+ char *symname;
+ char ***canonical;
+{
+ char **canonical_arr;
+ char *canonical_name;
+ char *filename;
+ struct symtab *s = sal->symtab;
+
+ if (s == (struct symtab *)NULL
+ || s->filename == (char *)NULL
+ || canonical == (char ***)NULL)
+ return;
+
+ canonical_arr = (char **) xmalloc (sizeof (char *));
+ *canonical = canonical_arr;
+
+ filename = s->filename;
+ if (symname != NULL)
+ {
+ canonical_name = xmalloc (strlen (filename) + strlen (symname) + 2);
+ sprintf (canonical_name, "%s:%s", filename, symname);
+ }
+ else
+ {
+ canonical_name = xmalloc (strlen (filename) + 30);
+ sprintf (canonical_name, "%s:%d", filename, sal->line);
+ }
+ canonical_arr[0] = canonical_name;
+}
+
+/* Parse a string that specifies a line number.
+ Pass the address of a char * variable; that variable will be
+ advanced over the characters actually parsed.
+
+ The string can be:
+
+ LINENUM -- that line number in current file. PC returned is 0.
+ FILE:LINENUM -- that line in that file. PC returned is 0.
+ FUNCTION -- line number of openbrace of that function.
+ PC returned is the start of the function.
+ VARIABLE -- line number of definition of that variable.
+ PC returned is 0.
+ FILE:FUNCTION -- likewise, but prefer functions in that file.
+ *EXPR -- line in which address EXPR appears.
+
+ FUNCTION may be an undebuggable function found in minimal symbol table.
+
+ If the argument FUNFIRSTLINE is nonzero, we want the first line
+ of real code inside a function when a function is specified, and it is
+ not OK to specify a variable or type to get its line number.
+
+ DEFAULT_SYMTAB specifies the file to use if none is specified.
+ It defaults to current_source_symtab.
+ DEFAULT_LINE specifies the line number to use for relative
+ line numbers (that start with signs). Defaults to current_source_line.
+ If CANONICAL is non-NULL, store an array of strings containing the canonical
+ line specs there if necessary. Currently overloaded member functions and
+ line numbers or static functions without a filename yield a canonical
+ line spec. The array and the line spec strings are allocated on the heap,
+ it is the callers responsibility to free them.
+
+ Note that it is possible to return zero for the symtab
+ 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;
+ int funfirstline;
+ struct symtab *default_symtab;
+ int default_line;
+ char ***canonical;
+{
+ struct symtabs_and_lines values;
+#ifdef HPPA_COMPILER_BUG
+ /* FIXME: The native HP 9000/700 compiler has a bug which appears
+ when optimizing this file with target i960-vxworks. I haven't
+ been able to construct a simple test case. The problem is that
+ in the second call to SKIP_PROLOGUE below, the compiler somehow
+ does not realize that the statement val = find_pc_line (...) will
+ change the values of the fields of val. It extracts the elements
+ into registers at the top of the block, and does not update the
+ registers after the call to find_pc_line. You can check this by
+ inserting a printf at the end of find_pc_line to show what values
+ it is returning for val.pc and val.end and another printf after
+ the call to see what values the function actually got (remember,
+ this is compiling with cc -O, with this patch removed). You can
+ also examine the assembly listing: search for the second call to
+ skip_prologue; the LDO statement before the next call to
+ find_pc_line loads the address of the structure which
+ find_pc_line will return; if there is a LDW just before the LDO,
+ which fetches an element of the structure, then the compiler
+ still has the bug.
+
+ Setting val to volatile avoids the problem. We must undef
+ volatile, because the HPPA native compiler does not define
+ __STDC__, although it does understand volatile, and so volatile
+ will have been defined away in defs.h. */
+#undef volatile
+ volatile struct symtab_and_line val;
+#define volatile /*nothing*/
+#else
+ struct symtab_and_line val;
+#endif
+ register char *p, *p1;
+ char *q, *pp;
+#if 0
+ char *q1;
+#endif
+ register struct symtab *s;
+
+ register struct symbol *sym;
+ /* The symtab that SYM was found in. */
+ struct symtab *sym_symtab;
+
+ register CORE_ADDR pc;
+ register struct minimal_symbol *msymbol;
+ char *copy;
+ struct symbol *sym_class;
+ int i1;
+ int is_quoted, has_parens;
+ struct symbol **sym_arr;
+ struct type *t;
+ char *saved_arg = *argptr;
+ extern char *gdb_completer_quote_characters;
+
+ /* Defaults have defaults. */
+
+ if (default_symtab == 0)
+ {
+ default_symtab = current_source_symtab;
+ default_line = current_source_line;
+ }
+
+ /* See if arg is *PC */
+
+ if (**argptr == '*')
+ {
+ (*argptr)++;
+ pc = parse_and_eval_address_1 (argptr);
+ 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 = pc;
+ return values;
+ }
+
+ /* Maybe arg is FILE : LINENUM or FILE : FUNCTION */
+
+ s = NULL;
+ is_quoted = (**argptr
+ && 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] == ':') && !has_parens)
+ {
+
+ /* C++ */
+ if (is_quoted) *argptr = *argptr+1;
+ if (p[1] ==':')
+ {
+ /* Extract the class name. */
+ p1 = p;
+ while (p != *argptr && p[-1] == ' ') --p;
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = 0;
+
+ /* Discard the class name from the arg. */
+ p = p1 + 2;
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ sym_class = lookup_symbol (copy, 0, STRUCT_NAMESPACE, 0,
+ (struct symtab **)NULL);
+
+ if (sym_class &&
+ (t = check_typedef (SYMBOL_TYPE (sym_class)),
+ (TYPE_CODE (t) == TYPE_CODE_STRUCT
+ || TYPE_CODE (t) == TYPE_CODE_UNION)))
+ {
+ /* Arg token is not digits => try it as a function name
+ Find the next token(everything up to end or next blank). */
+ if (**argptr
+ && 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;
+ char *tmp = alloca (q1 - q + 1);
+ memcpy (tmp, q, q1 - q);
+ tmp[q1 - q] = '\0';
+ opname = cplus_mangle_opname (tmp, DMGL_ANSI);
+ if (opname == NULL)
+ {
+ error_begin ();
+ printf_filtered ("no mangling for \"%s\"\n", tmp);
+ cplusplus_hint (saved_arg);
+ return_to_top_level (RETURN_ERROR);
+ }
+ copy = (char*) alloca (3 + strlen(opname));
+ sprintf (copy, "__%s", opname);
+ p = q1;
+ }
+ else
+*/
+ {
+ copy = (char *) alloca (p - *argptr + 1 );
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = '\0';
+ if (p != *argptr
+ && copy[p - *argptr - 1]
+ && strchr (gdb_completer_quote_characters,
+ copy[p - *argptr - 1]) != NULL)
+ copy[p - *argptr - 1] = '\0';
+ }
+
+ /* no line number may be specified */
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ sym = 0;
+ i1 = 0; /* counter for the symbol array */
+ sym_arr = (struct symbol **) alloca(total_number_of_methods (t)
+ * sizeof(struct symbol *));
+
+ /* Cfront objects don't have fieldlists. */
+ if (destructor_name_p (copy, t) && TYPE_FN_FIELDLISTS (t) != NULL)
+ {
+ /* destructors are a special case. */
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (t, 0);
+ int len = TYPE_FN_FIELDLIST_LENGTH (t, 0) - 1;
+ /* gcc 1.x puts destructor in last field,
+ gcc 2.x puts destructor in first field. */
+ char *phys_name = TYPE_FN_FIELD_PHYSNAME (f, len);
+ if (!DESTRUCTOR_PREFIX_P (phys_name))
+ {
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, 0);
+ if (!DESTRUCTOR_PREFIX_P (phys_name))
+ phys_name = "";
+ }
+ sym_arr[i1] =
+ lookup_symbol (phys_name, SYMBOL_BLOCK_VALUE (sym_class),
+ VAR_NAMESPACE, 0, (struct symtab **)NULL);
+ if (sym_arr[i1]) i1++;
+ }
+ else
+ i1 = find_methods (t, copy, sym_arr);
+ if (i1 == 1)
+ {
+ /* There is exactly one field with that name. */
+ sym = sym_arr[0];
+
+ if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
+ values.nelts = 1;
+ values.sals[0] = find_function_start_sal (sym,
+ funfirstline);
+ }
+ else
+ {
+ values.nelts = 0;
+ }
+ return values;
+ }
+ if (i1 > 0)
+ {
+ /* There is more than one field with that name
+ (overloaded). Ask the user which one to use. */
+ return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+ }
+ else
+ {
+ char *tmp;
+
+ if (OPNAME_PREFIX_P (copy))
+ {
+ tmp = (char *)alloca (strlen (copy+3) + 9);
+ strcpy (tmp, "operator ");
+ strcat (tmp, copy+3);
+ }
+ else
+ tmp = copy;
+ error_begin ();
+ if (tmp[0] == '~')
+ printf_filtered
+ ("the class `%s' does not have destructor defined\n",
+ SYMBOL_SOURCE_NAME(sym_class));
+ else
+ 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. */
+ printf_filtered
+ ("can't find class, struct, or union named \"%s\"\n", copy);
+ cplusplus_hint (saved_arg);
+ return_to_top_level (RETURN_ERROR);
+ }
+ }
+ /* end of C++ */
+
+
+ /* Extract the file name. */
+ p1 = p;
+ while (p != *argptr && p[-1] == ' ') --p;
+ copy = (char *) alloca (p - *argptr + 1);
+ memcpy (copy, *argptr, p - *argptr);
+ copy[p - *argptr] = 0;
+
+ /* Find that file's data. */
+ s = lookup_symtab (copy);
+ if (s == 0)
+ {
+ if (!have_full_symbols () && !have_partial_symbols ())
+ error (no_symtab_msg);
+ error ("No source file named %s.", copy);
+ }
+
+ /* Discard the file name from the arg. */
+ p = p1 + 1;
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+ }
+
+ /* S is specified file's symtab, or 0 if no file specified.
+ arg no longer contains the file name. */
+
+ /* Check whether arg is all digits (and sign) */
+
+ q = *argptr;
+ if (*q == '-' || *q == '+') q++;
+ while (*q >= '0' && *q <= '9')
+ q++;
+
+ 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;
+
+ /* We might need a canonical line spec if no file was specified. */
+ int need_canonical = (s == 0) ? 1 : 0;
+
+ /* This is where we need to make sure that we have good defaults.
+ We must guarantee that this section of code is never executed
+ when we are called with just a function name, since
+ select_source_symtab calls us with such an argument */
+
+ if (s == 0 && default_symtab == 0)
+ {
+ select_source_symtab (0);
+ default_symtab = current_source_symtab;
+ default_line = current_source_line;
+ }
+
+ if (**argptr == '+')
+ sign = plus, (*argptr)++;
+ else if (**argptr == '-')
+ sign = minus, (*argptr)++;
+ val.line = atoi (*argptr);
+ switch (sign)
+ {
+ case plus:
+ if (q == *argptr)
+ val.line = 5;
+ if (s == 0)
+ val.line = default_line + val.line;
+ break;
+ case minus:
+ if (q == *argptr)
+ val.line = 15;
+ if (s == 0)
+ val.line = default_line - val.line;
+ else
+ val.line = 1;
+ break;
+ case none:
+ break; /* No need to adjust val.line. */
+ }
+
+ while (*q == ' ' || *q == '\t') q++;
+ *argptr = q;
+ if (s == 0)
+ s = default_symtab;
+ val.symtab = s;
+ val.pc = 0;
+ values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
+ values.sals[0] = val;
+ values.nelts = 1;
+ if (need_canonical)
+ build_canonical_line_spec (values.sals, NULL, canonical);
+ return values;
+ }
+
+ /* Arg token is not digits => try it as a variable name
+ Find the next token (everything up to end or next whitespace). */
+
+ if (**argptr == '$') /* Convenience variable */
+ p = skip_quoted (*argptr + 1);
+ else 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 (p != *argptr
+ && copy[0]
+ && copy[0] == copy [p - *argptr - 1]
+ && strchr (gdb_completer_quote_characters, copy[0]) != NULL)
+ {
+ copy [p - *argptr - 1] = '\0';
+ copy++;
+ }
+ while (*p == ' ' || *p == '\t') p++;
+ *argptr = p;
+
+ /* See if it's a convenience variable */
+
+ if (*copy == '$')
+ {
+ value_ptr valx;
+ int need_canonical = (s == 0) ? 1 : 0;
+
+ valx = value_of_internalvar (lookup_internalvar (copy + 1));
+ if (TYPE_CODE (VALUE_TYPE (valx)) != TYPE_CODE_INT)
+ error ("Convenience variables used in line specs must have integer values.");
+
+ val.symtab = s ? s : default_symtab;
+ val.line = value_as_long (valx);
+ val.pc = 0;
+
+ values.sals = (struct symtab_and_line *)xmalloc (sizeof val);
+ values.sals[0] = val;
+ values.nelts = 1;
+
+ if (need_canonical)
+ build_canonical_line_spec (values.sals, NULL, canonical);
+
+ return values;
+ }
+
+
+ /* Look up that token as a variable.
+ If file specified, use that file's per-file block to start with. */
+
+ sym = lookup_symbol (copy,
+ (s ? BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)
+ : get_selected_block ()),
+ VAR_NAMESPACE, 0, &sym_symtab);
+
+ if (sym != NULL)
+ {
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ /* Arg is the name of a function */
+ values.sals = (struct symtab_and_line *)xmalloc (sizeof (struct symtab_and_line));
+ values.sals[0] = find_function_start_sal (sym, funfirstline);
+ values.nelts = 1;
+
+ /* 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);
+ struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+ if (lookup_block_symbol (b, copy, VAR_NAMESPACE) != NULL)
+ build_canonical_line_spec (values.sals, copy, canonical);
+ }
+ return values;
+ }
+ else
+ {
+ if (funfirstline)
+ error ("\"%s\" is not a function", copy);
+ else if (SYMBOL_LINE (sym) != 0)
+ {
+ /* We know its line number. */
+ values.sals = (struct symtab_and_line *)
+ xmalloc (sizeof (struct symtab_and_line));
+ values.nelts = 1;
+ memset (&values.sals[0], 0, sizeof (values.sals[0]));
+ values.sals[0].symtab = sym_symtab;
+ values.sals[0].line = SYMBOL_LINE (sym);
+ return values;
+ }
+ else
+ /* This can happen if it is compiled with a compiler which doesn't
+ put out line numbers for variables. */
+ /* FIXME: Shouldn't we just set .line and .symtab to zero
+ and return? For example, "info line foo" could print
+ the address. */
+ error ("Line number not known for symbol \"%s\"", copy);
+ }
+ }
+
+ msymbol = lookup_minimal_symbol (copy, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ val.symtab = 0;
+ val.line = 0;
+ val.pc = SYMBOL_VALUE_ADDRESS (msymbol);
+ if (funfirstline)
+ {
+ 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;
+ return values;
+ }
+
+ if (!have_full_symbols () &&
+ !have_partial_symbols () && !have_minimal_symbols ())
+ error (no_symtab_msg);
+
+ error ("Function \"%s\" not defined.", copy);
+ return values; /* for lint */
+}
+
+struct symtabs_and_lines
+decode_line_spec (string, funfirstline)
+ char *string;
+ int funfirstline;
+{
+ struct symtabs_and_lines sals;
+ if (string == 0)
+ error ("Empty line specification.");
+ sals = decode_line_1 (&string, funfirstline,
+ current_source_symtab, current_source_line,
+ (char ***)NULL);
+ if (*string)
+ error ("Junk at end of line specification: %s", string);
+ return sals;
+}
+
+/* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
+ operate on (ask user if necessary).
+ If CANONICAL is non-NULL return a corresponding array of mangled names
+ as canonical line specs there. */
+
+static struct symtabs_and_lines
+decode_line_2 (sym_arr, nelts, funfirstline, canonical)
+ struct symbol *sym_arr[];
+ int nelts;
+ int funfirstline;
+ char ***canonical;
+{
+ struct symtabs_and_lines values, return_values;
+ char *args, *arg1;
+ int i;
+ char *prompt;
+ char *symname;
+ struct cleanup *old_chain;
+ char **canonical_arr = (char **)NULL;
+
+ values.sals = (struct symtab_and_line *) alloca (nelts * sizeof(struct symtab_and_line));
+ return_values.sals = (struct symtab_and_line *) xmalloc (nelts * sizeof(struct symtab_and_line));
+ old_chain = make_cleanup (free, return_values.sals);
+
+ if (canonical)
+ {
+ canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
+ make_cleanup (free, canonical_arr);
+ memset (canonical_arr, 0, nelts * sizeof (char *));
+ *canonical = canonical_arr;
+ }
+
+ i = 0;
+ printf_unfiltered("[0] cancel\n[1] all\n");
+ while (i < nelts)
+ {
+ if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
+ {
+ 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_unfiltered ("?HERE\n");
+ i++;
+ }
+
+ if ((prompt = getenv ("PS2")) == NULL)
+ {
+ prompt = ">";
+ }
+ printf_unfiltered("%s ",prompt);
+ gdb_flush(gdb_stdout);
+
+ args = command_line_input ((char *) NULL, 0, "overload-choice");
+
+ if (args == 0 || *args == 0)
+ error_no_arg ("one or more choice numbers");
+
+ i = 0;
+ while (*args)
+ {
+ int num;
+
+ arg1 = args;
+ while (*arg1 >= '0' && *arg1 <= '9') arg1++;
+ if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
+ error ("Arguments must be choice numbers.");
+
+ num = atoi (args);
+
+ if (num == 0)
+ error ("cancelled");
+ else if (num == 1)
+ {
+ if (canonical_arr)
+ {
+ for (i = 0; i < nelts; i++)
+ {
+ if (canonical_arr[i] == NULL)
+ {
+ symname = SYMBOL_NAME (sym_arr[i]);
+ canonical_arr[i] = savestring (symname, strlen (symname));
+ }
+ }
+ }
+ memcpy (return_values.sals, values.sals,
+ (nelts * sizeof(struct symtab_and_line)));
+ return_values.nelts = nelts;
+ discard_cleanups (old_chain);
+ return return_values;
+ }
+
+ if (num > nelts + 2)
+ {
+ printf_unfiltered ("No choice number %d.\n", num);
+ }
+ else
+ {
+ num -= 2;
+ if (values.sals[num].pc)
+ {
+ if (canonical_arr)
+ {
+ symname = SYMBOL_NAME (sym_arr[num]);
+ make_cleanup (free, symname);
+ canonical_arr[i] = savestring (symname, strlen (symname));
+ }
+ return_values.sals[i++] = values.sals[num];
+ values.sals[num].pc = 0;
+ }
+ else
+ {
+ printf_unfiltered ("duplicate request for %d ignored.\n", num);
+ }
+ }
+
+ args = arg1;
+ while (*args == ' ' || *args == '\t') args++;
+ }
+ return_values.nelts = i;
+ discard_cleanups (old_chain);
+ return return_values;
+}
+
+
+/* Slave routine for sources_info. Force line breaks at ,'s.
+ NAME is the name to print and *FIRST is nonzero if this is the first
+ name printed. Set *FIRST to zero. */
+static void
+output_source_filename (name, first)
+ char *name;
+ int *first;
+{
+ /* Table of files printed so far. Since a single source file can
+ result in several partial symbol tables, we need to avoid printing
+ it more than once. Note: if some of the psymtabs are read in and
+ some are not, it gets printed both under "Source files for which
+ symbols have been read" and "Source files for which symbols will
+ be read in on demand". I consider this a reasonable way to deal
+ with the situation. I'm not sure whether this can also happen for
+ symtabs; it doesn't hurt to check. */
+ static char **tab = NULL;
+ /* Allocated size of tab in elements.
+ Start with one 256-byte block (when using GNU malloc.c).
+ 24 is the malloc overhead when range checking is in effect. */
+ static int tab_alloc_size = (256 - 24) / sizeof (char *);
+ /* Current size of tab in elements. */
+ static int tab_cur_size;
+
+ char **p;
+
+ if (*first)
+ {
+ if (tab == NULL)
+ tab = (char **) xmalloc (tab_alloc_size * sizeof (*tab));
+ tab_cur_size = 0;
+ }
+
+ /* Is NAME in tab? */
+ for (p = tab; p < tab + tab_cur_size; p++)
+ if (STREQ (*p, name))
+ /* Yes; don't print it again. */
+ return;
+ /* No; add it to tab. */
+ if (tab_cur_size == tab_alloc_size)
+ {
+ tab_alloc_size *= 2;
+ tab = (char **) xrealloc ((char *) tab, tab_alloc_size * sizeof (*tab));
+ }
+ tab[tab_cur_size++] = name;
+
+ if (*first)
+ {
+ *first = 0;
+ }
+ else
+ {
+ printf_filtered (", ");
+ }
+
+ wrap_here ("");
+ fputs_filtered (name, gdb_stdout);
+}
+
+static void
+sources_info (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct objfile *objfile;
+ int first;
+
+ if (!have_full_symbols () && !have_partial_symbols ())
+ {
+ error (no_symtab_msg);
+ }
+
+ printf_filtered ("Source files for which symbols have been read in:\n\n");
+
+ first = 1;
+ ALL_SYMTABS (objfile, s)
+ {
+ output_source_filename (s -> filename, &first);
+ }
+ printf_filtered ("\n\n");
+
+ printf_filtered ("Source files for which symbols will be read in on demand:\n\n");
+
+ first = 1;
+ ALL_PSYMTABS (objfile, ps)
+ {
+ if (!ps->readin)
+ {
+ output_source_filename (ps -> filename, &first);
+ }
+ }
+ printf_filtered ("\n");
+}
+
+/* List all symbols (if REGEXP is NULL) or all symbols matching REGEXP.
+ If CLASS is zero, list all symbols except functions, type names, and
+ constants (enums).
+ If CLASS is 1, list only functions.
+ If CLASS is 2, list only type names.
+ If CLASS is 3, list only method names.
+
+ BPT is non-zero if we should set a breakpoint at the functions
+ we find. */
+
+static void
+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;
+ register struct blockvector *bv;
+ struct blockvector *prev_bv = 0;
+ register struct block *b;
+ register int i, j;
+ register struct symbol *sym;
+ struct partial_symbol **psym;
+ struct objfile *objfile;
+ struct minimal_symbol *msymbol;
+ char *val;
+ static char *classnames[]
+ = {"variable", "function", "type", "method"};
+ int found_in_file = 0;
+ int found_misc = 0;
+ static enum minimal_symbol_type types[]
+ = {mst_data, mst_text, mst_abs, mst_unknown};
+ static enum minimal_symbol_type types2[]
+ = {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)
+ {
+ /* Make sure spacing is right for C++ operators.
+ This is just a courtesy to make the matching less sensitive
+ to how many spaces the user leaves between 'operator'
+ and <TYPENAME> or <OPERATOR>. */
+ char *opend;
+ char *opname = operator_chars (regexp, &opend);
+ if (*opname)
+ {
+ int fix = -1; /* -1 means ok; otherwise number of spaces needed. */
+ if (isalpha(*opname) || *opname == '_' || *opname == '$')
+ {
+ /* There should 1 space between 'operator' and 'TYPENAME'. */
+ if (opname[-1] != ' ' || opname[-2] == ' ')
+ fix = 1;
+ }
+ else
+ {
+ /* There should 0 spaces between 'operator' and 'OPERATOR'. */
+ if (opname[-1] == ' ')
+ fix = 0;
+ }
+ /* If wrong number of spaces, fix it. */
+ if (fix >= 0)
+ {
+ char *tmp = (char*) alloca(opend-opname+10);
+ sprintf(tmp, "operator%.*s%s", fix, " ", opname);
+ regexp = tmp;
+ }
+ }
+
+ if (0 != (val = re_comp (regexp)))
+ error ("Invalid regexp (%s): %s", val, regexp);
+ }
+
+ /* Search through the partial symtabs *first* for all symbols
+ matching the regexp. That way we don't have to reproduce all of
+ the machinery below. */
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ struct partial_symbol **bound, **gbound, **sbound;
+ int keep_going = 1;
+
+ if (ps->readin) continue;
+
+ gbound = objfile->global_psymbols.list + ps->globals_offset + ps->n_global_syms;
+ sbound = objfile->static_psymbols.list + ps->statics_offset + ps->n_static_syms;
+ bound = gbound;
+
+ /* Go through all of the symbols stored in a partial
+ symtab in one loop. */
+ psym = objfile->global_psymbols.list + ps->globals_offset;
+ while (keep_going)
+ {
+ if (psym >= bound)
+ {
+ if (bound == gbound && ps->n_static_syms != 0)
+ {
+ psym = objfile->static_psymbols.list + ps->statics_offset;
+ bound = sbound;
+ }
+ else
+ keep_going = 0;
+ continue;
+ }
+ else
+ {
+ QUIT;
+
+ /* If it would match (logic taken from loop below)
+ load the file and go on to the next one */
+ if ((regexp == NULL || SYMBOL_MATCHES_REGEXP (*psym))
+ && ((class == 0 && SYMBOL_CLASS (*psym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (*psym) != LOC_BLOCK)
+ || (class == 1 && SYMBOL_CLASS (*psym) == LOC_BLOCK)
+ || (class == 2 && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)
+ || (class == 3 && SYMBOL_CLASS (*psym) == LOC_BLOCK)))
+ {
+ PSYMTAB_TO_SYMTAB(ps);
+ keep_going = 0;
+ }
+ }
+ psym++;
+ }
+ }
+
+ /* Here, we search through the minimal symbol tables for functions
+ and variables that match, and force their symbols to be read.
+ This is in particular necessary for demangled variable names,
+ which are no longer put into the partial symbol tables.
+ The symbol will then be found during the scan of symtabs below.
+
+ For functions, find_pc_symtab should succeed if we have debug info
+ for the function, for variables we have to call lookup_symbol
+ to determine if the variable has debug info.
+ If the lookup fails, set found_misc so that we will rescan to print
+ any matching symbols without debug info.
+ */
+
+ if (class == 0 || class == 1)
+ {
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == ourtype ||
+ MSYMBOL_TYPE (msymbol) == ourtype2 ||
+ MSYMBOL_TYPE (msymbol) == ourtype3 ||
+ MSYMBOL_TYPE (msymbol) == ourtype4)
+ {
+ if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+ {
+ if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol)))
+ {
+ if (class == 1
+ || lookup_symbol (SYMBOL_NAME (msymbol),
+ (struct block *) NULL,
+ VAR_NAMESPACE,
+ 0, (struct symtab **) NULL) == NULL)
+ found_misc = 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* Printout here so as to get after the "Reading in symbols"
+ messages which will be generated above. */
+ if (!bpt)
+ printf_filtered (regexp
+ ? "All %ss matching regular expression \"%s\":\n"
+ : "All defined %ss:\n",
+ classnames[class],
+ regexp);
+
+ ALL_SYMTABS (objfile, s)
+ {
+ found_in_file = 0;
+ bv = BLOCKVECTOR (s);
+ /* Often many files share a blockvector.
+ Scan each blockvector only once so that
+ we don't get every symbol many times.
+ It happens that the first symtab in the list
+ for any given blockvector is the main file. */
+ if (bv != prev_bv)
+ for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+ {
+ b = BLOCKVECTOR_BLOCK (bv, i);
+ /* Skip the sort if this block is always sorted. */
+ if (!BLOCK_SHOULD_SORT (b))
+ sort_block_syms (b);
+ for (j = 0; j < BLOCK_NSYMS (b); j++)
+ {
+ QUIT;
+ sym = BLOCK_SYM (b, j);
+ if ((regexp == NULL || SYMBOL_MATCHES_REGEXP (sym))
+ && ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+ && SYMBOL_CLASS (sym) != LOC_BLOCK
+ && SYMBOL_CLASS (sym) != LOC_CONST)
+ || (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ || (class == 2 && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ || (class == 3 && SYMBOL_CLASS (sym) == LOC_BLOCK)))
+ {
+ if (bpt)
+ {
+ /* Set a breakpoint here, if it's a function */
+ if (class == 1)
+ {
+ /* There may be more than one function with the
+ 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.
+ 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))
+ + 4);
+ strcpy (string, s->filename);
+ strcat (string, ":'");
+ strcat (string, SYMBOL_NAME(sym));
+ strcat (string, "'");
+ break_command (string, from_tty);
+ }
+ }
+ else if (!found_in_file)
+ {
+ fputs_filtered ("\nFile ", gdb_stdout);
+ fputs_filtered (s->filename, gdb_stdout);
+ fputs_filtered (":\n", gdb_stdout);
+ }
+ found_in_file = 1;
+
+ if (class != 2 && i == STATIC_BLOCK)
+ printf_filtered ("static ");
+
+ /* Typedef that is not a C++ class */
+ if (class == 2
+ && SYMBOL_NAMESPACE (sym) != STRUCT_NAMESPACE)
+ c_typedef_print (SYMBOL_TYPE(sym), sym, gdb_stdout);
+ /* variable, func, or typedef-that-is-c++-class */
+ else if (class < 2 ||
+ (class == 2 &&
+ SYMBOL_NAMESPACE(sym) == STRUCT_NAMESPACE))
+ {
+ type_print (SYMBOL_TYPE (sym),
+ (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+ ? "" : SYMBOL_SOURCE_NAME (sym)),
+ gdb_stdout, 0);
+
+ printf_filtered (";\n");
+ }
+ else
+ {
+# if 0 /* FIXME, why is this zapped out? */
+ char buf[1024];
+ c_type_print_base (TYPE_FN_FIELD_TYPE(t, i),
+ gdb_stdout, 0, 0);
+ c_type_print_varspec_prefix (TYPE_FN_FIELD_TYPE(t, i),
+ gdb_stdout, 0);
+ sprintf (buf, " %s::", type_name_no_tag (t));
+ cp_type_print_method_args (TYPE_FN_FIELD_ARGS (t, i),
+ buf, name, gdb_stdout);
+# endif
+ }
+ }
+ }
+ }
+ prev_bv = bv;
+ }
+
+ /* If there are no eyes, avoid all contact. I mean, if there are
+ no debug symbols, then print directly from the msymbol_vector. */
+
+ if (found_misc || class != 1)
+ {
+ found_in_file = 0;
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ if (MSYMBOL_TYPE (msymbol) == ourtype ||
+ MSYMBOL_TYPE (msymbol) == ourtype2 ||
+ MSYMBOL_TYPE (msymbol) == ourtype3 ||
+ MSYMBOL_TYPE (msymbol) == ourtype4)
+ {
+ if (regexp == NULL || SYMBOL_MATCHES_REGEXP (msymbol))
+ {
+ /* Functions: Look up by address. */
+ if (class != 1 ||
+ (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))))
+ {
+ /* Variables/Absolutes: Look up by name */
+ if (lookup_symbol (SYMBOL_NAME (msymbol),
+ (struct block *) NULL, VAR_NAMESPACE,
+ 0, (struct symtab **) NULL) == NULL)
+ {
+ if (bpt)
+ {
+ break_command (SYMBOL_NAME (msymbol), from_tty);
+ printf_filtered ("<function, no debug info> %s;\n",
+ SYMBOL_SOURCE_NAME (msymbol));
+ continue;
+ }
+ if (!found_in_file)
+ {
+ printf_filtered ("\nNon-debugging symbols:\n");
+ found_in_file = 1;
+ }
+ printf_filtered (" %08lx %s\n",
+ (unsigned long) SYMBOL_VALUE_ADDRESS (msymbol),
+ SYMBOL_SOURCE_NAME (msymbol));
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void
+variables_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 0, 0, from_tty);
+}
+
+static void
+functions_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 1, 0, from_tty);
+}
+
+static void
+types_info (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 2, 0, from_tty);
+}
+
+#if 0
+/* Tiemann says: "info methods was never implemented." */
+static void
+methods_info (regexp)
+ char *regexp;
+{
+ list_symbols (regexp, 3, 0, from_tty);
+}
+#endif /* 0 */
+
+/* Breakpoint all functions matching regular expression. */
+static void
+rbreak_command (regexp, from_tty)
+ char *regexp;
+ int from_tty;
+{
+ list_symbols (regexp, 1, 1, from_tty);
+}
+
+
+/* Return Nonzero if block a is lexically nested within block b,
+ or if a and b have the same pc range.
+ Return zero otherwise. */
+int
+contained_in (a, b)
+ struct block *a, *b;
+{
+ if (!a || !b)
+ return 0;
+ return BLOCK_START (a) >= BLOCK_START (b)
+ && BLOCK_END (a) <= BLOCK_END (b);
+}
+
+
+/* Helper routine for make_symbol_completion_list. */
+
+static int return_val_size;
+static int return_val_index;
+static char **return_val;
+
+#define COMPLETION_LIST_ADD_SYMBOL(symbol, sym_text, len, text, word) \
+ do { \
+ if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) \
+ /* Put only the mangled name on the list. */ \
+ /* Advantage: "b foo<TAB>" completes to "b foo(int, int)" */ \
+ /* Disadvantage: "b foo__i<TAB>" doesn't complete. */ \
+ completion_list_add_name \
+ (SYMBOL_DEMANGLED_NAME (symbol), (sym_text), (len), (text), (word)); \
+ else \
+ completion_list_add_name \
+ (SYMBOL_NAME (symbol), (sym_text), (len), (text), (word)); \
+ } while (0)
+
+/* Test to see if the symbol specified by SYMNAME (which is already
+ demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
+ characters. If so, add it to the current completion list. */
+
+static void
+completion_list_add_name (symname, sym_text, sym_text_len, text, word)
+ char *symname;
+ char *sym_text;
+ int sym_text_len;
+ char *text;
+ char *word;
+{
+ int newsize;
+ int i;
+
+ /* clip symbols that cannot match */
+
+ if (strncmp (symname, sym_text, sym_text_len) != 0)
+ {
+ return;
+ }
+
+ /* Clip any symbol names that we've already considered. (This is a
+ time optimization) */
+
+ for (i = 0; i < return_val_index; ++i)
+ {
+ if (STREQ (symname, return_val[i]))
+ {
+ return;
+ }
+ }
+
+ /* We have a match for a completion, so add SYMNAME to the current list
+ of matches. Note that the name is moved to freshly malloc'd space. */
+
+ {
+ char *new;
+ if (word == sym_text)
+ {
+ new = xmalloc (strlen (symname) + 5);
+ strcpy (new, symname);
+ }
+ else if (word > sym_text)
+ {
+ /* Return some portion of symname. */
+ new = xmalloc (strlen (symname) + 5);
+ strcpy (new, symname + (word - sym_text));
+ }
+ else
+ {
+ /* Return some of SYM_TEXT plus symname. */
+ new = xmalloc (strlen (symname) + (sym_text - word) + 5);
+ strncpy (new, word, sym_text - word);
+ new[sym_text - word] = '\0';
+ strcat (new, symname);
+ }
+
+ /* Recheck for duplicates if we intend to add a modified symbol. */
+ if (word != sym_text)
+ {
+ for (i = 0; i < return_val_index; ++i)
+ {
+ if (STREQ (new, return_val[i]))
+ {
+ free (new);
+ return;
+ }
+ }
+ }
+
+ if (return_val_index + 3 > return_val_size)
+ {
+ newsize = (return_val_size *= 2) * sizeof (char *);
+ return_val = (char **) xrealloc ((char *) return_val, newsize);
+ }
+ return_val[return_val_index++] = new;
+ return_val[return_val_index] = NULL;
+ }
+}
+
+/* Return a NULL terminated array of all symbols (regardless of class) which
+ begin by matching TEXT. If the answer is no symbols, then the return value
+ is an array which contains only a NULL pointer.
+
+ Problem: All of the symbols have to be copied because readline frees them.
+ I'm not going to worry about this; hopefully there won't be that many. */
+
+char **
+make_symbol_completion_list (text, word)
+ char *text;
+ char *word;
+{
+ register struct symbol *sym;
+ register struct symtab *s;
+ register struct partial_symtab *ps;
+ register struct minimal_symbol *msymbol;
+ register struct objfile *objfile;
+ register struct block *b, *surrounding_static_block = 0;
+ register int i, j;
+ struct partial_symbol **psym;
+ /* The symbol we are completing on. Points in same buffer as text. */
+ char *sym_text;
+ /* Length of sym_text. */
+ int sym_text_len;
+
+ /* Now look for the symbol we are supposed to complete on.
+ FIXME: This should be language-specific. */
+ {
+ char *p;
+ char quote_found;
+ char *quote_pos = NULL;
+
+ /* First see if this is a quoted string. */
+ quote_found = '\0';
+ for (p = text; *p != '\0'; ++p)
+ {
+ if (quote_found != '\0')
+ {
+ if (*p == quote_found)
+ /* Found close quote. */
+ quote_found = '\0';
+ else if (*p == '\\' && p[1] == quote_found)
+ /* A backslash followed by the quote character
+ doesn't end the string. */
+ ++p;
+ }
+ else if (*p == '\'' || *p == '"')
+ {
+ quote_found = *p;
+ quote_pos = p;
+ }
+ }
+ if (quote_found == '\'')
+ /* A string within single quotes can be a symbol, so complete on it. */
+ sym_text = quote_pos + 1;
+ else if (quote_found == '"')
+ /* A double-quoted string is never a symbol, nor does it make sense
+ to complete it any other way. */
+ return NULL;
+ else
+ {
+ /* It is not a quoted string. Break it based on the characters
+ which are in symbols. */
+ while (p > text)
+ {
+ if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0')
+ --p;
+ else
+ break;
+ }
+ sym_text = p;
+ }
+ }
+
+ sym_text_len = strlen (sym_text);
+
+ return_val_size = 100;
+ return_val_index = 0;
+ return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *));
+ return_val[0] = NULL;
+
+ /* Look through the partial symtabs for all symbols which begin
+ by matching SYM_TEXT. Add each one that you find to the list. */
+
+ ALL_PSYMTABS (objfile, ps)
+ {
+ /* If the psymtab's been read in we'll get it when we search
+ through the blockvector. */
+ if (ps->readin) continue;
+
+ for (psym = objfile->global_psymbols.list + ps->globals_offset;
+ psym < (objfile->global_psymbols.list + ps->globals_offset
+ + ps->n_global_syms);
+ psym++)
+ {
+ /* If interrupted, then quit. */
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word);
+ }
+
+ for (psym = objfile->static_psymbols.list + ps->statics_offset;
+ psym < (objfile->static_psymbols.list + ps->statics_offset
+ + ps->n_static_syms);
+ psym++)
+ {
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (*psym, sym_text, sym_text_len, text, word);
+ }
+ }
+
+ /* At this point scan through the misc symbol vectors and add each
+ symbol you find to the list. Eventually we want to ignore
+ anything that isn't a text symbol (everything else will be
+ handled by the psymtab code above). */
+
+ ALL_MSYMBOLS (objfile, msymbol)
+ {
+ QUIT;
+ COMPLETION_LIST_ADD_SYMBOL (msymbol, sym_text, sym_text_len, text, word);
+ }
+
+ /* Search upwards from currently selected frame (so that we can
+ complete on local vars. */
+
+ for (b = get_selected_block (); b != NULL; b = BLOCK_SUPERBLOCK (b))
+ {
+ if (!BLOCK_SUPERBLOCK (b))
+ {
+ surrounding_static_block = b; /* For elmin of dups */
+ }
+
+ /* Also catch fields of types defined in this places which match our
+ text string. Only complete on types visible from current context. */
+
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+ {
+ struct type *t = SYMBOL_TYPE (sym);
+ enum type_code c = TYPE_CODE (t);
+
+ if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
+ {
+ for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
+ {
+ if (TYPE_FIELD_NAME (t, j))
+ {
+ completion_list_add_name (TYPE_FIELD_NAME (t, j),
+ sym_text, sym_text_len, text, word);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Go through the symtabs and check the externs and statics for
+ symbols which match. */
+
+ ALL_SYMTABS (objfile, s)
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ }
+ }
+
+ ALL_SYMTABS (objfile, s)
+ {
+ QUIT;
+ b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+ /* Don't do this block twice. */
+ if (b == surrounding_static_block) continue;
+ for (i = 0; i < BLOCK_NSYMS (b); i++)
+ {
+ sym = BLOCK_SYM (b, i);
+ COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word);
+ }
+ }
+
+ return (return_val);
+}
+
+/* Determine if PC is in the prologue of a function. The prologue is the area
+ between the first instruction of a function, and the first executable line.
+ Returns 1 if PC *might* be in prologue, 0 if definately *not* in prologue.
+
+ If non-zero, func_start is where we thing the prologue starts, possibly
+ by previous examination of symbol table information.
+ */
+
+int
+in_prologue (pc, func_start)
+ CORE_ADDR pc;
+ CORE_ADDR func_start;
+{
+ struct symtab_and_line sal;
+ CORE_ADDR func_addr, func_end;
+
+ if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
+ goto nosyms; /* Might be in prologue */
+
+ sal = find_pc_line (func_addr, 0);
+
+ if (sal.line == 0)
+ goto nosyms;
+
+ if (sal.end > func_addr
+ && sal.end <= func_end) /* Is prologue in function? */
+ return pc < sal.end; /* Yes, is pc in prologue? */
+
+ /* The line after the prologue seems to be outside the function. In this
+ case, tell the caller to find the prologue the hard way. */
+
+ return 1;
+
+/* Come here when symtabs don't contain line # info. In this case, it is
+ likely that the user has stepped into a library function w/o symbols, or
+ is doing a stepi/nexti through code without symbols. */
+
+ nosyms:
+
+/* If func_start is zero (meaning unknown) then we don't know whether pc is
+ in the prologue or not. I.E. it might be. */
+
+ if (!func_start) return 1;
+
+/* We need to call the target-specific prologue skipping functions with the
+ function's start address because PC may be pointing at an instruction that
+ could be mistakenly considered part of the prologue. */
+
+ SKIP_PROLOGUE (func_start);
+
+ return pc < func_start;
+}
+
+
+void
+_initialize_symtab ()
+{
+ add_info ("variables", variables_info,
+ "All global and static variable names, or those matching REGEXP.");
+ add_info ("functions", functions_info,
+ "All function names, or those matching REGEXP.");
+
+ /* FIXME: This command has at least the following problems:
+ 1. It prints builtin types (in a very strange and confusing fashion).
+ 2. It doesn't print right, e.g. with
+ typedef struct foo *FOO
+ type_print prints "FOO" when we want to make it (in this situation)
+ print "struct foo *".
+ I also think "ptype" or "whatis" is more likely to be useful (but if
+ there is much disagreement "info types" can be fixed). */
+ add_info ("types", types_info,
+ "All type names, or those matching REGEXP.");
+
+#if 0
+ add_info ("methods", methods_info,
+ "All method names, or those matching REGEXP::REGEXP.\n\
+If the class qualifier is omitted, it is assumed to be the current scope.\n\
+If the first REGEXP is omitted, then all methods matching the second REGEXP\n\
+are listed.");
+#endif
+ add_info ("sources", sources_info,
+ "Source files in the program.");
+
+ add_com ("rbreak", no_class, rbreak_command,
+ "Set a breakpoint for all functions matching REGEXP.");
+
+ /* Initialize the one built-in type that isn't language dependent... */
+ builtin_type_error = init_type (TYPE_CODE_ERROR, 0, 0,
+ "<unknown type>", (struct objfile *) NULL);
+}
diff --git a/contrib/gdb/gdb/symtab.h b/contrib/gdb/gdb/symtab.h
new file mode 100644
index 0000000..274d198
--- /dev/null
+++ b/contrib/gdb/gdb/symtab.h
@@ -0,0 +1,1222 @@
+/* Symbol table definitions for GDB.
+ Copyright 1986, 1989, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (SYMTAB_H)
+#define SYMTAB_H 1
+
+/* Some definitions and declarations to go with use of obstacks. */
+
+#include "obstack.h"
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+#include "bcache.h"
+
+/* 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.
+
+ These fields are ordered to encourage good packing, since we frequently
+ have tens or hundreds of thousands of these. */
+
+struct general_symbol_info
+{
+ /* Name of the symbol. This is a required field. Storage for the name is
+ allocated on the psymbol_obstack or symbol_obstack for the associated
+ objfile. */
+
+ char *name;
+
+ /* Value of the symbol. Which member of this union to use, and what
+ it means, depends on what kind of symbol this is and its
+ SYMBOL_CLASS. See comments there for more details. All of these
+ are in host byte order (though what they point to might be in
+ target byte order, e.g. LOC_CONST_BYTES). */
+
+ union
+ {
+ /* 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;
+
+ char *bytes;
+
+ CORE_ADDR address;
+
+ /* for opaque typedef struct chain */
+
+ struct symbol *chain;
+ }
+ value;
+
+ /* Since one and only one language can apply, wrap the language specific
+ information inside a union. */
+
+ union
+ {
+ struct cplus_specific /* For C++ */
+ {
+ char *demangled_name;
+ } cplus_specific;
+ struct chill_specific /* For Chill */
+ {
+ char *demangled_name;
+ } 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.
+ Disclaimer: currently this is just used for xcoff, so don't
+ expect all symbol-reading code to set it correctly (the ELF code
+ also tries to set it correctly). */
+
+ short section;
+};
+
+#define SYMBOL_NAME(symbol) (symbol)->ginfo.name
+#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
+#define SYMBOL_VALUE_CHAIN(symbol) (symbol)->ginfo.value.chain
+#define SYMBOL_LANGUAGE(symbol) (symbol)->ginfo.language
+#define SYMBOL_SECTION(symbol) (symbol)->ginfo.section
+
+#define SYMBOL_CPLUS_DEMANGLED_NAME(symbol) \
+ (symbol)->ginfo.language_specific.cplus_specific.demangled_name
+
+/* Macro that initializes the language dependent portion of a symbol
+ depending upon the language for the symbol. */
+
+#define SYMBOL_INIT_LANGUAGE_SPECIFIC(symbol,language) \
+ do { \
+ SYMBOL_LANGUAGE (symbol) = language; \
+ if (SYMBOL_LANGUAGE (symbol) == language_cplus) \
+ { \
+ SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ else if (SYMBOL_LANGUAGE (symbol) == language_chill) \
+ { \
+ SYMBOL_CHILL_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ else \
+ { \
+ memset (&(symbol)->ginfo.language_specific, 0, \
+ sizeof ((symbol)->ginfo.language_specific)); \
+ } \
+ } while (0)
+
+/* Macro that attempts to initialize the demangled name for a symbol,
+ based on the language of that symbol. If the language is set to
+ language_auto, it will attempt to find any demangling algorithm
+ that works and then set the language appropriately. If no demangling
+ of any kind is found, the language is set back to language_unknown,
+ so we can avoid doing this work again the next time we encounter
+ the symbol. Any required space to store the name is obtained from the
+ specified obstack. */
+
+#define SYMBOL_INIT_DEMANGLED_NAME(symbol,obstack) \
+ do { \
+ char *demangled = NULL; \
+ if (SYMBOL_LANGUAGE (symbol) == language_cplus \
+ || SYMBOL_LANGUAGE (symbol) == language_auto) \
+ { \
+ demangled = \
+ cplus_demangle (SYMBOL_NAME (symbol), DMGL_PARAMS | DMGL_ANSI);\
+ if (demangled != NULL) \
+ { \
+ SYMBOL_LANGUAGE (symbol) = language_cplus; \
+ SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = \
+ obsavestring (demangled, strlen (demangled), (obstack)); \
+ free (demangled); \
+ } \
+ else \
+ { \
+ SYMBOL_CPLUS_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ } \
+ if (demangled == NULL \
+ && (SYMBOL_LANGUAGE (symbol) == language_chill \
+ || SYMBOL_LANGUAGE (symbol) == language_auto)) \
+ { \
+ demangled = \
+ chill_demangle (SYMBOL_NAME (symbol)); \
+ if (demangled != NULL) \
+ { \
+ SYMBOL_LANGUAGE (symbol) = language_chill; \
+ SYMBOL_CHILL_DEMANGLED_NAME (symbol) = \
+ obsavestring (demangled, strlen (demangled), (obstack)); \
+ free (demangled); \
+ } \
+ else \
+ { \
+ SYMBOL_CHILL_DEMANGLED_NAME (symbol) = NULL; \
+ } \
+ } \
+ if (SYMBOL_LANGUAGE (symbol) == language_auto) \
+ { \
+ SYMBOL_LANGUAGE (symbol) = language_unknown; \
+ } \
+ } while (0)
+
+/* Macro that returns the demangled name for a symbol based on the language
+ for that symbol. If no demangled name exists, returns NULL. */
+
+#define SYMBOL_DEMANGLED_NAME(symbol) \
+ (SYMBOL_LANGUAGE (symbol) == language_cplus \
+ ? SYMBOL_CPLUS_DEMANGLED_NAME (symbol) \
+ : (SYMBOL_LANGUAGE (symbol) == language_chill \
+ ? SYMBOL_CHILL_DEMANGLED_NAME (symbol) \
+ : NULL))
+
+#define SYMBOL_CHILL_DEMANGLED_NAME(symbol) \
+ (symbol)->ginfo.language_specific.chill_specific.demangled_name
+
+/* Macro that returns the "natural source name" of a symbol. In C++ this is
+ the "demangled" form of the name if demangle is on and the "mangled" form
+ of the name if demangle is off. In other languages this is just the
+ symbol name. The result should never be NULL. */
+
+#define SYMBOL_SOURCE_NAME(symbol) \
+ (demangle && SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ ? SYMBOL_DEMANGLED_NAME (symbol) \
+ : SYMBOL_NAME (symbol))
+
+/* Macro that returns the "natural assembly name" of a symbol. In C++ this is
+ the "mangled" form of the name if demangle is off, or if demangle is on and
+ asm_demangle is off. Otherwise if asm_demangle is on it is the "demangled"
+ form. In other languages this is just the symbol name. The result should
+ never be NULL. */
+
+#define SYMBOL_LINKAGE_NAME(symbol) \
+ (demangle && asm_demangle && SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ ? SYMBOL_DEMANGLED_NAME (symbol) \
+ : SYMBOL_NAME (symbol))
+
+/* 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
+ match a C++ encoded name, so that "foo::bar(int,long)" is the same as
+ "foo :: bar (int, long)".
+ Evaluates to zero if the match fails, or nonzero if it succeeds. */
+
+#define SYMBOL_MATCHES_NAME(symbol, name) \
+ (STREQ (SYMBOL_NAME (symbol), (name)) \
+ || (SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ && strcmp_iw (SYMBOL_DEMANGLED_NAME (symbol), (name)) == 0))
+
+/* Macro that tests a symbol for an re-match against the last compiled regular
+ expression. First test the unencoded name, then look for and test a C++
+ encoded name if it exists.
+ Evaluates to zero if the match fails, or nonzero if it succeeds. */
+
+#define SYMBOL_MATCHES_REGEXP(symbol) \
+ (re_exec (SYMBOL_NAME (symbol)) != 0 \
+ || (SYMBOL_DEMANGLED_NAME (symbol) != NULL \
+ && re_exec (SYMBOL_DEMANGLED_NAME (symbol)) != 0))
+
+/* Define a simple structure used to hold some very basic information about
+ all defined global symbols (text, data, bss, abs, etc). The only required
+ information is the general_symbol_info.
+
+ In many cases, even if a file was compiled with no special options for
+ debugging at all, as long as was not stripped it will contain sufficient
+ information to build a useful minimal symbol table using this structure.
+ Even when a file contains enough debugging information to build a full
+ symbol table, these minimal symbols are still useful for quickly mapping
+ between names and addresses, and vice versa. They are also sometimes
+ used to figure out what full symbol table entries need to be read in. */
+
+struct minimal_symbol
+{
+
+ /* The general symbol info required for all types of symbols.
+
+ The SYMBOL_VALUE_ADDRESS contains the address that this symbol
+ corresponds to. */
+
+ struct general_symbol_info ginfo;
+
+ /* The info field is available for caching machine-specific information that
+ The AMD 29000 tdep.c uses it to remember things it has decoded from the
+ instructions in the function header, so it doesn't have to rederive the
+ info constantly (over a serial line). It is initialized to zero and
+ stays that way until target-dependent code sets it. Storage for any data
+ pointed to by this field should be allocated on the symbol_obstack for
+ the associated objfile. The type would be "void *" except for reasons
+ of compatibility with older compilers. This field is optional. */
+
+ char *info;
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+ /* Which source file is this symbol in? Only relevant for mst_file_*. */
+ char *filename;
+#endif
+
+ /* Classification types for this symbol. These should be taken as "advisory
+ only", since if gdb can't easily figure out a classification it simply
+ selects mst_unknown. It may also have to guess when it can't figure out
+ which is a better match between two types (mst_data versus mst_bss) for
+ example. Since the minimal symbol info is sometimes derived from the
+ BFD library's view of a file, we need to live with what information bfd
+ supplies. */
+
+ enum minimal_symbol_type
+ {
+ mst_unknown = 0, /* Unknown type, the default */
+ mst_text, /* Generally executable instructions */
+ 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 BYTE_BITFIELD;
+
+};
+
+#define MSYMBOL_INFO(msymbol) (msymbol)->info
+#define MSYMBOL_TYPE(msymbol) (msymbol)->type
+
+
+/* All of the name-scope contours of the program
+ are represented by `struct block' objects.
+ All of these objects are pointed to by the blockvector.
+
+ Each block represents one name scope.
+ Each lexical context has its own block.
+
+ The blockvector begins with some special blocks.
+ The GLOBAL_BLOCK contains all the symbols defined in this compilation
+ whose scope is the entire program linked together.
+ The STATIC_BLOCK contains all the symbols whose scope is the
+ entire compilation excluding other separate compilations.
+ Blocks starting with the FIRST_LOCAL_BLOCK are not special.
+
+ Each block records a range of core addresses for the code that
+ is in the scope of the block. The STATIC_BLOCK and GLOBAL_BLOCK
+ give, for the range of code, the entire range of code produced
+ by the compilation that the symbol segment belongs to.
+
+ The blocks appear in the blockvector
+ in order of increasing starting-address,
+ and, within that, in order of decreasing ending-address.
+
+ This implies that within the body of one function
+ the blocks appear in the order of a depth-first tree walk. */
+
+struct blockvector
+{
+ /* Number of blocks in the list. */
+ int nblocks;
+ /* The blocks themselves. */
+ struct block *block[1];
+};
+
+#define BLOCKVECTOR_NBLOCKS(blocklist) (blocklist)->nblocks
+#define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
+
+/* Special block numbers */
+
+#define GLOBAL_BLOCK 0
+#define STATIC_BLOCK 1
+#define FIRST_LOCAL_BLOCK 2
+
+struct block
+{
+
+ /* Addresses in the executable code that are in this block. */
+
+ CORE_ADDR startaddr;
+ CORE_ADDR endaddr;
+
+ /* The symbol that names this block, if the block is the body of a
+ function; otherwise, zero. */
+
+ struct symbol *function;
+
+ /* The `struct block' for the containing block, or 0 if none.
+
+ The superblock of a top-level local block (i.e. a function in the
+ case of C) is the STATIC_BLOCK. The superblock of the
+ STATIC_BLOCK is the GLOBAL_BLOCK. */
+
+ struct block *superblock;
+
+ /* Version of GCC used to compile the function corresponding
+ to this block, or 0 if not compiled with GCC. When possible,
+ GCC should be compatible with the native compiler, or if that
+ is not feasible, the differences should be fixed during symbol
+ reading. As of 16 Apr 93, this flag is never used to distinguish
+ between gcc2 and the native compiler.
+
+ If there is no function corresponding to this block, this meaning
+ of this flag is undefined. */
+
+ unsigned char gcc_compile_flag;
+
+ /* Number of local symbols. */
+
+ int nsyms;
+
+ /* The symbols. If some of them are arguments, then they must be
+ in the order in which we would like to print them. */
+
+ struct symbol *sym[1];
+};
+
+#define BLOCK_START(bl) (bl)->startaddr
+#define BLOCK_END(bl) (bl)->endaddr
+#define BLOCK_NSYMS(bl) (bl)->nsyms
+#define BLOCK_SYM(bl, n) (bl)->sym[n]
+#define BLOCK_FUNCTION(bl) (bl)->function
+#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
+#define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag
+
+/* Nonzero if symbols of block BL should be sorted alphabetically.
+ Don't sort a block which corresponds to a function. If we did the
+ sorting would have to preserve the order of the symbols for the
+ arguments. */
+
+#define BLOCK_SHOULD_SORT(bl) ((bl)->nsyms >= 40 && BLOCK_FUNCTION (bl) == NULL)
+
+
+/* Represent one symbol name; a variable, constant, function or typedef. */
+
+/* Different name spaces for symbols. Looking up a symbol specifies a
+ namespace and ignores symbol definitions in other name spaces. */
+
+typedef enum
+{
+ /* UNDEF_NAMESPACE is used when a namespace has not been discovered or
+ none of the following apply. This usually indicates an error either
+ in the symbol information or in gdb's handling of symbols. */
+
+ UNDEF_NAMESPACE,
+
+ /* VAR_NAMESPACE is the usual namespace. In C, this contains variables,
+ function names, typedef names and enum type values. */
+
+ VAR_NAMESPACE,
+
+ /* STRUCT_NAMESPACE is used in C to hold struct, union and enum type names.
+ Thus, if `struct foo' is used in a C program, it produces a symbol named
+ `foo' in the STRUCT_NAMESPACE. */
+
+ STRUCT_NAMESPACE,
+
+ /* LABEL_NAMESPACE may be used for names of labels (for gotos);
+ currently it is not used and labels are not recorded at all. */
+
+ LABEL_NAMESPACE
+} namespace_enum;
+
+/* An address-class says where to find the value of a symbol. */
+
+enum address_class
+{
+ /* Not used; catches errors */
+
+ LOC_UNDEF,
+
+ /* Value is constant int SYMBOL_VALUE, host byteorder */
+
+ LOC_CONST,
+
+ /* Value is at fixed address SYMBOL_VALUE_ADDRESS */
+
+ LOC_STATIC,
+
+ /* Value is in register. SYMBOL_VALUE is the register number. */
+
+ LOC_REGISTER,
+
+ /* It's an argument; the value is at SYMBOL_VALUE offset in arglist. */
+
+ LOC_ARG,
+
+ /* Value address is at SYMBOL_VALUE offset in arglist. */
+
+ LOC_REF_ARG,
+
+ /* Value is in register number SYMBOL_VALUE. Just like LOC_REGISTER
+ except this is an argument. Probably the cleaner way to handle
+ this would be to separate address_class (which would include
+ separate ARG and LOCAL to deal with FRAME_ARGS_ADDRESS versus
+ FRAME_LOCALS_ADDRESS), and an is_argument flag.
+
+ For some symbol formats (stabs, for some compilers at least),
+ the compiler generates two symbols, an argument and a register.
+ In some cases we combine them to a single LOC_REGPARM in symbol
+ reading, but currently not for all cases (e.g. it's passed on the
+ stack and then loaded into a register). */
+
+ LOC_REGPARM,
+
+ /* Value is in specified register. Just like LOC_REGPARM except the
+ register holds the address of the argument instead of the argument
+ itself. This is currently used for the passing of structs and unions
+ on sparc and hppa. It is also used for call by reference where the
+ address is in a register, at least by mipsread.c. */
+
+ LOC_REGPARM_ADDR,
+
+ /* Value is a local variable at SYMBOL_VALUE offset in stack frame. */
+
+ LOC_LOCAL,
+
+ /* Value not used; definition in SYMBOL_TYPE. Symbols in the namespace
+ STRUCT_NAMESPACE all have this class. */
+
+ LOC_TYPEDEF,
+
+ /* Value is address SYMBOL_VALUE_ADDRESS in the code */
+
+ LOC_LABEL,
+
+ /* In a symbol table, value is SYMBOL_BLOCK_VALUE of a `struct block'.
+ In a partial symbol table, SYMBOL_VALUE_ADDRESS is the start address
+ of the block. Function names have this class. */
+
+ LOC_BLOCK,
+
+ /* Value is a constant byte-sequence pointed to by SYMBOL_VALUE_BYTES, in
+ target byte order. */
+
+ LOC_CONST_BYTES,
+
+ /* Value is arg at SYMBOL_VALUE offset in stack frame. Differs from
+ LOC_LOCAL in that symbol is an argument; differs from LOC_ARG in
+ that we find it in the frame (FRAME_LOCALS_ADDRESS), not in the
+ arglist (FRAME_ARGS_ADDRESS). Added for i960, which passes args
+ in regs then copies to frame. */
+
+ LOC_LOCAL_ARG,
+
+ /* Value is at SYMBOL_VALUE offset from the current value of
+ register number SYMBOL_BASEREG. This exists mainly for the same
+ things that LOC_LOCAL and LOC_ARG do; but we need to do this
+ instead because on 88k DWARF gives us the offset from the
+ frame/stack pointer, rather than the offset from the "canonical
+ frame address" used by COFF, stabs, etc., and we don't know how
+ to convert between these until we start examining prologues.
+
+ Note that LOC_BASEREG is much less general than a DWARF expression.
+ We don't need the generality (at least not yet), and storing a general
+ DWARF expression would presumably take up more space than the existing
+ scheme. */
+
+ LOC_BASEREG,
+
+ /* Same as LOC_BASEREG but it is an argument. */
+
+ LOC_BASEREG_ARG,
+
+ /* Value is at fixed address, but the address of the variable has
+ to be determined from the minimal symbol table whenever the
+ variable is referenced.
+ This happens if debugging information for a global symbol is
+ emitted and the corresponding minimal symbol is defined
+ in another object file or runtime common storage.
+ The linker might even remove the minimal symbol if the global
+ symbol is never referenced, in which case the symbol remains
+ unresolved. */
+
+ LOC_UNRESOLVED,
+
+ /* The variable does not actually exist in the program.
+ The value is ignored. */
+
+ LOC_OPTIMIZED_OUT
+};
+
+struct symbol
+{
+
+ /* The general symbol info required for all types of symbols. */
+
+ struct general_symbol_info ginfo;
+
+ /* Data type of value */
+
+ struct type *type;
+
+ /* Name space code. */
+
+ namespace_enum namespace BYTE_BITFIELD;
+
+ /* Address class */
+
+ enum address_class aclass 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? */
+
+ unsigned short line;
+
+ /* Some symbols require an additional value to be recorded on a per-
+ symbol basis. Stash those values here. */
+
+ union
+ {
+ /* Used by LOC_BASEREG and LOC_BASEREG_ARG. */
+ short basereg;
+ }
+ aux_value;
+};
+
+#define SYMBOL_NAMESPACE(symbol) (symbol)->namespace
+#define SYMBOL_CLASS(symbol) (symbol)->aclass
+#define SYMBOL_TYPE(symbol) (symbol)->type
+#define SYMBOL_LINE(symbol) (symbol)->line
+#define SYMBOL_BASEREG(symbol) (symbol)->aux_value.basereg
+
+/* A partial_symbol records the name, namespace, and address class of
+ symbols whose types we have not parsed yet. For functions, it also
+ contains their memory address, so we can find them from a PC value.
+ Each partial_symbol sits in a partial_symtab, all of which are chained
+ on a partial symtab list and which points to the corresponding
+ normal symtab once the partial_symtab has been referenced. */
+
+struct partial_symbol
+{
+
+ /* The general symbol info required for all types of symbols. */
+
+ struct general_symbol_info ginfo;
+
+ /* Name space code. */
+
+ namespace_enum namespace BYTE_BITFIELD;
+
+ /* Address class (for info_symbols) */
+
+ enum address_class aclass BYTE_BITFIELD;
+
+};
+
+#define PSYMBOL_NAMESPACE(psymbol) (psymbol)->namespace
+#define PSYMBOL_CLASS(psymbol) (psymbol)->aclass
+
+
+/* Source-file information. This describes the relation between source files,
+ ine numbers and addresses in the program text. */
+
+struct sourcevector
+{
+ int length; /* Number of source files described */
+ struct source *source[1]; /* Descriptions of the files */
+};
+
+/* Each item represents a line-->pc (or the reverse) mapping. This is
+ somewhat more wasteful of space than one might wish, but since only
+ the files which are actually debugged are read in to core, we don't
+ waste much space. */
+
+struct linetable_entry
+{
+ int line;
+ CORE_ADDR pc;
+};
+
+/* The order of entries in the linetable is significant. They should
+ be sorted by increasing values of the pc field. If there is more than
+ one entry for a given pc, then I'm not sure what should happen (and
+ I not sure whether we currently handle it the best way).
+
+ Example: a C for statement generally looks like this
+
+ 10 0x100 - for the init/test part of a for stmt.
+ 20 0x200
+ 30 0x300
+ 10 0x400 - for the increment part of a for stmt.
+
+ */
+
+struct linetable
+{
+ int nitems;
+
+ /* Actually NITEMS elements. If you don't like this use of the
+ `struct hack', you can shove it up your ANSI (seriously, if the
+ committee tells us how to do it, we can probably go along). */
+ struct linetable_entry item[1];
+};
+
+/* All the information on one source file. */
+
+struct source
+{
+ char *name; /* Name of file */
+ struct linetable contents;
+};
+
+/* How to relocate the symbols from each section in a symbol file.
+ Each struct contains an array of offsets.
+ The ordering and meaning of the offsets is file-type-dependent;
+ typically it is indexed by section numbers or symbol types or
+ something like that.
+
+ To give us flexibility in changing the internal representation
+ of these offsets, the ANOFFSET macro must be used to insert and
+ extract offset values in the struct. */
+
+struct section_offsets
+ {
+ CORE_ADDR offsets[1]; /* As many as needed. */
+ };
+
+#define ANOFFSET(secoff, whichone) (secoff->offsets[whichone])
+
+/* Each source file or header is represented by a struct symtab.
+ These objects are chained through the `next' field. */
+
+struct symtab
+ {
+
+ /* Chain of all existing symtabs. */
+
+ struct symtab *next;
+
+ /* List of all symbol scope blocks for this symtab. May be shared
+ between different symtabs (and normally is for all the symtabs
+ in a given compilation unit). */
+
+ struct blockvector *blockvector;
+
+ /* Table mapping core addresses to line numbers for this file.
+ Can be NULL if none. Never shared between different symtabs. */
+
+ struct linetable *linetable;
+
+ /* Section in objfile->section_offsets for the blockvector and
+ the linetable. Probably always SECT_OFF_TEXT. */
+
+ int block_line_section;
+
+ /* If several symtabs share a blockvector, exactly one of them
+ should be designed the primary, so that the blockvector
+ is relocated exactly once by objfile_relocate. */
+
+ int primary;
+
+ /* Name of this source file. */
+
+ char *filename;
+
+ /* Directory in which it was compiled, or NULL if we don't know. */
+
+ char *dirname;
+
+ /* This component says how to free the data we point to:
+ free_contents => do a tree walk and free each object.
+ free_nothing => do nothing; some other symtab will free
+ the data this one uses.
+ free_linetable => free just the linetable. FIXME: Is this redundant
+ with the primary field? */
+
+ enum free_code
+ {
+ free_nothing, free_contents, free_linetable
+ }
+ free_code;
+
+ /* Pointer to one block of storage to be freed, if nonzero. */
+ /* This is IN ADDITION to the action indicated by free_code. */
+
+ char *free_ptr;
+
+ /* Total number of lines found in source file. */
+
+ int nlines;
+
+ /* line_charpos[N] is the position of the (N-1)th line of the
+ source file. "position" means something we can lseek() to; it
+ is not guaranteed to be useful any other way. */
+
+ int *line_charpos;
+
+ /* Language of this source file. */
+
+ enum language language;
+
+ /* String of version information. May be zero. */
+
+ char *version;
+
+ /* Full name of file as found by searching the source path.
+ NULL if not yet known. */
+
+ char *fullname;
+
+ /* Object file from which this symbol information was read. */
+
+ struct objfile *objfile;
+
+ /* Anything extra for this symtab. This is for target machines
+ with special debugging info of some sort (which cannot just
+ be represented in a normal symtab). */
+
+#if defined (EXTRA_SYMTAB_INFO)
+ EXTRA_SYMTAB_INFO
+#endif
+
+ };
+
+#define BLOCKVECTOR(symtab) (symtab)->blockvector
+#define LINETABLE(symtab) (symtab)->linetable
+
+
+/* Each source file that has not been fully read in is represented by
+ a partial_symtab. This contains the information on where in the
+ executable the debugging symbols for a specific file are, and a
+ list of names of global symbols which are located in this file.
+ They are all chained on partial symtab lists.
+
+ Even after the source file has been read into a symtab, the
+ partial_symtab remains around. They are allocated on an obstack,
+ psymbol_obstack. FIXME, this is bad for dynamic linking or VxWorks-
+ style execution of a bunch of .o's. */
+
+struct partial_symtab
+{
+
+ /* Chain of all existing partial symtabs. */
+
+ struct partial_symtab *next;
+
+ /* Name of the source file which this partial_symtab defines */
+
+ char *filename;
+
+ /* Information about the object file from which symbols should be read. */
+
+ struct objfile *objfile;
+
+ /* Set of relocation offsets to apply to each section. */
+
+ struct section_offsets *section_offsets;
+
+ /* Range of text addresses covered by this file; texthigh is the
+ beginning of the next section. */
+
+ CORE_ADDR textlow;
+ CORE_ADDR texthigh;
+
+ /* Array of pointers to all of the partial_symtab's which this one
+ depends on. Since this array can only be set to previous or
+ the current (?) psymtab, this dependency tree is guaranteed not
+ to have any loops. "depends on" means that symbols must be read
+ for the dependencies before being read for this psymtab; this is
+ for type references in stabs, where if foo.c includes foo.h, declarations
+ in foo.h may use type numbers defined in foo.c. For other debugging
+ formats there may be no need to use dependencies. */
+
+ struct partial_symtab **dependencies;
+
+ int number_of_dependencies;
+
+ /* Global symbol list. This list will be sorted after readin to
+ improve access. Binary search will be the usual method of
+ finding a symbol within it. globals_offset is an integer offset
+ within global_psymbols[]. */
+
+ int globals_offset;
+ int n_global_syms;
+
+ /* Static symbol list. This list will *not* be sorted after readin;
+ to find a symbol in it, exhaustive search must be used. This is
+ reasonable because searches through this list will eventually
+ lead to either the read in of a files symbols for real (assumed
+ to take a *lot* of time; check) or an error (and we don't care
+ how long errors take). This is an offset and size within
+ static_psymbols[]. */
+
+ int statics_offset;
+ int n_static_syms;
+
+ /* Pointer to symtab eventually allocated for this source file, 0 if
+ !readin or if we haven't looked for the symtab after it was readin. */
+
+ struct symtab *symtab;
+
+ /* Pointer to function which will read in the symtab corresponding to
+ this psymtab. */
+
+ void (*read_symtab) PARAMS ((struct partial_symtab *));
+
+ /* Information that lets read_symtab() locate the part of the symbol table
+ that this psymtab corresponds to. This information is private to the
+ format-dependent symbol reading routines. For further detail examine
+ the various symbol reading modules. Should really be (void *) but is
+ (char *) as with other such gdb variables. (FIXME) */
+
+ char *read_symtab_private;
+
+ /* Non-zero if the symtab corresponding to this psymtab has been readin */
+
+ unsigned char readin;
+};
+
+/* A fast way to get from a psymtab to its symtab (after the first time). */
+#define PSYMTAB_TO_SYMTAB(pst) \
+ ((pst) -> symtab != NULL ? (pst) -> symtab : psymtab_to_symtab (pst))
+
+
+/* The virtual function table is now an array of structures which have the
+ form { int16 offset, delta; void *pfn; }.
+
+ In normal virtual function tables, OFFSET is unused.
+ DELTA is the amount which is added to the apparent object's base
+ address in order to point to the actual object to which the
+ virtual function should be applied.
+ PFN is a pointer to the virtual function.
+
+ Note that this macro is g++ specific (FIXME). */
+
+#define VTBL_FNADDR_OFFSET 2
+
+/* Macro that yields non-zero value iff NAME is the prefix for C++ operator
+ names. If you leave out the parenthesis here you will lose!
+ Currently 'o' 'p' CPLUS_MARKER is used for both the symbol in the
+ symbol-file and the names in gdb's symbol table.
+ Note that this macro is g++ specific (FIXME). */
+
+#define OPNAME_PREFIX_P(NAME) \
+ ((NAME)[0] == 'o' && (NAME)[1] == 'p' && is_cplus_marker ((NAME)[2]))
+
+/* Macro that yields non-zero value iff NAME is the prefix for C++ vtbl
+ 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)[0] == '_' \
+ && (((NAME)[1] == 'V' && (NAME)[2] == 'T') \
+ || ((NAME)[1] == 'v' && (NAME)[2] == 't')) \
+ && is_cplus_marker ((NAME)[3]))
+
+/* Macro that yields non-zero value iff NAME is the prefix for C++ destructor
+ names. Note that this macro is g++ specific (FIXME). */
+
+#define DESTRUCTOR_PREFIX_P(NAME) \
+ ((NAME)[0] == '_' && is_cplus_marker ((NAME)[1]) && (NAME)[2] == '_')
+
+
+/* External variables and functions for the objects described above. */
+
+/* This symtab variable specifies the current file for printing source lines */
+
+extern struct symtab *current_source_symtab;
+
+/* This is the next line to print for listing source lines. */
+
+extern int current_source_line;
+
+/* See the comment in symfile.c about how current_objfile is used. */
+
+extern struct objfile *current_objfile;
+
+/* True if we are nested inside psymtab_to_symtab. */
+
+extern int currently_reading_symtab;
+
+/* From utils.c. */
+extern int demangle;
+extern int asm_demangle;
+
+extern struct symtab *
+lookup_symtab PARAMS ((char *));
+
+extern struct symbol *
+lookup_symbol PARAMS ((const char *, const struct block *,
+ const namespace_enum, int *, struct symtab **));
+
+extern struct symbol *
+lookup_block_symbol PARAMS ((const struct block *, const char *,
+ const namespace_enum));
+
+extern struct type *
+lookup_struct PARAMS ((char *, struct block *));
+
+extern struct type *
+lookup_union PARAMS ((char *, struct block *));
+
+extern struct type *
+lookup_enum PARAMS ((char *, struct block *));
+
+extern struct symbol *
+block_function PARAMS ((struct block *));
+
+extern struct symbol *
+find_pc_function PARAMS ((CORE_ADDR));
+
+extern int find_pc_partial_function
+ PARAMS ((CORE_ADDR, char **, CORE_ADDR *, CORE_ADDR *));
+
+extern void
+clear_pc_function_cache PARAMS ((void));
+
+extern struct partial_symtab *
+lookup_partial_symtab PARAMS ((char *));
+
+extern struct partial_symtab *
+find_pc_psymtab PARAMS ((CORE_ADDR));
+
+extern struct symtab *
+find_pc_symtab PARAMS ((CORE_ADDR));
+
+extern struct partial_symbol *
+find_pc_psymbol PARAMS ((struct partial_symtab *, CORE_ADDR));
+
+extern int
+find_pc_line_pc_range PARAMS ((CORE_ADDR, CORE_ADDR *, CORE_ADDR *));
+
+extern int
+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,
+ struct objfile *));
+
+extern struct minimal_symbol *prim_record_minimal_symbol_and_info
+ PARAMS ((const char *, CORE_ADDR,
+ enum minimal_symbol_type,
+ char *info, int section,
+ struct objfile *));
+
+#ifdef SOFUN_ADDRESS_MAYBE_MISSING
+extern CORE_ADDR find_stab_function_addr PARAMS ((char *,
+ struct partial_symtab *,
+ struct objfile *));
+#endif
+
+extern struct minimal_symbol *
+lookup_minimal_symbol PARAMS ((const char *, const char *, struct objfile *));
+
+extern struct minimal_symbol *
+lookup_minimal_symbol_text PARAMS ((const char *, const char *, struct objfile *));
+
+struct minimal_symbol *
+lookup_minimal_symbol_solib_trampoline PARAMS ((const char *,
+ 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));
+
+extern void
+discard_minimal_symbols PARAMS ((int));
+
+extern void
+install_minimal_symbols PARAMS ((struct objfile *));
+
+/* Sort all the minimal symbols in OBJFILE. */
+
+extern void msymbols_sort PARAMS ((struct objfile *objfile));
+
+struct symtab_and_line
+{
+ struct symtab *symtab;
+
+ /* Line number. Line numbers start at 1 and proceed through symtab->nlines.
+ 0 is never a valid line number; it is used to indicate that line number
+ information is not available. */
+ int line;
+
+ CORE_ADDR pc;
+ CORE_ADDR end;
+};
+
+struct symtabs_and_lines
+{
+ struct symtab_and_line *sals;
+ int nelts;
+};
+
+/* Given a pc value, return line number it is in. Second arg nonzero means
+ if pc is on the boundary use the previous statement's line number. */
+
+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_and_line,
+ CORE_ADDR *, CORE_ADDR *));
+
+extern void
+resolve_sal_pc PARAMS ((struct symtab_and_line *));
+
+/* Given a string, return the line specified by it. For commands like "list"
+ and "breakpoint". */
+
+extern struct symtabs_and_lines
+decode_line_spec PARAMS ((char *, int));
+
+extern struct symtabs_and_lines
+decode_line_spec_1 PARAMS ((char *, int));
+
+extern struct symtabs_and_lines
+decode_line_1 PARAMS ((char **, int, struct symtab *, int, char ***));
+
+/* Symmisc.c */
+
+#if MAINTENANCE_CMDS
+
+void
+maintenance_print_symbols PARAMS ((char *, int));
+
+void
+maintenance_print_psymbols PARAMS ((char *, int));
+
+void
+maintenance_print_msymbols PARAMS ((char *, int));
+
+void
+maintenance_print_objfiles PARAMS ((char *, int));
+
+void
+maintenance_check_symtabs PARAMS ((char *, int));
+
+#endif
+
+extern void
+free_symtab PARAMS ((struct symtab *));
+
+/* Symbol-reading stuff in symfile.c and solib.c. */
+
+extern struct symtab *
+psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+extern void
+clear_solib PARAMS ((void));
+
+extern struct objfile *
+symbol_file_add PARAMS ((char *, int, CORE_ADDR, int, int, int));
+
+/* source.c */
+
+extern int
+identify_source_line PARAMS ((struct symtab *, int, int, CORE_ADDR));
+
+extern void
+print_source_lines PARAMS ((struct symtab *, int, int, int));
+
+extern void
+forget_cached_source_info PARAMS ((void));
+
+extern void
+select_source_symtab PARAMS ((struct symtab *));
+
+extern char **make_symbol_completion_list PARAMS ((char *, char *));
+
+/* symtab.c */
+
+extern struct partial_symtab *
+find_main_psymtab PARAMS ((void));
+
+/* blockframe.c */
+
+extern struct blockvector *
+blockvector_for_pc PARAMS ((CORE_ADDR, int *));
+
+/* symfile.c */
+
+extern void
+clear_symtab_users PARAMS ((void));
+
+extern enum language
+deduce_language_from_filename PARAMS ((char *));
+
+/* symtab.c */
+
+extern int
+in_prologue PARAMS ((CORE_ADDR pc, CORE_ADDR func_start));
+
+#endif /* !defined(SYMTAB_H) */
diff --git a/contrib/gdb/gdb/target.c b/contrib/gdb/gdb/target.c
new file mode 100644
index 0000000..fc0dfd9
--- /dev/null
+++ b/contrib/gdb/gdb/target.c
@@ -0,0 +1,1858 @@
+/* Select target systems and architectures at runtime for GDB.
+ Copyright 1990, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include <errno.h>
+#include <ctype.h>
+#include "gdb_string.h"
+#include "target.h"
+#include "gdbcmd.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "bfd.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "wait.h"
+#include <signal.h>
+
+extern int errno;
+
+static void
+target_info PARAMS ((char *, int));
+
+static void
+cleanup_target PARAMS ((struct target_ops *));
+
+static void
+maybe_kill_then_create_inferior PARAMS ((char *, char *, char **));
+
+static void
+maybe_kill_then_attach PARAMS ((char *, int));
+
+static void
+kill_or_be_killed PARAMS ((int));
+
+static void
+default_terminal_info PARAMS ((char *, int));
+
+static int
+nosymbol PARAMS ((char *, CORE_ADDR *));
+
+static void
+tcomplain PARAMS ((void));
+
+static int
+nomemory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static int
+return_zero PARAMS ((void));
+
+static void
+ignore PARAMS ((void));
+
+static void
+target_command PARAMS ((char *, int));
+
+static struct target_ops *
+find_default_run_target PARAMS ((char *));
+
+/* Pointer to array of target architecture structures; the size of the
+ array; the current index into the array; the allocated size of the
+ array. */
+struct target_ops **target_structs;
+unsigned target_struct_size;
+unsigned target_struct_index;
+unsigned target_struct_allocsize;
+#define DEFAULT_ALLOCSIZE 10
+
+/* The initial current target, so that there is always a semi-valid
+ current target. */
+
+struct target_ops dummy_target = {
+ "None", /* to_shortname */
+ "None", /* to_longname */
+ "", /* to_doc */
+ 0, /* to_open */
+ 0, /* to_close */
+ find_default_attach, /* to_attach */
+ 0, /* to_detach */
+ 0, /* to_resume */
+ 0, /* to_wait */
+ 0, /* to_fetch_registers */
+ 0, /* to_store_registers */
+ 0, /* to_prepare_to_store */
+ 0, /* to_xfer_memory */
+ 0, /* to_files_info */
+ 0, /* to_insert_breakpoint */
+ 0, /* to_remove_breakpoint */
+ 0, /* to_terminal_init */
+ 0, /* to_terminal_inferior */
+ 0, /* to_terminal_ours_for_output */
+ 0, /* to_terminal_ours */
+ 0, /* to_terminal_info */
+ 0, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ find_default_create_inferior, /* to_create_inferior */
+ 0, /* to_mourn_inferior */
+ 0, /* to_can_run */
+ 0, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ 0, /* to_stop */
+ dummy_stratum, /* to_stratum */
+ 0, /* to_next */
+ 0, /* to_next */
+ 0, /* to_has_all_memory */
+ 0, /* to_has_memory */
+ 0, /* to_has_registers */
+ 0, /* to_has_execution */
+ 0, /* to_sections */
+ 0, /* to_sections_end */
+ OPS_MAGIC, /* to_magic */
+};
+
+/* Top of target stack. */
+
+struct target_stack_item *target_stack;
+
+/* The target structure we are currently using to talk to a process
+ or file or whatever "inferior" we have. */
+
+struct target_ops current_target;
+
+/* Command list for target. */
+
+static struct cmd_list_element *targetlist = NULL;
+
+/* Nonzero if we are debugging an attached outside process
+ rather than an inferior. */
+
+int attach_flag;
+
+#ifdef MAINTENANCE_CMDS
+/* Non-zero if we want to see trace of target level stuff. */
+
+static int targetdebug = 0;
+
+static void setup_target_debug PARAMS ((void));
+
+#endif
+
+/* The user just typed 'target' without the name of a target. */
+
+/* ARGSUSED */
+static void
+target_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ fputs_filtered ("Argument required (target name). Try `help target'\n",
+ gdb_stdout);
+}
+
+/* Add a possible target architecture to the list. */
+
+void
+add_target (t)
+ struct target_ops *t;
+{
+ if (!target_structs)
+ {
+ target_struct_allocsize = DEFAULT_ALLOCSIZE;
+ target_structs = (struct target_ops **) xmalloc
+ (target_struct_allocsize * sizeof (*target_structs));
+ }
+ if (target_struct_size >= target_struct_allocsize)
+ {
+ target_struct_allocsize *= 2;
+ target_structs = (struct target_ops **)
+ xrealloc ((char *) target_structs,
+ target_struct_allocsize * sizeof (*target_structs));
+ }
+ target_structs[target_struct_size++] = t;
+/* cleanup_target (t);*/
+
+ if (targetlist == NULL)
+ add_prefix_cmd ("target", class_run, target_command,
+ "Connect to a target machine or process.\n\
+The first argument is the type or protocol of the target machine.\n\
+Remaining arguments are interpreted by the target protocol. For more\n\
+information on the arguments for a particular protocol, type\n\
+`help target ' followed by the protocol name.",
+ &targetlist, "target ", 0, &cmdlist);
+ add_cmd (t->to_shortname, no_class, t->to_open, t->to_doc, &targetlist);
+}
+
+/* Stub functions */
+
+static void
+ignore ()
+{
+}
+
+/* ARGSUSED */
+static int
+nomemory (memaddr, myaddr, len, write, t)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *t;
+{
+ errno = EIO; /* Can't read/write this location */
+ return 0; /* No bytes handled */
+}
+
+static void
+tcomplain ()
+{
+ error ("You can't do that when your target is `%s'",
+ current_target.to_shortname);
+}
+
+void
+noprocess ()
+{
+ error ("You can't do that without a process to debug");
+}
+
+/* ARGSUSED */
+static int
+nosymbol (name, addrp)
+ char *name;
+ CORE_ADDR *addrp;
+{
+ return 1; /* Symbol does not exist in target env */
+}
+
+/* ARGSUSED */
+static void
+default_terminal_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered("No saved terminal information.\n");
+}
+
+/* This is the default target_create_inferior and target_attach function.
+ If the current target is executing, it asks whether to kill it off.
+ If this function returns without calling error(), it has killed off
+ the target, and the operation should be attempted. */
+
+static void
+kill_or_be_killed (from_tty)
+ int from_tty;
+{
+ if (target_has_execution)
+ {
+ printf_unfiltered ("You are already running a program:\n");
+ target_files_info ();
+ if (query ("Kill it? ")) {
+ target_kill ();
+ if (target_has_execution)
+ error ("Killing the program did not help.");
+ return;
+ } else {
+ error ("Program not killed.");
+ }
+ }
+ tcomplain();
+}
+
+static void
+maybe_kill_then_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ kill_or_be_killed (from_tty);
+ target_attach (args, from_tty);
+}
+
+static void
+maybe_kill_then_create_inferior (exec, args, env)
+ char *exec;
+ char *args;
+ char **env;
+{
+ kill_or_be_killed (0);
+ target_create_inferior (exec, args, env);
+}
+
+/* Clean up a target struct so it no longer has any zero pointers in it.
+ We default entries, at least to stubs that print error messages. */
+
+static void
+cleanup_target (t)
+ struct target_ops *t;
+{
+
+#define de_fault(field, value) \
+ if (!t->field) t->field = value
+
+ /* FIELD DEFAULT VALUE */
+
+ de_fault (to_open, (void (*)())tcomplain);
+ de_fault (to_close, (void (*)())ignore);
+ de_fault (to_attach, maybe_kill_then_attach);
+ de_fault (to_detach, (void (*)())ignore);
+ de_fault (to_resume, (void (*)())noprocess);
+ de_fault (to_wait, (int (*)())noprocess);
+ de_fault (to_fetch_registers, (void (*)())ignore);
+ de_fault (to_store_registers, (void (*)())noprocess);
+ de_fault (to_prepare_to_store, (void (*)())noprocess);
+ de_fault (to_xfer_memory, (int (*)())nomemory);
+ de_fault (to_files_info, (void (*)())ignore);
+ de_fault (to_insert_breakpoint, memory_insert_breakpoint);
+ de_fault (to_remove_breakpoint, memory_remove_breakpoint);
+ de_fault (to_terminal_init, ignore);
+ de_fault (to_terminal_inferior, ignore);
+ de_fault (to_terminal_ours_for_output,ignore);
+ de_fault (to_terminal_ours, ignore);
+ de_fault (to_terminal_info, default_terminal_info);
+ de_fault (to_kill, (void (*)())noprocess);
+ de_fault (to_load, (void (*)())tcomplain);
+ de_fault (to_lookup_symbol, nosymbol);
+ de_fault (to_create_inferior, maybe_kill_then_create_inferior);
+ de_fault (to_mourn_inferior, (void (*)())noprocess);
+ de_fault (to_can_run, return_zero);
+ de_fault (to_notice_signals, (void (*)())ignore);
+ de_fault (to_thread_alive, (int (*)())ignore);
+ de_fault (to_stop, (void (*)())ignore);
+
+#undef de_fault
+}
+
+/* Go through the target stack from top to bottom, copying over zero entries in
+ current_target. In effect, we are doing class inheritance through the
+ pushed target vectors. */
+
+static void
+update_current_target ()
+{
+ struct target_stack_item *item;
+ struct target_ops *t;
+
+ /* First, reset current_target */
+ memset (&current_target, 0, sizeof current_target);
+
+ for (item = target_stack; item; item = item->next)
+ {
+ t = item->target_ops;
+
+#define INHERIT(FIELD, TARGET) \
+ if (!current_target.FIELD) \
+ current_target.FIELD = TARGET->FIELD
+
+ INHERIT (to_shortname, t);
+ INHERIT (to_longname, t);
+ INHERIT (to_doc, t);
+ INHERIT (to_open, t);
+ INHERIT (to_close, t);
+ INHERIT (to_attach, t);
+ INHERIT (to_detach, t);
+ INHERIT (to_resume, t);
+ INHERIT (to_wait, t);
+ INHERIT (to_fetch_registers, t);
+ INHERIT (to_store_registers, t);
+ INHERIT (to_prepare_to_store, t);
+ INHERIT (to_xfer_memory, t);
+ INHERIT (to_files_info, t);
+ INHERIT (to_insert_breakpoint, t);
+ INHERIT (to_remove_breakpoint, t);
+ INHERIT (to_terminal_init, t);
+ INHERIT (to_terminal_inferior, t);
+ INHERIT (to_terminal_ours_for_output, t);
+ INHERIT (to_terminal_ours, t);
+ INHERIT (to_terminal_info, t);
+ INHERIT (to_kill, t);
+ INHERIT (to_load, t);
+ INHERIT (to_lookup_symbol, t);
+ INHERIT (to_create_inferior, t);
+ INHERIT (to_mourn_inferior, t);
+ INHERIT (to_can_run, t);
+ INHERIT (to_notice_signals, t);
+ INHERIT (to_thread_alive, t);
+ INHERIT (to_stop, t);
+ INHERIT (to_stratum, t);
+ INHERIT (DONT_USE, t);
+ INHERIT (to_has_all_memory, t);
+ INHERIT (to_has_memory, t);
+ INHERIT (to_has_stack, t);
+ INHERIT (to_has_registers, t);
+ INHERIT (to_has_execution, t);
+ INHERIT (to_sections, t);
+ INHERIT (to_sections_end, t);
+ INHERIT (to_magic, t);
+
+#undef INHERIT
+ }
+}
+
+/* Push a new target type into the stack of the existing target accessors,
+ possibly superseding some of the existing accessors.
+
+ Result is zero if the pushed target ended up on top of the stack,
+ nonzero if at least one target is on top of it.
+
+ Rather than allow an empty stack, we always have the dummy target at
+ the bottom stratum, so we can call the function vectors without
+ checking them. */
+
+int
+push_target (t)
+ struct target_ops *t;
+{
+ struct target_stack_item *cur, *prev, *tmp;
+
+ /* Check magic number. If wrong, it probably means someone changed
+ the struct definition, but not all the places that initialize one. */
+ if (t->to_magic != OPS_MAGIC)
+ {
+ fprintf_unfiltered(gdb_stderr,
+ "Magic number of %s target struct wrong\n",
+ t->to_shortname);
+ abort();
+ }
+
+ /* Find the proper stratum to install this target in. */
+
+ for (prev = NULL, cur = target_stack; cur; prev = cur, cur = cur->next)
+ {
+ if ((int)(t->to_stratum) >= (int)(cur->target_ops->to_stratum))
+ break;
+ }
+
+ /* If there's already targets at this stratum, remove them. */
+
+ if (cur)
+ while (t->to_stratum == cur->target_ops->to_stratum)
+ {
+ /* There's already something on this stratum. Close it off. */
+ (cur->target_ops->to_close) (0);
+ if (prev)
+ prev->next = cur->next; /* Unchain old target_ops */
+ else
+ target_stack = cur->next; /* Unchain first on list */
+ tmp = cur->next;
+ free (cur);
+ cur = tmp;
+ }
+
+ /* We have removed all targets in our stratum, now add the new one. */
+
+ tmp = (struct target_stack_item *)
+ xmalloc (sizeof (struct target_stack_item));
+ tmp->next = cur;
+ tmp->target_ops = t;
+
+ if (prev)
+ prev->next = tmp;
+ else
+ target_stack = tmp;
+
+ update_current_target ();
+
+ cleanup_target (&current_target); /* Fill in the gaps */
+
+#ifdef MAINTENANCE_CMDS
+ if (targetdebug)
+ setup_target_debug ();
+#endif
+
+ return prev != 0;
+}
+
+/* Remove a target_ops vector from the stack, wherever it may be.
+ Return how many times it was removed (0 or 1). */
+
+int
+unpush_target (t)
+ struct target_ops *t;
+{
+ struct target_stack_item *cur, *prev;
+
+ if (t->to_close)
+ t->to_close (0); /* Let it clean up */
+
+ /* Look for the specified target. Note that we assume that a target
+ can only occur once in the target stack. */
+
+ for (cur = target_stack, prev = NULL; cur; prev = cur, cur = cur->next)
+ if (cur->target_ops == t)
+ break;
+
+ if (!cur)
+ return 0; /* Didn't find target_ops, quit now */
+
+ /* Unchain the target */
+
+ if (!prev)
+ target_stack = cur->next;
+ else
+ prev->next = cur->next;
+
+ free (cur); /* Release the target_stack_item */
+
+ update_current_target ();
+ cleanup_target (&current_target);
+
+ return 1;
+}
+
+void
+pop_target ()
+{
+ (current_target.to_close)(0); /* Let it clean up */
+ if (unpush_target (target_stack->target_ops) == 1)
+ return;
+
+ fprintf_unfiltered(gdb_stderr,
+ "pop_target couldn't find target %s\n",
+ current_target.to_shortname);
+ abort();
+}
+
+#undef MIN
+#define MIN(A, B) (((A) <= (B)) ? (A) : (B))
+
+/* 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, string, len, errnop)
+ CORE_ADDR memaddr;
+ 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;
+
+ while (len > 0)
+ {
+ tlen = MIN (len, 4 - (memaddr & 3));
+ offset = memaddr & 3;
+
+ 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++)
+ {
+ *bufptr++ = buf[i + offset];
+ if (buf[i + offset] == '\000')
+ {
+ nbytes_read += i + 1;
+ goto done;
+ }
+ }
+
+ memaddr += tlen;
+ len -= tlen;
+ nbytes_read += tlen;
+ }
+ 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
+ GDB's memory at MYADDR. Returns either 0 for success or an errno value
+ if any error occurs.
+
+ If an error occurs, no guarantee is made about the contents of the data at
+ MYADDR. In particular, the caller should not depend upon partial reads
+ filling the buffer with good data. There is no way for the caller to know
+ how much good data might have been transfered anyway. Callers that can
+ deal with partial reads should call target_read_memory_partial. */
+
+int
+target_read_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ return target_xfer_memory (memaddr, myaddr, len, 0);
+}
+
+/* Read LEN bytes of target memory at address MEMADDR, placing the results
+ in GDB's memory at MYADDR. Returns a count of the bytes actually read,
+ and optionally an errno value in the location pointed to by ERRNOPTR
+ if ERRNOPTR is non-null. */
+
+int
+target_read_memory_partial (memaddr, myaddr, len, errnoptr)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int *errnoptr;
+{
+ int nread; /* Number of bytes actually read. */
+ int errcode; /* Error from last read. */
+
+ /* First try a complete read. */
+ errcode = target_xfer_memory (memaddr, myaddr, len, 0);
+ if (errcode == 0)
+ {
+ /* Got it all. */
+ nread = len;
+ }
+ else
+ {
+ /* Loop, reading one byte at a time until we get as much as we can. */
+ for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--)
+ {
+ errcode = target_xfer_memory (memaddr++, myaddr++, 1, 0);
+ }
+ /* If an error, the last read was unsuccessful, so adjust count. */
+ if (errcode != 0)
+ {
+ nread--;
+ }
+ }
+ if (errnoptr != NULL)
+ {
+ *errnoptr = errcode;
+ }
+ return (nread);
+}
+
+int
+target_write_memory (memaddr, myaddr, len)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+{
+ return target_xfer_memory (memaddr, myaddr, len, 1);
+}
+
+/* Move memory to or from the targets. Iterate until all of it has
+ been moved, if necessary. The top target gets priority; anything
+ it doesn't want, is offered to the next one down, etc. Note the
+ business with curlen: if an early target says "no, but I have a
+ boundary overlapping this xfer" then we shorten what we offer to
+ the subsequent targets so the early guy will get a chance at the
+ tail before the subsequent ones do.
+
+ Result is 0 or errno value. */
+
+int
+target_xfer_memory (memaddr, myaddr, len, write)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+{
+ int curlen;
+ int res;
+ struct target_ops *t;
+ struct target_stack_item *item;
+
+ /* to_xfer_memory is not guaranteed to set errno, even when it returns
+ 0. */
+ errno = 0;
+
+ /* The quick case is that the top target does it all. */
+ res = current_target.to_xfer_memory
+ (memaddr, myaddr, len, write, &current_target);
+ if (res == len)
+ return 0;
+
+ if (res > 0)
+ goto bump;
+ /* If res <= 0 then we call it again in the loop. Ah well. */
+
+ for (; len > 0;)
+ {
+ curlen = len; /* Want to do it all */
+ for (item = target_stack; item; item = item->next)
+ {
+ t = item->target_ops;
+ if (!t->to_has_memory)
+ continue;
+
+ res = t->to_xfer_memory (memaddr, myaddr, curlen, write, t);
+ if (res > 0)
+ break; /* Handled all or part of xfer */
+ if (t->to_has_all_memory)
+ break;
+ }
+
+ if (res <= 0)
+ {
+ /* If this address is for nonexistent memory,
+ read zeros if reading, or do nothing if writing. Return error. */
+ if (!write)
+ memset (myaddr, 0, len);
+ if (errno == 0)
+ return EIO;
+ else
+ return errno;
+ }
+bump:
+ memaddr += res;
+ myaddr += res;
+ len -= res;
+ }
+ return 0; /* We managed to cover it all somehow. */
+}
+
+
+/* ARGSUSED */
+static void
+target_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct target_ops *t;
+ struct target_stack_item *item;
+ int has_all_mem = 0;
+
+ if (symfile_objfile != NULL)
+ printf_unfiltered ("Symbols from \"%s\".\n", symfile_objfile->name);
+
+#ifdef FILES_INFO_HOOK
+ if (FILES_INFO_HOOK ())
+ return;
+#endif
+
+ for (item = target_stack; item; item = item->next)
+ {
+ t = item->target_ops;
+
+ if (!t->to_has_memory)
+ continue;
+
+ if ((int)(t->to_stratum) <= (int)dummy_stratum)
+ continue;
+ if (has_all_mem)
+ 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;
+ }
+}
+
+/* This is to be called by the open routine before it does
+ anything. */
+
+void
+target_preopen (from_tty)
+ int from_tty;
+{
+ dont_repeat();
+
+ if (target_has_execution)
+ {
+ if (query ("A program is being debugged already. Kill it? "))
+ target_kill ();
+ 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. */
+
+void
+target_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ /* Handle any optimized stores to the inferior. */
+#ifdef DO_DEFERRED_STORES
+ DO_DEFERRED_STORES;
+#endif
+ (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.
+
+ Result is always valid (error() is called for errors). */
+
+static struct target_ops *
+find_default_run_target (do_mesg)
+ char *do_mesg;
+{
+ struct target_ops **t;
+ struct target_ops *runable = NULL;
+ int count;
+
+ count = 0;
+
+ for (t = target_structs; t < target_structs + target_struct_size;
+ ++t)
+ {
+ if ((*t)->to_can_run && target_can_run(*t))
+ {
+ runable = *t;
+ ++count;
+ }
+ }
+
+ if (count != 1)
+ error ("Don't know how to %s. Try \"help target\".", do_mesg);
+
+ return runable;
+}
+
+void
+find_default_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct target_ops *t;
+
+ t = find_default_run_target("attach");
+ (t->to_attach) (args, from_tty);
+ return;
+}
+
+void
+find_default_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ struct target_ops *t;
+
+ t = find_default_run_target("run");
+ (t->to_create_inferior) (exec_file, allargs, env);
+ return;
+}
+
+static int
+return_zero ()
+{
+ return 0;
+}
+
+struct target_ops *
+find_core_target ()
+{
+ struct target_ops **t;
+ struct target_ops *runable = NULL;
+ int count;
+
+ count = 0;
+
+ for (t = target_structs; t < target_structs + target_struct_size;
+ ++t)
+ {
+ if ((*t)->to_stratum == core_stratum)
+ {
+ runable = *t;
+ ++count;
+ }
+ }
+
+ 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"},
+ {"SIGPRIO", "SIGPRIO"},
+ {"SIG33", "Real-time event 33"},
+ {"SIG34", "Real-time event 34"},
+ {"SIG35", "Real-time event 35"},
+ {"SIG36", "Real-time event 36"},
+ {"SIG37", "Real-time event 37"},
+ {"SIG38", "Real-time event 38"},
+ {"SIG39", "Real-time event 39"},
+ {"SIG40", "Real-time event 40"},
+ {"SIG41", "Real-time event 41"},
+ {"SIG42", "Real-time event 42"},
+ {"SIG43", "Real-time event 43"},
+ {"SIG44", "Real-time event 44"},
+ {"SIG45", "Real-time event 45"},
+ {"SIG46", "Real-time event 46"},
+ {"SIG47", "Real-time event 47"},
+ {"SIG48", "Real-time event 48"},
+ {"SIG49", "Real-time event 49"},
+ {"SIG50", "Real-time event 50"},
+ {"SIG51", "Real-time event 51"},
+ {"SIG52", "Real-time event 52"},
+ {"SIG53", "Real-time event 53"},
+ {"SIG54", "Real-time event 54"},
+ {"SIG55", "Real-time event 55"},
+ {"SIG56", "Real-time event 56"},
+ {"SIG57", "Real-time event 57"},
+ {"SIG58", "Real-time event 58"},
+ {"SIG59", "Real-time event 59"},
+ {"SIG60", "Real-time event 60"},
+ {"SIG61", "Real-time event 61"},
+ {"SIG62", "Real-time event 62"},
+ {"SIG63", "Real-time event 63"},
+
+ {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
+#if defined (SIGPRIO)
+ if (hostsig == SIGPRIO) return TARGET_SIGNAL_PRIO;
+#endif
+#if defined (REALTIME_LO)
+ if (hostsig >= REALTIME_LO && hostsig < REALTIME_HI)
+ return (enum target_signal)
+ (hostsig - 33 + (int) TARGET_SIGNAL_REALTIME_33);
+#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
+#if defined (SIGPRIO)
+ case TARGET_SIGNAL_PRIO: return SIGPRIO;
+#endif
+ default:
+#if defined (REALTIME_LO)
+ if (oursig >= TARGET_SIGNAL_REALTIME_33
+ && oursig <= TARGET_SIGNAL_REALTIME_63)
+ {
+ int retsig =
+ (int)oursig - (int)TARGET_SIGNAL_REALTIME_33 + REALTIME_LO;
+ if (retsig < REALTIME_HI)
+ return retsig;
+ }
+#endif
+ /* 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));
+ }
+}
+
+/* In some circumstances we allow a command to specify a numeric
+ signal. The idea is to keep these circumstances limited so that
+ users (and scripts) develop portable habits. For comparison,
+ POSIX.2 `kill' requires that 1,2,3,6,9,14, and 15 work (and using a
+ numeric signal at all is obscelescent. We are slightly more
+ lenient and allow 1-15 which should match host signal numbers on
+ most systems. Use of symbolic signal names is strongly encouraged. */
+
+enum target_signal
+target_signal_from_command (num)
+ int num;
+{
+ if (num >= 1 && num <= 15)
+ return (enum target_signal)num;
+ error ("Only signals 1-15 are valid as numeric signals.\n\
+Use \"info signals\" for a list of symbolic signals.");
+}
+
+/* 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. */
+
+char *
+normal_pid_to_str (pid)
+ int pid;
+{
+ static char buf[30];
+
+ if (STREQ (current_target.to_shortname, "remote"))
+ sprintf (buf, "thread %d", pid);
+ else
+ sprintf (buf, "process %d", pid);
+
+ return buf;
+}
+
+#ifdef MAINTENANCE_CMDS
+static struct target_ops debug_target;
+
+static void
+debug_to_open (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_open (args, from_tty);
+
+ fprintf_unfiltered (stderr, "target_open (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_close (quitting)
+ int quitting;
+{
+ debug_target.to_close (quitting);
+
+ fprintf_unfiltered (stderr, "target_close (%d)\n", quitting);
+}
+
+static void
+debug_to_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_attach (args, from_tty);
+
+ fprintf_unfiltered (stderr, "target_attach (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_detach (args, from_tty);
+
+ fprintf_unfiltered (stderr, "target_detach (%s, %d)\n", args, from_tty);
+}
+
+static void
+debug_to_resume (pid, step, siggnal)
+ int pid;
+ int step;
+ enum target_signal siggnal;
+{
+ debug_target.to_resume (pid, step, siggnal);
+
+ fprintf_unfiltered (stderr, "target_resume (%d, %s, %s)\n", pid,
+ step ? "step" : "continue",
+ target_signal_to_name (siggnal));
+}
+
+static int
+debug_to_wait (pid, status)
+ int pid;
+ struct target_waitstatus *status;
+{
+ int retval;
+
+ retval = debug_target.to_wait (pid, status);
+
+ fprintf_unfiltered (stderr, "target_wait (%d, status) = %d, ", pid, retval);
+ fprintf_unfiltered (stderr, "status->kind = ");
+ switch (status->kind)
+ {
+ case TARGET_WAITKIND_EXITED:
+ fprintf_unfiltered (stderr, "exited, status = %d\n", status->value.integer);
+ break;
+ case TARGET_WAITKIND_STOPPED:
+ fprintf_unfiltered (stderr, "stopped, signal = %s\n",
+ target_signal_to_name (status->value.sig));
+ break;
+ case TARGET_WAITKIND_SIGNALLED:
+ fprintf_unfiltered (stderr, "signalled, signal = %s\n",
+ target_signal_to_name (status->value.sig));
+ break;
+ case TARGET_WAITKIND_LOADED:
+ fprintf_unfiltered (stderr, "loaded\n");
+ break;
+ case TARGET_WAITKIND_SPURIOUS:
+ fprintf_unfiltered (stderr, "spurious\n");
+ break;
+ default:
+ fprintf_unfiltered (stderr, "unknown???\n");
+ break;
+ }
+
+ return retval;
+}
+
+static void
+debug_to_fetch_registers (regno)
+ int regno;
+{
+ debug_target.to_fetch_registers (regno);
+
+ fprintf_unfiltered (stderr, "target_fetch_registers (%s)",
+ regno != -1 ? reg_names[regno] : "-1");
+ if (regno != -1)
+ fprintf_unfiltered (stderr, " = 0x%x %d", read_register (regno),
+ read_register (regno));
+ fprintf_unfiltered (stderr, "\n");
+}
+
+static void
+debug_to_store_registers (regno)
+ int regno;
+{
+ debug_target.to_store_registers (regno);
+
+ if (regno >= 0 && regno < NUM_REGS)
+ fprintf_unfiltered (stderr, "target_store_registers (%s) = 0x%x %d\n",
+ reg_names[regno], read_register (regno),
+ read_register (regno));
+ else
+ fprintf_unfiltered (stderr, "target_store_registers (%d)\n", regno);
+}
+
+static void
+debug_to_prepare_to_store ()
+{
+ debug_target.to_prepare_to_store ();
+
+ fprintf_unfiltered (stderr, "target_prepare_to_store ()\n");
+}
+
+static int
+debug_to_xfer_memory (memaddr, myaddr, len, write, target)
+ CORE_ADDR memaddr;
+ char *myaddr;
+ int len;
+ int write;
+ struct target_ops *target;
+{
+ int retval;
+
+ retval = debug_target.to_xfer_memory (memaddr, myaddr, len, write, target);
+
+ fprintf_unfiltered (stderr, "target_xfer_memory (0x%x, xxx, %d, %s, xxx) = %d",
+ memaddr, len, write ? "write" : "read", retval);
+
+ if (retval > 0)
+ {
+ int i;
+
+ fputs_unfiltered (", bytes =", gdb_stderr);
+ for (i = 0; i < retval; i++)
+ fprintf_unfiltered (stderr, " %02x", myaddr[i] & 0xff);
+ }
+
+ fputc_unfiltered ('\n', gdb_stderr);
+
+ return retval;
+}
+
+static void
+debug_to_files_info (target)
+ struct target_ops *target;
+{
+ debug_target.to_files_info (target);
+
+ fprintf_unfiltered (stderr, "target_files_info (xxx)\n");
+}
+
+static int
+debug_to_insert_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int retval;
+
+ retval = debug_target.to_insert_breakpoint (addr, save);
+
+ fprintf_unfiltered (stderr, "target_insert_breakpoint (0x%x, xxx) = %d\n",
+ addr, retval);
+ return retval;
+}
+
+static int
+debug_to_remove_breakpoint (addr, save)
+ CORE_ADDR addr;
+ char *save;
+{
+ int retval;
+
+ retval = debug_target.to_remove_breakpoint (addr, save);
+
+ fprintf_unfiltered (stderr, "target_remove_breakpoint (0x%x, xxx) = %d\n",
+ addr, retval);
+ return retval;
+}
+
+static void
+debug_to_terminal_init ()
+{
+ debug_target.to_terminal_init ();
+
+ fprintf_unfiltered (stderr, "target_terminal_init ()\n");
+}
+
+static void
+debug_to_terminal_inferior ()
+{
+ debug_target.to_terminal_inferior ();
+
+ fprintf_unfiltered (stderr, "target_terminal_inferior ()\n");
+}
+
+static void
+debug_to_terminal_ours_for_output ()
+{
+ debug_target.to_terminal_ours_for_output ();
+
+ fprintf_unfiltered (stderr, "target_terminal_ours_for_output ()\n");
+}
+
+static void
+debug_to_terminal_ours ()
+{
+ debug_target.to_terminal_ours ();
+
+ fprintf_unfiltered (stderr, "target_terminal_ours ()\n");
+}
+
+static void
+debug_to_terminal_info (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ debug_target.to_terminal_info (arg, from_tty);
+
+ fprintf_unfiltered (stderr, "target_terminal_info (%s, %d)\n", arg,
+ from_tty);
+}
+
+static void
+debug_to_kill ()
+{
+ debug_target.to_kill ();
+
+ fprintf_unfiltered (stderr, "target_kill ()\n");
+}
+
+static void
+debug_to_load (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ debug_target.to_load (args, from_tty);
+
+ fprintf_unfiltered (stderr, "target_load (%s, %d)\n", args, from_tty);
+}
+
+static int
+debug_to_lookup_symbol (name, addrp)
+ char *name;
+ CORE_ADDR *addrp;
+{
+ int retval;
+
+ retval = debug_target.to_lookup_symbol (name, addrp);
+
+ fprintf_unfiltered (stderr, "target_lookup_symbol (%s, xxx)\n", name);
+
+ return retval;
+}
+
+static void
+debug_to_create_inferior (exec_file, args, env)
+ char *exec_file;
+ char *args;
+ char **env;
+{
+ debug_target.to_create_inferior (exec_file, args, env);
+
+ fprintf_unfiltered (stderr, "target_create_inferior (%s, %s, xxx)\n",
+ exec_file, args);
+}
+
+static void
+debug_to_mourn_inferior ()
+{
+ debug_target.to_mourn_inferior ();
+
+ fprintf_unfiltered (stderr, "target_mourn_inferior ()\n");
+}
+
+static int
+debug_to_can_run ()
+{
+ int retval;
+
+ retval = debug_target.to_can_run ();
+
+ fprintf_unfiltered (stderr, "target_can_run () = %d\n", retval);
+
+ return retval;
+}
+
+static void
+debug_to_notice_signals (pid)
+ int pid;
+{
+ debug_target.to_notice_signals (pid);
+
+ fprintf_unfiltered (stderr, "target_notice_signals (%d)\n", pid);
+}
+
+static int
+debug_to_thread_alive (pid)
+ int pid;
+{
+ debug_target.to_thread_alive (pid);
+
+ fprintf_unfiltered (stderr, "target_thread_alive (%d)\n", pid);
+ return (0);
+}
+
+static void
+debug_to_stop ()
+{
+ debug_target.to_stop ();
+
+ fprintf_unfiltered (stderr, "target_stop ()\n");
+}
+
+static void
+setup_target_debug ()
+{
+ memcpy (&debug_target, &current_target, sizeof debug_target);
+
+ current_target.to_open = debug_to_open;
+ current_target.to_close = debug_to_close;
+ current_target.to_attach = debug_to_attach;
+ current_target.to_detach = debug_to_detach;
+ current_target.to_resume = debug_to_resume;
+ current_target.to_wait = debug_to_wait;
+ current_target.to_fetch_registers = debug_to_fetch_registers;
+ current_target.to_store_registers = debug_to_store_registers;
+ current_target.to_prepare_to_store = debug_to_prepare_to_store;
+ current_target.to_xfer_memory = debug_to_xfer_memory;
+ current_target.to_files_info = debug_to_files_info;
+ current_target.to_insert_breakpoint = debug_to_insert_breakpoint;
+ current_target.to_remove_breakpoint = debug_to_remove_breakpoint;
+ current_target.to_terminal_init = debug_to_terminal_init;
+ current_target.to_terminal_inferior = debug_to_terminal_inferior;
+ current_target.to_terminal_ours_for_output = debug_to_terminal_ours_for_output;
+ current_target.to_terminal_ours = debug_to_terminal_ours;
+ current_target.to_terminal_info = debug_to_terminal_info;
+ current_target.to_kill = debug_to_kill;
+ current_target.to_load = debug_to_load;
+ current_target.to_lookup_symbol = debug_to_lookup_symbol;
+ current_target.to_create_inferior = debug_to_create_inferior;
+ current_target.to_mourn_inferior = debug_to_mourn_inferior;
+ current_target.to_can_run = debug_to_can_run;
+ current_target.to_notice_signals = debug_to_notice_signals;
+ current_target.to_thread_alive = debug_to_thread_alive;
+ current_target.to_stop = debug_to_stop;
+}
+#endif /* MAINTENANCE_CMDS */
+
+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\
+core-file, and process, if any), as well as the symbol file name.";
+
+void
+initialize_targets ()
+{
+ push_target (&dummy_target);
+
+ add_info ("target", target_info, targ_desc);
+ add_info ("files", target_info, targ_desc);
+
+#ifdef MAINTENANCE_CMDS
+ add_show_from_set (
+ add_set_cmd ("targetdebug", class_maintenance, var_zinteger,
+ (char *)&targetdebug,
+ "Set target debugging.\n\
+When non-zero, target debugging is enabled.", &setlist),
+ &showlist);
+#endif
+
+ if (!STREQ (signals[TARGET_SIGNAL_LAST].string, "TARGET_SIGNAL_MAGIC"))
+ abort ();
+}
diff --git a/contrib/gdb/gdb/target.h b/contrib/gdb/gdb/target.h
new file mode 100644
index 0000000..fa2291d
--- /dev/null
+++ b/contrib/gdb/gdb/target.h
@@ -0,0 +1,765 @@
+/* Interface between GDB and target environments, including files and processes
+ Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Contributed by Cygnus Support. Written by John Gilmore.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (TARGET_H)
+#define TARGET_H
+
+/* This include file defines the interface between the main part
+ of the debugger, and the part which is target-specific, or
+ specific to the communications interface between us and the
+ target.
+
+ A TARGET is an interface between the debugger and a particular
+ kind of file or process. Targets can be STACKED in STRATA,
+ so that more than one target can potentially respond to a request.
+ In particular, memory accesses will walk down the stack of targets
+ until they find a target that is interested in handling that particular
+ address. STRATA are artificial boundaries on the stack, within
+ which particular kinds of targets live. Strata exist so that
+ people don't get confused by pushing e.g. a process target and then
+ a file target, and wondering why they can't see the current values
+ of variables any more (the file target is handling them and they
+ never get to the process target). So when you push a file target,
+ it goes into the file stratum, which is always below the process
+ stratum. */
+
+#include "bfd.h"
+
+enum strata {
+ dummy_stratum, /* The lowest of the low */
+ file_stratum, /* Executable files, etc */
+ core_stratum, /* Core dump files */
+ download_stratum, /* Downloading of remote targets */
+ 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,
+ TARGET_SIGNAL_PRIO = 44,
+ TARGET_SIGNAL_REALTIME_33 = 45,
+ TARGET_SIGNAL_REALTIME_34 = 46,
+ TARGET_SIGNAL_REALTIME_35 = 47,
+ TARGET_SIGNAL_REALTIME_36 = 48,
+ TARGET_SIGNAL_REALTIME_37 = 49,
+ TARGET_SIGNAL_REALTIME_38 = 50,
+ TARGET_SIGNAL_REALTIME_39 = 51,
+ TARGET_SIGNAL_REALTIME_40 = 52,
+ TARGET_SIGNAL_REALTIME_41 = 53,
+ TARGET_SIGNAL_REALTIME_42 = 54,
+ TARGET_SIGNAL_REALTIME_43 = 55,
+ TARGET_SIGNAL_REALTIME_44 = 56,
+ TARGET_SIGNAL_REALTIME_45 = 57,
+ TARGET_SIGNAL_REALTIME_46 = 58,
+ TARGET_SIGNAL_REALTIME_47 = 59,
+ TARGET_SIGNAL_REALTIME_48 = 60,
+ TARGET_SIGNAL_REALTIME_49 = 61,
+ TARGET_SIGNAL_REALTIME_50 = 62,
+ TARGET_SIGNAL_REALTIME_51 = 63,
+ TARGET_SIGNAL_REALTIME_52 = 64,
+ TARGET_SIGNAL_REALTIME_53 = 65,
+ TARGET_SIGNAL_REALTIME_54 = 66,
+ TARGET_SIGNAL_REALTIME_55 = 67,
+ TARGET_SIGNAL_REALTIME_56 = 68,
+ TARGET_SIGNAL_REALTIME_57 = 69,
+ TARGET_SIGNAL_REALTIME_58 = 70,
+ TARGET_SIGNAL_REALTIME_59 = 71,
+ TARGET_SIGNAL_REALTIME_60 = 72,
+ TARGET_SIGNAL_REALTIME_61 = 73,
+ TARGET_SIGNAL_REALTIME_62 = 74,
+ TARGET_SIGNAL_REALTIME_63 = 75,
+
+ /* 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 */
+ char *to_longname; /* Name for printing */
+ char *to_doc; /* Documentation. Does not include trailing
+ newline, and starts with a one-line descrip-
+ tion (probably similar to to_longname). */
+ void (*to_open) PARAMS ((char *, int));
+ void (*to_close) PARAMS ((int));
+ void (*to_attach) PARAMS ((char *, int));
+ void (*to_detach) PARAMS ((char *, 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));
+
+ /* Transfer LEN bytes of memory between GDB address MYADDR and
+ target address MEMADDR. If WRITE, transfer them to the target, else
+ transfer them from the target. TARGET is the target from which we
+ get this function.
+
+ Return value, N, is one of the following:
+
+ 0 means that we can't handle this. If errno has been set, it is the
+ error which prevented us from doing it (FIXME: What about bfd_error?).
+
+ positive (call it N) means that we have transferred N bytes
+ starting at MEMADDR. We might be able to handle more bytes
+ beyond this length, but no promises.
+
+ negative (call its absolute value N) means that we cannot
+ transfer right at MEMADDR, but we could transfer at least
+ something at MEMADDR + N. */
+
+ int (*to_xfer_memory) PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ 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 *));
+ void (*to_terminal_init) PARAMS ((void));
+ void (*to_terminal_inferior) PARAMS ((void));
+ void (*to_terminal_ours_for_output) PARAMS ((void));
+ void (*to_terminal_ours) PARAMS ((void));
+ void (*to_terminal_info) PARAMS ((char *, int));
+ void (*to_kill) PARAMS ((void));
+ void (*to_load) PARAMS ((char *, int));
+ int (*to_lookup_symbol) PARAMS ((char *, CORE_ADDR *));
+ void (*to_create_inferior) PARAMS ((char *, char *, char **));
+ void (*to_mourn_inferior) PARAMS ((void));
+ int (*to_can_run) PARAMS ((void));
+ void (*to_notice_signals) PARAMS ((int pid));
+ int (*to_thread_alive) PARAMS ((int pid));
+ void (*to_stop) PARAMS ((void));
+ enum strata to_stratum;
+ struct target_ops
+ *DONT_USE; /* formerly to_next */
+ int to_has_all_memory;
+ int to_has_memory;
+ int to_has_stack;
+ int to_has_registers;
+ int to_has_execution;
+ struct section_table
+ *to_sections;
+ struct section_table
+ *to_sections_end;
+ int to_magic;
+ /* Need sub-structure for target machine related rather than comm related? */
+};
+
+/* Magic number for checking ops size. If a struct doesn't end with this
+ number, somebody changed the declaration but didn't change all the
+ places that initialize one. */
+
+#define OPS_MAGIC 3840
+
+/* The ops structure for our "current" target process. This should
+ never be NULL. If there is no target, it points to the dummy_target. */
+
+extern struct target_ops current_target;
+
+/* An item on the target stack. */
+
+struct target_stack_item
+{
+ struct target_stack_item *next;
+ struct target_ops *target_ops;
+};
+
+/* The target stack. */
+
+extern struct target_stack_item *target_stack;
+
+/* Define easy words for doing these operations on our current target. */
+
+#define target_shortname (current_target.to_shortname)
+#define target_longname (current_target.to_longname)
+
+/* The open routine takes the rest of the parameters from the command,
+ and (if successful) pushes a new target onto the stack.
+ Targets should supply this routine, if only to provide an error message. */
+#define target_open(name, from_tty) \
+ (*current_target.to_open) (name, from_tty)
+
+/* Does whatever cleanup is required for a target that we are no longer
+ going to be calling. Argument says whether we are quitting gdb and
+ should not get hung in case of errors, or whether we want a clean
+ termination even if it takes a while. This routine is automatically
+ always called just before a routine is popped off the target stack.
+ Closing file descriptors and freeing memory are typical things it should
+ do. */
+
+#define target_close(quitting) \
+ (*current_target.to_close) (quitting)
+
+/* Attaches to a process on the target side. Arguments are as passed
+ to the `attach' command by the user. This routine can be called
+ when the target is not on the target-stack, if the target_can_run
+ routine returns 1; in that case, it must push itself onto the stack.
+ Upon exit, the target should be ready for normal operations, and
+ should be ready to deliver the status of the process immediately
+ (without waiting) to an upcoming target_wait call. */
+
+#define target_attach(args, from_tty) \
+ (*current_target.to_attach) (args, from_tty)
+
+/* Takes a program previously attached to and detaches it.
+ The program may resume execution (some targets do, some don't) and will
+ no longer stop on signals, etc. We better not have left any breakpoints
+ in the program or it'll die when it hits one. ARGS is arguments
+ typed by the user (e.g. a signal to send the process). FROM_TTY
+ says whether to be verbose or not. */
+
+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 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. 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)
+
+/* Fetch register REGNO, or all regs if regno == -1. No result. */
+
+#define target_fetch_registers(regno) \
+ (*current_target.to_fetch_registers) (regno)
+
+/* Store at least register REGNO, or all regs if REGNO == -1.
+ It can store as many registers as it wants to, so target_prepare_to_store
+ must have been previously called. Calls error() if there are problems. */
+
+#define target_store_registers(regs) \
+ (*current_target.to_store_registers) (regs)
+
+/* Get ready to modify the registers array. On machines which store
+ individual registers, this doesn't need to do anything. On machines
+ which store all the registers in one fell swoop, this makes sure
+ that REGISTERS contains all the registers from the program being
+ debugged. */
+
+#define target_prepare_to_store() \
+ (*current_target.to_prepare_to_store) ()
+
+extern int target_read_string PARAMS ((CORE_ADDR, char **, int, int *));
+
+extern int
+target_read_memory PARAMS ((CORE_ADDR, char *, int));
+
+extern int
+target_read_memory_partial PARAMS ((CORE_ADDR, char *, int, int *));
+
+extern int
+target_write_memory PARAMS ((CORE_ADDR, char *, int));
+
+extern int
+xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+extern int
+child_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+/* Transfer LEN bytes between target address MEMADDR and GDB address MYADDR.
+ Returns 0 for success, errno code for failure (which includes partial
+ transfers--if you want a more useful response to partial transfers, try
+ target_read_memory_partial). */
+
+extern int target_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
+ int len, int write));
+
+/* From exec.c */
+
+extern void
+print_section_info PARAMS ((struct target_ops *, bfd *));
+
+/* Print a line about the current target. */
+
+#define target_files_info() \
+ (*current_target.to_files_info) (&current_target)
+
+/* Insert a breakpoint at address ADDR in the target machine.
+ SAVE is a pointer to memory allocated for saving the
+ target contents. It is guaranteed by the caller to be long enough
+ to save "sizeof BREAKPOINT" bytes. Result is 0 for success, or
+ an errno value. */
+
+#define target_insert_breakpoint(addr, save) \
+ (*current_target.to_insert_breakpoint) (addr, save)
+
+/* Remove a breakpoint at address ADDR in the target machine.
+ SAVE is a pointer to the same save area
+ that was previously passed to target_insert_breakpoint.
+ Result is 0 for success, or an errno value. */
+
+#define target_remove_breakpoint(addr, save) \
+ (*current_target.to_remove_breakpoint) (addr, save)
+
+/* Initialize the terminal settings we record for the inferior,
+ before we actually run the inferior. */
+
+#define target_terminal_init() \
+ (*current_target.to_terminal_init) ()
+
+/* Put the inferior's terminal settings into effect.
+ This is preparation for starting or resuming the inferior. */
+
+#define target_terminal_inferior() \
+ (*current_target.to_terminal_inferior) ()
+
+/* Put some of our terminal settings into effect,
+ enough to get proper results from our output,
+ but do not change into or out of RAW mode
+ so that no input is discarded.
+
+ After doing this, either terminal_ours or terminal_inferior
+ should be called to get back to a normal state of affairs. */
+
+#define target_terminal_ours_for_output() \
+ (*current_target.to_terminal_ours_for_output) ()
+
+/* Put our terminal settings into effect.
+ First record the inferior's terminal settings
+ so they can be restored properly later. */
+
+#define target_terminal_ours() \
+ (*current_target.to_terminal_ours) ()
+
+/* Print useful information about our terminal status, if such a thing
+ exists. */
+
+#define target_terminal_info(arg, from_tty) \
+ (*current_target.to_terminal_info) (arg, from_tty)
+
+/* Kill the inferior process. Make it go away. */
+
+#define target_kill() \
+ (*current_target.to_kill) ()
+
+/* Load an executable file into the target process. This is expected to
+ not only bring new code into the target process, but also to update
+ GDB's symbol tables to match. */
+
+#define target_load(arg, from_tty) \
+ (*current_target.to_load) (arg, from_tty)
+
+/* Look up a symbol in the target's symbol table. NAME is the symbol
+ name. ADDRP is a CORE_ADDR * pointing to where the value of the symbol
+ should be returned. The result is 0 if successful, nonzero if the
+ symbol does not exist in the target environment. This function should
+ not call error() if communication with the target is interrupted, since
+ it is called from symbol reading, but should return nonzero, possibly
+ doing a complain(). */
+
+#define target_lookup_symbol(name, addrp) \
+ (*current_target.to_lookup_symbol) (name, addrp)
+
+/* Start an inferior process and set 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().
+ On VxWorks and various standalone systems, we ignore exec_file. */
+
+#define target_create_inferior(exec_file, args, env) \
+ (*current_target.to_create_inferior) (exec_file, args, env)
+
+/* The inferior process has died. Do what is right. */
+
+#define target_mourn_inferior() \
+ (*current_target.to_mourn_inferior) ()
+
+/* Does target have enough data to do a run or attach command? */
+
+#define target_can_run(t) \
+ ((t)->to_can_run) ()
+
+/* post process changes to signal handling in the inferior. */
+
+#define target_notice_signals(pid) \
+ (*current_target.to_notice_signals) (pid)
+
+/* Check to see if a thread is still alive. */
+
+#define target_thread_alive(pid) \
+ (*current_target.to_thread_alive) (pid)
+
+/* Make target stop in a continuable fashion. (For instance, under Unix, this
+ should act like SIGSTOP). This function is normally used by GUIs to
+ implement a stop button. */
+
+#define target_stop() current_target.to_stop ()
+
+/* Pointer to next target in the chain, e.g. a core file and an exec file. */
+
+#define target_next \
+ (current_target.to_next)
+
+/* Does the target include all of memory, or only part of it? This
+ determines whether we look up the target chain for other parts of
+ memory if this target can't satisfy a request. */
+
+#define target_has_all_memory \
+ (current_target.to_has_all_memory)
+
+/* Does the target include memory? (Dummy targets don't.) */
+
+#define target_has_memory \
+ (current_target.to_has_memory)
+
+/* Does the target have a stack? (Exec files don't, VxWorks doesn't, until
+ we start a process.) */
+
+#define target_has_stack \
+ (current_target.to_has_stack)
+
+/* Does the target have registers? (Exec files don't.) */
+
+#define target_has_registers \
+ (current_target.to_has_registers)
+
+/* Does the target have execution? Can we make it jump (through
+ hoops), or pop its stack a few times? FIXME: If this is to work that
+ way, it needs to check whether an inferior actually exists.
+ remote-udi.c and probably other targets can be the current target
+ when the inferior doesn't actually exist at the moment. Right now
+ this just tells us whether this target is *capable* of execution. */
+
+#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'. */
+
+#ifndef target_pid_to_str
+#define target_pid_to_str(PID) \
+ normal_pid_to_str (PID)
+extern char *normal_pid_to_str PARAMS ((int pid));
+#endif
+
+/* Hook to call target-dependant code after reading in a new symbol table. */
+
+#ifndef TARGET_SYMFILE_POSTREAD
+#define TARGET_SYMFILE_POSTREAD(OBJFILE)
+#endif
+
+/* Hook to call target dependant code just after inferior target process has
+ started. */
+
+#ifndef TARGET_CREATE_INFERIOR_HOOK
+#define TARGET_CREATE_INFERIOR_HOOK(PID)
+#endif
+
+/* Hardware watchpoint interfaces. */
+
+/* Returns non-zero if we were stopped by a hardware watchpoint (memory read or
+ write). */
+
+#ifndef STOPPED_BY_WATCHPOINT
+#define STOPPED_BY_WATCHPOINT(w) 0
+#endif
+
+/* Provide defaults for systems that don't support hardware watchpoints. */
+
+#ifndef TARGET_HAS_HARDWARE_WATCHPOINTS
+
+/* Returns non-zero if we can set a hardware watchpoint of type TYPE. TYPE is
+ one of bp_hardware_watchpoint, bp_read_watchpoint, bp_write_watchpoint, or
+ bp_hardware_breakpoint. CNT is the number of such watchpoints used so far
+ (including this one?). OTHERTYPE is who knows what... */
+
+#define TARGET_CAN_USE_HARDWARE_WATCHPOINT(TYPE,CNT,OTHERTYPE) 0
+
+/* Set/clear a hardware watchpoint starting at ADDR, for LEN bytes. TYPE is 1
+ for read and 2 for read/write accesses. Returns 0 for success, non-zero for
+ failure. */
+
+#define target_remove_watchpoint(ADDR,LEN,TYPE) -1
+#define target_insert_watchpoint(ADDR,LEN,TYPE) -1
+
+#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
+
+#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
+
+/* If defined, then we need to decr pc by this much after a hardware break-
+ point. Presumably this overrides DECR_PC_AFTER_BREAK... */
+
+#ifndef DECR_PC_AFTER_HW_BREAK
+#define DECR_PC_AFTER_HW_BREAK 0
+#endif
+
+/* Routines for maintenance of the target structures...
+
+ add_target: Add a target to the list of all possible targets.
+
+ push_target: Make this target the top of the stack of currently used
+ targets, within its particular stratum of the stack. Result
+ is 0 if now atop the stack, nonzero if not on top (maybe
+ should warn user).
+
+ unpush_target: Remove this from the stack of currently used targets,
+ no matter where it is on the list. Returns 0 if no
+ change, 1 if removed from stack.
+
+ pop_target: Remove the top thing on the stack of current targets. */
+
+extern void
+add_target PARAMS ((struct target_ops *));
+
+extern int
+push_target PARAMS ((struct target_ops *));
+
+extern int
+unpush_target PARAMS ((struct target_ops *));
+
+extern void
+target_preopen PARAMS ((int));
+
+extern void
+pop_target PARAMS ((void));
+
+/* Struct section_table maps address ranges to file sections. It is
+ mostly used with BFD files, but can be used without (e.g. for handling
+ raw disks, or files not in formats handled by BFD). */
+
+struct section_table {
+ CORE_ADDR addr; /* Lowest address in section */
+ CORE_ADDR endaddr; /* 1+highest address in section */
+
+ sec_ptr the_bfd_section;
+
+ bfd *bfd; /* BFD file pointer */
+};
+
+/* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
+ Returns 0 if OK, 1 on error. */
+
+extern int
+build_section_table PARAMS ((bfd *, struct section_table **,
+ struct section_table **));
+
+/* From mem-break.c */
+
+extern int
+memory_remove_breakpoint PARAMS ((CORE_ADDR, char *));
+
+extern int
+memory_insert_breakpoint PARAMS ((CORE_ADDR, char *));
+
+/* From target.c */
+
+void
+noprocess PARAMS ((void));
+
+void
+find_default_attach PARAMS ((char *, int));
+
+void
+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));
+
+/* Convert from a number used in a GDB command to an enum target_signal. */
+extern enum target_signal target_signal_from_command PARAMS ((int));
+
+#endif /* !defined (TARGET_H) */
diff --git a/contrib/gdb/gdb/terminal.h b/contrib/gdb/gdb/terminal.h
new file mode 100644
index 0000000..9cae179
--- /dev/null
+++ b/contrib/gdb/gdb/terminal.h
@@ -0,0 +1,89 @@
+/* Terminal interface definitions for GDB, the GNU Debugger.
+ Copyright 1986, 1989, 1991, 1992 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (TERMINAL_H)
+#define TERMINAL_H 1
+
+
+/* If we're using autoconf, it will define HAVE_TERMIOS_H,
+ HAVE_TERMIO_H and HAVE_SGTTY_H for us. One day we can rewrite
+ ser-unix.c and inflow.c to inspect those names instead of
+ HAVE_TERMIOS, HAVE_TERMIO and the implicit HAVE_SGTTY (when neither
+ HAVE_TERMIOS or HAVE_TERMIO is set). Until then, make sure that
+ nothing has already defined the one of the names, and do the right
+ thing. */
+
+/* nothing works with go32, and the headers aren't complete */
+#if !defined (__GO32__)
+#if !defined (HAVE_TERMIOS) && !defined(HAVE_TERMIO) && !defined(HAVE_SGTTY)
+#if defined(HAVE_TERMIOS_H)
+#define HAVE_TERMIOS
+#elif defined(HAVE_TERMIO_H)
+#define HAVE_TERMIO
+#elif defined(HAVE_SGTTY_H)
+#define HAVE_SGTTY
+#endif
+#endif
+#endif
+
+#if defined(HAVE_TERMIOS)
+#include <termios.h>
+#endif
+
+
+#if !defined(__GO32__) && !defined(__WIN32__) && !defined (HAVE_TERMIOS)
+
+/* Define a common set of macros -- BSD based -- and redefine whatever
+ the system offers to make it look like that. FIXME: serial.h and
+ ser-*.c deal with this in a much cleaner fashion; as soon as stuff
+ is converted to use them, can get rid of this crap. */
+
+#ifdef HAVE_TERMIO
+
+#include <termio.h>
+
+#undef TIOCGETP
+#define TIOCGETP TCGETA
+#undef TIOCSETN
+#define TIOCSETN TCSETA
+#undef TIOCSETP
+#define TIOCSETP TCSETAF
+#define TERMINAL struct termio
+
+#else /* sgtty */
+
+#include <fcntl.h>
+#include <sgtty.h>
+#include <sys/ioctl.h>
+#define TERMINAL struct sgttyb
+
+#endif /* sgtty */
+#endif
+
+extern void new_tty PARAMS ((void));
+
+/* Do we have job control? Can be assumed to always be the same within
+ a given run of GDB. In inflow.c. */
+extern int job_control;
+
+/* Set the process group of the caller to its own pid, or do nothing if
+ we lack job control. */
+extern int gdb_setpgid PARAMS ((void));
+
+#endif /* !defined (TERMINAL_H) */
diff --git a/contrib/gdb/gdb/thread.c b/contrib/gdb/gdb/thread.c
new file mode 100644
index 0000000..d3ed393
--- /dev/null
+++ b/contrib/gdb/gdb/thread.c
@@ -0,0 +1,476 @@
+/* Multi-process/thread control for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1993
+
+ Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "frame.h"
+#include "inferior.h"
+#include "environ.h"
+#include "value.h"
+#include "target.h"
+#include "thread.h"
+#include "command.h"
+#include "gdbcmd.h"
+
+#include <ctype.h>
+#include <sys/types.h>
+#include <signal.h>
+
+/*#include "lynxos-core.h"*/
+
+struct thread_info
+{
+ struct thread_info *next;
+ int pid; /* Actual process id */
+ int num; /* Convenient handle */
+ CORE_ADDR prev_pc; /* State from wait_for_inferior */
+ CORE_ADDR prev_func_start;
+ char *prev_func_name;
+ struct breakpoint *step_resume_breakpoint;
+ struct breakpoint *through_sigtramp_breakpoint;
+ CORE_ADDR step_range_start;
+ CORE_ADDR step_range_end;
+ CORE_ADDR step_frame_address;
+ int trap_expected;
+ int handling_longjmp;
+ int another_trap;
+};
+
+static struct thread_info *thread_list = NULL;
+static int highest_thread_num;
+
+static void thread_command PARAMS ((char * tidstr, int from_tty));
+
+static void prune_threads PARAMS ((void));
+
+static void thread_switch PARAMS ((int pid));
+
+static struct thread_info * find_thread_id PARAMS ((int num));
+
+void
+init_thread_list ()
+{
+ struct thread_info *tp, *tpnext;
+
+ if (!thread_list)
+ return;
+
+ for (tp = thread_list; tp; tp = tpnext)
+ {
+ tpnext = tp->next;
+ free (tp);
+ }
+
+ thread_list = NULL;
+ highest_thread_num = 0;
+}
+
+void
+add_thread (pid)
+ int pid;
+{
+ struct thread_info *tp;
+
+ tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
+
+ tp->pid = pid;
+ tp->num = ++highest_thread_num;
+ tp->prev_pc = 0;
+ tp->prev_func_start = 0;
+ tp->prev_func_name = NULL;
+ tp->step_range_start = 0;
+ tp->step_range_end = 0;
+ tp->step_frame_address =0;
+ tp->step_resume_breakpoint = 0;
+ tp->through_sigtramp_breakpoint = 0;
+ tp->handling_longjmp = 0;
+ tp->trap_expected = 0;
+ tp->another_trap = 0;
+ tp->next = thread_list;
+ thread_list = tp;
+}
+
+static struct thread_info *
+find_thread_id (num)
+ int num;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->num == num)
+ return tp;
+
+ return NULL;
+}
+
+int
+valid_thread_id (num)
+ int num;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->num == num)
+ return 1;
+
+ return 0;
+}
+
+int
+pid_to_thread_id (pid)
+ int pid;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->pid == pid)
+ return tp->num;
+
+ return 0;
+}
+
+int
+in_thread_list (pid)
+ int pid;
+{
+ struct thread_info *tp;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->pid == pid)
+ return 1;
+
+ return 0; /* Never heard of 'im */
+}
+
+/* Load infrun state for the thread PID. */
+
+void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint, step_range_start,
+ step_range_end, step_frame_address,
+ handling_longjmp, another_trap)
+ int pid;
+ CORE_ADDR *prev_pc;
+ CORE_ADDR *prev_func_start;
+ char **prev_func_name;
+ int *trap_expected;
+ struct breakpoint **step_resume_breakpoint;
+ struct breakpoint **through_sigtramp_breakpoint;
+ CORE_ADDR *step_range_start;
+ CORE_ADDR *step_range_end;
+ CORE_ADDR *step_frame_address;
+ int *handling_longjmp;
+ int *another_trap;
+{
+ struct thread_info *tp;
+
+ /* If we can't find the thread, then we're debugging a single threaded
+ process. No need to do anything in that case. */
+ tp = find_thread_id (pid_to_thread_id (pid));
+ if (tp == NULL)
+ return;
+
+ *prev_pc = tp->prev_pc;
+ *prev_func_start = tp->prev_func_start;
+ *prev_func_name = tp->prev_func_name;
+ *step_resume_breakpoint = tp->step_resume_breakpoint;
+ *step_range_start = tp->step_range_start;
+ *step_range_end = tp->step_range_end;
+ *step_frame_address = tp->step_frame_address;
+ *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
+ *handling_longjmp = tp->handling_longjmp;
+ *trap_expected = tp->trap_expected;
+ *another_trap = tp->another_trap;
+}
+
+/* Save infrun state for the thread PID. */
+
+void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint, step_range_start,
+ step_range_end, step_frame_address,
+ handling_longjmp, another_trap)
+ int pid;
+ CORE_ADDR prev_pc;
+ CORE_ADDR prev_func_start;
+ char *prev_func_name;
+ int trap_expected;
+ struct breakpoint *step_resume_breakpoint;
+ struct breakpoint *through_sigtramp_breakpoint;
+ CORE_ADDR step_range_start;
+ CORE_ADDR step_range_end;
+ CORE_ADDR step_frame_address;
+ int handling_longjmp;
+ int another_trap;
+{
+ struct thread_info *tp;
+
+ /* If we can't find the thread, then we're debugging a single-threaded
+ process. Nothing to do in that case. */
+ tp = find_thread_id (pid_to_thread_id (pid));
+ if (tp == NULL)
+ return;
+
+ tp->prev_pc = prev_pc;
+ tp->prev_func_start = prev_func_start;
+ tp->prev_func_name = prev_func_name;
+ tp->step_resume_breakpoint = step_resume_breakpoint;
+ tp->step_range_start = step_range_start;
+ tp->step_range_end = step_range_end;
+ tp->step_frame_address = step_frame_address;
+ tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
+ tp->handling_longjmp = handling_longjmp;
+ tp->trap_expected = trap_expected;
+ tp->another_trap = another_trap;
+}
+
+static void
+prune_threads ()
+{
+ struct thread_info *tp, *tpprev;
+
+ tpprev = 0;
+
+ for (tp = thread_list; tp; tp = tp->next)
+ if (tp->pid == -1)
+ {
+ if (tpprev)
+ tpprev->next = tp->next;
+ else
+ thread_list = NULL;
+
+ free (tp);
+ }
+ else
+ tpprev = tp;
+}
+
+/* Print information about currently known threads */
+
+static void
+info_threads_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct thread_info *tp;
+ int current_pid = inferior_pid;
+
+ /* Avoid coredumps which would happen if we tried to access a NULL
+ selected_frame. */
+ if (!target_has_stack) error ("No stack.");
+
+ for (tp = thread_list; tp; tp = tp->next)
+ {
+ if (! target_thread_alive (tp->pid))
+ {
+ tp->pid = -1; /* Mark it as dead */
+ continue;
+ }
+
+ if (tp->pid == current_pid)
+ printf_filtered ("* ");
+ else
+ printf_filtered (" ");
+
+ printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
+
+ thread_switch (tp->pid);
+ print_stack_frame (selected_frame, -1, 0);
+ }
+
+ thread_switch (current_pid);
+ prune_threads ();
+}
+
+/* Switch from one thread to another. */
+
+static void
+thread_switch (pid)
+ int pid;
+{
+ if (pid == inferior_pid)
+ return;
+
+ inferior_pid = pid;
+ flush_cached_frames ();
+ registers_changed ();
+ stop_pc = read_pc();
+ 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;
+ int from_tty;
+{
+ int num;
+ struct thread_info *tp;
+
+ if (!tidstr)
+ 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);
+
+ if (!tp)
+ error ("Thread ID %d not known. Use the \"info threads\" command to\n\
+see the IDs of currently known threads.", num);
+
+ thread_switch (tp->pid);
+
+ printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
+ print_stack_frame (selected_frame, selected_frame_level, 1);
+}
+
+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_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/contrib/gdb/gdb/thread.h b/contrib/gdb/gdb/thread.h
new file mode 100644
index 0000000..6777887
--- /dev/null
+++ b/contrib/gdb/gdb/thread.h
@@ -0,0 +1,46 @@
+/* Multi-process/thread control defs for GDB, the GNU debugger.
+ Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993
+
+ Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef THREAD_H
+#define THREAD_H
+
+extern void init_thread_list PARAMS ((void));
+
+extern void add_thread PARAMS ((int pid));
+
+extern int in_thread_list PARAMS ((int pid));
+
+extern int pid_to_thread_id PARAMS ((int pid));
+
+extern int valid_thread_id PARAMS ((int thread));
+
+extern void load_infrun_state PARAMS ((int, CORE_ADDR *, CORE_ADDR *, char **,
+ int *, struct breakpoint **,
+ struct breakpoint **, CORE_ADDR *,
+ CORE_ADDR *, CORE_ADDR *, int *, int *));
+
+extern void save_infrun_state PARAMS ((int, CORE_ADDR, CORE_ADDR, char *,
+ int, struct breakpoint *,
+ struct breakpoint *, CORE_ADDR,
+ CORE_ADDR, CORE_ADDR, int, int));
+
+#endif /* THREAD_H */
diff --git a/contrib/gdb/gdb/top.c b/contrib/gdb/gdb/top.c
new file mode 100644
index 0000000..088bcd9
--- /dev/null
+++ b/contrib/gdb/gdb/top.c
@@ -0,0 +1,3557 @@
+/* Top level stuff for GDB, the GNU debugger.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdbcmd.h"
+#include "call-cmds.h"
+#include "symtab.h"
+#include "inferior.h"
+#include "signals.h"
+#include "target.h"
+#include "breakpoint.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "language.h"
+#include "terminal.h" /* For job_control. */
+#include "annotate.h"
+#include <setjmp.h>
+#include "top.h"
+
+/* readline include files */
+#include "readline.h"
+#include "history.h"
+
+/* readline defines this. */
+#undef savestring
+
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "gdb_string.h"
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#include <sys/param.h>
+#include "gdb_stat.h"
+#include <ctype.h>
+
+extern void initialize_targets PARAMS ((void));
+
+extern void initialize_utils PARAMS ((void));
+
+/* Prototypes for local functions */
+
+static char * line_completion_function PARAMS ((char *, int, char *, int));
+
+static char * readline_line_completion_function PARAMS ((char *, int));
+
+static void command_loop_marker PARAMS ((int));
+
+static void while_command PARAMS ((char *, int));
+
+static void if_command PARAMS ((char *, int));
+
+static struct command_line *
+build_command_line PARAMS ((enum command_control_type, char *));
+
+static struct command_line *
+get_command_line PARAMS ((enum command_control_type, char *));
+
+static void realloc_body_list PARAMS ((struct command_line *, int));
+
+static enum misc_command_type read_next_line PARAMS ((struct command_line **));
+
+static enum command_control_type
+recurse_read_control_structure PARAMS ((struct command_line *));
+
+static struct cleanup * setup_user_args PARAMS ((char *));
+
+static char * locate_arg PARAMS ((char *));
+
+static char * insert_args PARAMS ((char *));
+
+static void arg_cleanup PARAMS ((void));
+
+static void init_main PARAMS ((void));
+
+static void init_cmd_lists PARAMS ((void));
+
+static void float_handler PARAMS ((int));
+
+static void init_signals PARAMS ((void));
+
+static void set_verbose PARAMS ((char *, int, struct cmd_list_element *));
+
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+
+static void set_endian PARAMS ((char *, int));
+
+static void set_endian_big PARAMS ((char *, int));
+
+static void set_endian_little PARAMS ((char *, int));
+
+static void set_endian_auto PARAMS ((char *, int));
+
+static void show_endian PARAMS ((char *, int));
+
+#endif
+
+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 complete_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)))
+#endif
+
+/* Initialization file name for gdb. This is overridden in some configs. */
+
+#ifndef GDBINIT_FILENAME
+#define GDBINIT_FILENAME ".gdbinit"
+#endif
+char gdbinit[] = GDBINIT_FILENAME;
+
+int inhibit_gdbinit = 0;
+
+/* If nonzero, and GDB has been configured to be able to use windows,
+ attempt to open them upon startup. */
+
+int use_windows = 1;
+
+/* Version number of GDB, as a string. */
+
+extern char *version;
+
+/* Canonical host name as a string. */
+
+extern char *host_name;
+
+/* Canonical target name as a string. */
+
+extern char *target_name;
+
+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_elements. */
+
+/* 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;
+
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+/* Chain containing the \"set endian\" commands. */
+
+struct cmd_list_element *endianlist;
+#endif
+
+/* 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). */
+char gdb_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 *));
+
+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;
+
+/* Nonzero if the current command is modified by "server ". This
+ affects things like recording into the command history, comamnds
+ repeating on RETURN, etc. This is so a user interface (emacs, GUI,
+ whatever) can issue its own commands and also send along commands
+ from the user, and have the user not notice that the user interface
+ is issuing commands too. */
+int server_command;
+
+/* Baud rate specified for talking to serial target systems. Default
+ is left as -1, so targets can choose their own defaults. */
+/* FIXME: This means that "show remotebaud" and gr_files_info can print -1
+ or (unsigned int)-1. This is a Bad User Interface. */
+
+int baud_rate = -1;
+
+/* Non-zero tells remote* modules to output debugging info. */
+
+int remote_debug = 0;
+
+/* Level of control structure. */
+static int control_level;
+
+/* Structure for arguments to user defined functions. */
+#define MAXUSERARGS 10
+struct user_args
+{
+ struct user_args *next;
+ struct
+ {
+ char *arg;
+ int len;
+ } a[MAXUSERARGS];
+ int count;
+} *user_args;
+
+/* 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)
+#if !defined (USG)
+#define HAVE_SIGSETMASK 1
+#else
+#define HAVE_SIGSETMASK 0
+#endif
+#endif
+
+#if 0 == (HAVE_SIGSETMASK)
+#define sigsetmask(n)
+#endif
+
+/* Hooks for alternate command interfaces. */
+
+/* Called after most modules have been initialized, but before taking users
+ command file. */
+
+void (*init_ui_hook) PARAMS ((void));
+
+/* Called instead of command_loop at top level. Can be invoked via
+ return_to_top_level. */
+
+void (*command_loop_hook) PARAMS ((void));
+
+
+/* Called instead of fputs for all output. */
+
+void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, FILE *stream));
+
+/* Called when the target says something to the host, which may
+ want to appear in a different window. */
+
+void (*target_output_hook) PARAMS ((char *));
+
+/* Called from print_frame_info to list the line we stopped in. */
+
+void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, int line,
+ int stopline, int noerror));
+/* Replaces most of query. */
+
+int (*query_hook) PARAMS (());
+
+/* Called from gdb_flush to flush output. */
+
+void (*flush_hook) PARAMS ((FILE *stream));
+
+/* Called as appropriate to notify the interface of the specified breakpoint
+ conditions. */
+
+void (*create_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt));
+
+/* Called during long calculations to allow GUI to repair window damage, and to
+ check for stop buttons, etc... */
+
+void (*interactive_hook) PARAMS ((void));
+
+/* Called when the registers have changed, as a hint to a GUI
+ to minimize window update. */
+
+void (*registers_changed_hook) PARAMS ((void));
+
+/* Called when going to wait for the target. Usually allows the GUI to run
+ while waiting for target events. */
+
+int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status));
+
+/* Used by UI as a wrapper around command execution. May do various things
+ like enabling/disabling buttons, etc... */
+
+void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
+ int from_tty));
+
+
+/* Takes control from error (). Typically used to prevent longjmps out of the
+ middle of the GUI. Usually used in conjunction with a catch routine. */
+
+NORETURN void (*error_hook) PARAMS (()) ATTR_NORETURN;
+
+
+/* Where to go for return_to_top_level (RETURN_ERROR). */
+jmp_buf error_return;
+/* Where to go for return_to_top_level (RETURN_QUIT). */
+jmp_buf quit_return;
+
+/* Return for reason REASON. This generally gets back to the command
+ loop, but can be caught via catch_errors. */
+
+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);
+
+ if (annotation_level > 1)
+ switch (reason)
+ {
+ case RETURN_QUIT:
+ annotate_quit ();
+ break;
+ case RETURN_ERROR:
+ annotate_error ();
+ break;
+ }
+
+ (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;
+ char *saved_quit_pre_print;
+
+ saved_cleanup_chain = save_cleanups ();
+ saved_error_pre_print = error_pre_print;
+ saved_quit_pre_print = quit_pre_print;
+
+ if (mask & RETURN_MASK_ERROR)
+ {
+ memcpy ((char *)saved_error, (char *)error_return, sizeof (jmp_buf));
+ error_pre_print = errstring;
+ }
+ if (mask & RETURN_MASK_QUIT)
+ {
+ memcpy (saved_quit, quit_return, sizeof (jmp_buf));
+ quit_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);
+
+ if (mask & RETURN_MASK_ERROR)
+ {
+ memcpy (error_return, saved_error, sizeof (jmp_buf));
+ error_pre_print = saved_error_pre_print;
+ }
+ if (mask & RETURN_MASK_QUIT)
+ {
+ memcpy (quit_return, saved_quit, sizeof (jmp_buf));
+ quit_pre_print = saved_quit_pre_print;
+ }
+ 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;
+}
+
+/* Line number we are currently in in a file which is being sourced. */
+static int source_line_number;
+
+/* Name of the file we are sourcing. */
+static char *source_file_name;
+
+/* Buffer containing the error_pre_print used by the source stuff.
+ Malloc'd. */
+static char *source_error;
+static int source_error_allocated;
+
+/* Something to glom on to the start of error_pre_print if source_file_name
+ is set. */
+static char *source_pre_error;
+
+/* 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. */
+void
+read_command_file (stream)
+ FILE *stream;
+{
+ struct cleanup *cleanups;
+
+ cleanups = make_cleanup (source_cleanup, instream);
+ instream = stream;
+ command_loop ();
+ do_cleanups (cleanups);
+}
+
+extern void init_proc ();
+
+void (*pre_init_ui_hook) PARAMS ((void));
+
+void
+gdb_init ()
+{
+ if (pre_init_ui_hook)
+ pre_init_ui_hook ();
+
+ /* Run the init function of each source file */
+
+ getcwd (gdb_dirbuf, sizeof (gdb_dirbuf));
+ current_directory = gdb_dirbuf;
+
+ init_cmd_lists (); /* This needs to be done first */
+ initialize_targets (); /* Setup target_terminal macros for utils.c */
+ initialize_utils (); /* Make errors and warnings possible */
+ initialize_all_files ();
+ init_main (); /* But that omits this file! Do it now */
+ init_signals ();
+
+ init_proc ();
+
+ /* 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. */
+
+ if (init_ui_hook)
+ init_ui_hook ();
+}
+
+/* Allocate, initialize a new command line structure for one of the
+ control commands (if/while). */
+
+static struct command_line *
+build_command_line (type, args)
+ enum command_control_type type;
+ char *args;
+{
+ struct command_line *cmd;
+
+ if (args == NULL)
+ error ("if/while commands require arguments.\n");
+
+ cmd = (struct command_line *)xmalloc (sizeof (struct command_line));
+ cmd->next = NULL;
+ cmd->control_type = type;
+
+ cmd->body_count = 1;
+ cmd->body_list
+ = (struct command_line **)xmalloc (sizeof (struct command_line *)
+ * cmd->body_count);
+ memset (cmd->body_list, 0, sizeof (struct command_line *) * cmd->body_count);
+ cmd->line = savestring (args, strlen (args));
+ return cmd;
+}
+
+/* Build and return a new command structure for the control commands
+ such as "if" and "while". */
+
+static struct command_line *
+get_command_line (type, arg)
+ enum command_control_type type;
+ char *arg;
+{
+ struct command_line *cmd;
+ struct cleanup *old_chain = NULL;
+
+ /* Allocate and build a new command line structure. */
+ cmd = build_command_line (type, arg);
+
+ old_chain = make_cleanup (free_command_lines, &cmd);
+
+ /* Read in the body of this command. */
+ if (recurse_read_control_structure (cmd) == invalid_control)
+ {
+ warning ("error reading in control structure\n");
+ do_cleanups (old_chain);
+ return NULL;
+ }
+
+ discard_cleanups (old_chain);
+ return cmd;
+}
+
+/* Recursively print a command (including full control structures). */
+void
+print_command_line (cmd, depth)
+ struct command_line *cmd;
+ unsigned int depth;
+{
+ unsigned int i;
+
+ if (depth)
+ {
+ for (i = 0; i < depth; i++)
+ fputs_filtered (" ", gdb_stdout);
+ }
+
+ /* A simple command, print it and return. */
+ if (cmd->control_type == simple_control)
+ {
+ fputs_filtered (cmd->line, gdb_stdout);
+ fputs_filtered ("\n", gdb_stdout);
+ return;
+ }
+
+ /* loop_continue to jump to the start of a while loop, print it
+ and return. */
+ if (cmd->control_type == continue_control)
+ {
+ fputs_filtered ("loop_continue\n", gdb_stdout);
+ return;
+ }
+
+ /* loop_break to break out of a while loop, print it and return. */
+ if (cmd->control_type == break_control)
+ {
+ fputs_filtered ("loop_break\n", gdb_stdout);
+ return;
+ }
+
+ /* A while command. Recursively print its subcommands before returning. */
+ if (cmd->control_type == while_control)
+ {
+ struct command_line *list;
+ fputs_filtered ("while ", gdb_stdout);
+ fputs_filtered (cmd->line, gdb_stdout);
+ fputs_filtered ("\n", gdb_stdout);
+ list = *cmd->body_list;
+ while (list)
+ {
+ print_command_line (list, depth + 1);
+ list = list->next;
+ }
+ }
+
+ /* An if command. Recursively print both arms before returning. */
+ if (cmd->control_type == if_control)
+ {
+ fputs_filtered ("if ", gdb_stdout);
+ fputs_filtered (cmd->line, gdb_stdout);
+ fputs_filtered ("\n", gdb_stdout);
+ /* The true arm. */
+ print_command_line (cmd->body_list[0], depth + 1);
+
+ /* Show the false arm if it exists. */
+ if (cmd->body_count == 2)
+ {
+ if (depth)
+ {
+ for (i = 0; i < depth; i++)
+ fputs_filtered (" ", gdb_stdout);
+ }
+ fputs_filtered ("else\n", gdb_stdout);
+ print_command_line (cmd->body_list[1], depth + 1);
+ }
+ if (depth)
+ {
+ for (i = 0; i < depth; i++)
+ fputs_filtered (" ", gdb_stdout);
+ }
+ fputs_filtered ("end\n", gdb_stdout);
+ }
+}
+
+/* Execute the command in CMD. */
+
+enum command_control_type
+execute_control_command (cmd)
+ struct command_line *cmd;
+{
+ struct expression *expr;
+ struct command_line *current;
+ struct cleanup *old_chain = 0;
+ value_ptr val;
+ int loop;
+ enum command_control_type ret;
+ char *new_line;
+
+ switch (cmd->control_type)
+ {
+ case simple_control:
+ /* A simple command, execute it and return. */
+ new_line = insert_args (cmd->line);
+ if (!new_line)
+ return invalid_control;
+ old_chain = make_cleanup (free_current_contents, &new_line);
+ execute_command (new_line, 0);
+ ret = cmd->control_type;
+ break;
+
+ case continue_control:
+ case break_control:
+ /* Return for "continue", and "break" so we can either
+ continue the loop at the top, or break out. */
+ ret = cmd->control_type;
+ break;
+
+ case while_control:
+ {
+ /* Parse the loop control expression for the while statement. */
+ new_line = insert_args (cmd->line);
+ if (!new_line)
+ return invalid_control;
+ old_chain = make_cleanup (free_current_contents, &new_line);
+ expr = parse_expression (new_line);
+ make_cleanup (free_current_contents, &expr);
+
+ ret = simple_control;
+ loop = 1;
+
+ /* Keep iterating so long as the expression is true. */
+ while (loop == 1)
+ {
+ /* Evaluate the expression. */
+ val = evaluate_expression (expr);
+
+ /* If the value is false, then break out of the loop. */
+ if (!value_true (val))
+ break;
+
+ /* Execute the body of the while statement. */
+ current = *cmd->body_list;
+ while (current)
+ {
+ ret = execute_control_command (current);
+
+ /* If we got an error, or a "break" command, then stop
+ looping. */
+ if (ret == invalid_control || ret == break_control)
+ {
+ loop = 0;
+ break;
+ }
+
+ /* If we got a "continue" command, then restart the loop
+ at this point. */
+ if (ret == continue_control)
+ break;
+
+ /* Get the next statement. */
+ current = current->next;
+ }
+ }
+
+ /* Reset RET so that we don't recurse the break all the way down. */
+ if (ret == break_control)
+ ret = simple_control;
+
+ break;
+ }
+
+ case if_control:
+ {
+ new_line = insert_args (cmd->line);
+ if (!new_line)
+ return invalid_control;
+ old_chain = make_cleanup (free_current_contents, &new_line);
+ /* Parse the conditional for the if statement. */
+ expr = parse_expression (new_line);
+ make_cleanup (free_current_contents, &expr);
+
+ current = NULL;
+ ret = simple_control;
+
+ /* Evaluate the conditional. */
+ val = evaluate_expression (expr);
+
+ /* Choose which arm to take commands from based on the value of the
+ conditional expression. */
+ if (value_true (val))
+ current = *cmd->body_list;
+ else if (cmd->body_count == 2)
+ current = *(cmd->body_list + 1);
+
+ /* Execute commands in the given arm. */
+ while (current)
+ {
+ ret = execute_control_command (current);
+
+ /* If we got an error, get out. */
+ if (ret != simple_control)
+ break;
+
+ /* Get the next statement in the body. */
+ current = current->next;
+ }
+
+ break;
+ }
+
+ default:
+ warning ("Invalid control type in command structure.");
+ return invalid_control;
+ }
+
+ if (old_chain)
+ do_cleanups (old_chain);
+
+ return ret;
+}
+
+/* "while" command support. Executes a body of statements while the
+ loop condition is nonzero. */
+
+static void
+while_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct command_line *command = NULL;
+
+ control_level = 1;
+ command = get_command_line (while_control, arg);
+
+ if (command == NULL)
+ return;
+
+ execute_control_command (command);
+ free_command_lines (&command);
+}
+
+/* "if" command support. Execute either the true or false arm depending
+ on the value of the if conditional. */
+
+static void
+if_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ struct command_line *command = NULL;
+
+ control_level = 1;
+ command = get_command_line (if_control, arg);
+
+ if (command == NULL)
+ return;
+
+ execute_control_command (command);
+ free_command_lines (&command);
+}
+
+/* Cleanup */
+static void
+arg_cleanup ()
+{
+ struct user_args *oargs = user_args;
+ if (!user_args)
+ fatal ("Internal error, arg_cleanup called with no user args.\n");
+
+ user_args = user_args->next;
+ free (oargs);
+}
+
+/* Bind the incomming arguments for a user defined command to
+ $arg0, $arg1 ... $argMAXUSERARGS. */
+
+static struct cleanup *
+setup_user_args (p)
+ char *p;
+{
+ struct user_args *args;
+ struct cleanup *old_chain;
+ unsigned int arg_count = 0;
+
+ args = (struct user_args *)xmalloc (sizeof (struct user_args));
+ memset (args, 0, sizeof (struct user_args));
+
+ args->next = user_args;
+ user_args = args;
+
+ old_chain = make_cleanup (arg_cleanup, 0);
+
+ if (p == NULL)
+ return old_chain;
+
+ while (*p)
+ {
+ char *start_arg;
+
+ if (arg_count >= MAXUSERARGS)
+ {
+ error ("user defined function may only have %d arguments.\n",
+ MAXUSERARGS);
+ return old_chain;
+ }
+
+ /* Strip whitespace. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* P now points to an argument. */
+ start_arg = p;
+ user_args->a[arg_count].arg = p;
+
+ /* Get to the end of this argument. */
+ while (*p && *p != ' ' && *p != '\t')
+ p++;
+
+ user_args->a[arg_count].len = p - start_arg;
+ arg_count++;
+ user_args->count++;
+ }
+ return old_chain;
+}
+
+/* Given character string P, return a point to the first argument ($arg),
+ or NULL if P contains no arguments. */
+
+static char *
+locate_arg (p)
+ char *p;
+{
+ while ((p = strchr (p, '$')))
+ {
+ if (strncmp (p, "$arg", 4) == 0 && isdigit (p[4]))
+ return p;
+ p++;
+ }
+ return NULL;
+}
+
+/* Insert the user defined arguments stored in user_arg into the $arg
+ arguments found in line, with the updated copy being placed into nline. */
+
+static char *
+insert_args (line)
+ char *line;
+{
+ char *p, *save_line, *new_line;
+ unsigned len, i;
+
+ /* First we need to know how much memory to allocate for the new line. */
+ save_line = line;
+ len = 0;
+ while ((p = locate_arg (line)))
+ {
+ len += p - line;
+ i = p[4] - '0';
+
+ if (i >= user_args->count)
+ {
+ error ("Missing argument %d in user function.\n", i);
+ return NULL;
+ }
+ len += user_args->a[i].len;
+ line = p + 5;
+ }
+
+ /* Don't forget the tail. */
+ len += strlen (line);
+
+ /* Allocate space for the new line and fill it in. */
+ new_line = (char *)xmalloc (len + 1);
+ if (new_line == NULL)
+ return NULL;
+
+ /* Restore pointer to beginning of old line. */
+ line = save_line;
+
+ /* Save pointer to beginning of new line. */
+ save_line = new_line;
+
+ while ((p = locate_arg (line)))
+ {
+ int i, len;
+
+ memcpy (new_line, line, p - line);
+ new_line += p - line;
+ i = p[4] - '0';
+
+ len = user_args->a[i].len;
+ if (len)
+ {
+ memcpy (new_line, user_args->a[i].arg, len);
+ new_line += len;
+ }
+ line = p + 5;
+ }
+ /* Don't forget the tail. */
+ strcpy (new_line, line);
+
+ /* Return a pointer to the beginning of the new line. */
+ return save_line;
+}
+
+void
+execute_user_command (c, args)
+ struct cmd_list_element *c;
+ char *args;
+{
+ register struct command_line *cmdlines;
+ struct cleanup *old_chain;
+ enum command_control_type ret;
+
+ old_chain = setup_user_args (args);
+
+ 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)
+ {
+ ret = execute_control_command (cmdlines);
+ if (ret != simple_control && ret != break_control)
+ {
+ warning ("Error in control structure.\n");
+ break;
+ }
+ 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;
+ extern FILE *serial_logfp;
+
+ free_all_values ();
+
+ /* This can happen when command_line_input hits end of file. */
+ if (p == NULL)
+ return;
+
+ if (serial_logfp != NULL)
+ serial_log_command (p);
+
+ 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;
+
+ /* Clear off trailing whitespace, except for set and complete command. */
+ if (arg && c->type != set_cmd && c->function.cfunc != complete_command)
+ {
+ p = arg + strlen (arg) - 1;
+ while (p >= arg && (*p == ' ' || *p == '\t'))
+ p--;
+ *(p + 1) = '\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 if (call_command_hook)
+ call_command_hook (c, arg, from_tty & caution);
+ 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;
+{
+}
+
+/* Read commands from `instream' and execute them
+ until end of file or error reading instream. */
+
+void
+command_loop ()
+{
+ struct cleanup *old_chain;
+ char *command;
+ int stdin_is_tty = ISATTY (stdin);
+ long time_at_cmd_start;
+#ifdef HAVE_SBRK
+ long space_at_cmd_start;
+#endif
+ extern int display_time;
+ extern int display_space;
+
+ 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, "prompt");
+ if (command == 0)
+ return;
+
+ time_at_cmd_start = get_run_time ();
+
+ if (display_space)
+ {
+#ifdef HAVE_SBRK
+ extern char **environ;
+ char *lim = (char *) sbrk (0);
+
+ space_at_cmd_start = (long) (lim - (char *) &environ);
+#endif
+ }
+
+ execute_command (command, instream == stdin);
+ /* Do any commands attached to breakpoint we stopped at. */
+ bpstat_do_actions (&stop_bpstat);
+ do_cleanups (old_chain);
+
+ if (display_time)
+ {
+ long cmd_time = get_run_time () - time_at_cmd_start;
+
+ printf_unfiltered ("Command execution time: %ld.%06ld\n",
+ cmd_time / 1000000, cmd_time % 1000000);
+ }
+
+ if (display_space)
+ {
+#ifdef HAVE_SBRK
+ extern char **environ;
+ char *lim = (char *) sbrk (0);
+ long space_now = lim - (char *) &environ;
+ long space_diff = space_now - space_at_cmd_start;
+
+ printf_unfiltered ("Space used: %ld (%c%ld for this command)\n",
+ space_now,
+ (space_diff >= 0 ? '+' : '-'),
+ space_diff);
+#endif
+ }
+ }
+}
+
+/* Commands call this if they do not want to be repeated by null lines. */
+
+void
+dont_repeat ()
+{
+ if (server_command)
+ return;
+
+ /* 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_unfiltered (prrompt, gdb_stdout);
+#ifdef MPW
+ /* Move to a new line so the entered line doesn't have a prompt
+ on the front of it. */
+ fputs_unfiltered ("\n", gdb_stdout);
+#endif /* MPW */
+ gdb_flush (gdb_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/we" "ird" (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.
+ line_completion 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 the caller's idea of the "word" we are looking at.
+
+ 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.
+
+ LINE_BUFFER is available to be looked at; it contains the entire text
+ of the line. POINT is the offset in that line of the cursor. You
+ should pretend that the line ends at POINT.
+
+ Returns NULL if there are no more completions, else a pointer to a string
+ which is a possible completion, it is the caller's responsibility to
+ free the string. */
+
+static char *
+line_completion_function (text, matches, line_buffer, point)
+ char *text;
+ int matches;
+ char *line_buffer;
+ int point;
+{
+ 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;
+
+ 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 (point + 1);
+ p = tmp_command;
+
+ strncpy (tmp_command, line_buffer, point);
+ tmp_command[point] = '\0';
+ /* Since text always contains some number of characters leading up
+ to point, we can find the equivalent position in tmp_command
+ by subtracting that many characters from the end of tmp_command. */
+ word = tmp_command + point - strlen (text);
+
+ if (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 + 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 + 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 if (c->enums)
+ {
+ list = complete_on_enum (c->enums, p, word);
+ 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 if (c->enums)
+ {
+ list = complete_on_enum (c->enums, p, word);
+ }
+ 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);
+}
+
+/* Line completion interface function for readline. */
+
+static char *
+readline_line_completion_function (text, matches)
+ char *text;
+ int matches;
+{
+ return line_completion_function (text, matches, rl_line_buffer, rl_point);
+}
+
+/* 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_unfiltered ("%s", prompt);
+ gdb_flush (gdb_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 SIGTRAP was set to SIG_IGN, then the SIG_IGN will get passed
+ to the inferior and breakpoints will be ignored. */
+#ifdef SIGTRAP
+ signal (SIGTRAP, SIG_DFL);
+#endif
+
+ /* 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, annotation_suffix)
+ char *prrompt;
+ int repeat;
+ char *annotation_suffix;
+{
+ static char *linebuffer = 0;
+ static unsigned linelength = 0;
+ register char *p;
+ char *p1;
+ char *rl;
+ char *local_prompt = prrompt;
+ char *nline;
+ char got_eof = 0;
+
+ /* The annotation suffix must be non-NULL. */
+ if (annotation_suffix == NULL)
+ annotation_suffix = "";
+
+ if (annotation_level > 1 && instream == stdin)
+ {
+ local_prompt = alloca ((prrompt == NULL ? 0 : strlen (prrompt))
+ + strlen (annotation_suffix) + 40);
+ if (prrompt == NULL)
+ local_prompt[0] = '\0';
+ else
+ strcpy (local_prompt, prrompt);
+ strcat (local_prompt, "\n\032\032");
+ strcat (local_prompt, annotation_suffix);
+ strcat (local_prompt, "\n");
+ }
+
+ 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)
+ {
+ /* Make sure that all output has been output. Some machines may let
+ you get away with leaving out some of the gdb_flush, but not all. */
+ wrap_here ("");
+ gdb_flush (gdb_stdout);
+ gdb_flush (gdb_stderr);
+
+ if (source_file_name != NULL)
+ {
+ ++source_line_number;
+ sprintf (source_error,
+ "%s%s:%d: Error in sourced command file:\n",
+ source_pre_error,
+ source_file_name,
+ source_line_number);
+ error_pre_print = source_error;
+ }
+
+ if (annotation_level > 1 && instream == stdin)
+ {
+ printf_unfiltered ("\n\032\032pre-");
+ printf_unfiltered (annotation_suffix);
+ printf_unfiltered ("\n");
+ }
+
+ /* 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 (annotation_level > 1 && instream == stdin)
+ {
+ printf_unfiltered ("\n\032\032post-");
+ printf_unfiltered (annotation_suffix);
+ printf_unfiltered ("\n");
+ }
+
+ 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;
+
+#define SERVER_COMMAND_LENGTH 7
+ server_command =
+ (p - linebuffer > SERVER_COMMAND_LENGTH)
+ && STREQN (linebuffer, "server ", SERVER_COMMAND_LENGTH);
+ if (server_command)
+ {
+ /* Note that we don't set `line'. Between this and the check in
+ dont_repeat, this insures that repeating will still do the
+ right thing. */
+ *p = '\0';
+ return linebuffer + SERVER_COMMAND_LENGTH;
+ }
+
+ /* 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_unfiltered ("%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, annotation_suffix);
+ }
+ 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 && p == linebuffer)
+ return line;
+ for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++) ;
+ if (repeat && !*p1)
+ return line;
+
+ *p = 0;
+
+ /* Add line to history if appropriate. */
+ if (instream == stdin
+ && ISATTY (stdin) && *linebuffer)
+ add_history (linebuffer);
+
+ /* Note: lines consisting solely 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. */
+ if (*p1 == '#')
+ *p1 = '\0'; /* Found a comment. */
+
+ /* Save into global buffer if appropriate. */
+ if (repeat)
+ {
+ if (linelength > linesize)
+ {
+ line = xrealloc (line, linelength);
+ linesize = linelength;
+ }
+ strcpy (line, linebuffer);
+ return line;
+ }
+
+ return linebuffer;
+}
+
+
+/* Expand the body_list of COMMAND so that it can hold NEW_LENGTH
+ code bodies. This is typically used when we encounter an "else"
+ clause for an "if" command. */
+
+static void
+realloc_body_list (command, new_length)
+ struct command_line *command;
+ int new_length;
+{
+ int n;
+ struct command_line **body_list;
+
+ n = command->body_count;
+
+ /* Nothing to do? */
+ if (new_length <= n)
+ return;
+
+ body_list = (struct command_line **)
+ xmalloc (sizeof (struct command_line *) * new_length);
+
+ memcpy (body_list, command->body_list, sizeof (struct command_line *) * n);
+
+ free (command->body_list);
+ command->body_list = body_list;
+ command->body_count = new_length;
+}
+
+/* Read one line from the input stream. If the command is an "else" or
+ "end", return such an indication to the caller. */
+
+static enum misc_command_type
+read_next_line (command)
+ struct command_line **command;
+{
+ char *p, *p1, *prompt_ptr, control_prompt[256];
+ int i = 0;
+
+ if (control_level >= 254)
+ error ("Control nesting too deep!\n");
+
+ /* Set a prompt based on the nesting of the control commands. */
+ if (instream == stdin)
+ {
+ for (i = 0; i < control_level; i++)
+ control_prompt[i] = ' ';
+ control_prompt[i] = '>';
+ control_prompt[i+1] = '\0';
+ prompt_ptr = (char *)&control_prompt[0];
+ }
+ else
+ prompt_ptr = NULL;
+
+ p = command_line_input (prompt_ptr, instream == stdin, "commands");
+
+ /* Not sure what to do here. */
+ if (p == NULL)
+ return end_command;
+
+ /* Strip leading and trailing whitespace. */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ p1 = p + strlen (p);
+ while (p1 != p && (p1[-1] == ' ' || p1[-1] == '\t'))
+ p1--;
+
+ /* Blanks and comments don't really do anything, but we need to
+ distinguish them from else, end and other commands which can be
+ executed. */
+ if (p1 == p || p[0] == '#')
+ return nop_command;
+
+ /* Is this the end of a simple, while, or if control structure? */
+ if (p1 - p == 3 && !strncmp (p, "end", 3))
+ return end_command;
+
+ /* Is the else clause of an if control structure? */
+ if (p1 - p == 4 && !strncmp (p, "else", 4))
+ return else_command;
+
+ /* Check for while, if, break, continue, etc and build a new command
+ line structure for them. */
+ if (p1 - p > 5 && !strncmp (p, "while", 5))
+ *command = build_command_line (while_control, p + 6);
+ else if (p1 - p > 2 && !strncmp (p, "if", 2))
+ *command = build_command_line (if_control, p + 3);
+ else if (p1 - p == 5 && !strncmp (p, "loop_break", 5))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = break_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else if (p1 - p == 8 && !strncmp (p, "loop_continue", 8))
+ {
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = NULL;
+ (*command)->control_type = continue_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+ else
+ {
+ /* A normal command. */
+ *command = (struct command_line *)
+ xmalloc (sizeof (struct command_line));
+ (*command)->next = NULL;
+ (*command)->line = savestring (p, p1 - p);
+ (*command)->control_type = simple_control;
+ (*command)->body_count = 0;
+ (*command)->body_list = NULL;
+ }
+
+ /* Nothing special. */
+ return ok_command;
+}
+
+/* Recursively read in the control structures and create a command_line
+ tructure from them.
+
+ The parent_control parameter is the control structure in which the
+ following commands are nested. */
+
+static enum command_control_type
+recurse_read_control_structure (current_cmd)
+ struct command_line *current_cmd;
+{
+ int current_body, i;
+ enum misc_command_type val;
+ enum command_control_type ret;
+ struct command_line **body_ptr, *child_tail, *next;
+
+ child_tail = NULL;
+ current_body = 1;
+
+ /* Sanity checks. */
+ if (current_cmd->control_type == simple_control)
+ {
+ error ("Recursed on a simple control type\n");
+ return invalid_control;
+ }
+
+ if (current_body > current_cmd->body_count)
+ {
+ error ("Allocated body is smaller than this command type needs\n");
+ return invalid_control;
+ }
+
+ /* Read lines from the input stream and build control structures. */
+ while (1)
+ {
+ dont_repeat ();
+
+ next = NULL;
+ val = read_next_line (&next);
+
+ /* Just skip blanks and comments. */
+ if (val == nop_command)
+ continue;
+
+ if (val == end_command)
+ {
+ if (current_cmd->control_type == while_control
+ || current_cmd->control_type == if_control)
+ {
+ /* Success reading an entire control structure. */
+ ret = simple_control;
+ break;
+ }
+ else
+ {
+ ret = invalid_control;
+ break;
+ }
+ }
+
+ /* Not the end of a control structure. */
+ if (val == else_command)
+ {
+ if (current_cmd->control_type == if_control
+ && current_body == 1)
+ {
+ realloc_body_list (current_cmd, 2);
+ current_body = 2;
+ child_tail = NULL;
+ continue;
+ }
+ else
+ {
+ ret = invalid_control;
+ break;
+ }
+ }
+
+ if (child_tail)
+ {
+ child_tail->next = next;
+ }
+ else
+ {
+ body_ptr = current_cmd->body_list;
+ for (i = 1; i < current_body; i++)
+ body_ptr++;
+
+ *body_ptr = next;
+
+ }
+
+ child_tail = next;
+
+ /* If the latest line is another control structure, then recurse
+ on it. */
+ if (next->control_type == while_control
+ || next->control_type == if_control)
+ {
+ control_level++;
+ ret = recurse_read_control_structure (next);
+ control_level--;
+
+ if (ret != simple_control)
+ break;
+ }
+ }
+
+ dont_repeat ();
+
+ return ret;
+}
+
+
+/* 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 *head, *tail, *next;
+ struct cleanup *old_chain;
+ enum command_control_type ret;
+ enum misc_command_type val;
+
+ head = tail = NULL;
+ old_chain = NULL;
+
+ while (1)
+ {
+ val = read_next_line (&next);
+
+ /* Ignore blank lines or comments. */
+ if (val == nop_command)
+ continue;
+
+ if (val == end_command)
+ {
+ ret = simple_control;
+ break;
+ }
+
+ if (val != ok_command)
+ {
+ ret = invalid_control;
+ break;
+ }
+
+ if (next->control_type == while_control
+ || next->control_type == if_control)
+ {
+ control_level++;
+ ret = recurse_read_control_structure (next);
+ control_level--;
+
+ if (ret == invalid_control)
+ break;
+ }
+
+ if (tail)
+ {
+ tail->next = next;
+ }
+ else
+ {
+ head = next;
+ old_chain = make_cleanup (free_command_lines, &head);
+ }
+ tail = next;
+ }
+
+ dont_repeat ();
+
+ if (head)
+ {
+ if (ret != invalid_control)
+ {
+ discard_cleanups (old_chain);
+ return head;
+ }
+ else
+ do_cleanups (old_chain);
+ }
+
+ return NULL;
+}
+
+/* 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;
+ struct command_line **blist;
+ int i;
+
+ while (l)
+ {
+ if (l->body_count > 0)
+ {
+ blist = l->body_list;
+ for (i = 0; i < l->body_count; i++, blist++)
+ free_command_lines (blist);
+ }
+ 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_unfiltered ("\"info\" must be followed by the name of an info command.\n");
+ help_list (infolist, "info ", -1, gdb_stdout);
+}
+
+/* The "complete" command is used by Emacs to implement completion. */
+
+/* ARGSUSED */
+static void
+complete_command (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ int i;
+ int argpoint;
+ char *completion;
+
+ dont_repeat ();
+
+ if (arg == NULL)
+ arg = "";
+ argpoint = strlen (arg);
+
+ for (completion = line_completion_function (arg, i = 0, arg, argpoint);
+ completion;
+ completion = line_completion_function (arg, ++i, arg, argpoint))
+ {
+ printf_unfiltered ("%s\n", completion);
+ free (completion);
+ }
+}
+
+/* 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, gdb_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 != '-' && *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? "))
+ 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_unfiltered ("Type commands for definition of \"%s\".\n\
+End with a line saying just \"end\".\n", comname);
+ gdb_flush (gdb_stdout);
+ }
+
+ control_level = 0;
+ 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_unfiltered ("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);
+}
+
+void
+print_gnu_advertisement ()
+{
+ printf_unfiltered ("\
+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\
+");
+}
+
+void
+print_gdb_version (stream)
+ GDB_FILE *stream;
+{
+ fprintf_filtered (stream, "\
+GDB %s (%s", version, host_name);
+
+ if (!STREQ (host_name, target_name))
+ fprintf_filtered (stream, " --target %s", target_name);
+
+ fprintf_filtered (stream, "), ");
+ wrap_here("");
+ fprintf_filtered (stream, "Copyright 1996 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 (gdb_stdout);
+ printf_filtered ("\n");
+ immediate_quit--;
+}
+
+/* xgdb calls this to reprint the usual GDB prompt. Obsolete now that xgdb
+ is obsolete. */
+
+void
+print_prompt ()
+{
+ printf_unfiltered ("%s", prompt);
+ gdb_flush (gdb_stdout);
+}
+
+void
+quit_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ int exit_code = 0;
+
+ /* An optional expression may be used to cause gdb to terminate with the
+ value of that expression. */
+ if (args)
+ {
+ value_ptr val = parse_and_eval (args);
+
+ exit_code = (int) value_as_long (val);
+ }
+
+ 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.");
+ }
+ }
+ /* UDI wants this, to kill the TIP. */
+ target_close (1);
+
+ /* Save the history information if it is appropriate to do so. */
+ if (write_history_p && history_filename)
+ write_history (history_filename);
+
+ exit (exit_code);
+}
+
+/* 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 ()
+{
+ 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 (gdb_dirbuf, sizeof (gdb_dirbuf));
+
+ if (!STREQ (gdb_dirbuf, current_directory))
+ printf_unfiltered ("Working directory %s\n (canonically %s).\n",
+ current_directory, gdb_dirbuf);
+ else
+ printf_unfiltered ("Working directory %s.\n", current_directory);
+}
+
+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 && SLASH_P(dir[len-1])));
+ if (ROOTED_P(dir))
+ current_directory = dir;
+ else
+ {
+ if (SLASH_P (current_directory[0]) && current_directory[1] == '\0')
+ current_directory = concat (current_directory, dir, NULL);
+ else
+ current_directory = concat (current_directory, SLASH_STRING, dir, NULL);
+ free (dir);
+ }
+
+ /* Now simplify any occurrences of `.' and `..' in the pathname. */
+
+ found_real_path = 0;
+ for (p = current_directory; *p;)
+ {
+ if (SLASH_P (p[0]) && p[1] == '.' && (p[2] == 0 || SLASH_P (p[2])))
+ strcpy (p, p + 2);
+ else if (SLASH_P (p[0]) && p[1] == '.' && p[2] == '.'
+ && (p[3] == 0 || SLASH_P (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 && ! SLASH_P (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);
+}
+
+struct source_cleanup_lines_args {
+ int old_line;
+ char *old_file;
+ char *old_pre_error;
+ char *old_error_pre_print;
+};
+
+static void
+source_cleanup_lines (args)
+ PTR args;
+{
+ struct source_cleanup_lines_args *p =
+ (struct source_cleanup_lines_args *)args;
+ source_line_number = p->old_line;
+ source_file_name = p->old_file;
+ source_pre_error = p->old_pre_error;
+ error_pre_print = p->old_error_pre_print;
+}
+
+/* ARGSUSED */
+void
+source_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ FILE *stream;
+ struct cleanup *old_cleanups;
+ char *file = args;
+ struct source_cleanup_lines_args old_lines;
+ int needed_length;
+
+ if (file == NULL)
+ {
+ error ("source command requires pathname of file to source.");
+ }
+
+ file = tilde_expand (file);
+ old_cleanups = make_cleanup (free, file);
+
+ stream = fopen (file, FOPEN_RT);
+ if (stream == 0)
+ perror_with_name (file);
+
+ make_cleanup (fclose, stream);
+
+ old_lines.old_line = source_line_number;
+ old_lines.old_file = source_file_name;
+ old_lines.old_pre_error = source_pre_error;
+ old_lines.old_error_pre_print = error_pre_print;
+ make_cleanup (source_cleanup_lines, &old_lines);
+ source_line_number = 0;
+ source_file_name = file;
+ source_pre_error = error_pre_print == NULL ? "" : error_pre_print;
+ source_pre_error = savestring (source_pre_error, strlen (source_pre_error));
+ make_cleanup (free, source_pre_error);
+ /* This will get set every time we read a line. So it won't stay "" for
+ long. */
+ error_pre_print = "";
+
+ needed_length = strlen (source_file_name) + strlen (source_pre_error) + 80;
+ if (source_error_allocated < needed_length)
+ {
+ source_error_allocated *= 2;
+ if (source_error_allocated < needed_length)
+ source_error_allocated = needed_length;
+ if (source_error == NULL)
+ source_error = xmalloc (source_error_allocated);
+ else
+ source_error = xrealloc (source_error, source_error_allocated);
+ }
+
+ read_command_file (stream);
+
+ do_cleanups (old_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 ("");
+ gdb_flush (gdb_stdout);
+}
+
+/* ARGSUSED */
+static void
+dont_repeat_command (ignored, from_tty)
+ char *ignored;
+ int from_tty;
+{
+ *line = 0; /* Can't call dont_repeat here because we're not
+ necessarily reading from stdin. */
+}
+
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+
+/* Functions to manipulate the endianness of the target. */
+
+#ifndef TARGET_BYTE_ORDER_DEFAULT
+#define TARGET_BYTE_ORDER_DEFAULT BIG_ENDIAN
+#endif
+
+int target_byte_order = TARGET_BYTE_ORDER_DEFAULT;
+
+static int target_byte_order_auto = 1;
+
+/* Called if the user enters ``set endian'' without an argument. */
+static void
+set_endian (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ printf_unfiltered ("\"set endian\" must be followed by \"auto\", \"big\" or \"little\".\n");
+ show_endian (args, from_tty);
+}
+
+/* Called by ``set endian big''. */
+static void
+set_endian_big (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ target_byte_order = BIG_ENDIAN;
+ target_byte_order_auto = 0;
+}
+
+/* Called by ``set endian little''. */
+static void
+set_endian_little (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ target_byte_order = LITTLE_ENDIAN;
+ target_byte_order_auto = 0;
+}
+
+/* Called by ``set endian auto''. */
+static void
+set_endian_auto (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ target_byte_order_auto = 1;
+}
+
+/* Called by ``show endian''. */
+static void
+show_endian (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ const char *msg =
+ (target_byte_order_auto
+ ? "The target endianness is set automatically (currently %s endian)\n"
+ : "The target is assumed to be %s endian\n");
+ printf_unfiltered ((char *) msg, TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
+}
+
+#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
+
+/* Set the endianness from a BFD. */
+void
+set_endian_from_file (abfd)
+ bfd *abfd;
+{
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+ int want;
+
+ if (bfd_big_endian (abfd))
+ want = BIG_ENDIAN;
+ else
+ want = LITTLE_ENDIAN;
+ if (target_byte_order_auto)
+ target_byte_order = want;
+ else if (target_byte_order != want)
+ warning ("%s endian file does not match %s endian target.",
+ want == BIG_ENDIAN ? "big" : "little",
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
+
+#else /* ! defined (TARGET_BYTE_ORDER_SELECTABLE) */
+
+ if (bfd_big_endian (abfd)
+ ? TARGET_BYTE_ORDER != BIG_ENDIAN
+ : TARGET_BYTE_ORDER == BIG_ENDIAN)
+ warning ("%s endian file does not match %s endian target.",
+ bfd_big_endian (abfd) ? "big" : "little",
+ TARGET_BYTE_ORDER == BIG_ENDIAN ? "big" : "little");
+
+#endif /* ! defined (TARGET_BYTE_ORDER_SELECTABLE) */
+}
+
+/* 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 HIST_ENTRY *history_get PARAMS ((int));
+
+ /* 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 <exp>" should print around command number <exp>. */
+ 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_unfiltered ("\"set history\" must be followed by the name of a history subcommand.\n");
+ help_list (sethistlist, "set history ", -1, gdb_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.");
+}
+
+
+static void
+init_cmd_lists ()
+{
+ cmdlist = NULL;
+ infolist = NULL;
+ enablelist = NULL;
+ disablelist = NULL;
+ deletelist = NULL;
+ enablebreaklist = NULL;
+ setlist = NULL;
+ unsetlist = NULL;
+ showlist = NULL;
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+ endianlist = NULL;
+#endif
+ sethistlist = NULL;
+ showhistlist = NULL;
+ unsethistlist = NULL;
+#if MAINTENANCE_CMDS
+ maintenancelist = NULL;
+ maintenanceinfolist = NULL;
+ maintenanceprintlist = NULL;
+#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.
+ */
+
+void
+init_history()
+{
+ 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 ()
+{
+ struct cmd_list_element *c;
+
+#ifdef TARGET_BYTE_ORDER_SELECTABLE
+
+ add_prefix_cmd ("endian", class_support, set_endian,
+ "Set endianness of target.",
+ &endianlist, "set endian ", 0, &setlist);
+ add_cmd ("big", class_support, set_endian_big,
+ "Set target as being big endian.", &endianlist);
+ add_cmd ("little", class_support, set_endian_little,
+ "Set target as being little endian.", &endianlist);
+ add_cmd ("auto", class_support, set_endian_auto,
+ "Select target endianness automatically.", &endianlist);
+ add_cmd ("endian", class_support, show_endian,
+ "Show endianness of target.", &showlist);
+
+#endif /* defined (TARGET_BYTE_ORDER_SELECTABLE) */
+
+#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 (*)()) readline_line_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 may have up to ten 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);
+
+ add_com ("dont-repeat", class_support, dont_repeat_command, "Don't repeat this command.\n\
+Primarily used inside of user-defined commands that should not be repeated when\n\
+hitting return.");
+
+ 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_com ("complete", class_obscure, complete_command,
+ "List the completions for the rest of the line as a command.");
+
+ 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 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_com ("while", class_support, while_command,
+"Execute nested commands WHILE the conditional expression is non zero.\n\
+The conditional expression must follow the word `while' and must in turn be\n\
+followed by a new line. The nested commands must be entered one per line,\n\
+and should be terminated by the word `end'.");
+
+ add_com ("if", class_support, if_command,
+"Execute nested commands once IF the conditional expression is non zero.\n\
+The conditional expression must follow the word `if' and must in turn be\n\
+followed by a new line. The nested commands must be entered one per line,\n\
+and should be terminated by the word 'else' or `end'. If an else clause\n\
+is used, the same rules apply to its nested commands as to the first ones.");
+
+ /* If target is open when baud changes, it doesn't take effect until the
+ next open (I think, not sure). */
+ 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);
+
+ add_show_from_set (
+ add_set_cmd ("remotedebug", no_class, var_zinteger, (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);
+}
diff --git a/contrib/gdb/gdb/top.h b/contrib/gdb/gdb/top.h
new file mode 100644
index 0000000..661f4ef
--- /dev/null
+++ b/contrib/gdb/gdb/top.h
@@ -0,0 +1,48 @@
+/* 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.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* From top.c. */
+extern char *line;
+extern int linesize;
+extern FILE *instream;
+extern char gdb_dirbuf[1024];
+extern int inhibit_gdbinit;
+extern int epoch_interface;
+extern char gdbinit[];
+
+/* Generally one should use catch_errors rather than manipulating these
+ directly. The exception is main(). */
+extern jmp_buf error_return;
+extern jmp_buf quit_return;
+
+extern void print_gdb_version PARAMS ((GDB_FILE *));
+extern void print_gnu_advertisement PARAMS ((void));
+
+extern void source_command PARAMS ((char *, int));
+extern void cd_command PARAMS ((char *, int));
+extern void read_command_file PARAMS ((FILE *));
+extern void init_history PARAMS ((void));
+extern void command_loop PARAMS ((void));
+extern void quit_command PARAMS ((char *, int));
+
+/* From random places. */
+extern int mapped_symbol_files;
+extern int readnow_symbol_files;
+#define ALL_CLEANUPS ((struct cleanup *)0)
diff --git a/contrib/gdb/gdb/typeprint.c b/contrib/gdb/gdb/typeprint.c
new file mode 100644
index 0000000..6b1c6de
--- /dev/null
+++ b/contrib/gdb/gdb/typeprint.c
@@ -0,0 +1,302 @@
+/* Language independent support for printing types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h" /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "language.h"
+#include "demangle.h"
+
+#include "gdb_string.h"
+#include <errno.h>
+
+static void
+ptype_command PARAMS ((char *, int));
+
+static struct type *
+ptype_eval PARAMS ((struct expression *));
+
+static void
+whatis_command PARAMS ((char *, int));
+
+static void
+whatis_exp PARAMS ((char *, int));
+
+/* Print a description of a type TYPE in the form of a declaration of a
+ variable named VARSTRING. (VARSTRING is demangled if necessary.)
+ Output goes to STREAM (via stdio).
+ If SHOW is positive, we show the contents of the outermost level
+ of structure even if there is a type name that could be used instead.
+ If SHOW is negative, we never show the details of elements' types. */
+
+void
+type_print (type, varstring, stream, show)
+ struct type *type;
+ char *varstring;
+ GDB_FILE *stream;
+ int show;
+{
+ LA_PRINT_TYPE (type, varstring, stream, show, 0);
+}
+
+/* Print type of EXP, or last thing in value history if EXP == NULL.
+ show is passed to type_print. */
+
+static void
+whatis_exp (exp, show)
+ char *exp;
+ int show;
+{
+ struct expression *expr;
+ register value_ptr val;
+ register struct cleanup *old_chain = NULL;
+
+ if (exp)
+ {
+ expr = parse_expression (exp);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ val = evaluate_type (expr);
+ }
+ else
+ val = access_value_history (0);
+
+ printf_filtered ("type = ");
+ type_print (VALUE_TYPE (val), "", gdb_stdout, show);
+ printf_filtered ("\n");
+
+ if (exp)
+ do_cleanups (old_chain);
+}
+
+/* ARGSUSED */
+static void
+whatis_command (exp, from_tty)
+ char *exp;
+ int from_tty;
+{
+ /* Most of the time users do not want to see all the fields
+ in a structure. If they do they can use the "ptype" command.
+ Hence the "-1" below. */
+ whatis_exp (exp, -1);
+}
+
+/* Simple subroutine for ptype_command. */
+
+static struct type *
+ptype_eval (exp)
+ struct expression *exp;
+{
+ if (exp->elts[0].opcode == OP_TYPE)
+ {
+ return (exp->elts[1].type);
+ }
+ else
+ {
+ return (NULL);
+ }
+}
+
+/* TYPENAME is either the name of a type, or an expression. */
+
+/* ARGSUSED */
+static void
+ptype_command (typename, from_tty)
+ char *typename;
+ int from_tty;
+{
+ register struct type *type;
+ struct expression *expr;
+ register struct cleanup *old_chain;
+
+ if (typename == NULL)
+ {
+ /* Print type of last thing in value history. */
+ whatis_exp (typename, 1);
+ }
+ else
+ {
+ expr = parse_expression (typename);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ type = ptype_eval (expr);
+ if (type != NULL)
+ {
+ /* User did "ptype <typename>" */
+ printf_filtered ("type = ");
+ type_print (type, "", gdb_stdout, 1);
+ printf_filtered ("\n");
+ do_cleanups (old_chain);
+ }
+ else
+ {
+ /* User did "ptype <symbolname>" */
+ do_cleanups (old_chain);
+ whatis_exp (typename, 1);
+ }
+ }
+}
+
+/* Print integral scalar data VAL, of type TYPE, onto stdio stream STREAM.
+ Used to print data from type structures in a specified type. For example,
+ array bounds may be characters or booleans in some languages, and this
+ allows the ranges to be printed in their "natural" form rather than as
+ decimal integer values.
+
+ FIXME: This is here simply because only the type printing routines
+ currently use it, and it wasn't clear if it really belonged somewhere
+ else (like printcmd.c). There are a lot of other gdb routines that do
+ something similar, but they are generally concerned with printing values
+ that come from the inferior in target byte order and target size. */
+
+void
+print_type_scalar (type, val, stream)
+ struct type *type;
+ LONGEST val;
+ GDB_FILE *stream;
+{
+ unsigned int i;
+ unsigned len;
+
+ CHECK_TYPEDEF (type);
+
+ switch (TYPE_CODE (type))
+ {
+
+ case TYPE_CODE_ENUM:
+ len = TYPE_NFIELDS (type);
+ for (i = 0; i < len; i++)
+ {
+ if (TYPE_FIELD_BITPOS (type, i) == val)
+ {
+ break;
+ }
+ }
+ if (i < len)
+ {
+ fputs_filtered (TYPE_FIELD_NAME (type, i), stream);
+ }
+ else
+ {
+ print_longest (stream, 'd', 0, val);
+ }
+ break;
+
+ case TYPE_CODE_INT:
+ print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val);
+ break;
+
+ case TYPE_CODE_CHAR:
+ LA_PRINT_CHAR ((unsigned char) val, stream);
+ break;
+
+ case TYPE_CODE_BOOL:
+ fprintf_filtered (stream, val ? "TRUE" : "FALSE");
+ break;
+
+ case TYPE_CODE_RANGE:
+ print_type_scalar (TYPE_TARGET_TYPE (type), val, stream);
+ return;
+
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_ARRAY:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_FUNC:
+ case TYPE_CODE_FLT:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_REF:
+ error ("internal error: unhandled type in print_type_scalar");
+ break;
+
+ default:
+ error ("Invalid type code in symbol table.");
+ }
+ gdb_flush (stream);
+}
+
+#if MAINTENANCE_CMDS
+
+/* Dump details of a type specified either directly or indirectly.
+ Uses the same sort of type lookup mechanism as ptype_command()
+ and whatis_command(). */
+
+void
+maintenance_print_type (typename, from_tty)
+ char *typename;
+ int from_tty;
+{
+ register value_ptr val;
+ register struct type *type;
+ register struct cleanup *old_chain;
+ struct expression *expr;
+
+ if (typename != NULL)
+ {
+ expr = parse_expression (typename);
+ old_chain = make_cleanup (free_current_contents, &expr);
+ if (expr -> elts[0].opcode == OP_TYPE)
+ {
+ /* The user expression names a type directly, just use that type. */
+ type = expr -> elts[1].type;
+ }
+ else
+ {
+ /* The user expression may name a type indirectly by naming an
+ object of that type. Find that indirectly named type. */
+ val = evaluate_type (expr);
+ type = VALUE_TYPE (val);
+ }
+ if (type != NULL)
+ {
+ recursive_dump_type (type, 0);
+ }
+ do_cleanups (old_chain);
+ }
+}
+
+#endif /* MAINTENANCE_CMDS */
+
+
+void
+_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 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,
+ "Print data type of expression EXP.");
+
+}
diff --git a/contrib/gdb/gdb/typeprint.h b/contrib/gdb/gdb/typeprint.h
new file mode 100644
index 0000000..0dc32cd
--- /dev/null
+++ b/contrib/gdb/gdb/typeprint.h
@@ -0,0 +1,21 @@
+/* Language independent support for printing types for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+void
+print_type_scalar PARAMS ((struct type *type, LONGEST, GDB_FILE *));
diff --git a/contrib/gdb/gdb/umax-xdep.c b/contrib/gdb/gdb/umax-xdep.c
new file mode 100644
index 0000000..d54519e
--- /dev/null
+++ b/contrib/gdb/gdb/umax-xdep.c
@@ -0,0 +1,133 @@
+/* umax host stuff.
+ Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "frame.h"
+#include "inferior.h"
+
+#include <sys/param.h>
+#include <sys/dir.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include "gdbcore.h"
+#include <sys/ptrace.h>
+#define PTRACE_ATTACH PT_ATTACH
+#define PTRACE_DETACH PT_FREEPROC
+
+#include <sys/file.h>
+#include "gdb_stat.h"
+
+/* Work with core dump and executable files, for GDB.
+ This code would be in corefile.c if it weren't machine-dependent. */
+
+void
+core_file_command (filename, from_tty)
+ char *filename;
+ int from_tty;
+{
+ int val;
+ extern char registers[];
+
+ /* Discard all vestiges of any previous core file
+ and mark data and stack spaces as empty. */
+
+ if (corefile)
+ free (corefile);
+ corefile = 0;
+
+ if (corechan >= 0)
+ close (corechan);
+ corechan = -1;
+
+ data_start = 0;
+ data_end = 0;
+ stack_start = STACK_END_ADDR;
+ stack_end = STACK_END_ADDR;
+
+ /* Now, if a new core file was specified, open it and digest it. */
+
+ if (filename)
+ {
+ filename = tilde_expand (filename);
+ make_cleanup (free, filename);
+
+ if (have_inferior_p ())
+ error ("To look at a core file, you must kill the program with \"kill\".");
+ corechan = open (filename, O_RDONLY, 0);
+ if (corechan < 0)
+ perror_with_name (filename);
+ /* 4.2-style (and perhaps also sysV-style) core dump file. */
+ {
+ struct ptrace_user u;
+ int reg_offset;
+
+ val = myread (corechan, &u, sizeof u);
+ if (val < 0)
+ perror_with_name (filename);
+ data_start = exec_data_start;
+
+ data_end = data_start + u.pt_dsize;
+ stack_start = stack_end - u.pt_ssize;
+ data_offset = sizeof u;
+ stack_offset = data_offset + u.pt_dsize;
+ reg_offset = 0;
+
+ memcpy (&core_aouthdr, &u.pt_aouthdr, sizeof (AOUTHDR));
+ printf_unfiltered ("Core file is from \"%s\".\n", u.pt_comm);
+ if (u.pt_signal > 0)
+ printf_unfiltered ("Program terminated with signal %d, %s.\n",
+ u.pt_signal, safe_strsignal (u.pt_signal));
+
+ /* Read the register values out of the core file and store
+ them where `read_register' will find them. */
+
+ {
+ register int regno;
+
+ for (regno = 0; regno < NUM_REGS; regno++)
+ {
+ char buf[MAX_REGISTER_RAW_SIZE];
+
+ val = lseek (corechan, register_addr (regno, reg_offset), 0);
+ if (val < 0)
+ perror_with_name (filename);
+
+ val = myread (corechan, buf, sizeof buf);
+ if (val < 0)
+ perror_with_name (filename);
+ supply_register (regno, buf);
+ }
+ }
+ }
+ if (filename[0] == '/')
+ corefile = savestring (filename, strlen (filename));
+ else
+ {
+ corefile = concat (current_directory, "/", filename, NULL);
+ }
+
+ flush_cached_frames ();
+ select_frame (get_current_frame (), 0);
+ validate_files ();
+ }
+ else if (from_tty)
+ printf_unfiltered ("No core file now.\n");
+}
diff --git a/contrib/gdb/gdb/utils.c b/contrib/gdb/gdb/utils.c
new file mode 100644
index 0000000..5135514
--- /dev/null
+++ b/contrib/gdb/gdb/utils.c
@@ -0,0 +1,1948 @@
+/* General utility routines for GDB, the GNU debugger.
+ Copyright 1986, 1989, 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#if !defined(__GO32__) && !defined(__WIN32__) && !defined(MPW)
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <pwd.h>
+#endif
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+#include <ctype.h>
+#include "gdb_string.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "signals.h"
+#include "gdbcmd.h"
+#include "serial.h"
+#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 */
+
+#if defined (NO_MMALLOC) || defined (NO_MMALLOC_CHECK)
+#else
+
+static void
+malloc_botch PARAMS ((void));
+
+#endif /* NO_MMALLOC, etc */
+
+static void
+fatal_dump_core PARAMS((char *, ...));
+
+static void
+prompt_for_continue PARAMS ((void));
+
+static void
+set_width_command PARAMS ((char *, int, struct cmd_list_element *));
+
+/* 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)))
+#endif
+
+/* Chain of cleanup actions established with make_cleanup,
+ to be executed if an error happens. */
+
+static struct cleanup *cleanup_chain;
+
+/* Nonzero if we have job control. */
+
+int job_control;
+
+/* Nonzero means a quit has been requested. */
+
+int quit_flag;
+
+/* Nonzero means quit immediately if Control-C is typed now, rather
+ than waiting until QUIT is executed. Be careful in setting this;
+ code which executes with immediate_quit set has to be very careful
+ about being able to deal with being interrupted at any time. It is
+ almost always better to use QUIT; the only exception I can think of
+ is being able to quit out of a system call (using EINTR loses if
+ the SIGINT happens between the previous QUIT and the system call).
+ To immediately quit in the case in which a SIGINT happens between
+ the previous QUIT and setting immediate_quit (desirable anytime we
+ expect to block), call QUIT after setting immediate_quit. */
+
+int immediate_quit;
+
+/* Nonzero means that encoded C++ names should be printed out in their
+ C++ form rather than raw. */
+
+int demangle = 1;
+
+/* Nonzero means that encoded C++ names should be printed out in their
+ C++ form even in assembler language displays. If this is set, but
+ DEMANGLE is zero, names are printed raw, i.e. DEMANGLE controls. */
+
+int asm_demangle = 0;
+
+/* Nonzero means that strings with character values >0x7F should be printed
+ as octal escapes. Zero means just print the value (e.g. it's an
+ international character, and the terminal or window can cope.) */
+
+int sevenbit_strings = 0;
+
+/* String to be printed before error messages, if any. */
+
+char *error_pre_print;
+
+/* String to be printed before quit messages, if any. */
+
+char *quit_pre_print;
+
+/* String to be printed before warning messages, if any. */
+
+char *warning_pre_print = "\nwarning: ";
+
+/* Add a new cleanup to the cleanup_chain,
+ and return the previous chain pointer
+ to be passed later to do_cleanups or discard_cleanups.
+ Args are FUNCTION to clean up with, and ARG to pass to it. */
+
+struct cleanup *
+make_cleanup (function, arg)
+ void (*function) PARAMS ((PTR));
+ PTR arg;
+{
+ register struct cleanup *new
+ = (struct cleanup *) xmalloc (sizeof (struct cleanup));
+ register struct cleanup *old_chain = cleanup_chain;
+
+ new->next = cleanup_chain;
+ new->function = function;
+ new->arg = arg;
+ cleanup_chain = new;
+
+ return old_chain;
+}
+
+/* Discard cleanups and do the actions they describe
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+do_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ cleanup_chain = ptr->next; /* Do this first incase recursion */
+ (*ptr->function) (ptr->arg);
+ free (ptr);
+ }
+}
+
+/* Discard cleanups, not doing the actions they describe,
+ until we get back to the point OLD_CHAIN in the cleanup_chain. */
+
+void
+discard_cleanups (old_chain)
+ register struct cleanup *old_chain;
+{
+ register struct cleanup *ptr;
+ while ((ptr = cleanup_chain) != old_chain)
+ {
+ cleanup_chain = ptr->next;
+ free ((PTR)ptr);
+ }
+}
+
+/* Set the cleanup_chain to 0, and return the old cleanup chain. */
+struct cleanup *
+save_cleanups ()
+{
+ struct cleanup *old_chain = cleanup_chain;
+
+ cleanup_chain = 0;
+ return old_chain;
+}
+
+/* Restore the cleanup chain from a previously saved chain. */
+void
+restore_cleanups (chain)
+ struct cleanup *chain;
+{
+ cleanup_chain = chain;
+}
+
+/* This function is useful for cleanups.
+ Do
+
+ foo = xmalloc (...);
+ old_chain = make_cleanup (free_current_contents, &foo);
+
+ to arrange to free the object thus allocated. */
+
+void
+free_current_contents (location)
+ char **location;
+{
+ free (*location);
+}
+
+/* Provide a known function that does nothing, to use as a base for
+ for a possibly long chain of cleanups. This is useful where we
+ use the cleanup chain for handling normal cleanups as well as dealing
+ with cleanups that need to be done as a result of a call to error().
+ In such cases, we may not be certain where the first cleanup is, unless
+ we have a do-nothing one to always use as the base. */
+
+/* ARGSUSED */
+void
+null_cleanup (arg)
+ char **arg;
+{
+}
+
+
+/* Print a warning message. Way to use this is to call warning_begin,
+ output the warning message (use unfiltered output to gdb_stderr),
+ ending in a newline. There is not currently a warning_end that you
+ call afterwards, but such a thing might be added if it is useful
+ for a GUI to separate warning messages from other output.
+
+ FIXME: Why do warnings use unfiltered output and errors filtered?
+ Is this anything other than a historical accident? */
+
+void
+warning_begin ()
+{
+ target_terminal_ours ();
+ wrap_here(""); /* Force out any buffered output */
+ gdb_flush (gdb_stdout);
+ if (warning_pre_print)
+ fprintf_unfiltered (gdb_stderr, warning_pre_print);
+}
+
+/* Print a warning message.
+ The first argument STRING is the warning message, used as a fprintf string,
+ and the remaining args are passed as arguments to it.
+ The primary difference between warnings and errors is that a warning
+ does not force the return to command level. */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+warning (char *string, ...)
+#else
+warning (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ warning_begin ();
+ 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 to gdb_stderr
+ (FIXME: Some callers, like memory_error, use gdb_stdout)), ending
+ in a newline, 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. */
+
+#ifdef ANSI_PROTOTYPES
+NORETURN void
+error (char *string, ...)
+#else
+void
+error (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ va_start (args);
+#endif
+ if (error_hook)
+ (*error_hook) ();
+ else
+ {
+ error_begin ();
+#ifdef ANSI_PROTOTYPES
+ vfprintf_filtered (gdb_stderr, string, args);
+#else
+ {
+ char *string1;
+
+ string1 = va_arg (args, char *);
+ vfprintf_filtered (gdb_stderr, string1, args);
+ }
+#endif
+ fprintf_filtered (gdb_stderr, "\n");
+ va_end (args);
+ return_to_top_level (RETURN_ERROR);
+ }
+}
+
+
+/* Print an error message and exit reporting failure.
+ This is for a error that we cannot continue from.
+ The arguments are printed a la printf.
+
+ This function cannot be declared volatile (NORETURN) in an
+ ANSI environment because exit() is not declared volatile. */
+
+/* VARARGS */
+NORETURN void
+#ifdef ANSI_PROTOTYPES
+fatal (char *string, ...)
+#else
+fatal (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ fprintf_unfiltered (gdb_stderr, "\ngdb: ");
+ vfprintf_unfiltered (gdb_stderr, string, args);
+ fprintf_unfiltered (gdb_stderr, "\n");
+ va_end (args);
+ exit (1);
+}
+
+/* Print an error message and exit, dumping core.
+ The arguments are printed a la printf (). */
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+fatal_dump_core (char *string, ...)
+#else
+fatal_dump_core (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, string);
+#else
+ char *string;
+
+ va_start (args);
+ string = va_arg (args, char *);
+#endif
+ /* "internal error" is always correct, since GDB should never dump
+ core, no matter what the input. */
+ 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);
+ kill (getpid (), SIGQUIT);
+ /* We should never get here, but just in case... */
+ exit (1);
+}
+
+/* The strerror() function can return NULL for errno values that are
+ out of range. Provide a "safe" version that always returns a
+ printable string. */
+
+char *
+safe_strerror (errnum)
+ int errnum;
+{
+ char *msg;
+ static char buf[32];
+
+ if ((msg = strerror (errnum)) == NULL)
+ {
+ sprintf (buf, "(undocumented errno %d)", errnum);
+ msg = buf;
+ }
+ return (msg);
+}
+
+/* The strsignal() function can return NULL for signal values that are
+ out of range. Provide a "safe" version that always returns a
+ printable string. */
+
+char *
+safe_strsignal (signo)
+ int signo;
+{
+ char *msg;
+ static char buf[32];
+
+ if ((msg = strsignal (signo)) == NULL)
+ {
+ sprintf (buf, "(undocumented signal %d)", signo);
+ msg = buf;
+ }
+ return (msg);
+}
+
+
+/* Print the system error message for errno, and also mention STRING
+ as the file name for which the error was encountered.
+ Then return to command level. */
+
+void
+perror_with_name (string)
+ char *string;
+{
+ char *err;
+ char *combined;
+
+ err = safe_strerror (errno);
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ /* 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_set_error (bfd_error_no_error);
+ errno = 0;
+
+ error ("%s.", combined);
+}
+
+/* Print the system error message for ERRCODE, and also mention STRING
+ as the file name for which the error was encountered. */
+
+void
+print_sys_errmsg (string, errcode)
+ char *string;
+ int errcode;
+{
+ char *err;
+ char *combined;
+
+ err = safe_strerror (errcode);
+ combined = (char *) alloca (strlen (err) + strlen (string) + 3);
+ strcpy (combined, string);
+ strcat (combined, ": ");
+ strcat (combined, err);
+
+ /* 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. */
+
+void
+quit ()
+{
+ serial_t gdb_stdout_serial = serial_fdopen (1);
+
+ target_terminal_ours ();
+
+ /* 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): */
+
+ /* 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 (quit_pre_print)
+ fprintf_unfiltered (gdb_stderr, quit_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_unfiltered (gdb_stderr, "Quit\n");
+ else
+ fprintf_unfiltered (gdb_stderr,
+ "Quit (expect signal SIGINT when the program is resumed)\n");
+ return_to_top_level (RETURN_QUIT);
+}
+
+
+#if defined(__GO32__)||defined(WINGDB)
+
+/* In the absence of signals, poll keyboard for a quit.
+ Called from #define QUIT pollquit() in xm-go32.h. */
+
+void
+pollquit()
+{
+ if (kbhit ())
+ {
+ int k = getkey ();
+ if (k == 1) {
+ quit_flag = 1;
+ quit();
+ }
+ else if (k == 2) {
+ immediate_quit = 1;
+ quit ();
+ }
+ else
+ {
+ /* We just ignore it */
+ fprintf_unfiltered (gdb_stderr, "CTRL-A to quit, CTRL-B to quit harder\n");
+ }
+ }
+}
+
+
+#endif
+#if defined(__GO32__)||defined(WINGDB)
+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
+request_quit (signo)
+ int signo;
+{
+ quit_flag = 1;
+ /* 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);
+
+
+#ifdef REQUEST_QUIT
+ REQUEST_QUIT;
+#else
+ if (immediate_quit)
+ quit ();
+#endif
+}
+
+
+/* Memory management stuff (malloc friends). */
+
+#if defined (NO_MMALLOC)
+
+/* Make a substitute size_t for non-ANSI compilers. */
+
+#ifdef _AIX
+#include <stddef.h>
+#else /* Not AIX */
+#ifndef __STDC__
+#ifndef size_t
+#define size_t unsigned int
+#endif
+#endif
+#endif /* Not AIX */
+
+PTR
+mmalloc (md, size)
+ PTR md;
+ size_t size;
+{
+ return malloc (size);
+}
+
+PTR
+mrealloc (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ size_t size;
+{
+ if (ptr == 0) /* Guard against old realloc's */
+ return malloc (size);
+ else
+ return realloc (ptr, size);
+}
+
+void
+mfree (md, ptr)
+ PTR md;
+ PTR ptr;
+{
+ free (ptr);
+}
+
+#endif /* NO_MMALLOC */
+
+#if defined (NO_MMALLOC) || defined (NO_MMALLOC_CHECK)
+
+void
+init_malloc (md)
+ PTR md;
+{
+}
+
+#else /* have mmalloc and want corruption checking */
+
+static void
+malloc_botch ()
+{
+ fatal_dump_core ("Memory corruption");
+}
+
+/* Attempt to install hooks in mmalloc/mrealloc/mfree for the heap specified
+ by MD, to detect memory corruption. Note that MD may be NULL to specify
+ the default heap that grows via sbrk.
+
+ Note that for freshly created regions, we must call mmcheck prior to any
+ mallocs in the region. Otherwise, any region which was allocated prior to
+ installing the checking hooks, which is later reallocated or freed, will
+ fail the checks! The mmcheck function only allows initial hooks to be
+ installed before the first mmalloc. However, anytime after we have called
+ mmcheck the first time to install the checking hooks, we can call it again
+ to update the function pointer to the memory corruption handler.
+
+ Returns zero on failure, non-zero on success. */
+
+void
+init_malloc (md)
+ PTR md;
+{
+ if (!mmcheck (md, malloc_botch))
+ {
+ warning ("internal error: failed to install memory consistency checks");
+ }
+
+ mmtrace ();
+}
+
+#endif /* Have mmalloc and want corruption checking */
+
+/* Called when a memory allocation fails, with the number of bytes of
+ memory requested in SIZE. */
+
+NORETURN void
+nomem (size)
+ long size;
+{
+ if (size > 0)
+ {
+ fatal ("virtual memory exhausted: can't allocate %ld bytes.", size);
+ }
+ else
+ {
+ fatal ("virtual memory exhausted.");
+ }
+}
+
+/* Like mmalloc but get error if no storage available, and protect against
+ the caller wanting to allocate zero bytes. Whether to return NULL for
+ a zero byte request, or translate the request into a request for one
+ byte of zero'd storage, is a religious issue. */
+
+PTR
+xmmalloc (md, size)
+ PTR md;
+ long size;
+{
+ register PTR val;
+
+ if (size == 0)
+ {
+ val = NULL;
+ }
+ else if ((val = mmalloc (md, size)) == NULL)
+ {
+ nomem (size);
+ }
+ return (val);
+}
+
+/* Like mrealloc but get error if no storage available. */
+
+PTR
+xmrealloc (md, ptr, size)
+ PTR md;
+ PTR ptr;
+ long size;
+{
+ register PTR val;
+
+ if (ptr != NULL)
+ {
+ val = mrealloc (md, ptr, size);
+ }
+ else
+ {
+ val = mmalloc (md, size);
+ }
+ if (val == NULL)
+ {
+ nomem (size);
+ }
+ return (val);
+}
+
+/* Like malloc but get error if no storage available, and protect against
+ the caller wanting to allocate zero bytes. */
+
+PTR
+xmalloc (size)
+ long size;
+{
+ return (xmmalloc ((PTR) NULL, size));
+}
+
+/* Like mrealloc but get error if no storage available. */
+
+PTR
+xrealloc (ptr, size)
+ PTR ptr;
+ long size;
+{
+ return (xmrealloc ((PTR) NULL, ptr, size));
+}
+
+
+/* My replacement for the read system call.
+ Used like `read' but keeps going if `read' returns too soon. */
+
+int
+myread (desc, addr, len)
+ int desc;
+ char *addr;
+ int len;
+{
+ register int val;
+ int orglen = len;
+
+ while (len > 0)
+ {
+ val = read (desc, addr, len);
+ if (val < 0)
+ return val;
+ if (val == 0)
+ return orglen - len;
+ len -= val;
+ addr += val;
+ }
+ return orglen;
+}
+
+/* Make a copy of the string at PTR with SIZE characters
+ (and add a null character at the end in the copy).
+ Uses malloc to get the space. Returns the address of the copy. */
+
+char *
+savestring (ptr, size)
+ const char *ptr;
+ int size;
+{
+ register char *p = (char *) xmalloc (size + 1);
+ memcpy (p, ptr, size);
+ p[size] = 0;
+ return p;
+}
+
+char *
+msavestring (md, ptr, size)
+ PTR md;
+ const char *ptr;
+ int size;
+{
+ register char *p = (char *) xmmalloc (md, size + 1);
+ memcpy (p, ptr, size);
+ p[size] = 0;
+ return p;
+}
+
+/* The "const" is so it compiles under DGUX (which prototypes strsave
+ in <string.h>. FIXME: This should be named "xstrsave", shouldn't it?
+ Doesn't real strsave return NULL if out of memory? */
+char *
+strsave (ptr)
+ const char *ptr;
+{
+ return savestring (ptr, strlen (ptr));
+}
+
+char *
+mstrsave (md, ptr)
+ PTR md;
+ const char *ptr;
+{
+ return (msavestring (md, ptr, strlen (ptr)));
+}
+
+void
+print_spaces (n, file)
+ register int n;
+ register FILE *file;
+{
+ while (n-- > 0)
+ 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 "? ".
+ It should not say how to answer, because we do that. */
+
+/* VARARGS */
+int
+#ifdef ANSI_PROTOTYPES
+query (char *ctlstr, ...)
+#else
+query (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ register int answer;
+ register int ans2;
+ int retval;
+
+#ifdef ANSI_PROTOTYPES
+ va_start (args, ctlstr);
+#else
+ char *ctlstr;
+ va_start (args);
+ ctlstr = va_arg (args, char *);
+#endif
+
+ if (query_hook)
+ {
+ return query_hook (ctlstr, args);
+ }
+
+ /* Automatically answer "yes" if input is not from a terminal. */
+ if (!input_from_terminal_p ())
+ return 1;
+#ifdef MPW
+ /* FIXME Automatically answer "yes" if called from MacGDB. */
+ if (mac_app)
+ return 1;
+#endif /* MPW */
+
+ while (1)
+ {
+ wrap_here (""); /* Flush any buffered output */
+ gdb_flush (gdb_stdout);
+
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032pre-query\n");
+
+ vfprintf_filtered (gdb_stdout, ctlstr, args);
+ printf_filtered ("(y or n) ");
+
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032query\n");
+
+#ifdef MPW
+ /* If not in MacGDB, move to a new line so the entered line doesn't
+ have a prompt on the front of it. */
+ if (!mac_app)
+ fputs_unfiltered ("\n", gdb_stdout);
+#endif /* MPW */
+
+ gdb_flush (gdb_stdout);
+ answer = fgetc (stdin);
+ clearerr (stdin); /* in case of C-d */
+ if (answer == EOF) /* C-d */
+ {
+ retval = 1;
+ break;
+ }
+ if (answer != '\n') /* Eat rest of input line, to EOF or newline */
+ do
+ {
+ ans2 = fgetc (stdin);
+ clearerr (stdin);
+ }
+ while (ans2 != EOF && ans2 != '\n');
+ if (answer >= 'a')
+ answer -= 040;
+ if (answer == 'Y')
+ {
+ retval = 1;
+ break;
+ }
+ if (answer == 'N')
+ {
+ retval = 0;
+ break;
+ }
+ printf_filtered ("Please answer y or n.\n");
+ }
+
+ if (annotation_level > 1)
+ printf_filtered ("\n\032\032post-query\n");
+ return retval;
+}
+
+
+/* Parse a C escape sequence. STRING_PTR points to a variable
+ containing a pointer to the string to parse. That pointer
+ should point to the character after the \. That pointer
+ is updated past the characters we use. The value of the
+ escape sequence is returned.
+
+ A negative value means the sequence \ newline was seen,
+ which is supposed to be equivalent to nothing at all.
+
+ If \ is followed by a null character, we return a negative
+ value and leave the string pointer pointing at the null character.
+
+ If \ is followed by 000, we return 0 and leave the string pointer
+ after the zeros. A value of 0 does not mean end of string. */
+
+int
+parse_escape (string_ptr)
+ char **string_ptr;
+{
+ register int c = *(*string_ptr)++;
+ switch (c)
+ {
+ case 'a':
+ return 007; /* Bell (alert) char */
+ case 'b':
+ return '\b';
+ case 'e': /* Escape character */
+ return 033;
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'v':
+ return '\v';
+ case '\n':
+ return -2;
+ case 0:
+ (*string_ptr)--;
+ return 0;
+ case '^':
+ c = *(*string_ptr)++;
+ if (c == '\\')
+ c = parse_escape (string_ptr);
+ if (c == '?')
+ return 0177;
+ return (c & 0200) | (c & 037);
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ register int i = c - '0';
+ register int count = 0;
+ while (++count < 3)
+ {
+ if ((c = *(*string_ptr)++) >= '0' && c <= '7')
+ {
+ i *= 8;
+ i += c - '0';
+ }
+ else
+ {
+ (*string_ptr)--;
+ break;
+ }
+ }
+ return i;
+ }
+ default:
+ return c;
+ }
+}
+
+/* Print the character C on STREAM as part of the contents of a literal
+ string whose delimiter is QUOTER. Note that this routine should only
+ be call for printing things which are independent of the language
+ of the program being debugged. */
+
+void
+gdb_printchar (c, stream, quoter)
+ register int c;
+ FILE *stream;
+ int quoter;
+{
+
+ c &= 0xFF; /* Avoid sign bit follies */
+
+ if ( c < 0x20 || /* Low control chars */
+ (c >= 0x7F && c < 0xA0) || /* DEL, High controls */
+ (sevenbit_strings && c >= 0x80)) { /* high order bit set */
+ switch (c)
+ {
+ case '\n':
+ fputs_filtered ("\\n", stream);
+ break;
+ case '\b':
+ fputs_filtered ("\\b", stream);
+ break;
+ case '\t':
+ fputs_filtered ("\\t", stream);
+ break;
+ case '\f':
+ fputs_filtered ("\\f", stream);
+ break;
+ case '\r':
+ fputs_filtered ("\\r", stream);
+ break;
+ case '\033':
+ fputs_filtered ("\\e", stream);
+ break;
+ case '\007':
+ fputs_filtered ("\\a", stream);
+ break;
+ default:
+ fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
+ break;
+ }
+ } else {
+ if (c == '\\' || c == quoter)
+ fputs_filtered ("\\", stream);
+ fprintf_filtered (stream, "%c", c);
+ }
+}
+
+/* Number of lines per page or UINT_MAX if paging is disabled. */
+static unsigned int lines_per_page;
+/* Number of chars per line or UNIT_MAX is line folding is disabled. */
+static unsigned int chars_per_line;
+/* Current count of lines printed on this page, chars on this line. */
+static unsigned int lines_printed, chars_printed;
+
+/* Buffer and start column of buffered text, for doing smarter word-
+ wrapping. When someone calls wrap_here(), we start buffering output
+ that comes through fputs_filtered(). If we see a newline, we just
+ spit it out and forget about the wrap_here(). If we see another
+ wrap_here(), we spit it out and remember the newer one. If we see
+ the end of the line, we spit out a newline, the indent, and then
+ the buffered output. */
+
+/* Malloc'd buffer with chars_per_line+2 bytes. Contains characters which
+ are waiting to be output (they have already been counted in chars_printed).
+ When wrap_buffer[0] is null, the buffer is empty. */
+static char *wrap_buffer;
+
+/* Pointer in wrap_buffer to the next character to fill. */
+static char *wrap_pointer;
+
+/* String to indent by if the wrap occurs. Must not be NULL if wrap_column
+ is non-zero. */
+static char *wrap_indent;
+
+/* Column number on the screen where wrap_buffer begins, or 0 if wrapping
+ is not in effect. */
+static int wrap_column;
+
+/* ARGSUSED */
+static void
+set_width_command (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ if (!wrap_buffer)
+ {
+ wrap_buffer = (char *) xmalloc (chars_per_line + 2);
+ wrap_buffer[0] = '\0';
+ }
+ else
+ wrap_buffer = (char *) xrealloc (wrap_buffer, chars_per_line + 2);
+ wrap_pointer = wrap_buffer; /* Start it at the beginning */
+}
+
+/* Wait, so the user can read what's on the screen. Prompt the user
+ to continue by pressing RETURN. */
+
+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 <return> to continue, or q <return> 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
+ screen. */
+ reinitialize_more_filter ();
+
+ immediate_quit++;
+ /* On a real operating system, the user can quit with SIGINT.
+ But not on GO32.
+
+ 'q' is provided on all systems so users don't have to change habits
+ 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. */
+ /* 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;
+ while (*p == ' ' || *p == '\t')
+ ++p;
+ if (p[0] == 'q')
+ request_quit (SIGINT);
+ free (ignore);
+ }
+ immediate_quit--;
+
+ /* Now we have to do this again, so that GDB will know that it doesn't
+ need to save the ---Type <return>--- line at the top of the screen. */
+ reinitialize_more_filter ();
+
+ dont_repeat (); /* Forget prev cmd -- CR won't repeat it. */
+}
+
+/* Reinitialize filter; ie. tell it to reset to original values. */
+
+void
+reinitialize_more_filter ()
+{
+ lines_printed = 0;
+ chars_printed = 0;
+}
+
+/* Indicate that if the next sequence of characters overflows the line,
+ a newline should be inserted here rather than when it hits the end.
+ If INDENT is non-null, it is a string to be printed to indent the
+ wrapped part on the next line. INDENT must remain accessible until
+ the next call to wrap_here() or until a newline is printed through
+ fputs_filtered().
+
+ If the line is already overfull, we immediately print a newline and
+ the indentation, and disable further wrapping.
+
+ If we don't know the width of lines, but we know the page height,
+ we must not wrap words, but should still keep track of newlines
+ that were explicitly printed.
+
+ INDENT should not contain tabs, as that will mess up the char count
+ on the next line. FIXME.
+
+ This routine is guaranteed to force out any output which has been
+ squirreled away in the wrap_buffer, so wrap_here ((char *)0) can be
+ used to force out output from the wrap_buffer. */
+
+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_unfiltered (wrap_buffer, gdb_stdout);
+ }
+ wrap_pointer = wrap_buffer;
+ wrap_buffer[0] = '\0';
+ if (chars_per_line == UINT_MAX) /* No line overflow checking */
+ {
+ wrap_column = 0;
+ }
+ else if (chars_printed >= chars_per_line)
+ {
+ puts_filtered ("\n");
+ if (indent != NULL)
+ puts_filtered (indent);
+ wrap_column = 0;
+ }
+ else
+ {
+ wrap_column = chars_printed;
+ if (indent == NULL)
+ wrap_indent = "";
+ else
+ wrap_indent = indent;
+ }
+}
+
+/* Ensure that whatever gets printed next, using the filtered output
+ commands, starts at the beginning of the line. I.E. if there is
+ any pending output for the current line, flush it and start a new
+ line. Otherwise do nothing. */
+
+void
+begin_line ()
+{
+ if (chars_printed > 0)
+ {
+ puts_filtered ("\n");
+ }
+}
+
+
+GDB_FILE *
+gdb_fopen (name, mode)
+ char * name;
+ char * mode;
+{
+ return fopen (name, mode);
+}
+
+void
+gdb_flush (stream)
+ FILE *stream;
+{
+ if (flush_hook)
+ {
+ flush_hook (stream);
+ return;
+ }
+
+ 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 (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. */
+
+static void
+fputs_maybe_filtered (linebuffer, stream, filter)
+ const char *linebuffer;
+ FILE *stream;
+ int filter;
+{
+ const char *lineptr;
+
+ if (linebuffer == 0)
+ return;
+
+ /* Don't do any filtering if it is disabled. */
+ if (stream != gdb_stdout
+ || (lines_per_page == UINT_MAX && chars_per_line == UINT_MAX))
+ {
+ fputs_unfiltered (linebuffer, stream);
+ return;
+ }
+
+ /* Go through and output each character. Show line extension
+ when this is necessary; prompt user for new page when this is
+ necessary. */
+
+ lineptr = linebuffer;
+ while (*lineptr)
+ {
+ /* Possible new page. */
+ if (filter &&
+ (lines_printed >= lines_per_page - 1))
+ prompt_for_continue ();
+
+ while (*lineptr && *lineptr != '\n')
+ {
+ /* Print a single line. */
+ if (*lineptr == '\t')
+ {
+ if (wrap_column)
+ *wrap_pointer++ = '\t';
+ else
+ 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. */
+ chars_printed = ((chars_printed >> 3) + 1) << 3;
+ lineptr++;
+ }
+ else
+ {
+ if (wrap_column)
+ *wrap_pointer++ = *lineptr;
+ else
+ fputc_unfiltered (*lineptr, stream);
+ chars_printed++;
+ lineptr++;
+ }
+
+ if (chars_printed >= chars_per_line)
+ {
+ unsigned int save_chars = chars_printed;
+
+ chars_printed = 0;
+ lines_printed++;
+ /* If we aren't actually wrapping, don't output newline --
+ if chars_per_line is right, we probably just overflowed
+ anyway; if it's wrong, let us keep going. */
+ if (wrap_column)
+ fputc_unfiltered ('\n', stream);
+
+ /* Possible new page. */
+ if (lines_printed >= lines_per_page - 1)
+ prompt_for_continue ();
+
+ /* Now output indentation and wrapped string */
+ if (wrap_column)
+ {
+ 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
+ longer than (the user settable) chars_per_line.
+ Note also that this can set chars_printed > chars_per_line
+ if we are printing a long string. */
+ chars_printed = strlen (wrap_indent)
+ + (save_chars - wrap_column);
+ wrap_pointer = wrap_buffer; /* Reset buffer */
+ wrap_buffer[0] = '\0';
+ wrap_column = 0; /* And disable fancy wrap */
+ }
+ }
+ }
+
+ if (*lineptr == '\n')
+ {
+ chars_printed = 0;
+ wrap_here ((char *)0); /* Spit out chars, cancel further wraps */
+ lines_printed++;
+ fputc_unfiltered ('\n', stream);
+ lineptr++;
+ }
+ }
+}
+
+void
+fputs_filtered (linebuffer, stream)
+ const char *linebuffer;
+ FILE *stream;
+{
+ fputs_maybe_filtered (linebuffer, stream, 1);
+}
+
+int
+putchar_unfiltered (c)
+ int c;
+{
+ char buf[2];
+
+ buf[0] = c;
+ buf[1] = 0;
+ fputs_unfiltered (buf, gdb_stdout);
+ return c;
+}
+
+int
+fputc_unfiltered (c, stream)
+ int c;
+ FILE * stream;
+{
+ char buf[2];
+
+ buf[0] = c;
+ buf[1] = 0;
+ fputs_unfiltered (buf, stream);
+ return c;
+}
+
+
+/* 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,
+ 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 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. */
+
+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)
+ FILE *stream;
+ const char *format;
+ va_list args;
+{
+ vfprintf_maybe_filtered (stream, format, args, 1);
+}
+
+void
+vfprintf_unfiltered (stream, format, args)
+ FILE *stream;
+ const char *format;
+ va_list args;
+{
+ 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_unfiltered (linebuffer, stream);
+ do_cleanups (old_cleanups);
+}
+
+void
+vprintf_filtered (format, args)
+ const char *format;
+ va_list args;
+{
+ vfprintf_maybe_filtered (gdb_stdout, format, args, 1);
+}
+
+void
+vprintf_unfiltered (format, args)
+ const char *format;
+ va_list args;
+{
+ vfprintf_unfiltered (gdb_stdout, format, args);
+}
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+fprintf_filtered (FILE *stream, const char *format, ...)
+#else
+fprintf_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ FILE *stream;
+ char *format;
+
+ va_start (args);
+ stream = va_arg (args, FILE *);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_filtered (stream, format, args);
+ va_end (args);
+}
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+fprintf_unfiltered (FILE *stream, const char *format, ...)
+#else
+fprintf_unfiltered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ FILE *stream;
+ char *format;
+
+ va_start (args);
+ stream = va_arg (args, FILE *);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_unfiltered (stream, format, args);
+ va_end (args);
+}
+
+/* Like fprintf_filtered, but prints its result indented.
+ Called as fprintfi_filtered (spaces, stream, format, ...); */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+fprintfi_filtered (int spaces, FILE *stream, const char *format, ...)
+#else
+fprintfi_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ int spaces;
+ FILE *stream;
+ char *format;
+
+ va_start (args);
+ spaces = va_arg (args, int);
+ stream = va_arg (args, FILE *);
+ format = va_arg (args, char *);
+#endif
+ print_spaces_filtered (spaces, stream);
+
+ vfprintf_filtered (stream, format, args);
+ va_end (args);
+}
+
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+printf_filtered (const char *format, ...)
+#else
+printf_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_filtered (gdb_stdout, format, args);
+ va_end (args);
+}
+
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+printf_unfiltered (const char *format, ...)
+#else
+printf_unfiltered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ char *format;
+
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+ vfprintf_unfiltered (gdb_stdout, format, args);
+ va_end (args);
+}
+
+/* Like printf_filtered, but prints it's result indented.
+ Called as printfi_filtered (spaces, format, ...); */
+
+/* VARARGS */
+void
+#ifdef ANSI_PROTOTYPES
+printfi_filtered (int spaces, const char *format, ...)
+#else
+printfi_filtered (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+#ifdef ANSI_PROTOTYPES
+ va_start (args, format);
+#else
+ int spaces;
+ char *format;
+
+ va_start (args);
+ spaces = va_arg (args, int);
+ format = va_arg (args, char *);
+#endif
+ print_spaces_filtered (spaces, gdb_stdout);
+ vfprintf_filtered (gdb_stdout, format, args);
+ va_end (args);
+}
+
+/* Easy -- but watch out!
+
+ This routine is *not* a replacement for puts()! puts() appends a newline.
+ This one doesn't, and had better not! */
+
+void
+puts_filtered (string)
+ const char *string;
+{
+ fputs_filtered (string, gdb_stdout);
+}
+
+void
+puts_unfiltered (string)
+ const char *string;
+{
+ fputs_unfiltered (string, gdb_stdout);
+}
+
+/* Return a pointer to N spaces and a null. The pointer is good
+ until the next call to here. */
+char *
+n_spaces (n)
+ int n;
+{
+ register char *t;
+ static char *spaces;
+ static int max_spaces;
+
+ if (n > max_spaces)
+ {
+ if (spaces)
+ free (spaces);
+ spaces = (char *) xmalloc (n+1);
+ for (t = spaces+n; t != spaces;)
+ *--t = ' ';
+ spaces[n] = '\0';
+ max_spaces = n;
+ }
+
+ return spaces + max_spaces - n;
+}
+
+/* Print N spaces. */
+void
+print_spaces_filtered (n, stream)
+ int n;
+ FILE *stream;
+{
+ fputs_filtered (n_spaces (n), stream);
+}
+
+/* C++ demangler stuff. */
+
+/* fprintf_symbol_filtered attempts to demangle NAME, a symbol in language
+ LANG, using demangling args ARG_MODE, and print it filtered to STREAM.
+ If the name is not mangled, or the language for the name is unknown, or
+ demangling is off, the name is printed in its "raw" form. */
+
+void
+fprintf_symbol_filtered (stream, name, lang, arg_mode)
+ FILE *stream;
+ char *name;
+ enum language lang;
+ int arg_mode;
+{
+ char *demangled;
+
+ if (name != NULL)
+ {
+ /* If user wants to see raw output, no problem. */
+ if (!demangle)
+ {
+ fputs_filtered (name, stream);
+ }
+ else
+ {
+ switch (lang)
+ {
+ case language_cplus:
+ demangled = cplus_demangle (name, arg_mode);
+ break;
+ case language_chill:
+ demangled = chill_demangle (name);
+ break;
+ default:
+ demangled = NULL;
+ break;
+ }
+ fputs_filtered (demangled ? demangled : name, stream);
+ if (demangled != NULL)
+ {
+ free (demangled);
+ }
+ }
+ }
+}
+
+/* Do a strcmp() type operation on STRING1 and STRING2, ignoring any
+ differences in whitespace. Returns 0 if they match, non-zero if they
+ don't (slightly different than strcmp()'s range of return values).
+
+ As an extra hack, string1=="FOO(ARGS)" matches string2=="FOO".
+ This "feature" is useful when searching for matching C++ function names
+ (such as if the user types 'break FOO', where FOO is a mangled C++
+ function). */
+
+int
+strcmp_iw (string1, string2)
+ const char *string1;
+ const char *string2;
+{
+ while ((*string1 != '\0') && (*string2 != '\0'))
+ {
+ while (isspace (*string1))
+ {
+ string1++;
+ }
+ while (isspace (*string2))
+ {
+ string2++;
+ }
+ if (*string1 != *string2)
+ {
+ break;
+ }
+ if (*string1 != '\0')
+ {
+ string1++;
+ string2++;
+ }
+ }
+ return (*string1 != '\0' && *string1 != '(') || (*string2 != '\0');
+}
+
+
+void
+initialize_utils ()
+{
+ struct cmd_list_element *c;
+
+ c = add_set_cmd ("width", class_support, var_uinteger,
+ (char *)&chars_per_line,
+ "Set number of characters gdb thinks are in a line.",
+ &setlist);
+ add_show_from_set (c, &showlist);
+ c->function.sfunc = set_width_command;
+
+ add_show_from_set
+ (add_set_cmd ("height", class_support,
+ var_uinteger, (char *)&lines_per_page,
+ "Set number of lines gdb thinks are in a page.", &setlist),
+ &showlist);
+
+ /* These defaults will be used if we are unable to get the correct
+ values from termcap. */
+#if defined(__GO32__) || defined(__WIN32__)
+ lines_per_page = ScreenRows();
+ chars_per_line = ScreenCols();
+#else
+ lines_per_page = 24;
+ chars_per_line = 80;
+
+#ifndef MPW
+ /* No termcap under MPW, although might be cool to do something
+ by looking at worksheet or console window sizes. */
+ /* Initialize the screen height and width from termcap. */
+ {
+ char *termtype = getenv ("TERM");
+
+ /* Positive means success, nonpositive means failure. */
+ int status;
+
+ /* 2048 is large enough for all known terminals, according to the
+ GNU termcap manual. */
+ char term_buffer[2048];
+
+ if (termtype)
+ {
+ status = tgetent (term_buffer, termtype);
+ if (status > 0)
+ {
+ int val;
+
+ val = tgetnum ("li");
+ if (val >= 0)
+ lines_per_page = val;
+ else
+ /* The number of lines per page is not mentioned
+ in the terminal description. This probably means
+ that paging is not useful (e.g. emacs shell window),
+ so disable paging. */
+ lines_per_page = UINT_MAX;
+
+ val = tgetnum ("co");
+ if (val >= 0)
+ chars_per_line = val;
+ }
+ }
+ }
+#endif /* MPW */
+
+#if defined(SIGWINCH) && defined(SIGWINCH_HANDLER)
+
+ /* If there is a better way to determine the window size, use it. */
+ SIGWINCH_HANDLER ();
+#endif
+#endif
+ /* If the output is not a terminal, don't paginate it. */
+ if (!ISATTY (gdb_stdout))
+ lines_per_page = UINT_MAX;
+
+ set_width_command ((char *)NULL, 0, c);
+
+ add_show_from_set
+ (add_set_cmd ("demangle", class_support, var_boolean,
+ (char *)&demangle,
+ "Set demangling of encoded C++ names when displaying symbols.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("sevenbit-strings", class_support, var_boolean,
+ (char *)&sevenbit_strings,
+ "Set printing of 8-bit characters in strings as \\nnn.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("asm-demangle", class_support, var_boolean,
+ (char *)&asm_demangle,
+ "Set demangling of C++ names in disassembly listings.",
+ &setprintlist),
+ &showprintlist);
+}
+
+/* Machine specific function to handle SIGWINCH signal. */
+
+#ifdef SIGWINCH_HANDLER_BODY
+ SIGWINCH_HANDLER_BODY
+#endif
+
diff --git a/contrib/gdb/gdb/valarith.c b/contrib/gdb/gdb/valarith.c
new file mode 100644
index 0000000..c03d0a4
--- /dev/null
+++ b/contrib/gdb/gdb/valarith.c
@@ -0,0 +1,1213 @@
+/* Perform arithmetic and other operations on values, for GDB.
+ Copyright 1986, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "value.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "target.h"
+#include "language.h"
+#include "demangle.h"
+#include "gdb_string.h"
+
+/* Define whether or not the C operator '/' truncates towards zero for
+ differently signed operands (truncation direction is undefined in C). */
+
+#ifndef TRUNCATION_TOWARDS_ZERO
+#define TRUNCATION_TOWARDS_ZERO ((-5 / 2) == -2)
+#endif
+
+static value_ptr value_subscripted_rvalue PARAMS ((value_ptr, value_ptr, int));
+
+
+value_ptr
+value_add (arg1, arg2)
+ value_ptr arg1, arg2;
+{
+ register value_ptr valint, valptr;
+ register int len;
+ struct type *type1, *type2, *valptrtype;
+
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ if ((TYPE_CODE (type1) == TYPE_CODE_PTR
+ || TYPE_CODE (type2) == TYPE_CODE_PTR)
+ &&
+ (TYPE_CODE (type1) == TYPE_CODE_INT
+ || TYPE_CODE (type2) == TYPE_CODE_INT))
+ /* Exactly one argument is a pointer, and one is an integer. */
+ {
+ if (TYPE_CODE (type1) == TYPE_CODE_PTR)
+ {
+ valptr = arg1;
+ valint = arg2;
+ valptrtype = type1;
+ }
+ else
+ {
+ valptr = arg2;
+ valint = arg1;
+ valptrtype = type2;
+ }
+ len = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (valptrtype)));
+ if (len == 0) len = 1; /* For (void *) */
+ return value_from_longest (valptrtype,
+ value_as_long (valptr)
+ + (len * value_as_long (valint)));
+ }
+
+ return value_binop (arg1, arg2, BINOP_ADD);
+}
+
+value_ptr
+value_sub (arg1, arg2)
+ value_ptr arg1, arg2;
+{
+ struct type *type1, *type2;
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ if (TYPE_CODE (type1) == TYPE_CODE_PTR)
+ {
+ if (TYPE_CODE (type2) == TYPE_CODE_INT)
+ {
+ /* pointer - integer. */
+ LONGEST sz = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)));
+ return value_from_longest
+ (VALUE_TYPE (arg1),
+ value_as_long (arg1) - (sz * value_as_long (arg2)));
+ }
+ else if (TYPE_CODE (type2) == TYPE_CODE_PTR
+ && TYPE_LENGTH (TYPE_TARGET_TYPE (type1))
+ == TYPE_LENGTH (TYPE_TARGET_TYPE (type2)))
+ {
+ /* pointer to <type x> - pointer to <type x>. */
+ LONGEST sz = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)));
+ return value_from_longest
+ (builtin_type_long, /* FIXME -- should be ptrdiff_t */
+ (value_as_long (arg1) - value_as_long (arg2)) / sz);
+ }
+ else
+ {
+ error ("\
+First argument of `-' is a pointer and second argument is neither\n\
+an integer nor a pointer of the same type.");
+ }
+ }
+
+ return value_binop (arg1, arg2, BINOP_SUB);
+}
+
+/* Return the value of ARRAY[IDX].
+ See comments in value_coerce_array() for rationale for reason for
+ doing lower bounds adjustment here rather than there.
+ FIXME: Perhaps we should validate that the index is valid and if
+ verbosity is set, warn about invalid indices (but still use them). */
+
+value_ptr
+value_subscript (array, idx)
+ value_ptr array, idx;
+{
+ value_ptr bound;
+ int c_style = current_language->c_style_arrays;
+ struct type *tarray;
+
+ COERCE_REF (array);
+ tarray = check_typedef (VALUE_TYPE (array));
+ COERCE_VARYING_ARRAY (array, tarray);
+
+ if (TYPE_CODE (tarray) == TYPE_CODE_ARRAY
+ || TYPE_CODE (tarray) == TYPE_CODE_STRING)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (tarray);
+ LONGEST lowerbound, upperbound;
+ get_discrete_bounds (range_type, &lowerbound, &upperbound);
+
+ if (VALUE_LVAL (array) != lval_memory)
+ return value_subscripted_rvalue (array, idx, lowerbound);
+
+ if (c_style == 0)
+ {
+ LONGEST index = value_as_long (idx);
+ if (index >= lowerbound && index <= upperbound)
+ return value_subscripted_rvalue (array, idx, lowerbound);
+ warning ("array or string index out of range");
+ /* fall doing C stuff */
+ c_style = 1;
+ }
+
+ if (lowerbound != 0)
+ {
+ bound = value_from_longest (builtin_type_int, (LONGEST) lowerbound);
+ idx = value_sub (idx, bound);
+ }
+
+ array = value_coerce_array (array);
+ }
+
+ if (TYPE_CODE (tarray) == TYPE_CODE_BITSTRING)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (tarray);
+ LONGEST index = value_as_long (idx);
+ value_ptr v;
+ int offset, byte, bit_index;
+ LONGEST lowerbound, upperbound;
+ get_discrete_bounds (range_type, &lowerbound, &upperbound);
+ if (index < lowerbound || index > upperbound)
+ error ("bitstring index out of range");
+ index -= lowerbound;
+ offset = index / TARGET_CHAR_BIT;
+ byte = *((char*)VALUE_CONTENTS (array) + offset);
+ bit_index = index % TARGET_CHAR_BIT;
+ byte >>= (BITS_BIG_ENDIAN ? TARGET_CHAR_BIT - 1 - bit_index : bit_index);
+ v = value_from_longest (LA_BOOL_TYPE, byte & 1);
+ VALUE_BITPOS (v) = bit_index;
+ VALUE_BITSIZE (v) = 1;
+ VALUE_LVAL (v) = VALUE_LVAL (array);
+ if (VALUE_LVAL (array) == lval_internalvar)
+ VALUE_LVAL (v) = lval_internalvar_component;
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (array);
+ VALUE_OFFSET (v) = offset + VALUE_OFFSET (array);
+ return v;
+ }
+
+ if (c_style)
+ return value_ind (value_add (array, idx));
+ else
+ error ("not an array or string");
+}
+
+/* Return the value of EXPR[IDX], expr an aggregate rvalue
+ (eg, a vector register). This routine used to promote floats
+ to doubles, but no longer does. */
+
+static value_ptr
+value_subscripted_rvalue (array, idx, lowerbound)
+ value_ptr array, idx;
+ int lowerbound;
+{
+ struct type *array_type = check_typedef (VALUE_TYPE (array));
+ struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type));
+ unsigned int elt_size = TYPE_LENGTH (elt_type);
+ LONGEST index = value_as_long (idx);
+ unsigned int elt_offs = elt_size * longest_to_int (index - lowerbound);
+ value_ptr v;
+
+ if (index < lowerbound || elt_offs >= TYPE_LENGTH (array_type))
+ error ("no such vector element");
+
+ v = allocate_value (elt_type);
+ if (VALUE_LAZY (array))
+ VALUE_LAZY (v) = 1;
+ else
+ memcpy (VALUE_CONTENTS (v), VALUE_CONTENTS (array) + elt_offs, elt_size);
+
+ if (VALUE_LVAL (array) == lval_internalvar)
+ VALUE_LVAL (v) = lval_internalvar_component;
+ else
+ VALUE_LVAL (v) = VALUE_LVAL (array);
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (array);
+ VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs;
+ return v;
+}
+
+/* Check to see if either argument is a structure. This is called so
+ we know whether to go ahead with the normal binop or look for a
+ user defined function instead.
+
+ For now, we do not overload the `=' operator. */
+
+int
+binop_user_defined_p (op, arg1, arg2)
+ enum exp_opcode op;
+ value_ptr arg1, arg2;
+{
+ struct type *type1, *type2;
+ if (op == BINOP_ASSIGN || op == BINOP_CONCAT)
+ return 0;
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ return (TYPE_CODE (type1) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type2) == TYPE_CODE_STRUCT
+ || (TYPE_CODE (type1) == TYPE_CODE_REF
+ && TYPE_CODE (TYPE_TARGET_TYPE (type1)) == TYPE_CODE_STRUCT)
+ || (TYPE_CODE (type2) == TYPE_CODE_REF
+ && TYPE_CODE (TYPE_TARGET_TYPE (type2)) == TYPE_CODE_STRUCT));
+}
+
+/* Check to see if argument is a structure. This is called so
+ we know whether to go ahead with the normal unop or look for a
+ user defined function instead.
+
+ For now, we do not overload the `&' operator. */
+
+int unop_user_defined_p (op, arg1)
+ enum exp_opcode op;
+ value_ptr arg1;
+{
+ struct type *type1;
+ if (op == UNOP_ADDR)
+ return 0;
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ for (;;)
+ {
+ if (TYPE_CODE (type1) == TYPE_CODE_STRUCT)
+ return 1;
+ else if (TYPE_CODE (type1) == TYPE_CODE_REF)
+ type1 = TYPE_TARGET_TYPE (type1);
+ else
+ return 0;
+ }
+}
+
+/* We know either arg1 or arg2 is a structure, so try to find the right
+ user defined function. Create an argument vector that calls
+ arg1.operator @ (arg1,arg2) and return that value (where '@' is any
+ binary operator which is legal for GNU C++).
+
+ OP is the operatore, and if it is BINOP_ASSIGN_MODIFY, then OTHEROP
+ is the opcode saying how to modify it. Otherwise, OTHEROP is
+ unused. */
+
+value_ptr
+value_x_binop (arg1, arg2, op, otherop)
+ value_ptr arg1, arg2;
+ enum exp_opcode op, otherop;
+{
+ value_ptr * argvec;
+ char *ptr;
+ char tstr[13];
+ int static_memfuncp;
+
+ COERCE_REF (arg1);
+ COERCE_REF (arg2);
+ COERCE_ENUM (arg1);
+ COERCE_ENUM (arg2);
+
+ /* now we know that what we have to do is construct our
+ arg vector and find the right function to call it with. */
+
+ if (TYPE_CODE (check_typedef (VALUE_TYPE (arg1))) != TYPE_CODE_STRUCT)
+ error ("Can't do that binary op on that type"); /* FIXME be explicit */
+
+ argvec = (value_ptr *) alloca (sizeof (value_ptr) * 4);
+ argvec[1] = value_addr (arg1);
+ argvec[2] = arg2;
+ argvec[3] = 0;
+
+ /* make the right function name up */
+ strcpy(tstr, "operator__");
+ ptr = tstr+8;
+ switch (op)
+ {
+ case BINOP_ADD: strcpy(ptr,"+"); break;
+ case BINOP_SUB: strcpy(ptr,"-"); break;
+ case BINOP_MUL: strcpy(ptr,"*"); break;
+ case BINOP_DIV: strcpy(ptr,"/"); break;
+ case BINOP_REM: strcpy(ptr,"%"); break;
+ case BINOP_LSH: strcpy(ptr,"<<"); break;
+ case BINOP_RSH: strcpy(ptr,">>"); break;
+ case BINOP_BITWISE_AND: strcpy(ptr,"&"); break;
+ case BINOP_BITWISE_IOR: strcpy(ptr,"|"); break;
+ case BINOP_BITWISE_XOR: strcpy(ptr,"^"); break;
+ case BINOP_LOGICAL_AND: strcpy(ptr,"&&"); break;
+ case BINOP_LOGICAL_OR: strcpy(ptr,"||"); break;
+ case BINOP_MIN: strcpy(ptr,"<?"); break;
+ case BINOP_MAX: strcpy(ptr,">?"); break;
+ case BINOP_ASSIGN: strcpy(ptr,"="); break;
+ case BINOP_ASSIGN_MODIFY:
+ switch (otherop)
+ {
+ case BINOP_ADD: strcpy(ptr,"+="); break;
+ case BINOP_SUB: strcpy(ptr,"-="); break;
+ case BINOP_MUL: strcpy(ptr,"*="); break;
+ case BINOP_DIV: strcpy(ptr,"/="); break;
+ case BINOP_REM: strcpy(ptr,"%="); break;
+ case BINOP_BITWISE_AND: strcpy(ptr,"&="); break;
+ case BINOP_BITWISE_IOR: strcpy(ptr,"|="); break;
+ case BINOP_BITWISE_XOR: strcpy(ptr,"^="); break;
+ case BINOP_MOD: /* invalid */
+ default:
+ error ("Invalid binary operation specified.");
+ }
+ break;
+ case BINOP_SUBSCRIPT: strcpy(ptr,"[]"); break;
+ case BINOP_EQUAL: strcpy(ptr,"=="); break;
+ case BINOP_NOTEQUAL: strcpy(ptr,"!="); break;
+ case BINOP_LESS: strcpy(ptr,"<"); break;
+ case BINOP_GTR: strcpy(ptr,">"); break;
+ case BINOP_GEQ: strcpy(ptr,">="); break;
+ case BINOP_LEQ: strcpy(ptr,"<="); break;
+ case BINOP_MOD: /* invalid */
+ default:
+ error ("Invalid binary operation specified.");
+ }
+
+ argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure");
+
+ if (argvec[0])
+ {
+ if (static_memfuncp)
+ {
+ argvec[1] = argvec[0];
+ argvec++;
+ }
+ return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);
+ }
+ error ("member function %s not found", tstr);
+#ifdef lint
+ return call_function_by_hand (argvec[0], 2 - static_memfuncp, argvec + 1);
+#endif
+}
+
+/* We know that arg1 is a structure, so try to find a unary user
+ defined operator that matches the operator in question.
+ Create an argument vector that calls arg1.operator @ (arg1)
+ and return that value (where '@' is (almost) any unary operator which
+ is legal for GNU C++). */
+
+value_ptr
+value_x_unop (arg1, op)
+ value_ptr arg1;
+ enum exp_opcode op;
+{
+ value_ptr * argvec;
+ char *ptr, *mangle_ptr;
+ char tstr[13], mangle_tstr[13];
+ int static_memfuncp;
+
+ COERCE_REF (arg1);
+ COERCE_ENUM (arg1);
+
+ /* now we know that what we have to do is construct our
+ arg vector and find the right function to call it with. */
+
+ if (TYPE_CODE (check_typedef (VALUE_TYPE (arg1))) != TYPE_CODE_STRUCT)
+ error ("Can't do that unary op on that type"); /* FIXME be explicit */
+
+ 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;
+ case UNOP_PREDECREMENT: strcpy(ptr,"++"); break;
+ case UNOP_POSTINCREMENT: strcpy(ptr,"++"); break;
+ case UNOP_POSTDECREMENT: strcpy(ptr,"++"); break;
+ case UNOP_LOGICAL_NOT: strcpy(ptr,"!"); break;
+ case UNOP_COMPLEMENT: strcpy(ptr,"~"); break;
+ case UNOP_NEG: strcpy(ptr,"-"); break;
+ default:
+ error ("Invalid binary operation specified.");
+ }
+
+ argvec[0] = value_struct_elt (&arg1, argvec+1, tstr, &static_memfuncp, "structure");
+
+ if (argvec[0])
+ {
+ if (static_memfuncp)
+ {
+ argvec[1] = argvec[0];
+ argvec++;
+ }
+ return call_function_by_hand (argvec[0], 1 - static_memfuncp, argvec + 1);
+ }
+ error ("member function %s not found", tstr);
+ return 0; /* For lint -- never reached */
+}
+
+
+/* Concatenate two values with the following conditions:
+
+ (1) Both values must be either bitstring values or character string
+ values and the resulting value consists of the concatenation of
+ ARG1 followed by ARG2.
+
+ or
+
+ One value must be an integer value and the other value must be
+ either a bitstring value or character string value, which is
+ to be repeated by the number of times specified by the integer
+ value.
+
+
+ (2) Boolean values are also allowed and are treated as bit string
+ values of length 1.
+
+ (3) Character values are also allowed and are treated as character
+ string values of length 1.
+*/
+
+value_ptr
+value_concat (arg1, arg2)
+ value_ptr arg1, arg2;
+{
+ register value_ptr inval1, inval2, outval;
+ int inval1len, inval2len;
+ int count, idx;
+ char *ptr;
+ char inchar;
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+ struct type *type2 = check_typedef (VALUE_TYPE (arg2));
+
+ COERCE_VARYING_ARRAY (arg1, type1);
+ COERCE_VARYING_ARRAY (arg2, type2);
+
+ /* First figure out if we are dealing with two values to be concatenated
+ or a repeat count and a value to be repeated. INVAL1 is set to the
+ first of two concatenated values, or the repeat count. INVAL2 is set
+ to the second of the two concatenated values or the value to be
+ repeated. */
+
+ if (TYPE_CODE (type2) == TYPE_CODE_INT)
+ {
+ struct type *tmp = type1;
+ type1 = tmp;
+ tmp = type2;
+ inval1 = arg2;
+ inval2 = arg1;
+ }
+ else
+ {
+ inval1 = arg1;
+ inval2 = arg2;
+ }
+
+ /* Now process the input values. */
+
+ if (TYPE_CODE (type1) == TYPE_CODE_INT)
+ {
+ /* We have a repeat count. Validate the second value and then
+ construct a value repeated that many times. */
+ if (TYPE_CODE (type2) == TYPE_CODE_STRING
+ || TYPE_CODE (type2) == TYPE_CODE_CHAR)
+ {
+ count = longest_to_int (value_as_long (inval1));
+ inval2len = TYPE_LENGTH (type2);
+ ptr = (char *) alloca (count * inval2len);
+ if (TYPE_CODE (type2) == TYPE_CODE_CHAR)
+ {
+ inchar = (char) unpack_long (type2,
+ VALUE_CONTENTS (inval2));
+ for (idx = 0; idx < count; idx++)
+ {
+ *(ptr + idx) = inchar;
+ }
+ }
+ else
+ {
+ for (idx = 0; idx < count; idx++)
+ {
+ memcpy (ptr + (idx * inval2len), VALUE_CONTENTS (inval2),
+ inval2len);
+ }
+ }
+ outval = value_string (ptr, count * inval2len);
+ }
+ else if (TYPE_CODE (type2) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (type2) == TYPE_CODE_BOOL)
+ {
+ error ("unimplemented support for bitstring/boolean repeats");
+ }
+ else
+ {
+ error ("can't repeat values of that type");
+ }
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_STRING
+ || TYPE_CODE (type1) == TYPE_CODE_CHAR)
+ {
+ /* We have two character strings to concatenate. */
+ if (TYPE_CODE (type2) != TYPE_CODE_STRING
+ && TYPE_CODE (type2) != TYPE_CODE_CHAR)
+ {
+ error ("Strings can only be concatenated with other strings.");
+ }
+ inval1len = TYPE_LENGTH (type1);
+ inval2len = TYPE_LENGTH (type2);
+ ptr = (char *) alloca (inval1len + inval2len);
+ if (TYPE_CODE (type1) == TYPE_CODE_CHAR)
+ {
+ *ptr = (char) unpack_long (type1, VALUE_CONTENTS (inval1));
+ }
+ else
+ {
+ memcpy (ptr, VALUE_CONTENTS (inval1), inval1len);
+ }
+ if (TYPE_CODE (type2) == TYPE_CODE_CHAR)
+ {
+ *(ptr + inval1len) =
+ (char) unpack_long (type2, VALUE_CONTENTS (inval2));
+ }
+ else
+ {
+ memcpy (ptr + inval1len, VALUE_CONTENTS (inval2), inval2len);
+ }
+ outval = value_string (ptr, inval1len + inval2len);
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (type1) == TYPE_CODE_BOOL)
+ {
+ /* We have two bitstrings to concatenate. */
+ if (TYPE_CODE (type2) != TYPE_CODE_BITSTRING
+ && TYPE_CODE (type2) != TYPE_CODE_BOOL)
+ {
+ error ("Bitstrings or booleans can only be concatenated with other bitstrings or booleans.");
+ }
+ error ("unimplemented support for bitstring/boolean concatenation.");
+ }
+ else
+ {
+ /* We don't know how to concatenate these operands. */
+ error ("illegal operands for concatenation.");
+ }
+ return (outval);
+}
+
+
+
+/* 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_ptr
+value_binop (arg1, arg2, op)
+ value_ptr arg1, arg2;
+ enum exp_opcode op;
+{
+ register value_ptr val;
+ struct type *type1, *type2;
+
+ COERCE_REF (arg1);
+ COERCE_REF (arg2);
+ COERCE_ENUM (arg1);
+ COERCE_ENUM (arg2);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ if ((TYPE_CODE (type1) != TYPE_CODE_FLT
+ && TYPE_CODE (type1) != TYPE_CODE_CHAR
+ && TYPE_CODE (type1) != TYPE_CODE_INT
+ && TYPE_CODE (type1) != TYPE_CODE_BOOL
+ && TYPE_CODE (type1) != TYPE_CODE_RANGE)
+ ||
+ (TYPE_CODE (type2) != TYPE_CODE_FLT
+ && TYPE_CODE (type2) != TYPE_CODE_CHAR
+ && TYPE_CODE (type2) != TYPE_CODE_INT
+ && TYPE_CODE (type2) != TYPE_CODE_BOOL
+ && TYPE_CODE (type2) != TYPE_CODE_RANGE))
+ error ("Argument to arithmetic operation not a number or boolean.");
+
+ if (TYPE_CODE (type1) == TYPE_CODE_FLT
+ ||
+ TYPE_CODE (type2) == 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. */
+ DOUBLEST v1, v2, v;
+ v1 = value_as_double (arg1);
+ v2 = value_as_double (arg2);
+ switch (op)
+ {
+ case BINOP_ADD:
+ v = v1 + v2;
+ break;
+
+ case BINOP_SUB:
+ v = v1 - v2;
+ break;
+
+ case BINOP_MUL:
+ v = v1 * v2;
+ break;
+
+ case BINOP_DIV:
+ v = v1 / v2;
+ break;
+
+ default:
+ error ("Integer-only operation on floating point number.");
+ }
+
+ /* If either arg was long double, make sure that value is also long
+ double. */
+
+ if (TYPE_LENGTH(type1) * 8 > TARGET_DOUBLE_BIT
+ || TYPE_LENGTH(type2) * 8 > TARGET_DOUBLE_BIT)
+ val = allocate_value (builtin_type_long_double);
+ else
+ val = allocate_value (builtin_type_double);
+
+ store_floating (VALUE_CONTENTS_RAW (val), TYPE_LENGTH (VALUE_TYPE (val)),
+ v);
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
+ &&
+ TYPE_CODE (type2) == TYPE_CODE_BOOL)
+ {
+ LONGEST v1, v2, v;
+ v1 = value_as_long (arg1);
+ v2 = value_as_long (arg2);
+
+ switch (op)
+ {
+ case BINOP_BITWISE_AND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_BITWISE_IOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_BITWISE_XOR:
+ v = v1 ^ v2;
+ break;
+
+ default:
+ error ("Invalid operation on booleans.");
+ }
+
+ val = allocate_value (type1);
+ store_signed_integer (VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (type1),
+ v);
+ }
+ else
+ /* Integral operations here. */
+ /* FIXME: Also mixed integral/booleans, with result an integer. */
+ /* FIXME: This implements ANSI C rules (also correct for C++).
+ What about FORTRAN and chill? */
+ {
+ unsigned int promoted_len1 = TYPE_LENGTH (type1);
+ unsigned int promoted_len2 = TYPE_LENGTH (type2);
+ int is_unsigned1 = TYPE_UNSIGNED (type1);
+ int is_unsigned2 = TYPE_UNSIGNED (type2);
+ unsigned int result_len;
+ int unsigned_operation;
+
+ /* Determine type length and signedness after promotion for
+ both operands. */
+ if (promoted_len1 < TYPE_LENGTH (builtin_type_int))
+ {
+ is_unsigned1 = 0;
+ promoted_len1 = TYPE_LENGTH (builtin_type_int);
+ }
+ if (promoted_len2 < TYPE_LENGTH (builtin_type_int))
+ {
+ is_unsigned2 = 0;
+ promoted_len2 = TYPE_LENGTH (builtin_type_int);
+ }
+
+ /* Determine type length of the result, and if the operation should
+ be done unsigned.
+ Use the signedness of the operand with the greater length.
+ If both operands are of equal length, use unsigned operation
+ if one of the operands is unsigned. */
+ if (promoted_len1 > promoted_len2)
+ {
+ unsigned_operation = is_unsigned1;
+ result_len = promoted_len1;
+ }
+ else if (promoted_len2 > promoted_len1)
+ {
+ unsigned_operation = is_unsigned2;
+ result_len = promoted_len2;
+ }
+ else
+ {
+ unsigned_operation = is_unsigned1 || is_unsigned2;
+ result_len = promoted_len1;
+ }
+
+ if (unsigned_operation)
+ {
+ unsigned LONGEST v1, v2, v;
+ v1 = (unsigned LONGEST) value_as_long (arg1);
+ v2 = (unsigned LONGEST) value_as_long (arg2);
+
+ /* Truncate values to the type length of the result. */
+ if (result_len < sizeof (unsigned LONGEST))
+ {
+ v1 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1;
+ v2 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1;
+ }
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ v = v1 + v2;
+ break;
+
+ case BINOP_SUB:
+ v = v1 - v2;
+ break;
+
+ case BINOP_MUL:
+ v = v1 * v2;
+ break;
+
+ case BINOP_DIV:
+ v = v1 / v2;
+ break;
+
+ case BINOP_REM:
+ v = v1 % v2;
+ break;
+
+ case BINOP_MOD:
+ /* Knuth 1.2.4, integer only. Note that unlike the C '%' op,
+ v1 mod 0 has a defined value, v1. */
+ /* Chill specifies that v2 must be > 0, so check for that. */
+ if (current_language -> la_language == language_chill
+ && value_as_long (arg2) <= 0)
+ {
+ error ("Second operand of MOD must be greater than zero.");
+ }
+ if (v2 == 0)
+ {
+ v = v1;
+ }
+ else
+ {
+ v = v1/v2;
+ /* Note floor(v1/v2) == v1/v2 for unsigned. */
+ v = v1 - (v2 * v);
+ }
+ break;
+
+ case BINOP_LSH:
+ v = v1 << v2;
+ break;
+
+ case BINOP_RSH:
+ v = v1 >> v2;
+ break;
+
+ case BINOP_BITWISE_AND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_BITWISE_IOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_BITWISE_XOR:
+ v = v1 ^ v2;
+ break;
+
+ case BINOP_LOGICAL_AND:
+ v = v1 && v2;
+ break;
+
+ case BINOP_LOGICAL_OR:
+ v = v1 || v2;
+ break;
+
+ case BINOP_MIN:
+ v = v1 < v2 ? v1 : v2;
+ break;
+
+ case BINOP_MAX:
+ v = v1 > v2 ? v1 : v2;
+ break;
+
+ case BINOP_EQUAL:
+ v = v1 == v2;
+ break;
+
+ case BINOP_LESS:
+ v = v1 < v2;
+ break;
+
+ default:
+ error ("Invalid binary operation on numbers.");
+ }
+
+ /* 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
+ (result_len > 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);
+ }
+ else
+ {
+ LONGEST v1, v2, v;
+ v1 = value_as_long (arg1);
+ v2 = value_as_long (arg2);
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ v = v1 + v2;
+ break;
+
+ case BINOP_SUB:
+ v = v1 - v2;
+ break;
+
+ case BINOP_MUL:
+ v = v1 * v2;
+ break;
+
+ case BINOP_DIV:
+ v = v1 / v2;
+ break;
+
+ case BINOP_REM:
+ v = v1 % v2;
+ break;
+
+ case BINOP_MOD:
+ /* Knuth 1.2.4, integer only. Note that unlike the C '%' op,
+ X mod 0 has a defined value, X. */
+ /* Chill specifies that v2 must be > 0, so check for that. */
+ if (current_language -> la_language == language_chill
+ && v2 <= 0)
+ {
+ error ("Second operand of MOD must be greater than zero.");
+ }
+ if (v2 == 0)
+ {
+ v = v1;
+ }
+ else
+ {
+ v = v1/v2;
+ /* Compute floor. */
+ if (TRUNCATION_TOWARDS_ZERO && (v < 0) && ((v1 % v2) != 0))
+ {
+ v--;
+ }
+ v = v1 - (v2 * v);
+ }
+ break;
+
+ case BINOP_LSH:
+ v = v1 << v2;
+ break;
+
+ case BINOP_RSH:
+ v = v1 >> v2;
+ break;
+
+ case BINOP_BITWISE_AND:
+ v = v1 & v2;
+ break;
+
+ case BINOP_BITWISE_IOR:
+ v = v1 | v2;
+ break;
+
+ case BINOP_BITWISE_XOR:
+ v = v1 ^ v2;
+ break;
+
+ case BINOP_LOGICAL_AND:
+ v = v1 && v2;
+ break;
+
+ case BINOP_LOGICAL_OR:
+ v = v1 || v2;
+ break;
+
+ case BINOP_MIN:
+ v = v1 < v2 ? v1 : v2;
+ break;
+
+ case BINOP_MAX:
+ v = v1 > v2 ? v1 : v2;
+ break;
+
+ case BINOP_EQUAL:
+ v = v1 == v2;
+ break;
+
+ case BINOP_LESS:
+ v = v1 < v2;
+ break;
+
+ default:
+ error ("Invalid binary operation on numbers.");
+ }
+
+ /* 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
+ (result_len > 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);
+ }
+ }
+
+ return val;
+}
+
+/* Simulate the C operator ! -- return 1 if ARG1 contains zero. */
+
+int
+value_logical_not (arg1)
+ value_ptr arg1;
+{
+ register int len;
+ register char *p;
+ struct type *type1;
+
+ COERCE_NUMBER (arg1);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_CODE (type1) == TYPE_CODE_FLT)
+ return 0 == value_as_double (arg1);
+
+ len = TYPE_LENGTH (type1);
+ p = VALUE_CONTENTS (arg1);
+
+ while (--len >= 0)
+ {
+ if (*p++)
+ break;
+ }
+
+ return len < 0;
+}
+
+/* Simulate the C operator == by returning a 1
+ iff ARG1 and ARG2 have equal contents. */
+
+int
+value_equal (arg1, arg2)
+ register value_ptr arg1, arg2;
+
+{
+ register int len;
+ register char *p1, *p2;
+ struct type *type1, *type2;
+ enum type_code code1;
+ enum type_code code2;
+
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ code1 = TYPE_CODE (type1);
+ code2 = TYPE_CODE (type2);
+
+ if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+ return longest_to_int (value_as_long (value_binop (arg1, arg2,
+ BINOP_EQUAL)));
+ else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+ && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+ return value_as_double (arg1) == value_as_double (arg2);
+
+ /* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
+ is bigger. */
+ else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
+ return value_as_pointer (arg1) == (CORE_ADDR) value_as_long (arg2);
+ else if (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT)
+ return (CORE_ADDR) value_as_long (arg1) == value_as_pointer (arg2);
+
+ else if (code1 == code2
+ && ((len = (int) TYPE_LENGTH (type1))
+ == (int) TYPE_LENGTH (type2)))
+ {
+ p1 = VALUE_CONTENTS (arg1);
+ p2 = VALUE_CONTENTS (arg2);
+ while (--len >= 0)
+ {
+ if (*p1++ != *p2++)
+ break;
+ }
+ return len < 0;
+ }
+ else
+ {
+ error ("Invalid type combination in equality test.");
+ return 0; /* For lint -- never reached */
+ }
+}
+
+/* Simulate the C operator < by returning 1
+ iff ARG1's contents are less than ARG2's. */
+
+int
+value_less (arg1, arg2)
+ register value_ptr arg1, arg2;
+{
+ register enum type_code code1;
+ register enum type_code code2;
+ struct type *type1, *type2;
+
+ COERCE_NUMBER (arg1);
+ COERCE_NUMBER (arg2);
+
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ code1 = TYPE_CODE (type1);
+ code2 = TYPE_CODE (type2);
+
+ if (code1 == TYPE_CODE_INT && code2 == TYPE_CODE_INT)
+ return longest_to_int (value_as_long (value_binop (arg1, arg2,
+ BINOP_LESS)));
+ else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
+ && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
+ return value_as_double (arg1) < value_as_double (arg2);
+ else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
+ return value_as_pointer (arg1) < value_as_pointer (arg2);
+
+ /* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
+ is bigger. */
+ else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_INT)
+ return value_as_pointer (arg1) < (CORE_ADDR) value_as_long (arg2);
+ else if (code2 == TYPE_CODE_PTR && code1 == TYPE_CODE_INT)
+ return (CORE_ADDR) value_as_long (arg1) < value_as_pointer (arg2);
+
+ else
+ {
+ error ("Invalid type combination in ordering comparison.");
+ return 0;
+ }
+}
+
+/* The unary operators - and ~. Both free the argument ARG1. */
+
+value_ptr
+value_neg (arg1)
+ register value_ptr arg1;
+{
+ register struct type *type;
+
+ COERCE_REF (arg1);
+ COERCE_ENUM (arg1);
+
+ type = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return value_from_double (type, - value_as_double (arg1));
+ else if (TYPE_CODE (type) == TYPE_CODE_INT)
+ return value_from_longest (type, - value_as_long (arg1));
+ else {
+ error ("Argument to negate operation not a number.");
+ return 0; /* For lint -- never reached */
+ }
+}
+
+value_ptr
+value_complement (arg1)
+ register value_ptr arg1;
+{
+ COERCE_REF (arg1);
+ COERCE_ENUM (arg1);
+
+ if (TYPE_CODE (check_typedef (VALUE_TYPE (arg1))) != TYPE_CODE_INT)
+ error ("Argument to complement operation not an integer.");
+
+ 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;
+{
+ LONGEST low_bound, high_bound;
+ LONGEST word;
+ unsigned rel_index;
+ struct type *range = TYPE_FIELD_TYPE (type, 0);
+ if (get_discrete_bounds (range, &low_bound, &high_bound) < 0)
+ return -2;
+ if (index < low_bound || index > high_bound)
+ return -1;
+ rel_index = index - low_bound;
+ word = unpack_long (builtin_type_unsigned_char,
+ valaddr + (rel_index / TARGET_CHAR_BIT));
+ rel_index %= TARGET_CHAR_BIT;
+ if (BITS_BIG_ENDIAN)
+ rel_index = TARGET_CHAR_BIT - 1 - rel_index;
+ return (word >> rel_index) & 1;
+}
+
+value_ptr
+value_in (element, set)
+ value_ptr element, set;
+{
+ int member;
+ struct type *settype = check_typedef (VALUE_TYPE (set));
+ struct type *eltype = check_typedef (VALUE_TYPE (element));
+ if (TYPE_CODE (eltype) == TYPE_CODE_RANGE)
+ eltype = TYPE_TARGET_TYPE (eltype);
+ if (TYPE_CODE (settype) != TYPE_CODE_SET)
+ error ("Second argument of 'IN' has wrong type");
+ if (TYPE_CODE (eltype) != TYPE_CODE_INT
+ && TYPE_CODE (eltype) != TYPE_CODE_CHAR
+ && TYPE_CODE (eltype) != TYPE_CODE_ENUM
+ && TYPE_CODE (eltype) != TYPE_CODE_BOOL)
+ error ("First argument of 'IN' has wrong type");
+ member = value_bit_index (settype, VALUE_CONTENTS (set),
+ value_as_long (element));
+ if (member < 0)
+ error ("First argument of 'IN' not in range");
+ return value_from_longest (LA_BOOL_TYPE, member);
+}
+
+void
+_initialize_valarith ()
+{
+}
diff --git a/contrib/gdb/gdb/valops.c b/contrib/gdb/gdb/valops.c
new file mode 100644
index 0000000..684b224
--- /dev/null
+++ b/contrib/gdb/gdb/valops.c
@@ -0,0 +1,2346 @@
+/* Perform non-arithmetic operations on values, for GDB.
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "frame.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "demangle.h"
+#include "language.h"
+
+#include <errno.h>
+#include "gdb_string.h"
+
+/* Default to coercing float to double in function calls only when there is
+ no prototype. Otherwise on targets where the debug information is incorrect
+ for either the prototype or non-prototype case, we can force it by defining
+ COERCE_FLOAT_TO_DOUBLE in the target configuration file. */
+
+#ifndef COERCE_FLOAT_TO_DOUBLE
+#define COERCE_FLOAT_TO_DOUBLE (param_type == NULL)
+#endif
+
+/* Local functions. */
+
+static int typecmp PARAMS ((int staticp, struct type *t1[], value_ptr t2[]));
+
+static CORE_ADDR find_function_addr PARAMS ((value_ptr, struct type **));
+
+static CORE_ADDR value_push PARAMS ((CORE_ADDR, value_ptr));
+
+static value_ptr search_struct_field PARAMS ((char *, value_ptr, int,
+ struct type *, int));
+
+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 *));
+
+static CORE_ADDR allocate_space_in_inferior PARAMS ((int));
+
+static value_ptr cast_into_complex PARAMS ((struct type *, value_ptr));
+
+#define VALUE_SUBSTRING_START(VAL) VALUE_FRAME(VAL)
+
+/* Flag for whether we want to abandon failed expression evals by default. */
+
+#if 0
+static int auto_abandon = 0;
+#endif
+
+
+/* Find the address of function name NAME in the inferior. */
+
+value_ptr
+find_function_in_inferior (name)
+ char *name;
+{
+ register struct symbol *sym;
+ sym = lookup_symbol (name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym != NULL)
+ {
+ if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+ {
+ error ("\"%s\" exists in this program but is not a function.",
+ name);
+ }
+ return value_of_variable (sym, NULL);
+ }
+ else
+ {
+ struct minimal_symbol *msymbol = lookup_minimal_symbol(name, NULL, NULL);
+ if (msymbol != NULL)
+ {
+ struct type *type;
+ LONGEST maddr;
+ type = lookup_pointer_type (builtin_type_char);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ maddr = (LONGEST) SYMBOL_VALUE_ADDRESS (msymbol);
+ return value_from_longest (type, maddr);
+ }
+ else
+ {
+ error ("evaluation of this expression requires the program to have a function \"%s\".", name);
+ }
+ }
+}
+
+/* Allocate NBYTES of space in the inferior using the inferior's malloc
+ and return a value that is a pointer to the allocated space. */
+
+value_ptr
+value_allocate_space_in_inferior (len)
+ int len;
+{
+ value_ptr blocklen;
+ register value_ptr val = find_function_in_inferior ("malloc");
+
+ blocklen = value_from_longest (builtin_type_int, (LONGEST) len);
+ val = call_function_by_hand (val, 1, &blocklen);
+ if (value_logical_not (val))
+ {
+ error ("No memory available to program.");
+ }
+ return val;
+}
+
+static CORE_ADDR
+allocate_space_in_inferior (len)
+ int len;
+{
+ return value_as_long (value_allocate_space_in_inferior (len));
+}
+
+/* Cast value ARG2 to type TYPE and return as a value.
+ More general than a C cast: accepts any two types of the same length,
+ and if ARG2 is an lvalue it can be cast into anything at all. */
+/* In C++, casts may change pointer or object representations. */
+
+value_ptr
+value_cast (type, arg2)
+ struct type *type;
+ register value_ptr arg2;
+{
+ register enum type_code code1;
+ register enum type_code code2;
+ register int scalar;
+ struct type *type2;
+
+ if (VALUE_TYPE (arg2) == type)
+ return arg2;
+
+ CHECK_TYPEDEF (type);
+ code1 = TYPE_CODE (type);
+ COERCE_REF(arg2);
+ type2 = check_typedef (VALUE_TYPE (arg2));
+
+ /* A cast to an undetermined-length array_type, such as (TYPE [])OBJECT,
+ is treated like a cast to (TYPE [N])OBJECT,
+ where N is sizeof(OBJECT)/sizeof(TYPE). */
+ if (code1 == TYPE_CODE_ARRAY)
+ {
+ struct type *element_type = TYPE_TARGET_TYPE (type);
+ unsigned element_length = TYPE_LENGTH (check_typedef (element_type));
+ if (element_length > 0
+ && TYPE_ARRAY_UPPER_BOUND_TYPE (type) == BOUND_CANNOT_BE_DETERMINED)
+ {
+ struct type *range_type = TYPE_INDEX_TYPE (type);
+ int val_length = TYPE_LENGTH (type2);
+ LONGEST low_bound, high_bound, new_length;
+ if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+ low_bound = 0, high_bound = 0;
+ new_length = val_length / element_length;
+ if (val_length % element_length != 0)
+ warning("array element type size does not divide object size in cast");
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ range_type = create_range_type ((struct type *) NULL,
+ TYPE_TARGET_TYPE (range_type),
+ low_bound,
+ new_length + low_bound - 1);
+ VALUE_TYPE (arg2) = create_array_type ((struct type *) NULL,
+ element_type, range_type);
+ return arg2;
+ }
+ }
+
+ if (current_language->c_style_arrays
+ && TYPE_CODE (type2) == TYPE_CODE_ARRAY)
+ arg2 = value_coerce_array (arg2);
+
+ if (TYPE_CODE (type2) == TYPE_CODE_FUNC)
+ arg2 = value_coerce_function (arg2);
+
+ type2 = check_typedef (VALUE_TYPE (arg2));
+ COERCE_VARYING_ARRAY (arg2, type2);
+ code2 = TYPE_CODE (type2);
+
+ if (code1 == TYPE_CODE_COMPLEX)
+ return cast_into_complex (type, arg2);
+ if (code1 == TYPE_CODE_BOOL || code1 == TYPE_CODE_CHAR)
+ code1 = TYPE_CODE_INT;
+ if (code2 == TYPE_CODE_BOOL || code2 == TYPE_CODE_CHAR)
+ code2 = TYPE_CODE_INT;
+
+ scalar = (code2 == TYPE_CODE_INT || code2 == TYPE_CODE_FLT
+ || code2 == TYPE_CODE_ENUM || code2 == TYPE_CODE_RANGE);
+
+ if ( code1 == TYPE_CODE_STRUCT
+ && code2 == TYPE_CODE_STRUCT
+ && TYPE_NAME (type) != 0)
+ {
+ /* 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_ptr v = search_struct_field (type_name_no_tag (type),
+ arg2, 0, type2, 1);
+ if (v)
+ {
+ VALUE_TYPE (v) = type;
+ return v;
+ }
+ }
+ if (code1 == TYPE_CODE_FLT && scalar)
+ return value_from_double (type, value_as_double (arg2));
+ else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM
+ || code1 == TYPE_CODE_RANGE)
+ && (scalar || code2 == TYPE_CODE_PTR))
+ return value_from_longest (type, value_as_long (arg2));
+ else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2))
+ {
+ if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
+ {
+ /* 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 pointer rather than just change its type. */
+ struct type *t1 = check_typedef (TYPE_TARGET_TYPE (type));
+ struct type *t2 = check_typedef (TYPE_TARGET_TYPE (type2));
+ if ( TYPE_CODE (t1) == TYPE_CODE_STRUCT
+ && TYPE_CODE (t2) == TYPE_CODE_STRUCT
+ && TYPE_NAME (t1) != 0) /* if name unknown, can't have supercl */
+ {
+ value_ptr v = search_struct_field (type_name_no_tag (t1),
+ value_ind (arg2), 0, t2, 1);
+ if (v)
+ {
+ v = value_addr (v);
+ VALUE_TYPE (v) = type;
+ return v;
+ }
+ }
+ /* No superclass found, just fall through to change ptr type. */
+ }
+ VALUE_TYPE (arg2) = type;
+ return arg2;
+ }
+ else if (chill_varying_type (type))
+ {
+ struct type *range1, *range2, *eltype1, *eltype2;
+ value_ptr val;
+ int count1, count2;
+ LONGEST low_bound, high_bound;
+ char *valaddr, *valaddr_data;
+ if (code2 == TYPE_CODE_BITSTRING)
+ error ("not implemented: converting bitstring to varying type");
+ if ((code2 != TYPE_CODE_ARRAY && code2 != TYPE_CODE_STRING)
+ || (eltype1 = check_typedef (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 1))),
+ eltype2 = check_typedef (TYPE_TARGET_TYPE (type2)),
+ (TYPE_LENGTH (eltype1) != TYPE_LENGTH (eltype2)
+ /* || TYPE_CODE (eltype1) != TYPE_CODE (eltype2) */ )))
+ error ("Invalid conversion to varying type");
+ range1 = TYPE_FIELD_TYPE (TYPE_FIELD_TYPE (type, 1), 0);
+ range2 = TYPE_FIELD_TYPE (type2, 0);
+ if (get_discrete_bounds (range1, &low_bound, &high_bound) < 0)
+ count1 = -1;
+ else
+ count1 = high_bound - low_bound + 1;
+ if (get_discrete_bounds (range2, &low_bound, &high_bound) < 0)
+ count1 = -1, count2 = 0; /* To force error before */
+ else
+ count2 = high_bound - low_bound + 1;
+ if (count2 > count1)
+ error ("target varying type is too small");
+ val = allocate_value (type);
+ valaddr = VALUE_CONTENTS_RAW (val);
+ valaddr_data = valaddr + TYPE_FIELD_BITPOS (type, 1) / 8;
+ /* Set val's __var_length field to count2. */
+ store_signed_integer (valaddr, TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)),
+ count2);
+ /* Set the __var_data field to count2 elements copied from arg2. */
+ memcpy (valaddr_data, VALUE_CONTENTS (arg2),
+ count2 * TYPE_LENGTH (eltype2));
+ /* Zero the rest of the __var_data field of val. */
+ memset (valaddr_data + count2 * TYPE_LENGTH (eltype2), '\0',
+ (count1 - count2) * TYPE_LENGTH (eltype2));
+ return val;
+ }
+ else if (VALUE_LVAL (arg2) == lval_memory)
+ {
+ return value_at_lazy (type, VALUE_ADDRESS (arg2) + VALUE_OFFSET (arg2));
+ }
+ else if (code1 == TYPE_CODE_VOID)
+ {
+ return value_zero (builtin_type_void, not_lval);
+ }
+ else
+ {
+ error ("Invalid cast.");
+ return 0;
+ }
+}
+
+/* Create a value of type TYPE that is zero, and return it. */
+
+value_ptr
+value_zero (type, lv)
+ struct type *type;
+ enum lval_type lv;
+{
+ register value_ptr val = allocate_value (type);
+
+ memset (VALUE_CONTENTS (val), 0, TYPE_LENGTH (check_typedef (type)));
+ VALUE_LVAL (val) = lv;
+
+ return val;
+}
+
+/* Return a value with type TYPE located at ADDR.
+
+ Call value_at only if the data needs to be fetched immediately;
+ if we can be 'lazy' and defer the fetch, perhaps indefinately, call
+ value_at_lazy instead. value_at_lazy simply records the address of
+ the data and sets the lazy-evaluation-required flag. The lazy flag
+ is tested in the VALUE_CONTENTS macro, which is used if and when
+ the contents are actually required. */
+
+value_ptr
+value_at (type, addr)
+ struct type *type;
+ CORE_ADDR addr;
+{
+ register value_ptr val;
+
+ if (TYPE_CODE (check_typedef (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));
+
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = addr;
+
+ return val;
+}
+
+/* Return a lazy value with type TYPE located at ADDR (cf. value_at). */
+
+value_ptr
+value_at_lazy (type, addr)
+ struct type *type;
+ CORE_ADDR addr;
+{
+ register value_ptr val;
+
+ if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
+ error ("Attempt to dereference a generic pointer.");
+
+ val = allocate_value (type);
+
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = addr;
+ VALUE_LAZY (val) = 1;
+
+ return val;
+}
+
+/* Called only from the VALUE_CONTENTS macro, if the current data for
+ a variable needs to be loaded into VALUE_CONTENTS(VAL). Fetches the
+ data from the user's process, and clears the lazy flag to indicate
+ that the data in the buffer is valid.
+
+ If the value is zero-length, we avoid calling read_memory, which would
+ abort. We mark the value as fetched anyway -- all 0 bytes of it.
+
+ This function returns a value because it is used in the VALUE_CONTENTS
+ macro as part of an expression, where a void would not work. The
+ value is ignored. */
+
+int
+value_fetch_lazy (val)
+ register value_ptr val;
+{
+ CORE_ADDR addr = VALUE_ADDRESS (val) + VALUE_OFFSET (val);
+ int length = TYPE_LENGTH (VALUE_TYPE (val));
+
+ if (length)
+ read_memory (addr, VALUE_CONTENTS_RAW (val), length);
+ VALUE_LAZY (val) = 0;
+ return 0;
+}
+
+
+/* Store the contents of FROMVAL into the location of TOVAL.
+ Return a new value with the location of TOVAL and contents of FROMVAL. */
+
+value_ptr
+value_assign (toval, fromval)
+ register value_ptr toval, fromval;
+{
+ register struct type *type;
+ register value_ptr val;
+ char raw_buffer[MAX_REGISTER_RAW_SIZE];
+ int use_buffer = 0;
+
+ if (!toval->modifiable)
+ error ("Left operand of assignment is not a modifiable lvalue.");
+
+ COERCE_REF (toval);
+
+ type = VALUE_TYPE (toval);
+ if (VALUE_LVAL (toval) != lval_internalvar)
+ fromval = value_cast (type, fromval);
+ else
+ COERCE_ARRAY (fromval);
+ CHECK_TYPEDEF (type);
+
+ /* If TOVAL is a special machine register requiring conversion
+ of program values to a special raw format,
+ 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 (REGISTER_CONVERTIBLE (regno))
+ {
+ struct type *fromtype = check_typedef (VALUE_TYPE (fromval));
+ REGISTER_CONVERT_TO_RAW (fromtype, regno,
+ VALUE_CONTENTS (fromval), raw_buffer);
+ use_buffer = REGISTER_RAW_SIZE (regno);
+ }
+ }
+#endif
+
+ switch (VALUE_LVAL (toval))
+ {
+ case lval_internalvar:
+ set_internalvar (VALUE_INTERNALVAR (toval), fromval);
+ return value_copy (VALUE_INTERNALVAR (toval)->value);
+
+ case lval_internalvar_component:
+ set_internalvar_component (VALUE_INTERNALVAR (toval),
+ VALUE_OFFSET (toval),
+ VALUE_BITPOS (toval),
+ VALUE_BITSIZE (toval),
+ fromval);
+ break;
+
+ case lval_memory:
+ if (VALUE_BITSIZE (toval))
+ {
+ 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 > (int) 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),
+ buffer, len);
+ modify_field (buffer, value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ buffer, len);
+ }
+ else if (use_buffer)
+ write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ raw_buffer, use_buffer);
+ else
+ write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+ break;
+
+ case lval_register:
+ if (VALUE_BITSIZE (toval))
+ {
+ char buffer[sizeof (LONGEST)];
+ int len = REGISTER_RAW_SIZE (VALUE_REGNO (toval));
+
+ if (len > (int) 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),
+ raw_buffer, use_buffer);
+ else
+ {
+ /* Do any conversion necessary when storing this type to more
+ than one register. */
+#ifdef REGISTER_CONVERT_FROM_TYPE
+ memcpy (raw_buffer, VALUE_CONTENTS (fromval), TYPE_LENGTH (type));
+ REGISTER_CONVERT_FROM_TYPE(VALUE_REGNO (toval), type, raw_buffer);
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ raw_buffer, TYPE_LENGTH (type));
+#else
+ write_register_bytes (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval),
+ 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:
+ {
+ /* value is stored in a series of registers in the frame
+ specified by the structure. Copy that value out, modify
+ it, and copy it back in. */
+ int amount_to_copy = (VALUE_BITSIZE (toval) ? 1 : TYPE_LENGTH (type));
+ int reg_size = REGISTER_RAW_SIZE (VALUE_FRAME_REGNUM (toval));
+ int byte_offset = VALUE_OFFSET (toval) % reg_size;
+ int reg_offset = VALUE_OFFSET (toval) / reg_size;
+ int amount_copied;
+
+ /* Make the buffer large enough in all cases. */
+ char *buffer = (char *) alloca (amount_to_copy
+ + sizeof (LONGEST)
+ + MAX_REGISTER_RAW_SIZE);
+
+ int regno;
+ struct frame_info *frame;
+
+ /* Figure out which frame this is in currently. */
+ for (frame = get_current_frame ();
+ frame && FRAME_FP (frame) != VALUE_FRAME (toval);
+ frame = get_prev_frame (frame))
+ ;
+
+ if (!frame)
+ error ("Value being assigned to is no longer active.");
+
+ amount_to_copy += (reg_size - amount_to_copy % reg_size);
+
+ /* Copy it out. */
+ for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
+ amount_copied = 0);
+ amount_copied < amount_to_copy;
+ amount_copied += reg_size, regno++)
+ {
+ get_saved_register (buffer + amount_copied,
+ (int *)NULL, (CORE_ADDR *)NULL,
+ frame, regno, (enum lval_type *)NULL);
+ }
+
+ /* Modify what needs to be modified. */
+ if (VALUE_BITSIZE (toval))
+ modify_field (buffer + byte_offset,
+ value_as_long (fromval),
+ VALUE_BITPOS (toval), VALUE_BITSIZE (toval));
+ else if (use_buffer)
+ memcpy (buffer + byte_offset, raw_buffer, use_buffer);
+ else
+ memcpy (buffer + byte_offset, VALUE_CONTENTS (fromval),
+ TYPE_LENGTH (type));
+
+ /* Copy it back. */
+ for ((regno = VALUE_FRAME_REGNUM (toval) + reg_offset,
+ amount_copied = 0);
+ amount_copied < amount_to_copy;
+ amount_copied += reg_size, regno++)
+ {
+ enum lval_type lval;
+ CORE_ADDR addr;
+ int optim;
+
+ /* Just find out where to put it. */
+ get_saved_register ((char *)NULL,
+ &optim, &addr, frame, regno, &lval);
+
+ if (optim)
+ error ("Attempt to assign to a value that was optimized out.");
+ if (lval == lval_memory)
+ write_memory (addr, buffer + amount_copied, reg_size);
+ else if (lval == lval_register)
+ write_register_bytes (addr, buffer + amount_copied, reg_size);
+ else
+ error ("Attempt to assign to an unmodifiable value.");
+ }
+ }
+ break;
+
+
+ default:
+ error ("Left operand of assignment is not an lvalue.");
+ }
+
+ /* If the field does not entirely fill a LONGEST, then zero the sign bits.
+ If the field is signed, and is negative, then sign extend. */
+ if ((VALUE_BITSIZE (toval) > 0)
+ && (VALUE_BITSIZE (toval) < 8 * (int) sizeof (LONGEST)))
+ {
+ LONGEST fieldval = value_as_long (fromval);
+ LONGEST valmask = (((unsigned LONGEST) 1) << VALUE_BITSIZE (toval)) - 1;
+
+ fieldval &= valmask;
+ if (!TYPE_UNSIGNED (type) && (fieldval & (valmask ^ (valmask >> 1))))
+ fieldval |= ~valmask;
+
+ fromval = value_from_longest (type, fieldval);
+ }
+
+ val = value_copy (toval);
+ memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval),
+ TYPE_LENGTH (type));
+ VALUE_TYPE (val) = type;
+
+ return val;
+}
+
+/* Extend a value VAL to COUNT repetitions of its type. */
+
+value_ptr
+value_repeat (arg1, count)
+ value_ptr arg1;
+ int count;
+{
+ register value_ptr val;
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Only values in memory can be extended with '@'.");
+ if (count < 1)
+ error ("Invalid number %d of repetitions.", count);
+
+ val = allocate_repeat_value (VALUE_TYPE (arg1), count);
+
+ read_memory (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1),
+ VALUE_CONTENTS_RAW (val),
+ TYPE_LENGTH (VALUE_TYPE (val)));
+ VALUE_LVAL (val) = lval_memory;
+ VALUE_ADDRESS (val) = VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1);
+
+ return val;
+}
+
+value_ptr
+value_of_variable (var, b)
+ struct symbol *var;
+ struct block *b;
+{
+ value_ptr val;
+ struct frame_info *frame;
+
+ if (b == NULL)
+ /* Use selected frame. */
+ frame = NULL;
+ else
+ {
+ frame = block_innermost_frame (b);
+ if (frame == NULL && symbol_read_needs_frame (var))
+ {
+ if (BLOCK_FUNCTION (b) != NULL
+ && SYMBOL_NAME (BLOCK_FUNCTION (b)) != NULL)
+ error ("No frame is currently executing in block %s.",
+ SYMBOL_NAME (BLOCK_FUNCTION (b)));
+ else
+ error ("No frame is currently executing in specified block");
+ }
+ }
+ val = read_var_value (var, frame);
+ if (val == 0)
+ error ("Address of symbol \"%s\" is unknown.", SYMBOL_SOURCE_NAME (var));
+ return val;
+}
+
+/* Given a value which is an array, return a value which is a pointer to its
+ first element, regardless of whether or not the array has a nonzero lower
+ bound.
+
+ FIXME: A previous comment here indicated that this routine should be
+ substracting the array's lower bound. It's not clear to me that this
+ is correct. Given an array subscripting operation, it would certainly
+ work to do the adjustment here, essentially computing:
+
+ (&array[0] - (lowerbound * sizeof array[0])) + (index * sizeof array[0])
+
+ However I believe a more appropriate and logical place to account for
+ the lower bound is to do so in value_subscript, essentially computing:
+
+ (&array[0] + ((index - lowerbound) * sizeof array[0]))
+
+ As further evidence consider what would happen with operations other
+ than array subscripting, where the caller would get back a value that
+ had an address somewhere before the actual first element of the array,
+ and the information about the lower bound would be lost because of
+ the coercion to pointer type.
+ */
+
+value_ptr
+value_coerce_array (arg1)
+ value_ptr arg1;
+{
+ register struct type *type = check_typedef (VALUE_TYPE (arg1));
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Attempt to take address of value not located in memory.");
+
+ return value_from_longest (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+}
+
+/* Given a value which is a function, return a value which is a pointer
+ to it. */
+
+value_ptr
+value_coerce_function (arg1)
+ value_ptr arg1;
+{
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Attempt to take address of value not located in memory.");
+
+ return value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)),
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+}
+
+/* Return a pointer value for the object for which ARG1 is the contents. */
+
+value_ptr
+value_addr (arg1)
+ value_ptr arg1;
+{
+ struct type *type = check_typedef (VALUE_TYPE (arg1));
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ {
+ /* 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_ptr arg2 = value_copy (arg1);
+ VALUE_TYPE (arg2) = lookup_pointer_type (TYPE_TARGET_TYPE (type));
+ return arg2;
+ }
+ if (TYPE_CODE (type) == TYPE_CODE_FUNC)
+ return value_coerce_function (arg1);
+
+ if (VALUE_LVAL (arg1) != lval_memory)
+ error ("Attempt to take address of value not located in memory.");
+
+ return value_from_longest (lookup_pointer_type (VALUE_TYPE (arg1)),
+ (LONGEST) (VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1)));
+}
+
+/* Given a value of a pointer type, apply the C unary * operator to it. */
+
+value_ptr
+value_ind (arg1)
+ value_ptr arg1;
+{
+ struct type *type1;
+ COERCE_ARRAY (arg1);
+ type1 = check_typedef (VALUE_TYPE (arg1));
+
+ if (TYPE_CODE (type1) == TYPE_CODE_MEMBER)
+ error ("not implemented: member types in value_ind");
+
+ /* Allow * on an integer so we can cast it to whatever we want.
+ This returns an int, which seems like the most C-like thing
+ to do. "long long" variables are rare enough that
+ BUILTIN_TYPE_LONGEST would seem to be a mistake. */
+ if (TYPE_CODE (type1) == TYPE_CODE_INT)
+ return value_at (builtin_type_int,
+ (CORE_ADDR) value_as_long (arg1));
+ else if (TYPE_CODE (type1) == TYPE_CODE_PTR)
+ return value_at_lazy (TYPE_TARGET_TYPE (type1), value_as_pointer (arg1));
+ error ("Attempt to take contents of a non-pointer value.");
+ return 0; /* For lint -- never reached */
+}
+
+/* Pushing small parts of stack frames. */
+
+/* Push one word (the size of object that a register holds). */
+
+CORE_ADDR
+push_word (sp, word)
+ CORE_ADDR sp;
+ unsigned LONGEST word;
+{
+ register int len = REGISTER_SIZE;
+ char buffer[MAX_REGISTER_RAW_SIZE];
+
+ store_unsigned_integer (buffer, len, word);
+#if 1 INNER_THAN 2
+ sp -= len;
+ write_memory (sp, buffer, len);
+#else /* stack grows upward */
+ write_memory (sp, buffer, len);
+ sp += len;
+#endif /* stack grows upward */
+
+ return sp;
+}
+
+/* Push LEN bytes with data at BUFFER. */
+
+CORE_ADDR
+push_bytes (sp, buffer, len)
+ CORE_ADDR sp;
+ char *buffer;
+ int len;
+{
+#if 1 INNER_THAN 2
+ sp -= len;
+ write_memory (sp, buffer, len);
+#else /* stack grows upward */
+ write_memory (sp, buffer, len);
+ sp += len;
+#endif /* stack grows upward */
+
+ return sp;
+}
+
+/* Push onto the stack the specified value VALUE. */
+
+static CORE_ADDR
+value_push (sp, arg)
+ register CORE_ADDR sp;
+ value_ptr arg;
+{
+ register int len = TYPE_LENGTH (VALUE_TYPE (arg));
+
+#if 1 INNER_THAN 2
+ sp -= len;
+ write_memory (sp, VALUE_CONTENTS (arg), len);
+#else /* stack grows upward */
+ write_memory (sp, VALUE_CONTENTS (arg), len);
+ sp += len;
+#endif /* stack grows upward */
+
+ return sp;
+}
+
+/* Perform the standard coercions that are specified
+ for arguments to be passed to C functions.
+
+ If PARAM_TYPE is non-NULL, it is the expected parameter type. */
+
+static value_ptr
+value_arg_coerce (arg, param_type)
+ value_ptr arg;
+ struct type *param_type;
+{
+ register struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ register struct type *type
+ = param_type ? check_typedef (param_type) : arg_type;
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_REF:
+ if (TYPE_CODE (arg_type) != TYPE_CODE_REF)
+ {
+ arg = value_addr (arg);
+ VALUE_TYPE (arg) = param_type;
+ return arg;
+ }
+ break;
+ case TYPE_CODE_INT:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_ENUM:
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
+ type = builtin_type_int;
+ break;
+ case TYPE_CODE_FLT:
+ /* coerce float to double, unless the function prototype specifies float */
+ if (COERCE_FLOAT_TO_DOUBLE)
+ {
+ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_double))
+ type = builtin_type_double;
+ else if (TYPE_LENGTH (type) > TYPE_LENGTH (builtin_type_double))
+ type = builtin_type_long_double;
+ }
+ break;
+ case TYPE_CODE_FUNC:
+ type = lookup_pointer_type (type);
+ break;
+ case TYPE_CODE_ARRAY:
+ if (current_language->c_style_arrays)
+ type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
+ break;
+ case TYPE_CODE_UNDEF:
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ case TYPE_CODE_VOID:
+ case TYPE_CODE_SET:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_STRING:
+ case TYPE_CODE_BITSTRING:
+ case TYPE_CODE_ERROR:
+ case TYPE_CODE_MEMBER:
+ case TYPE_CODE_METHOD:
+ case TYPE_CODE_COMPLEX:
+ default:
+ break;
+ }
+
+ return value_cast (type, arg);
+}
+
+/* Determine a function's address and its return type from its value.
+ Calls error() if the function is not valid for calling. */
+
+static CORE_ADDR
+find_function_addr (function, retval_type)
+ value_ptr function;
+ struct type **retval_type;
+{
+ register struct type *ftype = check_typedef (VALUE_TYPE (function));
+ register enum type_code code = TYPE_CODE (ftype);
+ struct type *value_type;
+ CORE_ADDR funaddr;
+
+ /* If it's a member function, just look at the function
+ part of it. */
+
+ /* Determine address to call. */
+ if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD)
+ {
+ funaddr = VALUE_ADDRESS (function);
+ value_type = TYPE_TARGET_TYPE (ftype);
+ }
+ else if (code == TYPE_CODE_PTR)
+ {
+ funaddr = value_as_pointer (function);
+ ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+ if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
+ || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
+ {
+#ifdef CONVERT_FROM_FUNC_PTR_ADDR
+ /* FIXME: This is a workaround for the unusual function
+ pointer representation on the RS/6000, see comment
+ in config/rs6000/tm-rs6000.h */
+ funaddr = CONVERT_FROM_FUNC_PTR_ADDR (funaddr);
+#endif
+ value_type = TYPE_TARGET_TYPE (ftype);
+ }
+ else
+ value_type = builtin_type_int;
+ }
+ else if (code == TYPE_CODE_INT)
+ {
+ /* Handle the case of functions lacking debugging info.
+ Their values are characters since their addresses are char */
+ if (TYPE_LENGTH (ftype) == 1)
+ funaddr = value_as_pointer (value_addr (function));
+ else
+ /* Handle integer used as address of a function. */
+ funaddr = (CORE_ADDR) value_as_long (function);
+
+ value_type = builtin_type_int;
+ }
+ else
+ error ("Invalid data type for function to be called.");
+
+ *retval_type = value_type;
+ return funaddr;
+}
+
+#if defined (CALL_DUMMY)
+/* All this stuff with a dummy frame may seem unnecessarily complicated
+ (why not just save registers in GDB?). The purpose of pushing a dummy
+ frame which looks just like a real frame is so that if you call a
+ function and then hit a breakpoint (get a signal, etc), "backtrace"
+ will look right. Whether the backtrace needs to actually show the
+ stack at the time the inferior function was called is debatable, but
+ it certainly needs to not display garbage. So if you are contemplating
+ making dummy frames be different from normal frames, consider that. */
+
+/* Perform a function call in the inferior.
+ ARGS is a vector of values of arguments (NARGS of them).
+ FUNCTION is a value, the function to be called.
+ Returns a value representing what the function returned.
+ May fail to return, if a breakpoint or signal is hit
+ during the execution of the function.
+
+ ARGS is modified to contain coerced values. */
+
+value_ptr
+call_function_by_hand (function, nargs, args)
+ value_ptr function;
+ int nargs;
+ value_ptr *args;
+{
+ register CORE_ADDR sp;
+ register int i;
+ CORE_ADDR start_sp;
+ /* 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;
+ CORE_ADDR struct_addr;
+ struct inferior_status inf_status;
+ struct cleanup *old_chain;
+ CORE_ADDR funaddr;
+ int using_gcc;
+ CORE_ADDR real_pc;
+ struct type *ftype = check_typedef (SYMBOL_TYPE (function));
+
+ if (!target_has_execution)
+ noprocess();
+
+ save_inferior_status (&inf_status, 1);
+ old_chain = make_cleanup (restore_inferior_status, &inf_status);
+
+ /* PUSH_DUMMY_FRAME is responsible for saving the inferior registers
+ (and POP_FRAME for restoring them). (At least on most machines)
+ they are saved on the stack in the inferior. */
+ PUSH_DUMMY_FRAME;
+
+ old_sp = sp = read_sp ();
+
+#if 1 INNER_THAN 2 /* Stack grows down */
+ sp -= sizeof dummy1;
+ start_sp = sp;
+#else /* Stack grows up */
+ start_sp = sp;
+ sp += sizeof dummy1;
+#endif
+
+ funaddr = find_function_addr (function, &value_type);
+ CHECK_TYPEDEF (value_type);
+
+ {
+ struct block *b = block_for_pc (funaddr);
+ /* If compiled without -g, assume GCC. */
+ using_gcc = b == NULL ? 0 : BLOCK_GCC_COMPILED (b);
+ }
+
+ /* Are we returning a value using a structure return or a normal
+ value return? */
+
+ struct_return = using_struct_return (function, funaddr, value_type,
+ using_gcc);
+
+ /* Create a call sequence customized for this function
+ and the number of arguments for it. */
+ for (i = 0; i < (int) (sizeof (dummy) / sizeof (dummy[0])); i++)
+ store_unsigned_integer (&dummy1[i * REGISTER_SIZE],
+ REGISTER_SIZE,
+ (unsigned LONGEST)dummy[i]);
+
+#ifdef GDB_TARGET_IS_HPPA
+ real_pc = FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+ value_type, using_gcc);
+#else
+ FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, args,
+ value_type, using_gcc);
+ real_pc = start_sp;
+#endif
+
+#if CALL_DUMMY_LOCATION == ON_STACK
+ write_memory (start_sp, (char *)dummy1, sizeof dummy1);
+#endif /* On stack. */
+
+#if CALL_DUMMY_LOCATION == BEFORE_TEXT_END
+ /* Convex Unix prohibits executing in the stack segment. */
+ /* Hope there is empty room at the top of the text segment. */
+ {
+ extern CORE_ADDR text_end;
+ static checked = 0;
+ if (!checked)
+ for (start_sp = text_end - sizeof dummy1; start_sp < text_end; ++start_sp)
+ if (read_memory_integer (start_sp, 1) != 0)
+ error ("text segment full -- no place to put call");
+ checked = 1;
+ sp = old_sp;
+ real_pc = text_end - sizeof dummy1;
+ write_memory (real_pc, (char *)dummy1, sizeof dummy1);
+ }
+#endif /* Before text_end. */
+
+#if CALL_DUMMY_LOCATION == AFTER_TEXT_END
+ {
+ extern CORE_ADDR text_end;
+ int errcode;
+ sp = old_sp;
+ real_pc = text_end;
+ errcode = target_write_memory (real_pc, (char *)dummy1, sizeof dummy1);
+ if (errcode != 0)
+ error ("Cannot write text segment -- call_function failed");
+ }
+#endif /* After text_end. */
+
+#if CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+ real_pc = funaddr;
+#endif /* At entry point. */
+
+#ifdef lint
+ sp = old_sp; /* It really is used, for some ifdef's... */
+#endif
+
+ if (nargs < TYPE_NFIELDS (ftype))
+ error ("too few arguments in function call");
+
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ struct type *param_type;
+ if (TYPE_NFIELDS (ftype) > i)
+ param_type = TYPE_FIELD_TYPE (ftype, i);
+ else
+ param_type = 0;
+ args[i] = value_arg_coerce (args[i], param_type);
+ }
+
+#if defined (REG_STRUCT_HAS_ADDR)
+ {
+ /* This is a machine like the sparc, where we may need to pass a pointer
+ to the structure, not the structure itself. */
+ for (i = nargs - 1; i >= 0; i--)
+ {
+ struct type *arg_type = check_typedef (VALUE_TYPE (args[i]));
+ if ((TYPE_CODE (arg_type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (arg_type) == TYPE_CODE_UNION
+ || TYPE_CODE (arg_type) == TYPE_CODE_ARRAY
+ || TYPE_CODE (arg_type) == TYPE_CODE_STRING
+ || TYPE_CODE (arg_type) == TYPE_CODE_BITSTRING
+ || TYPE_CODE (arg_type) == TYPE_CODE_SET
+ || (TYPE_CODE (arg_type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (arg_type) > 8)
+ )
+ && REG_STRUCT_HAS_ADDR (using_gcc, arg_type))
+ {
+ CORE_ADDR addr;
+ int len = TYPE_LENGTH (arg_type);
+#ifdef STACK_ALIGN
+ int aligned_len = STACK_ALIGN (len);
+#else
+ int aligned_len = len;
+#endif
+#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;
+#else
+ sp -= aligned_len;
+#endif
+ /* Push the structure. */
+ write_memory (sp, VALUE_CONTENTS (args[i]), len);
+#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;
+#else
+ sp += aligned_len;
+#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);
+ }
+ }
+ }
+#endif /* REG_STRUCT_HAS_ADDR. */
+
+ /* Reserve space for the return structure to be written on the
+ stack, if necessary */
+
+ if (struct_return)
+ {
+ int len = TYPE_LENGTH (value_type);
+#ifdef STACK_ALIGN
+ len = STACK_ALIGN (len);
+#endif
+#if 1 INNER_THAN 2
+ sp -= len;
+ struct_addr = sp;
+#else
+ struct_addr = sp;
+ sp += len;
+#endif
+ }
+
+#ifdef STACK_ALIGN
+ /* If stack grows down, we must leave a hole at the top. */
+ {
+ int len = 0;
+
+ for (i = nargs - 1; i >= 0; i--)
+ len += TYPE_LENGTH (VALUE_TYPE (args[i]));
+#ifdef CALL_DUMMY_STACK_ADJUST
+ len += CALL_DUMMY_STACK_ADJUST;
+#endif
+#if 1 INNER_THAN 2
+ sp -= STACK_ALIGN (len) - len;
+#else
+ sp += STACK_ALIGN (len) - len;
+#endif
+ }
+#endif /* STACK_ALIGN */
+
+#ifdef PUSH_ARGUMENTS
+ PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr);
+#else /* !PUSH_ARGUMENTS */
+ for (i = nargs - 1; i >= 0; i--)
+ sp = value_push (sp, args[i]);
+#endif /* !PUSH_ARGUMENTS */
+
+#ifdef CALL_DUMMY_STACK_ADJUST
+#if 1 INNER_THAN 2
+ sp -= CALL_DUMMY_STACK_ADJUST;
+#else
+ sp += CALL_DUMMY_STACK_ADJUST;
+#endif
+#endif /* CALL_DUMMY_STACK_ADJUST */
+
+ /* Store the address at which the structure is supposed to be
+ written. Note that this (and the code which reserved the space
+ above) assumes that gcc was used to compile this function. Since
+ it doesn't cost us anything but space and if the function is pcc
+ it will ignore this value, we will make that assumption.
+
+ Also note that on some machines (like the sparc) pcc uses a
+ convention like gcc's. */
+
+ if (struct_return)
+ STORE_STRUCT_RETURN (struct_addr, sp);
+
+ /* Write the stack pointer. This is here because the statements above
+ might fool with it. On SPARC, this write also stores the register
+ window into the right place in the new stack frame, which otherwise
+ wouldn't happen. (See store_inferior_registers in sparc-nat.c.) */
+ write_sp (sp);
+
+ {
+ char retbuf[REGISTER_BYTES];
+ char *name;
+ struct symbol *symbol;
+
+ name = NULL;
+ symbol = find_pc_function (funaddr);
+ if (symbol)
+ {
+ name = SYMBOL_SOURCE_NAME (symbol);
+ }
+ else
+ {
+ /* Try the minimal symbols. */
+ struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (funaddr);
+
+ if (msymbol)
+ {
+ name = SYMBOL_SOURCE_NAME (msymbol);
+ }
+ }
+ if (name == NULL)
+ {
+ 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);
+ }
+
+ /* Execute the stack dummy routine, calling FUNCTION.
+ When it is done, discard the empty frame
+ after storing the contents of all regs into retbuf. */
+ if (run_stack_dummy (real_pc + CALL_DUMMY_START_OFFSET, retbuf))
+ {
+ /* We stopped somewhere besides the call dummy. */
+
+ /* If we did the cleanups, we would print a spurious error message
+ (Unable to restore previously selected frame), would write the
+ registers from the inf_status (which is wrong), and would do other
+ wrong things (like set stop_bpstat to the wrong thing). */
+ discard_cleanups (old_chain);
+ /* Prevent memory leak. */
+ bpstat_clear (&inf_status.stop_bpstat);
+
+ /* The following error message used to say "The expression
+ which contained the function call has been discarded." It
+ is a hard concept to explain in a few words. Ideally, GDB
+ would be able to resume evaluation of the expression when
+ the function finally is done executing. Perhaps someday
+ this will be implemented (it would not be easy). */
+
+ /* FIXME: Insert a bunch of wrap_here; name can be very long if it's
+ a C++ name with arguments and stuff. */
+ error ("\
+The program being debugged stopped while in a function called from GDB.\n\
+When the function (%s) is done executing, GDB will silently\n\
+stop (instead of continuing to evaluate the expression containing\n\
+the function call).", name);
+ }
+
+ do_cleanups (old_chain);
+
+ /* Figure out the value returned by the function. */
+ return value_being_returned (value_type, retbuf, struct_return);
+ }
+}
+#else /* no CALL_DUMMY. */
+value_ptr
+call_function_by_hand (function, nargs, args)
+ value_ptr function;
+ int nargs;
+ value_ptr *args;
+{
+ error ("Cannot invoke functions on this machine.");
+}
+#endif /* no CALL_DUMMY. */
+
+
+/* Create a value for an array by allocating space in the inferior, copying
+ the data into that space, and then setting up an array value.
+
+ The array bounds are set from LOWBOUND and HIGHBOUND, and the array is
+ populated from the values passed in ELEMVEC.
+
+ The element type of the array is inherited from the type of the
+ first element, and all elements must have the same size (though we
+ don't currently enforce any restriction on their types). */
+
+value_ptr
+value_array (lowbound, highbound, elemvec)
+ int lowbound;
+ int highbound;
+ value_ptr *elemvec;
+{
+ int nelem;
+ int idx;
+ unsigned int typelength;
+ value_ptr val;
+ struct type *rangetype;
+ struct type *arraytype;
+ CORE_ADDR addr;
+
+ /* Validate that the bounds are reasonable and that each of the elements
+ have the same size. */
+
+ nelem = highbound - lowbound + 1;
+ if (nelem <= 0)
+ {
+ error ("bad array bounds (%d, %d)", lowbound, highbound);
+ }
+ typelength = TYPE_LENGTH (VALUE_TYPE (elemvec[0]));
+ for (idx = 1; idx < nelem; idx++)
+ {
+ if (TYPE_LENGTH (VALUE_TYPE (elemvec[idx])) != typelength)
+ {
+ error ("array elements must all be the same size");
+ }
+ }
+
+ rangetype = create_range_type ((struct type *) NULL, builtin_type_int,
+ lowbound, highbound);
+ arraytype = create_array_type ((struct type *) NULL,
+ VALUE_TYPE (elemvec[0]), rangetype);
+
+ if (!current_language->c_style_arrays)
+ {
+ val = allocate_value (arraytype);
+ for (idx = 0; idx < nelem; idx++)
+ {
+ memcpy (VALUE_CONTENTS_RAW (val) + (idx * typelength),
+ VALUE_CONTENTS (elemvec[idx]),
+ typelength);
+ }
+ return val;
+ }
+
+ /* Allocate space to store the array in the inferior, and then initialize
+ it by copying in each element. FIXME: Is it worth it to create a
+ local buffer in which to collect each value and then write all the
+ bytes in one operation? */
+
+ addr = allocate_space_in_inferior (nelem * typelength);
+ for (idx = 0; idx < nelem; idx++)
+ {
+ write_memory (addr + (idx * typelength), VALUE_CONTENTS (elemvec[idx]),
+ typelength);
+ }
+
+ /* Create the array type and set up an array value to be evaluated lazily. */
+
+ val = value_at_lazy (arraytype, addr);
+ return (val);
+}
+
+/* Create a value for a string constant by allocating space in the inferior,
+ copying the data into that space, and returning the address with type
+ TYPE_CODE_STRING. PTR points to the string constant data; LEN is number
+ of characters.
+ Note that string types are like array of char types with a lower bound of
+ zero and an upper bound of LEN - 1. Also note that the string may contain
+ embedded null bytes. */
+
+value_ptr
+value_string (ptr, len)
+ char *ptr;
+ int len;
+{
+ value_ptr val;
+ int lowbound = current_language->string_lower_bound;
+ struct type *rangetype = create_range_type ((struct type *) NULL,
+ builtin_type_int,
+ lowbound, len + lowbound - 1);
+ struct type *stringtype
+ = create_string_type ((struct type *) NULL, rangetype);
+ CORE_ADDR addr;
+
+ if (current_language->c_style_arrays == 0)
+ {
+ val = allocate_value (stringtype);
+ memcpy (VALUE_CONTENTS_RAW (val), ptr, len);
+ return val;
+ }
+
+
+ /* Allocate space to store the string in the inferior, and then
+ copy LEN bytes from PTR in gdb to that address in the inferior. */
+
+ addr = allocate_space_in_inferior (len);
+ write_memory (addr, ptr, len);
+
+ val = value_at_lazy (stringtype, addr);
+ return (val);
+}
+
+value_ptr
+value_bitstring (ptr, len)
+ char *ptr;
+ int len;
+{
+ value_ptr val;
+ struct type *domain_type = create_range_type (NULL, builtin_type_int,
+ 0, len - 1);
+ struct type *type = create_set_type ((struct type*) NULL, domain_type);
+ TYPE_CODE (type) = TYPE_CODE_BITSTRING;
+ val = allocate_value (type);
+ memcpy (VALUE_CONTENTS_RAW (val), ptr, TYPE_LENGTH (type));
+ return val;
+}
+
+/* See if we can pass arguments in T2 to a function which takes arguments
+ of types T1. Both t1 and t2 are NULL-terminated vectors. If some
+ arguments need coercion of some sort, then the coerced values are written
+ into T2. Return value is 0 if the arguments could be matched, or the
+ position at which they differ if not.
+
+ STATICP is nonzero if the T1 argument list came from a
+ static member function.
+
+ For non-static member functions, we ignore the first argument,
+ which is the type of the instance variable. This is because we want
+ to handle calls with objects from derived classes. This is not
+ entirely correct: we should actually check to make sure that a
+ requested operation is type secure, shouldn't we? FIXME. */
+
+static int
+typecmp (staticp, t1, t2)
+ int staticp;
+ struct type *t1[];
+ value_ptr t2[];
+{
+ int i;
+
+ if (t2 == 0)
+ return 1;
+ if (staticp && t1 == 0)
+ return t2[1] != 0;
+ if (t1 == 0)
+ return 1;
+ if (TYPE_CODE (t1[0]) == TYPE_CODE_VOID) return 0;
+ 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;
+ tt1 = check_typedef (t1[i]);
+ tt2 = check_typedef (VALUE_TYPE(t2[i]));
+ if (TYPE_CODE (tt1) == TYPE_CODE_REF
+ /* We should be doing hairy argument matching, as below. */
+ && (TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (tt1))) == TYPE_CODE (tt2)))
+ {
+ if (TYPE_CODE (tt2) == TYPE_CODE_ARRAY)
+ t2[i] = value_coerce_array (t2[i]);
+ else
+ t2[i] = value_addr (t2[i]);
+ continue;
+ }
+
+ while (TYPE_CODE (tt1) == TYPE_CODE_PTR
+ && ( TYPE_CODE (tt2) == TYPE_CODE_ARRAY
+ || TYPE_CODE (tt2) == TYPE_CODE_PTR))
+ {
+ tt1 = check_typedef (TYPE_TARGET_TYPE(tt1));
+ tt2 = check_typedef (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
+ code. */
+ if (TYPE_CODE (t1[i]) != TYPE_CODE (VALUE_TYPE (t2[i])))
+ return i+1;
+ }
+ if (!t1[i]) return 0;
+ return t2[i] ? i+1 : 0;
+}
+
+/* Helper function used by value_struct_elt to recurse through baseclasses.
+ Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes,
+ and search in it assuming it has (class) type TYPE.
+ If found, return value, else return NULL.
+
+ If LOOKING_FOR_BASECLASS, then instead of looking for struct fields,
+ look for a baseclass named NAME. */
+
+static value_ptr
+search_struct_field (name, arg1, offset, type, looking_for_baseclass)
+ char *name;
+ register value_ptr arg1;
+ int offset;
+ register struct type *type;
+ int looking_for_baseclass;
+{
+ int i;
+
+ CHECK_TYPEDEF (type);
+
+ if (! looking_for_baseclass)
+ for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+ {
+ char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+ if (t_field_name && STREQ (t_field_name, name))
+ {
+ value_ptr v;
+ if (TYPE_FIELD_STATIC (type, i))
+ {
+ char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, i);
+ struct symbol *sym =
+ lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym == NULL)
+ error ("Internal error: could not find physical static variable named %s",
+ phys_name);
+ v = value_at (TYPE_FIELD_TYPE (type, i),
+ (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+ }
+ else
+ v = value_primitive_field (arg1, offset, i, type);
+ if (v == 0)
+ error("there is no field named %s", name);
+ return v;
+ }
+
+ if (t_field_name
+ && (t_field_name[0] == '\0'
+ || (TYPE_CODE (type) == TYPE_CODE_UNION
+ && STREQ (t_field_name, "else"))))
+ {
+ struct type *field_type = TYPE_FIELD_TYPE (type, i);
+ if (TYPE_CODE (field_type) == TYPE_CODE_UNION
+ || TYPE_CODE (field_type) == TYPE_CODE_STRUCT)
+ {
+ /* Look for a match through the fields of an anonymous union,
+ or anonymous struct. C++ provides anonymous unions.
+
+ In the GNU Chill implementation of variant record types,
+ each <alternative field> has an (anonymous) union type,
+ each member of the union represents a <variant alternative>.
+ Each <variant alternative> is represented as a struct,
+ with a member for each <variant field>. */
+
+ value_ptr v;
+ int new_offset = offset;
+
+ /* This is pretty gross. In G++, the offset in an anonymous
+ union is relative to the beginning of the enclosing struct.
+ In the GNU Chill implementation of variant records,
+ the bitpos is zero in an anonymous union field, so we
+ have to add the offset of the union here. */
+ if (TYPE_CODE (field_type) == TYPE_CODE_STRUCT
+ || (TYPE_NFIELDS (field_type) > 0
+ && TYPE_FIELD_BITPOS (field_type, 0) == 0))
+ new_offset += TYPE_FIELD_BITPOS (type, i) / 8;
+
+ v = search_struct_field (name, arg1, new_offset, field_type,
+ looking_for_baseclass);
+ if (v)
+ return v;
+ }
+ }
+ }
+
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ value_ptr v;
+ struct type *basetype = check_typedef (TYPE_BASECLASS (type, i));
+ /* 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. */
+ int found_baseclass = (looking_for_baseclass
+ && TYPE_BASECLASS_NAME (type, i) != NULL
+ && STREQ (name, TYPE_BASECLASS_NAME (type, i)));
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ int boffset = VALUE_OFFSET (arg1) + offset;
+ boffset = baseclass_offset (type, i,
+ VALUE_CONTENTS (arg1) + boffset,
+ VALUE_ADDRESS (arg1) + boffset);
+ if (boffset == -1)
+ error ("virtual baseclass botch");
+ if (found_baseclass)
+ {
+ value_ptr v2 = allocate_value (basetype);
+ VALUE_LVAL (v2) = VALUE_LVAL (arg1);
+ VALUE_ADDRESS (v2) = VALUE_ADDRESS (arg1);
+ VALUE_OFFSET (v2) = VALUE_OFFSET (arg1) + offset + boffset;
+ if (VALUE_LAZY (arg1))
+ VALUE_LAZY (v2) = 1;
+ else
+ memcpy (VALUE_CONTENTS_RAW (v2),
+ VALUE_CONTENTS_RAW (arg1) + offset + boffset,
+ TYPE_LENGTH (basetype));
+ return v2;
+ }
+ v = search_struct_field (name, arg1, offset + boffset,
+ TYPE_BASECLASS (type, i),
+ looking_for_baseclass);
+ }
+ else if (found_baseclass)
+ v = value_primitive_field (arg1, offset, i, type);
+ else
+ v = search_struct_field (name, arg1,
+ offset + TYPE_BASECLASS_BITPOS (type, i) / 8,
+ basetype, looking_for_baseclass);
+ if (v) return v;
+ }
+ return NULL;
+}
+
+/* Helper function used by value_struct_elt to recurse through baseclasses.
+ Look for a field NAME in ARG1. Adjust the address of ARG1 by OFFSET bytes,
+ and search in it assuming it has (class) type TYPE.
+ If found, return value, else if name matched and args not return (value)-1,
+ else return NULL. */
+
+static value_ptr
+search_struct_method (name, arg1p, args, offset, static_memfuncp, type)
+ char *name;
+ register value_ptr *arg1p, *args;
+ int offset, *static_memfuncp;
+ register struct type *type;
+{
+ int i;
+ value_ptr v;
+ int name_matched = 0;
+ char dem_opname[64];
+
+ CHECK_TYPEDEF (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;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ name_matched = 1;
+
+ if (j > 0 && args == 0)
+ error ("cannot resolve overloaded method `%s'", name);
+ while (j >= 0)
+ {
+ if (TYPE_FN_FIELD_STUB (f, j))
+ check_stub_method (type, i, j);
+ if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
+ TYPE_FN_FIELD_ARGS (f, j), args))
+ {
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ return value_virtual_fn_field (arg1p, f, j, type, offset);
+ if (TYPE_FN_FIELD_STATIC_P (f, j) && static_memfuncp)
+ *static_memfuncp = 1;
+ v = value_fn_field (arg1p, f, j, type, offset);
+ if (v != NULL) return v;
+ }
+ j--;
+ }
+ }
+ }
+
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ int base_offset;
+
+ if (BASETYPE_VIA_VIRTUAL (type, i))
+ {
+ base_offset = VALUE_OFFSET (*arg1p) + offset;
+ base_offset =
+ baseclass_offset (type, i,
+ VALUE_CONTENTS (*arg1p) + base_offset,
+ VALUE_ADDRESS (*arg1p) + base_offset);
+ if (base_offset == -1)
+ error ("virtual baseclass botch");
+ }
+ else
+ {
+ base_offset = TYPE_BASECLASS_BITPOS (type, i) / 8;
+ }
+ v = search_struct_method (name, arg1p, args, base_offset + offset,
+ static_memfuncp, TYPE_BASECLASS (type, i));
+ if (v == (value_ptr) -1)
+ {
+ name_matched = 1;
+ }
+ else if (v)
+ {
+/* FIXME-bothner: Why is this commented out? Why is it here? */
+/* *arg1p = arg1_tmp;*/
+ return v;
+ }
+ }
+ if (name_matched) return (value_ptr) -1;
+ else return NULL;
+}
+
+/* Given *ARGP, a value of type (pointer to a)* structure/union,
+ extract the component named NAME from the ultimate target structure/union
+ and return it as a value with its appropriate type.
+ ERR is used in the error message if *ARGP's type is wrong.
+
+ C++: ARGS is a list of argument types to aid in the selection of
+ an appropriate method. Also, handle derived types.
+
+ STATIC_MEMFUNCP, if non-NULL, points to a caller-supplied location
+ where the truthvalue of whether the function that was resolved was
+ a static member function or not is stored.
+
+ ERR is an error message to be printed in case the field is not found. */
+
+value_ptr
+value_struct_elt (argp, args, name, static_memfuncp, err)
+ register value_ptr *argp, *args;
+ char *name;
+ int *static_memfuncp;
+ char *err;
+{
+ register struct type *t;
+ value_ptr v;
+
+ COERCE_ARRAY (*argp);
+
+ t = check_typedef (VALUE_TYPE (*argp));
+
+ /* Follow pointers until we get to a non-pointer. */
+
+ while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+ {
+ *argp = value_ind (*argp);
+ /* Don't coerce fn pointer to fn and then back again! */
+ if (TYPE_CODE (VALUE_TYPE (*argp)) != TYPE_CODE_FUNC)
+ COERCE_ARRAY (*argp);
+ t = check_typedef (VALUE_TYPE (*argp));
+ }
+
+ if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+ error ("not implemented: member type in value_struct_elt");
+
+ if ( TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Attempt to extract a component of a value that is not a %s.", err);
+
+ /* Assume it's not, unless we see that it is. */
+ if (static_memfuncp)
+ *static_memfuncp =0;
+
+ if (!args)
+ {
+ /* if there are no arguments ...do this... */
+
+ /* Try as a field first, because if we succeed, there
+ is less work to be done. */
+ v = search_struct_field (name, *argp, 0, t, 0);
+ if (v)
+ return v;
+
+ /* C++: If it was not found as a data field, then try to
+ return it as a pointer to a method. */
+
+ if (destructor_name_p (name, t))
+ error ("Cannot get value of destructor");
+
+ v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
+
+ 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);
+ else
+ error ("There is no member named %s.", name);
+ }
+ return v;
+ }
+
+ if (destructor_name_p (name, t))
+ {
+ if (!args[1])
+ {
+ /* destructors are a special case. */
+ 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
+ {
+ error ("destructor should not have any argument");
+ }
+ }
+ else
+ v = search_struct_method (name, argp, args, 0, static_memfuncp, t);
+
+ if (v == (value_ptr) -1)
+ {
+ error("Argument list of %s mismatch with component in the structure.", name);
+ }
+ else if (v == 0)
+ {
+ /* See if user tried to invoke data as function. If so,
+ hand it back. If it's not callable (i.e., a pointer to function),
+ gdb should give an error. */
+ v = search_struct_field (name, *argp, 0, t, 0);
+ }
+
+ if (!v)
+ error ("Structure has no component named %s.", name);
+ return v;
+}
+
+/* C++: return 1 is NAME is a legitimate name for the destructor
+ of type TYPE. If TYPE does not have a destructor, or
+ if NAME is inappropriate for TYPE, an error is signaled. */
+int
+destructor_name_p (name, type)
+ const char *name;
+ const struct type *type;
+{
+ /* destructors are a special case. */
+
+ if (name[0] == '~')
+ {
+ char *dname = type_name_no_tag (type);
+ char *cp = strchr (dname, '<');
+ unsigned int len;
+
+ /* Do not compare the template part for template classes. */
+ if (cp == NULL)
+ len = strlen (dname);
+ else
+ len = cp - dname;
+ if (strlen (name + 1) != len || !STREQN (dname, name + 1, len))
+ error ("name of destructor must equal name of class");
+ else
+ return 1;
+ }
+ return 0;
+}
+
+/* Helper function for check_field: Given TYPE, a structure/union,
+ return 1 if the component named NAME from the ultimate
+ target structure/union is defined, otherwise, return 0. */
+
+static int
+check_field_in (type, name)
+ register struct type *type;
+ const char *name;
+{
+ register int i;
+
+ for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
+ {
+ char *t_field_name = TYPE_FIELD_NAME (type, i);
+ if (t_field_name && STREQ (t_field_name, name))
+ return 1;
+ }
+
+ /* C++: If it was not found as a data field, then try to
+ return it as a pointer to a method. */
+
+ /* Destructors are a special case. */
+ if (destructor_name_p (name, type))
+ return 1;
+
+ for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i)
+ {
+ if (STREQ (TYPE_FN_FIELDLIST_NAME (type, i), name))
+ return 1;
+ }
+
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ if (check_field_in (TYPE_BASECLASS (type, i), name))
+ return 1;
+
+ return 0;
+}
+
+
+/* C++: Given ARG1, a value of type (pointer to a)* structure/union,
+ return 1 if the component named NAME from the ultimate
+ target structure/union is defined, otherwise, return 0. */
+
+int
+check_field (arg1, name)
+ register value_ptr arg1;
+ const char *name;
+{
+ register struct type *t;
+
+ COERCE_ARRAY (arg1);
+
+ t = VALUE_TYPE (arg1);
+
+ /* Follow pointers until we get to a non-pointer. */
+
+ for (;;)
+ {
+ CHECK_TYPEDEF (t);
+ if (TYPE_CODE (t) != TYPE_CODE_PTR && TYPE_CODE (t) != TYPE_CODE_REF)
+ break;
+ t = TYPE_TARGET_TYPE (t);
+ }
+
+ if (TYPE_CODE (t) == TYPE_CODE_MEMBER)
+ error ("not implemented: member type in check_field");
+
+ if ( TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Internal error: `this' is not an aggregate");
+
+ return check_field_in (t, name);
+}
+
+/* C++: Given an aggregate type CURTYPE, and a member name NAME,
+ return the address of this member as a "pointer to member"
+ type. If INTYPE is non-null, then it will be the type
+ of the member we are looking for. This will help us resolve
+ "pointers to member functions". This function is used
+ to resolve user expressions of the form "DOMAIN::NAME". */
+
+value_ptr
+value_struct_elt_for_reference (domain, offset, curtype, name, intype)
+ struct type *domain, *curtype, *intype;
+ int offset;
+ char *name;
+{
+ register struct type *t = curtype;
+ register int i;
+ value_ptr v;
+
+ if ( TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION)
+ error ("Internal error: non-aggregate type to value_struct_elt_for_reference");
+
+ for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
+ {
+ char *t_field_name = TYPE_FIELD_NAME (t, i);
+
+ if (t_field_name && STREQ (t_field_name, name))
+ {
+ if (TYPE_FIELD_STATIC (t, i))
+ {
+ char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (t, i);
+ struct symbol *sym =
+ lookup_symbol (phys_name, 0, VAR_NAMESPACE, 0, NULL);
+ if (sym == NULL)
+ error ("Internal error: could not find physical static variable named %s",
+ phys_name);
+ return value_at (SYMBOL_TYPE (sym),
+ (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym));
+ }
+ if (TYPE_FIELD_PACKED (t, i))
+ error ("pointers to bitfield members not allowed");
+
+ return value_from_longest
+ (lookup_reference_type (lookup_member_type (TYPE_FIELD_TYPE (t, i),
+ domain)),
+ offset + (LONGEST) (TYPE_FIELD_BITPOS (t, i) >> 3));
+ }
+ }
+
+ /* C++: If it was not found as a data field, then try to
+ return it as a pointer to a method. */
+
+ /* Destructors are a special case. */
+ if (destructor_name_p (name, t))
+ {
+ error ("member pointers to destructors not implemented yet");
+ }
+
+ /* Perform all necessary dereferencing. */
+ while (intype && TYPE_CODE (intype) == TYPE_CODE_PTR)
+ intype = TYPE_TARGET_TYPE (intype);
+
+ for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i)
+ {
+ 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);
+
+ if (intype == 0 && j > 1)
+ error ("non-unique member `%s' requires type instantiation", name);
+ if (intype)
+ {
+ while (j--)
+ if (TYPE_FN_FIELD_TYPE (f, j) == intype)
+ break;
+ if (j < 0)
+ error ("no member function matches that type instantiation");
+ }
+ else
+ j = 0;
+
+ if (TYPE_FN_FIELD_STUB (f, j))
+ check_stub_method (t, i, j);
+ if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
+ {
+ return value_from_longest
+ (lookup_reference_type
+ (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
+ domain)),
+ (LONGEST) METHOD_PTR_FROM_VOFFSET (TYPE_FN_FIELD_VOFFSET (f, j)));
+ }
+ else
+ {
+ struct symbol *s = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (f, j),
+ 0, VAR_NAMESPACE, 0, NULL);
+ if (s == NULL)
+ {
+ v = 0;
+ }
+ else
+ {
+ v = read_var_value (s, 0);
+#if 0
+ VALUE_TYPE (v) = lookup_reference_type
+ (lookup_member_type (TYPE_FN_FIELD_TYPE (f, j),
+ domain));
+#endif
+ }
+ return v;
+ }
+ }
+ }
+ for (i = TYPE_N_BASECLASSES (t) - 1; i >= 0; i--)
+ {
+ value_ptr v;
+ int base_offset;
+
+ if (BASETYPE_VIA_VIRTUAL (t, i))
+ base_offset = 0;
+ else
+ base_offset = TYPE_BASECLASS_BITPOS (t, i) / 8;
+ v = value_struct_elt_for_reference (domain,
+ offset + base_offset,
+ TYPE_BASECLASS (t, i),
+ name,
+ intype);
+ if (v)
+ return v;
+ }
+ return 0;
+}
+
+/* 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_ptr
+value_of_this (complain)
+ int complain;
+{
+ struct symbol *func, *sym;
+ struct block *b;
+ int i;
+ static const char funny_this[] = "this";
+ value_ptr this;
+
+ if (selected_frame == 0)
+ if (complain)
+ error ("no frame selected");
+ else return 0;
+
+ func = get_frame_function (selected_frame);
+ if (!func)
+ {
+ if (complain)
+ error ("no `this' in nameless context");
+ else return 0;
+ }
+
+ b = SYMBOL_BLOCK_VALUE (func);
+ i = BLOCK_NSYMS (b);
+ if (i <= 0)
+ if (complain)
+ error ("no args, no `this'");
+ else return 0;
+
+ /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER
+ symbol instead of the LOC_ARG one (if both exist). */
+ sym = lookup_block_symbol (b, funny_this, VAR_NAMESPACE);
+ if (sym == NULL)
+ {
+ if (complain)
+ error ("current stack frame not in method");
+ else
+ return NULL;
+ }
+
+ this = read_var_value (sym, selected_frame);
+ if (this == 0 && complain)
+ error ("`this' argument at unknown address");
+ return this;
+}
+
+/* Create a slice (sub-string, sub-array) of ARRAY, that is LENGTH elements
+ long, starting at LOWBOUND. The result has the same lower bound as
+ the original ARRAY. */
+
+value_ptr
+value_slice (array, lowbound, length)
+ value_ptr array;
+ int lowbound, length;
+{
+ struct type *slice_range_type, *slice_type, *range_type;
+ LONGEST lowerbound, upperbound, offset;
+ value_ptr slice;
+ struct type *array_type;
+ array_type = check_typedef (VALUE_TYPE (array));
+ COERCE_VARYING_ARRAY (array, array_type);
+ if (TYPE_CODE (array_type) != TYPE_CODE_ARRAY
+ && TYPE_CODE (array_type) != TYPE_CODE_STRING
+ && TYPE_CODE (array_type) != TYPE_CODE_BITSTRING)
+ error ("cannot take slice of non-array");
+ range_type = TYPE_INDEX_TYPE (array_type);
+ if (get_discrete_bounds (range_type, &lowerbound, &upperbound) < 0)
+ error ("slice from bad array or bitstring");
+ if (lowbound < lowerbound || length < 0
+ || lowbound + length - 1 > upperbound
+ /* Chill allows zero-length strings but not arrays. */
+ || (current_language->la_language == language_chill
+ && length == 0 && TYPE_CODE (array_type) == TYPE_CODE_ARRAY))
+ error ("slice out of range");
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ slice_range_type = create_range_type ((struct type*) NULL,
+ TYPE_TARGET_TYPE (range_type),
+ lowerbound, lowerbound + length - 1);
+ if (TYPE_CODE (array_type) == TYPE_CODE_BITSTRING)
+ {
+ int i;
+ slice_type = create_set_type ((struct type*) NULL, slice_range_type);
+ TYPE_CODE (slice_type) = TYPE_CODE_BITSTRING;
+ slice = value_zero (slice_type, not_lval);
+ for (i = 0; i < length; i++)
+ {
+ int element = value_bit_index (array_type,
+ VALUE_CONTENTS (array),
+ lowbound + i);
+ if (element < 0)
+ error ("internal error accessing bitstring");
+ else if (element > 0)
+ {
+ int j = i % TARGET_CHAR_BIT;
+ if (BITS_BIG_ENDIAN)
+ j = TARGET_CHAR_BIT - 1 - j;
+ VALUE_CONTENTS_RAW (slice)[i / TARGET_CHAR_BIT] |= (1 << j);
+ }
+ }
+ /* We should set the address, bitssize, and bitspos, so the clice
+ can be used on the LHS, but that may require extensions to
+ value_assign. For now, just leave as a non_lval. FIXME. */
+ }
+ else
+ {
+ struct type *element_type = TYPE_TARGET_TYPE (array_type);
+ offset
+ = (lowbound - lowerbound) * TYPE_LENGTH (check_typedef (element_type));
+ slice_type = create_array_type ((struct type*) NULL, element_type,
+ slice_range_type);
+ TYPE_CODE (slice_type) = TYPE_CODE (array_type);
+ slice = allocate_value (slice_type);
+ if (VALUE_LAZY (array))
+ VALUE_LAZY (slice) = 1;
+ else
+ memcpy (VALUE_CONTENTS (slice), VALUE_CONTENTS (array) + offset,
+ TYPE_LENGTH (slice_type));
+ if (VALUE_LVAL (array) == lval_internalvar)
+ VALUE_LVAL (slice) = lval_internalvar_component;
+ else
+ VALUE_LVAL (slice) = VALUE_LVAL (array);
+ VALUE_ADDRESS (slice) = VALUE_ADDRESS (array);
+ VALUE_OFFSET (slice) = VALUE_OFFSET (array) + offset;
+ }
+ return slice;
+}
+
+/* Assuming chill_varying_type (VARRAY) is true, return an equivalent
+ value as a fixed-length array. */
+
+value_ptr
+varying_to_slice (varray)
+ value_ptr varray;
+{
+ struct type *vtype = check_typedef (VALUE_TYPE (varray));
+ LONGEST length = unpack_long (TYPE_FIELD_TYPE (vtype, 0),
+ VALUE_CONTENTS (varray)
+ + TYPE_FIELD_BITPOS (vtype, 0) / 8);
+ return value_slice (value_primitive_field (varray, 0, 1, vtype), 0, length);
+}
+
+/* Create a value for a FORTRAN complex number. Currently most of
+ the time values are coerced to COMPLEX*16 (i.e. a complex number
+ composed of 2 doubles. This really should be a smarter routine
+ that figures out precision inteligently as opposed to assuming
+ doubles. FIXME: fmb */
+
+value_ptr
+value_literal_complex (arg1, arg2, type)
+ value_ptr arg1;
+ value_ptr arg2;
+ struct type *type;
+{
+ register value_ptr val;
+ struct type *real_type = TYPE_TARGET_TYPE (type);
+
+ val = allocate_value (type);
+ arg1 = value_cast (real_type, arg1);
+ arg2 = value_cast (real_type, arg2);
+
+ memcpy (VALUE_CONTENTS_RAW (val),
+ VALUE_CONTENTS (arg1), TYPE_LENGTH (real_type));
+ memcpy (VALUE_CONTENTS_RAW (val) + TYPE_LENGTH (real_type),
+ VALUE_CONTENTS (arg2), TYPE_LENGTH (real_type));
+ return val;
+}
+
+/* Cast a value into the appropriate complex data type. */
+
+static value_ptr
+cast_into_complex (type, val)
+ struct type *type;
+ register value_ptr val;
+{
+ struct type *real_type = TYPE_TARGET_TYPE (type);
+ if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_COMPLEX)
+ {
+ struct type *val_real_type = TYPE_TARGET_TYPE (VALUE_TYPE (val));
+ value_ptr re_val = allocate_value (val_real_type);
+ value_ptr im_val = allocate_value (val_real_type);
+
+ memcpy (VALUE_CONTENTS_RAW (re_val),
+ VALUE_CONTENTS (val), TYPE_LENGTH (val_real_type));
+ memcpy (VALUE_CONTENTS_RAW (im_val),
+ VALUE_CONTENTS (val) + TYPE_LENGTH (val_real_type),
+ TYPE_LENGTH (val_real_type));
+
+ return value_literal_complex (re_val, im_val, type);
+ }
+ else if (TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_FLT
+ || TYPE_CODE (VALUE_TYPE (val)) == TYPE_CODE_INT)
+ return value_literal_complex (val, value_zero (real_type, not_lval), type);
+ else
+ error ("cannot cast non-number to complex");
+}
+
+void
+_initialize_valops ()
+{
+#if 0
+ add_show_from_set
+ (add_set_cmd ("abandon", class_support, var_boolean, (char *)&auto_abandon,
+ "Set automatic abandonment of expressions upon failure.",
+ &setlist),
+ &showlist);
+#endif
+}
diff --git a/contrib/gdb/gdb/valprint.c b/contrib/gdb/gdb/valprint.c
new file mode 100644
index 0000000..ce113ce
--- /dev/null
+++ b/contrib/gdb/gdb/valprint.c
@@ -0,0 +1,1015 @@
+/* Print values for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "obstack.h"
+#include "language.h"
+#include "demangle.h"
+#include "annotate.h"
+
+#include <errno.h>
+
+/* Prototypes for local functions */
+
+static void
+print_hex_chars PARAMS ((GDB_FILE *, unsigned char *, unsigned int));
+
+static void
+show_print PARAMS ((char *, int));
+
+static void
+set_print PARAMS ((char *, int));
+
+static void
+set_radix PARAMS ((char *, int));
+
+static void
+show_radix PARAMS ((char *, int));
+
+static void
+set_input_radix PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_input_radix_1 PARAMS ((int, unsigned));
+
+static void
+set_output_radix PARAMS ((char *, int, struct cmd_list_element *));
+
+static void
+set_output_radix_1 PARAMS ((int, unsigned));
+
+/* 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
+ "unlimited". */
+
+unsigned int print_max;
+#define PRINT_MAX_DEFAULT 200 /* Start print_max off at this value. */
+
+/* Default input and output radixes, and output format letter. */
+
+unsigned input_radix = 10;
+unsigned output_radix = 10;
+int output_format = 0;
+
+/* Print repeat counts if there are more than this many repetitions of an
+ element in an array. Referenced by the low level language dependent
+ print routines. */
+
+unsigned int repeat_count_threshold = 10;
+
+/* 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. */
+
+int unionprint; /* Controls printing of nested unions. */
+
+/* If nonzero, causes machine addresses to be printed in certain contexts. */
+
+int addressprint; /* Controls printing of machine addresses */
+
+
+/* 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 using TYPE).
+
+ If DEREF_REF is nonzero, then dereference references, otherwise just print
+ them like pointers.
+
+ The PRETTY parameter controls prettyprinting.
+
+ If the data are a string pointer, returns the number of string characters
+ printed.
+
+ FIXME: The data at VALADDR is in target byte order. If gdb is ever
+ enhanced to be able to debug more than the single target it was compiled
+ for (specific CPU type and thus specific target byte ordering), then
+ either the print routines are going to have to take this into account,
+ or the data is going to have to be passed into here already converted
+ to the host byte ordering, whichever is more convenient. */
+
+
+int
+val_print (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;
+{
+ struct type *real_type = check_typedef (type);
+ if (pretty == Val_pretty_default)
+ {
+ pretty = prettyprint_structs ? Val_prettyprint : Val_no_prettyprint;
+ }
+
+ QUIT;
+
+ /* 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. */
+
+ if (TYPE_FLAGS (real_type) & TYPE_FLAG_STUB)
+ {
+ fprintf_filtered (stream, "<incomplete type>");
+ gdb_flush (stream);
+ return (0);
+ }
+
+ return (LA_VAL_PRINT (type, valaddr, address, stream, format, deref_ref,
+ recurse, pretty));
+}
+
+/* Print the value VAL in C-ish syntax on stream STREAM.
+ FORMAT is a format-letter, or 0 for print in natural format of data type.
+ If the object printed is a string pointer, returns
+ the number of string bytes printed. */
+
+int
+value_print (val, stream, format, pretty)
+ value_ptr val;
+ GDB_FILE *stream;
+ int format;
+ enum val_prettyprint pretty;
+{
+ if (val == 0)
+ {
+ printf_filtered ("<address of value unknown>");
+ return 0;
+ }
+ if (VALUE_OPTIMIZED_OUT (val))
+ {
+ printf_filtered ("<value optimized out>");
+ return 0;
+ }
+ return LA_VALUE_PRINT (val, stream, format, pretty);
+}
+
+/* Called by various <lang>_val_print routines to print
+ TYPE_CODE_INT's. TYPE is the type. VALADDR is the address of the
+ value. STREAM is where to print the value. */
+
+void
+val_print_type_code_int (type, valaddr, stream)
+ struct type *type;
+ char *valaddr;
+ GDB_FILE *stream;
+{
+ if (TYPE_LENGTH (type) > sizeof (LONGEST))
+ {
+ LONGEST val;
+
+ if (TYPE_UNSIGNED (type)
+ && extract_long_unsigned_integer (valaddr, TYPE_LENGTH (type),
+ &val))
+ {
+ print_longest (stream, 'u', 0, val);
+ }
+ else
+ {
+ /* Signed, or we couldn't turn an unsigned value into a
+ LONGEST. For signed values, one could assume two's
+ complement (a reasonable assumption, I think) and do
+ better than this. */
+ print_hex_chars (stream, (unsigned char *) valaddr,
+ TYPE_LENGTH (type));
+ }
+ }
+ else
+ {
+#ifdef PRINT_TYPELESS_INTEGER
+ PRINT_TYPELESS_INTEGER (stream, type, unpack_long (type, valaddr));
+#else
+ print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0,
+ unpack_long (type, valaddr));
+#endif
+ }
+}
+
+/* Print a number according to FORMAT which is one of d,u,x,o,b,h,w,g.
+ The raison d'etre of this function is to consolidate printing of LONG_LONG's
+ into this one function. Some platforms have long longs but don't have a
+ 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(). 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)
+ GDB_FILE *stream;
+ int format;
+ int use_local;
+ LONGEST val_long;
+{
+#if defined (CC_HAS_LONG_LONG) && !defined (PRINTF_HAS_LONG_LONG)
+ long vtop, vbot;
+
+ vtop = val_long >> (sizeof (long) * HOST_CHAR_BIT);
+ vbot = (long) val_long;
+
+ if ((format == 'd' && (val_long < INT_MIN || val_long > INT_MAX))
+ || ((format == 'u' || format == 'x') && (unsigned long long)val_long > UINT_MAX))
+ {
+ fprintf_filtered (stream, "0x%lx%08lx", vtop, vbot);
+ return;
+ }
+#endif
+
+#ifdef PRINTF_HAS_LONG_LONG
+ switch (format)
+ {
+ case 'd':
+ fprintf_filtered (stream,
+ use_local ? local_decimal_format_custom ("ll")
+ : "%lld",
+ val_long);
+ break;
+ case 'u':
+ fprintf_filtered (stream, "%llu", val_long);
+ break;
+ case 'x':
+ fprintf_filtered (stream,
+ use_local ? local_hex_format_custom ("ll")
+ : "%llx",
+ val_long);
+ break;
+ case 'o':
+ fprintf_filtered (stream,
+ use_local ? local_octal_format_custom ("ll")
+ : "%llo",
+ val_long);
+ break;
+ case 'b':
+ fprintf_filtered (stream, local_hex_format_custom ("02ll"), val_long);
+ break;
+ case 'h':
+ fprintf_filtered (stream, local_hex_format_custom ("04ll"), val_long);
+ break;
+ case 'w':
+ fprintf_filtered (stream, local_hex_format_custom ("08ll"), val_long);
+ break;
+ case 'g':
+ fprintf_filtered (stream, local_hex_format_custom ("016ll"), val_long);
+ break;
+ default:
+ abort ();
+ }
+#else /* !PRINTF_HAS_LONG_LONG */
+ /* In the following it is important to coerce (val_long) to a long. It does
+ nothing if !LONG_LONG, but it will chop off the top half (which we know
+ we can ignore) if the host supports long longs. */
+
+ switch (format)
+ {
+ case 'd':
+ fprintf_filtered (stream,
+ use_local ? local_decimal_format_custom ("l")
+ : "%ld",
+ (long) val_long);
+ break;
+ case 'u':
+ fprintf_filtered (stream, "%lu", (unsigned long) val_long);
+ break;
+ case 'x':
+ fprintf_filtered (stream,
+ use_local ? local_hex_format_custom ("l")
+ : "%lx",
+ (long) val_long);
+ break;
+ case 'o':
+ fprintf_filtered (stream,
+ use_local ? local_octal_format_custom ("l")
+ : "%lo",
+ (long) val_long);
+ break;
+ case 'b':
+ fprintf_filtered (stream, local_hex_format_custom ("02l"),
+ (long) val_long);
+ break;
+ case 'h':
+ fprintf_filtered (stream, local_hex_format_custom ("04l"),
+ (long) val_long);
+ break;
+ case 'w':
+ fprintf_filtered (stream, local_hex_format_custom ("08l"),
+ (long) val_long);
+ break;
+ case 'g':
+ fprintf_filtered (stream, local_hex_format_custom ("016l"),
+ (long) val_long);
+ break;
+ default:
+ abort ();
+ }
+#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. */
+
+void
+print_floating (valaddr, type, stream)
+ char *valaddr;
+ struct type *type;
+ GDB_FILE *stream;
+{
+ DOUBLEST doub;
+ int inv;
+ unsigned len = TYPE_LENGTH (type);
+
+#if defined (IEEE_FLOAT)
+
+ /* Check for NaN's. Note that this code does not depend on us being
+ on an IEEE conforming system. It only depends on the target
+ machine using IEEE representation. This means (a)
+ cross-debugging works right, and (2) IEEE_FLOAT can (and should)
+ be defined for systems like the 68881, which uses IEEE
+ representation, but is not IEEE conforming. */
+
+ {
+ 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 == 4)
+ {
+ /* 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 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)
+ {
+ low = extract_unsigned_integer (valaddr + 4, 4);
+ high = extract_unsigned_integer (valaddr, 4);
+ }
+ else
+ {
+ low = extract_unsigned_integer (valaddr, 4);
+ high = extract_unsigned_integer (valaddr + 4, 4);
+ }
+ 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)
+ {
+ /* The meaning of the sign and fraction is not defined by IEEE.
+ But the user might know what they mean. For example, they
+ (in an implementation-defined manner) distinguish between
+ signaling and quiet NaN's. */
+ if (high)
+ fprintf_filtered (stream, "-NaN(0x%lx%.8lx)" + nonnegative,
+ high, low);
+ else
+ fprintf_filtered (stream, "-NaN(0x%lx)" + nonnegative, low);
+ return;
+ }
+ }
+#endif /* IEEE_FLOAT. */
+
+ doub = unpack_double (type, valaddr, &inv);
+ if (inv)
+ {
+ fprintf_filtered (stream, "<invalid float value>");
+ return;
+ }
+
+ if (len < sizeof (double))
+ fprintf_filtered (stream, "%.9g", (double) doub);
+ else if (len == sizeof (double))
+ fprintf_filtered (stream, "%.17g", (double) doub);
+ else
+#ifdef PRINTF_HAS_LONG_DOUBLE
+ fprintf_filtered (stream, "%.35Lg", doub);
+#else
+ /* This at least wins with values that are representable as doubles */
+ fprintf_filtered (stream, "%.17g", (double) doub);
+#endif
+}
+
+/* VALADDR points to an integer of LEN bytes. Print it in hex on stream. */
+
+static void
+print_hex_chars (stream, valaddr, len)
+ GDB_FILE *stream;
+ unsigned char *valaddr;
+ unsigned len;
+{
+ unsigned char *p;
+
+ /* FIXME: We should be not printing leading zeroes in most cases. */
+
+ fprintf_filtered (stream, local_hex_format_prefix ());
+ if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+ {
+ for (p = valaddr;
+ p < valaddr + len;
+ p++)
+ {
+ fprintf_filtered (stream, "%02x", *p);
+ }
+ }
+ else
+ {
+ for (p = valaddr + len - 1;
+ p >= valaddr;
+ p--)
+ {
+ fprintf_filtered (stream, "%02x", *p);
+ }
+ }
+ fprintf_filtered (stream, local_hex_format_suffix ());
+}
+
+/* Called by various <lang>_val_print routines to print elements of an
+ array in the form "<elem1>, <elem2>, <elem3>, ...".
+
+ (FIXME?) Assumes array element separator is a comma, which is correct
+ for all languages currently handled.
+ (FIXME?) Some languages have a notation for repeated array elements,
+ perhaps we should try to use that notation when appropriate.
+ */
+
+void
+val_print_array_elements (type, valaddr, address, stream, format, deref_ref,
+ recurse, pretty, i)
+ 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;
+{
+ unsigned int things_printed = 0;
+ unsigned len;
+ struct type *elttype;
+ 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;
+
+ elttype = TYPE_TARGET_TYPE (type);
+ eltlen = TYPE_LENGTH (check_typedef (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;
+ }
+
+ 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, " <repeats %u times>", reps);
+ annotate_elt_rep_end ();
+
+ i = rep1 - 1;
+ things_printed += repeat_count_threshold;
+ }
+ else
+ {
+ 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 a string from the inferior, starting at ADDR and printing up to LEN
+ characters, to STREAM. If LEN is zero, printing stops at the first null
+ 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;
+ GDB_FILE *stream;
+{
+ int force_ellipsis = 0; /* Force ellipsis to be printed if nonzero. */
+ int errcode; /* Errno returned from bad reads. */
+ unsigned int fetchlimit; /* Maximum number of bytes to fetch. */
+ unsigned int nfetch; /* Bytes to fetch / bytes fetched. */
+ unsigned int chunksize; /* Size of each fetch, in bytes. */
+ unsigned int bufsize; /* Size of current fetch buffer. */
+ char *buffer = NULL; /* Dynamically growable fetch buffer. */
+ char *bufptr; /* Pointer to next available byte in buffer. */
+ char *limit; /* First location past end of fetch buffer. */
+ struct cleanup *old_chain = NULL; /* Top of the old cleanup chain. */
+ char peekchar; /* Place into which we can read one char. */
+
+ /* First we need to figure out the limit on the number of characters we are
+ going to attempt to fetch and print. This is actually pretty simple. If
+ LEN is nonzero, then the limit is the minimum of LEN and print_max. If
+ LEN is zero, then the limit is print_max. This is true regardless of
+ whether print_max is zero, UINT_MAX (unlimited), or something in between,
+ because finding the null byte (or available memory) is what actually
+ limits the fetch. */
+
+ fetchlimit = (len == 0 ? print_max : min (len, print_max));
+
+ /* Now decide how large of chunks to try to read in one operation. This
+ is also pretty simple. If LEN is nonzero, then we want fetchlimit bytes,
+ so we might as well read them all in one operation. If LEN is zero, we
+ 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 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 (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. */
+
+ bufsize = 0;
+ do {
+ QUIT;
+ /* Figure out how much to fetch this time, and grow the buffer to fit. */
+ nfetch = min (chunksize, fetchlimit - bufsize);
+ bufsize += nfetch;
+ if (buffer == NULL)
+ {
+ buffer = (char *) xmalloc (bufsize);
+ bufptr = buffer;
+ }
+ else
+ {
+ discard_cleanups (old_chain);
+ buffer = (char *) xrealloc (buffer, bufsize);
+ bufptr = buffer + bufsize - nfetch;
+ }
+ old_chain = make_cleanup (free, buffer);
+
+ /* Read as much as we can. */
+ nfetch = target_read_memory_partial (addr, bufptr, nfetch, &errcode);
+ if (len != 0)
+ {
+ addr += nfetch;
+ bufptr += nfetch;
+ }
+ else
+ {
+ /* Scan this chunk for the null byte that terminates the string
+ to print. If found, we don't need to fetch any more. Note
+ that bufptr is explicitly left pointing at the next character
+ after the null byte, or at the next character after the end of
+ the buffer. */
+ limit = bufptr + nfetch;
+ 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 */
+ && 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. */
+
+ 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. */
+ if (target_read_memory (addr, &peekchar, 1) != 0 || peekchar != '\0')
+ {
+ force_ellipsis = 1;
+ }
+ }
+ else if ((len != 0 && errcode != 0) || (len > bufptr - buffer))
+ {
+ /* Getting an error when we have a requested length, or fetching less
+ than the number of characters actually requested, always make us
+ print ellipsis. */
+ force_ellipsis = 1;
+ }
+
+ QUIT;
+
+ /* 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)
+ {
+ if (addressprint)
+ {
+ fputs_filtered (" ", stream);
+ }
+ LA_PRINT_STRING (stream, buffer, bufptr - buffer, force_ellipsis);
+ }
+
+ if (errcode != 0)
+ {
+ if (errcode == EIO)
+ {
+ fprintf_filtered (stream, " <Address ");
+ print_address_numeric (addr, 1, stream);
+ fprintf_filtered (stream, " out of bounds>");
+ }
+ else
+ {
+ fprintf_filtered (stream, " <Error reading address ");
+ print_address_numeric (addr, 1, stream);
+ fprintf_filtered (stream, ": %s>", safe_strerror (errcode));
+ }
+ }
+ gdb_flush (stream);
+ do_cleanups (old_chain);
+ return (bufptr - buffer);
+}
+
+
+/* Validate an input or output radix setting, and make sure the user
+ knows what they really did here. Radix setting is confusing, e.g.
+ setting the input radix to "10" never changes it! */
+
+/* ARGSUSED */
+static void
+set_input_radix (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ set_input_radix_1 (from_tty, *(unsigned *)c->var);
+}
+
+/* ARGSUSED */
+static void
+set_input_radix_1 (from_tty, radix)
+ int from_tty;
+ unsigned radix;
+{
+ /* We don't currently disallow any input radix except 0 or 1, which don't
+ make any mathematical sense. In theory, we can deal with any input
+ radix greater than 1, even if we don't have unique digits for every
+ value from 0 to radix-1, but in practice we lose on large radix values.
+ We should either fix the lossage or restrict the radix range more.
+ (FIXME). */
+
+ if (radix < 2)
+ {
+ error ("Nonsense input radix ``decimal %u''; input radix unchanged.",
+ radix);
+ }
+ input_radix = radix;
+ if (from_tty)
+ {
+ printf_filtered ("Input radix now set to decimal %u, hex %x, octal %o.\n",
+ radix, radix, radix);
+ }
+}
+
+/* ARGSUSED */
+static void
+set_output_radix (args, from_tty, c)
+ char *args;
+ int from_tty;
+ struct cmd_list_element *c;
+{
+ set_output_radix_1 (from_tty, *(unsigned *)c->var);
+}
+
+static void
+set_output_radix_1 (from_tty, radix)
+ int from_tty;
+ unsigned radix;
+{
+ /* Validate the radix and disallow ones that we aren't prepared to
+ handle correctly, leaving the radix unchanged. */
+ switch (radix)
+ {
+ case 16:
+ output_format = 'x'; /* hex */
+ break;
+ case 10:
+ output_format = 0; /* decimal */
+ break;
+ case 8:
+ output_format = 'o'; /* octal */
+ break;
+ default:
+ error ("Unsupported output radix ``decimal %u''; output radix unchanged.",
+ radix);
+ }
+ output_radix = radix;
+ if (from_tty)
+ {
+ printf_filtered ("Output radix now set to decimal %u, hex %x, octal %o.\n",
+ radix, radix, radix);
+ }
+}
+
+/* Set both the input and output radix at once. Try to set the output radix
+ first, since it has the most restrictive range. An radix that is valid as
+ an output radix is also valid as an input radix.
+
+ It may be useful to have an unusual input radix. If the user wishes to
+ set an input radix that is not valid as an output radix, he needs to use
+ the 'set input-radix' command. */
+
+static void
+set_radix (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ unsigned radix;
+
+ radix = (arg == NULL) ? 10 : parse_and_eval_address (arg);
+ set_output_radix_1 (0, radix);
+ set_input_radix_1 (0, radix);
+ if (from_tty)
+ {
+ printf_filtered ("Input and output radices now set to decimal %u, hex %x, octal %o.\n",
+ radix, radix, radix);
+ }
+}
+
+/* Show both the input and output radices. */
+
+/*ARGSUSED*/
+static void
+show_radix (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ if (from_tty)
+ {
+ if (input_radix == output_radix)
+ {
+ printf_filtered ("Input and output radices set to decimal %u, hex %x, octal %o.\n",
+ input_radix, input_radix, input_radix);
+ }
+ else
+ {
+ printf_filtered ("Input radix set to decimal %u, hex %x, octal %o.\n",
+ input_radix, input_radix, input_radix);
+ printf_filtered ("Output radix set to decimal %u, hex %x, octal %o.\n",
+ output_radix, output_radix, output_radix);
+ }
+ }
+}
+
+
+/*ARGSUSED*/
+static void
+set_print (arg, from_tty)
+ char *arg;
+ int from_tty;
+{
+ printf_unfiltered (
+"\"set print\" must be followed by the name of a print subcommand.\n");
+ help_list (setprintlist, "set print ", -1, gdb_stdout);
+}
+
+/*ARGSUSED*/
+static void
+show_print (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ cmd_show_list (showprintlist, from_tty, "");
+}
+
+void
+_initialize_valprint ()
+{
+ struct cmd_list_element *c;
+
+ add_prefix_cmd ("print", no_class, set_print,
+ "Generic command for setting how things print.",
+ &setprintlist, "set print ", 0, &setlist);
+ add_alias_cmd ("p", "print", no_class, 1, &setlist);
+ /* prefer set print to set prompt */
+ add_alias_cmd ("pr", "print", no_class, 1, &setlist);
+
+ add_prefix_cmd ("print", no_class, show_print,
+ "Generic command for showing print settings.",
+ &showprintlist, "show print ", 0, &showlist);
+ add_alias_cmd ("p", "print", no_class, 1, &showlist);
+ add_alias_cmd ("pr", "print", no_class, 1, &showlist);
+
+ add_show_from_set
+ (add_set_cmd ("elements", no_class, var_uinteger, (char *)&print_max,
+ "Set limit on string chars or array elements to print.\n\
+\"set print elements 0\" causes there to be no limit.",
+ &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,
+ "Set threshold for repeated print elements.\n\
+\"set print repeats 0\" causes all elements to be individually printed.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("pretty", class_support, var_boolean,
+ (char *)&prettyprint_structs,
+ "Set prettyprinting of structures.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("union", class_support, var_boolean, (char *)&unionprint,
+ "Set printing of unions interior to structures.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("array", class_support, var_boolean,
+ (char *)&prettyprint_arrays,
+ "Set prettyprinting of arrays.",
+ &setprintlist),
+ &showprintlist);
+
+ add_show_from_set
+ (add_set_cmd ("address", class_support, var_boolean, (char *)&addressprint,
+ "Set printing of addresses.",
+ &setprintlist),
+ &showprintlist);
+
+ c = add_set_cmd ("input-radix", class_support, var_uinteger,
+ (char *)&input_radix,
+ "Set default input radix for entering numbers.",
+ &setlist);
+ add_show_from_set (c, &showlist);
+ c->function.sfunc = set_input_radix;
+
+ c = add_set_cmd ("output-radix", class_support, var_uinteger,
+ (char *)&output_radix,
+ "Set default output radix for printing of values.",
+ &setlist);
+ add_show_from_set (c, &showlist);
+ c->function.sfunc = set_output_radix;
+
+ /* The "set radix" and "show radix" commands are special in that they are
+ like normal set and show commands but allow two normally independent
+ variables to be either set or shown with a single command. So the
+ usual add_set_cmd() and add_show_from_set() commands aren't really
+ appropriate. */
+ add_cmd ("radix", class_support, set_radix,
+ "Set default input and output number radices.\n\
+Use 'set input-radix' or 'set output-radix' to independently set each.\n\
+Without an argument, sets both radices back to the default value of 10.",
+ &setlist);
+ add_cmd ("radix", class_support, show_radix,
+ "Show the default input and output number radices.\n\
+Use 'show input-radix' or 'show output-radix' to independently show each.",
+ &showlist);
+
+ /* Give people the defaults which they are used to. */
+ prettyprint_structs = 0;
+ prettyprint_arrays = 0;
+ unionprint = 1;
+ addressprint = 1;
+ print_max = PRINT_MAX_DEFAULT;
+}
diff --git a/contrib/gdb/gdb/valprint.h b/contrib/gdb/gdb/valprint.h
new file mode 100644
index 0000000..c486dee
--- /dev/null
+++ b/contrib/gdb/gdb/valprint.h
@@ -0,0 +1,44 @@
+/* Declarations for value printing routines for GDB, the GNU debugger.
+ Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+extern int prettyprint_arrays; /* Controls pretty printing of arrays. */
+extern int prettyprint_structs; /* Controls pretty printing of structures */
+extern int prettyprint_arrays; /* Controls pretty printing of arrays. */
+
+extern int vtblprint; /* Controls printing of vtbl's */
+extern int unionprint; /* Controls printing of nested unions. */
+extern int addressprint; /* Controls pretty printing of addresses. */
+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, GDB_FILE *,
+ int, int, int, enum val_prettyprint, int));
+
+extern void
+val_print_type_code_int PARAMS ((struct type *, char *, GDB_FILE *));
+
diff --git a/contrib/gdb/gdb/value.h b/contrib/gdb/gdb/value.h
new file mode 100644
index 0000000..2363695
--- /dev/null
+++ b/contrib/gdb/gdb/value.h
@@ -0,0 +1,491 @@
+/* Definitions for values of C expressions, for GDB.
+ Copyright 1986, 1987, 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (VALUE_H)
+#define VALUE_H 1
+
+/*
+ * The structure which defines the type of a value. It should never
+ * be possible for a program lval value to survive over a call to the inferior
+ * (ie to be put into the history list or an internal variable).
+ */
+enum lval_type {
+ /* Not an lval. */
+ not_lval,
+ /* In memory. Could be a saved register. */
+ lval_memory,
+ /* In a register. */
+ lval_register,
+ /* In a gdb internal variable. */
+ lval_internalvar,
+ /* Part of a gdb internal variable (structure field). */
+ lval_internalvar_component,
+ /* In a register series in a frame not the current one, which may have been
+ partially saved or saved in different places (otherwise would be
+ lval_register or lval_memory). */
+ lval_reg_frame_relative
+};
+
+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
+ {
+ /* Address in inferior or byte of registers structure. */
+ CORE_ADDR address;
+ /* Pointer to internal variable. */
+ struct internalvar *internalvar;
+ /* Number of register. Only used with
+ lval_reg_frame_relative. */
+ int regnum;
+ } location;
+ /* Describes offset of a value within lval a structure in bytes. */
+ int offset;
+ /* Only used for bitfields; number of bits contained in them. */
+ int bitsize;
+ /* Only used for bitfields; position of start of field.
+ For BITS_BIG_ENDIAN=0 targets, it is the position of the LSB.
+ For BITS_BIG_ENDIAN=1 targets, it is the position of the MSB. */
+ int bitpos;
+ /* Frame value is relative to. In practice, this address is only
+ used if the value is stored in several registers in other than
+ the current frame, and these registers have not all been saved
+ at the same place in memory. This will be described in the
+ lval enum above as "lval_reg_frame_relative". */
+ CORE_ADDR frame_addr;
+ /* Type of the value. */
+ struct type *type;
+ /* Values are stored in a chain, so that they can be deleted
+ easily over calls to the inferior. Values assigned to internal
+ variables or put into the value history are taken off this
+ list. */
+ struct value *next;
+
+ /* ??? When is this used? */
+ union {
+ CORE_ADDR memaddr;
+ char *myaddr;
+ } substring_addr;
+
+ /* Register number if the value is from a register. Is not kept
+ if you take a field of a structure that is stored in a
+ register. Shouldn't it be? */
+ short regno;
+ /* If zero, contents of this value are in the contents field.
+ If nonzero, contents are in inferior memory at address
+ in the location.address field plus the offset field
+ (and the lval field should be lval_memory). */
+ char lazy;
+ /* If nonzero, this is the value of a variable which does not
+ actually exist in the program. */
+ char optimized_out;
+ /* Actual contents of the value. For use of this value; setting
+ it uses the stuff above. Not valid if lazy is nonzero.
+ Target byte-order. We force it to be aligned properly for any
+ possible value. */
+ union {
+ long contents[1];
+ double force_double_align;
+ LONGEST force_longlong_align;
+ char *literal_data;
+ } aligner;
+
+ };
+
+typedef struct value *value_ptr;
+
+#define VALUE_TYPE(val) (val)->type
+#define VALUE_LAZY(val) (val)->lazy
+/* VALUE_CONTENTS and VALUE_CONTENTS_RAW both return the address of
+ the gdb buffer used to hold a copy of the contents of the lval.
+ VALUE_CONTENTS is used when the contents of the buffer are needed --
+ it uses value_fetch_lazy() to load the buffer from the process being
+ debugged if it hasn't already been loaded. VALUE_CONTENTS_RAW is
+ used when data is being stored into the buffer, or when it is
+ certain that the contents of the buffer are valid. */
+#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_ptr val));
+
+#define VALUE_LVAL(val) (val)->lval
+#define VALUE_ADDRESS(val) (val)->location.address
+#define VALUE_INTERNALVAR(val) (val)->location.internalvar
+#define VALUE_FRAME_REGNUM(val) ((val)->location.regnum)
+#define VALUE_FRAME(val) ((val)->frame_addr)
+#define VALUE_OFFSET(val) (val)->offset
+#define VALUE_BITSIZE(val) (val)->bitsize
+#define VALUE_BITPOS(val) (val)->bitpos
+#define VALUE_NEXT(val) (val)->next
+#define VALUE_REGNO(val) (val)->regno
+#define VALUE_OPTIMIZED_OUT(val) ((val)->optimized_out)
+
+/* Convert a REF to the object referenced. */
+
+#define COERCE_REF(arg) \
+{ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_REF) \
+ arg = value_at_lazy (TYPE_TARGET_TYPE (VALUE_TYPE (arg)), \
+ unpack_long (VALUE_TYPE (arg), \
+ VALUE_CONTENTS (arg)));}
+
+/* If ARG is an array, convert it to a pointer.
+ If ARG is an enum, convert it to an integer.
+ If ARG is a function, convert it to a function pointer.
+
+ References are dereferenced. */
+
+#define COERCE_ARRAY(arg) \
+do { COERCE_REF(arg); \
+ if (current_language->c_style_arrays \
+ && TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ARRAY) \
+ arg = value_coerce_array (arg); \
+ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_FUNC) \
+ arg = value_coerce_function (arg); \
+} while (0)
+
+#define COERCE_NUMBER(arg) \
+ do { COERCE_ARRAY(arg); COERCE_ENUM(arg); } while (0)
+
+#define COERCE_VARYING_ARRAY(arg, real_arg_type) \
+{ if (chill_varying_type (real_arg_type)) \
+ arg = varying_to_slice (arg), real_arg_type = VALUE_TYPE (arg); }
+
+/* If ARG is an enum, convert it to an integer. */
+
+#define COERCE_ENUM(arg) { \
+ if (TYPE_CODE (VALUE_TYPE (arg)) == TYPE_CODE_ENUM) \
+ arg = value_cast (builtin_type_unsigned_int, arg); \
+}
+
+/* Internal variables (variables for convenience of use of debugger)
+ are recorded as a chain of these structures. */
+
+struct internalvar
+{
+ struct internalvar *next;
+ char *name;
+ value_ptr value;
+};
+
+/* Pointer to member function. Depends on compiler implementation. */
+
+#define METHOD_PTR_IS_VIRTUAL(ADDR) ((ADDR) & 0x80000000)
+#define METHOD_PTR_FROM_VOFFSET(OFFSET) (0x80000000 + (OFFSET))
+#define METHOD_PTR_TO_VOFFSET(ADDR) (~0x80000000 & (ADDR))
+
+
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+
+#ifdef __STDC__
+struct frame_info;
+struct fn_field;
+#endif
+
+extern void
+print_address_demangle PARAMS ((CORE_ADDR, GDB_FILE *, int));
+
+extern LONGEST value_as_long PARAMS ((value_ptr val));
+
+extern DOUBLEST value_as_double PARAMS ((value_ptr val));
+
+extern CORE_ADDR value_as_pointer PARAMS ((value_ptr val));
+
+extern LONGEST unpack_long PARAMS ((struct type *type, char *valaddr));
+
+extern DOUBLEST 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_ptr value_from_longest PARAMS ((struct type *type, LONGEST num));
+
+extern value_ptr value_from_double PARAMS ((struct type *type, DOUBLEST num));
+
+extern value_ptr value_at PARAMS ((struct type *type, CORE_ADDR addr));
+
+extern value_ptr value_at_lazy PARAMS ((struct type *type, CORE_ADDR addr));
+
+extern value_ptr value_from_register PARAMS ((struct type *type, int regnum,
+ struct frame_info * frame));
+
+extern value_ptr value_of_variable PARAMS ((struct symbol *var,
+ struct block *b));
+
+extern value_ptr value_of_register PARAMS ((int regnum));
+
+extern int symbol_read_needs_frame PARAMS ((struct symbol *));
+
+extern value_ptr read_var_value PARAMS ((struct symbol *var,
+ struct frame_info *frame));
+
+extern value_ptr locate_var_value PARAMS ((struct symbol *var,
+ struct frame_info *frame));
+
+extern value_ptr allocate_value PARAMS ((struct type *type));
+
+extern value_ptr allocate_repeat_value PARAMS ((struct type *type, int count));
+
+extern value_ptr value_mark PARAMS ((void));
+
+extern void value_free_to_mark PARAMS ((value_ptr mark));
+
+extern value_ptr value_string PARAMS ((char *ptr, int len));
+extern value_ptr value_bitstring PARAMS ((char *ptr, int len));
+
+extern value_ptr value_array PARAMS ((int lowbound, int highbound,
+ value_ptr *elemvec));
+
+extern value_ptr value_concat PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern value_ptr value_binop PARAMS ((value_ptr arg1, value_ptr arg2,
+ enum exp_opcode op));
+
+extern value_ptr value_add PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern value_ptr value_sub PARAMS ((value_ptr arg1, value_ptr arg2));
+
+extern value_ptr value_coerce_array PARAMS ((value_ptr arg1));
+
+extern value_ptr value_coerce_function PARAMS ((value_ptr arg1));
+
+extern value_ptr value_ind PARAMS ((value_ptr arg1));
+
+extern value_ptr value_addr PARAMS ((value_ptr arg1));
+
+extern value_ptr value_assign PARAMS ((value_ptr toval, value_ptr fromval));
+
+extern value_ptr value_neg PARAMS ((value_ptr arg1));
+
+extern value_ptr value_complement PARAMS ((value_ptr arg1));
+
+extern value_ptr value_struct_elt PARAMS ((value_ptr *argp, value_ptr *args,
+ char *name,
+ int *static_memfuncp, char *err));
+
+extern value_ptr value_struct_elt_for_reference PARAMS ((struct type *domain,
+ int offset,
+ struct type *curtype,
+ char *name,
+ struct type *intype));
+
+extern value_ptr value_field PARAMS ((value_ptr arg1, int fieldno));
+
+extern value_ptr value_primitive_field PARAMS ((value_ptr arg1, int offset,
+ int fieldno,
+ struct type *arg_type));
+
+extern value_ptr value_cast PARAMS ((struct type *type, value_ptr arg2));
+
+extern value_ptr value_zero PARAMS ((struct type *type, enum lval_type lv));
+
+extern value_ptr value_repeat PARAMS ((value_ptr arg1, int count));
+
+extern value_ptr value_subscript PARAMS ((value_ptr array, value_ptr idx));
+
+extern value_ptr value_from_vtable_info PARAMS ((value_ptr arg,
+ struct type *type));
+
+extern value_ptr value_being_returned PARAMS ((struct type *valtype,
+ char retbuf[REGISTER_BYTES],
+ int struct_return));
+
+extern value_ptr value_in PARAMS ((value_ptr element, value_ptr set));
+
+extern int value_bit_index PARAMS ((struct type *type, char *addr, int index));
+
+extern int using_struct_return PARAMS ((value_ptr function, CORE_ADDR funcaddr,
+ struct type *value_type, int gcc_p));
+
+extern void set_return_value PARAMS ((value_ptr val));
+
+extern value_ptr evaluate_expression PARAMS ((struct expression *exp));
+
+extern value_ptr evaluate_type PARAMS ((struct expression *exp));
+
+extern value_ptr evaluate_subexp_with_coercion PARAMS ((struct expression *,
+ int *, enum noside));
+
+extern value_ptr parse_and_eval PARAMS ((char *exp));
+
+extern value_ptr parse_to_comma_and_eval PARAMS ((char **expp));
+
+extern struct type *parse_and_eval_type PARAMS ((char *p, int length));
+
+extern CORE_ADDR parse_and_eval_address PARAMS ((char *exp));
+
+extern CORE_ADDR parse_and_eval_address_1 PARAMS ((char **expptr));
+
+extern value_ptr access_value_history PARAMS ((int num));
+
+extern value_ptr value_of_internalvar PARAMS ((struct internalvar *var));
+
+extern void set_internalvar PARAMS ((struct internalvar *var, value_ptr val));
+
+extern void set_internalvar_component PARAMS ((struct internalvar *var,
+ int offset,
+ int bitpos, int bitsize,
+ value_ptr newvalue));
+
+extern struct internalvar *lookup_internalvar PARAMS ((char *name));
+
+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_ptr value_of_this PARAMS ((int complain));
+
+extern value_ptr value_x_binop PARAMS ((value_ptr arg1, value_ptr arg2,
+ enum exp_opcode op,
+ enum exp_opcode otherop));
+
+extern value_ptr value_x_unop PARAMS ((value_ptr arg1, enum exp_opcode op));
+
+extern value_ptr value_fn_field PARAMS ((value_ptr *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_ptr arg1, value_ptr arg2));
+
+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));
+
+#define value_free(val) free ((PTR)val)
+
+extern void free_all_values PARAMS ((void));
+
+extern void release_value PARAMS ((value_ptr val));
+
+extern int record_latest_value PARAMS ((value_ptr val));
+
+extern void registers_changed PARAMS ((void));
+
+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
+read_register_gen PARAMS ((int regno, char *myaddr));
+
+extern CORE_ADDR
+read_register PARAMS ((int regno));
+
+extern void
+write_register PARAMS ((int regno, LONGEST val));
+
+extern void
+supply_register PARAMS ((int regno, char *val));
+
+extern void
+get_saved_register PARAMS ((char *raw_buffer, int *optimized,
+ CORE_ADDR *addrp, struct frame_info *frame,
+ int regnum, enum lval_type *lval));
+
+extern void
+modify_field PARAMS ((char *addr, LONGEST fieldval, int bitpos, int bitsize));
+
+extern void
+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_ptr *valuep, int *errp));
+
+extern void
+print_longest PARAMS ((GDB_FILE *stream, int format, int use_local,
+ LONGEST val));
+
+extern void
+print_floating PARAMS ((char *valaddr, struct type *type, GDB_FILE *stream));
+
+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,
+ 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, GDB_FILE *stream));
+
+extern void
+print_variable_value PARAMS ((struct symbol *var, struct frame_info *frame,
+ GDB_FILE *stream));
+
+extern int check_field PARAMS ((value_ptr, const char *));
+
+extern void
+c_typedef_print PARAMS ((struct type *type, struct symbol *news, GDB_FILE *stream));
+
+extern char *
+internalvar_name PARAMS ((struct internalvar *var));
+
+extern void
+clear_value_history PARAMS ((void));
+
+extern void
+clear_internalvars PARAMS ((void));
+
+/* From values.c */
+
+extern value_ptr value_copy PARAMS ((value_ptr));
+
+extern int baseclass_offset PARAMS ((struct type *, int, char *, CORE_ADDR));
+
+/* From valops.c */
+
+extern value_ptr varying_to_slice PARAMS ((value_ptr));
+
+extern value_ptr value_slice PARAMS ((value_ptr, int, int));
+
+extern value_ptr call_function_by_hand PARAMS ((value_ptr, int, value_ptr *));
+
+extern value_ptr value_literal_complex PARAMS ((value_ptr, value_ptr, struct type*));
+
+#endif /* !defined (VALUE_H) */
diff --git a/contrib/gdb/gdb/values.c b/contrib/gdb/gdb/values.c
new file mode 100644
index 0000000..a3b6abd
--- /dev/null
+++ b/contrib/gdb/gdb/values.c
@@ -0,0 +1,1418 @@
+/* Low level packing and unpacking of values for GDB, the GNU Debugger.
+ Copyright 1986, 1987, 1989, 1991, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "gdb_string.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "frame.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "target.h"
+#include "language.h"
+#include "scm-lang.h"
+#include "demangle.h"
+
+/* Local function prototypes. */
+
+static value_ptr value_headof PARAMS ((value_ptr, struct type *,
+ struct type *));
+
+static void show_values 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
+ records 60 consecutive values. The first chunk on
+ the chain records the most recent values.
+ The total number of values is in value_history_count. */
+
+#define VALUE_HISTORY_CHUNK 60
+
+struct value_history_chunk
+{
+ struct value_history_chunk *next;
+ value_ptr values[VALUE_HISTORY_CHUNK];
+};
+
+/* Chain of chunks now in use. */
+
+static struct value_history_chunk *value_history_chain;
+
+static int value_history_count; /* Abs number of last entry stored */
+
+/* List of all value objects currently allocated
+ (except for those released by calls to release_value)
+ This is so they can be freed after each command. */
+
+static value_ptr all_values;
+
+/* Allocate a value that has the correct length for type TYPE. */
+
+value_ptr
+allocate_value (type)
+ struct type *type;
+{
+ register value_ptr val;
+ struct type *atype = check_typedef (type);
+
+ val = (struct value *) xmalloc (sizeof (struct value) + TYPE_LENGTH (atype));
+ VALUE_NEXT (val) = all_values;
+ all_values = val;
+ VALUE_TYPE (val) = type;
+ VALUE_LVAL (val) = not_lval;
+ VALUE_ADDRESS (val) = 0;
+ VALUE_FRAME (val) = 0;
+ VALUE_OFFSET (val) = 0;
+ VALUE_BITPOS (val) = 0;
+ VALUE_BITSIZE (val) = 0;
+ 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_ptr
+allocate_repeat_value (type, count)
+ struct type *type;
+ int count;
+{
+ int low_bound = current_language->string_lower_bound; /* ??? */
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ struct type *range_type
+ = create_range_type ((struct type *) NULL, builtin_type_int,
+ low_bound, count + low_bound - 1);
+ /* FIXME-type-allocation: need a way to free this type when we are
+ done with it. */
+ return allocate_value (create_array_type ((struct type *) NULL,
+ type, range_type));
+}
+
+/* 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_ptr
+value_mark ()
+{
+ return all_values;
+}
+
+/* Free all values allocated since MARK was obtained by value_mark
+ (except for those released). */
+void
+value_free_to_mark (mark)
+ value_ptr mark;
+{
+ value_ptr val, next;
+
+ for (val = all_values; val && val != mark; val = next)
+ {
+ next = VALUE_NEXT (val);
+ value_free (val);
+ }
+ all_values = val;
+}
+
+/* Free all the values that have been allocated (except for those released).
+ Called after each command, successful or not. */
+
+void
+free_all_values ()
+{
+ register value_ptr val, next;
+
+ for (val = all_values; val; val = next)
+ {
+ next = VALUE_NEXT (val);
+ value_free (val);
+ }
+
+ all_values = 0;
+}
+
+/* Remove VAL from the chain all_values
+ so it will not be freed automatically. */
+
+void
+release_value (val)
+ register value_ptr val;
+{
+ register value_ptr v;
+
+ if (all_values == val)
+ {
+ all_values = val->next;
+ return;
+ }
+
+ for (v = all_values; v; v = v->next)
+ {
+ if (v->next == val)
+ {
+ v->next = val->next;
+ break;
+ }
+ }
+}
+
+/* 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_ptr
+value_copy (arg)
+ value_ptr arg;
+{
+ register struct type *type = VALUE_TYPE (arg);
+ register value_ptr val = allocate_value (type);
+ VALUE_LVAL (val) = VALUE_LVAL (arg);
+ VALUE_ADDRESS (val) = VALUE_ADDRESS (arg);
+ VALUE_OFFSET (val) = VALUE_OFFSET (arg);
+ VALUE_BITPOS (val) = VALUE_BITPOS (arg);
+ VALUE_BITSIZE (val) = VALUE_BITSIZE (arg);
+ VALUE_FRAME (val) = VALUE_FRAME (arg);
+ VALUE_REGNO (val) = VALUE_REGNO (arg);
+ VALUE_LAZY (val) = VALUE_LAZY (arg);
+ VALUE_OPTIMIZED_OUT (val) = VALUE_OPTIMIZED_OUT (arg);
+ val->modifiable = arg->modifiable;
+ if (!VALUE_LAZY (val))
+ {
+ memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS_RAW (arg),
+ TYPE_LENGTH (VALUE_TYPE (arg)));
+ }
+ return val;
+}
+
+/* Access to the value history. */
+
+/* Record a new value in the value history.
+ Returns the absolute history index of the entry.
+ Result of -1 indicates the value was not saved; otherwise it is the
+ value history index of this new item. */
+
+int
+record_latest_value (val)
+ value_ptr val;
+{
+ int i;
+
+ /* We don't want this value to have anything to do with the inferior anymore.
+ In particular, "set $1 = 50" should not affect the variable from which
+ the value was taken, and fast watchpoints should be able to assume that
+ a value on the value history never changes. */
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+ /* 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);
+
+ /* Here we treat value_history_count as origin-zero
+ and applying to the value being stored now. */
+
+ i = value_history_count % VALUE_HISTORY_CHUNK;
+ if (i == 0)
+ {
+ register struct value_history_chunk *new
+ = (struct value_history_chunk *)
+ xmalloc (sizeof (struct value_history_chunk));
+ memset (new->values, 0, sizeof new->values);
+ new->next = value_history_chain;
+ value_history_chain = new;
+ }
+
+ value_history_chain->values[i] = val;
+
+ /* Now we regard value_history_count as origin-one
+ and applying to the value just stored. */
+
+ return ++value_history_count;
+}
+
+/* Return a copy of the value in the history with sequence number NUM. */
+
+value_ptr
+access_value_history (num)
+ int num;
+{
+ register struct value_history_chunk *chunk;
+ register int i;
+ register int absnum = num;
+
+ if (absnum <= 0)
+ absnum += value_history_count;
+
+ if (absnum <= 0)
+ {
+ if (num == 0)
+ error ("The history is empty.");
+ else if (num == 1)
+ error ("There is only one value in the history.");
+ else
+ error ("History does not go back to $$%d.", -num);
+ }
+ if (absnum > value_history_count)
+ error ("History has not yet reached $%d.", absnum);
+
+ absnum--;
+
+ /* Now absnum is always absolute and origin zero. */
+
+ chunk = value_history_chain;
+ for (i = (value_history_count - 1) / VALUE_HISTORY_CHUNK - absnum / VALUE_HISTORY_CHUNK;
+ i > 0; i--)
+ chunk = chunk->next;
+
+ return value_copy (chunk->values[absnum % VALUE_HISTORY_CHUNK]);
+}
+
+/* Clear the value history entirely.
+ Must be done when new symbol tables are loaded,
+ because the type pointers become invalid. */
+
+void
+clear_value_history ()
+{
+ register struct value_history_chunk *next;
+ register int i;
+ register value_ptr val;
+
+ while (value_history_chain)
+ {
+ for (i = 0; i < VALUE_HISTORY_CHUNK; i++)
+ if ((val = value_history_chain->values[i]) != NULL)
+ free ((PTR)val);
+ next = value_history_chain->next;
+ free ((PTR)value_history_chain);
+ value_history_chain = next;
+ }
+ value_history_count = 0;
+}
+
+static void
+show_values (num_exp, from_tty)
+ char *num_exp;
+ int from_tty;
+{
+ register int i;
+ register value_ptr val;
+ static int num = 1;
+
+ if (num_exp)
+ {
+ /* "info history +" should print from the stored position.
+ "info history <exp>" should print around value number <exp>. */
+ if (num_exp[0] != '+' || num_exp[1] != '\0')
+ num = parse_and_eval_address (num_exp) - 5;
+ }
+ else
+ {
+ /* "info history" means print the last 10 values. */
+ num = value_history_count - 9;
+ }
+
+ if (num <= 0)
+ num = 1;
+
+ for (i = num; i < num + 10 && i <= value_history_count; i++)
+ {
+ val = access_value_history (i);
+ printf_filtered ("$%d = ", i);
+ value_print (val, gdb_stdout, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+
+ /* The next "info history +" should start after what we just printed. */
+ num += 10;
+
+ /* Hitting just return after this command should do the same thing as
+ "info history +". If num_exp is null, this is unnecessary, since
+ "info history +" is not useful after "info history". */
+ if (from_tty && num_exp)
+ {
+ num_exp[0] = '+';
+ num_exp[1] = '\0';
+ }
+}
+
+/* Internal variables. These are variables within the debugger
+ that hold values assigned by debugger commands.
+ The user refers to them with a '$' prefix
+ that does not appear in the variable names stored internally. */
+
+static struct internalvar *internalvars;
+
+/* Look up an internal variable with name NAME. NAME should not
+ normally include a dollar sign.
+
+ If the specified internal variable does not exist,
+ one is created, with a void value. */
+
+struct internalvar *
+lookup_internalvar (name)
+ char *name;
+{
+ register struct internalvar *var;
+
+ for (var = internalvars; var; var = var->next)
+ if (STREQ (var->name, name))
+ return var;
+
+ var = (struct internalvar *) xmalloc (sizeof (struct internalvar));
+ var->name = concat (name, NULL);
+ var->value = allocate_value (builtin_type_void);
+ release_value (var->value);
+ var->next = internalvars;
+ internalvars = var;
+ return var;
+}
+
+value_ptr
+value_of_internalvar (var)
+ struct internalvar *var;
+{
+ register value_ptr val;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ return VALUE_OF_TRAPPED_INTERNALVAR (var);
+#endif
+
+ val = value_copy (var->value);
+ if (VALUE_LAZY (val))
+ value_fetch_lazy (val);
+ VALUE_LVAL (val) = lval_internalvar;
+ VALUE_INTERNALVAR (val) = var;
+ return val;
+}
+
+void
+set_internalvar_component (var, offset, bitpos, bitsize, newval)
+ struct internalvar *var;
+ int offset, bitpos, bitsize;
+ value_ptr newval;
+{
+ register char *addr = VALUE_CONTENTS (var->value) + offset;
+
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ SET_TRAPPED_INTERNALVAR (var, newval, bitpos, bitsize, offset);
+#endif
+
+ if (bitsize)
+ modify_field (addr, value_as_long (newval),
+ bitpos, bitsize);
+ else
+ memcpy (addr, VALUE_CONTENTS (newval), TYPE_LENGTH (VALUE_TYPE (newval)));
+}
+
+void
+set_internalvar (var, val)
+ struct internalvar *var;
+ 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
+
+ newval = value_copy (val);
+ newval->modifiable = 1;
+
+ /* 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 (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 *
+internalvar_name (var)
+ struct internalvar *var;
+{
+ return var->name;
+}
+
+/* Free all internalvars. Done when new symtabs are loaded,
+ because that makes the values invalid. */
+
+void
+clear_internalvars ()
+{
+ register struct internalvar *var;
+
+ while (internalvars)
+ {
+ var = internalvars;
+ internalvars = var->next;
+ free ((PTR)var->name);
+ free ((PTR)var->value);
+ free ((PTR)var);
+ }
+}
+
+static void
+show_convenience (ignore, from_tty)
+ char *ignore;
+ int from_tty;
+{
+ register struct internalvar *var;
+ int varseen = 0;
+
+ for (var = internalvars; var; var = var->next)
+ {
+#ifdef IS_TRAPPED_INTERNALVAR
+ if (IS_TRAPPED_INTERNALVAR (var->name))
+ continue;
+#endif
+ if (!varseen)
+ {
+ varseen = 1;
+ }
+ printf_filtered ("$%s = ", var->name);
+ value_print (var->value, gdb_stdout, 0, Val_pretty_default);
+ printf_filtered ("\n");
+ }
+ if (!varseen)
+ 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");
+}
+
+/* Extract a value as a C number (either long or double).
+ Knows how to convert fixed values to double, or
+ floating values to long.
+ Does not deallocate the value. */
+
+LONGEST
+value_as_long (val)
+ register value_ptr val;
+{
+ /* This coerces arrays and functions, which is necessary (e.g.
+ in disassemble_command). It also dereferences references, which
+ I suspect is the most logical thing to do. */
+ COERCE_ARRAY (val);
+ return unpack_long (VALUE_TYPE (val), VALUE_CONTENTS (val));
+}
+
+DOUBLEST
+value_as_double (val)
+ register value_ptr val;
+{
+ DOUBLEST foo;
+ int inv;
+
+ foo = unpack_double (VALUE_TYPE (val), VALUE_CONTENTS (val), &inv);
+ if (inv)
+ error ("Invalid floating value found in program.");
+ return foo;
+}
+/* Extract a value as a C pointer.
+ Does not deallocate the value. */
+CORE_ADDR
+value_as_pointer (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. */
+#if 0
+ /* ADDR_BITS_REMOVE is wrong if we are being called for a
+ non-address (e.g. argument to "signal", "info break", etc.), or
+ for pointers to char, in which the low bits *are* significant. */
+ return ADDR_BITS_REMOVE(value_as_long (val));
+#else
+ return value_as_long (val);
+#endif
+}
+
+/* Unpack raw data (copied from debugee, target byte order) at VALADDR
+ as a long, or as a double, assuming the raw data is described
+ by type TYPE. Knows how to convert different sizes of values
+ and can convert between fixed and floating point. We don't assume
+ any alignment for the raw data. Return value is in host byte order.
+
+ If you want functions and arrays to be coerced to pointers, and
+ references to be dereferenced, call value_as_long() instead.
+
+ C++: It is assumed that the front-end has taken care of
+ all matters concerning pointers to members. A pointer
+ to member which reaches here is considered to be equivalent
+ to an INT (or some size). After all, it is only an offset. */
+
+LONGEST
+unpack_long (type, valaddr)
+ struct type *type;
+ char *valaddr;
+{
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+ register int nosign = TYPE_UNSIGNED (type);
+
+ if (current_language->la_language == language_scm
+ && is_scmvalue_type (type))
+ return scm_unpack (type, valaddr, TYPE_CODE_INT);
+
+ switch (code)
+ {
+ case TYPE_CODE_TYPEDEF:
+ return unpack_long (check_typedef (type), valaddr);
+ 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
+ return extract_signed_integer (valaddr, len);
+
+ 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.
+ INVP points to an int which is set to 0 for valid value,
+ 1 for invalid value (bad float format). In either case,
+ the returned double is OK to use. Argument is in target
+ format, result is in host format. */
+
+DOUBLEST
+unpack_double (type, valaddr, invp)
+ struct type *type;
+ char *valaddr;
+ int *invp;
+{
+ register enum type_code code = TYPE_CODE (type);
+ register int len = TYPE_LENGTH (type);
+ register int nosign = TYPE_UNSIGNED (type);
+
+ *invp = 0; /* Assume valid. */
+ CHECK_TYPEDEF (type);
+ if (code == TYPE_CODE_FLT)
+ {
+#ifdef INVALID_FLOAT
+ if (INVALID_FLOAT (valaddr, len))
+ {
+ *invp = 1;
+ return 1.234567891011121314;
+ }
+#endif
+ 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);
+ }
+}
+
+/* Unpack raw data (copied from debugee, target byte order) at VALADDR
+ as a CORE_ADDR, assuming the raw data is described by type TYPE.
+ We don't assume any alignment for the raw data. Return value is in
+ host byte order.
+
+ If you want functions and arrays to be coerced to pointers, and
+ references to be dereferenced, call value_as_pointer() instead.
+
+ C++: It is assumed that the front-end has taken care of
+ all matters concerning pointers to members. A pointer
+ to member which reaches here is considered to be equivalent
+ to an INT (or some size). After all, it is only an offset. */
+
+CORE_ADDR
+unpack_pointer (type, valaddr)
+ struct type *type;
+ char *valaddr;
+{
+ /* Assume a CORE_ADDR can fit in a LONGEST (for now). Not sure
+ whether we want this to be true eventually. */
+ return unpack_long (type, valaddr);
+}
+
+/* Given a value ARG1 (offset by OFFSET bytes)
+ of a struct or union type ARG_TYPE,
+ extract and return the value of one of its fields.
+ FIELDNO says which field.
+
+ For C++, must also be able to return values from static fields */
+
+value_ptr
+value_primitive_field (arg1, offset, fieldno, arg_type)
+ register value_ptr arg1;
+ int offset;
+ register int fieldno;
+ register struct type *arg_type;
+{
+ register value_ptr v;
+ register struct type *type;
+
+ CHECK_TYPEDEF (arg_type);
+ type = TYPE_FIELD_TYPE (arg_type, fieldno);
+
+ /* Handle packed fields */
+
+ offset += TYPE_FIELD_BITPOS (arg_type, fieldno) / 8;
+ if (TYPE_FIELD_BITSIZE (arg_type, fieldno))
+ {
+ v = value_from_longest (type,
+ unpack_field_as_long (arg_type,
+ VALUE_CONTENTS (arg1),
+ fieldno));
+ VALUE_BITPOS (v) = TYPE_FIELD_BITPOS (arg_type, fieldno) % 8;
+ VALUE_BITSIZE (v) = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+ }
+ else
+ {
+ v = allocate_value (type);
+ if (VALUE_LAZY (arg1))
+ VALUE_LAZY (v) = 1;
+ else
+ memcpy (VALUE_CONTENTS_RAW (v), VALUE_CONTENTS_RAW (arg1) + offset,
+ TYPE_LENGTH (type));
+ }
+ VALUE_LVAL (v) = VALUE_LVAL (arg1);
+ if (VALUE_LVAL (arg1) == lval_internalvar)
+ VALUE_LVAL (v) = lval_internalvar_component;
+ VALUE_ADDRESS (v) = VALUE_ADDRESS (arg1);
+ VALUE_OFFSET (v) = offset + VALUE_OFFSET (arg1);
+ return v;
+}
+
+/* Given a value ARG1 of a struct or union type,
+ extract and return the value of one of its fields.
+ FIELDNO says which field.
+
+ For C++, must also be able to return values from static fields */
+
+value_ptr
+value_field (arg1, fieldno)
+ register value_ptr arg1;
+ register int fieldno;
+{
+ return value_primitive_field (arg1, 0, fieldno, VALUE_TYPE (arg1));
+}
+
+/* Return a non-virtual function as a value.
+ F is the list of member functions which contains the desired method.
+ J is an index into F which provides the desired method. */
+
+value_ptr
+value_fn_field (arg1p, f, j, type, offset)
+ value_ptr *arg1p;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+ int offset;
+{
+ 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)
+ 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));
+ VALUE_TYPE (v) = ftype;
+
+ if (arg1p)
+ {
+ if (type != VALUE_TYPE (*arg1p))
+ *arg1p = value_ind (value_cast (lookup_pointer_type (type),
+ value_addr (*arg1p)));
+
+ /* Move the `this' pointer according to the offset.
+ VALUE_OFFSET (*arg1p) += offset;
+ */
+ }
+
+ return v;
+}
+
+/* Return a virtual function as a value.
+ ARG1 is the object which provides the virtual function
+ table pointer. *ARG1P is side-effected in calling this function.
+ F is the list of member functions which contains the desired virtual
+ function.
+ J is an index into F which provides the desired virtual function.
+
+ TYPE is the type in which F is located. */
+value_ptr
+value_virtual_fn_field (arg1p, f, j, type, offset)
+ value_ptr *arg1p;
+ struct fn_field *f;
+ int j;
+ struct type *type;
+ int offset;
+{
+ value_ptr arg1 = *arg1p;
+ struct type *type1 = check_typedef (VALUE_TYPE (arg1));
+ struct type *entry_type;
+ /* 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_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)
+ /* We don't have an fcontext (e.g. the program was compiled with
+ g++ version 1). Try to get the vtbl from the TYPE_VPTR_BASETYPE.
+ This won't work right for multiple inheritance, but at least we
+ should do as well as GDB 3.x did. */
+ fcontext = TYPE_VPTR_BASETYPE (type);
+ context = lookup_pointer_type (fcontext);
+ /* Now context is a pointer to the basetype containing the vtbl. */
+ if (TYPE_TARGET_TYPE (context) != type1)
+ {
+ arg1 = value_ind (value_cast (context, value_addr (arg1)));
+ type1 = check_typedef (VALUE_TYPE (arg1));
+ }
+
+ context = type1;
+ /* Now context is the basetype containing the vtbl. */
+
+ /* This type may have been defined before its virtual function table
+ was. If so, fill in the virtual function table entry for the
+ type now. */
+ if (TYPE_VPTR_FIELDNO (context) < 0)
+ fill_in_vptr_fieldno (context);
+
+ /* The virtual function table is now an array of structures
+ which have the form { int16 offset, delta; void *pfn; }. */
+ vtbl = value_ind (value_primitive_field (arg1, 0,
+ TYPE_VPTR_FIELDNO (context),
+ TYPE_VPTR_BASETYPE (context)));
+
+ /* Index into the virtual function table. This is hard-coded because
+ looking up a field is not cheap, and it may be important to save
+ time, e.g. if the user has set a conditional breakpoint calling
+ a virtual function. */
+ entry = value_subscript (vtbl, vi);
+ entry_type = check_typedef (VALUE_TYPE (entry));
+
+ if (TYPE_CODE (entry_type) == TYPE_CODE_STRUCT)
+ {
+ /* 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);
+ }
+ else if (TYPE_CODE (entry_type) == 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));
+
+ *arg1p = arg1;
+ return vfn;
+}
+
+/* ARG is a pointer to an object we know to be at least
+ a DTYPE. BTYPE is the most derived basetype that has
+ already been searched (and need not be searched again).
+ After looking at the vtables between BTYPE and DTYPE,
+ return the most derived type we find. The caller must
+ be satisfied when the return value == DTYPE.
+
+ FIXME-tiemann: should work with dossier entries as well. */
+
+static value_ptr
+value_headof (in_arg, btype, dtype)
+ 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_ptr arg, vtbl, entry, best_entry = 0;
+ int i, nelems;
+ int offset, best_offset = 0;
+ struct symbol *sym;
+ CORE_ADDR pc_for_sym;
+ char *demangled_name;
+ struct minimal_symbol *msymbol;
+
+ btype = TYPE_VPTR_BASETYPE (dtype);
+ CHECK_TYPEDEF (btype);
+ arg = in_arg;
+ if (btype != dtype)
+ arg = value_cast (lookup_pointer_type (btype), arg);
+ vtbl = value_ind (value_field (value_ind (arg), TYPE_VPTR_FIELDNO (btype)));
+
+ /* Check that VTBL looks like it points to a virtual function table. */
+ msymbol = lookup_minimal_symbol_by_pc (VALUE_ADDRESS (vtbl));
+ if (msymbol == NULL
+ || (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.
+ FIXME: there has to be a better way to do this. */
+ struct type *error_type = (struct type *)xmalloc (sizeof (struct type));
+ memcpy (error_type, VALUE_TYPE (in_arg), sizeof (struct type));
+ TYPE_NAME (error_type) = savestring ("suspicious *", sizeof ("suspicious *"));
+ VALUE_TYPE (in_arg) = error_type;
+ return in_arg;
+ }
+
+ /* Now search through the virtual function table. */
+ entry = value_ind (vtbl);
+ nelems = longest_to_int (value_as_long (value_field (entry, 2)));
+ for (i = 1; i <= nelems; i++)
+ {
+ entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
+ (LONGEST) i));
+ /* This won't work if we're using thunks. */
+ if (TYPE_CODE (check_typedef (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. */
+ if (offset <= best_offset)
+ {
+ best_offset = offset;
+ best_entry = entry;
+ }
+ }
+ /* Move the pointer according to BEST_ENTRY's offset, and figure
+ out what type we should return as the new pointer. */
+ if (best_entry == 0)
+ {
+ /* An alternative method (which should no longer be necessary).
+ * But we leave it in for future use, when we will hopefully
+ * have optimizes the vtable to use thunks instead of offsets. */
+ /* Use the name of vtable itself to extract a base type. */
+ demangled_name += 4; /* Skip _vt$ prefix. */
+ }
+ else
+ {
+ pc_for_sym = value_as_pointer (value_field (best_entry, 2));
+ sym = find_pc_function (pc_for_sym);
+ demangled_name = cplus_demangle (SYMBOL_NAME (sym), DMGL_ANSI);
+ *(strchr (demangled_name, ':')) = '\0';
+ }
+ sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
+ if (sym == NULL)
+ error ("could not find type declaration for `%s'", demangled_name);
+ if (best_entry)
+ {
+ free (demangled_name);
+ arg = value_add (value_cast (builtin_type_int, arg),
+ value_field (best_entry, 0));
+ }
+ else arg = in_arg;
+ VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
+ return arg;
+}
+
+/* ARG is a pointer object of type TYPE. If TYPE has virtual
+ function tables, probe ARG's tables (including the vtables
+ of its baseclasses) to figure out the most derived type that ARG
+ could actually be a pointer to. */
+
+value_ptr
+value_from_vtable_info (arg, type)
+ value_ptr arg;
+ struct type *type;
+{
+ /* Take care of preliminaries. */
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ fill_in_vptr_fieldno (type);
+ if (TYPE_VPTR_FIELDNO (type) < 0)
+ return 0;
+
+ return value_headof (arg, 0, type);
+}
+
+/* Return true if the INDEXth field of TYPE is a virtual baseclass
+ pointer which is for the base class whose type is BASECLASS. */
+
+static int
+vb_match (type, index, basetype)
+ struct type *type;
+ int index;
+ struct type *basetype;
+{
+ struct type *fieldtype;
+ char *name = TYPE_FIELD_NAME (type, index);
+ char *field_class_name = NULL;
+
+ if (*name != '_')
+ return 0;
+ /* gcc 2.4 uses _vb$. */
+ if (name[1] == 'v' && name[2] == 'b' && is_cplus_marker (name[3]))
+ field_class_name = name + 4;
+ /* gcc 2.5 will use __vb_. */
+ if (name[1] == '_' && name[2] == 'v' && name[3] == 'b' && name[4] == '_')
+ field_class_name = name + 5;
+
+ if (field_class_name == NULL)
+ /* This field is not a virtual base class pointer. */
+ return 0;
+
+ /* It's a virtual baseclass pointer, now we just need to find out whether
+ it is for this baseclass. */
+ fieldtype = TYPE_FIELD_TYPE (type, index);
+ if (fieldtype == NULL
+ || TYPE_CODE (fieldtype) != TYPE_CODE_PTR)
+ /* "Can't happen". */
+ return 0;
+
+ /* What we check for is that either the types are equal (needed for
+ nameless types) or have the same name. This is ugly, and a more
+ elegant solution should be devised (which would probably just push
+ the ugliness into symbol reading unless we change the stabs format). */
+ if (TYPE_TARGET_TYPE (fieldtype) == basetype)
+ return 1;
+
+ if (TYPE_NAME (basetype) != NULL
+ && TYPE_NAME (TYPE_TARGET_TYPE (fieldtype)) != NULL
+ && STREQ (TYPE_NAME (basetype),
+ TYPE_NAME (TYPE_TARGET_TYPE (fieldtype))))
+ return 1;
+ return 0;
+}
+
+/* Compute the offset of the baseclass which is
+ the INDEXth baseclass of class TYPE,
+ for value at VALADDR (in host) at ADDRESS (in target).
+ The result is the offset of the baseclass value relative
+ to (the address of)(ARG) + OFFSET.
+
+ -1 is returned on error. */
+
+int
+baseclass_offset (type, index, valaddr, address)
+ struct type *type;
+ int index;
+ char *valaddr;
+ CORE_ADDR address;
+{
+ struct type *basetype = TYPE_BASECLASS (type, index);
+
+ if (BASETYPE_VIA_VIRTUAL (type, index))
+ {
+ /* Must hunt for the pointer to this virtual baseclass. */
+ register int i, len = TYPE_NFIELDS (type);
+ register int n_baseclasses = TYPE_N_BASECLASSES (type);
+
+ /* First look for the virtual baseclass pointer
+ in the fields. */
+ for (i = n_baseclasses; i < len; i++)
+ {
+ if (vb_match (type, i, basetype))
+ {
+ CORE_ADDR addr
+ = unpack_pointer (TYPE_FIELD_TYPE (type, i),
+ valaddr + (TYPE_FIELD_BITPOS (type, i) / 8));
+
+ return addr - (LONGEST) address;
+ }
+ }
+ /* Not in the fields, so try looking through the baseclasses. */
+ for (i = index+1; i < n_baseclasses; i++)
+ {
+ int boffset =
+ baseclass_offset (type, i, valaddr, address);
+ if (boffset)
+ return boffset;
+ }
+ /* Not found. */
+ return -1;
+ }
+
+ /* Baseclass is easily computed. */
+ return TYPE_BASECLASS_BITPOS (type, index) / 8;
+}
+
+/* Unpack a field FIELDNO of the specified TYPE, from the anonymous object at
+ VALADDR.
+
+ Extracting bits depends on endianness of the machine. Compute the
+ number of least significant bits to discard. For big endian machines,
+ we compute the total number of bits in the anonymous object, subtract
+ off the bit count from the MSB of the object to the MSB of the
+ bitfield, then the size of the bitfield, which leaves the LSB discard
+ count. For little endian machines, the discard count is simply the
+ number of bits from the LSB of the anonymous object to the LSB of the
+ bitfield.
+
+ If the field is signed, we also do sign extension. */
+
+LONGEST
+unpack_field_as_long (type, valaddr, fieldno)
+ struct type *type;
+ char *valaddr;
+ int fieldno;
+{
+ unsigned LONGEST val;
+ unsigned LONGEST valmask;
+ int bitpos = TYPE_FIELD_BITPOS (type, fieldno);
+ int bitsize = TYPE_FIELD_BITSIZE (type, fieldno);
+ int lsbcount;
+
+ val = extract_unsigned_integer (valaddr + bitpos / 8, sizeof (val));
+
+ /* Extract bits. See comment above. */
+
+ if (BITS_BIG_ENDIAN)
+ lsbcount = (sizeof val * 8 - bitpos % 8 - bitsize);
+ else
+ lsbcount = (bitpos % 8);
+ val >>= lsbcount;
+
+ /* If the field does not entirely fill a LONGEST, then zero the sign bits.
+ If the field is signed, and is negative, then sign extend. */
+
+ if ((bitsize > 0) && (bitsize < 8 * (int) sizeof (val)))
+ {
+ valmask = (((unsigned LONGEST) 1) << bitsize) - 1;
+ val &= valmask;
+ if (!TYPE_UNSIGNED (TYPE_FIELD_TYPE (type, fieldno)))
+ {
+ if (val & (valmask ^ (valmask >> 1)))
+ {
+ val |= ~valmask;
+ }
+ }
+ }
+ return (val);
+}
+
+/* Modify the value of a bitfield. ADDR points to a block of memory in
+ target byte order; the bitfield starts in the byte pointed to. FIELDVAL
+ is the desired value of the field, in host byte order. BITPOS and BITSIZE
+ indicate which bits (in target bit order) comprise the bitfield. */
+
+void
+modify_field (addr, fieldval, bitpos, bitsize)
+ char *addr;
+ LONGEST fieldval;
+ int bitpos, bitsize;
+{
+ LONGEST oword;
+
+ /* If a negative fieldval fits in the field in question, chop
+ off the sign extension bits. */
+ if (bitsize < (8 * (int) sizeof (fieldval))
+ && (~fieldval & ~((1 << (bitsize - 1)) - 1)) == 0)
+ fieldval = fieldval & ((1 << bitsize) - 1);
+
+ /* Warn if value is too big to fit in the field in question. */
+ if (bitsize < (8 * (int) sizeof (fieldval))
+ && 0 != (fieldval & ~((1<<bitsize)-1)))
+ {
+ /* FIXME: would like to include fieldval in the message, but
+ we don't have a sprintf_longest. */
+ warning ("Value does not fit in %d bits.", bitsize);
+
+ /* Truncate it, otherwise adjoining fields may be corrupted. */
+ fieldval = fieldval & ((1 << bitsize) - 1);
+ }
+
+ oword = extract_signed_integer (addr, sizeof oword);
+
+ /* Shifting for bit field depends on endianness of the target machine. */
+ if (BITS_BIG_ENDIAN)
+ bitpos = sizeof (oword) * 8 - bitpos - bitsize;
+
+ /* Mask out old value, while avoiding shifts >= size of oword */
+ if (bitsize < 8 * (int) sizeof (oword))
+ oword &= ~(((((unsigned LONGEST)1) << bitsize) - 1) << bitpos);
+ else
+ oword &= ~((~(unsigned LONGEST)0) << bitpos);
+ oword |= fieldval << bitpos;
+
+ store_signed_integer (addr, sizeof oword, oword);
+}
+
+/* Convert C numbers into newly allocated values */
+
+value_ptr
+value_from_longest (type, num)
+ struct type *type;
+ register LONGEST num;
+{
+ register value_ptr val = allocate_value (type);
+ register enum type_code code;
+ register int len;
+ retry:
+ code = TYPE_CODE (type);
+ len = TYPE_LENGTH (type);
+
+ switch (code)
+ {
+ case TYPE_CODE_TYPEDEF:
+ type = check_typedef (type);
+ goto retry;
+ case TYPE_CODE_INT:
+ 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;
+
+ case TYPE_CODE_REF:
+ case TYPE_CODE_PTR:
+ /* This assumes that all pointers of a given length
+ have the same form. */
+ store_address (VALUE_CONTENTS_RAW (val), len, (CORE_ADDR) num);
+ break;
+
+ default:
+ error ("Unexpected type encountered for integer constant.");
+ }
+ return val;
+}
+
+value_ptr
+value_from_double (type, num)
+ struct type *type;
+ DOUBLEST num;
+{
+ register value_ptr val = allocate_value (type);
+ struct type *base_type = check_typedef (type);
+ register enum type_code code = TYPE_CODE (base_type);
+ register int len = TYPE_LENGTH (base_type);
+
+ if (code == TYPE_CODE_FLT)
+ {
+ store_floating (VALUE_CONTENTS_RAW (val), len, num);
+ }
+ else
+ error ("Unexpected type encountered for floating constant.");
+
+ return val;
+}
+
+/* Deal with the value that is "about to be returned". */
+
+/* Return the value that a function returning now
+ would be returning to its caller, assuming its type is VALTYPE.
+ RETBUF is where we look for what ought to be the contents
+ of the registers (in raw form). This is because it is often
+ desirable to restore old values to those registers
+ after saving the contents of interest, and then call
+ this function using the saved values.
+ struct_return is non-zero when the function in question is
+ using the structure return conventions on the machine in question;
+ 0 when it is using the value returning conventions (this often
+ means returning pointer to where structure is vs. returning value). */
+
+value_ptr
+value_being_returned (valtype, retbuf, struct_return)
+ register struct type *valtype;
+ char retbuf[REGISTER_BYTES];
+ int struct_return;
+ /*ARGSUSED*/
+{
+ register value_ptr val;
+ CORE_ADDR addr;
+
+#if defined (EXTRACT_STRUCT_VALUE_ADDRESS)
+ /* If this is not defined, just use EXTRACT_RETURN_VALUE instead. */
+ if (struct_return) {
+ addr = EXTRACT_STRUCT_VALUE_ADDRESS (retbuf);
+ if (!addr)
+ error ("Function return value unknown");
+ return value_at (valtype, addr);
+ }
+#endif
+
+ val = allocate_value (valtype);
+ CHECK_TYPEDEF (valtype);
+ EXTRACT_RETURN_VALUE (valtype, retbuf, VALUE_CONTENTS_RAW (val));
+
+ return val;
+}
+
+/* Should we use EXTRACT_STRUCT_VALUE_ADDRESS instead of
+ EXTRACT_RETURN_VALUE? GCC_P is true if compiled with gcc
+ and TYPE is the type (which is known to be struct, union or array).
+
+ On most machines, the struct convention is used unless we are
+ using gcc and the type is of a special size. */
+/* As of about 31 Mar 93, GCC was changed to be compatible with the
+ native compiler. GCC 2.3.3 was the last release that did it the
+ old way. Since gcc2_compiled was not changed, we have no
+ way to correctly win in all cases, so we just do the right thing
+ for gcc1 and for gcc2 after this change. Thus it loses for gcc
+ 2.0-2.3.3. This is somewhat unfortunate, but changing gcc2_compiled
+ would cause more chaos than dealing with some struct returns being
+ handled wrong. */
+#if !defined (USE_STRUCT_CONVENTION)
+#define USE_STRUCT_CONVENTION(gcc_p, type)\
+ (!((gcc_p == 1) && (TYPE_LENGTH (value_type) == 1 \
+ || TYPE_LENGTH (value_type) == 2 \
+ || TYPE_LENGTH (value_type) == 4 \
+ || TYPE_LENGTH (value_type) == 8 \
+ ) \
+ ))
+#endif
+
+/* Some fundamental types (such as long double) are returned on the stack for
+ certain architectures. This macro should return true for any type besides
+ struct, union or array that gets returned on the stack. */
+
+#ifndef RETURN_VALUE_ON_STACK
+#define RETURN_VALUE_ON_STACK(TYPE) 0
+#endif
+
+/* Return true if the function specified is using the structure returning
+ convention on this machine to return arguments, or 0 if it is using
+ the value returning convention. FUNCTION is the value representing
+ the function, FUNCADDR is the address of the function, and VALUE_TYPE
+ is the type returned by the function. GCC_P is nonzero if compiled
+ with GCC. */
+
+int
+using_struct_return (function, funcaddr, value_type, gcc_p)
+ value_ptr function;
+ CORE_ADDR funcaddr;
+ struct type *value_type;
+ int gcc_p;
+ /*ARGSUSED*/
+{
+ register enum type_code code = TYPE_CODE (value_type);
+
+ if (code == TYPE_CODE_ERROR)
+ error ("Function return type unknown.");
+
+ if (code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION
+ || code == TYPE_CODE_ARRAY
+ || RETURN_VALUE_ON_STACK (value_type))
+ return USE_STRUCT_CONVENTION (gcc_p, value_type);
+
+ return 0;
+}
+
+/* Store VAL so it will be returned if a function returns now.
+ Does not verify that VAL's type matches what the current
+ function wants to return. */
+
+void
+set_return_value (val)
+ value_ptr val;
+{
+ struct type *type = check_typedef (VALUE_TYPE (val));
+ register enum type_code code = TYPE_CODE (type);
+
+ if (code == TYPE_CODE_ERROR)
+ error ("Function return type unknown.");
+
+ if ( code == TYPE_CODE_STRUCT
+ || code == TYPE_CODE_UNION) /* FIXME, implement struct return. */
+ error ("GDB does not support specifying a struct or union return value.");
+
+ STORE_RETURN_VALUE (type, VALUE_CONTENTS (val));
+}
+
+void
+_initialize_values ()
+{
+ add_cmd ("convenience", no_class, show_convenience,
+ "Debugger convenience (\"$foo\") variables.\n\
+These variables are created when you assign them values;\n\
+thus, \"print $foo=1\" gives \"$foo\" the value 1. Values may be any type.\n\n\
+A few convenience variables are given values automatically:\n\
+\"$_\"holds the last address examined with \"x\" or \"info lines\",\n\
+\"$__\" holds the contents of the last address examined with \"x\".",
+ &showlist);
+
+ add_cmd ("values", no_class, show_values,
+ "Elements of value history around item number IDX (or last ten).",
+ &showlist);
+}
diff --git a/contrib/gdb/gdb/xcoffread.c b/contrib/gdb/gdb/xcoffread.c
new file mode 100644
index 0000000..7704a5f
--- /dev/null
+++ b/contrib/gdb/gdb/xcoffread.c
@@ -0,0 +1,2767 @@
+/* Read AIX xcoff symbol tables and convert to internal format, for GDB.
+ Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ Free Software Foundation, Inc.
+ Derived from coffread.c, dbxread.c, and a lot of hacking.
+ Contributed by IBM Corporation.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* RS/6000 and PowerPC only:
+ Needs xcoff_add_toc_to_loadinfo and xcoff_init_loadinfo in
+ rs6000-tdep.c from target.
+ However, if you define FAKING_RS6000, then this code will link with
+ any target. */
+
+#include "defs.h"
+#include "bfd.h"
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include "gdb_string.h"
+
+#include <sys/param.h>
+#ifndef NO_SYS_FILE
+#include <sys/file.h>
+#endif
+#include "gdb_stat.h"
+
+#include "coff/internal.h"
+#include "libcoff.h" /* FIXME, internal data from BFD */
+#include "coff/rs6000.h"
+
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "buildsym.h"
+#include "stabsread.h"
+#include "expression.h"
+#include "language.h" /* Needed inside partial-stab.h */
+#include "complaints.h"
+
+#include "gdb-stabs.h"
+
+/* For interface with stabsread.c. */
+#include "aout/stab_gnu.h"
+
+/* For interface with partial-stab.h. */
+#define N_UNDF 0 /* Undefined symbol */
+#undef N_ABS
+#define N_ABS 2
+#define N_TEXT 4 /* Text sym -- defined at offset in text seg */
+#define N_DATA 6 /* Data sym -- defined at offset in data seg */
+#define N_BSS 8 /* BSS sym -- defined at offset in zero'd seg */
+#define N_COMM 0x12 /* Common symbol (visible after shared lib dynlink) */
+#define N_FN 0x1f /* File name of .o file */
+#define N_FN_SEQ 0x0C /* N_FN from Sequent compilers (sigh) */
+/* Note: N_EXT can only be usefully OR-ed with N_UNDF, N_ABS, N_TEXT,
+ N_DATA, or N_BSS. When the low-order bit of other types is set,
+ (e.g. N_WARNING versus N_FN), they are two different types. */
+#define N_EXT 1 /* External symbol (as opposed to local-to-this-file) */
+#define N_INDR 0x0a
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ elements value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+/* We put a pointer to this structure in the read_symtab_private field
+ of the psymtab. */
+
+struct symloc {
+
+ /* First symbol number for this file. */
+
+ int first_symnum;
+
+ /* Number of symbols in the section of the symbol table devoted to
+ this file's symbols (actually, the section bracketed may contain
+ more than just this file's symbols). If numsyms is 0, the only
+ reason for this thing's existence is the dependency list. Nothing
+ else will happen when it is read in. */
+
+ int numsyms;
+
+ /* Position of the start of the line number information for this psymtab. */
+ unsigned int lineno_off;
+};
+
+/* Remember what we deduced to be the source language of this psymtab. */
+
+static enum language psymtab_language = language_unknown;
+
+
+/* Simplified internal version of coff symbol table information */
+
+struct coff_symbol {
+ char *c_name;
+ int c_symnum; /* symbol number of this entry */
+ int c_naux; /* 0 if syment only, 1 if syment + auxent */
+ long c_value;
+ unsigned char c_sclass;
+ int c_secnum;
+ unsigned int c_type;
+};
+
+/* last function's saved coff symbol `cs' */
+
+static struct coff_symbol fcn_cs_saved;
+
+static bfd *symfile_bfd;
+
+/* Core address of start and end of text of current source file.
+ This is calculated from the first function seen after a C_FILE
+ symbol. */
+
+
+static CORE_ADDR cur_src_end_addr;
+
+/* Core address of the end of the first object file. */
+
+static CORE_ADDR first_object_file_end;
+
+/* initial symbol-table-debug-string vector length */
+
+#define INITIAL_STABVECTOR_LENGTH 40
+
+/* Nonzero if within a function (so symbols should be local,
+ if nothing says specifically). */
+
+int within_function;
+
+/* Size of a COFF symbol. I think it is always 18, so I'm not sure
+ there is any reason not to just use a #define, but might as well
+ ask BFD for the size and store it here, I guess. */
+
+static unsigned local_symesz;
+
+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 */
+
+ /* Pointer to the string table. */
+ char *strtbl;
+
+ /* Pointer to debug section. */
+ char *debugsec;
+
+ /* Pointer to the a.out symbol table. */
+ char *symtbl;
+
+ /* Number of symbols in symtbl. */
+ int symtbl_num_syms;
+};
+
+static struct complaint storclass_complaint =
+ {"Unexpected storage class: %d", 0, 0};
+
+static struct complaint bf_notfound_complaint =
+ {"line numbers off, `.bf' symbol not found", 0, 0};
+
+static struct complaint ef_complaint =
+ {"Mismatched .ef symbol ignored starting at symnum %d", 0, 0};
+
+static struct complaint eb_complaint =
+ {"Mismatched .eb symbol ignored starting at symnum %d", 0, 0};
+
+static void
+enter_line_range PARAMS ((struct subfile *, unsigned, unsigned,
+ CORE_ADDR, CORE_ADDR, unsigned *));
+
+static void
+init_stringtab PARAMS ((bfd *, file_ptr, struct objfile *));
+
+static void
+xcoff_symfile_init PARAMS ((struct objfile *));
+
+static void
+xcoff_new_init PARAMS ((struct objfile *));
+
+static void
+xcoff_symfile_finish PARAMS ((struct objfile *));
+
+static struct section_offsets *
+xcoff_symfile_offsets PARAMS ((struct objfile *, CORE_ADDR));
+
+static void
+find_linenos PARAMS ((bfd *, sec_ptr, PTR));
+
+static char *
+coff_getfilename PARAMS ((union internal_auxent *, struct objfile *));
+
+static void
+read_symbol PARAMS ((struct internal_syment *, int));
+
+static int
+read_symbol_lineno PARAMS ((int));
+
+static int
+read_symbol_nvalue PARAMS ((int));
+
+static struct symbol *
+process_xcoff_symbol PARAMS ((struct coff_symbol *, struct objfile *));
+
+static void
+read_xcoff_symtab PARAMS ((struct partial_symtab *));
+
+static void
+add_stab_to_list PARAMS ((char *, struct pending_stabs **));
+
+
+/* Translate from a COFF section number (target_index) to a SECT_OFF_*
+ code. */
+static int secnum_to_section PARAMS ((int, struct objfile *));
+
+struct find_targ_sec_arg {
+ int targ_index;
+ int *resultp;
+};
+
+static void find_targ_sec PARAMS ((bfd *, asection *, void *));
+
+static void find_targ_sec (abfd, sect, obj)
+ bfd *abfd;
+ asection *sect;
+ PTR obj;
+{
+ struct find_targ_sec_arg *args = (struct find_targ_sec_arg *)obj;
+ if (sect->target_index == args->targ_index)
+ {
+ /* This is the section. Figure out what SECT_OFF_* code it is. */
+ if (bfd_get_section_flags (abfd, sect) & SEC_CODE)
+ *args->resultp = SECT_OFF_TEXT;
+ else if (bfd_get_section_flags (abfd, sect) & SEC_LOAD)
+ *args->resultp = SECT_OFF_DATA;
+ else
+ *args->resultp = SECT_OFF_BSS;
+ }
+}
+
+/* Return the section number (SECT_OFF_*) that CS points to. */
+static int
+secnum_to_section (secnum, objfile)
+ int secnum;
+ struct objfile *objfile;
+{
+ int off = SECT_OFF_TEXT;
+ struct find_targ_sec_arg args;
+ args.targ_index = secnum;
+ args.resultp = &off;
+ bfd_map_over_sections (objfile->obfd, find_targ_sec, &args);
+ return off;
+}
+
+/* add a given stab string into given stab vector. */
+
+static void
+add_stab_to_list (stabname, stabvector)
+char *stabname;
+struct pending_stabs **stabvector;
+{
+ if ( *stabvector == NULL) {
+ *stabvector = (struct pending_stabs *)
+ xmalloc (sizeof (struct pending_stabs) +
+ INITIAL_STABVECTOR_LENGTH * sizeof (char*));
+ (*stabvector)->count = 0;
+ (*stabvector)->length = INITIAL_STABVECTOR_LENGTH;
+ }
+ else if ((*stabvector)->count >= (*stabvector)->length) {
+ (*stabvector)->length += INITIAL_STABVECTOR_LENGTH;
+ *stabvector = (struct pending_stabs *)
+ xrealloc ((char *) *stabvector, sizeof (struct pending_stabs) +
+ (*stabvector)->length * sizeof (char*));
+ }
+ (*stabvector)->stab [(*stabvector)->count++] = stabname;
+}
+
+/* Linenos are processed on a file-by-file basis.
+
+ Two reasons:
+
+ 1) xlc (IBM's native c compiler) postpones static function code
+ emission to the end of a compilation unit. This way it can
+ determine if those functions (statics) are needed or not, and
+ can do some garbage collection (I think). This makes line
+ numbers and corresponding addresses unordered, and we end up
+ with a line table like:
+
+
+ lineno addr
+ foo() 10 0x100
+ 20 0x200
+ 30 0x300
+
+ foo3() 70 0x400
+ 80 0x500
+ 90 0x600
+
+ static foo2()
+ 40 0x700
+ 50 0x800
+ 60 0x900
+
+ and that breaks gdb's binary search on line numbers, if the
+ above table is not sorted on line numbers. And that sort
+ should be on function based, since gcc can emit line numbers
+ like:
+
+ 10 0x100 - for the init/test part of a for stmt.
+ 20 0x200
+ 30 0x300
+ 10 0x400 - for the increment part of a for stmt.
+
+ arrange_linetable() will do this sorting.
+
+ 2) aix symbol table might look like:
+
+ c_file // beginning of a new file
+ .bi // beginning of include file
+ .ei // end of include file
+ .bi
+ .ei
+
+ basically, .bi/.ei pairs do not necessarily encapsulate
+ their scope. They need to be recorded, and processed later
+ on when we come the end of the compilation unit.
+ Include table (inclTable) and process_linenos() handle
+ that. */
+
+/* compare line table entry addresses. */
+
+static int
+compare_lte (lte1, lte2)
+ struct linetable_entry *lte1, *lte2;
+{
+ return lte1->pc - lte2->pc;
+}
+
+/* Give a line table with function entries are marked, arrange its functions
+ in assending order and strip off function entry markers and return it in
+ a newly created table. If the old one is good enough, return the old one. */
+/* FIXME: I think all this stuff can be replaced by just passing
+ sort_linevec = 1 to end_symtab. */
+
+static struct linetable *
+arrange_linetable (oldLineTb)
+ struct linetable *oldLineTb; /* old linetable */
+{
+ int ii, jj,
+ newline, /* new line count */
+ function_count; /* # of functions */
+
+ struct linetable_entry *fentry; /* function entry vector */
+ int fentry_size; /* # of function entries */
+ struct linetable *newLineTb; /* new line table */
+
+#define NUM_OF_FUNCTIONS 20
+
+ fentry_size = NUM_OF_FUNCTIONS;
+ fentry = (struct linetable_entry*)
+ xmalloc (fentry_size * sizeof (struct linetable_entry));
+
+ for (function_count=0, ii=0; ii <oldLineTb->nitems; ++ii) {
+
+ if (oldLineTb->item[ii].line == 0) { /* function entry found. */
+
+ if (function_count >= fentry_size) { /* make sure you have room. */
+ fentry_size *= 2;
+ fentry = (struct linetable_entry*)
+ xrealloc (fentry, fentry_size * sizeof (struct linetable_entry));
+ }
+ fentry[function_count].line = ii;
+ fentry[function_count].pc = oldLineTb->item[ii].pc;
+ ++function_count;
+ }
+ }
+
+ if (function_count == 0) {
+ free (fentry);
+ return oldLineTb;
+ }
+ else if (function_count > 1)
+ qsort (fentry, function_count, sizeof(struct linetable_entry), compare_lte);
+
+ /* allocate a new line table. */
+ newLineTb = (struct linetable *)
+ xmalloc
+ (sizeof (struct linetable) +
+ (oldLineTb->nitems - function_count) * sizeof (struct linetable_entry));
+
+ /* if line table does not start with a function beginning, copy up until
+ a function begin. */
+
+ newline = 0;
+ if (oldLineTb->item[0].line != 0)
+ for (newline=0;
+ newline < oldLineTb->nitems && oldLineTb->item[newline].line; ++newline)
+ newLineTb->item[newline] = oldLineTb->item[newline];
+
+ /* Now copy function lines one by one. */
+
+ for (ii=0; ii < function_count; ++ii) {
+ for (jj = fentry[ii].line + 1;
+ jj < oldLineTb->nitems && oldLineTb->item[jj].line != 0;
+ ++jj, ++newline)
+ newLineTb->item[newline] = oldLineTb->item[jj];
+ }
+ free (fentry);
+ newLineTb->nitems = oldLineTb->nitems - function_count;
+ return newLineTb;
+}
+
+/* include file support: C_BINCL/C_EINCL pairs will be kept in the
+ following `IncludeChain'. At the end of each symtab (end_symtab),
+ we will determine if we should create additional symtab's to
+ represent if (the include files. */
+
+
+typedef struct _inclTable {
+ char *name; /* include filename */
+
+ /* Offsets to the line table. end points to the last entry which is
+ part of this include file. */
+ int begin, end;
+
+ struct subfile *subfile;
+ unsigned funStartLine; /* start line # of its function */
+} InclTable;
+
+#define INITIAL_INCLUDE_TABLE_LENGTH 20
+static InclTable *inclTable; /* global include table */
+static int inclIndx; /* last entry to table */
+static int inclLength; /* table length */
+static int inclDepth; /* nested include depth */
+
+static void allocate_include_entry PARAMS ((void));
+
+static void
+record_include_begin (cs)
+struct coff_symbol *cs;
+{
+ if (inclDepth)
+ {
+ /* In xcoff, we assume include files cannot be nested (not in .c files
+ of course, but in corresponding .s files.). */
+
+ /* This can happen with old versions of GCC.
+ GCC 2.3.3-930426 does not exhibit this on a test case which
+ a user said produced the message for him. */
+ static struct complaint msg = {"Nested C_BINCL symbols", 0, 0};
+ complain (&msg);
+ }
+ ++inclDepth;
+
+ allocate_include_entry ();
+
+ inclTable [inclIndx].name = cs->c_name;
+ inclTable [inclIndx].begin = cs->c_value;
+}
+
+static void
+record_include_end (cs)
+struct coff_symbol *cs;
+{
+ InclTable *pTbl;
+
+ if (inclDepth == 0)
+ {
+ static struct complaint msg = {"Mismatched C_BINCL/C_EINCL pair", 0, 0};
+ complain (&msg);
+ }
+
+ allocate_include_entry ();
+
+ pTbl = &inclTable [inclIndx];
+ pTbl->end = cs->c_value;
+
+ --inclDepth;
+ ++inclIndx;
+}
+
+static void
+allocate_include_entry ()
+{
+ if (inclTable == NULL)
+ {
+ inclTable = (InclTable *)
+ xmalloc (sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH);
+ memset (inclTable,
+ '\0', sizeof (InclTable) * INITIAL_INCLUDE_TABLE_LENGTH);
+ inclLength = INITIAL_INCLUDE_TABLE_LENGTH;
+ inclIndx = 0;
+ }
+ else if (inclIndx >= inclLength)
+ {
+ inclLength += INITIAL_INCLUDE_TABLE_LENGTH;
+ inclTable = (InclTable *)
+ xrealloc (inclTable, sizeof (InclTable) * inclLength);
+ memset (inclTable + inclLength - INITIAL_INCLUDE_TABLE_LENGTH,
+ '\0', sizeof (InclTable)*INITIAL_INCLUDE_TABLE_LENGTH);
+ }
+}
+
+/* Global variable to pass the psymtab down to all the routines involved
+ in psymtab to symtab processing. */
+static struct partial_symtab *this_symtab_psymtab;
+
+/* given the start and end addresses of a compilation unit (or a csect,
+ at times) process its lines and create appropriate line vectors. */
+
+static void
+process_linenos (start, end)
+ CORE_ADDR start, end;
+{
+ int offset, ii;
+ file_ptr max_offset =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->max_lineno_offset;
+
+ /* subfile structure for the main compilation unit. */
+ struct subfile main_subfile;
+
+ /* In the main source file, any time we see a function entry, we
+ reset this variable to function's absolute starting line number.
+ All the following line numbers in the function are relative to
+ this, and we record absolute line numbers in record_line(). */
+
+ unsigned int main_source_baseline = 0;
+
+ unsigned *firstLine;
+
+ offset =
+ ((struct symloc *)this_symtab_psymtab->read_symtab_private)->lineno_off;
+ if (offset == 0)
+ goto return_after_cleanup;
+
+ memset (&main_subfile, '\0', sizeof (main_subfile));
+
+ if (inclIndx == 0)
+ /* All source lines were in the main source file. None in include files. */
+
+ enter_line_range (&main_subfile, offset, 0, start, end,
+ &main_source_baseline);
+
+ else
+ {
+ /* There was source with line numbers in include files. */
+ main_source_baseline = 0;
+ for (ii=0; ii < inclIndx; ++ii)
+ {
+ struct subfile *tmpSubfile;
+
+ /* If there is main file source before include file, enter it. */
+ if (offset < inclTable[ii].begin)
+ {
+ enter_line_range
+ (&main_subfile, offset, inclTable[ii].begin - LINESZ,
+ start, 0, &main_source_baseline);
+ }
+
+ /* Have a new subfile for the include file. */
+
+ tmpSubfile = inclTable[ii].subfile =
+ (struct subfile *) xmalloc (sizeof (struct subfile));
+
+ memset (tmpSubfile, '\0', sizeof (struct subfile));
+ firstLine = &(inclTable[ii].funStartLine);
+
+ /* Enter include file's lines now. */
+ enter_line_range (tmpSubfile, inclTable[ii].begin,
+ inclTable[ii].end, start, 0, firstLine);
+
+ if (offset <= inclTable[ii].end)
+ offset = inclTable[ii].end + LINESZ;
+ }
+
+ /* All the include files' line have been processed at this point. Now,
+ enter remaining lines of the main file, if any left. */
+ if (offset < max_offset + 1 - LINESZ)
+ {
+ enter_line_range (&main_subfile, offset, 0, start, end,
+ &main_source_baseline);
+ }
+ }
+
+ /* Process main file's line numbers. */
+ if (main_subfile.line_vector)
+ {
+ struct linetable *lineTb, *lv;
+
+ lv = main_subfile.line_vector;
+
+ /* Line numbers are not necessarily ordered. xlc compilation will
+ put static function to the end. */
+
+ lineTb = arrange_linetable (lv);
+ if (lv == lineTb)
+ {
+ current_subfile->line_vector = (struct linetable *)
+ xrealloc (lv, (sizeof (struct linetable)
+ + lv->nitems * sizeof (struct linetable_entry)));
+ }
+ else
+ {
+ free (lv);
+ current_subfile->line_vector = lineTb;
+ }
+
+ current_subfile->line_vector_length =
+ current_subfile->line_vector->nitems;
+ }
+
+ /* Now, process included files' line numbers. */
+
+ for (ii=0; ii < inclIndx; ++ii)
+ {
+ if ((inclTable[ii].subfile)->line_vector) /* Useless if!!! FIXMEmgo */
+ {
+ struct linetable *lineTb, *lv;
+
+ lv = (inclTable[ii].subfile)->line_vector;
+
+ /* Line numbers are not necessarily ordered. xlc compilation will
+ put static function to the end. */
+
+ lineTb = arrange_linetable (lv);
+
+ push_subfile ();
+
+ /* For the same include file, we might want to have more than one
+ subfile. This happens if we have something like:
+
+ ......
+ #include "foo.h"
+ ......
+ #include "foo.h"
+ ......
+
+ while foo.h including code in it. (stupid but possible)
+ Since start_subfile() looks at the name and uses an
+ existing one if finds, we need to provide a fake name and
+ fool it. */
+
+#if 0
+ start_subfile (inclTable[ii].name, (char*)0);
+#else
+ {
+ /* Pick a fake name that will produce the same results as this
+ one when passed to deduce_language_from_filename. Kludge on
+ top of kludge. */
+ char *fakename = strrchr (inclTable[ii].name, '.');
+ if (fakename == NULL)
+ fakename = " ?";
+ start_subfile (fakename, (char*)0);
+ free (current_subfile->name);
+ }
+ current_subfile->name = strdup (inclTable[ii].name);
+#endif
+
+ if (lv == lineTb)
+ {
+ current_subfile->line_vector =
+ (struct linetable *) xrealloc
+ (lv, (sizeof (struct linetable)
+ + lv->nitems * sizeof (struct linetable_entry)));
+
+ }
+ else
+ {
+ free (lv);
+ current_subfile->line_vector = lineTb;
+ }
+
+ current_subfile->line_vector_length =
+ current_subfile->line_vector->nitems;
+ start_subfile (pop_subfile (), (char*)0);
+ }
+ }
+
+ return_after_cleanup:
+
+ /* We don't want to keep alloc/free'ing the global include file table. */
+ inclIndx = 0;
+
+ /* Start with a fresh subfile structure for the next file. */
+ memset (&main_subfile, '\0', sizeof (struct subfile));
+}
+
+void
+aix_process_linenos ()
+{
+ /* process line numbers and enter them into line vector */
+ process_linenos (last_source_start_addr, cur_src_end_addr);
+}
+
+
+/* Enter a given range of lines into the line vector.
+ can be called in the following two ways:
+ enter_line_range (subfile, beginoffset, endoffset, startaddr, 0, firstLine) or
+ enter_line_range (subfile, beginoffset, 0, startaddr, endaddr, firstLine)
+
+ endoffset points to the last line table entry that we should pay
+ attention to. */
+
+static void
+enter_line_range (subfile, beginoffset, endoffset, startaddr, endaddr,
+ firstLine)
+ struct subfile *subfile;
+ unsigned beginoffset, endoffset; /* offsets to line table */
+ CORE_ADDR startaddr, endaddr;
+ unsigned *firstLine;
+{
+ unsigned int curoffset;
+ CORE_ADDR addr;
+ struct external_lineno ext_lnno;
+ struct internal_lineno int_lnno;
+ unsigned int limit_offset;
+ bfd *abfd;
+
+ if (endoffset == 0 && startaddr == 0 && endaddr == 0)
+ return;
+ curoffset = beginoffset;
+ limit_offset =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->max_lineno_offset;
+
+ if (endoffset != 0)
+ {
+ if (endoffset >= limit_offset)
+ {
+ static struct complaint msg =
+ {"Bad line table offset in C_EINCL directive", 0, 0};
+ complain (&msg);
+ return;
+ }
+ limit_offset = endoffset;
+ }
+ else
+ limit_offset -= 1;
+ abfd = this_symtab_psymtab->objfile->obfd;
+
+ while (curoffset <= limit_offset)
+ {
+ bfd_seek (abfd, curoffset, SEEK_SET);
+ bfd_read (&ext_lnno, sizeof (struct external_lineno), 1, abfd);
+ bfd_coff_swap_lineno_in (abfd, &ext_lnno, &int_lnno);
+
+ /* Find the address this line represents. */
+ addr = (int_lnno.l_lnno
+ ? int_lnno.l_addr.l_paddr
+ : read_symbol_nvalue (int_lnno.l_addr.l_symndx));
+ addr += ANOFFSET (this_symtab_psymtab->objfile->section_offsets,
+ SECT_OFF_TEXT);
+
+ if (addr < startaddr || (endaddr && addr >= endaddr))
+ return;
+
+ if (int_lnno.l_lnno == 0)
+ {
+ *firstLine = read_symbol_lineno (int_lnno.l_addr.l_symndx);
+ record_line (subfile, 0, addr);
+ --(*firstLine);
+ }
+ else
+ record_line (subfile, *firstLine + int_lnno.l_lnno, addr);
+ curoffset += LINESZ;
+ }
+}
+
+
+/* Save the vital information for use when closing off the current file.
+ NAME is the file name the symbols came from, START_ADDR is the first
+ text address for the file, and SIZE is the number of bytes of text. */
+
+#define complete_symtab(name, start_addr) { \
+ last_source_file = savestring (name, strlen (name)); \
+ last_source_start_addr = start_addr; \
+}
+
+
+/* Refill the symbol table input buffer
+ and set the variables that control fetching entries from it.
+ Reports an error if no data available.
+ This function can read past the end of the symbol table
+ (into the string table) but this does no harm. */
+
+/* Reading symbol table has to be fast! Keep the followings as macros, rather
+ than functions. */
+
+#define RECORD_MINIMAL_SYMBOL(NAME, ADDR, TYPE, SECTION, OBJFILE) \
+{ \
+ char *namestr; \
+ namestr = (NAME); \
+ if (namestr[0] == '.') ++namestr; \
+ prim_record_minimal_symbol_and_info (namestr, (ADDR), (TYPE), \
+ (char *)NULL, (SECTION), (OBJFILE)); \
+ misc_func_recorded = 1; \
+}
+
+
+/* xcoff has static blocks marked in `.bs', `.es' pairs. They cannot be
+ nested. At any given time, a symbol can only be in one static block.
+ This is the base address of current static block, zero if non exists. */
+
+static int static_block_base = 0;
+
+/* Section number for the current static block. */
+
+static int static_block_section = -1;
+
+/* true if space for symbol name has been allocated. */
+
+static int symname_alloced = 0;
+
+/* Next symbol to read. Pointer into raw seething symbol table. */
+
+static char *raw_symbol;
+
+/* This is the function which stabsread.c calls to get symbol
+ continuations. */
+static char *
+xcoff_next_symbol_text (objfile)
+ struct objfile *objfile;
+{
+ struct internal_syment symbol;
+ static struct complaint msg =
+ {"Unexpected symbol continuation", 0, 0};
+ char *retval;
+ /* FIXME: is this the same as the passed arg? */
+ objfile = this_symtab_psymtab->objfile;
+
+ bfd_coff_swap_sym_in (objfile->obfd, raw_symbol, &symbol);
+ if (symbol.n_zeroes)
+ {
+ complain (&msg);
+
+ /* Return something which points to '\0' and hope the symbol reading
+ code does something reasonable. */
+ retval = "";
+ }
+ else if (symbol.n_sclass & 0x80)
+ {
+ retval =
+ ((struct coff_symfile_info *)objfile->sym_private)->debugsec
+ + symbol.n_offset;
+ raw_symbol +=
+ coff_data (objfile->obfd)->local_symesz;
+ ++symnum;
+ }
+ else
+ {
+ complain (&msg);
+
+ /* Return something which points to '\0' and hope the symbol reading
+ code does something reasonable. */
+ retval = "";
+ }
+ return retval;
+}
+
+/* Read symbols for a given partial symbol table. */
+
+static void
+read_xcoff_symtab (pst)
+ struct partial_symtab *pst;
+{
+ struct objfile *objfile = pst->objfile;
+ bfd *abfd = objfile->obfd;
+ char *raw_auxptr; /* Pointer to first raw aux entry for sym */
+ char *strtbl = ((struct coff_symfile_info *)objfile->sym_private)->strtbl;
+ char *debugsec =
+ ((struct coff_symfile_info *)objfile->sym_private)->debugsec;
+
+ struct internal_syment symbol[1];
+ union internal_auxent main_aux;
+ struct coff_symbol cs[1];
+ CORE_ADDR file_start_addr = 0;
+ CORE_ADDR file_end_addr = 0;
+
+ int next_file_symnum = -1;
+ unsigned int max_symnum;
+ int just_started = 1;
+ int depth = 0;
+ int fcn_start_addr = 0;
+
+ struct coff_symbol fcn_stab_saved;
+
+ /* fcn_cs_saved is global because process_xcoff_symbol needs it. */
+ union internal_auxent fcn_aux_saved;
+ struct context_stack *new;
+
+ char *filestring = " _start_ "; /* Name of the current file. */
+
+ char *last_csect_name; /* last seen csect's name and value */
+ CORE_ADDR last_csect_val;
+ int last_csect_sec;
+
+ this_symtab_psymtab = pst;
+
+ /* Get the appropriate COFF "constants" related to the file we're
+ handling. */
+ local_symesz = coff_data (abfd)->local_symesz;
+
+ last_source_file = NULL;
+ last_csect_name = 0;
+ last_csect_val = 0;
+
+ start_stabs ();
+ start_symtab (filestring, (char *)NULL, file_start_addr);
+ symnum = ((struct symloc *)pst->read_symtab_private)->first_symnum;
+ max_symnum =
+ symnum + ((struct symloc *)pst->read_symtab_private)->numsyms;
+ first_object_file_end = 0;
+
+ raw_symbol =
+ ((struct coff_symfile_info *) objfile->sym_private)->symtbl
+ + symnum * local_symesz;
+
+ while (symnum < max_symnum)
+ {
+
+ QUIT; /* make this command interruptable. */
+
+ /* READ_ONE_SYMBOL (symbol, cs, symname_alloced); */
+ /* read one symbol into `cs' structure. After processing the
+ whole symbol table, only string table will be kept in memory,
+ symbol table and debug section of xcoff will be freed. Thus
+ we can mark symbols with names in string table as
+ `alloced'. */
+ {
+ int ii;
+
+ /* Swap and align the symbol into a reasonable C structure. */
+ bfd_coff_swap_sym_in (abfd, raw_symbol, symbol);
+
+ cs->c_symnum = symnum;
+ cs->c_naux = symbol->n_numaux;
+ if (symbol->n_zeroes)
+ {
+ symname_alloced = 0;
+ /* We must use the original, unswapped, name here so the name field
+ pointed to by cs->c_name will persist throughout xcoffread. If
+ we use the new field, it gets overwritten for each symbol. */
+ cs->c_name = ((struct external_syment *)raw_symbol)->e.e_name;
+ /* If it's exactly E_SYMNMLEN characters long it isn't
+ '\0'-terminated. */
+ if (cs->c_name[E_SYMNMLEN - 1] != '\0')
+ {
+ char *p;
+ p = obstack_alloc (&objfile->symbol_obstack, E_SYMNMLEN + 1);
+ strncpy (p, cs->c_name, E_SYMNMLEN);
+ p[E_SYMNMLEN] = '\0';
+ cs->c_name = p;
+ symname_alloced = 1;
+ }
+ }
+ else if (symbol->n_sclass & 0x80)
+ {
+ cs->c_name = debugsec + symbol->n_offset;
+ symname_alloced = 0;
+ }
+ else
+ {
+ /* in string table */
+ cs->c_name = strtbl + (int)symbol->n_offset;
+ symname_alloced = 1;
+ }
+ cs->c_value = symbol->n_value;
+ cs->c_sclass = symbol->n_sclass;
+ cs->c_secnum = symbol->n_scnum;
+ cs->c_type = (unsigned)symbol->n_type;
+
+ raw_symbol += coff_data (abfd)->local_symesz;
+ ++symnum;
+
+ /* Save addr of first aux entry. */
+ raw_auxptr = raw_symbol;
+
+ /* Skip all the auxents associated with this symbol. */
+ for (ii = symbol->n_numaux; ii; --ii)
+ {
+ raw_symbol += coff_data (abfd)->local_auxesz;
+ ++symnum;
+ }
+ }
+
+ /* if symbol name starts with ".$" or "$", ignore it. */
+ if (cs->c_name[0] == '$'
+ || (cs->c_name[1] == '$' && cs->c_name[0] == '.'))
+ continue;
+
+ if (cs->c_symnum == next_file_symnum && cs->c_sclass != C_FILE)
+ {
+ if (last_source_file)
+ {
+ pst->symtab =
+ end_symtab (cur_src_end_addr, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ }
+
+ start_stabs ();
+ start_symtab ("_globals_", (char *)NULL, (CORE_ADDR)0);
+ cur_src_end_addr = first_object_file_end;
+ /* done with all files, everything from here on is globals */
+ }
+
+ /* if explicitly specified as a function, treat is as one. */
+ if (ISFCN(cs->c_type) && cs->c_sclass != C_TPDEF)
+ {
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+ goto function_entry_point;
+ }
+
+ if ((cs->c_sclass == C_EXT || cs->c_sclass == C_HIDEXT)
+ && cs->c_naux == 1)
+ {
+ /* Dealing with a symbol with a csect entry. */
+
+#define CSECT(PP) ((PP)->x_csect)
+#define CSECT_LEN(PP) (CSECT(PP).x_scnlen.l)
+#define CSECT_ALIGN(PP) (SMTYP_ALIGN(CSECT(PP).x_smtyp))
+#define CSECT_SMTYP(PP) (SMTYP_SMTYP(CSECT(PP).x_smtyp))
+#define CSECT_SCLAS(PP) (CSECT(PP).x_smclas)
+
+ /* Convert the auxent to something we can access. */
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+
+ switch (CSECT_SMTYP (&main_aux))
+ {
+
+ case XTY_ER:
+ /* Ignore all external references. */
+ continue;
+
+ case XTY_SD:
+ /* A section description. */
+ {
+ switch (CSECT_SCLAS (&main_aux))
+ {
+
+ case XMC_PR:
+ {
+
+ /* A program csect is seen. We have to allocate one
+ symbol table for each program csect. Normally gdb
+ prefers one symtab for each source file. In case
+ of AIX, one source file might include more than one
+ [PR] csect, and they don't have to be adjacent in
+ terms of the space they occupy in memory. Thus, one
+ single source file might get fragmented in the
+ memory and gdb's file start and end address
+ approach does not work! GCC (and I think xlc) seem
+ to put all the code in the unnamed program csect. */
+
+ if (last_csect_name)
+ {
+ complete_symtab (filestring, file_start_addr);
+ cur_src_end_addr = file_end_addr;
+ end_symtab (file_end_addr, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+ start_stabs ();
+ /* Give all csects for this source file the same
+ name. */
+ start_symtab (filestring, NULL, (CORE_ADDR)0);
+ }
+
+ /* If this is the very first csect seen,
+ basically `__start'. */
+ if (just_started)
+ {
+ first_object_file_end
+ = cs->c_value + CSECT_LEN (&main_aux);
+ just_started = 0;
+ }
+
+ file_start_addr =
+ cs->c_value + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT);
+ file_end_addr = file_start_addr + CSECT_LEN (&main_aux);
+
+ if (cs->c_name && cs->c_name[0] == '.')
+ {
+ last_csect_name = cs->c_name;
+ last_csect_val = cs->c_value;
+ last_csect_sec = secnum_to_section (cs->c_secnum, objfile);
+ }
+ }
+ continue;
+
+ /* All other symbols are put into the minimal symbol
+ table only. */
+
+ case XMC_RW:
+ continue;
+
+ case XMC_TC0:
+ continue;
+
+ case XMC_TC:
+ continue;
+
+ default:
+ /* Ignore the symbol. */
+ continue;
+ }
+ }
+ break;
+
+ case XTY_LD:
+
+ switch (CSECT_SCLAS (&main_aux))
+ {
+ case XMC_PR:
+ /* a function entry point. */
+ function_entry_point:
+
+ fcn_start_addr = cs->c_value;
+
+ /* save the function header info, which will be used
+ when `.bf' is seen. */
+ fcn_cs_saved = *cs;
+ fcn_aux_saved = main_aux;
+ continue;
+
+ case XMC_GL:
+ /* shared library function trampoline code entry point. */
+ continue;
+
+ case XMC_DS:
+ /* The symbols often have the same names as debug symbols for
+ functions, and confuse lookup_symbol. */
+ continue;
+
+ default:
+ /* xlc puts each variable in a separate csect, so we get
+ an XTY_SD for each variable. But gcc puts several
+ variables in a csect, so that each variable only gets
+ an XTY_LD. This will typically be XMC_RW; I suspect
+ XMC_RO and XMC_BS might be possible too.
+ These variables are put in the minimal symbol table
+ only. */
+ continue;
+ }
+ break;
+
+ case XTY_CM:
+ /* Common symbols are put into the minimal symbol table only. */
+ continue;
+
+ default:
+ break;
+ }
+ }
+
+ switch (cs->c_sclass)
+ {
+
+ case C_FILE:
+
+ /* c_value field contains symnum of next .file entry in table
+ or symnum of first global after last .file. */
+
+ next_file_symnum = cs->c_value;
+
+ /* Complete symbol table for last object file containing
+ debugging information. */
+
+ /* Whether or not there was a csect in the previous file, we
+ have to call `end_stabs' and `start_stabs' to reset
+ type_vector, line_vector, etc. structures. */
+
+ complete_symtab (filestring, file_start_addr);
+ cur_src_end_addr = file_end_addr;
+ end_symtab (file_end_addr, objfile, SECT_OFF_TEXT);
+ end_stabs ();
+
+ /* XCOFF, according to the AIX 3.2 documentation, puts the filename
+ in cs->c_name. But xlc 1.3.0.2 has decided to do things the
+ standard COFF way and put it in the auxent. We use the auxent if
+ the symbol is ".file" and an auxent exists, otherwise use the symbol
+ itself. Simple enough. */
+ if (!strcmp (cs->c_name, ".file") && cs->c_naux > 0)
+ {
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+ filestring = coff_getfilename (&main_aux, objfile);
+ }
+ else
+ filestring = cs->c_name;
+
+ start_stabs ();
+ start_symtab (filestring, (char *)NULL, (CORE_ADDR)0);
+ last_csect_name = 0;
+
+ /* reset file start and end addresses. A compilation unit with no text
+ (only data) should have zero file boundaries. */
+ file_start_addr = file_end_addr = 0;
+ break;
+
+ case C_FUN:
+ fcn_stab_saved = *cs;
+ break;
+
+ case C_FCN:
+ if (STREQ (cs->c_name, ".bf"))
+ {
+ CORE_ADDR off = ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT);
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+
+ within_function = 1;
+
+ new = push_context (0, fcn_start_addr + off);
+
+ new->name = define_symbol
+ (fcn_cs_saved.c_value + off,
+ fcn_stab_saved.c_name, 0, 0, objfile);
+ if (new->name != NULL)
+ SYMBOL_SECTION (new->name) = SECT_OFF_TEXT;
+ }
+ else if (STREQ (cs->c_name, ".ef"))
+ {
+
+ bfd_coff_swap_aux_in (abfd, raw_auxptr, cs->c_type, cs->c_sclass,
+ 0, cs->c_naux, &main_aux);
+
+ /* The value of .ef is the address of epilogue code;
+ not useful for gdb. */
+ /* { main_aux.x_sym.x_misc.x_lnsz.x_lnno
+ contains number of lines to '}' */
+
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&ef_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
+ new = pop_context ();
+ /* Stack must be empty now. */
+ if (context_stack_depth > 0 || new == NULL)
+ {
+ complain (&ef_complaint, cs->c_symnum);
+ within_function = 0;
+ break;
+ }
+
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr,
+ (fcn_cs_saved.c_value
+ + fcn_aux_saved.x_sym.x_misc.x_fsize
+ + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT)),
+ objfile);
+ within_function = 0;
+ }
+ break;
+
+ case C_BSTAT:
+ /* Begin static block. */
+ {
+ struct internal_syment symbol;
+
+ read_symbol (&symbol, cs->c_value);
+ static_block_base = symbol.n_value;
+ static_block_section =
+ secnum_to_section (symbol.n_scnum, objfile);
+ }
+ break;
+
+ case C_ESTAT:
+ /* End of static block. */
+ static_block_base = 0;
+ static_block_section = -1;
+ break;
+
+ case C_ARG:
+ case C_REGPARM:
+ case C_REG:
+ case C_TPDEF:
+ case C_STRTAG:
+ case C_UNTAG:
+ case C_ENTAG:
+ {
+ static struct complaint msg =
+ {"Unrecognized storage class %d.", 0, 0};
+ complain (&msg, cs->c_sclass);
+ }
+ break;
+
+ case C_LABEL:
+ case C_NULL:
+ /* Ignore these. */
+ break;
+
+ case C_HIDEXT:
+ case C_STAT:
+ break;
+
+ case C_BINCL:
+ /* beginning of include file */
+ /* In xlc output, C_BINCL/C_EINCL pair doesn't show up in sorted
+ order. Thus, when wee see them, we might not know enough info
+ to process them. Thus, we'll be saving them into a table
+ (inclTable) and postpone their processing. */
+
+ record_include_begin (cs);
+ break;
+
+ case C_EINCL:
+ /* End of include file. */
+ /* See the comment after case C_BINCL. */
+ record_include_end (cs);
+ break;
+
+ case C_BLOCK:
+ if (STREQ (cs->c_name, ".bb"))
+ {
+ depth++;
+ new = push_context (depth,
+ (cs->c_value
+ + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT)));
+ }
+ else if (STREQ (cs->c_name, ".eb"))
+ {
+ if (context_stack_depth <= 0)
+ { /* We attempted to pop an empty context stack */
+ complain (&eb_complaint, cs->c_symnum);
+ break;
+ }
+ new = pop_context ();
+ if (depth-- != new->depth)
+ {
+ complain (&eb_complaint, cs->c_symnum);
+ break;
+ }
+ if (local_symbols && context_stack_depth > 0)
+ {
+ /* Make a block for the local symbols within. */
+ finish_block (new->name, &local_symbols, new->old_blocks,
+ new->start_addr,
+ (cs->c_value
+ + ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT)),
+ objfile);
+ }
+ local_symbols = new->locals;
+ }
+ break;
+
+ default:
+ process_xcoff_symbol (cs, objfile);
+ break;
+ }
+ }
+
+ if (last_source_file)
+ {
+ struct symtab *s;
+
+ complete_symtab (filestring, file_start_addr);
+ cur_src_end_addr = file_end_addr;
+ s = end_symtab (file_end_addr, objfile, SECT_OFF_TEXT);
+ /* When reading symbols for the last C_FILE of the objfile, try
+ to make sure that we set pst->symtab to the symtab for the
+ file, not to the _globals_ symtab. I'm not sure whether this
+ actually works right or when/if it comes up. */
+ if (pst->symtab == NULL)
+ pst->symtab = s;
+ end_stabs ();
+ }
+}
+
+#define SYMBOL_DUP(SYMBOL1, SYMBOL2) \
+ (SYMBOL2) = (struct symbol *) \
+ obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); \
+ *(SYMBOL2) = *(SYMBOL1);
+
+
+#define SYMNAME_ALLOC(NAME, ALLOCED) \
+ (ALLOCED) ? (NAME) : obstack_copy0 (&objfile->symbol_obstack, (NAME), strlen (NAME));
+
+
+static struct type *func_symbol_type;
+static struct type *var_symbol_type;
+
+/* process one xcoff symbol. */
+
+static struct symbol *
+process_xcoff_symbol (cs, objfile)
+ register struct coff_symbol *cs;
+ struct objfile *objfile;
+{
+ struct symbol onesymbol;
+ register struct symbol *sym = &onesymbol;
+ struct symbol *sym2 = NULL;
+ char *name, *pp;
+
+ int sec;
+ CORE_ADDR off;
+
+ if (cs->c_secnum < 0)
+ {
+ /* The value is a register number, offset within a frame, etc.,
+ and does not get relocated. */
+ off = 0;
+ sec = -1;
+ }
+ else
+ {
+ sec = secnum_to_section (cs->c_secnum, objfile);
+ off = ANOFFSET (objfile->section_offsets, sec);
+ }
+
+ name = cs->c_name;
+ if (name[0] == '.')
+ ++name;
+
+ memset (sym, '\0', sizeof (struct symbol));
+
+ /* default assumptions */
+ SYMBOL_VALUE (sym) = cs->c_value + off;
+ SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_SECTION (sym) = secnum_to_section (cs->c_secnum, objfile);
+
+ if (ISFCN (cs->c_type))
+ {
+ /* At this point, we don't know the type of the function. This
+ will be patched with the type from its stab entry later on in
+ patch_block_stabs (), unless the file was compiled without -g. */
+
+ SYMBOL_NAME (sym) = SYMNAME_ALLOC (name, symname_alloced);
+ SYMBOL_TYPE (sym) = func_symbol_type;
+
+ SYMBOL_CLASS (sym) = LOC_BLOCK;
+ SYMBOL_DUP (sym, sym2);
+
+ if (cs->c_sclass == C_EXT)
+ add_symbol_to_list (sym2, &global_symbols);
+ else if (cs->c_sclass == C_HIDEXT || cs->c_sclass == C_STAT)
+ add_symbol_to_list (sym2, &file_symbols);
+ }
+ else
+ {
+ /* In case we can't figure out the type, provide default. */
+ SYMBOL_TYPE (sym) = var_symbol_type;
+
+ switch (cs->c_sclass)
+ {
+#if 0
+ /* The values of functions and global symbols are now resolved
+ via the global_sym_chain in stabsread.c. */
+ case C_FUN:
+ if (fcn_cs_saved.c_sclass == C_EXT)
+ add_stab_to_list (name, &global_stabs);
+ else
+ add_stab_to_list (name, &file_stabs);
+ break;
+
+ case C_GSYM:
+ add_stab_to_list (name, &global_stabs);
+ break;
+#endif
+
+ case C_BCOMM:
+ common_block_start (cs->c_name, objfile);
+ break;
+
+ case C_ECOMM:
+ common_block_end (objfile);
+ break;
+
+ default:
+ complain (&storclass_complaint, cs->c_sclass);
+ /* FALLTHROUGH */
+
+ case C_DECL:
+ case C_PSYM:
+ case C_RPSYM:
+ case C_ECOML:
+ case C_LSYM:
+ case C_RSYM:
+ case C_GSYM:
+
+ {
+ sym = define_symbol (cs->c_value + off, cs->c_name, 0, 0, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_SECTION (sym) = sec;
+ }
+ return sym;
+ }
+
+ case C_STSYM:
+
+ /* For xlc (not GCC), the 'V' symbol descriptor is used for
+ all statics and we need to distinguish file-scope versus
+ function-scope using within_function. We do this by
+ changing the string we pass to define_symbol to use 'S'
+ where we need to, which is not necessarily super-clean,
+ but seems workable enough. */
+
+ if (*name == ':' || (pp = (char *) strchr(name, ':')) == NULL)
+ return NULL;
+
+ ++pp;
+ if (*pp == 'V' && !within_function)
+ *pp = 'S';
+ sym = define_symbol ((cs->c_value
+ + ANOFFSET (objfile->section_offsets,
+ static_block_section)),
+ cs->c_name, 0, 0, objfile);
+ if (sym != NULL)
+ {
+ SYMBOL_VALUE (sym) += static_block_base;
+ SYMBOL_SECTION (sym) = static_block_section;
+ }
+ return sym;
+
+ }
+ }
+ return sym2;
+}
+
+/* Extract the file name from the aux entry of a C_FILE symbol. Return
+ only the last component of the name. Result is in static storage and
+ is only good for temporary use. */
+
+static char *
+coff_getfilename (aux_entry, objfile)
+ union internal_auxent *aux_entry;
+ struct objfile *objfile;
+{
+ static char buffer[BUFSIZ];
+ register char *temp;
+ char *result;
+
+ if (aux_entry->x_file.x_n.x_zeroes == 0)
+ strcpy (buffer,
+ ((struct coff_symfile_info *)objfile->sym_private)->strtbl
+ + aux_entry->x_file.x_n.x_offset);
+ else
+ {
+ strncpy (buffer, aux_entry->x_file.x_fname, FILNMLEN);
+ buffer[FILNMLEN] = '\0';
+ }
+ result = buffer;
+
+ /* FIXME: We should not be throwing away the information about what
+ directory. It should go into dirname of the symtab, or some such
+ place. */
+ if ((temp = strrchr (result, '/')) != NULL)
+ result = temp + 1;
+ return (result);
+}
+
+/* Set *SYMBOL to symbol number symno in symtbl. */
+static void
+read_symbol (symbol, symno)
+ struct internal_syment *symbol;
+ int symno;
+{
+ int nsyms =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl_num_syms;
+ char *stbl =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl;
+ if (symno < 0 || symno >= nsyms)
+ {
+ static struct complaint msg =
+ {"Invalid symbol offset", 0, 0};
+ complain (&msg);
+ symbol->n_value = 0;
+ symbol->n_scnum = -1;
+ return;
+ }
+ bfd_coff_swap_sym_in (this_symtab_psymtab->objfile->obfd,
+ stbl + (symno*local_symesz),
+ symbol);
+}
+
+/* Get value corresponding to symbol number symno in symtbl. */
+
+static int
+read_symbol_nvalue (symno)
+ int symno;
+{
+ struct internal_syment symbol[1];
+
+ read_symbol (symbol, symno);
+ return symbol->n_value;
+}
+
+
+/* Find the address of the function corresponding to symno, where
+ symno is the symbol pointed to by the linetable. */
+
+static int
+read_symbol_lineno (symno)
+ int symno;
+{
+ int nsyms =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl_num_syms;
+ char *stbl =
+ ((struct coff_symfile_info *)this_symtab_psymtab->objfile->sym_private)
+ ->symtbl;
+ struct internal_syment symbol[1];
+ union internal_auxent main_aux[1];
+
+ if (symno < 0)
+ {
+ complain (&bf_notfound_complaint);
+ return 0;
+ }
+
+ /* Note that just searching for a short distance (e.g. 50 symbols)
+ is not enough, at least in the following case.
+
+ .extern foo
+ [many .stabx entries]
+ [a few functions, referring to foo]
+ .globl foo
+ .bf
+
+ What happens here is that the assembler moves the .stabx entries
+ to right before the ".bf" for foo, but the symbol for "foo" is before
+ all the stabx entries. See PR gdb/2222. */
+
+ /* Maintaining a table of .bf entries might be preferable to this search.
+ If I understand things correctly it would need to be done only for
+ the duration of a single psymtab to symtab conversion. */
+ while (symno < nsyms)
+ {
+ bfd_coff_swap_sym_in (symfile_bfd,
+ stbl + (symno * local_symesz), symbol);
+ if (symbol->n_sclass == C_FCN && STREQ (symbol->n_name, ".bf"))
+ goto gotit;
+ symno += symbol->n_numaux + 1;
+ }
+
+ complain (&bf_notfound_complaint);
+ return 0;
+
+gotit:
+ /* take aux entry and return its lineno */
+ symno++;
+ bfd_coff_swap_aux_in (this_symtab_psymtab->objfile->obfd,
+ stbl + symno * local_symesz,
+ symbol->n_type, symbol->n_sclass,
+ 0, symbol->n_numaux, main_aux);
+
+ return main_aux->x_sym.x_misc.x_lnsz.x_lnno;
+}
+
+/* Support for line number handling */
+
+/* This function is called for every section; it finds the outer limits
+ * of the line table (minimum and maximum file offset) so that the
+ * mainline code can read the whole thing for efficiency.
+ */
+static void
+find_linenos (abfd, asect, vpinfo)
+ bfd *abfd;
+ sec_ptr asect;
+ PTR vpinfo;
+{
+ struct coff_symfile_info *info;
+ int size, count;
+ file_ptr offset, maxoff;
+
+ count = asect->lineno_count;
+
+ if (!STREQ (asect->name, ".text") || count == 0)
+ return;
+
+ size = count * coff_data (abfd)->local_linesz;
+ info = (struct coff_symfile_info *)vpinfo;
+ offset = asect->line_filepos;
+ maxoff = offset + size;
+
+ if (offset < info->min_lineno_offset || info->min_lineno_offset == 0)
+ info->min_lineno_offset = offset;
+
+ if (maxoff > info->max_lineno_offset)
+ info->max_lineno_offset = maxoff;
+}
+
+static void xcoff_psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+
+static void
+xcoff_psymtab_to_symtab_1 (pst)
+ struct partial_symtab *pst;
+{
+ struct cleanup *old_chain;
+ int i;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered
+ (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ /* Read in all partial symtabs on which this one is dependent */
+ for (i = 0; i < pst->number_of_dependencies; i++)
+ if (!pst->dependencies[i]->readin)
+ {
+ /* Inform about additional files that need to be read in. */
+ if (info_verbose)
+ {
+ fputs_filtered (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ xcoff_psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ if (((struct symloc *)pst->read_symtab_private)->numsyms != 0)
+ {
+ /* Init stuff necessary for reading in symbols. */
+ stabsread_init ();
+ buildsym_init ();
+ old_chain = make_cleanup (really_free_pendings, 0);
+
+ read_xcoff_symtab (pst);
+ sort_symtab_syms (pst->symtab);
+
+ do_cleanups (old_chain);
+ }
+
+ pst->readin = 1;
+}
+
+static void xcoff_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+
+/* Read in all of the symbols for a given psymtab for real.
+ Be verbose about it if the user wants that. */
+
+static void
+xcoff_psymtab_to_symtab (pst)
+ struct partial_symtab *pst;
+{
+ bfd *sym_bfd;
+
+ if (!pst)
+ return;
+
+ if (pst->readin)
+ {
+ fprintf_unfiltered
+ (gdb_stderr, "Psymtab for %s already read in. Shouldn't happen.\n",
+ pst->filename);
+ return;
+ }
+
+ if (((struct symloc *)pst->read_symtab_private)->numsyms != 0
+ || pst->number_of_dependencies)
+ {
+ /* Print the message now, before reading the string table,
+ to avoid disconcerting pauses. */
+ if (info_verbose)
+ {
+ printf_filtered ("Reading in symbols for %s...", pst->filename);
+ gdb_flush (gdb_stdout);
+ }
+
+ sym_bfd = pst->objfile->obfd;
+
+ next_symbol_text_func = xcoff_next_symbol_text;
+
+ xcoff_psymtab_to_symtab_1 (pst);
+
+ /* 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);
+
+ /* Finish up the debug error message. */
+ if (info_verbose)
+ printf_filtered ("done.\n");
+ }
+}
+
+static void
+xcoff_new_init (objfile)
+ struct objfile *objfile;
+{
+ stabsread_new_init ();
+ buildsym_new_init ();
+}
+
+/* Do initialization in preparation for reading symbols from OBJFILE.
+
+ We will only be called if this is an XCOFF or XCOFF-like file.
+ BFD handles figuring out the format of the file, and code in symfile.c
+ uses BFD's determination to vector to us. */
+
+static void
+xcoff_symfile_init (objfile)
+ struct objfile *objfile;
+{
+ /* Allocate struct to keep track of the symfile */
+ objfile -> sym_private = xmmalloc (objfile -> md,
+ sizeof (struct coff_symfile_info));
+
+ /* XCOFF objects may be reordered, so set OBJF_REORDERED. If we
+ find this causes a significant slowdown in gdb then we could
+ set it in the debug symbol readers only when necessary. */
+ objfile->flags |= OBJF_REORDERED;
+
+ init_entry_point_info (objfile);
+}
+
+/* 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. */
+
+static void
+xcoff_symfile_finish (objfile)
+ struct objfile *objfile;
+{
+ if (objfile -> sym_private != NULL)
+ {
+ mfree (objfile -> md, objfile -> sym_private);
+ }
+
+ /* Start with a fresh include table for the next objfile. */
+ if (inclTable)
+ {
+ free (inclTable);
+ inclTable = NULL;
+ }
+ inclIndx = inclLength = inclDepth = 0;
+}
+
+
+static void
+init_stringtab (abfd, offset, objfile)
+ bfd *abfd;
+ file_ptr offset;
+ struct objfile *objfile;
+{
+ long length;
+ int val;
+ unsigned char lengthbuf[4];
+ char *strtbl;
+
+ ((struct coff_symfile_info *)objfile->sym_private)->strtbl = NULL;
+
+ if (bfd_seek (abfd, offset, SEEK_SET) < 0)
+ error ("cannot seek to string table in %s: %s",
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+
+ val = bfd_read ((char *)lengthbuf, 1, sizeof lengthbuf, abfd);
+ length = bfd_h_get_32 (abfd, lengthbuf);
+
+ /* If no string table is needed, then the file may end immediately
+ after the symbols. Just return with `strtbl' set to NULL. */
+
+ if (val != sizeof lengthbuf || length < sizeof lengthbuf)
+ return;
+
+ /* Allocate string table from symbol_obstack. We will need this table
+ as long as we have its symbol table around. */
+
+ strtbl = (char *) obstack_alloc (&objfile->symbol_obstack, length);
+ ((struct coff_symfile_info *)objfile->sym_private)->strtbl = strtbl;
+
+ /* Copy length buffer, the first byte is usually zero and is
+ used for stabs with a name length of zero. */
+ memcpy (strtbl, lengthbuf, sizeof lengthbuf);
+ if (length == sizeof lengthbuf)
+ return;
+
+ val = bfd_read (strtbl + sizeof lengthbuf, 1, length - sizeof lengthbuf,
+ abfd);
+
+ if (val != length - sizeof lengthbuf)
+ error ("cannot read string table from %s: %s",
+ bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ()));
+ if (strtbl[length - 1] != '\0')
+ error ("bad symbol file: string table does not end with null character");
+
+ return;
+}
+
+/* If we have not yet seen a function for this psymtab, this is 0. If we
+ have seen one, it is the offset in the line numbers of the line numbers
+ for the psymtab. */
+static unsigned int first_fun_line_offset;
+
+static struct partial_symtab *xcoff_start_psymtab
+ PARAMS ((struct objfile *, struct section_offsets *, char *, int,
+ struct partial_symbol **, struct partial_symbol **));
+
+/* Allocate and partially fill a partial symtab. It will be
+ completely filled at the end of the symbol list.
+
+ SYMFILE_NAME is the name of the symbol-file we are reading from, and ADDR
+ is the address relative to which its symbols are (incremental) or 0
+ (normal). */
+
+static struct partial_symtab *
+xcoff_start_psymtab (objfile, section_offsets,
+ filename, first_symnum, global_syms, static_syms)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ char *filename;
+ int first_symnum;
+ struct partial_symbol **global_syms;
+ struct partial_symbol **static_syms;
+{
+ struct partial_symtab *result =
+ start_psymtab_common (objfile, section_offsets,
+ filename,
+ /* We fill in textlow later. */
+ 0,
+ global_syms, static_syms);
+
+ result->read_symtab_private = (char *)
+ obstack_alloc (&objfile -> psymbol_obstack, sizeof (struct symloc));
+ ((struct symloc *)result->read_symtab_private)->first_symnum = first_symnum;
+ result->read_symtab = xcoff_psymtab_to_symtab;
+
+ /* Deduce the source language from the filename for this psymtab. */
+ psymtab_language = deduce_language_from_filename (filename);
+
+ return result;
+}
+
+static struct partial_symtab *xcoff_end_psymtab
+ PARAMS ((struct partial_symtab *, char **, int, int,
+ struct partial_symtab **, int));
+
+/* Close off the current usage of PST.
+ Returns PST, or NULL if the partial symtab was empty and thrown away.
+
+ CAPPING_SYMBOL_NUMBER is the end of pst (exclusive).
+
+ INCLUDE_LIST, NUM_INCLUDES, DEPENDENCY_LIST, and NUMBER_DEPENDENCIES
+ are the information for includes and dependencies. */
+
+static struct partial_symtab *
+xcoff_end_psymtab (pst, include_list, num_includes, capping_symbol_number,
+ dependency_list, number_dependencies)
+ struct partial_symtab *pst;
+ char **include_list;
+ int num_includes;
+ int capping_symbol_number;
+ struct partial_symtab **dependency_list;
+ int number_dependencies;
+{
+ int i;
+ struct objfile *objfile = pst -> objfile;
+
+ if (capping_symbol_number != -1)
+ ((struct symloc *)pst->read_symtab_private)->numsyms =
+ capping_symbol_number
+ - ((struct symloc *)pst->read_symtab_private)->first_symnum;
+ ((struct symloc *)pst->read_symtab_private)->lineno_off =
+ first_fun_line_offset;
+ first_fun_line_offset = 0;
+ pst->n_global_syms =
+ objfile->global_psymbols.next - (objfile->global_psymbols.list + pst->globals_offset);
+ pst->n_static_syms =
+ objfile->static_psymbols.next - (objfile->static_psymbols.list + pst->statics_offset);
+
+ pst->number_of_dependencies = number_dependencies;
+ if (number_dependencies)
+ {
+ pst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ number_dependencies * sizeof (struct partial_symtab *));
+ memcpy (pst->dependencies, dependency_list,
+ number_dependencies * sizeof (struct partial_symtab *));
+ }
+ else
+ pst->dependencies = 0;
+
+ for (i = 0; i < num_includes; i++)
+ {
+ struct partial_symtab *subpst =
+ allocate_psymtab (include_list[i], objfile);
+
+ subpst->section_offsets = pst->section_offsets;
+ subpst->read_symtab_private =
+ (char *) obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct symloc));
+ ((struct symloc *)subpst->read_symtab_private)->first_symnum = 0;
+ ((struct symloc *)subpst->read_symtab_private)->numsyms = 0;
+ subpst->textlow = 0;
+ subpst->texthigh = 0;
+
+ /* We could save slight bits of space by only making one of these,
+ shared by the entire set of include files. FIXME-someday. */
+ subpst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->psymbol_obstack,
+ sizeof (struct partial_symtab *));
+ subpst->dependencies[0] = pst;
+ subpst->number_of_dependencies = 1;
+
+ subpst->globals_offset =
+ subpst->n_global_syms =
+ subpst->statics_offset =
+ subpst->n_static_syms = 0;
+
+ subpst->readin = 0;
+ subpst->symtab = 0;
+ subpst->read_symtab = pst->read_symtab;
+ }
+
+ sort_pst_symbols (pst);
+
+ /* If there is already a psymtab or symtab for a file of this name,
+ remove it. (If there is a symtab, more drastic things also
+ happen.) This happens in VxWorks. */
+ 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. */
+ /* Empty psymtabs happen as a result of header files which don't have
+ any symbols in them. There can be a lot of them. */
+ struct partial_symtab *prev_pst;
+
+ /* 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;
+
+ /* Next, put it on a free list for recycling */
+
+ pst->next = pst->objfile->free_psymtabs;
+ pst->objfile->free_psymtabs = pst;
+
+ /* Indicate that psymtab was thrown away. */
+ pst = (struct partial_symtab *)NULL;
+ }
+ return pst;
+}
+
+static void swap_sym PARAMS ((struct internal_syment *,
+ union internal_auxent *, char **, char **,
+ unsigned int *,
+ struct objfile *));
+
+/* Swap raw symbol at *RAW and put the name in *NAME, the symbol in
+ *SYMBOL, the first auxent in *AUX. Advance *RAW and *SYMNUMP over
+ the symbol and its auxents. */
+
+static void
+swap_sym (symbol, aux, name, raw, symnump, objfile)
+ struct internal_syment *symbol;
+ union internal_auxent *aux;
+ char **name;
+ char **raw;
+ unsigned int *symnump;
+ struct objfile *objfile;
+{
+ bfd_coff_swap_sym_in (objfile->obfd, *raw, symbol);
+ if (symbol->n_zeroes)
+ {
+ /* If it's exactly E_SYMNMLEN characters long it isn't
+ '\0'-terminated. */
+ if (symbol->n_name[E_SYMNMLEN - 1] != '\0')
+ {
+ /* FIXME: wastes memory for symbols which we don't end up putting
+ into the minimal symbols. */
+ char *p;
+ p = obstack_alloc (&objfile->psymbol_obstack, E_SYMNMLEN + 1);
+ strncpy (p, symbol->n_name, E_SYMNMLEN);
+ p[E_SYMNMLEN] = '\0';
+ *name = p;
+ }
+ else
+ /* Point to the unswapped name as that persists as long as the
+ objfile does. */
+ *name = ((struct external_syment *)*raw)->e.e_name;
+ }
+ else if (symbol->n_sclass & 0x80)
+ {
+ *name = ((struct coff_symfile_info *)objfile->sym_private)->debugsec
+ + symbol->n_offset;
+ }
+ else
+ {
+ *name = ((struct coff_symfile_info *)objfile->sym_private)->strtbl
+ + symbol->n_offset;
+ }
+ ++*symnump;
+ *raw += coff_data (objfile->obfd)->local_symesz;
+ if (symbol->n_numaux > 0)
+ {
+ bfd_coff_swap_aux_in (objfile->obfd, *raw, symbol->n_type,
+ symbol->n_sclass, 0, symbol->n_numaux, aux);
+
+ *symnump += symbol->n_numaux;
+ *raw += coff_data (objfile->obfd)->local_symesz * symbol->n_numaux;
+ }
+}
+
+static void
+scan_xcoff_symtab (section_offsets, objfile)
+ struct section_offsets *section_offsets;
+ struct objfile *objfile;
+{
+ int toc_offset = 0; /* toc offset value in data section. */
+ char *filestring = NULL;
+
+ char *namestring;
+ int past_first_source_file = 0;
+ bfd *abfd;
+ unsigned int nsyms;
+
+ /* Current partial symtab */
+ struct partial_symtab *pst;
+
+ /* List of current psymtab's include files */
+ char **psymtab_include_list;
+ int includes_allocated;
+ int includes_used;
+
+ /* Index within current psymtab dependency list */
+ struct partial_symtab **dependency_list;
+ int dependencies_used, dependencies_allocated;
+
+ char *sraw_symbol;
+ struct internal_syment symbol;
+ union internal_auxent main_aux;
+ unsigned int ssymnum;
+
+ char *last_csect_name = NULL; /* last seen csect's name and value */
+ CORE_ADDR last_csect_val = 0;
+ int last_csect_sec = 0;
+ int misc_func_recorded = 0; /* true if any misc. function */
+
+ pst = (struct partial_symtab *) 0;
+
+ includes_allocated = 30;
+ includes_used = 0;
+ psymtab_include_list = (char **) alloca (includes_allocated *
+ sizeof (char *));
+
+ dependencies_allocated = 30;
+ dependencies_used = 0;
+ dependency_list =
+ (struct partial_symtab **) alloca (dependencies_allocated *
+ sizeof (struct partial_symtab *));
+
+ last_source_file = NULL;
+
+ abfd = objfile->obfd;
+
+ sraw_symbol = ((struct coff_symfile_info *)objfile->sym_private)->symtbl;
+ nsyms = ((struct coff_symfile_info *)objfile->sym_private)->symtbl_num_syms;
+ ssymnum = 0;
+ while (ssymnum < nsyms)
+ {
+ int sclass = ((struct external_syment *)sraw_symbol)->e_sclass[0] & 0xff;
+ /* This is the type we pass to partial-stab.h. A less kludgy solution
+ would be to break out partial-stab.h into its various parts--shuffle
+ off the DBXREAD_ONLY stuff to dbxread.c, and make separate
+ pstab-norm.h (for most types), pstab-sol.h (for N_SOL), etc. */
+ int stype;
+
+ QUIT;
+
+ switch (sclass)
+ {
+ case C_EXT:
+ case C_HIDEXT:
+ {
+ /* The CSECT auxent--always the last auxent. */
+ union internal_auxent csect_aux;
+ unsigned int symnum_before = ssymnum;
+
+ swap_sym (&symbol, &main_aux, &namestring, &sraw_symbol,
+ &ssymnum, objfile);
+ if (symbol.n_numaux > 1)
+ {
+ bfd_coff_swap_aux_in
+ (objfile->obfd,
+ sraw_symbol - coff_data(abfd)->local_symesz,
+ symbol.n_type,
+ symbol.n_sclass,
+ symbol.n_numaux - 1,
+ symbol.n_numaux,
+ &csect_aux);
+ }
+ else
+ csect_aux = main_aux;
+
+ /* If symbol name starts with ".$" or "$", ignore it. */
+ if (namestring[0] == '$'
+ || (namestring[0] == '.' && namestring[1] == '$'))
+ break;
+
+ switch (csect_aux.x_csect.x_smtyp & 0x7)
+ {
+ case XTY_SD:
+ switch (csect_aux.x_csect.x_smclas)
+ {
+ case XMC_PR:
+ if (last_csect_name)
+ {
+ /* If no misc. function recorded in the last
+ seen csect, enter it as a function. This
+ will take care of functions like strcmp()
+ compiled by xlc. */
+
+ if (!misc_func_recorded)
+ {
+ RECORD_MINIMAL_SYMBOL
+ (last_csect_name, last_csect_val,
+ mst_text, last_csect_sec,
+ objfile);
+ }
+
+ if (pst != NULL)
+ {
+ /* We have to allocate one psymtab for
+ each program csect, because their text
+ sections need not be adjacent. */
+ xcoff_end_psymtab
+ (pst, psymtab_include_list,
+ includes_used,
+ symnum_before,
+ dependency_list, dependencies_used);
+ includes_used = 0;
+ dependencies_used = 0;
+ /* Give all psymtabs for this source file the same
+ name. */
+ pst = xcoff_start_psymtab
+ (objfile, section_offsets,
+ filestring,
+ symnum_before,
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ }
+ }
+ if (namestring && namestring[0] == '.')
+ {
+ last_csect_name = namestring;
+ last_csect_val = symbol.n_value;
+ last_csect_sec =
+ secnum_to_section (symbol.n_scnum, objfile);
+ }
+ if (pst != NULL)
+ {
+ CORE_ADDR highval =
+ symbol.n_value + csect_aux.x_csect.x_scnlen.l;
+ if (highval > pst->texthigh)
+ pst->texthigh = highval;
+ if (pst->textlow == 0 || symbol.n_value < pst->textlow)
+ pst->textlow = symbol.n_value;
+ }
+ misc_func_recorded = 0;
+ break;
+
+ case XMC_RW:
+ /* Data variables are recorded in the minimal symbol
+ table, except for section symbols. */
+ if (*namestring != '.')
+ prim_record_minimal_symbol_and_info
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_data : mst_data,
+ NULL, secnum_to_section (symbol.n_scnum, objfile),
+ objfile);
+ break;
+
+ case XMC_TC0:
+ if (toc_offset)
+ warning ("More than one XMC_TC0 symbol found.");
+ toc_offset = symbol.n_value;
+ break;
+
+ case XMC_TC:
+ /* These symbols tell us where the TOC entry for a
+ variable is, not the variable itself. */
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case XTY_LD:
+ switch (csect_aux.x_csect.x_smclas)
+ {
+ case XMC_PR:
+ /* A function entry point. */
+
+ if (first_fun_line_offset == 0 && symbol.n_numaux > 1)
+ first_fun_line_offset =
+ main_aux.x_sym.x_fcnary.x_fcn.x_lnnoptr;
+ RECORD_MINIMAL_SYMBOL
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_text : mst_text,
+ secnum_to_section (symbol.n_scnum, objfile),
+ objfile);
+ break;
+
+ case XMC_GL:
+ /* shared library function trampoline code entry
+ point. */
+
+ /* record trampoline code entries as
+ mst_solib_trampoline symbol. When we lookup mst
+ symbols, we will choose mst_text over
+ mst_solib_trampoline. */
+ RECORD_MINIMAL_SYMBOL
+ (namestring, symbol.n_value,
+ mst_solib_trampoline,
+ secnum_to_section (symbol.n_scnum, objfile),
+ objfile);
+ break;
+
+ case XMC_DS:
+ /* The symbols often have the same names as
+ debug symbols for functions, and confuse
+ lookup_symbol. */
+ break;
+
+ default:
+
+ /* xlc puts each variable in a separate csect,
+ so we get an XTY_SD for each variable. But
+ gcc puts several variables in a csect, so
+ that each variable only gets an XTY_LD. We
+ still need to record them. This will
+ typically be XMC_RW; I suspect XMC_RO and
+ XMC_BS might be possible too. */
+ if (*namestring != '.')
+ prim_record_minimal_symbol_and_info
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_data : mst_data,
+ NULL, secnum_to_section (symbol.n_scnum, objfile),
+ objfile);
+ break;
+ }
+ break;
+
+ case XTY_CM:
+ switch (csect_aux.x_csect.x_smclas)
+ {
+ case XMC_RW:
+ case XMC_BS:
+ /* Common variables are recorded in the minimal symbol
+ table, except for section symbols. */
+ if (*namestring != '.')
+ prim_record_minimal_symbol_and_info
+ (namestring, symbol.n_value,
+ sclass == C_HIDEXT ? mst_file_bss : mst_bss,
+ NULL, secnum_to_section (symbol.n_scnum, objfile),
+ objfile);
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+ case C_FILE:
+ {
+ unsigned int symnum_before;
+
+ symnum_before = ssymnum;
+ swap_sym (&symbol, &main_aux, &namestring, &sraw_symbol,
+ &ssymnum, objfile);
+
+ /* See if the last csect needs to be recorded. */
+
+ if (last_csect_name && !misc_func_recorded)
+ {
+
+ /* If no misc. function recorded in the last seen csect, enter
+ it as a function. This will take care of functions like
+ strcmp() compiled by xlc. */
+
+ RECORD_MINIMAL_SYMBOL
+ (last_csect_name, last_csect_val,
+ mst_text, last_csect_sec, objfile);
+ }
+
+ if (pst)
+ {
+ xcoff_end_psymtab (pst, psymtab_include_list, includes_used,
+ symnum_before,
+ dependency_list, dependencies_used);
+ includes_used = 0;
+ dependencies_used = 0;
+ }
+ first_fun_line_offset = 0;
+
+ /* XCOFF, according to the AIX 3.2 documentation, puts the
+ filename in cs->c_name. But xlc 1.3.0.2 has decided to
+ do things the standard COFF way and put it in the auxent.
+ We use the auxent if the symbol is ".file" and an auxent
+ exists, otherwise use the symbol itself. */
+ if (!strcmp (namestring, ".file") && symbol.n_numaux > 0)
+ {
+ filestring = coff_getfilename (&main_aux, objfile);
+ }
+ else
+ filestring = namestring;
+
+ pst = xcoff_start_psymtab (objfile, section_offsets,
+ filestring,
+ symnum_before,
+ objfile->global_psymbols.next,
+ objfile->static_psymbols.next);
+ last_csect_name = NULL;
+ }
+ break;
+
+ default:
+ {
+ static struct complaint msg =
+ {"Storage class %d not recognized during scan", 0, 0};
+ complain (&msg, sclass);
+ }
+ /* FALLTHROUGH */
+
+ /* C_FCN is .bf and .ef symbols. I think it is sufficient
+ to handle only the C_FUN and C_EXT. */
+ case C_FCN:
+
+ case C_BSTAT:
+ case C_ESTAT:
+ case C_ARG:
+ case C_REGPARM:
+ case C_REG:
+ case C_TPDEF:
+ case C_STRTAG:
+ case C_UNTAG:
+ case C_ENTAG:
+ case C_LABEL:
+ case C_NULL:
+
+ /* C_EINCL means we are switching back to the main file. But there
+ is no reason to care; the only thing we want to know about
+ includes is the names of all the included (.h) files. */
+ case C_EINCL:
+
+ case C_BLOCK:
+
+ /* I don't think C_STAT is used in xcoff; C_HIDEXT appears to be
+ used instead. */
+ case C_STAT:
+
+ /* I don't think the name of the common block (as opposed to the
+ variables within it) is something which is user visible
+ currently. */
+ case C_BCOMM:
+ case C_ECOMM:
+
+ case C_PSYM:
+ case C_RPSYM:
+
+ /* I think we can ignore C_LSYM; types on xcoff seem to use C_DECL
+ so C_LSYM would appear to be only for locals. */
+ case C_LSYM:
+
+ case C_AUTO:
+ case C_RSYM:
+ {
+ /* We probably could save a few instructions by assuming that
+ C_LSYM, C_PSYM, etc., never have auxents. */
+ int naux1 =
+ ((struct external_syment *)sraw_symbol)->e_numaux[0] + 1;
+ ssymnum += naux1;
+ sraw_symbol += sizeof (struct external_syment) * naux1;
+ }
+ break;
+
+ case C_BINCL:
+ stype = N_SOL;
+ goto pstab;
+
+ case C_FUN:
+ /* The value of the C_FUN is not the address of the function (it
+ appears to be the address before linking), but as long as it
+ is smaller than the actual address, then find_pc_partial_function
+ will use the minimal symbols instead. I hope. */
+
+ case C_GSYM:
+ case C_ECOML:
+ case C_DECL:
+ case C_STSYM:
+ stype = N_LSYM;
+ pstab:;
+ swap_sym (&symbol, &main_aux, &namestring, &sraw_symbol,
+ &ssymnum, objfile);
+#define CUR_SYMBOL_TYPE stype
+#define CUR_SYMBOL_VALUE symbol.n_value
+
+/* START_PSYMTAB and END_PSYMTAB are never used, because they are only
+ called from DBXREAD_ONLY or N_SO code. Likewise for the symnum
+ variable. */
+#define START_PSYMTAB(ofile,secoff,fname,low,symoff,global_syms,static_syms) 0
+#define END_PSYMTAB(pst,ilist,ninc,c_off,c_text,dep_list,n_deps)\
+ do {} while (0)
+/* We have already set the namestring. */
+#define SET_NAMESTRING() /* */
+
+#include "partial-stab.h"
+ }
+ }
+
+ if (pst)
+ {
+ xcoff_end_psymtab (pst, psymtab_include_list, includes_used,
+ ssymnum,
+ dependency_list, dependencies_used);
+ }
+
+ /* Record the toc offset value of this symbol table into ldinfo structure.
+ If no XMC_TC0 is found, toc_offset should be zero. Another place to obtain
+ this information would be file auxiliary header. */
+
+#ifndef FAKING_RS6000
+ xcoff_add_toc_to_loadinfo (toc_offset);
+#endif
+}
+
+/* Scan and build partial symbols for a symbol file.
+ We have been initialized by a call to dbx_symfile_init, which
+ put all the relevant info into a "struct dbx_symfile_info",
+ hung off the objfile structure.
+
+ SECTION_OFFSETS contains offsets relative to which the symbols in the
+ various sections are (depending where the sections were actually loaded).
+ MAINLINE is true if we are reading the main symbol
+ table (as opposed to a shared lib or dynamically loaded file). */
+
+static void
+xcoff_initial_scan (objfile, section_offsets, mainline)
+ struct objfile *objfile;
+ struct section_offsets *section_offsets;
+ int mainline; /* FIXME comments above */
+{
+ bfd *abfd;
+ int val;
+ struct cleanup *back_to;
+ int num_symbols; /* # of symbols */
+ file_ptr symtab_offset; /* symbol table and */
+ file_ptr stringtab_offset; /* string table file offsets */
+ struct coff_symfile_info *info;
+ char *name;
+ unsigned int size;
+
+#ifndef FAKING_RS6000
+ /* Initialize load info structure. */
+ if (mainline)
+ xcoff_init_loadinfo ();
+#endif
+
+ info = (struct coff_symfile_info *) objfile -> sym_private;
+ symfile_bfd = abfd = objfile->obfd;
+ name = objfile->name;
+
+ num_symbols = bfd_get_symcount (abfd); /* # of symbols */
+ symtab_offset = obj_sym_filepos (abfd); /* symbol table file offset */
+ stringtab_offset = symtab_offset +
+ num_symbols * coff_data(abfd)->local_symesz;
+
+ info->min_lineno_offset = 0;
+ info->max_lineno_offset = 0;
+ bfd_map_over_sections (abfd, find_linenos, info);
+
+ if (num_symbols > 0)
+ {
+ /* Read the string table. */
+ init_stringtab (abfd, stringtab_offset, objfile);
+
+ /* Read the .debug section, if present. */
+ {
+ sec_ptr secp;
+ bfd_size_type length;
+ char *debugsec = NULL;
+
+ secp = bfd_get_section_by_name (abfd, ".debug");
+ if (secp)
+ {
+ length = bfd_section_size (abfd, secp);
+ if (length)
+ {
+ debugsec =
+ (char *) obstack_alloc (&objfile->symbol_obstack, length);
+
+ if (!bfd_get_section_contents (abfd, secp, debugsec,
+ (file_ptr) 0, length))
+ {
+ error ("Error reading .debug section of `%s': %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ }
+ }
+ }
+ ((struct coff_symfile_info *)objfile->sym_private)->debugsec =
+ debugsec;
+ }
+ }
+
+ /* Read the symbols. We keep them in core because we will want to
+ access them randomly in read_symbol*. */
+ val = bfd_seek (abfd, symtab_offset, SEEK_SET);
+ if (val < 0)
+ error ("Error reading symbols from %s: %s",
+ name, bfd_errmsg (bfd_get_error ()));
+ size = coff_data (abfd)->local_symesz * num_symbols;
+ ((struct coff_symfile_info *)objfile->sym_private)->symtbl =
+ obstack_alloc (&objfile->symbol_obstack, size);
+ ((struct coff_symfile_info *)objfile->sym_private)->symtbl_num_syms =
+ num_symbols;
+
+ val = bfd_read (((struct coff_symfile_info *)objfile->sym_private)->symtbl,
+ size, 1, abfd);
+ if (val != size)
+ perror_with_name ("reading symbol table");
+
+ /* If we are reinitializing, or if we have never loaded syms yet, init */
+ if (mainline
+ || objfile->global_psymbols.size == 0
+ || objfile->static_psymbols.size == 0)
+ /* I'm not sure how how good num_symbols is; the rule of thumb in
+ init_psymbol_list was developed for a.out. On the one hand,
+ num_symbols includes auxents. On the other hand, it doesn't
+ include N_SLINE. */
+ init_psymbol_list (objfile, num_symbols);
+
+ pending_blocks = 0;
+ back_to = make_cleanup (really_free_pendings, 0);
+
+ init_minimal_symbol_collection ();
+ make_cleanup (discard_minimal_symbols, 0);
+
+ /* Now that the symbol table data of the executable file are all in core,
+ process them and define symbols accordingly. */
+
+ scan_xcoff_symtab (section_offsets, objfile);
+
+ /* Install any minimal symbols that have been collected as the current
+ minimal symbols for this objfile. */
+
+ install_minimal_symbols (objfile);
+
+ do_cleanups (back_to);
+}
+
+static struct section_offsets *
+xcoff_symfile_offsets (objfile, addr)
+ struct objfile *objfile;
+ CORE_ADDR 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) * objfile->num_sections);
+
+ /* syms_from_objfile kindly subtracts from addr the bfd_section_vma
+ of the .text section. This strikes me as wrong--whether the
+ offset to be applied to symbol reading is relative to the start
+ address of the section depends on the symbol format. In any
+ event, this whole "addr" concept is pretty broken (it doesn't
+ handle any section but .text sensibly), so just ignore the addr
+ parameter and use 0. rs6000-nat.c will set the correct section
+ offsets via objfile_relocate. */
+ for (i = 0; i < objfile->num_sections; ++i)
+ ANOFFSET (section_offsets, i) = 0;
+
+ return section_offsets;
+}
+
+/* Register our ability to parse symbols for xcoff BFD files. */
+
+static struct sym_fns xcoff_sym_fns =
+{
+
+ /* Because the bfd uses coff_flavour, we need to specially kludge
+ the flavour. It is possible that coff and xcoff should be merged as
+ they do have fundamental similarities (for example, the extra storage
+ classes used for stabs could presumably be recognized in any COFF file).
+ However, in addition to obvious things like all the csect hair, there are
+ some subtler differences between xcoffread.c and coffread.c, notably
+ the fact that coffread.c has no need to read in all the symbols, but
+ xcoffread.c reads all the symbols and does in fact randomly access them
+ (in C_BSTAT and line number processing). */
+
+ (enum bfd_flavour)-1,
+
+ xcoff_new_init, /* sym_new_init: init anything gbl to entire symtab */
+ xcoff_symfile_init, /* sym_init: read initial info, setup for sym_read() */
+ xcoff_initial_scan, /* sym_read: read a symbol file into symtab */
+ xcoff_symfile_finish, /* sym_finish: finished with file, cleanup */
+ xcoff_symfile_offsets, /* sym_offsets: xlate offsets ext->int form */
+ NULL /* next: pointer to next struct sym_fns */
+};
+
+void
+_initialize_xcoffread ()
+{
+ add_symtab_fns(&xcoff_sym_fns);
+
+ func_symbol_type = init_type (TYPE_CODE_FUNC, 1, 0,
+ "<function, no debug info>", NULL);
+ TYPE_TARGET_TYPE (func_symbol_type) = builtin_type_int;
+ var_symbol_type =
+ init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+ "<variable, no debug info>", NULL);
+}
diff --git a/contrib/gdb/gdb/xcoffsolib.c b/contrib/gdb/gdb/xcoffsolib.c
new file mode 100644
index 0000000..edcfda1
--- /dev/null
+++ b/contrib/gdb/gdb/xcoffsolib.c
@@ -0,0 +1,211 @@
+/* Shared library support for RS/6000 (xcoff) object files, for GDB.
+ Copyright 1991, 1992 Free Software Foundation.
+ Contributed by IBM Corporation.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if 0
+#include <sys/types.h>
+#include <sys/ldr.h>
+#endif
+
+#include "defs.h"
+#include "bfd.h"
+#include "xcoffsolib.h"
+#include "inferior.h"
+
+#ifdef SOLIB_SYMBOLS_MANUAL
+
+extern struct symtab *current_source_symtab;
+extern int current_source_line;
+
+/* The real work of adding a shared library file to the symtab and
+ the section list. */
+
+void
+solib_add (arg_string, from_tty, target)
+ char *arg_string;
+ int from_tty;
+ struct target_ops *target;
+{
+ char *val;
+ struct vmap *vp = vmap;
+ struct objfile *obj;
+ struct symtab *saved_symtab;
+ int saved_line;
+
+ int loaded = 0; /* true if any shared obj loaded */
+ int matched = 0; /* true if any shared obj matched */
+
+ if (arg_string == 0)
+ re_comp (".");
+ else if (val = (char *) re_comp (arg_string)) {
+ error ("Invalid regexp: %s", val);
+ }
+ if (!vp || !vp->nxt)
+ return;
+
+ /* save current symbol table and line number, in case they get changed
+ in symbol loading process. */
+
+ saved_symtab = current_source_symtab;
+ saved_line = current_source_line;
+
+ /* skip over the first vmap, it is the main program, always loaded. */
+ vp = vp->nxt;
+
+ for (; vp; vp = vp->nxt) {
+
+ if (re_exec (vp->name) || (*vp->member && re_exec (vp->member))) {
+
+ matched = 1;
+
+ /* if already loaded, continue with the next one. */
+ if (vp->loaded) {
+
+ printf_unfiltered ("%s%s%s%s: already loaded.\n",
+ *vp->member ? "(" : "",
+ vp->member,
+ *vp->member ? ") " : "",
+ vp->name);
+ continue;
+ }
+
+ printf_unfiltered ("Loading %s%s%s%s...",
+ *vp->member ? "(" : "",
+ vp->member,
+ *vp->member ? ") " : "",
+ vp->name);
+ gdb_flush (gdb_stdout);
+
+ /* This is gross and doesn't work. If this code is re-enabled,
+ just stick a objfile member into the struct vmap; that's the
+ way solib.c (for SunOS/SVR4) does it. */
+ obj = lookup_objfile_bfd (vp->bfd);
+ if (!obj) {
+ warning ("\nObj structure for the shared object not found. Loading failed.");
+ continue;
+ }
+
+ syms_from_objfile (obj, 0, 0, 0);
+ new_symfile_objfile (obj, 0, 0);
+ vmap_symtab (vp, 0, 0);
+ printf_unfiltered ("Done.\n");
+ loaded = vp->loaded = 1;
+ }
+ }
+ /* if any shared object is loaded, then misc_func_vector needs sorting. */
+ if (loaded) {
+#if 0
+ sort_misc_function_vector ();
+#endif
+ current_source_symtab = saved_symtab;
+ current_source_line = saved_line;
+
+ /* Getting new symbols might change our opinion about what is frameless.
+ Is this correct?? FIXME. */
+/* reinit_frame_cache(); */
+ }
+ else if (!matched)
+ printf_unfiltered ("No matching shared object found.\n");
+}
+#endif /* SOLIB_SYMBOLS_MANUAL */
+
+/* Return the module name of a given text address. Note that returned buffer
+ is not persistent. */
+
+char *
+pc_load_segment_name (addr)
+CORE_ADDR addr;
+{
+ static char buffer [BUFSIZ];
+ struct vmap *vp = vmap;
+
+ buffer [0] = buffer [1] = '\0';
+ for (; vp; vp = vp->nxt)
+ if (vp->tstart <= addr && addr < vp->tend) {
+ if (*vp->member) {
+ buffer [0] = '(';
+ strcat (&buffer[1], vp->member);
+ strcat (buffer, ")");
+ }
+ strcat (buffer, vp->name);
+ return buffer;
+ }
+ return "(unknown load module)";
+}
+
+static void solib_info PARAMS ((char *, int));
+
+static void
+solib_info (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ struct vmap *vp = vmap;
+
+ /* Check for new shared libraries loaded with load (). */
+ xcoff_relocate_symtab (inferior_pid);
+
+ if (vp == NULL || vp->nxt == NULL)
+ {
+ printf_unfiltered ("No shared libraries loaded at this time.\n");
+ return;
+ }
+
+ /* Skip over the first vmap, it is the main program, always loaded. */
+ vp = vp->nxt;
+
+ printf_unfiltered ("\
+Text Range Data Range Syms Shared Object Library\n");
+
+ for (; vp != NULL; vp = vp->nxt)
+ {
+ printf_unfiltered ("0x%08x-0x%08x 0x%08x-0x%08x %s %s%s%s%s\n",
+ vp->tstart, vp->tend,
+ vp->dstart, vp->dend,
+ vp->loaded ? "Yes" : "No ",
+ *vp->member ? "(" : "",
+ vp->member,
+ *vp->member ? ") " : "",
+ vp->name);
+ }
+}
+
+void
+sharedlibrary_command (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ dont_repeat ();
+
+ /* Check for new shared libraries loaded with load (). */
+ xcoff_relocate_symtab (inferior_pid);
+
+#ifdef SOLIB_SYMBOLS_MANUAL
+ solib_add (args, from_tty, (struct target_ops *)0);
+#endif /* SOLIB_SYMBOLS_MANUAL */
+}
+
+void
+_initialize_solib()
+{
+ add_com ("sharedlibrary", class_files, sharedlibrary_command,
+ "Load shared object library symbols for files matching REGEXP.");
+ add_info ("sharedlibrary", solib_info,
+ "Status of loaded shared object libraries");
+}
diff --git a/contrib/gdb/gdb/xcoffsolib.h b/contrib/gdb/gdb/xcoffsolib.h
new file mode 100644
index 0000000..9d10b2e5
--- /dev/null
+++ b/contrib/gdb/gdb/xcoffsolib.h
@@ -0,0 +1,56 @@
+/* Data structures for RS/6000 shared libraries, for GDB.
+ Copyright 1991, 1992, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The vmap struct is used to describe the virtual address space of
+ the target we are manipulating. The first entry is always the "exec"
+ file. Subsequent entries correspond to other objects that are
+ mapped into the address space of a process created from the "exec" file.
+ These are either in response to exec()ing the file, in which case all
+ shared libraries are loaded, or a "load" system call, followed by the
+ user's issuance of a "load" command. */
+
+struct vmap {
+ struct vmap *nxt; /* ptr to next in chain */
+ bfd *bfd; /* BFD for mappable object library */
+ char *name; /* ptr to object file name */
+ char *member; /* ptr to member name */
+ CORE_ADDR tstart; /* virtual addr where member is mapped */
+ CORE_ADDR tend; /* virtual upper bound of member */
+ CORE_ADDR tadj; /* heuristically derived adjustment */
+ CORE_ADDR dstart; /* virtual address of data start */
+ CORE_ADDR dend; /* vitrual address of data end */
+
+ /* This is NULL for the exec-file. */
+ struct objfile *objfile;
+
+ unsigned loaded:1; /* True if symbols are loaded */
+ unsigned padding:15;
+};
+
+
+struct vmap_and_bfd {
+ bfd *pbfd;
+ struct vmap *pvmap;
+};
+
+extern struct vmap *vmap;
+
+void
+add_text_to_loadinfo PARAMS ((CORE_ADDR textaddr, CORE_ADDR dataaddr));
+
diff --git a/contrib/gdb/gdb/xmodem.c b/contrib/gdb/gdb/xmodem.c
new file mode 100644
index 0000000..dd13b87
--- /dev/null
+++ b/contrib/gdb/gdb/xmodem.c
@@ -0,0 +1,284 @@
+/* XMODEM support for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "defs.h"
+#include "serial.h"
+#include "target.h"
+#include "xmodem.h"
+
+/* These definitions are for xmodem protocol. */
+
+#define SOH 0x01
+#define STX 0x02
+#define ACK 0x06
+#define NAK 0x15
+#define EOT 0x04
+#define CANCEL 0x18
+
+static int blknum; /* XMODEM block number */
+static int crcflag; /* Sez we are using CRC's instead of cksums */
+
+static int
+readchar (desc, timeout)
+ serial_t desc;
+ int timeout;
+{
+ int c;
+
+ c = SERIAL_READCHAR (desc, timeout);
+
+ if (remote_debug > 0)
+ fputc_unfiltered (c, gdb_stderr);
+
+ if (c >= 0)
+ return c;
+
+ if (c == SERIAL_TIMEOUT)
+ error ("Timeout reading from remote system.");
+
+ perror_with_name ("xmodem.c:readchar()");
+}
+
+#define CRC16 0x1021 /* Generator polynomial (X^16 + X^12 + X^5 + 1) */
+
+static unsigned short *crctab;
+
+/* Call this to init the fast CRC-16 calculation table. */
+
+static void
+crcinit ()
+{
+ static int crctab_inited = 0;
+ int val;
+
+ if (crctab_inited == 1)
+ return;
+
+ crctab = xmalloc (256 * sizeof (short));
+
+ for (val = 0; val <= 255; val++)
+ {
+ int i;
+ unsigned int crc;
+
+ crc = val << 8;
+
+ for (i = 0; i < 8; ++i)
+ {
+ crc <<= 1;
+
+ if (crc & 0x10000)
+ crc ^= CRC16;
+ }
+
+ crctab [val] = crc;
+ }
+
+ crctab_inited = 1;
+}
+
+/* Calculate a CRC-16 for the LEN byte message pointed at by P. */
+
+static unsigned short
+docrc (p, len)
+ unsigned char *p;
+ int len;
+{
+ unsigned short crc = 0;
+
+ while (len-- > 0)
+ crc = (crc << 8) ^ crctab [(crc >> 8) ^ *p++];
+
+ return crc;
+}
+
+/* Start up the transmit process. Reset state variables. Wait for receiver to
+ send NAK or CRC request. */
+
+int
+xmodem_init_xfer (desc)
+ serial_t desc;
+{
+ int c;
+ int i;
+
+ blknum = 1;
+ crcflag = 0;
+ crcinit ();
+
+ for (i = 1; i <= 10; i++)
+ {
+ c = readchar (desc, 6);
+
+ switch (c)
+ {
+ case 'C':
+ crcflag = 1;
+ case NAK:
+ return 0;
+ default:
+ fprintf_unfiltered (gdb_stderr, "xmodem_init_xfer: Got unexpected character %c (0%o)\n", c, c);
+ continue;
+ case CANCEL: /* target aborted load */
+ fprintf_unfiltered (gdb_stderr, "Got a CANCEL from the target.\n");
+ continue;
+ }
+ }
+ error ("xmodem_init_xfer: Too many unexpected characters.");
+}
+
+/* Take 128 bytes of data and make a packet out of it.
+ *
+ * Each packet looks like this:
+ * +-----+-------+-------+------+-----+
+ * | SOH | Seq1. | Seq2. | data | SUM |
+ * +-----+-------+-------+------+-----+
+ * SOH = 0x01
+ * Seq1 = The sequence number.
+ * Seq2 = The complement of the sequence number.
+ * Data = A 128 bytes of data.
+ * SUM = Add the contents of the 128 bytes and use the low-order
+ * 8 bits of the result.
+ *
+ * send_xmodem_packet fills in the XMODEM fields of PACKET and sends it to the
+ * remote system. PACKET must be XMODEM_PACKETSIZE bytes long. The data must
+ * start 3 bytes after the beginning of the packet to leave room for the
+ * XMODEM header. LEN is the length of the data portion of the packet (and
+ * must be <= 128 bytes). If it is < 128 bytes, ^Z padding will be added.
+ */
+
+void
+xmodem_send_packet (desc, packet, len, hashmark)
+ serial_t desc;
+ unsigned char *packet;
+ int len;
+ int hashmark;
+{
+ int i;
+ int retries;
+ int pktlen;
+ int datasize;
+
+ /* build the packet header */
+
+ packet[1] = blknum;
+ packet[2] = ~blknum;
+
+ blknum++;
+
+ if (len <= XMODEM_DATASIZE)
+ {
+ packet[0] = SOH;
+ datasize = XMODEM_DATASIZE;
+ }
+ else if (len <= XMODEM_1KDATASIZE)
+ {
+ packet[0] = STX;
+ datasize = XMODEM_1KDATASIZE;
+ }
+ else
+ abort (); /* Packet way too large */
+
+ /* Add ^Z padding if packet < 128 (or 1024) bytes */
+
+ memset (packet + 3 + len, '\026', datasize - len);
+
+ if (crcflag)
+ {
+ int crc;
+
+ crc = docrc (packet + 3, datasize);
+
+ packet[3 + datasize] = crc >> 8;
+ packet[3 + datasize + 1] = crc;
+ pktlen = datasize + 5;
+ }
+ else
+ {
+ int sum;
+
+ sum = 0;
+ for (i = 3; i < datasize + 3; i++)
+ sum += packet[i];
+
+ packet[3 + datasize] = sum; /* add the checksum */
+ pktlen = datasize + 4;
+ }
+
+ for (retries = 3; retries >= 0; retries--)
+ {
+ int c;
+
+ SERIAL_WRITE (desc, packet, pktlen);
+
+ c = readchar (desc, 3);
+ switch (c)
+ {
+ case ACK:
+ return;
+ case NAK:
+ if (!hashmark)
+ continue;
+ putchar_unfiltered ('-');
+ gdb_flush (gdb_stdout);
+ continue;
+ case CANCEL:
+ error ("xmodem_send_packet: Transfer aborted by receiver.");
+ default:
+ fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
+ continue;
+ }
+ }
+
+ SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
+
+ error ("xmodem_send_packet: Excessive retries.");
+}
+
+/* Finish off the transfer. Send out the EOT, and wait for an ACK. */
+
+void
+xmodem_finish_xfer (desc)
+ serial_t desc;
+{
+ int retries;
+
+ for (retries = 10; retries >= 0; retries--)
+ {
+ int c;
+
+ SERIAL_WRITE (desc, "\004", 1); /* Send an EOT */
+
+ c = readchar (desc, 3);
+ switch (c)
+ {
+ case ACK:
+ return;
+ case NAK:
+ continue;
+ case CANCEL:
+ error ("xmodem_finish_xfer: Transfer aborted by receiver.");
+ default:
+ fprintf_unfiltered (gdb_stderr, "xmodem_send_packet: Got unexpected character %c (0%o)\n", c, c);
+ continue;
+ }
+ }
+
+ error ("xmodem_finish_xfer: Excessive retries.");
+}
diff --git a/contrib/gdb/gdb/xmodem.h b/contrib/gdb/gdb/xmodem.h
new file mode 100644
index 0000000..0303612
--- /dev/null
+++ b/contrib/gdb/gdb/xmodem.h
@@ -0,0 +1,29 @@
+/* XMODEM support for GDB, the GNU debugger.
+ Copyright 1995 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+int xmodem_init_xfer PARAMS ((serial_t desc));
+void send_xmodem_packet PARAMS ((serial_t desc, unsigned char *packet, int len,
+ int hashmark));
+void xmodem_finish_xfer PARAMS ((serial_t desc));
+
+#define XMODEM_DATASIZE 128 /* The data size is ALWAYS 128 */
+#define XMODEM_1KDATASIZE 1024 /* Unless it's 1024!!! */
+#define XMODEM_PACKETSIZE 133 /* data + packet headers and crc */
+#define XMODEM_1KPACKETSIZE 1024 + 5 /* data + packet headers and crc */
+#define XMODEM_DATAOFFSET 3 /* Offset to start of actual data */
diff --git a/contrib/gdb/include/COPYING b/contrib/gdb/include/COPYING
new file mode 100644
index 0000000..a43ea21
--- /dev/null
+++ b/contrib/gdb/include/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/contrib/gdb/include/ChangeLog b/contrib/gdb/include/ChangeLog
new file mode 100644
index 0000000..3594591
--- /dev/null
+++ b/contrib/gdb/include/ChangeLog
@@ -0,0 +1,973 @@
+Tue Mar 12 17:29:46 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * bfdlink.h (bfd_wrapped_link_hash_lookup): Declare.
+ (struct bfd_link_info): Add wrap_hash field.
+
+Wed Feb 14 16:49:17 1996 Martin Anantharaman <martin@mail.imech.uni-duisburg.de>
+
+ * ieee.h (ieee_record_enum_type): Define
+ ieee_external_reference_info_enum.
+
+Fri Feb 2 17:09:25 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * dis-asm.h (DISASM_RAW_INSN): Delete.
+
+Tue Jan 23 09:21:47 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * dis-asm.h (INIT_DISASSEMBLE_INFO): Set endian to BFD_ENDIAN_UNKNOWN.
+ New argument FPRINTF_FUNC.
+
+Mon Jan 22 16:37:59 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * dis-asm.h (disassemble_info): New members arch, mach, endian.
+ (INIT_DISASSEMBLE_INFO): Initialize them.
+ (DISASM_RAW_INSN{,FLAG}): Define.
+
+Thu Jan 18 11:32:38 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * demangle.h (cplus_demangle_opname): Change opname parameter to
+ const char *.
+ (cplus_mangle_opname): Change return type and opname parameter to
+ const char *.
+
+Fri Jan 5 00:01:22 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * ieee.h (enum ieee_record): Add ieee_asn_record_enum,
+ ieee_at_record_enum, ieee_ty_record_enum, ieee_atn_record_enum,
+ ieee_bb_record_enum, and ieee_be_record_enum.
+
+Wed Jan 3 13:12:09 1996 Fred Fish <fnf@cygnus.com>
+
+ * obstack.h: Update copyright to 1996.
+ (_obstack_memory_used): Declare.
+ (obstack_memory_used): Define macro.
+
+Thu Dec 28 11:42:12 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * libiberty.h (xstrdup): Declare.
+
+Thu Dec 21 14:47:17 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * wait.h: Protect all macros with #ifndef.
+
+Tue Oct 24 21:45:40 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * bfdlink.h (struct bfd_link_info): Add static_link field.
+
+Tue Sep 12 16:28:04 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * bfdlink.h (struct bfd_link_callbacks): Add symbol parameter to
+ warning callback.
+
+Fri Sep 1 13:11:51 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * bfdlink.h (struct bfd_link_callbacks): Change warning callback
+ to take BFD, section, and address arguments.
+
+Thu Aug 31 16:45:12 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * bfdlink.h (struct bfd_link_info): Remove PE stuff.
+
+Tue Aug 22 03:18:23 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * libiberty.h: Declare xstrerror. From Pat Rankin.
+
+Mon Aug 21 18:11:36 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * bfdlink.h (struct bfd_link_info): Remove PE stuff.
+
+Wed Aug 2 08:14:12 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * dis-asm.h (print_insn_sparc64): Declare.
+
+Mon Jul 10 13:26:49 1995 Eric Youngdale <eric@aib.com>
+
+ * bfdlink.h (struct bfd_link_info): Add new field symbolic.
+
+Sun Jul 2 17:48:40 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * bfdlink.h (struct bfd_link_info): Change type of base_file to
+ PTR.
+
+Thu Jun 29 00:02:45 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * bfdlink.h (struct bfd_link_info): Added base_file member.
+
+Tue Jun 20 16:40:04 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * ansidecl.h: win32s is ANSI enough.
+
+Thu May 18 04:25:50 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Wed May 10 14:28:16 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * dis-asm.h (print_insn_arm): Delete declaration.
+ (print_insn_{little,big}_arm): New declarations.
+
+ * floatformat.h (floatformat_arm_ext): Declare.
+
+Sat May 13 10:14:08 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * coff/pe.h: New file.
+ * bfdlink.h (subsytem, stack_heap_parameters): New.
+ * coff/i386.h (NT_SECTION_ALIGNMENT, NT_FILE_ALIGNMENT,
+ NT_DEF_RESERVE, NT_DEF_COMMIT): New.
+ * coff/internal.h (internal_filehdr): New fields for PE.
+ (IMAGE_DATA_DIRECTORY): New.
+ (internal_aouthdr): New fields for PE.
+
+Thu May 4 14:36:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * demangle.h: Don't include ansidecl.h if IN_GCC.
+
+
+Tue Feb 21 00:37:28 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hp-symtab.h: Don't use bitfield enumerations, the HP C compiler
+ does not handle them correctly.
+
+
+Thu Feb 9 14:20:27 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * libiberty.h (basename): Don't declare parameter type; some
+ systems have this in their header files.
+
+Wed Feb 8 17:35:38 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * bfdlink.h (struct bfd_link_hash_entry): Change format of common
+ symbol information, to remove restrictions on maximum size and
+ alignment power, by using a pointer to a structure instead.
+
+Mon Feb 6 14:55:32 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * bfdlink.h (enum bfd_link_hash_type): Rename bfd_link_hash_weak
+ to bfd_link_hash_undefweak. Add bfd_link_hash_defweak.
+
+Mon Jan 16 21:00:23 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * dis-asm.h (GDB_INIT_DISASSEMBLE_INFO, etc): Remove all
+ GDB-specific definitions.
+
+Sun Jan 15 18:39:35 1995 Steve Chamberlain <sac@splat>
+
+ * dis-asm.h (print_insn_w65): Declare.
+
+Thu Jan 12 17:51:17 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * libiberty.h (hex_p): Fix sense of test.
+
+Wed Jan 11 22:36:40 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * libiberty.h (_hex_array_size, _hex_bad, _hex_value, hex_init,
+ hex_p, hex_value): New macros and declarations, for hex.c.
+
+Fri Jan 6 17:44:14 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * dis-asm.h: Make idempotent.
+
+Wed Dec 14 13:08:43 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * progress.h: New file, empty definitions for progress macros.
+
+
+Fri Nov 25 00:14:05 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hp-symtab.h: New file describing the debug symbols emitted
+ by the HP C compilers.
+
+Fri Nov 11 15:48:37 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * bfdlink.h (struct bfd_link_hash_entry): Change u.c.size from 24
+ to 26 bits, and change u.c.alignment_power from 8 to 6 bits. 6
+ bit in the alignment power is enough for a 64 bit address space.
+
+Mon Oct 31 13:02:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * demangle.h (cplus_mangle_opname): Declare.
+
+Tue Oct 25 11:38:02 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * bfdlink.h (struct bfd_link_callbacks): Fix comments for
+ multiple_common field.
+
+Sun Sep 04 17:58:10 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+ * aout/aout64.h: Only define QMAGIC if it isn't already defined.
+
+ * dis-asm.h: Add support for the ARM.
+
+Wed Aug 10 12:51:41 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * libiberty.h (strsignal): Document its existence even if we
+ can't declare it.
+
+Tue Aug 2 14:40:03 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * os9k.h: Remove u_int16, u_int32, and owner_id typedefs and
+ expand their uses. Those names conflict with Mach headers.
+
+Fri Jul 22 14:17:12 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * bfdlink.h (struct bfd_link_hash_entry): Change u.c.size into a
+ bitfield. Add field u.c.alignment_power.
+
+Sun Jul 10 00:26:39 1994 Ian Dall (dall@hfrd.dsto.gov.au)
+
+ * dis-asm.h: Add print_insn_ns32k declaration.
+
+Mon Jun 20 17:13:29 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * bfdlink.h (bfd_link_hash_table): Make creator a const pointer.
+
+Sat Jun 18 16:09:32 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * demangle.h (cplus_demangle_opname): Declare.
+
+Thu Jun 16 15:19:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfdlink.h (struct bfd_link_info): Add new field shared.
+
+Mon Jun 6 14:39:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfdlink.h (struct bfd_link_hash_entry): Remove written field:
+ not needed for all backends.
+
+Thu Apr 28 19:06:50 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * dis-asm.h (disassembler): Declare.
+
+Fri Apr 1 00:38:17 1994 Jim Wilson (wilson@mole.gnu.ai.mit.edu)
+
+ * obstack.h: Delete use of IN_GCC to control whether
+ stddef.h or gstddef.h is included.
+
+Tue Mar 22 13:06:02 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfdlink.h (enum bfd_link_order_type): Add bfd_data_link_order.
+ (struct bfd_link_order): Add data field to union.
+
+Mon Mar 21 18:45:26 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfdlink.h (struct bfd_link_callbacks): Change bitsize argument
+ to add_to_set to reloc. Remove bitsize argument from constructor.
+ Comment that reloc_overflow, reloc_dangerous and unattached_reloc
+ must handle NULL pointers for reloc location.
+ (enum bfd_link_order_type): Add bfd_section_reloc_link_order and
+ bfd_symbol_reloc_link_order.
+ (struct bfd_link_order): Add reloc field to union.
+ (struct bfd_link_order_reloc): Define.
+
+Mon Mar 14 12:27:50 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * ieee-float.h: Removed; no longer used.
+
+Tue Mar 1 18:10:49 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * os9k.h: os9000 target specific header file, the header of the
+ object file is used now.
+
+Sun Feb 27 21:52:26 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * floatformat.h: New file, intended to replace ieee-float.h.
+
+Sun Feb 20 17:15:42 1994 Ian Lance Taylor (ian@lisa.cygnus.com)
+
+ * ansidecl.h (ANSI_PROTOTYPES): Define if using ANSI prototypes.
+
+Wed Feb 16 01:07:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * libiberty.h: Don't declare strsignal, to avoid conflicts with
+ Solaris system header files.
+
+Sat Feb 12 22:11:32 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * libiberty.h (xexit): Use __volatile__ to avoid losing if
+ compiling with gcc -traditional.
+
+Thu Feb 10 14:05:41 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * libiberty.h: New file. Declares functions provided by
+ libiberty.
+
+Tue Feb 8 05:19:52 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ Handle obstack_chunk_alloc returning NULL. This allows
+ obstacks to be used by libraries, without forcing them
+ to call exit or longjmp.
+ * obstack.h (struct obstack): Add alloc_failed flag.
+ _obstack_begin, _obstack_begin_1): Declare to return int, not void.
+ (obstack_finish): If alloc_failed, return NULL.
+ (obstack_base, obstack_next_free, objstack_object_size):
+ If alloc_failed, return 0.
+ (obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
+ obstack_int_grow, obstack_blank): If alloc_failed, do nothing that
+ could corrupt the obstack.
+
+Mon Jan 24 15:06:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfdlink.h (struct bfd_link_callbacks): Add name, reloc_name and
+ addend argments to reloc_overflow callback.
+
+Fri Jan 21 19:13:12 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * dis-asm.h (print_insn_big_powerpc, print_insn_little_powerpc,
+ print_insn_rs6000): Declare.
+
+Thu Jan 6 14:15:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfdlink.h (struct bfd_link_callbacks): Add bitsize argument to
+ add_to_set field. Add new callback named constructor.
+
+Thu Dec 30 10:44:06 1993 Ian Lance Taylor (ian@rtl.cygnus.com)
+
+ * bfdlink.h: New file for new BFD linker backend routines.
+
+Mon Nov 29 10:43:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * dis-asm.h (enum dis_insn_tyupe): Remove non-ANSI trailing comma.
+
+Sat Oct 2 20:42:26 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dis-asm.h: Move comment to right place.
+
+Mon Aug 9 19:03:35 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * obstack.h (obstack_chunkfun, obstack_freefun): Add defns from
+ previous version. Are these Cygnus local changes?
+
+Fri Aug 6 17:05:47 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * getopt.h, obstack.h: Update to latest FSF version.
+
+Mon Aug 2 16:37:14 1993 Stu Grossman (grossman at cygnus.com)
+
+ * coff/i386.h: Add Lynx magic number.
+
+Mon Aug 2 14:45:29 1993 John Gilmore (gnu@cygnus.com)
+
+ * dis-asm.h: Move enum outside of struct defn to avoid warnings.
+
+Mon Aug 2 08:49:30 1993 Stu Grossman (grossman at cygnus.com)
+
+ * wait.h (WEXITSTATUS, WSTOPSIG): Mask down to 8 bits. This is
+ for systems that store stuff into the high 16 bits of a wait
+ status.
+
+Fri Jul 30 18:38:02 1993 John Gilmore (gnu@cygnus.com)
+
+ * dis-asm.h: Add new fields insn_info_valid, branch_delay_insns,
+ data_size, insn_type, target, target2. These are used to return
+ information from the instruction decoders back to the calling
+ program. Add comments, make more readable.
+
+Mon Jul 19 22:14:14 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * nlm: New directory containing NLM/NetWare includes.
+
+Thu Jul 15 12:10:04 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * dis-asm.h (struct disassemble_info): New field application_data.
+
+Thu Jul 15 12:41:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * dis-asm.h: Added declaration of print_insn_m88k.
+
+Thu Jul 8 09:05:26 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * opcode/h8300.h: Lots of little fixes for the h8/300h.
+
+Fri Jul 2 10:31:59 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * ansidecl.h: Use ANSI macros if __mips and _SYSTYPE_SVR4 are
+ defined, since RISC/OS cc handles ANSI declarations in SVR4 mode
+ but does not define __STDC__.
+
+Sun Jun 20 18:27:52 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
+
+ * dis-asm.h: Don't need to include ansidecl.h any more.
+
+Fri Jun 18 03:22:10 1993 John Gilmore (gnu@cygnus.com)
+
+ * oasys.h: Eliminate "int8_type", "int16_type", "int32_type", and
+ their variants. These changes are coordinated with corresponding
+ changes in ../bfd/oasys.c.
+
+Wed Jun 16 10:43:08 1993 Fred Fish (fnf@cygnus.com)
+
+ * bfd.h: Note that it has been removed.
+
+Tue Jun 8 12:16:03 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ Support for H8/300-H
+ * dis-asm.h (print_insn_h8300, print_insn_h8300h): Declare it.
+ * coff/h8300.h: New magic number.
+ * coff/internal.h: New relocations.
+ * opcode/h8300.h: Lots of new opcodes.
+
+Tue Jun 1 07:35:03 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * ansidecl.h (const): Don't define it if it's already defined.
+
+Thu May 27 18:19:51 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * dis-asm.h (print_insn_hppa): Declare it.
+
+ * bfd.h: Moved to bfd directory. Small stub here includes it
+ without requiring "-I../bfd".
+
+Thu Apr 29 12:06:13 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * bfd.h: Updated with BSF_FUNCTION.
+
+Mon Apr 26 18:15:50 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * bfd.h, dis-asm.h: Updated with Hitachi SH.
+
+Fri Apr 23 18:41:38 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * bfd.h: Updated with alpha changes.
+ * dis-asm.h: Added alpha.
+
+Fri Apr 16 17:35:30 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * bfd.h: Update for signed bfd_*get_*.
+
+Thu Apr 15 09:24:21 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * bfd.h: Updated for file_truncated error.
+
+Thu Apr 8 10:53:47 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * ansidecl.h: If no ANSI, define const to be empty.
+
+Thu Apr 1 09:00:10 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * dis-asm.h: Declare a29k and i960 print_insn_*.
+
+ * dis-asm.h: Add print_address_func and related stuff.
+
+ * dis-asm.h (dis_asm_read_memory): Fix prototype.
+
+Wed Mar 31 17:40:16 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dis-asm.h: Add print_insn_sparc.
+
+Wed Mar 31 17:51:42 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * bfd.h: Updated for BFD_RELOC_MIPS_GPREL and bfd_[gs]et_gp_size
+ prototypes.
+
+Wed Mar 31 16:35:12 1993 Stu Grossman (grossman@cygnus.com)
+
+ * dis-asm.h: (disassemble_info): Fix typo in prototype of
+ dis_asm_memory_error().
+
+Tue Mar 30 19:09:23 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dis-asm.h (disassembler_info): Add read_memory_func,
+ memory_error_func, buffer, and length.
+ ({GDB_,}INIT_DISASSEMBLE_INFO): Set them.
+ print_insn_*: Remove second argument.
+
+Tue Mar 30 14:48:55 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * bfd.h: Update for lma field of section.
+
+Tue Mar 30 12:22:55 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * ansidecl.h: Use ANSI versions on AIX regardless of __STDC__.
+
+Fri Mar 19 14:49:49 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * dis-asm.h: Add h8500.
+
+Thu Mar 18 13:49:09 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * ieee-float.h: Moved from ../gdb.
+ * dis-asm.h: New file. Interface to dis-assembler.
+
+Thu Mar 11 10:52:57 1993 Fred Fish (fnf@cygnus.com)
+
+ * demangle.h (DMGL_NO_OPTS): Add define (set to 0) to use
+ in place of bare 0, for readability reasons.
+
+Tue Mar 2 17:50:11 1993 Fred Fish (fnf@cygnus.com)
+
+ * demangle.h: Replace all references to cfront with ARM.
+
+Tue Feb 23 12:21:14 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * bfd.h: Update for new elements in JUMP_TABLE.
+
+Tue Feb 16 00:51:30 1993 John Gilmore (gnu@cygnus.com)
+
+ * bfd.h: Update for BFD_VERSION 2.1.
+
+Tue Jan 26 11:49:20 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * bfd.h: Update for SEC_IS_COMMON flag.
+
+Tue Jan 19 12:25:12 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfd.h: Update for bfd_asymbol_value bug fix.
+
+Fri Jan 8 16:37:18 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * bfd.h: Update to include ECOFF tdata and target_flavour.
+
+Sun Dec 27 17:52:30 1992 Fred Fish (fnf@cygnus.com)
+
+ * bfd.h: Add declaration for bfd_get_size().
+
+Tue Dec 22 22:42:46 1992 Fred Fish (fnf@cygnus.com)
+
+ * demangle.h: Protect file from multiple inclusions with
+ #if !defined(DEMANGLE_H)...#define DEMANGLE_H...#endif.
+
+Mon Dec 21 21:25:50 1992 Stu Grossman (grossman at cygnus.com)
+
+ * bfd.h: Update to get hppa_core_struct from bfd.c.
+
+Thu Dec 17 00:42:35 1992 John Gilmore (gnu@cygnus.com)
+
+ * bfd.h: Update to get tekhex tdata name change from bfd.
+
+Mon Nov 9 23:55:42 1992 John Gilmore (gnu@cygnus.com)
+
+ * ansidecl.h: Update comments to discourage use of EXFUN.
+
+Thu Nov 5 16:35:44 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * bfd.h: Update to bring in SEC_SHARED_LIBRARY.
+
+Thu Nov 5 03:21:32 1992 John Gilmore (gnu@cygnus.com)
+
+ * bfd.h: Update to match EXFUN, bfd_seclet_struct, and SDEF
+ cleanups in bfd.
+
+Wed Nov 4 07:28:05 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * bout.h (N_CALLNAME, N_BALNAME): Define as char-type values, so
+ widening works consistently.
+
+Fri Oct 16 03:17:08 1992 John Gilmore (gnu@cygnus.com)
+
+ * getopt.h: Update to Revised Standard FSF Version.
+
+Thu Oct 15 21:43:22 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * getopt.h (struct option): use the provided enum for has_arg.
+
+ * demangle.h (AUTO_DEMANGLING, GNU_DEMANGLING,
+ LUCID_DEMANGLING): ultrix compilers require enums to be
+ enums and ints to be ints and casts where they meet. cast some
+ enums into ints.
+
+Thu Oct 15 04:35:51 1992 John Gilmore (gnu@cygnus.com)
+
+ * bfd.h: Update after comment changes.
+
+Thu Oct 8 09:03:02 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * bfd.h (bfd_get_symbol_leading_char): new macro for getting in xvec
+
+Thu Sep 3 09:10:50 1992 Stu Grossman (grossman at cygnus.com)
+
+ * bfd.h (struct reloc_howto_struct): size needs to be signed if
+ it's going to hold negative values.
+
+Sun Aug 30 17:50:27 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * demangle.h: New file, moved from ../gdb. Made independent
+ of gdb. Allow demangling style option to be passed as a
+ parameter to cplus_demangle(), but using the
+ current_demangling_style global as the default.
+
+Sat Aug 29 10:07:55 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.h: Merge comment change from current FSF version.
+
+Thu Aug 27 12:59:29 1992 Brendan Kehoe (brendan@cygnus.com)
+
+ * bfd.h: add we32k
+
+Tue Aug 25 15:07:47 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * bfd.h: new after Z8000 stuff
+
+Mon Aug 17 09:01:23 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * bfd.h: Regenerated after page/segment size changes.
+
+Sat Aug 1 13:46:31 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.h: Merge changes from current FSF version.
+
+Mon Jul 20 21:06:23 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.h (area_id, flags): Remove, replace with extra_arg,
+ use_extra_arg, and maybe_empty_object.
+ * obstack.h (OBSTACK_MAYBE_EMPTY_OBJECT, OBSTACK_MMALLOC_LIKE):
+ Remove, replaced by maybe_empty_object and use_extra_arg bitfields.
+ * obstack.h (obstack_full_begin, _obstack_begin): Remove area_id
+ and flags arguments.
+ * obstack.h (obstack_alloc_arg): New macro to set extra_arg.
+
+Thu Jul 16 08:12:44 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * bfd.h: new after adding BFD_IS_RELAXABLE
+
+Sat Jul 4 03:22:23 1992 John Gilmore (gnu at cygnus.com)
+
+ * bfd.h: Regen after adding BSF_FILE.
+
+Mon Jun 29 14:18:36 1992 Fred Fish (fnf at sunfish)
+
+ * obstack.h: Convert bcopy() use to memcpy(), which is more
+ portable, more standard, and can take advantage of gcc's builtin
+ functions for increased performance.
+
+Thu Jun 25 04:46:08 1992 John Gilmore (gnu at cygnus.com)
+
+ * ansidecl.h (PARAMS): Incorporate this macro from gdb's defs.h.
+ It's a cleaner way to forward-declare function prototypes.
+
+Fri Jun 19 15:46:32 1992 Stu Grossman (grossman at cygnus.com)
+
+ * bfd.h: HPPA merge.
+
+Tue Jun 16 21:30:56 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * getopt.h: gratuitous white space changes merged from other prep
+ releases.
+
+Thu Jun 11 01:10:55 1992 John Gilmore (gnu at cygnus.com)
+
+ * bfd.h: Regen'd from bfd.c after removing elf_core_tdata_struct.
+
+Mon May 18 17:29:03 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * getopt.h: merged changes from make-3.62.11.
+
+ * getopt.h: merged changes from grep-1.6 (alpha).
+
+Fri May 8 14:53:32 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * getopt.h: merged changes from bison-1.18.
+
+Sat Mar 14 17:25:20 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.h: Add "area_id" and "flags" members to obstack
+ structure. Add obstack_chunkfun() and obstack_freefun() to
+ set functions explicitly. Convert maybe_empty_object to
+ a bit in "flags".
+
+Thu Feb 27 22:01:02 1992 Per Bothner (bothner@cygnus.com)
+
+ * wait.h (WIFSTOPPED): Add IBM rs6000-specific version.
+
+Fri Feb 21 20:49:20 1992 John Gilmore (gnu at cygnus.com)
+
+ * obstack.h: Add obstack_full_begin.
+ * bfd.h, obstack.h: Protolint.
+
+Thu Jan 30 01:18:42 1992 John Gilmore (gnu at cygnus.com)
+
+ * bfd.h: Remove comma from enum declaration.
+
+Mon Jan 27 22:01:13 1992 Steve Chamberlain (sac at cygnus.com)
+
+ * bfd.h : new target entr, bfd_relax_section
+
+Wed Dec 18 17:19:44 1991 Stu Grossman (grossman at cygnus.com)
+
+ * bfd.h, ieee.h, opcode/m68k.h, opcode/sparc.h: ANSIfy enums.
+
+Thu Dec 12 20:59:56 1991 John Gilmore (gnu at cygnus.com)
+
+ * fopen-same.h, fopen-bin.h: New files for configuring
+ whether fopen distinguishes binary files or not. For use
+ by host-dependent config files.
+
+Sat Nov 30 20:46:43 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * bfd.h: change the documentation format.
+
+ * created coff, elf and opcode and aout directories. Moved:
+
+ aout64.h ==> aout/aout64.h
+ ar.h ==> aout/ar.h
+ a.out.encap.h ==> aout/encap.h
+ a.out.host.h ==> aout/host.h
+ a.out.hp.h ==> aout/hp.h
+ a.out.sun4.h ==> aout/sun4.h
+ ranlib.h ==> aout/ranlib.h
+ reloc.h ==> aout/reloc.h
+ stab.def ==> aout/stab.def
+ stab.gnu.h ==> aout/stab_gnu.h
+
+ coff-a29k.h ==> coff/a29k.h
+ coff-h8300.h ==> coff/h8300.h
+ coff-i386.h ==> coff/i386.h
+ coff-i960.h ==> coff/i960.h
+ internalcoff.h ==> coff/internal.h
+ coff-m68k.h ==> coff/m68k.h
+ coff-m88k.h ==> coff/m88k.h
+ coff-mips.h ==> coff/mips.h
+ coff-rs6000.h ==> coff/rs6000.h
+
+ elf-common.h ==> elf/common.h
+ dwarf.h ==> elf/dwarf.h
+ elf-external.h ==> elf/external.h
+ elf-internal.h ==> elf/internal.h
+
+ a29k-opcode.h ==> opcode/a29k.h
+ arm-opcode.h ==> opcode/arm.h
+ h8300-opcode.h ==> opcode/h8300.h
+ i386-opcode.h ==> opcode/i386.h
+ i860-opcode.h ==> opcode/i860.h
+ i960-opcode.h ==> opcode/i960.h
+ m68k-opcode.h ==> opcode/m68k.h
+ m88k-opcode.h ==> opcode/m88k.h
+ mips-opcode.h ==> opcode/mips.h
+ np1-opcode.h ==> opcode/np1.h
+ ns32k-opcode.h ==> opcode/ns32k.h
+ pn-opcode.h ==> opcode/pn.h
+ pyr-opcode.h ==> opcode/pyr.h
+ sparc-opcode.h ==> opcode/sparc.h
+ tahoe-opcode.h ==> opcode/tahoe.h
+ vax-opcode.h ==> opcode/vax.h
+
+
+
+Wed Nov 27 10:38:31 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * internalcoff.h: (internal_scnhdr) took out #def dependency, now
+ s_nreloc and s_nlnno are always long. (internal_reloc): allways
+ has an offset field now.
+
+Fri Nov 22 08:12:58 1991 John Gilmore (gnu at cygnus.com)
+
+ * coff-rs6000.h: Lint; use unsigned chars for external fields.
+ * internalcoff.h: Lint; cast storage classes to signed char.
+
+Thu Nov 21 21:01:05 1991 Per Bothner (bothner at cygnus.com)
+
+ * stab.def: Remove the GNU extended type codes (e.g. N_SETT).
+ * aout64.h: The heuristic for distinguishing between
+ sunos-style and bsd-style ZMAGIC files (wrt. where the
+ text segment starts) is moved into (the default definition of)
+ the macro N_HEADER_IN_TEXT. This definition is only used
+ if no other definition is used - e.g. bfd/newsos3.c defines
+ N_HEADER_IN_TEXT(x) to be always 0 (as before).
+
+Thu Nov 21 11:53:03 1991 John Gilmore (gnu at cygnus.com)
+
+ * aout64.h (N_TXTADDR, N_TXTOFF, N_TXTSIZE): New definitions
+ that should handle all uses. LOGICAL_ versions deleted.
+ Eliminate N_HEADER_IN_TEXT, using a_entry to determine which
+ kind of zmagic a.out file we are looking at.
+ * coff-rs6000.h: Typo.
+
+Tue Nov 19 18:43:37 1991 Per Bothner (bothner at cygnus.com)
+
+ (Note: This is a revised entry, as was aout64.h.)
+ * aout64.h: Some cleanups of N_TXTADDR and N_TXTOFF:
+ Will now work for both old- and new-style ZMAGIC files,
+ depending on N_HEADER_IN_TEXT macro.
+ Add LOGICAL_TXTADDR, LOICAL_TXTOFF and LOGICAL_TXTSIZE
+ that don't count the exec header as part
+ of the text segment, to be consistent with bfd.
+ * a.out.sun4.h: Simplified/fixed for previous change.
+
+Mon Nov 18 00:02:06 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarf.h: Update to DWARF draft 5 version from gcc2.
+
+Thu Nov 14 19:44:59 1991 Per Bothner (bothner at cygnus.com)
+
+ * stab.def: Added defs for extended GNU symbol types,
+ such as N_SETT. These are normally ifdef'd out (because
+ of conflicts with a.out.gnu.h), but are used by bfb_stab_name().
+
+Thu Nov 14 19:17:03 1991 Fred Fish (fnf at cygnus.com)
+
+ * elf-common.h: Add defines to support ELF symbol table code.
+
+Mon Nov 11 19:01:06 1991 Fred Fish (fnf at cygnus.com)
+
+ * elf-internal.h, elf-external.h, elf-common.h: Add support for
+ note sections, which are used in ELF core files to hold copies
+ of various /proc structures.
+
+Thu Nov 7 08:58:26 1991 Steve Chamberlain (sac at cygnus.com)
+
+ * internalcoff.h: took out the M88 dependency in the lineno
+ struct.
+ * coff-m88k.h: defines GET_LINENO_LNNO and PUT_LINENO_LNNO to use
+ 32bit linno entries.
+ * a29k-opcode.h: fixed encoding of mtacc
+
+Sun Nov 3 11:54:22 1991 Per Bothner (bothner at cygnus.com)
+
+ * bfd.h: Updated from ../bfd/bfd-in.h (q.v).
+
+Fri Nov 1 11:13:53 1991 John Gilmore (gnu at cygnus.com)
+
+ * internalcoff.h: Add x_csect defines.
+
+Fri Oct 25 03:18:20 1991 John Gilmore (gnu at cygnus.com)
+
+ * Rename COFF-related files in `coff-ARCH.h' form.
+ coff-a29k.h, coff-i386.h, coff-i960.h, coff-m68k.h, coff-m88k.h,
+ coff-mips.h, coff-rs6000.h to be exact.
+
+Thu Oct 24 22:11:11 1991 John Gilmore (gnu at cygnus.com)
+
+ RS/6000 support, by Metin G. Ozisik, Mimi Phûông-Thåo Võ, and
+ John Gilmore.
+
+ * a.out.gnu.h: Update slightly.
+ * bfd.h: Add new error code, fix doc, add bfd_arch_rs6000.
+ * internalcoff.h: Add more F_ codes for filehdr. Add
+ rs/6000-dependent fields to aouthdr. Add storage classes
+ to syments. Add 6000-specific auxent. Add r_size in reloc.
+ * rs6000coff.c: New file.
+
+Thu Oct 24 04:13:20 1991 Fred Fish (fnf at cygnus.com)
+
+ * dwarf.h: New file for dwarf support. Copied from gcc2
+ distribution.
+
+Wed Oct 16 13:31:45 1991 John Gilmore (gnu at cygnus.com)
+
+ * aout64.h: Remove PAGE_SIZE defines; they are target-dependent.
+ Add N_FN_SEQ for N_FN symbol type used on Sequent machines.
+ * stab.def: Include N_FN_SEQ in table.
+ * bout.h: External formats of structures use unsigned chars.
+
+Fri Oct 11 12:40:43 1991 Steve Chamberlain (steve at cygnus.com)
+
+ * bfd.h:upgrade from bfd.c
+ * internalcoff.h: add n_name, n_zeroes and n_offset macros
+ * amdcoff.h: Define OMAGIC and AOUTHDRSZ.
+
+Fri Oct 11 10:58:06 1991 Per Bothner (bothner at cygnus.com)
+
+ * a.out.host.h: Change SEGMENT_SIZE to 0x1000 for Sony.
+ * bfd.h (align_power): Add (actually move) comment.
+
+Tue Oct 8 15:29:32 1991 Per Bothner (bothner at cygnus.com)
+
+ * sys/h-rtbsd.h: Define MISSING_VFPRINT (for binutils/bucomm.c).
+
+Sun Oct 6 19:24:39 1991 John Gilmore (gnu at cygnus.com)
+
+ * aout64.h: Move struct internal_exec to ../bfd/libaout.h so
+ it can be shared by all `a.out-family' code. Rename
+ EXTERNAL_LIST_SIZE to EXTERNAL_NLIST_SIZE. Use basic types
+ for nlist members, and make strx integral rather than pointer.
+ More commentary on n_type values.
+ * bout.h: Provide a struct external_exec rather than an
+ internal_exec.
+ * m68kcoff.h: Remove `tagentries' which snuck in from the i960
+ COFF port.
+
+Fri Oct 4 01:25:59 1991 John Gilmore (gnu at cygnus.com)
+
+ * h8300-opcode.h: Remove `_enum' from the typedef for an enum.
+ * bfd.h: Update to match bfd changes.
+
+ * sys/h-i386mach.h, sysdep.h: Add 386 Mach host support.
+
+Tue Oct 1 04:58:42 1991 John Gilmore (gnu at cygnus.com)
+
+ * bfd.h, elf-common.h, elf-external.h, elf-internal.h:
+ Add preliminary ELF support, sufficient for GDB, from Fred Fish.
+ * sysdep.h, sys/h-amix.h: Support Amiga SVR4.
+
+ * sys/h-vaxult.h: Make it work. (David Taylor <taylor@think.com>)
+ * a.out.vax.h: Remove unused and confusing file.
+
+Mon Sep 30 12:52:35 1991 Per Bothner (bothner at cygnus.com)
+
+ * sysdep.h: Define NEWSOS3_SYS, and use it.
+
+Fri Sep 20 13:38:21 1991 John Gilmore (gnu at cygnus.com)
+
+ * a.out.gnu.h (N_FN): Its value *really is* 0x1F.
+ Fix it, and add comments warning about or-ing N_EXT with it
+ and/or N_WARNING.
+ * aout64.h (N_FN): Fix value, add comments about N_EXT.
+ * stab.def (table at end): Update to show all the type
+ values <0x20, including low order bits. Move N_FN to
+ its rightful place.
+
+Tue Sep 17 17:41:37 1991 Stu Grossman (grossman at cygnus.com)
+
+ * sys/h-irix3.h: sgi/irix support.
+
+Tue Sep 17 07:52:59 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * stab.def (N_DEFD): Add GNU Modula-2 debug stab, from Andrew
+ Beers.
+
+Thu Sep 12 14:12:59 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * internalcoff.h (SYMNMLEN, FILNMLEN, DIMNUM): Define these
+ for internalcoff, separately from the various external coff's.
+ * amdcoff.h, bcs88kcoff.h, i386coff.h, intel-coff.h, m68kcoff.h,
+ m88k-bcs.h: Prefix SYMNMLEN, FILNMLEN, and DIMNUM with E_'s for
+ the external struct definitions.
+ * ecoff.h: Remove these #define's, kludge no longer needed.
+
+ * sys/h-ultra3.h: Add new Ultracomputer host.
+ * sysdep.h: Add ULTRA3_SYM1_SYS and use it.
+
+Tue Sep 10 10:11:46 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * i386coff.h (LINESZ): Always 6, not based on sizeof().
+ (Fix from Peter Schauer <pes@regent.e-technik.tu-muenchen.de>.)
+
+Wed Sep 4 08:58:37 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * a.out.gnu.h, aout64.h: Add N_WARNING. Change N_FN to 0x0E,
+ to match SunOS and BSD. Add N_COMM as 0x12 for SunOS shared lib
+ support.
+ * stab.def: Add N_COMM to table, fix overlap comment.
+
+Tue Sep 3 06:29:20 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ Merge with latest FSF versions of these files.
+
+ * stab.gnu.h: Add LAST_UNUSED_STAB_CODE.
+ * stab.def: Update to GPL2. Move N_WARNING out, since not a
+ debug symbol. Change comments, and reorder table to numeric
+ order. Update final table comment.
+ (N_DSLINE, N_BSLINE): Renumber from 0x66 and 0x68, to 0x46 and 0x48.
+
+ * obstack.h: GPL2. Merge.
+
+Fri Aug 23 01:54:23 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * a.out.gnu.h, a.out.sun4.h: Make SEGMENT_SIZE able to depend
+ on the particular a.out being examined.
+ * a.out.sun4.h: Define segment sizes for Sun-3's and Sun-4's.
+ * FIXME: a.out.gnu.h is almost obsolete.
+ * FIXME: a.out.sun4.h should be renamed a.out.sun.h now.
+
+Wed Aug 21 20:32:13 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * Start a ChangeLog for the includes directory.
+
+ * a.out.gnu.h (N_FN): Fix value -- was 15, should be 0x1E.
+ * stab.def: Update allocation table in comments at end,
+ to reflect reality as I know it.
+
+
+Local Variables:
+mode: indented-text
+left-margin: 8
+fill-column: 74
+version-control: never
+End:
diff --git a/contrib/gdb/include/ansidecl.h b/contrib/gdb/include/ansidecl.h
new file mode 100644
index 0000000..be04e42
--- /dev/null
+++ b/contrib/gdb/include/ansidecl.h
@@ -0,0 +1,141 @@
+/* ANSI and traditional C compatability macros
+ Copyright 1991, 1992 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macro ANSI C definition Traditional C definition
+ ----- ---- - ---------- ----------- - ----------
+ PTR `void *' `char *'
+ LONG_DOUBLE `long double' `double'
+ VOLATILE `volatile' `'
+ SIGNED `signed' `'
+ PTRCONST `void *const' `char *'
+ ANSI_PROTOTYPES 1 not defined
+
+ CONST is also defined, but is obsolete. Just use const.
+
+ DEFUN (name, arglist, args)
+
+ Defines function NAME.
+
+ ARGLIST lists the arguments, separated by commas and enclosed in
+ parentheses. ARGLIST becomes the argument list in traditional C.
+
+ ARGS list the arguments with their types. It becomes a prototype in
+ ANSI C, and the type declarations in traditional C. Arguments should
+ be separated with `AND'. For functions with a variable number of
+ arguments, the last thing listed should be `DOTS'.
+
+ DEFUN_VOID (name)
+
+ Defines a function NAME, which takes no arguments.
+
+ obsolete -- EXFUN (name, (prototype)) -- obsolete.
+
+ Replaced by PARAMS. Do not use; will disappear someday soon.
+ Was used in external function declarations.
+ In ANSI C it is `NAME PROTOTYPE' (so PROTOTYPE should be enclosed in
+ parentheses). In traditional C it is `NAME()'.
+ For a function that takes no arguments, PROTOTYPE should be `(void)'.
+
+ PARAMS ((args))
+
+ We could use the EXFUN macro to handle prototype declarations, but
+ the name is misleading and the result is ugly. So we just define a
+ simple macro to handle the parameter lists, as in:
+
+ static int foo PARAMS ((int, char));
+
+ This produces: `static int foo();' or `static int foo (int, char);'
+
+ EXFUN would have done it like this:
+
+ static int EXFUN (foo, (int, char));
+
+ but the function is not external...and it's hard to visually parse
+ the function name out of the mess. EXFUN should be considered
+ obsolete; new code should be written to use PARAMS.
+
+ For example:
+ extern int printf PARAMS ((CONST char *format DOTS));
+ int DEFUN(fprintf, (stream, format),
+ FILE *stream AND CONST char *format DOTS) { ... }
+ void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef _ANSIDECL_H
+
+#define _ANSIDECL_H 1
+
+
+/* Every source file includes this file,
+ so they will all get the switch for lint. */
+/* LINTLIBRARY */
+
+
+#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32)
+/* All known AIX compilers implement these things (but don't always
+ define __STDC__). The RISC/OS MIPS compiler defines these things
+ in SVR4 mode, but does not define __STDC__. */
+
+#define PTR void *
+#define PTRCONST void *CONST
+#define LONG_DOUBLE long double
+
+#define AND ,
+#define NOARGS void
+#define CONST const
+#define VOLATILE volatile
+#define SIGNED signed
+#define DOTS , ...
+
+#define EXFUN(name, proto) name proto
+#define DEFUN(name, arglist, args) name(args)
+#define DEFUN_VOID(name) name(void)
+
+#define PROTO(type, name, arglist) type name arglist
+#define PARAMS(paramlist) paramlist
+#define ANSI_PROTOTYPES 1
+
+#else /* Not ANSI C. */
+
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define AND ;
+#define NOARGS
+#define CONST
+#ifndef const /* some systems define it in header files for non-ansi mode */
+#define const
+#endif
+#define VOLATILE
+#define SIGNED
+#define DOTS
+
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+#define PROTO(type, name, arglist) type name ()
+#define PARAMS(paramlist) ()
+
+#endif /* ANSI C. */
+
+#endif /* ansidecl.h */
diff --git a/contrib/gdb/include/aout/ChangeLog b/contrib/gdb/include/aout/ChangeLog
new file mode 100644
index 0000000..307448b
--- /dev/null
+++ b/contrib/gdb/include/aout/ChangeLog
@@ -0,0 +1,174 @@
+Mon Mar 11 12:15:52 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * stab.def: Use __define_stab_duplicate rather than __define_stab
+ for duplicate entries N_BROWS and N_MOD2.
+ * stab_gnu.h (__define_stab_duplicate): Define before including
+ stab.def.
+
+Fri Oct 27 17:47:16 1995 Niklas Hallqvist <niklas@appli.se>
+
+ * aout64.h, host.h, hp300hpux.h, sun4.h: Changed PAGE_SIZE to
+ TARGET_PAGE_SIZE.
+
+Tue Sep 12 12:07:02 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * sun4.h (struct internal_sun4_dynamic_link): Change all fields
+ from long to unsigned long.
+
+Wed Jul 12 00:15:13 1995 Ken Raeburn <raeburn@kr-pc.cygnus.com>
+
+ * sun4.h (PAGE_SIZE): Undefine before defining.
+
+Thu Jun 16 14:22:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * aout64.h (BMAGIC): Define.
+
+Sat Jun 11 16:16:09 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ Add weak symbols as an extension to a.out.
+ * aout64.h (N_WEAKU, N_WEAKA, N_WEAKT, N_WEAKD, N_WEAKB): Define.
+ * stab.def: Update symbol value table.
+
+Thu Jun 2 17:13:38 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * sun4.h (EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE): Correct from 28 to
+ 24. Fix up ld_got comment.
+
+Wed Mar 30 00:31:49 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dynix3.h: Cleanup, adapt to current bfd version.
+
+Sat Feb 26 10:25:53 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * aout64.h: Add casts to avoid warnings from SVR4 cc.
+
+Fri Feb 11 12:56:04 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * ar.h (ARMAG, ARMAGB, ARFMAG): Change '\n' to '\012', for greater
+ portability.
+
+Fri Jan 21 00:59:06 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * sun4.h: Added information about SunOS shared libraries.
+
+Fri Jan 7 08:20:13 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * aout64.h (N_TXTADDR): Add comment regarding OMAGIC and NMAGIC.
+
+Sat Dec 25 14:55:41 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * aout64.h (N_DATOFF): Don't pad (revert change of 8 Jul 1993).
+
+Tue Nov 16 15:43:46 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * aout64.h: New macros ZMAGIC_DISK_BLOCK_SIZE and N_DISK_BLOCK_SIZE
+ for Linux ZMAGIC.
+ (N_TXTOFF, N_DATOFF): Use them.
+
+Thu Nov 4 00:33:48 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * aout64.h (RELOC_STD_BITS_RELATIVE_LITTLE): Fixed value to match
+ sun3 system; used to overlap other fields.
+ (RELOC_STD_BITS_JMPTABLE_LITTLE): Likewise.
+
+Wed Nov 3 13:48:27 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * aout64.h (RELOC_STD_BITS_BASEREL_LITTLE): Make it 0x10 (Ken's
+ suggestion) to avoid conflict with RELOC_STD_BITS_EXTERN_LITTLE.
+
+Fri Oct 29 15:09:52 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * hp300hpux.h (N_SHARED_LIB): Define to be 0.
+
+Mon Sep 13 21:00:56 1993 John Gilmore (gnu@cygnus.com)
+
+ * ar.h (ARMAP_TIME_OFFSET): Add and describe.
+
+Mon Aug 23 Sean Fagan (sef@cygnus.com)
+
+ * aout64.h [ARCH_SIZE != 64]: Allow N_BADMAG to be overridden.
+
+Mon Aug 16 14:30:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stab_gnu.h: Include aout/stab.def not just stab.def.
+
+Sun Jul 18 21:41:47 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * dynix3.h: New, for symmetry running dynix.
+
+Thu Jul 8 12:52:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * aout64.h (N_BADMAG): Recognize QMAGIC.
+ N_TXTOFF, N_TXTADDR, N_TXTSIZE: Special code for QMAGIC.
+ N_DATOFF: Pad text size if we need to.
+
+Fri Jun 18 19:19:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * stab.def (N_ECOML): Fix comment.
+
+Mon May 31 09:21:30 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * stab.def: Remove Solaris information on N_FUN stabstring grammar;
+ I've transferred it to gdb/doc/stabs.texinfo, where it belongs.
+
+Mon May 10 05:48:43 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * hp300hpux.h: Patch from Glenn Engel for linker problem and
+ compatibility fix:
+ (OMAGIC, NMAGIC): New definitions.
+ (SHAREMAGIC): Deleted.
+ (HPUX_DOT_O_MAGIC): New macro.
+ (_N_BADMAG): Adjusted.
+ (N_HEADER_IN_TEXT, N_DATADDR): New macros.
+
+Thu Apr 29 12:07:37 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * hp300hpux.h: New file from Glenn Engel, glenne@lsid.hp.com.
+
+Tue Apr 27 05:51:04 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * aout64.h (struct external_exec, *MAGIC, N_BADMAG): Don't define
+ if `external_exec' is already defined as a macro.
+ (N_DATOFF, N_TRELOFF, N_DRELOFF, N_SYMOFF, N_STROFF): Don't define
+ if already defined.
+ (struct external_nlist, EXTERNAL_NLIST_SIZE): Don't define if
+ `external_nlist' is already defined as a macro.
+
+Sat Aug 15 04:23:02 1992 John Gilmore (gnu@cygnus.com)
+
+ * adobe.h: Add description of a.out.adobe format.
+
+Fri Jul 3 00:36:52 1992 John Gilmore (gnu at cygnus.com)
+
+ * stab.def: Update more Solaris definitions.
+ * stab_gnu.h: Add N_SO language types, and Solaris basic float types.
+
+Sun Jun 14 10:53:53 1992 John Gilmore (gnu at cygnus.com)
+
+ * stab.def: Update descriptions of Solaris-2 stabs; add N_UNDF.
+
+Thu Jun 11 01:12:07 1992 John Gilmore (gnu at cygnus.com)
+
+ * stab.def: Add N_OBJ and N_OPT from Solaris-2.
+
+Thu Jan 30 18:12:44 1992 John Gilmore (gnu at cygnus.com)
+
+ * aout/aout64.h: N_TXTSIZE needs some more parentheses.
+ I don't trust C precedence.
+
+Wed Dec 18 14:32:01 1991 Per Bothner (bothner at cygnus.com)
+
+ * aout/aout64.h: Move common sunos-specific test
+ to recognize shared libraries into new macro N_SHARED_LIB.
+ Use it to simplify&reformat N_TXTADDR, N_TXTOFF, N_TXTSIZE.
+
+Sat Nov 30 20:34:52 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * ChangeLog, aout64.h, ar.h, encap.h, host.h, hp.h, ranlib.h,
+ reloc.h, stab.def, stab_gnu.h, sun4.h: All moved from the
+ devo/include directory
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/include/aout/adobe.h b/contrib/gdb/include/aout/adobe.h
new file mode 100644
index 0000000..3d2f15c
--- /dev/null
+++ b/contrib/gdb/include/aout/adobe.h
@@ -0,0 +1,297 @@
+/* `a.out.adobe' differences from standard a.out files */
+
+#ifndef __A_OUT_ADOBE_H__
+#define __A_OUT_ADOBE_H__
+
+#define BYTES_IN_WORD 4
+
+/* Struct external_exec is the same. */
+
+/* This is the layout on disk of the 32-bit or 64-bit exec header. */
+
+struct external_exec
+{
+ bfd_byte e_info[4]; /* magic number and stuff */
+ bfd_byte e_text[BYTES_IN_WORD]; /* length of text section in bytes */
+ bfd_byte e_data[BYTES_IN_WORD]; /* length of data section in bytes */
+ bfd_byte e_bss[BYTES_IN_WORD]; /* length of bss area in bytes */
+ bfd_byte e_syms[BYTES_IN_WORD]; /* length of symbol table in bytes */
+ bfd_byte e_entry[BYTES_IN_WORD]; /* start address */
+ bfd_byte e_trsize[BYTES_IN_WORD]; /* length of text relocation info */
+ bfd_byte e_drsize[BYTES_IN_WORD]; /* length of data relocation info */
+};
+
+#define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7)
+
+/* Magic numbers for a.out files */
+
+#undef ZMAGIC
+#define ZMAGIC 0xAD0BE /* Cute, eh? */
+#undef OMAGIC
+#undef NMAGIC
+
+#define N_BADMAG(x) ((x).a_info != ZMAGIC)
+
+/* By default, segment size is constant. But some machines override this
+ to be a function of the a.out header (e.g. machine type). */
+#ifndef N_SEGSIZE
+#define N_SEGSIZE(x) SEGMENT_SIZE
+#endif
+#undef N_SEGSIZE /* FIXMEXXXX */
+
+/* Segment information for the a.out.Adobe format is specified after the
+ file header. It contains N segment descriptors, followed by one with
+ a type of zero.
+
+ The actual text of the segments starts at N_TXTOFF in the file,
+ regardless of how many or how few segment headers there are. */
+
+struct external_segdesc {
+ unsigned char e_type[1];
+ unsigned char e_size[3];
+ unsigned char e_virtbase[4];
+ unsigned char e_filebase[4];
+};
+
+struct internal_segdesc {
+ unsigned int a_type:8; /* Segment type N_TEXT, N_DATA, 0 */
+ unsigned int a_size:24; /* Segment size */
+ bfd_vma a_virtbase; /* Virtual address */
+ unsigned int a_filebase; /* Base address in object file */
+};
+
+#define N_TXTADDR(x) \
+
+/* This is documented to be at 1024, but appears to really be at 2048.
+ FIXME?! */
+#define N_TXTOFF(x) 2048
+
+#define N_TXTSIZE(x) ((x).a_text)
+
+#define N_DATADDR(x)
+
+#define N_BSSADDR(x)
+
+/* Offsets of the various portions of the file after the text segment. */
+
+#define N_DATOFF(x) ( N_TXTOFF(x) + N_TXTSIZE(x) )
+#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data )
+#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
+#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize )
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+
+/* Symbols */
+struct external_nlist {
+ bfd_byte e_strx[BYTES_IN_WORD]; /* index into string table of name */
+ bfd_byte e_type[1]; /* type of symbol */
+ bfd_byte e_other[1]; /* misc info (usually empty) */
+ bfd_byte e_desc[2]; /* description field */
+ bfd_byte e_value[BYTES_IN_WORD]; /* value of symbol */
+};
+
+#define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD)
+
+struct internal_nlist {
+ unsigned long n_strx; /* index into string table of name */
+ unsigned char n_type; /* type of symbol */
+ unsigned char n_other; /* misc info (usually empty) */
+ unsigned short n_desc; /* description field */
+ bfd_vma n_value; /* value of symbol */
+};
+
+/* The n_type field is the symbol type, containing: */
+
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol -- defined at particular addr */
+#define N_TEXT 4 /* Text sym -- defined at offset in text seg */
+#define N_DATA 6 /* Data sym -- defined at offset in data seg */
+#define N_BSS 8 /* BSS sym -- defined at offset in zero'd seg */
+#define N_COMM 0x12 /* Common symbol (visible after shared lib dynlink) */
+#define N_FN 0x1f /* File name of .o file */
+#define N_FN_SEQ 0x0C /* N_FN from Sequent compilers (sigh) */
+/* Note: N_EXT can only be usefully OR-ed with N_UNDF, N_ABS, N_TEXT,
+ N_DATA, or N_BSS. When the low-order bit of other types is set,
+ (e.g. N_WARNING versus N_FN), they are two different types. */
+#define N_EXT 1 /* External symbol (as opposed to local-to-this-file) */
+#define N_TYPE 0x1e
+#define N_STAB 0xe0 /* If any of these bits are on, it's a debug symbol */
+
+#define N_INDR 0x0a
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ elements value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+/* Warning symbol. The text gives a warning message, the next symbol
+ in the table will be undefined. When the symbol is referenced, the
+ message is printed. */
+
+#define N_WARNING 0x1e
+
+/* Relocations
+
+ There are two types of relocation flavours for a.out systems,
+ standard and extended. The standard form is used on systems where the
+ instruction has room for all the bits of an offset to the operand, whilst
+ the extended form is used when an address operand has to be split over n
+ instructions. Eg, on the 68k, each move instruction can reference
+ the target with a displacement of 16 or 32 bits. On the sparc, move
+ instructions use an offset of 14 bits, so the offset is stored in
+ the reloc field, and the data in the section is ignored.
+*/
+
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct reloc_std_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ 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_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_SH_LITTLE 1
+
+#define RELOC_STD_BITS_EXTERN_BIG 0x10
+#define RELOC_STD_BITS_EXTERN_LITTLE 0x08
+
+#define RELOC_STD_BITS_BASEREL_BIG 0x08
+#define RELOC_STD_BITS_BASEREL_LITTLE 0x08
+
+#define RELOC_STD_BITS_JMPTABLE_BIG 0x04
+#define RELOC_STD_BITS_JMPTABLE_LITTLE 0x04
+
+#define RELOC_STD_BITS_RELATIVE_BIG 0x02
+#define RELOC_STD_BITS_RELATIVE_LITTLE 0x02
+
+#define RELOC_STD_SIZE (BYTES_IN_WORD + 3 + 1) /* Bytes per relocation entry */
+
+struct reloc_std_internal
+{
+ bfd_vma r_address; /* Address (within segment) to be relocated. */
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in files the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* The next three bits are for SunOS shared libraries, and seem to
+ be undocumented. */
+ unsigned int r_baserel:1; /* Linkage table relative */
+ unsigned int r_jmptable:1; /* pc-relative to jump table */
+ unsigned int r_relative:1; /* "relative relocation" */
+ /* unused */
+ unsigned int r_pad:1; /* Padding -- set to zero */
+};
+
+
+/* EXTENDED RELOCS */
+
+struct reloc_ext_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ bfd_byte r_type[1]; /* relocation type */
+ 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_TYPE_BIG 0x1F
+#define RELOC_EXT_BITS_TYPE_SH_BIG 0
+#define RELOC_EXT_BITS_TYPE_LITTLE 0xF8
+#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
+
+/* Bytes per relocation entry */
+#define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD)
+
+enum reloc_type
+{
+ /* simple relocations */
+ RELOC_8, /* data[0:7] = addend + sv */
+ RELOC_16, /* data[0:15] = addend + sv */
+ RELOC_32, /* data[0:31] = addend + sv */
+ /* pc-rel displacement */
+ RELOC_DISP8, /* data[0:7] = addend - pc + sv */
+ RELOC_DISP16, /* data[0:15] = addend - pc + sv */
+ RELOC_DISP32, /* data[0:31] = addend - pc + sv */
+ /* Special */
+ RELOC_WDISP30, /* data[0:29] = (addend + sv - pc)>>2 */
+ RELOC_WDISP22, /* data[0:21] = (addend + sv - pc)>>2 */
+ RELOC_HI22, /* data[0:21] = (addend + sv)>>10 */
+ RELOC_22, /* data[0:21] = (addend + sv) */
+ RELOC_13, /* data[0:12] = (addend + sv) */
+ RELOC_LO10, /* data[0:9] = (addend + sv) */
+ RELOC_SFA_BASE,
+ RELOC_SFA_OFF13,
+ /* P.I.C. (base-relative) */
+ RELOC_BASE10, /* Not sure - maybe we can do this the */
+ RELOC_BASE13, /* right way now */
+ RELOC_BASE22,
+ /* for some sort of pc-rel P.I.C. (?) */
+ RELOC_PC10,
+ RELOC_PC22,
+ /* P.I.C. jump table */
+ RELOC_JMP_TBL,
+ /* reputedly for shared libraries somehow */
+ RELOC_SEGOFF16,
+ RELOC_GLOB_DAT,
+ RELOC_JMP_SLOT,
+ RELOC_RELATIVE,
+
+ RELOC_11,
+ RELOC_WDISP2_14,
+ RELOC_WDISP19,
+ RELOC_HHI22, /* data[0:21] = (addend + sv) >> 42 */
+ RELOC_HLO10, /* data[0:9] = (addend + sv) >> 32 */
+
+ /* 29K relocation types */
+ RELOC_JUMPTARG,
+ RELOC_CONST,
+ RELOC_CONSTH,
+
+ NO_RELOC
+ };
+
+
+struct reloc_internal {
+ bfd_vma r_address; /* offset of of data to relocate */
+ long r_index; /* symbol table index of symbol */
+ enum reloc_type r_type; /* relocation type */
+ bfd_vma r_addend; /* datum addend */
+};
+
+#endif /* __A_OUT_ADOBE_H__ */
diff --git a/contrib/gdb/include/aout/aout64.h b/contrib/gdb/include/aout/aout64.h
new file mode 100644
index 0000000..76f1140
--- /dev/null
+++ b/contrib/gdb/include/aout/aout64.h
@@ -0,0 +1,475 @@
+/* `a.out' object-file definitions, including extensions to 64-bit fields */
+
+#ifndef __A_OUT_64_H__
+#define __A_OUT_64_H__
+
+/* This is the layout on disk of the 32-bit or 64-bit exec header. */
+
+#ifndef external_exec
+struct external_exec
+{
+ bfd_byte e_info[4]; /* magic number and stuff */
+ bfd_byte e_text[BYTES_IN_WORD]; /* length of text section in bytes */
+ bfd_byte e_data[BYTES_IN_WORD]; /* length of data section in bytes */
+ bfd_byte e_bss[BYTES_IN_WORD]; /* length of bss area in bytes */
+ bfd_byte e_syms[BYTES_IN_WORD]; /* length of symbol table in bytes */
+ bfd_byte e_entry[BYTES_IN_WORD]; /* start address */
+ bfd_byte e_trsize[BYTES_IN_WORD]; /* length of text relocation info */
+ bfd_byte e_drsize[BYTES_IN_WORD]; /* length of data relocation info */
+};
+
+#define EXEC_BYTES_SIZE (4 + BYTES_IN_WORD * 7)
+
+/* Magic numbers for a.out files */
+
+#if ARCH_SIZE==64
+#define OMAGIC 0x1001 /* Code indicating object file */
+#define ZMAGIC 0x1002 /* Code indicating demand-paged executable. */
+#define NMAGIC 0x1003 /* Code indicating pure executable. */
+
+/* There is no 64-bit QMAGIC as far as I know. */
+
+#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC)
+#else
+#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.
+ It is used by 386BSD (and variants) and Linux, at least. */
+#ifndef QMAGIC
+#define QMAGIC 0314
+#endif
+# ifndef N_BADMAG
+# define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC \
+ && N_MAGIC(x) != QMAGIC)
+# endif /* N_BADMAG */
+#endif
+
+#endif
+
+#ifdef QMAGIC
+#define N_IS_QMAGIC(x) (N_MAGIC (x) == QMAGIC)
+#else
+#define N_IS_QMAGIC(x) (0)
+#endif
+
+/* The difference between TARGET_PAGE_SIZE and N_SEGSIZE is that TARGET_PAGE_SIZE is
+ 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
+ text segment and the data segment (in memory; on disk the padding
+ between them is TARGET_PAGE_SIZE). TARGET_PAGE_SIZE and N_SEGSIZE are the same
+ for most machines, but different for sun3. */
+
+/* By default, segment size is constant. But some machines override this
+ to be a function of the a.out header (e.g. machine type). */
+
+#ifndef N_SEGSIZE
+#define N_SEGSIZE(x) SEGMENT_SIZE
+#endif
+
+/* Virtual memory address of the text section.
+ This is getting very complicated. A good reason to discard a.out format
+ for something that specifies these fields explicitly. But til then...
+
+ * OMAGIC and NMAGIC files:
+ (object files: text for "relocatable addr 0" right after the header)
+ start at 0, offset is EXEC_BYTES_SIZE, size as stated.
+ * The text address, offset, and size of ZMAGIC files depend
+ on the entry point of the file:
+ * entry point below TEXT_START_ADDR:
+ (hack for SunOS shared libraries)
+ start at 0, offset is 0, size as stated.
+ * If N_HEADER_IN_TEXT(x) is true (which defaults to being the
+ case when the entry point is EXEC_BYTES_SIZE or further into a page):
+ no padding is needed; text can start after exec header. Sun
+ considers the text segment of such files to include the exec header;
+ for BFD's purposes, we don't, which makes more work for us.
+ start at TEXT_START_ADDR + EXEC_BYTES_SIZE, offset is EXEC_BYTES_SIZE,
+ size as stated minus EXEC_BYTES_SIZE.
+ * If N_HEADER_IN_TEXT(x) is false (which defaults to being the case when
+ the entry point is less than EXEC_BYTES_SIZE into a page (e.g. page
+ aligned)): (padding is needed so that text can start at a page boundary)
+ start at TEXT_START_ADDR, offset TARGET_PAGE_SIZE, size as stated.
+
+ Specific configurations may want to hardwire N_HEADER_IN_TEXT,
+ for efficiency or to allow people to play games with the entry point.
+ In that case, you would #define N_HEADER_IN_TEXT(x) as 1 for sunos,
+ and as 0 for most other hosts (Sony News, Vax Ultrix, etc).
+ (Do this in the appropriate bfd target file.)
+ (The default is a heuristic that will break if people try changing
+ the entry point, perhaps with the ld -e flag.)
+
+ * QMAGIC is always like a ZMAGIC for which N_HEADER_IN_TEXT is true,
+ and for which the starting address is TARGET_PAGE_SIZE (or should this be
+ SEGMENT_SIZE?) (TEXT_START_ADDR only applies to ZMAGIC, not to QMAGIC).
+ */
+
+/* This macro is only relevant for ZMAGIC files; QMAGIC always has the header
+ in the text. */
+#ifndef N_HEADER_IN_TEXT
+#define N_HEADER_IN_TEXT(x) (((x).a_entry & (TARGET_PAGE_SIZE-1)) >= EXEC_BYTES_SIZE)
+#endif
+
+/* Sun shared libraries, not linux. This macro is only relevant for ZMAGIC
+ files. */
+#ifndef N_SHARED_LIB
+#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, */ \
+ /* with the header in the text. */ \
+ N_IS_QMAGIC (x) ? TARGET_PAGE_SIZE + EXEC_BYTES_SIZE : \
+ N_MAGIC(x) != ZMAGIC ? 0 : /* object file or NMAGIC */\
+ N_SHARED_LIB(x) ? 0 : \
+ N_HEADER_IN_TEXT(x) ? \
+ TEXT_START_ADDR + EXEC_BYTES_SIZE : /* no padding */\
+ TEXT_START_ADDR /* a page of padding */\
+ )
+#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 TARGET_PAGE_SIZE. But for Linux, in the
+ time-honored tradition of crazy ZMAGIC hacks, it is 1024 which is
+ not what TARGET_PAGE_SIZE needs to be for QMAGIC. */
+
+#ifndef ZMAGIC_DISK_BLOCK_SIZE
+#define ZMAGIC_DISK_BLOCK_SIZE TARGET_PAGE_SIZE
+#endif
+
+#define N_DISK_BLOCK_SIZE(x) \
+ (N_MAGIC(x) == ZMAGIC ? ZMAGIC_DISK_BLOCK_SIZE : TARGET_PAGE_SIZE)
+
+/* Offset in an a.out of the start of the text section. */
+#ifndef N_TXTOFF
+#define N_TXTOFF(x) \
+ (/* For {O,N,Q}MAGIC, no padding. */ \
+ N_MAGIC(x) != ZMAGIC ? EXEC_BYTES_SIZE : \
+ N_SHARED_LIB(x) ? 0 : \
+ N_HEADER_IN_TEXT(x) ? \
+ EXEC_BYTES_SIZE : /* no padding */\
+ ZMAGIC_DISK_BLOCK_SIZE /* a page of padding */\
+ )
+#endif
+/* Size of the text section. It's always as stated, except that we
+ offset it to `undo' the adjustment to N_TXTADDR and N_TXTOFF
+ for ZMAGIC files that nominally include the exec header
+ as part of the first page of text. (BFD doesn't consider the
+ exec header to be part of the text segment.) */
+#ifndef N_TXTSIZE
+#define N_TXTSIZE(x) \
+ (/* For QMAGIC, we don't consider the header part of the text section. */\
+ N_IS_QMAGIC (x) ? (x).a_text - EXEC_BYTES_SIZE : \
+ (N_MAGIC(x) != ZMAGIC || N_SHARED_LIB(x)) ? (x).a_text : \
+ N_HEADER_IN_TEXT(x) ? \
+ (x).a_text - EXEC_BYTES_SIZE: /* no padding */\
+ (x).a_text /* a page of padding */\
+ )
+#endif
+/* The address of the data segment in virtual memory.
+ It is the text segment address, plus text segment size, rounded
+ up to a N_SEGSIZE boundary for pure or pageable files. */
+#ifndef N_DATADDR
+#define N_DATADDR(x) \
+ (N_MAGIC(x)==OMAGIC? (N_TXTADDR(x)+N_TXTSIZE(x)) \
+ : (N_SEGSIZE(x) + ((N_TXTADDR(x)+N_TXTSIZE(x)-1) & ~(N_SEGSIZE(x)-1))))
+#endif
+/* The address of the BSS segment -- immediately after the data segment. */
+
+#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
+
+/* Offsets of the various portions of the file after the text segment. */
+
+/* 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_TXTOFF(x) + N_TXTSIZE(x))
+#endif
+
+#ifndef N_TRELOFF
+#define N_TRELOFF(x) ( N_DATOFF(x) + (x).a_data )
+#endif
+#ifndef N_DRELOFF
+#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
+#endif
+#ifndef N_SYMOFF
+#define N_SYMOFF(x) ( N_DRELOFF(x) + (x).a_drsize )
+#endif
+#ifndef N_STROFF
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+#endif
+
+/* Symbols */
+#ifndef external_nlist
+struct external_nlist {
+ bfd_byte e_strx[BYTES_IN_WORD]; /* index into string table of name */
+ bfd_byte e_type[1]; /* type of symbol */
+ bfd_byte e_other[1]; /* misc info (usually empty) */
+ bfd_byte e_desc[2]; /* description field */
+ bfd_byte e_value[BYTES_IN_WORD]; /* value of symbol */
+};
+#define EXTERNAL_NLIST_SIZE (BYTES_IN_WORD+4+BYTES_IN_WORD)
+#endif
+
+struct internal_nlist {
+ unsigned long n_strx; /* index into string table of name */
+ unsigned char n_type; /* type of symbol */
+ unsigned char n_other; /* misc info (usually empty) */
+ unsigned short n_desc; /* description field */
+ bfd_vma n_value; /* value of symbol */
+};
+
+/* The n_type field is the symbol type, containing: */
+
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol -- defined at particular addr */
+#define N_TEXT 4 /* Text sym -- defined at offset in text seg */
+#define N_DATA 6 /* Data sym -- defined at offset in data seg */
+#define N_BSS 8 /* BSS sym -- defined at offset in zero'd seg */
+#define N_COMM 0x12 /* Common symbol (visible after shared lib dynlink) */
+#define N_FN 0x1f /* File name of .o file */
+#define N_FN_SEQ 0x0C /* N_FN from Sequent compilers (sigh) */
+/* Note: N_EXT can only be usefully OR-ed with N_UNDF, N_ABS, N_TEXT,
+ N_DATA, or N_BSS. When the low-order bit of other types is set,
+ (e.g. N_WARNING versus N_FN), they are two different types. */
+#define N_EXT 1 /* External symbol (as opposed to local-to-this-file) */
+#define N_TYPE 0x1e
+#define N_STAB 0xe0 /* If any of these bits are on, it's a debug symbol */
+
+#define N_INDR 0x0a
+
+/* The following symbols refer to set elements.
+ All the N_SET[ATDB] symbols with the same name form one set.
+ Space is allocated for the set in the text section, and each set
+ elements value is stored into one word of the space.
+ The first word of the space is the length of the set (number of elements).
+
+ The address of the set is made into an N_SETV symbol
+ whose name is the same as the name of the set.
+ This symbol acts like a N_DATA global symbol
+ in that it can satisfy undefined external references. */
+
+/* These appear as input to LD, in a .o file. */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1A /* Bss set element symbol */
+
+/* This is output from LD. */
+#define N_SETV 0x1C /* Pointer to set vector in data area. */
+
+/* Warning symbol. The text gives a warning message, the next symbol
+ in the table will be undefined. When the symbol is referenced, the
+ message is printed. */
+
+#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,
+ standard and extended. The standard form is used on systems where the
+ instruction has room for all the bits of an offset to the operand, whilst
+ the extended form is used when an address operand has to be split over n
+ instructions. Eg, on the 68k, each move instruction can reference
+ the target with a displacement of 16 or 32 bits. On the sparc, move
+ instructions use an offset of 14 bits, so the offset is stored in
+ the reloc field, and the data in the section is ignored.
+*/
+
+/* This structure describes a single relocation to be performed.
+ The text-relocation section of the file is a vector of these structures,
+ all of which apply to the text section.
+ Likewise, the data-relocation section applies to the data section. */
+
+struct reloc_std_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ bfd_byte r_type[1]; /* relocation type */
+};
+
+#define RELOC_STD_BITS_PCREL_BIG ((unsigned int) 0x80)
+#define RELOC_STD_BITS_PCREL_LITTLE ((unsigned int) 0x01)
+
+#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 ((unsigned int) 0x10)
+#define RELOC_STD_BITS_EXTERN_LITTLE ((unsigned int) 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 ((unsigned int) 0x04)
+#define RELOC_STD_BITS_JMPTABLE_LITTLE ((unsigned int) 0x20)
+
+#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 */
+
+struct reloc_std_internal
+{
+ bfd_vma r_address; /* Address (within segment) to be relocated. */
+ /* The meaning of r_symbolnum depends on r_extern. */
+ unsigned int r_symbolnum:24;
+ /* Nonzero means value is a pc-relative offset
+ and it should be relocated for changes in its own address
+ as well as for changes in the symbol or section specified. */
+ unsigned int r_pcrel:1;
+ /* Length (as exponent of 2) of the field to be relocated.
+ Thus, a value of 2 indicates 1<<2 bytes. */
+ unsigned int r_length:2;
+ /* 1 => relocate with value of symbol.
+ r_symbolnum is the index of the symbol
+ in files the symbol table.
+ 0 => relocate with the address of a segment.
+ r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
+ (the N_EXT bit may be set also, but signifies nothing). */
+ unsigned int r_extern:1;
+ /* The next three bits are for SunOS shared libraries, and seem to
+ be undocumented. */
+ unsigned int r_baserel:1; /* Linkage table relative */
+ unsigned int r_jmptable:1; /* pc-relative to jump table */
+ unsigned int r_relative:1; /* "relative relocation" */
+ /* unused */
+ unsigned int r_pad:1; /* Padding -- set to zero */
+};
+
+
+/* EXTENDED RELOCS */
+
+struct reloc_ext_external {
+ bfd_byte r_address[BYTES_IN_WORD]; /* offset of of data to relocate */
+ bfd_byte r_index[3]; /* symbol table index of symbol */
+ bfd_byte r_type[1]; /* relocation type */
+ bfd_byte r_addend[BYTES_IN_WORD]; /* datum addend */
+};
+
+#define RELOC_EXT_BITS_EXTERN_BIG ((unsigned int) 0x80)
+#define RELOC_EXT_BITS_EXTERN_LITTLE ((unsigned int) 0x01)
+
+#define RELOC_EXT_BITS_TYPE_BIG ((unsigned int) 0x1F)
+#define RELOC_EXT_BITS_TYPE_SH_BIG 0
+#define RELOC_EXT_BITS_TYPE_LITTLE ((unsigned int) 0xF8)
+#define RELOC_EXT_BITS_TYPE_SH_LITTLE 3
+
+/* Bytes per relocation entry */
+#define RELOC_EXT_SIZE (BYTES_IN_WORD + 3 + 1 + BYTES_IN_WORD)
+
+enum reloc_type
+{
+ /* simple relocations */
+ RELOC_8, /* data[0:7] = addend + sv */
+ RELOC_16, /* data[0:15] = addend + sv */
+ RELOC_32, /* data[0:31] = addend + sv */
+ /* pc-rel displacement */
+ RELOC_DISP8, /* data[0:7] = addend - pc + sv */
+ RELOC_DISP16, /* data[0:15] = addend - pc + sv */
+ RELOC_DISP32, /* data[0:31] = addend - pc + sv */
+ /* Special */
+ RELOC_WDISP30, /* data[0:29] = (addend + sv - pc)>>2 */
+ RELOC_WDISP22, /* data[0:21] = (addend + sv - pc)>>2 */
+ RELOC_HI22, /* data[0:21] = (addend + sv)>>10 */
+ RELOC_22, /* data[0:21] = (addend + sv) */
+ RELOC_13, /* data[0:12] = (addend + sv) */
+ RELOC_LO10, /* data[0:9] = (addend + sv) */
+ RELOC_SFA_BASE,
+ RELOC_SFA_OFF13,
+ /* P.I.C. (base-relative) */
+ RELOC_BASE10, /* Not sure - maybe we can do this the */
+ RELOC_BASE13, /* right way now */
+ RELOC_BASE22,
+ /* for some sort of pc-rel P.I.C. (?) */
+ RELOC_PC10,
+ RELOC_PC22,
+ /* P.I.C. jump table */
+ RELOC_JMP_TBL,
+ /* reputedly for shared libraries somehow */
+ RELOC_SEGOFF16,
+ RELOC_GLOB_DAT,
+ RELOC_JMP_SLOT,
+ RELOC_RELATIVE,
+
+ RELOC_11,
+ RELOC_WDISP2_14,
+ RELOC_WDISP19,
+ RELOC_HHI22, /* data[0:21] = (addend + sv) >> 42 */
+ RELOC_HLO10, /* data[0:9] = (addend + sv) >> 32 */
+
+ /* 29K relocation types */
+ RELOC_JUMPTARG,
+ 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
+ understand ? Should we sort the values ? What about using a
+ microcode format like the 68k ?
+ */
+ NO_RELOC
+ };
+
+
+struct reloc_internal {
+ bfd_vma r_address; /* offset of of data to relocate */
+ long r_index; /* symbol table index of symbol */
+ enum reloc_type r_type; /* relocation type */
+ bfd_vma r_addend; /* datum addend */
+};
+
+/* Q.
+ Should the length of the string table be 4 bytes or 8 bytes ?
+
+ Q.
+ What about archive indexes ?
+
+ */
+
+#endif /* __A_OUT_64_H__ */
diff --git a/contrib/gdb/include/aout/ar.h b/contrib/gdb/include/aout/ar.h
new file mode 100644
index 0000000..7b5dcda
--- /dev/null
+++ b/contrib/gdb/include/aout/ar.h
@@ -0,0 +1,36 @@
+/* archive file definition for GNU software */
+
+/* So far this is correct for BSDish archives. Don't forget that
+ files must begin on an even byte boundary. */
+
+#ifndef __GNU_AR_H__
+#define __GNU_AR_H__
+
+/* 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 "!<arch>\012" /* For COFF and a.out archives */
+#define ARMAGB "!<bout>\012" /* For b.out archives */
+#define SARMAG 8
+#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
+ BSD-derived linkers complain. We originally write the ar_date with
+ this offset from the real file's mod-time. After finishing the
+ file, we rewrite ar_date if it's not still greater than the mod date. */
+
+#define ARMAP_TIME_OFFSET 60
+
+struct ar_hdr {
+ char ar_name[16]; /* name of this member */
+ char ar_date[12]; /* file mtime */
+ char ar_uid[6]; /* owner uid; printed as decimal */
+ char ar_gid[6]; /* owner gid; printed as decimal */
+ char ar_mode[8]; /* file mode, printed as octal */
+ char ar_size[10]; /* file size, printed as decimal */
+ char ar_fmag[2]; /* should contain ARFMAG */
+};
+
+#endif /* __GNU_AR_H__ */
diff --git a/contrib/gdb/include/aout/dynix3.h b/contrib/gdb/include/aout/dynix3.h
new file mode 100644
index 0000000..efeeebf
--- /dev/null
+++ b/contrib/gdb/include/aout/dynix3.h
@@ -0,0 +1,71 @@
+/*
+ * a.out specifics for Sequent Symmetry running Dynix 3.x
+ */
+#ifndef A_OUT_DYNIX3_H
+#define A_OUT_DYNIX3_H
+
+#define external_exec dynix_external_exec
+
+/* struct exec for Dynix 3
+ *
+ * a_gdtbl and a_bootstrap are only for standalone binaries.
+ * Shared data fields are not supported by the kernel as of Dynix 3.1,
+ * but are supported by Dynix compiler programs.
+ */
+struct dynix_external_exec {
+ unsigned char e_info[4];
+ unsigned char e_text[4];
+ unsigned char e_data[4];
+ unsigned char e_bss[4];
+ unsigned char e_syms[4];
+ unsigned char e_entry[4];
+ unsigned char e_trsize[4];
+ unsigned char e_drsize[4];
+ unsigned char e_g_code[8], e_g_data[8], e_g_desc[8];
+ unsigned char e_shdata[4];
+ unsigned char e_shbss[4];
+ unsigned char e_shdrsize[4];
+ unsigned char e_bootstrap[44];
+ unsigned char e_reserved[12];
+ unsigned char e_version[4];
+};
+
+#define EXEC_BYTES_SIZE (128)
+
+/*
+ * All executables under Dynix are demand paged with read-only text,
+ * Thus no NMAGIC.
+ *
+ * ZMAGIC has a page of 0s at virtual 0,
+ * XMAGIC has an invalid page at virtual 0
+ */
+#define OMAGIC 0x12eb /* .o */
+#define ZMAGIC 0x22eb /* zero @ 0, demand load */
+#define XMAGIC 0x32eb /* invalid @ 0, demand load */
+#define SMAGIC 0x42eb /* standalone, not supported here */
+
+#define N_BADMAG(x) ((OMAGIC != N_MAGIC(x)) && \
+ (ZMAGIC != N_MAGIC(x)) && \
+ (XMAGIC != N_MAGIC(x)) && \
+ (SMAGIC != N_MAGIC(x)))
+
+#define N_ADDRADJ(x) ((ZMAGIC == N_MAGIC(x) || XMAGIC == N_MAGIC(x)) ? 0x1000 : 0)
+
+#define N_TXTOFF(x) (EXEC_BYTES_SIZE)
+#define N_DATOFF(x) (N_TXTOFF(x) + N_TXTSIZE(x))
+#define N_SHDATOFF(x) (N_DATOFF(x) + (x).a_data)
+#define N_TRELOFF(x) (N_SHDATOFF(x) + (x).a_shdata)
+#define N_DRELOFF(x) (N_TRELOFF(x) + (x).a_trsize)
+#define N_SHDRELOFF(x) (N_DRELOFF(x) + (x).a_drsize)
+#define N_SYMOFF(x) (N_SHDRELOFF(x) + (x).a_shdrsize)
+#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms)
+
+#define N_TXTADDR(x) \
+ (((OMAGIC == N_MAGIC(x)) || (SMAGIC == N_MAGIC(x))) ? 0 \
+ : TEXT_START_ADDR + EXEC_BYTES_SIZE)
+
+#define N_TXTSIZE(x) \
+ (((OMAGIC == N_MAGIC(x)) || (SMAGIC == N_MAGIC(x))) ? ((x).a_text) \
+ : ((x).a_text - N_ADDRADJ(x) - EXEC_BYTES_SIZE))
+
+#endif /* A_OUT_DYNIX3_H */
diff --git a/contrib/gdb/include/aout/encap.h b/contrib/gdb/include/aout/encap.h
new file mode 100644
index 0000000..b215d49
--- /dev/null
+++ b/contrib/gdb/include/aout/encap.h
@@ -0,0 +1,135 @@
+/* Yet Another Try at encapsulating bsd object files in coff.
+ Copyright (C) 1988, 1989, 1991 Free Software Foundation, Inc.
+ Written by Pace Willisson 12/9/88
+
+ This file is obsolete. It needs to be converted to just define a bunch
+ of stuff that BFD can use to do coff-encapsulated files. --gnu@cygnus.com
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * We only use the coff headers to tell the kernel
+ * how to exec the file. Therefore, the only fields that need to
+ * be filled in are the scnptr and vaddr for the text and data
+ * sections, and the vaddr for the bss. As far as coff is concerned,
+ * there is no symbol table, relocation, or line numbers.
+ *
+ * A normal bsd header (struct exec) is placed after the coff headers,
+ * and before the real text. I defined a the new fields 'a_machtype'
+ * and a_flags. If a_machtype is M_386, and a_flags & A_ENCAP is
+ * true, then the bsd header is preceeded by a coff header. Macros
+ * like N_TXTOFF and N_TXTADDR use this field to find the bsd header.
+ *
+ * The only problem is to track down the bsd exec header. The
+ * macros HEADER_OFFSET, etc do this.
+ */
+
+#define N_FLAGS_COFF_ENCAPSULATE 0x20 /* coff header precedes bsd header */
+
+/* Describe the COFF header used for encapsulation. */
+
+struct coffheader
+{
+ /* filehdr */
+ unsigned short f_magic;
+ unsigned short f_nscns;
+ long f_timdat;
+ long f_symptr;
+ long f_nsyms;
+ unsigned short f_opthdr;
+ unsigned short f_flags;
+ /* aouthdr */
+ short magic;
+ short vstamp;
+ long tsize;
+ long dsize;
+ long bsize;
+ long entry;
+ long text_start;
+ long data_start;
+ struct coffscn
+ {
+ char s_name[8];
+ long s_paddr;
+ long s_vaddr;
+ long s_size;
+ long s_scnptr;
+ long s_relptr;
+ long s_lnnoptr;
+ unsigned short s_nreloc;
+ unsigned short s_nlnno;
+ long s_flags;
+ } scns[3];
+};
+
+/* Describe some of the parameters of the encapsulation,
+ including how to find the encapsulated BSD header. */
+
+/* FIXME, this is dumb. The same tools can't handle a.outs for different
+ architectures, just because COFF_MAGIC is different; so you need a
+ separate GNU nm for every architecture!!? Unfortunately, it needs to
+ be this way, since the COFF_MAGIC value is determined by the kernel
+ we're trying to fool here. */
+
+#define COFF_MAGIC_I386 0514 /* I386MAGIC */
+#define COFF_MAGIC_M68K 0520 /* MC68MAGIC */
+#define COFF_MAGIC_A29K 0x17A /* Used by asm29k cross-tools */
+
+#ifdef COFF_MAGIC
+short __header_offset_temp;
+#define HEADER_OFFSET(f) \
+ (__header_offset_temp = 0, \
+ fread ((char *)&__header_offset_temp, sizeof (short), 1, (f)), \
+ fseek ((f), -sizeof (short), 1), \
+ __header_offset_temp==COFF_MAGIC ? sizeof(struct coffheader) : 0)
+#else
+#define HEADER_OFFSET(f) 0
+#endif
+
+#define HEADER_SEEK(f) (fseek ((f), HEADER_OFFSET((f)), 1))
+
+/* Describe the characteristics of the BSD header
+ that appears inside the encapsulation. */
+
+/* Encapsulated coff files that are linked ZMAGIC have a text segment
+ offset just past the header (and a matching TXTADDR), excluding
+ the headers from the text segment proper but keeping the physical
+ layout and the virtual memory layout page-aligned.
+
+ Non-encapsulated a.out files that are linked ZMAGIC have a text
+ segment that starts at 0 and an N_TXTADR similarly offset to 0.
+ They too are page-aligned with each other, but they include the
+ a.out header as part of the text.
+
+ The _N_HDROFF gets sizeof struct exec added to it, so we have
+ to compensate here. See <a.out.gnu.h>. */
+
+#undef _N_HDROFF
+#undef N_TXTADDR
+#undef N_DATADDR
+
+#define _N_HDROFF(x) ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
+ sizeof (struct coffheader) : 0)
+
+/* Address of text segment in memory after it is loaded. */
+#define N_TXTADDR(x) \
+ ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
+ sizeof (struct coffheader) + sizeof (struct exec) : 0)
+#define SEGMENT_SIZE 0x400000
+
+#define N_DATADDR(x) \
+ ((N_FLAGS(x) & N_FLAGS_COFF_ENCAPSULATE) ? \
+ (SEGMENT_SIZE + ((N_TXTADDR(x)+(x).a_text-1) & ~(SEGMENT_SIZE-1))) : \
+ (N_TXTADDR(x)+(x).a_text))
diff --git a/contrib/gdb/include/aout/host.h b/contrib/gdb/include/aout/host.h
new file mode 100644
index 0000000..8e36212
--- /dev/null
+++ b/contrib/gdb/include/aout/host.h
@@ -0,0 +1,22 @@
+/* Parameters about the a.out format, based on the host system on which
+ the program is compiled. */
+
+/* Address of data segment in memory after it is loaded.
+ It is up to you to define SEGMENT_SIZE
+ on machines not listed here. */
+#ifndef SEGMENT_SIZE
+#if defined(hp300) || defined(pyr)
+#define SEGMENT_SIZE page_size
+#endif
+#ifdef sony
+#define SEGMENT_SIZE 0x1000
+#endif /* Sony. */
+#ifdef is68k
+#define SEGMENT_SIZE 0x20000
+#endif
+#if defined(m68k) && defined(PORTAR)
+#define TARGET_PAGE_SIZE 0x400
+#define SEGMENT_SIZE TARGET_PAGE_SIZE
+#endif
+#endif /*!defined(SEGMENT_SIZE)*/
+
diff --git a/contrib/gdb/include/aout/hp.h b/contrib/gdb/include/aout/hp.h
new file mode 100644
index 0000000..002f49c
--- /dev/null
+++ b/contrib/gdb/include/aout/hp.h
@@ -0,0 +1,82 @@
+/* Special version of <a.out.h> for use under hp-ux.
+ Copyright 1988, 1991 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* THIS FILE IS OBSOLETE. It needs to be revised as a variant "external"
+ a.out format for use with BFD. */
+
+/* The `exec' structure and overall layout must be close to HP's when
+ we are running on an HP system, otherwise we will not be able to
+ execute the resulting file. */
+
+/* Allow this file to be included twice. */
+#ifndef __GNU_EXEC_MACROS__
+
+struct exec
+{
+ unsigned short a_machtype; /* machine type */
+ unsigned short a_magic; /* magic number */
+ unsigned long a_spare1;
+ unsigned long a_spare2;
+ unsigned long a_text; /* length of text, in bytes */
+ unsigned long a_data; /* length of data, in bytes */
+ unsigned long a_bss; /* length of uninitialized data area for file, in bytes */
+ unsigned long a_trsize; /* length of relocation info for text, in bytes */
+ unsigned long a_drsize; /* length of relocation info for data, in bytes */
+ unsigned long a_spare3; /* HP = pascal interface size */
+ unsigned long a_spare4; /* HP = symbol table size */
+ unsigned long a_spare5; /* HP = debug name table size */
+ unsigned long a_entry; /* start address */
+ unsigned long a_spare6; /* HP = source line table size */
+ unsigned long a_spare7; /* HP = value table size */
+ unsigned long a_syms; /* length of symbol table data in file, in bytes */
+ unsigned long a_spare8;
+};
+
+/* Tell a.out.gnu.h not to define `struct exec'. */
+#define __STRUCT_EXEC_OVERRIDE__
+
+#include "../a.out.gnu.h"
+
+#undef N_MAGIC
+#undef N_MACHTYPE
+#undef N_FLAGS
+#undef N_SET_INFO
+#undef N_SET_MAGIC
+#undef N_SET_MACHTYPE
+#undef N_SET_FLAGS
+
+#define N_MAGIC(exec) ((exec) . a_magic)
+#define N_MACHTYPE(exec) ((exec) . a_machtype)
+#define N_SET_MAGIC(exec, magic) (((exec) . a_magic) = (magic))
+#define N_SET_MACHTYPE(exec, machtype) (((exec) . a_machtype) = (machtype))
+
+#undef N_BADMAG
+#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x)))
+
+#define _N_BADMACH(x) \
+(((N_MACHTYPE (x)) != HP9000S200_ID) && \
+ ((N_MACHTYPE (x)) != HP98x6_ID))
+
+#define HP98x6_ID 0x20A
+#define HP9000S200_ID 0x20C
+
+#undef _N_HDROFF
+#define _N_HDROFF(x) (SEGMENT_SIZE - (sizeof (struct exec)))
+
+#define SEGMENT_SIZE 0x1000
+
+#endif /* __GNU_EXEC_MACROS__ */
diff --git a/contrib/gdb/include/aout/hp300hpux.h b/contrib/gdb/include/aout/hp300hpux.h
new file mode 100644
index 0000000..44d5196
--- /dev/null
+++ b/contrib/gdb/include/aout/hp300hpux.h
@@ -0,0 +1,119 @@
+/* Special version of <a.out.h> for use under hp-ux.
+ Copyright (C) 1988,1993 Free Software Foundation, Inc. */
+
+struct hp300hpux_exec_bytes
+{
+ unsigned char e_info[4]; /* a_machtype/a_magic */
+ unsigned char e_spare1[4];
+ unsigned char e_spare2[4];
+ unsigned char e_text[4]; /* length of text, in bytes */
+ unsigned char e_data[4]; /* length of data, in bytes */
+ unsigned char e_bss[4]; /* length of uninitialized data area , in bytes */
+ unsigned char e_trsize[4]; /* length of relocation info for text, in bytes*/
+ unsigned char e_drsize[4]; /* length of relocation info for data, in bytes*/
+ unsigned char e_passize[4];/* HP = pascal interface size */
+ unsigned char e_syms[4]; /* HP = symbol table size */
+ unsigned char e_spare5[4]; /* HP = debug name table size */
+ unsigned char e_entry[4]; /* start address */
+ unsigned char e_spare6[4]; /* HP = source line table size */
+ unsigned char e_supsize[4];/* HP = value table size */
+ unsigned char e_drelocs[4];
+ unsigned char e_extension[4]; /* file offset of extension */
+};
+#define EXEC_BYTES_SIZE 64
+
+struct hp300hpux_nlist_bytes
+ {
+ unsigned char e_value[4];
+ unsigned char e_type[1];
+ unsigned char e_length[1]; /* length of ascii symbol name */
+ unsigned char e_almod[2]; /* alignment mod */
+ unsigned char e_shlib[2]; /* info about dynamic linking */
+ };
+#define EXTERNAL_NLIST_SIZE 10
+
+struct hp300hpux_reloc
+ {
+ unsigned char r_address[4];/* offset of of data to relocate */
+ unsigned char r_index[2]; /* symbol table index of symbol */
+ unsigned char r_type[1]; /* relocation type */
+ unsigned char r_length[1]; /* length of item to reloc */
+ };
+
+struct hp300hpux_header_extension
+{
+ unsigned char e_syms[4];
+ unsigned char unique_headers[12*4];
+ unsigned char e_header[2]; /* type of header */
+ unsigned char e_version[2]; /* version */
+ unsigned char e_size[4]; /* bytes following*/
+ unsigned char e_extension[4];/* file offset of next extension */
+};
+#define EXTERNAL_EXTENSION_HEADER_SIZE (16*4)
+
+/* hpux separates object files (0x106) and impure executables (0x107) */
+/* but the bfd code does not distinguish between them. Since we want to*/
+/* read hpux .o files, we add an special define and use it below in */
+/* offset and address calculations. */
+
+#define HPUX_DOT_O_MAGIC 0x106
+#define OMAGIC 0x107 /* object file or impure executable. */
+#define NMAGIC 0x108 /* Code indicating pure executable. */
+#define ZMAGIC 0x10B /* demand-paged executable. */
+
+#define N_HEADER_IN_TEXT(x) 0
+
+#if 0 /* libaout.h only uses the lower 8 bits */
+#define HP98x6_ID 0x20A
+#define HP9000S200_ID 0x20C
+#endif
+#define HP98x6_ID 0x0A
+#define HP9000S200_ID 0x0C
+
+#define N_BADMAG(x) ((_N_BADMAG (x)) || (_N_BADMACH (x)))
+
+#define N_DATADDR(x) \
+ ((N_MAGIC(x)==OMAGIC || N_MAGIC(x)==HPUX_DOT_O_MAGIC) ? \
+ (N_TXTADDR(x)+N_TXTSIZE(x)) \
+ : (N_SEGSIZE(x) + ((N_TXTADDR(x)+N_TXTSIZE(x)-1) & ~(N_SEGSIZE(x)-1))))
+
+#define _N_BADMACH(x) \
+(((N_MACHTYPE (x)) != HP9000S200_ID) && \
+ ((N_MACHTYPE (x)) != HP98x6_ID))
+
+#define _N_BADMAG(x) (N_MAGIC(x) != HPUX_DOT_O_MAGIC \
+ && N_MAGIC(x) != OMAGIC \
+ && N_MAGIC(x) != NMAGIC \
+ && N_MAGIC(x) != ZMAGIC )
+
+#undef _N_HDROFF
+#define _N_HDROFF(x) (SEGMENT_SIZE - (sizeof (struct exec)))
+
+#undef N_DATOFF
+#undef N_PASOFF
+#undef N_SYMOFF
+#undef N_SUPOFF
+#undef N_TRELOFF
+#undef N_DRELOFF
+#undef N_STROFF
+
+#define N_DATOFF(x) ( N_TXTOFF(x) + N_TXTSIZE(x) )
+#define N_PASOFF(x) ( N_DATOFF(x) + (x).a_data)
+#define N_SYMOFF(x) ( N_PASOFF(x) /* + (x).a_passize*/ )
+#define N_SUPOFF(x) ( N_SYMOFF(x) + (x).a_syms )
+#define N_TRELOFF(x) ( N_SUPOFF(x) /* + 0 (x).a_supsize*/ )
+#define N_DRELOFF(x) ( N_TRELOFF(x) + (x).a_trsize )
+#define N_EXTHOFF(x) ( N_DRELOFF(x) /* + 0 (x).a_drsize */)
+#define N_STROFF(x) ( 0 /* no string table */ )
+
+/* use these when the file has gnu symbol tables */
+#define N_GNU_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
+#define N_GNU_DRELOFF(x) (N_GNU_TRELOFF(x) + (x).a_trsize)
+#define N_GNU_SYMOFF(x) (N_GNU_DRELOFF(x) + (x).a_drsize)
+
+#define TARGET_PAGE_SIZE 0x1000
+#define SEGMENT_SIZE 0x1000
+#define TEXT_START_ADDR 0
+
+#undef N_SHARED_LIB
+#define N_SHARED_LIB(x) ( 0 /* no shared libraries */ )
diff --git a/contrib/gdb/include/aout/hppa.h b/contrib/gdb/include/aout/hppa.h
new file mode 100644
index 0000000..7e185de
--- /dev/null
+++ b/contrib/gdb/include/aout/hppa.h
@@ -0,0 +1,7 @@
+#include "filehdr.h"
+#include "aouthdr.h"
+#include "scnhdr.h"
+#include "spacehdr.h"
+#include "syms.h"
+
+
diff --git a/contrib/gdb/include/aout/ranlib.h b/contrib/gdb/include/aout/ranlib.h
new file mode 100644
index 0000000..9826005
--- /dev/null
+++ b/contrib/gdb/include/aout/ranlib.h
@@ -0,0 +1,62 @@
+/* ranlib.h -- archive library index member definition for GNU.
+ Copyright 1990-1991 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The Symdef member of an archive contains two things:
+ a table that maps symbol-string offsets to file offsets,
+ and a symbol-string table. All the symbol names are
+ run together (each with trailing null) in the symbol-string
+ table. There is a single longword bytecount on the front
+ of each of these tables. Thus if we have two symbols,
+ "foo" and "_bar", that are in archive members at offsets
+ 200 and 900, it would look like this:
+ 16 ; byte count of index table
+ 0 ; offset of "foo" in string table
+ 200 ; offset of foo-module in file
+ 4 ; offset of "bar" in string table
+ 900 ; offset of bar-module in file
+ 9 ; byte count of string table
+ "foo\0_bar\0" ; string table */
+
+#define RANLIBMAG "__.SYMDEF" /* Archive file name containing index */
+#define RANLIBSKEW 3 /* Creation time offset */
+
+/* Format of __.SYMDEF:
+ First, a longword containing the size of the 'symdef' data that follows.
+ Second, zero or more 'symdef' structures.
+ Third, a longword containing the length of symbol name strings.
+ Fourth, zero or more symbol name strings (each followed by a null). */
+
+struct symdef
+ {
+ union
+ {
+ unsigned long string_offset; /* In the file */
+ char *name; /* In memory, sometimes */
+ } s;
+ /* this points to the front of the file header (AKA member header --
+ a struct ar_hdr), not to the front of the file or into the file).
+ in other words it only tells you which file to read */
+ unsigned long file_offset;
+ };
+
+/* Compatability with BSD code */
+
+#define ranlib symdef
+#define ran_un s
+#define ran_strx string_offset
+#define ran_name name
+#define ran_off file_offset
diff --git a/contrib/gdb/include/aout/reloc.h b/contrib/gdb/include/aout/reloc.h
new file mode 100644
index 0000000..563c552
--- /dev/null
+++ b/contrib/gdb/include/aout/reloc.h
@@ -0,0 +1,66 @@
+/* reloc.h -- Header file for relocation information.
+ Copyright 1989-1991 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Relocation types for a.out files using reloc_info_extended
+ (SPARC and AMD 29000). */
+
+#ifndef _RELOC_H_READ_
+#define _RELOC_H_READ_ 1
+
+enum reloc_type
+ {
+ RELOC_8, RELOC_16, RELOC_32, /* simple relocations */
+ RELOC_DISP8, RELOC_DISP16, RELOC_DISP32, /* pc-rel displacement */
+ RELOC_WDISP30, RELOC_WDISP22,
+ RELOC_HI22, RELOC_22,
+ RELOC_13, RELOC_LO10,
+ RELOC_SFA_BASE, RELOC_SFA_OFF13,
+ RELOC_BASE10, RELOC_BASE13, RELOC_BASE22, /* P.I.C. (base-relative) */
+ RELOC_PC10, RELOC_PC22, /* for some sort of pc-rel P.I.C. (?) */
+ RELOC_JMP_TBL, /* P.I.C. jump table */
+ RELOC_SEGOFF16, /* reputedly for shared libraries somehow */
+ RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE,
+ RELOC_11,
+ RELOC_WDISP2_14,
+ RELOC_WDISP19,
+ RELOC_HHI22,
+ RELOC_HLO10,
+
+ /* 29K relocation types */
+ RELOC_JUMPTARG, RELOC_CONST, RELOC_CONSTH,
+
+ RELOC_WDISP14, RELOC_WDISP21,
+
+ NO_RELOC
+ };
+
+#define RELOC_TYPE_NAMES \
+"8", "16", "32", "DISP8", \
+"DISP16", "DISP32", "WDISP30", "WDISP22", \
+"HI22", "22", "13", "LO10", \
+"SFA_BASE", "SFAOFF13", "BASE10", "BASE13", \
+"BASE22", "PC10", "PC22", "JMP_TBL", \
+"SEGOFF16", "GLOB_DAT", "JMP_SLOT", "RELATIVE", \
+"11", "WDISP2_14", "WDISP19", "HHI22", \
+"HLO10", \
+"JUMPTARG", "CONST", "CONSTH", "WDISP14", \
+"WDISP21", \
+"NO_RELOC"
+
+#endif /* _RELOC_H_READ_ */
+
+/* end of reloc.h */
diff --git a/contrib/gdb/include/aout/stab.def b/contrib/gdb/include/aout/stab.def
new file mode 100644
index 0000000..3c6b456
--- /dev/null
+++ b/contrib/gdb/include/aout/stab.def
@@ -0,0 +1,264 @@
+/* Table of DBX symbol codes for the GNU system.
+ Copyright (C) 1988, 91, 92, 93, 94, 95, 1996 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* New stab from Solaris 2. This uses an n_type of 0, which in a.out files
+ overlaps the N_UNDF used for ordinary symbols. In ELF files, the
+ debug information is in a different file section, so there is no conflict.
+ This symbol's n_value gives the size of the string section associated
+ with this file. The symbol's n_strx (relative to the just-updated
+ string section start address) gives the name of the source file,
+ e.g. "foo.c", without any path information. The symbol's n_desc gives
+ the count of upcoming symbols associated with this file (not including
+ this one). */
+/* __define_stab (N_UNDF, 0x00, "UNDF") */
+
+/* Global variable. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_GSYM, 0x20, "GSYM")
+
+/* Function name for BSD Fortran. Only the name is significant.
+ To find the address, look in the corresponding external symbol. */
+__define_stab (N_FNAME, 0x22, "FNAME")
+
+/* Function name or text-segment variable for C. Value is its address.
+ Desc is supposedly starting line number, but GCC doesn't set it
+ and DBX seems not to miss it. */
+__define_stab (N_FUN, 0x24, "FUN")
+
+/* Data-segment variable with internal linkage. Value is its address.
+ "Static Sym". */
+__define_stab (N_STSYM, 0x26, "STSYM")
+
+/* BSS-segment variable with internal linkage. Value is its address. */
+__define_stab (N_LCSYM, 0x28, "LCSYM")
+
+/* Name of main routine. Only the name is significant. */
+__define_stab (N_MAIN, 0x2a, "MAIN")
+
+/* Solaris2: Read-only data symbols. */
+__define_stab (N_ROSYM, 0x2c, "ROSYM")
+
+/* Global symbol in Pascal.
+ Supposedly the value is its line number; I'm skeptical. */
+__define_stab (N_PC, 0x30, "PC")
+
+/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
+__define_stab (N_NSYMS, 0x32, "NSYMS")
+
+/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
+__define_stab (N_NOMAP, 0x34, "NOMAP")
+
+/* New stab from Solaris 2. Like N_SO, but for the object file. Two in
+ a row provide the build directory and the relative path of the .o from it.
+ Solaris2 uses this to avoid putting the stabs info into the linked
+ executable; this stab goes into the ".stab.index" section, and the debugger
+ reads the real stabs directly from the .o files instead. */
+__define_stab (N_OBJ, 0x38, "OBJ")
+
+/* New stab from Solaris 2. Options for the debugger, related to the
+ source language for this module. E.g. whether to use ANSI
+ integral promotions or traditional integral promotions. */
+__define_stab (N_OPT, 0x3c, "OPT")
+
+/* Register variable. Value is number of register. */
+__define_stab (N_RSYM, 0x40, "RSYM")
+
+/* Modula-2 compilation unit. Can someone say what info it contains? */
+__define_stab (N_M2C, 0x42, "M2C")
+
+/* Line number in text segment. Desc is the line number;
+ value is corresponding address. On Solaris2, the line number is
+ relative to the start of the current function. */
+__define_stab (N_SLINE, 0x44, "SLINE")
+
+/* Similar, for data segment. */
+__define_stab (N_DSLINE, 0x46, "DSLINE")
+
+/* Similar, for bss segment. */
+__define_stab (N_BSLINE, 0x48, "BSLINE")
+
+/* Sun's source-code browser stabs. ?? Don't know what the fields are.
+ Supposedly the field is "path to associated .cb file". THIS VALUE
+ OVERLAPS WITH N_BSLINE! */
+__define_stab_duplicate (N_BROWS, 0x48, "BROWS")
+
+/* GNU Modula-2 definition module dependency. Value is the modification time
+ of the definition file. Other is non-zero if it is imported with the
+ GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
+ are enough empty fields? */
+__define_stab(N_DEFD, 0x4a, "DEFD")
+
+/* New in Solaris2. Function start/body/end line numbers. */
+__define_stab(N_FLINE, 0x4C, "FLINE")
+
+/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
+ and one is for C++. Still,... */
+/* GNU C++ exception variable. Name is variable name. */
+__define_stab (N_EHDECL, 0x50, "EHDECL")
+/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
+__define_stab_duplicate (N_MOD2, 0x50, "MOD2")
+
+/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
+ this entry is immediately followed by a CAUGHT stab saying what exception
+ was caught. Multiple CAUGHT stabs means that multiple exceptions
+ can be caught here. If Desc is 0, it means all exceptions are caught
+ here. */
+__define_stab (N_CATCH, 0x54, "CATCH")
+
+/* Structure or union element. Value is offset in the structure. */
+__define_stab (N_SSYM, 0x60, "SSYM")
+
+/* Solaris2: Last stab emitted for module. */
+__define_stab (N_ENDM, 0x62, "ENDM")
+
+/* Name of main source file.
+ Value is starting text address of the compilation.
+ If multiple N_SO's appear, the first to contain a trailing / is the
+ compilation directory. The first to not contain a trailing / is the
+ source file name, relative to the compilation directory. Others (perhaps
+ resulting from cfront) are ignored.
+ On Solaris2, value is undefined, but desc is a source-language code. */
+
+__define_stab (N_SO, 0x64, "SO")
+
+/* Automatic variable in the stack. Value is offset from frame pointer.
+ Also used for type descriptions. */
+__define_stab (N_LSYM, 0x80, "LSYM")
+
+/* Beginning of an include file. Only Sun uses this.
+ In an object file, only the name is significant.
+ The Sun linker puts data into some of the other fields. */
+__define_stab (N_BINCL, 0x82, "BINCL")
+
+/* Name of sub-source file (#include file).
+ Value is starting text address of the compilation. */
+__define_stab (N_SOL, 0x84, "SOL")
+
+/* Parameter variable. Value is offset from argument pointer.
+ (On most machines the argument pointer is the same as the frame pointer. */
+__define_stab (N_PSYM, 0xa0, "PSYM")
+
+/* End of an include file. No name.
+ This and N_BINCL act as brackets around the file's output.
+ In an object file, there is no significant data in this entry.
+ The Sun linker puts data into some of the fields. */
+__define_stab (N_EINCL, 0xa2, "EINCL")
+
+/* Alternate entry point. Value is its address. */
+__define_stab (N_ENTRY, 0xa4, "ENTRY")
+
+/* Beginning of lexical block.
+ The desc is the nesting level in lexical blocks.
+ The value is the address of the start of the text for the block.
+ The variables declared inside the block *precede* the N_LBRAC symbol.
+ On Solaris2, the value is relative to the start of the current function. */
+__define_stab (N_LBRAC, 0xc0, "LBRAC")
+
+/* Place holder for deleted include file. Replaces a N_BINCL and everything
+ up to the corresponding N_EINCL. The Sun linker generates these when
+ it finds multiple identical copies of the symbols from an include file.
+ This appears only in output from the Sun linker. */
+__define_stab (N_EXCL, 0xc2, "EXCL")
+
+/* Modula-2 scope information. Can someone say what info it contains? */
+__define_stab (N_SCOPE, 0xc4, "SCOPE")
+
+/* End of a lexical block. Desc matches the N_LBRAC's desc.
+ The value is the address of the end of the text for the block.
+ On Solaris2, the value is relative to the start of the current function. */
+__define_stab (N_RBRAC, 0xe0, "RBRAC")
+
+/* Begin named common block. Only the name is significant. */
+__define_stab (N_BCOMM, 0xe2, "BCOMM")
+
+/* End named common block. Only the name is significant
+ (and it should match the N_BCOMM). */
+__define_stab (N_ECOMM, 0xe4, "ECOMM")
+
+/* Member of a common block; value is offset within the common block.
+ This should occur within a BCOMM/ECOMM pair. */
+__define_stab (N_ECOML, 0xe8, "ECOML")
+
+/* Solaris2: Pascal "with" statement: type,,0,0,offset */
+__define_stab (N_WITH, 0xea, "WITH")
+
+/* These STAB's are used on Gould systems for Non-Base register symbols
+ or something like that. FIXME. I have assigned the values at random
+ since I don't have a Gould here. Fixups from Gould folk welcome... */
+__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
+__define_stab (N_NBDATA, 0xF2, "NBDATA")
+__define_stab (N_NBBSS, 0xF4, "NBBSS")
+__define_stab (N_NBSTS, 0xF6, "NBSTS")
+__define_stab (N_NBLCS, 0xF8, "NBLCS")
+
+/* Second symbol entry containing a length-value for the preceding entry.
+ The value is the length. */
+__define_stab (N_LENG, 0xfe, "LENG")
+
+/* The above information, in matrix format.
+
+ STAB MATRIX
+ _________________________________________________
+ | 00 - 1F are not dbx stab symbols |
+ | In most cases, the low bit is the EXTernal bit|
+
+ | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
+ | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
+
+ | 08 BSS | 0A INDR | 0C FN_SEQ | 0E WEAKA |
+ | 09 |EXT | 0B | 0D WEAKU | 0F WEAKT |
+
+ | 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 |
+
+ |_______________________________________________|
+ | Debug entries with bit 01 set are unused. |
+ | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
+ | 28 LCSYM | 2A MAIN | 2C ROSYM | 2E |
+ | 30 PC | 32 NSYMS | 34 NOMAP | 36 |
+ | 38 OBJ | 3A | 3C OPT | 3E |
+ | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
+ | 48 BSLINE*| 4A DEFD | 4C FLINE | 4E |
+ | 50 EHDECL*| 52 | 54 CATCH | 56 |
+ | 58 | 5A | 5C | 5E |
+ | 60 SSYM | 62 ENDM | 64 SO | 66 |
+ | 68 | 6A | 6C | 6E |
+ | 70 | 72 | 74 | 76 |
+ | 78 | 7A | 7C | 7E |
+ | 80 LSYM | 82 BINCL | 84 SOL | 86 |
+ | 88 | 8A | 8C | 8E |
+ | 90 | 92 | 94 | 96 |
+ | 98 | 9A | 9C | 9E |
+ | A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
+ | A8 | AA | AC | AE |
+ | B0 | B2 | B4 | B6 |
+ | B8 | BA | BC | BE |
+ | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
+ | C8 | CA | CC | CE |
+ | D0 | D2 | D4 | D6 |
+ | D8 | DA | DC | DE |
+ | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
+ | E8 ECOML | EA WITH | EC | EE |
+ | F0 | F2 | F4 | F6 |
+ | F8 | FA | FC | FE LENG |
+ +-----------------------------------------------+
+ * 50 EHDECL is also MOD2.
+ * 48 BSLINE is also BROWS.
+ */
diff --git a/contrib/gdb/include/aout/stab_gnu.h b/contrib/gdb/include/aout/stab_gnu.h
new file mode 100644
index 0000000..7d18e14
--- /dev/null
+++ b/contrib/gdb/include/aout/stab_gnu.h
@@ -0,0 +1,37 @@
+#ifndef __GNU_STAB__
+
+/* Indicate the GNU stab.h is in use. */
+
+#define __GNU_STAB__
+
+#define __define_stab(NAME, CODE, STRING) NAME=CODE,
+#define __define_stab_duplicate(NAME, CODE, STRING) NAME=CODE,
+
+enum __stab_debug_code
+{
+#include "aout/stab.def"
+LAST_UNUSED_STAB_CODE
+};
+
+#undef __define_stab
+
+/* Definitions of "desc" field for N_SO stabs in Solaris2. */
+
+#define N_SO_AS 1
+#define N_SO_C 2
+#define N_SO_ANSI_C 3
+#define N_SO_CC 4 /* C++ */
+#define N_SO_FORTRAN 5
+#define N_SO_PASCAL 6
+
+/* Solaris2: Floating point type values in basic types. */
+
+#define NF_NONE 0
+#define NF_SINGLE 1 /* IEEE 32-bit */
+#define NF_DOUBLE 2 /* IEEE 64-bit */
+#define NF_COMPLEX 3 /* Fortran complex */
+#define NF_COMPLEX16 4 /* Fortran double complex */
+#define NF_COMPLEX32 5 /* Fortran complex*16 */
+#define NF_LDOUBLE 6 /* Long double (whatever that is) */
+
+#endif /* __GNU_STAB_ */
diff --git a/contrib/gdb/include/aout/sun4.h b/contrib/gdb/include/aout/sun4.h
new file mode 100644
index 0000000..f42a0dd
--- /dev/null
+++ b/contrib/gdb/include/aout/sun4.h
@@ -0,0 +1,219 @@
+/* SPARC-specific values for a.out files */
+
+/* Some systems, e.g., AIX, may have defined this in header files already
+ included. */
+#undef TARGET_PAGE_SIZE
+#define TARGET_PAGE_SIZE 0x2000 /* 8K. aka NBPG in <sys/param.h> */
+/* Note that some SPARCs have 4K pages, some 8K, some others. */
+
+#define SEG_SIZE_SPARC TARGET_PAGE_SIZE
+#define SEG_SIZE_SUN3 0x20000 /* Resolution of r/w protection hw */
+
+#define TEXT_START_ADDR TARGET_PAGE_SIZE /* Location 0 is not accessible */
+#define N_HEADER_IN_TEXT(x) 1
+
+/* Non-default definitions of the accessor macros... */
+
+/* Segment size varies on Sun-3 versus Sun-4. */
+
+#define N_SEGSIZE(x) (N_MACHTYPE(x) == M_SPARC? SEG_SIZE_SPARC: \
+ N_MACHTYPE(x) == M_68020? SEG_SIZE_SUN3: \
+ /* Guess? */ TARGET_PAGE_SIZE)
+
+/* Virtual Address of text segment from the a.out file. For OMAGIC,
+ (almost always "unlinked .o's" these days), should be zero.
+ Sun added a kludge so that shared libraries linked ZMAGIC get
+ an address of zero if a_entry (!!!) is lower than the otherwise
+ expected text address. These kludges have gotta go!
+ For linked files, should reflect reality if we know it. */
+
+/* This differs from the version in aout64.h (which we override by defining
+ it here) only for NMAGIC (we return TEXT_START_ADDR+EXEC_BYTES_SIZE;
+ they return 0). */
+
+#define N_TXTADDR(x) \
+ (N_MAGIC(x)==OMAGIC? 0 \
+ : (N_MAGIC(x) == ZMAGIC && (x).a_entry < TEXT_START_ADDR)? 0 \
+ : TEXT_START_ADDR+EXEC_BYTES_SIZE)
+
+/* When a file is linked against a shared library on SunOS 4, the
+ dynamic bit in the exec header is set, and the first symbol in the
+ symbol table is __DYNAMIC. Its value is the address of the
+ following structure. */
+
+struct external_sun4_dynamic
+{
+ /* The version number of the structure. SunOS 4.1.x creates files
+ with version number 3, which is what this structure is based on.
+ According to gdb, version 2 is similar. I believe that version 2
+ used a different type of procedure linkage table, and there may
+ have been other differences. */
+ bfd_byte ld_version[4];
+ /* The virtual address of a 28 byte structure used in debugging.
+ The contents are filled in at run time by ld.so. */
+ bfd_byte ldd[4];
+ /* The virtual address of another structure with information about
+ how to relocate the executable at run time. */
+ bfd_byte ld[4];
+};
+
+/* The size of the debugging structure pointed to by the debugger
+ field of __DYNAMIC. */
+#define EXTERNAL_SUN4_DYNAMIC_DEBUGGER_SIZE (24)
+
+/* The structure pointed to by the linker field of __DYNAMIC. As far
+ as I can tell, most of the addresses in this structure are offsets
+ within the file, but some are actually virtual addresses. */
+
+struct internal_sun4_dynamic_link
+{
+ /* Linked list of loaded objects. This is filled in at runtime by
+ ld.so and probably by dlopen. */
+ unsigned long ld_loaded;
+
+ /* The address of the list of names of shared objects which must be
+ included at runtime. Each entry in the list is 16 bytes: the 4
+ byte address of the string naming the object (e.g., for -lc this
+ is "c"); 4 bytes of flags--the high bit is whether to search for
+ the object using the library path; the 2 byte major version
+ number; the 2 byte minor version number; the 4 byte address of
+ the next entry in the list (zero if this is the last entry). The
+ version numbers seem to only be non-zero when doing library
+ searching. */
+ unsigned long ld_need;
+
+ /* The address of the path to search for the shared objects which
+ must be included. This points to a string in PATH format which
+ is generated from the -L arguments to the linker. According to
+ the man page, ld.so implicitly adds ${LD_LIBRARY_PATH} to the
+ beginning of this string and /lib:/usr/lib:/usr/local/lib to the
+ end. The string is terminated by a null byte. This field is
+ zero if there is no additional path. */
+ unsigned long ld_rules;
+
+ /* The address of the global offset table. This appears to be a
+ virtual address, not a file offset. The first entry in the
+ global offset table seems to be the virtual address of the
+ sun4_dynamic structure (the same value as the __DYNAMIC symbol).
+ The global offset table is used for PIC code to hold the
+ addresses of variables. A dynamically linked file which does not
+ itself contain PIC code has a four byte global offset table. */
+ unsigned long ld_got;
+
+ /* The address of the procedure linkage table. This appears to be a
+ virtual address, not a file offset.
+
+ On a SPARC, the table is composed of 12 byte entries, each of
+ which consists of three instructions. The first entry is
+ sethi %hi(0),%g1
+ jmp %g1
+ nop
+ These instructions are changed by ld.so into a jump directly into
+ ld.so itself. Each subsequent entry is
+ save %sp, -96, %sp
+ call <address of first entry in procedure linkage table>
+ <reloc_number | 0x01000000>
+ The reloc_number is the number of the reloc to use to resolve
+ this entry. The reloc will be a JMP_SLOT reloc against some
+ symbol that is not defined in this object file but should be
+ defined in a shared object (if it is not, ld.so will report a
+ runtime error and exit). The constant 0x010000000 turns the
+ reloc number into a sethi of %g0, which does nothing since %g0 is
+ hardwired to zero.
+
+ When one of these entries is executed, it winds up calling into
+ ld.so. ld.so looks at the reloc number, available via the return
+ address, to determine which entry this is. It then looks at the
+ reloc and patches up the entry in the table into a sethi and jmp
+ to the real address followed by a nop. This means that the reloc
+ lookup only has to happen once, and it also means that the
+ relocation only needs to be done if the function is actually
+ called. The relocation is expensive because ld.so must look up
+ the symbol by name.
+
+ The size of the procedure linkage table is given by the ld_plt_sz
+ field. */
+ unsigned long ld_plt;
+
+ /* The address of the relocs. These are in the same format as
+ ordinary relocs. Symbol index numbers refer to the symbols
+ pointed to by ld_stab. I think the only way to determine the
+ number of relocs is to assume that all the bytes from ld_rel to
+ ld_hash contain reloc entries. */
+ unsigned long ld_rel;
+
+ /* The address of a hash table of symbols. The hash table has
+ roughly the same number of entries as there are dynamic symbols;
+ I think the only way to get the exact size is to assume that
+ every byte from ld_hash to ld_stab is devoted to the hash table.
+
+ Each entry in the hash table is eight bytes. The first four
+ bytes are a symbol index into the dynamic symbols. The second
+ four bytes are the index of the next hash table entry in the
+ bucket. The ld_buckets field gives the number of buckets, say B.
+ The first B entries in the hash table each start a bucket which
+ is chained through the second four bytes of each entry. A value
+ of zero ends the chain.
+
+ The hash function is simply
+ h = 0;
+ while (*string != '\0')
+ h = (h << 1) + *string++;
+ h &= 0x7fffffff;
+
+ To look up a symbol, compute the hash value of the name. Take
+ the modulos of hash value and the number of buckets. Start at
+ that entry in the hash table. See if the symbol (from the first
+ four bytes of the hash table entry) has the name you are looking
+ for. If not, use the chain field (the second four bytes of the
+ hash table entry) to move on to the next entry in this bucket.
+ If the chain field is zero you have reached the end of the
+ bucket, and the symbol is not in the hash table. */
+ unsigned long ld_hash;
+
+ /* The address of the symbol table. This is a list of
+ external_nlist structures. The string indices are relative to
+ the ld_symbols field. I think the only way to determine the
+ number of symbols is to assume that all the bytes between ld_stab
+ and ld_symbols are external_nlist structures. */
+ unsigned long ld_stab;
+
+ /* I don't know what this is for. It seems to always be zero. */
+ unsigned long ld_stab_hash;
+
+ /* The number of buckets in the hash table. */
+ unsigned long ld_buckets;
+
+ /* The address of the symbol string table. The first string in this
+ string table need not be the empty string. */
+ unsigned long ld_symbols;
+
+ /* The size in bytes of the symbol string table. */
+ unsigned long ld_symb_size;
+
+ /* The size in bytes of the text segment. */
+ unsigned long ld_text;
+
+ /* The size in bytes of the procedure linkage table. */
+ unsigned long ld_plt_sz;
+};
+
+/* The external form of the structure. */
+
+struct external_sun4_dynamic_link
+{
+ bfd_byte ld_loaded[4];
+ bfd_byte ld_need[4];
+ bfd_byte ld_rules[4];
+ bfd_byte ld_got[4];
+ bfd_byte ld_plt[4];
+ bfd_byte ld_rel[4];
+ bfd_byte ld_hash[4];
+ bfd_byte ld_stab[4];
+ bfd_byte ld_stab_hash[4];
+ bfd_byte ld_buckets[4];
+ bfd_byte ld_symbols[4];
+ bfd_byte ld_symb_size[4];
+ bfd_byte ld_text[4];
+ bfd_byte ld_plt_sz[4];
+};
diff --git a/contrib/gdb/include/bfdlink.h b/contrib/gdb/include/bfdlink.h
new file mode 100644
index 0000000..47d80b8
--- /dev/null
+++ b/contrib/gdb/include/bfdlink.h
@@ -0,0 +1,452 @@
+/* bfdlink.h -- header file for BFD link routines
+ Copyright 1993 Free Software Foundation, Inc.
+ Written by Steve Chamberlain and Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef BFDLINK_H
+#define BFDLINK_H
+
+/* Which symbols to strip during a link. */
+enum bfd_link_strip
+{
+ strip_none, /* Don't strip any symbols. */
+ strip_debugger, /* Strip debugging symbols. */
+ strip_some, /* keep_hash is the list of symbols to keep. */
+ strip_all /* Strip all symbols. */
+};
+
+/* Which local symbols to discard during a link. This is irrelevant
+ if strip_all is used. */
+enum bfd_link_discard
+{
+ discard_none, /* Don't discard any locals. */
+ discard_l, /* Discard locals with a certain prefix. */
+ discard_all /* Discard all locals. */
+};
+
+/* These are the possible types of an entry in the BFD link hash
+ table. */
+
+enum bfd_link_hash_type
+{
+ bfd_link_hash_new, /* Symbol is new. */
+ bfd_link_hash_undefined, /* Symbol seen before, but undefined. */
+ bfd_link_hash_undefweak, /* Symbol is weak and undefined. */
+ bfd_link_hash_defined, /* Symbol is defined. */
+ bfd_link_hash_defweak, /* Symbol is weak and defined. */
+ bfd_link_hash_common, /* Symbol is common. */
+ bfd_link_hash_indirect, /* Symbol is an indirect link. */
+ bfd_link_hash_warning /* Like indirect, but warn if referenced. */
+};
+
+/* The linking routines use a hash table which uses this structure for
+ its elements. */
+
+struct bfd_link_hash_entry
+{
+ /* Base hash table entry structure. */
+ struct bfd_hash_entry root;
+ /* Type of this entry. */
+ enum bfd_link_hash_type type;
+
+ /* Undefined and common symbols are kept in a linked list through
+ this field. This field is not in the union because that would
+ force us to remove entries from the list when we changed their
+ type, which would force the list to be doubly linked, which would
+ waste more memory. When an undefined or common symbol is
+ created, it should be added to this list, the head of which is in
+ the link hash table itself. As symbols are defined, they need
+ not be removed from the list; anything which reads the list must
+ doublecheck the symbol type.
+
+ Weak symbols are not kept on this list.
+
+ Defined and defweak symbols use this field as a reference marker.
+ If the field is not NULL, or this structure is the tail of the
+ undefined symbol list, the symbol has been referenced. If the
+ symbol is undefined and becomes defined, this field will
+ automatically be non-NULL since the symbol will have been on the
+ undefined symbol list. */
+ struct bfd_link_hash_entry *next;
+ /* A union of information depending upon the type. */
+ union
+ {
+ /* Nothing is kept for bfd_hash_new. */
+ /* bfd_link_hash_undefined, bfd_link_hash_undefweak. */
+ struct
+ {
+ bfd *abfd; /* BFD symbol was found in. */
+ } undef;
+ /* bfd_link_hash_defined, bfd_link_hash_defweak. */
+ struct
+ {
+ bfd_vma value; /* Symbol value. */
+ asection *section; /* Symbol section. */
+ } def;
+ /* bfd_link_hash_indirect, bfd_link_hash_warning. */
+ struct
+ {
+ struct bfd_link_hash_entry *link; /* Real symbol. */
+ const char *warning; /* Warning (bfd_link_hash_warning only). */
+ } i;
+ /* bfd_link_hash_common. */
+ struct
+ {
+ /* The linker needs to know three things about common
+ symbols: the size, the alignment, and the section in
+ which the symbol should be placed. We store the size
+ here, and we allocate a small structure to hold the
+ section and the alignment. The alignment is stored as a
+ power of two. We don't store all the information
+ directly because we don't want to increase the size of
+ the union; this structure is a major space user in the
+ linker. */
+ bfd_size_type size; /* Common symbol size. */
+ struct bfd_link_hash_common_entry
+ {
+ unsigned int alignment_power; /* Alignment. */
+ asection *section; /* Symbol section. */
+ } *p;
+ } c;
+ } u;
+};
+
+/* This is the link hash table. It is a derived class of
+ bfd_hash_table. */
+
+struct bfd_link_hash_table
+{
+ /* The hash table itself. */
+ struct bfd_hash_table table;
+ /* The back end which created this hash table. This indicates the
+ type of the entries in the hash table, which is sometimes
+ important information when linking object files of different
+ types together. */
+ const bfd_target *creator;
+ /* A linked list of undefined and common symbols, linked through the
+ next field in the bfd_link_hash_entry structure. */
+ struct bfd_link_hash_entry *undefs;
+ /* Entries are added to the tail of the undefs list. */
+ struct bfd_link_hash_entry *undefs_tail;
+};
+
+/* Look up an entry in a link hash table. If FOLLOW is true, this
+ follows bfd_link_hash_indirect and bfd_link_hash_warning links to
+ the real symbol. */
+extern struct bfd_link_hash_entry *bfd_link_hash_lookup
+ PARAMS ((struct bfd_link_hash_table *, const char *, boolean create,
+ boolean copy, boolean follow));
+
+/* Look up an entry in the main linker hash table if the symbol might
+ be wrapped. This should only be used for references to an
+ undefined symbol, not for definitions of a symbol. */
+
+extern struct bfd_link_hash_entry *bfd_wrapped_link_hash_lookup
+ PARAMS ((bfd *, struct bfd_link_info *, const char *, boolean, boolean,
+ boolean));
+
+/* Traverse a link hash table. */
+extern void bfd_link_hash_traverse
+ PARAMS ((struct bfd_link_hash_table *,
+ boolean (*) (struct bfd_link_hash_entry *, PTR),
+ PTR));
+
+/* Add an entry to the undefs list. */
+extern void bfd_link_add_undef
+ PARAMS ((struct bfd_link_hash_table *, struct bfd_link_hash_entry *));
+
+/* This structure holds all the information needed to communicate
+ between BFD and the linker when doing a link. */
+
+struct bfd_link_info
+{
+ /* Function callbacks. */
+ const struct bfd_link_callbacks *callbacks;
+ /* true if BFD should generate a relocateable object file. */
+ boolean relocateable;
+ /* true if BFD should generate a shared object. */
+ boolean shared;
+ /* true if BFD should pre-bind symbols in a shared object. */
+ boolean symbolic;
+ /* true if shared objects should be linked directly, not shared. */
+ boolean static_link;
+ /* Which symbols to strip. */
+ enum bfd_link_strip strip;
+ /* Which local symbols to discard. */
+ enum bfd_link_discard discard;
+ /* The local symbol prefix to discard if using discard_l. */
+ unsigned int lprefix_len;
+ const char *lprefix;
+ /* true if symbols should be retained in memory, false if they
+ should be freed and reread. */
+ boolean keep_memory;
+ /* The list of input BFD's involved in the link. These are chained
+ together via the link_next field. */
+ bfd *input_bfds;
+ /* If a symbol should be created for each input BFD, this is section
+ where those symbols should be placed. It must be a section in
+ the output BFD. It may be NULL, in which case no such symbols
+ will be created. This is to support CREATE_OBJECT_SYMBOLS in the
+ linker command language. */
+ asection *create_object_symbols_section;
+ /* Hash table handled by BFD. */
+ struct bfd_link_hash_table *hash;
+ /* Hash table of symbols to keep. This is NULL unless strip is
+ strip_some. */
+ struct bfd_hash_table *keep_hash;
+ /* Hash table of symbols to report back via notice_callback. If
+ this is NULL no symbols are reported back. */
+ struct bfd_hash_table *notice_hash;
+ /* Hash table of symbols which are being wrapped (the --wrap linker
+ option). If this is NULL, no symbols are being wrapped. */
+ struct bfd_hash_table *wrap_hash;
+
+ /* If a base output file is wanted, then this points to it */
+ PTR base_file;
+};
+
+/* This structures holds a set of callback functions. These are
+ called by the BFD linker routines. The first argument to each
+ callback function is the bfd_link_info structure being used. Each
+ function returns a boolean value. If the function returns false,
+ then the BFD function which called it will return with a failure
+ indication. */
+
+struct bfd_link_callbacks
+{
+ /* A function which is called when an object is added from an
+ archive. ABFD is the archive element being added. NAME is the
+ name of the symbol which caused the archive element to be pulled
+ in. */
+ boolean (*add_archive_element) PARAMS ((struct bfd_link_info *,
+ bfd *abfd,
+ const char *name));
+ /* A function which is called when a symbol is found with multiple
+ definitions. NAME is the symbol which is defined multiple times.
+ OBFD is the old BFD, OSEC is the old section, OVAL is the old
+ value, NBFD is the new BFD, NSEC is the new section, and NVAL is
+ the new value. OBFD may be NULL. OSEC and NSEC may be
+ bfd_com_section or bfd_ind_section. */
+ boolean (*multiple_definition) PARAMS ((struct bfd_link_info *,
+ const char *name,
+ bfd *obfd,
+ asection *osec,
+ bfd_vma oval,
+ bfd *nbfd,
+ asection *nsec,
+ bfd_vma nval));
+ /* A function which is called when a common symbol is defined
+ multiple times. NAME is the symbol appearing multiple times.
+ OBFD is the BFD of the existing symbol; it may be NULL if this is
+ not known. OTYPE is the type of the existing symbol, which may
+ be bfd_link_hash_defined, bfd_link_hash_defweak,
+ bfd_link_hash_common, or bfd_link_hash_indirect. If OTYPE is
+ bfd_link_hash_common, OSIZE is the size of the existing symbol.
+ NBFD is the BFD of the new symbol. NTYPE is the type of the new
+ symbol, one of bfd_link_hash_defined, bfd_link_hash_common, or
+ bfd_link_hash_indirect. If NTYPE is bfd_link_hash_common, NSIZE
+ is the size of the new symbol. */
+ boolean (*multiple_common) PARAMS ((struct bfd_link_info *,
+ const char *name,
+ bfd *obfd,
+ enum bfd_link_hash_type otype,
+ bfd_vma osize,
+ bfd *nbfd,
+ enum bfd_link_hash_type ntype,
+ bfd_vma nsize));
+ /* A function which is called to add a symbol to a set. ENTRY is
+ the link hash table entry for the set itself (e.g.,
+ __CTOR_LIST__). RELOC is the relocation to use for an entry in
+ the set when generating a relocateable file, and is also used to
+ get the size of the entry when generating an executable file.
+ ABFD, SEC and VALUE identify the value to add to the set. */
+ boolean (*add_to_set) PARAMS ((struct bfd_link_info *,
+ struct bfd_link_hash_entry *entry,
+ bfd_reloc_code_real_type reloc,
+ bfd *abfd, asection *sec, bfd_vma value));
+ /* A function which is called when the name of a g++ constructor or
+ destructor is found. This is only called by some object file
+ formats. CONSTRUCTOR is true for a constructor, false for a
+ destructor. This will use BFD_RELOC_CTOR when generating a
+ relocateable file. NAME is the name of the symbol found. ABFD,
+ SECTION and VALUE are the value of the symbol. */
+ boolean (*constructor) PARAMS ((struct bfd_link_info *,
+ boolean constructor,
+ const char *name, bfd *abfd, asection *sec,
+ bfd_vma value));
+ /* A function which is called to issue a linker warning. For
+ example, this is called when there is a reference to a warning
+ symbol. WARNING is the warning to be issued. SYMBOL is the name
+ of the symbol which triggered the warning; it may be NULL if
+ there is none. ABFD, SECTION and ADDRESS identify the location
+ which trigerred the warning; either ABFD or SECTION or both may
+ be NULL if the location is not known. */
+ boolean (*warning) PARAMS ((struct bfd_link_info *,
+ const char *warning, const char *symbol,
+ bfd *abfd, asection *section,
+ bfd_vma address));
+ /* A function which is called when a relocation is attempted against
+ an undefined symbol. NAME is the symbol which is undefined.
+ ABFD, SECTION and ADDRESS identify the location from which the
+ reference is made. In some cases SECTION may be NULL. */
+ boolean (*undefined_symbol) PARAMS ((struct bfd_link_info *,
+ const char *name, bfd *abfd,
+ asection *section, bfd_vma address));
+ /* A function which is called when a reloc overflow occurs. NAME is
+ the name of the symbol or section the reloc is against,
+ RELOC_NAME is the name of the relocation, and ADDEND is any
+ addend that is used. ABFD, SECTION and ADDRESS identify the
+ location at which the overflow occurs; if this is the result of a
+ bfd_section_reloc_link_order or bfd_symbol_reloc_link_order, then
+ ABFD will be NULL. */
+ boolean (*reloc_overflow) PARAMS ((struct bfd_link_info *,
+ const char *name,
+ const char *reloc_name, bfd_vma addend,
+ bfd *abfd, asection *section,
+ bfd_vma address));
+ /* A function which is called when a dangerous reloc is performed.
+ The canonical example is an a29k IHCONST reloc which does not
+ follow an IHIHALF reloc. MESSAGE is an appropriate message.
+ ABFD, SECTION and ADDRESS identify the location at which the
+ problem occurred; if this is the result of a
+ bfd_section_reloc_link_order or bfd_symbol_reloc_link_order, then
+ ABFD will be NULL. */
+ boolean (*reloc_dangerous) PARAMS ((struct bfd_link_info *,
+ const char *message,
+ bfd *abfd, asection *section,
+ bfd_vma address));
+ /* A function which is called when a reloc is found to be attached
+ to a symbol which is not being written out. NAME is the name of
+ the symbol. ABFD, SECTION and ADDRESS identify the location of
+ the reloc; if this is the result of a
+ bfd_section_reloc_link_order or bfd_symbol_reloc_link_order, then
+ ABFD will be NULL. */
+ boolean (*unattached_reloc) PARAMS ((struct bfd_link_info *,
+ const char *name,
+ bfd *abfd, asection *section,
+ bfd_vma address));
+ /* A function which is called when a symbol in notice_hash is
+ defined or referenced. NAME is the symbol. ABFD, SECTION and
+ ADDRESS are the value of the symbol. If SECTION is
+ bfd_und_section, this is a reference. */
+ boolean (*notice) PARAMS ((struct bfd_link_info *, const char *name,
+ bfd *abfd, asection *section, bfd_vma address));
+};
+
+/* The linker builds link_order structures which tell the code how to
+ include input data in the output file. */
+
+/* These are the types of link_order structures. */
+
+enum bfd_link_order_type
+{
+ bfd_undefined_link_order, /* Undefined. */
+ bfd_indirect_link_order, /* Built from a section. */
+ bfd_fill_link_order, /* Fill with a 16 bit constant. */
+ bfd_data_link_order, /* Set to explicit data. */
+ bfd_section_reloc_link_order, /* Relocate against a section. */
+ bfd_symbol_reloc_link_order /* Relocate against a symbol. */
+};
+
+/* This is the link_order structure itself. These form a chain
+ attached to the section whose contents they are describing. */
+
+struct bfd_link_order
+{
+ /* Next link_order in chain. */
+ struct bfd_link_order *next;
+ /* Type of link_order. */
+ enum bfd_link_order_type type;
+ /* Offset within output section. */
+ bfd_vma offset;
+ /* Size within output section. */
+ bfd_size_type size;
+ /* Type specific information. */
+ union
+ {
+ struct
+ {
+ /* Section to include. If this is used, then
+ section->output_section must be the section the
+ link_order is attached to, section->output_offset must
+ equal the link_order offset field, and section->_raw_size
+ must equal the link_order size field. Maybe these
+ restrictions should be relaxed someday. */
+ asection *section;
+ } indirect;
+ struct
+ {
+ /* Value to fill with. */
+ unsigned int value;
+ } fill;
+ struct
+ {
+ /* Data to put into file. The size field gives the number
+ of bytes which this field points to. */
+ bfd_byte *contents;
+ } data;
+ struct
+ {
+ /* Description of reloc to generate. Used for
+ bfd_section_reloc_link_order and
+ bfd_symbol_reloc_link_order. */
+ struct bfd_link_order_reloc *p;
+ } reloc;
+ } u;
+};
+
+/* A linker order of type bfd_section_reloc_link_order or
+ bfd_symbol_reloc_link_order means to create a reloc against a
+ section or symbol, respectively. This is used to implement -Ur to
+ generate relocs for the constructor tables. The
+ bfd_link_order_reloc structure describes the reloc that BFD should
+ create. It is similar to a arelent, but I didn't use arelent
+ because the linker does not know anything about most symbols, and
+ any asymbol structure it creates will be partially meaningless.
+ This information could logically be in the bfd_link_order struct,
+ but I didn't want to waste the space since these types of relocs
+ are relatively rare. */
+
+struct bfd_link_order_reloc
+{
+ /* Reloc type. */
+ bfd_reloc_code_real_type reloc;
+
+ union
+ {
+ /* For type bfd_section_reloc_link_order, this is the section
+ the reloc should be against. This must be a section in the
+ output BFD, not any of the input BFDs. */
+ asection *section;
+ /* For type bfd_symbol_reloc_link_order, this is the name of the
+ symbol the reloc should be against. */
+ const char *name;
+ } u;
+
+ /* Addend to use. The object file should contain zero. The BFD
+ backend is responsible for filling in the contents of the object
+ file correctly. For some object file formats (e.g., COFF) the
+ addend must be stored into in the object file, and for some
+ (e.g., SPARC a.out) it is kept in the reloc. */
+ bfd_vma addend;
+};
+
+/* Allocate a new link_order for a section. */
+extern struct bfd_link_order *bfd_new_link_order PARAMS ((bfd *, asection *));
+
+#endif
diff --git a/contrib/gdb/include/bout.h b/contrib/gdb/include/bout.h
new file mode 100644
index 0000000..8fc28cc
--- /dev/null
+++ b/contrib/gdb/include/bout.h
@@ -0,0 +1,182 @@
+/*
+ * This file is a modified version of 'a.out.h'. It is to be used in all
+ * GNU tools modified to support the i80960 (or tools that operate on
+ * object files created by such tools).
+ *
+ * All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e.,
+ * object code is generated on, and executed under the direction of a symbolic
+ * debugger running on, a host system. We do not want to be subject to the
+ * vagaries of which host it is or whether it supports COFF or a.out format,
+ * or anything else. We DO want to:
+ *
+ * o always generate the same format object files, regardless of host.
+ *
+ * o have an 'a.out' header that we can modify for our own purposes
+ * (the 80960 is typically an embedded processor and may require
+ * enhanced linker support that the normal a.out.h header can't
+ * accommodate).
+ *
+ * As for byte-ordering, the following rules apply:
+ *
+ * o Text and data that is actually downloaded to the target is always
+ * in i80960 (little-endian) order.
+ *
+ * o All other numbers (in the header, symbols, relocation directives)
+ * are in host byte-order: object files CANNOT be lifted from a
+ * little-end host and used on a big-endian (or vice versa) without
+ * modification.
+ * ==> THIS IS NO LONGER TRUE USING BFD. WE CAN GENERATE ANY BYTE ORDER
+ * FOR THE HEADER, AND READ ANY BYTE ORDER. PREFERENCE WOULD BE TO
+ * USE LITTLE-ENDIAN BYTE ORDER THROUGHOUT, REGARDLESS OF HOST. <==
+ *
+ * o The downloader ('comm960') takes care to generate a pseudo-header
+ * with correct (i80960) byte-ordering before shipping text and data
+ * off to the NINDY monitor in the target systems. Symbols and
+ * relocation info are never sent to the target.
+ */
+
+
+#define BMAGIC 0415
+/* We don't accept the following (see N_BADMAG macro).
+ * They're just here so GNU code will compile.
+ */
+#define OMAGIC 0407 /* old impure format */
+#define NMAGIC 0410 /* read-only text */
+#define ZMAGIC 0413 /* demand load format */
+
+/* FILE HEADER
+ * All 'lengths' are given as a number of bytes.
+ * All 'alignments' are for relinkable files only; an alignment of
+ * 'n' indicates the corresponding segment must begin at an
+ * address that is a multiple of (2**n).
+ */
+struct external_exec {
+ /* Standard stuff */
+ unsigned char e_info[4]; /* Identifies this as a b.out file */
+ unsigned char e_text[4]; /* Length of text */
+ unsigned char e_data[4]; /* Length of data */
+ unsigned char e_bss[4]; /* Length of uninitialized data area */
+ unsigned char e_syms[4]; /* Length of symbol table */
+ unsigned char e_entry[4]; /* Runtime start address */
+ unsigned char e_trsize[4]; /* Length of text relocation info */
+ unsigned char e_drsize[4]; /* Length of data relocation info */
+
+ /* Added for i960 */
+ unsigned char e_tload[4]; /* Text runtime load address */
+ unsigned char e_dload[4]; /* Data runtime load address */
+ unsigned char e_talign[1]; /* Alignment of text segment */
+ unsigned char e_dalign[1]; /* Alignment of data segment */
+ unsigned char e_balign[1]; /* Alignment of bss segment */
+ unsigned char e_relaxable[1]; /* Assembled with enough info to allow linker to relax */
+};
+
+#define EXEC_BYTES_SIZE (sizeof (struct external_exec))
+
+/* These macros use the a_xxx field names, since they operate on the exec
+ structure after it's been byte-swapped and realigned on the host machine. */
+#define N_BADMAG(x) (((x).a_info)!=BMAGIC)
+#define N_TXTOFF(x) EXEC_BYTES_SIZE
+#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text )
+#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data )
+#define N_TRELOFF N_TROFF
+#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize )
+#define N_DRELOFF N_DROFF
+#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize )
+#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms )
+#define N_DATADDR(x) ( (x).a_dload )
+
+/* Address of text segment in memory after it is loaded. */
+#if !defined (N_TXTADDR)
+#define N_TXTADDR(x) 0
+#endif
+
+/* A single entry in the symbol table
+ */
+struct nlist {
+ union {
+ char *n_name;
+ struct nlist *n_next;
+ long n_strx; /* Index into string table */
+ } n_un;
+ unsigned char n_type; /* See below */
+ char n_other; /* Used in i80960 support -- see below */
+ short n_desc;
+ unsigned long n_value;
+};
+
+
+/* Legal values of n_type
+ */
+#define N_UNDF 0 /* Undefined symbol */
+#define N_ABS 2 /* Absolute symbol */
+#define N_TEXT 4 /* Text symbol */
+#define N_DATA 6 /* Data symbol */
+#define N_BSS 8 /* BSS symbol */
+#define N_FN 31 /* Filename symbol */
+
+#define N_EXT 1 /* External symbol (OR'd in with one of above) */
+#define N_TYPE 036 /* Mask for all the type bits */
+#define N_STAB 0340 /* Mask for all bits used for SDB entries */
+
+/* MEANING OF 'n_other'
+ *
+ * If non-zero, the 'n_other' fields indicates either a leaf procedure or
+ * a system procedure, as follows:
+ *
+ * 1 <= n_other <= 32 :
+ * The symbol is the entry point to a system procedure.
+ * 'n_value' is the address of the entry, as for any other
+ * procedure. The system procedure number (which can be used in
+ * a 'calls' instruction) is (n_other-1). These entries come from
+ * '.sysproc' directives.
+ *
+ * n_other == N_CALLNAME
+ * the symbol is the 'call' entry point to a leaf procedure.
+ * The *next* symbol in the symbol table must be the corresponding
+ * 'bal' entry point to the procedure (see following). These
+ * entries come from '.leafproc' directives in which two different
+ * symbols are specified (the first one is represented here).
+ *
+ *
+ * n_other == N_BALNAME
+ * the symbol is the 'bal' entry point to a leaf procedure.
+ * These entries result from '.leafproc' directives in which only
+ * one symbol is specified, or in which the same symbol is
+ * specified twice.
+ *
+ * Note that an N_CALLNAME entry *must* have a corresponding N_BALNAME entry,
+ * but not every N_BALNAME entry must have an N_CALLNAME entry.
+ */
+#define N_CALLNAME ((char)-1)
+#define N_BALNAME ((char)-2)
+#define IS_CALLNAME(x) (N_CALLNAME == (x))
+#define IS_BALNAME(x) (N_BALNAME == (x))
+#define IS_OTHER(x) ((x)>0 && (x) <=32)
+
+#define b_out_relocation_info relocation_info
+struct relocation_info {
+ int r_address; /* File address of item to be relocated */
+ unsigned
+#define r_index r_symbolnum
+ r_symbolnum:24,/* Index of symbol on which relocation is based,
+ * if r_extern is set. Otherwise set to
+ * either N_TEXT, N_DATA, or N_BSS to
+ * indicate section on which relocation is
+ * based.
+ */
+ r_pcrel:1, /* 1 => relocate PC-relative; else absolute
+ * On i960, pc-relative implies 24-bit
+ * address, absolute implies 32-bit.
+ */
+ r_length:2, /* Number of bytes to relocate:
+ * 0 => 1 byte
+ * 1 => 2 bytes -- used for 13 bit pcrel
+ * 2 => 4 bytes
+ */
+ r_extern:1,
+ r_bsr:1, /* Something for the GNU NS32K assembler */
+ r_disp:1, /* Something for the GNU NS32K assembler */
+ r_callj:1, /* 1 if relocation target is an i960 'callj' */
+ r_relaxable:1; /* 1 if enough info is left to relax
+ the data */
+};
diff --git a/contrib/gdb/include/coff/ChangeLog b/contrib/gdb/include/coff/ChangeLog
new file mode 100644
index 0000000..06c7f80
--- /dev/null
+++ b/contrib/gdb/include/coff/ChangeLog
@@ -0,0 +1,622 @@
+Thu Mar 14 15:22:44 1996 Jeffrey A Law (law@cygnus.com)
+
+ * internal.h (R_MEM_INDIRECT): New reloc for the h8300.
+
+Fri Feb 9 10:44:11 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * aux-coff.h: Rename from aux.h, to avoid problems on hapless DOS
+ systems which think that aux is a com port.
+
+Mon Feb 5 18:35:00 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * i960.h (F_I960HX): Define.
+
+Wed Jan 31 13:11:54 1996 Richard Henderson <rth@tamu.edu>
+
+ * aux.h: New file.
+ * internal.h, m68k.h: Protect against multiple inclusion.
+
+Wed Nov 22 13:48:39 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.h (_RCONST, STYP_RCONST, RELOC_SECTION_RCONST): Define.
+ (NUM_RELOC_SECTIONS): Update.
+ * symconst.h (scRConst): Define.
+
+Tue Nov 14 18:54:29 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * internal.h (C_NT_WEAK): Define.
+
+Thu Nov 9 14:08:30 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * rs6000.h (STYP_OVRFLO): Define.
+
+Tue Nov 7 14:38:45 1995 Kim Knuttila <krk@cygnus.com>
+
+ * coff/powerpc.h (IMAGE_NT_OPTIONAL_HDR_MAGIC): Added define.
+ * coff/pe.h: Added defines for file level flags
+
+Mon Nov 6 17:28:01 1995 Harry Dolan <dolan@ssd.intel.com>
+
+ * i860.h: New file, based on i386.h.
+
+Wed Nov 1 15:25:18 1995 Manfred Hollstein KS/EF4A 60/1F/110 #40283 <manfred@lts.sel.alcatel.de>
+
+ * m68k.h (PAGEMAGICEXECSWAPPED): Define.
+ (PAGEMAGICPEXECSWAPPED): Define.
+ (PAGEMAGICPEXECTSHLIB): Define.
+ (PAGEMAGICPEXECPAGED): Define.
+ (_COMMENT): DEFINE.
+ * m88k.h (_COMMENT): Define.
+
+Wed Oct 18 18:36:19 1995 Geoffrey Noer <noer@cygnus.com>
+
+ * sym.h: #if 0'd out runtime_pdr struct because it chokes
+ Visual C++ and there aren't any references to it elsewhere in gdb.
+
+Mon Oct 16 11:12:24 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * rs6000.h (SMALL_AOUTSZ): Define.
+
+ * internal.h (XMC_TD): Define.
+
+Tue Oct 10 18:41:03 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * internal.h (struct internal_aouthdr): Add o_cputype field.
+ * rs6000.h (AOUTHDR): Rename o_resv1 to o_cputype.
+
+Mon Oct 9 14:45:46 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * rs6000.h (AOUTHDR): Add o_maxdata field. Add comments.
+ (_PAD, _LOADER): Define.
+ (STYP_LOADER): Define.
+ * internal.h (struct internal_aouthdr): Add o_maxdata field.
+
+Thu Oct 5 10:02:57 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.h: Define section name macros and STYP macros for various
+ Alpha sections: .got, .hash, .dynsym, .dynstr, .rel.dyn, .conflic,
+ .comment, .liblist, .dynamic.
+
+Wed Oct 4 10:56:35 1995 Kim Knuttila <krk@cygnus.com>
+
+ * pe.h: Moved DOSMAGIC and NT_SIGNATURE defines here
+ * powerpc.h: removed DOSMAGIC, NT_SIGNATURE, and DEFAULT_* defines
+ Also removed other unused defines (various MAGIC ones)
+ * i386.h: removed DOSMAGIC, NT_SIGNATURE, and DEFAULT_* defines
+ * arm.h: removed DOSMAGIC, NT_SIGNATURE, and DEFAULT_* defines
+ * apollo.h: removed unused DEFAULT_* defines
+ * alpha.h: removed unused DEFAULT_* defines
+ * h8500.h: removed unused DEFAULT_* defines
+ * h8300.h: removed unused DEFAULT_* defines
+ * i960.h: removed unused DEFAULT_* defines
+ * m88k.h: removed unused DEFAULT_* defines
+ * we32k.h: removed unused DEFAULT_* defines
+ * rs6000.h: removed unused DEFAULT_* defines
+ * mips.h: removed unused DEFAULT_* defines
+ * m68k.h: removed unused DEFAULT_* defines
+ * z8k.h: removed unused DEFAULT_* defines
+ * w65.h: removed unused DEFAULT_* defines
+ * sparc.h: removed unused DEFAULT_* defines
+ * sh.h: removed unused DEFAULT_* defines
+
+Fri Sep 29 08:40:08 1995 Kim Knuttila <krk@cygnus.com>
+
+ * powerpc.h: Reformatted to GNU coding conventions.
+
+Wed Sep 27 06:50:50 1995 Kim Knuttila <krk@nellie>
+
+ * pe.h: added defines for more section characteristics
+ * powerpc.h (new file): base coff definitions for ppc PE
+
+Tue Sep 12 12:08:20 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * internal.h (struct internal_syment): Change n_numaux field from
+ char to unsigned char.
+
+Fri Sep 1 15:39:36 1995 Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>
+
+ * mips.h (struct rpdr_ext): Define.
+
+Thu Aug 31 16:51:50 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * internal.h (internal_aouthdr, internal_filehdr):
+ don't indirect the pe stuff.
+
+Tue Aug 29 14:16:07 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * i386.h (NT_DEF_RESERVE, NT_DEF_COMMIT): Make the same
+ as 'the other' compiler.
+ * internal.h (NT_IMAGE_BASE): Deleted.
+ (NT_EXE_IMAGE_BASE, NT_DLL_IMAGE_BASE): New.
+ (PE_DEF_SECTION_ALIGNMENT, PE_DEF_FILE_ALIGNMENT): New.
+ (R_IMAGEBASE): New.
+
+Mon Aug 21 18:12:19 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * internal.h: (internal_filehdr): Moved PE stuff into
+ internal_extra_pe_filehdr.
+ (internal_aouthdr): Moved PE stuff into
+ interanl_extra_pe_aouthdr.
+
+Mon Jul 24 14:05:39 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * internal.h: Move R_SH_* relocs from here...
+ * sh.h: ...to here.
+ (R_SH_SWITCH16, R_SH_SWITCH32): Define.
+ (R_SH_USES, R_SH_COUNT, R_SH_ALIGN): Define.
+
+Thu Jun 29 00:04:25 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * internal.h (NT_DEF_RESERVE, NT_DEF_COMMIT): Increase a lot.
+
+Tue May 16 15:08:20 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * internal.h (NT_subsystem, NT_stack_heap): Delete
+
+Tue May 16 15:08:20 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * internal.h (NT_subsystem, NT_stack_heap): Now extern.
+
+Tue Feb 14 17:59:37 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ecoff.h (struct ecoff_fdrtab_entry): Define.
+ (struct ecoff_find_line): Define.
+
+Sat Feb 4 14:38:03 1995 David Mosberger-Tang <davidm@piston.cs.arizona.edu>
+
+ * sym.h (struct pdr): field "prof" added.
+
+ * alpha.h (PDR_BITS1_PROF_*): added, macros for PDR_BITS*_RESERVED_*
+ updated accordingly.
+
+Sun Jan 15 18:38:33 1995 Steve Chamberlain <sac@splat>
+
+ * w65.h: New file.
+
+Wed Nov 23 22:43:38 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * sh.h (SH_ARCH_MAGIC_BIG, SH_ARCH_MAGIC_LITTLE): New.
+ (SHBADMAG): Changed to suit.
+
+Tue Jul 26 17:46:08 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * i960.h (F_I960JX): New macro.
+
+Wed Jul 6 00:48:57 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha.h: Add definitions for alpha file header flags, encoding
+ the object type of the file.
+
+Mon Jun 20 13:47:01 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * ecoff.h (ecoff_swap_tir_in): Remove declaration.
+ (ecoff_swap_tir_out): Likewise.
+ (ecoff_swap_rndx_in, ecoff_swap_rndx_out): Likewise.
+ (struct ecoff_debug_swap): Add new fields: swap_tir_in,
+ swap_rndx_in, swap_tir_out, swap_rndx_out, read_debug_info.
+
+Sun Jun 12 03:51:52 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * symconst.h: Pick up SGI define for stIndirect.
+
+Fri Apr 22 13:05:28 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (REGINFO): Don't define.
+ (struct ecoff_reginfo): Don't define.
+
+ * sh.h (SH_ARCH_MAGIC): Rename from SHMAGIC. SHMAGIC is used by
+ several targets to mean a shared library.
+ (SHBADMAG): Corresponding change.
+
+Thu Apr 14 13:00:53 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (RELOC_BITS3_TYPE_BIG): Changed from 0x1e to 0x3e.
+ (RELOC_BITS3_TYPEHI_LITTLE): Define.
+ (RELOC_BITS3_TYPEHI_SH_LITTLE): Define.
+ (MIPS_R_PCREL16): Change value from 8 to 12 to match Irix 4.
+ (MIPS_R_RELHI): Define.
+ (MIPS_R_RELLO): Define.
+ (MIPS_R_SWITCH): Change value from 9 to 22.
+
+Thu Apr 7 14:19:35 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (MIPS_R_SWITCH): Define.
+
+Thu Mar 31 19:28:33 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * internal.h (internal_aouthdr): Added comments for Apollo fields.
+
+Thu Mar 31 16:28:02 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (STYP_ECOFF_LIB): Define as used on Irix 4.
+
+Fri Mar 25 17:16:55 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (struct ecoff_debug_info): Add adjust field.
+ (struct ecoff_value_adjust): Define.
+
+Tue Mar 22 13:22:47 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (MIPS_R_PCREL16): Define.
+
+Sat Feb 26 10:26:38 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * ecoff.h: Add casts to avoid warnings from SVR4 cc.
+
+Mon Feb 21 09:48:46 1994 Ian Lance Taylor (ian@lisa.cygnus.com)
+
+ * sym.h (struct runtime_pdr): Make field adr bfd_vma, not unsigned
+ long.
+ (SYMR): Make field value bfd_vma, not long.
+
+Fri Feb 4 23:35:53 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * rs6000.h (STYP_DEBUG): Define.
+
+Wed Feb 2 14:31:37 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * internal.h (union internal_auxent): Change x_csect.x_scnlen into
+ a union of a long and a pointer to a symbol. XCOFF sometimes uses
+ this field as a symbol index.
+
+Mon Jan 10 23:54:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (ecoff_debug_info): Remove fields line_end,
+ external_dnr_end, external_pdr_end, external_sym_end,
+ external_opt_end, external_aux_end, ss_end, external_fdr_end.
+ Replace ifdbase with ifdmap.
+
+Wed Jan 5 17:05:36 1994 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * ecoff.h (STYP_EXTENDESC, STYP_COMMENT, STYP_XDATA, STYP_PDATA):
+ Define.
+
+Wed Jan 5 16:58:24 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (NUM_RELOC_SECTIONS): Define.
+
+Tue Dec 21 09:24:56 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * sparc.h (struct external_reloc): Rename field r_addend to
+ r_offset.
+
+Sat Dec 11 16:12:32 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * internal.h (R_DISP7, R_SH_IMM16): New reloc types.
+
+Tue Nov 23 14:23:19 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (struct ecoff_debug_swap): Added *_end fields for all
+ the symbolic information pointers.
+
+ * sym.h: Named the EXTR structure ecoff_extr.
+
+Fri Nov 19 08:21:18 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * sparc.h (RELSZ): Use correct size.
+
+Wed Nov 17 17:18:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (struct ecoff_debug_info): Define.
+
+Tue Nov 2 17:56:57 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (struct ecoff_debug_swap): Define.
+
+Thu Oct 28 17:07:50 1993 Stan Shebs (shebs@rtl.cygnus.com)
+
+ * i386.h (I386LYNXMAGIC): Rename to LYNXCOFFMAGIC.
+ * m68k.h (LYNXCOFFMAGIC): Define.
+ * sparc.h: New file.
+
+Tue Oct 19 15:34:50 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * alpha.h (external_aouthdr): Split four byte padding field into
+ two byte bldrev field and two byte padding field.
+
+ * ecoff.h (_LITA, _PDATA, _XDATA, STYP_LITA): Defined.
+
+Wed Oct 13 15:52:34 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ Sun Oct 10 17:27:10 1993 Troy Rollo (troy@cbme.unsw.edu.au)
+
+ * coff/internal.h: Added o_sri, o_inlib and o_vid for Apollos
+ as well as R_DIR16.
+
+ * coff/apollo.h: New file
+
+Mon Oct 11 17:16:48 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (REGINFO, struct ecoff_reginfo): Define.
+
+Tue Oct 5 10:52:53 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * rs6000.h: Change non-ASCII characters in comment to octal
+ escapes.
+
+Tue Sep 28 03:27:04 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * ecoff.h (_FINI, STYP_ECOFF_FINI): Add to support .fini section.
+
+Fri Sep 24 11:53:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (BADMAG): Recognize MIPS_MAGIC_LITTLE3 and MIPS_MAGIC_BIG3.
+ * ecoff.h: Define MIPS_MAGIC_LITTLE3 and MIPS_MAGIC_BIG3.
+
+Thu Sep 23 21:07:14 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * mips.h (BADMAG): Recognize MIPS_MAGIC_LITTLE2 and MIPS_MAGIC_BIG2.
+ * ecoff.h: Define MIPS_MAGIC_LITTLE2 and MIPS_MAGIC_BIG2.
+
+Thu Sep 16 20:27:21 1993 Jim Kingdon (kingdon@cirdan.cygnus.com)
+
+ * sym.h, symconst.h: Add comment stating these files are not part
+ of GDB, GAS, etc. In 1991, when we asked rms whether we could
+ include these files in GDB (although they are copyrighted by
+ someone besides the FSF), he said it was OK if they were not
+ considered part of GDB.
+
+Fri Sep 10 17:40:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (AUX_PUT_ANY): Cast val argument to bfd_vma.
+
+ * alpha.c (external_aouthdr): Need four bytes of padding between
+ vstamp and tsize.
+
+Tue Sep 7 14:20:43 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff.h (AUX_GET_ANY, AUX_PUT_ANY): Changed to reflect further
+ change in bfd swapping routine names.
+
+Tue Sep 7 10:15:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ecoff.h (AUX_GET_ANY): Change name of _do_getb32 to reflect bfd
+ changes.
+
+Fri Aug 13 14:30:32 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * ecoff.h (RELOC_SECTION_NONE): Define.
+
+Thu Aug 12 11:24:42 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * alpha.h (struct external_reloc): Add r_symndx field.
+ (RELSZ): Correct.
+ (RELOC_BITS*): Correct.
+ (ALPHA_R_*): Define.
+ * ecoff.h (RELOC_SECTION_{XDATA,PDATA,FINI,LITA,ABS}): Define.
+ (r_extern): Undefine.
+ * internal.h (struct internal_reloc): Make r_vaddr bfd_vma rather
+ than long. Add r_extern field.
+
+ * alpha.h (PDR_BITS*): Define.
+ * sym.h (PDR): Give correct names to new fields.
+
+ * ecoff.h: Moved MIPS reloc definitions from here...
+ * mips.h: to here.
+
+Tue Aug 3 11:17:53 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * alpha.h: Corrected external symbolic debugging structures to
+ match actual usage.
+ * internal.h (internal_filehdr, internal_aouthdr,
+ internal_scnhdr): Changed type of some fields to bfd_vma so they
+ can hold 64 bits.
+ * sym.h (HDRR, FDR, PDR, EXTR): Likewise.
+ (PDR): Added new fields found on Alpha.
+ * symconst.h (magicSym2): Define; new value found on Alpha.
+
+ * ecoff.h: New file.
+ * alpha.h, mips.h: Moved common information into ecoff.h. Moved
+ external structure definitions in from ecoff-ext.h.
+ * ecoff-ext.h: Removed; information now in alpha.h and mips.h.
+
+Sun Jul 18 21:43:59 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * i386.h: Recognize I386PTXMAGIC.
+
+Fri Jul 16 09:54:35 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h (MIPS_AOUT_{OZ}MAGIC): Renamed from {OZ}MAGIC.
+
+Thu Jul 15 12:23:55 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m88k.h (union external_auxent): Move x_fcn back inside x_fcnary.
+ ({GET,PUT}_FCN_{LNNOPTR,ENDNDX}): Adjust accordingly.
+
+Sun Jul 11 18:00:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m68k.h: Define MC68KBCSMAGIC.
+
+Thu Jun 10 11:46:28 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h (_INIT, STYP_MIPS_INIT): Define (used on Irix4).
+ (STYP_OTHER_LOAD): Define as STYP_MIPS_INIT.
+
+Wed Jun 9 15:09:09 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h (OMAGIC): Define.
+
+Mon Apr 26 18:04:47 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * internal.h, sh.h: Support for SH.
+
+Sat Apr 24 21:34:59 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * a29k.h: Define _LIT.
+
+Fri Apr 23 18:41:23 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * alpha.h: New file.
+
+Thu Apr 8 12:36:34 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * internal.h (C_SHADOW, C_VERSION): Copied in from m88k.h.
+ * m88k.h, i386.h, we32k.h: Don't define all the storage classes;
+ they're already in internal.h.
+
+Wed Apr 7 11:51:24 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * internal.h: Change n_sclass to unsigned char.
+ Change C_EFCN to 0xff, change RS/6000 dbx symbols
+ to no longer be signed.
+
+Fri Mar 19 14:52:56 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * internal.h: Add H8/500 reloc types.
+
+Wed Mar 17 09:46:03 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * ecoff-ext.h (AUX_PUT_ANY): Don't use void values in branches of
+ conditional expression.
+
+Thu Mar 4 14:12:06 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * ecoff-ext.h (AUX_GET_*): Rewrote to use new macro AUX_GET_ANY.
+ (AUX_PUT_*): New macros corresponding to the AUX_GET macros.
+ (ecoff_swap_tir_out): Added prototype.
+
+ * mips.h (N_BTMASK, N_TMASK, N_BTSHFT, N_TSHIFT): Define; these
+ are needed to interpret gcc debugging output.
+
+Tue Feb 9 07:43:27 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * we32k.h (BTYPE, ISPTR, ISFCN, ISARY, DECREF): Removed
+ more definitions duplicated in internal.h.
+
+Wed Feb 3 09:18:24 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h (RELOC_BITS3_TYPE_*): Correct for big endian machines.
+
+Mon Jan 25 11:35:51 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * internal.h (internal_aouthdr): Added additional fields used only
+ by MIPS ECOFF.
+
+Thu Jan 21 10:28:38 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h (AOUTHDR): Added additional fields used by ECOFF.
+
+Tue Jan 19 12:21:19 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i386.h, we32k.h (N_*, T_*, DT_*): Removed still more definitions
+ duplicated in internal.h.
+
+ * mips.h (RELOC_SECTION_*, ECOFF_R_*): Defined constants for ECOFF
+ relocs.
+
+Fri Jan 15 18:17:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff-ext.h: Added prototypes for new ECOFF swapping functions.
+ (opt_ext): New structure.
+ * mips.h (ZMAGIC): Defined to be 0413.
+ (_LIB): Defined to be ".lib"
+ (external_reloc): MIPS ECOFF relocs are only 8 bytes. Added
+ macros to aid in swapping.
+
+Fri Jan 8 16:19:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ecoff-ext.h: Added prototypes for ECOFF swapping functions.
+ * internal.h (internal_scnhdr): Always provide s_align field, not
+ just on i960.
+ (internal_reloc): Always provide r_size field, not just on
+ RS/6000.
+ * mips.h (_RDATA, _SDATA, _SBSS, _LIT4, _LIT8, STYP_RDATA,
+ STYP_SDATA, STYP_SBSS, STYP_LIT4, STYP_LIT8): Defined.
+ (CODE_MASK, MIPS_IS_STAB, MIPS_MARK_STAB, MIPS_UNMARK_STAB,
+ STABS_SYMBOL): Moved in from gdb/mipsread.c.
+
+Wed Jan 6 14:01:46 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i386.h, we32k.h: removed STYP_* defines, since they duplicated
+ those in internal.h.
+
+Tue Dec 29 15:40:07 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * i386.h: define I386AIXMAGIC for Danbury AIX PS/2 compiler.
+
+Sat Dec 12 16:07:57 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * i386.h: don't define BTYPE, ISPTR, ISFCN, ISARY, DECREF: they
+ are defined in internal.h.
+
+Thu Nov 12 09:52:01 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * internal.h: (internal_reloc): r_offset is now a long.
+ * z8k.h: slight comment enhancement
+
+Wed Sep 30 07:46:08 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * internal.h: changed z8k reloc types
+
+Fri Aug 28 10:16:31 1992 Brendan Kehoe (brendan@cygnus.com)
+
+ * we32k.h: new file
+
+Thu Aug 27 13:00:01 1992 Brendan Kehoe (brendan@cygnus.com)
+
+ * symconst.h: comment out cruft at the end of #endif
+
+Tue Aug 25 15:06:49 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * internal.h: added #define for STYP_LIT, removed from a29k and
+ h8300.
+
+ * z8k.h: added z8000 support
+
+Thu Jul 16 16:32:00 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * internal.h: added R_RELLONG_NEG reloc type
+
+Fri Jun 12 20:11:04 1992 John Gilmore (gnu at cygnus.com)
+
+ * symconst.h: Fix unterminated comment.
+
+Wed Jun 10 07:57:49 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * i386.h: a.out magic numbers from
+ mohring@informatik.tu-muenchen.de
+
+Mon Jun 8 20:13:33 1992 John Gilmore (gnu at cygnus.com)
+
+ * ecoff-ext.h, mips.h: Use unsigned chars everywhere.
+ (Suggested by Antti Miettinen.)
+
+Tue Apr 14 15:18:44 1992 John Gilmore (gnu at cygnus.com)
+
+ * sym.h: Add comments.
+ * symconst.h: Merge with Fred's changes.
+
+Tue Apr 14 14:30:05 1992 Fred Fish (fnf@cygnus.com)
+
+ * symconst.h: Pick up SGI defines for stStruct, stUnion, stEnum,
+ langCplusplus, and langCplusplusV2.
+
+Thu Apr 2 19:47:43 1992 John Gilmore (gnu at cygnus.com)
+
+ * sym.h, symconst.h: MIPS has provided redistributable versions
+ of these files. Thanks!
+ * ecoff-ext.h: Add weakext bit to match new sym.h.
+
+Fri Mar 6 00:10:46 1992 John Gilmore (gnu at cygnus.com)
+
+ * ecoff-ext.h: Add relative file descriptors.
+
+Thu Feb 27 11:53:04 1992 John Gilmore (gnu at cygnus.com)
+
+ * ecoff-ext.h: New file for external (in-file) form of ecoff
+ symbol structures.
+
+Thu Feb 6 11:33:32 1992 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * h8300.h: made the external_lineno l_lnno field 4 bytes wide.
+ andded GET/PUT_LINENO_LNNO macros
+
+Sat Nov 30 20:38:35 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * ChangeLog, a29k.h, h8300.h, i386.h, i960.h, internal.h, m68k.h,
+ m88k.h, mips.h, rs6000.h: move from above coff-<foo>.h
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/include/coff/a29k.h b/contrib/gdb/include/coff/a29k.h
new file mode 100644
index 0000000..13b35f2
--- /dev/null
+++ b/contrib/gdb/include/coff/a29k.h
@@ -0,0 +1,305 @@
+/* COFF spec for AMD 290*0
+ Contributed by David Wood @ New York University.
+ */
+
+#ifndef AMD
+# define AMD
+#endif
+
+/****************************************************************/
+
+/*
+** File Header and related definitions
+*/
+
+struct external_filehdr
+{
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof (FILHDR)
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Magic numbers for Am29000
+** (AT&T will assign the "real" magic number)
+*/
+
+#define SIPFBOMAGIC 0572 /* Am29000 (Byte 0 is MSB) */
+#define SIPRBOMAGIC 0573 /* Am29000 (Byte 0 is LSB) */
+
+
+#define A29K_MAGIC_BIG SIPFBOMAGIC
+#define A29K_MAGIC_LITTLE SIPRBOMAGIC
+#define A29KBADMAG(x) (((x).f_magic!=A29K_MAGIC_BIG) && \
+ ((x).f_magic!=A29K_MAGIC_LITTLE))
+
+#define OMAGIC A29K_MAGIC_BIG
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** File header flags currently known to us.
+**
+** Am29000 will use the F_AR32WR and F_AR32W flags to indicate
+** the byte ordering in the file.
+*/
+
+/*--------------------------------------------------------------*/
+
+/*
+** Optional (a.out) header
+*/
+
+typedef struct external_aouthdr
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+} AOUTHDR;
+
+#define AOUTSZ (sizeof(AOUTHDR))
+#define AOUTHDRSZ (sizeof(AOUTHDR))
+
+/* aouthdr magic numbers */
+#define NMAGIC 0410 /* separate i/d executable */
+#define SHMAGIC 0406 /* NYU/Ultra3 shared data executable
+ (writable text) */
+
+#define _ETEXT "_etext"
+
+/*--------------------------------------------------------------*/
+
+/*
+** Section header and related definitions
+*/
+
+struct external_scnhdr
+{
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof (SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _LIT ".lit"
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Section types - with additional section type for global
+** registers which will be relocatable for the Am29000.
+**
+** In instances where it is necessary for a linker to produce an
+** output file which contains text or data not based at virtual
+** address 0, e.g. for a ROM, then the linker should accept
+** address base information as command input and use PAD sections
+** to skip over unused addresses.
+*/
+
+#define STYP_BSSREG 0x1200 /* Global register area (like STYP_INFO) */
+#define STYP_ENVIR 0x2200 /* Environment (like STYP_INFO) */
+#define STYP_ABS 0x4000 /* Absolute (allocated, not reloc, loaded) */
+
+/*--------------------------------------------------------------*/
+
+/*
+** Relocation information declaration and related definitions
+*/
+
+struct external_reloc {
+ char r_vaddr[4]; /* (virtual) address of reference */
+ char r_symndx[4]; /* index into symbol table */
+ char r_type[2]; /* relocation type */
+};
+
+#define RELOC struct external_reloc
+#define RELSZ 10 /* sizeof (RELOC) */
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Relocation types for the Am29000
+*/
+
+#define R_ABS 0 /* reference is absolute */
+
+#define R_IREL 030 /* instruction relative (jmp/call) */
+#define R_IABS 031 /* instruction absolute (jmp/call) */
+#define R_ILOHALF 032 /* instruction low half (const) */
+#define R_IHIHALF 033 /* instruction high half (consth) part 1 */
+#define R_IHCONST 034 /* instruction high half (consth) part 2 */
+ /* constant offset of R_IHIHALF relocation */
+#define R_BYTE 035 /* relocatable byte value */
+#define R_HWORD 036 /* relocatable halfword value */
+#define R_WORD 037 /* relocatable word value */
+
+#define R_IGLBLRC 040 /* instruction global register RC */
+#define R_IGLBLRA 041 /* instruction global register RA */
+#define R_IGLBLRB 042 /* instruction global register RB */
+
+/*
+NOTE:
+All the "I" forms refer to 29000 instruction formats. The linker is
+expected to know how the numeric information is split and/or aligned
+within the instruction word(s). R_BYTE works for instructions, too.
+
+If the parameter to a CONSTH instruction is a relocatable type, two
+relocation records are written. The first has an r_type of R_IHIHALF
+(33 octal) and a normal r_vaddr and r_symndx. The second relocation
+record has an r_type of R_IHCONST (34 octal), a normal r_vaddr (which
+is redundant), and an r_symndx containing the 32-bit constant offset
+to the relocation instead of the actual symbol table index. This
+second record is always written, even if the constant offset is zero.
+The constant fields of the instruction are set to zero.
+*/
+
+/*--------------------------------------------------------------*/
+
+/*
+** Line number entry declaration and related definitions
+*/
+
+struct external_lineno
+{
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+#define LINENO struct external_lineno
+#define LINESZ 6 /* sizeof (LINENO) */
+
+/*--------------------------------------------------------------*/
+
+/*
+** Symbol entry declaration and related definitions
+*/
+
+#define E_SYMNMLEN 8 /* Number of characters in a symbol name */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ sizeof(SYMENT)
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Storage class definitions - new classes for global registers.
+*/
+
+#define C_GLBLREG 19 /* global register */
+#define C_EXTREG 20 /* external global register */
+#define C_DEFREG 21 /* ext. def. of global register */
+
+
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/*
+** Derived symbol mask/shifts.
+*/
+
+#define N_BTMASK (0xf)
+#define N_BTSHFT (4)
+#define N_TMASK (0x30)
+#define N_TSHIFT (2)
+
+/*--------------------------------------------------------------*/
+
+/*
+** Auxiliary symbol table entry declaration and related
+** definitions.
+*/
+
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+};
+
+#define AUXENT union external_auxent
+#define AUXESZ 18
diff --git a/contrib/gdb/include/coff/alpha.h b/contrib/gdb/include/coff/alpha.h
new file mode 100644
index 0000000..1f1bfb6
--- /dev/null
+++ b/contrib/gdb/include/coff/alpha.h
@@ -0,0 +1,342 @@
+/* ECOFF support on Alpha machines.
+ coff/ecoff.h must be included before this file. */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ unsigned char f_magic[2]; /* magic number */
+ unsigned char f_nscns[2]; /* number of sections */
+ unsigned char f_timdat[4]; /* time & date stamp */
+ unsigned char f_symptr[8]; /* file pointer to symtab */
+ unsigned char f_nsyms[4]; /* number of symtab entries */
+ unsigned char f_opthdr[2]; /* sizeof(optional hdr) */
+ unsigned char f_flags[2]; /* flags */
+};
+
+/* Magic numbers are defined in coff/ecoff.h. */
+#define ALPHA_ECOFF_BADMAG(x) ((x).f_magic!=ALPHA_MAGIC)
+
+/* The object type is encoded in the f_flags. */
+#define F_ALPHA_OBJECT_TYPE_MASK 0x3000
+#define F_ALPHA_NO_SHARED 0x1000
+#define F_ALPHA_SHARABLE 0x2000
+#define F_ALPHA_CALL_SHARED 0x3000
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct external_aouthdr
+{
+ unsigned char magic[2]; /* type of file */
+ unsigned char vstamp[2]; /* version stamp */
+ unsigned char bldrev[2]; /* ?? */
+ unsigned char padding[2]; /* pad to quadword boundary */
+ unsigned char tsize[8]; /* text size in bytes */
+ unsigned char dsize[8]; /* initialized data " " */
+ unsigned char bsize[8]; /* uninitialized data " " */
+ unsigned char entry[8]; /* entry pt. */
+ unsigned char text_start[8]; /* base of text used for this file */
+ unsigned char data_start[8]; /* base of data used for this file */
+ unsigned char bss_start[8]; /* base of bss used for this file */
+ unsigned char gprmask[4]; /* bitmask of general registers used */
+ unsigned char fprmask[4]; /* bitmask of floating point registers used */
+ unsigned char gp_value[8]; /* value for gp register */
+} AOUTHDR;
+
+/* compute size of a header */
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+/********************** SECTION HEADER **********************/
+
+struct external_scnhdr {
+ unsigned char s_name[8]; /* section name */
+ unsigned char s_paddr[8]; /* physical address, aliased s_nlib */
+ unsigned char s_vaddr[8]; /* virtual address */
+ unsigned char s_size[8]; /* section size */
+ unsigned char s_scnptr[8]; /* file ptr to raw data for section */
+ unsigned char s_relptr[8]; /* file ptr to relocation */
+ unsigned char s_lnnoptr[8]; /* file ptr to line numbers */
+ unsigned char s_nreloc[2]; /* number of relocation entries */
+ unsigned char s_nlnno[2]; /* number of line number entries*/
+ unsigned char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct external_reloc {
+ unsigned char r_vaddr[8];
+ unsigned char r_symndx[4];
+ unsigned char r_bits[4];
+};
+
+#define RELOC struct external_reloc
+#define RELSZ 16
+
+/* Constants to unpack the r_bits field. The Alpha seems to always be
+ little endian, so I haven't bothered to define big endian variants
+ of these. */
+
+#define RELOC_BITS0_TYPE_LITTLE 0xff
+#define RELOC_BITS0_TYPE_SH_LITTLE 0
+
+#define RELOC_BITS1_EXTERN_LITTLE 0x01
+
+#define RELOC_BITS1_OFFSET_LITTLE 0x7e
+#define RELOC_BITS1_OFFSET_SH_LITTLE 1
+
+#define RELOC_BITS1_RESERVED_LITTLE 0x80
+#define RELOC_BITS1_RESERVED_SH_LITTLE 7
+#define RELOC_BITS2_RESERVED_LITTLE 0xff
+#define RELOC_BITS2_RESERVED_SH_LEFT_LITTLE 1
+#define RELOC_BITS3_RESERVED_LITTLE 0x03
+#define RELOC_BITS3_RESERVED_SH_LEFT_LITTLE 9
+
+#define RELOC_BITS3_SIZE_LITTLE 0xfc
+#define RELOC_BITS3_SIZE_SH_LITTLE 2
+
+/* The r_type field in a reloc is one of the following values. */
+#define ALPHA_R_IGNORE 0
+#define ALPHA_R_REFLONG 1
+#define ALPHA_R_REFQUAD 2
+#define ALPHA_R_GPREL32 3
+#define ALPHA_R_LITERAL 4
+#define ALPHA_R_LITUSE 5
+#define ALPHA_R_GPDISP 6
+#define ALPHA_R_BRADDR 7
+#define ALPHA_R_HINT 8
+#define ALPHA_R_SREL16 9
+#define ALPHA_R_SREL32 10
+#define ALPHA_R_SREL64 11
+#define ALPHA_R_OP_PUSH 12
+#define ALPHA_R_OP_STORE 13
+#define ALPHA_R_OP_PSUB 14
+#define ALPHA_R_OP_PRSHIFT 15
+#define ALPHA_R_GPVALUE 16
+
+/********************** SYMBOLIC INFORMATION **********************/
+
+/* Written by John Gilmore. */
+
+/* ECOFF uses COFF-like section structures, but its own symbol format.
+ This file defines the symbol format in fields whose size and alignment
+ will not vary on different host systems. */
+
+/* File header as a set of bytes */
+
+struct hdr_ext {
+ unsigned char h_magic[2];
+ unsigned char h_vstamp[2];
+ unsigned char h_ilineMax[4];
+ unsigned char h_idnMax[4];
+ unsigned char h_ipdMax[4];
+ unsigned char h_isymMax[4];
+ unsigned char h_ioptMax[4];
+ unsigned char h_iauxMax[4];
+ unsigned char h_issMax[4];
+ unsigned char h_issExtMax[4];
+ unsigned char h_ifdMax[4];
+ unsigned char h_crfd[4];
+ unsigned char h_iextMax[4];
+ unsigned char h_cbLine[8];
+ unsigned char h_cbLineOffset[8];
+ unsigned char h_cbDnOffset[8];
+ unsigned char h_cbPdOffset[8];
+ unsigned char h_cbSymOffset[8];
+ unsigned char h_cbOptOffset[8];
+ unsigned char h_cbAuxOffset[8];
+ unsigned char h_cbSsOffset[8];
+ unsigned char h_cbSsExtOffset[8];
+ unsigned char h_cbFdOffset[8];
+ unsigned char h_cbRfdOffset[8];
+ unsigned char h_cbExtOffset[8];
+};
+
+/* File descriptor external record */
+
+struct fdr_ext {
+ unsigned char f_adr[8];
+ unsigned char f_cbLineOffset[8];
+ unsigned char f_cbLine[8];
+ unsigned char f_cbSs[8];
+ unsigned char f_rss[4];
+ unsigned char f_issBase[4];
+ unsigned char f_isymBase[4];
+ unsigned char f_csym[4];
+ unsigned char f_ilineBase[4];
+ unsigned char f_cline[4];
+ unsigned char f_ioptBase[4];
+ unsigned char f_copt[4];
+ unsigned char f_ipdFirst[4];
+ unsigned char f_cpd[4];
+ unsigned char f_iauxBase[4];
+ unsigned char f_caux[4];
+ unsigned char f_rfdBase[4];
+ unsigned char f_crfd[4];
+ unsigned char f_bits1[1];
+ unsigned char f_bits2[3];
+ unsigned char f_padding[4];
+};
+
+#define FDR_BITS1_LANG_BIG 0xF8
+#define FDR_BITS1_LANG_SH_BIG 3
+#define FDR_BITS1_LANG_LITTLE 0x1F
+#define FDR_BITS1_LANG_SH_LITTLE 0
+
+#define FDR_BITS1_FMERGE_BIG 0x04
+#define FDR_BITS1_FMERGE_LITTLE 0x20
+
+#define FDR_BITS1_FREADIN_BIG 0x02
+#define FDR_BITS1_FREADIN_LITTLE 0x40
+
+#define FDR_BITS1_FBIGENDIAN_BIG 0x01
+#define FDR_BITS1_FBIGENDIAN_LITTLE 0x80
+
+#define FDR_BITS2_GLEVEL_BIG 0xC0
+#define FDR_BITS2_GLEVEL_SH_BIG 6
+#define FDR_BITS2_GLEVEL_LITTLE 0x03
+#define FDR_BITS2_GLEVEL_SH_LITTLE 0
+
+/* We ignore the `reserved' field in bits2. */
+
+/* Procedure descriptor external record */
+
+struct pdr_ext {
+ unsigned char p_adr[8];
+ unsigned char p_cbLineOffset[8];
+ unsigned char p_isym[4];
+ unsigned char p_iline[4];
+ unsigned char p_regmask[4];
+ unsigned char p_regoffset[4];
+ unsigned char p_iopt[4];
+ unsigned char p_fregmask[4];
+ unsigned char p_fregoffset[4];
+ unsigned char p_frameoffset[4];
+ unsigned char p_lnLow[4];
+ unsigned char p_lnHigh[4];
+ unsigned char p_gp_prologue[1];
+ unsigned char p_bits1[1];
+ unsigned char p_bits2[1];
+ unsigned char p_localoff[1];
+ unsigned char p_framereg[2];
+ unsigned char p_pcreg[2];
+};
+
+#define PDR_BITS1_GP_USED_BIG 0x80
+#define PDR_BITS1_REG_FRAME_BIG 0x40
+#define PDR_BITS1_PROF_BIG 0x20
+#define PDR_BITS1_RESERVED_BIG 0x1f
+#define PDR_BITS1_RESERVED_SH_LEFT_BIG 8
+#define PDR_BITS2_RESERVED_BIG 0xff
+#define PDR_BITS2_RESERVED_SH_BIG 0
+
+#define PDR_BITS1_GP_USED_LITTLE 0x01
+#define PDR_BITS1_REG_FRAME_LITTLE 0x02
+#define PDR_BITS1_PROF_LITTLE 0x04
+#define PDR_BITS1_RESERVED_LITTLE 0xf8
+#define PDR_BITS1_RESERVED_SH_LITTLE 3
+#define PDR_BITS2_RESERVED_LITTLE 0xff
+#define PDR_BITS2_RESERVED_SH_LEFT_LITTLE 5
+
+/* Line numbers */
+
+struct line_ext {
+ unsigned char l_line[4];
+};
+
+/* Symbol external record */
+
+struct sym_ext {
+ unsigned char s_value[8];
+ unsigned char s_iss[4];
+ unsigned char s_bits1[1];
+ unsigned char s_bits2[1];
+ unsigned char s_bits3[1];
+ unsigned char s_bits4[1];
+};
+
+#define SYM_BITS1_ST_BIG 0xFC
+#define SYM_BITS1_ST_SH_BIG 2
+#define SYM_BITS1_ST_LITTLE 0x3F
+#define SYM_BITS1_ST_SH_LITTLE 0
+
+#define SYM_BITS1_SC_BIG 0x03
+#define SYM_BITS1_SC_SH_LEFT_BIG 3
+#define SYM_BITS1_SC_LITTLE 0xC0
+#define SYM_BITS1_SC_SH_LITTLE 6
+
+#define SYM_BITS2_SC_BIG 0xE0
+#define SYM_BITS2_SC_SH_BIG 5
+#define SYM_BITS2_SC_LITTLE 0x07
+#define SYM_BITS2_SC_SH_LEFT_LITTLE 2
+
+#define SYM_BITS2_RESERVED_BIG 0x10
+#define SYM_BITS2_RESERVED_LITTLE 0x08
+
+#define SYM_BITS2_INDEX_BIG 0x0F
+#define SYM_BITS2_INDEX_SH_LEFT_BIG 16
+#define SYM_BITS2_INDEX_LITTLE 0xF0
+#define SYM_BITS2_INDEX_SH_LITTLE 4
+
+#define SYM_BITS3_INDEX_SH_LEFT_BIG 8
+#define SYM_BITS3_INDEX_SH_LEFT_LITTLE 4
+
+#define SYM_BITS4_INDEX_SH_LEFT_BIG 0
+#define SYM_BITS4_INDEX_SH_LEFT_LITTLE 12
+
+/* External symbol external record */
+
+struct ext_ext {
+ struct sym_ext es_asym;
+ unsigned char es_bits1[1];
+ unsigned char es_bits2[3];
+ unsigned char es_ifd[4];
+};
+
+#define EXT_BITS1_JMPTBL_BIG 0x80
+#define EXT_BITS1_JMPTBL_LITTLE 0x01
+
+#define EXT_BITS1_COBOL_MAIN_BIG 0x40
+#define EXT_BITS1_COBOL_MAIN_LITTLE 0x02
+
+#define EXT_BITS1_WEAKEXT_BIG 0x20
+#define EXT_BITS1_WEAKEXT_LITTLE 0x04
+
+/* Dense numbers external record */
+
+struct dnr_ext {
+ unsigned char d_rfd[4];
+ unsigned char d_index[4];
+};
+
+/* Relative file descriptor */
+
+struct rfd_ext {
+ unsigned char rfd[4];
+};
+
+/* Optimizer symbol external record */
+
+struct opt_ext {
+ unsigned char o_bits1[1];
+ unsigned char o_bits2[1];
+ unsigned char o_bits3[1];
+ unsigned char o_bits4[1];
+ struct rndx_ext o_rndx;
+ unsigned char o_offset[4];
+};
+
+#define OPT_BITS2_VALUE_SH_LEFT_BIG 16
+#define OPT_BITS2_VALUE_SH_LEFT_LITTLE 0
+
+#define OPT_BITS3_VALUE_SH_LEFT_BIG 8
+#define OPT_BITS3_VALUE_SH_LEFT_LITTLE 8
+
+#define OPT_BITS4_VALUE_SH_LEFT_BIG 0
+#define OPT_BITS4_VALUE_SH_LEFT_LITTLE 16
diff --git a/contrib/gdb/include/coff/apollo.h b/contrib/gdb/include/coff/apollo.h
new file mode 100644
index 0000000..c481d48
--- /dev/null
+++ b/contrib/gdb/include/coff/apollo.h
@@ -0,0 +1,248 @@
+/*** coff information for Apollo M68K */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+/* Motorola 68000/68008/68010/68020 */
+#define MC68MAGIC 0520
+#define MC68KWRMAGIC 0520 /* writeable text segments */
+#define MC68TVMAGIC 0521
+#define MC68KROMAGIC 0521 /* readonly shareable text segments */
+#define MC68KPGMAGIC 0522 /* demand paged text segments */
+#define M68MAGIC 0210
+#define M68TVMAGIC 0211
+
+/* Apollo 68000-based machines have a different magic number. This comes
+ * from /usr/include/apollo/filehdr.h
+ */
+#define APOLLOM68KMAGIC 0627
+
+#define OMAGIC M68MAGIC
+#define M68KBADMAG(x) (((x).f_magic!=MC68MAGIC) && ((x).f_magic!=MC68KWRMAGIC) && ((x).f_magic!=MC68TVMAGIC) && \
+ ((x).f_magic!=MC68KROMAGIC) && ((x).f_magic!=MC68KPGMAGIC) && ((x).f_magic!=M68MAGIC) && ((x).f_magic!=M68TVMAGIC) && \
+ ((x).f_magic!=APOLLOM68KMAGIC) )
+
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+ char o_sri[4]; /* Apollo specific - .sri data pointer */
+ char o_inlib[4]; /* Apollo specific - .inlib data pointer */
+ char vid[8]; /* Apollo specific - 64 bit version ID */
+}
+AOUTHDR;
+
+#define APOLLO_COFF_VERSION_NUMBER 1 /* the value of the aouthdr magic */
+#define AOUTHDRSZ (sizeof(AOUTHDR))
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+/********************** SECTION HEADER **********************/
+
+struct external_scnhdr {
+ /* Apollo allow for larger section names by allowing it to be in
+ * the string table.
+ */
+ char s_name[8];
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/* If s_zeores is all zeroes, s_offset gives the real location of the name
+ * in the string table.
+ */
+
+#define s_zeroes section_name.s_name
+#define s_offset (section_name.s_name+4)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _TV ".tv"
+#define _INIT ".init"
+#define _FINI ".fini"
+#define _LINES ".lines"
+#define _BLOCKS ".blocks"
+#define _SRI ".sri" /* Static Resource Information (systype,
+ et al.) */
+#define _MIR ".mir" /* Module Information Records */
+#define _APTV ".aptv" /* Apollo-style transfer vectors. */
+#define _INLIB ".inlib" /* Shared Library information */
+#define _RWDI ".rwdi" /* Read/write data initialization directives for
+ compressed sections */
+#define _UNWIND ".unwind" /* Stack unwind information */
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+#ifdef M68K_COFF_OFFSET
+ char r_offset[4];
+#endif
+
+};
+
+
+#define RELOC struct external_reloc
+
+#define RELSZ sizeof(struct external_reloc)
+
+/* Apollo specific STYP flags */
+
+#define STYP_RELOCATED_NOT_LOADED 0x00010000 /* Section is relocated normally during linking, but need
+ not be loaded during program execution */
+#define STYP_DEBUG 0x00020000 /* debug section */
+#define STYP_OVERLAY 0x00040000 /* Section is overlayed */
+#define STYP_INSTRUCTION 0x00200000 /* Section contains executable code */
+
+#define STYP_ZERO 0x00800000 /* Section is initialized to zero */
+#define STYP_INSTALLED 0x02000000 /* Section should be installable in KGT */
+#define STYP_LOOK_INSTALLED 0x04000000 /* Look for section in KGT */
+#define STYP_SECALIGN1 0x08000000 /* Specially aligned section */
+#define STYP_SECALIGN2 0x10000000 /* " " " */
+#define STYP_COMPRESSED 0x20000000 /* No section data per se (s_scnptr = 0), but there are
+ initialization directives for it in .rwdi section
+ (used in conjunction with STYP_BSS) */
diff --git a/contrib/gdb/include/coff/arm.h b/contrib/gdb/include/coff/arm.h
new file mode 100644
index 0000000..33b11cb
--- /dev/null
+++ b/contrib/gdb/include/coff/arm.h
@@ -0,0 +1,215 @@
+/*** coff information for the ARM */
+
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved external references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+
+
+
+#define ARMMAGIC 0xa00 /* I just made these up */
+
+#define ARMBADMAG(x) (((x).f_magic != ARMMAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+
+
+}
+AOUTHDR;
+
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+#define OMAGIC 0404 /* object files, eg as output */
+#define ZMAGIC 0413 /* demand load format, eg normal ld output */
+#define STMAGIC 0401 /* target shlib */
+#define SHMAGIC 0443 /* host shlib */
+
+
+/* define some NT default values */
+/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT 0x200
+#define NT_DEF_RESERVE 0x100000
+#define NT_DEF_COMMIT 0x1000
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _COMMENT ".comment"
+#define _LIB ".lib"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ 6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+#define N_BTMASK (0xf)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+# define _ETEXT "etext"
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+ char r_offset[4];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ sizeof (RELOC)
diff --git a/contrib/gdb/include/coff/aux-coff.h b/contrib/gdb/include/coff/aux-coff.h
new file mode 100644
index 0000000..c89c124
--- /dev/null
+++ b/contrib/gdb/include/coff/aux-coff.h
@@ -0,0 +1,31 @@
+/* Modifications of internal.h and m68k.h needed by A/UX
+ Suggested by Ian Lance Taylor <ian@cygnus.com> */
+
+#ifndef GNU_COFF_AUX_H
+#define GNU_COFF_AUX_H 1
+
+#include "coff/internal.h"
+#include "coff/m68k.h"
+
+/* Section contains 64-byte padded pathnames of shared libraries */
+#undef STYP_LIB
+#define STYP_LIB 0x200
+
+/* Section contains shared library initialization code */
+#undef STYP_INIT
+#define STYP_INIT 0x400
+
+/* Section contains .ident information */
+#undef STYP_IDENT
+#define STYP_IDENT 0x800
+
+/* Section types used by bfd and gas not defined (directly) by A/UX */
+#undef STYP_OVER
+#define STYP_OVER 0
+#undef STYP_INFO
+#define STYP_INFO STYP_IDENT
+
+/* Traditional name of the section tagged with STYP_LIB */
+#define _LIB ".lib"
+
+#endif /* GNU_COFF_AUX_H */
diff --git a/contrib/gdb/include/coff/ecoff.h b/contrib/gdb/include/coff/ecoff.h
new file mode 100644
index 0000000..120f888
--- /dev/null
+++ b/contrib/gdb/include/coff/ecoff.h
@@ -0,0 +1,408 @@
+#ifndef ECOFF_H
+#define ECOFF_H
+
+/* Generic ECOFF support.
+ This does not include symbol information, found in sym.h and
+ symconst.h. */
+
+/* Mips magic numbers used in filehdr. MIPS_MAGIC_LITTLE is used on
+ little endian machines. MIPS_MAGIC_BIG is used on big endian
+ machines. Where is MIPS_MAGIC_1 from? */
+#define MIPS_MAGIC_1 0x0180
+#define MIPS_MAGIC_LITTLE 0x0162
+#define MIPS_MAGIC_BIG 0x0160
+
+/* These are the magic numbers used for MIPS code compiled at ISA
+ level 2. */
+#define MIPS_MAGIC_LITTLE2 0x0166
+#define MIPS_MAGIC_BIG2 0x0163
+
+/* These are the magic numbers used for MIPS code compiled at ISA
+ level 3. */
+#define MIPS_MAGIC_LITTLE3 0x142
+#define MIPS_MAGIC_BIG3 0x140
+
+/* Alpha magic numbers used in filehdr. */
+#define ALPHA_MAGIC 0x183
+
+/* Magic numbers used in a.out header. */
+#define ECOFF_AOUT_OMAGIC 0407 /* not demand paged (ld -N). */
+#define ECOFF_AOUT_ZMAGIC 0413 /* demand load format, eg normal ld output */
+
+/* Names of special sections. */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#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"
+#define _GOT ".got"
+#define _HASH ".hash"
+#define _DYNSYM ".dynsym"
+#define _DYNSTR ".dynstr"
+#define _RELDYN ".rel.dyn"
+#define _CONFLIC ".conflic"
+#define _COMMENT ".comment"
+#define _LIBLIST ".liblist"
+#define _DYNAMIC ".dynamic"
+#define _RCONST ".rconst"
+
+/* ECOFF uses some additional section flags. */
+#define STYP_RDATA 0x100
+#define STYP_SDATA 0x200
+#define STYP_SBSS 0x400
+#define STYP_GOT 0x1000
+#define STYP_DYNAMIC 0x2000
+#define STYP_DYNSYM 0x4000
+#define STYP_RELDYN 0x8000
+#define STYP_DYNSTR 0x10000
+#define STYP_HASH 0x20000
+#define STYP_LIBLIST 0x40000
+#define STYP_CONFLIC 0x100000
+#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_RCONST 0x2200000
+#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"
+
+/* 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. */
+#define RELOC_SECTION_NONE 0
+#define RELOC_SECTION_TEXT 1
+#define RELOC_SECTION_RDATA 2
+#define RELOC_SECTION_DATA 3
+#define RELOC_SECTION_SDATA 4
+#define RELOC_SECTION_SBSS 5
+#define RELOC_SECTION_BSS 6
+#define RELOC_SECTION_INIT 7
+#define RELOC_SECTION_LIT8 8
+#define RELOC_SECTION_LIT4 9
+#define RELOC_SECTION_XDATA 10
+#define RELOC_SECTION_PDATA 11
+#define RELOC_SECTION_FINI 12
+#define RELOC_SECTION_LITA 13
+#define RELOC_SECTION_ABS 14
+#define RELOC_SECTION_RCONST 15
+
+#define NUM_RELOC_SECTIONS 16
+
+/********************** STABS **********************/
+
+/* gcc uses mips-tfile to output type information in special stabs
+ entries. These must match the corresponding definition in
+ gcc/config/mips.h. At some point, these should probably go into a
+ shared include file, but currently gcc and gdb do not share any
+ directories. */
+#define CODE_MASK 0x8F300
+#define ECOFF_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
+#define ECOFF_MARK_STAB(code) ((code)+CODE_MASK)
+#define ECOFF_UNMARK_STAB(code) ((code)-CODE_MASK)
+#define STABS_SYMBOL "@stabs"
+
+/********************** COFF **********************/
+
+/* gcc also uses mips-tfile to output COFF debugging information.
+ These are the values it uses when outputting the .type directive.
+ These should also be in a shared include file. */
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+/********************** AUX **********************/
+
+/* The auxiliary type information is the same on all known ECOFF
+ targets. I can't see any reason that it would ever change, so I am
+ going to gamble and define the external structures here, in the
+ target independent ECOFF header file. The internal forms are
+ defined in coff/sym.h, which was originally donated by MIPS
+ Computer Systems. */
+
+/* Type information external record */
+
+struct tir_ext {
+ unsigned char t_bits1[1];
+ unsigned char t_tq45[1];
+ unsigned char t_tq01[1];
+ unsigned char t_tq23[1];
+};
+
+#define TIR_BITS1_FBITFIELD_BIG ((unsigned int) 0x80)
+#define TIR_BITS1_FBITFIELD_LITTLE ((unsigned int) 0x01)
+
+#define TIR_BITS1_CONTINUED_BIG ((unsigned int) 0x40)
+#define TIR_BITS1_CONTINUED_LITTLE ((unsigned int) 0x02)
+
+#define TIR_BITS1_BT_BIG ((unsigned int) 0x3F)
+#define TIR_BITS1_BT_SH_BIG 0
+#define TIR_BITS1_BT_LITTLE ((unsigned int) 0xFC)
+#define TIR_BITS1_BT_SH_LITTLE 2
+
+#define TIR_BITS_TQ4_BIG ((unsigned int) 0xF0)
+#define TIR_BITS_TQ4_SH_BIG 4
+#define TIR_BITS_TQ5_BIG ((unsigned int) 0x0F)
+#define TIR_BITS_TQ5_SH_BIG 0
+#define TIR_BITS_TQ4_LITTLE ((unsigned int) 0x0F)
+#define TIR_BITS_TQ4_SH_LITTLE 0
+#define TIR_BITS_TQ5_LITTLE ((unsigned int) 0xF0)
+#define TIR_BITS_TQ5_SH_LITTLE 4
+
+#define TIR_BITS_TQ0_BIG ((unsigned int) 0xF0)
+#define TIR_BITS_TQ0_SH_BIG 4
+#define TIR_BITS_TQ1_BIG ((unsigned int) 0x0F)
+#define TIR_BITS_TQ1_SH_BIG 0
+#define TIR_BITS_TQ0_LITTLE ((unsigned int) 0x0F)
+#define TIR_BITS_TQ0_SH_LITTLE 0
+#define TIR_BITS_TQ1_LITTLE ((unsigned int) 0xF0)
+#define TIR_BITS_TQ1_SH_LITTLE 4
+
+#define TIR_BITS_TQ2_BIG ((unsigned int) 0xF0)
+#define TIR_BITS_TQ2_SH_BIG 4
+#define TIR_BITS_TQ3_BIG ((unsigned int) 0x0F)
+#define TIR_BITS_TQ3_SH_BIG 0
+#define TIR_BITS_TQ2_LITTLE ((unsigned int) 0x0F)
+#define TIR_BITS_TQ2_SH_LITTLE 0
+#define TIR_BITS_TQ3_LITTLE ((unsigned int) 0xF0)
+#define TIR_BITS_TQ3_SH_LITTLE 4
+
+/* Relative symbol external record */
+
+struct rndx_ext {
+ unsigned char r_bits[4];
+};
+
+#define RNDX_BITS0_RFD_SH_LEFT_BIG 4
+#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 ((unsigned int) 0x0F)
+#define RNDX_BITS1_RFD_SH_LEFT_LITTLE 8
+
+#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 ((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
+
+/* Auxiliary symbol information external record */
+
+union aux_ext {
+ struct tir_ext a_ti;
+ struct rndx_ext a_rndx;
+ unsigned char a_dnLow[4];
+ unsigned char a_dnHigh[4];
+ unsigned char a_isym[4];
+ unsigned char a_iss[4];
+ unsigned char a_width[4];
+ unsigned char a_count[4];
+};
+
+#define AUX_GET_ANY(bigend, ax, field) \
+ ((bigend) ? bfd_getb32 ((ax)->field) : bfd_getl32 ((ax)->field))
+
+#define AUX_GET_DNLOW(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_dnLow)
+#define AUX_GET_DNHIGH(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_dnHigh)
+#define AUX_GET_ISYM(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_isym)
+#define AUX_GET_ISS(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_iss)
+#define AUX_GET_WIDTH(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_width)
+#define AUX_GET_COUNT(bigend, ax) AUX_GET_ANY ((bigend), (ax), a_count)
+
+#define AUX_PUT_ANY(bigend, val, ax, field) \
+ ((bigend) \
+ ? (bfd_putb32 ((bfd_vma) (val), (ax)->field), 0) \
+ : (bfd_putl32 ((bfd_vma) (val), (ax)->field), 0))
+
+#define AUX_PUT_DNLOW(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_dnLow)
+#define AUX_PUT_DNHIGH(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_dnHigh)
+#define AUX_PUT_ISYM(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_isym)
+#define AUX_PUT_ISS(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_iss)
+#define AUX_PUT_WIDTH(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_width)
+#define AUX_PUT_COUNT(bigend, val, ax) \
+ AUX_PUT_ANY ((bigend), (val), (ax), a_count)
+
+/********************** SYMBOLS **********************/
+
+/* 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;
+};
+
+/* These structures are used by the ECOFF find_nearest_line function. */
+
+struct ecoff_fdrtab_entry
+{
+ /* Base address in .text of this FDR. */
+ bfd_vma base_addr;
+ FDR *fdr;
+};
+
+struct ecoff_find_line
+{
+ /* Allocated memory to hold function and file names. */
+ char *find_buffer;
+
+ /* FDR table, sorted by address: */
+ long fdrtab_len;
+ struct ecoff_fdrtab_entry *fdrtab;
+};
+
+/********************** 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/contrib/gdb/include/coff/h8300.h b/contrib/gdb/include/coff/h8300.h
new file mode 100644
index 0000000..8fe8f61
--- /dev/null
+++ b/contrib/gdb/include/coff/h8300.h
@@ -0,0 +1,203 @@
+/*** coff information for Hitachi H8/300 and H8/300-H */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+
+#define H8300MAGIC 0x8300
+#define H8300HMAGIC 0x8301
+
+
+#define H8300BADMAG(x) (((x).f_magic!=H8300MAGIC))
+#define H8300HBADMAG(x) (((x).f_magic!=H8300HMAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+
+#define AOUTHDRSZ (sizeof(AOUTHDR))
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[4]; /* line number */
+};
+
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) (ext->l_lnno));
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_32(abfd,val, (bfd_byte *) (ext->l_lnno));
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+/* The external reloc has an offset field, because some of the reloc
+ types on the h8 don't have room in the instruction for the entire
+ offset - eg the strange jump and high page addressing modes */
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_offset[4];
+ char r_type[2];
+ char r_stuff[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 16
+
+
+
+
diff --git a/contrib/gdb/include/coff/h8500.h b/contrib/gdb/include/coff/h8500.h
new file mode 100644
index 0000000..5a8c9fe
--- /dev/null
+++ b/contrib/gdb/include/coff/h8500.h
@@ -0,0 +1,201 @@
+/*** coff information for Hitachi H8/500 */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+
+#define H8500MAGIC 0x8500
+
+
+#define H8500BADMAG(x) ((0xffff && ((x).f_magic)!=H8500MAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+
+#define AOUTHDRSZ (sizeof(AOUTHDR))
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[4]; /* line number */
+};
+
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) (ext->l_lnno));
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_32(abfd,val, (bfd_byte *) (ext->l_lnno));
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+/* The external reloc has an offset field, because some of the reloc
+ types on the h8 don't have room in the instruction for the entire
+ offset - eg the strange jump and high page addressing modes */
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_offset[4];
+ char r_type[2];
+ char r_stuff[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 16
+
+
+
+
diff --git a/contrib/gdb/include/coff/i386.h b/contrib/gdb/include/coff/i386.h
new file mode 100644
index 0000000..b7ecf0b
--- /dev/null
+++ b/contrib/gdb/include/coff/i386.h
@@ -0,0 +1,224 @@
+/*** coff information for Intel 386/486. */
+
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved external references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+
+
+
+#define I386MAGIC 0x14c
+#define I386PTXMAGIC 0x154
+#define I386AIXMAGIC 0x175
+
+/* This is Lynx's all-platform magic number for executables. */
+
+#define LYNXCOFFMAGIC 0415
+
+#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \
+ && (x).f_magic != I386AIXMAGIC \
+ && (x).f_magic != I386PTXMAGIC \
+ && (x).f_magic != LYNXCOFFMAGIC)
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+
+
+}
+AOUTHDR;
+
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+#define OMAGIC 0404 /* object files, eg as output */
+#define ZMAGIC 0413 /* demand load format, eg normal ld output */
+#define STMAGIC 0401 /* target shlib */
+#define SHMAGIC 0443 /* host shlib */
+
+
+/* define some NT default values */
+/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT 0x200
+#define NT_DEF_RESERVE 0x100000
+#define NT_DEF_COMMIT 0x1000
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _COMMENT ".comment"
+#define _LIB ".lib"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ 6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+#define N_BTMASK (0xf)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+# define _ETEXT "etext"
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
diff --git a/contrib/gdb/include/coff/i860.h b/contrib/gdb/include/coff/i860.h
new file mode 100644
index 0000000..e09ec5f0
--- /dev/null
+++ b/contrib/gdb/include/coff/i860.h
@@ -0,0 +1,204 @@
+/* This file was hacked from i386.h [dolan@ssd.intel.com] */
+
+/*** coff information for Intel 860. */
+
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved external references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+
+
+
+#define I860MAGIC 0x14d
+
+#define I860BADMAG(x) ((x).f_magic != I860MAGIC)
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+/* FIXME: What are the a.out magic numbers? */
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _COMMENT ".comment"
+#define _LIB ".lib"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ 6
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+#define N_BTMASK (0xf)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+# define _ETEXT "etext"
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
diff --git a/contrib/gdb/include/coff/i960.h b/contrib/gdb/include/coff/i960.h
new file mode 100644
index 0000000..c20893c
--- /dev/null
+++ b/contrib/gdb/include/coff/i960.h
@@ -0,0 +1,251 @@
+/*** coff information for 80960. Origins: Intel corp, natch. */
+
+/* NOTE: Tagentries (cf TAGBITS) are no longer used by the 960 */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+#define OMAGIC (0407) /* old impure format. data immediately
+ follows text. both sections are rw. */
+#define NMAGIC (0410) /* split i&d, read-only text */
+
+/*
+* Intel 80960 (I960) processor flags.
+* F_I960TYPE == mask for processor type field.
+*/
+
+#define F_I960TYPE (0xf000)
+#define F_I960CORE (0x1000)
+#define F_I960KB (0x2000)
+#define F_I960SB (0x2000)
+#define F_I960MC (0x3000)
+#define F_I960XA (0x4000)
+#define F_I960CA (0x5000)
+#define F_I960KA (0x6000)
+#define F_I960SA (0x6000)
+#define F_I960JX (0x7000)
+#define F_I960HX (0x8000)
+
+
+/** i80960 Magic Numbers
+*/
+
+#define I960ROMAGIC (0x160) /* read-only text segments */
+#define I960RWMAGIC (0x161) /* read-write text segments */
+
+#define I960BADMAG(x) (((x).f_magic!=I960ROMAGIC) && ((x).f_magic!=I960RWMAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ 20
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+typedef struct {
+ unsigned long phys_addr;
+ unsigned long bitarray;
+} TAGBITS;
+
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+ char tagentries[4]; /* number of tag entries to follow */
+}
+AOUTHDR;
+
+/* return a pointer to the tag bits array */
+
+#define TAGPTR(aout) ((TAGBITS *) (&(aout.tagentries)+1))
+
+/* compute size of a header */
+
+/*#define AOUTSZ(aout) (sizeof(AOUTHDR)+(aout.tagentries*sizeof(TAGBITS)))*/
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+ char s_align[4]; /* section alignment */
+};
+
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+ char padding[2]; /* force alignment */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ 8
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_flags[2];
+ char e_type[4];
+ char e_sclass[1];
+ char e_numaux[1];
+ char pad2[2];
+};
+
+
+
+
+#define N_BTMASK (0x1f)
+#define N_TMASK (0x60)
+#define N_BTSHFT (5)
+#define N_TSHIFT (2)
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+ /******************************************
+ * I960-specific *2nd* aux. entry formats
+ ******************************************/
+ struct {
+ /* This is a very old typo that keeps getting propagated. */
+#define x_stdindx x_stindx
+ char x_stindx[4]; /* sys. table entry */
+ } x_sc; /* system call entry */
+
+ struct {
+ char x_balntry[4]; /* BAL entry point */
+ } x_bal; /* BAL-callable function */
+
+ struct {
+ char x_timestamp[4]; /* time stamp */
+ char x_idstring[20]; /* producer identity string */
+ } x_ident; /* Producer ident info */
+
+};
+
+
+
+#define SYMENT struct external_syment
+#define SYMESZ sizeof(SYMENT) /* FIXME - calc by hand */
+#define AUXENT union external_auxent
+#define AUXESZ sizeof(AUXENT) /* FIXME - calc by hand */
+
+# define _ETEXT "_etext"
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+ char pad[2];
+};
+
+
+/* Relevent values for r_type and i960. Would someone please document them */
+
+
+#define RELOC struct external_reloc
+#define RELSZ 12
+
diff --git a/contrib/gdb/include/coff/internal.h b/contrib/gdb/include/coff/internal.h
new file mode 100644
index 0000000..b43cf76
--- /dev/null
+++ b/contrib/gdb/include/coff/internal.h
@@ -0,0 +1,648 @@
+/* Internal format of COFF object file data structures, for GNU BFD.
+ This file is part of BFD, the Binary File Descriptor library. */
+
+#ifndef GNU_COFF_INTERNAL_H
+#define GNU_COFF_INTERNAL_H 1
+
+/* First, make "signed char" work, even on old compilers. */
+#ifndef signed
+#ifndef __STDC__
+#define signed /**/
+#endif
+#endif
+
+/********************** FILE HEADER **********************/
+
+/* extra stuff in a PE header. */
+
+struct internal_extra_pe_filehdr
+{
+ /* DOS header data follows for PE stuff */
+ unsigned short e_magic; /* Magic number, 0x5a4d */
+ unsigned short e_cblp; /* Bytes on last page of file, 0x90 */
+ unsigned short e_cp; /* Pages in file, 0x3 */
+ unsigned short e_crlc; /* Relocations, 0x0 */
+ unsigned short e_cparhdr; /* Size of header in paragraphs, 0x4 */
+ unsigned short e_minalloc; /* Minimum extra paragraphs needed, 0x0 */
+ unsigned short e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */
+ unsigned short e_ss; /* Initial (relative) SS value, 0x0 */
+ unsigned short e_sp; /* Initial SP value, 0xb8 */
+ unsigned short e_csum; /* Checksum, 0x0 */
+ unsigned short e_ip; /* Initial IP value, 0x0 */
+ unsigned short e_cs; /* Initial (relative) CS value, 0x0 */
+ unsigned short e_lfarlc; /* File address of relocation table, 0x40 */
+ unsigned short e_ovno; /* Overlay number, 0x0 */
+ unsigned short e_res[4]; /* Reserved words, all 0x0 */
+ unsigned short e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */
+ unsigned short e_oeminfo; /* OEM information; e_oemid specific, 0x0 */
+ unsigned short e_res2[10]; /* Reserved words, all 0x0 */
+ bfd_vma e_lfanew; /* File address of new exe header, 0x80 */
+ unsigned long dos_message[16]; /* text which always follows dos header */
+ bfd_vma nt_signature; /* required NT signature, 0x4550 */
+};
+
+struct internal_filehdr
+{
+ struct internal_extra_pe_filehdr pe;
+
+ /* standard coff internal info */
+ unsigned short f_magic; /* magic number */
+ unsigned short f_nscns; /* number of sections */
+ long f_timdat; /* time & date stamp */
+ bfd_vma f_symptr; /* file pointer to symtab */
+ long f_nsyms; /* number of symtab entries */
+ unsigned short f_opthdr; /* sizeof(optional hdr) */
+ unsigned short f_flags; /* flags */
+};
+
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved external references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR16WR file is 16-bit little-endian
+ * F_AR32WR file is 32-bit little-endian
+ * F_AR32W file is 32-bit big-endian
+ * F_DYNLOAD rs/6000 aix: dynamically loadable w/imports & exports
+ * F_SHROBJ rs/6000 aix: file is a shared object
+ * F_DLL PE format DLL
+ */
+
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+#define F_AR16WR (0x0080)
+#define F_AR32WR (0x0100)
+#define F_AR32W (0x0200)
+#define F_DYNLOAD (0x1000)
+#define F_SHROBJ (0x2000)
+#define F_DLL (0x2000)
+
+/* extra structure which is used in the optional header */
+typedef struct _IMAGE_DATA_DIRECTORY
+{
+ bfd_vma VirtualAddress;
+ long Size;
+} IMAGE_DATA_DIRECTORY;
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+
+/* default image base for NT */
+#define NT_EXE_IMAGE_BASE 0x400000
+#define NT_DLL_IMAGE_BASE 0x10000000
+
+/* Extra stuff in a PE aouthdr */
+
+#define PE_DEF_SECTION_ALIGNMENT 0x1000
+#define PE_DEF_FILE_ALIGNMENT 0x200
+
+struct internal_extra_pe_aouthdr
+{
+ /* PE stuff */
+ bfd_vma ImageBase; /* address of specific location in memory that
+ file is located, NT default 0x10000 */
+
+ bfd_vma SectionAlignment; /* section alignment default 0x1000 */
+ bfd_vma FileAlignment; /* file alignment default 0x200 */
+ short MajorOperatingSystemVersion; /* minimum version of the operating */
+ short MinorOperatingSystemVersion; /* system req'd for exe, default to 1*/
+ short MajorImageVersion; /* user defineable field to store version of */
+ short MinorImageVersion; /* exe or dll being created, default to 0 */
+ short MajorSubsystemVersion; /* minimum subsystem version required to */
+ short MinorSubsystemVersion; /* run exe; default to 3.1 */
+ long Reserved1; /* seems to be 0 */
+ long SizeOfImage; /* size of memory to allocate for prog */
+ long SizeOfHeaders; /* size of PE header and section table */
+ long CheckSum; /* set to 0 */
+ short Subsystem;
+
+ /* type of subsystem exe uses for user interface,
+ possible values:
+ 1 - NATIVE Doesn't require a subsystem
+ 2 - WINDOWS_GUI runs in Windows GUI subsystem
+ 3 - WINDOWS_CUI runs in Windows char sub. (console app)
+ 5 - OS2_CUI runs in OS/2 character subsystem
+ 7 - POSIX_CUI runs in Posix character subsystem */
+ short DllCharacteristics; /* flags for DLL init, use 0 */
+ bfd_vma SizeOfStackReserve; /* amount of memory to reserve */
+ bfd_vma SizeOfStackCommit; /* amount of memory initially committed for
+ initial thread's stack, default is 0x1000 */
+ bfd_vma SizeOfHeapReserve; /* amount of virtual memory to reserve and */
+ bfd_vma SizeOfHeapCommit; /* commit, don't know what to defaut it to */
+ long LoaderFlags; /* can probably set to 0 */
+ long NumberOfRvaAndSizes; /* number of entries in next entry, 16 */
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+};
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+struct internal_aouthdr
+{
+ short magic; /* type of file */
+ short vstamp; /* version stamp */
+ bfd_vma tsize; /* text size in bytes, padded to FW bdry*/
+ bfd_vma dsize; /* initialized data " " */
+ bfd_vma bsize; /* uninitialized data " " */
+ bfd_vma entry; /* entry pt. */
+ bfd_vma text_start; /* base of text used for this file */
+ bfd_vma data_start; /* base of data used for this file */
+
+ /* i960 stuff */
+ unsigned long tagentries; /* number of tag entries to follow */
+
+ /* RS/6000 stuff */
+ unsigned long o_toc; /* address of TOC */
+ short o_snentry; /* section number for entry point */
+ short o_sntext; /* section number for text */
+ short o_sndata; /* section number for data */
+ short o_sntoc; /* section number for toc */
+ short o_snloader; /* section number for loader section */
+ short o_snbss; /* section number for bss */
+ short o_algntext; /* max alignment for text */
+ short o_algndata; /* max alignment for data */
+ short o_modtype; /* Module type field, 1R,RE,RO */
+ short o_cputype; /* Encoded CPU type */
+ unsigned long o_maxstack; /* max stack size allowed. */
+ unsigned long o_maxdata; /* max data size allowed. */
+
+ /* ECOFF stuff */
+ bfd_vma bss_start; /* Base of bss section. */
+ 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. */
+
+ /* Apollo stuff */
+ long o_inlib; /* inlib data */
+ long o_sri; /* Static Resource Information */
+ long vid[2]; /* Version id */
+
+
+ struct internal_extra_pe_aouthdr pe;
+
+};
+
+/********************** STORAGE CLASSES **********************/
+
+/* This used to be defined as -1, but now n_sclass is unsigned. */
+#define C_EFCN 0xff /* physical end of function */
+#define C_NULL 0
+#define C_AUTO 1 /* automatic variable */
+#define C_EXT 2 /* external symbol */
+#define C_STAT 3 /* static */
+#define C_REG 4 /* register variable */
+#define C_EXTDEF 5 /* external definition */
+#define C_LABEL 6 /* label */
+#define C_ULABEL 7 /* undefined label */
+#define C_MOS 8 /* member of structure */
+#define C_ARG 9 /* function argument */
+#define C_STRTAG 10 /* structure tag */
+#define C_MOU 11 /* member of union */
+#define C_UNTAG 12 /* union tag */
+#define C_TPDEF 13 /* type definition */
+#define C_USTATIC 14 /* undefined static */
+#define C_ENTAG 15 /* enumeration tag */
+#define C_MOE 16 /* member of enumeration */
+#define C_REGPARM 17 /* register parameter */
+#define C_FIELD 18 /* bit field */
+#define C_AUTOARG 19 /* auto argument */
+#define C_LASTENT 20 /* dummy entry (end of block) */
+#define C_BLOCK 100 /* ".bb" or ".eb" */
+#define C_FCN 101 /* ".bf" or ".ef" */
+#define C_EOS 102 /* end of structure */
+#define C_FILE 103 /* file name */
+#define C_LINE 104 /* line # reformatted as symbol table entry */
+#define C_ALIAS 105 /* duplicate tag */
+#define C_HIDDEN 106 /* ext symbol in dmert public lib */
+
+/* New storage classes for WINDOWS_NT */
+#define C_SECTION 104 /* section name */
+#define C_NT_WEAK 105 /* weak external */
+
+ /* New storage classes for 80960 */
+
+/* C_LEAFPROC is obsolete. Use C_LEAFEXT or C_LEAFSTAT */
+#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */
+
+#define C_SCALL 107 /* Procedure reachable via system call */
+#define C_LEAFEXT 108 /* External leaf */
+#define C_LEAFSTAT 113 /* Static leaf */
+#define C_OPTVAR 109 /* Optimized variable */
+#define C_DEFINE 110 /* Preprocessor #define */
+#define C_PRAGMA 111 /* Advice to compiler or linker */
+#define C_SEGMENT 112 /* 80960 segment name */
+
+ /* Storage classes for m88k */
+#define C_SHADOW 107 /* shadow symbol */
+#define C_VERSION 108 /* coff version symbol */
+
+ /* New storage classes for RS/6000 */
+#define C_HIDEXT 107 /* Un-named external symbol */
+#define C_BINCL 108 /* Marks beginning of include file */
+#define C_EINCL 109 /* Marks ending of include file */
+
+ /* storage classes for stab symbols for RS/6000 */
+#define C_GSYM (0x80)
+#define C_LSYM (0x81)
+#define C_PSYM (0x82)
+#define C_RSYM (0x83)
+#define C_RPSYM (0x84)
+#define C_STSYM (0x85)
+#define C_TCSYM (0x86)
+#define C_BCOMM (0x87)
+#define C_ECOML (0x88)
+#define C_ECOMM (0x89)
+#define C_DECL (0x8c)
+#define C_ENTRY (0x8d)
+#define C_FUN (0x8e)
+#define C_BSTAT (0x8f)
+#define C_ESTAT (0x90)
+
+/********************** SECTION HEADER **********************/
+struct internal_scnhdr
+{
+ char s_name[8]; /* section name */
+ bfd_vma s_paddr; /* physical address, aliased s_nlib */
+ bfd_vma s_vaddr; /* virtual address */
+ bfd_vma s_size; /* section size */
+ bfd_vma s_scnptr; /* file ptr to raw data for section */
+ bfd_vma s_relptr; /* file ptr to relocation */
+ bfd_vma s_lnnoptr; /* file ptr to line numbers */
+ unsigned long s_nreloc; /* number of relocation entries */
+ unsigned long s_nlnno; /* number of line number entries*/
+ long s_flags; /* flags */
+ long s_align; /* used on I960 */
+};
+
+/*
+ * s_flags "type"
+ */
+#define STYP_REG (0x0000) /* "regular": allocated, relocated, loaded */
+#define STYP_DSECT (0x0001) /* "dummy": relocated only*/
+#define STYP_NOLOAD (0x0002) /* "noload": allocated, relocated, not loaded */
+#define STYP_GROUP (0x0004) /* "grouped": formed of input sections */
+#define STYP_PAD (0x0008) /* "padding": not allocated, not relocated, loaded */
+#define STYP_COPY (0x0010) /* "copy": for decision function used by field update; not allocated, not relocated,
+ loaded; reloc & lineno entries processed normally */
+#define STYP_TEXT (0x0020) /* section contains text only */
+#define S_SHRSEG (0x0020) /* In 3b Update files (output of ogen), sections which appear in SHARED segments of the Pfile
+ will have the S_SHRSEG flag set by ogen, to inform dufr that updating 1 copy of the proc. will
+ update all process invocations. */
+#define STYP_DATA (0x0040) /* section contains data only */
+#define STYP_BSS (0x0080) /* section contains bss only */
+#define S_NEWFCN (0x0100) /* In a minimal file or an update file, a new function (as compared with a replaced function) */
+#define STYP_INFO (0x0200) /* comment: not allocated not relocated, not loaded */
+#define STYP_OVER (0x0400) /* overlay: relocated not allocated or loaded */
+#define STYP_LIB (0x0800) /* for .lib: same as INFO */
+#define STYP_MERGE (0x2000) /* merge section -- combines with text, data or bss sections only */
+#define STYP_REVERSE_PAD (0x4000) /* section will be padded with no-op instructions wherever padding is necessary and there is a
+
+ word of contiguous bytes
+ beginning on a word boundary. */
+
+#define STYP_LIT 0x8020 /* Literal data (like STYP_TEXT) */
+
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+
+struct internal_lineno
+{
+ union
+ {
+ long l_symndx; /* function name symbol index, iff l_lnno == 0*/
+ long l_paddr; /* (physical) address of line number */
+ } l_addr;
+ unsigned long l_lnno; /* line number */
+};
+
+/********************** SYMBOLS **********************/
+
+#define SYMNMLEN 8 /* # characters in a symbol name */
+#define FILNMLEN 14 /* # characters in a file name */
+#define DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct internal_syment
+{
+ union
+ {
+ char _n_name[SYMNMLEN]; /* old COFF version */
+ struct
+ {
+ long _n_zeroes; /* new == 0 */
+ long _n_offset; /* offset into string table */
+ } _n_n;
+ char *_n_nptr[2]; /* allows for overlaying */
+ } _n;
+ long n_value; /* value of symbol */
+ short n_scnum; /* section number */
+ unsigned short n_flags; /* copy of flags from filhdr */
+ unsigned short n_type; /* type and derived type */
+ unsigned char n_sclass; /* storage class */
+ unsigned char n_numaux; /* number of aux. entries */
+};
+
+#define n_name _n._n_name
+#define n_zeroes _n._n_n._n_zeroes
+#define n_offset _n._n_n._n_offset
+
+
+/* Relocatable symbols have number of the section in which they are defined,
+ or one of the following: */
+
+#define N_UNDEF ((short)0) /* undefined symbol */
+#define N_ABS ((short)-1) /* value of symbol is absolute */
+#define N_DEBUG ((short)-2) /* debugging symbol -- value is meaningless */
+#define N_TV ((short)-3) /* indicates symbol needs preload transfer vector */
+#define P_TV ((short)-4) /* indicates symbol needs postload transfer vector*/
+
+/*
+ * Type of a symbol, in low N bits of the word
+ */
+#define T_NULL 0
+#define T_VOID 1 /* function argument (only used by compiler) */
+#define T_CHAR 2 /* character */
+#define T_SHORT 3 /* short integer */
+#define T_INT 4 /* integer */
+#define T_LONG 5 /* long integer */
+#define T_FLOAT 6 /* floating point */
+#define T_DOUBLE 7 /* double word */
+#define T_STRUCT 8 /* structure */
+#define T_UNION 9 /* union */
+#define T_ENUM 10 /* enumeration */
+#define T_MOE 11 /* member of enumeration*/
+#define T_UCHAR 12 /* unsigned character */
+#define T_USHORT 13 /* unsigned short */
+#define T_UINT 14 /* unsigned integer */
+#define T_ULONG 15 /* unsigned long */
+#define T_LNGDBL 16 /* long double */
+
+/*
+ * derived types, in n_type
+*/
+#define DT_NON (0) /* no derived type */
+#define DT_PTR (1) /* pointer */
+#define DT_FCN (2) /* function */
+#define DT_ARY (3) /* array */
+
+#define BTYPE(x) ((x) & N_BTMASK)
+
+#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
+#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
+#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
+#define ISTAG(x) ((x)==C_STRTAG||(x)==C_UNTAG||(x)==C_ENTAG)
+#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK))
+
+
+union internal_auxent
+{
+ struct
+ {
+
+ union
+ {
+ long l; /* str, un, or enum tag indx */
+ struct coff_ptr_struct *p;
+ } x_tagndx;
+
+ union
+ {
+ struct
+ {
+ unsigned short x_lnno; /* declaration line number */
+ unsigned short x_size; /* str/union/array size */
+ } x_lnsz;
+ long x_fsize; /* size of function */
+ } x_misc;
+
+ union
+ {
+ struct
+ { /* if ISFCN, tag, or .bb */
+ long x_lnnoptr; /* ptr to fcn line # */
+ union
+ { /* entry ndx past block end */
+ long l;
+ struct coff_ptr_struct *p;
+ } x_endndx;
+ } x_fcn;
+
+ struct
+ { /* if ISARY, up to 4 dimen. */
+ unsigned short x_dimen[DIMNUM];
+ } x_ary;
+ } x_fcnary;
+
+ unsigned short x_tvndx; /* tv index */
+ } x_sym;
+
+ union
+ {
+ char x_fname[FILNMLEN];
+ struct
+ {
+ long x_zeroes;
+ long x_offset;
+ } x_n;
+ } x_file;
+
+ struct
+ {
+ long x_scnlen; /* section length */
+ unsigned short x_nreloc; /* # relocation entries */
+ unsigned short x_nlinno; /* # line numbers */
+ } x_scn;
+
+ struct
+ {
+ long x_tvfill; /* tv fill value */
+ unsigned short x_tvlen; /* length of .tv */
+ unsigned short x_tvran[2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+ /******************************************
+ * RS/6000-specific auxent - last auxent for every external symbol
+ ******************************************/
+ struct
+ {
+ 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 */
+ /* 0-4 - Log 2 of alignment */
+ /* 5-7 - symbol type */
+ unsigned char x_smclas; /* storage mapping class */
+ long x_stab; /* dbx stab info index */
+ unsigned short x_snstab; /* sect num with dbx stab */
+ } x_csect; /* csect definition information */
+
+/* x_smtyp values: */
+
+#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */
+#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */
+/* Symbol type values: */
+#define XTY_ER 0 /* External reference */
+#define XTY_SD 1 /* Csect definition */
+#define XTY_LD 2 /* Label definition */
+#define XTY_CM 3 /* .BSS */
+#define XTY_EM 4 /* Error message */
+#define XTY_US 5 /* "Reserved for internal use" */
+
+/* x_smclas values: */
+
+#define XMC_PR 0 /* Read-only program code */
+#define XMC_RO 1 /* Read-only constant */
+#define XMC_DB 2 /* Read-only debug dictionary table */
+#define XMC_TC 3 /* Read-write general TOC entry */
+#define XMC_UA 4 /* Read-write unclassified */
+#define XMC_RW 5 /* Read-write data */
+#define XMC_GL 6 /* Read-only global linkage */
+#define XMC_XO 7 /* Read-only extended operation */
+#define XMC_SV 8 /* Read-only supervisor call */
+#define XMC_BS 9 /* Read-write BSS */
+#define XMC_DS 10 /* Read-write descriptor csect */
+#define XMC_UC 11 /* Read-write unnamed Fortran common */
+#define XMC_TI 12 /* Read-only traceback index csect */
+#define XMC_TB 13 /* Read-only traceback table csect */
+/* 14 ??? */
+#define XMC_TC0 15 /* Read-write TOC anchor */
+#define XMC_TD 16 /* Read-write data in TOC */
+
+ /******************************************
+ * I960-specific *2nd* aux. entry formats
+ ******************************************/
+ struct
+ {
+ /* This is a very old typo that keeps getting propagated. */
+#define x_stdindx x_stindx
+ long x_stindx; /* sys. table entry */
+ } x_sc; /* system call entry */
+
+ struct
+ {
+ unsigned long x_balntry; /* BAL entry point */
+ } x_bal; /* BAL-callable function */
+
+ struct
+ {
+ unsigned long x_timestamp; /* time stamp */
+ char x_idstring[20]; /* producer identity string */
+ } x_ident; /* Producer ident info */
+
+};
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct internal_reloc
+{
+ bfd_vma r_vaddr; /* Virtual address of reference */
+ long r_symndx; /* Index into symbol table */
+ 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 Alpha ECOFF, SPARC, others */
+};
+
+#define R_RELBYTE 017
+#define R_RELWORD 020
+#define R_PCRBYTE 022
+#define R_PCRWORD 023
+#define R_PCRLONG 024
+
+#define R_DIR16 01
+#define R_DIR32 06
+#define R_PCLONG 020
+#define R_RELBYTE 017
+#define R_RELWORD 020
+#define R_IMAGEBASE 07
+
+
+#define R_PCR16L 128
+#define R_PCR26L 129
+#define R_VRT16 130
+#define R_HVRT16 131
+#define R_LVRT16 132
+#define R_VRT32 133
+#define R_RELLONG (0x11) /* Direct 32-bit relocation */
+#define R_IPRSHORT (0x18)
+#define R_IPRMED (0x19) /* 24-bit ip-relative relocation */
+#define R_IPRLONG (0x1a)
+#define R_OPTCALL (0x1b) /* 32-bit optimizable call (leafproc/sysproc) */
+#define R_OPTCALLX (0x1c) /* 64-bit optimizable call (leafproc/sysproc) */
+#define R_GETSEG (0x1d)
+#define R_GETPA (0x1e)
+#define R_TAGWORD (0x1f)
+#define R_JUMPTARG 0x20 /* strange 29k 00xx00xx reloc */
+
+
+#define R_MOVB1 0x41 /* Special h8 16bit or 8 bit reloc for mov.b */
+#define R_MOVB2 0x42 /* Special h8 opcode for 8bit which could be 16 */
+#define R_JMP1 0x43 /* Special h8 16bit jmp which could be pcrel */
+#define R_JMP2 0x44 /* a branch which used to be a jmp */
+#define R_RELLONG_NEG 0x45
+
+#define R_JMPL1 0x46 /* Special h8 24bit jmp which could be pcrel */
+#define R_JMPL_B8 0x47 /* a 8 bit pcrel which used to be a jmp */
+
+#define R_MOVLB1 0x48 /* Special h8 24bit or 8 bit reloc for mov.b */
+#define R_MOVLB2 0x49 /* Special h8 opcode for 8bit which could be 24 */
+
+/* An h8300 memory indirect jump/call. Forces the address of the jump/call
+ target into the function vector (in page zero), and the address of the
+ vector entry to be placed in the jump/call instruction. */
+#define R_MEM_INDIRECT 0x4a
+
+/* Z8k modes */
+#define R_IMM16 0x01 /* 16 bit abs */
+#define R_JR 0x02 /* jr 8 bit disp */
+#define R_IMM4L 0x23 /* low nibble */
+#define R_IMM8 0x22 /* 8 bit abs */
+#define R_IMM32 R_RELLONG /* 32 bit abs */
+#define R_CALL R_DA /* Absolute address which could be a callr */
+#define R_JP R_DA /* Absolute address which could be a jp */
+#define R_REL16 0x04 /* 16 bit PC rel */
+#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 */
+
+#define R_H8500_IMM8 1 /* 8 bit immediate */
+#define R_H8500_IMM16 2 /* 16 bit immediate */
+#define R_H8500_PCREL8 3 /* 8 bit pcrel */
+#define R_H8500_PCREL16 4 /* 16 bit pcrel */
+#define R_H8500_HIGH8 5 /* high 8 bits of 24 bit address */
+#define R_H8500_LOW16 7 /* low 16 bits of 24 bit immediate */
+#define R_H8500_IMM24 6 /* 24 bit immediate */
+#define R_H8500_IMM32 8 /* 32 bit immediate */
+#define R_H8500_HIGH16 9 /* high 16 bits of 32 bit immediate */
+
+/* W65 modes */
+
+#define R_W65_ABS8 1 /* addr & 0xff */
+#define R_W65_ABS16 2 /* addr & 0xffff */
+#define R_W65_ABS24 3 /* addr & 0xffffff */
+
+#define R_W65_ABS8S8 4 /* (addr >> 8) & 0xff */
+#define R_W65_ABS8S16 5 /* (addr >> 16) & 0xff */
+
+#define R_W65_ABS16S8 6 /* (addr >> 8) & 0ffff */
+#define R_W65_ABS16S16 7 /* (addr >> 16) & 0ffff */
+
+#define R_W65_PCR8 8
+#define R_W65_PCR16 9
+
+#define R_W65_DP 10 /* direct page 8 bits only */
+
+#endif /* GNU_COFF_INTERNAL_H */
diff --git a/contrib/gdb/include/coff/m68k.h b/contrib/gdb/include/coff/m68k.h
new file mode 100644
index 0000000..a3c15be
--- /dev/null
+++ b/contrib/gdb/include/coff/m68k.h
@@ -0,0 +1,221 @@
+/*** coff information for M68K */
+
+#ifndef GNU_COFF_M68K_H
+#define GNU_COFF_M68K_H 1
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+/* Motorola 68000/68008/68010/68020 */
+#define MC68MAGIC 0520
+#define MC68KWRMAGIC 0520 /* writeable text segments */
+#define MC68TVMAGIC 0521
+#define MC68KROMAGIC 0521 /* readonly shareable text segments */
+#define MC68KPGMAGIC 0522 /* demand paged text segments */
+#define M68MAGIC 0210
+#define M68TVMAGIC 0211
+
+/* this is the magic of the Bull dpx/2 */
+#define MC68KBCSMAGIC 0526
+
+/* This is Lynx's all-platform magic number for executables. */
+
+#define LYNXCOFFMAGIC 0415
+
+#define OMAGIC M68MAGIC
+
+/* This intentionally does not include MC68KBCSMAGIC; it only includes
+ magic numbers which imply that names do not have underscores. */
+#define M68KBADMAG(x) (((x).f_magic!=MC68MAGIC) && ((x).f_magic!=MC68KWRMAGIC) && ((x).f_magic!=MC68TVMAGIC) && \
+ ((x).f_magic!=MC68KROMAGIC) && ((x).f_magic!=MC68KPGMAGIC) && ((x).f_magic!=M68MAGIC) && ((x).f_magic!=M68TVMAGIC) && ((x).f_magic!=LYNXCOFFMAGIC) )
+
+/* Magic numbers for the a.out header. */
+
+#define PAGEMAGICEXECSWAPPED 0407 /* executable (swapped) */
+#define PAGEMAGICPEXECSWAPPED 0410 /* pure executable (swapped) */
+#define PAGEMAGICPEXECTSHLIB 0443 /* pure executable (target shared library) */
+#define PAGEMAGICPEXECPAGED 0413 /* pure executable (paged) */
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _COMMENT ".comment"
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+#ifdef M68K_COFF_OFFSET
+ char r_offset[4];
+#endif
+
+};
+
+
+#define RELOC struct external_reloc
+
+#define RELSZ sizeof(struct external_reloc)
+
+#endif /* GNU_COFF_M68K_H */
diff --git a/contrib/gdb/include/coff/m88k.h b/contrib/gdb/include/coff/m88k.h
new file mode 100644
index 0000000..9068dd3
--- /dev/null
+++ b/contrib/gdb/include/coff/m88k.h
@@ -0,0 +1,218 @@
+/*** coff information for 88k bcs */
+
+/********************** FILE HEADER **********************/
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+#define MC88MAGIC 0540 /* 88k BCS executable */
+#define MC88DMAGIC 0541 /* DG/UX executable */
+#define MC88OMAGIC 0555 /* Object file */
+
+#define MC88BADMAG(x) (((x).f_magic!=MC88MAGIC) &&((x).f_magic!=MC88DMAGIC) && ((x).f_magic != MC88OMAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+#define PAGEMAGIC3 0414 /* Split i&d, zero mapped */
+#define PAGEMAGICBCS 0413
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+
+/* compute size of a header */
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr
+{
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[4]; /* number of relocation entries */
+ char s_nlnno[4]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _COMMENT ".comment"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno{
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+
+ char l_lnno[4];
+
+};
+
+#define LINENO struct external_lineno
+#define LINESZ 8
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+ char pad2[2];
+};
+
+
+
+
+#define N_BTMASK 017
+#define N_TMASK 060
+#define N_BTSHFT 4
+#define N_TSHIFT 2
+
+
+/* Note that this isn't the same shape as other coffs */
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ /* 4 */
+ union {
+ char x_fsize[4]; /* size of function */
+ struct {
+ char x_lnno[4]; /* declaration line number */
+ char x_size[4]; /* str/union/array size */
+ } x_lnsz;
+ } x_misc;
+
+ /* 12 */
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ /* 20 */
+
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[4]; /* # relocation entries */
+ char x_nlinno[4]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+};
+
+#define GET_FCN_LNNOPTR(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *)ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#define GET_FCN_ENDNDX(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
+#define PUT_FCN_LNNOPTR(abfd, in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_lnnoptr)
+#define PUT_FCN_ENDNDX(abfd, in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_sym.x_fcnary.x_fcn.x_endndx)
+#define GET_LNSZ_SIZE(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_size)
+#define GET_LNSZ_LNNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_lnno)
+#define PUT_LNSZ_LNNO(abfd, in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_lnno)
+#define PUT_LNSZ_SIZE(abfd, in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_sym.x_misc.x_lnsz.x_size)
+#define GET_SCN_SCNLEN(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_scn.x_scnlen)
+#define GET_SCN_NRELOC(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_scn.x_nreloc)
+#define GET_SCN_NLINNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) ext->x_scn.x_nlinno)
+#define PUT_SCN_SCNLEN(abfd,in, ext) bfd_h_put_32(abfd, in, (bfd_byte *) ext->x_scn.x_scnlen)
+#define PUT_SCN_NRELOC(abfd,in, ext) bfd_h_put_32(abfd, in, (bfd_byte *)ext->x_scn.x_nreloc)
+#define PUT_SCN_NLINNO(abfd,in, ext) bfd_h_put_32(abfd,in, (bfd_byte *) ext->x_scn.x_nlinno)
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) (ext->l_lnno))
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_32(abfd,val, (bfd_byte *) (ext->l_lnno));
+
+
+
+#define SYMENT struct external_syment
+#define SYMESZ 20
+#define AUXENT union external_auxent
+#define AUXESZ 20
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+ char r_offset[2];
+};
+
+#define RELOC struct external_reloc
+#define RELSZ 12
+
+#define NO_TVNDX
diff --git a/contrib/gdb/include/coff/mips.h b/contrib/gdb/include/coff/mips.h
new file mode 100644
index 0000000..f35187e
--- /dev/null
+++ b/contrib/gdb/include/coff/mips.h
@@ -0,0 +1,368 @@
+/* ECOFF support on MIPS machines.
+ coff/ecoff.h must be included before this file. */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ unsigned char f_magic[2]; /* magic number */
+ unsigned char f_nscns[2]; /* number of sections */
+ unsigned char f_timdat[4]; /* time & date stamp */
+ unsigned char f_symptr[4]; /* file pointer to symtab */
+ unsigned char f_nsyms[4]; /* number of symtab entries */
+ unsigned char f_opthdr[2]; /* sizeof(optional hdr) */
+ unsigned char f_flags[2]; /* flags */
+};
+
+/* Magic numbers are defined in coff/ecoff.h. */
+#define MIPS_ECOFF_BADMAG(x) (((x).f_magic!=MIPS_MAGIC_1) && \
+ ((x).f_magic!=MIPS_MAGIC_LITTLE) &&\
+ ((x).f_magic!=MIPS_MAGIC_BIG) && \
+ ((x).f_magic!=MIPS_MAGIC_LITTLE2) && \
+ ((x).f_magic!=MIPS_MAGIC_BIG2) && \
+ ((x).f_magic!=MIPS_MAGIC_LITTLE3) && \
+ ((x).f_magic!=MIPS_MAGIC_BIG3))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ 20
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct external_aouthdr
+{
+ unsigned char magic[2]; /* type of file */
+ unsigned char vstamp[2]; /* version stamp */
+ unsigned char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ unsigned char dsize[4]; /* initialized data " " */
+ unsigned char bsize[4]; /* uninitialized data " " */
+ unsigned char entry[4]; /* entry pt. */
+ unsigned char text_start[4]; /* base of text used for this file */
+ unsigned char data_start[4]; /* base of data used for this file */
+ unsigned char bss_start[4]; /* base of bss used for this file */
+ unsigned char gprmask[4]; /* ?? */
+ unsigned char cprmask[4][4]; /* ?? */
+ unsigned char gp_value[4]; /* value for gp register */
+} AOUTHDR;
+
+/* compute size of a header */
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+/********************** SECTION HEADER **********************/
+
+struct external_scnhdr {
+ unsigned char s_name[8]; /* section name */
+ unsigned char s_paddr[4]; /* physical address, aliased s_nlib */
+ unsigned char s_vaddr[4]; /* virtual address */
+ unsigned char s_size[4]; /* section size */
+ unsigned char s_scnptr[4]; /* file ptr to raw data for section */
+ unsigned char s_relptr[4]; /* file ptr to relocation */
+ unsigned char s_lnnoptr[4]; /* file ptr to line numbers */
+ unsigned char s_nreloc[2]; /* number of relocation entries */
+ unsigned char s_nlnno[2]; /* number of line number entries*/
+ unsigned char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct external_reloc {
+ unsigned char r_vaddr[4];
+ unsigned char r_bits[4];
+};
+
+#define RELOC struct external_reloc
+#define RELSZ 8
+
+/* MIPS ECOFF uses a packed 8 byte format for relocs. These constants
+ are used to unpack the r_bits field. */
+
+#define RELOC_BITS0_SYMNDX_SH_LEFT_BIG 16
+#define RELOC_BITS0_SYMNDX_SH_LEFT_LITTLE 0
+
+#define RELOC_BITS1_SYMNDX_SH_LEFT_BIG 8
+#define RELOC_BITS1_SYMNDX_SH_LEFT_LITTLE 8
+
+#define RELOC_BITS2_SYMNDX_SH_LEFT_BIG 0
+#define RELOC_BITS2_SYMNDX_SH_LEFT_LITTLE 16
+
+/* Originally, ECOFF used four bits for the reloc type and had three
+ reserved bits. Irix 4 added another bit for the reloc type, which
+ was easy because it was big endian and one of the spare bits became
+ the new most significant bit. To make this also work for little
+ endian ECOFF, we need to wrap one of the reserved bits around to
+ become the most significant bit of the reloc type. */
+#define RELOC_BITS3_TYPE_BIG 0x3E
+#define RELOC_BITS3_TYPE_SH_BIG 1
+#define RELOC_BITS3_TYPE_LITTLE 0x78
+#define RELOC_BITS3_TYPE_SH_LITTLE 3
+#define RELOC_BITS3_TYPEHI_LITTLE 0x04
+#define RELOC_BITS3_TYPEHI_SH_LITTLE 2
+
+#define RELOC_BITS3_EXTERN_BIG 0x01
+#define RELOC_BITS3_EXTERN_LITTLE 0x80
+
+/* The r_type field in a reloc is one of the following values. I
+ don't know if any other values can appear. These seem to be all
+ that occur in the Ultrix 4.2 libraries. */
+#define MIPS_R_IGNORE 0
+#define MIPS_R_REFHALF 1
+#define MIPS_R_REFWORD 2
+#define MIPS_R_JMPADDR 3
+#define MIPS_R_REFHI 4
+#define MIPS_R_REFLO 5
+#define MIPS_R_GPREL 6
+#define MIPS_R_LITERAL 7
+
+/* These reloc types are a Cygnus extension used when generating
+ position independent code for embedded systems. The numbers are
+ taken from Irix 4, but at least for internal relocs Irix 5 does not
+ give them the same meaning. For an internal reloc the symbol index
+ of RELHI and RELLO is modified as described below for
+ MIPS_R_SWITCH. */
+#define MIPS_R_PCREL16 12
+#define MIPS_R_RELHI 13
+#define MIPS_R_RELLO 14
+
+/* This reloc type is a Cygnus extension used when generating position
+ independent code for embedded systems. It is used for an entry in
+ a switch table, which looks like this:
+ .word $L3-$LS12
+ The object file will contain the correct difference, and does not
+ require adjustment. However, when the linker is relaxing PC
+ relative calls, it is possible for $L3 to move farther away. This
+ reloc always appears in the .text section, and is always against
+ the .text section. However, the symbol index is not
+ RELOC_SECTION_TEXT. It is, instead, the distance between this
+ switch table entry and $LS12. Thus, the original value of $L12 is
+ vaddr - symndx
+ and the original value of $L3 is
+ vaddr - symndx + addend
+ where addend is the value in the object file. Knowing this, the
+ linker can know whether the addend in the object file must be
+ adjusted. */
+#define MIPS_R_SWITCH 22
+
+/********************** STABS **********************/
+
+#define MIPS_IS_STAB ECOFF_IS_STAB
+#define MIPS_MARK_STAB ECOFF_MARK_STAB
+#define MIPS_UNMARK_STAB ECOFF_UNMARK_STAB
+
+/********************** SYMBOLIC INFORMATION **********************/
+
+/* Written by John Gilmore. */
+
+/* ECOFF uses COFF-like section structures, but its own symbol format.
+ This file defines the symbol format in fields whose size and alignment
+ will not vary on different host systems. */
+
+/* File header as a set of bytes */
+
+struct hdr_ext {
+ unsigned char h_magic[2];
+ unsigned char h_vstamp[2];
+ unsigned char h_ilineMax[4];
+ unsigned char h_cbLine[4];
+ unsigned char h_cbLineOffset[4];
+ unsigned char h_idnMax[4];
+ unsigned char h_cbDnOffset[4];
+ unsigned char h_ipdMax[4];
+ unsigned char h_cbPdOffset[4];
+ unsigned char h_isymMax[4];
+ unsigned char h_cbSymOffset[4];
+ unsigned char h_ioptMax[4];
+ unsigned char h_cbOptOffset[4];
+ unsigned char h_iauxMax[4];
+ unsigned char h_cbAuxOffset[4];
+ unsigned char h_issMax[4];
+ unsigned char h_cbSsOffset[4];
+ unsigned char h_issExtMax[4];
+ unsigned char h_cbSsExtOffset[4];
+ unsigned char h_ifdMax[4];
+ unsigned char h_cbFdOffset[4];
+ unsigned char h_crfd[4];
+ unsigned char h_cbRfdOffset[4];
+ unsigned char h_iextMax[4];
+ unsigned char h_cbExtOffset[4];
+};
+
+/* File descriptor external record */
+
+struct fdr_ext {
+ unsigned char f_adr[4];
+ unsigned char f_rss[4];
+ unsigned char f_issBase[4];
+ unsigned char f_cbSs[4];
+ unsigned char f_isymBase[4];
+ unsigned char f_csym[4];
+ unsigned char f_ilineBase[4];
+ unsigned char f_cline[4];
+ unsigned char f_ioptBase[4];
+ unsigned char f_copt[4];
+ unsigned char f_ipdFirst[2];
+ unsigned char f_cpd[2];
+ unsigned char f_iauxBase[4];
+ unsigned char f_caux[4];
+ unsigned char f_rfdBase[4];
+ unsigned char f_crfd[4];
+ unsigned char f_bits1[1];
+ unsigned char f_bits2[3];
+ unsigned char f_cbLineOffset[4];
+ unsigned char f_cbLine[4];
+};
+
+#define FDR_BITS1_LANG_BIG 0xF8
+#define FDR_BITS1_LANG_SH_BIG 3
+#define FDR_BITS1_LANG_LITTLE 0x1F
+#define FDR_BITS1_LANG_SH_LITTLE 0
+
+#define FDR_BITS1_FMERGE_BIG 0x04
+#define FDR_BITS1_FMERGE_LITTLE 0x20
+
+#define FDR_BITS1_FREADIN_BIG 0x02
+#define FDR_BITS1_FREADIN_LITTLE 0x40
+
+#define FDR_BITS1_FBIGENDIAN_BIG 0x01
+#define FDR_BITS1_FBIGENDIAN_LITTLE 0x80
+
+#define FDR_BITS2_GLEVEL_BIG 0xC0
+#define FDR_BITS2_GLEVEL_SH_BIG 6
+#define FDR_BITS2_GLEVEL_LITTLE 0x03
+#define FDR_BITS2_GLEVEL_SH_LITTLE 0
+
+/* We ignore the `reserved' field in bits2. */
+
+/* Procedure descriptor external record */
+
+struct pdr_ext {
+ unsigned char p_adr[4];
+ unsigned char p_isym[4];
+ unsigned char p_iline[4];
+ unsigned char p_regmask[4];
+ unsigned char p_regoffset[4];
+ unsigned char p_iopt[4];
+ unsigned char p_fregmask[4];
+ unsigned char p_fregoffset[4];
+ unsigned char p_frameoffset[4];
+ unsigned char p_framereg[2];
+ unsigned char p_pcreg[2];
+ unsigned char p_lnLow[4];
+ unsigned char p_lnHigh[4];
+ unsigned char p_cbLineOffset[4];
+};
+
+/* Runtime procedure table */
+
+struct rpdr_ext {
+ unsigned char p_adr[4];
+ unsigned char p_regmask[4];
+ unsigned char p_regoffset[4];
+ unsigned char p_fregmask[4];
+ unsigned char p_fregoffset[4];
+ unsigned char p_frameoffset[4];
+ unsigned char p_framereg[2];
+ unsigned char p_pcreg[2];
+ unsigned char p_irpss[4];
+ unsigned char p_reserved[4];
+ unsigned char p_exception_info[4];
+};
+
+/* Line numbers */
+
+struct line_ext {
+ unsigned char l_line[4];
+};
+
+/* Symbol external record */
+
+struct sym_ext {
+ unsigned char s_iss[4];
+ unsigned char s_value[4];
+ unsigned char s_bits1[1];
+ unsigned char s_bits2[1];
+ unsigned char s_bits3[1];
+ unsigned char s_bits4[1];
+};
+
+#define SYM_BITS1_ST_BIG 0xFC
+#define SYM_BITS1_ST_SH_BIG 2
+#define SYM_BITS1_ST_LITTLE 0x3F
+#define SYM_BITS1_ST_SH_LITTLE 0
+
+#define SYM_BITS1_SC_BIG 0x03
+#define SYM_BITS1_SC_SH_LEFT_BIG 3
+#define SYM_BITS1_SC_LITTLE 0xC0
+#define SYM_BITS1_SC_SH_LITTLE 6
+
+#define SYM_BITS2_SC_BIG 0xE0
+#define SYM_BITS2_SC_SH_BIG 5
+#define SYM_BITS2_SC_LITTLE 0x07
+#define SYM_BITS2_SC_SH_LEFT_LITTLE 2
+
+#define SYM_BITS2_RESERVED_BIG 0x10
+#define SYM_BITS2_RESERVED_LITTLE 0x08
+
+#define SYM_BITS2_INDEX_BIG 0x0F
+#define SYM_BITS2_INDEX_SH_LEFT_BIG 16
+#define SYM_BITS2_INDEX_LITTLE 0xF0
+#define SYM_BITS2_INDEX_SH_LITTLE 4
+
+#define SYM_BITS3_INDEX_SH_LEFT_BIG 8
+#define SYM_BITS3_INDEX_SH_LEFT_LITTLE 4
+
+#define SYM_BITS4_INDEX_SH_LEFT_BIG 0
+#define SYM_BITS4_INDEX_SH_LEFT_LITTLE 12
+
+/* External symbol external record */
+
+struct ext_ext {
+ unsigned char es_bits1[1];
+ unsigned char es_bits2[1];
+ unsigned char es_ifd[2];
+ struct sym_ext es_asym;
+};
+
+#define EXT_BITS1_JMPTBL_BIG 0x80
+#define EXT_BITS1_JMPTBL_LITTLE 0x01
+
+#define EXT_BITS1_COBOL_MAIN_BIG 0x40
+#define EXT_BITS1_COBOL_MAIN_LITTLE 0x02
+
+#define EXT_BITS1_WEAKEXT_BIG 0x20
+#define EXT_BITS1_WEAKEXT_LITTLE 0x04
+
+/* Dense numbers external record */
+
+struct dnr_ext {
+ unsigned char d_rfd[4];
+ unsigned char d_index[4];
+};
+
+/* Relative file descriptor */
+
+struct rfd_ext {
+ unsigned char rfd[4];
+};
+
+/* Optimizer symbol external record */
+
+struct opt_ext {
+ unsigned char o_bits1[1];
+ unsigned char o_bits2[1];
+ unsigned char o_bits3[1];
+ unsigned char o_bits4[1];
+ struct rndx_ext o_rndx;
+ unsigned char o_offset[4];
+};
+
+#define OPT_BITS2_VALUE_SH_LEFT_BIG 16
+#define OPT_BITS2_VALUE_SH_LEFT_LITTLE 0
+
+#define OPT_BITS3_VALUE_SH_LEFT_BIG 8
+#define OPT_BITS3_VALUE_SH_LEFT_LITTLE 8
+
+#define OPT_BITS4_VALUE_SH_LEFT_BIG 0
+#define OPT_BITS4_VALUE_SH_LEFT_LITTLE 16
diff --git a/contrib/gdb/include/coff/pe.h b/contrib/gdb/include/coff/pe.h
new file mode 100644
index 0000000..f13b8b9
--- /dev/null
+++ b/contrib/gdb/include/coff/pe.h
@@ -0,0 +1,161 @@
+/* PE COFF header information */
+
+#ifndef _PE_H
+#define _PE_H
+
+/* NT specific file attributes */
+#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
+#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
+#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
+#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
+#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
+#define IMAGE_FILE_32BIT_MACHINE 0x0100
+#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
+#define IMAGE_FILE_SYSTEM 0x1000
+#define IMAGE_FILE_DLL 0x2000
+#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
+
+/* additional flags to be set for section headers to allow the NT loader to
+ read and write to the section data (to replace the addresses of data in
+ dlls for one thing); also to execute the section in .text's case */
+#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
+#define IMAGE_SCN_MEM_EXECUTE 0x20000000
+#define IMAGE_SCN_MEM_READ 0x40000000
+#define IMAGE_SCN_MEM_WRITE 0x80000000
+
+/*
+ * Section characteristics added for ppc-nt
+ */
+
+#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */
+
+#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */
+
+#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */
+#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */
+#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */
+#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */
+
+#define IMAGE_SCN_MEM_FARDATA 0x00008000
+
+#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
+#define IMAGE_SCN_MEM_16BIT 0x00020000
+#define IMAGE_SCN_MEM_LOCKED 0x00040000
+#define IMAGE_SCN_MEM_PRELOAD 0x00080000
+
+#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
+#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
+#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
+#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
+#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */
+#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
+#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
+
+
+#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */
+#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */
+#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */
+#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */
+
+
+/* Magic values that are true for all dos/nt implementations */
+#define DOSMAGIC 0x5a4d
+#define NT_SIGNATURE 0x00004550
+
+ /* NT allows long filenames, we want to accommodate this. This may break
+ some of the bfd functions */
+#undef FILNMLEN
+#define FILNMLEN 18 /* # characters in a file name */
+
+
+#ifdef COFF_IMAGE_WITH_PE
+/* The filehdr is only weired in images */
+
+#undef FILHDR
+struct external_PE_filehdr
+{
+ /* DOS header fields */
+ char e_magic[2]; /* Magic number, 0x5a4d */
+ char e_cblp[2]; /* Bytes on last page of file, 0x90 */
+ char e_cp[2]; /* Pages in file, 0x3 */
+ char e_crlc[2]; /* Relocations, 0x0 */
+ char e_cparhdr[2]; /* Size of header in paragraphs, 0x4 */
+ char e_minalloc[2]; /* Minimum extra paragraphs needed, 0x0 */
+ char e_maxalloc[2]; /* Maximum extra paragraphs needed, 0xFFFF */
+ char e_ss[2]; /* Initial (relative) SS value, 0x0 */
+ char e_sp[2]; /* Initial SP value, 0xb8 */
+ char e_csum[2]; /* Checksum, 0x0 */
+ char e_ip[2]; /* Initial IP value, 0x0 */
+ char e_cs[2]; /* Initial (relative) CS value, 0x0 */
+ char e_lfarlc[2]; /* File address of relocation table, 0x40 */
+ char e_ovno[2]; /* Overlay number, 0x0 */
+ char e_res[4][2]; /* Reserved words, all 0x0 */
+ char e_oemid[2]; /* OEM identifier (for e_oeminfo), 0x0 */
+ char e_oeminfo[2]; /* OEM information; e_oemid specific, 0x0 */
+ char e_res2[10][2]; /* Reserved words, all 0x0 */
+ char e_lfanew[4]; /* File address of new exe header, 0x80 */
+ char dos_message[16][4]; /* other stuff, always follow DOS header */
+ char nt_signature[4]; /* required NT signature, 0x4550 */
+
+ /* From standard header */
+
+
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+
+};
+
+
+#define FILHDR struct external_PE_filehdr
+
+
+#endif
+
+typedef struct
+{
+ AOUTHDR standard;
+
+ /* NT extra fields; see internal.h for descriptions */
+ char ImageBase[4];
+ char SectionAlignment[4];
+ char FileAlignment[4];
+ char MajorOperatingSystemVersion[2];
+ char MinorOperatingSystemVersion[2];
+ char MajorImageVersion[2];
+ char MinorImageVersion[2];
+ char MajorSubsystemVersion[2];
+ char MinorSubsystemVersion[2];
+ char Reserved1[4];
+ char SizeOfImage[4];
+ char SizeOfHeaders[4];
+ char CheckSum[4];
+ char Subsystem[2];
+ char DllCharacteristics[2];
+ char SizeOfStackReserve[4];
+ char SizeOfStackCommit[4];
+ char SizeOfHeapReserve[4];
+ char SizeOfHeapCommit[4];
+ char LoaderFlags[4];
+ char NumberOfRvaAndSizes[4];
+ /* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
+ char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
+
+} PEAOUTHDR;
+
+
+#undef AOUTSZ
+#define AOUTSZ sizeof(PEAOUTHDR)
+
+#undef E_FILNMLEN
+#define E_FILNMLEN 18 /* # characters in a file name */
+#endif
+
+
+
diff --git a/contrib/gdb/include/coff/powerpc.h b/contrib/gdb/include/coff/powerpc.h
new file mode 100644
index 0000000..6866fc8
--- /dev/null
+++ b/contrib/gdb/include/coff/powerpc.h
@@ -0,0 +1,196 @@
+/* Basic coff information for the PowerPC
+ *
+ * Based on coff/rs6000.h, coff/i386.h and others.
+ *
+ * Initial release: Kim Knuttila (krk@cygnus.com)
+ */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved external references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+
+/* extra NT defines */
+#define PPCMAGIC 0760 /* peeked on aa PowerPC Windows NT box */
+#define DOSMAGIC 0x5a4d /* from arm.h, i386.h */
+#define NT_SIGNATURE 0x00004550 /* from arm.h, i386.h */
+
+/* from winnt.h */
+#define IMAGE_NT_OPTIONAL_HDR_MAGIC 0x10b
+
+#define PPCBADMAG(x) ((x).f_magic != PPCMAGIC)
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+/********************** SECTION HEADER **********************/
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries */
+ char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _COMMENT ".comment"
+#define _LIB ".lib"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0 */
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+#define LINENO struct external_lineno
+#define LINESZ 6
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+
+/* Allow the file name length to be overridden in the including file */
+#ifndef E_FILNMLEN
+#define E_FILNMLEN 14
+#endif
+
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+
+#define N_BTMASK (0xf)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+};
+
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+#define _ETEXT "etext"
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+};
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
diff --git a/contrib/gdb/include/coff/rs6000.h b/contrib/gdb/include/coff/rs6000.h
new file mode 100644
index 0000000..62a6f86
--- /dev/null
+++ b/contrib/gdb/include/coff/rs6000.h
@@ -0,0 +1,242 @@
+/* IBM RS/6000 "XCOFF" file definitions for BFD.
+ Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ FIXME: Can someone provide a transliteration of this name into ASCII?
+ Using the following chars caused a compiler warning on HIUX (so I replaced
+ them with octal escapes), and isn't useful without an understanding of what
+ character set it is.
+ Written by Mimi Ph\373\364ng-Th\345o V\365 of IBM
+ and John Gilmore of Cygnus Support. */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+ /* IBM RS/6000 */
+#define U802WRMAGIC 0730 /* writeable text segments **chh** */
+#define U802ROMAGIC 0735 /* readonly sharable text segments */
+#define U802TOCMAGIC 0737 /* readonly text segments and TOC */
+
+#define BADMAG(x) \
+ ((x).f_magic != U802ROMAGIC && (x).f_magic != U802WRMAGIC && \
+ (x).f_magic != U802TOCMAGIC)
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ unsigned char magic[2]; /* type of file */
+ unsigned char vstamp[2]; /* version stamp */
+ unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
+ unsigned char dsize[4]; /* initialized data " " */
+ unsigned char bsize[4]; /* uninitialized data " " */
+ unsigned char entry[4]; /* entry pt. */
+ unsigned char text_start[4]; /* base of text used for this file */
+ unsigned char data_start[4]; /* base of data used for this file */
+ unsigned char o_toc[4]; /* address of TOC */
+ unsigned char o_snentry[2]; /* section number of entry point */
+ unsigned char o_sntext[2]; /* section number of .text section */
+ unsigned char o_sndata[2]; /* section number of .data section */
+ unsigned char o_sntoc[2]; /* section number of TOC */
+ unsigned char o_snloader[2]; /* section number of .loader section */
+ unsigned char o_snbss[2]; /* section number of .bss section */
+ unsigned char o_algntext[2]; /* .text alignment */
+ unsigned char o_algndata[2]; /* .data alignment */
+ unsigned char o_modtype[2]; /* module type (??) */
+ unsigned char o_cputype[2]; /* cpu type */
+ unsigned char o_maxstack[4]; /* max stack size (??) */
+ unsigned char o_maxdata[4]; /* max data size (??) */
+ unsigned char o_resv2[12]; /* reserved */
+}
+AOUTHDR;
+
+#define AOUTSZ (sizeof(AOUTHDR))
+#define SMALL_AOUTSZ (28)
+
+#define RS6K_AOUTHDR_OMAGIC 0x0107 /* old: text & data writeable */
+#define RS6K_AOUTHDR_NMAGIC 0x0108 /* new: text r/o, data r/w */
+#define RS6K_AOUTHDR_ZMAGIC 0x010B /* paged: text r/o, both page-aligned */
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _PAD ".pad"
+#define _LOADER ".loader"
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/* XCOFF uses a special .loader section with type STYP_LOADER. */
+#define STYP_LOADER 0x1000
+
+/* XCOFF uses a special .debug section with type STYP_DEBUG. */
+#define STYP_DEBUG 0x2000
+
+/* XCOFF handles line number or relocation overflow by creating
+ another section header with STYP_OVRFLO set. */
+#define STYP_OVRFLO 0x8000
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+ struct {
+ unsigned char x_scnlen[4];
+ unsigned char x_parmhash[4];
+ unsigned char x_snhash[2];
+ unsigned char x_smtyp[1];
+ unsigned char x_smclas[1];
+ unsigned char x_stab[4];
+ unsigned char x_snstab[2];
+ } x_csect;
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+#define DBXMASK 0x80 /* for dbx storage mask */
+#define SYMNAME_IN_DEBUG(symptr) ((symptr)->n_sclass & DBXMASK)
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_size[1];
+ char r_type[1];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 10
+
+#define DEFAULT_DATA_SECTION_ALIGNMENT 4
+#define DEFAULT_BSS_SECTION_ALIGNMENT 4
+#define DEFAULT_TEXT_SECTION_ALIGNMENT 4
+/* For new sections we havn't heard of before */
+#define DEFAULT_SECTION_ALIGNMENT 4
diff --git a/contrib/gdb/include/coff/sh.h b/contrib/gdb/include/coff/sh.h
new file mode 100644
index 0000000..af49674
--- /dev/null
+++ b/contrib/gdb/include/coff/sh.h
@@ -0,0 +1,253 @@
+/*** coff information for Hitachi SH */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+
+#define SH_ARCH_MAGIC_BIG 0x0500
+#define SH_ARCH_MAGIC_LITTLE 0x0550 /* Little endian SH */
+
+
+#define SHBADMAG(x) \
+ (((x).f_magic!=SH_ARCH_MAGIC_BIG) && \
+ ((x).f_magic!=SH_ARCH_MAGIC_LITTLE))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+
+#define AOUTHDRSZ (sizeof(AOUTHDR))
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[4]; /* line number */
+};
+
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) (ext->l_lnno));
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_32(abfd,val, (bfd_byte *) (ext->l_lnno));
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+/* The external reloc has an offset field, because some of the reloc
+ types on the h8 don't have room in the instruction for the entire
+ offset - eg the strange jump and high page addressing modes */
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_offset[4];
+ char r_type[2];
+ char r_stuff[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 16
+
+/* SH relocation types. Not all of these are actually used. */
+
+#define R_SH_UNUSED 0 /* only used internally */
+#define R_SH_PCREL8 3 /* 8 bit pcrel */
+#define R_SH_PCREL16 4 /* 16 bit pcrel */
+#define R_SH_HIGH8 5 /* high 8 bits of 24 bit address */
+#define R_SH_LOW16 7 /* low 16 bits of 24 bit immediate */
+#define R_SH_IMM24 6 /* 24 bit immediate */
+#define R_SH_PCDISP8BY4 9 /* PC rel 8 bits *4 +ve */
+#define R_SH_PCDISP8BY2 10 /* PC rel 8 bits *2 +ve */
+#define R_SH_PCDISP8 11 /* 8 bit branch */
+#define R_SH_PCDISP 12 /* 12 bit branch */
+#define R_SH_IMM32 14 /* 32 bit immediate */
+#define R_SH_IMM8 16 /* 8 bit immediate */
+#define R_SH_IMM8BY2 17 /* 8 bit immediate *2 */
+#define R_SH_IMM8BY4 18 /* 8 bit immediate *4 */
+#define R_SH_IMM4 19 /* 4 bit immediate */
+#define R_SH_IMM4BY2 20 /* 4 bit immediate *2 */
+#define R_SH_IMM4BY4 21 /* 4 bit immediate *4 */
+#define R_SH_PCRELIMM8BY2 22 /* PC rel 8 bits *2 unsigned */
+#define R_SH_PCRELIMM8BY4 23 /* PC rel 8 bits *4 unsigned */
+#define R_SH_IMM16 24 /* 16 bit immediate */
+
+/* The switch table reloc types are used for relaxing. They are
+ generated for expressions such as
+ .word L1 - L2
+ The r_offset field holds the difference between the reloc address
+ and L2. */
+#define R_SH_SWITCH16 25 /* 16 bit switch table entry */
+#define R_SH_SWITCH32 26 /* 16 bit switch table entry */
+
+/* The USES reloc type is used for relaxing. The compiler will
+ generate .uses pseudo-ops when it finds a function call which it
+ can relax. The r_offset field of the USES reloc holds the PC
+ relative offset to the instruction which loads the register used in
+ the function call. */
+#define R_SH_USES 27 /* .uses pseudo-op */
+
+/* The COUNT reloc type is used for relaxing. The assembler will
+ generate COUNT relocs for addresses referred to by the register
+ loads associated with USES relocs. The r_offset field of the COUNT
+ reloc holds the number of times the address is references in the
+ object file. */
+#define R_SH_COUNT 28 /* Count of constant pool uses */
+
+/* The ALIGN reloc type is used for relaxing. The r_offset field is
+ the power of two to which subsequent portions of the object file
+ must be aligned. */
+#define R_SH_ALIGN 29 /* .align pseudo-op */
+
+
+
diff --git a/contrib/gdb/include/coff/sparc.h b/contrib/gdb/include/coff/sparc.h
new file mode 100644
index 0000000..0e3217b
--- /dev/null
+++ b/contrib/gdb/include/coff/sparc.h
@@ -0,0 +1,209 @@
+/*** coff information for Sparc. */
+
+/* This file is an amalgamation of several standard include files that
+ define coff format, such as filehdr.h, aouthdr.h, and so forth. In
+ addition, all datatypes have been translated into character arrays of
+ (presumed) equivalent size. This is necessary so that this file can
+ be used with different systems while still yielding the same results. */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr
+{
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+#define F_RELFLG (0x0001) /* relocation info stripped */
+#define F_EXEC (0x0002) /* file is executable */
+#define F_LNNO (0x0004) /* line numbers stripped */
+#define F_LSYMS (0x0008) /* local symbols stripped */
+
+#define SPARCMAGIC (0540)
+
+/* This is Lynx's all-platform magic number for executables. */
+
+#define LYNXCOFFMAGIC (0415)
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+#define OMAGIC 0404 /* object files, eg as output */
+#define ZMAGIC 0413 /* demand load format, eg normal ld output */
+#define STMAGIC 0401 /* target shlib */
+#define SHMAGIC 0443 /* host shlib */
+
+/********************** SECTION HEADER **********************/
+
+struct external_scnhdr
+{
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/* Names of "special" sections. */
+
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _TV ".tv"
+#define _INIT ".init"
+#define _FINI ".fini"
+#define _COMMENT ".comment"
+#define _LIB ".lib"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ Line numbers are grouped on a per function basis; first entry in a function
+ grouping will have l_lnno = 0 and in place of physical address will be the
+ symbol table index of the function name. */
+
+struct external_lineno
+{
+ union {
+ char l_symndx[4]; /* fn name symbol index, iff l_lnno == 0 */
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+#define LINENO struct external_lineno
+#define LINESZ (6)
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN (8) /* # characters in a symbol name */
+#define E_FILNMLEN (14) /* # characters in a file name */
+#define E_DIMNUM (4) /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+#if 0 /* of doubtful value */
+ char e_nptr[2][4];
+ struct {
+ char e_leading_zero[1];
+ char e_dbx_type[1];
+ char e_dbx_desc[2];
+ } e_dbx;
+#endif
+ } e;
+
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+ char padding[2];
+};
+
+#define N_BTMASK (0xf)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+union external_auxent
+{
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* .tv section info (in auxent of sym .tv)) */
+
+ char x_fill[20]; /* forces to 20-byte size */
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 20
+#define AUXENT union external_auxent
+#define AUXESZ 20
+
+#define _ETEXT "etext"
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+ char r_spare[2];
+ char r_offset[4];
+};
+
+#define RELOC struct external_reloc
+#define RELSZ sizeof (RELOC)
+
diff --git a/contrib/gdb/include/coff/sym.h b/contrib/gdb/include/coff/sym.h
new file mode 100644
index 0000000..76204af
--- /dev/null
+++ b/contrib/gdb/include/coff/sym.h
@@ -0,0 +1,484 @@
+/* Declarations of internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+#ifndef _SYM_H
+#define _SYM_H
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/*
+ * This file contains the definition of the Third Eye Symbol Table.
+ *
+ * Symbols are assumed to be in 'encounter order' - i.e. the order that
+ * the things they represent were encountered by the compiler/assembler/loader.
+ * EXCEPT for globals! These are assumed to be bunched together,
+ * probably right after the last 'normal' symbol. Globals ARE sorted
+ * in ascending order.
+ *
+ * -----------------------------------------------------------------------
+ * A brief word about Third Eye naming/use conventions:
+ *
+ * All arrays and index's are 0 based.
+ * All "ifooMax" values are the highest legal value PLUS ONE. This makes
+ * them good for allocating arrays, etc. All checks are "ifoo < ifooMax".
+ *
+ * "isym" Index into the SYMbol table.
+ * "ipd" Index into the Procedure Descriptor array.
+ * "ifd" Index into the File Descriptor array.
+ * "iss" Index into String Space.
+ * "cb" Count of Bytes.
+ * "rgPd" array whose domain is "0..ipdMax-1" and RanGe is PDR.
+ * "rgFd" array whose domain is "0..ifdMax-1" and RanGe is FDR.
+ */
+
+
+/*
+ * Symbolic Header (HDR) structure.
+ * As long as all the pointers are set correctly,
+ * we don't care WHAT order the various sections come out in!
+ *
+ * A file produced solely for the use of CDB will probably NOT have
+ * any instructions or data areas in it, as these are available
+ * in the original.
+ */
+
+typedef struct {
+ short magic; /* to verify validity of the table */
+ short vstamp; /* version stamp */
+ long ilineMax; /* number of line number entries */
+ bfd_vma cbLine; /* number of bytes for line number entries */
+ bfd_vma cbLineOffset; /* offset to start of line number entries*/
+ long idnMax; /* max index into dense number table */
+ bfd_vma cbDnOffset; /* offset to start dense number table */
+ long ipdMax; /* number of procedures */
+ bfd_vma cbPdOffset; /* offset to procedure descriptor table */
+ long isymMax; /* number of local symbols */
+ bfd_vma cbSymOffset; /* offset to start of local symbols*/
+ long ioptMax; /* max index into optimization symbol entries */
+ bfd_vma cbOptOffset; /* offset to optimization symbol entries */
+ long iauxMax; /* number of auxillary symbol entries */
+ bfd_vma cbAuxOffset; /* offset to start of auxillary symbol entries*/
+ long issMax; /* max index into local strings */
+ bfd_vma cbSsOffset; /* offset to start of local strings */
+ long issExtMax; /* max index into external strings */
+ bfd_vma cbSsExtOffset; /* offset to start of external strings */
+ long ifdMax; /* number of file descriptor entries */
+ bfd_vma cbFdOffset; /* offset to file descriptor table */
+ long crfd; /* number of relative file descriptor entries */
+ bfd_vma cbRfdOffset; /* offset to relative file descriptor table */
+ long iextMax; /* max index into external symbols */
+ bfd_vma cbExtOffset; /* offset to start of external symbol entries*/
+ /* If you add machine dependent fields, add them here */
+ } HDRR, *pHDRR;
+#define cbHDRR sizeof(HDRR)
+#define hdrNil ((pHDRR)0)
+
+/*
+ * The FDR and PDR structures speed mapping of address <-> name.
+ * They are sorted in ascending memory order and are kept in
+ * memory by CDB at runtime.
+ */
+
+/*
+ * File Descriptor
+ *
+ * There is one of these for EVERY FILE, whether compiled with
+ * full debugging symbols or not. The name of a file should be
+ * the path name given to the compiler. This allows the user
+ * to simply specify the names of the directories where the COMPILES
+ * were done, and we will be able to find their files.
+ * A field whose comment starts with "R - " indicates that it will be
+ * setup at runtime.
+ */
+typedef struct fdr {
+ bfd_vma adr; /* memory address of beginning of file */
+ long rss; /* file name (of source, if known) */
+ long issBase; /* file's string space */
+ bfd_vma cbSs; /* number of bytes in the ss */
+ long isymBase; /* beginning of symbols */
+ long csym; /* count file's of symbols */
+ long ilineBase; /* file's line symbols */
+ long cline; /* count of file's line symbols */
+ long ioptBase; /* file's optimization entries */
+ long copt; /* count of file's optimization entries */
+ unsigned short ipdFirst;/* start of procedures for this file */
+ short cpd; /* count of procedures for this file */
+ long iauxBase; /* file's auxiliary entries */
+ long caux; /* count of file's auxiliary entries */
+ long rfdBase; /* index into the file indirect table */
+ long crfd; /* count file indirect entries */
+ unsigned lang: 5; /* language for this file */
+ unsigned fMerge : 1; /* whether this file can be merged */
+ unsigned fReadin : 1; /* true if it was read in (not just created) */
+ unsigned fBigendian : 1;/* if set, was compiled on big endian machine */
+ /* aux's will be in compile host's sex */
+ unsigned glevel : 2; /* level this file was compiled with */
+ unsigned reserved : 22; /* reserved for future use */
+ bfd_vma cbLineOffset; /* byte offset from header for this file ln's */
+ bfd_vma cbLine; /* size of lines for this file */
+ } FDR, *pFDR;
+#define cbFDR sizeof(FDR)
+#define fdNil ((pFDR)0)
+#define ifdNil -1
+#define ifdTemp 0
+#define ilnNil -1
+
+
+/*
+ * Procedure Descriptor
+ *
+ * There is one of these for EVERY TEXT LABEL.
+ * If a procedure is in a file with full symbols, then isym
+ * will point to the PROC symbols, else it will point to the
+ * global symbol for the label.
+ */
+
+typedef struct pdr {
+ bfd_vma adr; /* memory address of start of procedure */
+ long isym; /* start of local symbol entries */
+ long iline; /* start of line number entries*/
+ long regmask; /* save register mask */
+ long regoffset; /* save register offset */
+ long iopt; /* start of optimization symbol entries*/
+ long fregmask; /* save floating point register mask */
+ long fregoffset; /* save floating point register offset */
+ long frameoffset; /* frame size */
+ short framereg; /* frame pointer register */
+ short pcreg; /* offset or reg of return pc */
+ long lnLow; /* lowest line in the procedure */
+ long lnHigh; /* highest line in the procedure */
+ bfd_vma cbLineOffset; /* byte offset for this procedure from the fd base */
+ /* These fields are new for 64 bit ECOFF. */
+ unsigned gp_prologue : 8; /* byte size of GP prologue */
+ unsigned gp_used : 1; /* true if the procedure uses GP */
+ unsigned reg_frame : 1; /* true if register frame procedure */
+ unsigned prof : 1; /* true if compiled with -pg */
+ unsigned reserved : 13; /* reserved: must be zero */
+ unsigned localoff : 8; /* offset of local variables from vfp */
+ } PDR, *pPDR;
+#define cbPDR sizeof(PDR)
+#define pdNil ((pPDR) 0)
+#define ipdNil -1
+
+/*
+ * The structure of the runtime procedure descriptor created by the loader
+ * for use by the static exception system.
+ */
+/*
+ * If 0'd out because exception_info chokes Visual C++ and because there
+ * don't seem to be any references to this structure elsewhere in gdb.
+ */
+#if 0
+typedef struct runtime_pdr {
+ 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 */
+ long fregoffset; /* save floating point register offset */
+ long frameoffset; /* frame size */
+ short framereg; /* frame pointer register */
+ short pcreg; /* offset or reg of return pc */
+ long irpss; /* index into the runtime string table */
+ long reserved;
+ struct exception_info *exception_info;/* pointer to exception array */
+} RPDR, *pRPDR;
+#define cbRPDR sizeof(RPDR)
+#define rpdNil ((pRPDR) 0)
+#endif
+
+/*
+ * Line Numbers
+ *
+ * Line Numbers are segregated from the normal symbols because they
+ * are [1] smaller , [2] are of no interest to your
+ * average loader, and [3] are never needed in the middle of normal
+ * scanning and therefore slow things down.
+ *
+ * By definition, the first LINER for any given procedure will have
+ * the first line of a procedure and represent the first address.
+ */
+
+typedef long LINER, *pLINER;
+#define lineNil ((pLINER)0)
+#define cbLINER sizeof(LINER)
+#define ilineNil -1
+
+
+
+/*
+ * The Symbol Structure (GFW, to those who Know!)
+ */
+
+typedef struct {
+ long iss; /* index into String Space of name */
+ bfd_vma value; /* value of symbol */
+ unsigned st : 6; /* symbol type */
+ unsigned sc : 5; /* storage class - text, data, etc */
+ unsigned reserved : 1; /* reserved */
+ unsigned index : 20; /* index into sym/aux table */
+ } SYMR, *pSYMR;
+#define symNil ((pSYMR)0)
+#define cbSYMR sizeof(SYMR)
+#define isymNil -1
+#define indexNil 0xfffff
+#define issNil -1
+#define issNull 0
+
+
+/* The following converts a memory resident string to an iss.
+ * This hack is recognized in SbFIss, in sym.c of the debugger.
+ */
+#define IssFSb(sb) (0x80000000 | ((unsigned long)(sb)))
+
+/* E X T E R N A L S Y M B O L R E C O R D
+ *
+ * Same as the SYMR except it contains file context to determine where
+ * the index is.
+ */
+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 */
+ unsigned reserved:13; /* reserved for future use */
+ int ifd; /* where the iss and index fields point into */
+ SYMR asym; /* symbol for the external */
+ } EXTR, *pEXTR;
+#define extNil ((pEXTR)0)
+#define cbEXTR sizeof(EXTR)
+
+
+/* A U X I L L A R Y T Y P E I N F O R M A T I O N */
+
+/*
+ * Type Information Record
+ */
+typedef struct {
+ unsigned fBitfield : 1; /* set if bit width is specified */
+ unsigned continued : 1; /* indicates additional TQ info in next AUX */
+ unsigned bt : 6; /* basic type */
+ unsigned tq4 : 4;
+ unsigned tq5 : 4;
+ /* ---- 16 bit boundary ---- */
+ unsigned tq0 : 4;
+ unsigned tq1 : 4; /* 6 type qualifiers - tqPtr, etc. */
+ unsigned tq2 : 4;
+ unsigned tq3 : 4;
+ } TIR, *pTIR;
+#define cbTIR sizeof(TIR)
+#define tiNil ((pTIR)0)
+#define itqMax 6
+
+/*
+ * Relative symbol record
+ *
+ * If the rfd field is 4095, the index field indexes into the global symbol
+ * table.
+ */
+
+typedef struct {
+ unsigned rfd : 12; /* index into the file indirect table */
+ unsigned index : 20; /* index int sym/aux/iss tables */
+ } RNDXR, *pRNDXR;
+#define cbRNDXR sizeof(RNDXR)
+#define rndxNil ((pRNDXR)0)
+
+/* dense numbers or sometimes called block numbers are stored in this type,
+ * a rfd of 0xffffffff is an index into the global table.
+ */
+typedef struct {
+ unsigned long rfd; /* index into the file table */
+ unsigned long index; /* index int sym/aux/iss tables */
+ } DNR, *pDNR;
+#define cbDNR sizeof(DNR)
+#define dnNil ((pDNR)0)
+
+
+
+/*
+ * Auxillary information occurs only if needed.
+ * It ALWAYS occurs in this order when present.
+
+ isymMac used by stProc only
+ TIR type info
+ TIR additional TQ info (if first TIR was not enough)
+ rndx if (bt == btStruct,btUnion,btEnum,btSet,btRange,
+ btTypedef):
+ rsym.index == iaux for btSet or btRange
+ else rsym.index == isym
+ dimLow btRange, btSet
+ dimMac btRange, btSet
+ rndx0 As many as there are tq arrays
+ dimLow0
+ dimHigh0
+ ...
+ rndxMax-1
+ dimLowMax-1
+ dimHighMax-1
+ width in bits if (bit field), width in bits.
+ */
+#define cAuxMax (6 + (idimMax*3))
+
+/* a union of all possible info in the AUX universe */
+typedef union {
+ TIR ti; /* type information record */
+ RNDXR rndx; /* relative index into symbol table */
+ long dnLow; /* low dimension */
+ long dnHigh; /* high dimension */
+ long isym; /* symbol table index (end of proc) */
+ long iss; /* index into string space (not used) */
+ long width; /* width for non-default sized struc fields */
+ long count; /* count of ranges for variant arm */
+ } AUXU, *pAUXU;
+#define cbAUXU sizeof(AUXU)
+#define auxNil ((pAUXU)0)
+#define iauxNil -1
+
+
+/*
+ * Optimization symbols
+ *
+ * Optimization symbols contain some overlap information with the normal
+ * symbol table. In particular, the proc information
+ * is somewhat redundant but necessary to easily find the other information
+ * present.
+ *
+ * All of the offsets are relative to the beginning of the last otProc
+ */
+
+typedef struct {
+ unsigned ot: 8; /* optimization type */
+ unsigned value: 24; /* address where we are moving it to */
+ RNDXR rndx; /* points to a symbol or opt entry */
+ unsigned long offset; /* relative offset this occured */
+ } OPTR, *pOPTR;
+#define optNil ((pOPTR) 0)
+#define cbOPTR sizeof(OPTR)
+#define ioptNil -1
+
+/*
+ * File Indirect
+ *
+ * When a symbol is referenced across files the following procedure is used:
+ * 1) use the file index to get the File indirect entry.
+ * 2) use the file indirect entry to get the File descriptor.
+ * 3) add the sym index to the base of that file's sym table
+ *
+ */
+
+typedef long RFDT, *pRFDT;
+#define cbRFDT sizeof(RFDT)
+#define rfdNil -1
+
+/*
+ * The file indirect table in the mips loader is known as an array of FITs.
+ * This is done to keep the code in the loader readable in the area where
+ * these tables are merged. Note this is only a name change.
+ */
+typedef long FIT, *pFIT;
+#define cbFIT sizeof(FIT)
+#define ifiNil -1
+#define fiNil ((pFIT) 0)
+
+#ifdef _LANGUAGE_PASCAL
+#define ifdNil -1
+#define ilnNil -1
+#define ipdNil -1
+#define ilineNil -1
+#define isymNil -1
+#define indexNil 16#fffff
+#define issNil -1
+#define issNull 0
+#define itqMax 6
+#define iauxNil -1
+#define ioptNil -1
+#define rfdNil -1
+#define ifiNil -1
+#endif /* _LANGUAGE_PASCAL */
+
+
+/* Dense numbers
+ *
+ * Rather than use file index, symbol index pairs to represent symbols
+ * and globals, we use dense number so that they can be easily embeded
+ * in intermediate code and the programs that process them can
+ * use direct access tabls instead of hash table (which would be
+ * necesary otherwise because of the sparse name space caused by
+ * file index, symbol index pairs. Dense number are represented
+ * by RNDXRs.
+ */
+
+/*
+ * The following table defines the meaning of each SYM field as
+ * a function of the "st". (scD/B == scData OR scBss)
+ *
+ * Note: the value "isymMac" is used by symbols that have the concept
+ * of enclosing a block of related information. This value is the
+ * isym of the first symbol AFTER the end associated with the primary
+ * symbol. For example if a procedure was at isym==90 and had an
+ * isymMac==155, the associated end would be at isym==154, and the
+ * symbol at 155 would probably (although not necessarily) be the
+ * symbol for the next procedure. This allows rapid skipping over
+ * internal information of various sorts. "stEnd"s ALWAYS have the
+ * isym of the primary symbol that started the block.
+ *
+
+ST SC VALUE INDEX
+-------- ------ -------- ------
+stFile scText address isymMac
+stLabel scText address ---
+stGlobal scD/B address iaux
+stStatic scD/B address iaux
+stParam scAbs offset iaux
+stLocal scAbs offset iaux
+stProc scText address iaux (isymMac is first AUX)
+stStaticProc scText address iaux (isymMac is first AUX)
+
+stMember scNil ordinal --- (if member of enum)
+ (mipsread thinks the case below has a bit, not byte, offset.)
+stMember scNil byte offset iaux (if member of struct/union)
+stMember scBits bit offset iaux (bit field spec)
+
+stBlock scText address isymMac (text block)
+ (the code seems to think that rather than scNil, we see scInfo for
+ the two cases below.)
+stBlock scNil cb isymMac (struct/union member define)
+stBlock scNil cMembers isymMac (enum member define)
+
+ (New types added by SGI to simplify things:)
+stStruct scInfo cb isymMac (struct type define)
+stUnion scInfo cb isymMac (union type define)
+stEnum scInfo cMembers isymMac (enum type define)
+
+stEnd scText address isymStart
+stEnd scNil ------- isymStart (struct/union/enum)
+
+stTypedef scNil ------- iaux
+stRegReloc sc??? value old register number
+stForward sc??? new address isym to original symbol
+
+stConstant scInfo value --- (scalar)
+stConstant scInfo iss --- (complex, e.g. string)
+
+ *
+ */
+#endif
diff --git a/contrib/gdb/include/coff/symconst.h b/contrib/gdb/include/coff/symconst.h
new file mode 100644
index 0000000..f40eef2
--- /dev/null
+++ b/contrib/gdb/include/coff/symconst.h
@@ -0,0 +1,177 @@
+/* Declarations of constants for internal format of MIPS ECOFF symbols.
+ Originally contributed by MIPS Computer Systems and Third Eye Software.
+ Changes contributed by Cygnus Support are in the public domain.
+
+ This file is just aggregated with the files that make up the GNU
+ release; it is not considered part of GAS, GDB, or other GNU
+ programs. */
+
+/*
+ * |-----------------------------------------------------------|
+ * | Copyright (c) 1992, 1991, 1990 MIPS Computer Systems, Inc.|
+ * | MIPS Computer Systems, Inc. grants reproduction and use |
+ * | rights to all parties, PROVIDED that this comment is |
+ * | maintained in the copy. |
+ * |-----------------------------------------------------------|
+ */
+
+/* (C) Copyright 1984 by Third Eye Software, Inc.
+ *
+ * Third Eye Software, Inc. grants reproduction and use rights to
+ * all parties, PROVIDED that this comment is maintained in the copy.
+ *
+ * Third Eye makes no claims about the applicability of this
+ * symbol table to a particular use.
+ */
+
+/* glevels for field in FDR */
+#define GLEVEL_0 2
+#define GLEVEL_1 1
+#define GLEVEL_2 0 /* for upward compat reasons. */
+#define GLEVEL_3 3
+
+/* magic number fo symheader */
+#define magicSym 0x7009
+/* The Alpha uses this value instead, for some reason. */
+#define magicSym2 0x1992
+
+/* Language codes */
+#define langC 0
+#define langPascal 1
+#define langFortran 2
+#define langAssembler 3 /* one Assembley inst might map to many mach */
+#define langMachine 4
+#define langNil 5
+#define langAda 6
+#define langPl1 7
+#define langCobol 8
+#define langStdc 9 /* FIXME: Collides with SGI langCplusplus */
+#define langCplusplus 9 /* FIXME: Collides with langStdc */
+#define langCplusplusV2 10 /* SGI addition */
+#define langMax 11 /* maximun allowed 32 -- 5 bits */
+
+/* The following are value definitions for the fields in the SYMR */
+
+/*
+ * Storage Classes
+ */
+
+#define scNil 0
+#define scText 1 /* text symbol */
+#define scData 2 /* initialized data symbol */
+#define scBss 3 /* un-initialized data symbol */
+#define scRegister 4 /* value of symbol is register number */
+#define scAbs 5 /* value of symbol is absolute */
+#define scUndefined 6 /* who knows? */
+#define scCdbLocal 7 /* variable's value is IN se->va.?? */
+#define scBits 8 /* this is a bit field */
+#define scCdbSystem 9 /* variable's value is IN CDB's address space */
+#define scDbx 9 /* overlap dbx internal use */
+#define scRegImage 10 /* register value saved on stack */
+#define scInfo 11 /* symbol contains debugger information */
+#define scUserStruct 12 /* address in struct user for current process */
+#define scSData 13 /* load time only small data */
+#define scSBss 14 /* load time only small common */
+#define scRData 15 /* load time only read only data */
+#define scVar 16 /* Var parameter (fortran,pascal) */
+#define scCommon 17 /* common variable */
+#define scSCommon 18 /* small common */
+#define scVarRegister 19 /* Var parameter in a register */
+#define scVariant 20 /* Variant record */
+#define scSUndefined 21 /* small undefined(external) data */
+#define scInit 22 /* .init section symbol */
+#define scBasedVar 23 /* Fortran or PL/1 ptr based var */
+#define scXData 24 /* exception handling data */
+#define scPData 25 /* Procedure section */
+#define scFini 26 /* .fini section */
+#define scRConst 27 /* .rconst section */
+#define scMax 32
+
+
+/*
+ * Symbol Types
+ */
+
+#define stNil 0 /* Nuthin' special */
+#define stGlobal 1 /* external symbol */
+#define stStatic 2 /* static */
+#define stParam 3 /* procedure argument */
+#define stLocal 4 /* local variable */
+#define stLabel 5 /* label */
+#define stProc 6 /* " " Procedure */
+#define stBlock 7 /* beginnning of block */
+#define stEnd 8 /* end (of anything) */
+#define stMember 9 /* member (of anything - struct/union/enum */
+#define stTypedef 10 /* type definition */
+#define stFile 11 /* file name */
+#define stRegReloc 12 /* register relocation */
+#define stForward 13 /* forwarding address */
+#define stStaticProc 14 /* load time only static procs */
+#define stConstant 15 /* const */
+#define stStaParam 16 /* Fortran static parameters */
+ /* These new symbol types have been recently added to SGI machines. */
+#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 */
+#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 */
+#define stType 63 /* post-coersion SER */
+#define stMax 64
+
+/* definitions for fields in TIR */
+
+/* type qualifiers for ti.tq0 -> ti.(itqMax-1) */
+#define tqNil 0 /* bt is what you see */
+#define tqPtr 1 /* pointer */
+#define tqProc 2 /* procedure */
+#define tqArray 3 /* duh */
+#define tqFar 4 /* longer addressing - 8086/8 land */
+#define tqVol 5 /* volatile */
+#define tqConst 6 /* const */
+#define tqMax 8
+
+/* basic types as seen in ti.bt */
+#define btNil 0 /* undefined (also, enum members) */
+#define btAdr 1 /* address - integer same size as pointer */
+#define btChar 2 /* character */
+#define btUChar 3 /* unsigned character */
+#define btShort 4 /* short */
+#define btUShort 5 /* unsigned short */
+#define btInt 6 /* int */
+#define btUInt 7 /* unsigned int */
+#define btLong 8 /* long */
+#define btULong 9 /* unsigned long */
+#define btFloat 10 /* float (real) */
+#define btDouble 11 /* Double (real) */
+#define btStruct 12 /* Structure (Record) */
+#define btUnion 13 /* Union (variant) */
+#define btEnum 14 /* Enumerated */
+#define btTypedef 15 /* defined via a typedef, isymRef points */
+#define btRange 16 /* subrange of int */
+#define btSet 17 /* pascal sets */
+#define btComplex 18 /* fortran complex */
+#define btDComplex 19 /* fortran double complex */
+#define btIndirect 20 /* forward or unnamed typedef */
+#define btFixedDec 21 /* Fixed Decimal */
+#define btFloatDec 22 /* Float Decimal */
+#define btString 23 /* Varying Length Character String */
+#define btBit 24 /* Aligned Bit String */
+#define btPicture 25 /* Picture */
+#define btVoid 26 /* void */
+#define btLongLong 27 /* long long */
+#define btULongLong 28 /* unsigned long long */
+#define btMax 64
+
+#if (_MFG == _MIPS)
+/* optimization type codes */
+#define otNil 0
+#define otReg 1 /* move var to reg */
+#define otBlock 2 /* begin basic block */
+#define otProc 3 /* procedure */
+#define otInline 4 /* inline procedure */
+#define otEnd 5 /* whatever you started */
+#define otMax 6 /* KEEP UP TO DATE */
+#endif /* (_MFG == _MIPS) */
diff --git a/contrib/gdb/include/coff/w65.h b/contrib/gdb/include/coff/w65.h
new file mode 100644
index 0000000..c80b9fe
--- /dev/null
+++ b/contrib/gdb/include/coff/w65.h
@@ -0,0 +1,201 @@
+/*** coff information for WDC 65816 */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+
+#define W65MAGIC 0x6500
+
+
+#define W65BADMAG(x) (((x).f_magic!=W65MAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+
+#define AOUTHDRSZ (sizeof(AOUTHDR))
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[4]; /* line number */
+};
+
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) (ext->l_lnno));
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_32(abfd,val, (bfd_byte *) (ext->l_lnno));
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+/* The external reloc has an offset field, because some of the reloc
+ types on the w65 don't have room in the instruction for the entire
+ offset - eg the strange jump and high page addressing modes */
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_offset[4];
+ char r_type[2];
+ char r_stuff[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 16
+
+
+
+
diff --git a/contrib/gdb/include/coff/we32k.h b/contrib/gdb/include/coff/we32k.h
new file mode 100644
index 0000000..414c450
--- /dev/null
+++ b/contrib/gdb/include/coff/we32k.h
@@ -0,0 +1,206 @@
+/*** coff information for we32k */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+/* Bits for f_flags:
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (no unresolved external references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
+ */
+
+#define F_RELFLG (0x0001)
+#define F_EXEC (0x0002)
+#define F_LNNO (0x0004)
+#define F_LSYMS (0x0008)
+#define F_BM32B (0020000)
+#define F_BM32MAU (0040000)
+
+#define WE32KMAGIC 0x170 /* we32k sans transfer vector */
+#define FBOMAGIC 0x170 /* we32k sans transfer vector */
+#define MTVMAGIC 0x171 /* we32k with transfer vector */
+#define RBOMAGIC 0x172 /* reserved */
+#define WE32KBADMAG(x) (((x).f_magic != WE32KMAGIC) \
+ && ((x).f_magic != FBOMAGIC) \
+ && ((x).f_magic != RBOMAGIC) \
+ && ((x).f_magic != MTVMAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+#define _TV ".tv"
+#define _INIT ".init"
+#define _FINI ".fini"
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+#define N_BTMASK (0xf)
+#define N_TMASK (0x30)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+# define _ETEXT "etext"
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_type[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ sizeof(RELOC)
+
diff --git a/contrib/gdb/include/coff/z8k.h b/contrib/gdb/include/coff/z8k.h
new file mode 100644
index 0000000..4881795
--- /dev/null
+++ b/contrib/gdb/include/coff/z8k.h
@@ -0,0 +1,201 @@
+/*** coff information for Zilog Z800N */
+
+/********************** FILE HEADER **********************/
+
+struct external_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+
+/* Type of cpu is stored in flags */
+#define F_Z8001 0x1000
+#define F_Z8002 0x2000
+#define F_MACHMASK 0xf000
+
+#define Z8KMAGIC 0x8000
+
+#define Z8KBADMAG(x) (((x).f_magic!=Z8KMAGIC))
+
+#define FILHDR struct external_filehdr
+#define FILHSZ sizeof(FILHDR)
+
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry*/
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+AOUTHDR;
+
+
+#define AOUTHDRSZ (sizeof(AOUTHDR))
+#define AOUTSZ (sizeof(AOUTHDR))
+
+
+
+
+/********************** SECTION HEADER **********************/
+
+
+struct external_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries*/
+ char s_flags[4]; /* flags */
+};
+
+/*
+ * names of "special" sections
+ */
+#define _TEXT ".text"
+#define _DATA ".data"
+#define _BSS ".bss"
+
+
+#define SCNHDR struct external_scnhdr
+#define SCNHSZ sizeof(SCNHDR)
+
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+struct external_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[4]; /* line number */
+};
+
+#define GET_LINENO_LNNO(abfd, ext) bfd_h_get_32(abfd, (bfd_byte *) (ext->l_lnno));
+#define PUT_LINENO_LNNO(abfd,val, ext) bfd_h_put_32(abfd,val, (bfd_byte *) (ext->l_lnno));
+
+#define LINENO struct external_lineno
+#define LINESZ sizeof(LINENO)
+
+
+/********************** SYMBOLS **********************/
+
+#define E_SYMNMLEN 8 /* # characters in a symbol name */
+#define E_FILNMLEN 14 /* # characters in a file name */
+#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+struct external_syment
+{
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
+};
+
+
+
+#define N_BTMASK (017)
+#define N_TMASK (060)
+#define N_BTSHFT (4)
+#define N_TSHIFT (2)
+
+
+union external_auxent {
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+
+
+};
+
+#define SYMENT struct external_syment
+#define SYMESZ 18
+#define AUXENT union external_auxent
+#define AUXESZ 18
+
+
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+/* The external reloc has an offset field, because some of the reloc
+ types on the z8k don't have room in the instruction for the entire
+ offset - eg with segments */
+
+struct external_reloc {
+ char r_vaddr[4];
+ char r_symndx[4];
+ char r_offset[4];
+ char r_type[2];
+ char r_stuff[2];
+};
+
+
+#define RELOC struct external_reloc
+#define RELSZ 16
+
diff --git a/contrib/gdb/include/demangle.h b/contrib/gdb/include/demangle.h
new file mode 100644
index 0000000..d4d0a3f
--- /dev/null
+++ b/contrib/gdb/include/demangle.h
@@ -0,0 +1,108 @@
+/* Defs for interface to demanglers.
+ Copyright 1992, 1995, 1996 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
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+
+#if !defined (DEMANGLE_H)
+#define DEMANGLE_H
+
+#ifdef IN_GCC
+
+/* Add prototype support. */
+#ifndef PROTO
+#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
+#define PROTO(ARGS) ARGS
+#else
+#define PROTO(ARGS) ()
+#endif
+#endif
+
+#define PARAMS(ARGS) PROTO(ARGS)
+
+#ifdef __STDC__
+#define PTR void *
+#else
+#ifndef const
+#define const
+#endif
+#define PTR char *
+#endif
+
+#else /* ! IN_GCC */
+#include <ansidecl.h>
+#endif /* IN_GCC */
+
+/* Options passed to cplus_demangle (in 2nd parameter). */
+
+#define DMGL_NO_OPTS 0 /* For readability... */
+#define DMGL_PARAMS (1 << 0) /* Include function args */
+#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
+
+#define DMGL_AUTO (1 << 8)
+#define DMGL_GNU (1 << 9)
+#define DMGL_LUCID (1 << 10)
+#define DMGL_ARM (1 << 11)
+/* If none of these are set, use 'current_demangling_style' as the default. */
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM)
+
+/* Enumeration of possible demangling styles.
+
+ Lucid and ARM styles are still kept logically distinct, even though
+ they now both behave identically. The resulting style is actual the
+ union of both. I.E. either style recognizes both "__pt__" and "__rf__"
+ for operator "->", even though the first is lucid style and the second
+ is ARM style. (FIXME?) */
+
+extern enum demangling_styles
+{
+ unknown_demangling = 0,
+ auto_demangling = DMGL_AUTO,
+ gnu_demangling = DMGL_GNU,
+ lucid_demangling = DMGL_LUCID,
+ arm_demangling = DMGL_ARM
+} current_demangling_style;
+
+/* Define string names for the various demangling styles. */
+
+#define AUTO_DEMANGLING_STYLE_STRING "auto"
+#define GNU_DEMANGLING_STYLE_STRING "gnu"
+#define LUCID_DEMANGLING_STYLE_STRING "lucid"
+#define ARM_DEMANGLING_STYLE_STRING "arm"
+
+/* Some macros to test what demangling style is active. */
+
+#define CURRENT_DEMANGLING_STYLE current_demangling_style
+#define AUTO_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_AUTO)
+#define GNU_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU)
+#define LUCID_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_LUCID)
+#define ARM_DEMANGLING (CURRENT_DEMANGLING_STYLE & DMGL_ARM)
+
+extern char *
+cplus_demangle PARAMS ((const char *mangled, int options));
+
+extern int
+cplus_demangle_opname PARAMS ((const char *opname, char *result, int options));
+
+extern const char *
+cplus_mangle_opname PARAMS ((const char *opname, int options));
+
+/* Note: This sets global state. FIXME if you care about multi-threading. */
+
+extern void
+set_cplus_marker_for_demangling PARAMS ((int ch));
+
+#endif /* DEMANGLE_H */
diff --git a/contrib/gdb/include/dis-asm.h b/contrib/gdb/include/dis-asm.h
new file mode 100644
index 0000000..d70bd51
--- /dev/null
+++ b/contrib/gdb/include/dis-asm.h
@@ -0,0 +1,175 @@
+/* Interface between the opcode library and its callers.
+ Written by Cygnus Support, 1993.
+
+ The opcode library (libopcodes.a) provides instruction decoders for
+ a large variety of instruction sets, callable with an identical
+ interface, for making instruction-processing programs more independent
+ of the instruction set being processed. */
+
+#ifndef DIS_ASM_H
+#define DIS_ASM_H
+
+#include <stdio.h>
+#include "bfd.h"
+
+typedef int (*fprintf_ftype) PARAMS((FILE*, const char*, ...));
+
+enum dis_insn_type {
+ dis_noninsn, /* Not a valid instruction */
+ dis_nonbranch, /* Not a branch instruction */
+ dis_branch, /* Unconditional branch */
+ dis_condbranch, /* Conditional branch */
+ dis_jsr, /* Jump to subroutine */
+ dis_condjsr, /* Conditional jump to subroutine */
+ dis_dref, /* Data reference instruction */
+ dis_dref2 /* Two data references in instruction */
+};
+
+/* This struct is passed into the instruction decoding routine,
+ and is passed back out into each callback. The various fields are used
+ for conveying information from your main routine into your callbacks,
+ for passing information into the instruction decoders (such as the
+ addresses of the callback functions), or for passing information
+ back from the instruction decoders to their callers.
+
+ It must be initialized before it is first passed; this can be done
+ by hand, or using one of the initialization macros below. */
+
+typedef struct disassemble_info {
+ fprintf_ftype fprintf_func;
+ FILE *stream;
+ PTR application_data;
+
+ /* Target description. We could replace this with a pointer to the bfd,
+ but that would require one. There currently isn't any such requirement
+ so to avoid introducing one we record these explicitly. */
+ /* The bfd_arch value. */
+ enum bfd_architecture arch;
+ /* The bfd_mach value. */
+ unsigned long mach;
+ /* Endianness (for bi-endian cpus). Mono-endian cpus can ignore this. */
+ enum bfd_endian endian;
+
+ /* For use by the disassembler.
+ The top 16 bits are reserved for public use (and are documented here).
+ The bottom 16 bits are for the internal use of the disassembler. */
+ unsigned long flags;
+ PTR private_data;
+
+ /* Function used to get bytes to disassemble. MEMADDR is the
+ address of the stuff to be disassembled, MYADDR is the address to
+ put the bytes in, and LENGTH is the number of bytes to read.
+ INFO is a pointer to this struct.
+ Returns an errno value or 0 for success. */
+ int (*read_memory_func)
+ PARAMS ((bfd_vma memaddr, bfd_byte *myaddr, int length,
+ struct disassemble_info *info));
+
+ /* Function which should be called if we get an error that we can't
+ recover from. STATUS is the errno value from read_memory_func and
+ MEMADDR is the address that we were trying to read. INFO is a
+ pointer to this struct. */
+ void (*memory_error_func)
+ PARAMS ((int status, bfd_vma memaddr, struct disassemble_info *info));
+
+ /* Function called to print ADDR. */
+ void (*print_address_func)
+ PARAMS ((bfd_vma addr, struct disassemble_info *info));
+
+ /* These are for buffer_read_memory. */
+ bfd_byte *buffer;
+ bfd_vma buffer_vma;
+ int buffer_length;
+
+ /* Results from instruction decoders. Not all decoders yet support
+ this information. This info is set each time an instruction is
+ decoded, and is only valid for the last such instruction.
+
+ To determine whether this decoder supports this information, set
+ insn_info_valid to 0, decode an instruction, then check it. */
+
+ char insn_info_valid; /* Branch info has been set. */
+ char branch_delay_insns; /* How many sequential insn's will run before
+ a branch takes effect. (0 = normal) */
+ char data_size; /* Size of data reference in insn, in bytes */
+ enum dis_insn_type insn_type; /* Type of instruction */
+ bfd_vma target; /* Target address of branch or dref, if known;
+ zero if unknown. */
+ bfd_vma target2; /* Second target address for dref2 */
+
+} disassemble_info;
+
+
+/* Standard disassemblers. Disassemble one instruction at the given
+ target address. Return number of bytes processed. */
+typedef int (*disassembler_ftype)
+ PARAMS((bfd_vma, disassemble_info *));
+
+extern int print_insn_big_mips PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_mips PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i386 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_m68k PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_z8001 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_z8002 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8300 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8300h PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_big_arm PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_arm PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_sparc64 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_i960 PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_sh PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_shl 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*));
+extern int print_insn_w65 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
+ into a buffer before calling the instruction decoder. */
+
+/* Here is a function which callers may wish to use for read_memory_func.
+ It gets bytes from a buffer. */
+extern int buffer_read_memory
+ PARAMS ((bfd_vma, bfd_byte *, int, struct disassemble_info *));
+
+/* This function goes with buffer_read_memory.
+ It prints a message using info->fprintf_func and info->stream. */
+extern void perror_memory PARAMS ((int, bfd_vma, struct disassemble_info *));
+
+
+/* Just print the address in hex. This is included for completeness even
+ though both GDB and objdump provide their own (to print symbolic
+ addresses). */
+extern void generic_print_address
+ PARAMS ((bfd_vma, struct disassemble_info *));
+
+/* Macro to initialize a disassemble_info struct. This should be called
+ by all applications creating such a struct. */
+#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \
+ (INFO).fprintf_func = (FPRINTF_FUNC), \
+ (INFO).stream = (STREAM), \
+ (INFO).buffer = NULL, \
+ (INFO).buffer_vma = 0, \
+ (INFO).buffer_length = 0, \
+ (INFO).read_memory_func = buffer_read_memory, \
+ (INFO).memory_error_func = perror_memory, \
+ (INFO).print_address_func = generic_print_address, \
+ (INFO).arch = bfd_arch_unknown, \
+ (INFO).mach = 0, \
+ (INFO).endian = BFD_ENDIAN_UNKNOWN, \
+ (INFO).flags = 0, \
+ (INFO).insn_info_valid = 0
+
+#endif /* ! defined (DIS_ASM_H) */
diff --git a/contrib/gdb/include/elf/ChangeLog b/contrib/gdb/include/elf/ChangeLog
new file mode 100644
index 0000000..b56f9bb
--- /dev/null
+++ b/contrib/gdb/include/elf/ChangeLog
@@ -0,0 +1,195 @@
+Mon Feb 19 01:55:56 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc.h (R_SPARC_{PLT32,HIPLT22,LOPLT10,PCPLT32,PCPLT22,
+ PCPLT10,5,6}): Don't define ifdef SPARC64_OLD_RELOCS.
+
+Tue Feb 6 11:33:58 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc.h (enum sparc_elf_reloc_type): Define.
+
+Wed Jan 17 09:09:16 1996 Doug Evans <dje@canuck.cygnus.com>
+
+ * common.h: Define EM_SPARC32PLUS.
+ * sparc.h: New file.
+
+Thu Jan 11 16:27:34 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc.h (SHF_EXCLUDE, SHT_ORDERED): New fields from the abi.
+
+Thu Nov 30 16:47:18 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * internal.h (struct elf_segment_map): Add includes_filehdr and
+ includes_phdrs fields.
+
+Tue Nov 28 16:58:10 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * internal.h (struct elf_segment_map): Define.
+
+Tue Oct 31 15:19:36 1995 Fred Fish <fnf@cygnus.com>
+
+ * common.h, dwarf.h, external.h, hppa.h, internal.h,
+ mips.h, ppc.h: Protect against multiple inclusions.
+
+Thu Sep 21 13:51:58 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc.h (EF_PPC_RELOCATABLE_LIB): Add new flag bit.
+
+Fri Sep 1 15:32:17 1995 Kazumoto Kojima <kkojima@info.kanagawa-u.ac.jp>
+
+ * mips.h: Add some definitions used on Irix 5.
+
+Tue Jun 20 10:18:28 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa.h (CPU_PA_RISC1_0): Protect from redefinitions.
+ (CPU_PA_RISC1_1): Likewise.
+
+Wed Mar 8 18:14:37 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc.h: New file for PowerPC support.
+
+Tue Feb 14 13:59:13 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * common.h (EM_PPC): Use offical value of 20, not 17.
+ (EM_PPC_OLD): Define this to be the old value of EM_PPC.
+
+
+Tue Jan 24 09:40:59 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * common.h (EM_PPC): New macro, PowerPC machine id.
+
+Tue Jan 17 10:51:38 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * mips.h (SHT_MIPS_MSYM, SHT_MIPS_DWARF, SHT_MIPS_EVENTS): Define.
+
+
+Mon Oct 17 13:43:59 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * internal.h (Elf_Internal_Shdr): Remove rawdata and size fields.
+ Add bfd_section field.
+
+Tue May 24 16:11:50 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (Elf32_External_gptab): Define.
+
+Mon May 16 13:22:04 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * common.h (EM_HPPA): Delete.
+ (EM_PARISC): Add.
+ * hppa.h: New file.
+
+Mon May 9 13:27:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * common.h (SHN_LORESERVE): Rename from SHN_LORESERV.
+ (ELF32_R_TYPE, ELF32_R_INFO): Don't rely on size of unsigned char.
+ (ELF64_R_TYPE): Don't rely on size of unsigned long.
+
+Mon Apr 25 15:53:09 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * internal.h (Elf_Internal_Shdr): Use PTR, not void *.
+
+Fri Mar 11 00:34:59 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips.h (SHN_MIPS_TEXT, SHN_MIPS_DATA): Define.
+
+Sat Mar 5 14:08:54 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * internal.h: Remove Elf32_*, Elf64_* typedefs. These names
+ cause conflicts with system headers, e.g. link.h in gdb/solib.c.
+ Combine 32- and 64-bit versions of *_Internal_Dyn.
+ * common.h: Replace uses of Elf64_Word, Elf64_Xword typedefs
+ by their expansion.
+ * mips.h: Replace uses of Elf32_Word, Elf32_Sword, Elf32_Addr
+ typedefs by their expansion. Add DT_MIPS_RLD_MAP definition.
+
+Fri Feb 18 10:39:54 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * common.h (EM_CYGNUS_POWERPC): Define. This may be temporary,
+ depending upon how quickly I can find a real PowerPC ABI.
+
+Mon Feb 7 08:27:13 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * internal.h: Change HOST_64_BIT to BFD_HOST_64_BIT.
+
+Wed Feb 2 14:12:18 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * common.h: Add comments regarding value of EM_HPPA and how to
+ pick an unofficial value.
+
+Wed Nov 17 17:14:26 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (SHT_MIPS_OPTIONS): Define.
+
+Mon Nov 8 17:57:00 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h: Added some more MIPS ABI macro definitions.
+
+Wed Nov 3 22:07:17 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * common.h (EM_MIPS_RS4_BE): New macro.
+
+Tue Oct 12 07:28:18 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h: New file. MIPS ABI specific information.
+
+Mon Jun 21 13:13:43 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
+
+ * internal.h: Combined 32- and 64-bit versions of all structures
+ except *_Internal_Dyn. This will simply the assembler interface,
+ and some bfd code.
+
+Tue May 25 02:00:16 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * external.h, internal.h, common.h: Added 64-bit versions of some
+ structures and macros. Renamed old versions to put "32" in the
+ name. Some are unchanged.
+
+Thu Apr 29 12:12:20 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * common.h (EM_HPPA, NT_VERSION, STN_UNDEF, DT_*): New macros.
+ * external.h (Elf_External_Dyn): New type.
+
+ * internal.h (Elf_Intenral_Shdr): New field `size'.
+ (Elf_Internal_Dyn): New type.
+
+Tue Apr 20 16:03:45 1993 Fred Fish (fnf@cygnus.com)
+
+ * dwarf.h (LANG_CHILL): Change value to one randomly picked in
+ the user defined range, to reduce probability of collisions.
+
+Sun Nov 15 09:34:02 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarf.h (AT_src_coords): Whitespace change only.
+ * dwarf.h (AT_body_begin, AT_body_end, LANG_MODULA2):
+ Add from latest gcc.
+ * dwarf.h (LANG_CHILL): Add as GNU extension.
+
+Sat Aug 1 13:46:53 1992 Fred Fish (fnf@cygnus.com)
+
+ * dwarf.h: Replace with current version from gcc distribution.
+
+Fri Jun 19 19:05:09 1992 John Gilmore (gnu at cygnus.com)
+
+ * internal.h: Add real struct tags to all the Type_Defs, so they
+ can be used in prototypes where the Type_Defs are not known.
+
+Fri Apr 3 20:58:58 1992 Mark Eichin (eichin at cygnus.com)
+
+ * common.h: added ELF_R_{SYM,TYPE,INFO} for handling relocation
+ info
+ added EM_MIPS, and corrected value of EM_860 based on System V ABI
+ manual.
+
+ * external.h: added Elf_External_{Rel,Rela}.
+
+ * internal.h: added Elf_Internal_{Rel,Rela}.
+ added rawdata to Elf_Internal_Shdr.
+
+Sat Nov 30 20:43:59 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * common.h, dwarf.h, external.h, internal.h, ChangeLog; moved from
+ ../elf-<foo>
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/include/elf/common.h b/contrib/gdb/include/elf/common.h
new file mode 100644
index 0000000..c9e7474
--- /dev/null
+++ b/contrib/gdb/include/elf/common.h
@@ -0,0 +1,239 @@
+/* ELF support for BFD.
+ Copyright (C) 1991, 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, from information published
+ in "UNIX System V Release 4, Programmers Guide: ANSI C and
+ Programming Support Tools".
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is part of ELF support for BFD, and contains the portions
+ that are common to both the internal and external representations.
+ For example, ELFMAG0 is the byte 0x7F in both the internal (in-memory)
+ and external (in-file) representations. */
+
+#ifndef _ELF_COMMON_H
+#define _ELF_COMMON_H
+
+/* Fields in e_ident[] */
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7F /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+#define EI_CLASS 4 /* File class */
+#define ELFCLASSNONE 0 /* Invalid class */
+#define ELFCLASS32 1 /* 32-bit objects */
+#define ELFCLASS64 2 /* 64-bit objects */
+
+#define EI_DATA 5 /* Data encoding */
+#define ELFDATANONE 0 /* Invalid data encoding */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+#define ELFDATA2MSB 2 /* 2's complement, big endian */
+
+#define EI_VERSION 6 /* File version */
+
+#define EI_PAD 7 /* Start of padding bytes */
+
+
+/* Values for e_type, which identifies the object file type */
+
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* Relocatable file */
+#define ET_EXEC 2 /* Executable file */
+#define ET_DYN 3 /* Shared object file */
+#define ET_CORE 4 /* Core file */
+#define ET_LOPROC 0xFF00 /* Processor-specific */
+#define ET_HIPROC 0xFFFF /* Processor-specific */
+
+/* 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 (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 */
+
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+
+#define EM_PPC 20 /* PowerPC */
+
+/* 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
+
+/* Old version of PowerPC, this should be removed shortly. */
+#define EM_PPC_OLD 17
+
+
+/* Values for e_version */
+
+#define EV_NONE 0 /* Invalid ELF version */
+#define EV_CURRENT 1 /* Current version */
+
+/* Values for program header, p_type field */
+
+#define PT_NULL 0 /* Program header table entry unused */
+#define PT_LOAD 1 /* Loadable program segment */
+#define PT_DYNAMIC 2 /* Dynamic linking information */
+#define PT_INTERP 3 /* Program interpreter */
+#define PT_NOTE 4 /* Auxiliary information */
+#define PT_SHLIB 5 /* Reserved, unspecified semantics */
+#define PT_PHDR 6 /* Entry for header table itself */
+#define PT_LOPROC 0x70000000 /* Processor-specific */
+#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
+
+/* Program segment permissions, in program header p_flags field */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
+
+/* Values for section header, sh_type field */
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program specific (private) data */
+#define SHT_SYMTAB 2 /* Link editing symbol table */
+#define SHT_STRTAB 3 /* A string table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* A symbol hash table */
+#define SHT_DYNAMIC 6 /* Information for dynamic linking */
+#define SHT_NOTE 7 /* Information that marks file */
+#define SHT_NOBITS 8 /* Section occupies no space in file */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved, unspecified semantics */
+#define SHT_DYNSYM 11 /* Dynamic linking symbol table */
+#define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */
+#define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */
+#define SHT_LOUSER 0x80000000 /* Application-specific semantics */
+#define SHT_HIUSER 0x8FFFFFFF /* Application-specific semantics */
+
+/* Values for section header, sh_flags field */
+
+#define SHF_WRITE (1 << 0) /* Writable data during execution */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
+#define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */
+
+/* Values of note segment descriptor types for core files. */
+
+#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
+#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
+#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
+
+/* Values of note segment descriptor types for object files. */
+/* (Only for hppa right now. Should this be moved elsewhere?) */
+
+#define NT_VERSION 1 /* Contains a version string. */
+
+/* These three macros disassemble and assemble a symbol table st_info field,
+ which contains the symbol binding and symbol type. The STB_ and STT_
+ defines identify the binding and type. */
+
+#define ELF_ST_BIND(val) (((unsigned int)(val)) >> 4)
+#define ELF_ST_TYPE(val) ((val) & 0xF)
+#define ELF_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xF))
+
+#define STN_UNDEF 0 /* undefined symbol index */
+
+#define STB_LOCAL 0 /* Symbol not visible outside obj */
+#define STB_GLOBAL 1 /* Symbol visible outside obj */
+#define STB_WEAK 2 /* Like globals, lower precedence */
+#define STB_LOPROC 13 /* Application-specific semantics */
+#define STB_HIPROC 15 /* Application-specific semantics */
+
+#define STT_NOTYPE 0 /* Symbol type is unspecified */
+#define STT_OBJECT 1 /* Symbol is a data object */
+#define STT_FUNC 2 /* Symbol is a code object */
+#define STT_SECTION 3 /* Symbol associated with a section */
+#define STT_FILE 4 /* Symbol gives a file name */
+#define STT_LOPROC 13 /* Application-specific semantics */
+#define STT_HIPROC 15 /* Application-specific semantics */
+
+/* Special section indices, which may show up in st_shndx fields, among
+ other places. */
+
+#define SHN_UNDEF 0 /* Undefined section reference */
+#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 */
+#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
+#define SHN_HIRESERVE 0xFFFF /* End range of reserved indices */
+
+/* relocation info handling macros */
+
+#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) ((i) & 0xffffffff)
+#define ELF64_R_INFO(s,t) (((bfd_vma) (s) << 32) + (bfd_vma) (t))
+
+/* Dynamic section tags */
+
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_LOPROC 0x70000000
+#define DT_HIPROC 0x7fffffff
+
+#endif /* _ELF_COMMON_H */
diff --git a/contrib/gdb/include/elf/dwarf.h b/contrib/gdb/include/elf/dwarf.h
new file mode 100644
index 0000000..4333d5e
--- /dev/null
+++ b/contrib/gdb/include/elf/dwarf.h
@@ -0,0 +1,319 @@
+/* Declarations and definitions of codes relating to the DWARF symbolic
+ debugging information format.
+
+ Written by Ron Guilmette (rfg@ncd.com)
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file is derived from the DWARF specification (a public document)
+ Revision 1.0.1 (April 8, 1992) developed by the UNIX International
+ Programming Languages Special Interest Group (UI/PLSIG) and distributed
+ by UNIX International. Copies of this specification are available from
+ UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
+*/
+
+#ifndef _ELF_DWARF_H
+#define _ELF_DWARF_H
+
+/* Tag names and codes. */
+
+enum dwarf_tag {
+ TAG_padding = 0x0000,
+ TAG_array_type = 0x0001,
+ TAG_class_type = 0x0002,
+ TAG_entry_point = 0x0003,
+ TAG_enumeration_type = 0x0004,
+ TAG_formal_parameter = 0x0005,
+ TAG_global_subroutine = 0x0006,
+ TAG_global_variable = 0x0007,
+ /* 0x0008 -- reserved */
+ /* 0x0009 -- reserved */
+ TAG_label = 0x000a,
+ TAG_lexical_block = 0x000b,
+ TAG_local_variable = 0x000c,
+ TAG_member = 0x000d,
+ /* 0x000e -- reserved */
+ TAG_pointer_type = 0x000f,
+ TAG_reference_type = 0x0010,
+ TAG_compile_unit = 0x0011,
+ TAG_string_type = 0x0012,
+ TAG_structure_type = 0x0013,
+ TAG_subroutine = 0x0014,
+ TAG_subroutine_type = 0x0015,
+ TAG_typedef = 0x0016,
+ TAG_union_type = 0x0017,
+ TAG_unspecified_parameters = 0x0018,
+ TAG_variant = 0x0019,
+ TAG_common_block = 0x001a,
+ TAG_common_inclusion = 0x001b,
+ TAG_inheritance = 0x001c,
+ TAG_inlined_subroutine = 0x001d,
+ TAG_module = 0x001e,
+ TAG_ptr_to_member_type = 0x001f,
+ TAG_set_type = 0x0020,
+ TAG_subrange_type = 0x0021,
+ TAG_with_stmt = 0x0022,
+
+ /* GNU extensions */
+
+ TAG_format_label = 0x8000, /* for FORTRAN 77 and Fortran 90 */
+ TAG_namelist = 0x8001, /* For Fortran 90 */
+ TAG_function_template = 0x8002, /* for C++ */
+ TAG_class_template = 0x8003 /* for C++ */
+};
+
+#define TAG_lo_user 0x8000 /* implementation-defined range start */
+#define TAG_hi_user 0xffff /* implementation-defined range end */
+#define TAG_source_file TAG_compile_unit /* for backward compatibility */
+
+/* Form names and codes. */
+
+enum dwarf_form {
+ FORM_ADDR = 0x1,
+ FORM_REF = 0x2,
+ FORM_BLOCK2 = 0x3,
+ FORM_BLOCK4 = 0x4,
+ FORM_DATA2 = 0x5,
+ FORM_DATA4 = 0x6,
+ FORM_DATA8 = 0x7,
+ FORM_STRING = 0x8
+};
+
+/* Attribute names and codes. */
+
+enum dwarf_attribute {
+ AT_sibling = (0x0010|FORM_REF),
+ AT_location = (0x0020|FORM_BLOCK2),
+ AT_name = (0x0030|FORM_STRING),
+ AT_fund_type = (0x0050|FORM_DATA2),
+ AT_mod_fund_type = (0x0060|FORM_BLOCK2),
+ AT_user_def_type = (0x0070|FORM_REF),
+ AT_mod_u_d_type = (0x0080|FORM_BLOCK2),
+ AT_ordering = (0x0090|FORM_DATA2),
+ AT_subscr_data = (0x00a0|FORM_BLOCK2),
+ AT_byte_size = (0x00b0|FORM_DATA4),
+ AT_bit_offset = (0x00c0|FORM_DATA2),
+ AT_bit_size = (0x00d0|FORM_DATA4),
+ /* (0x00e0|FORM_xxxx) -- reserved */
+ AT_element_list = (0x00f0|FORM_BLOCK4),
+ AT_stmt_list = (0x0100|FORM_DATA4),
+ AT_low_pc = (0x0110|FORM_ADDR),
+ AT_high_pc = (0x0120|FORM_ADDR),
+ AT_language = (0x0130|FORM_DATA4),
+ AT_member = (0x0140|FORM_REF),
+ AT_discr = (0x0150|FORM_REF),
+ AT_discr_value = (0x0160|FORM_BLOCK2),
+ /* (0x0170|FORM_xxxx) -- reserved */
+ /* (0x0180|FORM_xxxx) -- reserved */
+ AT_string_length = (0x0190|FORM_BLOCK2),
+ AT_common_reference = (0x01a0|FORM_REF),
+ AT_comp_dir = (0x01b0|FORM_STRING),
+ AT_const_value_string = (0x01c0|FORM_STRING),
+ AT_const_value_data2 = (0x01c0|FORM_DATA2),
+ AT_const_value_data4 = (0x01c0|FORM_DATA4),
+ AT_const_value_data8 = (0x01c0|FORM_DATA8),
+ AT_const_value_block2 = (0x01c0|FORM_BLOCK2),
+ AT_const_value_block4 = (0x01c0|FORM_BLOCK4),
+ AT_containing_type = (0x01d0|FORM_REF),
+ AT_default_value_addr = (0x01e0|FORM_ADDR),
+ AT_default_value_data2 = (0x01e0|FORM_DATA2),
+ AT_default_value_data4 = (0x01e0|FORM_DATA4),
+ AT_default_value_data8 = (0x01e0|FORM_DATA8),
+ AT_default_value_string = (0x01e0|FORM_STRING),
+ AT_friends = (0x01f0|FORM_BLOCK2),
+ AT_inline = (0x0200|FORM_STRING),
+ AT_is_optional = (0x0210|FORM_STRING),
+ AT_lower_bound_ref = (0x0220|FORM_REF),
+ AT_lower_bound_data2 = (0x0220|FORM_DATA2),
+ AT_lower_bound_data4 = (0x0220|FORM_DATA4),
+ AT_lower_bound_data8 = (0x0220|FORM_DATA8),
+ AT_private = (0x0240|FORM_STRING),
+ AT_producer = (0x0250|FORM_STRING),
+ AT_program = (0x0230|FORM_STRING),
+ AT_protected = (0x0260|FORM_STRING),
+ AT_prototyped = (0x0270|FORM_STRING),
+ AT_public = (0x0280|FORM_STRING),
+ AT_pure_virtual = (0x0290|FORM_STRING),
+ AT_return_addr = (0x02a0|FORM_BLOCK2),
+ AT_abstract_origin = (0x02b0|FORM_REF),
+ AT_start_scope = (0x02c0|FORM_DATA4),
+ AT_stride_size = (0x02e0|FORM_DATA4),
+ AT_upper_bound_ref = (0x02f0|FORM_REF),
+ AT_upper_bound_data2 = (0x02f0|FORM_DATA2),
+ AT_upper_bound_data4 = (0x02f0|FORM_DATA4),
+ AT_upper_bound_data8 = (0x02f0|FORM_DATA8),
+ AT_virtual = (0x0300|FORM_STRING),
+
+ /* GNU extensions. */
+
+ AT_sf_names = (0x8000|FORM_DATA4),
+ AT_src_info = (0x8010|FORM_DATA4),
+ AT_mac_info = (0x8020|FORM_DATA4),
+ AT_src_coords = (0x8030|FORM_DATA4),
+ AT_body_begin = (0x8040|FORM_ADDR),
+ AT_body_end = (0x8050|FORM_ADDR)
+};
+
+#define AT_lo_user 0x8000 /* implementation-defined range start */
+#define AT_hi_user 0xffff /* implementation-defined range end */
+
+/* Location atom names and codes. */
+
+enum dwarf_location_atom {
+ OP_REG = 0x01,
+ OP_BASEREG = 0x02,
+ OP_ADDR = 0x03,
+ OP_CONST = 0x04,
+ OP_DEREF2 = 0x05,
+ OP_DEREF4 = 0x06,
+ OP_ADD = 0x07
+};
+
+#define OP_LO_USER 0x80 /* implementation-defined range start */
+#define OP_HI_USER 0xff /* implementation-defined range end */
+
+/* Fundamental type names and codes. */
+
+enum dwarf_fundamental_type {
+ FT_char = 0x0001,
+ FT_signed_char = 0x0002,
+ FT_unsigned_char = 0x0003,
+ FT_short = 0x0004,
+ FT_signed_short = 0x0005,
+ FT_unsigned_short = 0x0006,
+ FT_integer = 0x0007,
+ FT_signed_integer = 0x0008,
+ FT_unsigned_integer = 0x0009,
+ FT_long = 0x000a,
+ FT_signed_long = 0x000b,
+ FT_unsigned_long = 0x000c,
+ FT_pointer = 0x000d, /* an alias for (void *) */
+ FT_float = 0x000e,
+ FT_dbl_prec_float = 0x000f,
+ FT_ext_prec_float = 0x0010, /* breaks "classic" svr4 SDB */
+ FT_complex = 0x0011, /* breaks "classic" svr4 SDB */
+ FT_dbl_prec_complex = 0x0012, /* breaks "classic" svr4 SDB */
+ /* 0x0013 -- reserved */
+ FT_void = 0x0014,
+ FT_boolean = 0x0015, /* breaks "classic" svr4 SDB */
+ FT_ext_prec_complex = 0x0016, /* breaks "classic" svr4 SDB */
+ FT_label = 0x0017,
+
+ /* GNU extensions
+ The low order byte must indicate the size (in bytes) for the type.
+ All of these types will probably break "classic" svr4 SDB */
+
+ FT_long_long = 0x8008,
+ FT_signed_long_long = 0x8108,
+ FT_unsigned_long_long = 0x8208,
+
+ FT_int8 = 0x9001,
+ FT_signed_int8 = 0x9101,
+ FT_unsigned_int8 = 0x9201,
+ FT_int16 = 0x9302,
+ FT_signed_int16 = 0x9402,
+ FT_unsigned_int16 = 0x9502,
+ FT_int32 = 0x9604,
+ FT_signed_int32 = 0x9704,
+ FT_unsigned_int32 = 0x9804,
+ FT_int64 = 0x9908,
+ FT_signed_int64 = 0x9a08,
+ FT_unsigned_int64 = 0x9b08,
+
+ FT_real32 = 0xa004,
+ FT_real64 = 0xa108,
+ FT_real96 = 0xa20c,
+ FT_real128 = 0xa310
+};
+
+#define FT_lo_user 0x8000 /* implementation-defined range start */
+#define FT_hi_user 0xffff /* implementation defined range end */
+
+/* Type modifier names and codes. */
+
+enum dwarf_type_modifier {
+ MOD_pointer_to = 0x01,
+ MOD_reference_to = 0x02,
+ MOD_const = 0x03,
+ MOD_volatile = 0x04
+};
+
+#define MOD_lo_user 0x80 /* implementation-defined range start */
+#define MOD_hi_user 0xff /* implementation-defined range end */
+
+/* Array ordering names and codes. */
+
+enum dwarf_array_dim_ordering {
+ ORD_row_major = 0,
+ ORD_col_major = 1
+};
+
+/* Array subscript format names and codes. */
+
+enum dwarf_subscr_data_formats {
+ FMT_FT_C_C = 0x0,
+ FMT_FT_C_X = 0x1,
+ FMT_FT_X_C = 0x2,
+ FMT_FT_X_X = 0x3,
+ FMT_UT_C_C = 0x4,
+ FMT_UT_C_X = 0x5,
+ FMT_UT_X_C = 0x6,
+ FMT_UT_X_X = 0x7,
+ FMT_ET = 0x8
+};
+
+/* Derived from above for ease of use. */
+
+#define FMT_CODE(_FUNDAMENTAL_TYPE_P, _UB_CONST_P, _LB_CONST_P) \
+ (((_FUNDAMENTAL_TYPE_P) ? 0 : 4) \
+ | ((_UB_CONST_P) ? 0 : 2) \
+ | ((_LB_CONST_P) ? 0 : 1))
+
+/* Source language names and codes. */
+
+enum dwarf_source_language {
+ LANG_C89 = 0x00000001,
+ LANG_C = 0x00000002,
+ LANG_ADA83 = 0x00000003,
+ LANG_C_PLUS_PLUS = 0x00000004,
+ LANG_COBOL74 = 0x00000005,
+ LANG_COBOL85 = 0x00000006,
+ LANG_FORTRAN77 = 0x00000007,
+ LANG_FORTRAN90 = 0x00000008,
+ LANG_PASCAL83 = 0x00000009,
+ LANG_MODULA2 = 0x0000000a,
+
+ /* GNU extensions */
+
+ LANG_CHILL = 0x00009af3 /* random value for GNU Chill */
+};
+
+#define LANG_lo_user 0x00008000 /* implementation-defined range start */
+#define LANG_hi_user 0x0000ffff /* implementation-defined range end */
+
+/* Names and codes for GNU "macinfo" extension. */
+
+enum dwarf_macinfo_record_type {
+ MACINFO_start = 's',
+ MACINFO_resume = 'r',
+ MACINFO_define = 'd',
+ MACINFO_undef = 'u'
+};
+
+#endif /* _ELF_DWARF_H */
diff --git a/contrib/gdb/include/elf/external.h b/contrib/gdb/include/elf/external.h
new file mode 100644
index 0000000..e6618cb
--- /dev/null
+++ b/contrib/gdb/include/elf/external.h
@@ -0,0 +1,195 @@
+/* ELF support for BFD.
+ Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ Cygnus Support, from information published
+ in "UNIX System V Release 4, Programmers Guide: ANSI C and
+ Programming Support Tools".
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is part of ELF support for BFD, and contains the portions
+ that describe how ELF is represented externally by the BFD library.
+ I.E. it describes the in-file representation of ELF. It requires
+ the elf-common.h file which contains the portions that are common to
+ both the internal and external representations. */
+
+/* The 64-bit stuff is kind of random. Perhaps someone will publish a
+ spec someday. */
+
+#ifndef _ELF_EXTERNAL_H
+#define _ELF_EXTERNAL_H
+
+/* ELF Header (32-bit implementations) */
+
+typedef struct {
+ unsigned char e_ident[16]; /* ELF "magic number" */
+ unsigned char e_type[2]; /* Identifies object file type */
+ unsigned char e_machine[2]; /* Specifies required architecture */
+ unsigned char e_version[4]; /* Identifies object file version */
+ unsigned char e_entry[4]; /* Entry point virtual address */
+ unsigned char e_phoff[4]; /* Program header table file offset */
+ unsigned char e_shoff[4]; /* Section header table file offset */
+ unsigned char e_flags[4]; /* Processor-specific flags */
+ unsigned char e_ehsize[2]; /* ELF header size in bytes */
+ unsigned char e_phentsize[2]; /* Program header table entry size */
+ unsigned char e_phnum[2]; /* Program header table entry count */
+ unsigned char e_shentsize[2]; /* Section header table entry size */
+ unsigned char e_shnum[2]; /* Section header table entry count */
+ unsigned char e_shstrndx[2]; /* Section header string table index */
+} Elf32_External_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[16]; /* ELF "magic number" */
+ unsigned char e_type[2]; /* Identifies object file type */
+ unsigned char e_machine[2]; /* Specifies required architecture */
+ unsigned char e_version[4]; /* Identifies object file version */
+ unsigned char e_entry[8]; /* Entry point virtual address */
+ unsigned char e_phoff[8]; /* Program header table file offset */
+ unsigned char e_shoff[8]; /* Section header table file offset */
+ unsigned char e_flags[4]; /* Processor-specific flags */
+ unsigned char e_ehsize[2]; /* ELF header size in bytes */
+ unsigned char e_phentsize[2]; /* Program header table entry size */
+ unsigned char e_phnum[2]; /* Program header table entry count */
+ unsigned char e_shentsize[2]; /* Section header table entry size */
+ unsigned char e_shnum[2]; /* Section header table entry count */
+ unsigned char e_shstrndx[2]; /* Section header string table index */
+} Elf64_External_Ehdr;
+
+/* Program header */
+
+typedef struct {
+ unsigned char p_type[4]; /* Identifies program segment type */
+ unsigned char p_offset[4]; /* Segment file offset */
+ unsigned char p_vaddr[4]; /* Segment virtual address */
+ unsigned char p_paddr[4]; /* Segment physical address */
+ unsigned char p_filesz[4]; /* Segment size in file */
+ unsigned char p_memsz[4]; /* Segment size in memory */
+ unsigned char p_flags[4]; /* Segment flags */
+ unsigned char p_align[4]; /* Segment alignment, file & memory */
+} Elf32_External_Phdr;
+
+typedef struct {
+ unsigned char p_type[4]; /* Identifies program segment type */
+ unsigned char p_flags[4]; /* Segment flags */
+ unsigned char p_offset[8]; /* Segment file offset */
+ unsigned char p_vaddr[8]; /* Segment virtual address */
+ unsigned char p_paddr[8]; /* Segment physical address */
+ unsigned char p_filesz[8]; /* Segment size in file */
+ unsigned char p_memsz[8]; /* Segment size in memory */
+ unsigned char p_align[8]; /* Segment alignment, file & memory */
+} Elf64_External_Phdr;
+
+/* Section header */
+
+typedef struct {
+ unsigned char sh_name[4]; /* Section name, index in string tbl */
+ unsigned char sh_type[4]; /* Type of section */
+ unsigned char sh_flags[4]; /* Miscellaneous section attributes */
+ unsigned char sh_addr[4]; /* Section virtual addr at execution */
+ unsigned char sh_offset[4]; /* Section file offset */
+ unsigned char sh_size[4]; /* Size of section in bytes */
+ unsigned char sh_link[4]; /* Index of another section */
+ unsigned char sh_info[4]; /* Additional section information */
+ unsigned char sh_addralign[4]; /* Section alignment */
+ unsigned char sh_entsize[4]; /* Entry size if section holds table */
+} Elf32_External_Shdr;
+
+typedef struct {
+ unsigned char sh_name[4]; /* Section name, index in string tbl */
+ unsigned char sh_type[4]; /* Type of section */
+ unsigned char sh_flags[8]; /* Miscellaneous section attributes */
+ unsigned char sh_addr[8]; /* Section virtual addr at execution */
+ unsigned char sh_offset[8]; /* Section file offset */
+ unsigned char sh_size[8]; /* Size of section in bytes */
+ unsigned char sh_link[4]; /* Index of another section */
+ unsigned char sh_info[4]; /* Additional section information */
+ unsigned char sh_addralign[8]; /* Section alignment */
+ unsigned char sh_entsize[8]; /* Entry size if section holds table */
+} Elf64_External_Shdr;
+
+/* Symbol table entry */
+
+typedef struct {
+ unsigned char st_name[4]; /* Symbol name, index in string tbl */
+ unsigned char st_value[4]; /* 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 */
+} Elf32_External_Sym;
+
+typedef struct {
+ unsigned char st_name[4]; /* Symbol name, index in string tbl */
+ 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 */
+ unsigned char st_value[8]; /* Value of the symbol */
+ unsigned char st_size[8]; /* Associated symbol size */
+} Elf64_External_Sym;
+
+/* Note segments */
+
+typedef struct {
+ unsigned char namesz[4]; /* Size of entry's owner string */
+ unsigned char descsz[4]; /* Size of the note descriptor */
+ unsigned char type[4]; /* Interpretation of the descriptor */
+ char name[1]; /* Start of the name+desc data */
+} Elf_External_Note;
+
+/* Relocation Entries */
+typedef struct {
+ unsigned char r_offset[4]; /* Location at which to apply the action */
+ unsigned char r_info[4]; /* index and type of relocation */
+} Elf32_External_Rel;
+
+typedef struct {
+ unsigned char r_offset[4]; /* Location at which to apply the action */
+ unsigned char r_info[4]; /* index and type of relocation */
+ unsigned char r_addend[4]; /* Constant addend used to compute value */
+} Elf32_External_Rela;
+
+typedef struct {
+ unsigned char r_offset[8]; /* Location at which to apply the action */
+ unsigned char r_info[8]; /* index and type of relocation */
+} Elf64_External_Rel;
+
+typedef struct {
+ unsigned char r_offset[8]; /* Location at which to apply the action */
+ unsigned char r_info[8]; /* index and type of relocation */
+ unsigned char r_addend[8]; /* Constant addend used to compute value */
+} Elf64_External_Rela;
+
+/* dynamic section structure */
+
+typedef struct {
+ unsigned char d_tag[4]; /* entry tag value */
+ union {
+ unsigned char d_val[4];
+ unsigned char d_ptr[4];
+ } d_un;
+} Elf32_External_Dyn;
+
+typedef struct {
+ unsigned char d_tag[8]; /* entry tag value */
+ union {
+ unsigned char d_val[8];
+ unsigned char d_ptr[8];
+ } d_un;
+} Elf64_External_Dyn;
+
+#endif /* _ELF_EXTERNAL_H */
diff --git a/contrib/gdb/include/elf/hppa.h b/contrib/gdb/include/elf/hppa.h
new file mode 100644
index 0000000..c34077f
--- /dev/null
+++ b/contrib/gdb/include/elf/hppa.h
@@ -0,0 +1,94 @@
+/* HPPA ELF support for BFD.
+ Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file holds definitions specific to the HPPA ELF ABI. Note
+ that most of this is not actually implemented by BFD. */
+
+#ifndef _ELF_HPPA_H
+#define _ELF_HPPA_H
+
+/* Processor specific flags for the ELF header e_flags field. */
+
+/* Target processor IDs to be placed in the low 16 bits of the flags
+ field. Note these names are shared with SOM, and therefore do not
+ follow ELF naming conventions. */
+
+/* PA 1.0 big endian. */
+#ifndef CPU_PA_RISC1_0
+#define CPU_PA_RISC1_0 0x0000020b
+#endif
+
+/* PA 1.1 big endian. */
+#ifndef CPU_PA_RISC1_1
+#define CPU_PA_RISC1_1 0x00000210
+#endif
+
+/* PA 1.0 little endian (unsupported) is 0x0000028b. */
+/* PA 1.1 little endian (unsupported) is 0x00000290. */
+
+/* Trap null address dereferences. */
+#define ELF_PARISC_TRAPNIL 0x00010000
+
+/* .PARISC.archext section is present. */
+#define EF_PARISC_EXT 0x00020000
+
+/* Processor specific section types. */
+
+/* Holds the global offset table, a table of pointers to external
+ data. */
+#define SHT_PARISC_GOT SHT_LOPROC+0
+
+/* Nonloadable section containing information in architecture
+ extensions used by the code. */
+#define SHT_PARISC_ARCH SHT_LOPROC+1
+
+/* Section in which $global$ is defined. */
+#define SHT_PARISC_GLOBAL SHT_LOPROC+2
+
+/* Section holding millicode routines (mul, div, rem, dyncall, etc. */
+#define SHT_PARISC_MILLI SHT_LOPROC+3
+
+/* Section holding unwind information for use by debuggers. */
+#define SHT_PARISC_UNWIND SHT_LOPROC+4
+
+/* Section holding the procedure linkage table. */
+#define SHT_PARISC_PLT SHT_LOPROC+5
+
+/* Short initialized and uninitialized data. */
+#define SHT_PARISC_SDATA SHT_LOPROC+6
+#define SHT_PARISC_SBSS SHT_LOPROC+7
+
+/* Optional section holding argument location/relocation info. */
+#define SHT_PARISC_SYMEXTN SHT_LOPROC+8
+
+/* Option section for linker stubs. */
+#define SHT_PARISC_STUBS SHT_LOPROC+9
+
+/* Processor specific section flags. */
+
+/* This section is near the global data pointer and thus allows short
+ addressing modes to be used. */
+#define SHF_PARISC_SHORT 0x20000000
+
+/* Processor specific symbol types. */
+
+/* Millicode function entry point. */
+#define STT_PARISC_MILLICODE STT_LOPROC+0
+
+#endif /* _ELF_HPPA_H */
diff --git a/contrib/gdb/include/elf/internal.h b/contrib/gdb/include/elf/internal.h
new file mode 100644
index 0000000..6375e89
--- /dev/null
+++ b/contrib/gdb/include/elf/internal.h
@@ -0,0 +1,207 @@
+/* ELF support for BFD.
+ 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
+ Programming Support Tools".
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is part of ELF support for BFD, and contains the portions
+ that describe how ELF is represented internally in the BFD library.
+ I.E. it describes the in-memory representation of ELF. It requires
+ the elf-common.h file which contains the portions that are common to
+ both the internal and external representations. */
+
+
+/* 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
+ packing under various circumstances. */
+
+#ifndef _ELF_INTERNAL_H
+#define _ELF_INTERNAL_H
+
+/* ELF Header */
+
+#define EI_NIDENT 16 /* Size of e_ident[] */
+
+typedef struct elf_internal_ehdr {
+ unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
+ bfd_vma e_entry; /* Entry point virtual address */
+ bfd_signed_vma e_phoff; /* Program header table file offset */
+ bfd_signed_vma e_shoff; /* Section header table file offset */
+ unsigned long e_version; /* Identifies object file version */
+ unsigned long e_flags; /* Processor-specific flags */
+ unsigned short e_type; /* Identifies object file type */
+ unsigned short e_machine; /* Specifies required architecture */
+ unsigned short e_ehsize; /* ELF header size in bytes */
+ unsigned short e_phentsize; /* Program header table entry size */
+ unsigned short e_phnum; /* Program header table entry count */
+ unsigned short e_shentsize; /* Section header table entry size */
+ unsigned short e_shnum; /* Section header table entry count */
+ unsigned short e_shstrndx; /* Section header string table index */
+} Elf_Internal_Ehdr;
+
+#define elf32_internal_ehdr elf_internal_ehdr
+#define Elf32_Internal_Ehdr Elf_Internal_Ehdr
+#define elf64_internal_ehdr elf_internal_ehdr
+#define Elf64_Internal_Ehdr Elf_Internal_Ehdr
+
+/* Program header */
+
+struct elf_internal_phdr {
+ unsigned long p_type; /* Identifies program segment type */
+ unsigned long p_flags; /* Segment flags */
+ bfd_vma p_offset; /* Segment file offset */
+ bfd_vma p_vaddr; /* Segment virtual address */
+ bfd_vma p_paddr; /* Segment physical address */
+ bfd_vma p_filesz; /* Segment size in file */
+ bfd_vma p_memsz; /* Segment size in memory */
+ bfd_vma p_align; /* Segment alignment, file & memory */
+};
+
+typedef struct elf_internal_phdr Elf_Internal_Phdr;
+#define elf32_internal_phdr elf_internal_phdr
+#define Elf32_Internal_Phdr Elf_Internal_Phdr
+#define elf64_internal_phdr elf_internal_phdr
+#define Elf64_Internal_Phdr Elf_Internal_Phdr
+
+/* Section header */
+
+typedef struct elf_internal_shdr {
+ unsigned int sh_name; /* Section name, index in string tbl */
+ unsigned int sh_type; /* Type of section */
+ bfd_vma sh_flags; /* Miscellaneous section attributes */
+ bfd_vma sh_addr; /* Section virtual addr at execution */
+ bfd_size_type sh_size; /* Size of section in bytes */
+ bfd_size_type sh_entsize; /* Entry size if section holds table */
+ unsigned long sh_link; /* Index of another section */
+ unsigned long sh_info; /* Additional section information */
+ file_ptr sh_offset; /* Section file offset */
+ unsigned int sh_addralign; /* Section alignment */
+
+ /* The internal rep also has some cached info associated with it. */
+ asection * bfd_section; /* Associated BFD section. */
+ PTR contents; /* Section contents. */
+} Elf_Internal_Shdr;
+
+#define elf32_internal_shdr elf_internal_shdr
+#define Elf32_Internal_Shdr Elf_Internal_Shdr
+#define elf64_internal_shdr elf_internal_shdr
+#define Elf64_Internal_Shdr Elf_Internal_Shdr
+
+/* Symbol table entry */
+
+struct elf_internal_sym {
+ bfd_vma st_value; /* Value of the symbol */
+ bfd_vma st_size; /* Associated symbol size */
+ unsigned long st_name; /* Symbol name, index in string tbl */
+ unsigned char st_info; /* Type and binding attributes */
+ unsigned char st_other; /* No defined meaning, 0 */
+ unsigned short st_shndx; /* Associated section index */
+};
+
+typedef struct elf_internal_sym Elf_Internal_Sym;
+
+#define elf32_internal_sym elf_internal_sym
+#define elf64_internal_sym elf_internal_sym
+#define Elf32_Internal_Sym Elf_Internal_Sym
+#define Elf64_Internal_Sym Elf_Internal_Sym
+
+/* Note segments */
+
+typedef struct elf_internal_note {
+ unsigned long namesz; /* Size of entry's owner string */
+ unsigned long descsz; /* Size of the note descriptor */
+ unsigned long type; /* Interpretation of the descriptor */
+ char name[1]; /* Start of the name+desc data */
+} Elf_Internal_Note;
+#define Elf32_Internal_Note Elf_Internal_Note
+#define elf32_internal_note elf_internal_note
+
+/* Relocation Entries */
+
+typedef struct elf_internal_rel {
+ bfd_vma r_offset; /* Location at which to apply the action */
+ /* This needs to support 64-bit values in elf64. */
+ bfd_vma r_info; /* index and type of relocation */
+} Elf_Internal_Rel;
+
+#define elf32_internal_rel elf_internal_rel
+#define Elf32_Internal_Rel Elf_Internal_Rel
+#define elf64_internal_rel elf_internal_rel
+#define Elf64_Internal_Rel Elf_Internal_Rel
+
+typedef struct elf_internal_rela {
+ bfd_vma r_offset; /* Location at which to apply the action */
+ bfd_vma r_info; /* Index and Type of relocation */
+ bfd_signed_vma r_addend; /* Constant addend used to compute value */
+} Elf_Internal_Rela;
+
+#define elf32_internal_rela elf_internal_rela
+#define elf64_internal_rela elf_internal_rela
+#define Elf32_Internal_Rela Elf_Internal_Rela
+#define Elf64_Internal_Rela Elf_Internal_Rela
+
+/* dynamic section structure */
+
+typedef struct elf_internal_dyn {
+ /* This needs to support 64-bit values in elf64. */
+ bfd_vma d_tag; /* entry tag value */
+ union {
+ /* This needs to support 64-bit values in elf64. */
+ bfd_vma d_val;
+ bfd_vma d_ptr;
+ } d_un;
+} Elf_Internal_Dyn;
+
+#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
+
+/* This structure is used to describe how sections should be assigned
+ to program segments. */
+
+struct elf_segment_map
+{
+ /* Next program segment. */
+ struct elf_segment_map *next;
+ /* Program segment type. */
+ unsigned long p_type;
+ /* Program segment flags. */
+ unsigned long p_flags;
+ /* Program segment physical address. */
+ bfd_vma p_paddr;
+ /* Whether the p_flags field is valid; if not, the flags are based
+ on the section flags. */
+ unsigned int p_flags_valid : 1;
+ /* Whether the p_paddr field is valid; if not, the physical address
+ is based on the section lma values. */
+ unsigned int p_paddr_valid : 1;
+ /* Whether this segment includes the file header. */
+ unsigned int includes_filehdr : 1;
+ /* Whether this segment includes the program headers. */
+ unsigned int includes_phdrs : 1;
+ /* Number of sections (may be 0). */
+ unsigned int count;
+ /* Sections. Actual number of elements is in count field. */
+ asection *sections[1];
+};
+
+#endif /* _ELF_INTERNAL_H */
diff --git a/contrib/gdb/include/elf/mips.h b/contrib/gdb/include/elf/mips.h
new file mode 100644
index 0000000..f0d8cd7
--- /dev/null
+++ b/contrib/gdb/include/elf/mips.h
@@ -0,0 +1,298 @@
+/* MIPS ELF support for BFD.
+ Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+
+ By Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>, from
+ information in the System V Application Binary Interface, MIPS
+ Processor Supplement.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file holds definitions specific to the MIPS ELF ABI. Note
+ that most of this is not actually implemented by BFD. */
+
+#ifndef _ELF_MIPS_H
+#define _ELF_MIPS_H
+
+/* Processor specific flags for the ELF header e_flags field. */
+
+/* At least one .noreorder directive appears in the source. */
+#define EF_MIPS_NOREORDER 0x00000001
+
+/* File contains position independent code. */
+#define EF_MIPS_PIC 0x00000002
+
+/* Code in file uses the standard calling sequence for calling
+ position independent code. */
+#define EF_MIPS_CPIC 0x00000004
+
+/* Four bit MIPS architecture field. */
+#define EF_MIPS_ARCH 0xf0000000
+
+/* -mips1 code. */
+#define E_MIPS_ARCH_1 0x00000000
+
+/* -mips2 code. */
+#define E_MIPS_ARCH_2 0x10000000
+
+/* -mips3 code. */
+#define E_MIPS_ARCH_3 0x20000000
+
+/* Processor specific section indices. These sections do not actually
+ exist. Symbols with a st_shndx field corresponding to one of these
+ values have a special meaning. */
+
+/* Defined and allocated common symbol. Value is virtual address. If
+ relocated, alignment must be preserved. */
+#define SHN_MIPS_ACOMMON 0xff00
+
+/* Defined and allocated text symbol. Value is virtual address.
+ Occur in the dynamic symbol table of Alpha OSF/1 and Irix 5 executables. */
+#define SHN_MIPS_TEXT 0xff01
+
+/* Defined and allocated data symbol. Value is virtual address.
+ Occur in the dynamic symbol table of Alpha OSF/1 and Irix 5 executables. */
+#define SHN_MIPS_DATA 0xff02
+
+/* Small common symbol. */
+#define SHN_MIPS_SCOMMON 0xff03
+
+/* Small undefined symbol. */
+#define SHN_MIPS_SUNDEFINED 0xff04
+
+/* Processor specific section types. */
+
+/* Section contains the set of dynamic shared objects used when
+ statically linking. */
+#define SHT_MIPS_LIBLIST 0x70000000
+
+/* I'm not sure what this is, but it's used on Irix 5. */
+#define SHT_MIPS_MSYM 0x70000001
+
+/* Section contains list of symbols whose definitions conflict with
+ symbols defined in shared objects. */
+#define SHT_MIPS_CONFLICT 0x70000002
+
+/* Section contains the global pointer table. */
+#define SHT_MIPS_GPTAB 0x70000003
+
+/* Section contains microcode information. The exact format is
+ unspecified. */
+#define SHT_MIPS_UCODE 0x70000004
+
+/* Section contains some sort of debugging information. The exact
+ format is unspecified. It's probably ECOFF symbols. */
+#define SHT_MIPS_DEBUG 0x70000005
+
+/* Section contains register usage information. */
+#define SHT_MIPS_REGINFO 0x70000006
+
+/* Section contains miscellaneous options (used on Irix). */
+#define SHT_MIPS_OPTIONS 0x7000000d
+
+/* DWARF debugging section (used on Irix 6). */
+#define SHT_MIPS_DWARF 0x7000001e
+
+/* Events section. This appears on Irix 6. I don't know what it
+ means. */
+#define SHT_MIPS_EVENTS 0x70000021
+
+/* A section of type SHT_MIPS_LIBLIST contains an array of the
+ following structure. The sh_link field is the section index of the
+ string table. The sh_info field is the number of entries in the
+ section. */
+typedef struct
+{
+ /* String table index for name of shared object. */
+ unsigned long l_name;
+ /* Time stamp. */
+ unsigned long l_time_stamp;
+ /* Checksum of symbol names and common sizes. */
+ unsigned long l_checksum;
+ /* String table index for version. */
+ unsigned long l_version;
+ /* Flags. */
+ unsigned long l_flags;
+} Elf32_Lib;
+
+/* The l_flags field of an Elf32_Lib structure may contain the
+ following flags. */
+
+/* Require an exact match at runtime. */
+#define LL_EXACT_MATCH 0x00000001
+
+/* Ignore version incompatibilities at runtime. */
+#define LL_IGNORE_INT_VER 0x00000002
+
+/* A section of type SHT_MIPS_CONFLICT is an array of indices into the
+ .dynsym section. Each element has the following type. */
+typedef unsigned long Elf32_Conflict;
+
+/* A section of type SHT_MIPS_GPTAB contains information about how
+ much GP space would be required for different -G arguments. This
+ information is only used so that the linker can provide informative
+ suggestions as to the best -G value to use. The sh_info field is
+ the index of the section for which this information applies. The
+ contents of the section are an array of the following union. The
+ first element uses the gt_header field. The remaining elements use
+ the gt_entry field. */
+typedef union
+{
+ struct
+ {
+ /* -G value actually used for this object file. */
+ unsigned long gt_current_g_value;
+ /* Unused. */
+ unsigned long gt_unused;
+ } gt_header;
+ struct
+ {
+ /* If this -G argument has been used... */
+ unsigned long gt_g_value;
+ /* ...this many GP section bytes would be required. */
+ unsigned long gt_bytes;
+ } gt_entry;
+} Elf32_gptab;
+
+/* The external version of Elf32_gptab. */
+
+typedef union
+{
+ struct
+ {
+ unsigned char gt_current_g_value[4];
+ unsigned char gt_unused[4];
+ } gt_header;
+ struct
+ {
+ unsigned char gt_g_value[4];
+ unsigned char gt_bytes[4];
+ } gt_entry;
+} Elf32_External_gptab;
+
+/* A section of type SHT_MIPS_REGINFO contains the following
+ structure. */
+typedef struct
+{
+ /* Mask of general purpose registers used. */
+ unsigned long ri_gprmask;
+ /* Mask of co-processor registers used. */
+ unsigned long ri_cprmask[4];
+ /* GP register value for this object file. */
+ long ri_gp_value;
+} Elf32_RegInfo;
+
+/* The external version of the Elf_RegInfo structure. */
+typedef struct
+{
+ unsigned char ri_gprmask[4];
+ unsigned char ri_cprmask[4][4];
+ unsigned char ri_gp_value[4];
+} Elf32_External_RegInfo;
+
+/* MIPS ELF .reginfo swapping routines. */
+extern void bfd_mips_elf32_swap_reginfo_in
+ PARAMS ((bfd *, const Elf32_External_RegInfo *, Elf32_RegInfo *));
+extern void bfd_mips_elf32_swap_reginfo_out
+ PARAMS ((bfd *, const Elf32_RegInfo *, Elf32_External_RegInfo *));
+
+/* Processor specific section flags. */
+
+/* This section must be in the global data area. */
+#define SHF_MIPS_GPREL 0x10000000
+
+/* Processor specific program header types. */
+
+/* Register usage information. Identifies one .reginfo section. */
+#define PT_MIPS_REGINFO 0x70000000
+
+/* Runtime procedure table. */
+#define PT_MIPS_RTPROC 0x70000001
+
+/* Processor specific dynamic array tags. */
+
+/* 32 bit version number for runtime linker interface. */
+#define DT_MIPS_RLD_VERSION 0x70000001
+
+/* Time stamp. */
+#define DT_MIPS_TIME_STAMP 0x70000002
+
+/* Checksum of external strings and common sizes. */
+#define DT_MIPS_ICHECKSUM 0x70000003
+
+/* Index of version string in string table. */
+#define DT_MIPS_IVERSION 0x70000004
+
+/* 32 bits of flags. */
+#define DT_MIPS_FLAGS 0x70000005
+
+/* Base address of the segment. */
+#define DT_MIPS_BASE_ADDRESS 0x70000006
+
+/* Address of .conflict section. */
+#define DT_MIPS_CONFLICT 0x70000008
+
+/* Address of .liblist section. */
+#define DT_MIPS_LIBLIST 0x70000009
+
+/* Number of local global offset table entries. */
+#define DT_MIPS_LOCAL_GOTNO 0x7000000a
+
+/* Number of entries in the .conflict section. */
+#define DT_MIPS_CONFLICTNO 0x7000000b
+
+/* Number of entries in the .liblist section. */
+#define DT_MIPS_LIBLISTNO 0x70000010
+
+/* Number of entries in the .dynsym section. */
+#define DT_MIPS_SYMTABNO 0x70000011
+
+/* Index of first external dynamic symbol not referenced locally. */
+#define DT_MIPS_UNREFEXTNO 0x70000012
+
+/* Index of first dynamic symbol in global offset table. */
+#define DT_MIPS_GOTSYM 0x70000013
+
+/* Number of page table entries in global offset table. */
+#define DT_MIPS_HIPAGENO 0x70000014
+
+/* Address of run time loader map, used for debugging. */
+#define DT_MIPS_RLD_MAP 0x70000016
+
+/* Flags which may appear in a DT_MIPS_FLAGS entry. */
+
+/* No flags. */
+#define RHF_NONE 0x00000000
+
+/* Uses shortcut pointers. */
+#define RHF_QUICKSTART 0x00000001
+
+/* Hash size is not a power of two. */
+#define RHF_NOTPOT 0x00000002
+
+/* Ignore LD_LIBRARY_PATH. */
+#define RHS_NO_LIBRARY_REPLACEMENT \
+ 0x00000004
+
+/* Special values for the st_other field in the symbol table. These
+ are used in an Irix 5 dynamic symbol table. */
+
+#define STO_DEFAULT 0x00
+#define STO_INTERNAL 0x01
+#define STO_HIDDEN 0x02
+#define STO_PROTECTED 0x03
+
+#endif /* _ELF_MIPS_H */
diff --git a/contrib/gdb/include/elf/ppc.h b/contrib/gdb/include/elf/ppc.h
new file mode 100644
index 0000000..1da118d
--- /dev/null
+++ b/contrib/gdb/include/elf/ppc.h
@@ -0,0 +1,54 @@
+/* PPC ELF support for BFD.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+ By Michael Meissner, Cygnus Support, <meissner@cygnus.com>, from information
+ in the System V Application Binary Interface, PowerPC Processor Supplement
+ and the PowerPC Embedded Application Binary Interface (eabi).
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file holds definitions specific to the PPC ELF ABI. Note
+ that most of this is not actually implemented by BFD. */
+
+#ifndef _ELF_PPC_H
+#define _ELF_PPC_H
+
+/* Processor specific flags for the ELF header e_flags field. */
+
+#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
+
+ /* CYGNUS local bits below */
+#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag */
+#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib flag */
+
+/* Processor specific section headers, sh_type field */
+
+#define SHT_ORDERED SHT_HIPROC /* Link editor is to sort the \
+ entries in this section \
+ based on the address \
+ specified in the associated \
+ symbol table entry. */
+
+/* Processor specific section flags, sh_flags field */
+
+#define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude \
+ this section from executable \
+ and shared objects that it \
+ builds when those objects \
+ are not to be furhter \
+ relocated. */
+#endif /* _ELF_PPC_H */
diff --git a/contrib/gdb/include/elf/sparc.h b/contrib/gdb/include/elf/sparc.h
new file mode 100644
index 0000000..84408e3
--- /dev/null
+++ b/contrib/gdb/include/elf/sparc.h
@@ -0,0 +1,73 @@
+/* SPARC ELF support for BFD.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+
+ By Doug Evans, Cygnus Support, <dje@cygnus.com>.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _ELF_SPARC_H
+#define _ELF_SPARC_H
+
+/* Processor specific flags for the ELF header e_flags field. */
+
+/* These are defined by Sun. */
+
+#define EF_SPARC_32PLUS_MASK 0xffff00 /* bits indicating V8+ type */
+#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
+
+/* Relocation types. */
+
+enum elf_sparc_reloc_type {
+ R_SPARC_NONE = 0,
+ R_SPARC_8, R_SPARC_16, R_SPARC_32,
+ R_SPARC_DISP8, R_SPARC_DISP16, R_SPARC_DISP32,
+ R_SPARC_WDISP30, R_SPARC_WDISP22,
+ R_SPARC_HI22, R_SPARC_22,
+ R_SPARC_13, R_SPARC_LO10,
+ R_SPARC_GOT10, R_SPARC_GOT13, R_SPARC_GOT22,
+ R_SPARC_PC10, R_SPARC_PC22,
+ R_SPARC_WPLT30,
+ R_SPARC_COPY,
+ R_SPARC_GLOB_DAT, R_SPARC_JMP_SLOT,
+ R_SPARC_RELATIVE,
+ R_SPARC_UA32,
+
+ /* ??? These 6 relocs are new but not currently used. For binary
+ compatility in the sparc64-elf toolchain, we leave them out.
+ A non-binary upward compatible change is expected for sparc64-elf. */
+#ifndef SPARC64_OLD_RELOCS
+ /* ??? New relocs on the UltraSPARC. Not sure what they're for yet. */
+ R_SPARC_PLT32, R_SPARC_HIPLT22, R_SPARC_LOPLT10,
+ R_SPARC_PCPLT32, R_SPARC_PCPLT22, R_SPARC_PCPLT10,
+#endif
+
+ /* v9 relocs */
+ R_SPARC_10, R_SPARC_11, R_SPARC_64,
+ R_SPARC_OLO10, R_SPARC_HH22, R_SPARC_HM10, R_SPARC_LM22,
+ R_SPARC_PC_HH22, R_SPARC_PC_HM10, R_SPARC_PC_LM22,
+ R_SPARC_WDISP16, R_SPARC_WDISP19,
+ R_SPARC_GLOB_JMP,
+ R_SPARC_7,
+#ifndef SPARC64_OLD_RELOCS
+ R_SPARC_5, R_SPARC_6,
+#endif
+
+ R_SPARC_max
+};
+
+#endif /* _ELF_SPARC_H */
diff --git a/contrib/gdb/include/floatformat.h b/contrib/gdb/include/floatformat.h
new file mode 100644
index 0000000..01e3dcb
--- /dev/null
+++ b/contrib/gdb/include/floatformat.h
@@ -0,0 +1,88 @@
+/* IEEE floating point support declarations, for GDB, the GNU Debugger.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined (FLOATFORMAT_H)
+#define FLOATFORMAT_H 1
+
+#include "ansidecl.h"
+
+/* A floatformat consists of a sign bit, an exponent and a mantissa. Once the
+ bytes are concatenated according to the byteorder flag, then each of those
+ fields is contiguous. We number the bits with 0 being the most significant
+ (i.e. BITS_BIG_ENDIAN type numbering), and specify which bits each field
+ contains with the *_start and *_len fields. */
+
+enum floatformat_byteorders { floatformat_little, floatformat_big };
+
+enum floatformat_intbit { floatformat_intbit_yes, floatformat_intbit_no };
+
+struct floatformat
+{
+ enum floatformat_byteorders byteorder;
+ unsigned int totalsize; /* Total size of number in bits */
+
+ /* Sign bit is always one bit long. 1 means negative, 0 means positive. */
+ unsigned int sign_start;
+
+ unsigned int exp_start;
+ unsigned int exp_len;
+ /* Amount added to "true" exponent. 0x3fff for many IEEE extendeds. */
+ unsigned int exp_bias;
+ /* Exponent value which indicates NaN. This is the actual value stored in
+ the float, not adjusted by the exp_bias. This usually consists of all
+ one bits. */
+ unsigned int exp_nan;
+
+ unsigned int man_start;
+ unsigned int man_len;
+
+ /* Is the integer bit explicit or implicit? */
+ enum floatformat_intbit intbit;
+};
+
+/* floatformats for IEEE single and double, big and little endian. */
+
+extern const struct floatformat floatformat_ieee_single_big;
+extern const struct floatformat floatformat_ieee_single_little;
+extern const struct floatformat floatformat_ieee_double_big;
+extern const struct floatformat floatformat_ieee_double_little;
+
+/* floatformats for various extendeds. */
+
+extern const struct floatformat floatformat_i387_ext;
+extern const struct floatformat floatformat_m68881_ext;
+extern const struct floatformat floatformat_i960_ext;
+extern const struct floatformat floatformat_m88110_ext;
+extern const struct floatformat floatformat_arm_ext;
+
+/* Convert from FMT to a double.
+ FROM is the address of the extended float.
+ Store the double in *TO. */
+
+extern void
+floatformat_to_double PARAMS ((const struct floatformat *, char *, double *));
+
+/* The converse: convert the double *FROM to FMT
+ and store where TO points. */
+
+extern void
+floatformat_from_double PARAMS ((const struct floatformat *,
+ double *, char *));
+
+#endif /* defined (FLOATFORMAT_H) */
diff --git a/contrib/gdb/include/fopen-bin.h b/contrib/gdb/include/fopen-bin.h
new file mode 100644
index 0000000..b868f63
--- /dev/null
+++ b/contrib/gdb/include/fopen-bin.h
@@ -0,0 +1,27 @@
+/* Macros for the 'type' part of an fopen, freopen or fdopen.
+
+ <Read|Write>[Update]<Binary file|text file>
+
+ This version is for "binary" systems, where text and binary files are
+ different. An example is Mess-Dose. Many Unix systems could also
+ cope with a "b" in the string, indicating binary files, but some reject this
+ (and thereby don't conform to ANSI C, but what else is new?).
+
+ This file is designed for inclusion by host-dependent .h files. No
+ user application should include it directly, since that would make
+ the application unable to be configured for both "same" and "binary"
+ variant systems. */
+
+#define FOPEN_RB "rb"
+#define FOPEN_WB "wb"
+#define FOPEN_AB "ab"
+#define FOPEN_RUB "r+b"
+#define FOPEN_WUB "w+b"
+#define FOPEN_AUB "a+b"
+
+#define FOPEN_RT "r"
+#define FOPEN_WT "w"
+#define FOPEN_AT "a"
+#define FOPEN_RUT "r+"
+#define FOPEN_WUT "w+"
+#define FOPEN_AUT "a+"
diff --git a/contrib/gdb/include/fopen-same.h b/contrib/gdb/include/fopen-same.h
new file mode 100644
index 0000000..0f37529
--- /dev/null
+++ b/contrib/gdb/include/fopen-same.h
@@ -0,0 +1,27 @@
+/* Macros for the 'type' part of an fopen, freopen or fdopen.
+
+ <Read|Write>[Update]<Binary file|text file>
+
+ This version is for "same" systems, where text and binary files are
+ the same. An example is Unix. Many Unix systems could also add a
+ "b" to the string, indicating binary files, but some reject this
+ (and thereby don't conform to ANSI C, but what else is new?).
+
+ This file is designed for inclusion by host-dependent .h files. No
+ user application should include it directly, since that would make
+ the application unable to be configured for both "same" and "binary"
+ variant systems. */
+
+#define FOPEN_RB "r"
+#define FOPEN_WB "w"
+#define FOPEN_AB "a"
+#define FOPEN_RUB "r+"
+#define FOPEN_WUB "w+"
+#define FOPEN_AUB "a+"
+
+#define FOPEN_RT "r"
+#define FOPEN_WT "w"
+#define FOPEN_AT "a"
+#define FOPEN_RUT "r+"
+#define FOPEN_WUT "w+"
+#define FOPEN_AUT "a+"
diff --git a/contrib/gdb/include/gdbm.h b/contrib/gdb/include/gdbm.h
new file mode 100644
index 0000000..3ebc26d
--- /dev/null
+++ b/contrib/gdb/include/gdbm.h
@@ -0,0 +1,91 @@
+/* GNU DBM - DataBase Manager include file
+ Copyright 1989, 1991 Free Software Foundation, Inc.
+ Written by Philip A. Nelson.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* You may contact the author by:
+ e-mail: phil@wwu.edu
+ us-mail: Philip A. Nelson
+ Computer Science Department
+ Western Washington University
+ Bellingham, WA 98226
+ phone: (206) 676-3035
+
+*************************************************************************/
+
+/* Parameters to gdbm_open for READERS, WRITERS, and WRITERS who
+ can create the database. */
+#define GDBM_READER 0
+#define GDBM_WRITER 1
+#define GDBM_WRCREAT 2
+#define GDBM_NEWDB 3
+
+/* Parameters to gdbm_store for simple insertion or replacement. */
+#define GDBM_INSERT 0
+#define GDBM_REPLACE 1
+
+
+/* The data and key structure. This structure is defined for compatibility. */
+typedef struct {
+ char *dptr;
+ int dsize;
+ } datum;
+
+
+/* The file information header. This is good enough for most applications. */
+typedef struct {int dummy[10];} *GDBM_FILE;
+
+
+/* These are the routines! */
+
+extern GDBM_FILE gdbm_open ();
+
+extern void gdbm_close ();
+
+extern datum gdbm_fetch ();
+
+extern int gdbm_store ();
+
+extern int gdbm_delete ();
+
+extern datum gdbm_firstkey ();
+
+extern datum gdbm_nextkey ();
+
+extern int gdbm_reorganize ();
+
+
+/* gdbm sends back the following error codes in the variable gdbm_errno. */
+typedef enum { NO_ERROR,
+ MALLOC_ERROR,
+ BLOCK_SIZE_ERROR,
+ FILE_OPEN_ERROR,
+ FILE_WRITE_ERROR,
+ FILE_SEEK_ERROR,
+ FILE_READ_ERROR,
+ BAD_MAGIC_NUMBER,
+ EMPTY_DATABASE,
+ CANT_BE_READER,
+ CANT_BE_WRITER,
+ READER_CANT_RECOVER,
+ READER_CANT_DELETE,
+ READER_CANT_STORE,
+ READER_CANT_REORGANIZE,
+ UNKNOWN_UPDATE,
+ ITEM_NOT_FOUND,
+ REORGANIZE_FAILED,
+ CANNOT_REPLACE}
+ gdbm_error;
diff --git a/contrib/gdb/include/getopt.h b/contrib/gdb/include/getopt.h
new file mode 100644
index 0000000..abf9153
--- /dev/null
+++ b/contrib/gdb/include/getopt.h
@@ -0,0 +1,129 @@
+/* Declarations for getopt.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993 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 Free Software Foundation; either version 2, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _GETOPT_H
+#define _GETOPT_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+#if __STDC__
+ const char *name;
+#else
+ char *name;
+#endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+#define no_argument 0
+#define required_argument 1
+#define optional_argument 2
+
+#if __STDC__
+#if defined(__GNU_LIBRARY__)
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+#else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+#endif /* not __GNU_LIBRARY__ */
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+#else /* not __STDC__ */
+extern int getopt ();
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+#endif /* not __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GETOPT_H */
diff --git a/contrib/gdb/include/hp-symtab.h b/contrib/gdb/include/hp-symtab.h
new file mode 100644
index 0000000..051c4c6
--- /dev/null
+++ b/contrib/gdb/include/hp-symtab.h
@@ -0,0 +1,983 @@
+/* Definitions and structures for reading debug symbols from the
+ native HP C compiler.
+
+ Written by the Center for Software Science at the University of Utah
+ and by Cygnus Support.
+
+ Copyright 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef HP_SYMTAB_INCLUDED
+#define HP_SYMTAB_INCLUDED
+
+/* General information:
+
+ This header file defines and describes only the basic data structures
+ necessary to read debug symbols produced by the HP C compiler using the
+ SOM object file format. Definitions and structures used by other compilers
+ for other languages or object file formats may be missing.
+ (For a full description of the debug format, ftp hpux-symtab.h from
+ jaguar.cs.utah.edu:/dist).
+
+
+ Debug symbols are contained entirely within an unloadable space called
+ $DEBUG$. $DEBUG$ contains several subspaces which group related
+ debug symbols.
+
+ $GNTT$ contains information for global variables, types and contants.
+
+ $LNTT$ contains information for procedures (including nesting), scoping
+ information, local variables, types, and constants.
+
+ $SLT$ contains source line information so that code addresses may be
+ mapped to source lines.
+
+ $VT$ contains various strings and constants for named objects (variables,
+ typedefs, functions, etc). Strings are stored as null-terminated character
+ lists. Constants always begin on word boundaries. The first byte of
+ the VT must be zero (a null string).
+
+ $XT$ is not currently used by GDB.
+
+ Many structures within the subspaces point to other structures within
+ the same subspace, or to structures within a different subspace. These
+ pointers are represented as a structure index from the beginning of
+ the appropriate subspace. */
+
+/* Used to describe where a constant is stored. */
+enum location_type
+{
+ LOCATION_IMMEDIATE,
+ LOCATION_PTR,
+ LOCATION_VT,
+};
+
+/* Languages supported by this debug format. Within the data structures
+ this type is limited to 4 bits for a maximum of 16 languages. */
+enum hp_language
+{
+ HP_LANGUAGE_UNKNOWN,
+ HP_LANGUAGE_C,
+ HP_LANGUAGE_F77,
+ HP_LANGUAGE_PASCAL,
+ HP_LANGUAGE_COBOL,
+ HP_LANGUAGE_BASIC,
+ HP_LANGUAGE_ADA,
+ HP_LANGUAGE_CPLUSPLUS,
+};
+
+
+/* Basic data types available in this debug format. Within the data
+ structures this type is limited to 5 bits for a maximum of 32 basic
+ data types. */
+enum hp_type
+{
+ HP_TYPE_UNDEFINED,
+ HP_TYPE_BOOLEAN,
+ HP_TYPE_CHAR,
+ HP_TYPE_INT,
+ HP_TYPE_UNSIGNED_INT,
+ HP_TYPE_REAL,
+ HP_TYPE_COMPLEX,
+ HP_TYPE_STRING200,
+ HP_TYPE_LONGSTRING200,
+ HP_TYPE_TEXT,
+ HP_TYPE_FLABEL,
+ HP_TYPE_FTN_STRING_SPEC,
+ HP_TYPE_MOD_STRING_SPEC,
+ HP_TYPE_PACKED_DECIMAL,
+ HP_TYPE_REAL_3000,
+ HP_TYPE_MOD_STRING_3000,
+ HP_TYPE_ANYPOINTER,
+ HP_TYPE_GLOBAL_ANYPOINTER,
+ HP_TYPE_LOCAL_ANYPOINTER,
+ HP_TYPE_COMPLEXS3000,
+ HP_TYPE_FTN_STRING_S300_COMPAT,
+ HP_TYPE_FTN_STRING_VAX_COMPAT,
+ HP_TYPE_BOOLEAN_S300_COMPAT,
+ HP_TYPE_BOOLEAN_VAX_COMPAT,
+ HP_TYPE_WIDE_CHAR,
+ HP_TYPE_LONG,
+ HP_TYPE_UNSIGNED_LONG,
+ HP_TYPE_DOUBLE,
+ HP_TYPE_TEMPLATE_ARG,
+};
+
+/* An immediate name and type table entry.
+
+ extension and immediate will always be one.
+ global will always be zero.
+ hp_type is the basic type this entry describes.
+ bitlength is the length in bits for the basic type. */
+struct dnttp_immediate
+{
+ unsigned int extension: 1;
+ unsigned int immediate: 1;
+ unsigned int global: 1;
+ unsigned int type: 5;
+ unsigned int bitlength: 24;
+};
+
+/* A nonimmediate name and type table entry.
+
+ extension will always be one.
+ immediate will always be zero.
+ if global is zero, this entry points into the LNTT
+ if global is one, this entry points into the GNTT
+ index is the index within the GNTT or LNTT for this entry. */
+struct dnttp_nonimmediate
+{
+ unsigned int extension: 1;
+ unsigned int immediate: 1;
+ unsigned int global: 1;
+ unsigned int index: 29;
+};
+
+/* A pointer to an entry in the GNTT and LNTT tables. It has two
+ forms depending on the type being described.
+
+ The immediate form is used for simple entries and is one
+ word.
+
+ The nonimmediate form is used for complex entries and contains
+ an index into the LNTT or GNTT which describes the entire type.
+
+ If a dnttpointer is -1, then it is a NIL entry. */
+
+#define DNTTNIL (-1)
+typedef union dnttpointer
+{
+ struct dnttp_immediate dntti;
+ struct dnttp_nonimmediate dnttp;
+ int word;
+} dnttpointer;
+
+/* An index into the source line table. As with dnttpointers, a sltpointer
+ of -1 indicates a NIL entry. */
+#define SLTNIL (-1)
+typedef int sltpointer;
+
+/* Unsigned byte offset into the VT. */
+typedef unsigned int vtpointer;
+
+/* A DNTT entry (used within the GNTT and LNTT).
+
+ DNTT entries are variable sized objects, but are always a multiple
+ of 3 words (we call each group of 3 words a "block").
+
+ The first bit in each block is an extension bit. This bit is zero
+ for the first block of a DNTT entry. If the entry requires more
+ than one block, then this bit is set to one in all blocks after
+ the first one. */
+
+/* Each DNTT entry describes a particular debug symbol (beginning of
+ a source file, a function, variables, structures, etc.
+
+ The type of the DNTT entry is stored in the "kind" field within the
+ DNTT entry itself. */
+
+enum dntt_entry_type
+{
+ DNTT_TYPE_NIL = -1,
+ DNTT_TYPE_SRCFILE,
+ DNTT_TYPE_MODULE,
+ DNTT_TYPE_FUNCTION,
+ DNTT_TYPE_ENTRY,
+ DNTT_TYPE_BEGIN,
+ DNTT_TYPE_END,
+ DNTT_TYPE_IMPORT,
+ DNTT_TYPE_LABEL,
+ DNTT_TYPE_FPARAM,
+ DNTT_TYPE_SVAR,
+ DNTT_TYPE_DVAR,
+ DNTT_TYPE_HOLE1,
+ DNTT_TYPE_CONST,
+ DNTT_TYPE_TYPEDEF,
+ DNTT_TYPE_TAGDEF,
+ DNTT_TYPE_POINTER,
+ DNTT_TYPE_ENUM,
+ DNTT_TYPE_MEMENUM,
+ DNTT_TYPE_SET,
+ DNTT_TYPE_SUBRANGE,
+ DNTT_TYPE_ARRAY,
+ DNTT_TYPE_STRUCT,
+ DNTT_TYPE_UNION,
+ DNTT_TYPE_FIELD,
+ DNTT_TYPE_VARIANT,
+ DNTT_TYPE_FILE,
+ DNTT_TYPE_FUNCTYPE,
+ DNTT_TYPE_WITH,
+ DNTT_TYPE_COMMON,
+ DNTT_TYPE_COBSTRUCT,
+ DNTT_TYPE_XREF,
+ DNTT_TYPE_SA,
+ DNTT_TYPE_MACRO,
+ DNTT_TYPE_BLOCKDATA,
+ DNTT_TYPE_CLASS_SCOPE,
+ DNTT_TYPE_REFERENCE,
+ DNTT_TYPE_PTRMEM,
+ DNTT_TYPE_PTRMEMFUNC,
+ DNTT_TYPE_CLASS,
+ DNTT_TYPE_GENFIELD,
+ DNTT_TYPE_VFUNC,
+ DNTT_TYPE_MEMACCESS,
+ DNTT_TYPE_INHERITANCE,
+ DNTT_TYPE_FRIEND_CLASS,
+ DNTT_TYPE_FRIEND_FUNC,
+ DNTT_TYPE_MODIFIER,
+ DNTT_TYPE_OBJECT_ID,
+ DNTT_TYPE_MEMFUNC,
+ DNTT_TYPE_TEMPLATE,
+ DNTT_TYPE_TEMPLATE_ARG,
+ DNTT_TYPE_FUNC_TEMPLATE,
+ DNTT_TYPE_LINK,
+ DNTT_TYPE_MAX,
+};
+
+/* DNTT_TYPE_SRCFILE:
+
+ One DNTT_TYPE_SRCFILE symbol is output for the start of each source
+ file and at the begin and end of an included file. A DNTT_TYPE_SRCFILE
+ entry is also output before each DNTT_TYPE_FUNC symbol so that debuggers
+ can determine what file a function was defined in.
+
+ LANGUAGE describes the source file's language.
+
+ NAME points to an VT entry providing the source file's name.
+
+ Note the name used for DNTT_TYPE_SRCFILE entries are exactly as seen
+ by the compiler (ie they may be relative or absolute). C include files
+ via <> inclusion must use absolute paths.
+
+ ADDRESS points to an SLT entry from which line number and code locations
+ may be determined. */
+
+struct dntt_type_srcfile
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int language: 4;
+ unsigned int unused: 17;
+ vtpointer name;
+ sltpointer address;
+};
+
+/* DNTT_TYPE_MODULE:
+
+ A DNTT_TYPE_MODULE symbol is emitted for the start of a pascal
+ module or C source file.
+
+ Each DNTT_TYPE_MODULE must have an associated DNTT_TYPE_END symbol.
+
+ NAME points to a VT entry providing the module's name. Note C
+ source files are considered nameless modules.
+
+ ALIAS point to a VT entry providing a secondary name.
+
+ ADDRESS points to an SLT entry from which line number and code locations
+ may be determined. */
+
+struct dntt_type_module
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int unused: 21;
+ vtpointer name;
+ vtpointer alias;
+ dnttpointer unused2;
+ sltpointer address;
+};
+
+/* DNTT_TYPE_FUNCTION:
+
+ A DNTT_TYPE_FUNCTION symbol is emitted for each function definition;
+ a DNTT_TYPE_ENTRY symbols is used for secondary entry points. Both
+ symbols used the dntt_type_function structure.
+
+ Each DNTT_TYPE_FUNCTION must have a matching DNTT_TYPE_END.
+
+ GLOBAL is nonzero if the function has global scope.
+
+ LANGUAGE describes the function's source language.
+
+ OPT_LEVEL describes the optimization level the function was compiled
+ with.
+
+ VARARGS is nonzero if the function uses varargs.
+
+ NAME points to a VT entry providing the function's name.
+
+ ALIAS points to a VT entry providing a secondary name for the function.
+
+ FIRSTPARAM points to a LNTT entry which describes the parameter list.
+
+ ADDRESS points to an SLT entry from which line number and code locations
+ may be determined.
+
+ ENTRYADDR is the memory address corresponding the the function's entry point
+
+ RETVAL points to a LNTT entry describing the function's return value.
+
+ LOWADDR is the lowest memory address associated with this function.
+
+ HIADDR is the highest memory address associated with this function. */
+
+struct dntt_type_function
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int global: 1;
+ unsigned int language: 4;
+ unsigned int nest_level: 5;
+ unsigned int opt_level: 2;
+ unsigned int varargs: 1;
+ unsigned int lang_info: 4;
+ unsigned int inlined: 1;
+ unsigned int localalloc: 1;
+ unsigned int expansion: 1;
+ unsigned int unused: 1;
+ vtpointer name;
+ vtpointer alias;
+ dnttpointer firstparam;
+ sltpointer address;
+ CORE_ADDR entryaddr;
+ dnttpointer retval;
+ CORE_ADDR lowaddr;
+ CORE_ADDR hiaddr;
+};
+
+/* DNTT_TYPE_BEGIN:
+
+ A DNTT_TYPE_BEGIN symbol is emitted to begin a new nested scope.
+ Every DNTT_TYPE_BEGIN symbol must have a matching DNTT_TYPE_END symbol.
+
+ CLASSFLAG is nonzero if this is the beginning of a c++ class definition.
+
+ ADDRESS points to an SLT entry from which line number and code locations
+ may be determined. */
+
+struct dntt_type_begin
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int classflag: 1;
+ unsigned int unused: 20;
+ sltpointer address;
+};
+
+/* DNTT_TYPE_END:
+
+ A DNTT_TYPE_END symbol is emitted when closing a scope started by
+ a DNTT_TYPE_MODULE, DNTT_TYPE_FUNCTION, and DNTT_TYPE_BEGIN symbols.
+
+ ENDKIND describes what type of scope the DNTT_TYPE_END is closing
+ (DNTT_TYPE_MODULE, DNTT_TYPE_BEGIN, etc).
+
+ CLASSFLAG is nonzero if this is the end of a c++ class definition.
+
+ ADDRESS points to an SLT entry from which line number and code locations
+ may be determined.
+
+ BEGINSCOPE points to the LNTT entry which opened the scope. */
+
+struct dntt_type_end
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int endkind: 10;
+ unsigned int classflag: 1;
+ unsigned int unused: 10;
+ sltpointer address;
+ dnttpointer beginscope;
+};
+
+/* DNTT_TYPE_IMPORT is unused by GDB. */
+/* DNTT_TYPE_LABEL is unused by GDB. */
+
+/* DNTT_TYPE_FPARAM:
+
+ A DNTT_TYPE_FPARAM symbol is emitted for a function argument. When
+ chained together the symbols represent an argument list for a function.
+
+ REGPARAM is nonzero if this parameter was passed in a register.
+
+ INDIRECT is nonzero if this parameter is a pointer to the parameter
+ (pass by reference or pass by value for large items).
+
+ LONGADDR is nonzero if the parameter is a 64bit pointer.
+
+ NAME is a pointer into the VT for the parameter's name.
+
+ LOCATION describes where the parameter is stored. Depending on the
+ parameter type LOCATION could be a register number, or an offset
+ from the stack pointer.
+
+ TYPE points to a NTT entry describing the type of this parameter.
+
+ NEXTPARAM points to the LNTT entry describing the next parameter. */
+
+struct dntt_type_fparam
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int regparam: 1;
+ unsigned int indirect: 1;
+ unsigned int longaddr: 1;
+ unsigned int copyparam: 1;
+ unsigned int dflt: 1;
+ unsigned int unused: 16;
+ vtpointer name;
+ int location;
+ dnttpointer type;
+ dnttpointer nextparam;
+ int misc;
+};
+
+/* DNTT_TYPE_SVAR:
+
+ A DNTT_TYPE_SVAR is emitted to describe a variable in static storage.
+
+ GLOBAL is nonzero if the variable has global scope.
+
+ INDIRECT is nonzero if the variable is a pointer to an object.
+
+ LONGADDR is nonzero if the variable is in long pointer space.
+
+ STATICMEM is nonzero if the variable is a member of a class.
+
+ A_UNION is nonzero if the variable is an anonymous union member.
+
+ NAME is a pointer into the VT for the variable's name.
+
+ LOCATION provides the memory address for the variable.
+
+ TYPE is a pointer into either the GNTT or LNTT which describes
+ the type of this variable. */
+
+struct dntt_type_svar
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int global: 1;
+ unsigned int indirect: 1;
+ unsigned int longaddr: 1;
+ unsigned int staticmem: 1;
+ unsigned int a_union: 1;
+ unsigned int unused: 16;
+ vtpointer name;
+ CORE_ADDR location;
+ dnttpointer type;
+ unsigned int offset;
+ unsigned int displacement;
+};
+
+/* DNTT_TYPE_DVAR:
+
+ A DNTT_TYPE_DVAR is emitted to describe automatic variables and variables
+ held in registers.
+
+ GLOBAL is nonzero if the variable has global scope.
+
+ INDIRECT is nonzero if the variable is a pointer to an object.
+
+ REGVAR is nonzero if the variable is in a register.
+
+ A_UNION is nonzero if the variable is an anonymous union member.
+
+ NAME is a pointer into the VT for the variable's name.
+
+ LOCATION provides the memory address or register number for the variable.
+
+ TYPE is a pointer into either the GNTT or LNTT which describes
+ the type of this variable. */
+
+struct dntt_type_dvar
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int global: 1;
+ unsigned int indirect: 1;
+ unsigned int regvar: 1;
+ unsigned int a_union: 1;
+ unsigned int unused: 17;
+ vtpointer name;
+ int location;
+ dnttpointer type;
+ unsigned int offset;
+};
+
+/* DNTT_TYPE_CONST:
+
+ A DNTT_TYPE_CONST symbol is emitted for program constants.
+
+ GLOBAL is nonzero if the constant has global scope.
+
+ INDIRECT is nonzero if the constant is a pointer to an object.
+
+ LOCATION_TYPE describes where to find the constant's value
+ (in the VT, memory, or embedded in an instruction).
+
+ CLASSMEM is nonzero if the constant is a member of a class.
+
+ NAME is a pointer into the VT for the constant's name.
+
+ LOCATION provides the memory address, register number or pointer
+ into the VT for the constant's value.
+
+ TYPE is a pointer into either the GNTT or LNTT which describes
+ the type of this variable. */
+
+struct dntt_type_const
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int global: 1;
+ unsigned int indirect: 1;
+ unsigned int: 3;
+ unsigned int classmem: 1;
+ unsigned int unused: 15;
+ vtpointer name;
+ CORE_ADDR location;
+ dnttpointer type;
+ unsigned int offset;
+ unsigned int displacement;
+};
+
+/* DNTT_TYPE_TYPEDEF and DNTT_TYPE_TAGDEF:
+
+ The same structure is used to describe typedefs and tagdefs.
+
+ DNTT_TYPE_TYPEDEFS are associated with C "typedefs".
+
+ DNTT_TYPE_TAGDEFs are associated with C "struct", "union", and "enum"
+ tags, which may have the same name as a typedef in the same scope.
+
+ GLOBAL is nonzero if the typedef/tagdef has global scope.
+
+ TYPEINFO is used to determine if full type information is available
+ for a tag. (usually 1, but can be zero for opaque types in C).
+
+ NAME is a pointer into the VT for the constant's name.
+
+ TYPE points to the underlying type for the typedef/tagdef in the
+ GNTT or LNTT. */
+
+struct dntt_type_type
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int global: 1;
+ unsigned int typeinfo: 1;
+ unsigned int unused: 19;
+ vtpointer name;
+ dnttpointer type;
+};
+
+/* DNTT_TYPE_POINTER:
+
+ Used to describe a pointer to an underlying type.
+
+ POINTSTO is a pointer into the GNTT or LNTT for the type which this
+ pointer points to.
+
+ BITLENGTH is the length of the pointer (not the underlying type). */
+
+struct dntt_type_pointer
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int unused: 21;
+ dnttpointer pointsto;
+ unsigned int bitlength;
+};
+
+
+/* DNTT_TYPE_ENUM:
+
+ Used to describe enumerated types.
+
+ FIRSTMEM is a pointer to a DNTT_TYPE_MEMENUM in the GNTT/LNTT which
+ describes the first member (and contains a pointer to the chain of
+ members).
+
+ BITLENGTH is the number of bits used to hold the values of the enum's
+ members. */
+
+struct dntt_type_enum
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int unused: 21;
+ dnttpointer firstmem;
+ unsigned int bitlength;
+};
+
+/* DNTT_TYPE_MEMENUM
+
+ Used to describe members of an enumerated type.
+
+ CLASSMEM is nonzero if this member is part of a class.
+
+ NAME points into the VT for the name of this member.
+
+ VALUE is the value of this enumeration member.
+
+ NEXTMEM points to the next DNTT_TYPE_MEMENUM in the chain. */
+
+struct dntt_type_memenum
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int classmem: 1;
+ unsigned int unused: 20;
+ vtpointer name;
+ unsigned int value;
+ dnttpointer nextmem;
+};
+
+/* DNTT_TYPE_SET
+
+ DECLARATION describes the bitpacking of the set.
+
+ SUBTYPE points to a DNTT entry describing the type of the members.
+
+ BITLENGTH is the size of the set. */
+
+struct dntt_type_set
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int declaration: 2;
+ unsigned int unused: 19;
+ dnttpointer subtype;
+ unsigned int bitlength;
+};
+
+/* DNTT_TYPE_SUBRANGE
+
+ DYN_LOW describes the lower bound of the subrange:
+
+ 00 for a constant lower bound (found in LOWBOUND).
+
+ 01 for a dynamic lower bound with the lower bound found in the the
+ memory address pointed to by LOWBOUND.
+
+ 10 for a dynamic lower bound described by an variable found in the
+ DNTT/LNTT (LOWBOUND would be a pointer into the DNTT/LNTT).
+
+ DYN_HIGH is similar to DYN_LOW, except it describes the upper bound.
+
+ SUBTYPE points to the type of the subrange.
+
+ BITLENGTH is the length in bits needed to describe the subrange's
+ values. */
+
+struct dntt_type_subrange
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int dyn_low: 2;
+ unsigned int dyn_high: 2;
+ unsigned int unused: 17;
+ int lowbound;
+ int highbound;
+ dnttpointer subtype;
+ unsigned int bitlength;
+};
+
+/* DNTT_TYPE_ARRAY
+
+ DECLARATION describes the bit packing used in the array.
+
+ ARRAYISBYTES is nonzero if the field in arraylength describes the
+ length in bytes rather than in bits. A value of zero is used to
+ describe an array with size 2**32.
+
+ ELEMISBYTES is nonzero if the length if each element in the array
+ is describes in bytes rather than bits. A value of zero is used
+ to an element with size 2**32.
+
+ ELEMORDER is nonzero if the elements are indexed in increasing order.
+
+ JUSTIFIED if the elements are left justified to index zero.
+
+ ARRAYLENGTH is the length of the array.
+
+ INDEXTYPE is a DNTT pointer to the type used to index the array.
+
+ ELEMTYPE is a DNTT pointer to the type for the array elements.
+
+ ELEMLENGTH is the length of each element in the array (including
+ any padding).
+
+ Multi-dimensional arrays are represented by ELEMTYPE pointing to
+ another DNTT_TYPE_ARRAY. */
+
+struct dntt_type_array
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int declaration: 2;
+ unsigned int dyn_low: 2;
+ unsigned int dyn_high: 2;
+ unsigned int arrayisbytes: 1;
+ unsigned int elemisbytes: 1;
+ unsigned int elemorder: 1;
+ unsigned int justified: 1;
+ unsigned int unused: 11;
+ unsigned int arraylength;
+ dnttpointer indextype;
+ dnttpointer elemtype;
+ unsigned int elemlength;
+};
+
+/* DNTT_TYPE_STRUCT
+
+ DNTT_TYPE_STRUCT is used to describe a C structure.
+
+ DECLARATION describes the bitpacking used.
+
+ FIRSTFIELD is a DNTT pointer to the first field of the structure
+ (each field contains a pointer to the next field, walk the list
+ to access all fields of the structure).
+
+ VARTAGFIELD and VARLIST are used for Pascal variant records.
+
+ BITLENGTH is the size of the structure in bits. */
+
+struct dntt_type_struct
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int declaration: 2;
+ unsigned int unused: 19;
+ dnttpointer firstfield;
+ dnttpointer vartagfield;
+ dnttpointer varlist;
+ unsigned int bitlength;
+};
+
+/* DNTT_TYPE_UNION
+
+ DNTT_TYPE_UNION is used to describe a C union.
+
+ FIRSTFIELD is a DNTT pointer to the beginning of the field chain.
+
+ BITLENGTH is the size of the union in bits. */
+
+struct dntt_type_union
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int unused: 21;
+ dnttpointer firstfield;
+ unsigned int bitlength;
+};
+
+/* DNTT_TYPE_FIELD
+
+ DNTT_TYPE_FIELD describes one field in a structure or union.
+
+ VISIBILITY is used to describe the visibility of the field
+ (for c++. public = 0, protected = 1, private = 2).
+
+ A_UNION is nonzero if this field is a member of an anonymous union.
+
+ STATICMEM is nonzero if this field is a static member of a template.
+
+ NAME is a pointer into the VT for the name of the field.
+
+ BITOFFSET gives the offset of this field in bits from the beginning
+ of the structure or union this field is a member of.
+
+ TYPE is a DNTT pointer to the type describing this field.
+
+ BITLENGTH is the size of the entry in bits.
+
+ NEXTFIELD is a DNTT pointer to the next field in the chain. */
+
+struct dntt_type_field
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int visibility: 2;
+ unsigned int a_union: 1;
+ unsigned int staticmem: 1;
+ unsigned int unused: 17;
+ vtpointer name;
+ unsigned int bitoffset;
+ dnttpointer type;
+ unsigned int bitlength;
+ dnttpointer nextfield;
+};
+
+/* DNTT_TYPE_VARIANT is unused by GDB. */
+/* DNTT_TYPE_FILE is unused by GDB. */
+
+/* DNTT_TYPE_COMMON is unused by GDB. */
+/* DNTT_TYPE_LINK is unused by GDB. */
+/* DNTT_TYPE_FFUNC_LINK is unused by GDB. */
+/* DNTT_TYPE_TEMPLATE is unused by GDB. */
+
+/* DNTT_TYPE_FUNCTYPE
+
+ VARARGS is nonzero if this function uses varargs.
+
+ FIRSTPARAM is a DNTT pointer to the first entry in the parameter
+ chain.
+
+ RETVAL is a DNTT pointer to the type of the return value. */
+
+struct dntt_type_functype
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int varargs: 1;
+ unsigned int info: 4;
+ unsigned int unused: 16;
+ unsigned int bitlength;
+ dnttpointer firstparam;
+ dnttpointer retval;
+};
+
+/* DNTT_TYPE_WITH is unued by GDB. */
+/* DNTT_TYPE_COBSTRUCT is unused by GDB. */
+/* DNTT_TYPE_MODIFIER is unused by GDB. */
+/* DNTT_TYPE_GENFIELD is unused by GDB. */
+/* DNTT_TYPE_MEMACCESS is unused by GDB. */
+/* DNTT_TYPE_VFUNC is unused by GDB. */
+/* DNTT_TYPE_CLASS_SCOPE is unused by GDB. */
+/* DNTT_TYPE_FRIEND_CLASS is unused by GDB. */
+/* DNTT_TYPE_FRIEND_FUNC is unused by GDB. */
+/* DNTT_TYPE_CLASS unused by GDB. */
+/* DNTT_TYPE_TEMPLATE unused by GDB. */
+/* DNTT_TYPE_TEMPL_ARG is unused by GDB. */
+/* DNTT_TYPE_PTRMEM not used by GDB */
+/* DNTT_TYPE_INHERITANCE is unused by GDB. */
+/* DNTT_TYPE_OBJECT_ID is unused by GDB. */
+/* DNTT_TYPE_XREF is unused by GDB. */
+/* DNTT_TYPE_SA is unused by GDB. */
+
+/* DNTT_TYPE_GENERIC and DNTT_TYPE_BLOCK are convience structures
+ so we can examine a DNTT entry in a generic fashion. */
+struct dntt_type_generic
+{
+ unsigned int word[9];
+};
+
+struct dntt_type_block
+{
+ unsigned int extension: 1;
+ unsigned int kind: 10;
+ unsigned int unused: 21;
+ unsigned int word[2];
+};
+
+/* One entry in a DNTT (either the LNTT or GNTT). */
+union dnttentry
+{
+ struct dntt_type_srcfile dsfile;
+ struct dntt_type_module dmodule;
+ struct dntt_type_function dfunc;
+ struct dntt_type_function dentry;
+ struct dntt_type_begin dbegin;
+ struct dntt_type_end dend;
+ struct dntt_type_fparam dfparam;
+ struct dntt_type_svar dsvar;
+ struct dntt_type_dvar ddvar;
+ struct dntt_type_const dconst;
+ struct dntt_type_type dtype;
+ struct dntt_type_type dtag;
+ struct dntt_type_pointer dptr;
+ struct dntt_type_enum denum;
+ struct dntt_type_memenum dmember;
+ struct dntt_type_set dset;
+ struct dntt_type_subrange dsubr;
+ struct dntt_type_array darray;
+ struct dntt_type_struct dstruct;
+ struct dntt_type_union dunion;
+ struct dntt_type_field dfield;
+ struct dntt_type_functype dfunctype;
+ struct dntt_type_generic dgeneric;
+ struct dntt_type_block dblock;
+};
+
+/* Source line entry types. */
+enum slttype
+{
+ SLT_NORMAL,
+ SLT_SRCFILE,
+ SLT_MODULE,
+ SLT_FUNCTION,
+ SLT_ENTRY,
+ SLT_BEGIN,
+ SLT_END,
+ SLT_WITH,
+ SLT_EXIT,
+ SLT_ASSIST,
+ SLT_MARKER,
+};
+
+/* A normal source line entry. Simply provides a mapping of a source
+ line number to a code address.
+
+ SLTDESC will always be SLT_NORMAL or SLT_EXIT. */
+
+struct slt_normal
+{
+ unsigned int sltdesc: 4;
+ unsigned int line: 28;
+ CORE_ADDR address;
+};
+
+/* A special source line entry. Provides a mapping of a declaration
+ to a line number. These entries point back into the DNTT which
+ references them. */
+
+struct slt_special
+{
+ unsigned int sltdesc: 4;
+ unsigned int line: 28;
+ dnttpointer backptr;
+};
+
+/* Used to describe nesting.
+
+ For nested languages, an slt_assist entry must follow each SLT_FUNC
+ entry in the SLT. The address field will point forward to the
+ first slt_normal entry within the function's scope. */
+
+struct slt_assist
+{
+ unsigned int sltdesc: 4;
+ unsigned int unused: 28;
+ sltpointer address;
+};
+
+struct slt_generic
+{
+ unsigned int word[2];
+};
+
+union sltentry
+{
+ struct slt_normal snorm;
+ struct slt_special sspec;
+ struct slt_assist sasst;
+ struct slt_generic sgeneric;
+};
+
+#endif /* HP_SYMTAB_INCLUDED */
diff --git a/contrib/gdb/include/ieee.h b/contrib/gdb/include/ieee.h
new file mode 100644
index 0000000..5ade39d
--- /dev/null
+++ b/contrib/gdb/include/ieee.h
@@ -0,0 +1,139 @@
+/* IEEE Standard 695-1980 "Universal Format for Object Modules" header file
+ Contributed by Cygnus Support. */
+
+#define N_W_VARIABLES 8
+#define Module_Beginning 0xe0
+
+typedef struct ieee_module {
+ char *processor;
+ char *module_name;
+} ieee_module_begin_type;
+
+#define Address_Descriptor 0xec
+typedef struct ieee_address {
+bfd_vma number_of_bits_mau;
+ bfd_vma number_of_maus_in_address;
+
+ unsigned char byte_order;
+#define IEEE_LITTLE 0xcc
+#define IEEE_BIG 0xcd
+} ieee_address_descriptor_type;
+
+typedef union ieee_w_variable {
+ file_ptr offset[N_W_VARIABLES];
+ struct {
+ file_ptr extension_record;
+ file_ptr environmental_record;
+ file_ptr section_part;
+ file_ptr external_part;
+ file_ptr debug_information_part;
+ file_ptr data_part;
+ file_ptr trailer_part;
+ file_ptr me_record;
+ } r;
+} ieee_w_variable_type;
+
+
+
+
+
+typedef enum ieee_record
+{
+ ieee_number_start_enum = 0x00,
+ ieee_number_end_enum=0x7f,
+ ieee_number_repeat_start_enum = 0x80,
+ ieee_number_repeat_end_enum = 0x88,
+ ieee_number_repeat_4_enum = 0x84,
+ ieee_number_repeat_3_enum = 0x83,
+ ieee_number_repeat_2_enum = 0x82,
+ ieee_number_repeat_1_enum = 0x81,
+ ieee_module_beginning_enum = 0xe0,
+ ieee_module_end_enum = 0xe1,
+ ieee_extension_length_1_enum = 0xde,
+ ieee_extension_length_2_enum = 0xdf,
+ ieee_section_type_enum = 0xe6,
+ ieee_section_alignment_enum = 0xe7,
+ ieee_external_symbol_enum = 0xe8,
+ ieee_comma = 0x90,
+ ieee_external_reference_enum = 0xe9,
+ ieee_set_current_section_enum = 0xe5,
+ ieee_address_descriptor_enum = 0xec,
+ ieee_load_constant_bytes_enum = 0xed,
+ ieee_load_with_relocation_enum = 0xe4,
+
+ ieee_variable_A_enum = 0xc1,
+ ieee_variable_B_enum = 0xc2,
+ ieee_variable_C_enum = 0xc3,
+ ieee_variable_D_enum = 0xc4,
+ ieee_variable_E_enum = 0xc5,
+ ieee_variable_F_enum = 0xc6,
+ ieee_variable_G_enum = 0xc7,
+ ieee_variable_H_enum = 0xc8,
+ ieee_variable_I_enum = 0xc9,
+ ieee_variable_J_enum = 0xca,
+ ieee_variable_K_enum = 0xcb,
+ ieee_variable_L_enum = 0xcc,
+ ieee_variable_M_enum = 0xcd,
+ ieee_variable_N_enum = 0xce,
+ ieee_variable_O_enum = 0xcf,
+ ieee_variable_P_enum = 0xd0,
+ ieee_variable_Q_enum = 0xd1,
+ ieee_variable_R_enum = 0xd2,
+ ieee_variable_S_enum = 0xd3,
+ ieee_variable_T_enum = 0xd4,
+ ieee_variable_U_enum = 0xd5,
+ ieee_variable_V_enum = 0xd6,
+ ieee_variable_W_enum = 0xd7,
+ ieee_variable_X_enum = 0xd8,
+ ieee_variable_Y_enum = 0xd9,
+ ieee_variable_Z_enum = 0xda,
+ ieee_function_plus_enum = 0xa5,
+ ieee_function_minus_enum = 0xa6,
+ ieee_function_signed_open_b_enum = 0xba,
+ ieee_function_signed_close_b_enum = 0xbb,
+
+ ieee_function_unsigned_open_b_enum = 0xbc,
+ ieee_function_unsigned_close_b_enum = 0xbd,
+
+ ieee_function_either_open_b_enum = 0xbe,
+ ieee_function_either_close_b_enum = 0xbf,
+ ieee_record_seperator_enum = 0xdb,
+
+ ieee_e2_first_byte_enum = 0xe2,
+ ieee_section_size_enum = 0xe2d3,
+ ieee_physical_region_size_enum = 0xe2c1,
+ ieee_region_base_address_enum = 0xe2c2,
+ ieee_mau_size_enum = 0xe2c6,
+ ieee_m_value_enum = 0xe2cd,
+ ieee_section_base_address_enum = 0xe2cc,
+ ieee_asn_record_enum = 0xe2ce,
+ ieee_section_offset_enum = 0xe2d2,
+ ieee_value_starting_address_enum = 0xe2c7,
+ ieee_assign_value_to_variable_enum = 0xe2d7,
+ ieee_set_current_pc_enum = 0xe2d0,
+ ieee_value_record_enum = 0xe2c9,
+ ieee_nn_record = 0xf0,
+ ieee_at_record_enum = 0xf1,
+ ieee_ty_record_enum = 0xf2,
+ ieee_attribute_record_enum = 0xf1c9,
+ ieee_atn_record_enum = 0xf1ce,
+ ieee_external_reference_info_record_enum = 0xf1d8,
+ ieee_weak_external_reference_enum= 0xf4,
+ ieee_repeat_data_enum = 0xf7,
+ ieee_bb_record_enum = 0xf8,
+ ieee_be_record_enum = 0xf9
+} ieee_record_enum_type;
+
+
+typedef struct ieee_section {
+ unsigned int section_index;
+ unsigned int section_type;
+ char *section_name;
+ unsigned int parent_section_index;
+ unsigned int sibling_section_index;
+ unsigned int context_index;
+} ieee_section_type;
+#define IEEE_REFERENCE_BASE 11
+#define IEEE_PUBLIC_BASE 32
+#define IEEE_SECTION_NUMBER_BASE 1
+
diff --git a/contrib/gdb/include/libiberty.h b/contrib/gdb/include/libiberty.h
new file mode 100644
index 0000000..dc083c8
--- /dev/null
+++ b/contrib/gdb/include/libiberty.h
@@ -0,0 +1,133 @@
+/* Function declarations for libiberty.
+ Written by Cygnus Support, 1994.
+
+ The libiberty library provides a number of functions which are
+ missing on some operating systems. We do not declare those here,
+ to avoid conflicts with the system header files on operating
+ systems that do support those functions. In this file we only
+ declare those functions which are specific to libiberty. */
+
+#ifndef LIBIBERTY_H
+#define LIBIBERTY_H
+
+#include "ansidecl.h"
+
+/* Build an argument vector from a string. Allocates memory using
+ malloc. Use freeargv to free the vector. */
+
+extern char **buildargv PARAMS ((char *));
+
+/* Free a vector returned by buildargv. */
+
+extern void freeargv PARAMS ((char **));
+
+/* Return the last component of a path name. */
+
+extern char *basename ();
+
+/* Concatenate an arbitrary number of strings, up to (char *) NULL.
+ Allocates memory using xmalloc. */
+
+extern char *concat PARAMS ((const char *, ...));
+
+/* Check whether two file descriptors refer to the same file. */
+
+extern int fdmatch PARAMS ((int fd1, int fd2));
+
+/* Get the amount of time the process has run, in microseconds. */
+
+extern long get_run_time PARAMS ((void));
+
+/* Allocate memory filled with spaces. Allocates using malloc. */
+
+extern const char *spaces PARAMS ((int count));
+
+/* Return the maximum error number for which strerror will return a
+ string. */
+
+extern int errno_max PARAMS ((void));
+
+/* Return the name of an errno value (e.g., strerrno (EINVAL) returns
+ "EINVAL"). */
+
+extern const char *strerrno PARAMS ((int));
+
+/* Given the name of an errno value, return the value. */
+
+extern int strtoerrno PARAMS ((const char *));
+
+/* ANSI's strerror(), but more robust. */
+
+extern char *xstrerror PARAMS ((int));
+
+/* Return the maximum signal number for which strsignal will return a
+ string. */
+
+extern int signo_max PARAMS ((void));
+
+/* Return a signal message string for a signal number
+ (e.g., strsignal (SIGHUP) returns something like "Hangup"). */
+/* This is commented out as it can conflict with one in system headers.
+ We still document its existence though. */
+
+/*extern const char *strsignal PARAMS ((int));*/
+
+/* Return the name of a signal number (e.g., strsigno (SIGHUP) returns
+ "SIGHUP"). */
+
+extern const char *strsigno PARAMS ((int));
+
+/* Given the name of a signal, return its number. */
+
+extern int strtosigno PARAMS ((const char *));
+
+/* Register a function to be run by xexit. Returns 0 on success. */
+
+extern int xatexit PARAMS ((void (*fn) (void)));
+
+/* Exit, calling all the functions registered with xatexit. */
+
+#ifndef __GNUC__
+extern void xexit PARAMS ((int status));
+#else
+typedef void libiberty_voidfn PARAMS ((int status));
+__volatile__ libiberty_voidfn xexit;
+#endif
+
+/* Set the program name used by xmalloc. */
+
+extern void xmalloc_set_program_name PARAMS ((const char *));
+
+/* Allocate memory without fail. If malloc fails, this will print a
+ message to stderr (using the name set by xmalloc_set_program_name,
+ if any) and then call xexit.
+
+ FIXME: We do not declare the parameter type (size_t) in order to
+ avoid conflicts with other declarations of xmalloc that exist in
+ programs which use libiberty. */
+
+extern PTR xmalloc ();
+
+/* Reallocate memory without fail. This works like xmalloc.
+
+ FIXME: We do not declare the parameter types for the same reason as
+ xmalloc. */
+
+extern PTR xrealloc ();
+
+/* Copy a string into a memory buffer without fail. */
+
+extern char *xstrdup PARAMS ((const char *));
+
+/* hex character manipulation routines */
+
+#define _hex_array_size 256
+#define _hex_bad 99
+extern char _hex_value[_hex_array_size];
+extern void hex_init PARAMS ((void));
+#define hex_p(c) (hex_value (c) != _hex_bad)
+/* If you change this, note well: Some code relies on side effects in
+ the argument being performed exactly once. */
+#define hex_value(c) (_hex_value[(unsigned char) (c)])
+
+#endif /* ! defined (LIBIBERTY_H) */
diff --git a/contrib/gdb/include/mpw/ChangeLog b/contrib/gdb/include/mpw/ChangeLog
new file mode 100644
index 0000000..8dbad87
--- /dev/null
+++ b/contrib/gdb/include/mpw/ChangeLog
@@ -0,0 +1,61 @@
+Tue Feb 27 12:23:04 1996 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mpw.h (HAVE_VPRINTF): Add and define to have the value 1.
+
+Fri Dec 29 14:40:46 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.h (HAVE_STDLIB_H, etc): Define to have the value 1.
+ (HAVE_FCNTL_H): Define.
+
+Mon Dec 11 15:39:06 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.h (open, access): Define as mpw_open and mpw_access.
+
+Thu Nov 9 15:38:37 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.h: Include unix.h if USE_MW_HEADERS, otherwise include
+ various original MPW include files (ioctl.h, etc).
+ (EIO): Define if not defined.
+ * sys/ioctl.h: Remove, not needed.
+
+Wed Oct 25 12:30:44 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.h: Don't include errno.h or ioctl.h.
+ (ENOENT, EACCES, ENOSYS): Define if not defined.
+ (fdopen): Declare if __STDC__.
+ (R_OK, W_OK, X_OK): Define if not defined.
+
+Tue Sep 26 14:57:21 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.h: New file, universally useful MPW host definitions.
+ Many of these used to live in bfd/hosts/mpw.h.
+ * grp.h: Remove RCS comment.
+ * sys/ioctl.h: Add a comment line.
+
+Wed Dec 14 13:12:14 1994 Stan Shebs <shebs@andros.cygnus.com>
+
+ * spin.h: New file, cursor spinning for progress.
+
+Thu Jun 30 15:32:07 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * fcntl.h (open): Allow optional third arg.
+
+Thu Apr 14 12:54:51 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * dir.h, dirent.h, fcntl.h, grp.h, pwd.h, stat.h: New files.
+ * sys/ioctl.h: New file.
+
+Mon Feb 21 09:44:45 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * sys/stat.h (struct stat): New field st_rsize.
+ (S_IFMT, etc): Use different bit positions.
+ (fstat): Add parameter names to prototype.
+
+Mon Jan 31 19:30:16 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * README: New file.
+ * utime.h, varargs.h: New files, simulated Posix.
+ * sys/{file,param,resource,stat,time,types}.h: New files, more
+ simulated Posix.
+
+
diff --git a/contrib/gdb/include/mpw/README b/contrib/gdb/include/mpw/README
new file mode 100644
index 0000000..10e92de
--- /dev/null
+++ b/contrib/gdb/include/mpw/README
@@ -0,0 +1 @@
+This is a collection of include files that help imitate Posix in MPW.
diff --git a/contrib/gdb/include/mpw/dir.h b/contrib/gdb/include/mpw/dir.h
new file mode 100644
index 0000000..e6ccd2d
--- /dev/null
+++ b/contrib/gdb/include/mpw/dir.h
@@ -0,0 +1,23 @@
+/* The <dir.h> header gives the layout of a directory. */
+
+#pragma once
+
+#ifndef _DIR_H
+#define _DIR_H
+
+#ifndef _TYPES_H /* not quite right */
+#include <sys/types.h>
+#endif
+
+#define DIRBLKSIZ 512 /* size of directory block */
+
+#ifndef DIRSIZ
+#define DIRSIZ 14
+#endif
+
+struct direct {
+ ino_t d_ino;
+ char d_name[DIRSIZ];
+};
+
+#endif /* _DIR_H */
diff --git a/contrib/gdb/include/mpw/dirent.h b/contrib/gdb/include/mpw/dirent.h
new file mode 100644
index 0000000..38000b2
--- /dev/null
+++ b/contrib/gdb/include/mpw/dirent.h
@@ -0,0 +1,31 @@
+#ifndef __dirent_h
+#define __dirent_h
+
+#include "sys/dir.h"
+
+struct dirent {
+ long d_ino; /* inode number of entry */
+ off_t d_off; /* offset of disk directory entry */
+ unsigned short d_reclen; /* length of this record */
+ char d_name[1]; /* name of file */
+};
+
+/*
+#define DIRENTBASESIZE \
+ (((struct dirent *) 0)->d_name - (char *) 0)
+#define DIRENTSIZE(namelen) \
+ ((DIRENTBASESIZE + (namelen) + NBPW) & ~(NBPW - 1))
+*/
+
+/* from Mips posix/dirent.h */
+
+/*
+#undef rewinddir
+*/
+
+extern DIR *opendir();
+extern struct dirent *readdir();
+extern void rewinddir();
+extern int closedir();
+
+#endif /* ! __dirent_h */
diff --git a/contrib/gdb/include/mpw/fcntl.h b/contrib/gdb/include/mpw/fcntl.h
new file mode 100644
index 0000000..30999b4
--- /dev/null
+++ b/contrib/gdb/include/mpw/fcntl.h
@@ -0,0 +1,124 @@
+/*
+ * FCntl.h -- faccess(), fcntl(), and open() mode flags
+ *
+ * Portions copyright American Telephone & Telegraph
+ * Used with permission, Apple Computer Inc. (1985,1988,1990,1992)
+ * All rights reserved.
+ */
+
+#ifndef __FCNTL__
+#define __FCNTL__
+
+#ifndef __TYPES__
+#include <Types.h>
+#endif
+
+/*
+ * For use by lseek():
+ */
+
+#ifndef __STDIO__ /* these defns exactly paralled in StdIO.h for fseek() */
+#define SEEK_CUR 1
+#define SEEK_END 2
+#define SEEK_SET 0
+#endif
+
+/*
+ * faccess() commands; for general use
+ */
+ /* 'd' => "directory" ops */
+#define F_DELETE (('d'<<8)|0x01)
+#define F_RENAME (('d'<<8)|0x02)
+
+/*
+ * more faccess() commands; for use only by MPW tools
+ */
+
+#define F_OPEN (('d'<<8)|0x00) /* reserved for operating system use */
+ /* 'e' => "editor" ops */
+#define F_GTABINFO (('e'<<8)|0x00) /* get tab offset for file */
+#define F_STABINFO (('e'<<8)|0x01) /* set " " " " */
+#define F_GFONTINFO (('e'<<8)|0x02) /* get font number and size for file */
+#define F_SFONTINFO (('e'<<8)|0x03) /* set " " " " " " */
+#define F_GPRINTREC (('e'<<8)|0x04) /* get print record for file */
+#define F_SPRINTREC (('e'<<8)|0x05) /* set " " " " */
+#define F_GSELINFO (('e'<<8)|0x06) /* get selection information for file */
+#define F_SSELINFO (('e'<<8)|0x07) /* set " " " " */
+#define F_GWININFO (('e'<<8)|0x08) /* get current window position */
+#define F_SWININFO (('e'<<8)|0x09) /* set " " " */
+#define F_GSCROLLINFO (('e'<<8)|0x0A) /* get scroll information */
+#define F_SSCROLLINFO (('e'<<8)|0x0B) /* set " " */
+#define F_GMARKER (('e'<<8)|0x0D) /* Get Marker */
+#define F_SMARKER (('e'<<8)|0x0C) /* Set " */
+#define F_GSAVEONCLOSE (('e'<<8)|0x0F) /* Get Save on close */
+#define F_SSAVEONCLOSE (('e'<<8)|0x0E) /* Set " " " */
+
+/*
+ * argument structures used by various faccess() commands
+ */
+
+struct MarkElement {
+ int start; /* start position of mark */
+ int end; /* end position */
+ unsigned char charCount; /* number of chars in mark name */
+ char name[64]; /* mark name */
+} ; /* note: marker names may be up to 64 characters long */
+
+#ifndef __cplusplus
+typedef struct MarkElement MarkElement;
+#endif
+
+struct SelectionRecord {
+ long startingPos;
+ long endingPos;
+ long displayTop;
+};
+
+#ifndef __cplusplus
+typedef struct SelectionRecord SelectionRecord;
+#endif
+
+
+/*
+ * Mode values accessible to open()
+ */
+#define O_RDONLY 0 /* Bits 0 and 1 are used internally */
+#define O_WRONLY 1 /* Values 0..2 are historical */
+#define O_RDWR 2 /* NOTE: it goes 0, 1, 2, *!* 8, 16, 32, ... */
+#define O_APPEND (1<< 3) /* append (writes guaranteed at the end) */
+#define O_RSRC (1<< 4) /* Open the resource fork */
+#define O_ALIAS (1<< 5) /* Open alias file */
+#define O_CREAT (1<< 8) /* Open with file create */
+#define O_TRUNC (1<< 9) /* Open with truncation */
+#define O_EXCL (1<<10) /* w/ O_CREAT: Exclusive "create-only" */
+#define O_BINARY (1<<11) /* Open as a binary stream */
+#define O_NRESOLVE (1<<14) /* Don't resolve any aliases */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * function prototypes
+ */
+int close(int);
+int creat(const char*);
+int dup(int filedes); /* OBSOLETE: fcntl(filedes, F_DUPFD, 0) is preferred */
+int faccess(char*, unsigned int, long*);
+int fcntl(int, unsigned int, int);
+long lseek(int, long, int);
+int open(const char*, int, ...);
+int read(int, char*, unsigned);
+int unlink(char*);
+int write(int, const char*, unsigned);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * fcntl() commands
+ */
+#define F_DUPFD 0 /* Duplicate files (file descriptor) */
+
+#endif __FCNTL__
diff --git a/contrib/gdb/include/mpw/grp.h b/contrib/gdb/include/mpw/grp.h
new file mode 100644
index 0000000..faf2c6a
--- /dev/null
+++ b/contrib/gdb/include/mpw/grp.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "sys/types.h"
+
+struct group {
+ char *gr_name;
+ gid_t gr_gid;
+ char *gr_passwd;
+ char **gr_mem;
+};
diff --git a/contrib/gdb/include/mpw/mpw.h b/contrib/gdb/include/mpw/mpw.h
new file mode 100644
index 0000000..58702e7
--- /dev/null
+++ b/contrib/gdb/include/mpw/mpw.h
@@ -0,0 +1,130 @@
+/* Mac MPW host-specific definitions. */
+
+#ifndef __INCLUDE_MPW_H
+#define __INCLUDE_MPW_H
+
+#ifndef MPW
+#define MPW
+#endif
+
+/* MPW C is basically ANSI, but doesn't actually enable __STDC__,
+ nor does it allow __STDC__ to be #defined. */
+
+#ifndef ALMOST_STDC
+#define ALMOST_STDC
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+
+#define HAVE_TIME_T_IN_TIME_H 1
+
+#define HAVE_STDLIB_H 1
+
+#define HAVE_ERRNO_H 1
+
+#define HAVE_STDDEF_H 1
+
+#define HAVE_STRING_H 1
+
+#define HAVE_STDARG_H 1
+
+#define HAVE_VPRINTF 1
+
+#ifdef USE_MW_HEADERS
+
+#include <unix.h>
+
+#else
+
+#include <fcntl.h>
+#include <ioctl.h>
+#include <sys/stat.h>
+
+#define HAVE_FCNTL_H 1
+
+#ifndef O_ACCMODE
+#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
+#endif
+
+#ifndef fileno
+#define fileno(fp) ((fp)->_file)
+#endif
+
+/* stdio.h does not define this if __STDC__, so define here. */
+
+#ifdef __STDC__
+FILE *fdopen(int fildes, const char *mode);
+#endif
+
+#endif /* USE_MW_HEADERS */
+
+/* Add ersatz definitions, for systems that lack them. */
+
+#ifndef EIO
+#define EIO 96
+#endif
+#ifndef ENOENT
+#define ENOENT 97
+#endif
+#ifndef EACCES
+#define EACCES 98
+#endif
+#ifndef ENOSYS
+#define ENOSYS 99
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#endif
+
+/* Binary files have different characteristics; for instance, no cr/nl
+ translation. */
+
+#define USE_BINARY_FOPEN
+
+#include <spin.h>
+
+#ifdef MPW_C
+#undef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((int)(P))
+#undef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((char *)(P))
+#endif /* MPW_C */
+
+#define NO_FCNTL
+
+int fstat ();
+
+FILE *mpw_fopen ();
+int mpw_fseek ();
+int mpw_fread ();
+int mpw_fwrite ();
+int mpw_access ();
+int mpw_open ();
+int mpw_creat ();
+void mpw_abort (void);
+
+/* Map these standard functions to improved versions in libiberty. */
+
+#define fopen mpw_fopen
+#define fseek mpw_fseek
+#define fread mpw_fread
+#define fwrite mpw_fwrite
+#define open mpw_open
+#define access mpw_access
+#define creat mpw_creat
+#define abort mpw_abort
+
+#define POSIX_UTIME
+
+#define LOSING_TOTALLY
+
+/* Define this so that files will be closed before being unlinked. */
+
+#define CLOSE_BEFORE_UNLINK
+
+#endif /* __INCLUDE_MPW_H */
diff --git a/contrib/gdb/include/mpw/pwd.h b/contrib/gdb/include/mpw/pwd.h
new file mode 100644
index 0000000..2d4fb70
--- /dev/null
+++ b/contrib/gdb/include/mpw/pwd.h
@@ -0,0 +1,15 @@
+#ifndef __pwd_h
+#define __pwd_h
+
+#include <sys/types.h>
+
+struct passwd {
+ char *pw_name;
+ uid_t pw_uid;
+ gid_t pw_gid;
+ char *pw_dir;
+ char *pw_shell;
+ char *pw_passwd;
+};
+
+#endif /* ! __pwd_h */
diff --git a/contrib/gdb/include/mpw/spin.h b/contrib/gdb/include/mpw/spin.h
new file mode 100644
index 0000000..867d145
--- /dev/null
+++ b/contrib/gdb/include/mpw/spin.h
@@ -0,0 +1,64 @@
+/* Progress macros that use SpinCursor in MPW.
+ Copyright (C) 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef _SPIN_H
+#define _SPIN_H
+
+/* For MPW, progress macros just need to "spin the cursor" frequently,
+ preferably several times per second on a 68K Mac. */
+
+/* In order to determine if we're meeting the goal, define this macro
+ and information about frequency of spinning will be collected and
+ displayed. */
+
+#define SPIN_MEASUREMENT
+
+#include <CursorCtl.h>
+
+/* Programs use this macro to indicate the start of a lengthy
+ activity. STR identifies the particular activity, while N
+ indicates the expected duration, in unspecified units. If N is
+ zero, then the expected time to completion is unknown. */
+
+#undef START_PROGRESS
+#define START_PROGRESS(STR,N) mpw_start_progress (STR, N, __FILE__, __LINE__);
+
+/* Programs use this macro to indicate that progress has been made on a
+ lengthy activity. */
+
+#undef PROGRESS
+#ifdef SPIN_MEASUREMENT
+#define PROGRESS(X) mpw_progress_measured (X, __FILE__, __LINE__);
+#else
+#define PROGRESS(X) mpw_progress (X);
+#endif
+
+/* Programs use this macro to indicate the end of a lengthy activity.
+ STR must match a STR passed to START_PROGRESS previously. */
+
+#undef END_PROGRESS
+#define END_PROGRESS(STR) mpw_end_progress (STR, __FILE__, __LINE__);
+
+extern void mpw_start_progress (char *, int, char *, int);
+
+extern void mpw_progress (int);
+
+extern void mpw_progress_measured (int, char *, int);
+
+extern void mpw_end_progress (char *, char *, int);
+
+#endif /* _SPIN_H */
diff --git a/contrib/gdb/include/mpw/stat.h b/contrib/gdb/include/mpw/stat.h
new file mode 100644
index 0000000..057b8d5
--- /dev/null
+++ b/contrib/gdb/include/mpw/stat.h
@@ -0,0 +1,75 @@
+/* The <sys/stat.h> header defines a struct that is used in the stat() and
+ * fstat functions. The information in this struct comes from the i-node of
+ * some file. These calls are the only approved way to inspect i-nodes.
+ */
+
+#ifndef _STAT_H
+#define _STAT_H
+
+#ifndef _TYPES_H /* not quite right */
+#include <sys/types.h>
+#endif
+
+struct stat {
+ dev_t st_dev; /* major/minor device number */
+ ino_t st_ino; /* i-node number */
+ mode_t st_mode; /* file mode, protection bits, etc. */
+ short int st_nlink; /* # links; TEMPORARY HACK: should be nlink_t*/
+ uid_t st_uid; /* uid of the file's owner */
+ short int st_gid; /* gid; TEMPORARY HACK: should be gid_t */
+ dev_t st_rdev;
+ off_t st_size; /* file size */
+ time_t st_atime; /* time of last access */
+ time_t st_mtime; /* time of last data modification */
+ time_t st_ctime; /* time of last file status change */
+};
+
+/* Traditional mask definitions for st_mode. */
+#define S_IFMT 0170000 /* type of file */
+#define S_IFREG 0100000 /* regular */
+#define S_IFBLK 0060000 /* block special */
+#define S_IFDIR 0040000 /* directory */
+#define S_IFCHR 0020000 /* character special */
+#define S_IFIFO 0010000 /* this is a FIFO */
+#define S_ISUID 0004000 /* set user id on execution */
+#define S_ISGID 0002000 /* set group id on execution */
+ /* next is reserved for future use */
+#define S_ISVTX 01000 /* save swapped text even after use */
+
+/* POSIX masks for st_mode. */
+#define S_IRWXU 00700 /* owner: rwx------ */
+#define S_IRUSR 00400 /* owner: r-------- */
+#define S_IWUSR 00200 /* owner: -w------- */
+#define S_IXUSR 00100 /* owner: --x------ */
+
+#define S_IRWXG 00070 /* group: ---rwx--- */
+#define S_IRGRP 00040 /* group: ---r----- */
+#define S_IWGRP 00020 /* group: ----w---- */
+#define S_IXGRP 00010 /* group: -----x--- */
+
+#define S_IRWXO 00007 /* others: ------rwx */
+#define S_IROTH 00004 /* others: ------r-- */
+#define S_IWOTH 00002 /* others: -------w- */
+#define S_IXOTH 00001 /* others: --------x */
+
+/* The following macros test st_mode (from POSIX Sec. 5.6.1.1. */
+#define S_ISREG(m) ((m & S_IFMT) == S_IFREG) /* is a reg file */
+#define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) /* is a directory */
+#define S_ISCHR(m) ((m & S_IFMT) == S_IFCHR) /* is a char spec */
+#define S_ISBLK(m) ((m & S_IFMT) == S_IFBLK) /* is a block spec */
+#define S_ISFIFO(m) ((m & S_IFMT) == S_IFIFO) /* is a pipe/FIFO */
+
+
+/* Function Prototypes. */
+#ifndef _ANSI_H
+#include <ansi.h>
+#endif
+
+_PROTOTYPE( int chmod, (const char *_path, int _mode) );
+_PROTOTYPE( int fstat, (int _fildes, struct stat *_buf) );
+_PROTOTYPE( int mkdir, (const char *_path, int _mode) );
+_PROTOTYPE( int mkfifo, (const char *_path, int _mode) );
+_PROTOTYPE( int stat , (const char *_path, struct stat *_buf) );
+_PROTOTYPE( mode_t umask, (int _cmask) );
+
+#endif /* _STAT_H */
diff --git a/contrib/gdb/include/mpw/sys/file.h b/contrib/gdb/include/mpw/sys/file.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/contrib/gdb/include/mpw/sys/file.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/contrib/gdb/include/mpw/sys/param.h b/contrib/gdb/include/mpw/sys/param.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/contrib/gdb/include/mpw/sys/param.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/contrib/gdb/include/mpw/sys/resource.h b/contrib/gdb/include/mpw/sys/resource.h
new file mode 100644
index 0000000..d39439d
--- /dev/null
+++ b/contrib/gdb/include/mpw/sys/resource.h
@@ -0,0 +1,9 @@
+#ifndef __SYS_RESOURCE_H__
+#define __SYS_RESOURCE_H__
+
+struct rusage {
+ struct timeval ru_utime;
+ struct timeval ru_stime;
+};
+
+#endif /* __SYS_RESOURCE_H__ */
diff --git a/contrib/gdb/include/mpw/sys/stat.h b/contrib/gdb/include/mpw/sys/stat.h
new file mode 100644
index 0000000..b65c72e
--- /dev/null
+++ b/contrib/gdb/include/mpw/sys/stat.h
@@ -0,0 +1,44 @@
+/* Imitation sys/stat.h. */
+
+#ifndef __SYS_STAT_H__
+#define __SYS_STAT_H__
+
+#include <sys/types.h>
+#include <time.h>
+
+struct stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ short st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ off_t st_rsize;
+ time_t st_atime;
+ int st_spare1;
+ time_t st_mtime;
+ int st_spare2;
+ time_t st_ctime;
+ int st_spare3;
+ long st_blksize;
+ long st_blocks;
+ long st_spare4[2];
+};
+
+#define S_IFMT 0170000L
+#define S_IFDIR 0040000L
+#define S_IFREG 0100000L
+#define S_IREAD 0400
+#define S_IWRITE 0200
+#define S_IEXEC 0100
+
+#define S_IFIFO 010000 /* FIFO special */
+#define S_IFCHR 020000 /* character special */
+#define S_IFBLK 030000 /* block special */
+
+int stat (char *path, struct stat *buf);
+int fstat (int fd, struct stat *buf);
+
+#endif /* __SYS_STAT_H___ */
diff --git a/contrib/gdb/include/mpw/sys/time.h b/contrib/gdb/include/mpw/sys/time.h
new file mode 100644
index 0000000..f9e4852
--- /dev/null
+++ b/contrib/gdb/include/mpw/sys/time.h
@@ -0,0 +1,13 @@
+/* Imitation sys/time.h. */
+
+#ifndef __SYS_TIME_H__
+#define __SYS_TIME_H__
+
+#include <time.h>
+
+struct timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
+#endif /* __SYS_TIME_H__ */
diff --git a/contrib/gdb/include/mpw/sys/types.h b/contrib/gdb/include/mpw/sys/types.h
new file mode 100644
index 0000000..d7d9c9f
--- /dev/null
+++ b/contrib/gdb/include/mpw/sys/types.h
@@ -0,0 +1,15 @@
+/* Imitation sys/types.h. */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <Types.h>
+
+typedef short dev_t;
+typedef short ino_t;
+typedef unsigned short mode_t;
+typedef unsigned short uid_t;
+typedef unsigned short gid_t;
+typedef long off_t;
+
+#endif /* __SYS_TYPES_H__ */
diff --git a/contrib/gdb/include/mpw/utime.h b/contrib/gdb/include/mpw/utime.h
new file mode 100644
index 0000000..e8bf66f
--- /dev/null
+++ b/contrib/gdb/include/mpw/utime.h
@@ -0,0 +1,7 @@
+
+struct utimbuf {
+ time_t actime;
+ time_t modtime;
+};
+
+int utime (char *, struct utimbuf *);
diff --git a/contrib/gdb/include/mpw/varargs.h b/contrib/gdb/include/mpw/varargs.h
new file mode 100644
index 0000000..acb9e45
--- /dev/null
+++ b/contrib/gdb/include/mpw/varargs.h
@@ -0,0 +1,9 @@
+/* varargs.h. */
+#ifndef __va_list__
+#define __va_list__
+typedef char *va_list;
+#endif
+#define va_dcl int va_alist;
+#define va_start(list) list = (char *) &va_alist
+#define va_end(list)
+#define va_arg(list,mode) ((mode *)(list += sizeof(mode)))[-1]
diff --git a/contrib/gdb/include/nlm/ChangeLog b/contrib/gdb/include/nlm/ChangeLog
new file mode 100644
index 0000000..d9ea3d0
--- /dev/null
+++ b/contrib/gdb/include/nlm/ChangeLog
@@ -0,0 +1,83 @@
+Fri May 6 13:31:04 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * external.h (nlmNAME(External_Custom_Header)): Add length,
+ dataOffset, and dataStamp field.
+ (nlmNAME(External_Cygnus_Ext_Header)): Remove.
+ * internal.h (Nlm_Internal_Custom_Header): Add hdrLength,
+ dataOffset, dataStamp and hdr fields.
+
+Fri Apr 22 11:12:39 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * external.h (struct nlmNAME(external_cygnus_ext_header)): Rename
+ from nlmNAME(external_cygnus_section_header). Change stamp field
+ to 8 bytes. Add bytes field.
+ * internal.h (nlm_internal_cygnus_ext_header): Rename from
+ nlm_internal_cygnus_section_header. Change stamp field to 8
+ bytes.
+
+Thu Apr 21 11:57:09 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * internal.h (struct nlm_internal_cygnus_section_header): Define.
+ * external.h (struct nlmNAME(external_cygnus_section_header):
+ Define.
+
+Wed Apr 20 14:27:43 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * internal.h (struct nlm_internal_custom_header): Remove
+ debugRecOffset and debugRecLength fields. Add data field.
+ * external.h (struct nlmNAME(external_custom_header)): Remove
+ debugRecOffset and debugRecLength fields.
+
+Mon Feb 7 08:28:40 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * internal.h: Change HOST_64_BIT to BFD_HOST_64_BIT.
+
+Thu Dec 2 14:14:48 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * alpha-ext.h: New file describing formats of information in Alpha
+ NetWare files.
+ * common.h: Define some non-external Alpha information.
+
+Wed Nov 17 17:38:58 1993 Sean Eric Fagan (sef@cygnus.com)
+
+ * external.h: Don't define external_fixed_header here.
+ * i386-ext.h, sparc32-ext.h: New header files to define
+ external_fixed_header for particular CPU's.
+
+Wed Oct 27 11:45:56 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * internal.h (Nlm_Internal_Extended_Header): Added fields
+ sharedDebugRecordOffset and sharedDebugRecordCount.
+ * external.h (NlmNAME(External_Extended_Header)): Likewise.
+
+ * common.h (NLM_SIGNATURE): Do not define (it's different for each
+ backend).
+
+Tue Aug 31 13:24:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * internal.h: Change length fields of type char to type unsigned
+ char.
+
+Sat Jul 31 02:12:14 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * common.h (NLM_HIBIT, NLM_HEADER_VERSION): Define.
+
+Thu Jul 22 16:09:47 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * common.h (NLM_CAT*, NLM_ARCH_SIZE, NLM_TARGET_LONG_SIZE,
+ NLM_TARGET_ADDRESS_SIZE, NLM_NAME, NlmNAME, nlmNAME): New
+ macros.
+ * external.h (TARGET_LONG_SIZE, TARGET_ADDRESS_SIZE): Remove
+ macros, convert usages to NLM_ equivalents.
+ * external.h: Use nlmNAME and NlmNAME macros to derive both
+ 32 and 64 bit versions.
+
+Mon Jul 19 22:12:40 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * (common.h, external.h, internal.h): New files for NLM/NetWare
+ support.
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/include/nlm/alpha-ext.h b/contrib/gdb/include/nlm/alpha-ext.h
new file mode 100644
index 0000000..37199dd
--- /dev/null
+++ b/contrib/gdb/include/nlm/alpha-ext.h
@@ -0,0 +1,166 @@
+/* Alpha NLM (NetWare Loadable Module) support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+ By Ian Lance Taylor, 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* An Alpha NLM starts with an instance of this structure. */
+
+struct nlm32_alpha_external_prefix_header
+{
+ /* Magic number. Must be NLM32_ALPHA_MAGIC. */
+ unsigned char magic[4];
+ /* Format descriptor. Current value is 2. */
+ unsigned char format[4];
+ /* Size of prefix header. */
+ unsigned char size[4];
+ /* Padding. */
+ unsigned char pad1[4];
+ /* More fields may be added later, supposedly. */
+};
+
+/* The external format of an Alpha NLM reloc. This is the same as an
+ Alpha ECOFF reloc. */
+
+struct nlm32_alpha_external_reloc
+{
+ unsigned char r_vaddr[8];
+ unsigned char r_symndx[4];
+ unsigned char r_bits[4];
+};
+
+/* Constants to unpack the r_bits field of a reloc. */
+
+#define RELOC_BITS0_TYPE_LITTLE 0xff
+#define RELOC_BITS0_TYPE_SH_LITTLE 0
+
+#define RELOC_BITS1_EXTERN_LITTLE 0x01
+
+#define RELOC_BITS1_OFFSET_LITTLE 0x7e
+#define RELOC_BITS1_OFFSET_SH_LITTLE 1
+
+#define RELOC_BITS1_RESERVED_LITTLE 0x80
+#define RELOC_BITS1_RESERVED_SH_LITTLE 7
+#define RELOC_BITS2_RESERVED_LITTLE 0xff
+#define RELOC_BITS2_RESERVED_SH_LEFT_LITTLE 1
+#define RELOC_BITS3_RESERVED_LITTLE 0x03
+#define RELOC_BITS3_RESERVED_SH_LEFT_LITTLE 9
+
+#define RELOC_BITS3_SIZE_LITTLE 0xfc
+#define RELOC_BITS3_SIZE_SH_LITTLE 2
+
+/* The external format of the fixed header. */
+
+typedef struct nlm32_alpha_external_fixed_header
+{
+
+ /* The signature field identifies the file as an NLM. It must contain
+ the signature string, which depends upon the NLM target. */
+
+ unsigned char signature[24];
+
+ /* The version of the header. At this time, the highest version number
+ is 4. */
+
+ unsigned char version[4];
+
+ /* The name of the module, which must be a DOS name (1-8 characters followed
+ by a period and a 1-3 character extension). The first byte is the byte
+ length of the name and the last byte is a null terminator byte. This
+ field is fixed length, and any unused bytes should be null bytes. The
+ value is set by the OUTPUT keyword to NLMLINK. */
+
+ unsigned char moduleName[14];
+
+ /* Padding to make it come out correct. */
+
+ unsigned char pad1[2];
+
+ /* The byte offset of the code image from the start of the file. */
+
+ unsigned char codeImageOffset[4];
+
+ /* The size of the code image, in bytes. */
+
+ unsigned char codeImageSize[4];
+
+ /* The byte offset of the data image from the start of the file. */
+
+ unsigned char dataImageOffset[4];
+
+ /* The size of the data image, in bytes. */
+
+ unsigned char dataImageSize[4];
+
+ /* The size of the uninitialized data region that the loader is to be
+ allocated at load time. Uninitialized data follows the initialized
+ data in the NLM address space. */
+
+ unsigned char uninitializedDataSize[4];
+
+ /* The byte offset of the custom data from the start of the file. The
+ custom data is set by the CUSTOM keyword to NLMLINK. It is possible
+ for this to be EOF if there is no custom data. */
+
+ unsigned char customDataOffset[4];
+
+ /* The size of the custom data, in bytes. */
+
+ unsigned char customDataSize[4];
+
+ /* The byte offset of the module dependencies from the start of the file.
+ The module dependencies are determined by the MODULE keyword in
+ NLMLINK. */
+
+ unsigned char moduleDependencyOffset[4];
+
+ /* The number of module dependencies at the moduleDependencyOffset. */
+
+ unsigned char numberOfModuleDependencies[4];
+
+ /* The byte offset of the relocation fixup data from the start of the file */
+
+ unsigned char relocationFixupOffset[4];
+
+ unsigned char numberOfRelocationFixups[4];
+
+ unsigned char externalReferencesOffset[4];
+
+ unsigned char numberOfExternalReferences[4];
+
+ unsigned char publicsOffset[4];
+
+ unsigned char numberOfPublics[4];
+
+ /* The byte offset of the internal debug info from the start of the file.
+ It is possible for this to be EOF if there is no debug info. */
+
+ unsigned char debugInfoOffset[4];
+
+ unsigned char numberOfDebugRecords[4];
+
+ unsigned char codeStartOffset[4];
+
+ unsigned char exitProcedureOffset[4];
+
+ unsigned char checkUnloadProcedureOffset[4];
+
+ unsigned char moduleType[4];
+
+ unsigned char flags[4];
+
+} Nlm32_alpha_External_Fixed_Header;
diff --git a/contrib/gdb/include/nlm/common.h b/contrib/gdb/include/nlm/common.h
new file mode 100644
index 0000000..e96550a
--- /dev/null
+++ b/contrib/gdb/include/nlm/common.h
@@ -0,0 +1,124 @@
+/* NLM (NetWare Loadable Module) support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is part of NLM support for BFD, and contains the portions
+ that are common to both the internal and external representations. */
+
+/* Semi-portable string concatenation in cpp.
+ The NLM_CAT4 hack is to avoid a problem with some strict ANSI C
+ preprocessors. The problem is, "32_" or "64_" are not a valid
+ preprocessing tokens, and we don't want extra underscores (e.g.,
+ "nlm_32_"). The XNLM_CAT2 macro will cause the inner NLM_CAT macros
+ to be evaluated first, producing still-valid pp-tokens. Then the
+ final concatenation can be done. (Sigh.) */
+
+#ifdef SABER
+# define NLM_CAT(a,b) a##b
+# define NLM_CAT3(a,b,c) a##b##c
+# define NLM_CAT4(a,b,c,d) a##b##c##d
+#else
+# ifdef __STDC__
+# define NLM_CAT(a,b) a##b
+# define NLM_CAT3(a,b,c) a##b##c
+# define XNLM_CAT2(a,b) NLM_CAT(a,b)
+# define NLM_CAT4(a,b,c,d) XNLM_CAT2(NLM_CAT(a,b),NLM_CAT(c,d))
+# else
+# define NLM_CAT(a,b) a/**/b
+# define NLM_CAT3(a,b,c) a/**/b/**/c
+# define NLM_CAT4(a,b,c,d) a/**/b/**/c/**/d
+# endif
+#endif
+
+/* If NLM_ARCH_SIZE is not defined, default to 32. NLM_ARCH_SIZE is
+ optionally defined by the application. */
+
+#ifndef NLM_ARCH_SIZE
+# define NLM_ARCH_SIZE 32
+#endif
+
+#if NLM_ARCH_SIZE == 32
+# define NLM_TARGET_LONG_SIZE 4
+# define NLM_TARGET_ADDRESS_SIZE 4
+# define NLM_NAME(x,y) NLM_CAT4(x,32,_,y)
+# define NLM_HIBIT (((bfd_vma) 1) << 31)
+#endif
+#if NLM_ARCH_SIZE == 64
+# define NLM_TARGET_LONG_SIZE 8
+# define NLM_TARGET_ADDRESS_SIZE 8
+# define NLM_NAME(x,y) NLM_CAT4(x,64,_,y)
+# define NLM_HIBIT (((bfd_vma) 1) << 63)
+#endif
+
+#define NlmNAME(X) NLM_NAME(Nlm,X)
+#define nlmNAME(X) NLM_NAME(nlm,X)
+
+/* Give names to things that should not change. */
+
+#define NLM_MAX_DESCRIPTION_LENGTH 127
+#define NLM_MAX_SCREEN_NAME_LENGTH 71
+#define NLM_MAX_THREAD_NAME_LENGTH 71
+#define NLM_MAX_COPYRIGHT_MESSAGE_LENGTH 255
+#define NLM_OTHER_DATA_LENGTH 400 /* FIXME */
+#define NLM_OLD_THREAD_NAME_LENGTH 5
+#define NLM_SIGNATURE_SIZE 24
+#define NLM_HEADER_VERSION 4
+#define NLM_MODULE_NAME_SIZE 14
+#define NLM_DEFAULT_STACKSIZE (8 * 1024)
+
+/* Alpha information. This should probably be in a separate Alpha
+ header file, but it can't go in alpha-ext.h because some of it is
+ needed by nlmconv.c. */
+
+/* Magic number in Alpha prefix header. */
+#define NLM32_ALPHA_MAGIC (0x83561840)
+
+/* The r_type field in an Alpha reloc is one of the following values. */
+#define ALPHA_R_IGNORE 0
+#define ALPHA_R_REFLONG 1
+#define ALPHA_R_REFQUAD 2
+#define ALPHA_R_GPREL32 3
+#define ALPHA_R_LITERAL 4
+#define ALPHA_R_LITUSE 5
+#define ALPHA_R_GPDISP 6
+#define ALPHA_R_BRADDR 7
+#define ALPHA_R_HINT 8
+#define ALPHA_R_SREL16 9
+#define ALPHA_R_SREL32 10
+#define ALPHA_R_SREL64 11
+#define ALPHA_R_OP_PUSH 12
+#define ALPHA_R_OP_STORE 13
+#define ALPHA_R_OP_PSUB 14
+#define ALPHA_R_OP_PRSHIFT 15
+#define ALPHA_R_GPVALUE 16
+#define ALPHA_R_NW_RELOC 250
+
+/* A local reloc, other than ALPHA_R_GPDISP or ALPHA_R_IGNORE, must be
+ against one of these symbol indices. */
+#define ALPHA_RELOC_SECTION_TEXT 1
+#define ALPHA_RELOC_SECTION_DATA 3
+
+/* An ALPHA_R_NW_RELOC has one of these values in the size field. If
+ it is SETGP, the r_vaddr field holds the GP value to use. If it is
+ LITA, the r_vaddr field holds the address of the .lita section and
+ the r_symndx field holds the size of the .lita section. */
+#define ALPHA_R_NW_RELOC_SETGP 1
+#define ALPHA_R_NW_RELOC_LITA 2
diff --git a/contrib/gdb/include/nlm/external.h b/contrib/gdb/include/nlm/external.h
new file mode 100644
index 0000000..f77a5bb
--- /dev/null
+++ b/contrib/gdb/include/nlm/external.h
@@ -0,0 +1,174 @@
+/* NLM (NetWare Loadable Module) support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is part of NLM support for BFD, and contains the portions
+ that describe how NLM is represented externally by the BFD library.
+ I.E. it describes the in-file representation of NLM. It requires
+ the nlm/common.h file which contains the portions that are common to
+ both the internal and external representations.
+
+ Note that an NLM header consists of three parts:
+
+ (1) A fixed length header that has specific fields of known length,
+ at specific offsets in the file.
+
+ (2) A variable length header that has specific fields in a specific
+ order, but some fields may be variable length.
+
+ (3) A auxiliary header that has various optional fields in no specific
+ order. There is no way to identify the end of the auxiliary headers
+ except by finding a header without a recognized 'stamp'.
+
+ The exact format of the fixed length header unfortunately varies
+ from one NLM target to another, due to padding. Each target
+ defines the correct external format in a separate header file.
+
+*/
+
+/* NLM Header */
+
+/* The version header is one of the optional auxiliary headers and
+ follows the fixed length and variable length NLM headers. */
+
+typedef struct nlmNAME(external_version_header)
+{
+
+ /* The header is recognized by "VeRsIoN#" in the stamp field. */
+ char stamp[8];
+
+ unsigned char majorVersion[NLM_TARGET_LONG_SIZE];
+
+ unsigned char minorVersion[NLM_TARGET_LONG_SIZE];
+
+ unsigned char revision[NLM_TARGET_LONG_SIZE];
+
+ unsigned char year[NLM_TARGET_LONG_SIZE];
+
+ unsigned char month[NLM_TARGET_LONG_SIZE];
+
+ unsigned char day[NLM_TARGET_LONG_SIZE];
+
+} NlmNAME(External_Version_Header);
+
+
+typedef struct nlmNAME(external_copyright_header)
+{
+
+ /* The header is recognized by "CoPyRiGhT=" in the stamp field. */
+
+ char stamp[10];
+
+ unsigned char copyrightMessageLength[1];
+
+ /* There is a variable length field here called 'copyrightMessage'
+ that is the length specified by copyrightMessageLength. */
+
+} NlmNAME(External_Copyright_Header);
+
+
+typedef struct nlmNAME(external_extended_header)
+{
+
+ /* The header is recognized by "MeSsAgEs" in the stamp field. */
+
+ char stamp[8];
+
+ unsigned char languageID[NLM_TARGET_LONG_SIZE];
+
+ unsigned char messageFileOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char messageFileLength[NLM_TARGET_LONG_SIZE];
+
+ unsigned char messageCount[NLM_TARGET_LONG_SIZE];
+
+ unsigned char helpFileOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char helpFileLength[NLM_TARGET_LONG_SIZE];
+
+ unsigned char RPCDataOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char RPCDataLength[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedCodeOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedCodeLength[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedDataOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedDataLength[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedRelocationFixupOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedRelocationFixupCount[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedExternalReferenceOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedExternalReferenceCount[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedPublicsOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedPublicsCount[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedDebugRecordOffset[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedDebugRecordCount[NLM_TARGET_LONG_SIZE];
+
+ unsigned char sharedInitializationOffset[NLM_TARGET_ADDRESS_SIZE];
+
+ unsigned char SharedExitProcedureOffset[NLM_TARGET_ADDRESS_SIZE];
+
+ unsigned char productID[NLM_TARGET_LONG_SIZE];
+
+ unsigned char reserved0[NLM_TARGET_LONG_SIZE];
+
+ unsigned char reserved1[NLM_TARGET_LONG_SIZE];
+
+ unsigned char reserved2[NLM_TARGET_LONG_SIZE];
+
+ unsigned char reserved3[NLM_TARGET_LONG_SIZE];
+
+ unsigned char reserved4[NLM_TARGET_LONG_SIZE];
+
+ unsigned char reserved5[NLM_TARGET_LONG_SIZE];
+
+} NlmNAME(External_Extended_Header);
+
+
+typedef struct nlmNAME(external_custom_header)
+{
+
+ /* The header is recognized by "CuStHeAd" in the stamp field. */
+ char stamp[8];
+
+ /* Length of this header. */
+ unsigned char length[NLM_TARGET_LONG_SIZE];
+
+ /* Offset to data. */
+ unsigned char dataOffset[NLM_TARGET_LONG_SIZE];
+
+ /* Length of data. */
+ unsigned char dataLength[NLM_TARGET_LONG_SIZE];
+
+ /* Stamp for this customer header--we recognize "CyGnUsEx". */
+ char dataStamp[8];
+
+} NlmNAME(External_Custom_Header);
diff --git a/contrib/gdb/include/nlm/i386-ext.h b/contrib/gdb/include/nlm/i386-ext.h
new file mode 100644
index 0000000..d33ad2d
--- /dev/null
+++ b/contrib/gdb/include/nlm/i386-ext.h
@@ -0,0 +1,116 @@
+/* i386 NLM (NetWare Loadable Module) support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The external format of the fixed header. */
+
+typedef struct nlm32_i386_external_fixed_header
+{
+
+ /* The signature field identifies the file as an NLM. It must contain
+ the signature string, which depends upon the NLM target. */
+
+ unsigned char signature[24];
+
+ /* The version of the header. At this time, the highest version number
+ is 4. */
+
+ unsigned char version[4];
+
+ /* The name of the module, which must be a DOS name (1-8 characters followed
+ by a period and a 1-3 character extension). The first byte is the byte
+ length of the name and the last byte is a null terminator byte. This
+ field is fixed length, and any unused bytes should be null bytes. The
+ value is set by the OUTPUT keyword to NLMLINK. */
+
+ unsigned char moduleName[14];
+
+ /* The byte offset of the code image from the start of the file. */
+
+ unsigned char codeImageOffset[4];
+
+ /* The size of the code image, in bytes. */
+
+ unsigned char codeImageSize[4];
+
+ /* The byte offset of the data image from the start of the file. */
+
+ unsigned char dataImageOffset[4];
+
+ /* The size of the data image, in bytes. */
+
+ unsigned char dataImageSize[4];
+
+ /* The size of the uninitialized data region that the loader is to be
+ allocated at load time. Uninitialized data follows the initialized
+ data in the NLM address space. */
+
+ unsigned char uninitializedDataSize[4];
+
+ /* The byte offset of the custom data from the start of the file. The
+ custom data is set by the CUSTOM keyword to NLMLINK. It is possible
+ for this to be EOF if there is no custom data. */
+
+ unsigned char customDataOffset[4];
+
+ /* The size of the custom data, in bytes. */
+
+ unsigned char customDataSize[4];
+
+ /* The byte offset of the module dependencies from the start of the file.
+ The module dependencies are determined by the MODULE keyword in
+ NLMLINK. */
+
+ unsigned char moduleDependencyOffset[4];
+
+ /* The number of module dependencies at the moduleDependencyOffset. */
+
+ unsigned char numberOfModuleDependencies[4];
+
+ /* The byte offset of the relocation fixup data from the start of the file */
+
+ unsigned char relocationFixupOffset[4];
+
+ unsigned char numberOfRelocationFixups[4];
+
+ unsigned char externalReferencesOffset[4];
+
+ unsigned char numberOfExternalReferences[4];
+
+ unsigned char publicsOffset[4];
+
+ unsigned char numberOfPublics[4];
+
+ /* The byte offset of the internal debug info from the start of the file.
+ It is possible for this to be EOF if there is no debug info. */
+
+ unsigned char debugInfoOffset[4];
+
+ unsigned char numberOfDebugRecords[4];
+
+ unsigned char codeStartOffset[4];
+
+ unsigned char exitProcedureOffset[4];
+
+ unsigned char checkUnloadProcedureOffset[4];
+
+ unsigned char moduleType[4];
+
+ unsigned char flags[4];
+
+} Nlm32_i386_External_Fixed_Header;
diff --git a/contrib/gdb/include/nlm/internal.h b/contrib/gdb/include/nlm/internal.h
new file mode 100644
index 0000000..dd27dc4
--- /dev/null
+++ b/contrib/gdb/include/nlm/internal.h
@@ -0,0 +1,309 @@
+/* NLM (NetWare Loadable Module) support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+ Written by Fred Fish @ 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
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+/* This file is part of NLM support for BFD, and contains the portions
+ that describe how NLM is represented internally in the BFD library.
+ I.E. it describes the in-memory representation of NLM. It requires
+ the nlm/common.h file which contains the portions that are common to
+ both the internal and external representations. */
+
+#if 0
+
+/* Types used by various structures, functions, etc. */
+
+typedef unsigned long Nlm32_Addr; /* Unsigned program address */
+typedef unsigned long Nlm32_Off; /* Unsigned file offset */
+typedef long Nlm32_Sword; /* Signed large integer */
+typedef unsigned long Nlm32_Word; /* Unsigned large integer */
+typedef unsigned short Nlm32_Half; /* Unsigned medium integer */
+typedef unsigned char Nlm32_Char; /* Unsigned tiny integer */
+
+#ifdef BFD_HOST_64_BIT
+typedef unsigned BFD_HOST_64_BIT Nlm64_Addr;
+typedef unsigned BFD_HOST_64_BIT Nlm64_Off;
+typedef BFD_HOST_64_BIT Nlm64_Sxword;
+typedef unsigned BFD_HOST_64_BIT Nlm64_Xword;
+#endif
+typedef long Nlm64_Sword;
+typedef unsigned long Nlm64_Word;
+typedef unsigned short Nlm64_Half;
+
+#endif /* 0 */
+
+/* This structure contains the internal form of the portion of the NLM
+ header that is fixed length. */
+
+typedef struct nlm_internal_fixed_header
+{
+ /* The signature field identifies the file as an NLM. It must contain
+ the signature string, which depends upon the NLM target. */
+
+ char signature[NLM_SIGNATURE_SIZE];
+
+ /* The version of the header. At this time, the highest version number
+ is 4. */
+
+ long version;
+
+ /* The name of the module, which must be a DOS name (1-8 characters followed
+ by a period and a 1-3 character extension. The first byte is the byte
+ length of the name and the last byte is a null terminator byte. This
+ field is fixed length, and any unused bytes should be null bytes. The
+ value is set by the OUTPUT keyword to NLMLINK. */
+
+ char moduleName[NLM_MODULE_NAME_SIZE];
+
+ /* The byte offset of the code image from the start of the file. */
+
+ file_ptr codeImageOffset;
+
+ /* The size of the code image, in bytes. */
+
+ bfd_size_type codeImageSize;
+
+ /* The byte offset of the data image from the start of the file. */
+
+ file_ptr dataImageOffset;
+
+ /* The size of the data image, in bytes. */
+
+ bfd_size_type dataImageSize;
+
+ /* The size of the uninitialized data region that the loader is to be
+ allocated at load time. Uninitialized data follows the initialized
+ data in the NLM address space. */
+
+ bfd_size_type uninitializedDataSize;
+
+ /* The byte offset of the custom data from the start of the file. The
+ custom data is set by the CUSTOM keyword to NLMLINK. */
+
+ file_ptr customDataOffset;
+
+ /* The size of the custom data, in bytes. */
+
+ bfd_size_type customDataSize;
+
+ /* The byte offset of the module dependencies from the start of the file.
+ The module dependencies are determined by the MODULE keyword in
+ NLMLINK. */
+
+ file_ptr moduleDependencyOffset;
+
+ /* The number of module dependencies at the moduleDependencyOffset. */
+
+ long numberOfModuleDependencies;
+
+ /* The byte offset of the relocation fixup data from the start of the file */
+
+ file_ptr relocationFixupOffset;
+ long numberOfRelocationFixups;
+ file_ptr externalReferencesOffset;
+ long numberOfExternalReferences;
+ file_ptr publicsOffset;
+ long numberOfPublics;
+ file_ptr debugInfoOffset;
+ long numberOfDebugRecords;
+ file_ptr codeStartOffset;
+ file_ptr exitProcedureOffset;
+ file_ptr checkUnloadProcedureOffset;
+ long moduleType;
+ long flags;
+} Nlm_Internal_Fixed_Header;
+
+#define nlm32_internal_fixed_header nlm_internal_fixed_header
+#define Nlm32_Internal_Fixed_Header Nlm_Internal_Fixed_Header
+#define nlm64_internal_fixed_header nlm_internal_fixed_header
+#define Nlm64_Internal_Fixed_Header Nlm_Internal_Fixed_Header
+
+/* This structure contains the portions of the NLM header that are either
+ variable in size in the external representation, or else are not at a
+ fixed offset relative to the start of the NLM header due to preceding
+ variable sized fields.
+
+ Note that all the fields must exist in the external header, and in
+ the order used here (the same order is used in the internal form
+ for consistency, not out of necessity). */
+
+typedef struct nlm_internal_variable_header
+{
+
+ /* The descriptionLength field contains the length of the text in
+ descriptionText, excluding the null terminator. The descriptionText
+ field contains the NLM description obtained from the DESCRIPTION
+ keyword in NLMLINK plus the null byte terminator. The descriptionText
+ can be up to NLM_MAX_DESCRIPTION_LENGTH characters. */
+
+ unsigned char descriptionLength;
+ char descriptionText[NLM_MAX_DESCRIPTION_LENGTH + 1];
+
+ /* The stackSize field contains the size of the stack in bytes, as
+ specified by the STACK or STACKSIZE keyword in NLMLINK. If no size
+ is specified, the default is NLM_DEFAULT_STACKSIZE. */
+
+ long stackSize;
+
+ /* The reserved field is included only for completeness. It should contain
+ zero. */
+
+ long reserved;
+
+ /* This field is fixed length, should contain " LONG" (note leading
+ space), and is unused. */
+
+ char oldThreadName[NLM_OLD_THREAD_NAME_LENGTH];
+
+ /* The screenNameLength field contains the length of the actual text stored
+ in the screenName field, excluding the null byte terminator. The
+ screenName field contains the screen name as specified by the SCREENNAME
+ keyword in NLMLINK, and can be up to NLM_MAX_SCREEN_NAME_LENGTH
+ characters. */
+
+ unsigned char screenNameLength;
+ char screenName[NLM_MAX_SCREEN_NAME_LENGTH + 1];
+
+ /* The threadNameLength field contains the length of the actual text stored
+ in the threadName field, excluding the null byte terminator. The
+ threadName field contains the thread name as specified by the THREADNAME
+ keyword in NLMLINK, and can be up to NLM_MAX_THREAD_NAME_LENGTH
+ characters. */
+
+ unsigned char threadNameLength;
+ char threadName[NLM_MAX_THREAD_NAME_LENGTH + 1];
+
+} Nlm_Internal_Variable_Header;
+
+#define nlm32_internal_variable_header nlm_internal_variable_header
+#define Nlm32_Internal_Variable_Header Nlm_Internal_Variable_Header
+#define nlm64_internal_variable_header nlm_internal_variable_header
+#define Nlm64_Internal_Variable_Header Nlm_Internal_Variable_Header
+
+/* The version header is one of the optional auxiliary headers and
+ follows the fixed length and variable length NLM headers. */
+
+typedef struct nlm_internal_version_header
+{
+ /* The header is recognized by "VeRsIoN#" in the stamp field. */
+ char stamp[8];
+ long majorVersion;
+ long minorVersion;
+ long revision;
+ long year;
+ long month;
+ long day;
+} Nlm_Internal_Version_Header;
+
+#define nlm32_internal_version_header nlm_internal_version_header
+#define Nlm32_Internal_Version_Header Nlm_Internal_Version_Header
+#define nlm64_internal_version_header nlm_internal_version_header
+#define Nlm64_Internal_Version_Header Nlm_Internal_Version_Header
+
+typedef struct nlm_internal_copyright_header
+{
+ /* The header is recognized by "CoPyRiGhT=" in the stamp field. */
+ char stamp[10];
+ unsigned char copyrightMessageLength;
+ char copyrightMessage[NLM_MAX_COPYRIGHT_MESSAGE_LENGTH];
+} Nlm_Internal_Copyright_Header;
+
+#define nlm32_internal_copyright_header nlm_internal_copyright_header
+#define Nlm32_Internal_Copyright_Header Nlm_Internal_Copyright_Header
+#define nlm64_internal_copyright_header nlm_internal_copyright_header
+#define Nlm64_Internal_Copyright_Header Nlm_Internal_Copyright_Header
+
+typedef struct nlm_internal_extended_header
+{
+ /* The header is recognized by "MeSsAgEs" in the stamp field. */
+ char stamp[8];
+ long languageID;
+ file_ptr messageFileOffset;
+ bfd_size_type messageFileLength;
+ long messageCount;
+ file_ptr helpFileOffset;
+ bfd_size_type helpFileLength;
+ file_ptr RPCDataOffset;
+ bfd_size_type RPCDataLength;
+ file_ptr sharedCodeOffset;
+ bfd_size_type sharedCodeLength;
+ file_ptr sharedDataOffset;
+ bfd_size_type sharedDataLength;
+ file_ptr sharedRelocationFixupOffset;
+ long sharedRelocationFixupCount;
+ file_ptr sharedExternalReferenceOffset;
+ long sharedExternalReferenceCount;
+ file_ptr sharedPublicsOffset;
+ long sharedPublicsCount;
+ file_ptr sharedDebugRecordOffset;
+ long sharedDebugRecordCount;
+ bfd_vma SharedInitializationOffset;
+ bfd_vma SharedExitProcedureOffset;
+ long productID;
+ long reserved0;
+ long reserved1;
+ long reserved2;
+ long reserved3;
+ long reserved4;
+ long reserved5;
+} Nlm_Internal_Extended_Header;
+
+#define nlm32_internal_extended_header nlm_internal_extended_header
+#define Nlm32_Internal_Extended_Header Nlm_Internal_Extended_Header
+#define nlm64_internal_extended_header nlm_internal_extended_header
+#define Nlm64_Internal_Extended_Header Nlm_Internal_Extended_Header
+
+/* The format of a custom header as stored internally is different
+ from the external format. This is how we store a custom header
+ which we do not recognize. */
+
+typedef struct nlm_internal_custom_header
+{
+ /* The header is recognized by "CuStHeAd" in the stamp field. */
+ char stamp[8];
+ bfd_size_type hdrLength;
+ file_ptr dataOffset;
+ bfd_size_type dataLength;
+ char dataStamp[8];
+ PTR hdr;
+} Nlm_Internal_Custom_Header;
+
+#define nlm32_internal_custom_header nlm_internal_custom_header
+#define Nlm32_Internal_Custom_Header Nlm_Internal_Custom_Header
+#define nlm64_internal_custom_header nlm_internal_custom_header
+#define Nlm64_Internal_Custom_Header Nlm_Internal_Custom_Header
+
+/* The internal Cygnus header is written out externally as a custom
+ header. We don't try to replicate that structure here. */
+
+typedef struct nlm_internal_cygnus_ext_header
+{
+ /* The header is recognized by "CyGnUsEx" in the stamp field. */
+ char stamp[8];
+ /* File location of debugging information. */
+ file_ptr offset;
+ /* Length of debugging information. */
+ bfd_size_type length;
+} Nlm_Internal_Cygnus_Ext_Header;
+
+#define nlm32_internal_cygnus_ext_header nlm_internal_cygnus_ext_header
+#define Nlm32_Internal_Cygnus_Ext_Header Nlm_Internal_Cygnus_Ext_Header
+#define nlm64_internal_cygnus_ext_header nlm_internal_cygnus_ext_header
+#define Nlm64_Internal_Cygnus_Ext_Header Nlm_Internal_Cygnus_Ext_Header
diff --git a/contrib/gdb/include/nlm/ppc-ext.h b/contrib/gdb/include/nlm/ppc-ext.h
new file mode 100644
index 0000000..0aae107
--- /dev/null
+++ b/contrib/gdb/include/nlm/ppc-ext.h
@@ -0,0 +1,163 @@
+/* PowerPC NLM (NetWare Loadable Module) support for BFD.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef OLDFORMAT
+
+/* The format of a PowerPC NLM changed. These structures are only
+ used in the old format. */
+
+/* A PowerPC NLM starts with an instance of this structure. */
+
+struct nlm32_powerpc_external_prefix_header
+{
+ /* Signature. Must be "AppleNLM". */
+ char signature[8];
+ /* Version number. Current value is 1. */
+ unsigned char headerVersion[4];
+ /* ??. Should be set to 0. */
+ unsigned char origins[4];
+ /* File creation date in standard Unix time format (seconds since
+ 1/1/70). */
+ unsigned char date[4];
+};
+
+#define NLM32_POWERPC_SIGNATURE "AppleNLM"
+#define NLM32_POWERPC_HEADER_VERSION 1
+
+/* The external format of a PowerPC NLM reloc. This is the same as an
+ XCOFF dynamic reloc. */
+
+struct nlm32_powerpc_external_reloc
+{
+ /* Address. */
+ unsigned char l_vaddr[4];
+ /* Symbol table index. This is 0 for .text and 1 for .data. 2
+ means .bss, but I don't know if it is used. In XCOFF, larger
+ numbers are indices into the dynamic symbol table, but they are
+ presumably not used in an NLM. */
+ unsigned char l_symndx[4];
+ /* Relocation type. */
+ unsigned char l_rtype[2];
+ /* Section number being relocated. */
+ unsigned char l_rsecnm[2];
+};
+
+#endif /* OLDFORMAT */
+
+/* The external format of the fixed header. */
+
+typedef struct nlm32_powerpc_external_fixed_header
+{
+
+ /* The signature field identifies the file as an NLM. It must contain
+ the signature string, which depends upon the NLM target. */
+
+ unsigned char signature[24];
+
+ /* The version of the header. At this time, the highest version number
+ is 4. */
+
+ unsigned char version[4];
+
+ /* The name of the module, which must be a DOS name (1-8 characters followed
+ by a period and a 1-3 character extension). The first byte is the byte
+ length of the name and the last byte is a null terminator byte. This
+ field is fixed length, and any unused bytes should be null bytes. The
+ value is set by the OUTPUT keyword to NLMLINK. */
+
+ unsigned char moduleName[14];
+
+ /* Padding to make it come out correct. */
+
+ unsigned char pad1[2];
+
+ /* The byte offset of the code image from the start of the file. */
+
+ unsigned char codeImageOffset[4];
+
+ /* The size of the code image, in bytes. */
+
+ unsigned char codeImageSize[4];
+
+ /* The byte offset of the data image from the start of the file. */
+
+ unsigned char dataImageOffset[4];
+
+ /* The size of the data image, in bytes. */
+
+ unsigned char dataImageSize[4];
+
+ /* The size of the uninitialized data region that the loader is to be
+ allocated at load time. Uninitialized data follows the initialized
+ data in the NLM address space. */
+
+ unsigned char uninitializedDataSize[4];
+
+ /* The byte offset of the custom data from the start of the file. The
+ custom data is set by the CUSTOM keyword to NLMLINK. It is possible
+ for this to be EOF if there is no custom data. */
+
+ unsigned char customDataOffset[4];
+
+ /* The size of the custom data, in bytes. */
+
+ unsigned char customDataSize[4];
+
+ /* The byte offset of the module dependencies from the start of the file.
+ The module dependencies are determined by the MODULE keyword in
+ NLMLINK. */
+
+ unsigned char moduleDependencyOffset[4];
+
+ /* The number of module dependencies at the moduleDependencyOffset. */
+
+ unsigned char numberOfModuleDependencies[4];
+
+ /* The byte offset of the relocation fixup data from the start of the file */
+
+ unsigned char relocationFixupOffset[4];
+
+ unsigned char numberOfRelocationFixups[4];
+
+ unsigned char externalReferencesOffset[4];
+
+ unsigned char numberOfExternalReferences[4];
+
+ unsigned char publicsOffset[4];
+
+ unsigned char numberOfPublics[4];
+
+ /* The byte offset of the internal debug info from the start of the file.
+ It is possible for this to be EOF if there is no debug info. */
+
+ unsigned char debugInfoOffset[4];
+
+ unsigned char numberOfDebugRecords[4];
+
+ unsigned char codeStartOffset[4];
+
+ unsigned char exitProcedureOffset[4];
+
+ unsigned char checkUnloadProcedureOffset[4];
+
+ unsigned char moduleType[4];
+
+ unsigned char flags[4];
+
+} Nlm32_powerpc_External_Fixed_Header;
diff --git a/contrib/gdb/include/nlm/sparc32-ext.h b/contrib/gdb/include/nlm/sparc32-ext.h
new file mode 100644
index 0000000..0deb2de
--- /dev/null
+++ b/contrib/gdb/include/nlm/sparc32-ext.h
@@ -0,0 +1,120 @@
+/* SPARC NLM (NetWare Loadable Module) support for BFD.
+ Copyright (C) 1993 Free Software Foundation, Inc.
+
+This file is part of BFD, the Binary File Descriptor library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The external format of the fixed header. */
+
+typedef struct nlm32_sparc_external_fixed_header
+{
+
+ /* The signature field identifies the file as an NLM. It must contain
+ the signature string, which depends upon the NLM target. */
+
+ unsigned char signature[24];
+
+ /* The version of the header. At this time, the highest version number
+ is 4. */
+
+ unsigned char version[4];
+
+ /* The name of the module, which must be a DOS name (1-8 characters followed
+ by a period and a 1-3 character extension). The first byte is the byte
+ length of the name and the last byte is a null terminator byte. This
+ field is fixed length, and any unused bytes should be null bytes. The
+ value is set by the OUTPUT keyword to NLMLINK. */
+
+ unsigned char moduleName[14];
+
+ /* Padding to make it come out correct. */
+
+ unsigned char pad1[2];
+
+ /* The byte offset of the code image from the start of the file. */
+
+ unsigned char codeImageOffset[4];
+
+ /* The size of the code image, in bytes. */
+
+ unsigned char codeImageSize[4];
+
+ /* The byte offset of the data image from the start of the file. */
+
+ unsigned char dataImageOffset[4];
+
+ /* The size of the data image, in bytes. */
+
+ unsigned char dataImageSize[4];
+
+ /* The size of the uninitialized data region that the loader is to be
+ allocated at load time. Uninitialized data follows the initialized
+ data in the NLM address space. */
+
+ unsigned char uninitializedDataSize[4];
+
+ /* The byte offset of the custom data from the start of the file. The
+ custom data is set by the CUSTOM keyword to NLMLINK. It is possible
+ for this to be EOF if there is no custom data. */
+
+ unsigned char customDataOffset[4];
+
+ /* The size of the custom data, in bytes. */
+
+ unsigned char customDataSize[4];
+
+ /* The byte offset of the module dependencies from the start of the file.
+ The module dependencies are determined by the MODULE keyword in
+ NLMLINK. */
+
+ unsigned char moduleDependencyOffset[4];
+
+ /* The number of module dependencies at the moduleDependencyOffset. */
+
+ unsigned char numberOfModuleDependencies[4];
+
+ /* The byte offset of the relocation fixup data from the start of the file */
+
+ unsigned char relocationFixupOffset[4];
+
+ unsigned char numberOfRelocationFixups[4];
+
+ unsigned char externalReferencesOffset[4];
+
+ unsigned char numberOfExternalReferences[4];
+
+ unsigned char publicsOffset[4];
+
+ unsigned char numberOfPublics[4];
+
+ /* The byte offset of the internal debug info from the start of the file.
+ It is possible for this to be EOF if there is no debug info. */
+
+ unsigned char debugInfoOffset[4];
+
+ unsigned char numberOfDebugRecords[4];
+
+ unsigned char codeStartOffset[4];
+
+ unsigned char exitProcedureOffset[4];
+
+ unsigned char checkUnloadProcedureOffset[4];
+
+ unsigned char moduleType[4];
+
+ unsigned char flags[4];
+
+} Nlm32_sparc_External_Fixed_Header;
diff --git a/contrib/gdb/include/oasys.h b/contrib/gdb/include/oasys.h
new file mode 100644
index 0000000..867d250
--- /dev/null
+++ b/contrib/gdb/include/oasys.h
@@ -0,0 +1,152 @@
+/* Oasys object format header file for BFD.
+ Contributed by Cygnus Support. */
+
+#define OASYS_MAX_SEC_COUNT 16
+/* **** */
+
+typedef struct oasys_archive_header {
+ unsigned int version;
+ char create_date[12];
+ char revision_date[12];
+ unsigned int mod_count;
+ file_ptr mod_tbl_offset;
+ unsigned int sym_tbl_size;
+ unsigned int sym_count;
+ file_ptr sym_tbl_offset;
+ unsigned int xref_count;
+ file_ptr xref_lst_offset;
+} oasys_archive_header_type;
+
+typedef struct oasys_extarchive_header {
+ bfd_byte version[4];
+ bfd_byte create_date[12];
+ bfd_byte revision_date[12];
+ bfd_byte mod_count[4];
+ bfd_byte mod_tbl_offset[4];
+ bfd_byte sym_tbl_size[4];
+ bfd_byte sym_count[4];
+ bfd_byte sym_tbl_offset[4];
+ bfd_byte xref_count[4];
+ bfd_byte xref_lst_offset[4];
+} oasys_extarchive_header_type;
+
+typedef struct oasys_module_table {
+ int mod_number;
+ char mod_date[12];
+ unsigned int mod_size;
+ unsigned int dep_count;
+ unsigned int depee_count;
+ file_ptr file_offset;
+ unsigned int sect_count;
+ char *module_name;
+ unsigned int module_name_size;
+} oasys_module_table_type;
+
+
+typedef struct oasys_extmodule_table_a {
+ bfd_byte mod_number[4];
+ bfd_byte mod_date[12];
+ bfd_byte mod_size[4];
+ bfd_byte dep_count[4];
+ bfd_byte depee_count[4];
+ bfd_byte sect_count[4];
+ bfd_byte file_offset[4];
+ bfd_byte mod_name[32];
+} oasys_extmodule_table_type_a_type;
+
+typedef struct oasys_extmodule_table_b {
+ bfd_byte mod_number[4];
+ bfd_byte mod_date[12];
+ bfd_byte mod_size[4];
+ bfd_byte dep_count[4];
+ bfd_byte depee_count[4];
+ bfd_byte sect_count[4];
+ bfd_byte file_offset[4];
+ bfd_byte mod_name_length[4];
+} oasys_extmodule_table_type_b_type;
+
+
+typedef enum oasys_record {
+ oasys_record_is_end_enum = 0,
+ oasys_record_is_data_enum = 1,
+ oasys_record_is_symbol_enum = 2,
+ oasys_record_is_header_enum = 3,
+ oasys_record_is_named_section_enum = 4,
+ oasys_record_is_com_enum = 5,
+ oasys_record_is_debug_enum = 6,
+ oasys_record_is_section_enum = 7,
+ oasys_record_is_debug_file_enum = 8,
+ oasys_record_is_module_enum = 9,
+ oasys_record_is_local_enum = 10
+} oasys_record_enum_type;
+
+
+
+typedef struct oasys_record_header {
+ unsigned char length;
+ unsigned char check_sum;
+ unsigned char type;
+ unsigned char fill;
+} oasys_record_header_type;
+
+typedef struct oasys_data_record {
+ oasys_record_header_type header;
+ unsigned char relb;
+ bfd_byte addr[4];
+ /* maximum total size of data record is 255 bytes */
+ bfd_byte data[246];
+} oasys_data_record_type;
+
+typedef struct oasys_header_record {
+ oasys_record_header_type header;
+ unsigned char version_number;
+ unsigned char rev_number;
+ char module_name[26-6];
+ char description[64-26];
+} oasys_header_record_type;
+
+#define OASYS_VERSION_NUMBER 0
+#define OASYS_REV_NUMBER 0
+
+typedef struct oasys_symbol_record {
+ oasys_record_header_type header;
+ unsigned char relb;
+ bfd_byte value[4];
+ bfd_byte refno[2];
+ char name[64];
+} oasys_symbol_record_type;
+
+#define RELOCATION_PCREL_BIT 0x80
+#define RELOCATION_32BIT_BIT 0x40
+#define RELOCATION_TYPE_BITS 0x30
+#define RELOCATION_TYPE_ABS 0x00
+#define RELOCATION_TYPE_REL 0x10
+#define RELOCATION_TYPE_UND 0x20
+#define RELOCATION_TYPE_COM 0x30
+#define RELOCATION_SECT_BITS 0x0f
+
+typedef struct oasys_section_record {
+ oasys_record_header_type header;
+ unsigned char relb;
+ bfd_byte value[4];
+ bfd_byte vma[4];
+ bfd_byte fill[3];
+} oasys_section_record_type;
+
+typedef struct oasys_end_record {
+ oasys_record_header_type header;
+ unsigned char relb;
+ bfd_byte entry[4];
+ bfd_byte fill[2];
+ bfd_byte zero;
+} oasys_end_record_type;
+
+typedef union oasys_record_union {
+ oasys_record_header_type header;
+ oasys_data_record_type data;
+ oasys_section_record_type section;
+ oasys_symbol_record_type symbol;
+ oasys_header_record_type first;
+ oasys_end_record_type end;
+ bfd_byte pad[256];
+} oasys_record_union_type;
diff --git a/contrib/gdb/include/obstack.h b/contrib/gdb/include/obstack.h
new file mode 100644
index 0000000..416b8bf
--- /dev/null
+++ b/contrib/gdb/include/obstack.h
@@ -0,0 +1,518 @@
+/* obstack.h - object stack macros
+ Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96 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
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Summary:
+
+All the apparent functions defined here are macros. The idea
+is that you would use these pre-tested macros to solve a
+very specific set of problems, and they would run fast.
+Caution: no side-effects in arguments please!! They may be
+evaluated MANY times!!
+
+These macros operate a stack of objects. Each object starts life
+small, and may grow to maturity. (Consider building a word syllable
+by syllable.) An object can move while it is growing. Once it has
+been "finished" it never changes address again. So the "top of the
+stack" is typically an immature growing object, while the rest of the
+stack is of mature, fixed size and fixed address objects.
+
+These routines grab large chunks of memory, using a function you
+supply, called `obstack_chunk_alloc'. On occasion, they free chunks,
+by calling `obstack_chunk_free'. You must define them and declare
+them before using any obstack macros.
+
+Each independent stack is represented by a `struct obstack'.
+Each of the obstack macros expects a pointer to such a structure
+as the first argument.
+
+One motivation for this package is the problem of growing char strings
+in symbol tables. Unless you are "fascist pig with a read-only mind"
+--Gosper's immortal quote from HAKMEM item 154, out of context--you
+would not like to put any arbitrary upper limit on the length of your
+symbols.
+
+In practice this often means you will build many short symbols and a
+few long symbols. At the time you are reading a symbol you don't know
+how long it is. One traditional method is to read a symbol into a
+buffer, realloc()ating the buffer every time you try to read a symbol
+that is longer than the buffer. This is beaut, but you still will
+want to copy the symbol from the buffer to a more permanent
+symbol-table entry say about half the time.
+
+With obstacks, you can work differently. Use one obstack for all symbol
+names. As you read a symbol, grow the name in the obstack gradually.
+When the name is complete, finalize it. Then, if the symbol exists already,
+free the newly read name.
+
+The way we do this is to take a large chunk, allocating memory from
+low addresses. When you want to build a symbol in the chunk you just
+add chars above the current "high water mark" in the chunk. When you
+have finished adding chars, because you got to the end of the symbol,
+you know how long the chars are, and you can create a new object.
+Mostly the chars will not burst over the highest address of the chunk,
+because you would typically expect a chunk to be (say) 100 times as
+long as an average object.
+
+In case that isn't clear, when we have enough chars to make up
+the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
+so we just point to it where it lies. No moving of chars is
+needed and this is the second win: potentially long strings need
+never be explicitly shuffled. Once an object is formed, it does not
+change its address during its lifetime.
+
+When the chars burst over a chunk boundary, we allocate a larger
+chunk, and then copy the partly formed object from the end of the old
+chunk to the beginning of the new larger chunk. We then carry on
+accreting characters to the end of the object as we normally would.
+
+A special macro is provided to add a single char at a time to a
+growing object. This allows the use of register variables, which
+break the ordinary 'growth' macro.
+
+Summary:
+ We allocate large chunks.
+ We carve out one object at a time from the current chunk.
+ Once carved, an object never moves.
+ We are free to append data of any size to the currently
+ growing object.
+ Exactly one object is growing in an obstack at any one time.
+ You can run one obstack per control block.
+ You may have as many control blocks as you dare.
+ Because of the way we do it, you can `unwind' an obstack
+ back to a previous state. (You may remove objects much
+ as you would with a stack.)
+*/
+
+
+/* Don't do the contents of this file more than once. */
+
+#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
+ may ignore the byte-within-word field of the pointer. */
+
+#ifndef __PTR_TO_INT
+#define __PTR_TO_INT(P) ((P) - (char *)0)
+#endif
+
+#ifndef __INT_TO_PTR
+#define __INT_TO_PTR(P) ((P) + (char *)0)
+#endif
+
+/* We need the type of the resulting object. In ANSI C it is ptrdiff_t
+ but in traditional C it is usually long. If we are in ANSI C and
+ don't already have ptrdiff_t get it. */
+
+#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 stddef.h.
+ Otherwise, define just ptrdiff_t, which is all we need. */
+#ifndef __NeXT__
+#define __need_ptrdiff_t
+#endif
+#endif
+
+#include <stddef.h>
+#endif
+
+#ifdef __STDC__
+#define PTR_INT_TYPE ptrdiff_t
+#else
+#define PTR_INT_TYPE long
+#endif
+
+struct _obstack_chunk /* Lives at front of each chunk. */
+{
+ char *limit; /* 1 past end of this chunk */
+ struct _obstack_chunk *prev; /* address of prior chunk or NULL */
+ char contents[4]; /* objects begin here */
+};
+
+struct obstack /* control current object in current chunk */
+{
+ long chunk_size; /* preferred size to allocate chunks in */
+ struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
+ char *object_base; /* address of object we are building */
+ char *next_free; /* where to add next char to current object */
+ char *chunk_limit; /* address of char after current chunk */
+ PTR_INT_TYPE temp; /* Temporary for some macros. */
+ int alignment_mask; /* Mask of alignment for each object. */
+ struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
+ void (*freefun) (); /* User's function to free a chunk. */
+ char *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+ unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
+ unsigned maybe_empty_object:1;/* There is a possibility that the current
+ 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. */
+
+#ifdef __STDC__
+extern void _obstack_newchunk (struct obstack *, int);
+extern void _obstack_free (struct obstack *, void *);
+extern int _obstack_begin (struct obstack *, int, int,
+ void *(*) (), void (*) ());
+extern int _obstack_begin_1 (struct obstack *, int, int,
+ void *(*) (), void (*) (), void *);
+extern int _obstack_memory_used (struct obstack *);
+#else
+extern void _obstack_newchunk ();
+extern void _obstack_free ();
+extern int _obstack_begin ();
+extern int _obstack_begin_1 ();
+extern int _obstack_memory_used ();
+#endif
+
+#ifdef __STDC__
+
+/* Do the function-declarations after the structs
+ but before defining the macros. */
+
+void obstack_init (struct obstack *obstack);
+
+void * obstack_alloc (struct obstack *obstack, int size);
+
+void * obstack_copy (struct obstack *obstack, void *address, int size);
+void * obstack_copy0 (struct obstack *obstack, void *address, int size);
+
+void obstack_free (struct obstack *obstack, void *block);
+
+void obstack_blank (struct obstack *obstack, int size);
+
+void obstack_grow (struct obstack *obstack, void *data, int size);
+void obstack_grow0 (struct obstack *obstack, void *data, int size);
+
+void obstack_1grow (struct obstack *obstack, int data_char);
+void obstack_ptr_grow (struct obstack *obstack, void *data);
+void obstack_int_grow (struct obstack *obstack, int data);
+
+void * obstack_finish (struct obstack *obstack);
+
+int obstack_object_size (struct obstack *obstack);
+
+int obstack_room (struct obstack *obstack);
+void obstack_1grow_fast (struct obstack *obstack, int data_char);
+void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
+void obstack_int_grow_fast (struct obstack *obstack, int data);
+void obstack_blank_fast (struct obstack *obstack, int size);
+
+void * obstack_base (struct obstack *obstack);
+void * obstack_next_free (struct obstack *obstack);
+int obstack_alignment_mask (struct obstack *obstack);
+int obstack_chunk_size (struct obstack *obstack);
+int obstack_memory_used (struct obstack *obstack);
+
+#endif /* __STDC__ */
+
+/* Non-ANSI C cannot really support alternative functions for these macros,
+ so we do not declare them. */
+
+/* Pointer to beginning of object being allocated or to be allocated next.
+ 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)->alloc_failed ? 0 : (h)->object_base)
+
+/* Size for allocating ordinary chunks. */
+
+#define obstack_chunk_size(h) ((h)->chunk_size)
+
+/* Pointer to next byte not yet allocated in current chunk. */
+
+#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. */
+
+#define obstack_alignment_mask(h) ((h)->alignment_mask)
+
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
+
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ (void *(*) ()) (chunkfun), (void (*) ()) (freefun))
+
+#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+ _obstack_begin_1 ((h), (size), (alignment), \
+ (void *(*) ()) (chunkfun), (void (*) ()) (freefun), (arg))
+
+#define obstack_chunkfun(h, newchunkfun) \
+ ((h) -> chunkfun = (struct _obstack_chunk *(*)()) (newchunkfun))
+
+#define obstack_freefun(h, newfreefun) \
+ ((h) -> freefun = (void (*)()) (newfreefun))
+
+#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
+
+#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#define obstack_memory_used(h) _obstack_memory_used (h)
+
+#if defined (__GNUC__) && defined (__STDC__)
+#if __GNUC__ < 2
+#define __extension__
+#endif
+
+/* For GNU C, if not -traditional,
+ we can define these macros to compute all args only once
+ without using a global variable.
+ Also, we can avoid using the `temp' slot, to make faster code. */
+
+#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) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ (unsigned) (__o->chunk_limit - __o->next_free); })
+
+#define obstack_grow(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ 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); \
+ 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); \
+ 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,
+ and that the data added so far to the current object
+ shares that much alignment. */
+
+#define obstack_ptr_grow(OBSTACK,datum) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ 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); \
+ 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)
+#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
+
+#define obstack_blank(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ 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) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_blank (__h, (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+#define obstack_copy0(OBSTACK,where,length) \
+__extension__ \
+({ struct obstack *__h = (OBSTACK); \
+ obstack_grow0 (__h, (where), (length)); \
+ obstack_finish (__h); })
+
+/* The local variable is named __o1 to avoid a name conflict
+ when obstack_blank is called. */
+#define obstack_finish(OBSTACK) \
+__extension__ \
+({ struct obstack *__o1 = (OBSTACK); \
+ 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) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ void *__obj = (OBJ); \
+ if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \
+ __o->next_free = __o->object_base = __obj; \
+ else (obstack_free) (__o, __obj); })
+
+#else /* not __GNUC__ or not __STDC__ */
+
+#define obstack_object_size(h) \
+ (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), \
+ ((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), \
+ ((h)->alloc_failed ? 0 : \
+ (bcopy (where, (h)->next_free, (h)->temp), \
+ (h)->next_free += (h)->temp, \
+ *((h)->next_free)++ = 0)))
+
+#define obstack_1grow(h,datum) \
+( (((h)->next_free + 1 > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), 1), 0) : 0), \
+ ((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), \
+ ((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), \
+ ((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)
+
+#define obstack_blank(h,length) \
+( (h)->temp = (length), \
+ (((h)->chunk_limit - (h)->next_free < (h)->temp) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
+ ((h)->alloc_failed ? 0 : \
+ ((h)->next_free += (h)->temp)))
+
+#define obstack_alloc(h,length) \
+ (obstack_blank ((h), (length)), obstack_finish ((h)))
+
+#define obstack_copy(h,where,length) \
+ (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_copy0(h,where,length) \
+ (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
+
+#define obstack_finish(h) \
+( (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), \
+ (h)->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
+ & ~ ((h)->alignment_mask)), \
+ (((h)->next_free - (char *)(h)->chunk \
+ > (h)->chunk_limit - (char *)(h)->chunk) \
+ ? ((h)->next_free = (h)->chunk_limit) : 0), \
+ (h)->object_base = (h)->next_free, \
+ __INT_TO_PTR ((h)->temp)))
+
+#ifdef __STDC__
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
+#else
+#define obstack_free(h,obj) \
+( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+ (((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
+ ? (int) ((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk) \
+ : (_obstack_free ((h), (h)->temp + (char *) (h)->chunk), 0)))
+#endif
+
+#endif /* not __GNUC__ or not __STDC__ */
+
+#endif /* not __OBSTACK_H__ */
diff --git a/contrib/gdb/include/opcode/ChangeLog b/contrib/gdb/include/opcode/ChangeLog
new file mode 100644
index 0000000..f56df4b
--- /dev/null
+++ b/contrib/gdb/include/opcode/ChangeLog
@@ -0,0 +1,812 @@
+Thu Mar 7 15:08:23 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc.h (O): Mark operand letter as in use.
+
+Tue Feb 20 20:46:21 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc.h (sparc_{encode,decode}_sparclet_cpreg): Declare.
+ Mark operand letters uU as in use.
+
+Mon Feb 19 01:59:08 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc.h (sparc_opcode_arch_val): Add SPARC_OPCODE_ARCH_SPARCLET.
+ (sparc_opcode_arch): Delete member `conflicts'. Add `supported'.
+ (SPARC_OPCODE_SUPPORTED): New macro.
+ (SPARC_OPCODE_CONFLICT_P): Rewrite.
+ (F_NOTV9): Delete.
+
+Fri Feb 16 12:23:34 1996 Jeffrey A Law (law@cygnus.com)
+
+ * sparc.h (sparc_opcode_lookup_arch) Make return type in
+ declaration consistent with return type in definition.
+
+Wed Feb 14 18:14:11 1996 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * i386.h (i386_optab): Remove Data32 from pushf and popf.
+
+Thu Feb 8 14:27:21 1996 James Carlson <carlson@xylogics.com>
+
+ * i386.h (i386_regtab): Add 80486 test registers.
+
+Mon Feb 5 18:35:46 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * i960.h (I_HX): Define.
+ (i960_opcodes): Add HX instruction.
+
+Mon Jan 29 12:43:39 1996 Ken Raeburn <raeburn@cygnus.com>
+
+ * i386.h: Fix waiting forms of finit, fstenv, fsave, fstsw, fstcw,
+ and fclex.
+
+Wed Jan 24 22:36:59 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc.h (enum sparc_opcode_arch_val): Replaces sparc_architecture.
+ (SPARC_OPCODE_CONFLICT_P): Renamed from ARCHITECTURES_CONFLICT_P.
+ (bfd_* defines): Delete.
+ (sparc_opcode_archs): Replaces architecture_pname.
+ (sparc_opcode_lookup_arch): Declare.
+ (NUMOPCODES): Delete.
+
+Mon Jan 22 08:24:32 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc.h (enum sparc_architecture): Add v9a.
+ (ARCHITECTURES_CONFLICT_P): Update.
+
+Thu Dec 28 13:27:53 1995 John Hassey <hassey@rtp.dg.com>
+
+ * i386.h: Added Pentium Pro instructions.
+
+Thu Nov 2 22:59:22 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k.h: Document new 'W' operand place.
+
+Tue Oct 24 10:49:10 1995 Jeffrey A Law (law@cygnus.com)
+
+ * hppa.h: Add lci and syncdma instructions.
+
+Mon Oct 23 11:09:16 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * mips.h: Added INSN_4100 flag to mark NEC VR4100 specific
+ instructions.
+
+Mon Oct 16 10:28:15 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc.h (PPC_OPCODE_{COMMON,ANY}): New opcode flags for
+ assembler's -mcom and -many switches.
+
+Wed Oct 11 16:56:33 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * i386.h: Fix cmpxchg8b extension opcode description.
+
+Thu Oct 5 18:03:36 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * i386.h: Add Pentium instructions wrmsr, rdtsc, rdmsr, cmpxchg8b,
+ and register cr4.
+
+Tue Sep 19 15:26:43 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k.h: Change comment: split type P into types 0, 1 and 2.
+
+Wed Aug 30 13:50:55 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc.h (sparc_{encode,decode}_prefetch): Declare.
+
+Tue Aug 29 15:34:58 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc.h (sparc_{encode,decode}_{asi,membar}): Declare.
+
+Wed Aug 2 18:32:19 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68kmri.h: Remove.
+
+ * m68k.h: Move tables into opcodes/m68k-opc.c, leaving just the
+ declarations. Remove F_ALIAS and flag field of struct
+ m68k_opcode. Change arch field of struct m68k_opcode to unsigned
+ int. Make name and args fields of struct m68k_opcode const.
+
+Wed Aug 2 08:16:46 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc.h (F_NOTV9): Define.
+
+Tue Jul 11 14:20:42 1995 Jeff Spiegel <jeffs@lsil.com>
+
+ * mips.h (INSN_4010): Define.
+
+Wed Jun 21 18:49:51 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * m68k.h (TBL1): Reverse sense of "round" argument in result.
+
+ Changes from Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>:
+ * m68k.h: Fix argument descriptions of coprocessor
+ instructions to allow only alterable operands where appropriate.
+ [!NO_DEFAULT_SIZES]: An omitted size defaults to `w'.
+ (m68k_opcode_aliases): Add more aliases.
+
+
+Fri Apr 14 22:15:34 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * m68k.h: Added explcitly short-sized conditional branches, and a
+ bunch of aliases (fmov*, ftest*, tdivul) to support gcc's
+ svr4-based configurations.
+
+
+Mon Mar 13 21:30:01 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Mon Feb 27 08:36:39 1995 Bryan Ford <baford@cs.utah.edu>
+ * i386.h: added missing Data16/Data32 flags to a few instructions.
+
+Wed Mar 8 15:19:53 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips.h (OP_MASK_FR, OP_SH_FR): Define.
+ (OP_MASK_BCC, OP_SH_BCC): Define.
+ (OP_MASK_PREFX, OP_SH_PREFX): Define.
+ (OP_MASK_CCC, OP_SH_CCC): Define.
+ (INSN_READ_FPR_R): Define.
+ (INSN_RFE): Delete.
+
+Wed Mar 8 03:13:23 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * m68k.h (enum m68k_architecture): Deleted.
+ (struct m68k_opcode_alias): New type.
+ (m68k_opcodes): Now const. Deleted opcode aliases with exactly
+ matching constraints, values and flags. As a side effect of this,
+ the MOTOROLA_SYNTAX_ONLY and MIT_SYNTAX_ONLY macros, which so far
+ as I know were never used, now may need re-examining.
+ (numopcodes): Now const.
+ (m68k_opcode_aliases, numaliases): New variables.
+ (endop): Deleted.
+ [DONT_DEFINE_TABLE]: Declare numopcodes, numaliases, and
+ m68k_opcode_aliases; update declaration of m68k_opcodes.
+
+
+Mon Mar 6 10:02:00 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa.h (delay_type): Delete unused enumeration.
+ (pa_opcode): Replace unused delayed field with an architecture
+ field.
+ (pa_opcodes): Mark each instruction as either PA1.0 or PA1.1.
+
+Fri Mar 3 16:10:24 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips.h (INSN_ISA4): Define.
+
+Fri Feb 24 19:13:37 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips.h (M_DLA_AB, M_DLI): Define.
+
+Thu Feb 23 17:33:09 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa.h (fstwx): Fix single-bit error.
+
+Wed Feb 15 12:19:52 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips.h (M_ULD, M_ULD_A, M_USD, M_USD_A): Define.
+
+
+Mon Feb 6 10:35:23 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * i386.h: added cpuid instruction , and dr[0-7] aliases for the
+ debug registers. From Charles Hannum (mycroft@netbsd.org).
+
+Mon Feb 6 03:31:54 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Changes from Bryan Ford <baford@schirf.cs.utah.edu> for 16-bit
+ i386 support:
+ * i386.h (MOV_AX_DISP32): New macro.
+ (i386_optab): Added Data16 and Data32 as needed. Added "w" forms
+ of several call/return instructions.
+ (ADDR_PREFIX_OPCODE): New macro.
+
+Mon Jan 23 16:45:43 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ Sat Jan 21 17:50:38 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * ../include/opcode/vax.h (struct vot_wot, field `args'): make
+ it pointer to const char;
+ (struct vot, field `name'): ditto.
+
+Thu Jan 19 14:47:53 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * vax.h: Supply and properly group all values in end sentinel.
+
+Tue Jan 17 10:55:30 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * mips.h (INSN_ISA, INSN_4650): Define.
+
+
+
+Wed Oct 19 13:34:17 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * a29k.h: Add operand type 'I' for `inv' and `iretinv'. On
+ systems with a separate instruction and data cache, such as the
+ 29040, these instructions take an optional argument.
+
+Wed Sep 14 17:44:20 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mips.h (INSN_STORE_MEMORY): Correct value to not conflict with
+ INSN_TRAP.
+
+Tue Sep 6 11:39:08 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mips.h (INSN_STORE_MEMORY): Define.
+
+Thu Jul 28 19:28:07 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * sparc.h: Document new operand type 'x'.
+
+Tue Jul 26 17:48:05 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * i960.h (I_CX2): New instruction category. It includes
+ instructions available on Cx and Jx processors.
+ (I_JX): New instruction category, for JX-only instructions.
+ (i960_opcodes): Put eshro and sysctl in I_CX2 category. Added
+ Jx-only instructions, in I_JX category.
+
+Wed Jul 13 18:43:47 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * ns32k.h (endop): Made pointer const too.
+
+Sun Jul 10 11:01:09 1994 Ian Dall (dall@hfrd.dsto.gov.au)
+
+ * ns32k.h: Drop Q operand type as there is no correct use
+ for it. Add I and Z operand types which allow better checking.
+
+Thu Jul 7 12:34:48 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * h8300.h (xor.l) :fix bit pattern.
+ (L_2): New size of operand.
+ (trapa): Use it.
+
+Fri Jun 10 16:38:11 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m68k.h: Move "trap" before "tpcc" to change disassembly.
+
+Fri Jun 3 15:57:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * sparc.h: Include v9 definitions.
+
+Thu Jun 2 12:23:17 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * m68k.h (m68060): Defined.
+ (m68040up, mfloat, mmmu): Include it.
+ (struct m68k_opcode): Widen `arch' field.
+ (m68k_opcodes): Updated for M68060. Removed comments that were
+ instructions commented out by "JF" years ago.
+
+Thu Apr 28 18:31:14 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * m68k.h (struct m68k_opcode): Shorten `arch' field to 8 bits, and
+ add a one-bit `flags' field.
+ (F_ALIAS): New macro.
+
+Wed Apr 27 11:29:52 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * h8300.h (dec, inc): Get encoding right.
+
+Mon Apr 4 13:12:43 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc.h (struct powerpc_operand): Removed signedp field; just use
+ a flag instead.
+ (PPC_OPERAND_SIGNED): Define.
+ (PPC_OPERAND_SIGNOPT): Define.
+
+Thu Mar 31 19:34:08 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * i386.h (IS_JUMP_ON_ECX_ZERO, "jcxz" pattern): Operand size
+ prefix is 0x66, not 0x67. Patch from H.J. Lu (hlu@nynexst.com).
+
+Thu Mar 3 15:51:05 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * i386.h: Reverse last change. It'll be handled in gas instead.
+
+Thu Feb 24 15:29:05 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * i386.h (sar): Disabled the two-operand Imm1 form, since it was
+ slower on the 486 and used the implicit shift count despite the
+ explicit operand. The one-operand form is still available to get
+ the shorter form with the implicit shift count.
+
+Thu Feb 17 12:27:52 1994 Torbjorn Granlund (tege@mexican.cygnus.com)
+
+ * hppa.h: Fix typo in fstws arg string.
+
+Wed Feb 9 21:23:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc.h (struct powerpc_opcode): Make operands field unsigned.
+
+Mon Feb 7 19:14:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc.h (PPC_OPCODE_601): Define.
+
+Fri Feb 4 23:43:50 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa.h (addb): Use '@' for addb and addib pseudo ops.
+ (so we can determine valid completers for both addb and addb[tf].)
+
+ * hppa.h (xmpyu): No floating point format specifier for the
+ xmpyu instruction.
+
+Fri Feb 4 23:36:52 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc.h (PPC_OPERAND_NEXT): Define.
+ (PPC_OPERAND_NEGATIVE): Change value to make room for above.
+ (struct powerpc_macro): Define.
+ (powerpc_macros, powerpc_num_macros): Declare.
+
+Fri Jan 21 19:13:50 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc.h: New file. Header file for PowerPC opcode table.
+
+Mon Jan 17 00:14:23 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa.h: More minor template fixes for sfu and copr (to allow
+ for easier disassembly).
+
+ * hppa.h: Fix templates for all the sfu and copr instructions.
+
+Wed Dec 15 15:12:42 1993 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * i386.h (push): Permit Imm16 operand too.
+
+Sat Dec 11 16:14:06 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * h8300.h (andc): Exists in base arch.
+
+Wed Dec 1 12:15:32 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * From Hisashi MINAMINO <minamino@sramhc.sra.co.jp>
+ * hppa.h: #undef NONE to avoid conflict with hiux include files.
+
+Sun Nov 21 22:06:57 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa.h: Add FP quadword store instructions.
+
+Wed Nov 17 17:13:16 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h: (M_J_A): Added.
+ (M_LA): Removed.
+
+Mon Nov 8 12:12:47 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (OP_MASK_CACHE, OP_SH_CACHE): Define. From Ted Lemon
+ <mellon@pepper.ncd.com>.
+
+Sun Nov 7 00:30:11 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa.h: Immediate field in probei instructions is unsigned,
+ not low-sign extended.
+
+Wed Nov 3 10:30:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m88k.h (RRI10MASK): Change from 0xfc00ffe0 to 0xfc00fc00.
+
+Tue Nov 2 12:41:30 1993 Ken Raeburn (raeburn@rover.cygnus.com)
+
+ * i386.h: Add "fxch" without operand.
+
+Mon Nov 1 18:13:03 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (M_JAL_1, M_JAL_2, M_JAL_A): Added.
+
+Sat Oct 2 22:26:11 1993 Jeffrey A Law (law@snake.cs.utah.edu)
+
+ * hppa.h: Add gfw and gfr to the opcode table.
+
+Wed Sep 29 16:23:00 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * m88k.h: extended to handle m88110.
+
+Tue Sep 28 19:19:08 1993 Jeffrey A Law (law@snake.cs.utah.edu)
+
+ * hppa.h (be, ble): Use operand type 'z' to denote absolute branch
+ addresses.
+
+Tue Sep 14 14:04:35 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i960.h (i960_opcodes): Properly bracket initializers.
+
+Mon Sep 13 12:50:52 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * m88k.h (BOFLAG): rewrite to avoid nested comment.
+
+Mon Sep 13 15:46:06 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m68k.h (two): Protect second argument with parentheses.
+
+Fri Sep 10 16:29:47 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * i386.h (i386_optab): Added new instruction "rsm" (for i386sl).
+ Deleted old in/out instructions in "#if 0" section.
+
+Thu Sep 9 17:42:19 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i386.h (i386_optab): Properly bracket initializers.
+
+Wed Aug 25 13:50:56 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * hppa.h (pa_opcode): Use '|' for movb and movib insns. (From
+ Jeff Law, law@cs.utah.edu).
+
+Mon Aug 23 16:55:03 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * i386.h (lcall): Accept Imm32 operand also.
+
+Mon Aug 23 12:43:11 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (M_ABSU): Removed (absolute value of unsigned number??).
+ (M_DABS): Added.
+
+Thu Aug 19 15:08:37 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h (INSN_*): Changed values. Removed unused definitions.
+ Added INSN_COND_BRANCH_LIKELY, INSN_ISA2 and INSN_ISA3. Split
+ INSN_LOAD_DELAY into INSN_LOAD_MEMORY_DELAY and
+ INSN_LOAD_COPROC_DELAY. Split INSN_COPROC_DELAY into
+ INSN_COPROC_MOVE_DELAY and INSN_COPROC_MEMORY_DELAY.
+ (M_*): Added new values for r6000 and r4000 macros.
+ (ANY_DELAY): Removed.
+
+Wed Aug 18 15:37:48 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h: Added M_LI_S and M_LI_SS.
+
+Tue Aug 17 07:08:08 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * h8300.h: Get some rare mov.bs correct.
+
+Thu Aug 5 09:15:17 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc.h: Don't define const ourself; rely on ansidecl.h having
+ been included.
+
+Fri Jul 30 18:41:11 1993 John Gilmore (gnu@cygnus.com)
+
+ * sparc.h (F_JSR, F_UNBR, F_CONDBR): Add new flags to mark
+ jump instructions, for use in disassemblers.
+
+Thu Jul 22 07:25:27 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * m88k.h: Make bitfields just unsigned, not unsigned long or
+ unsigned short.
+
+Wed Jul 21 11:55:31 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * hppa.h: New argument type 'y'. Use in various float instructions.
+
+Mon Jul 19 17:17:03 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * hppa.h (break): First immediate field is unsigned.
+
+ * hppa.h: Add rfir instruction.
+
+Sun Jul 18 16:28:08 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * mips.h: Split the actual table out into ../../opcodes/mips-opc.c.
+
+Fri Jul 16 09:59:29 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h: Reworked the hazard information somewhat, and fixed some
+ bugs in the instruction hazard descriptions.
+
+Thu Jul 15 12:42:01 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m88k.h: Corrected a couple of opcodes.
+
+Tue Jul 6 15:17:35 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips.h: Replaced with version from Ralph Campbell and OSF. The
+ new version includes instruction hazard information, but is
+ otherwise reasonably similar.
+
+Thu Jul 1 20:36:17 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * h8300.h: Fix typo in UNOP3 (affected sh[al][lr].l).
+
+Fri Jun 11 18:38:44 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ Patches from Jeff Law, law@cs.utah.edu:
+ * hppa.h: Clean up some of the OLD_TABLE, non-OLD_TABLE braindamage.
+ Make the tables be the same for the following instructions:
+ "bb", "addb[tf]", "addib[tf]", "add", "add[loc]", "addco",
+ "sh[123]add", "sh[123]add[lo]", "sub", "sub[obt]", "sub[bt]o",
+ "ds", "comclr", "addi", "addi[ot]", "addito", "subi", "subio",
+ "comiclr", "fadd", "fsub", "fmpy", "fdiv", "fsqrt", "fabs",
+ "frnd", "fcpy", "fcnvff", "fcnvxf", "fcnvfx", "fcnvfxt",
+ "fcmp", and "ftest".
+
+ * hppa.h: Make new and old tables the same for "break", "mtctl",
+ "mfctl", "bb", "ssm", "rsm", "xmpyu", "fmpyadd", "fmpysub".
+ Fix typo in last patch. Collapse several #ifdefs into a
+ single #ifdef.
+
+ * hppa.h: Delete remaining OLD_TABLE code. Bring some
+ of the comments up-to-date.
+
+ * hppa.h: Update "free list" of letters and update
+ comments describing each letter's function.
+
+Fri Jun 4 15:41:37 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * h8300.h: checkpoint, includes H8/300-H opcodes.
+
+Thu Jun 3 15:42:59 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Patches from Jeffrey Law <law@cs.utah.edu>.
+ * hppa.h: Rework single precision FP
+ instructions so that they correctly disassemble code
+ PA1.1 code.
+
+Thu May 27 19:21:22 1993 Bruce Bauman (boot@osf.org)
+
+ * i386.h (i386_optab, mov pattern): Remove Mem16 restriction from
+ mov to allow instructions like mov ss,xyz(ecx) to assemble.
+
+Tue May 25 00:39:40 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * hppa.h: Use new version from Utah if OLD_TABLE isn't defined;
+ gdb will define it for now.
+
+Mon May 24 15:20:06 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * sparc.h: Don't end enumerator list with comma.
+
+Fri May 14 15:15:50 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Based on patches from davidj@ICSI.Berkeley.EDU (David Johnson):
+ * mips.h (OP_MASK_COPZ, OP_SH_COPZ): Define.
+ ("bc2t"): Correct typo.
+ ("[ls]wc[023]"): Use T rather than t.
+ ("c[0123]"): Define general coprocessor instructions.
+
+Mon May 10 06:02:25 1993 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ * m68k.h: Move split point for gcc compilation more towards
+ middle.
+
+Fri Apr 9 13:26:16 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * rs6k.h: Clean up instructions for primary opcode 19 (many were
+ simply wrong, ics, rfi, & rfsvc were missing).
+ Add "a" to opr_ext for "bb". Doc fix.
+
+Thu Mar 18 13:45:31 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * i386.h: 486 extensions from John Hassey (hassey@dg-rtp.dg.com).
+ * mips.h: Add casts, to suppress warnings about shifting too much.
+ * m68k.h: Document the placement code '9'.
+
+Thu Feb 18 02:03:14 1993 John Gilmore (gnu@cygnus.com)
+
+ * m68k.h (BREAK_UP_BIG_DECL, AND_OTHER_PART): Add kludge which
+ allows callers to break up the large initialized struct full of
+ opcodes into two half-sized ones. This permits GCC to compile
+ this module, since it takes exponential space for initializers.
+ (numopcodes, endop): Revise to use AND_OTHER_PART in size calcs.
+
+Thu Feb 4 02:06:56 1993 John Gilmore (gnu@cygnus.com)
+
+ * a29k.h: Remove RCS crud, update GPL to v2, update copyrights.
+ * convex.h: Added, from GDB's convx-opcode.h. Added CONST to all
+ initialized structs in it.
+
+Thu Jan 28 21:32:22 1993 John Gilmore (gnu@cygnus.com)
+
+ Delta 88 changes inspired by Carl Greco, <cgreco@Creighton.Edu>:
+ * m88k.h (PMEM): Avoid previous definition from <sys/param.h>.
+ (AND): Change to AND_ to avoid ansidecl.h `AND' conflict.
+
+Sat Jan 23 18:10:49 PST 1993 Ralph Campbell (ralphc@pyramid.com)
+
+ * mips.h: document "i" and "j" operands correctly.
+
+Thu Jan 7 15:58:13 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips.h: Removed endianness dependency.
+
+Sun Jan 3 14:13:35 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * h8300.h: include info on number of cycles per instruction.
+
+Mon Dec 21 21:29:08 1992 Stu Grossman (grossman at cygnus.com)
+
+ * hppa.h: Move handy aliases to the front. Fix masks for extract
+ and deposit instructions.
+
+Sat Dec 12 16:09:48 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * i386.h: accept shld and shrd both with and without the shift
+ count argument, which is always %cl.
+
+Fri Nov 27 17:13:18 1992 Ken Raeburn (raeburn at cygnus.com)
+
+ * i386.h (i386_optab_end, i386_regtab_end): Now const.
+ (one_byte_segment_defaults, two_byte_segment_defaults,
+ i386_prefixtab_end): Ditto.
+
+Mon Nov 23 10:47:25 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * vax.h (bb*): Use "v" (bitfield type), not "a" (address operand)
+ for operand 2; from John Carr, jfc@dsg.dec.com.
+
+Wed Nov 4 07:36:49 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * m68k.h: Define FIXED_SIZE_BRANCH, so bsr and bra instructions
+ always use 16-bit offsets. Makes calculated-size jump tables
+ feasible.
+
+Fri Oct 16 22:52:43 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * i386.h: Fix one-operand forms of in* and out* patterns.
+
+Tue Sep 22 14:08:14 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * m68k.h: Added CPU32 support.
+
+Tue Sep 22 00:38:41 1992 John Gilmore (gnu@cygnus.com)
+
+ * mips.h (break): Disassemble the argument. Patch from
+ jonathan@cs.stanford.edu (Jonathan Stone).
+
+Wed Sep 9 11:25:28 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * m68k.h: merged Motorola and MIT syntax.
+
+Thu Sep 3 09:33:22 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * m68k.h (pmove): make the tests less strict, the 68k book is
+ wrong.
+
+Tue Aug 25 23:25:19 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * m68k.h (m68ec030): Defined as alias for 68030.
+ (m68k_opcodes): New type characters "3" for 68030 MMU regs and "t"
+ for immediate 0-7 added. Set up some opcodes (ptest, bkpt) to use
+ them. Tightened description of "fmovex" to distinguish it from
+ some "pmove" encodings. Added "pmove" for 68030 MMU regs, cleaned
+ up descriptions that claimed versions were available for chips not
+ supporting them. Added "pmovefd".
+
+Mon Aug 24 12:04:51 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * m68k.h: fix where the . goes in divull
+
+Wed Aug 19 11:22:24 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * m68k.h: the cas2 instruction is supposed to be written with
+ indirection on the last two operands, which can be either data or
+ address registers. Added a new operand type 'r' which accepts
+ either register type. Added new cases for cas2l and cas2w which
+ use them. Corrected masks for cas2 which failed to recognize use
+ of address register.
+
+Fri Aug 14 14:20:38 1992 Per Bothner (bothner@cygnus.com)
+
+ * m68k.h: Merged in patches (mostly m68040-specific) from
+ Colin Smith <colin@wrs.com>.
+
+ * m68k.h: Merged m68kmri.h and m68k.h (using the former as a
+ base). Also cleaned up duplicates, re-ordered instructions for
+ the sake of dis-assembling (so aliases come after standard names).
+ * m68kmri.h: Now just defines some macros, and #includes m68k.h.
+
+Wed Aug 12 16:38:15 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * m68kmri.h: added various opcodes. Moved jbxx to bxxes. Filled in
+ all missing .s
+
+Mon Aug 10 23:22:33 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * sparc.h: Moved tables to BFD library.
+
+ * i386.h (i386_optab): Add fildq, fistpq aliases used by gcc.
+
+Sun Jun 28 13:29:03 1992 Fred Fish (fnf@cygnus.com)
+
+ * h8300.h: Finish filling in all the holes in the opcode table,
+ so that the Lucid C compiler can digest this as well...
+
+Fri Jun 26 21:27:17 1992 John Gilmore (gnu at cygnus.com)
+
+ * i386.h: Add setc, setnc, addr16, data16, repz, repnz aliases.
+ Fix opcodes on various sizes of fild/fist instructions
+ (16bit=no suffix, 32bit="l" suffix, 64bit="ll" suffix).
+ Use tabs to indent for comments. Fixes suggested by Minh Tran-Le.
+
+Thu Jun 25 16:13:26 1992 Stu Grossman (grossman at cygnus.com)
+
+ * h8300.h: Fill in all the holes in the opcode table so that the
+ losing HPUX C compiler can digest this...
+
+Thu Jun 11 12:15:25 1992 John Gilmore (gnu at cygnus.com)
+
+ * mips.h: Fix decoding of coprocessor instructions, somewhat.
+ (Fix by Eric Anderson, 3jean@maas-neotek.arc.nasa.gov.)
+
+Thu May 28 11:17:44 1992 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * sparc.h: Add new architecture variant sparclite; add its scan
+ and divscc opcodes. Define ARCHITECTURES_CONFLICT_P macro.
+
+Tue May 5 14:23:27 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * mips.h: Add some more opcode synonyms (from Frank Yellin,
+ fy@lucid.com).
+
+Thu Apr 16 18:25:26 1992 Per Bothner (bothner@cygnus.com)
+
+ * rs6k.h: New version from IBM (Metin).
+
+Thu Apr 9 00:31:19 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * rs6k.h: Fix incorrect extended opcode for instructions `fm'
+ and `fd'. (From metin@ibmpa.awdpa.ibm.com (Metin G. Ozisik).)
+
+Tue Apr 7 13:38:47 1992 Stu Grossman (grossman at cygnus.com)
+
+ * rs6k.h: Move from ../../gdb/rs6k-opcode.h.
+
+Fri Apr 3 11:30:20 1992 Fred Fish (fnf@cygnus.com)
+
+ * m68k.h (one, two): Cast macro args to unsigned to suppress
+ complaints from compiler and lint about integer overflow during
+ shift.
+
+Sun Mar 29 12:22:08 1992 John Gilmore (gnu at cygnus.com)
+
+ * sparc.h (OP): Avoid signed overflow when shifting to high order bit.
+
+Fri Mar 6 00:22:38 1992 John Gilmore (gnu at cygnus.com)
+
+ * mips.h: Make bitfield layout depend on the HOST compiler,
+ not on the TARGET system.
+
+Fri Feb 21 01:29:51 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * i386.h: added inb, inw, outb, outw opcodes, added att syntax for
+ scmp, slod, smov, ssca, ssto. Curtesy Minh Tran-Le
+ <TRANLE@INTELLICORP.COM>.
+
+Thu Jan 30 07:31:44 1992 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * h8300.h: turned op_type enum into #define list
+
+Thu Jan 30 01:07:24 1992 John Gilmore (gnu at cygnus.com)
+
+ * sparc.h: Remove "cypress" architecture. Remove "fitox" and
+ similar instructions -- they've been renamed to "fitoq", etc.
+ REALLY fix tsubcctv. Fix "fcmpeq" and "fcmpq" which had wrong
+ number of arguments.
+ * h8300.h: Remove extra ; which produces compiler warning.
+
+Tue Jan 28 22:59:22 1992 Stu Grossman (grossman at cygnus.com)
+
+ * sparc.h: fix opcode for tsubcctv.
+
+Tue Jan 7 17:19:39 1992 K. Richard Pixley (rich at cygnus.com)
+
+ * sparc.h: fba and cba are now aliases for fb and cb respectively.
+
+Fri Dec 27 10:55:50 1991 Per Bothner (bothner at cygnus.com)
+
+ * sparc.h (nop): Made the 'lose' field be even tighter,
+ so only a standard 'nop' is disassembled as a nop.
+
+Sun Dec 22 12:18:18 1991 Michael Tiemann (tiemann at cygnus.com)
+
+ * sparc.h (nop): Add RD_GO to `lose' so that only %g0 in dest is
+ disassembled as a nop.
+
+Tue Dec 10 00:22:20 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * sparc.h: fix a typo.
+
+Sat Nov 30 20:40:51 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+
+ * a29k.h, arm.h, h8300.h, i386.h, i860.h, i960.h , m68k.h,
+ m88k.h, mips.h , np1.h, ns32k.h, pn.h, pyr.h, sparc.h, tahoe.h,
+ vax.h, ChangeLog: renamed from ../<foo>-opcode.h
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/include/opcode/a29k.h b/contrib/gdb/include/opcode/a29k.h
new file mode 100644
index 0000000..002e127
--- /dev/null
+++ b/contrib/gdb/include/opcode/a29k.h
@@ -0,0 +1,285 @@
+/* Table of opcodes for the AMD 29000 family.
+ Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct a29k_opcode {
+ /* Name of the instruction. */
+ char *name;
+
+ /* Opcode word */
+ unsigned long opcode;
+
+ /* A string of characters which describe the operands.
+ Valid characters are:
+ , Itself. The character appears in the assembly code.
+ a RA. The register number is in bits 8-15 of the instruction.
+ b RB. The register number is in bits 0-7 of the instruction.
+ c RC. The register number is in bits 16-23 of the instruction.
+ i An immediate operand is in bits 0-7 of the instruction.
+ x Bits 0-7 and 16-23 of the instruction are bits 0-7 and 8-15
+ (respectively) of the immediate operand.
+ h Same as x but the instruction contains bits 16-31 of the
+ immediate operand.
+ X Same as x but bits 16-31 of the signed immediate operand
+ are set to 1 (thus the operand is always negative).
+ P,A Bits 0-7 and 16-23 of the instruction are bits 2-9 and 10-17
+ (respectively) of the immediate operand.
+ P=PC-relative, sign-extended to 32 bits.
+ A=Absolute, zero-extended to 32 bits.
+ e CE bit (bit 23) for a load/store instruction.
+ n Control field (bits 16-22) for a load/store instruction.
+ v Immediate operand in bits 16-23 of the instruction.
+ (used for trap numbers).
+ s SA. Special-purpose register number in bits 8-15
+ of the instruction.
+ u UI--bit 7 of the instruction.
+ r RND--bits 4-6 of the instruction.
+ d FD--bits 2-3 of the instruction.
+ f FS--bits 0-1 of the instruction.
+ I ID--bits 16-17 of the instruction.
+
+ Extensions for 29050:
+
+ d FMT--bits 2-3 of the instruction (not really new).
+ f ACN--bits 0-1 of the instruction (not really new).
+ F FUNC--Special function in bits 18-21 of the instruction.
+ C ACN--bits 16-17 specifying the accumlator register. */
+ char *args;
+};
+
+#ifndef CONST
+#define CONST
+#endif /* CONST */
+
+static CONST struct a29k_opcode a29k_opcodes[] =
+{
+
+{ "add", 0x14000000, "c,a,b" },
+{ "add", 0x15000000, "c,a,i" },
+{ "addc", 0x1c000000, "c,a,b" },
+{ "addc", 0x1d000000, "c,a,i" },
+{ "addcs", 0x18000000, "c,a,b" },
+{ "addcs", 0x19000000, "c,a,i" },
+{ "addcu", 0x1a000000, "c,a,b" },
+{ "addcu", 0x1b000000, "c,a,i" },
+{ "adds", 0x10000000, "c,a,b" },
+{ "adds", 0x11000000, "c,a,i" },
+{ "addu", 0x12000000, "c,a,b" },
+{ "addu", 0x13000000, "c,a,i" },
+{ "and", 0x90000000, "c,a,b" },
+{ "and", 0x91000000, "c,a,i" },
+{ "andn", 0x9c000000, "c,a,b" },
+{ "andn", 0x9d000000, "c,a,i" },
+{ "aseq", 0x70000000, "v,a,b" },
+{ "aseq", 0x71000000, "v,a,i" },
+{ "asge", 0x5c000000, "v,a,b" },
+{ "asge", 0x5d000000, "v,a,i" },
+{ "asgeu", 0x5e000000, "v,a,b" },
+{ "asgeu", 0x5f000000, "v,a,i" },
+{ "asgt", 0x58000000, "v,a,b" },
+{ "asgt", 0x59000000, "v,a,i" },
+{ "asgtu", 0x5a000000, "v,a,b" },
+{ "asgtu", 0x5b000000, "v,a,i" },
+{ "asle", 0x54000000, "v,a,b" },
+{ "asle", 0x55000000, "v,a,i" },
+{ "asleu", 0x56000000, "v,a,b" },
+{ "asleu", 0x57000000, "v,a,i" },
+{ "aslt", 0x50000000, "v,a,b" },
+{ "aslt", 0x51000000, "v,a,i" },
+{ "asltu", 0x52000000, "v,a,b" },
+{ "asltu", 0x53000000, "v,a,i" },
+{ "asneq", 0x72000000, "v,a,b" },
+{ "asneq", 0x73000000, "v,a,i" },
+{ "call", 0xa8000000, "a,P" },
+{ "call", 0xa9000000, "a,A" },
+{ "calli", 0xc8000000, "a,b" },
+{ "class", 0xe6000000, "c,a,f" },
+{ "clz", 0x08000000, "c,b" },
+{ "clz", 0x09000000, "c,i" },
+{ "const", 0x03000000, "a,x" },
+{ "consth", 0x02000000, "a,h" },
+{ "consthz", 0x05000000, "a,h" },
+{ "constn", 0x01000000, "a,X" },
+{ "convert", 0xe4000000, "c,a,u,r,d,f" },
+{ "cpbyte", 0x2e000000, "c,a,b" },
+{ "cpbyte", 0x2f000000, "c,a,i" },
+{ "cpeq", 0x60000000, "c,a,b" },
+{ "cpeq", 0x61000000, "c,a,i" },
+{ "cpge", 0x4c000000, "c,a,b" },
+{ "cpge", 0x4d000000, "c,a,i" },
+{ "cpgeu", 0x4e000000, "c,a,b" },
+{ "cpgeu", 0x4f000000, "c,a,i" },
+{ "cpgt", 0x48000000, "c,a,b" },
+{ "cpgt", 0x49000000, "c,a,i" },
+{ "cpgtu", 0x4a000000, "c,a,b" },
+{ "cpgtu", 0x4b000000, "c,a,i" },
+{ "cple", 0x44000000, "c,a,b" },
+{ "cple", 0x45000000, "c,a,i" },
+{ "cpleu", 0x46000000, "c,a,b" },
+{ "cpleu", 0x47000000, "c,a,i" },
+{ "cplt", 0x40000000, "c,a,b" },
+{ "cplt", 0x41000000, "c,a,i" },
+{ "cpltu", 0x42000000, "c,a,b" },
+{ "cpltu", 0x43000000, "c,a,i" },
+{ "cpneq", 0x62000000, "c,a,b" },
+{ "cpneq", 0x63000000, "c,a,i" },
+{ "dadd", 0xf1000000, "c,a,b" },
+{ "ddiv", 0xf7000000, "c,a,b" },
+{ "deq", 0xeb000000, "c,a,b" },
+{ "dge", 0xef000000, "c,a,b" },
+{ "dgt", 0xed000000, "c,a,b" },
+{ "div", 0x6a000000, "c,a,b" },
+{ "div", 0x6b000000, "c,a,i" },
+{ "div0", 0x68000000, "c,b" },
+{ "div0", 0x69000000, "c,i" },
+{ "divide", 0xe1000000, "c,a,b" },
+{ "dividu", 0xe3000000, "c,a,b" },
+{ "divl", 0x6c000000, "c,a,b" },
+{ "divl", 0x6d000000, "c,a,i" },
+{ "divrem", 0x6e000000, "c,a,b" },
+{ "divrem", 0x6f000000, "c,a,i" },
+{ "dmac", 0xd9000000, "F,C,a,b" },
+{ "dmsm", 0xdb000000, "c,a,b" },
+{ "dmul", 0xf5000000, "c,a,b" },
+{ "dsub", 0xf3000000, "c,a,b" },
+{ "emulate", 0xd7000000, "v,a,b" },
+{ "exbyte", 0x0a000000, "c,a,b" },
+{ "exbyte", 0x0b000000, "c,a,i" },
+{ "exhw", 0x7c000000, "c,a,b" },
+{ "exhw", 0x7d000000, "c,a,i" },
+{ "exhws", 0x7e000000, "c,a" },
+{ "extract", 0x7a000000, "c,a,b" },
+{ "extract", 0x7b000000, "c,a,i" },
+{ "fadd", 0xf0000000, "c,a,b" },
+{ "fdiv", 0xf6000000, "c,a,b" },
+{ "fdmul", 0xf9000000, "c,a,b" },
+{ "feq", 0xea000000, "c,a,b" },
+{ "fge", 0xee000000, "c,a,b" },
+{ "fgt", 0xec000000, "c,a,b" },
+{ "fmac", 0xd8000000, "F,C,a,b" },
+{ "fmsm", 0xda000000, "c,a,b" },
+{ "fmul", 0xf4000000, "c,a,b" },
+{ "fsub", 0xf2000000, "c,a,b" },
+{ "halt", 0x89000000, "" },
+{ "inbyte", 0x0c000000, "c,a,b" },
+{ "inbyte", 0x0d000000, "c,a,i" },
+{ "inhw", 0x78000000, "c,a,b" },
+{ "inhw", 0x79000000, "c,a,i" },
+{ "inv", 0x9f000000, "I" },
+{ "iret", 0x88000000, "" },
+{ "iretinv", 0x8c000000, "I" },
+{ "jmp", 0xa0000000, "P" },
+{ "jmp", 0xa1000000, "A" },
+{ "jmpf", 0xa4000000, "a,P" },
+{ "jmpf", 0xa5000000, "a,A" },
+{ "jmpfdec", 0xb4000000, "a,P" },
+{ "jmpfdec", 0xb5000000, "a,A" },
+{ "jmpfi", 0xc4000000, "a,b" },
+{ "jmpi", 0xc0000000, "b" },
+{ "jmpt", 0xac000000, "a,P" },
+{ "jmpt", 0xad000000, "a,A" },
+{ "jmpti", 0xcc000000, "a,b" },
+{ "load", 0x16000000, "e,n,a,b" },
+{ "load", 0x17000000, "e,n,a,i" },
+{ "loadl", 0x06000000, "e,n,a,b" },
+{ "loadl", 0x07000000, "e,n,a,i" },
+{ "loadm", 0x36000000, "e,n,a,b" },
+{ "loadm", 0x37000000, "e,n,a,i" },
+{ "loadset", 0x26000000, "e,n,a,b" },
+{ "loadset", 0x27000000, "e,n,a,i" },
+{ "mfacc", 0xe9000100, "c,d,f" },
+{ "mfsr", 0xc6000000, "c,s" },
+{ "mftlb", 0xb6000000, "c,a" },
+{ "mtacc", 0xe8010000, "a,d,f" },
+{ "mtsr", 0xce000000, "s,b" },
+{ "mtsrim", 0x04000000, "s,x" },
+{ "mttlb", 0xbe000000, "a,b" },
+{ "mul", 0x64000000, "c,a,b" },
+{ "mul", 0x65000000, "c,a,i" },
+{ "mull", 0x66000000, "c,a,b" },
+{ "mull", 0x67000000, "c,a,i" },
+{ "multiplu", 0xe2000000, "c,a,b" },
+{ "multiply", 0xe0000000, "c,a,b" },
+{ "multm", 0xde000000, "c,a,b" },
+{ "multmu", 0xdf000000, "c,a,b" },
+{ "mulu", 0x74000000, "c,a,b" },
+{ "mulu", 0x75000000, "c,a,i" },
+{ "nand", 0x9a000000, "c,a,b" },
+{ "nand", 0x9b000000, "c,a,i" },
+{ "nop", 0x70400101, "" },
+{ "nor", 0x98000000, "c,a,b" },
+{ "nor", 0x99000000, "c,a,i" },
+{ "or", 0x92000000, "c,a,b" },
+{ "or", 0x93000000, "c,a,i" },
+{ "orn", 0xaa000000, "c,a,b" },
+{ "orn", 0xab000000, "c,a,i" },
+
+/* The description of "setip" in Chapter 8 ("instruction set") of the user's
+ manual claims that these are absolute register numbers. But section
+ 7.2.1 explains that they are not. The latter is correct, so print
+ these normally ("lr0", "lr5", etc.). */
+{ "setip", 0x9e000000, "c,a,b" },
+
+{ "sll", 0x80000000, "c,a,b" },
+{ "sll", 0x81000000, "c,a,i" },
+{ "sqrt", 0xe5000000, "c,a,f" },
+{ "sra", 0x86000000, "c,a,b" },
+{ "sra", 0x87000000, "c,a,i" },
+{ "srl", 0x82000000, "c,a,b" },
+{ "srl", 0x83000000, "c,a,i" },
+{ "store", 0x1e000000, "e,n,a,b" },
+{ "store", 0x1f000000, "e,n,a,i" },
+{ "storel", 0x0e000000, "e,n,a,b" },
+{ "storel", 0x0f000000, "e,n,a,i" },
+{ "storem", 0x3e000000, "e,n,a,b" },
+{ "storem", 0x3f000000, "e,n,a,i" },
+{ "sub", 0x24000000, "c,a,b" },
+{ "sub", 0x25000000, "c,a,i" },
+{ "subc", 0x2c000000, "c,a,b" },
+{ "subc", 0x2d000000, "c,a,i" },
+{ "subcs", 0x28000000, "c,a,b" },
+{ "subcs", 0x29000000, "c,a,i" },
+{ "subcu", 0x2a000000, "c,a,b" },
+{ "subcu", 0x2b000000, "c,a,i" },
+{ "subr", 0x34000000, "c,a,b" },
+{ "subr", 0x35000000, "c,a,i" },
+{ "subrc", 0x3c000000, "c,a,b" },
+{ "subrc", 0x3d000000, "c,a,i" },
+{ "subrcs", 0x38000000, "c,a,b" },
+{ "subrcs", 0x39000000, "c,a,i" },
+{ "subrcu", 0x3a000000, "c,a,b" },
+{ "subrcu", 0x3b000000, "c,a,i" },
+{ "subrs", 0x30000000, "c,a,b" },
+{ "subrs", 0x31000000, "c,a,i" },
+{ "subru", 0x32000000, "c,a,b" },
+{ "subru", 0x33000000, "c,a,i" },
+{ "subs", 0x20000000, "c,a,b" },
+{ "subs", 0x21000000, "c,a,i" },
+{ "subu", 0x22000000, "c,a,b" },
+{ "subu", 0x23000000, "c,a,i" },
+{ "xnor", 0x96000000, "c,a,b" },
+{ "xnor", 0x97000000, "c,a,i" },
+{ "xor", 0x94000000, "c,a,b" },
+{ "xor", 0x95000000, "c,a,i" },
+
+{ "", 0x0, "" } /* Dummy entry, not included in NUM_OPCODES. This
+ lets code examine entry i+1 without checking
+ if we've run off the end of the table. */
+};
+
+CONST unsigned int num_opcodes = (((sizeof a29k_opcodes) / (sizeof a29k_opcodes[0])) - 1);
diff --git a/contrib/gdb/include/opcode/arm.h b/contrib/gdb/include/opcode/arm.h
new file mode 100644
index 0000000..c7087eb
--- /dev/null
+++ b/contrib/gdb/include/opcode/arm.h
@@ -0,0 +1,294 @@
+/* ARM opcode list.
+ Copyright (C) 1989, Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+GDB and GAS are free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB and GAS are distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB or GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* types of instruction (encoded in bits 26 and 27 of the instruction) */
+
+#define TYPE_ARITHMETIC 0
+#define TYPE_LDR_STR 1
+#define TYPE_BLOCK_BRANCH 2
+#define TYPE_SWI 3
+
+/* bit 25 decides whether an instruction is a block move or a branch */
+#define SUBTYPE_BLOCK 0
+#define SUBTYPE_BRANCH 1
+
+/* codes to distinguish the arithmetic instructions */
+
+#define OPCODE_AND 0
+#define OPCODE_EOR 1
+#define OPCODE_SUB 2
+#define OPCODE_RSB 3
+#define OPCODE_ADD 4
+#define OPCODE_ADC 5
+#define OPCODE_SBC 6
+#define OPCODE_RSC 7
+#define OPCODE_TST 8
+#define OPCODE_TEQ 9
+#define OPCODE_CMP 10
+#define OPCODE_CMN 11
+#define OPCODE_ORR 12
+#define OPCODE_MOV 13
+#define OPCODE_BIC 14
+#define OPCODE_MVN 15
+
+/* condition codes */
+
+#define COND_EQ 0
+#define COND_NE 1
+#define COND_CS 2
+#define COND_CC 3
+#define COND_MI 4
+#define COND_PL 5
+#define COND_VS 6
+#define COND_VC 7
+#define COND_HI 8
+#define COND_LS 9
+#define COND_GE 10
+#define COND_LT 11
+#define COND_GT 12
+#define COND_LE 13
+#define COND_AL 14
+#define COND_NV 15
+
+/* Describes the format of an ARM machine instruction */
+
+struct generic_fmt {
+ unsigned rest :25; /* the rest of the instruction */
+ unsigned subtype :1; /* used to decide between block and branch */
+ unsigned type :2; /* one of TYPE_* */
+ unsigned cond :4; /* one of COND_* defined above */
+};
+
+struct arith_fmt {
+ unsigned operand2 :12; /* #nn or rn or rn shift #m or rn shift rm */
+ unsigned dest :4; /* place where the answer goes */
+ unsigned operand1 :4; /* first operand to instruction */
+ unsigned set :1; /* == 1 means set processor flags */
+ unsigned opcode :4; /* one of OPCODE_* defined above */
+ unsigned immed :1; /* operand2 is an immediate value */
+ unsigned type :2; /* == TYPE_ARITHMETIC */
+ unsigned cond :4; /* one of COND_* defined above */
+};
+
+struct ldr_str_fmt {
+ unsigned offset :12; /* #nn or rn or rn shift #m */
+ unsigned reg :4; /* destination for LDR, source for STR */
+ unsigned base :4; /* base register */
+ unsigned is_load :1; /* == 1 for LDR */
+ unsigned writeback :1; /* == 1 means write back (base+offset) into base */
+ unsigned byte :1; /* == 1 means byte access else word */
+ unsigned up :1; /* == 1 means add offset else subtract it */
+ unsigned pre_index :1; /* == 1 means [a,b] form else [a],b form */
+ unsigned immed :1; /* == 0 means immediate offset */
+ unsigned type :2; /* == TYPE_LDR_STR */
+ unsigned cond :4; /* one of COND_* defined above */
+};
+
+struct block_fmt {
+ unsigned mask :16; /* register mask */
+ unsigned base :4; /* register used as base of move */
+ unsigned is_load :1; /* == 1 for LDM */
+ unsigned writeback :1; /* == 1 means update base after move */
+ unsigned set :1; /* == 1 means set flags in pc if included in mask */
+ unsigned increment :1; /* == 1 means increment base register */
+ unsigned before :1; /* == 1 means inc/dec before each move */
+ unsigned is_block :1; /* == SUBTYPE_BLOCK */
+ unsigned type :2; /* == TYPE_BLOCK_BRANCH */
+ unsigned cond :4; /* one of COND_* defined above */
+};
+
+struct branch_fmt {
+ unsigned dest :24; /* destination of the branch */
+ unsigned link :1; /* branch with link (function call) */
+ unsigned is_branch :1; /* == SUBTYPE_BRANCH */
+ unsigned type :2; /* == TYPE_BLOCK_BRANCH */
+ unsigned cond :4; /* one of COND_* defined above */
+};
+
+#define ROUND_N 0
+#define ROUND_P 1
+#define ROUND_M 2
+#define ROUND_Z 3
+
+#define FLOAT2_MVF 0
+#define FLOAT2_MNF 1
+#define FLOAT2_ABS 2
+#define FLOAT2_RND 3
+#define FLOAT2_SQT 4
+#define FLOAT2_LOG 5
+#define FLOAT2_LGN 6
+#define FLOAT2_EXP 7
+#define FLOAT2_SIN 8
+#define FLOAT2_COS 9
+#define FLOAT2_TAN 10
+#define FLOAT2_ASN 11
+#define FLOAT2_ACS 12
+#define FLOAT2_ATN 13
+
+#define FLOAT3_ADF 0
+#define FLOAT3_MUF 1
+#define FLOAT3_SUF 2
+#define FLOAT3_RSF 3
+#define FLOAT3_DVF 4
+#define FLOAT3_RDF 5
+#define FLOAT3_POW 6
+#define FLOAT3_RPW 7
+#define FLOAT3_RMF 8
+#define FLOAT3_FML 9
+#define FLOAT3_FDV 10
+#define FLOAT3_FRD 11
+#define FLOAT3_POL 12
+
+struct float2_fmt {
+ unsigned operand2 :3; /* second operand */
+ unsigned immed :1; /* == 1 if second operand is a constant */
+ unsigned pad1 :1; /* == 0 */
+ unsigned rounding :2; /* ROUND_* */
+ unsigned is_double :1; /* == 1 if precision is double (only if not extended) */
+ unsigned pad2 :4; /* == 1 */
+ unsigned dest :3; /* destination */
+ unsigned is_2_op :1; /* == 1 if 2 operand ins */
+ unsigned operand1 :3; /* first operand (only of is_2_op == 0) */
+ unsigned is_extended :1; /* == 1 if precision is extended */
+ unsigned opcode :4; /* FLOAT2_* or FLOAT3_* depending on is_2_op */
+ unsigned must_be_2 :2; /* == 2 */
+ unsigned type :2; /* == TYPE_SWI */
+ unsigned cond :4; /* COND_* */
+};
+
+struct swi_fmt {
+ unsigned argument :24; /* argument to SWI (syscall number) */
+ unsigned must_be_3 :2; /* == 3 */
+ unsigned type :2; /* == TYPE_SWI */
+ unsigned cond :4; /* one of COND_* defined above */
+};
+
+union insn_fmt {
+ struct generic_fmt generic;
+ struct arith_fmt arith;
+ struct ldr_str_fmt ldr_str;
+ struct block_fmt block;
+ struct branch_fmt branch;
+ struct swi_fmt swi;
+ unsigned long ins;
+};
+
+struct opcode {
+ unsigned long value, mask; /* recognise instruction if (op&mask)==value */
+ char *assembler; /* how to disassemble this instruction */
+};
+
+/* format of the assembler string :
+
+ %% %
+ %<bitfield>d print the bitfield in decimal
+ %<bitfield>x print the bitfield in hex
+ %<bitfield>r print as an ARM register
+ %<bitfield>f print a floating point constant if >7 else an fp register
+ %c print condition code (always bits 28-31)
+ %P print floating point precision in arithmetic insn
+ %Q print floating point precision in ldf/stf insn
+ %R print floating point rounding mode
+ %<bitnum>'c print specified char iff bit is one
+ %<bitnum>`c print specified char iff bit is zero
+ %<bitnum>?ab print a if bit is one else print b
+ %p print 'p' iff bits 12-15 are 15
+ %o print operand2 (immediate or register + shift)
+ %a print address for ldr/str instruction
+ %b print branch destination
+ %A print address for ldc/stc/ldf/stf instruction
+ %m print register mask for ldm/stm instruction
+*/
+
+static struct opcode opcodes[] = {
+ /* ARM instructions */
+ 0x00000090, 0x0fe000f0, "mul%20's %12-15r, %16-19r, %0-3r",
+ 0x00200090, 0x0fe000f0, "mla%20's %12-15r, %16-19r, %0-3r, %8-11r",
+ 0x00000000, 0x0de00000, "and%c%20's %12-15r, %16-19r, %o",
+ 0x00200000, 0x0de00000, "eor%c%20's %12-15r, %16-19r, %o",
+ 0x00400000, 0x0de00000, "sub%c%20's %12-15r, %16-19r, %o",
+ 0x00600000, 0x0de00000, "rsb%c%20's %12-15r, %16-19r, %o",
+ 0x00800000, 0x0de00000, "add%c%20's %12-15r, %16-19r, %o",
+ 0x00a00000, 0x0de00000, "adc%c%20's %12-15r, %16-19r, %o",
+ 0x00c00000, 0x0de00000, "sbc%c%20's %12-15r, %16-19r, %o",
+ 0x00e00000, 0x0de00000, "rsc%c%20's %12-15r, %16-19r, %o",
+ 0x01000000, 0x0de00000, "tst%c%p %16-19r, %o",
+ 0x01200000, 0x0de00000, "teq%c%p %16-19r, %o",
+ 0x01400000, 0x0de00000, "cmp%c%p %16-19r, %o",
+ 0x01600000, 0x0de00000, "cmn%c%p %16-19r, %o",
+ 0x01800000, 0x0de00000, "orr%c%20's %12-15r, %16-19r, %o",
+ 0x01a00000, 0x0de00000, "mov%c%20's %12-15r, %o",
+ 0x01c00000, 0x0de00000, "bic%c%20's %12-15r, %16-19r, %o",
+ 0x01e00000, 0x0de00000, "mvn%c%20's %12-15r, %o",
+ 0x04000000, 0x0c100000, "str%c%22'b %12-15r, %a",
+ 0x04100000, 0x0c100000, "ldr%c%22'b %12-15r, %a",
+ 0x08000000, 0x0e100000, "stm%c%23?id%24?ba %16-19r%22`!, %m",
+ 0x08100000, 0x0e100000, "ldm%c%23?id%24?ba %16-19r%22`!, %m%22'^",
+ 0x0a000000, 0x0e000000, "b%c%24'l %b",
+ 0x0f000000, 0x0f000000, "swi%c %0-23x",
+ /* Floating point coprocessor instructions */
+ 0x0e000100, 0x0ff08f10, "adf%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e100100, 0x0ff08f10, "muf%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e200100, 0x0ff08f10, "suf%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e300100, 0x0ff08f10, "rsf%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e400100, 0x0ff08f10, "dvf%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e500100, 0x0ff08f10, "rdf%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e600100, 0x0ff08f10, "pow%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e700100, 0x0ff08f10, "rpw%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e800100, 0x0ff08f10, "rmf%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e900100, 0x0ff08f10, "fml%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0ea00100, 0x0ff08f10, "fdv%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0eb00100, 0x0ff08f10, "frd%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0ec00100, 0x0ff08f10, "pol%c%P%R %12-14f, %16-18f, %0-3f",
+ 0x0e008100, 0x0ff08f10, "mvf%c%P%R %12-14f, %0-3f",
+ 0x0e108100, 0x0ff08f10, "mnf%c%P%R %12-14f, %0-3f",
+ 0x0e208100, 0x0ff08f10, "abs%c%P%R %12-14f, %0-3f",
+ 0x0e308100, 0x0ff08f10, "rnd%c%P%R %12-14f, %0-3f",
+ 0x0e408100, 0x0ff08f10, "sqt%c%P%R %12-14f, %0-3f",
+ 0x0e508100, 0x0ff08f10, "log%c%P%R %12-14f, %0-3f",
+ 0x0e608100, 0x0ff08f10, "lgn%c%P%R %12-14f, %0-3f",
+ 0x0e708100, 0x0ff08f10, "exp%c%P%R %12-14f, %0-3f",
+ 0x0e808100, 0x0ff08f10, "sin%c%P%R %12-14f, %0-3f",
+ 0x0e908100, 0x0ff08f10, "cos%c%P%R %12-14f, %0-3f",
+ 0x0ea08100, 0x0ff08f10, "tan%c%P%R %12-14f, %0-3f",
+ 0x0eb08100, 0x0ff08f10, "asn%c%P%R %12-14f, %0-3f",
+ 0x0ec08100, 0x0ff08f10, "acs%c%P%R %12-14f, %0-3f",
+ 0x0ed08100, 0x0ff08f10, "atn%c%P%R %12-14f, %0-3f",
+ 0x0e000110, 0x0ff00f1f, "flt%c%P%R %16-18f, %12-15r",
+ 0x0e100110, 0x0fff0f98, "fix%c%R %12-15r, %0-2f",
+ 0x0e200110, 0x0fff0fff, "wfs%c %12-15r",
+ 0x0e300110, 0x0fff0fff, "rfs%c %12-15r",
+ 0x0e400110, 0x0fff0fff, "wfc%c %12-15r",
+ 0x0e500110, 0x0fff0fff, "rfc%c %12-15r",
+ 0x0e90f110, 0x0ff8fff0, "cmf%c %16-18f, %0-3f",
+ 0x0eb0f110, 0x0ff8fff0, "cnf%c %16-18f, %0-3f",
+ 0x0ed0f110, 0x0ff8fff0, "cmfe%c %16-18f, %0-3f",
+ 0x0ef0f110, 0x0ff8fff0, "cnfe%c %16-18f, %0-3f",
+ 0x0c000100, 0x0e100f00, "stf%c%Q %12-14f, %A",
+ 0x0c100100, 0x0e100f00, "ldf%c%Q %12-14f, %A",
+ /* Generic coprocessor instructions */
+ 0x0e000000, 0x0f000010, "cdp%c %8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}",
+ 0x0e000010, 0x0f100010, "mrc%c %8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}",
+ 0x0e100010, 0x0f100010, "mcr%c %8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}",
+ 0x0c000000, 0x0e100000, "stc%c%22`l %8-11d, cr%12-15d, %A",
+ 0x0c100000, 0x0e100000, "ldc%c%22`l %8-11d, cr%12-15d, %A",
+ /* the rest */
+ 0x00000000, 0x00000000, "undefined instruction %0-31x",
+};
+#define N_OPCODES (sizeof opcodes / sizeof opcodes[0])
diff --git a/contrib/gdb/include/opcode/convex.h b/contrib/gdb/include/opcode/convex.h
new file mode 100644
index 0000000..efaeebb
--- /dev/null
+++ b/contrib/gdb/include/opcode/convex.h
@@ -0,0 +1,1711 @@
+/* Information for instruction disassembly on the Convex.
+ Copyright 1989, 1993 Free Software Foundation.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef CONST
+#define CONST
+#endif /* CONST */
+
+#define xxx 0
+#define rrr 1
+#define rr 2
+#define rxr 3
+#define r 4
+#define nops 5
+#define nr 6
+#define pcrel 7
+#define lr 8
+#define rxl 9
+#define rlr 10
+#define rrl 11
+#define iml 12
+#define imr 13
+#define a1r 14
+#define a1l 15
+#define a2r 16
+#define a2l 17
+#define a3 18
+#define a4 19
+#define a5 20
+#define V 1
+#define S 2
+#define VM 3
+#define A 4
+#define VL 5
+#define VS 6
+#define VLS 7
+#define PSW 8
+/* Prevent an error during "make depend". */
+#if !defined (PC)
+#define PC 9
+#endif
+#define ITR 10
+#define VV 11
+#define ITSR 12
+#define TOC 13
+#define CIR 14
+#define TTR 15
+#define VMU 16
+#define VML 17
+#define ICR 18
+#define TCPU 19
+#define CPUID 20
+#define TID 21
+
+CONST char *op[] = {
+ "",
+ "v0\0v1\0v2\0v3\0v4\0v5\0v6\0v7",
+ "s0\0s1\0s2\0s3\0s4\0s5\0s6\0s7",
+ "vm",
+ "sp\0a1\0a2\0a3\0a4\0a5\0ap\0fp",
+ "vl",
+ "vs",
+ "vls",
+ "psw",
+ "pc",
+ "itr",
+ "vv",
+ "itsr",
+ "toc",
+ "cir",
+ "ttr",
+ "vmu",
+ "vml",
+ "icr",
+ "tcpu",
+ "cpuid",
+ "tid",
+};
+
+CONST struct formstr format0[] = {
+ {0,0,rrr,V,S,S}, /* mov */
+ {0,0,rrr,S,S,V}, /* mov */
+ {1,1,rrr,V,V,V}, /* merg.t */
+ {2,1,rrr,V,V,V}, /* mask.t */
+ {1,2,rrr,V,S,V}, /* merg.f */
+ {2,2,rrr,V,S,V}, /* mask.f */
+ {1,1,rrr,V,S,V}, /* merg.t */
+ {2,1,rrr,V,S,V}, /* mask.t */
+ {3,3,rrr,V,V,V}, /* mul.s */
+ {3,4,rrr,V,V,V}, /* mul.d */
+ {4,3,rrr,V,V,V}, /* div.s */
+ {4,4,rrr,V,V,V}, /* div.d */
+ {3,3,rrr,V,S,V}, /* mul.s */
+ {3,4,rrr,V,S,V}, /* mul.d */
+ {4,3,rrr,V,S,V}, /* div.s */
+ {4,4,rrr,V,S,V}, /* div.d */
+ {5,0,rrr,V,V,V}, /* and */
+ {6,0,rrr,V,V,V}, /* or */
+ {7,0,rrr,V,V,V}, /* xor */
+ {8,0,rrr,V,V,V}, /* shf */
+ {5,0,rrr,V,S,V}, /* and */
+ {6,0,rrr,V,S,V}, /* or */
+ {7,0,rrr,V,S,V}, /* xor */
+ {8,0,rrr,V,S,V}, /* shf */
+ {9,3,rrr,V,V,V}, /* add.s */
+ {9,4,rrr,V,V,V}, /* add.d */
+ {10,3,rrr,V,V,V}, /* sub.s */
+ {10,4,rrr,V,V,V}, /* sub.d */
+ {9,3,rrr,V,S,V}, /* add.s */
+ {9,4,rrr,V,S,V}, /* add.d */
+ {10,3,rrr,V,S,V}, /* sub.s */
+ {10,4,rrr,V,S,V}, /* sub.d */
+ {9,5,rrr,V,V,V}, /* add.b */
+ {9,6,rrr,V,V,V}, /* add.h */
+ {9,7,rrr,V,V,V}, /* add.w */
+ {9,8,rrr,V,V,V}, /* add.l */
+ {9,5,rrr,V,S,V}, /* add.b */
+ {9,6,rrr,V,S,V}, /* add.h */
+ {9,7,rrr,V,S,V}, /* add.w */
+ {9,8,rrr,V,S,V}, /* add.l */
+ {10,5,rrr,V,V,V}, /* sub.b */
+ {10,6,rrr,V,V,V}, /* sub.h */
+ {10,7,rrr,V,V,V}, /* sub.w */
+ {10,8,rrr,V,V,V}, /* sub.l */
+ {10,5,rrr,V,S,V}, /* sub.b */
+ {10,6,rrr,V,S,V}, /* sub.h */
+ {10,7,rrr,V,S,V}, /* sub.w */
+ {10,8,rrr,V,S,V}, /* sub.l */
+ {3,5,rrr,V,V,V}, /* mul.b */
+ {3,6,rrr,V,V,V}, /* mul.h */
+ {3,7,rrr,V,V,V}, /* mul.w */
+ {3,8,rrr,V,V,V}, /* mul.l */
+ {3,5,rrr,V,S,V}, /* mul.b */
+ {3,6,rrr,V,S,V}, /* mul.h */
+ {3,7,rrr,V,S,V}, /* mul.w */
+ {3,8,rrr,V,S,V}, /* mul.l */
+ {4,5,rrr,V,V,V}, /* div.b */
+ {4,6,rrr,V,V,V}, /* div.h */
+ {4,7,rrr,V,V,V}, /* div.w */
+ {4,8,rrr,V,V,V}, /* div.l */
+ {4,5,rrr,V,S,V}, /* div.b */
+ {4,6,rrr,V,S,V}, /* div.h */
+ {4,7,rrr,V,S,V}, /* div.w */
+ {4,8,rrr,V,S,V}, /* div.l */
+};
+
+CONST struct formstr format1[] = {
+ {11,0,xxx,0,0,0}, /* exit */
+ {12,0,a3,0,0,0}, /* jmp */
+ {13,2,a3,0,0,0}, /* jmpi.f */
+ {13,1,a3,0,0,0}, /* jmpi.t */
+ {14,2,a3,0,0,0}, /* jmpa.f */
+ {14,1,a3,0,0,0}, /* jmpa.t */
+ {15,2,a3,0,0,0}, /* jmps.f */
+ {15,1,a3,0,0,0}, /* jmps.t */
+ {16,0,a3,0,0,0}, /* tac */
+ {17,0,a1r,A,0,0}, /* ldea */
+ {18,8,a1l,VLS,0,0}, /* ld.l */
+ {18,9,a1l,VM,0,0}, /* ld.x */
+ {19,0,a3,0,0,0}, /* tas */
+ {20,0,a3,0,0,0}, /* pshea */
+ {21,8,a2l,VLS,0,0}, /* st.l */
+ {21,9,a2l,VM,0,0}, /* st.x */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {22,0,a3,0,0,0}, /* call */
+ {23,0,a3,0,0,0}, /* calls */
+ {24,0,a3,0,0,0}, /* callq */
+ {25,0,a1r,A,0,0}, /* pfork */
+ {26,5,a2r,S,0,0}, /* ste.b */
+ {26,6,a2r,S,0,0}, /* ste.h */
+ {26,7,a2r,S,0,0}, /* ste.w */
+ {26,8,a2r,S,0,0}, /* ste.l */
+ {18,5,a1r,A,0,0}, /* ld.b */
+ {18,6,a1r,A,0,0}, /* ld.h */
+ {18,7,a1r,A,0,0}, /* ld.w */
+ {27,7,a1r,A,0,0}, /* incr.w */
+ {21,5,a2r,A,0,0}, /* st.b */
+ {21,6,a2r,A,0,0}, /* st.h */
+ {21,7,a2r,A,0,0}, /* st.w */
+ {27,8,a1r,S,0,0}, /* incr.l */
+ {18,5,a1r,S,0,0}, /* ld.b */
+ {18,6,a1r,S,0,0}, /* ld.h */
+ {18,7,a1r,S,0,0}, /* ld.w */
+ {18,8,a1r,S,0,0}, /* ld.l */
+ {21,5,a2r,S,0,0}, /* st.b */
+ {21,6,a2r,S,0,0}, /* st.h */
+ {21,7,a2r,S,0,0}, /* st.w */
+ {21,8,a2r,S,0,0}, /* st.l */
+ {18,5,a1r,V,0,0}, /* ld.b */
+ {18,6,a1r,V,0,0}, /* ld.h */
+ {18,7,a1r,V,0,0}, /* ld.w */
+ {18,8,a1r,V,0,0}, /* ld.l */
+ {21,5,a2r,V,0,0}, /* st.b */
+ {21,6,a2r,V,0,0}, /* st.h */
+ {21,7,a2r,V,0,0}, /* st.w */
+ {21,8,a2r,V,0,0}, /* st.l */
+};
+
+CONST struct formstr format2[] = {
+ {28,5,rr,A,A,0}, /* cvtw.b */
+ {28,6,rr,A,A,0}, /* cvtw.h */
+ {29,7,rr,A,A,0}, /* cvtb.w */
+ {30,7,rr,A,A,0}, /* cvth.w */
+ {28,5,rr,S,S,0}, /* cvtw.b */
+ {28,6,rr,S,S,0}, /* cvtw.h */
+ {29,7,rr,S,S,0}, /* cvtb.w */
+ {30,7,rr,S,S,0}, /* cvth.w */
+ {28,3,rr,S,S,0}, /* cvtw.s */
+ {31,7,rr,S,S,0}, /* cvts.w */
+ {32,3,rr,S,S,0}, /* cvtd.s */
+ {31,4,rr,S,S,0}, /* cvts.d */
+ {31,8,rr,S,S,0}, /* cvts.l */
+ {32,8,rr,S,S,0}, /* cvtd.l */
+ {33,3,rr,S,S,0}, /* cvtl.s */
+ {33,4,rr,S,S,0}, /* cvtl.d */
+ {34,0,rr,A,A,0}, /* ldpa */
+ {8,0,nr,A,0,0}, /* shf */
+ {18,6,nr,A,0,0}, /* ld.h */
+ {18,7,nr,A,0,0}, /* ld.w */
+ {33,7,rr,S,S,0}, /* cvtl.w */
+ {28,8,rr,S,S,0}, /* cvtw.l */
+ {35,1,rr,S,S,0}, /* plc.t */
+ {36,0,rr,S,S,0}, /* tzc */
+ {37,6,rr,A,A,0}, /* eq.h */
+ {37,7,rr,A,A,0}, /* eq.w */
+ {37,6,nr,A,0,0}, /* eq.h */
+ {37,7,nr,A,0,0}, /* eq.w */
+ {37,5,rr,S,S,0}, /* eq.b */
+ {37,6,rr,S,S,0}, /* eq.h */
+ {37,7,rr,S,S,0}, /* eq.w */
+ {37,8,rr,S,S,0}, /* eq.l */
+ {38,6,rr,A,A,0}, /* leu.h */
+ {38,7,rr,A,A,0}, /* leu.w */
+ {38,6,nr,A,0,0}, /* leu.h */
+ {38,7,nr,A,0,0}, /* leu.w */
+ {38,5,rr,S,S,0}, /* leu.b */
+ {38,6,rr,S,S,0}, /* leu.h */
+ {38,7,rr,S,S,0}, /* leu.w */
+ {38,8,rr,S,S,0}, /* leu.l */
+ {39,6,rr,A,A,0}, /* ltu.h */
+ {39,7,rr,A,A,0}, /* ltu.w */
+ {39,6,nr,A,0,0}, /* ltu.h */
+ {39,7,nr,A,0,0}, /* ltu.w */
+ {39,5,rr,S,S,0}, /* ltu.b */
+ {39,6,rr,S,S,0}, /* ltu.h */
+ {39,7,rr,S,S,0}, /* ltu.w */
+ {39,8,rr,S,S,0}, /* ltu.l */
+ {40,6,rr,A,A,0}, /* le.h */
+ {40,7,rr,A,A,0}, /* le.w */
+ {40,6,nr,A,0,0}, /* le.h */
+ {40,7,nr,A,0,0}, /* le.w */
+ {40,5,rr,S,S,0}, /* le.b */
+ {40,6,rr,S,S,0}, /* le.h */
+ {40,7,rr,S,S,0}, /* le.w */
+ {40,8,rr,S,S,0}, /* le.l */
+ {41,6,rr,A,A,0}, /* lt.h */
+ {41,7,rr,A,A,0}, /* lt.w */
+ {41,6,nr,A,0,0}, /* lt.h */
+ {41,7,nr,A,0,0}, /* lt.w */
+ {41,5,rr,S,S,0}, /* lt.b */
+ {41,6,rr,S,S,0}, /* lt.h */
+ {41,7,rr,S,S,0}, /* lt.w */
+ {41,8,rr,S,S,0}, /* lt.l */
+ {9,7,rr,S,A,0}, /* add.w */
+ {8,0,rr,A,A,0}, /* shf */
+ {0,0,rr,A,A,0}, /* mov */
+ {0,0,rr,S,A,0}, /* mov */
+ {0,7,rr,S,S,0}, /* mov.w */
+ {8,0,rr,S,S,0}, /* shf */
+ {0,0,rr,S,S,0}, /* mov */
+ {0,0,rr,A,S,0}, /* mov */
+ {5,0,rr,A,A,0}, /* and */
+ {6,0,rr,A,A,0}, /* or */
+ {7,0,rr,A,A,0}, /* xor */
+ {42,0,rr,A,A,0}, /* not */
+ {5,0,rr,S,S,0}, /* and */
+ {6,0,rr,S,S,0}, /* or */
+ {7,0,rr,S,S,0}, /* xor */
+ {42,0,rr,S,S,0}, /* not */
+ {40,3,rr,S,S,0}, /* le.s */
+ {40,4,rr,S,S,0}, /* le.d */
+ {41,3,rr,S,S,0}, /* lt.s */
+ {41,4,rr,S,S,0}, /* lt.d */
+ {9,3,rr,S,S,0}, /* add.s */
+ {9,4,rr,S,S,0}, /* add.d */
+ {10,3,rr,S,S,0}, /* sub.s */
+ {10,4,rr,S,S,0}, /* sub.d */
+ {37,3,rr,S,S,0}, /* eq.s */
+ {37,4,rr,S,S,0}, /* eq.d */
+ {43,6,rr,A,A,0}, /* neg.h */
+ {43,7,rr,A,A,0}, /* neg.w */
+ {3,3,rr,S,S,0}, /* mul.s */
+ {3,4,rr,S,S,0}, /* mul.d */
+ {4,3,rr,S,S,0}, /* div.s */
+ {4,4,rr,S,S,0}, /* div.d */
+ {9,6,rr,A,A,0}, /* add.h */
+ {9,7,rr,A,A,0}, /* add.w */
+ {9,6,nr,A,0,0}, /* add.h */
+ {9,7,nr,A,0,0}, /* add.w */
+ {9,5,rr,S,S,0}, /* add.b */
+ {9,6,rr,S,S,0}, /* add.h */
+ {9,7,rr,S,S,0}, /* add.w */
+ {9,8,rr,S,S,0}, /* add.l */
+ {10,6,rr,A,A,0}, /* sub.h */
+ {10,7,rr,A,A,0}, /* sub.w */
+ {10,6,nr,A,0,0}, /* sub.h */
+ {10,7,nr,A,0,0}, /* sub.w */
+ {10,5,rr,S,S,0}, /* sub.b */
+ {10,6,rr,S,S,0}, /* sub.h */
+ {10,7,rr,S,S,0}, /* sub.w */
+ {10,8,rr,S,S,0}, /* sub.l */
+ {3,6,rr,A,A,0}, /* mul.h */
+ {3,7,rr,A,A,0}, /* mul.w */
+ {3,6,nr,A,0,0}, /* mul.h */
+ {3,7,nr,A,0,0}, /* mul.w */
+ {3,5,rr,S,S,0}, /* mul.b */
+ {3,6,rr,S,S,0}, /* mul.h */
+ {3,7,rr,S,S,0}, /* mul.w */
+ {3,8,rr,S,S,0}, /* mul.l */
+ {4,6,rr,A,A,0}, /* div.h */
+ {4,7,rr,A,A,0}, /* div.w */
+ {4,6,nr,A,0,0}, /* div.h */
+ {4,7,nr,A,0,0}, /* div.w */
+ {4,5,rr,S,S,0}, /* div.b */
+ {4,6,rr,S,S,0}, /* div.h */
+ {4,7,rr,S,S,0}, /* div.w */
+ {4,8,rr,S,S,0}, /* div.l */
+};
+
+CONST struct formstr format3[] = {
+ {32,3,rr,V,V,0}, /* cvtd.s */
+ {31,4,rr,V,V,0}, /* cvts.d */
+ {33,4,rr,V,V,0}, /* cvtl.d */
+ {32,8,rr,V,V,0}, /* cvtd.l */
+ {0,0,rrl,S,S,VM}, /* mov */
+ {0,0,rlr,S,VM,S}, /* mov */
+ {0,0,0,0,0,0},
+ {44,0,rr,S,S,0}, /* lop */
+ {36,0,rr,V,V,0}, /* tzc */
+ {44,0,rr,V,V,0}, /* lop */
+ {0,0,0,0,0,0},
+ {42,0,rr,V,V,0}, /* not */
+ {8,0,rr,S,V,0}, /* shf */
+ {35,1,rr,V,V,0}, /* plc.t */
+ {45,2,rr,V,V,0}, /* cprs.f */
+ {45,1,rr,V,V,0}, /* cprs.t */
+ {37,3,rr,V,V,0}, /* eq.s */
+ {37,4,rr,V,V,0}, /* eq.d */
+ {43,3,rr,V,V,0}, /* neg.s */
+ {43,4,rr,V,V,0}, /* neg.d */
+ {37,3,rr,S,V,0}, /* eq.s */
+ {37,4,rr,S,V,0}, /* eq.d */
+ {43,3,rr,S,S,0}, /* neg.s */
+ {43,4,rr,S,S,0}, /* neg.d */
+ {40,3,rr,V,V,0}, /* le.s */
+ {40,4,rr,V,V,0}, /* le.d */
+ {41,3,rr,V,V,0}, /* lt.s */
+ {41,4,rr,V,V,0}, /* lt.d */
+ {40,3,rr,S,V,0}, /* le.s */
+ {40,4,rr,S,V,0}, /* le.d */
+ {41,3,rr,S,V,0}, /* lt.s */
+ {41,4,rr,S,V,0}, /* lt.d */
+ {37,5,rr,V,V,0}, /* eq.b */
+ {37,6,rr,V,V,0}, /* eq.h */
+ {37,7,rr,V,V,0}, /* eq.w */
+ {37,8,rr,V,V,0}, /* eq.l */
+ {37,5,rr,S,V,0}, /* eq.b */
+ {37,6,rr,S,V,0}, /* eq.h */
+ {37,7,rr,S,V,0}, /* eq.w */
+ {37,8,rr,S,V,0}, /* eq.l */
+ {40,5,rr,V,V,0}, /* le.b */
+ {40,6,rr,V,V,0}, /* le.h */
+ {40,7,rr,V,V,0}, /* le.w */
+ {40,8,rr,V,V,0}, /* le.l */
+ {40,5,rr,S,V,0}, /* le.b */
+ {40,6,rr,S,V,0}, /* le.h */
+ {40,7,rr,S,V,0}, /* le.w */
+ {40,8,rr,S,V,0}, /* le.l */
+ {41,5,rr,V,V,0}, /* lt.b */
+ {41,6,rr,V,V,0}, /* lt.h */
+ {41,7,rr,V,V,0}, /* lt.w */
+ {41,8,rr,V,V,0}, /* lt.l */
+ {41,5,rr,S,V,0}, /* lt.b */
+ {41,6,rr,S,V,0}, /* lt.h */
+ {41,7,rr,S,V,0}, /* lt.w */
+ {41,8,rr,S,V,0}, /* lt.l */
+ {43,5,rr,V,V,0}, /* neg.b */
+ {43,6,rr,V,V,0}, /* neg.h */
+ {43,7,rr,V,V,0}, /* neg.w */
+ {43,8,rr,V,V,0}, /* neg.l */
+ {43,5,rr,S,S,0}, /* neg.b */
+ {43,6,rr,S,S,0}, /* neg.h */
+ {43,7,rr,S,S,0}, /* neg.w */
+ {43,8,rr,S,S,0}, /* neg.l */
+};
+
+CONST struct formstr format4[] = {
+ {46,0,nops,0,0,0}, /* nop */
+ {47,0,pcrel,0,0,0}, /* br */
+ {48,2,pcrel,0,0,0}, /* bri.f */
+ {48,1,pcrel,0,0,0}, /* bri.t */
+ {49,2,pcrel,0,0,0}, /* bra.f */
+ {49,1,pcrel,0,0,0}, /* bra.t */
+ {50,2,pcrel,0,0,0}, /* brs.f */
+ {50,1,pcrel,0,0,0}, /* brs.t */
+};
+
+CONST struct formstr format5[] = {
+ {51,5,rr,V,V,0}, /* ldvi.b */
+ {51,6,rr,V,V,0}, /* ldvi.h */
+ {51,7,rr,V,V,0}, /* ldvi.w */
+ {51,8,rr,V,V,0}, /* ldvi.l */
+ {28,3,rr,V,V,0}, /* cvtw.s */
+ {31,7,rr,V,V,0}, /* cvts.w */
+ {28,8,rr,V,V,0}, /* cvtw.l */
+ {33,7,rr,V,V,0}, /* cvtl.w */
+ {52,5,rxr,V,V,0}, /* stvi.b */
+ {52,6,rxr,V,V,0}, /* stvi.h */
+ {52,7,rxr,V,V,0}, /* stvi.w */
+ {52,8,rxr,V,V,0}, /* stvi.l */
+ {52,5,rxr,S,V,0}, /* stvi.b */
+ {52,6,rxr,S,V,0}, /* stvi.h */
+ {52,7,rxr,S,V,0}, /* stvi.w */
+ {52,8,rxr,S,V,0}, /* stvi.l */
+};
+
+CONST struct formstr format6[] = {
+ {53,0,r,A,0,0}, /* ldsdr */
+ {54,0,r,A,0,0}, /* ldkdr */
+ {55,3,r,S,0,0}, /* ln.s */
+ {55,4,r,S,0,0}, /* ln.d */
+ {56,0,nops,0,0,0}, /* patu */
+ {57,0,r,A,0,0}, /* pate */
+ {58,0,nops,0,0,0}, /* pich */
+ {59,0,nops,0,0,0}, /* plch */
+ {0,0,lr,PSW,A,0}, /* mov */
+ {0,0,rxl,A,PSW,0}, /* mov */
+ {0,0,lr,PC,A,0}, /* mov */
+ {60,0,r,S,0,0}, /* idle */
+ {0,0,lr,ITR,S,0}, /* mov */
+ {0,0,rxl,S,ITR,0}, /* mov */
+ {0,0,0,0,0,0},
+ {0,0,rxl,S,ITSR,0}, /* mov */
+ {61,0,nops,0,0,0}, /* rtnq */
+ {62,0,nops,0,0,0}, /* cfork */
+ {63,0,nops,0,0,0}, /* rtn */
+ {64,0,nops,0,0,0}, /* wfork */
+ {65,0,nops,0,0,0}, /* join */
+ {66,0,nops,0,0,0}, /* rtnc */
+ {67,3,r,S,0,0}, /* exp.s */
+ {67,4,r,S,0,0}, /* exp.d */
+ {68,3,r,S,0,0}, /* sin.s */
+ {68,4,r,S,0,0}, /* sin.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {69,3,r,S,0,0}, /* cos.s */
+ {69,4,r,S,0,0}, /* cos.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {70,7,r,A,0,0}, /* psh.w */
+ {0,0,0,0,0,0},
+ {71,7,r,A,0,0}, /* pop.w */
+ {0,0,0,0,0,0},
+ {70,7,r,S,0,0}, /* psh.w */
+ {70,8,r,S,0,0}, /* psh.l */
+ {71,7,r,S,0,0}, /* pop.w */
+ {71,8,r,S,0,0}, /* pop.l */
+ {72,0,nops,0,0,0}, /* eni */
+ {73,0,nops,0,0,0}, /* dsi */
+ {74,0,nops,0,0,0}, /* bkpt */
+ {75,0,nops,0,0,0}, /* msync */
+ {76,0,r,S,0,0}, /* mski */
+ {77,0,r,S,0,0}, /* xmti */
+ {0,0,rxl,S,VV,0}, /* mov */
+ {78,0,nops,0,0,0}, /* tstvv */
+ {0,0,lr,VS,A,0}, /* mov */
+ {0,0,rxl,A,VS,0}, /* mov */
+ {0,0,lr,VL,A,0}, /* mov */
+ {0,0,rxl,A,VL,0}, /* mov */
+ {0,7,lr,VS,S,0}, /* mov.w */
+ {0,7,rxl,S,VS,0}, /* mov.w */
+ {0,7,lr,VL,S,0}, /* mov.w */
+ {0,7,rxl,S,VL,0}, /* mov.w */
+ {79,0,r,A,0,0}, /* diag */
+ {80,0,nops,0,0,0}, /* pbkpt */
+ {81,3,r,S,0,0}, /* sqrt.s */
+ {81,4,r,S,0,0}, /* sqrt.d */
+ {82,0,nops,0,0,0}, /* casr */
+ {0,0,0,0,0,0},
+ {83,3,r,S,0,0}, /* atan.s */
+ {83,4,r,S,0,0}, /* atan.d */
+};
+
+CONST struct formstr format7[] = {
+ {84,5,r,V,0,0}, /* sum.b */
+ {84,6,r,V,0,0}, /* sum.h */
+ {84,7,r,V,0,0}, /* sum.w */
+ {84,8,r,V,0,0}, /* sum.l */
+ {85,0,r,V,0,0}, /* all */
+ {86,0,r,V,0,0}, /* any */
+ {87,0,r,V,0,0}, /* parity */
+ {0,0,0,0,0,0},
+ {88,5,r,V,0,0}, /* max.b */
+ {88,6,r,V,0,0}, /* max.h */
+ {88,7,r,V,0,0}, /* max.w */
+ {88,8,r,V,0,0}, /* max.l */
+ {89,5,r,V,0,0}, /* min.b */
+ {89,6,r,V,0,0}, /* min.h */
+ {89,7,r,V,0,0}, /* min.w */
+ {89,8,r,V,0,0}, /* min.l */
+ {84,3,r,V,0,0}, /* sum.s */
+ {84,4,r,V,0,0}, /* sum.d */
+ {90,3,r,V,0,0}, /* prod.s */
+ {90,4,r,V,0,0}, /* prod.d */
+ {88,3,r,V,0,0}, /* max.s */
+ {88,4,r,V,0,0}, /* max.d */
+ {89,3,r,V,0,0}, /* min.s */
+ {89,4,r,V,0,0}, /* min.d */
+ {90,5,r,V,0,0}, /* prod.b */
+ {90,6,r,V,0,0}, /* prod.h */
+ {90,7,r,V,0,0}, /* prod.w */
+ {90,8,r,V,0,0}, /* prod.l */
+ {35,2,lr,VM,S,0}, /* plc.f */
+ {35,1,lr,VM,S,0}, /* plc.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr formatx[] = {
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr format1a[] = {
+ {91,0,imr,A,0,0}, /* halt */
+ {92,0,a4,0,0,0}, /* sysc */
+ {18,6,imr,A,0,0}, /* ld.h */
+ {18,7,imr,A,0,0}, /* ld.w */
+ {5,0,imr,A,0,0}, /* and */
+ {6,0,imr,A,0,0}, /* or */
+ {7,0,imr,A,0,0}, /* xor */
+ {8,0,imr,A,0,0}, /* shf */
+ {9,6,imr,A,0,0}, /* add.h */
+ {9,7,imr,A,0,0}, /* add.w */
+ {10,6,imr,A,0,0}, /* sub.h */
+ {10,7,imr,A,0,0}, /* sub.w */
+ {3,6,imr,A,0,0}, /* mul.h */
+ {3,7,imr,A,0,0}, /* mul.w */
+ {4,6,imr,A,0,0}, /* div.h */
+ {4,7,imr,A,0,0}, /* div.w */
+ {18,7,iml,VL,0,0}, /* ld.w */
+ {18,7,iml,VS,0,0}, /* ld.w */
+ {0,0,0,0,0,0},
+ {8,7,imr,S,0,0}, /* shf.w */
+ {93,0,a5,0,0,0}, /* trap */
+ {0,0,0,0,0,0},
+ {37,6,imr,A,0,0}, /* eq.h */
+ {37,7,imr,A,0,0}, /* eq.w */
+ {38,6,imr,A,0,0}, /* leu.h */
+ {38,7,imr,A,0,0}, /* leu.w */
+ {39,6,imr,A,0,0}, /* ltu.h */
+ {39,7,imr,A,0,0}, /* ltu.w */
+ {40,6,imr,A,0,0}, /* le.h */
+ {40,7,imr,A,0,0}, /* le.w */
+ {41,6,imr,A,0,0}, /* lt.h */
+ {41,7,imr,A,0,0}, /* lt.w */
+};
+
+CONST struct formstr format1b[] = {
+ {18,4,imr,S,0,0}, /* ld.d */
+ {18,10,imr,S,0,0}, /* ld.u */
+ {18,8,imr,S,0,0}, /* ld.l */
+ {18,7,imr,S,0,0}, /* ld.w */
+ {5,0,imr,S,0,0}, /* and */
+ {6,0,imr,S,0,0}, /* or */
+ {7,0,imr,S,0,0}, /* xor */
+ {8,0,imr,S,0,0}, /* shf */
+ {9,6,imr,S,0,0}, /* add.h */
+ {9,7,imr,S,0,0}, /* add.w */
+ {10,6,imr,S,0,0}, /* sub.h */
+ {10,7,imr,S,0,0}, /* sub.w */
+ {3,6,imr,S,0,0}, /* mul.h */
+ {3,7,imr,S,0,0}, /* mul.w */
+ {4,6,imr,S,0,0}, /* div.h */
+ {4,7,imr,S,0,0}, /* div.w */
+ {9,3,imr,S,0,0}, /* add.s */
+ {10,3,imr,S,0,0}, /* sub.s */
+ {3,3,imr,S,0,0}, /* mul.s */
+ {4,3,imr,S,0,0}, /* div.s */
+ {40,3,imr,S,0,0}, /* le.s */
+ {41,3,imr,S,0,0}, /* lt.s */
+ {37,6,imr,S,0,0}, /* eq.h */
+ {37,7,imr,S,0,0}, /* eq.w */
+ {38,6,imr,S,0,0}, /* leu.h */
+ {38,7,imr,S,0,0}, /* leu.w */
+ {39,6,imr,S,0,0}, /* ltu.h */
+ {39,7,imr,S,0,0}, /* ltu.w */
+ {40,6,imr,S,0,0}, /* le.h */
+ {40,7,imr,S,0,0}, /* le.w */
+ {41,6,imr,S,0,0}, /* lt.h */
+ {41,7,imr,S,0,0}, /* lt.w */
+};
+
+CONST struct formstr e0_format0[] = {
+ {10,3,rrr,S,V,V}, /* sub.s */
+ {10,4,rrr,S,V,V}, /* sub.d */
+ {4,3,rrr,S,V,V}, /* div.s */
+ {4,4,rrr,S,V,V}, /* div.d */
+ {10,11,rrr,S,V,V}, /* sub.s.f */
+ {10,12,rrr,S,V,V}, /* sub.d.f */
+ {4,11,rrr,S,V,V}, /* div.s.f */
+ {4,12,rrr,S,V,V}, /* div.d.f */
+ {3,11,rrr,V,V,V}, /* mul.s.f */
+ {3,12,rrr,V,V,V}, /* mul.d.f */
+ {4,11,rrr,V,V,V}, /* div.s.f */
+ {4,12,rrr,V,V,V}, /* div.d.f */
+ {3,11,rrr,V,S,V}, /* mul.s.f */
+ {3,12,rrr,V,S,V}, /* mul.d.f */
+ {4,11,rrr,V,S,V}, /* div.s.f */
+ {4,12,rrr,V,S,V}, /* div.d.f */
+ {5,2,rrr,V,V,V}, /* and.f */
+ {6,2,rrr,V,V,V}, /* or.f */
+ {7,2,rrr,V,V,V}, /* xor.f */
+ {8,2,rrr,V,V,V}, /* shf.f */
+ {5,2,rrr,V,S,V}, /* and.f */
+ {6,2,rrr,V,S,V}, /* or.f */
+ {7,2,rrr,V,S,V}, /* xor.f */
+ {8,2,rrr,V,S,V}, /* shf.f */
+ {9,11,rrr,V,V,V}, /* add.s.f */
+ {9,12,rrr,V,V,V}, /* add.d.f */
+ {10,11,rrr,V,V,V}, /* sub.s.f */
+ {10,12,rrr,V,V,V}, /* sub.d.f */
+ {9,11,rrr,V,S,V}, /* add.s.f */
+ {9,12,rrr,V,S,V}, /* add.d.f */
+ {10,11,rrr,V,S,V}, /* sub.s.f */
+ {10,12,rrr,V,S,V}, /* sub.d.f */
+ {9,13,rrr,V,V,V}, /* add.b.f */
+ {9,14,rrr,V,V,V}, /* add.h.f */
+ {9,15,rrr,V,V,V}, /* add.w.f */
+ {9,16,rrr,V,V,V}, /* add.l.f */
+ {9,13,rrr,V,S,V}, /* add.b.f */
+ {9,14,rrr,V,S,V}, /* add.h.f */
+ {9,15,rrr,V,S,V}, /* add.w.f */
+ {9,16,rrr,V,S,V}, /* add.l.f */
+ {10,13,rrr,V,V,V}, /* sub.b.f */
+ {10,14,rrr,V,V,V}, /* sub.h.f */
+ {10,15,rrr,V,V,V}, /* sub.w.f */
+ {10,16,rrr,V,V,V}, /* sub.l.f */
+ {10,13,rrr,V,S,V}, /* sub.b.f */
+ {10,14,rrr,V,S,V}, /* sub.h.f */
+ {10,15,rrr,V,S,V}, /* sub.w.f */
+ {10,16,rrr,V,S,V}, /* sub.l.f */
+ {3,13,rrr,V,V,V}, /* mul.b.f */
+ {3,14,rrr,V,V,V}, /* mul.h.f */
+ {3,15,rrr,V,V,V}, /* mul.w.f */
+ {3,16,rrr,V,V,V}, /* mul.l.f */
+ {3,13,rrr,V,S,V}, /* mul.b.f */
+ {3,14,rrr,V,S,V}, /* mul.h.f */
+ {3,15,rrr,V,S,V}, /* mul.w.f */
+ {3,16,rrr,V,S,V}, /* mul.l.f */
+ {4,13,rrr,V,V,V}, /* div.b.f */
+ {4,14,rrr,V,V,V}, /* div.h.f */
+ {4,15,rrr,V,V,V}, /* div.w.f */
+ {4,16,rrr,V,V,V}, /* div.l.f */
+ {4,13,rrr,V,S,V}, /* div.b.f */
+ {4,14,rrr,V,S,V}, /* div.h.f */
+ {4,15,rrr,V,S,V}, /* div.w.f */
+ {4,16,rrr,V,S,V}, /* div.l.f */
+};
+
+CONST struct formstr e0_format1[] = {
+ {0,0,0,0,0,0},
+ {94,0,a3,0,0,0}, /* tst */
+ {95,0,a3,0,0,0}, /* lck */
+ {96,0,a3,0,0,0}, /* ulk */
+ {17,0,a1r,S,0,0}, /* ldea */
+ {97,0,a1r,A,0,0}, /* spawn */
+ {98,0,a1r,A,0,0}, /* ldcmr */
+ {99,0,a2r,A,0,0}, /* stcmr */
+ {100,0,a1r,A,0,0}, /* popr */
+ {101,0,a2r,A,0,0}, /* pshr */
+ {102,7,a1r,A,0,0}, /* rcvr.w */
+ {103,7,a2r,A,0,0}, /* matm.w */
+ {104,7,a2r,A,0,0}, /* sndr.w */
+ {104,8,a2r,S,0,0}, /* sndr.l */
+ {102,8,a1r,S,0,0}, /* rcvr.l */
+ {103,8,a2r,S,0,0}, /* matm.l */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {105,7,a2r,A,0,0}, /* putr.w */
+ {105,8,a2r,S,0,0}, /* putr.l */
+ {106,7,a1r,A,0,0}, /* getr.w */
+ {106,8,a1r,S,0,0}, /* getr.l */
+ {26,13,a2r,S,0,0}, /* ste.b.f */
+ {26,14,a2r,S,0,0}, /* ste.h.f */
+ {26,15,a2r,S,0,0}, /* ste.w.f */
+ {26,16,a2r,S,0,0}, /* ste.l.f */
+ {107,7,a2r,A,0,0}, /* matr.w */
+ {108,7,a2r,A,0,0}, /* mat.w */
+ {109,7,a1r,A,0,0}, /* get.w */
+ {110,7,a1r,A,0,0}, /* rcv.w */
+ {0,0,0,0,0,0},
+ {111,7,a1r,A,0,0}, /* inc.w */
+ {112,7,a2r,A,0,0}, /* put.w */
+ {113,7,a2r,A,0,0}, /* snd.w */
+ {107,8,a2r,S,0,0}, /* matr.l */
+ {108,8,a2r,S,0,0}, /* mat.l */
+ {109,8,a1r,S,0,0}, /* get.l */
+ {110,8,a1r,S,0,0}, /* rcv.l */
+ {0,0,0,0,0,0},
+ {111,8,a1r,S,0,0}, /* inc.l */
+ {112,8,a2r,S,0,0}, /* put.l */
+ {113,8,a2r,S,0,0}, /* snd.l */
+ {18,13,a1r,V,0,0}, /* ld.b.f */
+ {18,14,a1r,V,0,0}, /* ld.h.f */
+ {18,15,a1r,V,0,0}, /* ld.w.f */
+ {18,16,a1r,V,0,0}, /* ld.l.f */
+ {21,13,a2r,V,0,0}, /* st.b.f */
+ {21,14,a2r,V,0,0}, /* st.h.f */
+ {21,15,a2r,V,0,0}, /* st.w.f */
+ {21,16,a2r,V,0,0}, /* st.l.f */
+};
+
+CONST struct formstr e0_format2[] = {
+ {28,5,rr,V,V,0}, /* cvtw.b */
+ {28,6,rr,V,V,0}, /* cvtw.h */
+ {29,7,rr,V,V,0}, /* cvtb.w */
+ {30,7,rr,V,V,0}, /* cvth.w */
+ {28,13,rr,V,V,0}, /* cvtw.b.f */
+ {28,14,rr,V,V,0}, /* cvtw.h.f */
+ {29,15,rr,V,V,0}, /* cvtb.w.f */
+ {30,15,rr,V,V,0}, /* cvth.w.f */
+ {31,8,rr,V,V,0}, /* cvts.l */
+ {32,7,rr,V,V,0}, /* cvtd.w */
+ {33,3,rr,V,V,0}, /* cvtl.s */
+ {28,4,rr,V,V,0}, /* cvtw.d */
+ {31,16,rr,V,V,0}, /* cvts.l.f */
+ {32,15,rr,V,V,0}, /* cvtd.w.f */
+ {33,11,rr,V,V,0}, /* cvtl.s.f */
+ {28,12,rr,V,V,0}, /* cvtw.d.f */
+ {114,0,rr,S,S,0}, /* enal */
+ {8,7,rr,S,S,0}, /* shf.w */
+ {115,0,rr,S,S,0}, /* enag */
+ {0,0,0,0,0,0},
+ {28,4,rr,S,S,0}, /* cvtw.d */
+ {32,7,rr,S,S,0}, /* cvtd.w */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,3,rr,S,S,0}, /* frint.s */
+ {116,4,rr,S,S,0}, /* frint.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,3,rr,V,V,0}, /* frint.s */
+ {116,4,rr,V,V,0}, /* frint.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,11,rr,V,V,0}, /* frint.s.f */
+ {116,12,rr,V,V,0}, /* frint.d.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {81,3,rr,V,V,0}, /* sqrt.s */
+ {81,4,rr,V,V,0}, /* sqrt.d */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {81,11,rr,V,V,0}, /* sqrt.s.f */
+ {81,12,rr,V,V,0}, /* sqrt.d.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e0_format3[] = {
+ {32,11,rr,V,V,0}, /* cvtd.s.f */
+ {31,12,rr,V,V,0}, /* cvts.d.f */
+ {33,12,rr,V,V,0}, /* cvtl.d.f */
+ {32,16,rr,V,V,0}, /* cvtd.l.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {36,2,rr,V,V,0}, /* tzc.f */
+ {44,2,rr,V,V,0}, /* lop.f */
+ {117,2,rr,V,V,0}, /* xpnd.f */
+ {42,2,rr,V,V,0}, /* not.f */
+ {8,2,rr,S,V,0}, /* shf.f */
+ {35,17,rr,V,V,0}, /* plc.t.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {37,11,rr,V,V,0}, /* eq.s.f */
+ {37,12,rr,V,V,0}, /* eq.d.f */
+ {43,11,rr,V,V,0}, /* neg.s.f */
+ {43,12,rr,V,V,0}, /* neg.d.f */
+ {37,11,rr,S,V,0}, /* eq.s.f */
+ {37,12,rr,S,V,0}, /* eq.d.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {40,11,rr,V,V,0}, /* le.s.f */
+ {40,12,rr,V,V,0}, /* le.d.f */
+ {41,11,rr,V,V,0}, /* lt.s.f */
+ {41,12,rr,V,V,0}, /* lt.d.f */
+ {40,11,rr,S,V,0}, /* le.s.f */
+ {40,12,rr,S,V,0}, /* le.d.f */
+ {41,11,rr,S,V,0}, /* lt.s.f */
+ {41,12,rr,S,V,0}, /* lt.d.f */
+ {37,13,rr,V,V,0}, /* eq.b.f */
+ {37,14,rr,V,V,0}, /* eq.h.f */
+ {37,15,rr,V,V,0}, /* eq.w.f */
+ {37,16,rr,V,V,0}, /* eq.l.f */
+ {37,13,rr,S,V,0}, /* eq.b.f */
+ {37,14,rr,S,V,0}, /* eq.h.f */
+ {37,15,rr,S,V,0}, /* eq.w.f */
+ {37,16,rr,S,V,0}, /* eq.l.f */
+ {40,13,rr,V,V,0}, /* le.b.f */
+ {40,14,rr,V,V,0}, /* le.h.f */
+ {40,15,rr,V,V,0}, /* le.w.f */
+ {40,16,rr,V,V,0}, /* le.l.f */
+ {40,13,rr,S,V,0}, /* le.b.f */
+ {40,14,rr,S,V,0}, /* le.h.f */
+ {40,15,rr,S,V,0}, /* le.w.f */
+ {40,16,rr,S,V,0}, /* le.l.f */
+ {41,13,rr,V,V,0}, /* lt.b.f */
+ {41,14,rr,V,V,0}, /* lt.h.f */
+ {41,15,rr,V,V,0}, /* lt.w.f */
+ {41,16,rr,V,V,0}, /* lt.l.f */
+ {41,13,rr,S,V,0}, /* lt.b.f */
+ {41,14,rr,S,V,0}, /* lt.h.f */
+ {41,15,rr,S,V,0}, /* lt.w.f */
+ {41,16,rr,S,V,0}, /* lt.l.f */
+ {43,13,rr,V,V,0}, /* neg.b.f */
+ {43,14,rr,V,V,0}, /* neg.h.f */
+ {43,15,rr,V,V,0}, /* neg.w.f */
+ {43,16,rr,V,V,0}, /* neg.l.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e0_format4[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e0_format5[] = {
+ {51,13,rr,V,V,0}, /* ldvi.b.f */
+ {51,14,rr,V,V,0}, /* ldvi.h.f */
+ {51,15,rr,V,V,0}, /* ldvi.w.f */
+ {51,16,rr,V,V,0}, /* ldvi.l.f */
+ {28,11,rr,V,V,0}, /* cvtw.s.f */
+ {31,15,rr,V,V,0}, /* cvts.w.f */
+ {28,16,rr,V,V,0}, /* cvtw.l.f */
+ {33,15,rr,V,V,0}, /* cvtl.w.f */
+ {52,13,rxr,V,V,0}, /* stvi.b.f */
+ {52,14,rxr,V,V,0}, /* stvi.h.f */
+ {52,15,rxr,V,V,0}, /* stvi.w.f */
+ {52,16,rxr,V,V,0}, /* stvi.l.f */
+ {52,13,rxr,S,V,0}, /* stvi.b.f */
+ {52,14,rxr,S,V,0}, /* stvi.h.f */
+ {52,15,rxr,S,V,0}, /* stvi.w.f */
+ {52,16,rxr,S,V,0}, /* stvi.l.f */
+};
+
+CONST struct formstr e0_format6[] = {
+ {0,0,rxl,S,CIR,0}, /* mov */
+ {0,0,lr,CIR,S,0}, /* mov */
+ {0,0,lr,TOC,S,0}, /* mov */
+ {0,0,lr,CPUID,S,0}, /* mov */
+ {0,0,rxl,S,TTR,0}, /* mov */
+ {0,0,lr,TTR,S,0}, /* mov */
+ {118,0,nops,0,0,0}, /* ctrsl */
+ {119,0,nops,0,0,0}, /* ctrsg */
+ {0,0,rxl,S,VMU,0}, /* mov */
+ {0,0,lr,VMU,S,0}, /* mov */
+ {0,0,rxl,S,VML,0}, /* mov */
+ {0,0,lr,VML,S,0}, /* mov */
+ {0,0,rxl,S,ICR,0}, /* mov */
+ {0,0,lr,ICR,S,0}, /* mov */
+ {0,0,rxl,S,TCPU,0}, /* mov */
+ {0,0,lr,TCPU,S,0}, /* mov */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {120,0,nops,0,0,0}, /* stop */
+ {0,0,0,0,0,0},
+ {0,0,rxl,S,TID,0}, /* mov */
+ {0,0,lr,TID,S,0}, /* mov */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e0_format7[] = {
+ {84,13,r,V,0,0}, /* sum.b.f */
+ {84,14,r,V,0,0}, /* sum.h.f */
+ {84,15,r,V,0,0}, /* sum.w.f */
+ {84,16,r,V,0,0}, /* sum.l.f */
+ {85,2,r,V,0,0}, /* all.f */
+ {86,2,r,V,0,0}, /* any.f */
+ {87,2,r,V,0,0}, /* parity.f */
+ {0,0,0,0,0,0},
+ {88,13,r,V,0,0}, /* max.b.f */
+ {88,14,r,V,0,0}, /* max.h.f */
+ {88,15,r,V,0,0}, /* max.w.f */
+ {88,16,r,V,0,0}, /* max.l.f */
+ {89,13,r,V,0,0}, /* min.b.f */
+ {89,14,r,V,0,0}, /* min.h.f */
+ {89,15,r,V,0,0}, /* min.w.f */
+ {89,16,r,V,0,0}, /* min.l.f */
+ {84,11,r,V,0,0}, /* sum.s.f */
+ {84,12,r,V,0,0}, /* sum.d.f */
+ {90,11,r,V,0,0}, /* prod.s.f */
+ {90,12,r,V,0,0}, /* prod.d.f */
+ {88,11,r,V,0,0}, /* max.s.f */
+ {88,12,r,V,0,0}, /* max.d.f */
+ {89,11,r,V,0,0}, /* min.s.f */
+ {89,12,r,V,0,0}, /* min.d.f */
+ {90,13,r,V,0,0}, /* prod.b.f */
+ {90,14,r,V,0,0}, /* prod.h.f */
+ {90,15,r,V,0,0}, /* prod.w.f */
+ {90,16,r,V,0,0}, /* prod.l.f */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e1_format0[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {10,18,rrr,S,V,V}, /* sub.s.t */
+ {10,19,rrr,S,V,V}, /* sub.d.t */
+ {4,18,rrr,S,V,V}, /* div.s.t */
+ {4,19,rrr,S,V,V}, /* div.d.t */
+ {3,18,rrr,V,V,V}, /* mul.s.t */
+ {3,19,rrr,V,V,V}, /* mul.d.t */
+ {4,18,rrr,V,V,V}, /* div.s.t */
+ {4,19,rrr,V,V,V}, /* div.d.t */
+ {3,18,rrr,V,S,V}, /* mul.s.t */
+ {3,19,rrr,V,S,V}, /* mul.d.t */
+ {4,18,rrr,V,S,V}, /* div.s.t */
+ {4,19,rrr,V,S,V}, /* div.d.t */
+ {5,1,rrr,V,V,V}, /* and.t */
+ {6,1,rrr,V,V,V}, /* or.t */
+ {7,1,rrr,V,V,V}, /* xor.t */
+ {8,1,rrr,V,V,V}, /* shf.t */
+ {5,1,rrr,V,S,V}, /* and.t */
+ {6,1,rrr,V,S,V}, /* or.t */
+ {7,1,rrr,V,S,V}, /* xor.t */
+ {8,1,rrr,V,S,V}, /* shf.t */
+ {9,18,rrr,V,V,V}, /* add.s.t */
+ {9,19,rrr,V,V,V}, /* add.d.t */
+ {10,18,rrr,V,V,V}, /* sub.s.t */
+ {10,19,rrr,V,V,V}, /* sub.d.t */
+ {9,18,rrr,V,S,V}, /* add.s.t */
+ {9,19,rrr,V,S,V}, /* add.d.t */
+ {10,18,rrr,V,S,V}, /* sub.s.t */
+ {10,19,rrr,V,S,V}, /* sub.d.t */
+ {9,20,rrr,V,V,V}, /* add.b.t */
+ {9,21,rrr,V,V,V}, /* add.h.t */
+ {9,22,rrr,V,V,V}, /* add.w.t */
+ {9,23,rrr,V,V,V}, /* add.l.t */
+ {9,20,rrr,V,S,V}, /* add.b.t */
+ {9,21,rrr,V,S,V}, /* add.h.t */
+ {9,22,rrr,V,S,V}, /* add.w.t */
+ {9,23,rrr,V,S,V}, /* add.l.t */
+ {10,20,rrr,V,V,V}, /* sub.b.t */
+ {10,21,rrr,V,V,V}, /* sub.h.t */
+ {10,22,rrr,V,V,V}, /* sub.w.t */
+ {10,23,rrr,V,V,V}, /* sub.l.t */
+ {10,20,rrr,V,S,V}, /* sub.b.t */
+ {10,21,rrr,V,S,V}, /* sub.h.t */
+ {10,22,rrr,V,S,V}, /* sub.w.t */
+ {10,23,rrr,V,S,V}, /* sub.l.t */
+ {3,20,rrr,V,V,V}, /* mul.b.t */
+ {3,21,rrr,V,V,V}, /* mul.h.t */
+ {3,22,rrr,V,V,V}, /* mul.w.t */
+ {3,23,rrr,V,V,V}, /* mul.l.t */
+ {3,20,rrr,V,S,V}, /* mul.b.t */
+ {3,21,rrr,V,S,V}, /* mul.h.t */
+ {3,22,rrr,V,S,V}, /* mul.w.t */
+ {3,23,rrr,V,S,V}, /* mul.l.t */
+ {4,20,rrr,V,V,V}, /* div.b.t */
+ {4,21,rrr,V,V,V}, /* div.h.t */
+ {4,22,rrr,V,V,V}, /* div.w.t */
+ {4,23,rrr,V,V,V}, /* div.l.t */
+ {4,20,rrr,V,S,V}, /* div.b.t */
+ {4,21,rrr,V,S,V}, /* div.h.t */
+ {4,22,rrr,V,S,V}, /* div.w.t */
+ {4,23,rrr,V,S,V}, /* div.l.t */
+};
+
+CONST struct formstr e1_format1[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {26,20,a2r,S,0,0}, /* ste.b.t */
+ {26,21,a2r,S,0,0}, /* ste.h.t */
+ {26,22,a2r,S,0,0}, /* ste.w.t */
+ {26,23,a2r,S,0,0}, /* ste.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {18,20,a1r,V,0,0}, /* ld.b.t */
+ {18,21,a1r,V,0,0}, /* ld.h.t */
+ {18,22,a1r,V,0,0}, /* ld.w.t */
+ {18,23,a1r,V,0,0}, /* ld.l.t */
+ {21,20,a2r,V,0,0}, /* st.b.t */
+ {21,21,a2r,V,0,0}, /* st.h.t */
+ {21,22,a2r,V,0,0}, /* st.w.t */
+ {21,23,a2r,V,0,0}, /* st.l.t */
+};
+
+CONST struct formstr e1_format2[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {28,20,rr,V,V,0}, /* cvtw.b.t */
+ {28,21,rr,V,V,0}, /* cvtw.h.t */
+ {29,22,rr,V,V,0}, /* cvtb.w.t */
+ {30,22,rr,V,V,0}, /* cvth.w.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {31,23,rr,V,V,0}, /* cvts.l.t */
+ {32,22,rr,V,V,0}, /* cvtd.w.t */
+ {33,18,rr,V,V,0}, /* cvtl.s.t */
+ {28,19,rr,V,V,0}, /* cvtw.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {116,18,rr,V,V,0}, /* frint.s.t */
+ {116,19,rr,V,V,0}, /* frint.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {81,18,rr,V,V,0}, /* sqrt.s.t */
+ {81,19,rr,V,V,0}, /* sqrt.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e1_format3[] = {
+ {32,18,rr,V,V,0}, /* cvtd.s.t */
+ {31,19,rr,V,V,0}, /* cvts.d.t */
+ {33,19,rr,V,V,0}, /* cvtl.d.t */
+ {32,23,rr,V,V,0}, /* cvtd.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {36,1,rr,V,V,0}, /* tzc.t */
+ {44,1,rr,V,V,0}, /* lop.t */
+ {117,1,rr,V,V,0}, /* xpnd.t */
+ {42,1,rr,V,V,0}, /* not.t */
+ {8,1,rr,S,V,0}, /* shf.t */
+ {35,24,rr,V,V,0}, /* plc.t.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {37,18,rr,V,V,0}, /* eq.s.t */
+ {37,19,rr,V,V,0}, /* eq.d.t */
+ {43,18,rr,V,V,0}, /* neg.s.t */
+ {43,19,rr,V,V,0}, /* neg.d.t */
+ {37,18,rr,S,V,0}, /* eq.s.t */
+ {37,19,rr,S,V,0}, /* eq.d.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {40,18,rr,V,V,0}, /* le.s.t */
+ {40,19,rr,V,V,0}, /* le.d.t */
+ {41,18,rr,V,V,0}, /* lt.s.t */
+ {41,19,rr,V,V,0}, /* lt.d.t */
+ {40,18,rr,S,V,0}, /* le.s.t */
+ {40,19,rr,S,V,0}, /* le.d.t */
+ {41,18,rr,S,V,0}, /* lt.s.t */
+ {41,19,rr,S,V,0}, /* lt.d.t */
+ {37,20,rr,V,V,0}, /* eq.b.t */
+ {37,21,rr,V,V,0}, /* eq.h.t */
+ {37,22,rr,V,V,0}, /* eq.w.t */
+ {37,23,rr,V,V,0}, /* eq.l.t */
+ {37,20,rr,S,V,0}, /* eq.b.t */
+ {37,21,rr,S,V,0}, /* eq.h.t */
+ {37,22,rr,S,V,0}, /* eq.w.t */
+ {37,23,rr,S,V,0}, /* eq.l.t */
+ {40,20,rr,V,V,0}, /* le.b.t */
+ {40,21,rr,V,V,0}, /* le.h.t */
+ {40,22,rr,V,V,0}, /* le.w.t */
+ {40,23,rr,V,V,0}, /* le.l.t */
+ {40,20,rr,S,V,0}, /* le.b.t */
+ {40,21,rr,S,V,0}, /* le.h.t */
+ {40,22,rr,S,V,0}, /* le.w.t */
+ {40,23,rr,S,V,0}, /* le.l.t */
+ {41,20,rr,V,V,0}, /* lt.b.t */
+ {41,21,rr,V,V,0}, /* lt.h.t */
+ {41,22,rr,V,V,0}, /* lt.w.t */
+ {41,23,rr,V,V,0}, /* lt.l.t */
+ {41,20,rr,S,V,0}, /* lt.b.t */
+ {41,21,rr,S,V,0}, /* lt.h.t */
+ {41,22,rr,S,V,0}, /* lt.w.t */
+ {41,23,rr,S,V,0}, /* lt.l.t */
+ {43,20,rr,V,V,0}, /* neg.b.t */
+ {43,21,rr,V,V,0}, /* neg.h.t */
+ {43,22,rr,V,V,0}, /* neg.w.t */
+ {43,23,rr,V,V,0}, /* neg.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e1_format4[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e1_format5[] = {
+ {51,20,rr,V,V,0}, /* ldvi.b.t */
+ {51,21,rr,V,V,0}, /* ldvi.h.t */
+ {51,22,rr,V,V,0}, /* ldvi.w.t */
+ {51,23,rr,V,V,0}, /* ldvi.l.t */
+ {28,18,rr,V,V,0}, /* cvtw.s.t */
+ {31,22,rr,V,V,0}, /* cvts.w.t */
+ {28,23,rr,V,V,0}, /* cvtw.l.t */
+ {33,22,rr,V,V,0}, /* cvtl.w.t */
+ {52,20,rxr,V,V,0}, /* stvi.b.t */
+ {52,21,rxr,V,V,0}, /* stvi.h.t */
+ {52,22,rxr,V,V,0}, /* stvi.w.t */
+ {52,23,rxr,V,V,0}, /* stvi.l.t */
+ {52,20,rxr,S,V,0}, /* stvi.b.t */
+ {52,21,rxr,S,V,0}, /* stvi.h.t */
+ {52,22,rxr,S,V,0}, /* stvi.w.t */
+ {52,23,rxr,S,V,0}, /* stvi.l.t */
+};
+
+CONST struct formstr e1_format6[] = {
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+CONST struct formstr e1_format7[] = {
+ {84,20,r,V,0,0}, /* sum.b.t */
+ {84,21,r,V,0,0}, /* sum.h.t */
+ {84,22,r,V,0,0}, /* sum.w.t */
+ {84,23,r,V,0,0}, /* sum.l.t */
+ {85,1,r,V,0,0}, /* all.t */
+ {86,1,r,V,0,0}, /* any.t */
+ {87,1,r,V,0,0}, /* parity.t */
+ {0,0,0,0,0,0},
+ {88,20,r,V,0,0}, /* max.b.t */
+ {88,21,r,V,0,0}, /* max.h.t */
+ {88,22,r,V,0,0}, /* max.w.t */
+ {88,23,r,V,0,0}, /* max.l.t */
+ {89,20,r,V,0,0}, /* min.b.t */
+ {89,21,r,V,0,0}, /* min.h.t */
+ {89,22,r,V,0,0}, /* min.w.t */
+ {89,23,r,V,0,0}, /* min.l.t */
+ {84,18,r,V,0,0}, /* sum.s.t */
+ {84,19,r,V,0,0}, /* sum.d.t */
+ {90,18,r,V,0,0}, /* prod.s.t */
+ {90,19,r,V,0,0}, /* prod.d.t */
+ {88,18,r,V,0,0}, /* max.s.t */
+ {88,19,r,V,0,0}, /* max.d.t */
+ {89,18,r,V,0,0}, /* min.s.t */
+ {89,19,r,V,0,0}, /* min.d.t */
+ {90,20,r,V,0,0}, /* prod.b.t */
+ {90,21,r,V,0,0}, /* prod.h.t */
+ {90,22,r,V,0,0}, /* prod.w.t */
+ {90,23,r,V,0,0}, /* prod.l.t */
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+ {0,0,0,0,0,0},
+};
+
+char *lop[] = {
+ "mov", /* 0 */
+ "merg", /* 1 */
+ "mask", /* 2 */
+ "mul", /* 3 */
+ "div", /* 4 */
+ "and", /* 5 */
+ "or", /* 6 */
+ "xor", /* 7 */
+ "shf", /* 8 */
+ "add", /* 9 */
+ "sub", /* 10 */
+ "exit", /* 11 */
+ "jmp", /* 12 */
+ "jmpi", /* 13 */
+ "jmpa", /* 14 */
+ "jmps", /* 15 */
+ "tac", /* 16 */
+ "ldea", /* 17 */
+ "ld", /* 18 */
+ "tas", /* 19 */
+ "pshea", /* 20 */
+ "st", /* 21 */
+ "call", /* 22 */
+ "calls", /* 23 */
+ "callq", /* 24 */
+ "pfork", /* 25 */
+ "ste", /* 26 */
+ "incr", /* 27 */
+ "cvtw", /* 28 */
+ "cvtb", /* 29 */
+ "cvth", /* 30 */
+ "cvts", /* 31 */
+ "cvtd", /* 32 */
+ "cvtl", /* 33 */
+ "ldpa", /* 34 */
+ "plc", /* 35 */
+ "tzc", /* 36 */
+ "eq", /* 37 */
+ "leu", /* 38 */
+ "ltu", /* 39 */
+ "le", /* 40 */
+ "lt", /* 41 */
+ "not", /* 42 */
+ "neg", /* 43 */
+ "lop", /* 44 */
+ "cprs", /* 45 */
+ "nop", /* 46 */
+ "br", /* 47 */
+ "bri", /* 48 */
+ "bra", /* 49 */
+ "brs", /* 50 */
+ "ldvi", /* 51 */
+ "stvi", /* 52 */
+ "ldsdr", /* 53 */
+ "ldkdr", /* 54 */
+ "ln", /* 55 */
+ "patu", /* 56 */
+ "pate", /* 57 */
+ "pich", /* 58 */
+ "plch", /* 59 */
+ "idle", /* 60 */
+ "rtnq", /* 61 */
+ "cfork", /* 62 */
+ "rtn", /* 63 */
+ "wfork", /* 64 */
+ "join", /* 65 */
+ "rtnc", /* 66 */
+ "exp", /* 67 */
+ "sin", /* 68 */
+ "cos", /* 69 */
+ "psh", /* 70 */
+ "pop", /* 71 */
+ "eni", /* 72 */
+ "dsi", /* 73 */
+ "bkpt", /* 74 */
+ "msync", /* 75 */
+ "mski", /* 76 */
+ "xmti", /* 77 */
+ "tstvv", /* 78 */
+ "diag", /* 79 */
+ "pbkpt", /* 80 */
+ "sqrt", /* 81 */
+ "casr", /* 82 */
+ "atan", /* 83 */
+ "sum", /* 84 */
+ "all", /* 85 */
+ "any", /* 86 */
+ "parity", /* 87 */
+ "max", /* 88 */
+ "min", /* 89 */
+ "prod", /* 90 */
+ "halt", /* 91 */
+ "sysc", /* 92 */
+ "trap", /* 93 */
+ "tst", /* 94 */
+ "lck", /* 95 */
+ "ulk", /* 96 */
+ "spawn", /* 97 */
+ "ldcmr", /* 98 */
+ "stcmr", /* 99 */
+ "popr", /* 100 */
+ "pshr", /* 101 */
+ "rcvr", /* 102 */
+ "matm", /* 103 */
+ "sndr", /* 104 */
+ "putr", /* 105 */
+ "getr", /* 106 */
+ "matr", /* 107 */
+ "mat", /* 108 */
+ "get", /* 109 */
+ "rcv", /* 110 */
+ "inc", /* 111 */
+ "put", /* 112 */
+ "snd", /* 113 */
+ "enal", /* 114 */
+ "enag", /* 115 */
+ "frint", /* 116 */
+ "xpnd", /* 117 */
+ "ctrsl", /* 118 */
+ "ctrsg", /* 119 */
+ "stop", /* 120 */
+};
+
+char *rop[] = {
+ "", /* 0 */
+ ".t", /* 1 */
+ ".f", /* 2 */
+ ".s", /* 3 */
+ ".d", /* 4 */
+ ".b", /* 5 */
+ ".h", /* 6 */
+ ".w", /* 7 */
+ ".l", /* 8 */
+ ".x", /* 9 */
+ ".u", /* 10 */
+ ".s.f", /* 11 */
+ ".d.f", /* 12 */
+ ".b.f", /* 13 */
+ ".h.f", /* 14 */
+ ".w.f", /* 15 */
+ ".l.f", /* 16 */
+ ".t.f", /* 17 */
+ ".s.t", /* 18 */
+ ".d.t", /* 19 */
+ ".b.t", /* 20 */
+ ".h.t", /* 21 */
+ ".w.t", /* 22 */
+ ".l.t", /* 23 */
+ ".t.t", /* 24 */
+};
diff --git a/contrib/gdb/include/opcode/h8300.h b/contrib/gdb/include/opcode/h8300.h
new file mode 100644
index 0000000..9d726e2
--- /dev/null
+++ b/contrib/gdb/include/opcode/h8300.h
@@ -0,0 +1,550 @@
+/* Opcode table for the H8-300
+ Copyright (C) 1991,1992 Free Software Foundation.
+ Written by Steve Chamberlain, sac@cygnus.com.
+
+ This file is part of GDB, the GNU Debugger and GAS, the GNU Assembler.
+
+ 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Instructions are stored as a sequence of nibbles.
+ If the nibble has value 15 or less then the representation is complete.
+ Otherwise, we record what it contains with several flags. */
+
+typedef int op_type;
+
+#define Hex0 0
+#define Hex1 1
+#define Hex2 2
+#define Hex3 3
+#define Hex4 4
+#define Hex5 5
+#define Hex6 6
+#define Hex7 7
+#define Hex8 8
+#define Hex9 9
+#define HexA 10
+#define HexB 11
+#define HexC 12
+#define HexD 13
+#define HexE 14
+#define HexF 15
+
+#define START 0x20
+#define SRC 0x40
+#define DST 0x80
+#define L_8 0x01
+#define L_16 0x02
+#define L_32 0x04
+#define L_P 0x08
+#define L_24 0x10
+
+#define REG 0x100
+#define IMM 0x1000
+#define DISP 0x2000
+#define IND 0x4000
+#define INC 0x8000
+#define DEC 0x10000
+#define L_3 0x20000
+#define KBIT 0x40000
+#define DBIT 0x80000
+#define DISPREG 0x100000
+#define IGNORE 0x200000
+#define E 0x400000 /* FIXME: end of nibble sequence? */
+#define L_2 0x800000
+#define CCR 0x4000000
+#define ABS 0x8000000
+#define B30 0x1000000 /* bit 3 must be low */
+#define B31 0x2000000 /* bit 3 must be high */
+#define ABSJMP 0x10000000
+#define ABSMOV 0x20000000
+#define PCREL 0x40000000
+#define MEMIND 0x80000000
+
+#define IMM3 IMM|L_3
+#define IMM2 IMM|L_2
+
+#define SIZE (L_2|L_3|L_8|L_16|L_32|L_P|L_24)
+#define MODE (REG|IMM|DISP|IND|INC|DEC|CCR|ABS|MEMIND)
+
+#define RD8 (DST|L_8|REG)
+#define RD16 (DST|L_16|REG)
+#define RD32 (DST|L_32|REG)
+#define RS8 (SRC|L_8|REG)
+#define RS16 (SRC|L_16|REG)
+#define RS32 (SRC|L_32|REG)
+
+#define RSP (SRC|L_P|REG)
+#define RDP (DST|L_P|REG)
+
+#define IMM8 (IMM|SRC|L_8)
+#define IMM16 (IMM|SRC|L_16)
+#define IMM32 (IMM|SRC|L_32)
+
+#define ABS8SRC (SRC|ABS|L_8)
+#define ABS8DST (DST|ABS|L_8)
+
+#define DISP8 (PCREL|L_8)
+#define DISP16 (PCREL|L_16)
+
+#define DISP8SRC (DISP|L_8|SRC)
+#define DISP16SRC (DISP|L_16|SRC)
+
+#define DISP8DST (DISP|L_8|DST)
+#define DISP16DST (DISP|L_16|DST)
+
+#define ABS16SRC (SRC|ABS|L_16)
+#define ABS16DST (DST|ABS|L_16)
+#define ABS24SRC (SRC|ABS|L_24)
+#define ABS24DST (DST|ABS|L_24)
+
+#define RDDEC (DST|DEC)
+#define RSINC (SRC|INC)
+
+#define RDIND (DST|IND)
+#define RSIND (SRC|IND)
+
+#if 1
+#define OR8 RS8 /* ??? OR as in One Register? */
+#define OR16 RS16
+#define OR32 RS32
+#else
+#define OR8 RD8
+#define OR16 RD16
+#define OR32 RD32
+#endif
+
+struct code
+{
+ op_type nib[30];
+};
+
+struct arg
+{
+ op_type nib[3];
+};
+
+struct h8_opcode
+{
+ int how;
+ int inbase;
+ int time;
+ char *name;
+ struct arg args;
+ struct code data;
+ int length;
+ int noperands;
+ int idx;
+ int size;
+};
+
+#ifdef DEFINE_TABLE
+
+#define BITOP(code, imm, name, op00, op01,op10,op11, op20,op21)\
+{ code, 1, 2, name, {imm,RD8,E}, {op00, op01, imm, RD8, E, 0, 0, 0, 0}, 0, 0, 0, 0},\
+{ code, 1, 6, name, {imm,RDIND,E}, {op10, op11, B30|RDIND, 0, op00,op01, imm, 0, E}, 0, 0, 0, 0},\
+{ code, 1, 6, name, {imm,ABS8DST,E},{op20, op21, ABS8DST, IGNORE, op00,op01, imm, 0,E}, 0, 0, 0, 0}
+
+#define EBITOP(code, imm, name, op00, op01,op10,op11, op20,op21)\
+ BITOP(code,imm, name, op00+1, op01, op10,op11, op20,op21),\
+ BITOP(code,RS8, name, op00, op01, op10,op11, op20,op21)
+
+#define WTWOP(code,name, op1, op2) \
+{ code, 1, 2, name, {RS16, RD16, E}, { op1, op2, RS16, RD16, E, 0, 0, 0, 0}, 0, 0, 0, 0}
+
+#define BRANCH(code, name, op) \
+{ code, 1, 4,name,{DISP8,E,0}, { 0x4, op, DISP8, IGNORE, E, 0, 0, 0, 0}, 0, 0, 0, 0}, \
+{ code, 0, 6,name,{DISP16,E,0}, { 0x5, 0x8, op, 0x0, DISP16, IGNORE, IGNORE, IGNORE, E,0}, 0, 0, 0, 0}
+
+#define SOP(code, x,name) \
+{code, 1, x, name
+
+#define NEW_SOP(code, in,x,name) \
+{code, in, x, name
+#define EOP ,0,0,0 }
+
+#define TWOOP(code, name, op1, op2,op3) \
+{ code,1, 2,name, {IMM8, RD8, E}, { op1, RD8, IMM8, IGNORE, E, 0, 0, 0, 0}, 0, 0, 0, 0},\
+{ code, 1, 2,name, {RS8, RD8, E}, { op2, op3, RS8, RD8, E, 0, 0, 0, 0}, 0, 0, 0, 0}
+
+#define UNOP(code,name, op1, op2) \
+{ code, 1, 2, name, {OR8, E, 0}, { op1, op2, 0, OR8, E, 0, 0, 0, 0}, 0, 0, 0, 0}
+
+#define UNOP3(code, name, op1, op2, op3) \
+{ O(code,SB), 1, 2, name, {OR8, E, 0}, {op1, op2, op3+0, OR8, E, 0, 0, 0, 0}, 0, 0, 0, 0}, \
+{ O(code,SW), 0, 2, name, {OR16, E, 0}, {op1, op2, op3+1, OR16, E, 0, 0, 0, 0}, 0, 0, 0, 0}, \
+{ O(code,SL), 0, 2, name, {OR32, E, 0}, {op1, op2, op3+3, OR32|B30, E, 0, 0, 0, 0}, 0, 0, 0, 0}
+
+#define IMM32LIST IMM32,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE
+#define IMM24LIST IMM24,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE
+#define IMM16LIST IMM16,IGNORE,IGNORE,IGNORE
+#define A16LIST L_16,IGNORE,IGNORE,IGNORE
+#define DISP24LIST DISP|L_24,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE
+#define ABS24LIST ABS|L_24,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE
+#define A24LIST L_24,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE
+#define PREFIX32 0x0,0x1,0x0,0x0
+#define PREFIXLDC 0x0,0x1,0x4,0x0
+
+
+#define O(op, size) (op*4+size)
+
+#define O_RECOMPILE 0
+#define O_ADD 1
+#define O_ADDX 2
+#define O_AND 3
+#define O_BAND 4
+#define O_BRA 5
+#define O_BRN 6
+#define O_BHI 7
+#define O_BLS 8
+#define O_BCC 9
+#define O_BCS 10
+#define O_BNE 11
+#define O_BVC 12
+#define O_BVS 13
+#define O_BPL 14
+#define O_BMI 15
+#define O_BGE 16
+#define O_BLT 17
+#define O_BGT 18
+#define O_BLE 19
+#define O_ANDC 20
+#define O_BEQ 21
+#define O_BCLR 22
+#define O_BIAND 23
+#define O_BILD 24
+#define O_BIOR 25
+#define O_BIXOR 26
+#define O_BIST 27
+#define O_BLD 28
+#define O_BNOT 29
+#define O_BSET 30
+#define O_BSR 31
+#define O_BXOR 32
+#define O_CMP 33
+#define O_DAA 34
+#define O_DAS 35
+#define O_DEC 36
+#define O_DIVU 37
+#define O_DIVS 38
+#define O_INC 39
+#define O_LDC 40
+#define O_MOV_TO_MEM 41
+#define O_OR 42
+#define O_ROTL 43
+#define O_ROTR 44
+#define O_ROTXL 45
+#define O_ROTXR 46
+#define O_BPT 47
+#define O_SHAL 48
+#define O_SHAR 49
+#define O_SHLL 50
+#define O_SHLR 51
+#define O_SUB 52
+#define O_SUBS 53
+#define O_TRAPA 54
+#define O_XOR 55
+#define O_XORC 56
+#define O_BOR 57
+#define O_BST 58
+#define O_BTST 59
+#define O_EEPMOV 60
+#define O_EXTS 61
+#define O_EXTU 62
+#define O_JMP 63
+#define O_JSR 64
+#define O_MULU 65
+#define O_MULS 66
+#define O_NOP 67
+#define O_NOT 68
+#define O_ORC 69
+#define O_RTE 70
+#define O_STC 71
+#define O_SUBX 72
+#define O_NEG 73
+#define O_RTS 74
+#define O_SLEEP 75
+#define O_ILL 76
+#define O_ADDS 77
+#define O_SYSCALL 78
+#define O_MOV_TO_REG 79
+#define O_LAST 80
+#define SB 0
+#define SW 1
+#define SL 2
+
+
+/* FIXME: Lots of insns have "E, 0, 0, 0, 0" in the nibble code sequences.
+ Methinks the zeroes aren't necessary. Once confirmed, nuke 'em. */
+
+struct h8_opcode h8_opcodes[] =
+{
+ TWOOP(O(O_ADD,SB),"add.b", 0x8, 0x0,0x8),
+
+ NEW_SOP(O(O_ADD,SW),1,2,"add.w"),{RS16,RD16,E },{0x0,0x9,RS16,RD16,E} EOP,
+ NEW_SOP(O(O_ADD,SW),0,4,"add.w"),{IMM16,RD16,E },{0x7,0x9,0x1,RD16,IMM16,IGNORE,IGNORE,IGNORE,E} EOP,
+ NEW_SOP(O(O_ADD,SL),0,2,"add.l"),{RS32,RD32,E }, {0x0,0xA,B31|RS32,B30|RD32,E} EOP,
+ NEW_SOP(O(O_ADD,SL),0,6,"add.l"),{IMM32,RD32,E },{0x7,0xA,0x1,B30|RD32,IMM32LIST,E} EOP,
+ NEW_SOP(O(O_ADDS,SL),1,2,"adds"), {KBIT,RDP,E}, {0x0,0xB,KBIT,RDP,E,0,0,0,0} EOP,
+
+ TWOOP(O(O_ADDX,SB),"addx",0x9,0x0,0xE),
+ TWOOP(O(O_AND,SB), "and.b",0xE,0x1,0x6),
+
+ NEW_SOP(O(O_AND,SW),0,2,"and.w"),{RS16,RD16,E },{0x6,0x6,RS16,RD16,E} EOP,
+ NEW_SOP(O(O_AND,SW),0,4,"and.w"),{IMM16,RD16,E },{0x7,0x9,0x6,RD16,IMM16,IGNORE,IGNORE,IGNORE,E} EOP,
+
+ NEW_SOP(O(O_AND,SL),0,6,"and.l"),{IMM32,RD32,E },{0x7,0xA,0x6,B30|RD32,IMM32LIST,E} EOP,
+ NEW_SOP(O(O_AND,SL),0,2,"and.l") ,{RS32,RD32,E },{0x0,0x1,0xF,0x0,0x6,0x6,B30|RS32,B30|RD32,E} EOP,
+
+ NEW_SOP(O(O_ANDC,SB),1,2,"andc"), {IMM8,CCR,E},{ 0x0,0x6,IMM8,IGNORE,E,0,0,0,0} EOP,
+
+ BITOP(O(O_BAND,SB), IMM3,"band",0x7,0x6,0x7,0xC,0x7,0xE),
+ BRANCH(O(O_BRA,SB),"bra",0x0),
+ BRANCH(O(O_BRA,SB),"bt",0x0),
+ BRANCH(O(O_BRN,SB),"brn",0x1),
+ BRANCH(O(O_BRN,SB),"bf",0x1),
+ BRANCH(O(O_BHI,SB),"bhi",0x2),
+ BRANCH(O(O_BLS,SB),"bls",0x3),
+ BRANCH(O(O_BCC,SB),"bcc",0x4),
+ BRANCH(O(O_BCC,SB),"bhs",0x4),
+ BRANCH(O(O_BCS,SB),"bcs",0x5),
+ BRANCH(O(O_BCS,SB),"blo",0x5),
+ BRANCH(O(O_BNE,SB),"bne",0x6),
+ BRANCH(O(O_BEQ,SB),"beq",0x7),
+ BRANCH(O(O_BVC,SB),"bvc",0x8),
+ BRANCH(O(O_BVS,SB),"bvs",0x9),
+ BRANCH(O(O_BPL,SB),"bpl",0xA),
+ BRANCH(O(O_BMI,SB),"bmi",0xB),
+ BRANCH(O(O_BGE,SB),"bge",0xC),
+ BRANCH(O(O_BLT,SB),"blt",0xD),
+ BRANCH(O(O_BGT,SB),"bgt",0xE),
+ BRANCH(O(O_BLE,SB),"ble",0xF),
+
+ EBITOP(O(O_BCLR,SB),IMM3, "bclr", 0x6,0x2,0x7,0xD,0x7,0xF),
+ BITOP(O(O_BIAND,SB),IMM3|B31,"biand",0x7,0x6,0x7,0xC,0x7,0xE),
+ BITOP(O(O_BILD,SB), IMM3|B31,"bild", 0x7,0x7,0x7,0xC,0x7,0xE),
+ BITOP(O(O_BIOR,SB), IMM3|B31,"bior", 0x7,0x4,0x7,0xC,0x7,0xE),
+ BITOP(O(O_BIST,SB), IMM3|B31,"bist", 0x6,0x7,0x7,0xD,0x7,0xF),
+ BITOP(O(O_BIXOR,SB),IMM3|B31,"bixor",0x7,0x5,0x7,0xC,0x7,0xE),
+ BITOP(O(O_BLD,SB), IMM3|B30,"bld", 0x7,0x7,0x7,0xC,0x7,0xE),
+ EBITOP(O(O_BNOT,SB),IMM3|B30,"bnot", 0x6,0x1,0x7,0xD,0x7,0xF),
+ BITOP(O(O_BOR,SB), IMM3|B30,"bor", 0x7,0x4,0x7,0xC,0x7,0xE),
+ EBITOP(O(O_BSET,SB),IMM3|B30,"bset", 0x6,0x0,0x7,0xD,0x7,0xF),
+
+ SOP(O(O_BSR,SB),6,"bsr"),{DISP8,E,0},{ 0x5,0x5,DISP8,IGNORE,E,0,0,0,0} EOP,
+ SOP(O(O_BSR,SB),6,"bsr"),{DISP16,E,0},{ 0x5,0xC,0x0,0x0,DISP16,IGNORE,IGNORE,IGNORE,E,0,0,0,0} EOP,
+ BITOP(O(O_BST,SB), IMM3|B30,"bst",0x6,0x7,0x7,0xD,0x7,0xF),
+ EBITOP(O(O_BTST,SB), IMM3|B30,"btst",0x6,0x3,0x7,0xC,0x7,0xE),
+ BITOP(O(O_BXOR,SB), IMM3|B30,"bxor",0x7,0x5,0x7,0xC,0x7,0xE),
+
+ TWOOP(O(O_CMP,SB), "cmp.b",0xA,0x1,0xC),
+ WTWOP(O(O_CMP,SW), "cmp.w",0x1,0xD),
+
+ NEW_SOP(O(O_CMP,SW),1,2,"cmp.w"),{RS16,RD16,E },{0x1,0xD,RS16,RD16,E} EOP,
+ NEW_SOP(O(O_CMP,SW),0,4,"cmp.w"),{IMM16,RD16,E },{0x7,0x9,0x2,RD16,IMM16,IGNORE,IGNORE,IGNORE,E} EOP,
+
+ NEW_SOP(O(O_CMP,SL),0,6,"cmp.l"),{IMM32,RD32,E },{0x7,0xA,0x2,B30|RD32,IMM32LIST,E} EOP,
+ NEW_SOP(O(O_CMP,SL),0,2,"cmp.l") ,{RS32,RD32,E },{0x1,0xF,B31|RS32,B30|RD32,E} EOP,
+
+ UNOP(O(O_DAA,SB), "daa",0x0,0xF),
+ UNOP(O(O_DAS,SB), "das",0x1,0xF),
+ UNOP(O(O_DEC,SB), "dec.b",0x1,0xA),
+
+ NEW_SOP(O(O_DEC, SW),0,2,"dec.w") ,{DBIT,RD16,E },{0x1,0xB,0x5|DBIT,RD16,E} EOP,
+ NEW_SOP(O(O_DEC, SL),0,2,"dec.l") ,{DBIT,RD32,E },{0x1,0xB,0x7|DBIT,RD32|B30,E} EOP,
+
+ NEW_SOP(O(O_DIVU,SB),1,6,"divxu.b"), {RS8,RD16,E}, {0x5,0x1,RS8,RD16,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_DIVU,SW),0,20,"divxu.w"),{RS16,RD32,E},{0x5,0x3,RS16,B30|RD32,E}EOP,
+
+ NEW_SOP(O(O_DIVS,SB),0,20,"divxs.b") ,{RS8,RD16,E },{0x0,0x1,0xD,0x0,0x5,0x1,RS8,RD16,E} EOP,
+ NEW_SOP(O(O_DIVS,SW),0,02,"divxs.w") ,{RS16,RD32,E },{0x0,0x1,0xD,0x0,0x5,0x3,RS16,B30|RD32,E} EOP,
+
+ NEW_SOP(O(O_EEPMOV,SB),1,50,"eepmov"),{ E,0,0},{0x7,0xB,0x5,0xC,0x5,0x9,0x8,0xF,E}EOP,
+ NEW_SOP(O(O_EEPMOV,SW),0,50,"eepmovw"),{E,0,0},{0x7,0xB,0xD,0x4,0x5,0x9,0x8,0xF,E} EOP,
+
+ NEW_SOP(O(O_EXTS,SW),0,2,"exts.w"),{OR16,E,0},{0x1,0x7,0xD,OR16,E }EOP,
+ NEW_SOP(O(O_EXTS,SL),0,2,"exts.l"),{OR32,E,0},{0x1,0x7,0xF,OR32|B30,E }EOP,
+
+ NEW_SOP(O(O_EXTU,SW),0,2,"extu.w"),{OR16,E,0},{0x1,0x7,0x5,OR16,E }EOP,
+ NEW_SOP(O(O_EXTU,SL),0,2,"extu.l"),{OR32,E,0},{0x1,0x7,0x7,OR32|B30,E }EOP,
+
+ UNOP(O(O_INC,SB), "inc",0x0,0xA),
+
+ NEW_SOP(O(O_INC,SW),0,2,"inc.w") ,{DBIT,RD16,E },{0x0,0xB,0x5|DBIT,RD16,E} EOP,
+ NEW_SOP(O(O_INC,SL),0,2,"inc.l") ,{DBIT,RD32,E },{0x0,0xB,0x7|DBIT,RD32|B30,E} EOP,
+
+ SOP(O(O_JMP,SB),4,"jmp"),{RSIND,E,0},{0x5,0x9,B30|RSIND,0x0,E,0,0,0,0}EOP,
+ SOP(O(O_JMP,SB),6,"jmp"),{SRC|ABSJMP,E,0},{0x5,0xA,SRC|ABSJMP,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_JMP,SB),8,"jmp"),{SRC|MEMIND,E,0},{0x5,0xB,SRC|MEMIND,IGNORE,E,0,0,0,0}EOP,
+
+ SOP(O(O_JSR,SB),6,"jsr"),{SRC|RSIND,E,0}, {0x5,0xD,B30|RSIND,0x0,E,0,0,0,0}EOP,
+ SOP(O(O_JSR,SB),8,"jsr"),{SRC|ABSJMP,E,0},{0x5,0xE,SRC|ABSJMP,IGNORE,IGNORE,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_JSR,SB),8,"jsr"),{SRC|MEMIND,E,0},{0x5,0xF,SRC|MEMIND,IGNORE,E,0,0,0,0}EOP,
+
+ NEW_SOP(O(O_LDC,SB),1,2,"ldc"),{IMM8,CCR,E}, { 0x0,0x7,IMM8,IGNORE,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_LDC,SB),1,2,"ldc"),{OR8,CCR,E}, { 0x0,0x3,0x0,OR8,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_LDC,SB),0,2,"ldc"),{ABS16SRC,CCR,E}, {PREFIXLDC,0x6,0xB,0x0,0x0,ABS16SRC,IGNORE,IGNORE,IGNORE,E}EOP,
+ NEW_SOP(O(O_LDC,SB),0,2,"ldc"),{ABS24SRC,CCR,E}, {PREFIXLDC,0x6,0xB,0x2,0x0,0x0,0x0,SRC|ABS24LIST,E}EOP,
+ NEW_SOP(O(O_LDC,SB),0,2,"ldc"),{DISP|SRC|L_16,CCR,E},{PREFIXLDC,0x6,0x9,B30|DISPREG,0,DISP|L_16,IGNORE,IGNORE,IGNORE,E}EOP,
+ NEW_SOP(O(O_LDC,SB),0,2,"ldc"),{DISP|SRC|L_24,CCR,E},{PREFIXLDC,0x7,0x8,B30|DISPREG,0,0x6,0xB,0x2,0x0,0x0,0x0,SRC|DISP24LIST,E}EOP,
+ NEW_SOP(O(O_LDC,SB),0,2,"ldc"),{RSINC,CCR,E}, {PREFIXLDC,0x6,0xD,B30|RSINC,0x0,E}EOP,
+ NEW_SOP(O(O_LDC,SB),0,2,"ldc"),{RSIND,CCR,E}, {PREFIXLDC,0x6,0x9,B30|RDIND,0x0,E} EOP,
+
+
+ SOP(O(O_MOV_TO_REG,SB),4,"mov.b"),{ABSMOV|ABS|SRC|L_16,RD8,E}, { 0x6,0xA,0x0,RD8,ABSMOV|SRC|ABS|A16LIST,E}EOP,
+ SOP(O(O_MOV_TO_REG,SB),6,"mov.b"),{ABSMOV|ABS|SRC|L_24,RD8,E }, { 0x6,0xA,0x2,RD8,0x0,0x0,SRC|ABSMOV|ABS|A24LIST,E }EOP,
+ SOP(O(O_MOV_TO_MEM,SB),4,"mov.b"),{RS8,ABSMOV|ABS|L_16|DST,E}, { 0x6,0xA,0x8,RS8,ABSMOV|DST|ABS|A16LIST,E}EOP,
+ SOP(O(O_MOV_TO_MEM,SB),6,"mov.b"),{RS8,ABSMOV|ABS|DST|L_24,E }, { 0x6,0xA,0xA,RS8,0x0,0x0,DST|ABSMOV|ABS|A24LIST,E }EOP,
+
+ SOP(O(O_MOV_TO_REG,SB),6,"mov.b"),{DISP|L_24|SRC,RD8,E}, { 0x7,0x8,B30|DISPREG,0x0,0x6,0xA,0x2,RD8,0x0,0x0,SRC|DISP24LIST,E}EOP,
+ SOP(O(O_MOV_TO_MEM,SB),6,"mov.b"),{RS8,DISP|L_24|DST,E}, { 0x7,0x8,B30|DISPREG,0x0,0x6,0xA,0xA,RS8,0x0,0x0,DST|DISP24LIST,E}EOP,
+
+
+
+ SOP(O(O_MOV_TO_REG,SB),2,"mov.b"),{RS8,RD8,E}, { 0x0,0xC,RS8,RD8,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_REG,SB),2,"mov.b"),{IMM8,RD8,E}, { 0xF,RD8,IMM8,IGNORE,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_REG,SB),4,"mov.b"),{RSIND,RD8,E}, { 0x6,0x8,B30|RSIND,RD8,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_REG,SB),6,"mov.b"),{DISP16SRC,RD8,E}, { 0x6,0xE,B30|DISPREG,RD8,DISP16SRC,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_MOV_TO_REG,SB),6,"mov.b"),{RSINC,RD8,E}, { 0x6,0xC,B30|RSINC,RD8,E,0,0,0,0}EOP,
+
+ SOP(O(O_MOV_TO_REG,SB),4,"mov.b"),{ABS8SRC,RD8,E}, { 0x2,RD8,ABS8SRC,IGNORE,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_MEM,SB),4,"mov.b"),{RS8,RDIND,E}, { 0x6,0x8,RDIND|B31,RS8,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_MEM,SB),6,"mov.b"),{RS8,DISP16DST,E}, { 0x6,0xE,DISPREG|B31,RS8,DISP16DST,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_MOV_TO_MEM,SB),6,"mov.b"),{RS8,RDDEC|B31,E}, { 0x6,0xC,RDDEC|B31,RS8,E,0,0,0,0}EOP,
+
+ SOP(O(O_MOV_TO_MEM,SB),4,"mov.b"),{RS8,ABS8DST,E}, { 0x3,RS8,ABS8DST,IGNORE,E,0,0,0,0}EOP,
+
+ SOP(O(O_MOV_TO_MEM,SW),6,"mov.w"),{RS16,RDIND,E}, { 0x6,0x9,RDIND|B31,RS16,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_REG,SW),6,"mov.w"),{DISP|L_24|SRC,RD16,E},{ 0x7,0x8,B30|DISPREG,0x0,0x6,0xB,0x2,RD16,0x0,0x0,SRC|DISP24LIST,E}EOP,
+ SOP(O(O_MOV_TO_MEM,SW),6,"mov.w"),{RS16,DISP|L_24|DST,E},{ 0x7,0x8,B30|DISPREG,0x0,0x6,0xB,0xA,RS16,0x0,0x0,DST|DISP24LIST,E}EOP,
+ SOP(O(O_MOV_TO_REG,SW),6,"mov.w"),{ABS|L_24|SRC,RD16,E },{ 0x6,0xB,0x2,RD16,0x0,0x0,SRC|ABS24LIST,E }EOP,
+ SOP(O(O_MOV_TO_MEM,SW),6,"mov.w"),{RS16,ABS|L_24|DST,E },{ 0x6,0xB,0xA,RS16,0x0,0x0,DST|ABS24LIST,E }EOP,
+ SOP(O(O_MOV_TO_REG,SW),2,"mov.w"),{RS16,RD16,E}, { 0x0,0xD,RS16, RD16,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_REG,SW),4,"mov.w"),{IMM16,RD16,E}, { 0x7,0x9,0x0,RD16,IMM16,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_MOV_TO_REG,SW),4,"mov.w"),{RSIND,RD16,E}, { 0x6,0x9,B30|RSIND,RD16,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_REG,SW),6,"mov.w"),{DISP16SRC,RD16,E}, { 0x6,0xF,B30|DISPREG,RD16,DISP16SRC,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_MOV_TO_REG,SW),6,"mov.w"),{RSINC,RD16,E}, { 0x6,0xD,B30|RSINC,RD16,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_REG,SW),6,"mov.w"),{ABS16SRC,RD16,E}, { 0x6,0xB,0x0,RD16,ABS16SRC,IGNORE,IGNORE,IGNORE,E}EOP,
+
+ SOP(O(O_MOV_TO_MEM,SW),6,"mov.w"),{RS16,DISP16DST,E}, { 0x6,0xF,DISPREG|B31,RS16,DISP16DST,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_MOV_TO_MEM,SW),6,"mov.w"),{RS16,RDDEC,E}, { 0x6,0xD,RDDEC|B31,RS16,E,0,0,0,0}EOP,
+ SOP(O(O_MOV_TO_MEM,SW),6,"mov.w"),{RS16,ABS16DST,E}, { 0x6,0xB,0x8,RS16,ABS16DST,IGNORE,IGNORE,IGNORE,E}EOP,
+
+ SOP(O(O_MOV_TO_REG,SL),4,"mov.l"),{IMM32,RD32,E}, { 0x7,0xA,0x0,B30|RD32,IMM32LIST,E}EOP,
+ SOP(O(O_MOV_TO_REG,SL),2,"mov.l"),{RS32,RD32,E}, { 0x0,0xF,B31|RS32,B30|RD32,E,0,0,0,0}EOP,
+
+ SOP(O(O_MOV_TO_REG,SL),4,"mov.l"),{RSIND,RD32,E}, { PREFIX32,0x6,0x9,RSIND|B30,B30|RD32,E,0,0,0,0 }EOP,
+ SOP(O(O_MOV_TO_REG,SL),6,"mov.l"),{DISP16SRC,RD32,E}, { PREFIX32,0x6,0xF,DISPREG|B30,B30|RD32,DISP16SRC,IGNORE,IGNORE,IGNORE,E }EOP,
+ SOP(O(O_MOV_TO_REG,SL),6,"mov.l"),{DISP|L_24|SRC,RD32,E},{ PREFIX32,0x7,0x8,B30|DISPREG,0x0,0x6,0xB,0x2,B30|RD32,0x0,0x0,SRC|DISP24LIST,E }EOP,
+ SOP(O(O_MOV_TO_REG,SL),6,"mov.l"),{RSINC,RD32,E}, { PREFIX32,0x6,0xD,B30|RSINC,B30|RD32,E,0,0,0,0 }EOP,
+ SOP(O(O_MOV_TO_REG,SL),6,"mov.l"),{ABS16SRC,RD32,E}, { PREFIX32,0x6,0xB,0x0,B30|RD32,ABS16SRC,IGNORE,IGNORE,IGNORE,E }EOP,
+ SOP(O(O_MOV_TO_REG,SL),6,"mov.l"),{ABS24SRC,RD32,E }, { PREFIX32,0x6,0xB,0x2,B30|RD32,0x0,0x0,SRC|ABS24LIST,E }EOP,
+ SOP(O(O_MOV_TO_MEM,SL),6,"mov.l"),{RS32,RDIND,E}, { PREFIX32,0x6,0x9,RDIND|B31,B30|RS32,E,0,0,0,0 }EOP,
+ SOP(O(O_MOV_TO_MEM,SL),6,"mov.l"),{RS32,DISP16DST,E}, { PREFIX32,0x6,0xF,DISPREG|B31,B30|RS32,DISP16DST,IGNORE,IGNORE,IGNORE,E }EOP,
+ SOP(O(O_MOV_TO_MEM,SL),6,"mov.l"),{RS32,DISP|L_24|DST,E},{ PREFIX32,0x7,0x8,B31|DISPREG,0x0,0x6,0xB,0xA,B30|RS32,0x0,0x0,DST|DISP24LIST,E }EOP,
+ SOP(O(O_MOV_TO_MEM,SL),6,"mov.l"),{RS32,RDDEC,E}, { PREFIX32,0x6,0xD,RDDEC|B31,B30|RS32,E,0,0,0,0 }EOP,
+ SOP(O(O_MOV_TO_MEM,SL),6,"mov.l"),{RS32,ABS16DST,E}, { PREFIX32,0x6,0xB,0x8,B30|RS32,ABS16DST,IGNORE,IGNORE,IGNORE,E }EOP,
+ SOP(O(O_MOV_TO_MEM,SL),6,"mov.l"),{RS32,ABS24DST,E }, { PREFIX32,0x6,0xB,0xA,B30|RS32,0x0,0x0,DST|ABS24LIST,E }EOP,
+
+ SOP(O(O_MOV_TO_REG,SB),10,"movfpe"),{ABS16SRC,RD8,E},{ 0x6,0xA,0x4,RD8,ABS16SRC,IGNORE,IGNORE,IGNORE,E}EOP,
+ SOP(O(O_MOV_TO_MEM,SB),10,"movtpe"),{RS8,ABS16DST,E},{ 0x6,0xA,0xC,RS8,ABS16DST,IGNORE,IGNORE,IGNORE,E}EOP,
+
+ NEW_SOP(O(O_MULU,SB),1,14,"mulxu.b"),{RS8,RD16,E}, { 0x5,0x0,RS8,RD16,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_MULU,SW),0,14,"mulxu.w"),{RS16,RD32,E},{ 0x5,0x2,RS16,B30|RD32,E,0,0,0,0}EOP,
+
+ NEW_SOP(O(O_MULS,SB),0,20,"mulxs.b"),{RS8,RD16,E}, { 0x0,0x1,0xc,0x0,0x5,0x0,RS8,RD16,E}EOP,
+ NEW_SOP(O(O_MULS,SW),0,20,"mulxs.w"),{RS16,RD32,E},{ 0x0,0x1,0xc,0x0,0x5,0x2,RS16,B30|RD32,E}EOP,
+
+ /* ??? This can use UNOP3. */
+ NEW_SOP(O(O_NEG,SB),1,2,"neg.b"),{ OR8,E, 0},{ 0x1,0x7,0x8,OR8,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_NEG,SW),0,2,"neg.w"),{ OR16,E,0},{ 0x1,0x7,0x9,OR16,E}EOP,
+ NEW_SOP(O(O_NEG,SL),0,2,"neg.l"),{ OR32,E,0},{ 0x1,0x7,0xB,B30|OR32,E}EOP,
+
+ NEW_SOP(O(O_NOP,SB),1,2,"nop"),{E,0,0},{ 0x0,0x0,0x0,0x0,E,0,0,0,0}EOP,
+
+ /* ??? This can use UNOP3. */
+ NEW_SOP(O(O_NOT,SB),1,2,"not.b"),{ OR8,E, 0},{ 0x1,0x7,0x0,OR8,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_NOT,SW),0,2,"not.w"),{ OR16,E,0},{ 0x1,0x7,0x1,OR16,E}EOP,
+ NEW_SOP(O(O_NOT,SL),0,2,"not.l"),{ OR32,E,0},{ 0x1,0x7,0x3,B30|OR32,E}EOP,
+
+ TWOOP(O(O_OR, SB),"or.b",0xC,0x1,0x4),
+ NEW_SOP(O(O_OR,SW),0,4,"or.w"),{IMM16,RD16,E },{0x7,0x9,0x4,RD16,IMM16,IGNORE,IGNORE,IGNORE,E} EOP,
+ NEW_SOP(O(O_OR,SW),0,2,"or.w"),{RS16,RD16,E },{0x6,0x4,RS16,RD16,E} EOP,
+
+ NEW_SOP(O(O_OR,SL),0,6,"or.l"),{IMM32,RD32,E },{0x7,0xA,0x4,B30|RD32,IMM32LIST,E} EOP,
+ NEW_SOP(O(O_OR,SL),0,2,"or.l"),{RS32,RD32,E },{0x0,0x1,0xF,0x0,0x6,0x4,B30|RS32,B30|RD32,E} EOP,
+
+ NEW_SOP(O(O_ORC,SB),1,2,"orc"),{IMM8,CCR,E},{ 0x0,0x4,IMM8,IGNORE,E,0,0,0,0}EOP,
+
+ NEW_SOP(O(O_MOV_TO_REG,SW),1,6,"pop.w"),{OR16,E,0},{ 0x6,0xD,0x7,OR16,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_MOV_TO_REG,SL),0,6,"pop.l"),{OR32,E,0},{ PREFIX32,0x6,0xD,0x7,OR32|B30,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_MOV_TO_MEM,SW),1,6,"push.w"),{OR16,E,0},{ 0x6,0xD,0xF,OR16,E,0,0,0,0}EOP,
+ NEW_SOP(O(O_MOV_TO_MEM,SL),0,6,"push.l"),{OR32,E,0},{ PREFIX32,0x6,0xD,0xF,OR32|B30,E,0,0,0,0}EOP,
+
+ UNOP3(O_ROTL, "rotl", 0x1,0x2,0x8),
+ UNOP3(O_ROTR, "rotr", 0x1,0x3,0x8),
+ UNOP3(O_ROTXL, "rotxl",0x1,0x2,0x0),
+ UNOP3(O_ROTXR, "rotxr",0x1,0x3,0x0),
+
+ SOP(O(O_BPT,SB), 10,"bpt"),{E,0,0},{ 0x7,0xA,0xF,0xF,E,0,0,0,0}EOP,
+ SOP(O(O_RTE,SB), 10,"rte"),{E,0,0},{ 0x5,0x6,0x7,0x0,E,0,0,0,0}EOP,
+ SOP(O(O_RTS,SB), 8,"rts"),{E,0,0},{ 0x5,0x4,0x7,0x0,E,0,0,0,0}EOP,
+
+ UNOP3(O_SHAL, "shal",0x1,0x0,0x8),
+ UNOP3(O_SHAR, "shar",0x1,0x1,0x8),
+ UNOP3(O_SHLL, "shll",0x1,0x0,0x0),
+ UNOP3(O_SHLR, "shlr",0x1,0x1,0x0),
+
+ SOP(O(O_SLEEP,SB),2,"sleep"),{E,0,0},{ 0x0,0x1,0x8,0x0,E,0,0,0,0} EOP,
+
+ NEW_SOP(O(O_STC,SB), 1,2,"stc"),{CCR,RD8,E},{ 0x0,0x2,0x0,RD8,E,0,0,0,0} EOP,
+
+ NEW_SOP(O(O_STC,SB),0,2,"stc"),{CCR,RSIND,E}, {PREFIXLDC,0x6,0x9,B31|RDIND,0x0,E} EOP,
+ NEW_SOP(O(O_STC,SB),0,2,"stc"),{CCR,DISP|DST|L_16,E},{PREFIXLDC,0x6,0x9,B31|DISPREG,0,DST|DISP|L_16,IGNORE,IGNORE,IGNORE,E}EOP,
+ NEW_SOP(O(O_STC,SB),0,2,"stc"),{CCR,DISP|DST|L_24,E},{PREFIXLDC,0x7,0x8,B31|DISPREG,0,0x6,0xB,0x2,0x0,0x0,0x0,DST|DISP24LIST,E}EOP,
+ NEW_SOP(O(O_STC,SB),0,2,"stc"),{CCR,RDDEC,E}, {PREFIXLDC,0x6,0xD,B31|RDDEC,0x0,E}EOP,
+
+ NEW_SOP(O(O_STC,SB),0,2,"stc"),{CCR,ABS16SRC,E}, {PREFIXLDC,0x6,0xB,0x8,0x0,ABS16DST,IGNORE,IGNORE,IGNORE,E}EOP,
+ NEW_SOP(O(O_STC,SB),0,2,"stc"),{CCR,ABS24SRC,E}, {PREFIXLDC,0x6,0xB,0xA,0x0,0x0,0x0,DST|ABS24LIST,E}EOP,
+
+ SOP(O(O_SUB,SB),2,"sub.b"),{RS8,RD8,E},{ 0x1,0x8,RS8,RD8,E,0,0,0,0}EOP,
+
+ NEW_SOP(O(O_SUB,SW),1,2,"sub.w"),{RS16,RD16,E }, {0x1,0x9,RS16,RD16,E} EOP,
+ NEW_SOP(O(O_SUB,SW),0,4,"sub.w"),{IMM16,RD16,E }, {0x7,0x9,0x3,RD16,IMM16,IGNORE,IGNORE,IGNORE,E} EOP,
+ NEW_SOP(O(O_SUB,SL),0,2,"sub.l") ,{RS32,RD32,E }, {0x1,0xA,B31|RS32,B30|RD32,E} EOP,
+ NEW_SOP(O(O_SUB,SL),0,6,"sub.l"), {IMM32,RD32,E },{0x7,0xA,0x3,B30|RD32,IMM32LIST,E} EOP,
+
+ SOP(O(O_SUBS,SL),2,"subs"),{KBIT,RDP,E},{ 0x1,0xB,KBIT,RDP,E,0,0,0,0}EOP,
+ TWOOP(O(O_SUBX,SB),"subx",0xB,0x1,0xE),
+
+ NEW_SOP(O(O_TRAPA,SB),0,2,"trapa"),{ IMM2,E}, {0x5,0x7,IMM2,IGNORE,E }EOP,
+
+ TWOOP(O(O_XOR, SB),"xor",0xD,0x1,0x5),
+
+ NEW_SOP(O(O_XOR,SW),0,4,"xor.w"),{IMM16,RD16,E },{0x7,0x9,0x5,RD16,IMM16,IGNORE,IGNORE,IGNORE,E} EOP,
+ NEW_SOP(O(O_XOR,SW),0,2,"xor.w"),{RS16,RD16,E },{0x6,0x5,RS16,RD16,E} EOP,
+
+ NEW_SOP(O(O_XOR,SL),0,6,"xor.l"),{IMM32,RD32,E },{0x7,0xA,0x5,B30|RD32,IMM32LIST,E} EOP,
+ NEW_SOP(O(O_XOR,SL),0,2,"xor.l") ,{RS32,RD32,E },{0x0,0x1,0xF,0x0,0x6,0x5,B30|RS32,B30|RD32,E} EOP,
+
+ SOP(O(O_XORC,SB),2,"xorc"),{IMM8,CCR,E},{ 0x0,0x5,IMM8,IGNORE,E,0,0,0,0}EOP,
+ 0
+};
+#else
+extern struct h8_opcode h8_opcodes[] ;
+#endif
+
+
+
+
diff --git a/contrib/gdb/include/opcode/hppa.h b/contrib/gdb/include/opcode/hppa.h
new file mode 100644
index 0000000..6f50e6b
--- /dev/null
+++ b/contrib/gdb/include/opcode/hppa.h
@@ -0,0 +1,471 @@
+/* Table of opcodes for the PA-RISC.
+ Copyright (C) 1990, 1991, 1993, 1995 Free Software Foundation, Inc.
+
+ Contributed by the Center for Software Science at the
+ University of Utah (pa-gdb-bugs@cs.utah.edu).
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+
+/* There are two kinds of delay slot nullification: normal which is
+ * controled by the nullification bit, and conditional, which depends
+ * on the direction of the branch and its success or failure.
+ *
+ * NONE is unfortunately #defined in the hiux system include files.
+ * #undef it away.
+ */
+#undef NONE
+struct pa_opcode
+{
+ const char *name;
+ unsigned long int match; /* Bits that must be set... */
+ unsigned long int mask; /* ... in these bits. */
+ char *args;
+ enum pa_arch arch;
+};
+
+/*
+ All hppa opcodes are 32 bits.
+
+ The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing one character
+ for each operand of the instruction.
+
+ Bit positions in this description follow HP usage of lsb = 31,
+ "at" is lsb of field.
+
+ In the args field, the following characters must match exactly:
+
+ '+,() '
+
+ In the args field, the following characters are unused:
+
+ ' "#$% *+- ./ 3 :; = '
+ ' B L [\] _'
+ ' e gh lm qr { } '
+
+ Here are all the characters:
+
+ ' !"#$%&'()*+-,./0123456789:;<=>?@'
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_'
+ 'abcdefghijklmnopqrstuvwxyz{|}~'
+
+Kinds of operands:
+ x integer register field at 15.
+ b integer register field at 10.
+ t integer register field at 31.
+ y floating point register field at 31
+ 5 5 bit immediate at 15.
+ s 2 bit space specifier at 17.
+ S 3 bit space specifier at 18.
+ c indexed load completer.
+ C short load and store completer.
+ Y Store Bytes Short completer
+ < non-negated compare/subtract conditions.
+ a compare/subtract conditions
+ d non-negated add conditions
+ & logical instruction conditions
+ U unit instruction conditions
+ > shift/extract/deposit conditions.
+ ~ bvb,bb conditions
+ V 5 bit immediate value at 31
+ i 11 bit immediate value at 31
+ j 14 bit immediate value at 31
+ k 21 bit immediate value at 31
+ n nullification for branch instructions
+ N nullification for spop and copr instructions
+ w 12 bit branch displacement
+ W 17 bit branch displacement (PC relative)
+ z 17 bit branch displacement (just a number, not an address)
+
+Also these:
+
+ p 5 bit shift count at 26 (to support the SHD instruction) encoded as
+ 31-p
+ P 5 bit bit position at 26
+ T 5 bit field length at 31 (encoded as 32-T)
+ A 13 bit immediate at 18 (to support the BREAK instruction)
+ ^ like b, but describes a control register
+ Z System Control Completer (to support LPA, LHA, etc.)
+ D 26 bit immediate at 31 (to support the DIAG instruction)
+
+ f 3 bit Special Function Unit identifier at 25
+ O 20 bit Special Function Unit operation split between 15 bits at 20
+ and 5 bits at 31
+ o 15 bit Special Function Unit operation at 20
+ 2 22 bit Special Function Unit operation split between 17 bits at 20
+ and 5 bits at 31
+ 1 15 bit Special Function Unit operation split between 10 bits at 20
+ and 5 bits at 31
+ 0 10 bit Special Function Unit operation split between 5 bits at 20
+ and 5 bits at 31
+ u 3 bit coprocessor unit identifier at 25
+ F Source Floating Point Operand Format Completer encoded 2 bits at 20
+ I Source Floating Point Operand Format Completer encoded 1 bits at 20
+ (for 0xe format FP instructions)
+ G Destination Floating Point Operand Format Completer encoded 2 bits at 18
+ M Floating-Point Compare Conditions (encoded as 5 bits at 31)
+ ? non-negated/negated compare/subtract conditions.
+ @ non-negated/negated add conditions.
+ ! non-negated add conditions.
+
+ s 2 bit space specifier at 17.
+ b register field at 10.
+ r 5 bit immediate value at 31 (for the break instruction)
+ (very similar to V above, except the value is unsigned instead of
+ low_sign_ext)
+ R 5 bit immediate value at 15 (for the ssm, rsm, probei instructions)
+ (same as r above, except the value is in a different location)
+ Q 5 bit immediate value at 10 (a bit position specified in
+ the bb instruction. It's the same as r above, except the
+ value is in a different location)
+ | shift/extract/deposit conditions when used in a conditional branch
+
+And these (PJH) for PA-89 F.P. registers and instructions:
+
+ v a 't' operand type extended to handle L/R register halves.
+ E a 'b' operand type extended to handle L/R register halves.
+ X an 'x' operand type extended to handle L/R register halves.
+ J a 'b' operand type further extended to handle extra 1.1 registers
+ K a 'x' operand type further extended to handle extra 1.1 registers
+ 4 a variation of the 'b' operand type for 'fmpyadd' and 'fmpysub'
+ 6 a variation of the 'x' operand type for 'fmpyadd' and 'fmpysub'
+ 7 a variation of the 't' operand type for 'fmpyadd' and 'fmpysub'
+ 8 5 bit register field at 20 (used in 'fmpyadd' and 'fmpysub')
+ 9 5 bit register field at 25 (used in 'fmpyadd' and 'fmpysub')
+ H Floating Point Operand Format at 26 for 'fmpyadd' and 'fmpysub'
+ (very similar to 'F')
+*/
+
+/* The order of the opcodes in this table is significant:
+
+ * The assembler requires that all instances of the same mnemonic must be
+ consecutive. If they aren't, the assembler will bomb at runtime.
+
+ * The disassembler should not care about the order of the opcodes. */
+
+static const struct pa_opcode pa_opcodes[] =
+{
+
+/* pseudo-instructions */
+
+{ "b", 0xe8000000, 0xffe0e000, "nW", pa10}, /* bl foo,r0 */
+{ "ldi", 0x34000000, 0xffe0c000, "j,x", pa10}, /* ldo val(r0),r */
+{ "comib", 0x84000000, 0xfc000000, "?n5,b,w", pa10}, /* comib{tf}*/
+{ "comb", 0x80000000, 0xfc000000, "?nx,b,w", pa10}, /* comb{tf} */
+{ "addb", 0xa0000000, 0xfc000000, "@nx,b,w", pa10}, /* addb{tf} */
+{ "addib", 0xa4000000, 0xfc000000, "@n5,b,w", pa10}, /* addib{tf}*/
+{ "nop", 0x08000240, 0xffffffff, "", pa10}, /* or 0,0,0 */
+{ "copy", 0x08000240, 0xffe0ffe0, "x,t", pa10}, /* or r,0,t */
+{ "mtsar", 0x01601840, 0xffe0ffff, "x", pa10}, /* mtctl r,cr11 */
+
+/* Loads and Stores for integer registers. */
+{ "ldw", 0x48000000, 0xfc000000, "j(s,b),x", pa10},
+{ "ldw", 0x48000000, 0xfc000000, "j(b),x", pa10},
+{ "ldh", 0x44000000, 0xfc000000, "j(s,b),x", pa10},
+{ "ldh", 0x44000000, 0xfc000000, "j(b),x", pa10},
+{ "ldb", 0x40000000, 0xfc000000, "j(s,b),x", pa10},
+{ "ldb", 0x40000000, 0xfc000000, "j(b),x", pa10},
+{ "stw", 0x68000000, 0xfc000000, "x,j(s,b)", pa10},
+{ "stw", 0x68000000, 0xfc000000, "x,j(b)", pa10},
+{ "sth", 0x64000000, 0xfc000000, "x,j(s,b)", pa10},
+{ "sth", 0x64000000, 0xfc000000, "x,j(b)", pa10},
+{ "stb", 0x60000000, 0xfc000000, "x,j(s,b)", pa10},
+{ "stb", 0x60000000, 0xfc000000, "x,j(b)", pa10},
+{ "ldwm", 0x4c000000, 0xfc000000, "j(s,b),x", pa10},
+{ "ldwm", 0x4c000000, 0xfc000000, "j(b),x", pa10},
+{ "stwm", 0x6c000000, 0xfc000000, "x,j(s,b)", pa10},
+{ "stwm", 0x6c000000, 0xfc000000, "x,j(b)", pa10},
+{ "ldwx", 0x0c000080, 0xfc001fc0, "cx(s,b),t", pa10},
+{ "ldwx", 0x0c000080, 0xfc001fc0, "cx(b),t", pa10},
+{ "ldhx", 0x0c000040, 0xfc001fc0, "cx(s,b),t", pa10},
+{ "ldhx", 0x0c000040, 0xfc001fc0, "cx(b),t", pa10},
+{ "ldbx", 0x0c000000, 0xfc001fc0, "cx(s,b),t", pa10},
+{ "ldbx", 0x0c000000, 0xfc001fc0, "cx(b),t", pa10},
+{ "ldwax", 0x0c000180, 0xfc00dfc0, "cx(b),t", pa10},
+{ "ldcwx", 0x0c0001c0, 0xfc001fc0, "cx(s,b),t", pa10},
+{ "ldcwx", 0x0c0001c0, 0xfc001fc0, "cx(b),t", pa10},
+{ "ldws", 0x0c001080, 0xfc001fc0, "C5(s,b),t", pa10},
+{ "ldws", 0x0c001080, 0xfc001fc0, "C5(b),t", pa10},
+{ "ldhs", 0x0c001040, 0xfc001fc0, "C5(s,b),t", pa10},
+{ "ldhs", 0x0c001040, 0xfc001fc0, "C5(b),t", pa10},
+{ "ldbs", 0x0c001000, 0xfc001fc0, "C5(s,b),t", pa10},
+{ "ldbs", 0x0c001000, 0xfc001fc0, "C5(b),t", pa10},
+{ "ldwas", 0x0c001180, 0xfc00dfc0, "C5(b),t", pa10},
+{ "ldcws", 0x0c0011c0, 0xfc001fc0, "C5(s,b),t", pa10},
+{ "ldcws", 0x0c0011c0, 0xfc001fc0, "C5(b),t", pa10},
+{ "stws", 0x0c001280, 0xfc001fc0, "Cx,V(s,b)", pa10},
+{ "stws", 0x0c001280, 0xfc001fc0, "Cx,V(b)", pa10},
+{ "sths", 0x0c001240, 0xfc001fc0, "Cx,V(s,b)", pa10},
+{ "sths", 0x0c001240, 0xfc001fc0, "Cx,V(b)", pa10},
+{ "stbs", 0x0c001200, 0xfc001fc0, "Cx,V(s,b)", pa10},
+{ "stbs", 0x0c001200, 0xfc001fc0, "Cx,V(b)", pa10},
+{ "stwas", 0x0c001380, 0xfc00dfc0, "Cx,V(b)", pa10},
+{ "stbys", 0x0c001300, 0xfc001fc0, "Yx,V(s,b)", pa10},
+{ "stbys", 0x0c001300, 0xfc001fc0, "Yx,V(b)", pa10},
+
+/* Immediate instructions. */
+{ "ldo", 0x34000000, 0xfc00c000, "j(b),x", pa10},
+{ "ldil", 0x20000000, 0xfc000000, "k,b", pa10},
+{ "addil", 0x28000000, 0xfc000000, "k,b", pa10},
+
+/* Branching instructions. */
+{ "bl", 0xe8000000, 0xfc00e000, "nW,b", pa10},
+{ "gate", 0xe8002000, 0xfc00e000, "nW,b", pa10},
+{ "blr", 0xe8004000, 0xfc00e001, "nx,b", pa10},
+{ "bv", 0xe800c000, 0xfc00e001, "nx(b)", pa10},
+{ "bv", 0xe800c000, 0xfc00e001, "n(b)", pa10},
+{ "be", 0xe0000000, 0xfc000000, "nz(S,b)", pa10},
+{ "ble", 0xe4000000, 0xfc000000, "nz(S,b)", pa10},
+{ "movb", 0xc8000000, 0xfc000000, "|nx,b,w", pa10},
+{ "movib", 0xcc000000, 0xfc000000, "|n5,b,w", pa10},
+{ "combt", 0x80000000, 0xfc000000, "<nx,b,w", pa10},
+{ "combf", 0x88000000, 0xfc000000, "<nx,b,w", pa10},
+{ "comibt", 0x84000000, 0xfc000000, "<n5,b,w", pa10},
+{ "comibf", 0x8c000000, 0xfc000000, "<n5,b,w", pa10},
+{ "addbt", 0xa0000000, 0xfc000000, "!nx,b,w", pa10},
+{ "addbf", 0xa8000000, 0xfc000000, "!nx,b,w", pa10},
+{ "addibt", 0xa4000000, 0xfc000000, "!n5,b,w", pa10},
+{ "addibf", 0xac000000, 0xfc000000, "!n5,b,w", pa10},
+{ "bvb", 0xc0000000, 0xffe00000, "~nx,w", pa10},
+{ "bb", 0xc4000000, 0xfc000000, "~nx,Q,w", pa10},
+
+/* Computation Instructions */
+
+{ "add", 0x08000600, 0xfc000fe0, "dx,b,t", pa10},
+{ "addl", 0x08000a00, 0xfc000fe0, "dx,b,t", pa10},
+{ "addo", 0x08000e00, 0xfc000fe0, "dx,b,t", pa10},
+{ "addc", 0x08000700, 0xfc000fe0, "dx,b,t", pa10},
+{ "addco", 0x08000f00, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh1add", 0x08000640, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh1addl", 0x08000a40, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh1addo", 0x08000e40, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh2add", 0x08000680, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh2addl", 0x08000a80, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh2addo", 0x08000e80, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh3add", 0x080006c0, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh3addl", 0x08000ac0, 0xfc000fe0, "dx,b,t", pa10},
+{ "sh3addo", 0x08000ec0, 0xfc000fe0, "dx,b,t", pa10},
+{ "sub", 0x08000400, 0xfc000fe0, "ax,b,t", pa10},
+{ "subo", 0x08000c00, 0xfc000fe0, "ax,b,t", pa10},
+{ "subb", 0x08000500, 0xfc000fe0, "ax,b,t", pa10},
+{ "subbo", 0x08000d00, 0xfc000fe0, "ax,b,t", pa10},
+{ "subt", 0x080004c0, 0xfc000fe0, "ax,b,t", pa10},
+{ "subto", 0x08000cc0, 0xfc000fe0, "ax,b,t", pa10},
+{ "ds", 0x08000440, 0xfc000fe0, "ax,b,t", pa10},
+{ "comclr", 0x08000880, 0xfc000fe0, "ax,b,t", pa10},
+{ "or", 0x08000240, 0xfc000fe0, "&x,b,t", pa10},
+{ "xor", 0x08000280, 0xfc000fe0, "&x,b,t", pa10},
+{ "and", 0x08000200, 0xfc000fe0, "&x,b,t", pa10},
+{ "andcm", 0x08000000, 0xfc000fe0, "&x,b,t", pa10},
+{ "uxor", 0x08000380, 0xfc000fe0, "Ux,b,t", pa10},
+{ "uaddcm", 0x08000980, 0xfc000fe0, "Ux,b,t", pa10},
+{ "uaddcmt", 0x080009c0, 0xfc000fe0, "Ux,b,t", pa10},
+{ "dcor", 0x08000b80, 0xfc1f0fe0, "Ub,t", pa10},
+{ "idcor", 0x08000bc0, 0xfc1f0fe0, "Ub,t", pa10},
+{ "addi", 0xb4000000, 0xfc000800, "di,b,x", pa10},
+{ "addio", 0xb4000800, 0xfc000800, "di,b,x", pa10},
+{ "addit", 0xb0000000, 0xfc000800, "di,b,x", pa10},
+{ "addito", 0xb0000800, 0xfc000800, "di,b,x", pa10},
+{ "subi", 0x94000000, 0xfc000800, "ai,b,x", pa10},
+{ "subio", 0x94000800, 0xfc000800, "ai,b,x", pa10},
+{ "comiclr", 0x90000000, 0xfc000800, "ai,b,x", pa10},
+
+/* Extract and Deposit Instructions */
+
+{ "vshd", 0xd0000000, 0xfc001fe0, ">x,b,t", pa10},
+{ "shd", 0xd0000800, 0xfc001c00, ">x,b,p,t", pa10},
+{ "vextru", 0xd0001000, 0xfc001fe0, ">b,T,x", pa10},
+{ "vextrs", 0xd0001400, 0xfc001fe0, ">b,T,x", pa10},
+{ "extru", 0xd0001800, 0xfc001c00, ">b,P,T,x", pa10},
+{ "extrs", 0xd0001c00, 0xfc001c00, ">b,P,T,x", pa10},
+{ "zvdep", 0xd4000000, 0xfc001fe0, ">x,T,b", pa10},
+{ "vdep", 0xd4000400, 0xfc001fe0, ">x,T,b", pa10},
+{ "zdep", 0xd4000800, 0xfc001c00, ">x,p,T,b", pa10},
+{ "dep", 0xd4000c00, 0xfc001c00, ">x,p,T,b", pa10},
+{ "zvdepi", 0xd4001000, 0xfc001fe0, ">5,T,b", pa10},
+{ "vdepi", 0xd4001400, 0xfc001fe0, ">5,T,b", pa10},
+{ "zdepi", 0xd4001800, 0xfc001c00, ">5,p,T,b", pa10},
+{ "depi", 0xd4001c00, 0xfc001c00, ">5,p,T,b", pa10},
+
+/* System Control Instructions */
+
+{ "break", 0x00000000, 0xfc001fe0, "r,A", pa10},
+{ "rfi", 0x00000c00, 0xffffffff, "", pa10},
+{ "rfir", 0x00000ca0, 0xffffffff, "", pa11},
+{ "ssm", 0x00000d60, 0xffe0ffe0, "R,t", pa10},
+{ "rsm", 0x00000e60, 0xffe0ffe0, "R,t", pa10},
+{ "mtsm", 0x00001860, 0xffe0ffff, "x", pa10},
+{ "ldsid", 0x000010a0, 0xfc1f3fe0, "(s,b),t", pa10},
+{ "ldsid", 0x000010a0, 0xfc1f3fe0, "(b),t", pa10},
+{ "mtsp", 0x00001820, 0xffe01fff, "x,S", pa10},
+{ "mtctl", 0x00001840, 0xfc00ffff, "x,^", pa10},
+{ "mfsp", 0x000004a0, 0xffff1fe0, "S,t", pa10},
+{ "mfctl", 0x000008a0, 0xfc1fffe0, "^,t", pa10},
+{ "sync", 0x00000400, 0xffffffff, "", pa10},
+{ "syncdma", 0x00100400, 0xffffffff, "", pa10},
+{ "prober", 0x04001180, 0xfc003fe0, "(s,b),x,t", pa10},
+{ "prober", 0x04001180, 0xfc003fe0, "(b),x,t", pa10},
+{ "proberi", 0x04003180, 0xfc003fe0, "(s,b),R,t", pa10},
+{ "proberi", 0x04003180, 0xfc003fe0, "(b),R,t", pa10},
+{ "probew", 0x040011c0, 0xfc003fe0, "(s,b),x,t", pa10},
+{ "probew", 0x040011c0, 0xfc003fe0, "(b),x,t", pa10},
+{ "probewi", 0x040031c0, 0xfc003fe0, "(s,b),R,t", pa10},
+{ "probewi", 0x040031c0, 0xfc003fe0, "(b),R,t", pa10},
+{ "lpa", 0x04001340, 0xfc003fc0, "Zx(s,b),t", pa10},
+{ "lpa", 0x04001340, 0xfc003fc0, "Zx(b),t", pa10},
+{ "lha", 0x04001300, 0xfc003fc0, "Zx(s,b),t", pa10},
+{ "lha", 0x04001300, 0xfc003fc0, "Zx(b),t", pa10},
+{ "lci", 0x04001300, 0xfc003fe0, "x(s,b),t", pa10},
+{ "lci", 0x04001300, 0xfc003fe0, "x(b),t", pa10},
+{ "pdtlb", 0x04001200, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "pdtlb", 0x04001200, 0xfc003fdf, "Zx(b)", pa10},
+{ "pitlb", 0x04000200, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "pitlb", 0x04000200, 0xfc003fdf, "Zx(b)", pa10},
+{ "pdtlbe", 0x04001240, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "pdtlbe", 0x04001240, 0xfc003fdf, "Zx(b)", pa10},
+{ "pitlbe", 0x04000240, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "pitlbe", 0x04000240, 0xfc003fdf, "Zx(b)", pa10},
+{ "idtlba", 0x04001040, 0xfc003fff, "x,(s,b)", pa10},
+{ "idtlba", 0x04001040, 0xfc003fff, "x,(b)", pa10},
+{ "iitlba", 0x04000040, 0xfc003fff, "x,(s,b)", pa10},
+{ "iitlba", 0x04000040, 0xfc003fff, "x,(b)", pa10},
+{ "idtlbp", 0x04001000, 0xfc003fff, "x,(s,b)", pa10},
+{ "idtlbp", 0x04001000, 0xfc003fff, "x,(b)", pa10},
+{ "iitlbp", 0x04000000, 0xfc003fff, "x,(s,b)", pa10},
+{ "iitlbp", 0x04000000, 0xfc003fff, "x,(b)", pa10},
+{ "pdc", 0x04001380, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "pdc", 0x04001380, 0xfc003fdf, "Zx(b)", pa10},
+{ "fdc", 0x04001280, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "fdc", 0x04001280, 0xfc003fdf, "Zx(b)", pa10},
+{ "fic", 0x04000280, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "fic", 0x04000280, 0xfc003fdf, "Zx(b)", pa10},
+{ "fdce", 0x040012c0, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "fdce", 0x040012c0, 0xfc003fdf, "Zx(b)", pa10},
+{ "fice", 0x040002c0, 0xfc003fdf, "Zx(s,b)", pa10},
+{ "fice", 0x040002c0, 0xfc003fdf, "Zx(b)", pa10},
+{ "diag", 0x14000000, 0xfc000000, "D", pa10},
+
+/* gfw and gfr are not in the HP PA 1.1 manual, but they are in either
+ the Timex FPU or the Mustang ERS (not sure which) manual. */
+{ "gfw", 0x04001680, 0xfc003fdf, "Zx(s,b)", pa11},
+{ "gfw", 0x04001680, 0xfc003fdf, "Zx(b)", pa11},
+{ "gfr", 0x04001a80, 0xfc003fdf, "Zx(s,b)", pa11},
+{ "gfr", 0x04001a80, 0xfc003fdf, "Zx(b)", pa11},
+
+/* Floating Point Coprocessor Instructions */
+
+{ "fldwx", 0x24000000, 0xfc001f80, "cx(s,b),v", pa10},
+{ "fldwx", 0x24000000, 0xfc001f80, "cx(b),v", pa10},
+{ "flddx", 0x2c000000, 0xfc001fc0, "cx(s,b),y", pa10},
+{ "flddx", 0x2c000000, 0xfc001fc0, "cx(b),y", pa10},
+{ "fstwx", 0x24000200, 0xfc001f80, "cv,x(s,b)", pa10},
+{ "fstwx", 0x24000200, 0xfc001f80, "cv,x(b)", pa10},
+{ "fstdx", 0x2c000200, 0xfc001fc0, "cy,x(s,b)", pa10},
+{ "fstdx", 0x2c000200, 0xfc001fc0, "cy,x(b)", pa10},
+{ "fstqx", 0x3c000200, 0xfc001fc0, "cy,x(s,b)", pa10},
+{ "fstqx", 0x3c000200, 0xfc001fc0, "cy,x(b)", pa10},
+{ "fldws", 0x24001000, 0xfc001f80, "C5(s,b),v", pa10},
+{ "fldws", 0x24001000, 0xfc001f80, "C5(b),v", pa10},
+{ "fldds", 0x2c001000, 0xfc001fc0, "C5(s,b),y", pa10},
+{ "fldds", 0x2c001000, 0xfc001fc0, "C5(b),y", pa10},
+{ "fstws", 0x24001200, 0xfc001f80, "Cv,5(s,b)", pa10},
+{ "fstws", 0x24001200, 0xfc001f80, "Cv,5(b)", pa10},
+{ "fstds", 0x2c001200, 0xfc001fc0, "Cy,5(s,b)", pa10},
+{ "fstds", 0x2c001200, 0xfc001fc0, "Cy,5(b)", pa10},
+{ "fstqs", 0x3c001200, 0xfc001fc0, "Cy,5(s,b)", pa10},
+{ "fstqs", 0x3c001200, 0xfc001fc0, "Cy,5(b)", pa10},
+{ "fadd", 0x30000600, 0xfc00e7e0, "FE,X,v", pa10},
+{ "fadd", 0x38000600, 0xfc00e720, "IJ,K,v", pa10},
+{ "fsub", 0x30002600, 0xfc00e7e0, "FE,X,v", pa10},
+{ "fsub", 0x38002600, 0xfc00e720, "IJ,K,v", pa10},
+{ "fmpy", 0x30004600, 0xfc00e7e0, "FE,X,v", pa10},
+{ "fmpy", 0x38004600, 0xfc00e720, "IJ,K,v", pa10},
+{ "fdiv", 0x30006600, 0xfc00e7e0, "FE,X,v", pa10},
+{ "fdiv", 0x38006600, 0xfc00e720, "IJ,K,v", pa10},
+{ "fsqrt", 0x30008000, 0xfc1fe7e0, "FE,v", pa10},
+{ "fsqrt", 0x38008000, 0xfc1fe720, "FJ,v", pa10},
+{ "fabs", 0x30006000, 0xfc1fe7e0, "FE,v", pa10},
+{ "fabs", 0x38006000, 0xfc1fe720, "FJ,v", pa10},
+{ "frem", 0x30008600, 0xfc00e7e0, "FE,X,v", pa10},
+{ "frem", 0x38008600, 0xfc00e720, "FJ,K,v", pa10},
+{ "frnd", 0x3000a000, 0xfc1fe7e0, "FE,v", pa10},
+{ "frnd", 0x3800a000, 0xfc1fe720, "FJ,v", pa10},
+{ "fcpy", 0x30004000, 0xfc1fe7e0, "FE,v", pa10},
+{ "fcpy", 0x38004000, 0xfc1fe720, "FJ,v", pa10},
+{ "fcnvff", 0x30000200, 0xfc1f87e0, "FGE,v", pa10},
+{ "fcnvff", 0x38000200, 0xfc1f8720, "FGJ,v", pa10},
+{ "fcnvxf", 0x30008200, 0xfc1f87e0, "FGE,v", pa10},
+{ "fcnvxf", 0x38008200, 0xfc1f8720, "FGJ,v", pa10},
+{ "fcnvfx", 0x30010200, 0xfc1f87e0, "FGE,v", pa10},
+{ "fcnvfx", 0x38010200, 0xfc1f8720, "FGJ,v", pa10},
+{ "fcnvfxt", 0x30018200, 0xfc1f87e0, "FGE,v", pa10},
+{ "fcnvfxt", 0x38018200, 0xfc1f8720, "FGJ,v", pa10},
+{ "fcmp", 0x30000400, 0xfc00e7e0, "FME,X", pa10},
+{ "fcmp", 0x38000400, 0xfc00e720, "IMJ,K", pa10},
+{ "xmpyu", 0x38004700, 0xfc00e720, "E,X,v", pa11},
+{ "fmpyadd", 0x18000000, 0xfc000000, "H4,6,7,9,8", pa11},
+{ "fmpysub", 0x98000000, 0xfc000000, "H4,6,7,9,8", pa11},
+{ "ftest", 0x30002420, 0xffffffff, "", pa10},
+
+
+/* Assist Instructions */
+
+{ "spop0", 0x10000000, 0xfc000600, "f,ON", pa10},
+{ "spop1", 0x10000200, 0xfc000600, "f,oNt", pa10},
+{ "spop2", 0x10000400, 0xfc000600, "f,1Nb", pa10},
+{ "spop3", 0x10000600, 0xfc000600, "f,0Nx,b", pa10},
+{ "copr", 0x30000000, 0xfc000000, "u,2N", pa10},
+{ "cldwx", 0x24000000, 0xfc001e00, "ucx(s,b),t", pa10},
+{ "cldwx", 0x24000000, 0xfc001e00, "ucx(b),t", pa10},
+{ "clddx", 0x2c000000, 0xfc001e00, "ucx(s,b),t", pa10},
+{ "clddx", 0x2c000000, 0xfc001e00, "ucx(b),t", pa10},
+{ "cstwx", 0x24000200, 0xfc001e00, "uct,x(s,b)", pa10},
+{ "cstwx", 0x24000200, 0xfc001e00, "uct,x(b)", pa10},
+{ "cstdx", 0x2c000200, 0xfc001e00, "uct,x(s,b)", pa10},
+{ "cstdx", 0x2c000200, 0xfc001e00, "uct,x(b)", pa10},
+{ "cldws", 0x24001000, 0xfc001e00, "uC5(s,b),t", pa10},
+{ "cldws", 0x24001000, 0xfc001e00, "uC5(b),t", pa10},
+{ "cldds", 0x2c001000, 0xfc001e00, "uC5(s,b),t", pa10},
+{ "cldds", 0x2c001000, 0xfc001e00, "uC5(b),t", pa10},
+{ "cstws", 0x24001200, 0xfc001e00, "uCt,5(s,b)", pa10},
+{ "cstws", 0x24001200, 0xfc001e00, "uCt,5(b)", pa10},
+{ "cstds", 0x2c001200, 0xfc001e00, "uCt,5(s,b)", pa10},
+{ "cstds", 0x2c001200, 0xfc001e00, "uCt,5(b)", pa10},
+};
+
+#define NUMOPCODES ((sizeof pa_opcodes)/(sizeof pa_opcodes[0]))
+
+/* SKV 12/18/92. Added some denotations for various operands. */
+
+#define PA_IMM11_AT_31 'i'
+#define PA_IMM14_AT_31 'j'
+#define PA_IMM21_AT_31 'k'
+#define PA_DISP12 'w'
+#define PA_DISP17 'W'
+
+#define N_HPPA_OPERAND_FORMATS 5
diff --git a/contrib/gdb/include/opcode/i386.h b/contrib/gdb/include/opcode/i386.h
new file mode 100644
index 0000000..849a86f
--- /dev/null
+++ b/contrib/gdb/include/opcode/i386.h
@@ -0,0 +1,898 @@
+/* i386-opcode.h -- Intel 80386 opcode table
+ Copyright 1989, 1991, 1992, 1995 Free Software Foundation.
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU Debugger.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+static const template i386_optab[] = {
+
+#define _ None
+/* move instructions */
+#define MOV_AX_DISP32 0xa0
+{ "mov", 2, 0xa0, _, DW|NoModrm, { Disp32, Acc, 0 } },
+{ "mov", 2, 0x88, _, DW|Modrm, { Reg, Reg|Mem, 0 } },
+{ "mov", 2, 0xb0, _, ShortFormW, { Imm, Reg, 0 } },
+{ "mov", 2, 0xc6, _, W|Modrm, { Imm, Reg|Mem, 0 } },
+{ "mov", 2, 0x8c, _, D|Modrm, { SReg3|SReg2, Reg16|Mem, 0 } },
+/* move to/from control debug registers */
+{ "mov", 2, 0x0f20, _, D|Modrm, { Control, Reg32, 0} },
+{ "mov", 2, 0x0f21, _, D|Modrm, { Debug, Reg32, 0} },
+{ "mov", 2, 0x0f24, _, D|Modrm, { Test, Reg32, 0} },
+
+/* move with sign extend */
+/* "movsbl" & "movsbw" must not be unified into "movsb" to avoid
+ conflict with the "movs" string move instruction. Thus,
+ {"movsb", 2, 0x0fbe, _, ReverseRegRegmem|Modrm, { Reg8|Mem, Reg16|Reg32, 0} },
+ is not kosher; we must seperate the two instructions. */
+{"movsbl", 2, 0x0fbe, _, ReverseRegRegmem|Modrm|Data32, { Reg8|Mem, Reg32, 0} },
+{"movsbw", 2, 0x0fbe, _, ReverseRegRegmem|Modrm|Data16, { Reg8|Mem, Reg16, 0} },
+{"movswl", 2, 0x0fbf, _, ReverseRegRegmem|Modrm, { Reg16|Mem, Reg32, 0} },
+
+/* move with zero extend */
+{"movzb", 2, 0x0fb6, _, ReverseRegRegmem|Modrm, { Reg8|Mem, Reg16|Reg32, 0} },
+{"movzwl", 2, 0x0fb7, _, ReverseRegRegmem|Modrm, { Reg16|Mem, Reg32, 0} },
+
+/* push instructions */
+{"push", 1, 0x50, _, ShortForm, { WordReg,0,0 } },
+{"push", 1, 0xff, 0x6, Modrm, { WordReg|WordMem, 0, 0 } },
+{"push", 1, 0x6a, _, NoModrm, { Imm8S, 0, 0} },
+{"push", 1, 0x68, _, NoModrm, { Imm16|Imm32, 0, 0} },
+{"push", 1, 0x06, _, Seg2ShortForm, { SReg2,0,0 } },
+{"push", 1, 0x0fa0, _, Seg3ShortForm, { SReg3,0,0 } },
+/* push all */
+{"pusha", 0, 0x60, _, NoModrm, { 0, 0, 0 } },
+
+/* pop instructions */
+{"pop", 1, 0x58, _, ShortForm, { WordReg,0,0 } },
+{"pop", 1, 0x8f, 0x0, Modrm, { WordReg|WordMem, 0, 0 } },
+#define POP_SEG_SHORT 0x7
+{"pop", 1, 0x07, _, Seg2ShortForm, { SReg2,0,0 } },
+{"pop", 1, 0x0fa1, _, Seg3ShortForm, { SReg3,0,0 } },
+/* pop all */
+{"popa", 0, 0x61, _, NoModrm, { 0, 0, 0 } },
+
+/* xchg exchange instructions
+ xchg commutes: we allow both operand orders */
+{"xchg", 2, 0x90, _, ShortForm, { WordReg, Acc, 0 } },
+{"xchg", 2, 0x90, _, ShortForm, { Acc, WordReg, 0 } },
+{"xchg", 2, 0x86, _, W|Modrm, { Reg, Reg|Mem, 0 } },
+{"xchg", 2, 0x86, _, W|Modrm, { Reg|Mem, Reg, 0 } },
+
+/* in/out from ports */
+{"in", 2, 0xe4, _, W|NoModrm, { Imm8, Acc, 0 } },
+{"in", 2, 0xec, _, W|NoModrm, { InOutPortReg, Acc, 0 } },
+{"in", 1, 0xe4, _, W|NoModrm, { Imm8, 0, 0 } },
+{"in", 1, 0xec, _, W|NoModrm, { InOutPortReg, 0, 0 } },
+{"out", 2, 0xe6, _, W|NoModrm, { Acc, Imm8, 0 } },
+{"out", 2, 0xee, _, W|NoModrm, { Acc, InOutPortReg, 0 } },
+{"out", 1, 0xe6, _, W|NoModrm, { Imm8, 0, 0 } },
+{"out", 1, 0xee, _, W|NoModrm, { InOutPortReg, 0, 0 } },
+
+/* load effective address */
+{"lea", 2, 0x8d, _, Modrm, { WordMem, WordReg, 0 } },
+
+/* load segment registers from memory */
+{"lds", 2, 0xc5, _, Modrm, { Mem, Reg32, 0} },
+{"les", 2, 0xc4, _, Modrm, { Mem, Reg32, 0} },
+{"lfs", 2, 0x0fb4, _, Modrm, { Mem, Reg32, 0} },
+{"lgs", 2, 0x0fb5, _, Modrm, { Mem, Reg32, 0} },
+{"lss", 2, 0x0fb2, _, Modrm, { Mem, Reg32, 0} },
+
+/* flags register instructions */
+{"clc", 0, 0xf8, _, NoModrm, { 0, 0, 0} },
+{"cld", 0, 0xfc, _, NoModrm, { 0, 0, 0} },
+{"cli", 0, 0xfa, _, NoModrm, { 0, 0, 0} },
+{"clts", 0, 0x0f06, _, NoModrm, { 0, 0, 0} },
+{"cmc", 0, 0xf5, _, NoModrm, { 0, 0, 0} },
+{"lahf", 0, 0x9f, _, NoModrm, { 0, 0, 0} },
+{"sahf", 0, 0x9e, _, NoModrm, { 0, 0, 0} },
+{"pushfl", 0, 0x9c, _, NoModrm|Data32, { 0, 0, 0} },
+{"popfl", 0, 0x9d, _, NoModrm|Data32, { 0, 0, 0} },
+{"pushfw", 0, 0x9c, _, NoModrm|Data16, { 0, 0, 0} },
+{"popfw", 0, 0x9d, _, NoModrm|Data16, { 0, 0, 0} },
+{"pushf", 0, 0x9c, _, NoModrm, { 0, 0, 0} },
+{"popf", 0, 0x9d, _, NoModrm, { 0, 0, 0} },
+{"stc", 0, 0xf9, _, NoModrm, { 0, 0, 0} },
+{"std", 0, 0xfd, _, NoModrm, { 0, 0, 0} },
+{"sti", 0, 0xfb, _, NoModrm, { 0, 0, 0} },
+
+{"add", 2, 0x0, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"add", 2, 0x83, 0, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"add", 2, 0x4, _, W|NoModrm, { Imm, Acc, 0} },
+{"add", 2, 0x80, 0, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"inc", 1, 0x40, _, ShortForm, { WordReg, 0, 0} },
+{"inc", 1, 0xfe, 0, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"sub", 2, 0x28, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"sub", 2, 0x83, 5, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"sub", 2, 0x2c, _, W|NoModrm, { Imm, Acc, 0} },
+{"sub", 2, 0x80, 5, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"dec", 1, 0x48, _, ShortForm, { WordReg, 0, 0} },
+{"dec", 1, 0xfe, 1, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"sbb", 2, 0x18, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"sbb", 2, 0x83, 3, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"sbb", 2, 0x1c, _, W|NoModrm, { Imm, Acc, 0} },
+{"sbb", 2, 0x80, 3, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"cmp", 2, 0x38, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"cmp", 2, 0x83, 7, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"cmp", 2, 0x3c, _, W|NoModrm, { Imm, Acc, 0} },
+{"cmp", 2, 0x80, 7, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"test", 2, 0x84, _, W|Modrm, { Reg|Mem, Reg, 0} },
+{"test", 2, 0x84, _, W|Modrm, { Reg, Reg|Mem, 0} },
+{"test", 2, 0xa8, _, W|NoModrm, { Imm, Acc, 0} },
+{"test", 2, 0xf6, 0, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"and", 2, 0x20, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"and", 2, 0x83, 4, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"and", 2, 0x24, _, W|NoModrm, { Imm, Acc, 0} },
+{"and", 2, 0x80, 4, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"or", 2, 0x08, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"or", 2, 0x83, 1, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"or", 2, 0x0c, _, W|NoModrm, { Imm, Acc, 0} },
+{"or", 2, 0x80, 1, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"xor", 2, 0x30, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"xor", 2, 0x83, 6, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"xor", 2, 0x34, _, W|NoModrm, { Imm, Acc, 0} },
+{"xor", 2, 0x80, 6, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"adc", 2, 0x10, _, DW|Modrm, { Reg, Reg|Mem, 0} },
+{"adc", 2, 0x83, 2, Modrm, { Imm8S, WordReg|WordMem, 0} },
+{"adc", 2, 0x14, _, W|NoModrm, { Imm, Acc, 0} },
+{"adc", 2, 0x80, 2, W|Modrm, { Imm, Reg|Mem, 0} },
+
+{"neg", 1, 0xf6, 3, W|Modrm, { Reg|Mem, 0, 0} },
+{"not", 1, 0xf6, 2, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"aaa", 0, 0x37, _, NoModrm, { 0, 0, 0} },
+{"aas", 0, 0x3f, _, NoModrm, { 0, 0, 0} },
+{"daa", 0, 0x27, _, NoModrm, { 0, 0, 0} },
+{"das", 0, 0x2f, _, NoModrm, { 0, 0, 0} },
+{"aad", 0, 0xd50a, _, NoModrm, { 0, 0, 0} },
+{"aam", 0, 0xd40a, _, NoModrm, { 0, 0, 0} },
+
+/* conversion insns */
+/* conversion: intel naming */
+{"cbw", 0, 0x98, _, NoModrm|Data16, { 0, 0, 0} },
+{"cwd", 0, 0x99, _, NoModrm|Data16, { 0, 0, 0} },
+{"cwde", 0, 0x98, _, NoModrm|Data32, { 0, 0, 0} },
+{"cdq", 0, 0x99, _, NoModrm|Data32, { 0, 0, 0} },
+/* att naming */
+{"cbtw", 0, 0x98, _, NoModrm|Data16, { 0, 0, 0} },
+{"cwtl", 0, 0x98, _, NoModrm|Data32, { 0, 0, 0} },
+{"cwtd", 0, 0x99, _, NoModrm|Data16, { 0, 0, 0} },
+{"cltd", 0, 0x99, _, NoModrm|Data32, { 0, 0, 0} },
+
+/* Warning! the mul/imul (opcode 0xf6) must only have 1 operand! They are
+ expanding 64-bit multiplies, and *cannot* be selected to accomplish
+ 'imul %ebx, %eax' (opcode 0x0faf must be used in this case)
+ These multiplies can only be selected with single operand forms. */
+{"mul", 1, 0xf6, 4, W|Modrm, { Reg|Mem, 0, 0} },
+{"imul", 1, 0xf6, 5, W|Modrm, { Reg|Mem, 0, 0} },
+
+
+
+
+/* imulKludge here is needed to reverse the i.rm.reg & i.rm.regmem fields.
+ These instructions are exceptions: 'imul $2, %eax, %ecx' would put
+ '%eax' in the reg field and '%ecx' in the regmem field if we did not
+ switch them. */
+{"imul", 2, 0x0faf, _, Modrm|ReverseRegRegmem, { WordReg|Mem, WordReg, 0} },
+{"imul", 3, 0x6b, _, Modrm|ReverseRegRegmem, { Imm8S, WordReg|Mem, WordReg} },
+{"imul", 3, 0x69, _, Modrm|ReverseRegRegmem, { Imm16|Imm32, WordReg|Mem, WordReg} },
+/*
+ imul with 2 operands mimicks imul with 3 by puting register both
+ in i.rm.reg & i.rm.regmem fields
+*/
+{"imul", 2, 0x6b, _, Modrm|imulKludge, { Imm8S, WordReg, 0} },
+{"imul", 2, 0x69, _, Modrm|imulKludge, { Imm16|Imm32, WordReg, 0} },
+{"div", 1, 0xf6, 6, W|Modrm, { Reg|Mem, 0, 0} },
+{"div", 2, 0xf6, 6, W|Modrm, { Reg|Mem, Acc, 0} },
+{"idiv", 1, 0xf6, 7, W|Modrm, { Reg|Mem, 0, 0} },
+{"idiv", 2, 0xf6, 7, W|Modrm, { Reg|Mem, Acc, 0} },
+
+{"rol", 2, 0xd0, 0, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"rol", 2, 0xc0, 0, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"rol", 2, 0xd2, 0, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"rol", 1, 0xd0, 0, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"ror", 2, 0xd0, 1, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"ror", 2, 0xc0, 1, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"ror", 2, 0xd2, 1, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"ror", 1, 0xd0, 1, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"rcl", 2, 0xd0, 2, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"rcl", 2, 0xc0, 2, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"rcl", 2, 0xd2, 2, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"rcl", 1, 0xd0, 2, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"rcr", 2, 0xd0, 3, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"rcr", 2, 0xc0, 3, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"rcr", 2, 0xd2, 3, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"rcr", 1, 0xd0, 3, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"sal", 2, 0xd0, 4, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"sal", 2, 0xc0, 4, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"sal", 2, 0xd2, 4, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"sal", 1, 0xd0, 4, W|Modrm, { Reg|Mem, 0, 0} },
+{"shl", 2, 0xd0, 4, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"shl", 2, 0xc0, 4, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"shl", 2, 0xd2, 4, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"shl", 1, 0xd0, 4, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"shld", 3, 0x0fa4, _, Modrm, { Imm8, WordReg, WordReg|Mem} },
+{"shld", 3, 0x0fa5, _, Modrm, { ShiftCount, WordReg, WordReg|Mem} },
+{"shld", 2, 0x0fa5, _, Modrm, { WordReg, WordReg|Mem, 0} },
+
+{"shr", 2, 0xd0, 5, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"shr", 2, 0xc0, 5, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"shr", 2, 0xd2, 5, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"shr", 1, 0xd0, 5, W|Modrm, { Reg|Mem, 0, 0} },
+
+{"shrd", 3, 0x0fac, _, Modrm, { Imm8, WordReg, WordReg|Mem} },
+{"shrd", 3, 0x0fad, _, Modrm, { ShiftCount, WordReg, WordReg|Mem} },
+{"shrd", 2, 0x0fad, _, Modrm, { WordReg, WordReg|Mem, 0} },
+
+{"sar", 2, 0xd0, 7, W|Modrm, { Imm1, Reg|Mem, 0} },
+{"sar", 2, 0xc0, 7, W|Modrm, { Imm8, Reg|Mem, 0} },
+{"sar", 2, 0xd2, 7, W|Modrm, { ShiftCount, Reg|Mem, 0} },
+{"sar", 1, 0xd0, 7, W|Modrm, { Reg|Mem, 0, 0} },
+
+/* control transfer instructions */
+#define CALL_PC_RELATIVE 0xe8
+{"call", 1, 0xe8, _, JumpDword, { Disp32, 0, 0} },
+{"call", 1, 0xff, 2, Modrm|Data32, { Reg|Mem|JumpAbsolute, 0, 0} },
+{"callw", 1, 0xff, 2, Modrm|Data16, { Reg|Mem|JumpAbsolute, 0, 0} },
+#define CALL_FAR_IMMEDIATE 0x9a
+{"lcall", 2, 0x9a, _, JumpInterSegment, { Imm16, Abs32|Imm32, 0} },
+{"lcall", 1, 0xff, 3, Modrm|Data32, { Mem, 0, 0} },
+{"lcallw", 1, 0xff, 3, Modrm|Data16, { Mem, 0, 0} },
+
+#define JUMP_PC_RELATIVE 0xeb
+{"jmp", 1, 0xeb, _, Jump, { Disp, 0, 0} },
+{"jmp", 1, 0xff, 4, Modrm, { Reg32|Mem|JumpAbsolute, 0, 0} },
+#define JUMP_FAR_IMMEDIATE 0xea
+{"ljmp", 2, 0xea, _, JumpInterSegment, { Imm16, Imm32, 0} },
+{"ljmp", 1, 0xff, 5, Modrm|Data32, { Mem, 0, 0} },
+
+{"ret", 0, 0xc3, _, NoModrm|Data32, { 0, 0, 0} },
+{"ret", 1, 0xc2, _, NoModrm|Data32, { Imm16, 0, 0} },
+{"retw", 0, 0xc3, _, NoModrm|Data16, { 0, 0, 0} },
+{"retw", 1, 0xc2, _, NoModrm|Data16, { Imm16, 0, 0} },
+{"lret", 0, 0xcb, _, NoModrm|Data32, { 0, 0, 0} },
+{"lret", 1, 0xca, _, NoModrm|Data32, { Imm16, 0, 0} },
+{"lretw", 0, 0xcb, _, NoModrm|Data16, { 0, 0, 0} },
+{"lretw", 1, 0xca, _, NoModrm|Data16, { Imm16, 0, 0} },
+{"enter", 2, 0xc8, _, NoModrm|Data32, { Imm16, Imm8, 0} },
+{"leave", 0, 0xc9, _, NoModrm|Data32, { 0, 0, 0} },
+{"enterw", 2, 0xc8, _, NoModrm|Data16, { Imm16, Imm8, 0} },
+{"leavew", 0, 0xc9, _, NoModrm|Data16, { 0, 0, 0} },
+
+/* conditional jumps */
+{"jo", 1, 0x70, _, Jump, { Disp, 0, 0} },
+
+{"jno", 1, 0x71, _, Jump, { Disp, 0, 0} },
+
+{"jb", 1, 0x72, _, Jump, { Disp, 0, 0} },
+{"jc", 1, 0x72, _, Jump, { Disp, 0, 0} },
+{"jnae", 1, 0x72, _, Jump, { Disp, 0, 0} },
+
+{"jnb", 1, 0x73, _, Jump, { Disp, 0, 0} },
+{"jnc", 1, 0x73, _, Jump, { Disp, 0, 0} },
+{"jae", 1, 0x73, _, Jump, { Disp, 0, 0} },
+
+{"je", 1, 0x74, _, Jump, { Disp, 0, 0} },
+{"jz", 1, 0x74, _, Jump, { Disp, 0, 0} },
+
+{"jne", 1, 0x75, _, Jump, { Disp, 0, 0} },
+{"jnz", 1, 0x75, _, Jump, { Disp, 0, 0} },
+
+{"jbe", 1, 0x76, _, Jump, { Disp, 0, 0} },
+{"jna", 1, 0x76, _, Jump, { Disp, 0, 0} },
+
+{"jnbe", 1, 0x77, _, Jump, { Disp, 0, 0} },
+{"ja", 1, 0x77, _, Jump, { Disp, 0, 0} },
+
+{"js", 1, 0x78, _, Jump, { Disp, 0, 0} },
+
+{"jns", 1, 0x79, _, Jump, { Disp, 0, 0} },
+
+{"jp", 1, 0x7a, _, Jump, { Disp, 0, 0} },
+{"jpe", 1, 0x7a, _, Jump, { Disp, 0, 0} },
+
+{"jnp", 1, 0x7b, _, Jump, { Disp, 0, 0} },
+{"jpo", 1, 0x7b, _, Jump, { Disp, 0, 0} },
+
+{"jl", 1, 0x7c, _, Jump, { Disp, 0, 0} },
+{"jnge", 1, 0x7c, _, Jump, { Disp, 0, 0} },
+
+{"jnl", 1, 0x7d, _, Jump, { Disp, 0, 0} },
+{"jge", 1, 0x7d, _, Jump, { Disp, 0, 0} },
+
+{"jle", 1, 0x7e, _, Jump, { Disp, 0, 0} },
+{"jng", 1, 0x7e, _, Jump, { Disp, 0, 0} },
+
+{"jnle", 1, 0x7f, _, Jump, { Disp, 0, 0} },
+{"jg", 1, 0x7f, _, Jump, { Disp, 0, 0} },
+
+#if 0 /* XXX where are these macros used?
+ To get them working again, they need to take
+ an entire template as the parameter,
+ and check for Data16/Data32 flags. */
+/* these turn into pseudo operations when disp is larger than 8 bits */
+#define IS_JUMP_ON_CX_ZERO(o) \
+ (o == 0x66e3)
+#define IS_JUMP_ON_ECX_ZERO(o) \
+ (o == 0xe3)
+#endif
+
+{"jcxz", 1, 0xe3, _, JumpByte|Data16, { Disp, 0, 0} },
+{"jecxz", 1, 0xe3, _, JumpByte|Data32, { Disp, 0, 0} },
+
+#define IS_LOOP_ECX_TIMES(o) \
+ (o == 0xe2 || o == 0xe1 || o == 0xe0)
+
+{"loop", 1, 0xe2, _, JumpByte, { Disp, 0, 0} },
+
+{"loopz", 1, 0xe1, _, JumpByte, { Disp, 0, 0} },
+{"loope", 1, 0xe1, _, JumpByte, { Disp, 0, 0} },
+
+{"loopnz", 1, 0xe0, _, JumpByte, { Disp, 0, 0} },
+{"loopne", 1, 0xe0, _, JumpByte, { Disp, 0, 0} },
+
+/* set byte on flag instructions */
+{"seto", 1, 0x0f90, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setno", 1, 0x0f91, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setb", 1, 0x0f92, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setc", 1, 0x0f92, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setnae", 1, 0x0f92, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setnb", 1, 0x0f93, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setnc", 1, 0x0f93, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setae", 1, 0x0f93, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"sete", 1, 0x0f94, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setz", 1, 0x0f94, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setne", 1, 0x0f95, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setnz", 1, 0x0f95, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setbe", 1, 0x0f96, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setna", 1, 0x0f96, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setnbe", 1, 0x0f97, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"seta", 1, 0x0f97, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"sets", 1, 0x0f98, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setns", 1, 0x0f99, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setp", 1, 0x0f9a, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setpe", 1, 0x0f9a, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setnp", 1, 0x0f9b, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setpo", 1, 0x0f9b, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setl", 1, 0x0f9c, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setnge", 1, 0x0f9c, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setnl", 1, 0x0f9d, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setge", 1, 0x0f9d, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setle", 1, 0x0f9e, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setng", 1, 0x0f9e, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+{"setnle", 1, 0x0f9f, 0, Modrm, { Reg8|Mem, 0, 0} },
+{"setg", 1, 0x0f9f, 0, Modrm, { Reg8|Mem, 0, 0} },
+
+#define IS_STRING_INSTRUCTION(o) \
+ ((o) == 0xa6 || (o) == 0x6c || (o) == 0x6e || (o) == 0x6e || \
+ (o) == 0xac || (o) == 0xa4 || (o) == 0xae || (o) == 0xaa || \
+ (o) == 0xd7)
+
+/* string manipulation */
+{"cmps", 0, 0xa6, _, W|NoModrm, { 0, 0, 0} },
+{"scmp", 0, 0xa6, _, W|NoModrm, { 0, 0, 0} },
+{"ins", 0, 0x6c, _, W|NoModrm, { 0, 0, 0} },
+{"outs", 0, 0x6e, _, W|NoModrm, { 0, 0, 0} },
+{"lods", 0, 0xac, _, W|NoModrm, { 0, 0, 0} },
+{"slod", 0, 0xac, _, W|NoModrm, { 0, 0, 0} },
+{"movs", 0, 0xa4, _, W|NoModrm, { 0, 0, 0} },
+{"smov", 0, 0xa4, _, W|NoModrm, { 0, 0, 0} },
+{"scas", 0, 0xae, _, W|NoModrm, { 0, 0, 0} },
+{"ssca", 0, 0xae, _, W|NoModrm, { 0, 0, 0} },
+{"stos", 0, 0xaa, _, W|NoModrm, { 0, 0, 0} },
+{"ssto", 0, 0xaa, _, W|NoModrm, { 0, 0, 0} },
+{"xlat", 0, 0xd7, _, NoModrm, { 0, 0, 0} },
+
+/* bit manipulation */
+{"bsf", 2, 0x0fbc, _, Modrm|ReverseRegRegmem, { Reg|Mem, Reg, 0} },
+{"bsr", 2, 0x0fbd, _, Modrm|ReverseRegRegmem, { Reg|Mem, Reg, 0} },
+{"bt", 2, 0x0fa3, _, Modrm, { Reg, Reg|Mem, 0} },
+{"bt", 2, 0x0fba, 4, Modrm, { Imm8, Reg|Mem, 0} },
+{"btc", 2, 0x0fbb, _, Modrm, { Reg, Reg|Mem, 0} },
+{"btc", 2, 0x0fba, 7, Modrm, { Imm8, Reg|Mem, 0} },
+{"btr", 2, 0x0fb3, _, Modrm, { Reg, Reg|Mem, 0} },
+{"btr", 2, 0x0fba, 6, Modrm, { Imm8, Reg|Mem, 0} },
+{"bts", 2, 0x0fab, _, Modrm, { Reg, Reg|Mem, 0} },
+{"bts", 2, 0x0fba, 5, Modrm, { Imm8, Reg|Mem, 0} },
+
+/* interrupts & op. sys insns */
+/* See gas/config/tc-i386.c for conversion of 'int $3' into the special
+ int 3 insn. */
+#define INT_OPCODE 0xcd
+#define INT3_OPCODE 0xcc
+{"int", 1, 0xcd, _, NoModrm, { Imm8, 0, 0} },
+{"int3", 0, 0xcc, _, NoModrm, { 0, 0, 0} },
+{"into", 0, 0xce, _, NoModrm, { 0, 0, 0} },
+{"iret", 0, 0xcf, _, NoModrm|Data32, { 0, 0, 0} },
+{"iretw", 0, 0xcf, _, NoModrm|Data16, { 0, 0, 0} },
+/* i386sl, i486sl, later 486, and Pentium */
+{"rsm", 0, 0x0faa, _, NoModrm,{ 0, 0, 0} },
+
+{"boundl", 2, 0x62, _, Modrm|Data32, { Reg32, Mem, 0} },
+{"boundw", 2, 0x62, _, Modrm|Data16, { Reg16, Mem, 0} },
+
+{"hlt", 0, 0xf4, _, NoModrm, { 0, 0, 0} },
+{"wait", 0, 0x9b, _, NoModrm, { 0, 0, 0} },
+/* nop is actually 'xchgl %eax, %eax' */
+{"nop", 0, 0x90, _, NoModrm, { 0, 0, 0} },
+
+/* protection control */
+{"arpl", 2, 0x63, _, Modrm, { Reg16, Reg16|Mem, 0} },
+{"lar", 2, 0x0f02, _, Modrm|ReverseRegRegmem, { WordReg|Mem, WordReg, 0} },
+{"lgdt", 1, 0x0f01, 2, Modrm, { Mem, 0, 0} },
+{"lidt", 1, 0x0f01, 3, Modrm, { Mem, 0, 0} },
+{"lldt", 1, 0x0f00, 2, Modrm, { WordReg|Mem, 0, 0} },
+{"lmsw", 1, 0x0f01, 6, Modrm, { WordReg|Mem, 0, 0} },
+{"lsl", 2, 0x0f03, _, Modrm|ReverseRegRegmem, { WordReg|Mem, WordReg, 0} },
+{"ltr", 1, 0x0f00, 3, Modrm, { WordReg|Mem, 0, 0} },
+
+{"sgdt", 1, 0x0f01, 0, Modrm, { Mem, 0, 0} },
+{"sidt", 1, 0x0f01, 1, Modrm, { Mem, 0, 0} },
+{"sldt", 1, 0x0f00, 0, Modrm, { WordReg|Mem, 0, 0} },
+{"smsw", 1, 0x0f01, 4, Modrm, { WordReg|Mem, 0, 0} },
+{"str", 1, 0x0f00, 1, Modrm, { Reg16|Mem, 0, 0} },
+
+{"verr", 1, 0x0f00, 4, Modrm, { WordReg|Mem, 0, 0} },
+{"verw", 1, 0x0f00, 5, Modrm, { WordReg|Mem, 0, 0} },
+
+/* floating point instructions */
+
+/* load */
+{"fld", 1, 0xd9c0, _, ShortForm, { FloatReg, 0, 0} }, /* register */
+{"flds", 1, 0xd9, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem float */
+{"fldl", 1, 0xdd, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem double */
+{"fldl", 1, 0xd9c0, _, ShortForm, { FloatReg, 0, 0} }, /* register */
+{"fild", 1, 0xdf, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem word (16) */
+{"fildl", 1, 0xdb, 0, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem dword (32) */
+{"fildq",1, 0xdf, 5, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem qword (64) */
+{"fildll",1, 0xdf, 5, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem qword (64) */
+{"fldt", 1, 0xdb, 5, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem efloat */
+{"fbld", 1, 0xdf, 4, Modrm, { Mem, 0, 0} }, /* %st0 <-- mem bcd */
+
+/* store (no pop) */
+{"fst", 1, 0xddd0, _, ShortForm, { FloatReg, 0, 0} }, /* register */
+{"fsts", 1, 0xd9, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem float */
+{"fstl", 1, 0xdd, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem double */
+{"fstl", 1, 0xddd0, _, ShortForm, { FloatReg, 0, 0} }, /* register */
+{"fist", 1, 0xdf, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem word (16) */
+{"fistl", 1, 0xdb, 2, Modrm, { Mem, 0, 0} }, /* %st0 --> mem dword (32) */
+
+/* store (with pop) */
+{"fstp", 1, 0xddd8, _, ShortForm, { FloatReg, 0, 0} }, /* register */
+{"fstps", 1, 0xd9, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem float */
+{"fstpl", 1, 0xdd, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem double */
+{"fstpl", 1, 0xddd8, _, ShortForm, { FloatReg, 0, 0} }, /* register */
+{"fistp", 1, 0xdf, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem word (16) */
+{"fistpl",1, 0xdb, 3, Modrm, { Mem, 0, 0} }, /* %st0 --> mem dword (32) */
+{"fistpq",1, 0xdf, 7, Modrm, { Mem, 0, 0} }, /* %st0 --> mem qword (64) */
+{"fistpll",1,0xdf, 7, Modrm, { Mem, 0, 0} }, /* %st0 --> mem qword (64) */
+{"fstpt", 1, 0xdb, 7, Modrm, { Mem, 0, 0} }, /* %st0 --> mem efloat */
+{"fbstp", 1, 0xdf, 6, Modrm, { Mem, 0, 0} }, /* %st0 --> mem bcd */
+
+/* exchange %st<n> with %st0 */
+{"fxch", 1, 0xd9c8, _, ShortForm, { FloatReg, 0, 0} },
+{"fxch", 0, 0xd9c9, _, NoModrm, { 0, 0, 0} }, /* alias for fxch %st, %st(1) */
+
+/* comparison (without pop) */
+{"fcom", 1, 0xd8d0, _, ShortForm, { FloatReg, 0, 0} },
+{"fcoms", 1, 0xd8, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem float */
+{"ficoml", 1, 0xda, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem word */
+{"fcoml", 1, 0xdc, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem double */
+{"fcoml", 1, 0xd8d0, _, ShortForm, { FloatReg, 0, 0} },
+{"ficoms", 1, 0xde, 2, Modrm, { Mem, 0, 0} }, /* compare %st0, mem dword */
+
+/* comparison (with pop) */
+{"fcomp", 1, 0xd8d8, _, ShortForm, { FloatReg, 0, 0} },
+{"fcomps", 1, 0xd8, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem float */
+{"ficompl", 1, 0xda, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem word */
+{"fcompl", 1, 0xdc, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem double */
+{"fcompl", 1, 0xd8d8, _, ShortForm, { FloatReg, 0, 0} },
+{"ficomps", 1, 0xde, 3, Modrm, { Mem, 0, 0} }, /* compare %st0, mem dword */
+{"fcompp", 0, 0xded9, _, NoModrm, { 0, 0, 0} }, /* compare %st0, %st1 & pop 2 */
+
+/* unordered comparison (with pop) */
+{"fucom", 1, 0xdde0, _, ShortForm, { FloatReg, 0, 0} },
+{"fucomp", 1, 0xdde8, _, ShortForm, { FloatReg, 0, 0} },
+{"fucompp", 0, 0xdae9, _, NoModrm, { 0, 0, 0} }, /* ucompare %st0, %st1 & pop twice */
+
+{"ftst", 0, 0xd9e4, _, NoModrm, { 0, 0, 0} }, /* test %st0 */
+{"fxam", 0, 0xd9e5, _, NoModrm, { 0, 0, 0} }, /* examine %st0 */
+
+/* load constants into %st0 */
+{"fld1", 0, 0xd9e8, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- 1.0 */
+{"fldl2t", 0, 0xd9e9, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- log2(10) */
+{"fldl2e", 0, 0xd9ea, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- log2(e) */
+{"fldpi", 0, 0xd9eb, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- pi */
+{"fldlg2", 0, 0xd9ec, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- log10(2) */
+{"fldln2", 0, 0xd9ed, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- ln(2) */
+{"fldz", 0, 0xd9ee, _, NoModrm, { 0, 0, 0} }, /* %st0 <-- 0.0 */
+
+/* arithmetic */
+
+/* add */
+{"fadd", 1, 0xd8c0, _, ShortForm, { FloatReg, 0, 0} },
+{"fadd", 2, 0xd8c0, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} },
+{"fadd", 0, 0xdcc1, _, NoModrm, { 0, 0, 0} }, /* alias for fadd %st, %st(1) */
+{"faddp", 1, 0xdac0, _, ShortForm, { FloatReg, 0, 0} },
+{"faddp", 2, 0xdac0, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} },
+{"faddp", 0, 0xdec1, _, NoModrm, { 0, 0, 0} }, /* alias for faddp %st, %st(1) */
+{"fadds", 1, 0xd8, 0, Modrm, { Mem, 0, 0} },
+{"fiaddl", 1, 0xda, 0, Modrm, { Mem, 0, 0} },
+{"faddl", 1, 0xdc, 0, Modrm, { Mem, 0, 0} },
+{"fiadds", 1, 0xde, 0, Modrm, { Mem, 0, 0} },
+
+/* sub */
+/* Note: intel has decided that certain of these operations are reversed
+ in assembler syntax. */
+{"fsub", 1, 0xd8e0, _, ShortForm, { FloatReg, 0, 0} },
+{"fsub", 2, 0xd8e0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fsub", 2, 0xdce8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fsub", 2, 0xdce0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fsub", 0, 0xdce1, _, NoModrm, { 0, 0, 0} },
+{"fsubp", 1, 0xdae0, _, ShortForm, { FloatReg, 0, 0} },
+{"fsubp", 2, 0xdae0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fsubp", 2, 0xdee8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fsubp", 2, 0xdee0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fsubp", 0, 0xdee1, _, NoModrm, { 0, 0, 0} },
+{"fsubs", 1, 0xd8, 4, Modrm, { Mem, 0, 0} },
+{"fisubl", 1, 0xda, 4, Modrm, { Mem, 0, 0} },
+{"fsubl", 1, 0xdc, 4, Modrm, { Mem, 0, 0} },
+{"fisubs", 1, 0xde, 4, Modrm, { Mem, 0, 0} },
+
+/* sub reverse */
+{"fsubr", 1, 0xd8e8, _, ShortForm, { FloatReg, 0, 0} },
+{"fsubr", 2, 0xd8e8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fsubr", 2, 0xdce0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fsubr", 2, 0xdce8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fsubr", 0, 0xdce9, _, NoModrm, { 0, 0, 0} },
+{"fsubrp", 1, 0xdae8, _, ShortForm, { FloatReg, 0, 0} },
+{"fsubrp", 2, 0xdae8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fsubrp", 2, 0xdee0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fsubrp", 2, 0xdee8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fsubrp", 0, 0xdee9, _, NoModrm, { 0, 0, 0} },
+{"fsubrs", 1, 0xd8, 5, Modrm, { Mem, 0, 0} },
+{"fisubrl", 1, 0xda, 5, Modrm, { Mem, 0, 0} },
+{"fsubrl", 1, 0xdc, 5, Modrm, { Mem, 0, 0} },
+{"fisubrs", 1, 0xde, 5, Modrm, { Mem, 0, 0} },
+
+/* mul */
+{"fmul", 1, 0xd8c8, _, ShortForm, { FloatReg, 0, 0} },
+{"fmul", 2, 0xd8c8, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} },
+{"fmul", 0, 0xdcc9, _, NoModrm, { 0, 0, 0} },
+{"fmulp", 1, 0xdac8, _, ShortForm, { FloatReg, 0, 0} },
+{"fmulp", 2, 0xdac8, _, ShortForm|FloatD, { FloatReg, FloatAcc, 0} },
+{"fmulp", 0, 0xdec9, _, NoModrm, { 0, 0, 0} },
+{"fmuls", 1, 0xd8, 1, Modrm, { Mem, 0, 0} },
+{"fimull", 1, 0xda, 1, Modrm, { Mem, 0, 0} },
+{"fmull", 1, 0xdc, 1, Modrm, { Mem, 0, 0} },
+{"fimuls", 1, 0xde, 1, Modrm, { Mem, 0, 0} },
+
+/* div */
+/* Note: intel has decided that certain of these operations are reversed
+ in assembler syntax. */
+{"fdiv", 1, 0xd8f0, _, ShortForm, { FloatReg, 0, 0} },
+{"fdiv", 2, 0xd8f0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fdiv", 2, 0xdcf8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fdiv", 2, 0xdcf0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fdiv", 0, 0xdcf1, _, NoModrm, { 0, 0, 0} },
+{"fdivp", 1, 0xdaf0, _, ShortForm, { FloatReg, 0, 0} },
+{"fdivp", 2, 0xdaf0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fdivp", 2, 0xdef8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fdivp", 2, 0xdef0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fdivp", 0, 0xdef1, _, NoModrm, { 0, 0, 0} },
+{"fdivs", 1, 0xd8, 6, Modrm, { Mem, 0, 0} },
+{"fidivl", 1, 0xda, 6, Modrm, { Mem, 0, 0} },
+{"fdivl", 1, 0xdc, 6, Modrm, { Mem, 0, 0} },
+{"fidivs", 1, 0xde, 6, Modrm, { Mem, 0, 0} },
+
+/* div reverse */
+{"fdivr", 1, 0xd8f8, _, ShortForm, { FloatReg, 0, 0} },
+{"fdivr", 2, 0xd8f8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fdivr", 2, 0xdcf0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fdivr", 2, 0xdcf8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fdivr", 0, 0xdcf9, _, NoModrm, { 0, 0, 0} },
+{"fdivrp", 1, 0xdaf8, _, ShortForm, { FloatReg, 0, 0} },
+{"fdivrp", 2, 0xdaf8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+#ifdef NON_BROKEN_OPCODES
+{"fdivrp", 2, 0xdef0, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#else
+{"fdivrp", 2, 0xdef8, _, ShortForm, { FloatAcc, FloatReg, 0} },
+#endif
+{"fdivrp", 0, 0xdef9, _, NoModrm, { 0, 0, 0} },
+{"fdivrs", 1, 0xd8, 7, Modrm, { Mem, 0, 0} },
+{"fidivrl", 1, 0xda, 7, Modrm, { Mem, 0, 0} },
+{"fdivrl", 1, 0xdc, 7, Modrm, { Mem, 0, 0} },
+{"fidivrs", 1, 0xde, 7, Modrm, { Mem, 0, 0} },
+
+{"f2xm1", 0, 0xd9f0, _, NoModrm, { 0, 0, 0} },
+{"fyl2x", 0, 0xd9f1, _, NoModrm, { 0, 0, 0} },
+{"fptan", 0, 0xd9f2, _, NoModrm, { 0, 0, 0} },
+{"fpatan", 0, 0xd9f3, _, NoModrm, { 0, 0, 0} },
+{"fxtract", 0, 0xd9f4, _, NoModrm, { 0, 0, 0} },
+{"fprem1", 0, 0xd9f5, _, NoModrm, { 0, 0, 0} },
+{"fdecstp", 0, 0xd9f6, _, NoModrm, { 0, 0, 0} },
+{"fincstp", 0, 0xd9f7, _, NoModrm, { 0, 0, 0} },
+{"fprem", 0, 0xd9f8, _, NoModrm, { 0, 0, 0} },
+{"fyl2xp1", 0, 0xd9f9, _, NoModrm, { 0, 0, 0} },
+{"fsqrt", 0, 0xd9fa, _, NoModrm, { 0, 0, 0} },
+{"fsincos", 0, 0xd9fb, _, NoModrm, { 0, 0, 0} },
+{"frndint", 0, 0xd9fc, _, NoModrm, { 0, 0, 0} },
+{"fscale", 0, 0xd9fd, _, NoModrm, { 0, 0, 0} },
+{"fsin", 0, 0xd9fe, _, NoModrm, { 0, 0, 0} },
+{"fcos", 0, 0xd9ff, _, NoModrm, { 0, 0, 0} },
+
+{"fchs", 0, 0xd9e0, _, NoModrm, { 0, 0, 0} },
+{"fabs", 0, 0xd9e1, _, NoModrm, { 0, 0, 0} },
+
+/* processor control */
+{"fninit", 0, 0xdbe3, _, NoModrm, { 0, 0, 0} },
+{"finit", 0, 0x9bdbe3, _, NoModrm, { 0, 0, 0} },
+{"fldcw", 1, 0xd9, 5, Modrm, { Mem, 0, 0} },
+{"fnstcw", 1, 0xd9, 7, Modrm, { Mem, 0, 0} },
+{"fstcw", 1, 0x9bd9, 7, Modrm, { Mem, 0, 0} },
+{"fnstsw", 1, 0xdfe0, _, NoModrm, { Acc, 0, 0} },
+{"fnstsw", 1, 0xdd, 7, Modrm, { Mem, 0, 0} },
+{"fnstsw", 0, 0xdfe0, _, NoModrm, { 0, 0, 0} },
+{"fstsw", 1, 0x9bdfe0, _, NoModrm, { Acc, 0, 0} },
+{"fstsw", 1, 0x9bdd, 7, Modrm, { Mem, 0, 0} },
+{"fstsw", 0, 0x9bdfe0, _, NoModrm, { 0, 0, 0} },
+{"fnclex", 0, 0xdbe2, _, NoModrm, { 0, 0, 0} },
+{"fclex", 0, 0x9bdbe2, _, NoModrm, { 0, 0, 0} },
+/*
+ We ignore the short format (287) versions of fstenv/fldenv & fsave/frstor
+ instructions; i'm not sure how to add them or how they are different.
+ My 386/387 book offers no details about this.
+*/
+{"fnstenv", 1, 0xd9, 6, Modrm, { Mem, 0, 0} },
+{"fstenv", 1, 0x9bd9, 6, Modrm, { Mem, 0, 0} },
+{"fldenv", 1, 0xd9, 4, Modrm, { Mem, 0, 0} },
+{"fnsave", 1, 0xdd, 6, Modrm, { Mem, 0, 0} },
+{"fsave", 1, 0x9bdd, 6, Modrm, { Mem, 0, 0} },
+{"frstor", 1, 0xdd, 4, Modrm, { Mem, 0, 0} },
+
+{"ffree", 1, 0xddc0, _, ShortForm, { FloatReg, 0, 0} },
+{"fnop", 0, 0xd9d0, _, NoModrm, { 0, 0, 0} },
+{"fwait", 0, 0x9b, _, NoModrm, { 0, 0, 0} },
+
+/*
+ opcode prefixes; we allow them as seperate insns too
+ (see prefix table below)
+*/
+{"aword", 0, 0x67, _, NoModrm, { 0, 0, 0} },
+{"addr16", 0, 0x67, _, NoModrm, { 0, 0, 0} },
+{"word", 0, 0x66, _, NoModrm, { 0, 0, 0} },
+{"data16", 0, 0x66, _, NoModrm, { 0, 0, 0} },
+{"lock", 0, 0xf0, _, NoModrm, { 0, 0, 0} },
+{"cs", 0, 0x2e, _, NoModrm, { 0, 0, 0} },
+{"ds", 0, 0x3e, _, NoModrm, { 0, 0, 0} },
+{"es", 0, 0x26, _, NoModrm, { 0, 0, 0} },
+{"fs", 0, 0x64, _, NoModrm, { 0, 0, 0} },
+{"gs", 0, 0x65, _, NoModrm, { 0, 0, 0} },
+{"ss", 0, 0x36, _, NoModrm, { 0, 0, 0} },
+{"rep", 0, 0xf3, _, NoModrm, { 0, 0, 0} },
+{"repe", 0, 0xf3, _, NoModrm, { 0, 0, 0} },
+{"repz", 0, 0xf3, _, NoModrm, { 0, 0, 0} },
+{"repne", 0, 0xf2, _, NoModrm, { 0, 0, 0} },
+{"repnz", 0, 0xf2, _, NoModrm, { 0, 0, 0} },
+
+/* 486 extensions */
+
+{"bswap", 1, 0x0fc8, _, ShortForm, { Reg32,0,0 } },
+{"xadd", 2, 0x0fc0, _, DW|Modrm, { Reg, Reg|Mem, 0 } },
+{"cmpxchg", 2, 0x0fb0, _, DW|Modrm, { Reg, Reg|Mem, 0 } },
+{"invd", 0, 0x0f08, _, NoModrm, { 0, 0, 0} },
+{"wbinvd", 0, 0x0f09, _, NoModrm, { 0, 0, 0} },
+{"invlpg", 1, 0x0f01, 7, Modrm, { Mem, 0, 0} },
+
+/* 586 and late 486 extensions */
+{"cpuid", 0, 0x0fa2, _, NoModrm, { 0, 0, 0} },
+
+/* Pentium extensions */
+{"wrmsr", 0, 0x0f30, _, NoModrm, { 0, 0, 0} },
+{"rdtsc", 0, 0x0f31, _, NoModrm, { 0, 0, 0} },
+{"rdmsr", 0, 0x0f32, _, NoModrm, { 0, 0, 0} },
+{"cmpxchg8b", 1, 0x0fc7, 1, Modrm, { Mem, 0, 0} },
+
+/* Pentium Pro extensions */
+{"rdpmc", 0, 0x0f33, _, NoModrm, { 0, 0, 0} },
+
+{"cmovo", 2, 0x0f40, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovno", 2, 0x0f41, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovb", 2, 0x0f42, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovae", 2, 0x0f43, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmove", 2, 0x0f44, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovne", 2, 0x0f45, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovbe", 2, 0x0f46, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmova", 2, 0x0f47, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovs", 2, 0x0f48, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovns", 2, 0x0f49, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovp", 2, 0x0f4a, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovnp", 2, 0x0f4b, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovl", 2, 0x0f4c, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovge", 2, 0x0f4d, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovle", 2, 0x0f4e, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+{"cmovg", 2, 0x0f4f, _, W|Modrm|ReverseRegRegmem, { WordReg|WordMem, WordReg, 0} },
+
+{"fcmovb", 2, 0xdac0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcmove", 2, 0xdac8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcmovbe",2, 0xdad0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcmovu", 2, 0xdad8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcmovnb", 2, 0xdbc0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcmovne", 2, 0xdbc8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcmovnbe",2, 0xdbd0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcmovnu", 2, 0xdbd8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+
+{"fcomi", 2, 0xdbf0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fucomi", 2, 0xdbe8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fcomip", 2, 0xdff0, _, ShortForm, { FloatReg, FloatAcc, 0} },
+{"fucomip",2, 0xdfe8, _, ShortForm, { FloatReg, FloatAcc, 0} },
+
+{"", 0, 0, 0, 0, { 0, 0, 0} } /* sentinel */
+};
+#undef _
+
+static const template *const i386_optab_end
+ = i386_optab + sizeof (i386_optab)/sizeof(i386_optab[0]);
+
+/* 386 register table */
+
+static const reg_entry i386_regtab[] = {
+ /* 8 bit regs */
+ {"al", Reg8|Acc, 0}, {"cl", Reg8|ShiftCount, 1}, {"dl", Reg8, 2},
+ {"bl", Reg8, 3},
+ {"ah", Reg8, 4}, {"ch", Reg8, 5}, {"dh", Reg8, 6}, {"bh", Reg8, 7},
+ /* 16 bit regs */
+ {"ax", Reg16|Acc, 0}, {"cx", Reg16, 1}, {"dx", Reg16|InOutPortReg, 2}, {"bx", Reg16, 3},
+ {"sp", Reg16, 4}, {"bp", Reg16, 5}, {"si", Reg16, 6}, {"di", Reg16, 7},
+ /* 32 bit regs */
+ {"eax", Reg32|Acc, 0}, {"ecx", Reg32, 1}, {"edx", Reg32, 2}, {"ebx", Reg32, 3},
+ {"esp", Reg32, 4}, {"ebp", Reg32, 5}, {"esi", Reg32, 6}, {"edi", Reg32, 7},
+ /* segment registers */
+ {"es", SReg2, 0}, {"cs", SReg2, 1}, {"ss", SReg2, 2},
+ {"ds", SReg2, 3}, {"fs", SReg3, 4}, {"gs", SReg3, 5},
+ /* control registers */
+ {"cr0", Control, 0}, {"cr2", Control, 2}, {"cr3", Control, 3},
+ {"cr4", Control, 4},
+ /* debug registers */
+ {"db0", Debug, 0}, {"db1", Debug, 1}, {"db2", Debug, 2},
+ {"db3", Debug, 3}, {"db6", Debug, 6}, {"db7", Debug, 7},
+ {"dr0", Debug, 0}, {"dr1", Debug, 1}, {"dr2", Debug, 2},
+ {"dr3", Debug, 3}, {"dr6", Debug, 6}, {"dr7", Debug, 7},
+ /* test registers */
+ {"tr3", Test, 3}, {"tr4", Test, 4}, {"tr5", Test, 5},
+ {"tr6", Test, 6}, {"tr7", Test, 7},
+ /* float registers */
+ {"st(0)", FloatReg|FloatAcc, 0},
+ {"st", FloatReg|FloatAcc, 0},
+ {"st(1)", FloatReg, 1}, {"st(2)", FloatReg, 2},
+ {"st(3)", FloatReg, 3}, {"st(4)", FloatReg, 4}, {"st(5)", FloatReg, 5},
+ {"st(6)", FloatReg, 6}, {"st(7)", FloatReg, 7}
+};
+
+#define MAX_REG_NAME_SIZE 8 /* for parsing register names from input */
+
+static const reg_entry *const i386_regtab_end
+ = i386_regtab + sizeof(i386_regtab)/sizeof(i386_regtab[0]);
+
+/* segment stuff */
+static const seg_entry cs = { "cs", 0x2e };
+static const seg_entry ds = { "ds", 0x3e };
+static const seg_entry ss = { "ss", 0x36 };
+static const seg_entry es = { "es", 0x26 };
+static const seg_entry fs = { "fs", 0x64 };
+static const seg_entry gs = { "gs", 0x65 };
+static const seg_entry null = { "", 0x0 };
+
+/*
+ This table is used to store the default segment register implied by all
+ possible memory addressing modes.
+ It is indexed by the mode & modrm entries of the modrm byte as follows:
+ index = (mode<<3) | modrm;
+*/
+static const seg_entry *const one_byte_segment_defaults[] = {
+ /* mode 0 */
+ &ds, &ds, &ds, &ds, &null, &ds, &ds, &ds,
+ /* mode 1 */
+ &ds, &ds, &ds, &ds, &null, &ss, &ds, &ds,
+ /* mode 2 */
+ &ds, &ds, &ds, &ds, &null, &ss, &ds, &ds,
+ /* mode 3 --- not a memory reference; never referenced */
+};
+
+static const seg_entry *const two_byte_segment_defaults[] = {
+ /* mode 0 */
+ &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
+ /* mode 1 */
+ &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
+ /* mode 2 */
+ &ds, &ds, &ds, &ds, &ss, &ds, &ds, &ds,
+ /* mode 3 --- not a memory reference; never referenced */
+};
+
+static const prefix_entry i386_prefixtab[] = {
+#define ADDR_PREFIX_OPCODE 0x67
+ { "addr16", 0x67 }, /* address size prefix ==> 16bit addressing
+ * (How is this useful?) */
+#define WORD_PREFIX_OPCODE 0x66
+ { "data16", 0x66 }, /* operand size prefix */
+ { "lock", 0xf0 }, /* bus lock prefix */
+ { "wait", 0x9b }, /* wait for coprocessor */
+ { "cs", 0x2e }, { "ds", 0x3e }, /* segment overrides ... */
+ { "es", 0x26 }, { "fs", 0x64 },
+ { "gs", 0x65 }, { "ss", 0x36 },
+/* REPE & REPNE used to detect rep/repne with a non-string instruction */
+#define REPNE 0xf2
+#define REPE 0xf3
+ { "rep", 0xf3 }, /* repeat string instructions */
+ { "repe", 0xf3 }, { "repz", 0xf3 },
+ { "repne", 0xf2 }, { "repnz", 0xf2 }
+};
+
+static const prefix_entry *const i386_prefixtab_end
+ = i386_prefixtab + sizeof(i386_prefixtab)/sizeof(i386_prefixtab[0]);
+
+/* end of i386-opcode.h */
diff --git a/contrib/gdb/include/opcode/i860.h b/contrib/gdb/include/opcode/i860.h
new file mode 100644
index 0000000..b6ebd25
--- /dev/null
+++ b/contrib/gdb/include/opcode/i860.h
@@ -0,0 +1,491 @@
+/* Table of opcodes for the i860.
+ Copyright (C) 1989 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler, and GDB, the GNU disassembler.
+
+GAS/GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if !defined(__STDC__) && !defined(const)
+#define const
+#endif
+
+/*
+ * Structure of an opcode table entry.
+ */
+struct i860_opcode
+{
+ const char *name;
+ unsigned long match; /* Bits that must be set. */
+ unsigned long lose; /* Bits that must not be set. */
+ const char *args;
+ /* Nonzero if this is a possible expand-instruction. */
+ char expand;
+};
+
+enum expand_type
+{
+ E_MOV = 1, E_ADDR, E_U32, E_AND, E_S32, E_DELAY
+};
+
+/*
+ All i860 opcodes are 32 bits, except for the pseudoinstructions
+ and the operations utilizing a 32-bit address expression, an
+ unsigned 32-bit constant, or a signed 32-bit constant.
+ These opcodes are expanded into a two-instruction sequence for
+ any situation where the immediate operand does not fit in 32 bits.
+ In the case of the add and subtract operations the expansion is
+ to a three-instruction sequence (ex: orh, or, adds). In cases
+ where the address is to be relocated, the instruction is
+ expanded to handle the worse case, this could be optimized at
+ the final link if the actual address were known.
+
+ The pseudoinstructions are: mov, fmov, pmov, nop, and fnop.
+ These instructions are implemented as a one or two instruction
+ sequence of other operations.
+
+ The match component is a mask saying which bits must match a
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing one character
+ for each operand of the instruction.
+
+Kinds of operands:
+ # Number used by optimizer. It is ignored.
+ 1 src1 integer register.
+ 2 src2 integer register.
+ d dest register.
+ c ctrlreg control register.
+ i 16 bit immediate.
+ I 16 bit immediate, aligned.
+ 5 5 bit immediate.
+ l lbroff 26 bit PC relative immediate.
+ r sbroff 16 bit PC relative immediate.
+ s split 16 bit immediate.
+ S split 16 bit immediate, aligned.
+ e src1 floating point register.
+ f src2 floating point register.
+ g dest floating point register.
+
+*/
+
+/* The order of the opcodes in this table is significant:
+
+ * The assembler requires that all instances of the same mnemonic must be
+ consecutive. If they aren't, the assembler will bomb at runtime.
+
+ * The disassembler should not care about the order of the opcodes. */
+
+static struct i860_opcode i860_opcodes[] =
+{
+
+/* REG-Format Instructions */
+{ "ld.c", 0x30000000, 0xcc000000, "c,d", 0 }, /* ld.c csrc2,idest */
+{ "ld.b", 0x00000000, 0xfc000000, "1(2),d", 0 }, /* ld.b isrc1(isrc2),idest */
+{ "ld.b", 0x04000000, 0xf8000000, "I(2),d", E_ADDR }, /* ld.b #const(isrc2),idest */
+{ "ld.s", 0x10000000, 0xec000001, "1(2),d", 0 }, /* ld.s isrc1(isrc2),idest */
+{ "ld.s", 0x14000001, 0xe8000000, "I(2),d", E_ADDR }, /* ld.s #const(isrc2),idest */
+{ "ld.l", 0x10000001, 0xec000000, "1(2),d", 0 }, /* ld.l isrc1(isrc2),idest */
+{ "ld.l", 0x14000001, 0xe8000000, "I(2),d", E_ADDR }, /* ld.l #const(isrc2),idest */
+
+{ "st.c", 0x38000000, 0xc4000000, "1,c", 0 }, /* st.c isrc1ni,csrc2 */
+{ "st.b", 0x0c000000, 0xf0000000, "1,S(2)", E_ADDR }, /* st.b isrc1ni,#const(isrc2) */
+{ "st.s", 0x1c000000, 0xe0000000, "1,S(2)", E_ADDR }, /* st.s isrc1ni,#const(isrc2) */
+{ "st.l", 0x1c000001, 0xe0000000, "1,S(2)", E_ADDR }, /* st.l isrc1ni,#const(isrc2) */
+
+{ "ixfr", 0x08000000, 0xf4000000, "1,g", 0 }, /* ixfr isrc1ni,fdest */
+
+{ "fld.l", 0x20000002, 0xdc000001, "1(2),g", 0 }, /* fld.l isrc1(isrc2),fdest */
+{ "fld.l", 0x24000002, 0xd8000001, "i(2),g", E_ADDR }, /* fld.l #const(isrc2),fdest */
+{ "fld.l", 0x20000003, 0xdc000000, "1(2)++,g", 0 }, /* fld.l isrc1(isrc2)++,fdest */
+{ "fld.l", 0x24000003, 0xd8000000, "i(2)++,g", E_ADDR }, /* fld.l #const(isrc2)++,fdest */
+{ "fld.d", 0x20000000, 0xdc000007, "1(2),g", 0 }, /* fld.d isrc1(isrc2),fdest */
+{ "fld.d", 0x24000000, 0xd8000007, "i(2),g", E_ADDR }, /* fld.d #const(isrc2),fdest */
+{ "fld.d", 0x20000001, 0xdc000006, "1(2)++,g", 0 }, /* fld.d isrc1(isrc2)++,fdest */
+{ "fld.d", 0x24000001, 0xd8000006, "i(2)++,g", E_ADDR }, /* fld.d #const(isrc2)++,fdest */
+{ "fld.q", 0x20000004, 0xdc000003, "1(2),g", 0 }, /* fld.q isrc1(isrc2),fdest */
+{ "fld.q", 0x24000004, 0xd8000003, "i(2),g", E_ADDR }, /* fld.q #const(isrc2),fdest */
+{ "fld.q", 0x20000005, 0xdc000002, "1(2)++,g", 0 }, /* fld.q isrc1(isrc2)++,fdest */
+{ "fld.q", 0x24000005, 0xd8000002, "i(2)++,g", E_ADDR }, /* fld.q #const(isrc2)++,fdest */
+
+{ "pfld.l", 0x60000000, 0x9c000003, "1(2),g", 0 }, /* pfld.l isrc1(isrc2),fdest */
+{ "pfld.l", 0x64000000, 0x98000003, "i(2),g", E_ADDR }, /* pfld.l #const(isrc2),fdest */
+{ "pfld.l", 0x60000001, 0x9c000002, "1(2)++,g", 0 }, /* pfld.l isrc1(isrc2)++,fdest */
+{ "pfld.l", 0x64000001, 0x98000002, "i(2)++,g", E_ADDR }, /* pfld.l #const(isrc2)++,fdest */
+{ "pfld.d", 0x60000000, 0x9c000007, "1(2),g", 0 }, /* pfld.d isrc1(isrc2),fdest */
+{ "pfld.d", 0x64000000, 0x98000007, "i(2),g", E_ADDR }, /* pfld.d #const(isrc2),fdest */
+{ "pfld.d", 0x60000001, 0x9c000006, "1(2)++,g", 0 }, /* pfld.d isrc1(isrc2)++,fdest */
+{ "pfld.d", 0x64000001, 0x98000006, "i(2)++,g", E_ADDR }, /* pfld.d #const(isrc2)++,fdest */
+
+{ "fst.l", 0x28000002, 0xd4000001, "g,1(2)", 0 }, /* fst.l fdest,isrc1(isrc2) */
+{ "fst.l", 0x2c000002, 0xd0000001, "g,i(2)", E_ADDR }, /* fst.l fdest,#const(isrc2) */
+{ "fst.l", 0x28000003, 0xd4000000, "g,1(2)++", 0 }, /* fst.l fdest,isrc1(isrc2)++ */
+{ "fst.l", 0x2c000003, 0xd0000000, "g,i(2)++", E_ADDR }, /* fst.l fdest,#const(isrc2)++ */
+{ "fst.d", 0x28000000, 0xd4000007, "g,1(2)", 0 }, /* fst.d fdest,isrc1(isrc2) */
+{ "fst.d", 0x2c000000, 0xd0000007, "g,i(2)", E_ADDR }, /* fst.d fdest,#const(isrc2) */
+{ "fst.d", 0x28000001, 0xd4000006, "g,1(2)++", 0 }, /* fst.d fdest,isrc1(isrc2)++ */
+{ "fst.d", 0x2c000001, 0xd0000006, "g,i(2)++", E_ADDR }, /* fst.d fdest,#const(isrc2)++ */
+
+{ "pst.d", 0x3c000000, 0xc0000007, "g,i(2)", E_ADDR }, /* pst.d fdest,#const(isrc2) */
+{ "pst.d", 0x3c000001, 0xc0000006, "g,i(2)++", E_ADDR }, /* pst.d fdest,#const(isrc2)++ */
+
+{ "addu", 0x80000000, 0x7c000000, "1,2,d", 0 }, /* addu isrc1,isrc2,idest */
+{ "addu", 0x84000000, 0x78000000, "i,2,d", E_S32 }, /* addu #const,isrc2,idest */
+{ "adds", 0x90000000, 0x6c000000, "1,2,d", 0 }, /* adds isrc1,isrc2,idest */
+{ "adds", 0x94000000, 0x68000000, "i,2,d", E_S32 }, /* adds #const,isrc2,idest */
+{ "subu", 0x88000000, 0x74000000, "1,2,d", 0 }, /* subu isrc1,isrc2,idest */
+{ "subu", 0x8c000000, 0x70000000, "i,2,d", E_S32 }, /* subu #const,isrc2,idest */
+{ "subs", 0x98000000, 0x64000000, "1,2,d", 0 }, /* subs isrc1,isrc2,idest */
+{ "subs", 0x9c000000, 0x60000000, "i,2,d", E_S32 }, /* subs #const,isrc2,idest */
+
+{ "shl", 0xa0000000, 0x5c000000, "1,2,d", 0 }, /* shl isrc1,isrc2,idest */
+{ "shl", 0xa4000000, 0x58000000, "i,2,d", 0 }, /* shl #const,isrc2,idest */
+{ "shr", 0xa8000000, 0x54000000, "1,2,d", 0 }, /* shr isrc1,isrc2,idest */
+{ "shr", 0xac000000, 0x50000000, "i,2,d", 0 }, /* shr #const,isrc2,idest */
+{ "shrd", 0xb0000000, 0x4c000000, "1,2,d", 0 }, /* shrd isrc1,isrc2,idest */
+{ "shra", 0xb8000000, 0x44000000, "1,2,d", 0 }, /* shra isrc1,isrc2,idest */
+{ "shra", 0xbc000000, 0x40000000, "i,2,d", 0 }, /* shra #const,isrc2,idest */
+
+{ "mov", 0xa0000000, 0x5c00f800, "2,d", 0 }, /* shl r0,isrc2,idest */
+{ "mov", 0x94000000, 0x69e00000, "i,d", E_MOV }, /* adds #const,r0,idest */
+{ "nop", 0xa0000000, 0x5ffff800, "", 0 }, /* shl r0,r0,r0 */
+{ "fnop", 0xb0000000, 0x4ffff800, "", 0 }, /* shrd r0,r0,r0 */
+
+{ "trap", 0x44000000, 0xb8000000, "1,2,d", 0 }, /* trap isrc1ni,isrc2,idest */
+
+{ "flush", 0x34000000, 0xc81f0001, "i(2)", E_ADDR }, /* flush #const(isrc2) */
+{ "flush", 0x34000001, 0xc81f0000, "i(2)++", E_ADDR }, /* flush #const(isrc2)++ */
+
+{ "and", 0xc0000000, 0x3c000000, "1,2,d", 0 }, /* and isrc1,isrc2,idest */
+{ "and", 0xc4000000, 0x38000000, "i,2,d", E_AND }, /* and #const,isrc2,idest */
+{ "andh", 0xc8000000, 0x34000000, "1,2,d", 0 }, /* andh isrc1,isrc2,idest */
+{ "andh", 0xcc000000, 0x30000000, "i,2,d", 0 }, /* andh #const,isrc2,idest */
+{ "andnot", 0xd0000000, 0x2c000000, "1,2,d", 0 }, /* andnot isrc1,isrc2,idest */
+{ "andnot", 0xd4000000, 0x28000000, "i,2,d", E_U32 }, /* andnot #const,isrc2,idest */
+{ "andnoth", 0xd8000000, 0x24000000, "1,2,d", 0 }, /* andnoth isrc1,isrc2,idest */
+{ "andnoth", 0xdc000000, 0x20000000, "i,2,d", 0 }, /* andnoth #const,isrc2,idest */
+{ "or", 0xe0000000, 0x1c000000, "1,2,d", 0 }, /* or isrc1,isrc2,idest */
+{ "or", 0xe4000000, 0x18000000, "i,2,d", E_U32 }, /* or #const,isrc2,idest */
+{ "orh", 0xe8000000, 0x14000000, "1,2,d", 0 }, /* orh isrc1,isrc2,idest */
+{ "orh", 0xec000000, 0x10000000, "i,2,d", 0 }, /* orh #const,isrc2,idest */
+{ "xor", 0xf0000000, 0x0c000000, "1,2,d", 0 }, /* xor isrc1,isrc2,idest */
+{ "xor", 0xf4000000, 0x08000000, "i,2,d", E_U32 }, /* xor #const,isrc2,idest */
+{ "xorh", 0xf8000000, 0x04000000, "1,2,d", 0 }, /* xorh isrc1,isrc2,idest */
+{ "xorh", 0xfc000000, 0x00000000, "i,2,d", 0 }, /* xorh #const,isrc2,idest */
+
+{ "bte", 0x58000000, 0xa4000000, "1,2,s", 0 }, /* bte isrc1s,isrc2,sbroff */
+{ "bte", 0x5c000000, 0xa0000000, "5,2,s", 0 }, /* bte #const5,isrc2,sbroff */
+{ "btne", 0x50000000, 0xac000000, "1,2,s", 0 }, /* btne isrc1s,isrc2,sbroff */
+{ "btne", 0x54000000, 0xa8000000, "5,2,s", 0 }, /* btne #const5,isrc2,sbroff */
+{ "bla", 0xb4000000, 0x48000000, "1,2,s", E_DELAY }, /* bla isrc1s,isrc2,sbroff */
+{ "bri", 0x40000000, 0xbc000000, "1", E_DELAY }, /* bri isrc1ni */
+
+/* Core Escape Instruction Format */
+{ "lock", 0x4c000001, 0xb000001e, "", 0 }, /* lock set BL in dirbase */
+{ "calli", 0x4c000002, 0xb000001d, "1", E_DELAY }, /* calli isrc1ni */
+{ "intovr", 0x4c000004, 0xb000001b, "", 0 }, /* intovr trap on integer overflow */
+{ "unlock", 0x4c000007, 0xb0000018, "", 0 }, /* unlock clear BL in dirbase */
+
+/* CTRL-Format Instructions */
+{ "br", 0x68000000, 0x94000000, "l", E_DELAY }, /* br lbroff */
+{ "call", 0x6c000000, 0x90000000, "l", E_DELAY }, /* call lbroff */
+{ "bc", 0x70000000, 0x8c000000, "l", 0 }, /* bc lbroff */
+{ "bc.t", 0x74000000, 0x88000000, "l", E_DELAY }, /* bc.t lbroff */
+{ "bnc", 0x78000000, 0x84000000, "l", 0 }, /* bnc lbroff */
+{ "bnc.t", 0x7c000000, 0x80000000, "l", E_DELAY }, /* bnc.t lbroff */
+
+/* Floating Point Escape Instruction Format - pfam.p fsrc1,fsrc2,fdest */
+{ "r2p1.ss", 0x48000400, 0xb40003ff, "e,f,g", 0 },
+{ "r2p1.sd", 0x48000480, 0xb400037f, "e,f,g", 0 },
+{ "r2p1.dd", 0x48000580, 0xb400027f, "e,f,g", 0 },
+{ "r2pt.ss", 0x48000401, 0xb40003fe, "e,f,g", 0 },
+{ "r2pt.sd", 0x48000481, 0xb400037e, "e,f,g", 0 },
+{ "r2pt.dd", 0x48000581, 0xb400027e, "e,f,g", 0 },
+{ "r2ap1.ss", 0x48000402, 0xb40003fd, "e,f,g", 0 },
+{ "r2ap1.sd", 0x48000482, 0xb400037d, "e,f,g", 0 },
+{ "r2ap1.dd", 0x48000582, 0xb400027d, "e,f,g", 0 },
+{ "r2apt.ss", 0x48000403, 0xb40003fc, "e,f,g", 0 },
+{ "r2apt.sd", 0x48000483, 0xb400037c, "e,f,g", 0 },
+{ "r2apt.dd", 0x48000583, 0xb400027c, "e,f,g", 0 },
+{ "i2p1.ss", 0x48000404, 0xb40003fb, "e,f,g", 0 },
+{ "i2p1.sd", 0x48000484, 0xb400037b, "e,f,g", 0 },
+{ "i2p1.dd", 0x48000584, 0xb400027b, "e,f,g", 0 },
+{ "i2pt.ss", 0x48000405, 0xb40003fa, "e,f,g", 0 },
+{ "i2pt.sd", 0x48000485, 0xb400037a, "e,f,g", 0 },
+{ "i2pt.dd", 0x48000585, 0xb400027a, "e,f,g", 0 },
+{ "i2ap1.ss", 0x48000406, 0xb40003f9, "e,f,g", 0 },
+{ "i2ap1.sd", 0x48000486, 0xb4000379, "e,f,g", 0 },
+{ "i2ap1.dd", 0x48000586, 0xb4000279, "e,f,g", 0 },
+{ "i2apt.ss", 0x48000407, 0xb40003f8, "e,f,g", 0 },
+{ "i2apt.sd", 0x48000487, 0xb4000378, "e,f,g", 0 },
+{ "i2apt.dd", 0x48000587, 0xb4000278, "e,f,g", 0 },
+{ "rat1p2.ss", 0x48000408, 0xb40003f7, "e,f,g", 0 },
+{ "rat1p2.sd", 0x48000488, 0xb4000377, "e,f,g", 0 },
+{ "rat1p2.dd", 0x48000588, 0xb4000277, "e,f,g", 0 },
+{ "m12apm.ss", 0x48000409, 0xb40003f6, "e,f,g", 0 },
+{ "m12apm.sd", 0x48000489, 0xb4000376, "e,f,g", 0 },
+{ "m12apm.dd", 0x48000589, 0xb4000276, "e,f,g", 0 },
+{ "ra1p2.ss", 0x4800040a, 0xb40003f5, "e,f,g", 0 },
+{ "ra1p2.sd", 0x4800048a, 0xb4000375, "e,f,g", 0 },
+{ "ra1p2.dd", 0x4800058a, 0xb4000275, "e,f,g", 0 },
+{ "m12ttpa.ss", 0x4800040b, 0xb40003f4, "e,f,g", 0 },
+{ "m12ttpa.sd", 0x4800048b, 0xb4000374, "e,f,g", 0 },
+{ "m12ttpa.dd", 0x4800058b, 0xb4000274, "e,f,g", 0 },
+{ "iat1p2.ss", 0x4800040c, 0xb40003f3, "e,f,g", 0 },
+{ "iat1p2.sd", 0x4800048c, 0xb4000373, "e,f,g", 0 },
+{ "iat1p2.dd", 0x4800058c, 0xb4000273, "e,f,g", 0 },
+{ "m12tpm.ss", 0x4800040d, 0xb40003f2, "e,f,g", 0 },
+{ "m12tpm.sd", 0x4800048d, 0xb4000372, "e,f,g", 0 },
+{ "m12tpm.dd", 0x4800058d, 0xb4000272, "e,f,g", 0 },
+{ "ia1p2.ss", 0x4800040e, 0xb40003f1, "e,f,g", 0 },
+{ "ia1p2.sd", 0x4800048e, 0xb4000371, "e,f,g", 0 },
+{ "ia1p2.dd", 0x4800058e, 0xb4000271, "e,f,g", 0 },
+{ "m12tpa.ss", 0x4800040f, 0xb40003f0, "e,f,g", 0 },
+{ "m12tpa.sd", 0x4800048f, 0xb4000370, "e,f,g", 0 },
+{ "m12tpa.dd", 0x4800058f, 0xb4000270, "e,f,g", 0 },
+
+/* Floating Point Escape Instruction Format - pfsm.p fsrc1,fsrc2,fdest */
+{ "r2s1.ss", 0x48000410, 0xb40003ef, "e,f,g", 0 },
+{ "r2s1.sd", 0x48000490, 0xb400036f, "e,f,g", 0 },
+{ "r2s1.dd", 0x48000590, 0xb400026f, "e,f,g", 0 },
+{ "r2st.ss", 0x48000411, 0xb40003ee, "e,f,g", 0 },
+{ "r2st.sd", 0x48000491, 0xb400036e, "e,f,g", 0 },
+{ "r2st.dd", 0x48000591, 0xb400026e, "e,f,g", 0 },
+{ "r2as1.ss", 0x48000412, 0xb40003ed, "e,f,g", 0 },
+{ "r2as1.sd", 0x48000492, 0xb400036d, "e,f,g", 0 },
+{ "r2as1.dd", 0x48000592, 0xb400026d, "e,f,g", 0 },
+{ "r2ast.ss", 0x48000413, 0xb40003ec, "e,f,g", 0 },
+{ "r2ast.sd", 0x48000493, 0xb400036c, "e,f,g", 0 },
+{ "r2ast.dd", 0x48000593, 0xb400026c, "e,f,g", 0 },
+{ "i2s1.ss", 0x48000414, 0xb40003eb, "e,f,g", 0 },
+{ "i2s1.sd", 0x48000494, 0xb400036b, "e,f,g", 0 },
+{ "i2s1.dd", 0x48000594, 0xb400026b, "e,f,g", 0 },
+{ "i2st.ss", 0x48000415, 0xb40003ea, "e,f,g", 0 },
+{ "i2st.sd", 0x48000495, 0xb400036a, "e,f,g", 0 },
+{ "i2st.dd", 0x48000595, 0xb400026a, "e,f,g", 0 },
+{ "i2as1.ss", 0x48000416, 0xb40003e9, "e,f,g", 0 },
+{ "i2as1.sd", 0x48000496, 0xb4000369, "e,f,g", 0 },
+{ "i2as1.dd", 0x48000596, 0xb4000269, "e,f,g", 0 },
+{ "i2ast.ss", 0x48000417, 0xb40003e8, "e,f,g", 0 },
+{ "i2ast.sd", 0x48000497, 0xb4000368, "e,f,g", 0 },
+{ "i2ast.dd", 0x48000597, 0xb4000268, "e,f,g", 0 },
+{ "rat1s2.ss", 0x48000418, 0xb40003e7, "e,f,g", 0 },
+{ "rat1s2.sd", 0x48000498, 0xb4000367, "e,f,g", 0 },
+{ "rat1s2.dd", 0x48000598, 0xb4000267, "e,f,g", 0 },
+{ "m12asm.ss", 0x48000419, 0xb40003e6, "e,f,g", 0 },
+{ "m12asm.sd", 0x48000499, 0xb4000366, "e,f,g", 0 },
+{ "m12asm.dd", 0x48000599, 0xb4000266, "e,f,g", 0 },
+{ "ra1s2.ss", 0x4800041a, 0xb40003e5, "e,f,g", 0 },
+{ "ra1s2.sd", 0x4800049a, 0xb4000365, "e,f,g", 0 },
+{ "ra1s2.dd", 0x4800059a, 0xb4000265, "e,f,g", 0 },
+{ "m12ttsa.ss", 0x4800041b, 0xb40003e4, "e,f,g", 0 },
+{ "m12ttsa.sd", 0x4800049b, 0xb4000364, "e,f,g", 0 },
+{ "m12ttsa.dd", 0x4800059b, 0xb4000264, "e,f,g", 0 },
+{ "iat1s2.ss", 0x4800041c, 0xb40003e3, "e,f,g", 0 },
+{ "iat1s2.sd", 0x4800049c, 0xb4000363, "e,f,g", 0 },
+{ "iat1s2.dd", 0x4800059c, 0xb4000263, "e,f,g", 0 },
+{ "m12tsm.ss", 0x4800041d, 0xb40003e2, "e,f,g", 0 },
+{ "m12tsm.sd", 0x4800049d, 0xb4000362, "e,f,g", 0 },
+{ "m12tsm.dd", 0x4800059d, 0xb4000262, "e,f,g", 0 },
+{ "ia1s2.ss", 0x4800041e, 0xb40003e1, "e,f,g", 0 },
+{ "ia1s2.sd", 0x4800049e, 0xb4000361, "e,f,g", 0 },
+{ "ia1s2.dd", 0x4800059e, 0xb4000261, "e,f,g", 0 },
+{ "m12tsa.ss", 0x4800041f, 0xb40003e0, "e,f,g", 0 },
+{ "m12tsa.sd", 0x4800049f, 0xb4000360, "e,f,g", 0 },
+{ "m12tsa.dd", 0x4800059f, 0xb4000260, "e,f,g", 0 },
+
+/* Floating Point Escape Instruction Format - pfmam.p fsrc1,fsrc2,fdest */
+{ "mr2p1.ss", 0x48000000, 0xb40007ff, "e,f,g", 0 },
+{ "mr2p1.sd", 0x48000080, 0xb400077f, "e,f,g", 0 },
+{ "mr2p1.dd", 0x48000180, 0xb400067f, "e,f,g", 0 },
+{ "mr2pt.ss", 0x48000001, 0xb40007fe, "e,f,g", 0 },
+{ "mr2pt.sd", 0x48000081, 0xb400077e, "e,f,g", 0 },
+{ "mr2pt.dd", 0x48000181, 0xb400067e, "e,f,g", 0 },
+{ "mr2mp1.ss", 0x48000002, 0xb40007fd, "e,f,g", 0 },
+{ "mr2mp1.sd", 0x48000082, 0xb400077d, "e,f,g", 0 },
+{ "mr2mp1.dd", 0x48000182, 0xb400067d, "e,f,g", 0 },
+{ "mr2mpt.ss", 0x48000003, 0xb40007fc, "e,f,g", 0 },
+{ "mr2mpt.sd", 0x48000083, 0xb400077c, "e,f,g", 0 },
+{ "mr2mpt.dd", 0x48000183, 0xb400067c, "e,f,g", 0 },
+{ "mi2p1.ss", 0x48000004, 0xb40007fb, "e,f,g", 0 },
+{ "mi2p1.sd", 0x48000084, 0xb400077b, "e,f,g", 0 },
+{ "mi2p1.dd", 0x48000184, 0xb400067b, "e,f,g", 0 },
+{ "mi2pt.ss", 0x48000005, 0xb40007fa, "e,f,g", 0 },
+{ "mi2pt.sd", 0x48000085, 0xb400077a, "e,f,g", 0 },
+{ "mi2pt.dd", 0x48000185, 0xb400067a, "e,f,g", 0 },
+{ "mi2mp1.ss", 0x48000006, 0xb40007f9, "e,f,g", 0 },
+{ "mi2mp1.sd", 0x48000086, 0xb4000779, "e,f,g", 0 },
+{ "mi2mp1.dd", 0x48000186, 0xb4000679, "e,f,g", 0 },
+{ "mi2mpt.ss", 0x48000007, 0xb40007f8, "e,f,g", 0 },
+{ "mi2mpt.sd", 0x48000087, 0xb4000778, "e,f,g", 0 },
+{ "mi2mpt.dd", 0x48000187, 0xb4000678, "e,f,g", 0 },
+{ "mrmt1p2.ss", 0x48000008, 0xb40007f7, "e,f,g", 0 },
+{ "mrmt1p2.sd", 0x48000088, 0xb4000777, "e,f,g", 0 },
+{ "mrmt1p2.dd", 0x48000188, 0xb4000677, "e,f,g", 0 },
+{ "mm12mpm.ss", 0x48000009, 0xb40007f6, "e,f,g", 0 },
+{ "mm12mpm.sd", 0x48000089, 0xb4000776, "e,f,g", 0 },
+{ "mm12mpm.dd", 0x48000189, 0xb4000676, "e,f,g", 0 },
+{ "mrm1p2.ss", 0x4800000a, 0xb40007f5, "e,f,g", 0 },
+{ "mrm1p2.sd", 0x4800008a, 0xb4000775, "e,f,g", 0 },
+{ "mrm1p2.dd", 0x4800018a, 0xb4000675, "e,f,g", 0 },
+{ "mm12ttpm.ss",0x4800000b, 0xb40007f4, "e,f,g", 0 },
+{ "mm12ttpm.sd",0x4800008b, 0xb4000774, "e,f,g", 0 },
+{ "mm12ttpm.dd",0x4800018b, 0xb4000674, "e,f,g", 0 },
+{ "mimt1p2.ss", 0x4800000c, 0xb40007f3, "e,f,g", 0 },
+{ "mimt1p2.sd", 0x4800008c, 0xb4000773, "e,f,g", 0 },
+{ "mimt1p2.dd", 0x4800018c, 0xb4000673, "e,f,g", 0 },
+{ "mm12tpm.ss", 0x4800000d, 0xb40007f2, "e,f,g", 0 },
+{ "mm12tpm.sd", 0x4800008d, 0xb4000772, "e,f,g", 0 },
+{ "mm12tpm.dd", 0x4800018d, 0xb4000672, "e,f,g", 0 },
+{ "mim1p2.ss", 0x4800000e, 0xb40007f1, "e,f,g", 0 },
+{ "mim1p2.sd", 0x4800008e, 0xb4000771, "e,f,g", 0 },
+{ "mim1p2.dd", 0x4800018e, 0xb4000671, "e,f,g", 0 },
+
+/* Floating Point Escape Instruction Format - pfmsm.p fsrc1,fsrc2,fdest */
+{ "mr2s1.ss", 0x48000010, 0xb40007ef, "e,f,g", 0 },
+{ "mr2s1.sd", 0x48000090, 0xb400076f, "e,f,g", 0 },
+{ "mr2s1.dd", 0x48000190, 0xb400066f, "e,f,g", 0 },
+{ "mr2st.ss", 0x48000011, 0xb40007ee, "e,f,g", 0 },
+{ "mr2st.sd", 0x48000091, 0xb400076e, "e,f,g", 0 },
+{ "mr2st.dd", 0x48000191, 0xb400066e, "e,f,g", 0 },
+{ "mr2ms1.ss", 0x48000012, 0xb40007ed, "e,f,g", 0 },
+{ "mr2ms1.sd", 0x48000092, 0xb400076d, "e,f,g", 0 },
+{ "mr2ms1.dd", 0x48000192, 0xb400066d, "e,f,g", 0 },
+{ "mr2mst.ss", 0x48000013, 0xb40007ec, "e,f,g", 0 },
+{ "mr2mst.sd", 0x48000093, 0xb400076c, "e,f,g", 0 },
+{ "mr2mst.dd", 0x48000193, 0xb400066c, "e,f,g", 0 },
+{ "mi2s1.ss", 0x48000014, 0xb40007eb, "e,f,g", 0 },
+{ "mi2s1.sd", 0x48000094, 0xb400076b, "e,f,g", 0 },
+{ "mi2s1.dd", 0x48000194, 0xb400066b, "e,f,g", 0 },
+{ "mi2st.ss", 0x48000015, 0xb40007ea, "e,f,g", 0 },
+{ "mi2st.sd", 0x48000095, 0xb400076a, "e,f,g", 0 },
+{ "mi2st.dd", 0x48000195, 0xb400066a, "e,f,g", 0 },
+{ "mi2ms1.ss", 0x48000016, 0xb40007e9, "e,f,g", 0 },
+{ "mi2ms1.sd", 0x48000096, 0xb4000769, "e,f,g", 0 },
+{ "mi2ms1.dd", 0x48000196, 0xb4000669, "e,f,g", 0 },
+{ "mi2mst.ss", 0x48000017, 0xb40007e8, "e,f,g", 0 },
+{ "mi2mst.sd", 0x48000097, 0xb4000768, "e,f,g", 0 },
+{ "mi2mst.dd", 0x48000197, 0xb4000668, "e,f,g", 0 },
+{ "mrmt1s2.ss", 0x48000018, 0xb40007e7, "e,f,g", 0 },
+{ "mrmt1s2.sd", 0x48000098, 0xb4000767, "e,f,g", 0 },
+{ "mrmt1s2.dd", 0x48000198, 0xb4000667, "e,f,g", 0 },
+{ "mm12msm.ss", 0x48000019, 0xb40007e6, "e,f,g", 0 },
+{ "mm12msm.sd", 0x48000099, 0xb4000766, "e,f,g", 0 },
+{ "mm12msm.dd", 0x48000199, 0xb4000666, "e,f,g", 0 },
+{ "mrm1s2.ss", 0x4800001a, 0xb40007e5, "e,f,g", 0 },
+{ "mrm1s2.sd", 0x4800009a, 0xb4000765, "e,f,g", 0 },
+{ "mrm1s2.dd", 0x4800019a, 0xb4000665, "e,f,g", 0 },
+{ "mm12ttsm.ss",0x4800001b, 0xb40007e4, "e,f,g", 0 },
+{ "mm12ttsm.sd",0x4800009b, 0xb4000764, "e,f,g", 0 },
+{ "mm12ttsm.dd",0x4800019b, 0xb4000664, "e,f,g", 0 },
+{ "mimt1s2.ss", 0x4800001c, 0xb40007e3, "e,f,g", 0 },
+{ "mimt1s2.sd", 0x4800009c, 0xb4000763, "e,f,g", 0 },
+{ "mimt1s2.dd", 0x4800019c, 0xb4000663, "e,f,g", 0 },
+{ "mm12tsm.ss", 0x4800001d, 0xb40007e2, "e,f,g", 0 },
+{ "mm12tsm.sd", 0x4800009d, 0xb4000762, "e,f,g", 0 },
+{ "mm12tsm.dd", 0x4800019d, 0xb4000662, "e,f,g", 0 },
+{ "mim1s2.ss", 0x4800001e, 0xb40007e1, "e,f,g", 0 },
+{ "mim1s2.sd", 0x4800009e, 0xb4000761, "e,f,g", 0 },
+{ "mim1s2.dd", 0x4800019e, 0xb4000661, "e,f,g", 0 },
+
+
+{ "fmul.ss", 0x48000020, 0xb40007df, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */
+{ "fmul.sd", 0x480000a0, 0xb400075f, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */
+{ "fmul.dd", 0x480001a0, 0xb400065f, "e,f,g", 0 }, /* fmul.p fsrc1,fsrc2,fdest */
+{ "pfmul.ss", 0x48000420, 0xb40003df, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */
+{ "pfmul.sd", 0x480004a0, 0xb400035f, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */
+{ "pfmul.dd", 0x480005a0, 0xb400025f, "e,f,g", 0 }, /* pfmul.p fsrc1,fsrc2,fdest */
+{ "pfmul3.dd", 0x480005a4, 0xb400025b, "e,f,g", 0 }, /* pfmul3.p fsrc1,fsrc2,fdest */
+{ "fmlow.dd", 0x480001a1, 0xb400065e, "e,f,g", 0 }, /* fmlow.dd fsrc1,fsrc2,fdest */
+{ "frcp.ss", 0x48000022, 0xb40007dd, "f,g", 0 }, /* frcp.p fsrc2,fdest */
+{ "frcp.sd", 0x480000a2, 0xb400075d, "f,g", 0 }, /* frcp.p fsrc2,fdest */
+{ "frcp.dd", 0x480001a2, 0xb400065d, "f,g", 0 }, /* frcp.p fsrc2,fdest */
+{ "frsqr.ss", 0x48000023, 0xb40007dc, "f,g", 0 }, /* frsqr.p fsrc2,fdest */
+{ "frsqr.sd", 0x480000a3, 0xb400075c, "f,g", 0 }, /* frsqr.p fsrc2,fdest */
+{ "frsqr.dd", 0x480001a3, 0xb400065c, "f,g", 0 }, /* frsqr.p fsrc2,fdest */
+{ "fadd.ss", 0x48000030, 0xb40007cf, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */
+{ "fadd.sd", 0x480000b0, 0xb400074f, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */
+{ "fadd.dd", 0x480001b0, 0xb400064f, "e,f,g", 0 }, /* fadd.p fsrc1,fsrc2,fdest */
+{ "pfadd.ss", 0x48000430, 0xb40003cf, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */
+{ "pfadd.sd", 0x480004b0, 0xb400034f, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */
+{ "pfadd.dd", 0x480005b0, 0xb400024f, "e,f,g", 0 }, /* pfadd.p fsrc1,fsrc2,fdest */
+{ "fsub.ss", 0x48000031, 0xb40007ce, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */
+{ "fsub.sd", 0x480000b1, 0xb400074e, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */
+{ "fsub.dd", 0x480001b1, 0xb400064e, "e,f,g", 0 }, /* fsub.p fsrc1,fsrc2,fdest */
+{ "pfsub.ss", 0x48000431, 0xb40003ce, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */
+{ "pfsub.sd", 0x480004b1, 0xb400034e, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */
+{ "pfsub.dd", 0x480005b1, 0xb400024e, "e,f,g", 0 }, /* pfsub.p fsrc1,fsrc2,fdest */
+{ "fix.ss", 0x48000032, 0xb40007cd, "e,g", 0 }, /* fix.p fsrc1,fdest */
+{ "fix.sd", 0x480000b2, 0xb400074d, "e,g", 0 }, /* fix.p fsrc1,fdest */
+{ "fix.dd", 0x480001b2, 0xb400064d, "e,g", 0 }, /* fix.p fsrc1,fdest */
+{ "pfix.ss", 0x48000432, 0xb40003cd, "e,g", 0 }, /* pfix.p fsrc1,fdest */
+{ "pfix.sd", 0x480004b2, 0xb400034d, "e,g", 0 }, /* pfix.p fsrc1,fdest */
+{ "pfix.dd", 0x480005b2, 0xb400024d, "e,g", 0 }, /* pfix.p fsrc1,fdest */
+{ "famov.ss", 0x48000033, 0xb40007cc, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "famov.ds", 0x48000133, 0xb40006cc, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "famov.sd", 0x480000b3, 0xb400074c, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "famov.dd", 0x480001b3, 0xb400064c, "e,g", 0 }, /* famov.p fsrc1,fdest */
+{ "pfamov.ss", 0x48000433, 0xb40003cc, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+{ "pfamov.ds", 0x48000533, 0xb40002cc, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+{ "pfamov.sd", 0x480004b3, 0xb400034c, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+{ "pfamov.dd", 0x480005b3, 0xb400024c, "e,g", 0 }, /* pfamov.p fsrc1,fdest */
+/* pfgt has R bit cleared; pfle has R bit set */
+{ "pfgt.ss", 0x48000434, 0xb40003cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */
+{ "pfgt.sd", 0x48000434, 0xb40003cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */
+{ "pfgt.dd", 0x48000534, 0xb40002cb, "e,f,g", 0 }, /* pfgt.p fsrc1,fsrc2,fdest */
+/* pfgt has R bit cleared; pfle has R bit set */
+{ "pfle.ss", 0x480004b4, 0xb400034b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */
+{ "pfle.sd", 0x480004b4, 0xb400034b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */
+{ "pfle.dd", 0x480005b4, 0xb400024b, "e,f,g", 0 }, /* pfle.p fsrc1,fsrc2,fdest */
+{ "ftrunc.ss", 0x4800003a, 0xb40007c5, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */
+{ "ftrunc.sd", 0x480000ba, 0xb4000745, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */
+{ "ftrunc.dd", 0x480001ba, 0xb4000645, "e,g", 0 }, /* ftrunc.p fsrc1,fdest */
+{ "pftrunc.ss", 0x4800043a, 0xb40003c5, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */
+{ "pftrunc.sd", 0x480004ba, 0xb4000345, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */
+{ "pftrunc.dd", 0x480005ba, 0xb4000245, "e,g", 0 }, /* pftrunc.p fsrc1,fdest */
+{ "fxfr", 0x48000040, 0xb40007bf, "e,d", 0 }, /* fxfr fsrc1,idest */
+{ "fiadd.ss", 0x48000049, 0xb40007b6, "e,f,g", 0 }, /* fiadd.w fsrc1,fsrc2,fdest */
+{ "fiadd.dd", 0x480001c9, 0xb4000636, "e,f,g", 0 }, /* fiadd.w fsrc1,fsrc2,fdest */
+{ "pfiadd.ss", 0x48000449, 0xb40003b6, "e,f,g", 0 }, /* pfiadd.w fsrc1,fsrc2,fdest */
+{ "pfiadd.dd", 0x480005c9, 0xb4000236, "e,f,g", 0 }, /* pfiadd.w fsrc1,fsrc2,fdest */
+{ "fisub.ss", 0x4800004d, 0xb40007b2, "e,f,g", 0 }, /* fisub.w fsrc1,fsrc2,fdest */
+{ "fisub.dd", 0x480001cd, 0xb4000632, "e,f,g", 0 }, /* fisub.w fsrc1,fsrc2,fdest */
+{ "pfisub.ss", 0x4800044d, 0xb40003b2, "e,f,g", 0 }, /* pfisub.w fsrc1,fsrc2,fdest */
+{ "pfisub.dd", 0x480005cd, 0xb4000232, "e,f,g", 0 }, /* pfisub.w fsrc1,fsrc2,fdest */
+{ "fzchkl", 0x48000057, 0xb40007a8, "e,f,g", 0 }, /* fzchkl fsrc1,fsrc2,fdest */
+{ "pfzchkl", 0x48000457, 0xb40003a8, "e,f,g", 0 }, /* pfzchkl fsrc1,fsrc2,fdest */
+{ "fzchks", 0x4800005f, 0xb40007a0, "e,f,g", 0 }, /* fzchks fsrc1,fsrc2,fdest */
+{ "pfzchks", 0x4800045f, 0xb40003a0, "e,f,g", 0 }, /* pfzchks fsrc1,fsrc2,fdest */
+{ "faddp", 0x48000050, 0xb40007af, "e,f,g", 0 }, /* faddp fsrc1,fsrc2,fdest */
+{ "pfaddp", 0x48000450, 0xb40003af, "e,f,g", 0 }, /* pfaddp fsrc1,fsrc2,fdest */
+{ "faddz", 0x48000051, 0xb40007ae, "e,f,g", 0 }, /* faddz fsrc1,fsrc2,fdest */
+{ "pfaddz", 0x48000451, 0xb40003ae, "e,f,g", 0 }, /* pfaddz fsrc1,fsrc2,fdest */
+{ "form", 0x4800005a, 0xb40007a5, "e,g", 0 }, /* form fsrc1,fdest */
+{ "pform", 0x4800045a, 0xb40003a5, "e,g", 0 }, /* pform fsrc1,fdest */
+
+/* Floating point pseudo-instructions */
+{ "fmov.ss", 0x48000049, 0xb7e007b6, "e,g", 0 }, /* fiadd.ss fsrc1,f0,fdest */
+{ "fmov.dd", 0x480001c9, 0xb7e00636, "e,g", 0 }, /* fiadd.dd fsrc1,f0,fdest */
+{ "fmov.sd", 0x480000b0, 0xb7e0074f, "e,g", 0 }, /* fadd.sd fsrc1,f0,fdest */
+{ "fmov.ds", 0x48000130, 0xb7e006cf, "e,g", 0 }, /* fadd.ds fsrc1,f0,fdest */
+{ "pfmov.ds", 0x48000530, 0xb73002cf, "e,g", 0 }, /* pfadd.ds fsrc1,f0,fdest */
+{ "pfmov.dd", 0x480005c9, 0xb7e00236, "e,g", 0 }, /* pfiadd.dd fsrc1,f0,fdest */
+
+
+};
+
+#define NUMOPCODES ((sizeof i860_opcodes)/(sizeof i860_opcodes[0]))
+
+
diff --git a/contrib/gdb/include/opcode/i960.h b/contrib/gdb/include/opcode/i960.h
new file mode 100644
index 0000000..8030ad8
--- /dev/null
+++ b/contrib/gdb/include/opcode/i960.h
@@ -0,0 +1,509 @@
+/* Basic 80960 instruction formats.
+ *
+ * The 'COJ' instructions are actually COBR instructions with the 'b' in
+ * the mnemonic replaced by a 'j'; they are ALWAYS "de-optimized" if necessary:
+ * if the displacement will not fit in 13 bits, the assembler will replace them
+ * with the corresponding compare and branch instructions.
+ *
+ * All of the 'MEMn' instructions are the same format; the 'n' in the name
+ * indicates the default index scale factor (the size of the datum operated on).
+ *
+ * The FBRA formats are not actually an instruction format. They are the
+ * "convenience directives" for branching on floating-point comparisons,
+ * each of which generates 2 instructions (a 'bno' and one other branch).
+ *
+ * The CALLJ format is not actually an instruction format. It indicates that
+ * the instruction generated (a CTRL-format 'call') should have its relocation
+ * specially flagged for link-time replacement with a 'bal' or 'calls' if
+ * appropriate.
+ */
+
+#define CTRL 0
+#define COBR 1
+#define COJ 2
+#define REG 3
+#define MEM1 4
+#define MEM2 5
+#define MEM4 6
+#define MEM8 7
+#define MEM12 8
+#define MEM16 9
+#define FBRA 10
+#define CALLJ 11
+
+/* Masks for the mode bits in REG format instructions */
+#define M1 0x0800
+#define M2 0x1000
+#define M3 0x2000
+
+/* Generate the 12-bit opcode for a REG format instruction by placing the
+ * high 8 bits in instruction bits 24-31, the low 4 bits in instruction bits
+ * 7-10.
+ */
+
+#define REG_OPC(opc) ((opc & 0xff0) << 20) | ((opc & 0xf) << 7)
+
+/* Generate a template for a REG format instruction: place the opcode bits
+ * in the appropriate fields and OR in mode bits for the operands that will not
+ * be used. I.e.,
+ * set m1=1, if src1 will not be used
+ * set m2=1, if src2 will not be used
+ * set m3=1, if dst will not be used
+ *
+ * Setting the "unused" mode bits to 1 speeds up instruction execution(!).
+ * The information is also useful to us because some 1-operand REG instructions
+ * use the src1 field, others the dst field; and some 2-operand REG instructions
+ * use src1/src2, others src1/dst. The set mode bits enable us to distinguish.
+ */
+#define R_0(opc) ( REG_OPC(opc) | M1 | M2 | M3 ) /* No operands */
+#define R_1(opc) ( REG_OPC(opc) | M2 | M3 ) /* 1 operand: src1 */
+#define R_1D(opc) ( REG_OPC(opc) | M1 | M2 ) /* 1 operand: dst */
+#define R_2(opc) ( REG_OPC(opc) | M3 ) /* 2 ops: src1/src2 */
+#define R_2D(opc) ( REG_OPC(opc) | M2 ) /* 2 ops: src1/dst */
+#define R_3(opc) ( REG_OPC(opc) ) /* 3 operands */
+
+/* DESCRIPTOR BYTES FOR REGISTER OPERANDS
+ *
+ * Interpret names as follows:
+ * R: global or local register only
+ * RS: global, local, or (if target allows) special-function register only
+ * RL: global or local register, or integer literal
+ * RSL: global, local, or (if target allows) special-function register;
+ * or integer literal
+ * F: global, local, or floating-point register
+ * FL: global, local, or floating-point register; or literal (including
+ * floating point)
+ *
+ * A number appended to a name indicates that registers must be aligned,
+ * as follows:
+ * 2: register number must be multiple of 2
+ * 4: register number must be multiple of 4
+ */
+
+#define SFR 0x10 /* Mask for the "sfr-OK" bit */
+#define LIT 0x08 /* Mask for the "literal-OK" bit */
+#define FP 0x04 /* Mask for "floating-point-OK" bit */
+
+/* This macro ors the bits together. Note that 'align' is a mask
+ * for the low 0, 1, or 2 bits of the register number, as appropriate.
+ */
+#define OP(align,lit,fp,sfr) ( align | lit | fp | sfr )
+
+#define R OP( 0, 0, 0, 0 )
+#define RS OP( 0, 0, 0, SFR )
+#define RL OP( 0, LIT, 0, 0 )
+#define RSL OP( 0, LIT, 0, SFR )
+#define F OP( 0, 0, FP, 0 )
+#define FL OP( 0, LIT, FP, 0 )
+#define R2 OP( 1, 0, 0, 0 )
+#define RL2 OP( 1, LIT, 0, 0 )
+#define F2 OP( 1, 0, FP, 0 )
+#define FL2 OP( 1, LIT, FP, 0 )
+#define R4 OP( 3, 0, 0, 0 )
+#define RL4 OP( 3, LIT, 0, 0 )
+#define F4 OP( 3, 0, FP, 0 )
+#define FL4 OP( 3, LIT, FP, 0 )
+
+#define M 0x7f /* Memory operand (MEMA & MEMB format instructions) */
+
+/* Macros to extract info from the register operand descriptor byte 'od'.
+ */
+#define SFR_OK(od) (od & SFR) /* TRUE if sfr operand allowed */
+#define LIT_OK(od) (od & LIT) /* TRUE if literal operand allowed */
+#define FP_OK(od) (od & FP) /* TRUE if floating-point op allowed */
+#define REG_ALIGN(od,n) ((od & 0x3 & n) == 0)
+ /* TRUE if reg #n is properly aligned */
+#define MEMOP(od) (od == M) /* TRUE if operand is a memory operand*/
+
+/* Description of a single i80960 instruction */
+struct i960_opcode {
+ long opcode; /* 32 bits, constant fields filled in, rest zeroed */
+ char *name; /* Assembler mnemonic */
+ short iclass; /* Class: see #defines below */
+ char format; /* REG, COBR, CTRL, MEMn, COJ, FBRA, or CALLJ */
+ char num_ops; /* Number of operands */
+ char operand[3];/* Operand descriptors; same order as assembler instr */
+};
+
+/* Classes of 960 intructions:
+ * - each instruction falls into one class.
+ * - each target architecture supports one or more classes.
+ *
+ * EACH CONSTANT MUST CONTAIN 1 AND ONLY 1 SET BIT!: see targ_has_iclass().
+ */
+#define I_BASE 0x01 /* 80960 base instruction set */
+#define I_CX 0x02 /* 80960Cx instruction */
+#define I_DEC 0x04 /* Decimal instruction */
+#define I_FP 0x08 /* Floating point instruction */
+#define I_KX 0x10 /* 80960Kx instruction */
+#define I_MIL 0x20 /* Military instruction */
+#define I_CASIM 0x40 /* CA simulator instruction */
+#define I_CX2 0x80 /* Cx/Jx/Hx instructions */
+#define I_JX 0x100 /* Jx/Hx instruction */
+#define I_HX 0x200 /* Hx instructions */
+
+/******************************************************************************
+ *
+ * TABLE OF i960 INSTRUCTION DESCRIPTIONS
+ *
+ ******************************************************************************/
+
+const struct i960_opcode i960_opcodes[] = {
+
+ /* if a CTRL instruction has an operand, it's always a displacement */
+
+ /* callj default=='call' */
+ { 0x09000000, "callj", I_BASE, CALLJ, 1, { 0, 0, 0 } },
+ { 0x08000000, "b", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x09000000, "call", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x0a000000, "ret", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x0b000000, "bal", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x10000000, "bno", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* bf same as bno */
+ { 0x10000000, "bf", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* bru same as bno */
+ { 0x10000000, "bru", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x11000000, "bg", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* brg same as bg */
+ { 0x11000000, "brg", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x12000000, "be", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* bre same as be */
+ { 0x12000000, "bre", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x13000000, "bge", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* brge same as bge */
+ { 0x13000000, "brge", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x14000000, "bl", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* brl same as bl */
+ { 0x14000000, "brl", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x15000000, "bne", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* brlg same as bne */
+ { 0x15000000, "brlg", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x16000000, "ble", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* brle same as ble */
+ { 0x16000000, "brle", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x17000000, "bo", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* bt same as bo */
+ { 0x17000000, "bt", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ /* bro same as bo */
+ { 0x17000000, "bro", I_BASE, CTRL, 1, { 0, 0, 0 } },
+ { 0x18000000, "faultno", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ /* faultf same as faultno */
+ { 0x18000000, "faultf", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x19000000, "faultg", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x1a000000, "faulte", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x1b000000, "faultge", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x1c000000, "faultl", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x1d000000, "faultne", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x1e000000, "faultle", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ { 0x1f000000, "faulto", I_BASE, CTRL, 0, { 0, 0, 0 } },
+ /* faultt syn for faulto */
+ { 0x1f000000, "faultt", I_BASE, CTRL, 0, { 0, 0, 0 } },
+
+ { 0x01000000, "syscall", I_CASIM,CTRL, 0, { 0, 0, 0 } },
+
+ /* If a COBR (or COJ) has 3 operands, the last one is always a
+ * displacement and does not appear explicitly in the table.
+ */
+
+ { 0x20000000, "testno", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x21000000, "testg", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x22000000, "teste", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x23000000, "testge", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x24000000, "testl", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x25000000, "testne", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x26000000, "testle", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x27000000, "testo", I_BASE, COBR, 1, { R, 0, 0 } },
+ { 0x30000000, "bbc", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x31000000, "cmpobg", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x32000000, "cmpobe", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x33000000, "cmpobge", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x34000000, "cmpobl", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x35000000, "cmpobne", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x36000000, "cmpoble", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x37000000, "bbs", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x38000000, "cmpibno", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x39000000, "cmpibg", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x3a000000, "cmpibe", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x3b000000, "cmpibge", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x3c000000, "cmpibl", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x3d000000, "cmpibne", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x3e000000, "cmpible", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x3f000000, "cmpibo", I_BASE, COBR, 3, { RL, RS, 0 } },
+ { 0x31000000, "cmpojg", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x32000000, "cmpoje", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x33000000, "cmpojge", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x34000000, "cmpojl", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x35000000, "cmpojne", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x36000000, "cmpojle", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x38000000, "cmpijno", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x39000000, "cmpijg", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x3a000000, "cmpije", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x3b000000, "cmpijge", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x3c000000, "cmpijl", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x3d000000, "cmpijne", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x3e000000, "cmpijle", I_BASE, COJ, 3, { RL, RS, 0 } },
+ { 0x3f000000, "cmpijo", I_BASE, COJ, 3, { RL, RS, 0 } },
+
+ { 0x80000000, "ldob", I_BASE, MEM1, 2, { M, R, 0 } },
+ { 0x82000000, "stob", I_BASE, MEM1, 2, { R, M, 0 } },
+ { 0x84000000, "bx", I_BASE, MEM1, 1, { M, 0, 0 } },
+ { 0x85000000, "balx", I_BASE, MEM1, 2, { M, R, 0 } },
+ { 0x86000000, "callx", I_BASE, MEM1, 1, { M, 0, 0 } },
+ { 0x88000000, "ldos", I_BASE, MEM2, 2, { M, R, 0 } },
+ { 0x8a000000, "stos", I_BASE, MEM2, 2, { R, M, 0 } },
+ { 0x8c000000, "lda", I_BASE, MEM1, 2, { M, R, 0 } },
+ { 0x90000000, "ld", I_BASE, MEM4, 2, { M, R, 0 } },
+ { 0x92000000, "st", I_BASE, MEM4, 2, { R, M, 0 } },
+ { 0x98000000, "ldl", I_BASE, MEM8, 2, { M, R2, 0 } },
+ { 0x9a000000, "stl", I_BASE, MEM8, 2, { R2, M, 0 } },
+ { 0xa0000000, "ldt", I_BASE, MEM12, 2, { M, R4, 0 } },
+ { 0xa2000000, "stt", I_BASE, MEM12, 2, { R4, M, 0 } },
+ { 0xb0000000, "ldq", I_BASE, MEM16, 2, { M, R4, 0 } },
+ { 0xb2000000, "stq", I_BASE, MEM16, 2, { R4, M, 0 } },
+ { 0xc0000000, "ldib", I_BASE, MEM1, 2, { M, R, 0 } },
+ { 0xc2000000, "stib", I_BASE, MEM1, 2, { R, M, 0 } },
+ { 0xc8000000, "ldis", I_BASE, MEM2, 2, { M, R, 0 } },
+ { 0xca000000, "stis", I_BASE, MEM2, 2, { R, M, 0 } },
+
+ { R_3(0x580), "notbit", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x581), "and", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x582), "andnot", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x583), "setbit", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x584), "notand", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x586), "xor", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x587), "or", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x588), "nor", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x589), "xnor", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_2D(0x58a), "not", I_BASE, REG, 2, { RSL,RS, 0 } },
+ { R_3(0x58b), "ornot", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x58c), "clrbit", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x58d), "notor", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x58e), "nand", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x58f), "alterbit", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x590), "addo", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x591), "addi", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x592), "subo", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x593), "subi", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x598), "shro", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x59a), "shrdi", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x59b), "shri", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x59c), "shlo", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x59d), "rotate", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x59e), "shli", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_2(0x5a0), "cmpo", I_BASE, REG, 2, { RSL,RSL, 0 } },
+ { R_2(0x5a1), "cmpi", I_BASE, REG, 2, { RSL,RSL, 0 } },
+ { R_2(0x5a2), "concmpo", I_BASE, REG, 2, { RSL,RSL, 0 } },
+ { R_2(0x5a3), "concmpi", I_BASE, REG, 2, { RSL,RSL, 0 } },
+ { R_3(0x5a4), "cmpinco", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x5a5), "cmpinci", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x5a6), "cmpdeco", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x5a7), "cmpdeci", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_2(0x5ac), "scanbyte", I_BASE, REG, 2, { RSL,RSL, 0 } },
+ { R_2(0x5ae), "chkbit", I_BASE, REG, 2, { RSL,RSL, 0 } },
+ { R_3(0x5b0), "addc", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x5b2), "subc", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_2D(0x5cc), "mov", I_BASE, REG, 2, { RSL,RS, 0 } },
+ { R_2D(0x5dc), "movl", I_BASE, REG, 2, { RL2,R2, 0 } },
+ { R_2D(0x5ec), "movt", I_BASE, REG, 2, { RL4,R4, 0 } },
+ { R_2D(0x5fc), "movq", I_BASE, REG, 2, { RL4,R4, 0 } },
+ { R_3(0x610), "atmod", I_BASE, REG, 3, { RS, RSL,R } },
+ { R_3(0x612), "atadd", I_BASE, REG, 3, { RS, RSL,RS } },
+ { R_2D(0x640), "spanbit", I_BASE, REG, 2, { RSL,RS, 0 } },
+ { R_2D(0x641), "scanbit", I_BASE, REG, 2, { RSL,RS, 0 } },
+ { R_3(0x645), "modac", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x650), "modify", I_BASE, REG, 3, { RSL,RSL,R } },
+ { R_3(0x651), "extract", I_BASE, REG, 3, { RSL,RSL,R } },
+ { R_3(0x654), "modtc", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x655), "modpc", I_BASE, REG, 3, { RSL,RSL,R } },
+ { R_1(0x660), "calls", I_BASE, REG, 1, { RSL, 0, 0 } },
+ { R_0(0x66b), "mark", I_BASE, REG, 0, { 0, 0, 0 } },
+ { R_0(0x66c), "fmark", I_BASE, REG, 0, { 0, 0, 0 } },
+ { R_0(0x66d), "flushreg", I_BASE, REG, 0, { 0, 0, 0 } },
+ { R_0(0x66f), "syncf", I_BASE, REG, 0, { 0, 0, 0 } },
+ { R_3(0x670), "emul", I_BASE, REG, 3, { RSL,RSL,R2 } },
+ { R_3(0x671), "ediv", I_BASE, REG, 3, { RSL,RL2,RS } },
+ { R_2D(0x672), "cvtadr", I_CASIM,REG, 2, { RL, R2, 0 } },
+ { R_3(0x701), "mulo", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x708), "remo", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x70b), "divo", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x741), "muli", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x748), "remi", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x749), "modi", I_BASE, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x74b), "divi", I_BASE, REG, 3, { RSL,RSL,RS } },
+
+ /* Floating-point instructions */
+
+ { R_2D(0x674), "cvtir", I_FP, REG, 2, { RL, F, 0 } },
+ { R_2D(0x675), "cvtilr", I_FP, REG, 2, { RL, F, 0 } },
+ { R_3(0x676), "scalerl", I_FP, REG, 3, { RL, FL2,F2 } },
+ { R_3(0x677), "scaler", I_FP, REG, 3, { RL, FL, F } },
+ { R_3(0x680), "atanr", I_FP, REG, 3, { FL, FL, F } },
+ { R_3(0x681), "logepr", I_FP, REG, 3, { FL, FL, F } },
+ { R_3(0x682), "logr", I_FP, REG, 3, { FL, FL, F } },
+ { R_3(0x683), "remr", I_FP, REG, 3, { FL, FL, F } },
+ { R_2(0x684), "cmpor", I_FP, REG, 2, { FL, FL, 0 } },
+ { R_2(0x685), "cmpr", I_FP, REG, 2, { FL, FL, 0 } },
+ { R_2D(0x688), "sqrtr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_2D(0x689), "expr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_2D(0x68a), "logbnr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_2D(0x68b), "roundr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_2D(0x68c), "sinr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_2D(0x68d), "cosr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_2D(0x68e), "tanr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_1(0x68f), "classr", I_FP, REG, 1, { FL, 0, 0 } },
+ { R_3(0x690), "atanrl", I_FP, REG, 3, { FL2,FL2,F2 } },
+ { R_3(0x691), "logeprl", I_FP, REG, 3, { FL2,FL2,F2 } },
+ { R_3(0x692), "logrl", I_FP, REG, 3, { FL2,FL2,F2 } },
+ { R_3(0x693), "remrl", I_FP, REG, 3, { FL2,FL2,F2 } },
+ { R_2(0x694), "cmporl", I_FP, REG, 2, { FL2,FL2, 0 } },
+ { R_2(0x695), "cmprl", I_FP, REG, 2, { FL2,FL2, 0 } },
+ { R_2D(0x698), "sqrtrl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_2D(0x699), "exprl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_2D(0x69a), "logbnrl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_2D(0x69b), "roundrl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_2D(0x69c), "sinrl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_2D(0x69d), "cosrl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_2D(0x69e), "tanrl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_1(0x69f), "classrl", I_FP, REG, 1, { FL2, 0, 0 } },
+ { R_2D(0x6c0), "cvtri", I_FP, REG, 2, { FL, R, 0 } },
+ { R_2D(0x6c1), "cvtril", I_FP, REG, 2, { FL, R2, 0 } },
+ { R_2D(0x6c2), "cvtzri", I_FP, REG, 2, { FL, R, 0 } },
+ { R_2D(0x6c3), "cvtzril", I_FP, REG, 2, { FL, R2, 0 } },
+ { R_2D(0x6c9), "movr", I_FP, REG, 2, { FL, F, 0 } },
+ { R_2D(0x6d9), "movrl", I_FP, REG, 2, { FL2,F2, 0 } },
+ { R_2D(0x6e1), "movre", I_FP, REG, 2, { FL4,F4, 0 } },
+ { R_3(0x6e2), "cpysre", I_FP, REG, 3, { FL4,FL4,F4 } },
+ { R_3(0x6e3), "cpyrsre", I_FP, REG, 3, { FL4,FL4,F4 } },
+ { R_3(0x78b), "divr", I_FP, REG, 3, { FL, FL, F } },
+ { R_3(0x78c), "mulr", I_FP, REG, 3, { FL, FL, F } },
+ { R_3(0x78d), "subr", I_FP, REG, 3, { FL, FL, F } },
+ { R_3(0x78f), "addr", I_FP, REG, 3, { FL, FL, F } },
+ { R_3(0x79b), "divrl", I_FP, REG, 3, { FL2,FL2,F2 } },
+ { R_3(0x79c), "mulrl", I_FP, REG, 3, { FL2,FL2,F2 } },
+ { R_3(0x79d), "subrl", I_FP, REG, 3, { FL2,FL2,F2 } },
+ { R_3(0x79f), "addrl", I_FP, REG, 3, { FL2,FL2,F2 } },
+
+ /* These are the floating point branch instructions. Each actually
+ * generates 2 branch instructions: the first a CTRL instruction with
+ * the indicated opcode, and the second a 'bno'.
+ */
+
+ { 0x12000000, "brue", I_FP, FBRA, 1, { 0, 0, 0 } },
+ { 0x11000000, "brug", I_FP, FBRA, 1, { 0, 0, 0 } },
+ { 0x13000000, "bruge", I_FP, FBRA, 1, { 0, 0, 0 } },
+ { 0x14000000, "brul", I_FP, FBRA, 1, { 0, 0, 0 } },
+ { 0x16000000, "brule", I_FP, FBRA, 1, { 0, 0, 0 } },
+ { 0x15000000, "brulg", I_FP, FBRA, 1, { 0, 0, 0 } },
+
+
+ /* Decimal instructions */
+
+ { R_3(0x642), "daddc", I_DEC, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x643), "dsubc", I_DEC, REG, 3, { RSL,RSL,RS } },
+ { R_2D(0x644), "dmovt", I_DEC, REG, 2, { RSL,RS, 0 } },
+
+
+ /* KX extensions */
+
+ { R_2(0x600), "synmov", I_KX, REG, 2, { R, R, 0 } },
+ { R_2(0x601), "synmovl", I_KX, REG, 2, { R, R, 0 } },
+ { R_2(0x602), "synmovq", I_KX, REG, 2, { R, R, 0 } },
+ { R_2D(0x615), "synld", I_KX, REG, 2, { R, R, 0 } },
+
+
+ /* MC extensions */
+
+ { R_3(0x603), "cmpstr", I_MIL, REG, 3, { R, R, RL } },
+ { R_3(0x604), "movqstr", I_MIL, REG, 3, { R, R, RL } },
+ { R_3(0x605), "movstr", I_MIL, REG, 3, { R, R, RL } },
+ { R_2D(0x613), "inspacc", I_MIL, REG, 2, { R, R, 0 } },
+ { R_2D(0x614), "ldphy", I_MIL, REG, 2, { R, R, 0 } },
+ { R_3(0x617), "fill", I_MIL, REG, 3, { R, RL, RL } },
+ { R_2D(0x646), "condrec", I_MIL, REG, 2, { R, R, 0 } },
+ { R_2D(0x656), "receive", I_MIL, REG, 2, { R, R, 0 } },
+ { R_3(0x662), "send", I_MIL, REG, 3, { R, RL, R } },
+ { R_1(0x663), "sendserv", I_MIL, REG, 1, { R, 0, 0 } },
+ { R_1(0x664), "resumprcs", I_MIL, REG, 1, { R, 0, 0 } },
+ { R_1(0x665), "schedprcs", I_MIL, REG, 1, { R, 0, 0 } },
+ { R_0(0x666), "saveprcs", I_MIL, REG, 0, { 0, 0, 0 } },
+ { R_1(0x668), "condwait", I_MIL, REG, 1, { R, 0, 0 } },
+ { R_1(0x669), "wait", I_MIL, REG, 1, { R, 0, 0 } },
+ { R_1(0x66a), "signal", I_MIL, REG, 1, { R, 0, 0 } },
+ { R_1D(0x673), "ldtime", I_MIL, REG, 1, { R2, 0, 0 } },
+
+
+ /* CX extensions */
+
+ { R_3(0x5d8), "eshro", I_CX2, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x630), "sdma", I_CX, REG, 3, { RSL,RSL,RL } },
+ { R_3(0x631), "udma", I_CX, REG, 0, { 0, 0, 0 } },
+ { R_3(0x659), "sysctl", I_CX2, REG, 3, { RSL,RSL,RL } },
+
+
+ /* Jx extensions. */
+ { R_3(0x780), "addono", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x790), "addog", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7a0), "addoe", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7b0), "addoge", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7c0), "addol", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7d0), "addone", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7e0), "addole", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7f0), "addoo", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x781), "addino", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x791), "addig", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7a1), "addie", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7b1), "addige", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7c1), "addil", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7d1), "addine", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7e1), "addile", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7f1), "addio", I_JX, REG, 3, { RSL,RSL,RS } },
+
+ { R_2D(0x5ad), "bswap", I_JX, REG, 2, { RSL, RS, 0 } },
+
+ { R_2(0x594), "cmpob", I_JX, REG, 2, { RSL,RSL, 0 } },
+ { R_2(0x595), "cmpib", I_JX, REG, 2, { RSL,RSL, 0 } },
+ { R_2(0x596), "cmpos", I_JX, REG, 2, { RSL,RSL, 0 } },
+ { R_2(0x597), "cmpis", I_JX, REG, 2, { RSL,RSL, 0 } },
+
+ { R_3(0x784), "selno", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x794), "selg", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7a4), "sele", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7b4), "selge", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7c4), "sell", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7d4), "selne", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7e4), "selle", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7f4), "selo", I_JX, REG, 3, { RSL,RSL,RS } },
+
+ { R_3(0x782), "subono", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x792), "subog", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7a2), "suboe", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7b2), "suboge", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7c2), "subol", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7d2), "subone", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7e2), "subole", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7f2), "suboo", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x783), "subino", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x793), "subig", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7a3), "subie", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7b3), "subige", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7c3), "subil", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7d3), "subine", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7e3), "subile", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_3(0x7f3), "subio", I_JX, REG, 3, { RSL,RSL,RS } },
+
+ { R_3(0x65c), "dcctl", I_JX, REG, 3, { RSL,RSL,RL } },
+ { R_3(0x65b), "icctl", I_JX, REG, 3, { RSL,RSL,RS } },
+ { R_2D(0x658), "intctl", I_JX, REG, 2, { RSL, RS, 0 } },
+ { R_0(0x5b4), "intdis", I_JX, REG, 0, { 0, 0, 0 } },
+ { R_0(0x5b5), "inten", I_JX, REG, 0, { 0, 0, 0 } },
+ { R_0(0x65d), "halt", I_JX, REG, 0, { 0, 0, 0 } },
+
+ /* Hx extensions. */
+ { 0xac000000, "dcinva", I_HX, MEM1, 1, { M, 0, 0 } },
+
+ /* END OF TABLE */
+
+ { 0, NULL, 0, 0, 0, { 0, 0, 0 } }
+};
+
+ /* end of i960-opcode.h */
diff --git a/contrib/gdb/include/opcode/m68k.h b/contrib/gdb/include/opcode/m68k.h
new file mode 100644
index 0000000..e0b371c
--- /dev/null
+++ b/contrib/gdb/include/opcode/m68k.h
@@ -0,0 +1,297 @@
+/* Opcode table header for m680[01234]0/m6888[12]/m68851.
+ Copyright 1989, 1991, 1992, 1993, 1994, 1995 Free Software Foundation.
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+will be useful, but WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this file; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+/* These are used as bit flags for the arch field in the m68k_opcode
+ structure. */
+#define _m68k_undef 0
+#define m68000 0x001
+#define m68008 m68000 /* synonym for -m68000. otherwise unused. */
+#define m68010 0x002
+#define m68020 0x004
+#define m68030 0x008
+#define m68ec030 m68030 /* similar enough to -m68030 to ignore differences;
+ gas will deal with the few differences. */
+#define m68040 0x010
+/* there is no 68050 */
+#define m68060 0x020
+#define m68881 0x040
+#define m68882 m68881 /* synonym for -m68881. otherwise unused. */
+#define m68851 0x080
+#define cpu32 0x100 /* e.g., 68332 */
+
+ /* handy aliases */
+#define m68040up (m68040 | m68060)
+#define m68030up (m68030 | m68040up)
+#define m68020up (m68020 | m68030up)
+#define m68010up (m68010 | cpu32 | m68020up)
+#define m68000up (m68000 | m68010up)
+
+#define mfloat (m68881 | m68882 | m68040 | m68060)
+#define mmmu (m68851 | m68030 | m68040 | m68060)
+
+/* The structure used to hold information for an opcode. */
+
+struct m68k_opcode
+{
+ /* The opcode name. */
+ const char *name;
+ /* The opcode itself. */
+ unsigned long opcode;
+ /* The mask used by the disassembler. */
+ unsigned long match;
+ /* The arguments. */
+ const char *args;
+ /* The architectures which support this opcode. */
+ unsigned int arch;
+};
+
+/* The structure used to hold information for an opcode alias. */
+
+struct m68k_opcode_alias
+{
+ /* The alias name. */
+ const char *alias;
+ /* The instruction for which this is an alias. */
+ const char *primary;
+};
+
+/* We store four bytes of opcode for all opcodes because that is the
+ most any of them need. The actual length of an instruction is
+ always at least 2 bytes, and is as much longer as necessary to hold
+ the operands it has.
+
+ The match field is a mask saying which bits must match particular
+ opcode in order for an instruction to be an instance of that
+ opcode.
+
+ The args field is a string containing two characters for each
+ operand of the instruction. The first specifies the kind of
+ operand; the second, the place it is stored. */
+
+/* Kinds of operands:
+ Characters used: AaBCcDdFfIJkLlMOQRrSsTtUVWXYZ0123|*~%;@!&$?/#^+-
+
+ D data register only. Stored as 3 bits.
+ A address register only. Stored as 3 bits.
+ a address register indirect only. Stored as 3 bits.
+ R either kind of register. Stored as 4 bits.
+ r either kind of register indirect only. Stored as 4 bits.
+ At the moment, used only for cas2 instruction.
+ F floating point coprocessor register only. Stored as 3 bits.
+ O an offset (or width): immediate data 0-31 or data register.
+ Stored as 6 bits in special format for BF... insns.
+ + autoincrement only. Stored as 3 bits (number of the address register).
+ - autodecrement only. Stored as 3 bits (number of the address register).
+ Q quick immediate data. Stored as 3 bits.
+ This matches an immediate operand only when value is in range 1 .. 8.
+ M moveq immediate data. Stored as 8 bits.
+ This matches an immediate operand only when value is in range -128..127
+ T trap vector immediate data. Stored as 4 bits.
+
+ k K-factor for fmove.p instruction. Stored as a 7-bit constant or
+ a three bit register offset, depending on the field type.
+
+ # immediate data. Stored in special places (b, w or l)
+ which say how many bits to store.
+ ^ immediate data for floating point instructions. Special places
+ are offset by 2 bytes from '#'...
+ B pc-relative address, converted to an offset
+ that is treated as immediate data.
+ d displacement and register. Stores the register as 3 bits
+ and stores the displacement in the entire second word.
+
+ C the CCR. No need to store it; this is just for filtering validity.
+ S the SR. No need to store, just as with CCR.
+ U the USP. No need to store, just as with CCR.
+
+ I Coprocessor ID. Not printed if 1. The Coprocessor ID is always
+ extracted from the 'd' field of word one, which means that an extended
+ coprocessor opcode can be skipped using the 'i' place, if needed.
+
+ s System Control register for the floating point coprocessor.
+
+ J Misc register for movec instruction, stored in 'j' format.
+ Possible values:
+ 0x000 SFC Source Function Code reg [60, 40, 30, 20, 10]
+ 0x001 DFC Data Function Code reg [60, 40, 30, 20, 10]
+ 0x002 CACR Cache Control Register [60, 40, 30, 20]
+ 0x003 TC MMU Translation Control [60, 40]
+ 0x004 ITT0 Instruction Transparent
+ Translation reg 0 [60, 40]
+ 0x005 ITT1 Instruction Transparent
+ Translation reg 1 [60, 40]
+ 0x006 DTT0 Data Transparent
+ Translation reg 0 [60, 40]
+ 0x007 DTT1 Data Transparent
+ Translation reg 1 [60, 40]
+ 0x008 BUSCR Bus Control Register [60]
+ 0x800 USP User Stack Pointer [60, 40, 30, 20, 10]
+ 0x801 VBR Vector Base reg [60, 40, 30, 20, 10]
+ 0x802 CAAR Cache Address Register [ 30, 20]
+ 0x803 MSP Master Stack Pointer [ 40, 30, 20]
+ 0x804 ISP Interrupt Stack Pointer [ 40, 30, 20]
+ 0x805 MMUSR MMU Status reg [ 40]
+ 0x806 URP User Root Pointer [60, 40]
+ 0x807 SRP Supervisor Root Pointer [60, 40]
+ 0x808 PCR Processor Configuration reg [60]
+
+ L Register list of the type d0-d7/a0-a7 etc.
+ (New! Improved! Can also hold fp0-fp7, as well!)
+ The assembler tries to see if the registers match the insn by
+ looking at where the insn wants them stored.
+
+ l Register list like L, but with all the bits reversed.
+ Used for going the other way. . .
+
+ c cache identifier which may be "nc" for no cache, "ic"
+ for instruction cache, "dc" for data cache, or "bc"
+ for both caches. Used in cinv and cpush. Always
+ stored in position "d".
+
+ The remainder are all stored as 6 bits using an address mode and a
+ register number; they differ in which addressing modes they match.
+
+ * all (modes 0-6,7.*)
+ ~ alterable memory (modes 2-6,7.0,7.1)
+ (not 0,1,7.~)
+ % alterable (modes 0-6,7.0,7.1)(not 7.~)
+ ; data (modes 0,2-6,7.*)(not 1)
+ @ data, but not immediate (modes 0,2-6,7.? ? ?)
+ (not 1,7.?)
+ This may really be ;,
+ the 68020 book says it is
+ ! control (modes 2,5,6,7.*-)
+ (not 0,1,3,4,7.4)
+ & alterable control (modes 2,5,6,7.0,7.1)
+ (not 0,1,7.? ? ?)
+ $ alterable data (modes 0,2-6,7.0,7.1)
+ (not 1,7.~)
+ ? alterable control, or data register (modes 0,2,5,6,7.0,7.1)
+ (not 1,3,4,7.~)
+ / control, or data register (modes 0,2,5,6,7.0,7.1,7.2,7.3)
+ (not 1,3,4,7.4)
+ ` control, plus pre-dec, not simple indir. (modes 4,5,6,7.*-)
+ (not 0,1,2,3,7.4) */
+
+/* For the 68851: */
+/*
+ I didn't use much imagination in choosing the
+ following codes, so many of them aren't very
+ mnemonic. -rab
+
+ 0 32 bit pmmu register
+ Possible values:
+ 000 TC Translation Control Register (68030, 68851)
+
+ 1 16 bit pmmu register
+ 111 AC Access Control (68851)
+
+ 2 8 bit pmmu register
+ 100 CAL Current Access Level (68851)
+ 101 VAL Validate Access Level (68851)
+ 110 SCC Stack Change Control (68851)
+
+ 3 68030-only pmmu registers (32 bit)
+ 010 TT0 Transparent Translation reg 0
+ (aka Access Control reg 0 -- AC0 -- on 68ec030)
+ 011 TT1 Transparent Translation reg 1
+ (aka Access Control reg 1 -- AC1 -- on 68ec030)
+
+ W wide pmmu registers
+ Possible values:
+ 001 DRP Dma Root Pointer (68851)
+ 010 SRP Supervisor Root Pointer (68030, 68851)
+ 011 CRP Cpu Root Pointer (68030, 68851)
+
+ f function code register (68030, 68851)
+ 0 SFC
+ 1 DFC
+
+ V VAL register only (68851)
+
+ X BADx, BACx (16 bit)
+ 100 BAD Breakpoint Acknowledge Data (68851)
+ 101 BAC Breakpoint Acknowledge Control (68851)
+
+ Y PSR (68851) (MMUSR on 68030) (ACUSR on 68ec030)
+ Z PCSR (68851)
+
+ | memory (modes 2-6, 7.*)
+
+ t address test level (68030 only)
+ Stored as 3 bits, range 0-7.
+ Also used for breakpoint instruction now.
+
+*/
+
+/* Places to put an operand, for non-general operands:
+ s source, low bits of first word.
+ d dest, shifted 9 in first word
+ 1 second word, shifted 12
+ 2 second word, shifted 6
+ 3 second word, shifted 0
+ 4 third word, shifted 12
+ 5 third word, shifted 6
+ 6 third word, shifted 0
+ 7 second word, shifted 7
+ 8 second word, shifted 10
+ 9 second word, shifted 5
+ D store in both place 1 and place 3; for divul and divsl.
+ B first word, low byte, for branch displacements
+ W second word (entire), for branch displacements
+ L second and third words (entire), for branch displacements
+ (also overloaded for move16)
+ b second word, low byte
+ w second word (entire) [variable word/long branch offset for dbra]
+ W second word (entire) (must be signed 16 bit value)
+ l second and third word (entire)
+ g variable branch offset for bra and similar instructions.
+ The place to store depends on the magnitude of offset.
+ t store in both place 7 and place 8; for floating point operations
+ c branch offset for cpBcc operations.
+ The place to store is word two if bit six of word one is zero,
+ and words two and three if bit six of word one is one.
+ i Increment by two, to skip over coprocessor extended operands. Only
+ works with the 'I' format.
+ k Dynamic K-factor field. Bits 6-4 of word 2, used as a register number.
+ Also used for dynamic fmovem instruction.
+ C floating point coprocessor constant - 7 bits. Also used for static
+ K-factors...
+ j Movec register #, stored in 12 low bits of second word.
+
+ Places to put operand, for general operands:
+ d destination, shifted 6 bits in first word
+ b source, at low bit of first word, and immediate uses one byte
+ w source, at low bit of first word, and immediate uses two bytes
+ l source, at low bit of first word, and immediate uses four bytes
+ s source, at low bit of first word.
+ Used sometimes in contexts where immediate is not allowed anyway.
+ f single precision float, low bit of 1st word, immediate uses 4 bytes
+ F double precision float, low bit of 1st word, immediate uses 8 bytes
+ x extended precision float, low bit of 1st word, immediate uses 12 bytes
+ p packed float, low bit of 1st word, immediate uses 12 bytes
+*/
+
+extern const struct m68k_opcode m68k_opcodes[];
+extern const struct m68k_opcode_alias m68k_opcode_aliases[];
+
+extern const int m68k_numopcodes, m68k_numaliases;
+
+/* end of m68k-opcode.h */
diff --git a/contrib/gdb/include/opcode/m88k.h b/contrib/gdb/include/opcode/m88k.h
new file mode 100644
index 0000000..a17fa03
--- /dev/null
+++ b/contrib/gdb/include/opcode/m88k.h
@@ -0,0 +1,923 @@
+/* Table of opcodes for the motorola 88k family.
+ Copyright 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * Disassembler Instruction Table
+ *
+ * The first field of the table is the opcode field. If an opcode
+ * is specified which has any non-opcode bits on, a system error
+ * will occur when the system attempts the install it into the
+ * instruction table. The second parameter is a pointer to the
+ * instruction mnemonic. Each operand is specified by offset, width,
+ * and type. The offset is the bit number of the least significant
+ * bit of the operand with bit 0 being the least significant bit of
+ * the instruction. The width is the number of bits used to specify
+ * the operand. The type specifies the output format to be used for
+ * the operand. The valid formats are: register, register indirect,
+ * hex constant, and bit field specification. The last field is a
+ * pointer to the next instruction in the linked list. These pointers
+ * are initialized by init_disasm().
+ *
+ * Structure Format
+ *
+ * struct INSTAB {
+ * UPINT opcode;
+ * char *mnemonic;
+ * struct OPSPEC op1,op2,op3;
+ * struct SIM_FLAGS flgs;
+ * struct INSTAB *next;
+ * }
+ *
+ * struct OPSPEC {
+ * UPINT offset:5;
+ * UPINT width:6;
+ * UPINT type:5;
+ * }
+ *
+ * Revision History
+ *
+ * Revision 1.0 11/08/85 Creation date
+ * 1.1 02/05/86 Updated instruction mnemonic table MD
+ * 1.2 06/16/86 Updated SIM_FLAGS for floating point
+ * 1.3 09/20/86 Updated for new encoding
+ * 05/11/89 R. Trawick adapted from Motorola disassembler
+ */
+
+#include <stdio.h>
+
+
+/*
+ * This file contains the structures and constants needed to build the M88000
+ * simulator. It is the main include file, containing all the
+ * structures, macros and definitions except for the floating point
+ * instruction set.
+ */
+
+/*
+ * The following flag informs the Simulator as to what type of byte ordering
+ * will be used. For instance, a BOFLAG = 1 indicates a DEC VAX and IBM type
+ * of ordering shall be used.
+*/
+
+/* # define BOFLAG 1 */ /* BYTE ORDERING FLAG */
+
+/* define the number of bits in the primary opcode field of the instruction,
+ * the destination field, the source 1 and source 2 fields.
+ */
+# define OP 8 /* size of opcode field */
+# define DEST 6 /* size of destination */
+# define SOURCE1 6 /* size of source1 */
+# define SOURCE2 6 /* size of source2 */
+
+# define REGs 32 /* number of registers */
+
+# define WORD long
+# define FLAG unsigned
+# define STATE short
+
+# define TRUE 1
+# define FALSE 0
+
+# define READ 0
+# define WRITE 1
+
+/* The next four equates define the priorities that the various classes
+ * of instructions have regarding writing results back into registers and
+ * signalling exceptions.
+ */
+/* PMEM is also defined in <sys/param.h> on Delta 88's. Sigh! */
+#undef PMEM
+
+# define PINT 0 /* Integer Priority */
+# define PFLT 1 /* Floating Point Priority */
+# define PMEM 2 /* Memory Priority */
+# define NA 3 /* Not Applicable, instruction doesnt write to regs */
+# define HIPRI 3 /* highest of these priorities */
+
+/* The instruction registers are an artificial mechanism to speed up
+ * simulator execution. In the real processor, an instruction register
+ * is 32 bits wide. In the simulator, the 32 bit instruction is kept in
+ * a structure field called rawop, and the instruction is partially decoded,
+ * and split into various fields and flags which make up the other fields
+ * of the structure.
+ * The partial decode is done when the instructions are initially loaded
+ * into simulator memory. The simulator code memory is not an array of
+ * 32 bit words, but is an array of instruction register structures.
+ * Yes this wastes memory, but it executes much quicker.
+ */
+
+struct IR_FIELDS {
+ unsigned op:OP,
+ dest: DEST,
+ src1: SOURCE1,
+ src2: SOURCE2;
+ int ltncy,
+ extime,
+ wb_pri; /* writeback priority */
+ unsigned imm_flags:2,/* immediate size */
+ rs1_used:1, /* register source 1 used */
+ rs2_used:1, /* register source 2 used */
+ rsd_used:1, /* register source/dest. used */
+ c_flag:1, /* complement */
+ u_flag:1, /* upper half word */
+ n_flag:1, /* execute next */
+ wb_flag:1, /* uses writeback slot */
+ dest_64:1, /* dest size */
+ s1_64:1, /* source 1 size */
+ s2_64:1, /* source 2 size */
+ scale_flag:1, /* scaled register */
+ brk_flg:1;
+ };
+
+struct mem_segs {
+ struct mem_wrd *seg; /* pointer (returned by calloc) to segment */
+ unsigned long baseaddr; /* base load address from file headers */
+ unsigned long endaddr; /* Ending address of segment */
+ int flags; /* segment control flags (none defined 12/5/86) */
+};
+
+#define MAXSEGS (10) /* max number of segment allowed */
+#define MEMSEGSIZE (sizeof(struct mem_segs))/* size of mem_segs structure */
+
+
+#define BRK_RD (0x01) /* break on memory read */
+#define BRK_WR (0x02) /* break on memory write */
+#define BRK_EXEC (0x04) /* break on execution */
+#define BRK_CNT (0x08) /* break on terminal count */
+
+
+struct mem_wrd {
+ struct IR_FIELDS opcode; /* simulator instruction break down */
+ union {
+ unsigned long l; /* memory element break down */
+ unsigned short s[2];
+ unsigned char c[4];
+ } mem;
+};
+
+#define MEMWRDSIZE (sizeof(struct mem_wrd)) /* size of each 32 bit memory model */
+
+/* External declarations */
+
+extern struct mem_segs memory[];
+extern struct PROCESSOR m78000;
+
+struct PROCESSOR {
+ unsigned WORD
+ ip, /* execute instruction pointer */
+ vbr, /* vector base register */
+ psr; /* processor status register */
+
+ WORD S1bus, /* source 1 */
+ S2bus, /* source 2 */
+ Dbus, /* destination */
+ DAbus, /* data address bus */
+ ALU,
+ Regs[REGs], /* data registers */
+ time_left[REGs], /* max clocks before reg is available */
+ wb_pri[REGs], /* writeback priority of reg */
+ SFU0_regs[REGs], /* integer unit control regs */
+ SFU1_regs[REGs], /* floating point control regs */
+ Scoreboard[REGs],
+ Vbr;
+ unsigned WORD scoreboard,
+ Psw,
+ Tpsw;
+ FLAG jump_pending:1; /* waiting for a jump instr. */
+ };
+
+# define i26bit 1 /* size of immediate field */
+# define i16bit 2
+# define i10bit 3
+
+/* Definitions for fields in psr */
+
+# define mode 31
+# define rbo 30
+# define ser 29
+# define carry 28
+# define sf7m 11
+# define sf6m 10
+# define sf5m 9
+# define sf4m 8
+# define sf3m 7
+# define sf2m 6
+# define sf1m 5
+# define mam 4
+# define inm 3
+# define exm 2
+# define trm 1
+# define ovfm 0
+
+#define MODEMASK (1<<(mode-1))
+# define SILENT 0 /* simulate without output to crt */
+# define VERBOSE 1 /* simulate in verbose mode */
+# define PR_INSTR 2 /* only print instructions */
+
+# define RESET 16 /* reset phase */
+
+# define PHASE1 0 /* data path phases */
+# define PHASE2 1
+
+/* the 1 clock operations */
+
+# define ADDU 1
+# define ADDC 2
+# define ADDUC 3
+# define ADD 4
+
+# define SUBU ADD+1
+# define SUBB ADD+2
+# define SUBUB ADD+3
+# define SUB ADD+4
+
+# define AND_ ADD+5
+# define OR ADD+6
+# define XOR ADD+7
+# define CMP ADD+8
+
+/* the LOADS */
+
+# define LDAB CMP+1
+# define LDAH CMP+2
+# define LDA CMP+3
+# define LDAD CMP+4
+
+# define LDB LDAD+1
+# define LDH LDAD+2
+# define LD LDAD+3
+# define LDD LDAD+4
+# define LDBU LDAD+5
+# define LDHU LDAD+6
+
+/* the STORES */
+
+# define STB LDHU+1
+# define STH LDHU+2
+# define ST LDHU+3
+# define STD LDHU+4
+
+/* the exchange */
+
+# define XMEMBU LDHU+5
+# define XMEM LDHU+6
+
+/* the branches */
+# define JSR STD+1
+# define BSR STD+2
+# define BR STD+3
+# define JMP STD+4
+# define BB1 STD+5
+# define BB0 STD+6
+# define RTN STD+7
+# define BCND STD+8
+
+/* the TRAPS */
+# define TB1 BCND+1
+# define TB0 BCND+2
+# define TCND BCND+3
+# define RTE BCND+4
+# define TBND BCND+5
+
+/* the MISC instructions */
+# define MUL TBND + 1
+# define DIV MUL +2
+# define DIVU MUL +3
+# define MASK MUL +4
+# define FF0 MUL +5
+# define FF1 MUL +6
+# define CLR MUL +7
+# define SET MUL +8
+# define EXT MUL +9
+# define EXTU MUL +10
+# define MAK MUL +11
+# define ROT MUL +12
+
+/* control register manipulations */
+
+# define LDCR ROT +1
+# define STCR ROT +2
+# define XCR ROT +3
+
+# define FLDCR ROT +4
+# define FSTCR ROT +5
+# define FXCR ROT +6
+
+
+# define NOP XCR +1
+
+/* floating point instructions */
+
+# define FADD NOP +1
+# define FSUB NOP +2
+# define FMUL NOP +3
+# define FDIV NOP +4
+# define FSQRT NOP +5
+# define FCMP NOP +6
+# define FIP NOP +7
+# define FLT NOP +8
+# define INT NOP +9
+# define NINT NOP +10
+# define TRNC NOP +11
+# define FLDC NOP +12
+# define FSTC NOP +13
+# define FXC NOP +14
+
+# define UEXT(src,off,wid) ((((unsigned int)(src))>>(off)) & ((1<<(wid)) - 1))
+# define SEXT(src,off,wid) (((((int)(src))<<(32-((off)+(wid)))) >>(32-(wid))) )
+# define MAKE(src,off,wid) \
+ ((((unsigned int)(src)) & ((1<<(wid)) - 1)) << (off))
+
+# define opword(n) (unsigned long) (memaddr->mem.l)
+
+/* Constants and Masks */
+
+#define SFU0 0x80000000
+#define SFU1 0x84000000
+#define SFU7 0x9c000000
+#define RRI10 0xf0000000
+#define RRR 0xf4000000
+#define SFUMASK 0xfc00ffe0
+#define RRRMASK 0xfc00ffe0
+#define RRI10MASK 0xfc00fc00
+#define DEFMASK 0xfc000000
+#define CTRL 0x0000f000
+#define CTRLMASK 0xfc00f800
+
+/* Operands types */
+
+enum operand_type {
+ HEX = 1,
+ REG = 2,
+ CONT = 3,
+ IND = 3,
+ BF = 4,
+ REGSC = 5 /* scaled register */,
+ CRREG = 6 /* control register */,
+ FCRREG = 7 /* floating point control register */,
+ PCREL = 8,
+ CONDMASK = 9,
+ XREG = 10, /* extended register */
+ DEC = 11, /* decimal */
+};
+
+/* Hashing Specification */
+
+#define HASHVAL 79
+
+/* Type definitions */
+
+typedef unsigned int UINT;
+
+/* Structure templates */
+
+#if never
+typedef struct {
+ unsigned int offset:5;
+ unsigned int width:6;
+ unsigned int type:5;
+} OPSPEC;
+#endif
+
+typedef struct {
+ unsigned int offset;
+ unsigned int width;
+ enum operand_type type;
+} OPSPEC;
+
+ struct SIM_FLAGS {
+ int ltncy, /* latency (max number of clocks needed to execute) */
+ extime, /* execution time (min number of clocks needed to execute) */
+ wb_pri; /* writeback slot priority */
+ unsigned op:OP, /* simulator version of opcode */
+ imm_flags:2, /* 10,16 or 26 bit immediate flags */
+ rs1_used:1, /* register source 1 used */
+ rs2_used:1, /* register source 2 used */
+ rsd_used:1, /* register source/dest used */
+ c_flag:1, /* complement */
+ u_flag:1, /* upper half word */
+ n_flag:1, /* execute next */
+ wb_flag:1, /* uses writeback slot */
+ dest_64:1, /* double precision dest */
+ s1_64:1, /* double precision source 1 */
+ s2_64:1, /* double precision source 2 */
+ scale_flag:1; /* register is scaled */
+};
+
+typedef struct INSTRUCTAB {
+ unsigned int opcode;
+ char *mnemonic;
+ OPSPEC op1,op2,op3;
+ struct SIM_FLAGS flgs;
+ struct INSTRUCTAB *next;
+} INSTAB;
+
+
+#define NO_OPERAND {0,0,0}
+
+/* Opcode Mnemonic Op 1 Spec Op 2 Spec Op 3 Spec Simflags Next */
+
+static INSTAB instructions[] = {
+ {0xf400c800,"jsr ",{0,5,REG} ,NO_OPERAND ,NO_OPERAND , {2,2,NA,JSR , 0,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xf400cc00,"jsr.n ",{0,5,REG} ,NO_OPERAND ,NO_OPERAND , {1,1,NA,JSR , 0,0,1,0,0,0,1,1,0,0,0,0}, NULL },
+ {0xf400c000,"jmp ",{0,5,REG} ,NO_OPERAND ,NO_OPERAND , {2,2,NA,JMP , 0,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xf400c400,"jmp.n ",{0,5,REG} ,NO_OPERAND ,NO_OPERAND , {1,1,NA,JMP , 0,0,1,0,0,0,1,1,0,0,0,0}, NULL },
+ {0xc8000000,"bsr ",{0,26,PCREL},NO_OPERAND ,NO_OPERAND , {2,2,NA,BSR , i26bit,0,0,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xcc000000,"bsr.n ",{0,26,PCREL},NO_OPERAND ,NO_OPERAND , {1,1,NA,BSR , i26bit,0,0,0,0,0,1,1,0,0,0,0}, NULL },
+ {0xc0000000,"br ",{0,26,PCREL},NO_OPERAND ,NO_OPERAND , {2,2,NA,BR , i26bit,0,0,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xc4000000,"br.n ",{0,26,PCREL},NO_OPERAND ,NO_OPERAND , {1,1,NA,BR , i26bit,0,0,0,0,0,1,1,0,0,0,0}, NULL },
+ {0xd0000000,"bb0 ",{21,5,HEX} ,{16,5,REG} ,{0,16,PCREL},{2,2,NA,BB0, i16bit,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xd4000000,"bb0.n ",{21,5,HEX} ,{16,5,REG} ,{0,16,PCREL},{1,1,NA,BB0, i16bit,0,1,0,0,0,1,1,0,0,0,0}, NULL },
+ {0xd8000000,"bb1 ",{21,5,HEX},{16,5,REG} ,{0,16,PCREL},{2,2,NA,BB1, i16bit,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xdc000000,"bb1.n ",{21,5,HEX},{16,5,REG} ,{0,16,PCREL},{1,1,NA,BB1, i16bit,0,1,0,0,0,1,1,0,0,0,0}, NULL },
+ {0xf000d000,"tb0 ",{21,5,HEX} ,{16,5,REG} ,{0,10,HEX}, {2,2,NA,TB0 , i10bit,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xf000d800,"tb1 ",{21,5,HEX} ,{16,5,REG} ,{0,10,HEX}, {2,2,NA,TB1 , i10bit,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xe8000000,"bcnd ",{21,5,CONDMASK},{16,5,REG},{0,16,PCREL},{2,2,NA,BCND, i16bit,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xec000000,"bcnd.n ",{21,5,CONDMASK},{16,5,REG},{0,16,PCREL},{1,1,NA,BCND, i16bit,0,1,0,0,0,1,1,0,0,0,0}, NULL },
+ {0xf000e800,"tcnd ",{21,5,CONDMASK},{16,5,REG},{0,10,HEX}, {2,2,NA,TCND, i10bit,0,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xf8000000,"tbnd ",{16,5,REG} ,{0,16,HEX} ,NO_OPERAND , {2,2,NA,TBND, i10bit,1,0,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xf400f800,"tbnd ",{16,5,REG} ,{0,5,REG} ,NO_OPERAND , {2,2,NA,TBND, 0,1,1,0,0,0,0,1,0,0,0,0}, NULL },
+ {0xf400fc00,"rte ",NO_OPERAND ,NO_OPERAND ,NO_OPERAND , {2,2,NA,RTE , 0,0,0,0,0,0,0,1,0,0,0,0}, NULL },
+ {0x1c000000,"ld.b ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDB ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001c00,"ld.b ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDB , 0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0x0c000000,"ld.bu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDBU, i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4000c00,"ld.bu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDBU ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0x18000000,"ld.h ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDH ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001800,"ld.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDH ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001a00,"ld.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LDH ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL },
+ {0x08000000,"ld.hu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDHU, i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4000800,"ld.hu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDHU ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4000a00,"ld.hu ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LDHU ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL },
+ {0x14000000,"ld ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LD ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001400,"ld ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001600,"ld ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL },
+ {0x10000000,"ld.d ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,LDD ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001000,"ld.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LDD ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001200,"ld.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LDD ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL },
+ {0xf4001500,"ld.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4001700,"ld.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,LD ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL },
+ {0x2c000000,"st.b ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,STB ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4002c00,"st.b ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,STB ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0x28000000,"st.h ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,STH ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4002800,"st.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,STH ,0,1,1,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4002a00,"st.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,STH ,0,1,1,1,0,0,0,1,0,0,0,1}, NULL },
+ {0x24000000,"st ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,ST ,i16bit,1,0,1,0,0,0,1,0,0,0,0}, NULL },
+ {0xf4002400,"st ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0xf4002600,"st ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL },
+ {0x20000000,"st.d ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,NA,STD ,i16bit,0,1,0,0,0,0,1,0,0,0,0} ,NULL },
+ {0xf4002000,"st.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,STD ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0xf4002200,"st.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,STD ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL },
+ {0xf4002500,"st.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0xf4002700,"st.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,NA,ST ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL },
+/* m88100 only:
+ {0x00000000,"xmem.bu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,XMEMBU ,i16bit,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ */
+ {0xf4000000,"xmem.bu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+/* m88100 only:
+ {0x04000000,"xmem ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {3,1,PMEM,XMEM ,i16bit,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ */
+ {0xf4000400,"xmem ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0xf4000600,"xmem ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL },
+ {0xf4000500,"xmem.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0xf4000700,"xmem.usr ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{3,1,PMEM,XMEM ,0,1,1,1,0,0,0,1,0,0,0,1} ,NULL },
+/* m88100 only:
+ {0xf4003e00,"lda.b ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDAH, 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL },
+ */
+ {0xf4003e00,"lda.x ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDAH, 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL },
+ {0xf4003a00,"lda.h ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDAH, 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL },
+ {0xf4003600,"lda ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDA , 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL },
+ {0xf4003200,"lda.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REGSC},{1,1,PINT,LDAD, 0,1,1,1,0,0,0,0,0,0,0,1} ,NULL },
+
+ {0x80004000,"ldcr ",{21,5,REG} ,{5,6,CRREG} ,NO_OPERAND ,{1,1,PINT,LDCR, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x80008000,"stcr ",{16,5,REG} ,{5,6,CRREG} ,NO_OPERAND ,{1,1,PINT,STCR, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x8000c000,"xcr ",{21,5,REG} ,{16,5,REG} ,{5,6,CRREG},{1,1,PINT,XCR, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+
+ {0xf4006000,"addu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006200,"addu.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006100,"addu.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006300,"addu.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADDU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006400,"subu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006600,"subu.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006500,"subu.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006700,"subu.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUBU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006800,"divu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {32,32,PINT,DIVU, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4006900,"divu.d ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}, NULL },
+ {0xf4006e00,"muls ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,}, NULL },
+ {0xf4006c00,"mulu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,4,PINT,MUL, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007000,"add ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007200,"add.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007100,"add.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007300,"add.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ADD , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007400,"sub ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007600,"sub.ci ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007500,"sub.co ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007700,"sub.cio ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SUB , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007800,"divs ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {32,32,PINT,DIV , 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4007c00,"cmp ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,CMP, 0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+
+ {0x60000000,"addu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,ADDU, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x64000000,"subu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,SUBU, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+
+ {0x68000000,"divu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {32,32,PINT,DIVU, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x6c000000,"mulu ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {4,1,PINT,MUL, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x70000000,"add ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,ADD, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x74000000,"sub ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,SUB, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x78000000,"divs ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {32,32,PINT,DIV, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x7c000000,"cmp ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,CMP, i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+
+ {0xf4004000,"and ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,AND_ ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4004400,"and.c ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,AND_ ,0,1,1,1,1,0,0,0,0,0,0,0} ,NULL },
+ {0xf4005800,"or ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,OR ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4005c00,"or.c ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,OR ,0,1,1,1,1,0,0,0,0,0,0,0} ,NULL },
+ {0xf4005000,"xor ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,XOR ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4005400,"xor.c ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,XOR ,0,1,1,1,1,0,0,0,0,0,0,0} ,NULL },
+ {0x40000000,"and ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,AND_ ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x44000000,"and.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,AND_ ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL },
+ {0x58000000,"or ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,OR ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x5c000000,"or.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,OR ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL },
+ {0x50000000,"xor ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,XOR ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x54000000,"xor.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,XOR ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL },
+ {0x48000000,"mask ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,MASK ,i16bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0x4c000000,"mask.u ",{21,5,REG} ,{16,5,REG} ,{0,16,HEX}, {1,1,PINT,MASK ,i16bit,1,0,1,0,1,0,0,0,0,0,0} ,NULL },
+ {0xf400ec00,"ff0 ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {1,1,PINT,FF0 ,0,0,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf400e800,"ff1 ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {1,1,PINT,FF1 ,0,0,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf0008000,"clr ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,CLR ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf0008800,"set ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,SET ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf0009000,"ext ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,EXT ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf0009800,"extu ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,EXTU ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf000a000,"mak ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,MAK ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf000a800,"rot ",{21,5,REG} ,{16,5,REG} ,{0,10,BF} , {1,1,PINT,ROT ,i10bit,1,0,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4008000,"clr ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,CLR ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4008800,"set ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,SET ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4009000,"ext ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,EXT ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf4009800,"extu ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,EXTU ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf400a000,"mak ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,MAK ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+ {0xf400a800,"rot ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {1,1,PINT,ROT ,0,1,1,1,0,0,0,0,0,0,0,0} ,NULL },
+
+ {0x84002800,"fadd.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {5,1,PFLT,FADD ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84002880,"fadd.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL },
+ {0x84002a00,"fadd.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL },
+ {0x84002a80,"fadd.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL },
+ {0x84002820,"fadd.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x840028a0,"fadd.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL },
+ {0x84002a20,"fadd.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL },
+ {0x84002aa0,"fadd.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FADD ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL },
+ {0x84003000,"fsub.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {5,1,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84003080,"fsub.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL },
+ {0x84003200,"fsub.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL },
+ {0x84003280,"fsub.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL },
+ {0x84003020,"fsub.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x840030a0,"fsub.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL },
+ {0x84003220,"fsub.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL },
+ {0x840032a0,"fsub.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,2,PFLT,FSUB ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL },
+ {0x84000000,"fmul.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84000080,"fmul.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL },
+ {0x84000200,"fmul.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL },
+ {0x84000280,"fmul.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL },
+ {0x84000020,"fmul.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x840000a0,"fmul.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL },
+ {0x84000220,"fmul.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL },
+ {0x840002a0,"fmul.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {9,2,PFLT,FMUL ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL },
+ {0x84007000,"fdiv.sss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {30,30,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84007080,"fdiv.ssd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,0,1,0} ,NULL },
+ {0x84007200,"fdiv.sds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL },
+ {0x84007280,"fdiv.sdd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,0,1,1,0} ,NULL },
+ {0x84007020,"fdiv.dss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x840070a0,"fdiv.dsd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,0,1,0} ,NULL },
+ {0x84007220,"fdiv.dds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL },
+ {0x840072a0,"fdiv.ddd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {60,60,PFLT,FDIV ,0,1,1,1,0,0,0,1,1,1,1,0} ,NULL },
+ {0x84007800,"fsqrt.ss ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84007820,"fsqrt.sd ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84007880,"fsqrt.ds ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x840078a0,"fsqrt.dd ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {6,1,PFLT,FLT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x84003800,"fcmp.ss ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {5,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84003880,"fcmp.sd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,0,1,0,0} ,NULL },
+ {0x84003a00,"fcmp.ds ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x84003a80,"fcmp.dd ",{21,5,REG} ,{16,5,REG} ,{0,5,REG} , {6,1,PFLT,FCMP ,0,1,1,1,0,0,0,1,1,1,0,0} ,NULL },
+ {0x84002000,"flt.s ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {5,1,PFLT,FLT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84002020,"flt.d ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {6,1,PFLT,FLT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x84004800,"int.s ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {5,1,PFLT,INT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84004880,"int.d ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {6,1,PFLT,INT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x84005000,"nint.s ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {5,1,PFLT,INT ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84005080,"nint.d ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {6,1,PFLT,INT ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL },
+ {0x84005800,"trnc.s ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {5,1,PFLT,TRNC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x84005880,"trnc.d ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND , {6,1,PFLT,TRNC ,0,0,1,1,0,0,0,1,1,0,0,0} ,NULL },
+
+ {0x80004800,"fldcr ",{21,5,REG} ,{5,6,FCRREG} ,NO_OPERAND , {1,1,PFLT,FLDC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x80008800,"fstcr ",{16,5,REG} ,{5,6,FCRREG} ,NO_OPERAND , {1,1,PFLT,FSTC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+ {0x8000c800,"fxcr ",{21,5,REG} ,{16,5,REG} ,{5,6,FCRREG} , {1,1,PFLT,FXC ,0,0,1,1,0,0,0,1,0,0,0,0} ,NULL },
+
+/* The following are new for the 88110. */
+
+ {0x8400aaa0,"fadd.ddd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400aa80,"fadd.dds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400aac0,"fadd.ddx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400aa20,"fadd.dsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400aa00,"fadd.dss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400aa40,"fadd.dsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ab20,"fadd.dxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ab00,"fadd.dxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ab40,"fadd.dxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a8a0,"fadd.sdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a880,"fadd.sds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a8c0,"fadd.sdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a820,"fadd.ssd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a800,"fadd.sss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a840,"fadd.ssx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a920,"fadd.sxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a900,"fadd.sxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400a940,"fadd.sxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400aca0,"fadd.xdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ac80,"fadd.xds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400acc0,"fadd.xdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ac20,"fadd.xsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ac00,"fadd.xss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ac40,"fadd.xsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ad20,"fadd.xxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ad00,"fadd.xxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ad40,"fadd.xxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400ba80,"fcmp.sdd ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ba00,"fcmp.sds ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bb00,"fcmp.sdx ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b880,"fcmp.ssd ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b800,"fcmp.sss ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b900,"fcmp.ssx ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bc80,"fcmp.sxd ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bc00,"fcmp.sxs ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bd00,"fcmp.sxx ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400baa0,"fcmpu.sdd ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400ba20,"fcmpu.sds ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bb20,"fcmpu.sdx ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b8a0,"fcmpu.ssd ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b820,"fcmpu.sss ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b920,"fcmpu.ssx ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bca0,"fcmpu.sxd ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bc20,"fcmpu.sxs ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400bd20,"fcmpu.sxx ",{21,5,REG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x84000820,"fcvt.sd ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84000880,"fcvt.ds ",{21,5,REG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x84008880,"fcvt.ds ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x840088c0,"fcvt.dx ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008820,"fcvt.sd ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008840,"fcvt.sx ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008920,"fcvt.xd ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008900,"fcvt.xs ",{21,5,XREG} ,{0,5,XREG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400f2a0,"fdiv.ddd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f280,"fdiv.dds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f2c0,"fdiv.ddx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f220,"fdiv.dsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f200,"fdiv.dss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f240,"fdiv.dsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f320,"fdiv.dxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f300,"fdiv.dxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f340,"fdiv.dxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f0a0,"fdiv.sdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f080,"fdiv.sds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f0c0,"fdiv.sdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f020,"fdiv.ssd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f000,"fdiv.sss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f040,"fdiv.ssx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f120,"fdiv.sxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f100,"fdiv.sxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f140,"fdiv.sxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f4a0,"fdiv.xdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f480,"fdiv.xds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f4c0,"fdiv.xdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f420,"fdiv.xsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f400,"fdiv.xss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f440,"fdiv.xsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f520,"fdiv.xxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f500,"fdiv.xxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f540,"fdiv.xxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x84002220,"flt.ds ",{21,5,XREG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84002200,"flt.ss ",{21,5,XREG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84002240,"flt.xs ",{21,5,XREG} ,{0,5,REG} ,NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x840082a0,"fmul.ddd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008280,"fmul.dds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x840082c0,"fmul.ddx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008220,"fmul.dsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008200,"fmul.dss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008240,"fmul.dsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008320,"fmul.dxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008300,"fmul.dxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008340,"fmul.dxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x840080a0,"fmul.sdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008080,"fmul.sds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x840080c0,"fmul.sdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008020,"fmul.ssd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008000,"fmul.sss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008040,"fmul.ssx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008120,"fmul.sxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008100,"fmul.sxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008140,"fmul.sxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x840084a0,"fmul.xdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008480,"fmul.xds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x840084c0,"fmul.xdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008420,"fmul.xsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008400,"fmul.xss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008440,"fmul.xsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008520,"fmul.xxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008500,"fmul.xxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84008540,"fmul.xxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400f8a0,"fsqrt.dd ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f880,"fsqrt.ds ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f8c0,"fsqrt.dx ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f820,"fsqrt.sd ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f800,"fsqrt.ss ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f840,"fsqrt.sx ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f920,"fsqrt.xd ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f900,"fsqrt.xs ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400f940,"fsqrt.xx ",{21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400b2a0,"fsub.ddd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b280,"fsub.dds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b2c0,"fsub.ddx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b220,"fsub.dsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b200,"fsub.dss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b240,"fsub.dsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b320,"fsub.dxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b300,"fsub.dxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b340,"fsub.dxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b0a0,"fsub.sdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b080,"fsub.sds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b0c0,"fsub.sdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b020,"fsub.ssd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b000,"fsub.sss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b040,"fsub.ssx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b120,"fsub.sxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b100,"fsub.sxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b140,"fsub.sxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b4a0,"fsub.xdd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b480,"fsub.xds ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b4c0,"fsub.xdx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b420,"fsub.xsd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b400,"fsub.xss ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b440,"fsub.xsx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b520,"fsub.xxd ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b500,"fsub.xxs ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400b540,"fsub.xxx ",{21,5,XREG} ,{16,5,XREG} ,{0,5,XREG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400fc00,"illop", {0,2,DEC}, NO_OPERAND, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400c800,"int.ss ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400c880,"int.sd ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400c900,"int.sx ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x04000000,"ld ", {21,5,XREG}, {16,5,REG}, {0,16,HEX}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x00000000,"ld.d ", {21,5,XREG}, {16,5,REG}, {0,16,HEX}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x3c000000,"ld.x ", {21,5,XREG}, {16,5,REG}, {0,16,HEX}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0xf0001400,"ld ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001000,"ld.d ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001800,"ld.x ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001500,"ld.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001100,"ld.d.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001900,"ld.x.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0xf0001600,"ld ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001200,"ld.d ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001a00,"ld.x ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001700,"ld.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001300,"ld.d.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0001b00,"ld.x.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400c000,"mov.s ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400c080,"mov.d ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84004200,"mov.s ", {21,5,XREG}, {0,5,REG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x84004280,"mov.d ", {21,5,XREG}, {0,5,REG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400c300,"mov ", {21,5,XREG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0xf4006d00,"mulu.d ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400d080,"nint.sd ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400d000,"nint.ss ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400d100,"nint.sx ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x88002020,"padd.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88002040,"padd.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88002060,"padd ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x880021e0,"padds.s ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880021a0,"padds.s.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880021c0,"padds.s.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880020e0,"padds.u ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880020a0,"padds.u.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880020c0,"padds.u.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88002160,"padds.us ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88002120,"padds.us.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88002140,"padds.us.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x88003860,"pcmp ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x88000000,"pmul ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x88006260,"ppack.16 ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88006240,"ppack.16.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88006460,"ppack.32 ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88006420,"ppack.32.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88006440,"ppack.32.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88006160,"ppack.8 ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x88007200,"prot ", {21,5,REG}, {16,5,REG}, {5,6,HEX}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88007800,"prot ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x88003020,"psub.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88003040,"psub.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88003060,"psub ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x880031e0,"psubs.s ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880031a0,"psubs.s.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880031c0,"psubs.s.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880030e0,"psubs.u ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880030a0,"psubs.u.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x880030c0,"psubs.u.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88003160,"psubs.us ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88003120,"psubs.us.b ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88003140,"psubs.us.h ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x88006800,"punpk.n ", {21,5,REG}, {16,5,REG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x88006820,"punpk.b ", {21,5,REG}, {16,5,REG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x34000000,"st ", {21,5,XREG}, {16,5,REG}, {0,16,HEX}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x30000000,"st.d ", {21,5,XREG}, {16,5,REG}, {0,16,HEX}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x38000000,"st.x ", {21,5,XREG}, {16,5,REG}, {0,16,HEX}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0xf4002c80,"st.b.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002880,"st.h.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002480,"st.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002080,"st.d.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002d80,"st.b.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002980,"st.h.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002580,"st.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002180,"st.d.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0xf0002400,"st ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002000,"st.d ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002100,"st.d.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002180,"st.d.usr.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002080,"st.d.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002500,"st.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002580,"st.usr.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002480,"st.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002800,"st.x ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002900,"st.x.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002980,"st.x.usr.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002880,"st.x.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REG}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0xf4002f80,"st.b.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002e80,"st.b.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002380,"st.d.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002280,"st.d.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002b80,"st.h.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002a80,"st.h.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002780,"st.usr.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf4002680,"st.wt ", {21,5,REG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0xf0002600,"st ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002200,"st.d ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002300,"st.d.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002380,"st.d.usr.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002280,"st.d.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002700,"st.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002780,"st.usr.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002680,"st.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002a00,"st.x ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002b00,"st.x.usr ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002b80,"st.x.usr.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0xf0002a80,"st.x.wt ", {21,5,XREG}, {16,5,REG}, {0,5,REGSC}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+ {0x8400d880,"trnc.sd ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400d800,"trnc.ss ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+ {0x8400d900,"trnc.sx ", {21,5,REG}, {0,5,XREG}, NO_OPERAND, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, NULL },
+
+};
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * End:
+ */
diff --git a/contrib/gdb/include/opcode/mips.h b/contrib/gdb/include/opcode/mips.h
new file mode 100644
index 0000000..14ceec9
--- /dev/null
+++ b/contrib/gdb/include/opcode/mips.h
@@ -0,0 +1,481 @@
+/* mips.h. Mips opcode list for GDB, the GNU debugger.
+ Copyright 1993, 1995 Free Software Foundation, Inc.
+ Contributed by Ralph Campbell and OSF
+ Commented and modified by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+will be useful, but WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this file; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* These are bit masks and shift counts to use to access the various
+ fields of an instruction. To retrieve the X field of an
+ instruction, use the expression
+ (i >> OP_SH_X) & OP_MASK_X
+ To set the same field (to j), use
+ i = (i &~ (OP_MASK_X << OP_SH_X)) | (j << OP_SH_X)
+
+ Make sure you use fields that are appropriate for the instruction,
+ of course.
+
+ The 'i' format uses OP, RS, RT and IMMEDIATE.
+
+ The 'j' format uses OP and TARGET.
+
+ The 'r' format uses OP, RS, RT, RD, SHAMT and FUNCT.
+
+ The 'b' format uses OP, RS, RT and DELTA.
+
+ The floating point 'i' format uses OP, RS, RT and IMMEDIATE.
+
+ The floating point 'r' format uses OP, FMT, FT, FS, FD and FUNCT.
+
+ A breakpoint instruction uses OP, CODE and SPEC (10 bits of the
+ breakpoint instruction are not defined; Kane says the breakpoint
+ code field in BREAK is 20 bits; yet MIPS assemblers and debuggers
+ only use ten bits).
+
+ The syscall instruction uses SYSCALL.
+
+ The general coprocessor instructions use COPZ. */
+
+#define OP_MASK_OP 0x3f
+#define OP_SH_OP 26
+#define OP_MASK_RS 0x1f
+#define OP_SH_RS 21
+#define OP_MASK_FR 0x1f
+#define OP_SH_FR 21
+#define OP_MASK_FMT 0x1f
+#define OP_SH_FMT 21
+#define OP_MASK_BCC 0x7
+#define OP_SH_BCC 18
+#define OP_MASK_CODE 0x3ff
+#define OP_SH_CODE 16
+#define OP_MASK_RT 0x1f
+#define OP_SH_RT 16
+#define OP_MASK_FT 0x1f
+#define OP_SH_FT 16
+#define OP_MASK_CACHE 0x1f
+#define OP_SH_CACHE 16
+#define OP_MASK_RD 0x1f
+#define OP_SH_RD 11
+#define OP_MASK_FS 0x1f
+#define OP_SH_FS 11
+#define OP_MASK_PREFX 0x1f
+#define OP_SH_PREFX 11
+#define OP_MASK_CCC 0x7
+#define OP_SH_CCC 8
+#define OP_MASK_SYSCALL 0xfffff
+#define OP_SH_SYSCALL 6
+#define OP_MASK_SHAMT 0x1f
+#define OP_SH_SHAMT 6
+#define OP_MASK_FD 0x1f
+#define OP_SH_FD 6
+#define OP_MASK_TARGET 0x3ffffff
+#define OP_SH_TARGET 0
+#define OP_MASK_COPZ 0x1ffffff
+#define OP_SH_COPZ 0
+#define OP_MASK_IMMEDIATE 0xffff
+#define OP_SH_IMMEDIATE 0
+#define OP_MASK_DELTA 0xffff
+#define OP_SH_DELTA 0
+#define OP_MASK_FUNCT 0x3f
+#define OP_SH_FUNCT 0
+#define OP_MASK_SPEC 0x3f
+#define OP_SH_SPEC 0
+
+/* This structure holds information for a particular instruction. */
+
+struct mips_opcode
+{
+ /* The name of the instruction. */
+ const char *name;
+ /* A string describing the arguments for this instruction. */
+ const char *args;
+ /* The basic opcode for the instruction. When assembling, this
+ opcode is modified by the arguments to produce the actual opcode
+ that is used. If pinfo is INSN_MACRO, then this is instead the
+ ISA level of the macro (0 or 1 is always supported, 2 is ISA 2,
+ etc.). */
+ unsigned long match;
+ /* If pinfo is not INSN_MACRO, then this is a bit mask for the
+ relevant portions of the opcode when disassembling. If the
+ actual opcode anded with the match field equals the opcode field,
+ then we have found the correct instruction. If pinfo is
+ INSN_MACRO, then this field is the macro identifier. */
+ unsigned long mask;
+ /* For a macro, this is INSN_MACRO. Otherwise, it is a collection
+ of bits describing the instruction, notably any relevant hazard
+ information. */
+ unsigned long pinfo;
+};
+
+/* These are the characters which may appears in the args field of an
+ instruction. They appear in the order in which the fields appear
+ when the instruction is used. Commas and parentheses in the args
+ string are ignored when assembling, and written into the output
+ when disassembling.
+
+ Each of these characters corresponds to a mask field defined above.
+
+ "<" 5 bit shift amount (OP_*_SHAMT)
+ ">" shift amount between 32 and 63, stored after subtracting 32 (OP_*_SHAMT)
+ "a" 26 bit target address (OP_*_TARGET)
+ "b" 5 bit base register (OP_*_RS)
+ "c" 10 bit breakpoint code (OP_*_CODE)
+ "d" 5 bit destination register specifier (OP_*_RD)
+ "h" 5 bit prefx hint (OP_*_PREFX)
+ "i" 16 bit unsigned immediate (OP_*_IMMEDIATE)
+ "j" 16 bit signed immediate (OP_*_DELTA)
+ "k" 5 bit cache opcode in target register position (OP_*_CACHE)
+ "o" 16 bit signed offset (OP_*_DELTA)
+ "p" 16 bit PC relative branch target address (OP_*_DELTA)
+ "r" 5 bit same register used as both source and target (OP_*_RS)
+ "s" 5 bit source register specifier (OP_*_RS)
+ "t" 5 bit target register (OP_*_RT)
+ "u" 16 bit upper 16 bits of address (OP_*_IMMEDIATE)
+ "v" 5 bit same register used as both source and destination (OP_*_RS)
+ "w" 5 bit same register used as both target and destination (OP_*_RT)
+ "C" 25 bit coprocessor function code (OP_*_COPZ)
+ "B" 20 bit syscall function code (OP_*_SYSCALL)
+ "x" accept and ignore register name
+ "z" must be zero register
+
+ Floating point instructions:
+ "D" 5 bit destination register (OP_*_FD)
+ "M" 3 bit compare condition code (OP_*_CCC) (only used for mips4 and up)
+ "N" 3 bit branch condition code (OP_*_BCC) (only used for mips4 and up)
+ "S" 5 bit fs source 1 register (OP_*_FS)
+ "T" 5 bit ft source 2 register (OP_*_FT)
+ "R" 5 bit fr source 3 register (OP_*_FR)
+ "V" 5 bit same register used as floating source and destination (OP_*_FS)
+ "W" 5 bit same register used as floating target and destination (OP_*_FT)
+
+ Coprocessor instructions:
+ "E" 5 bit target register (OP_*_RT)
+ "G" 5 bit destination register (OP_*_RD)
+
+ Macro instructions:
+ "A" General 32 bit expression
+ "I" 32 bit immediate
+ "F" 64 bit floating point constant in .rdata
+ "L" 64 bit floating point constant in .lit8
+ "f" 32 bit floating point constant
+ "l" 32 bit floating point constant in .lit4
+*/
+
+/* These are the bits which may be set in the pinfo field of an
+ instructions, if it is not equal to INSN_MACRO. */
+
+/* Modifies the general purpose register in OP_*_RD. */
+#define INSN_WRITE_GPR_D 0x00000001
+/* Modifies the general purpose register in OP_*_RT. */
+#define INSN_WRITE_GPR_T 0x00000002
+/* Modifies general purpose register 31. */
+#define INSN_WRITE_GPR_31 0x00000004
+/* Modifies the floating point register in OP_*_FD. */
+#define INSN_WRITE_FPR_D 0x00000008
+/* Modifies the floating point register in OP_*_FS. */
+#define INSN_WRITE_FPR_S 0x00000010
+/* Modifies the floating point register in OP_*_FT. */
+#define INSN_WRITE_FPR_T 0x00000020
+/* Reads the general purpose register in OP_*_RS. */
+#define INSN_READ_GPR_S 0x00000040
+/* Reads the general purpose register in OP_*_RT. */
+#define INSN_READ_GPR_T 0x00000080
+/* Reads the floating point register in OP_*_FS. */
+#define INSN_READ_FPR_S 0x00000100
+/* Reads the floating point register in OP_*_FT. */
+#define INSN_READ_FPR_T 0x00000200
+/* Reads the floating point register in OP_*_FR. */
+#define INSN_READ_FPR_R 0x00000400
+/* Modifies coprocessor condition code. */
+#define INSN_WRITE_COND_CODE 0x00000800
+/* Reads coprocessor condition code. */
+#define INSN_READ_COND_CODE 0x00001000
+/* TLB operation. */
+#define INSN_TLB 0x00002000
+/* Reads coprocessor register other than floating point register. */
+#define INSN_COP 0x00004000
+/* Instruction loads value from memory, requiring delay. */
+#define INSN_LOAD_MEMORY_DELAY 0x00008000
+/* Instruction loads value from coprocessor, requiring delay. */
+#define INSN_LOAD_COPROC_DELAY 0x00010000
+/* Instruction has unconditional branch delay slot. */
+#define INSN_UNCOND_BRANCH_DELAY 0x00020000
+/* Instruction has conditional branch delay slot. */
+#define INSN_COND_BRANCH_DELAY 0x00040000
+/* Conditional branch likely: if branch not taken, insn nullified. */
+#define INSN_COND_BRANCH_LIKELY 0x00080000
+/* Moves to coprocessor register, requiring delay. */
+#define INSN_COPROC_MOVE_DELAY 0x00100000
+/* Loads coprocessor register from memory, requiring delay. */
+#define INSN_COPROC_MEMORY_DELAY 0x00200000
+/* Reads the HI register. */
+#define INSN_READ_HI 0x00400000
+/* Reads the LO register. */
+#define INSN_READ_LO 0x00800000
+/* Modifies the HI register. */
+#define INSN_WRITE_HI 0x01000000
+/* Modifies the LO register. */
+#define INSN_WRITE_LO 0x02000000
+/* Takes a trap (easier to keep out of delay slot). */
+#define INSN_TRAP 0x04000000
+/* Instruction stores value into memory. */
+#define INSN_STORE_MEMORY 0x08000000
+/* MIPS ISA field--CPU level at which insn is supported. */
+#define INSN_ISA 0x70000000
+/* MIPS ISA 2 instruction (R6000 or R4000). */
+#define INSN_ISA2 0x10000000
+/* MIPS ISA 3 instruction (R4000). */
+#define INSN_ISA3 0x20000000
+/* MIPS R4650 instruction. */
+#define INSN_4650 0x30000000
+/* MIPS ISA 4 instruction (R8000). */
+#define INSN_ISA4 0x40000000
+/* LSI R4010 instruction. */
+#define INSN_4010 0x50000000
+/* NEC VR4100 instruction. */
+#define INSN_4100 0x60000000
+
+/* Instruction is actually a macro. It should be ignored by the
+ disassembler, and requires special treatment by the assembler. */
+#define INSN_MACRO 0xffffffff
+
+/* This is a list of macro expanded instructions.
+ *
+ * _I appended means immediate
+ * _A appended means address
+ * _AB appended means address with base register
+ * _D appended means 64 bit floating point constant
+ * _S appended means 32 bit floating point constant
+ */
+enum {
+ M_ABS,
+ M_ADD_I,
+ M_ADDU_I,
+ M_AND_I,
+ M_BEQ_I,
+ M_BEQL_I,
+ M_BGE,
+ M_BGEL,
+ M_BGE_I,
+ M_BGEL_I,
+ M_BGEU,
+ M_BGEUL,
+ M_BGEU_I,
+ M_BGEUL_I,
+ M_BGT,
+ M_BGTL,
+ M_BGT_I,
+ M_BGTL_I,
+ M_BGTU,
+ M_BGTUL,
+ M_BGTU_I,
+ M_BGTUL_I,
+ M_BLE,
+ M_BLEL,
+ M_BLE_I,
+ M_BLEL_I,
+ M_BLEU,
+ M_BLEUL,
+ M_BLEU_I,
+ M_BLEUL_I,
+ M_BLT,
+ M_BLTL,
+ M_BLT_I,
+ M_BLTL_I,
+ M_BLTU,
+ M_BLTUL,
+ M_BLTU_I,
+ M_BLTUL_I,
+ M_BNE_I,
+ M_BNEL_I,
+ M_DABS,
+ M_DADD_I,
+ M_DADDU_I,
+ M_DDIV_3,
+ M_DDIV_3I,
+ M_DDIVU_3,
+ M_DDIVU_3I,
+ M_DIV_3,
+ M_DIV_3I,
+ M_DIVU_3,
+ M_DIVU_3I,
+ M_DLA_AB,
+ M_DLI,
+ M_DMUL,
+ M_DMUL_I,
+ M_DMULO,
+ M_DMULO_I,
+ M_DMULOU,
+ M_DMULOU_I,
+ M_DREM_3,
+ M_DREM_3I,
+ M_DREMU_3,
+ M_DREMU_3I,
+ M_DSUB_I,
+ M_DSUBU_I,
+ M_J_A,
+ M_JAL_1,
+ M_JAL_2,
+ M_JAL_A,
+ M_L_DOB,
+ M_L_DAB,
+ M_LA_AB,
+ M_LB_A,
+ M_LB_AB,
+ M_LBU_A,
+ M_LBU_AB,
+ M_LD_A,
+ M_LD_OB,
+ M_LD_AB,
+ M_LDC1_AB,
+ M_LDC2_AB,
+ M_LDC3_AB,
+ M_LDL_AB,
+ M_LDR_AB,
+ M_LH_A,
+ M_LH_AB,
+ M_LHU_A,
+ M_LHU_AB,
+ M_LI,
+ M_LI_D,
+ M_LI_DD,
+ M_LI_S,
+ M_LI_SS,
+ M_LL_AB,
+ M_LLD_AB,
+ M_LS_A,
+ M_LW_A,
+ M_LW_AB,
+ M_LWC0_A,
+ M_LWC0_AB,
+ M_LWC1_A,
+ M_LWC1_AB,
+ M_LWC2_A,
+ M_LWC2_AB,
+ M_LWC3_A,
+ M_LWC3_AB,
+ M_LWL_A,
+ M_LWL_AB,
+ M_LWR_A,
+ M_LWR_AB,
+ M_LWU_AB,
+ M_MUL,
+ M_MUL_I,
+ M_MULO,
+ M_MULO_I,
+ M_MULOU,
+ M_MULOU_I,
+ M_NOR_I,
+ M_OR_I,
+ M_REM_3,
+ M_REM_3I,
+ M_REMU_3,
+ M_REMU_3I,
+ M_ROL,
+ M_ROL_I,
+ M_ROR,
+ M_ROR_I,
+ M_S_DA,
+ M_S_DOB,
+ M_S_DAB,
+ M_S_S,
+ M_SC_AB,
+ M_SCD_AB,
+ M_SD_A,
+ M_SD_OB,
+ M_SD_AB,
+ M_SDC1_AB,
+ M_SDC2_AB,
+ M_SDC3_AB,
+ M_SDL_AB,
+ M_SDR_AB,
+ M_SEQ,
+ M_SEQ_I,
+ M_SGE,
+ M_SGE_I,
+ M_SGEU,
+ M_SGEU_I,
+ M_SGT,
+ M_SGT_I,
+ M_SGTU,
+ M_SGTU_I,
+ M_SLE,
+ M_SLE_I,
+ M_SLEU,
+ M_SLEU_I,
+ M_SLT_I,
+ M_SLTU_I,
+ M_SNE,
+ M_SNE_I,
+ M_SB_A,
+ M_SB_AB,
+ M_SH_A,
+ M_SH_AB,
+ M_SW_A,
+ M_SW_AB,
+ M_SWC0_A,
+ M_SWC0_AB,
+ M_SWC1_A,
+ M_SWC1_AB,
+ M_SWC2_A,
+ M_SWC2_AB,
+ M_SWC3_A,
+ M_SWC3_AB,
+ M_SWL_A,
+ M_SWL_AB,
+ M_SWR_A,
+ M_SWR_AB,
+ M_SUB_I,
+ M_SUBU_I,
+ M_TEQ_I,
+ M_TGE_I,
+ M_TGEU_I,
+ M_TLT_I,
+ M_TLTU_I,
+ M_TNE_I,
+ M_TRUNCWD,
+ M_TRUNCWS,
+ M_ULD,
+ M_ULD_A,
+ M_ULH,
+ M_ULH_A,
+ M_ULHU,
+ M_ULHU_A,
+ M_ULW,
+ M_ULW_A,
+ M_USH,
+ M_USH_A,
+ M_USW,
+ M_USW_A,
+ M_USD,
+ M_USD_A,
+ M_XOR_I
+};
+
+/* The order of overloaded instructions matters. Label arguments and
+ register arguments look the same. Instructions that can have either
+ for arguments must apear in the correct order in this table for the
+ assembler to pick the right one. In other words, entries with
+ immediate operands must apear after the same instruction with
+ registers.
+
+ Many instructions are short hand for other instructions (i.e., The
+ jal <register> instruction is short for jalr <register>). */
+
+extern const struct mips_opcode mips_opcodes[];
+extern const int bfd_mips_num_opcodes;
+#define NUMOPCODES bfd_mips_num_opcodes
diff --git a/contrib/gdb/include/opcode/np1.h b/contrib/gdb/include/opcode/np1.h
new file mode 100644
index 0000000..d23adc7
--- /dev/null
+++ b/contrib/gdb/include/opcode/np1.h
@@ -0,0 +1,422 @@
+/* Print GOULD NPL instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct gld_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long mask;
+ char *args;
+ int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and at most four. The length of the
+ instruction is based on the opcode.
+
+ The mask component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing characters
+ that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+ r Register in first field
+ R Register in second field
+ b Base register in first field
+ B Base register in second field
+ v Vector register in first field
+ V Vector register in first field
+ A Optional address register (base register)
+ X Optional index register
+ I Immediate data (16bits signed)
+ O Offset field (16bits signed)
+ h Offset field (15bits signed)
+ d Offset field (14bits signed)
+ S Shift count field
+
+ any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "lb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lbs", 0xec080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lnh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ld", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lnd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "li", 0xf8000000, 0xfc7f0000, "r,I", 4 },
+{ "lpa", 0x50080000, 0xfc080000, "r,xOA,X", 4 },
+{ "la", 0x50000000, 0xfc080000, "r,xOA,X", 4 },
+{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lbp", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lhp", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lwp", 0x90000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ldp", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
+{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
+{ "lf", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lfbr", 0xbc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
+{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stfbr", 0xdc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "zmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "zmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stbp", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sthp", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stwp", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stdp", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lil", 0xf80b0000, 0xfc7f0000, "r,D", 4 },
+{ "lwsl1", 0xec000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwsl2", 0xfc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwsl3", 0xfc080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "lvb", 0xb0080000, 0xfc080000, "v,xOA,X", 4 },
+{ "lvh", 0xb0000001, 0xfc080001, "v,xOA,X", 4 },
+{ "lvw", 0xb0000000, 0xfc080000, "v,xOA,X", 4 },
+{ "lvd", 0xb0000002, 0xfc080002, "v,xOA,X", 4 },
+{ "liv", 0x3c040000, 0xfc0f0000, "v,R", 2 },
+{ "livf", 0x3c080000, 0xfc0f0000, "v,R", 2 },
+{ "stvb", 0xd0080000, 0xfc080000, "v,xOA,X", 4 },
+{ "stvh", 0xd0000001, 0xfc080001, "v,xOA,X", 4 },
+{ "stvw", 0xd0000000, 0xfc080000, "v,xOA,X", 4 },
+{ "stvd", 0xd0000002, 0xfc080002, "v,xOA,X", 4 },
+
+{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
+{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
+{ "trnd", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
+{ "trabs", 0x2c010000, 0xfc0f0000, "r,R", 2 },
+{ "trabsd", 0x2c090000, 0xfc0f0000, "r,R", 2 },
+{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
+{ "xcr", 0x28040000, 0xfc0f0000, "r,R", 2 },
+{ "cxcr", 0x2c060000, 0xfc0f0000, "r,R", 2 },
+{ "cxcrd", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
+{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
+{ "trbr", 0x28030000, 0xfc0f0000, "b,R", 2 },
+{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
+{ "tbrbr", 0x28010000, 0xfc0f0000, "b,B", 2 },
+
+{ "trvv", 0x28050000, 0xfc0f0000, "v,V", 2 },
+{ "trvvn", 0x2c050000, 0xfc0f0000, "v,V", 2 },
+{ "trvvnd", 0x2c0d0000, 0xfc0f0000, "v,V", 2 },
+{ "trvab", 0x2c070000, 0xfc0f0000, "v,V", 2 },
+{ "trvabd", 0x2c0f0000, 0xfc0f0000, "v,V", 2 },
+{ "cmpv", 0x14060000, 0xfc0f0000, "v,V", 2 },
+{ "expv", 0x14070000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvlt", 0x10030000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvle", 0x10040000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvgt", 0x14030000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvge", 0x14040000, 0xfc0f0000, "v,V", 2 },
+{ "mrvveq", 0x10050000, 0xfc0f0000, "v,V", 2 },
+{ "mrvvne", 0x10050000, 0xfc0f0000, "v,V", 2 },
+{ "mrvrlt", 0x100d0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrle", 0x100e0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrgt", 0x140d0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrge", 0x140e0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvreq", 0x100f0000, 0xfc0f0000, "v,R", 2 },
+{ "mrvrne", 0x140f0000, 0xfc0f0000, "v,R", 2 },
+{ "trvr", 0x140b0000, 0xfc0f0000, "r,V", 2 },
+{ "trrv", 0x140c0000, 0xfc0f0000, "v,R", 2 },
+
+{ "bu", 0x40000000, 0xff880000, "xOA,X", 4 },
+{ "bns", 0x70080000, 0xff880000, "xOA,X", 4 },
+{ "bnco", 0x70880000, 0xff880000, "xOA,X", 4 },
+{ "bge", 0x71080000, 0xff880000, "xOA,X", 4 },
+{ "bne", 0x71880000, 0xff880000, "xOA,X", 4 },
+{ "bunge", 0x72080000, 0xff880000, "xOA,X", 4 },
+{ "bunle", 0x72880000, 0xff880000, "xOA,X", 4 },
+{ "bgt", 0x73080000, 0xff880000, "xOA,X", 4 },
+{ "bnany", 0x73880000, 0xff880000, "xOA,X", 4 },
+{ "bs" , 0x70000000, 0xff880000, "xOA,X", 4 },
+{ "bco", 0x70800000, 0xff880000, "xOA,X", 4 },
+{ "blt", 0x71000000, 0xff880000, "xOA,X", 4 },
+{ "beq", 0x71800000, 0xff880000, "xOA,X", 4 },
+{ "buge", 0x72000000, 0xff880000, "xOA,X", 4 },
+{ "bult", 0x72800000, 0xff880000, "xOA,X", 4 },
+{ "ble", 0x73000000, 0xff880000, "xOA,X", 4 },
+{ "bany", 0x73800000, 0xff880000, "xOA,X", 4 },
+{ "brlnk", 0x44000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bib", 0x48000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bih", 0x48080000, 0xfc080000, "r,xOA,X", 4 },
+{ "biw", 0x4c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bid", 0x4c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivb", 0x60000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivh", 0x60080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivw", 0x64000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bivd", 0x64080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsb", 0x68000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsh", 0x68080000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsw", 0x6c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bvsd", 0x6c080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "camb", 0x80080000, 0xfc080000, "r,xOA,X", 4 },
+{ "camh", 0x80000001, 0xfc080001, "r,xOA,X", 4 },
+{ "camw", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
+{ "camd", 0x80000002, 0xfc080002, "r,xOA,X", 4 },
+{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
+{ "card", 0x14000000, 0xfc0f0000, "r,R", 2 },
+{ "ci", 0xf8050000, 0xfc7f0000, "r,I", 4 },
+{ "chkbnd", 0x5c080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "cavv", 0x10010000, 0xfc0f0000, "v,V", 2 },
+{ "cavr", 0x10020000, 0xfc0f0000, "v,R", 2 },
+{ "cavvd", 0x10090000, 0xfc0f0000, "v,V", 2 },
+{ "cavrd", 0x100b0000, 0xfc0f0000, "v,R", 2 },
+
+{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
+{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
+{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
+{ "ani", 0xf8080000, 0xfc7f0000, "r,I", 4 },
+{ "ormb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "ormw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
+{ "oi", 0xf8090000, 0xfc7f0000, "r,I", 4 },
+{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
+{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
+{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
+{ "eoi", 0xf80a0000, 0xfc7f0000, "r,I", 4 },
+
+{ "anvv", 0x04010000, 0xfc0f0000, "v,V", 2 },
+{ "anvr", 0x04020000, 0xfc0f0000, "v,R", 2 },
+{ "orvv", 0x08010000, 0xfc0f0000, "v,V", 2 },
+{ "orvr", 0x08020000, 0xfc0f0000, "v,R", 2 },
+{ "eovv", 0x0c010000, 0xfc0f0000, "v,V", 2 },
+{ "eovr", 0x0c020000, 0xfc0f0000, "v,R", 2 },
+
+{ "sacz", 0x100c0000, 0xfc0f0000, "r,R", 2 },
+{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
+{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
+{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
+{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
+{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
+{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
+{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
+{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
+{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
+{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
+{ "sda", 0x3c030000, 0xfc0f0000, "r,R", 2 },
+{ "sdl", 0x3c020000, 0xfc0f0000, "r,R", 2 },
+{ "sdc", 0x3c010000, 0xfc0f0000, "r,R", 2 },
+{ "sdad", 0x3c0b0000, 0xfc0f0000, "r,R", 2 },
+{ "sdld", 0x3c0a0000, 0xfc0f0000, "r,R", 2 },
+
+{ "svda", 0x3c070000, 0xfc0f0000, "v,R", 2 },
+{ "svdl", 0x3c060000, 0xfc0f0000, "v,R", 2 },
+{ "svdc", 0x3c050000, 0xfc0f0000, "v,R", 2 },
+{ "svdad", 0x3c0e0000, 0xfc0f0000, "v,R", 2 },
+{ "svdld", 0x3c0d0000, 0xfc0f0000, "v,R", 2 },
+
+{ "sbm", 0xac080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zbm", 0xac000000, 0xfc080000, "f,xOA,X", 4 },
+{ "tbm", 0xa8080000, 0xfc080000, "f,xOA,X", 4 },
+{ "incmb", 0xa0000000, 0xfc080000, "xOA,X", 4 },
+{ "incmh", 0xa0080000, 0xfc080000, "xOA,X", 4 },
+{ "incmw", 0xa4000000, 0xfc080000, "xOA,X", 4 },
+{ "incmd", 0xa4080000, 0xfc080000, "xOA,X", 4 },
+{ "sbmd", 0x7c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zbmd", 0x7c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "tbmd", 0x78080000, 0xfc080000, "r,xOA,X", 4 },
+
+{ "ssm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zsm", 0x9c000000, 0xfc080000, "f,xOA,X", 4 },
+{ "tsm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
+
+{ "admb", 0xc8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "admh", 0xc8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "admw", 0xc8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "admd", 0xc8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
+{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "adi", 0xf8010000, 0xfc0f0000, "r,I", 4 },
+{ "sumb", 0xcc080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumh", 0xcc000001, 0xfc080001, "r,xOA,X", 4 },
+{ "sumw", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumd", 0xcc000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
+{ "sui", 0xf8020000, 0xfc0f0000, "r,I", 4 },
+{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
+{ "mprd", 0x3c0f0000, 0xfc0f0000, "r,R", 2 },
+{ "mpi", 0xf8030000, 0xfc0f0000, "r,I", 4 },
+{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
+{ "dvi", 0xf8040000, 0xfc0f0000, "r,I", 4 },
+{ "exs", 0x38080000, 0xfc0f0000, "r,R", 2 },
+
+{ "advv", 0x30000000, 0xfc0f0000, "v,V", 2 },
+{ "advvd", 0x30080000, 0xfc0f0000, "v,V", 2 },
+{ "adrv", 0x34000000, 0xfc0f0000, "v,R", 2 },
+{ "adrvd", 0x34080000, 0xfc0f0000, "v,R", 2 },
+{ "suvv", 0x30010000, 0xfc0f0000, "v,V", 2 },
+{ "suvvd", 0x30090000, 0xfc0f0000, "v,V", 2 },
+{ "surv", 0x34010000, 0xfc0f0000, "v,R", 2 },
+{ "survd", 0x34090000, 0xfc0f0000, "v,R", 2 },
+{ "mpvv", 0x30020000, 0xfc0f0000, "v,V", 2 },
+{ "mprv", 0x34020000, 0xfc0f0000, "v,R", 2 },
+
+{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
+{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
+{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
+{ "surfw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "surfd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
+{ "surfd", 0x380b0000, 0xfc0f0000, "r,R", 2 },
+{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
+{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
+{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
+{ "rfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "rfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "rrfw", 0x0c0e0000, 0xfc0f0000, "r", 2 },
+{ "rrfd", 0x0c0f0000, 0xfc0f0000, "r", 2 },
+
+{ "advvfw", 0x30040000, 0xfc0f0000, "v,V", 2 },
+{ "advvfd", 0x300c0000, 0xfc0f0000, "v,V", 2 },
+{ "adrvfw", 0x34040000, 0xfc0f0000, "v,R", 2 },
+{ "adrvfd", 0x340c0000, 0xfc0f0000, "v,R", 2 },
+{ "suvvfw", 0x30050000, 0xfc0f0000, "v,V", 2 },
+{ "suvvfd", 0x300d0000, 0xfc0f0000, "v,V", 2 },
+{ "survfw", 0x34050000, 0xfc0f0000, "v,R", 2 },
+{ "survfd", 0x340d0000, 0xfc0f0000, "v,R", 2 },
+{ "mpvvfw", 0x30060000, 0xfc0f0000, "v,V", 2 },
+{ "mpvvfd", 0x300e0000, 0xfc0f0000, "v,V", 2 },
+{ "mprvfw", 0x34060000, 0xfc0f0000, "v,R", 2 },
+{ "mprvfd", 0x340e0000, 0xfc0f0000, "v,R", 2 },
+{ "rvfw", 0x30070000, 0xfc0f0000, "v", 2 },
+{ "rvfd", 0x300f0000, 0xfc0f0000, "v", 2 },
+
+{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
+{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
+{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
+{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
+{ "cfpds", 0x3c090000, 0xfc0f0000, "r,R", 2 },
+
+{ "fltvw", 0x080d0000, 0xfc0f0000, "v,V", 2 },
+{ "fltvd", 0x080f0000, 0xfc0f0000, "v,V", 2 },
+{ "fixvw", 0x080c0000, 0xfc0f0000, "v,V", 2 },
+{ "fixvd", 0x080e0000, 0xfc0f0000, "v,V", 2 },
+{ "cfpvds", 0x0c0d0000, 0xfc0f0000, "v,V", 2 },
+
+{ "orvrn", 0x000a0000, 0xfc0f0000, "r,V", 2 },
+{ "andvrn", 0x00080000, 0xfc0f0000, "r,V", 2 },
+{ "frsteq", 0x04090000, 0xfc0f0000, "r,V", 2 },
+{ "sigma", 0x0c080000, 0xfc0f0000, "r,V", 2 },
+{ "sigmad", 0x0c0a0000, 0xfc0f0000, "r,V", 2 },
+{ "sigmf", 0x08080000, 0xfc0f0000, "r,V", 2 },
+{ "sigmfd", 0x080a0000, 0xfc0f0000, "r,V", 2 },
+{ "prodf", 0x04080000, 0xfc0f0000, "r,V", 2 },
+{ "prodfd", 0x040a0000, 0xfc0f0000, "r,V", 2 },
+{ "maxv", 0x10080000, 0xfc0f0000, "r,V", 2 },
+{ "maxvd", 0x100a0000, 0xfc0f0000, "r,V", 2 },
+{ "minv", 0x14080000, 0xfc0f0000, "r,V", 2 },
+{ "minvd", 0x140a0000, 0xfc0f0000, "r,V", 2 },
+
+{ "lpsd", 0xf0000000, 0xfc080000, "xOA,X", 4 },
+{ "ldc", 0xf0080000, 0xfc080000, "xOA,X", 4 },
+{ "spm", 0x040c0000, 0xfc0f0000, "r", 2 },
+{ "rpm", 0x040d0000, 0xfc0f0000, "r", 2 },
+{ "tritr", 0x00070000, 0xfc0f0000, "r", 2 },
+{ "trrit", 0x00060000, 0xfc0f0000, "r", 2 },
+{ "rpswt", 0x04080000, 0xfc0f0000, "r", 2 },
+{ "exr", 0xf8070000, 0xfc0f0000, "", 4 },
+{ "halt", 0x00000000, 0xfc0f0000, "", 2 },
+{ "wait", 0x00010000, 0xfc0f0000, "", 2 },
+{ "nop", 0x00020000, 0xfc0f0000, "", 2 },
+{ "eiae", 0x00030000, 0xfc0f0000, "", 2 },
+{ "efae", 0x000d0000, 0xfc0f0000, "", 2 },
+{ "diae", 0x000e0000, 0xfc0f0000, "", 2 },
+{ "dfae", 0x000f0000, 0xfc0f0000, "", 2 },
+{ "spvc", 0xf8060000, 0xfc0f0000, "r,T,N", 4 },
+{ "rdsts", 0x00090000, 0xfc0f0000, "r", 2 },
+{ "setcpu", 0x000c0000, 0xfc0f0000, "r", 2 },
+{ "cmc", 0x000b0000, 0xfc0f0000, "r", 2 },
+{ "trrcu", 0x00040000, 0xfc0f0000, "r", 2 },
+{ "attnio", 0x00050000, 0xfc0f0000, "", 2 },
+{ "fudit", 0x28080000, 0xfc0f0000, "", 2 },
+{ "break", 0x28090000, 0xfc0f0000, "", 2 },
+{ "frzss", 0x280a0000, 0xfc0f0000, "", 2 },
+{ "ripi", 0x04040000, 0xfc0f0000, "r,R", 2 },
+{ "xcp", 0x04050000, 0xfc0f0000, "r", 2 },
+{ "block", 0x04060000, 0xfc0f0000, "", 2 },
+{ "unblock", 0x04070000, 0xfc0f0000, "", 2 },
+{ "trsc", 0x08060000, 0xfc0f0000, "r,R", 2 },
+{ "tscr", 0x08070000, 0xfc0f0000, "r,R", 2 },
+{ "fq", 0x04080000, 0xfc0f0000, "r", 2 },
+{ "flupte", 0x2c080000, 0xfc0f0000, "r", 2 },
+{ "rviu", 0x040f0000, 0xfc0f0000, "", 2 },
+{ "ldel", 0x280c0000, 0xfc0f0000, "r,R", 2 },
+{ "ldu", 0x280d0000, 0xfc0f0000, "r,R", 2 },
+{ "stdecc", 0x280b0000, 0xfc0f0000, "r,R", 2 },
+{ "trpc", 0x08040000, 0xfc0f0000, "r", 2 },
+{ "tpcr", 0x08050000, 0xfc0f0000, "r", 2 },
+{ "ghalt", 0x0c050000, 0xfc0f0000, "r", 2 },
+{ "grun", 0x0c040000, 0xfc0f0000, "", 2 },
+{ "tmpr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
+{ "trmp", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
+
+{ "trrve", 0x28060000, 0xfc0f0000, "r", 2 },
+{ "trver", 0x28070000, 0xfc0f0000, "r", 2 },
+{ "trvlr", 0x280f0000, 0xfc0f0000, "r", 2 },
+
+{ "linkfl", 0x18000000, 0xfc0f0000, "r,R", 2 },
+{ "linkbl", 0x18020000, 0xfc0f0000, "r,R", 2 },
+{ "linkfp", 0x18010000, 0xfc0f0000, "r,R", 2 },
+{ "linkbp", 0x18030000, 0xfc0f0000, "r,R", 2 },
+{ "linkpl", 0x18040000, 0xfc0f0000, "r,R", 2 },
+{ "ulinkl", 0x18080000, 0xfc0f0000, "r,R", 2 },
+{ "ulinkp", 0x18090000, 0xfc0f0000, "r,R", 2 },
+{ "ulinktl", 0x180a0000, 0xfc0f0000, "r,R", 2 },
+{ "ulinktp", 0x180b0000, 0xfc0f0000, "r,R", 2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+ sizeof(gld_opcodes[0]);
diff --git a/contrib/gdb/include/opcode/ns32k.h b/contrib/gdb/include/opcode/ns32k.h
new file mode 100644
index 0000000..42bb8b8
--- /dev/null
+++ b/contrib/gdb/include/opcode/ns32k.h
@@ -0,0 +1,491 @@
+/* ns32k-opcode.h -- Opcode table for National Semi 32k processor
+ Copyright (C) 1987 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler.
+
+GAS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GAS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef SEQUENT_COMPATABILITY
+#define DEF_MODEC 20
+#define DEF_MODEL 21
+#endif
+
+#ifndef DEF_MODEC
+#define DEF_MODEC 20
+#endif
+
+#ifndef DEF_MODEL
+#define DEF_MODEL 20
+#endif
+/*
+ After deciding the instruction entry (via hash.c) the instruction parser
+ will try to match the operands after the instruction to the required set
+ given in the entry operandfield. Every operand will result in a change in
+ the opcode or the addition of data to the opcode.
+ The operands in the source instruction are checked for inconsistent
+ semantics.
+
+ F : 32 bit float general form
+ L : 64 bit float "
+ B : byte "
+ W : word "
+ D : double-word "
+ A : double-word gen-address-form ie no regs, no immediate
+ I : integer writeable gen int except immediate (A + reg)
+ Z : floating writeable gen float except immediate (Z + freg)
+ d : displacement
+ b : displacement - pc relative addressing acb
+ p : displacement - pc relative addressing br bcond bsr cxp
+ q : quick
+ i : immediate (8 bits)
+ This is not a standard ns32k operandtype, it is used to build
+ instructions like svc arg1,arg2
+ Svc is the instruction SuperVisorCall and is sometimes used to
+ call OS-routines from usermode. Some args might be handy!
+ r : register number (3 bits)
+ O : setcfg instruction optionslist
+ C : cinv instruction optionslist
+ S : stringinstruction optionslist
+ U : registerlist save,enter
+ u : registerlist restore,exit
+ M : mmu register
+ P : cpu register
+ g : 3:rd operand of inss or exts instruction
+ G : 4:th operand of inss or exts instruction
+ Those operands are encoded in the same byte.
+ This byte is placed last in the instruction.
+ f : operand of sfsr
+ H : sequent-hack for bsr (Warning)
+
+column 1 instructions
+ 2 number of bits in opcode.
+ 3 number of bits in opcode explicitly
+ determined by the instruction type.
+ 4 opcodeseed, the number we build our opcode
+ from.
+ 5 operandtypes, used by operandparser.
+ 6 size in bytes of immediate
+*/
+struct ns32k_opcode {
+ char *name;
+ unsigned char opcode_id_size; /* not used by the assembler */
+ unsigned char opcode_size;
+ unsigned long opcode_seed;
+ char *operands;
+ unsigned char im_size; /* not used by dissassembler */
+ char *default_args; /* default to those args when none given */
+ char default_modec; /* default to this addr-mode when ambigous
+ ie when the argument of a general addr-mode
+ is a plain constant */
+ char default_model; /* is a plain label */
+};
+
+#ifdef comment
+/* This section was from the gdb version of this file. */
+
+#ifndef ns32k_opcodeT
+#define ns32k_opcodeT int
+#endif /* no ns32k_opcodeT */
+
+struct not_wot /* ns32k opcode table: wot to do with this */
+ /* particular opcode */
+{
+ int obits; /* number of opcode bits */
+ int ibits; /* number of instruction bits */
+ ns32k_opcodeT code; /* op-code (may be > 8 bits!) */
+ char *args; /* how to compile said opcode */
+};
+
+struct not /* ns32k opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct not_wot detail; /* rest of opcode table [datum] */
+};
+
+/* Instructions look like this:
+
+ basic instruction--1, 2, or 3 bytes
+ index byte for operand A, if operand A is indexed--1 byte
+ index byte for operand B, if operand B is indexed--1 byte
+ addressing extension for operand A
+ addressing extension for operand B
+ implied operands
+
+ Operand A is the operand listed first in the following opcode table.
+ Operand B is the operand listed second in the following opcode table.
+ All instructions have at most 2 general operands, so this is enough.
+ The implied operands are associated with operands other than A and B.
+
+ Each operand has a digit and a letter.
+
+ The digit gives the position in the assembly language. The letter,
+ one of the following, tells us what kind of operand it is. */
+
+/* F : 32 bit float
+ * L : 64 bit float
+ * B : byte
+ * W : word
+ * D : double-word
+ * I : integer not immediate
+ * Z : floating not immediate
+ * d : displacement
+ * q : quick
+ * i : immediate (8 bits)
+ * r : register number (3 bits)
+ * p : displacement - pc relative addressing
+*/
+
+
+#endif /* comment */
+
+static const struct ns32k_opcode ns32k_opcodes[]=
+{
+ { "absf", 14,24, 0x35be, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "absl", 14,24, 0x34be, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "absb", 14,24, 0x304e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "absw", 14,24, 0x314e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "absd", 14,24, 0x334e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "acbb", 7,16, 0x4c, "2I1q3p", 1, "", DEF_MODEC,DEF_MODEL },
+ { "acbw", 7,16, 0x4d, "2I1q3p", 2, "", DEF_MODEC,DEF_MODEL },
+ { "acbd", 7,16, 0x4f, "2I1q3p", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addf", 14,24, 0x01be, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addl", 14,24, 0x00be, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "addb", 6,16, 0x00, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addw", 6,16, 0x01, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addd", 6,16, 0x03, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addcb", 6,16, 0x10, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addcw", 6,16, 0x11, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addcd", 6,16, 0x13, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addpb", 14,24, 0x3c4e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addpw", 14,24, 0x3d4e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addpd", 14,24, 0x3f4e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addqb", 7,16, 0x0c, "2I1q", 1, "", DEF_MODEC,DEF_MODEL },
+ { "addqw", 7,16, 0x0d, "2I1q", 2, "", DEF_MODEC,DEF_MODEL },
+ { "addqd", 7,16, 0x0f, "2I1q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "addr", 6,16, 0x27, "1A2I", 4, "", 21,21 },
+ { "adjspb", 11,16, 0x057c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "adjspw", 11,16, 0x057d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "adjspd", 11,16, 0x057f, "1D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "andb", 6,16, 0x28, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "andw", 6,16, 0x29, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "andd", 6,16, 0x2b, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "ashb", 14,24, 0x044e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ashw", 14,24, 0x054e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ashd", 14,24, 0x074e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "beq", 8,8, 0x0a, "1p", 0, "", 21,21 },
+ { "bne", 8,8, 0x1a, "1p", 0, "", 21,21 },
+ { "bcs", 8,8, 0x2a, "1p", 0, "", 21,21 },
+ { "bcc", 8,8, 0x3a, "1p", 0, "", 21,21 },
+ { "bhi", 8,8, 0x4a, "1p", 0, "", 21,21 },
+ { "bls", 8,8, 0x5a, "1p", 0, "", 21,21 },
+ { "bgt", 8,8, 0x6a, "1p", 0, "", 21,21 },
+ { "ble", 8,8, 0x7a, "1p", 0, "", 21,21 },
+ { "bfs", 8,8, 0x8a, "1p", 0, "", 21,21 },
+ { "bfc", 8,8, 0x9a, "1p", 0, "", 21,21 },
+ { "blo", 8,8, 0xaa, "1p", 0, "", 21,21 },
+ { "bhs", 8,8, 0xba, "1p", 0, "", 21,21 },
+ { "blt", 8,8, 0xca, "1p", 0, "", 21,21 },
+ { "bge", 8,8, 0xda, "1p", 0, "", 21,21 },
+ { "but", 8,8, 0xea, "1p", 0, "", 21,21 },
+ { "buf", 8,8, 0xfa, "1p", 0, "", 21,21 },
+ { "bicb", 6,16, 0x08, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "bicw", 6,16, 0x09, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "bicd", 6,16, 0x0b, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "bicpsrb", 11,16, 0x17c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "bicpsrw", 11,16, 0x17d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "bispsrb", 11,16, 0x37c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "bispsrw", 11,16, 0x37d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "bpt", 8,8, 0xf2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "br", 8,8, 0xea, "1p", 0, "", 21,21 },
+#ifdef SEQUENT_COMPATABILITY
+ { "bsr", 8,8, 0x02, "1H", 0, "", 21,21 },
+#else
+ { "bsr", 8,8, 0x02, "1p", 0, "", 21,21 },
+#endif
+ { "caseb", 11,16, 0x77c, "1B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "casew", 11,16, 0x77d, "1W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cased", 11,16, 0x77f, "1D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cbitb", 14,24, 0x084e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cbitw", 14,24, 0x094e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cbitd", 14,24, 0x0b4e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cbitib", 14,24, 0x0c4e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cbitiw", 14,24, 0x0d4e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cbitid", 14,24, 0x0f4e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "checkb", 11,24, 0x0ee, "2A3B1r", 1, "", DEF_MODEC,DEF_MODEL },
+ { "checkw", 11,24, 0x1ee, "2A3W1r", 2, "", DEF_MODEC,DEF_MODEL },
+ { "checkd", 11,24, 0x3ee, "2A3D1r", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cinv", 14,24, 0x271e, "2D1C", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpf", 14,24, 0x09be, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpl", 14,24, 0x08be, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "cmpb", 6,16, 0x04, "1B2B", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cmpw", 6,16, 0x05, "1W2W", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cmpd", 6,16, 0x07, "1D2D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpmb", 14,24, 0x04ce, "1A2A3b", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cmpmw", 14,24, 0x05ce, "1A2A3b", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cmpmd", 14,24, 0x07ce, "1A2A3b", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpqb", 7,16, 0x1c, "2B1q", 1, "", DEF_MODEC,DEF_MODEL },
+ { "cmpqw", 7,16, 0x1d, "2W1q", 2, "", DEF_MODEC,DEF_MODEL },
+ { "cmpqd", 7,16, 0x1f, "2D1q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cmpsb", 16,24, 0x040e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "cmpsw", 16,24, 0x050e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "cmpsd", 16,24, 0x070e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "cmpst", 16,24, 0x840e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "comb", 14,24, 0x344e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "comw", 14,24, 0x354e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "comd", 14,24, 0x374e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cvtp", 11,24, 0x036e, "2A3D1r", 4, "", DEF_MODEC,DEF_MODEL },
+ { "cxp", 8,8, 0x22, "1p", 0, "", 21,21 },
+ { "cxpd", 11,16, 0x07f, "1A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "deib", 14,24, 0x2cce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "deiw", 14,24, 0x2dce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "deid", 14,24, 0x2fce, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "dia", 8,8, 0xc2, "", 1, "", DEF_MODEC,DEF_MODEL },
+ { "divf", 14,24, 0x21be, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "divl", 14,24, 0x20be, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "divb", 14,24, 0x3cce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "divw", 14,24, 0x3dce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "divd", 14,24, 0x3fce, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "enter", 8,8, 0x82, "1U2d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "exit", 8,8, 0x92, "1u", 0, "", DEF_MODEC,DEF_MODEL },
+ { "extb", 11,24, 0x02e, "2I3B1r4d", 1, "", DEF_MODEC,DEF_MODEL },
+ { "extw", 11,24, 0x12e, "2I3W1r4d", 2, "", DEF_MODEC,DEF_MODEL },
+ { "extd", 11,24, 0x32e, "2I3D1r4d", 4, "", DEF_MODEC,DEF_MODEL },
+ { "extsb", 14,24, 0x0cce, "1I2I4G3g", 1, "", DEF_MODEC,DEF_MODEL },
+ { "extsw", 14,24, 0x0dce, "1I2I4G3g", 2, "", DEF_MODEC,DEF_MODEL },
+ { "extsd", 14,24, 0x0fce, "1I2I4G3g", 4, "", DEF_MODEC,DEF_MODEL },
+ { "ffsb", 14,24, 0x046e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ffsw", 14,24, 0x056e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "ffsd", 14,24, 0x076e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "flag", 8,8, 0xd2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "floorfb", 14,24, 0x3c3e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "floorfw", 14,24, 0x3d3e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "floorfd", 14,24, 0x3f3e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "floorlb", 14,24, 0x383e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "floorlw", 14,24, 0x393e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "floorld", 14,24, 0x3b3e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "ibitb", 14,24, 0x384e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "ibitw", 14,24, 0x394e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "ibitd", 14,24, 0x3b4e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "indexb", 11,24, 0x42e, "2B3B1r", 1, "", DEF_MODEC,DEF_MODEL },
+ { "indexw", 11,24, 0x52e, "2W3W1r", 2, "", DEF_MODEC,DEF_MODEL },
+ { "indexd", 11,24, 0x72e, "2D3D1r", 4, "", DEF_MODEC,DEF_MODEL },
+ { "insb", 11,24, 0x0ae, "2B3I1r4d", 1, "", DEF_MODEC,DEF_MODEL },
+ { "insw", 11,24, 0x1ae, "2W3I1r4d", 2, "", DEF_MODEC,DEF_MODEL },
+ { "insd", 11,24, 0x3ae, "2D3I1r4d", 4, "", DEF_MODEC,DEF_MODEL },
+ { "inssb", 14,24, 0x08ce, "1B2I4G3g", 1, "", DEF_MODEC,DEF_MODEL },
+ { "inssw", 14,24, 0x09ce, "1W2I4G3g", 2, "", DEF_MODEC,DEF_MODEL },
+ { "inssd", 14,24, 0x0bce, "1D2I4G3g", 4, "", DEF_MODEC,DEF_MODEL },
+ { "jsr", 11,16, 0x67f, "1A", 4, "", 21,21 },
+ { "jump", 11,16, 0x27f, "1A", 4, "", 21,21 },
+ { "lfsr", 19,24, 0x00f3e,"1D", 4, "", DEF_MODEC,DEF_MODEL },
+ { "lmr", 15,24, 0x0b1e, "2D1M", 4, "", DEF_MODEC,DEF_MODEL },
+ { "lprb", 7,16, 0x6c, "2B1P", 1, "", DEF_MODEC,DEF_MODEL },
+ { "lprw", 7,16, 0x6d, "2W1P", 2, "", DEF_MODEC,DEF_MODEL },
+ { "lprd", 7,16, 0x6f, "2D1P", 4, "", DEF_MODEC,DEF_MODEL },
+ { "lshb", 14,24, 0x144e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "lshw", 14,24, 0x154e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "lshd", 14,24, 0x174e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "meib", 14,24, 0x24ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "meiw", 14,24, 0x25ce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "meid", 14,24, 0x27ce, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "modb", 14,24, 0x38ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "modw", 14,24, 0x39ce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "modd", 14,24, 0x3bce, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movf", 14,24, 0x05be, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movl", 14,24, 0x04be, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "movb", 6,16, 0x14, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movw", 6,16, 0x15, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movd", 6,16, 0x17, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movbf", 14,24, 0x043e, "1B2Z", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movwf", 14,24, 0x053e, "1W2Z", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movdf", 14,24, 0x073e, "1D2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movbl", 14,24, 0x003e, "1B2Z", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movwl", 14,24, 0x013e, "1W2Z", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movdl", 14,24, 0x033e, "1D2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movfl", 14,24, 0x1b3e, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movlf", 14,24, 0x163e, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "movmb", 14,24, 0x00ce, "1A2A3b", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movmw", 14,24, 0x01ce, "1A2A3b", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movmd", 14,24, 0x03ce, "1A2A3b", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movqb", 7,16, 0x5c, "2I1q", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movqw", 7,16, 0x5d, "2I1q", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movqd", 7,16, 0x5f, "2I1q", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movsb", 16,24, 0x000e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movsw", 16,24, 0x010e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movsd", 16,24, 0x030e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movst", 16,24, 0x800e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "movsub", 14,24, 0x0cae, "1A2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movsuw", 14,24, 0x0dae, "1A2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movsud", 14,24, 0x0fae, "1A2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movusb", 14,24, 0x1cae, "1A2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movusw", 14,24, 0x1dae, "1A2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movusd", 14,24, 0x1fae, "1A2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "movxbd", 14,24, 0x1cce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movxwd", 14,24, 0x1dce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movxbw", 14,24, 0x10ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movzbd", 14,24, 0x18ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "movzwd", 14,24, 0x19ce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "movzbw", 14,24, 0x14ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "mulf", 14,24, 0x31be, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "mull", 14,24, 0x30be, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "mulb", 14,24, 0x20ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "mulw", 14,24, 0x21ce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "muld", 14,24, 0x23ce, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "negf", 14,24, 0x15be, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "negl", 14,24, 0x14be, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "negb", 14,24, 0x204e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "negw", 14,24, 0x214e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "negd", 14,24, 0x234e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "nop", 8,8, 0xa2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "notb", 14,24, 0x244e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "notw", 14,24, 0x254e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "notd", 14,24, 0x274e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "orb", 6,16, 0x18, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "orw", 6,16, 0x19, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "ord", 6,16, 0x1b, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "quob", 14,24, 0x30ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "quow", 14,24, 0x31ce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "quod", 14,24, 0x33ce, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "rdval", 19,24, 0x0031e,"1A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "remb", 14,24, 0x34ce, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "remw", 14,24, 0x35ce, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "remd", 14,24, 0x37ce, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "restore", 8,8, 0x72, "1u", 0, "", DEF_MODEC,DEF_MODEL },
+ { "ret", 8,8, 0x12, "1d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "reti", 8,8, 0x52, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "rett", 8,8, 0x42, "1d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "rotb", 14,24, 0x004e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "rotw", 14,24, 0x014e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "rotd", 14,24, 0x034e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "roundfb", 14,24, 0x243e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "roundfw", 14,24, 0x253e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "roundfd", 14,24, 0x273e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "roundlb", 14,24, 0x203e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "roundlw", 14,24, 0x213e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "roundld", 14,24, 0x233e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "rxp", 8,8, 0x32, "1d", 0, "", DEF_MODEC,DEF_MODEL },
+ { "seqb", 11,16, 0x3c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "seqw", 11,16, 0x3d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "seqd", 11,16, 0x3f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sneb", 11,16, 0xbc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "snew", 11,16, 0xbd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sned", 11,16, 0xbf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "scsb", 11,16, 0x13c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "scsw", 11,16, 0x13d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "scsd", 11,16, 0x13f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sccb", 11,16, 0x1bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sccw", 11,16, 0x1bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sccd", 11,16, 0x1bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shib", 11,16, 0x23c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shiw", 11,16, 0x23d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shid", 11,16, 0x23f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slsb", 11,16, 0x2bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slsw", 11,16, 0x2bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slsd", 11,16, 0x2bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgtb", 11,16, 0x33c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgtw", 11,16, 0x33d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgtd", 11,16, 0x33f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sleb", 11,16, 0x3bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slew", 11,16, 0x3bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sled", 11,16, 0x3bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsb", 11,16, 0x43c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsw", 11,16, 0x43d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsd", 11,16, 0x43f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfcb", 11,16, 0x4bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfcw", 11,16, 0x4bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfcd", 11,16, 0x4bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slob", 11,16, 0x53c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slow", 11,16, 0x53d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "slod", 11,16, 0x53f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shsb", 11,16, 0x5bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shsw", 11,16, 0x5bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "shsd", 11,16, 0x5bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sltb", 11,16, 0x63c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sltw", 11,16, 0x63d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sltd", 11,16, 0x63f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgeb", 11,16, 0x6bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sgew", 11,16, 0x6bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sged", 11,16, 0x6bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sutb", 11,16, 0x73c, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sutw", 11,16, 0x73d, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sutd", 11,16, 0x73f, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sufb", 11,16, 0x7bc, "1B", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sufw", 11,16, 0x7bd, "1W", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sufd", 11,16, 0x7bf, "1D", 0, "", DEF_MODEC,DEF_MODEL },
+ { "save", 8,8, 0x62, "1U", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sbitb", 14,24, 0x184e, "1B2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "sbitw", 14,24, 0x194e, "1W2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "sbitd", 14,24, 0x1b4e, "1D2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "sbitib", 14,24, 0x1c4e, "1B2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "sbitiw", 14,24, 0x1d4e, "1W2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "sbitid", 14,24, 0x1f4e, "1D2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "setcfg", 15,24, 0x0b0e, "1O", 0, "", DEF_MODEC,DEF_MODEL },
+ { "sfsr", 14,24, 0x373e, "1f", 0, "", DEF_MODEC,DEF_MODEL },
+ { "skpsb", 16,24, 0x0c0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "skpsw", 16,24, 0x0d0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "skpsd", 16,24, 0x0f0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "skpst", 16,24, 0x8c0e, "1S", 0, "[]", DEF_MODEC,DEF_MODEL },
+ { "smr", 15,24, 0x0f1e, "2I1M", 4, "", DEF_MODEC,DEF_MODEL },
+ { "sprb", 7,16, 0x2c, "2I1P", 1, "", DEF_MODEC,DEF_MODEL },
+ { "sprw", 7,16, 0x2d, "2I1P", 2, "", DEF_MODEC,DEF_MODEL },
+ { "sprd", 7,16, 0x2f, "2I1P", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subf", 14,24, 0x11be, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subl", 14,24, 0x10be, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "subb", 6,16, 0x20, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "subw", 6,16, 0x21, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "subd", 6,16, 0x23, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subcb", 6,16, 0x30, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "subcw", 6,16, 0x31, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "subcd", 6,16, 0x33, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "subpb", 14,24, 0x2c4e, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "subpw", 14,24, 0x2d4e, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "subpd", 14,24, 0x2f4e, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+#ifdef NS32K_SVC_IMMED_OPERANDS
+ { "svc", 8,8, 0xe2, "2i1i", 1, "", DEF_MODEC,DEF_MODEL }, /* not really, but some unix uses it */
+#else
+ { "svc", 8,8, 0xe2, "", 0, "", DEF_MODEC,DEF_MODEL },
+#endif
+ { "tbitb", 6,16, 0x34, "1B2A", 1, "", DEF_MODEC,DEF_MODEL },
+ { "tbitw", 6,16, 0x35, "1W2A", 2, "", DEF_MODEC,DEF_MODEL },
+ { "tbitd", 6,16, 0x37, "1D2A", 4, "", DEF_MODEC,DEF_MODEL },
+ { "truncfb", 14,24, 0x2c3e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "truncfw", 14,24, 0x2d3e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "truncfd", 14,24, 0x2f3e, "1F2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "trunclb", 14,24, 0x283e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "trunclw", 14,24, 0x293e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "truncld", 14,24, 0x2b3e, "1L2I", 8, "", DEF_MODEC,DEF_MODEL },
+ { "wait", 8,8, 0xb2, "", 0, "", DEF_MODEC,DEF_MODEL },
+ { "wrval", 19,24, 0x0071e,"1A", 0, "", DEF_MODEC,DEF_MODEL },
+ { "xorb", 6,16, 0x38, "1B2I", 1, "", DEF_MODEC,DEF_MODEL },
+ { "xorw", 6,16, 0x39, "1W2I", 2, "", DEF_MODEC,DEF_MODEL },
+ { "xord", 6,16, 0x3b, "1D2I", 4, "", DEF_MODEC,DEF_MODEL },
+ { "dotf", 14,24, 0x0dfe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "dotl", 14,24, 0x0cfe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "logbf", 14,24, 0x15fe, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "logbl", 14,24, 0x14fe, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+ { "polyf", 14,24, 0x09fe, "1F2F", 4, "", DEF_MODEC,DEF_MODEL },
+ { "polyl", 14,24, 0x08fe, "1L2L", 8, "", DEF_MODEC,DEF_MODEL },
+ { "scalbf", 14,24, 0x11fe, "1F2Z", 4, "", DEF_MODEC,DEF_MODEL },
+ { "scalbl", 14,24, 0x10fe, "1L2Z", 8, "", DEF_MODEC,DEF_MODEL },
+};
+
+static const int numopcodes=sizeof(ns32k_opcodes)/sizeof(ns32k_opcodes[0]);
+
+static const struct ns32k_opcode *const endop = ns32k_opcodes+sizeof(ns32k_opcodes)/sizeof(ns32k_opcodes[0]);
+
+#define MAX_ARGS 4
+#define ARG_LEN 50
+
diff --git a/contrib/gdb/include/opcode/pn.h b/contrib/gdb/include/opcode/pn.h
new file mode 100644
index 0000000..0f59a2a
--- /dev/null
+++ b/contrib/gdb/include/opcode/pn.h
@@ -0,0 +1,282 @@
+/* Print GOULD PN (PowerNode) instructions for GDB, the GNU debugger.
+ Copyright (C) 1986, 1987, 1989 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+struct gld_opcode
+{
+ char *name;
+ unsigned long opcode;
+ unsigned long mask;
+ char *args;
+ int length;
+};
+
+/* We store four bytes of opcode for all opcodes because that
+ is the most any of them need. The actual length of an instruction
+ is always at least 2 bytes, and at most four. The length of the
+ instruction is based on the opcode.
+
+ The mask component is a mask saying which bits must match
+ particular opcode in order for an instruction to be an instance
+ of that opcode.
+
+ The args component is a string containing characters
+ that are used to format the arguments to the instruction. */
+
+/* Kinds of operands:
+ r Register in first field
+ R Register in second field
+ b Base register in first field
+ B Base register in second field
+ v Vector register in first field
+ V Vector register in first field
+ A Optional address register (base register)
+ X Optional index register
+ I Immediate data (16bits signed)
+ O Offset field (16bits signed)
+ h Offset field (15bits signed)
+ d Offset field (14bits signed)
+ S Shift count field
+
+ any other characters are printed as is...
+*/
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+struct gld_opcode gld_opcodes[] =
+{
+{ "abm", 0xa0080000, 0xfc080000, "f,xOA,X", 4 },
+{ "abr", 0x18080000, 0xfc0c0000, "r,f", 2 },
+{ "aci", 0xfc770000, 0xfc7f8000, "r,I", 4 },
+{ "adfd", 0xe0080002, 0xfc080002, "r,xOA,X", 4 },
+{ "adfw", 0xe0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "adi", 0xc8010000, 0xfc7f0000, "r,I", 4 },
+{ "admb", 0xb8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "admd", 0xb8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "admh", 0xb8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "admw", 0xb8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "adr", 0x38000000, 0xfc0f0000, "r,R", 2 },
+{ "adrfd", 0x38090000, 0xfc0f0000, "r,R", 2 },
+{ "adrfw", 0x38010000, 0xfc0f0000, "r,R", 2 },
+{ "adrm", 0x38080000, 0xfc0f0000, "r,R", 2 },
+{ "ai", 0xfc030000, 0xfc07ffff, "I", 4 },
+{ "anmb", 0x84080000, 0xfc080000, "r,xOA,X", 4 },
+{ "anmd", 0x84000002, 0xfc080002, "r,xOA,X", 4 },
+{ "anmh", 0x84000001, 0xfc080001, "r,xOA,X", 4 },
+{ "anmw", 0x84000000, 0xfc080000, "r,xOA,X", 4 },
+{ "anr", 0x04000000, 0xfc0f0000, "r,R", 2 },
+{ "armb", 0xe8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "armd", 0xe8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "armh", 0xe8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "armw", 0xe8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "bcf", 0xf0000000, 0xfc080000, "I,xOA,X", 4 },
+{ "bct", 0xec000000, 0xfc080000, "I,xOA,X", 4 },
+{ "bei", 0x00060000, 0xffff0000, "", 2 },
+{ "bft", 0xf0000000, 0xff880000, "xOA,X", 4 },
+{ "bib", 0xf4000000, 0xfc780000, "r,xOA", 4 },
+{ "bid", 0xf4600000, 0xfc780000, "r,xOA", 4 },
+{ "bih", 0xf4200000, 0xfc780000, "r,xOA", 4 },
+{ "biw", 0xf4400000, 0xfc780000, "r,xOA", 4 },
+{ "bl", 0xf8800000, 0xff880000, "xOA,X", 4 },
+{ "bsub", 0x5c080000, 0xff8f0000, "", 2 },
+{ "bsubm", 0x28080000, 0xfc080000, "", 4 },
+{ "bu", 0xec000000, 0xff880000, "xOA,X", 4 },
+{ "call", 0x28080000, 0xfc0f0000, "", 2 },
+{ "callm", 0x5c080000, 0xff880000, "", 4 },
+{ "camb", 0x90080000, 0xfc080000, "r,xOA,X", 4 },
+{ "camd", 0x90000002, 0xfc080002, "r,xOA,X", 4 },
+{ "camh", 0x90000001, 0xfc080001, "r,xOA,X", 4 },
+{ "camw", 0x90000000, 0xfc080000, "r.xOA,X", 4 },
+{ "car", 0x10000000, 0xfc0f0000, "r,R", 2 },
+{ "cd", 0xfc060000, 0xfc070000, "r,f", 4 },
+{ "cea", 0x000f0000, 0xffff0000, "", 2 },
+{ "ci", 0xc8050000, 0xfc7f0000, "r,I", 4 },
+{ "cmc", 0x040a0000, 0xfc7f0000, "r", 2 },
+{ "cmmb", 0x94080000, 0xfc080000, "r,xOA,X", 4 },
+{ "cmmd", 0x94000002, 0xfc080002, "r,xOA,X", 4 },
+{ "cmmh", 0x94000001, 0xfc080001, "r,xOA,X", 4 },
+{ "cmmw", 0x94000000, 0xfc080000, "r,xOA,X", 4 },
+{ "cmr", 0x14000000, 0xfc0f0000, "r,R", 2 },
+{ "daci", 0xfc7f0000, 0xfc7f8000, "r,I", 4 },
+{ "dae", 0x000e0000, 0xffff0000, "", 2 },
+{ "dai", 0xfc040000, 0xfc07ffff, "I", 4 },
+{ "dci", 0xfc6f0000, 0xfc7f8000, "r,I", 4 },
+{ "di", 0xfc010000, 0xfc07ffff, "I", 4 },
+{ "dvfd", 0xe4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "dvfw", 0xe4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvi", 0xc8040000, 0xfc7f0000, "r,I", 4 },
+{ "dvmb", 0xc4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvmh", 0xc4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "dvmw", 0xc4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "dvr", 0x380a0000, 0xfc0f0000, "r,R", 2 },
+{ "dvrfd", 0x380c0000, 0xfc0f0000, "r,R", 4 },
+{ "dvrfw", 0x38040000, 0xfc0f0000, "r,xOA,X", 4 },
+{ "eae", 0x00080000, 0xffff0000, "", 2 },
+{ "eci", 0xfc670000, 0xfc7f8080, "r,I", 4 },
+{ "ecwcs", 0xfc4f0000, 0xfc7f8000, "", 4 },
+{ "ei", 0xfc000000, 0xfc07ffff, "I", 4 },
+{ "eomb", 0x8c080000, 0xfc080000, "r,xOA,X", 4 },
+{ "eomd", 0x8c000002, 0xfc080002, "r,xOA,X", 4 },
+{ "eomh", 0x8c000001, 0xfc080001, "r,xOA,X", 4 },
+{ "eomw", 0x8c000000, 0xfc080000, "r,xOA,X", 4 },
+{ "eor", 0x0c000000, 0xfc0f0000, "r,R", 2 },
+{ "eorm", 0x0c080000, 0xfc0f0000, "r,R", 2 },
+{ "es", 0x00040000, 0xfc7f0000, "r", 2 },
+{ "exm", 0xa8000000, 0xff880000, "xOA,X", 4 },
+{ "exr", 0xc8070000, 0xfc7f0000, "r", 2 },
+{ "exrr", 0xc8070002, 0xfc7f0002, "r", 2 },
+{ "fixd", 0x380d0000, 0xfc0f0000, "r,R", 2 },
+{ "fixw", 0x38050000, 0xfc0f0000, "r,R", 2 },
+{ "fltd", 0x380f0000, 0xfc0f0000, "r,R", 2 },
+{ "fltw", 0x38070000, 0xfc0f0000, "r,R", 2 },
+{ "grio", 0xfc3f0000, 0xfc7f8000, "r,I", 4 },
+{ "halt", 0x00000000, 0xffff0000, "", 2 },
+{ "hio", 0xfc370000, 0xfc7f8000, "r,I", 4 },
+{ "jwcs", 0xfa080000, 0xff880000, "xOA,X", 4 },
+{ "la", 0x50000000, 0xfc000000, "r,xOA,X", 4 },
+{ "labr", 0x58080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lb", 0xac080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lcs", 0x00030000, 0xfc7f0000, "r", 2 },
+{ "ld", 0xac000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lear", 0x80000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lf", 0xcc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lfbr", 0xcc080000, 0xfc080000, "b,xOA,X", 4 },
+{ "lh", 0xac000001, 0xfc080001, "r,xOA,X", 4 },
+{ "li", 0xc8000000, 0xfc7f0000, "r,I", 4 },
+{ "lmap", 0x2c070000, 0xfc7f0000, "r", 2 },
+{ "lmb", 0xb0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lmd", 0xb0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lmh", 0xb0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lmw", 0xb0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnb", 0xb4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "lnd", 0xb4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "lnh", 0xb4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "lnw", 0xb4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lpsd", 0xf9800000, 0xff880000, "r,xOA,X", 4 },
+{ "lpsdcm", 0xfa800000, 0xff880000, "r,xOA,X", 4 },
+{ "lw", 0xac000000, 0xfc080000, "r,xOA,X", 4 },
+{ "lwbr", 0x5c000000, 0xfc080000, "b,xOA,X", 4 },
+{ "mpfd", 0xe4080002, 0xfc080002, "r,xOA,X", 4 },
+{ "mpfw", 0xe4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpi", 0xc8030000, 0xfc7f0000, "r,I", 4 },
+{ "mpmb", 0xc0080000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpmh", 0xc0000001, 0xfc080001, "r,xOA,X", 4 },
+{ "mpmw", 0xc0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "mpr", 0x38020000, 0xfc0f0000, "r,R", 2 },
+{ "mprfd", 0x380e0000, 0xfc0f0000, "r,R", 2 },
+{ "mprfw", 0x38060000, 0xfc0f0000, "r,R", 2 },
+{ "nop", 0x00020000, 0xffff0000, "", 2 },
+{ "ormb", 0x88080000, 0xfc080000, "r,xOA,X", 4 },
+{ "ormd", 0x88000002, 0xfc080002, "r,xOA,X", 4 },
+{ "ormh", 0x88000001, 0xfc080001, "r,xOA,X", 4 },
+{ "ormw", 0x88000000, 0xfc080000, "r,xOA,X", 4 },
+{ "orr", 0x08000000, 0xfc0f0000, "r,R", 2 },
+{ "orrm", 0x08080000, 0xfc0f0000, "r,R", 2 },
+{ "rdsts", 0x00090000, 0xfc7f0000, "r", 2 },
+{ "return", 0x280e0000, 0xfc7f0000, "", 2 },
+{ "ri", 0xfc020000, 0xfc07ffff, "I", 4 },
+{ "rnd", 0x00050000, 0xfc7f0000, "r", 2 },
+{ "rpswt", 0x040b0000, 0xfc7f0000, "r", 2 },
+{ "rschnl", 0xfc2f0000, 0xfc7f8000, "r,I", 4 },
+{ "rsctl", 0xfc470000, 0xfc7f8000, "r,I", 4 },
+{ "rwcs", 0x000b0000, 0xfc0f0000, "r,R", 2 },
+{ "sacz", 0x10080000, 0xfc0f0000, "r,R", 2 },
+{ "sbm", 0x98080000, 0xfc080000, "f,xOA,X", 4 },
+{ "sbr", 0x18000000, 0xfc0c0000, "r,f", 4 },
+{ "sea", 0x000d0000, 0xffff0000, "", 2 },
+{ "setcpu", 0x2c090000, 0xfc7f0000, "r", 2 },
+{ "sio", 0xfc170000, 0xfc7f8000, "r,I", 4 },
+{ "sipu", 0x000a0000, 0xffff0000, "", 2 },
+{ "sla", 0x1c400000, 0xfc600000, "r,S", 2 },
+{ "slad", 0x20400000, 0xfc600000, "r,S", 2 },
+{ "slc", 0x24400000, 0xfc600000, "r,S", 2 },
+{ "sll", 0x1c600000, 0xfc600000, "r,S", 2 },
+{ "slld", 0x20600000, 0xfc600000, "r,S", 2 },
+{ "smc", 0x04070000, 0xfc070000, "", 2 },
+{ "sra", 0x1c000000, 0xfc600000, "r,S", 2 },
+{ "srad", 0x20000000, 0xfc600000, "r,S", 2 },
+{ "src", 0x24000000, 0xfc600000, "r,S", 2 },
+{ "srl", 0x1c200000, 0xfc600000, "r,S", 2 },
+{ "srld", 0x20200000, 0xfc600000, "r,S", 2 },
+{ "stb", 0xd4080000, 0xfc080000, "r,xOA,X", 4 },
+{ "std", 0xd4000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stf", 0xdc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stfbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "sth", 0xd4000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stmb", 0xd8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "stmd", 0xd8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "stmh", 0xd8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "stmw", 0xd8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stpio", 0xfc270000, 0xfc7f8000, "r,I", 4 },
+{ "stw", 0xd4000000, 0xfc080000, "r,xOA,X", 4 },
+{ "stwbr", 0x54000000, 0xfc080000, "b,xOA,X", 4 },
+{ "suabr", 0x58000000, 0xfc080000, "b,xOA,X", 4 },
+{ "sufd", 0xe0000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sufw", 0xe0000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sui", 0xc8020000, 0xfc7f0000, "r,I", 4 },
+{ "sumb", 0xbc080000, 0xfc080000, "r,xOA,X", 4 },
+{ "sumd", 0xbc000002, 0xfc080002, "r,xOA,X", 4 },
+{ "sumh", 0xbc000001, 0xfc080001, "r,xOA,X", 4 },
+{ "sumw", 0xbc000000, 0xfc080000, "r,xOA,X", 4 },
+{ "sur", 0x3c000000, 0xfc0f0000, "r,R", 2 },
+{ "surfd", 0x380b0000, 0xfc0f0000, "r,xOA,X", 4 },
+{ "surfw", 0x38030000, 0xfc0f0000, "r,R", 2 },
+{ "surm", 0x3c080000, 0xfc0f0000, "r,R", 2 },
+{ "svc", 0xc8060000, 0xffff0000, "", 4 },
+{ "tbm", 0xa4080000, 0xfc080000, "f,xOA,X", 4 },
+{ "tbr", 0x180c0000, 0xfc0c0000, "r,f", 2 },
+{ "tbrr", 0x2c020000, 0xfc0f0000, "r,B", 2 },
+{ "tccr", 0x28040000, 0xfc7f0000, "", 2 },
+{ "td", 0xfc050000, 0xfc070000, "r,f", 4 },
+{ "tio", 0xfc1f0000, 0xfc7f8000, "r,I", 4 },
+{ "tmapr", 0x2c0a0000, 0xfc0f0000, "r,R", 2 },
+{ "tpcbr", 0x280c0000, 0xfc7f0000, "r", 2 },
+{ "trbr", 0x2c010000, 0xfc0f0000, "b,R", 2 },
+{ "trc", 0x2c030000, 0xfc0f0000, "r,R", 2 },
+{ "trcc", 0x28050000, 0xfc7f0000, "", 2 },
+{ "trcm", 0x2c0b0000, 0xfc0f0000, "r,R", 2 },
+{ "trn", 0x2c040000, 0xfc0f0000, "r,R", 2 },
+{ "trnm", 0x2c0c0000, 0xfc0f0000, "r,R", 2 },
+{ "trr", 0x2c000000, 0xfc0f0000, "r,R", 2 },
+{ "trrm", 0x2c080000, 0xfc0f0000, "r,R", 2 },
+{ "trsc", 0x2c0e0000, 0xfc0f0000, "r,R", 2 },
+{ "trsw", 0x28000000, 0xfc7f0000, "r", 2 },
+{ "tscr", 0x2c0f0000, 0xfc0f0000, "r,R", 2 },
+{ "uei", 0x00070000, 0xffff0000, "", 2 },
+{ "wait", 0x00010000, 0xffff0000, "", 2 },
+{ "wcwcs", 0xfc5f0000, 0xfc7f8000, "", 4 },
+{ "wwcs", 0x000c0000, 0xfc0f0000, "r,R", 2 },
+{ "xcbr", 0x28020000, 0xfc0f0000, "b,B", 2 },
+{ "xcr", 0x2c050000, 0xfc0f0000, "r,R", 2 },
+{ "xcrm", 0x2c0d0000, 0xfc0f0000, "r,R", 2 },
+{ "zbm", 0x9c080000, 0xfc080000, "f,xOA,X", 4 },
+{ "zbr", 0x18040000, 0xfc0c0000, "r,f", 2 },
+{ "zmb", 0xf8080000, 0xfc080000, "r,xOA,X", 4 },
+{ "zmd", 0xf8000002, 0xfc080002, "r,xOA,X", 4 },
+{ "zmh", 0xf8000001, 0xfc080001, "r,xOA,X", 4 },
+{ "zmw", 0xf8000000, 0xfc080000, "r,xOA,X", 4 },
+{ "zr", 0x0c000000, 0xfc0f0000, "r", 2 },
+};
+
+int numopcodes = sizeof(gld_opcodes) / sizeof(gld_opcodes[0]);
+
+struct gld_opcode *endop = gld_opcodes + sizeof(gld_opcodes) /
+ sizeof(gld_opcodes[0]);
diff --git a/contrib/gdb/include/opcode/ppc.h b/contrib/gdb/include/opcode/ppc.h
new file mode 100644
index 0000000..a9e3b24
--- /dev/null
+++ b/contrib/gdb/include/opcode/ppc.h
@@ -0,0 +1,248 @@
+/* ppc.h -- Header file for PowerPC opcode table
+ Copyright 1994, 1995 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Cygnus Support
+
+This file is part of GDB, GAS, and the GNU binutils.
+
+GDB, GAS, and the GNU binutils are free software; you can redistribute
+them and/or modify them under the terms of the GNU General Public
+License as published by the Free Software Foundation; either version
+1, or (at your option) any later version.
+
+GDB, GAS, and the GNU binutils are distributed in the hope that they
+will be useful, but WITHOUT ANY WARRANTY; without even the implied
+warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this file; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef PPC_H
+#define PPC_H
+
+/* The opcode table is an array of struct powerpc_opcode. */
+
+struct powerpc_opcode
+{
+ /* The opcode name. */
+ const char *name;
+
+ /* The opcode itself. Those bits which will be filled in with
+ operands are zeroes. */
+ unsigned long opcode;
+
+ /* The opcode mask. This is used by the disassembler. This is a
+ mask containing ones indicating those bits which must match the
+ opcode field, and zeroes indicating those bits which need not
+ match (and are presumably filled in by operands). */
+ unsigned long mask;
+
+ /* One bit flags for the opcode. These are used to indicate which
+ specific processors support the instructions. The defined values
+ are listed below. */
+ unsigned long flags;
+
+ /* An array of operand codes. Each code is an index into the
+ operand table. They appear in the order which the operands must
+ appear in assembly code, and are terminated by a zero. */
+ unsigned char operands[8];
+};
+
+/* The table itself is sorted by major opcode number, and is otherwise
+ in the order in which the disassembler should consider
+ instructions. */
+extern const struct powerpc_opcode powerpc_opcodes[];
+extern const int powerpc_num_opcodes;
+
+/* Values defined for the flags field of a struct powerpc_opcode. */
+
+/* Opcode is defined for the PowerPC architecture. */
+#define PPC_OPCODE_PPC (01)
+
+/* Opcode is defined for the POWER (RS/6000) architecture. */
+#define PPC_OPCODE_POWER (02)
+
+/* Opcode is defined for the POWER2 (Rios 2) architecture. */
+#define PPC_OPCODE_POWER2 (04)
+
+/* Opcode is only defined on 32 bit architectures. */
+#define PPC_OPCODE_32 (010)
+
+/* Opcode is only defined on 64 bit architectures. */
+#define PPC_OPCODE_64 (020)
+
+/* Opcode is supported by the Motorola PowerPC 601 processor. The 601
+ is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions,
+ but it also supports many additional POWER instructions. */
+#define PPC_OPCODE_601 (040)
+
+/* Opcode is supported in both the Power and PowerPC architectures
+ (ie, compiler's -mcpu=common or assembler's -mcom). */
+#define PPC_OPCODE_COMMON (0100)
+
+/* Opcode is supported for any Power or PowerPC platform (this is
+ for the assembler's -many option, and it eliminates duplicates). */
+#define PPC_OPCODE_ANY (0200)
+
+/* A macro to extract the major opcode from an instruction. */
+#define PPC_OP(i) (((i) >> 26) & 0x3f)
+
+/* The operands table is an array of struct powerpc_operand. */
+
+struct powerpc_operand
+{
+ /* The number of bits in the operand. */
+ int bits;
+
+ /* How far the operand is left shifted in the instruction. */
+ int shift;
+
+ /* Insertion function. This is used by the assembler. To insert an
+ operand value into an instruction, check this field.
+
+ If it is NULL, execute
+ i |= (op & ((1 << o->bits) - 1)) << o->shift;
+ (i is the instruction which we are filling in, o is a pointer to
+ this structure, and op is the opcode value; this assumes twos
+ complement arithmetic).
+
+ If this field is not NULL, then simply call it with the
+ instruction and the operand value. It will return the new value
+ of the instruction. If the ERRMSG argument is not NULL, then if
+ the operand value is illegal, *ERRMSG will be set to a warning
+ string (the operand will be inserted in any case). If the
+ operand value is legal, *ERRMSG will be unchanged (most operands
+ can accept any value). */
+ unsigned long (*insert) PARAMS ((unsigned long instruction, long op,
+ const char **errmsg));
+
+ /* Extraction function. This is used by the disassembler. To
+ extract this operand type from an instruction, check this field.
+
+ If it is NULL, compute
+ op = ((i) >> o->shift) & ((1 << o->bits) - 1);
+ if ((o->flags & PPC_OPERAND_SIGNED) != 0
+ && (op & (1 << (o->bits - 1))) != 0)
+ op -= 1 << o->bits;
+ (i is the instruction, o is a pointer to this structure, and op
+ is the result; this assumes twos complement arithmetic).
+
+ If this field is not NULL, then simply call it with the
+ instruction value. It will return the value of the operand. If
+ the INVALID argument is not NULL, *INVALID will be set to
+ non-zero if this operand type can not actually be extracted from
+ this operand (i.e., the instruction does not match). If the
+ operand is valid, *INVALID will not be changed. */
+ long (*extract) PARAMS ((unsigned long instruction, int *invalid));
+
+ /* One bit syntax flags. */
+ unsigned long flags;
+};
+
+/* Elements in the table are retrieved by indexing with values from
+ the operands field of the powerpc_opcodes table. */
+
+extern const struct powerpc_operand powerpc_operands[];
+
+/* Values defined for the flags field of a struct powerpc_operand. */
+
+/* This operand takes signed values. */
+#define PPC_OPERAND_SIGNED (01)
+
+/* This operand takes signed values, but also accepts a full positive
+ range of values when running in 32 bit mode. That is, if bits is
+ 16, it takes any value from -0x8000 to 0xffff. In 64 bit mode,
+ this flag is ignored. */
+#define PPC_OPERAND_SIGNOPT (02)
+
+/* This operand does not actually exist in the assembler input. This
+ is used to support extended mnemonics such as mr, for which two
+ operands fields are identical. The assembler should call the
+ insert function with any op value. The disassembler should call
+ the extract function, ignore the return value, and check the value
+ placed in the valid argument. */
+#define PPC_OPERAND_FAKE (04)
+
+/* The next operand should be wrapped in parentheses rather than
+ separated from this one by a comma. This is used for the load and
+ store instructions which want their operands to look like
+ reg,displacement(reg)
+ */
+#define PPC_OPERAND_PARENS (010)
+
+/* This operand may use the symbolic names for the CR fields, which
+ are
+ lt 0 gt 1 eq 2 so 3 un 3
+ cr0 0 cr1 1 cr2 2 cr3 3
+ cr4 4 cr5 5 cr6 6 cr7 7
+ These may be combined arithmetically, as in cr2*4+gt. These are
+ only supported on the PowerPC, not the POWER. */
+#define PPC_OPERAND_CR (020)
+
+/* This operand names a register. The disassembler uses this to print
+ register names with a leading 'r'. */
+#define PPC_OPERAND_GPR (040)
+
+/* This operand names a floating point register. The disassembler
+ prints these with a leading 'f'. */
+#define PPC_OPERAND_FPR (0100)
+
+/* This operand is a relative branch displacement. The disassembler
+ prints these symbolically if possible. */
+#define PPC_OPERAND_RELATIVE (0200)
+
+/* This operand is an absolute branch address. The disassembler
+ prints these symbolically if possible. */
+#define PPC_OPERAND_ABSOLUTE (0400)
+
+/* This operand is optional, and is zero if omitted. This is used for
+ the optional BF and L fields in the comparison instructions. The
+ assembler must count the number of operands remaining on the line,
+ and the number of operands remaining for the opcode, and decide
+ whether this operand is present or not. The disassembler should
+ print this operand out only if it is not zero. */
+#define PPC_OPERAND_OPTIONAL (01000)
+
+/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand
+ is omitted, then for the next operand use this operand value plus
+ 1, ignoring the next operand field for the opcode. This wretched
+ hack is needed because the Power rotate instructions can take
+ either 4 or 5 operands. The disassembler should print this operand
+ out regardless of the PPC_OPERAND_OPTIONAL field. */
+#define PPC_OPERAND_NEXT (02000)
+
+/* This operand should be regarded as a negative number for the
+ purposes of overflow checking (i.e., the normal most negative
+ number is disallowed and one more than the normal most positive
+ number is allowed). This flag will only be set for a signed
+ operand. */
+#define PPC_OPERAND_NEGATIVE (04000)
+
+/* The POWER and PowerPC assemblers use a few macros. We keep them
+ with the operands table for simplicity. The macro table is an
+ array of struct powerpc_macro. */
+
+struct powerpc_macro
+{
+ /* The macro name. */
+ const char *name;
+
+ /* The number of operands the macro takes. */
+ unsigned int operands;
+
+ /* One bit flags for the opcode. These are used to indicate which
+ specific processors support the instructions. The values are the
+ same as those for the struct powerpc_opcode flags field. */
+ unsigned long flags;
+
+ /* A format string to turn the macro into a normal instruction.
+ Each %N in the string is replaced with operand number N (zero
+ based). */
+ const char *format;
+};
+
+extern const struct powerpc_macro powerpc_macros[];
+extern const int powerpc_num_macros;
+
+#endif /* PPC_H */
diff --git a/contrib/gdb/include/opcode/pyr.h b/contrib/gdb/include/opcode/pyr.h
new file mode 100644
index 0000000..06632b8
--- /dev/null
+++ b/contrib/gdb/include/opcode/pyr.h
@@ -0,0 +1,287 @@
+/* pyramid.opcode.h -- gdb initial attempt. */
+
+/* pyramid opcode table: wot to do with this
+ particular opcode */
+
+struct pyr_datum
+{
+ char nargs;
+ char * args; /* how to compile said opcode */
+ unsigned long mask; /* Bit vector: which operand modes are valid
+ for this opcode */
+ unsigned char code; /* op-code (always 6(?) bits */
+};
+
+typedef struct pyr_insn_format {
+ unsigned int mode :4;
+ unsigned int operator :8;
+ unsigned int index_scale :2;
+ unsigned int index_reg :6;
+ unsigned int operand_1 :6;
+ unsigned int operand_2:6;
+} pyr_insn_format;
+
+
+/* We store four bytes of opcode for all opcodes.
+ Pyramid is sufficiently RISCy that:
+ - insns are always an integral number of words;
+ - the length of any insn can be told from the first word of
+ the insn. (ie, if there are zero, one, or two words of
+ immediate operand/offset).
+
+
+ The args component is a string containing two characters for each
+ operand of the instruction. The first specifies the kind of operand;
+ the second, the place it is stored. */
+
+/* Kinds of operands:
+ mask assembler syntax description
+ 0x0001: movw Rn,Rn register to register
+ 0x0002: movw K,Rn quick immediate to register
+ 0x0004: movw I,Rn long immediate to register
+ 0x0008: movw (Rn),Rn register indirect to register
+ movw (Rn)[x],Rn register indirect to register
+ 0x0010: movw I(Rn),Rn offset register indirect to register
+ movw I(Rn)[x],Rn offset register indirect, indexed, to register
+
+ 0x0020: movw Rn,(Rn) register to register indirect
+ 0x0040: movw K,(Rn) quick immediate to register indirect
+ 0x0080: movw I,(Rn) long immediate to register indirect
+ 0x0100: movw (Rn),(Rn) register indirect to-register indirect
+ 0x0100: movw (Rn),(Rn) register indirect to-register indirect
+ 0x0200: movw I(Rn),(Rn) register indirect+offset to register indirect
+ 0x0200: movw I(Rn),(Rn) register indirect+offset to register indirect
+
+ 0x0400: movw Rn,I(Rn) register to register indirect+offset
+ 0x0800: movw K,I(Rn) quick immediate to register indirect+offset
+ 0x1000: movw I,I(Rn) long immediate to register indirect+offset
+ 0x1000: movw (Rn),I(Rn) register indirect to-register indirect+offset
+ 0x1000: movw I(Rn),I(Rn) register indirect+offset to register indirect
+ +offset
+ 0x0000: (irregular) ???
+
+
+ Each insn has a four-bit field encoding the type(s) of its operands.
+*/
+
+/* Some common combinations
+ */
+
+/* the first 5,(0x1|0x2|0x4|0x8|0x10) ie (1|2|4|8|16), ie ( 32 -1)*/
+#define GEN_TO_REG (31)
+
+#define UNKNOWN ((unsigned long)-1)
+#define ANY (GEN_TO_REG | (GEN_TO_REG << 5) | (GEN_TO_REG << 15))
+
+#define CONVERT (1|8|0x10|0x20|0x200)
+
+#define K_TO_REG (2)
+#define I_TO_REG (4)
+#define NOTK_TO_REG (GEN_TO_REG & ~K_TO_REG)
+#define NOTI_TO_REG (GEN_TO_REG & ~I_TO_REG)
+
+/* The assembler requires that this array be sorted as follows:
+ all instances of the same mnemonic must be consecutive.
+ All instances of the same mnemonic with the same number of operands
+ must be consecutive.
+ */
+
+struct pyr_opcode /* pyr opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct pyr_datum datum; /* rest of opcode table [datum] */
+};
+
+#define pyr_how args
+#define pyr_nargs nargs
+#define pyr_mask mask
+#define pyr_name name
+
+struct pyr_opcode pyr_opcodes[] =
+{
+ {"movb", { 2, "", UNKNOWN, 0x11}, },
+ {"movh", { 2, "", UNKNOWN, 0x12} },
+ {"movw", { 2, "", ANY, 0x10} },
+ {"movl", { 2, "", ANY, 0x13} },
+ {"mnegw", { 2, "", (0x1|0x8|0x10), 0x14} },
+ {"mnegf", { 2, "", 0x1, 0x15} },
+ {"mnegd", { 2, "", 0x1, 0x16} },
+ {"mcomw", { 2, "", (0x1|0x8|0x10), 0x17} },
+ {"mabsw", { 2, "", (0x1|0x8|0x10), 0x18} },
+ {"mabsf", { 2, "", 0x1, 0x19} },
+ {"mabsd", { 2, "", 0x1, 0x1a} },
+ {"mtstw", { 2, "", (0x1|0x8|0x10), 0x1c} },
+ {"mtstf", { 2, "", 0x1, 0x1d} },
+ {"mtstd", { 2, "", 0x1, 0x1e} },
+ {"mova", { 2, "", 0x8|0x10, 0x1f} },
+ {"movzbw", { 2, "", (0x1|0x8|0x10), 0x20} },
+ {"movzhw", { 2, "", (0x1|0x8|0x10), 0x21} },
+ /* 2 insns out of order here */
+ {"movbl", { 2, "", 1, 0x4f} },
+ {"filbl", { 2, "", 1, 0x4e} },
+
+ {"cvtbw", { 2, "", CONVERT, 0x22} },
+ {"cvthw", { 2, "", CONVERT, 0x23} },
+ {"cvtwb", { 2, "", CONVERT, 0x24} },
+ {"cvtwh", { 2, "", CONVERT, 0x25} },
+ {"cvtwf", { 2, "", CONVERT, 0x26} },
+ {"cvtwd", { 2, "", CONVERT, 0x27} },
+ {"cvtfw", { 2, "", CONVERT, 0x28} },
+ {"cvtfd", { 2, "", CONVERT, 0x29} },
+ {"cvtdw", { 2, "", CONVERT, 0x2a} },
+ {"cvtdf", { 2, "", CONVERT, 0x2b} },
+
+ {"addw", { 2, "", GEN_TO_REG, 0x40} },
+ {"addwc", { 2, "", GEN_TO_REG, 0x41} },
+ {"subw", { 2, "", GEN_TO_REG, 0x42} },
+ {"subwb", { 2, "", GEN_TO_REG, 0x43} },
+ {"rsubw", { 2, "", GEN_TO_REG, 0x44} },
+ {"mulw", { 2, "", GEN_TO_REG, 0x45} },
+ {"emul", { 2, "", GEN_TO_REG, 0x47} },
+ {"umulw", { 2, "", GEN_TO_REG, 0x46} },
+ {"divw", { 2, "", GEN_TO_REG, 0x48} },
+ {"ediv", { 2, "", GEN_TO_REG, 0x4a} },
+ {"rdivw", { 2, "", GEN_TO_REG, 0x4b} },
+ {"udivw", { 2, "", GEN_TO_REG, 0x49} },
+ {"modw", { 2, "", GEN_TO_REG, 0x4c} },
+ {"umodw", { 2, "", GEN_TO_REG, 0x4d} },
+
+
+ {"addf", { 2, "", 1, 0x50} },
+ {"addd", { 2, "", 1, 0x51} },
+ {"subf", { 2, "", 1, 0x52} },
+ {"subd", { 2, "", 1, 0x53} },
+ {"mulf", { 2, "", 1, 0x56} },
+ {"muld", { 2, "", 1, 0x57} },
+ {"divf", { 2, "", 1, 0x58} },
+ {"divd", { 2, "", 1, 0x59} },
+
+
+ {"cmpb", { 2, "", UNKNOWN, 0x61} },
+ {"cmph", { 2, "", UNKNOWN, 0x62} },
+ {"cmpw", { 2, "", UNKNOWN, 0x60} },
+ {"ucmpb", { 2, "", UNKNOWN, 0x66} },
+ /* WHY no "ucmph"??? */
+ {"ucmpw", { 2, "", UNKNOWN, 0x65} },
+ {"xchw", { 2, "", UNKNOWN, 0x0f} },
+
+
+ {"andw", { 2, "", GEN_TO_REG, 0x30} },
+ {"orw", { 2, "", GEN_TO_REG, 0x31} },
+ {"xorw", { 2, "", GEN_TO_REG, 0x32} },
+ {"bicw", { 2, "", GEN_TO_REG, 0x33} },
+ {"lshlw", { 2, "", GEN_TO_REG, 0x38} },
+ {"ashlw", { 2, "", GEN_TO_REG, 0x3a} },
+ {"ashll", { 2, "", GEN_TO_REG, 0x3c} },
+ {"ashrw", { 2, "", GEN_TO_REG, 0x3b} },
+ {"ashrl", { 2, "", GEN_TO_REG, 0x3d} },
+ {"rotlw", { 2, "", GEN_TO_REG, 0x3e} },
+ {"rotrw", { 2, "", GEN_TO_REG, 0x3f} },
+
+ /* push and pop insns are "going away next release". */
+ {"pushw", { 2, "", GEN_TO_REG, 0x0c} },
+ {"popw", { 2, "", (0x1|0x8|0x10), 0x0d} },
+ {"pusha", { 2, "", (0x8|0x10), 0x0e} },
+
+ {"bitsw", { 2, "", UNKNOWN, 0x35} },
+ {"bitcw", { 2, "", UNKNOWN, 0x36} },
+ /* some kind of ibra/dbra insns??*/
+ {"icmpw", { 2, "", UNKNOWN, 0x67} },
+ {"dcmpw", { 2, "", (1|4|0x20|0x80|0x400|0x1000), 0x69} },/*FIXME*/
+ {"acmpw", { 2, "", 1, 0x6b} },
+
+ /* Call is written as a 1-op insn, but is always (dis)assembled as a 2-op
+ insn with a 2nd op of tr14. The assembler will have to grok this. */
+ {"call", { 2, "", GEN_TO_REG, 0x04} },
+ {"call", { 1, "", GEN_TO_REG, 0x04} },
+
+ {"callk", { 1, "", UNKNOWN, 0x06} },/* system call?*/
+ /* Ret is usually written as a 0-op insn, but gets disassembled as a
+ 1-op insn. The operand is always tr15. */
+ {"ret", { 0, "", UNKNOWN, 0x09} },
+ {"ret", { 1, "", UNKNOWN, 0x09} },
+ {"adsf", { 2, "", (1|2|4), 0x08} },
+ {"retd", { 2, "", UNKNOWN, 0x0a} },
+ {"btc", { 2, "", UNKNOWN, 0x01} },
+ {"bfc", { 2, "", UNKNOWN, 0x02} },
+ /* Careful: halt is 0x00000000. Jump must have some other (mode?)bit set?? */
+ {"jump", { 1, "", UNKNOWN, 0x00} },
+ {"btp", { 2, "", UNKNOWN, 0xf00} },
+ /* read control-stack pointer is another 1-or-2 operand insn. */
+ {"rcsp", { 2, "", UNKNOWN, 0x01f} },
+ {"rcsp", { 1, "", UNKNOWN, 0x01f} }
+};
+
+/* end: pyramid.opcode.h */
+/* One day I will have to take the time to find out what operands
+ are valid for these insns, and guess at what they mean.
+
+ I can't imagine what the "I???" insns (iglob, etc) do.
+
+ the arithmetic-sounding insns ending in "p" sound awfully like BCD
+ arithmetic insns:
+ dshlp -> Decimal SHift Left Packed
+ dshrp -> Decimal SHift Right Packed
+ and cvtlp would be convert long to packed.
+ I have no idea how the operands are interpreted; but having them be
+ a long register with (address, length) of an in-memory packed BCD operand
+ would not be surprising.
+ They are unlikely to be a packed bcd string: 64 bits of long give
+ is only 15 digits+sign, which isn't enough for COBOL.
+ */
+#if 0
+ {"wcsp", { 2, "", UNKNOWN, 0x00} }, /*write csp?*/
+ /* The OSx Operating System Porting Guide claims SSL does things
+ with tr12 (a register reserved to it) to do with static block-structure
+ references. SSL=Set Static Link? It's "Going away next release". */
+ {"ssl", { 2, "", UNKNOWN, 0x00} },
+ {"ccmps", { 2, "", UNKNOWN, 0x00} },
+ {"lcd", { 2, "", UNKNOWN, 0x00} },
+ {"uemul", { 2, "", UNKNOWN, 0x00} }, /*unsigned emul*/
+ {"srf", { 2, "", UNKNOWN, 0x00} }, /*Gidget time???*/
+ {"mnegp", { 2, "", UNKNOWN, 0x00} }, /move-neg phys?*/
+ {"ldp", { 2, "", UNKNOWN, 0x00} }, /*load phys?*/
+ {"ldti", { 2, "", UNKNOWN, 0x00} },
+ {"ldb", { 2, "", UNKNOWN, 0x00} },
+ {"stp", { 2, "", UNKNOWN, 0x00} },
+ {"stti", { 2, "", UNKNOWN, 0x00} },
+ {"stb", { 2, "", UNKNOWN, 0x00} },
+ {"stu", { 2, "", UNKNOWN, 0x00} },
+ {"addp", { 2, "", UNKNOWN, 0x00} },
+ {"subp", { 2, "", UNKNOWN, 0x00} },
+ {"mulp", { 2, "", UNKNOWN, 0x00} },
+ {"divp", { 2, "", UNKNOWN, 0x00} },
+ {"dshlp", { 2, "", UNKNOWN, 0x00} }, /* dec shl packed? */
+ {"dshrp", { 2, "", UNKNOWN, 0x00} }, /* dec shr packed? */
+ {"movs", { 2, "", UNKNOWN, 0x00} }, /*move (string?)?*/
+ {"cmpp", { 2, "", UNKNOWN, 0x00} }, /* cmp phys?*/
+ {"cmps", { 2, "", UNKNOWN, 0x00} }, /* cmp (string?)?*/
+ {"cvtlp", { 2, "", UNKNOWN, 0x00} }, /* cvt long to p??*/
+ {"cvtpl", { 2, "", UNKNOWN, 0x00} }, /* cvt p to l??*/
+ {"dintr", { 2, "", UNKNOWN, 0x00} }, /* ?? intr ?*/
+ {"rphysw", { 2, "", UNKNOWN, 0x00} }, /* read phys word?*/
+ {"wphysw", { 2, "", UNKNOWN, 0x00} }, /* write phys word?*/
+ {"cmovs", { 2, "", UNKNOWN, 0x00} },
+ {"rsubw", { 2, "", UNKNOWN, 0x00} },
+ {"bicpsw", { 2, "", UNKNOWN, 0x00} }, /* clr bit in psw? */
+ {"bispsw", { 2, "", UNKNOWN, 0x00} }, /* set bit in psw? */
+ {"eio", { 2, "", UNKNOWN, 0x00} }, /* ?? ?io ? */
+ {"callp", { 2, "", UNKNOWN, 0x00} }, /* call phys?*/
+ {"callr", { 2, "", UNKNOWN, 0x00} },
+ {"lpcxt", { 2, "", UNKNOWN, 0x00} }, /*load proc context*/
+ {"rei", { 2, "", UNKNOWN, 0x00} }, /*ret from intrpt*/
+ {"rport", { 2, "", UNKNOWN, 0x00} }, /*read-port?*/
+ {"rtod", { 2, "", UNKNOWN, 0x00} }, /*read-time-of-day?*/
+ {"ssi", { 2, "", UNKNOWN, 0x00} },
+ {"vtpa", { 2, "", UNKNOWN, 0x00} }, /*virt-to-phys-addr?*/
+ {"wicl", { 2, "", UNKNOWN, 0x00} }, /* write icl ? */
+ {"wport", { 2, "", UNKNOWN, 0x00} }, /*write-port?*/
+ {"wtod", { 2, "", UNKNOWN, 0x00} }, /*write-time-of-day?*/
+ {"flic", { 2, "", UNKNOWN, 0x00} },
+ {"iglob", { 2, "", UNKNOWN, 0x00} }, /* I global? */
+ {"iphys", { 2, "", UNKNOWN, 0x00} }, /* I physical? */
+ {"ipid", { 2, "", UNKNOWN, 0x00} }, /* I pid? */
+ {"ivect", { 2, "", UNKNOWN, 0x00} }, /* I vector? */
+ {"lamst", { 2, "", UNKNOWN, 0x00} },
+ {"tio", { 2, "", UNKNOWN, 0x00} },
+#endif
diff --git a/contrib/gdb/include/opcode/rs6k.h b/contrib/gdb/include/opcode/rs6k.h
new file mode 100644
index 0000000..fac9cf4
--- /dev/null
+++ b/contrib/gdb/include/opcode/rs6k.h
@@ -0,0 +1,254 @@
+/* IBM RS/6000 instruction set definitions, for GNU software. */
+
+/* These are all possible instruction formats as used in IBM Assembler
+ Language Reference, Appendix A. */
+
+typedef enum { A=0, B, D, I, M, SC, X, XL, XO, XFL, XFX } InsnFmt;
+
+/* Extended opcode masks. Used for extracting extended opcode values from
+ instructions. Each instruction's format decides which mask applies.
+ They *should* retain the same order as the above formats. */
+
+static int eopMask[] =
+ { 0x1f, 0, 0, 0, 0, 0, 0x3ff, 0x3ff, 0x1ff, 0x3ff, 0x3ff };
+
+/* All the things you need to know about an opcode. */
+
+typedef struct rs6000_insn {
+ char *operator; /* opcode name */
+ char *opr_ext; /* opcode name extension */
+ InsnFmt format; /* opcode format */
+ char p_opcode; /* primary opcode */
+ int e_opcode; /* extended opcode */
+ char oprnd_format[6]; /* operand format */
+} OPCODE;
+
+/* operand format specifiers */
+
+#define TO 1
+#define RA 2
+#define SI 3
+#define RT 4
+#define UI 5
+#define BF 6
+#define BFA 7
+#define BT 8
+#define BA 9
+#define BB 10
+#define BO 11
+#define BI 12
+#define RB 13
+#define RS 14
+#define SH 15
+#define MB 16
+#define ME 17
+#define SPR 18
+#define DIS 19
+#define FXM 21
+#define FRT 22
+#define NB 23
+#define FRS 24
+#define FRA 25
+#define FRB 26
+#define FRC 27
+#define FLM 28
+#define I 29
+#define LI 30
+#define A2 31
+#define TA14 32 /* 14 bit representation of target address */
+#define TA24 33 /* 24 bit representation of target address */
+#define FL1 34
+#define FL2 35
+#define LEV 36
+
+/* RS/6000 INSTRUCTION SET
+ (sorted on primary and extended opcode)
+
+ oprtr primary ext.
+operator ext format opcode opcode operand format
+------- ------- ------ ------- ------ --------------- */
+
+struct rs6000_insn rs6k_ops [] = {
+
+{"ti", 0, D, 3, -1, {TO,RA,SI,0} },
+{"muli", 0, D, 7, -1, {RT,RA,SI,0} },
+{"sfi", 0, D, 8, -1, {RT,RA,SI,0} },
+{"dozi", 0, D, 9, -1, {RT,RA,SI,0} },
+{"cmpli", 0, D, 10, -1, {BF,RA,UI,0} },
+{"cmpi", 0, D, 11, -1, {BF,RA,SI,0} },
+{"ai", 0, D, 12, -1, {RT,RA,SI,0} },
+{"ai.", 0, D, 13, -1, {RT,RA,SI,0} },
+{"lil", 0, D, 14, -1, {RT,SI,0} }, /* same as `cal' */
+{"cal", 0, D, 14, -1, {RT,DIS,RA,0} },
+{"liu", 0, D, 15, -1, {RT, UI,0} }, /* same as `cau' */
+{"cau", 0, D, 15, -1, {RT,RA,UI,0} },
+
+/* "1" indicates an exception--"bb" is only usable for some values of
+ BO, so the disassembler first matches this instruction and then changes
+ it to "bc" if that is the case. */
+{"bb", "1tfla", B, 16, -1, {LI,A2,0} },
+{"bc", "la", B, 16, -1, {BO,BI,TA14,0} },
+
+{"svc", "la", SC, 17, -1, {LEV,FL1,FL2,0} },
+{"b", "la", I, 18, -1, {TA24,0} },
+{"mcrf", 0, XL, 19, 0, {BF,BFA,0} },
+{"bcr", "l", XL, 19, 16, {BO,BI,0} },
+{"crnor", 0, XL, 19, 33, {BT,BA,BB,0} },
+{"rfi", 0, X, 19, 50, {0} },
+{"rfsvc", 0, X, 19, 82, {0} },
+{"crandc", 0, XL, 19, 129, {BT,BA,BB,0} },
+{"ics", 0, X, 19, 150, {0} },
+{"crxor", 0, XL, 19, 193, {BT,BA,BB,0} },
+{"crnand", 0, XL, 19, 225, {BT,BA,BB,0} },
+{"crand", 0, XL, 19, 257, {BT,BA,BB,0} },
+{"creqv", 0, XL, 19, 289, {BT,BA,BB,0} },
+{"crorc", 0, XL, 19, 417, {BT,BA,BB,0} },
+{"cror", 0, XL, 19, 449, {BT,BA,BB,0} },
+{"bcc", "l", XL, 19, 528, {BO,BI,0} },
+{"rlimi", ".", M, 20, -1, {RA,RS,SH,MB,ME,0} /*??*/},
+{"rlinm", ".", M, 21, -1, {RA,RS,SH,MB,ME,0} /*??*/},
+{"rlmi", ".", M, 22, -1, {RA,RS,RB,MB,ME,0} /*??*/},
+{"rlnm", ".", M, 23, -1, {RA,RS,RB,MB,ME,0} /*??*/},
+{"oril", 0, D, 24, -1, {RA,RS,UI,0} },
+{"oriu", 0, D, 25, -1, {RA,RS,UI,0} },
+{"xoril", 0, D, 26, -1, {RA,RS,UI,0} },
+{"xoriu", 0, D, 27, -1, {RA,RS,UI,0} },
+{"andil.", 0, D, 28, -1, {RA,RS,UI,0} },
+{"andiu.", 0, D, 29, -1, {RA,RS,UI,0} },
+{"cmp", 0, X, 31, 0, {BF,RA,RB,0} },
+{"t", 0, X, 31, 4, {TO,RA,RB,0} },
+{"sf", "o.", XO, 31, 8, {RT,RA,RB,0} },
+{"a", "o.", XO, 31, 10, {RT,RA,RB,0} },
+{"mfcr", 0, X, 31, 19, {RT,0} },
+{"lx", 0, X, 31, 23, {RT,RA,RB,0} },
+{"sl", ".", X, 31, 24, {RA,RS,RB,0} },
+{"cntlz", ".", XO, 31, 26, {RA,RS,0} },
+{"and", ".", X, 31, 28, {RA,RS,RB,0} },
+{"maskg", ".", X, 31, 29, {RA,RS,RB,0} },
+{"cmpl", 0, X, 31, 32, {BF,RA,RB,0} },
+{"sfe", "o.", XO, 31, 136, {RT,RA,RB,0} },
+{"lux", 0, X, 31, 55, {RT,RA,RB,0} },
+{"andc", ".", X, 31, 60, {RA,RS,RB,0} },
+{"mfmsr", 0, X, 31, 83, {RT,0} },
+{"lbzx", 0, X, 31, 87, {RT,RA,RB,0} },
+{"neg", "o.", XO, 31, 104, {RT,RA,0} },
+{"mul", "o.", XO, 31, 107, {RT,RA,RB,0} },
+{"lbzux", 0, X, 31, 119, {RT,RA,RB,0} },
+{"nor", ".", X, 31, 124, {RA,RS,RB,0} },
+{"ae", "o.", XO, 31, 138, {RT,RA,RB,0} },
+{"mtcrf", 0, XFX, 31, 144, {FXM,RS,0} },
+{"stx", 0, X, 31, 151, {RS,RA,RB,0} },
+{"slq", ".", X, 31, 152, {RA,RS,RB,0} },
+{"sle", ".", X, 31, 153, {RA,RS,RB,0} },
+{"stux", 0, X, 31, 183, {RS,RA,RB,0} },
+{"sliq", ".", X, 31, 184, {RA,RS,SH,0} },
+{"sfze", "o.", XO, 31, 200, {RT,RA,0} },
+{"aze", "o.", XO, 31, 202, {RT,RA,0} },
+{"stbx", 0, X, 31, 215, {RS,RA,RB,0} },
+{"sllq", ".", X, 31, 216, {RA,RS,RB,0} },
+{"sleq", ".", X, 31, 217, {RA,RS,RB,0} },
+{"sfme", "o.", XO, 31, 232, {RT,RA,0} },
+{"ame", "o.", XO, 31, 234, {RT,RA,0} },
+{"muls", "o.", XO, 31, 235, {RT,RA,RB,0} },
+{"stbux", 0, X, 31, 247, {RS,RA,RB,0} },
+{"slliq", ".", X, 31, 248, {RA,RS,SH,0} },
+{"doz", "o.", X, 31, 264, {RT,RA,RB,0} },
+{"cax", "o.", XO, 31, 266, {RT,RA,RB,0} },
+{"lscbx", ".", X, 31, 277, {RT,RA,RB,0} },
+{"lhzx", 0, X, 31, 279, {RT,RA,RB,0} },
+{"eqv", ".", X, 31, 284, {RA,RS,RB,0} },
+{"lhzux", 0, X, 31, 311, {RT,RA,RB,0} },
+{"xor", ".", X, 31, 316, {RA,RS,RB,0} },
+{"div", "o.", XO, 31, 331, {RT,RA,RB,0} },
+{"mfspr", 0, X, 31, 339, {RT,SPR,0} },
+{"lhax", 0, X, 31, 343, {RT,RA,RB,0} },
+{"abs", "o.", XO, 31, 360, {RT,RA,0} },
+{"divs", "o.", XO, 31, 363, {RT,RA,RB,0} },
+{"lhaux", 0, X, 31, 375, {RT,RA,RB,0} },
+{"sthx", 0, X, 31, 407, {RS,RA,RB,0} },
+{"orc", ".", X, 31, 412, {RA,RS,RB,0} },
+{"sthux", 0, X, 31, 439, {RS,RA,RB,0} },
+{"or", ".", X, 31, 444, {RA,RS,RB,0} },
+{"mtspr", 0, X, 31, 467, {SPR,RS,0} },
+{"nand", ".", X, 31, 476, {RA,RS,RB,0} },
+{"nabs", "o.", XO, 31, 488, {RT,RA,0} },
+{"mcrxr", 0, X, 31, 512, {BF,0} },
+{"lsx", 0, X, 31, 533, {RT,RA,RB,0} },
+{"lbrx", 0, X, 31, 534, {RT,RA,RB,0} },
+{"lfsx", 0, X, 31, 535, {FRT,RA,RB,0} },
+{"sr", ".", X, 31, 536, {RA,RS,RB,0} },
+{"rrib", ".", X, 31, 537, {RA,RS,RB,0} },
+{"maskir", ".", X, 31, 541, {RA,RS,RB,0} },
+{"lfsux", 0, X, 31, 567, {FRT,RA,RB,0} },
+{"lsi", 0, X, 31, 597, {RT,RA,NB,0} },
+{"lfdx", 0, X, 31, 599, {FRT,RA,RB,0} },
+{"lfdux", 0, X, 31, 631, {FRT,RA,RB,0} },
+{"stsx", 0, X, 31, 661, {RS,RA,RB,0} },
+{"stbrx", 0, X, 31, 662, {RS,RA,RB,0} },
+{"stfsx", 0, X, 31, 663, {FRS,RA,RB,0} },
+{"srq", ".", X, 31, 664, {RA,RS,RB,0} },
+{"sre", ".", X, 31, 665, {RA,RS,RB,0} },
+{"stfsux", 0, X, 31, 695, {FRS,RA,RB,0} },
+{"sriq", ".", X, 31, 696, {RA,RS,SH,0} },
+{"stsi", 0, X, 31, 725, {RS,RA,NB,0} },
+{"stfdx", 0, X, 31, 727, {FRS,RA,RB,0} },
+{"srlq", ".", X, 31, 728, {RA,RS,RB,0} },
+{"sreq", ".", X, 31, 729, {RA,RS,RB,0} },
+{"stfdux", 0, X, 31, 759, {FRS,RA,RB,0} },
+{"srliq", ".", X, 31, 760, {RA,RS,SH,0} },
+{"lhbrx", 0, X, 31, 790, {RT,RA,RB,0} },
+{"sra", ".", X, 31, 792, {RA,RS,RB,0} },
+{"srai", ".", X, 31, 824, {RA,RS,SH,0} },
+{"sthbrx", 0, X, 31, 918, {RS,RA,RB,0} },
+{"sraq", ".", X, 31, 920, {RA,RS,RB,0} },
+{"srea", ".", X, 31, 921, {RA,RS,RB,0} },
+{"exts", ".", X, 31, 922, {RA,RS,0} },
+{"sraiq", ".", X, 31, 952, {RA,RS,SH,0} },
+{"l", 0, D, 32, -1, {RT,DIS,RA,0} },
+{"lu", 0, D, 33, -1, {RT,DIS,RA,0} },
+{"lbz", 0, D, 34, -1, {RT,DIS,RA,0} },
+{"lbzu", 0, D, 35, -1, {RT,DIS,RA,0} },
+{"st", 0, D, 36, -1, {RS,DIS,RA,0} },
+{"stu", 0, D, 37, -1, {RS,DIS,RA,0} },
+{"stb", 0, D, 38, -1, {RS,DIS,RA,0} },
+{"stbu", 0, D, 39, -1, {RS,DIS,RA,0} },
+{"lhz", 0, D, 40, -1, {RT,DIS,RA,0} },
+{"lhzu", 0, D, 41, -1, {RT,DIS,RA,0} },
+{"lha", 0, D, 42, -1, {RT,DIS,RA,0} },
+{"lhau", 0, D, 43, -1, {RT,DIS,RA,0} },
+{"sth", 0, D, 44, -1, {RS,DIS,RA,0} },
+{"sthu", 0, D, 45, -1, {RS,DIS,RA,0} },
+{"lm", 0, D, 46, -1, {RT,DIS,RA,0} },
+{"stm", 0, D, 47, -1, {RS,DIS,RA,0} },
+{"lfs", 0, D, 48, -1, {FRT,DIS,RA,0} },
+{"lfsu", 0, D, 49, -1, {FRT,DIS,RA,0} },
+{"lfd", 0, D, 50, -1, {FRT,DIS,RA,0} },
+{"lfdu", 0, D, 51, -1, {FRT,DIS,RA,0} },
+{"stfs", 0, D, 52, -1, {FRS,DIS,RA,0} },
+{"stfsu", 0, D, 53, -1, {FRS,DIS,RA,0} },
+{"stfd", 0, D, 54, -1, {FRS,DIS,RA,0} },
+{"stfdu", 0, D, 55, -1, {FRS,DIS,RA,0} },
+{"fcmpu", 0, X, 63, 0, {BF,FRA,FRB,0} },
+{"frsp", ".", X, 63, 12, {FRT,FRB,0} },
+{"fd", ".", A, 63, 18, {FRT,FRA,FRB,0} },
+{"fs", ".", A, 63, 20, {FRT,FRA,FRB,0} },
+{"fa", ".", A, 63, 21, {FRT,FRA,FRB,0} },
+{"fm", ".", A, 63, 25, {FRT,FRA,FRC,0} },
+{"fms", ".", A, 63, 28, {FRT,FRA,FRC,FRB,0} },
+{"fma", ".", A, 63, 29, {FRT,FRA,FRC,FRB,0} },
+{"fnms", ".", A, 63, 30, {FRT,FRA,FRC,FRB,0} },
+{"fnma", ".", A, 63, 31, {FRT,FRA,FRC,FRB,0} },
+{"fcmpo", 0, X, 63, 32, {BF,FRA,FRB,0} },
+{"mtfsb1", ".", X, 63, 38, {BT,0} },
+{"fneg", ".", X, 63, 40, {FRT,FRB,0} },
+{"mcrfs", 0, X, 63, 64, {BF,BFA,0} },
+{"mtfsb0", ".", X, 63, 70, {BT,0} },
+{"fmr", ".", X, 63, 72, {FRT,FRB,0} },
+{"mtfsfi", ".", X, 63, 134, {BF,I,0} },
+{"fnabs", ".", X, 63, 136, {FRT,FRB,0} },
+{"fabs", ".", X, 63, 264, {FRT,FRB,0} },
+{"mffs", ".", X, 63, 583, {FRT,0} },
+{"mtfsf", ".", XFL, 63, 711, {FLM,FRB,0} },
+};
+
+#define NOPCODES (sizeof (rs6k_ops) / sizeof (struct rs6000_insn))
diff --git a/contrib/gdb/include/opcode/sparc.h b/contrib/gdb/include/opcode/sparc.h
new file mode 100644
index 0000000..b9281e6
--- /dev/null
+++ b/contrib/gdb/include/opcode/sparc.h
@@ -0,0 +1,220 @@
+/* Definitions for opcode table for the sparc.
+ Copyright (C) 1989, 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of GAS, the GNU Assembler, GDB, the GNU debugger, and
+the GNU Binutils.
+
+GAS/GDB is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GAS/GDB is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GAS or GDB; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* The SPARC opcode table (and other related data) is defined in
+ the opcodes library in sparc-opc.c. If you change anything here, make
+ sure you fix up that file, and vice versa. */
+
+ /* FIXME-someday: perhaps the ,a's and such should be embedded in the
+ instruction's name rather than the args. This would make gas faster, pinsn
+ slower, but would mess up some macros a bit. xoxorich. */
+
+/* List of instruction sets variations.
+ These values are such that each element is either a superset of a
+ preceding each one or they conflict in which case SPARC_OPCODE_CONFLICT_P
+ returns non-zero.
+ The values are indices into `sparc_opcode_archs' defined in sparc-opc.c.
+ Don't change this without updating sparc-opc.c. */
+
+enum sparc_opcode_arch_val {
+ SPARC_OPCODE_ARCH_V6 = 0,
+ SPARC_OPCODE_ARCH_V7,
+ SPARC_OPCODE_ARCH_V8,
+ SPARC_OPCODE_ARCH_SPARCLET,
+ SPARC_OPCODE_ARCH_SPARCLITE,
+ /* v9 variants must appear last */
+ SPARC_OPCODE_ARCH_V9,
+ SPARC_OPCODE_ARCH_V9A, /* v9 with ultrasparc additions */
+ SPARC_OPCODE_ARCH_BAD /* error return from sparc_opcode_lookup_arch */
+};
+
+/* The highest architecture in the table. */
+#define SPARC_OPCODE_ARCH_MAX (SPARC_OPCODE_ARCH_BAD - 1)
+
+/* Table of cpu variants. */
+
+struct sparc_opcode_arch {
+ const char *name;
+ /* Mask of sparc_opcode_arch_val's supported.
+ EG: For v7 this would be ((1 << v6) | (1 << v7)). */
+ /* These are short's because sparc_opcode.architecture is. */
+ short supported;
+};
+
+extern const struct sparc_opcode_arch sparc_opcode_archs[];
+
+/* Given architecture name, look up it's sparc_opcode_arch_val value. */
+extern enum sparc_opcode_arch_val sparc_opcode_lookup_arch ();
+
+/* Return the bitmask of supported architectures for ARCH. */
+#define SPARC_OPCODE_SUPPORTED(ARCH) (sparc_opcode_archs[ARCH].supported)
+
+/* Non-zero if ARCH1 conflicts with ARCH2.
+ IE: ARCH1 as a supported bit set that ARCH2 doesn't, and vice versa. */
+#define SPARC_OPCODE_CONFLICT_P(ARCH1, ARCH2) \
+(((SPARC_OPCODE_SUPPORTED (ARCH1) & SPARC_OPCODE_SUPPORTED (ARCH2)) \
+ != SPARC_OPCODE_SUPPORTED (ARCH1)) \
+ && ((SPARC_OPCODE_SUPPORTED (ARCH1) & SPARC_OPCODE_SUPPORTED (ARCH2)) \
+ != SPARC_OPCODE_SUPPORTED (ARCH2)))
+
+/* Structure of an opcode table entry. */
+
+struct sparc_opcode {
+ const char *name;
+ unsigned long match; /* Bits that must be set. */
+ unsigned long lose; /* Bits that must not be set. */
+ const char *args;
+ /* This was called "delayed" in versions before the flags. */
+ char flags;
+ short architecture; /* Bitmask of sparc_opcode_arch_val's. */
+};
+
+#define F_DELAYED 1 /* Delayed branch */
+#define F_ALIAS 2 /* Alias for a "real" instruction */
+#define F_UNBR 4 /* Unconditional branch */
+#define F_CONDBR 8 /* Conditional branch */
+#define F_JSR 16 /* Subroutine call */
+/* FIXME: Add F_ANACHRONISTIC flag for v9. */
+
+/*
+
+All sparc opcodes are 32 bits, except for the `set' instruction (really a
+macro), which is 64 bits. It is handled as a special case.
+
+The match component is a mask saying which bits must match a particular
+opcode in order for an instruction to be an instance of that opcode.
+
+The args component is a string containing one character for each operand of the
+instruction.
+
+Kinds of operands:
+ # Number used by optimizer. It is ignored.
+ 1 rs1 register.
+ 2 rs2 register.
+ d rd register.
+ e frs1 floating point register.
+ v frs1 floating point register (double/even).
+ V frs1 floating point register (quad/multiple of 4).
+ f frs2 floating point register.
+ B frs2 floating point register (double/even).
+ R frs2 floating point register (quad/multiple of 4).
+ g frsd floating point register.
+ H frsd floating point register (double/even).
+ J frsd floating point register (quad/multiple of 4).
+ b crs1 coprocessor register
+ c crs2 coprocessor register
+ D crsd coprocessor register
+ m alternate space register (asr) in rd
+ M alternate space register (asr) in rs1
+ h 22 high bits.
+ K MEMBAR mask (7 bits). (v9)
+ j 10 bit Immediate. (v9)
+ I 11 bit Immediate. (v9)
+ i 13 bit Immediate.
+ n 22 bit immediate.
+ k 2+14 bit PC relative immediate. (v9)
+ G 19 bit PC relative immediate. (v9)
+ l 22 bit PC relative immediate.
+ L 30 bit PC relative immediate.
+ a Annul. The annul bit is set.
+ A Alternate address space. Stored as 8 bits.
+ C Coprocessor state register.
+ F floating point state register.
+ p Processor state register.
+ N Branch predict clear ",pn" (v9)
+ T Branch predict set ",pt" (v9)
+ z %icc. (v9)
+ Z %xcc. (v9)
+ q Floating point queue.
+ r Single register that is both rs1 and rd.
+ O Single register that is both rs2 and rd.
+ Q Coprocessor queue.
+ S Special case.
+ t Trap base register.
+ w Window invalid mask register.
+ y Y register.
+ u sparclet coprocessor registers in rd position
+ U sparclet coprocessor registers in rs1 position
+ E %ccr. (v9)
+ s %fprs. (v9)
+ P %pc. (v9)
+ W %tick. (v9)
+ o %asi. (v9)
+ 6 %fcc0. (v9)
+ 7 %fcc1. (v9)
+ 8 %fcc2. (v9)
+ 9 %fcc3. (v9)
+ ! Privileged Register in rd (v9)
+ ? Privileged Register in rs1 (v9)
+ * Prefetch function constant. (v9)
+ x OPF field (v9 impdep).
+
+The following chars are unused: (note: ,[] are used as punctuation)
+[XY3450]
+
+*/
+
+#define OP2(x) (((x)&0x7) << 22) /* op2 field of format2 insns */
+#define OP3(x) (((x)&0x3f) << 19) /* op3 field of format3 insns */
+#define OP(x) ((unsigned)((x)&0x3) << 30) /* op field of all insns */
+#define OPF(x) (((x)&0x1ff) << 5) /* opf field of float insns */
+#define OPF_LOW5(x) OPF((x)&0x1f) /* v9 */
+#define F3F(x, y, z) (OP(x) | OP3(y) | OPF(z)) /* format3 float insns */
+#define F3I(x) (((x)&0x1) << 13) /* immediate field of format 3 insns */
+#define F2(x, y) (OP(x) | OP2(y)) /* format 2 insns */
+#define F3(x, y, z) (OP(x) | OP3(y) | F3I(z)) /* format3 insns */
+#define F1(x) (OP(x))
+#define DISP30(x) ((x)&0x3fffffff)
+#define ASI(x) (((x)&0xff) << 5) /* asi field of format3 insns */
+#define RS2(x) ((x)&0x1f) /* rs2 field */
+#define SIMM13(x) ((x)&0x1fff) /* simm13 field */
+#define RD(x) (((x)&0x1f) << 25) /* destination register field */
+#define RS1(x) (((x)&0x1f) << 14) /* rs1 field */
+#define ASI_RS2(x) (SIMM13(x))
+#define MEMBAR(x) ((x)&0x7f)
+
+#define ANNUL (1<<29)
+#define BPRED (1<<19) /* v9 */
+#define IMMED F3I(1)
+#define RD_G0 RD(~0)
+#define RS1_G0 RS1(~0)
+#define RS2_G0 RS2(~0)
+
+extern struct sparc_opcode sparc_opcodes[];
+extern const int sparc_num_opcodes;
+
+int sparc_encode_asi ();
+char *sparc_decode_asi ();
+int sparc_encode_membar ();
+char *sparc_decode_membar ();
+int sparc_encode_prefetch ();
+char *sparc_decode_prefetch ();
+int sparc_encode_sparclet_cpreg ();
+char *sparc_decode_sparclet_cpreg ();
+
+/*
+ * Local Variables:
+ * fill-column: 131
+ * comment-column: 0
+ * End:
+ */
+
+/* end of sparc.h */
diff --git a/contrib/gdb/include/opcode/tahoe.h b/contrib/gdb/include/opcode/tahoe.h
new file mode 100644
index 0000000..b5cee24
--- /dev/null
+++ b/contrib/gdb/include/opcode/tahoe.h
@@ -0,0 +1,213 @@
+/*
+ * Ported by the State University of New York at Buffalo by the Distributed
+ * Computer Systems Lab, Department of Computer Science, 1991.
+ */
+
+#ifndef tahoe_opcodeT
+#define tahoe_opcodeT int
+#endif /* no tahoe_opcodeT */
+
+struct vot_wot /* tahoe opcode table: wot to do with this */
+ /* particular opcode */
+{
+ char * args; /* how to compile said opcode */
+ tahoe_opcodeT code; /* op-code (may be > 8 bits!) */
+};
+
+struct vot /* tahoe opcode text */
+{
+ char * name; /* opcode name: lowercase string [key] */
+ struct vot_wot detail; /* rest of opcode table [datum] */
+};
+
+#define vot_how args
+#define vot_code code
+#define vot_detail detail
+#define vot_name name
+
+static struct vot
+votstrs[] =
+{
+{ "halt", {"", 0x00 } },
+{ "sinf", {"", 0x05 } },
+{ "ldf", {"rl", 0x06 } },
+{ "ldd", {"rq", 0x07 } },
+{ "addb2", {"rbmb", 0x08 } },
+{ "movb", {"rbwb", 0x09 } },
+{ "addw2", {"rwmw", 0x0a } },
+{ "movw", {"rwww", 0x0b } },
+{ "addl2", {"rlml", 0x0c } },
+{ "movl", {"rlwl", 0x0d } },
+{ "bbs", {"rlvlbw", 0x0e } },
+{ "nop", {"", 0x10 } },
+{ "brb", {"bb", 0x11 } },
+{ "brw", {"bw", 0x13 } },
+{ "cosf", {"", 0x15 } },
+{ "lnf", {"rl", 0x16 } },
+{ "lnd", {"rq", 0x17 } },
+{ "addb3", {"rbrbwb", 0x18 } },
+{ "cmpb", {"rbwb", 0x19 } },
+{ "addw3", {"rwrwww", 0x1a } },
+{ "cmpw", {"rwww", 0x1b } },
+{ "addl3", {"rlrlwl", 0x1c } },
+{ "cmpl", {"rlwl", 0x1d } },
+{ "bbc", {"rlvlbw", 0x1e } },
+{ "rei", {"", 0x20 } },
+{ "bneq", {"bb", 0x21 } },
+{ "bnequ", {"bb", 0x21 } },
+{ "cvtwl", {"rwwl", 0x23 } },
+{ "stf", {"wl", 0x26 } },
+{ "std", {"wq", 0x27 } },
+{ "subb2", {"rbmb", 0x28 } },
+{ "mcomb", {"rbwb", 0x29 } },
+{ "subw2", {"rwmw", 0x2a } },
+{ "mcomw", {"rwww", 0x2b } },
+{ "subl2", {"rlml", 0x2c } },
+{ "mcoml", {"rlwl", 0x2d } },
+{ "emul", {"rlrlrlwq", 0x2e } },
+{ "aoblss", {"rlmlbw", 0x2f } },
+{ "bpt", {"", 0x30 } },
+{ "beql", {"bb", 0x31 } },
+{ "beqlu", {"bb", 0x31 } },
+{ "cvtwb", {"rwwb", 0x33 } },
+{ "logf", {"", 0x35 } },
+{ "cmpf", {"rl", 0x36 } },
+{ "cmpd", {"rq", 0x37 } },
+{ "subb3", {"rbrbwb", 0x38 } },
+{ "bitb", {"rbrb", 0x39 } },
+{ "subw3", {"rwrwww", 0x3a } },
+{ "bitw", {"rwrw", 0x3b } },
+{ "subl3", {"rlrlwl", 0x3c } },
+{ "bitl", {"rlrl", 0x3d } },
+{ "ediv", {"rlrqwlwl", 0x3e } },
+{ "aobleq", {"rlmlbw", 0x3f } },
+{ "ret", {"", 0x40 } },
+{ "bgtr", {"bb", 0x41 } },
+{ "sqrtf", {"", 0x45 } },
+{ "cmpf2", {"rl", 0x46 } },
+{ "cmpd2", {"rqrq", 0x47 } },
+{ "shll", {"rbrlwl", 0x48 } },
+{ "clrb", {"wb", 0x49 } },
+{ "shlq", {"rbrqwq", 0x4a } },
+{ "clrw", {"ww", 0x4b } },
+{ "mull2", {"rlml", 0x4c } },
+{ "clrl", {"wl", 0x4d } },
+{ "shal", {"rbrlwl", 0x4e } },
+{ "bleq", {"bb", 0x51 } },
+{ "expf", {"", 0x55 } },
+{ "tstf", {"", 0x56 } },
+{ "tstd", {"", 0x57 } },
+{ "shrl", {"rbrlwl", 0x58 } },
+{ "tstb", {"rb", 0x59 } },
+{ "shrq", {"rbrqwq", 0x5a } },
+{ "tstw", {"rw", 0x5b } },
+{ "mull3", {"rlrlwl", 0x5c } },
+{ "tstl", {"rl", 0x5d } },
+{ "shar", {"rbrlwl", 0x5e } },
+{ "bbssi", {"rlmlbw", 0x5f } },
+{ "ldpctx", {"", 0x60 } },
+{ "pushd", {"", 0x67 } },
+{ "incb", {"mb", 0x69 } },
+{ "incw", {"mw", 0x6b } },
+{ "divl2", {"rlml", 0x6c } },
+{ "incl", {"ml", 0x6d } },
+{ "cvtlb", {"rlwb", 0x6f } },
+{ "svpctx", {"", 0x70 } },
+{ "jmp", {"ab", 0x71 } },
+{ "cvlf", {"rl", 0x76 } },
+{ "cvld", {"rl", 0x77 } },
+{ "decb", {"mb", 0x79 } },
+{ "decw", {"mw", 0x7b } },
+{ "divl3", {"rlrlwl", 0x7c } },
+{ "decl", {"ml", 0x7d } },
+{ "cvtlw", {"rlww", 0x7f } },
+{ "bgeq", {"bb", 0x81 } },
+{ "movs2", {"abab", 0x82 } },
+{ "cvfl", {"wl", 0x86 } },
+{ "cvdl", {"wl", 0x87 } },
+{ "orb2", {"rbmb", 0x88 } },
+{ "cvtbl", {"rbwl", 0x89 } },
+{ "orw2", {"rwmw", 0x8a } },
+{ "bispsw", {"rw", 0x8b } },
+{ "orl2", {"rlml", 0x8c } },
+{ "adwc", {"rlml", 0x8d } },
+{ "adda", {"rlml", 0x8e } },
+{ "blss", {"bb", 0x91 } },
+{ "cmps2", {"abab", 0x92 } },
+{ "ldfd", {"rl", 0x97 } },
+{ "orb3", {"rbrbwb", 0x98 } },
+{ "cvtbw", {"rbww", 0x99 } },
+{ "orw3", {"rwrwww", 0x9a } },
+{ "bicpsw", {"rw", 0x9b } },
+{ "orl3", {"rlrlwl", 0x9c } },
+{ "sbwc", {"rlml", 0x9d } },
+{ "suba", {"rlml", 0x9e } },
+{ "bgtru", {"bb", 0xa1 } },
+{ "cvdf", {"", 0xa6 } },
+{ "andb2", {"rbmb", 0xa8 } },
+{ "movzbl", {"rbwl", 0xa9 } },
+{ "andw2", {"rwmw", 0xaa } },
+{ "loadr", {"rwal", 0xab } },
+{ "andl2", {"rlml", 0xac } },
+{ "mtpr", {"rlrl", 0xad } },
+{ "ffs", {"rlwl", 0xae } },
+{ "blequ", {"bb", 0xb1 } },
+{ "negf", {"", 0xb6 } },
+{ "negd", {"", 0xb7 } },
+{ "andb3", {"rbrbwb", 0xb8 } },
+{ "movzbw", {"rbww", 0xb9 } },
+{ "andw3", {"rwrwww", 0xba } },
+{ "storer", {"rwal", 0xbb } },
+{ "andl3", {"rlrlwl", 0xbc } },
+{ "mfpr", {"rlwl", 0xbd } },
+{ "ffc", {"rlwl", 0xbe } },
+{ "calls", {"rbab", 0xbf } },
+{ "prober", {"rbabrl", 0xc0 } },
+{ "bvc", {"bb", 0xc1 } },
+{ "movs3", {"ababrw", 0xc2 } },
+{ "movzwl", {"rwwl", 0xc3 } },
+{ "addf", {"rl", 0xc6 } },
+{ "addd", {"rq", 0xc7 } },
+{ "xorb2", {"rbmb", 0xc8 } },
+{ "movob", {"rbwb", 0xc9 } },
+{ "xorw2", {"rwmw", 0xca } },
+{ "movow", {"rwww", 0xcb } },
+{ "xorl2", {"rlml", 0xcc } },
+{ "movpsl", {"wl", 0xcd } },
+{ "kcall", {"rw", 0xcf } },
+{ "probew", {"rbabrl", 0xd0 } },
+{ "bvs", {"bb", 0xd1 } },
+{ "cmps3", {"ababrw", 0xd2 } },
+{ "subf", {"rq", 0xd6 } },
+{ "subd", {"rq", 0xd7 } },
+{ "xorb3", {"rbrbwb", 0xd8 } },
+{ "pushb", {"rb", 0xd9 } },
+{ "xorw3", {"rwrwww", 0xda } },
+{ "pushw", {"rw", 0xdb } },
+{ "xorl3", {"rlrlwl", 0xdc } },
+{ "pushl", {"rl", 0xdd } },
+{ "insque", {"abab", 0xe0 } },
+{ "bcs", {"bb", 0xe1 } },
+{ "bgequ", {"bb", 0xe1 } },
+{ "mulf", {"rq", 0xe6 } },
+{ "muld", {"rq", 0xe7 } },
+{ "mnegb", {"rbwb", 0xe8 } },
+{ "movab", {"abwl", 0xe9 } },
+{ "mnegw", {"rwww", 0xea } },
+{ "movaw", {"awwl", 0xeb } },
+{ "mnegl", {"rlwl", 0xec } },
+{ "moval", {"alwl", 0xed } },
+{ "remque", {"ab", 0xf0 } },
+{ "bcc", {"bb", 0xf1 } },
+{ "blssu", {"bb", 0xf1 } },
+{ "divf", {"rq", 0xf6 } },
+{ "divd", {"rq", 0xf7 } },
+{ "movblk", {"alalrw", 0xf8 } },
+{ "pushab", {"ab", 0xf9 } },
+{ "pushaw", {"aw", 0xfb } },
+{ "casel", {"rlrlrl", 0xfc } },
+{ "pushal", {"al", 0xfd } },
+{ "callf", {"rbab", 0xfe } },
+{ "" , "" } /* empty is end sentinel */
+
+};
diff --git a/contrib/gdb/include/opcode/vax.h b/contrib/gdb/include/opcode/vax.h
new file mode 100644
index 0000000..f3afebd
--- /dev/null
+++ b/contrib/gdb/include/opcode/vax.h
@@ -0,0 +1,382 @@
+/* Vax opcde list.
+ Copyright (C) 1989, 1995 Free Software Foundation, Inc.
+
+This file is part of GDB and GAS.
+
+GDB and GAS are free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 1, or (at your option)
+any later version.
+
+GDB and GAS are distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GDB or GAS; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef vax_opcodeT
+#define vax_opcodeT int
+#endif /* no vax_opcodeT */
+
+struct vot_wot /* vax opcode table: wot to do with this */
+ /* particular opcode */
+{
+ const char *args; /* how to compile said opcode */
+ vax_opcodeT code; /* op-code (may be > 8 bits!) */
+};
+
+struct vot /* vax opcode text */
+{
+ const char *name; /* opcode name: lowercase string [key] */
+ struct vot_wot detail; /* rest of opcode table [datum] */
+};
+
+#define vot_how args
+#define vot_code code
+#define vot_detail detail
+#define vot_name name
+
+static const struct vot
+votstrs[] =
+{
+{ "halt", {"", 0x00 } },
+{ "nop", {"", 0x01 } },
+{ "rei", {"", 0x02 } },
+{ "bpt", {"", 0x03 } },
+{ "ret", {"", 0x04 } },
+{ "rsb", {"", 0x05 } },
+{ "ldpctx", {"", 0x06 } },
+{ "svpctx", {"", 0x07 } },
+{ "cvtps", {"rwabrwab", 0x08 } },
+{ "cvtsp", {"rwabrwab", 0x09 } },
+{ "index", {"rlrlrlrlrlwl", 0x0a } },
+{ "crc", {"abrlrwab", 0x0b } },
+{ "prober", {"rbrwab", 0x0c } },
+{ "probew", {"rbrwab", 0x0d } },
+{ "insque", {"abab", 0x0e } },
+{ "remque", {"abwl", 0x0f } },
+{ "bsbb", {"bb", 0x10 } },
+{ "brb", {"bb", 0x11 } },
+{ "bneq", {"bb", 0x12 } },
+{ "bnequ", {"bb", 0x12 } },
+{ "beql", {"bb", 0x13 } },
+{ "beqlu", {"bb", 0x13 } },
+{ "bgtr", {"bb", 0x14 } },
+{ "bleq", {"bb", 0x15 } },
+{ "jsb", {"ab", 0x16 } },
+{ "jmp", {"ab", 0x17 } },
+{ "bgeq", {"bb", 0x18 } },
+{ "blss", {"bb", 0x19 } },
+{ "bgtru", {"bb", 0x1a } },
+{ "blequ", {"bb", 0x1b } },
+{ "bvc", {"bb", 0x1c } },
+{ "bvs", {"bb", 0x1d } },
+{ "bcc", {"bb", 0x1e } },
+{ "bgequ", {"bb", 0x1e } },
+{ "blssu", {"bb", 0x1f } },
+{ "bcs", {"bb", 0x1f } },
+{ "addp4", {"rwabrwab", 0x20 } },
+{ "addp6", {"rwabrwabrwab", 0x21 } },
+{ "subp4", {"rwabrwab", 0x22 } },
+{ "subp6", {"rwabrwabrwab", 0x23 } },
+{ "cvtpt", {"rwababrwab", 0x24 } },
+{ "mulp", {"rwabrwabrwab", 0x25 } },
+{ "cvttp", {"rwababrwab", 0x26 } },
+{ "divp", {"rwabrwabrwab", 0x27 } },
+{ "movc3", {"rwabab", 0x28 } },
+{ "cmpc3", {"rwabab", 0x29 } },
+{ "scanc", {"rwababrb", 0x2a } },
+{ "spanc", {"rwababrb", 0x2b } },
+{ "movc5", {"rwabrbrwab", 0x2c } },
+{ "cmpc5", {"rwabrbrwab", 0x2d } },
+{ "movtc", {"rwabrbabrwab", 0x2e } },
+{ "movtuc", {"rwabrbabrwab", 0x2f } },
+{ "bsbw", {"bw", 0x30 } },
+{ "brw", {"bw", 0x31 } },
+{ "cvtwl", {"rwwl", 0x32 } },
+{ "cvtwb", {"rwwb", 0x33 } },
+{ "movp", {"rwabab", 0x34 } },
+{ "cmpp3", {"rwabab", 0x35 } },
+{ "cvtpl", {"rwabwl", 0x36 } },
+{ "cmpp4", {"rwabrwab", 0x37 } },
+{ "editpc", {"rwababab", 0x38 } },
+{ "matchc", {"rwabrwab", 0x39 } },
+{ "locc", {"rbrwab", 0x3a } },
+{ "skpc", {"rbrwab", 0x3b } },
+{ "movzwl", {"rwwl", 0x3c } },
+{ "acbw", {"rwrwmwbw", 0x3d } },
+{ "movaw", {"awwl", 0x3e } },
+{ "pushaw", {"aw", 0x3f } },
+{ "addf2", {"rfmf", 0x40 } },
+{ "addf3", {"rfrfwf", 0x41 } },
+{ "subf2", {"rfmf", 0x42 } },
+{ "subf3", {"rfrfwf", 0x43 } },
+{ "mulf2", {"rfmf", 0x44 } },
+{ "mulf3", {"rfrfwf", 0x45 } },
+{ "divf2", {"rfmf", 0x46 } },
+{ "divf3", {"rfrfwf", 0x47 } },
+{ "cvtfb", {"rfwb", 0x48 } },
+{ "cvtfw", {"rfww", 0x49 } },
+{ "cvtfl", {"rfwl", 0x4a } },
+{ "cvtrfl", {"rfwl", 0x4b } },
+{ "cvtbf", {"rbwf", 0x4c } },
+{ "cvtwf", {"rwwf", 0x4d } },
+{ "cvtlf", {"rlwf", 0x4e } },
+{ "acbf", {"rfrfmfbw", 0x4f } },
+{ "movf", {"rfwf", 0x50 } },
+{ "cmpf", {"rfrf", 0x51 } },
+{ "mnegf", {"rfwf", 0x52 } },
+{ "tstf", {"rf", 0x53 } },
+{ "emodf", {"rfrbrfwlwf", 0x54 } },
+{ "polyf", {"rfrwab", 0x55 } },
+{ "cvtfd", {"rfwd", 0x56 } },
+ /* opcode 57 is not defined yet */
+{ "adawi", {"rwmw", 0x58 } },
+ /* opcode 59 is not defined yet */
+ /* opcode 5a is not defined yet */
+ /* opcode 5b is not defined yet */
+{ "insqhi", {"abaq", 0x5c } },
+{ "insqti", {"abaq", 0x5d } },
+{ "remqhi", {"aqwl", 0x5e } },
+{ "remqti", {"aqwl", 0x5f } },
+{ "addd2", {"rdmd", 0x60 } },
+{ "addd3", {"rdrdwd", 0x61 } },
+{ "subd2", {"rdmd", 0x62 } },
+{ "subd3", {"rdrdwd", 0x63 } },
+{ "muld2", {"rdmd", 0x64 } },
+{ "muld3", {"rdrdwd", 0x65 } },
+{ "divd2", {"rdmd", 0x66 } },
+{ "divd3", {"rdrdwd", 0x67 } },
+{ "cvtdb", {"rdwb", 0x68 } },
+{ "cvtdw", {"rdww", 0x69 } },
+{ "cvtdl", {"rdwl", 0x6a } },
+{ "cvtrdl", {"rdwl", 0x6b } },
+{ "cvtbd", {"rbwd", 0x6c } },
+{ "cvtwd", {"rwwd", 0x6d } },
+{ "cvtld", {"rlwd", 0x6e } },
+{ "acbd", {"rdrdmdbw", 0x6f } },
+{ "movd", {"rdwd", 0x70 } },
+{ "cmpd", {"rdrd", 0x71 } },
+{ "mnegd", {"rdwd", 0x72 } },
+{ "tstd", {"rd", 0x73 } },
+{ "emodd", {"rdrbrdwlwd", 0x74 } },
+{ "polyd", {"rdrwab", 0x75 } },
+{ "cvtdf", {"rdwf", 0x76 } },
+ /* opcode 77 is not defined yet */
+{ "ashl", {"rbrlwl", 0x78 } },
+{ "ashq", {"rbrqwq", 0x79 } },
+{ "emul", {"rlrlrlwq", 0x7a } },
+{ "ediv", {"rlrqwlwl", 0x7b } },
+{ "clrd", {"wd", 0x7c } },
+{ "clrg", {"wg", 0x7c } },
+{ "clrq", {"wd", 0x7c } },
+{ "movq", {"rqwq", 0x7d } },
+{ "movaq", {"aqwl", 0x7e } },
+{ "movad", {"adwl", 0x7e } },
+{ "pushaq", {"aq", 0x7f } },
+{ "pushad", {"ad", 0x7f } },
+{ "addb2", {"rbmb", 0x80 } },
+{ "addb3", {"rbrbwb", 0x81 } },
+{ "subb2", {"rbmb", 0x82 } },
+{ "subb3", {"rbrbwb", 0x83 } },
+{ "mulb2", {"rbmb", 0x84 } },
+{ "mulb3", {"rbrbwb", 0x85 } },
+{ "divb2", {"rbmb", 0x86 } },
+{ "divb3", {"rbrbwb", 0x87 } },
+{ "bisb2", {"rbmb", 0x88 } },
+{ "bisb3", {"rbrbwb", 0x89 } },
+{ "bicb2", {"rbmb", 0x8a } },
+{ "bicb3", {"rbrbwb", 0x8b } },
+{ "xorb2", {"rbmb", 0x8c } },
+{ "xorb3", {"rbrbwb", 0x8d } },
+{ "mnegb", {"rbwb", 0x8e } },
+{ "caseb", {"rbrbrb", 0x8f } },
+{ "movb", {"rbwb", 0x90 } },
+{ "cmpb", {"rbrb", 0x91 } },
+{ "mcomb", {"rbwb", 0x92 } },
+{ "bitb", {"rbrb", 0x93 } },
+{ "clrb", {"wb", 0x94 } },
+{ "tstb", {"rb", 0x95 } },
+{ "incb", {"mb", 0x96 } },
+{ "decb", {"mb", 0x97 } },
+{ "cvtbl", {"rbwl", 0x98 } },
+{ "cvtbw", {"rbww", 0x99 } },
+{ "movzbl", {"rbwl", 0x9a } },
+{ "movzbw", {"rbww", 0x9b } },
+{ "rotl", {"rbrlwl", 0x9c } },
+{ "acbb", {"rbrbmbbw", 0x9d } },
+{ "movab", {"abwl", 0x9e } },
+{ "pushab", {"ab", 0x9f } },
+{ "addw2", {"rwmw", 0xa0 } },
+{ "addw3", {"rwrwww", 0xa1 } },
+{ "subw2", {"rwmw", 0xa2 } },
+{ "subw3", {"rwrwww", 0xa3 } },
+{ "mulw2", {"rwmw", 0xa4 } },
+{ "mulw3", {"rwrwww", 0xa5 } },
+{ "divw2", {"rwmw", 0xa6 } },
+{ "divw3", {"rwrwww", 0xa7 } },
+{ "bisw2", {"rwmw", 0xa8 } },
+{ "bisw3", {"rwrwww", 0xa9 } },
+{ "bicw2", {"rwmw", 0xaa } },
+{ "bicw3", {"rwrwww", 0xab } },
+{ "xorw2", {"rwmw", 0xac } },
+{ "xorw3", {"rwrwww", 0xad } },
+{ "mnegw", {"rwww", 0xae } },
+{ "casew", {"rwrwrw", 0xaf } },
+{ "movw", {"rwww", 0xb0 } },
+{ "cmpw", {"rwrw", 0xb1 } },
+{ "mcomw", {"rwww", 0xb2 } },
+{ "bitw", {"rwrw", 0xb3 } },
+{ "clrw", {"ww", 0xb4 } },
+{ "tstw", {"rw", 0xb5 } },
+{ "incw", {"mw", 0xb6 } },
+{ "decw", {"mw", 0xb7 } },
+{ "bispsw", {"rw", 0xb8 } },
+{ "bicpsw", {"rw", 0xb9 } },
+{ "popr", {"rw", 0xba } },
+{ "pushr", {"rw", 0xbb } },
+{ "chmk", {"rw", 0xbc } },
+{ "chme", {"rw", 0xbd } },
+{ "chms", {"rw", 0xbe } },
+{ "chmu", {"rw", 0xbf } },
+{ "addl2", {"rlml", 0xc0 } },
+{ "addl3", {"rlrlwl", 0xc1 } },
+{ "subl2", {"rlml", 0xc2 } },
+{ "subl3", {"rlrlwl", 0xc3 } },
+{ "mull2", {"rlml", 0xc4 } },
+{ "mull3", {"rlrlwl", 0xc5 } },
+{ "divl2", {"rlml", 0xc6 } },
+{ "divl3", {"rlrlwl", 0xc7 } },
+{ "bisl2", {"rlml", 0xc8 } },
+{ "bisl3", {"rlrlwl", 0xc9 } },
+{ "bicl2", {"rlml", 0xca } },
+{ "bicl3", {"rlrlwl", 0xcb } },
+{ "xorl2", {"rlml", 0xcc } },
+{ "xorl3", {"rlrlwl", 0xcd } },
+{ "mnegl", {"rlwl", 0xce } },
+{ "casel", {"rlrlrl", 0xcf } },
+{ "movl", {"rlwl", 0xd0 } },
+{ "cmpl", {"rlrl", 0xd1 } },
+{ "mcoml", {"rlwl", 0xd2 } },
+{ "bitl", {"rlrl", 0xd3 } },
+{ "clrf", {"wf", 0xd4 } },
+{ "clrl", {"wl", 0xd4 } },
+{ "tstl", {"rl", 0xd5 } },
+{ "incl", {"ml", 0xd6 } },
+{ "decl", {"ml", 0xd7 } },
+{ "adwc", {"rlml", 0xd8 } },
+{ "sbwc", {"rlml", 0xd9 } },
+{ "mtpr", {"rlrl", 0xda } },
+{ "mfpr", {"rlwl", 0xdb } },
+{ "movpsl", {"wl", 0xdc } },
+{ "pushl", {"rl", 0xdd } },
+{ "moval", {"alwl", 0xde } },
+{ "movaf", {"afwl", 0xde } },
+{ "pushal", {"al", 0xdf } },
+{ "pushaf", {"af", 0xdf } },
+{ "bbs", {"rlvbbb", 0xe0 } },
+{ "bbc", {"rlvbbb", 0xe1 } },
+{ "bbss", {"rlvbbb", 0xe2 } },
+{ "bbcs", {"rlvbbb", 0xe3 } },
+{ "bbsc", {"rlvbbb", 0xe4 } },
+{ "bbcc", {"rlvbbb", 0xe5 } },
+{ "bbssi", {"rlvbbb", 0xe6 } },
+{ "bbcci", {"rlvbbb", 0xe7 } },
+{ "blbs", {"rlbb", 0xe8 } },
+{ "blbc", {"rlbb", 0xe9 } },
+{ "ffs", {"rlrbvbwl", 0xea } },
+{ "ffc", {"rlrbvbwl", 0xeb } },
+{ "cmpv", {"rlrbvbrl", 0xec } },
+{ "cmpzv", {"rlrbvbrl", 0xed } },
+{ "extv", {"rlrbvbwl", 0xee } },
+{ "extzv", {"rlrbvbwl", 0xef } },
+{ "insv", {"rlrlrbvb", 0xf0 } },
+{ "acbl", {"rlrlmlbw", 0xf1 } },
+{ "aoblss", {"rlmlbb", 0xf2 } },
+{ "aobleq", {"rlmlbb", 0xf3 } },
+{ "sobgeq", {"mlbb", 0xf4 } },
+{ "sobgtr", {"mlbb", 0xf5 } },
+{ "cvtlb", {"rlwb", 0xf6 } },
+{ "cvtlw", {"rlww", 0xf7 } },
+{ "ashp", {"rbrwabrbrwab", 0xf8 } },
+{ "cvtlp", {"rlrwab", 0xf9 } },
+{ "callg", {"abab", 0xfa } },
+{ "calls", {"rlab", 0xfb } },
+{ "xfc", {"", 0xfc } },
+ /* undefined opcodes here */
+{ "cvtdh", {"rdwh", 0x32fd } },
+{ "cvtgf", {"rgwh", 0x33fd } },
+{ "addg2", {"rgmg", 0x40fd } },
+{ "addg3", {"rgrgwg", 0x41fd } },
+{ "subg2", {"rgmg", 0x42fd } },
+{ "subg3", {"rgrgwg", 0x43fd } },
+{ "mulg2", {"rgmg", 0x44fd } },
+{ "mulg3", {"rgrgwg", 0x45fd } },
+{ "divg2", {"rgmg", 0x46fd } },
+{ "divg3", {"rgrgwg", 0x47fd } },
+{ "cvtgb", {"rgwb", 0x48fd } },
+{ "cvtgw", {"rgww", 0x49fd } },
+{ "cvtgl", {"rgwl", 0x4afd } },
+{ "cvtrgl", {"rgwl", 0x4bfd } },
+{ "cvtbg", {"rbwg", 0x4cfd } },
+{ "cvtwg", {"rwwg", 0x4dfd } },
+{ "cvtlg", {"rlwg", 0x4efd } },
+{ "acbg", {"rgrgmgbw", 0x4ffd } },
+{ "movg", {"rgwg", 0x50fd } },
+{ "cmpg", {"rgrg", 0x51fd } },
+{ "mnegg", {"rgwg", 0x52fd } },
+{ "tstg", {"rg", 0x53fd } },
+{ "emodg", {"rgrwrgwlwg", 0x54fd } },
+{ "polyg", {"rgrwab", 0x55fd } },
+{ "cvtgh", {"rgwh", 0x56fd } },
+ /* undefined opcodes here */
+{ "addh2", {"rhmh", 0x60fd } },
+{ "addh3", {"rhrhwh", 0x61fd } },
+{ "subh2", {"rhmh", 0x62fd } },
+{ "subh3", {"rhrhwh", 0x63fd } },
+{ "mulh2", {"rhmh", 0x64fd } },
+{ "mulh3", {"rhrhwh", 0x65fd } },
+{ "divh2", {"rhmh", 0x66fd } },
+{ "divh3", {"rhrhwh", 0x67fd } },
+{ "cvthb", {"rhwb", 0x68fd } },
+{ "cvthw", {"rhww", 0x69fd } },
+{ "cvthl", {"rhwl", 0x6afd } },
+{ "cvtrhl", {"rhwl", 0x6bfd } },
+{ "cvtbh", {"rbwh", 0x6cfd } },
+{ "cvtwh", {"rwwh", 0x6dfd } },
+{ "cvtlh", {"rlwh", 0x6efd } },
+{ "acbh", {"rhrhmhbw", 0x6ffd } },
+{ "movh", {"rhwh", 0x70fd } },
+{ "cmph", {"rhrh", 0x71fd } },
+{ "mnegh", {"rhwh", 0x72fd } },
+{ "tsth", {"rh", 0x73fd } },
+{ "emodh", {"rhrwrhwlwh", 0x74fd } },
+{ "polyh", {"rhrwab", 0x75fd } },
+{ "cvthg", {"rhwg", 0x76fd } },
+ /* undefined opcodes here */
+{ "clrh", {"wh", 0x7cfd } },
+{ "clro", {"wo", 0x7cfd } },
+{ "movo", {"rowo", 0x7dfd } },
+{ "movah", {"ahwl", 0x7efd } },
+{ "movao", {"aowl", 0x7efd } },
+{ "pushah", {"ah", 0x7ffd } },
+{ "pushao", {"ao", 0x7ffd } },
+ /* undefined opcodes here */
+{ "cvtfh", {"rfwh", 0x98fd } },
+{ "cvtfg", {"rfwg", 0x99fd } },
+ /* undefined opcodes here */
+{ "cvthf", {"rhwf", 0xf6fd } },
+{ "cvthd", {"rhwd", 0xf7fd } },
+ /* undefined opcodes here */
+{ "bugl", {"rl", 0xfdff } },
+{ "bugw", {"rw", 0xfeff } },
+ /* undefined opcodes here */
+
+{ "", {"", 0} } /* empty is end sentinel */
+
+}; /* votstrs */
+
+/* end: vax.opcode.h */
diff --git a/contrib/gdb/include/os9k.h b/contrib/gdb/include/os9k.h
new file mode 100644
index 0000000..0f2eed2
--- /dev/null
+++ b/contrib/gdb/include/os9k.h
@@ -0,0 +1,169 @@
+#if !defined(_MODULE_H)
+#define _MODULE_H
+
+/* OS-9000 i386 module header definitions */
+#define _MPF386
+
+/* sizeof common header less parity field */
+#define N_M_PARITY (sizeof(mh_com)-sizeof(unisgned short))
+#define OLD_M_PARITY 46
+#define M_PARITY N_M_PARITY
+
+#ifdef _MPF68K
+#define MODSYNC 0x4afd /* module header sync code for 680x0 processors */
+#endif
+
+#ifdef _MPF386
+#define MODSYNC 0x4afc /* module header sync code for 80386 processors */
+#endif
+
+#define MODREV 1 /* module format revision 1 */
+#define CRCCON 0x800fe3 /* crc polynomial constant */
+
+/* Module access permission values */
+#define MP_OWNER_READ 0x0001
+#define MP_OWNER_WRITE 0x0002
+#define MP_OWNER_EXEC 0x0004
+#define MP_GROUP_READ 0x0010
+#define MP_GROUP_WRITE 0x0020
+#define MP_GROUP_EXEC 0x0040
+#define MP_WORLD_READ 0x0100
+#define MP_WORLD_WRITE 0x0200
+#define MP_WORLD_EXEC 0x0400
+#define MP_WORLD_ACCESS 0x0777
+#define MP_OWNER_MASK 0x000f
+#define MP_GROUP_MASK 0x00f0
+#define MP_WORLD_MASK 0x0f00
+#define MP_SYSTM_MASK 0xf000
+
+/* Module Type/Language values */
+#define MT_ANY 0
+#define MT_PROGRAM 0x0001
+#define MT_SUBROUT 0x0002
+#define MT_MULTI 0x0003
+#define MT_DATA 0x0004
+#define MT_TRAPLIB 0x000b
+#define MT_SYSTEM 0x000c
+#define MT_FILEMAN 0x000d
+#define MT_DEVDRVR 0x000e
+#define MT_DEVDESC 0x000f
+#define MT_MASK 0xff00
+
+#define ML_ANY 0
+#define ML_OBJECT 1
+#define ML_ICODE 2
+#define ML_PCODE 3
+#define ML_CCODE 4
+#define ML_CBLCODE 5
+#define ML_FRTNCODE 6
+#define ML_MASK 0x00ff
+
+#define mktypelang(type,lang) (((type)<<8)|(lang))
+
+/* Module Attribute values */
+#define MA_REENT 0x80
+#define MA_GHOST 0x40
+#define MA_SUPER 0x20
+#define MA_MASK 0xff00
+#define MR_MASK 0x00ff
+
+#define mkattrevs(attr, revs) (((attr)<<8)|(revs))
+
+#define m_user m_owner.grp_usr.usr
+#define m_group m_owner.grp_usr.grp
+#define m_group_user m_owner.group_user
+
+/* macro definitions for accessing module header fields */
+#define MODNAME(mod) ((u_char*)((u_char*)mod + ((Mh_com)mod)->m_name))
+#if 0
+/* Appears not to be used, and the u_int32 typedef is gone (because it
+ conflicted with a Mach header. */
+#define MODSIZE(mod) ((u_int32)((Mh_com)mod)->m_size)
+#endif /* 0 */
+#define MHCOM_BYTES_SIZE 80
+#define N_BADMAG(a) (((a).a_info) != MODSYNC)
+
+typedef struct mh_com {
+ /* sync bytes ($4afc). */
+ unsigned char m_sync[2];
+ unsigned char m_sysrev[2]; /* system revision check value */
+ unsigned char
+ m_size[4]; /* module size */
+ unsigned char
+ m_owner[4]; /* group/user id */
+ unsigned char
+ m_name[4]; /* offset to module name */
+ unsigned char
+ m_access[2], /* access permissions */
+ m_tylan[2], /* type/lang */
+ m_attrev[2], /* rev/attr */
+ m_edit[2]; /* edition */
+ unsigned char
+ m_needs[4], /* module hardware requirements flags. (reserved) */
+ m_usage[4], /* comment string offset */
+ m_symbol[4], /* symbol table offset */
+ m_exec[4], /* offset to execution entry point */
+ m_excpt[4], /* offset to exception entry point */
+ m_data[4], /* data storage requirement */
+ m_stack[4], /* stack size */
+ m_idata[4], /* offset to initialized data */
+ m_idref[4], /* offset to data reference lists */
+ m_init[4], /* initialization routine offset */
+ m_term[4]; /* termination routine offset */
+ unsigned char
+ m_ident[2]; /* ident code for ident program */
+ char
+ m_spare[8]; /* reserved bytes */
+ unsigned char
+ m_parity[2]; /* header parity */
+} mh_com,*Mh_com;
+
+/* Executable memory module */
+typedef mh_com *Mh_exec,mh_exec;
+
+/* Data memory module */
+typedef mh_com *Mh_data,mh_data;
+
+/* File manager memory module */
+typedef mh_com *Mh_fman,mh_fman;
+
+/* device driver module */
+typedef mh_com *Mh_drvr,mh_drvr;
+
+/* trap handler module */
+typedef mh_com mh_trap, *Mh_trap;
+
+/* Device descriptor module */
+typedef mh_com *Mh_dev,mh_dev;
+
+/* Configuration module */
+typedef mh_com *Mh_config, mh_config;
+
+#if 0
+
+#if !defined(_MODDIR_H)
+/* go get _os_fmod (and others) */
+#include <moddir.h>
+#endif
+
+error_code _os_crc(void *, u_int32, int *);
+error_code _os_datmod(char *, u_int32, u_int16 *, u_int16 *, u_int32, void **, mh_data **);
+error_code _os_get_moddir(void *, u_int32 *);
+error_code _os_initdata(mh_com *, void *);
+error_code _os_link(char **, mh_com **, void **, u_int16 *, u_int16 *);
+error_code _os_linkm(mh_com *, void **, u_int16 *, u_int16 *);
+error_code _os_load(char *, mh_com **, void **, u_int32, u_int16 *, u_int16 *, u_int32);
+error_code _os_mkmodule(char *, u_int32, u_int16 *, u_int16 *, u_int32, void **, mh_com **, u_int32);
+error_code _os_modaddr(void *, mh_com **);
+error_code _os_setcrc(mh_com *);
+error_code _os_slink(u_int32, char *, void **, void **, mh_com **);
+error_code _os_slinkm(u_int32, mh_com *, void **, void **);
+error_code _os_unlink(mh_com *);
+error_code _os_unload(char *, u_int32);
+error_code _os_tlink(u_int32, char *, void **, mh_trap **, void *, u_int32);
+error_code _os_tlinkm(u_int32, mh_com *, void **, void *, u_int32);
+error_code _os_iodel(mh_com *);
+error_code _os_vmodul(mh_com *, mh_com *, u_int32);
+#endif /* 0 */
+
+#endif
diff --git a/contrib/gdb/include/progress.h b/contrib/gdb/include/progress.h
new file mode 100644
index 0000000..f18318a
--- /dev/null
+++ b/contrib/gdb/include/progress.h
@@ -0,0 +1,37 @@
+/* Default definitions for progress macros.
+ Copyright (C) 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* The default definitions below are intended to be replaced by real
+ definitions, if building the tools for an interactive programming
+ environment. */
+
+#ifndef _PROGRESS_H
+#define _PROGRESS_H
+
+#ifndef START_PROGRESS
+#define START_PROGRESS(STR,N)
+#endif
+
+#ifndef PROGRESS
+#define PROGRESS(X)
+#endif
+
+#ifndef END_PROGRESS
+#define END_PROGRESS(STR)
+#endif
+
+#endif /* _PROGRESS_H */
diff --git a/contrib/gdb/include/wait.h b/contrib/gdb/include/wait.h
new file mode 100644
index 0000000..fa3c9cc
--- /dev/null
+++ b/contrib/gdb/include/wait.h
@@ -0,0 +1,63 @@
+/* Define how to access the int that the wait system call stores.
+ This has been compatible in all Unix systems since time immemorial,
+ but various well-meaning people have defined various different
+ words for the same old bits in the same old int (sometimes claimed
+ to be a struct). We just know it's an int and we use these macros
+ to access the bits. */
+
+/* The following macros are defined equivalently to their definitions
+ in POSIX.1. We fail to define WNOHANG and WUNTRACED, which POSIX.1
+ <sys/wait.h> defines, since our code does not use waitpid(). We
+ also fail to declare wait() and waitpid(). */
+
+#ifndef WIFEXITED
+#define WIFEXITED(w) (((w)&0377) == 0)
+#endif
+
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#endif
+
+#ifndef WIFSTOPPED
+#ifdef IBM6000
+
+/* Unfortunately, the above comment (about being compatible in all Unix
+ systems) is not quite correct for AIX, sigh. And AIX 3.2 can generate
+ status words like 0x57c (sigtrap received after load), and gdb would
+ choke on it. */
+
+#define WIFSTOPPED(w) ((w)&0x40)
+
+#else
+#define WIFSTOPPED(w) (((w)&0377) == 0177)
+#endif
+#endif
+
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) >> 8) & 0377) /* same as WRETCODE */
+#endif
+
+#ifndef WTERMSIG
+#define WTERMSIG(w) ((w) & 0177)
+#endif
+
+#ifndef WSTOPSIG
+#define WSTOPSIG WEXITSTATUS
+#endif
+
+/* These are not defined in POSIX, but are used by our programs. */
+
+#define WAITTYPE int
+
+#ifndef WCOREDUMP
+#define WCOREDUMP(w) (((w)&0200) != 0)
+#endif
+
+#ifndef WSETEXIT
+#define WSETEXIT(w,status) ((w) = (0 | ((status) << 8)))
+#endif
+
+#ifndef WSETSTOP
+#define WSETSTOP(w,sig) ((w) = (0177 | ((sig) << 8)))
+#endif
+
diff --git a/contrib/gdb/libiberty/COPYING.LIB b/contrib/gdb/libiberty/COPYING.LIB
new file mode 100644
index 0000000..eb685a5
--- /dev/null
+++ b/contrib/gdb/libiberty/COPYING.LIB
@@ -0,0 +1,481 @@
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL. It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Library General Public License, applies to some
+specially designated Free Software Foundation software, and to any
+other libraries whose authors decide to use it. You can use it for
+your libraries, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if
+you distribute copies of the library, or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link a program with the library, you must provide
+complete object files to the recipients so that they can relink them
+with the library, after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ Our method of protecting your rights has two steps: (1) copyright
+the library, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ Also, for each distributor's protection, we want to make certain
+that everyone understands that there is no warranty for this free
+library. If the library is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original
+version, so that any problems introduced by others will not reflect on
+the original authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that companies distributing free
+software will individually obtain patent licenses, thus in effect
+transforming the program into proprietary software. To prevent this,
+we have made it clear that any patent must be licensed for everyone's
+free use or not licensed at all.
+
+ Most GNU software, including some libraries, is covered by the ordinary
+GNU General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary
+one; be sure to read it in full, and don't assume that anything in it is
+the same as in the ordinary license.
+
+ The reason we have a separate public license for some libraries is that
+they blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in
+a textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+ Because of this blurred distinction, using the ordinary General
+Public License for libraries did not effectively promote software
+sharing, because most developers did not use the libraries. We
+concluded that weaker conditions might promote sharing better.
+
+ However, unrestricted linking of non-free programs would deprive the
+users of those programs of all benefit from the free status of the
+libraries themselves. This Library General Public License is intended to
+permit developers of non-free programs to use free libraries, while
+preserving your freedom as a user of such programs to change the free
+libraries that are incorporated in them. (We have not seen how to achieve
+this as regards changes in header files, but we have achieved it as regards
+changes in the actual functions of the Library.) The hope is that this
+will lead to faster development of free libraries.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, while the latter only
+works together with the library.
+
+ Note that it is possible for a library to be covered by the ordinary
+General Public License rather than by this special one.
+
+ GNU LIBRARY GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library which
+contains a notice placed by the copyright holder or other authorized
+party saying it may be distributed under the terms of this Library
+General Public License (also called "this License"). Each licensee is
+addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also compile or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ c) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ d) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the source code distributed need not include anything that is normally
+distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Library General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library 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 Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/contrib/gdb/libiberty/ChangeLog b/contrib/gdb/libiberty/ChangeLog
new file mode 100644
index 0000000..b28ef2f
--- /dev/null
+++ b/contrib/gdb/libiberty/ChangeLog
@@ -0,0 +1,1815 @@
+Tue Mar 19 22:02:07 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cplus-dem.c (demangle_template): Fix for non-mangled pointer
+ arguments.
+
+Fri Mar 8 17:24:18 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: If srcdir is `.' and with_target_subdir is not
+ `.', then set MULTISRCTOP before calling config-ml.in.
+
+Thu Mar 7 13:37:10 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.c (mpw_open): Add debugging output option.
+
+Wed Mar 6 17:36:03 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cplus-dem.c (demangle_template): Fix for address-of-extern arguments.
+
+Tue Feb 27 12:00:50 1996 Raymond Jou <rjou@mexican.cygnus.com>
+
+ * mpw.c (mpwify_filename): Change 6 to 5 in
+ strncmp (unixname, "/tmp/", 5).
+
+Tue Feb 20 10:55:53 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * cplus-dem.c (demangle_template): Initialize is_bool. Correctly
+ handle 0 as a pointer value parameter.
+
+Mon Feb 5 16:41:44 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (all): Depend upon required-list.
+ (required-list): New target.
+ (clean): Remove required-list.
+
+Wed Jan 31 10:19:41 1996 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * win32.c: Deleted.
+ * config.table (i386-*-win32): Deleted.
+ * config/mh-i386win32: Deleted.
+
+Thu Jan 18 11:34:17 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * cplus-dem.c (cplus_demangle_opname): Change opname parameter to
+ const char *.
+ (cplus_mangle_opname): Change return type and opname parameter to
+ const char *. Don't cast return value.
+
+Tue Jan 16 12:13:11 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.c: Include Timer.h, in order to get m68k Microseconds trap
+ definition.
+
+Wed Jan 3 13:15:04 1996 Fred Fish <fnf@cygnus.com>
+
+ * obstack.c: Update copyright to 1996.
+ (_obstack_memory_used): Define new function. Called via
+ obstack_memory_used macro.
+
+Thu Dec 28 11:39:40 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * xstrdup.c: New file.
+ * Makefile.in (CFILES): Add xstrdup.c.
+ (REQUIRED_OFILES): Add xstrdup.o.
+ (xstrdup.o): New target.
+
+Mon Dec 11 18:18:52 1995 Mike Stump <mrs@cygnus.com>
+
+ * atexit.c: New stub to provide atexit on systems that have
+ on_exit, like SunOS 4.1.x systems.
+ * functions.def (on_exit, atexit): Ditto.
+
+Mon Dec 11 15:42:14 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw.c (mpw_abort): Remove decl.
+ (mpw_access): Move debugging printf.
+
+Sat Dec 2 01:25:23 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.table: Consistently use ${host} rather than ${xhost} or
+ ${target}.
+ * configure.in: Don't bother to set ${xhost} before calling
+ config.table.
+
+Tue Nov 28 14:16:57 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * Makefile.in (.c.o): Use test instead of the left bracket, to
+ avoid problems with some versions of make.
+
+Tue Nov 28 11:45:17 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Fix INCDIR edit to work with Nov 14 change.
+
+Tue Nov 21 11:26:34 1995 Fred Fish <fnf@rtl.cygnus.com>
+
+ * config/mh-hpux: Remove. It was only used to define EXTRA_OFILES,
+ which was set to just alloca.o, which is now automatically marked
+ as needed by the autoconfiguration process.
+
+Tue Nov 21 14:15:06 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config.table: Check ${with_cross_host} rather than comparing
+ ${host} and ${target}.
+
+Thu Nov 16 14:34:42 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: If with_target_subdir is empty, set xhost to
+ ${host} rather than ${target} before calling config.table.
+
+Tue Nov 14 01:38:30 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (MULTITOP): Deleted.
+ (MULTISRCTOP, MULTIBUILDTOP): New.
+ (FLAGS_TO_PASS): Delete INCDIR.
+ (INCDIR): Add $(MULTISRCTOP).
+ (install_to_libdir): Add $(MULTISUBDIR). Call $(MULTIDO).
+ * configure.in: Delete call to cfg-ml-com.in. Call config-ml.in
+ instead of cfg-ml-pos.in.
+ (cross-compile check): Change to test for with_target_subdir.
+ (EXTRA_LINKS): Delete.
+
+Sun Nov 12 12:13:04 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Add getpagesize.c.o to needed-list.
+ * mpw.c [USE_MW_HEADERS]: Conditionalize compiling of
+ functions that are supplied by Metrowerks libraries.
+ (fstat): Clean up descriptor->pointer conversion code.
+ (InstallConsole, etc): Empty definitions, for when linking
+ with SIOUX.
+
+Sun Nov 5 19:25:27 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * Makefile.in (FLAGS_TO_PASS): Also pass PICFLAGS.
+ (.c.o): Stylistic change.
+
+Thu Nov 2 12:06:29 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * strtol.c, strtoul.c: Don't include <stdlib.h>. From
+ phdm@info.ucl.ac.be (Philippe De Muyter).
+
+Wed Nov 1 11:59:36 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Correct sed call.
+
+Mon Oct 30 13:03:45 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * configure.in: Clean up / simplify for native.
+
+ * configure.in: Merge in stuff from ../xiberty/configure.in.
+ * Makefile.in (CC): Add definition (so it can be overrridden
+ by ../configure).
+
+Tue Oct 24 17:57:27 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Leave strerror.c.o in standard list of functions.
+ * mpw.c (R_OK, ENOENT, EACCESS, ENOSYS): Remove.
+ (link): Remove useless definition with error return.
+ (last_microseconds, warn_if_spin_delay, record_for_spin_delay):
+ Use UnsignedWide type for microsecond counts.
+
+Thu Oct 19 10:52:07 1995 Michael Meissner <meissner@wogglebug.tiac.net>
+
+ * memcmp.c (memcmp): Argument types are const void *, not void
+ *const.
+
+ * strncasecmp.c (strncasecmp): Include ansidecl.h/stdarg.h, not
+ sys/types.h.
+ * strcasecmp.c (strcasecmp): Ditto.
+
+Tue Oct 10 11:03:24 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (BISON): Remove macro.
+
+Tue Sep 26 15:06:46 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * Makefile.in (HFILES): Add default empty definition.
+ * mpw-config.in (config.h): Only update if changed.
+ * mpw-make.in: Remove.
+ * mpw-make.sed: New file, edits Makefile.in into MPW makefile.
+ * mpw.c: Remove semi-clone of strerror code.
+ (sys_nerr, sys_errlist): Define here.
+ (Microseconds): Only define as A-line trap if m68k Mac.
+
+Wed Sep 20 12:53:32 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New synonym for distclean.
+
+Mon Aug 28 19:47:52 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * config.table: For host, generalize rs6000-ibm-aix*
+ to *-ibm-aix* so we also include powerpc.
+
+Tue Aug 22 03:18:05 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Fri Jun 16 18:35:40 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * xstrerror.c: New file.
+ * Makefile.in, vmsbuild.com: Compile it.
+
+Mon Jul 31 12:16:32 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ * config.table (i386-*-win32): New.
+
+Fri Jul 21 11:35:52 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * Makefile.in (MULTITOP): New variable.
+ (MULTIDIRS, MULTISUBDIR, MULTIDO, MULTICLEAN): Likewise.
+ (all): Add multilib support.
+ (install_to_tooldir, *clean): Likewise.
+
+Mon Jul 10 11:47:27 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * makefile.dos (OBJS): Add hex.o. From DJ Delorie.
+
+Fri Jun 30 17:28:59 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * vmsbuild.com: create "new-lib.olb", build libiberty under that
+ name, and then make it become "liberty.olb" when done, so that an
+ incomplete build attempt never leaves behind something which looks
+ like a complete library.
+
+Thu Jun 29 00:22:02 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * config/mh-i386pe: New file for PE hosts.
+ * config.table: Understand PE hosts.
+
+Wed Jun 28 19:13:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * cplus-dem.c: Update from gcc.
+
+ * argv.c, dummy.c: If __STDC__, #include "alloca-conf.h" after
+ <stddef.h>.
+ * alloca-norm.h: If __STDC__, declare alloca with its parameter.
+
+Thu Jun 22 18:57:47 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.in (ALL_CFLAGS): Define NEED_basename.
+ * mpw.c: Only test DebugPI once whenever printing debug info.
+ (mpwify_filename): If filename is /tmp/foo, change it into :_foo,
+ also fix to not write on input filename buffer.
+ (mpw_access): Use stat() instead of open(), works for directories
+ as well as files.
+
+Mon Jun 19 00:33:22 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * Makefile.in: Massage broken shells that require 'else true'.
+
+Sat Jun 17 23:21:58 1995 Fred Fish <fnf@cygnus.com>
+
+ * alloca-norm.h: Declare alloca as type "PTR" to match functions.def.
+ Declare __builtin_alloca in the sparc case, as argv.c did.
+ * argv.c: Replace inline version of alloca-norm.h at start of file with
+ a #include of alloca-conf.h. Precede it with an include of ansidecl.h
+ because alloca-norm.h needs to declare alloca as "PTR".
+
+Mon Jun 12 14:24:26 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * win32.c: New file.
+
+Fri Jun 9 15:16:14 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * dummy.c: #include "alloca-conf.h".
+
+Wed Jun 7 11:46:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * Makefile.in (mostlyclean): Remove stamp-picdir.
+ (clean): Don't.
+
+Mon Jun 5 18:46:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * config.table (frags): Use toplevel pic frags.
+
+ * Makefile.in (PICFLAG): New macro.
+ (all): Depend on stamp-picdir.
+ (needed-list): Ditto.
+ (.c.o): Also build pic object.
+ (stamp-picdir): New rule.
+ (mostlyclean): Remove pic.
+ (clean): Remove stamp-picdir.
+
+Fri Mar 24 16:55:48 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * vmsbuild.com (config.h): Add `#define NEED_basename'.
+
+Tue May 23 10:12:46 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * clock.c, getopt.c, strtod.c, vsprintf.c: Change from using LGPL
+ to libio-style copyright.
+ * getpagesize.c: Remove FSF copyright.
+
+Sat May 20 12:30:23 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Added improved VMS support from Pat Rankin:
+
+ Fri Mar 17 18:40:36 1995 Pat Rankin (rankin@eql.caltech.edu)
+
+ * vmsbuild.com: new file.
+
+ * getpagesize.c (getpagesize): implement for VMS;
+ * strerror.c (strerror, strerrno, strtoerrno): add rudimentary
+ support for EVMSERR.
+
+Thu May 18 17:01:42 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ Wed May 10 14:28:16 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * floatformat.c (floatformat_arm_ext): Define.
+
+Tue May 16 13:30:59 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * basename.c, bcmp.c, getcwd.c, insque.c, rename.c, sigsetmask.c,
+ strerror.c, strsignal.c: Remove FSF copyright.
+ * sigsetmask.c: #include <sys/types.h> - seems to be needed by ISC.
+
+Mon May 15 19:53:17 1995 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * bcopy.c, bzero.c, memcmp.c, memcpy.c, memset.c, strchr.c,
+ strrchr.c, strstr.c, vfork.c: Remove FSF Copyright, because this
+ might contaminate libstdc++ with the LGPL. (OK'd by RMS 11 Oct 94.)
+ * strchr.c, strrchr.c: Add cast to suppress const warning.
+
+Thu May 4 14:36:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * cplus-dem.c: Use const instead of CONST. Don't include
+ ansidecl.h directly.
+
+Wed Apr 19 01:30:27 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * cplus-dem.c: Don't include libiberty.h. Do declare xmalloc and
+ xrealloc.
+ (-DMAIN): Don't rely on an externally-defined version number;
+ instead, require the version number to be defined as a
+ preprocessor macro. Handle the RS/6000 leading dot. Define
+ xmalloc, xrealloc and fatal. Don't strip a leading underscore
+ if we couldn't demangle the word.
+
+Tue Apr 4 13:03:51 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ (Old mpw.c change descriptions retained for informational value.)
+ * mpw.c (warning_threshold): Default to .4 sec.
+ (overflow_count, current_progress): New globals.
+ (warn_if_spin_delay): Include current progress type,
+ such as program name, in message.
+ (mpw_start_progress): Set current_progress variable from arg.
+ (mpw_end_progress): Report spin delays by power-of-two-size
+ buckets instead of constant-size buckets.
+
+ * mpw.c: Clean up formatting, types, returns, etc.
+ (ENOSYS): Define.
+ (mpw_fread, mpw_fwrite): Define.
+ (sleep): Define correctly.
+
+ * mpw.c: New code to implement cursor spinning support.
+ (umask): New function.
+ (mpw_fopen, mpw_fseek, stat, fstat): Call PROGRESS.
+
+ * mpw.c (mpw_basename, mpw_mixed_basename): New functions, find
+ basenames for MPW and MPW/Unix filenames.
+ (mpw_special_init): New function, calls Macsbug if desired.
+
+ * mpw.c: Add GPL notice.
+ (mpwify_filename): Add more transformations.
+ (mpw_fopen): Call mpwify_filename on file names.
+ (rename): Remove.
+ (chdir, getcwd): Add simple definitions.
+
+ * mpw.c: Random cleanups, remove unused code bits.
+ Added copy of strerror.c for gcc's use.
+ (stat, fstat, _stat): New versions based on Guido van Rossum code.
+
+ * mpw.c (mpw_fseek): Make it work correctly when doing SEEK_CUR.
+
+ * mpw.c (stat): Remove hack definition, get from sys/stat.h.
+ (fork, vfork, etc): Print error messages if called.
+ (getrusage, sbrk, environ, isatty, link, utime, mkdir, rmdir,
+ rename, chown): Define.
+
+ * mpw-config.in: New file, MPW version of configure.in.
+ * mpw-make.in: New file, MPW version of Makefile.in.
+ * mpw.c: New file, MPW compatibility routines.
+
+Fri Mar 24 14:10:30 1995 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * basename.c: Include config.h before checking for NEED_basename.
+
+Thu Mar 23 19:09:54 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * functions.def: Add DEFFUNC for basename.
+
+ * basename.c: Only define basename if NEED_basename.
+
+Thu Mar 16 13:36:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * config.table: Fix --enable-shared logic for native builds.
+
+Mon Mar 13 11:05:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * cplus-dem.c (demangle_template): Demangle bool literals properly.
+
+Mon Mar 6 23:57:28 1995 Stu Grossman (grossman@cygnus.com)
+
+ * strtol.c strtoul.c: Replace these with less buggy versions from
+ NetBSD. (strtoul in particular couldn't handle base 16.)
+
+Wed Mar 1 15:59:01 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * config/mt-vxworks5 (HDEFINES): Define NO_SYS_PARAM_H.
+
+ * clock.c: If NO_SYS_PARAM_H is defined, don't include
+ <sys/param.h>.
+ * getcwd.c, getpagesize.c, getruntime.c: Likewise.
+
+Fri Feb 17 15:40:55 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * getruntime.c (get_run_time): Don't assume that CLOCKS_PER_SEC is
+ a number; ANSI appears to permit any expression, including a
+ function call.
+
+ * config.table (*-*-vxworks5*): Use mt-vxworks5 when configuring
+ xiberty.
+ * config/mt-vxworks5: New file.
+
+Thu Feb 9 14:19:45 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * basename.c (basename): Change argument to be const.
+
+Wed Feb 8 18:06:52 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * Makefile.in (lneeded-list): Don't worry about xmalloc.
+
+Sun Jan 15 00:40:36 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * Makefile.in (distclean): Delete xhost-mkfrag.
+
+Thu Jan 12 16:54:18 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+
+ * Makefile.in (lneeded-list): If alloca.o is needed, so is xmalloc.o.
+
+Wed Jan 11 22:39:56 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * hex.c: New file.
+ * Makefile.in (REQUIRED_OFILES, CFILES): List it.
+ (hex.o): Add dependencies.
+
+ * cplus-dem.c (demangle_prefix): For GNU style constructor and
+ destructor names, try demangling the remainder of the string.
+
+Wed Dec 28 00:49:15 1994 Ian Lance Taylor <ian@tweedledumb.cygnus.com>
+
+ * vasprintf.c (int_vasprintf): New static function.
+ (vasprintf): Use int_vasprintf. Removes assumption that va_list
+ is assignment compatible.
+
+Sat Nov 5 19:29:12 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+
+ * Makefile.in (LIBCFLAGS): New variable.
+ (FLAGS_TO_PASS): Pass it.
+ (.c.o): Use it.
+
+Thu Nov 3 19:09:47 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * getopt.c, getopt1.c: Do compile these functions under Linux,
+ since many native versions are based on glibc but are buggy.
+
+Mon Oct 24 15:16:46 1994 Per Bothner <bothner@kalessin.cygnus.com>
+
+ * vasprintf.c: Make 'format' arg be const, to avoid a mismatch
+ with prototype in GNU libc. Support stdarg.h as well as varargs.h.
+
+Tue Oct 11 17:48:27 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+
+ * Makefile.in (REQUIRED_OFILES): Add vasprintf.o.
+ * functions.def: Remove vasprintf.
+
+Wed Sep 14 17:04:55 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * xmalloc.c (first_break): New static variable.
+ (xmalloc_set_program_name): Record sbrk (0) in first_break.
+ (xmalloc): If memory allocation fails, try to report how much
+ memory was allocated by the program up to this point.
+ (xrealloc): Likewise.
+
+Sun Sep 04 17:58:10 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+ * Makefile.in (ERRORS_CC): New variable, defaulted to $(CC). Use it
+ when linking dummy.
+ * config.table: Add host RISCiX Makefile frag.
+ * config/mh-riscix: New file.
+
+Thu Aug 25 17:29:44 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * Makefile.in (FLAGS_TO_PASS): Define.
+ ($(RULE1)): Use $(FLAGS_TO_PASS).
+
+Wed Aug 24 17:08:47 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * vasprintf.c: Include <string.h>.
+ (vasprintf): Add casts to void for va_arg to avoid gcc warnings.
+ * xatexit.c: Declare malloc.
+
+Fri Aug 19 15:29:12 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (demangle_args): Fix a bug in previous patch (the
+ one below).
+
+Thu Aug 18 14:37:14 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (demangle args): Handle ARM repeat encoding where
+ the type index is greater than 9.
+
+Wed Aug 17 16:13:49 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (demangle_qualified): accept optional '_' between
+ qualified name. This is baecause the template name may end with
+ numeric and can mixed up with the length of next qualified name.
+
+Wed Aug 3 05:52:14 1994 D. V. Henkel-Wallace (gumby@cygnus.com)
+
+ * config/mt-sunos4: Use our standard location for cross-includes
+ and cross-libs when the target is also a "host" environment (ie no
+ newlib; includes and such don't belong to us). This is specific
+ to the Cygnus Support environment.
+
+Tue Aug 2 15:25:12 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (demangle_template): demangle as xxx<'Q'> not
+ xxx<ch=81>.
+
+Mon Aug 1 17:02:48 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (main): flush stdout to make pipe work.
+
+Sat Jul 16 12:56:32 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * config.table (*-*-cxux7*): Recognize.
+ * floatformat.c (floatformat_m88110_ext) [HARRIS_FLOAT_FORMAT]:
+ Harris-specific float format.
+ * config/mh-cxux7: New file.
+
+Wed Jun 29 00:26:17 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * cplus-dem.c (demangle_template): Make sure that the result of
+ consume_count doesn't index beyond the end of the string.
+
+Mon Jun 20 23:54:37 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * cplus-dem.c (gnu_special): Handle vtable mangling of gcc-2.4.5 and
+ earlier. Improve test for new vtable mangling. Change output back
+ to `virtual table'.
+
+Mon Jun 20 11:37:30 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * obstack.c: Always compile this code, even if using the GNU
+ library. Avoids problems with relatively recent binary
+ incompatibility.
+
+Thu Jun 16 17:54:01 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * cplus-dem.c: Include libiberty.h.
+ (xmalloc, xrealloc, free): Don't declare.
+ (strstr): Don't declare parameters.
+ (xmalloc, xrealloc): Don't define.
+ (long_options): Add no-strip-underscores.
+ (main): Call xmalloc_set_program_name. Pass n in short options to
+ getopt_long. Handle option 'n' to not strip underscores.
+ (usage): Mention -n and --no-strip-underscores.
+
+Sun Jun 12 01:37:09 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * cplus-dem.c (demangle_template): Separate consecutive >'s with a
+ space.
+ (gnu_special): Demangle template and qualified names in a vtable name.
+
+Fri May 27 12:27:52 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ From gas-2.3 and binutils-2.4 net releases:
+
+ Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com)
+
+ * makefile.dos: [new] Makefile for dos/go32
+ * configure.bat: update for latest files
+ * msdos.c: remove some functions now in libc.a
+
+Fri May 20 18:53:32 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * cplus-dem.c (gnu_special): Recognize thunks, as well as
+ the new naming style for vtables (when -fvtable-thunks).
+
+Wed May 18 13:34:06 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (XTRAFLAGS): Don't define.
+ (.c.o, dummy.o): Don't use XTRAFLAGS.
+ ($(RULE1)): Don't pass XTRAFLAGS down in recursive call.
+
+Fri May 13 16:02:12 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * vasprintf.c: New file.
+ * Makefile.in, functions.def: Add it.
+
+Fri May 13 16:20:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * cplus-dem.c (demangle_fund_type): Grok bool.
+
+Fri May 6 14:44:21 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * config.table: Add go32
+ * config/mh-go32: New template.
+
+Fri May 6 11:01:59 1994 D. V. Henkel-Wallace (gumby@rtl.cygnus.com)
+
+ * config.table, config/mt-sunos4: config for when sun4 is cross target.
+
+Mon Apr 11 00:54:33 1994 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * getopt.c [not __GNU_LIBRARY__] [__GCC__] [not __STDC__]:
+ Declare strlen to return int. Don't include stddef.h.
+
+Fri Apr 1 00:38:17 1994 Jim Wilson (wilson@mole.gnu.ai.mit.edu)
+
+ * getopt.c: Delete use of IN_GCC to control whether
+ stddef.h or gstddef.h is included.
+
+Thu Apr 14 14:00:56 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (demangle_signature): Fix a bug in template function
+ type numbering.
+
+Wed Apr 13 17:23:03 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (demangle_signature): Fix template function with arm
+ style argument type number, Tn.
+
+Wed Apr 13 17:11:15 1994 Jason Merrill (jason@deneb.cygnus.com)
+
+ * cplus-dem.c (optable): Add new[] and delete[].
+
+Fri Apr 8 11:21:42 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * argv.c (buildargv): Don't produce empty argument just because
+ there is trailing whitespace.
+
+Wed Apr 6 11:42:14 1994 Kung Hsu (kung@mexican.cygnus.com)
+
+ * cplus-dem.c (demangle_template): fix 'Q' qualified name bug.
+ Handle 'p' same as 'P'.
+ * cplus-dem.c (do_type): Handle 'p' same as 'P'.
+
+Sat Mar 26 12:00:13 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * floatformat.c (get_field, put_field): Fix off by one error in
+ little endian case.
+
+Thu Mar 24 10:40:19 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * floatformat.c (floatformat_from_double): Pass unsigned char *,
+ not char *, to put_field.
+
+Fri Mar 18 12:34:33 1994 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * memmove.c: Re-wrote; placed in public domain.
+
+Wed Mar 16 10:33:07 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * cplus-dem.c (demangle_prefix): If ARM demangling, don't treat
+ __Q* as a constructor.
+
+Mon Mar 14 12:26:02 1994 Ian Lance Taylor (ian@cygnus.com)
+
+ * ieee-float.c: Removed; no longer used.
+ * Makefile.in: Changed accordingly.
+
+Mon Mar 7 12:28:17 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * floatformat.c (get_field): Removed unused local variable i.
+ (put_field): Removed unused local variable i.
+
+Sun Feb 27 21:50:11 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * floatformat.c: New file, intended to replace ieee-float.c.
+ * Makefile.in: Change accordingly.
+
+Thu Feb 24 11:51:12 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * getopt.c: Remove #ifdef GETOPT_COMPAT and #if 0 code.
+ (_getopt_initialize): New function, broken out of _getopt_internal.
+ (_getopt_internal):
+ 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.
+
+Thu Feb 10 14:44:16 1994 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * getopt.c [not __GNU_LIBRARY__] [__GNUC__] [not IN_GCC]:
+ Test just __STDC__, not emacs.
+
+Wed Feb 9 00:14:00 1994 Richard Stallman (rms@mole.gnu.ai.mit.edu)
+
+ * getopt.c [not __GNU_LIBRARY__] [__GNUC__] [not IN_GCC]
+ [emacs] [not __STDC__]: Don't include stddef.h. Don't declare strlen.
+
+Fri Dec 24 19:43:00 1993 Noah Friedman (friedman@nutrimat.gnu.ai.mit.edu)
+
+ * getopt.c (_NO_PROTO): Define before config.h is included.
+
+Mon Sep 20 15:59:03 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * getopt.c, getopt1.c [emacs || CONFIG_BROKETS]: Include
+ <config.h> only under these, else "config.h".
+
+Thu Aug 12 18:16:49 1993 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
+
+ * getopt.c, getopt1.c [HAVE_CONFIG_H]: Include
+ <config.h> instead of "config.h".
+
+Sun Feb 20 17:17:01 1994 Ian Lance Taylor (ian@lisa.cygnus.com)
+
+ * concat.c: Check ANSI_PROTOTYPES rather than __STDC__ to decide
+ whether to use prototypes or not.
+ * strerror.c (const): Never undefine; let ansidecl.h handle it.
+ * strsignal.c (const): Likewise.
+
+Thu Feb 17 13:27:35 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * xatexit.c (_xexit_cleanup): Declare as extern; don't initialize.
+ Merging common and initialized variables need not be supported by
+ ANSI C compilers.
+ (xatexit): Initialize _xexit_cleanup if not already set.
+ * xexit.c: Comment fix.
+
+Wed Feb 16 01:15:36 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * xmalloc.c: Don't declare xexit; it's declared in libiberty.h.
+ (xrealloc): If oldmem is NULL, allocate with malloc, rather than
+ assuming that realloc works correctly.
+
+Tue Feb 15 09:26:16 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * concat.c, ieee-float.c: Replace inclusion of <string.h>
+ with explicit function declarations, as recommended by Ian Taylor.
+
+Sat Feb 12 10:31:11 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * xmalloc.c (xmalloc, xrealloc): Use PTR and size_t throughout.
+ (malloc, realloc): Declare.
+
+Thu Feb 10 17:08:19 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * argv.c, basename.c: Include ansidecl.h and libiberty.h.
+ * concat.c, fdmatch.c, getruntime.c, spaces.c: Likewise.
+ * strerror.c, strsignal.c, xatexit.c, xexit.c: Likewise.
+ * xmalloc.c: Likewise.
+ * concat.c: Don't declare xmalloc. If __STDC__, use <stdarg.h>
+ macros, not <varargs.h> macros.
+ * spaces.c (spaces): Make return type const. Don't crash if
+ malloc returns NULL.
+ * strerror.c (struct error_info): Make name and msg fields const.
+ (error_names): Make const.
+ (strerrno): Make const.
+ (strtoerrno): Make argument const.
+ * strsignal.c (struct signal_info): Make name and msg fields
+ const.
+ (signal_names, sys_siglist): Make const.
+ (strsignal, strsigno): Make const.
+ (strtosigno): Make argument const.
+ * xatexit.c: Declare parameter types.
+ * xmalloc.c (name): Make const.
+ (xmalloc_set_program_name): Make argument const.
+ * Makefile.in (INCDIR): Define.
+ (.c.o): Use $(INCDIR).
+ (dummy.o): Likewise.
+ (argv.o, basename.o): New targets; depend on libiberty.h.
+ (concat.o, fdmatch.o, getruntime.o, spaces.o): Likewise.
+ (strerror.o, strsignal.o, xatexit.o, xexit.o): Likewise.
+ (xmalloc.o): Likewise.
+ (cplus-dem.o): New target; depend on demangle.h.
+ (getopt.o, getopt1.o): New targets; depend on getopt.h.
+ (ieee-float.o): New target; depend on ieee-float.h.
+ (obstack.o): New target; depend on obstack.h.
+
+Tue Feb 8 05:29:08 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ Handle obstack_chunk_alloc returning NULL. This allows
+ obstacks to be used by libraries, without forcing them
+ to call exit or longjmp.
+ * obstack.c (_obstack_begin, _obstack_begin_1, _obstack_newchunk):
+ If CALL_CHUNKFUN returns NULL, set alloc_failed, else clear it.
+ (_obstack_begin, _obstack_begin_1): Return 1 if successful, 0 if not.
+
+Tue Feb 8 00:32:28 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * concat.c, ieee-float.c: Include <string.h>.
+
+Sun Feb 6 21:28:46 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * xmalloc.c (xmalloc_set_program_name): New function.
+ (xmalloc, xrealloc): Include the name in the error message, if set.
+
+ * Replace atexit.c with xatexit.c.
+ * Makefile.in (CFILES), functions.def: Change references.
+
+Sat Feb 5 14:02:32 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * getruntime.c (get_run_time): Use getrusage or times if
+ HAVE_GETRUSAGE or HAVE_TIMES are defined.
+
+Fri Feb 4 15:49:38 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * atexit.c: New file.
+ * Makefile.in (CFILES), functions.def: Add it.
+ * xexit.c: New file.
+ * Makefile.in (CFILES, REQUIRED_OFILES): Add it.
+ * xmalloc.c (xmalloc, xrealloc): Call xexit instead of exit.
+ Change request for 0 bytes into request for 1 byte.
+
+Wed Feb 2 11:36:49 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * xmalloc.c (xmalloc, xrealloc): Print size using %lu, and cast to
+ unsigned long, to avoid warnings.
+
+Fri Jan 28 17:49:06 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * dummy.c: Don't include time.h ever; always define clock_t as
+ "unsigned long". Until gcc/fixincludes ensures that clock_t
+ exists, __STDC__ isn't a sufficient test. And if clock() doesn't
+ exist, clock_t probably doesn't either.
+
+Mon Jan 24 11:52:31 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * clock.c, getruntime.c: New files.
+ * Makefile.in: Add to file lists.
+ * functions.def (clock): Add to list.
+ * dummy.c (time.h): Add if __STDC__.
+ (clock_t): #define as "unsigned long" if not __STDC__.
+
+Tue Jan 11 11:27:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * strtod.c: Declare atof. From edler@jan.ultra.nyu.edu (Jan
+ Edler).
+
+Tue Dec 28 14:17:30 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (errors): Use CFLAGS as well as LDFLAGS when
+ linking.
+
+Fri Dec 17 12:26:07 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c (demangle_arm_pt): New function. Common code
+ for ARM template demangling.
+ * cplus-dem.c (demangle_class_name): Use demangle_arm_pt.
+ * cplus-dem.c (demangle_prefix): Likewise.
+
+Tue Nov 30 15:47:48 1993 Jason Merrill (jason@deneb.cygnus.com)
+
+ * cplus-dem.c (cplus_demangle_opname): Add CONST to please gcc.
+
+Sat Nov 27 11:05:50 1993 Fred Fish (fnf@cygnus.com)
+
+ Merge changes from tom@basil.icce.rug.nl (Tom R.Hageman)
+ * strerror.c, strsignal.c: As a small space optimization, don't
+ include messages when they aren't actually used.
+
+ Merge changes from takefive.co.at!joe (Josef Leherbauer)
+ * cplus-dem.c (demangle_prefix, demangle_function_name,
+ cplus_demangle_opname): Fixes for systems where cplus_marker
+ is something other than '$'.
+
+Fri Nov 26 13:51:11 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * waitpid.c: Simple-minded approcimation to waitpid
+ using vanilla wait.
+ * functions.def, Makefile.in: Update accordingly,
+
+Thu Nov 18 18:01:15 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c(demangle_template): fix bug template instantiation
+ with value of user defined type.
+
+Wed Nov 17 18:30:21 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c(cplus_demangle_opname): add the subject new function
+ to support unified search of operator in class.
+
+Wed Nov 10 09:47:22 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ gcc -Wall lint:
+ * strtoul.c (strtoul): use "(digit = *s) != '\0'" not just
+ "digit = *s" as condition in while loop.
+
+Tue Nov 9 15:52:22 1993 Mark Eichin (eichin@cygnus.com)
+
+ * Makefile.in: pass SHELL to recursive make
+
+Thu Nov 4 12:09:26 1993 Per Bothner (bothner@kalessin.cygnus.com)
+
+ * vfprintf.c, vprintf.c, vsprintf.c: Make format arg
+ be (const char*), for ANSI (and gcc w/fixproto) consistency.
+
+Thu Nov 4 08:29:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.table: Make *-*-hiux* use mh-hpux.
+
+Fri Oct 22 07:53:15 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * config.table: Add * to end of all OS names.
+
+Tue Oct 19 17:12:01 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Makefile.in (lneeded-list): ensure that object file names are
+ not duplicated, as multiple instances of the same object file in
+ a library causes problems on some machines
+
+Mon Oct 18 21:59:28 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * strcasecmp.c, strncasecmp.c: Change u_char to unsigned char.
+
+Fri Oct 15 22:17:11 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * strncasecmp.c: new file, implements strncasecmp
+ * strcasecmp.c: new file, implement strcasecmp
+
+ * Makefile.in (CFILES): list these two new source files
+
+ * functions.def: add strcasecmp and strncasecmp entries
+
+Fri Oct 15 14:53:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * strtoul.c (strtoul), strtol.c (strtol): Handle overflow
+ according to ANSI C.
+
+Thu Oct 14 16:34:19 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c: add support of ARM global constructor/destructor,
+ and 'G' for passing record or union in parameter.
+
+Wed Oct 13 13:36:19 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Fix comment to clarify that stuff in REQUIRED_OFILES
+ should not be in functions.def.
+
+Wed Oct 13 13:13:38 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * functions.def: Removed xmalloc. Stuff in REQUIRED_OFILES should
+ not be in functions.def.
+
+Mon Oct 4 18:26:39 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c: change globl constructor/destructor to proper name
+
+Tue Sep 28 18:11:07 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c: fix bug in constructor/destructor
+
+Tue Sep 28 16:20:49 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c: support both old and new _vt$... vtbl mangled names
+
+Fri Sep 24 19:07:16 1993 Jason Merrill (jason@deneb.cygnus.com)
+
+ * cplus-dem.c: Fix demangle_template prototype
+
+Fri Sep 24 17:32:55 1993 Kung Hsu (kung@cirdan.cygnus.com)
+
+ * cplus-dem.c: fix template demangling
+ * cplus-dem.c: fix const type demangling
+ * cplus-dem.c: fix constructor/destructor, virtual table,
+ qualifier, global constructor/destructor demangling
+
+Wed Sep 1 23:13:11 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * strsignal.c, strerror.c: Use fully-bracketed initializer to
+ keep gcc -Wall happy.
+
+Fri Aug 27 10:30:09 1993 Jason Merrill (jason@deneb.cygnus.com)
+
+ * cplus-dem.c (do_type): Add CONSTS to make gcc happy with last
+ patch.
+
+Fri Aug 27 11:24:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ Patch from Paul Flinders:
+ * cplus-dem.c (do_type): Deal with arrays.
+
+Tue Aug 24 14:23:50 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * cplus-dem.c (demangle_qualified: Deal with GNU format for more
+ than 9 classes.
+
+Wed Aug 18 19:50:29 1993 Jason Merrill (jason@deneb.cygnus.com)
+
+ * Makefile.in (dummy.o): Redirect to /dev/null to avoid "variable
+ not initialized" warnings under HP/UX
+
+Sun Aug 15 20:42:40 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * strerror.c: Move include of stdio.h after sys_errlist #define.
+ Also remove NULL definition (stdio.h always defines NULL, so it
+ never did anything but clutter up the code).
+
+Sat Aug 14 14:21:49 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * Makefile.in, functions.def: handle xmalloc.c
+
+ * xmalloc.c: provide xmalloc and xrealloc functions
+
+Thu Aug 12 17:38:57 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * cplus-dem.c: Fix a comment.
+
+Sat Aug 7 13:56:35 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * getopt1.c: Declare const the way getopt.c does.
+
+Fri Aug 6 17:03:13 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * obstack.c, alloca.c: Update from FSF.
+ * getopt.c, getopt1.c: Update to current FSF version, which
+ doesn't use alloca.
+
+Tue Jul 27 14:03:57 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * Makefile.in (demangle): Add the target with a message saying
+ where demangle went.
+
+Mon Jul 26 15:49:54 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Remove obsolete `demangle' target.
+
+Thu Jul 22 08:31:01 1993 Fred Fish (fnf@deneb.cygnus.com)
+
+ * cplus-dem.c (arm_special): Apply patch from arg@lucid.com to
+ avoid infinite loop on vtbl symbols with disambiguating "junk"
+ tacked on the end.
+
+Mon Jul 19 14:10:37 1993 david d `zoo' zuhn (zoo@rtl.cygnus.com)
+
+ * strsignal.c: work around some systems losing definitions of
+ sys_siglist
+
+ * config/mh-lynxos: this system has a losing definition of
+ sys_siglist
+
+ * config.table: use mh-lynxos for *-*-lynxos
+
+Mon Jul 19 17:08:52 1993 Ken Raeburn (raeburn@rtl.cygnus.com)
+
+ * config.table: Add support for HPPA BSD hosts.
+
+ * config/mh-hpbsd: New file.
+
+Mon Jul 12 18:00:40 1993 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in (TAGS): make work when srcdir != objdir.
+
+Sun Jun 27 15:35:31 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * cplus-dem.c (main): Add long options, including --help and
+ --version.
+ (usage): New function from code in main.
+
+Tue Jun 22 11:37:38 1993 Per Bothner (bothner@deneb.cygnus.com)
+
+ * config.table: New shell scipt, sourced by both ./configure,in
+ and ../xiberty/configure.in, to avoid maintainance lossages.
+ * configure.in and ../xiberty/configure.in: Use config.table.
+
+ * configure.in: Don't use mh-aix for AIX 3.2, only for 3.1.
+ * configure.in: Map *-*-irix* (except irix4) to mh-sysv.
+ * ../xiberty/configure.in: Update from ./configure.in.
+
+Tue Jun 15 17:05:31 1993 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: remove parentdir support
+
+Wed May 26 12:59:09 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * cplus-dem.c (xrealloc): Match definition with prototype.
+
+Tue May 25 14:27:51 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * cplus-dem.c (demangle_prefix): Demangle cfront
+ local variables as an extension to ARM demangling.
+
+Fri May 21 09:53:57 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * ieee-float.c: Don't require pointers to double to be aligned.
+
+Tue May 18 17:12:10 1993 Fred Fish (fnf@cygnus.com)
+
+ (merge changes from dlong@cse.ucsc.edu)
+ * cplus-dem.c (consume_count): Simplify.
+ * cplus-dem.c (arm_pt, demangle_class_name): New functions.
+ * cplus-dem.c (various): Calls to arm_pt, demangle_class_name.
+
+ * cplus-dem.c (xmalloc, xrealloc, strstr): Make extern decls into
+ full prototypes.
+ * cplus-dem.c (free): Add prototype.
+ * cplus-dem.c (optable): Fully bracketize initializer.
+
+Fri May 14 17:13:05 1993 Per Bothner (bothner@cygnus.com)
+
+ * cplus-dem.c: Whether initial underscores are stripped
+ depends on the external variable prepends_underscore
+ (which is generated by the binutils Makefile).
+
+Fri May 14 07:32:20 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * cplus-dem.c (mop_up, arm_special): Remove some unused variables.
+
+Tue May 4 20:31:59 1993 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c (consume_count): Return zero if arg does not
+ start with digit, and don't consume any input.
+
+Tue May 4 08:10:28 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * Makefile.in (demangle): Use ${srcdir} not $^.
+
+ * strtod.c: New file, needed at least for BSD 4.3.
+
+Sun May 2 11:30:42 1993 Fred Fish (fnf@cygnus.com)
+
+ * strsignal.c (sys_siglist): For ANSI compilations, type is
+ "const char *const". Also remove conditionalization on __STDC__
+ since const is defined away for non-ANSI.
+
+Wed Apr 28 19:29:55 1993 Ken Raeburn (raeburn@deneb.cygnus.com)
+
+ * configure.in: Recognize *-*-hpux.
+ * config/mh-hpux: New file.
+
+Tue Apr 27 15:22:19 1993 Per Bothner (bothner@cygnus.com)
+
+ * tmpnam.c: Added ANSI tmpnam() function.
+ * functions.def, Makefile.in: Update accordingly.
+
+Tue Apr 27 13:38:38 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * cplus-dem.c (demangle_function_name): Get the demangling of
+ stop__1A right.
+
+Fri Apr 16 23:48:24 1993 Jim Kingdon (kingdon at calvin)
+
+ * cplus-dem.c: Declare strstr return type.
+
+Fri Mar 26 12:01:26 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * strsignal.c: Add some AIX signals.
+
+Thu Mar 25 15:17:23 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in (MAKEOVERRIDES): Define to be empty.
+
+Wed Mar 24 01:59:25 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: add installcheck & dvi targets
+
+Thu Mar 18 14:05:44 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * ieee-float.c: New file, moved from ../gdb (since it is
+ needed by ../opcode/m68k-dis.c).
+
+Tue Mar 2 17:47:31 1993 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c: Replace all references to cfront with ARM.
+
+Fri Feb 26 00:17:07 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * cplus-dem.c: Fix main program (when compiled with -DMAIN)
+ to be more useful as a filter.
+
+Sat Feb 20 21:41:39 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * Makefile.in (install_to_libdir, install_to_tooldir): Go into the
+ destination directory before running $(RANLIB), in case that
+ program tries to create a file in the current directory as part of
+ its work.
+
+Thu Feb 18 23:00:19 1993 John Gilmore (gnu@cygnus.com)
+
+ * strsignal.c (sys_siglist): Remove yet another *%^&%&$# "const"
+ because BSD 4.4 lacks one. Isn't this fun?
+
+Thu Feb 18 11:24:25 1993 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c (demangle_signature): Set func_done after
+ demangling a template.
+ * cplus-dem.c (demangle_template): Fix several small bugs
+ in demangling GNU style templates.
+ * cplus-dem.c (demangle_prefix): Fix for templates in GNU
+ style constructors.
+ * cplus-dem.c (gnu_special): Fix for templates in GNU style
+ static data members.
+
+Tue Feb 16 17:28:35 1993 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c (demangle_signature): Modify to include type
+ modifiers like static and const in remembered types.
+
+Thu Feb 11 22:20:47 1993 Fred Fish (fnf@cygnus.com)
+
+ * cplus-dem.c (demangled_qualified): Add new parameter that tells
+ whether to prepend or append the qualifiers.
+ * cplus-dem.c (string_prepends): Used now, remove #if 0.
+ * cplus-dem.c (demangle_signature): Call demangle_qualified
+ with prepending.
+ * cplus_dem.c (gnu_special): Recognize static data members that
+ use qualified names.
+ * cplus-dem.c (demangle_qualified): Accumulate qualifiers in a
+ temporary buffer and the prepend or append them to the result,
+ as specified by the new "append" flag.
+ * cplus-dem.c (do_type): Call demangled_qualified with
+ appending.
+
+Mon Dec 28 10:47:19 1992 Ken Raeburn (raeburn@cygnus.com)
+
+ * strsignal.c (signal_table): Now const.
+ (init_signal_tables): Variable eip now points to const.
+
+ * strerror.c (error_table): Now const.
+ (init_error_tables): Variable eip now points to const.
+
+Tue Dec 15 15:36:50 1992 Per Bothner (bothner@cygnus.com)
+
+ * memchr.c (memchr): New (ANSI standard) function.
+ * Makefile.in, functions.def: Added memchr.
+ * Makefile.in (AR_FLAGS): Use rc instad of non-standard cq.
+
+Wed Dec 2 22:49:10 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * getopt.c: remove use of USG around <alloca.h>, which never meant
+ anything anyway
+
+ * config/mh-{aix,apollo68,ncr3000,sysv,sysv4}: removed definitions
+ of USG and USGr4
+
+Thu Nov 19 03:09:33 1992 Brendan Kehoe (brendan@lisa.cygnus.com)
+
+ * cplus-dem.c (demangle_fund_type): Recognize `w', a wide character;
+ it's now a type according to the ANSI X3J16 working paper; output
+ "wchar_t" for it.
+ (demangle_template): Accept `w' as an integral type.
+ (xmalloc, xrealloc): Use `char *', not `PTR'. Cast calls to their
+ counterparts malloc and realloc to `char *'.
+ (main): Exit with a 0 status.
+ * Makefile.in (demangle): Don't expect the user to define
+ DEMANGLE, instead force to be cplus-dem.c. Look in $(srcdir)/../include
+ for demangle.h. Pass it any HDEFINES or XTRAFLAGS.
+
+Wed Nov 18 18:56:20 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (AR_FLAGS): Avoid verbosity.
+ * config/mh-sysv4: Remove AR_FLAGS override, use INSTALL=cp,
+ replace USGr4 with HAVE_SYSCONF.
+ * config/mh-solaris: Remove; mh-sysv4 works now.
+ * getpagesize.c: Replace USGr4 with HAVE_SYSCONF.
+ * configure.in: Simplify host matching table, remove separate
+ solaris config file.
+
+Sun Nov 15 09:35:16 1992 Fred Fish (fnf@cygnus.com)
+
+ * configure.in (i[34]86-*-solaris2*): Add, use mh-sysv4.
+
+Tue Nov 3 21:27:03 1992 Brendan Kehoe (brendan@cygnus.com)
+
+ * cplus-dem.c (xmalloc, xrealloc): Add decls.
+ (remember_type): Don't cast xmalloc.
+ (string_need): Likewise; don't cast xrealloc either.
+
+Fri Oct 23 08:52:01 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in, functions.defs, rename.c: added simple
+ implementation of rename, since some binutils programs use it.
+
+Thu Oct 15 15:18:22 1992 Per Bothner (bothner@cygnus.com)
+
+ * strsignal.c: Add appropriate 'const' to sys_siglist
+ extern declaration (if __STDC__). (Needed for Linux.)
+ * strsignal.c (strsignal): Add cast to remove const-ness.
+
+Fri Oct 9 03:22:55 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (needed.awk, needed2.awk): Remove erroneous \'s
+ before "'s, diagnosed by BSD 4.4 awk.
+
+Thu Oct 8 15:25:12 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: create config.h and needed-list through $(CONFIG_H)
+ and $(NEEDED_LIST), to give some hooks for xiberty.
+
+Thu Oct 1 23:31:42 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: use cpu-vendor-triple instead of nested cases
+
+Wed Sep 30 11:26:59 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in, argv.c, basename.c, bcmp.c, bcopy.c, bzero.c,
+ concat.c, cplus-dem.c, fdmatch.c, getcwd.c, getopt.c, getopt1.c,
+ getpagesize.c, insque.c, memcmp.c, memcpy.c, memmove.c, memset.c,
+ obstack.c, sigsetmask.c, spaces.c, strchr.c, strerror.c,
+ strrchr.c, strsignal.c, strstr.c, vfork.c, vsprintf.c:
+ Convert from using GPL to LGPL.
+
+Sat Sep 26 04:01:30 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (errors): Leave dummy.o and dummy around so that
+ we can see how the needed list was generated (it's sometimes wrong).
+ (mostlyclean): Remove them.
+
+Mon Sep 21 14:50:42 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * getcwd.c: supply a default if MAXPATHLEN is not defined.
+
+ * config/mh-irix4: set EXTRA_OFILES to alloca.o, from WRS.
+
+Wed Sep 9 12:41:48 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: Use XTRAFLAGS when compiling, so that xiberty works
+ when cross-compiling.
+
+Thu Sep 3 13:29:39 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * cplus-dem.c: (demangle_prefix): reduction in strength of strstr
+ as a time optimization.
+
+ * cplus-dem.c (cplus_demangle): remove strpbrk test. Appears to
+ be more expensive than simply demangling.
+
+ * cplus-dem.c (cplus_match): new function.
+
+Tue Sep 1 15:24:04 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * cplus-dem.c: #include <stdio.h>, to define NULL.
+ Define current_demangling_style.
+
+Sun Aug 30 17:58:19 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * cplus-dem.c: New file, moved from ../gdb.
+ * cplus-dem.c (set_cplus_marker_for_demangling): New exported
+ function, to avoid compiling in target-dependency for CPLUS_MARKER.
+ * cplus-dem.c (cplus_demangle): Allow demangling style option
+ to be passed as a parameter, but using the global variable
+ current_demangling_style as a default.
+ * Makefile.in: Update for cplus-dem.c
+
+Sat Aug 29 10:44:09 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.c: Merge in comment changes from FSF version. Now
+ matches the FSF version exactly.
+
+Fri Aug 28 18:39:08 1992 John Gilmore (gnu@cygnus.com)
+
+ * obstack.c (CALL_FREEFUN): Can't use ?: with void values (at
+ least on losing DECstations!); use if-then-else instead.
+
+Wed Aug 19 14:40:34 1992 Ian Lance Taylor (ian@cygnus.com)
+
+ * Makefile.in: always create installation directories.
+
+Mon Aug 10 17:33:40 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: clean up definition of CFILES, more comments
+
+Sat Aug 8 23:10:59 1992 Fred Fish (fnf@cygnus.com)
+
+ * getopt.c (my_index): Make first arg const to match strchr,
+ which it sometimes is remapped to.
+
+Sat Aug 1 13:48:50 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.c (DEFAULT_ALIGNMENT): Update to match FSF version.
+ * obstack.c (_obstack_begin): Initialize use_extra_arg.
+ * obstack.c (_obstack_begin_1): New, from FSF version.
+
+Mon Jul 20 21:07:58 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.c (CALL_CHECKFUN, CALL_FREEFUN): Use use_extra_arg and
+ extra_arg.
+ * obstack.c (_obstack_begin): Remove area_id and flags arguments
+ (previously added for mmalloc support, interface has changed).
+ Also convert flags usage to use use_extra_arg and maybe_empty_object.
+
+Fri Jul 10 00:41:53 1992 Fred Fish (fnf@cygnus.com)
+
+ * argv.c: Move expandargv inline and eliminate static variables.
+ Rewrite to always allocate in powers of two. Fix to return an
+ argv with a single null string arg if passed a null string.
+
+Fri Jul 3 20:27:29 1992 Fred Fish (fnf@cygnus.com)
+
+ * random.c, sigsetmask.c, strerror.c, strsignal.c: Remove
+ "(void)" casts from function calls where the return value is
+ ignored, in accordance with GNU coding standards.
+
+Mon Jun 29 10:54:19 1992 Fred Fish (fnf at cygnus.com)
+
+ * bcopy.c, strerror.c, strsignal.c: Lint.
+
+Thu Jun 25 09:18:41 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * getopt.c: merge changes from make.
+
+Thu Jun 25 04:43:22 1992 John Gilmore (gnu at cygnus.com)
+
+ * alloca.c: Incorporate fixes from gdb/alloca.c.
+ FIXME: Eventually move gdb's alloca configuration files here,
+ and remove gdb/alloca.c and its Makefile.in support.
+
+Tue Jun 23 21:56:30 1992 Fred Fish (fnf@cygnus.com)
+
+ * dummy.c: Define NOTHING to /*nothing*/, change return type
+ of main to int and return zero.
+ * functions.def: Supply NOTHING as the fourth arg to macros
+ that don't have an explicit arg, to satisfy picky preprocessors.
+
+Wed Jun 17 18:13:58 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in: Clean up *clean rules, as per standards.texi.
+
+Tue Jun 16 16:11:59 1992 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * getopt.c, getopt1.c: merged largely gratuitous, mostly
+ whitespace diffs from other prep distributions.
+
+Mon Jun 15 12:25:46 1992 Fred Fish (fnf@cygnus.com)
+
+ * config/mh-ncr3000 (INSTALL): Don't use /usr/ucb/install,
+ it is broken on ncr 3000's.
+
+Mon Jun 15 01:03:26 1992 John Gilmore (gnu at cygnus.com)
+
+ * sigsetmask.c: Rewrite. Old one was very confused about its
+ arguments and result. New one can't do much, but at least knows
+ what it can't do, and it's good enough for GDB's use.
+
+Sun Jun 14 15:17:40 1992 Stu Grossman (grossman at cygnus.com)
+
+ * functions.def: Use proper prototype for strtoul.
+
+Fri Jun 12 19:22:40 1992 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Add random.c.
+ * config/mh-*: Use "true" rather than "echo >/dev/null" for ranlib.
+ * configure.in: update solaris2 config.
+
+Wed Jun 10 16:31:29 1992 Fred Fish (fnf@cygnus.com)
+
+ * random.c: Add for random() and srandom().
+ * functions.def: Add random
+
+Tue Jun 9 17:27:18 1992 Fred Fish (fnf@cygnus.com)
+
+ * config/{mh-ncr3000, mh-sysv4}: Add definition for INSTALL
+ using /usr/ucb/install.
+
+Mon Jun 1 13:20:17 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * strerror.c: Kludge to guard against a conflict with
+ possible declaration of sys_errlist in errno.h.
+
+Sun May 31 15:07:47 1992 Mark Eichin (eichin at cygnus.com)
+
+ * configure.in, config/mh-solaris: add solaris2 config support.
+
+Fri May 29 17:23:23 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * sigsetmask.c: #ifdef out sigsetmask if SIG_SETMASK
+ is not defined (should be defined in signal.h, says Posix.).
+
+Mon May 18 17:35:04 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * getopt.c: merged changes from make-3.62.11.
+
+Fri May 8 14:53:07 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * getopt.c: merged changes from bison-1.18.
+
+Tue May 5 11:51:40 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in: Don't have $(EXTRA_OFILES) depend on config.h,
+ since that introduces a circular dependency.
+ ($(EXTRA_OFILES) are used to build config.h.)
+
+ * strtoul.c: Fixes to handle non-decimal bases better.
+
+Wed Apr 22 09:27:51 1992 Fred Fish (fnf@cygnus.com)
+
+ * config/mh-ncr3000: Replace MINUS_G with CFLAGS.
+ * Makefile.dos: Finish MINUS_G eradication.
+ * Makefile.in (CFILES): Add strsignal.c.
+ * Makefile.in (REQUIRED_OFILES): Add strerror.o strsignal.o
+ * Makefile.in (needed-list): Split creation of errors file to
+ separate make target.
+ * Makefile.in (config.h, needed2.awk, errors): New targets.
+ * Makefile.in (clean): Split to multiple lines, add needed2.awk
+ and config.h.
+ * dummy.c (DEFFUNC, DEFVAR): Add defines and undefs.
+ * functions.def (strerror): Remove from optional list.
+ * functions.def (sys_nerr, sys_errlist, sys_siglist): DEFVAR's
+ * functions.def (strerror, psignal): DEFFUNC's
+ * strerror.c: Rewrite from scratch to use sys_errlist only if
+ available, add errno_max(), add strerrno(), add strtoerrno(),
+ add test driver.
+ * strsignal.c: New file, signal equivalent to strerror.c.
+ Uses sys_siglist if available, defines signo_max(), strsignal(),
+ strsigno(), strtosigno(), psignal(), and test driver.
+
+Mon Apr 20 20:49:32 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in: do not print recursion line.
+
+ * Makefile.in: allow CFLAGS to be passed in from command line.
+ Removed MINUS_G. Default CFLAGS to -g.
+
+Mon Apr 20 12:57:46 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * config/mh-aix: New. EXTRA_OFILES lists copysign.o,
+ so libg++ users don't have to be inconvenienced by a
+ libc.a bug (libc.a needs copysign, but doesn't define it!).
+ * configure.in: Use config/mh-aix.
+ * strtoul.c: Handle '-' as required by ANSI.
+ Clean up radix handling.
+ * strstr.c: Fix buggy algorithm.
+ * Makefile.in: Change so that ${EXTRA_OFILES} is
+ appended to needed-list (which is used by libg++).
+
+Fri Apr 10 22:51:41 1992 Fred Fish (fnf@cygnus.com)
+
+ * configure.in: Recognize new ncr3000 config.
+ * config/mh-ncr3000: New config file.
+
+Wed Apr 1 23:31:43 1992 John Gilmore (gnu at cygnus.com)
+
+ * argv.c, dummy.c: Lint.
+
+Tue Mar 31 18:46:44 1992 Fred Fish (fnf@cygnus.com)
+
+ * config/mh-sysv4: New config file.
+ * configure.in (host_makefile_frag): Set to config/mh-sysv4 for
+ host_os == sysv4.
+ * getpagesize.c: For SVR4, use sysconf(_SC_PAGESIZE) to get
+ pagesize.
+
+Sun Mar 29 12:26:42 1992 John Gilmore (gnu at cygnus.com)
+
+ * getopt.c: Lint.
+
+Fri Mar 27 08:32:55 1992 Fred Fish (fnf@cygnus.com)
+
+ * functions.def (alloca): Fix return type and args to avoid
+ type clash with gcc's builtin alloca.
+
+Tue Mar 24 23:33:42 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * configure.in, config/mh-irix4: irix4 support.
+
+ * Makefile.in, functions.def, alloca.c: added alloca.
+
+Tue Mar 24 17:34:46 1992 Stu Grossman (grossman at cygnus.com)
+
+ * obstack.c (CALL_FREEFUN): Make it compile on DECstations.
+
+Thu Mar 19 13:57:42 1992 Fred Fish (fnf@cygnus.com)
+
+ * argv.c: Fix various external function definitions to be
+ correct in an ANSI compilation environment.
+
+Sat Mar 14 17:28:17 1992 Fred Fish (fnf@cygnus.com)
+
+ * obstack.c: Changes to support calling mmalloc functions,
+ which take an additional argument over malloc functions.
+
+Fri Mar 6 22:01:10 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * added check target.
+
+Thu Feb 27 22:19:39 1992 Per Bothner (bothner@cygnus.com)
+
+ * argv.c: #include alloca-conf.h (needed by AIX).
+
+Wed Feb 26 18:04:40 1992 K. Richard Pixley (rich@cygnus.com)
+
+ * Makefile.in, configure.in: removed traces of namesubdir,
+ -subdirs, $(subdir), $(unsubdir), some rcs triggers. Forced
+ copyrights to '92, changed some from Cygnus to FSF.
+
+Sat Feb 22 01:09:21 1992 Stu Grossman (grossman at cygnus.com)
+
+ * argv.c: Check in Fred's version which fixes problems with
+ alloca().
+
+Fri Feb 7 21:46:08 1992 Stu Grossman (grossman at cygnus.com)
+
+ * makefile.dos: Remove NUL to keep patch from failing.
+
+Thu Jan 30 22:48:41 1992 Stu Grossman (grossman at cygnus.com)
+
+ * getopt.c (_getopt_internal): Fix usage of enum has_arg.
+
+Mon Jan 20 18:53:23 1992 Stu Grossman (grossman at cygnus.com)
+
+ * getopt.c, getopt1.c, ../include/getopt.h: Get latest versions.
+
+Sat Jan 18 16:53:01 1992 Fred Fish (fnf at cygnus.com)
+
+ * argv.c: New file to build and destroy standard argument
+ vectors from a command string.
+
+ * Makefile.in: Add argv.c and argv.o to appropriate macros.
+
+Fri Dec 20 12:12:57 1991 Fred Fish (fnf at cygnus.com)
+
+ * configure.in: Change svr4 references to sysv4.
+
+ * rindex.c: Declare return type of externally used function
+ strrchr().
+
+Thu Dec 19 18:35:03 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Remove "***" in normal output, since Make produces
+ this on errors, and it's convenient to search for.
+
+Tue Dec 17 23:21:30 1991 Per Bothner (bothner at cygnus.com)
+
+ * memcmp.c, memcpy.c, memmove.c, memset.c, strchr.c, strrchr.c:
+ New ANSI functions. The old non-ANSI functions (such as bcopy)
+ should be avoided.
+ * bcopy.c: Fix to correctly handle overlapping regions.
+ * index.c, rindex.c: Re-write in terms of strchr() and strrchr().
+ * functions.def: Add the new functions.
+ * functions.def: Add 4th parameter to DEF macro,
+ an ansidecl.h-style prototype.
+ * dummy.c: Use expanded DEF macro to create a dummy function
+ call, with correct parameter types. (This avoids some
+ complaints from gcc about predefined builtins.)
+
+ Move the functionality of config/mh-default into Makefile.in.
+ This avoid duplication, and simplifies things slightly.
+ * Makefile.in: Tweak so we don't need config/mh-default.
+ * README: Update.
+ * configure.in: No longer need config/mh-default.
+ * config/mh-default: Deleted.
+ * config/mh-sysv: Remove lines copied from old mh-default.
+
+Tue Dec 17 05:46:46 1991 John Gilmore (gnu at cygnus.com)
+
+ * fdmatch.c (fdmatch): Don't compare st_rdev, which is for
+ 'mknod' device numbers.
+
+Mon Dec 16 12:25:34 1991 Fred Fish (fnf at cygnus.com)
+
+ * fdmatch.c, Makefile.in: Add new function that takes two
+ open file descriptors and returns nonzero if they refer to
+ the same file, zero otherwise. (used in gdb)
+
+Wed Dec 11 17:40:39 1991 Steve Chamberlain (sac at rtl.cygnus.com)
+ From DJ:
+ * msdos.c: stub functions for dos.
+ * makefile.dos, configdj.bat: new.
+ * getopt.c: Don't include alloca-conf.h in a GO32 world.
+
+
+Tue Dec 10 04:14:49 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: infodir belongs in datadir.
+
+Fri Dec 6 23:26:45 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: remove spaces following hyphens because bsd make
+ can't cope. added standards.text support. install using
+ INSTALL_DATA.
+
+ * configure.in: remove commontargets as it is no longer a
+ recognized hook.
+
+Thu Dec 5 22:46:46 1991 K. Richard Pixley (rich at rtl.cygnus.com)
+
+ * Makefile.in: idestdir and ddestdir go away. Added copyrights
+ and shift gpl to v2. Added ChangeLog if it didn't exist. docdir
+ and mandir now keyed off datadir by default.
+
+Fri Nov 22 19:15:29 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: find-needed.awk does not fit in 14 chars.
+
+ * Makefile.in: Suppress error checking when compiling the test
+ program, because Ultrix make/sh aborts there due to a bug.
+
+Fri Nov 22 12:23:17 1991 Per Bothner (bothner at cygnus.com)
+
+ * Makefile.in: Re-did how EXTRA_OFILES is used to be more useful.
+ * README: Explained how the auto-configuration works,
+ and how to add new files and/or configurations.
+
+Fri Nov 22 09:45:23 1991 John Gilmore (gnu at cygnus.com)
+
+ * strtoul.c: Avoid defining ULONG_MAX if already defined;
+ cast a const char * to char * for pedants.
+
+ * getopt.c: Only define "const" after local include files get to,
+ and only if they haven't defined it.
+
+Thu Nov 21 16:58:53 1991 John Gilmore (gnu at cygnus.com)
+
+ * getcwd.c (remove getwd.c): GNU code should call getcwd(). We
+ emulate it with getwd() if available. This avoids callers having
+ to find a MAXPATHLEN or PATH_MAX value from somewhere.
+ * Makefile.in, functions.def: getwd->getcwd.
+ * configure.in: Use generic case for every system.
+ * config/mh-{delta88,mach,rs6000,svr4}: Remove.
+ * config/mh-sysv: Use default handling, just add -DUSG.
+
+Thu Nov 14 10:58:05 1991 Per Bothner (bothner at cygnus.com)
+
+ * Makefile.in, config/mh-default: Re-do make magic
+ so that for the default ("automatic") mode we only
+ compile the files we actually need. Do this using
+ a recursive make: The top-level generates the list
+ of needed files (loosely, the ones missing in libc),
+ and then passes that list to the recursive make.
+ * config/mh-mach: Remove obsolete STRERROR-{C,O} macros.
+
+Tue Nov 12 19:10:57 1991 John Gilmore (gnu at cygnus.com)
+
+ RS/6000 host support (grumble).
+
+ * configure.in: Build alloca-conf.h file from alloca-norm.h
+ (everything else) or alloca-botch.h (rs/6000).
+ * Makefile.in: Include . on the include path.
+ * getopt.c: Use alloca-conf.h.
+ * alloca-norm.h: How to declare alloca on reasonable machines.
+ * alloca-botch.h: How to declare alloca on braindead machines.
+
+Tue Nov 12 09:21:48 1991 Fred Fish (fnf at cygnus.com)
+
+ * concat.c : New file, like concat() in gdb but can take a
+ variable number of arguments rather than fixed at 3 args. For
+ now, client applications must supply an xmalloc(), which is a
+ front end function to malloc() that deals with out-of-memory
+ conditions.
+
+ * Makefile.in: Add concat.c and concat.o to appropriate macros.
+
+Sat Nov 9 13:29:59 1991 Fred Fish (fnf at cygnus.com)
+
+ * config/mh-svr4: Add sigsetmask to list of required functions.
+
+Sun Nov 3 11:57:56 1991 Per Bothner (bothner at cygnus.com)
+
+ * vsprintf.c: New file.
+ * functions.def, Makefile.in: Add vsprintf.
+
+Sun Oct 27 16:31:22 1991 John Gilmore (gnu at cygnus.com)
+
+ * configure.in, config/mh-rs6000: Add rs/6000 host support.
+ * Makefile.in: Compile with debug info.
+
+Fri Oct 25 17:01:12 1991 Per Bothner (bothner at cygnus.com)
+
+ * Makefile.in, configure.in, and new files: dummy.c, functions.def,
+ config/mf-default: Added a default configuration mode,
+ which includes into libiberty.a functions that are "missing" in libc.
+ * strdup.c, vprintf.c, vfprintf.c: New files.
+
+Thu Oct 24 02:29:26 1991 Fred Fish (fnf at cygnus.com)
+
+ * config/hmake-svr4: New file.
+
+ * config/hmake-sysv: Add HOST_CFILES and HOST_OFILES.
+
+ * basename.c, bcmp.c, bcopy.c, bzero.c, getpagesize.c getwd.c,
+ index.c, insque.c, rindex.c, spaces.c, strstr.c, vfork.c: New
+ files containing either portable C versions or emulations using
+ native library calls.
+
+ * strerror.c: Add copyright, internal documentation, etc.
+
+ * strtol.c: Replace hardwired hex constants with some more
+ portable macros. Remove illegal (according to gcc) cast.
+
+ * strtoul.c: Replace hardwired hex constant with more portable
+ macro.
+
+ * Makefile.in: Move TARGETLIB and CFLAGS where makefile fragments
+ can override them. Add new source and object file names to CFILES
+ and OFILES respectively.
+
+ * configure.in: Add support for SVR4 makefile fragments.
+
+Tue Oct 22 19:00:23 1991 Steve Chamberlain (steve at cygnus.com)
+
+ * Makefile.in: Move RANLIB, AR and AR_FLAGS to where they can be
+ over-ridden by config/hmake-*
+ * configure.in: added m88kcvs to sysv list
+
+Fri Oct 4 01:29:08 1991 John Gilmore (gnu at cygnus.com)
+
+ * Makefile.in: Most hosts need strerror, but one or two don't,
+ and they override these definitions in the host-dependent makefile
+ fragment.
+ * config/hmake-mach: The odd man out on strerror -- it's supplied.
+ * strerror.c: New file.
+
+ * strtol.c, strtoul.c: Add strtol to libiberty, since Mach lacks
+ it and bfd uses it.
+ * configure.in, Makefile.in, config/hmake-mach: Only configure
+ strtol & strotoul in on Mach.
+
+Tue Sep 3 06:36:23 1991 John Gilmore (gnu at cygint.cygnus.com)
+
+ * obstack.c: Merge with latest FSF version.
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/libiberty/Makefile.in b/contrib/gdb/libiberty/Makefile.in
new file mode 100644
index 0000000..7f11d51
--- /dev/null
+++ b/contrib/gdb/libiberty/Makefile.in
@@ -0,0 +1,321 @@
+#
+# Makefile
+# Copyright (C) 1990, 1991, 1992, 1995 Free Software Foundation
+#
+# This file is part of the libiberty library.
+# Libiberty 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 Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# Libiberty is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with libiberty; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+# This file was written, and is maintained by K. Richard Pixley
+# <rich@cygnus.com>.
+
+#
+# Makefile for libiberty directory
+#
+
+srcdir = .
+
+prefix = /usr/local
+
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+
+datadir = $(prefix)/lib
+
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+oldincludedir =
+docdir = $(datadir)/doc
+
+SHELL = /bin/sh
+
+# Multilib support variables.
+MULTISRCTOP =
+MULTIBUILDTOP =
+MULTIDIRS =
+MULTISUBDIR =
+MULTIDO = true
+MULTICLEAN = true
+
+INSTALL = install -c
+INSTALL_PROGRAM = $(INSTALL)
+INSTALL_DATA = $(INSTALL)
+
+AR = ar
+AR_FLAGS = rc
+
+ERRORS_CC = $(CC)
+CC = cc
+CFLAGS = -g
+LIBCFLAGS = $(CFLAGS)
+MAKEINFO = makeinfo
+RANLIB = ranlib
+
+PICFLAG =
+
+MAKEOVERRIDES =
+
+TARGETLIB = libiberty.a
+
+CONFIG_H = lconfig.h
+NEEDED_LIST = lneeded-list
+
+# HOST_OFILES contains the list of objects that should be in the
+# library (in addition to the REQUIRED_OFILES and EXTRA_OFILES).
+# A configuration may override this with a fixed list a object files
+# names (hard to maintain), or some other way to generate a list.
+HOST_OFILES=`cat needed-list`
+
+# Extra targets that the top-level target depends on.
+# Specifically, what needs to be made before HOST_OFILES can be used.
+# Can be empty if HOST_OFILES is just a list of file names.
+DO_ALSO = needed-list
+
+# A configuration can specify extra .o files that should be included,
+# even if they are in libc. (Perhaps the libc version is buggy.)
+EXTRA_OFILES =
+
+# Flags to pass to a recursive make.
+FLAGS_TO_PASS = \
+ "AR=$(AR)" \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS)" \
+ "LIBCFLAGS=$(LIBCFLAGS)" \
+ "EXTRA_OFILES=$(EXTRA_OFILES)" \
+ "HDEFINES=$(HDEFINES)" \
+ "LDFLAGS=$(LDFLAGS)" \
+ "LOADLIBES=$(LOADLIBES)" \
+ "PICFLAG=$(PICFLAG)" \
+ "RANLIB=$(RANLIB)" \
+ "SHELL=$(SHELL)"
+
+all: stamp-picdir $(TARGETLIB) required-list
+ @if [ "$(RULE1)" != "not-used" ]; then \
+ $(MULTIDO) $(FLAGS_TO_PASS) multi-do DO=all; \
+ else true; \
+ fi
+
+.PHONY: check installcheck
+check installcheck:
+
+
+#### Host, target, and site specific Makefile fragments come in here.
+###
+
+INCDIR=$(srcdir)/$(MULTISRCTOP)../include
+
+COMPILE.c = $(CC) -c $(LIBCFLAGS) -I. -I$(INCDIR) $(HDEFINES)
+.c.o:
+ test -z "$(PICFLAG)" || \
+ $(COMPILE.c) $(PICFLAG) $< -o pic/$@
+ $(COMPILE.c) $<
+
+# The default target just invokes make recursively.
+# However, the automatic configuration (in config/mh_default).
+# first causes it to figure out the objects missing in libc.
+info install-info clean-info dvi:
+
+# Include files that are in this directory.
+HFILES =
+
+# NOTE: If you add new files to the library, add them to this list
+# (alphabetical), and add them to REQUIRED_OFILES or 'functions.def'.
+CFILES = alloca.c argv.c basename.c bcmp.c bcopy.c bzero.c \
+ clock.c concat.c cplus-dem.c fdmatch.c \
+ getcwd.c getopt.c getopt1.c getpagesize.c getruntime.c \
+ floatformat.c hex.c index.c insque.c \
+ memchr.c memcmp.c memcpy.c memmove.c memset.c \
+ obstack.c random.c rename.c rindex.c sigsetmask.c spaces.c \
+ strcasecmp.c strncasecmp.c \
+ strchr.c strdup.c strerror.c strrchr.c strsignal.c \
+ strstr.c strtod.c strtol.c strtoul.c tmpnam.c \
+ vasprintf.c vfork.c vfprintf.c vprintf.c vsprintf.c waitpid.c \
+ xatexit.c xexit.c xmalloc.c xstrdup.c xstrerror.c
+# These are always included in the library.
+REQUIRED_OFILES = argv.o basename.o concat.o cplus-dem.o fdmatch.o \
+ getopt.o getopt1.o getruntime.o hex.o \
+ floatformat.o obstack.o spaces.o strerror.o strsignal.o \
+ vasprintf.o xatexit.o xexit.o xmalloc.o xstrdup.o xstrerror.o
+
+# Do we want/need any config overrides?
+#
+
+STAGESTUFF = $(TARGETLIB) *.o
+
+INSTALL_DEST = libdir
+install: install_to_$(INSTALL_DEST)
+
+install_to_libdir: all
+ $(INSTALL_DATA) $(TARGETLIB) $(libdir)/$(TARGETLIB).n
+ ( cd $(libdir) ; $(RANLIB) $(libdir)/$(TARGETLIB).n )
+ mv -f $(libdir)/$(TARGETLIB).n $(libdir)$(MULTISUBDIR)/$(TARGETLIB)
+ @$(MULTIDO) $(FLAGS_TO_PASS) multi-do DO=install
+
+install_to_tooldir: all
+ $(INSTALL_DATA) $(TARGETLIB) $(tooldir)/lib/$(TARGETLIB).n
+ ( cd $(tooldir) ; $(RANLIB) $(tooldir)/lib/$(TARGETLIB).n )
+ mv -f $(tooldir)/lib/$(TARGETLIB).n $(tooldir)/lib$(MULTISUBDIR)/$(TARGETLIB)
+ @$(MULTIDO) $(FLAGS_TO_PASS) multi-do DO=install
+
+# The default configuration adds to libiberty all those functions that are
+# missing in libc. More precisely, it includes whatever $(CC) fails to find.
+# Then a sed+awk combination translates the ld error messages into
+# a list of .o files.
+
+needed-list: stamp-picdir $(NEEDED_LIST)
+ cp $(NEEDED_LIST) needed-list
+
+lneeded-list: $(EXTRA_OFILES) needed.awk errors
+ rm -f lneeded-list
+ f=""; \
+ for i in `awk -f needed.awk <errors` $(EXTRA_OFILES) ; do \
+ case " $$f " in \
+ *" $$i "*) ;; \
+ *) f="$$f $$i" ;; \
+ esac ; \
+ done ; \
+ echo $$f >>lneeded-list
+
+# Generate an awk script that looks for functions in functions.def
+
+needed.awk: $(srcdir)/functions.def Makefile
+ echo "# !Automatically generated from $(srcdir)/functions.def"\
+ "- DO NOT EDIT!" >needed.awk
+ grep '^DEF(' < $(srcdir)/functions.def \
+ | sed -e '/DEF/s|DEF.\([^,]*\).*|/\1/ { printf "\1.o " }|' \
+ >>needed.awk
+
+config.h: $(CONFIG_H)
+ cp $(CONFIG_H) config.h
+
+lconfig.h: needed2.awk errors
+ echo "/* !Automatically generated from $(srcdir)/functions.def"\
+ "- DO NOT EDIT! */" >lconfig.h
+ awk -f needed2.awk <errors >>lconfig.h
+
+# Generate an awk script that looks for variables in functions.def
+
+needed2.awk: $(srcdir)/functions.def Makefile
+ echo "# !Automatically generated from $(srcdir)/functions.def"\
+ "- DO NOT EDIT!" >needed2.awk
+ grep '^DEFVAR(' < $(srcdir)/functions.def \
+ | sed -e '/DEFVAR/s|DEFVAR.\([^,]*\).*|/\1/ { printf "#ifndef NEED_\1\\n#define NEED_\1\\n#endif\\n" }|' \
+ >>needed2.awk
+ grep '^DEFFUNC(' < $(srcdir)/functions.def \
+ | sed -e '/DEFFUNC/s|DEFFUNC.\([^,]*\).*|/\1/ { printf "#ifndef NEED_\1\\n#define NEED_\1\\n#endif\\n" }|' \
+ >>needed2.awk
+
+dummy.o: $(srcdir)/dummy.c $(srcdir)/functions.def
+ $(CC) -c $(CFLAGS) -I. -I$(INCDIR) $(HDEFINES) $(srcdir)/dummy.c 2>/dev/null
+
+errors: dummy.o $(EXTRA_OFILES)
+ -($(ERRORS_CC) -o dummy $(CFLAGS) $(LDFLAGS) $(ERRORS_LDFLAGS) dummy.o $(EXTRA_OFILES) $(LOADLIBES)) >errors 2>&1 || true
+
+# required-list is used when building a shared bfd/opcodes/libiberty library.
+required-list: Makefile
+ echo $(REQUIRED_OFILES) > required-list
+
+$(HOST_OFILES) $(REQUIRED_OFILES) : config.h
+
+RULE1 = $(TARGETLIB)
+$(RULE1): $(REQUIRED_OFILES) $(DO_ALSO) .always.
+ @$(MAKE) RULE1=not-used RULE2=$(TARGETLIB) $(FLAGS_TO_PASS) \
+ "HOST_OFILES=$(HOST_OFILES)"
+
+# Rule invoked by recursive make in $(RULE1).
+RULE2 = not-used
+$(RULE2): $(REQUIRED_OFILES) $(HOST_OFILES)
+ rm -rf $(TARGETLIB)
+ $(AR) $(AR_FLAGS) $(TARGETLIB) \
+ $(REQUIRED_OFILES) $(HOST_OFILES)
+ $(RANLIB) $(TARGETLIB)
+
+stamp-picdir:
+ if [ -n "$(PICFLAG)" ] && [ ! -d pic ]; then \
+ mkdir pic; \
+ else true; fi
+ touch stamp-picdir
+
+.always.:
+# Do nothing.
+
+.PHONY: all etags tags ls clean stage1 stage2 .always.
+
+etags tags: TAGS
+
+TAGS: $(CFILES) $(HFILES)
+ etags `for i in $(HFILES) $(CFILES); do echo $(srcdir)/$$i ; done`
+
+# The standalone demangler (c++filt) has been moved to binutils.
+demangle:
+ @echo "The standalone demangler, now named c++filt, is now"
+ @echo "a part of binutils."
+ @false
+
+ls:
+ @echo Makefile $(HFILES) $(CFILES)
+
+# Need to deal with profiled libraries, too.
+
+mostlyclean:
+ rm -rf *.o pic core errs \#* *.E a.out
+ rm -f needed.awk needed2.awk errors dummy needed-list config.h
+ rm -f $(CONFIG_H) $(NEEDED_LIST) stamp-picdir
+ @$(MULTICLEAN) multi-clean DO=mostlyclean
+clean: mostlyclean
+ rm -f *.a required-list
+ @$(MULTICLEAN) multi-clean DO=clean
+distclean: clean
+ rm -f *~ Makefile config.status alloca-conf.h xhost-mkfrag TAGS
+ @$(MULTICLEAN) multi-clean DO=distclean
+maintainer-clean realclean: distclean
+
+force:
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
+
+argv.o: $(INCDIR)/libiberty.h
+basename.o: $(INCDIR)/libiberty.h
+concat.o: $(INCDIR)/libiberty.h
+cplus-dem.o: $(INCDIR)/demangle.h
+fdmatch.o: $(INCDIR)/libiberty.h
+getopt.o: $(INCDIR)/getopt.h
+getopt1.o: $(INCDIR)/getopt.h
+getruntime.o: $(INCDIR)/libiberty.h
+hex.o: $(INCDIR)/libiberty.h
+floatformat.o: $(INCDIR)/floatformat.h
+obstack.o: $(INCDIR)/obstack.h
+spaces.o: $(INCDIR)/libiberty.h
+strerror.o: $(INCDIR)/libiberty.h
+strsignal.o: $(INCDIR)/libiberty.h
+xatexit.o: $(INCDIR)/libiberty.h
+xexit.o: $(INCDIR)/libiberty.h
+xmalloc.o: $(INCDIR)/libiberty.h
+xstrdup.o: $(INCDIR)/libiberty.h
+xstrerror.o: $(INCDIR)/libiberty.h
diff --git a/contrib/gdb/libiberty/README b/contrib/gdb/libiberty/README
new file mode 100644
index 0000000..5081bba
--- /dev/null
+++ b/contrib/gdb/libiberty/README
@@ -0,0 +1,129 @@
+This directory contains the -liberty library of free software.
+It is a collection of subroutines used by various GNU programs.
+Current members include:
+
+ getopt -- get options from command line
+ obstack -- stacks of arbitrarily-sized objects
+ strerror -- error message strings corresponding to errno
+ strtol -- string-to-long conversion
+ strtoul -- string-to-unsigned-long conversion
+
+We expect many of the GNU subroutines that are floating around to
+eventually arrive here.
+
+To build the library, do:
+
+ ./configure HOSTTYPE
+ make
+
+Please report bugs and fixes to "bug-gnu-utils@prep.ai.mit.edu". Thank you.
+
+ADDING A NEW FILE
+=================
+
+There are two sets of files: Those that are "required" will be
+included in the library for all configurations, while those
+that are "optional" will be included in the library only if "needed."
+
+To add a new required file, edit Makefile to add the source file
+name to CFILES and the object file to REQUIRED_OFILES.
+
+Adding a new optional file is more fragile. As a general rule,
+an optional file will be included in the library if it provides
+functionality missing in the "standard" C library.
+For most hosts, the Makefile automatically figures out which
+functionality is missing by compiling and linking a dummy test
+program, and examining the error messages.
+
+So to get this to work, you should do the following:
+
+1) Select one function defined in the file you're adding.
+For example, the getcwd function.
+2) Add that function to the list in the file functions.def.
+3) The name of the new file must be the same as the function
+you've chosen with the .c suffix added. E.g. getcwd() must be
+defined in getcwd.c. (The file can define other functions as well.)
+4) In Makefile.in, add the name of the source file (e.g. getcwd.c)
+to CFILES.
+
+The file you've added (e.g. getcwd.c) should compile and work
+on all hosts where it is needed (e.g. not found when linking
+the dummy.c program). It does not have to work or even
+compile on hosts where it is not needed.
+
+HOW THE AUTOMATIC CONFIGURATION WORKS
+=====================================
+
+The libiberty.a target (in RULE1) depends on $(DO_ALSO).
+For normal configurations, DO_ALSO=needed-list.
+
+So needed-list is first made. The needed-list rule compiles
+dummy.c. Because dummy.c includes functions.def, the
+resulting object file will contain a call to each of the
+optional functions (for simplicity assume each optional file
+defines a single function). This object file will be linked
+against the standard libraries (as defined by using $(CC)
+and various flags). Any function missing will causes the
+linker to emit an error message. We assume the name
+of the missing function(s) are in the error message(s).
+The awk script find-needed.awk has been generated from
+functions.def. It is used to search the linker output
+messages for words that match the functions listed in
+functions.def. The list of functions found is written
+on a single line to the file needed-list.
+
+After needed-list has been generated, the libiberty.a
+target (in RULE1) just calls 'make' recursively.
+It passes the contents of needed-list using the
+definition (expanded) HOST_OFILES="`cat needed-list`".
+It also tells the inferior 'make' to use RULE2.
+
+The inferior 'make' is very conventional: The main
+rule is $(RULE2) (which is libiberty.a). It depends
+on a list of object files: $(REQUIRED_OFILES) $(HOST_OFILES)
+(and $(EXTRA_OFILES), which is usually empty). The superior
+'make' passes in $(HOST_OFILES); the others are fixed
+in the Makefile.
+
+ADDING A NEW CONFIGURATION
+==========================
+
+On most hosts you should be able to use the scheme for automatically
+figuring out which files are needed. In that case, you probably
+don't need a special Makefile stub for that configuration.
+
+If the fully automatic scheme doesn't work, you may be able to get
+by with defining EXTRA_OFILES in your Makefile stub. This is
+a list of object file names that should be treated as required
+for this configuration - they will be included in libiberty.a,
+regardless of whatever might be in the C library. Moreover,
+when the dummy.c program is linked, it will be linked with
+$(EXTRA_OFILES). Therefore, if a function in functions.def
+is defined by one of the EXTRA_OFILES, it will not be listed as
+"needed". Thus if your hal9000 host needs a special implementation
+of getcwd, you can just create hal9000-getcwd.c, and define:
+ EXTRA_OFILES=hal9000-getcwd.o
+Or if you want to use the libiberty version of strstr(),
+even though there is a version in the C library (it might be
+buggy or slow), just define:
+ EXTRA_OFILES=strstr.o
+
+You can create a "manual" host configuration FOO with a file
+config/mh-FOO. In it, the HOST_OFILES macro should explicitly
+list that subset of the optional files that should be in the
+library. You should also set:
+ DO_ALSO =
+This overrides all of the magic needed to automatically
+determine which files are "needed." However, keeping that list
+up to date is another matter...
+
+HOW THE MANUAL CONFIGURATION WORKS
+==================================
+
+This also uses a recursive make, but the superior make
+does not do anything interesting - it just calls the
+inferior make with HOST_OFILES defined as $(HOST_OFILES),
+which is the list you created in your configuration.
+
+You probably don't want to depend on manual configuration,
+because keeping the HOST_OFILES list up-to-date will be a pain.
diff --git a/contrib/gdb/libiberty/alloca-botch.h b/contrib/gdb/libiberty/alloca-botch.h
new file mode 100644
index 0000000..c909573
--- /dev/null
+++ b/contrib/gdb/libiberty/alloca-botch.h
@@ -0,0 +1,5 @@
+/* RS/6000 AIX botched alloca and requires a pragma, which ordinary compilers
+ throw up about, so we have to put it in a specially-configured file.
+ Like this one. */
+
+#pragma alloca
diff --git a/contrib/gdb/libiberty/alloca-norm.h b/contrib/gdb/libiberty/alloca-norm.h
new file mode 100644
index 0000000..8d91b5a
--- /dev/null
+++ b/contrib/gdb/libiberty/alloca-norm.h
@@ -0,0 +1,16 @@
+/* "Normal" configuration for alloca. */
+
+#ifdef __GNUC__
+#define alloca __builtin_alloca
+#else /* not __GNUC__ */
+#ifdef sparc
+#include <alloca.h>
+extern char *__builtin_alloca(); /* Stupid include file doesn't declare it */
+#else
+#ifdef __STDC__
+PTR alloca (size_t);
+#else
+PTR alloca (); /* must agree with functions.def */
+#endif
+#endif /* sparc */
+#endif /* not __GNUC__ */
diff --git a/contrib/gdb/libiberty/alloca.c b/contrib/gdb/libiberty/alloca.c
new file mode 100644
index 0000000..9c472ea
--- /dev/null
+++ b/contrib/gdb/libiberty/alloca.c
@@ -0,0 +1,475 @@
+/* alloca.c -- allocate automatically reclaimed memory
+ (Mostly) portable public-domain implementation -- D A Gwyn
+
+ This implementation of the PWB library alloca function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+ J.Otto Tennant <jot@cray.com> contributed the Cray support.
+
+ There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection. */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* If compiling with GCC, this file's not needed. */
+#ifndef alloca
+
+#ifdef emacs
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+/* If your stack is a linked list of frames, you have to
+ provide an "address metric" ADDRESS_FUNCTION macro. */
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+long i00afunc ();
+#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
+#else
+#define ADDRESS_FUNCTION(arg) &(arg)
+#endif
+
+#if __STDC__
+typedef void *pointer;
+#else
+typedef char *pointer;
+#endif
+
+#define NULL 0
+
+/* Different portions of Emacs need to call different versions of
+ malloc. The Emacs executable needs alloca to call xmalloc, because
+ ordinary malloc isn't protected from input signals. On the other
+ hand, the utilities in lib-src need alloca to call malloc; some of
+ them are very simple, and don't have an xmalloc routine.
+
+ Non-Emacs programs expect this to call use xmalloc.
+
+ Callers below should use malloc. */
+
+#ifndef emacs
+#define malloc xmalloc
+extern pointer xmalloc ();
+#endif
+
+/* Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown */
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* Direction unknown. */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
+
+#else /* STACK_DIRECTION == 0; need run-time code. */
+
+static int stack_dir; /* 1 or -1 once known. */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction ()
+{
+ static char *addr = NULL; /* Address of first `dummy', once known. */
+ auto char dummy; /* To get stack address. */
+
+ if (addr == NULL)
+ { /* Initial entry. */
+ addr = ADDRESS_FUNCTION (dummy);
+
+ find_stack_direction (); /* Recurse once. */
+ }
+ else
+ {
+ /* Second entry. */
+ if (ADDRESS_FUNCTION (dummy) > addr)
+ stack_dir = 1; /* Stack grew upward. */
+ else
+ stack_dir = -1; /* Stack grew downward. */
+ }
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/* An "alloca header" is used to:
+ (a) chain together all alloca'ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc
+ alignment chunk size. The following default should work okay. */
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* To force sizeof(header). */
+ struct
+ {
+ union hdr *next; /* For chaining headers. */
+ char *deep; /* For stack depth measure. */
+ } h;
+} header;
+
+static header *last_alloca_header = NULL; /* -> last alloca header. */
+
+/* Return a pointer to at least SIZE bytes of storage,
+ which will be automatically reclaimed upon exit from
+ the procedure that called alloca. Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32. */
+
+pointer
+alloca (size)
+ unsigned size;
+{
+ auto char probe; /* Probes stack depth: */
+ register char *depth = ADDRESS_FUNCTION (probe);
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* Unknown growth direction. */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca'd storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* Traverses linked list. */
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if ((STACK_DIR > 0 && hp->h.deep > depth)
+ || (STACK_DIR < 0 && hp->h.deep < depth))
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* Collect garbage. */
+
+ hp = np; /* -> next header. */
+ }
+ else
+ break; /* Rest are not deeper. */
+
+ last_alloca_header = hp; /* -> last valid storage. */
+ }
+
+ if (size == 0)
+ return NULL; /* No allocation required. */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = malloc (sizeof (header) + size);
+ /* Address of header. */
+
+ ((header *) new)->h.next = last_alloca_header;
+ ((header *) new)->h.deep = depth;
+
+ last_alloca_header = (header *) new;
+
+ /* User storage begins just after header. */
+
+ return (pointer) ((char *) new + sizeof (header));
+ }
+}
+
+#if defined (CRAY) && defined (CRAY_STACKSEG_END)
+
+#ifdef DEBUG_I00AFUNC
+#include <stdio.h>
+#endif
+
+#ifndef CRAY_STACK
+#define CRAY_STACK
+#ifndef CRAY2
+/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
+struct stack_control_header
+ {
+ long shgrow:32; /* Number of times stack has grown. */
+ long shaseg:32; /* Size of increments to stack. */
+ long shhwm:32; /* High water mark of stack. */
+ long shsize:32; /* Current size of stack (all segments). */
+ };
+
+/* The stack segment linkage control information occurs at
+ the high-address end of a stack segment. (The stack
+ grows from low addresses to high addresses.) The initial
+ part of the stack segment linkage control information is
+ 0200 (octal) words. This provides for register storage
+ for the routine which overflows the stack. */
+
+struct stack_segment_linkage
+ {
+ long ss[0200]; /* 0200 overflow words. */
+ long sssize:32; /* Number of words in this segment. */
+ long ssbase:32; /* Offset to stack base. */
+ long:32;
+ long sspseg:32; /* Offset to linkage control of previous
+ segment of stack. */
+ long:32;
+ long sstcpt:32; /* Pointer to task common address block. */
+ long sscsnm; /* Private control structure number for
+ microtasking. */
+ long ssusr1; /* Reserved for user. */
+ long ssusr2; /* Reserved for user. */
+ long sstpid; /* Process ID for pid based multi-tasking. */
+ long ssgvup; /* Pointer to multitasking thread giveup. */
+ long sscray[7]; /* Reserved for Cray Research. */
+ long ssa0;
+ long ssa1;
+ long ssa2;
+ long ssa3;
+ long ssa4;
+ long ssa5;
+ long ssa6;
+ long ssa7;
+ long sss0;
+ long sss1;
+ long sss2;
+ long sss3;
+ long sss4;
+ long sss5;
+ long sss6;
+ long sss7;
+ };
+
+#else /* CRAY2 */
+/* The following structure defines the vector of words
+ returned by the STKSTAT library routine. */
+struct stk_stat
+ {
+ long now; /* Current total stack size. */
+ long maxc; /* Amount of contiguous space which would
+ be required to satisfy the maximum
+ stack demand to date. */
+ long high_water; /* Stack high-water mark. */
+ long overflows; /* Number of stack overflow ($STKOFEN) calls. */
+ long hits; /* Number of internal buffer hits. */
+ long extends; /* Number of block extensions. */
+ long stko_mallocs; /* Block allocations by $STKOFEN. */
+ long underflows; /* Number of stack underflow calls ($STKRETN). */
+ long stko_free; /* Number of deallocations by $STKRETN. */
+ long stkm_free; /* Number of deallocations by $STKMRET. */
+ long segments; /* Current number of stack segments. */
+ long maxs; /* Maximum number of stack segments so far. */
+ long pad_size; /* Stack pad size. */
+ long current_address; /* Current stack segment address. */
+ long current_size; /* Current stack segment size. This
+ number is actually corrupted by STKSTAT to
+ include the fifteen word trailer area. */
+ long initial_address; /* Address of initial segment. */
+ long initial_size; /* Size of initial segment. */
+ };
+
+/* The following structure describes the data structure which trails
+ any stack segment. I think that the description in 'asdef' is
+ out of date. I only describe the parts that I am sure about. */
+
+struct stk_trailer
+ {
+ long this_address; /* Address of this block. */
+ long this_size; /* Size of this block (does not include
+ this trailer). */
+ long unknown2;
+ long unknown3;
+ long link; /* Address of trailer block of previous
+ segment. */
+ long unknown5;
+ long unknown6;
+ long unknown7;
+ long unknown8;
+ long unknown9;
+ long unknown10;
+ long unknown11;
+ long unknown12;
+ long unknown13;
+ long unknown14;
+ };
+
+#endif /* CRAY2 */
+#endif /* not CRAY_STACK */
+
+#ifdef CRAY2
+/* Determine a "stack measure" for an arbitrary ADDRESS.
+ I doubt that "lint" will like this much. */
+
+static long
+i00afunc (long *address)
+{
+ struct stk_stat status;
+ struct stk_trailer *trailer;
+ long *block, size;
+ long result = 0;
+
+ /* We want to iterate through all of the segments. The first
+ step is to get the stack status structure. We could do this
+ more quickly and more directly, perhaps, by referencing the
+ $LM00 common block, but I know that this works. */
+
+ STKSTAT (&status);
+
+ /* Set up the iteration. */
+
+ trailer = (struct stk_trailer *) (status.current_address
+ + status.current_size
+ - 15);
+
+ /* There must be at least one stack segment. Therefore it is
+ a fatal error if "trailer" is null. */
+
+ if (trailer == 0)
+ abort ();
+
+ /* Discard segments that do not contain our argument address. */
+
+ while (trailer != 0)
+ {
+ block = (long *) trailer->this_address;
+ size = trailer->this_size;
+ if (block == 0 || size == 0)
+ abort ();
+ trailer = (struct stk_trailer *) trailer->link;
+ if ((block <= address) && (address < (block + size)))
+ break;
+ }
+
+ /* Set the result to the offset in this segment and add the sizes
+ of all predecessor segments. */
+
+ result = address - block;
+
+ if (trailer == 0)
+ {
+ return result;
+ }
+
+ do
+ {
+ if (trailer->this_size <= 0)
+ abort ();
+ result += trailer->this_size;
+ trailer = (struct stk_trailer *) trailer->link;
+ }
+ while (trailer != 0);
+
+ /* We are done. Note that if you present a bogus address (one
+ not in any segment), you will get a different number back, formed
+ from subtracting the address of the first block. This is probably
+ not what you want. */
+
+ return (result);
+}
+
+#else /* not CRAY2 */
+/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
+ Determine the number of the cell within the stack,
+ given the address of the cell. The purpose of this
+ routine is to linearize, in some sense, stack addresses
+ for alloca. */
+
+static long
+i00afunc (long address)
+{
+ long stkl = 0;
+
+ long size, pseg, this_segment, stack;
+ long result = 0;
+
+ struct stack_segment_linkage *ssptr;
+
+ /* Register B67 contains the address of the end of the
+ current stack segment. If you (as a subprogram) store
+ your registers on the stack and find that you are past
+ the contents of B67, you have overflowed the segment.
+
+ B67 also points to the stack segment linkage control
+ area, which is what we are really interested in. */
+
+ stkl = CRAY_STACKSEG_END ();
+ ssptr = (struct stack_segment_linkage *) stkl;
+
+ /* If one subtracts 'size' from the end of the segment,
+ one has the address of the first word of the segment.
+
+ If this is not the first segment, 'pseg' will be
+ nonzero. */
+
+ pseg = ssptr->sspseg;
+ size = ssptr->sssize;
+
+ this_segment = stkl - size;
+
+ /* It is possible that calling this routine itself caused
+ a stack overflow. Discard stack segments which do not
+ contain the target address. */
+
+ while (!(this_segment <= address && address <= stkl))
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl);
+#endif
+ if (pseg == 0)
+ break;
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ this_segment = stkl - size;
+ }
+
+ result = address - this_segment;
+
+ /* If you subtract pseg from the current end of the stack,
+ you get the address of the previous stack segment's end.
+ This seems a little convoluted to me, but I'll bet you save
+ a cycle somewhere. */
+
+ while (pseg != 0)
+ {
+#ifdef DEBUG_I00AFUNC
+ fprintf (stderr, "%011o %011o\n", pseg, size);
+#endif
+ stkl = stkl - pseg;
+ ssptr = (struct stack_segment_linkage *) stkl;
+ size = ssptr->sssize;
+ pseg = ssptr->sspseg;
+ result += size;
+ }
+ return (result);
+}
+
+#endif /* not CRAY2 */
+#endif /* CRAY */
+
+#endif /* no alloca */
diff --git a/contrib/gdb/libiberty/argv.c b/contrib/gdb/libiberty/argv.c
new file mode 100644
index 0000000..40582ab
--- /dev/null
+++ b/contrib/gdb/libiberty/argv.c
@@ -0,0 +1,328 @@
+/* Create and destroy argument vectors (argv's)
+ Copyright (C) 1992 Free Software Foundation, Inc.
+ Written by Fred Fish @ Cygnus Support
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* Create and destroy argument vectors. An argument vector is simply an
+ array of string pointers, terminated by a NULL pointer. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#define isspace(ch) ((ch) == ' ' || (ch) == '\t')
+
+/* Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+
+#include <stddef.h>
+extern void *memcpy (void *s1, const void *s2, size_t n); /* 4.11.2.1 */
+extern size_t strlen (const char *s); /* 4.11.6.3 */
+extern void *malloc (size_t size); /* 4.10.3.3 */
+extern void *realloc (void *ptr, size_t size); /* 4.10.3.4 */
+extern void free (void *ptr); /* 4.10.3.2 */
+extern char *strdup (const char *s); /* Non-ANSI */
+
+#else /* !__STDC__ */
+
+extern char *memcpy (); /* Copy memory region */
+extern int strlen (); /* Count length of string */
+extern char *malloc (); /* Standard memory allocater */
+extern char *realloc (); /* Standard memory reallocator */
+extern void free (); /* Free malloc'd memory */
+extern char *strdup (); /* Duplicate a string */
+
+#endif /* __STDC__ */
+
+#include "alloca-conf.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef EOS
+#define EOS '\0'
+#endif
+
+#define INITIAL_MAXARGC 8 /* Number of args + NULL in initial argv */
+
+
+/*
+
+NAME
+
+ freeargv -- free an argument vector
+
+SYNOPSIS
+
+ void freeargv (vector)
+ char **vector;
+
+DESCRIPTION
+
+ Free an argument vector that was built using buildargv. Simply scans
+ through the vector, freeing the memory for each argument until the
+ terminating NULL is found, and then frees the vector itself.
+
+RETURNS
+
+ No value.
+
+*/
+
+void freeargv (vector)
+char **vector;
+{
+ register char **scan;
+
+ if (vector != NULL)
+ {
+ for (scan = vector; *scan != NULL; scan++)
+ {
+ free (*scan);
+ }
+ free (vector);
+ }
+}
+
+/*
+
+NAME
+
+ buildargv -- build an argument vector from a string
+
+SYNOPSIS
+
+ char **buildargv (sp)
+ char *sp;
+
+DESCRIPTION
+
+ Given a pointer to a string, parse the string extracting fields
+ separated by whitespace and optionally enclosed within either single
+ or double quotes (which are stripped off), and build a vector of
+ pointers to copies of the string for each field. The input string
+ remains unchanged.
+
+ All of the memory for the pointer array and copies of the string
+ is obtained from malloc. All of the memory can be returned to the
+ system with the single function call freeargv, which takes the
+ returned result of buildargv, as it's argument.
+
+ The memory for the argv array is dynamically expanded as necessary.
+
+RETURNS
+
+ Returns a pointer to the argument vector if successful. Returns NULL
+ if the input string pointer is NULL or if there is insufficient
+ memory to complete building the argument vector.
+
+NOTES
+
+ In order to provide a working buffer for extracting arguments into,
+ with appropriate stripping of quotes and translation of backslash
+ sequences, we allocate a working buffer at least as long as the input
+ string. This ensures that we always have enough space in which to
+ work, since the extracted arg is never larger than the input string.
+
+ If the input is a null string (as opposed to a NULL pointer), then
+ buildarg returns an argv that has one arg, a null string.
+
+ Argv is always kept terminated with a NULL arg pointer, so it can
+ be passed to freeargv at any time, or returned, as appropriate.
+*/
+
+char **buildargv (input)
+char *input;
+{
+ char *arg;
+ char *copybuf;
+ int squote = 0;
+ int dquote = 0;
+ int bsquote = 0;
+ int argc = 0;
+ int maxargc = 0;
+ char **argv = NULL;
+ char **nargv;
+
+ if (input != NULL)
+ {
+ copybuf = alloca (strlen (input) + 1);
+ /* Is a do{}while to always execute the loop once. Always return an
+ argv, even for null strings. See NOTES above, test case below. */
+ do
+ {
+ /* Pick off argv[argc] */
+ while (isspace (*input))
+ {
+ input++;
+ }
+ if ((maxargc == 0) || (argc >= (maxargc - 1)))
+ {
+ /* argv needs initialization, or expansion */
+ if (argv == NULL)
+ {
+ maxargc = INITIAL_MAXARGC;
+ nargv = (char **) malloc (maxargc * sizeof (char *));
+ }
+ else
+ {
+ maxargc *= 2;
+ nargv = (char **) realloc (argv, maxargc * sizeof (char *));
+ }
+ if (nargv == NULL)
+ {
+ if (argv != NULL)
+ {
+ freeargv (argv);
+ argv = NULL;
+ }
+ break;
+ }
+ argv = nargv;
+ argv[argc] = NULL;
+ }
+ /* Begin scanning arg */
+ arg = copybuf;
+ while (*input != EOS)
+ {
+ if (isspace (*input) && !squote && !dquote && !bsquote)
+ {
+ break;
+ }
+ else
+ {
+ if (bsquote)
+ {
+ bsquote = 0;
+ *arg++ = *input;
+ }
+ else if (*input == '\\')
+ {
+ bsquote = 1;
+ }
+ else if (squote)
+ {
+ if (*input == '\'')
+ {
+ squote = 0;
+ }
+ else
+ {
+ *arg++ = *input;
+ }
+ }
+ else if (dquote)
+ {
+ if (*input == '"')
+ {
+ dquote = 0;
+ }
+ else
+ {
+ *arg++ = *input;
+ }
+ }
+ else
+ {
+ if (*input == '\'')
+ {
+ squote = 1;
+ }
+ else if (*input == '"')
+ {
+ dquote = 1;
+ }
+ else
+ {
+ *arg++ = *input;
+ }
+ }
+ input++;
+ }
+ }
+ *arg = EOS;
+ argv[argc] = strdup (copybuf);
+ if (argv[argc] == NULL)
+ {
+ freeargv (argv);
+ argv = NULL;
+ break;
+ }
+ argc++;
+ argv[argc] = NULL;
+
+ while (isspace (*input))
+ {
+ input++;
+ }
+ }
+ while (*input != EOS);
+ }
+ return (argv);
+}
+
+#ifdef MAIN
+
+/* Simple little test driver. */
+
+static char *tests[] =
+{
+ "a simple command line",
+ "arg 'foo' is single quoted",
+ "arg \"bar\" is double quoted",
+ "arg \"foo bar\" has embedded whitespace",
+ "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
+};
+
+main ()
+{
+ char **argv;
+ char **test;
+ char **targs;
+
+ for (test = tests; *test != NULL; test++)
+ {
+ printf ("buildargv(\"%s\")\n", *test);
+ if ((argv = buildargv (*test)) == NULL)
+ {
+ printf ("failed!\n\n");
+ }
+ else
+ {
+ for (targs = argv; *targs != NULL; targs++)
+ {
+ printf ("\t\"%s\"\n", *targs);
+ }
+ printf ("\n");
+ }
+ freeargv (argv);
+ }
+
+}
+
+#endif /* MAIN */
diff --git a/contrib/gdb/libiberty/atexit.c b/contrib/gdb/libiberty/atexit.c
new file mode 100644
index 0000000..4463cb6
--- /dev/null
+++ b/contrib/gdb/libiberty/atexit.c
@@ -0,0 +1,14 @@
+/* Wrapper to implement ANSI C's atexit using SunOS's on_exit. */
+/* This function is in the public domain. --Mike Stump. */
+
+#ifndef NEED_on_exit
+int
+atexit(f)
+ void (*f)();
+{
+ /* If the system doesn't provide a definition for atexit, use on_exit
+ if the system provides that. */
+ on_exit (f, 0);
+ return 0;
+}
+#endif
diff --git a/contrib/gdb/libiberty/basename.c b/contrib/gdb/libiberty/basename.c
new file mode 100644
index 0000000..689b0c2
--- /dev/null
+++ b/contrib/gdb/libiberty/basename.c
@@ -0,0 +1,43 @@
+/* Return the basename of a pathname.
+ This file is in the public domain. */
+
+/*
+NAME
+ basename -- return pointer to last component of a pathname
+
+SYNOPSIS
+ char *basename (const char *name)
+
+DESCRIPTION
+ Given a pointer to a string containing a typical pathname
+ (/usr/src/cmd/ls/ls.c for example), returns a pointer to the
+ last component of the pathname ("ls.c" in this case).
+
+BUGS
+ Presumes a UNIX style path with UNIX style separators.
+*/
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include "config.h"
+
+#ifdef NEED_basename
+
+char *
+basename (name)
+ const char *name;
+{
+ const char *base = name;
+
+ while (*name)
+ {
+ if (*name++ == '/')
+ {
+ base = name;
+ }
+ }
+ return (char *) base;
+}
+
+#endif
diff --git a/contrib/gdb/libiberty/bcmp.c b/contrib/gdb/libiberty/bcmp.c
new file mode 100644
index 0000000..11e4417
--- /dev/null
+++ b/contrib/gdb/libiberty/bcmp.c
@@ -0,0 +1,49 @@
+/* bcmp
+ This function is in the public domain. */
+
+/*
+
+NAME
+
+ bcmp -- compare two memory regions
+
+SYNOPSIS
+
+ int bcmp (char *from, char *to, int count)
+
+DESCRIPTION
+
+ Compare two memory regions and return zero if they are identical,
+ non-zero otherwise. If count is zero, return zero.
+
+NOTES
+
+ No guarantee is made about the non-zero returned value. In
+ particular, the results may be signficantly different than
+ strcmp(), where the return value is guaranteed to be less than,
+ equal to, or greater than zero, according to lexicographical
+ sorting of the compared regions.
+
+BUGS
+
+*/
+
+
+int
+bcmp (from, to, count)
+ char *from, *to;
+ int count;
+{
+ int rtnval = 0;
+
+ while (count-- > 0)
+ {
+ if (*from++ != *to++)
+ {
+ rtnval = 1;
+ break;
+ }
+ }
+ return (rtnval);
+}
+
diff --git a/contrib/gdb/libiberty/bcopy.c b/contrib/gdb/libiberty/bcopy.c
new file mode 100644
index 0000000..b655363
--- /dev/null
+++ b/contrib/gdb/libiberty/bcopy.c
@@ -0,0 +1,35 @@
+/* bcopy -- copy memory regions of arbitary length
+
+NAME
+ bcopy -- copy memory regions of arbitrary length
+
+SYNOPSIS
+ void bcopy (char *in, char *out, int length)
+
+DESCRIPTION
+ Copy LENGTH bytes from memory region pointed to by IN to memory
+ region pointed to by OUT.
+
+BUGS
+ Significant speed improvements can be made in some cases by
+ implementing copies of multiple bytes simultaneously, or unrolling
+ the copy loop.
+
+*/
+
+void
+bcopy (src, dest, len)
+ register char *src, *dest;
+ int len;
+{
+ if (dest < src)
+ while (len--)
+ *dest++ = *src++;
+ else
+ {
+ char *lasts = src + (len-1);
+ char *lastd = dest + (len-1);
+ while (len--)
+ *(char *)lastd-- = *(char *)lasts--;
+ }
+}
diff --git a/contrib/gdb/libiberty/bzero.c b/contrib/gdb/libiberty/bzero.c
new file mode 100644
index 0000000..d01644b7
--- /dev/null
+++ b/contrib/gdb/libiberty/bzero.c
@@ -0,0 +1,31 @@
+/* Portable version of bzero for systems without it.
+ This function is in the public domain. */
+
+/*
+NAME
+ bzero -- zero the contents of a specified memory region
+
+SYNOPSIS
+ void bzero (char *to, int count)
+
+DESCRIPTION
+ Zero COUNT bytes of memory pointed to by TO.
+
+BUGS
+ Significant speed enhancements may be made in some environments
+ by zeroing more than a single byte at a time, or by unrolling the
+ loop.
+
+*/
+
+
+void
+bzero (to, count)
+ char *to;
+ int count;
+{
+ while (count-- > 0)
+ {
+ *to++ = 0;
+ }
+}
diff --git a/contrib/gdb/libiberty/clock.c b/contrib/gdb/libiberty/clock.c
new file mode 100644
index 0000000..b60de16
--- /dev/null
+++ b/contrib/gdb/libiberty/clock.c
@@ -0,0 +1,73 @@
+/* ANSI-compatible clock function.
+ Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of the libiberty library. This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#ifdef HAVE_GETRUSAGE
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_TIMES
+#ifndef NO_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/times.h>
+#endif
+
+/* FIXME: should be able to declare as clock_t. */
+
+long
+clock ()
+{
+#ifdef HAVE_GETRUSAGE
+ struct rusage rusage;
+
+ getrusage (0, &rusage);
+ return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
+ + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
+#else
+#ifdef HAVE_TIMES
+ struct tms tms;
+
+ times (&tms);
+ return (tms.tms_utime + tms.tms_stime) * (1000000 / HZ);
+#else
+#ifdef VMS
+ struct
+ {
+ int proc_user_time;
+ int proc_system_time;
+ int child_user_time;
+ int child_system_time;
+ } vms_times;
+
+ times (&vms_times);
+ return (vms_times.proc_user_time + vms_times.proc_system_time) * 10000;
+#else
+ /* A fallback, if nothing else available. */
+ return 0;
+#endif /* VMS */
+#endif /* HAVE_TIMES */
+#endif /* HAVE_GETRUSAGE */
+}
+
diff --git a/contrib/gdb/libiberty/concat.c b/contrib/gdb/libiberty/concat.c
new file mode 100644
index 0000000..5b132c8
--- /dev/null
+++ b/contrib/gdb/libiberty/concat.c
@@ -0,0 +1,167 @@
+/* Concatenate variable number of strings.
+ Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+ Written by Fred Fish @ Cygnus Support
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/*
+
+NAME
+
+ concat -- concatenate a variable number of strings
+
+SYNOPSIS
+
+ #include <varargs.h>
+
+ char *concat (s1, s2, s3, ..., NULL)
+
+DESCRIPTION
+
+ Concatenate a variable number of strings and return the result
+ in freshly malloc'd memory.
+
+ Returns NULL if insufficient memory is available. The argument
+ list is terminated by the first NULL pointer encountered. Pointers
+ to empty strings are ignored.
+
+NOTES
+
+ This function uses xmalloc() which is expected to be a front end
+ function to malloc() that deals with low memory situations. In
+ typical use, if malloc() returns NULL then xmalloc() diverts to an
+ error handler routine which never returns, and thus xmalloc will
+ never return a NULL pointer. If the client application wishes to
+ deal with low memory situations itself, it should supply an xmalloc
+ that just directly invokes malloc and blindly returns whatever
+ malloc returns.
+*/
+
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#ifdef ANSI_PROTOTYPES
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef __STDC__
+#include <stddef.h>
+extern size_t strlen (const char *s);
+#else
+extern int strlen ();
+#endif
+
+#define NULLP (char *)0
+
+/* VARARGS */
+#ifdef ANSI_PROTOTYPES
+char *
+concat (const char *first, ...)
+#else
+char *
+concat (va_alist)
+ va_dcl
+#endif
+{
+ register int length;
+ register char *newstr;
+ register char *end;
+ 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);
+ first = va_arg (args, const char *);
+#endif
+
+ if (first == NULLP)
+ length = 0;
+ else
+ {
+ length = strlen (first);
+ while ((arg = va_arg (args, const char *)) != NULLP)
+ {
+ length += strlen (arg);
+ }
+ }
+ newstr = (char *) xmalloc (length + 1);
+ va_end (args);
+
+ /* Now copy the individual pieces to the result string. */
+
+ if (newstr != NULLP)
+ {
+#ifdef ANSI_PROTOTYPES
+ va_start (args, first);
+#else
+ va_start (args);
+ first = va_arg (args, const char *);
+#endif
+ end = newstr;
+ 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);
+ }
+
+ return (newstr);
+}
+
+#ifdef MAIN
+
+/* Simple little test driver. */
+
+#include <stdio.h>
+
+int
+main ()
+{
+ printf ("\"\" = \"%s\"\n", concat (NULLP));
+ printf ("\"a\" = \"%s\"\n", concat ("a", NULLP));
+ printf ("\"ab\" = \"%s\"\n", concat ("a", "b", NULLP));
+ printf ("\"abc\" = \"%s\"\n", concat ("a", "b", "c", NULLP));
+ 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/contrib/gdb/libiberty/config.table b/contrib/gdb/libiberty/config.table
new file mode 100644
index 0000000..1b67dd5
--- /dev/null
+++ b/contrib/gdb/libiberty/config.table
@@ -0,0 +1,63 @@
+case "${host}" in
+ rs6000-ibm-aix3.1 | rs6000-ibm-aix)
+ frag=mh-aix
+ files=${xsrcdir}alloca-botch.h ;;
+ *-ibm-aix*) files=${xsrcdir}alloca-botch.h ;;
+ arm-*-riscix*) frag=mh-riscix ;;
+ m68k-apollo-bsd*) frag=mh-a68bsd ;;
+ m68k-apollo-sysv*) frag=mh-apollo68 ;;
+ i[345]86-ncr-sysv4*) frag=mh-ncr3000 ;;
+ *-*-cxux7*) frag=mh-cxux7 ;;
+ *-*-lynxos*) frag=mh-lynxos ;;
+ *-*-dgux*) frag=mh-sysv ;;
+ hppa*-hp-bsd*) frag=mh-hpbsd ;;
+ *-*-hpux*) frag=mh-hpux ;;
+ *-*-hiux*) frag=mh-hpux ;;
+ *-*-irix4*) frag=mh-irix4 ;;
+ *-*-irix*) frag=mh-sysv ;;
+ *-*-m88kbcs*) frag=mh-sysv ;;
+ *-*-solaris2*) frag=mh-sysv4 ;;
+ *-*-sysv4*) frag=mh-sysv4 ;;
+ *-*-sysv*) frag=mh-sysv ;;
+ *-*-go32) frag=mh-go32 ;;
+
+ *-*-vxworks5*)
+ # VxWorks 5 needs special action, because the usual
+ # autoconfiguration scheme does not work.
+ frag=mt-vxworks5
+ ;;
+esac
+
+# Try to handle funky case of solaris 2 -> sun 4.
+case "${host}" in
+ sparc-sun-sunos4.1.3)
+ if [ "${with_cross_host}" != "${host}" ] ; then
+ frag=mt-sunos4
+ fi
+ ;;
+esac
+
+frags=$frag
+
+# If they didn't specify --enable-shared, don't generate shared libs.
+if [ "${enable_shared}" = "yes" ]; then
+ case "${host}" in
+ hppa*-*-*) frags="${frags} ../../config/mh-papic" ;;
+ i[345]86-*-*) frags="${frags} ../../config/mh-x86pic" ;;
+ *-*-*) frags="${frags} ../../config/mh-${host_cpu}pic" ;;
+ esac
+fi
+
+echo "# Warning: this fragment is automatically generated" > temp-frag
+
+for frag in ${frags}; do
+ frag=${srcdir}/${xsrcdir}config/$frag
+ if [ -f ${frag} ]; then
+ echo "Appending ${frag} to xhost-mkfrag"
+ echo "# Following fragment copied from ${frag}" >> temp-frag
+ cat ${frag} >> temp-frag
+ fi
+done
+
+frag=xhost-mkfrag
+${moveifchange} temp-frag xhost-mkfrag
diff --git a/contrib/gdb/libiberty/config/mh-a68bsd b/contrib/gdb/libiberty/config/mh-a68bsd
new file mode 100644
index 0000000..3c5a237
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-a68bsd
@@ -0,0 +1,2 @@
+RANLIB=ranlib
+CC= cc -A ansi -A runtype,any -A systype,any -U__STDC__
diff --git a/contrib/gdb/libiberty/config/mh-aix b/contrib/gdb/libiberty/config/mh-aix
new file mode 100644
index 0000000..c7b848d
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-aix
@@ -0,0 +1,10 @@
+HDEFINES = -D__IEEE_BIG_ENDIAN
+RANLIB=true
+INSTALL=cp
+
+# Most releases of AIX 3.1 include an incorrect internal version of copysign
+# in libc.a for use by some libc public functions including modf. The public
+# version of copysign in libm.a is usable. For the sake of libg++ (which
+# uses modf), we add copysign here. Supposedly, this problem is fixed in AIX
+# 3.1.8 and above, including all releases of AIX 3.2.
+EXTRA_OFILES = copysign.o
diff --git a/contrib/gdb/libiberty/config/mh-apollo68 b/contrib/gdb/libiberty/config/mh-apollo68
new file mode 100644
index 0000000..651770c
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-apollo68
@@ -0,0 +1,2 @@
+RANLIB=true
+CC= cc -A ansi -A runtype,any -A systype,any -U__STDC__
diff --git a/contrib/gdb/libiberty/config/mh-cxux7 b/contrib/gdb/libiberty/config/mh-cxux7
new file mode 100644
index 0000000..6d4d30b
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-cxux7
@@ -0,0 +1,3 @@
+HDEFINES = -DHAVE_SYSCONF -DHARRIS_FLOAT_FORMAT
+RANLIB=true
+INSTALL = cp
diff --git a/contrib/gdb/libiberty/config/mh-go32 b/contrib/gdb/libiberty/config/mh-go32
new file mode 100644
index 0000000..7c9fe4f
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-go32
@@ -0,0 +1,4 @@
+HDEFINES=-DHAVE_GETRUSAGE
+CC=i386-go32-gcc -O2 -fno-omit-frame-pointer
+AR=i386-go32-ar
+RANLIB=i386-go32-ranlib
diff --git a/contrib/gdb/libiberty/config/mh-hpbsd b/contrib/gdb/libiberty/config/mh-hpbsd
new file mode 100644
index 0000000..ce11dcd
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-hpbsd
@@ -0,0 +1,2 @@
+# HPPA hosts using BSD
+RANLIB=true
diff --git a/contrib/gdb/libiberty/config/mh-irix4 b/contrib/gdb/libiberty/config/mh-irix4
new file mode 100644
index 0000000..ace7678
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-irix4
@@ -0,0 +1,4 @@
+CC = cc -cckr
+RANLIB = true
+INSTALL = cp
+EXTRA_OFILES = alloca.o
diff --git a/contrib/gdb/libiberty/config/mh-lynxos b/contrib/gdb/libiberty/config/mh-lynxos
new file mode 100644
index 0000000..2f22110
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-lynxos
@@ -0,0 +1 @@
+HDEFINES = -DLOSING_SYS_SIGLIST
diff --git a/contrib/gdb/libiberty/config/mh-ncr3000 b/contrib/gdb/libiberty/config/mh-ncr3000
new file mode 100644
index 0000000..3a45c22
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-ncr3000
@@ -0,0 +1,19 @@
+# Host configuration file for an NCR 3000 (i486/SVR4) system.
+
+# The NCR 3000 ships with a MetaWare compiler installed as /bin/cc.
+# This compiler not only emits obnoxious copyright messages every time
+# you run it, but it chokes and dies on a whole bunch of GNU source
+# files. Default to using the AT&T compiler installed in /usr/ccs/ATT/cc.
+# Unfortunately though, the AT&T compiler sometimes generates code that
+# the assembler barfs on if -g is used, so disable it by default as well.
+CC = /usr/ccs/ATT/cc
+CFLAGS =
+
+RANLIB = true
+
+# The /usr/ucb/install program is incompatible (complains about unknown
+# group staff). Use good old cp...
+INSTALL = cp
+
+# The l flag generates a warning from the SVR4 archiver, remove it.
+AR_FLAGS = cq
diff --git a/contrib/gdb/libiberty/config/mh-riscix b/contrib/gdb/libiberty/config/mh-riscix
new file mode 100644
index 0000000..0209279
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-riscix
@@ -0,0 +1,6 @@
+# The native linker only reports the first undefined symbol if linking with a
+# shared library. So build using gcc and link statically (this requires
+# gcc 2.6.0 or above).
+
+ERRORS_CC = gcc
+ERRORS_LDFLAGS = -static
diff --git a/contrib/gdb/libiberty/config/mh-sysv b/contrib/gdb/libiberty/config/mh-sysv
new file mode 100644
index 0000000..eb102d5
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-sysv
@@ -0,0 +1 @@
+RANLIB=true
diff --git a/contrib/gdb/libiberty/config/mh-sysv4 b/contrib/gdb/libiberty/config/mh-sysv4
new file mode 100644
index 0000000..4d1aa3c
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mh-sysv4
@@ -0,0 +1,3 @@
+HDEFINES = -DHAVE_SYSCONF
+RANLIB=true
+INSTALL = cp
diff --git a/contrib/gdb/libiberty/config/mt-sunos4 b/contrib/gdb/libiberty/config/mt-sunos4
new file mode 100644
index 0000000..c25baa6
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mt-sunos4
@@ -0,0 +1,2 @@
+XTRAFLAGS = -isystem /s1/cygnus/dejagnu/sparc-sun-sunos4.1.3/include/
+LOADLIBES = -L/s1/cygnus/dejagnu/sparc-sun-sunos4.1.3/lib
diff --git a/contrib/gdb/libiberty/config/mt-vxworks5 b/contrib/gdb/libiberty/config/mt-vxworks5
new file mode 100644
index 0000000..f1a46d3
--- /dev/null
+++ b/contrib/gdb/libiberty/config/mt-vxworks5
@@ -0,0 +1,27 @@
+# VxWorks 5.x target Makefile fragment.
+# The autoconfiguration fails for a VxWorks target, because the
+# libraries are actually on the target board, not in the file system.
+# Therefore, we compute the dependencies by hand.
+
+HDEFINES = -DNO_SYS_PARAM_H
+CONFIG_H = vxconfig.h
+NEEDED_LIST = vxneeded-list
+
+vxconfig.h: Makefile
+ if [ -f ../newlib/Makefile ]; then \
+ $(MAKE) $(FLAGS_TO_PASS) xconfig.h; \
+ cp xconfig.h vxconfig.h; \
+ else \
+ echo "#define NEED_sys_nerr 1" >vxconfig.h; \
+ echo "#define NEED_sys_errlist 1" >>vxconfig.h; \
+ echo "#define NEED_sys_siglist 1" >>vxconfig.h; \
+ echo "#define NEED_psignal 1" >>vxconfig.h; \
+ fi
+
+vxneeded-list: Makefile
+ if [ -f ../newlib/Makefile ]; then \
+ $(MAKE) $(FLAGS_TO_PASS) xneeded-list; \
+ cp xneeded-list vxneeded-list; \
+ else \
+ echo getopt.o getpagesize.o insque.o random.o strcasecmp.o strncasecmp.o strdup.o vfork.o sigsetmask.o waitpid.o >vxneeded-list; \
+ fi
diff --git a/contrib/gdb/libiberty/configure.bat b/contrib/gdb/libiberty/configure.bat
new file mode 100644
index 0000000..ed33777
--- /dev/null
+++ b/contrib/gdb/libiberty/configure.bat
@@ -0,0 +1,15 @@
+@echo off
+if "%1" == "h8/300" goto h8300
+
+echo Configuring libiberty for go32
+copy Makefile.dos Makefile
+echo #define NEED_sys_siglist 1 >> config.h
+echo #define NEED_psignal 1 >> config.h
+update alloca-normal.h alloca-conf.h
+goto exit
+
+:h8300
+echo Configuring libiberty for H8/300
+copy Makefile.dos Makefile
+
+:exit
diff --git a/contrib/gdb/libiberty/configure.in b/contrib/gdb/libiberty/configure.in
new file mode 100644
index 0000000..84e4eac
--- /dev/null
+++ b/contrib/gdb/libiberty/configure.in
@@ -0,0 +1,77 @@
+# This file is a shell script fragment that supplies the information
+# necessary for a configure script to process the program in
+# this directory. For more information, look at ../configure.
+
+configdirs=
+srctrigger=getopt1.c
+srcname="-liberty library"
+
+# per-host:
+
+files="alloca-norm.h"
+links="alloca-conf.h"
+
+. ${srcdir}/config.table
+host_makefile_frag=${frag}
+
+# per-target:
+
+# post-target:
+
+# If this is the target libiberty, check at compile time whether we are using
+# newlib. If we are, we already know the files we need, since the linker
+# will fail when run on some of the newlib targets.
+if [ -n "${with_target_subdir}" ] ; then
+ cat > Makefile.tem <<'!EOF!'
+CONFIG_H = xconfig.h
+NEEDED_LIST = xneeded-list
+
+xconfig.h: Makefile
+ if [ -f ../newlib/Makefile ]; then \
+ echo "#define NEED_sys_nerr 1" >xconfig.h; \
+ echo "#define NEED_sys_errlist 1" >>xconfig.h; \
+ echo "#define NEED_sys_siglist 1" >>xconfig.h; \
+ echo "#define NEED_psignal 1" >>xconfig.h; \
+ else \
+ $(MAKE) $(FLAGS_TO_PASS) lconfig.h; \
+ cp lconfig.h xconfig.h; \
+ fi
+
+xneeded-list: Makefile
+ if [ -f ../newlib/Makefile ]; then \
+ echo insque.o random.o strdup.o alloca.o >xneeded-list; \
+ else \
+ $(MAKE) $(FLAGS_TO_PASS) lneeded-list; \
+ cp lneeded-list xneeded-list; \
+ fi
+!EOF!
+sed -e "/^####/ r Makefile.tem" \
+ -e '/INSTALL_DEST =/s/libdir/tooldir/' ${Makefile} > Makefile.tem3
+mv Makefile.tem3 ${Makefile}
+rm -f Makefile.tem
+fi
+
+# We need multilib support, but only if configuring for the target.
+if [ -n "${with_target_subdir}" ] ; then
+ case ${srcdir} in
+ .)
+ if [ "${with_target_subdir}" != "." ] ; then
+
+ # Set MULTISRCTOP to the value we need if we are not doing
+ # multilib. This will be overridden if --enable-multilib was
+ # used.
+ sed -e "s:^MULTISRCTOP[ ]*=.*$:MULTISRCTOP = ../:" \
+ ${Makefile} > Makefile.tem
+ rm -f ${Makefile}
+ mv Makefile.tem ${Makefile}
+
+ . ${srcdir}/${with_multisrctop}../../config-ml.in
+ else
+ . ${srcdir}/${with_multisrctop}../config-ml.in
+ fi
+ ;;
+ *)
+ . ${srcdir}/../config-ml.in
+ ;;
+ esac
+fi
diff --git a/contrib/gdb/libiberty/copysign.c b/contrib/gdb/libiberty/copysign.c
new file mode 100644
index 0000000..0b5f8c3
--- /dev/null
+++ b/contrib/gdb/libiberty/copysign.c
@@ -0,0 +1,140 @@
+#include <ansidecl.h>
+
+#ifdef __IEEE_BIG_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+ unsigned int sign : 1;
+ unsigned int exponent: 11;
+ unsigned int fraction0:4;
+ unsigned int fraction1:16;
+ unsigned int fraction2:16;
+ unsigned int fraction3:16;
+
+ } number;
+ struct
+ {
+ unsigned int sign : 1;
+ unsigned int exponent: 11;
+ unsigned int quiet:1;
+ unsigned int function0:3;
+ unsigned int function1:16;
+ unsigned int function2:16;
+ unsigned int function3:16;
+ } nan;
+ struct
+ {
+ unsigned long msw;
+ unsigned long lsw;
+ } parts;
+ long aslong[2];
+} __ieee_double_shape_type;
+
+#endif
+
+#ifdef __IEEE_LITTLE_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+#ifdef __SMALL_BITFIELDS
+ unsigned int fraction3:16;
+ unsigned int fraction2:16;
+ unsigned int fraction1:16;
+ unsigned int fraction0: 4;
+#else
+ unsigned int fraction1:32;
+ unsigned int fraction0:20;
+#endif
+ unsigned int exponent :11;
+ unsigned int sign : 1;
+ } number;
+ struct
+ {
+#ifdef __SMALL_BITFIELDS
+ unsigned int function3:16;
+ unsigned int function2:16;
+ unsigned int function1:16;
+ unsigned int function0:3;
+#else
+ unsigned int function1:32;
+ unsigned int function0:19;
+#endif
+ unsigned int quiet:1;
+ unsigned int exponent: 11;
+ unsigned int sign : 1;
+ } nan;
+ struct
+ {
+ unsigned long lsw;
+ unsigned long msw;
+ } parts;
+
+ long aslong[2];
+
+} __ieee_double_shape_type;
+
+#endif
+
+#ifdef __IEEE_BIG_ENDIAN
+typedef union
+{
+ float value;
+ struct
+ {
+ unsigned int sign : 1;
+ unsigned int exponent: 8;
+ unsigned int fraction0: 7;
+ unsigned int fraction1: 16;
+ } number;
+ struct
+ {
+ unsigned int sign:1;
+ unsigned int exponent:8;
+ unsigned int quiet:1;
+ unsigned int function0:6;
+ unsigned int function1:16;
+ } nan;
+ long p1;
+
+} __ieee_float_shape_type;
+#endif
+
+#ifdef __IEEE_LITTLE_ENDIAN
+typedef union
+{
+ float value;
+ struct
+ {
+ unsigned int fraction0: 7;
+ unsigned int fraction1: 16;
+ unsigned int exponent: 8;
+ unsigned int sign : 1;
+ } number;
+ struct
+ {
+ unsigned int function1:16;
+ unsigned int function0:6;
+ unsigned int quiet:1;
+ unsigned int exponent:8;
+ unsigned int sign:1;
+ } nan;
+ long p1;
+
+} __ieee_float_shape_type;
+#endif
+
+
+double DEFUN(copysign, (x, y), double x AND double y)
+{
+ __ieee_double_shape_type a,b;
+ b.value = y;
+ a.value = x;
+ a.number.sign =b.number.sign;
+ return a.value;
+}
diff --git a/contrib/gdb/libiberty/cplus-dem.c b/contrib/gdb/libiberty/cplus-dem.c
new file mode 100644
index 0000000..a7f8680
--- /dev/null
+++ b/contrib/gdb/libiberty/cplus-dem.c
@@ -0,0 +1,3019 @@
+/* Demangler for GNU C++
+ Copyright 1989, 1991, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.uucp)
+ Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This file exports two functions; cplus_mangle_opname and cplus_demangle.
+
+ This file imports xmalloc and xrealloc, which are like malloc and
+ realloc except that they generate a fatal error if there is no
+ available memory. */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <demangle.h>
+#undef CURRENT_DEMANGLING_STYLE
+#define CURRENT_DEMANGLING_STYLE work->options
+
+extern char *xmalloc PARAMS((unsigned));
+extern char *xrealloc PARAMS((char *, unsigned));
+
+char *
+mystrstr (s1, s2)
+ char *s1, *s2;
+{
+ register char *p = s1;
+ register int len = strlen (s2);
+
+ for (; (p = strchr (p, *s2)) != 0; p++)
+ {
+ if (strncmp (p, s2, len) == 0)
+ {
+ return (p);
+ }
+ }
+ return (0);
+}
+
+/* In order to allow a single demangler executable to demangle strings
+ using various common values of CPLUS_MARKER, as well as any specific
+ one set at compile time, we maintain a string containing all the
+ commonly used ones, and check to see if the marker we are looking for
+ is in that string. CPLUS_MARKER is usually '$' on systems where the
+ assembler can deal with that. Where the assembler can't, it's usually
+ '.' (but on many systems '.' is used for other things). We put the
+ current defined CPLUS_MARKER first (which defaults to '$'), followed
+ by the next most common value, followed by an explicit '$' in case
+ the value of CPLUS_MARKER is not '$'.
+
+ We could avoid this if we could just get g++ to tell us what the actual
+ cplus marker character is as part of the debug information, perhaps by
+ ensuring that it is the character that terminates the gcc<n>_compiled
+ marker symbol (FIXME). */
+
+#if !defined (CPLUS_MARKER)
+#define CPLUS_MARKER '$'
+#endif
+
+enum demangling_styles current_demangling_style = gnu_demangling;
+
+static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' };
+
+void
+set_cplus_marker_for_demangling (ch)
+ int ch;
+{
+ cplus_markers[0] = ch;
+}
+
+/* Stuff that is shared between sub-routines.
+ * Using a shared structure allows cplus_demangle to be reentrant. */
+
+struct work_stuff
+{
+ int options;
+ char **typevec;
+ int ntypes;
+ int typevec_size;
+ int constructor;
+ int destructor;
+ int static_type; /* A static member function */
+ int const_type; /* A const member function */
+};
+
+#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
+#define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS)
+
+static const struct optable
+{
+ const char *in;
+ const char *out;
+ int flags;
+} optable[] = {
+ {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */
+ {"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 */
+ {"ge", ">=", DMGL_ANSI}, /* old, ansi */
+ {"gt", ">", DMGL_ANSI}, /* old, ansi */
+ {"le", "<=", DMGL_ANSI}, /* old, ansi */
+ {"lt", "<", DMGL_ANSI}, /* old, ansi */
+ {"plus", "+", 0}, /* old */
+ {"pl", "+", DMGL_ANSI}, /* ansi */
+ {"apl", "+=", DMGL_ANSI}, /* ansi */
+ {"minus", "-", 0}, /* old */
+ {"mi", "-", DMGL_ANSI}, /* ansi */
+ {"ami", "-=", DMGL_ANSI}, /* ansi */
+ {"mult", "*", 0}, /* old */
+ {"ml", "*", DMGL_ANSI}, /* ansi */
+ {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */
+ {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */
+ {"convert", "+", 0}, /* old (unary +) */
+ {"negate", "-", 0}, /* old (unary -) */
+ {"trunc_mod", "%", 0}, /* old */
+ {"md", "%", DMGL_ANSI}, /* ansi */
+ {"amd", "%=", DMGL_ANSI}, /* ansi */
+ {"trunc_div", "/", 0}, /* old */
+ {"dv", "/", DMGL_ANSI}, /* ansi */
+ {"adv", "/=", DMGL_ANSI}, /* ansi */
+ {"truth_andif", "&&", 0}, /* old */
+ {"aa", "&&", DMGL_ANSI}, /* ansi */
+ {"truth_orif", "||", 0}, /* old */
+ {"oo", "||", DMGL_ANSI}, /* ansi */
+ {"truth_not", "!", 0}, /* old */
+ {"nt", "!", DMGL_ANSI}, /* ansi */
+ {"postincrement","++", 0}, /* old */
+ {"pp", "++", DMGL_ANSI}, /* ansi */
+ {"postdecrement","--", 0}, /* old */
+ {"mm", "--", DMGL_ANSI}, /* ansi */
+ {"bit_ior", "|", 0}, /* old */
+ {"or", "|", DMGL_ANSI}, /* ansi */
+ {"aor", "|=", DMGL_ANSI}, /* ansi */
+ {"bit_xor", "^", 0}, /* old */
+ {"er", "^", DMGL_ANSI}, /* ansi */
+ {"aer", "^=", DMGL_ANSI}, /* ansi */
+ {"bit_and", "&", 0}, /* old */
+ {"ad", "&", DMGL_ANSI}, /* ansi */
+ {"aad", "&=", DMGL_ANSI}, /* ansi */
+ {"bit_not", "~", 0}, /* old */
+ {"co", "~", DMGL_ANSI}, /* ansi */
+ {"call", "()", 0}, /* old */
+ {"cl", "()", DMGL_ANSI}, /* ansi */
+ {"alshift", "<<", 0}, /* old */
+ {"ls", "<<", DMGL_ANSI}, /* ansi */
+ {"als", "<<=", DMGL_ANSI}, /* ansi */
+ {"arshift", ">>", 0}, /* old */
+ {"rs", ">>", DMGL_ANSI}, /* ansi */
+ {"ars", ">>=", DMGL_ANSI}, /* ansi */
+ {"component", "->", 0}, /* old */
+ {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */
+ {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */
+ {"indirect", "*", 0}, /* old */
+ {"method_call", "->()", 0}, /* old */
+ {"addr", "&", 0}, /* old (unary &) */
+ {"array", "[]", 0}, /* old */
+ {"vc", "[]", DMGL_ANSI}, /* ansi */
+ {"compound", ", ", 0}, /* old */
+ {"cm", ", ", DMGL_ANSI}, /* ansi */
+ {"cond", "?:", 0}, /* old */
+ {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */
+ {"max", ">?", 0}, /* old */
+ {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */
+ {"min", "<?", 0}, /* old */
+ {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */
+ {"nop", "", 0}, /* old (for operator=) */
+ {"rm", "->*", DMGL_ANSI} /* ansi */
+};
+
+
+typedef struct string /* Beware: these aren't required to be */
+{ /* '\0' terminated. */
+ char *b; /* pointer to start of string */
+ char *p; /* pointer after last character */
+ char *e; /* pointer after end of allocated space */
+} string;
+
+#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
+#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
+ string_prepend(str, " ");}
+#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
+ string_append(str, " ");}
+
+#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
+#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
+
+/* Prototypes for local functions */
+
+static char *
+mop_up PARAMS ((struct work_stuff *, string *, int));
+
+#if 0
+static int
+demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *));
+#endif
+
+static int
+demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
+ string *));
+
+static int
+demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
+ int, int));
+
+static int
+demangle_class PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_signature PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+demangle_prefix PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+gnu_special PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+arm_special PARAMS ((struct work_stuff *, const char **, string *));
+
+static void
+string_need PARAMS ((string *, int));
+
+static void
+string_delete PARAMS ((string *));
+
+static void
+string_init PARAMS ((string *));
+
+static void
+string_clear PARAMS ((string *));
+
+#if 0
+static int
+string_empty PARAMS ((string *));
+#endif
+
+static void
+string_append PARAMS ((string *, const char *));
+
+static void
+string_appends PARAMS ((string *, string *));
+
+static void
+string_appendn PARAMS ((string *, const char *, int));
+
+static void
+string_prepend PARAMS ((string *, const char *));
+
+static void
+string_prependn PARAMS ((string *, const char *, int));
+
+static int
+get_count PARAMS ((const char **, int *));
+
+static int
+consume_count PARAMS ((const char **));
+
+static int
+demangle_args PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+do_type PARAMS ((struct work_stuff *, const char **, string *));
+
+static int
+do_arg PARAMS ((struct work_stuff *, const char **, string *));
+
+static void
+demangle_function_name PARAMS ((struct work_stuff *, const char **, string *,
+ const char *));
+
+static void
+remember_type PARAMS ((struct work_stuff *, const char *, int));
+
+static void
+forget_types PARAMS ((struct work_stuff *));
+
+static void
+string_prepends PARAMS ((string *, string *));
+
+/* Translate count to integer, consuming tokens in the process.
+ Conversion terminates on the first non-digit character.
+ Trying to consume something that isn't a count results in
+ no consumption of input and a return of 0. */
+
+static int
+consume_count (type)
+ const char **type;
+{
+ int count = 0;
+
+ while (isdigit (**type))
+ {
+ count *= 10;
+ count += **type - '0';
+ (*type)++;
+ }
+ return (count);
+}
+
+int
+cplus_demangle_opname (opname, result, options)
+ const 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.
+
+ If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
+ if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
+
+const char *
+cplus_mangle_opname (opname, options)
+ const char *opname;
+ int options;
+{
+ int i;
+ int len;
+
+ len = strlen (opname);
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].out) == len
+ && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
+ && memcmp (optable[i].out, opname, len) == 0)
+ return optable[i].in;
+ }
+ return (0);
+}
+
+/* check to see whether MANGLED can match TEXT in the first TEXT_LEN
+ characters. */
+
+int cplus_match (mangled, text, text_len)
+ const char *mangled;
+ char *text;
+ int text_len;
+{
+ if (strncmp (mangled, text, text_len) != 0) {
+ return(0); /* cannot match either */
+ } else {
+ return(1); /* matches mangled, may match demangled */
+ }
+}
+
+/* char *cplus_demangle (const char *mangled, int options)
+
+ 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
+ is returned.
+
+ The OPTIONS arg may contain one or more of the following bits:
+
+ DMGL_ANSI ANSI qualifiers such as `const' and `void' are
+ included.
+ DMGL_PARAMS Function parameters are included.
+
+ For example,
+
+ cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)"
+ cplus_demangle ("foo__1Ai", 0) => "A::foo"
+
+ cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)"
+ cplus_demangle ("foo__1Afe", 0) => "A::foo"
+
+ Note that any leading underscores, or other such characters prepended by
+ the compilation system, are presumed to have already been stripped from
+ MANGLED. */
+
+char *
+cplus_demangle (mangled, options)
+ const char *mangled;
+ int options;
+{
+ string decl;
+ int success = 0;
+ struct work_stuff work[1];
+ char *demangled = NULL;
+
+ if ((mangled != NULL) && (*mangled != '\0'))
+ {
+ memset ((char *) work, 0, sizeof (work));
+ work -> options = options;
+ if ((work->options & DMGL_STYLE_MASK) == 0)
+ work->options |= (int)current_demangling_style & DMGL_STYLE_MASK;
+
+ string_init (&decl);
+
+ /* First check to see if gnu style demangling is active and if the
+ string to be demangled contains a CPLUS_MARKER. If so, attempt to
+ recognize one of the gnu special forms rather than looking for a
+ standard prefix. In particular, don't worry about whether there
+ is a "__" string in the mangled string. Consider "_$_5__foo" for
+ example. */
+
+ if ((AUTO_DEMANGLING || GNU_DEMANGLING))
+ {
+ success = gnu_special (work, &mangled, &decl);
+ }
+ if (!success)
+ {
+ success = demangle_prefix (work, &mangled, &decl);
+ }
+ if (success && (*mangled != '\0'))
+ {
+ success = demangle_signature (work, &mangled, &decl);
+ }
+ if (work->constructor == 2)
+ {
+ string_prepend(&decl, "global constructors keyed to ");
+ work->constructor = 0;
+ }
+ else if (work->destructor == 2)
+ {
+ string_prepend(&decl, "global destructors keyed to ");
+ work->destructor = 0;
+ }
+ demangled = mop_up (work, &decl, success);
+ }
+ return (demangled);
+}
+
+static char *
+mop_up (work, declp, success)
+ struct work_stuff *work;
+ string *declp;
+ int success;
+{
+ char *demangled = NULL;
+
+ /* Discard the remembered types, if any. */
+
+ forget_types (work);
+ if (work -> typevec != NULL)
+ {
+ free ((char *) work -> typevec);
+ }
+
+ /* If demangling was successful, ensure that the demangled string is null
+ terminated and return it. Otherwise, free the demangling decl. */
+
+ if (!success)
+ {
+ string_delete (declp);
+ }
+ else
+ {
+ string_appendn (declp, "", 1);
+ demangled = declp -> b;
+ }
+ return (demangled);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_signature -- demangle the signature part of a mangled name
+
+SYNOPSIS
+
+ static int
+ demangle_signature (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+DESCRIPTION
+
+ Consume and demangle the signature portion of the mangled name.
+
+ DECLP is the string where demangled output is being built. At
+ entry it contains the demangled root name from the mangled name
+ prefix. I.E. either a demangled operator name or the root function
+ name. In some special cases, it may contain nothing.
+
+ *MANGLED points to the current unconsumed location in the mangled
+ name. As tokens are consumed and demangling is performed, the
+ pointer is updated to continuously point at the next token to
+ be consumed.
+
+ Demangling GNU style mangled names is nasty because there is no
+ explicit token that marks the start of the outermost function
+ argument list.
+*/
+
+static int
+demangle_signature (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 1;
+ int func_done = 0;
+ int expect_func = 0;
+ const char *oldmangled = NULL;
+ string trawname;
+ string tname;
+
+ while (success && (**mangled != '\0'))
+ {
+ switch (**mangled)
+ {
+ case 'Q':
+ oldmangled = *mangled;
+ success = demangle_qualified (work, mangled, declp, 1, 0);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
+
+ case 'S':
+ /* Static member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> static_type = 1;
+ break;
+
+ case 'C':
+ /* a const member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> const_type = 1;
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ success = demangle_class (work, mangled, declp);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
+
+ case 'F':
+ /* Function */
+ /* ARM style demangling includes a specific 'F' character after
+ the class name. For GNU style, it is just implied. So we can
+ safely just consume any 'F' at this point and be compatible
+ with either style. */
+
+ oldmangled = NULL;
+ func_done = 1;
+ (*mangled)++;
+
+ /* For lucid/ARM style we have to forget any types we might
+ have remembered up to this point, since they were not argument
+ types. GNU style considers all types seen as available for
+ back references. See comment in demangle_args() */
+
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+ forget_types (work);
+ }
+ success = demangle_args (work, mangled, declp);
+ break;
+
+ case 't':
+ /* 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)
+ {
+ string_prepend (&trawname, "~");
+ string_appends (declp, &trawname);
+ work->destructor -= 1;
+ }
+ if ((work->constructor & 1) || (work->destructor & 1))
+ {
+ string_appends (declp, &trawname);
+ work->constructor -= 1;
+ }
+ string_delete(&trawname);
+ string_delete(&tname);
+ oldmangled = NULL;
+ expect_func = 1;
+ break;
+
+ case '_':
+ /* At the outermost level, we cannot have a return type specified,
+ so if we run into another '_' at this point we are dealing with
+ a mangled name that is either bogus, or has been mangled by
+ some algorithm we don't know how to deal with. So just
+ reject the entire demangling. */
+ success = 0;
+ break;
+
+ default:
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ /* Assume we have stumbled onto the first outermost function
+ argument token, and start processing args. */
+ func_done = 1;
+ success = demangle_args (work, mangled, declp);
+ }
+ else
+ {
+ /* Non-GNU demanglers use a specific token to mark the start
+ of the outermost function argument tokens. Typically 'F',
+ for ARM-demangling, for example. So if we find something
+ we are not prepared for, it must be an error. */
+ success = 0;
+ }
+ break;
+ }
+/*
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+*/
+ {
+ if (success && expect_func)
+ {
+ func_done = 1;
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+ }
+ if (success && !func_done)
+ {
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
+ bar__3fooi is 'foo::bar(int)'. We get here when we find the
+ first case, and need to ensure that the '(void)' gets added to
+ the current declp. Note that with ARM, the first case
+ represents the name of a static data member 'foo::bar',
+ which is in the current declp, so we leave it alone. */
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+ if (success && work -> static_type && PRINT_ARG_TYPES)
+ {
+ string_append (declp, " static");
+ }
+ if (success && work -> const_type && PRINT_ARG_TYPES)
+ {
+ string_append (declp, " const");
+ }
+ return (success);
+}
+
+#if 0
+
+static int
+demangle_method_args (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 0;
+
+ if (work -> static_type)
+ {
+ string_append (declp, *mangled + 1);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ success = demangle_args (work, mangled, declp);
+ }
+ return (success);
+}
+
+#endif
+
+static int
+demangle_template (work, mangled, tname, trawname)
+ struct work_stuff *work;
+ const char **mangled;
+ string *tname;
+ string *trawname;
+{
+ int i;
+ int is_pointer;
+ int is_real;
+ int is_integral;
+ int is_char;
+ int is_bool;
+ int r;
+ int need_comma = 0;
+ int success = 0;
+ int done;
+ const char *old_p;
+ const char *start;
+ int symbol_len;
+ string temp;
+
+ (*mangled)++;
+ start = *mangled;
+ /* get template name */
+ if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
+ {
+ return (0);
+ }
+ if (trawname)
+ string_appendn (trawname, *mangled, r);
+ string_appendn (tname, *mangled, r);
+ *mangled += r;
+ string_append (tname, "<");
+ /* get size of template parameter list */
+ if (!get_count (mangled, &r))
+ {
+ return (0);
+ }
+ for (i = 0; i < r; i++)
+ {
+ if (need_comma)
+ {
+ string_append (tname, ", ");
+ }
+ /* Z for type parameters */
+ if (**mangled == 'Z')
+ {
+ (*mangled)++;
+ /* temp is initialized in do_type */
+ success = do_type (work, mangled, &temp);
+ if (success)
+ {
+ string_appends (tname, &temp);
+ }
+ string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+ }
+ else
+ {
+ /* otherwise, value parameter */
+ old_p = *mangled;
+ is_pointer = 0;
+ is_real = 0;
+ is_integral = 0;
+ is_char = 0;
+ is_bool = 0;
+ done = 0;
+ /* temp is initialized in do_type */
+ success = do_type (work, mangled, &temp);
+/*
+ if (success)
+ {
+ string_appends (tname, &temp);
+ }
+*/
+ string_delete(&temp);
+ if (!success)
+ {
+ break;
+ }
+/*
+ string_append (tname, "=");
+*/
+ while (*old_p && !done)
+ {
+ switch (*old_p)
+ {
+ case 'P':
+ case 'p':
+ case 'R':
+ done = is_pointer = 1;
+ break;
+ case 'C': /* const */
+ case 'S': /* explicitly signed [char] */
+ case 'U': /* unsigned */
+ case 'V': /* volatile */
+ case 'F': /* function */
+ case 'M': /* member function */
+ case 'O': /* ??? */
+ old_p++;
+ continue;
+ case 'Q': /* qualified name */
+ done = is_integral = 1;
+ break;
+ case 'T': /* remembered type */
+ abort ();
+ break;
+ case 'v': /* void */
+ abort ();
+ break;
+ case 'x': /* long long */
+ case 'l': /* long */
+ case 'i': /* int */
+ case 's': /* short */
+ case 'w': /* wchar_t */
+ done = is_integral = 1;
+ break;
+ case 'b': /* bool */
+ done = is_bool = 1;
+ break;
+ case 'c': /* char */
+ done = is_char = 1;
+ break;
+ case 'r': /* long double */
+ case 'd': /* double */
+ case 'f': /* float */
+ done = is_real = 1;
+ break;
+ default:
+ /* it's probably user defined type, let's assume
+ it's integral, it seems hard to figure out
+ what it really is */
+ done = is_integral = 1;
+ }
+ }
+ if (is_integral)
+ {
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ else if (is_char)
+ {
+ char tmp[2];
+ int val;
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ string_appendn (tname, "'", 1);
+ val = consume_count(mangled);
+ if (val == 0)
+ {
+ success = 0;
+ break;
+ }
+ tmp[0] = (char)val;
+ tmp[1] = '\0';
+ string_appendn (tname, &tmp[0], 1);
+ string_appendn (tname, "'", 1);
+ }
+ else if (is_bool)
+ {
+ int val = consume_count (mangled);
+ if (val == 0)
+ string_appendn (tname, "false", 5);
+ else if (val == 1)
+ string_appendn (tname, "true", 4);
+ else
+ success = 0;
+ }
+ else if (is_real)
+ {
+ if (**mangled == 'm')
+ {
+ string_appendn (tname, "-", 1);
+ (*mangled)++;
+ }
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ if (**mangled == '.') /* fraction */
+ {
+ string_appendn (tname, ".", 1);
+ (*mangled)++;
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ if (**mangled == 'e') /* exponent */
+ {
+ string_appendn (tname, "e", 1);
+ (*mangled)++;
+ while (isdigit (**mangled))
+ {
+ string_appendn (tname, *mangled, 1);
+ (*mangled)++;
+ }
+ }
+ }
+ else if (is_pointer)
+ {
+ if (!get_count (mangled, &symbol_len))
+ {
+ success = 0;
+ break;
+ }
+ if (symbol_len == 0)
+ string_appendn (tname, "0", 1);
+ else
+ {
+ char *p = xmalloc (symbol_len + 1), *q;
+ strncpy (p, *mangled, symbol_len);
+ p [symbol_len] = '\0';
+ q = cplus_demangle (p, work->options);
+ string_appendn (tname, "&", 1);
+ if (q)
+ {
+ string_append (tname, q);
+ free (q);
+ }
+ else
+ string_append (tname, p);
+ free (p);
+ }
+ *mangled += symbol_len;
+ }
+ }
+ need_comma = 1;
+ }
+ if (tname->p[-1] == '>')
+ string_append (tname, " ");
+ string_append (tname, ">");
+
+/*
+ if (work -> static_type)
+ {
+ string_append (declp, *mangled + 1);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+*/
+ return (success);
+}
+
+static int
+arm_pt (work, mangled, n, anchor, args)
+ struct work_stuff *work;
+ const char *mangled;
+ int n;
+ const char **anchor, **args;
+{
+ /* ARM template? */
+ if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
+ {
+ int len;
+ *args = *anchor + 6;
+ len = consume_count (args);
+ if (*args + len == mangled + n && **args == '_')
+ {
+ ++*args;
+ return 1;
+ }
+ }
+ 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;
+ const char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 0;
+
+ n = consume_count (mangled);
+ if (strlen (*mangled) >= n)
+ {
+ demangle_arm_pt (work, mangled, n, declp);
+ success = 1;
+ }
+
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_class -- demangle a mangled class sequence
+
+SYNOPSIS
+
+ static int
+ demangle_class (struct work_stuff *work, const char **mangled,
+ strint *declp)
+
+DESCRIPTION
+
+ DECLP points to the buffer into which demangling is being done.
+
+ *MANGLED points to the current token to be demangled. On input,
+ it points to a mangled class (I.E. "3foo", "13verylongclass", etc.)
+ On exit, it points to the next token after the mangled class on
+ success, or the first unconsumed token on failure.
+
+ If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then
+ we are demangling a constructor or destructor. In this case
+ we prepend "class::class" or "class::~class" to DECLP.
+
+ Otherwise, we prepend "class::" to the current DECLP.
+
+ Reset the constructor/destructor flags once they have been
+ "consumed". This allows demangle_class to be called later during
+ the same demangling, to do normal class demangling.
+
+ Returns 1 if demangling is successful, 0 otherwise.
+
+*/
+
+static int
+demangle_class (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 0;
+ string class_name;
+
+ string_init (&class_name);
+ if (demangle_class_name (work, mangled, &class_name))
+ {
+ if ((work->constructor & 1) || (work->destructor & 1))
+ {
+ string_prepends (declp, &class_name);
+ if (work -> destructor & 1)
+ {
+ string_prepend (declp, "~");
+ work -> destructor -= 1;
+ }
+ else
+ {
+ work -> constructor -= 1;
+ }
+ }
+ string_prepend (declp, "::");
+ string_prepends (declp, &class_name);
+ success = 1;
+ }
+ string_delete (&class_name);
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_prefix -- consume the mangled name prefix and find signature
+
+SYNOPSIS
+
+ static int
+ demangle_prefix (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+DESCRIPTION
+
+ Consume and demangle the prefix of the mangled name.
+
+ DECLP points to the string buffer into which demangled output is
+ placed. On entry, the buffer is empty. On exit it contains
+ the root function name, the demangled operator name, or in some
+ special cases either nothing or the completely demangled result.
+
+ MANGLED points to the current pointer into the mangled name. As each
+ token of the mangled name is consumed, it is updated. Upon entry
+ the current mangled name pointer points to the first character of
+ the mangled name. Upon exit, it should point to the first character
+ of the signature if demangling was successful, or to the first
+ unconsumed character if demangling of the prefix was unsuccessful.
+
+ Returns 1 on success, 0 otherwise.
+ */
+
+static int
+demangle_prefix (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int success = 1;
+ const char *scan;
+ int i;
+
+ if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0)
+ {
+ 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;
+ if (gnu_special (work, mangled, declp))
+ return success;
+ }
+ else if ((*mangled)[9] == 'I')
+ {
+ /* it's a GNU global constructor to be executed at program init */
+ (*mangled) += 11;
+ work->constructor = 2;
+ if (gnu_special (work, mangled, declp))
+ return success;
+ }
+ }
+ }
+ else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0)
+ {
+ /* it's a ARM global destructor to be executed at program exit */
+ (*mangled) += 7;
+ work->destructor = 2;
+ }
+ else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0)
+ {
+ /* it's a ARM global constructor to be executed at program initial */
+ (*mangled) += 7;
+ work->constructor = 2;
+ }
+
+/* This block of code is a reduction in strength time optimization
+ of:
+ scan = mystrstr (*mangled, "__"); */
+
+ {
+ scan = *mangled;
+
+ do {
+ scan = strchr (scan, '_');
+ } while (scan != NULL && *++scan != '_');
+
+ if (scan != NULL) --scan;
+ }
+
+ if (scan != NULL)
+ {
+ /* We found a sequence of two or more '_', ensure that we start at
+ the last pair in the sequence. */
+ i = strspn (scan, "_");
+ if (i > 2)
+ {
+ scan += (i - 2);
+ }
+ }
+
+ if (scan == NULL)
+ {
+ success = 0;
+ }
+ else if (work -> static_type)
+ {
+ if (!isdigit (scan[0]) && (scan[0] != 't'))
+ {
+ success = 0;
+ }
+ }
+ else if ((scan == *mangled) &&
+ (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
+ {
+ /* The ARM says nothing about the mangling of local variables.
+ But cfront mangles local variables by prepending __<nesting_level>
+ to them. As an extension to ARM demangling we handle this case. */
+ if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2]))
+ {
+ *mangled = scan + 2;
+ consume_count (mangled);
+ string_append (declp, *mangled);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ else
+ {
+ /* 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'))
+ {
+ /* Mangled name starts with "__". Skip over any leading '_' characters,
+ then find the next "__" that separates the prefix from the signature.
+ */
+ if (!(ARM_DEMANGLING || LUCID_DEMANGLING)
+ || (arm_special (work, mangled, declp) == 0))
+ {
+ while (*scan == '_')
+ {
+ scan++;
+ }
+ if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0'))
+ {
+ /* No separator (I.E. "__not_mangled"), or empty signature
+ (I.E. "__not_mangled_either__") */
+ success = 0;
+ }
+ else
+ {
+ demangle_function_name (work, mangled, declp, scan);
+ }
+ }
+ }
+ 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
+ in there with non empty stuff after it. Looks like a global
+ function name. */
+ demangle_function_name (work, mangled, declp, scan);
+ }
+ else
+ {
+ /* Doesn't look like a mangled name */
+ success = 0;
+ }
+
+ if (!success && (work->constructor == 2 || work->destructor == 2))
+ {
+ string_append (declp, *mangled);
+ *mangled += strlen (*mangled);
+ success = 1;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ gnu_special -- special handling of gnu mangled strings
+
+SYNOPSIS
+
+ static int
+ gnu_special (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+
+DESCRIPTION
+
+ Process some special GNU style mangling forms that don't fit
+ the normal pattern. For example:
+
+ _$_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
+gnu_special (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 1;
+ const char *p;
+
+ if ((*mangled)[0] == '_'
+ && strchr (cplus_markers, (*mangled)[1]) != NULL
+ && (*mangled)[2] == '_')
+ {
+ /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */
+ (*mangled) += 3;
+ work -> destructor += 1;
+ }
+ else if ((*mangled)[0] == '_'
+ && (((*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<CPLUS_MARKER>"
+ and create the decl. Note that we consume the entire mangled
+ input string, which means that demangle_signature has no work
+ to do. */
+ if ((*mangled)[2] == 'v')
+ (*mangled) += 5; /* New style, with thunks: "__vt_" */
+ else
+ (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */
+ while (**mangled != '\0')
+ {
+ p = strpbrk (*mangled, cplus_markers);
+ switch (**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
+ {
+ success = 0;
+ break;
+ }
+ }
+ if (success)
+ string_append (declp, " virtual table");
+ }
+ else if ((*mangled)[0] == '_'
+ && (strchr("0123456789Qt", (*mangled)[1]) != NULL)
+ && (p = strpbrk (*mangled, cplus_markers)) != NULL)
+ {
+ /* static data member, "_3foo$varname" for example */
+ (*mangled)++;
+ switch (**mangled)
+ {
+ case 'Q':
+ success = demangle_qualified (work, mangled, declp, 0, 1);
+ break;
+ case 't':
+ success = demangle_template (work, mangled, declp, 0);
+ break;
+ default:
+ n = consume_count (mangled);
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+ }
+ if (success && (p == *mangled))
+ {
+ /* Consumed everything up to the cplus_marker, append the
+ variable name. */
+ (*mangled)++;
+ string_append (declp, "::");
+ n = strlen (*mangled);
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
+ }
+ else
+ {
+ 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;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ arm_special -- special handling of ARM/lucid mangled strings
+
+SYNOPSIS
+
+ static int
+ arm_special (struct work_stuff *work, const char **mangled,
+ string *declp);
+
+
+DESCRIPTION
+
+ Process some special ARM style mangling forms that don't fit
+ the normal pattern. For example:
+
+ __vtbl__3foo (foo virtual table)
+ __vtbl__3foo__3bar (bar::foo virtual table)
+
+ */
+
+static int
+arm_special (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ int n;
+ int success = 1;
+ const char *scan;
+
+ if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0)
+ {
+ /* Found a ARM style virtual table, get past ARM_VTABLE_STRING
+ and create the decl. Note that we consume the entire mangled
+ input string, which means that demangle_signature has no work
+ to do. */
+ scan = *mangled + ARM_VTABLE_STRLEN;
+ while (*scan != '\0') /* first check it can be demangled */
+ {
+ n = consume_count (&scan);
+ if (n==0)
+ {
+ return (0); /* no good */
+ }
+ scan += n;
+ if (scan[0] == '_' && scan[1] == '_')
+ {
+ scan += 2;
+ }
+ }
+ (*mangled) += ARM_VTABLE_STRLEN;
+ while (**mangled != '\0')
+ {
+ n = consume_count (mangled);
+ string_prependn (declp, *mangled, n);
+ (*mangled) += n;
+ if ((*mangled)[0] == '_' && (*mangled)[1] == '_')
+ {
+ string_prepend (declp, "::");
+ (*mangled) += 2;
+ }
+ }
+ string_append (declp, " virtual table");
+ }
+ else
+ {
+ success = 0;
+ }
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ demangle_qualified -- demangle 'Q' qualified name strings
+
+SYNOPSIS
+
+ static int
+ demangle_qualified (struct work_stuff *, const char *mangled,
+ string *result, int isfuncname, int append);
+
+DESCRIPTION
+
+ Demangle a qualified name, such as "Q25Outer5Inner" which is
+ the mangled form of "Outer::Inner". The demangled output is
+ prepended or appended to the result string according to the
+ state of the append flag.
+
+ If isfuncname is nonzero, then the qualified name we are building
+ is going to be used as a member function name, so if it is a
+ constructor or destructor function, append an appropriate
+ constructor or destructor name. I.E. for the above example,
+ the result for use as a constructor is "Outer::Inner::Inner"
+ and the result for use as a destructor is "Outer::Inner::~Inner".
+
+BUGS
+
+ Numeric conversion is ASCII dependent (FIXME).
+
+ */
+
+static int
+demangle_qualified (work, mangled, result, isfuncname, append)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+ int isfuncname;
+ int append;
+{
+ int qualifiers;
+ int namelength;
+ int success = 1;
+ const char *p;
+ char num[2];
+ string temp;
+
+ string_init (&temp);
+ switch ((*mangled)[1])
+ {
+ case '_':
+ /* GNU mangled name with more than 9 classes. The count is preceded
+ by an underscore (to distinguish it from the <= 9 case) and followed
+ by an underscore. */
+ p = *mangled + 2;
+ qualifiers = atoi (p);
+ if (!isdigit (*p) || *p == '0')
+ success = 0;
+
+ /* Skip the digits. */
+ while (isdigit (*p))
+ ++p;
+
+ if (*p != '_')
+ success = 0;
+
+ *mangled = p + 1;
+ break;
+
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* The count is in a single digit. */
+ num[0] = (*mangled)[1];
+ num[1] = '\0';
+ qualifiers = atoi (num);
+
+ /* If there is an underscore after the digit, skip it. This is
+ said to be for ARM-qualified names, but the ARM makes no
+ mention of such an underscore. Perhaps cfront uses one. */
+ if ((*mangled)[2] == '_')
+ {
+ (*mangled)++;
+ }
+ (*mangled) += 2;
+ break;
+
+ case '0':
+ default:
+ success = 0;
+ }
+
+ if (!success)
+ return success;
+
+ /* Pick off the names and collect them in the temp buffer in the order
+ in which they are found, separated by '::'. */
+
+ while (qualifiers-- > 0)
+ {
+ if (*mangled[0] == '_')
+ *mangled = *mangled + 1;
+ if (*mangled[0] == 't')
+ {
+ success = demangle_template(work, mangled, &temp, 0);
+ if (!success) break;
+ }
+ else
+ {
+ namelength = consume_count (mangled);
+ if (strlen (*mangled) < namelength)
+ {
+ /* Simple sanity check failed */
+ success = 0;
+ break;
+ }
+ string_appendn (&temp, *mangled, namelength);
+ *mangled += namelength;
+ }
+ if (qualifiers > 0)
+ {
+ string_appendn (&temp, "::", 2);
+ }
+ }
+
+ /* If we are using the result as a function name, we need to append
+ the appropriate '::' separated constructor or destructor name.
+ We do this here because this is the most convenient place, where
+ we already have a pointer to the name and the length of the name. */
+
+ if (isfuncname && (work->constructor & 1 || work->destructor & 1))
+ {
+ string_appendn (&temp, "::", 2);
+ if (work -> destructor & 1)
+ {
+ string_append (&temp, "~");
+ }
+ string_appendn (&temp, (*mangled) - namelength, namelength);
+ }
+
+ /* Now either prepend the temp buffer to the result, or append it,
+ depending upon the state of the append flag. */
+
+ if (append)
+ {
+ string_appends (result, &temp);
+ }
+ else
+ {
+ if (!STRING_EMPTY (result))
+ {
+ string_appendn (&temp, "::", 2);
+ }
+ string_prepends (result, &temp);
+ }
+
+ string_delete (&temp);
+ return (success);
+}
+
+/*
+
+LOCAL FUNCTION
+
+ get_count -- convert an ascii count to integer, consuming tokens
+
+SYNOPSIS
+
+ static int
+ get_count (const char **type, int *count)
+
+DESCRIPTION
+
+ Return 0 if no conversion is performed, 1 if a string is converted.
+*/
+
+static int
+get_count (type, count)
+ const char **type;
+ int *count;
+{
+ const char *p;
+ int n;
+
+ if (!isdigit (**type))
+ {
+ return (0);
+ }
+ else
+ {
+ *count = **type - '0';
+ (*type)++;
+ if (isdigit (**type))
+ {
+ p = *type;
+ n = *count;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p++;
+ }
+ while (isdigit (*p));
+ if (*p == '_')
+ {
+ *type = p + 1;
+ *count = n;
+ }
+ }
+ }
+ return (1);
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (work, mangled, result)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+{
+ int n;
+ int done;
+ int success;
+ string decl;
+ const char *remembered_type;
+ int constp;
+ int volatilep;
+
+ string_init (&decl);
+ string_init (result);
+
+ done = 0;
+ success = 1;
+ while (success && !done)
+ {
+ int member;
+ switch (**mangled)
+ {
+
+ /* A pointer type */
+ case 'P':
+ case 'p':
+ (*mangled)++;
+ string_prepend (&decl, "*");
+ break;
+
+ /* A reference type */
+ case 'R':
+ (*mangled)++;
+ string_prepend (&decl, "&");
+ break;
+
+ /* An array */
+ case 'A':
+ {
+ const char *p = ++(*mangled);
+
+ string_prepend (&decl, "(");
+ string_append (&decl, ")[");
+ /* Copy anything up until the next underscore (the size of the
+ array). */
+ while (**mangled && **mangled != '_')
+ ++(*mangled);
+ if (**mangled == '_')
+ {
+ string_appendn (&decl, p, *mangled - p);
+ string_append (&decl, "]");
+ *mangled += 1;
+ }
+ else
+ success = 0;
+ break;
+ }
+
+ /* A back reference to a previously seen type */
+ case 'T':
+ (*mangled)++;
+ if (!get_count (mangled, &n) || n >= work -> ntypes)
+ {
+ success = 0;
+ }
+ else
+ {
+ remembered_type = work -> typevec[n];
+ mangled = &remembered_type;
+ }
+ break;
+
+ /* A function */
+ case 'F':
+ (*mangled)++;
+ if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
+ {
+ string_prepend (&decl, "(");
+ string_append (&decl, ")");
+ }
+ /* After picking off the function args, we expect to either find the
+ function return type (preceded by an '_') or the end of the
+ string. */
+ if (!demangle_args (work, mangled, &decl)
+ || (**mangled != '_' && **mangled != '\0'))
+ {
+ success = 0;
+ }
+ if (success && (**mangled == '_'))
+ {
+ (*mangled)++;
+ }
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ constp = 0;
+ volatilep = 0;
+
+ member = **mangled == 'M';
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ {
+ success = 0;
+ break;
+ }
+ n = consume_count (mangled);
+ if (strlen (*mangled) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_append (&decl, ")");
+ string_prepend (&decl, "::");
+ string_prependn (&decl, *mangled, n);
+ string_prepend (&decl, "(");
+ *mangled += n;
+ if (member)
+ {
+ if (**mangled == 'C')
+ {
+ (*mangled)++;
+ constp = 1;
+ }
+ if (**mangled == 'V')
+ {
+ (*mangled)++;
+ volatilep = 1;
+ }
+ if (*(*mangled)++ != 'F')
+ {
+ success = 0;
+ break;
+ }
+ }
+ if ((member && !demangle_args (work, mangled, &decl))
+ || **mangled != '_')
+ {
+ success = 0;
+ break;
+ }
+ (*mangled)++;
+ if (! PRINT_ANSI_QUALIFIERS)
+ {
+ break;
+ }
+ if (constp)
+ {
+ APPEND_BLANK (&decl);
+ string_append (&decl, "const");
+ }
+ if (volatilep)
+ {
+ APPEND_BLANK (&decl);
+ string_append (&decl, "volatile");
+ }
+ break;
+ }
+ case 'G':
+ (*mangled)++;
+ break;
+
+ case 'C':
+ (*mangled)++;
+/*
+ if ((*mangled)[1] == 'P')
+ {
+*/
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ if (!STRING_EMPTY (&decl))
+ {
+ string_prepend (&decl, " ");
+ }
+ string_prepend (&decl, "const");
+ }
+ break;
+/*
+ }
+*/
+
+ /* fall through */
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ switch (**mangled)
+ {
+ /* A qualified name, such as "Outer::Inner". */
+ case 'Q':
+ success = demangle_qualified (work, mangled, result, 0, 1);
+ break;
+
+ default:
+ success = demangle_fund_type (work, mangled, result);
+ break;
+ }
+
+ if (success)
+ {
+ if (!STRING_EMPTY (&decl))
+ {
+ string_append (result, " ");
+ string_appends (result, &decl);
+ }
+ }
+ else
+ {
+ string_delete (result);
+ }
+ string_delete (&decl);
+ return (success);
+}
+
+/* Given a pointer to a type string that represents a fundamental type
+ argument (int, long, unsigned int, etc) in TYPE, a pointer to the
+ string in which the demangled output is being built in RESULT, and
+ the WORK structure, decode the types and add them to the result.
+
+ For example:
+
+ "Ci" => "const int"
+ "Sl" => "signed long"
+ "CUs" => "const unsigned short"
+
+ */
+
+static int
+demangle_fund_type (work, mangled, result)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+{
+ int done = 0;
+ int success = 1;
+
+ /* First pick off any type qualifiers. There can be more than one. */
+
+ while (!done)
+ {
+ switch (**mangled)
+ {
+ case 'C':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "const");
+ }
+ break;
+ case 'U':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "unsigned");
+ break;
+ case 'S': /* signed char only */
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "signed");
+ break;
+ case 'V':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "volatile");
+ }
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ /* Now pick off the fundamental type. There can be only one. */
+
+ switch (**mangled)
+ {
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "void");
+ break;
+ case 'x':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long long");
+ break;
+ case 'l':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long");
+ break;
+ case 'i':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "int");
+ break;
+ case 's':
+ (*mangled)++;
+ 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);
+ string_append (result, "char");
+ break;
+ case 'w':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "wchar_t");
+ break;
+ case 'r':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long double");
+ break;
+ case 'd':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "double");
+ break;
+ case 'f':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "float");
+ break;
+ case 'G':
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ {
+ success = 0;
+ break;
+ }
+ /* fall through */
+ /* An explicit type, such as "6mytype" or "7integer" */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ APPEND_BLANK (result);
+ if (!demangle_class_name (work, mangled, result)) {
+ --result->p;
+ success = 0;
+ }
+ break;
+ case 't':
+ success = demangle_template(work,mangled, result, 0);
+ break;
+ default:
+ success = 0;
+ break;
+ }
+
+ return (success);
+}
+
+/* `result' will be initialized in do_type; it will be freed on failure */
+
+static int
+do_arg (work, mangled, result)
+ struct work_stuff *work;
+ const char **mangled;
+ string *result;
+{
+ const char *start = *mangled;
+
+ if (!do_type (work, mangled, result))
+ {
+ return (0);
+ }
+ else
+ {
+ remember_type (work, start, *mangled - start);
+ return (1);
+ }
+}
+
+static void
+remember_type (work, start, len)
+ struct work_stuff *work;
+ const char *start;
+ int len;
+{
+ char *tem;
+
+ if (work -> ntypes >= work -> typevec_size)
+ {
+ if (work -> typevec_size == 0)
+ {
+ work -> typevec_size = 3;
+ work -> typevec =
+ (char **) xmalloc (sizeof (char *) * work -> typevec_size);
+ }
+ else
+ {
+ work -> typevec_size *= 2;
+ work -> typevec =
+ (char **) xrealloc ((char *)work -> typevec,
+ sizeof (char *) * work -> typevec_size);
+ }
+ }
+ tem = xmalloc (len + 1);
+ memcpy (tem, start, len);
+ tem[len] = '\0';
+ work -> typevec[work -> ntypes++] = tem;
+}
+
+/* Forget the remembered types, but not the type vector itself. */
+
+static void
+forget_types (work)
+ struct work_stuff *work;
+{
+ int i;
+
+ while (work -> ntypes > 0)
+ {
+ i = --(work -> ntypes);
+ if (work -> typevec[i] != NULL)
+ {
+ free (work -> typevec[i]);
+ work -> typevec[i] = NULL;
+ }
+ }
+}
+
+/* Process the argument list part of the signature, after any class spec
+ has been consumed, as well as the first 'F' character (if any). For
+ example:
+
+ "__als__3fooRT0" => process "RT0"
+ "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i"
+
+ DECLP must be already initialised, usually non-empty. It won't be freed
+ on failure.
+
+ Note that g++ differs significantly from ARM and lucid style mangling
+ with regards to references to previously seen types. For example, given
+ the source fragment:
+
+ class foo {
+ public:
+ foo::foo (int, foo &ia, int, foo &ib, int, foo &ic);
+ };
+
+ foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+ void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; }
+
+ g++ produces the names:
+
+ __3fooiRT0iT2iT2
+ foo__FiR3fooiT1iT1
+
+ while lcc (and presumably other ARM style compilers as well) produces:
+
+ foo__FiR3fooT1T2T1T2
+ __ct__3fooFiR3fooT1T2T1T2
+
+ Note that g++ bases it's type numbers starting at zero and counts all
+ previously seen types, while lucid/ARM bases it's type numbers starting
+ at one and only considers types after it has seen the 'F' character
+ indicating the start of the function args. For lucid/ARM style, we
+ account for this difference by discarding any previously seen types when
+ we see the 'F' character, and subtracting one from the type number
+ reference.
+
+ */
+
+static int
+demangle_args (work, mangled, declp)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+{
+ string arg;
+ int need_comma = 0;
+ int r;
+ int t;
+ const char *tem;
+ char temptype;
+
+ if (PRINT_ARG_TYPES)
+ {
+ string_append (declp, "(");
+ if (**mangled == '\0')
+ {
+ string_append (declp, "void");
+ }
+ }
+
+ while (**mangled != '_' && **mangled != '\0' && **mangled != 'e')
+ {
+ if ((**mangled == 'N') || (**mangled == 'T'))
+ {
+ temptype = *(*mangled)++;
+
+ if (temptype == 'N')
+ {
+ if (!get_count (mangled, &r))
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ r = 1;
+ }
+ if (ARM_DEMANGLING && work -> ntypes >= 10)
+ {
+ /* If we have 10 or more types we might have more than a 1 digit
+ index so we'll have to consume the whole count here. This
+ will lose if the next thing is a type name preceded by a
+ count but it's impossible to demangle that case properly
+ anyway. Eg if we already have 12 types is T12Pc "(..., type1,
+ Pc, ...)" or "(..., type12, char *, ...)" */
+ if ((t = consume_count(mangled)) == 0)
+ {
+ return (0);
+ }
+ }
+ else
+ {
+ if (!get_count (mangled, &t))
+ {
+ return (0);
+ }
+ }
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+ t--;
+ }
+ /* Validate the type index. Protect against illegal indices from
+ malformed type strings. */
+ if ((t < 0) || (t >= work -> ntypes))
+ {
+ return (0);
+ }
+ while (--r >= 0)
+ {
+ tem = work -> typevec[t];
+ if (need_comma && PRINT_ARG_TYPES)
+ {
+ string_append (declp, ", ");
+ }
+ if (!do_arg (work, &tem, &arg))
+ {
+ return (0);
+ }
+ if (PRINT_ARG_TYPES)
+ {
+ string_appends (declp, &arg);
+ }
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+ else
+ {
+ if (need_comma & PRINT_ARG_TYPES)
+ {
+ string_append (declp, ", ");
+ }
+ if (!do_arg (work, mangled, &arg))
+ {
+ return (0);
+ }
+ if (PRINT_ARG_TYPES)
+ {
+ string_appends (declp, &arg);
+ }
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+
+ if (**mangled == 'e')
+ {
+ (*mangled)++;
+ if (PRINT_ARG_TYPES)
+ {
+ if (need_comma)
+ {
+ string_append (declp, ",");
+ }
+ string_append (declp, "...");
+ }
+ }
+
+ if (PRINT_ARG_TYPES)
+ {
+ string_append (declp, ")");
+ }
+ return (1);
+}
+
+static void
+demangle_function_name (work, mangled, declp, scan)
+ struct work_stuff *work;
+ const char **mangled;
+ string *declp;
+ const char *scan;
+{
+ int i;
+ int len;
+ string type;
+ const char *tem;
+
+ string_appendn (declp, (*mangled), scan - (*mangled));
+ string_need (declp, 1);
+ *(declp -> p) = '\0';
+
+ /* Consume the function name, including the "__" separating the name
+ from the signature. We are guaranteed that SCAN points to the
+ separator. */
+
+ (*mangled) = scan + 2;
+
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+
+ /* See if we have an ARM style constructor or destructor operator.
+ If so, then just record it, clear the decl, and return.
+ We can't build the actual constructor/destructor decl until later,
+ when we recover the class name from the signature. */
+
+ if (strcmp (declp -> b, "__ct") == 0)
+ {
+ work -> constructor += 1;
+ string_clear (declp);
+ return;
+ }
+ else if (strcmp (declp -> b, "__dt") == 0)
+ {
+ work -> destructor += 1;
+ string_clear (declp);
+ return;
+ }
+ }
+
+ if (declp->p - declp->b >= 3
+ && declp->b[0] == 'o'
+ && declp->b[1] == 'p'
+ && strchr (cplus_markers, declp->b[2]) != NULL)
+ {
+ /* see if it's an assignment expression */
+ if (declp->p - declp->b >= 10 /* op$assign_ */
+ && memcmp (declp->b + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ len = declp->p - declp->b - 10;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, declp->b + 10, len) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ string_append (declp, "=");
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ int len = declp->p - declp->b - 3;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, declp->b + 3, len) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ }
+ 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;
+ if (do_type (work, &tem, &type))
+ {
+ string_clear (declp);
+ string_append (declp, "operator ");
+ string_appends (declp, &type);
+ string_delete (&type);
+ }
+ }
+ else if (declp->b[0] == '_' && declp->b[1] == '_'
+ && declp->b[2] == 'o' && declp->b[3] == 'p')
+ {
+ /* ANSI. */
+ /* type conversion operator. */
+ tem = declp->b + 4;
+ if (do_type (work, &tem, &type))
+ {
+ string_clear (declp);
+ string_append (declp, "operator ");
+ string_appends (declp, &type);
+ string_delete (&type);
+ }
+ }
+ else if (declp->b[0] == '_' && declp->b[1] == '_'
+ && declp->b[2] >= 'a' && declp->b[2] <= 'z'
+ && declp->b[3] >= 'a' && declp->b[3] <= 'z')
+ {
+ if (declp->b[4] == '\0')
+ {
+ /* Operator. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 2
+ && memcmp (optable[i].in, declp->b + 2, 2) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (declp->b[2] == 'a' && declp->b[5] == '\0')
+ {
+ /* Assignment. */
+ for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
+ {
+ if (strlen (optable[i].in) == 3
+ && memcmp (optable[i].in, declp->b + 2, 3) == 0)
+ {
+ string_clear (declp);
+ string_append (declp, "operator");
+ string_append (declp, optable[i].out);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+ string *s;
+ int n;
+{
+ int tem;
+
+ if (s->b == NULL)
+ {
+ if (n < 32)
+ {
+ n = 32;
+ }
+ s->p = s->b = xmalloc (n);
+ s->e = s->b + n;
+ }
+ else if (s->e - s->p < n)
+ {
+ tem = s->p - s->b;
+ n += tem;
+ n *= 2;
+ s->b = xrealloc (s->b, n);
+ s->p = s->b + tem;
+ s->e = s->b + n;
+ }
+}
+
+static void
+string_delete (s)
+ string *s;
+{
+ if (s->b != NULL)
+ {
+ free (s->b);
+ s->b = s->e = s->p = NULL;
+ }
+}
+
+static void
+string_init (s)
+ string *s;
+{
+ s->b = s->p = s->e = NULL;
+}
+
+static void
+string_clear (s)
+ string *s;
+{
+ s->p = s->b;
+}
+
+#if 0
+
+static int
+string_empty (s)
+ string *s;
+{
+ return (s->b == s->p);
+}
+
+#endif
+
+static void
+string_append (p, s)
+ string *p;
+ const char *s;
+{
+ int n;
+ if (s == NULL || *s == '\0')
+ return;
+ n = strlen (s);
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_appends (p, s)
+ string *p, *s;
+{
+ int n;
+
+ if (s->b != s->p)
+ {
+ n = s->p - s->b;
+ string_need (p, n);
+ memcpy (p->p, s->b, n);
+ p->p += n;
+ }
+}
+
+static void
+string_appendn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ if (n != 0)
+ {
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+ }
+}
+
+static void
+string_prepend (p, s)
+ string *p;
+ const char *s;
+{
+ if (s != NULL && *s != '\0')
+ {
+ string_prependn (p, s, strlen (s));
+ }
+}
+
+static void
+string_prepends (p, s)
+ string *p, *s;
+{
+ if (s->b != s->p)
+ {
+ string_prependn (p, s->b, s->p - s->b);
+ }
+}
+
+static void
+string_prependn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ char *q;
+
+ if (n != 0)
+ {
+ string_need (p, n);
+ for (q = p->p - 1; q >= p->b; q--)
+ {
+ q[n] = q[0];
+ }
+ memcpy (p->b, s, n);
+ p->p += n;
+ }
+}
+
+/* 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
+
+static void
+demangle_it (mangled_name)
+ char *mangled_name;
+{
+ char *result;
+
+ result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
+ if (result == NULL)
+ {
+ printf ("%s\n", mangled_name);
+ }
+ else
+ {
+ printf ("%s\n", result);
+ free (result);
+ }
+}
+
+#include "getopt.h"
+
+static char *program_name;
+static char *program_version = VERSION;
+
+static void
+usage (stream, status)
+ FILE *stream;
+ int status;
+{
+ fprintf (stream, "\
+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);
+}
+
+#define MBUF_SIZE 512
+char mbuffer[MBUF_SIZE];
+
+/* Defined in the automatically-generated underscore.c. */
+extern int prepends_underscore;
+
+int strip_underscore = 0;
+
+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}
+};
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *result;
+ int c;
+
+ program_name = argv[0];
+
+ strip_underscore = prepends_underscore;
+
+ while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
+ {
+ switch (c)
+ {
+ case '?':
+ usage (stderr, 1);
+ 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);
+ case '_':
+ strip_underscore = 1;
+ break;
+ case 's':
+ if (strcmp (optarg, "gnu") == 0)
+ {
+ current_demangling_style = gnu_demangling;
+ }
+ else if (strcmp (optarg, "lucid") == 0)
+ {
+ current_demangling_style = lucid_demangling;
+ }
+ else if (strcmp (optarg, "arm") == 0)
+ {
+ current_demangling_style = arm_demangling;
+ }
+ else
+ {
+ fprintf (stderr, "%s: unknown demangling style `%s'\n",
+ program_name, optarg);
+ exit (1);
+ }
+ break;
+ }
+ }
+
+ if (optind < argc)
+ {
+ for ( ; optind < argc; optind++)
+ {
+ demangle_it (argv[optind]);
+ }
+ }
+ else
+ {
+ for (;;)
+ {
+ int i = 0;
+ c = getchar ();
+ /* Try to read a label. */
+ while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
+ {
+ if (i >= MBUF_SIZE-1)
+ break;
+ mbuffer[i++] = c;
+ c = getchar ();
+ }
+ if (i > 0)
+ {
+ int skip_first = 0;
+
+ if (mbuffer[0] == '.')
+ ++skip_first;
+ if (strip_underscore && mbuffer[skip_first] == '_')
+ ++skip_first;
+
+ if (skip_first > i)
+ skip_first = i;
+
+ mbuffer[i] = 0;
+
+ result = cplus_demangle (mbuffer + skip_first,
+ DMGL_PARAMS | DMGL_ANSI);
+ if (result)
+ {
+ if (mbuffer[0] == '.')
+ putc ('.', stdout);
+ fputs (result, stdout);
+ free (result);
+ }
+ else
+ fputs (mbuffer, stdout);
+
+ fflush (stdout);
+ }
+ if (c == EOF)
+ break;
+ putchar (c);
+ }
+ }
+
+ exit (0);
+}
+
+static void
+fatal (str)
+ char *str;
+{
+ fprintf (stderr, "%s: %s\n", program_name, str);
+ exit (1);
+}
+
+char * malloc ();
+char * realloc ();
+
+char *
+xmalloc (size)
+ unsigned size;
+{
+ register char *value = (char *) malloc (size);
+ if (value == 0)
+ fatal ("virtual memory exhausted");
+ return value;
+}
+
+char *
+xrealloc (ptr, size)
+ char *ptr;
+ unsigned size;
+{
+ register char *value = (char *) realloc (ptr, size);
+ if (value == 0)
+ fatal ("virtual memory exhausted");
+ return value;
+}
+#endif /* main */
diff --git a/contrib/gdb/libiberty/dummy.c b/contrib/gdb/libiberty/dummy.c
new file mode 100644
index 0000000..08da647
--- /dev/null
+++ b/contrib/gdb/libiberty/dummy.c
@@ -0,0 +1,49 @@
+#include <ansidecl.h>
+
+#ifdef __STDC__
+#include <stddef.h>
+#define clock_t unsigned long
+#define DEF(NAME, RETURN_TYPE, ARGLIST, ARGS) extern RETURN_TYPE NAME (ARGS);
+#define DEFFUNC(NAME, RETURN_TYPE, ARGLIST, ARGS) extern RETURN_TYPE NAME (ARGS);
+#else
+#define void int
+#define size_t unsigned long
+#define clock_t unsigned long
+#define DEF(NAME, RETURN_TYPE, ARGLIST, ARGS) extern RETURN_TYPE NAME ();
+#define DEFFUNC(NAME, RETURN_TYPE, ARGLIST, ARGS) extern RETURN_TYPE NAME ();
+#endif
+
+#define DEFVAR(NAME,DECL,USE) extern DECL;
+
+#define NOTHING /*nothing*/
+
+#include "alloca-conf.h"
+#include "functions.def"
+
+/* Always use our: getopt.o getopt1.o obstack.o spaces.o */
+
+int
+main (argc, argv)
+ int argc; char **argv;
+{
+
+/* Create a dummy function call for each DEF-defined function. */
+
+#undef DEF
+#undef DEFVAR
+#undef DEFFUNC
+#undef AND
+#define AND = 0;
+/* ARGS expands into a set of declaration. NAME ARG_LIST expands
+ info a function call that uses those variables as actual parameters.
+ If the function has been DEF'ed correctly, we can pass the right
+ number and types of parameters, which is nice. (E.g. gcc may
+ otherwise complain about the wrong number of parameters to certain
+ builtins.) */
+#define DEF(NAME, RETURN_TYPE, ARG_LIST, ARGS) { ARGS; NAME ARG_LIST; }
+#define DEFVAR(NAME, DECL, USE) { USE; }
+#define DEFFUNC(NAME, RETURN_TYPE, ARG_LIST, ARGS) { ARGS; NAME ARG_LIST; }
+#include "functions.def"
+
+ return (0);
+}
diff --git a/contrib/gdb/libiberty/fdmatch.c b/contrib/gdb/libiberty/fdmatch.c
new file mode 100644
index 0000000..7af039f
--- /dev/null
+++ b/contrib/gdb/libiberty/fdmatch.c
@@ -0,0 +1,73 @@
+/* Compare two open file descriptors to see if they refer to the same file.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/*
+
+NAME
+
+ fdmatch -- see if two file descriptors refer to same file
+
+SYNOPSIS
+
+ int fdmatch (int fd1, int fd2)
+
+DESCRIPTION
+
+ Check to see if two open file descriptors refer to the same file.
+ This is useful, for example, when we have an open file descriptor
+ for an unnamed file, and the name of a file that we believe to
+ correspond to that fd. This can happen when we are exec'd with
+ an already open file (stdout for example) or from the SVR4 /proc
+ calls that return open file descriptors for mapped address spaces.
+ All we have to do is open the file by name and check the two file
+ descriptors for a match, which is done by comparing major&minor
+ device numbers and inode numbers.
+
+BUGS
+
+ (FIXME: does this work for networks?)
+ It works for NFS, which assigns a device number to each mount.
+
+*/
+
+#include "ansidecl.h"
+#include "libiberty.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int fdmatch (fd1, fd2)
+ int fd1;
+ int fd2;
+{
+ struct stat sbuf1;
+ struct stat sbuf2;
+
+ if ((fstat (fd1, &sbuf1) == 0) &&
+ (fstat (fd2, &sbuf2) == 0) &&
+ (sbuf1.st_dev == sbuf2.st_dev) &&
+ (sbuf1.st_ino == sbuf2.st_ino))
+ {
+ return (1);
+ }
+ else
+ {
+ return (0);
+ }
+}
diff --git a/contrib/gdb/libiberty/floatformat.c b/contrib/gdb/libiberty/floatformat.c
new file mode 100644
index 0000000..655f4ea
--- /dev/null
+++ b/contrib/gdb/libiberty/floatformat.c
@@ -0,0 +1,385 @@
+/* IEEE floating point support routines, for GDB, the GNU Debugger.
+ Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "floatformat.h"
+#include <math.h> /* ldexp */
+#ifdef __STDC__
+#include <stddef.h>
+extern void *memcpy (void *s1, const void *s2, size_t n);
+extern void *memset (void *s, int c, size_t n);
+#else
+extern char *memcpy ();
+extern char *memset ();
+#endif
+
+/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
+ going to bother with trying to muck around with whether it is defined in
+ a system header, what we do if not, etc. */
+#define FLOATFORMAT_CHAR_BIT 8
+
+/* floatformats for IEEE single and double, big and little endian. */
+const struct floatformat floatformat_ieee_single_big =
+{
+ floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23, floatformat_intbit_no
+};
+const struct floatformat floatformat_ieee_single_little =
+{
+ floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23, floatformat_intbit_no
+};
+const struct floatformat floatformat_ieee_double_big =
+{
+ floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52, floatformat_intbit_no
+};
+const struct floatformat floatformat_ieee_double_little =
+{
+ floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52, floatformat_intbit_no
+};
+
+const struct floatformat floatformat_i387_ext =
+{
+ floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
+ floatformat_intbit_yes
+};
+const struct floatformat floatformat_m68881_ext =
+{
+ /* Note that the bits from 16 to 31 are unused. */
+ floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64, floatformat_intbit_yes
+};
+const struct floatformat floatformat_i960_ext =
+{
+ /* Note that the bits from 0 to 15 are unused. */
+ floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
+ floatformat_intbit_yes
+};
+const struct floatformat floatformat_m88110_ext =
+{
+#ifdef HARRIS_FLOAT_FORMAT
+ /* Harris uses raw format 128 bytes long, but the number is just an ieee
+ double, and the last 64 bits are wasted. */
+ floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52,
+ floatformat_intbit_no
+#else
+ floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
+ floatformat_intbit_yes
+#endif /* HARRIS_FLOAT_FORMAT */
+};
+const struct floatformat floatformat_arm_ext =
+{
+ /* Bits 1 to 16 are unused. */
+ floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
+ floatformat_intbit_yes
+};
+
+static unsigned long get_field PARAMS ((unsigned char *,
+ enum floatformat_byteorders,
+ unsigned int,
+ unsigned int,
+ unsigned int));
+
+/* Extract a field which starts at START and is LEN bytes long. DATA and
+ TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
+static unsigned long
+get_field (data, order, total_len, start, len)
+ unsigned char *data;
+ enum floatformat_byteorders order;
+ unsigned int total_len;
+ unsigned int start;
+ unsigned int len;
+{
+ unsigned long result;
+ unsigned int cur_byte;
+ int cur_bitshift;
+
+ /* Start at the least significant part of the field. */
+ cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little)
+ cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
+ cur_bitshift =
+ ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
+ result = *(data + cur_byte) >> (-cur_bitshift);
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little)
+ ++cur_byte;
+ else
+ --cur_byte;
+
+ /* Move towards the most significant part of the field. */
+ while (cur_bitshift < len)
+ {
+ if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
+ /* This is the last byte; zero out the bits which are not part of
+ this field. */
+ result |=
+ (*(data + cur_byte) & ((1 << (len - cur_bitshift)) - 1))
+ << cur_bitshift;
+ else
+ result |= *(data + cur_byte) << cur_bitshift;
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little)
+ ++cur_byte;
+ else
+ --cur_byte;
+ }
+ return result;
+}
+
+/* Convert from FMT to a double.
+ FROM is the address of the extended float.
+ Store the double in *TO. */
+
+void
+floatformat_to_double (fmt, from, to)
+ const struct floatformat *fmt;
+ char *from;
+ double *to;
+{
+ unsigned char *ufrom = (unsigned char *)from;
+ double dto;
+ long exponent;
+ unsigned long mant;
+ unsigned int mant_bits, mant_off;
+ int mant_bits_left;
+
+ exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+ fmt->exp_start, fmt->exp_len);
+ /* Note that if exponent indicates a NaN, we can't really do anything useful
+ (not knowing if the host has NaN's, or how to build one). So it will
+ end up as an infinity or something close; that is OK. */
+
+ mant_bits_left = fmt->man_len;
+ mant_off = fmt->man_start;
+ dto = 0.0;
+ exponent -= fmt->exp_bias;
+
+ /* Build the result algebraically. Might go infinite, underflow, etc;
+ who cares. */
+ while (mant_bits_left > 0)
+ {
+ int exp_bits;
+ exp_bits = mant_bits_left < 32 ? mant_bits_left : 32;
+ if (mant_bits_left == fmt->man_len
+ && exp_bits == 32
+ && fmt->intbit == floatformat_intbit_no)
+ {
+ /* If there is no integer bit, we need to get only 31 bits
+ so we have room for an integer bit that we create. */
+ mant_bits = 31;
+ }
+ else
+ mant_bits = exp_bits;
+
+ mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
+ mant_off, mant_bits);
+ if (mant_bits_left == fmt->man_len)
+ mant |= 0x80000000;
+ dto += ldexp ((double)mant, exponent - (exp_bits - 1));
+ exponent -= exp_bits;
+ mant_off += mant_bits;
+ mant_bits_left -= mant_bits;
+ }
+
+ /* Negate it if negative. */
+ if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
+ dto = -dto;
+ memcpy (to, &dto, sizeof (dto));
+}
+
+static void put_field PARAMS ((unsigned char *, enum floatformat_byteorders,
+ unsigned int,
+ unsigned int,
+ unsigned int,
+ unsigned long));
+
+/* Set a field which starts at START and is LEN bytes long. DATA and
+ TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
+static void
+put_field (data, order, total_len, start, len, stuff_to_put)
+ unsigned char *data;
+ enum floatformat_byteorders order;
+ unsigned int total_len;
+ unsigned int start;
+ unsigned int len;
+ unsigned long stuff_to_put;
+{
+ unsigned int cur_byte;
+ int cur_bitshift;
+
+ /* Start at the least significant part of the field. */
+ cur_byte = (start + len) / FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little)
+ cur_byte = (total_len / FLOATFORMAT_CHAR_BIT) - cur_byte - 1;
+ cur_bitshift =
+ ((start + len) % FLOATFORMAT_CHAR_BIT) - FLOATFORMAT_CHAR_BIT;
+ *(data + cur_byte) &=
+ ~(((1 << ((start + len) % FLOATFORMAT_CHAR_BIT)) - 1) << (-cur_bitshift));
+ *(data + cur_byte) |=
+ (stuff_to_put & ((1 << FLOATFORMAT_CHAR_BIT) - 1)) << (-cur_bitshift);
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little)
+ ++cur_byte;
+ else
+ --cur_byte;
+
+ /* Move towards the most significant part of the field. */
+ while (cur_bitshift < len)
+ {
+ if (len - cur_bitshift < FLOATFORMAT_CHAR_BIT)
+ {
+ /* This is the last byte. */
+ *(data + cur_byte) &=
+ ~((1 << (len - cur_bitshift)) - 1);
+ *(data + cur_byte) |= (stuff_to_put >> cur_bitshift);
+ }
+ else
+ *(data + cur_byte) = ((stuff_to_put >> cur_bitshift)
+ & ((1 << FLOATFORMAT_CHAR_BIT) - 1));
+ cur_bitshift += FLOATFORMAT_CHAR_BIT;
+ if (order == floatformat_little)
+ ++cur_byte;
+ else
+ --cur_byte;
+ }
+}
+
+/* The converse: convert the double *FROM to an extended float
+ and store where TO points. Neither FROM nor TO have any alignment
+ restrictions. */
+
+void
+floatformat_from_double (fmt, from, to)
+ CONST struct floatformat *fmt;
+ double *from;
+ char *to;
+{
+ double dfrom;
+ int exponent;
+ double mant;
+ unsigned int mant_bits, mant_off;
+ int mant_bits_left;
+ unsigned char *uto = (unsigned char *)to;
+
+ memcpy (&dfrom, from, sizeof (dfrom));
+ memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
+ if (dfrom == 0)
+ return; /* Result is zero */
+ if (dfrom != dfrom)
+ {
+ /* From is NaN */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
+ fmt->exp_len, fmt->exp_nan);
+ /* Be sure it's not infinity, but NaN value is irrel */
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
+ 32, 1);
+ return;
+ }
+
+ /* If negative, set the sign bit. */
+ if (dfrom < 0)
+ {
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
+ dfrom = -dfrom;
+ }
+
+ /* How to tell an infinity from an ordinary number? FIXME-someday */
+
+ mant = frexp (dfrom, &exponent);
+ put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len,
+ exponent + fmt->exp_bias - 1);
+
+ mant_bits_left = fmt->man_len;
+ mant_off = fmt->man_start;
+ while (mant_bits_left > 0)
+ {
+ unsigned long mant_long;
+ mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
+
+ mant *= 4294967296.0;
+ mant_long = (unsigned long)mant;
+ mant -= mant_long;
+
+ /* If the integer bit is implicit, then we need to discard it.
+ If we are discarding a zero, we should be (but are not) creating
+ a denormalized number which means adjusting the exponent
+ (I think). */
+ if (mant_bits_left == fmt->man_len
+ && fmt->intbit == floatformat_intbit_no)
+ {
+ mant_long &= 0x7fffffff;
+ mant_bits -= 1;
+ }
+ else if (mant_bits < 32)
+ {
+ /* The bits we want are in the most significant MANT_BITS bits of
+ mant_long. Move them to the least significant. */
+ mant_long >>= 32 - mant_bits;
+ }
+
+ put_field (uto, fmt->byteorder, fmt->totalsize,
+ mant_off, mant_bits, mant_long);
+ mant_off += mant_bits;
+ mant_bits_left -= mant_bits;
+ }
+}
+
+
+#ifdef IEEE_DEBUG
+
+/* This is to be run on a host which uses IEEE floating point. */
+
+void
+ieee_test (n)
+ double n;
+{
+ double result;
+ char exten[16];
+
+ floatformat_to_double (&floatformat_ieee_double_big, &n, &result);
+ if (n != result)
+ printf ("Differ(to): %.20g -> %.20g\n", n, result);
+ floatformat_from_double (&floatformat_ieee_double_big, &n, &result);
+ if (n != result)
+ printf ("Differ(from): %.20g -> %.20g\n", n, result);
+
+ floatformat_from_double (&floatformat_m68881_ext, &n, exten);
+ floatformat_to_double (&floatformat_m68881_ext, exten, &result);
+ if (n != result)
+ printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
+
+#if IEEE_DEBUG > 1
+ /* This is to be run on a host which uses 68881 format. */
+ {
+ long double ex = *(long double *)exten;
+ if (ex != n)
+ printf ("Differ(from vs. extended): %.20g\n", n);
+ }
+#endif
+}
+
+int
+main ()
+{
+ ieee_test (0.5);
+ ieee_test (256.0);
+ ieee_test (0.12345);
+ ieee_test (234235.78907234);
+ ieee_test (-512.0);
+ ieee_test (-0.004321);
+ return 0;
+}
+#endif
diff --git a/contrib/gdb/libiberty/functions.def b/contrib/gdb/libiberty/functions.def
new file mode 100644
index 0000000..8becc89
--- /dev/null
+++ b/contrib/gdb/libiberty/functions.def
@@ -0,0 +1,67 @@
+/*
+ * List of function definitions that may *optionally* be included
+ * in libiberty.a. The function names must match the filenames,
+ * e.g. bzero() is defined in bzero.c. (While each file can contain
+ * extra functions, do not list them.)
+ *
+ * In the default libiberty configuration, these object files
+ * (e.g bzero.o) are included if and only if cc fails to find
+ * the corresponding function in libc.
+ */
+
+DEF(atexit, int, (f), void (*f)())
+DEF(bcmp, int, (s1, s2, length), char *s1 AND char *s2 AND int length )
+DEF(bcopy, void, (s1, s2, length), char *s1 AND char *s2 AND int length )
+DEF(bzero, void, (s, length), char *s AND int length)
+DEF(clock, clock_t, (), NOTHING)
+DEF(getopt, int, (argc, argv, optstring),
+ int argc AND char **argv AND CONST char *optstring)
+DEF(getpagesize, int , (), NOTHING)
+DEF(getcwd, char*, (buf, len), char *buf AND int len)
+DEF(index, char*, (s, c), char *s AND int c)
+DEF(insque, void, (), NOTHING)
+DEF(memchr, PTR, (s, c, length), CONST PTR s AND int c AND size_t length)
+DEF(memcmp, int, (s1, s2, length),
+ CONST PTR s1 AND CONST PTR s2 AND size_t length)
+DEF(memcpy, PTR, (s1, s2, length), PTR s1 AND CONST PTR s2 AND size_t length)
+DEF(memmove, PTR, (s1, s2, length), PTR s1 AND CONST PTR s2 AND size_t length)
+DEF(memset, PTR, (s, val, length), PTR s AND int val AND size_t length )
+DEF(random, long int, (), NOTHING)
+DEF(rename, int, (f, t), char *f AND char *t)
+DEF(rindex, char*, (s, c), char *s AND int c)
+DEF(strcasecmp, int, (s1, s2), char *s1 AND char *s2)
+DEF(strncasecmp, int, (s1, s2, n), char *s1 AND char *s2 AND int n)
+DEF(strchr, char*, (s, c), CONST char *s AND int c)
+DEF(strdup, char*, (s1), char * s1)
+DEF(strrchr, char*, (s, c), CONST char *s AND int c)
+DEF(strstr, char*, (), NOTHING)
+DEF(strtod, double, (), NOTHING)
+DEF(strtol, long, (), NOTHING)
+DEF(strtoul, unsigned long, (), NOTHING)
+DEF(tmpnam, char *, (s), char * s)
+DEF(vfork, int, (), NOTHING)
+DEF(vfprintf, int, (), NOTHING)
+DEF(vprintf, int, (), NOTHING)
+DEF(vsprintf, int, (), NOTHING)
+DEF(sigsetmask, int, (), NOTHING)
+DEF(alloca, PTR, (size), size_t size)
+DEF(waitpid, int, (pid, statp, opts), int pid AND int* statp AND int opts )
+
+/* List of global variables that we want to look for in the host
+ environment, and to generate an entry NEED_<variable> in config.h
+ if they are not found. The first arg is the variable name, the
+ second arg is how to declare the variable, and the third is how to
+ use it. */
+
+DEFVAR(sys_nerr, int sys_nerr, sys_nerr = 0)
+DEFVAR(sys_errlist, char *sys_errlist[], sys_errlist[0] = 0)
+DEFVAR(sys_siglist, char *sys_siglist[], sys_siglist[0] = 0)
+
+/* List of global functions that we want to look for in the host
+ environment, and to generate an entry NEED_<funcname> in config.h
+ if they are not found. */
+
+DEFFUNC(strerror, char*, (), NOTHING)
+DEFFUNC(psignal, void, (signo, message), unsigned signo AND char *message)
+DEFFUNC(basename, char *, (name), CONST char *name)
+DEFFUNC(on_exit, void, (f, arg), void (*f)() AND char *arg)
diff --git a/contrib/gdb/libiberty/getcwd.c b/contrib/gdb/libiberty/getcwd.c
new file mode 100644
index 0000000..60c1dd8
--- /dev/null
+++ b/contrib/gdb/libiberty/getcwd.c
@@ -0,0 +1,52 @@
+/* Emulate getcwd using getwd.
+ This function is in the public domain. */
+
+/*
+NAME
+ getcwd -- get absolute pathname for current working directory
+
+SYNOPSIS
+ char *getcwd (char pathname[len], len)
+
+DESCRIPTION
+ Copy the absolute pathname for the current working directory into
+ the supplied buffer and return a pointer to the buffer. If the
+ current directory's path doesn't fit in LEN characters, the result
+ is NULL and errno is set.
+
+BUGS
+ Emulated via the getwd() call, which is reasonable for most
+ systems that do not have getcwd().
+
+*/
+
+#ifndef NO_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <errno.h>
+
+extern char *getwd ();
+extern int errno;
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+char *
+getcwd (buf, len)
+ char *buf;
+ int len;
+{
+ char ourbuf[MAXPATHLEN];
+ char *result;
+
+ result = getwd (ourbuf);
+ if (result) {
+ if (strlen (ourbuf) >= len) {
+ errno = ERANGE;
+ return 0;
+ }
+ strcpy (buf, ourbuf);
+ }
+ return buf;
+}
diff --git a/contrib/gdb/libiberty/getopt.c b/contrib/gdb/libiberty/getopt.c
new file mode 100644
index 0000000..458dca2
--- /dev/null
+++ b/contrib/gdb/libiberty/getopt.c
@@ -0,0 +1,757 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "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, 93, 94, 95
+ Free Software Foundation, Inc.
+
+This file is part of the libiberty library. This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+#if defined (emacs) || defined (CONFIG_BROKETS)
+/* We use <config.h> 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 <config.h>
+#else
+#include "config.h"
+#endif
+#endif
+
+#ifndef __STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ 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. */
+/* Many versions of the Linux C library include older, broken versions
+ of these routines, which will break the linker's command-line
+ parsing. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+#include <stdlib.h>
+#endif /* GNU C library. */
+
+/* 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.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg = NULL;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns EOF, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* XXX 1003.2 says this must be 1 before any call. */
+int optind = 0;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+#include <string.h>
+#define my_index strchr
+#else
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+char *getenv ();
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* 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 /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ 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.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns `EOF'.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ optarg = NULL;
+
+ if (optind == 0)
+ 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,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* 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. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return EOF;
+ }
+
+ /* 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'))
+ {
+ if (ordering == REQUIRE_ORDER)
+ return EOF;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ 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][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* 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 (nameend - nextchar == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ 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 = nameend + 1;
+ else
+ {
+ if (opterr)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ "%s: option `--%s' doesn't allow an argument\n",
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ "%s: option `%c%s' doesn't allow an argument\n",
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr, "%s: option `%s' requires an argument\n",
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ 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] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (opterr)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: option requires an argument -- %c\n",
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/gdb/libiberty/getopt1.c b/contrib/gdb/libiberty/getopt1.c
new file mode 100644
index 0000000..c3400e5
--- /dev/null
+++ b/contrib/gdb/libiberty/getopt1.c
@@ -0,0 +1,190 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ 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 Free Software Foundation; either version 2, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#if defined (emacs) || defined (CONFIG_BROKETS)
+/* We use <config.h> 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 <config.h>
+#else
+#include "config.h"
+#endif
+#endif
+
+#include "getopt.h"
+
+#ifndef __STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ 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. */
+/* Many versions of the Linux C library include older, broken versions
+ of these routines, which will break the linker's command-line
+ parsing. */
+
+#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
+
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#else
+char *getenv ();
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/contrib/gdb/libiberty/getpagesize.c b/contrib/gdb/libiberty/getpagesize.c
new file mode 100644
index 0000000..e9784b8
--- /dev/null
+++ b/contrib/gdb/libiberty/getpagesize.c
@@ -0,0 +1,89 @@
+/* Emulation of getpagesize() for systems that need it. */
+
+/*
+
+NAME
+
+ getpagesize -- return the number of bytes in page of memory
+
+SYNOPSIS
+
+ int getpagesize (void)
+
+DESCRIPTION
+
+ Returns the number of bytes in a page of memory. This is the
+ granularity of many of the system memory management routines.
+ No guarantee is made as to whether or not it is the same as the
+ basic memory management hardware page size.
+
+BUGS
+
+ Is intended as a reasonable replacement for systems where this
+ is not provided as a system call. The value of 4096 may or may
+ not be correct for the systems where it is returned as the default
+ value.
+
+*/
+
+#ifndef VMS
+
+#include <sys/types.h>
+#ifndef NO_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_SYSCONF
+#include <unistd.h>
+#define GNU_OUR_PAGESIZE sysconf(_SC_PAGESIZE)
+#else
+#ifdef PAGESIZE
+#define GNU_OUR_PAGESIZE PAGESIZE
+#else /* no PAGESIZE */
+#ifdef EXEC_PAGESIZE
+#define GNU_OUR_PAGESIZE EXEC_PAGESIZE
+#else /* no EXEC_PAGESIZE */
+#ifdef NBPG
+#define GNU_OUR_PAGESIZE (NBPG * CLSIZE)
+#ifndef CLSIZE
+#define CLSIZE 1
+#endif /* CLSIZE */
+#else /* no NBPG */
+#ifdef NBPC
+#define GNU_OUR_PAGESIZE NBPC
+#else /* no NBPC */
+#define GNU_OUR_PAGESIZE 4096 /* Just punt and use reasonable value */
+#endif /* NBPC */
+#endif /* NBPG */
+#endif /* EXEC_PAGESIZE */
+#endif /* PAGESIZE */
+#endif /* HAVE_SYSCONF */
+
+int
+getpagesize ()
+{
+ return (GNU_OUR_PAGESIZE);
+}
+
+#else /* VMS */
+
+#if 0 /* older distributions of gcc-vms are missing <syidef.h> */
+#include <syidef.h>
+#endif
+#ifndef SYI$_PAGE_SIZE /* VMS V5.4 and earlier didn't have this yet */
+#define SYI$_PAGE_SIZE 4452
+#endif
+extern unsigned long lib$getsyi(const unsigned short *,...);
+
+int getpagesize ()
+{
+ long pagsiz = 0L;
+ unsigned short itmcod = SYI$_PAGE_SIZE;
+
+ (void) lib$getsyi (&itmcod, (void *) &pagsiz);
+ if (pagsiz == 0L)
+ pagsiz = 512L; /* VAX default */
+ return (int) pagsiz;
+}
+
+#endif /* VMS */
diff --git a/contrib/gdb/libiberty/getruntime.c b/contrib/gdb/libiberty/getruntime.c
new file mode 100644
index 0000000..1be3b4c
--- /dev/null
+++ b/contrib/gdb/libiberty/getruntime.c
@@ -0,0 +1,82 @@
+/* Return time used so far, in microseconds.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+/* There are several ways to get elapsed execution time; unfortunately no
+ single way is available for all host systems, nor are there reliable
+ ways to find out which way is correct for a given host. */
+
+#include <time.h>
+
+/* These should go away when libiberty uses autoconf. */
+
+#if defined(__sun__) && !defined(__svr4__)
+#define HAVE_GETRUSAGE
+#endif
+
+#ifdef HAVE_SYSCONF
+#define HAVE_TIMES
+#endif
+
+#ifdef HAVE_GETRUSAGE
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_TIMES
+#ifndef NO_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <sys/times.h>
+#endif
+
+/* This is a fallback; if wrong, it will likely make obviously wrong
+ results. */
+
+#ifndef CLOCKS_PER_SEC
+#define CLOCKS_PER_SEC 1
+#endif
+
+long
+get_run_time ()
+{
+#ifdef HAVE_GETRUSAGE
+ struct rusage rusage;
+
+ getrusage (0, &rusage);
+ return (rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec
+ + rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec);
+#else /* ! HAVE_GETRUSAGE */
+#ifdef HAVE_TIMES
+ struct tms tms;
+
+ times (&tms);
+ return (tms.tms_utime + tms.tms_stime) * (1000000 / HZ);
+#else /* ! HAVE_TIMES */
+ /* Fall back on clock and hope it's correctly implemented. */
+ const long clocks_per_sec = CLOCKS_PER_SEC;
+ if (clocks_per_sec <= 1000000)
+ return clock () * (1000000 / clocks_per_sec);
+ else
+ return clock () / clocks_per_sec;
+#endif /* HAVE_TIMES */
+#endif /* HAVE_GETRUSAGE */
+}
diff --git a/contrib/gdb/libiberty/hex.c b/contrib/gdb/libiberty/hex.c
new file mode 100644
index 0000000..3a2eef0
--- /dev/null
+++ b/contrib/gdb/libiberty/hex.c
@@ -0,0 +1,33 @@
+/* Hex character manipulation support.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "libiberty.h"
+
+char _hex_value[_hex_array_size];
+
+void hex_init ()
+{
+ int i;
+ for (i = 0; i < _hex_array_size; i++)
+ _hex_value[i] = _hex_bad;
+ for (i = 0; i < 10; i++)
+ _hex_value['0' + i] = i;
+ for (i = 0; i < 6; i++)
+ _hex_value['a' + i] = _hex_value['A' + i] = 10 + i;
+}
diff --git a/contrib/gdb/libiberty/index.c b/contrib/gdb/libiberty/index.c
new file mode 100644
index 0000000..e5a00f5
--- /dev/null
+++ b/contrib/gdb/libiberty/index.c
@@ -0,0 +1,11 @@
+/* Stub implementation of (obsolete) index(). */
+
+extern char * strchr();
+
+char *
+index (s, c)
+ char *s;
+ int c;
+{
+ return strchr (s, c);
+}
diff --git a/contrib/gdb/libiberty/insque.c b/contrib/gdb/libiberty/insque.c
new file mode 100644
index 0000000..775019f
--- /dev/null
+++ b/contrib/gdb/libiberty/insque.c
@@ -0,0 +1,50 @@
+/* insque(3C) routines
+ This file is in the public domain. */
+
+/*
+NAME
+ insque, remque -- insert, remove an element from a queue
+
+SYNOPSIS
+ struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+ char q_data[];
+ };
+
+ void insque (struct qelem *elem, struct qelem *pred)
+
+ void remque (struct qelem *elem)
+
+DESCRIPTION
+ Routines to manipulate queues built from doubly linked lists.
+ The insque routine inserts ELEM in the queue immediately after
+ PRED. The remque routine removes ELEM from its containing queue.
+*/
+
+
+struct qelem {
+ struct qelem *q_forw;
+ struct qelem *q_back;
+};
+
+
+void
+insque (elem, pred)
+ struct qelem *elem;
+ struct qelem *pred;
+{
+ elem -> q_forw = pred -> q_forw;
+ pred -> q_forw -> q_back = elem;
+ elem -> q_back = pred;
+ pred -> q_forw = elem;
+}
+
+
+void
+remque (elem)
+ struct qelem *elem;
+{
+ elem -> q_forw -> q_back = elem -> q_back;
+ elem -> q_back -> q_forw = elem -> q_forw;
+}
diff --git a/contrib/gdb/libiberty/makefile.dos b/contrib/gdb/libiberty/makefile.dos
new file mode 100644
index 0000000..7eba62c
--- /dev/null
+++ b/contrib/gdb/libiberty/makefile.dos
@@ -0,0 +1,29 @@
+CFLAGS=-O2
+
+OBJS = \
+ argv.o \
+ basename.o \
+ concat.o \
+ cplus-dem.o \
+ fdmatch.o \
+ floatformat.o \
+ getopt.o \
+ getopt1.o \
+ getruntime.o \
+ hex.o \
+ msdos.o \
+ obstack.o \
+ spaces.o \
+ strerror.o \
+ strsignal.o \
+ xatexit.o \
+ xexit.o \
+ xmalloc.o \
+ $E
+
+.c.o:
+ gcc -I../include $(CFLAGS) -c $<
+
+libiberty.a : $(OBJS)
+ -rm libiberty.a
+ ar rvs libiberty.a $(OBJS)
diff --git a/contrib/gdb/libiberty/memchr.c b/contrib/gdb/libiberty/memchr.c
new file mode 100644
index 0000000..93ef43d
--- /dev/null
+++ b/contrib/gdb/libiberty/memchr.c
@@ -0,0 +1,60 @@
+/*
+FUNCTION
+ <<memchr>>---find character in memory
+
+INDEX
+ memchr
+
+ANSI_SYNOPSIS
+ #include <string.h>
+ void *memchr(const void *<[src]>, int <[c]>, size_t <[length]>);
+
+TRAD_SYNOPSIS
+ #include <string.h>
+ void *memchr(<[src]>, <[c]>, <[length]>)
+ void *<[src]>;
+ void *<[c]>;
+ size_t <[length]>;
+
+DESCRIPTION
+ This function searches memory starting at <<*<[src]>>> for the
+ character <[c]>. The search only ends with the first
+ occurrence of <[c]>, or after <[length]> characters; in
+ particular, <<NULL>> does not terminate the search.
+
+RETURNS
+ If the character <[c]> is found within <[length]> characters
+ of <<*<[src]>>>, a pointer to the character is returned. If
+ <[c]> is not found, then <<NULL>> is returned.
+
+PORTABILITY
+<<memchr>> requires no supporting OS subroutines.
+
+QUICKREF
+ memchr ansi pure
+
+*/
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+PTR
+memchr (src_void, c, length)
+ register CONST PTR src_void;
+ int c;
+ size_t length;
+{
+ CONST unsigned char *src = (CONST unsigned char *)src_void;
+
+ while (--length >= 0)
+ {
+ if (*src == c)
+ return (PTR)src;
+ src++;
+ }
+ return NULL;
+}
diff --git a/contrib/gdb/libiberty/memcmp.c b/contrib/gdb/libiberty/memcmp.c
new file mode 100644
index 0000000..127ae0c
--- /dev/null
+++ b/contrib/gdb/libiberty/memcmp.c
@@ -0,0 +1,38 @@
+/* memcmp -- compare two memory regions.
+ This function is in the public domain. */
+
+/*
+NAME
+ memcmp -- compare two memory regions
+
+SYNOPSIS
+ int memcmp (const void *from, const void *to, size_t count)
+
+DESCRIPTION
+ Compare two memory regions and return less than,
+ equal to, or greater than zero, according to lexicographical
+ ordering of the compared regions.
+*/
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+int
+DEFUN(memcmp, (str1, str2, count),
+ const PTR str1 AND const PTR str2 AND size_t count)
+{
+ register unsigned char *s1 = (unsigned char*)str1;
+ register unsigned char *s2 = (unsigned char*)str2;
+
+ while (count-- > 0)
+ {
+ if (*s1++ != *s2++)
+ return s1[-1] < s2[-1] ? -1 : 1;
+ }
+ return 0;
+}
+
diff --git a/contrib/gdb/libiberty/memcpy.c b/contrib/gdb/libiberty/memcpy.c
new file mode 100644
index 0000000..c28208a0
--- /dev/null
+++ b/contrib/gdb/libiberty/memcpy.c
@@ -0,0 +1,28 @@
+/* memcpy (the standard C function)
+ This function is in the public domain. */
+
+/*
+NAME
+ memcpy -- copy memory regions of arbitary length
+
+SYNOPSIS
+ void* memcpy (void *out, const void *in, size_t n);
+
+DESCRIPTION
+ Copy LENGTH bytes from memory region pointed to by IN to memory
+ region pointed to by OUT.
+*/
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+PTR
+DEFUN(memcpy, (out, in, length), PTR out AND CONST PTR in AND size_t length)
+{
+ bcopy(in, out, length);
+ return out;
+}
diff --git a/contrib/gdb/libiberty/memmove.c b/contrib/gdb/libiberty/memmove.c
new file mode 100644
index 0000000..818fc24
--- /dev/null
+++ b/contrib/gdb/libiberty/memmove.c
@@ -0,0 +1,18 @@
+/* Wrapper to implement ANSI C's memmove using BSD's bcopy. */
+/* This function is in the public domain. --Per Bothner. */
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+PTR
+memmove (s1, s2, n)
+ PTR s1;
+ CONST PTR s2;
+ size_t n;
+{
+ bcopy (s2, s1, n);
+ return s1;
+}
diff --git a/contrib/gdb/libiberty/memset.c b/contrib/gdb/libiberty/memset.c
new file mode 100644
index 0000000..5f54831
--- /dev/null
+++ b/contrib/gdb/libiberty/memset.c
@@ -0,0 +1,19 @@
+/* memset
+ This implementation is in the public domain. */
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+PTR
+DEFUN(memset, (dest, val, len),
+ PTR dest AND register int val AND register size_t len)
+{
+ register unsigned char *ptr = (unsigned char*)dest;
+ while (len-- > 0)
+ *ptr++ = val;
+ return dest;
+}
diff --git a/contrib/gdb/libiberty/mpw-config.in b/contrib/gdb/libiberty/mpw-config.in
new file mode 100644
index 0000000..829d8e7
--- /dev/null
+++ b/contrib/gdb/libiberty/mpw-config.in
@@ -0,0 +1,9 @@
+# MPW configuration fragment for libiberty.
+
+forward-include "{srcdir}"alloca-norm.h alloca-conf.h
+
+Echo '/* config.h. Generated by mpw-configure. */' > "{o}"config.new
+
+MoveIfChange "{o}"config.new "{o}"config.h
+
+
diff --git a/contrib/gdb/libiberty/mpw-make.sed b/contrib/gdb/libiberty/mpw-make.sed
new file mode 100644
index 0000000..f99eb1a
--- /dev/null
+++ b/contrib/gdb/libiberty/mpw-make.sed
@@ -0,0 +1,49 @@
+# Sed commands to finish translating libiberty's Unix makefile to MPW syntax.
+
+# Comment out a useless thing.
+/^\.always\./s/^/#/
+
+# Replace the auto-generated list with the list of what we know we need.
+s/`cat needed-list`/"{o}"alloca.c.o "{o}"bcopy.c.o "{o}"getpagesize.c.o "{o}"insque.c.o "{o}"mpw.c.o "{o}"strcasecmp.c.o "{o}"strdup.c.o "{o}"strncasecmp.c.o/
+
+# Paste in some desirable definitions.
+/^###$/a\
+\
+HDEFINES = -d NEED_sys_siglist -d NEED_sys_errlist -d NEED_basename -d NEED_strcasecmp -d NEED_strncasecmp\
+INCLUDES = -i : -i {INCDIR}: -i {INCDIR}:mpw: -i ::extra-include: -i "{s}"\
+\
+.c.o \\Option-f .c\
+ {CC} {DepDir}{Default}.c {LIBCFLAGS} {INCLUDES} {HDEFINES} @SEGMENT_FLAG@ -o {TargDir}{Default}.c.o\
+
+# Remove dependency on needed-list, which we don't use.
+/DO_ALSO =/s/needed-list//
+
+/INCDIR=/s/"{srcdir}"{MULTISRCTOP}::/"{topsrcdir}"/
+
+# Whack out the COMPILE.c trickiness.
+/^COMPILE.c /,/^$/d
+
+# Remove the multido trickiness from the "all" target.
+/^all \\Option-f/,/^$/c\
+all \\Option-f {TARGETLIB}\
+
+
+# Remove the RULE1/RULE2 crud.
+/if \[/,/fi/d
+/^RULE1 =/,/RULE2 =/d
+/RULE2/s/RULE2/TARGETLIB/
+
+# Don't want fdmatch ever.
+s/ "{o}"fdmatch.c.o//
+
+# Fix paths to generated files.
+/config.h/s/"{s}"config.h/"{o}"config.h/
+
+# Whack out config rebuild rules.
+/^"{o}"config.h \\Option-f/,/^$/d
+
+
+
+
+
+
diff --git a/contrib/gdb/libiberty/mpw.c b/contrib/gdb/libiberty/mpw.c
new file mode 100644
index 0000000..b93e100
--- /dev/null
+++ b/contrib/gdb/libiberty/mpw.c
@@ -0,0 +1,1010 @@
+/* MPW-Unix compatibility library.
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This should only be compiled and linked under MPW. */
+
+#include "mpw.h"
+
+#include <stdlib.h>
+
+#ifndef USE_MW_HEADERS
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+#include <Types.h>
+#include <Files.h>
+
+#include <Timer.h>
+
+/* Initialize to 0 at first, then set to errno_max() later. */
+
+int sys_nerr = 0;
+
+/* Debug flag for pathname hacking. Set this to one and rebuild. */
+
+int DebugPI = 0;
+
+void
+mpwify_filename(char *unixname, char *macname)
+{
+ int i, j, in_middle, terminate = 0;
+
+ /* (should truncate 255 chars from end of name, not beginning) */
+ if (strlen (unixname) > 255)
+ {
+ fprintf (stderr, "Pathname \"%s\" is too long for Macs, truncating\n",
+ unixname);
+ terminate = 1;
+ }
+ /* Abs Unix path to abs Mac path. */
+ if (*unixname == '/')
+ {
+ if (strncmp (unixname, "/tmp/", 5) == 0)
+ {
+ /* A temporary name, make a more Mac-flavored tmpname. */
+ /* A better choice would be {Boot}Trash:foo, but that would
+ require being able to identify the boot disk's and trashcan's
+ name. Another option would be to have an env var, so user
+ can point it at a ramdisk. */
+ strncpy (macname, unixname, 255);
+ if (terminate)
+ macname[255] = '\0';
+ macname[0] = ':';
+ macname[4] = '_';
+ }
+ else
+ {
+ /* Assume that the leading component is a valid disk name. */
+ strncpy (macname, unixname + 1, 255);
+ }
+ }
+ else
+ {
+ /* If this is a "Unix-only" pathname, assume relative. */
+ if (strchr (unixname, '/') && ! strchr (unixname, ':'))
+ {
+ macname[0] = ':';
+ strncpy (macname + 1, unixname, 255);
+ }
+ else
+ {
+ /* Otherwise copy it verbatim. */
+ /* ... but if of the form ":/foo", lose the extra colon;
+ the slash will be made into a colon shortly. */
+ if (unixname[0] == ':' && unixname[1] == '/')
+ ++unixname;
+ strncpy (macname, unixname, 255);
+ }
+ }
+ if (terminate)
+ macname[255] = '\0';
+ for (i = 0; macname[i] != '\0'; ++i)
+ {
+ if (macname[i] == '/')
+ macname[i] = ':';
+ }
+ in_middle = 0;
+ j = 0;
+ for (i = 0; macname[i] != '\0'; ++i)
+ {
+ /* We're in the middle of the name when a char is not a colon. */
+ if (macname[i] != ':')
+ in_middle = 1;
+ /* Copy chars verbatim, *unless* the char is the first of a pair
+ of colons in the middle of a pathname. */
+ if (!(in_middle && macname[i] == ':' && macname[i+1] == ':'))
+ macname[j++] = macname[i];
+ }
+ macname[j] = '\0';
+ /* If we have a trailing ":.", make it into a ":". */
+ if (j >= 2 && macname[j-2] == ':' && macname[j-1] == '.')
+ macname[j-1] = '\0';
+ if (DebugPI)
+ {
+ fprintf (stderr, "# Made \"%s\"\n", unixname);
+ fprintf (stderr, "# into \"%s\"\n", macname);
+ }
+}
+
+/* MPW-flavored basename finder. */
+
+char *
+mpw_basename (name)
+ char *name;
+{
+ char *base = name;
+
+ while (*name)
+ {
+ if (*name++ == ':')
+ {
+ base = name;
+ }
+ }
+ return base;
+}
+
+/* Mixed MPW/Unix basename finder. This can be led astray by
+ filenames with slashes in them and come up with a basename that
+ either corresponds to no file or (worse) to some other file, so
+ should only be tried if other methods of finding a file via a
+ basename have failed. */
+
+char *
+mpw_mixed_basename (name)
+ char *name;
+{
+ char *base = name;
+
+ while (*name)
+ {
+ if (*name == '/' || *name == ':')
+ {
+ base = name + 1;
+ }
+ ++name;
+ }
+ return base;
+}
+
+/* This function is fopen() modified to create files that are type TEXT
+ or 'BIN ', and always of type 'MPS '. */
+
+FILE *
+mpw_fopen (char *name, char *mode)
+{
+#undef fopen
+ int errnum;
+ FILE *fp;
+ char tmpname[256];
+
+ mpwify_filename (name, tmpname);
+ PROGRESS (1);
+ fp = fopen (tmpname, mode);
+ errnum = errno;
+
+ /* If writing, need to set type and creator usefully. */
+ if (strchr (mode, 'w'))
+ {
+ char *pname = (char *) malloc (strlen (tmpname) + 2);
+ OSErr e;
+ struct FInfo fi;
+
+ pname[0] = strlen (tmpname);
+ strcpy (pname+1, tmpname);
+
+ e = GetFInfo ((ConstStr255Param) pname, 0, &fi);
+ /* should do spiffier error handling */
+ if (e != 0)
+ fprintf(stderr, "GetFInfo returns %d\n", e);
+ if (strchr (mode, 'b'))
+ {
+ fi.fdType = (OSType) 'BIN ';
+ }
+ else
+ {
+ fi.fdType = (OSType) 'TEXT';
+ }
+ fi.fdCreator = (OSType) 'MPS ';
+ e = SetFInfo ((ConstStr255Param) pname, 0, &fi);
+ if (e != 0)
+ fprintf(stderr, "SetFInfo returns %d\n", e);
+ free (pname);
+ }
+ if (fp == NULL)
+ errno = errnum;
+ return fp;
+}
+
+/* This is a version of fseek() modified to fill the file with zeros
+ if seeking past the end of it. */
+
+#define ZEROBLKSIZE 4096
+
+char zeros[ZEROBLKSIZE];
+
+int
+mpw_fseek (FILE *fp, int offset, int whence)
+{
+#undef fseek
+ int cursize, numleft;
+
+ PROGRESS (1);
+ if (whence == SEEK_SET)
+ {
+ fseek (fp, 0, SEEK_END);
+ cursize = ftell (fp);
+ if (offset > cursize)
+ {
+ numleft = offset - cursize;
+ while (numleft > ZEROBLKSIZE)
+ {
+ /* This might fail, should check for that. */
+ PROGRESS (1);
+ fwrite (zeros, 1, ZEROBLKSIZE, fp);
+ numleft -= ZEROBLKSIZE;
+ }
+ PROGRESS (1);
+ fwrite (zeros, 1, numleft, fp);
+ fflush (fp);
+ }
+ }
+ return fseek (fp, offset, whence);
+}
+
+int
+mpw_fread (char *ptr, int size, int nitems, FILE *stream)
+{
+#undef fread
+ int rslt;
+
+ PROGRESS (1);
+ rslt = fread (ptr, size, nitems, stream);
+ PROGRESS (1);
+ return rslt;
+}
+
+int
+mpw_fwrite (char *ptr, int size, int nitems, FILE *stream)
+{
+#undef fwrite
+ int rslt;
+
+ PROGRESS (1);
+ rslt = fwrite (ptr, size, nitems, stream);
+ PROGRESS (1);
+ return rslt;
+}
+
+int
+link ()
+{
+ fprintf (stderr, "link not available!\n");
+ mpw_abort ();
+}
+
+int
+fork ()
+{
+ fprintf (stderr, "fork not available!\n");
+ mpw_abort ();
+}
+
+int
+vfork ()
+{
+ fprintf (stderr, "vfork not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+int
+pipe (int *fd)
+{
+ fprintf (stderr, "pipe not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+#ifndef USE_MW_HEADERS
+int
+execvp (char *file, char **argv)
+{
+ fprintf (stderr, "execvp not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+int
+execv (char *path, char **argv)
+{
+ fprintf (stderr, "execv not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+#endif
+
+int
+kill (int pid, int sig)
+{
+ fprintf (stderr, "kill not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+int
+wait (int *status)
+{
+ *status = 0;
+ return 0;
+}
+
+#ifndef USE_MW_HEADERS
+int
+sleep (int seconds)
+{
+ unsigned long start_time, now;
+
+ time (&start_time);
+
+ while (1)
+ {
+ PROGRESS (1);
+ time (&now);
+ if (now > start_time + seconds)
+ return 0;
+ }
+}
+#endif
+
+void
+putenv (char *str)
+{
+ /* The GCC driver calls this to do things for collect2, but we
+ don't care about collect2. */
+}
+
+int
+chmod (char *path, int mode)
+{
+ /* Pretend it was all OK. */
+ return 0;
+}
+
+#ifndef USE_MW_HEADERS
+int
+getuid ()
+{
+ /* One value is as good as another... */
+ return 0;
+}
+
+int
+getgid ()
+{
+ /* One value is as good as another... */
+ return 0;
+}
+#endif
+
+/* Instead of coredumping, which is not a normal Mac facility, we
+ drop into Macsbug. If we then "g" from Macsbug, the program will
+ exit cleanly. */
+
+void
+mpw_abort ()
+{
+ /* Make sure no output still buffered up, then zap into MacsBug. */
+ fflush(stdout);
+ fflush(stderr);
+ printf("## Abort! ##\n");
+#ifdef MPW_SADE
+ SysError(8005);
+#else
+ Debugger();
+#endif
+ /* "g" in MacsBug will then cause a regular error exit. */
+ exit (1);
+}
+
+/* Imitation getrusage based on the ANSI clock() function. */
+
+int
+getrusage (int who, struct rusage *rusage)
+{
+ int clk = clock ();
+
+#if 0
+ rusage->ru_utime.tv_sec = clk / CLOCKS_PER_SEC;
+ rusage->ru_utime.tv_usec = ((clk * 1000) / CLOCKS_PER_SEC) * 1000;
+ rusage->ru_stime.tv_sec = 0;
+ rusage->ru_stime.tv_usec = 0;
+#endif
+}
+
+int
+sbrk ()
+{
+ return 0;
+}
+
+#ifndef USE_MW_HEADERS
+int
+isatty (int fd)
+{
+ return 0;
+}
+
+/* This is inherited from Timothy Murray's Posix library. */
+
+#include "utime.h"
+
+int
+utime (char *filename, struct utimbuf *times)
+{
+ CInfoPBRec cipbr;
+ HFileInfo *fpb = (HFileInfo *) &cipbr;
+ DirInfo *dpb = (DirInfo *) &cipbr;
+ unsigned char pname[256];
+ short err;
+
+ strcpy ((char *) pname, filename);
+ c2pstr (pname);
+
+ dpb->ioDrDirID = 0L;
+ fpb->ioNamePtr = pname;
+ fpb->ioVRefNum = 0;
+ fpb->ioFDirIndex = 0;
+ fpb->ioFVersNum = 0;
+ err = PBGetCatInfo (&cipbr, 0);
+ if (err != noErr) {
+ errno = ENOENT;
+ return -1;
+ }
+ dpb->ioDrDirID = 0L;
+ fpb->ioFlMdDat = times->modtime;
+ fpb->ioFlCrDat = times->actime;
+ err = PBSetCatInfo (&cipbr, 0);
+ if (err != noErr) {
+ errno = EACCES;
+ return -1;
+ }
+ return 0;
+}
+
+int
+mkdir (char *path, int mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+rmdir ()
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+chown ()
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+char *myenviron[] = {NULL};
+
+char **environ = myenviron;
+
+#ifndef USE_MW_HEADERS
+
+/* Minimal 'stat' emulation: tells directories from files and
+ gives length and mtime.
+
+ Derived from code written by Guido van Rossum, CWI, Amsterdam
+ and placed by him in the public domain. */
+
+extern int __uid, __gid;
+
+int __uid = 0;
+int __gid = 0;
+
+/* Bits in ioFlAttrib: */
+#define LOCKBIT (1<<0) /* File locked */
+#define DIRBIT (1<<4) /* It's a directory */
+
+/* Macified "stat" in which filename is given relative to a directory,
+ specified by long DirID. */
+
+static int
+_stat (char *name, long dirid, struct stat *buf)
+{
+ CInfoPBRec cipbr;
+ HFileInfo *fpb = (HFileInfo*) &cipbr;
+ DirInfo *dpb = (DirInfo*) &cipbr;
+ Str255 pname;
+ short err;
+
+ /* Make a temp copy of the name and pascalize. */
+ strcpy ((char *) pname, name);
+ c2pstr (pname);
+
+ cipbr.dirInfo.ioDrDirID = dirid;
+ cipbr.hFileInfo.ioNamePtr = pname;
+ cipbr.hFileInfo.ioVRefNum = 0;
+ cipbr.hFileInfo.ioFDirIndex = 0;
+ cipbr.hFileInfo.ioFVersNum = 0;
+ err = PBGetCatInfo (&cipbr, 0);
+ if (err != noErr)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+ /* Mac files are readable if they can be accessed at all. */
+ buf->st_mode = 0444;
+ /* Mark unlocked files as writeable. */
+ if (!(fpb->ioFlAttrib & LOCKBIT))
+ buf->st_mode |= 0222;
+ if (fpb->ioFlAttrib & DIRBIT)
+ {
+ /* Mark directories as "executable". */
+ buf->st_mode |= 0111 | S_IFDIR;
+ buf->st_size = dpb->ioDrNmFls;
+ buf->st_rsize = 0;
+ }
+ else
+ {
+ buf->st_mode |= S_IFREG;
+ /* Mark apps as "executable". */
+ if (fpb->ioFlFndrInfo.fdType == 'APPL')
+ buf->st_mode |= 0111;
+ /* Fill in the sizes of data and resource forks. */
+ buf->st_size = fpb->ioFlLgLen;
+ buf->st_rsize = fpb->ioFlRLgLen;
+ }
+ /* Fill in various times. */
+ buf->st_atime = fpb->ioFlCrDat;
+ buf->st_mtime = fpb->ioFlMdDat;
+ buf->st_ctime = fpb->ioFlCrDat;
+ /* Set up an imitation inode number. */
+ buf->st_ino = (unsigned short) fpb->ioDirID;
+ /* Set up an imitation device. */
+ GetVRefNum (buf->st_ino, &buf->st_dev);
+ buf->st_uid = __uid;
+ buf->st_gid = __gid;
+/* buf->st_FlFndrInfo = fpb->ioFlFndrInfo; */
+ return 0;
+}
+
+/* stat() sets up an empty dirid. */
+
+int
+stat (char *path, struct stat *buf)
+{
+ long rslt, errnum;
+ char tmpname[256];
+
+ mpwify_filename (path, tmpname);
+ if (DebugPI)
+ fprintf (stderr, "# stat (%s, %x)", tmpname, buf);
+ PROGRESS (1);
+ rslt = _stat (tmpname, 0L, buf);
+ errnum = errno;
+ if (DebugPI)
+ {
+ fprintf (stderr, " -> %d", rslt);
+ if (rslt != 0)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+ if (rslt != 0)
+ errno = errnum;
+ return rslt;
+}
+
+int
+fstat (int fd, struct stat *buf)
+{
+ FCBPBRec fcb;
+ FILE *fp;
+ Str255 pathname;
+ long dirid = 0L, temp;
+ long rslt, errnum;
+ short err;
+
+ if (DebugPI)
+ fprintf (stderr, "# fstat (%d, %x)", fd, buf);
+ PROGRESS (1);
+ pathname[0] = 0;
+#ifdef FIOFNAME
+ /* Use an MPW-specific ioctl to get the pathname associated with
+ the file descriptor. */
+ ioctl (fd, FIOFNAME, (long *) pathname);
+#else
+ you lose
+#endif
+ if (DebugPI)
+ fprintf (stderr, " (name is %s)", pathname);
+ dirid = 0L /* fcb.ioFCBParID */ ;
+ rslt = _stat ((char *) pathname, dirid, buf);
+ errnum = errno;
+ if (DebugPI)
+ {
+ fprintf (stderr, " -> %d", rslt);
+ if (rslt != 0)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+ if (rslt != 0)
+ errno = errnum;
+ return rslt;
+}
+
+#endif /* n USE_MW_HEADERS */
+
+chdir ()
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+char *
+getcwd (char *buf, int size)
+{
+ if (buf == NULL)
+ buf = (char *) malloc (size);
+ strcpy(buf, ":");
+ return buf;
+}
+
+/* This should probably be more elaborate for MPW. */
+
+char *
+getpwd ()
+{
+ return ":";
+}
+
+int
+mpw_open (char *filename, int arg2, int arg3)
+{
+#undef open
+ int fd, errnum = 0;
+ char tmpname[256];
+
+ mpwify_filename (filename, tmpname);
+ fd = open (tmpname, arg2);
+ errnum = errno;
+
+ if (DebugPI)
+ {
+ fprintf (stderr, "# open (%s, %d, %d)", tmpname, arg2, arg3);
+ fprintf (stderr, " -> %d", fd);
+ if (fd == -1)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ }
+ if (fd == -1)
+ errno = errnum;
+ return fd;
+}
+
+int
+mpw_access (char *filename, unsigned int cmd)
+{
+#undef access
+
+ int rslt, errnum = 0;
+ struct stat st;
+ char tmpname[256];
+
+ mpwify_filename (filename, tmpname);
+ if (cmd & R_OK || cmd & X_OK)
+ {
+ rslt = stat (tmpname, &st);
+ errnum = errno;
+ if (rslt >= 0)
+ {
+ if (((st.st_mode & 004 == 0) && (cmd & R_OK))
+ || ((st.st_mode & 002 == 0) && (cmd & W_OK))
+ || ((st.st_mode & 001 == 0) && (cmd & X_OK)))
+ {
+ rslt = -1;
+ errnum = EACCES;
+ }
+ }
+ }
+ if (DebugPI)
+ {
+ fprintf (stderr, "# mpw_access (%s, %d)", tmpname, cmd);
+ fprintf (stderr, " -> %d", rslt);
+ if (rslt != 0)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ }
+ if (rslt != 0)
+ errno = errnum;
+ return rslt;
+}
+
+/* The MPW library creat() has no mode argument. */
+
+int
+mpw_creat (char *path, /* mode_t */ int mode)
+{
+#undef creat
+
+#ifdef USE_MW_HEADERS
+ return creat (path, mode);
+#else
+ return creat (path);
+#endif
+}
+
+/* This is a hack to get control in an MPW tool before it crashes the
+ machine. */
+
+mpw_special_init (name)
+ char *name;
+{
+ if (strstr (name, "DEBUG"))
+ DebugStr("\pat beginning of program");
+}
+
+static int current_umask;
+
+int
+umask(int mask)
+{
+ int oldmask = current_umask;
+
+ current_umask = mask;
+ return oldmask;
+}
+
+/* Cursor-spinning stuff that includes metering of spin rate and delays. */
+
+/* Nonzero when cursor spinning has been set up properly. */
+
+int cursor_inited;
+
+/* Nonzero if spin should be measured and excessive delays reported. */
+
+int measure_spin;
+
+/* Nonzero if spin histogram and rate data should be written out. */
+
+int dump_spin_data;
+
+long warning_threshold = 400000;
+
+long bucket_size = 1024;
+
+long bucket_power = 10;
+
+long numbuckets = 300;
+
+int *delay_counts;
+
+int overflow_count;
+
+char *current_progress;
+
+static UnsignedWide last_microseconds;
+
+static char *last_spin_file = "";
+
+static int last_spin_line;
+
+void
+warn_if_spin_delay (char *file, int line)
+{
+ long diff, ix;
+ UnsignedWide now;
+
+ Microseconds(&now);
+
+ diff = now.lo - last_microseconds.lo;
+
+ if (diff > warning_threshold)
+ fprintf (stderr, "# %s: %ld.%06ld sec delay getting from %s:%d to %s:%d\n",
+ (current_progress ? current_progress : ""),
+ diff / 1000000, diff % 1000000,
+ last_spin_file, last_spin_line, file, line);
+ if (dump_spin_data)
+ {
+ if (diff >= 0)
+ {
+ ix = diff >> bucket_power;
+ if (ix >= 0 && ix < numbuckets && delay_counts != NULL)
+ ++delay_counts[ix];
+ else
+ ++overflow_count;
+ }
+ else
+ fprintf (stderr, "raw diff is %ld (?)\n", diff);
+ }
+}
+
+void
+record_for_spin_delay (char *file, int line)
+{
+ Microseconds (&last_microseconds);
+ last_spin_file = file;
+ last_spin_line = line;
+}
+
+void
+mpw_start_progress (char *str, int n, char *file, int line)
+{
+ int i;
+ char *measure, *threshold;
+
+ if (!cursor_inited)
+ {
+ InitCursorCtl (nil);
+ cursor_inited = 1;
+ record_for_spin_delay (file, line);
+ measure = getenv ("MEASURE_SPIN");
+ if (measure != NULL && measure[0] != '\0')
+ {
+ measure_spin = 1;
+ if (strcmp (measure, "all") == 0)
+ dump_spin_data = 1;
+ }
+ threshold = getenv ((const char *) "SPIN_WARN_THRESHOLD");
+ if (threshold != NULL && threshold[0] != '\0')
+ warning_threshold = atol (threshold);
+ if (dump_spin_data)
+ {
+ if (delay_counts == NULL)
+ delay_counts = (int *) malloc (numbuckets * sizeof (int));
+ for (i = 0; i < numbuckets; ++i)
+ delay_counts[i] = 0;
+ overflow_count = 0;
+ }
+ }
+ current_progress = str;
+
+ sys_nerr = errno_max ();
+
+ mpw_special_init (str);
+}
+
+void
+mpw_progress (int n)
+{
+ SpinCursor (32);
+}
+
+void
+mpw_progress_measured (int n, char *file, int line)
+{
+ if (measure_spin)
+ warn_if_spin_delay (file, line);
+ SpinCursor (32);
+ if (measure_spin)
+ record_for_spin_delay (file, line);
+}
+
+void
+mpw_end_progress (char *str, char *file, int line)
+{
+ long i, delay, count = 0, sum = 0, avgdelay, spinrate;
+ long curpower = 0, curgroup = 0;
+
+ /* Warn if it's been a while since the last spin. */
+ if (measure_spin)
+ warn_if_spin_delay (file, line);
+
+ /* Dump all the nonzero delay counts and an approximation of the delay. */
+ if (dump_spin_data && delay_counts != NULL)
+ {
+ for (i = 0; i < numbuckets; ++i)
+ {
+ delay = (i + 1) * bucket_size;
+ sum += delay_counts[i] * (i + 1);
+ count += delay_counts[i];
+ if (delay <= (1 << curpower))
+ {
+ curgroup += delay_counts[i];
+ }
+ else
+ {
+ if (curgroup > 0)
+ fprintf (stderr,
+ "# %s: %d delays between %ld.%06ld and %ld.%06ld sec\n",
+ (str ? str : ""),
+ curgroup,
+ (1 << curpower) / 1000000,
+ (1 << curpower) % 1000000,
+ (1 << (curpower + 1)) / 1000000,
+ (1 << (curpower + 1)) % 1000000);
+ ++curpower;
+ curgroup = 0;
+ }
+ }
+ if (count > 0)
+ {
+ avgdelay = (sum * bucket_size) / count;
+ spinrate = 1000000 / avgdelay;
+ fprintf (stderr, "# %s: Average spin rate is %d times/sec\n",
+ (str ? str : ""), spinrate);
+ }
+ }
+}
+
+#ifdef PROGRESS_TEST
+
+/* Test program. */
+
+main ()
+{
+ int i, j;
+ double x = 1.0, y = 2.4;
+ long start = Microseconds (), tm; FIXME
+
+ START_PROGRESS ("hi", 0);
+
+ for (i = 0; i < 1000; ++i)
+ {
+ PROGRESS (1);
+
+ for (j = 0; j < (i * 100); ++j)
+ {
+ x += (x * y) / j;
+ }
+ }
+
+ END_PROGRESS ("hi");
+
+ tm = Microseconds () - start;
+
+ printf ("Total time is %d.%d secs\n", tm / 1000000, tm % 1000000);
+}
+
+#endif
+
+#ifdef USE_MW_HEADERS
+/* Empty definitions for Metrowerks' SIOUX console library. */
+
+#ifndef __CONSOLE__
+#include <console.h>
+#endif
+
+short
+InstallConsole(short fd)
+{
+#pragma unused (fd)
+ return 0;
+}
+
+void
+RemoveConsole(void)
+{
+}
+
+long
+WriteCharsToConsole(char *buf, long n)
+{
+#pragma unused (buf, n)
+ return 0;
+}
+
+long ReadCharsFromConsole(char *buf, long n)
+{
+#pragma unused (buf, n)
+ return 0;
+}
+
+extern char *
+__ttyname(long fd)
+{
+ static char *__devicename = "null device";
+
+ if (fd >= 0 && fd <= 2)
+ return (__devicename);
+ return NULL;
+}
+
+#endif
diff --git a/contrib/gdb/libiberty/msdos.c b/contrib/gdb/libiberty/msdos.c
new file mode 100644
index 0000000..923e64d
--- /dev/null
+++ b/contrib/gdb/libiberty/msdos.c
@@ -0,0 +1,15 @@
+char msg[] = "No vfork available - aborting\n";
+vfork()
+{
+ write(1, msg, sizeof(msg));
+}
+
+sigsetmask()
+{
+ /* no signals support in go32 (yet) */
+}
+
+waitpid()
+{
+ return -1;
+}
diff --git a/contrib/gdb/libiberty/obstack.c b/contrib/gdb/libiberty/obstack.c
new file mode 100644
index 0000000..2d38094
--- /dev/null
+++ b/contrib/gdb/libiberty/obstack.c
@@ -0,0 +1,507 @@
+/* obstack.c - subroutines used implicitly by object stack macros
+ Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 96 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
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with this program; if not, write to the Free Software
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "obstack.h"
+
+/* This is just to get __GNU_LIBRARY__ defined. */
+#include <stdio.h>
+
+/* Comment out all this code if we are using the GNU C Library, and are not
+ actually compiling the library itself. This code is part of the GNU C
+ Library, but also included in many other GNU distributions. Compiling
+ and linking in this code is a waste when using the GNU C library
+ (especially if it is a shared library). Rather than having every GNU
+ 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__
+#define POINTER void *
+#else
+#define POINTER char *
+#endif
+
+/* Determine default alignment. */
+struct fooalign {char x; double d;};
+#define DEFAULT_ALIGNMENT \
+ ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0))
+/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
+ But in fact it might be less smart and round addresses to as much as
+ DEFAULT_ROUNDING. So we prepare for it to do that. */
+union fooround {long x; double d;};
+#define DEFAULT_ROUNDING (sizeof (union fooround))
+
+/* When we copy a long block of data, this is the unit to do it with.
+ On some machines, copying successive ints does not work;
+ in such a case, redefine COPYING_UNIT to `long' (if that works)
+ or `char' as a last resort. */
+#ifndef COPYING_UNIT
+#define COPYING_UNIT int
+#endif
+
+/* The non-GNU-C macros copy the obstack into this global variable
+ to avoid multiple evaluation. */
+
+struct obstack *_obstack;
+
+/* Define a macro that either calls functions with the traditional malloc/free
+ calling interface, or calls functions with the mmalloc/mfree interface
+ (that adds an extra first argument), based on the state of use_extra_arg.
+ For free, do not use ?:, since some compilers, like the MIPS compilers,
+ do not allow (expr) ? void : void. */
+
+#define CALL_CHUNKFUN(h, size) \
+ (((h) -> use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+ do { \
+ if ((h) -> use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(h)->freefun) ((old_chunk)); \
+ } while (0)
+
+
+/* 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.
+
+ 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;
+ int alignment;
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+{
+ register struct _obstack_chunk* chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ 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;
+}
+
+int
+_obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
+ struct obstack *h;
+ int size;
+ int alignment;
+ POINTER (*chunkfun) ();
+ void (*freefun) ();
+ POINTER arg;
+{
+ register struct _obstack_chunk* chunk; /* points to new chunk */
+
+ if (alignment == 0)
+ alignment = DEFAULT_ALIGNMENT;
+ if (size == 0)
+ /* Default size is what GNU malloc can fit in a 4096-byte block. */
+ {
+ /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
+ Use the values for range checking, because if range checking is off,
+ the extra bytes won't be missed terribly, but if range checking is on
+ and we used a larger request, a whole extra 4096 bytes would be
+ allocated.
+
+ These number are irrelevant to the new GNU malloc. I suspect it is
+ less sensitive to the size of the request. */
+ int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ + 4 + DEFAULT_ROUNDING - 1)
+ & ~(DEFAULT_ROUNDING - 1));
+ size = 4096 - extra;
+ }
+
+ h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
+ h->freefun = freefun;
+ h->chunk_size = size;
+ h->alignment_mask = alignment - 1;
+ h->extra_arg = 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
+ on the assumption that LENGTH bytes need to be added
+ to the current object, or a new object of length LENGTH allocated.
+ Copies any partial object from the end of the old chunk
+ to the beginning of the new one. */
+
+void
+_obstack_newchunk (h, length)
+ struct obstack *h;
+ int length;
+{
+ register struct _obstack_chunk* old_chunk = h->chunk;
+ register struct _obstack_chunk* new_chunk;
+ register long new_size;
+ register int obj_size = h->next_free - h->object_base;
+ register int i;
+ int already;
+
+ /* Compute size for new chunk. */
+ new_size = (obj_size + length) + (obj_size >> 3) + 100;
+ if (new_size < h->chunk_size)
+ new_size = h->chunk_size;
+
+ /* Allocate and initialize the new chunk. */
+ 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;
+
+ /* Move the existing object to the new chunk.
+ Word at a time is fast and is safe if the object
+ is sufficiently aligned. */
+ if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
+ {
+ for (i = obj_size / sizeof (COPYING_UNIT) - 1;
+ i >= 0; i--)
+ ((COPYING_UNIT *)new_chunk->contents)[i]
+ = ((COPYING_UNIT *)h->object_base)[i];
+ /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
+ but that can cross a page boundary on a machine
+ which does not do strict alignment for COPYING_UNITS. */
+ already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
+ }
+ else
+ already = 0;
+ /* Copy remaining bytes one by one. */
+ for (i = already; i < obj_size; i++)
+ new_chunk->contents[i] = h->object_base[i];
+
+ /* If the object just copied was the only data in OLD_CHUNK,
+ free that chunk and remove it from the chain.
+ But not if that chunk might contain an empty object. */
+ if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
+ {
+ new_chunk->prev = old_chunk->prev;
+ CALL_FREEFUN (h, old_chunk);
+ }
+
+ h->object_base = new_chunk->contents;
+ h->next_free = h->object_base + obj_size;
+ /* The new chunk certainly contains no empty object yet. */
+ h->maybe_empty_object = 0;
+}
+
+/* Return nonzero if object OBJ has been allocated from obstack H.
+ This is here for debugging.
+ If you use it in a program, you are probably losing. */
+
+#ifdef __STDC__
+/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
+ obstack.h because it is just for debugging. */
+int _obstack_allocated_p (struct obstack *h, POINTER obj);
+#endif
+
+int
+_obstack_allocated_p (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = (h)->chunk;
+ /* We use >= rather than > since the object cannot be exactly at
+ the beginning of the chunk but might be an empty object exactly
+ at the end of an adjacent chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp->prev;
+ lp = plp;
+ }
+ return lp != 0;
+}
+
+/* Free objects in obstack H, including OBJ and everything allocate
+ more recently than OBJ. If OBJ is zero, free everything in H. */
+
+#undef obstack_free
+
+/* This function has two names with identical definitions.
+ This is the first one, called from non-ANSI code. */
+
+void
+_obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = h->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp->prev;
+ CALL_FREEFUN (h, lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ if (lp)
+ {
+ h->object_base = h->next_free = (char *)(obj);
+ h->chunk_limit = lp->limit;
+ h->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+/* This function is used from ANSI code. */
+
+void
+obstack_free (h, obj)
+ struct obstack *h;
+ POINTER obj;
+{
+ register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk* plp; /* point to previous chunk if any */
+
+ lp = h->chunk;
+ /* We use >= because there cannot be an object at the beginning of a chunk.
+ But there can be an empty object at that address
+ at the end of another chunk. */
+ while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ {
+ plp = lp->prev;
+ CALL_FREEFUN (h, lp);
+ lp = plp;
+ /* If we switch chunks, we can't tell whether the new current
+ chunk contains an empty object, so assume that it may. */
+ h->maybe_empty_object = 1;
+ }
+ if (lp)
+ {
+ h->object_base = h->next_free = (char *)(obj);
+ h->chunk_limit = lp->limit;
+ h->chunk = lp;
+ }
+ else if (obj != 0)
+ /* obj is not in any of the chunks! */
+ abort ();
+}
+
+int
+_obstack_memory_used (h)
+ struct obstack *h;
+{
+ register struct _obstack_chunk* lp;
+ register int nbytes = 0;
+
+ for (lp = h->chunk; lp != 0; lp = lp->prev)
+ {
+ nbytes += lp->limit - (char *) lp;
+ }
+ return nbytes;
+}
+
+#if 0
+/* These are now turned off because the applications do not use it
+ and it uses bcopy via obstack_grow, which causes trouble on sysV. */
+
+/* Now define the functional versions of the obstack macros.
+ Define them to simply use the corresponding macros to do the job. */
+
+#ifdef __STDC__
+/* These function definitions do not work with non-ANSI preprocessors;
+ they won't pass through the macro names in parentheses. */
+
+/* The function names appear in parentheses in order to prevent
+ the macro-definitions of the names from being expanded there. */
+
+POINTER (obstack_base) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_base (obstack);
+}
+
+POINTER (obstack_next_free) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_next_free (obstack);
+}
+
+int (obstack_object_size) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_object_size (obstack);
+}
+
+int (obstack_room) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_room (obstack);
+}
+
+void (obstack_grow) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow (obstack, pointer, length);
+}
+
+void (obstack_grow0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ obstack_grow0 (obstack, pointer, length);
+}
+
+void (obstack_1grow) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow (obstack, character);
+}
+
+void (obstack_blank) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank (obstack, length);
+}
+
+void (obstack_1grow_fast) (obstack, character)
+ struct obstack *obstack;
+ int character;
+{
+ obstack_1grow_fast (obstack, character);
+}
+
+void (obstack_blank_fast) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ obstack_blank_fast (obstack, length);
+}
+
+POINTER (obstack_finish) (obstack)
+ struct obstack *obstack;
+{
+ return obstack_finish (obstack);
+}
+
+POINTER (obstack_alloc) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_alloc (obstack, length);
+}
+
+POINTER (obstack_copy) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy (obstack, pointer, length);
+}
+
+POINTER (obstack_copy0) (obstack, pointer, length)
+ struct obstack *obstack;
+ POINTER pointer;
+ int length;
+{
+ return obstack_copy0 (obstack, pointer, length);
+}
+
+#endif /* __STDC__ */
+
+#endif /* 0 */
+
+#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/contrib/gdb/libiberty/random.c b/contrib/gdb/libiberty/random.c
new file mode 100644
index 0000000..e205719
--- /dev/null
+++ b/contrib/gdb/libiberty/random.c
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * This is derived from the Berkeley source:
+ * @(#)random.c 5.5 (Berkeley) 7/6/88
+ * It was reworked for the GNU C Library by Roland McGrath.
+ */
+
+#include <errno.h>
+
+#if 0
+
+#include <ansidecl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#else
+
+#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF for 32-bits */
+#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF for 32-bits*/
+
+#ifdef __STDC__
+# define PTR void *
+# define NULL (void *) 0
+#else
+# define PTR char *
+# define NULL 0
+#endif
+
+#endif
+
+long int random ();
+
+/* An improved random number generation package. In addition to the standard
+ rand()/srand() like interface, this package also has a special state info
+ interface. The initstate() routine is called with a seed, an array of
+ bytes, and a count of how many bytes are being passed in; this array is
+ then initialized to contain information for random number generation with
+ that much state information. Good sizes for the amount of state
+ information are 32, 64, 128, and 256 bytes. The state can be switched by
+ calling the setstate() function with the same array as was initiallized
+ with initstate(). By default, the package runs with 128 bytes of state
+ information and generates far better random numbers than a linear
+ congruential generator. If the amount of state information is less than
+ 32 bytes, a simple linear congruential R.N.G. is used. Internally, the
+ state information is treated as an array of longs; the zeroeth element of
+ the array is the type of R.N.G. being used (small integer); the remainder
+ of the array is the state information for the R.N.G. Thus, 32 bytes of
+ state information will give 7 longs worth of state information, which will
+ allow a degree seven polynomial. (Note: The zeroeth word of state
+ information also has some other information stored in it; see setstate
+ for details). The random number generation technique is a linear feedback
+ shift register approach, employing trinomials (since there are fewer terms
+ to sum up that way). In this approach, the least significant bit of all
+ the numbers in the state table will act as a linear feedback shift register,
+ and will have period 2^deg - 1 (where deg is the degree of the polynomial
+ being used, assuming that the polynomial is irreducible and primitive).
+ The higher order bits will have longer periods, since their values are
+ also influenced by pseudo-random carries out of the lower bits. The
+ total period of the generator is approximately deg*(2**deg - 1); thus
+ doubling the amount of state information has a vast influence on the
+ period of the generator. Note: The deg*(2**deg - 1) is an approximation
+ only good for large deg, when the period of the shift register is the
+ dominant factor. With deg equal to seven, the period is actually much
+ longer than the 7*(2**7 - 1) predicted by this formula. */
+
+
+
+/* For each of the currently supported random number generators, we have a
+ break value on the amount of state information (you need at least thi
+ bytes of state info to support this random number generator), a degree for
+ the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ separation between the two lower order coefficients of the trinomial. */
+
+/* Linear congruential. */
+#define TYPE_0 0
+#define BREAK_0 8
+#define DEG_0 0
+#define SEP_0 0
+
+/* x**7 + x**3 + 1. */
+#define TYPE_1 1
+#define BREAK_1 32
+#define DEG_1 7
+#define SEP_1 3
+
+/* x**15 + x + 1. */
+#define TYPE_2 2
+#define BREAK_2 64
+#define DEG_2 15
+#define SEP_2 1
+
+/* x**31 + x**3 + 1. */
+#define TYPE_3 3
+#define BREAK_3 128
+#define DEG_3 31
+#define SEP_3 3
+
+/* x**63 + x + 1. */
+#define TYPE_4 4
+#define BREAK_4 256
+#define DEG_4 63
+#define SEP_4 1
+
+
+/* Array versions of the above information to make code run faster.
+ Relies on fact that TYPE_i == i. */
+
+#define MAX_TYPES 5 /* Max number of types above. */
+
+static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static int seps[MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+
+
+/* Initially, everything is set up as if from:
+ initstate(1, randtbl, 128);
+ Note that this initialization takes advantage of the fact that srandom
+ advances the front and rear pointers 10*rand_deg times, and hence the
+ rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ element of the state information, which contains info about the current
+ position of the rear pointer is just
+ (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */
+
+static long int randtbl[DEG_3 + 1] =
+ { TYPE_3,
+ 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342,
+ 0xde3b81e0, 0xdf0a6fb5, 0xf103bc02, 0x48f340fb,
+ 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+ 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86,
+ 0xda672e2a, 0x1588ca88, 0xe369735d, 0x904f35f7,
+ 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+ 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b,
+ 0xf5ad9d0e, 0x8999220b, 0x27fb47b9
+ };
+
+/* FPTR and RPTR are two pointers into the state info, a front and a rear
+ pointer. These two pointers are always rand_sep places aparts, as they
+ cycle through the state information. (Yes, this does mean we could get
+ away with just one pointer, but the code for random is more efficient
+ this way). The pointers are left positioned as they would be from the call:
+ initstate(1, randtbl, 128);
+ (The position of the rear pointer, rptr, is really 0 (as explained above
+ in the initialization of randtbl) because the state table pointer is set
+ to point to randtbl[1] (as explained below).) */
+
+static long int *fptr = &randtbl[SEP_3 + 1];
+static long int *rptr = &randtbl[1];
+
+
+
+/* The following things are the pointer to the state information table,
+ the type of the current generator, the degree of the current polynomial
+ being used, and the separation between the two pointers.
+ Note that for efficiency of random, we remember the first location of
+ the state information, not the zeroeth. Hence it is valid to access
+ state[-1], which is used to store the type of the R.N.G.
+ Also, we remember the last location, since this is more efficient than
+ indexing every time to find the address of the last element to see if
+ the front and rear pointers have wrapped. */
+
+static long int *state = &randtbl[1];
+
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+
+static long int *end_ptr = &randtbl[sizeof(randtbl) / sizeof(randtbl[0])];
+
+/* Initialize the random number generator based on the given seed. If the
+ type is the trivial no-state-information type, just remember the seed.
+ Otherwise, initializes state[] based on the given "seed" via a linear
+ congruential generator. Then, the pointers are set to known locations
+ that are exactly rand_sep places apart. Lastly, it cycles the state
+ information a given number of times to get rid of any initial dependencies
+ introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
+ for default usage relies on values produced by this routine. */
+void
+srandom (x)
+ unsigned int x;
+{
+ state[0] = x;
+ if (rand_type != TYPE_0)
+ {
+ register long int i;
+ for (i = 1; i < rand_deg; ++i)
+ state[i] = (1103515145 * state[i - 1]) + 12345;
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+ for (i = 0; i < 10 * rand_deg; ++i)
+ random();
+ }
+}
+
+/* Initialize the state information in the given array of N bytes for
+ future random number generation. Based on the number of bytes we
+ are given, and the break values for the different R.N.G.'s, we choose
+ the best (largest) one we can and set things up for it. srandom is
+ then called to initialize the state information. Note that on return
+ from srandom, we set state[-1] to be the type multiplexed with the current
+ value of the rear pointer; this is so successive calls to initstate won't
+ lose this information and will be able to restart with setstate.
+ Note: The first thing we do is save the current state, if any, just like
+ setstate so that it doesn't matter when initstate is called.
+ Returns a pointer to the old state. */
+PTR
+initstate (seed, arg_state, n)
+ unsigned int seed;
+ PTR arg_state;
+ unsigned long n;
+{
+ PTR ostate = (PTR) &state[-1];
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+ if (n < BREAK_1)
+ {
+ if (n < BREAK_0)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+ rand_type = TYPE_0;
+ rand_deg = DEG_0;
+ rand_sep = SEP_0;
+ }
+ else if (n < BREAK_2)
+ {
+ rand_type = TYPE_1;
+ rand_deg = DEG_1;
+ rand_sep = SEP_1;
+ }
+ else if (n < BREAK_3)
+ {
+ rand_type = TYPE_2;
+ rand_deg = DEG_2;
+ rand_sep = SEP_2;
+ }
+ else if (n < BREAK_4)
+ {
+ rand_type = TYPE_3;
+ rand_deg = DEG_3;
+ rand_sep = SEP_3;
+ }
+ else
+ {
+ rand_type = TYPE_4;
+ rand_deg = DEG_4;
+ rand_sep = SEP_4;
+ }
+
+ state = &((long int *) arg_state)[1]; /* First location. */
+ /* Must set END_PTR before srandom. */
+ end_ptr = &state[rand_deg];
+ srandom(seed);
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+
+ return ostate;
+}
+
+/* Restore the state from the given state array.
+ Note: It is important that we also remember the locations of the pointers
+ in the current state information, and restore the locations of the pointers
+ from the old state information. This is done by multiplexing the pointer
+ location into the zeroeth word of the state information. Note that due
+ to the order in which things are done, it is OK to call setstate with the
+ same state as the current state
+ Returns a pointer to the old state information. */
+
+PTR
+setstate (arg_state)
+ PTR arg_state;
+{
+ register long int *new_state = (long int *) arg_state;
+ register int type = new_state[0] % MAX_TYPES;
+ register int rear = new_state[0] / MAX_TYPES;
+ PTR ostate = (PTR) &state[-1];
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = (MAX_TYPES * (rptr - state)) + rand_type;
+
+ switch (type)
+ {
+ case TYPE_0:
+ case TYPE_1:
+ case TYPE_2:
+ case TYPE_3:
+ case TYPE_4:
+ rand_type = type;
+ rand_deg = degrees[type];
+ rand_sep = seps[type];
+ break;
+ default:
+ /* State info munged. */
+ errno = EINVAL;
+ return NULL;
+ }
+
+ state = &new_state[1];
+ if (rand_type != TYPE_0)
+ {
+ rptr = &state[rear];
+ fptr = &state[(rear + rand_sep) % rand_deg];
+ }
+ /* Set end_ptr too. */
+ end_ptr = &state[rand_deg];
+
+ return ostate;
+}
+
+/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
+ same in all ther other cases due to all the global variables that have been
+ set up. The basic operation is to add the number at the rear pointer into
+ the one at the front pointer. Then both pointers are advanced to the next
+ location cyclically in the table. The value returned is the sum generated,
+ reduced to 31 bits by throwing away the "least random" low bit.
+ Note: The code takes advantage of the fact that both the front and
+ rear pointers can't wrap on the same call by not testing the rear
+ pointer if the front one has wrapped. Returns a 31-bit random number. */
+
+long int
+random ()
+{
+ if (rand_type == TYPE_0)
+ {
+ state[0] = ((state[0] * 1103515245) + 12345) & LONG_MAX;
+ return state[0];
+ }
+ else
+ {
+ long int i;
+ *fptr += *rptr;
+ /* Chucking least random bit. */
+ i = (*fptr >> 1) & LONG_MAX;
+ ++fptr;
+ if (fptr >= end_ptr)
+ {
+ fptr = state;
+ ++rptr;
+ }
+ else
+ {
+ ++rptr;
+ if (rptr >= end_ptr)
+ rptr = state;
+ }
+ return i;
+ }
+}
diff --git a/contrib/gdb/libiberty/rename.c b/contrib/gdb/libiberty/rename.c
new file mode 100644
index 0000000..ae26e2d
--- /dev/null
+++ b/contrib/gdb/libiberty/rename.c
@@ -0,0 +1,22 @@
+/* rename -- rename a file
+ This function is in the public domain. */
+
+/* Rename a file. */
+
+#include <errno.h>
+
+int
+rename (zfrom, zto)
+ char *zfrom;
+ char *zto;
+{
+ if (link (zfrom, zto) < 0)
+ {
+ if (errno != EEXIST)
+ return -1;
+ if (unlink (zto) < 0
+ || link (zfrom, zto) < 0)
+ return -1;
+ }
+ return unlink (zfrom);
+}
diff --git a/contrib/gdb/libiberty/rindex.c b/contrib/gdb/libiberty/rindex.c
new file mode 100644
index 0000000..061d126
--- /dev/null
+++ b/contrib/gdb/libiberty/rindex.c
@@ -0,0 +1,11 @@
+/* Stub implementation of (obsolete) rindex(). */
+
+extern char *strrchr ();
+
+char *
+rindex (s, c)
+ char *s;
+ int c;
+{
+ return strrchr (s, c);
+}
diff --git a/contrib/gdb/libiberty/sigsetmask.c b/contrib/gdb/libiberty/sigsetmask.c
new file mode 100644
index 0000000..2a09e6a
--- /dev/null
+++ b/contrib/gdb/libiberty/sigsetmask.c
@@ -0,0 +1,30 @@
+/* Version of sigsetmask.c
+ Written by Steve Chamberlain (sac@cygnus.com).
+ Contributed by Cygnus Support.
+ This file is in the public doamin. */
+
+/* Set the current signal mask to the set provided, and return the
+ previous value */
+
+#define _POSIX_SOURCE
+#include <ansidecl.h>
+/* Including <sys/types.h> seems to be needed by ISC. */
+#include <sys/types.h>
+#include <signal.h>
+
+#ifdef SIG_SETMASK
+int
+DEFUN(sigsetmask,(set),
+ int set)
+{
+ sigset_t new;
+ sigset_t old;
+
+ sigemptyset (&new);
+ if (set != 0) {
+ abort(); /* FIXME, we don't know how to translate old mask to new */
+ }
+ sigprocmask(SIG_SETMASK, &new, &old);
+ return 1; /* FIXME, we always return 1 as old value. */
+}
+#endif
diff --git a/contrib/gdb/libiberty/spaces.c b/contrib/gdb/libiberty/spaces.c
new file mode 100644
index 0000000..7ea8532
--- /dev/null
+++ b/contrib/gdb/libiberty/spaces.c
@@ -0,0 +1,71 @@
+/* Allocate memory region filled with spaces.
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/*
+
+NAME
+
+ spaces -- return a pointer to a buffer full of spaces
+
+SYNOPSIS
+
+ char *spaces (int count)
+
+DESCRIPTION
+
+ Returns a pointer to a memory region filled with the specified
+ number of spaces and null terminated. The returned pointer is
+ valid until at least the next call.
+
+BUGS
+
+*/
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+const char *
+spaces (count)
+ int count;
+{
+ register char *t;
+ static char *buf;
+ static int maxsize;
+ extern char *malloc ();
+ extern void free ();
+
+ if (count > maxsize)
+ {
+ if (buf)
+ {
+ free (buf);
+ }
+ buf = malloc (count + 1);
+ if (buf == (char *) 0)
+ return 0;
+ for (t = buf + count ; t != buf ; )
+ {
+ *--t = ' ';
+ }
+ maxsize = count;
+ buf[count] = '\0';
+ }
+ return (const char *) (buf + maxsize - count);
+}
+
diff --git a/contrib/gdb/libiberty/strcasecmp.c b/contrib/gdb/libiberty/strcasecmp.c
new file mode 100644
index 0000000..53387ca
--- /dev/null
+++ b/contrib/gdb/libiberty/strcasecmp.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific written prior permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c 5.5 (Berkeley) 11/24/87";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison. The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+int
+strcasecmp(s1, s2)
+ const char *s1, *s2;
+{
+ register unsigned char u1, u2;
+
+ for (;;) {
+ u1 = (unsigned char) *s1++;
+ u2 = (unsigned char) *s2++;
+ if (charmap[u1] != charmap[u2]) {
+ return charmap[u1] - charmap[u2];
+ }
+ if (u1 == '\0') {
+ return 0;
+ }
+ }
+}
+
diff --git a/contrib/gdb/libiberty/strchr.c b/contrib/gdb/libiberty/strchr.c
new file mode 100644
index 0000000..22976ce
--- /dev/null
+++ b/contrib/gdb/libiberty/strchr.c
@@ -0,0 +1,34 @@
+/* Portable version of strchr()
+ This function is in the public domain. */
+
+/*
+NAME
+ strchr -- return pointer to first occurance of a character
+
+SYNOPSIS
+ char *strchr (const char *s, int c)
+
+DESCRIPTION
+ Returns a pointer to the first occurance of character C in
+ string S, or a NULL pointer if no occurance is found.
+
+BUGS
+ Behavior when character is the null character is implementation
+ dependent.
+*/
+
+#include <ansidecl.h>
+
+char *
+strchr (s, c)
+ register CONST char *s;
+ int c;
+{
+ do {
+ if (*s == c)
+ {
+ return (char*)s;
+ }
+ } while (*s++);
+ return (0);
+}
diff --git a/contrib/gdb/libiberty/strdup.c b/contrib/gdb/libiberty/strdup.c
new file mode 100644
index 0000000..1785b34
--- /dev/null
+++ b/contrib/gdb/libiberty/strdup.c
@@ -0,0 +1,10 @@
+char *
+strdup(s)
+ char *s;
+{
+ char *result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
diff --git a/contrib/gdb/libiberty/strerror.c b/contrib/gdb/libiberty/strerror.c
new file mode 100644
index 0000000..9f3f92b
--- /dev/null
+++ b/contrib/gdb/libiberty/strerror.c
@@ -0,0 +1,829 @@
+/* Extended support for using errno values.
+ Written by Fred Fish. fnf@cygnus.com
+ This file is in the public domain. --Per Bothner. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include "config.h"
+
+#ifndef NEED_sys_errlist
+/* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
+ might declare sys_errlist in a way that the compiler might consider
+ incompatible with our later declaration, perhaps by using const
+ attributes. So we hide the declaration in errno.h (if any) using a
+ macro. */
+#define sys_errlist sys_errlist__
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef NEED_sys_errlist
+#undef sys_errlist
+#endif
+
+/* Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+#include <stddef.h>
+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__ */
+extern char *malloc (); /* Standard memory allocater */
+extern char *memset ();
+#endif /* __STDC__ */
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* Translation table for errno values. See intro(2) in most UNIX systems
+ Programmers Reference Manuals.
+
+ Note that this table is generally only accessed when it is used at runtime
+ to initialize errno name and message tables that are indexed by errno
+ value.
+
+ Not all of these errnos will exist on all systems. This table is the only
+ thing that should have to be updated as new error numbers are introduced.
+ It's sort of ugly, but at least its portable. */
+
+struct error_info
+{
+ int value; /* The numeric value from <errno.h> */
+ 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)
+ ENTRY(EPERM, "EPERM", "Not owner"),
+#endif
+#if defined (ENOENT)
+ ENTRY(ENOENT, "ENOENT", "No such file or directory"),
+#endif
+#if defined (ESRCH)
+ ENTRY(ESRCH, "ESRCH", "No such process"),
+#endif
+#if defined (EINTR)
+ ENTRY(EINTR, "EINTR", "Interrupted system call"),
+#endif
+#if defined (EIO)
+ ENTRY(EIO, "EIO", "I/O error"),
+#endif
+#if defined (ENXIO)
+ ENTRY(ENXIO, "ENXIO", "No such device or address"),
+#endif
+#if defined (E2BIG)
+ ENTRY(E2BIG, "E2BIG", "Arg list too long"),
+#endif
+#if defined (ENOEXEC)
+ ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
+#endif
+#if defined (EBADF)
+ ENTRY(EBADF, "EBADF", "Bad file number"),
+#endif
+#if defined (ECHILD)
+ ENTRY(ECHILD, "ECHILD", "No child processes"),
+#endif
+#if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */
+ ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
+#endif
+#if defined (EAGAIN)
+ ENTRY(EAGAIN, "EAGAIN", "No more processes"),
+#endif
+#if defined (ENOMEM)
+ ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
+#endif
+#if defined (EACCES)
+ ENTRY(EACCES, "EACCES", "Permission denied"),
+#endif
+#if defined (EFAULT)
+ ENTRY(EFAULT, "EFAULT", "Bad address"),
+#endif
+#if defined (ENOTBLK)
+ ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
+#endif
+#if defined (EBUSY)
+ ENTRY(EBUSY, "EBUSY", "Device busy"),
+#endif
+#if defined (EEXIST)
+ ENTRY(EEXIST, "EEXIST", "File exists"),
+#endif
+#if defined (EXDEV)
+ ENTRY(EXDEV, "EXDEV", "Cross-device link"),
+#endif
+#if defined (ENODEV)
+ ENTRY(ENODEV, "ENODEV", "No such device"),
+#endif
+#if defined (ENOTDIR)
+ ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
+#endif
+#if defined (EISDIR)
+ ENTRY(EISDIR, "EISDIR", "Is a directory"),
+#endif
+#if defined (EINVAL)
+ ENTRY(EINVAL, "EINVAL", "Invalid argument"),
+#endif
+#if defined (ENFILE)
+ ENTRY(ENFILE, "ENFILE", "File table overflow"),
+#endif
+#if defined (EMFILE)
+ ENTRY(EMFILE, "EMFILE", "Too many open files"),
+#endif
+#if defined (ENOTTY)
+ ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
+#endif
+#if defined (ETXTBSY)
+ ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
+#endif
+#if defined (EFBIG)
+ ENTRY(EFBIG, "EFBIG", "File too large"),
+#endif
+#if defined (ENOSPC)
+ ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
+#endif
+#if defined (ESPIPE)
+ ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
+#endif
+#if defined (EROFS)
+ ENTRY(EROFS, "EROFS", "Read-only file system"),
+#endif
+#if defined (EMLINK)
+ ENTRY(EMLINK, "EMLINK", "Too many links"),
+#endif
+#if defined (EPIPE)
+ ENTRY(EPIPE, "EPIPE", "Broken pipe"),
+#endif
+#if defined (EDOM)
+ ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
+#endif
+#if defined (ERANGE)
+ ENTRY(ERANGE, "ERANGE", "Math result not representable"),
+#endif
+#if defined (ENOMSG)
+ ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
+#endif
+#if defined (EIDRM)
+ ENTRY(EIDRM, "EIDRM", "Identifier removed"),
+#endif
+#if defined (ECHRNG)
+ ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
+#endif
+#if defined (EL2NSYNC)
+ ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
+#endif
+#if defined (EL3HLT)
+ ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
+#endif
+#if defined (EL3RST)
+ ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
+#endif
+#if defined (ELNRNG)
+ ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
+#endif
+#if defined (EUNATCH)
+ ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
+#endif
+#if defined (ENOCSI)
+ ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
+#endif
+#if defined (EL2HLT)
+ ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
+#endif
+#if defined (EDEADLK)
+ ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
+#endif
+#if defined (ENOLCK)
+ ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
+#endif
+#if defined (EBADE)
+ ENTRY(EBADE, "EBADE", "Invalid exchange"),
+#endif
+#if defined (EBADR)
+ ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
+#endif
+#if defined (EXFULL)
+ ENTRY(EXFULL, "EXFULL", "Exchange full"),
+#endif
+#if defined (ENOANO)
+ ENTRY(ENOANO, "ENOANO", "No anode"),
+#endif
+#if defined (EBADRQC)
+ ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
+#endif
+#if defined (EBADSLT)
+ ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
+#endif
+#if defined (EDEADLOCK)
+ ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
+#endif
+#if defined (EBFONT)
+ ENTRY(EBFONT, "EBFONT", "Bad font file format"),
+#endif
+#if defined (ENOSTR)
+ ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
+#endif
+#if defined (ENODATA)
+ ENTRY(ENODATA, "ENODATA", "No data available"),
+#endif
+#if defined (ETIME)
+ ENTRY(ETIME, "ETIME", "Timer expired"),
+#endif
+#if defined (ENOSR)
+ ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
+#endif
+#if defined (ENONET)
+ ENTRY(ENONET, "ENONET", "Machine is not on the network"),
+#endif
+#if defined (ENOPKG)
+ ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
+#endif
+#if defined (EREMOTE)
+ ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
+#endif
+#if defined (ENOLINK)
+ ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
+#endif
+#if defined (EADV)
+ ENTRY(EADV, "EADV", "Advertise error"),
+#endif
+#if defined (ESRMNT)
+ ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
+#endif
+#if defined (ECOMM)
+ ENTRY(ECOMM, "ECOMM", "Communication error on send"),
+#endif
+#if defined (EPROTO)
+ ENTRY(EPROTO, "EPROTO", "Protocol error"),
+#endif
+#if defined (EMULTIHOP)
+ ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
+#endif
+#if defined (EDOTDOT)
+ ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
+#endif
+#if defined (EBADMSG)
+ ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
+#endif
+#if defined (ENAMETOOLONG)
+ ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
+#endif
+#if defined (EOVERFLOW)
+ ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
+#endif
+#if defined (ENOTUNIQ)
+ ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
+#endif
+#if defined (EBADFD)
+ ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
+#endif
+#if defined (EREMCHG)
+ ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
+#endif
+#if defined (ELIBACC)
+ ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
+#endif
+#if defined (ELIBBAD)
+ ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
+#endif
+#if defined (ELIBSCN)
+ ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
+#endif
+#if defined (ELIBMAX)
+ ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
+#endif
+#if defined (ELIBEXEC)
+ ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
+#endif
+#if defined (EILSEQ)
+ ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
+#endif
+#if defined (ENOSYS)
+ ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
+#endif
+#if defined (ELOOP)
+ ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
+#endif
+#if defined (ERESTART)
+ ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
+#endif
+#if defined (ESTRPIPE)
+ ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
+#endif
+#if defined (ENOTEMPTY)
+ ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
+#endif
+#if defined (EUSERS)
+ ENTRY(EUSERS, "EUSERS", "Too many users"),
+#endif
+#if defined (ENOTSOCK)
+ ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
+#endif
+#if defined (EDESTADDRREQ)
+ ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
+#endif
+#if defined (EMSGSIZE)
+ ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
+#endif
+#if defined (EPROTOTYPE)
+ ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
+#endif
+#if defined (ENOPROTOOPT)
+ ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
+#endif
+#if defined (EPROTONOSUPPORT)
+ ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
+#endif
+#if defined (ESOCKTNOSUPPORT)
+ ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
+#endif
+#if defined (EOPNOTSUPP)
+ ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
+#endif
+#if defined (EPFNOSUPPORT)
+ ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
+#endif
+#if defined (EAFNOSUPPORT)
+ ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
+#endif
+#if defined (EADDRINUSE)
+ ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
+#endif
+#if defined (EADDRNOTAVAIL)
+ ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
+#endif
+#if defined (ENETDOWN)
+ ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
+#endif
+#if defined (ENETUNREACH)
+ ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
+#endif
+#if defined (ENETRESET)
+ ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
+#endif
+#if defined (ECONNABORTED)
+ ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
+#endif
+#if defined (ECONNRESET)
+ ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
+#endif
+#if defined (ENOBUFS)
+ ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
+#endif
+#if defined (EISCONN)
+ ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
+#endif
+#if defined (ENOTCONN)
+ ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
+#endif
+#if defined (ESHUTDOWN)
+ ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
+#endif
+#if defined (ETOOMANYREFS)
+ ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
+#endif
+#if defined (ETIMEDOUT)
+ ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
+#endif
+#if defined (ECONNREFUSED)
+ ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
+#endif
+#if defined (EHOSTDOWN)
+ ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
+#endif
+#if defined (EHOSTUNREACH)
+ ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
+#endif
+#if defined (EALREADY)
+ ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
+#endif
+#if defined (EINPROGRESS)
+ ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
+#endif
+#if defined (ESTALE)
+ ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
+#endif
+#if defined (EUCLEAN)
+ ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
+#endif
+#if defined (ENOTNAM)
+ ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
+#endif
+#if defined (ENAVAIL)
+ ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
+#endif
+#if defined (EISNAM)
+ ENTRY(EISNAM, "EISNAM", "Is a named type file"),
+#endif
+#if defined (EREMOTEIO)
+ ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
+#endif
+ ENTRY(0, NULL, NULL)
+};
+
+#ifdef EVMSERR
+/* This is not in the table, because the numeric value of EVMSERR (32767)
+ lies outside the range of sys_errlist[]. */
+static struct { int value; const char *name, *msg; }
+ evmserr = { EVMSERR, "EVMSERR", "VMS-specific error" };
+#endif
+
+/* Translation table allocated and initialized at runtime. Indexed by the
+ errno value to find the equivalent symbolic value. */
+
+static const char **error_names;
+static int num_error_names = 0;
+
+/* Translation table allocated and initialized at runtime, if it does not
+ already exist in the host environment. Indexed by the errno value to find
+ the descriptive string.
+
+ We don't export it for use in other modules because even though it has the
+ same name, it differs from other implementations in that it is dynamically
+ initialized rather than statically initialized. */
+
+#ifdef NEED_sys_errlist
+
+static int sys_nerr;
+static const char **sys_errlist;
+
+#else
+
+extern int sys_nerr;
+extern char *sys_errlist[];
+
+#endif
+
+
+/*
+
+NAME
+
+ init_error_tables -- initialize the name and message tables
+
+SYNOPSIS
+
+ static void init_error_tables ();
+
+DESCRIPTION
+
+ Using the error_table, which is initialized at compile time, generate
+ the error_names and the sys_errlist (if needed) tables, which are
+ indexed at runtime by a specific errno value.
+
+BUGS
+
+ The initialization of the tables may fail under low memory conditions,
+ in which case we don't do anything particularly useful, but we don't
+ bomb either. Who knows, it might succeed at a later point if we free
+ some memory in the meantime. In any case, the other routines know
+ how to deal with lack of a table after trying to initialize it. This
+ may or may not be considered to be a bug, that we don't specifically
+ warn about this particular failure mode.
+
+*/
+
+static void
+init_error_tables ()
+{
+ const struct error_info *eip;
+ int nbytes;
+
+ /* If we haven't already scanned the error_table once to find the maximum
+ errno value, then go find it now. */
+
+ if (num_error_names == 0)
+ {
+ for (eip = error_table; eip -> name != NULL; eip++)
+ {
+ if (eip -> value >= num_error_names)
+ {
+ num_error_names = eip -> value + 1;
+ }
+ }
+ }
+
+ /* Now attempt to allocate the error_names table, zero it out, and then
+ initialize it from the statically initialized error_table. */
+
+ if (error_names == NULL)
+ {
+ nbytes = num_error_names * sizeof (char *);
+ if ((error_names = (const char **) malloc (nbytes)) != NULL)
+ {
+ memset (error_names, 0, nbytes);
+ for (eip = error_table; eip -> name != NULL; eip++)
+ {
+ error_names[eip -> value] = eip -> name;
+ }
+ }
+ }
+
+#ifdef NEED_sys_errlist
+
+ /* Now attempt to allocate the sys_errlist table, zero it out, and then
+ initialize it from the statically initialized error_table. */
+
+ if (sys_errlist == NULL)
+ {
+ nbytes = num_error_names * sizeof (char *);
+ if ((sys_errlist = (const char **) malloc (nbytes)) != NULL)
+ {
+ memset (sys_errlist, 0, nbytes);
+ sys_nerr = num_error_names;
+ for (eip = error_table; eip -> name != NULL; eip++)
+ {
+ sys_errlist[eip -> value] = eip -> msg;
+ }
+ }
+ }
+
+#endif
+
+}
+
+/*
+
+NAME
+
+ errno_max -- return the max errno value
+
+SYNOPSIS
+
+ int errno_max ();
+
+DESCRIPTION
+
+ Returns the maximum errno value for which a corresponding symbolic
+ name or message is available. Note that in the case where
+ we use the sys_errlist supplied by the system, it is possible for
+ there to be more symbolic names than messages, or vice versa.
+ In fact, the manual page for perror(3C) explicitly warns that one
+ should check the size of the table (sys_nerr) before indexing it,
+ since new error codes may be added to the system before they are
+ added to the table. Thus sys_nerr might be smaller than value
+ implied by the largest errno value defined in <errno.h>.
+
+ We return the maximum value that can be used to obtain a meaningful
+ symbolic name or message.
+
+*/
+
+int
+errno_max ()
+{
+ int maxsize;
+
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+ maxsize = MAX (sys_nerr, num_error_names);
+ return (maxsize - 1);
+}
+
+#ifdef NEED_strerror
+
+/*
+
+NAME
+
+ strerror -- map an error number to an error message string
+
+SYNOPSIS
+
+ char *strerror (int errnoval)
+
+DESCRIPTION
+
+ Maps an errno number to an error message string, the contents of
+ which are implementation defined. On systems which have the external
+ variables sys_nerr and sys_errlist, these strings will be the same
+ as the ones used by perror().
+
+ If the supplied error number is within the valid range of indices
+ for the sys_errlist, but no message is available for the particular
+ error number, then returns the string "Error NUM", where NUM is the
+ error number.
+
+ If the supplied error number is not a valid index into sys_errlist,
+ returns NULL.
+
+ The returned string is only guaranteed to be valid only until the
+ next call to strerror.
+
+*/
+
+char *
+strerror (errnoval)
+ int errnoval;
+{
+ char *msg;
+ static char buf[32];
+
+#ifdef NEED_sys_errlist
+
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+
+#endif
+
+ if ((errnoval < 0) || (errnoval >= sys_nerr))
+ {
+#ifdef EVMSERR
+ if (errnoval == evmserr.value)
+ msg = evmserr.msg;
+ else
+#endif
+ /* Out of range, just return NULL */
+ msg = NULL;
+ }
+ else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
+ {
+ /* In range, but no sys_errlist or no entry at this index. */
+ sprintf (buf, "Error %d", errnoval);
+ msg = buf;
+ }
+ else
+ {
+ /* In range, and a valid message. Just return the message. */
+ msg = (char *) sys_errlist[errnoval];
+ }
+
+ return (msg);
+}
+
+#endif /* NEED_strerror */
+
+
+/*
+
+NAME
+
+ strerrno -- map an error number to a symbolic name string
+
+SYNOPSIS
+
+ const char *strerrno (int errnoval)
+
+DESCRIPTION
+
+ Given an error number returned from a system call (typically
+ returned in errno), returns a pointer to a string containing the
+ symbolic name of that error number, as found in <errno.h>.
+
+ If the supplied error number is within the valid range of indices
+ for symbolic names, but no name is available for the particular
+ error number, then returns the string "Error NUM", where NUM is
+ the error number.
+
+ If the supplied error number is not within the range of valid
+ indices, then returns NULL.
+
+BUGS
+
+ The contents of the location pointed to are only guaranteed to be
+ valid until the next call to strerrno.
+
+*/
+
+const char *
+strerrno (errnoval)
+ int errnoval;
+{
+ const char *name;
+ static char buf[32];
+
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+
+ if ((errnoval < 0) || (errnoval >= num_error_names))
+ {
+#ifdef EVMSERR
+ if (errnoval == evmserr.value)
+ name = evmserr.name;
+ else
+#endif
+ /* Out of range, just return NULL */
+ name = NULL;
+ }
+ else if ((error_names == NULL) || (error_names[errnoval] == NULL))
+ {
+ /* In range, but no error_names or no entry at this index. */
+ sprintf (buf, "Error %d", errnoval);
+ name = (const char *) buf;
+ }
+ else
+ {
+ /* In range, and a valid name. Just return the name. */
+ name = error_names[errnoval];
+ }
+
+ return (name);
+}
+
+/*
+
+NAME
+
+ strtoerrno -- map a symbolic errno name to a numeric value
+
+SYNOPSIS
+
+ int strtoerrno (char *name)
+
+DESCRIPTION
+
+ Given the symbolic name of a error number, map it to an errno value.
+ If no translation is found, returns 0.
+
+*/
+
+int
+strtoerrno (name)
+ const char *name;
+{
+ int errnoval = 0;
+
+ if (name != NULL)
+ {
+ if (error_names == NULL)
+ {
+ init_error_tables ();
+ }
+ for (errnoval = 0; errnoval < num_error_names; errnoval++)
+ {
+ if ((error_names[errnoval] != NULL) &&
+ (strcmp (name, error_names[errnoval]) == 0))
+ {
+ break;
+ }
+ }
+ if (errnoval == num_error_names)
+ {
+#ifdef EVMSERR
+ if (strcmp (name, evmserr.name) == 0)
+ errnoval = evmserr.value;
+ else
+#endif
+ errnoval = 0;
+ }
+ }
+ return (errnoval);
+}
+
+
+/* A simple little main that does nothing but print all the errno translations
+ if MAIN is defined and this file is compiled and linked. */
+
+#ifdef MAIN
+
+#include <stdio.h>
+
+int
+main ()
+{
+ int errn;
+ int errnmax;
+ const char *name;
+ char *msg;
+ char *strerror ();
+
+ errnmax = errno_max ();
+ printf ("%d entries in names table.\n", num_error_names);
+ printf ("%d entries in messages table.\n", sys_nerr);
+ printf ("%d is max useful index.\n", errnmax);
+
+ /* Keep printing values until we get to the end of *both* tables, not
+ *either* table. Note that knowing the maximum useful index does *not*
+ relieve us of the responsibility of testing the return pointer for
+ NULL. */
+
+ for (errn = 0; errn <= errnmax; errn++)
+ {
+ name = strerrno (errn);
+ name = (name == NULL) ? "<NULL>" : name;
+ msg = strerror (errn);
+ msg = (msg == NULL) ? "<NULL>" : msg;
+ printf ("%-4d%-18s%s\n", errn, name, msg);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/contrib/gdb/libiberty/strncasecmp.c b/contrib/gdb/libiberty/strncasecmp.c
new file mode 100644
index 0000000..4485cac
--- /dev/null
+++ b/contrib/gdb/libiberty/strncasecmp.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific written prior permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c 5.5 (Berkeley) 11/24/87";
+#endif /* LIBC_SCCS and not lint */
+
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison. The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+ '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+};
+
+int
+strncasecmp(s1, s2, n)
+ const char *s1, *s2;
+ register size_t n;
+{
+ register unsigned char u1, u2;
+
+ for (; n != 0; --n) {
+ u1 = (unsigned char) *s1++;
+ u2 = (unsigned char) *s2++;
+ if (charmap[u1] != charmap[u2]) {
+ return charmap[u1] - charmap[u2];
+ }
+ if (u1 == '\0') {
+ return 0;
+ }
+ }
+ return 0;
+}
diff --git a/contrib/gdb/libiberty/strrchr.c b/contrib/gdb/libiberty/strrchr.c
new file mode 100644
index 0000000..30f9e8a
--- /dev/null
+++ b/contrib/gdb/libiberty/strrchr.c
@@ -0,0 +1,34 @@
+/* Portable version of strrchr().
+ This function is in the public domain. */
+
+/*
+NAME
+ strrchr -- return pointer to last occurance of a character
+
+SYNOPSIS
+ char *strrchr (const char *s, int c)
+
+DESCRIPTION
+ Returns a pointer to the last occurance of character C in
+ string S, or a NULL pointer if no occurance is found.
+
+BUGS
+ Behavior when character is the null character is implementation
+ dependent.
+*/
+
+#include <ansidecl.h>
+
+char *
+strrchr (s, c)
+ register CONST char *s;
+ int c;
+{
+ char *rtnval = 0;
+
+ do {
+ if (*s == c)
+ rtnval = (char*) s;
+ } while (*s++);
+ return (rtnval);
+}
diff --git a/contrib/gdb/libiberty/strsignal.c b/contrib/gdb/libiberty/strsignal.c
new file mode 100644
index 0000000..c4dd63c
--- /dev/null
+++ b/contrib/gdb/libiberty/strsignal.c
@@ -0,0 +1,627 @@
+/* Extended support for using signal values.
+ Written by Fred Fish. fnf@cygnus.com
+ This file is in the public domain. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include "config.h"
+
+#ifdef LOSING_SYS_SIGLIST
+#define sys_siglist no_such_symbol
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+
+/* Routines imported from standard C runtime libraries. */
+
+#ifdef __STDC__
+#include <stddef.h>
+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__ */
+extern char *malloc (); /* Standard memory allocater */
+extern char *memset ();
+#endif /* __STDC__ */
+
+#ifdef LOSING_SYS_SIGLIST
+#undef sys_siglist
+#endif
+
+
+#ifndef NULL
+# ifdef __STDC__
+# define NULL (void *) 0
+# else
+# define NULL 0
+# endif
+#endif
+
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+/* Translation table for signal values.
+
+ Note that this table is generally only accessed when it is used at runtime
+ to initialize signal name and message tables that are indexed by signal
+ value.
+
+ Not all of these signals will exist on all systems. This table is the only
+ thing that should have to be updated as new signal numbers are introduced.
+ It's sort of ugly, but at least its portable. */
+
+struct signal_info
+{
+ int value; /* The numeric value from <signal.h> */
+ 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)
+ ENTRY(SIGHUP, "SIGHUP", "Hangup"),
+#endif
+#if defined (SIGINT)
+ ENTRY(SIGINT, "SIGINT", "Interrupt"),
+#endif
+#if defined (SIGQUIT)
+ ENTRY(SIGQUIT, "SIGQUIT", "Quit"),
+#endif
+#if defined (SIGILL)
+ ENTRY(SIGILL, "SIGILL", "Illegal instruction"),
+#endif
+#if defined (SIGTRAP)
+ 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)
+ ENTRY(SIGIOT, "SIGIOT", "IOT trap"),
+#endif
+#if defined (SIGABRT)
+ ENTRY(SIGABRT, "SIGABRT", "Aborted"),
+#endif
+#if defined (SIGEMT)
+ ENTRY(SIGEMT, "SIGEMT", "Emulation trap"),
+#endif
+#if defined (SIGFPE)
+ ENTRY(SIGFPE, "SIGFPE", "Arithmetic exception"),
+#endif
+#if defined (SIGKILL)
+ ENTRY(SIGKILL, "SIGKILL", "Killed"),
+#endif
+#if defined (SIGBUS)
+ ENTRY(SIGBUS, "SIGBUS", "Bus error"),
+#endif
+#if defined (SIGSEGV)
+ ENTRY(SIGSEGV, "SIGSEGV", "Segmentation fault"),
+#endif
+#if defined (SIGSYS)
+ ENTRY(SIGSYS, "SIGSYS", "Bad system call"),
+#endif
+#if defined (SIGPIPE)
+ ENTRY(SIGPIPE, "SIGPIPE", "Broken pipe"),
+#endif
+#if defined (SIGALRM)
+ ENTRY(SIGALRM, "SIGALRM", "Alarm clock"),
+#endif
+#if defined (SIGTERM)
+ ENTRY(SIGTERM, "SIGTERM", "Terminated"),
+#endif
+#if defined (SIGUSR1)
+ ENTRY(SIGUSR1, "SIGUSR1", "User defined signal 1"),
+#endif
+#if defined (SIGUSR2)
+ 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)
+ ENTRY(SIGCLD, "SIGCLD", "Child status changed"),
+#endif
+#if defined (SIGCHLD)
+ ENTRY(SIGCHLD, "SIGCHLD", "Child status changed"),
+#endif
+#if defined (SIGPWR)
+ ENTRY(SIGPWR, "SIGPWR", "Power fail/restart"),
+#endif
+#if defined (SIGWINCH)
+ ENTRY(SIGWINCH, "SIGWINCH", "Window size changed"),
+#endif
+#if defined (SIGURG)
+ 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. */
+ ENTRY(SIGIO, "SIGIO", "I/O possible"),
+#endif
+#if defined (SIGPOLL)
+ ENTRY(SIGPOLL, "SIGPOLL", "Pollable event occurred"),
+#endif
+#if defined (SIGSTOP)
+ ENTRY(SIGSTOP, "SIGSTOP", "Stopped (signal)"),
+#endif
+#if defined (SIGTSTP)
+ ENTRY(SIGTSTP, "SIGTSTP", "Stopped (user)"),
+#endif
+#if defined (SIGCONT)
+ ENTRY(SIGCONT, "SIGCONT", "Continued"),
+#endif
+#if defined (SIGTTIN)
+ ENTRY(SIGTTIN, "SIGTTIN", "Stopped (tty input)"),
+#endif
+#if defined (SIGTTOU)
+ ENTRY(SIGTTOU, "SIGTTOU", "Stopped (tty output)"),
+#endif
+#if defined (SIGVTALRM)
+ ENTRY(SIGVTALRM, "SIGVTALRM", "Virtual timer expired"),
+#endif
+#if defined (SIGPROF)
+ ENTRY(SIGPROF, "SIGPROF", "Profiling timer expired"),
+#endif
+#if defined (SIGXCPU)
+ ENTRY(SIGXCPU, "SIGXCPU", "CPU time limit exceeded"),
+#endif
+#if defined (SIGXFSZ)
+ ENTRY(SIGXFSZ, "SIGXFSZ", "File size limit exceeded"),
+#endif
+#if defined (SIGWIND)
+ ENTRY(SIGWIND, "SIGWIND", "SIGWIND"),
+#endif
+#if defined (SIGPHONE)
+ ENTRY(SIGPHONE, "SIGPHONE", "SIGPHONE"),
+#endif
+#if defined (SIGLOST)
+ ENTRY(SIGLOST, "SIGLOST", "Resource lost"),
+#endif
+#if defined (SIGWAITING)
+ ENTRY(SIGWAITING, "SIGWAITING", "Process's LWPs are blocked"),
+#endif
+#if defined (SIGLWP)
+ ENTRY(SIGLWP, "SIGLWP", "Signal LWP"),
+#endif
+#if defined (SIGDANGER)
+ ENTRY(SIGDANGER, "SIGDANGER", "Swap space dangerously low"),
+#endif
+#if defined (SIGGRANT)
+ ENTRY(SIGGRANT, "SIGGRANT", "Monitor mode granted"),
+#endif
+#if defined (SIGRETRACT)
+ ENTRY(SIGRETRACT, "SIGRETRACT", "Need to relinguish monitor mode"),
+#endif
+#if defined (SIGMSG)
+ ENTRY(SIGMSG, "SIGMSG", "Monitor mode data available"),
+#endif
+#if defined (SIGSOUND)
+ ENTRY(SIGSOUND, "SIGSOUND", "Sound completed"),
+#endif
+#if defined (SIGSAK)
+ ENTRY(SIGSAK, "SIGSAK", "Secure attention"),
+#endif
+ ENTRY(0, NULL, NULL)
+};
+
+/* Translation table allocated and initialized at runtime. Indexed by the
+ signal value to find the equivalent symbolic value. */
+
+static const char **signal_names;
+static int num_signal_names = 0;
+
+/* Translation table allocated and initialized at runtime, if it does not
+ already exist in the host environment. Indexed by the signal value to find
+ the descriptive string.
+
+ We don't export it for use in other modules because even though it has the
+ same name, it differs from other implementations in that it is dynamically
+ initialized rather than statically initialized. */
+
+#ifdef NEED_sys_siglist
+
+static int sys_nsig;
+static const char **sys_siglist;
+
+#else
+
+static int sys_nsig = NSIG;
+extern const char * const sys_siglist[];
+
+#endif
+
+
+/*
+
+NAME
+
+ init_signal_tables -- initialize the name and message tables
+
+SYNOPSIS
+
+ static void init_signal_tables ();
+
+DESCRIPTION
+
+ Using the signal_table, which is initialized at compile time, generate
+ the signal_names and the sys_siglist (if needed) tables, which are
+ indexed at runtime by a specific signal value.
+
+BUGS
+
+ The initialization of the tables may fail under low memory conditions,
+ in which case we don't do anything particularly useful, but we don't
+ bomb either. Who knows, it might succeed at a later point if we free
+ some memory in the meantime. In any case, the other routines know
+ how to deal with lack of a table after trying to initialize it. This
+ may or may not be considered to be a bug, that we don't specifically
+ warn about this particular failure mode.
+
+*/
+
+static void
+init_signal_tables ()
+{
+ const struct signal_info *eip;
+ int nbytes;
+
+ /* If we haven't already scanned the signal_table once to find the maximum
+ signal value, then go find it now. */
+
+ if (num_signal_names == 0)
+ {
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ if (eip -> value >= num_signal_names)
+ {
+ num_signal_names = eip -> value + 1;
+ }
+ }
+ }
+
+ /* Now attempt to allocate the signal_names table, zero it out, and then
+ initialize it from the statically initialized signal_table. */
+
+ if (signal_names == NULL)
+ {
+ nbytes = num_signal_names * sizeof (char *);
+ if ((signal_names = (const char **) malloc (nbytes)) != NULL)
+ {
+ memset (signal_names, 0, nbytes);
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ signal_names[eip -> value] = eip -> name;
+ }
+ }
+ }
+
+#ifdef NEED_sys_siglist
+
+ /* Now attempt to allocate the sys_siglist table, zero it out, and then
+ initialize it from the statically initialized signal_table. */
+
+ if (sys_siglist == NULL)
+ {
+ nbytes = num_signal_names * sizeof (char *);
+ if ((sys_siglist = (const char **) malloc (nbytes)) != NULL)
+ {
+ memset (sys_siglist, 0, nbytes);
+ sys_nsig = num_signal_names;
+ for (eip = signal_table; eip -> name != NULL; eip++)
+ {
+ sys_siglist[eip -> value] = eip -> msg;
+ }
+ }
+ }
+
+#endif
+
+}
+
+
+/*
+
+NAME
+
+ signo_max -- return the max signo value
+
+SYNOPSIS
+
+ int signo_max ();
+
+DESCRIPTION
+
+ Returns the maximum signo value for which a corresponding symbolic
+ name or message is available. Note that in the case where
+ we use the sys_siglist supplied by the system, it is possible for
+ there to be more symbolic names than messages, or vice versa.
+ In fact, the manual page for psignal(3b) explicitly warns that one
+ should check the size of the table (NSIG) before indexing it,
+ since new signal codes may be added to the system before they are
+ added to the table. Thus NSIG might be smaller than value
+ implied by the largest signo value defined in <signal.h>.
+
+ We return the maximum value that can be used to obtain a meaningful
+ symbolic name or message.
+
+*/
+
+int
+signo_max ()
+{
+ int maxsize;
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ maxsize = MAX (sys_nsig, num_signal_names);
+ return (maxsize - 1);
+}
+
+
+/*
+
+NAME
+
+ strsignal -- map a signal number to a signal message string
+
+SYNOPSIS
+
+ const char *strsignal (int signo)
+
+DESCRIPTION
+
+ Maps an signal number to an signal message string, the contents of
+ which are implementation defined. On systems which have the external
+ variable sys_siglist, these strings will be the same as the ones used
+ by psignal().
+
+ If the supplied signal number is within the valid range of indices
+ for the sys_siglist, but no message is available for the particular
+ signal number, then returns the string "Signal NUM", where NUM is the
+ signal number.
+
+ If the supplied signal number is not a valid index into sys_siglist,
+ returns NULL.
+
+ The returned string is only guaranteed to be valid only until the
+ next call to strsignal.
+
+*/
+
+const char *
+strsignal (signo)
+ int signo;
+{
+ const char *msg;
+ static char buf[32];
+
+#ifdef NEED_sys_siglist
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+
+#endif
+
+ if ((signo < 0) || (signo >= sys_nsig))
+ {
+ /* Out of range, just return NULL */
+ msg = NULL;
+ }
+ else if ((sys_siglist == NULL) || (sys_siglist[signo] == NULL))
+ {
+ /* In range, but no sys_siglist or no entry at this index. */
+ sprintf (buf, "Signal %d", signo);
+ msg = (const char *) buf;
+ }
+ else
+ {
+ /* In range, and a valid message. Just return the message. */
+ msg = (const char *) sys_siglist[signo];
+ }
+
+ return (msg);
+}
+
+
+/*
+
+NAME
+
+ strsigno -- map an signal number to a symbolic name string
+
+SYNOPSIS
+
+ const char *strsigno (int signo)
+
+DESCRIPTION
+
+ Given an signal number, returns a pointer to a string containing
+ the symbolic name of that signal number, as found in <signal.h>.
+
+ If the supplied signal number is within the valid range of indices
+ for symbolic names, but no name is available for the particular
+ signal number, then returns the string "Signal NUM", where NUM is
+ the signal number.
+
+ If the supplied signal number is not within the range of valid
+ indices, then returns NULL.
+
+BUGS
+
+ The contents of the location pointed to are only guaranteed to be
+ valid until the next call to strsigno.
+
+*/
+
+const char *
+strsigno (signo)
+ int signo;
+{
+ const char *name;
+ static char buf[32];
+
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+
+ if ((signo < 0) || (signo >= num_signal_names))
+ {
+ /* Out of range, just return NULL */
+ name = NULL;
+ }
+ else if ((signal_names == NULL) || (signal_names[signo] == NULL))
+ {
+ /* In range, but no signal_names or no entry at this index. */
+ sprintf (buf, "Signal %d", signo);
+ name = (const char *) buf;
+ }
+ else
+ {
+ /* In range, and a valid name. Just return the name. */
+ name = signal_names[signo];
+ }
+
+ return (name);
+}
+
+
+/*
+
+NAME
+
+ strtosigno -- map a symbolic signal name to a numeric value
+
+SYNOPSIS
+
+ int strtosigno (char *name)
+
+DESCRIPTION
+
+ Given the symbolic name of a signal, map it to a signal number.
+ If no translation is found, returns 0.
+
+*/
+
+int
+strtosigno (name)
+ const char *name;
+{
+ int signo = 0;
+
+ if (name != NULL)
+ {
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ for (signo = 0; signo < num_signal_names; signo++)
+ {
+ if ((signal_names[signo] != NULL) &&
+ (strcmp (name, signal_names[signo]) == 0))
+ {
+ break;
+ }
+ }
+ if (signo == num_signal_names)
+ {
+ signo = 0;
+ }
+ }
+ return (signo);
+}
+
+
+/*
+
+NAME
+
+ psignal -- print message about signal to stderr
+
+SYNOPSIS
+
+ void psignal (unsigned signo, char *message);
+
+DESCRIPTION
+
+ Print to the standard error the message, followed by a colon,
+ followed by the description of the signal specified by signo,
+ followed by a newline.
+*/
+
+#ifdef NEED_psignal
+
+void
+psignal (signo, message)
+ unsigned signo;
+ char *message;
+{
+ if (signal_names == NULL)
+ {
+ init_signal_tables ();
+ }
+ if ((signo <= 0) || (signo >= sys_nsig))
+ {
+ fprintf (stderr, "%s: unknown signal\n", message);
+ }
+ else
+ {
+ fprintf (stderr, "%s: %s\n", message, sys_siglist[signo]);
+ }
+}
+
+#endif /* NEED_psignal */
+
+
+/* A simple little main that does nothing but print all the signal translations
+ if MAIN is defined and this file is compiled and linked. */
+
+#ifdef MAIN
+
+#include <stdio.h>
+
+int
+main ()
+{
+ int signo;
+ int maxsigno;
+ const char *name;
+ const char *msg;
+
+ maxsigno = signo_max ();
+ printf ("%d entries in names table.\n", num_signal_names);
+ printf ("%d entries in messages table.\n", sys_nsig);
+ printf ("%d is max useful index.\n", maxsigno);
+
+ /* Keep printing values until we get to the end of *both* tables, not
+ *either* table. Note that knowing the maximum useful index does *not*
+ relieve us of the responsibility of testing the return pointer for
+ NULL. */
+
+ for (signo = 0; signo <= maxsigno; signo++)
+ {
+ name = strsigno (signo);
+ name = (name == NULL) ? "<NULL>" : name;
+ msg = strsignal (signo);
+ msg = (msg == NULL) ? "<NULL>" : msg;
+ printf ("%-4d%-18s%s\n", signo, name, msg);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/contrib/gdb/libiberty/strstr.c b/contrib/gdb/libiberty/strstr.c
new file mode 100644
index 0000000..fab36e3
--- /dev/null
+++ b/contrib/gdb/libiberty/strstr.c
@@ -0,0 +1,51 @@
+/* Simple implementation of strstr for systems without it.
+ This function is in the public domain. */
+
+/*
+
+NAME
+
+ strstr -- locate first occurance of a substring
+
+SYNOPSIS
+
+ #include <string.h>
+
+ char *strstr (char *s1, char *s2)
+
+DESCRIPTION
+
+ Locates the first occurance in the string pointed to by S1 of
+ the string pointed to by S2. Returns a pointer to the substring
+ found, or a NULL pointer if not found. If S2 points to a string
+ with zero length, the function returns S1.
+
+BUGS
+
+*/
+
+
+/* FIXME: The above description is ANSI compiliant. This routine has not
+ been validated to comply with it. -fnf */
+
+char *
+strstr (s1, s2)
+ char *s1, *s2;
+{
+ register char *p = s1;
+ extern char *strchr ();
+ extern int strncmp ();
+#if __GNUC__==2
+ extern __SIZE_TYPE__ strlen ();
+#endif
+ register int len = strlen (s2);
+
+ for (; (p = strchr (p, *s2)) != 0; p++)
+ {
+ if (strncmp (p, s2, len) == 0)
+ {
+ return (p);
+ }
+ }
+ return (0);
+}
diff --git a/contrib/gdb/libiberty/strtod.c b/contrib/gdb/libiberty/strtod.c
new file mode 100644
index 0000000..c86c73d
--- /dev/null
+++ b/contrib/gdb/libiberty/strtod.c
@@ -0,0 +1,122 @@
+/* Implementation of strtod for systems with atof.
+ Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+
+This file is part of the libiberty library. This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include <ctype.h>
+
+extern double atof ();
+
+/* Disclaimer: this is currently just used by CHILL in GDB and therefore
+ has not been tested well. It may have been tested for nothing except
+ that it compiles. */
+
+double
+strtod (str, ptr)
+ char *str;
+ char **ptr;
+{
+ char *p;
+
+ if (ptr == (char **)0)
+ return atof (str);
+
+ p = str;
+
+ while (isspace (*p))
+ ++p;
+
+ if (*p == '+' || *p == '-')
+ ++p;
+
+ /* INF or INFINITY. */
+ if ((p[0] == 'i' || p[0] == 'I')
+ && (p[1] == 'n' || p[1] == 'N')
+ && (p[2] == 'f' || p[2] == 'F'))
+ {
+ if ((p[3] == 'i' || p[3] == 'I')
+ && (p[4] == 'n' || p[4] == 'N')
+ && (p[5] == 'i' || p[5] == 'I')
+ && (p[6] == 't' || p[6] == 'T')
+ && (p[7] == 'y' || p[7] == 'Y'))
+ {
+ *ptr = p + 7;
+ return atof (str);
+ }
+ else
+ {
+ *ptr = p + 3;
+ return atof (str);
+ }
+ }
+
+ /* NAN or NAN(foo). */
+ if ((p[0] == 'n' || p[0] == 'N')
+ && (p[1] == 'a' || p[1] == 'A')
+ && (p[2] == 'n' || p[2] == 'N'))
+ {
+ p += 3;
+ if (*p == '(')
+ {
+ ++p;
+ while (*p != '\0' && *p != ')')
+ ++p;
+ if (*p == ')')
+ ++p;
+ }
+ *ptr = p;
+ return atof (str);
+ }
+
+ /* digits, with 0 or 1 periods in it. */
+ if (isdigit (*p) || *p == '.')
+ {
+ int got_dot = 0;
+ while (isdigit (*p) || (!got_dot && *p == '.'))
+ {
+ if (*p == '.')
+ got_dot = 1;
+ ++p;
+ }
+
+ /* Exponent. */
+ if (*p == 'e' || *p == 'E')
+ {
+ int i;
+ i = 1;
+ if (p[i] == '+' || p[i] == '-')
+ ++i;
+ if (isdigit (p[i]))
+ {
+ while (isdigit (p[i]))
+ ++i;
+ *ptr = p + i;
+ return atof (str);
+ }
+ }
+ *ptr = p;
+ return atof (str);
+ }
+ /* Didn't find any digits. Doesn't look like a number. */
+ *ptr = str;
+ return 0.0;
+}
diff --git a/contrib/gdb/libiberty/strtol.c b/contrib/gdb/libiberty/strtol.c
new file mode 100644
index 0000000..db27ee0
--- /dev/null
+++ b/contrib/gdb/libiberty/strtol.c
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#if 0
+#include <stdlib.h>
+#endif
+#include "ansidecl.h"
+
+/* FIXME: It'd be nice to configure around these, but the include files are too
+ painful. These macros should at least be more portable than hardwired hex
+ constants. */
+
+#ifndef ULONG_MAX
+#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
+#endif
+
+#ifndef LONG_MAX
+#define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF */
+#endif
+
+#ifndef LONG_MIN
+#define LONG_MIN ((long)(~LONG_MAX)) /* 0x80000000 */
+#endif
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long
+strtol(nptr, endptr, base)
+ CONST char *nptr;
+ char **endptr;
+ register int base;
+{
+ register CONST char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/contrib/gdb/libiberty/strtoul.c b/contrib/gdb/libiberty/strtoul.c
new file mode 100644
index 0000000..4090245
--- /dev/null
+++ b/contrib/gdb/libiberty/strtoul.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#if 0
+#include <stdlib.h>
+#endif
+#include "ansidecl.h"
+
+#ifndef ULONG_MAX
+#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
+#endif
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+strtoul(nptr, endptr, base)
+ CONST char *nptr;
+ char **endptr;
+ register int base;
+{
+ register CONST char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
+ cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *) (any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/contrib/gdb/libiberty/tmpnam.c b/contrib/gdb/libiberty/tmpnam.c
new file mode 100644
index 0000000..c061467
--- /dev/null
+++ b/contrib/gdb/libiberty/tmpnam.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+
+#ifndef L_tmpnam
+#define L_tmpname 100
+#endif
+#ifndef P_tmpdir
+#define P_tmpdir "/usr/tmp"
+#endif
+
+static char tmpnam_buffer[L_tmpnam];
+static int tmpnam_counter;
+
+extern int getpid ();
+
+char *
+tmpnam (s)
+ char *s;
+{
+ int pid = getpid ();
+
+ if (s == NULL)
+ s = tmpnam_buffer;
+
+ /* Generate the filename and make sure that there isn't one called
+ it already. */
+
+ while (1)
+ {
+ FILE *f;
+ sprintf (s, "%s/%s%x.%x", P_tmpdir, "t", pid, tmpnam_counter);
+ f = fopen (s, "r");
+ if (f == NULL)
+ break;
+ tmpnam_counter++;
+ fclose (f);
+ }
+
+ return s;
+}
diff --git a/contrib/gdb/libiberty/vasprintf.c b/contrib/gdb/libiberty/vasprintf.c
new file mode 100644
index 0000000..3794cbd
--- /dev/null
+++ b/contrib/gdb/libiberty/vasprintf.c
@@ -0,0 +1,165 @@
+/* Like vsprintf but provides a pointer to malloc'd storage, which must
+ be freed by the caller.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <string.h>
+#include <ansidecl.h>
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef TEST
+int global_total_width;
+#endif
+
+unsigned long strtoul ();
+char *malloc ();
+
+static int
+int_vasprintf (result, format, args)
+ char **result;
+ const char *format;
+ va_list *args;
+{
+ const char *p = format;
+ /* Add one to make sure that it is never zero, which might cause malloc
+ to return NULL. */
+ int total_width = strlen (format) + 1;
+ va_list ap;
+
+ memcpy ((PTR) &ap, (PTR) args, sizeof (va_list));
+
+ while (*p != '\0')
+ {
+ if (*p++ == '%')
+ {
+ while (strchr ("-+ #0", *p))
+ ++p;
+ if (*p == '*')
+ {
+ ++p;
+ total_width += abs (va_arg (ap, int));
+ }
+ else
+ total_width += strtoul (p, &p, 10);
+ if (*p == '.')
+ {
+ ++p;
+ if (*p == '*')
+ {
+ ++p;
+ total_width += abs (va_arg (ap, int));
+ }
+ else
+ total_width += strtoul (p, &p, 10);
+ }
+ while (strchr ("hlL", *p))
+ ++p;
+ /* Should be big enough for any format specifier except %s. */
+ total_width += 30;
+ switch (*p)
+ {
+ case 'd':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'c':
+ (void) va_arg (ap, int);
+ break;
+ case 'f':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ (void) va_arg (ap, double);
+ break;
+ case 's':
+ total_width += strlen (va_arg (ap, char *));
+ break;
+ case 'p':
+ case 'n':
+ (void) va_arg (ap, char *);
+ break;
+ }
+ }
+ }
+#ifdef TEST
+ global_total_width = total_width;
+#endif
+ *result = malloc (total_width);
+ if (*result != NULL)
+ return vsprintf (*result, format, *args);
+ else
+ return 0;
+}
+
+int
+vasprintf (result, format, args)
+ char **result;
+ const char *format;
+ va_list args;
+{
+ return int_vasprintf (result, format, &args);
+}
+
+#ifdef TEST
+void
+checkit
+#ifdef __STDC__
+ (const char* format, ...)
+#else
+ (va_alist)
+ va_dcl
+#endif
+{
+ va_list args;
+ char *result;
+
+#ifdef __STDC__
+ va_start (args, format);
+#else
+ char *format;
+ va_start (args);
+ format = va_arg (args, char *);
+#endif
+ vasprintf (&result, format, args);
+ if (strlen (result) < global_total_width)
+ printf ("PASS: ");
+ else
+ printf ("FAIL: ");
+ printf ("%d %s\n", global_total_width, result);
+}
+
+int
+main ()
+{
+ checkit ("%d", 0x12345678);
+ checkit ("%200d", 5);
+ checkit ("%.300d", 6);
+ checkit ("%100.150d", 7);
+ checkit ("%s", "jjjjjjjjjiiiiiiiiiiiiiiioooooooooooooooooppppppppppppaa\n\
+777777777777777777333333333333366666666666622222222222777777777777733333");
+ checkit ("%f%s%d%s", 1.0, "foo", 77, "asdjffffffffffffffiiiiiiiiiiixxxxx");
+}
+#endif /* TEST */
diff --git a/contrib/gdb/libiberty/vfork.c b/contrib/gdb/libiberty/vfork.c
new file mode 100644
index 0000000..86c4591
--- /dev/null
+++ b/contrib/gdb/libiberty/vfork.c
@@ -0,0 +1,8 @@
+/* Emulate vfork using just plain fork, for systems without a real vfork.
+ This function is in the public domain. */
+
+int
+vfork ()
+{
+ return (fork ());
+}
diff --git a/contrib/gdb/libiberty/vfprintf.c b/contrib/gdb/libiberty/vfprintf.c
new file mode 100644
index 0000000..ce3fdf9
--- /dev/null
+++ b/contrib/gdb/libiberty/vfprintf.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <varargs.h>
+#include <ansidecl.h>
+#undef vfprintf
+
+int
+vfprintf (file, format, ap)
+ FILE *file;
+ const char *format;
+ va_list ap;
+{
+ return _doprnt (format, ap, file);
+}
diff --git a/contrib/gdb/libiberty/vmsbuild.com b/contrib/gdb/libiberty/vmsbuild.com
new file mode 100644
index 0000000..e1c203f
--- /dev/null
+++ b/contrib/gdb/libiberty/vmsbuild.com
@@ -0,0 +1,142 @@
+$! libiberty/vmsbuild.com -- build liberty.olb for VMS host, VMS target
+$!
+$ CC = "gcc /noVerbose/Debug/Incl=([],[-.include])"
+$ LIBR = "library /Obj"
+$ LINK = "link"
+$ DELETE= "delete /noConfirm"
+$ SEARCH= "search /Exact"
+$ ECHO = "write sys$output"
+$ ABORT = "exit %x002C"
+$!
+$ LIB_NAME = "liberty.olb" !this is what we're going to construct
+$ WORK_LIB = "new-lib.olb" !used to guard against an incomplete build
+$
+$! manually copied from Makefile.in
+$ REQUIRED_OFILES = "argv.o basename.o concat.o cplus-dem.o fdmatch.o "-
+ + "getopt.o getopt1.o getruntime.o hex.o "-
+ + "floatformat.o obstack.o spaces.o strerror.o strsignal.o "-
+ + "vasprintf.o xatexit.o xexit.o xmalloc.o xstrerror.o"
+$! anything not caught by link+search of dummy.* should be added here
+$ EXTRA_OFILES = ""
+$!
+$! move to the directory which contains this command procedure
+$ old_dir = f$environ("DEFAULT")
+$ new_dir = f$parse("_._;",f$environ("PROCEDURE")) - "_._;"
+$ set default 'new_dir'
+$
+$ ECHO "Starting libiberty build..."
+$ create config.h
+/* libiberty config.h for VMS */
+#define NEED_sys_siglist
+#define NEED_psignal
+#define NEED_basename
+$ if f$search("alloca-conf.h").eqs."" then -
+ copy alloca-norm.h alloca-conf.h
+$ LIBR 'WORK_LIB' /Create
+$
+$! first pass: compile "required" modules
+$ ofiles = REQUIRED_OFILES + " " + EXTRA_OFILES
+$ gosub do_ofiles
+$
+$! second pass: process dummy.c, using the first pass' results
+$ ECHO " now checking run-time library for missing functionality"
+$ if f$search("dummy.obj").nes."" then DELETE dummy.obj;*
+$ define/noLog sys$error _NL: !can't use /User_Mode here due to gcc
+$ define/noLog sys$output _NL: ! driver's use of multiple image activation
+$ on error then continue
+$ 'CC' dummy.c
+$ deassign sys$error !restore, more or less
+$ deassign sys$output
+$ if f$search("dummy.obj").eqs."" then goto pass2_failure1
+$! link dummy.obj, capturing full linker feedback in dummy.map
+$ oldmsg = f$environ("MESSAGE")
+$ set message /Facility/Severity/Identification/Text
+$ define/User sys$output _NL:
+$ define/User sys$error _NL:
+$ LINK/Map=dummy.map/noExe dummy.obj,'WORK_LIB'/Libr,-
+ gnu_cc:[000000]gcclib.olb/Libr,sys$library:vaxcrtl.olb/Libr
+$ set message 'oldmsg'
+$ if f$search("dummy.map").eqs."" then goto pass2_failure2
+$ DELETE dummy.obj;*
+$ SEARCH dummy.map "%LINK-I-UDFSYM" /Output=dummy.list
+$ DELETE dummy.map;*
+$ ECHO " check completed"
+$! we now have a file with one entry per line of unresolvable symbols
+$ ofiles = ""
+$ if f$trnlnm("IFILE$").nes."" then close/noLog ifile$
+$ open/Read ifile$ dummy.list
+$iloop: read/End=idone ifile$ iline
+$ iline = f$edit(iline,"COMPRESS,TRIM,LOWERCASE")
+$ ofiles = ofiles + " " + f$element(1," ",iline) + ".o"
+$ goto iloop
+$idone: close ifile$
+$ DELETE dummy.list;*
+$
+$! third pass: compile "missing" modules collected in pass 2
+$ gosub do_ofiles
+$
+$! finish up
+$ LIBR 'WORK_LIB' /Compress /Output='LIB_NAME' !new-lib.olb -> liberty.olb
+$ DELETE 'WORK_LIB';*
+$
+$! all done
+$ ECHO "Completed libiberty build."
+$ type sys$input:
+
+ You many wish to do
+ $ COPY LIBERTY.OLB GNU_CC:[000000]
+ so that this run-time library resides in the same location as gcc's
+ support library. When building gas, be sure to leave the original
+ copy of liberty.olb here so that gas's build procedure can find it.
+
+$ set default 'old_dir'
+$ exit
+$
+$!
+$! compile each element of the space-delimited list 'ofiles'
+$!
+$do_ofiles:
+$ ofiles = f$edit(ofiles,"COMPRESS,TRIM")
+$ i = 0
+$oloop:
+$ f = f$element(i," ",ofiles)
+$ if f.eqs." " then goto odone
+$ f = f - ".o" !strip dummy suffix
+$ ECHO " ''f'"
+$ 'CC' 'f'.c
+$ LIBR 'WORK_LIB' 'f'.obj /Insert
+$ DELETE 'f'.obj;*
+$ i = i + 1
+$ goto oloop
+$odone:
+$ return
+$
+$!
+$pass2_failure1:
+$! if we reach here, dummy.c failed to compile and we're really stuck
+$ type sys$input:
+
+ Cannot compile the library contents checker (dummy.c + functions.def),
+ so cannot continue!
+
+$! attempt the compile again, without suppressing diagnostic messages this time
+$ on error then ABORT +0*f$verify(v)
+$ v = f$verify(1)
+$ 'CC' dummy.c
+$ ABORT +0*f$verify(v) !'f$verify(0)'
+$!
+$pass2_failure2:
+$! should never reach here..
+$ type sys$input:
+
+ Cannot link the library contents checker (dummy.obj), so cannot continue!
+
+$! attempt the link again, without suppressing diagnostic messages this time
+$ on error then ABORT +0*f$verify(v)
+$ v = f$verify(1)
+$ LINK/Map=dummy.map/noExe dummy.obj,'WORK_LIB'/Libr,-
+ gnu_cc:[000000]gcclib.olb/Libr,sys$library:vaxcrtl.olb/Libr
+$ ABORT +0*f$verify(v) !'f$verify(0)'
+$
+$! not reached
+$ exit
diff --git a/contrib/gdb/libiberty/vprintf.c b/contrib/gdb/libiberty/vprintf.c
new file mode 100644
index 0000000..63ac53c
--- /dev/null
+++ b/contrib/gdb/libiberty/vprintf.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <varargs.h>
+#include <ansidecl.h>
+#undef vprintf
+int
+vprintf (format, ap)
+ const char *format;
+ va_list ap;
+{
+ return vfprintf (stdout, format, ap);
+}
diff --git a/contrib/gdb/libiberty/vsprintf.c b/contrib/gdb/libiberty/vsprintf.c
new file mode 100644
index 0000000..bf0760c
--- /dev/null
+++ b/contrib/gdb/libiberty/vsprintf.c
@@ -0,0 +1,55 @@
+/* Simple implementation of vsprintf for systems without it.
+ Highly system-dependent, but should work on most "traditional"
+ implementations of stdio; newer ones should already have vsprintf.
+ Written by Per Bothner of Cygnus Support.
+ Based on libg++'s "form" (written by Doug Lea; dl@rocky.oswego.edu).
+ Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+
+This file is part of the libiberty library. This library is free
+software; you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+As a special exception, if you link this library with files
+compiled with a GNU compiler to produce an executable, this does not cause
+the resulting executable to be covered by the GNU General Public License.
+This exception does not however invalidate any other reasons why
+the executable file might be covered by the GNU General Public License. */
+
+#include <varargs.h>
+#include <stdio.h>
+#include <ansidecl.h>
+#undef vsprintf
+
+int
+vsprintf (buf, format, ap)
+ char *buf;
+ const char *format;
+ va_list ap;
+{
+ FILE b;
+ int ret;
+#ifdef VMS
+ b->_flag = _IOWRT|_IOSTRG;
+ b->_ptr = buf;
+ b->_cnt = 12000;
+#else
+ b._flag = _IOWRT|_IOSTRG;
+ b._ptr = buf;
+ b._cnt = 12000;
+#endif
+ ret = _doprnt(format, ap, &b);
+ putc('\0', &b);
+ return ret;
+
+}
diff --git a/contrib/gdb/libiberty/waitpid.c b/contrib/gdb/libiberty/waitpid.c
new file mode 100644
index 0000000..23db0b9
--- /dev/null
+++ b/contrib/gdb/libiberty/waitpid.c
@@ -0,0 +1,11 @@
+int
+waitpid (pid, stat_loc, options)
+ int pid, *stat_loc, options;
+{
+ for (;;)
+ {
+ int wpid = wait(stat_loc);
+ if (wpid == pid || wpid == -1)
+ return wpid;
+ }
+}
diff --git a/contrib/gdb/libiberty/xatexit.c b/contrib/gdb/libiberty/xatexit.c
new file mode 100644
index 0000000..7dd27e1
--- /dev/null
+++ b/contrib/gdb/libiberty/xatexit.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1990 Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ */
+
+/* Adapted from newlib/libc/stdlib/{,at}exit.[ch].
+ If you use xatexit, you must call xexit instead of exit. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#define size_t unsigned long
+#endif
+
+/* For systems with larger pointers than ints, this must be declared. */
+PTR malloc PARAMS ((size_t));
+
+static void xatexit_cleanup PARAMS ((void));
+
+/* Pointer to function run by xexit. */
+extern void (*_xexit_cleanup) ();
+
+#define XATEXIT_SIZE 32
+
+struct xatexit {
+ struct xatexit *next; /* next in list */
+ int ind; /* next index in this table */
+ void (*fns[XATEXIT_SIZE]) PARAMS ((void)); /* the table itself */
+};
+
+/* Allocate one struct statically to guarantee that we can register
+ at least a few handlers. */
+static struct xatexit xatexit_first;
+
+/* Points to head of LIFO stack. */
+static struct xatexit *xatexit_head = &xatexit_first;
+
+/* Register function FN to be run by xexit.
+ Return 0 if successful, -1 if not. */
+
+int
+xatexit (fn)
+ void (*fn) PARAMS ((void));
+{
+ register struct xatexit *p;
+
+ /* Tell xexit to call xatexit_cleanup. */
+ if (!_xexit_cleanup)
+ _xexit_cleanup = xatexit_cleanup;
+
+ p = xatexit_head;
+ if (p->ind >= XATEXIT_SIZE)
+ {
+ if ((p = (struct xatexit *) malloc (sizeof *p)) == NULL)
+ return -1;
+ p->ind = 0;
+ p->next = xatexit_head;
+ xatexit_head = p;
+ }
+ p->fns[p->ind++] = fn;
+ return 0;
+}
+
+/* Call any cleanup functions. */
+
+static void
+xatexit_cleanup ()
+{
+ register struct xatexit *p;
+ register int n;
+
+ for (p = xatexit_head; p; p = p->next)
+ for (n = p->ind; --n >= 0;)
+ (*p->fns[n]) ();
+}
diff --git a/contrib/gdb/libiberty/xexit.c b/contrib/gdb/libiberty/xexit.c
new file mode 100644
index 0000000..98baeca
--- /dev/null
+++ b/contrib/gdb/libiberty/xexit.c
@@ -0,0 +1,36 @@
+/* xexit.c -- Run any exit handlers, then exit.
+ Copyright (C) 1994 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty 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 Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include <stdio.h>
+
+/* This variable is set by xatexit if it is called. This way, xmalloc
+ doesn't drag xatexit into the link. */
+void (*_xexit_cleanup) ();
+
+void
+xexit (code)
+ int code;
+{
+ if (_xexit_cleanup != NULL)
+ (*_xexit_cleanup) ();
+ exit (code);
+}
diff --git a/contrib/gdb/libiberty/xmalloc.c b/contrib/gdb/libiberty/xmalloc.c
new file mode 100644
index 0000000..95967ab
--- /dev/null
+++ b/contrib/gdb/libiberty/xmalloc.c
@@ -0,0 +1,106 @@
+/* memory allocation routines with error checking.
+ 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
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include <stdio.h>
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+#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 = "";
+
+/* The initial sbrk, set when the program name is set. */
+static char *first_break = NULL;
+
+void
+xmalloc_set_program_name (s)
+ const char *s;
+{
+ name = s;
+ if (first_break == NULL)
+ first_break = (char *) sbrk (0);
+}
+
+PTR
+xmalloc (size)
+ size_t size;
+{
+ PTR newmem;
+
+ if (size == 0)
+ size = 1;
+ newmem = malloc (size);
+ if (!newmem)
+ {
+ extern char **environ;
+ size_t allocated;
+
+ if (first_break != NULL)
+ allocated = (char *) sbrk (0) - first_break;
+ else
+ allocated = (char *) sbrk (0) - (char *) &environ;
+ fprintf (stderr,
+ "\n%s%sCan not allocate %lu bytes after allocating %lu bytes\n",
+ name, *name ? ": " : "",
+ (unsigned long) size, (unsigned long) allocated);
+ xexit (1);
+ }
+ return (newmem);
+}
+
+PTR
+xrealloc (oldmem, size)
+ PTR oldmem;
+ size_t size;
+{
+ PTR newmem;
+
+ if (size == 0)
+ size = 1;
+ if (!oldmem)
+ newmem = malloc (size);
+ else
+ newmem = realloc (oldmem, size);
+ if (!newmem)
+ {
+ extern char **environ;
+ size_t allocated;
+
+ if (first_break != NULL)
+ allocated = (char *) sbrk (0) - first_break;
+ else
+ allocated = (char *) sbrk (0) - (char *) &environ;
+ fprintf (stderr,
+ "\n%s%sCan not reallocate %lu bytes after allocating %lu bytes\n",
+ name, *name ? ": " : "",
+ (unsigned long) size, (unsigned long) allocated);
+ xexit (1);
+ }
+ return (newmem);
+}
diff --git a/contrib/gdb/libiberty/xstrdup.c b/contrib/gdb/libiberty/xstrdup.c
new file mode 100644
index 0000000..9d08bc7
--- /dev/null
+++ b/contrib/gdb/libiberty/xstrdup.c
@@ -0,0 +1,17 @@
+/* xstrdup.c -- Duplicate a string in memory, using xmalloc.
+ This trivial function is in the public domain.
+ Ian Lance Taylor, Cygnus Support, December 1995. */
+
+#include "ansidecl.h"
+#include "libiberty.h"
+
+char *
+xstrdup (s)
+ const char *s;
+{
+ char *ret;
+
+ ret = xmalloc (strlen (s) + 1);
+ strcpy (ret, s);
+ return ret;
+}
diff --git a/contrib/gdb/libiberty/xstrerror.c b/contrib/gdb/libiberty/xstrerror.c
new file mode 100644
index 0000000..d05369a
--- /dev/null
+++ b/contrib/gdb/libiberty/xstrerror.c
@@ -0,0 +1,54 @@
+/* xstrerror.c -- jacket routine for more robust strerror() usage.
+ Fri Jun 16 18:30:00 1995 Pat Rankin <rankin@eql.caltech.edu>
+ This code is in the public domain. */
+
+#include "libiberty.h"
+#include "config.h"
+
+#ifdef VMS
+#include <errno.h>
+#if !defined (__STRICT_ANSI__) && !defined (__HIDE_FORBIDDEN_NAMES)
+extern char *strerror PARAMS ((int,...));
+#define DONT_DECLARE_STRERROR
+#endif
+#endif /* VMS */
+
+#ifndef DONT_DECLARE_STRERROR
+extern char *strerror PARAMS ((int));
+#endif
+
+/* If strerror returns NULL, we'll format the number into a static buffer. */
+
+#define ERRSTR_FMT "undocumented error #%d"
+static char xstrerror_buf[sizeof ERRSTR_FMT + 20];
+
+/* Like strerror, but result is never a null pointer. */
+
+char *
+xstrerror (errnum)
+ int errnum;
+{
+ char *errstr;
+#ifdef VMS
+ char *(*vmslib_strerror) PARAMS ((int,...));
+
+ /* Override any possibly-conflicting declaration from system header. */
+ vmslib_strerror = (char *(*) PARAMS ((int,...))) strerror;
+ /* Second argument matters iff first is EVMSERR, but it's simpler to
+ pass it unconditionally. `vaxc$errno' is declared in <errno.h>
+ and maintained by the run-time library in parallel to `errno'.
+ We assume that `errnum' corresponds to the last value assigned to
+ errno by the run-time library, hence vaxc$errno will be relevant. */
+ errstr = (*vmslib_strerror) (errnum, vaxc$errno);
+#else
+ errstr = strerror (errnum);
+#endif
+
+ /* If `errnum' is out of range, result might be NULL. We'll fix that. */
+ if (!errstr)
+ {
+ sprintf (xstrerror_buf, ERRSTR_FMT, errnum);
+ errstr = xstrerror_buf;
+ }
+ return errstr;
+}
diff --git a/contrib/gdb/opcodes/ChangeLog b/contrib/gdb/opcodes/ChangeLog
new file mode 100644
index 0000000..589c1a2
--- /dev/null
+++ b/contrib/gdb/opcodes/ChangeLog
@@ -0,0 +1,1772 @@
+Sun Apr 7 15:06:17 1996 Fred Fish <fnf@cygnus.com>
+
+ From: Miles Bader <miles@gnu.ai.mit.edu>
+ * configure.in: Use AC_CHECK_TOOL to find AR & RANLIB.
+ * configure: Regenerate with autoconf.
+
+Sat Mar 16 13:04:07 1996 Fred Fish <fnf@cygnus.com>
+
+ * z8kgen.c (internal, gas): Call xmalloc rather than unchecked
+ malloc.
+
+Tue Mar 12 12:14:10 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Rebuild with autoconf 2.8.
+
+Thu Mar 7 15:11:10 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-dis.c (print_insn_sparc): Handle 'O' operand char like 'r'.
+ * sparc-opc.c (sparc_opcodes): Use 'O' operand char for `neg reg'.
+
+Tue Mar 5 15:51:57 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Don't set SHLIB or SHLINK to an empty string,
+ since they appear as targets in Makefile.in.
+ * configure: Rebuild.
+
+Mon Feb 26 13:03:40 1996 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-make.sed: Edit out shared library support bits.
+
+Tue Feb 20 20:48:28 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-opc.c (v8,v6notv9): Add MASK_SPARCLET.
+ (sparc_opcode_archs): Add MASK_V8 to sparclet entry.
+ (sparc_opcodes): Add sparclet insns.
+ (sparclet_cpreg_table): New static local.
+ (sparc_{encode,decode}_sparclet_cpreg): New functions.
+ * sparc-dis.c (print_insn_sparc): Handle sparclet cpregs.
+
+Tue Feb 20 11:02:44 1996 Alan Modra <alan@mullet.Levels.UniSA.Edu.Au>
+
+ * i386-dis.c (index16): New static variable.
+ (putop): Print jecxz for 32 bit case, jcxz for 16 bit, not the
+ other way around.
+ (OP_indirE): Return result of OP_E.
+ (OP_E): Check for 16 bit addressing mode, and disassemble
+ correctly. Optimised 32 bit case a little. Don't print
+ "(base,index,scale)" when sib specifies only an offset.
+
+Mon Feb 19 12:32:17 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Set and substitute SHLIB_DEP.
+ * configure: Rebuild.
+ * Makefile.in (SHLIB_DEP): New variable.
+ (LIBIBERTY_LISTS, BFD_LIST): New variables.
+ (stamp-piclist): Depend upon LIBIBERTY_LISTS and BFD_LIST. If
+ COMMON_SHLIB, add them to piclist with appropriate modifications.
+ ($(SHLIB)): Depend upon $(SHLIB_DEP). Don't check COMMON_SHLIB
+ here: just use piclist.
+
+Mon Feb 19 02:03:50 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-dis.c (MASK_V9,V9_ONLY_P,V9_P): Define.
+ (print_insn_sparc): Rewrite v9/not-v9 tests.
+ (compare_opcodes): Likewise.
+ * sparc-opc.c (MASK_<ARCH>): Define.
+ (v6,v7,v8,sparclite,v9,v9a): Redefine.
+ (sparclet,v6notv9): Define.
+ (sparc_opcode_archs): Delete member `conflicts'. Add `supported'.
+ (sparc_opcodes): Delete F_NOTV9, use v6notv9 instead.
+
+Thu Feb 15 14:45:05 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Call AC_PROG_CC before configure.host.
+ * configure: Rebuild.
+
+ * Makefile.in (SONAME): Remove leading ../bfd/ from $(SHLIB).
+
+Wed Feb 14 19:01:27 1996 Alan Modra <alan@spri.levels.unisa.edu.au>
+
+ * i386-dis.c (onebyte_has_modrm): New static array.
+ (twobyte_has_modrm): New static array.
+ (print_insn_i386): Only fetch the mod/reg/rm byte if it is needed.
+
+Tue Feb 13 15:15:01 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in ($(SHLINK)): Check ts against $(SHLIB), not
+ $(SHLINK).
+
+Mon Feb 12 16:26:06 1996 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-opc.c (PPC): Undef, so default defination on Windows NT
+ doesn't conflict.
+
+Wed Feb 7 13:59:54 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c (m68k_opcodes): The bkpt instruction is supported on
+ m68010up, not just m68020up | cpu32.
+
+ * Makefile.in (SONAME): New variable.
+ ($(SHLINK)): Make a link to the transformed name, as well.
+ (stamp-tshlink): New target.
+ (install): Skip stamp-tshlink during install.
+
+Tue Feb 6 12:28:54 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Call AC_ARG_PROGRAM.
+ * configure: Rebuild.
+ * Makefile.in (program_transform_name): New variable.
+ (install): Transform library name before installing it.
+
+Mon Feb 5 16:14:42 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * i960-dis.c (mem): Add HX dcinva instruction.
+
+ Support for building as a shared library, based on patches from
+ Alan Modra <alan@spri.levels.unisa.edu.au>:
+ * configure.in: Add AC_ARG_ENABLE for shared and commonbfdlib.
+ New substitutions: ALLLIBS, PICFLAG, SHLIB, SHLIB_CC,
+ SHLIB_CFLAGS, COMMON_SHLIB, SHLINK.
+ * configure: Rebuild.
+ * Makefile.in (ALLLIBS): New variable.
+ (PICFLAG, SHLIB, SHLIB_CC, SHLIB_CFLAGS): New variables.
+ (COMMON_SHLIB, SHLINK): New variables.
+ (.c.o): If PICFLAG is set, compile twice, once PIC, once normal.
+ (STAGESTUFF): Remove variable.
+ (all): Depend upon $(ALLLIBS) rather than $(TARGETLIB).
+ (stamp-piclist, piclist): New targets.
+ ($(SHLIB), $(SHLINK)): New targets.
+ ($(OFILES)): Depend upon stamp-picdir.
+ (disassemble.o): Build twice if PICFLAG is set.
+ (MOSTLYCLEAN): Add pic/*.o.
+ (clean): Remove $(SHLIB), $(SHLINK), piclist, and stamp-piclist.
+ (distclean): Remove pic and stamp-picdir.
+ (install): Install shared libraries.
+ (stamp-picdir): New target.
+
+Fri Feb 2 17:15:25 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-dis.c (print_insn_sparc): Delete DISASM_RAW_INSN support.
+ Print unknown instruction as "unknown", rather than in hex.
+
+Tue Jan 30 14:06:08 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * dis-buf.c: Include "sysdep.h" before "dis-asm.h".
+
+Thu Jan 25 20:24:07 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-opc.c (sparc_opcode_archs): Mark v8/sparclite as conflicting.
+
+Thu Jan 25 11:56:49 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * i386-dis.c (print_insn_i386): Only fetch the mod/reg/rm byte
+ when necessary. From Ulrich Drepper
+ <drepper@myware.rz.uni-karlsruhe.de>.
+
+Thu Jan 25 03:39:10 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-dis.c (print_insn_sparc): NUMOPCODES replaced with
+ sparc_num_opcodes. Update architecture enum values.
+ * sparc-opc.c (sparc_opcode_archs): Replaces architecture_pname.
+ (sparc_opcode_lookup_arch): New function.
+ (sparc_num_opcodes): Renamed from bfd_sparc_num_opcodes.
+ (sparc_opcodes): Add v9a shutdown insn.
+
+Mon Jan 22 08:29:59 1996 Doug Evans <dje@charmed.cygnus.com>
+
+ * sparc-dis.c (print_insn_sparc): Renamed from print_insn.
+ If DISASM_RAW_INSN, print insn in hex. Handle v9a as opcode
+ architecture.
+ (print_insn_sparc64): Deleted.
+ * disassemble.c (disassembler, case bfd_arch_sparc): Always use
+ print_insn_sparc.
+
+ * sparc-opc.c (architecture_pname): Add v9a.
+
+Fri Jan 12 14:35:58 1996 David Mosberger-Tang <davidm@AZStarNet.com>
+
+ * alpha-opc.h (alpha_insn_set): VAX floating point opcode was
+ incorrectly defined as 0x16 when it should be 0x15.
+ (FLOAT_FORMAT_MASK): function code is 11 bits, not just 7 bits!
+ (alpha_insn_set): added cvtst and cvttq float ops. Also added
+ excb (exception barrier) which is defined in the Alpha
+ Architecture Handbook version 2.
+ * alpha-dis.c (print_insn_alpha): Fixed special-case decoding for
+ OPERATE_FORMAT_CODE type instructions. The bug caused mulq to be
+ disassembled as or, for example.
+
+Wed Jan 10 12:37:22 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips-dis.c (print_insn_arg): Print cases 'i' and 'u' in hex.
+ (_print_insn_mips): Change i from int to unsigned int.
+
+Thu Jan 4 17:21:10 1996 David Edelsohn <edelsohn@mhpcc.edu>
+
+ * ppc-opc.c (powerpc_opcodes): tlbi POWER opcode form different
+ from tlbie PowerPC opcode. Add PPC603 tlbld and tlbli.
+
+Thu Dec 28 13:29:19 1995 John Hassey <hassey@rtp.dg.com>
+
+ * i386-dis.c: Added Pentium Pro instructions.
+
+Tue Dec 19 22:56:35 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-opc.c (fsqrt{,.}): Duplicate for PowerPC in addition to
+ being for Power2.
+
+Fri Dec 15 14:14:15 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * sh-opc.h (sh_nibble_type): Added REG_B.
+ (sh_arg_type): Added A_REG_B.
+ (sh_table): Added pref and bank reg versions of ldc, ldc.l, stc
+ and stc.l opcodes.
+ * sh-dis.c (print_insn_shx): Added cases for REG_B and A_REG_B.
+
+Fri Dec 15 16:44:31 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * disassemble.c (disassembler): Use new bfd_big_endian macro.
+
+Tue Dec 12 12:22:24 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (distclean): Remove stamp-h. From Ronald
+ F. Guilmette <rfg@monkeys.com>.
+
+Tue Dec 5 13:42:44 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ From David Mosberger-Tang <davidm@azstarnet.com>:
+ * alpha-dis.c (print_insn_alpha): fixed decoding of cpys
+ instruction.
+
+Mon Dec 4 12:29:05 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * sh-opc.h (sh_arg_type): Added A_SSR and A_SPC.
+ (sh_table): Added many SH3 opcodes.
+ * sh-dis.c (print_insn_shx): Added cases for A_SSR and A_SPC.
+
+Fri Dec 1 07:42:18 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-opc.c (subfc., subfco): Mark this PPCCOM, not PPC.
+ (subco,subco.): Mark this PPC, not PPCCOM.
+
+Mon Nov 27 13:09:52 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Rebuild with autoconf 2.7.
+
+Tue Nov 21 18:28:06 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure: Rebuild with autoconf 2.6.
+
+Wed Nov 15 19:02:53 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * configure.in: Sort list of architectures. Accept but do nothing
+ for alliant, convex, pyramid, romp, and tahoe.
+
+Wed Nov 8 20:18:59 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * a29k-dis.c (print_special): Change num to unsigned int.
+
+Wed Nov 8 20:10:35 1995 Eric Freudenthal <freudenthal@nyu.edu>
+
+ * a29k-dis.c (print_insn): Cast insn24 to unsigned long when
+ shifting it.
+
+Tue Nov 7 15:21:06 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Call AC_CHECK_PROG to find and cache AR.
+ * configure: Rebuilt.
+
+Mon Nov 6 17:39:47 1995 Harry Dolan <dolan@ssd.intel.com>
+
+ * configure.in: Add case for bfd_i860_arch.
+ * configure: Rebuild.
+
+Fri Nov 3 12:45:31 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c (m68k_opcodes): Correct fmoveml operands.
+ * m68k-dis.c (NEXTSINGLE): Change i to unsigned int.
+ (NEXTDOUBLE): Likewise.
+ (print_insn_m68k): Don't match fmoveml if there is more than one
+ register in the list.
+ (print_insn_arg): Handle a place of '8' for a type of 'L'.
+
+Thu Nov 2 23:06:33 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c: Use #W rather than #w.
+ * m68k-dis.c (print_insn_arg): Handle new 'W' place.
+
+Wed Nov 1 13:30:24 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c (m68k_opcode_aliases): Add dbfw as an alias for dbf,
+ and likewise for all the dbxx opcodes.
+
+Mon Oct 30 20:50:40 1995 Fred Fish <fnf@cygnus.com>
+
+ * arc-dis.c: Include elf-bfd.h rather than libelf.h.
+
+Mon Oct 23 11:11:34 1995 James G. Smith <jsmith@pasanda.cygnus.co.uk>
+
+ * mips-opc.c: Added shorthand (V1) for INSN_4100 manifest. Added
+ the VR4100 specific instructions to the mips_opcodes structure.
+
+Thu Oct 19 11:05:23 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in, mpw-make.sed: Remove ugly workaround for
+ ugly Metrowerks bug in CW6, is fixed in CW7.
+
+Mon Oct 16 12:59:01 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-opc.c (whole file): Add flags for common/any support.
+
+Tue Oct 10 11:06:07 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (BISON): Remove macro.
+ (FLAGS_TO_PASS): Remove BISON.
+
+Fri Oct 6 16:26:45 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ Mon Sep 25 22:49:32 1995 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+ * m68k-dis.c (print_insn_m68k): Recognize all two-word
+ instructions that take no args by looking at the match mask.
+ (print_insn_arg): Always print "%" before register names.
+ [case 'c']: Use "nc" for the no-cache case, as recognized by gas.
+ [case '_']: Don't print "@#" before address.
+ [case 'J']: Use "%s" as format string, not register name.
+ [case 'B']: Treat place == 'C' like 'l' and 'L'.
+
+Thu Oct 5 22:16:20 1995 Ken Raeburn <raeburn@cygnus.com>
+
+ * i386-dis.c: Describe cmpxchg8b operand, and spell the opcode
+ name correctly.
+
+Tue Oct 3 08:30:20 1995 steve chamberlain <sac@slash.cygnus.com>
+
+ From David Mosberger-Tang <davidm@azstarnet.com>
+
+ * alpha-opc.h (MEMORY_FUNCTION_FORMAT_MASK): added.
+ (alpha_insn_set): added definitions for VAX floating point
+ instructions (Unix compilers don't generate these, but handcoded
+ assembly might still use them).
+
+ * alpha-dis.c (print_insn_alpha): added support for disassembling
+ the miscellaneous instructions in the Alpha instruction set.
+
+Tue Sep 26 18:47:20 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Add m68k-opc.c.o to BFD_MACHINES for m68k,
+ no longer create sysdep.h, sed ppc-opc.c to work around a
+ serious Metrowerks C bug.
+ * mpw-make.in: Remove.
+ * mpw-make.sed: New file, used by mpw-configure to edit
+ Makefile.in into an MPW makefile.
+
+Wed Sep 20 12:55:28 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New synonym for realclean.
+
+Tue Sep 19 15:28:36 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c: Split pmove patterns which use 'P' into patterns
+ which use '0', '1', and '2' instead. Specify the proper size for
+ a pmove immediate operand. Correct the pmovefd patterns to be
+ moves to a register, not from a register.
+ * m68k-dis.c (print_insn_arg): Replace 'P' with '0', '1', '2'.
+
+Thu Sep 14 11:58:22 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-opc.c (sparc_opcodes): Mark all insns that reference
+ %psr, %wim, %tbr as F_NOTV9.
+
+Fri Sep 8 01:07:38 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (Makefile): Just rebuild Makefile when running
+ config.status.
+ (config.h, stamp-h): New targets.
+ * configure.in: Call AC_CONFIG_HEADER and AC_CANONICAL_SYSTEM
+ earlier. Don't bother to call AC_ARG_PROGRAM. Touch stamp-h when
+ rebuilding config.h.
+ * configure: Rebuild.
+
+ * mips-opc.c: Change unaligned loads and stores with "t,A"
+ operands to use "t,A(b)".
+
+Thu Sep 7 19:02:46 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-dis.c (print_insn_shx): Add F_FR0 support.
+
+Thu Sep 7 19:02:46 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-dis.c (print_insn_shx): Change loop over op->arg[n] to iterate
+ until 3 instead of until 2.
+
+Wed Sep 6 21:21:33 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (ALL_CFLAGS): Define.
+ (.c.o, disassemble.o): Use $(ALL_CFLAGS).
+ (MOSTLYCLEAN): Add config.log.
+ (distclean): Don't remove config.log.
+ * configure.in: Substitute HDEFINES.
+ * configure: Rebuild.
+
+Wed Sep 6 15:08:09 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-opc.h (sh_arg_type): Add F_FR0.
+ (sh_table, case fmac): Add F_FR0 as first argument.
+
+Wed Sep 6 15:08:09 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-opc.h (sh_opcode_info): Increase arg array size to 4.
+
+Tue Sep 5 18:28:10 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-dis.c: Remove all references to NO_V9.
+
+Tue Sep 5 20:03:26 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * aclocal.m4: Just include ../bfd/aclocal.m4.
+ * configure: Rebuild.
+
+Tue Sep 5 16:09:59 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-dis.c (X_DISP19): Define.
+ (print_insn, case 'G'): Use it.
+ (print_insn, case 'L'): Sign extend displacement.
+
+Mon Sep 4 14:28:46 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * configure.in: Run ../bfd/configure.host before AC_PROG_CC.
+ Subsitute CFLAGS and AR. Call AC_PROG_INSTALL. Don't substitute
+ host_makefile_frag or frags.
+ * aclocal.m4: New file.
+ * configure: Rebuild.
+ * Makefile.in (INSTALL): Set to @INSTALL@.
+ (INSTALL_PROGRAM): Set to @INSTALL_PROGRAM@.
+ (INSTALL_DATA): Set to @INSTALL_DATA@.
+ (AR): Set to @AR@.
+ (AR_FLAGS): Set to rc rather than qc.
+ (CC): Define as @CC@.
+ (CFLAGS): Set to @CFLAGS@.
+ (@host_makefile_frag@): Remove.
+ (config.status): Remove dependency upon @frags@.
+
+ * configure.in: ../bfd/config.bfd now just sets shell variables.
+ Use them rather than looking through target Makefile fragments.
+ * configure: Rebuild.
+
+Thu Aug 31 12:35:32 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-opc.h (ftrc): Change FPUL_N to FPUL_M.
+
+Wed Aug 30 13:52:28 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-opc.c (sparc_opcodes): Delete duplicate wr %y insn.
+ Add clrx, iprefetch, signx, clruw, cas, casl, casx, casxl synthetic
+ sparc64 insns.
+
+ * sparc-opc.c (sparc_opcodes): Fix prefetcha insn.
+ (lookup_{name,value}): New functions.
+ (prefetch_table): New static local.
+ (sparc_{encode,decode}_prefetch): New functions.
+ * sparc-dis.c (print_insn): Handle '*' arg (prefetch function).
+
+Wed Aug 30 11:11:58 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-opc.h: Add blank lines to improve readabililty of sh3e
+ instructions.
+
+Wed Aug 30 11:09:38 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-dis.c: Correct comment on first line of file.
+
+Tue Aug 29 15:37:18 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * disassemble.c (disassembler): Handle bfd_mach_sparc64.
+
+ * sparc-opc.c (asi, membar): New static locals.
+ (sparc_{encode,decode}_{asi,membar}): New functions.
+ (sparc_opcodes, membar insn): Fix.
+ * sparc-dis.c (print_insn): Call sparc_decode_asi.
+ Support decoding of membar masks.
+ (X_MEMBAR): Define.
+
+Sat Aug 26 21:22:48 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c (m68k_opcode_aliases): Add br, brs, brb, brw, brl.
+
+Mon Aug 21 17:33:36 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c (m68k_opcode_aliases): Add bhib as an alias for bhis,
+ and likewise for the other branches. Add bhs as an alias for bcc,
+ and likewise for the size variants. Add dbhs as an alias for
+ dbcc.
+
+Fri Aug 11 13:40:24 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * sh-opc.h (FP sts instructions): Update to match reality.
+
+Mon Aug 7 16:12:58 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-dis.c: (fpcr_names): Add % before all register names.
+ (reg_names): Likewise.
+ (print_insn_arg): Don't explicitly print % before register names.
+ Add % before register names in static array names. In case 'r',
+ print data registers as `@(Dn)', not `Dn@'. When printing a
+ memory address, don't print @# before it.
+ (print_indexed): Change base_disp and outer_disp from int to
+ bfd_vma. Print using MIT syntax, not mutant invalid Motorola
+ syntax. Sign extend 8 byte displacement correctly.
+ (print_base): Print using MIT syntax. Print zpc when appropriate.
+ Change parameter disp from int to bfd_vma.
+
+ * m68k-opc.c (m68k_opcode_aliases): Add jsrl and jsrs as aliases
+ for jsr.
+
+Mon Aug 7 02:21:40 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * sh-dis.c (print_insn_shx): Handle new operand types F_REG_N,
+ F_REG_M, FPSCR_M, FPSCR_N, FPUL_M and FPUL_N.
+ * sh-opc.h (sh_arg_type): Add new operand types.
+ (sh_table): Add new opcodes from SH3E Floating Point ISA.
+
+Sat Aug 5 16:50:14 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (distclean): Remove generated file config.h.
+
+Sat Aug 5 16:50:14 1995 Fred Fish <fnf@cygnus.com>
+
+ * Makefile.in (distclean): Remove generated file config.h.
+
+Wed Aug 2 18:33:40 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * m68k-opc.c: New file, holding tables from include/opcode/m68k.h.
+ Clean up tables.
+ * m68k-dis.c: Remove BREAK_UP_BIG_DECL stuff.
+ (opcode): Remove.
+ (print_insn_m68k): Change d to be const. Use m68k_numopcodes
+ rather than numopcodes. Use m68k_opcodes rather than removed
+ opcode function. Don't check F_ALIAS.
+ (print_insn_arg): Change first parameter to be const char *.
+ * Makefile.in (ALL_MACHINES): Add m68k-opc.o.
+ (m68k-opc.o): New target.
+ * configure.in: Build m68k-opc.o for bfd_m68k_arch.
+ * configure: Rebuild.
+
+Wed Aug 2 08:23:38 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-dis.c (HASH_SIZE, HASH_INSN): Define.
+ (opcode_bits, opcode_hash_table): New variables.
+ (opcodes_initialized): Renamed from opcodes_sorted.
+ (build_hash_table): New function.
+ (is_delayed_branch): Use hash table.
+ (print_insn): Renamed from print_insn_sparc, made static.
+ Build and use hash table. If !sparc64, ignore sparc64 insns,
+ and vice-versa if sparc64.
+ (print_insn_sparc, print_insn_sparc64): New functions.
+ (compare_opcodes): Move sparc64 opcodes to end.
+ Print commutative insns with constant second.
+ * sparc-opc.c (all non-v9 insns): Use flag F_NOTV9 instead of F_ALIAS.
+
+Tue Aug 1 00:12:49 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * sh-dis.c (print_insn_shx): Remove unused local dslot. Use
+ print_address_func for A_BDISP12 and A_BDISP8. Correct test which
+ avoids printing a delay slot in a delay slot.
+ * sh-opc.h (sh_table): Fully bracket last entry.
+
+Mon Jul 31 12:04:47 1995 Doug Evans <dje@canuck.cygnus.com>
+
+ * sparc-opc.c (sllx, srax, srlx): Fix disassembly.
+
+Wed Jul 12 00:59:34 1995 Ken Raeburn <raeburn@kr-pc.cygnus.com>
+
+ * configure.in: Get host_makefile_frag from ${srcdir}.
+
+ * configure.in: Autoconfiscated. Check for string[s].h. Create
+ config.h from config.in. Don't set up sysdep.h link.
+ * sysdep.h: New file.
+ * configure, config.in: New files, generated from configure.in.
+ * Makefile.in: Updated to be processed autoconf-style.
+ (distclean): Keep sysdep.h. Remove config.log and config.cache.
+ (Makefile): Depend on config.status.
+ (config.status): New rule.
+ * configure.bat: Update Makefile substitutions.
+
+Tue Jul 11 14:23:37 1995 Jeff Spiegel <jeffs@lsil.com>
+
+ * mips-opc.c (L1): Define.
+ (mips_opcodes): Add R4010 instructions: flushi, flushd, flushid,
+ addciu, madd, maddu, ffc, ffs, msub, msubu, selsi, selsr, waiti,
+ and wb.
+
+Tue Jul 11 11:49:49 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips-opc.c (mips_opcodes): For the move pseudo-op, prefer daddu
+ if ISA 3 and addu otherwise, replacing or, since some MIPS chips
+ have multiple add units but only a single logical unit.
+
+ * ppc-opc.c (powerpc_operands): Change CR to use a bitsize of 3,
+ shifted by 18, without any insertion or extraction function.
+ (insert_cr, extract_cr): Remove.
+
+Wed Jun 21 20:05:39 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * m68k-dis.c (print_insn_arg, print_indexed): Print "%" before
+ register names.
+
+Thu Jun 15 17:23:31 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * mpw-config.in: Add sh and i386 configs, remove sparc config.
+ * sh-opc.h: Add copyright.
+
+Mon Jun 5 03:30:43 1995 Ken Raeburn <raeburn@kr-laptop.cygnus.com>
+
+ * Makefile.in (crunch-m68k): Delete extra target accidentally
+ checked in a while ago.
+
+Wed May 24 16:22:13 1995 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * sh-opc.h (sh_table): Add SH3 support.
+
+Wed May 24 14:16:08 1995 Steve Chamberlain <sac@slash.cygnus.com>
+
+ * sh-opc.h: Added bsrf and braf.
+
+Wed May 10 14:28:16 1995 Richard Earnshaw (rearnsha@armltd.co.uk)
+
+ * arm-opc.h (arm_opcodes): Add 64-bit multiply patterns. Delete
+ bogus [ls]fm{ea,fd} patterns.
+
+ * arm-opc.h (arm_opcodes): Correct typos in stm, ldm, std, and ldc.
+ * arm-dis.c (print_insn_arm): Make GIVEN a parameter, don't try and
+ initialize it from memory. Make function static.
+ (print_insn_{big,little}_arm): New functions.
+ * disassemble.c (disassembler, case bfd_arch_arm): Disassemble for
+ the correct endianness.
+
+
+Mon Apr 24 14:18:05 1995 Jason Molenda (crash@phydeaux.cygnus.com>
+
+ * sh-opc.h (sh_nibble_type, sh_arg_type): remove trailing , from
+ enum list.
+
+Wed Apr 19 14:07:03 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * m68k-dis.c (opcode): Finish change made by Kung Hsu on April
+ 17th, so that it builds again using GCC as the compiler.
+
+Tue Apr 18 12:14:51 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * mips-dis.c (print_insn_little_mips): Cast return value from
+ bfd_getl32 from bfd_vma to unsigned long, because _print_insn_mips
+ expects an unsigned long, and that might be fewer words of
+ argument storage (e.g., if bfd_vma is long long on a 32-bit
+ machine).
+ (print_insn_big_mips): Likewise with bfd_getb32 value.
+ (_print_insn_mips): Now static.
+
+Mon Apr 17 12:23:28 1995 Kung Hsu <kung@rtl.cygnus.com>
+
+ * m68k-dis.c: Take out #define BREAK_UP_BIG_DECL kludge, because
+ gcc memory hog problem with initializer is fixed.
+
+
+Mon Apr 10 15:55:01 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ Merge in support for Mac MPW as a host.
+ (Old change descriptions retained for informational value.)
+
+ * mpw-config.in (archname): Compute from the config.
+ (BFD_MACHINES, ARCHDEFS): Put into mk.tmp.
+
+ * mpw-config.in (target_arch): Compute from canonical target.
+ (m68k, mips, powerpc, sparc): Add architectures.
+ * mpw-make.in (disassemble.c.o): Add.
+ (ALL_CFLAGS): Remove special flags (-mc68020 -mc68881 -model far).
+
+ * mpw-config.in (BFD_MACHINES): Set to a default value.
+ * mpw-make.in (BFD_MACHINES): Remove wired-in value.
+
+ * mpw-make.in (CSEARCH): Add extra-include to search path.
+
+ * mpw-config.in (varargs.h): Don't create.
+ (sysdep.h): Create using forward-include.
+ * mpw-make.in (CSEARCH): Add include/mpw to search path.
+
+ * mpw-config.in: New file, MPW version of configure.in.
+ * mpw-make.in: New file, MPW version of Makefile.in.
+
+
+Fri Mar 31 14:23:38 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * alpha-dis.c (print_insn_alpha): Put empty statement after
+ default label.
+
+Tue Mar 21 10:51:40 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-dis.c (sign_extend): Delete, redundant with libhppa.h version.
+ (low_sign_extend): Likewise.
+ (get_field): Delete unused function.
+ (set_field, deposit_14, deposit_21): Likewise.
+
+Fri Mar 17 15:55:53 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * i386-dis.c: Support for more pentium opcodes. From Guy Harris
+ (guy@netapp.com).
+
+Tue Mar 14 00:52:57 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com)
+
+ Sat Feb 11 17:22:41 1995 Klaus Kaempf (kkaempf@didymus.rmi.de)
+
+ * alpha-opc.h (OSF_ASMCODE): define
+ print pal-code names as defined in App C of the
+ Alpha Architecture Reference Manual
+
+ * alpha-dis.c: cleaned up output
+ print stylized code forms as defined in App A.4.3 of the
+ Alpha Architecture Reference Manual
+
+Wed Mar 8 15:21:14 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips-opc.c: Add new mips4 instructions. Don't set INSN_RFE for
+ `rfe'.
+ * mips-dis.c (print_insn_arg): Handle new argument types 'h', 'R',
+ 'N', and 'M'.
+
+Wed Mar 8 02:54:05 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * m68k-dis.c (opcode): New function. Returns address of opcode
+ table entry given index, even if the opcode table was split to
+ work around gcc bugs.
+ (print_insn_m68k): Call opcode instead of referencing m68k_opcodes
+ directly.
+ (BREAK_UP_BIG_DECL): Make secondary array static and const.
+ (reg_names): Now const.
+ (print_insn_arg): Arrays cacheFieldName and names now const.
+ (print_indexed): Array scales now const.
+
+
+Tue Mar 7 16:41:21 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ppc-opc.c: Sort recently added instructions by minor opcode
+ number within major opcode number.
+
+Mon Mar 6 10:04:36 1995 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-dis.c: Include libhppa.h.
+
+Fri Feb 24 19:15:36 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips-opc.c: Change dli to use M_DLI, and add dla.
+
+Mon Feb 20 23:54:38 1995 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * Makefile.in (ALL_MACHINES): Add w65-dis.o.
+
+
+Thu Feb 16 17:34:41 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips-opc.c: Add r4650 mul instruction.
+
+Wed Feb 15 15:45:20 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * mips-opc.c: Add uld and usd macros for unaligned double load and
+ store.
+
+Tue Feb 14 13:17:37 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-opc.c (powerpc_opcodes): Add 403GA opcodes rfci, dccci,
+ mfdcr, mtdcr, icbt, iccci.
+
+
+Thu Feb 9 12:28:13 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * i960-dis.c (struct tabent, struct sparse_tabent): Change the
+ signed char fields to shorts, more portable.
+
+Wed Feb 8 17:29:29 1995 Stan Shebs <shebs@andros.cygnus.com>
+
+ * i960-dis.c (struct tabent, struct sparse_tabent): Declare the
+ char fields as signed chars, since they may have negative values.
+
+Mon Feb 6 10:52:06 1995 J.T. Conklin <jtc@rtl.cygnus.com>
+
+ * i386-dis.c (dis386_twobyte): Add cpuid, From Charles Hannum
+ (mycroft@netbsd.org).
+
+Mon Jan 30 12:38:00 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ From "Logg, Ed" <elogg@ea.com>:
+ * ppc-opc.c (extract_bdm): Correct parenthezisation.
+ * ppc-dis.c (print_insn_powerpc): Print .long before unrecognized
+ value.
+
+Thu Jan 26 18:32:08 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * ppc-opc.c: Changes based on patch from David Edelsohn
+ <edelsohn@mhpcc.edu>.
+ (powerpc_operands): Add operands SPRBAT and SPRG. Split TBR out of
+ SPR.
+ (FXM_MASK): Define.
+ (insert_tbr): New static function.
+ (extract_tbr): New static function.
+ (XFXFXM_MASK, XFXM): Define.
+ (XSPRBAT_MASK, XSPRG_MASK): Define.
+ (powerpc_opcodes): Add instructions to access special registers by
+ name. Add mtcr and mftbu.
+
+Tue Jan 17 10:56:43 1995 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * mips-opc.c (P3): Define.
+ (mips_opcodes): Add mad and madu.
+
+Sun Jan 15 16:32:59 1995 Steve Chamberlain <sac@splat>
+
+ * configure.in: Add W65 support.
+ * disassemble.c: Likewise.
+ * w65-opc.h, w65-dis.c: New files.
+
+Wed Dec 28 22:15:33 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * h8300-dis.c (bfd_h8_disassemble): Add support for 2 bit
+ immediates.
+
+
+Tue Dec 20 11:25:12 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * mips-opc.c: Add dli as a synonym for li.
+
+
+Thu Dec 8 18:23:31 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * alpha-dis.c (print_insn_alpha): Handle call_pal instruction, and
+ print something for reserved opcode values, even if it won't
+ assemble again.
+
+ * mips-dis.c (_print_insn_mips): When initializing, shift right
+ and mask, to avoid sign extension problems on the Alpha.
+
+ * m68k-dis.c (print_insn_arg, case 'J'): Handle buscr and pcr
+ control registers.
+
+
+Wed Nov 23 22:34:51 1994 Steve Chamberlain (sac@jonny.cygnus.com)
+
+ * sh-opc.h (mov.l gbr): Get direction right.
+ * sh-dis.c (print_insn_shx): New function.
+ (print_insn_shl, print_insn_sh): Call print_insn_shx to
+ print opcodes with right byte order.
+
+Thu Nov 3 19:32:22 1994 Ken Raeburn <raeburn@cujo.cygnus.com>
+
+ * ns32k-dis.c (struct ns32k_option): Renamed from struct option,
+ to avoid conflicts with getopt.
+
+Mon Oct 31 18:48:10 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * hppa-dis.c (print_insn_hppa): Read the instruction using
+ bfd_getb32, so that it works on a little endian or 64 bit host.
+ Remove unused local variable op.
+
+Tue Oct 25 17:07:57 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * mips-opc.c: Use or instead of addu for pseudo-op move, since
+ addu does not work correctly if -mips3.
+
+Wed Oct 19 13:40:16 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * a29k-dis.c (print_special): Add special register names defined
+ on 29030, 29040 and 29050.
+ (print_insn): Handle new operand type 'I'.
+
+Wed Oct 12 11:59:55 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * Makefile.in (INSTALL): Use top level install.sh script.
+
+Wed Oct 5 19:16:29 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * sparc-dis.c: Rewrite to use bitfields, rather than a union, so
+ that it works on a little endian host.
+
+Tue Oct 4 12:14:21 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+
+ * configure.in: Use ${config_shell} when running config.bfd.
+
+Wed Sep 21 18:49:12 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mips-opc.c (mips_opcodes): "dabs" is only available with -mips3.
+
+Thu Sep 15 16:30:22 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * a29k-dis.c (print_insn): Print the opcode.
+
+Wed Sep 14 17:52:14 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mips-opc.c (mips_opcodes): Set WR_t for sc and scd.
+
+Sun Sep 11 22:32:17 1994 Jeff Law (law@snake.cs.utah.edu)
+
+ * hppa-dis.c (reg_names): Use r26-r23 for arg0-arg3.
+
+Tue Sep 6 11:37:12 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mips-opc.c: Set INSN_STORE_MEMORY flag for all instructions
+ which store a value into memory.
+
+Sun Sep 04 17:58:10 1994 Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+
+ * configure.in, Makefile.in, disassemble.c: Add support for the ARM.
+ * arm-dis.c, arm-opc.h: New files.
+
+Fri Aug 5 14:00:05 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * Makefile.in (ns32k-dis.o): Add dependency.
+ * ns32k-dis.c (print_insn_arg): Declare initialized local as
+ string, not as array of chars.
+
+Thu Jul 28 18:14:16 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * sparc-dis.c (print_insn_sparc): Handle new operand type 'x'.
+
+ * sparc-opc.c: Added sparclite extended FP operations, and
+ versions of v9 impdep* instructions permitting specification of
+ the OPF field.
+
+Tue Jul 26 16:36:03 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * i960-dis.c (reg_names): Now const.
+ (struct sparse_tabent): New type, copied from array type in mem
+ function.
+ (ctrl): Local static array ctrl_tab now const.
+ (cobr): Local static array cobr_tab now const.
+ (mem): Local variables reg1, reg2, reg3 now point to const. Local
+ static variable mem_tab no longer explicitly initialized. Changed
+ mem_init to const array of struct sparse_tabent.
+ (reg): Local static variable reg_tab no longer explicitly
+ initialized. Changed reg_init to const array of struct
+ sparse_tabent.
+ (ea): Local static array scale_tab now const.
+
+ * i960-dis.c (reg): Added i960JX instructions to reg_init table.
+ (REG_MAX): Updated.
+
+Tue Jul 19 21:00:00 1994 DJ Delorie (dj@ctron.com)
+
+ * configure.bat: the disassember needs to be enabled for
+ "objdump -d" to work in djgpp.
+
+Wed Jul 13 18:01:58 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * ns32k-dis.c: Deleted all code in "#ifdef GDB".
+ (invalid_float): Enabled general version, doesn't require running
+ on ns32k host. Changed to take char* argument, and test for
+ explicitly specified sizes, instead of using sizeof() on host CPU
+ types.
+ (INVALID_FLOAT): Cast first argument.
+ (opt_u, opt_U, opt_O, opt_C, opt_S, list_P532, list_M532,
+ list_P032, list_M032): Now const.
+ (optlist, list_search): Made appropriate arguments now point to
+ const.
+ (print_insn_arg): Changed static array of one-character-string
+ pointers into a static const array of characters; fixed sprintf
+ statement accordingly.
+
+Sun Jul 10 00:27:47 1994 Ian Dall (dall@hfrd.dsto.gov.au)
+
+ * opcodes/ns32k-dis.c: Semi-new file. Had apparently been dropped
+ from distribution. A ns32k-dis.c from a previous distribution has
+ been brought up to date and supports the new interface.
+
+ * disassemble.c: define ARCH_ns32k and add case bfd_arch_ns32k.
+
+ * configure.in: add bfd_ns32k_arch target support.
+
+ * Makefile.in: add ns32k-dis.o to ALL_MACHINES.
+ Add ns32k-dis.c to CFILES. Add dependencies for ns32k-dis.o.
+
+Wed Jun 29 22:10:37 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * h8300-dis.c (bfd_h8_disassemble): Get 16bit branch
+ disassembly right.
+
+Tue Jun 28 13:22:06 1994 Stan Shebs (shebs@andros.cygnus.com)
+
+ * h8300-dis.c, mips-dis.c: Don't use true and false.
+
+Thu Jun 23 12:53:19 1994 David J. Mackenzie (djm@rtl.cygnus.com)
+
+ * configure.in: Change --with-targets to --enable-targets.
+
+Wed Jun 22 13:38:32 1994 Ian Lance Taylor (ian@sanguine.cygnus.com)
+
+ * mips-dis.c (_print_insn_mips): Build a static hash table mapping
+ opcodes to the first instruction with that opcode, to speed
+ disassembly of large files. From ralphc@pyramid.com (Ralph
+ Campbell).
+
+Tue Jun 7 12:49:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * Makefile.in (mostlyclean): Fix typo (was mostyclean).
+
+Wed May 11 22:32:00 1994 DJ Delorie (dj@ctron.com)
+
+ * configure.bat: update to latest makefile.in
+
+Sat May 7 17:13:21 1994 Steve Chamberlain (sac@cygnus.com)
+
+ * a29k-dis.c (print_insn): Print 'x' type operand in hex.
+ * h8300-dis.c (bfd_h8_disassemble): Print 16bit rels correctly.
+ * sh-dis.c (print_insn_sh): Don't recur endlessly if delay
+ slot insn is in a delay slot.
+ * z8k-opc.h: (resflg): Fix patterns.
+ * h8500-opc.h Fix CR insn patterns.
+
+Fri May 6 14:34:46 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc-opc.c (powerpc_opcodes): Put PowerPC versions of "cmp" and
+ "cmpl" before POWER versions, so that gas -many uses them.
+
+Thu Apr 28 18:32:36 1994 Ken Raeburn (raeburn@cujo.cygnus.com)
+
+ * disassemble.c: New file.
+ * Makefile.in (OFILES): Add disassemble.o.
+ (disassemble.o): Provide dependencies; compile with $(ARCHDEFS).
+ * configure.in: Define ARCHDEFS in Makefile. Code taken from
+ binutils/configure.in.
+
+ * m68k-dis.c (print_insn_m68k): If F_ALIAS flag is set, skip the
+ opcode being examined.
+
+Thu Apr 21 17:08:40 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc-opc.c (powerpc_operands): Added RAL, RAM and RAS.
+ (insert_ral, insert_ram, insert_ras): New functions.
+ (powerpc_opcodes): Use RAL for load with update, RAM for lmw, and
+ RAS for store with update.
+
+Sat Apr 16 23:41:44 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc-opc.c (powerpc_opcodes): Correct fcir. From David Edelsohn
+ (edelsohn@npac.syr.edu).
+
+Wed Apr 6 17:11:45 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c (mips_opcodes): Correct operands of "nor" with an
+ immediate argument.
+
+Mon Apr 4 16:30:46 1994 Doug Evans (dje@canuck.cygnus.com)
+
+ * sparc-opc.c (sparc_opcodes): Fix "rd %fprs,%l0".
+
+Mon Apr 4 13:22:00 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc-opc.c (powerpc_operands): The signedp field has been
+ removed, so don't initialize it. Set the PPC_OPERAND_SIGNED flag
+ instead. Add new operand SISIGNOPT.
+ (powerpc_opcodes): For lis, liu, addis, and cau use SISIGNOPT.
+ Based on patch from David Edelsohn (edelsohn@npac.syr.edu).
+ * ppc-dis.c (print_insn_powerpc): Check PPC_OPERAND_SIGNED rather
+ than signedp field.
+
+Wed Mar 30 00:31:49 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * i386-dis.c (struct private): Renamed to dis_private. `private'
+ is a reserved word for dynix cc.
+
+Mon Mar 28 13:00:15 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Change error message to refer to bfd/config.bfd
+ rather than bfd/configure.in.
+
+Mon Mar 28 12:28:30 1994 David Edelsohn (edelsohn@npac.syr.edu)
+
+ * ppc-opc.c: Define POWER2 as short alias flag.
+ (powerpc_opcodes): Add POWER/2 opcodes lfq*, stfq*, fcir[z], and
+ fsqrt.
+
+Wed Mar 23 12:23:05 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i960-dis.c (print_insn_i960): Don't read a second word for
+ opcodes 0, 1, 2 and 3.
+
+Wed Mar 16 15:37:58 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in: Don't build m68881-ext.o for bfd_m68k_arch.
+
+Mon Mar 14 14:53:50 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m68881-ext.c: Removed; no longer used.
+ * Makefile.in: Changed accordingly.
+
+ * m68k-dis.c (ext_format_68881): Don't declare.
+ (print_insn_m68k): If an instruction uses place 'i', it uses at
+ least four fixed bytes.
+ (print_insn_arg): Don't bump p by 2 for case 'I', place 'i'. For
+ extended float, convert to double using floatformat_to_double, not
+ ieee_extended_to_double, and fetch the data before converting it.
+
+Tue Mar 8 18:12:25 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: It's sqrt.s, not sqrt.w. From
+ davidj@ICSI.Berkeley.EDU (David Johnson).
+
+Tue Feb 8 16:55:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc-opc.c (powerpc_opcodes): The POWER uses bdn[l][a] where the
+ PowerPC uses bdnz[l][a].
+
+Tue Feb 8 00:32:28 1994 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * dis-buf.c, i386-dis.c: Include sysdep.h.
+
+Mon Feb 7 19:22:23 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * configure.in (bfd_powerpc_arch): Use ppc-dis.o and ppc-opc.o.
+
+ * ppc-opc.c (powerpc_opcodes): Mark POWER instructions supported
+ by Motorola PowerPC 601 with PPC_OPCODE_601.
+ * ppc-dis.c (print_insn_big_powerpc, print_insn_little_powerpc):
+ Disassemble Motorola PowerPC 601 instructions as well as normal
+ PowerPC instructions.
+
+Sun Feb 6 07:45:17 1994 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * i960-dis.c (reg, mem): Just use a static array instead of
+ calling xmalloc.
+
+Sat Feb 5 00:04:02 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-dis.c (print_insn_hppa): For '?' and '@' only adjust the
+ condition name index if this is for a negated condition.
+
+ * hppa-dis.c (print_insn_hppa): No space before 'H' operand.
+ Floating point format for 'H' operand is backwards from normal
+ case (0 == double, 1 == single). For '4', '6', '7', '9', and '8'
+ operands (fmpyadd and fmpysub), handle bizarre register
+ translation correctly for single precision format.
+
+ * hppa-dis.c (print_insn_hppa): Do not emit a space after 'F'
+ or 'I' operands if the next format specifier is 'M' (fcmp
+ condition completer).
+
+Feb 4 23:38:03 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc-opc.c (powerpc_operands): New operand type MBE to handle a
+ single number giving a bitmask for the MB and ME fields of an M
+ form instruction. Change NB to accept 32, and turn it into 0;
+ also turn 0 into 32 when disassembling. Seperated SH from NB.
+ (insert_mbe, extract_mbe): New functions.
+ (insert_nb, extract_nb): New functions.
+ (SC_MASK): Mask out SA and LK bits.
+ (powerpc_opcodes): Change "cal" to use RT, D, RA rather than RT,
+ RA, SI. Change "liu" and "cau" to use UI rather than SI. Mark
+ "bctr" and "bctrl" as accepted by POWER. Change "rlwimi",
+ "rlimi", "rlwimi.", "rlimi.", "rlwinm", "rlinm", "rlwinm.",
+ "rlinm.", "rlmi", "rlmi.", "rlwnm", "rlnm", "rlwnm.", "rlnm." to
+ use MBE rather than MB. Add "mfmq" and "mtmq" POWER instructions.
+ (powerpc_macros): Define table of macro definitions.
+ (powerpc_num_macros): Define.
+
+ * ppc-dis.c (print_insn_powerpc): Don't skip optional operands
+ if PPC_OPERAND_NEXT is set.
+
+Sat Jan 22 23:10:07 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * i960-dis.c (print_insn_i960): Make buffer bfd_byte instead of
+ char. Retrieve contents using bfd_getl32 instead of shifting.
+
+Fri Jan 21 19:01:39 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * ppc-opc.c: New file. Opcode table for PowerPC, including
+ opcodes for POWER (RS/6000).
+ * ppc-dis.c: New file. PowerPC and Power (RS/6000) disassembler.
+ * Makefile.in (ALL_MACHINES): Add ppc-dis.o and ppc-opc.o.
+ (CFILES): Add ppc-dis.c.
+ (ppc-dis.o, ppc-opc.o): New targets.
+ * configure.in: Build ppc-dis.o and ppc-opc.o for bfd_rs6000_arch.
+
+Mon Jan 17 20:05:49 1994 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * hppa-dis.c (print_insn_hppa): Handle 'N' in assembler template.
+ No space before 'u', 'f', or 'N'.
+
+Sun Jan 16 14:20:16 1994 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * i386-dis.c (print_insn_i386): Add FIXME comment regarding reading
+ farther than we should.
+
+ * i386-dis.c (dis386): Use Yb and Yv for scasb and scasS.
+
+Thu Jan 6 12:38:05 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * sparc-dis.c m68k-dis.c alpha-dis.c a29k-dis.c: Fix comments.
+
+Wed Jan 5 11:56:21 1994 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * i960-dis.c (print_insn_i960): Only read word2 if the instruction
+ needs it, to prevent reading past the end of a section.
+
+Wed Nov 17 17:20:12 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.h: Use macro for j instruction, to support SVR4 PIC.
+ Removed t,A case for la; always use t,A(b) case.
+
+Mon Nov 8 12:37:36 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ From Ted Lemen <mellon@pepper.ncd.com>
+ * mips-dis.c (print_insn_arg): Handle 'k'.
+ * mips-opc.c: Make cache use k, not t.
+
+Sun Nov 7 23:52:34 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-opc.h, alpha-dis.c (print_insn_alpha): Add
+ FLOAT_MEMORY_FORMAT_CODE, FLOAT_BRANCH_FORMAT_CODE, correct
+ FLOAT_FORMAT_CODE to put out floating point register names.
+
+Mon Nov 1 18:17:51 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Use macros for jal variants, to support SVR4 PIC.
+
+Thu Oct 28 17:42:23 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * a29k-dis.c (print_insn): Use 0x%08x, not 0x%8x.
+
+Wed Oct 27 11:48:01 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c (dsll, dsra, dsrl): Added '>' cases for shift counts
+ larger than 32. Moved dsxx32 variants first for disassembler.
+
+Mon Oct 25 11:33:14 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * z8kgen.c, z8k-opc.h: Add full lda information.
+
+Tue Oct 19 12:39:25 1993 Jeffrey A Law (law@cs.utah.edu)
+
+ * hppa-dis.c (print_insn_hppa): Do not emit a space after
+ movb instructions. Any necessary space will be emitted by
+ the code to handle nullification completers.
+
+Wed Oct 13 16:19:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Moved l.d down so that it disassembles as ldc1.
+
+Fri Oct 8 02:34:21 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-opc.h: Add ldl_l, fix typo for ldq_u.
+ * alpha-dis.c (print_insn_alpha): Add code for PAL_FORMAT_CODE.
+
+Tue Oct 5 17:47:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Correct lwu opcode value (book had it wrong).
+
+Thu Sep 30 11:26:18 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * z8k-dis.c (FETCH_DATA): get just the right amount of data.
+ (unpack_instr): Cope with ARG_IMM4M1 type instructions.
+
+Wed Sep 29 16:24:49 1993 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * m88k-dis.c (m88kdis): comment change. Remove space after
+ printing mnemonic.
+ (printop): handle new arg types DEC and XREG for m88110.
+
+Tue Sep 28 19:20:16 1993 Jeffrey A Law (law@snake.cs.utah.edu)
+
+ * hppa-dis.c (print_insn_hppa): Handle 'z' operand
+ type for absolute branch addresses. Delete special
+ "ble" and "be" code in 'W' operand code.
+
+Fri Sep 24 14:08:33 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Set hazard information correctly for branch
+ likely instructions.
+
+Fri Sep 17 04:41:17 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * alpha-dis.c (print_insn_alpha), alpha-opc.h: Fix bugs, use
+ info->fprintf_func for printing and info->print_address_func for
+ address output.
+
+Wed Sep 15 12:12:07 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Set INSN_TRAP for tXX instructions.
+
+Thu Sep 9 10:11:27 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: From davidj@ICSI.Berkeley.EDU (David Johnson):
+ Corrected second case of "b" for disassembler.
+
+Tue Sep 7 14:25:15 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-dis.c, m88k-dis.c: Don't include libbfd.h. Changed calls
+ to BFD swapping routines to correspond to BFD name changes.
+
+Thu Sep 2 10:35:25 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Change div machine instruction to be z,s,t rather
+ than s,t. Change div macro to be d,v,t rather than d,s,t.
+ Likewise for divu, ddiv, ddivu. Added z,s,t case for drem, dremu,
+ rem and remu which generates only the corresponding div
+ instruction. This is for compatibility with the MIPS assembler,
+ which only generates the simple machine instruction when an
+ explicit destination of $0 is used.
+ * mips-dis.c (print_insn_arg): Handle 'z' (always register zero).
+
+Thu Aug 26 17:41:44 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: From davidj@ICSI.Berkeley.EDU (David Johnson): Set
+ WR_31 hazard for bal, bgezal, bltzal.
+
+Thu Aug 26 17:20:02 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * hppa-dis.c (print_insn_hppa): Use print function
+ from within the disassemble_info, not fprintf_filtered.
+
+Wed Aug 25 13:51:40 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * hppa-dis.c (print_insn_hppa): Handle '|' like '>'. (From Jeff
+ Law, law@cs.utah.edu.)
+
+Mon Aug 23 12:44:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c ("absu"): Removed.
+ ("dabs"): Added.
+
+Fri Aug 20 10:52:52 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Added r6000 and r4000 instructions and macros.
+ Changed hazard information to distinguish between memory load
+ delays and coprocessor load delays.
+
+Wed Aug 18 15:39:23 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: li.d uses "T,L", not "S,F". Added li.s.
+
+Tue Aug 17 09:44:42 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * configure.in: Don't pass cpu to config.bfd.
+
+Tue Aug 17 12:23:52 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m88k-dis.c (m88kdis): Make class unsigned.
+
+Thu Aug 12 15:08:18 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * alpha-dis.c (print_insn_alpha): One branch format case was
+ missing the instruction name.
+
+Wed Aug 11 19:29:39 1993 David J. Mackenzie (djm@thepub.cygnus.com)
+
+ * Makefile.in (ALL_MACHINES): Renamed from DIS_LIBS.
+ Add the arch-specific auxiliary files.
+ (OFILES): Remove the arch-specific auxiliary files
+ and use BFD_MACHINES instead of DIS_LIBS.
+ * configure.in: Set BFD_MACHINES based on --with-targets option.
+
+Thu Aug 12 12:04:53 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: Added lwc1 E,A(b) to go with lwc1 T,A(b). Similarly
+ for swc1.
+
+Sun Aug 8 15:09:30 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-opc.c: Change CONST to const to deal with gcc
+ -Dconst=__const -traditional.
+
+Fri Aug 6 10:58:55 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-opc.c: From davidj@ICSI.Berkeley.EDU (David Johnson): Took
+ coprocessor instructions out of #if 0, and made them use new
+ argument type "C".
+
+Thu Aug 5 17:11:06 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * sparc-dis.c: Include ansidecl.h before opcodes/sparc.h.
+
+Fri Jul 30 18:48:15 1993 John Gilmore (gnu@cygnus.com)
+
+ * sparc-opc.c: Add F_JSR, F_UNBR, or F_CONDBR flags to each branch
+ instruction, for use by the disassembler.
+
+ * sparc-dis.c (SEX): Add sign extension macro. Replace many
+ hand-coded sign extensions that depended on 32-bit host ints.
+ FIXME, we still depend on big-endian host bitfield ordering.
+ (sparc_print_insn): Set the insn_info_valid field, and the
+ other fields that describe the instruction being printed.
+
+Tue Jul 27 17:04:58 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+
+ * sparc-opc.c (call): Accept all 6 addressing modes valid for
+ `jmp' instead of just one of them.
+
+Wed Jul 21 11:43:32 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * hppa-dis.c: Move floating registers from reg_names to fp_reg_names.
+ (fput_fp_reg_r): Renamed from fput_reg_r.
+ (fput_fp_reg): New function.
+ (print_insn_hppa): Use fput_fp_reg{,_r} where appropriate.
+
+ * hppa-dis.c (print_insn_hppa, cases 'a', 'd'): Print space afterwards.
+
+ * hppa-dis.c (print_insn_hppa, case 'd'): Use GET_COND not GET_FIELD.
+
+Mon Jul 19 13:52:21 1993 Jim Kingdon (kingdon@deneb.cygnus.com)
+
+ * hppa-dis.c (print_insn_hppa): Use extract_5r_store for 'r'.
+
+ * hppa-dis.c (print_insn_hppa, case '>'): If next character is 'n',
+ don't output a space.
+
+ * hppa-dis.c (float_format_names): 10 is undefined, and 11 is quad.
+
+Sun Jul 18 16:30:02 1993 Jim Kingdon (kingdon@rtl.cygnus.com)
+
+ * mips-opc.c: New file, containing opcode table from
+ ../include/opcode/mips.h.
+ * Makefile.in: Add it.
+
+Thu Jul 15 12:37:05 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * m88k-dis.c: New file, moved in from gdb and changed to use the
+ new dis-asm.h disassembler interface.
+ * Makefile.in (DIS_LIBS): Added m88k-dis.o.
+ (m88k-dis.o): New target.
+
+Tue Jul 13 10:04:16 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-dis.c (print_insn_arg, _print_insn_mips): Made pointer to
+ argument string const char * to correspond to opcode/mips.h.
+
+Tue Jul 6 15:18:37 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * mips-dis.c: Updated to account for name changes in new version
+ of opcode/mips.h.
+ * Makefile.in: Added header file dependencies.
+
+Sat Jul 3 23:47:56 1993 Doug Evans (dje@canuck.cygnus.com)
+
+ * h8300-dis.c (bfd_h8_disassemble): Correct fetching of instruction.
+
+Thu Jul 1 12:23:38 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * m68k-dis.c (NEXTWORD, NEXTLONG): Use ((x) ^ 0x8000) - 0x8000 to sign
+ extend, rather than shifts.
+
+Sun Jun 20 20:56:56 1993 Ken Raeburn (raeburn@poseidon.cygnus.com)
+
+ * Makefile.in: Undo 15 June change.
+
+Fri Jun 18 14:15:15 1993 Per Bothner (bothner@deneb.cygnus.com)
+
+ * m68k-dis.c (print_insn_arg): Change return value to byte count
+ or error code.
+ * m68k-dis.c: Re-write to detect invalid operands before
+ printing anything, so we can handle this the same way we
+ handle invalid opcodes.
+
+Thu Jun 17 15:01:36 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * sh-dis.c, sh-opc.h: Understand some more opcodes.
+
+Wed Jun 16 13:48:05 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * hppa-dis.c: Include <ansidecl.h> and sysdep.h before other
+ header files.
+
+Tue Jun 15 21:45:26 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * sparc-dis.c: Don't declare qsort, since sysdep.h might.
+
+ * configure.in: Do make sysdep.h link.
+ * Makefile.in: Search ../include. Don't search ../bfd.
+
+Tue Jun 15 13:36:10 1993 Stu Grossman (grossman@cygnus.com)
+
+ Changes from Jeff Law, law@cs.utah.edu:
+ * hppa-dis.c: Fix typo. 'a' and 'd' were reversed.
+ Do not print a space before the completers specified by
+ 'a' and 'd'.
+
+Fri Jun 11 18:40:21 1993 Ken Raeburn (raeburn@cygnus.com)
+
+ * mips-dis.c: No longer need to bomb out if HOST_64_BIT is
+ defined, since gdb has been fixed.
+
+ Changes from Jeff Law, law@cs.utah.edu:
+ * hppa-dis.c (print_insn_hppa): Last argument to fput_reg,
+ fput_reg_r, fput_creg, fput_const, and fputs_filtered should
+ be a *disassemble_info, not a *FILE.
+ * hppa-dis.c: Support 'd', '!', and 'a'.
+ * hppa-dis.c: Support 's' to extract a 2 bit space register.
+ * hppa-dis.c: Delete cases which are no longer needed.
+
+Fri Jun 11 07:53:48 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * m68k-dis.c (print_insn_{m68k,arg}): Add MMU codes.
+
+Tue Jun 8 12:25:01 1993 Steve Chamberlain (sac@phydeaux.cygnus.com)
+
+ * h8300-dis.c: New file, removed from bfd/cpu-h8300.c, with
+ H8/300-H opcodes.
+
+Mon Jun 7 12:58:49 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in (CSEARCH): Add -I../bfd for sysdep.h and bfd.h.
+ * configure.in: No longer need to configure to get sysdep.h.
+
+Thu Jun 3 15:56:49 1993 Stu Grossman (grossman@cygnus.com)
+
+ * Patches from Jeffrey Law <law@cs.utah.edu>.
+ * hppa-dis.c: Support 'I', 'J', and 'K' in output
+ templates for 1.1 FP computational instructions.
+
+Tue May 25 13:05:48 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * h8500-dis.c (print_insn_h8500): Address argument is type
+ bfd_vma.
+ * z8k-dis.c (print_insn_z8k, print_insn_z8001, print_insn_z8002):
+ Ditto.
+
+ * h8500-opc.h (addr_class_type): No comma at end of enumerator.
+ * sh-opc.h (sh_nibble_type, sh_arg_type): Ditto.
+
+ * sparc-dis.c (compare_opcodes): Move static declaration to
+ top-level.
+
+Fri May 21 14:17:37 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * sparc-dis.c (print_insn_sparc): Implement 'n' argument for unimp
+ instruction, remove unimp hack from 'l' argument.
+
+Wed May 19 15:35:54 1993 Stu Grossman (grossman@cygnus.com)
+
+ * z8k-dis.c (fetch_data): Use unsigned char to make ancient gcc's
+ happy.
+
+Fri May 14 15:22:46 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * Based on patches from davidj@ICSI.Berkeley.EDU (David Johnson):
+ * mips-dis.c (print_insn_arg): Handle 'C' for general coprocessor
+ instructions.
+
+Fri May 14 00:09:14 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * hppa-dis.c: Include dis-asm.h before sysdep.h. Changed some
+ arrays of string pointers to 2-d arrays of chars, to save
+ space.
+
+Thu May 6 20:51:17 1993 Fred Fish (fnf@cygnus.com)
+
+ * a29k-dis.c, alpha-dis.c, i960-dis.c, sparc-dis.c, z8k-dis.c:
+ Cast second arg to read_memory_func to "bfd_byte *", as necessary.
+
+Tue May 4 20:31:10 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * hppa-dis.c: New file from Utah, adapted to new disassembler
+ calling interface.
+ * Makefile.in: Include it.
+
+Mon Apr 26 18:17:42 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * sh-dis.c, sh-opc.h: New files.
+
+Fri Apr 23 18:51:22 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * alpha-dis.c, alpha-opc.h: New files.
+
+Tue Apr 6 12:54:08 1993 Peter Schauer (pes@regent.e-technik.tu-muenchen.de)
+
+ * mips-dis.c: Sign extend 'j' and 'b' arguments, delta is a signed
+ value.
+
+Mon Apr 5 17:37:37 1993 John Gilmore (gnu@cygnus.com)
+
+ * sparc-dis.c: Make "ta" the default trap instruction, "t" the alias.
+
+Fri Apr 2 07:24:27 1993 Ian Lance Taylor (ian@cygnus.com)
+
+ * a29k-dis.c, sparc-dis.c, sparc-opc.c: Use CONST rather than
+ const.
+
+Thu Apr 1 11:20:43 1993 Jim Kingdon (kingdon@cygnus.com)
+
+ * sparc-dis.c: Use fprintf_func a few places where I forgot,
+ and double percent signs a few places.
+
+ * a29k-dis.c, i960-dis.c: New, merged from gdb and binutils.
+
+ * i386-dis.c, m68k-dis.c, mips-dis.c, sparc-dis.c:
+ Use info->print_address_func not print_address.
+
+ * dis-buf.c (generic_print_address): New function.
+
+Wed Mar 31 10:07:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * Makefile.in: Add sparc-dis.c.
+ sparc-dis.c: New file, merges binutils and gdb versions as follows:
+ From GDB:
+ Add `add' instruction to the set that get checked
+ for a preceding `sethi' in order to print an absolute address.
+ * (print_insn): Disassembly prefers real instructions.
+ (is_delayed_branch): Speed up.
+ * sparc-opcode.h: Add ALIAS bit to aliases. Fix up opcode tables.
+ Still missing some float ops, and needs testing.
+ * sparc-pinsn.c (print_insn): Eliminate 'set' test, subsumed by
+ F_ALIAS. Use printf, not fprintf, when not passing a file
+ pointer...
+ (compare_opcodes): Check that identical instructions have
+ identical opcodes, complain otherwise.
+ From binutils:
+ * New 'm' arg.
+ * Include reg_names.
+ From neither:
+ Use dis-asm.h/read_memory_func interface.
+
+Wed Mar 31 20:49:06 1993 K. Richard Pixley (rich@rtl.cygnus.com)
+
+ * h8500-dis.c, i386-dis.c, m68k-dis.c, z8k-dis.c (fetch_data):
+ deliberately return non-zero to setjmp from longjmp. Otherwise
+ this code fails to compile.
+
+Wed Mar 31 17:04:31 1993 Stu Grossman (grossman@cygnus.com)
+
+ * m68k-dis.c: Fix prototype for fetch_arg().
+
+Wed Mar 31 10:07:04 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
+
+ * dis-buf.c: New file, for new read_memory_func interface.
+ Makefile.in (OFILES): Include it.
+ m68k-dis.c, i386-dis.c, h8500-dis.c, mips-dis.c, z8k-dis.c:
+ Use new read_memory_func interface.
+
+Mon Mar 29 14:02:17 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * h8500-dis.c (print_insn_h8500): Get sign of fp offsets right.
+ * h8500-opc.h: Fix couple of opcodes.
+
+Wed Mar 24 02:03:36 1993 david d `zoo' zuhn (zoo at poseidon.cygnus.com)
+
+ * Makefile.in: add dvi & installcheck targets
+
+Mon Mar 22 18:55:04 1993 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in: Update for h8500-dis.c.
+
+Fri Mar 19 14:27:17 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * h8500-dis.c, h8500-opc.h: New files
+
+Thu Mar 18 14:12:37 1993 Per Bothner (bothner@rtl.cygnus.com)
+
+ * mips-dis.c, z8k-dis.c: Converted to use interface defined in
+ ../include/dis-asm.h.
+ * m68k-dis.c: New file (merge of ../binutils/m68k-pinsn.c
+ and ../gdb/m68k-pinsn.c).
+ * i386-dis.c: New file (merge of ../binutils/i386-pinsn.c
+ and ../gdb/i386-pinsn.c).
+ * m68881-ext.c: New file. Moved definition of
+ ext_format ext_format_68881 from ../gdb/m68k-tdep.c.
+ * Makefile.in: Adjust for new files.
+ * i386-dis.c: Patches from John Hassey (hassey@dg-rtp.dg.com).
+ * m68k-dis.c: Recognize '9' placement code, so (say) pflush
+ can be dis-assembled.
+
+Wed Feb 17 09:19:47 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * mips-dis.c (print_insn_arg): Now returns void.
+
+Mon Jan 11 16:09:16 1993 Fred Fish (fnf@cygnus.com)
+
+ * mips-dis.c (ansidecl.h): Include for benefit of sysdep.h
+ files that use the macros.
+
+Thu Jan 7 13:15:17 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+
+ * mips-dis.c: New file, from gdb/mips-pinsn.c.
+ * Makefile.in (DIS_LIBS): Added mips-dis.o.
+ (CFILES): Added mips-dis.c.
+
+Thu Jan 7 07:36:33 1993 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * z8k-dis.c (print_insn_z8001, print_insn_z8002): new routines
+ * z8kgen.c, z8k-opc.h: fix sizes of some shifts.
+
+Tue Dec 22 15:42:44 1992 Per Bothner (bothner@rtl.cygnus.com)
+
+ * Makefile.in: Improve *clean rules.
+ * configure.in: Allow a default host.
+
+Tue Nov 17 19:53:54 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * Makefile.in: also use -I$(srcdir)/../bfd, since some sysdep
+ files include other sysdep files
+
+Thu Nov 12 16:10:37 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * z8k-dis.c z8k-opc.h z8kgen.c: checkpoint
+
+Fri Oct 9 04:56:05 1992 John Gilmore (gnu@cygnus.com)
+
+ * configure.in: For host support, use ../bfd/configure.host
+ so it stays in sync with the ../bfd/hosts database.
+
+Thu Oct 1 23:38:54 1992 david d `zoo' zuhn (zoo at cirdan.cygnus.com)
+
+ * configure.in: use cpu-vendor-os triple instead of nested cases
+
+Wed Sep 30 16:09:20 1992 Michael Werner (mtw@cygnus.com)
+
+ * z8k-dis.c (unparse_instr): fix bug where opcode returned was
+ *always* the wrong one.
+
+Wed Sep 30 07:42:17 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * z8kgen.c: added copyright info
+
+Tue Sep 29 12:20:21 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * z8k-dis.c (unparse_instr): prettier tabs
+ * z8kgen.c -> z8k-opc.h: bug fixes in tables
+
+Fri Sep 25 12:50:32 1992 Stu Grossman (grossman at cygnus.com)
+
+ * configure.in: Add ncr* configuration.
+ * z8k-dis.c (struct instr_data_s): Make instr_asmsrc char to make
+ picayune ANSI compilers happy.
+
+Sep 20 08:50:55 1992 Fred Fish (fnf@cygnus.com)
+
+ * configure.in (i386): Make i386 and i486 synonymous for now.
+ * configure.in (i[34]86-*-sysv4): Add my_host definition.
+
+Fri Sep 18 17:01:23 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (install): Fix typo.
+
+Fri Sep 18 02:04:24 1992 John Gilmore (gnu@cygnus.com)
+
+ * Makefile.in (make): Remove obsolete crud.
+ (sparc-opc.o): Avoid Sun Make VPATH bug.
+
+Tue Sep 8 17:29:27 1992 K. Richard Pixley (rich@sendai.cygnus.com)
+
+ * Makefile.in: since there are no SUBDIRS, remove rule and
+ references of subdir_do.
+
+Tue Sep 8 17:02:58 1992 Ken Raeburn (raeburn@cambridge.cygnus.com)
+
+ * Makefile.in (install): Get the library name right here too.
+ Don't install bfd.h, since it's unrelated to this library. No
+ subdirs to recurse into, either.
+ (CFILES): The source file has a .c suffix, not .o.
+
+ * sparc-opc.c: New file, moved from BFD.
+ * Makefile.in (OFILES): Build it.
+
+Thu Sep 3 16:59:20 1992 Michael Werner (mtw@cygnus.com)
+
+ * z8k-dis.c: fixed forward refferences of some declarations.
+
+Mon Aug 31 16:09:45 1992 Michael Werner (mtw@cygnus.com)
+
+ * Makefile.in: get the name of the library right
+
+Mon Aug 31 13:47:35 1992 Steve Chamberlain (sac@thepub.cygnus.com)
+
+ * z8k-dis.c: knows how to disassemble z8k stuff
+ * z8k-opc.h: new file full of z8000 opcodes
+
+
+Local Variables:
+version-control: never
+End:
diff --git a/contrib/gdb/opcodes/Makefile.in b/contrib/gdb/opcodes/Makefile.in
new file mode 100644
index 0000000..c274cb1
--- /dev/null
+++ b/contrib/gdb/opcodes/Makefile.in
@@ -0,0 +1,305 @@
+# Makefile template for Configure for the opcodes library.
+# Copyright (C) 1990, 1991, 1992, 1995 Free Software Foundation, Inc.
+# Written by Cygnus Support.
+#
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+prefix = @prefix@
+
+program_transform_name = @program_transform_name@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+libdir = $(exec_prefix)/lib
+
+datadir = $(prefix)/lib
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man2dir = $(mandir)/man2
+man3dir = $(mandir)/man3
+man4dir = $(mandir)/man4
+man5dir = $(mandir)/man5
+man6dir = $(mandir)/man6
+man7dir = $(mandir)/man7
+man8dir = $(mandir)/man8
+man9dir = $(mandir)/man9
+infodir = $(prefix)/info
+includedir = $(prefix)/include
+oldincludedir =
+docdir = $(srcdir)/doc
+
+SHELL = /bin/sh
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+AR = @AR@
+AR_FLAGS = rc
+CC = @CC@
+CFLAGS = @CFLAGS@
+MAKEINFO = makeinfo
+RANLIB = @RANLIB@
+
+ALLLIBS = @ALLLIBS@
+
+PICFLAG = @PICFLAG@
+SHLIB = @SHLIB@
+SHLIB_CC = @SHLIB_CC@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+COMMON_SHLIB = @COMMON_SHLIB@
+SHLIB_DEP = @SHLIB_DEP@
+SHLINK = @SHLINK@
+
+SONAME = lib`echo $(SHLIB) | sed -e 's,^\.\./bfd/,,' -e 's/^lib//' | sed '$(program_transform_name)'`
+
+INCDIR = $(srcdir)/../include
+BFDDIR = $(srcdir)/../bfd
+CSEARCH = -I. -I$(srcdir) -I../bfd -I$(INCDIR) -I$(BFDDIR)
+DEP = mkdep
+
+TARGETLIB = libopcodes.a
+
+# To circumvent a Sun make VPATH bug, each file listed here
+# should also have a foo.o: foo.c line further along in this file.
+
+ALL_MACHINES = a29k-dis.o alpha-dis.o h8300-dis.o h8500-dis.o \
+ hppa-dis.o i386-dis.o i960-dis.o m68k-dis.o m68k-opc.o \
+ m88k-dis.o mips-dis.o mips-opc.o sh-dis.o sparc-dis.o \
+ sparc-opc.o z8k-dis.o ns32k-dis.o ppc-dis.o ppc-opc.o \
+ arm-dis.o w65-dis.o
+
+OFILES = @BFD_MACHINES@ dis-buf.o disassemble.o
+
+FLAGS_TO_PASS = \
+ "against=$(against)" \
+ "AR=$(AR)" \
+ "AR_FLAGS=$(AR_FLAGS)" \
+ "CC=$(CC)" \
+ "CFLAGS=$(CFLAGS)" \
+ "RANLIB=$(RANLIB)" \
+ "MAKEINFO=$(MAKEINFO)" \
+ "INSTALL=$(INSTALL)" \
+ "INSTALL_DATA=$(INSTALL_DATA)" \
+ "INSTALL_PROGRAM=$(INSTALL_PROGRAM)"
+
+ALL_CFLAGS = $(CSEARCH) @HDEFINES@ $(CFLAGS)
+
+.c.o:
+ if [ -n "$(PICFLAG)" ]; then \
+ $(CC) -c $(PICFLAG) $(ALL_CFLAGS) $< -o pic/$@; \
+ else true; fi
+ $(CC) -c $(ALL_CFLAGS) $<
+
+# C source files that correspond to .o's.
+CFILES = i386-dis.c z8k-dis.c m68k-dis.c mips-dis.c ns32k-dis.c ppc-dis.c
+
+all: $(ALLLIBS)
+
+.NOEXPORT:
+
+installcheck check:
+
+info:
+clean-info:
+install-info:
+dvi:
+
+# HDEPFILES comes from the host config; TDEPFILES from the target config.
+
+
+$(TARGETLIB): $(OFILES)
+ rm -f $(TARGETLIB)
+ $(AR) $(AR_FLAGS) $(TARGETLIB) $(OFILES)
+ $(RANLIB) $(TARGETLIB)
+
+LIBIBERTY_LISTS = ../libiberty/required-list ../libiberty/needed-list
+BFD_LIST = ../bfd/piclist
+
+stamp-piclist: Makefile $(LIBIBERTY_LISTS) $(BFD_LIST)
+ rm -f tpiclist
+ if [ -n "$(PICFLAG)" ]; then \
+ echo $(OFILES) | sed -e 's,\([^ ][^ ]*\),pic/\1,g' > tpiclist; \
+ else \
+ echo $(OFILES) > tpiclist; \
+ fi
+ if [ "$(COMMON_SHLIB)" = "yes" ]; then \
+ lobjs=`cat $(LIBIBERTY_LISTS)`; \
+ if [ -n "$(PICFLAG)" ]; then \
+ lobjs=`echo $$lobjs | sed -e 's,\([^ ][^ ]*\),pic/\1,g'`; \
+ fi; \
+ lobjs=`echo $$lobjs | sed -e 's,\([^ ][^ ]*\),../libiberty/\1,g'`; \
+ echo $$lobjs >> tpiclist; \
+ sed -e 's,\([^ ][^ ]*\),../bfd/\1,g' $(BFD_LIST) >> tpiclist; \
+ else true; fi
+ $(srcdir)/../move-if-change tpiclist piclist
+ touch stamp-piclist
+
+piclist: stamp-piclist ; @true
+
+$(SHLIB): stamp-picdir $(OFILES) piclist $(SHLIB_DEP)
+ rm -f $(SHLIB)
+ $(SHLIB_CC) $(SHLIB_CFLAGS) -o $(SHLIB) `cat piclist`
+
+$(SHLINK): $(SHLIB)
+ ts=lib`echo $(SHLIB) | sed -e 's,^\.\./bfd/,,' -e 's/^lib//' | sed -e '$(program_transform_name)'`; \
+ if [ "$(COMMON_SHLIB)" = "yes" ]; then \
+ ts=../bfd/$$ts; \
+ fi; \
+ if [ "$$ts" != "$(SHLIB)" ]; then \
+ rm -f $$ts; \
+ ln -sf `echo $(SHLIB) | sed -e 's,^\.\./bfd/,,'` $$ts; \
+ else true; fi
+ rm -f $(SHLINK)
+ ln -sf `echo $(SHLIB) | sed -e 's,^\.\./bfd/,,'` $(SHLINK)
+
+# This target creates libTARGET-opcodes.so.VERSION as a symlink to
+# libopcodes.so.VERSION. It is used on SunOS, which does not have SONAME.
+stamp-tshlink: $(SHLIB)
+ tf=lib`echo $(SHLIB) | sed -e 's,\.\./bfd/,,' -e 's/^lib//' | sed '$(program_transform_name)'`; \
+ if [ "$(COMMON_SHLIB)" = "yes" ]; then \
+ tf=../bfd/$$tf; \
+ fi; \
+ if [ "$$tf" != "$(SHLIB)" ]; then \
+ rm -f $$tf; \
+ ln -sf $(SHLIB) $$tf; \
+ else true; fi
+ if [ "$(COMMON_SHLIB)" = "yes" ]; then \
+ tf=lib`echo $(TARGETLIB) | sed -e 's/^lib//' | sed '$(program_transform_name)'`; \
+ if [ "$$tf" != "$(TARGETLIB)" ]; then \
+ rm -f $$tf; \
+ ln -sf $(TARGETLIB) $$tf; \
+ else true; fi; \
+ else true; fi
+ touch stamp-tshlink
+
+$(OFILES): stamp-picdir
+
+disassemble.o: disassemble.c $(INCDIR)/dis-asm.h
+ if [ -n "$(PICFLAG)" ]; then \
+ $(CC) -c @archdefs@ $(PICFLAG) $(ALL_CFLAGS) $(srcdir)/disassemble.c -o pic/disassemble.o; \
+ else true; fi
+ $(CC) -c @archdefs@ $(ALL_CFLAGS) $(srcdir)/disassemble.c
+
+a29k-dis.o: a29k-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/a29k.h
+dis-buf.o: dis-buf.c $(INCDIR)/dis-asm.h
+h8500-dis.o: h8500-dis.c h8500-opc.h $(INCDIR)/dis-asm.h
+h8300-dis.o: h8300-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/h8300.h
+i386-dis.o: i386-dis.c $(INCDIR)/dis-asm.h
+i960-dis.o: i960-dis.c $(INCDIR)/dis-asm.h
+w65-dis.o: w65-dis.c
+m68k-dis.o: m68k-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/floatformat.h \
+ $(INCDIR)/opcode/m68k.h
+m68k-opc.o: m68k-opc.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/m68k.h
+mips-dis.o: mips-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/mips.h
+mips-opc.o: mips-opc.c $(INCDIR)/opcode/mips.h
+ppc-dis.o: ppc-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/ppc.h
+ppc-opc.o: ppc-opc.c $(INCDIR)/opcode/ppc.h
+sparc-dis.o: sparc-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/sparc.h
+sparc-opc.o: sparc-opc.c $(INCDIR)/opcode/sparc.h
+z8k-dis.o: z8k-dis.c z8k-opc.h $(INCDIR)/dis-asm.h
+ns32k-dis.o: ns32k-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/ns32k.h
+sh-dis.o: sh-dis.c sh-opc.h $(INCDIR)/dis-asm.h
+alpha-dis.o: alpha-dis.c alpha-opc.h $(INCDIR)/dis-asm.h
+hppa-dis.o: hppa-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/hppa.h
+m88k-dis.o: m88k-dis.c $(INCDIR)/dis-asm.h $(INCDIR)/opcode/m88k.h
+arm-dis.o: arm-dis.c arm-opc.h $(INCDIR)/dis-asm.h
+
+tags etags: TAGS
+
+TAGS: force
+ etags $(INCDIR)/*.h $(srcdir)/*.h $(srcdir)/*.c
+
+MOSTLYCLEAN = *.o core *.E *.p *.ip config.log pic/*.o
+mostlyclean:
+ rm -rf $(MOSTLYCLEAN)
+clean:
+ rm -f *.a $(MOSTLYCLEAN) $(SHLIB) $(SHLINK) piclist stamp-piclist
+distclean: clean
+ rm -rf Makefile config.status TAGS config.cache config.h stamp-h \
+ pic stamp-picdir
+clobber realclean maintainer-clean: distclean
+
+# Mark everything as depending on config.status, since the timestamp on
+# sysdep.h might actually move backwards if we reconfig and relink it
+# to a different hosts/h-xxx.h file. This will force a recompile anyway.
+RECONFIG = config.status
+
+
+
+# This target should be invoked before building a new release.
+# 'VERSION' file must be present and contain a string of the form "x.y"
+#
+roll:
+ @V=`cat VERSION` ; \
+ MAJ=`sed 's/\..*//' VERSION` ; \
+ MIN=`sed 's/.*\.//' VERSION` ; \
+ V=$$MAJ.`expr $$MIN + 1` ; \
+ rm -f VERSION ; \
+ echo $$V >VERSION ; \
+ echo Version $$V
+
+# Dummy target to force execution of dependent targets.
+#
+force:
+
+install: $(ALLLIBS)
+ for f in $(ALLLIBS); do \
+ if [ "$$f" = "stamp-tshlink" ]; then \
+ continue; \
+ fi; \
+ tf=lib`echo $$f | sed -e 's,^\.\./bfd/,,' -e 's/^lib//' | sed '$(program_transform_name)'`; \
+ rm -f $(libdir)/$$tf; \
+ if [ "$$f" = "$(SHLINK)" ]; then \
+ ts=lib`echo $(SHLIB) | sed -e 's,^\.\./bfd/,,' -e 's/^lib//' | sed '$(program_transform_name)'`; \
+ ln -sf $$ts $(libdir)/$$tf; \
+ elif [ "$$f" = "$(SHLIB)" ]; then \
+ $(INSTALL_PROGRAM) $$f $(libdir)/$$tf; \
+ else \
+ $(INSTALL_DATA) $$f $(libdir)/$$tf; \
+ $(RANLIB) $(libdir)/$$tf; \
+ chmod a-x $(libdir)/$$tf; \
+ fi; \
+ done
+
+Makefile: Makefile.in config.status
+ CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+config.h: stamp-h ; @true
+stamp-h: config.in config.status
+ CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status
+
+config.status : configure $(srcdir)/../bfd/configure.host $(srcdir)/../bfd/config.bfd
+ $(SHELL) config.status --recheck
+
+dep: $(CFILES)
+ mkdep $(CFLAGS) $?
+
+stamp-picdir:
+ if [ -n "$(PICFLAG)" ] && [ ! -d pic ]; then \
+ mkdir pic; \
+ else true; fi
+ touch stamp-picdir
+
+# What appears below is generated by a hacked mkdep using gcc -MM.
+
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
+
diff --git a/contrib/gdb/opcodes/dis-buf.c b/contrib/gdb/opcodes/dis-buf.c
new file mode 100644
index 0000000..47a2e33
--- /dev/null
+++ b/contrib/gdb/opcodes/dis-buf.c
@@ -0,0 +1,70 @@
+/* Disassemble from a buffer, for GNU.
+ 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "sysdep.h"
+#include "dis-asm.h"
+#include <errno.h>
+
+/* Get LENGTH bytes from info's buffer, at target address memaddr.
+ Transfer them to myaddr. */
+int
+buffer_read_memory (memaddr, myaddr, length, info)
+ bfd_vma memaddr;
+ bfd_byte *myaddr;
+ int length;
+ struct disassemble_info *info;
+{
+ if (memaddr < info->buffer_vma
+ || memaddr + length > info->buffer_vma + info->buffer_length)
+ /* Out of bounds. Use EIO because GDB uses it. */
+ return EIO;
+ memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
+ return 0;
+}
+
+/* Print an error message. We can assume that this is in response to
+ an error return from buffer_read_memory. */
+void
+perror_memory (status, memaddr, info)
+ int status;
+ bfd_vma memaddr;
+ struct disassemble_info *info;
+{
+ if (status != EIO)
+ /* Can't happen. */
+ (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
+ else
+ /* Actually, address between memaddr and memaddr + len was
+ out of bounds. */
+ (*info->fprintf_func) (info->stream,
+ "Address 0x%x is out of bounds.\n", memaddr);
+}
+
+/* This could be in a separate file, to save miniscule amounts of space
+ in statically linked executables. */
+
+/* Just print the address is hex. This is included for completeness even
+ though both GDB and objdump provide their own (to print symbolic
+ addresses). */
+
+void
+generic_print_address (addr, info)
+ bfd_vma addr;
+ struct disassemble_info *info;
+{
+ (*info->fprintf_func) (info->stream, "0x%x", addr);
+}
diff --git a/contrib/gdb/opcodes/disassemble.c b/contrib/gdb/opcodes/disassemble.c
new file mode 100644
index 0000000..b5d37ae
--- /dev/null
+++ b/contrib/gdb/opcodes/disassemble.c
@@ -0,0 +1,166 @@
+/* Select disassembly routine for specified architecture.
+ Copyright (C) 1994, 1995 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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#include "ansidecl.h"
+#include "dis-asm.h"
+
+#ifdef ARCH_all
+#define ARCH_a29k
+#define ARCH_alpha
+#define ARCH_arm
+#define ARCH_h8300
+#define ARCH_h8500
+#define ARCH_hppa
+#define ARCH_i386
+#define ARCH_i960
+#define ARCH_m68k
+#define ARCH_m88k
+#define ARCH_mips
+#define ARCH_ns32k
+#define ARCH_powerpc
+#define ARCH_rs6000
+#define ARCH_sh
+#define ARCH_sparc
+#define ARCH_w65
+#define ARCH_z8k
+#endif
+
+disassembler_ftype
+disassembler (abfd)
+ bfd *abfd;
+{
+ enum bfd_architecture a = bfd_get_arch (abfd);
+ disassembler_ftype disassemble;
+
+ switch (a)
+ {
+ /* If you add a case to this table, also add it to the
+ ARCH_all definition right above this function. */
+#ifdef ARCH_a29k
+ case bfd_arch_a29k:
+ /* As far as I know we only handle big-endian 29k objects. */
+ disassemble = print_insn_big_a29k;
+ break;
+#endif
+#ifdef ARCH_alpha
+ case bfd_arch_alpha:
+ disassemble = print_insn_alpha;
+ break;
+#endif
+#ifdef ARCH_arm
+ case bfd_arch_arm:
+ if (bfd_big_endian (abfd))
+ disassemble = print_insn_big_arm;
+ else
+ disassemble = print_insn_little_arm;
+ break;
+#endif
+#ifdef ARCH_h8300
+ case bfd_arch_h8300:
+ if (bfd_get_mach(abfd) == bfd_mach_h8300h)
+ disassemble = print_insn_h8300h;
+ else
+ disassemble = print_insn_h8300;
+ break;
+#endif
+#ifdef ARCH_h8500
+ case bfd_arch_h8500:
+ disassemble = print_insn_h8500;
+ break;
+#endif
+#ifdef ARCH_hppa
+ case bfd_arch_hppa:
+ disassemble = print_insn_hppa;
+ break;
+#endif
+#ifdef ARCH_i386
+ case bfd_arch_i386:
+ disassemble = print_insn_i386;
+ break;
+#endif
+#ifdef ARCH_i960
+ case bfd_arch_i960:
+ disassemble = print_insn_i960;
+ break;
+#endif
+#ifdef ARCH_m68k
+ case bfd_arch_m68k:
+ disassemble = print_insn_m68k;
+ break;
+#endif
+#ifdef ARCH_m88k
+ case bfd_arch_m88k:
+ disassemble = print_insn_m88k;
+ break;
+#endif
+#ifdef ARCH_ns32k
+ case bfd_arch_ns32k:
+ disassemble = print_insn_ns32k;
+ break;
+#endif
+#ifdef ARCH_mips
+ case bfd_arch_mips:
+ if (bfd_big_endian (abfd))
+ disassemble = print_insn_big_mips;
+ else
+ disassemble = print_insn_little_mips;
+ break;
+#endif
+#ifdef ARCH_powerpc
+ case bfd_arch_powerpc:
+ if (bfd_big_endian (abfd))
+ disassemble = print_insn_big_powerpc;
+ else
+ disassemble = print_insn_little_powerpc;
+ break;
+#endif
+#ifdef ARCH_rs6000
+ case bfd_arch_rs6000:
+ disassemble = print_insn_rs6000;
+ break;
+#endif
+#ifdef ARCH_sh
+ case bfd_arch_sh:
+ if (bfd_big_endian (abfd))
+ disassemble = print_insn_sh;
+ else
+ disassemble = print_insn_shl;
+ break;
+#endif
+#ifdef ARCH_sparc
+ case bfd_arch_sparc:
+ disassemble = print_insn_sparc;
+ break;
+#endif
+#ifdef ARCH_w65
+ case bfd_arch_w65:
+ disassemble = print_insn_w65;
+ break;
+#endif
+#ifdef ARCH_z8k
+ case bfd_arch_z8k:
+ if (bfd_get_mach(abfd) == bfd_mach_z8001)
+ disassemble = print_insn_z8001;
+ else
+ disassemble = print_insn_z8002;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ return disassemble;
+}
diff --git a/contrib/gdb/opcodes/i386-dis.c b/contrib/gdb/opcodes/i386-dis.c
new file mode 100644
index 0000000..b781edc
--- /dev/null
+++ b/contrib/gdb/opcodes/i386-dis.c
@@ -0,0 +1,2031 @@
+/* Print i386 instructions for GDB, the GNU debugger.
+ Copyright (C) 1988, 89, 91, 93, 94, 95, 1996 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/*
+ * 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu)
+ * July 1988
+ * modified by John Hassey (hassey@dg-rtp.dg.com)
+ */
+
+/*
+ * The main tables describing the instructions is essentially a copy
+ * of the "Opcode Map" chapter (Appendix A) of the Intel 80386
+ * Programmers Manual. Usually, there is a capital letter, followed
+ * by a small letter. The capital letter tell the addressing mode,
+ * and the small letter tells about the operand size. Refer to
+ * the Intel manual for details.
+ */
+
+#include "dis-asm.h"
+#include "sysdep.h"
+
+#define MAXLEN 20
+
+#include <setjmp.h>
+
+struct dis_private
+{
+ /* Points to first byte not fetched. */
+ bfd_byte *max_fetched;
+ bfd_byte the_buffer[MAXLEN];
+ bfd_vma insn_start;
+ jmp_buf bailout;
+};
+
+/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
+ to ADDR (exclusive) are valid. Returns 1 for success, longjmps
+ on error. */
+#define FETCH_DATA(info, addr) \
+ ((addr) <= ((struct dis_private *)(info->private_data))->max_fetched \
+ ? 1 : fetch_data ((info), (addr)))
+
+static int
+fetch_data (info, addr)
+ struct disassemble_info *info;
+ bfd_byte *addr;
+{
+ int status;
+ 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,
+ priv->max_fetched,
+ addr - priv->max_fetched,
+ info);
+ if (status != 0)
+ {
+ (*info->memory_error_func) (status, start, info);
+ longjmp (priv->bailout, 1);
+ }
+ else
+ priv->max_fetched = addr;
+ return 1;
+}
+
+#define Eb OP_E, b_mode
+#define indirEb OP_indirE, b_mode
+#define Gb OP_G, b_mode
+#define Ev OP_E, v_mode
+#define indirEv OP_indirE, v_mode
+#define Ew OP_E, w_mode
+#define Ma OP_E, v_mode
+#define M OP_E, 0
+#define Mp OP_E, 0 /* ? */
+#define Gv OP_G, v_mode
+#define Gw OP_G, w_mode
+#define Rw OP_rm, w_mode
+#define Rd OP_rm, d_mode
+#define Ib OP_I, b_mode
+#define sIb OP_sI, b_mode /* sign extened byte */
+#define Iv OP_I, v_mode
+#define Iw OP_I, w_mode
+#define Jb OP_J, b_mode
+#define Jv OP_J, v_mode
+#define ONE OP_ONE, 0
+#define Cd OP_C, d_mode
+#define Dd OP_D, d_mode
+#define Td OP_T, d_mode
+
+#define eAX OP_REG, eAX_reg
+#define eBX OP_REG, eBX_reg
+#define eCX OP_REG, eCX_reg
+#define eDX OP_REG, eDX_reg
+#define eSP OP_REG, eSP_reg
+#define eBP OP_REG, eBP_reg
+#define eSI OP_REG, eSI_reg
+#define eDI OP_REG, eDI_reg
+#define AL OP_REG, al_reg
+#define CL OP_REG, cl_reg
+#define DL OP_REG, dl_reg
+#define BL OP_REG, bl_reg
+#define AH OP_REG, ah_reg
+#define CH OP_REG, ch_reg
+#define DH OP_REG, dh_reg
+#define BH OP_REG, bh_reg
+#define AX OP_REG, ax_reg
+#define DX OP_REG, dx_reg
+#define indirDX OP_REG, indir_dx_reg
+
+#define Sw OP_SEG, w_mode
+#define Ap OP_DIR, lptr
+#define Av OP_DIR, v_mode
+#define Ob OP_OFF, b_mode
+#define Ov OP_OFF, v_mode
+#define Xb OP_DSSI, b_mode
+#define Xv OP_DSSI, v_mode
+#define Yb OP_ESDI, b_mode
+#define Yv OP_ESDI, v_mode
+
+#define es OP_REG, es_reg
+#define ss OP_REG, ss_reg
+#define cs OP_REG, cs_reg
+#define ds OP_REG, ds_reg
+#define fs OP_REG, fs_reg
+#define gs OP_REG, gs_reg
+
+int OP_E(), OP_indirE(), OP_G(), OP_I(), OP_sI(), OP_REG();
+int OP_J(), OP_SEG();
+int OP_DIR(), OP_OFF(), OP_DSSI(), OP_ESDI(), OP_ONE(), OP_C();
+int OP_D(), OP_T(), OP_rm();
+
+static void dofloat (), putop (), append_prefix (), set_op ();
+static int get16 (), get32 ();
+
+#define b_mode 1
+#define v_mode 2
+#define w_mode 3
+#define d_mode 4
+
+#define es_reg 100
+#define cs_reg 101
+#define ss_reg 102
+#define ds_reg 103
+#define fs_reg 104
+#define gs_reg 105
+#define eAX_reg 107
+#define eCX_reg 108
+#define eDX_reg 109
+#define eBX_reg 110
+#define eSP_reg 111
+#define eBP_reg 112
+#define eSI_reg 113
+#define eDI_reg 114
+
+#define lptr 115
+
+#define al_reg 116
+#define cl_reg 117
+#define dl_reg 118
+#define bl_reg 119
+#define ah_reg 120
+#define ch_reg 121
+#define dh_reg 122
+#define bh_reg 123
+
+#define ax_reg 124
+#define cx_reg 125
+#define dx_reg 126
+#define bx_reg 127
+#define sp_reg 128
+#define bp_reg 129
+#define si_reg 130
+#define di_reg 131
+
+#define indir_dx_reg 150
+
+#define GRP1b NULL, NULL, 0
+#define GRP1S NULL, NULL, 1
+#define GRP1Ss NULL, NULL, 2
+#define GRP2b NULL, NULL, 3
+#define GRP2S NULL, NULL, 4
+#define GRP2b_one NULL, NULL, 5
+#define GRP2S_one NULL, NULL, 6
+#define GRP2b_cl NULL, NULL, 7
+#define GRP2S_cl NULL, NULL, 8
+#define GRP3b NULL, NULL, 9
+#define GRP3S NULL, NULL, 10
+#define GRP4 NULL, NULL, 11
+#define GRP5 NULL, NULL, 12
+#define GRP6 NULL, NULL, 13
+#define GRP7 NULL, NULL, 14
+#define GRP8 NULL, NULL, 15
+#define GRP9 NULL, NULL, 16
+
+#define FLOATCODE 50
+#define FLOAT NULL, NULL, FLOATCODE
+
+struct dis386 {
+ char *name;
+ int (*op1)();
+ int bytemode1;
+ int (*op2)();
+ int bytemode2;
+ int (*op3)();
+ int bytemode3;
+};
+
+struct dis386 dis386[] = {
+ /* 00 */
+ { "addb", Eb, Gb },
+ { "addS", Ev, Gv },
+ { "addb", Gb, Eb },
+ { "addS", Gv, Ev },
+ { "addb", AL, Ib },
+ { "addS", eAX, Iv },
+ { "pushl", es },
+ { "popl", es },
+ /* 08 */
+ { "orb", Eb, Gb },
+ { "orS", Ev, Gv },
+ { "orb", Gb, Eb },
+ { "orS", Gv, Ev },
+ { "orb", AL, Ib },
+ { "orS", eAX, Iv },
+ { "pushl", cs },
+ { "(bad)" }, /* 0x0f extended opcode escape */
+ /* 10 */
+ { "adcb", Eb, Gb },
+ { "adcS", Ev, Gv },
+ { "adcb", Gb, Eb },
+ { "adcS", Gv, Ev },
+ { "adcb", AL, Ib },
+ { "adcS", eAX, Iv },
+ { "pushl", ss },
+ { "popl", ss },
+ /* 18 */
+ { "sbbb", Eb, Gb },
+ { "sbbS", Ev, Gv },
+ { "sbbb", Gb, Eb },
+ { "sbbS", Gv, Ev },
+ { "sbbb", AL, Ib },
+ { "sbbS", eAX, Iv },
+ { "pushl", ds },
+ { "popl", ds },
+ /* 20 */
+ { "andb", Eb, Gb },
+ { "andS", Ev, Gv },
+ { "andb", Gb, Eb },
+ { "andS", Gv, Ev },
+ { "andb", AL, Ib },
+ { "andS", eAX, Iv },
+ { "(bad)" }, /* SEG ES prefix */
+ { "daa" },
+ /* 28 */
+ { "subb", Eb, Gb },
+ { "subS", Ev, Gv },
+ { "subb", Gb, Eb },
+ { "subS", Gv, Ev },
+ { "subb", AL, Ib },
+ { "subS", eAX, Iv },
+ { "(bad)" }, /* SEG CS prefix */
+ { "das" },
+ /* 30 */
+ { "xorb", Eb, Gb },
+ { "xorS", Ev, Gv },
+ { "xorb", Gb, Eb },
+ { "xorS", Gv, Ev },
+ { "xorb", AL, Ib },
+ { "xorS", eAX, Iv },
+ { "(bad)" }, /* SEG SS prefix */
+ { "aaa" },
+ /* 38 */
+ { "cmpb", Eb, Gb },
+ { "cmpS", Ev, Gv },
+ { "cmpb", Gb, Eb },
+ { "cmpS", Gv, Ev },
+ { "cmpb", AL, Ib },
+ { "cmpS", eAX, Iv },
+ { "(bad)" }, /* SEG DS prefix */
+ { "aas" },
+ /* 40 */
+ { "incS", eAX },
+ { "incS", eCX },
+ { "incS", eDX },
+ { "incS", eBX },
+ { "incS", eSP },
+ { "incS", eBP },
+ { "incS", eSI },
+ { "incS", eDI },
+ /* 48 */
+ { "decS", eAX },
+ { "decS", eCX },
+ { "decS", eDX },
+ { "decS", eBX },
+ { "decS", eSP },
+ { "decS", eBP },
+ { "decS", eSI },
+ { "decS", eDI },
+ /* 50 */
+ { "pushS", eAX },
+ { "pushS", eCX },
+ { "pushS", eDX },
+ { "pushS", eBX },
+ { "pushS", eSP },
+ { "pushS", eBP },
+ { "pushS", eSI },
+ { "pushS", eDI },
+ /* 58 */
+ { "popS", eAX },
+ { "popS", eCX },
+ { "popS", eDX },
+ { "popS", eBX },
+ { "popS", eSP },
+ { "popS", eBP },
+ { "popS", eSI },
+ { "popS", eDI },
+ /* 60 */
+ { "pusha" },
+ { "popa" },
+ { "boundS", Gv, Ma },
+ { "arpl", Ew, Gw },
+ { "(bad)" }, /* seg fs */
+ { "(bad)" }, /* seg gs */
+ { "(bad)" }, /* op size prefix */
+ { "(bad)" }, /* adr size prefix */
+ /* 68 */
+ { "pushS", Iv }, /* 386 book wrong */
+ { "imulS", Gv, Ev, Iv },
+ { "pushl", sIb }, /* push of byte really pushes 4 bytes */
+ { "imulS", Gv, Ev, Ib },
+ { "insb", Yb, indirDX },
+ { "insS", Yv, indirDX },
+ { "outsb", indirDX, Xb },
+ { "outsS", indirDX, Xv },
+ /* 70 */
+ { "jo", Jb },
+ { "jno", Jb },
+ { "jb", Jb },
+ { "jae", Jb },
+ { "je", Jb },
+ { "jne", Jb },
+ { "jbe", Jb },
+ { "ja", Jb },
+ /* 78 */
+ { "js", Jb },
+ { "jns", Jb },
+ { "jp", Jb },
+ { "jnp", Jb },
+ { "jl", Jb },
+ { "jnl", Jb },
+ { "jle", Jb },
+ { "jg", Jb },
+ /* 80 */
+ { GRP1b },
+ { GRP1S },
+ { "(bad)" },
+ { GRP1Ss },
+ { "testb", Eb, Gb },
+ { "testS", Ev, Gv },
+ { "xchgb", Eb, Gb },
+ { "xchgS", Ev, Gv },
+ /* 88 */
+ { "movb", Eb, Gb },
+ { "movS", Ev, Gv },
+ { "movb", Gb, Eb },
+ { "movS", Gv, Ev },
+ { "movw", Ew, Sw },
+ { "leaS", Gv, M },
+ { "movw", Sw, Ew },
+ { "popS", Ev },
+ /* 90 */
+ { "nop" },
+ { "xchgS", eCX, eAX },
+ { "xchgS", eDX, eAX },
+ { "xchgS", eBX, eAX },
+ { "xchgS", eSP, eAX },
+ { "xchgS", eBP, eAX },
+ { "xchgS", eSI, eAX },
+ { "xchgS", eDI, eAX },
+ /* 98 */
+ { "cwtl" },
+ { "cltd" },
+ { "lcall", Ap },
+ { "(bad)" }, /* fwait */
+ { "pushf" },
+ { "popf" },
+ { "sahf" },
+ { "lahf" },
+ /* a0 */
+ { "movb", AL, Ob },
+ { "movS", eAX, Ov },
+ { "movb", Ob, AL },
+ { "movS", Ov, eAX },
+ { "movsb", Yb, Xb },
+ { "movsS", Yv, Xv },
+ { "cmpsb", Yb, Xb },
+ { "cmpsS", Yv, Xv },
+ /* a8 */
+ { "testb", AL, Ib },
+ { "testS", eAX, Iv },
+ { "stosb", Yb, AL },
+ { "stosS", Yv, eAX },
+ { "lodsb", AL, Xb },
+ { "lodsS", eAX, Xv },
+ { "scasb", AL, Yb },
+ { "scasS", eAX, Yv },
+ /* b0 */
+ { "movb", AL, Ib },
+ { "movb", CL, Ib },
+ { "movb", DL, Ib },
+ { "movb", BL, Ib },
+ { "movb", AH, Ib },
+ { "movb", CH, Ib },
+ { "movb", DH, Ib },
+ { "movb", BH, Ib },
+ /* b8 */
+ { "movS", eAX, Iv },
+ { "movS", eCX, Iv },
+ { "movS", eDX, Iv },
+ { "movS", eBX, Iv },
+ { "movS", eSP, Iv },
+ { "movS", eBP, Iv },
+ { "movS", eSI, Iv },
+ { "movS", eDI, Iv },
+ /* c0 */
+ { GRP2b },
+ { GRP2S },
+ { "ret", Iw },
+ { "ret" },
+ { "lesS", Gv, Mp },
+ { "ldsS", Gv, Mp },
+ { "movb", Eb, Ib },
+ { "movS", Ev, Iv },
+ /* c8 */
+ { "enter", Iw, Ib },
+ { "leave" },
+ { "lret", Iw },
+ { "lret" },
+ { "int3" },
+ { "int", Ib },
+ { "into" },
+ { "iret" },
+ /* d0 */
+ { GRP2b_one },
+ { GRP2S_one },
+ { GRP2b_cl },
+ { GRP2S_cl },
+ { "aam", Ib },
+ { "aad", Ib },
+ { "(bad)" },
+ { "xlat" },
+ /* d8 */
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ { FLOAT },
+ /* e0 */
+ { "loopne", Jb },
+ { "loope", Jb },
+ { "loop", Jb },
+ { "jCcxz", Jb },
+ { "inb", AL, Ib },
+ { "inS", eAX, Ib },
+ { "outb", Ib, AL },
+ { "outS", Ib, eAX },
+ /* e8 */
+ { "call", Av },
+ { "jmp", Jv },
+ { "ljmp", Ap },
+ { "jmp", Jb },
+ { "inb", AL, indirDX },
+ { "inS", eAX, indirDX },
+ { "outb", indirDX, AL },
+ { "outS", indirDX, eAX },
+ /* f0 */
+ { "(bad)" }, /* lock prefix */
+ { "(bad)" },
+ { "(bad)" }, /* repne */
+ { "(bad)" }, /* repz */
+ { "hlt" },
+ { "cmc" },
+ { GRP3b },
+ { GRP3S },
+ /* f8 */
+ { "clc" },
+ { "stc" },
+ { "cli" },
+ { "sti" },
+ { "cld" },
+ { "std" },
+ { GRP4 },
+ { GRP5 },
+};
+
+struct dis386 dis386_twobyte[] = {
+ /* 00 */
+ { GRP6 },
+ { GRP7 },
+ { "larS", Gv, Ew },
+ { "lslS", Gv, Ew },
+ { "(bad)" },
+ { "(bad)" },
+ { "clts" },
+ { "(bad)" },
+ /* 08 */
+ { "invd" },
+ { "wbinvd" },
+ { "(bad)" }, { "ud2a" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 10 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 18 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 20 */
+ /* these are all backward in appendix A of the intel book */
+ { "movl", Rd, Cd },
+ { "movl", Rd, Dd },
+ { "movl", Cd, Rd },
+ { "movl", Dd, Rd },
+ { "movl", Rd, Td },
+ { "(bad)" },
+ { "movl", Td, Rd },
+ { "(bad)" },
+ /* 28 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 30 */
+ { "wrmsr" }, { "rdtsc" }, { "rdmsr" }, { "rdpmc" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 38 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 40 */
+ { "cmovo", Gv,Ev }, { "cmovno", Gv,Ev }, { "cmovb", Gv,Ev }, { "cmovae", Gv,Ev },
+ { "cmove", Gv,Ev }, { "cmovne", Gv,Ev }, { "cmovbe", Gv,Ev }, { "cmova", Gv,Ev },
+ /* 48 */
+ { "cmovs", Gv,Ev }, { "cmovns", Gv,Ev }, { "cmovp", Gv,Ev }, { "cmovnp", Gv,Ev },
+ { "cmovl", Gv,Ev }, { "cmovge", Gv,Ev }, { "cmovle", Gv,Ev }, { "cmovg", Gv,Ev },
+ /* 50 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 58 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 60 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 68 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 70 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 78 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* 80 */
+ { "jo", Jv },
+ { "jno", Jv },
+ { "jb", Jv },
+ { "jae", Jv },
+ { "je", Jv },
+ { "jne", Jv },
+ { "jbe", Jv },
+ { "ja", Jv },
+ /* 88 */
+ { "js", Jv },
+ { "jns", Jv },
+ { "jp", Jv },
+ { "jnp", Jv },
+ { "jl", Jv },
+ { "jge", Jv },
+ { "jle", Jv },
+ { "jg", Jv },
+ /* 90 */
+ { "seto", Eb },
+ { "setno", Eb },
+ { "setb", Eb },
+ { "setae", Eb },
+ { "sete", Eb },
+ { "setne", Eb },
+ { "setbe", Eb },
+ { "seta", Eb },
+ /* 98 */
+ { "sets", Eb },
+ { "setns", Eb },
+ { "setp", Eb },
+ { "setnp", Eb },
+ { "setl", Eb },
+ { "setge", Eb },
+ { "setle", Eb },
+ { "setg", Eb },
+ /* a0 */
+ { "pushl", fs },
+ { "popl", fs },
+ { "cpuid" },
+ { "btS", Ev, Gv },
+ { "shldS", Ev, Gv, Ib },
+ { "shldS", Ev, Gv, CL },
+ { "(bad)" },
+ { "(bad)" },
+ /* a8 */
+ { "pushl", gs },
+ { "popl", gs },
+ { "rsm" },
+ { "btsS", Ev, Gv },
+ { "shrdS", Ev, Gv, Ib },
+ { "shrdS", Ev, Gv, CL },
+ { "(bad)" },
+ { "imulS", Gv, Ev },
+ /* b0 */
+ { "cmpxchgb", Eb, Gb },
+ { "cmpxchgS", Ev, Gv },
+ { "lssS", Gv, Mp }, /* 386 lists only Mp */
+ { "btrS", Ev, Gv },
+ { "lfsS", Gv, Mp }, /* 386 lists only Mp */
+ { "lgsS", Gv, Mp }, /* 386 lists only Mp */
+ { "movzbS", Gv, Eb },
+ { "movzwS", Gv, Ew },
+ /* b8 */
+ { "ud2b" },
+ { "(bad)" },
+ { GRP8 },
+ { "btcS", Ev, Gv },
+ { "bsfS", Gv, Ev },
+ { "bsrS", Gv, Ev },
+ { "movsbS", Gv, Eb },
+ { "movswS", Gv, Ew },
+ /* c0 */
+ { "xaddb", Eb, Gb },
+ { "xaddS", Ev, Gv },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { GRP9 },
+ /* c8 */
+ { "bswap", eAX },
+ { "bswap", eCX },
+ { "bswap", eDX },
+ { "bswap", eBX },
+ { "bswap", eSP },
+ { "bswap", eBP },
+ { "bswap", eSI },
+ { "bswap", eDI },
+ /* d0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* d8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* e8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f0 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ /* f8 */
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+ { "(bad)" }, { "(bad)" }, { "(bad)" }, { "(bad)" },
+};
+
+static const unsigned char onebyte_has_modrm[256] = {
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
+ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1
+};
+
+static const unsigned char twobyte_has_modrm[256] = {
+ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+
+static char obuf[100];
+static char *obufp;
+static char scratchbuf[100];
+static unsigned char *start_codep;
+static unsigned char *codep;
+static disassemble_info *the_info;
+static int mod;
+static int rm;
+static int reg;
+static void oappend ();
+
+static char *names32[]={
+ "%eax","%ecx","%edx","%ebx", "%esp","%ebp","%esi","%edi",
+};
+static char *names16[] = {
+ "%ax","%cx","%dx","%bx","%sp","%bp","%si","%di",
+};
+static char *names8[] = {
+ "%al","%cl","%dl","%bl","%ah","%ch","%dh","%bh",
+};
+static char *names_seg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+};
+static char *index16[] = {
+ "bx+si","bx+di","bp+si","bp+di","si","di","bp","bx"
+};
+
+struct dis386 grps[][8] = {
+ /* GRP1b */
+ {
+ { "addb", Eb, Ib },
+ { "orb", Eb, Ib },
+ { "adcb", Eb, Ib },
+ { "sbbb", Eb, Ib },
+ { "andb", Eb, Ib },
+ { "subb", Eb, Ib },
+ { "xorb", Eb, Ib },
+ { "cmpb", Eb, Ib }
+ },
+ /* GRP1S */
+ {
+ { "addS", Ev, Iv },
+ { "orS", Ev, Iv },
+ { "adcS", Ev, Iv },
+ { "sbbS", Ev, Iv },
+ { "andS", Ev, Iv },
+ { "subS", Ev, Iv },
+ { "xorS", Ev, Iv },
+ { "cmpS", Ev, Iv }
+ },
+ /* GRP1Ss */
+ {
+ { "addS", Ev, sIb },
+ { "orS", Ev, sIb },
+ { "adcS", Ev, sIb },
+ { "sbbS", Ev, sIb },
+ { "andS", Ev, sIb },
+ { "subS", Ev, sIb },
+ { "xorS", Ev, sIb },
+ { "cmpS", Ev, sIb }
+ },
+ /* GRP2b */
+ {
+ { "rolb", Eb, Ib },
+ { "rorb", Eb, Ib },
+ { "rclb", Eb, Ib },
+ { "rcrb", Eb, Ib },
+ { "shlb", Eb, Ib },
+ { "shrb", Eb, Ib },
+ { "(bad)" },
+ { "sarb", Eb, Ib },
+ },
+ /* GRP2S */
+ {
+ { "rolS", Ev, Ib },
+ { "rorS", Ev, Ib },
+ { "rclS", Ev, Ib },
+ { "rcrS", Ev, Ib },
+ { "shlS", Ev, Ib },
+ { "shrS", Ev, Ib },
+ { "(bad)" },
+ { "sarS", Ev, Ib },
+ },
+ /* GRP2b_one */
+ {
+ { "rolb", Eb },
+ { "rorb", Eb },
+ { "rclb", Eb },
+ { "rcrb", Eb },
+ { "shlb", Eb },
+ { "shrb", Eb },
+ { "(bad)" },
+ { "sarb", Eb },
+ },
+ /* GRP2S_one */
+ {
+ { "rolS", Ev },
+ { "rorS", Ev },
+ { "rclS", Ev },
+ { "rcrS", Ev },
+ { "shlS", Ev },
+ { "shrS", Ev },
+ { "(bad)" },
+ { "sarS", Ev },
+ },
+ /* GRP2b_cl */
+ {
+ { "rolb", Eb, CL },
+ { "rorb", Eb, CL },
+ { "rclb", Eb, CL },
+ { "rcrb", Eb, CL },
+ { "shlb", Eb, CL },
+ { "shrb", Eb, CL },
+ { "(bad)" },
+ { "sarb", Eb, CL },
+ },
+ /* GRP2S_cl */
+ {
+ { "rolS", Ev, CL },
+ { "rorS", Ev, CL },
+ { "rclS", Ev, CL },
+ { "rcrS", Ev, CL },
+ { "shlS", Ev, CL },
+ { "shrS", Ev, CL },
+ { "(bad)" },
+ { "sarS", Ev, CL }
+ },
+ /* GRP3b */
+ {
+ { "testb", Eb, Ib },
+ { "(bad)", Eb },
+ { "notb", Eb },
+ { "negb", Eb },
+ { "mulb", AL, Eb },
+ { "imulb", AL, Eb },
+ { "divb", AL, Eb },
+ { "idivb", AL, Eb }
+ },
+ /* GRP3S */
+ {
+ { "testS", Ev, Iv },
+ { "(bad)" },
+ { "notS", Ev },
+ { "negS", Ev },
+ { "mulS", eAX, Ev },
+ { "imulS", eAX, Ev },
+ { "divS", eAX, Ev },
+ { "idivS", eAX, Ev },
+ },
+ /* GRP4 */
+ {
+ { "incb", Eb },
+ { "decb", Eb },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* GRP5 */
+ {
+ { "incS", Ev },
+ { "decS", Ev },
+ { "call", indirEv },
+ { "lcall", indirEv },
+ { "jmp", indirEv },
+ { "ljmp", indirEv },
+ { "pushS", Ev },
+ { "(bad)" },
+ },
+ /* GRP6 */
+ {
+ { "sldt", Ew },
+ { "str", Ew },
+ { "lldt", Ew },
+ { "ltr", Ew },
+ { "verr", Ew },
+ { "verw", Ew },
+ { "(bad)" },
+ { "(bad)" }
+ },
+ /* GRP7 */
+ {
+ { "sgdt", Ew },
+ { "sidt", Ew },
+ { "lgdt", Ew },
+ { "lidt", Ew },
+ { "smsw", Ew },
+ { "(bad)" },
+ { "lmsw", Ew },
+ { "invlpg", Ew },
+ },
+ /* GRP8 */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "btS", Ev, Ib },
+ { "btsS", Ev, Ib },
+ { "btrS", Ev, Ib },
+ { "btcS", Ev, Ib },
+ },
+ /* GRP9 */
+ {
+ { "(bad)" },
+ { "cmpxchg8b", Ev },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ }
+};
+
+#define PREFIX_REPZ 1
+#define PREFIX_REPNZ 2
+#define PREFIX_LOCK 4
+#define PREFIX_CS 8
+#define PREFIX_SS 0x10
+#define PREFIX_DS 0x20
+#define PREFIX_ES 0x40
+#define PREFIX_FS 0x80
+#define PREFIX_GS 0x100
+#define PREFIX_DATA 0x200
+#define PREFIX_ADR 0x400
+#define PREFIX_FWAIT 0x800
+
+static int prefixes;
+
+static void
+ckprefix ()
+{
+ prefixes = 0;
+ while (1)
+ {
+ FETCH_DATA (the_info, codep + 1);
+ switch (*codep)
+ {
+ case 0xf3:
+ prefixes |= PREFIX_REPZ;
+ break;
+ case 0xf2:
+ prefixes |= PREFIX_REPNZ;
+ break;
+ case 0xf0:
+ prefixes |= PREFIX_LOCK;
+ break;
+ case 0x2e:
+ prefixes |= PREFIX_CS;
+ break;
+ case 0x36:
+ prefixes |= PREFIX_SS;
+ break;
+ case 0x3e:
+ prefixes |= PREFIX_DS;
+ break;
+ case 0x26:
+ prefixes |= PREFIX_ES;
+ break;
+ case 0x64:
+ prefixes |= PREFIX_FS;
+ break;
+ case 0x65:
+ prefixes |= PREFIX_GS;
+ break;
+ case 0x66:
+ prefixes |= PREFIX_DATA;
+ break;
+ case 0x67:
+ prefixes |= PREFIX_ADR;
+ break;
+ case 0x9b:
+ prefixes |= PREFIX_FWAIT;
+ break;
+ default:
+ return;
+ }
+ codep++;
+ }
+}
+
+static int dflag;
+static int aflag;
+
+static char op1out[100], op2out[100], op3out[100];
+static int op_address[3], op_ad, op_index[3];
+static int start_pc;
+
+
+/*
+ * On the 386's of 1988, the maximum length of an instruction is 15 bytes.
+ * (see topic "Redundant prefixes" in the "Differences from 8086"
+ * section of the "Virtual 8086 Mode" chapter.)
+ * 'pc' should be the address of this instruction, it will
+ * be used to print the target address if this is a relative jump or call
+ * The function returns the length of this instruction in bytes.
+ */
+
+int
+print_insn_i386 (pc, info)
+ bfd_vma pc;
+ disassemble_info *info;
+{
+ struct dis386 *dp;
+ int i;
+ int enter_instruction;
+ char *first, *second, *third;
+ int needcomma;
+ unsigned char need_modrm;
+
+ struct dis_private priv;
+ bfd_byte *inbuf = priv.the_buffer;
+
+ info->private_data = (PTR) &priv;
+ priv.max_fetched = priv.the_buffer;
+ priv.insn_start = pc;
+ if (setjmp (priv.bailout) != 0)
+ /* Error return. */
+ return -1;
+
+ obuf[0] = 0;
+ op1out[0] = 0;
+ op2out[0] = 0;
+ op3out[0] = 0;
+
+ op_index[0] = op_index[1] = op_index[2] = -1;
+
+ the_info = info;
+ start_pc = pc;
+ start_codep = inbuf;
+ codep = inbuf;
+
+ ckprefix ();
+
+ FETCH_DATA (info, codep + 1);
+ if (*codep == 0xc8)
+ enter_instruction = 1;
+ else
+ enter_instruction = 0;
+
+ obufp = obuf;
+
+ if (prefixes & PREFIX_REPZ)
+ oappend ("repz ");
+ if (prefixes & PREFIX_REPNZ)
+ oappend ("repnz ");
+ if (prefixes & PREFIX_LOCK)
+ oappend ("lock ");
+
+ if ((prefixes & PREFIX_FWAIT)
+ && ((*codep < 0xd8) || (*codep > 0xdf)))
+ {
+ /* fwait not followed by floating point instruction */
+ (*info->fprintf_func) (info->stream, "fwait");
+ return (1);
+ }
+
+ /* these would be initialized to 0 if disassembling for 8086 or 286 */
+ dflag = 1;
+ aflag = 1;
+
+ if (prefixes & PREFIX_DATA)
+ dflag ^= 1;
+
+ if (prefixes & PREFIX_ADR)
+ {
+ aflag ^= 1;
+ oappend ("addr16 ");
+ }
+
+ if (*codep == 0x0f)
+ {
+ FETCH_DATA (info, codep + 2);
+ dp = &dis386_twobyte[*++codep];
+ need_modrm = twobyte_has_modrm[*codep];
+ }
+ else
+ {
+ dp = &dis386[*codep];
+ need_modrm = onebyte_has_modrm[*codep];
+ }
+ codep++;
+
+ if (need_modrm)
+ {
+ FETCH_DATA (info, codep + 1);
+ mod = (*codep >> 6) & 3;
+ reg = (*codep >> 3) & 7;
+ rm = *codep & 7;
+ }
+
+ if (dp->name == NULL && dp->bytemode1 == FLOATCODE)
+ {
+ dofloat ();
+ }
+ else
+ {
+ if (dp->name == NULL)
+ dp = &grps[dp->bytemode1][reg];
+
+ putop (dp->name);
+
+ obufp = op1out;
+ op_ad = 2;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+
+ obufp = op2out;
+ op_ad = 1;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+
+ obufp = op3out;
+ op_ad = 0;
+ if (dp->op3)
+ (*dp->op3)(dp->bytemode3);
+ }
+
+ obufp = obuf + strlen (obuf);
+ for (i = strlen (obuf); i < 6; i++)
+ oappend (" ");
+ oappend (" ");
+ (*info->fprintf_func) (info->stream, "%s", obuf);
+
+ /* enter instruction is printed with operands in the
+ * same order as the intel book; everything else
+ * is printed in reverse order
+ */
+ if (enter_instruction)
+ {
+ first = op1out;
+ second = op2out;
+ third = op3out;
+ op_ad = op_index[0];
+ op_index[0] = op_index[2];
+ op_index[2] = op_ad;
+ }
+ else
+ {
+ first = op3out;
+ second = op2out;
+ third = op1out;
+ }
+ needcomma = 0;
+ if (*first)
+ {
+ if (op_index[0] != -1)
+ (*info->print_address_func) (op_address[op_index[0]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", first);
+ needcomma = 1;
+ }
+ if (*second)
+ {
+ if (needcomma)
+ (*info->fprintf_func) (info->stream, ",");
+ if (op_index[1] != -1)
+ (*info->print_address_func) (op_address[op_index[1]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", second);
+ needcomma = 1;
+ }
+ if (*third)
+ {
+ if (needcomma)
+ (*info->fprintf_func) (info->stream, ",");
+ if (op_index[2] != -1)
+ (*info->print_address_func) (op_address[op_index[2]], info);
+ else
+ (*info->fprintf_func) (info->stream, "%s", third);
+ }
+ return (codep - inbuf);
+}
+
+char *float_mem[] = {
+ /* d8 */
+ "fadds",
+ "fmuls",
+ "fcoms",
+ "fcomps",
+ "fsubs",
+ "fsubrs",
+ "fdivs",
+ "fdivrs",
+ /* d9 */
+ "flds",
+ "(bad)",
+ "fsts",
+ "fstps",
+ "fldenv",
+ "fldcw",
+ "fNstenv",
+ "fNstcw",
+ /* da */
+ "fiaddl",
+ "fimull",
+ "ficoml",
+ "ficompl",
+ "fisubl",
+ "fisubrl",
+ "fidivl",
+ "fidivrl",
+ /* db */
+ "fildl",
+ "(bad)",
+ "fistl",
+ "fistpl",
+ "(bad)",
+ "fldt",
+ "(bad)",
+ "fstpt",
+ /* dc */
+ "faddl",
+ "fmull",
+ "fcoml",
+ "fcompl",
+ "fsubl",
+ "fsubrl",
+ "fdivl",
+ "fdivrl",
+ /* dd */
+ "fldl",
+ "(bad)",
+ "fstl",
+ "fstpl",
+ "frstor",
+ "(bad)",
+ "fNsave",
+ "fNstsw",
+ /* de */
+ "fiadd",
+ "fimul",
+ "ficom",
+ "ficomp",
+ "fisub",
+ "fisubr",
+ "fidiv",
+ "fidivr",
+ /* df */
+ "fild",
+ "(bad)",
+ "fist",
+ "fistp",
+ "fbld",
+ "fildll",
+ "fbstp",
+ "fistpll",
+};
+
+#define ST OP_ST, 0
+#define STi OP_STi, 0
+int OP_ST(), OP_STi();
+
+#define FGRPd9_2 NULL, NULL, 0
+#define FGRPd9_4 NULL, NULL, 1
+#define FGRPd9_5 NULL, NULL, 2
+#define FGRPd9_6 NULL, NULL, 3
+#define FGRPd9_7 NULL, NULL, 4
+#define FGRPda_5 NULL, NULL, 5
+#define FGRPdb_4 NULL, NULL, 6
+#define FGRPde_3 NULL, NULL, 7
+#define FGRPdf_4 NULL, NULL, 8
+
+struct dis386 float_reg[][8] = {
+ /* d8 */
+ {
+ { "fadd", ST, STi },
+ { "fmul", ST, STi },
+ { "fcom", STi },
+ { "fcomp", STi },
+ { "fsub", ST, STi },
+ { "fsubr", ST, STi },
+ { "fdiv", ST, STi },
+ { "fdivr", ST, STi },
+ },
+ /* d9 */
+ {
+ { "fld", STi },
+ { "fxch", STi },
+ { FGRPd9_2 },
+ { "(bad)" },
+ { FGRPd9_4 },
+ { FGRPd9_5 },
+ { FGRPd9_6 },
+ { FGRPd9_7 },
+ },
+ /* da */
+ {
+ { "fcmovb", ST, STi },
+ { "fcmove", ST, STi },
+ { "fcmovbe",ST, STi },
+ { "fcmovu", ST, STi },
+ { "(bad)" },
+ { FGRPda_5 },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* db */
+ {
+ { "fcmovnb",ST, STi },
+ { "fcmovne",ST, STi },
+ { "fcmovnbe",ST, STi },
+ { "fcmovnu",ST, STi },
+ { FGRPdb_4 },
+ { "fucomi", ST, STi },
+ { "fcomi", ST, STi },
+ { "(bad)" },
+ },
+ /* dc */
+ {
+ { "fadd", STi, ST },
+ { "fmul", STi, ST },
+ { "(bad)" },
+ { "(bad)" },
+ { "fsub", STi, ST },
+ { "fsubr", STi, ST },
+ { "fdiv", STi, ST },
+ { "fdivr", STi, ST },
+ },
+ /* dd */
+ {
+ { "ffree", STi },
+ { "(bad)" },
+ { "fst", STi },
+ { "fstp", STi },
+ { "fucom", STi },
+ { "fucomp", STi },
+ { "(bad)" },
+ { "(bad)" },
+ },
+ /* de */
+ {
+ { "faddp", STi, ST },
+ { "fmulp", STi, ST },
+ { "(bad)" },
+ { FGRPde_3 },
+ { "fsubp", STi, ST },
+ { "fsubrp", STi, ST },
+ { "fdivp", STi, ST },
+ { "fdivrp", STi, ST },
+ },
+ /* df */
+ {
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { "(bad)" },
+ { FGRPdf_4 },
+ { "fucomip",ST, STi },
+ { "fcomip", ST, STi },
+ { "(bad)" },
+ },
+};
+
+
+char *fgrps[][8] = {
+ /* d9_2 0 */
+ {
+ "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* d9_4 1 */
+ {
+ "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)",
+ },
+
+ /* d9_5 2 */
+ {
+ "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)",
+ },
+
+ /* d9_6 3 */
+ {
+ "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp",
+ },
+
+ /* d9_7 4 */
+ {
+ "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos",
+ },
+
+ /* da_5 5 */
+ {
+ "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* db_4 6 */
+ {
+ "feni(287 only)","fdisi(287 only)","fNclex","fNinit",
+ "fNsetpm(287 only)","(bad)","(bad)","(bad)",
+ },
+
+ /* de_3 7 */
+ {
+ "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+
+ /* df_4 8 */
+ {
+ "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)",
+ },
+};
+
+static void
+dofloat ()
+{
+ struct dis386 *dp;
+ unsigned char floatop;
+
+ floatop = codep[-1];
+
+ if (mod != 3)
+ {
+ putop (float_mem[(floatop - 0xd8) * 8 + reg]);
+ obufp = op1out;
+ OP_E (v_mode);
+ return;
+ }
+ codep++;
+
+ dp = &float_reg[floatop - 0xd8][reg];
+ if (dp->name == NULL)
+ {
+ putop (fgrps[dp->bytemode1][rm]);
+ /* instruction fnstsw is only one with strange arg */
+ if (floatop == 0xdf
+ && FETCH_DATA (the_info, codep + 1)
+ && *codep == 0xe0)
+ strcpy (op1out, "%eax");
+ }
+ else
+ {
+ putop (dp->name);
+ obufp = op1out;
+ if (dp->op1)
+ (*dp->op1)(dp->bytemode1);
+ obufp = op2out;
+ if (dp->op2)
+ (*dp->op2)(dp->bytemode2);
+ }
+}
+
+/* ARGSUSED */
+int
+OP_ST (ignore)
+ int ignore;
+{
+ oappend ("%st");
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_STi (ignore)
+ int ignore;
+{
+ sprintf (scratchbuf, "%%st(%d)", rm);
+ oappend (scratchbuf);
+ return (0);
+}
+
+
+/* capital letters in template are macros */
+static void
+putop (template)
+ char *template;
+{
+ char *p;
+
+ for (p = template; *p; p++)
+ {
+ switch (*p)
+ {
+ default:
+ *obufp++ = *p;
+ break;
+ case 'C': /* For jcxz/jecxz */
+ if (aflag)
+ *obufp++ = 'e';
+ break;
+ case 'N':
+ if ((prefixes & PREFIX_FWAIT) == 0)
+ *obufp++ = 'n';
+ break;
+ case 'S':
+ /* operand size flag */
+ if (dflag)
+ *obufp++ = 'l';
+ else
+ *obufp++ = 'w';
+ break;
+ }
+ }
+ *obufp = 0;
+}
+
+static void
+oappend (s)
+ char *s;
+{
+ strcpy (obufp, s);
+ obufp += strlen (s);
+ *obufp = 0;
+}
+
+static void
+append_prefix ()
+{
+ if (prefixes & PREFIX_CS)
+ oappend ("%cs:");
+ if (prefixes & PREFIX_DS)
+ oappend ("%ds:");
+ if (prefixes & PREFIX_SS)
+ oappend ("%ss:");
+ if (prefixes & PREFIX_ES)
+ oappend ("%es:");
+ if (prefixes & PREFIX_FS)
+ oappend ("%fs:");
+ if (prefixes & PREFIX_GS)
+ oappend ("%gs:");
+}
+
+int
+OP_indirE (bytemode)
+ int bytemode;
+{
+ oappend ("*");
+ return OP_E (bytemode);
+}
+
+int
+OP_E (bytemode)
+ int bytemode;
+{
+ int disp;
+
+ /* skip mod/rm byte */
+ codep++;
+
+ if (mod == 3)
+ {
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[rm]);
+ else
+ oappend (names16[rm]);
+ break;
+ default:
+ oappend ("<bad dis table>");
+ break;
+ }
+ return 0;
+ }
+
+ disp = 0;
+ append_prefix ();
+
+ if (aflag) /* 32 bit address mode */
+ {
+ int havesib;
+ int havebase;
+ int base;
+ int index;
+ int scale;
+
+ havesib = 0;
+ havebase = 1;
+ base = rm;
+
+ if (base == 4)
+ {
+ havesib = 1;
+ FETCH_DATA (the_info, codep + 1);
+ scale = (*codep >> 6) & 3;
+ index = (*codep >> 3) & 7;
+ base = *codep & 7;
+ codep++;
+ }
+
+ switch (mod)
+ {
+ case 0:
+ if (base == 5)
+ {
+ havebase = 0;
+ disp = get32 ();
+ }
+ break;
+ case 1:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *(char *)codep++;
+ break;
+ case 2:
+ disp = get32 ();
+ break;
+ }
+
+ if (mod != 0 || base == 5)
+ {
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+ }
+
+ if (havebase || (havesib && (index != 4 || scale != 0)))
+ {
+ oappend ("(");
+ if (havebase)
+ oappend (names32[base]);
+ if (havesib)
+ {
+ if (index != 4)
+ {
+ sprintf (scratchbuf, ",%s", names32[index]);
+ oappend (scratchbuf);
+ }
+ sprintf (scratchbuf, ",%d", 1 << scale);
+ oappend (scratchbuf);
+ }
+ oappend (")");
+ }
+ }
+ else
+ { /* 16 bit address mode */
+ switch (mod)
+ {
+ case 0:
+ if (rm == 6)
+ disp = (short) get16 ();
+ break;
+ case 1:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *(char *)codep++;
+ break;
+ case 2:
+ disp = (short) get16 ();
+ break;
+ }
+
+ if (mod != 0 || rm == 6)
+ {
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+ }
+
+ if (mod != 0 || rm != 6)
+ {
+ oappend ("(");
+ oappend (index16[rm]);
+ oappend (")");
+ }
+ }
+ return 0;
+}
+
+int
+OP_G (bytemode)
+ int bytemode;
+{
+ switch (bytemode)
+ {
+ case b_mode:
+ oappend (names8[reg]);
+ break;
+ case w_mode:
+ oappend (names16[reg]);
+ break;
+ case d_mode:
+ oappend (names32[reg]);
+ break;
+ case v_mode:
+ if (dflag)
+ oappend (names32[reg]);
+ else
+ oappend (names16[reg]);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+ return (0);
+}
+
+static int
+get32 ()
+{
+ int x = 0;
+
+ FETCH_DATA (the_info, codep + 4);
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ x |= (*codep++ & 0xff) << 16;
+ x |= (*codep++ & 0xff) << 24;
+ return (x);
+}
+
+static int
+get16 ()
+{
+ int x = 0;
+
+ FETCH_DATA (the_info, codep + 2);
+ x = *codep++ & 0xff;
+ x |= (*codep++ & 0xff) << 8;
+ return (x);
+}
+
+static void
+set_op (op)
+ int op;
+{
+ op_index[op_ad] = op_ad;
+ op_address[op_ad] = op;
+}
+
+int
+OP_REG (code)
+ int code;
+{
+ char *s;
+
+ switch (code)
+ {
+ case indir_dx_reg: s = "(%dx)"; break;
+ case ax_reg: case cx_reg: case dx_reg: case bx_reg:
+ case sp_reg: case bp_reg: case si_reg: case di_reg:
+ s = names16[code - ax_reg];
+ break;
+ case es_reg: case ss_reg: case cs_reg:
+ case ds_reg: case fs_reg: case gs_reg:
+ s = names_seg[code - es_reg];
+ break;
+ case al_reg: case ah_reg: case cl_reg: case ch_reg:
+ case dl_reg: case dh_reg: case bl_reg: case bh_reg:
+ s = names8[code - al_reg];
+ break;
+ case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg:
+ case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg:
+ if (dflag)
+ s = names32[code - eAX_reg];
+ else
+ s = names16[code - eAX_reg];
+ break;
+ default:
+ s = "<internal disassembler error>";
+ break;
+ }
+ oappend (s);
+ return (0);
+}
+
+int
+OP_I (bytemode)
+ int bytemode;
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ FETCH_DATA (the_info, codep + 1);
+ op = *codep++ & 0xff;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = get16 ();
+ break;
+ case w_mode:
+ op = get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return (0);
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+ return (0);
+}
+
+int
+OP_sI (bytemode)
+ int bytemode;
+{
+ int op;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ FETCH_DATA (the_info, codep + 1);
+ op = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ op = get32 ();
+ else
+ op = (short)get16();
+ break;
+ case w_mode:
+ op = (short)get16 ();
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return (0);
+ }
+ sprintf (scratchbuf, "$0x%x", op);
+ oappend (scratchbuf);
+ return (0);
+}
+
+int
+OP_J (bytemode)
+ int bytemode;
+{
+ int disp;
+ int mask = -1;
+
+ switch (bytemode)
+ {
+ case b_mode:
+ FETCH_DATA (the_info, codep + 1);
+ disp = *(char *)codep++;
+ break;
+ case v_mode:
+ if (dflag)
+ disp = get32 ();
+ else
+ {
+ disp = (short)get16 ();
+ /* for some reason, a data16 prefix on a jump instruction
+ means that the pc is masked to 16 bits after the
+ displacement is added! */
+ mask = 0xffff;
+ }
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ return (0);
+ }
+ disp = (start_pc + codep - start_codep + disp) & mask;
+ set_op (disp);
+ sprintf (scratchbuf, "0x%x", disp);
+ oappend (scratchbuf);
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_SEG (dummy)
+ int dummy;
+{
+ static char *sreg[] = {
+ "%es","%cs","%ss","%ds","%fs","%gs","%?","%?",
+ };
+
+ oappend (sreg[reg]);
+ return (0);
+}
+
+int
+OP_DIR (size)
+ int size;
+{
+ int seg, offset;
+
+ switch (size)
+ {
+ case lptr:
+ if (aflag)
+ {
+ offset = get32 ();
+ seg = get16 ();
+ }
+ else
+ {
+ offset = get16 ();
+ seg = get16 ();
+ }
+ sprintf (scratchbuf, "0x%x,0x%x", seg, offset);
+ oappend (scratchbuf);
+ break;
+ case v_mode:
+ if (aflag)
+ offset = get32 ();
+ else
+ offset = (short)get16 ();
+
+ offset = start_pc + codep - start_codep + offset;
+ set_op (offset);
+ sprintf (scratchbuf, "0x%x", offset);
+ oappend (scratchbuf);
+ break;
+ default:
+ oappend ("<internal disassembler error>");
+ break;
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_OFF (bytemode)
+ int bytemode;
+{
+ int off;
+
+ if (aflag)
+ off = get32 ();
+ else
+ off = get16 ();
+
+ sprintf (scratchbuf, "0x%x", off);
+ oappend (scratchbuf);
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_ESDI (dummy)
+ int dummy;
+{
+ oappend ("%es:(");
+ oappend (aflag ? "%edi" : "%di");
+ oappend (")");
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_DSSI (dummy)
+ int dummy;
+{
+ oappend ("%ds:(");
+ oappend (aflag ? "%esi" : "%si");
+ oappend (")");
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_ONE (dummy)
+ int dummy;
+{
+ oappend ("1");
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_C (dummy)
+ int dummy;
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%cr%d", reg);
+ oappend (scratchbuf);
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_D (dummy)
+ int dummy;
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%db%d", reg);
+ oappend (scratchbuf);
+ return (0);
+}
+
+/* ARGSUSED */
+int
+OP_T (dummy)
+ int dummy;
+{
+ codep++; /* skip mod/rm */
+ sprintf (scratchbuf, "%%tr%d", reg);
+ oappend (scratchbuf);
+ return (0);
+}
+
+int
+OP_rm (bytemode)
+ int bytemode;
+{
+ switch (bytemode)
+ {
+ case d_mode:
+ oappend (names32[rm]);
+ break;
+ case w_mode:
+ oappend (names16[rm]);
+ break;
+ }
+ return (0);
+}
diff --git a/contrib/gdb/opcodes/sysdep.h b/contrib/gdb/opcodes/sysdep.h
new file mode 100644
index 0000000..f1556da
--- /dev/null
+++ b/contrib/gdb/opcodes/sysdep.h
@@ -0,0 +1,38 @@
+/* Random host-dependent support code.
+ Copyright (C) 1995 Free Software Foundation, Inc.
+ Written by Ken Raeburn.
+
+This file is part of libopcodes, the opcodes library.
+
+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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Do system-dependent stuff, mainly driven by autoconf-detected info.
+
+ Well, some generic common stuff is done here too, like including
+ ansidecl.h. That's because the .h files in bfd/hosts files I'm
+ trying to replace often did that. If it can be dropped from this
+ file (check in a non-ANSI environment!), it should be. */
+
+#include "config.h"
+
+#include <ansidecl.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
diff --git a/contrib/gdb/readline/doc/ChangeLog b/contrib/gdb/readline/doc/ChangeLog
new file mode 100644
index 0000000..2520a85
--- /dev/null
+++ b/contrib/gdb/readline/doc/ChangeLog
@@ -0,0 +1,12 @@
+Wed Sep 20 12:57:29 1995 Ian Lance Taylor <ian@cygnus.com>
+
+ * Makefile.in (maintainer-clean): New synonym for realclean.
+
+Tue Feb 2 11:40:04 1993 Roland H. Pesch (pesch@fowanton.cygnus.com)
+
+ * Makefile.in: configurable (and useable) Makefile template
+ * Makefile: removed, replaced with configurable Makefile.in
+ * texindex.c texinfo.tex: remove, replacing w/refs to tools
+ elsewhere in distribution tree
+ * configure.in: pro forma configure stub
+ * ChangeLog: new file
diff --git a/contrib/gdb/readline/doc/Makefile.in b/contrib/gdb/readline/doc/Makefile.in
new file mode 100644
index 0000000..451b9fe
--- /dev/null
+++ b/contrib/gdb/readline/doc/Makefile.in
@@ -0,0 +1,94 @@
+## Copyright (C) 1993 Free Software Foundation, Inc.
+
+# Makefile for Readline documentation.
+
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# 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.
+
+srcdir = .
+
+prefix = /usr/local
+
+infodir = $(prefix)/info
+
+SHELL = /bin/sh
+
+INSTALL = install -c
+INSTALL_DATA = $(INSTALL)
+
+# where to find texinfo
+TEXIDIR=$(srcdir)/../../texinfo
+
+# where to find makeinfo, preferably one designed for texinfo-2
+MAKEINFO=makeinfo
+
+# auxiliary program for sorting Texinfo indices
+TEXINDEX=texindex
+
+# Don Knuth's TeX formatter
+TEX=tex
+
+#### Host, target, and site specific Makefile fragments come in here.
+###
+
+all: info dvi
+
+install: install-info
+
+info: history.info readline.info
+
+dvi: history.dvi readline.dvi
+
+install-info: info
+ -parent=`echo $(infodir)|sed -e 's@/[^/]*$$@@'`; \
+ if [ -d $$parent ] ; then true ; else mkdir $$parent ; fi
+ -if [ -d $(infodir) ] ; then true ; else mkdir $(infodir) ; fi
+ for i in *.info* ; do \
+ $(INSTALL_DATA) $$i $(infodir)/$$i ; \
+ done
+
+history.info: hist.texinfo hsuser.texinfo hstech.texinfo
+ $(MAKEINFO) -I $(srcdir) -o ./history.info $(srcdir)/hist.texinfo
+
+history.dvi: hist.texinfo hsuser.texinfo hstech.texinfo $(TEXIDIR)/texinfo.tex
+ TEXINPUTS=${TEXIDIR}:$(srcdir):$$TEXINPUTS $(TEX) hist.texinfo
+ $(TEXINDEX) hist.??
+ TEXINPUTS=${TEXIDIR}:$(srcdir):$$TEXINPUTS $(TEX) hist.texinfo
+
+readline.info: rlman.texinfo rluser.texinfo rltech.texinfo
+ $(MAKEINFO) -I $(srcdir) -o ./readline.info $(srcdir)/rlman.texinfo
+
+readline.dvi: rlman.texinfo rluser.texinfo rltech.texinfo
+ TEXINPUTS=${TEXIDIR}:$(srcdir):$$TEXINPUTS $(TEX) rlman.texinfo
+ $(TEXINDEX) rlman.??
+ TEXINPUTS=${TEXIDIR}:$(srcdir):$$TEXINPUTS $(TEX) rlman.texinfo
+
+distclean: clean
+ rm -f Makefile config.status
+
+mostlyclean: clean
+
+realclean maintainer-clean: distclean
+
+clean: clean-info clean-dvi
+
+clean-info:
+ rm -f history.info* readline.info*
+
+clean-dvi:
+ rm -f hist.?? hist.???
+ rm -f rlman.?? rlman.???
+
+Makefile: $(srcdir)/Makefile.in $(host_makefile_frag) $(target_makefile_frag)
+ $(SHELL) ./config.status
diff --git a/contrib/gdb/readline/doc/configure.in b/contrib/gdb/readline/doc/configure.in
new file mode 100644
index 0000000..c082c56
--- /dev/null
+++ b/contrib/gdb/readline/doc/configure.in
@@ -0,0 +1,8 @@
+srcname="READLINE doc"
+srctrigger=rlman.texinfo
+# per-host:
+
+# per-target:
+
+files=""
+links=""
diff --git a/contrib/gdb/readline/doc/hist.texinfo b/contrib/gdb/readline/doc/hist.texinfo
new file mode 100644
index 0000000..6292738
--- /dev/null
+++ b/contrib/gdb/readline/doc/hist.texinfo
@@ -0,0 +1,106 @@
+\input texinfo @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename history.info
+@settitle GNU Readline Library
+@comment %**end of header (This is for running Texinfo on a region.)
+@synindex vr fn
+@setchapternewpage odd
+
+@ifinfo
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@titlepage
+@sp 10
+@center @titlefont{GNU History Library}
+@center Brian Fox
+@center Free Software Foundation
+@center Version 1.1
+@center April 1991
+
+@c Include the Distribution inside the titlepage environment so
+@c that headings are turned off.
+
+@page
+
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+@end titlepage
+
+@ifinfo
+@node Top
+@top GNU History Library
+
+This document describes the GNU History library, a programming tool that
+provides a consistent user interface for recalling lines of previously
+typed input.
+
+@menu
+* Using History Interactively:: GNU History User's Manual.
+* Programming with GNU History:: GNU History Programmer's Manual.
+* Concept Index:: Index of concepts described in this manual.
+* Function and Variable Index:: Index of externally visible functions
+ and variables.
+@end menu
+@end ifinfo
+
+@include hsuser.texinfo
+@include hstech.texinfo
+
+@node Concept Index
+@appendix Concept Index
+@printindex cp
+
+@node Function and Variable Index
+@appendix Function and Variable Index
+@printindex vr
+@contents
+
+@bye
diff --git a/contrib/gdb/readline/doc/hstech.texinfo b/contrib/gdb/readline/doc/hstech.texinfo
new file mode 100644
index 0000000..c3fe3f6
--- /dev/null
+++ b/contrib/gdb/readline/doc/hstech.texinfo
@@ -0,0 +1,311 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Programming with GNU History
+@chapter Programming with GNU History
+
+This chapter describes how to interface the GNU History Library with
+programs that you write. It should be considered a technical guide.
+For information on the interactive use of GNU History, @pxref{Using
+History Interactively}.
+
+@menu
+* Introduction to History:: What is the GNU History library for?
+* History Storage:: How information is stored.
+* History Functions:: Functions that you can use.
+* History Variables:: Variables that control behaviour.
+* History Programming Example:: Example of using the GNU History Library.
+@end menu
+
+@node Introduction to History
+@section Introduction to History
+
+Many programs read input from the user a line at a time. The GNU history
+library is able to keep track of those lines, associate arbitrary data with
+each line, and utilize information from previous lines in making up new
+ones.
+
+The programmer using the History library has available to him functions
+for remembering lines on a history stack, associating arbitrary data
+with a line, removing lines from the stack, searching through the stack
+for a line containing an arbitrary text string, and referencing any line
+on the stack directly. In addition, a history @dfn{expansion} function
+is available which provides for a consistent user interface across many
+different programs.
+
+The end-user using programs written with the History library has the
+benifit of a consistent user interface, with a set of well-known
+commands for manipulating the text of previous lines and using that text
+in new commands. The basic history manipulation commands are similar to
+the history substitution used by @code{Csh}.
+
+If the programmer desires, he can use the Readline library, which
+includes some history manipulation by default, and has the added
+advantage of Emacs style command line editing.
+
+@node History Storage
+@section History Storage
+
+@example
+typedef struct _hist_entry @{
+ char *line;
+ char *data;
+@} HIST_ENTRY;
+@end example
+
+@node History Functions
+@section History Functions
+
+This section describes the calling sequence for the various functions
+present in GNU History.
+
+@defun {void using_history} ()
+Begin a session in which the history functions might be used. This
+just initializes the interactive variables.
+@end defun
+
+@defun {void add_history} (char *string)
+Place @var{string} at the end of the history list. The associated data
+field (if any) is set to @code{NULL}.
+@end defun
+
+@defun {int where_history} ()
+Returns the number which says what history element we are now looking
+at.
+@end defun
+
+@defun {int history_set_pos} (int pos)
+Set the position in the history list to @var{pos}.
+@end defun
+
+@defun {int history_search_pos} (char *string, int direction, int pos)
+Search for @var{string} in the history list, starting at @var{pos}, an
+absolute index into the list. @var{direction}, if negative, says to search
+backwards from @var{pos}, else forwards. Returns the absolute index of
+the history element where @var{string} was found, or -1 otherwise.
+@end defun
+
+@defun {HIST_ENTRY *remove_history} ();
+Remove history element @var{which} from the history. The removed
+element is returned to you so you can free the line, data,
+and containing structure.
+@end defun
+
+@defun {void stifle_history} (int max)
+Stifle the history list, remembering only @var{max} number of entries.
+@end defun
+
+@defun {int unstifle_history} ();
+Stop stifling the history. This returns the previous amount the
+history was stifled by. The value is positive if the history was
+stifled, negative if it wasn't.
+@end defun
+
+@defun {int read_history} (char *filename)
+Add the contents of @var{filename} to the history list, a line at a
+time. If @var{filename} is @code{NULL}, then read from
+@file{~/.history}. Returns 0 if successful, or errno if not.
+@end defun
+
+@defun {int read_history_range} (char *filename, int from, int to)
+Read a range of lines from @var{filename}, adding them to the history list.
+Start reading at the @var{from}'th line and end at the @var{to}'th. If
+@var{from} is zero, start at the beginning. If @var{to} is less than
+@var{from}, then read until the end of the file. If @var{filename} is
+@code{NULL}, then read from @file{~/.history}. Returns 0 if successful,
+or @code{errno} if not.
+@end defun
+
+@defun {int write_history} (char *filename)
+Append the current history to @var{filename}. If @var{filename} is
+@code{NULL}, then append the history list to @file{~/.history}. Values
+returned are as in @code{read_history ()}.
+@end defun
+
+@defun {int append_history} (int nelements, char *filename)
+Append @var{nelement} entries to @var{filename}. The entries appended
+are from the end of the list minus @var{nelements} up to the end of the
+list.
+@end defun
+
+@defun {HIST_ENTRY *replace_history_entry} ()
+Make the history entry at @var{which} have @var{line} and @var{data}.
+This returns the old entry so you can dispose of the data. In the case
+of an invalid @var{which}, a @code{NULL} pointer is returned.
+@end defun
+
+@defun {HIST_ENTRY *current_history} ()
+Return the history entry at the current position, as determined by
+@code{history_offset}. If there is no entry there, return a @code{NULL}
+pointer.
+@end defun
+
+@defun {HIST_ENTRY *previous_history} ()
+Back up @var{history_offset} to the previous history entry, and return a
+pointer to that entry. If there is no previous entry, return a
+@code{NULL} pointer.
+@end defun
+
+@defun {HIST_ENTRY *next_history} ()
+Move @code{history_offset} forward to the next history entry, and return
+the a pointer to that entry. If there is no next entry, return a
+@code{NULL} pointer.
+@end defun
+
+@defun {HIST_ENTRY **history_list} ()
+Return a @code{NULL} terminated array of @code{HIST_ENTRY} which is the
+current input history. Element 0 of this list is the beginning of time.
+If there is no history, return @code{NULL}.
+@end defun
+
+@defun {int history_search} (char *string, int direction)
+Search the history for @var{string}, starting at @code{history_offset}.
+If @var{direction} < 0, then the search is through previous entries,
+else through subsequent. If @var{string} is found, then
+@code{current_history ()} is the history entry, and the value of this
+function is the offset in the line of that history entry that the
+@var{string} was found in. Otherwise, nothing is changed, and a -1 is
+returned.
+@end defun
+
+@defun {int history_expand} (char *string, char **output)
+Expand @var{string}, placing the result into @var{output}, a pointer
+to a string. Returns:
+@table @code
+@item 0
+If no expansions took place (or, if the only change in
+the text was the de-slashifying of the history expansion
+character),
+@item 1
+if expansions did take place, or
+@item -1
+if there was an error in expansion.
+@end table
+
+If an error ocurred in expansion, then @var{output} contains a descriptive
+error message.
+@end defun
+
+@defun {char *history_arg_extract} (int first, int last, char *string)
+Extract a string segment consisting of the @var{first} through @var{last}
+arguments present in @var{string}. Arguments are broken up as in
+the GNU Bash shell.
+@end defun
+
+@defun {int history_total_bytes} ();
+Return the number of bytes that the primary history entries are using.
+This just adds up the lengths of @code{the_history->lines}.
+@end defun
+
+@node History Variables
+@section History Variables
+
+This section describes the variables in GNU History that are externally
+visible.
+
+@defvar {int history_base}
+For convenience only. You set this when interpreting history commands.
+It is the logical offset of the first history element.
+@end defvar
+
+@node History Programming Example
+@section History Programming Example
+
+The following snippet of code demonstrates simple use of the GNU History
+Library.
+
+@smallexample
+main ()
+@{
+ char line[1024], *t;
+ int done = 0;
+
+ line[0] = 0;
+
+ while (!done)
+ @{
+ fprintf (stdout, "history%% ");
+ t = gets (line);
+
+ if (!t)
+ strcpy (line, "quit");
+
+ if (line[0])
+ @{
+ char *expansion;
+ int result;
+
+ using_history ();
+
+ result = history_expand (line, &expansion);
+ strcpy (line, expansion);
+ free (expansion);
+ if (result)
+ fprintf (stderr, "%s\n", line);
+
+ if (result < 0)
+ continue;
+
+ add_history (line);
+ @}
+
+ if (strcmp (line, "quit") == 0) done = 1;
+ if (strcmp (line, "save") == 0) write_history (0);
+ if (strcmp (line, "read") == 0) read_history (0);
+ if (strcmp (line, "list") == 0)
+ @{
+ register HIST_ENTRY **the_list = history_list ();
+ register int i;
+
+ if (the_list)
+ for (i = 0; the_list[i]; i++)
+ fprintf (stdout, "%d: %s\n",
+ i + history_base, the_list[i]->line);
+ @}
+ if (strncmp (line, "delete", strlen ("delete")) == 0)
+ @{
+ int which;
+ if ((sscanf (line + strlen ("delete"), "%d", &which)) == 1)
+ @{
+ HIST_ENTRY *entry = remove_history (which);
+ if (!entry)
+ fprintf (stderr, "No such entry %d\n", which);
+ else
+ @{
+ free (entry->line);
+ free (entry);
+ @}
+ @}
+ else
+ @{
+ fprintf (stderr, "non-numeric arg given to `delete'\n");
+ @}
+ @}
+ @}
+@}
+@end smallexample
+
+
+
diff --git a/contrib/gdb/readline/doc/hsuser.texinfo b/contrib/gdb/readline/doc/hsuser.texinfo
new file mode 100644
index 0000000..cda0a68
--- /dev/null
+++ b/contrib/gdb/readline/doc/hsuser.texinfo
@@ -0,0 +1,153 @@
+@ignore
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Using History Interactively
+@chapter Using History Interactively
+
+This chapter describes how to use the GNU History Library interactively,
+from a user's standpoint. It should be considered a user's guide. For
+information on using the GNU History Library in your own programs,
+@pxref{Programming with GNU History}.
+
+@menu
+* History Interaction:: What it feels like using History as a user.
+@end menu
+
+@node History Interaction
+@section History Interaction
+@cindex expansion
+
+The History library provides a history expansion feature that is similar
+to the history expansion in Csh. The following text describes the sytax
+that you use to manipulate the history information.
+
+History expansion takes place in two parts. The first is to determine
+which line from the previous history should be used during substitution.
+The second is to select portions of that line for inclusion into the
+current one. The line selected from the previous history is called the
+@dfn{event}, and the portions of that line that are acted upon are
+called @dfn{words}. The line is broken into words in the same fashion
+that the Bash shell does, so that several English (or Unix) words
+surrounded by quotes are considered as one word.
+
+@menu
+* Event Designators:: How to specify which history line to use.
+* Word Designators:: Specifying which words are of interest.
+* Modifiers:: Modifying the results of susbstitution.
+@end menu
+
+@node Event Designators
+@subsection Event Designators
+@cindex event designators
+
+An event designator is a reference to a command line entry in the
+history list.
+
+@table @asis
+
+@item @code{!}
+Start a history subsititution, except when followed by a space, tab, or
+the end of the line... @key{=} or @key{(}.
+
+@item @code{!!}
+Refer to the previous command. This is a synonym for @code{!-1}.
+
+@item @code{!n}
+Refer to command line @var{n}.
+
+@item @code{!-n}
+Refer to the command line @var{n} lines back.
+
+@item @code{!string}
+Refer to the most recent command starting with @var{string}.
+
+@item @code{!?string}[@code{?}]
+Refer to the most recent command containing @var{string}.
+
+@end table
+
+@node Word Designators
+@subsection Word Designators
+
+A @key{:} separates the event specification from the word designator. It
+can be omitted if the word designator begins with a @key{^}, @key{$},
+@key{*} or @key{%}. Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+
+@table @code
+
+@item 0 (zero)
+The zero'th word. For many applications, this is the command word.
+
+@item n
+The @var{n}'th word.
+
+@item ^
+The first argument. that is, word 1.
+
+@item $
+The last argument.
+
+@item %
+The word matched by the most recent @code{?string?} search.
+
+@item x-y
+A range of words; @code{-@var{y}} Abbreviates @code{0-@var{y}}.
+
+@item *
+All of the words, excepting the zero'th. This is a synonym for @code{1-$}.
+It is not an error to use @key{*} if there is just one word in the event.
+The empty string is returned in that case.
+
+@end table
+
+@node Modifiers
+@subsection Modifiers
+
+After the optional word designator, you can add a sequence of one or more
+of the following modifiers, each preceded by a @key{:}.
+
+@table @code
+
+@item #
+The entire command line typed so far. This means the current command,
+not the previous command, so it really isn't a word designator, and doesn't
+belong in this section.
+
+@item h
+Remove a trailing pathname component, leaving only the head.
+
+@item r
+Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename.
+
+@item e
+Remove all but the suffix.
+
+@item t
+Remove all leading pathname components, leaving the tail.
+
+@item p
+Print the new command but do not execute it.
+@end table
diff --git a/contrib/gdb/readline/doc/inc-hist.texi b/contrib/gdb/readline/doc/inc-hist.texi
new file mode 100644
index 0000000..9cdde40
--- /dev/null
+++ b/contrib/gdb/readline/doc/inc-hist.texi
@@ -0,0 +1,159 @@
+@ignore
+This file is completely identical to hsuser.texinfo, except that it has the
+reference to the programming manual removed. There are definately better ways
+to do this!
+
+This file documents the user interface to the GNU History library.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+Authored by Brian Fox.
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Using History Interactively
+@appendix Using History Interactively
+
+This chapter describes how to use the GNU History Library interactively,
+from a user's standpoint.
+
+@menu
+* History Interaction:: What it feels like using History as a user.
+@end menu
+
+@node History Interaction
+@section History Interaction
+@cindex expansion
+
+The History library provides a history expansion feature similar
+to the history expansion in @code{csh}. The following text describes the
+syntax you use to manipulate history information.
+
+History expansion takes two parts. In the first part, determine
+which line from the previous history will be used for substitution.
+This line is called the @dfn{event}.
+In the second part, select portions of that line for inclusion into the
+current line. These portions are called @dfn{words}.
+@value{GDBN} breaks the line into words in the same
+way that the Bash shell does, so that several English (or Unix) words
+surrounded by quotes are considered one word.
+
+@menu
+* Event Designators:: How to specify which history line to use.
+* Word Designators:: Specifying which words are of interest.
+* Modifiers:: Modifying the results of susbstitution.
+@end menu
+
+@node Event Designators
+@subsection Event Designators
+@cindex event designators
+
+An @dfn{event designator} is a reference to a command line entry in the
+history list.
+
+@table @asis
+
+@item @code{!}
+Start a history subsititution, except when followed by a space, tab, or
+the end of the line... @key{=} or @key{(}.
+
+@item @code{!!}
+Refer to the previous command. This is a synonym for @code{!-1}.
+
+@item @code{!n}
+Refer to command line @var{n}.
+
+@item @code{!-n}
+Refer to the command line @var{n} lines back.
+
+@item @code{!string}
+Refer to the most recent command starting with @var{string}.
+
+@item @code{!?string}[@code{?}]
+Refer to the most recent command containing @var{string}.
+
+@end table
+
+@node Word Designators
+@subsection Word Designators
+
+A @key{:} separates the event designator from the @dfn{word designator}.
+It can be omitted if the word designator begins with a @key{^}, @key{$},
+@key{*} or @key{%}. Words are numbered from the beginning of the line,
+with the first word being denoted by a 0 (zero).
+
+@table @code
+
+@item 0 (zero)
+The zero'th word. For many applications, this is the command word.
+
+@item n
+The @var{n}'th word.
+
+@item ^
+The first argument. that is, word 1.
+
+@item $
+The last argument.
+
+@item %
+The word matched by the most recent @code{?string?} search.
+
+@item x-y
+A range of words; @code{-@var{y}} Abbreviates @code{0-@var{y}}.
+
+@item *
+All of the words, excepting the zero'th. This is a synonym for @code{1-$}.
+It is not an error to use @key{*} if there is just one word in the event.
+The empty string is returned in that case.
+
+@end table
+
+@node Modifiers
+@subsection Modifiers
+
+After the optional word designator, you can add a sequence of one or more
+of the following @dfn{modifiers}, each preceded by a @key{:}.
+
+@table @code
+
+@item #
+The entire command line typed so far. This means the current command,
+not the previous command.
+@c
+@c FIXME: If it doesn't belong here, let's put it where it does.
+@c
+@c so it technically isn't a word designator and doesn't belong in
+@c this section.
+
+@item h
+Remove a trailing pathname component, leaving only the head.
+
+@item r
+Remove a trailing suffix of the form @samp{.}@var{suffix}, leaving the basename.
+
+@item e
+Remove all but the suffix.
+
+@item t
+Remove all leading pathname components, leaving the tail.
+
+@item p
+Print the new command but do not execute it.
+@end table
diff --git a/contrib/gdb/readline/doc/rlman.texinfo b/contrib/gdb/readline/doc/rlman.texinfo
new file mode 100644
index 0000000..f2e7fb6
--- /dev/null
+++ b/contrib/gdb/readline/doc/rlman.texinfo
@@ -0,0 +1,103 @@
+\input texinfo @c -*-texinfo-*-
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename readline.info
+@settitle GNU Readline Library
+@comment %**end of header (This is for running Texinfo on a region.)
+@synindex vr fn
+@setchapternewpage odd
+
+@ifinfo
+This document describes the GNU Readline Library, a utility which aids
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+
+Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@titlepage
+@sp 10
+@center @titlefont{GNU Readline Library}
+@center Brian Fox
+@center Free Software Foundation
+@center Version 1.1
+@center April 1991
+
+@page
+This document describes the GNU Readline Library, a utility which aids
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+
+Published by the Free Software Foundation @*
+675 Massachusetts Avenue, @*
+Cambridge, MA 02139 USA
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1989, 1991 Free Software Foundation, Inc.
+@end titlepage
+
+@ifinfo
+@node Top
+@top GNU Readline Library
+
+This document describes the GNU Readline Library, a utility which aids
+in the consistency of user interface across discrete programs that need
+to provide a command line interface.
+
+@menu
+* Command Line Editing:: GNU Readline User's Manual.
+* Programming with GNU Readline:: GNU Readline Programmer's Manual.
+* Concept Index:: Index of concepts described in this manual.
+* Function and Variable Index:: Index of externally visible functions
+ and variables.
+@end menu
+@end ifinfo
+
+@include rluser.texinfo
+@include rltech.texinfo
+
+@node Concept Index
+@unnumbered Concept Index
+@printindex cp
+
+@node Function and Variable Index
+@unnumbered Function and Variable Index
+@printindex fn
+
+@contents
+@bye
+
diff --git a/contrib/gdb/readline/doc/rltech.texinfo b/contrib/gdb/readline/doc/rltech.texinfo
new file mode 100644
index 0000000..2048b7c
--- /dev/null
+++ b/contrib/gdb/readline/doc/rltech.texinfo
@@ -0,0 +1,1012 @@
+@comment %**start of header (This is for running Texinfo on a region.)
+@setfilename rltech.info
+@comment %**end of header (This is for running Texinfo on a region.)
+@setchapternewpage odd
+
+@ifinfo
+This document describes the GNU Readline Library, a utility for aiding
+in the consitency of user interface across discrete programs that need
+to provide a command line interface.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+pare preserved on all copies.
+
+@ignore
+Permission is granted to process this file through TeX and print the
+results, provided the printed document carries copying permission
+notice identical to this one except for the removal of this paragraph
+(this paragraph not being relevant to the printed manual).
+@end ignore
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the entire
+resulting derived work is distributed under the terms of a permission
+notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions,
+except that this permission notice may be stated in a translation approved
+by the Foundation.
+@end ifinfo
+
+@node Programming with GNU Readline
+@chapter Programming with GNU Readline
+
+This manual describes the interface between the GNU Readline Library and
+user programs. If you are a programmer, and you wish to include the
+features found in GNU Readline in your own programs, such as completion,
+line editing, and interactive history manipulation, this documentation
+is for you.
+
+@menu
+* Default Behaviour:: Using the default behaviour of Readline.
+* Custom Functions:: Adding your own functions to Readline.
+* Custom Completers:: Supplanting or supplementing Readline's
+ completion functions.
+@end menu
+
+@node Default Behaviour
+@section Default Behaviour
+
+Many programs provide a command line interface, such as @code{mail},
+@code{ftp}, and @code{sh}. For such programs, the default behaviour of
+Readline is sufficient. This section describes how to use Readline in
+the simplest way possible, perhaps to replace calls in your code to
+@code{gets ()}.
+
+@findex readline ()
+@cindex readline, function
+The function @code{readline} prints a prompt and then reads and returns
+a single line of text from the user. The line which @code{readline ()}
+returns is allocated with @code{malloc ()}; you should @code{free ()}
+the line when you are done with it. The declaration for @code{readline}
+in ANSI C is
+
+@example
+@code{char *readline (char *@var{prompt});}
+@end example
+
+So, one might say
+@example
+@code{char *line = readline ("Enter a line: ");}
+@end example
+in order to read a line of text from the user.
+
+The line which is returned has the final newline removed, so only the
+text of the line remains.
+
+If readline encounters an @code{EOF} while reading the line, and the
+line is empty at that point, then @code{(char *)NULL} is returned.
+Otherwise, the line is ended just as if a newline was typed.
+
+If you want the user to be able to get at the line later, (with
+@key{C-p} for example), you must call @code{add_history ()} to save the
+line away in a @dfn{history} list of such lines.
+
+@example
+@code{add_history (line)};
+@end example
+
+For full details on the GNU History Library, see the associated manual.
+
+It is polite to avoid saving empty lines on the history list, since it
+is rare than someone has a burning need to reuse a blank line. Here is
+a function which usefully replaces the standard @code{gets ()} library
+function:
+
+@example
+/* A static variable for holding the line. */
+static char *line_read = (char *)NULL;
+
+/* Read a string, and return a pointer to it. Returns NULL on EOF. */
+char *
+do_gets ()
+@{
+ /* If the buffer has already been allocated, return the memory
+ to the free pool. */
+ if (line_read != (char *)NULL)
+ @{
+ free (line_read);
+ line_read = (char *)NULL;
+ @}
+
+ /* Get a line from the user. */
+ line_read = readline ("");
+
+ /* If the line has any text in it, save it on the history. */
+ if (line_read && *line_read)
+ add_history (line_read);
+
+ return (line_read);
+@}
+@end example
+
+The above code gives the user the default behaviour of @key{TAB}
+completion: completion on file names. If you do not want readline to
+complete on filenames, you can change the binding of the @key{TAB} key
+with @code{rl_bind_key ()}.
+
+@findex rl_bind_key ()
+@example
+@code{int rl_bind_key (int @var{key}, int (*@var{function})());}
+@end example
+
+@code{rl_bind_key ()} takes 2 arguments; @var{key} is the character that
+you want to bind, and @var{function} is the address of the function to
+run when @var{key} is pressed. Binding @key{TAB} to @code{rl_insert ()}
+makes @key{TAB} just insert itself.
+
+@code{rl_bind_key ()} returns non-zero if @var{key} is not a valid
+ASCII character code (between 0 and 255).
+
+@example
+@code{rl_bind_key ('\t', rl_insert);}
+@end example
+
+This code should be executed once at the start of your program; you
+might write a function called @code{initialize_readline ()} which
+performs this and other desired initializations, such as installing
+custom completers, etc.
+
+@node Custom Functions
+@section Custom Functions
+
+Readline provides a great many functions for manipulating the text of
+the line. But it isn't possible to anticipate the needs of all
+programs. This section describes the various functions and variables
+defined in within the Readline library which allow a user program to add
+customized functionality to Readline.
+
+@menu
+* The Function Type:: C declarations to make code readable.
+* Function Naming:: How to give a function you write a name.
+* Keymaps:: Making keymaps.
+* Binding Keys:: Changing Keymaps.
+* Function Writing:: Variables and calling conventions.
+* Allowing Undoing:: How to make your functions undoable.
+@end menu
+
+@node The Function Type
+@subsection The Function Type
+
+For the sake of readabilty, we declare a new type of object, called
+@dfn{Function}. A @code{Function} is a C language function which
+returns an @code{int}. The type declaration for @code{Function} is:
+
+@noindent
+@code{typedef int Function ();}
+
+The reason for declaring this new type is to make it easier to write
+code describing pointers to C functions. Let us say we had a variable
+called @var{func} which was a pointer to a function. Instead of the
+classic C declaration
+
+@code{int (*)()func;}
+
+we have
+
+@code{Function *func;}
+
+@node Function Naming
+@subsection Naming a Function
+
+The user can dynamically change the bindings of keys while using
+Readline. This is done by representing the function with a descriptive
+name. The user is able to type the descriptive name when referring to
+the function. Thus, in an init file, one might find
+
+@example
+Meta-Rubout: backward-kill-word
+@end example
+
+This binds the keystroke @key{Meta-Rubout} to the function
+@emph{descriptively} named @code{backward-kill-word}. You, as the
+programmer, should bind the functions you write to descriptive names as
+well. Readline provides a function for doing that:
+
+@defun rl_add_defun (char *name, Function *function, int key)
+Add @var{name} to the list of named functions. Make @var{function} be
+the function that gets called. If @var{key} is not -1, then bind it to
+@var{function} using @code{rl_bind_key ()}.
+@end defun
+
+Using this function alone is sufficient for most applications. It is
+the recommended way to add a few functions to the default functions that
+Readline has built in already. If you need to do more or different
+things than adding a function to Readline, you may need to use the
+underlying functions described below.
+
+@node Keymaps
+@subsection Selecting a Keymap
+
+Key bindings take place on a @dfn{keymap}. The keymap is the
+association between the keys that the user types and the functions that
+get run. You can make your own keymaps, copy existing keymaps, and tell
+Readline which keymap to use.
+
+@defun {Keymap rl_make_bare_keymap} ()
+Returns a new, empty keymap. The space for the keymap is allocated with
+@code{malloc ()}; you should @code{free ()} it when you are done.
+@end defun
+
+@defun {Keymap rl_copy_keymap} (Keymap map)
+Return a new keymap which is a copy of @var{map}.
+@end defun
+
+@defun {Keymap rl_make_keymap} ()
+Return a new keymap with the printing characters bound to rl_insert,
+the lowercase Meta characters bound to run their equivalents, and
+the Meta digits bound to produce numeric arguments.
+@end defun
+
+@node Binding Keys
+@subsection Binding Keys
+
+You associate keys with functions through the keymap. Here are
+functions for doing that.
+
+@defun {int rl_bind_key} (int key, Function *function)
+Binds @var{key} to @var{function} in the currently selected keymap.
+Returns non-zero in the case of an invalid @var{key}.
+@end defun
+
+@defun {int rl_bind_key_in_map} (int key, Function *function, Keymap map)
+Bind @var{key} to @var{function} in @var{map}. Returns non-zero in the case
+of an invalid @var{key}.
+@end defun
+
+@defun {int rl_unbind_key} (int key)
+Make @var{key} do nothing in the currently selected keymap.
+Returns non-zero in case of error.
+@end defun
+
+@defun {int rl_unbind_key_in_map} (int key, Keymap map)
+Make @var{key} be bound to the null function in @var{map}.
+Returns non-zero in case of error.
+@end defun
+
+@defun rl_generic_bind (int type, char *keyseq, char *data, Keymap map)
+Bind the key sequence represented by the string @var{keyseq} to the arbitrary
+pointer @var{data}. @var{type} says what kind of data is pointed to by
+@var{data}; right now this can be a function (@code{ISFUNC}), a macro
+(@code{ISMACR}), or a keymap (@code{ISKMAP}). This makes new keymaps as
+necessary. The initial place to do bindings is in @var{map}.
+@end defun
+
+@node Function Writing
+@subsection Writing a New Function
+
+In order to write new functions for Readline, you need to know the
+calling conventions for keyboard invoked functions, and the names of the
+variables that describe the current state of the line gathered so far.
+
+@defvar {char *rl_line_buffer}
+This is the line gathered so far. You are welcome to modify the
+contents of this, but see Undoing, below.
+@end defvar
+
+@defvar {int rl_point}
+The offset of the current cursor position in @var{rl_line_buffer}.
+@end defvar
+
+@defvar {int rl_end}
+The number of characters present in @code{rl_line_buffer}. When
+@code{rl_point} is at the end of the line, then @code{rl_point} and
+@code{rl_end} are equal.
+@end defvar
+
+The calling sequence for a command @code{foo} looks like
+
+@example
+@code{foo (int count, int key)}
+@end example
+
+where @var{count} is the numeric argument (or 1 if defaulted) and
+@var{key} is the key that invoked this function.
+
+It is completely up to the function as to what should be done with the
+numeric argument; some functions use it as a repeat count, other
+functions as a flag, and some choose to ignore it. In general, if a
+function uses the numeric argument as a repeat count, it should be able
+to do something useful with a negative argument as well as a positive
+argument. At the very least, it should be aware that it can be passed a
+negative argument.
+
+@node Allowing Undoing
+@subsection Allowing Undoing
+
+Supporting the undo command is a painless thing to do, and makes your
+functions much more useful to the end user. It is certainly easy to try
+something if you know you can undo it. I could use an undo function for
+the stock market.
+
+If your function simply inserts text once, or deletes text once, and it
+calls @code{rl_insert_text ()} or @code{rl_delete_text ()} to do it, then
+undoing is already done for you automatically, and you can safely skip
+this section.
+
+If you do multiple insertions or multiple deletions, or any combination
+of these operations, you should group them together into one operation.
+This can be done with @code{rl_begin_undo_group ()} and
+@code{rl_end_undo_group ()}.
+
+@defun rl_begin_undo_group ()
+Begins saving undo information in a group construct. The undo
+information usually comes from calls to @code{rl_insert_text ()} and
+@code{rl_delete_text ()}, but they could be direct calls to
+@code{rl_add_undo ()}.
+@end defun
+
+@defun rl_end_undo_group ()
+Closes the current undo group started with @code{rl_begin_undo_group
+()}. There should be exactly one call to @code{rl_end_undo_group ()}
+for every call to @code{rl_begin_undo_group ()}.
+@end defun
+
+Finally, if you neither insert nor delete text, but directly modify the
+existing text (e.g. change its case), you call @code{rl_modifying ()}
+once, just before you modify the text. You must supply the indices of
+the text range that you are going to modify.
+
+@defun rl_modifying (int start, int end)
+Tell Readline to save the text between @var{start} and @var{end} as a
+single undo unit. It is assumed that subsequent to this call you will
+modify that range of text in some way.
+@end defun
+
+@subsection An Example
+
+Here is a function which changes lowercase characters to the uppercase
+equivalents, and uppercase characters to the lowercase equivalents. If
+this function was bound to @samp{M-c}, then typing @samp{M-c} would
+change the case of the character under point. Typing @samp{10 M-c}
+would change the case of the following 10 characters, leaving the cursor on
+the last character changed.
+
+@example
+/* Invert the case of the COUNT following characters. */
+invert_case_line (count, key)
+ int count, key;
+@{
+ register int start, end;
+
+ start = rl_point;
+
+ if (count < 0)
+ @{
+ direction = -1;
+ count = -count;
+ @}
+ else
+ direction = 1;
+
+ /* Find the end of the range to modify. */
+ end = start + (count * direction);
+
+ /* Force it to be within range. */
+ if (end > rl_end)
+ end = rl_end;
+ else if (end < 0)
+ end = -1;
+
+ if (start > end)
+ @{
+ int temp = start;
+ start = end;
+ end = temp;
+ @}
+
+ if (start == end)
+ return;
+
+ /* Tell readline that we are modifying the line, so save the undo
+ information. */
+ rl_modifying (start, end);
+
+ for (; start != end; start += direction)
+ @{
+ if (uppercase_p (rl_line_buffer[start]))
+ rl_line_buffer[start] = to_lower (rl_line_buffer[start]);
+ else if (lowercase_p (rl_line_buffer[start]))
+ rl_line_buffer[start] = to_upper (rl_line_buffer[start]);
+ @}
+ /* Move point to on top of the last character changed. */
+ rl_point = end - direction;
+@}
+@end example
+
+@node Custom Completers
+@section Custom Completers
+
+Typically, a program that reads commands from the user has a way of
+disambiguating commands and data. If your program is one of these, then
+it can provide completion for either commands, or data, or both commands
+and data. The following sections describe how your program and Readline
+cooperate to provide this service to end users.
+
+@menu
+* How Completing Works:: The logic used to do completion.
+* Completion Functions:: Functions provided by Readline.
+* Completion Variables:: Variables which control completion.
+* A Short Completion Example:: An example of writing completer subroutines.
+@end menu
+
+@node How Completing Works
+@subsection How Completing Works
+
+In order to complete some text, the full list of possible completions
+must be available. That is to say, it is not possible to accurately
+expand a partial word without knowing what all of the possible words
+that make sense in that context are. The GNU Readline library provides
+the user interface to completion, and additionally, two of the most common
+completion functions; filename and username. For completing other types
+of text, you must write your own completion function. This section
+describes exactly what those functions must do, and provides an example
+function.
+
+There are three major functions used to perform completion:
+
+@enumerate
+@item
+The user-interface function @code{rl_complete ()}. This function is
+called interactively with the same calling conventions as other
+functions in readline intended for interactive use; i.e. @var{count},
+and @var{invoking-key}. It isolates the word to be completed and calls
+@code{completion_matches ()} to generate a list of possible completions.
+It then either lists the possible completions or actually performs the
+completion, depending on which behaviour is desired.
+
+@item
+The internal function @code{completion_matches ()} uses your
+@dfn{generator} function to generate the list of possible matches, and
+then returns the array of these matches. You should place the address
+of your generator function in @code{rl_completion_entry_function}.
+
+@item
+The generator function is called repeatedly from
+@code{completion_matches ()}, returning a string each time. The
+arguments to the generator function are @var{text} and @var{state}.
+@var{text} is the partial word to be completed. @var{state} is zero the
+first time the function is called, and a positive non-zero integer for
+each subsequent call. When the generator function returns @code{(char
+*)NULL} this signals @code{completion_matches ()} that there are no more
+possibilities left.
+
+@end enumerate
+
+@defun rl_complete (int ignore, int invoking_key)
+Complete the word at or before point. You have supplied the function
+that does the initial simple matching selection algorithm (see
+@code{completion_matches ()}). The default is to do filename completion.
+@end defun
+
+Note that @code{rl_complete ()} has the identical calling conventions as
+any other key-invokable function; this is because by default it is bound
+to the @samp{TAB} key.
+
+@defvar {Function *rl_completion_entry_function}
+This is a pointer to the generator function for @code{completion_matches
+()}. If the value of @code{rl_completion_entry_function} is
+@code{(Function *)NULL} then the default filename generator function is
+used, namely @code{filename_entry_function ()}.
+@end defvar
+
+@node Completion Functions
+@subsection Completion Functions
+
+Here is the complete list of callable completion functions present in
+Readline.
+
+@defun rl_complete_internal (int what_to_do)
+Complete the word at or before point. @var{what_to_do} says what to do
+with the completion. A value of @samp{?} means list the possible
+completions. @samp{TAB} means do standard completion. @samp{*} means
+insert all of the possible completions.
+@end defun
+
+@defun rl_complete (int ignore, int invoking_key)
+Complete the word at or before point. You have supplied the function
+that does the initial simple matching selection algorithm (see
+@code{completion_matches ()}). The default is to do filename
+completion. This just calls @code{rl_complete_internal ()} with an
+argument of @samp{TAB}.
+@end defun
+
+@defun rl_possible_completions ()
+List the possible completions. See description of @code{rl_complete
+()}. This just calls @code{rl_complete_internal ()} with an argument of
+@samp{?}.
+@end defun
+
+@defun {char **completion_matches} (char *text, char *(*entry_function) ())
+Returns an array of @code{(char *)} which is a list of completions for
+@var{text}. If there are no completions, returns @code{(char **)NULL}.
+The first entry in the returned array is the substitution for @var{text}.
+The remaining entries are the possible completions. The array is
+terminated with a @code{NULL} pointer.
+
+@var{entry_function} is a function of two args, and returns a
+@code{(char *)}. The first argument is @var{text}. The second is a
+state argument; it is zero on the first call, and non-zero on subsequent
+calls. It returns a @code{NULL} pointer to the caller when there are
+no more matches.
+@end defun
+
+@defun {char *filename_completion_function} (char *text, int state)
+A generator function for filename completion in the general case. Note
+that completion in the Bash shell is a little different because of all
+the pathnames that must be followed when looking up the completion for a
+command.
+@end defun
+
+@defun {char *username_completion_function} (char *text, int state)
+A completion generator for usernames. @var{text} contains a partial
+username preceded by a random character (usually @samp{~}).
+@end defun
+
+@node Completion Variables
+@subsection Completion Variables
+
+@defvar {Function *rl_completion_entry_function}
+A pointer to the generator function for @code{completion_matches ()}.
+@code{NULL} means to use @code{filename_entry_function ()}, the default
+filename completer.
+@end defvar
+
+@defvar {Function *rl_attempted_completion_function}
+A pointer to an alternative function to create matches.
+The function is called with @var{text}, @var{start}, and @var{end}.
+@var{start} and @var{end} are indices in @code{rl_line_buffer} saying
+what the boundaries of @var{text} are. If this function exists and
+returns @code{NULL} then @code{rl_complete ()} will call the value of
+@code{rl_completion_entry_function} to generate matches, otherwise the
+array of strings returned will be used.
+@end defvar
+
+@defvar {int rl_completion_query_items}
+Up to this many items will be displayed in response to a
+possible-completions call. After that, we ask the user if she is sure
+she wants to see them all. The default value is 100.
+@end defvar
+
+@defvar {char *rl_basic_word_break_characters}
+The basic list of characters that signal a break between words for the
+completer routine. The contents of this variable is what breaks words
+in the Bash shell, i.e. " \t\n\"\\'`@@$><=;|&@{(".
+@end defvar
+
+@defvar {char *rl_completer_word_break_characters}
+The list of characters that signal a break between words for
+@code{rl_complete_internal ()}. The default list is the contents of
+@code{rl_basic_word_break_characters}.
+@end defvar
+
+@defvar {char *rl_special_prefixes}
+The list of characters that are word break characters, but should be
+left in @var{text} when it is passed to the completion function.
+Programs can use this to help determine what kind of completing to do.
+@end defvar
+
+@defvar {int rl_ignore_completion_duplicates}
+If non-zero, then disallow duplicates in the matches. Default is 1.
+@end defvar
+
+@defvar {int rl_filename_completion_desired}
+Non-zero means that the results of the matches are to be treated as
+filenames. This is @emph{always} zero on entry, and can only be changed
+within a completion entry generator function.
+@end defvar
+
+@defvar {Function *rl_ignore_some_completions_function}
+This function, if defined, is called by the completer when real filename
+completion is done, after all the matching names have been generated.
+It is passed a @code{NULL} terminated array of @code{(char *)} known as
+@var{matches} in the code. The 1st element (@code{matches[0]}) is the
+maximal substring that is common to all matches. This function can
+re-arrange the list of matches as required, but each deleted element of
+the array must be @code{free()}'d.
+@end defvar
+
+@node A Short Completion Example
+@subsection A Short Completion Example
+
+Here is a small application demonstrating the use of the GNU Readline
+library. It is called @code{fileman}, and the source code resides in
+@file{readline/examples/fileman.c}. This sample application provides
+completion of command names, line editing features, and access to the
+history list.
+
+@page
+@smallexample
+/* fileman.c -- A tiny application which demonstrates how to use the
+ GNU Readline library. This application interactively allows users
+ to manipulate files and their modes. */
+
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+
+/* The names of functions that actually do the manipulation. */
+int com_list (), com_view (), com_rename (), com_stat (), com_pwd ();
+int com_delete (), com_help (), com_cd (), com_quit ();
+
+/* A structure which contains information on the commands this program
+ can understand. */
+
+typedef struct @{
+ char *name; /* User printable name of the function. */
+ Function *func; /* Function to call to do the job. */
+ char *doc; /* Documentation for this function. */
+@} COMMAND;
+
+COMMAND commands[] = @{
+ @{ "cd", com_cd, "Change to directory DIR" @},
+ @{ "delete", com_delete, "Delete FILE" @},
+ @{ "help", com_help, "Display this text" @},
+ @{ "?", com_help, "Synonym for `help'" @},
+ @{ "list", com_list, "List files in DIR" @},
+ @{ "ls", com_list, "Synonym for `list'" @},
+ @{ "pwd", com_pwd, "Print the current working directory" @},
+ @{ "quit", com_quit, "Quit using Fileman" @},
+ @{ "rename", com_rename, "Rename FILE to NEWNAME" @},
+ @{ "stat", com_stat, "Print out statistics on FILE" @},
+ @{ "view", com_view, "View the contents of FILE" @},
+ @{ (char *)NULL, (Function *)NULL, (char *)NULL @}
+@};
+
+/* The name of this program, as taken from argv[0]. */
+char *progname;
+
+/* When non-zero, this global means the user is done using this program. */
+int done = 0;
+@page
+main (argc, argv)
+ int argc;
+ char **argv;
+@{
+ progname = argv[0];
+
+ initialize_readline (); /* Bind our completer. */
+
+ /* Loop reading and executing lines until the user quits. */
+ while (!done)
+ @{
+ char *line;
+
+ line = readline ("FileMan: ");
+
+ if (!line)
+ @{
+ done = 1; /* Encountered EOF at top level. */
+ @}
+ else
+ @{
+ /* Remove leading and trailing whitespace from the line.
+ Then, if there is anything left, add it to the history list
+ and execute it. */
+ stripwhite (line);
+
+ if (*line)
+ @{
+ add_history (line);
+ execute_line (line);
+ @}
+ @}
+
+ if (line)
+ free (line);
+ @}
+ exit (0);
+@}
+
+/* Execute a command line. */
+execute_line (line)
+ char *line;
+@{
+ register int i;
+ COMMAND *find_command (), *command;
+ char *word;
+
+ /* Isolate the command word. */
+ i = 0;
+ while (line[i] && !whitespace (line[i]))
+ i++;
+
+ word = line;
+
+ if (line[i])
+ line[i++] = '\0';
+
+ command = find_command (word);
+
+ if (!command)
+ @{
+ fprintf (stderr, "%s: No such command for FileMan.\n", word);
+ return;
+ @}
+
+ /* Get argument to command, if any. */
+ while (whitespace (line[i]))
+ i++;
+
+ word = line + i;
+
+ /* Call the function. */
+ (*(command->func)) (word);
+@}
+
+/* Look up NAME as the name of a command, and return a pointer to that
+ command. Return a NULL pointer if NAME isn't a command name. */
+COMMAND *
+find_command (name)
+ char *name;
+@{
+ register int i;
+
+ for (i = 0; commands[i].name; i++)
+ if (strcmp (name, commands[i].name) == 0)
+ return (&commands[i]);
+
+ return ((COMMAND *)NULL);
+@}
+
+/* Strip whitespace from the start and end of STRING. */
+stripwhite (string)
+ char *string;
+@{
+ register int i = 0;
+
+ while (whitespace (string[i]))
+ i++;
+
+ if (i)
+ strcpy (string, string + i);
+
+ i = strlen (string) - 1;
+
+ while (i > 0 && whitespace (string[i]))
+ i--;
+
+ string[++i] = '\0';
+@}
+@page
+/* **************************************************************** */
+/* */
+/* Interface to Readline Completion */
+/* */
+/* **************************************************************** */
+
+/* Tell the GNU Readline library how to complete. We want to try to complete
+ on command names if this is the first word in the line, or on filenames
+ if not. */
+initialize_readline ()
+@{
+ char **fileman_completion ();
+
+ /* Allow conditional parsing of the ~/.inputrc file. */
+ rl_readline_name = "FileMan";
+
+ /* Tell the completer that we want a crack first. */
+ rl_attempted_completion_function = (Function *)fileman_completion;
+@}
+
+/* Attempt to complete on the contents of TEXT. START and END show the
+ region of TEXT that contains the word to complete. We can use the
+ entire line in case we want to do some simple parsing. Return the
+ array of matches, or NULL if there aren't any. */
+char **
+fileman_completion (text, start, end)
+ char *text;
+ int start, end;
+@{
+ char **matches;
+ char *command_generator ();
+
+ matches = (char **)NULL;
+
+ /* If this word is at the start of the line, then it is a command
+ to complete. Otherwise it is the name of a file in the current
+ directory. */
+ if (start == 0)
+ matches = completion_matches (text, command_generator);
+
+ return (matches);
+@}
+
+/* Generator function for command completion. STATE lets us know whether
+ to start from scratch; without any state (i.e. STATE == 0), then we
+ start at the top of the list. */
+char *
+command_generator (text, state)
+ char *text;
+ int state;
+@{
+ static int list_index, len;
+ char *name;
+
+ /* If this is a new word to complete, initialize now. This includes
+ saving the length of TEXT for efficiency, and initializing the index
+ variable to 0. */
+ if (!state)
+ @{
+ list_index = 0;
+ len = strlen (text);
+ @}
+
+ /* Return the next name which partially matches from the command list. */
+ while (name = commands[list_index].name)
+ @{
+ list_index++;
+
+ if (strncmp (name, text, len) == 0)
+ return (name);
+ @}
+
+ /* If no names matched, then return NULL. */
+ return ((char *)NULL);
+@}
+@page
+/* **************************************************************** */
+/* */
+/* FileMan Commands */
+/* */
+/* **************************************************************** */
+
+/* String to pass to system (). This is for the LIST, VIEW and RENAME
+ commands. */
+static char syscom[1024];
+
+/* List the file(s) named in arg. */
+com_list (arg)
+ char *arg;
+@{
+ if (!arg)
+ arg = "*";
+
+ sprintf (syscom, "ls -FClg %s", arg);
+ system (syscom);
+@}
+
+com_view (arg)
+ char *arg;
+@{
+ if (!valid_argument ("view", arg))
+ return;
+
+ sprintf (syscom, "cat %s | more", arg);
+ system (syscom);
+@}
+
+com_rename (arg)
+ char *arg;
+@{
+ too_dangerous ("rename");
+@}
+
+com_stat (arg)
+ char *arg;
+@{
+ struct stat finfo;
+
+ if (!valid_argument ("stat", arg))
+ return;
+
+ if (stat (arg, &finfo) == -1)
+ @{
+ perror (arg);
+ return;
+ @}
+
+ printf ("Statistics for `%s':\n", arg);
+
+ printf ("%s has %d link%s, and is %d bytes in length.\n", arg,
+ finfo.st_nlink, (finfo.st_nlink == 1) ? "" : "s", finfo.st_size);
+ printf (" Created on: %s", ctime (&finfo.st_ctime));
+ printf (" Last access at: %s", ctime (&finfo.st_atime));
+ printf ("Last modified at: %s", ctime (&finfo.st_mtime));
+@}
+
+com_delete (arg)
+ char *arg;
+@{
+ too_dangerous ("delete");
+@}
+
+/* Print out help for ARG, or for all of the commands if ARG is
+ not present. */
+com_help (arg)
+ char *arg;
+@{
+ register int i;
+ int printed = 0;
+
+ for (i = 0; commands[i].name; i++)
+ @{
+ if (!*arg || (strcmp (arg, commands[i].name) == 0))
+ @{
+ printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
+ printed++;
+ @}
+ @}
+
+ if (!printed)
+ @{
+ printf ("No commands match `%s'. Possibilties are:\n", arg);
+
+ for (i = 0; commands[i].name; i++)
+ @{
+ /* Print in six columns. */
+ if (printed == 6)
+ @{
+ printed = 0;
+ printf ("\n");
+ @}
+
+ printf ("%s\t", commands[i].name);
+ printed++;
+ @}
+
+ if (printed)
+ printf ("\n");
+ @}
+@}
+
+/* Change to the directory ARG. */
+com_cd (arg)
+ char *arg;
+@{
+ if (chdir (arg) == -1)
+ perror (arg);
+
+ com_pwd ("");
+@}
+
+/* Print out the current working directory. */
+com_pwd (ignore)
+ char *ignore;
+@{
+ char dir[1024];
+
+ (void) getwd (dir);
+
+ printf ("Current directory is %s\n", dir);
+@}
+
+/* The user wishes to quit using this program. Just set DONE non-zero. */
+com_quit (arg)
+ char *arg;
+@{
+ done = 1;
+@}
+
+/* Function which tells you that you can't do this. */
+too_dangerous (caller)
+ char *caller;
+@{
+ fprintf (stderr,
+ "%s: Too dangerous for me to distribute. Write it yourself.\n",
+ caller);
+@}
+
+/* Return non-zero if ARG is a valid argument for CALLER, else print
+ an error message and return zero. */
+int
+valid_argument (caller, arg)
+ char *caller, *arg;
+@{
+ if (!arg || !*arg)
+ @{
+ fprintf (stderr, "%s: Argument required.\n", caller);
+ return (0);
+ @}
+
+ return (1);
+@}
+@end smallexample
diff --git a/contrib/gdb/readline/doc/rluser.texinfo b/contrib/gdb/readline/doc/rluser.texinfo
new file mode 100644
index 0000000..da11111
--- /dev/null
+++ b/contrib/gdb/readline/doc/rluser.texinfo
@@ -0,0 +1,566 @@
+@ignore
+This file documents the end user interface to the GNU command line
+editing feautres. It is to be an appendix to manuals for programs which
+use these features. There is a document entitled "readline.texinfo"
+which contains both end-user and programmer documentation for the GNU
+Readline Library.
+
+Copyright (C) 1988 Free Software Foundation, Inc.
+
+Authored by Brian Fox.
+
+Permission is granted to process this file through Tex and print the
+results, provided the printed document carries copying permission notice
+identical to this one except for the removal of this paragraph (this
+paragraph not being relevant to the printed manual).
+
+Permission is granted to make and distribute verbatim copies of this manual
+provided the copyright notice and this permission notice are preserved on
+all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that the
+GNU Copyright statement is available to the distributee, and provided that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+@end ignore
+
+@node Command Line Editing
+@appendix Command Line Editing
+
+This text describes GNU's command line editing interface.
+
+@menu
+* Introduction and Notation:: Notation used in this text.
+* Readline Interaction:: The minimum set of commands for editing a line.
+* Readline Init File:: Customizing Readline from a user's view.
+@end menu
+
+@node Introduction and Notation
+@section Introduction to Line Editing
+
+The following paragraphs describe the notation we use to represent
+keystrokes.
+
+The text @key{C-k} is read as `Control-K' and describes the character
+produced when the Control key is depressed and the @key{k} key is struck.
+
+The text @key{M-k} is read as `Meta-K' and describes the character
+produced when the meta key (if you have one) is depressed, and the @key{k}
+key is struck. If you do not have a meta key, the identical keystroke
+can be generated by typing @key{ESC} @i{first}, and then typing @key{k}.
+Either process is known as @dfn{metafying} the @key{k} key.
+
+The text @key{M-C-k} is read as `Meta-Control-k' and describes the
+character produced by @dfn{metafying} @key{C-k}.
+
+In addition, several keys have their own names. Specifically,
+@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all
+stand for themselves when seen in this text, or in an init file
+(@pxref{Readline Init File}, for more info).
+
+@node Readline Interaction
+@section Readline Interaction
+@cindex interaction, readline
+
+Often during an interactive session you type in a long line of text,
+only to notice that the first word on the line is misspelled. The
+Readline library gives you a set of commands for manipulating the text
+as you type it in, allowing you to just fix your typo, and not forcing
+you to retype the majority of the line. Using these editing commands,
+you move the cursor to the place that needs correction, and delete or
+insert the text of the corrections. Then, when you are satisfied with
+the line, you simply press @key{RET}. You do not have to be at the
+end of the line to press @key{RET}; the entire line is accepted
+regardless of the location of the cursor within the line.
+
+@menu
+* Readline Bare Essentials:: The least you need to know about Readline.
+* Readline Movement Commands:: Moving about the input line.
+* Readline Killing Commands:: How to delete text, and how to get it back!
+* Readline Arguments:: Giving numeric arguments to commands.
+@end menu
+
+@node Readline Bare Essentials
+@subsection Readline Bare Essentials
+
+In order to enter characters into the line, simply type them. The typed
+character appears where the cursor was, and then the cursor moves one
+space to the right. If you mistype a character, you can use @key{DEL} to
+back up, and delete the mistyped character.
+
+Sometimes you may miss typing a character that you wanted to type, and
+not notice your error until you have typed several other characters. In
+that case, you can type @key{C-b} to move the cursor to the left, and then
+correct your mistake. Aftwerwards, you can move the cursor to the right
+with @key{C-f}.
+
+When you add text in the middle of a line, you will notice that characters
+to the right of the cursor get `pushed over' to make room for the text
+that you have inserted. Likewise, when you delete text behind the cursor,
+characters to the right of the cursor get `pulled back' to fill in the
+blank space created by the removal of the text. A list of the basic bare
+essentials for editing the text of an input line follows.
+
+@table @asis
+@item @key{C-b}
+Move back one character.
+@item @key{C-f}
+Move forward one character.
+@item @key{DEL}
+Delete the character to the left of the cursor.
+@item @key{C-d}
+Delete the character underneath the cursor.
+@item @w{Printing characters}
+Insert itself into the line at the cursor.
+@item @key{C-_}
+Undo the last thing that you did. You can undo all the way back to an
+empty line.
+@end table
+
+@node Readline Movement Commands
+@subsection Readline Movement Commands
+
+The above table describes the most basic possible keystrokes that you need
+in order to do editing of the input line. For your convenience, many
+other commands have been added in addition to @key{C-b}, @key{C-f},
+@key{C-d}, and @key{DEL}. Here are some commands for moving more rapidly
+about the line.
+
+@table @key
+@item C-a
+Move to the start of the line.
+@item C-e
+Move to the end of the line.
+@item M-f
+Move forward a word.
+@item M-b
+Move backward a word.
+@item C-l
+Clear the screen, reprinting the current line at the top.
+@end table
+
+Notice how @key{C-f} moves forward a character, while @key{M-f} moves
+forward a word. It is a loose convention that control keystrokes
+operate on characters while meta keystrokes operate on words.
+
+@node Readline Killing Commands
+@subsection Readline Killing Commands
+
+@dfn{Killing} text means to delete the text from the line, but to save
+it away for later use, usually by @dfn{yanking} it back into the line.
+If the description for a command says that it `kills' text, then you can
+be sure that you can get the text back in a different (or the same)
+place later.
+
+Here is the list of commands for killing text.
+
+@table @key
+@item C-k
+Kill the text from the current cursor position to the end of the line.
+
+@item M-d
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.
+
+@item M-DEL
+Kill from the cursor to the start of the previous word, or if between
+words, to the start of the previous word.
+
+@item C-w
+Kill from the cursor to the previous whitespace. This is different than
+@key{M-DEL} because the word boundaries differ.
+
+@end table
+
+And, here is how to @dfn{yank} the text back into the line.
+
+@table @key
+@item C-y
+Yank the most recently killed text back into the buffer at the cursor.
+
+@item M-y
+Rotate the kill-ring, and yank the new top. You can only do this if
+the prior command is @key{C-y} or @key{M-y}.
+@end table
+
+When you use a kill command, the text is saved in a @dfn{kill-ring}.
+Any number of consecutive kills save all of the killed text together, so
+that when you yank it back, you get it in one clean sweep. The kill
+ring is not line specific; the text that you killed on a previously
+typed line is available to be yanked back later, when you are typing
+another line.
+
+@node Readline Arguments
+@subsection Readline Arguments
+
+You can pass numeric arguments to Readline commands. Sometimes the
+argument acts as a repeat count, other times it is the @i{sign} of the
+argument that is significant. If you pass a negative argument to a
+command which normally acts in a forward direction, that command will
+act in a backward direction. For example, to kill text back to the
+start of the line, you might type @key{M--} @key{C-k}.
+
+The general way to pass numeric arguments to a command is to type meta
+digits before the command. If the first `digit' you type is a minus
+sign (@key{-}), then the sign of the argument will be negative. Once
+you have typed one meta digit to get the argument started, you can type
+the remainder of the digits, and then the command. For example, to give
+the @key{C-d} command an argument of 10, you could type @key{M-1 0 C-d}.
+
+
+@node Readline Init File
+@section Readline Init File
+
+Although the Readline library comes with a set of @sc{gnu} Emacs-like
+keybindings, it is possible that you would like to use a different set
+of keybindings. You can customize programs that use Readline by putting
+commands in an @dfn{init} file in your home directory. The name of this
+file is @file{~/.inputrc}.
+
+When a program which uses the Readline library starts up, the
+@file{~/.inputrc} file is read, and the keybindings are set.
+
+In addition, the @key{C-x C-r} command re-reads this init file, thus
+incorporating any changes that you might have made to it.
+
+@menu
+* Readline Init Syntax:: Syntax for the commands in @file{~/.inputrc}.
+* Readline vi Mode:: Switching to @code{vi} mode in Readline.
+@end menu
+
+@node Readline Init Syntax
+@subsection Readline Init Syntax
+
+There are only four constructs allowed in the @file{~/.inputrc}
+file:
+
+@table @asis
+@item Variable Settings
+You can change the state of a few variables in Readline. You do this by
+using the @code{set} command within the init file. Here is how you
+would specify that you wish to use @code{vi} line editing commands:
+
+@example
+set editing-mode vi
+@end example
+
+Right now, there are only a few variables which can be set; so few in
+fact, that we just iterate them here:
+
+@table @code
+
+@item editing-mode
+@vindex editing-mode
+The @code{editing-mode} variable controls which editing mode you are
+using. By default, @sc{gnu} Readline starts up in Emacs editing mode, where
+the keystrokes are most similar to Emacs. This variable can either be
+set to @code{emacs} or @code{vi}.
+
+@item horizontal-scroll-mode
+@vindex horizontal-scroll-mode
+This variable can either be set to @code{On} or @code{Off}. Setting it
+to @code{On} means that the text of the lines that you edit will scroll
+horizontally on a single screen line when they are larger than the width
+of the screen, instead of wrapping onto a new screen line. By default,
+this variable is set to @code{Off}.
+
+@item mark-modified-lines
+@vindex mark-modified-lines
+This variable when set to @code{On}, says to display an asterisk
+(@samp{*}) at the starts of history lines which have been modified.
+This variable is off by default.
+
+@item prefer-visible-bell
+@vindex prefer-visible-bell
+If this variable is set to @code{On} it means to use a visible bell if
+one is available, rather than simply ringing the terminal bell. By
+default, the value is @code{Off}.
+@end table
+
+@item Key Bindings
+The syntax for controlling keybindings in the @file{~/.inputrc} file is
+simple. First you have to know the @i{name} of the command that you
+want to change. The following pages contain tables of the command name,
+the default keybinding, and a short description of what the command
+does.
+
+Once you know the name of the command, simply place the name of the key
+you wish to bind the command to, a colon, and then the name of the
+command on a line in the @file{~/.inputrc} file. The name of the key
+can be expressed in different ways, depending on which is most
+comfortable for you.
+
+@table @asis
+@item @w{@var{keyname}: @var{function-name} or @var{macro}}
+@var{keyname} is the name of a key spelled out in English. For example:
+@example
+Control-u: universal-argument
+Meta-Rubout: backward-kill-word
+Control-o: ">&output"
+@end example
+
+In the above example, @key{C-u} is bound to the function
+@code{universal-argument}, and @key{C-o} is bound to run the macro
+expressed on the right hand side (that is, to insert the text
+@samp{>&output} into the line).
+
+@item @w{"@var{keyseq}": @var{function-name} or @var{macro}}
+@var{keyseq} differs from @var{keyname} above in that strings denoting
+an entire key sequence can be specified. Simply place the key sequence
+in double quotes. @sc{gnu} Emacs style key escapes can be used, as in the
+following example:
+
+@example
+"\C-u": universal-argument
+"\C-x\C-r": re-read-init-file
+"\e[11~": "Function Key 1"
+@end example
+
+In the above example, @key{C-u} is bound to the function
+@code{universal-argument} (just as it was in the first example),
+@key{C-x C-r} is bound to the function @code{re-read-init-file}, and
+@key{ESC [ 1 1 ~} is bound to insert the text @samp{Function Key 1}.
+
+@end table
+@end table
+
+@menu
+* Commands For Moving:: Moving about the line.
+* Commands For History:: Getting at previous lines.
+* Commands For Text:: Commands for changing text.
+* Commands For Killing:: Commands for killing and yanking.
+* Numeric Arguments:: Specifying numeric arguments, repeat counts.
+* Commands For Completion:: Getting Readline to do the typing for you.
+* Miscellaneous Commands:: Other miscillaneous commands.
+@end menu
+
+@need 2000
+@node Commands For Moving
+@subsubsection Commands For Moving
+
+@ftable @code
+@item beginning-of-line (@key{C-a})
+Move to the start of the current line.
+
+@item end-of-line (@key{C-e})
+Move to the end of the line.
+
+@item forward-char (@key{C-f})
+Move forward a character.
+
+@item backward-char (@key{C-b})
+Move back a character.
+
+@item forward-word (@key{M-f})
+Move forward to the end of the next word.
+
+@item backward-word (@key{M-b})
+Move back to the start of this, or the previous, word.
+
+@item clear-screen (@key{C-l})
+Clear the screen leaving the current line at the top of the screen.
+
+@end ftable
+
+@need 2000
+@node Commands For History
+@subsubsection Commands For Manipulating The History
+
+@ftable @code
+@item accept-line (Newline, Return)
+Accept the line regardless of where the cursor is. If this line is
+non-empty, add it to the history list. If this line was a history
+line, then restore the history line to its original state.
+
+@item previous-history (@key{C-p})
+Move `up' through the history list.
+
+@item next-history (@key{C-n})
+Move `down' through the history list.
+
+@item beginning-of-history (@key{M-<})
+Move to the first line in the history.
+
+@item end-of-history (@key{M->})
+Move to the end of the input history, i.e., the line you are entering.
+
+@item reverse-search-history (@key{C-r})
+Search backward starting at the current line and moving `up' through
+the history as necessary. This is an incremental search.
+
+@item forward-search-history (@key{C-s})
+Search forward starting at the current line and moving `down' through
+the the history as necessary.
+
+@end ftable
+
+@need 2000
+@node Commands For Text
+@subsubsection Commands For Changing Text
+
+@ftable @code
+@item delete-char (@key{C-d})
+Delete the character under the cursor. If the cursor is at the
+beginning of the line, and there are no characters in the line, and
+the last character typed was not @key{C-d}, then return EOF.
+
+@item backward-delete-char (Rubout)
+Delete the character behind the cursor. A numeric argument says to kill
+the characters instead of deleting them.
+
+@item quoted-insert (@key{C-q}, @key{C-v})
+Add the next character that you type to the line verbatim. This is
+how to insert things like @key{C-q} for example.
+
+@item tab-insert (@key{M-TAB})
+Insert a tab character.
+
+@item self-insert (a, b, A, 1, !, ...)
+Insert yourself.
+
+@item transpose-chars (@key{C-t})
+Drag the character before point forward over the character at point.
+Point moves forward as well. If point is at the end of the line, then
+transpose the two characters before point. Negative arguments don't work.
+
+@item transpose-words (@key{M-t})
+Drag the word behind the cursor past the word in front of the cursor
+moving the cursor over that word as well.
+
+@item upcase-word (@key{M-u})
+Uppercase all letters in the current (or following) word. With a
+negative argument, do the previous word, but do not move point.
+
+@item downcase-word (@key{M-l})
+Lowercase all letters in the current (or following) word. With a
+negative argument, do the previous word, but do not move point.
+
+@item capitalize-word (@key{M-c})
+Uppercase the first letter in the current (or following) word. With a
+negative argument, do the previous word, but do not move point.
+
+@end ftable
+
+@need 2000
+@node Commands For Killing
+@subsubsection Killing And Yanking
+
+@ftable @code
+@item kill-line (@key{C-k})
+Kill the text from the current cursor position to the end of the line.
+
+@item backward-kill-line ()
+Kill backward to the beginning of the line. This is normally unbound.
+
+@item kill-word (@key{M-d})
+Kill from the cursor to the end of the current word, or if between
+words, to the end of the next word.
+
+@item backward-kill-word (@key{M-DEL})
+Kill the word behind the cursor.
+
+@item unix-line-discard (@key{C-u})
+Kill the whole line the way @key{C-u} used to in Unix line input.
+The killed text is saved on the kill-ring.
+
+@item unix-word-rubout (@key{C-w})
+Kill the word the way @key{C-w} used to in Unix line input.
+The killed text is saved on the kill-ring. This is different than
+backward-kill-word because the word boundaries differ.
+
+@item yank (@key{C-y})
+Yank the top of the kill ring into the buffer at point.
+
+@item yank-pop (@key{M-y})
+Rotate the kill-ring, and yank the new top. You can only do this if
+the prior command is yank or yank-pop.
+@end ftable
+
+@need 2000
+@node Numeric Arguments
+@subsubsection Specifying Numeric Arguments
+
+@ftable @code
+
+@item digit-argument (@key{M-0}, @key{M-1}, ... @key{M--})
+Add this digit to the argument already accumulating, or start a new
+argument. @key{M--} starts a negative argument.
+
+@item universal-argument ()
+Do what @key{C-u} does in @sc{gnu} Emacs. By default, this is not bound.
+@end ftable
+
+
+@need 2000
+@node Commands For Completion
+@subsubsection Letting Readline Type For You
+
+@ftable @code
+@item complete (TAB)
+Attempt to do completion on the text before point. This is
+implementation defined. Generally, if you are typing a filename
+argument, you can do filename completion; if you are typing a command,
+you can do command completion, if you are typing in a symbol to GDB, you
+can do symbol name completion, if you are typing in a variable to Bash,
+you can do variable name completion.
+
+@item possible-completions (M-?)
+List the possible completions of the text before point.
+@end ftable
+
+@need 2000
+@node Miscellaneous Commands
+@subsubsection Some Miscellaneous Commands
+
+@ftable @code
+
+@item re-read-init-file (@key{C-x} @key{C-r})
+Read in the contents of your @file{~/.inputrc} file, and incorporate
+any bindings found there.
+
+@item abort (@key{C-g})
+Stop running the current editing command.
+
+@ignore
+@c I have no idea what this means, and can't figure it out by
+@c experiment, and can't find it in the readline source.
+@c doc@cygnus.com, 20may1993.
+@item do-uppercase-version (@key{M-a}, @key{M-b}, ...)
+Run the command that is bound to your uppercase brother.
+@end ignore
+
+@item prefix-meta (ESC)
+Make the next character that you type be metafied. This is for people
+without a meta key. Typing @key{ESC f} is equivalent to typing
+@key{M-f}.
+
+@item undo (@key{C-_})
+Incremental undo, separately remembered for each line.
+
+@item revert-line (@key{M-r})
+Undo all changes made to this line. This is like typing the `undo'
+command enough times to get back to the beginning.
+@end ftable
+
+@need 2000
+@node Readline vi Mode
+@subsection Readline @code{vi} Mode
+
+@cindex @code{vi} style command editing
+@kindex toggle-editing-mode
+While the Readline library does not have a full set of @code{vi} editing
+functions, it does contain enough to allow simple editing of the line.
+
+In order to switch interactively between @sc{gnu} Emacs and @code{vi}
+editing modes, use the command @key{M-C-j} (toggle-editing-mode).
+
+When you enter a line in @code{vi} mode, you are already placed in `insertion'
+mode, as if you had typed an `i'. Pressing @key{ESC} switches you into
+`edit' mode, where you can edit the text of the line with the standard
+@code{vi} movement keys, move to previous history lines with `k', and following
+lines with `j', and so forth.
+
OpenPOWER on IntegriCloud